* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-03-11 20:59 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-03-11 20:59 UTC (permalink / raw
To: gentoo-commits
commit: d28bc7b26a2b978abb89076172397bcd551bc4d5
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Mon Mar 11 20:48:49 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Mon Mar 11 20:48:49 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=d28bc7b2
CPU Optimization patch
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
5010_enable-cpu-optimizations-universal.patch | 787 ++++++++++++++++++++++++++
2 files changed, 791 insertions(+)
diff --git a/0000_README b/0000_README
index a4c7916d..887cea4c 100644
--- a/0000_README
+++ b/0000_README
@@ -78,3 +78,7 @@ Desc: Print firmware info (Reqs CONFIG_GENTOO_PRINT_FIRMWARE_INFO). Thanks to
Patch: 4567_distro-Gentoo-Kconfig.patch
From: Tom Wijsman <TomWij@gentoo.org>
Desc: Add Gentoo Linux support config settings and defaults.
+
+Patch: 5010_enable-cpu-optimizations-universal.patch
+From: https://github.com/graysky2/kernel_compiler_patch
+Desc: Kernel >= 5.15 patch enables gcc = v11.1+ optimizations for additional CPUs.
diff --git a/5010_enable-cpu-optimizations-universal.patch b/5010_enable-cpu-optimizations-universal.patch
new file mode 100644
index 00000000..75c48bf1
--- /dev/null
+++ b/5010_enable-cpu-optimizations-universal.patch
@@ -0,0 +1,787 @@
+From 71dd30c3e2ab2852b0290ae1f34ce1c7f8655040 Mon Sep 17 00:00:00 2001
+From: graysky <therealgraysky@proton.me>
+Date: Wed, 21 Feb 2024 08:38:13 -0500
+
+FEATURES
+This patch adds additional CPU options to the Linux kernel accessible under:
+ Processor type and features --->
+ Processor family --->
+
+With the release of gcc 11.1 and clang 12.0, several generic 64-bit levels are
+offered which are good for supported Intel or AMD CPUs:
+• x86-64-v2
+• x86-64-v3
+• x86-64-v4
+
+Users of glibc 2.33 and above can see which level is supported by running:
+ /lib/ld-linux-x86-64.so.2 --help | grep supported
+Or
+ /lib64/ld-linux-x86-64.so.2 --help | grep supported
+
+Alternatively, compare the flags from /proc/cpuinfo to this list.[1]
+
+CPU-specific microarchitectures include:
+• AMD Improved K8-family
+• AMD K10-family
+• AMD Family 10h (Barcelona)
+• AMD Family 14h (Bobcat)
+• AMD Family 16h (Jaguar)
+• AMD Family 15h (Bulldozer)
+• AMD Family 15h (Piledriver)
+• AMD Family 15h (Steamroller)
+• AMD Family 15h (Excavator)
+• AMD Family 17h (Zen)
+• AMD Family 17h (Zen 2)
+• AMD Family 19h (Zen 3)†
+• AMD Family 19h (Zen 4)§
+• Intel Silvermont low-power processors
+• Intel Goldmont low-power processors (Apollo Lake and Denverton)
+• Intel Goldmont Plus low-power processors (Gemini Lake)
+• Intel 1st Gen Core i3/i5/i7 (Nehalem)
+• Intel 1.5 Gen Core i3/i5/i7 (Westmere)
+• Intel 2nd Gen Core i3/i5/i7 (Sandybridge)
+• Intel 3rd Gen Core i3/i5/i7 (Ivybridge)
+• Intel 4th Gen Core i3/i5/i7 (Haswell)
+• Intel 5th Gen Core i3/i5/i7 (Broadwell)
+• Intel 6th Gen Core i3/i5/i7 (Skylake)
+• Intel 6th Gen Core i7/i9 (Skylake X)
+• Intel 8th Gen Core i3/i5/i7 (Cannon Lake)
+• Intel 10th Gen Core i7/i9 (Ice Lake)
+• Intel Xeon (Cascade Lake)
+• Intel Xeon (Cooper Lake)*
+• Intel 3rd Gen 10nm++ i3/i5/i7/i9-family (Tiger Lake)*
+• Intel 4th Gen 10nm++ Xeon (Sapphire Rapids)‡
+• Intel 11th Gen i3/i5/i7/i9-family (Rocket Lake)‡
+• Intel 12th Gen i3/i5/i7/i9-family (Alder Lake)‡
+• Intel 13th Gen i3/i5/i7/i9-family (Raptor Lake)§
+• Intel 14th Gen i3/i5/i7/i9-family (Meteor Lake)§
+• Intel 5th Gen 10nm++ Xeon (Emerald Rapids)§
+
+Notes: If not otherwise noted, gcc >=9.1 is required for support.
+ *Requires gcc >=10.1 or clang >=10.0
+ †Required gcc >=10.3 or clang >=12.0
+ ‡Required gcc >=11.1 or clang >=12.0
+ §Required gcc >=13.0 or clang >=15.0.5
+
+It also offers to compile passing the 'native' option which, "selects the CPU
+to generate code for at compilation time by determining the processor type of
+the compiling machine. Using -march=native enables all instruction subsets
+supported by the local machine and will produce code optimized for the local
+machine under the constraints of the selected instruction set."[2]
+
+Users of Intel CPUs should select the 'Intel-Native' option and users of AMD
+CPUs should select the 'AMD-Native' option.
+
+MINOR NOTES RELATING TO INTEL ATOM PROCESSORS
+This patch also changes -march=atom to -march=bonnell in accordance with the
+gcc v4.9 changes. Upstream is using the deprecated -match=atom flags when I
+believe it should use the newer -march=bonnell flag for atom processors.[3]
+
+It is not recommended to compile on Atom-CPUs with the 'native' option.[4] The
+recommendation is to use the 'atom' option instead.
+
+BENEFITS
+Small but real speed increases are measurable using a make endpoint comparing
+a generic kernel to one built with one of the respective microarchs.
+
+See the following experimental evidence supporting this statement:
+https://github.com/graysky2/kernel_gcc_patch
+
+REQUIREMENTS
+linux version 5.17+
+gcc version >=9.0 or clang version >=9.0
+
+ACKNOWLEDGMENTS
+This patch builds on the seminal work by Jeroen.[5]
+
+REFERENCES
+1. https://gitlab.com/x86-psABIs/x86-64-ABI/-/commit/77566eb03bc6a326811cb7e9
+2. https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#index-x86-Options
+3. https://bugzilla.kernel.org/show_bug.cgi?id=77461
+4. https://github.com/graysky2/kernel_gcc_patch/issues/15
+5. http://www.linuxforge.net/docs/linux/linux-gcc.php
+---
+ arch/x86/Kconfig.cpu | 424 ++++++++++++++++++++++++++++++--
+ arch/x86/Makefile | 44 +++-
+ arch/x86/include/asm/vermagic.h | 74 ++++++
+ 3 files changed, 526 insertions(+), 16 deletions(-)
+
+diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
+index 2a7279d80460a..6924a0f5f1c26 100644
+--- a/arch/x86/Kconfig.cpu
++++ b/arch/x86/Kconfig.cpu
+@@ -157,7 +157,7 @@ config MPENTIUM4
+
+
+ config MK6
+- bool "K6/K6-II/K6-III"
++ bool "AMD K6/K6-II/K6-III"
+ depends on X86_32
+ help
+ Select this for an AMD K6-family processor. Enables use of
+@@ -165,7 +165,7 @@ config MK6
+ flags to GCC.
+
+ config MK7
+- bool "Athlon/Duron/K7"
++ bool "AMD Athlon/Duron/K7"
+ depends on X86_32
+ help
+ Select this for an AMD Athlon K7-family processor. Enables use of
+@@ -173,12 +173,106 @@ config MK7
+ flags to GCC.
+
+ config MK8
+- bool "Opteron/Athlon64/Hammer/K8"
++ bool "AMD Opteron/Athlon64/Hammer/K8"
+ help
+ Select this for an AMD Opteron or Athlon64 Hammer-family processor.
+ Enables use of some extended instructions, and passes appropriate
+ optimization flags to GCC.
+
++config MK8SSE3
++ bool "AMD Opteron/Athlon64/Hammer/K8 with SSE3"
++ help
++ Select this for improved AMD Opteron or Athlon64 Hammer-family processors.
++ Enables use of some extended instructions, and passes appropriate
++ optimization flags to GCC.
++
++config MK10
++ bool "AMD 61xx/7x50/PhenomX3/X4/II/K10"
++ help
++ Select this for an AMD 61xx Eight-Core Magny-Cours, Athlon X2 7x50,
++ Phenom X3/X4/II, Athlon II X2/X3/X4, or Turion II-family processor.
++ Enables use of some extended instructions, and passes appropriate
++ optimization flags to GCC.
++
++config MBARCELONA
++ bool "AMD Barcelona"
++ help
++ Select this for AMD Family 10h Barcelona processors.
++
++ Enables -march=barcelona
++
++config MBOBCAT
++ bool "AMD Bobcat"
++ help
++ Select this for AMD Family 14h Bobcat processors.
++
++ Enables -march=btver1
++
++config MJAGUAR
++ bool "AMD Jaguar"
++ help
++ Select this for AMD Family 16h Jaguar processors.
++
++ Enables -march=btver2
++
++config MBULLDOZER
++ bool "AMD Bulldozer"
++ help
++ Select this for AMD Family 15h Bulldozer processors.
++
++ Enables -march=bdver1
++
++config MPILEDRIVER
++ bool "AMD Piledriver"
++ help
++ Select this for AMD Family 15h Piledriver processors.
++
++ Enables -march=bdver2
++
++config MSTEAMROLLER
++ bool "AMD Steamroller"
++ help
++ Select this for AMD Family 15h Steamroller processors.
++
++ Enables -march=bdver3
++
++config MEXCAVATOR
++ bool "AMD Excavator"
++ help
++ Select this for AMD Family 15h Excavator processors.
++
++ Enables -march=bdver4
++
++config MZEN
++ bool "AMD Zen"
++ help
++ Select this for AMD Family 17h Zen processors.
++
++ Enables -march=znver1
++
++config MZEN2
++ bool "AMD Zen 2"
++ help
++ Select this for AMD Family 17h Zen 2 processors.
++
++ Enables -march=znver2
++
++config MZEN3
++ bool "AMD Zen 3"
++ depends on (CC_IS_GCC && GCC_VERSION >= 100300) || (CC_IS_CLANG && CLANG_VERSION >= 120000)
++ help
++ Select this for AMD Family 19h Zen 3 processors.
++
++ Enables -march=znver3
++
++config MZEN4
++ bool "AMD Zen 4"
++ depends on (CC_IS_GCC && GCC_VERSION >= 130000) || (CC_IS_CLANG && CLANG_VERSION >= 160000)
++ help
++ Select this for AMD Family 19h Zen 4 processors.
++
++ Enables -march=znver4
++
+ config MCRUSOE
+ bool "Crusoe"
+ depends on X86_32
+@@ -270,7 +364,7 @@ config MPSC
+ in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one.
+
+ config MCORE2
+- bool "Core 2/newer Xeon"
++ bool "Intel Core 2"
+ help
+
+ Select this for Intel Core 2 and newer Core 2 Xeons (Xeon 51xx and
+@@ -278,6 +372,8 @@ config MCORE2
+ family in /proc/cpuinfo. Newer ones have 6 and older ones 15
+ (not a typo)
+
++ Enables -march=core2
++
+ config MATOM
+ bool "Intel Atom"
+ help
+@@ -287,6 +383,212 @@ config MATOM
+ accordingly optimized code. Use a recent GCC with specific Atom
+ support in order to fully benefit from selecting this option.
+
++config MNEHALEM
++ bool "Intel Nehalem"
++ select X86_P6_NOP
++ help
++
++ Select this for 1st Gen Core processors in the Nehalem family.
++
++ Enables -march=nehalem
++
++config MWESTMERE
++ bool "Intel Westmere"
++ select X86_P6_NOP
++ help
++
++ Select this for the Intel Westmere formerly Nehalem-C family.
++
++ Enables -march=westmere
++
++config MSILVERMONT
++ bool "Intel Silvermont"
++ select X86_P6_NOP
++ help
++
++ Select this for the Intel Silvermont platform.
++
++ Enables -march=silvermont
++
++config MGOLDMONT
++ bool "Intel Goldmont"
++ select X86_P6_NOP
++ help
++
++ Select this for the Intel Goldmont platform including Apollo Lake and Denverton.
++
++ Enables -march=goldmont
++
++config MGOLDMONTPLUS
++ bool "Intel Goldmont Plus"
++ select X86_P6_NOP
++ help
++
++ Select this for the Intel Goldmont Plus platform including Gemini Lake.
++
++ Enables -march=goldmont-plus
++
++config MSANDYBRIDGE
++ bool "Intel Sandy Bridge"
++ select X86_P6_NOP
++ help
++
++ Select this for 2nd Gen Core processors in the Sandy Bridge family.
++
++ Enables -march=sandybridge
++
++config MIVYBRIDGE
++ bool "Intel Ivy Bridge"
++ select X86_P6_NOP
++ help
++
++ Select this for 3rd Gen Core processors in the Ivy Bridge family.
++
++ Enables -march=ivybridge
++
++config MHASWELL
++ bool "Intel Haswell"
++ select X86_P6_NOP
++ help
++
++ Select this for 4th Gen Core processors in the Haswell family.
++
++ Enables -march=haswell
++
++config MBROADWELL
++ bool "Intel Broadwell"
++ select X86_P6_NOP
++ help
++
++ Select this for 5th Gen Core processors in the Broadwell family.
++
++ Enables -march=broadwell
++
++config MSKYLAKE
++ bool "Intel Skylake"
++ select X86_P6_NOP
++ help
++
++ Select this for 6th Gen Core processors in the Skylake family.
++
++ Enables -march=skylake
++
++config MSKYLAKEX
++ bool "Intel Skylake X"
++ select X86_P6_NOP
++ help
++
++ Select this for 6th Gen Core processors in the Skylake X family.
++
++ Enables -march=skylake-avx512
++
++config MCANNONLAKE
++ bool "Intel Cannon Lake"
++ select X86_P6_NOP
++ help
++
++ Select this for 8th Gen Core processors
++
++ Enables -march=cannonlake
++
++config MICELAKE
++ bool "Intel Ice Lake"
++ select X86_P6_NOP
++ help
++
++ Select this for 10th Gen Core processors in the Ice Lake family.
++
++ Enables -march=icelake-client
++
++config MCASCADELAKE
++ bool "Intel Cascade Lake"
++ select X86_P6_NOP
++ help
++
++ Select this for Xeon processors in the Cascade Lake family.
++
++ Enables -march=cascadelake
++
++config MCOOPERLAKE
++ bool "Intel Cooper Lake"
++ depends on (CC_IS_GCC && GCC_VERSION > 100100) || (CC_IS_CLANG && CLANG_VERSION >= 100000)
++ select X86_P6_NOP
++ help
++
++ Select this for Xeon processors in the Cooper Lake family.
++
++ Enables -march=cooperlake
++
++config MTIGERLAKE
++ bool "Intel Tiger Lake"
++ depends on (CC_IS_GCC && GCC_VERSION > 100100) || (CC_IS_CLANG && CLANG_VERSION >= 100000)
++ select X86_P6_NOP
++ help
++
++ Select this for third-generation 10 nm process processors in the Tiger Lake family.
++
++ Enables -march=tigerlake
++
++config MSAPPHIRERAPIDS
++ bool "Intel Sapphire Rapids"
++ depends on (CC_IS_GCC && GCC_VERSION > 110000) || (CC_IS_CLANG && CLANG_VERSION >= 120000)
++ select X86_P6_NOP
++ help
++
++ Select this for fourth-generation 10 nm process processors in the Sapphire Rapids family.
++
++ Enables -march=sapphirerapids
++
++config MROCKETLAKE
++ bool "Intel Rocket Lake"
++ depends on (CC_IS_GCC && GCC_VERSION > 110000) || (CC_IS_CLANG && CLANG_VERSION >= 120000)
++ select X86_P6_NOP
++ help
++
++ Select this for eleventh-generation processors in the Rocket Lake family.
++
++ Enables -march=rocketlake
++
++config MALDERLAKE
++ bool "Intel Alder Lake"
++ depends on (CC_IS_GCC && GCC_VERSION > 110000) || (CC_IS_CLANG && CLANG_VERSION >= 120000)
++ select X86_P6_NOP
++ help
++
++ Select this for twelfth-generation processors in the Alder Lake family.
++
++ Enables -march=alderlake
++
++config MRAPTORLAKE
++ bool "Intel Raptor Lake"
++ depends on (CC_IS_GCC && GCC_VERSION >= 130000) || (CC_IS_CLANG && CLANG_VERSION >= 150500)
++ select X86_P6_NOP
++ help
++
++ Select this for thirteenth-generation processors in the Raptor Lake family.
++
++ Enables -march=raptorlake
++
++config MMETEORLAKE
++ bool "Intel Meteor Lake"
++ depends on (CC_IS_GCC && GCC_VERSION >= 130000) || (CC_IS_CLANG && CLANG_VERSION >= 150500)
++ select X86_P6_NOP
++ help
++
++ Select this for fourteenth-generation processors in the Meteor Lake family.
++
++ Enables -march=meteorlake
++
++config MEMERALDRAPIDS
++ bool "Intel Emerald Rapids"
++ depends on (CC_IS_GCC && GCC_VERSION > 130000) || (CC_IS_CLANG && CLANG_VERSION >= 150500)
++ select X86_P6_NOP
++ help
++
++ Select this for fifth-generation 10 nm process processors in the Emerald Rapids family.
++
++ Enables -march=emeraldrapids
++
+ config GENERIC_CPU
+ bool "Generic-x86-64"
+ depends on X86_64
+@@ -294,6 +596,50 @@ config GENERIC_CPU
+ Generic x86-64 CPU.
+ Run equally well on all x86-64 CPUs.
+
++config GENERIC_CPU2
++ bool "Generic-x86-64-v2"
++ depends on (CC_IS_GCC && GCC_VERSION > 110000) || (CC_IS_CLANG && CLANG_VERSION >= 120000)
++ depends on X86_64
++ help
++ Generic x86-64 CPU.
++ Run equally well on all x86-64 CPUs with min support of x86-64-v2.
++
++config GENERIC_CPU3
++ bool "Generic-x86-64-v3"
++ depends on (CC_IS_GCC && GCC_VERSION > 110000) || (CC_IS_CLANG && CLANG_VERSION >= 120000)
++ depends on X86_64
++ help
++ Generic x86-64-v3 CPU with v3 instructions.
++ Run equally well on all x86-64 CPUs with min support of x86-64-v3.
++
++config GENERIC_CPU4
++ bool "Generic-x86-64-v4"
++ depends on (CC_IS_GCC && GCC_VERSION > 110000) || (CC_IS_CLANG && CLANG_VERSION >= 120000)
++ depends on X86_64
++ help
++ Generic x86-64 CPU with v4 instructions.
++ Run equally well on all x86-64 CPUs with min support of x86-64-v4.
++
++config MNATIVE_INTEL
++ bool "Intel-Native optimizations autodetected by the compiler"
++ help
++
++ Clang 3.8, GCC 4.2 and above support -march=native, which automatically detects
++ the optimum settings to use based on your processor. Do NOT use this
++ for AMD CPUs. Intel Only!
++
++ Enables -march=native
++
++config MNATIVE_AMD
++ bool "AMD-Native optimizations autodetected by the compiler"
++ help
++
++ Clang 3.8, GCC 4.2 and above support -march=native, which automatically detects
++ the optimum settings to use based on your processor. Do NOT use this
++ for Intel CPUs. AMD Only!
++
++ Enables -march=native
++
+ endchoice
+
+ config X86_GENERIC
+@@ -318,9 +664,17 @@ config X86_INTERNODE_CACHE_SHIFT
+ config X86_L1_CACHE_SHIFT
+ int
+ default "7" if MPENTIUM4 || MPSC
+- default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MATOM || MVIAC7 || X86_GENERIC || GENERIC_CPU
++ default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MATOM || MVIAC7 || MK8SSE3 || MK10 \
++ || MBARCELONA || MBOBCAT || MJAGUAR || MBULLDOZER || MPILEDRIVER || MSTEAMROLLER \
++ || MEXCAVATOR || MZEN || MZEN2 || MZEN3 || MZEN4 || MNEHALEM || MWESTMERE || MSILVERMONT \
++ || MGOLDMONT || MGOLDMONTPLUS || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL \
++ || MSKYLAKE || MSKYLAKEX || MCANNONLAKE || MICELAKE || MCASCADELAKE || MCOOPERLAKE \
++ || MTIGERLAKE || MSAPPHIRERAPIDS || MROCKETLAKE || MALDERLAKE || MRAPTORLAKE || MMETEORLAKE \
++ || MEMERALDRAPIDS || MNATIVE_INTEL || MNATIVE_AMD || X86_GENERIC || GENERIC_CPU || GENERIC_CPU2 \
++ || GENERIC_CPU3 || GENERIC_CPU4
+ default "4" if MELAN || M486SX || M486 || MGEODEGX1
+- default "5" if MWINCHIP3D || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
++ default "5" if MWINCHIP3D || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII \
++ || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX
+
+ config X86_F00F_BUG
+ def_bool y
+@@ -332,15 +686,27 @@ config X86_INVD_BUG
+
+ config X86_ALIGNMENT_16
+ def_bool y
+- depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MELAN || MK6 || M586MMX || M586TSC || M586 || M486SX || M486 || MVIAC3_2 || MGEODEGX1
++ depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MELAN || MK6 || M586MMX || M586TSC \
++ || M586 || M486SX || M486 || MVIAC3_2 || MGEODEGX1
+
+ config X86_INTEL_USERCOPY
+ def_bool y
+- depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON || MCORE2
++ depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC \
++ || MK8 || MK7 || MEFFICEON || MCORE2 || MNEHALEM || MWESTMERE || MSILVERMONT || MGOLDMONT \
++ || MGOLDMONTPLUS || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MSKYLAKE || MSKYLAKEX \
++ || MCANNONLAKE || MICELAKE || MCASCADELAKE || MCOOPERLAKE || MTIGERLAKE || MSAPPHIRERAPIDS \
++ || MROCKETLAKE || MALDERLAKE || MRAPTORLAKE || MMETEORLAKE || MEMERALDRAPIDS || MNATIVE_INTEL
+
+ config X86_USE_PPRO_CHECKSUM
+ def_bool y
+- depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MVIAC7 || MEFFICEON || MGEODE_LX || MCORE2 || MATOM
++ depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM \
++ || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MVIAC7 || MEFFICEON || MGEODE_LX \
++ || MCORE2 || MATOM || MK8SSE3 || MK10 || MBARCELONA || MBOBCAT || MJAGUAR || MBULLDOZER \
++ || MPILEDRIVER || MSTEAMROLLER || MEXCAVATOR || MZEN || MZEN2 || MZEN3 || MZEN4 || MNEHALEM \
++ || MWESTMERE || MSILVERMONT || MGOLDMONT || MGOLDMONTPLUS || MSANDYBRIDGE || MIVYBRIDGE \
++ || MHASWELL || MBROADWELL || MSKYLAKE || MSKYLAKEX || MCANNONLAKE || MICELAKE \
++ || MCASCADELAKE || MCOOPERLAKE || MTIGERLAKE || MSAPPHIRERAPIDS || MROCKETLAKE \
++ || MALDERLAKE || MRAPTORLAKE || MMETEORLAKE || MEMERALDRAPIDS || MNATIVE_INTEL || MNATIVE_AMD
+
+ #
+ # P6_NOPs are a relatively minor optimization that require a family >=
+@@ -356,11 +722,22 @@ config X86_USE_PPRO_CHECKSUM
+ config X86_P6_NOP
+ def_bool y
+ depends on X86_64
+- depends on (MCORE2 || MPENTIUM4 || MPSC)
++ depends on (MCORE2 || MPENTIUM4 || MPSC || MNEHALEM || MWESTMERE || MSILVERMONT || MGOLDMONT \
++ || MGOLDMONTPLUS || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MSKYLAKE \
++ || MSKYLAKEX || MCANNONLAKE || MICELAKE || MCASCADELAKE || MCOOPERLAKE || MTIGERLAKE \
++ || MSAPPHIRERAPIDS || MROCKETLAKE || MALDERLAKE || MRAPTORLAKE || MMETEORLAKE || MEMERALDRAPIDS \
++ || MNATIVE_INTEL)
+
+ config X86_TSC
+ def_bool y
+- depends on (MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2 || MATOM) || X86_64
++ depends on (MWINCHIP3D || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM \
++ || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 \
++ || MGEODE_LX || MCORE2 || MATOM || MK8SSE3 || MK10 || MBARCELONA || MBOBCAT || MJAGUAR || MBULLDOZER \
++ || MPILEDRIVER || MSTEAMROLLER || MEXCAVATOR || MZEN || MZEN2 || MZEN3 || MZEN4 || MNEHALEM \
++ || MWESTMERE || MSILVERMONT || MGOLDMONT || MGOLDMONTPLUS || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL \
++ || MBROADWELL || MSKYLAKE || MSKYLAKEX || MCANNONLAKE || MICELAKE || MCASCADELAKE || MCOOPERLAKE \
++ || MTIGERLAKE || MSAPPHIRERAPIDS || MROCKETLAKE || MALDERLAKE || MRAPTORLAKE || MMETEORLAKE || MEMERALDRAPIDS \
++ || MNATIVE_INTEL || MNATIVE_AMD) || X86_64
+
+ config X86_HAVE_PAE
+ def_bool y
+@@ -368,18 +745,37 @@ config X86_HAVE_PAE
+
+ config X86_CMPXCHG64
+ def_bool y
+- depends on X86_HAVE_PAE || M586TSC || M586MMX || MK6 || MK7
++ depends on X86_PAE || X86_64 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 \
++ || M586TSC || M586MMX || MATOM || MGEODE_LX || MGEODEGX1 || MK6 || MK7 || MK8 || MK8SSE3 || MK10 \
++ || MBARCELONA || MBOBCAT || MJAGUAR || MBULLDOZER || MPILEDRIVER || MSTEAMROLLER || MEXCAVATOR || MZEN \
++ || MZEN2 || MZEN3 || MZEN4 || MNEHALEM || MWESTMERE || MSILVERMONT || MGOLDMONT || MGOLDMONTPLUS \
++ || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MSKYLAKE || MSKYLAKEX || MCANNONLAKE \
++ || MICELAKE || MCASCADELAKE || MCOOPERLAKE || MTIGERLAKE || MSAPPHIRERAPIDS || MROCKETLAKE \
++ || MALDERLAKE || MRAPTORLAKE || MMETEORLAKE || MEMERALDRAPIDS || MNATIVE_INTEL || MNATIVE_AMD
+
+ # this should be set for all -march=.. options where the compiler
+ # generates cmov.
+ config X86_CMOV
+ def_bool y
+- depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MATOM || MGEODE_LX)
++ depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 \
++ || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64 || MATOM || MGEODE_LX || MK8SSE3 || MK10 \
++ || MBARCELONA || MBOBCAT || MJAGUAR || MBULLDOZER || MPILEDRIVER || MSTEAMROLLER || MEXCAVATOR \
++ || MZEN || MZEN2 || MZEN3 || MZEN4 || MNEHALEM || MWESTMERE || MSILVERMONT || MGOLDMONT \
++ || MGOLDMONTPLUS || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL || MSKYLAKE || MSKYLAKEX \
++ || MCANNONLAKE || MICELAKE || MCASCADELAKE || MCOOPERLAKE || MTIGERLAKE || MSAPPHIRERAPIDS \
++ || MROCKETLAKE || MALDERLAKE || MRAPTORLAKE || MMETEORLAKE || MEMERALDRAPIDS || MNATIVE_INTEL || MNATIVE_AMD)
+
+ config X86_MINIMUM_CPU_FAMILY
+ int
+ default "64" if X86_64
+- default "6" if X86_32 && (MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MEFFICEON || MATOM || MCORE2 || MK7 || MK8)
++ default "6" if X86_32 && (MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 \
++ || MVIAC3_2 || MVIAC7 || MEFFICEON || MATOM || MCORE2 || MK7 || MK8 || MK8SSE3 \
++ || MK10 || MBARCELONA || MBOBCAT || MJAGUAR || MBULLDOZER || MPILEDRIVER || MSTEAMROLLER \
++ || MEXCAVATOR || MZEN || MZEN2 || MZEN3 || MZEN4 || MNEHALEM || MWESTMERE || MSILVERMONT \
++ || MGOLDMONT || MGOLDMONTPLUS || MSANDYBRIDGE || MIVYBRIDGE || MHASWELL || MBROADWELL \
++ || MSKYLAKE || MSKYLAKEX || MCANNONLAKE || MICELAKE || MCASCADELAKE || MCOOPERLAKE \
++ || MTIGERLAKE || MSAPPHIRERAPIDS || MROCKETLAKE || MALDERLAKE || MRAPTORLAKE || MRAPTORLAKE \
++ || MNATIVE_INTEL || MNATIVE_AMD)
+ default "5" if X86_32 && X86_CMPXCHG64
+ default "4"
+
+diff --git a/arch/x86/Makefile b/arch/x86/Makefile
+index da8f3caf27815..c873d10df15d0 100644
+--- a/arch/x86/Makefile
++++ b/arch/x86/Makefile
+@@ -152,8 +152,48 @@ else
+ # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu)
+ cflags-$(CONFIG_MK8) += -march=k8
+ cflags-$(CONFIG_MPSC) += -march=nocona
+- cflags-$(CONFIG_MCORE2) += -march=core2
+- cflags-$(CONFIG_MATOM) += -march=atom
++ cflags-$(CONFIG_MK8SSE3) += -march=k8-sse3
++ cflags-$(CONFIG_MK10) += -march=amdfam10
++ cflags-$(CONFIG_MBARCELONA) += -march=barcelona
++ cflags-$(CONFIG_MBOBCAT) += -march=btver1
++ cflags-$(CONFIG_MJAGUAR) += -march=btver2
++ cflags-$(CONFIG_MBULLDOZER) += -march=bdver1
++ cflags-$(CONFIG_MPILEDRIVER) += -march=bdver2 -mno-tbm
++ cflags-$(CONFIG_MSTEAMROLLER) += -march=bdver3 -mno-tbm
++ cflags-$(CONFIG_MEXCAVATOR) += -march=bdver4 -mno-tbm
++ cflags-$(CONFIG_MZEN) += -march=znver1
++ cflags-$(CONFIG_MZEN2) += -march=znver2
++ cflags-$(CONFIG_MZEN3) += -march=znver3
++ cflags-$(CONFIG_MZEN4) += -march=znver4
++ cflags-$(CONFIG_MNATIVE_INTEL) += -march=native
++ cflags-$(CONFIG_MNATIVE_AMD) += -march=native
++ cflags-$(CONFIG_MATOM) += -march=bonnell
++ cflags-$(CONFIG_MCORE2) += -march=core2
++ cflags-$(CONFIG_MNEHALEM) += -march=nehalem
++ cflags-$(CONFIG_MWESTMERE) += -march=westmere
++ cflags-$(CONFIG_MSILVERMONT) += -march=silvermont
++ cflags-$(CONFIG_MGOLDMONT) += -march=goldmont
++ cflags-$(CONFIG_MGOLDMONTPLUS) += -march=goldmont-plus
++ cflags-$(CONFIG_MSANDYBRIDGE) += -march=sandybridge
++ cflags-$(CONFIG_MIVYBRIDGE) += -march=ivybridge
++ cflags-$(CONFIG_MHASWELL) += -march=haswell
++ cflags-$(CONFIG_MBROADWELL) += -march=broadwell
++ cflags-$(CONFIG_MSKYLAKE) += -march=skylake
++ cflags-$(CONFIG_MSKYLAKEX) += -march=skylake-avx512
++ cflags-$(CONFIG_MCANNONLAKE) += -march=cannonlake
++ cflags-$(CONFIG_MICELAKE) += -march=icelake-client
++ cflags-$(CONFIG_MCASCADELAKE) += -march=cascadelake
++ cflags-$(CONFIG_MCOOPERLAKE) += -march=cooperlake
++ cflags-$(CONFIG_MTIGERLAKE) += -march=tigerlake
++ cflags-$(CONFIG_MSAPPHIRERAPIDS) += -march=sapphirerapids
++ cflags-$(CONFIG_MROCKETLAKE) += -march=rocketlake
++ cflags-$(CONFIG_MALDERLAKE) += -march=alderlake
++ cflags-$(CONFIG_MRAPTORLAKE) += -march=raptorlake
++ cflags-$(CONFIG_MMETEORLAKE) += -march=meteorlake
++ cflags-$(CONFIG_MEMERALDRAPIDS) += -march=emeraldrapids
++ cflags-$(CONFIG_GENERIC_CPU2) += -march=x86-64-v2
++ cflags-$(CONFIG_GENERIC_CPU3) += -march=x86-64-v3
++ cflags-$(CONFIG_GENERIC_CPU4) += -march=x86-64-v4
+ cflags-$(CONFIG_GENERIC_CPU) += -mtune=generic
+ KBUILD_CFLAGS += $(cflags-y)
+
+diff --git a/arch/x86/include/asm/vermagic.h b/arch/x86/include/asm/vermagic.h
+index 75884d2cdec37..02c1386eb653e 100644
+--- a/arch/x86/include/asm/vermagic.h
++++ b/arch/x86/include/asm/vermagic.h
+@@ -17,6 +17,54 @@
+ #define MODULE_PROC_FAMILY "586MMX "
+ #elif defined CONFIG_MCORE2
+ #define MODULE_PROC_FAMILY "CORE2 "
++#elif defined CONFIG_MNATIVE_INTEL
++#define MODULE_PROC_FAMILY "NATIVE_INTEL "
++#elif defined CONFIG_MNATIVE_AMD
++#define MODULE_PROC_FAMILY "NATIVE_AMD "
++#elif defined CONFIG_MNEHALEM
++#define MODULE_PROC_FAMILY "NEHALEM "
++#elif defined CONFIG_MWESTMERE
++#define MODULE_PROC_FAMILY "WESTMERE "
++#elif defined CONFIG_MSILVERMONT
++#define MODULE_PROC_FAMILY "SILVERMONT "
++#elif defined CONFIG_MGOLDMONT
++#define MODULE_PROC_FAMILY "GOLDMONT "
++#elif defined CONFIG_MGOLDMONTPLUS
++#define MODULE_PROC_FAMILY "GOLDMONTPLUS "
++#elif defined CONFIG_MSANDYBRIDGE
++#define MODULE_PROC_FAMILY "SANDYBRIDGE "
++#elif defined CONFIG_MIVYBRIDGE
++#define MODULE_PROC_FAMILY "IVYBRIDGE "
++#elif defined CONFIG_MHASWELL
++#define MODULE_PROC_FAMILY "HASWELL "
++#elif defined CONFIG_MBROADWELL
++#define MODULE_PROC_FAMILY "BROADWELL "
++#elif defined CONFIG_MSKYLAKE
++#define MODULE_PROC_FAMILY "SKYLAKE "
++#elif defined CONFIG_MSKYLAKEX
++#define MODULE_PROC_FAMILY "SKYLAKEX "
++#elif defined CONFIG_MCANNONLAKE
++#define MODULE_PROC_FAMILY "CANNONLAKE "
++#elif defined CONFIG_MICELAKE
++#define MODULE_PROC_FAMILY "ICELAKE "
++#elif defined CONFIG_MCASCADELAKE
++#define MODULE_PROC_FAMILY "CASCADELAKE "
++#elif defined CONFIG_MCOOPERLAKE
++#define MODULE_PROC_FAMILY "COOPERLAKE "
++#elif defined CONFIG_MTIGERLAKE
++#define MODULE_PROC_FAMILY "TIGERLAKE "
++#elif defined CONFIG_MSAPPHIRERAPIDS
++#define MODULE_PROC_FAMILY "SAPPHIRERAPIDS "
++#elif defined CONFIG_ROCKETLAKE
++#define MODULE_PROC_FAMILY "ROCKETLAKE "
++#elif defined CONFIG_MALDERLAKE
++#define MODULE_PROC_FAMILY "ALDERLAKE "
++#elif defined CONFIG_MRAPTORLAKE
++#define MODULE_PROC_FAMILY "RAPTORLAKE "
++#elif defined CONFIG_MMETEORLAKE
++#define MODULE_PROC_FAMILY "METEORLAKE "
++#elif defined CONFIG_MEMERALDRAPIDS
++#define MODULE_PROC_FAMILY "EMERALDRAPIDS "
+ #elif defined CONFIG_MATOM
+ #define MODULE_PROC_FAMILY "ATOM "
+ #elif defined CONFIG_M686
+@@ -35,6 +83,32 @@
+ #define MODULE_PROC_FAMILY "K7 "
+ #elif defined CONFIG_MK8
+ #define MODULE_PROC_FAMILY "K8 "
++#elif defined CONFIG_MK8SSE3
++#define MODULE_PROC_FAMILY "K8SSE3 "
++#elif defined CONFIG_MK10
++#define MODULE_PROC_FAMILY "K10 "
++#elif defined CONFIG_MBARCELONA
++#define MODULE_PROC_FAMILY "BARCELONA "
++#elif defined CONFIG_MBOBCAT
++#define MODULE_PROC_FAMILY "BOBCAT "
++#elif defined CONFIG_MBULLDOZER
++#define MODULE_PROC_FAMILY "BULLDOZER "
++#elif defined CONFIG_MPILEDRIVER
++#define MODULE_PROC_FAMILY "PILEDRIVER "
++#elif defined CONFIG_MSTEAMROLLER
++#define MODULE_PROC_FAMILY "STEAMROLLER "
++#elif defined CONFIG_MJAGUAR
++#define MODULE_PROC_FAMILY "JAGUAR "
++#elif defined CONFIG_MEXCAVATOR
++#define MODULE_PROC_FAMILY "EXCAVATOR "
++#elif defined CONFIG_MZEN
++#define MODULE_PROC_FAMILY "ZEN "
++#elif defined CONFIG_MZEN2
++#define MODULE_PROC_FAMILY "ZEN2 "
++#elif defined CONFIG_MZEN3
++#define MODULE_PROC_FAMILY "ZEN3 "
++#elif defined CONFIG_MZEN4
++#define MODULE_PROC_FAMILY "ZEN4 "
+ #elif defined CONFIG_MELAN
+ #define MODULE_PROC_FAMILY "ELAN "
+ #elif defined CONFIG_MCRUSOE
+--
+2.43.2
+
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-03-11 21:02 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-03-11 21:02 UTC (permalink / raw
To: gentoo-commits
commit: 76acca2656ef93ae0db5b975caf3138ba0bac5c5
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Mon Mar 11 21:02:04 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Mon Mar 11 21:02:04 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=76acca26
BMQ(BitMap Queue) Scheduler. USE=experimental
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
5020_BMQ-and-PDS-io-scheduler-v6.8-r0.patch | 11504 ++++++++++++++++++++++++++
2 files changed, 11508 insertions(+)
diff --git a/0000_README b/0000_README
index 887cea4c..e6b9bd5b 100644
--- a/0000_README
+++ b/0000_README
@@ -82,3 +82,7 @@ Desc: Add Gentoo Linux support config settings and defaults.
Patch: 5010_enable-cpu-optimizations-universal.patch
From: https://github.com/graysky2/kernel_compiler_patch
Desc: Kernel >= 5.15 patch enables gcc = v11.1+ optimizations for additional CPUs.
+
+Patch: 5020_BMQ-and-PDS-io-scheduler-v6.8-r0.patch
+From: https://gitlab.com/alfredchen/projectc
+Desc: BMQ(BitMap Queue) Scheduler. A new CPU scheduler developed from PDS(incld). Inspired by the scheduler in zircon.
diff --git a/5020_BMQ-and-PDS-io-scheduler-v6.8-r0.patch b/5020_BMQ-and-PDS-io-scheduler-v6.8-r0.patch
new file mode 100644
index 00000000..d914861f
--- /dev/null
+++ b/5020_BMQ-and-PDS-io-scheduler-v6.8-r0.patch
@@ -0,0 +1,11504 @@
+diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
+index 6584a1f9bfe3..226c79dd34cc 100644
+--- a/Documentation/admin-guide/sysctl/kernel.rst
++++ b/Documentation/admin-guide/sysctl/kernel.rst
+@@ -1646,3 +1646,13 @@ is 10 seconds.
+
+ The softlockup threshold is (``2 * watchdog_thresh``). Setting this
+ tunable to zero will disable lockup detection altogether.
++
++yield_type:
++===========
++
++BMQ/PDS CPU scheduler only. This determines what type of yield calls
++to sched_yield() will be performed.
++
++ 0 - No yield.
++ 1 - Requeue task. (default)
++ 2 - Set run queue skip task. Same as CFS.
+diff --git a/Documentation/scheduler/sched-BMQ.txt b/Documentation/scheduler/sched-BMQ.txt
+new file mode 100644
+index 000000000000..05c84eec0f31
+--- /dev/null
++++ b/Documentation/scheduler/sched-BMQ.txt
+@@ -0,0 +1,110 @@
++ BitMap queue CPU Scheduler
++ --------------------------
++
++CONTENT
++========
++
++ Background
++ Design
++ Overview
++ Task policy
++ Priority management
++ BitMap Queue
++ CPU Assignment and Migration
++
++
++Background
++==========
++
++BitMap Queue CPU scheduler, referred to as BMQ from here on, is an evolution
++of previous Priority and Deadline based Skiplist multiple queue scheduler(PDS),
++and inspired by Zircon scheduler. The goal of it is to keep the scheduler code
++simple, while efficiency and scalable for interactive tasks, such as desktop,
++movie playback and gaming etc.
++
++Design
++======
++
++Overview
++--------
++
++BMQ use per CPU run queue design, each CPU(logical) has it's own run queue,
++each CPU is responsible for scheduling the tasks that are putting into it's
++run queue.
++
++The run queue is a set of priority queues. Note that these queues are fifo
++queue for non-rt tasks or priority queue for rt tasks in data structure. See
++BitMap Queue below for details. BMQ is optimized for non-rt tasks in the fact
++that most applications are non-rt tasks. No matter the queue is fifo or
++priority, In each queue is an ordered list of runnable tasks awaiting execution
++and the data structures are the same. When it is time for a new task to run,
++the scheduler simply looks the lowest numbered queueue that contains a task,
++and runs the first task from the head of that queue. And per CPU idle task is
++also in the run queue, so the scheduler can always find a task to run on from
++its run queue.
++
++Each task will assigned the same timeslice(default 4ms) when it is picked to
++start running. Task will be reinserted at the end of the appropriate priority
++queue when it uses its whole timeslice. When the scheduler selects a new task
++from the priority queue it sets the CPU's preemption timer for the remainder of
++the previous timeslice. When that timer fires the scheduler will stop execution
++on that task, select another task and start over again.
++
++If a task blocks waiting for a shared resource then it's taken out of its
++priority queue and is placed in a wait queue for the shared resource. When it
++is unblocked it will be reinserted in the appropriate priority queue of an
++eligible CPU.
++
++Task policy
++-----------
++
++BMQ supports DEADLINE, FIFO, RR, NORMAL, BATCH and IDLE task policy like the
++mainline CFS scheduler. But BMQ is heavy optimized for non-rt task, that's
++NORMAL/BATCH/IDLE policy tasks. Below is the implementation detail of each
++policy.
++
++DEADLINE
++ It is squashed as priority 0 FIFO task.
++
++FIFO/RR
++ All RT tasks share one single priority queue in BMQ run queue designed. The
++complexity of insert operation is O(n). BMQ is not designed for system runs
++with major rt policy tasks.
++
++NORMAL/BATCH/IDLE
++ BATCH and IDLE tasks are treated as the same policy. They compete CPU with
++NORMAL policy tasks, but they just don't boost. To control the priority of
++NORMAL/BATCH/IDLE tasks, simply use nice level.
++
++ISO
++ ISO policy is not supported in BMQ. Please use nice level -20 NORMAL policy
++task instead.
++
++Priority management
++-------------------
++
++RT tasks have priority from 0-99. For non-rt tasks, there are three different
++factors used to determine the effective priority of a task. The effective
++priority being what is used to determine which queue it will be in.
++
++The first factor is simply the task’s static priority. Which is assigned from
++task's nice level, within [-20, 19] in userland's point of view and [0, 39]
++internally.
++
++The second factor is the priority boost. This is a value bounded between
++[-MAX_PRIORITY_ADJ, MAX_PRIORITY_ADJ] used to offset the base priority, it is
++modified by the following cases:
++
++*When a thread has used up its entire timeslice, always deboost its boost by
++increasing by one.
++*When a thread gives up cpu control(voluntary or non-voluntary) to reschedule,
++and its switch-in time(time after last switch and run) below the thredhold
++based on its priority boost, will boost its boost by decreasing by one buti is
++capped at 0 (won’t go negative).
++
++The intent in this system is to ensure that interactive threads are serviced
++quickly. These are usually the threads that interact directly with the user
++and cause user-perceivable latency. These threads usually do little work and
++spend most of their time blocked awaiting another user event. So they get the
++priority boost from unblocking while background threads that do most of the
++processing receive the priority penalty for using their entire timeslice.
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index 18550c071d71..fa8cf95568b6 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -481,7 +481,7 @@ static int proc_pid_schedstat(struct seq_file *m, struct pid_namespace *ns,
+ seq_puts(m, "0 0 0\n");
+ else
+ seq_printf(m, "%llu %llu %lu\n",
+- (unsigned long long)task->se.sum_exec_runtime,
++ (unsigned long long)tsk_seruntime(task),
+ (unsigned long long)task->sched_info.run_delay,
+ task->sched_info.pcount);
+
+diff --git a/include/asm-generic/resource.h b/include/asm-generic/resource.h
+index 8874f681b056..59eb72bf7d5f 100644
+--- a/include/asm-generic/resource.h
++++ b/include/asm-generic/resource.h
+@@ -23,7 +23,7 @@
+ [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY }, \
+ [RLIMIT_SIGPENDING] = { 0, 0 }, \
+ [RLIMIT_MSGQUEUE] = { MQ_BYTES_MAX, MQ_BYTES_MAX }, \
+- [RLIMIT_NICE] = { 0, 0 }, \
++ [RLIMIT_NICE] = { 30, 30 }, \
+ [RLIMIT_RTPRIO] = { 0, 0 }, \
+ [RLIMIT_RTTIME] = { RLIM_INFINITY, RLIM_INFINITY }, \
+ }
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index ffe8f618ab86..3c17bfa142b7 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -771,8 +771,14 @@ struct task_struct {
+ unsigned int ptrace;
+
+ #ifdef CONFIG_SMP
+- int on_cpu;
+ struct __call_single_node wake_entry;
++#endif
++#if defined(CONFIG_SMP) || defined(CONFIG_SCHED_ALT)
++ int on_cpu;
++#endif
++
++#ifdef CONFIG_SMP
++#ifndef CONFIG_SCHED_ALT
+ unsigned int wakee_flips;
+ unsigned long wakee_flip_decay_ts;
+ struct task_struct *last_wakee;
+@@ -786,6 +792,7 @@ struct task_struct {
+ */
+ int recent_used_cpu;
+ int wake_cpu;
++#endif /* !CONFIG_SCHED_ALT */
+ #endif
+ int on_rq;
+
+@@ -794,6 +801,20 @@ struct task_struct {
+ int normal_prio;
+ unsigned int rt_priority;
+
++#ifdef CONFIG_SCHED_ALT
++ u64 last_ran;
++ s64 time_slice;
++ int sq_idx;
++ struct list_head sq_node;
++#ifdef CONFIG_SCHED_BMQ
++ int boost_prio;
++#endif /* CONFIG_SCHED_BMQ */
++#ifdef CONFIG_SCHED_PDS
++ u64 deadline;
++#endif /* CONFIG_SCHED_PDS */
++ /* sched_clock time spent running */
++ u64 sched_time;
++#else /* !CONFIG_SCHED_ALT */
+ struct sched_entity se;
+ struct sched_rt_entity rt;
+ struct sched_dl_entity dl;
+@@ -805,6 +826,7 @@ struct task_struct {
+ unsigned long core_cookie;
+ unsigned int core_occupation;
+ #endif
++#endif /* !CONFIG_SCHED_ALT */
+
+ #ifdef CONFIG_CGROUP_SCHED
+ struct task_group *sched_task_group;
+@@ -1564,6 +1586,15 @@ struct task_struct {
+ */
+ };
+
++#ifdef CONFIG_SCHED_ALT
++#define tsk_seruntime(t) ((t)->sched_time)
++/* replace the uncertian rt_timeout with 0UL */
++#define tsk_rttimeout(t) (0UL)
++#else /* CFS */
++#define tsk_seruntime(t) ((t)->se.sum_exec_runtime)
++#define tsk_rttimeout(t) ((t)->rt.timeout)
++#endif /* !CONFIG_SCHED_ALT */
++
+ #define TASK_REPORT_IDLE (TASK_REPORT + 1)
+ #define TASK_REPORT_MAX (TASK_REPORT_IDLE << 1)
+
+diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h
+index df3aca89d4f5..1df1f7635188 100644
+--- a/include/linux/sched/deadline.h
++++ b/include/linux/sched/deadline.h
+@@ -2,6 +2,25 @@
+ #ifndef _LINUX_SCHED_DEADLINE_H
+ #define _LINUX_SCHED_DEADLINE_H
+
++#ifdef CONFIG_SCHED_ALT
++
++static inline int dl_task(struct task_struct *p)
++{
++ return 0;
++}
++
++#ifdef CONFIG_SCHED_BMQ
++#define __tsk_deadline(p) (0UL)
++#endif
++
++#ifdef CONFIG_SCHED_PDS
++#define __tsk_deadline(p) ((((u64) ((p)->prio))<<56) | (p)->deadline)
++#endif
++
++#else
++
++#define __tsk_deadline(p) ((p)->dl.deadline)
++
+ /*
+ * SCHED_DEADLINE tasks has negative priorities, reflecting
+ * the fact that any of them has higher prio than RT and
+@@ -23,6 +42,7 @@ static inline int dl_task(struct task_struct *p)
+ {
+ return dl_prio(p->prio);
+ }
++#endif /* CONFIG_SCHED_ALT */
+
+ static inline bool dl_time_before(u64 a, u64 b)
+ {
+diff --git a/include/linux/sched/prio.h b/include/linux/sched/prio.h
+index ab83d85e1183..a9a1dfa99140 100644
+--- a/include/linux/sched/prio.h
++++ b/include/linux/sched/prio.h
+@@ -18,6 +18,32 @@
+ #define MAX_PRIO (MAX_RT_PRIO + NICE_WIDTH)
+ #define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2)
+
++#ifdef CONFIG_SCHED_ALT
++
++/* Undefine MAX_PRIO and DEFAULT_PRIO */
++#undef MAX_PRIO
++#undef DEFAULT_PRIO
++
++/* +/- priority levels from the base priority */
++#ifdef CONFIG_SCHED_BMQ
++#define MAX_PRIORITY_ADJ (12)
++
++#define MIN_NORMAL_PRIO (MAX_RT_PRIO)
++#define MAX_PRIO (MIN_NORMAL_PRIO + NICE_WIDTH)
++#define DEFAULT_PRIO (MIN_NORMAL_PRIO + NICE_WIDTH / 2)
++#endif
++
++#ifdef CONFIG_SCHED_PDS
++#define MAX_PRIORITY_ADJ (0)
++
++#define MIN_NORMAL_PRIO (128)
++#define NORMAL_PRIO_NUM (64)
++#define MAX_PRIO (MIN_NORMAL_PRIO + NORMAL_PRIO_NUM)
++#define DEFAULT_PRIO (MAX_PRIO - NICE_WIDTH / 2)
++#endif
++
++#endif /* CONFIG_SCHED_ALT */
++
+ /*
+ * Convert user-nice values [ -20 ... 0 ... 19 ]
+ * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
+diff --git a/include/linux/sched/rt.h b/include/linux/sched/rt.h
+index b2b9e6eb9683..09bd4d8758b2 100644
+--- a/include/linux/sched/rt.h
++++ b/include/linux/sched/rt.h
+@@ -24,8 +24,10 @@ static inline bool task_is_realtime(struct task_struct *tsk)
+
+ if (policy == SCHED_FIFO || policy == SCHED_RR)
+ return true;
++#ifndef CONFIG_SCHED_ALT
+ if (policy == SCHED_DEADLINE)
+ return true;
++#endif
+ return false;
+ }
+
+diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h
+index a6e04b4a21d7..66f5170037c3 100644
+--- a/include/linux/sched/topology.h
++++ b/include/linux/sched/topology.h
+@@ -238,7 +238,8 @@ static inline bool cpus_share_resources(int this_cpu, int that_cpu)
+
+ #endif /* !CONFIG_SMP */
+
+-#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)
++#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) && \
++ !defined(CONFIG_SCHED_ALT)
+ extern void rebuild_sched_domains_energy(void);
+ #else
+ static inline void rebuild_sched_domains_energy(void)
+diff --git a/init/Kconfig b/init/Kconfig
+index bee58f7468c3..81f568107a6b 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -638,6 +638,7 @@ config TASK_IO_ACCOUNTING
+
+ config PSI
+ bool "Pressure stall information tracking"
++ depends on !SCHED_ALT
+ select KERNFS
+ help
+ Collect metrics that indicate how overcommitted the CPU, memory,
+@@ -803,6 +804,7 @@ menu "Scheduler features"
+ config UCLAMP_TASK
+ bool "Enable utilization clamping for RT/FAIR tasks"
+ depends on CPU_FREQ_GOV_SCHEDUTIL
++ depends on !SCHED_ALT
+ help
+ This feature enables the scheduler to track the clamped utilization
+ of each CPU based on RUNNABLE tasks scheduled on that CPU.
+@@ -849,6 +851,35 @@ config UCLAMP_BUCKETS_COUNT
+
+ If in doubt, use the default value.
+
++menuconfig SCHED_ALT
++ bool "Alternative CPU Schedulers"
++ default y
++ help
++ This feature enable alternative CPU scheduler"
++
++if SCHED_ALT
++
++choice
++ prompt "Alternative CPU Scheduler"
++ default SCHED_BMQ
++
++config SCHED_BMQ
++ bool "BMQ CPU scheduler"
++ help
++ The BitMap Queue CPU scheduler for excellent interactivity and
++ responsiveness on the desktop and solid scalability on normal
++ hardware and commodity servers.
++
++config SCHED_PDS
++ bool "PDS CPU scheduler"
++ help
++ The Priority and Deadline based Skip list multiple queue CPU
++ Scheduler.
++
++endchoice
++
++endif
++
+ endmenu
+
+ #
+@@ -914,6 +945,7 @@ config NUMA_BALANCING
+ depends on ARCH_SUPPORTS_NUMA_BALANCING
+ depends on !ARCH_WANT_NUMA_VARIABLE_LOCALITY
+ depends on SMP && NUMA && MIGRATION && !PREEMPT_RT
++ depends on !SCHED_ALT
+ help
+ This option adds support for automatic NUMA aware memory/task placement.
+ The mechanism is quite primitive and is based on migrating memory when
+@@ -1011,6 +1043,7 @@ config FAIR_GROUP_SCHED
+ depends on CGROUP_SCHED
+ default CGROUP_SCHED
+
++if !SCHED_ALT
+ config CFS_BANDWIDTH
+ bool "CPU bandwidth provisioning for FAIR_GROUP_SCHED"
+ depends on FAIR_GROUP_SCHED
+@@ -1033,6 +1066,7 @@ config RT_GROUP_SCHED
+ realtime bandwidth for them.
+ See Documentation/scheduler/sched-rt-group.rst for more information.
+
++endif #!SCHED_ALT
+ endif #CGROUP_SCHED
+
+ config SCHED_MM_CID
+@@ -1281,6 +1315,7 @@ config CHECKPOINT_RESTORE
+
+ config SCHED_AUTOGROUP
+ bool "Automatic process group scheduling"
++ depends on !SCHED_ALT
+ select CGROUPS
+ select CGROUP_SCHED
+ select FAIR_GROUP_SCHED
+diff --git a/init/init_task.c b/init/init_task.c
+index 7ecb458eb3da..9530a7173b37 100644
+--- a/init/init_task.c
++++ b/init/init_task.c
+@@ -70,9 +70,15 @@ struct task_struct init_task __aligned(L1_CACHE_BYTES) = {
+ .stack = init_stack,
+ .usage = REFCOUNT_INIT(2),
+ .flags = PF_KTHREAD,
++#ifdef CONFIG_SCHED_ALT
++ .prio = DEFAULT_PRIO + MAX_PRIORITY_ADJ,
++ .static_prio = DEFAULT_PRIO,
++ .normal_prio = DEFAULT_PRIO + MAX_PRIORITY_ADJ,
++#else
+ .prio = MAX_PRIO - 20,
+ .static_prio = MAX_PRIO - 20,
+ .normal_prio = MAX_PRIO - 20,
++#endif
+ .policy = SCHED_NORMAL,
+ .cpus_ptr = &init_task.cpus_mask,
+ .user_cpus_ptr = NULL,
+@@ -84,6 +90,17 @@ struct task_struct init_task __aligned(L1_CACHE_BYTES) = {
+ .restart_block = {
+ .fn = do_no_restart_syscall,
+ },
++#ifdef CONFIG_SCHED_ALT
++ .sq_node = LIST_HEAD_INIT(init_task.sq_node),
++#ifdef CONFIG_SCHED_BMQ
++ .boost_prio = 0,
++ .sq_idx = 15,
++#endif
++#ifdef CONFIG_SCHED_PDS
++ .deadline = 0,
++#endif
++ .time_slice = HZ,
++#else
+ .se = {
+ .group_node = LIST_HEAD_INIT(init_task.se.group_node),
+ },
+@@ -91,6 +108,7 @@ struct task_struct init_task __aligned(L1_CACHE_BYTES) = {
+ .run_list = LIST_HEAD_INIT(init_task.rt.run_list),
+ .time_slice = RR_TIMESLICE,
+ },
++#endif
+ .tasks = LIST_HEAD_INIT(init_task.tasks),
+ #ifdef CONFIG_SMP
+ .pushable_tasks = PLIST_NODE_INIT(init_task.pushable_tasks, MAX_PRIO),
+diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
+index c2f1fd95a821..41654679b1b2 100644
+--- a/kernel/Kconfig.preempt
++++ b/kernel/Kconfig.preempt
+@@ -117,7 +117,7 @@ config PREEMPT_DYNAMIC
+
+ config SCHED_CORE
+ bool "Core Scheduling for SMT"
+- depends on SCHED_SMT
++ depends on SCHED_SMT && !SCHED_ALT
+ help
+ This option permits Core Scheduling, a means of coordinated task
+ selection across SMT siblings. When enabled -- see
+diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
+index 927bef3a598a..69e748ec80ab 100644
+--- a/kernel/cgroup/cpuset.c
++++ b/kernel/cgroup/cpuset.c
+@@ -855,7 +855,7 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
+ return ret;
+ }
+
+-#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_ALT)
+ /*
+ * Helper routine for generate_sched_domains().
+ * Do cpusets a, b have overlapping effective cpus_allowed masks?
+@@ -1254,7 +1254,7 @@ static void rebuild_sched_domains_locked(void)
+ /* Have scheduler rebuild the domains */
+ partition_and_rebuild_sched_domains(ndoms, doms, attr);
+ }
+-#else /* !CONFIG_SMP */
++#else /* !CONFIG_SMP || CONFIG_SCHED_ALT */
+ static void rebuild_sched_domains_locked(void)
+ {
+ }
+@@ -3308,12 +3308,15 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
+ goto out_unlock;
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ if (dl_task(task)) {
+ cs->nr_migrate_dl_tasks++;
+ cs->sum_migrate_dl_bw += task->dl.dl_bw;
+ }
++#endif
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ if (!cs->nr_migrate_dl_tasks)
+ goto out_success;
+
+@@ -3334,6 +3337,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
+ }
+
+ out_success:
++#endif
+ /*
+ * Mark attach is in progress. This makes validate_change() fail
+ * changes which zero cpus/mems_allowed.
+@@ -3357,12 +3361,14 @@ static void cpuset_cancel_attach(struct cgroup_taskset *tset)
+ if (!cs->attach_in_progress)
+ wake_up(&cpuset_attach_wq);
+
++#ifndef CONFIG_SCHED_ALT
+ if (cs->nr_migrate_dl_tasks) {
+ int cpu = cpumask_any(cs->effective_cpus);
+
+ dl_bw_free(cpu, cs->sum_migrate_dl_bw);
+ reset_migrate_dl_data(cs);
+ }
++#endif
+
+ mutex_unlock(&cpuset_mutex);
+ }
+diff --git a/kernel/delayacct.c b/kernel/delayacct.c
+index 6f0c358e73d8..8111481ce8b1 100644
+--- a/kernel/delayacct.c
++++ b/kernel/delayacct.c
+@@ -150,7 +150,7 @@ int delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
+ */
+ t1 = tsk->sched_info.pcount;
+ t2 = tsk->sched_info.run_delay;
+- t3 = tsk->se.sum_exec_runtime;
++ t3 = tsk_seruntime(tsk);
+
+ d->cpu_count += t1;
+
+diff --git a/kernel/exit.c b/kernel/exit.c
+index dfb963d2f862..510f2dea00c4 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -176,7 +176,7 @@ static void __exit_signal(struct task_struct *tsk)
+ sig->curr_target = next_thread(tsk);
+ }
+
+- add_device_randomness((const void*) &tsk->se.sum_exec_runtime,
++ add_device_randomness((const void*) &tsk_seruntime(tsk),
+ sizeof(unsigned long long));
+
+ /*
+@@ -197,7 +197,7 @@ static void __exit_signal(struct task_struct *tsk)
+ sig->inblock += task_io_get_inblock(tsk);
+ sig->oublock += task_io_get_oublock(tsk);
+ task_io_accounting_add(&sig->ioac, &tsk->ioac);
+- sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
++ sig->sum_sched_runtime += tsk_seruntime(tsk);
+ sig->nr_threads--;
+ __unhash_process(tsk, group_dead);
+ write_sequnlock(&sig->stats_lock);
+diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
+index 4a10e8c16fd2..cfbbdd64b851 100644
+--- a/kernel/locking/rtmutex.c
++++ b/kernel/locking/rtmutex.c
+@@ -362,7 +362,7 @@ waiter_update_prio(struct rt_mutex_waiter *waiter, struct task_struct *task)
+ lockdep_assert(RB_EMPTY_NODE(&waiter->tree.entry));
+
+ waiter->tree.prio = __waiter_prio(task);
+- waiter->tree.deadline = task->dl.deadline;
++ waiter->tree.deadline = __tsk_deadline(task);
+ }
+
+ /*
+@@ -383,16 +383,20 @@ waiter_clone_prio(struct rt_mutex_waiter *waiter, struct task_struct *task)
+ * Only use with rt_waiter_node_{less,equal}()
+ */
+ #define task_to_waiter_node(p) \
+- &(struct rt_waiter_node){ .prio = __waiter_prio(p), .deadline = (p)->dl.deadline }
++ &(struct rt_waiter_node){ .prio = __waiter_prio(p), .deadline = __tsk_deadline(p) }
+ #define task_to_waiter(p) \
+ &(struct rt_mutex_waiter){ .tree = *task_to_waiter_node(p) }
+
+ static __always_inline int rt_waiter_node_less(struct rt_waiter_node *left,
+ struct rt_waiter_node *right)
+ {
++#ifdef CONFIG_SCHED_PDS
++ return (left->deadline < right->deadline);
++#else
+ if (left->prio < right->prio)
+ return 1;
+
++#ifndef CONFIG_SCHED_BMQ
+ /*
+ * If both waiters have dl_prio(), we check the deadlines of the
+ * associated tasks.
+@@ -401,16 +405,22 @@ static __always_inline int rt_waiter_node_less(struct rt_waiter_node *left,
+ */
+ if (dl_prio(left->prio))
+ return dl_time_before(left->deadline, right->deadline);
++#endif
+
+ return 0;
++#endif
+ }
+
+ static __always_inline int rt_waiter_node_equal(struct rt_waiter_node *left,
+ struct rt_waiter_node *right)
+ {
++#ifdef CONFIG_SCHED_PDS
++ return (left->deadline == right->deadline);
++#else
+ if (left->prio != right->prio)
+ return 0;
+
++#ifndef CONFIG_SCHED_BMQ
+ /*
+ * If both waiters have dl_prio(), we check the deadlines of the
+ * associated tasks.
+@@ -419,8 +429,10 @@ static __always_inline int rt_waiter_node_equal(struct rt_waiter_node *left,
+ */
+ if (dl_prio(left->prio))
+ return left->deadline == right->deadline;
++#endif
+
+ return 1;
++#endif
+ }
+
+ static inline bool rt_mutex_steal(struct rt_mutex_waiter *waiter,
+diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
+index 976092b7bd45..31d587c16ec1 100644
+--- a/kernel/sched/Makefile
++++ b/kernel/sched/Makefile
+@@ -28,7 +28,12 @@ endif
+ # These compilation units have roughly the same size and complexity - so their
+ # build parallelizes well and finishes roughly at once:
+ #
++ifdef CONFIG_SCHED_ALT
++obj-y += alt_core.o
++obj-$(CONFIG_SCHED_DEBUG) += alt_debug.o
++else
+ obj-y += core.o
+ obj-y += fair.o
++endif
+ obj-y += build_policy.o
+ obj-y += build_utility.o
+diff --git a/kernel/sched/alt_core.c b/kernel/sched/alt_core.c
+new file mode 100644
+index 000000000000..2745abb36a20
+--- /dev/null
++++ b/kernel/sched/alt_core.c
+@@ -0,0 +1,8960 @@
++/*
++ * kernel/sched/alt_core.c
++ *
++ * Core alternative kernel scheduler code and related syscalls
++ *
++ * Copyright (C) 1991-2002 Linus Torvalds
++ *
++ * 2009-08-13 Brainfuck deadline scheduling policy by Con Kolivas deletes
++ * a whole lot of those previous things.
++ * 2017-09-06 Priority and Deadline based Skip list multiple queue kernel
++ * scheduler by Alfred Chen.
++ * 2019-02-20 BMQ(BitMap Queue) kernel scheduler by Alfred Chen.
++ */
++#include <linux/sched/clock.h>
++#include <linux/sched/cputime.h>
++#include <linux/sched/debug.h>
++#include <linux/sched/hotplug.h>
++#include <linux/sched/init.h>
++#include <linux/sched/isolation.h>
++#include <linux/sched/loadavg.h>
++#include <linux/sched/mm.h>
++#include <linux/sched/nohz.h>
++#include <linux/sched/stat.h>
++#include <linux/sched/wake_q.h>
++
++#include <linux/blkdev.h>
++#include <linux/context_tracking.h>
++#include <linux/cpuset.h>
++#include <linux/delayacct.h>
++#include <linux/init_task.h>
++#include <linux/kcov.h>
++#include <linux/kprobes.h>
++#include <linux/nmi.h>
++#include <linux/rseq.h>
++#include <linux/scs.h>
++
++#include <uapi/linux/sched/types.h>
++
++#include <asm/irq_regs.h>
++#include <asm/switch_to.h>
++
++#define CREATE_TRACE_POINTS
++#include <trace/events/sched.h>
++#include <trace/events/ipi.h>
++#undef CREATE_TRACE_POINTS
++
++#include "sched.h"
++#include "smp.h"
++
++#include "pelt.h"
++
++#include "../../io_uring/io-wq.h"
++#include "../smpboot.h"
++
++EXPORT_TRACEPOINT_SYMBOL_GPL(ipi_send_cpu);
++EXPORT_TRACEPOINT_SYMBOL_GPL(ipi_send_cpumask);
++
++/*
++ * Export tracepoints that act as a bare tracehook (ie: have no trace event
++ * associated with them) to allow external modules to probe them.
++ */
++EXPORT_TRACEPOINT_SYMBOL_GPL(pelt_irq_tp);
++
++#ifdef CONFIG_SCHED_DEBUG
++#define sched_feat(x) (1)
++/*
++ * Print a warning if need_resched is set for the given duration (if
++ * LATENCY_WARN is enabled).
++ *
++ * If sysctl_resched_latency_warn_once is set, only one warning will be shown
++ * per boot.
++ */
++__read_mostly int sysctl_resched_latency_warn_ms = 100;
++__read_mostly int sysctl_resched_latency_warn_once = 1;
++#else
++#define sched_feat(x) (0)
++#endif /* CONFIG_SCHED_DEBUG */
++
++#define ALT_SCHED_VERSION "v6.8-r0"
++
++/*
++ * Compile time debug macro
++ * #define ALT_SCHED_DEBUG
++ */
++
++/* rt_prio(prio) defined in include/linux/sched/rt.h */
++#define rt_task(p) rt_prio((p)->prio)
++#define rt_policy(policy) ((policy) == SCHED_FIFO || (policy) == SCHED_RR)
++#define task_has_rt_policy(p) (rt_policy((p)->policy))
++
++#define STOP_PRIO (MAX_RT_PRIO - 1)
++
++/*
++ * Time slice
++ * (default: 4 msec, units: nanoseconds)
++ */
++unsigned int sysctl_sched_base_slice __read_mostly = (4 << 20);
++
++static inline void requeue_task(struct task_struct *p, struct rq *rq, int idx);
++
++#ifdef CONFIG_SCHED_BMQ
++#include "bmq.h"
++#endif
++#ifdef CONFIG_SCHED_PDS
++#include "pds.h"
++#endif
++
++struct affinity_context {
++ const struct cpumask *new_mask;
++ struct cpumask *user_mask;
++ unsigned int flags;
++};
++
++/* Reschedule if less than this many μs left */
++#define RESCHED_NS (100 << 10)
++
++/**
++ * sched_yield_type - Type of sched_yield() will be performed.
++ * 0: No yield.
++ * 1: Requeue task. (default)
++ * 2: Set rq skip task. (Same as mainline)
++ */
++int sched_yield_type __read_mostly = 1;
++
++#ifdef CONFIG_SMP
++static cpumask_t sched_rq_pending_mask ____cacheline_aligned_in_smp;
++
++DEFINE_PER_CPU_ALIGNED(cpumask_t [NR_CPU_AFFINITY_LEVELS], sched_cpu_topo_masks);
++DEFINE_PER_CPU_ALIGNED(cpumask_t *, sched_cpu_llc_mask);
++DEFINE_PER_CPU_ALIGNED(cpumask_t *, sched_cpu_topo_end_mask);
++
++#ifdef CONFIG_SCHED_SMT
++DEFINE_STATIC_KEY_FALSE(sched_smt_present);
++EXPORT_SYMBOL_GPL(sched_smt_present);
++#endif
++
++/*
++ * Keep a unique ID per domain (we use the first CPUs number in the cpumask of
++ * the domain), this allows us to quickly tell if two cpus are in the same cache
++ * domain, see cpus_share_cache().
++ */
++DEFINE_PER_CPU(int, sd_llc_id);
++#endif /* CONFIG_SMP */
++
++static DEFINE_MUTEX(sched_hotcpu_mutex);
++
++DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
++
++#ifndef prepare_arch_switch
++# define prepare_arch_switch(next) do { } while (0)
++#endif
++#ifndef finish_arch_post_lock_switch
++# define finish_arch_post_lock_switch() do { } while (0)
++#endif
++
++#ifdef CONFIG_SCHED_SMT
++static cpumask_t sched_sg_idle_mask ____cacheline_aligned_in_smp;
++#endif
++static cpumask_t sched_preempt_mask[SCHED_QUEUE_BITS] ____cacheline_aligned_in_smp;
++static cpumask_t *const sched_idle_mask = &sched_preempt_mask[0];
++
++/* task function */
++static inline const struct cpumask *task_user_cpus(struct task_struct *p)
++{
++ if (!p->user_cpus_ptr)
++ return cpu_possible_mask; /* &init_task.cpus_mask */
++ return p->user_cpus_ptr;
++}
++
++/* sched_queue related functions */
++static inline void sched_queue_init(struct sched_queue *q)
++{
++ int i;
++
++ bitmap_zero(q->bitmap, SCHED_QUEUE_BITS);
++ for(i = 0; i < SCHED_LEVELS; i++)
++ INIT_LIST_HEAD(&q->heads[i]);
++}
++
++/*
++ * Init idle task and put into queue structure of rq
++ * IMPORTANT: may be called multiple times for a single cpu
++ */
++static inline void sched_queue_init_idle(struct sched_queue *q,
++ struct task_struct *idle)
++{
++ idle->sq_idx = IDLE_TASK_SCHED_PRIO;
++ INIT_LIST_HEAD(&q->heads[idle->sq_idx]);
++ list_add(&idle->sq_node, &q->heads[idle->sq_idx]);
++}
++
++static inline void
++clear_recorded_preempt_mask(int pr, int low, int high, int cpu)
++{
++ if (low < pr && pr <= high)
++ cpumask_clear_cpu(cpu, sched_preempt_mask + SCHED_QUEUE_BITS - pr);
++}
++
++static inline void
++set_recorded_preempt_mask(int pr, int low, int high, int cpu)
++{
++ if (low < pr && pr <= high)
++ cpumask_set_cpu(cpu, sched_preempt_mask + SCHED_QUEUE_BITS - pr);
++}
++
++static atomic_t sched_prio_record = ATOMIC_INIT(0);
++
++/* water mark related functions */
++static inline void update_sched_preempt_mask(struct rq *rq)
++{
++ unsigned long prio = find_first_bit(rq->queue.bitmap, SCHED_QUEUE_BITS);
++ unsigned long last_prio = rq->prio;
++ int cpu, pr;
++
++ if (prio == last_prio)
++ return;
++
++ rq->prio = prio;
++ cpu = cpu_of(rq);
++ pr = atomic_read(&sched_prio_record);
++
++ if (prio < last_prio) {
++ if (IDLE_TASK_SCHED_PRIO == last_prio) {
++#ifdef CONFIG_SCHED_SMT
++ if (static_branch_likely(&sched_smt_present))
++ cpumask_andnot(&sched_sg_idle_mask,
++ &sched_sg_idle_mask, cpu_smt_mask(cpu));
++#endif
++ cpumask_clear_cpu(cpu, sched_idle_mask);
++ last_prio -= 2;
++ }
++ clear_recorded_preempt_mask(pr, prio, last_prio, cpu);
++
++ return;
++ }
++ /* last_prio < prio */
++ if (IDLE_TASK_SCHED_PRIO == prio) {
++#ifdef CONFIG_SCHED_SMT
++ if (static_branch_likely(&sched_smt_present) &&
++ cpumask_intersects(cpu_smt_mask(cpu), sched_idle_mask))
++ cpumask_or(&sched_sg_idle_mask,
++ &sched_sg_idle_mask, cpu_smt_mask(cpu));
++#endif
++ cpumask_set_cpu(cpu, sched_idle_mask);
++ prio -= 2;
++ }
++ set_recorded_preempt_mask(pr, last_prio, prio, cpu);
++}
++
++/*
++ * This routine assume that the idle task always in queue
++ */
++static inline struct task_struct *sched_rq_first_task(struct rq *rq)
++{
++ const struct list_head *head = &rq->queue.heads[sched_prio2idx(rq->prio, rq)];
++
++ return list_first_entry(head, struct task_struct, sq_node);
++}
++
++static inline struct task_struct *
++sched_rq_next_task(struct task_struct *p, struct rq *rq)
++{
++ unsigned long idx = p->sq_idx;
++ struct list_head *head = &rq->queue.heads[idx];
++
++ if (list_is_last(&p->sq_node, head)) {
++ idx = find_next_bit(rq->queue.bitmap, SCHED_QUEUE_BITS,
++ sched_idx2prio(idx, rq) + 1);
++ head = &rq->queue.heads[sched_prio2idx(idx, rq)];
++
++ return list_first_entry(head, struct task_struct, sq_node);
++ }
++
++ return list_next_entry(p, sq_node);
++}
++
++static inline struct task_struct *rq_runnable_task(struct rq *rq)
++{
++ struct task_struct *next = sched_rq_first_task(rq);
++
++ if (unlikely(next == rq->skip))
++ next = sched_rq_next_task(next, rq);
++
++ return next;
++}
++
++/*
++ * Serialization rules:
++ *
++ * Lock order:
++ *
++ * p->pi_lock
++ * rq->lock
++ * hrtimer_cpu_base->lock (hrtimer_start() for bandwidth controls)
++ *
++ * rq1->lock
++ * rq2->lock where: rq1 < rq2
++ *
++ * Regular state:
++ *
++ * Normal scheduling state is serialized by rq->lock. __schedule() takes the
++ * local CPU's rq->lock, it optionally removes the task from the runqueue and
++ * always looks at the local rq data structures to find the most eligible task
++ * to run next.
++ *
++ * Task enqueue is also under rq->lock, possibly taken from another CPU.
++ * Wakeups from another LLC domain might use an IPI to transfer the enqueue to
++ * the local CPU to avoid bouncing the runqueue state around [ see
++ * ttwu_queue_wakelist() ]
++ *
++ * Task wakeup, specifically wakeups that involve migration, are horribly
++ * complicated to avoid having to take two rq->locks.
++ *
++ * Special state:
++ *
++ * System-calls and anything external will use task_rq_lock() which acquires
++ * both p->pi_lock and rq->lock. As a consequence the state they change is
++ * stable while holding either lock:
++ *
++ * - sched_setaffinity()/
++ * set_cpus_allowed_ptr(): p->cpus_ptr, p->nr_cpus_allowed
++ * - set_user_nice(): p->se.load, p->*prio
++ * - __sched_setscheduler(): p->sched_class, p->policy, p->*prio,
++ * p->se.load, p->rt_priority,
++ * p->dl.dl_{runtime, deadline, period, flags, bw, density}
++ * - sched_setnuma(): p->numa_preferred_nid
++ * - sched_move_task(): p->sched_task_group
++ * - uclamp_update_active() p->uclamp*
++ *
++ * p->state <- TASK_*:
++ *
++ * is changed locklessly using set_current_state(), __set_current_state() or
++ * set_special_state(), see their respective comments, or by
++ * try_to_wake_up(). This latter uses p->pi_lock to serialize against
++ * concurrent self.
++ *
++ * p->on_rq <- { 0, 1 = TASK_ON_RQ_QUEUED, 2 = TASK_ON_RQ_MIGRATING }:
++ *
++ * is set by activate_task() and cleared by deactivate_task(), under
++ * rq->lock. Non-zero indicates the task is runnable, the special
++ * ON_RQ_MIGRATING state is used for migration without holding both
++ * rq->locks. It indicates task_cpu() is not stable, see task_rq_lock().
++ *
++ * p->on_cpu <- { 0, 1 }:
++ *
++ * is set by prepare_task() and cleared by finish_task() such that it will be
++ * set before p is scheduled-in and cleared after p is scheduled-out, both
++ * under rq->lock. Non-zero indicates the task is running on its CPU.
++ *
++ * [ The astute reader will observe that it is possible for two tasks on one
++ * CPU to have ->on_cpu = 1 at the same time. ]
++ *
++ * task_cpu(p): is changed by set_task_cpu(), the rules are:
++ *
++ * - Don't call set_task_cpu() on a blocked task:
++ *
++ * We don't care what CPU we're not running on, this simplifies hotplug,
++ * the CPU assignment of blocked tasks isn't required to be valid.
++ *
++ * - for try_to_wake_up(), called under p->pi_lock:
++ *
++ * This allows try_to_wake_up() to only take one rq->lock, see its comment.
++ *
++ * - for migration called under rq->lock:
++ * [ see task_on_rq_migrating() in task_rq_lock() ]
++ *
++ * o move_queued_task()
++ * o detach_task()
++ *
++ * - for migration called under double_rq_lock():
++ *
++ * o __migrate_swap_task()
++ * o push_rt_task() / pull_rt_task()
++ * o push_dl_task() / pull_dl_task()
++ * o dl_task_offline_migration()
++ *
++ */
++
++/*
++ * Context: p->pi_lock
++ */
++static inline struct rq
++*__task_access_lock(struct task_struct *p, raw_spinlock_t **plock)
++{
++ struct rq *rq;
++ for (;;) {
++ rq = task_rq(p);
++ if (p->on_cpu || task_on_rq_queued(p)) {
++ raw_spin_lock(&rq->lock);
++ if (likely((p->on_cpu || task_on_rq_queued(p))
++ && rq == task_rq(p))) {
++ *plock = &rq->lock;
++ return rq;
++ }
++ raw_spin_unlock(&rq->lock);
++ } else if (task_on_rq_migrating(p)) {
++ do {
++ cpu_relax();
++ } while (unlikely(task_on_rq_migrating(p)));
++ } else {
++ *plock = NULL;
++ return rq;
++ }
++ }
++}
++
++static inline void
++__task_access_unlock(struct task_struct *p, raw_spinlock_t *lock)
++{
++ if (NULL != lock)
++ raw_spin_unlock(lock);
++}
++
++static inline struct rq
++*task_access_lock_irqsave(struct task_struct *p, raw_spinlock_t **plock,
++ unsigned long *flags)
++{
++ struct rq *rq;
++ for (;;) {
++ rq = task_rq(p);
++ if (p->on_cpu || task_on_rq_queued(p)) {
++ raw_spin_lock_irqsave(&rq->lock, *flags);
++ if (likely((p->on_cpu || task_on_rq_queued(p))
++ && rq == task_rq(p))) {
++ *plock = &rq->lock;
++ return rq;
++ }
++ raw_spin_unlock_irqrestore(&rq->lock, *flags);
++ } else if (task_on_rq_migrating(p)) {
++ do {
++ cpu_relax();
++ } while (unlikely(task_on_rq_migrating(p)));
++ } else {
++ raw_spin_lock_irqsave(&p->pi_lock, *flags);
++ if (likely(!p->on_cpu && !p->on_rq &&
++ rq == task_rq(p))) {
++ *plock = &p->pi_lock;
++ return rq;
++ }
++ raw_spin_unlock_irqrestore(&p->pi_lock, *flags);
++ }
++ }
++}
++
++static inline void
++task_access_unlock_irqrestore(struct task_struct *p, raw_spinlock_t *lock,
++ unsigned long *flags)
++{
++ raw_spin_unlock_irqrestore(lock, *flags);
++}
++
++/*
++ * __task_rq_lock - lock the rq @p resides on.
++ */
++struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf)
++ __acquires(rq->lock)
++{
++ struct rq *rq;
++
++ lockdep_assert_held(&p->pi_lock);
++
++ for (;;) {
++ rq = task_rq(p);
++ raw_spin_lock(&rq->lock);
++ if (likely(rq == task_rq(p) && !task_on_rq_migrating(p)))
++ return rq;
++ raw_spin_unlock(&rq->lock);
++
++ while (unlikely(task_on_rq_migrating(p)))
++ cpu_relax();
++ }
++}
++
++/*
++ * task_rq_lock - lock p->pi_lock and lock the rq @p resides on.
++ */
++struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf)
++ __acquires(p->pi_lock)
++ __acquires(rq->lock)
++{
++ struct rq *rq;
++
++ for (;;) {
++ raw_spin_lock_irqsave(&p->pi_lock, rf->flags);
++ rq = task_rq(p);
++ raw_spin_lock(&rq->lock);
++ /*
++ * move_queued_task() task_rq_lock()
++ *
++ * ACQUIRE (rq->lock)
++ * [S] ->on_rq = MIGRATING [L] rq = task_rq()
++ * WMB (__set_task_cpu()) ACQUIRE (rq->lock);
++ * [S] ->cpu = new_cpu [L] task_rq()
++ * [L] ->on_rq
++ * RELEASE (rq->lock)
++ *
++ * If we observe the old CPU in task_rq_lock(), the acquire of
++ * the old rq->lock will fully serialize against the stores.
++ *
++ * If we observe the new CPU in task_rq_lock(), the address
++ * dependency headed by '[L] rq = task_rq()' and the acquire
++ * will pair with the WMB to ensure we then also see migrating.
++ */
++ if (likely(rq == task_rq(p) && !task_on_rq_migrating(p))) {
++ return rq;
++ }
++ raw_spin_unlock(&rq->lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags);
++
++ while (unlikely(task_on_rq_migrating(p)))
++ cpu_relax();
++ }
++}
++
++static inline void
++rq_lock_irqsave(struct rq *rq, struct rq_flags *rf)
++ __acquires(rq->lock)
++{
++ raw_spin_lock_irqsave(&rq->lock, rf->flags);
++}
++
++static inline void
++rq_unlock_irqrestore(struct rq *rq, struct rq_flags *rf)
++ __releases(rq->lock)
++{
++ raw_spin_unlock_irqrestore(&rq->lock, rf->flags);
++}
++
++DEFINE_LOCK_GUARD_1(rq_lock_irqsave, struct rq,
++ rq_lock_irqsave(_T->lock, &_T->rf),
++ rq_unlock_irqrestore(_T->lock, &_T->rf),
++ struct rq_flags rf)
++
++void raw_spin_rq_lock_nested(struct rq *rq, int subclass)
++{
++ raw_spinlock_t *lock;
++
++ /* Matches synchronize_rcu() in __sched_core_enable() */
++ preempt_disable();
++
++ for (;;) {
++ lock = __rq_lockp(rq);
++ raw_spin_lock_nested(lock, subclass);
++ if (likely(lock == __rq_lockp(rq))) {
++ /* preempt_count *MUST* be > 1 */
++ preempt_enable_no_resched();
++ return;
++ }
++ raw_spin_unlock(lock);
++ }
++}
++
++void raw_spin_rq_unlock(struct rq *rq)
++{
++ raw_spin_unlock(rq_lockp(rq));
++}
++
++/*
++ * RQ-clock updating methods:
++ */
++
++static void update_rq_clock_task(struct rq *rq, s64 delta)
++{
++/*
++ * In theory, the compile should just see 0 here, and optimize out the call
++ * to sched_rt_avg_update. But I don't trust it...
++ */
++ s64 __maybe_unused steal = 0, irq_delta = 0;
++
++#ifdef CONFIG_IRQ_TIME_ACCOUNTING
++ irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time;
++
++ /*
++ * Since irq_time is only updated on {soft,}irq_exit, we might run into
++ * this case when a previous update_rq_clock() happened inside a
++ * {soft,}irq region.
++ *
++ * When this happens, we stop ->clock_task and only update the
++ * prev_irq_time stamp to account for the part that fit, so that a next
++ * update will consume the rest. This ensures ->clock_task is
++ * monotonic.
++ *
++ * It does however cause some slight miss-attribution of {soft,}irq
++ * time, a more accurate solution would be to update the irq_time using
++ * the current rq->clock timestamp, except that would require using
++ * atomic ops.
++ */
++ if (irq_delta > delta)
++ irq_delta = delta;
++
++ rq->prev_irq_time += irq_delta;
++ delta -= irq_delta;
++ delayacct_irq(rq->curr, irq_delta);
++#endif
++#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
++ if (static_key_false((¶virt_steal_rq_enabled))) {
++ steal = paravirt_steal_clock(cpu_of(rq));
++ steal -= rq->prev_steal_time_rq;
++
++ if (unlikely(steal > delta))
++ steal = delta;
++
++ rq->prev_steal_time_rq += steal;
++ delta -= steal;
++ }
++#endif
++
++ rq->clock_task += delta;
++
++#ifdef CONFIG_HAVE_SCHED_AVG_IRQ
++ if ((irq_delta + steal))
++ update_irq_load_avg(rq, irq_delta + steal);
++#endif
++}
++
++static inline void update_rq_clock(struct rq *rq)
++{
++ s64 delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
++
++ if (unlikely(delta <= 0))
++ return;
++ rq->clock += delta;
++ sched_update_rq_clock(rq);
++ update_rq_clock_task(rq, delta);
++}
++
++/*
++ * RQ Load update routine
++ */
++#define RQ_LOAD_HISTORY_BITS (sizeof(s32) * 8ULL)
++#define RQ_UTIL_SHIFT (8)
++#define RQ_LOAD_HISTORY_TO_UTIL(l) (((l) >> (RQ_LOAD_HISTORY_BITS - 1 - RQ_UTIL_SHIFT)) & 0xff)
++
++#define LOAD_BLOCK(t) ((t) >> 17)
++#define LOAD_HALF_BLOCK(t) ((t) >> 16)
++#define BLOCK_MASK(t) ((t) & ((0x01 << 18) - 1))
++#define LOAD_BLOCK_BIT(b) (1UL << (RQ_LOAD_HISTORY_BITS - 1 - (b)))
++#define CURRENT_LOAD_BIT LOAD_BLOCK_BIT(0)
++
++static inline void rq_load_update(struct rq *rq)
++{
++ u64 time = rq->clock;
++ u64 delta = min(LOAD_BLOCK(time) - LOAD_BLOCK(rq->load_stamp),
++ RQ_LOAD_HISTORY_BITS - 1);
++ u64 prev = !!(rq->load_history & CURRENT_LOAD_BIT);
++ u64 curr = !!rq->nr_running;
++
++ if (delta) {
++ rq->load_history = rq->load_history >> delta;
++
++ if (delta < RQ_UTIL_SHIFT) {
++ rq->load_block += (~BLOCK_MASK(rq->load_stamp)) * prev;
++ if (!!LOAD_HALF_BLOCK(rq->load_block) ^ curr)
++ rq->load_history ^= LOAD_BLOCK_BIT(delta);
++ }
++
++ rq->load_block = BLOCK_MASK(time) * prev;
++ } else {
++ rq->load_block += (time - rq->load_stamp) * prev;
++ }
++ if (prev ^ curr)
++ rq->load_history ^= CURRENT_LOAD_BIT;
++ rq->load_stamp = time;
++}
++
++unsigned long rq_load_util(struct rq *rq, unsigned long max)
++{
++ return RQ_LOAD_HISTORY_TO_UTIL(rq->load_history) * (max >> RQ_UTIL_SHIFT);
++}
++
++#ifdef CONFIG_SMP
++unsigned long sched_cpu_util(int cpu)
++{
++ return rq_load_util(cpu_rq(cpu), arch_scale_cpu_capacity(cpu));
++}
++#endif /* CONFIG_SMP */
++
++#ifdef CONFIG_CPU_FREQ
++/**
++ * cpufreq_update_util - Take a note about CPU utilization changes.
++ * @rq: Runqueue to carry out the update for.
++ * @flags: Update reason flags.
++ *
++ * This function is called by the scheduler on the CPU whose utilization is
++ * being updated.
++ *
++ * It can only be called from RCU-sched read-side critical sections.
++ *
++ * The way cpufreq is currently arranged requires it to evaluate the CPU
++ * performance state (frequency/voltage) on a regular basis to prevent it from
++ * being stuck in a completely inadequate performance level for too long.
++ * That is not guaranteed to happen if the updates are only triggered from CFS
++ * and DL, though, because they may not be coming in if only RT tasks are
++ * active all the time (or there are RT tasks only).
++ *
++ * As a workaround for that issue, this function is called periodically by the
++ * RT sched class to trigger extra cpufreq updates to prevent it from stalling,
++ * but that really is a band-aid. Going forward it should be replaced with
++ * solutions targeted more specifically at RT tasks.
++ */
++static inline void cpufreq_update_util(struct rq *rq, unsigned int flags)
++{
++ struct update_util_data *data;
++
++#ifdef CONFIG_SMP
++ rq_load_update(rq);
++#endif
++ data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data,
++ cpu_of(rq)));
++ if (data)
++ data->func(data, rq_clock(rq), flags);
++}
++#else
++static inline void cpufreq_update_util(struct rq *rq, unsigned int flags)
++{
++#ifdef CONFIG_SMP
++ rq_load_update(rq);
++#endif
++}
++#endif /* CONFIG_CPU_FREQ */
++
++#ifdef CONFIG_NO_HZ_FULL
++/*
++ * Tick may be needed by tasks in the runqueue depending on their policy and
++ * requirements. If tick is needed, lets send the target an IPI to kick it out
++ * of nohz mode if necessary.
++ */
++static inline void sched_update_tick_dependency(struct rq *rq)
++{
++ int cpu = cpu_of(rq);
++
++ if (!tick_nohz_full_cpu(cpu))
++ return;
++
++ if (rq->nr_running < 2)
++ tick_nohz_dep_clear_cpu(cpu, TICK_DEP_BIT_SCHED);
++ else
++ tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_SCHED);
++}
++#else /* !CONFIG_NO_HZ_FULL */
++static inline void sched_update_tick_dependency(struct rq *rq) { }
++#endif
++
++bool sched_task_on_rq(struct task_struct *p)
++{
++ return task_on_rq_queued(p);
++}
++
++unsigned long get_wchan(struct task_struct *p)
++{
++ unsigned long ip = 0;
++ unsigned int state;
++
++ if (!p || p == current)
++ return 0;
++
++ /* Only get wchan if task is blocked and we can keep it that way. */
++ raw_spin_lock_irq(&p->pi_lock);
++ state = READ_ONCE(p->__state);
++ smp_rmb(); /* see try_to_wake_up() */
++ if (state != TASK_RUNNING && state != TASK_WAKING && !p->on_rq)
++ ip = __get_wchan(p);
++ raw_spin_unlock_irq(&p->pi_lock);
++
++ return ip;
++}
++
++/*
++ * Add/Remove/Requeue task to/from the runqueue routines
++ * Context: rq->lock
++ */
++#define __SCHED_DEQUEUE_TASK(p, rq, flags, func) \
++ sched_info_dequeue(rq, p); \
++ \
++ list_del(&p->sq_node); \
++ if (list_empty(&rq->queue.heads[p->sq_idx])) { \
++ clear_bit(sched_idx2prio(p->sq_idx, rq), rq->queue.bitmap); \
++ func; \
++ }
++
++#define __SCHED_ENQUEUE_TASK(p, rq, flags) \
++ sched_info_enqueue(rq, p); \
++ \
++ p->sq_idx = task_sched_prio_idx(p, rq); \
++ list_add_tail(&p->sq_node, &rq->queue.heads[p->sq_idx]); \
++ set_bit(sched_idx2prio(p->sq_idx, rq), rq->queue.bitmap);
++
++static inline void dequeue_task(struct task_struct *p, struct rq *rq, int flags)
++{
++#ifdef ALT_SCHED_DEBUG
++ lockdep_assert_held(&rq->lock);
++
++ /*printk(KERN_INFO "sched: dequeue(%d) %px %016llx\n", cpu_of(rq), p, p->deadline);*/
++ WARN_ONCE(task_rq(p) != rq, "sched: dequeue task reside on cpu%d from cpu%d\n",
++ task_cpu(p), cpu_of(rq));
++#endif
++
++ __SCHED_DEQUEUE_TASK(p, rq, flags, update_sched_preempt_mask(rq));
++ --rq->nr_running;
++#ifdef CONFIG_SMP
++ if (1 == rq->nr_running)
++ cpumask_clear_cpu(cpu_of(rq), &sched_rq_pending_mask);
++#endif
++
++ sched_update_tick_dependency(rq);
++}
++
++static inline void enqueue_task(struct task_struct *p, struct rq *rq, int flags)
++{
++#ifdef ALT_SCHED_DEBUG
++ lockdep_assert_held(&rq->lock);
++
++ /*printk(KERN_INFO "sched: enqueue(%d) %px %d\n", cpu_of(rq), p, p->prio);*/
++ WARN_ONCE(task_rq(p) != rq, "sched: enqueue task reside on cpu%d to cpu%d\n",
++ task_cpu(p), cpu_of(rq));
++#endif
++
++ __SCHED_ENQUEUE_TASK(p, rq, flags);
++ update_sched_preempt_mask(rq);
++ ++rq->nr_running;
++#ifdef CONFIG_SMP
++ if (2 == rq->nr_running)
++ cpumask_set_cpu(cpu_of(rq), &sched_rq_pending_mask);
++#endif
++
++ sched_update_tick_dependency(rq);
++}
++
++static inline void requeue_task(struct task_struct *p, struct rq *rq, int idx)
++{
++#ifdef ALT_SCHED_DEBUG
++ lockdep_assert_held(&rq->lock);
++ /*printk(KERN_INFO "sched: requeue(%d) %px %016llx\n", cpu_of(rq), p, p->deadline);*/
++ WARN_ONCE(task_rq(p) != rq, "sched: cpu[%d] requeue task reside on cpu%d\n",
++ cpu_of(rq), task_cpu(p));
++#endif
++
++ list_del(&p->sq_node);
++ list_add_tail(&p->sq_node, &rq->queue.heads[idx]);
++ if (idx != p->sq_idx) {
++ if (list_empty(&rq->queue.heads[p->sq_idx]))
++ clear_bit(sched_idx2prio(p->sq_idx, rq), rq->queue.bitmap);
++ p->sq_idx = idx;
++ set_bit(sched_idx2prio(p->sq_idx, rq), rq->queue.bitmap);
++ update_sched_preempt_mask(rq);
++ }
++}
++
++/*
++ * cmpxchg based fetch_or, macro so it works for different integer types
++ */
++#define fetch_or(ptr, mask) \
++ ({ \
++ typeof(ptr) _ptr = (ptr); \
++ typeof(mask) _mask = (mask); \
++ typeof(*_ptr) _val = *_ptr; \
++ \
++ do { \
++ } while (!try_cmpxchg(_ptr, &_val, _val | _mask)); \
++ _val; \
++})
++
++#if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG)
++/*
++ * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG,
++ * this avoids any races wrt polling state changes and thereby avoids
++ * spurious IPIs.
++ */
++static inline bool set_nr_and_not_polling(struct task_struct *p)
++{
++ struct thread_info *ti = task_thread_info(p);
++ return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG);
++}
++
++/*
++ * Atomically set TIF_NEED_RESCHED if TIF_POLLING_NRFLAG is set.
++ *
++ * If this returns true, then the idle task promises to call
++ * sched_ttwu_pending() and reschedule soon.
++ */
++static bool set_nr_if_polling(struct task_struct *p)
++{
++ struct thread_info *ti = task_thread_info(p);
++ typeof(ti->flags) val = READ_ONCE(ti->flags);
++
++ do {
++ if (!(val & _TIF_POLLING_NRFLAG))
++ return false;
++ if (val & _TIF_NEED_RESCHED)
++ return true;
++ } while (!try_cmpxchg(&ti->flags, &val, val | _TIF_NEED_RESCHED));
++
++ return true;
++}
++
++#else
++static inline bool set_nr_and_not_polling(struct task_struct *p)
++{
++ set_tsk_need_resched(p);
++ return true;
++}
++
++#ifdef CONFIG_SMP
++static inline bool set_nr_if_polling(struct task_struct *p)
++{
++ return false;
++}
++#endif
++#endif
++
++static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task)
++{
++ struct wake_q_node *node = &task->wake_q;
++
++ /*
++ * Atomically grab the task, if ->wake_q is !nil already it means
++ * it's already queued (either by us or someone else) and will get the
++ * wakeup due to that.
++ *
++ * In order to ensure that a pending wakeup will observe our pending
++ * state, even in the failed case, an explicit smp_mb() must be used.
++ */
++ smp_mb__before_atomic();
++ if (unlikely(cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL)))
++ return false;
++
++ /*
++ * The head is context local, there can be no concurrency.
++ */
++ *head->lastp = node;
++ head->lastp = &node->next;
++ return true;
++}
++
++/**
++ * wake_q_add() - queue a wakeup for 'later' waking.
++ * @head: the wake_q_head to add @task to
++ * @task: the task to queue for 'later' wakeup
++ *
++ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
++ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
++ * instantly.
++ *
++ * This function must be used as-if it were wake_up_process(); IOW the task
++ * must be ready to be woken at this location.
++ */
++void wake_q_add(struct wake_q_head *head, struct task_struct *task)
++{
++ if (__wake_q_add(head, task))
++ get_task_struct(task);
++}
++
++/**
++ * wake_q_add_safe() - safely queue a wakeup for 'later' waking.
++ * @head: the wake_q_head to add @task to
++ * @task: the task to queue for 'later' wakeup
++ *
++ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
++ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
++ * instantly.
++ *
++ * This function must be used as-if it were wake_up_process(); IOW the task
++ * must be ready to be woken at this location.
++ *
++ * This function is essentially a task-safe equivalent to wake_q_add(). Callers
++ * that already hold reference to @task can call the 'safe' version and trust
++ * wake_q to do the right thing depending whether or not the @task is already
++ * queued for wakeup.
++ */
++void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task)
++{
++ if (!__wake_q_add(head, task))
++ put_task_struct(task);
++}
++
++void wake_up_q(struct wake_q_head *head)
++{
++ struct wake_q_node *node = head->first;
++
++ while (node != WAKE_Q_TAIL) {
++ struct task_struct *task;
++
++ task = container_of(node, struct task_struct, wake_q);
++ /* task can safely be re-inserted now: */
++ node = node->next;
++ task->wake_q.next = NULL;
++
++ /*
++ * wake_up_process() executes a full barrier, which pairs with
++ * the queueing in wake_q_add() so as not to miss wakeups.
++ */
++ wake_up_process(task);
++ put_task_struct(task);
++ }
++}
++
++/*
++ * resched_curr - mark rq's current task 'to be rescheduled now'.
++ *
++ * On UP this means the setting of the need_resched flag, on SMP it
++ * might also involve a cross-CPU call to trigger the scheduler on
++ * the target CPU.
++ */
++static inline void resched_curr(struct rq *rq)
++{
++ struct task_struct *curr = rq->curr;
++ int cpu;
++
++ lockdep_assert_held(&rq->lock);
++
++ if (test_tsk_need_resched(curr))
++ return;
++
++ cpu = cpu_of(rq);
++ if (cpu == smp_processor_id()) {
++ set_tsk_need_resched(curr);
++ set_preempt_need_resched();
++ return;
++ }
++
++ if (set_nr_and_not_polling(curr))
++ smp_send_reschedule(cpu);
++ else
++ trace_sched_wake_idle_without_ipi(cpu);
++}
++
++void resched_cpu(int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++ unsigned long flags;
++
++ raw_spin_lock_irqsave(&rq->lock, flags);
++ if (cpu_online(cpu) || cpu == smp_processor_id())
++ resched_curr(cpu_rq(cpu));
++ raw_spin_unlock_irqrestore(&rq->lock, flags);
++}
++
++#ifdef CONFIG_SMP
++#ifdef CONFIG_NO_HZ_COMMON
++/*
++ * This routine will record that the CPU is going idle with tick stopped.
++ * This info will be used in performing idle load balancing in the future.
++ */
++void nohz_balance_enter_idle(int cpu) {}
++
++/*
++ * In the semi idle case, use the nearest busy CPU for migrating timers
++ * from an idle CPU. This is good for power-savings.
++ *
++ * We don't do similar optimization for completely idle system, as
++ * selecting an idle CPU will add more delays to the timers than intended
++ * (as that CPU's timer base may not be uptodate wrt jiffies etc).
++ */
++int get_nohz_timer_target(void)
++{
++ int i, cpu = smp_processor_id(), default_cpu = -1;
++ struct cpumask *mask;
++ const struct cpumask *hk_mask;
++
++ if (housekeeping_cpu(cpu, HK_TYPE_TIMER)) {
++ if (!idle_cpu(cpu))
++ return cpu;
++ default_cpu = cpu;
++ }
++
++ hk_mask = housekeeping_cpumask(HK_TYPE_TIMER);
++
++ for (mask = per_cpu(sched_cpu_topo_masks, cpu) + 1;
++ mask < per_cpu(sched_cpu_topo_end_mask, cpu); mask++)
++ for_each_cpu_and(i, mask, hk_mask)
++ if (!idle_cpu(i))
++ return i;
++
++ if (default_cpu == -1)
++ default_cpu = housekeeping_any_cpu(HK_TYPE_TIMER);
++ cpu = default_cpu;
++
++ return cpu;
++}
++
++/*
++ * When add_timer_on() enqueues a timer into the timer wheel of an
++ * idle CPU then this timer might expire before the next timer event
++ * which is scheduled to wake up that CPU. In case of a completely
++ * idle system the next event might even be infinite time into the
++ * future. wake_up_idle_cpu() ensures that the CPU is woken up and
++ * leaves the inner idle loop so the newly added timer is taken into
++ * account when the CPU goes back to idle and evaluates the timer
++ * wheel for the next timer event.
++ */
++static inline void wake_up_idle_cpu(int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ if (cpu == smp_processor_id())
++ return;
++
++ /*
++ * Set TIF_NEED_RESCHED and send an IPI if in the non-polling
++ * part of the idle loop. This forces an exit from the idle loop
++ * and a round trip to schedule(). Now this could be optimized
++ * because a simple new idle loop iteration is enough to
++ * re-evaluate the next tick. Provided some re-ordering of tick
++ * nohz functions that would need to follow TIF_NR_POLLING
++ * clearing:
++ *
++ * - On most archs, a simple fetch_or on ti::flags with a
++ * "0" value would be enough to know if an IPI needs to be sent.
++ *
++ * - x86 needs to perform a last need_resched() check between
++ * monitor and mwait which doesn't take timers into account.
++ * There a dedicated TIF_TIMER flag would be required to
++ * fetch_or here and be checked along with TIF_NEED_RESCHED
++ * before mwait().
++ *
++ * However, remote timer enqueue is not such a frequent event
++ * and testing of the above solutions didn't appear to report
++ * much benefits.
++ */
++ if (set_nr_and_not_polling(rq->idle))
++ smp_send_reschedule(cpu);
++ else
++ trace_sched_wake_idle_without_ipi(cpu);
++}
++
++static inline bool wake_up_full_nohz_cpu(int cpu)
++{
++ /*
++ * We just need the target to call irq_exit() and re-evaluate
++ * the next tick. The nohz full kick at least implies that.
++ * If needed we can still optimize that later with an
++ * empty IRQ.
++ */
++ if (cpu_is_offline(cpu))
++ return true; /* Don't try to wake offline CPUs. */
++ if (tick_nohz_full_cpu(cpu)) {
++ if (cpu != smp_processor_id() ||
++ tick_nohz_tick_stopped())
++ tick_nohz_full_kick_cpu(cpu);
++ return true;
++ }
++
++ return false;
++}
++
++void wake_up_nohz_cpu(int cpu)
++{
++ if (!wake_up_full_nohz_cpu(cpu))
++ wake_up_idle_cpu(cpu);
++}
++
++static void nohz_csd_func(void *info)
++{
++ struct rq *rq = info;
++ int cpu = cpu_of(rq);
++ unsigned int flags;
++
++ /*
++ * Release the rq::nohz_csd.
++ */
++ flags = atomic_fetch_andnot(NOHZ_KICK_MASK, nohz_flags(cpu));
++ WARN_ON(!(flags & NOHZ_KICK_MASK));
++
++ rq->idle_balance = idle_cpu(cpu);
++ if (rq->idle_balance && !need_resched()) {
++ rq->nohz_idle_balance = flags;
++ raise_softirq_irqoff(SCHED_SOFTIRQ);
++ }
++}
++
++#endif /* CONFIG_NO_HZ_COMMON */
++#endif /* CONFIG_SMP */
++
++static inline void wakeup_preempt(struct rq *rq)
++{
++ if (sched_rq_first_task(rq) != rq->curr)
++ resched_curr(rq);
++}
++
++static __always_inline
++int __task_state_match(struct task_struct *p, unsigned int state)
++{
++ if (READ_ONCE(p->__state) & state)
++ return 1;
++
++ if (READ_ONCE(p->saved_state) & state)
++ return -1;
++
++ return 0;
++}
++
++static __always_inline
++int task_state_match(struct task_struct *p, unsigned int state)
++{
++ /*
++ * Serialize against current_save_and_set_rtlock_wait_state(),
++ * current_restore_rtlock_saved_state(), and __refrigerator().
++ */
++ guard(raw_spinlock_irq)(&p->pi_lock);
++
++ return __task_state_match(p, state);
++}
++
++/*
++ * wait_task_inactive - wait for a thread to unschedule.
++ *
++ * Wait for the thread to block in any of the states set in @match_state.
++ * If it changes, i.e. @p might have woken up, then return zero. When we
++ * succeed in waiting for @p to be off its CPU, we return a positive number
++ * (its total switch count). If a second call a short while later returns the
++ * same number, the caller can be sure that @p has remained unscheduled the
++ * whole time.
++ *
++ * The caller must ensure that the task *will* unschedule sometime soon,
++ * else this function might spin for a *long* time. This function can't
++ * be called with interrupts off, or it may introduce deadlock with
++ * smp_call_function() if an IPI is sent by the same process we are
++ * waiting to become inactive.
++ */
++unsigned long wait_task_inactive(struct task_struct *p, unsigned int match_state)
++{
++ unsigned long flags;
++ int running, queued, match;
++ unsigned long ncsw;
++ struct rq *rq;
++ raw_spinlock_t *lock;
++
++ for (;;) {
++ rq = task_rq(p);
++
++ /*
++ * If the task is actively running on another CPU
++ * still, just relax and busy-wait without holding
++ * any locks.
++ *
++ * NOTE! Since we don't hold any locks, it's not
++ * even sure that "rq" stays as the right runqueue!
++ * But we don't care, since this will return false
++ * if the runqueue has changed and p is actually now
++ * running somewhere else!
++ */
++ while (task_on_cpu(p)) {
++ if (!task_state_match(p, match_state))
++ return 0;
++ cpu_relax();
++ }
++
++ /*
++ * Ok, time to look more closely! We need the rq
++ * lock now, to be *sure*. If we're wrong, we'll
++ * just go back and repeat.
++ */
++ task_access_lock_irqsave(p, &lock, &flags);
++ trace_sched_wait_task(p);
++ running = task_on_cpu(p);
++ queued = p->on_rq;
++ ncsw = 0;
++ if ((match = __task_state_match(p, match_state))) {
++ /*
++ * When matching on p->saved_state, consider this task
++ * still queued so it will wait.
++ */
++ if (match < 0)
++ queued = 1;
++ ncsw = p->nvcsw | LONG_MIN; /* sets MSB */
++ }
++ task_access_unlock_irqrestore(p, lock, &flags);
++
++ /*
++ * If it changed from the expected state, bail out now.
++ */
++ if (unlikely(!ncsw))
++ break;
++
++ /*
++ * Was it really running after all now that we
++ * checked with the proper locks actually held?
++ *
++ * Oops. Go back and try again..
++ */
++ if (unlikely(running)) {
++ cpu_relax();
++ continue;
++ }
++
++ /*
++ * It's not enough that it's not actively running,
++ * it must be off the runqueue _entirely_, and not
++ * preempted!
++ *
++ * So if it was still runnable (but just not actively
++ * running right now), it's preempted, and we should
++ * yield - it could be a while.
++ */
++ if (unlikely(queued)) {
++ ktime_t to = NSEC_PER_SEC / HZ;
++
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_hrtimeout(&to, HRTIMER_MODE_REL_HARD);
++ continue;
++ }
++
++ /*
++ * Ahh, all good. It wasn't running, and it wasn't
++ * runnable, which means that it will never become
++ * running in the future either. We're all done!
++ */
++ break;
++ }
++
++ return ncsw;
++}
++
++#ifdef CONFIG_SCHED_HRTICK
++/*
++ * Use HR-timers to deliver accurate preemption points.
++ */
++
++static void hrtick_clear(struct rq *rq)
++{
++ if (hrtimer_active(&rq->hrtick_timer))
++ hrtimer_cancel(&rq->hrtick_timer);
++}
++
++/*
++ * High-resolution timer tick.
++ * Runs from hardirq context with interrupts disabled.
++ */
++static enum hrtimer_restart hrtick(struct hrtimer *timer)
++{
++ struct rq *rq = container_of(timer, struct rq, hrtick_timer);
++
++ WARN_ON_ONCE(cpu_of(rq) != smp_processor_id());
++
++ raw_spin_lock(&rq->lock);
++ resched_curr(rq);
++ raw_spin_unlock(&rq->lock);
++
++ return HRTIMER_NORESTART;
++}
++
++/*
++ * Use hrtick when:
++ * - enabled by features
++ * - hrtimer is actually high res
++ */
++static inline int hrtick_enabled(struct rq *rq)
++{
++ /**
++ * Alt schedule FW doesn't support sched_feat yet
++ if (!sched_feat(HRTICK))
++ return 0;
++ */
++ if (!cpu_active(cpu_of(rq)))
++ return 0;
++ return hrtimer_is_hres_active(&rq->hrtick_timer);
++}
++
++#ifdef CONFIG_SMP
++
++static void __hrtick_restart(struct rq *rq)
++{
++ struct hrtimer *timer = &rq->hrtick_timer;
++ ktime_t time = rq->hrtick_time;
++
++ hrtimer_start(timer, time, HRTIMER_MODE_ABS_PINNED_HARD);
++}
++
++/*
++ * called from hardirq (IPI) context
++ */
++static void __hrtick_start(void *arg)
++{
++ struct rq *rq = arg;
++
++ raw_spin_lock(&rq->lock);
++ __hrtick_restart(rq);
++ raw_spin_unlock(&rq->lock);
++}
++
++/*
++ * Called to set the hrtick timer state.
++ *
++ * called with rq->lock held and irqs disabled
++ */
++static inline void hrtick_start(struct rq *rq, u64 delay)
++{
++ struct hrtimer *timer = &rq->hrtick_timer;
++ s64 delta;
++
++ /*
++ * Don't schedule slices shorter than 10000ns, that just
++ * doesn't make sense and can cause timer DoS.
++ */
++ delta = max_t(s64, delay, 10000LL);
++
++ rq->hrtick_time = ktime_add_ns(timer->base->get_time(), delta);
++
++ if (rq == this_rq())
++ __hrtick_restart(rq);
++ else
++ smp_call_function_single_async(cpu_of(rq), &rq->hrtick_csd);
++}
++
++#else
++/*
++ * Called to set the hrtick timer state.
++ *
++ * called with rq->lock held and irqs disabled
++ */
++static inline void hrtick_start(struct rq *rq, u64 delay)
++{
++ /*
++ * Don't schedule slices shorter than 10000ns, that just
++ * doesn't make sense. Rely on vruntime for fairness.
++ */
++ delay = max_t(u64, delay, 10000LL);
++ hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay),
++ HRTIMER_MODE_REL_PINNED_HARD);
++}
++#endif /* CONFIG_SMP */
++
++static void hrtick_rq_init(struct rq *rq)
++{
++#ifdef CONFIG_SMP
++ INIT_CSD(&rq->hrtick_csd, __hrtick_start, rq);
++#endif
++
++ hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
++ rq->hrtick_timer.function = hrtick;
++}
++#else /* CONFIG_SCHED_HRTICK */
++static inline int hrtick_enabled(struct rq *rq)
++{
++ return 0;
++}
++
++static inline void hrtick_clear(struct rq *rq)
++{
++}
++
++static inline void hrtick_rq_init(struct rq *rq)
++{
++}
++#endif /* CONFIG_SCHED_HRTICK */
++
++static inline int __normal_prio(int policy, int rt_prio, int static_prio)
++{
++ return rt_policy(policy) ? (MAX_RT_PRIO - 1 - rt_prio) :
++ static_prio + MAX_PRIORITY_ADJ;
++}
++
++/*
++ * Calculate the expected normal priority: i.e. priority
++ * without taking RT-inheritance into account. Might be
++ * boosted by interactivity modifiers. Changes upon fork,
++ * setprio syscalls, and whenever the interactivity
++ * estimator recalculates.
++ */
++static inline int normal_prio(struct task_struct *p)
++{
++ return __normal_prio(p->policy, p->rt_priority, p->static_prio);
++}
++
++/*
++ * Calculate the current priority, i.e. the priority
++ * taken into account by the scheduler. This value might
++ * be boosted by RT tasks as it will be RT if the task got
++ * RT-boosted. If not then it returns p->normal_prio.
++ */
++static int effective_prio(struct task_struct *p)
++{
++ p->normal_prio = normal_prio(p);
++ /*
++ * If we are RT tasks or we were boosted to RT priority,
++ * keep the priority unchanged. Otherwise, update priority
++ * to the normal priority:
++ */
++ if (!rt_prio(p->prio))
++ return p->normal_prio;
++ return p->prio;
++}
++
++/*
++ * activate_task - move a task to the runqueue.
++ *
++ * Context: rq->lock
++ */
++static void activate_task(struct task_struct *p, struct rq *rq)
++{
++ enqueue_task(p, rq, ENQUEUE_WAKEUP);
++
++ WRITE_ONCE(p->on_rq, TASK_ON_RQ_QUEUED);
++ ASSERT_EXCLUSIVE_WRITER(p->on_rq);
++
++ /*
++ * If in_iowait is set, the code below may not trigger any cpufreq
++ * utilization updates, so do it here explicitly with the IOWAIT flag
++ * passed.
++ */
++ cpufreq_update_util(rq, SCHED_CPUFREQ_IOWAIT * p->in_iowait);
++}
++
++/*
++ * deactivate_task - remove a task from the runqueue.
++ *
++ * Context: rq->lock
++ */
++static inline void deactivate_task(struct task_struct *p, struct rq *rq)
++{
++ WRITE_ONCE(p->on_rq, 0);
++ ASSERT_EXCLUSIVE_WRITER(p->on_rq);
++
++ dequeue_task(p, rq, DEQUEUE_SLEEP);
++
++ cpufreq_update_util(rq, 0);
++}
++
++static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
++{
++#ifdef CONFIG_SMP
++ /*
++ * After ->cpu is set up to a new value, task_access_lock(p, ...) can be
++ * successfully executed on another CPU. We must ensure that updates of
++ * per-task data have been completed by this moment.
++ */
++ smp_wmb();
++
++ WRITE_ONCE(task_thread_info(p)->cpu, cpu);
++#endif
++}
++
++static inline bool is_migration_disabled(struct task_struct *p)
++{
++#ifdef CONFIG_SMP
++ return p->migration_disabled;
++#else
++ return false;
++#endif
++}
++
++#define SCA_CHECK 0x01
++#define SCA_USER 0x08
++
++#ifdef CONFIG_SMP
++
++void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
++{
++#ifdef CONFIG_SCHED_DEBUG
++ unsigned int state = READ_ONCE(p->__state);
++
++ /*
++ * We should never call set_task_cpu() on a blocked task,
++ * ttwu() will sort out the placement.
++ */
++ WARN_ON_ONCE(state != TASK_RUNNING && state != TASK_WAKING && !p->on_rq);
++
++#ifdef CONFIG_LOCKDEP
++ /*
++ * The caller should hold either p->pi_lock or rq->lock, when changing
++ * a task's CPU. ->pi_lock for waking tasks, rq->lock for runnable tasks.
++ *
++ * sched_move_task() holds both and thus holding either pins the cgroup,
++ * see task_group().
++ */
++ WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) ||
++ lockdep_is_held(&task_rq(p)->lock)));
++#endif
++ /*
++ * Clearly, migrating tasks to offline CPUs is a fairly daft thing.
++ */
++ WARN_ON_ONCE(!cpu_online(new_cpu));
++
++ WARN_ON_ONCE(is_migration_disabled(p));
++#endif
++ trace_sched_migrate_task(p, new_cpu);
++
++ if (task_cpu(p) != new_cpu)
++ {
++ rseq_migrate(p);
++ perf_event_task_migrate(p);
++ }
++
++ __set_task_cpu(p, new_cpu);
++}
++
++#define MDF_FORCE_ENABLED 0x80
++
++static void
++__do_set_cpus_ptr(struct task_struct *p, const struct cpumask *new_mask)
++{
++ /*
++ * This here violates the locking rules for affinity, since we're only
++ * supposed to change these variables while holding both rq->lock and
++ * p->pi_lock.
++ *
++ * HOWEVER, it magically works, because ttwu() is the only code that
++ * accesses these variables under p->pi_lock and only does so after
++ * smp_cond_load_acquire(&p->on_cpu, !VAL), and we're in __schedule()
++ * before finish_task().
++ *
++ * XXX do further audits, this smells like something putrid.
++ */
++ SCHED_WARN_ON(!p->on_cpu);
++ p->cpus_ptr = new_mask;
++}
++
++void migrate_disable(void)
++{
++ struct task_struct *p = current;
++ int cpu;
++
++ if (p->migration_disabled) {
++ p->migration_disabled++;
++ return;
++ }
++
++ guard(preempt)();
++ cpu = smp_processor_id();
++ if (cpumask_test_cpu(cpu, &p->cpus_mask)) {
++ cpu_rq(cpu)->nr_pinned++;
++ p->migration_disabled = 1;
++ p->migration_flags &= ~MDF_FORCE_ENABLED;
++
++ /*
++ * Violates locking rules! see comment in __do_set_cpus_ptr().
++ */
++ if (p->cpus_ptr == &p->cpus_mask)
++ __do_set_cpus_ptr(p, cpumask_of(cpu));
++ }
++}
++EXPORT_SYMBOL_GPL(migrate_disable);
++
++void migrate_enable(void)
++{
++ struct task_struct *p = current;
++
++ if (0 == p->migration_disabled)
++ return;
++
++ if (p->migration_disabled > 1) {
++ p->migration_disabled--;
++ return;
++ }
++
++ if (WARN_ON_ONCE(!p->migration_disabled))
++ return;
++
++ /*
++ * Ensure stop_task runs either before or after this, and that
++ * __set_cpus_allowed_ptr(SCA_MIGRATE_ENABLE) doesn't schedule().
++ */
++ guard(preempt)();
++ /*
++ * Assumption: current should be running on allowed cpu
++ */
++ WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &p->cpus_mask));
++ if (p->cpus_ptr != &p->cpus_mask)
++ __do_set_cpus_ptr(p, &p->cpus_mask);
++ /*
++ * Mustn't clear migration_disabled() until cpus_ptr points back at the
++ * regular cpus_mask, otherwise things that race (eg.
++ * select_fallback_rq) get confused.
++ */
++ barrier();
++ p->migration_disabled = 0;
++ this_rq()->nr_pinned--;
++}
++EXPORT_SYMBOL_GPL(migrate_enable);
++
++static inline bool rq_has_pinned_tasks(struct rq *rq)
++{
++ return rq->nr_pinned;
++}
++
++/*
++ * Per-CPU kthreads are allowed to run on !active && online CPUs, see
++ * __set_cpus_allowed_ptr() and select_fallback_rq().
++ */
++static inline bool is_cpu_allowed(struct task_struct *p, int cpu)
++{
++ /* When not in the task's cpumask, no point in looking further. */
++ if (!cpumask_test_cpu(cpu, p->cpus_ptr))
++ return false;
++
++ /* migrate_disabled() must be allowed to finish. */
++ if (is_migration_disabled(p))
++ return cpu_online(cpu);
++
++ /* Non kernel threads are not allowed during either online or offline. */
++ if (!(p->flags & PF_KTHREAD))
++ return cpu_active(cpu) && task_cpu_possible(cpu, p);
++
++ /* KTHREAD_IS_PER_CPU is always allowed. */
++ if (kthread_is_per_cpu(p))
++ return cpu_online(cpu);
++
++ /* Regular kernel threads don't get to stay during offline. */
++ if (cpu_dying(cpu))
++ return false;
++
++ /* But are allowed during online. */
++ return cpu_online(cpu);
++}
++
++/*
++ * This is how migration works:
++ *
++ * 1) we invoke migration_cpu_stop() on the target CPU using
++ * stop_one_cpu().
++ * 2) stopper starts to run (implicitly forcing the migrated thread
++ * off the CPU)
++ * 3) it checks whether the migrated task is still in the wrong runqueue.
++ * 4) if it's in the wrong runqueue then the migration thread removes
++ * it and puts it into the right queue.
++ * 5) stopper completes and stop_one_cpu() returns and the migration
++ * is done.
++ */
++
++/*
++ * move_queued_task - move a queued task to new rq.
++ *
++ * Returns (locked) new rq. Old rq's lock is released.
++ */
++static struct rq *move_queued_task(struct rq *rq, struct task_struct *p, int
++ new_cpu)
++{
++ int src_cpu;
++
++ lockdep_assert_held(&rq->lock);
++
++ src_cpu = cpu_of(rq);
++ WRITE_ONCE(p->on_rq, TASK_ON_RQ_MIGRATING);
++ dequeue_task(p, rq, 0);
++ set_task_cpu(p, new_cpu);
++ raw_spin_unlock(&rq->lock);
++
++ rq = cpu_rq(new_cpu);
++
++ raw_spin_lock(&rq->lock);
++ WARN_ON_ONCE(task_cpu(p) != new_cpu);
++
++ sched_mm_cid_migrate_to(rq, p, src_cpu);
++
++ sched_task_sanity_check(p, rq);
++ enqueue_task(p, rq, 0);
++ WRITE_ONCE(p->on_rq, TASK_ON_RQ_QUEUED);
++ wakeup_preempt(rq);
++
++ return rq;
++}
++
++struct migration_arg {
++ struct task_struct *task;
++ int dest_cpu;
++};
++
++/*
++ * Move (not current) task off this CPU, onto the destination CPU. We're doing
++ * this because either it can't run here any more (set_cpus_allowed()
++ * away from this CPU, or CPU going down), or because we're
++ * attempting to rebalance this task on exec (sched_exec).
++ *
++ * So we race with normal scheduler movements, but that's OK, as long
++ * as the task is no longer on this CPU.
++ */
++static struct rq *__migrate_task(struct rq *rq, struct task_struct *p, int
++ dest_cpu)
++{
++ /* Affinity changed (again). */
++ if (!is_cpu_allowed(p, dest_cpu))
++ return rq;
++
++ return move_queued_task(rq, p, dest_cpu);
++}
++
++/*
++ * migration_cpu_stop - this will be executed by a highprio stopper thread
++ * and performs thread migration by bumping thread off CPU then
++ * 'pushing' onto another runqueue.
++ */
++static int migration_cpu_stop(void *data)
++{
++ struct migration_arg *arg = data;
++ struct task_struct *p = arg->task;
++ struct rq *rq = this_rq();
++ unsigned long flags;
++
++ /*
++ * The original target CPU might have gone down and we might
++ * be on another CPU but it doesn't matter.
++ */
++ local_irq_save(flags);
++ /*
++ * We need to explicitly wake pending tasks before running
++ * __migrate_task() such that we will not miss enforcing cpus_ptr
++ * during wakeups, see set_cpus_allowed_ptr()'s TASK_WAKING test.
++ */
++ flush_smp_call_function_queue();
++
++ raw_spin_lock(&p->pi_lock);
++ raw_spin_lock(&rq->lock);
++ /*
++ * If task_rq(p) != rq, it cannot be migrated here, because we're
++ * holding rq->lock, if p->on_rq == 0 it cannot get enqueued because
++ * we're holding p->pi_lock.
++ */
++ if (task_rq(p) == rq && task_on_rq_queued(p)) {
++ update_rq_clock(rq);
++ rq = __migrate_task(rq, p, arg->dest_cpu);
++ }
++ raw_spin_unlock(&rq->lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++
++ return 0;
++}
++
++static inline void
++set_cpus_allowed_common(struct task_struct *p, struct affinity_context *ctx)
++{
++ cpumask_copy(&p->cpus_mask, ctx->new_mask);
++ p->nr_cpus_allowed = cpumask_weight(ctx->new_mask);
++
++ /*
++ * Swap in a new user_cpus_ptr if SCA_USER flag set
++ */
++ if (ctx->flags & SCA_USER)
++ swap(p->user_cpus_ptr, ctx->user_mask);
++}
++
++static void
++__do_set_cpus_allowed(struct task_struct *p, struct affinity_context *ctx)
++{
++ lockdep_assert_held(&p->pi_lock);
++ set_cpus_allowed_common(p, ctx);
++}
++
++/*
++ * Used for kthread_bind() and select_fallback_rq(), in both cases the user
++ * affinity (if any) should be destroyed too.
++ */
++void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
++{
++ struct affinity_context ac = {
++ .new_mask = new_mask,
++ .user_mask = NULL,
++ .flags = SCA_USER, /* clear the user requested mask */
++ };
++ union cpumask_rcuhead {
++ cpumask_t cpumask;
++ struct rcu_head rcu;
++ };
++
++ __do_set_cpus_allowed(p, &ac);
++
++ /*
++ * Because this is called with p->pi_lock held, it is not possible
++ * to use kfree() here (when PREEMPT_RT=y), therefore punt to using
++ * kfree_rcu().
++ */
++ kfree_rcu((union cpumask_rcuhead *)ac.user_mask, rcu);
++}
++
++static cpumask_t *alloc_user_cpus_ptr(int node)
++{
++ /*
++ * See do_set_cpus_allowed() above for the rcu_head usage.
++ */
++ int size = max_t(int, cpumask_size(), sizeof(struct rcu_head));
++
++ return kmalloc_node(size, GFP_KERNEL, node);
++}
++
++int dup_user_cpus_ptr(struct task_struct *dst, struct task_struct *src,
++ int node)
++{
++ cpumask_t *user_mask;
++ unsigned long flags;
++
++ /*
++ * Always clear dst->user_cpus_ptr first as their user_cpus_ptr's
++ * may differ by now due to racing.
++ */
++ dst->user_cpus_ptr = NULL;
++
++ /*
++ * This check is racy and losing the race is a valid situation.
++ * It is not worth the extra overhead of taking the pi_lock on
++ * every fork/clone.
++ */
++ if (data_race(!src->user_cpus_ptr))
++ return 0;
++
++ user_mask = alloc_user_cpus_ptr(node);
++ if (!user_mask)
++ return -ENOMEM;
++
++ /*
++ * Use pi_lock to protect content of user_cpus_ptr
++ *
++ * Though unlikely, user_cpus_ptr can be reset to NULL by a concurrent
++ * do_set_cpus_allowed().
++ */
++ raw_spin_lock_irqsave(&src->pi_lock, flags);
++ if (src->user_cpus_ptr) {
++ swap(dst->user_cpus_ptr, user_mask);
++ cpumask_copy(dst->user_cpus_ptr, src->user_cpus_ptr);
++ }
++ raw_spin_unlock_irqrestore(&src->pi_lock, flags);
++
++ if (unlikely(user_mask))
++ kfree(user_mask);
++
++ return 0;
++}
++
++static inline struct cpumask *clear_user_cpus_ptr(struct task_struct *p)
++{
++ struct cpumask *user_mask = NULL;
++
++ swap(p->user_cpus_ptr, user_mask);
++
++ return user_mask;
++}
++
++void release_user_cpus_ptr(struct task_struct *p)
++{
++ kfree(clear_user_cpus_ptr(p));
++}
++
++#endif
++
++/**
++ * task_curr - is this task currently executing on a CPU?
++ * @p: the task in question.
++ *
++ * Return: 1 if the task is currently executing. 0 otherwise.
++ */
++inline int task_curr(const struct task_struct *p)
++{
++ return cpu_curr(task_cpu(p)) == p;
++}
++
++#ifdef CONFIG_SMP
++/***
++ * kick_process - kick a running thread to enter/exit the kernel
++ * @p: the to-be-kicked thread
++ *
++ * Cause a process which is running on another CPU to enter
++ * kernel-mode, without any delay. (to get signals handled.)
++ *
++ * NOTE: this function doesn't have to take the runqueue lock,
++ * because all it wants to ensure is that the remote task enters
++ * the kernel. If the IPI races and the task has been migrated
++ * to another CPU then no harm is done and the purpose has been
++ * achieved as well.
++ */
++void kick_process(struct task_struct *p)
++{
++ guard(preempt)();
++ int cpu = task_cpu(p);
++
++ if ((cpu != smp_processor_id()) && task_curr(p))
++ smp_send_reschedule(cpu);
++}
++EXPORT_SYMBOL_GPL(kick_process);
++
++/*
++ * ->cpus_ptr is protected by both rq->lock and p->pi_lock
++ *
++ * A few notes on cpu_active vs cpu_online:
++ *
++ * - cpu_active must be a subset of cpu_online
++ *
++ * - on CPU-up we allow per-CPU kthreads on the online && !active CPU,
++ * see __set_cpus_allowed_ptr(). At this point the newly online
++ * CPU isn't yet part of the sched domains, and balancing will not
++ * see it.
++ *
++ * - on cpu-down we clear cpu_active() to mask the sched domains and
++ * avoid the load balancer to place new tasks on the to be removed
++ * CPU. Existing tasks will remain running there and will be taken
++ * off.
++ *
++ * This means that fallback selection must not select !active CPUs.
++ * And can assume that any active CPU must be online. Conversely
++ * select_task_rq() below may allow selection of !active CPUs in order
++ * to satisfy the above rules.
++ */
++static int select_fallback_rq(int cpu, struct task_struct *p)
++{
++ int nid = cpu_to_node(cpu);
++ const struct cpumask *nodemask = NULL;
++ enum { cpuset, possible, fail } state = cpuset;
++ int dest_cpu;
++
++ /*
++ * If the node that the CPU is on has been offlined, cpu_to_node()
++ * will return -1. There is no CPU on the node, and we should
++ * select the CPU on the other node.
++ */
++ if (nid != -1) {
++ nodemask = cpumask_of_node(nid);
++
++ /* Look for allowed, online CPU in same node. */
++ for_each_cpu(dest_cpu, nodemask) {
++ if (is_cpu_allowed(p, dest_cpu))
++ return dest_cpu;
++ }
++ }
++
++ for (;;) {
++ /* Any allowed, online CPU? */
++ for_each_cpu(dest_cpu, p->cpus_ptr) {
++ if (!is_cpu_allowed(p, dest_cpu))
++ continue;
++ goto out;
++ }
++
++ /* No more Mr. Nice Guy. */
++ switch (state) {
++ case cpuset:
++ if (cpuset_cpus_allowed_fallback(p)) {
++ state = possible;
++ break;
++ }
++ fallthrough;
++ case possible:
++ /*
++ * XXX When called from select_task_rq() we only
++ * hold p->pi_lock and again violate locking order.
++ *
++ * More yuck to audit.
++ */
++ do_set_cpus_allowed(p, task_cpu_possible_mask(p));
++ state = fail;
++ break;
++
++ case fail:
++ BUG();
++ break;
++ }
++ }
++
++out:
++ if (state != cpuset) {
++ /*
++ * Don't tell them about moving exiting tasks or
++ * kernel threads (both mm NULL), since they never
++ * leave kernel.
++ */
++ if (p->mm && printk_ratelimit()) {
++ printk_deferred("process %d (%s) no longer affine to cpu%d\n",
++ task_pid_nr(p), p->comm, cpu);
++ }
++ }
++
++ return dest_cpu;
++}
++
++static inline void
++sched_preempt_mask_flush(cpumask_t *mask, int prio)
++{
++ int cpu;
++
++ cpumask_copy(mask, sched_idle_mask);
++
++ for_each_clear_bit(cpu, cpumask_bits(mask), nr_cpumask_bits) {
++ if (prio < cpu_rq(cpu)->prio)
++ cpumask_set_cpu(cpu, mask);
++ }
++}
++
++static inline int
++preempt_mask_check(struct task_struct *p, cpumask_t *allow_mask, cpumask_t *preempt_mask)
++{
++ int task_prio = task_sched_prio(p);
++ cpumask_t *mask = sched_preempt_mask + SCHED_QUEUE_BITS - 1 - task_prio;
++ int pr = atomic_read(&sched_prio_record);
++
++ if (pr != task_prio) {
++ sched_preempt_mask_flush(mask, task_prio);
++ atomic_set(&sched_prio_record, task_prio);
++ }
++
++ return cpumask_and(preempt_mask, allow_mask, mask);
++}
++
++static inline int select_task_rq(struct task_struct *p)
++{
++ cpumask_t allow_mask, mask;
++
++ if (unlikely(!cpumask_and(&allow_mask, p->cpus_ptr, cpu_active_mask)))
++ return select_fallback_rq(task_cpu(p), p);
++
++ if (
++#ifdef CONFIG_SCHED_SMT
++ cpumask_and(&mask, &allow_mask, &sched_sg_idle_mask) ||
++#endif
++ cpumask_and(&mask, &allow_mask, sched_idle_mask) ||
++ preempt_mask_check(p, &allow_mask, &mask))
++ return best_mask_cpu(task_cpu(p), &mask);
++
++ return best_mask_cpu(task_cpu(p), &allow_mask);
++}
++
++void sched_set_stop_task(int cpu, struct task_struct *stop)
++{
++ static struct lock_class_key stop_pi_lock;
++ struct sched_param stop_param = { .sched_priority = STOP_PRIO };
++ struct sched_param start_param = { .sched_priority = 0 };
++ struct task_struct *old_stop = cpu_rq(cpu)->stop;
++
++ if (stop) {
++ /*
++ * Make it appear like a SCHED_FIFO task, its something
++ * userspace knows about and won't get confused about.
++ *
++ * Also, it will make PI more or less work without too
++ * much confusion -- but then, stop work should not
++ * rely on PI working anyway.
++ */
++ sched_setscheduler_nocheck(stop, SCHED_FIFO, &stop_param);
++
++ /*
++ * The PI code calls rt_mutex_setprio() with ->pi_lock held to
++ * adjust the effective priority of a task. As a result,
++ * rt_mutex_setprio() can trigger (RT) balancing operations,
++ * which can then trigger wakeups of the stop thread to push
++ * around the current task.
++ *
++ * The stop task itself will never be part of the PI-chain, it
++ * never blocks, therefore that ->pi_lock recursion is safe.
++ * Tell lockdep about this by placing the stop->pi_lock in its
++ * own class.
++ */
++ lockdep_set_class(&stop->pi_lock, &stop_pi_lock);
++ }
++
++ cpu_rq(cpu)->stop = stop;
++
++ if (old_stop) {
++ /*
++ * Reset it back to a normal scheduling policy so that
++ * it can die in pieces.
++ */
++ sched_setscheduler_nocheck(old_stop, SCHED_NORMAL, &start_param);
++ }
++}
++
++static int affine_move_task(struct rq *rq, struct task_struct *p, int dest_cpu,
++ raw_spinlock_t *lock, unsigned long irq_flags)
++ __releases(rq->lock)
++ __releases(p->pi_lock)
++{
++ /* Can the task run on the task's current CPU? If so, we're done */
++ if (!cpumask_test_cpu(task_cpu(p), &p->cpus_mask)) {
++ if (p->migration_disabled) {
++ if (likely(p->cpus_ptr != &p->cpus_mask))
++ __do_set_cpus_ptr(p, &p->cpus_mask);
++ p->migration_disabled = 0;
++ p->migration_flags |= MDF_FORCE_ENABLED;
++ /* When p is migrate_disabled, rq->lock should be held */
++ rq->nr_pinned--;
++ }
++
++ if (task_on_cpu(p) || READ_ONCE(p->__state) == TASK_WAKING) {
++ struct migration_arg arg = { p, dest_cpu };
++
++ /* Need help from migration thread: drop lock and wait. */
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
++ stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg);
++ return 0;
++ }
++ if (task_on_rq_queued(p)) {
++ /*
++ * OK, since we're going to drop the lock immediately
++ * afterwards anyway.
++ */
++ update_rq_clock(rq);
++ rq = move_queued_task(rq, p, dest_cpu);
++ lock = &rq->lock;
++ }
++ }
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
++ return 0;
++}
++
++static int __set_cpus_allowed_ptr_locked(struct task_struct *p,
++ struct affinity_context *ctx,
++ struct rq *rq,
++ raw_spinlock_t *lock,
++ unsigned long irq_flags)
++{
++ const struct cpumask *cpu_allowed_mask = task_cpu_possible_mask(p);
++ const struct cpumask *cpu_valid_mask = cpu_active_mask;
++ bool kthread = p->flags & PF_KTHREAD;
++ int dest_cpu;
++ int ret = 0;
++
++ if (kthread || is_migration_disabled(p)) {
++ /*
++ * Kernel threads are allowed on online && !active CPUs,
++ * however, during cpu-hot-unplug, even these might get pushed
++ * away if not KTHREAD_IS_PER_CPU.
++ *
++ * Specifically, migration_disabled() tasks must not fail the
++ * cpumask_any_and_distribute() pick below, esp. so on
++ * SCA_MIGRATE_ENABLE, otherwise we'll not call
++ * set_cpus_allowed_common() and actually reset p->cpus_ptr.
++ */
++ cpu_valid_mask = cpu_online_mask;
++ }
++
++ if (!kthread && !cpumask_subset(ctx->new_mask, cpu_allowed_mask)) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ /*
++ * Must re-check here, to close a race against __kthread_bind(),
++ * sched_setaffinity() is not guaranteed to observe the flag.
++ */
++ if ((ctx->flags & SCA_CHECK) && (p->flags & PF_NO_SETAFFINITY)) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ if (cpumask_equal(&p->cpus_mask, ctx->new_mask))
++ goto out;
++
++ dest_cpu = cpumask_any_and(cpu_valid_mask, ctx->new_mask);
++ if (dest_cpu >= nr_cpu_ids) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ __do_set_cpus_allowed(p, ctx);
++
++ return affine_move_task(rq, p, dest_cpu, lock, irq_flags);
++
++out:
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
++
++ return ret;
++}
++
++/*
++ * Change a given task's CPU affinity. Migrate the thread to a
++ * is removed from the allowed bitmask.
++ *
++ * NOTE: the caller must have a valid reference to the task, the
++ * task must not exit() & deallocate itself prematurely. The
++ * call is not atomic; no spinlocks may be held.
++ */
++static int __set_cpus_allowed_ptr(struct task_struct *p,
++ struct affinity_context *ctx)
++{
++ unsigned long irq_flags;
++ struct rq *rq;
++ raw_spinlock_t *lock;
++
++ raw_spin_lock_irqsave(&p->pi_lock, irq_flags);
++ rq = __task_access_lock(p, &lock);
++ /*
++ * Masking should be skipped if SCA_USER or any of the SCA_MIGRATE_*
++ * flags are set.
++ */
++ if (p->user_cpus_ptr &&
++ !(ctx->flags & SCA_USER) &&
++ cpumask_and(rq->scratch_mask, ctx->new_mask, p->user_cpus_ptr))
++ ctx->new_mask = rq->scratch_mask;
++
++
++ return __set_cpus_allowed_ptr_locked(p, ctx, rq, lock, irq_flags);
++}
++
++int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
++{
++ struct affinity_context ac = {
++ .new_mask = new_mask,
++ .flags = 0,
++ };
++
++ return __set_cpus_allowed_ptr(p, &ac);
++}
++EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr);
++
++/*
++ * Change a given task's CPU affinity to the intersection of its current
++ * affinity mask and @subset_mask, writing the resulting mask to @new_mask.
++ * If user_cpus_ptr is defined, use it as the basis for restricting CPU
++ * affinity or use cpu_online_mask instead.
++ *
++ * If the resulting mask is empty, leave the affinity unchanged and return
++ * -EINVAL.
++ */
++static int restrict_cpus_allowed_ptr(struct task_struct *p,
++ struct cpumask *new_mask,
++ const struct cpumask *subset_mask)
++{
++ struct affinity_context ac = {
++ .new_mask = new_mask,
++ .flags = 0,
++ };
++ unsigned long irq_flags;
++ raw_spinlock_t *lock;
++ struct rq *rq;
++ int err;
++
++ raw_spin_lock_irqsave(&p->pi_lock, irq_flags);
++ rq = __task_access_lock(p, &lock);
++
++ if (!cpumask_and(new_mask, task_user_cpus(p), subset_mask)) {
++ err = -EINVAL;
++ goto err_unlock;
++ }
++
++ return __set_cpus_allowed_ptr_locked(p, &ac, rq, lock, irq_flags);
++
++err_unlock:
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
++ return err;
++}
++
++/*
++ * Restrict the CPU affinity of task @p so that it is a subset of
++ * task_cpu_possible_mask() and point @p->user_cpus_ptr to a copy of the
++ * old affinity mask. If the resulting mask is empty, we warn and walk
++ * up the cpuset hierarchy until we find a suitable mask.
++ */
++void force_compatible_cpus_allowed_ptr(struct task_struct *p)
++{
++ cpumask_var_t new_mask;
++ const struct cpumask *override_mask = task_cpu_possible_mask(p);
++
++ alloc_cpumask_var(&new_mask, GFP_KERNEL);
++
++ /*
++ * __migrate_task() can fail silently in the face of concurrent
++ * offlining of the chosen destination CPU, so take the hotplug
++ * lock to ensure that the migration succeeds.
++ */
++ cpus_read_lock();
++ if (!cpumask_available(new_mask))
++ goto out_set_mask;
++
++ if (!restrict_cpus_allowed_ptr(p, new_mask, override_mask))
++ goto out_free_mask;
++
++ /*
++ * We failed to find a valid subset of the affinity mask for the
++ * task, so override it based on its cpuset hierarchy.
++ */
++ cpuset_cpus_allowed(p, new_mask);
++ override_mask = new_mask;
++
++out_set_mask:
++ if (printk_ratelimit()) {
++ printk_deferred("Overriding affinity for process %d (%s) to CPUs %*pbl\n",
++ task_pid_nr(p), p->comm,
++ cpumask_pr_args(override_mask));
++ }
++
++ WARN_ON(set_cpus_allowed_ptr(p, override_mask));
++out_free_mask:
++ cpus_read_unlock();
++ free_cpumask_var(new_mask);
++}
++
++static int
++__sched_setaffinity(struct task_struct *p, struct affinity_context *ctx);
++
++/*
++ * Restore the affinity of a task @p which was previously restricted by a
++ * call to force_compatible_cpus_allowed_ptr().
++ *
++ * It is the caller's responsibility to serialise this with any calls to
++ * force_compatible_cpus_allowed_ptr(@p).
++ */
++void relax_compatible_cpus_allowed_ptr(struct task_struct *p)
++{
++ struct affinity_context ac = {
++ .new_mask = task_user_cpus(p),
++ .flags = 0,
++ };
++ int ret;
++
++ /*
++ * Try to restore the old affinity mask with __sched_setaffinity().
++ * Cpuset masking will be done there too.
++ */
++ ret = __sched_setaffinity(p, &ac);
++ WARN_ON_ONCE(ret);
++}
++
++#else /* CONFIG_SMP */
++
++static inline int select_task_rq(struct task_struct *p)
++{
++ return 0;
++}
++
++static inline int
++__set_cpus_allowed_ptr(struct task_struct *p,
++ struct affinity_context *ctx)
++{
++ return set_cpus_allowed_ptr(p, ctx->new_mask);
++}
++
++static inline bool rq_has_pinned_tasks(struct rq *rq)
++{
++ return false;
++}
++
++static inline cpumask_t *alloc_user_cpus_ptr(int node)
++{
++ return NULL;
++}
++
++#endif /* !CONFIG_SMP */
++
++static void
++ttwu_stat(struct task_struct *p, int cpu, int wake_flags)
++{
++ struct rq *rq;
++
++ if (!schedstat_enabled())
++ return;
++
++ rq = this_rq();
++
++#ifdef CONFIG_SMP
++ if (cpu == rq->cpu) {
++ __schedstat_inc(rq->ttwu_local);
++ __schedstat_inc(p->stats.nr_wakeups_local);
++ } else {
++ /** Alt schedule FW ToDo:
++ * How to do ttwu_wake_remote
++ */
++ }
++#endif /* CONFIG_SMP */
++
++ __schedstat_inc(rq->ttwu_count);
++ __schedstat_inc(p->stats.nr_wakeups);
++}
++
++/*
++ * Mark the task runnable.
++ */
++static inline void ttwu_do_wakeup(struct task_struct *p)
++{
++ WRITE_ONCE(p->__state, TASK_RUNNING);
++ trace_sched_wakeup(p);
++}
++
++static inline void
++ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags)
++{
++ if (p->sched_contributes_to_load)
++ rq->nr_uninterruptible--;
++
++ if (
++#ifdef CONFIG_SMP
++ !(wake_flags & WF_MIGRATED) &&
++#endif
++ p->in_iowait) {
++ delayacct_blkio_end(p);
++ atomic_dec(&task_rq(p)->nr_iowait);
++ }
++
++ activate_task(p, rq);
++ wakeup_preempt(rq);
++
++ ttwu_do_wakeup(p);
++}
++
++/*
++ * Consider @p being inside a wait loop:
++ *
++ * for (;;) {
++ * set_current_state(TASK_UNINTERRUPTIBLE);
++ *
++ * if (CONDITION)
++ * break;
++ *
++ * schedule();
++ * }
++ * __set_current_state(TASK_RUNNING);
++ *
++ * between set_current_state() and schedule(). In this case @p is still
++ * runnable, so all that needs doing is change p->state back to TASK_RUNNING in
++ * an atomic manner.
++ *
++ * By taking task_rq(p)->lock we serialize against schedule(), if @p->on_rq
++ * then schedule() must still happen and p->state can be changed to
++ * TASK_RUNNING. Otherwise we lost the race, schedule() has happened, and we
++ * need to do a full wakeup with enqueue.
++ *
++ * Returns: %true when the wakeup is done,
++ * %false otherwise.
++ */
++static int ttwu_runnable(struct task_struct *p, int wake_flags)
++{
++ struct rq *rq;
++ raw_spinlock_t *lock;
++ int ret = 0;
++
++ rq = __task_access_lock(p, &lock);
++ if (task_on_rq_queued(p)) {
++ if (!task_on_cpu(p)) {
++ /*
++ * When on_rq && !on_cpu the task is preempted, see if
++ * it should preempt the task that is current now.
++ */
++ update_rq_clock(rq);
++ wakeup_preempt(rq);
++ }
++ ttwu_do_wakeup(p);
++ ret = 1;
++ }
++ __task_access_unlock(p, lock);
++
++ return ret;
++}
++
++#ifdef CONFIG_SMP
++void sched_ttwu_pending(void *arg)
++{
++ struct llist_node *llist = arg;
++ struct rq *rq = this_rq();
++ struct task_struct *p, *t;
++ struct rq_flags rf;
++
++ if (!llist)
++ return;
++
++ rq_lock_irqsave(rq, &rf);
++ update_rq_clock(rq);
++
++ llist_for_each_entry_safe(p, t, llist, wake_entry.llist) {
++ if (WARN_ON_ONCE(p->on_cpu))
++ smp_cond_load_acquire(&p->on_cpu, !VAL);
++
++ if (WARN_ON_ONCE(task_cpu(p) != cpu_of(rq)))
++ set_task_cpu(p, cpu_of(rq));
++
++ ttwu_do_activate(rq, p, p->sched_remote_wakeup ? WF_MIGRATED : 0);
++ }
++
++ /*
++ * Must be after enqueueing at least once task such that
++ * idle_cpu() does not observe a false-negative -- if it does,
++ * it is possible for select_idle_siblings() to stack a number
++ * of tasks on this CPU during that window.
++ *
++ * It is ok to clear ttwu_pending when another task pending.
++ * We will receive IPI after local irq enabled and then enqueue it.
++ * Since now nr_running > 0, idle_cpu() will always get correct result.
++ */
++ WRITE_ONCE(rq->ttwu_pending, 0);
++ rq_unlock_irqrestore(rq, &rf);
++}
++
++/*
++ * Prepare the scene for sending an IPI for a remote smp_call
++ *
++ * Returns true if the caller can proceed with sending the IPI.
++ * Returns false otherwise.
++ */
++bool call_function_single_prep_ipi(int cpu)
++{
++ if (set_nr_if_polling(cpu_rq(cpu)->idle)) {
++ trace_sched_wake_idle_without_ipi(cpu);
++ return false;
++ }
++
++ return true;
++}
++
++/*
++ * Queue a task on the target CPUs wake_list and wake the CPU via IPI if
++ * necessary. The wakee CPU on receipt of the IPI will queue the task
++ * via sched_ttwu_wakeup() for activation so the wakee incurs the cost
++ * of the wakeup instead of the waker.
++ */
++static void __ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ p->sched_remote_wakeup = !!(wake_flags & WF_MIGRATED);
++
++ WRITE_ONCE(rq->ttwu_pending, 1);
++ __smp_call_single_queue(cpu, &p->wake_entry.llist);
++}
++
++static inline bool ttwu_queue_cond(struct task_struct *p, int cpu)
++{
++ /*
++ * Do not complicate things with the async wake_list while the CPU is
++ * in hotplug state.
++ */
++ if (!cpu_active(cpu))
++ return false;
++
++ /* Ensure the task will still be allowed to run on the CPU. */
++ if (!cpumask_test_cpu(cpu, p->cpus_ptr))
++ return false;
++
++ /*
++ * If the CPU does not share cache, then queue the task on the
++ * remote rqs wakelist to avoid accessing remote data.
++ */
++ if (!cpus_share_cache(smp_processor_id(), cpu))
++ return true;
++
++ if (cpu == smp_processor_id())
++ return false;
++
++ /*
++ * If the wakee cpu is idle, or the task is descheduling and the
++ * only running task on the CPU, then use the wakelist to offload
++ * the task activation to the idle (or soon-to-be-idle) CPU as
++ * the current CPU is likely busy. nr_running is checked to
++ * avoid unnecessary task stacking.
++ *
++ * Note that we can only get here with (wakee) p->on_rq=0,
++ * p->on_cpu can be whatever, we've done the dequeue, so
++ * the wakee has been accounted out of ->nr_running.
++ */
++ if (!cpu_rq(cpu)->nr_running)
++ return true;
++
++ return false;
++}
++
++static bool ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
++{
++ if (__is_defined(ALT_SCHED_TTWU_QUEUE) && ttwu_queue_cond(p, cpu)) {
++ sched_clock_cpu(cpu); /* Sync clocks across CPUs */
++ __ttwu_queue_wakelist(p, cpu, wake_flags);
++ return true;
++ }
++
++ return false;
++}
++
++void wake_up_if_idle(int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ guard(rcu)();
++ if (is_idle_task(rcu_dereference(rq->curr))) {
++ guard(raw_spinlock_irqsave)(&rq->lock);
++ if (is_idle_task(rq->curr))
++ resched_curr(rq);
++ }
++}
++
++bool cpus_share_cache(int this_cpu, int that_cpu)
++{
++ if (this_cpu == that_cpu)
++ return true;
++
++ return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu);
++}
++#else /* !CONFIG_SMP */
++
++static inline bool ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
++{
++ return false;
++}
++
++#endif /* CONFIG_SMP */
++
++static inline void ttwu_queue(struct task_struct *p, int cpu, int wake_flags)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ if (ttwu_queue_wakelist(p, cpu, wake_flags))
++ return;
++
++ raw_spin_lock(&rq->lock);
++ update_rq_clock(rq);
++ ttwu_do_activate(rq, p, wake_flags);
++ raw_spin_unlock(&rq->lock);
++}
++
++/*
++ * Invoked from try_to_wake_up() to check whether the task can be woken up.
++ *
++ * The caller holds p::pi_lock if p != current or has preemption
++ * disabled when p == current.
++ *
++ * The rules of saved_state:
++ *
++ * The related locking code always holds p::pi_lock when updating
++ * p::saved_state, which means the code is fully serialized in both cases.
++ *
++ * For PREEMPT_RT, the lock wait and lock wakeups happen via TASK_RTLOCK_WAIT.
++ * No other bits set. This allows to distinguish all wakeup scenarios.
++ *
++ * For FREEZER, the wakeup happens via TASK_FROZEN. No other bits set. This
++ * allows us to prevent early wakeup of tasks before they can be run on
++ * asymmetric ISA architectures (eg ARMv9).
++ */
++static __always_inline
++bool ttwu_state_match(struct task_struct *p, unsigned int state, int *success)
++{
++ int match;
++
++ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT)) {
++ WARN_ON_ONCE((state & TASK_RTLOCK_WAIT) &&
++ state != TASK_RTLOCK_WAIT);
++ }
++
++ *success = !!(match = __task_state_match(p, state));
++
++ /*
++ * Saved state preserves the task state across blocking on
++ * an RT lock or TASK_FREEZABLE tasks. If the state matches,
++ * set p::saved_state to TASK_RUNNING, but do not wake the task
++ * because it waits for a lock wakeup or __thaw_task(). Also
++ * indicate success because from the regular waker's point of
++ * view this has succeeded.
++ *
++ * After acquiring the lock the task will restore p::__state
++ * from p::saved_state which ensures that the regular
++ * wakeup is not lost. The restore will also set
++ * p::saved_state to TASK_RUNNING so any further tests will
++ * not result in false positives vs. @success
++ */
++ if (match < 0)
++ p->saved_state = TASK_RUNNING;
++
++ return match > 0;
++}
++
++/*
++ * Notes on Program-Order guarantees on SMP systems.
++ *
++ * MIGRATION
++ *
++ * The basic program-order guarantee on SMP systems is that when a task [t]
++ * migrates, all its activity on its old CPU [c0] happens-before any subsequent
++ * execution on its new CPU [c1].
++ *
++ * For migration (of runnable tasks) this is provided by the following means:
++ *
++ * A) UNLOCK of the rq(c0)->lock scheduling out task t
++ * B) migration for t is required to synchronize *both* rq(c0)->lock and
++ * rq(c1)->lock (if not at the same time, then in that order).
++ * C) LOCK of the rq(c1)->lock scheduling in task
++ *
++ * Transitivity guarantees that B happens after A and C after B.
++ * Note: we only require RCpc transitivity.
++ * Note: the CPU doing B need not be c0 or c1
++ *
++ * Example:
++ *
++ * CPU0 CPU1 CPU2
++ *
++ * LOCK rq(0)->lock
++ * sched-out X
++ * sched-in Y
++ * UNLOCK rq(0)->lock
++ *
++ * LOCK rq(0)->lock // orders against CPU0
++ * dequeue X
++ * UNLOCK rq(0)->lock
++ *
++ * LOCK rq(1)->lock
++ * enqueue X
++ * UNLOCK rq(1)->lock
++ *
++ * LOCK rq(1)->lock // orders against CPU2
++ * sched-out Z
++ * sched-in X
++ * UNLOCK rq(1)->lock
++ *
++ *
++ * BLOCKING -- aka. SLEEP + WAKEUP
++ *
++ * For blocking we (obviously) need to provide the same guarantee as for
++ * migration. However the means are completely different as there is no lock
++ * chain to provide order. Instead we do:
++ *
++ * 1) smp_store_release(X->on_cpu, 0) -- finish_task()
++ * 2) smp_cond_load_acquire(!X->on_cpu) -- try_to_wake_up()
++ *
++ * Example:
++ *
++ * CPU0 (schedule) CPU1 (try_to_wake_up) CPU2 (schedule)
++ *
++ * LOCK rq(0)->lock LOCK X->pi_lock
++ * dequeue X
++ * sched-out X
++ * smp_store_release(X->on_cpu, 0);
++ *
++ * smp_cond_load_acquire(&X->on_cpu, !VAL);
++ * X->state = WAKING
++ * set_task_cpu(X,2)
++ *
++ * LOCK rq(2)->lock
++ * enqueue X
++ * X->state = RUNNING
++ * UNLOCK rq(2)->lock
++ *
++ * LOCK rq(2)->lock // orders against CPU1
++ * sched-out Z
++ * sched-in X
++ * UNLOCK rq(2)->lock
++ *
++ * UNLOCK X->pi_lock
++ * UNLOCK rq(0)->lock
++ *
++ *
++ * However; for wakeups there is a second guarantee we must provide, namely we
++ * must observe the state that lead to our wakeup. That is, not only must our
++ * task observe its own prior state, it must also observe the stores prior to
++ * its wakeup.
++ *
++ * This means that any means of doing remote wakeups must order the CPU doing
++ * the wakeup against the CPU the task is going to end up running on. This,
++ * however, is already required for the regular Program-Order guarantee above,
++ * since the waking CPU is the one issueing the ACQUIRE (smp_cond_load_acquire).
++ *
++ */
++
++/**
++ * try_to_wake_up - wake up a thread
++ * @p: the thread to be awakened
++ * @state: the mask of task states that can be woken
++ * @wake_flags: wake modifier flags (WF_*)
++ *
++ * Conceptually does:
++ *
++ * If (@state & @p->state) @p->state = TASK_RUNNING.
++ *
++ * If the task was not queued/runnable, also place it back on a runqueue.
++ *
++ * This function is atomic against schedule() which would dequeue the task.
++ *
++ * It issues a full memory barrier before accessing @p->state, see the comment
++ * with set_current_state().
++ *
++ * Uses p->pi_lock to serialize against concurrent wake-ups.
++ *
++ * Relies on p->pi_lock stabilizing:
++ * - p->sched_class
++ * - p->cpus_ptr
++ * - p->sched_task_group
++ * in order to do migration, see its use of select_task_rq()/set_task_cpu().
++ *
++ * Tries really hard to only take one task_rq(p)->lock for performance.
++ * Takes rq->lock in:
++ * - ttwu_runnable() -- old rq, unavoidable, see comment there;
++ * - ttwu_queue() -- new rq, for enqueue of the task;
++ * - psi_ttwu_dequeue() -- much sadness :-( accounting will kill us.
++ *
++ * As a consequence we race really badly with just about everything. See the
++ * many memory barriers and their comments for details.
++ *
++ * Return: %true if @p->state changes (an actual wakeup was done),
++ * %false otherwise.
++ */
++int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
++{
++ guard(preempt)();
++ int cpu, success = 0;
++
++ if (p == current) {
++ /*
++ * We're waking current, this means 'p->on_rq' and 'task_cpu(p)
++ * == smp_processor_id()'. Together this means we can special
++ * case the whole 'p->on_rq && ttwu_runnable()' case below
++ * without taking any locks.
++ *
++ * In particular:
++ * - we rely on Program-Order guarantees for all the ordering,
++ * - we're serialized against set_special_state() by virtue of
++ * it disabling IRQs (this allows not taking ->pi_lock).
++ */
++ if (!ttwu_state_match(p, state, &success))
++ goto out;
++
++ trace_sched_waking(p);
++ ttwu_do_wakeup(p);
++ goto out;
++ }
++
++ /*
++ * If we are going to wake up a thread waiting for CONDITION we
++ * need to ensure that CONDITION=1 done by the caller can not be
++ * reordered with p->state check below. This pairs with smp_store_mb()
++ * in set_current_state() that the waiting thread does.
++ */
++ scoped_guard (raw_spinlock_irqsave, &p->pi_lock) {
++ smp_mb__after_spinlock();
++ if (!ttwu_state_match(p, state, &success))
++ break;
++
++ trace_sched_waking(p);
++
++ /*
++ * Ensure we load p->on_rq _after_ p->state, otherwise it would
++ * be possible to, falsely, observe p->on_rq == 0 and get stuck
++ * in smp_cond_load_acquire() below.
++ *
++ * sched_ttwu_pending() try_to_wake_up()
++ * STORE p->on_rq = 1 LOAD p->state
++ * UNLOCK rq->lock
++ *
++ * __schedule() (switch to task 'p')
++ * LOCK rq->lock smp_rmb();
++ * smp_mb__after_spinlock();
++ * UNLOCK rq->lock
++ *
++ * [task p]
++ * STORE p->state = UNINTERRUPTIBLE LOAD p->on_rq
++ *
++ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in
++ * __schedule(). See the comment for smp_mb__after_spinlock().
++ *
++ * A similar smp_rmb() lives in __task_needs_rq_lock().
++ */
++ smp_rmb();
++ if (READ_ONCE(p->on_rq) && ttwu_runnable(p, wake_flags))
++ break;
++
++#ifdef CONFIG_SMP
++ /*
++ * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be
++ * possible to, falsely, observe p->on_cpu == 0.
++ *
++ * One must be running (->on_cpu == 1) in order to remove oneself
++ * from the runqueue.
++ *
++ * __schedule() (switch to task 'p') try_to_wake_up()
++ * STORE p->on_cpu = 1 LOAD p->on_rq
++ * UNLOCK rq->lock
++ *
++ * __schedule() (put 'p' to sleep)
++ * LOCK rq->lock smp_rmb();
++ * smp_mb__after_spinlock();
++ * STORE p->on_rq = 0 LOAD p->on_cpu
++ *
++ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in
++ * __schedule(). See the comment for smp_mb__after_spinlock().
++ *
++ * Form a control-dep-acquire with p->on_rq == 0 above, to ensure
++ * schedule()'s deactivate_task() has 'happened' and p will no longer
++ * care about it's own p->state. See the comment in __schedule().
++ */
++ smp_acquire__after_ctrl_dep();
++
++ /*
++ * We're doing the wakeup (@success == 1), they did a dequeue (p->on_rq
++ * == 0), which means we need to do an enqueue, change p->state to
++ * TASK_WAKING such that we can unlock p->pi_lock before doing the
++ * enqueue, such as ttwu_queue_wakelist().
++ */
++ WRITE_ONCE(p->__state, TASK_WAKING);
++
++ /*
++ * If the owning (remote) CPU is still in the middle of schedule() with
++ * this task as prev, considering queueing p on the remote CPUs wake_list
++ * which potentially sends an IPI instead of spinning on p->on_cpu to
++ * let the waker make forward progress. This is safe because IRQs are
++ * disabled and the IPI will deliver after on_cpu is cleared.
++ *
++ * Ensure we load task_cpu(p) after p->on_cpu:
++ *
++ * set_task_cpu(p, cpu);
++ * STORE p->cpu = @cpu
++ * __schedule() (switch to task 'p')
++ * LOCK rq->lock
++ * smp_mb__after_spin_lock() smp_cond_load_acquire(&p->on_cpu)
++ * STORE p->on_cpu = 1 LOAD p->cpu
++ *
++ * to ensure we observe the correct CPU on which the task is currently
++ * scheduling.
++ */
++ if (smp_load_acquire(&p->on_cpu) &&
++ ttwu_queue_wakelist(p, task_cpu(p), wake_flags))
++ break;
++
++ /*
++ * If the owning (remote) CPU is still in the middle of schedule() with
++ * this task as prev, wait until it's done referencing the task.
++ *
++ * Pairs with the smp_store_release() in finish_task().
++ *
++ * This ensures that tasks getting woken will be fully ordered against
++ * their previous state and preserve Program Order.
++ */
++ smp_cond_load_acquire(&p->on_cpu, !VAL);
++
++ sched_task_ttwu(p);
++
++ if ((wake_flags & WF_CURRENT_CPU) &&
++ cpumask_test_cpu(smp_processor_id(), p->cpus_ptr))
++ cpu = smp_processor_id();
++ else
++ cpu = select_task_rq(p);
++
++ if (cpu != task_cpu(p)) {
++ if (p->in_iowait) {
++ delayacct_blkio_end(p);
++ atomic_dec(&task_rq(p)->nr_iowait);
++ }
++
++ wake_flags |= WF_MIGRATED;
++ set_task_cpu(p, cpu);
++ }
++#else
++ sched_task_ttwu(p);
++
++ cpu = task_cpu(p);
++#endif /* CONFIG_SMP */
++
++ ttwu_queue(p, cpu, wake_flags);
++ }
++out:
++ if (success)
++ ttwu_stat(p, task_cpu(p), wake_flags);
++
++ return success;
++}
++
++static bool __task_needs_rq_lock(struct task_struct *p)
++{
++ unsigned int state = READ_ONCE(p->__state);
++
++ /*
++ * Since pi->lock blocks try_to_wake_up(), we don't need rq->lock when
++ * the task is blocked. Make sure to check @state since ttwu() can drop
++ * locks at the end, see ttwu_queue_wakelist().
++ */
++ if (state == TASK_RUNNING || state == TASK_WAKING)
++ return true;
++
++ /*
++ * Ensure we load p->on_rq after p->__state, otherwise it would be
++ * possible to, falsely, observe p->on_rq == 0.
++ *
++ * See try_to_wake_up() for a longer comment.
++ */
++ smp_rmb();
++ if (p->on_rq)
++ return true;
++
++#ifdef CONFIG_SMP
++ /*
++ * Ensure the task has finished __schedule() and will not be referenced
++ * anymore. Again, see try_to_wake_up() for a longer comment.
++ */
++ smp_rmb();
++ smp_cond_load_acquire(&p->on_cpu, !VAL);
++#endif
++
++ return false;
++}
++
++/**
++ * task_call_func - Invoke a function on task in fixed state
++ * @p: Process for which the function is to be invoked, can be @current.
++ * @func: Function to invoke.
++ * @arg: Argument to function.
++ *
++ * Fix the task in it's current state by avoiding wakeups and or rq operations
++ * and call @func(@arg) on it. This function can use ->on_rq and task_curr()
++ * to work out what the state is, if required. Given that @func can be invoked
++ * with a runqueue lock held, it had better be quite lightweight.
++ *
++ * Returns:
++ * Whatever @func returns
++ */
++int task_call_func(struct task_struct *p, task_call_f func, void *arg)
++{
++ struct rq *rq = NULL;
++ struct rq_flags rf;
++ int ret;
++
++ raw_spin_lock_irqsave(&p->pi_lock, rf.flags);
++
++ if (__task_needs_rq_lock(p))
++ rq = __task_rq_lock(p, &rf);
++
++ /*
++ * At this point the task is pinned; either:
++ * - blocked and we're holding off wakeups (pi->lock)
++ * - woken, and we're holding off enqueue (rq->lock)
++ * - queued, and we're holding off schedule (rq->lock)
++ * - running, and we're holding off de-schedule (rq->lock)
++ *
++ * The called function (@func) can use: task_curr(), p->on_rq and
++ * p->__state to differentiate between these states.
++ */
++ ret = func(p, arg);
++
++ if (rq)
++ __task_rq_unlock(rq, &rf);
++
++ raw_spin_unlock_irqrestore(&p->pi_lock, rf.flags);
++ return ret;
++}
++
++/**
++ * cpu_curr_snapshot - Return a snapshot of the currently running task
++ * @cpu: The CPU on which to snapshot the task.
++ *
++ * Returns the task_struct pointer of the task "currently" running on
++ * the specified CPU. If the same task is running on that CPU throughout,
++ * the return value will be a pointer to that task's task_struct structure.
++ * If the CPU did any context switches even vaguely concurrently with the
++ * execution of this function, the return value will be a pointer to the
++ * task_struct structure of a randomly chosen task that was running on
++ * that CPU somewhere around the time that this function was executing.
++ *
++ * If the specified CPU was offline, the return value is whatever it
++ * is, perhaps a pointer to the task_struct structure of that CPU's idle
++ * task, but there is no guarantee. Callers wishing a useful return
++ * value must take some action to ensure that the specified CPU remains
++ * online throughout.
++ *
++ * This function executes full memory barriers before and after fetching
++ * the pointer, which permits the caller to confine this function's fetch
++ * with respect to the caller's accesses to other shared variables.
++ */
++struct task_struct *cpu_curr_snapshot(int cpu)
++{
++ struct task_struct *t;
++
++ smp_mb(); /* Pairing determined by caller's synchronization design. */
++ t = rcu_dereference(cpu_curr(cpu));
++ smp_mb(); /* Pairing determined by caller's synchronization design. */
++ return t;
++}
++
++/**
++ * wake_up_process - Wake up a specific process
++ * @p: The process to be woken up.
++ *
++ * Attempt to wake up the nominated process and move it to the set of runnable
++ * processes.
++ *
++ * Return: 1 if the process was woken up, 0 if it was already running.
++ *
++ * This function executes a full memory barrier before accessing the task state.
++ */
++int wake_up_process(struct task_struct *p)
++{
++ return try_to_wake_up(p, TASK_NORMAL, 0);
++}
++EXPORT_SYMBOL(wake_up_process);
++
++int wake_up_state(struct task_struct *p, unsigned int state)
++{
++ return try_to_wake_up(p, state, 0);
++}
++
++/*
++ * Perform scheduler related setup for a newly forked process p.
++ * p is forked by current.
++ *
++ * __sched_fork() is basic setup used by init_idle() too:
++ */
++static inline void __sched_fork(unsigned long clone_flags, struct task_struct *p)
++{
++ p->on_rq = 0;
++ p->on_cpu = 0;
++ p->utime = 0;
++ p->stime = 0;
++ p->sched_time = 0;
++
++#ifdef CONFIG_SCHEDSTATS
++ /* Even if schedstat is disabled, there should not be garbage */
++ memset(&p->stats, 0, sizeof(p->stats));
++#endif
++
++#ifdef CONFIG_PREEMPT_NOTIFIERS
++ INIT_HLIST_HEAD(&p->preempt_notifiers);
++#endif
++
++#ifdef CONFIG_COMPACTION
++ p->capture_control = NULL;
++#endif
++#ifdef CONFIG_SMP
++ p->wake_entry.u_flags = CSD_TYPE_TTWU;
++#endif
++ init_sched_mm_cid(p);
++}
++
++/*
++ * fork()/clone()-time setup:
++ */
++int sched_fork(unsigned long clone_flags, struct task_struct *p)
++{
++ __sched_fork(clone_flags, p);
++ /*
++ * We mark the process as NEW here. This guarantees that
++ * nobody will actually run it, and a signal or other external
++ * event cannot wake it up and insert it on the runqueue either.
++ */
++ p->__state = TASK_NEW;
++
++ /*
++ * Make sure we do not leak PI boosting priority to the child.
++ */
++ p->prio = current->normal_prio;
++
++ /*
++ * Revert to default priority/policy on fork if requested.
++ */
++ if (unlikely(p->sched_reset_on_fork)) {
++ if (task_has_rt_policy(p)) {
++ p->policy = SCHED_NORMAL;
++ p->static_prio = NICE_TO_PRIO(0);
++ p->rt_priority = 0;
++ } else if (PRIO_TO_NICE(p->static_prio) < 0)
++ p->static_prio = NICE_TO_PRIO(0);
++
++ p->prio = p->normal_prio = p->static_prio;
++
++ /*
++ * We don't need the reset flag anymore after the fork. It has
++ * fulfilled its duty:
++ */
++ p->sched_reset_on_fork = 0;
++ }
++
++#ifdef CONFIG_SCHED_INFO
++ if (unlikely(sched_info_on()))
++ memset(&p->sched_info, 0, sizeof(p->sched_info));
++#endif
++ init_task_preempt_count(p);
++
++ return 0;
++}
++
++void sched_cgroup_fork(struct task_struct *p, struct kernel_clone_args *kargs)
++{
++ unsigned long flags;
++ struct rq *rq;
++
++ /*
++ * Because we're not yet on the pid-hash, p->pi_lock isn't strictly
++ * required yet, but lockdep gets upset if rules are violated.
++ */
++ raw_spin_lock_irqsave(&p->pi_lock, flags);
++ /*
++ * Share the timeslice between parent and child, thus the
++ * total amount of pending timeslices in the system doesn't change,
++ * resulting in more scheduling fairness.
++ */
++ rq = this_rq();
++ raw_spin_lock(&rq->lock);
++
++ rq->curr->time_slice /= 2;
++ p->time_slice = rq->curr->time_slice;
++#ifdef CONFIG_SCHED_HRTICK
++ hrtick_start(rq, rq->curr->time_slice);
++#endif
++
++ if (p->time_slice < RESCHED_NS) {
++ p->time_slice = sysctl_sched_base_slice;
++ resched_curr(rq);
++ }
++ sched_task_fork(p, rq);
++ raw_spin_unlock(&rq->lock);
++
++ rseq_migrate(p);
++ /*
++ * We're setting the CPU for the first time, we don't migrate,
++ * so use __set_task_cpu().
++ */
++ __set_task_cpu(p, smp_processor_id());
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++}
++
++void sched_post_fork(struct task_struct *p)
++{
++}
++
++#ifdef CONFIG_SCHEDSTATS
++
++DEFINE_STATIC_KEY_FALSE(sched_schedstats);
++
++static void set_schedstats(bool enabled)
++{
++ if (enabled)
++ static_branch_enable(&sched_schedstats);
++ else
++ static_branch_disable(&sched_schedstats);
++}
++
++void force_schedstat_enabled(void)
++{
++ if (!schedstat_enabled()) {
++ pr_info("kernel profiling enabled schedstats, disable via kernel.sched_schedstats.\n");
++ static_branch_enable(&sched_schedstats);
++ }
++}
++
++static int __init setup_schedstats(char *str)
++{
++ int ret = 0;
++ if (!str)
++ goto out;
++
++ if (!strcmp(str, "enable")) {
++ set_schedstats(true);
++ ret = 1;
++ } else if (!strcmp(str, "disable")) {
++ set_schedstats(false);
++ ret = 1;
++ }
++out:
++ if (!ret)
++ pr_warn("Unable to parse schedstats=\n");
++
++ return ret;
++}
++__setup("schedstats=", setup_schedstats);
++
++#ifdef CONFIG_PROC_SYSCTL
++static int sysctl_schedstats(struct ctl_table *table, int write, void *buffer,
++ size_t *lenp, loff_t *ppos)
++{
++ struct ctl_table t;
++ int err;
++ int state = static_branch_likely(&sched_schedstats);
++
++ if (write && !capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ t = *table;
++ t.data = &state;
++ err = proc_dointvec_minmax(&t, write, buffer, lenp, ppos);
++ if (err < 0)
++ return err;
++ if (write)
++ set_schedstats(state);
++ return err;
++}
++
++static struct ctl_table sched_core_sysctls[] = {
++ {
++ .procname = "sched_schedstats",
++ .data = NULL,
++ .maxlen = sizeof(unsigned int),
++ .mode = 0644,
++ .proc_handler = sysctl_schedstats,
++ .extra1 = SYSCTL_ZERO,
++ .extra2 = SYSCTL_ONE,
++ },
++ {}
++};
++static int __init sched_core_sysctl_init(void)
++{
++ register_sysctl_init("kernel", sched_core_sysctls);
++ return 0;
++}
++late_initcall(sched_core_sysctl_init);
++#endif /* CONFIG_PROC_SYSCTL */
++#endif /* CONFIG_SCHEDSTATS */
++
++/*
++ * wake_up_new_task - wake up a newly created task for the first time.
++ *
++ * This function will do some initial scheduler statistics housekeeping
++ * that must be done for every newly created context, then puts the task
++ * on the runqueue and wakes it.
++ */
++void wake_up_new_task(struct task_struct *p)
++{
++ unsigned long flags;
++ struct rq *rq;
++
++ raw_spin_lock_irqsave(&p->pi_lock, flags);
++ WRITE_ONCE(p->__state, TASK_RUNNING);
++ rq = cpu_rq(select_task_rq(p));
++#ifdef CONFIG_SMP
++ rseq_migrate(p);
++ /*
++ * Fork balancing, do it here and not earlier because:
++ * - cpus_ptr can change in the fork path
++ * - any previously selected CPU might disappear through hotplug
++ *
++ * Use __set_task_cpu() to avoid calling sched_class::migrate_task_rq,
++ * as we're not fully set-up yet.
++ */
++ __set_task_cpu(p, cpu_of(rq));
++#endif
++
++ raw_spin_lock(&rq->lock);
++ update_rq_clock(rq);
++
++ activate_task(p, rq);
++ trace_sched_wakeup_new(p);
++ wakeup_preempt(rq);
++
++ raw_spin_unlock(&rq->lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++}
++
++#ifdef CONFIG_PREEMPT_NOTIFIERS
++
++static DEFINE_STATIC_KEY_FALSE(preempt_notifier_key);
++
++void preempt_notifier_inc(void)
++{
++ static_branch_inc(&preempt_notifier_key);
++}
++EXPORT_SYMBOL_GPL(preempt_notifier_inc);
++
++void preempt_notifier_dec(void)
++{
++ static_branch_dec(&preempt_notifier_key);
++}
++EXPORT_SYMBOL_GPL(preempt_notifier_dec);
++
++/**
++ * preempt_notifier_register - tell me when current is being preempted & rescheduled
++ * @notifier: notifier struct to register
++ */
++void preempt_notifier_register(struct preempt_notifier *notifier)
++{
++ if (!static_branch_unlikely(&preempt_notifier_key))
++ WARN(1, "registering preempt_notifier while notifiers disabled\n");
++
++ hlist_add_head(¬ifier->link, ¤t->preempt_notifiers);
++}
++EXPORT_SYMBOL_GPL(preempt_notifier_register);
++
++/**
++ * preempt_notifier_unregister - no longer interested in preemption notifications
++ * @notifier: notifier struct to unregister
++ *
++ * This is *not* safe to call from within a preemption notifier.
++ */
++void preempt_notifier_unregister(struct preempt_notifier *notifier)
++{
++ hlist_del(¬ifier->link);
++}
++EXPORT_SYMBOL_GPL(preempt_notifier_unregister);
++
++static void __fire_sched_in_preempt_notifiers(struct task_struct *curr)
++{
++ struct preempt_notifier *notifier;
++
++ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link)
++ notifier->ops->sched_in(notifier, raw_smp_processor_id());
++}
++
++static __always_inline void fire_sched_in_preempt_notifiers(struct task_struct *curr)
++{
++ if (static_branch_unlikely(&preempt_notifier_key))
++ __fire_sched_in_preempt_notifiers(curr);
++}
++
++static void
++__fire_sched_out_preempt_notifiers(struct task_struct *curr,
++ struct task_struct *next)
++{
++ struct preempt_notifier *notifier;
++
++ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link)
++ notifier->ops->sched_out(notifier, next);
++}
++
++static __always_inline void
++fire_sched_out_preempt_notifiers(struct task_struct *curr,
++ struct task_struct *next)
++{
++ if (static_branch_unlikely(&preempt_notifier_key))
++ __fire_sched_out_preempt_notifiers(curr, next);
++}
++
++#else /* !CONFIG_PREEMPT_NOTIFIERS */
++
++static inline void fire_sched_in_preempt_notifiers(struct task_struct *curr)
++{
++}
++
++static inline void
++fire_sched_out_preempt_notifiers(struct task_struct *curr,
++ struct task_struct *next)
++{
++}
++
++#endif /* CONFIG_PREEMPT_NOTIFIERS */
++
++static inline void prepare_task(struct task_struct *next)
++{
++ /*
++ * Claim the task as running, we do this before switching to it
++ * such that any running task will have this set.
++ *
++ * See the smp_load_acquire(&p->on_cpu) case in ttwu() and
++ * its ordering comment.
++ */
++ WRITE_ONCE(next->on_cpu, 1);
++}
++
++static inline void finish_task(struct task_struct *prev)
++{
++#ifdef CONFIG_SMP
++ /*
++ * This must be the very last reference to @prev from this CPU. After
++ * p->on_cpu is cleared, the task can be moved to a different CPU. We
++ * must ensure this doesn't happen until the switch is completely
++ * finished.
++ *
++ * In particular, the load of prev->state in finish_task_switch() must
++ * happen before this.
++ *
++ * Pairs with the smp_cond_load_acquire() in try_to_wake_up().
++ */
++ smp_store_release(&prev->on_cpu, 0);
++#else
++ prev->on_cpu = 0;
++#endif
++}
++
++#ifdef CONFIG_SMP
++
++static void do_balance_callbacks(struct rq *rq, struct balance_callback *head)
++{
++ void (*func)(struct rq *rq);
++ struct balance_callback *next;
++
++ lockdep_assert_held(&rq->lock);
++
++ while (head) {
++ func = (void (*)(struct rq *))head->func;
++ next = head->next;
++ head->next = NULL;
++ head = next;
++
++ func(rq);
++ }
++}
++
++static void balance_push(struct rq *rq);
++
++/*
++ * balance_push_callback is a right abuse of the callback interface and plays
++ * by significantly different rules.
++ *
++ * Where the normal balance_callback's purpose is to be ran in the same context
++ * that queued it (only later, when it's safe to drop rq->lock again),
++ * balance_push_callback is specifically targeted at __schedule().
++ *
++ * This abuse is tolerated because it places all the unlikely/odd cases behind
++ * a single test, namely: rq->balance_callback == NULL.
++ */
++struct balance_callback balance_push_callback = {
++ .next = NULL,
++ .func = balance_push,
++};
++
++static inline struct balance_callback *
++__splice_balance_callbacks(struct rq *rq, bool split)
++{
++ struct balance_callback *head = rq->balance_callback;
++
++ if (likely(!head))
++ return NULL;
++
++ lockdep_assert_rq_held(rq);
++ /*
++ * Must not take balance_push_callback off the list when
++ * splice_balance_callbacks() and balance_callbacks() are not
++ * in the same rq->lock section.
++ *
++ * In that case it would be possible for __schedule() to interleave
++ * and observe the list empty.
++ */
++ if (split && head == &balance_push_callback)
++ head = NULL;
++ else
++ rq->balance_callback = NULL;
++
++ return head;
++}
++
++static inline struct balance_callback *splice_balance_callbacks(struct rq *rq)
++{
++ return __splice_balance_callbacks(rq, true);
++}
++
++static void __balance_callbacks(struct rq *rq)
++{
++ do_balance_callbacks(rq, __splice_balance_callbacks(rq, false));
++}
++
++static inline void balance_callbacks(struct rq *rq, struct balance_callback *head)
++{
++ unsigned long flags;
++
++ if (unlikely(head)) {
++ raw_spin_lock_irqsave(&rq->lock, flags);
++ do_balance_callbacks(rq, head);
++ raw_spin_unlock_irqrestore(&rq->lock, flags);
++ }
++}
++
++#else
++
++static inline void __balance_callbacks(struct rq *rq)
++{
++}
++
++static inline struct balance_callback *splice_balance_callbacks(struct rq *rq)
++{
++ return NULL;
++}
++
++static inline void balance_callbacks(struct rq *rq, struct balance_callback *head)
++{
++}
++
++#endif
++
++static inline void
++prepare_lock_switch(struct rq *rq, struct task_struct *next)
++{
++ /*
++ * Since the runqueue lock will be released by the next
++ * task (which is an invalid locking op but in the case
++ * of the scheduler it's an obvious special-case), so we
++ * do an early lockdep release here:
++ */
++ spin_release(&rq->lock.dep_map, _THIS_IP_);
++#ifdef CONFIG_DEBUG_SPINLOCK
++ /* this is a valid case when another task releases the spinlock */
++ rq->lock.owner = next;
++#endif
++}
++
++static inline void finish_lock_switch(struct rq *rq)
++{
++ /*
++ * If we are tracking spinlock dependencies then we have to
++ * fix up the runqueue lock - which gets 'carried over' from
++ * prev into current:
++ */
++ spin_acquire(&rq->lock.dep_map, 0, 0, _THIS_IP_);
++ __balance_callbacks(rq);
++ raw_spin_unlock_irq(&rq->lock);
++}
++
++/*
++ * NOP if the arch has not defined these:
++ */
++
++#ifndef prepare_arch_switch
++# define prepare_arch_switch(next) do { } while (0)
++#endif
++
++#ifndef finish_arch_post_lock_switch
++# define finish_arch_post_lock_switch() do { } while (0)
++#endif
++
++static inline void kmap_local_sched_out(void)
++{
++#ifdef CONFIG_KMAP_LOCAL
++ if (unlikely(current->kmap_ctrl.idx))
++ __kmap_local_sched_out();
++#endif
++}
++
++static inline void kmap_local_sched_in(void)
++{
++#ifdef CONFIG_KMAP_LOCAL
++ if (unlikely(current->kmap_ctrl.idx))
++ __kmap_local_sched_in();
++#endif
++}
++
++/**
++ * prepare_task_switch - prepare to switch tasks
++ * @rq: the runqueue preparing to switch
++ * @next: the task we are going to switch to.
++ *
++ * This is called with the rq lock held and interrupts off. It must
++ * be paired with a subsequent finish_task_switch after the context
++ * switch.
++ *
++ * prepare_task_switch sets up locking and calls architecture specific
++ * hooks.
++ */
++static inline void
++prepare_task_switch(struct rq *rq, struct task_struct *prev,
++ struct task_struct *next)
++{
++ kcov_prepare_switch(prev);
++ sched_info_switch(rq, prev, next);
++ perf_event_task_sched_out(prev, next);
++ rseq_preempt(prev);
++ fire_sched_out_preempt_notifiers(prev, next);
++ kmap_local_sched_out();
++ prepare_task(next);
++ prepare_arch_switch(next);
++}
++
++/**
++ * finish_task_switch - clean up after a task-switch
++ * @rq: runqueue associated with task-switch
++ * @prev: the thread we just switched away from.
++ *
++ * finish_task_switch must be called after the context switch, paired
++ * with a prepare_task_switch call before the context switch.
++ * finish_task_switch will reconcile locking set up by prepare_task_switch,
++ * and do any other architecture-specific cleanup actions.
++ *
++ * Note that we may have delayed dropping an mm in context_switch(). If
++ * so, we finish that here outside of the runqueue lock. (Doing it
++ * with the lock held can cause deadlocks; see schedule() for
++ * details.)
++ *
++ * The context switch have flipped the stack from under us and restored the
++ * local variables which were saved when this task called schedule() in the
++ * past. prev == current is still correct but we need to recalculate this_rq
++ * because prev may have moved to another CPU.
++ */
++static struct rq *finish_task_switch(struct task_struct *prev)
++ __releases(rq->lock)
++{
++ struct rq *rq = this_rq();
++ struct mm_struct *mm = rq->prev_mm;
++ unsigned int prev_state;
++
++ /*
++ * The previous task will have left us with a preempt_count of 2
++ * because it left us after:
++ *
++ * schedule()
++ * preempt_disable(); // 1
++ * __schedule()
++ * raw_spin_lock_irq(&rq->lock) // 2
++ *
++ * Also, see FORK_PREEMPT_COUNT.
++ */
++ if (WARN_ONCE(preempt_count() != 2*PREEMPT_DISABLE_OFFSET,
++ "corrupted preempt_count: %s/%d/0x%x\n",
++ current->comm, current->pid, preempt_count()))
++ preempt_count_set(FORK_PREEMPT_COUNT);
++
++ rq->prev_mm = NULL;
++
++ /*
++ * A task struct has one reference for the use as "current".
++ * If a task dies, then it sets TASK_DEAD in tsk->state and calls
++ * schedule one last time. The schedule call will never return, and
++ * the scheduled task must drop that reference.
++ *
++ * We must observe prev->state before clearing prev->on_cpu (in
++ * finish_task), otherwise a concurrent wakeup can get prev
++ * running on another CPU and we could rave with its RUNNING -> DEAD
++ * transition, resulting in a double drop.
++ */
++ prev_state = READ_ONCE(prev->__state);
++ vtime_task_switch(prev);
++ perf_event_task_sched_in(prev, current);
++ finish_task(prev);
++ tick_nohz_task_switch();
++ finish_lock_switch(rq);
++ finish_arch_post_lock_switch();
++ kcov_finish_switch(current);
++ /*
++ * kmap_local_sched_out() is invoked with rq::lock held and
++ * interrupts disabled. There is no requirement for that, but the
++ * sched out code does not have an interrupt enabled section.
++ * Restoring the maps on sched in does not require interrupts being
++ * disabled either.
++ */
++ kmap_local_sched_in();
++
++ fire_sched_in_preempt_notifiers(current);
++ /*
++ * When switching through a kernel thread, the loop in
++ * membarrier_{private,global}_expedited() may have observed that
++ * kernel thread and not issued an IPI. It is therefore possible to
++ * schedule between user->kernel->user threads without passing though
++ * switch_mm(). Membarrier requires a barrier after storing to
++ * rq->curr, before returning to userspace, so provide them here:
++ *
++ * - a full memory barrier for {PRIVATE,GLOBAL}_EXPEDITED, implicitly
++ * provided by mmdrop(),
++ * - a sync_core for SYNC_CORE.
++ */
++ if (mm) {
++ membarrier_mm_sync_core_before_usermode(mm);
++ mmdrop_sched(mm);
++ }
++ if (unlikely(prev_state == TASK_DEAD)) {
++ /* Task is done with its stack. */
++ put_task_stack(prev);
++
++ put_task_struct_rcu_user(prev);
++ }
++
++ return rq;
++}
++
++/**
++ * schedule_tail - first thing a freshly forked thread must call.
++ * @prev: the thread we just switched away from.
++ */
++asmlinkage __visible void schedule_tail(struct task_struct *prev)
++ __releases(rq->lock)
++{
++ /*
++ * New tasks start with FORK_PREEMPT_COUNT, see there and
++ * finish_task_switch() for details.
++ *
++ * finish_task_switch() will drop rq->lock() and lower preempt_count
++ * and the preempt_enable() will end up enabling preemption (on
++ * PREEMPT_COUNT kernels).
++ */
++
++ finish_task_switch(prev);
++ preempt_enable();
++
++ if (current->set_child_tid)
++ put_user(task_pid_vnr(current), current->set_child_tid);
++
++ calculate_sigpending();
++}
++
++/*
++ * context_switch - switch to the new MM and the new thread's register state.
++ */
++static __always_inline struct rq *
++context_switch(struct rq *rq, struct task_struct *prev,
++ struct task_struct *next)
++{
++ prepare_task_switch(rq, prev, next);
++
++ /*
++ * For paravirt, this is coupled with an exit in switch_to to
++ * combine the page table reload and the switch backend into
++ * one hypercall.
++ */
++ arch_start_context_switch(prev);
++
++ /*
++ * kernel -> kernel lazy + transfer active
++ * user -> kernel lazy + mmgrab() active
++ *
++ * kernel -> user switch + mmdrop() active
++ * user -> user switch
++ *
++ * switch_mm_cid() needs to be updated if the barriers provided
++ * by context_switch() are modified.
++ */
++ if (!next->mm) { // to kernel
++ enter_lazy_tlb(prev->active_mm, next);
++
++ next->active_mm = prev->active_mm;
++ if (prev->mm) // from user
++ mmgrab(prev->active_mm);
++ else
++ prev->active_mm = NULL;
++ } else { // to user
++ membarrier_switch_mm(rq, prev->active_mm, next->mm);
++ /*
++ * sys_membarrier() requires an smp_mb() between setting
++ * rq->curr / membarrier_switch_mm() and returning to userspace.
++ *
++ * The below provides this either through switch_mm(), or in
++ * case 'prev->active_mm == next->mm' through
++ * finish_task_switch()'s mmdrop().
++ */
++ switch_mm_irqs_off(prev->active_mm, next->mm, next);
++ lru_gen_use_mm(next->mm);
++
++ if (!prev->mm) { // from kernel
++ /* will mmdrop() in finish_task_switch(). */
++ rq->prev_mm = prev->active_mm;
++ prev->active_mm = NULL;
++ }
++ }
++
++ /* switch_mm_cid() requires the memory barriers above. */
++ switch_mm_cid(rq, prev, next);
++
++ prepare_lock_switch(rq, next);
++
++ /* Here we just switch the register state and the stack. */
++ switch_to(prev, next, prev);
++ barrier();
++
++ return finish_task_switch(prev);
++}
++
++/*
++ * nr_running, nr_uninterruptible and nr_context_switches:
++ *
++ * externally visible scheduler statistics: current number of runnable
++ * threads, total number of context switches performed since bootup.
++ */
++unsigned int nr_running(void)
++{
++ unsigned int i, sum = 0;
++
++ for_each_online_cpu(i)
++ sum += cpu_rq(i)->nr_running;
++
++ return sum;
++}
++
++/*
++ * Check if only the current task is running on the CPU.
++ *
++ * Caution: this function does not check that the caller has disabled
++ * preemption, thus the result might have a time-of-check-to-time-of-use
++ * race. The caller is responsible to use it correctly, for example:
++ *
++ * - from a non-preemptible section (of course)
++ *
++ * - from a thread that is bound to a single CPU
++ *
++ * - in a loop with very short iterations (e.g. a polling loop)
++ */
++bool single_task_running(void)
++{
++ return raw_rq()->nr_running == 1;
++}
++EXPORT_SYMBOL(single_task_running);
++
++unsigned long long nr_context_switches_cpu(int cpu)
++{
++ return cpu_rq(cpu)->nr_switches;
++}
++
++unsigned long long nr_context_switches(void)
++{
++ int i;
++ unsigned long long sum = 0;
++
++ for_each_possible_cpu(i)
++ sum += cpu_rq(i)->nr_switches;
++
++ return sum;
++}
++
++/*
++ * Consumers of these two interfaces, like for example the cpuidle menu
++ * governor, are using nonsensical data. Preferring shallow idle state selection
++ * for a CPU that has IO-wait which might not even end up running the task when
++ * it does become runnable.
++ */
++
++unsigned int nr_iowait_cpu(int cpu)
++{
++ return atomic_read(&cpu_rq(cpu)->nr_iowait);
++}
++
++/*
++ * IO-wait accounting, and how it's mostly bollocks (on SMP).
++ *
++ * The idea behind IO-wait account is to account the idle time that we could
++ * have spend running if it were not for IO. That is, if we were to improve the
++ * storage performance, we'd have a proportional reduction in IO-wait time.
++ *
++ * This all works nicely on UP, where, when a task blocks on IO, we account
++ * idle time as IO-wait, because if the storage were faster, it could've been
++ * running and we'd not be idle.
++ *
++ * This has been extended to SMP, by doing the same for each CPU. This however
++ * is broken.
++ *
++ * Imagine for instance the case where two tasks block on one CPU, only the one
++ * CPU will have IO-wait accounted, while the other has regular idle. Even
++ * though, if the storage were faster, both could've ran at the same time,
++ * utilising both CPUs.
++ *
++ * This means, that when looking globally, the current IO-wait accounting on
++ * SMP is a lower bound, by reason of under accounting.
++ *
++ * Worse, since the numbers are provided per CPU, they are sometimes
++ * interpreted per CPU, and that is nonsensical. A blocked task isn't strictly
++ * associated with any one particular CPU, it can wake to another CPU than it
++ * blocked on. This means the per CPU IO-wait number is meaningless.
++ *
++ * Task CPU affinities can make all that even more 'interesting'.
++ */
++
++unsigned int nr_iowait(void)
++{
++ unsigned int i, sum = 0;
++
++ for_each_possible_cpu(i)
++ sum += nr_iowait_cpu(i);
++
++ return sum;
++}
++
++#ifdef CONFIG_SMP
++
++/*
++ * sched_exec - execve() is a valuable balancing opportunity, because at
++ * this point the task has the smallest effective memory and cache
++ * footprint.
++ */
++void sched_exec(void)
++{
++}
++
++#endif
++
++DEFINE_PER_CPU(struct kernel_stat, kstat);
++DEFINE_PER_CPU(struct kernel_cpustat, kernel_cpustat);
++
++EXPORT_PER_CPU_SYMBOL(kstat);
++EXPORT_PER_CPU_SYMBOL(kernel_cpustat);
++
++static inline void update_curr(struct rq *rq, struct task_struct *p)
++{
++ s64 ns = rq->clock_task - p->last_ran;
++
++ p->sched_time += ns;
++ cgroup_account_cputime(p, ns);
++ account_group_exec_runtime(p, ns);
++
++ p->time_slice -= ns;
++ p->last_ran = rq->clock_task;
++}
++
++/*
++ * Return accounted runtime for the task.
++ * Return separately the current's pending runtime that have not been
++ * accounted yet.
++ */
++unsigned long long task_sched_runtime(struct task_struct *p)
++{
++ unsigned long flags;
++ struct rq *rq;
++ raw_spinlock_t *lock;
++ u64 ns;
++
++#if defined(CONFIG_64BIT) && defined(CONFIG_SMP)
++ /*
++ * 64-bit doesn't need locks to atomically read a 64-bit value.
++ * So we have a optimization chance when the task's delta_exec is 0.
++ * Reading ->on_cpu is racy, but this is ok.
++ *
++ * If we race with it leaving CPU, we'll take a lock. So we're correct.
++ * If we race with it entering CPU, unaccounted time is 0. This is
++ * indistinguishable from the read occurring a few cycles earlier.
++ * If we see ->on_cpu without ->on_rq, the task is leaving, and has
++ * been accounted, so we're correct here as well.
++ */
++ if (!p->on_cpu || !task_on_rq_queued(p))
++ return tsk_seruntime(p);
++#endif
++
++ rq = task_access_lock_irqsave(p, &lock, &flags);
++ /*
++ * Must be ->curr _and_ ->on_rq. If dequeued, we would
++ * project cycles that may never be accounted to this
++ * thread, breaking clock_gettime().
++ */
++ if (p == rq->curr && task_on_rq_queued(p)) {
++ update_rq_clock(rq);
++ update_curr(rq, p);
++ }
++ ns = tsk_seruntime(p);
++ task_access_unlock_irqrestore(p, lock, &flags);
++
++ return ns;
++}
++
++/* This manages tasks that have run out of timeslice during a scheduler_tick */
++static inline void scheduler_task_tick(struct rq *rq)
++{
++ struct task_struct *p = rq->curr;
++
++ if (is_idle_task(p))
++ return;
++
++ update_curr(rq, p);
++ cpufreq_update_util(rq, 0);
++
++ /*
++ * Tasks have less than RESCHED_NS of time slice left they will be
++ * rescheduled.
++ */
++ if (p->time_slice >= RESCHED_NS)
++ return;
++ set_tsk_need_resched(p);
++ set_preempt_need_resched();
++}
++
++#ifdef CONFIG_SCHED_DEBUG
++static u64 cpu_resched_latency(struct rq *rq)
++{
++ int latency_warn_ms = READ_ONCE(sysctl_resched_latency_warn_ms);
++ u64 resched_latency, now = rq_clock(rq);
++ static bool warned_once;
++
++ if (sysctl_resched_latency_warn_once && warned_once)
++ return 0;
++
++ if (!need_resched() || !latency_warn_ms)
++ return 0;
++
++ if (system_state == SYSTEM_BOOTING)
++ return 0;
++
++ if (!rq->last_seen_need_resched_ns) {
++ rq->last_seen_need_resched_ns = now;
++ rq->ticks_without_resched = 0;
++ return 0;
++ }
++
++ rq->ticks_without_resched++;
++ resched_latency = now - rq->last_seen_need_resched_ns;
++ if (resched_latency <= latency_warn_ms * NSEC_PER_MSEC)
++ return 0;
++
++ warned_once = true;
++
++ return resched_latency;
++}
++
++static int __init setup_resched_latency_warn_ms(char *str)
++{
++ long val;
++
++ if ((kstrtol(str, 0, &val))) {
++ pr_warn("Unable to set resched_latency_warn_ms\n");
++ return 1;
++ }
++
++ sysctl_resched_latency_warn_ms = val;
++ return 1;
++}
++__setup("resched_latency_warn_ms=", setup_resched_latency_warn_ms);
++#else
++static inline u64 cpu_resched_latency(struct rq *rq) { return 0; }
++#endif /* CONFIG_SCHED_DEBUG */
++
++/*
++ * This function gets called by the timer code, with HZ frequency.
++ * We call it with interrupts disabled.
++ */
++void scheduler_tick(void)
++{
++ int cpu __maybe_unused = smp_processor_id();
++ struct rq *rq = cpu_rq(cpu);
++ struct task_struct *curr = rq->curr;
++ u64 resched_latency;
++
++ if (housekeeping_cpu(cpu, HK_TYPE_TICK))
++ arch_scale_freq_tick();
++
++ sched_clock_tick();
++
++ raw_spin_lock(&rq->lock);
++ update_rq_clock(rq);
++
++ scheduler_task_tick(rq);
++ if (sched_feat(LATENCY_WARN))
++ resched_latency = cpu_resched_latency(rq);
++ calc_global_load_tick(rq);
++
++ task_tick_mm_cid(rq, rq->curr);
++
++ raw_spin_unlock(&rq->lock);
++
++ if (sched_feat(LATENCY_WARN) && resched_latency)
++ resched_latency_warn(cpu, resched_latency);
++
++ perf_event_task_tick();
++
++ if (curr->flags & PF_WQ_WORKER)
++ wq_worker_tick(curr);
++}
++
++#ifdef CONFIG_SCHED_SMT
++static inline int sg_balance_cpu_stop(void *data)
++{
++ struct rq *rq = this_rq();
++ struct task_struct *p = data;
++ cpumask_t tmp;
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ raw_spin_lock(&p->pi_lock);
++ raw_spin_lock(&rq->lock);
++
++ rq->active_balance = 0;
++ /* _something_ may have changed the task, double check again */
++ if (task_on_rq_queued(p) && task_rq(p) == rq &&
++ cpumask_and(&tmp, p->cpus_ptr, &sched_sg_idle_mask) &&
++ !is_migration_disabled(p)) {
++ int cpu = cpu_of(rq);
++ int dcpu = __best_mask_cpu(&tmp, per_cpu(sched_cpu_llc_mask, cpu));
++ rq = move_queued_task(rq, p, dcpu);
++ }
++
++ raw_spin_unlock(&rq->lock);
++ raw_spin_unlock(&p->pi_lock);
++
++ local_irq_restore(flags);
++
++ return 0;
++}
++
++/* sg_balance_trigger - trigger slibing group balance for @cpu */
++static inline int sg_balance_trigger(const int cpu)
++{
++ struct rq *rq= cpu_rq(cpu);
++ unsigned long flags;
++ struct task_struct *curr;
++ int res;
++
++ if (!raw_spin_trylock_irqsave(&rq->lock, flags))
++ return 0;
++ curr = rq->curr;
++ res = (!is_idle_task(curr)) && (1 == rq->nr_running) &&\
++ cpumask_intersects(curr->cpus_ptr, &sched_sg_idle_mask) &&\
++ !is_migration_disabled(curr) && (!rq->active_balance);
++
++ if (res)
++ rq->active_balance = 1;
++
++ raw_spin_unlock_irqrestore(&rq->lock, flags);
++
++ if (res)
++ stop_one_cpu_nowait(cpu, sg_balance_cpu_stop, curr,
++ &rq->active_balance_work);
++ return res;
++}
++
++/*
++ * sg_balance - slibing group balance check for run queue @rq
++ */
++static inline void sg_balance(struct rq *rq, int cpu)
++{
++ cpumask_t chk;
++
++ /* exit when cpu is offline */
++ if (unlikely(!rq->online))
++ return;
++
++ /*
++ * Only cpu in slibing idle group will do the checking and then
++ * find potential cpus which can migrate the current running task
++ */
++ if (cpumask_test_cpu(cpu, &sched_sg_idle_mask) &&
++ cpumask_andnot(&chk, cpu_online_mask, sched_idle_mask) &&
++ cpumask_andnot(&chk, &chk, &sched_rq_pending_mask)) {
++ int i;
++
++ for_each_cpu_wrap(i, &chk, cpu) {
++ if (!cpumask_intersects(cpu_smt_mask(i), sched_idle_mask) &&\
++ sg_balance_trigger(i))
++ return;
++ }
++ }
++}
++#endif /* CONFIG_SCHED_SMT */
++
++#ifdef CONFIG_NO_HZ_FULL
++
++struct tick_work {
++ int cpu;
++ atomic_t state;
++ struct delayed_work work;
++};
++/* Values for ->state, see diagram below. */
++#define TICK_SCHED_REMOTE_OFFLINE 0
++#define TICK_SCHED_REMOTE_OFFLINING 1
++#define TICK_SCHED_REMOTE_RUNNING 2
++
++/*
++ * State diagram for ->state:
++ *
++ *
++ * TICK_SCHED_REMOTE_OFFLINE
++ * | ^
++ * | |
++ * | | sched_tick_remote()
++ * | |
++ * | |
++ * +--TICK_SCHED_REMOTE_OFFLINING
++ * | ^
++ * | |
++ * sched_tick_start() | | sched_tick_stop()
++ * | |
++ * V |
++ * TICK_SCHED_REMOTE_RUNNING
++ *
++ *
++ * Other transitions get WARN_ON_ONCE(), except that sched_tick_remote()
++ * and sched_tick_start() are happy to leave the state in RUNNING.
++ */
++
++static struct tick_work __percpu *tick_work_cpu;
++
++static void sched_tick_remote(struct work_struct *work)
++{
++ struct delayed_work *dwork = to_delayed_work(work);
++ struct tick_work *twork = container_of(dwork, struct tick_work, work);
++ int cpu = twork->cpu;
++ struct rq *rq = cpu_rq(cpu);
++ int os;
++
++ /*
++ * Handle the tick only if it appears the remote CPU is running in full
++ * dynticks mode. The check is racy by nature, but missing a tick or
++ * having one too much is no big deal because the scheduler tick updates
++ * statistics and checks timeslices in a time-independent way, regardless
++ * of when exactly it is running.
++ */
++ if (tick_nohz_tick_stopped_cpu(cpu)) {
++ guard(raw_spinlock_irqsave)(&rq->lock);
++ struct task_struct *curr = rq->curr;
++
++ if (cpu_online(cpu)) {
++ update_rq_clock(rq);
++
++ if (!is_idle_task(curr)) {
++ /*
++ * Make sure the next tick runs within a
++ * reasonable amount of time.
++ */
++ u64 delta = rq_clock_task(rq) - curr->last_ran;
++ WARN_ON_ONCE(delta > (u64)NSEC_PER_SEC * 3);
++ }
++ scheduler_task_tick(rq);
++
++ calc_load_nohz_remote(rq);
++ }
++ }
++
++ /*
++ * Run the remote tick once per second (1Hz). This arbitrary
++ * frequency is large enough to avoid overload but short enough
++ * to keep scheduler internal stats reasonably up to date. But
++ * first update state to reflect hotplug activity if required.
++ */
++ os = atomic_fetch_add_unless(&twork->state, -1, TICK_SCHED_REMOTE_RUNNING);
++ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_OFFLINE);
++ if (os == TICK_SCHED_REMOTE_RUNNING)
++ queue_delayed_work(system_unbound_wq, dwork, HZ);
++}
++
++static void sched_tick_start(int cpu)
++{
++ int os;
++ struct tick_work *twork;
++
++ if (housekeeping_cpu(cpu, HK_TYPE_TICK))
++ return;
++
++ WARN_ON_ONCE(!tick_work_cpu);
++
++ twork = per_cpu_ptr(tick_work_cpu, cpu);
++ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_RUNNING);
++ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_RUNNING);
++ if (os == TICK_SCHED_REMOTE_OFFLINE) {
++ twork->cpu = cpu;
++ INIT_DELAYED_WORK(&twork->work, sched_tick_remote);
++ queue_delayed_work(system_unbound_wq, &twork->work, HZ);
++ }
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++static void sched_tick_stop(int cpu)
++{
++ struct tick_work *twork;
++ int os;
++
++ if (housekeeping_cpu(cpu, HK_TYPE_TICK))
++ return;
++
++ WARN_ON_ONCE(!tick_work_cpu);
++
++ twork = per_cpu_ptr(tick_work_cpu, cpu);
++ /* There cannot be competing actions, but don't rely on stop-machine. */
++ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_OFFLINING);
++ WARN_ON_ONCE(os != TICK_SCHED_REMOTE_RUNNING);
++ /* Don't cancel, as this would mess up the state machine. */
++}
++#endif /* CONFIG_HOTPLUG_CPU */
++
++int __init sched_tick_offload_init(void)
++{
++ tick_work_cpu = alloc_percpu(struct tick_work);
++ BUG_ON(!tick_work_cpu);
++ return 0;
++}
++
++#else /* !CONFIG_NO_HZ_FULL */
++static inline void sched_tick_start(int cpu) { }
++static inline void sched_tick_stop(int cpu) { }
++#endif
++
++#if defined(CONFIG_PREEMPTION) && (defined(CONFIG_DEBUG_PREEMPT) || \
++ defined(CONFIG_PREEMPT_TRACER))
++/*
++ * If the value passed in is equal to the current preempt count
++ * then we just disabled preemption. Start timing the latency.
++ */
++static inline void preempt_latency_start(int val)
++{
++ if (preempt_count() == val) {
++ unsigned long ip = get_lock_parent_ip();
++#ifdef CONFIG_DEBUG_PREEMPT
++ current->preempt_disable_ip = ip;
++#endif
++ trace_preempt_off(CALLER_ADDR0, ip);
++ }
++}
++
++void preempt_count_add(int val)
++{
++#ifdef CONFIG_DEBUG_PREEMPT
++ /*
++ * Underflow?
++ */
++ if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0)))
++ return;
++#endif
++ __preempt_count_add(val);
++#ifdef CONFIG_DEBUG_PREEMPT
++ /*
++ * Spinlock count overflowing soon?
++ */
++ DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >=
++ PREEMPT_MASK - 10);
++#endif
++ preempt_latency_start(val);
++}
++EXPORT_SYMBOL(preempt_count_add);
++NOKPROBE_SYMBOL(preempt_count_add);
++
++/*
++ * If the value passed in equals to the current preempt count
++ * then we just enabled preemption. Stop timing the latency.
++ */
++static inline void preempt_latency_stop(int val)
++{
++ if (preempt_count() == val)
++ trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip());
++}
++
++void preempt_count_sub(int val)
++{
++#ifdef CONFIG_DEBUG_PREEMPT
++ /*
++ * Underflow?
++ */
++ if (DEBUG_LOCKS_WARN_ON(val > preempt_count()))
++ return;
++ /*
++ * Is the spinlock portion underflowing?
++ */
++ if (DEBUG_LOCKS_WARN_ON((val < PREEMPT_MASK) &&
++ !(preempt_count() & PREEMPT_MASK)))
++ return;
++#endif
++
++ preempt_latency_stop(val);
++ __preempt_count_sub(val);
++}
++EXPORT_SYMBOL(preempt_count_sub);
++NOKPROBE_SYMBOL(preempt_count_sub);
++
++#else
++static inline void preempt_latency_start(int val) { }
++static inline void preempt_latency_stop(int val) { }
++#endif
++
++static inline unsigned long get_preempt_disable_ip(struct task_struct *p)
++{
++#ifdef CONFIG_DEBUG_PREEMPT
++ return p->preempt_disable_ip;
++#else
++ return 0;
++#endif
++}
++
++/*
++ * Print scheduling while atomic bug:
++ */
++static noinline void __schedule_bug(struct task_struct *prev)
++{
++ /* Save this before calling printk(), since that will clobber it */
++ unsigned long preempt_disable_ip = get_preempt_disable_ip(current);
++
++ if (oops_in_progress)
++ return;
++
++ printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n",
++ prev->comm, prev->pid, preempt_count());
++
++ debug_show_held_locks(prev);
++ print_modules();
++ if (irqs_disabled())
++ print_irqtrace_events(prev);
++ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT)) {
++ pr_err("Preemption disabled at:");
++ print_ip_sym(KERN_ERR, preempt_disable_ip);
++ }
++ check_panic_on_warn("scheduling while atomic");
++
++ dump_stack();
++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
++}
++
++/*
++ * Various schedule()-time debugging checks and statistics:
++ */
++static inline void schedule_debug(struct task_struct *prev, bool preempt)
++{
++#ifdef CONFIG_SCHED_STACK_END_CHECK
++ if (task_stack_end_corrupted(prev))
++ panic("corrupted stack end detected inside scheduler\n");
++
++ if (task_scs_end_corrupted(prev))
++ panic("corrupted shadow stack detected inside scheduler\n");
++#endif
++
++#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
++ if (!preempt && READ_ONCE(prev->__state) && prev->non_block_count) {
++ printk(KERN_ERR "BUG: scheduling in a non-blocking section: %s/%d/%i\n",
++ prev->comm, prev->pid, prev->non_block_count);
++ dump_stack();
++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
++ }
++#endif
++
++ if (unlikely(in_atomic_preempt_off())) {
++ __schedule_bug(prev);
++ preempt_count_set(PREEMPT_DISABLED);
++ }
++ rcu_sleep_check();
++ SCHED_WARN_ON(ct_state() == CONTEXT_USER);
++
++ profile_hit(SCHED_PROFILING, __builtin_return_address(0));
++
++ schedstat_inc(this_rq()->sched_count);
++}
++
++#ifdef ALT_SCHED_DEBUG
++void alt_sched_debug(void)
++{
++ printk(KERN_INFO "sched: pending: 0x%04lx, idle: 0x%04lx, sg_idle: 0x%04lx\n",
++ sched_rq_pending_mask.bits[0],
++ sched_idle_mask->bits[0],
++ sched_sg_idle_mask.bits[0]);
++}
++#else
++inline void alt_sched_debug(void) {}
++#endif
++
++#ifdef CONFIG_SMP
++
++#ifdef CONFIG_PREEMPT_RT
++#define SCHED_NR_MIGRATE_BREAK 8
++#else
++#define SCHED_NR_MIGRATE_BREAK 32
++#endif
++
++const_debug unsigned int sysctl_sched_nr_migrate = SCHED_NR_MIGRATE_BREAK;
++
++/*
++ * Migrate pending tasks in @rq to @dest_cpu
++ */
++static inline int
++migrate_pending_tasks(struct rq *rq, struct rq *dest_rq, const int dest_cpu)
++{
++ struct task_struct *p, *skip = rq->curr;
++ int nr_migrated = 0;
++ int nr_tries = min(rq->nr_running / 2, sysctl_sched_nr_migrate);
++
++ /* WA to check rq->curr is still on rq */
++ if (!task_on_rq_queued(skip))
++ return 0;
++
++ while (skip != rq->idle && nr_tries &&
++ (p = sched_rq_next_task(skip, rq)) != rq->idle) {
++ skip = sched_rq_next_task(p, rq);
++ if (cpumask_test_cpu(dest_cpu, p->cpus_ptr)) {
++ __SCHED_DEQUEUE_TASK(p, rq, 0, );
++ set_task_cpu(p, dest_cpu);
++ sched_task_sanity_check(p, dest_rq);
++ sched_mm_cid_migrate_to(dest_rq, p, cpu_of(rq));
++ __SCHED_ENQUEUE_TASK(p, dest_rq, 0);
++ nr_migrated++;
++ }
++ nr_tries--;
++ }
++
++ return nr_migrated;
++}
++
++static inline int take_other_rq_tasks(struct rq *rq, int cpu)
++{
++ struct cpumask *topo_mask, *end_mask;
++
++ if (unlikely(!rq->online))
++ return 0;
++
++ if (cpumask_empty(&sched_rq_pending_mask))
++ return 0;
++
++ topo_mask = per_cpu(sched_cpu_topo_masks, cpu) + 1;
++ end_mask = per_cpu(sched_cpu_topo_end_mask, cpu);
++ do {
++ int i;
++ for_each_cpu_and(i, &sched_rq_pending_mask, topo_mask) {
++ int nr_migrated;
++ struct rq *src_rq;
++
++ src_rq = cpu_rq(i);
++ if (!do_raw_spin_trylock(&src_rq->lock))
++ continue;
++ spin_acquire(&src_rq->lock.dep_map,
++ SINGLE_DEPTH_NESTING, 1, _RET_IP_);
++
++ if ((nr_migrated = migrate_pending_tasks(src_rq, rq, cpu))) {
++ src_rq->nr_running -= nr_migrated;
++ if (src_rq->nr_running < 2)
++ cpumask_clear_cpu(i, &sched_rq_pending_mask);
++
++ spin_release(&src_rq->lock.dep_map, _RET_IP_);
++ do_raw_spin_unlock(&src_rq->lock);
++
++ rq->nr_running += nr_migrated;
++ if (rq->nr_running > 1)
++ cpumask_set_cpu(cpu, &sched_rq_pending_mask);
++
++ update_sched_preempt_mask(rq);
++ cpufreq_update_util(rq, 0);
++
++ return 1;
++ }
++
++ spin_release(&src_rq->lock.dep_map, _RET_IP_);
++ do_raw_spin_unlock(&src_rq->lock);
++ }
++ } while (++topo_mask < end_mask);
++
++ return 0;
++}
++#endif
++
++static inline void time_slice_expired(struct task_struct *p, struct rq *rq)
++{
++ p->time_slice = sysctl_sched_base_slice;
++
++ sched_task_renew(p, rq);
++
++ if (SCHED_FIFO != p->policy && task_on_rq_queued(p))
++ requeue_task(p, rq, task_sched_prio_idx(p, rq));
++}
++
++/*
++ * Timeslices below RESCHED_NS are considered as good as expired as there's no
++ * point rescheduling when there's so little time left.
++ */
++static inline void check_curr(struct task_struct *p, struct rq *rq)
++{
++ if (unlikely(rq->idle == p))
++ return;
++
++ update_curr(rq, p);
++
++ if (p->time_slice < RESCHED_NS)
++ time_slice_expired(p, rq);
++}
++
++static inline struct task_struct *
++choose_next_task(struct rq *rq, int cpu)
++{
++ struct task_struct *next;
++
++ if (unlikely(rq->skip)) {
++ next = rq_runnable_task(rq);
++ if (next == rq->idle) {
++#ifdef CONFIG_SMP
++ if (!take_other_rq_tasks(rq, cpu)) {
++#endif
++ rq->skip = NULL;
++ schedstat_inc(rq->sched_goidle);
++ return next;
++#ifdef CONFIG_SMP
++ }
++ next = rq_runnable_task(rq);
++#endif
++ }
++ rq->skip = NULL;
++#ifdef CONFIG_HIGH_RES_TIMERS
++ hrtick_start(rq, next->time_slice);
++#endif
++ return next;
++ }
++
++ next = sched_rq_first_task(rq);
++ if (next == rq->idle) {
++#ifdef CONFIG_SMP
++ if (!take_other_rq_tasks(rq, cpu)) {
++#endif
++ schedstat_inc(rq->sched_goidle);
++ /*printk(KERN_INFO "sched: choose_next_task(%d) idle %px\n", cpu, next);*/
++ return next;
++#ifdef CONFIG_SMP
++ }
++ next = sched_rq_first_task(rq);
++#endif
++ }
++#ifdef CONFIG_HIGH_RES_TIMERS
++ hrtick_start(rq, next->time_slice);
++#endif
++ /*printk(KERN_INFO "sched: choose_next_task(%d) next %px\n", cpu, next);*/
++ return next;
++}
++
++/*
++ * Constants for the sched_mode argument of __schedule().
++ *
++ * The mode argument allows RT enabled kernels to differentiate a
++ * preemption from blocking on an 'sleeping' spin/rwlock. Note that
++ * SM_MASK_PREEMPT for !RT has all bits set, which allows the compiler to
++ * optimize the AND operation out and just check for zero.
++ */
++#define SM_NONE 0x0
++#define SM_PREEMPT 0x1
++#define SM_RTLOCK_WAIT 0x2
++
++#ifndef CONFIG_PREEMPT_RT
++# define SM_MASK_PREEMPT (~0U)
++#else
++# define SM_MASK_PREEMPT SM_PREEMPT
++#endif
++
++/*
++ * schedule() is the main scheduler function.
++ *
++ * The main means of driving the scheduler and thus entering this function are:
++ *
++ * 1. Explicit blocking: mutex, semaphore, waitqueue, etc.
++ *
++ * 2. TIF_NEED_RESCHED flag is checked on interrupt and userspace return
++ * paths. For example, see arch/x86/entry_64.S.
++ *
++ * To drive preemption between tasks, the scheduler sets the flag in timer
++ * interrupt handler scheduler_tick().
++ *
++ * 3. Wakeups don't really cause entry into schedule(). They add a
++ * task to the run-queue and that's it.
++ *
++ * Now, if the new task added to the run-queue preempts the current
++ * task, then the wakeup sets TIF_NEED_RESCHED and schedule() gets
++ * called on the nearest possible occasion:
++ *
++ * - If the kernel is preemptible (CONFIG_PREEMPTION=y):
++ *
++ * - in syscall or exception context, at the next outmost
++ * preempt_enable(). (this might be as soon as the wake_up()'s
++ * spin_unlock()!)
++ *
++ * - in IRQ context, return from interrupt-handler to
++ * preemptible context
++ *
++ * - If the kernel is not preemptible (CONFIG_PREEMPTION is not set)
++ * then at the next:
++ *
++ * - cond_resched() call
++ * - explicit schedule() call
++ * - return from syscall or exception to user-space
++ * - return from interrupt-handler to user-space
++ *
++ * WARNING: must be called with preemption disabled!
++ */
++static void __sched notrace __schedule(unsigned int sched_mode)
++{
++ struct task_struct *prev, *next;
++ unsigned long *switch_count;
++ unsigned long prev_state;
++ struct rq *rq;
++ int cpu;
++
++ cpu = smp_processor_id();
++ rq = cpu_rq(cpu);
++ prev = rq->curr;
++
++ schedule_debug(prev, !!sched_mode);
++
++ /* by passing sched_feat(HRTICK) checking which Alt schedule FW doesn't support */
++ hrtick_clear(rq);
++
++ local_irq_disable();
++ rcu_note_context_switch(!!sched_mode);
++
++ /*
++ * Make sure that signal_pending_state()->signal_pending() below
++ * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE)
++ * done by the caller to avoid the race with signal_wake_up():
++ *
++ * __set_current_state(@state) signal_wake_up()
++ * schedule() set_tsk_thread_flag(p, TIF_SIGPENDING)
++ * wake_up_state(p, state)
++ * LOCK rq->lock LOCK p->pi_state
++ * smp_mb__after_spinlock() smp_mb__after_spinlock()
++ * if (signal_pending_state()) if (p->state & @state)
++ *
++ * Also, the membarrier system call requires a full memory barrier
++ * after coming from user-space, before storing to rq->curr.
++ */
++ raw_spin_lock(&rq->lock);
++ smp_mb__after_spinlock();
++
++ update_rq_clock(rq);
++
++ switch_count = &prev->nivcsw;
++ /*
++ * We must load prev->state once (task_struct::state is volatile), such
++ * that we form a control dependency vs deactivate_task() below.
++ */
++ prev_state = READ_ONCE(prev->__state);
++ if (!(sched_mode & SM_MASK_PREEMPT) && prev_state) {
++ if (signal_pending_state(prev_state, prev)) {
++ WRITE_ONCE(prev->__state, TASK_RUNNING);
++ } else {
++ prev->sched_contributes_to_load =
++ (prev_state & TASK_UNINTERRUPTIBLE) &&
++ !(prev_state & TASK_NOLOAD) &&
++ !(prev_state & TASK_FROZEN);
++
++ if (prev->sched_contributes_to_load)
++ rq->nr_uninterruptible++;
++
++ /*
++ * __schedule() ttwu()
++ * prev_state = prev->state; if (p->on_rq && ...)
++ * if (prev_state) goto out;
++ * p->on_rq = 0; smp_acquire__after_ctrl_dep();
++ * p->state = TASK_WAKING
++ *
++ * Where __schedule() and ttwu() have matching control dependencies.
++ *
++ * After this, schedule() must not care about p->state any more.
++ */
++ sched_task_deactivate(prev, rq);
++ deactivate_task(prev, rq);
++
++ if (prev->in_iowait) {
++ atomic_inc(&rq->nr_iowait);
++ delayacct_blkio_start();
++ }
++ }
++ switch_count = &prev->nvcsw;
++ }
++
++ check_curr(prev, rq);
++
++ next = choose_next_task(rq, cpu);
++ clear_tsk_need_resched(prev);
++ clear_preempt_need_resched();
++#ifdef CONFIG_SCHED_DEBUG
++ rq->last_seen_need_resched_ns = 0;
++#endif
++
++ if (likely(prev != next)) {
++#ifdef CONFIG_SCHED_BMQ
++ rq->last_ts_switch = rq->clock;
++#endif
++ next->last_ran = rq->clock_task;
++
++ /*printk(KERN_INFO "sched: %px -> %px\n", prev, next);*/
++ rq->nr_switches++;
++ /*
++ * RCU users of rcu_dereference(rq->curr) may not see
++ * changes to task_struct made by pick_next_task().
++ */
++ RCU_INIT_POINTER(rq->curr, next);
++ /*
++ * The membarrier system call requires each architecture
++ * to have a full memory barrier after updating
++ * rq->curr, before returning to user-space.
++ *
++ * Here are the schemes providing that barrier on the
++ * various architectures:
++ * - mm ? switch_mm() : mmdrop() for x86, s390, sparc, PowerPC.
++ * switch_mm() rely on membarrier_arch_switch_mm() on PowerPC.
++ * - finish_lock_switch() for weakly-ordered
++ * architectures where spin_unlock is a full barrier,
++ * - switch_to() for arm64 (weakly-ordered, spin_unlock
++ * is a RELEASE barrier),
++ */
++ ++*switch_count;
++
++ trace_sched_switch(sched_mode & SM_MASK_PREEMPT, prev, next, prev_state);
++
++ /* Also unlocks the rq: */
++ rq = context_switch(rq, prev, next);
++
++ cpu = cpu_of(rq);
++ } else {
++ __balance_callbacks(rq);
++ raw_spin_unlock_irq(&rq->lock);
++ }
++
++#ifdef CONFIG_SCHED_SMT
++ sg_balance(rq, cpu);
++#endif
++}
++
++void __noreturn do_task_dead(void)
++{
++ /* Causes final put_task_struct in finish_task_switch(): */
++ set_special_state(TASK_DEAD);
++
++ /* Tell freezer to ignore us: */
++ current->flags |= PF_NOFREEZE;
++
++ __schedule(SM_NONE);
++ BUG();
++
++ /* Avoid "noreturn function does return" - but don't continue if BUG() is a NOP: */
++ for (;;)
++ cpu_relax();
++}
++
++static inline void sched_submit_work(struct task_struct *tsk)
++{
++ static DEFINE_WAIT_OVERRIDE_MAP(sched_map, LD_WAIT_CONFIG);
++ unsigned int task_flags;
++
++ /*
++ * Establish LD_WAIT_CONFIG context to ensure none of the code called
++ * will use a blocking primitive -- which would lead to recursion.
++ */
++ lock_map_acquire_try(&sched_map);
++
++ task_flags = tsk->flags;
++ /*
++ * If a worker goes to sleep, notify and ask workqueue whether it
++ * wants to wake up a task to maintain concurrency.
++ */
++ if (task_flags & PF_WQ_WORKER)
++ wq_worker_sleeping(tsk);
++ else if (task_flags & PF_IO_WORKER)
++ io_wq_worker_sleeping(tsk);
++
++ /*
++ * spinlock and rwlock must not flush block requests. This will
++ * deadlock if the callback attempts to acquire a lock which is
++ * already acquired.
++ */
++ SCHED_WARN_ON(current->__state & TASK_RTLOCK_WAIT);
++
++ /*
++ * If we are going to sleep and we have plugged IO queued,
++ * make sure to submit it to avoid deadlocks.
++ */
++ blk_flush_plug(tsk->plug, true);
++
++ lock_map_release(&sched_map);
++}
++
++static void sched_update_worker(struct task_struct *tsk)
++{
++ if (tsk->flags & (PF_WQ_WORKER | PF_IO_WORKER)) {
++ if (tsk->flags & PF_WQ_WORKER)
++ wq_worker_running(tsk);
++ else
++ io_wq_worker_running(tsk);
++ }
++}
++
++static __always_inline void __schedule_loop(unsigned int sched_mode)
++{
++ do {
++ preempt_disable();
++ __schedule(sched_mode);
++ sched_preempt_enable_no_resched();
++ } while (need_resched());
++}
++
++asmlinkage __visible void __sched schedule(void)
++{
++ struct task_struct *tsk = current;
++
++#ifdef CONFIG_RT_MUTEXES
++ lockdep_assert(!tsk->sched_rt_mutex);
++#endif
++
++ if (!task_is_running(tsk))
++ sched_submit_work(tsk);
++ __schedule_loop(SM_NONE);
++ sched_update_worker(tsk);
++}
++EXPORT_SYMBOL(schedule);
++
++/*
++ * synchronize_rcu_tasks() makes sure that no task is stuck in preempted
++ * state (have scheduled out non-voluntarily) by making sure that all
++ * tasks have either left the run queue or have gone into user space.
++ * As idle tasks do not do either, they must not ever be preempted
++ * (schedule out non-voluntarily).
++ *
++ * schedule_idle() is similar to schedule_preempt_disable() except that it
++ * never enables preemption because it does not call sched_submit_work().
++ */
++void __sched schedule_idle(void)
++{
++ /*
++ * As this skips calling sched_submit_work(), which the idle task does
++ * regardless because that function is a nop when the task is in a
++ * TASK_RUNNING state, make sure this isn't used someplace that the
++ * current task can be in any other state. Note, idle is always in the
++ * TASK_RUNNING state.
++ */
++ WARN_ON_ONCE(current->__state);
++ do {
++ __schedule(SM_NONE);
++ } while (need_resched());
++}
++
++#if defined(CONFIG_CONTEXT_TRACKING_USER) && !defined(CONFIG_HAVE_CONTEXT_TRACKING_USER_OFFSTACK)
++asmlinkage __visible void __sched schedule_user(void)
++{
++ /*
++ * If we come here after a random call to set_need_resched(),
++ * or we have been woken up remotely but the IPI has not yet arrived,
++ * we haven't yet exited the RCU idle mode. Do it here manually until
++ * we find a better solution.
++ *
++ * NB: There are buggy callers of this function. Ideally we
++ * should warn if prev_state != CONTEXT_USER, but that will trigger
++ * too frequently to make sense yet.
++ */
++ enum ctx_state prev_state = exception_enter();
++ schedule();
++ exception_exit(prev_state);
++}
++#endif
++
++/**
++ * schedule_preempt_disabled - called with preemption disabled
++ *
++ * Returns with preemption disabled. Note: preempt_count must be 1
++ */
++void __sched schedule_preempt_disabled(void)
++{
++ sched_preempt_enable_no_resched();
++ schedule();
++ preempt_disable();
++}
++
++#ifdef CONFIG_PREEMPT_RT
++void __sched notrace schedule_rtlock(void)
++{
++ __schedule_loop(SM_RTLOCK_WAIT);
++}
++NOKPROBE_SYMBOL(schedule_rtlock);
++#endif
++
++static void __sched notrace preempt_schedule_common(void)
++{
++ do {
++ /*
++ * Because the function tracer can trace preempt_count_sub()
++ * and it also uses preempt_enable/disable_notrace(), if
++ * NEED_RESCHED is set, the preempt_enable_notrace() called
++ * by the function tracer will call this function again and
++ * cause infinite recursion.
++ *
++ * Preemption must be disabled here before the function
++ * tracer can trace. Break up preempt_disable() into two
++ * calls. One to disable preemption without fear of being
++ * traced. The other to still record the preemption latency,
++ * which can also be traced by the function tracer.
++ */
++ preempt_disable_notrace();
++ preempt_latency_start(1);
++ __schedule(SM_PREEMPT);
++ preempt_latency_stop(1);
++ preempt_enable_no_resched_notrace();
++
++ /*
++ * Check again in case we missed a preemption opportunity
++ * between schedule and now.
++ */
++ } while (need_resched());
++}
++
++#ifdef CONFIG_PREEMPTION
++/*
++ * This is the entry point to schedule() from in-kernel preemption
++ * off of preempt_enable.
++ */
++asmlinkage __visible void __sched notrace preempt_schedule(void)
++{
++ /*
++ * If there is a non-zero preempt_count or interrupts are disabled,
++ * we do not want to preempt the current task. Just return..
++ */
++ if (likely(!preemptible()))
++ return;
++
++ preempt_schedule_common();
++}
++NOKPROBE_SYMBOL(preempt_schedule);
++EXPORT_SYMBOL(preempt_schedule);
++
++#ifdef CONFIG_PREEMPT_DYNAMIC
++#if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
++#ifndef preempt_schedule_dynamic_enabled
++#define preempt_schedule_dynamic_enabled preempt_schedule
++#define preempt_schedule_dynamic_disabled NULL
++#endif
++DEFINE_STATIC_CALL(preempt_schedule, preempt_schedule_dynamic_enabled);
++EXPORT_STATIC_CALL_TRAMP(preempt_schedule);
++#elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
++static DEFINE_STATIC_KEY_TRUE(sk_dynamic_preempt_schedule);
++void __sched notrace dynamic_preempt_schedule(void)
++{
++ if (!static_branch_unlikely(&sk_dynamic_preempt_schedule))
++ return;
++ preempt_schedule();
++}
++NOKPROBE_SYMBOL(dynamic_preempt_schedule);
++EXPORT_SYMBOL(dynamic_preempt_schedule);
++#endif
++#endif
++
++/**
++ * preempt_schedule_notrace - preempt_schedule called by tracing
++ *
++ * The tracing infrastructure uses preempt_enable_notrace to prevent
++ * recursion and tracing preempt enabling caused by the tracing
++ * infrastructure itself. But as tracing can happen in areas coming
++ * from userspace or just about to enter userspace, a preempt enable
++ * can occur before user_exit() is called. This will cause the scheduler
++ * to be called when the system is still in usermode.
++ *
++ * To prevent this, the preempt_enable_notrace will use this function
++ * instead of preempt_schedule() to exit user context if needed before
++ * calling the scheduler.
++ */
++asmlinkage __visible void __sched notrace preempt_schedule_notrace(void)
++{
++ enum ctx_state prev_ctx;
++
++ if (likely(!preemptible()))
++ return;
++
++ do {
++ /*
++ * Because the function tracer can trace preempt_count_sub()
++ * and it also uses preempt_enable/disable_notrace(), if
++ * NEED_RESCHED is set, the preempt_enable_notrace() called
++ * by the function tracer will call this function again and
++ * cause infinite recursion.
++ *
++ * Preemption must be disabled here before the function
++ * tracer can trace. Break up preempt_disable() into two
++ * calls. One to disable preemption without fear of being
++ * traced. The other to still record the preemption latency,
++ * which can also be traced by the function tracer.
++ */
++ preempt_disable_notrace();
++ preempt_latency_start(1);
++ /*
++ * Needs preempt disabled in case user_exit() is traced
++ * and the tracer calls preempt_enable_notrace() causing
++ * an infinite recursion.
++ */
++ prev_ctx = exception_enter();
++ __schedule(SM_PREEMPT);
++ exception_exit(prev_ctx);
++
++ preempt_latency_stop(1);
++ preempt_enable_no_resched_notrace();
++ } while (need_resched());
++}
++EXPORT_SYMBOL_GPL(preempt_schedule_notrace);
++
++#ifdef CONFIG_PREEMPT_DYNAMIC
++#if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
++#ifndef preempt_schedule_notrace_dynamic_enabled
++#define preempt_schedule_notrace_dynamic_enabled preempt_schedule_notrace
++#define preempt_schedule_notrace_dynamic_disabled NULL
++#endif
++DEFINE_STATIC_CALL(preempt_schedule_notrace, preempt_schedule_notrace_dynamic_enabled);
++EXPORT_STATIC_CALL_TRAMP(preempt_schedule_notrace);
++#elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
++static DEFINE_STATIC_KEY_TRUE(sk_dynamic_preempt_schedule_notrace);
++void __sched notrace dynamic_preempt_schedule_notrace(void)
++{
++ if (!static_branch_unlikely(&sk_dynamic_preempt_schedule_notrace))
++ return;
++ preempt_schedule_notrace();
++}
++NOKPROBE_SYMBOL(dynamic_preempt_schedule_notrace);
++EXPORT_SYMBOL(dynamic_preempt_schedule_notrace);
++#endif
++#endif
++
++#endif /* CONFIG_PREEMPTION */
++
++/*
++ * This is the entry point to schedule() from kernel preemption
++ * off of irq context.
++ * Note, that this is called and return with irqs disabled. This will
++ * protect us against recursive calling from irq.
++ */
++asmlinkage __visible void __sched preempt_schedule_irq(void)
++{
++ enum ctx_state prev_state;
++
++ /* Catch callers which need to be fixed */
++ BUG_ON(preempt_count() || !irqs_disabled());
++
++ prev_state = exception_enter();
++
++ do {
++ preempt_disable();
++ local_irq_enable();
++ __schedule(SM_PREEMPT);
++ local_irq_disable();
++ sched_preempt_enable_no_resched();
++ } while (need_resched());
++
++ exception_exit(prev_state);
++}
++
++int default_wake_function(wait_queue_entry_t *curr, unsigned mode, int wake_flags,
++ void *key)
++{
++ WARN_ON_ONCE(IS_ENABLED(CONFIG_SCHED_DEBUG) && wake_flags & ~(WF_SYNC|WF_CURRENT_CPU));
++ return try_to_wake_up(curr->private, mode, wake_flags);
++}
++EXPORT_SYMBOL(default_wake_function);
++
++static inline void check_task_changed(struct task_struct *p, struct rq *rq)
++{
++ /* Trigger resched if task sched_prio has been modified. */
++ if (task_on_rq_queued(p)) {
++ int idx;
++
++ update_rq_clock(rq);
++ idx = task_sched_prio_idx(p, rq);
++ if (idx != p->sq_idx) {
++ requeue_task(p, rq, idx);
++ wakeup_preempt(rq);
++ }
++ }
++}
++
++static void __setscheduler_prio(struct task_struct *p, int prio)
++{
++ p->prio = prio;
++}
++
++#ifdef CONFIG_RT_MUTEXES
++
++/*
++ * Would be more useful with typeof()/auto_type but they don't mix with
++ * bit-fields. Since it's a local thing, use int. Keep the generic sounding
++ * name such that if someone were to implement this function we get to compare
++ * notes.
++ */
++#define fetch_and_set(x, v) ({ int _x = (x); (x) = (v); _x; })
++
++void rt_mutex_pre_schedule(void)
++{
++ lockdep_assert(!fetch_and_set(current->sched_rt_mutex, 1));
++ sched_submit_work(current);
++}
++
++void rt_mutex_schedule(void)
++{
++ lockdep_assert(current->sched_rt_mutex);
++ __schedule_loop(SM_NONE);
++}
++
++void rt_mutex_post_schedule(void)
++{
++ sched_update_worker(current);
++ lockdep_assert(fetch_and_set(current->sched_rt_mutex, 0));
++}
++
++static inline int __rt_effective_prio(struct task_struct *pi_task, int prio)
++{
++ if (pi_task)
++ prio = min(prio, pi_task->prio);
++
++ return prio;
++}
++
++static inline int rt_effective_prio(struct task_struct *p, int prio)
++{
++ struct task_struct *pi_task = rt_mutex_get_top_task(p);
++
++ return __rt_effective_prio(pi_task, prio);
++}
++
++/*
++ * rt_mutex_setprio - set the current priority of a task
++ * @p: task to boost
++ * @pi_task: donor task
++ *
++ * This function changes the 'effective' priority of a task. It does
++ * not touch ->normal_prio like __setscheduler().
++ *
++ * Used by the rt_mutex code to implement priority inheritance
++ * logic. Call site only calls if the priority of the task changed.
++ */
++void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task)
++{
++ int prio;
++ struct rq *rq;
++ raw_spinlock_t *lock;
++
++ /* XXX used to be waiter->prio, not waiter->task->prio */
++ prio = __rt_effective_prio(pi_task, p->normal_prio);
++
++ /*
++ * If nothing changed; bail early.
++ */
++ if (p->pi_top_task == pi_task && prio == p->prio)
++ return;
++
++ rq = __task_access_lock(p, &lock);
++ /*
++ * Set under pi_lock && rq->lock, such that the value can be used under
++ * either lock.
++ *
++ * Note that there is loads of tricky to make this pointer cache work
++ * right. rt_mutex_slowunlock()+rt_mutex_postunlock() work together to
++ * ensure a task is de-boosted (pi_task is set to NULL) before the
++ * task is allowed to run again (and can exit). This ensures the pointer
++ * points to a blocked task -- which guarantees the task is present.
++ */
++ p->pi_top_task = pi_task;
++
++ /*
++ * For FIFO/RR we only need to set prio, if that matches we're done.
++ */
++ if (prio == p->prio)
++ goto out_unlock;
++
++ /*
++ * Idle task boosting is a nono in general. There is one
++ * exception, when PREEMPT_RT and NOHZ is active:
++ *
++ * The idle task calls get_next_timer_interrupt() and holds
++ * the timer wheel base->lock on the CPU and another CPU wants
++ * to access the timer (probably to cancel it). We can safely
++ * ignore the boosting request, as the idle CPU runs this code
++ * with interrupts disabled and will complete the lock
++ * protected section without being interrupted. So there is no
++ * real need to boost.
++ */
++ if (unlikely(p == rq->idle)) {
++ WARN_ON(p != rq->curr);
++ WARN_ON(p->pi_blocked_on);
++ goto out_unlock;
++ }
++
++ trace_sched_pi_setprio(p, pi_task);
++
++ __setscheduler_prio(p, prio);
++
++ check_task_changed(p, rq);
++out_unlock:
++ /* Avoid rq from going away on us: */
++ preempt_disable();
++
++ __balance_callbacks(rq);
++ __task_access_unlock(p, lock);
++
++ preempt_enable();
++}
++#else
++static inline int rt_effective_prio(struct task_struct *p, int prio)
++{
++ return prio;
++}
++#endif
++
++void set_user_nice(struct task_struct *p, long nice)
++{
++ unsigned long flags;
++ struct rq *rq;
++ raw_spinlock_t *lock;
++
++ if (task_nice(p) == nice || nice < MIN_NICE || nice > MAX_NICE)
++ return;
++ /*
++ * We have to be careful, if called from sys_setpriority(),
++ * the task might be in the middle of scheduling on another CPU.
++ */
++ raw_spin_lock_irqsave(&p->pi_lock, flags);
++ rq = __task_access_lock(p, &lock);
++
++ p->static_prio = NICE_TO_PRIO(nice);
++ /*
++ * The RT priorities are set via sched_setscheduler(), but we still
++ * allow the 'normal' nice value to be set - but as expected
++ * it won't have any effect on scheduling until the task is
++ * not SCHED_NORMAL/SCHED_BATCH:
++ */
++ if (task_has_rt_policy(p))
++ goto out_unlock;
++
++ p->prio = effective_prio(p);
++
++ check_task_changed(p, rq);
++out_unlock:
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++}
++EXPORT_SYMBOL(set_user_nice);
++
++/*
++ * is_nice_reduction - check if nice value is an actual reduction
++ *
++ * Similar to can_nice() but does not perform a capability check.
++ *
++ * @p: task
++ * @nice: nice value
++ */
++static bool is_nice_reduction(const struct task_struct *p, const int nice)
++{
++ /* Convert nice value [19,-20] to rlimit style value [1,40]: */
++ int nice_rlim = nice_to_rlimit(nice);
++
++ return (nice_rlim <= task_rlimit(p, RLIMIT_NICE));
++}
++
++/*
++ * can_nice - check if a task can reduce its nice value
++ * @p: task
++ * @nice: nice value
++ */
++int can_nice(const struct task_struct *p, const int nice)
++{
++ return is_nice_reduction(p, nice) || capable(CAP_SYS_NICE);
++}
++
++#ifdef __ARCH_WANT_SYS_NICE
++
++/*
++ * sys_nice - change the priority of the current process.
++ * @increment: priority increment
++ *
++ * sys_setpriority is a more generic, but much slower function that
++ * does similar things.
++ */
++SYSCALL_DEFINE1(nice, int, increment)
++{
++ long nice, retval;
++
++ /*
++ * Setpriority might change our priority at the same moment.
++ * We don't have to worry. Conceptually one call occurs first
++ * and we have a single winner.
++ */
++
++ increment = clamp(increment, -NICE_WIDTH, NICE_WIDTH);
++ nice = task_nice(current) + increment;
++
++ nice = clamp_val(nice, MIN_NICE, MAX_NICE);
++ if (increment < 0 && !can_nice(current, nice))
++ return -EPERM;
++
++ retval = security_task_setnice(current, nice);
++ if (retval)
++ return retval;
++
++ set_user_nice(current, nice);
++ return 0;
++}
++
++#endif
++
++/**
++ * task_prio - return the priority value of a given task.
++ * @p: the task in question.
++ *
++ * Return: The priority value as seen by users in /proc.
++ *
++ * sched policy return value kernel prio user prio/nice
++ *
++ * (BMQ)normal, batch, idle[0 ... 53] [100 ... 139] 0/[-20 ... 19]/[-7 ... 7]
++ * (PDS)normal, batch, idle[0 ... 39] 100 0/[-20 ... 19]
++ * fifo, rr [-1 ... -100] [99 ... 0] [0 ... 99]
++ */
++int task_prio(const struct task_struct *p)
++{
++ return (p->prio < MAX_RT_PRIO) ? p->prio - MAX_RT_PRIO :
++ task_sched_prio_normal(p, task_rq(p));
++}
++
++/**
++ * idle_cpu - is a given CPU idle currently?
++ * @cpu: the processor in question.
++ *
++ * Return: 1 if the CPU is currently idle. 0 otherwise.
++ */
++int idle_cpu(int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ if (rq->curr != rq->idle)
++ return 0;
++
++ if (rq->nr_running)
++ return 0;
++
++#ifdef CONFIG_SMP
++ if (rq->ttwu_pending)
++ return 0;
++#endif
++
++ return 1;
++}
++
++/**
++ * idle_task - return the idle task for a given CPU.
++ * @cpu: the processor in question.
++ *
++ * Return: The idle task for the cpu @cpu.
++ */
++struct task_struct *idle_task(int cpu)
++{
++ return cpu_rq(cpu)->idle;
++}
++
++/**
++ * find_process_by_pid - find a process with a matching PID value.
++ * @pid: the pid in question.
++ *
++ * The task of @pid, if found. %NULL otherwise.
++ */
++static inline struct task_struct *find_process_by_pid(pid_t pid)
++{
++ return pid ? find_task_by_vpid(pid) : current;
++}
++
++static struct task_struct *find_get_task(pid_t pid)
++{
++ struct task_struct *p;
++ guard(rcu)();
++
++ p = find_process_by_pid(pid);
++ if (likely(p))
++ get_task_struct(p);
++
++ return p;
++}
++
++DEFINE_CLASS(find_get_task, struct task_struct *, if (_T) put_task_struct(_T),
++ find_get_task(pid), pid_t pid)
++
++/*
++ * sched_setparam() passes in -1 for its policy, to let the functions
++ * it calls know not to change it.
++ */
++#define SETPARAM_POLICY -1
++
++static void __setscheduler_params(struct task_struct *p,
++ const struct sched_attr *attr)
++{
++ int policy = attr->sched_policy;
++
++ if (policy == SETPARAM_POLICY)
++ policy = p->policy;
++
++ p->policy = policy;
++
++ /*
++ * allow normal nice value to be set, but will not have any
++ * effect on scheduling until the task not SCHED_NORMAL/
++ * SCHED_BATCH
++ */
++ p->static_prio = NICE_TO_PRIO(attr->sched_nice);
++
++ /*
++ * __sched_setscheduler() ensures attr->sched_priority == 0 when
++ * !rt_policy. Always setting this ensures that things like
++ * getparam()/getattr() don't report silly values for !rt tasks.
++ */
++ p->rt_priority = attr->sched_priority;
++ p->normal_prio = normal_prio(p);
++}
++
++/*
++ * check the target process has a UID that matches the current process's
++ */
++static bool check_same_owner(struct task_struct *p)
++{
++ const struct cred *cred = current_cred(), *pcred;
++ guard(rcu)();
++
++ pcred = __task_cred(p);
++ return (uid_eq(cred->euid, pcred->euid) ||
++ uid_eq(cred->euid, pcred->uid));
++}
++
++/*
++ * Allow unprivileged RT tasks to decrease priority.
++ * Only issue a capable test if needed and only once to avoid an audit
++ * event on permitted non-privileged operations:
++ */
++static int user_check_sched_setscheduler(struct task_struct *p,
++ const struct sched_attr *attr,
++ int policy, int reset_on_fork)
++{
++ if (rt_policy(policy)) {
++ unsigned long rlim_rtprio = task_rlimit(p, RLIMIT_RTPRIO);
++
++ /* Can't set/change the rt policy: */
++ if (policy != p->policy && !rlim_rtprio)
++ goto req_priv;
++
++ /* Can't increase priority: */
++ if (attr->sched_priority > p->rt_priority &&
++ attr->sched_priority > rlim_rtprio)
++ goto req_priv;
++ }
++
++ /* Can't change other user's priorities: */
++ if (!check_same_owner(p))
++ goto req_priv;
++
++ /* Normal users shall not reset the sched_reset_on_fork flag: */
++ if (p->sched_reset_on_fork && !reset_on_fork)
++ goto req_priv;
++
++ return 0;
++
++req_priv:
++ if (!capable(CAP_SYS_NICE))
++ return -EPERM;
++
++ return 0;
++}
++
++static int __sched_setscheduler(struct task_struct *p,
++ const struct sched_attr *attr,
++ bool user, bool pi)
++{
++ const struct sched_attr dl_squash_attr = {
++ .size = sizeof(struct sched_attr),
++ .sched_policy = SCHED_FIFO,
++ .sched_nice = 0,
++ .sched_priority = 99,
++ };
++ int oldpolicy = -1, policy = attr->sched_policy;
++ int retval, newprio;
++ struct balance_callback *head;
++ unsigned long flags;
++ struct rq *rq;
++ int reset_on_fork;
++ raw_spinlock_t *lock;
++
++ /* The pi code expects interrupts enabled */
++ BUG_ON(pi && in_interrupt());
++
++ /*
++ * Alt schedule FW supports SCHED_DEADLINE by squash it as prio 0 SCHED_FIFO
++ */
++ if (unlikely(SCHED_DEADLINE == policy)) {
++ attr = &dl_squash_attr;
++ policy = attr->sched_policy;
++ }
++recheck:
++ /* Double check policy once rq lock held */
++ if (policy < 0) {
++ reset_on_fork = p->sched_reset_on_fork;
++ policy = oldpolicy = p->policy;
++ } else {
++ reset_on_fork = !!(attr->sched_flags & SCHED_RESET_ON_FORK);
++
++ if (policy > SCHED_IDLE)
++ return -EINVAL;
++ }
++
++ if (attr->sched_flags & ~(SCHED_FLAG_ALL))
++ return -EINVAL;
++
++ /*
++ * Valid priorities for SCHED_FIFO and SCHED_RR are
++ * 1..MAX_RT_PRIO-1, valid priority for SCHED_NORMAL and
++ * SCHED_BATCH and SCHED_IDLE is 0.
++ */
++ if (attr->sched_priority < 0 ||
++ (p->mm && attr->sched_priority > MAX_RT_PRIO - 1) ||
++ (!p->mm && attr->sched_priority > MAX_RT_PRIO - 1))
++ return -EINVAL;
++ if ((SCHED_RR == policy || SCHED_FIFO == policy) !=
++ (attr->sched_priority != 0))
++ return -EINVAL;
++
++ if (user) {
++ retval = user_check_sched_setscheduler(p, attr, policy, reset_on_fork);
++ if (retval)
++ return retval;
++
++ retval = security_task_setscheduler(p);
++ if (retval)
++ return retval;
++ }
++
++ /*
++ * Make sure no PI-waiters arrive (or leave) while we are
++ * changing the priority of the task:
++ */
++ raw_spin_lock_irqsave(&p->pi_lock, flags);
++
++ /*
++ * To be able to change p->policy safely, task_access_lock()
++ * must be called.
++ * IF use task_access_lock() here:
++ * For the task p which is not running, reading rq->stop is
++ * racy but acceptable as ->stop doesn't change much.
++ * An enhancemnet can be made to read rq->stop saftly.
++ */
++ rq = __task_access_lock(p, &lock);
++
++ /*
++ * Changing the policy of the stop threads its a very bad idea
++ */
++ if (p == rq->stop) {
++ retval = -EINVAL;
++ goto unlock;
++ }
++
++ /*
++ * If not changing anything there's no need to proceed further:
++ */
++ if (unlikely(policy == p->policy)) {
++ if (rt_policy(policy) && attr->sched_priority != p->rt_priority)
++ goto change;
++ if (!rt_policy(policy) &&
++ NICE_TO_PRIO(attr->sched_nice) != p->static_prio)
++ goto change;
++
++ p->sched_reset_on_fork = reset_on_fork;
++ retval = 0;
++ goto unlock;
++ }
++change:
++
++ /* Re-check policy now with rq lock held */
++ if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
++ policy = oldpolicy = -1;
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++ goto recheck;
++ }
++
++ p->sched_reset_on_fork = reset_on_fork;
++
++ newprio = __normal_prio(policy, attr->sched_priority, NICE_TO_PRIO(attr->sched_nice));
++ if (pi) {
++ /*
++ * Take priority boosted tasks into account. If the new
++ * effective priority is unchanged, we just store the new
++ * normal parameters and do not touch the scheduler class and
++ * the runqueue. This will be done when the task deboost
++ * itself.
++ */
++ newprio = rt_effective_prio(p, newprio);
++ }
++
++ if (!(attr->sched_flags & SCHED_FLAG_KEEP_PARAMS)) {
++ __setscheduler_params(p, attr);
++ __setscheduler_prio(p, newprio);
++ }
++
++ check_task_changed(p, rq);
++
++ /* Avoid rq from going away on us: */
++ preempt_disable();
++ head = splice_balance_callbacks(rq);
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++
++ if (pi)
++ rt_mutex_adjust_pi(p);
++
++ /* Run balance callbacks after we've adjusted the PI chain: */
++ balance_callbacks(rq, head);
++ preempt_enable();
++
++ return 0;
++
++unlock:
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++ return retval;
++}
++
++static int _sched_setscheduler(struct task_struct *p, int policy,
++ const struct sched_param *param, bool check)
++{
++ struct sched_attr attr = {
++ .sched_policy = policy,
++ .sched_priority = param->sched_priority,
++ .sched_nice = PRIO_TO_NICE(p->static_prio),
++ };
++
++ /* Fixup the legacy SCHED_RESET_ON_FORK hack. */
++ if ((policy != SETPARAM_POLICY) && (policy & SCHED_RESET_ON_FORK)) {
++ attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
++ policy &= ~SCHED_RESET_ON_FORK;
++ attr.sched_policy = policy;
++ }
++
++ return __sched_setscheduler(p, &attr, check, true);
++}
++
++/**
++ * sched_setscheduler - change the scheduling policy and/or RT priority of a thread.
++ * @p: the task in question.
++ * @policy: new policy.
++ * @param: structure containing the new RT priority.
++ *
++ * Use sched_set_fifo(), read its comment.
++ *
++ * Return: 0 on success. An error code otherwise.
++ *
++ * NOTE that the task may be already dead.
++ */
++int sched_setscheduler(struct task_struct *p, int policy,
++ const struct sched_param *param)
++{
++ return _sched_setscheduler(p, policy, param, true);
++}
++
++int sched_setattr(struct task_struct *p, const struct sched_attr *attr)
++{
++ return __sched_setscheduler(p, attr, true, true);
++}
++
++int sched_setattr_nocheck(struct task_struct *p, const struct sched_attr *attr)
++{
++ return __sched_setscheduler(p, attr, false, true);
++}
++EXPORT_SYMBOL_GPL(sched_setattr_nocheck);
++
++/**
++ * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace.
++ * @p: the task in question.
++ * @policy: new policy.
++ * @param: structure containing the new RT priority.
++ *
++ * Just like sched_setscheduler, only don't bother checking if the
++ * current context has permission. For example, this is needed in
++ * stop_machine(): we create temporary high priority worker threads,
++ * but our caller might not have that capability.
++ *
++ * Return: 0 on success. An error code otherwise.
++ */
++int sched_setscheduler_nocheck(struct task_struct *p, int policy,
++ const struct sched_param *param)
++{
++ return _sched_setscheduler(p, policy, param, false);
++}
++
++/*
++ * SCHED_FIFO is a broken scheduler model; that is, it is fundamentally
++ * incapable of resource management, which is the one thing an OS really should
++ * be doing.
++ *
++ * This is of course the reason it is limited to privileged users only.
++ *
++ * Worse still; it is fundamentally impossible to compose static priority
++ * workloads. You cannot take two correctly working static prio workloads
++ * and smash them together and still expect them to work.
++ *
++ * For this reason 'all' FIFO tasks the kernel creates are basically at:
++ *
++ * MAX_RT_PRIO / 2
++ *
++ * The administrator _MUST_ configure the system, the kernel simply doesn't
++ * know enough information to make a sensible choice.
++ */
++void sched_set_fifo(struct task_struct *p)
++{
++ struct sched_param sp = { .sched_priority = MAX_RT_PRIO / 2 };
++ WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0);
++}
++EXPORT_SYMBOL_GPL(sched_set_fifo);
++
++/*
++ * For when you don't much care about FIFO, but want to be above SCHED_NORMAL.
++ */
++void sched_set_fifo_low(struct task_struct *p)
++{
++ struct sched_param sp = { .sched_priority = 1 };
++ WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0);
++}
++EXPORT_SYMBOL_GPL(sched_set_fifo_low);
++
++void sched_set_normal(struct task_struct *p, int nice)
++{
++ struct sched_attr attr = {
++ .sched_policy = SCHED_NORMAL,
++ .sched_nice = nice,
++ };
++ WARN_ON_ONCE(sched_setattr_nocheck(p, &attr) != 0);
++}
++EXPORT_SYMBOL_GPL(sched_set_normal);
++
++static int
++do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
++{
++ struct sched_param lparam;
++
++ if (!param || pid < 0)
++ return -EINVAL;
++ if (copy_from_user(&lparam, param, sizeof(struct sched_param)))
++ return -EFAULT;
++
++ CLASS(find_get_task, p)(pid);
++ if (!p)
++ return -ESRCH;
++
++ return sched_setscheduler(p, policy, &lparam);
++}
++
++/*
++ * Mimics kernel/events/core.c perf_copy_attr().
++ */
++static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *attr)
++{
++ u32 size;
++ int ret;
++
++ /* Zero the full structure, so that a short copy will be nice: */
++ memset(attr, 0, sizeof(*attr));
++
++ ret = get_user(size, &uattr->size);
++ if (ret)
++ return ret;
++
++ /* ABI compatibility quirk: */
++ if (!size)
++ size = SCHED_ATTR_SIZE_VER0;
++
++ if (size < SCHED_ATTR_SIZE_VER0 || size > PAGE_SIZE)
++ goto err_size;
++
++ ret = copy_struct_from_user(attr, sizeof(*attr), uattr, size);
++ if (ret) {
++ if (ret == -E2BIG)
++ goto err_size;
++ return ret;
++ }
++
++ /*
++ * XXX: Do we want to be lenient like existing syscalls; or do we want
++ * to be strict and return an error on out-of-bounds values?
++ */
++ attr->sched_nice = clamp(attr->sched_nice, -20, 19);
++
++ /* sched/core.c uses zero here but we already know ret is zero */
++ return 0;
++
++err_size:
++ put_user(sizeof(*attr), &uattr->size);
++ return -E2BIG;
++}
++
++/**
++ * sys_sched_setscheduler - set/change the scheduler policy and RT priority
++ * @pid: the pid in question.
++ * @policy: new policy.
++ *
++ * Return: 0 on success. An error code otherwise.
++ * @param: structure containing the new RT priority.
++ */
++SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param)
++{
++ if (policy < 0)
++ return -EINVAL;
++
++ return do_sched_setscheduler(pid, policy, param);
++}
++
++/**
++ * sys_sched_setparam - set/change the RT priority of a thread
++ * @pid: the pid in question.
++ * @param: structure containing the new RT priority.
++ *
++ * Return: 0 on success. An error code otherwise.
++ */
++SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
++{
++ return do_sched_setscheduler(pid, SETPARAM_POLICY, param);
++}
++
++static void get_params(struct task_struct *p, struct sched_attr *attr)
++{
++ if (task_has_rt_policy(p))
++ attr->sched_priority = p->rt_priority;
++ else
++ attr->sched_nice = task_nice(p);
++}
++
++/**
++ * sys_sched_setattr - same as above, but with extended sched_attr
++ * @pid: the pid in question.
++ * @uattr: structure containing the extended parameters.
++ */
++SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr,
++ unsigned int, flags)
++{
++ struct sched_attr attr;
++ int retval;
++
++ if (!uattr || pid < 0 || flags)
++ return -EINVAL;
++
++ retval = sched_copy_attr(uattr, &attr);
++ if (retval)
++ return retval;
++
++ if ((int)attr.sched_policy < 0)
++ return -EINVAL;
++
++ CLASS(find_get_task, p)(pid);
++ if (!p)
++ return -ESRCH;
++
++ if (attr.sched_flags & SCHED_FLAG_KEEP_PARAMS)
++ get_params(p, &attr);
++
++ return sched_setattr(p, &attr);
++}
++
++/**
++ * sys_sched_getscheduler - get the policy (scheduling class) of a thread
++ * @pid: the pid in question.
++ *
++ * Return: On success, the policy of the thread. Otherwise, a negative error
++ * code.
++ */
++SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
++{
++ struct task_struct *p;
++ int retval = -EINVAL;
++
++ if (pid < 0)
++ return -ESRCH;
++
++ guard(rcu)();
++ p = find_process_by_pid(pid);
++ if (!p)
++ return -ESRCH;
++
++ retval = security_task_getscheduler(p);
++ if (!retval)
++ retval = p->policy;
++
++ return retval;
++}
++
++/**
++ * sys_sched_getscheduler - get the RT priority of a thread
++ * @pid: the pid in question.
++ * @param: structure containing the RT priority.
++ *
++ * Return: On success, 0 and the RT priority is in @param. Otherwise, an error
++ * code.
++ */
++SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
++{
++ struct sched_param lp = { .sched_priority = 0 };
++ struct task_struct *p;
++
++ if (!param || pid < 0)
++ return -EINVAL;
++
++ scoped_guard (rcu) {
++ int retval;
++
++ p = find_process_by_pid(pid);
++ if (!p)
++ return -EINVAL;
++
++ retval = security_task_getscheduler(p);
++ if (retval)
++ return retval;
++
++ if (task_has_rt_policy(p))
++ lp.sched_priority = p->rt_priority;
++ }
++
++ /*
++ * This one might sleep, we cannot do it with a spinlock held ...
++ */
++ return copy_to_user(param, &lp, sizeof(*param)) ? -EFAULT : 0;
++}
++
++/*
++ * Copy the kernel size attribute structure (which might be larger
++ * than what user-space knows about) to user-space.
++ *
++ * Note that all cases are valid: user-space buffer can be larger or
++ * smaller than the kernel-space buffer. The usual case is that both
++ * have the same size.
++ */
++static int
++sched_attr_copy_to_user(struct sched_attr __user *uattr,
++ struct sched_attr *kattr,
++ unsigned int usize)
++{
++ unsigned int ksize = sizeof(*kattr);
++
++ if (!access_ok(uattr, usize))
++ return -EFAULT;
++
++ /*
++ * sched_getattr() ABI forwards and backwards compatibility:
++ *
++ * If usize == ksize then we just copy everything to user-space and all is good.
++ *
++ * If usize < ksize then we only copy as much as user-space has space for,
++ * this keeps ABI compatibility as well. We skip the rest.
++ *
++ * If usize > ksize then user-space is using a newer version of the ABI,
++ * which part the kernel doesn't know about. Just ignore it - tooling can
++ * detect the kernel's knowledge of attributes from the attr->size value
++ * which is set to ksize in this case.
++ */
++ kattr->size = min(usize, ksize);
++
++ if (copy_to_user(uattr, kattr, kattr->size))
++ return -EFAULT;
++
++ return 0;
++}
++
++/**
++ * sys_sched_getattr - similar to sched_getparam, but with sched_attr
++ * @pid: the pid in question.
++ * @uattr: structure containing the extended parameters.
++ * @usize: sizeof(attr) for fwd/bwd comp.
++ * @flags: for future extension.
++ */
++SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
++ unsigned int, usize, unsigned int, flags)
++{
++ struct sched_attr kattr = { };
++ struct task_struct *p;
++ int retval;
++
++ if (!uattr || pid < 0 || usize > PAGE_SIZE ||
++ usize < SCHED_ATTR_SIZE_VER0 || flags)
++ return -EINVAL;
++
++ scoped_guard (rcu) {
++ p = find_process_by_pid(pid);
++ if (!p)
++ return -ESRCH;
++
++ retval = security_task_getscheduler(p);
++ if (retval)
++ return retval;
++
++ kattr.sched_policy = p->policy;
++ if (p->sched_reset_on_fork)
++ kattr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
++ get_params(p, &kattr);
++ kattr.sched_flags &= SCHED_FLAG_ALL;
++
++#ifdef CONFIG_UCLAMP_TASK
++ kattr.sched_util_min = p->uclamp_req[UCLAMP_MIN].value;
++ kattr.sched_util_max = p->uclamp_req[UCLAMP_MAX].value;
++#endif
++ }
++
++ return sched_attr_copy_to_user(uattr, &kattr, usize);
++}
++
++#ifdef CONFIG_SMP
++int dl_task_check_affinity(struct task_struct *p, const struct cpumask *mask)
++{
++ return 0;
++}
++#endif
++
++static int
++__sched_setaffinity(struct task_struct *p, struct affinity_context *ctx)
++{
++ int retval;
++ cpumask_var_t cpus_allowed, new_mask;
++
++ if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL))
++ return -ENOMEM;
++
++ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) {
++ retval = -ENOMEM;
++ goto out_free_cpus_allowed;
++ }
++
++ cpuset_cpus_allowed(p, cpus_allowed);
++ cpumask_and(new_mask, ctx->new_mask, cpus_allowed);
++
++ ctx->new_mask = new_mask;
++ ctx->flags |= SCA_CHECK;
++
++ retval = __set_cpus_allowed_ptr(p, ctx);
++ if (retval)
++ goto out_free_new_mask;
++
++ cpuset_cpus_allowed(p, cpus_allowed);
++ if (!cpumask_subset(new_mask, cpus_allowed)) {
++ /*
++ * We must have raced with a concurrent cpuset
++ * update. Just reset the cpus_allowed to the
++ * cpuset's cpus_allowed
++ */
++ cpumask_copy(new_mask, cpus_allowed);
++
++ /*
++ * If SCA_USER is set, a 2nd call to __set_cpus_allowed_ptr()
++ * will restore the previous user_cpus_ptr value.
++ *
++ * In the unlikely event a previous user_cpus_ptr exists,
++ * we need to further restrict the mask to what is allowed
++ * by that old user_cpus_ptr.
++ */
++ if (unlikely((ctx->flags & SCA_USER) && ctx->user_mask)) {
++ bool empty = !cpumask_and(new_mask, new_mask,
++ ctx->user_mask);
++
++ if (WARN_ON_ONCE(empty))
++ cpumask_copy(new_mask, cpus_allowed);
++ }
++ __set_cpus_allowed_ptr(p, ctx);
++ retval = -EINVAL;
++ }
++
++out_free_new_mask:
++ free_cpumask_var(new_mask);
++out_free_cpus_allowed:
++ free_cpumask_var(cpus_allowed);
++ return retval;
++}
++
++long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
++{
++ struct affinity_context ac;
++ struct cpumask *user_mask;
++ int retval;
++
++ CLASS(find_get_task, p)(pid);
++ if (!p)
++ return -ESRCH;
++
++ if (p->flags & PF_NO_SETAFFINITY)
++ return -EINVAL;
++
++ if (!check_same_owner(p)) {
++ guard(rcu)();
++ if (!ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE))
++ return -EPERM;
++ }
++
++ retval = security_task_setscheduler(p);
++ if (retval)
++ return retval;
++
++ /*
++ * With non-SMP configs, user_cpus_ptr/user_mask isn't used and
++ * alloc_user_cpus_ptr() returns NULL.
++ */
++ user_mask = alloc_user_cpus_ptr(NUMA_NO_NODE);
++ if (user_mask) {
++ cpumask_copy(user_mask, in_mask);
++ } else if (IS_ENABLED(CONFIG_SMP)) {
++ return -ENOMEM;
++ }
++
++ ac = (struct affinity_context){
++ .new_mask = in_mask,
++ .user_mask = user_mask,
++ .flags = SCA_USER,
++ };
++
++ retval = __sched_setaffinity(p, &ac);
++ kfree(ac.user_mask);
++
++ return retval;
++}
++
++static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len,
++ struct cpumask *new_mask)
++{
++ if (len < cpumask_size())
++ cpumask_clear(new_mask);
++ else if (len > cpumask_size())
++ len = cpumask_size();
++
++ return copy_from_user(new_mask, user_mask_ptr, len) ? -EFAULT : 0;
++}
++
++/**
++ * sys_sched_setaffinity - set the CPU affinity of a process
++ * @pid: pid of the process
++ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
++ * @user_mask_ptr: user-space pointer to the new CPU mask
++ *
++ * Return: 0 on success. An error code otherwise.
++ */
++SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len,
++ unsigned long __user *, user_mask_ptr)
++{
++ cpumask_var_t new_mask;
++ int retval;
++
++ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL))
++ return -ENOMEM;
++
++ retval = get_user_cpu_mask(user_mask_ptr, len, new_mask);
++ if (retval == 0)
++ retval = sched_setaffinity(pid, new_mask);
++ free_cpumask_var(new_mask);
++ return retval;
++}
++
++long sched_getaffinity(pid_t pid, cpumask_t *mask)
++{
++ struct task_struct *p;
++ int retval;
++
++ guard(rcu)();
++ p = find_process_by_pid(pid);
++ if (!p)
++ return -ESRCH;
++
++ retval = security_task_getscheduler(p);
++ if (retval)
++ return retval;
++
++ guard(raw_spinlock_irqsave)(&p->pi_lock);
++ cpumask_and(mask, &p->cpus_mask, cpu_active_mask);
++
++ return retval;
++}
++
++/**
++ * sys_sched_getaffinity - get the CPU affinity of a process
++ * @pid: pid of the process
++ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
++ * @user_mask_ptr: user-space pointer to hold the current CPU mask
++ *
++ * Return: size of CPU mask copied to user_mask_ptr on success. An
++ * error code otherwise.
++ */
++SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
++ unsigned long __user *, user_mask_ptr)
++{
++ int ret;
++ cpumask_var_t mask;
++
++ if ((len * BITS_PER_BYTE) < nr_cpu_ids)
++ return -EINVAL;
++ if (len & (sizeof(unsigned long)-1))
++ return -EINVAL;
++
++ if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
++ return -ENOMEM;
++
++ ret = sched_getaffinity(pid, mask);
++ if (ret == 0) {
++ unsigned int retlen = min(len, cpumask_size());
++
++ if (copy_to_user(user_mask_ptr, cpumask_bits(mask), retlen))
++ ret = -EFAULT;
++ else
++ ret = retlen;
++ }
++ free_cpumask_var(mask);
++
++ return ret;
++}
++
++static void do_sched_yield(void)
++{
++ struct rq *rq;
++ struct rq_flags rf;
++ struct task_struct *p;
++
++ if (!sched_yield_type)
++ return;
++
++ rq = this_rq_lock_irq(&rf);
++
++ schedstat_inc(rq->yld_count);
++
++ p = current;
++ if (rt_task(p)) {
++ if (task_on_rq_queued(p))
++ requeue_task(p, rq, task_sched_prio_idx(p, rq));
++ } else if (rq->nr_running > 1) {
++ if (1 == sched_yield_type) {
++ do_sched_yield_type_1(p, rq);
++ if (task_on_rq_queued(p))
++ requeue_task(p, rq, task_sched_prio_idx(p, rq));
++ } else if (2 == sched_yield_type) {
++ rq->skip = p;
++ }
++ }
++
++ preempt_disable();
++ raw_spin_unlock_irq(&rq->lock);
++ sched_preempt_enable_no_resched();
++
++ schedule();
++}
++
++/**
++ * sys_sched_yield - yield the current processor to other threads.
++ *
++ * This function yields the current CPU to other tasks. If there are no
++ * other threads running on this CPU then this function will return.
++ *
++ * Return: 0.
++ */
++SYSCALL_DEFINE0(sched_yield)
++{
++ do_sched_yield();
++ return 0;
++}
++
++#if !defined(CONFIG_PREEMPTION) || defined(CONFIG_PREEMPT_DYNAMIC)
++int __sched __cond_resched(void)
++{
++ if (should_resched(0)) {
++ preempt_schedule_common();
++ return 1;
++ }
++ /*
++ * In preemptible kernels, ->rcu_read_lock_nesting tells the tick
++ * whether the current CPU is in an RCU read-side critical section,
++ * so the tick can report quiescent states even for CPUs looping
++ * in kernel context. In contrast, in non-preemptible kernels,
++ * RCU readers leave no in-memory hints, which means that CPU-bound
++ * processes executing in kernel context might never report an
++ * RCU quiescent state. Therefore, the following code causes
++ * cond_resched() to report a quiescent state, but only when RCU
++ * is in urgent need of one.
++ */
++#ifndef CONFIG_PREEMPT_RCU
++ rcu_all_qs();
++#endif
++ return 0;
++}
++EXPORT_SYMBOL(__cond_resched);
++#endif
++
++#ifdef CONFIG_PREEMPT_DYNAMIC
++#if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
++#define cond_resched_dynamic_enabled __cond_resched
++#define cond_resched_dynamic_disabled ((void *)&__static_call_return0)
++DEFINE_STATIC_CALL_RET0(cond_resched, __cond_resched);
++EXPORT_STATIC_CALL_TRAMP(cond_resched);
++
++#define might_resched_dynamic_enabled __cond_resched
++#define might_resched_dynamic_disabled ((void *)&__static_call_return0)
++DEFINE_STATIC_CALL_RET0(might_resched, __cond_resched);
++EXPORT_STATIC_CALL_TRAMP(might_resched);
++#elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
++static DEFINE_STATIC_KEY_FALSE(sk_dynamic_cond_resched);
++int __sched dynamic_cond_resched(void)
++{
++ klp_sched_try_switch();
++ if (!static_branch_unlikely(&sk_dynamic_cond_resched))
++ return 0;
++ return __cond_resched();
++}
++EXPORT_SYMBOL(dynamic_cond_resched);
++
++static DEFINE_STATIC_KEY_FALSE(sk_dynamic_might_resched);
++int __sched dynamic_might_resched(void)
++{
++ if (!static_branch_unlikely(&sk_dynamic_might_resched))
++ return 0;
++ return __cond_resched();
++}
++EXPORT_SYMBOL(dynamic_might_resched);
++#endif
++#endif
++
++/*
++ * __cond_resched_lock() - if a reschedule is pending, drop the given lock,
++ * call schedule, and on return reacquire the lock.
++ *
++ * This works OK both with and without CONFIG_PREEMPTION. We do strange low-level
++ * operations here to prevent schedule() from being called twice (once via
++ * spin_unlock(), once by hand).
++ */
++int __cond_resched_lock(spinlock_t *lock)
++{
++ int resched = should_resched(PREEMPT_LOCK_OFFSET);
++ int ret = 0;
++
++ lockdep_assert_held(lock);
++
++ if (spin_needbreak(lock) || resched) {
++ spin_unlock(lock);
++ if (!_cond_resched())
++ cpu_relax();
++ ret = 1;
++ spin_lock(lock);
++ }
++ return ret;
++}
++EXPORT_SYMBOL(__cond_resched_lock);
++
++int __cond_resched_rwlock_read(rwlock_t *lock)
++{
++ int resched = should_resched(PREEMPT_LOCK_OFFSET);
++ int ret = 0;
++
++ lockdep_assert_held_read(lock);
++
++ if (rwlock_needbreak(lock) || resched) {
++ read_unlock(lock);
++ if (!_cond_resched())
++ cpu_relax();
++ ret = 1;
++ read_lock(lock);
++ }
++ return ret;
++}
++EXPORT_SYMBOL(__cond_resched_rwlock_read);
++
++int __cond_resched_rwlock_write(rwlock_t *lock)
++{
++ int resched = should_resched(PREEMPT_LOCK_OFFSET);
++ int ret = 0;
++
++ lockdep_assert_held_write(lock);
++
++ if (rwlock_needbreak(lock) || resched) {
++ write_unlock(lock);
++ if (!_cond_resched())
++ cpu_relax();
++ ret = 1;
++ write_lock(lock);
++ }
++ return ret;
++}
++EXPORT_SYMBOL(__cond_resched_rwlock_write);
++
++#ifdef CONFIG_PREEMPT_DYNAMIC
++
++#ifdef CONFIG_GENERIC_ENTRY
++#include <linux/entry-common.h>
++#endif
++
++/*
++ * SC:cond_resched
++ * SC:might_resched
++ * SC:preempt_schedule
++ * SC:preempt_schedule_notrace
++ * SC:irqentry_exit_cond_resched
++ *
++ *
++ * NONE:
++ * cond_resched <- __cond_resched
++ * might_resched <- RET0
++ * preempt_schedule <- NOP
++ * preempt_schedule_notrace <- NOP
++ * irqentry_exit_cond_resched <- NOP
++ *
++ * VOLUNTARY:
++ * cond_resched <- __cond_resched
++ * might_resched <- __cond_resched
++ * preempt_schedule <- NOP
++ * preempt_schedule_notrace <- NOP
++ * irqentry_exit_cond_resched <- NOP
++ *
++ * FULL:
++ * cond_resched <- RET0
++ * might_resched <- RET0
++ * preempt_schedule <- preempt_schedule
++ * preempt_schedule_notrace <- preempt_schedule_notrace
++ * irqentry_exit_cond_resched <- irqentry_exit_cond_resched
++ */
++
++enum {
++ preempt_dynamic_undefined = -1,
++ preempt_dynamic_none,
++ preempt_dynamic_voluntary,
++ preempt_dynamic_full,
++};
++
++int preempt_dynamic_mode = preempt_dynamic_undefined;
++
++int sched_dynamic_mode(const char *str)
++{
++ if (!strcmp(str, "none"))
++ return preempt_dynamic_none;
++
++ if (!strcmp(str, "voluntary"))
++ return preempt_dynamic_voluntary;
++
++ if (!strcmp(str, "full"))
++ return preempt_dynamic_full;
++
++ return -EINVAL;
++}
++
++#if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
++#define preempt_dynamic_enable(f) static_call_update(f, f##_dynamic_enabled)
++#define preempt_dynamic_disable(f) static_call_update(f, f##_dynamic_disabled)
++#elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
++#define preempt_dynamic_enable(f) static_key_enable(&sk_dynamic_##f.key)
++#define preempt_dynamic_disable(f) static_key_disable(&sk_dynamic_##f.key)
++#else
++#error "Unsupported PREEMPT_DYNAMIC mechanism"
++#endif
++
++static DEFINE_MUTEX(sched_dynamic_mutex);
++static bool klp_override;
++
++static void __sched_dynamic_update(int mode)
++{
++ /*
++ * Avoid {NONE,VOLUNTARY} -> FULL transitions from ever ending up in
++ * the ZERO state, which is invalid.
++ */
++ if (!klp_override)
++ preempt_dynamic_enable(cond_resched);
++ preempt_dynamic_enable(cond_resched);
++ preempt_dynamic_enable(might_resched);
++ preempt_dynamic_enable(preempt_schedule);
++ preempt_dynamic_enable(preempt_schedule_notrace);
++ preempt_dynamic_enable(irqentry_exit_cond_resched);
++
++ switch (mode) {
++ case preempt_dynamic_none:
++ if (!klp_override)
++ preempt_dynamic_enable(cond_resched);
++ preempt_dynamic_disable(might_resched);
++ preempt_dynamic_disable(preempt_schedule);
++ preempt_dynamic_disable(preempt_schedule_notrace);
++ preempt_dynamic_disable(irqentry_exit_cond_resched);
++ if (mode != preempt_dynamic_mode)
++ pr_info("Dynamic Preempt: none\n");
++ break;
++
++ case preempt_dynamic_voluntary:
++ if (!klp_override)
++ preempt_dynamic_enable(cond_resched);
++ preempt_dynamic_enable(might_resched);
++ preempt_dynamic_disable(preempt_schedule);
++ preempt_dynamic_disable(preempt_schedule_notrace);
++ preempt_dynamic_disable(irqentry_exit_cond_resched);
++ if (mode != preempt_dynamic_mode)
++ pr_info("Dynamic Preempt: voluntary\n");
++ break;
++
++ case preempt_dynamic_full:
++ if (!klp_override)
++ preempt_dynamic_enable(cond_resched);
++ preempt_dynamic_disable(might_resched);
++ preempt_dynamic_enable(preempt_schedule);
++ preempt_dynamic_enable(preempt_schedule_notrace);
++ preempt_dynamic_enable(irqentry_exit_cond_resched);
++ if (mode != preempt_dynamic_mode)
++ pr_info("Dynamic Preempt: full\n");
++ break;
++ }
++
++ preempt_dynamic_mode = mode;
++}
++
++void sched_dynamic_update(int mode)
++{
++ mutex_lock(&sched_dynamic_mutex);
++ __sched_dynamic_update(mode);
++ mutex_unlock(&sched_dynamic_mutex);
++}
++
++#ifdef CONFIG_HAVE_PREEMPT_DYNAMIC_CALL
++
++static int klp_cond_resched(void)
++{
++ __klp_sched_try_switch();
++ return __cond_resched();
++}
++
++void sched_dynamic_klp_enable(void)
++{
++ mutex_lock(&sched_dynamic_mutex);
++
++ klp_override = true;
++ static_call_update(cond_resched, klp_cond_resched);
++
++ mutex_unlock(&sched_dynamic_mutex);
++}
++
++void sched_dynamic_klp_disable(void)
++{
++ mutex_lock(&sched_dynamic_mutex);
++
++ klp_override = false;
++ __sched_dynamic_update(preempt_dynamic_mode);
++
++ mutex_unlock(&sched_dynamic_mutex);
++}
++
++#endif /* CONFIG_HAVE_PREEMPT_DYNAMIC_CALL */
++
++
++static int __init setup_preempt_mode(char *str)
++{
++ int mode = sched_dynamic_mode(str);
++ if (mode < 0) {
++ pr_warn("Dynamic Preempt: unsupported mode: %s\n", str);
++ return 0;
++ }
++
++ sched_dynamic_update(mode);
++ return 1;
++}
++__setup("preempt=", setup_preempt_mode);
++
++static void __init preempt_dynamic_init(void)
++{
++ if (preempt_dynamic_mode == preempt_dynamic_undefined) {
++ if (IS_ENABLED(CONFIG_PREEMPT_NONE)) {
++ sched_dynamic_update(preempt_dynamic_none);
++ } else if (IS_ENABLED(CONFIG_PREEMPT_VOLUNTARY)) {
++ sched_dynamic_update(preempt_dynamic_voluntary);
++ } else {
++ /* Default static call setting, nothing to do */
++ WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPT));
++ preempt_dynamic_mode = preempt_dynamic_full;
++ pr_info("Dynamic Preempt: full\n");
++ }
++ }
++}
++
++#define PREEMPT_MODEL_ACCESSOR(mode) \
++ bool preempt_model_##mode(void) \
++ { \
++ WARN_ON_ONCE(preempt_dynamic_mode == preempt_dynamic_undefined); \
++ return preempt_dynamic_mode == preempt_dynamic_##mode; \
++ } \
++ EXPORT_SYMBOL_GPL(preempt_model_##mode)
++
++PREEMPT_MODEL_ACCESSOR(none);
++PREEMPT_MODEL_ACCESSOR(voluntary);
++PREEMPT_MODEL_ACCESSOR(full);
++
++#else /* !CONFIG_PREEMPT_DYNAMIC */
++
++static inline void preempt_dynamic_init(void) { }
++
++#endif /* #ifdef CONFIG_PREEMPT_DYNAMIC */
++
++/**
++ * yield - yield the current processor to other threads.
++ *
++ * Do not ever use this function, there's a 99% chance you're doing it wrong.
++ *
++ * The scheduler is at all times free to pick the calling task as the most
++ * eligible task to run, if removing the yield() call from your code breaks
++ * it, it's already broken.
++ *
++ * Typical broken usage is:
++ *
++ * while (!event)
++ * yield();
++ *
++ * where one assumes that yield() will let 'the other' process run that will
++ * make event true. If the current task is a SCHED_FIFO task that will never
++ * happen. Never use yield() as a progress guarantee!!
++ *
++ * If you want to use yield() to wait for something, use wait_event().
++ * If you want to use yield() to be 'nice' for others, use cond_resched().
++ * If you still want to use yield(), do not!
++ */
++void __sched yield(void)
++{
++ set_current_state(TASK_RUNNING);
++ do_sched_yield();
++}
++EXPORT_SYMBOL(yield);
++
++/**
++ * yield_to - yield the current processor to another thread in
++ * your thread group, or accelerate that thread toward the
++ * processor it's on.
++ * @p: target task
++ * @preempt: whether task preemption is allowed or not
++ *
++ * It's the caller's job to ensure that the target task struct
++ * can't go away on us before we can do any checks.
++ *
++ * In Alt schedule FW, yield_to is not supported.
++ *
++ * Return:
++ * true (>0) if we indeed boosted the target task.
++ * false (0) if we failed to boost the target.
++ * -ESRCH if there's no task to yield to.
++ */
++int __sched yield_to(struct task_struct *p, bool preempt)
++{
++ return 0;
++}
++EXPORT_SYMBOL_GPL(yield_to);
++
++int io_schedule_prepare(void)
++{
++ int old_iowait = current->in_iowait;
++
++ current->in_iowait = 1;
++ blk_flush_plug(current->plug, true);
++ return old_iowait;
++}
++
++void io_schedule_finish(int token)
++{
++ current->in_iowait = token;
++}
++
++/*
++ * This task is about to go to sleep on IO. Increment rq->nr_iowait so
++ * that process accounting knows that this is a task in IO wait state.
++ *
++ * But don't do that if it is a deliberate, throttling IO wait (this task
++ * has set its backing_dev_info: the queue against which it should throttle)
++ */
++
++long __sched io_schedule_timeout(long timeout)
++{
++ int token;
++ long ret;
++
++ token = io_schedule_prepare();
++ ret = schedule_timeout(timeout);
++ io_schedule_finish(token);
++
++ return ret;
++}
++EXPORT_SYMBOL(io_schedule_timeout);
++
++void __sched io_schedule(void)
++{
++ int token;
++
++ token = io_schedule_prepare();
++ schedule();
++ io_schedule_finish(token);
++}
++EXPORT_SYMBOL(io_schedule);
++
++/**
++ * sys_sched_get_priority_max - return maximum RT priority.
++ * @policy: scheduling class.
++ *
++ * Return: On success, this syscall returns the maximum
++ * rt_priority that can be used by a given scheduling class.
++ * On failure, a negative error code is returned.
++ */
++SYSCALL_DEFINE1(sched_get_priority_max, int, policy)
++{
++ int ret = -EINVAL;
++
++ switch (policy) {
++ case SCHED_FIFO:
++ case SCHED_RR:
++ ret = MAX_RT_PRIO - 1;
++ break;
++ case SCHED_NORMAL:
++ case SCHED_BATCH:
++ case SCHED_IDLE:
++ ret = 0;
++ break;
++ }
++ return ret;
++}
++
++/**
++ * sys_sched_get_priority_min - return minimum RT priority.
++ * @policy: scheduling class.
++ *
++ * Return: On success, this syscall returns the minimum
++ * rt_priority that can be used by a given scheduling class.
++ * On failure, a negative error code is returned.
++ */
++SYSCALL_DEFINE1(sched_get_priority_min, int, policy)
++{
++ int ret = -EINVAL;
++
++ switch (policy) {
++ case SCHED_FIFO:
++ case SCHED_RR:
++ ret = 1;
++ break;
++ case SCHED_NORMAL:
++ case SCHED_BATCH:
++ case SCHED_IDLE:
++ ret = 0;
++ break;
++ }
++ return ret;
++}
++
++static int sched_rr_get_interval(pid_t pid, struct timespec64 *t)
++{
++ struct task_struct *p;
++ int retval;
++
++ alt_sched_debug();
++
++ if (pid < 0)
++ return -EINVAL;
++
++ guard(rcu)();
++ p = find_process_by_pid(pid);
++ if (!p)
++ return -EINVAL;
++
++ retval = security_task_getscheduler(p);
++ if (retval)
++ return retval;
++
++ *t = ns_to_timespec64(sysctl_sched_base_slice);
++ return 0;
++}
++
++/**
++ * sys_sched_rr_get_interval - return the default timeslice of a process.
++ * @pid: pid of the process.
++ * @interval: userspace pointer to the timeslice value.
++ *
++ *
++ * Return: On success, 0 and the timeslice is in @interval. Otherwise,
++ * an error code.
++ */
++SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
++ struct __kernel_timespec __user *, interval)
++{
++ struct timespec64 t;
++ int retval = sched_rr_get_interval(pid, &t);
++
++ if (retval == 0)
++ retval = put_timespec64(&t, interval);
++
++ return retval;
++}
++
++#ifdef CONFIG_COMPAT_32BIT_TIME
++SYSCALL_DEFINE2(sched_rr_get_interval_time32, pid_t, pid,
++ struct old_timespec32 __user *, interval)
++{
++ struct timespec64 t;
++ int retval = sched_rr_get_interval(pid, &t);
++
++ if (retval == 0)
++ retval = put_old_timespec32(&t, interval);
++ return retval;
++}
++#endif
++
++void sched_show_task(struct task_struct *p)
++{
++ unsigned long free = 0;
++ int ppid;
++
++ if (!try_get_task_stack(p))
++ return;
++
++ pr_info("task:%-15.15s state:%c", p->comm, task_state_to_char(p));
++
++ if (task_is_running(p))
++ pr_cont(" running task ");
++#ifdef CONFIG_DEBUG_STACK_USAGE
++ free = stack_not_used(p);
++#endif
++ ppid = 0;
++ rcu_read_lock();
++ if (pid_alive(p))
++ ppid = task_pid_nr(rcu_dereference(p->real_parent));
++ rcu_read_unlock();
++ pr_cont(" stack:%-5lu pid:%-5d tgid:%-5d ppid:%-6d flags:0x%08lx\n",
++ free, task_pid_nr(p), task_tgid_nr(p),
++ ppid, read_task_thread_flags(p));
++
++ print_worker_info(KERN_INFO, p);
++ print_stop_info(KERN_INFO, p);
++ show_stack(p, NULL, KERN_INFO);
++ put_task_stack(p);
++}
++EXPORT_SYMBOL_GPL(sched_show_task);
++
++static inline bool
++state_filter_match(unsigned long state_filter, struct task_struct *p)
++{
++ unsigned int state = READ_ONCE(p->__state);
++
++ /* no filter, everything matches */
++ if (!state_filter)
++ return true;
++
++ /* filter, but doesn't match */
++ if (!(state & state_filter))
++ return false;
++
++ /*
++ * When looking for TASK_UNINTERRUPTIBLE skip TASK_IDLE (allows
++ * TASK_KILLABLE).
++ */
++ if (state_filter == TASK_UNINTERRUPTIBLE && (state & TASK_NOLOAD))
++ return false;
++
++ return true;
++}
++
++
++void show_state_filter(unsigned int state_filter)
++{
++ struct task_struct *g, *p;
++
++ rcu_read_lock();
++ for_each_process_thread(g, p) {
++ /*
++ * reset the NMI-timeout, listing all files on a slow
++ * console might take a lot of time:
++ * Also, reset softlockup watchdogs on all CPUs, because
++ * another CPU might be blocked waiting for us to process
++ * an IPI.
++ */
++ touch_nmi_watchdog();
++ touch_all_softlockup_watchdogs();
++ if (state_filter_match(state_filter, p))
++ sched_show_task(p);
++ }
++
++#ifdef CONFIG_SCHED_DEBUG
++ /* TODO: Alt schedule FW should support this
++ if (!state_filter)
++ sysrq_sched_debug_show();
++ */
++#endif
++ rcu_read_unlock();
++ /*
++ * Only show locks if all tasks are dumped:
++ */
++ if (!state_filter)
++ debug_show_all_locks();
++}
++
++void dump_cpu_task(int cpu)
++{
++ if (cpu == smp_processor_id() && in_hardirq()) {
++ struct pt_regs *regs;
++
++ regs = get_irq_regs();
++ if (regs) {
++ show_regs(regs);
++ return;
++ }
++ }
++
++ if (trigger_single_cpu_backtrace(cpu))
++ return;
++
++ pr_info("Task dump for CPU %d:\n", cpu);
++ sched_show_task(cpu_curr(cpu));
++}
++
++/**
++ * init_idle - set up an idle thread for a given CPU
++ * @idle: task in question
++ * @cpu: CPU the idle task belongs to
++ *
++ * NOTE: this function does not set the idle thread's NEED_RESCHED
++ * flag, to make booting more robust.
++ */
++void __init init_idle(struct task_struct *idle, int cpu)
++{
++#ifdef CONFIG_SMP
++ struct affinity_context ac = (struct affinity_context) {
++ .new_mask = cpumask_of(cpu),
++ .flags = 0,
++ };
++#endif
++ struct rq *rq = cpu_rq(cpu);
++ unsigned long flags;
++
++ __sched_fork(0, idle);
++
++ raw_spin_lock_irqsave(&idle->pi_lock, flags);
++ raw_spin_lock(&rq->lock);
++
++ idle->last_ran = rq->clock_task;
++ idle->__state = TASK_RUNNING;
++ /*
++ * PF_KTHREAD should already be set at this point; regardless, make it
++ * look like a proper per-CPU kthread.
++ */
++ idle->flags |= PF_KTHREAD | PF_NO_SETAFFINITY;
++ kthread_set_per_cpu(idle, cpu);
++
++ sched_queue_init_idle(&rq->queue, idle);
++
++#ifdef CONFIG_SMP
++ /*
++ * It's possible that init_idle() gets called multiple times on a task,
++ * in that case do_set_cpus_allowed() will not do the right thing.
++ *
++ * And since this is boot we can forgo the serialisation.
++ */
++ set_cpus_allowed_common(idle, &ac);
++#endif
++
++ /* Silence PROVE_RCU */
++ rcu_read_lock();
++ __set_task_cpu(idle, cpu);
++ rcu_read_unlock();
++
++ rq->idle = idle;
++ rcu_assign_pointer(rq->curr, idle);
++ idle->on_cpu = 1;
++
++ raw_spin_unlock(&rq->lock);
++ raw_spin_unlock_irqrestore(&idle->pi_lock, flags);
++
++ /* Set the preempt count _outside_ the spinlocks! */
++ init_idle_preempt_count(idle, cpu);
++
++ ftrace_graph_init_idle_task(idle, cpu);
++ vtime_init_idle(idle, cpu);
++#ifdef CONFIG_SMP
++ sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu);
++#endif
++}
++
++#ifdef CONFIG_SMP
++
++int cpuset_cpumask_can_shrink(const struct cpumask __maybe_unused *cur,
++ const struct cpumask __maybe_unused *trial)
++{
++ return 1;
++}
++
++int task_can_attach(struct task_struct *p)
++{
++ int ret = 0;
++
++ /*
++ * Kthreads which disallow setaffinity shouldn't be moved
++ * to a new cpuset; we don't want to change their CPU
++ * affinity and isolating such threads by their set of
++ * allowed nodes is unnecessary. Thus, cpusets are not
++ * applicable for such threads. This prevents checking for
++ * success of set_cpus_allowed_ptr() on all attached tasks
++ * before cpus_mask may be changed.
++ */
++ if (p->flags & PF_NO_SETAFFINITY)
++ ret = -EINVAL;
++
++ return ret;
++}
++
++bool sched_smp_initialized __read_mostly;
++
++#ifdef CONFIG_HOTPLUG_CPU
++/*
++ * Ensures that the idle task is using init_mm right before its CPU goes
++ * offline.
++ */
++void idle_task_exit(void)
++{
++ struct mm_struct *mm = current->active_mm;
++
++ BUG_ON(current != this_rq()->idle);
++
++ if (mm != &init_mm) {
++ switch_mm(mm, &init_mm, current);
++ finish_arch_post_lock_switch();
++ }
++
++ /* finish_cpu(), as ran on the BP, will clean up the active_mm state */
++}
++
++static int __balance_push_cpu_stop(void *arg)
++{
++ struct task_struct *p = arg;
++ struct rq *rq = this_rq();
++ struct rq_flags rf;
++ int cpu;
++
++ raw_spin_lock_irq(&p->pi_lock);
++ rq_lock(rq, &rf);
++
++ update_rq_clock(rq);
++
++ if (task_rq(p) == rq && task_on_rq_queued(p)) {
++ cpu = select_fallback_rq(rq->cpu, p);
++ rq = __migrate_task(rq, p, cpu);
++ }
++
++ rq_unlock(rq, &rf);
++ raw_spin_unlock_irq(&p->pi_lock);
++
++ put_task_struct(p);
++
++ return 0;
++}
++
++static DEFINE_PER_CPU(struct cpu_stop_work, push_work);
++
++/*
++ * This is enabled below SCHED_AP_ACTIVE; when !cpu_active(), but only
++ * effective when the hotplug motion is down.
++ */
++static void balance_push(struct rq *rq)
++{
++ struct task_struct *push_task = rq->curr;
++
++ lockdep_assert_held(&rq->lock);
++
++ /*
++ * Ensure the thing is persistent until balance_push_set(.on = false);
++ */
++ rq->balance_callback = &balance_push_callback;
++
++ /*
++ * Only active while going offline and when invoked on the outgoing
++ * CPU.
++ */
++ if (!cpu_dying(rq->cpu) || rq != this_rq())
++ return;
++
++ /*
++ * Both the cpu-hotplug and stop task are in this case and are
++ * required to complete the hotplug process.
++ */
++ if (kthread_is_per_cpu(push_task) ||
++ is_migration_disabled(push_task)) {
++
++ /*
++ * If this is the idle task on the outgoing CPU try to wake
++ * up the hotplug control thread which might wait for the
++ * last task to vanish. The rcuwait_active() check is
++ * accurate here because the waiter is pinned on this CPU
++ * and can't obviously be running in parallel.
++ *
++ * On RT kernels this also has to check whether there are
++ * pinned and scheduled out tasks on the runqueue. They
++ * need to leave the migrate disabled section first.
++ */
++ if (!rq->nr_running && !rq_has_pinned_tasks(rq) &&
++ rcuwait_active(&rq->hotplug_wait)) {
++ raw_spin_unlock(&rq->lock);
++ rcuwait_wake_up(&rq->hotplug_wait);
++ raw_spin_lock(&rq->lock);
++ }
++ return;
++ }
++
++ get_task_struct(push_task);
++ /*
++ * Temporarily drop rq->lock such that we can wake-up the stop task.
++ * Both preemption and IRQs are still disabled.
++ */
++ preempt_disable();
++ raw_spin_unlock(&rq->lock);
++ stop_one_cpu_nowait(rq->cpu, __balance_push_cpu_stop, push_task,
++ this_cpu_ptr(&push_work));
++ preempt_enable();
++ /*
++ * At this point need_resched() is true and we'll take the loop in
++ * schedule(). The next pick is obviously going to be the stop task
++ * which kthread_is_per_cpu() and will push this task away.
++ */
++ raw_spin_lock(&rq->lock);
++}
++
++static void balance_push_set(int cpu, bool on)
++{
++ struct rq *rq = cpu_rq(cpu);
++ struct rq_flags rf;
++
++ rq_lock_irqsave(rq, &rf);
++ if (on) {
++ WARN_ON_ONCE(rq->balance_callback);
++ rq->balance_callback = &balance_push_callback;
++ } else if (rq->balance_callback == &balance_push_callback) {
++ rq->balance_callback = NULL;
++ }
++ rq_unlock_irqrestore(rq, &rf);
++}
++
++/*
++ * Invoked from a CPUs hotplug control thread after the CPU has been marked
++ * inactive. All tasks which are not per CPU kernel threads are either
++ * pushed off this CPU now via balance_push() or placed on a different CPU
++ * during wakeup. Wait until the CPU is quiescent.
++ */
++static void balance_hotplug_wait(void)
++{
++ struct rq *rq = this_rq();
++
++ rcuwait_wait_event(&rq->hotplug_wait,
++ rq->nr_running == 1 && !rq_has_pinned_tasks(rq),
++ TASK_UNINTERRUPTIBLE);
++}
++
++#else
++
++static void balance_push(struct rq *rq)
++{
++}
++
++static void balance_push_set(int cpu, bool on)
++{
++}
++
++static inline void balance_hotplug_wait(void)
++{
++}
++#endif /* CONFIG_HOTPLUG_CPU */
++
++static void set_rq_offline(struct rq *rq)
++{
++ if (rq->online) {
++ update_rq_clock(rq);
++ rq->online = false;
++ }
++}
++
++static void set_rq_online(struct rq *rq)
++{
++ if (!rq->online)
++ rq->online = true;
++}
++
++/*
++ * used to mark begin/end of suspend/resume:
++ */
++static int num_cpus_frozen;
++
++/*
++ * Update cpusets according to cpu_active mask. If cpusets are
++ * disabled, cpuset_update_active_cpus() becomes a simple wrapper
++ * around partition_sched_domains().
++ *
++ * If we come here as part of a suspend/resume, don't touch cpusets because we
++ * want to restore it back to its original state upon resume anyway.
++ */
++static void cpuset_cpu_active(void)
++{
++ if (cpuhp_tasks_frozen) {
++ /*
++ * num_cpus_frozen tracks how many CPUs are involved in suspend
++ * resume sequence. As long as this is not the last online
++ * operation in the resume sequence, just build a single sched
++ * domain, ignoring cpusets.
++ */
++ partition_sched_domains(1, NULL, NULL);
++ if (--num_cpus_frozen)
++ return;
++ /*
++ * This is the last CPU online operation. So fall through and
++ * restore the original sched domains by considering the
++ * cpuset configurations.
++ */
++ cpuset_force_rebuild();
++ }
++
++ cpuset_update_active_cpus();
++}
++
++static int cpuset_cpu_inactive(unsigned int cpu)
++{
++ if (!cpuhp_tasks_frozen) {
++ cpuset_update_active_cpus();
++ } else {
++ num_cpus_frozen++;
++ partition_sched_domains(1, NULL, NULL);
++ }
++ return 0;
++}
++
++int sched_cpu_activate(unsigned int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++ unsigned long flags;
++
++ /*
++ * Clear the balance_push callback and prepare to schedule
++ * regular tasks.
++ */
++ balance_push_set(cpu, false);
++
++#ifdef CONFIG_SCHED_SMT
++ /*
++ * When going up, increment the number of cores with SMT present.
++ */
++ if (cpumask_weight(cpu_smt_mask(cpu)) == 2)
++ static_branch_inc_cpuslocked(&sched_smt_present);
++#endif
++ set_cpu_active(cpu, true);
++
++ if (sched_smp_initialized)
++ cpuset_cpu_active();
++
++ /*
++ * Put the rq online, if not already. This happens:
++ *
++ * 1) In the early boot process, because we build the real domains
++ * after all cpus have been brought up.
++ *
++ * 2) At runtime, if cpuset_cpu_active() fails to rebuild the
++ * domains.
++ */
++ raw_spin_lock_irqsave(&rq->lock, flags);
++ set_rq_online(rq);
++ raw_spin_unlock_irqrestore(&rq->lock, flags);
++
++ return 0;
++}
++
++int sched_cpu_deactivate(unsigned int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++ unsigned long flags;
++ int ret;
++
++ set_cpu_active(cpu, false);
++
++ /*
++ * From this point forward, this CPU will refuse to run any task that
++ * is not: migrate_disable() or KTHREAD_IS_PER_CPU, and will actively
++ * push those tasks away until this gets cleared, see
++ * sched_cpu_dying().
++ */
++ balance_push_set(cpu, true);
++
++ /*
++ * We've cleared cpu_active_mask, wait for all preempt-disabled and RCU
++ * users of this state to go away such that all new such users will
++ * observe it.
++ *
++ * Specifically, we rely on ttwu to no longer target this CPU, see
++ * ttwu_queue_cond() and is_cpu_allowed().
++ *
++ * Do sync before park smpboot threads to take care the rcu boost case.
++ */
++ synchronize_rcu();
++
++ raw_spin_lock_irqsave(&rq->lock, flags);
++ set_rq_offline(rq);
++ raw_spin_unlock_irqrestore(&rq->lock, flags);
++
++#ifdef CONFIG_SCHED_SMT
++ /*
++ * When going down, decrement the number of cores with SMT present.
++ */
++ if (cpumask_weight(cpu_smt_mask(cpu)) == 2) {
++ static_branch_dec_cpuslocked(&sched_smt_present);
++ if (!static_branch_likely(&sched_smt_present))
++ cpumask_clear(&sched_sg_idle_mask);
++ }
++#endif
++
++ if (!sched_smp_initialized)
++ return 0;
++
++ ret = cpuset_cpu_inactive(cpu);
++ if (ret) {
++ balance_push_set(cpu, false);
++ set_cpu_active(cpu, true);
++ return ret;
++ }
++
++ return 0;
++}
++
++static void sched_rq_cpu_starting(unsigned int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ rq->calc_load_update = calc_load_update;
++}
++
++int sched_cpu_starting(unsigned int cpu)
++{
++ sched_rq_cpu_starting(cpu);
++ sched_tick_start(cpu);
++ return 0;
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++
++/*
++ * Invoked immediately before the stopper thread is invoked to bring the
++ * CPU down completely. At this point all per CPU kthreads except the
++ * hotplug thread (current) and the stopper thread (inactive) have been
++ * either parked or have been unbound from the outgoing CPU. Ensure that
++ * any of those which might be on the way out are gone.
++ *
++ * If after this point a bound task is being woken on this CPU then the
++ * responsible hotplug callback has failed to do it's job.
++ * sched_cpu_dying() will catch it with the appropriate fireworks.
++ */
++int sched_cpu_wait_empty(unsigned int cpu)
++{
++ balance_hotplug_wait();
++ return 0;
++}
++
++/*
++ * Since this CPU is going 'away' for a while, fold any nr_active delta we
++ * might have. Called from the CPU stopper task after ensuring that the
++ * stopper is the last running task on the CPU, so nr_active count is
++ * stable. We need to take the teardown thread which is calling this into
++ * account, so we hand in adjust = 1 to the load calculation.
++ *
++ * Also see the comment "Global load-average calculations".
++ */
++static void calc_load_migrate(struct rq *rq)
++{
++ long delta = calc_load_fold_active(rq, 1);
++
++ if (delta)
++ atomic_long_add(delta, &calc_load_tasks);
++}
++
++static void dump_rq_tasks(struct rq *rq, const char *loglvl)
++{
++ struct task_struct *g, *p;
++ int cpu = cpu_of(rq);
++
++ lockdep_assert_held(&rq->lock);
++
++ printk("%sCPU%d enqueued tasks (%u total):\n", loglvl, cpu, rq->nr_running);
++ for_each_process_thread(g, p) {
++ if (task_cpu(p) != cpu)
++ continue;
++
++ if (!task_on_rq_queued(p))
++ continue;
++
++ printk("%s\tpid: %d, name: %s\n", loglvl, p->pid, p->comm);
++ }
++}
++
++int sched_cpu_dying(unsigned int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++ unsigned long flags;
++
++ /* Handle pending wakeups and then migrate everything off */
++ sched_tick_stop(cpu);
++
++ raw_spin_lock_irqsave(&rq->lock, flags);
++ if (rq->nr_running != 1 || rq_has_pinned_tasks(rq)) {
++ WARN(true, "Dying CPU not properly vacated!");
++ dump_rq_tasks(rq, KERN_WARNING);
++ }
++ raw_spin_unlock_irqrestore(&rq->lock, flags);
++
++ calc_load_migrate(rq);
++ hrtick_clear(rq);
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_SMP
++static void sched_init_topology_cpumask_early(void)
++{
++ int cpu;
++ cpumask_t *tmp;
++
++ for_each_possible_cpu(cpu) {
++ /* init topo masks */
++ tmp = per_cpu(sched_cpu_topo_masks, cpu);
++
++ cpumask_copy(tmp, cpumask_of(cpu));
++ tmp++;
++ cpumask_copy(tmp, cpu_possible_mask);
++ per_cpu(sched_cpu_llc_mask, cpu) = tmp;
++ per_cpu(sched_cpu_topo_end_mask, cpu) = ++tmp;
++ /*per_cpu(sd_llc_id, cpu) = cpu;*/
++ }
++}
++
++#define TOPOLOGY_CPUMASK(name, mask, last)\
++ if (cpumask_and(topo, topo, mask)) { \
++ cpumask_copy(topo, mask); \
++ printk(KERN_INFO "sched: cpu#%02d topo: 0x%08lx - "#name, \
++ cpu, (topo++)->bits[0]); \
++ } \
++ if (!last) \
++ bitmap_complement(cpumask_bits(topo), cpumask_bits(mask), \
++ nr_cpumask_bits);
++
++static void sched_init_topology_cpumask(void)
++{
++ int cpu;
++ cpumask_t *topo;
++
++ for_each_online_cpu(cpu) {
++ /* take chance to reset time slice for idle tasks */
++ cpu_rq(cpu)->idle->time_slice = sysctl_sched_base_slice;
++
++ topo = per_cpu(sched_cpu_topo_masks, cpu) + 1;
++
++ bitmap_complement(cpumask_bits(topo), cpumask_bits(cpumask_of(cpu)),
++ nr_cpumask_bits);
++#ifdef CONFIG_SCHED_SMT
++ TOPOLOGY_CPUMASK(smt, topology_sibling_cpumask(cpu), false);
++#endif
++ per_cpu(sd_llc_id, cpu) = cpumask_first(cpu_coregroup_mask(cpu));
++ per_cpu(sched_cpu_llc_mask, cpu) = topo;
++ TOPOLOGY_CPUMASK(coregroup, cpu_coregroup_mask(cpu), false);
++
++ TOPOLOGY_CPUMASK(core, topology_core_cpumask(cpu), false);
++
++ TOPOLOGY_CPUMASK(others, cpu_online_mask, true);
++
++ per_cpu(sched_cpu_topo_end_mask, cpu) = topo;
++ printk(KERN_INFO "sched: cpu#%02d llc_id = %d, llc_mask idx = %d\n",
++ cpu, per_cpu(sd_llc_id, cpu),
++ (int) (per_cpu(sched_cpu_llc_mask, cpu) -
++ per_cpu(sched_cpu_topo_masks, cpu)));
++ }
++}
++#endif
++
++void __init sched_init_smp(void)
++{
++ /* Move init over to a non-isolated CPU */
++ if (set_cpus_allowed_ptr(current, housekeeping_cpumask(HK_TYPE_DOMAIN)) < 0)
++ BUG();
++ current->flags &= ~PF_NO_SETAFFINITY;
++
++ sched_init_topology_cpumask();
++
++ sched_smp_initialized = true;
++}
++
++static int __init migration_init(void)
++{
++ sched_cpu_starting(smp_processor_id());
++ return 0;
++}
++early_initcall(migration_init);
++
++#else
++void __init sched_init_smp(void)
++{
++ cpu_rq(0)->idle->time_slice = sysctl_sched_base_slice;
++}
++#endif /* CONFIG_SMP */
++
++int in_sched_functions(unsigned long addr)
++{
++ return in_lock_functions(addr) ||
++ (addr >= (unsigned long)__sched_text_start
++ && addr < (unsigned long)__sched_text_end);
++}
++
++#ifdef CONFIG_CGROUP_SCHED
++/*
++ * Default task group.
++ * Every task in system belongs to this group at bootup.
++ */
++struct task_group root_task_group;
++LIST_HEAD(task_groups);
++
++/* Cacheline aligned slab cache for task_group */
++static struct kmem_cache *task_group_cache __ro_after_init;
++#endif /* CONFIG_CGROUP_SCHED */
++
++void __init sched_init(void)
++{
++ int i;
++ struct rq *rq;
++
++ printk(KERN_INFO "sched/alt: "ALT_SCHED_NAME" CPU Scheduler "ALT_SCHED_VERSION\
++ " by Alfred Chen.\n");
++
++ wait_bit_init();
++
++#ifdef CONFIG_SMP
++ for (i = 0; i < SCHED_QUEUE_BITS; i++)
++ cpumask_copy(sched_preempt_mask + i, cpu_present_mask);
++#endif
++
++#ifdef CONFIG_CGROUP_SCHED
++ task_group_cache = KMEM_CACHE(task_group, 0);
++
++ list_add(&root_task_group.list, &task_groups);
++ INIT_LIST_HEAD(&root_task_group.children);
++ INIT_LIST_HEAD(&root_task_group.siblings);
++#endif /* CONFIG_CGROUP_SCHED */
++ for_each_possible_cpu(i) {
++ rq = cpu_rq(i);
++
++ sched_queue_init(&rq->queue);
++ rq->prio = IDLE_TASK_SCHED_PRIO;
++ rq->skip = NULL;
++
++ raw_spin_lock_init(&rq->lock);
++ rq->nr_running = rq->nr_uninterruptible = 0;
++ rq->calc_load_active = 0;
++ rq->calc_load_update = jiffies + LOAD_FREQ;
++#ifdef CONFIG_SMP
++ rq->online = false;
++ rq->cpu = i;
++
++#ifdef CONFIG_SCHED_SMT
++ rq->active_balance = 0;
++#endif
++
++#ifdef CONFIG_NO_HZ_COMMON
++ INIT_CSD(&rq->nohz_csd, nohz_csd_func, rq);
++#endif
++ rq->balance_callback = &balance_push_callback;
++#ifdef CONFIG_HOTPLUG_CPU
++ rcuwait_init(&rq->hotplug_wait);
++#endif
++#endif /* CONFIG_SMP */
++ rq->nr_switches = 0;
++
++ hrtick_rq_init(rq);
++ atomic_set(&rq->nr_iowait, 0);
++
++ zalloc_cpumask_var_node(&rq->scratch_mask, GFP_KERNEL, cpu_to_node(i));
++ }
++#ifdef CONFIG_SMP
++ /* Set rq->online for cpu 0 */
++ cpu_rq(0)->online = true;
++#endif
++ /*
++ * The boot idle thread does lazy MMU switching as well:
++ */
++ mmgrab(&init_mm);
++ enter_lazy_tlb(&init_mm, current);
++
++ /*
++ * The idle task doesn't need the kthread struct to function, but it
++ * is dressed up as a per-CPU kthread and thus needs to play the part
++ * if we want to avoid special-casing it in code that deals with per-CPU
++ * kthreads.
++ */
++ WARN_ON(!set_kthread_struct(current));
++
++ /*
++ * Make us the idle thread. Technically, schedule() should not be
++ * called from this thread, however somewhere below it might be,
++ * but because we are the idle thread, we just pick up running again
++ * when this runqueue becomes "idle".
++ */
++ init_idle(current, smp_processor_id());
++
++ calc_load_update = jiffies + LOAD_FREQ;
++
++#ifdef CONFIG_SMP
++ idle_thread_set_boot_cpu();
++ balance_push_set(smp_processor_id(), false);
++
++ sched_init_topology_cpumask_early();
++#endif /* SMP */
++
++ preempt_dynamic_init();
++}
++
++#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
++
++void __might_sleep(const char *file, int line)
++{
++ unsigned int state = get_current_state();
++ /*
++ * Blocking primitives will set (and therefore destroy) current->state,
++ * since we will exit with TASK_RUNNING make sure we enter with it,
++ * otherwise we will destroy state.
++ */
++ WARN_ONCE(state != TASK_RUNNING && current->task_state_change,
++ "do not call blocking ops when !TASK_RUNNING; "
++ "state=%x set at [<%p>] %pS\n", state,
++ (void *)current->task_state_change,
++ (void *)current->task_state_change);
++
++ __might_resched(file, line, 0);
++}
++EXPORT_SYMBOL(__might_sleep);
++
++static void print_preempt_disable_ip(int preempt_offset, unsigned long ip)
++{
++ if (!IS_ENABLED(CONFIG_DEBUG_PREEMPT))
++ return;
++
++ if (preempt_count() == preempt_offset)
++ return;
++
++ pr_err("Preemption disabled at:");
++ print_ip_sym(KERN_ERR, ip);
++}
++
++static inline bool resched_offsets_ok(unsigned int offsets)
++{
++ unsigned int nested = preempt_count();
++
++ nested += rcu_preempt_depth() << MIGHT_RESCHED_RCU_SHIFT;
++
++ return nested == offsets;
++}
++
++void __might_resched(const char *file, int line, unsigned int offsets)
++{
++ /* Ratelimiting timestamp: */
++ static unsigned long prev_jiffy;
++
++ unsigned long preempt_disable_ip;
++
++ /* WARN_ON_ONCE() by default, no rate limit required: */
++ rcu_sleep_check();
++
++ if ((resched_offsets_ok(offsets) && !irqs_disabled() &&
++ !is_idle_task(current) && !current->non_block_count) ||
++ system_state == SYSTEM_BOOTING || system_state > SYSTEM_RUNNING ||
++ oops_in_progress)
++ return;
++ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
++ return;
++ prev_jiffy = jiffies;
++
++ /* Save this before calling printk(), since that will clobber it: */
++ preempt_disable_ip = get_preempt_disable_ip(current);
++
++ pr_err("BUG: sleeping function called from invalid context at %s:%d\n",
++ file, line);
++ pr_err("in_atomic(): %d, irqs_disabled(): %d, non_block: %d, pid: %d, name: %s\n",
++ in_atomic(), irqs_disabled(), current->non_block_count,
++ current->pid, current->comm);
++ pr_err("preempt_count: %x, expected: %x\n", preempt_count(),
++ offsets & MIGHT_RESCHED_PREEMPT_MASK);
++
++ if (IS_ENABLED(CONFIG_PREEMPT_RCU)) {
++ pr_err("RCU nest depth: %d, expected: %u\n",
++ rcu_preempt_depth(), offsets >> MIGHT_RESCHED_RCU_SHIFT);
++ }
++
++ if (task_stack_end_corrupted(current))
++ pr_emerg("Thread overran stack, or stack corrupted\n");
++
++ debug_show_held_locks(current);
++ if (irqs_disabled())
++ print_irqtrace_events(current);
++
++ print_preempt_disable_ip(offsets & MIGHT_RESCHED_PREEMPT_MASK,
++ preempt_disable_ip);
++
++ dump_stack();
++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
++}
++EXPORT_SYMBOL(__might_resched);
++
++void __cant_sleep(const char *file, int line, int preempt_offset)
++{
++ static unsigned long prev_jiffy;
++
++ if (irqs_disabled())
++ return;
++
++ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT))
++ return;
++
++ if (preempt_count() > preempt_offset)
++ return;
++
++ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
++ return;
++ prev_jiffy = jiffies;
++
++ printk(KERN_ERR "BUG: assuming atomic context at %s:%d\n", file, line);
++ printk(KERN_ERR "in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n",
++ in_atomic(), irqs_disabled(),
++ current->pid, current->comm);
++
++ debug_show_held_locks(current);
++ dump_stack();
++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
++}
++EXPORT_SYMBOL_GPL(__cant_sleep);
++
++#ifdef CONFIG_SMP
++void __cant_migrate(const char *file, int line)
++{
++ static unsigned long prev_jiffy;
++
++ if (irqs_disabled())
++ return;
++
++ if (is_migration_disabled(current))
++ return;
++
++ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT))
++ return;
++
++ if (preempt_count() > 0)
++ return;
++
++ if (current->migration_flags & MDF_FORCE_ENABLED)
++ return;
++
++ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
++ return;
++ prev_jiffy = jiffies;
++
++ pr_err("BUG: assuming non migratable context at %s:%d\n", file, line);
++ pr_err("in_atomic(): %d, irqs_disabled(): %d, migration_disabled() %u pid: %d, name: %s\n",
++ in_atomic(), irqs_disabled(), is_migration_disabled(current),
++ current->pid, current->comm);
++
++ debug_show_held_locks(current);
++ dump_stack();
++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
++}
++EXPORT_SYMBOL_GPL(__cant_migrate);
++#endif
++#endif
++
++#ifdef CONFIG_MAGIC_SYSRQ
++void normalize_rt_tasks(void)
++{
++ struct task_struct *g, *p;
++ struct sched_attr attr = {
++ .sched_policy = SCHED_NORMAL,
++ };
++
++ read_lock(&tasklist_lock);
++ for_each_process_thread(g, p) {
++ /*
++ * Only normalize user tasks:
++ */
++ if (p->flags & PF_KTHREAD)
++ continue;
++
++ schedstat_set(p->stats.wait_start, 0);
++ schedstat_set(p->stats.sleep_start, 0);
++ schedstat_set(p->stats.block_start, 0);
++
++ if (!rt_task(p)) {
++ /*
++ * Renice negative nice level userspace
++ * tasks back to 0:
++ */
++ if (task_nice(p) < 0)
++ set_user_nice(p, 0);
++ continue;
++ }
++
++ __sched_setscheduler(p, &attr, false, false);
++ }
++ read_unlock(&tasklist_lock);
++}
++#endif /* CONFIG_MAGIC_SYSRQ */
++
++#if defined(CONFIG_KGDB_KDB)
++/*
++ * These functions are only useful for kdb.
++ *
++ * They can only be called when the whole system has been
++ * stopped - every CPU needs to be quiescent, and no scheduling
++ * activity can take place. Using them for anything else would
++ * be a serious bug, and as a result, they aren't even visible
++ * under any other configuration.
++ */
++
++/**
++ * curr_task - return the current task for a given CPU.
++ * @cpu: the processor in question.
++ *
++ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
++ *
++ * Return: The current task for @cpu.
++ */
++struct task_struct *curr_task(int cpu)
++{
++ return cpu_curr(cpu);
++}
++
++#endif /* defined(CONFIG_KGDB_KDB) */
++
++#ifdef CONFIG_CGROUP_SCHED
++static void sched_free_group(struct task_group *tg)
++{
++ kmem_cache_free(task_group_cache, tg);
++}
++
++static void sched_free_group_rcu(struct rcu_head *rhp)
++{
++ sched_free_group(container_of(rhp, struct task_group, rcu));
++}
++
++static void sched_unregister_group(struct task_group *tg)
++{
++ /*
++ * We have to wait for yet another RCU grace period to expire, as
++ * print_cfs_stats() might run concurrently.
++ */
++ call_rcu(&tg->rcu, sched_free_group_rcu);
++}
++
++/* allocate runqueue etc for a new task group */
++struct task_group *sched_create_group(struct task_group *parent)
++{
++ struct task_group *tg;
++
++ tg = kmem_cache_alloc(task_group_cache, GFP_KERNEL | __GFP_ZERO);
++ if (!tg)
++ return ERR_PTR(-ENOMEM);
++
++ return tg;
++}
++
++void sched_online_group(struct task_group *tg, struct task_group *parent)
++{
++}
++
++/* rcu callback to free various structures associated with a task group */
++static void sched_unregister_group_rcu(struct rcu_head *rhp)
++{
++ /* Now it should be safe to free those cfs_rqs: */
++ sched_unregister_group(container_of(rhp, struct task_group, rcu));
++}
++
++void sched_destroy_group(struct task_group *tg)
++{
++ /* Wait for possible concurrent references to cfs_rqs complete: */
++ call_rcu(&tg->rcu, sched_unregister_group_rcu);
++}
++
++void sched_release_group(struct task_group *tg)
++{
++}
++
++static inline struct task_group *css_tg(struct cgroup_subsys_state *css)
++{
++ return css ? container_of(css, struct task_group, css) : NULL;
++}
++
++static struct cgroup_subsys_state *
++cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
++{
++ struct task_group *parent = css_tg(parent_css);
++ struct task_group *tg;
++
++ if (!parent) {
++ /* This is early initialization for the top cgroup */
++ return &root_task_group.css;
++ }
++
++ tg = sched_create_group(parent);
++ if (IS_ERR(tg))
++ return ERR_PTR(-ENOMEM);
++ return &tg->css;
++}
++
++/* Expose task group only after completing cgroup initialization */
++static int cpu_cgroup_css_online(struct cgroup_subsys_state *css)
++{
++ struct task_group *tg = css_tg(css);
++ struct task_group *parent = css_tg(css->parent);
++
++ if (parent)
++ sched_online_group(tg, parent);
++ return 0;
++}
++
++static void cpu_cgroup_css_released(struct cgroup_subsys_state *css)
++{
++ struct task_group *tg = css_tg(css);
++
++ sched_release_group(tg);
++}
++
++static void cpu_cgroup_css_free(struct cgroup_subsys_state *css)
++{
++ struct task_group *tg = css_tg(css);
++
++ /*
++ * Relies on the RCU grace period between css_released() and this.
++ */
++ sched_unregister_group(tg);
++}
++
++#ifdef CONFIG_RT_GROUP_SCHED
++static int cpu_cgroup_can_attach(struct cgroup_taskset *tset)
++{
++ return 0;
++}
++#endif
++
++static void cpu_cgroup_attach(struct cgroup_taskset *tset)
++{
++}
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++static DEFINE_MUTEX(shares_mutex);
++
++int sched_group_set_shares(struct task_group *tg, unsigned long shares)
++{
++ /*
++ * We can't change the weight of the root cgroup.
++ */
++ if (&root_task_group == tg)
++ return -EINVAL;
++
++ shares = clamp(shares, scale_load(MIN_SHARES), scale_load(MAX_SHARES));
++
++ mutex_lock(&shares_mutex);
++ if (tg->shares == shares)
++ goto done;
++
++ tg->shares = shares;
++done:
++ mutex_unlock(&shares_mutex);
++ return 0;
++}
++
++static int cpu_shares_write_u64(struct cgroup_subsys_state *css,
++ struct cftype *cftype, u64 shareval)
++{
++ if (shareval > scale_load_down(ULONG_MAX))
++ shareval = MAX_SHARES;
++ return sched_group_set_shares(css_tg(css), scale_load(shareval));
++}
++
++static u64 cpu_shares_read_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ struct task_group *tg = css_tg(css);
++
++ return (u64) scale_load_down(tg->shares);
++}
++#endif
++
++static s64 cpu_cfs_quota_read_s64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_cfs_quota_write_s64(struct cgroup_subsys_state *css,
++ struct cftype *cftype, s64 cfs_quota_us)
++{
++ return 0;
++}
++
++static u64 cpu_cfs_period_read_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_cfs_period_write_u64(struct cgroup_subsys_state *css,
++ struct cftype *cftype, u64 cfs_period_us)
++{
++ return 0;
++}
++
++static u64 cpu_cfs_burst_read_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_cfs_burst_write_u64(struct cgroup_subsys_state *css,
++ struct cftype *cftype, u64 cfs_burst_us)
++{
++ return 0;
++}
++
++static int cpu_cfs_stat_show(struct seq_file *sf, void *v)
++{
++ return 0;
++}
++
++static int cpu_cfs_local_stat_show(struct seq_file *sf, void *v)
++{
++ return 0;
++}
++
++static int cpu_rt_runtime_write(struct cgroup_subsys_state *css,
++ struct cftype *cft, s64 val)
++{
++ return 0;
++}
++
++static s64 cpu_rt_runtime_read(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_rt_period_write_uint(struct cgroup_subsys_state *css,
++ struct cftype *cftype, u64 rt_period_us)
++{
++ return 0;
++}
++
++static u64 cpu_rt_period_read_uint(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_uclamp_min_show(struct seq_file *sf, void *v)
++{
++ return 0;
++}
++
++static int cpu_uclamp_max_show(struct seq_file *sf, void *v)
++{
++ return 0;
++}
++
++static ssize_t cpu_uclamp_min_write(struct kernfs_open_file *of,
++ char *buf, size_t nbytes,
++ loff_t off)
++{
++ return nbytes;
++}
++
++static ssize_t cpu_uclamp_max_write(struct kernfs_open_file *of,
++ char *buf, size_t nbytes,
++ loff_t off)
++{
++ return nbytes;
++}
++
++static struct cftype cpu_legacy_files[] = {
++#ifdef CONFIG_FAIR_GROUP_SCHED
++ {
++ .name = "shares",
++ .read_u64 = cpu_shares_read_u64,
++ .write_u64 = cpu_shares_write_u64,
++ },
++#endif
++ {
++ .name = "cfs_quota_us",
++ .read_s64 = cpu_cfs_quota_read_s64,
++ .write_s64 = cpu_cfs_quota_write_s64,
++ },
++ {
++ .name = "cfs_period_us",
++ .read_u64 = cpu_cfs_period_read_u64,
++ .write_u64 = cpu_cfs_period_write_u64,
++ },
++ {
++ .name = "cfs_burst_us",
++ .read_u64 = cpu_cfs_burst_read_u64,
++ .write_u64 = cpu_cfs_burst_write_u64,
++ },
++ {
++ .name = "stat",
++ .seq_show = cpu_cfs_stat_show,
++ },
++ {
++ .name = "stat.local",
++ .seq_show = cpu_cfs_local_stat_show,
++ },
++ {
++ .name = "rt_runtime_us",
++ .read_s64 = cpu_rt_runtime_read,
++ .write_s64 = cpu_rt_runtime_write,
++ },
++ {
++ .name = "rt_period_us",
++ .read_u64 = cpu_rt_period_read_uint,
++ .write_u64 = cpu_rt_period_write_uint,
++ },
++ {
++ .name = "uclamp.min",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_uclamp_min_show,
++ .write = cpu_uclamp_min_write,
++ },
++ {
++ .name = "uclamp.max",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_uclamp_max_show,
++ .write = cpu_uclamp_max_write,
++ },
++ { } /* Terminate */
++};
++
++static u64 cpu_weight_read_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_weight_write_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft, u64 weight)
++{
++ return 0;
++}
++
++static s64 cpu_weight_nice_read_s64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_weight_nice_write_s64(struct cgroup_subsys_state *css,
++ struct cftype *cft, s64 nice)
++{
++ return 0;
++}
++
++static s64 cpu_idle_read_s64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_idle_write_s64(struct cgroup_subsys_state *css,
++ struct cftype *cft, s64 idle)
++{
++ return 0;
++}
++
++static int cpu_max_show(struct seq_file *sf, void *v)
++{
++ return 0;
++}
++
++static ssize_t cpu_max_write(struct kernfs_open_file *of,
++ char *buf, size_t nbytes, loff_t off)
++{
++ return nbytes;
++}
++
++static struct cftype cpu_files[] = {
++ {
++ .name = "weight",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .read_u64 = cpu_weight_read_u64,
++ .write_u64 = cpu_weight_write_u64,
++ },
++ {
++ .name = "weight.nice",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .read_s64 = cpu_weight_nice_read_s64,
++ .write_s64 = cpu_weight_nice_write_s64,
++ },
++ {
++ .name = "idle",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .read_s64 = cpu_idle_read_s64,
++ .write_s64 = cpu_idle_write_s64,
++ },
++ {
++ .name = "max",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_max_show,
++ .write = cpu_max_write,
++ },
++ {
++ .name = "max.burst",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .read_u64 = cpu_cfs_burst_read_u64,
++ .write_u64 = cpu_cfs_burst_write_u64,
++ },
++ {
++ .name = "uclamp.min",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_uclamp_min_show,
++ .write = cpu_uclamp_min_write,
++ },
++ {
++ .name = "uclamp.max",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_uclamp_max_show,
++ .write = cpu_uclamp_max_write,
++ },
++ { } /* terminate */
++};
++
++static int cpu_extra_stat_show(struct seq_file *sf,
++ struct cgroup_subsys_state *css)
++{
++ return 0;
++}
++
++static int cpu_local_stat_show(struct seq_file *sf,
++ struct cgroup_subsys_state *css)
++{
++ return 0;
++}
++
++struct cgroup_subsys cpu_cgrp_subsys = {
++ .css_alloc = cpu_cgroup_css_alloc,
++ .css_online = cpu_cgroup_css_online,
++ .css_released = cpu_cgroup_css_released,
++ .css_free = cpu_cgroup_css_free,
++ .css_extra_stat_show = cpu_extra_stat_show,
++ .css_local_stat_show = cpu_local_stat_show,
++#ifdef CONFIG_RT_GROUP_SCHED
++ .can_attach = cpu_cgroup_can_attach,
++#endif
++ .attach = cpu_cgroup_attach,
++ .legacy_cftypes = cpu_legacy_files,
++ .dfl_cftypes = cpu_files,
++ .early_init = true,
++ .threaded = true,
++};
++#endif /* CONFIG_CGROUP_SCHED */
++
++#undef CREATE_TRACE_POINTS
++
++#ifdef CONFIG_SCHED_MM_CID
++
++#
++/*
++ * @cid_lock: Guarantee forward-progress of cid allocation.
++ *
++ * Concurrency ID allocation within a bitmap is mostly lock-free. The cid_lock
++ * is only used when contention is detected by the lock-free allocation so
++ * forward progress can be guaranteed.
++ */
++DEFINE_RAW_SPINLOCK(cid_lock);
++
++/*
++ * @use_cid_lock: Select cid allocation behavior: lock-free vs spinlock.
++ *
++ * When @use_cid_lock is 0, the cid allocation is lock-free. When contention is
++ * detected, it is set to 1 to ensure that all newly coming allocations are
++ * serialized by @cid_lock until the allocation which detected contention
++ * completes and sets @use_cid_lock back to 0. This guarantees forward progress
++ * of a cid allocation.
++ */
++int use_cid_lock;
++
++/*
++ * mm_cid remote-clear implements a lock-free algorithm to clear per-mm/cpu cid
++ * concurrently with respect to the execution of the source runqueue context
++ * switch.
++ *
++ * There is one basic properties we want to guarantee here:
++ *
++ * (1) Remote-clear should _never_ mark a per-cpu cid UNSET when it is actively
++ * used by a task. That would lead to concurrent allocation of the cid and
++ * userspace corruption.
++ *
++ * Provide this guarantee by introducing a Dekker memory ordering to guarantee
++ * that a pair of loads observe at least one of a pair of stores, which can be
++ * shown as:
++ *
++ * X = Y = 0
++ *
++ * w[X]=1 w[Y]=1
++ * MB MB
++ * r[Y]=y r[X]=x
++ *
++ * Which guarantees that x==0 && y==0 is impossible. But rather than using
++ * values 0 and 1, this algorithm cares about specific state transitions of the
++ * runqueue current task (as updated by the scheduler context switch), and the
++ * per-mm/cpu cid value.
++ *
++ * Let's introduce task (Y) which has task->mm == mm and task (N) which has
++ * task->mm != mm for the rest of the discussion. There are two scheduler state
++ * transitions on context switch we care about:
++ *
++ * (TSA) Store to rq->curr with transition from (N) to (Y)
++ *
++ * (TSB) Store to rq->curr with transition from (Y) to (N)
++ *
++ * On the remote-clear side, there is one transition we care about:
++ *
++ * (TMA) cmpxchg to *pcpu_cid to set the LAZY flag
++ *
++ * There is also a transition to UNSET state which can be performed from all
++ * sides (scheduler, remote-clear). It is always performed with a cmpxchg which
++ * guarantees that only a single thread will succeed:
++ *
++ * (TMB) cmpxchg to *pcpu_cid to mark UNSET
++ *
++ * Just to be clear, what we do _not_ want to happen is a transition to UNSET
++ * when a thread is actively using the cid (property (1)).
++ *
++ * Let's looks at the relevant combinations of TSA/TSB, and TMA transitions.
++ *
++ * Scenario A) (TSA)+(TMA) (from next task perspective)
++ *
++ * CPU0 CPU1
++ *
++ * Context switch CS-1 Remote-clear
++ * - store to rq->curr: (N)->(Y) (TSA) - cmpxchg to *pcpu_id to LAZY (TMA)
++ * (implied barrier after cmpxchg)
++ * - switch_mm_cid()
++ * - memory barrier (see switch_mm_cid()
++ * comment explaining how this barrier
++ * is combined with other scheduler
++ * barriers)
++ * - mm_cid_get (next)
++ * - READ_ONCE(*pcpu_cid) - rcu_dereference(src_rq->curr)
++ *
++ * This Dekker ensures that either task (Y) is observed by the
++ * rcu_dereference() or the LAZY flag is observed by READ_ONCE(), or both are
++ * observed.
++ *
++ * If task (Y) store is observed by rcu_dereference(), it means that there is
++ * still an active task on the cpu. Remote-clear will therefore not transition
++ * to UNSET, which fulfills property (1).
++ *
++ * If task (Y) is not observed, but the lazy flag is observed by READ_ONCE(),
++ * it will move its state to UNSET, which clears the percpu cid perhaps
++ * uselessly (which is not an issue for correctness). Because task (Y) is not
++ * observed, CPU1 can move ahead to set the state to UNSET. Because moving
++ * state to UNSET is done with a cmpxchg expecting that the old state has the
++ * LAZY flag set, only one thread will successfully UNSET.
++ *
++ * If both states (LAZY flag and task (Y)) are observed, the thread on CPU0
++ * will observe the LAZY flag and transition to UNSET (perhaps uselessly), and
++ * CPU1 will observe task (Y) and do nothing more, which is fine.
++ *
++ * What we are effectively preventing with this Dekker is a scenario where
++ * neither LAZY flag nor store (Y) are observed, which would fail property (1)
++ * because this would UNSET a cid which is actively used.
++ */
++
++void sched_mm_cid_migrate_from(struct task_struct *t)
++{
++ t->migrate_from_cpu = task_cpu(t);
++}
++
++static
++int __sched_mm_cid_migrate_from_fetch_cid(struct rq *src_rq,
++ struct task_struct *t,
++ struct mm_cid *src_pcpu_cid)
++{
++ struct mm_struct *mm = t->mm;
++ struct task_struct *src_task;
++ int src_cid, last_mm_cid;
++
++ if (!mm)
++ return -1;
++
++ last_mm_cid = t->last_mm_cid;
++ /*
++ * If the migrated task has no last cid, or if the current
++ * task on src rq uses the cid, it means the source cid does not need
++ * to be moved to the destination cpu.
++ */
++ if (last_mm_cid == -1)
++ return -1;
++ src_cid = READ_ONCE(src_pcpu_cid->cid);
++ if (!mm_cid_is_valid(src_cid) || last_mm_cid != src_cid)
++ return -1;
++
++ /*
++ * If we observe an active task using the mm on this rq, it means we
++ * are not the last task to be migrated from this cpu for this mm, so
++ * there is no need to move src_cid to the destination cpu.
++ */
++ rcu_read_lock();
++ src_task = rcu_dereference(src_rq->curr);
++ if (READ_ONCE(src_task->mm_cid_active) && src_task->mm == mm) {
++ rcu_read_unlock();
++ t->last_mm_cid = -1;
++ return -1;
++ }
++ rcu_read_unlock();
++
++ return src_cid;
++}
++
++static
++int __sched_mm_cid_migrate_from_try_steal_cid(struct rq *src_rq,
++ struct task_struct *t,
++ struct mm_cid *src_pcpu_cid,
++ int src_cid)
++{
++ struct task_struct *src_task;
++ struct mm_struct *mm = t->mm;
++ int lazy_cid;
++
++ if (src_cid == -1)
++ return -1;
++
++ /*
++ * Attempt to clear the source cpu cid to move it to the destination
++ * cpu.
++ */
++ lazy_cid = mm_cid_set_lazy_put(src_cid);
++ if (!try_cmpxchg(&src_pcpu_cid->cid, &src_cid, lazy_cid))
++ return -1;
++
++ /*
++ * The implicit barrier after cmpxchg per-mm/cpu cid before loading
++ * rq->curr->mm matches the scheduler barrier in context_switch()
++ * between store to rq->curr and load of prev and next task's
++ * per-mm/cpu cid.
++ *
++ * The implicit barrier after cmpxchg per-mm/cpu cid before loading
++ * rq->curr->mm_cid_active matches the barrier in
++ * sched_mm_cid_exit_signals(), sched_mm_cid_before_execve(), and
++ * sched_mm_cid_after_execve() between store to t->mm_cid_active and
++ * load of per-mm/cpu cid.
++ */
++
++ /*
++ * If we observe an active task using the mm on this rq after setting
++ * the lazy-put flag, this task will be responsible for transitioning
++ * from lazy-put flag set to MM_CID_UNSET.
++ */
++ scoped_guard (rcu) {
++ src_task = rcu_dereference(src_rq->curr);
++ if (READ_ONCE(src_task->mm_cid_active) && src_task->mm == mm) {
++ rcu_read_unlock();
++ /*
++ * We observed an active task for this mm, there is therefore
++ * no point in moving this cid to the destination cpu.
++ */
++ t->last_mm_cid = -1;
++ return -1;
++ }
++ }
++
++ /*
++ * The src_cid is unused, so it can be unset.
++ */
++ if (!try_cmpxchg(&src_pcpu_cid->cid, &lazy_cid, MM_CID_UNSET))
++ return -1;
++ return src_cid;
++}
++
++/*
++ * Migration to dst cpu. Called with dst_rq lock held.
++ * Interrupts are disabled, which keeps the window of cid ownership without the
++ * source rq lock held small.
++ */
++void sched_mm_cid_migrate_to(struct rq *dst_rq, struct task_struct *t, int src_cpu)
++{
++ struct mm_cid *src_pcpu_cid, *dst_pcpu_cid;
++ struct mm_struct *mm = t->mm;
++ int src_cid, dst_cid;
++ struct rq *src_rq;
++
++ lockdep_assert_rq_held(dst_rq);
++
++ if (!mm)
++ return;
++ if (src_cpu == -1) {
++ t->last_mm_cid = -1;
++ return;
++ }
++ /*
++ * Move the src cid if the dst cid is unset. This keeps id
++ * allocation closest to 0 in cases where few threads migrate around
++ * many cpus.
++ *
++ * If destination cid is already set, we may have to just clear
++ * the src cid to ensure compactness in frequent migrations
++ * scenarios.
++ *
++ * It is not useful to clear the src cid when the number of threads is
++ * greater or equal to the number of allowed cpus, because user-space
++ * can expect that the number of allowed cids can reach the number of
++ * allowed cpus.
++ */
++ dst_pcpu_cid = per_cpu_ptr(mm->pcpu_cid, cpu_of(dst_rq));
++ dst_cid = READ_ONCE(dst_pcpu_cid->cid);
++ if (!mm_cid_is_unset(dst_cid) &&
++ atomic_read(&mm->mm_users) >= t->nr_cpus_allowed)
++ return;
++ src_pcpu_cid = per_cpu_ptr(mm->pcpu_cid, src_cpu);
++ src_rq = cpu_rq(src_cpu);
++ src_cid = __sched_mm_cid_migrate_from_fetch_cid(src_rq, t, src_pcpu_cid);
++ if (src_cid == -1)
++ return;
++ src_cid = __sched_mm_cid_migrate_from_try_steal_cid(src_rq, t, src_pcpu_cid,
++ src_cid);
++ if (src_cid == -1)
++ return;
++ if (!mm_cid_is_unset(dst_cid)) {
++ __mm_cid_put(mm, src_cid);
++ return;
++ }
++ /* Move src_cid to dst cpu. */
++ mm_cid_snapshot_time(dst_rq, mm);
++ WRITE_ONCE(dst_pcpu_cid->cid, src_cid);
++}
++
++static void sched_mm_cid_remote_clear(struct mm_struct *mm, struct mm_cid *pcpu_cid,
++ int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++ struct task_struct *t;
++ int cid, lazy_cid;
++
++ cid = READ_ONCE(pcpu_cid->cid);
++ if (!mm_cid_is_valid(cid))
++ return;
++
++ /*
++ * Clear the cpu cid if it is set to keep cid allocation compact. If
++ * there happens to be other tasks left on the source cpu using this
++ * mm, the next task using this mm will reallocate its cid on context
++ * switch.
++ */
++ lazy_cid = mm_cid_set_lazy_put(cid);
++ if (!try_cmpxchg(&pcpu_cid->cid, &cid, lazy_cid))
++ return;
++
++ /*
++ * The implicit barrier after cmpxchg per-mm/cpu cid before loading
++ * rq->curr->mm matches the scheduler barrier in context_switch()
++ * between store to rq->curr and load of prev and next task's
++ * per-mm/cpu cid.
++ *
++ * The implicit barrier after cmpxchg per-mm/cpu cid before loading
++ * rq->curr->mm_cid_active matches the barrier in
++ * sched_mm_cid_exit_signals(), sched_mm_cid_before_execve(), and
++ * sched_mm_cid_after_execve() between store to t->mm_cid_active and
++ * load of per-mm/cpu cid.
++ */
++
++ /*
++ * If we observe an active task using the mm on this rq after setting
++ * the lazy-put flag, that task will be responsible for transitioning
++ * from lazy-put flag set to MM_CID_UNSET.
++ */
++ scoped_guard (rcu) {
++ t = rcu_dereference(rq->curr);
++ if (READ_ONCE(t->mm_cid_active) && t->mm == mm)
++ return;
++ }
++
++ /*
++ * The cid is unused, so it can be unset.
++ * Disable interrupts to keep the window of cid ownership without rq
++ * lock small.
++ */
++ scoped_guard (irqsave) {
++ if (try_cmpxchg(&pcpu_cid->cid, &lazy_cid, MM_CID_UNSET))
++ __mm_cid_put(mm, cid);
++ }
++}
++
++static void sched_mm_cid_remote_clear_old(struct mm_struct *mm, int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++ struct mm_cid *pcpu_cid;
++ struct task_struct *curr;
++ u64 rq_clock;
++
++ /*
++ * rq->clock load is racy on 32-bit but one spurious clear once in a
++ * while is irrelevant.
++ */
++ rq_clock = READ_ONCE(rq->clock);
++ pcpu_cid = per_cpu_ptr(mm->pcpu_cid, cpu);
++
++ /*
++ * In order to take care of infrequently scheduled tasks, bump the time
++ * snapshot associated with this cid if an active task using the mm is
++ * observed on this rq.
++ */
++ scoped_guard (rcu) {
++ curr = rcu_dereference(rq->curr);
++ if (READ_ONCE(curr->mm_cid_active) && curr->mm == mm) {
++ WRITE_ONCE(pcpu_cid->time, rq_clock);
++ return;
++ }
++ }
++
++ if (rq_clock < pcpu_cid->time + SCHED_MM_CID_PERIOD_NS)
++ return;
++ sched_mm_cid_remote_clear(mm, pcpu_cid, cpu);
++}
++
++static void sched_mm_cid_remote_clear_weight(struct mm_struct *mm, int cpu,
++ int weight)
++{
++ struct mm_cid *pcpu_cid;
++ int cid;
++
++ pcpu_cid = per_cpu_ptr(mm->pcpu_cid, cpu);
++ cid = READ_ONCE(pcpu_cid->cid);
++ if (!mm_cid_is_valid(cid) || cid < weight)
++ return;
++ sched_mm_cid_remote_clear(mm, pcpu_cid, cpu);
++}
++
++static void task_mm_cid_work(struct callback_head *work)
++{
++ unsigned long now = jiffies, old_scan, next_scan;
++ struct task_struct *t = current;
++ struct cpumask *cidmask;
++ struct mm_struct *mm;
++ int weight, cpu;
++
++ SCHED_WARN_ON(t != container_of(work, struct task_struct, cid_work));
++
++ work->next = work; /* Prevent double-add */
++ if (t->flags & PF_EXITING)
++ return;
++ mm = t->mm;
++ if (!mm)
++ return;
++ old_scan = READ_ONCE(mm->mm_cid_next_scan);
++ next_scan = now + msecs_to_jiffies(MM_CID_SCAN_DELAY);
++ if (!old_scan) {
++ unsigned long res;
++
++ res = cmpxchg(&mm->mm_cid_next_scan, old_scan, next_scan);
++ if (res != old_scan)
++ old_scan = res;
++ else
++ old_scan = next_scan;
++ }
++ if (time_before(now, old_scan))
++ return;
++ if (!try_cmpxchg(&mm->mm_cid_next_scan, &old_scan, next_scan))
++ return;
++ cidmask = mm_cidmask(mm);
++ /* Clear cids that were not recently used. */
++ for_each_possible_cpu(cpu)
++ sched_mm_cid_remote_clear_old(mm, cpu);
++ weight = cpumask_weight(cidmask);
++ /*
++ * Clear cids that are greater or equal to the cidmask weight to
++ * recompact it.
++ */
++ for_each_possible_cpu(cpu)
++ sched_mm_cid_remote_clear_weight(mm, cpu, weight);
++}
++
++void init_sched_mm_cid(struct task_struct *t)
++{
++ struct mm_struct *mm = t->mm;
++ int mm_users = 0;
++
++ if (mm) {
++ mm_users = atomic_read(&mm->mm_users);
++ if (mm_users == 1)
++ mm->mm_cid_next_scan = jiffies + msecs_to_jiffies(MM_CID_SCAN_DELAY);
++ }
++ t->cid_work.next = &t->cid_work; /* Protect against double add */
++ init_task_work(&t->cid_work, task_mm_cid_work);
++}
++
++void task_tick_mm_cid(struct rq *rq, struct task_struct *curr)
++{
++ struct callback_head *work = &curr->cid_work;
++ unsigned long now = jiffies;
++
++ if (!curr->mm || (curr->flags & (PF_EXITING | PF_KTHREAD)) ||
++ work->next != work)
++ return;
++ if (time_before(now, READ_ONCE(curr->mm->mm_cid_next_scan)))
++ return;
++ task_work_add(curr, work, TWA_RESUME);
++}
++
++void sched_mm_cid_exit_signals(struct task_struct *t)
++{
++ struct mm_struct *mm = t->mm;
++ struct rq *rq;
++
++ if (!mm)
++ return;
++
++ preempt_disable();
++ rq = this_rq();
++ guard(rq_lock_irqsave)(rq);
++ preempt_enable_no_resched(); /* holding spinlock */
++ WRITE_ONCE(t->mm_cid_active, 0);
++ /*
++ * Store t->mm_cid_active before loading per-mm/cpu cid.
++ * Matches barrier in sched_mm_cid_remote_clear_old().
++ */
++ smp_mb();
++ mm_cid_put(mm);
++ t->last_mm_cid = t->mm_cid = -1;
++}
++
++void sched_mm_cid_before_execve(struct task_struct *t)
++{
++ struct mm_struct *mm = t->mm;
++ struct rq *rq;
++
++ if (!mm)
++ return;
++
++ preempt_disable();
++ rq = this_rq();
++ guard(rq_lock_irqsave)(rq);
++ preempt_enable_no_resched(); /* holding spinlock */
++ WRITE_ONCE(t->mm_cid_active, 0);
++ /*
++ * Store t->mm_cid_active before loading per-mm/cpu cid.
++ * Matches barrier in sched_mm_cid_remote_clear_old().
++ */
++ smp_mb();
++ mm_cid_put(mm);
++ t->last_mm_cid = t->mm_cid = -1;
++}
++
++void sched_mm_cid_after_execve(struct task_struct *t)
++{
++ struct mm_struct *mm = t->mm;
++ struct rq *rq;
++
++ if (!mm)
++ return;
++
++ preempt_disable();
++ rq = this_rq();
++ scoped_guard (rq_lock_irqsave, rq) {
++ preempt_enable_no_resched(); /* holding spinlock */
++ WRITE_ONCE(t->mm_cid_active, 1);
++ /*
++ * Store t->mm_cid_active before loading per-mm/cpu cid.
++ * Matches barrier in sched_mm_cid_remote_clear_old().
++ */
++ smp_mb();
++ t->last_mm_cid = t->mm_cid = mm_cid_get(rq, mm);
++ }
++ rseq_set_notify_resume(t);
++}
++
++void sched_mm_cid_fork(struct task_struct *t)
++{
++ WARN_ON_ONCE(!t->mm || t->mm_cid != -1);
++ t->mm_cid_active = 1;
++}
++#endif
+diff --git a/kernel/sched/alt_debug.c b/kernel/sched/alt_debug.c
+new file mode 100644
+index 000000000000..1dbd7eb6a434
+--- /dev/null
++++ b/kernel/sched/alt_debug.c
+@@ -0,0 +1,32 @@
++/*
++ * kernel/sched/alt_debug.c
++ *
++ * Print the alt scheduler debugging details
++ *
++ * Author: Alfred Chen
++ * Date : 2020
++ */
++#include "sched.h"
++#include "linux/sched/debug.h"
++
++/*
++ * This allows printing both to /proc/sched_debug and
++ * to the console
++ */
++#define SEQ_printf(m, x...) \
++ do { \
++ if (m) \
++ seq_printf(m, x); \
++ else \
++ pr_cont(x); \
++ } while (0)
++
++void proc_sched_show_task(struct task_struct *p, struct pid_namespace *ns,
++ struct seq_file *m)
++{
++ SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, task_pid_nr_ns(p, ns),
++ get_nr_threads(p));
++}
++
++void proc_sched_set_task(struct task_struct *p)
++{}
+diff --git a/kernel/sched/alt_sched.h b/kernel/sched/alt_sched.h
+new file mode 100644
+index 000000000000..e9bfc67e8165
+--- /dev/null
++++ b/kernel/sched/alt_sched.h
+@@ -0,0 +1,954 @@
++#ifndef ALT_SCHED_H
++#define ALT_SCHED_H
++
++#include <linux/context_tracking.h>
++#include <linux/profile.h>
++#include <linux/stop_machine.h>
++#include <linux/syscalls.h>
++#include <linux/tick.h>
++
++#include <trace/events/power.h>
++#include <trace/events/sched.h>
++
++#include "../workqueue_internal.h"
++
++#include "cpupri.h"
++
++#ifdef CONFIG_CGROUP_SCHED
++/* task group related information */
++struct task_group {
++ struct cgroup_subsys_state css;
++
++ struct rcu_head rcu;
++ struct list_head list;
++
++ struct task_group *parent;
++ struct list_head siblings;
++ struct list_head children;
++#ifdef CONFIG_FAIR_GROUP_SCHED
++ unsigned long shares;
++#endif
++};
++
++extern struct task_group *sched_create_group(struct task_group *parent);
++extern void sched_online_group(struct task_group *tg,
++ struct task_group *parent);
++extern void sched_destroy_group(struct task_group *tg);
++extern void sched_release_group(struct task_group *tg);
++#endif /* CONFIG_CGROUP_SCHED */
++
++#define MIN_SCHED_NORMAL_PRIO (32)
++/*
++ * levels: RT(0-24), reserved(25-31), NORMAL(32-63), cpu idle task(64)
++ *
++ * -- BMQ --
++ * NORMAL: (lower boost range 12, NICE_WIDTH 40, higher boost range 12) / 2
++ * -- PDS --
++ * NORMAL: SCHED_EDGE_DELTA + ((NICE_WIDTH 40) / 2)
++ */
++#define SCHED_LEVELS (64 + 1)
++
++#define IDLE_TASK_SCHED_PRIO (SCHED_LEVELS - 1)
++
++#ifdef CONFIG_SCHED_DEBUG
++# define SCHED_WARN_ON(x) WARN_ONCE(x, #x)
++extern void resched_latency_warn(int cpu, u64 latency);
++#else
++# define SCHED_WARN_ON(x) ({ (void)(x), 0; })
++static inline void resched_latency_warn(int cpu, u64 latency) {}
++#endif
++
++/*
++ * Increase resolution of nice-level calculations for 64-bit architectures.
++ * The extra resolution improves shares distribution and load balancing of
++ * low-weight task groups (eg. nice +19 on an autogroup), deeper taskgroup
++ * hierarchies, especially on larger systems. This is not a user-visible change
++ * and does not change the user-interface for setting shares/weights.
++ *
++ * We increase resolution only if we have enough bits to allow this increased
++ * resolution (i.e. 64-bit). The costs for increasing resolution when 32-bit
++ * are pretty high and the returns do not justify the increased costs.
++ *
++ * Really only required when CONFIG_FAIR_GROUP_SCHED=y is also set, but to
++ * increase coverage and consistency always enable it on 64-bit platforms.
++ */
++#ifdef CONFIG_64BIT
++# define NICE_0_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT + SCHED_FIXEDPOINT_SHIFT)
++# define scale_load(w) ((w) << SCHED_FIXEDPOINT_SHIFT)
++# define scale_load_down(w) \
++({ \
++ unsigned long __w = (w); \
++ if (__w) \
++ __w = max(2UL, __w >> SCHED_FIXEDPOINT_SHIFT); \
++ __w; \
++})
++#else
++# define NICE_0_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT)
++# define scale_load(w) (w)
++# define scale_load_down(w) (w)
++#endif
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++#define ROOT_TASK_GROUP_LOAD NICE_0_LOAD
++
++/*
++ * A weight of 0 or 1 can cause arithmetics problems.
++ * A weight of a cfs_rq is the sum of weights of which entities
++ * are queued on this cfs_rq, so a weight of a entity should not be
++ * too large, so as the shares value of a task group.
++ * (The default weight is 1024 - so there's no practical
++ * limitation from this.)
++ */
++#define MIN_SHARES (1UL << 1)
++#define MAX_SHARES (1UL << 18)
++#endif
++
++/*
++ * Tunables that become constants when CONFIG_SCHED_DEBUG is off:
++ */
++#ifdef CONFIG_SCHED_DEBUG
++# define const_debug __read_mostly
++#else
++# define const_debug const
++#endif
++
++/* task_struct::on_rq states: */
++#define TASK_ON_RQ_QUEUED 1
++#define TASK_ON_RQ_MIGRATING 2
++
++static inline int task_on_rq_queued(struct task_struct *p)
++{
++ return p->on_rq == TASK_ON_RQ_QUEUED;
++}
++
++static inline int task_on_rq_migrating(struct task_struct *p)
++{
++ return READ_ONCE(p->on_rq) == TASK_ON_RQ_MIGRATING;
++}
++
++/* Wake flags. The first three directly map to some SD flag value */
++#define WF_EXEC 0x02 /* Wakeup after exec; maps to SD_BALANCE_EXEC */
++#define WF_FORK 0x04 /* Wakeup after fork; maps to SD_BALANCE_FORK */
++#define WF_TTWU 0x08 /* Wakeup; maps to SD_BALANCE_WAKE */
++
++#define WF_SYNC 0x10 /* Waker goes to sleep after wakeup */
++#define WF_MIGRATED 0x20 /* Internal use, task got migrated */
++#define WF_CURRENT_CPU 0x40 /* Prefer to move the wakee to the current CPU. */
++
++#ifdef CONFIG_SMP
++static_assert(WF_EXEC == SD_BALANCE_EXEC);
++static_assert(WF_FORK == SD_BALANCE_FORK);
++static_assert(WF_TTWU == SD_BALANCE_WAKE);
++#endif
++
++#define SCHED_QUEUE_BITS (SCHED_LEVELS - 1)
++
++struct sched_queue {
++ DECLARE_BITMAP(bitmap, SCHED_QUEUE_BITS);
++ struct list_head heads[SCHED_LEVELS];
++};
++
++struct rq;
++struct cpuidle_state;
++
++struct balance_callback {
++ struct balance_callback *next;
++ void (*func)(struct rq *rq);
++};
++
++/*
++ * This is the main, per-CPU runqueue data structure.
++ * This data should only be modified by the local cpu.
++ */
++struct rq {
++ /* runqueue lock: */
++ raw_spinlock_t lock;
++
++ struct task_struct __rcu *curr;
++ struct task_struct *idle;
++ struct task_struct *stop;
++ struct task_struct *skip;
++ struct mm_struct *prev_mm;
++
++ struct sched_queue queue;
++#ifdef CONFIG_SCHED_PDS
++ u64 time_edge;
++#endif
++ unsigned long prio;
++
++ /* switch count */
++ u64 nr_switches;
++
++ atomic_t nr_iowait;
++
++#ifdef CONFIG_SCHED_DEBUG
++ u64 last_seen_need_resched_ns;
++ int ticks_without_resched;
++#endif
++
++#ifdef CONFIG_MEMBARRIER
++ int membarrier_state;
++#endif
++
++#ifdef CONFIG_SMP
++ int cpu; /* cpu of this runqueue */
++ bool online;
++
++ unsigned int ttwu_pending;
++ unsigned char nohz_idle_balance;
++ unsigned char idle_balance;
++
++#ifdef CONFIG_HAVE_SCHED_AVG_IRQ
++ struct sched_avg avg_irq;
++#endif
++
++#ifdef CONFIG_SCHED_SMT
++ int active_balance;
++ struct cpu_stop_work active_balance_work;
++#endif
++ struct balance_callback *balance_callback;
++#ifdef CONFIG_HOTPLUG_CPU
++ struct rcuwait hotplug_wait;
++#endif
++ unsigned int nr_pinned;
++
++#endif /* CONFIG_SMP */
++#ifdef CONFIG_IRQ_TIME_ACCOUNTING
++ u64 prev_irq_time;
++#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
++#ifdef CONFIG_PARAVIRT
++ u64 prev_steal_time;
++#endif /* CONFIG_PARAVIRT */
++#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
++ u64 prev_steal_time_rq;
++#endif /* CONFIG_PARAVIRT_TIME_ACCOUNTING */
++
++ /* For genenal cpu load util */
++ s32 load_history;
++ u64 load_block;
++ u64 load_stamp;
++
++ /* calc_load related fields */
++ unsigned long calc_load_update;
++ long calc_load_active;
++
++ /* Ensure that all clocks are in the same cache line */
++ u64 clock ____cacheline_aligned;
++ u64 clock_task;
++#ifdef CONFIG_SCHED_BMQ
++ u64 last_ts_switch;
++#endif
++
++ unsigned int nr_running;
++ unsigned long nr_uninterruptible;
++
++#ifdef CONFIG_SCHED_HRTICK
++#ifdef CONFIG_SMP
++ call_single_data_t hrtick_csd;
++#endif
++ struct hrtimer hrtick_timer;
++ ktime_t hrtick_time;
++#endif
++
++#ifdef CONFIG_SCHEDSTATS
++
++ /* latency stats */
++ struct sched_info rq_sched_info;
++ unsigned long long rq_cpu_time;
++ /* could above be rq->cfs_rq.exec_clock + rq->rt_rq.rt_runtime ? */
++
++ /* sys_sched_yield() stats */
++ unsigned int yld_count;
++
++ /* schedule() stats */
++ unsigned int sched_switch;
++ unsigned int sched_count;
++ unsigned int sched_goidle;
++
++ /* try_to_wake_up() stats */
++ unsigned int ttwu_count;
++ unsigned int ttwu_local;
++#endif /* CONFIG_SCHEDSTATS */
++
++#ifdef CONFIG_CPU_IDLE
++ /* Must be inspected within a rcu lock section */
++ struct cpuidle_state *idle_state;
++#endif
++
++#ifdef CONFIG_NO_HZ_COMMON
++#ifdef CONFIG_SMP
++ call_single_data_t nohz_csd;
++#endif
++ atomic_t nohz_flags;
++#endif /* CONFIG_NO_HZ_COMMON */
++
++ /* Scratch cpumask to be temporarily used under rq_lock */
++ cpumask_var_t scratch_mask;
++};
++
++extern unsigned int sysctl_sched_base_slice;
++
++extern unsigned long rq_load_util(struct rq *rq, unsigned long max);
++
++extern unsigned long calc_load_update;
++extern atomic_long_t calc_load_tasks;
++
++extern void calc_global_load_tick(struct rq *this_rq);
++extern long calc_load_fold_active(struct rq *this_rq, long adjust);
++
++DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
++#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu)))
++#define this_rq() this_cpu_ptr(&runqueues)
++#define task_rq(p) cpu_rq(task_cpu(p))
++#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
++#define raw_rq() raw_cpu_ptr(&runqueues)
++
++#ifdef CONFIG_SMP
++#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL)
++void register_sched_domain_sysctl(void);
++void unregister_sched_domain_sysctl(void);
++#else
++static inline void register_sched_domain_sysctl(void)
++{
++}
++static inline void unregister_sched_domain_sysctl(void)
++{
++}
++#endif
++
++extern bool sched_smp_initialized;
++
++enum {
++ ITSELF_LEVEL_SPACE_HOLDER,
++#ifdef CONFIG_SCHED_SMT
++ SMT_LEVEL_SPACE_HOLDER,
++#endif
++ COREGROUP_LEVEL_SPACE_HOLDER,
++ CORE_LEVEL_SPACE_HOLDER,
++ OTHER_LEVEL_SPACE_HOLDER,
++ NR_CPU_AFFINITY_LEVELS
++};
++
++DECLARE_PER_CPU_ALIGNED(cpumask_t [NR_CPU_AFFINITY_LEVELS], sched_cpu_topo_masks);
++
++static inline int
++__best_mask_cpu(const cpumask_t *cpumask, const cpumask_t *mask)
++{
++ int cpu;
++
++ while ((cpu = cpumask_any_and(cpumask, mask)) >= nr_cpu_ids)
++ mask++;
++
++ return cpu;
++}
++
++static inline int best_mask_cpu(int cpu, const cpumask_t *mask)
++{
++ return __best_mask_cpu(mask, per_cpu(sched_cpu_topo_masks, cpu));
++}
++
++extern void flush_smp_call_function_queue(void);
++
++#else /* !CONFIG_SMP */
++static inline void flush_smp_call_function_queue(void) { }
++#endif
++
++#ifndef arch_scale_freq_tick
++static __always_inline
++void arch_scale_freq_tick(void)
++{
++}
++#endif
++
++#ifndef arch_scale_freq_capacity
++static __always_inline
++unsigned long arch_scale_freq_capacity(int cpu)
++{
++ return SCHED_CAPACITY_SCALE;
++}
++#endif
++
++static inline u64 __rq_clock_broken(struct rq *rq)
++{
++ return READ_ONCE(rq->clock);
++}
++
++static inline u64 rq_clock(struct rq *rq)
++{
++ /*
++ * Relax lockdep_assert_held() checking as in VRQ, call to
++ * sched_info_xxxx() may not held rq->lock
++ * lockdep_assert_held(&rq->lock);
++ */
++ return rq->clock;
++}
++
++static inline u64 rq_clock_task(struct rq *rq)
++{
++ /*
++ * Relax lockdep_assert_held() checking as in VRQ, call to
++ * sched_info_xxxx() may not held rq->lock
++ * lockdep_assert_held(&rq->lock);
++ */
++ return rq->clock_task;
++}
++
++/*
++ * {de,en}queue flags:
++ *
++ * DEQUEUE_SLEEP - task is no longer runnable
++ * ENQUEUE_WAKEUP - task just became runnable
++ *
++ */
++
++#define DEQUEUE_SLEEP 0x01
++
++#define ENQUEUE_WAKEUP 0x01
++
++
++/*
++ * Below are scheduler API which using in other kernel code
++ * It use the dummy rq_flags
++ * ToDo : BMQ need to support these APIs for compatibility with mainline
++ * scheduler code.
++ */
++struct rq_flags {
++ unsigned long flags;
++};
++
++struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf)
++ __acquires(rq->lock);
++
++struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf)
++ __acquires(p->pi_lock)
++ __acquires(rq->lock);
++
++static inline void __task_rq_unlock(struct rq *rq, struct rq_flags *rf)
++ __releases(rq->lock)
++{
++ raw_spin_unlock(&rq->lock);
++}
++
++static inline void
++task_rq_unlock(struct rq *rq, struct task_struct *p, struct rq_flags *rf)
++ __releases(rq->lock)
++ __releases(p->pi_lock)
++{
++ raw_spin_unlock(&rq->lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags);
++}
++
++static inline void
++rq_lock(struct rq *rq, struct rq_flags *rf)
++ __acquires(rq->lock)
++{
++ raw_spin_lock(&rq->lock);
++}
++
++static inline void
++rq_unlock(struct rq *rq, struct rq_flags *rf)
++ __releases(rq->lock)
++{
++ raw_spin_unlock(&rq->lock);
++}
++
++static inline void
++rq_lock_irq(struct rq *rq, struct rq_flags *rf)
++ __acquires(rq->lock)
++{
++ raw_spin_lock_irq(&rq->lock);
++}
++
++static inline void
++rq_unlock_irq(struct rq *rq, struct rq_flags *rf)
++ __releases(rq->lock)
++{
++ raw_spin_unlock_irq(&rq->lock);
++}
++
++static inline struct rq *
++this_rq_lock_irq(struct rq_flags *rf)
++ __acquires(rq->lock)
++{
++ struct rq *rq;
++
++ local_irq_disable();
++ rq = this_rq();
++ raw_spin_lock(&rq->lock);
++
++ return rq;
++}
++
++static inline raw_spinlock_t *__rq_lockp(struct rq *rq)
++{
++ return &rq->lock;
++}
++
++static inline raw_spinlock_t *rq_lockp(struct rq *rq)
++{
++ return __rq_lockp(rq);
++}
++
++static inline void lockdep_assert_rq_held(struct rq *rq)
++{
++ lockdep_assert_held(__rq_lockp(rq));
++}
++
++extern void raw_spin_rq_lock_nested(struct rq *rq, int subclass);
++extern void raw_spin_rq_unlock(struct rq *rq);
++
++static inline void raw_spin_rq_lock(struct rq *rq)
++{
++ raw_spin_rq_lock_nested(rq, 0);
++}
++
++static inline void raw_spin_rq_lock_irq(struct rq *rq)
++{
++ local_irq_disable();
++ raw_spin_rq_lock(rq);
++}
++
++static inline void raw_spin_rq_unlock_irq(struct rq *rq)
++{
++ raw_spin_rq_unlock(rq);
++ local_irq_enable();
++}
++
++static inline int task_current(struct rq *rq, struct task_struct *p)
++{
++ return rq->curr == p;
++}
++
++static inline bool task_on_cpu(struct task_struct *p)
++{
++ return p->on_cpu;
++}
++
++extern int task_running_nice(struct task_struct *p);
++
++extern struct static_key_false sched_schedstats;
++
++#ifdef CONFIG_CPU_IDLE
++static inline void idle_set_state(struct rq *rq,
++ struct cpuidle_state *idle_state)
++{
++ rq->idle_state = idle_state;
++}
++
++static inline struct cpuidle_state *idle_get_state(struct rq *rq)
++{
++ WARN_ON(!rcu_read_lock_held());
++ return rq->idle_state;
++}
++#else
++static inline void idle_set_state(struct rq *rq,
++ struct cpuidle_state *idle_state)
++{
++}
++
++static inline struct cpuidle_state *idle_get_state(struct rq *rq)
++{
++ return NULL;
++}
++#endif
++
++static inline int cpu_of(const struct rq *rq)
++{
++#ifdef CONFIG_SMP
++ return rq->cpu;
++#else
++ return 0;
++#endif
++}
++
++extern void resched_cpu(int cpu);
++
++#include "stats.h"
++
++#ifdef CONFIG_NO_HZ_COMMON
++#define NOHZ_BALANCE_KICK_BIT 0
++#define NOHZ_STATS_KICK_BIT 1
++
++#define NOHZ_BALANCE_KICK BIT(NOHZ_BALANCE_KICK_BIT)
++#define NOHZ_STATS_KICK BIT(NOHZ_STATS_KICK_BIT)
++
++#define NOHZ_KICK_MASK (NOHZ_BALANCE_KICK | NOHZ_STATS_KICK)
++
++#define nohz_flags(cpu) (&cpu_rq(cpu)->nohz_flags)
++
++/* TODO: needed?
++extern void nohz_balance_exit_idle(struct rq *rq);
++#else
++static inline void nohz_balance_exit_idle(struct rq *rq) { }
++*/
++#endif
++
++#ifdef CONFIG_IRQ_TIME_ACCOUNTING
++struct irqtime {
++ u64 total;
++ u64 tick_delta;
++ u64 irq_start_time;
++ struct u64_stats_sync sync;
++};
++
++DECLARE_PER_CPU(struct irqtime, cpu_irqtime);
++
++/*
++ * Returns the irqtime minus the softirq time computed by ksoftirqd.
++ * Otherwise ksoftirqd's sum_exec_runtime is substracted its own runtime
++ * and never move forward.
++ */
++static inline u64 irq_time_read(int cpu)
++{
++ struct irqtime *irqtime = &per_cpu(cpu_irqtime, cpu);
++ unsigned int seq;
++ u64 total;
++
++ do {
++ seq = __u64_stats_fetch_begin(&irqtime->sync);
++ total = irqtime->total;
++ } while (__u64_stats_fetch_retry(&irqtime->sync, seq));
++
++ return total;
++}
++#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
++
++#ifdef CONFIG_CPU_FREQ
++DECLARE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
++#endif /* CONFIG_CPU_FREQ */
++
++#ifdef CONFIG_NO_HZ_FULL
++extern int __init sched_tick_offload_init(void);
++#else
++static inline int sched_tick_offload_init(void) { return 0; }
++#endif
++
++#ifdef arch_scale_freq_capacity
++#ifndef arch_scale_freq_invariant
++#define arch_scale_freq_invariant() (true)
++#endif
++#else /* arch_scale_freq_capacity */
++#define arch_scale_freq_invariant() (false)
++#endif
++
++#ifdef CONFIG_SMP
++unsigned long sugov_effective_cpu_perf(int cpu, unsigned long actual,
++ unsigned long min,
++ unsigned long max);
++#endif /* CONFIG_SMP */
++
++extern void schedule_idle(void);
++
++#define cap_scale(v, s) ((v)*(s) >> SCHED_CAPACITY_SHIFT)
++
++/*
++ * !! For sched_setattr_nocheck() (kernel) only !!
++ *
++ * This is actually gross. :(
++ *
++ * It is used to make schedutil kworker(s) higher priority than SCHED_DEADLINE
++ * tasks, but still be able to sleep. We need this on platforms that cannot
++ * atomically change clock frequency. Remove once fast switching will be
++ * available on such platforms.
++ *
++ * SUGOV stands for SchedUtil GOVernor.
++ */
++#define SCHED_FLAG_SUGOV 0x10000000
++
++#ifdef CONFIG_MEMBARRIER
++/*
++ * The scheduler provides memory barriers required by membarrier between:
++ * - prior user-space memory accesses and store to rq->membarrier_state,
++ * - store to rq->membarrier_state and following user-space memory accesses.
++ * In the same way it provides those guarantees around store to rq->curr.
++ */
++static inline void membarrier_switch_mm(struct rq *rq,
++ struct mm_struct *prev_mm,
++ struct mm_struct *next_mm)
++{
++ int membarrier_state;
++
++ if (prev_mm == next_mm)
++ return;
++
++ membarrier_state = atomic_read(&next_mm->membarrier_state);
++ if (READ_ONCE(rq->membarrier_state) == membarrier_state)
++ return;
++
++ WRITE_ONCE(rq->membarrier_state, membarrier_state);
++}
++#else
++static inline void membarrier_switch_mm(struct rq *rq,
++ struct mm_struct *prev_mm,
++ struct mm_struct *next_mm)
++{
++}
++#endif
++
++#ifdef CONFIG_NUMA
++extern int sched_numa_find_closest(const struct cpumask *cpus, int cpu);
++#else
++static inline int sched_numa_find_closest(const struct cpumask *cpus, int cpu)
++{
++ return nr_cpu_ids;
++}
++#endif
++
++extern void swake_up_all_locked(struct swait_queue_head *q);
++extern void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait);
++
++extern int try_to_wake_up(struct task_struct *tsk, unsigned int state, int wake_flags);
++
++#ifdef CONFIG_PREEMPT_DYNAMIC
++extern int preempt_dynamic_mode;
++extern int sched_dynamic_mode(const char *str);
++extern void sched_dynamic_update(int mode);
++#endif
++
++static inline void nohz_run_idle_balance(int cpu) { }
++
++static inline
++unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util,
++ struct task_struct *p)
++{
++ return util;
++}
++
++static inline bool uclamp_rq_is_capped(struct rq *rq) { return false; }
++
++#ifdef CONFIG_SCHED_MM_CID
++
++#define SCHED_MM_CID_PERIOD_NS (100ULL * 1000000) /* 100ms */
++#define MM_CID_SCAN_DELAY 100 /* 100ms */
++
++extern raw_spinlock_t cid_lock;
++extern int use_cid_lock;
++
++extern void sched_mm_cid_migrate_from(struct task_struct *t);
++extern void sched_mm_cid_migrate_to(struct rq *dst_rq, struct task_struct *t, int src_cpu);
++extern void task_tick_mm_cid(struct rq *rq, struct task_struct *curr);
++extern void init_sched_mm_cid(struct task_struct *t);
++
++static inline void __mm_cid_put(struct mm_struct *mm, int cid)
++{
++ if (cid < 0)
++ return;
++ cpumask_clear_cpu(cid, mm_cidmask(mm));
++}
++
++/*
++ * The per-mm/cpu cid can have the MM_CID_LAZY_PUT flag set or transition to
++ * the MM_CID_UNSET state without holding the rq lock, but the rq lock needs to
++ * be held to transition to other states.
++ *
++ * State transitions synchronized with cmpxchg or try_cmpxchg need to be
++ * consistent across cpus, which prevents use of this_cpu_cmpxchg.
++ */
++static inline void mm_cid_put_lazy(struct task_struct *t)
++{
++ struct mm_struct *mm = t->mm;
++ struct mm_cid __percpu *pcpu_cid = mm->pcpu_cid;
++ int cid;
++
++ lockdep_assert_irqs_disabled();
++ cid = __this_cpu_read(pcpu_cid->cid);
++ if (!mm_cid_is_lazy_put(cid) ||
++ !try_cmpxchg(&this_cpu_ptr(pcpu_cid)->cid, &cid, MM_CID_UNSET))
++ return;
++ __mm_cid_put(mm, mm_cid_clear_lazy_put(cid));
++}
++
++static inline int mm_cid_pcpu_unset(struct mm_struct *mm)
++{
++ struct mm_cid __percpu *pcpu_cid = mm->pcpu_cid;
++ int cid, res;
++
++ lockdep_assert_irqs_disabled();
++ cid = __this_cpu_read(pcpu_cid->cid);
++ for (;;) {
++ if (mm_cid_is_unset(cid))
++ return MM_CID_UNSET;
++ /*
++ * Attempt transition from valid or lazy-put to unset.
++ */
++ res = cmpxchg(&this_cpu_ptr(pcpu_cid)->cid, cid, MM_CID_UNSET);
++ if (res == cid)
++ break;
++ cid = res;
++ }
++ return cid;
++}
++
++static inline void mm_cid_put(struct mm_struct *mm)
++{
++ int cid;
++
++ lockdep_assert_irqs_disabled();
++ cid = mm_cid_pcpu_unset(mm);
++ if (cid == MM_CID_UNSET)
++ return;
++ __mm_cid_put(mm, mm_cid_clear_lazy_put(cid));
++}
++
++static inline int __mm_cid_try_get(struct mm_struct *mm)
++{
++ struct cpumask *cpumask;
++ int cid;
++
++ cpumask = mm_cidmask(mm);
++ /*
++ * Retry finding first zero bit if the mask is temporarily
++ * filled. This only happens during concurrent remote-clear
++ * which owns a cid without holding a rq lock.
++ */
++ for (;;) {
++ cid = cpumask_first_zero(cpumask);
++ if (cid < nr_cpu_ids)
++ break;
++ cpu_relax();
++ }
++ if (cpumask_test_and_set_cpu(cid, cpumask))
++ return -1;
++ return cid;
++}
++
++/*
++ * Save a snapshot of the current runqueue time of this cpu
++ * with the per-cpu cid value, allowing to estimate how recently it was used.
++ */
++static inline void mm_cid_snapshot_time(struct rq *rq, struct mm_struct *mm)
++{
++ struct mm_cid *pcpu_cid = per_cpu_ptr(mm->pcpu_cid, cpu_of(rq));
++
++ lockdep_assert_rq_held(rq);
++ WRITE_ONCE(pcpu_cid->time, rq->clock);
++}
++
++static inline int __mm_cid_get(struct rq *rq, struct mm_struct *mm)
++{
++ int cid;
++
++ /*
++ * All allocations (even those using the cid_lock) are lock-free. If
++ * use_cid_lock is set, hold the cid_lock to perform cid allocation to
++ * guarantee forward progress.
++ */
++ if (!READ_ONCE(use_cid_lock)) {
++ cid = __mm_cid_try_get(mm);
++ if (cid >= 0)
++ goto end;
++ raw_spin_lock(&cid_lock);
++ } else {
++ raw_spin_lock(&cid_lock);
++ cid = __mm_cid_try_get(mm);
++ if (cid >= 0)
++ goto unlock;
++ }
++
++ /*
++ * cid concurrently allocated. Retry while forcing following
++ * allocations to use the cid_lock to ensure forward progress.
++ */
++ WRITE_ONCE(use_cid_lock, 1);
++ /*
++ * Set use_cid_lock before allocation. Only care about program order
++ * because this is only required for forward progress.
++ */
++ barrier();
++ /*
++ * Retry until it succeeds. It is guaranteed to eventually succeed once
++ * all newcoming allocations observe the use_cid_lock flag set.
++ */
++ do {
++ cid = __mm_cid_try_get(mm);
++ cpu_relax();
++ } while (cid < 0);
++ /*
++ * Allocate before clearing use_cid_lock. Only care about
++ * program order because this is for forward progress.
++ */
++ barrier();
++ WRITE_ONCE(use_cid_lock, 0);
++unlock:
++ raw_spin_unlock(&cid_lock);
++end:
++ mm_cid_snapshot_time(rq, mm);
++ return cid;
++}
++
++static inline int mm_cid_get(struct rq *rq, struct mm_struct *mm)
++{
++ struct mm_cid __percpu *pcpu_cid = mm->pcpu_cid;
++ struct cpumask *cpumask;
++ int cid;
++
++ lockdep_assert_rq_held(rq);
++ cpumask = mm_cidmask(mm);
++ cid = __this_cpu_read(pcpu_cid->cid);
++ if (mm_cid_is_valid(cid)) {
++ mm_cid_snapshot_time(rq, mm);
++ return cid;
++ }
++ if (mm_cid_is_lazy_put(cid)) {
++ if (try_cmpxchg(&this_cpu_ptr(pcpu_cid)->cid, &cid, MM_CID_UNSET))
++ __mm_cid_put(mm, mm_cid_clear_lazy_put(cid));
++ }
++ cid = __mm_cid_get(rq, mm);
++ __this_cpu_write(pcpu_cid->cid, cid);
++ return cid;
++}
++
++static inline void switch_mm_cid(struct rq *rq,
++ struct task_struct *prev,
++ struct task_struct *next)
++{
++ /*
++ * Provide a memory barrier between rq->curr store and load of
++ * {prev,next}->mm->pcpu_cid[cpu] on rq->curr->mm transition.
++ *
++ * Should be adapted if context_switch() is modified.
++ */
++ if (!next->mm) { // to kernel
++ /*
++ * user -> kernel transition does not guarantee a barrier, but
++ * we can use the fact that it performs an atomic operation in
++ * mmgrab().
++ */
++ if (prev->mm) // from user
++ smp_mb__after_mmgrab();
++ /*
++ * kernel -> kernel transition does not change rq->curr->mm
++ * state. It stays NULL.
++ */
++ } else { // to user
++ /*
++ * kernel -> user transition does not provide a barrier
++ * between rq->curr store and load of {prev,next}->mm->pcpu_cid[cpu].
++ * Provide it here.
++ */
++ if (!prev->mm) // from kernel
++ smp_mb();
++ /*
++ * user -> user transition guarantees a memory barrier through
++ * switch_mm() when current->mm changes. If current->mm is
++ * unchanged, no barrier is needed.
++ */
++ }
++ if (prev->mm_cid_active) {
++ mm_cid_snapshot_time(rq, prev->mm);
++ mm_cid_put_lazy(prev);
++ prev->mm_cid = -1;
++ }
++ if (next->mm_cid_active)
++ next->last_mm_cid = next->mm_cid = mm_cid_get(rq, next->mm);
++}
++
++#else
++static inline void switch_mm_cid(struct rq *rq, struct task_struct *prev, struct task_struct *next) { }
++static inline void sched_mm_cid_migrate_from(struct task_struct *t) { }
++static inline void sched_mm_cid_migrate_to(struct rq *dst_rq, struct task_struct *t, int src_cpu) { }
++static inline void task_tick_mm_cid(struct rq *rq, struct task_struct *curr) { }
++static inline void init_sched_mm_cid(struct task_struct *t) { }
++#endif
++
++#endif /* ALT_SCHED_H */
+diff --git a/kernel/sched/bmq.h b/kernel/sched/bmq.h
+new file mode 100644
+index 000000000000..840009dc1e8d
+--- /dev/null
++++ b/kernel/sched/bmq.h
+@@ -0,0 +1,99 @@
++#define ALT_SCHED_NAME "BMQ"
++
++/*
++ * BMQ only routines
++ */
++#define rq_switch_time(rq) ((rq)->clock - (rq)->last_ts_switch)
++#define boost_threshold(p) (sysctl_sched_base_slice >> ((14 - (p)->boost_prio) / 2))
++
++static inline void boost_task(struct task_struct *p)
++{
++ int limit;
++
++ switch (p->policy) {
++ case SCHED_NORMAL:
++ limit = -MAX_PRIORITY_ADJ;
++ break;
++ case SCHED_BATCH:
++ case SCHED_IDLE:
++ limit = 0;
++ break;
++ default:
++ return;
++ }
++
++ if (p->boost_prio > limit)
++ p->boost_prio--;
++}
++
++static inline void deboost_task(struct task_struct *p)
++{
++ if (p->boost_prio < MAX_PRIORITY_ADJ)
++ p->boost_prio++;
++}
++
++/*
++ * Common interfaces
++ */
++static inline void sched_timeslice_imp(const int timeslice_ms) {}
++
++static inline int
++task_sched_prio_normal(const struct task_struct *p, const struct rq *rq)
++{
++ return p->prio + p->boost_prio - MAX_RT_PRIO;
++}
++
++static inline int task_sched_prio(const struct task_struct *p)
++{
++ return (p->prio < MAX_RT_PRIO)? (p->prio >> 2) :
++ MIN_SCHED_NORMAL_PRIO + (p->prio + p->boost_prio - MAX_RT_PRIO) / 2;
++}
++
++static inline int
++task_sched_prio_idx(const struct task_struct *p, const struct rq *rq)
++{
++ return task_sched_prio(p);
++}
++
++static inline int sched_prio2idx(int prio, struct rq *rq)
++{
++ return prio;
++}
++
++static inline int sched_idx2prio(int idx, struct rq *rq)
++{
++ return idx;
++}
++
++inline int task_running_nice(struct task_struct *p)
++{
++ return (p->prio + p->boost_prio > DEFAULT_PRIO + MAX_PRIORITY_ADJ);
++}
++
++static inline void sched_update_rq_clock(struct rq *rq) {}
++
++static inline void sched_task_renew(struct task_struct *p, const struct rq *rq)
++{
++ if (rq_switch_time(rq) > sysctl_sched_base_slice)
++ deboost_task(p);
++}
++
++static inline void sched_task_sanity_check(struct task_struct *p, struct rq *rq) {}
++static void sched_task_fork(struct task_struct *p, struct rq *rq) {}
++
++static inline void do_sched_yield_type_1(struct task_struct *p, struct rq *rq)
++{
++ p->boost_prio = MAX_PRIORITY_ADJ;
++}
++
++static inline void sched_task_ttwu(struct task_struct *p)
++{
++ if(this_rq()->clock_task - p->last_ran > sysctl_sched_base_slice)
++ boost_task(p);
++}
++
++static inline void sched_task_deactivate(struct task_struct *p, struct rq *rq)
++{
++ if (rq_switch_time(rq) < boost_threshold(p))
++ boost_task(p);
++}
+diff --git a/kernel/sched/build_policy.c b/kernel/sched/build_policy.c
+index d9dc9ab3773f..71a25540d65e 100644
+--- a/kernel/sched/build_policy.c
++++ b/kernel/sched/build_policy.c
+@@ -42,13 +42,19 @@
+
+ #include "idle.c"
+
++#ifndef CONFIG_SCHED_ALT
+ #include "rt.c"
++#endif
+
+ #ifdef CONFIG_SMP
++#ifndef CONFIG_SCHED_ALT
+ # include "cpudeadline.c"
++#endif
+ # include "pelt.c"
+ #endif
+
+ #include "cputime.c"
+-#include "deadline.c"
+
++#ifndef CONFIG_SCHED_ALT
++#include "deadline.c"
++#endif
+diff --git a/kernel/sched/build_utility.c b/kernel/sched/build_utility.c
+index 80a3df49ab47..bc17d5a6fc41 100644
+--- a/kernel/sched/build_utility.c
++++ b/kernel/sched/build_utility.c
+@@ -84,7 +84,9 @@
+
+ #ifdef CONFIG_SMP
+ # include "cpupri.c"
++#ifndef CONFIG_SCHED_ALT
+ # include "stop_task.c"
++#endif
+ # include "topology.c"
+ #endif
+
+diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
+index eece6244f9d2..3075127f9e95 100644
+--- a/kernel/sched/cpufreq_schedutil.c
++++ b/kernel/sched/cpufreq_schedutil.c
+@@ -197,12 +197,17 @@ unsigned long sugov_effective_cpu_perf(int cpu, unsigned long actual,
+
+ static void sugov_get_util(struct sugov_cpu *sg_cpu, unsigned long boost)
+ {
++#ifndef CONFIG_SCHED_ALT
+ unsigned long min, max, util = cpu_util_cfs_boost(sg_cpu->cpu);
+
+ util = effective_cpu_util(sg_cpu->cpu, util, &min, &max);
+ util = max(util, boost);
+ sg_cpu->bw_min = min;
+ sg_cpu->util = sugov_effective_cpu_perf(sg_cpu->cpu, util, min, max);
++#else /* CONFIG_SCHED_ALT */
++ sg_cpu->bw_min = 0;
++ sg_cpu->util = rq_load_util(cpu_rq(sg_cpu->cpu), arch_scale_cpu_capacity(sg_cpu->cpu));
++#endif /* CONFIG_SCHED_ALT */
+ }
+
+ /**
+@@ -343,8 +348,10 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; }
+ */
+ static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu)
+ {
++#ifndef CONFIG_SCHED_ALT
+ if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_min)
+ sg_cpu->sg_policy->limits_changed = true;
++#endif
+ }
+
+ static inline bool sugov_update_single_common(struct sugov_cpu *sg_cpu,
+@@ -676,6 +683,7 @@ static int sugov_kthread_create(struct sugov_policy *sg_policy)
+ }
+
+ ret = sched_setattr_nocheck(thread, &attr);
++
+ if (ret) {
+ kthread_stop(thread);
+ pr_warn("%s: failed to set SCHED_DEADLINE\n", __func__);
+diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
+index af7952f12e6c..6461cbbb734d 100644
+--- a/kernel/sched/cputime.c
++++ b/kernel/sched/cputime.c
+@@ -126,7 +126,7 @@ void account_user_time(struct task_struct *p, u64 cputime)
+ p->utime += cputime;
+ account_group_user_time(p, cputime);
+
+- index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER;
++ index = task_running_nice(p) ? CPUTIME_NICE : CPUTIME_USER;
+
+ /* Add user time to cpustat. */
+ task_group_account_field(p, index, cputime);
+@@ -150,7 +150,7 @@ void account_guest_time(struct task_struct *p, u64 cputime)
+ p->gtime += cputime;
+
+ /* Add guest time to cpustat. */
+- if (task_nice(p) > 0) {
++ if (task_running_nice(p)) {
+ task_group_account_field(p, CPUTIME_NICE, cputime);
+ cpustat[CPUTIME_GUEST_NICE] += cputime;
+ } else {
+@@ -288,7 +288,7 @@ static inline u64 account_other_time(u64 max)
+ #ifdef CONFIG_64BIT
+ static inline u64 read_sum_exec_runtime(struct task_struct *t)
+ {
+- return t->se.sum_exec_runtime;
++ return tsk_seruntime(t);
+ }
+ #else
+ static u64 read_sum_exec_runtime(struct task_struct *t)
+@@ -298,7 +298,7 @@ static u64 read_sum_exec_runtime(struct task_struct *t)
+ struct rq *rq;
+
+ rq = task_rq_lock(t, &rf);
+- ns = t->se.sum_exec_runtime;
++ ns = tsk_seruntime(t);
+ task_rq_unlock(rq, t, &rf);
+
+ return ns;
+@@ -630,7 +630,7 @@ void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev,
+ void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st)
+ {
+ struct task_cputime cputime = {
+- .sum_exec_runtime = p->se.sum_exec_runtime,
++ .sum_exec_runtime = tsk_seruntime(p),
+ };
+
+ if (task_cputime(p, &cputime.utime, &cputime.stime))
+diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
+index 8d5d98a5834d..15b9a02717ae 100644
+--- a/kernel/sched/debug.c
++++ b/kernel/sched/debug.c
+@@ -7,6 +7,7 @@
+ * Copyright(C) 2007, Red Hat, Inc., Ingo Molnar
+ */
+
++#ifndef CONFIG_SCHED_ALT
+ /*
+ * This allows printing both to /sys/kernel/debug/sched/debug and
+ * to the console
+@@ -215,6 +216,7 @@ static const struct file_operations sched_scaling_fops = {
+ };
+
+ #endif /* SMP */
++#endif /* !CONFIG_SCHED_ALT */
+
+ #ifdef CONFIG_PREEMPT_DYNAMIC
+
+@@ -278,6 +280,7 @@ static const struct file_operations sched_dynamic_fops = {
+
+ #endif /* CONFIG_PREEMPT_DYNAMIC */
+
++#ifndef CONFIG_SCHED_ALT
+ __read_mostly bool sched_debug_verbose;
+
+ #ifdef CONFIG_SMP
+@@ -332,6 +335,7 @@ static const struct file_operations sched_debug_fops = {
+ .llseek = seq_lseek,
+ .release = seq_release,
+ };
++#endif /* !CONFIG_SCHED_ALT */
+
+ static struct dentry *debugfs_sched;
+
+@@ -341,14 +345,17 @@ static __init int sched_init_debug(void)
+
+ debugfs_sched = debugfs_create_dir("sched", NULL);
+
++#ifndef CONFIG_SCHED_ALT
+ debugfs_create_file("features", 0644, debugfs_sched, NULL, &sched_feat_fops);
+ debugfs_create_file_unsafe("verbose", 0644, debugfs_sched, &sched_debug_verbose, &sched_verbose_fops);
++#endif /* !CONFIG_SCHED_ALT */
+ #ifdef CONFIG_PREEMPT_DYNAMIC
+ debugfs_create_file("preempt", 0644, debugfs_sched, NULL, &sched_dynamic_fops);
+ #endif
+
+ debugfs_create_u32("base_slice_ns", 0644, debugfs_sched, &sysctl_sched_base_slice);
+
++#ifndef CONFIG_SCHED_ALT
+ debugfs_create_u32("latency_warn_ms", 0644, debugfs_sched, &sysctl_resched_latency_warn_ms);
+ debugfs_create_u32("latency_warn_once", 0644, debugfs_sched, &sysctl_resched_latency_warn_once);
+
+@@ -373,11 +380,13 @@ static __init int sched_init_debug(void)
+ #endif
+
+ debugfs_create_file("debug", 0444, debugfs_sched, NULL, &sched_debug_fops);
++#endif /* !CONFIG_SCHED_ALT */
+
+ return 0;
+ }
+ late_initcall(sched_init_debug);
+
++#ifndef CONFIG_SCHED_ALT
+ #ifdef CONFIG_SMP
+
+ static cpumask_var_t sd_sysctl_cpus;
+@@ -1110,6 +1119,7 @@ void proc_sched_set_task(struct task_struct *p)
+ memset(&p->stats, 0, sizeof(p->stats));
+ #endif
+ }
++#endif /* !CONFIG_SCHED_ALT */
+
+ void resched_latency_warn(int cpu, u64 latency)
+ {
+diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
+index 31231925f1ec..c087311032f2 100644
+--- a/kernel/sched/idle.c
++++ b/kernel/sched/idle.c
+@@ -410,6 +410,7 @@ void cpu_startup_entry(enum cpuhp_state state)
+ do_idle();
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ /*
+ * idle-task scheduling class.
+ */
+@@ -531,3 +532,4 @@ DEFINE_SCHED_CLASS(idle) = {
+ .switched_to = switched_to_idle,
+ .update_curr = update_curr_idle,
+ };
++#endif
+diff --git a/kernel/sched/pds.h b/kernel/sched/pds.h
+new file mode 100644
+index 000000000000..c35dfb909f23
+--- /dev/null
++++ b/kernel/sched/pds.h
+@@ -0,0 +1,141 @@
++#define ALT_SCHED_NAME "PDS"
++
++static const u64 RT_MASK = ((1ULL << MIN_SCHED_NORMAL_PRIO) - 1);
++
++#define SCHED_NORMAL_PRIO_NUM (32)
++#define SCHED_EDGE_DELTA (SCHED_NORMAL_PRIO_NUM - NICE_WIDTH / 2)
++
++/* PDS assume NORMAL_PRIO_NUM is power of 2 */
++#define SCHED_NORMAL_PRIO_MOD(x) ((x) & (SCHED_NORMAL_PRIO_NUM - 1))
++
++/* default time slice 4ms -> shift 22, 2 time slice slots -> shift 23 */
++static __read_mostly int sched_timeslice_shift = 23;
++
++/*
++ * Common interfaces
++ */
++static inline void sched_timeslice_imp(const int timeslice_ms)
++{
++ if (2 == timeslice_ms)
++ sched_timeslice_shift = 22;
++}
++
++static inline int
++task_sched_prio_normal(const struct task_struct *p, const struct rq *rq)
++{
++ s64 delta = p->deadline - rq->time_edge + SCHED_EDGE_DELTA;
++
++#ifdef ALT_SCHED_DEBUG
++ if (WARN_ONCE(delta > NORMAL_PRIO_NUM - 1,
++ "pds: task_sched_prio_normal() delta %lld\n", delta))
++ return SCHED_NORMAL_PRIO_NUM - 1;
++#endif
++
++ return max(0LL, delta);
++}
++
++static inline int task_sched_prio(const struct task_struct *p)
++{
++ return (p->prio < MIN_NORMAL_PRIO) ? (p->prio >> 2) :
++ MIN_SCHED_NORMAL_PRIO + task_sched_prio_normal(p, task_rq(p));
++}
++
++static inline int
++task_sched_prio_idx(const struct task_struct *p, const struct rq *rq)
++{
++ u64 idx;
++
++ if (p->prio < MIN_NORMAL_PRIO)
++ return p->prio >> 2;
++
++ idx = max(p->deadline + SCHED_EDGE_DELTA, rq->time_edge);
++ /*printk(KERN_INFO "sched: task_sched_prio_idx edge:%llu, deadline=%llu idx=%llu\n", rq->time_edge, p->deadline, idx);*/
++ return MIN_SCHED_NORMAL_PRIO + SCHED_NORMAL_PRIO_MOD(idx);
++}
++
++static inline int sched_prio2idx(int sched_prio, struct rq *rq)
++{
++ return (IDLE_TASK_SCHED_PRIO == sched_prio || sched_prio < MIN_SCHED_NORMAL_PRIO) ?
++ sched_prio :
++ MIN_SCHED_NORMAL_PRIO + SCHED_NORMAL_PRIO_MOD(sched_prio + rq->time_edge);
++}
++
++static inline int sched_idx2prio(int sched_idx, struct rq *rq)
++{
++ return (sched_idx < MIN_SCHED_NORMAL_PRIO) ?
++ sched_idx :
++ MIN_SCHED_NORMAL_PRIO + SCHED_NORMAL_PRIO_MOD(sched_idx - rq->time_edge);
++}
++
++int task_running_nice(struct task_struct *p)
++{
++ return (p->prio > DEFAULT_PRIO);
++}
++
++static inline void sched_update_rq_clock(struct rq *rq)
++{
++ struct list_head head;
++ u64 old = rq->time_edge;
++ u64 now = rq->clock >> sched_timeslice_shift;
++ u64 prio, delta;
++ DECLARE_BITMAP(normal, SCHED_QUEUE_BITS);
++
++ if (now == old)
++ return;
++
++ rq->time_edge = now;
++ delta = min_t(u64, SCHED_NORMAL_PRIO_NUM, now - old);
++ INIT_LIST_HEAD(&head);
++
++ prio = MIN_SCHED_NORMAL_PRIO;
++ for_each_set_bit_from(prio, rq->queue.bitmap, MIN_SCHED_NORMAL_PRIO + delta)
++ list_splice_tail_init(rq->queue.heads + MIN_SCHED_NORMAL_PRIO +
++ SCHED_NORMAL_PRIO_MOD(prio + old), &head);
++
++ bitmap_shift_right(normal, rq->queue.bitmap, delta, SCHED_QUEUE_BITS);
++ if (!list_empty(&head)) {
++ struct task_struct *p;
++ u64 idx = MIN_SCHED_NORMAL_PRIO + SCHED_NORMAL_PRIO_MOD(now);
++
++ list_for_each_entry(p, &head, sq_node)
++ p->sq_idx = idx;
++
++ list_splice(&head, rq->queue.heads + idx);
++ set_bit(MIN_SCHED_NORMAL_PRIO, normal);
++ }
++ bitmap_replace(rq->queue.bitmap, normal, rq->queue.bitmap,
++ (const unsigned long *)&RT_MASK, SCHED_QUEUE_BITS);
++
++ if (rq->prio < MIN_SCHED_NORMAL_PRIO || IDLE_TASK_SCHED_PRIO == rq->prio)
++ return;
++
++ rq->prio = (rq->prio < MIN_SCHED_NORMAL_PRIO + delta) ?
++ MIN_SCHED_NORMAL_PRIO : rq->prio - delta;
++}
++
++static inline void sched_task_renew(struct task_struct *p, const struct rq *rq)
++{
++ if (p->prio >= MIN_NORMAL_PRIO)
++ p->deadline = rq->time_edge + (p->static_prio - (MAX_PRIO - NICE_WIDTH)) / 2;
++}
++
++static inline void sched_task_sanity_check(struct task_struct *p, struct rq *rq)
++{
++ u64 max_dl = rq->time_edge + NICE_WIDTH / 2 - 1;
++ if (unlikely(p->deadline > max_dl))
++ p->deadline = max_dl;
++}
++
++static void sched_task_fork(struct task_struct *p, struct rq *rq)
++{
++ sched_task_renew(p, rq);
++}
++
++static inline void do_sched_yield_type_1(struct task_struct *p, struct rq *rq)
++{
++ p->time_slice = sysctl_sched_base_slice;
++ sched_task_renew(p, rq);
++}
++
++static inline void sched_task_ttwu(struct task_struct *p) {}
++static inline void sched_task_deactivate(struct task_struct *p, struct rq *rq) {}
+diff --git a/kernel/sched/pelt.c b/kernel/sched/pelt.c
+index 63b6cf898220..9ca10ece4d3a 100644
+--- a/kernel/sched/pelt.c
++++ b/kernel/sched/pelt.c
+@@ -266,6 +266,7 @@ ___update_load_avg(struct sched_avg *sa, unsigned long load)
+ WRITE_ONCE(sa->util_avg, sa->util_sum / divider);
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ /*
+ * sched_entity:
+ *
+@@ -383,8 +384,9 @@ int update_dl_rq_load_avg(u64 now, struct rq *rq, int running)
+
+ return 0;
+ }
++#endif
+
+-#ifdef CONFIG_SCHED_THERMAL_PRESSURE
++#if defined(CONFIG_SCHED_THERMAL_PRESSURE) && !defined(CONFIG_SCHED_ALT)
+ /*
+ * thermal:
+ *
+diff --git a/kernel/sched/pelt.h b/kernel/sched/pelt.h
+index 9e1083465fbc..d35f050e8296 100644
+--- a/kernel/sched/pelt.h
++++ b/kernel/sched/pelt.h
+@@ -1,13 +1,15 @@
+ #ifdef CONFIG_SMP
+ #include "sched-pelt.h"
+
++#ifndef CONFIG_SCHED_ALT
+ int __update_load_avg_blocked_se(u64 now, struct sched_entity *se);
+ int __update_load_avg_se(u64 now, struct cfs_rq *cfs_rq, struct sched_entity *se);
+ int __update_load_avg_cfs_rq(u64 now, struct cfs_rq *cfs_rq);
+ int update_rt_rq_load_avg(u64 now, struct rq *rq, int running);
+ int update_dl_rq_load_avg(u64 now, struct rq *rq, int running);
++#endif
+
+-#ifdef CONFIG_SCHED_THERMAL_PRESSURE
++#if defined(CONFIG_SCHED_THERMAL_PRESSURE) && !defined(CONFIG_SCHED_ALT)
+ int update_thermal_load_avg(u64 now, struct rq *rq, u64 capacity);
+
+ static inline u64 thermal_load_avg(struct rq *rq)
+@@ -44,6 +46,7 @@ static inline u32 get_pelt_divider(struct sched_avg *avg)
+ return PELT_MIN_DIVIDER + avg->period_contrib;
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ static inline void cfs_se_util_change(struct sched_avg *avg)
+ {
+ unsigned int enqueued;
+@@ -180,9 +183,11 @@ static inline u64 cfs_rq_clock_pelt(struct cfs_rq *cfs_rq)
+ return rq_clock_pelt(rq_of(cfs_rq));
+ }
+ #endif
++#endif /* CONFIG_SCHED_ALT */
+
+ #else
+
++#ifndef CONFIG_SCHED_ALT
+ static inline int
+ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
+ {
+@@ -200,6 +205,7 @@ update_dl_rq_load_avg(u64 now, struct rq *rq, int running)
+ {
+ return 0;
+ }
++#endif
+
+ static inline int
+ update_thermal_load_avg(u64 now, struct rq *rq, u64 capacity)
+diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
+index 001fe047bd5d..a2fafb8f3306 100644
+--- a/kernel/sched/sched.h
++++ b/kernel/sched/sched.h
+@@ -5,6 +5,10 @@
+ #ifndef _KERNEL_SCHED_SCHED_H
+ #define _KERNEL_SCHED_SCHED_H
+
++#ifdef CONFIG_SCHED_ALT
++#include "alt_sched.h"
++#else
++
+ #include <linux/sched/affinity.h>
+ #include <linux/sched/autogroup.h>
+ #include <linux/sched/cpufreq.h>
+@@ -3473,4 +3477,9 @@ static inline void init_sched_mm_cid(struct task_struct *t) { }
+ extern u64 avg_vruntime(struct cfs_rq *cfs_rq);
+ extern int entity_eligible(struct cfs_rq *cfs_rq, struct sched_entity *se);
+
++static inline int task_running_nice(struct task_struct *p)
++{
++ return (task_nice(p) > 0);
++}
++#endif /* !CONFIG_SCHED_ALT */
+ #endif /* _KERNEL_SCHED_SCHED_H */
+diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c
+index 857f837f52cb..5486c63e4790 100644
+--- a/kernel/sched/stats.c
++++ b/kernel/sched/stats.c
+@@ -125,8 +125,10 @@ static int show_schedstat(struct seq_file *seq, void *v)
+ } else {
+ struct rq *rq;
+ #ifdef CONFIG_SMP
++#ifndef CONFIG_SCHED_ALT
+ struct sched_domain *sd;
+ int dcount = 0;
++#endif
+ #endif
+ cpu = (unsigned long)(v - 2);
+ rq = cpu_rq(cpu);
+@@ -143,6 +145,7 @@ static int show_schedstat(struct seq_file *seq, void *v)
+ seq_printf(seq, "\n");
+
+ #ifdef CONFIG_SMP
++#ifndef CONFIG_SCHED_ALT
+ /* domain-specific stats */
+ rcu_read_lock();
+ for_each_domain(cpu, sd) {
+@@ -171,6 +174,7 @@ static int show_schedstat(struct seq_file *seq, void *v)
+ sd->ttwu_move_balance);
+ }
+ rcu_read_unlock();
++#endif
+ #endif
+ }
+ return 0;
+diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h
+index 38f3698f5e5b..b9d597394316 100644
+--- a/kernel/sched/stats.h
++++ b/kernel/sched/stats.h
+@@ -89,6 +89,7 @@ static inline void rq_sched_info_depart (struct rq *rq, unsigned long long delt
+
+ #endif /* CONFIG_SCHEDSTATS */
+
++#ifndef CONFIG_SCHED_ALT
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ struct sched_entity_stats {
+ struct sched_entity se;
+@@ -105,6 +106,7 @@ __schedstats_from_se(struct sched_entity *se)
+ #endif
+ return &task_of(se)->stats;
+ }
++#endif /* CONFIG_SCHED_ALT */
+
+ #ifdef CONFIG_PSI
+ void psi_task_change(struct task_struct *task, int clear, int set);
+diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
+index 10d1391e7416..dc717683342e 100644
+--- a/kernel/sched/topology.c
++++ b/kernel/sched/topology.c
+@@ -3,6 +3,7 @@
+ * Scheduler topology setup/handling methods
+ */
+
++#ifndef CONFIG_SCHED_ALT
+ #include <linux/bsearch.h>
+
+ DEFINE_MUTEX(sched_domains_mutex);
+@@ -1445,8 +1446,10 @@ static void asym_cpu_capacity_scan(void)
+ */
+
+ static int default_relax_domain_level = -1;
++#endif /* CONFIG_SCHED_ALT */
+ int sched_domain_level_max;
+
++#ifndef CONFIG_SCHED_ALT
+ static int __init setup_relax_domain_level(char *str)
+ {
+ if (kstrtoint(str, 0, &default_relax_domain_level))
+@@ -1680,6 +1683,7 @@ sd_init(struct sched_domain_topology_level *tl,
+
+ return sd;
+ }
++#endif /* CONFIG_SCHED_ALT */
+
+ /*
+ * Topology list, bottom-up.
+@@ -1716,6 +1720,7 @@ void __init set_sched_topology(struct sched_domain_topology_level *tl)
+ sched_domain_topology_saved = NULL;
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ #ifdef CONFIG_NUMA
+
+ static const struct cpumask *sd_numa_mask(int cpu)
+@@ -2793,3 +2798,26 @@ void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
+ partition_sched_domains_locked(ndoms_new, doms_new, dattr_new);
+ mutex_unlock(&sched_domains_mutex);
+ }
++#else /* CONFIG_SCHED_ALT */
++void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
++ struct sched_domain_attr *dattr_new)
++{}
++
++#ifdef CONFIG_NUMA
++int sched_numa_find_closest(const struct cpumask *cpus, int cpu)
++{
++ return best_mask_cpu(cpu, cpus);
++}
++
++int sched_numa_find_nth_cpu(const struct cpumask *cpus, int cpu, int node)
++{
++ return cpumask_nth(cpu, cpus);
++}
++
++const struct cpumask *sched_numa_hop_mask(unsigned int node, unsigned int hops)
++{
++ return ERR_PTR(-EOPNOTSUPP);
++}
++EXPORT_SYMBOL_GPL(sched_numa_hop_mask);
++#endif /* CONFIG_NUMA */
++#endif
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index 157f7ce2942d..63083a9a2935 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -92,6 +92,10 @@ EXPORT_SYMBOL_GPL(sysctl_long_vals);
+
+ /* Constants used for minimum and maximum */
+
++#ifdef CONFIG_SCHED_ALT
++extern int sched_yield_type;
++#endif
++
+ #ifdef CONFIG_PERF_EVENTS
+ static const int six_hundred_forty_kb = 640 * 1024;
+ #endif
+@@ -1912,6 +1916,17 @@ static struct ctl_table kern_table[] = {
+ .proc_handler = proc_dointvec,
+ },
+ #endif
++#ifdef CONFIG_SCHED_ALT
++ {
++ .procname = "yield_type",
++ .data = &sched_yield_type,
++ .maxlen = sizeof (int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec_minmax,
++ .extra1 = SYSCTL_ZERO,
++ .extra2 = SYSCTL_TWO,
++ },
++#endif
+ #if defined(CONFIG_S390) && defined(CONFIG_SMP)
+ {
+ .procname = "spin_retry",
+diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
+index edb0f821dcea..bfc4a6afc77e 100644
+--- a/kernel/time/hrtimer.c
++++ b/kernel/time/hrtimer.c
+@@ -2092,8 +2092,10 @@ long hrtimer_nanosleep(ktime_t rqtp, const enum hrtimer_mode mode,
+ int ret = 0;
+ u64 slack;
+
++#ifndef CONFIG_SCHED_ALT
+ slack = current->timer_slack_ns;
+- if (rt_task(current))
++ if (dl_task(current) || rt_task(current))
++#endif
+ slack = 0;
+
+ hrtimer_init_sleeper_on_stack(&t, clockid, mode);
+diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
+index e9c6f9d0e42c..43ee0a94abdd 100644
+--- a/kernel/time/posix-cpu-timers.c
++++ b/kernel/time/posix-cpu-timers.c
+@@ -223,7 +223,7 @@ static void task_sample_cputime(struct task_struct *p, u64 *samples)
+ u64 stime, utime;
+
+ task_cputime(p, &utime, &stime);
+- store_samples(samples, stime, utime, p->se.sum_exec_runtime);
++ store_samples(samples, stime, utime, tsk_seruntime(p));
+ }
+
+ static void proc_sample_cputime_atomic(struct task_cputime_atomic *at,
+@@ -867,6 +867,7 @@ static void collect_posix_cputimers(struct posix_cputimers *pct, u64 *samples,
+ }
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ static inline void check_dl_overrun(struct task_struct *tsk)
+ {
+ if (tsk->dl.dl_overrun) {
+@@ -874,6 +875,7 @@ static inline void check_dl_overrun(struct task_struct *tsk)
+ send_signal_locked(SIGXCPU, SEND_SIG_PRIV, tsk, PIDTYPE_TGID);
+ }
+ }
++#endif
+
+ static bool check_rlimit(u64 time, u64 limit, int signo, bool rt, bool hard)
+ {
+@@ -901,8 +903,10 @@ static void check_thread_timers(struct task_struct *tsk,
+ u64 samples[CPUCLOCK_MAX];
+ unsigned long soft;
+
++#ifndef CONFIG_SCHED_ALT
+ if (dl_task(tsk))
+ check_dl_overrun(tsk);
++#endif
+
+ if (expiry_cache_is_inactive(pct))
+ return;
+@@ -916,7 +920,7 @@ static void check_thread_timers(struct task_struct *tsk,
+ soft = task_rlimit(tsk, RLIMIT_RTTIME);
+ if (soft != RLIM_INFINITY) {
+ /* Task RT timeout is accounted in jiffies. RTTIME is usec */
+- unsigned long rttime = tsk->rt.timeout * (USEC_PER_SEC / HZ);
++ unsigned long rttime = tsk_rttimeout(tsk) * (USEC_PER_SEC / HZ);
+ unsigned long hard = task_rlimit_max(tsk, RLIMIT_RTTIME);
+
+ /* At the hard limit, send SIGKILL. No further action. */
+@@ -1152,8 +1156,10 @@ static inline bool fastpath_timer_check(struct task_struct *tsk)
+ return true;
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ if (dl_task(tsk) && tsk->dl.dl_overrun)
+ return true;
++#endif
+
+ return false;
+ }
+diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
+index 529590499b1f..d04bb99b4f0e 100644
+--- a/kernel/trace/trace_selftest.c
++++ b/kernel/trace/trace_selftest.c
+@@ -1155,10 +1155,15 @@ static int trace_wakeup_test_thread(void *data)
+ {
+ /* Make this a -deadline thread */
+ static const struct sched_attr attr = {
++#ifdef CONFIG_SCHED_ALT
++ /* No deadline on BMQ/PDS, use RR */
++ .sched_policy = SCHED_RR,
++#else
+ .sched_policy = SCHED_DEADLINE,
+ .sched_runtime = 100000ULL,
+ .sched_deadline = 10000000ULL,
+ .sched_period = 10000000ULL
++#endif
+ };
+ struct wakeup_test_data *x = data;
+
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index 7b482a26d741..e5b053326631 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -1120,6 +1120,7 @@ static bool kick_pool(struct worker_pool *pool)
+
+ p = worker->task;
+
++#ifndef CONFIG_SCHED_ALT
+ #ifdef CONFIG_SMP
+ /*
+ * Idle @worker is about to execute @work and waking up provides an
+@@ -1145,6 +1146,8 @@ static bool kick_pool(struct worker_pool *pool)
+ get_work_pwq(work)->stats[PWQ_STAT_REPATRIATED]++;
+ }
+ #endif
++#endif /* !CONFIG_SCHED_ALT */
++
+ wake_up_process(p);
+ return true;
+ }
+@@ -1269,7 +1272,11 @@ void wq_worker_running(struct task_struct *task)
+ * CPU intensive auto-detection cares about how long a work item hogged
+ * CPU without sleeping. Reset the starting timestamp on wakeup.
+ */
++#ifdef CONFIG_SCHED_ALT
++ worker->current_at = worker->task->sched_time;
++#else
+ worker->current_at = worker->task->se.sum_exec_runtime;
++#endif
+
+ WRITE_ONCE(worker->sleeping, 0);
+ }
+@@ -1354,7 +1361,11 @@ void wq_worker_tick(struct task_struct *task)
+ * We probably want to make this prettier in the future.
+ */
+ if ((worker->flags & WORKER_NOT_RUNNING) || READ_ONCE(worker->sleeping) ||
++#ifdef CONFIG_SCHED_ALT
++ worker->task->sched_time - worker->current_at <
++#else
+ worker->task->se.sum_exec_runtime - worker->current_at <
++#endif
+ wq_cpu_intensive_thresh_us * NSEC_PER_USEC)
+ return;
+
+@@ -2565,7 +2576,11 @@ __acquires(&pool->lock)
+ worker->current_work = work;
+ worker->current_func = work->func;
+ worker->current_pwq = pwq;
++#ifdef CONFIG_SCHED_ALT
++ worker->current_at = worker->task->sched_time;
++#else
+ worker->current_at = worker->task->se.sum_exec_runtime;
++#endif
+ work_data = *work_data_bits(work);
+ worker->current_color = get_work_color(work_data);
+
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-03-15 21:58 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-03-15 21:58 UTC (permalink / raw
To: gentoo-commits
commit: 8c47d4e09a8d4127e428ed961b17408e56d0f7ab
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Fri Mar 15 21:58:25 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Fri Mar 15 21:58:25 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=8c47d4e0
Linux patch 6.8.1
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1001_linux-6.8.1.patch | 523 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 527 insertions(+)
diff --git a/0000_README b/0000_README
index e6b9bd5b..5fe89b7e 100644
--- a/0000_README
+++ b/0000_README
@@ -43,6 +43,10 @@ EXPERIMENTAL
Individual Patch Descriptions:
--------------------------------------------------------------------------
+Patch: 1000_linux-6.8.1.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.1
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1001_linux-6.8.1.patch b/1001_linux-6.8.1.patch
new file mode 100644
index 00000000..071efefa
--- /dev/null
+++ b/1001_linux-6.8.1.patch
@@ -0,0 +1,523 @@
+diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
+index a1db6db475055..710d47be11e04 100644
+--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
++++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
+@@ -516,6 +516,7 @@ What: /sys/devices/system/cpu/vulnerabilities
+ /sys/devices/system/cpu/vulnerabilities/mds
+ /sys/devices/system/cpu/vulnerabilities/meltdown
+ /sys/devices/system/cpu/vulnerabilities/mmio_stale_data
++ /sys/devices/system/cpu/vulnerabilities/reg_file_data_sampling
+ /sys/devices/system/cpu/vulnerabilities/retbleed
+ /sys/devices/system/cpu/vulnerabilities/spec_store_bypass
+ /sys/devices/system/cpu/vulnerabilities/spectre_v1
+diff --git a/Documentation/admin-guide/hw-vuln/index.rst b/Documentation/admin-guide/hw-vuln/index.rst
+index de99caabf65a3..ff0b440ef2dc9 100644
+--- a/Documentation/admin-guide/hw-vuln/index.rst
++++ b/Documentation/admin-guide/hw-vuln/index.rst
+@@ -21,3 +21,4 @@ are configurable at compile, boot or run time.
+ cross-thread-rsb
+ srso
+ gather_data_sampling
++ reg-file-data-sampling
+diff --git a/Documentation/admin-guide/hw-vuln/reg-file-data-sampling.rst b/Documentation/admin-guide/hw-vuln/reg-file-data-sampling.rst
+new file mode 100644
+index 0000000000000..0585d02b9a6cb
+--- /dev/null
++++ b/Documentation/admin-guide/hw-vuln/reg-file-data-sampling.rst
+@@ -0,0 +1,104 @@
++==================================
++Register File Data Sampling (RFDS)
++==================================
++
++Register File Data Sampling (RFDS) is a microarchitectural vulnerability that
++only affects Intel Atom parts(also branded as E-cores). RFDS may allow
++a malicious actor to infer data values previously used in floating point
++registers, vector registers, or integer registers. RFDS does not provide the
++ability to choose which data is inferred. CVE-2023-28746 is assigned to RFDS.
++
++Affected Processors
++===================
++Below is the list of affected Intel processors [#f1]_:
++
++ =================== ============
++ Common name Family_Model
++ =================== ============
++ ATOM_GOLDMONT 06_5CH
++ ATOM_GOLDMONT_D 06_5FH
++ ATOM_GOLDMONT_PLUS 06_7AH
++ ATOM_TREMONT_D 06_86H
++ ATOM_TREMONT 06_96H
++ ALDERLAKE 06_97H
++ ALDERLAKE_L 06_9AH
++ ATOM_TREMONT_L 06_9CH
++ RAPTORLAKE 06_B7H
++ RAPTORLAKE_P 06_BAH
++ ATOM_GRACEMONT 06_BEH
++ RAPTORLAKE_S 06_BFH
++ =================== ============
++
++As an exception to this table, Intel Xeon E family parts ALDERLAKE(06_97H) and
++RAPTORLAKE(06_B7H) codenamed Catlow are not affected. They are reported as
++vulnerable in Linux because they share the same family/model with an affected
++part. Unlike their affected counterparts, they do not enumerate RFDS_CLEAR or
++CPUID.HYBRID. This information could be used to distinguish between the
++affected and unaffected parts, but it is deemed not worth adding complexity as
++the reporting is fixed automatically when these parts enumerate RFDS_NO.
++
++Mitigation
++==========
++Intel released a microcode update that enables software to clear sensitive
++information using the VERW instruction. Like MDS, RFDS deploys the same
++mitigation strategy to force the CPU to clear the affected buffers before an
++attacker can extract the secrets. This is achieved by using the otherwise
++unused and obsolete VERW instruction in combination with a microcode update.
++The microcode clears the affected CPU buffers when the VERW instruction is
++executed.
++
++Mitigation points
++-----------------
++VERW is executed by the kernel before returning to user space, and by KVM
++before VMentry. None of the affected cores support SMT, so VERW is not required
++at C-state transitions.
++
++New bits in IA32_ARCH_CAPABILITIES
++----------------------------------
++Newer processors and microcode update on existing affected processors added new
++bits to IA32_ARCH_CAPABILITIES MSR. These bits can be used to enumerate
++vulnerability and mitigation capability:
++
++- Bit 27 - RFDS_NO - When set, processor is not affected by RFDS.
++- Bit 28 - RFDS_CLEAR - When set, processor is affected by RFDS, and has the
++ microcode that clears the affected buffers on VERW execution.
++
++Mitigation control on the kernel command line
++---------------------------------------------
++The kernel command line allows to control RFDS mitigation at boot time with the
++parameter "reg_file_data_sampling=". The valid arguments are:
++
++ ========== =================================================================
++ on If the CPU is vulnerable, enable mitigation; CPU buffer clearing
++ on exit to userspace and before entering a VM.
++ off Disables mitigation.
++ ========== =================================================================
++
++Mitigation default is selected by CONFIG_MITIGATION_RFDS.
++
++Mitigation status information
++-----------------------------
++The Linux kernel provides a sysfs interface to enumerate the current
++vulnerability status of the system: whether the system is vulnerable, and
++which mitigations are active. The relevant sysfs file is:
++
++ /sys/devices/system/cpu/vulnerabilities/reg_file_data_sampling
++
++The possible values in this file are:
++
++ .. list-table::
++
++ * - 'Not affected'
++ - The processor is not vulnerable
++ * - 'Vulnerable'
++ - The processor is vulnerable, but no mitigation enabled
++ * - 'Vulnerable: No microcode'
++ - The processor is vulnerable but microcode is not updated.
++ * - 'Mitigation: Clear Register File'
++ - The processor is vulnerable and the CPU buffer clearing mitigation is
++ enabled.
++
++References
++----------
++.. [#f1] Affected Processors
++ https://www.intel.com/content/www/us/en/developer/topic-technology/software-security-guidance/processors-affected-consolidated-product-cpu-model.html
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index 31b3a25680d08..73062d47a462e 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -1150,6 +1150,26 @@
+ The filter can be disabled or changed to another
+ driver later using sysfs.
+
++ reg_file_data_sampling=
++ [X86] Controls mitigation for Register File Data
++ Sampling (RFDS) vulnerability. RFDS is a CPU
++ vulnerability which may allow userspace to infer
++ kernel data values previously stored in floating point
++ registers, vector registers, or integer registers.
++ RFDS only affects Intel Atom processors.
++
++ on: Turns ON the mitigation.
++ off: Turns OFF the mitigation.
++
++ This parameter overrides the compile time default set
++ by CONFIG_MITIGATION_RFDS. Mitigation cannot be
++ disabled when other VERW based mitigations (like MDS)
++ are enabled. In order to disable RFDS mitigation all
++ VERW based mitigations need to be disabled.
++
++ For details see:
++ Documentation/admin-guide/hw-vuln/reg-file-data-sampling.rst
++
+ driver_async_probe= [KNL]
+ List of driver names to be probed asynchronously. *
+ matches with all driver names. If * is specified, the
+@@ -3398,6 +3418,7 @@
+ nospectre_bhb [ARM64]
+ nospectre_v1 [X86,PPC]
+ nospectre_v2 [X86,PPC,S390,ARM64]
++ reg_file_data_sampling=off [X86]
+ retbleed=off [X86]
+ spec_store_bypass_disable=off [X86,PPC]
+ spectre_v2_user=off [X86]
+diff --git a/Makefile b/Makefile
+index c7ee53f4bf044..95b320ada47c4 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 0
++SUBLEVEL = 1
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 5edec175b9bfc..637e337c332e4 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -2614,6 +2614,17 @@ config GDS_FORCE_MITIGATION
+
+ If in doubt, say N.
+
++config MITIGATION_RFDS
++ bool "RFDS Mitigation"
++ depends on CPU_SUP_INTEL
++ default y
++ help
++ Enable mitigation for Register File Data Sampling (RFDS) by default.
++ RFDS is a hardware vulnerability which affects Intel Atom CPUs. It
++ allows unprivileged speculative access to stale data previously
++ stored in floating point, vector and integer registers.
++ See also <file:Documentation/admin-guide/hw-vuln/reg-file-data-sampling.rst>
++
+ endif
+
+ config ARCH_HAS_ADD_PAGES
+diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
+index 2b62cdd8dd122..8511aad595813 100644
+--- a/arch/x86/include/asm/cpufeatures.h
++++ b/arch/x86/include/asm/cpufeatures.h
+@@ -503,4 +503,5 @@
+ /* BUG word 2 */
+ #define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */
+ #define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */
++#define X86_BUG_RFDS X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */
+ #endif /* _ASM_X86_CPUFEATURES_H */
+diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
+index f1bd7b91b3c63..d1b5edaf6c34b 100644
+--- a/arch/x86/include/asm/msr-index.h
++++ b/arch/x86/include/asm/msr-index.h
+@@ -165,6 +165,14 @@
+ * CPU is not vulnerable to Gather
+ * Data Sampling (GDS).
+ */
++#define ARCH_CAP_RFDS_NO BIT(27) /*
++ * Not susceptible to Register
++ * File Data Sampling.
++ */
++#define ARCH_CAP_RFDS_CLEAR BIT(28) /*
++ * VERW clears CPU Register
++ * File.
++ */
+
+ #define ARCH_CAP_XAPIC_DISABLE BIT(21) /*
+ * IA32_XAPIC_DISABLE_STATUS MSR
+diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
+index 48d049cd74e71..01ac18f56147f 100644
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -422,6 +422,13 @@ static void __init mmio_select_mitigation(void)
+ if (boot_cpu_has_bug(X86_BUG_MDS) || (boot_cpu_has_bug(X86_BUG_TAA) &&
+ boot_cpu_has(X86_FEATURE_RTM)))
+ setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF);
++
++ /*
++ * X86_FEATURE_CLEAR_CPU_BUF could be enabled by other VERW based
++ * mitigations, disable KVM-only mitigation in that case.
++ */
++ if (boot_cpu_has(X86_FEATURE_CLEAR_CPU_BUF))
++ static_branch_disable(&mmio_stale_data_clear);
+ else
+ static_branch_enable(&mmio_stale_data_clear);
+
+@@ -473,6 +480,57 @@ static int __init mmio_stale_data_parse_cmdline(char *str)
+ }
+ early_param("mmio_stale_data", mmio_stale_data_parse_cmdline);
+
++#undef pr_fmt
++#define pr_fmt(fmt) "Register File Data Sampling: " fmt
++
++enum rfds_mitigations {
++ RFDS_MITIGATION_OFF,
++ RFDS_MITIGATION_VERW,
++ RFDS_MITIGATION_UCODE_NEEDED,
++};
++
++/* Default mitigation for Register File Data Sampling */
++static enum rfds_mitigations rfds_mitigation __ro_after_init =
++ IS_ENABLED(CONFIG_MITIGATION_RFDS) ? RFDS_MITIGATION_VERW : RFDS_MITIGATION_OFF;
++
++static const char * const rfds_strings[] = {
++ [RFDS_MITIGATION_OFF] = "Vulnerable",
++ [RFDS_MITIGATION_VERW] = "Mitigation: Clear Register File",
++ [RFDS_MITIGATION_UCODE_NEEDED] = "Vulnerable: No microcode",
++};
++
++static void __init rfds_select_mitigation(void)
++{
++ if (!boot_cpu_has_bug(X86_BUG_RFDS) || cpu_mitigations_off()) {
++ rfds_mitigation = RFDS_MITIGATION_OFF;
++ return;
++ }
++ if (rfds_mitigation == RFDS_MITIGATION_OFF)
++ return;
++
++ if (x86_read_arch_cap_msr() & ARCH_CAP_RFDS_CLEAR)
++ setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF);
++ else
++ rfds_mitigation = RFDS_MITIGATION_UCODE_NEEDED;
++}
++
++static __init int rfds_parse_cmdline(char *str)
++{
++ if (!str)
++ return -EINVAL;
++
++ if (!boot_cpu_has_bug(X86_BUG_RFDS))
++ return 0;
++
++ if (!strcmp(str, "off"))
++ rfds_mitigation = RFDS_MITIGATION_OFF;
++ else if (!strcmp(str, "on"))
++ rfds_mitigation = RFDS_MITIGATION_VERW;
++
++ return 0;
++}
++early_param("reg_file_data_sampling", rfds_parse_cmdline);
++
+ #undef pr_fmt
+ #define pr_fmt(fmt) "" fmt
+
+@@ -498,11 +556,19 @@ static void __init md_clear_update_mitigation(void)
+ taa_mitigation = TAA_MITIGATION_VERW;
+ taa_select_mitigation();
+ }
+- if (mmio_mitigation == MMIO_MITIGATION_OFF &&
+- boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA)) {
++ /*
++ * MMIO_MITIGATION_OFF is not checked here so that mmio_stale_data_clear
++ * gets updated correctly as per X86_FEATURE_CLEAR_CPU_BUF state.
++ */
++ if (boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA)) {
+ mmio_mitigation = MMIO_MITIGATION_VERW;
+ mmio_select_mitigation();
+ }
++ if (rfds_mitigation == RFDS_MITIGATION_OFF &&
++ boot_cpu_has_bug(X86_BUG_RFDS)) {
++ rfds_mitigation = RFDS_MITIGATION_VERW;
++ rfds_select_mitigation();
++ }
+ out:
+ if (boot_cpu_has_bug(X86_BUG_MDS))
+ pr_info("MDS: %s\n", mds_strings[mds_mitigation]);
+@@ -512,6 +578,8 @@ static void __init md_clear_update_mitigation(void)
+ pr_info("MMIO Stale Data: %s\n", mmio_strings[mmio_mitigation]);
+ else if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
+ pr_info("MMIO Stale Data: Unknown: No mitigations\n");
++ if (boot_cpu_has_bug(X86_BUG_RFDS))
++ pr_info("Register File Data Sampling: %s\n", rfds_strings[rfds_mitigation]);
+ }
+
+ static void __init md_clear_select_mitigation(void)
+@@ -519,11 +587,12 @@ static void __init md_clear_select_mitigation(void)
+ mds_select_mitigation();
+ taa_select_mitigation();
+ mmio_select_mitigation();
++ rfds_select_mitigation();
+
+ /*
+- * As MDS, TAA and MMIO Stale Data mitigations are inter-related, update
+- * and print their mitigation after MDS, TAA and MMIO Stale Data
+- * mitigation selection is done.
++ * As these mitigations are inter-related and rely on VERW instruction
++ * to clear the microarchitural buffers, update and print their status
++ * after mitigation selection is done for each of these vulnerabilities.
+ */
+ md_clear_update_mitigation();
+ }
+@@ -2612,6 +2681,11 @@ static ssize_t mmio_stale_data_show_state(char *buf)
+ sched_smt_active() ? "vulnerable" : "disabled");
+ }
+
++static ssize_t rfds_show_state(char *buf)
++{
++ return sysfs_emit(buf, "%s\n", rfds_strings[rfds_mitigation]);
++}
++
+ static char *stibp_state(void)
+ {
+ if (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
+@@ -2771,6 +2845,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
+ case X86_BUG_GDS:
+ return gds_show_state(buf);
+
++ case X86_BUG_RFDS:
++ return rfds_show_state(buf);
++
+ default:
+ break;
+ }
+@@ -2845,4 +2922,9 @@ ssize_t cpu_show_gds(struct device *dev, struct device_attribute *attr, char *bu
+ {
+ return cpu_show_common(dev, attr, buf, X86_BUG_GDS);
+ }
++
++ssize_t cpu_show_reg_file_data_sampling(struct device *dev, struct device_attribute *attr, char *buf)
++{
++ return cpu_show_common(dev, attr, buf, X86_BUG_RFDS);
++}
+ #endif
+diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
+index fbc4e60d027cb..40d8c110bb32e 100644
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -1267,6 +1267,8 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
+ #define SRSO BIT(5)
+ /* CPU is affected by GDS */
+ #define GDS BIT(6)
++/* CPU is affected by Register File Data Sampling */
++#define RFDS BIT(7)
+
+ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
+ VULNBL_INTEL_STEPPINGS(IVYBRIDGE, X86_STEPPING_ANY, SRBDS),
+@@ -1294,9 +1296,18 @@ static const struct x86_cpu_id cpu_vuln_blacklist[] __initconst = {
+ VULNBL_INTEL_STEPPINGS(TIGERLAKE, X86_STEPPING_ANY, GDS),
+ VULNBL_INTEL_STEPPINGS(LAKEFIELD, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RETBLEED),
+ VULNBL_INTEL_STEPPINGS(ROCKETLAKE, X86_STEPPING_ANY, MMIO | RETBLEED | GDS),
+- VULNBL_INTEL_STEPPINGS(ATOM_TREMONT, X86_STEPPING_ANY, MMIO | MMIO_SBDS),
+- VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPING_ANY, MMIO),
+- VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS),
++ VULNBL_INTEL_STEPPINGS(ALDERLAKE, X86_STEPPING_ANY, RFDS),
++ VULNBL_INTEL_STEPPINGS(ALDERLAKE_L, X86_STEPPING_ANY, RFDS),
++ VULNBL_INTEL_STEPPINGS(RAPTORLAKE, X86_STEPPING_ANY, RFDS),
++ VULNBL_INTEL_STEPPINGS(RAPTORLAKE_P, X86_STEPPING_ANY, RFDS),
++ VULNBL_INTEL_STEPPINGS(RAPTORLAKE_S, X86_STEPPING_ANY, RFDS),
++ VULNBL_INTEL_STEPPINGS(ATOM_GRACEMONT, X86_STEPPING_ANY, RFDS),
++ VULNBL_INTEL_STEPPINGS(ATOM_TREMONT, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RFDS),
++ VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_D, X86_STEPPING_ANY, MMIO | RFDS),
++ VULNBL_INTEL_STEPPINGS(ATOM_TREMONT_L, X86_STEPPING_ANY, MMIO | MMIO_SBDS | RFDS),
++ VULNBL_INTEL_STEPPINGS(ATOM_GOLDMONT, X86_STEPPING_ANY, RFDS),
++ VULNBL_INTEL_STEPPINGS(ATOM_GOLDMONT_D, X86_STEPPING_ANY, RFDS),
++ VULNBL_INTEL_STEPPINGS(ATOM_GOLDMONT_PLUS, X86_STEPPING_ANY, RFDS),
+
+ VULNBL_AMD(0x15, RETBLEED),
+ VULNBL_AMD(0x16, RETBLEED),
+@@ -1330,6 +1341,24 @@ static bool arch_cap_mmio_immune(u64 ia32_cap)
+ ia32_cap & ARCH_CAP_SBDR_SSDP_NO);
+ }
+
++static bool __init vulnerable_to_rfds(u64 ia32_cap)
++{
++ /* The "immunity" bit trumps everything else: */
++ if (ia32_cap & ARCH_CAP_RFDS_NO)
++ return false;
++
++ /*
++ * VMMs set ARCH_CAP_RFDS_CLEAR for processors not in the blacklist to
++ * indicate that mitigation is needed because guest is running on a
++ * vulnerable hardware or may migrate to such hardware:
++ */
++ if (ia32_cap & ARCH_CAP_RFDS_CLEAR)
++ return true;
++
++ /* Only consult the blacklist when there is no enumeration: */
++ return cpu_matches(cpu_vuln_blacklist, RFDS);
++}
++
+ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ {
+ u64 ia32_cap = x86_read_arch_cap_msr();
+@@ -1441,6 +1470,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ boot_cpu_has(X86_FEATURE_AVX))
+ setup_force_cpu_bug(X86_BUG_GDS);
+
++ if (vulnerable_to_rfds(ia32_cap))
++ setup_force_cpu_bug(X86_BUG_RFDS);
++
+ if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
+ return;
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index e02cc710f56de..ffe580169c93f 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -1623,7 +1623,8 @@ static bool kvm_is_immutable_feature_msr(u32 msr)
+ ARCH_CAP_SKIP_VMENTRY_L1DFLUSH | ARCH_CAP_SSB_NO | ARCH_CAP_MDS_NO | \
+ ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \
+ ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \
+- ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO | ARCH_CAP_GDS_NO)
++ ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO | ARCH_CAP_GDS_NO | \
++ ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR)
+
+ static u64 kvm_get_arch_capabilities(void)
+ {
+@@ -1655,6 +1656,8 @@ static u64 kvm_get_arch_capabilities(void)
+ data |= ARCH_CAP_SSB_NO;
+ if (!boot_cpu_has_bug(X86_BUG_MDS))
+ data |= ARCH_CAP_MDS_NO;
++ if (!boot_cpu_has_bug(X86_BUG_RFDS))
++ data |= ARCH_CAP_RFDS_NO;
+
+ if (!boot_cpu_has(X86_FEATURE_RTM)) {
+ /*
+diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
+index 47de0f140ba65..0b33e81f9c9b6 100644
+--- a/drivers/base/cpu.c
++++ b/drivers/base/cpu.c
+@@ -588,6 +588,7 @@ CPU_SHOW_VULN_FALLBACK(mmio_stale_data);
+ CPU_SHOW_VULN_FALLBACK(retbleed);
+ CPU_SHOW_VULN_FALLBACK(spec_rstack_overflow);
+ CPU_SHOW_VULN_FALLBACK(gds);
++CPU_SHOW_VULN_FALLBACK(reg_file_data_sampling);
+
+ static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
+ static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
+@@ -602,6 +603,7 @@ static DEVICE_ATTR(mmio_stale_data, 0444, cpu_show_mmio_stale_data, NULL);
+ static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL);
+ static DEVICE_ATTR(spec_rstack_overflow, 0444, cpu_show_spec_rstack_overflow, NULL);
+ static DEVICE_ATTR(gather_data_sampling, 0444, cpu_show_gds, NULL);
++static DEVICE_ATTR(reg_file_data_sampling, 0444, cpu_show_reg_file_data_sampling, NULL);
+
+ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
+ &dev_attr_meltdown.attr,
+@@ -617,6 +619,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
+ &dev_attr_retbleed.attr,
+ &dev_attr_spec_rstack_overflow.attr,
+ &dev_attr_gather_data_sampling.attr,
++ &dev_attr_reg_file_data_sampling.attr,
+ NULL
+ };
+
+diff --git a/include/linux/cpu.h b/include/linux/cpu.h
+index dcb89c9871640..8654714421a0d 100644
+--- a/include/linux/cpu.h
++++ b/include/linux/cpu.h
+@@ -75,6 +75,8 @@ extern ssize_t cpu_show_spec_rstack_overflow(struct device *dev,
+ struct device_attribute *attr, char *buf);
+ extern ssize_t cpu_show_gds(struct device *dev,
+ struct device_attribute *attr, char *buf);
++extern ssize_t cpu_show_reg_file_data_sampling(struct device *dev,
++ struct device_attribute *attr, char *buf);
+
+ extern __printf(4, 5)
+ struct device *cpu_device_create(struct device *parent, void *drvdata,
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-03-27 11:22 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-03-27 11:22 UTC (permalink / raw
To: gentoo-commits
commit: 3aa27a23fc901db82a7d02bc717bf1699abca15d
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Wed Mar 27 11:21:26 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Wed Mar 27 11:21:26 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=3aa27a23
Linux patch 6.8.2
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1001_linux-6.8.2.patch | 33522 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 33526 insertions(+)
diff --git a/0000_README b/0000_README
index 5fe89b7e..5b18c2c3 100644
--- a/0000_README
+++ b/0000_README
@@ -47,6 +47,10 @@ Patch: 1000_linux-6.8.1.patch
From: https://www.kernel.org
Desc: Linux 6.8.1
+Patch: 1001_linux-6.8.2.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.2
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1001_linux-6.8.2.patch b/1001_linux-6.8.2.patch
new file mode 100644
index 00000000..7e16c762
--- /dev/null
+++ b/1001_linux-6.8.2.patch
@@ -0,0 +1,33522 @@
+diff --git a/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml
+index 0999ea07f47bb..e4576546bf0db 100644
+--- a/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml
++++ b/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml
+@@ -127,6 +127,7 @@ patternProperties:
+ - qcom,dsi-phy-20nm
+ - qcom,dsi-phy-28nm-8226
+ - qcom,dsi-phy-28nm-hpm
++ - qcom,dsi-phy-28nm-hpm-fam-b
+ - qcom,dsi-phy-28nm-lp
+ - qcom,hdmi-phy-8084
+ - qcom,hdmi-phy-8660
+diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
+index a4042ae247702..38c48131e6e7b 100644
+--- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
++++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
+@@ -484,7 +484,12 @@ allOf:
+ - if:
+ properties:
+ compatible:
+- const: qcom,sm8450-smmu-500
++ items:
++ - const: qcom,sm8450-smmu-500
++ - const: qcom,adreno-smmu
++ - const: qcom,smmu-500
++ - const: arm,mmu-500
++
+ then:
+ properties:
+ clock-names:
+@@ -508,7 +513,11 @@ allOf:
+ - if:
+ properties:
+ compatible:
+- const: qcom,sm8550-smmu-500
++ items:
++ - const: qcom,sm8550-smmu-500
++ - const: qcom,adreno-smmu
++ - const: qcom,smmu-500
++ - const: arm,mmu-500
+ then:
+ properties:
+ clock-names:
+diff --git a/Documentation/devicetree/bindings/media/i2c/techwell,tw9900.yaml b/Documentation/devicetree/bindings/media/i2c/techwell,tw9900.yaml
+index e37317f810722..c9673391afdbd 100644
+--- a/Documentation/devicetree/bindings/media/i2c/techwell,tw9900.yaml
++++ b/Documentation/devicetree/bindings/media/i2c/techwell,tw9900.yaml
+@@ -36,7 +36,7 @@ properties:
+
+ properties:
+ port@0:
+- $ref: /schemas/graph.yaml#/$defs/port-base
++ $ref: /schemas/graph.yaml#/properties/port
+ description: Analog input port
+
+ properties:
+diff --git a/Documentation/driver-api/soundwire/stream.rst b/Documentation/driver-api/soundwire/stream.rst
+index b432a2de45d37..2a794484f62c9 100644
+--- a/Documentation/driver-api/soundwire/stream.rst
++++ b/Documentation/driver-api/soundwire/stream.rst
+@@ -324,12 +324,12 @@ framework, this stream state is linked to .hw_params() operation.
+
+ int sdw_stream_add_master(struct sdw_bus * bus,
+ struct sdw_stream_config * stream_config,
+- struct sdw_ports_config * ports_config,
++ const struct sdw_ports_config * ports_config,
+ struct sdw_stream_runtime * stream);
+
+ int sdw_stream_add_slave(struct sdw_slave * slave,
+ struct sdw_stream_config * stream_config,
+- struct sdw_ports_config * ports_config,
++ const struct sdw_ports_config * ports_config,
+ struct sdw_stream_runtime * stream);
+
+
+diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml
+index cf6eaa0da821b..09fbb4c03fc8d 100644
+--- a/Documentation/netlink/specs/devlink.yaml
++++ b/Documentation/netlink/specs/devlink.yaml
+@@ -290,7 +290,7 @@ attribute-sets:
+ enum: eswitch-mode
+ -
+ name: eswitch-inline-mode
+- type: u16
++ type: u8
+ enum: eswitch-inline-mode
+ -
+ name: dpipe-tables
+diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml
+index 3dcc9ece272aa..d0c821c202036 100644
+--- a/Documentation/netlink/specs/dpll.yaml
++++ b/Documentation/netlink/specs/dpll.yaml
+@@ -274,6 +274,7 @@ attribute-sets:
+ -
+ name: capabilities
+ type: u32
++ enum: pin-capabilities
+ -
+ name: parent-device
+ type: nest
+diff --git a/Documentation/networking/net_cachelines/net_device.rst b/Documentation/networking/net_cachelines/net_device.rst
+index dceb49d56a911..70c4fb9d4e5ce 100644
+--- a/Documentation/networking/net_cachelines/net_device.rst
++++ b/Documentation/networking/net_cachelines/net_device.rst
+@@ -13,7 +13,7 @@ struct_dev_ifalias* ifalias
+ unsigned_long mem_end
+ unsigned_long mem_start
+ unsigned_long base_addr
+-unsigned_long state
++unsigned_long state read_mostly read_mostly netif_running(dev)
+ struct_list_head dev_list
+ struct_list_head napi_list
+ struct_list_head unreg_list
+diff --git a/Makefile b/Makefile
+index 95b320ada47c4..33d8e822f6f11 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 1
++SUBLEVEL = 2
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/arch/arm/boot/dts/arm/arm-realview-pb1176.dts b/arch/arm/boot/dts/arm/arm-realview-pb1176.dts
+index efed325af88d2..d99bac02232b3 100644
+--- a/arch/arm/boot/dts/arm/arm-realview-pb1176.dts
++++ b/arch/arm/boot/dts/arm/arm-realview-pb1176.dts
+@@ -451,7 +451,7 @@ pb1176_serial3: serial@1010f000 {
+
+ /* Direct-mapped development chip ROM */
+ pb1176_rom@10200000 {
+- compatible = "direct-mapped";
++ compatible = "mtd-rom";
+ reg = <0x10200000 0x4000>;
+ bank-width = <1>;
+ };
+diff --git a/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-common.dtsi
+index 3be38a3c4bb11..c32ea040fecdd 100644
+--- a/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-common.dtsi
++++ b/arch/arm/boot/dts/nxp/imx/imx6dl-yapp4-common.dtsi
+@@ -117,17 +117,9 @@ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+- phy_port2: phy@1 {
+- reg = <1>;
+- };
+-
+- phy_port3: phy@2 {
+- reg = <2>;
+- };
+-
+ switch@10 {
+ compatible = "qca,qca8334";
+- reg = <10>;
++ reg = <0x10>;
+ reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
+
+ switch_ports: ports {
+@@ -149,15 +141,30 @@ fixed-link {
+ eth2: port@2 {
+ reg = <2>;
+ label = "eth2";
++ phy-mode = "internal";
+ phy-handle = <&phy_port2>;
+ };
+
+ eth1: port@3 {
+ reg = <3>;
+ label = "eth1";
++ phy-mode = "internal";
+ phy-handle = <&phy_port3>;
+ };
+ };
++
++ mdio {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ phy_port2: ethernet-phy@1 {
++ reg = <1>;
++ };
++
++ phy_port3: ethernet-phy@2 {
++ reg = <2>;
++ };
++ };
+ };
+ };
+ };
+diff --git a/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
+index b1413983787c2..083ab780ab7e4 100644
+--- a/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
++++ b/arch/arm/boot/dts/qcom/qcom-msm8974.dtsi
+@@ -1234,7 +1234,7 @@ restart@fc4ab000 {
+
+ qfprom: qfprom@fc4bc000 {
+ compatible = "qcom,msm8974-qfprom", "qcom,qfprom";
+- reg = <0xfc4bc000 0x1000>;
++ reg = <0xfc4bc000 0x2100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+diff --git a/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts
+index ed75c01dbee10..3d02f065f71c2 100644
+--- a/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts
++++ b/arch/arm/boot/dts/renesas/r8a73a4-ape6evm.dts
+@@ -209,6 +209,18 @@ &cmt1 {
+ status = "okay";
+ };
+
++&extal1_clk {
++ clock-frequency = <26000000>;
++};
++
++&extal2_clk {
++ clock-frequency = <48000000>;
++};
++
++&extalr_clk {
++ clock-frequency = <32768>;
++};
++
+ &pfc {
+ scifa0_pins: scifa0 {
+ groups = "scifa0_data";
+diff --git a/arch/arm/boot/dts/renesas/r8a73a4.dtsi b/arch/arm/boot/dts/renesas/r8a73a4.dtsi
+index c39066967053f..d1f4cbd099efb 100644
+--- a/arch/arm/boot/dts/renesas/r8a73a4.dtsi
++++ b/arch/arm/boot/dts/renesas/r8a73a4.dtsi
+@@ -450,17 +450,20 @@ clocks {
+ extalr_clk: extalr {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+- clock-frequency = <32768>;
++ /* This value must be overridden by the board. */
++ clock-frequency = <0>;
+ };
+ extal1_clk: extal1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+- clock-frequency = <25000000>;
++ /* This value must be overridden by the board. */
++ clock-frequency = <0>;
+ };
+ extal2_clk: extal2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+- clock-frequency = <48000000>;
++ /* This value must be overridden by the board. */
++ clock-frequency = <0>;
+ };
+ fsiack_clk: fsiack {
+ compatible = "fixed-clock";
+diff --git a/arch/arm/crypto/sha256_glue.c b/arch/arm/crypto/sha256_glue.c
+index 433ee4ddce6c8..f85933fdec75f 100644
+--- a/arch/arm/crypto/sha256_glue.c
++++ b/arch/arm/crypto/sha256_glue.c
+@@ -24,8 +24,8 @@
+
+ #include "sha256_glue.h"
+
+-asmlinkage void sha256_block_data_order(u32 *digest, const void *data,
+- unsigned int num_blks);
++asmlinkage void sha256_block_data_order(struct sha256_state *state,
++ const u8 *data, int num_blks);
+
+ int crypto_sha256_arm_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+@@ -33,23 +33,20 @@ int crypto_sha256_arm_update(struct shash_desc *desc, const u8 *data,
+ /* make sure casting to sha256_block_fn() is safe */
+ BUILD_BUG_ON(offsetof(struct sha256_state, state) != 0);
+
+- return sha256_base_do_update(desc, data, len,
+- (sha256_block_fn *)sha256_block_data_order);
++ return sha256_base_do_update(desc, data, len, sha256_block_data_order);
+ }
+ EXPORT_SYMBOL(crypto_sha256_arm_update);
+
+ static int crypto_sha256_arm_final(struct shash_desc *desc, u8 *out)
+ {
+- sha256_base_do_finalize(desc,
+- (sha256_block_fn *)sha256_block_data_order);
++ sha256_base_do_finalize(desc, sha256_block_data_order);
+ return sha256_base_finish(desc, out);
+ }
+
+ int crypto_sha256_arm_finup(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+ {
+- sha256_base_do_update(desc, data, len,
+- (sha256_block_fn *)sha256_block_data_order);
++ sha256_base_do_update(desc, data, len, sha256_block_data_order);
+ return crypto_sha256_arm_final(desc, out);
+ }
+ EXPORT_SYMBOL(crypto_sha256_arm_finup);
+diff --git a/arch/arm/crypto/sha512-glue.c b/arch/arm/crypto/sha512-glue.c
+index 0635a65aa488b..1be5bd498af36 100644
+--- a/arch/arm/crypto/sha512-glue.c
++++ b/arch/arm/crypto/sha512-glue.c
+@@ -25,27 +25,25 @@ MODULE_ALIAS_CRYPTO("sha512");
+ MODULE_ALIAS_CRYPTO("sha384-arm");
+ MODULE_ALIAS_CRYPTO("sha512-arm");
+
+-asmlinkage void sha512_block_data_order(u64 *state, u8 const *src, int blocks);
++asmlinkage void sha512_block_data_order(struct sha512_state *state,
++ u8 const *src, int blocks);
+
+ int sha512_arm_update(struct shash_desc *desc, const u8 *data,
+ unsigned int len)
+ {
+- return sha512_base_do_update(desc, data, len,
+- (sha512_block_fn *)sha512_block_data_order);
++ return sha512_base_do_update(desc, data, len, sha512_block_data_order);
+ }
+
+ static int sha512_arm_final(struct shash_desc *desc, u8 *out)
+ {
+- sha512_base_do_finalize(desc,
+- (sha512_block_fn *)sha512_block_data_order);
++ sha512_base_do_finalize(desc, sha512_block_data_order);
+ return sha512_base_finish(desc, out);
+ }
+
+ int sha512_arm_finup(struct shash_desc *desc, const u8 *data,
+ unsigned int len, u8 *out)
+ {
+- sha512_base_do_update(desc, data, len,
+- (sha512_block_fn *)sha512_block_data_order);
++ sha512_base_do_update(desc, data, len, sha512_block_data_order);
+ return sha512_arm_final(desc, out);
+ }
+
+diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
+index aa7c1d4351396..6b96d75a3a3d8 100644
+--- a/arch/arm64/Kconfig
++++ b/arch/arm64/Kconfig
+@@ -198,7 +198,7 @@ config ARM64
+ if DYNAMIC_FTRACE_WITH_ARGS && DYNAMIC_FTRACE_WITH_CALL_OPS
+ select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS \
+ if (DYNAMIC_FTRACE_WITH_ARGS && !CFI_CLANG && \
+- !CC_OPTIMIZE_FOR_SIZE)
++ (CC_IS_CLANG || !CC_OPTIMIZE_FOR_SIZE))
+ select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY \
+ if DYNAMIC_FTRACE_WITH_ARGS
+ select HAVE_SAMPLE_FTRACE_DIRECT
+diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
+index 9ec49ac2f6fd5..381d58cea092d 100644
+--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts
+@@ -291,6 +291,8 @@ sw {
+ };
+
+ &spdif {
++ pinctrl-names = "default";
++ pinctrl-0 = <&spdif_tx_pin>;
+ status = "okay";
+ };
+
+diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi
+index 4903d6358112d..855b7d43bc503 100644
+--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi
++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-tanix.dtsi
+@@ -166,6 +166,8 @@ &r_ir {
+ };
+
+ &spdif {
++ pinctrl-names = "default";
++ pinctrl-0 = <&spdif_tx_pin>;
+ status = "okay";
+ };
+
+diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+index ca1d287a0a01d..d11e5041bae9a 100644
+--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+@@ -406,6 +406,7 @@ spi1_cs_pin: spi1-cs-pin {
+ function = "spi1";
+ };
+
++ /omit-if-no-ref/
+ spdif_tx_pin: spdif-tx-pin {
+ pins = "PH7";
+ function = "spdif";
+@@ -655,10 +656,8 @@ spdif: spdif@5093000 {
+ clocks = <&ccu CLK_BUS_SPDIF>, <&ccu CLK_SPDIF>;
+ clock-names = "apb", "spdif";
+ resets = <&ccu RST_BUS_SPDIF>;
+- dmas = <&dma 2>;
+- dma-names = "tx";
+- pinctrl-names = "default";
+- pinctrl-0 = <&spdif_tx_pin>;
++ dmas = <&dma 2>, <&dma 2>;
++ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi
+index 2f124b027bbf0..aadfa0ae05252 100644
+--- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi
++++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi
+@@ -227,9 +227,6 @@ ethernet-switch@0 {
+ brcm,num-gphy = <5>;
+ brcm,num-rgmii-ports = <2>;
+
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+ ports: ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl-osm-s.dts b/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl-osm-s.dts
+index 8b16bd68576c0..d9fa0deea7002 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl-osm-s.dts
++++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl-osm-s.dts
+@@ -294,8 +294,8 @@ MX8MM_IOMUXC_SAI3_MCLK_GPIO5_IO2 0x19
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+- MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c3
+- MX8MM_IOMUXC_I2C4_SDA_I2C4_SDA 0x400001c3
++ MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x40000083
++ MX8MM_IOMUXC_I2C4_SDA_I2C4_SDA 0x40000083
+ >;
+ };
+
+@@ -313,19 +313,19 @@ MX8MM_IOMUXC_SAI5_MCLK_GPIO3_IO25 0x19
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+- MX8MM_IOMUXC_SAI2_RXC_UART1_DCE_RX 0x140
+- MX8MM_IOMUXC_SAI2_RXFS_UART1_DCE_TX 0x140
+- MX8MM_IOMUXC_SAI2_RXD0_UART1_DCE_RTS_B 0x140
+- MX8MM_IOMUXC_SAI2_TXFS_UART1_DCE_CTS_B 0x140
++ MX8MM_IOMUXC_SAI2_RXC_UART1_DCE_RX 0x0
++ MX8MM_IOMUXC_SAI2_RXFS_UART1_DCE_TX 0x0
++ MX8MM_IOMUXC_SAI2_RXD0_UART1_DCE_RTS_B 0x0
++ MX8MM_IOMUXC_SAI2_TXFS_UART1_DCE_CTS_B 0x0
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+- MX8MM_IOMUXC_SAI3_TXFS_UART2_DCE_RX 0x140
+- MX8MM_IOMUXC_SAI3_TXC_UART2_DCE_TX 0x140
+- MX8MM_IOMUXC_SAI3_RXD_UART2_DCE_RTS_B 0x140
+- MX8MM_IOMUXC_SAI3_RXC_UART2_DCE_CTS_B 0x140
++ MX8MM_IOMUXC_SAI3_TXFS_UART2_DCE_RX 0x0
++ MX8MM_IOMUXC_SAI3_TXC_UART2_DCE_TX 0x0
++ MX8MM_IOMUXC_SAI3_RXD_UART2_DCE_RTS_B 0x0
++ MX8MM_IOMUXC_SAI3_RXC_UART2_DCE_CTS_B 0x0
+ >;
+ };
+
+@@ -337,40 +337,40 @@ MX8MM_IOMUXC_NAND_CE1_B_GPIO3_IO2 0x19
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+- MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x190
++ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x90
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d0
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d0
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d0
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d0
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d0
+- MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x019
+- MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
++ MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x19
++ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xd0
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+- MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x194
++ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x94
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d4
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d4
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d4
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d4
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d4
+- MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x019
+- MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
++ MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x19
++ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xd0
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+- MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x196
++ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x96
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d6
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d6
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d6
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d6
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d6
+- MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x019
+- MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
++ MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x19
++ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xd0
+ >;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts b/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts
+index dcec57c20399e..aab8e24216501 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts
++++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-bl.dts
+@@ -279,8 +279,8 @@ MX8MM_IOMUXC_SAI3_MCLK_GPIO5_IO2 0x19
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+- MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c3
+- MX8MM_IOMUXC_I2C4_SDA_I2C4_SDA 0x400001c3
++ MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x40000083
++ MX8MM_IOMUXC_I2C4_SDA_I2C4_SDA 0x40000083
+ >;
+ };
+
+@@ -292,19 +292,19 @@ MX8MM_IOMUXC_SPDIF_RX_PWM2_OUT 0x19
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+- MX8MM_IOMUXC_SAI2_RXC_UART1_DCE_RX 0x140
+- MX8MM_IOMUXC_SAI2_RXFS_UART1_DCE_TX 0x140
+- MX8MM_IOMUXC_SAI2_RXD0_UART1_DCE_RTS_B 0x140
+- MX8MM_IOMUXC_SAI2_TXFS_UART1_DCE_CTS_B 0x140
++ MX8MM_IOMUXC_SAI2_RXC_UART1_DCE_RX 0x0
++ MX8MM_IOMUXC_SAI2_RXFS_UART1_DCE_TX 0x0
++ MX8MM_IOMUXC_SAI2_RXD0_UART1_DCE_RTS_B 0x0
++ MX8MM_IOMUXC_SAI2_TXFS_UART1_DCE_CTS_B 0x0
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+- MX8MM_IOMUXC_SAI3_TXFS_UART2_DCE_RX 0x140
+- MX8MM_IOMUXC_SAI3_TXC_UART2_DCE_TX 0x140
+- MX8MM_IOMUXC_SAI3_RXD_UART2_DCE_RTS_B 0x140
+- MX8MM_IOMUXC_SAI3_RXC_UART2_DCE_CTS_B 0x140
++ MX8MM_IOMUXC_SAI3_TXFS_UART2_DCE_RX 0x0
++ MX8MM_IOMUXC_SAI3_TXC_UART2_DCE_TX 0x0
++ MX8MM_IOMUXC_SAI3_RXD_UART2_DCE_RTS_B 0x0
++ MX8MM_IOMUXC_SAI3_RXC_UART2_DCE_CTS_B 0x0
+ >;
+ };
+
+@@ -316,40 +316,40 @@ MX8MM_IOMUXC_NAND_CE1_B_GPIO3_IO2 0x19
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+- MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x190
++ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x90
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d0
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d0
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d0
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d0
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d0
+- MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x019
+- MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
++ MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x19
++ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xd0
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+- MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x194
++ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x94
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d4
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d4
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d4
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d4
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d4
+- MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x019
+- MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
++ MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x19
++ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xd0
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+- MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x196
++ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x96
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d6
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d6
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d6
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d6
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d6
+- MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x019
+- MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
++ MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x19
++ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xd0
+ >;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-osm-s.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-kontron-osm-s.dtsi
+index 6e75ab879bf59..60abcb636cedf 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-osm-s.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-osm-s.dtsi
+@@ -210,7 +210,7 @@ rv3028: rtc@52 {
+ reg = <0x52>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rtc>;
+- interrupts-extended = <&gpio4 1 IRQ_TYPE_LEVEL_HIGH>;
++ interrupts-extended = <&gpio4 1 IRQ_TYPE_LEVEL_LOW>;
+ trickle-diode-disable;
+ };
+ };
+@@ -252,8 +252,8 @@ MX8MM_IOMUXC_ECSPI1_SS0_GPIO5_IO9 0x19
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+- MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL 0x400001c3
+- MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA 0x400001c3
++ MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL 0x40000083
++ MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA 0x40000083
+ >;
+ };
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-sl.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-kontron-sl.dtsi
+index 1f8326613ee9e..2076148e08627 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-sl.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-sl.dtsi
+@@ -237,8 +237,8 @@ MX8MM_IOMUXC_ECSPI1_SS0_GPIO5_IO9 0x19
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+- MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL 0x400001c3
+- MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA 0x400001c3
++ MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL 0x40000083
++ MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA 0x40000083
+ >;
+ };
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
+index 6425773f68e0a..bbbaf2165ea28 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw71xx.dtsi
+@@ -47,17 +47,6 @@ pps {
+ gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+ };
+-
+- reg_usb_otg1_vbus: regulator-usb-otg1 {
+- pinctrl-names = "default";
+- pinctrl-0 = <&pinctrl_reg_usb1_en>;
+- compatible = "regulator-fixed";
+- regulator-name = "usb_otg1_vbus";
+- gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+- enable-active-high;
+- regulator-min-microvolt = <5000000>;
+- regulator-max-microvolt = <5000000>;
+- };
+ };
+
+ /* off-board header */
+@@ -144,9 +133,10 @@ &uart3 {
+ };
+
+ &usbotg1 {
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_usbotg1>;
+ dr_mode = "otg";
+ over-current-active-low;
+- vbus-supply = <®_usb_otg1_vbus>;
+ status = "okay";
+ };
+
+@@ -204,14 +194,6 @@ MX8MM_IOMUXC_GPIO1_IO15_GPIO1_IO15 0x41
+ >;
+ };
+
+- pinctrl_reg_usb1_en: regusb1grp {
+- fsl,pins = <
+- MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x41
+- MX8MM_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x141
+- MX8MM_IOMUXC_GPIO1_IO13_USB1_OTG_OC 0x41
+- >;
+- };
+-
+ pinctrl_spi2: spi2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI2_SCLK_ECSPI2_SCLK 0xd6
+@@ -234,4 +216,11 @@ MX8MM_IOMUXC_UART3_RXD_UART3_DCE_RX 0x140
+ MX8MM_IOMUXC_UART3_TXD_UART3_DCE_TX 0x140
+ >;
+ };
++
++ pinctrl_usbotg1: usbotg1grp {
++ fsl,pins = <
++ MX8MM_IOMUXC_GPIO1_IO12_GPIO1_IO12 0x141
++ MX8MM_IOMUXC_GPIO1_IO13_USB1_OTG_OC 0x41
++ >;
++ };
+ };
+diff --git a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts
+index 5828c9d7821de..b5ce7b14b5434 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts
++++ b/arch/arm64/boot/dts/freescale/imx8mp-data-modul-edm-sbc.dts
+@@ -121,7 +121,7 @@ &ecspi1 {
+ flash@0 { /* W25Q128JVEI */
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+- spi-max-frequency = <100000000>; /* Up to 133 MHz */
++ spi-max-frequency = <40000000>;
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <1>;
+ };
+diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
+index f87fa5a948ccc..9beba8d6a0dfe 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
++++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
+@@ -23,7 +23,7 @@ hdmi-connector {
+
+ port {
+ hdmi_connector_in: endpoint {
+- remote-endpoint = <&adv7533_out>;
++ remote-endpoint = <&adv7535_out>;
+ };
+ };
+ };
+@@ -107,6 +107,13 @@ reg_usdhc2_vmmc: regulator-usdhc2 {
+ enable-active-high;
+ };
+
++ reg_vext_3v3: regulator-vext-3v3 {
++ compatible = "regulator-fixed";
++ regulator-name = "VEXT_3V3";
++ regulator-min-microvolt = <3300000>;
++ regulator-max-microvolt = <3300000>;
++ };
++
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "wm8960-audio";
+@@ -364,7 +371,7 @@ BUCK4 {
+ regulator-always-on;
+ };
+
+- BUCK5 {
++ reg_buck5: BUCK5 {
+ regulator-name = "BUCK5";
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <1950000>;
+@@ -415,14 +422,16 @@ &i2c2 {
+
+ hdmi@3d {
+ compatible = "adi,adv7535";
+- reg = <0x3d>, <0x3c>, <0x3e>, <0x3f>;
+- reg-names = "main", "cec", "edid", "packet";
++ reg = <0x3d>;
++ interrupt-parent = <&gpio1>;
++ interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+ adi,dsi-lanes = <4>;
+- adi,input-depth = <8>;
+- adi,input-colorspace = "rgb";
+- adi,input-clock = "1x";
+- adi,input-style = <1>;
+- adi,input-justification = "evenly";
++ avdd-supply = <®_buck5>;
++ dvdd-supply = <®_buck5>;
++ pvdd-supply = <®_buck5>;
++ a2vdd-supply = <®_buck5>;
++ v3p3-supply = <®_vext_3v3>;
++ v1p2-supply = <®_buck5>;
+
+ ports {
+ #address-cells = <1>;
+@@ -431,7 +440,7 @@ ports {
+ port@0 {
+ reg = <0>;
+
+- adv7533_in: endpoint {
++ adv7535_in: endpoint {
+ remote-endpoint = <&dsi_out>;
+ };
+ };
+@@ -439,7 +448,7 @@ adv7533_in: endpoint {
+ port@1 {
+ reg = <1>;
+
+- adv7533_out: endpoint {
++ adv7535_out: endpoint {
+ remote-endpoint = <&hdmi_connector_in>;
+ };
+ };
+@@ -524,7 +533,7 @@ port@1 {
+ reg = <1>;
+
+ dsi_out: endpoint {
+- remote-endpoint = <&adv7533_in>;
++ remote-endpoint = <&adv7535_in>;
+ data-lanes = <1 2 3 4>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
+index 69cb8676732ea..cafc1383115ab 100644
+--- a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
+@@ -96,15 +96,30 @@ &edma2 {
+ status = "okay";
+ };
+
++/* It is eDMA1 in 8QM RM, but 8QXP it is eDMA3 */
+ &edma3 {
++ reg = <0x5a9f0000 0x210000>;
++ dma-channels = <10>;
++ interrupts = <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 432 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 433 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&pd IMX_SC_R_DMA_1_CH0>,
+- <&pd IMX_SC_R_DMA_1_CH1>,
+- <&pd IMX_SC_R_DMA_1_CH2>,
+- <&pd IMX_SC_R_DMA_1_CH3>,
+- <&pd IMX_SC_R_DMA_1_CH4>,
+- <&pd IMX_SC_R_DMA_1_CH5>,
+- <&pd IMX_SC_R_DMA_1_CH6>,
+- <&pd IMX_SC_R_DMA_1_CH7>;
++ <&pd IMX_SC_R_DMA_1_CH1>,
++ <&pd IMX_SC_R_DMA_1_CH2>,
++ <&pd IMX_SC_R_DMA_1_CH3>,
++ <&pd IMX_SC_R_DMA_1_CH4>,
++ <&pd IMX_SC_R_DMA_1_CH5>,
++ <&pd IMX_SC_R_DMA_1_CH6>,
++ <&pd IMX_SC_R_DMA_1_CH7>,
++ <&pd IMX_SC_R_DMA_1_CH8>,
++ <&pd IMX_SC_R_DMA_1_CH9>;
+ };
+
+ &flexcan1 {
+diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+index e300145ad1a6f..1cc3fa1c354de 100644
+--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
++++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+@@ -431,14 +431,14 @@ xor11 {
+ crypto: crypto@90000 {
+ compatible = "inside-secure,safexcel-eip97ies";
+ reg = <0x90000 0x20000>;
+- interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+- interrupt-names = "mem", "ring0", "ring1",
+- "ring2", "ring3", "eip";
++ <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "ring0", "ring1", "ring2",
++ "ring3", "eip", "mem";
+ clocks = <&nb_periph_clk 15>;
+ };
+
+diff --git a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
+index 4ec1aae0a3a9c..7e595ac80043a 100644
+--- a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
++++ b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi
+@@ -511,14 +511,14 @@ CP11X_LABEL(sdhci0): mmc@780000 {
+ CP11X_LABEL(crypto): crypto@800000 {
+ compatible = "inside-secure,safexcel-eip197b";
+ reg = <0x800000 0x200000>;
+- interrupts = <87 IRQ_TYPE_LEVEL_HIGH>,
+- <88 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts = <88 IRQ_TYPE_LEVEL_HIGH>,
+ <89 IRQ_TYPE_LEVEL_HIGH>,
+ <90 IRQ_TYPE_LEVEL_HIGH>,
+ <91 IRQ_TYPE_LEVEL_HIGH>,
+- <92 IRQ_TYPE_LEVEL_HIGH>;
+- interrupt-names = "mem", "ring0", "ring1",
+- "ring2", "ring3", "eip";
++ <92 IRQ_TYPE_LEVEL_HIGH>,
++ <87 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "ring0", "ring1", "ring2", "ring3",
++ "eip", "mem";
+ clock-names = "core", "reg";
+ clocks = <&CP11X_LABEL(clk) 1 26>,
+ <&CP11X_LABEL(clk) 1 17>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
+index a1f42048dcc70..850b3e2773680 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
+@@ -75,6 +75,7 @@ led-1 {
+
+ memory@40000000 {
+ reg = <0 0x40000000 0 0x40000000>;
++ device_type = "memory";
+ };
+
+ reg_1p8v: regulator-1p8v {
+diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+index 2dc1bdc74e212..5c26021fc4cf1 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+@@ -57,6 +57,7 @@ key-wps {
+
+ memory@40000000 {
+ reg = <0 0x40000000 0 0x20000000>;
++ device_type = "memory";
+ };
+
+ reg_1p8v: regulator-1p8v {
+diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
+index d06d4af43cbff..e04b1c0c0ebbf 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
+@@ -43,7 +43,7 @@ fan: pwm-fan {
+ #cooling-cells = <2>;
+ /* cooling level (0, 1, 2) - pwm inverted */
+ cooling-levels = <255 96 0>;
+- pwms = <&pwm 0 10000 0>;
++ pwms = <&pwm 0 10000>;
+ status = "okay";
+ };
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts
+index 3ef371ca254e8..2f884c24f1eb4 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts
+@@ -237,12 +237,13 @@ &spi0 {
+ pinctrl-0 = <&spi_flash_pins>;
+ cs-gpios = <0>, <0>;
+ status = "okay";
+- spi_nand: spi_nand@0 {
++
++ spi_nand: flash@0 {
+ compatible = "spi-nand";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+- spi-tx-buswidth = <4>;
+- spi-rx-buswidth = <4>;
++ spi-tx-bus-width = <4>;
++ spi-rx-bus-width = <4>;
+ };
+ };
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+index fc751e049953c..d974739eae1c9 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+@@ -153,6 +153,7 @@ infracfg: infracfg@10001000 {
+ compatible = "mediatek,mt7986-infracfg", "syscon";
+ reg = <0 0x10001000 0 0x1000>;
+ #clock-cells = <1>;
++ #reset-cells = <1>;
+ };
+
+ wed_pcie: wed-pcie@10003000 {
+@@ -234,7 +235,6 @@ crypto: crypto@10320000 {
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ring0", "ring1", "ring2", "ring3";
+ clocks = <&infracfg CLK_INFRA_EIP97_CK>;
+- clock-names = "infra_eip97_ck";
+ assigned-clocks = <&topckgen CLK_TOP_EIP_B_SEL>;
+ assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>;
+ status = "disabled";
+@@ -243,7 +243,6 @@ crypto: crypto@10320000 {
+ pwm: pwm@10048000 {
+ compatible = "mediatek,mt7986-pwm";
+ reg = <0 0x10048000 0 0x1000>;
+- #clock-cells = <1>;
+ #pwm-cells = <2>;
+ interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&topckgen CLK_TOP_PWM_SEL>,
+diff --git a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts
+index dde190442e386..57dcaeef31d7f 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts
+@@ -152,12 +152,13 @@ &spi0 {
+ pinctrl-0 = <&spi_flash_pins>;
+ cs-gpios = <0>, <0>;
+ status = "okay";
+- spi_nand: spi_nand@0 {
++
++ spi_nand: flash@0 {
+ compatible = "spi-nand";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+- spi-tx-buswidth = <4>;
+- spi-rx-buswidth = <4>;
++ spi-tx-bus-width = <4>;
++ spi-rx-bus-width = <4>;
+ };
+ };
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi
+index b6a9830af2696..bfb9e42c8acaa 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kakadu.dtsi
+@@ -360,6 +360,10 @@ pen_eject {
+ };
+
+ &cros_ec {
++ cbas {
++ compatible = "google,cros-cbas";
++ };
++
+ keyboard-controller {
+ compatible = "google,cros-ec-keyb-switches";
+ };
+diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi
+index 306c95166f3fe..5c1bf6a1e4758 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-kodama.dtsi
+@@ -339,6 +339,10 @@ touch_pin_reset: pin_reset {
+ };
+
+ &cros_ec {
++ cbas {
++ compatible = "google,cros-cbas";
++ };
++
+ keyboard-controller {
+ compatible = "google,cros-ec-keyb-switches";
+ };
+diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi
+index 382e4c6d7191c..0f5fa893a7742 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-krane.dtsi
+@@ -343,6 +343,10 @@ rst_pin {
+ };
+
+ &cros_ec {
++ cbas {
++ compatible = "google,cros-cbas";
++ };
++
+ keyboard-controller {
+ compatible = "google,cros-ec-keyb-switches";
+ };
+diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
+index 1b3396b1cee39..90c5ad917a9ba 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
+@@ -937,10 +937,6 @@ usbc_extcon: extcon0 {
+ google,usb-port-id = <0>;
+ };
+
+- cbas {
+- compatible = "google,cros-cbas";
+- };
+-
+ typec {
+ compatible = "google,cros-ec-typec";
+ #address-cells = <1>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt8186.dtsi b/arch/arm64/boot/dts/mediatek/mt8186.dtsi
+index 2fec6fd1c1a71..84ec6c1aa12b9 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8186.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8186.dtsi
+@@ -931,11 +931,17 @@ power-domain@MT8186_POWER_DOMAIN_CSIRX_TOP {
+
+ power-domain@MT8186_POWER_DOMAIN_SSUSB {
+ reg = <MT8186_POWER_DOMAIN_SSUSB>;
++ clocks = <&topckgen CLK_TOP_USB_TOP>,
++ <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_REF>;
++ clock-names = "sys_ck", "ref_ck";
+ #power-domain-cells = <0>;
+ };
+
+ power-domain@MT8186_POWER_DOMAIN_SSUSB_P1 {
+ reg = <MT8186_POWER_DOMAIN_SSUSB_P1>;
++ clocks = <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_SYS>,
++ <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_REF>;
++ clock-names = "sys_ck", "ref_ck";
+ #power-domain-cells = <0>;
+ };
+
+@@ -1061,7 +1067,7 @@ power-domain@MT8186_POWER_DOMAIN_VENC {
+ reg = <MT8186_POWER_DOMAIN_VENC>;
+ clocks = <&topckgen CLK_TOP_VENC>,
+ <&vencsys CLK_VENC_CKE1_VENC>;
+- clock-names = "venc0", "larb";
++ clock-names = "venc0", "subsys-larb";
+ mediatek,infracfg = <&infracfg_ao>;
+ #power-domain-cells = <0>;
+ };
+@@ -1530,8 +1536,9 @@ ssusb0: usb@11201000 {
+ clocks = <&topckgen CLK_TOP_USB_TOP>,
+ <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_REF>,
+ <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_HCLK>,
+- <&infracfg_ao CLK_INFRA_AO_ICUSB>;
+- clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck";
++ <&infracfg_ao CLK_INFRA_AO_ICUSB>,
++ <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_XHCI>;
++ clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck", "xhci_ck";
+ interrupts = <GIC_SPI 303 IRQ_TYPE_LEVEL_HIGH 0>;
+ phys = <&u2port0 PHY_TYPE_USB2>;
+ power-domains = <&spm MT8186_POWER_DOMAIN_SSUSB>;
+@@ -1595,8 +1602,9 @@ ssusb1: usb@11281000 {
+ clocks = <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_SYS>,
+ <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_REF>,
+ <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_HCLK>,
+- <&clk26m>;
+- clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck";
++ <&clk26m>,
++ <&infracfg_ao CLK_INFRA_AO_SSUSB_TOP_P1_XHCI>;
++ clock-names = "sys_ck", "ref_ck", "mcu_ck", "dma_ck", "xhci_ck";
+ interrupts = <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH 0>;
+ phys = <&u2port1 PHY_TYPE_USB2>, <&u3port1 PHY_TYPE_USB3>;
+ power-domains = <&spm MT8186_POWER_DOMAIN_SSUSB_P1>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
+index d87aab8d7a79e..d4dd5e8b2e1d3 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
+@@ -1336,10 +1336,6 @@ cros_ec: ec@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+- base_detection: cbas {
+- compatible = "google,cros-cbas";
+- };
+-
+ cros_ec_pwm: pwm {
+ compatible = "google,cros-ec-pwm";
+ #pwm-cells = <1>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt8192.dtsi b/arch/arm64/boot/dts/mediatek/mt8192.dtsi
+index 6dd32dbfb832e..0e432636b8c23 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8192.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8192.dtsi
+@@ -1814,7 +1814,7 @@ vcodec_enc: vcodec@17020000 {
+ mediatek,scp = <&scp>;
+ power-domains = <&spm MT8192_POWER_DOMAIN_VENC>;
+ clocks = <&vencsys CLK_VENC_SET1_VENC>;
+- clock-names = "venc-set1";
++ clock-names = "venc_sel";
+ assigned-clocks = <&topckgen CLK_TOP_VENC_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D4>;
+ };
+diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r1.dts b/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r1.dts
+index 2d5e8f371b6de..a82d716f10d44 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r1.dts
++++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r1.dts
+@@ -23,3 +23,7 @@ &sound {
+ &ts_10 {
+ status = "okay";
+ };
++
++&watchdog {
++ /delete-property/ mediatek,disable-extrst;
++};
+diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r2.dts b/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r2.dts
+index 2586c32ce6e6f..2fe20e0dad836 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r2.dts
++++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r2.dts
+@@ -43,3 +43,7 @@ &sound {
+ &ts_10 {
+ status = "okay";
+ };
++
++&watchdog {
++ /delete-property/ mediatek,disable-extrst;
++};
+diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r3.dts b/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r3.dts
+index f54f9477b99da..dd294ca98194c 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r3.dts
++++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry-tomato-r3.dts
+@@ -44,3 +44,7 @@ &sound {
+ &ts_10 {
+ status = "okay";
+ };
++
++&watchdog {
++ /delete-property/ mediatek,disable-extrst;
++};
+diff --git a/arch/arm64/boot/dts/qcom/pm2250.dtsi b/arch/arm64/boot/dts/qcom/pm2250.dtsi
+deleted file mode 100644
+index 5f1d15db5c993..0000000000000
+--- a/arch/arm64/boot/dts/qcom/pm2250.dtsi
++++ /dev/null
+@@ -1,63 +0,0 @@
+-// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+-/*
+- * Copyright (c) 2023, Linaro Ltd
+- */
+-
+-#include <dt-bindings/iio/qcom,spmi-vadc.h>
+-#include <dt-bindings/input/input.h>
+-#include <dt-bindings/interrupt-controller/irq.h>
+-#include <dt-bindings/spmi/spmi.h>
+-
+-&spmi_bus {
+- pmic@0 {
+- compatible = "qcom,pm2250", "qcom,spmi-pmic";
+- reg = <0x0 SPMI_USID>;
+- #address-cells = <1>;
+- #size-cells = <0>;
+-
+- pon@800 {
+- compatible = "qcom,pm8916-pon";
+- reg = <0x800>;
+-
+- pm2250_pwrkey: pwrkey {
+- compatible = "qcom,pm8941-pwrkey";
+- interrupts-extended = <&spmi_bus 0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
+- linux,code = <KEY_POWER>;
+- debounce = <15625>;
+- bias-pull-up;
+- };
+-
+- pm2250_resin: resin {
+- compatible = "qcom,pm8941-resin";
+- interrupts-extended = <&spmi_bus 0x0 0x8 1 IRQ_TYPE_EDGE_BOTH>;
+- debounce = <15625>;
+- bias-pull-up;
+- status = "disabled";
+- };
+- };
+-
+- rtc@6000 {
+- compatible = "qcom,pm8941-rtc";
+- reg = <0x6000>, <0x6100>;
+- reg-names = "rtc", "alarm";
+- interrupts-extended = <&spmi_bus 0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>;
+- };
+-
+- pm2250_gpios: gpio@c000 {
+- compatible = "qcom,pm2250-gpio", "qcom,spmi-gpio";
+- reg = <0xc000>;
+- gpio-controller;
+- gpio-ranges = <&pm2250_gpios 0 0 10>;
+- #gpio-cells = <2>;
+- interrupt-controller;
+- #interrupt-cells = <2>;
+- };
+- };
+-
+- pmic@1 {
+- compatible = "qcom,pm2250", "qcom,spmi-pmic";
+- reg = <0x1 SPMI_USID>;
+- #address-cells = <1>;
+- #size-cells = <0>;
+- };
+-};
+diff --git a/arch/arm64/boot/dts/qcom/pm4125.dtsi b/arch/arm64/boot/dts/qcom/pm4125.dtsi
+new file mode 100644
+index 0000000000000..d886a9e4b0918
+--- /dev/null
++++ b/arch/arm64/boot/dts/qcom/pm4125.dtsi
+@@ -0,0 +1,63 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
++/*
++ * Copyright (c) 2023, Linaro Ltd
++ */
++
++#include <dt-bindings/iio/qcom,spmi-vadc.h>
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/interrupt-controller/irq.h>
++#include <dt-bindings/spmi/spmi.h>
++
++&spmi_bus {
++ pmic@0 {
++ compatible = "qcom,pm2250", "qcom,spmi-pmic";
++ reg = <0x0 SPMI_USID>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ pon@800 {
++ compatible = "qcom,pm8916-pon";
++ reg = <0x800>;
++
++ pm4125_pwrkey: pwrkey {
++ compatible = "qcom,pm8941-pwrkey";
++ interrupts-extended = <&spmi_bus 0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
++ linux,code = <KEY_POWER>;
++ debounce = <15625>;
++ bias-pull-up;
++ };
++
++ pm4125_resin: resin {
++ compatible = "qcom,pm8941-resin";
++ interrupts-extended = <&spmi_bus 0x0 0x8 1 IRQ_TYPE_EDGE_BOTH>;
++ debounce = <15625>;
++ bias-pull-up;
++ status = "disabled";
++ };
++ };
++
++ rtc@6000 {
++ compatible = "qcom,pm8941-rtc";
++ reg = <0x6000>, <0x6100>;
++ reg-names = "rtc", "alarm";
++ interrupts-extended = <&spmi_bus 0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>;
++ };
++
++ pm4125_gpios: gpio@c000 {
++ compatible = "qcom,pm2250-gpio", "qcom,spmi-gpio";
++ reg = <0xc000>;
++ gpio-controller;
++ gpio-ranges = <&pm4125_gpios 0 0 10>;
++ #gpio-cells = <2>;
++ interrupt-controller;
++ #interrupt-cells = <2>;
++ };
++ };
++
++ pmic@1 {
++ compatible = "qcom,pm2250", "qcom,spmi-pmic";
++ reg = <0x1 SPMI_USID>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ };
++};
+diff --git a/arch/arm64/boot/dts/qcom/qcm2290.dtsi b/arch/arm64/boot/dts/qcom/qcm2290.dtsi
+index 0911fb08ed632..89beac833d435 100644
+--- a/arch/arm64/boot/dts/qcom/qcm2290.dtsi
++++ b/arch/arm64/boot/dts/qcom/qcm2290.dtsi
+@@ -442,6 +442,11 @@ tcsr_mutex: hwlock@340000 {
+ #hwlock-cells = <1>;
+ };
+
++ tcsr_regs: syscon@3c0000 {
++ compatible = "qcom,qcm2290-tcsr", "syscon";
++ reg = <0x0 0x003c0000 0x0 0x40000>;
++ };
++
+ tlmm: pinctrl@500000 {
+ compatible = "qcom,qcm2290-tlmm";
+ reg = <0x0 0x00500000 0x0 0x300000>;
+@@ -690,6 +695,8 @@ usb_qmpphy: phy@1615000 {
+
+ #phy-cells = <0>;
+
++ qcom,tcsr-reg = <&tcsr_regs 0xb244>;
++
+ status = "disabled";
+ };
+
+diff --git a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
+index 176898c9dbbd7..1e85c43a6fd14 100644
+--- a/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
++++ b/arch/arm64/boot/dts/qcom/qcm6490-fairphone-fp5.dts
+@@ -82,6 +82,11 @@ cdsp_mem: cdsp@88f00000 {
+ no-map;
+ };
+
++ removed_mem: removed@c0000000 {
++ reg = <0x0 0xc0000000 0x0 0x5100000>;
++ no-map;
++ };
++
+ rmtfs_mem: memory@f8500000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0x0 0xf8500000 0x0 0x600000>;
+diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
+index 03e97e27d16d4..74f5a43d53db9 100644
+--- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
++++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
+@@ -123,8 +123,8 @@ debug_vm_mem: debug-vm@d0600000 {
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+- regulator-min-microvolt = <2500000>;
+- regulator-max-microvolt = <4350000>;
++ regulator-min-microvolt = <3700000>;
++ regulator-max-microvolt = <3700000>;
+ };
+ };
+
+diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
+index 8bb7d13d85f66..ae1632182d7c1 100644
+--- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
++++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
+@@ -124,8 +124,8 @@ debug_vm_mem: debug-vm@d0600000 {
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+- regulator-min-microvolt = <2500000>;
+- regulator-max-microvolt = <4350000>;
++ regulator-min-microvolt = <3700000>;
++ regulator-max-microvolt = <3700000>;
+ };
+ };
+
+diff --git a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
+index aa53b6af6d9cb..64b2ab2862793 100644
+--- a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
++++ b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
+@@ -7,7 +7,7 @@
+
+ #include <dt-bindings/leds/common.h>
+ #include "qcm2290.dtsi"
+-#include "pm2250.dtsi"
++#include "pm4125.dtsi"
+
+ / {
+ model = "Qualcomm Technologies, Inc. Robotics RB1";
+@@ -226,7 +226,7 @@ &mdss {
+ };
+
+ &mdss_dsi0 {
+- vdda-supply = <&pm2250_l5>;
++ vdda-supply = <&pm4125_l5>;
+ status = "okay";
+ };
+
+@@ -239,7 +239,7 @@ &mdss_dsi0_phy {
+ status = "okay";
+ };
+
+-&pm2250_resin {
++&pm4125_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+ };
+@@ -263,23 +263,23 @@ regulators {
+ compatible = "qcom,rpm-pm2250-regulators";
+ vdd_s3-supply = <&vph_pwr>;
+ vdd_s4-supply = <&vph_pwr>;
+- vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12-supply = <&pm2250_s3>;
++ vdd_l1_l2_l3_l5_l6_l7_l8_l9_l10_l11_l12-supply = <&pm4125_s3>;
+ vdd_l4_l17_l18_l19_l20_l21_l22-supply = <&vph_pwr>;
+- vdd_l13_l14_l15_l16-supply = <&pm2250_s4>;
++ vdd_l13_l14_l15_l16-supply = <&pm4125_s4>;
+
+ /*
+ * S1 - VDD_APC
+ * S2 - VDD_CX
+ */
+
+- pm2250_s3: s3 {
++ pm4125_s3: s3 {
+ /* 0.4V-1.6625V -> 1.3V (Power tree requirements) */
+ regulator-min-microvolt = <1352000>;
+ regulator-max-microvolt = <1352000>;
+ regulator-boot-on;
+ };
+
+- pm2250_s4: s4 {
++ pm4125_s4: s4 {
+ /* 1.2V-2.35V -> 2.05V (Power tree requirements) */
+ regulator-min-microvolt = <2072000>;
+ regulator-max-microvolt = <2072000>;
+@@ -288,7 +288,7 @@ pm2250_s4: s4 {
+
+ /* L1 - VDD_MX */
+
+- pm2250_l2: l2 {
++ pm4125_l2: l2 {
+ /* LPDDR4X VDD2 */
+ regulator-min-microvolt = <1136000>;
+ regulator-max-microvolt = <1136000>;
+@@ -296,7 +296,7 @@ pm2250_l2: l2 {
+ regulator-boot-on;
+ };
+
+- pm2250_l3: l3 {
++ pm4125_l3: l3 {
+ /* LPDDR4X VDDQ */
+ regulator-min-microvolt = <616000>;
+ regulator-max-microvolt = <616000>;
+@@ -304,14 +304,14 @@ pm2250_l3: l3 {
+ regulator-boot-on;
+ };
+
+- pm2250_l4: l4 {
++ pm4125_l4: l4 {
+ /* max = 3.05V -> max = 2.7 to disable 3V signaling (SDHCI2) */
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2700000>;
+ regulator-allow-set-load;
+ };
+
+- pm2250_l5: l5 {
++ pm4125_l5: l5 {
+ /* CSI/DSI */
+ regulator-min-microvolt = <1232000>;
+ regulator-max-microvolt = <1232000>;
+@@ -319,7 +319,7 @@ pm2250_l5: l5 {
+ regulator-boot-on;
+ };
+
+- pm2250_l6: l6 {
++ pm4125_l6: l6 {
+ /* DRAM PLL */
+ regulator-min-microvolt = <928000>;
+ regulator-max-microvolt = <928000>;
+@@ -327,7 +327,7 @@ pm2250_l6: l6 {
+ regulator-boot-on;
+ };
+
+- pm2250_l7: l7 {
++ pm4125_l7: l7 {
+ /* Wi-Fi CX/MX */
+ regulator-min-microvolt = <664000>;
+ regulator-max-microvolt = <664000>;
+@@ -338,20 +338,20 @@ pm2250_l7: l7 {
+ * L9 - VDD_LPI_MX
+ */
+
+- pm2250_l10: l10 {
++ pm4125_l10: l10 {
+ /* Wi-Fi RFA */
+ regulator-min-microvolt = <1304000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+- pm2250_l11: l11 {
++ pm4125_l11: l11 {
+ /* GPS RF1 */
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-boot-on;
+ };
+
+- pm2250_l12: l12 {
++ pm4125_l12: l12 {
+ /* USB PHYs */
+ regulator-min-microvolt = <928000>;
+ regulator-max-microvolt = <928000>;
+@@ -359,7 +359,7 @@ pm2250_l12: l12 {
+ regulator-boot-on;
+ };
+
+- pm2250_l13: l13 {
++ pm4125_l13: l13 {
+ /* USB/QFPROM/PLLs */
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+@@ -367,7 +367,7 @@ pm2250_l13: l13 {
+ regulator-boot-on;
+ };
+
+- pm2250_l14: l14 {
++ pm4125_l14: l14 {
+ /* SDHCI1 VQMMC */
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+@@ -376,7 +376,7 @@ pm2250_l14: l14 {
+ regulator-always-on;
+ };
+
+- pm2250_l15: l15 {
++ pm4125_l15: l15 {
+ /* WCD/DSI/BT VDDIO */
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+@@ -385,38 +385,38 @@ pm2250_l15: l15 {
+ regulator-boot-on;
+ };
+
+- pm2250_l16: l16 {
++ pm4125_l16: l16 {
+ /* GPS RF2 */
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ };
+
+- pm2250_l17: l17 {
++ pm4125_l17: l17 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+- pm2250_l18: l18 {
++ pm4125_l18: l18 {
+ /* VDD_PXn */
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+- pm2250_l19: l19 {
++ pm4125_l19: l19 {
+ /* VDD_PXn */
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+- pm2250_l20: l20 {
++ pm4125_l20: l20 {
+ /* SDHCI1 VMMC */
+ regulator-min-microvolt = <2400000>;
+ regulator-max-microvolt = <3600000>;
+ regulator-allow-set-load;
+ };
+
+- pm2250_l21: l21 {
++ pm4125_l21: l21 {
+ /* SDHCI2 VMMC */
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <3300000>;
+@@ -424,7 +424,7 @@ pm2250_l21: l21 {
+ regulator-boot-on;
+ };
+
+- pm2250_l22: l22 {
++ pm4125_l22: l22 {
+ /* Wi-Fi */
+ regulator-min-microvolt = <3312000>;
+ regulator-max-microvolt = <3312000>;
+@@ -433,8 +433,8 @@ pm2250_l22: l22 {
+ };
+
+ &sdhc_1 {
+- vmmc-supply = <&pm2250_l20>;
+- vqmmc-supply = <&pm2250_l14>;
++ vmmc-supply = <&pm4125_l20>;
++ vqmmc-supply = <&pm4125_l14>;
+ pinctrl-0 = <&sdc1_state_on>;
+ pinctrl-1 = <&sdc1_state_off>;
+ pinctrl-names = "default", "sleep";
+@@ -446,8 +446,8 @@ &sdhc_1 {
+ };
+
+ &sdhc_2 {
+- vmmc-supply = <&pm2250_l21>;
+- vqmmc-supply = <&pm2250_l4>;
++ vmmc-supply = <&pm4125_l21>;
++ vqmmc-supply = <&pm4125_l4>;
+ cd-gpios = <&tlmm 88 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&sdc2_state_on &sd_det_in_on>;
+ pinctrl-1 = <&sdc2_state_off &sd_det_in_off>;
+@@ -518,8 +518,8 @@ &usb {
+ };
+
+ &usb_qmpphy {
+- vdda-phy-supply = <&pm2250_l12>;
+- vdda-pll-supply = <&pm2250_l13>;
++ vdda-phy-supply = <&pm4125_l12>;
++ vdda-pll-supply = <&pm4125_l13>;
+ status = "okay";
+ };
+
+@@ -528,17 +528,17 @@ &usb_dwc3 {
+ };
+
+ &usb_hsphy {
+- vdd-supply = <&pm2250_l12>;
+- vdda-pll-supply = <&pm2250_l13>;
+- vdda-phy-dpdm-supply = <&pm2250_l21>;
++ vdd-supply = <&pm4125_l12>;
++ vdda-pll-supply = <&pm4125_l13>;
++ vdda-phy-dpdm-supply = <&pm4125_l21>;
+ status = "okay";
+ };
+
+ &wifi {
+- vdd-0.8-cx-mx-supply = <&pm2250_l7>;
+- vdd-1.8-xo-supply = <&pm2250_l13>;
+- vdd-1.3-rfa-supply = <&pm2250_l10>;
+- vdd-3.3-ch0-supply = <&pm2250_l22>;
++ vdd-0.8-cx-mx-supply = <&pm4125_l7>;
++ vdd-1.8-xo-supply = <&pm4125_l13>;
++ vdd-1.3-rfa-supply = <&pm4125_l10>;
++ vdd-3.3-ch0-supply = <&pm4125_l22>;
+ qcom,ath10k-calibration-variant = "Thundercomm_RB1";
+ status = "okay";
+ };
+diff --git a/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts b/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts
+index 7c19f874fa716..52f31f3166c2f 100644
+--- a/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts
++++ b/arch/arm64/boot/dts/qcom/qrb4210-rb2.dts
+@@ -607,10 +607,6 @@ &usb {
+ status = "okay";
+ };
+
+-&usb_dwc3 {
+- maximum-speed = "super-speed";
+-};
+-
+ &usb_hsphy {
+ vdd-supply = <&vreg_l4a_0p9>;
+ vdda-pll-supply = <&vreg_l12a_1p8>;
+diff --git a/arch/arm64/boot/dts/qcom/sa8540p.dtsi b/arch/arm64/boot/dts/qcom/sa8540p.dtsi
+index 96b2c59ad02b4..23888029cc117 100644
+--- a/arch/arm64/boot/dts/qcom/sa8540p.dtsi
++++ b/arch/arm64/boot/dts/qcom/sa8540p.dtsi
+@@ -168,6 +168,9 @@ opp-2592000000 {
+ };
+
+ &gpucc {
++ /* SA8295P and SA8540P doesn't provide gfx.lvl */
++ /delete-property/ power-domains;
++
+ status = "disabled";
+ };
+
+diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
+index 83b5b76ba1794..ce0d24ee7eedb 100644
+--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
++++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
+@@ -2345,6 +2345,8 @@ cryptobam: dma-controller@1dc4000 {
+ <&apps_smmu 0x4e6 0x0011>;
+ qcom,ee = <0>;
+ qcom,controlled-remotely;
++ num-channels = <16>;
++ qcom,num-ees = <4>;
+ };
+
+ crypto: crypto@1dfa000 {
+diff --git a/arch/arm64/boot/dts/qcom/sc8180x.dtsi b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
+index 0430d99091e30..c0dd44f146748 100644
+--- a/arch/arm64/boot/dts/qcom/sc8180x.dtsi
++++ b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
+@@ -290,7 +290,7 @@ LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ compatible = "arm,idle-state";
+ arm,psci-suspend-param = <0x40000004>;
+- entry-latency-us = <241>;
++ entry-latency-us = <2411>;
+ exit-latency-us = <1461>;
+ min-residency-us = <4488>;
+ local-timer-stop;
+@@ -298,7 +298,15 @@ BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ };
+
+ domain-idle-states {
+- CLUSTER_SLEEP_0: cluster-sleep-0 {
++ CLUSTER_SLEEP_APSS_OFF: cluster-sleep-0 {
++ compatible = "domain-idle-state";
++ arm,psci-suspend-param = <0x41000044>;
++ entry-latency-us = <3300>;
++ exit-latency-us = <3300>;
++ min-residency-us = <6000>;
++ };
++
++ CLUSTER_SLEEP_AOSS_SLEEP: cluster-sleep-1 {
+ compatible = "domain-idle-state";
+ arm,psci-suspend-param = <0x4100a344>;
+ entry-latency-us = <3263>;
+@@ -582,7 +590,7 @@ CPU_PD7: power-domain-cpu7 {
+
+ CLUSTER_PD: power-domain-cpu-cluster0 {
+ #power-domain-cells = <0>;
+- domain-idle-states = <&CLUSTER_SLEEP_0>;
++ domain-idle-states = <&CLUSTER_SLEEP_APSS_OFF &CLUSTER_SLEEP_AOSS_SLEEP>;
+ };
+ };
+
+@@ -782,6 +790,7 @@ gcc: clock-controller@100000 {
+ clock-names = "bi_tcxo",
+ "bi_tcxo_ao",
+ "sleep_clk";
++ power-domains = <&rpmhpd SC8180X_CX>;
+ };
+
+ qupv3_id_0: geniqup@8c0000 {
+@@ -2692,9 +2701,15 @@ mdss: mdss@ae00000 {
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+- interconnects = <&mmss_noc MASTER_MDP_PORT0 0 &mc_virt SLAVE_EBI_CH0 0>,
+- <&mmss_noc MASTER_MDP_PORT1 0 &mc_virt SLAVE_EBI_CH0 0>;
+- interconnect-names = "mdp0-mem", "mdp1-mem";
++ interconnects = <&mmss_noc MASTER_MDP_PORT0 QCOM_ICC_TAG_ALWAYS
++ &mc_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ALWAYS>,
++ <&mmss_noc MASTER_MDP_PORT1 QCOM_ICC_TAG_ALWAYS
++ &mc_virt SLAVE_EBI_CH0 QCOM_ICC_TAG_ALWAYS>,
++ <&gem_noc MASTER_AMPSS_M0 QCOM_ICC_TAG_ALWAYS
++ &config_noc SLAVE_DISPLAY_CFG QCOM_ICC_TAG_ALWAYS>;
++ interconnect-names = "mdp0-mem",
++ "mdp1-mem",
++ "cpu-cfg";
+
+ iommus = <&apps_smmu 0x800 0x420>;
+
+@@ -2723,10 +2738,8 @@ mdss_mdp: mdp@ae01000 {
+ "rot",
+ "lut";
+
+- assigned-clocks = <&dispcc DISP_CC_MDSS_MDP_CLK>,
+- <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+- assigned-clock-rates = <460000000>,
+- <19200000>;
++ assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
++ assigned-clock-rates = <19200000>;
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmhpd SC8180X_MMCX>;
+@@ -3184,7 +3197,7 @@ edp_phy: phy@aec2a00 {
+ <&dispcc DISP_CC_MDSS_AHB_CLK>;
+ clock-names = "aux", "cfg_ahb";
+
+- power-domains = <&dispcc MDSS_GDSC>;
++ power-domains = <&rpmhpd SC8180X_MX>;
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+@@ -3210,6 +3223,7 @@ dispcc: clock-controller@af00000 {
+ "edp_phy_pll_link_clk",
+ "edp_phy_pll_vco_div_clk";
+ power-domains = <&rpmhpd SC8180X_MMCX>;
++ required-opps = <&rpmhpd_opp_low_svs>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+@@ -3248,7 +3262,7 @@ tsens1: thermal-sensor@c265000 {
+
+ aoss_qmp: power-controller@c300000 {
+ compatible = "qcom,sc8180x-aoss-qmp", "qcom,aoss-qmp";
+- reg = <0x0 0x0c300000 0x0 0x100000>;
++ reg = <0x0 0x0c300000 0x0 0x400>;
+ interrupts = <GIC_SPI 389 IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&apss_shared 0>;
+
+diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
+index ab6220456513c..1f517328199b9 100644
+--- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
++++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
+@@ -580,7 +580,7 @@ &mss_pil {
+ &pcie0 {
+ status = "okay";
+ perst-gpios = <&tlmm 35 GPIO_ACTIVE_LOW>;
+- enable-gpio = <&tlmm 134 GPIO_ACTIVE_HIGH>;
++ wake-gpios = <&tlmm 134 GPIO_ACTIVE_HIGH>;
+
+ vddpe-3v3-supply = <&pcie0_3p3v_dual>;
+
+diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
+index e821103d49c0a..46e25c53829ad 100644
+--- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
++++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
+@@ -508,13 +508,13 @@ led-1 {
+ };
+
+ &q6afedai {
+- qi2s@22 {
+- reg = <22>;
++ dai@22 {
++ reg = <QUATERNARY_MI2S_RX>;
+ qcom,sd-lines = <1>;
+ };
+
+- qi2s@23 {
+- reg = <23>;
++ dai@23 {
++ reg = <QUATERNARY_MI2S_TX>;
+ qcom,sd-lines = <0>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
+index c2244824355a2..237d404861424 100644
+--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
++++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
+@@ -3366,8 +3366,8 @@ slpi_pas: remoteproc@5c00000 {
+
+ qcom,qmp = <&aoss_qmp>;
+
+- power-domains = <&rpmhpd SDM845_CX>,
+- <&rpmhpd SDM845_MX>;
++ power-domains = <&rpmhpd SDM845_LCX>,
++ <&rpmhpd SDM845_LMX>;
+ power-domain-names = "lcx", "lmx";
+
+ memory-region = <&slpi_mem>;
+diff --git a/arch/arm64/boot/dts/qcom/sm6115.dtsi b/arch/arm64/boot/dts/qcom/sm6115.dtsi
+index f9849b8befbf2..d33763d092659 100644
+--- a/arch/arm64/boot/dts/qcom/sm6115.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm6115.dtsi
+@@ -614,6 +614,11 @@ tcsr_mutex: hwlock@340000 {
+ #hwlock-cells = <1>;
+ };
+
++ tcsr_regs: syscon@3c0000 {
++ compatible = "qcom,sm6115-tcsr", "syscon";
++ reg = <0x0 0x003c0000 0x0 0x40000>;
++ };
++
+ tlmm: pinctrl@500000 {
+ compatible = "qcom,sm6115-tlmm";
+ reg = <0x0 0x00500000 0x0 0x400000>,
+@@ -879,6 +884,8 @@ usb_qmpphy: phy@1615000 {
+
+ #phy-cells = <0>;
+
++ qcom,tcsr-reg = <&tcsr_regs 0xb244>;
++
+ status = "disabled";
+ };
+
+@@ -1603,7 +1610,6 @@ &bimc SLAVE_EBI_CH0 RPM_ALWAYS_TAG>,
+ interconnect-names = "usb-ddr",
+ "apps-usb";
+
+- qcom,select-utmi-as-pipe-clk;
+ status = "disabled";
+
+ usb_dwc3: usb@4e00000 {
+diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
+index 761a6757dc26f..2abd4c87a3ca9 100644
+--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
+@@ -1879,7 +1879,7 @@ pcie0: pcie@1c00000 {
+ phy-names = "pciephy";
+
+ perst-gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>;
+- enable-gpio = <&tlmm 37 GPIO_ACTIVE_HIGH>;
++ wake-gpios = <&tlmm 37 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_default_state>;
+diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
+index 01e4dfc4babd2..06f183ef8c78f 100644
+--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
+@@ -1028,6 +1028,12 @@ uart20: serial@894000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_uart20_default>;
+ interrupts = <GIC_SPI 587 IRQ_TYPE_LEVEL_HIGH>;
++ interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS
++ &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>,
++ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
++ &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>;
++ interconnect-names = "qup-core",
++ "qup-config";
+ status = "disabled";
+ };
+
+@@ -1420,6 +1426,12 @@ uart7: serial@99c000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_uart7_tx>, <&qup_uart7_rx>;
+ interrupts = <GIC_SPI 608 IRQ_TYPE_LEVEL_HIGH>;
++ interconnects = <&clk_virt MASTER_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS
++ &clk_virt SLAVE_QUP_CORE_2 QCOM_ICC_TAG_ALWAYS>,
++ <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ALWAYS
++ &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>;
++ interconnect-names = "qup-core",
++ "qup-config";
+ status = "disabled";
+ };
+ };
+diff --git a/arch/arm64/boot/dts/qcom/sm8550.dtsi b/arch/arm64/boot/dts/qcom/sm8550.dtsi
+index ee1ba5a8c8fc2..90acdf16b8307 100644
+--- a/arch/arm64/boot/dts/qcom/sm8550.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8550.dtsi
+@@ -3248,7 +3248,7 @@ sram@c3f0000 {
+ spmi_bus: spmi@c400000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0 0x0c400000 0 0x3000>,
+- <0 0x0c500000 0 0x4000000>,
++ <0 0x0c500000 0 0x400000>,
+ <0 0x0c440000 0 0x80000>,
+ <0 0x0c4c0000 0 0x20000>,
+ <0 0x0c42d000 0 0x4000>;
+diff --git a/arch/arm64/boot/dts/qcom/sm8650.dtsi b/arch/arm64/boot/dts/qcom/sm8650.dtsi
+index 2df77123a8c7b..0e4bd83b2c68a 100644
+--- a/arch/arm64/boot/dts/qcom/sm8650.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8650.dtsi
+@@ -2448,10 +2448,12 @@ ufs_mem_phy: phy@1d80000 {
+ compatible = "qcom,sm8650-qmp-ufs-phy";
+ reg = <0 0x01d80000 0 0x2000>;
+
+- clocks = <&tcsr TCSR_UFS_CLKREF_EN>,
+- <&gcc GCC_UFS_PHY_PHY_AUX_CLK>;
++ clocks = <&rpmhcc RPMH_CXO_CLK>,
++ <&gcc GCC_UFS_PHY_PHY_AUX_CLK>,
++ <&tcsr TCSR_UFS_CLKREF_EN>;
+ clock-names = "ref",
+- "ref_aux";
++ "ref_aux",
++ "qref";
+
+ resets = <&ufs_mem_hc 0>;
+ reset-names = "ufsphy";
+@@ -3703,7 +3705,7 @@ sram@c3f0000 {
+ spmi_bus: spmi@c400000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0 0x0c400000 0 0x3000>,
+- <0 0x0c500000 0 0x4000000>,
++ <0 0x0c500000 0 0x400000>,
+ <0 0x0c440000 0 0x80000>,
+ <0 0x0c4c0000 0 0x20000>,
+ <0 0x0c42d000 0 0x4000>;
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
+index a37ad9475c90d..3112487d2a168 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
++++ b/arch/arm64/boot/dts/qcom/x1e80100-qcp.dts
+@@ -243,7 +243,7 @@ regulators-3 {
+ qcom,pmic-id = "e";
+
+ vdd-l2-supply = <&vreg_s1f_0p7>;
+- vdd-l3-supply = <&vph_pwr>;
++ vdd-l3-supply = <&vreg_s5j_1p2>;
+
+ vreg_l2e_0p8: ldo2 {
+ regulator-name = "vreg_l2e_0p8";
+@@ -349,7 +349,7 @@ regulators-7 {
+ qcom,pmic-id = "j";
+
+ vdd-l1-supply = <&vreg_s1f_0p7>;
+- vdd-l2-supply = <&vph_pwr>;
++ vdd-l2-supply = <&vreg_s5j_1p2>;
+ vdd-l3-supply = <&vreg_s1f_0p7>;
+ vdd-s5-supply = <&vph_pwr>;
+
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
+index 6f75fc342ceb3..be1285d9919e0 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi
++++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
+@@ -3315,7 +3315,6 @@ apps_rsc: rsc@17500000 {
+ <0 0x17510000 0 0x10000>,
+ <0 0x17520000 0 0x10000>;
+ reg-names = "drv-0", "drv-1", "drv-2";
+- qcom,drv-count = <3>;
+
+ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+diff --git a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
+index 4e67a03564971..504ac8c93faf5 100644
+--- a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
++++ b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
+@@ -658,7 +658,7 @@ channel7 {
+ avb0: ethernet@e6800000 {
+ compatible = "renesas,etheravb-r8a779a0",
+ "renesas,etheravb-rcar-gen4";
+- reg = <0 0xe6800000 0 0x800>;
++ reg = <0 0xe6800000 0 0x1000>;
+ interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>,
+@@ -706,7 +706,7 @@ avb0: ethernet@e6800000 {
+ avb1: ethernet@e6810000 {
+ compatible = "renesas,etheravb-r8a779a0",
+ "renesas,etheravb-rcar-gen4";
+- reg = <0 0xe6810000 0 0x800>;
++ reg = <0 0xe6810000 0 0x1000>;
+ interrupts = <GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 283 IRQ_TYPE_LEVEL_HIGH>,
+diff --git a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
+index d3d25e077c5d5..d7677595204dc 100644
+--- a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
++++ b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
+@@ -161,11 +161,6 @@ L3_CA76_1: cache-controller-1 {
+ };
+ };
+
+- psci {
+- compatible = "arm,psci-1.0", "arm,psci-0.2";
+- method = "smc";
+- };
+-
+ extal_clk: extal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+@@ -185,13 +180,24 @@ pmu_a76 {
+ interrupts-extended = <&gic GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+- /* External SCIF clock - to be overridden by boards that provide it */
++ psci {
++ compatible = "arm,psci-1.0", "arm,psci-0.2";
++ method = "smc";
++ };
++
++ /* External SCIF clocks - to be overridden by boards that provide them */
+ scif_clk: scif {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
++ scif_clk2: scif2 {
++ compatible = "fixed-clock";
++ #clock-cells = <0>;
++ clock-frequency = <0>;
++ };
++
+ soc: soc {
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+@@ -681,7 +687,7 @@ hscif2: serial@e6560000 {
+ interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 516>,
+ <&cpg CPG_CORE R8A779G0_CLK_SASYNCPERD1>,
+- <&scif_clk>;
++ <&scif_clk2>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x35>, <&dmac0 0x34>,
+ <&dmac1 0x35>, <&dmac1 0x34>;
+@@ -761,7 +767,7 @@ channel7 {
+ avb0: ethernet@e6800000 {
+ compatible = "renesas,etheravb-r8a779g0",
+ "renesas,etheravb-rcar-gen4";
+- reg = <0 0xe6800000 0 0x800>;
++ reg = <0 0xe6800000 0 0x1000>;
+ interrupts = <GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>,
+@@ -808,7 +814,7 @@ avb0: ethernet@e6800000 {
+ avb1: ethernet@e6810000 {
+ compatible = "renesas,etheravb-r8a779g0",
+ "renesas,etheravb-rcar-gen4";
+- reg = <0 0xe6810000 0 0x800>;
++ reg = <0 0xe6810000 0 0x1000>;
+ interrupts = <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 362 IRQ_TYPE_LEVEL_HIGH>,
+@@ -1057,7 +1063,7 @@ scif4: serial@e6c40000 {
+ interrupts = <GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 705>,
+ <&cpg CPG_CORE R8A779G0_CLK_SASYNCPERD1>,
+- <&scif_clk>;
++ <&scif_clk2>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x59>, <&dmac0 0x58>,
+ <&dmac1 0x59>, <&dmac1 0x58>;
+@@ -1777,6 +1783,37 @@ ssi0: ssi-0 {
+ };
+ };
+
++ mmc0: mmc@ee140000 {
++ compatible = "renesas,sdhi-r8a779g0",
++ "renesas,rcar-gen4-sdhi";
++ reg = <0 0xee140000 0 0x2000>;
++ interrupts = <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&cpg CPG_MOD 706>,
++ <&cpg CPG_CORE R8A779G0_CLK_SD0H>;
++ clock-names = "core", "clkh";
++ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
++ resets = <&cpg 706>;
++ max-frequency = <200000000>;
++ iommus = <&ipmmu_ds0 32>;
++ status = "disabled";
++ };
++
++ rpc: spi@ee200000 {
++ compatible = "renesas,r8a779g0-rpc-if",
++ "renesas,rcar-gen4-rpc-if";
++ reg = <0 0xee200000 0 0x200>,
++ <0 0x08000000 0 0x04000000>,
++ <0 0xee208000 0 0x100>;
++ reg-names = "regs", "dirmap", "wbuf";
++ interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&cpg CPG_MOD 629>;
++ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
++ resets = <&cpg 629>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++ status = "disabled";
++ };
++
+ ipmmu_rt0: iommu@ee480000 {
+ compatible = "renesas,ipmmu-r8a779g0",
+ "renesas,rcar-gen4-ipmmu-vmsa";
+@@ -1886,37 +1923,6 @@ ipmmu_mm: iommu@eefc0000 {
+ #iommu-cells = <1>;
+ };
+
+- mmc0: mmc@ee140000 {
+- compatible = "renesas,sdhi-r8a779g0",
+- "renesas,rcar-gen4-sdhi";
+- reg = <0 0xee140000 0 0x2000>;
+- interrupts = <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>;
+- clocks = <&cpg CPG_MOD 706>,
+- <&cpg CPG_CORE R8A779G0_CLK_SD0H>;
+- clock-names = "core", "clkh";
+- power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+- resets = <&cpg 706>;
+- max-frequency = <200000000>;
+- iommus = <&ipmmu_ds0 32>;
+- status = "disabled";
+- };
+-
+- rpc: spi@ee200000 {
+- compatible = "renesas,r8a779g0-rpc-if",
+- "renesas,rcar-gen4-rpc-if";
+- reg = <0 0xee200000 0 0x200>,
+- <0 0x08000000 0 0x04000000>,
+- <0 0xee208000 0 0x100>;
+- reg-names = "regs", "dirmap", "wbuf";
+- interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
+- clocks = <&cpg CPG_MOD 629>;
+- power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+- resets = <&cpg 629>;
+- #address-cells = <1>;
+- #size-cells = <0>;
+- status = "disabled";
+- };
+-
+ gic: interrupt-controller@f1000000 {
+ compatible = "arm,gic-v3";
+ #interrupt-cells = <3>;
+diff --git a/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi b/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi
+index 2ab231572d95f..b3f83d0ebcbb5 100644
+--- a/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi
++++ b/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi
+@@ -109,7 +109,13 @@ irqc: interrupt-controller@110a0000 {
+ <SOC_PERIPHERAL_IRQ(473) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(474) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(475) IRQ_TYPE_LEVEL_HIGH>,
+- <SOC_PERIPHERAL_IRQ(25) IRQ_TYPE_EDGE_RISING>;
++ <SOC_PERIPHERAL_IRQ(25) IRQ_TYPE_EDGE_RISING>,
++ <SOC_PERIPHERAL_IRQ(34) IRQ_TYPE_EDGE_RISING>,
++ <SOC_PERIPHERAL_IRQ(35) IRQ_TYPE_EDGE_RISING>,
++ <SOC_PERIPHERAL_IRQ(36) IRQ_TYPE_EDGE_RISING>,
++ <SOC_PERIPHERAL_IRQ(37) IRQ_TYPE_EDGE_RISING>,
++ <SOC_PERIPHERAL_IRQ(38) IRQ_TYPE_EDGE_RISING>,
++ <SOC_PERIPHERAL_IRQ(39) IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "nmi",
+ "irq0", "irq1", "irq2", "irq3",
+ "irq4", "irq5", "irq6", "irq7",
+@@ -121,7 +127,9 @@ irqc: interrupt-controller@110a0000 {
+ "tint20", "tint21", "tint22", "tint23",
+ "tint24", "tint25", "tint26", "tint27",
+ "tint28", "tint29", "tint30", "tint31",
+- "bus-err";
++ "bus-err", "ec7tie1-0", "ec7tie2-0",
++ "ec7tiovf-0", "ec7tie1-1", "ec7tie2-1",
++ "ec7tiovf-1";
+ clocks = <&cpg CPG_MOD R9A07G043_IA55_CLK>,
+ <&cpg CPG_MOD R9A07G043_IA55_PCLK>;
+ clock-names = "clk", "pclk";
+diff --git a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
+index 66f68fc2b2411..081d8f49db879 100644
+--- a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
++++ b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
+@@ -905,7 +905,27 @@ irqc: interrupt-controller@110a0000 {
+ <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>;
++ <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 25 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 37 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 38 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 39 IRQ_TYPE_EDGE_RISING>;
++ interrupt-names = "nmi", "irq0", "irq1", "irq2", "irq3",
++ "irq4", "irq5", "irq6", "irq7",
++ "tint0", "tint1", "tint2", "tint3",
++ "tint4", "tint5", "tint6", "tint7",
++ "tint8", "tint9", "tint10", "tint11",
++ "tint12", "tint13", "tint14", "tint15",
++ "tint16", "tint17", "tint18", "tint19",
++ "tint20", "tint21", "tint22", "tint23",
++ "tint24", "tint25", "tint26", "tint27",
++ "tint28", "tint29", "tint30", "tint31",
++ "bus-err", "ec7tie1-0", "ec7tie2-0",
++ "ec7tiovf-0", "ec7tie1-1", "ec7tie2-1",
++ "ec7tiovf-1";
+ clocks = <&cpg CPG_MOD R9A07G044_IA55_CLK>,
+ <&cpg CPG_MOD R9A07G044_IA55_PCLK>;
+ clock-names = "clk", "pclk";
+diff --git a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi
+index 1f1d481dc7830..0d327464d2baf 100644
+--- a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi
++++ b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi
+@@ -912,7 +912,27 @@ irqc: interrupt-controller@110a0000 {
+ <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>;
++ <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 25 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 34 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 37 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 38 IRQ_TYPE_EDGE_RISING>,
++ <GIC_SPI 39 IRQ_TYPE_EDGE_RISING>;
++ interrupt-names = "nmi", "irq0", "irq1", "irq2", "irq3",
++ "irq4", "irq5", "irq6", "irq7",
++ "tint0", "tint1", "tint2", "tint3",
++ "tint4", "tint5", "tint6", "tint7",
++ "tint8", "tint9", "tint10", "tint11",
++ "tint12", "tint13", "tint14", "tint15",
++ "tint16", "tint17", "tint18", "tint19",
++ "tint20", "tint21", "tint22", "tint23",
++ "tint24", "tint25", "tint26", "tint27",
++ "tint28", "tint29", "tint30", "tint31",
++ "bus-err", "ec7tie1-0", "ec7tie2-0",
++ "ec7tiovf-0", "ec7tie1-1", "ec7tie2-1",
++ "ec7tiovf-1";
+ clocks = <&cpg CPG_MOD R9A07G054_IA55_CLK>,
+ <&cpg CPG_MOD R9A07G054_IA55_PCLK>;
+ clock-names = "clk", "pclk";
+diff --git a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
+index 5facfad961583..6315ffa6c1bb9 100644
+--- a/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
++++ b/arch/arm64/boot/dts/renesas/r9a08g045.dtsi
+@@ -152,7 +152,10 @@ irqc: interrupt-controller@11050000 {
+ <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>,
+- <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
++ <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "nmi",
+ "irq0", "irq1", "irq2", "irq3",
+ "irq4", "irq5", "irq6", "irq7",
+@@ -164,7 +167,8 @@ irqc: interrupt-controller@11050000 {
+ "tint20", "tint21", "tint22", "tint23",
+ "tint24", "tint25", "tint26", "tint27",
+ "tint28", "tint29", "tint30", "tint31",
+- "bus-err";
++ "bus-err", "ec7tie1-0", "ec7tie2-0",
++ "ec7tiovf-0";
+ clocks = <&cpg CPG_MOD R9A08G045_IA55_CLK>,
+ <&cpg CPG_MOD R9A08G045_IA55_PCLK>;
+ clock-names = "clk", "pclk";
+diff --git a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi
+index f062d4ad78b79..d33ab4c887878 100644
+--- a/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi
++++ b/arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi
+@@ -193,12 +193,14 @@ &sdhi2 {
+ #endif
+
+ &pinctrl {
++#if SW_CONFIG3 == SW_ON
+ eth0-phy-irq-hog {
+ gpio-hog;
+ gpios = <RZG2L_GPIO(12, 0) GPIO_ACTIVE_LOW>;
+ input;
+ line-name = "eth0-phy-irq";
+ };
++#endif
+
+ eth0_pins: eth0 {
+ txc {
+@@ -234,12 +236,14 @@ mux {
+ };
+ };
+
++#if SW_CONFIG3 == SW_ON
+ eth1-phy-irq-hog {
+ gpio-hog;
+ gpios = <RZG2L_GPIO(12, 1) GPIO_ACTIVE_LOW>;
+ input;
+ line-name = "eth1-phy-irq";
+ };
++#endif
+
+ eth1_pins: eth1 {
+ txc {
+diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+index c19c0f1b3778f..92f96ec01385d 100644
+--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+@@ -597,6 +597,7 @@ vpu: video-codec@fdea0400 {
+ compatible = "rockchip,rk3568-vpu";
+ reg = <0x0 0xfdea0000 0x0 0x800>;
+ interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "vdpu";
+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
+ clock-names = "aclk", "hclk";
+ iommus = <&vdpu_mmu>;
+@@ -1123,7 +1124,7 @@ i2s2_2ch: i2s@fe420000 {
+ dmas = <&dmac1 4>, <&dmac1 5>;
+ dma-names = "tx", "rx";
+ resets = <&cru SRST_M_I2S2_2CH>;
+- reset-names = "m";
++ reset-names = "tx-m";
+ rockchip,grf = <&grf>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s2m0_sclktx
+diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+index 36b1b7acfe6a1..82350ddb262f2 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+@@ -1704,7 +1704,6 @@ i2s2_2ch: i2s@fe490000 {
+ dmas = <&dmac1 0>, <&dmac1 1>;
+ dma-names = "tx", "rx";
+ power-domains = <&power RK3588_PD_AUDIO>;
+- rockchip,trcm-sync-tx-only;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s2m1_lrck
+ &i2s2m1_sclk
+@@ -1725,7 +1724,6 @@ i2s3_2ch: i2s@fe4a0000 {
+ dmas = <&dmac1 2>, <&dmac1 3>;
+ dma-names = "tx", "rx";
+ power-domains = <&power RK3588_PD_AUDIO>;
+- rockchip,trcm-sync-tx-only;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s3_lrck
+ &i2s3_sclk
+diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile
+index 52c1dc9103087..08ce34d21d5d0 100644
+--- a/arch/arm64/boot/dts/ti/Makefile
++++ b/arch/arm64/boot/dts/ti/Makefile
+@@ -57,6 +57,7 @@ dtb-$(CONFIG_ARCH_K3) += k3-am654-base-board.dtb
+ dtb-$(CONFIG_ARCH_K3) += k3-am654-gp-evm.dtb
+ dtb-$(CONFIG_ARCH_K3) += k3-am654-evm.dtb
+ dtb-$(CONFIG_ARCH_K3) += k3-am654-idk.dtb
++dtb-$(CONFIG_ARCH_K3) += k3-am654-base-board-rocktech-rk101-panel.dtbo
+
+ # Boards with J7200 SoC
+ k3-j7200-evm-dtbs := k3-j7200-common-proc-board.dtb k3-j7200-evm-quad-port-eth-exp.dtbo
+diff --git a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
+index 464b7565d085d..6d07b65a3614e 100644
+--- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
+@@ -640,6 +640,8 @@ usb0: usb@31000000 {
+ interrupt-names = "host", "peripheral";
+ maximum-speed = "high-speed";
+ dr_mode = "otg";
++ snps,usb2-gadget-lpm-disable;
++ snps,usb2-lpm-disable;
+ };
+ };
+
+@@ -663,6 +665,8 @@ usb1: usb@31100000 {
+ interrupt-names = "host", "peripheral";
+ maximum-speed = "high-speed";
+ dr_mode = "otg";
++ snps,usb2-gadget-lpm-disable;
++ snps,usb2-lpm-disable;
+ };
+ };
+
+@@ -779,9 +783,10 @@ dss: dss@30200000 {
+ <0x00 0x30207000 0x00 0x1000>, /* ovr1 */
+ <0x00 0x30208000 0x00 0x1000>, /* ovr2 */
+ <0x00 0x3020a000 0x00 0x1000>, /* vp1: Used for OLDI */
+- <0x00 0x3020b000 0x00 0x1000>; /* vp2: Used as DPI Out */
++ <0x00 0x3020b000 0x00 0x1000>, /* vp2: Used as DPI Out */
++ <0x00 0x30201000 0x00 0x1000>; /* common1 */
+ reg-names = "common", "vidl1", "vid",
+- "ovr1", "ovr2", "vp1", "vp2";
++ "ovr1", "ovr2", "vp1", "vp2", "common1";
+ power-domains = <&k3_pds 186 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&k3_clks 186 6>,
+ <&dss_vp1_clk>,
+diff --git a/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi
+index c4b0b91d70cf3..14eb9ba836d32 100644
+--- a/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi
+@@ -187,6 +187,8 @@ mcu_r5fss0: r5fss@79000000 {
+ ranges = <0x79000000 0x00 0x79000000 0x8000>,
+ <0x79020000 0x00 0x79020000 0x8000>;
+ power-domains = <&k3_pds 7 TI_SCI_PD_EXCLUSIVE>;
++ status = "disabled";
++
+ mcu_r5fss0_core0: r5f@79000000 {
+ compatible = "ti,am62-r5f";
+ reg = <0x79000000 0x00008000>,
+diff --git a/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi
+index 19f42b39394ee..10a7059b2d9b5 100644
+--- a/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi
+@@ -78,6 +78,7 @@ wkup_r5fss0: r5fss@78000000 {
+ ranges = <0x78000000 0x00 0x78000000 0x8000>,
+ <0x78100000 0x00 0x78100000 0x8000>;
+ power-domains = <&k3_pds 119 TI_SCI_PD_EXCLUSIVE>;
++ status = "disabled";
+
+ wkup_r5fss0_core0: r5f@78000000 {
+ compatible = "ti,am62-r5f";
+diff --git a/arch/arm64/boot/dts/ti/k3-am62p.dtsi b/arch/arm64/boot/dts/ti/k3-am62p.dtsi
+index 84ffe7b9dcaf3..4f22b5d9fb9f0 100644
+--- a/arch/arm64/boot/dts/ti/k3-am62p.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-am62p.dtsi
+@@ -71,7 +71,7 @@ cbass_main: bus@f0000 {
+ <0x00 0x43600000 0x00 0x43600000 0x00 0x00010000>, /* SA3 sproxy data */
+ <0x00 0x44043000 0x00 0x44043000 0x00 0x00000fe0>, /* TI SCI DEBUG */
+ <0x00 0x44860000 0x00 0x44860000 0x00 0x00040000>, /* SA3 sproxy config */
+- <0x00 0x48000000 0x00 0x48000000 0x00 0x06400000>, /* DMSS */
++ <0x00 0x48000000 0x00 0x48000000 0x00 0x06408000>, /* DMSS */
+ <0x00 0x60000000 0x00 0x60000000 0x00 0x08000000>, /* FSS0 DAT1 */
+ <0x00 0x70000000 0x00 0x70000000 0x00 0x00010000>, /* OCSRAM */
+ <0x01 0x00000000 0x01 0x00000000 0x00 0x00310000>, /* A53 PERIPHBASE */
+diff --git a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
+index 1773c05f752cd..60868862e3b43 100644
+--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
++++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
+@@ -445,6 +445,10 @@ &cpsw_port2 {
+ };
+
+ &cpsw3g_mdio {
++ pinctrl-names = "default";
++ pinctrl-0 = <&main_mdio1_pins_default>;
++ status = "okay";
++
+ cpsw3g_phy0: ethernet-phy@0 {
+ reg = <0>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+diff --git a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
+index e348114f42e01..ba624ef72f5b4 100644
+--- a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
+@@ -633,6 +633,9 @@ sdhci0: mmc@fa10000 {
+ ti,otap-del-sel-mmc-hs = <0x0>;
+ ti,otap-del-sel-ddr52 = <0x6>;
+ ti,otap-del-sel-hs200 = <0x7>;
++ ti,itap-del-sel-legacy = <0x10>;
++ ti,itap-del-sel-mmc-hs = <0xa>;
++ ti,itap-del-sel-ddr52 = <0x3>;
+ status = "disabled";
+ };
+
+@@ -645,12 +648,16 @@ sdhci1: mmc@fa00000 {
+ clock-names = "clk_ahb", "clk_xin";
+ ti,trm-icp = <0x2>;
+ ti,otap-del-sel-legacy = <0x0>;
+- ti,otap-del-sel-sd-hs = <0xf>;
++ ti,otap-del-sel-sd-hs = <0x0>;
+ ti,otap-del-sel-sdr12 = <0xf>;
+ ti,otap-del-sel-sdr25 = <0xf>;
+ ti,otap-del-sel-sdr50 = <0xc>;
+ ti,otap-del-sel-sdr104 = <0x6>;
+ ti,otap-del-sel-ddr50 = <0x9>;
++ ti,itap-del-sel-legacy = <0x0>;
++ ti,itap-del-sel-sd-hs = <0x0>;
++ ti,itap-del-sel-sdr12 = <0x0>;
++ ti,itap-del-sel-sdr25 = <0x0>;
+ ti,clkbuf-sel = <0x7>;
+ status = "disabled";
+ };
+diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+index fcea544656360..5b2d4365b9111 100644
+--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+@@ -1019,9 +1019,10 @@ dss: dss@4a00000 {
+ <0x0 0x04a07000 0x0 0x1000>, /* ovr1 */
+ <0x0 0x04a08000 0x0 0x1000>, /* ovr2 */
+ <0x0 0x04a0a000 0x0 0x1000>, /* vp1 */
+- <0x0 0x04a0b000 0x0 0x1000>; /* vp2 */
++ <0x0 0x04a0b000 0x0 0x1000>, /* vp2 */
++ <0x0 0x04a01000 0x0 0x1000>; /* common1 */
+ reg-names = "common", "vidl1", "vid",
+- "ovr1", "ovr2", "vp1", "vp2";
++ "ovr1", "ovr2", "vp1", "vp2", "common1";
+
+ ti,am65x-oldi-io-ctrl = <&dss_oldi_io_ctrl>;
+
+diff --git a/arch/arm64/boot/dts/ti/k3-am69-sk.dts b/arch/arm64/boot/dts/ti/k3-am69-sk.dts
+index 8da5915798688..c8fb9dfb89723 100644
+--- a/arch/arm64/boot/dts/ti/k3-am69-sk.dts
++++ b/arch/arm64/boot/dts/ti/k3-am69-sk.dts
+@@ -646,7 +646,7 @@ tps659413: pmic@48 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_irq_pins_default>;
+ interrupt-parent = <&wkup_gpio0>;
+- interrupts = <39 IRQ_TYPE_EDGE_FALLING>;
++ interrupts = <83 IRQ_TYPE_EDGE_FALLING>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ti,primary-pmic;
+@@ -918,13 +918,9 @@ &dss {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dss_vout0_pins_default>;
+ assigned-clocks = <&k3_clks 218 2>,
+- <&k3_clks 218 5>,
+- <&k3_clks 218 14>,
+- <&k3_clks 218 18>;
++ <&k3_clks 218 5>;
+ assigned-clock-parents = <&k3_clks 218 3>,
+- <&k3_clks 218 7>,
+- <&k3_clks 218 16>,
+- <&k3_clks 218 22>;
++ <&k3_clks 218 7>;
+ };
+
+ &serdes_wiz4 {
+diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
+index cee2b4b0eb87d..7a0c599f2b1c3 100644
+--- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
++++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
+@@ -91,24 +91,25 @@ vdd_sd_dv: gpio-regulator-TLV71033 {
+ };
+
+ &wkup_pmx0 {
++};
++
++&wkup_pmx2 {
+ mcu_uart0_pins_default: mcu-uart0-default-pins {
+ pinctrl-single,pins = <
+- J721E_WKUP_IOPAD(0xf4, PIN_INPUT, 0) /* (D20) MCU_UART0_RXD */
+- J721E_WKUP_IOPAD(0xf0, PIN_OUTPUT, 0) /* (D19) MCU_UART0_TXD */
+- J721E_WKUP_IOPAD(0xf8, PIN_INPUT, 0) /* (E20) MCU_UART0_CTSn */
+- J721E_WKUP_IOPAD(0xfc, PIN_OUTPUT, 0) /* (E21) MCU_UART0_RTSn */
++ J721E_WKUP_IOPAD(0x90, PIN_INPUT, 0) /* (E20) MCU_UART0_CTSn */
++ J721E_WKUP_IOPAD(0x94, PIN_OUTPUT, 0) /* (E21) MCU_UART0_RTSn */
++ J721E_WKUP_IOPAD(0x8c, PIN_INPUT, 0) /* (D20) MCU_UART0_RXD */
++ J721E_WKUP_IOPAD(0x88, PIN_OUTPUT, 0) /* (D19) MCU_UART0_TXD */
+ >;
+ };
+
+ wkup_uart0_pins_default: wkup-uart0-default-pins {
+ pinctrl-single,pins = <
+- J721E_WKUP_IOPAD(0xb0, PIN_INPUT, 0) /* (B14) WKUP_UART0_RXD */
+- J721E_WKUP_IOPAD(0xb4, PIN_OUTPUT, 0) /* (A14) WKUP_UART0_TXD */
++ J721E_WKUP_IOPAD(0x48, PIN_INPUT, 0) /* (B14) WKUP_UART0_RXD */
++ J721E_WKUP_IOPAD(0x4c, PIN_OUTPUT, 0) /* (A14) WKUP_UART0_TXD */
+ >;
+ };
+-};
+
+-&wkup_pmx2 {
+ mcu_cpsw_pins_default: mcu-cpsw-default-pins {
+ pinctrl-single,pins = <
+ J721E_WKUP_IOPAD(0x0000, PIN_OUTPUT, 0) /* MCU_RGMII1_TX_CTL */
+@@ -210,7 +211,6 @@ &mcu_uart0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_uart0_pins_default>;
+- clock-frequency = <96000000>;
+ };
+
+ &main_uart0 {
+diff --git a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
+index a74912d9e4daf..c463e23ced04e 100644
+--- a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
+@@ -353,9 +353,9 @@ fss: bus@47000000 {
+
+ hbmc_mux: mux-controller@47000004 {
+ compatible = "reg-mux";
+- reg = <0x00 0x47000004 0x00 0x2>;
++ reg = <0x00 0x47000004 0x00 0x4>;
+ #mux-control-cells = <1>;
+- mux-reg-masks = <0x4 0x2>; /* HBMC select */
++ mux-reg-masks = <0x0 0x2>; /* HBMC select */
+ };
+
+ hbmc: hyperbus@47034000 {
+diff --git a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
+index 188dfe291a32b..658764f7d5443 100644
+--- a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
++++ b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
+@@ -574,7 +574,7 @@ tps659413: pmic@48 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_irq_pins_default>;
+ interrupt-parent = <&wkup_gpio0>;
+- interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
++ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ti,primary-pmic;
+@@ -651,7 +651,7 @@ tps659411: pmic@4c {
+ reg = <0x4c>;
+ system-power-controller;
+ interrupt-parent = <&wkup_gpio0>;
+- interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
++ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ buck1234-supply = <&vsys_3v3>;
+diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts
+index c6b85bbf9a179..1ba1f53c72d03 100644
+--- a/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts
++++ b/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts
+@@ -190,8 +190,6 @@ J721S2_IOPAD(0x038, PIN_OUTPUT, 0) /* (AB28) MCASP0_ACLKX.MCAN5_TX */
+ &wkup_pmx2 {
+ wkup_uart0_pins_default: wkup-uart0-default-pins {
+ pinctrl-single,pins = <
+- J721S2_WKUP_IOPAD(0x070, PIN_INPUT, 0) /* (E25) WKUP_GPIO0_6.WKUP_UART0_CTSn */
+- J721S2_WKUP_IOPAD(0x074, PIN_OUTPUT, 0) /* (F28) WKUP_GPIO0_7.WKUP_UART0_RTSn */
+ J721S2_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (D28) WKUP_UART0_RXD */
+ J721S2_WKUP_IOPAD(0x04c, PIN_OUTPUT, 0) /* (D27) WKUP_UART0_TXD */
+ >;
+diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
+index 80aa33c58a452..a47cb557dd956 100644
+--- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
+@@ -663,7 +663,7 @@ wkup_vtm0: temperature-sensor@42040000 {
+ compatible = "ti,j7200-vtm";
+ reg = <0x00 0x42040000 0x0 0x350>,
+ <0x00 0x42050000 0x0 0x350>;
+- power-domains = <&k3_pds 154 TI_SCI_PD_SHARED>;
++ power-domains = <&k3_pds 180 TI_SCI_PD_SHARED>;
+ #thermal-sensor-cells = <1>;
+ };
+
+diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
+index f34b92acc56d8..33795a0bc69cf 100644
+--- a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
++++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
+@@ -335,8 +335,6 @@ &wkup_pmx2 {
+ wkup_uart0_pins_default: wkup-uart0-default-pins {
+ bootph-all;
+ pinctrl-single,pins = <
+- J721S2_WKUP_IOPAD(0x070, PIN_INPUT, 0) /* (L37) WKUP_GPIO0_6.WKUP_UART0_CTSn */
+- J721S2_WKUP_IOPAD(0x074, PIN_INPUT, 0) /* (L36) WKUP_GPIO0_7.WKUP_UART0_RTSn */
+ J721S2_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (K35) WKUP_UART0_RXD */
+ J721S2_WKUP_IOPAD(0x04c, PIN_INPUT, 0) /* (K34) WKUP_UART0_TXD */
+ >;
+diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
+index f2b720ed1e4f2..56c8eaad6324b 100644
+--- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
+@@ -52,12 +52,12 @@ serdes_ln_ctrl: mux-controller@4080 {
+ compatible = "reg-mux";
+ reg = <0x00004080 0x30>;
+ #mux-control-cells = <1>;
+- mux-reg-masks = <0x4080 0x3>, <0x4084 0x3>, /* SERDES0 lane0/1 select */
+- <0x4088 0x3>, <0x408c 0x3>, /* SERDES0 lane2/3 select */
+- <0x4090 0x3>, <0x4094 0x3>, /* SERDES1 lane0/1 select */
+- <0x4098 0x3>, <0x409c 0x3>, /* SERDES1 lane2/3 select */
+- <0x40a0 0x3>, <0x40a4 0x3>, /* SERDES2 lane0/1 select */
+- <0x40a8 0x3>, <0x40ac 0x3>; /* SERDES2 lane2/3 select */
++ mux-reg-masks = <0x0 0x3>, <0x4 0x3>, /* SERDES0 lane0/1 select */
++ <0x8 0x3>, <0xc 0x3>, /* SERDES0 lane2/3 select */
++ <0x10 0x3>, <0x14 0x3>, /* SERDES1 lane0/1 select */
++ <0x18 0x3>, <0x1c 0x3>, /* SERDES1 lane2/3 select */
++ <0x20 0x3>, <0x24 0x3>, /* SERDES2 lane0/1 select */
++ <0x28 0x3>, <0x2c 0x3>; /* SERDES2 lane2/3 select */
+ idle-states = <J784S4_SERDES0_LANE0_PCIE1_LANE0>,
+ <J784S4_SERDES0_LANE1_PCIE1_LANE1>,
+ <J784S4_SERDES0_LANE2_IP3_UNUSED>,
+diff --git a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi
+index 3902a921d7e58..337122c3f4020 100644
+--- a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi
++++ b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi
+@@ -628,7 +628,7 @@ wkup_vtm0: temperature-sensor@42040000 {
+ compatible = "ti,j7200-vtm";
+ reg = <0x00 0x42040000 0x00 0x350>,
+ <0x00 0x42050000 0x00 0x350>;
+- power-domains = <&k3_pds 154 TI_SCI_PD_SHARED>;
++ power-domains = <&k3_pds 243 TI_SCI_PD_SHARED>;
+ #thermal-sensor-cells = <1>;
+ };
+
+diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h
+index 23c67c0871b17..6cc79296c8ef2 100644
+--- a/arch/mips/include/asm/mips-cm.h
++++ b/arch/mips/include/asm/mips-cm.h
+@@ -33,6 +33,19 @@ extern void __iomem *mips_cm_l2sync_base;
+ */
+ extern phys_addr_t __mips_cm_phys_base(void);
+
++/**
++ * mips_cm_l2sync_phys_base - retrieve the physical base address of the CM
++ * L2-sync region
++ *
++ * This function returns the physical base address of the Coherence Manager
++ * L2-cache only region. It provides a default implementation which reads the
++ * CMGCRL2OnlySyncBase register where available or returns a 4K region just
++ * behind the CM GCR base address. It may be overridden by platforms which
++ * determine this address in a different way by defining a function with the
++ * same prototype.
++ */
++extern phys_addr_t mips_cm_l2sync_phys_base(void);
++
+ /*
+ * mips_cm_is64 - determine CM register width
+ *
+diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c
+index 84b3affb9de88..268ac0b811e35 100644
+--- a/arch/mips/kernel/mips-cm.c
++++ b/arch/mips/kernel/mips-cm.c
+@@ -201,7 +201,7 @@ phys_addr_t __mips_cm_phys_base(void)
+ phys_addr_t mips_cm_phys_base(void)
+ __attribute__((weak, alias("__mips_cm_phys_base")));
+
+-static phys_addr_t __mips_cm_l2sync_phys_base(void)
++phys_addr_t __weak mips_cm_l2sync_phys_base(void)
+ {
+ u32 base_reg;
+
+@@ -217,9 +217,6 @@ static phys_addr_t __mips_cm_l2sync_phys_base(void)
+ return mips_cm_phys_base() + MIPS_CM_GCR_SIZE;
+ }
+
+-phys_addr_t mips_cm_l2sync_phys_base(void)
+- __attribute__((weak, alias("__mips_cm_l2sync_phys_base")));
+-
+ static void mips_cm_probe_l2sync(void)
+ {
+ unsigned major_rev;
+diff --git a/arch/powerpc/include/asm/vmalloc.h b/arch/powerpc/include/asm/vmalloc.h
+index 4c69ece52a31e..59ed89890c902 100644
+--- a/arch/powerpc/include/asm/vmalloc.h
++++ b/arch/powerpc/include/asm/vmalloc.h
+@@ -7,14 +7,14 @@
+ #ifdef CONFIG_HAVE_ARCH_HUGE_VMAP
+
+ #define arch_vmap_pud_supported arch_vmap_pud_supported
+-static inline bool arch_vmap_pud_supported(pgprot_t prot)
++static __always_inline bool arch_vmap_pud_supported(pgprot_t prot)
+ {
+ /* HPT does not cope with large pages in the vmalloc area */
+ return radix_enabled();
+ }
+
+ #define arch_vmap_pmd_supported arch_vmap_pmd_supported
+-static inline bool arch_vmap_pmd_supported(pgprot_t prot)
++static __always_inline bool arch_vmap_pmd_supported(pgprot_t prot)
+ {
+ return radix_enabled();
+ }
+diff --git a/arch/powerpc/perf/hv-gpci.c b/arch/powerpc/perf/hv-gpci.c
+index 27f18119fda17..241551d1282f8 100644
+--- a/arch/powerpc/perf/hv-gpci.c
++++ b/arch/powerpc/perf/hv-gpci.c
+@@ -695,6 +695,20 @@ static unsigned long single_gpci_request(u32 req, u32 starting_index,
+
+ ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO,
+ virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE);
++
++ /*
++ * ret value as 'H_PARAMETER' with detail_rc as 'GEN_BUF_TOO_SMALL',
++ * specifies that the current buffer size cannot accommodate
++ * all the information and a partial buffer returned.
++ * Since in this function we are only accessing data for a given starting index,
++ * we don't need to accommodate whole data and can get required count by
++ * accessing first entry data.
++ * Hence hcall fails only incase the ret value is other than H_SUCCESS or
++ * H_PARAMETER with detail_rc value as GEN_BUF_TOO_SMALL(0x1B).
++ */
++ if (ret == H_PARAMETER && be32_to_cpu(arg->params.detail_rc) == 0x1B)
++ ret = 0;
++
+ if (ret) {
+ pr_devel("hcall failed: 0x%lx\n", ret);
+ goto out;
+@@ -759,6 +773,7 @@ static int h_gpci_event_init(struct perf_event *event)
+ {
+ u64 count;
+ u8 length;
++ unsigned long ret;
+
+ /* Not our event */
+ if (event->attr.type != event->pmu->type)
+@@ -789,13 +804,23 @@ static int h_gpci_event_init(struct perf_event *event)
+ }
+
+ /* check if the request works... */
+- if (single_gpci_request(event_get_request(event),
++ ret = single_gpci_request(event_get_request(event),
+ event_get_starting_index(event),
+ event_get_secondary_index(event),
+ event_get_counter_info_version(event),
+ event_get_offset(event),
+ length,
+- &count)) {
++ &count);
++
++ /*
++ * ret value as H_AUTHORITY implies that partition is not permitted to retrieve
++ * performance information, and required to set
++ * "Enable Performance Information Collection" option.
++ */
++ if (ret == H_AUTHORITY)
++ return -EPERM;
++
++ if (ret) {
+ pr_devel("gpci hcall failed\n");
+ return -EINVAL;
+ }
+diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c
+index bf0188dcb9184..a5001d32f978d 100644
+--- a/arch/powerpc/platforms/44x/warp.c
++++ b/arch/powerpc/platforms/44x/warp.c
+@@ -8,6 +8,7 @@
+ #include <linux/err.h>
+ #include <linux/init.h>
+ #include <linux/of_platform.h>
++#include <linux/platform_device.h>
+ #include <linux/kthread.h>
+ #include <linux/leds.h>
+ #include <linux/i2c.h>
+diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
+index 9c10aac40c7b1..e265f026eee2a 100644
+--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
++++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
+@@ -99,9 +99,6 @@ static void __init linkstation_init_IRQ(void)
+ mpic_init(mpic);
+ }
+
+-extern void avr_uart_configure(void);
+-extern void avr_uart_send(const char);
+-
+ static void __noreturn linkstation_restart(char *cmd)
+ {
+ local_irq_disable();
+diff --git a/arch/powerpc/platforms/embedded6xx/mpc10x.h b/arch/powerpc/platforms/embedded6xx/mpc10x.h
+index 5ad12023e5628..ebc258fa4858d 100644
+--- a/arch/powerpc/platforms/embedded6xx/mpc10x.h
++++ b/arch/powerpc/platforms/embedded6xx/mpc10x.h
+@@ -156,4 +156,7 @@ int mpc10x_disable_store_gathering(struct pci_controller *hose);
+ /* For MPC107 boards that use the built-in openpic */
+ void mpc10x_set_openpic(void);
+
++void avr_uart_configure(void);
++void avr_uart_send(const char c);
++
+ #endif /* __PPC_KERNEL_MPC10X_H */
+diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig
+index 8bdae0caf21e5..84f101ec53a96 100644
+--- a/arch/powerpc/platforms/powermac/Kconfig
++++ b/arch/powerpc/platforms/powermac/Kconfig
+@@ -2,7 +2,7 @@
+ config PPC_PMAC
+ bool "Apple PowerMac based machines"
+ depends on PPC_BOOK3S && CPU_BIG_ENDIAN
+- select ADB_CUDA if POWER_RESET && PPC32
++ select ADB_CUDA if POWER_RESET && ADB
+ select MPIC
+ select FORCE_PCI
+ select PPC_INDIRECT_PCI if PPC32
+diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig
+index e9c1087dd42ec..706194e5f0b46 100644
+--- a/arch/powerpc/platforms/ps3/Kconfig
++++ b/arch/powerpc/platforms/ps3/Kconfig
+@@ -67,6 +67,7 @@ config PS3_VUART
+ config PS3_PS3AV
+ depends on PPC_PS3
+ tristate "PS3 AV settings driver" if PS3_ADVANCED
++ select VIDEO
+ select PS3_VUART
+ default y
+ help
+diff --git a/arch/powerpc/platforms/pseries/papr_platform_attributes.c b/arch/powerpc/platforms/pseries/papr_platform_attributes.c
+index 526c621b098be..eea2041b270b5 100644
+--- a/arch/powerpc/platforms/pseries/papr_platform_attributes.c
++++ b/arch/powerpc/platforms/pseries/papr_platform_attributes.c
+@@ -101,10 +101,12 @@ static int papr_get_attr(u64 id, struct energy_scale_attribute *esi)
+ esi_buf_size = ESI_HDR_SIZE + (CURR_MAX_ESI_ATTRS * max_esi_attrs);
+
+ temp_buf = krealloc(buf, esi_buf_size, GFP_KERNEL);
+- if (temp_buf)
++ if (temp_buf) {
+ buf = temp_buf;
+- else
+- return -ENOMEM;
++ } else {
++ ret = -ENOMEM;
++ goto out_buf;
++ }
+
+ goto retry;
+ }
+diff --git a/arch/riscv/boot/dts/starfive/jh7100.dtsi b/arch/riscv/boot/dts/starfive/jh7100.dtsi
+index 8bcf36d07f3f7..5d499d8aa8044 100644
+--- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
++++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
+@@ -116,6 +116,7 @@ cpu-crit {
+ osc_sys: osc-sys {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
++ clock-output-names = "osc_sys";
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+@@ -123,6 +124,7 @@ osc_sys: osc-sys {
+ osc_aud: osc-aud {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
++ clock-output-names = "osc_aud";
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+@@ -130,6 +132,7 @@ osc_aud: osc-aud {
+ gmac_rmii_ref: gmac-rmii-ref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
++ clock-output-names = "gmac_rmii_ref";
+ /* Should be overridden by the board when needed */
+ clock-frequency = <0>;
+ };
+@@ -137,6 +140,7 @@ gmac_rmii_ref: gmac-rmii-ref {
+ gmac_gr_mii_rxclk: gmac-gr-mii-rxclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
++ clock-output-names = "gmac_gr_mii_rxclk";
+ /* Should be overridden by the board when needed */
+ clock-frequency = <0>;
+ };
+diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
+index 6066822e7396f..3422ced8a07fd 100644
+--- a/arch/riscv/include/asm/pgtable.h
++++ b/arch/riscv/include/asm/pgtable.h
+@@ -439,9 +439,11 @@ static inline pte_t pte_mkhuge(pte_t pte)
+ return pte;
+ }
+
++#ifdef CONFIG_RISCV_ISA_SVNAPOT
+ #define pte_leaf_size(pte) (pte_napot(pte) ? \
+ napot_cont_size(napot_cont_order(pte)) :\
+ PAGE_SIZE)
++#endif
+
+ #ifdef CONFIG_NUMA_BALANCING
+ /*
+diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
+index 8ded225e8c5b1..c2ed4e689bf96 100644
+--- a/arch/riscv/kernel/traps_misaligned.c
++++ b/arch/riscv/kernel/traps_misaligned.c
+@@ -632,7 +632,7 @@ void unaligned_emulation_finish(void)
+ * accesses emulated since tasks requesting such control can run on any
+ * CPU.
+ */
+- for_each_present_cpu(cpu) {
++ for_each_online_cpu(cpu) {
+ if (per_cpu(misaligned_access_speed, cpu) !=
+ RISCV_HWPROBE_MISALIGNED_EMULATED) {
+ return;
+diff --git a/arch/riscv/kvm/vcpu_insn.c b/arch/riscv/kvm/vcpu_insn.c
+index 7a6abed41bc17..ee7215f4071f5 100644
+--- a/arch/riscv/kvm/vcpu_insn.c
++++ b/arch/riscv/kvm/vcpu_insn.c
+@@ -7,6 +7,8 @@
+ #include <linux/bitops.h>
+ #include <linux/kvm_host.h>
+
++#include <asm/cpufeature.h>
++
+ #define INSN_OPCODE_MASK 0x007c
+ #define INSN_OPCODE_SHIFT 2
+ #define INSN_OPCODE_SYSTEM 28
+@@ -213,9 +215,20 @@ struct csr_func {
+ unsigned long wr_mask);
+ };
+
++static int seed_csr_rmw(struct kvm_vcpu *vcpu, unsigned int csr_num,
++ unsigned long *val, unsigned long new_val,
++ unsigned long wr_mask)
++{
++ if (!riscv_isa_extension_available(vcpu->arch.isa, ZKR))
++ return KVM_INSN_ILLEGAL_TRAP;
++
++ return KVM_INSN_EXIT_TO_USER_SPACE;
++}
++
+ static const struct csr_func csr_funcs[] = {
+ KVM_RISCV_VCPU_AIA_CSR_FUNCS
+ KVM_RISCV_VCPU_HPMCOUNTER_CSR_FUNCS
++ { .base = CSR_SEED, .count = 1, .func = seed_csr_rmw },
+ };
+
+ /**
+diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c
+index 56254fa06f990..4f26690302209 100644
+--- a/arch/s390/kernel/cache.c
++++ b/arch/s390/kernel/cache.c
+@@ -166,5 +166,6 @@ int populate_cache_leaves(unsigned int cpu)
+ ci_leaf_init(this_leaf++, pvt, ctype, level, cpu);
+ }
+ }
++ this_cpu_ci->cpu_map_populated = true;
+ return 0;
+ }
+diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c
+index bf8a672b15a41..522a5ea0a9f49 100644
+--- a/arch/s390/kernel/perf_pai_crypto.c
++++ b/arch/s390/kernel/perf_pai_crypto.c
+@@ -721,7 +721,7 @@ static int __init attr_event_init(void)
+ for (i = 0; i < ARRAY_SIZE(paicrypt_ctrnames); i++) {
+ ret = attr_event_init_one(attrs, i);
+ if (ret) {
+- attr_event_free(attrs, i - 1);
++ attr_event_free(attrs, i);
+ return ret;
+ }
+ }
+diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c
+index af7f2b538c8fd..95d1a890640a3 100644
+--- a/arch/s390/kernel/perf_pai_ext.c
++++ b/arch/s390/kernel/perf_pai_ext.c
+@@ -611,7 +611,7 @@ static int __init attr_event_init(void)
+ for (i = 0; i < ARRAY_SIZE(paiext_ctrnames); i++) {
+ ret = attr_event_init_one(attrs, i);
+ if (ret) {
+- attr_event_free(attrs, i - 1);
++ attr_event_free(attrs, i);
+ return ret;
+ }
+ }
+diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile
+index caec7db6f9668..b12a274cbb473 100644
+--- a/arch/s390/kernel/vdso32/Makefile
++++ b/arch/s390/kernel/vdso32/Makefile
+@@ -22,7 +22,7 @@ KBUILD_CFLAGS_32 := $(filter-out -m64,$(KBUILD_CFLAGS))
+ KBUILD_CFLAGS_32 := $(filter-out -mno-pic-data-is-text-relative,$(KBUILD_CFLAGS_32))
+ KBUILD_CFLAGS_32 += -m31 -fPIC -shared -fno-common -fno-builtin
+
+-LDFLAGS_vdso32.so.dbg += -fPIC -shared -soname=linux-vdso32.so.1 \
++LDFLAGS_vdso32.so.dbg += -shared -soname=linux-vdso32.so.1 \
+ --hash-style=both --build-id=sha1 -melf_s390 -T
+
+ $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_32)
+diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile
+index e3c9085f8fa72..caa4ebff8a193 100644
+--- a/arch/s390/kernel/vdso64/Makefile
++++ b/arch/s390/kernel/vdso64/Makefile
+@@ -26,7 +26,7 @@ KBUILD_AFLAGS_64 += -m64
+ KBUILD_CFLAGS_64 := $(filter-out -m64,$(KBUILD_CFLAGS))
+ KBUILD_CFLAGS_64 := $(filter-out -mno-pic-data-is-text-relative,$(KBUILD_CFLAGS_64))
+ KBUILD_CFLAGS_64 += -m64 -fPIC -fno-common -fno-builtin
+-ldflags-y := -fPIC -shared -soname=linux-vdso64.so.1 \
++ldflags-y := -shared -soname=linux-vdso64.so.1 \
+ --hash-style=both --build-id=sha1 -T
+
+ $(targets:%=$(obj)/%.dbg): KBUILD_CFLAGS = $(KBUILD_CFLAGS_64)
+diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
+index e0a88dcaf5cb7..24a18e5ef6e8e 100644
+--- a/arch/s390/kernel/vtime.c
++++ b/arch/s390/kernel/vtime.c
+@@ -210,13 +210,13 @@ void vtime_flush(struct task_struct *tsk)
+ virt_timer_expire();
+
+ steal = S390_lowcore.steal_timer;
+- avg_steal = S390_lowcore.avg_steal_timer / 2;
++ avg_steal = S390_lowcore.avg_steal_timer;
+ if ((s64) steal > 0) {
+ S390_lowcore.steal_timer = 0;
+ account_steal_time(cputime_to_nsecs(steal));
+ avg_steal += steal;
+ }
+- S390_lowcore.avg_steal_timer = avg_steal;
++ S390_lowcore.avg_steal_timer = avg_steal / 2;
+ }
+
+ static u64 vtime_delta(void)
+diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
+index 204c43cb3d435..37a1cfecd9c73 100644
+--- a/arch/sparc/Kconfig
++++ b/arch/sparc/Kconfig
+@@ -57,6 +57,8 @@ config SPARC32
+ select CLZ_TAB
+ select DMA_DIRECT_REMAP
+ select GENERIC_ATOMIC64
++ select GENERIC_LIB_CMPDI2
++ select GENERIC_LIB_UCMPDI2
+ select HAVE_UID16
+ select LOCK_MM_AND_FIND_VMA
+ select OLD_SIGACTION
+@@ -140,10 +142,6 @@ config HIGHMEM
+ default y if SPARC32
+ select KMAP_LOCAL
+
+-config GENERIC_ISA_DMA
+- bool
+- default y if SPARC32
+-
+ config PGTABLE_LEVELS
+ default 4 if 64BIT
+ default 3
+diff --git a/arch/sparc/kernel/leon_pci_grpci1.c b/arch/sparc/kernel/leon_pci_grpci1.c
+index 8700a0e3b0df7..b2b639bee0684 100644
+--- a/arch/sparc/kernel/leon_pci_grpci1.c
++++ b/arch/sparc/kernel/leon_pci_grpci1.c
+@@ -697,7 +697,7 @@ static int grpci1_of_probe(struct platform_device *ofdev)
+ return err;
+ }
+
+-static const struct of_device_id grpci1_of_match[] __initconst = {
++static const struct of_device_id grpci1_of_match[] = {
+ {
+ .name = "GAISLER_PCIFBRG",
+ },
+diff --git a/arch/sparc/kernel/leon_pci_grpci2.c b/arch/sparc/kernel/leon_pci_grpci2.c
+index 60b6bdf7761fb..ac2acd62a24ec 100644
+--- a/arch/sparc/kernel/leon_pci_grpci2.c
++++ b/arch/sparc/kernel/leon_pci_grpci2.c
+@@ -889,7 +889,7 @@ static int grpci2_of_probe(struct platform_device *ofdev)
+ return err;
+ }
+
+-static const struct of_device_id grpci2_of_match[] __initconst = {
++static const struct of_device_id grpci2_of_match[] = {
+ {
+ .name = "GAISLER_GRPCI2",
+ },
+diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile
+index 59669ebddd4e1..ee5091dd67ed7 100644
+--- a/arch/sparc/lib/Makefile
++++ b/arch/sparc/lib/Makefile
+@@ -14,7 +14,7 @@ lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o
+ lib-$(CONFIG_SPARC32) += copy_user.o locks.o
+ lib-$(CONFIG_SPARC64) += atomic_64.o
+ lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o
+-lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o
++lib-$(CONFIG_SPARC32) += muldi3.o bitext.o
+ lib-$(CONFIG_SPARC64) += multi3.o
+ lib-$(CONFIG_SPARC64) += fls.o
+ lib-$(CONFIG_SPARC64) += fls64.o
+@@ -51,5 +51,5 @@ lib-$(CONFIG_SPARC64) += copy_in_user.o memmove.o
+ lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o
+
+ obj-$(CONFIG_SPARC64) += iomap.o
+-obj-$(CONFIG_SPARC32) += atomic32.o ucmpdi2.o
++obj-$(CONFIG_SPARC32) += atomic32.o
+ obj-$(CONFIG_SPARC64) += PeeCeeI.o
+diff --git a/arch/sparc/lib/cmpdi2.c b/arch/sparc/lib/cmpdi2.c
+deleted file mode 100644
+index 333367fe73533..0000000000000
+--- a/arch/sparc/lib/cmpdi2.c
++++ /dev/null
+@@ -1,28 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-#include <linux/module.h>
+-
+-#include "libgcc.h"
+-
+-word_type __cmpdi2(long long a, long long b)
+-{
+- const DWunion au = {
+- .ll = a
+- };
+- const DWunion bu = {
+- .ll = b
+- };
+-
+- if (au.s.high < bu.s.high)
+- return 0;
+- else if (au.s.high > bu.s.high)
+- return 2;
+-
+- if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
+- return 0;
+- else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
+- return 2;
+-
+- return 1;
+-}
+-
+-EXPORT_SYMBOL(__cmpdi2);
+diff --git a/arch/sparc/lib/ucmpdi2.c b/arch/sparc/lib/ucmpdi2.c
+deleted file mode 100644
+index 82c1cccb12644..0000000000000
+--- a/arch/sparc/lib/ucmpdi2.c
++++ /dev/null
+@@ -1,20 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0
+-#include <linux/module.h>
+-#include "libgcc.h"
+-
+-word_type __ucmpdi2(unsigned long long a, unsigned long long b)
+-{
+- const DWunion au = {.ll = a};
+- const DWunion bu = {.ll = b};
+-
+- if ((unsigned int) au.s.high < (unsigned int) bu.s.high)
+- return 0;
+- else if ((unsigned int) au.s.high > (unsigned int) bu.s.high)
+- return 2;
+- if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
+- return 0;
+- else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
+- return 2;
+- return 1;
+-}
+-EXPORT_SYMBOL(__ucmpdi2);
+diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
+index 81f6d8275b6bf..1f114d4bfe303 100644
+--- a/arch/x86/events/amd/core.c
++++ b/arch/x86/events/amd/core.c
+@@ -604,7 +604,6 @@ static void amd_pmu_cpu_dead(int cpu)
+
+ kfree(cpuhw->lbr_sel);
+ cpuhw->lbr_sel = NULL;
+- amd_pmu_cpu_reset(cpu);
+
+ if (!x86_pmu.amd_nb_constraints)
+ return;
+diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c
+index cf1b78cb2d043..c8062975a5316 100644
+--- a/arch/x86/hyperv/hv_vtl.c
++++ b/arch/x86/hyperv/hv_vtl.c
+@@ -12,6 +12,7 @@
+ #include <asm/i8259.h>
+ #include <asm/mshyperv.h>
+ #include <asm/realmode.h>
++#include <../kernel/smpboot.h>
+
+ extern struct boot_params boot_params;
+ static struct real_mode_header hv_vtl_real_mode_header;
+@@ -64,7 +65,7 @@ static void hv_vtl_ap_entry(void)
+ ((secondary_startup_64_fn)secondary_startup_64)(&boot_params, &boot_params);
+ }
+
+-static int hv_vtl_bringup_vcpu(u32 target_vp_index, u64 eip_ignored)
++static int hv_vtl_bringup_vcpu(u32 target_vp_index, int cpu, u64 eip_ignored)
+ {
+ u64 status;
+ int ret = 0;
+@@ -78,7 +79,9 @@ static int hv_vtl_bringup_vcpu(u32 target_vp_index, u64 eip_ignored)
+ struct ldttss_desc *ldt;
+ struct desc_struct *gdt;
+
+- u64 rsp = current->thread.sp;
++ struct task_struct *idle = idle_thread_get(cpu);
++ u64 rsp = (unsigned long)idle->thread.sp;
++
+ u64 rip = (u64)&hv_vtl_ap_entry;
+
+ native_store_gdt(&gdt_ptr);
+@@ -205,7 +208,15 @@ static int hv_vtl_apicid_to_vp_id(u32 apic_id)
+
+ static int hv_vtl_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip)
+ {
+- int vp_id;
++ int vp_id, cpu;
++
++ /* Find the logical CPU for the APIC ID */
++ for_each_present_cpu(cpu) {
++ if (arch_match_cpu_phys_id(cpu, apicid))
++ break;
++ }
++ if (cpu >= nr_cpu_ids)
++ return -EINVAL;
+
+ pr_debug("Bringing up CPU with APIC ID %d in VTL2...\n", apicid);
+ vp_id = hv_vtl_apicid_to_vp_id(apicid);
+@@ -219,7 +230,7 @@ static int hv_vtl_wakeup_secondary_cpu(u32 apicid, unsigned long start_eip)
+ return -EINVAL;
+ }
+
+- return hv_vtl_bringup_vcpu(vp_id, start_eip);
++ return hv_vtl_bringup_vcpu(vp_id, cpu, start_eip);
+ }
+
+ int __init hv_vtl_early_init(void)
+diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
+index 3814a9263d64e..294cd2a408181 100644
+--- a/arch/x86/include/asm/io.h
++++ b/arch/x86/include/asm/io.h
+@@ -379,7 +379,7 @@ static inline void iosubmit_cmds512(void __iomem *dst, const void *src,
+ const u8 *end = from + count * 64;
+
+ while (from < end) {
+- movdir64b(dst, from);
++ movdir64b_io(dst, from);
+ from += 64;
+ }
+ }
+diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
+index d18e5c332cb9f..1b93ff80b43bc 100644
+--- a/arch/x86/include/asm/page.h
++++ b/arch/x86/include/asm/page.h
+@@ -66,10 +66,14 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
+ * virt_addr_valid(kaddr) returns true.
+ */
+ #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+-#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
+ extern bool __virt_addr_valid(unsigned long kaddr);
+ #define virt_addr_valid(kaddr) __virt_addr_valid((unsigned long) (kaddr))
+
++static __always_inline void *pfn_to_kaddr(unsigned long pfn)
++{
++ return __va(pfn << PAGE_SHIFT);
++}
++
+ static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits)
+ {
+ return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
+diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h
+index 48f8dd47cf688..09a5461d72439 100644
+--- a/arch/x86/include/asm/special_insns.h
++++ b/arch/x86/include/asm/special_insns.h
+@@ -224,10 +224,10 @@ static inline void serialize(void)
+ }
+
+ /* The dst parameter must be 64-bytes aligned */
+-static inline void movdir64b(void __iomem *dst, const void *src)
++static inline void movdir64b(void *dst, const void *src)
+ {
+ const struct { char _[64]; } *__src = src;
+- struct { char _[64]; } __iomem *__dst = dst;
++ struct { char _[64]; } *__dst = dst;
+
+ /*
+ * MOVDIR64B %(rdx), rax.
+@@ -245,6 +245,11 @@ static inline void movdir64b(void __iomem *dst, const void *src)
+ : "m" (*__src), "a" (__dst), "d" (__src));
+ }
+
++static inline void movdir64b_io(void __iomem *dst, const void *src)
++{
++ movdir64b((void __force *)dst, src);
++}
++
+ /**
+ * enqcmds - Enqueue a command in supervisor (CPL0) mode
+ * @dst: destination, in MMIO space (must be 512-bit aligned)
+diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c
+index 8d8752b44f113..ff8f25faca3dd 100644
+--- a/arch/x86/kernel/acpi/cppc.c
++++ b/arch/x86/kernel/acpi/cppc.c
+@@ -20,7 +20,7 @@ bool cpc_supported_by_cpu(void)
+ (boot_cpu_data.x86_model >= 0x20 && boot_cpu_data.x86_model <= 0x2f)))
+ return true;
+ else if (boot_cpu_data.x86 == 0x17 &&
+- boot_cpu_data.x86_model >= 0x70 && boot_cpu_data.x86_model <= 0x7f)
++ boot_cpu_data.x86_model >= 0x30 && boot_cpu_data.x86_model <= 0x7f)
+ return true;
+ return boot_cpu_has(X86_FEATURE_CPPC);
+ }
+diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
+index 19e0681f04356..d04371e851b4c 100644
+--- a/arch/x86/kernel/cpu/resctrl/core.c
++++ b/arch/x86/kernel/cpu/resctrl/core.c
+@@ -231,9 +231,7 @@ static bool __get_mem_config_intel(struct rdt_resource *r)
+ static bool __rdt_get_mem_config_amd(struct rdt_resource *r)
+ {
+ struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
+- union cpuid_0x10_3_eax eax;
+- union cpuid_0x10_x_edx edx;
+- u32 ebx, ecx, subleaf;
++ u32 eax, ebx, ecx, edx, subleaf;
+
+ /*
+ * Query CPUID_Fn80000020_EDX_x01 for MBA and
+@@ -241,9 +239,9 @@ static bool __rdt_get_mem_config_amd(struct rdt_resource *r)
+ */
+ subleaf = (r->rid == RDT_RESOURCE_SMBA) ? 2 : 1;
+
+- cpuid_count(0x80000020, subleaf, &eax.full, &ebx, &ecx, &edx.full);
+- hw_res->num_closid = edx.split.cos_max + 1;
+- r->default_ctrl = MAX_MBA_BW_AMD;
++ cpuid_count(0x80000020, subleaf, &eax, &ebx, &ecx, &edx);
++ hw_res->num_closid = edx + 1;
++ r->default_ctrl = 1 << eax;
+
+ /* AMD does not use delay */
+ r->membw.delay_linear = false;
+diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
+index a4f1aa15f0a2a..52e7e7deee106 100644
+--- a/arch/x86/kernel/cpu/resctrl/internal.h
++++ b/arch/x86/kernel/cpu/resctrl/internal.h
+@@ -18,7 +18,6 @@
+ #define MBM_OVERFLOW_INTERVAL 1000
+ #define MAX_MBA_BW 100u
+ #define MBA_IS_LINEAR 0x4
+-#define MAX_MBA_BW_AMD 0x800
+ #define MBM_CNTR_WIDTH_OFFSET_AMD 20
+
+ #define RMID_VAL_ERROR BIT_ULL(63)
+@@ -296,14 +295,10 @@ struct rftype {
+ * struct mbm_state - status for each MBM counter in each domain
+ * @prev_bw_bytes: Previous bytes value read for bandwidth calculation
+ * @prev_bw: The most recent bandwidth in MBps
+- * @delta_bw: Difference between the current and previous bandwidth
+- * @delta_comp: Indicates whether to compute the delta_bw
+ */
+ struct mbm_state {
+ u64 prev_bw_bytes;
+ u32 prev_bw;
+- u32 delta_bw;
+- bool delta_comp;
+ };
+
+ /**
+@@ -395,6 +390,8 @@ struct rdt_parse_data {
+ * @msr_update: Function pointer to update QOS MSRs
+ * @mon_scale: cqm counter * mon_scale = occupancy in bytes
+ * @mbm_width: Monitor width, to detect and correct for overflow.
++ * @mbm_cfg_mask: Bandwidth sources that can be tracked when Bandwidth
++ * Monitoring Event Configuration (BMEC) is supported.
+ * @cdp_enabled: CDP state of this resource
+ *
+ * Members of this structure are either private to the architecture
+@@ -409,6 +406,7 @@ struct rdt_hw_resource {
+ struct rdt_resource *r);
+ unsigned int mon_scale;
+ unsigned int mbm_width;
++ unsigned int mbm_cfg_mask;
+ bool cdp_enabled;
+ };
+
+diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
+index f136ac046851c..3a6c069614eb8 100644
+--- a/arch/x86/kernel/cpu/resctrl/monitor.c
++++ b/arch/x86/kernel/cpu/resctrl/monitor.c
+@@ -440,9 +440,6 @@ static void mbm_bw_count(u32 rmid, struct rmid_read *rr)
+
+ cur_bw = bytes / SZ_1M;
+
+- if (m->delta_comp)
+- m->delta_bw = abs(cur_bw - m->prev_bw);
+- m->delta_comp = false;
+ m->prev_bw = cur_bw;
+ }
+
+@@ -520,11 +517,11 @@ static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm)
+ {
+ u32 closid, rmid, cur_msr_val, new_msr_val;
+ struct mbm_state *pmbm_data, *cmbm_data;
+- u32 cur_bw, delta_bw, user_bw;
+ struct rdt_resource *r_mba;
+ struct rdt_domain *dom_mba;
+ struct list_head *head;
+ struct rdtgroup *entry;
++ u32 cur_bw, user_bw;
+
+ if (!is_mbm_local_enabled())
+ return;
+@@ -543,7 +540,6 @@ static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm)
+
+ cur_bw = pmbm_data->prev_bw;
+ user_bw = dom_mba->mbps_val[closid];
+- delta_bw = pmbm_data->delta_bw;
+
+ /* MBA resource doesn't support CDP */
+ cur_msr_val = resctrl_arch_get_config(r_mba, dom_mba, closid, CDP_NONE);
+@@ -555,49 +551,31 @@ static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm)
+ list_for_each_entry(entry, head, mon.crdtgrp_list) {
+ cmbm_data = &dom_mbm->mbm_local[entry->mon.rmid];
+ cur_bw += cmbm_data->prev_bw;
+- delta_bw += cmbm_data->delta_bw;
+ }
+
+ /*
+ * Scale up/down the bandwidth linearly for the ctrl group. The
+ * bandwidth step is the bandwidth granularity specified by the
+ * hardware.
+- *
+- * The delta_bw is used when increasing the bandwidth so that we
+- * dont alternately increase and decrease the control values
+- * continuously.
+- *
+- * For ex: consider cur_bw = 90MBps, user_bw = 100MBps and if
+- * bandwidth step is 20MBps(> user_bw - cur_bw), we would keep
+- * switching between 90 and 110 continuously if we only check
+- * cur_bw < user_bw.
++ * Always increase throttling if current bandwidth is above the
++ * target set by user.
++ * But avoid thrashing up and down on every poll by checking
++ * whether a decrease in throttling is likely to push the group
++ * back over target. E.g. if currently throttling to 30% of bandwidth
++ * on a system with 10% granularity steps, check whether moving to
++ * 40% would go past the limit by multiplying current bandwidth by
++ * "(30 + 10) / 30".
+ */
+ if (cur_msr_val > r_mba->membw.min_bw && user_bw < cur_bw) {
+ new_msr_val = cur_msr_val - r_mba->membw.bw_gran;
+ } else if (cur_msr_val < MAX_MBA_BW &&
+- (user_bw > (cur_bw + delta_bw))) {
++ (user_bw > (cur_bw * (cur_msr_val + r_mba->membw.min_bw) / cur_msr_val))) {
+ new_msr_val = cur_msr_val + r_mba->membw.bw_gran;
+ } else {
+ return;
+ }
+
+ resctrl_arch_update_one(r_mba, dom_mba, closid, CDP_NONE, new_msr_val);
+-
+- /*
+- * Delta values are updated dynamically package wise for each
+- * rdtgrp every time the throttle MSR changes value.
+- *
+- * This is because (1)the increase in bandwidth is not perfectly
+- * linear and only "approximately" linear even when the hardware
+- * says it is linear.(2)Also since MBA is a core specific
+- * mechanism, the delta values vary based on number of cores used
+- * by the rdtgrp.
+- */
+- pmbm_data->delta_comp = true;
+- list_for_each_entry(entry, head, mon.crdtgrp_list) {
+- cmbm_data = &dom_mbm->mbm_local[entry->mon.rmid];
+- cmbm_data->delta_comp = true;
+- }
+ }
+
+ static void mbm_update(struct rdt_resource *r, struct rdt_domain *d, int rmid)
+@@ -813,6 +791,12 @@ int __init rdt_get_mon_l3_config(struct rdt_resource *r)
+ return ret;
+
+ if (rdt_cpu_has(X86_FEATURE_BMEC)) {
++ u32 eax, ebx, ecx, edx;
++
++ /* Detect list of bandwidth sources that can be tracked */
++ cpuid_count(0x80000020, 3, &eax, &ebx, &ecx, &edx);
++ hw_res->mbm_cfg_mask = ecx & MAX_EVT_CONFIG_BITS;
++
+ if (rdt_cpu_has(X86_FEATURE_CQM_MBM_TOTAL)) {
+ mbm_total_event.configurable = true;
+ mbm_config_rftype_init("mbm_total_bytes_config");
+diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+index 69a1de92384ab..2b69e560b05f1 100644
+--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
++++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+@@ -1620,12 +1620,6 @@ static int mbm_config_write_domain(struct rdt_resource *r,
+ struct mon_config_info mon_info = {0};
+ int ret = 0;
+
+- /* mon_config cannot be more than the supported set of events */
+- if (val > MAX_EVT_CONFIG_BITS) {
+- rdt_last_cmd_puts("Invalid event configuration\n");
+- return -EINVAL;
+- }
+-
+ /*
+ * Read the current config value first. If both are the same then
+ * no need to write it again.
+@@ -1663,6 +1657,7 @@ static int mbm_config_write_domain(struct rdt_resource *r,
+
+ static int mon_config_write(struct rdt_resource *r, char *tok, u32 evtid)
+ {
++ struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r);
+ char *dom_str = NULL, *id_str;
+ unsigned long dom_id, val;
+ struct rdt_domain *d;
+@@ -1686,6 +1681,13 @@ static int mon_config_write(struct rdt_resource *r, char *tok, u32 evtid)
+ return -EINVAL;
+ }
+
++ /* Value from user cannot be more than the supported set of events */
++ if ((val & hw_res->mbm_cfg_mask) != val) {
++ rdt_last_cmd_printf("Invalid event configuration: max valid mask is 0x%02x\n",
++ hw_res->mbm_cfg_mask);
++ return -EINVAL;
++ }
++
+ list_for_each_entry(d, &r->domains, list) {
+ if (d->id == dom_id) {
+ ret = mbm_config_write_domain(r, d, evtid, val);
+diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c
+index d73aeb16417fc..7f72472a34d6d 100644
+--- a/arch/x86/mm/mem_encrypt_identity.c
++++ b/arch/x86/mm/mem_encrypt_identity.c
+@@ -507,7 +507,6 @@ void __init sme_enable(struct boot_params *bp)
+ const char *cmdline_ptr, *cmdline_arg, *cmdline_on, *cmdline_off;
+ unsigned int eax, ebx, ecx, edx;
+ unsigned long feature_mask;
+- bool active_by_default;
+ unsigned long me_mask;
+ char buffer[16];
+ bool snp;
+@@ -593,22 +592,19 @@ void __init sme_enable(struct boot_params *bp)
+ : "p" (sme_cmdline_off));
+
+ if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT))
+- active_by_default = true;
+- else
+- active_by_default = false;
++ sme_me_mask = me_mask;
+
+ cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr |
+ ((u64)bp->ext_cmd_line_ptr << 32));
+
+ if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0)
+- return;
++ goto out;
+
+ if (!strncmp(buffer, cmdline_on, sizeof(buffer)))
+ sme_me_mask = me_mask;
+ else if (!strncmp(buffer, cmdline_off, sizeof(buffer)))
+ sme_me_mask = 0;
+- else
+- sme_me_mask = active_by_default ? me_mask : 0;
++
+ out:
+ if (sme_me_mask) {
+ physical_mask &= ~sme_me_mask;
+diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
+index a3bae2b24626b..b029fb81ebeee 100644
+--- a/arch/x86/tools/relocs.c
++++ b/arch/x86/tools/relocs.c
+@@ -653,6 +653,14 @@ static void print_absolute_relocs(void)
+ if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
+ continue;
+ }
++ /*
++ * Do not perform relocations in .notes section; any
++ * values there are meant for pre-boot consumption (e.g.
++ * startup_xen).
++ */
++ if (sec_applies->shdr.sh_type == SHT_NOTE) {
++ continue;
++ }
+ sh_symtab = sec_symtab->symtab;
+ sym_strtab = sec_symtab->link->strtab;
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
+diff --git a/block/holder.c b/block/holder.c
+index 37d18c13d9581..791091a7eac23 100644
+--- a/block/holder.c
++++ b/block/holder.c
+@@ -8,6 +8,8 @@ struct bd_holder_disk {
+ int refcnt;
+ };
+
++static DEFINE_MUTEX(blk_holder_mutex);
++
+ static struct bd_holder_disk *bd_find_holder_disk(struct block_device *bdev,
+ struct gendisk *disk)
+ {
+@@ -80,7 +82,7 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
+ kobject_get(bdev->bd_holder_dir);
+ mutex_unlock(&bdev->bd_disk->open_mutex);
+
+- mutex_lock(&disk->open_mutex);
++ mutex_lock(&blk_holder_mutex);
+ WARN_ON_ONCE(!bdev->bd_holder);
+
+ holder = bd_find_holder_disk(bdev, disk);
+@@ -108,7 +110,7 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
+ goto out_del_symlink;
+ list_add(&holder->list, &disk->slave_bdevs);
+
+- mutex_unlock(&disk->open_mutex);
++ mutex_unlock(&blk_holder_mutex);
+ return 0;
+
+ out_del_symlink:
+@@ -116,7 +118,7 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
+ out_free_holder:
+ kfree(holder);
+ out_unlock:
+- mutex_unlock(&disk->open_mutex);
++ mutex_unlock(&blk_holder_mutex);
+ if (ret)
+ kobject_put(bdev->bd_holder_dir);
+ return ret;
+@@ -140,7 +142,7 @@ void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk)
+ if (WARN_ON_ONCE(!disk->slave_dir))
+ return;
+
+- mutex_lock(&disk->open_mutex);
++ mutex_lock(&blk_holder_mutex);
+ holder = bd_find_holder_disk(bdev, disk);
+ if (!WARN_ON_ONCE(holder == NULL) && !--holder->refcnt) {
+ del_symlink(disk->slave_dir, bdev_kobj(bdev));
+@@ -149,6 +151,6 @@ void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk)
+ list_del_init(&holder->list);
+ kfree(holder);
+ }
+- mutex_unlock(&disk->open_mutex);
++ mutex_unlock(&blk_holder_mutex);
+ }
+ EXPORT_SYMBOL_GPL(bd_unlink_disk_holder);
+diff --git a/crypto/Kconfig b/crypto/Kconfig
+index 7d156c75f15f2..44661c2e30ca5 100644
+--- a/crypto/Kconfig
++++ b/crypto/Kconfig
+@@ -1269,10 +1269,11 @@ config CRYPTO_JITTERENTROPY
+
+ A non-physical non-deterministic ("true") RNG (e.g., an entropy source
+ compliant with NIST SP800-90B) intended to provide a seed to a
+- deterministic RNG (e.g. per NIST SP800-90C).
++ deterministic RNG (e.g., per NIST SP800-90C).
+ This RNG does not perform any cryptographic whitening of the generated
++ random numbers.
+
+- See https://www.chronox.de/jent.html
++ See https://www.chronox.de/jent/
+
+ if CRYPTO_JITTERENTROPY
+ if CRYPTO_FIPS && EXPERT
+diff --git a/drivers/acpi/numa/hmat.c b/drivers/acpi/numa/hmat.c
+index d6b85f0f6082f..a26e7793ec4ef 100644
+--- a/drivers/acpi/numa/hmat.c
++++ b/drivers/acpi/numa/hmat.c
+@@ -770,12 +770,12 @@ static void __hmat_register_target_initiators(struct memory_target *target,
+ }
+ }
+
+-static void hmat_register_generic_target_initiators(struct memory_target *target)
++static void hmat_update_generic_target(struct memory_target *target)
+ {
+ static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
+
+- __hmat_register_target_initiators(target, p_nodes,
+- NODE_ACCESS_CLASS_GENPORT_SINK);
++ hmat_update_target_attrs(target, p_nodes,
++ NODE_ACCESS_CLASS_GENPORT_SINK);
+ }
+
+ static void hmat_register_target_initiators(struct memory_target *target)
+@@ -835,7 +835,7 @@ static void hmat_register_target(struct memory_target *target)
+ */
+ mutex_lock(&target_lock);
+ if (*(u16 *)target->gen_port_device_handle) {
+- hmat_register_generic_target_initiators(target);
++ hmat_update_generic_target(target);
+ target->registered = true;
+ }
+ mutex_unlock(&target_lock);
+diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
+index 55437f5e0c3ae..bd6a7857ce058 100644
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -1430,6 +1430,8 @@ int acpi_processor_power_exit(struct acpi_processor *pr)
+ acpi_processor_registered--;
+ if (acpi_processor_registered == 0)
+ cpuidle_unregister_driver(&acpi_idle_driver);
++
++ kfree(dev);
+ }
+
+ pr->flags.power_setup_done = 0;
+diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
+index dacad1d846c0d..c843feb02e980 100644
+--- a/drivers/acpi/resource.c
++++ b/drivers/acpi/resource.c
+@@ -588,6 +588,27 @@ static const struct dmi_system_id irq1_edge_low_force_override[] = {
+ DMI_MATCH(DMI_BOARD_NAME, "GM5RGEE0016COM"),
+ },
+ },
++ {
++ /* Lunnen Ground 15 / AMD Ryzen 5 5500U */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Lunnen"),
++ DMI_MATCH(DMI_BOARD_NAME, "LLL5DAW"),
++ },
++ },
++ {
++ /* Lunnen Ground 16 / AMD Ryzen 7 5800U */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Lunnen"),
++ DMI_MATCH(DMI_BOARD_NAME, "LL6FA"),
++ },
++ },
++ {
++ /* MAIBENBEN X577 */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "MAIBENBEN"),
++ DMI_MATCH(DMI_BOARD_NAME, "X577"),
++ },
++ },
+ { }
+ };
+
+diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
+index e6ed1ba91e5c9..617f3e0e963d5 100644
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -314,18 +314,14 @@ static int acpi_scan_device_check(struct acpi_device *adev)
+ * again).
+ */
+ if (adev->handler) {
+- dev_warn(&adev->dev, "Already enumerated\n");
+- return -EALREADY;
++ dev_dbg(&adev->dev, "Already enumerated\n");
++ return 0;
+ }
+ error = acpi_bus_scan(adev->handle);
+ if (error) {
+ dev_warn(&adev->dev, "Namespace scan failure\n");
+ return error;
+ }
+- if (!adev->handler) {
+- dev_warn(&adev->dev, "Enumeration failure\n");
+- error = -ENODEV;
+- }
+ } else {
+ error = acpi_scan_device_not_enumerated(adev);
+ }
+diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
+index d7317425be510..cc9077b588d7e 100644
+--- a/drivers/block/aoe/aoecmd.c
++++ b/drivers/block/aoe/aoecmd.c
+@@ -419,13 +419,16 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff_head *qu
+ rcu_read_lock();
+ for_each_netdev_rcu(&init_net, ifp) {
+ dev_hold(ifp);
+- if (!is_aoe_netif(ifp))
+- goto cont;
++ if (!is_aoe_netif(ifp)) {
++ dev_put(ifp);
++ continue;
++ }
+
+ skb = new_skb(sizeof *h + sizeof *ch);
+ if (skb == NULL) {
+ printk(KERN_INFO "aoe: skb alloc failure\n");
+- goto cont;
++ dev_put(ifp);
++ continue;
+ }
+ skb_put(skb, sizeof *h + sizeof *ch);
+ skb->dev = ifp;
+@@ -440,9 +443,6 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff_head *qu
+ h->major = cpu_to_be16(aoemajor);
+ h->minor = aoeminor;
+ h->cmd = AOECMD_CFG;
+-
+-cont:
+- dev_put(ifp);
+ }
+ rcu_read_unlock();
+ }
+diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
+index c51ea95bc2ce4..923a134fd7665 100644
+--- a/drivers/block/aoe/aoenet.c
++++ b/drivers/block/aoe/aoenet.c
+@@ -63,6 +63,7 @@ tx(int id) __must_hold(&txlock)
+ pr_warn("aoe: packet could not be sent on %s. %s\n",
+ ifp ? ifp->name : "netif",
+ "consider increasing tx_queue_len");
++ dev_put(ifp);
+ spin_lock_irq(&txlock);
+ }
+ return 0;
+diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
+index 33a8f37bb6a1f..b7c332528ed7a 100644
+--- a/drivers/block/nbd.c
++++ b/drivers/block/nbd.c
+@@ -2433,6 +2433,12 @@ static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info)
+ }
+
+ dev_list = nla_nest_start_noflag(reply, NBD_ATTR_DEVICE_LIST);
++ if (!dev_list) {
++ nlmsg_free(reply);
++ ret = -EMSGSIZE;
++ goto out;
++ }
++
+ if (index == -1) {
+ ret = idr_for_each(&nbd_index_idr, &status_cb, reply);
+ if (ret) {
+diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
+index aaabb732082cd..285418dbb43f5 100644
+--- a/drivers/bluetooth/btmtk.c
++++ b/drivers/bluetooth/btmtk.c
+@@ -372,8 +372,10 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
+ struct btmediatek_data *data = hci_get_priv(hdev);
+ int err;
+
+- if (!IS_ENABLED(CONFIG_DEV_COREDUMP))
++ if (!IS_ENABLED(CONFIG_DEV_COREDUMP)) {
++ kfree_skb(skb);
+ return 0;
++ }
+
+ switch (data->cd_info.state) {
+ case HCI_DEVCOREDUMP_IDLE:
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index d31edad7a0560..6cb87d47ad7d5 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -3273,7 +3273,6 @@ static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
+ {
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ u16 handle = le16_to_cpu(hci_acl_hdr(skb)->handle);
+- struct sk_buff *skb_cd;
+
+ switch (handle) {
+ case 0xfc6f: /* Firmware dump from device */
+@@ -3286,9 +3285,12 @@ static int btusb_recv_acl_mtk(struct hci_dev *hdev, struct sk_buff *skb)
+ * for backward compatibility, so we have to clone the packet
+ * extraly for the in-kernel coredump support.
+ */
+- skb_cd = skb_clone(skb, GFP_ATOMIC);
+- if (skb_cd)
+- btmtk_process_coredump(hdev, skb_cd);
++ if (IS_ENABLED(CONFIG_DEV_COREDUMP)) {
++ struct sk_buff *skb_cd = skb_clone(skb, GFP_ATOMIC);
++
++ if (skb_cd)
++ btmtk_process_coredump(hdev, skb_cd);
++ }
+
+ fallthrough;
+ case 0x05ff: /* Firmware debug logging 1 */
+diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c
+index 71e748a9477e4..c0436881a533c 100644
+--- a/drivers/bluetooth/hci_h5.c
++++ b/drivers/bluetooth/hci_h5.c
+@@ -113,6 +113,7 @@ struct h5_vnd {
+ int (*suspend)(struct h5 *h5);
+ int (*resume)(struct h5 *h5);
+ const struct acpi_gpio_mapping *acpi_gpio_map;
++ int sizeof_priv;
+ };
+
+ struct h5_device_data {
+@@ -863,7 +864,8 @@ static int h5_serdev_probe(struct serdev_device *serdev)
+ if (IS_ERR(h5->device_wake_gpio))
+ return PTR_ERR(h5->device_wake_gpio);
+
+- return hci_uart_register_device(&h5->serdev_hu, &h5p);
++ return hci_uart_register_device_priv(&h5->serdev_hu, &h5p,
++ h5->vnd->sizeof_priv);
+ }
+
+ static void h5_serdev_remove(struct serdev_device *serdev)
+@@ -1070,6 +1072,7 @@ static struct h5_vnd rtl_vnd = {
+ .suspend = h5_btrtl_suspend,
+ .resume = h5_btrtl_resume,
+ .acpi_gpio_map = acpi_btrtl_gpios,
++ .sizeof_priv = sizeof(struct btrealtek_data),
+ };
+
+ static const struct h5_device_data h5_data_rtl8822cs = {
+diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
+index edd2a81b4d5ed..8a60ad7acd705 100644
+--- a/drivers/bluetooth/hci_qca.c
++++ b/drivers/bluetooth/hci_qca.c
+@@ -2326,7 +2326,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
+
+ qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
+ GPIOD_OUT_LOW);
+- if (IS_ERR_OR_NULL(qcadev->bt_en) &&
++ if (IS_ERR(qcadev->bt_en) &&
+ (data->soc_type == QCA_WCN6750 ||
+ data->soc_type == QCA_WCN6855)) {
+ dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n");
+@@ -2335,7 +2335,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
+
+ qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl",
+ GPIOD_IN);
+- if (IS_ERR_OR_NULL(qcadev->sw_ctrl) &&
++ if (IS_ERR(qcadev->sw_ctrl) &&
+ (data->soc_type == QCA_WCN6750 ||
+ data->soc_type == QCA_WCN6855 ||
+ data->soc_type == QCA_WCN7850))
+@@ -2357,7 +2357,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
+ default:
+ qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
+ GPIOD_OUT_LOW);
+- if (IS_ERR_OR_NULL(qcadev->bt_en)) {
++ if (IS_ERR(qcadev->bt_en)) {
+ dev_warn(&serdev->dev, "failed to acquire enable gpio\n");
+ power_ctrl_enabled = false;
+ }
+diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c
+index 39c8b567da3c0..214fff876eae5 100644
+--- a/drivers/bluetooth/hci_serdev.c
++++ b/drivers/bluetooth/hci_serdev.c
+@@ -300,8 +300,9 @@ static const struct serdev_device_ops hci_serdev_client_ops = {
+ .write_wakeup = hci_uart_write_wakeup,
+ };
+
+-int hci_uart_register_device(struct hci_uart *hu,
+- const struct hci_uart_proto *p)
++int hci_uart_register_device_priv(struct hci_uart *hu,
++ const struct hci_uart_proto *p,
++ int sizeof_priv)
+ {
+ int err;
+ struct hci_dev *hdev;
+@@ -325,7 +326,7 @@ int hci_uart_register_device(struct hci_uart *hu,
+ set_bit(HCI_UART_PROTO_READY, &hu->flags);
+
+ /* Initialize and register HCI device */
+- hdev = hci_alloc_dev();
++ hdev = hci_alloc_dev_priv(sizeof_priv);
+ if (!hdev) {
+ BT_ERR("Can't allocate HCI device");
+ err = -ENOMEM;
+@@ -394,7 +395,7 @@ int hci_uart_register_device(struct hci_uart *hu,
+ percpu_free_rwsem(&hu->proto_lock);
+ return err;
+ }
+-EXPORT_SYMBOL_GPL(hci_uart_register_device);
++EXPORT_SYMBOL_GPL(hci_uart_register_device_priv);
+
+ void hci_uart_unregister_device(struct hci_uart *hu)
+ {
+diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
+index fb4a2d0d8cc80..68c8c7e95d64d 100644
+--- a/drivers/bluetooth/hci_uart.h
++++ b/drivers/bluetooth/hci_uart.h
+@@ -97,7 +97,17 @@ struct hci_uart {
+
+ int hci_uart_register_proto(const struct hci_uart_proto *p);
+ int hci_uart_unregister_proto(const struct hci_uart_proto *p);
+-int hci_uart_register_device(struct hci_uart *hu, const struct hci_uart_proto *p);
++
++int hci_uart_register_device_priv(struct hci_uart *hu,
++ const struct hci_uart_proto *p,
++ int sizeof_priv);
++
++static inline int hci_uart_register_device(struct hci_uart *hu,
++ const struct hci_uart_proto *p)
++{
++ return hci_uart_register_device_priv(hu, p, 0);
++}
++
+ void hci_uart_unregister_device(struct hci_uart *hu);
+
+ int hci_uart_tx_wakeup(struct hci_uart *hu);
+diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
+index e6742998f372c..d5e7fa9173a16 100644
+--- a/drivers/bus/Kconfig
++++ b/drivers/bus/Kconfig
+@@ -186,11 +186,12 @@ config SUNXI_RSB
+
+ config TEGRA_ACONNECT
+ tristate "Tegra ACONNECT Bus Driver"
+- depends on ARCH_TEGRA_210_SOC
++ depends on ARCH_TEGRA
+ depends on OF && PM
+ help
+ Driver for the Tegra ACONNECT bus which is used to interface with
+- the devices inside the Audio Processing Engine (APE) for Tegra210.
++ the devices inside the Audio Processing Engine (APE) for
++ Tegra210 and later.
+
+ config TEGRA_GMI
+ tristate "Tegra Generic Memory Interface bus driver"
+diff --git a/drivers/bus/mhi/ep/main.c b/drivers/bus/mhi/ep/main.c
+index 65fc1d738bec2..65f1f6b9b5df3 100644
+--- a/drivers/bus/mhi/ep/main.c
++++ b/drivers/bus/mhi/ep/main.c
+@@ -1496,7 +1496,7 @@ int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl,
+ mhi_cntrl->ring_item_cache = kmem_cache_create("mhi_ep_ring_item",
+ sizeof(struct mhi_ep_ring_item), 0,
+ 0, NULL);
+- if (!mhi_cntrl->ev_ring_el_cache) {
++ if (!mhi_cntrl->ring_item_cache) {
+ ret = -ENOMEM;
+ goto err_destroy_tre_buf_cache;
+ }
+diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+index 019cf6079cecd..6d2eadefd9dc9 100644
+--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
++++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+@@ -639,8 +639,8 @@ static int hwicap_setup(struct platform_device *pdev, int id,
+ dev_set_drvdata(dev, (void *)drvdata);
+
+ drvdata->base_address = devm_platform_ioremap_resource(pdev, 0);
+- if (!drvdata->base_address) {
+- retval = -ENODEV;
++ if (IS_ERR(drvdata->base_address)) {
++ retval = PTR_ERR(drvdata->base_address);
+ goto failed;
+ }
+
+diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
+index 2253c154a8248..20c4b28fed061 100644
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -418,6 +418,9 @@ static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
+ if (IS_ERR(hw))
+ return ERR_CAST(hw);
+
++ if (!hw)
++ return NULL;
++
+ return hw->core;
+ }
+
+diff --git a/drivers/clk/hisilicon/clk-hi3519.c b/drivers/clk/hisilicon/clk-hi3519.c
+index b871872d9960d..141b727ff60d6 100644
+--- a/drivers/clk/hisilicon/clk-hi3519.c
++++ b/drivers/clk/hisilicon/clk-hi3519.c
+@@ -130,7 +130,7 @@ static void hi3519_clk_unregister(struct platform_device *pdev)
+ of_clk_del_provider(pdev->dev.of_node);
+
+ hisi_clk_unregister_gate(hi3519_gate_clks,
+- ARRAY_SIZE(hi3519_mux_clks),
++ ARRAY_SIZE(hi3519_gate_clks),
+ crg->clk_data);
+ hisi_clk_unregister_mux(hi3519_mux_clks,
+ ARRAY_SIZE(hi3519_mux_clks),
+diff --git a/drivers/clk/hisilicon/clk-hi3559a.c b/drivers/clk/hisilicon/clk-hi3559a.c
+index ff4ca0edce06a..4623befafaec4 100644
+--- a/drivers/clk/hisilicon/clk-hi3559a.c
++++ b/drivers/clk/hisilicon/clk-hi3559a.c
+@@ -491,7 +491,6 @@ static void hisi_clk_register_pll(struct hi3559av100_pll_clock *clks,
+
+ clk = clk_register(NULL, &p_clk->hw);
+ if (IS_ERR(clk)) {
+- devm_kfree(dev, p_clk);
+ dev_err(dev, "%s: failed to register clock %s\n",
+ __func__, clks[i].name);
+ continue;
+diff --git a/drivers/clk/imx/clk-imx8mp-audiomix.c b/drivers/clk/imx/clk-imx8mp-audiomix.c
+index e4300df88f1ac..55ed211a5e0b1 100644
+--- a/drivers/clk/imx/clk-imx8mp-audiomix.c
++++ b/drivers/clk/imx/clk-imx8mp-audiomix.c
+@@ -18,7 +18,12 @@
+
+ #define CLKEN0 0x000
+ #define CLKEN1 0x004
+-#define SAI_MCLK_SEL(n) (0x300 + 4 * (n)) /* n in 0..5 */
++#define SAI1_MCLK_SEL 0x300
++#define SAI2_MCLK_SEL 0x304
++#define SAI3_MCLK_SEL 0x308
++#define SAI5_MCLK_SEL 0x30C
++#define SAI6_MCLK_SEL 0x310
++#define SAI7_MCLK_SEL 0x314
+ #define PDM_SEL 0x318
+ #define SAI_PLL_GNRL_CTL 0x400
+
+@@ -95,13 +100,13 @@ static const struct clk_parent_data clk_imx8mp_audiomix_pll_bypass_sels[] = {
+ IMX8MP_CLK_AUDIOMIX_SAI##n##_MCLK1_SEL, {}, \
+ clk_imx8mp_audiomix_sai##n##_mclk1_parents, \
+ ARRAY_SIZE(clk_imx8mp_audiomix_sai##n##_mclk1_parents), \
+- SAI_MCLK_SEL(n), 1, 0 \
++ SAI##n##_MCLK_SEL, 1, 0 \
+ }, { \
+ "sai"__stringify(n)"_mclk2_sel", \
+ IMX8MP_CLK_AUDIOMIX_SAI##n##_MCLK2_SEL, {}, \
+ clk_imx8mp_audiomix_sai_mclk2_parents, \
+ ARRAY_SIZE(clk_imx8mp_audiomix_sai_mclk2_parents), \
+- SAI_MCLK_SEL(n), 4, 1 \
++ SAI##n##_MCLK_SEL, 4, 1 \
+ }, { \
+ "sai"__stringify(n)"_ipg_cg", \
+ IMX8MP_CLK_AUDIOMIX_SAI##n##_IPG, \
+diff --git a/drivers/clk/mediatek/clk-mt7622-apmixedsys.c b/drivers/clk/mediatek/clk-mt7622-apmixedsys.c
+index 9cffd278e9a43..1b8f859b6b6cc 100644
+--- a/drivers/clk/mediatek/clk-mt7622-apmixedsys.c
++++ b/drivers/clk/mediatek/clk-mt7622-apmixedsys.c
+@@ -127,7 +127,6 @@ static void clk_mt7622_apmixed_remove(struct platform_device *pdev)
+ of_clk_del_provider(node);
+ mtk_clk_unregister_gates(apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data);
+ mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
+- mtk_free_clk_data(clk_data);
+ }
+
+ static const struct of_device_id of_match_clk_mt7622_apmixed[] = {
+diff --git a/drivers/clk/mediatek/clk-mt7981-topckgen.c b/drivers/clk/mediatek/clk-mt7981-topckgen.c
+index 682f4ca9e89ad..493aa11d3a175 100644
+--- a/drivers/clk/mediatek/clk-mt7981-topckgen.c
++++ b/drivers/clk/mediatek/clk-mt7981-topckgen.c
+@@ -357,8 +357,9 @@ static const struct mtk_mux top_muxes[] = {
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel",
+ sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15,
+ 0x1C0, 21),
+- MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents,
+- 0x050, 0x054, 0x058, 16, 1, 23, 0x1C0, 22),
++ MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", sgm_reg_parents,
++ 0x050, 0x054, 0x058, 16, 1, 23, 0x1C0, 22,
++ CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
+ MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP97B_SEL, "eip97b_sel", eip97b_parents,
+ 0x050, 0x054, 0x058, 24, 3, 31, 0x1C0, 23),
+ /* CLK_CFG_6 */
+diff --git a/drivers/clk/mediatek/clk-mt8135-apmixedsys.c b/drivers/clk/mediatek/clk-mt8135-apmixedsys.c
+index d1239b4b3db74..41bb2d2e2ea74 100644
+--- a/drivers/clk/mediatek/clk-mt8135-apmixedsys.c
++++ b/drivers/clk/mediatek/clk-mt8135-apmixedsys.c
+@@ -59,7 +59,7 @@ static int clk_mt8135_apmixed_probe(struct platform_device *pdev)
+
+ ret = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+ if (ret)
+- return ret;
++ goto free_clk_data;
+
+ ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
+ if (ret)
+@@ -69,6 +69,8 @@ static int clk_mt8135_apmixed_probe(struct platform_device *pdev)
+
+ unregister_plls:
+ mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
++free_clk_data:
++ mtk_free_clk_data(clk_data);
+
+ return ret;
+ }
+diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c
+index 6e23461a04559..934d5a15acfc5 100644
+--- a/drivers/clk/mediatek/clk-mt8183.c
++++ b/drivers/clk/mediatek/clk-mt8183.c
+@@ -790,7 +790,7 @@ static const struct mtk_gate infra_clks[] = {
+ /* infra_sspm_26m_self is main clock in co-processor, should not be closed in Linux. */
+ GATE_INFRA3_FLAGS(CLK_INFRA_SSPM_26M_SELF, "infra_sspm_26m_self", "f_f26m_ck", 3, CLK_IS_CRITICAL),
+ /* infra_sspm_32k_self is main clock in co-processor, should not be closed in Linux. */
+- GATE_INFRA3_FLAGS(CLK_INFRA_SSPM_32K_SELF, "infra_sspm_32k_self", "f_f26m_ck", 4, CLK_IS_CRITICAL),
++ GATE_INFRA3_FLAGS(CLK_INFRA_SSPM_32K_SELF, "infra_sspm_32k_self", "clk32k", 4, CLK_IS_CRITICAL),
+ GATE_INFRA3(CLK_INFRA_UFS_AXI, "infra_ufs_axi", "axi_sel", 5),
+ GATE_INFRA3(CLK_INFRA_I2C6, "infra_i2c6", "i2c_sel", 6),
+ GATE_INFRA3(CLK_INFRA_AP_MSDC0, "infra_ap_msdc0", "msdc50_hclk_sel", 7),
+diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
+index c12f81dfa6745..5f60f2bcca592 100644
+--- a/drivers/clk/meson/axg.c
++++ b/drivers/clk/meson/axg.c
+@@ -2142,7 +2142,9 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
+ &axg_vclk_input,
+ &axg_vclk2_input,
+ &axg_vclk_div,
++ &axg_vclk_div1,
+ &axg_vclk2_div,
++ &axg_vclk2_div1,
+ &axg_vclk_div2_en,
+ &axg_vclk_div4_en,
+ &axg_vclk_div6_en,
+diff --git a/drivers/clk/qcom/dispcc-sdm845.c b/drivers/clk/qcom/dispcc-sdm845.c
+index 735adfefc3798..e792e0b130d33 100644
+--- a/drivers/clk/qcom/dispcc-sdm845.c
++++ b/drivers/clk/qcom/dispcc-sdm845.c
+@@ -759,6 +759,8 @@ static struct clk_branch disp_cc_mdss_vsync_clk = {
+
+ static struct gdsc mdss_gdsc = {
+ .gdscr = 0x3000,
++ .en_few_wait_val = 0x6,
++ .en_rest_wait_val = 0x5,
+ .pd = {
+ .name = "mdss_gdsc",
+ },
+diff --git a/drivers/clk/qcom/gcc-ipq5018.c b/drivers/clk/qcom/gcc-ipq5018.c
+index 4aba47e8700d2..e2bd54826a4ce 100644
+--- a/drivers/clk/qcom/gcc-ipq5018.c
++++ b/drivers/clk/qcom/gcc-ipq5018.c
+@@ -1754,7 +1754,7 @@ static struct clk_branch gcc_gmac0_sys_clk = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .halt_bit = 31,
+ .clkr = {
+- .enable_reg = 0x683190,
++ .enable_reg = 0x68190,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data) {
+ .name = "gcc_gmac0_sys_clk",
+@@ -2180,7 +2180,7 @@ static struct clk_branch gcc_pcie1_axi_s_clk = {
+ };
+
+ static struct clk_branch gcc_pcie1_pipe_clk = {
+- .halt_reg = 8,
++ .halt_reg = 0x76018,
+ .halt_check = BRANCH_HALT_DELAY,
+ .halt_bit = 31,
+ .clkr = {
+@@ -3632,7 +3632,7 @@ static const struct qcom_reset_map gcc_ipq5018_resets[] = {
+ [GCC_SYSTEM_NOC_BCR] = { 0x26000, 0 },
+ [GCC_TCSR_BCR] = { 0x28000, 0 },
+ [GCC_TLMM_BCR] = { 0x34000, 0 },
+- [GCC_UBI0_AXI_ARES] = { 0x680},
++ [GCC_UBI0_AXI_ARES] = { 0x68010, 0 },
+ [GCC_UBI0_AHB_ARES] = { 0x68010, 1 },
+ [GCC_UBI0_NC_AXI_ARES] = { 0x68010, 2 },
+ [GCC_UBI0_DBG_ARES] = { 0x68010, 3 },
+diff --git a/drivers/clk/qcom/reset.c b/drivers/clk/qcom/reset.c
+index e45e32804d2c7..d96c96a9089f4 100644
+--- a/drivers/clk/qcom/reset.c
++++ b/drivers/clk/qcom/reset.c
+@@ -22,8 +22,8 @@ static int qcom_reset(struct reset_controller_dev *rcdev, unsigned long id)
+ return 0;
+ }
+
+-static int
+-qcom_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
++static int qcom_reset_set_assert(struct reset_controller_dev *rcdev,
++ unsigned long id, bool assert)
+ {
+ struct qcom_reset_controller *rst;
+ const struct qcom_reset_map *map;
+@@ -33,21 +33,22 @@ qcom_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
+ map = &rst->reset_map[id];
+ mask = map->bitmask ? map->bitmask : BIT(map->bit);
+
+- return regmap_update_bits(rst->regmap, map->reg, mask, mask);
++ regmap_update_bits(rst->regmap, map->reg, mask, assert ? mask : 0);
++
++ /* Read back the register to ensure write completion, ignore the value */
++ regmap_read(rst->regmap, map->reg, &mask);
++
++ return 0;
+ }
+
+-static int
+-qcom_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
++static int qcom_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
+ {
+- struct qcom_reset_controller *rst;
+- const struct qcom_reset_map *map;
+- u32 mask;
+-
+- rst = to_qcom_reset_controller(rcdev);
+- map = &rst->reset_map[id];
+- mask = map->bitmask ? map->bitmask : BIT(map->bit);
++ return qcom_reset_set_assert(rcdev, id, true);
++}
+
+- return regmap_update_bits(rst->regmap, map->reg, mask, 0);
++static int qcom_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
++{
++ return qcom_reset_set_assert(rcdev, id, false);
+ }
+
+ const struct reset_control_ops qcom_reset_ops = {
+diff --git a/drivers/clk/renesas/r8a779f0-cpg-mssr.c b/drivers/clk/renesas/r8a779f0-cpg-mssr.c
+index f721835c7e212..cc06127406ab5 100644
+--- a/drivers/clk/renesas/r8a779f0-cpg-mssr.c
++++ b/drivers/clk/renesas/r8a779f0-cpg-mssr.c
+@@ -161,7 +161,7 @@ static const struct mssr_mod_clk r8a779f0_mod_clks[] __initconst = {
+ DEF_MOD("cmt1", 911, R8A779F0_CLK_R),
+ DEF_MOD("cmt2", 912, R8A779F0_CLK_R),
+ DEF_MOD("cmt3", 913, R8A779F0_CLK_R),
+- DEF_MOD("pfc0", 915, R8A779F0_CLK_CL16M),
++ DEF_MOD("pfc0", 915, R8A779F0_CLK_CPEX),
+ DEF_MOD("tsc", 919, R8A779F0_CLK_CL16M),
+ DEF_MOD("rswitch2", 1505, R8A779F0_CLK_RSW2),
+ DEF_MOD("ether-serdes", 1506, R8A779F0_CLK_S0D2_HSC),
+diff --git a/drivers/clk/renesas/r8a779g0-cpg-mssr.c b/drivers/clk/renesas/r8a779g0-cpg-mssr.c
+index 5974adcef3eda..c4b1938db76b3 100644
+--- a/drivers/clk/renesas/r8a779g0-cpg-mssr.c
++++ b/drivers/clk/renesas/r8a779g0-cpg-mssr.c
+@@ -22,7 +22,7 @@
+
+ enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+- LAST_DT_CORE_CLK = R8A779G0_CLK_R,
++ LAST_DT_CORE_CLK = R8A779G0_CLK_CP,
+
+ /* External Input Clocks */
+ CLK_EXTAL,
+@@ -141,6 +141,7 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
+ DEF_FIXED("svd2_vip", R8A779G0_CLK_SVD2_VIP, CLK_SV_VIP, 2, 1),
+ DEF_FIXED("cbfusa", R8A779G0_CLK_CBFUSA, CLK_EXTAL, 2, 1),
+ DEF_FIXED("cpex", R8A779G0_CLK_CPEX, CLK_EXTAL, 2, 1),
++ DEF_FIXED("cp", R8A779G0_CLK_CP, CLK_EXTAL, 2, 1),
+ DEF_FIXED("viobus", R8A779G0_CLK_VIOBUS, CLK_VIO, 1, 1),
+ DEF_FIXED("viobusd2", R8A779G0_CLK_VIOBUSD2, CLK_VIO, 2, 1),
+ DEF_FIXED("vcbus", R8A779G0_CLK_VCBUS, CLK_VC, 1, 1),
+@@ -193,7 +194,7 @@ static const struct mssr_mod_clk r8a779g0_mod_clks[] __initconst = {
+ DEF_MOD("msi4", 622, R8A779G0_CLK_MSO),
+ DEF_MOD("msi5", 623, R8A779G0_CLK_MSO),
+ DEF_MOD("pciec0", 624, R8A779G0_CLK_S0D2_HSC),
+- DEF_MOD("pscie1", 625, R8A779G0_CLK_S0D2_HSC),
++ DEF_MOD("pciec1", 625, R8A779G0_CLK_S0D2_HSC),
+ DEF_MOD("pwm", 628, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("rpc-if", 629, R8A779G0_CLK_RPCD2),
+ DEF_MOD("scif0", 702, R8A779G0_CLK_SASYNCPERD4),
+@@ -232,10 +233,10 @@ static const struct mssr_mod_clk r8a779g0_mod_clks[] __initconst = {
+ DEF_MOD("cmt1", 911, R8A779G0_CLK_R),
+ DEF_MOD("cmt2", 912, R8A779G0_CLK_R),
+ DEF_MOD("cmt3", 913, R8A779G0_CLK_R),
+- DEF_MOD("pfc0", 915, R8A779G0_CLK_CL16M),
+- DEF_MOD("pfc1", 916, R8A779G0_CLK_CL16M),
+- DEF_MOD("pfc2", 917, R8A779G0_CLK_CL16M),
+- DEF_MOD("pfc3", 918, R8A779G0_CLK_CL16M),
++ DEF_MOD("pfc0", 915, R8A779G0_CLK_CP),
++ DEF_MOD("pfc1", 916, R8A779G0_CLK_CP),
++ DEF_MOD("pfc2", 917, R8A779G0_CLK_CP),
++ DEF_MOD("pfc3", 918, R8A779G0_CLK_CP),
+ DEF_MOD("tsc", 919, R8A779G0_CLK_CL16M),
+ DEF_MOD("tsn", 2723, R8A779G0_CLK_S0D4_HSC),
+ DEF_MOD("ssiu", 2926, R8A779G0_CLK_S0D6_PER),
+diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c
+index b70bb378ab469..075ade0925d45 100644
+--- a/drivers/clk/renesas/r9a07g043-cpg.c
++++ b/drivers/clk/renesas/r9a07g043-cpg.c
+@@ -138,7 +138,7 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = {
+ DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
+ DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+- DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi,
++ DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_shdi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4),
+ DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4),
+diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c
+index 1047278c9079a..bc822b9fd7ce6 100644
+--- a/drivers/clk/renesas/r9a07g044-cpg.c
++++ b/drivers/clk/renesas/r9a07g044-cpg.c
+@@ -178,7 +178,7 @@ static const struct {
+ DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
+ DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+- DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi,
++ DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_shdi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4),
+ DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4),
+diff --git a/drivers/clk/samsung/clk-exynos850.c b/drivers/clk/samsung/clk-exynos850.c
+index bdc1eef7d6e54..c7b0b9751307b 100644
+--- a/drivers/clk/samsung/clk-exynos850.c
++++ b/drivers/clk/samsung/clk-exynos850.c
+@@ -605,7 +605,7 @@ static const struct samsung_div_clock apm_div_clks[] __initconst = {
+
+ static const struct samsung_gate_clock apm_gate_clks[] __initconst = {
+ GATE(CLK_GOUT_CLKCMU_CMGP_BUS, "gout_clkcmu_cmgp_bus", "dout_apm_bus",
+- CLK_CON_GAT_CLKCMU_CMGP_BUS, 21, 0, 0),
++ CLK_CON_GAT_CLKCMU_CMGP_BUS, 21, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_CLKCMU_CHUB_BUS, "gout_clkcmu_chub_bus",
+ "mout_clkcmu_chub_bus",
+ CLK_CON_GAT_GATE_CLKCMU_CHUB_BUS, 21, 0, 0),
+@@ -974,19 +974,19 @@ static const struct samsung_fixed_rate_clock cmgp_fixed_clks[] __initconst = {
+ static const struct samsung_mux_clock cmgp_mux_clks[] __initconst = {
+ MUX(CLK_MOUT_CMGP_ADC, "mout_cmgp_adc", mout_cmgp_adc_p,
+ CLK_CON_MUX_CLK_CMGP_ADC, 0, 1),
+- MUX(CLK_MOUT_CMGP_USI0, "mout_cmgp_usi0", mout_cmgp_usi0_p,
+- CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP0, 0, 1),
+- MUX(CLK_MOUT_CMGP_USI1, "mout_cmgp_usi1", mout_cmgp_usi1_p,
+- CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP1, 0, 1),
++ MUX_F(CLK_MOUT_CMGP_USI0, "mout_cmgp_usi0", mout_cmgp_usi0_p,
++ CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP0, 0, 1, CLK_SET_RATE_PARENT, 0),
++ MUX_F(CLK_MOUT_CMGP_USI1, "mout_cmgp_usi1", mout_cmgp_usi1_p,
++ CLK_CON_MUX_MUX_CLK_CMGP_USI_CMGP1, 0, 1, CLK_SET_RATE_PARENT, 0),
+ };
+
+ static const struct samsung_div_clock cmgp_div_clks[] __initconst = {
+ DIV(CLK_DOUT_CMGP_ADC, "dout_cmgp_adc", "gout_clkcmu_cmgp_bus",
+ CLK_CON_DIV_DIV_CLK_CMGP_ADC, 0, 4),
+- DIV(CLK_DOUT_CMGP_USI0, "dout_cmgp_usi0", "mout_cmgp_usi0",
+- CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP0, 0, 5),
+- DIV(CLK_DOUT_CMGP_USI1, "dout_cmgp_usi1", "mout_cmgp_usi1",
+- CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP1, 0, 5),
++ DIV_F(CLK_DOUT_CMGP_USI0, "dout_cmgp_usi0", "mout_cmgp_usi0",
++ CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP0, 0, 5, CLK_SET_RATE_PARENT, 0),
++ DIV_F(CLK_DOUT_CMGP_USI1, "dout_cmgp_usi1", "mout_cmgp_usi1",
++ CLK_CON_DIV_DIV_CLK_CMGP_USI_CMGP1, 0, 5, CLK_SET_RATE_PARENT, 0),
+ };
+
+ static const struct samsung_gate_clock cmgp_gate_clks[] __initconst = {
+@@ -1001,12 +1001,12 @@ static const struct samsung_gate_clock cmgp_gate_clks[] __initconst = {
+ "gout_clkcmu_cmgp_bus",
+ CLK_CON_GAT_GOUT_CMGP_GPIO_PCLK, 21, CLK_IGNORE_UNUSED, 0),
+ GATE(CLK_GOUT_CMGP_USI0_IPCLK, "gout_cmgp_usi0_ipclk", "dout_cmgp_usi0",
+- CLK_CON_GAT_GOUT_CMGP_USI_CMGP0_IPCLK, 21, 0, 0),
++ CLK_CON_GAT_GOUT_CMGP_USI_CMGP0_IPCLK, 21, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_CMGP_USI0_PCLK, "gout_cmgp_usi0_pclk",
+ "gout_clkcmu_cmgp_bus",
+ CLK_CON_GAT_GOUT_CMGP_USI_CMGP0_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_CMGP_USI1_IPCLK, "gout_cmgp_usi1_ipclk", "dout_cmgp_usi1",
+- CLK_CON_GAT_GOUT_CMGP_USI_CMGP1_IPCLK, 21, 0, 0),
++ CLK_CON_GAT_GOUT_CMGP_USI_CMGP1_IPCLK, 21, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_CMGP_USI1_PCLK, "gout_cmgp_usi1_pclk",
+ "gout_clkcmu_cmgp_bus",
+ CLK_CON_GAT_GOUT_CMGP_USI_CMGP1_PCLK, 21, 0, 0),
+@@ -1557,8 +1557,9 @@ static const struct samsung_mux_clock peri_mux_clks[] __initconst = {
+ mout_peri_uart_user_p, PLL_CON0_MUX_CLKCMU_PERI_UART_USER, 4, 1),
+ MUX(CLK_MOUT_PERI_HSI2C_USER, "mout_peri_hsi2c_user",
+ mout_peri_hsi2c_user_p, PLL_CON0_MUX_CLKCMU_PERI_HSI2C_USER, 4, 1),
+- MUX(CLK_MOUT_PERI_SPI_USER, "mout_peri_spi_user", mout_peri_spi_user_p,
+- PLL_CON0_MUX_CLKCMU_PERI_SPI_USER, 4, 1),
++ MUX_F(CLK_MOUT_PERI_SPI_USER, "mout_peri_spi_user",
++ mout_peri_spi_user_p, PLL_CON0_MUX_CLKCMU_PERI_SPI_USER, 4, 1,
++ CLK_SET_RATE_PARENT, 0),
+ };
+
+ static const struct samsung_div_clock peri_div_clks[] __initconst = {
+@@ -1568,8 +1569,8 @@ static const struct samsung_div_clock peri_div_clks[] __initconst = {
+ CLK_CON_DIV_DIV_CLK_PERI_HSI2C_1, 0, 5),
+ DIV(CLK_DOUT_PERI_HSI2C2, "dout_peri_hsi2c2", "gout_peri_hsi2c2",
+ CLK_CON_DIV_DIV_CLK_PERI_HSI2C_2, 0, 5),
+- DIV(CLK_DOUT_PERI_SPI0, "dout_peri_spi0", "mout_peri_spi_user",
+- CLK_CON_DIV_DIV_CLK_PERI_SPI_0, 0, 5),
++ DIV_F(CLK_DOUT_PERI_SPI0, "dout_peri_spi0", "mout_peri_spi_user",
++ CLK_CON_DIV_DIV_CLK_PERI_SPI_0, 0, 5, CLK_SET_RATE_PARENT, 0),
+ };
+
+ static const struct samsung_gate_clock peri_gate_clks[] __initconst = {
+@@ -1611,7 +1612,7 @@ static const struct samsung_gate_clock peri_gate_clks[] __initconst = {
+ "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_PWM_MOTOR_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_SPI0_IPCLK, "gout_spi0_ipclk", "dout_peri_spi0",
+- CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK, 21, 0, 0),
++ CLK_CON_GAT_GOUT_PERI_SPI_0_IPCLK, 21, CLK_SET_RATE_PARENT, 0),
+ GATE(CLK_GOUT_SPI0_PCLK, "gout_spi0_pclk", "mout_peri_bus_user",
+ CLK_CON_GAT_GOUT_PERI_SPI_0_PCLK, 21, 0, 0),
+ GATE(CLK_GOUT_SYSREG_PERI_PCLK, "gout_sysreg_peri_pclk",
+diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c
+index 7bdeaff2bfd68..c28d3dacf0fb2 100644
+--- a/drivers/clk/zynq/clkc.c
++++ b/drivers/clk/zynq/clkc.c
+@@ -42,6 +42,7 @@ static void __iomem *zynq_clkc_base;
+ #define SLCR_SWDT_CLK_SEL (zynq_clkc_base + 0x204)
+
+ #define NUM_MIO_PINS 54
++#define CLK_NAME_LEN 16
+
+ #define DBG_CLK_CTRL_CLKACT_TRC BIT(0)
+ #define DBG_CLK_CTRL_CPU_1XCLKACT BIT(1)
+@@ -215,7 +216,7 @@ static void __init zynq_clk_setup(struct device_node *np)
+ int i;
+ u32 tmp;
+ int ret;
+- char *clk_name;
++ char clk_name[CLK_NAME_LEN];
+ unsigned int fclk_enable = 0;
+ const char *clk_output_name[clk_max];
+ const char *cpu_parents[4];
+@@ -426,12 +427,10 @@ static void __init zynq_clk_setup(struct device_node *np)
+ "gem1_emio_mux", CLK_SET_RATE_PARENT,
+ SLCR_GEM1_CLK_CTRL, 0, 0, &gem1clk_lock);
+
+- tmp = strlen("mio_clk_00x");
+- clk_name = kmalloc(tmp, GFP_KERNEL);
+ for (i = 0; i < NUM_MIO_PINS; i++) {
+ int idx;
+
+- snprintf(clk_name, tmp, "mio_clk_%2.2d", i);
++ snprintf(clk_name, CLK_NAME_LEN, "mio_clk_%2.2d", i);
+ idx = of_property_match_string(np, "clock-names", clk_name);
+ if (idx >= 0)
+ can_mio_mux_parents[i] = of_clk_get_parent_name(np,
+@@ -439,7 +438,6 @@ static void __init zynq_clk_setup(struct device_node *np)
+ else
+ can_mio_mux_parents[i] = dummy_nm;
+ }
+- kfree(clk_name);
+ clk_register_mux(NULL, "can_mux", periph_parents, 4,
+ CLK_SET_RATE_NO_REPARENT, SLCR_CAN_CLK_CTRL, 4, 2, 0,
+ &canclk_lock);
+diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
+index f911606897b8d..a0ebad77666e3 100644
+--- a/drivers/cpufreq/Kconfig.arm
++++ b/drivers/cpufreq/Kconfig.arm
+@@ -173,6 +173,7 @@ config ARM_QCOM_CPUFREQ_NVMEM
+ config ARM_QCOM_CPUFREQ_HW
+ tristate "QCOM CPUFreq HW driver"
+ depends on ARCH_QCOM || COMPILE_TEST
++ depends on COMMON_CLK
+ help
+ Support for the CPUFreq HW driver.
+ Some QCOM chipsets have a HW engine to offload the steps
+diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c
+index 35fb3a559ea97..1a1857b0a6f48 100644
+--- a/drivers/cpufreq/brcmstb-avs-cpufreq.c
++++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c
+@@ -481,6 +481,8 @@ static bool brcm_avs_is_firmware_loaded(struct private_data *priv)
+ static unsigned int brcm_avs_cpufreq_get(unsigned int cpu)
+ {
+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
++ if (!policy)
++ return 0;
+ struct private_data *priv = policy->driver_data;
+
+ cpufreq_cpu_put(policy);
+diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
+index 44db4f59c4cc6..7d570b44777ac 100644
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -644,14 +644,16 @@ static ssize_t store_local_boost(struct cpufreq_policy *policy,
+ if (policy->boost_enabled == enable)
+ return count;
+
++ policy->boost_enabled = enable;
++
+ cpus_read_lock();
+ ret = cpufreq_driver->set_boost(policy, enable);
+ cpus_read_unlock();
+
+- if (ret)
++ if (ret) {
++ policy->boost_enabled = !policy->boost_enabled;
+ return ret;
+-
+- policy->boost_enabled = enable;
++ }
+
+ return count;
+ }
+@@ -1419,6 +1421,9 @@ static int cpufreq_online(unsigned int cpu)
+ goto out_free_policy;
+ }
+
++ /* Let the per-policy boost flag mirror the cpufreq_driver boost during init */
++ policy->boost_enabled = cpufreq_boost_enabled() && policy_has_boost_freq(policy);
++
+ /*
+ * The initialization has succeeded and the policy is online.
+ * If there is a problem with its frequency table, take it
+@@ -2755,11 +2760,12 @@ int cpufreq_boost_trigger_state(int state)
+
+ cpus_read_lock();
+ for_each_active_policy(policy) {
++ policy->boost_enabled = state;
+ ret = cpufreq_driver->set_boost(policy, state);
+- if (ret)
++ if (ret) {
++ policy->boost_enabled = !policy->boost_enabled;
+ goto err_reset_state;
+-
+- policy->boost_enabled = state;
++ }
+ }
+ cpus_read_unlock();
+
+diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
+index c4d4643b6ca65..c17dc51a5a022 100644
+--- a/drivers/cpufreq/freq_table.c
++++ b/drivers/cpufreq/freq_table.c
+@@ -40,7 +40,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
+ cpufreq_for_each_valid_entry(pos, table) {
+ freq = pos->frequency;
+
+- if (!cpufreq_boost_enabled()
++ if ((!cpufreq_boost_enabled() || !policy->boost_enabled)
+ && (pos->flags & CPUFREQ_BOOST_FREQ))
+ continue;
+
+diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c b/drivers/cpufreq/mediatek-cpufreq-hw.c
+index d46afb3c00923..8d097dcddda47 100644
+--- a/drivers/cpufreq/mediatek-cpufreq-hw.c
++++ b/drivers/cpufreq/mediatek-cpufreq-hw.c
+@@ -13,6 +13,7 @@
+ #include <linux/of.h>
+ #include <linux/of_platform.h>
+ #include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
+ #include <linux/slab.h>
+
+ #define LUT_MAX_ENTRIES 32U
+@@ -300,7 +301,23 @@ static struct cpufreq_driver cpufreq_mtk_hw_driver = {
+ static int mtk_cpufreq_hw_driver_probe(struct platform_device *pdev)
+ {
+ const void *data;
+- int ret;
++ int ret, cpu;
++ struct device *cpu_dev;
++ struct regulator *cpu_reg;
++
++ /* Make sure that all CPU supplies are available before proceeding. */
++ for_each_possible_cpu(cpu) {
++ cpu_dev = get_cpu_device(cpu);
++ if (!cpu_dev)
++ return dev_err_probe(&pdev->dev, -EPROBE_DEFER,
++ "Failed to get cpu%d device\n", cpu);
++
++ cpu_reg = devm_regulator_get(cpu_dev, "cpu");
++ if (IS_ERR(cpu_reg))
++ return dev_err_probe(&pdev->dev, PTR_ERR(cpu_reg),
++ "CPU%d regulator get failed\n", cpu);
++ }
++
+
+ data = of_device_get_match_data(&pdev->dev);
+ if (!data)
+diff --git a/drivers/crypto/ccp/platform-access.c b/drivers/crypto/ccp/platform-access.c
+index 94367bc49e35b..1b8ed33897332 100644
+--- a/drivers/crypto/ccp/platform-access.c
++++ b/drivers/crypto/ccp/platform-access.c
+@@ -118,9 +118,16 @@ int psp_send_platform_access_msg(enum psp_platform_access_msg msg,
+ goto unlock;
+ }
+
+- /* Store the status in request header for caller to investigate */
++ /*
++ * Read status from PSP. If status is non-zero, it indicates an error
++ * occurred during "processing" of the command.
++ * If status is zero, it indicates the command was "processed"
++ * successfully, but the result of the command is in the payload.
++ * Return both cases to the caller as -EIO to investigate.
++ */
+ cmd_reg = ioread32(cmd);
+- req->header.status = FIELD_GET(PSP_CMDRESP_STS, cmd_reg);
++ if (FIELD_GET(PSP_CMDRESP_STS, cmd_reg))
++ req->header.status = FIELD_GET(PSP_CMDRESP_STS, cmd_reg);
+ if (req->header.status) {
+ ret = -EIO;
+ goto unlock;
+diff --git a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c
+index a87d29ae724fe..7909b51e97c30 100644
+--- a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c
++++ b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c
+@@ -372,6 +372,13 @@ static u16 get_ring_to_svc_map(struct adf_accel_dev *accel_dev)
+ if (!fw_config)
+ return 0;
+
++ /* If dcc, all rings handle compression requests */
++ if (adf_get_service_enabled(accel_dev) == SVC_DCC) {
++ for (i = 0; i < RP_GROUP_COUNT; i++)
++ rps[i] = COMP;
++ goto set_mask;
++ }
++
+ for (i = 0; i < RP_GROUP_COUNT; i++) {
+ switch (fw_config[i].ae_mask) {
+ case ADF_AE_GROUP_0:
+@@ -400,6 +407,7 @@ static u16 get_ring_to_svc_map(struct adf_accel_dev *accel_dev)
+ }
+ }
+
++set_mask:
+ ring_to_svc_map = rps[RP_GROUP_0] << ADF_CFG_SERV_RING_PAIR_0_SHIFT |
+ rps[RP_GROUP_1] << ADF_CFG_SERV_RING_PAIR_1_SHIFT |
+ rps[RP_GROUP_0] << ADF_CFG_SERV_RING_PAIR_2_SHIFT |
+diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
+index 94a0ebb03d8c9..e171cddf6f025 100644
+--- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
++++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
+@@ -331,6 +331,13 @@ static u16 get_ring_to_svc_map(struct adf_accel_dev *accel_dev)
+ if (!fw_config)
+ return 0;
+
++ /* If dcc, all rings handle compression requests */
++ if (adf_get_service_enabled(accel_dev) == SVC_DCC) {
++ for (i = 0; i < RP_GROUP_COUNT; i++)
++ rps[i] = COMP;
++ goto set_mask;
++ }
++
+ for (i = 0; i < RP_GROUP_COUNT; i++) {
+ switch (fw_config[i].ae_mask) {
+ case ADF_AE_GROUP_0:
+@@ -359,6 +366,7 @@ static u16 get_ring_to_svc_map(struct adf_accel_dev *accel_dev)
+ }
+ }
+
++set_mask:
+ ring_to_svc_map = rps[RP_GROUP_0] << ADF_CFG_SERV_RING_PAIR_0_SHIFT |
+ rps[RP_GROUP_1] << ADF_CFG_SERV_RING_PAIR_1_SHIFT |
+ rps[RP_GROUP_0] << ADF_CFG_SERV_RING_PAIR_2_SHIFT |
+diff --git a/drivers/crypto/intel/qat/qat_common/adf_clock.c b/drivers/crypto/intel/qat/qat_common/adf_clock.c
+index 01e0a389e462b..cf89f57de2a70 100644
+--- a/drivers/crypto/intel/qat/qat_common/adf_clock.c
++++ b/drivers/crypto/intel/qat/qat_common/adf_clock.c
+@@ -83,6 +83,9 @@ static int measure_clock(struct adf_accel_dev *accel_dev, u32 *frequency)
+ }
+
+ delta_us = timespec_to_us(&ts3) - timespec_to_us(&ts1);
++ if (!delta_us)
++ return -EINVAL;
++
+ temp = (timestamp2 - timestamp1) * ME_CLK_DIVIDER * 10;
+ temp = DIV_ROUND_CLOSEST_ULL(temp, delta_us);
+ /*
+diff --git a/drivers/crypto/intel/qat/qat_common/adf_cnv_dbgfs.c b/drivers/crypto/intel/qat/qat_common/adf_cnv_dbgfs.c
+index 07119c487da01..627953a72d478 100644
+--- a/drivers/crypto/intel/qat/qat_common/adf_cnv_dbgfs.c
++++ b/drivers/crypto/intel/qat/qat_common/adf_cnv_dbgfs.c
+@@ -16,7 +16,6 @@
+
+ #define CNV_ERR_INFO_MASK GENMASK(11, 0)
+ #define CNV_ERR_TYPE_MASK GENMASK(15, 12)
+-#define CNV_SLICE_ERR_MASK GENMASK(7, 0)
+ #define CNV_SLICE_ERR_SIGN_BIT_INDEX 7
+ #define CNV_DELTA_ERR_SIGN_BIT_INDEX 11
+
+diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c
+index 9985683056d5f..f752653ccb47e 100644
+--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c
++++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c
+@@ -398,6 +398,9 @@ int adf_gen4_init_thd2arb_map(struct adf_accel_dev *accel_dev)
+ ADF_GEN4_ADMIN_ACCELENGINES;
+
+ if (srv_id == SVC_DCC) {
++ if (ae_cnt > ICP_QAT_HW_AE_DELIMITER)
++ return -EINVAL;
++
+ memcpy(thd2arb_map, thrd_to_arb_map_dcc,
+ array_size(sizeof(*thd2arb_map), ae_cnt));
+ return 0;
+diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c
+index 048c246079390..2dd3772bf58a6 100644
+--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c
++++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_ras.c
+@@ -1007,8 +1007,7 @@ static bool adf_handle_spppar_err(struct adf_accel_dev *accel_dev,
+ static bool adf_handle_ssmcpppar_err(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 iastatssm)
+ {
+- u32 reg = ADF_CSR_RD(csr, ADF_GEN4_SSMCPPERR);
+- u32 bits_num = BITS_PER_REG(reg);
++ u32 reg, bits_num = BITS_PER_REG(reg);
+ bool reset_required = false;
+ unsigned long errs_bits;
+ u32 bit_iterator;
+@@ -1106,8 +1105,7 @@ static bool adf_handle_rf_parr_err(struct adf_accel_dev *accel_dev,
+ static bool adf_handle_ser_err_ssmsh(struct adf_accel_dev *accel_dev,
+ void __iomem *csr, u32 iastatssm)
+ {
+- u32 reg = ADF_CSR_RD(csr, ADF_GEN4_SER_ERR_SSMSH);
+- u32 bits_num = BITS_PER_REG(reg);
++ u32 reg, bits_num = BITS_PER_REG(reg);
+ bool reset_required = false;
+ unsigned long errs_bits;
+ u32 bit_iterator;
+diff --git a/drivers/crypto/intel/qat/qat_common/qat_comp_algs.c b/drivers/crypto/intel/qat/qat_common/qat_comp_algs.c
+index bf8c0ee629175..2ba4aa22e0927 100644
+--- a/drivers/crypto/intel/qat/qat_common/qat_comp_algs.c
++++ b/drivers/crypto/intel/qat/qat_common/qat_comp_algs.c
+@@ -13,15 +13,6 @@
+ #include "qat_compression.h"
+ #include "qat_algs_send.h"
+
+-#define QAT_RFC_1950_HDR_SIZE 2
+-#define QAT_RFC_1950_FOOTER_SIZE 4
+-#define QAT_RFC_1950_CM_DEFLATE 8
+-#define QAT_RFC_1950_CM_DEFLATE_CINFO_32K 7
+-#define QAT_RFC_1950_CM_MASK 0x0f
+-#define QAT_RFC_1950_CM_OFFSET 4
+-#define QAT_RFC_1950_DICT_MASK 0x20
+-#define QAT_RFC_1950_COMP_HDR 0x785e
+-
+ static DEFINE_MUTEX(algs_lock);
+ static unsigned int active_devs;
+
+diff --git a/drivers/crypto/xilinx/zynqmp-aes-gcm.c b/drivers/crypto/xilinx/zynqmp-aes-gcm.c
+index 3c205324b22b6..e614057188409 100644
+--- a/drivers/crypto/xilinx/zynqmp-aes-gcm.c
++++ b/drivers/crypto/xilinx/zynqmp-aes-gcm.c
+@@ -231,7 +231,10 @@ static int zynqmp_handle_aes_req(struct crypto_engine *engine,
+ err = zynqmp_aes_aead_cipher(areq);
+ }
+
++ local_bh_disable();
+ crypto_finalize_aead_request(engine, areq, err);
++ local_bh_enable();
++
+ return 0;
+ }
+
+diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c
+index 08fd0baea7a0e..0363ca434ef45 100644
+--- a/drivers/cxl/core/cdat.c
++++ b/drivers/cxl/core/cdat.c
+@@ -389,36 +389,38 @@ EXPORT_SYMBOL_NS_GPL(cxl_endpoint_parse_cdat, CXL);
+ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg,
+ const unsigned long end)
+ {
++ struct acpi_cdat_sslbis_table {
++ struct acpi_cdat_header header;
++ struct acpi_cdat_sslbis sslbis_header;
++ struct acpi_cdat_sslbe entries[];
++ } *tbl = (struct acpi_cdat_sslbis_table *)header;
++ int size = sizeof(header->cdat) + sizeof(tbl->sslbis_header);
+ struct acpi_cdat_sslbis *sslbis;
+- int size = sizeof(header->cdat) + sizeof(*sslbis);
+ struct cxl_port *port = arg;
+ struct device *dev = &port->dev;
+- struct acpi_cdat_sslbe *entry;
+ int remain, entries, i;
+ u16 len;
+
+ len = le16_to_cpu((__force __le16)header->cdat.length);
+ remain = len - size;
+- if (!remain || remain % sizeof(*entry) ||
++ if (!remain || remain % sizeof(tbl->entries[0]) ||
+ (unsigned long)header + len > end) {
+ dev_warn(dev, "Malformed SSLBIS table length: (%u)\n", len);
+ return -EINVAL;
+ }
+
+- /* Skip common header */
+- sslbis = (struct acpi_cdat_sslbis *)((unsigned long)header +
+- sizeof(header->cdat));
+-
++ sslbis = &tbl->sslbis_header;
+ /* Unrecognized data type, we can skip */
+ if (sslbis->data_type > ACPI_HMAT_WRITE_BANDWIDTH)
+ return 0;
+
+- entries = remain / sizeof(*entry);
+- entry = (struct acpi_cdat_sslbe *)((unsigned long)header + sizeof(*sslbis));
++ entries = remain / sizeof(tbl->entries[0]);
++ if (struct_size(tbl, entries, entries) != len)
++ return -EINVAL;
+
+ for (i = 0; i < entries; i++) {
+- u16 x = le16_to_cpu((__force __le16)entry->portx_id);
+- u16 y = le16_to_cpu((__force __le16)entry->porty_id);
++ u16 x = le16_to_cpu((__force __le16)tbl->entries[i].portx_id);
++ u16 y = le16_to_cpu((__force __le16)tbl->entries[i].porty_id);
+ __le64 le_base;
+ __le16 le_val;
+ struct cxl_dport *dport;
+@@ -448,8 +450,8 @@ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg,
+ break;
+ }
+
+- le_base = (__force __le64)sslbis->entry_base_unit;
+- le_val = (__force __le16)entry->latency_or_bandwidth;
++ le_base = (__force __le64)tbl->sslbis_header.entry_base_unit;
++ le_val = (__force __le16)tbl->entries[i].latency_or_bandwidth;
+
+ if (check_mul_overflow(le64_to_cpu(le_base),
+ le16_to_cpu(le_val), &val))
+@@ -462,8 +464,6 @@ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg,
+ sslbis->data_type,
+ val);
+ }
+-
+- entry++;
+ }
+
+ return 0;
+diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
+index e928f2ca0f1e9..002a5ec806207 100644
+--- a/drivers/dma/Kconfig
++++ b/drivers/dma/Kconfig
+@@ -643,16 +643,16 @@ config TEGRA20_APB_DMA
+
+ config TEGRA210_ADMA
+ tristate "NVIDIA Tegra210 ADMA support"
+- depends on (ARCH_TEGRA_210_SOC || COMPILE_TEST)
++ depends on (ARCH_TEGRA || COMPILE_TEST)
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ help
+- Support for the NVIDIA Tegra210 ADMA controller driver. The
+- DMA controller has multiple DMA channels and is used to service
+- various audio clients in the Tegra210 audio processing engine
+- (APE). This DMA controller transfers data from memory to
+- peripheral and vice versa. It does not support memory to
+- memory data transfer.
++ Support for the NVIDIA Tegra210/Tegra186/Tegra194/Tegra234 ADMA
++ controller driver. The DMA controller has multiple DMA channels
++ and is used to service various audio clients in the Tegra210
++ audio processing engine (APE). This DMA controller transfers
++ data from memory to peripheral and vice versa. It does not
++ support memory to memory data transfer.
+
+ config TIMB_DMA
+ tristate "Timberdale FPGA DMA support"
+diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
+index 7f686d179fc93..c751a87c7a8e6 100644
+--- a/drivers/dpll/dpll_core.c
++++ b/drivers/dpll/dpll_core.c
+@@ -129,9 +129,9 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
+ reg = dpll_pin_registration_find(ref, ops, priv);
+ if (WARN_ON(!reg))
+ return -EINVAL;
++ list_del(®->list);
++ kfree(reg);
+ if (refcount_dec_and_test(&ref->refcount)) {
+- list_del(®->list);
+- kfree(reg);
+ xa_erase(xa_pins, i);
+ WARN_ON(!list_empty(&ref->registration_list));
+ kfree(ref);
+@@ -209,9 +209,9 @@ dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll,
+ reg = dpll_pin_registration_find(ref, ops, priv);
+ if (WARN_ON(!reg))
+ return;
++ list_del(®->list);
++ kfree(reg);
+ if (refcount_dec_and_test(&ref->refcount)) {
+- list_del(®->list);
+- kfree(reg);
+ xa_erase(xa_dplls, i);
+ WARN_ON(!list_empty(&ref->registration_list));
+ kfree(ref);
+diff --git a/drivers/firmware/arm_scmi/smc.c b/drivers/firmware/arm_scmi/smc.c
+index 7611e9665038d..39936e1dd30e9 100644
+--- a/drivers/firmware/arm_scmi/smc.c
++++ b/drivers/firmware/arm_scmi/smc.c
+@@ -214,6 +214,13 @@ static int smc_chan_free(int id, void *p, void *data)
+ struct scmi_chan_info *cinfo = p;
+ struct scmi_smc *scmi_info = cinfo->transport_info;
+
++ /*
++ * Different protocols might share the same chan info, so a previous
++ * smc_chan_free call might have already freed the structure.
++ */
++ if (!scmi_info)
++ return 0;
++
+ /* Ignore any possible further reception on the IRQ path */
+ if (scmi_info->irq > 0)
+ free_irq(scmi_info->irq, scmi_info);
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index 99429bc4b0c7e..c9857ee3880c2 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -21,6 +21,8 @@
+ #include "efistub.h"
+ #include "x86-stub.h"
+
++extern char _bss[], _ebss[];
++
+ const efi_system_table_t *efi_system_table;
+ const efi_dxe_services_table_t *efi_dxe_table;
+ static efi_loaded_image_t *image = NULL;
+@@ -465,6 +467,9 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ efi_status_t status;
+ char *cmdline_ptr;
+
++ if (efi_is_native())
++ memset(_bss, 0, _ebss - _bss);
++
+ efi_system_table = sys_table_arg;
+
+ /* Check if we were booted by the EFI firmware */
+@@ -958,8 +963,6 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
+ void efi_handover_entry(efi_handle_t handle, efi_system_table_t *sys_table_arg,
+ struct boot_params *boot_params)
+ {
+- extern char _bss[], _ebss[];
+-
+ memset(_bss, 0, _ebss - _bss);
+ efi_stub_entry(handle, sys_table_arg, boot_params);
+ }
+diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
+index 1301cec94f128..353af1a4d0ace 100644
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -711,7 +711,8 @@ config GPIO_UNIPHIER
+ Say yes here to support UniPhier GPIOs.
+
+ config GPIO_VF610
+- def_bool y
++ bool "VF610 GPIO support"
++ default y if SOC_VF610
+ depends on ARCH_MXC
+ select GPIOLIB_IRQCHIP
+ help
+diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c
+index fe9ce6b19f15c..4987e62dcb3d1 100644
+--- a/drivers/gpio/gpiolib-devres.c
++++ b/drivers/gpio/gpiolib-devres.c
+@@ -158,7 +158,7 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
+ if (!dr)
+ return ERR_PTR(-ENOMEM);
+
+- desc = fwnode_gpiod_get_index(fwnode, con_id, index, flags, label);
++ desc = gpiod_find_and_request(dev, fwnode, con_id, index, flags, label, false);
+ if (IS_ERR(desc)) {
+ devres_free(dr);
+ return desc;
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index 75be4a3ca7f84..3ad09d2193330 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -4138,13 +4138,13 @@ static struct gpio_desc *gpiod_find_by_fwnode(struct fwnode_handle *fwnode,
+ return desc;
+ }
+
+-static struct gpio_desc *gpiod_find_and_request(struct device *consumer,
+- struct fwnode_handle *fwnode,
+- const char *con_id,
+- unsigned int idx,
+- enum gpiod_flags flags,
+- const char *label,
+- bool platform_lookup_allowed)
++struct gpio_desc *gpiod_find_and_request(struct device *consumer,
++ struct fwnode_handle *fwnode,
++ const char *con_id,
++ unsigned int idx,
++ enum gpiod_flags flags,
++ const char *label,
++ bool platform_lookup_allowed)
+ {
+ unsigned long lookupflags = GPIO_LOOKUP_FLAGS_DEFAULT;
+ struct gpio_desc *desc;
+diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
+index a4a2520b5f31c..c6e5fb9aa2122 100644
+--- a/drivers/gpio/gpiolib.h
++++ b/drivers/gpio/gpiolib.h
+@@ -202,6 +202,14 @@ static inline int gpiod_request_user(struct gpio_desc *desc, const char *label)
+ return ret;
+ }
+
++struct gpio_desc *gpiod_find_and_request(struct device *consumer,
++ struct fwnode_handle *fwnode,
++ const char *con_id,
++ unsigned int idx,
++ enum gpiod_flags flags,
++ const char *label,
++ bool platform_lookup_allowed);
++
+ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
+ unsigned long lflags, enum gpiod_flags dflags);
+ int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+index c7d60dd0fb975..4f9900779ef9e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+@@ -1278,11 +1278,10 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
+ * 0b10 : encode is disabled
+ * 0b01 : decode is disabled
+ */
+- adev->vcn.vcn_config[adev->vcn.num_vcn_inst] =
+- ip->revision & 0xc0;
+- ip->revision &= ~0xc0;
+ if (adev->vcn.num_vcn_inst <
+ AMDGPU_MAX_VCN_INSTANCES) {
++ adev->vcn.vcn_config[adev->vcn.num_vcn_inst] =
++ ip->revision & 0xc0;
+ adev->vcn.num_vcn_inst++;
+ adev->vcn.inst_mask |=
+ (1U << ip->instance_number);
+@@ -1293,6 +1292,7 @@ static int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
+ adev->vcn.num_vcn_inst + 1,
+ AMDGPU_MAX_VCN_INSTANCES);
+ }
++ ip->revision &= ~0xc0;
+ }
+ if (le16_to_cpu(ip->hw_id) == SDMA0_HWID ||
+ le16_to_cpu(ip->hw_id) == SDMA1_HWID ||
+diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c
+index a33e890c70d90..ac51d19b518ca 100644
+--- a/drivers/gpu/drm/amd/amdgpu/atom.c
++++ b/drivers/gpu/drm/amd/amdgpu/atom.c
+@@ -313,7 +313,7 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr,
+ DEBUG("IMM 0x%02X\n", val);
+ return val;
+ }
+- return 0;
++ break;
+ case ATOM_ARG_PLL:
+ idx = U8(*ptr);
+ (*ptr)++;
+diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+index c9c653cfc765b..3f1692194b7ad 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+@@ -570,6 +570,7 @@ static void gmc_v11_0_set_mmhub_funcs(struct amdgpu_device *adev)
+ adev->mmhub.funcs = &mmhub_v3_0_2_funcs;
+ break;
+ case IP_VERSION(3, 3, 0):
++ case IP_VERSION(3, 3, 1):
+ adev->mmhub.funcs = &mmhub_v3_3_funcs;
+ break;
+ default:
+diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c
+index dc4812ecc98d6..238ea40c24500 100644
+--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c
++++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_3.c
+@@ -98,16 +98,16 @@ mmhub_v3_3_print_l2_protection_fault_status(struct amdgpu_device *adev,
+
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
+ case IP_VERSION(3, 3, 0):
+- mmhub_cid = mmhub_client_ids_v3_3[cid][rw];
++ case IP_VERSION(3, 3, 1):
++ mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_3) ?
++ mmhub_client_ids_v3_3[cid][rw] :
++ cid == 0x140 ? "UMSCH" : NULL;
+ break;
+ default:
+ mmhub_cid = NULL;
+ break;
+ }
+
+- if (!mmhub_cid && cid == 0x140)
+- mmhub_cid = "UMSCH";
+-
+ dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
+ mmhub_cid ? mmhub_cid : "unknown", cid);
+ dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
+diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+index 2d688dca26bed..45a67a77455ee 100644
+--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
++++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+@@ -429,16 +429,11 @@ static void sdma_v4_4_2_inst_gfx_stop(struct amdgpu_device *adev,
+ struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES];
+ u32 doorbell_offset, doorbell;
+ u32 rb_cntl, ib_cntl;
+- int i, unset = 0;
++ int i;
+
+ for_each_inst(i, inst_mask) {
+ sdma[i] = &adev->sdma.instance[i].ring;
+
+- if ((adev->mman.buffer_funcs_ring == sdma[i]) && unset != 1) {
+- amdgpu_ttm_set_buffer_funcs_status(adev, false);
+- unset = 1;
+- }
+-
+ rb_cntl = RREG32_SDMA(i, regSDMA_GFX_RB_CNTL);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA_GFX_RB_CNTL, RB_ENABLE, 0);
+ WREG32_SDMA(i, regSDMA_GFX_RB_CNTL, rb_cntl);
+@@ -485,20 +480,10 @@ static void sdma_v4_4_2_inst_rlc_stop(struct amdgpu_device *adev,
+ static void sdma_v4_4_2_inst_page_stop(struct amdgpu_device *adev,
+ uint32_t inst_mask)
+ {
+- struct amdgpu_ring *sdma[AMDGPU_MAX_SDMA_INSTANCES];
+ u32 rb_cntl, ib_cntl;
+ int i;
+- bool unset = false;
+
+ for_each_inst(i, inst_mask) {
+- sdma[i] = &adev->sdma.instance[i].page;
+-
+- if ((adev->mman.buffer_funcs_ring == sdma[i]) &&
+- (!unset)) {
+- amdgpu_ttm_set_buffer_funcs_status(adev, false);
+- unset = true;
+- }
+-
+ rb_cntl = RREG32_SDMA(i, regSDMA_PAGE_RB_CNTL);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA_PAGE_RB_CNTL,
+ RB_ENABLE, 0);
+@@ -948,13 +933,7 @@ static int sdma_v4_4_2_inst_start(struct amdgpu_device *adev,
+ r = amdgpu_ring_test_helper(page);
+ if (r)
+ return r;
+-
+- if (adev->mman.buffer_funcs_ring == page)
+- amdgpu_ttm_set_buffer_funcs_status(adev, true);
+ }
+-
+- if (adev->mman.buffer_funcs_ring == ring)
+- amdgpu_ttm_set_buffer_funcs_status(adev, true);
+ }
+
+ return r;
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 1a9bbb04bd5e2..8083e7156afcf 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -1929,17 +1929,15 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
+ adev->dm.hdcp_workqueue = NULL;
+ }
+
+- if (adev->dm.dc)
++ if (adev->dm.dc) {
+ dc_deinit_callbacks(adev->dm.dc);
+-
+- if (adev->dm.dc)
+ dc_dmub_srv_destroy(&adev->dm.dc->ctx->dmub_srv);
+-
+- if (dc_enable_dmub_notifications(adev->dm.dc)) {
+- kfree(adev->dm.dmub_notify);
+- adev->dm.dmub_notify = NULL;
+- destroy_workqueue(adev->dm.delayed_hpd_wq);
+- adev->dm.delayed_hpd_wq = NULL;
++ if (dc_enable_dmub_notifications(adev->dm.dc)) {
++ kfree(adev->dm.dmub_notify);
++ adev->dm.dmub_notify = NULL;
++ destroy_workqueue(adev->dm.delayed_hpd_wq);
++ adev->dm.delayed_hpd_wq = NULL;
++ }
+ }
+
+ if (adev->dm.dmub_bo)
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+index 68a8463239127..85fc6181303bb 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+@@ -1483,7 +1483,7 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
+ const uint32_t rd_buf_size = 10;
+ struct pipe_ctx *pipe_ctx;
+ ssize_t result = 0;
+- int i, r, str_len = 30;
++ int i, r, str_len = 10;
+
+ rd_buf = kcalloc(rd_buf_size, sizeof(char), GFP_KERNEL);
+
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+index 6dd479e8a3485..f614bc2806d86 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+@@ -1840,6 +1840,9 @@ bool dcn10_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
+ {
+ struct dpp *dpp = pipe_ctx->plane_res.dpp;
+
++ if (!stream)
++ return false;
++
+ if (dpp == NULL)
+ return false;
+
+@@ -1862,8 +1865,8 @@ bool dcn10_set_output_transfer_func(struct dc *dc, struct pipe_ctx *pipe_ctx,
+ } else
+ dpp->funcs->dpp_program_regamma_pwl(dpp, NULL, OPP_REGAMMA_BYPASS);
+
+- if (stream != NULL && stream->ctx != NULL &&
+- stream->out_transfer_func != NULL) {
++ if (stream->ctx &&
++ stream->out_transfer_func) {
+ log_tf(stream->ctx,
+ stream->out_transfer_func,
+ dpp->regamma_params.hw_points_num);
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+index 046d3e2054153..f1489f4a40c12 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+@@ -892,7 +892,8 @@ bool edp_set_replay_allow_active(struct dc_link *link, const bool *allow_active,
+
+ /* Set power optimization flag */
+ if (power_opts && link->replay_settings.replay_power_opt_active != *power_opts) {
+- if (link->replay_settings.replay_feature_enabled && replay->funcs->replay_set_power_opt) {
++ if (replay != NULL && link->replay_settings.replay_feature_enabled &&
++ replay->funcs->replay_set_power_opt) {
+ replay->funcs->replay_set_power_opt(replay, *power_opts, panel_inst);
+ link->replay_settings.replay_power_opt_active = *power_opts;
+ }
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+index bcad42534da46..1d96eb274d72d 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+@@ -2272,8 +2272,8 @@ static uint16_t arcturus_get_current_pcie_link_speed(struct smu_context *smu)
+
+ /* TODO: confirm this on real target */
+ esm_ctrl = RREG32_PCIE(smnPCIE_ESM_CTRL);
+- if ((esm_ctrl >> 15) & 0x1FFFF)
+- return (uint16_t)(((esm_ctrl >> 8) & 0x3F) + 128);
++ if ((esm_ctrl >> 15) & 0x1)
++ return (uint16_t)(((esm_ctrl >> 8) & 0x7F) + 128);
+
+ return smu_v11_0_get_current_pcie_link_speed(smu);
+ }
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+index dd9bcbd630a1f..ca0d5a5b204ad 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+@@ -1682,8 +1682,8 @@ static int aldebaran_get_current_pcie_link_speed(struct smu_context *smu)
+
+ /* TODO: confirm this on real target */
+ esm_ctrl = RREG32_PCIE(smnPCIE_ESM_CTRL);
+- if ((esm_ctrl >> 15) & 0x1FFFF)
+- return (((esm_ctrl >> 8) & 0x3F) + 128);
++ if ((esm_ctrl >> 15) & 0x1)
++ return (((esm_ctrl >> 8) & 0x7F) + 128);
+
+ return smu_v13_0_get_current_pcie_link_speed(smu);
+ }
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+index 7e1941cf17964..78491b04df108 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+@@ -2060,8 +2060,8 @@ static int smu_v13_0_6_get_current_pcie_link_speed(struct smu_context *smu)
+
+ /* TODO: confirm this on real target */
+ esm_ctrl = RREG32_PCIE(smnPCIE_ESM_CTRL);
+- if ((esm_ctrl >> 15) & 0x1FFFF)
+- return (((esm_ctrl >> 8) & 0x3F) + 128);
++ if ((esm_ctrl >> 15) & 0x1)
++ return (((esm_ctrl >> 8) & 0x7F) + 128);
+
+ speed_level = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
+ PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
+diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+index 8be235144f6d9..6fc292393c674 100644
+--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
++++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+@@ -1277,17 +1277,6 @@ static int adv7511_probe(struct i2c_client *i2c)
+
+ INIT_WORK(&adv7511->hpd_work, adv7511_hpd_work);
+
+- if (i2c->irq) {
+- init_waitqueue_head(&adv7511->wq);
+-
+- ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
+- adv7511_irq_handler,
+- IRQF_ONESHOT, dev_name(dev),
+- adv7511);
+- if (ret)
+- goto err_unregister_cec;
+- }
+-
+ adv7511_power_off(adv7511);
+
+ i2c_set_clientdata(i2c, adv7511);
+@@ -1311,6 +1300,17 @@ static int adv7511_probe(struct i2c_client *i2c)
+
+ adv7511_audio_init(dev, adv7511);
+
++ if (i2c->irq) {
++ init_waitqueue_head(&adv7511->wq);
++
++ ret = devm_request_threaded_irq(dev, i2c->irq, NULL,
++ adv7511_irq_handler,
++ IRQF_ONESHOT, dev_name(dev),
++ adv7511);
++ if (ret)
++ goto err_unregister_audio;
++ }
++
+ if (adv7511->info->has_dsi) {
+ ret = adv7533_attach_dsi(adv7511);
+ if (ret)
+diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml
+index 2c9a1838e7284..5e1c727640c40 100644
+--- a/drivers/gpu/drm/ci/test.yml
++++ b/drivers/gpu/drm/ci/test.yml
+@@ -104,7 +104,10 @@ msm:apq8016:
+ DRIVER_NAME: msm
+ BM_DTB: https://${PIPELINE_ARTIFACTS_BASE}/arm64/apq8016-sbc-usb-host.dtb
+ GPU_VERSION: apq8016
+- BM_CMDLINE: "ip=dhcp console=ttyMSM0,115200n8 $BM_KERNEL_EXTRA_ARGS root=/dev/nfs rw nfsrootdebug nfsroot=,tcp,nfsvers=4.2 init=/init $BM_KERNELARGS"
++ # disabling unused clocks congests with the MDSS runtime PM trying to
++ # disable those clocks and causes boot to fail.
++ # Reproducer: DRM_MSM=y, DRM_I2C_ADV7511=m
++ BM_KERNEL_EXTRA_ARGS: clk_ignore_unused
+ RUNNER_TAG: google-freedreno-db410c
+ script:
+ - ./install/bare-metal/fastboot.sh
+diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c
+index 4f9736e5f929b..7ea244d876ca6 100644
+--- a/drivers/gpu/drm/lima/lima_gem.c
++++ b/drivers/gpu/drm/lima/lima_gem.c
+@@ -75,29 +75,34 @@ int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm)
+ } else {
+ bo->base.sgt = kmalloc(sizeof(*bo->base.sgt), GFP_KERNEL);
+ if (!bo->base.sgt) {
+- sg_free_table(&sgt);
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto err_out0;
+ }
+ }
+
+ ret = dma_map_sgtable(dev, &sgt, DMA_BIDIRECTIONAL, 0);
+- if (ret) {
+- sg_free_table(&sgt);
+- kfree(bo->base.sgt);
+- bo->base.sgt = NULL;
+- return ret;
+- }
++ if (ret)
++ goto err_out1;
+
+ *bo->base.sgt = sgt;
+
+ if (vm) {
+ ret = lima_vm_map_bo(vm, bo, old_size >> PAGE_SHIFT);
+ if (ret)
+- return ret;
++ goto err_out2;
+ }
+
+ bo->heap_size = new_size;
+ return 0;
++
++err_out2:
++ dma_unmap_sgtable(dev, &sgt, DMA_BIDIRECTIONAL, 0);
++err_out1:
++ kfree(bo->base.sgt);
++ bo->base.sgt = NULL;
++err_out0:
++ sg_free_table(&sgt);
++ return ret;
+ }
+
+ int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file,
+diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+index c729af3b98224..3d17de34d72bd 100644
+--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
++++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+@@ -95,11 +95,13 @@ static void mtk_drm_crtc_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
+ struct drm_crtc *crtc = &mtk_crtc->base;
+ unsigned long flags;
+
+- spin_lock_irqsave(&crtc->dev->event_lock, flags);
+- drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
+- drm_crtc_vblank_put(crtc);
+- mtk_crtc->event = NULL;
+- spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
++ if (mtk_crtc->event) {
++ spin_lock_irqsave(&crtc->dev->event_lock, flags);
++ drm_crtc_send_vblank_event(crtc, mtk_crtc->event);
++ drm_crtc_vblank_put(crtc);
++ mtk_crtc->event = NULL;
++ spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
++ }
+ }
+
+ static void mtk_drm_finish_page_flip(struct mtk_drm_crtc *mtk_crtc)
+diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
+index a2fdfc8ddb153..cd19885ee017f 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
+@@ -71,8 +71,8 @@
+ #define DSI_PS_WC 0x3fff
+ #define DSI_PS_SEL (3 << 16)
+ #define PACKED_PS_16BIT_RGB565 (0 << 16)
+-#define LOOSELY_PS_18BIT_RGB666 (1 << 16)
+-#define PACKED_PS_18BIT_RGB666 (2 << 16)
++#define PACKED_PS_18BIT_RGB666 (1 << 16)
++#define LOOSELY_PS_24BIT_RGB666 (2 << 16)
+ #define PACKED_PS_24BIT_RGB888 (3 << 16)
+
+ #define DSI_VSA_NL 0x20
+@@ -369,10 +369,10 @@ static void mtk_dsi_ps_control_vact(struct mtk_dsi *dsi)
+ ps_bpp_mode |= PACKED_PS_24BIT_RGB888;
+ break;
+ case MIPI_DSI_FMT_RGB666:
+- ps_bpp_mode |= PACKED_PS_18BIT_RGB666;
++ ps_bpp_mode |= LOOSELY_PS_24BIT_RGB666;
+ break;
+ case MIPI_DSI_FMT_RGB666_PACKED:
+- ps_bpp_mode |= LOOSELY_PS_18BIT_RGB666;
++ ps_bpp_mode |= PACKED_PS_18BIT_RGB666;
+ break;
+ case MIPI_DSI_FMT_RGB565:
+ ps_bpp_mode |= PACKED_PS_16BIT_RGB565;
+@@ -426,7 +426,7 @@ static void mtk_dsi_ps_control(struct mtk_dsi *dsi)
+ dsi_tmp_buf_bpp = 3;
+ break;
+ case MIPI_DSI_FMT_RGB666:
+- tmp_reg = LOOSELY_PS_18BIT_RGB666;
++ tmp_reg = LOOSELY_PS_24BIT_RGB666;
+ dsi_tmp_buf_bpp = 3;
+ break;
+ case MIPI_DSI_FMT_RGB666_PACKED:
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+index c9c55e2ea5849..fd60e49b8ec4d 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+@@ -1292,9 +1292,8 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
+ gpu->ubwc_config.ubwc_mode = 1;
+ }
+
+- /* a618 is using the hw default values */
+ if (adreno_is_a618(gpu))
+- return;
++ gpu->ubwc_config.highest_bank_bit = 14;
+
+ if (adreno_is_a619_holi(gpu))
+ gpu->ubwc_config.highest_bank_bit = 13;
+@@ -2427,7 +2426,7 @@ static int a6xx_gmu_pm_resume(struct msm_gpu *gpu)
+
+ msm_devfreq_resume(gpu);
+
+- adreno_is_a7xx(adreno_gpu) ? a7xx_llc_activate : a6xx_llc_activate(a6xx_gpu);
++ adreno_is_a7xx(adreno_gpu) ? a7xx_llc_activate(a6xx_gpu) : a6xx_llc_activate(a6xx_gpu);
+
+ return ret;
+ }
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+index 6a4b489d44e51..aca689314ccea 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+@@ -226,6 +226,13 @@ bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc)
+ return dpu_enc->wide_bus_en;
+ }
+
++bool dpu_encoder_is_dsc_enabled(const struct drm_encoder *drm_enc)
++{
++ const struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
++
++ return dpu_enc->dsc ? true : false;
++}
++
+ int dpu_encoder_get_crc_values_cnt(const struct drm_encoder *drm_enc)
+ {
+ struct dpu_encoder_virt *dpu_enc;
+@@ -1853,7 +1860,9 @@ static void dpu_encoder_prep_dsc(struct dpu_encoder_virt *dpu_enc,
+ dsc_common_mode = 0;
+ pic_width = dsc->pic_width;
+
+- dsc_common_mode = DSC_MODE_MULTIPLEX | DSC_MODE_SPLIT_PANEL;
++ dsc_common_mode = DSC_MODE_SPLIT_PANEL;
++ if (dpu_encoder_use_dsc_merge(enc_master->parent))
++ dsc_common_mode |= DSC_MODE_MULTIPLEX;
+ if (enc_master->intf_mode == INTF_MODE_VIDEO)
+ dsc_common_mode |= DSC_MODE_VIDEO;
+
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+index 4c05fd5e9ed18..fe6b1d312a742 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+@@ -158,6 +158,13 @@ int dpu_encoder_get_vsync_count(struct drm_encoder *drm_enc);
+
+ bool dpu_encoder_is_widebus_enabled(const struct drm_encoder *drm_enc);
+
++/**
++ * dpu_encoder_is_dsc_enabled - indicate whether dsc is enabled
++ * for the encoder.
++ * @drm_enc: Pointer to previously created drm encoder structure
++ */
++bool dpu_encoder_is_dsc_enabled(const struct drm_encoder *drm_enc);
++
+ /**
+ * dpu_encoder_get_crc_values_cnt - get number of physical encoders contained
+ * in virtual encoder that can collect CRC values
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+index d0f56c5c4cce9..f02411b062c4c 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+@@ -102,6 +102,7 @@ static void drm_mode_to_intf_timing_params(
+ }
+
+ timing->wide_bus_en = dpu_encoder_is_widebus_enabled(phys_enc->parent);
++ timing->compression_en = dpu_encoder_is_dsc_enabled(phys_enc->parent);
+
+ /*
+ * for DP, divide the horizonal parameters by 2 when
+@@ -259,12 +260,14 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
+ mode.htotal >>= 1;
+ mode.hsync_start >>= 1;
+ mode.hsync_end >>= 1;
++ mode.hskew >>= 1;
+
+ DPU_DEBUG_VIDENC(phys_enc,
+- "split_role %d, halve horizontal %d %d %d %d\n",
++ "split_role %d, halve horizontal %d %d %d %d %d\n",
+ phys_enc->split_role,
+ mode.hdisplay, mode.htotal,
+- mode.hsync_start, mode.hsync_end);
++ mode.hsync_start, mode.hsync_end,
++ mode.hskew);
+ }
+
+ drm_mode_to_intf_timing_params(phys_enc, &mode, &timing_params);
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
+index e9cdc7934a499..9016b3ade6bc3 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
+@@ -186,7 +186,7 @@ static int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx, struct dpu_hw_cdm_cfg *cdm)
+ dpu_hw_cdm_setup_cdwn(ctx, cdm);
+
+ if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
+- if (fmt->chroma_sample != DPU_CHROMA_H1V2)
++ if (fmt->chroma_sample == DPU_CHROMA_H1V2)
+ return -EINVAL; /*unsupported format */
+ opmode = CDM_HDMI_PACK_OP_MODE_EN;
+ opmode |= (fmt->chroma_sample << 1);
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+index 6bba531d6dc41..965692ef7892c 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+@@ -163,13 +163,8 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
+ hsync_ctl = (hsync_period << 16) | p->hsync_pulse_width;
+ display_hctl = (hsync_end_x << 16) | hsync_start_x;
+
+- /*
+- * DATA_HCTL_EN controls data timing which can be different from
+- * video timing. It is recommended to enable it for all cases, except
+- * if compression is enabled in 1 pixel per clock mode
+- */
+ if (p->wide_bus_en)
+- intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN | INTF_CFG2_DATA_HCTL_EN;
++ intf_cfg2 |= INTF_CFG2_DATABUS_WIDEN;
+
+ data_width = p->width;
+
+@@ -229,6 +224,14 @@ static void dpu_hw_intf_setup_timing_engine(struct dpu_hw_intf *ctx,
+ DPU_REG_WRITE(c, INTF_CONFIG, intf_cfg);
+ DPU_REG_WRITE(c, INTF_PANEL_FORMAT, panel_format);
+ if (ctx->cap->features & BIT(DPU_DATA_HCTL_EN)) {
++ /*
++ * DATA_HCTL_EN controls data timing which can be different from
++ * video timing. It is recommended to enable it for all cases, except
++ * if compression is enabled in 1 pixel per clock mode
++ */
++ if (!(p->compression_en && !p->wide_bus_en))
++ intf_cfg2 |= INTF_CFG2_DATA_HCTL_EN;
++
+ DPU_REG_WRITE(c, INTF_CONFIG2, intf_cfg2);
+ DPU_REG_WRITE(c, INTF_DISPLAY_DATA_HCTL, display_data_hctl);
+ DPU_REG_WRITE(c, INTF_ACTIVE_DATA_HCTL, active_data_hctl);
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
+index 0bd57a32144a6..6f4c87244f944 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
+@@ -33,6 +33,7 @@ struct dpu_hw_intf_timing_params {
+ u32 hsync_skew;
+
+ bool wide_bus_en;
++ bool compression_en;
+ };
+
+ struct dpu_hw_intf_prog_fetch {
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+index 723cc1d821431..2330eb2a4e9c8 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+@@ -374,6 +374,12 @@ static int dpu_kms_global_obj_init(struct dpu_kms *dpu_kms)
+ return 0;
+ }
+
++static void dpu_kms_global_obj_fini(struct dpu_kms *dpu_kms)
++{
++ drm_atomic_private_obj_fini(&dpu_kms->global_state);
++ drm_modeset_lock_fini(&dpu_kms->global_state_lock);
++}
++
+ static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms)
+ {
+ struct icc_path *path0;
+@@ -801,6 +807,8 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
+ dpu_kms->hw_vbif[i] = NULL;
+ }
+
++ dpu_kms_global_obj_fini(dpu_kms);
++
+ dpu_kms->catalog = NULL;
+
+ dpu_kms->hw_mdp = NULL;
+diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
+index 00cc7d1abaa39..5d8ee17295424 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
++++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
+@@ -1264,6 +1264,8 @@ nouveau_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *reg)
+ drm_vma_node_unmap(&nvbo->bo.base.vma_node,
+ bdev->dev_mapping);
+ nouveau_ttm_io_mem_free_locked(drm, nvbo->bo.resource);
++ nvbo->bo.resource->bus.offset = 0;
++ nvbo->bo.resource->bus.addr = NULL;
+ goto retry;
+ }
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c
+index 666eb93b1742c..11b4c9c274a1a 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c
+@@ -41,7 +41,6 @@ r535_devinit_new(const struct nvkm_devinit_func *hw,
+
+ rm->dtor = r535_devinit_dtor;
+ rm->post = hw->post;
+- rm->disable = hw->disable;
+
+ ret = nv50_devinit_new_(rm, device, type, inst, pdevinit);
+ if (ret)
+diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
+index 4945a1e787eb3..0ffe8f8c01de8 100644
+--- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
++++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c
+@@ -1871,6 +1871,8 @@ static int boe_panel_add(struct boe_panel *boe)
+
+ gpiod_set_value(boe->enable_gpio, 0);
+
++ boe->base.prepare_prev_first = true;
++
+ drm_panel_init(&boe->base, dev, &boe_panel_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+ err = of_drm_get_panel_orientation(dev->of_node, &boe->orientation);
+diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
+index a0b6f69b916f9..e5e3f0b9ca61d 100644
+--- a/drivers/gpu/drm/panel/panel-edp.c
++++ b/drivers/gpu/drm/panel/panel-edp.c
+@@ -413,8 +413,7 @@ static int panel_edp_unprepare(struct drm_panel *panel)
+ if (!p->prepared)
+ return 0;
+
+- pm_runtime_mark_last_busy(panel->dev);
+- ret = pm_runtime_put_autosuspend(panel->dev);
++ ret = pm_runtime_put_sync_suspend(panel->dev);
+ if (ret < 0)
+ return ret;
+ p->prepared = false;
+diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
+index 927e5f42e97d0..3e48cbb522a1c 100644
+--- a/drivers/gpu/drm/radeon/ni.c
++++ b/drivers/gpu/drm/radeon/ni.c
+@@ -813,7 +813,7 @@ int ni_init_microcode(struct radeon_device *rdev)
+ err = 0;
+ } else if (rdev->smc_fw->size != smc_req_size) {
+ pr_err("ni_mc: Bogus length %zu in firmware \"%s\"\n",
+- rdev->mc_fw->size, fw_name);
++ rdev->smc_fw->size, fw_name);
+ err = -EINVAL;
+ }
+ }
+diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
+index e6fbe040ccf6a..b66c1ef5838fd 100644
+--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
++++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
+@@ -411,7 +411,7 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
+ hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
+ hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
+
+- value = mode->hsync_start - mode->hdisplay;
++ value = mode->htotal - mode->hsync_start;
+ hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
+ hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
+
+@@ -426,7 +426,7 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
+ value = mode->vtotal - mode->vdisplay;
+ hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
+
+- value = mode->vsync_start - mode->vdisplay;
++ value = mode->vtotal - mode->vsync_start;
+ hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
+
+ value = mode->vsync_end - mode->vsync_start;
+diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
+index 59341654ec32b..77b76cff1adb9 100644
+--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
++++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
+@@ -576,8 +576,7 @@ static int rockchip_lvds_bind(struct device *dev, struct device *master,
+ ret = -EINVAL;
+ goto err_put_port;
+ } else if (ret) {
+- DRM_DEV_ERROR(dev, "failed to find panel and bridge node\n");
+- ret = -EPROBE_DEFER;
++ dev_err_probe(dev, ret, "failed to find panel and bridge node\n");
+ goto err_put_port;
+ }
+ if (lvds->panel)
+diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
+index ef02d530f78d7..ae12d001a04bf 100644
+--- a/drivers/gpu/drm/tegra/dpaux.c
++++ b/drivers/gpu/drm/tegra/dpaux.c
+@@ -522,7 +522,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
+ if (err < 0) {
+ dev_err(dpaux->dev, "failed to request IRQ#%u: %d\n",
+ dpaux->irq, err);
+- return err;
++ goto err_pm_disable;
+ }
+
+ disable_irq(dpaux->irq);
+@@ -542,7 +542,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
+ */
+ err = tegra_dpaux_pad_config(dpaux, DPAUX_PADCTL_FUNC_I2C);
+ if (err < 0)
+- return err;
++ goto err_pm_disable;
+
+ #ifdef CONFIG_GENERIC_PINCONF
+ dpaux->desc.name = dev_name(&pdev->dev);
+@@ -555,7 +555,8 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
+ dpaux->pinctrl = devm_pinctrl_register(&pdev->dev, &dpaux->desc, dpaux);
+ if (IS_ERR(dpaux->pinctrl)) {
+ dev_err(&pdev->dev, "failed to register pincontrol\n");
+- return PTR_ERR(dpaux->pinctrl);
++ err = PTR_ERR(dpaux->pinctrl);
++ goto err_pm_disable;
+ }
+ #endif
+ /* enable and clear all interrupts */
+@@ -571,10 +572,15 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
+ err = devm_of_dp_aux_populate_ep_devices(&dpaux->aux);
+ if (err < 0) {
+ dev_err(dpaux->dev, "failed to populate AUX bus: %d\n", err);
+- return err;
++ goto err_pm_disable;
+ }
+
+ return 0;
++
++err_pm_disable:
++ pm_runtime_put_sync(&pdev->dev);
++ pm_runtime_disable(&pdev->dev);
++ return err;
+ }
+
+ static void tegra_dpaux_remove(struct platform_device *pdev)
+diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
+index fbfe92a816d4b..db606e151afc8 100644
+--- a/drivers/gpu/drm/tegra/dsi.c
++++ b/drivers/gpu/drm/tegra/dsi.c
+@@ -1544,9 +1544,11 @@ static int tegra_dsi_ganged_probe(struct tegra_dsi *dsi)
+ np = of_parse_phandle(dsi->dev->of_node, "nvidia,ganged-mode", 0);
+ if (np) {
+ struct platform_device *gangster = of_find_device_by_node(np);
++ of_node_put(np);
++ if (!gangster)
++ return -EPROBE_DEFER;
+
+ dsi->slave = platform_get_drvdata(gangster);
+- of_node_put(np);
+
+ if (!dsi->slave) {
+ put_device(&gangster->dev);
+@@ -1594,44 +1596,58 @@ static int tegra_dsi_probe(struct platform_device *pdev)
+
+ if (!pdev->dev.pm_domain) {
+ dsi->rst = devm_reset_control_get(&pdev->dev, "dsi");
+- if (IS_ERR(dsi->rst))
+- return PTR_ERR(dsi->rst);
++ if (IS_ERR(dsi->rst)) {
++ err = PTR_ERR(dsi->rst);
++ goto remove;
++ }
+ }
+
+ dsi->clk = devm_clk_get(&pdev->dev, NULL);
+- if (IS_ERR(dsi->clk))
+- return dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk),
+- "cannot get DSI clock\n");
++ if (IS_ERR(dsi->clk)) {
++ err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk),
++ "cannot get DSI clock\n");
++ goto remove;
++ }
+
+ dsi->clk_lp = devm_clk_get(&pdev->dev, "lp");
+- if (IS_ERR(dsi->clk_lp))
+- return dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_lp),
+- "cannot get low-power clock\n");
++ if (IS_ERR(dsi->clk_lp)) {
++ err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_lp),
++ "cannot get low-power clock\n");
++ goto remove;
++ }
+
+ dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
+- if (IS_ERR(dsi->clk_parent))
+- return dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_parent),
+- "cannot get parent clock\n");
++ if (IS_ERR(dsi->clk_parent)) {
++ err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->clk_parent),
++ "cannot get parent clock\n");
++ goto remove;
++ }
+
+ dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
+- if (IS_ERR(dsi->vdd))
+- return dev_err_probe(&pdev->dev, PTR_ERR(dsi->vdd),
+- "cannot get VDD supply\n");
++ if (IS_ERR(dsi->vdd)) {
++ err = dev_err_probe(&pdev->dev, PTR_ERR(dsi->vdd),
++ "cannot get VDD supply\n");
++ goto remove;
++ }
+
+ err = tegra_dsi_setup_clocks(dsi);
+ if (err < 0) {
+ dev_err(&pdev->dev, "cannot setup clocks\n");
+- return err;
++ goto remove;
+ }
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ dsi->regs = devm_ioremap_resource(&pdev->dev, regs);
+- if (IS_ERR(dsi->regs))
+- return PTR_ERR(dsi->regs);
++ if (IS_ERR(dsi->regs)) {
++ err = PTR_ERR(dsi->regs);
++ goto remove;
++ }
+
+ dsi->mipi = tegra_mipi_request(&pdev->dev, pdev->dev.of_node);
+- if (IS_ERR(dsi->mipi))
+- return PTR_ERR(dsi->mipi);
++ if (IS_ERR(dsi->mipi)) {
++ err = PTR_ERR(dsi->mipi);
++ goto remove;
++ }
+
+ dsi->host.ops = &tegra_dsi_host_ops;
+ dsi->host.dev = &pdev->dev;
+@@ -1659,9 +1675,12 @@ static int tegra_dsi_probe(struct platform_device *pdev)
+ return 0;
+
+ unregister:
++ pm_runtime_disable(&pdev->dev);
+ mipi_dsi_host_unregister(&dsi->host);
+ mipi_free:
+ tegra_mipi_free(dsi->mipi);
++remove:
++ tegra_output_remove(&dsi->output);
+ return err;
+ }
+
+diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
+index a719af1dc9a57..46170753699dc 100644
+--- a/drivers/gpu/drm/tegra/fb.c
++++ b/drivers/gpu/drm/tegra/fb.c
+@@ -159,6 +159,7 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
+
+ if (gem->size < size) {
+ err = -EINVAL;
++ drm_gem_object_put(gem);
+ goto unreference;
+ }
+
+diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
+index a1fcee665023b..417fb884240a6 100644
+--- a/drivers/gpu/drm/tegra/hdmi.c
++++ b/drivers/gpu/drm/tegra/hdmi.c
+@@ -1856,12 +1856,14 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
+ return err;
+
+ hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
+- if (IS_ERR(hdmi->regs))
+- return PTR_ERR(hdmi->regs);
++ if (IS_ERR(hdmi->regs)) {
++ err = PTR_ERR(hdmi->regs);
++ goto remove;
++ }
+
+ err = platform_get_irq(pdev, 0);
+ if (err < 0)
+- return err;
++ goto remove;
+
+ hdmi->irq = err;
+
+@@ -1870,18 +1872,18 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n",
+ hdmi->irq, err);
+- return err;
++ goto remove;
+ }
+
+ platform_set_drvdata(pdev, hdmi);
+
+ err = devm_pm_runtime_enable(&pdev->dev);
+ if (err)
+- return err;
++ goto remove;
+
+ err = devm_tegra_core_dev_init_opp_table_common(&pdev->dev);
+ if (err)
+- return err;
++ goto remove;
+
+ INIT_LIST_HEAD(&hdmi->client.list);
+ hdmi->client.ops = &hdmi_client_ops;
+@@ -1891,10 +1893,14 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to register host1x client: %d\n",
+ err);
+- return err;
++ goto remove;
+ }
+
+ return 0;
++
++remove:
++ tegra_output_remove(&hdmi->output);
++ return err;
+ }
+
+ static void tegra_hdmi_remove(struct platform_device *pdev)
+diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
+index dc2dcb5ca1c89..d7d2389ac2f5a 100644
+--- a/drivers/gpu/drm/tegra/output.c
++++ b/drivers/gpu/drm/tegra/output.c
+@@ -142,8 +142,10 @@ int tegra_output_probe(struct tegra_output *output)
+ GPIOD_IN,
+ "HDMI hotplug detect");
+ if (IS_ERR(output->hpd_gpio)) {
+- if (PTR_ERR(output->hpd_gpio) != -ENOENT)
+- return PTR_ERR(output->hpd_gpio);
++ if (PTR_ERR(output->hpd_gpio) != -ENOENT) {
++ err = PTR_ERR(output->hpd_gpio);
++ goto put_i2c;
++ }
+
+ output->hpd_gpio = NULL;
+ }
+@@ -152,7 +154,7 @@ int tegra_output_probe(struct tegra_output *output)
+ err = gpiod_to_irq(output->hpd_gpio);
+ if (err < 0) {
+ dev_err(output->dev, "gpiod_to_irq(): %d\n", err);
+- return err;
++ goto put_i2c;
+ }
+
+ output->hpd_irq = err;
+@@ -165,7 +167,7 @@ int tegra_output_probe(struct tegra_output *output)
+ if (err < 0) {
+ dev_err(output->dev, "failed to request IRQ#%u: %d\n",
+ output->hpd_irq, err);
+- return err;
++ goto put_i2c;
+ }
+
+ output->connector.polled = DRM_CONNECTOR_POLL_HPD;
+@@ -179,6 +181,12 @@ int tegra_output_probe(struct tegra_output *output)
+ }
+
+ return 0;
++
++put_i2c:
++ if (output->ddc)
++ i2c_put_adapter(output->ddc);
++
++ return err;
+ }
+
+ void tegra_output_remove(struct tegra_output *output)
+diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c
+index fc66bbd913b24..1e8ec50b759e4 100644
+--- a/drivers/gpu/drm/tegra/rgb.c
++++ b/drivers/gpu/drm/tegra/rgb.c
+@@ -225,26 +225,28 @@ int tegra_dc_rgb_probe(struct tegra_dc *dc)
+ rgb->clk = devm_clk_get(dc->dev, NULL);
+ if (IS_ERR(rgb->clk)) {
+ dev_err(dc->dev, "failed to get clock\n");
+- return PTR_ERR(rgb->clk);
++ err = PTR_ERR(rgb->clk);
++ goto remove;
+ }
+
+ rgb->clk_parent = devm_clk_get(dc->dev, "parent");
+ if (IS_ERR(rgb->clk_parent)) {
+ dev_err(dc->dev, "failed to get parent clock\n");
+- return PTR_ERR(rgb->clk_parent);
++ err = PTR_ERR(rgb->clk_parent);
++ goto remove;
+ }
+
+ err = clk_set_parent(rgb->clk, rgb->clk_parent);
+ if (err < 0) {
+ dev_err(dc->dev, "failed to set parent clock: %d\n", err);
+- return err;
++ goto remove;
+ }
+
+ rgb->pll_d_out0 = clk_get_sys(NULL, "pll_d_out0");
+ if (IS_ERR(rgb->pll_d_out0)) {
+ err = PTR_ERR(rgb->pll_d_out0);
+ dev_err(dc->dev, "failed to get pll_d_out0: %d\n", err);
+- return err;
++ goto remove;
+ }
+
+ if (dc->soc->has_pll_d2_out0) {
+@@ -252,13 +254,19 @@ int tegra_dc_rgb_probe(struct tegra_dc *dc)
+ if (IS_ERR(rgb->pll_d2_out0)) {
+ err = PTR_ERR(rgb->pll_d2_out0);
+ dev_err(dc->dev, "failed to get pll_d2_out0: %d\n", err);
+- return err;
++ goto put_pll;
+ }
+ }
+
+ dc->rgb = &rgb->output;
+
+ return 0;
++
++put_pll:
++ clk_put(rgb->pll_d_out0);
++remove:
++ tegra_output_remove(&rgb->output);
++ return err;
+ }
+
+ void tegra_dc_rgb_remove(struct tegra_dc *dc)
+diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c b/drivers/gpu/drm/tests/drm_buddy_test.c
+index 484360c7e1f65..e48863a445564 100644
+--- a/drivers/gpu/drm/tests/drm_buddy_test.c
++++ b/drivers/gpu/drm/tests/drm_buddy_test.c
+@@ -260,30 +260,30 @@ static void drm_test_buddy_alloc_contiguous(struct kunit *test)
+ KUNIT_ASSERT_FALSE_MSG(test,
+ drm_buddy_alloc_blocks(&mm, 0, mm_size,
+ ps, ps, list, 0),
+- "buddy_alloc hit an error size=%u\n",
++ "buddy_alloc hit an error size=%lu\n",
+ ps);
+ } while (++i < n_pages);
+
+ KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
+ 3 * ps, ps, &allocated,
+ DRM_BUDDY_CONTIGUOUS_ALLOCATION),
+- "buddy_alloc didn't error size=%u\n", 3 * ps);
++ "buddy_alloc didn't error size=%lu\n", 3 * ps);
+
+ drm_buddy_free_list(&mm, &middle);
+ KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
+ 3 * ps, ps, &allocated,
+ DRM_BUDDY_CONTIGUOUS_ALLOCATION),
+- "buddy_alloc didn't error size=%u\n", 3 * ps);
++ "buddy_alloc didn't error size=%lu\n", 3 * ps);
+ KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
+ 2 * ps, ps, &allocated,
+ DRM_BUDDY_CONTIGUOUS_ALLOCATION),
+- "buddy_alloc didn't error size=%u\n", 2 * ps);
++ "buddy_alloc didn't error size=%lu\n", 2 * ps);
+
+ drm_buddy_free_list(&mm, &right);
+ KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
+ 3 * ps, ps, &allocated,
+ DRM_BUDDY_CONTIGUOUS_ALLOCATION),
+- "buddy_alloc didn't error size=%u\n", 3 * ps);
++ "buddy_alloc didn't error size=%lu\n", 3 * ps);
+ /*
+ * At this point we should have enough contiguous space for 2 blocks,
+ * however they are never buddies (since we freed middle and right) so
+@@ -292,13 +292,13 @@ static void drm_test_buddy_alloc_contiguous(struct kunit *test)
+ KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
+ 2 * ps, ps, &allocated,
+ DRM_BUDDY_CONTIGUOUS_ALLOCATION),
+- "buddy_alloc hit an error size=%u\n", 2 * ps);
++ "buddy_alloc hit an error size=%lu\n", 2 * ps);
+
+ drm_buddy_free_list(&mm, &left);
+ KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
+ 3 * ps, ps, &allocated,
+ DRM_BUDDY_CONTIGUOUS_ALLOCATION),
+- "buddy_alloc hit an error size=%u\n", 3 * ps);
++ "buddy_alloc hit an error size=%lu\n", 3 * ps);
+
+ total = 0;
+ list_for_each_entry(block, &allocated, link)
+diff --git a/drivers/gpu/drm/tests/drm_mm_test.c b/drivers/gpu/drm/tests/drm_mm_test.c
+index 1eb0c304f9607..f37c0d7658656 100644
+--- a/drivers/gpu/drm/tests/drm_mm_test.c
++++ b/drivers/gpu/drm/tests/drm_mm_test.c
+@@ -157,7 +157,7 @@ static void drm_test_mm_init(struct kunit *test)
+
+ /* After creation, it should all be one massive hole */
+ if (!assert_one_hole(test, &mm, 0, size)) {
+- KUNIT_FAIL(test, "");
++ KUNIT_FAIL(test, "mm not one hole on creation");
+ goto out;
+ }
+
+@@ -171,14 +171,14 @@ static void drm_test_mm_init(struct kunit *test)
+
+ /* After filling the range entirely, there should be no holes */
+ if (!assert_no_holes(test, &mm)) {
+- KUNIT_FAIL(test, "");
++ KUNIT_FAIL(test, "mm has holes when filled");
+ goto out;
+ }
+
+ /* And then after emptying it again, the massive hole should be back */
+ drm_mm_remove_node(&tmp);
+ if (!assert_one_hole(test, &mm, 0, size)) {
+- KUNIT_FAIL(test, "");
++ KUNIT_FAIL(test, "mm does not have single hole after emptying");
+ goto out;
+ }
+
+diff --git a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c
+index 5f838980c7a11..94f8e3178df58 100644
+--- a/drivers/gpu/drm/tidss/tidss_crtc.c
++++ b/drivers/gpu/drm/tidss/tidss_crtc.c
+@@ -265,6 +265,16 @@ static void tidss_crtc_atomic_disable(struct drm_crtc *crtc,
+
+ reinit_completion(&tcrtc->framedone_completion);
+
++ /*
++ * If a layer is left enabled when the videoport is disabled, and the
++ * vid pipeline that was used for the layer is taken into use on
++ * another videoport, the DSS will report sync lost issues. Disable all
++ * the layers here as a work-around.
++ */
++ for (u32 layer = 0; layer < tidss->feat->num_planes; layer++)
++ dispc_ovr_enable_layer(tidss->dispc, tcrtc->hw_videoport, layer,
++ false);
++
+ dispc_vp_disable(tidss->dispc, tcrtc->hw_videoport);
+
+ if (!wait_for_completion_timeout(&tcrtc->framedone_completion,
+diff --git a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c
+index e1c0ef0c3894c..68fed531f6a7f 100644
+--- a/drivers/gpu/drm/tidss/tidss_plane.c
++++ b/drivers/gpu/drm/tidss/tidss_plane.c
+@@ -213,7 +213,7 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
+
+ drm_plane_helper_add(&tplane->plane, &tidss_plane_helper_funcs);
+
+- drm_plane_create_zpos_property(&tplane->plane, hw_plane_id, 0,
++ drm_plane_create_zpos_property(&tplane->plane, tidss->num_planes, 0,
+ num_planes - 1);
+
+ ret = drm_plane_create_color_properties(&tplane->plane,
+diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c
+index 3c99fb8b54e2d..e7441b227b3ce 100644
+--- a/drivers/gpu/drm/vkms/vkms_composer.c
++++ b/drivers/gpu/drm/vkms/vkms_composer.c
+@@ -123,6 +123,8 @@ static u16 apply_lut_to_channel_value(const struct vkms_color_lut *lut, u16 chan
+ enum lut_channel channel)
+ {
+ s64 lut_index = get_lut_index(lut, channel_value);
++ u16 *floor_lut_value, *ceil_lut_value;
++ u16 floor_channel_value, ceil_channel_value;
+
+ /*
+ * This checks if `struct drm_color_lut` has any gap added by the compiler
+@@ -130,11 +132,15 @@ static u16 apply_lut_to_channel_value(const struct vkms_color_lut *lut, u16 chan
+ */
+ static_assert(sizeof(struct drm_color_lut) == sizeof(__u16) * 4);
+
+- u16 *floor_lut_value = (__u16 *)&lut->base[drm_fixp2int(lut_index)];
+- u16 *ceil_lut_value = (__u16 *)&lut->base[drm_fixp2int_ceil(lut_index)];
++ floor_lut_value = (__u16 *)&lut->base[drm_fixp2int(lut_index)];
++ if (drm_fixp2int(lut_index) == (lut->lut_length - 1))
++ /* We're at the end of the LUT array, use same value for ceil and floor */
++ ceil_lut_value = floor_lut_value;
++ else
++ ceil_lut_value = (__u16 *)&lut->base[drm_fixp2int_ceil(lut_index)];
+
+- u16 floor_channel_value = floor_lut_value[channel];
+- u16 ceil_channel_value = ceil_lut_value[channel];
++ floor_channel_value = floor_lut_value[channel];
++ ceil_channel_value = ceil_lut_value[channel];
+
+ return lerp_u16(floor_channel_value, ceil_channel_value,
+ lut_index & DRM_FIXED_DECIMAL_MASK);
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
+index ceb4d3d3b965a..a0b47c9b33f55 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
+@@ -64,8 +64,11 @@ static int vmw_gmrid_man_get_node(struct ttm_resource_manager *man,
+ ttm_resource_init(bo, place, *res);
+
+ id = ida_alloc_max(&gman->gmr_ida, gman->max_gmr_ids - 1, GFP_KERNEL);
+- if (id < 0)
++ if (id < 0) {
++ ttm_resource_fini(man, *res);
++ kfree(*res);
+ return id;
++ }
+
+ spin_lock(&gman->lock);
+
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+index 5fd0ccaa0b41b..b6f40781b907a 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+@@ -272,6 +272,7 @@ static int vmw_du_get_cursor_mob(struct vmw_cursor_plane *vcp,
+ u32 size = vmw_du_cursor_mob_size(vps->base.crtc_w, vps->base.crtc_h);
+ u32 i;
+ u32 cursor_max_dim, mob_max_size;
++ struct vmw_fence_obj *fence = NULL;
+ int ret;
+
+ if (!dev_priv->has_mob ||
+@@ -313,7 +314,15 @@ static int vmw_du_get_cursor_mob(struct vmw_cursor_plane *vcp,
+ if (ret != 0)
+ goto teardown;
+
+- vmw_bo_fence_single(&vps->cursor.bo->tbo, NULL);
++ ret = vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL);
++ if (ret != 0) {
++ ttm_bo_unreserve(&vps->cursor.bo->tbo);
++ goto teardown;
++ }
++
++ dma_fence_wait(&fence->base, false);
++ dma_fence_put(&fence->base);
++
+ ttm_bo_unreserve(&vps->cursor.bo->tbo);
+ return 0;
+
+diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
+index efcf0ab7a1a69..802c807c782cc 100644
+--- a/drivers/gpu/drm/xe/Makefile
++++ b/drivers/gpu/drm/xe/Makefile
+@@ -42,7 +42,8 @@ generated_oob := $(obj)/generated/xe_wa_oob.c $(obj)/generated/xe_wa_oob.h
+ quiet_cmd_wa_oob = GEN $(notdir $(generated_oob))
+ cmd_wa_oob = mkdir -p $(@D); $^ $(generated_oob)
+
+-$(generated_oob) &: $(obj)/xe_gen_wa_oob $(srctree)/$(src)/xe_wa_oob.rules
++$(obj)/generated/%_wa_oob.c $(obj)/generated/%_wa_oob.h: $(obj)/xe_gen_wa_oob \
++ $(srctree)/$(src)/xe_wa_oob.rules
+ $(call cmd,wa_oob)
+
+ uses_generated_oob := \
+diff --git a/drivers/gpu/drm/xe/tests/xe_migrate.c b/drivers/gpu/drm/xe/tests/xe_migrate.c
+index a6523df0f1d39..c347e2c29f81f 100644
+--- a/drivers/gpu/drm/xe/tests/xe_migrate.c
++++ b/drivers/gpu/drm/xe/tests/xe_migrate.c
+@@ -114,21 +114,21 @@ static void test_copy(struct xe_migrate *m, struct xe_bo *bo,
+ region |
+ XE_BO_NEEDS_CPU_ACCESS);
+ if (IS_ERR(remote)) {
+- KUNIT_FAIL(test, "Failed to allocate remote bo for %s: %li\n",
+- str, PTR_ERR(remote));
++ KUNIT_FAIL(test, "Failed to allocate remote bo for %s: %pe\n",
++ str, remote);
+ return;
+ }
+
+ err = xe_bo_validate(remote, NULL, false);
+ if (err) {
+- KUNIT_FAIL(test, "Failed to validate system bo for %s: %li\n",
++ KUNIT_FAIL(test, "Failed to validate system bo for %s: %i\n",
+ str, err);
+ goto out_unlock;
+ }
+
+ err = xe_bo_vmap(remote);
+ if (err) {
+- KUNIT_FAIL(test, "Failed to vmap system bo for %s: %li\n",
++ KUNIT_FAIL(test, "Failed to vmap system bo for %s: %i\n",
+ str, err);
+ goto out_unlock;
+ }
+diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
+index 17f26952e6656..222209b0d6904 100644
+--- a/drivers/gpu/drm/xe/xe_exec.c
++++ b/drivers/gpu/drm/xe/xe_exec.c
+@@ -196,6 +196,29 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+ goto err_unlock_list;
+ }
+
++ if (!args->num_batch_buffer) {
++ err = xe_vm_lock(vm, true);
++ if (err)
++ goto err_unlock_list;
++
++ if (!xe_vm_in_lr_mode(vm)) {
++ struct dma_fence *fence;
++
++ fence = xe_sync_in_fence_get(syncs, num_syncs, q, vm);
++ if (IS_ERR(fence)) {
++ err = PTR_ERR(fence);
++ goto err_unlock_list;
++ }
++ for (i = 0; i < num_syncs; i++)
++ xe_sync_entry_signal(&syncs[i], NULL, fence);
++ xe_exec_queue_last_fence_set(q, vm, fence);
++ dma_fence_put(fence);
++ }
++
++ xe_vm_unlock(vm);
++ goto err_unlock_list;
++ }
++
+ vm_exec.vm = &vm->gpuvm;
+ vm_exec.num_fences = 1 + vm->xe->info.tile_count;
+ vm_exec.flags = DRM_EXEC_INTERRUPTIBLE_WAIT;
+@@ -216,24 +239,6 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+ goto err_exec;
+ }
+
+- if (!args->num_batch_buffer) {
+- if (!xe_vm_in_lr_mode(vm)) {
+- struct dma_fence *fence;
+-
+- fence = xe_sync_in_fence_get(syncs, num_syncs, q, vm);
+- if (IS_ERR(fence)) {
+- err = PTR_ERR(fence);
+- goto err_exec;
+- }
+- for (i = 0; i < num_syncs; i++)
+- xe_sync_entry_signal(&syncs[i], NULL, fence);
+- xe_exec_queue_last_fence_set(q, vm, fence);
+- dma_fence_put(fence);
+- }
+-
+- goto err_exec;
+- }
+-
+ if (xe_exec_queue_is_lr(q) && xe_exec_queue_ring_full(q)) {
+ err = -EWOULDBLOCK; /* Aliased to -EAGAIN */
+ skip_retry = true;
+diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c
+index 73f08f1924df2..ab8536c4fd580 100644
+--- a/drivers/gpu/drm/xe/xe_gt_pagefault.c
++++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c
+@@ -69,7 +69,7 @@ static bool access_is_atomic(enum access_type access_type)
+ static bool vma_is_valid(struct xe_tile *tile, struct xe_vma *vma)
+ {
+ return BIT(tile->id) & vma->tile_present &&
+- !(BIT(tile->id) & vma->usm.tile_invalidated);
++ !(BIT(tile->id) & vma->tile_invalidated);
+ }
+
+ static bool vma_matches(struct xe_vma *vma, u64 page_addr)
+@@ -146,10 +146,12 @@ static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf)
+ /* ASID to VM */
+ mutex_lock(&xe->usm.lock);
+ vm = xa_load(&xe->usm.asid_to_vm, pf->asid);
+- if (vm)
++ if (vm && xe_vm_in_fault_mode(vm))
+ xe_vm_get(vm);
++ else
++ vm = NULL;
+ mutex_unlock(&xe->usm.lock);
+- if (!vm || !xe_vm_in_fault_mode(vm))
++ if (!vm)
+ return -EINVAL;
+
+ retry_userptr:
+@@ -224,7 +226,7 @@ static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf)
+
+ if (xe_vma_is_userptr(vma))
+ ret = xe_vma_userptr_check_repin(to_userptr_vma(vma));
+- vma->usm.tile_invalidated &= ~BIT(tile->id);
++ vma->tile_invalidated &= ~BIT(tile->id);
+
+ unlock_dma_resv:
+ drm_exec_fini(&exec);
+diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h
+index 4ddc55527f9ab..846f14507d5ff 100644
+--- a/drivers/gpu/drm/xe/xe_trace.h
++++ b/drivers/gpu/drm/xe/xe_trace.h
+@@ -468,7 +468,7 @@ DEFINE_EVENT(xe_vma, xe_vma_userptr_invalidate,
+ TP_ARGS(vma)
+ );
+
+-DEFINE_EVENT(xe_vma, xe_vma_usm_invalidate,
++DEFINE_EVENT(xe_vma, xe_vma_invalidate,
+ TP_PROTO(struct xe_vma *vma),
+ TP_ARGS(vma)
+ );
+diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
+index 3b21afe5b4883..a2397f232efc6 100644
+--- a/drivers/gpu/drm/xe/xe_vm.c
++++ b/drivers/gpu/drm/xe/xe_vm.c
+@@ -706,6 +706,7 @@ int xe_vm_userptr_pin(struct xe_vm *vm)
+ int err = 0;
+ LIST_HEAD(tmp_evict);
+
++ xe_assert(vm->xe, !xe_vm_in_fault_mode(vm));
+ lockdep_assert_held_write(&vm->lock);
+
+ /* Collect invalidated userptrs */
+@@ -722,11 +723,27 @@ int xe_vm_userptr_pin(struct xe_vm *vm)
+ list_for_each_entry_safe(uvma, next, &vm->userptr.repin_list,
+ userptr.repin_link) {
+ err = xe_vma_userptr_pin_pages(uvma);
+- if (err < 0)
+- return err;
++ if (err == -EFAULT) {
++ list_del_init(&uvma->userptr.repin_link);
+
+- list_del_init(&uvma->userptr.repin_link);
+- list_move_tail(&uvma->vma.combined_links.rebind, &vm->rebind_list);
++ /* Wait for pending binds */
++ xe_vm_lock(vm, false);
++ dma_resv_wait_timeout(xe_vm_resv(vm),
++ DMA_RESV_USAGE_BOOKKEEP,
++ false, MAX_SCHEDULE_TIMEOUT);
++
++ err = xe_vm_invalidate_vma(&uvma->vma);
++ xe_vm_unlock(vm);
++ if (err)
++ return err;
++ } else {
++ if (err < 0)
++ return err;
++
++ list_del_init(&uvma->userptr.repin_link);
++ list_move_tail(&uvma->vma.combined_links.rebind,
++ &vm->rebind_list);
++ }
+ }
+
+ return 0;
+@@ -2010,7 +2027,7 @@ static int xe_vm_prefetch(struct xe_vm *vm, struct xe_vma *vma,
+ return err;
+ }
+
+- if (vma->tile_mask != (vma->tile_present & ~vma->usm.tile_invalidated)) {
++ if (vma->tile_mask != (vma->tile_present & ~vma->tile_invalidated)) {
+ return xe_vm_bind(vm, vma, q, xe_vma_bo(vma), syncs, num_syncs,
+ true, first_op, last_op);
+ } else {
+@@ -3184,9 +3201,8 @@ int xe_vm_invalidate_vma(struct xe_vma *vma)
+ u8 id;
+ int ret;
+
+- xe_assert(xe, xe_vm_in_fault_mode(xe_vma_vm(vma)));
+ xe_assert(xe, !xe_vma_is_null(vma));
+- trace_xe_vma_usm_invalidate(vma);
++ trace_xe_vma_invalidate(vma);
+
+ /* Check that we don't race with page-table updates */
+ if (IS_ENABLED(CONFIG_PROVE_LOCKING)) {
+@@ -3224,7 +3240,7 @@ int xe_vm_invalidate_vma(struct xe_vma *vma)
+ }
+ }
+
+- vma->usm.tile_invalidated = vma->tile_mask;
++ vma->tile_invalidated = vma->tile_mask;
+
+ return 0;
+ }
+diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
+index 7300eea5394ba..5b96549479504 100644
+--- a/drivers/gpu/drm/xe/xe_vm_types.h
++++ b/drivers/gpu/drm/xe/xe_vm_types.h
+@@ -83,11 +83,8 @@ struct xe_vma {
+ struct work_struct destroy_work;
+ };
+
+- /** @usm: unified shared memory state */
+- struct {
+- /** @tile_invalidated: VMA has been invalidated */
+- u8 tile_invalidated;
+- } usm;
++ /** @tile_invalidated: VMA has been invalidated */
++ u8 tile_invalidated;
+
+ /** @tile_mask: Tile mask of where to create binding for this VMA */
+ u8 tile_mask;
+diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+index 2530fa98b568b..ce449da08e9ba 100644
+--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
++++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+@@ -35,6 +35,8 @@ static int sensor_mask_override = -1;
+ module_param_named(sensor_mask, sensor_mask_override, int, 0444);
+ MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask");
+
++static bool intr_disable = true;
++
+ static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
+ {
+ union cmd_response cmd_resp;
+@@ -55,7 +57,7 @@ static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sen
+
+ cmd_base.ul = 0;
+ cmd_base.cmd_v2.cmd_id = ENABLE_SENSOR;
+- cmd_base.cmd_v2.intr_disable = 1;
++ cmd_base.cmd_v2.intr_disable = intr_disable;
+ cmd_base.cmd_v2.period = info.period;
+ cmd_base.cmd_v2.sensor_id = info.sensor_idx;
+ cmd_base.cmd_v2.length = 16;
+@@ -73,7 +75,7 @@ static void amd_stop_sensor_v2(struct amd_mp2_dev *privdata, u16 sensor_idx)
+
+ cmd_base.ul = 0;
+ cmd_base.cmd_v2.cmd_id = DISABLE_SENSOR;
+- cmd_base.cmd_v2.intr_disable = 1;
++ cmd_base.cmd_v2.intr_disable = intr_disable;
+ cmd_base.cmd_v2.period = 0;
+ cmd_base.cmd_v2.sensor_id = sensor_idx;
+ cmd_base.cmd_v2.length = 16;
+@@ -87,7 +89,7 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
+ union sfh_cmd_base cmd_base;
+
+ cmd_base.cmd_v2.cmd_id = STOP_ALL_SENSORS;
+- cmd_base.cmd_v2.intr_disable = 1;
++ cmd_base.cmd_v2.intr_disable = intr_disable;
+ cmd_base.cmd_v2.period = 0;
+ cmd_base.cmd_v2.sensor_id = 0;
+
+@@ -292,6 +294,26 @@ int amd_sfh_irq_init(struct amd_mp2_dev *privdata)
+ return 0;
+ }
+
++static int mp2_disable_intr(const struct dmi_system_id *id)
++{
++ intr_disable = false;
++ return 0;
++}
++
++static const struct dmi_system_id dmi_sfh_table[] = {
++ {
++ /*
++ * https://bugzilla.kernel.org/show_bug.cgi?id=218104
++ */
++ .callback = mp2_disable_intr,
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook x360 435 G7"),
++ },
++ },
++ {}
++};
++
+ static const struct dmi_system_id dmi_nodevs[] = {
+ {
+ /*
+@@ -315,6 +337,8 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
+ if (dmi_first_match(dmi_nodevs))
+ return -ENODEV;
+
++ dmi_check_system(dmi_sfh_table);
++
+ privdata = devm_kzalloc(&pdev->dev, sizeof(*privdata), GFP_KERNEL);
+ if (!privdata)
+ return -ENOMEM;
+diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
+index 70add75fc5066..05e400a4a83e4 100644
+--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
++++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
+@@ -90,10 +90,10 @@ enum mem_use_type {
+ struct hpd_status {
+ union {
+ struct {
+- u32 human_presence_report : 4;
+- u32 human_presence_actual : 4;
+- u32 probablity : 8;
+ u32 object_distance : 16;
++ u32 probablity : 8;
++ u32 human_presence_actual : 4;
++ u32 human_presence_report : 4;
+ } shpd;
+ u32 val;
+ };
+diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c
+index 149a3c74346b4..f86c1ea83a037 100644
+--- a/drivers/hid/hid-lenovo.c
++++ b/drivers/hid/hid-lenovo.c
+@@ -54,10 +54,10 @@ struct lenovo_drvdata {
+ /* 0: Up
+ * 1: Down (undecided)
+ * 2: Scrolling
+- * 3: Patched firmware, disable workaround
+ */
+ u8 middlebutton_state;
+ bool fn_lock;
++ bool middleclick_workaround_cptkbd;
+ };
+
+ #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c))
+@@ -621,6 +621,36 @@ static ssize_t attr_sensitivity_store_cptkbd(struct device *dev,
+ return count;
+ }
+
++static ssize_t attr_middleclick_workaround_show_cptkbd(struct device *dev,
++ struct device_attribute *attr,
++ char *buf)
++{
++ struct hid_device *hdev = to_hid_device(dev);
++ struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
++
++ return snprintf(buf, PAGE_SIZE, "%u\n",
++ cptkbd_data->middleclick_workaround_cptkbd);
++}
++
++static ssize_t attr_middleclick_workaround_store_cptkbd(struct device *dev,
++ struct device_attribute *attr,
++ const char *buf,
++ size_t count)
++{
++ struct hid_device *hdev = to_hid_device(dev);
++ struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
++ int value;
++
++ if (kstrtoint(buf, 10, &value))
++ return -EINVAL;
++ if (value < 0 || value > 1)
++ return -EINVAL;
++
++ cptkbd_data->middleclick_workaround_cptkbd = !!value;
++
++ return count;
++}
++
+
+ static struct device_attribute dev_attr_fn_lock =
+ __ATTR(fn_lock, S_IWUSR | S_IRUGO,
+@@ -632,10 +662,16 @@ static struct device_attribute dev_attr_sensitivity_cptkbd =
+ attr_sensitivity_show_cptkbd,
+ attr_sensitivity_store_cptkbd);
+
++static struct device_attribute dev_attr_middleclick_workaround_cptkbd =
++ __ATTR(middleclick_workaround, S_IWUSR | S_IRUGO,
++ attr_middleclick_workaround_show_cptkbd,
++ attr_middleclick_workaround_store_cptkbd);
++
+
+ static struct attribute *lenovo_attributes_cptkbd[] = {
+ &dev_attr_fn_lock.attr,
+ &dev_attr_sensitivity_cptkbd.attr,
++ &dev_attr_middleclick_workaround_cptkbd.attr,
+ NULL
+ };
+
+@@ -686,23 +722,7 @@ static int lenovo_event_cptkbd(struct hid_device *hdev,
+ {
+ struct lenovo_drvdata *cptkbd_data = hid_get_drvdata(hdev);
+
+- if (cptkbd_data->middlebutton_state != 3) {
+- /* REL_X and REL_Y events during middle button pressed
+- * are only possible on patched, bug-free firmware
+- * so set middlebutton_state to 3
+- * to never apply workaround anymore
+- */
+- if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD &&
+- cptkbd_data->middlebutton_state == 1 &&
+- usage->type == EV_REL &&
+- (usage->code == REL_X || usage->code == REL_Y)) {
+- cptkbd_data->middlebutton_state = 3;
+- /* send middle button press which was hold before */
+- input_event(field->hidinput->input,
+- EV_KEY, BTN_MIDDLE, 1);
+- input_sync(field->hidinput->input);
+- }
+-
++ if (cptkbd_data->middleclick_workaround_cptkbd) {
+ /* "wheel" scroll events */
+ if (usage->type == EV_REL && (usage->code == REL_WHEEL ||
+ usage->code == REL_HWHEEL)) {
+@@ -1166,6 +1186,7 @@ static int lenovo_probe_cptkbd(struct hid_device *hdev)
+ cptkbd_data->middlebutton_state = 0;
+ cptkbd_data->fn_lock = true;
+ cptkbd_data->sensitivity = 0x05;
++ cptkbd_data->middleclick_workaround_cptkbd = true;
+ lenovo_features_set_cptkbd(hdev);
+
+ ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_cptkbd);
+diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
+index 00242107d62e0..862c47b191afe 100644
+--- a/drivers/hv/Kconfig
++++ b/drivers/hv/Kconfig
+@@ -16,6 +16,7 @@ config HYPERV
+ config HYPERV_VTL_MODE
+ bool "Enable Linux to boot in VTL context"
+ depends on X86_64 && HYPERV
++ depends on SMP
+ default n
+ help
+ Virtual Secure Mode (VSM) is a set of hypervisor capabilities and
+diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c
+index d7f0e231feb99..965bb6d4e1bf4 100644
+--- a/drivers/hwtracing/coresight/coresight-core.c
++++ b/drivers/hwtracing/coresight/coresight-core.c
+@@ -441,8 +441,26 @@ static void coresight_disable_helpers(struct coresight_device *csdev)
+ }
+ }
+
++/*
++ * Helper function to call source_ops(csdev)->disable and also disable the
++ * helpers.
++ *
++ * There is an imbalance between coresight_enable_path() and
++ * coresight_disable_path(). Enabling also enables the source's helpers as part
++ * of the path, but disabling always skips the first item in the path (which is
++ * the source), so sources and their helpers don't get disabled as part of that
++ * function and we need the extra step here.
++ */
++void coresight_disable_source(struct coresight_device *csdev, void *data)
++{
++ if (source_ops(csdev)->disable)
++ source_ops(csdev)->disable(csdev, data);
++ coresight_disable_helpers(csdev);
++}
++EXPORT_SYMBOL_GPL(coresight_disable_source);
++
+ /**
+- * coresight_disable_source - Drop the reference count by 1 and disable
++ * coresight_disable_source_sysfs - Drop the reference count by 1 and disable
+ * the device if there are no users left.
+ *
+ * @csdev: The coresight device to disable
+@@ -451,17 +469,15 @@ static void coresight_disable_helpers(struct coresight_device *csdev)
+ *
+ * Returns true if the device has been disabled.
+ */
+-bool coresight_disable_source(struct coresight_device *csdev, void *data)
++static bool coresight_disable_source_sysfs(struct coresight_device *csdev,
++ void *data)
+ {
+ if (atomic_dec_return(&csdev->refcnt) == 0) {
+- if (source_ops(csdev)->disable)
+- source_ops(csdev)->disable(csdev, data);
+- coresight_disable_helpers(csdev);
++ coresight_disable_source(csdev, data);
+ csdev->enable = false;
+ }
+ return !csdev->enable;
+ }
+-EXPORT_SYMBOL_GPL(coresight_disable_source);
+
+ /*
+ * coresight_disable_path_from : Disable components in the given path beyond
+@@ -1204,7 +1220,7 @@ void coresight_disable(struct coresight_device *csdev)
+ if (ret)
+ goto out;
+
+- if (!csdev->enable || !coresight_disable_source(csdev, NULL))
++ if (!csdev->enable || !coresight_disable_source_sysfs(csdev, NULL))
+ goto out;
+
+ switch (csdev->subtype.source_subtype) {
+diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c
+index a52cfcce25d6d..c0c60e6a1703e 100644
+--- a/drivers/hwtracing/coresight/coresight-etm-perf.c
++++ b/drivers/hwtracing/coresight/coresight-etm-perf.c
+@@ -589,7 +589,7 @@ static void etm_event_stop(struct perf_event *event, int mode)
+ return;
+
+ /* stop tracer */
+- source_ops(csdev)->disable(csdev, event);
++ coresight_disable_source(csdev, event);
+
+ /* tell the core */
+ event->hw.state = PERF_HES_STOPPED;
+diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+index ce1995a2827f0..2e2cabc5f50ab 100644
+--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
++++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+@@ -1200,6 +1200,7 @@ static void etm4_init_arch_data(void *info)
+ struct etm4_init_arg *init_arg = info;
+ struct etmv4_drvdata *drvdata;
+ struct csdev_access *csa;
++ struct device *dev = init_arg->dev;
+ int i;
+
+ drvdata = dev_get_drvdata(init_arg->dev);
+@@ -1213,6 +1214,10 @@ static void etm4_init_arch_data(void *info)
+ if (!etm4_init_csdev_access(drvdata, csa))
+ return;
+
++ if (!csa->io_mem ||
++ fwnode_property_present(dev_fwnode(dev), "qcom,skip-power-up"))
++ drvdata->skip_power_up = true;
++
+ /* Detect the support for OS Lock before we actually use it */
+ etm_detect_os_lock(drvdata, csa);
+
+@@ -2040,11 +2045,6 @@ static int etm4_add_coresight_dev(struct etm4_init_arg *init_arg)
+ if (!drvdata->arch)
+ return -EINVAL;
+
+- /* TRCPDCR is not accessible with system instructions. */
+- if (!desc.access.io_mem ||
+- fwnode_property_present(dev_fwnode(dev), "qcom,skip-power-up"))
+- drvdata->skip_power_up = true;
+-
+ major = ETM_ARCH_MAJOR_VERSION(drvdata->arch);
+ minor = ETM_ARCH_MINOR_VERSION(drvdata->arch);
+
+diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
+index 767076e079701..30c051055e54b 100644
+--- a/drivers/hwtracing/coresight/coresight-priv.h
++++ b/drivers/hwtracing/coresight/coresight-priv.h
+@@ -233,6 +233,6 @@ void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
+ struct coresight_device *coresight_get_percpu_sink(int cpu);
+ int coresight_enable_source(struct coresight_device *csdev, enum cs_mode mode,
+ void *data);
+-bool coresight_disable_source(struct coresight_device *csdev, void *data);
++void coresight_disable_source(struct coresight_device *csdev, void *data);
+
+ #endif
+diff --git a/drivers/hwtracing/ptt/hisi_ptt.c b/drivers/hwtracing/ptt/hisi_ptt.c
+index c1b5fd2b89741..4bf04a9778407 100644
+--- a/drivers/hwtracing/ptt/hisi_ptt.c
++++ b/drivers/hwtracing/ptt/hisi_ptt.c
+@@ -998,6 +998,9 @@ static int hisi_ptt_pmu_event_init(struct perf_event *event)
+ int ret;
+ u32 val;
+
++ if (event->attr.type != hisi_ptt->hisi_ptt_pmu.type)
++ return -ENOENT;
++
+ if (event->cpu < 0) {
+ dev_dbg(event->pmu->dev, "Per-task mode not supported\n");
+ return -EOPNOTSUPP;
+@@ -1006,9 +1009,6 @@ static int hisi_ptt_pmu_event_init(struct perf_event *event)
+ if (event->attach_state & PERF_ATTACH_TASK)
+ return -EOPNOTSUPP;
+
+- if (event->attr.type != hisi_ptt->hisi_ptt_pmu.type)
+- return -ENOENT;
+-
+ ret = hisi_ptt_trace_valid_filter(hisi_ptt, event->attr.config);
+ if (ret < 0)
+ return ret;
+diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
+index ef5751e91cc9e..276153e10f5a4 100644
+--- a/drivers/i3c/master/dw-i3c-master.c
++++ b/drivers/i3c/master/dw-i3c-master.c
+@@ -1163,8 +1163,10 @@ static void dw_i3c_master_set_sir_enabled(struct dw_i3c_master *master,
+ global = reg == 0xffffffff;
+ reg &= ~BIT(idx);
+ } else {
+- global = reg == 0;
++ bool hj_rejected = !!(readl(master->regs + DEVICE_CTRL) & DEV_CTRL_HOT_JOIN_NACK);
++
+ reg |= BIT(idx);
++ global = (reg == 0xffffffff) && hj_rejected;
+ }
+ writel(reg, master->regs + IBI_SIR_REQ_REJECT);
+
+diff --git a/drivers/iio/industrialio-gts-helper.c b/drivers/iio/industrialio-gts-helper.c
+index 7653261d2dc2b..b51eb6cb766f3 100644
+--- a/drivers/iio/industrialio-gts-helper.c
++++ b/drivers/iio/industrialio-gts-helper.c
+@@ -34,24 +34,11 @@
+ static int iio_gts_get_gain(const u64 max, const u64 scale)
+ {
+ u64 full = max;
+- int tmp = 1;
+
+ if (scale > full || !scale)
+ return -EINVAL;
+
+- if (U64_MAX - full < scale) {
+- /* Risk of overflow */
+- if (full - scale < scale)
+- return 1;
+-
+- full -= scale;
+- tmp++;
+- }
+-
+- while (full > scale * (u64)tmp)
+- tmp++;
+-
+- return tmp;
++ return div64_u64(full, scale);
+ }
+
+ /**
+diff --git a/drivers/iio/pressure/mprls0025pa.c b/drivers/iio/pressure/mprls0025pa.c
+index 30fb2de368210..e3f0de020a40c 100644
+--- a/drivers/iio/pressure/mprls0025pa.c
++++ b/drivers/iio/pressure/mprls0025pa.c
+@@ -323,6 +323,7 @@ static int mpr_probe(struct i2c_client *client)
+ struct iio_dev *indio_dev;
+ struct device *dev = &client->dev;
+ s64 scale, offset;
++ u32 func;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_BYTE))
+ return dev_err_probe(dev, -EOPNOTSUPP,
+@@ -362,10 +363,11 @@ static int mpr_probe(struct i2c_client *client)
+ return dev_err_probe(dev, ret,
+ "honeywell,pmax-pascal could not be read\n");
+ ret = device_property_read_u32(dev,
+- "honeywell,transfer-function", &data->function);
++ "honeywell,transfer-function", &func);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "honeywell,transfer-function could not be read\n");
++ data->function = func - 1;
+ if (data->function > MPR_FUNCTION_C)
+ return dev_err_probe(dev, -EINVAL,
+ "honeywell,transfer-function %d invalid\n",
+diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
+index 67bcea7a153c6..07cb6c5ffda00 100644
+--- a/drivers/infiniband/core/device.c
++++ b/drivers/infiniband/core/device.c
+@@ -1730,7 +1730,7 @@ static int assign_client_id(struct ib_client *client)
+ {
+ int ret;
+
+- down_write(&clients_rwsem);
++ lockdep_assert_held(&clients_rwsem);
+ /*
+ * The add/remove callbacks must be called in FIFO/LIFO order. To
+ * achieve this we assign client_ids so they are sorted in
+@@ -1739,14 +1739,11 @@ static int assign_client_id(struct ib_client *client)
+ client->client_id = highest_client_id;
+ ret = xa_insert(&clients, client->client_id, client, GFP_KERNEL);
+ if (ret)
+- goto out;
++ return ret;
+
+ highest_client_id++;
+ xa_set_mark(&clients, client->client_id, CLIENT_REGISTERED);
+-
+-out:
+- up_write(&clients_rwsem);
+- return ret;
++ return 0;
+ }
+
+ static void remove_client_id(struct ib_client *client)
+@@ -1776,25 +1773,35 @@ int ib_register_client(struct ib_client *client)
+ {
+ struct ib_device *device;
+ unsigned long index;
++ bool need_unreg = false;
+ int ret;
+
+ refcount_set(&client->uses, 1);
+ init_completion(&client->uses_zero);
++
++ /*
++ * The devices_rwsem is held in write mode to ensure that a racing
++ * ib_register_device() sees a consisent view of clients and devices.
++ */
++ down_write(&devices_rwsem);
++ down_write(&clients_rwsem);
+ ret = assign_client_id(client);
+ if (ret)
+- return ret;
++ goto out;
+
+- down_read(&devices_rwsem);
++ need_unreg = true;
+ xa_for_each_marked (&devices, index, device, DEVICE_REGISTERED) {
+ ret = add_client_context(device, client);
+- if (ret) {
+- up_read(&devices_rwsem);
+- ib_unregister_client(client);
+- return ret;
+- }
++ if (ret)
++ goto out;
+ }
+- up_read(&devices_rwsem);
+- return 0;
++ ret = 0;
++out:
++ up_write(&clients_rwsem);
++ up_write(&devices_rwsem);
++ if (need_unreg && ret)
++ ib_unregister_client(client);
++ return ret;
+ }
+ EXPORT_SYMBOL(ib_register_client);
+
+diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h
+index b1fce5ddf6316..46f8a631093ba 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_device.h
++++ b/drivers/infiniband/hw/hns/hns_roce_device.h
+@@ -585,6 +585,13 @@ struct hns_roce_work {
+ u32 queue_num;
+ };
+
++enum hns_roce_cong_type {
++ CONG_TYPE_DCQCN,
++ CONG_TYPE_LDCP,
++ CONG_TYPE_HC3,
++ CONG_TYPE_DIP,
++};
++
+ struct hns_roce_qp {
+ struct ib_qp ibqp;
+ struct hns_roce_wq rq;
+@@ -628,6 +635,7 @@ struct hns_roce_qp {
+ struct list_head sq_node; /* all send qps are on a list */
+ struct hns_user_mmap_entry *dwqe_mmap_entry;
+ u32 config;
++ enum hns_roce_cong_type cong_type;
+ };
+
+ struct hns_roce_ib_iboe {
+@@ -699,13 +707,6 @@ struct hns_roce_eq_table {
+ struct hns_roce_eq *eq;
+ };
+
+-enum cong_type {
+- CONG_TYPE_DCQCN,
+- CONG_TYPE_LDCP,
+- CONG_TYPE_HC3,
+- CONG_TYPE_DIP,
+-};
+-
+ struct hns_roce_caps {
+ u64 fw_ver;
+ u8 num_ports;
+@@ -835,7 +836,7 @@ struct hns_roce_caps {
+ u16 default_aeq_period;
+ u16 default_aeq_arm_st;
+ u16 default_ceq_arm_st;
+- enum cong_type cong_type;
++ enum hns_roce_cong_type cong_type;
+ };
+
+ enum hns_roce_device_state {
+diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+index 8206daea6767d..34e58e09b15d8 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+@@ -4745,12 +4745,15 @@ static int check_cong_type(struct ib_qp *ibqp,
+ struct hns_roce_congestion_algorithm *cong_alg)
+ {
+ struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device);
++ struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
+
+- if (ibqp->qp_type == IB_QPT_UD)
+- hr_dev->caps.cong_type = CONG_TYPE_DCQCN;
++ if (ibqp->qp_type == IB_QPT_UD || ibqp->qp_type == IB_QPT_GSI)
++ hr_qp->cong_type = CONG_TYPE_DCQCN;
++ else
++ hr_qp->cong_type = hr_dev->caps.cong_type;
+
+ /* different congestion types match different configurations */
+- switch (hr_dev->caps.cong_type) {
++ switch (hr_qp->cong_type) {
+ case CONG_TYPE_DCQCN:
+ cong_alg->alg_sel = CONG_DCQCN;
+ cong_alg->alg_sub_sel = UNSUPPORT_CONG_LEVEL;
+@@ -4778,8 +4781,8 @@ static int check_cong_type(struct ib_qp *ibqp,
+ default:
+ ibdev_warn(&hr_dev->ib_dev,
+ "invalid type(%u) for congestion selection.\n",
+- hr_dev->caps.cong_type);
+- hr_dev->caps.cong_type = CONG_TYPE_DCQCN;
++ hr_qp->cong_type);
++ hr_qp->cong_type = CONG_TYPE_DCQCN;
+ cong_alg->alg_sel = CONG_DCQCN;
+ cong_alg->alg_sub_sel = UNSUPPORT_CONG_LEVEL;
+ cong_alg->dip_vld = DIP_INVALID;
+@@ -4798,6 +4801,7 @@ static int fill_cong_field(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
+ struct hns_roce_congestion_algorithm cong_field;
+ struct ib_device *ibdev = ibqp->device;
+ struct hns_roce_dev *hr_dev = to_hr_dev(ibdev);
++ struct hns_roce_qp *hr_qp = to_hr_qp(ibqp);
+ u32 dip_idx = 0;
+ int ret;
+
+@@ -4810,7 +4814,7 @@ static int fill_cong_field(struct ib_qp *ibqp, const struct ib_qp_attr *attr,
+ return ret;
+
+ hr_reg_write(context, QPC_CONG_ALGO_TMPL_ID, hr_dev->cong_algo_tmpl_id +
+- hr_dev->caps.cong_type * HNS_ROCE_CONG_SIZE);
++ hr_qp->cong_type * HNS_ROCE_CONG_SIZE);
+ hr_reg_clear(qpc_mask, QPC_CONG_ALGO_TMPL_ID);
+ hr_reg_write(&context->ext, QPCEX_CONG_ALG_SEL, cong_field.alg_sel);
+ hr_reg_clear(&qpc_mask->ext, QPCEX_CONG_ALG_SEL);
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 0b046c061742b..12704efb7b19a 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -719,7 +719,6 @@ static int irdma_setup_kmode_qp(struct irdma_device *iwdev,
+ info->rq_pa + (ukinfo->rq_depth * IRDMA_QP_WQE_MIN_SIZE);
+ ukinfo->sq_size = ukinfo->sq_depth >> ukinfo->sq_shift;
+ ukinfo->rq_size = ukinfo->rq_depth >> ukinfo->rq_shift;
+- ukinfo->qp_id = iwqp->ibqp.qp_num;
+
+ iwqp->max_send_wr = (ukinfo->sq_depth - IRDMA_SQ_RSVD) >> ukinfo->sq_shift;
+ iwqp->max_recv_wr = (ukinfo->rq_depth - IRDMA_RQ_RSVD) >> ukinfo->rq_shift;
+@@ -944,7 +943,7 @@ static int irdma_create_qp(struct ib_qp *ibqp,
+ iwqp->host_ctx.size = IRDMA_QP_CTX_SIZE;
+
+ init_info.pd = &iwpd->sc_pd;
+- init_info.qp_uk_init_info.qp_id = iwqp->ibqp.qp_num;
++ init_info.qp_uk_init_info.qp_id = qp_num;
+ if (!rdma_protocol_roce(&iwdev->ibdev, 1))
+ init_info.qp_uk_init_info.first_sq_wq = 1;
+ iwqp->ctx_info.qp_compl_ctx = (uintptr_t)qp;
+diff --git a/drivers/infiniband/hw/mana/cq.c b/drivers/infiniband/hw/mana/cq.c
+index 83ebd070535ab..4a71e678d09c1 100644
+--- a/drivers/infiniband/hw/mana/cq.c
++++ b/drivers/infiniband/hw/mana/cq.c
+@@ -16,7 +16,7 @@ int mana_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
+ int err;
+
+ mdev = container_of(ibdev, struct mana_ib_dev, ib_dev);
+- gc = mdev->gdma_dev->gdma_context;
++ gc = mdev_to_gc(mdev);
+
+ if (udata->inlen < sizeof(ucmd))
+ return -EINVAL;
+@@ -48,7 +48,7 @@ int mana_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
+ return err;
+ }
+
+- err = mana_ib_gd_create_dma_region(mdev, cq->umem, &cq->gdma_region);
++ err = mana_ib_create_zero_offset_dma_region(mdev, cq->umem, &cq->gdma_region);
+ if (err) {
+ ibdev_dbg(ibdev,
+ "Failed to create dma region for create cq, %d\n",
+@@ -57,7 +57,7 @@ int mana_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
+ }
+
+ ibdev_dbg(ibdev,
+- "mana_ib_gd_create_dma_region ret %d gdma_region 0x%llx\n",
++ "create_dma_region ret %d gdma_region 0x%llx\n",
+ err, cq->gdma_region);
+
+ /*
+@@ -81,7 +81,7 @@ int mana_ib_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
+ int err;
+
+ mdev = container_of(ibdev, struct mana_ib_dev, ib_dev);
+- gc = mdev->gdma_dev->gdma_context;
++ gc = mdev_to_gc(mdev);
+
+ err = mana_ib_gd_destroy_dma_region(mdev, cq->gdma_region);
+ if (err) {
+@@ -100,10 +100,29 @@ int mana_ib_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
+ return 0;
+ }
+
+-void mana_ib_cq_handler(void *ctx, struct gdma_queue *gdma_cq)
++static void mana_ib_cq_handler(void *ctx, struct gdma_queue *gdma_cq)
+ {
+ struct mana_ib_cq *cq = ctx;
+
+ if (cq->ibcq.comp_handler)
+ cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
+ }
++
++int mana_ib_install_cq_cb(struct mana_ib_dev *mdev, struct mana_ib_cq *cq)
++{
++ struct gdma_context *gc = mdev_to_gc(mdev);
++ struct gdma_queue *gdma_cq;
++
++ /* Create CQ table entry */
++ WARN_ON(gc->cq_table[cq->id]);
++ gdma_cq = kzalloc(sizeof(*gdma_cq), GFP_KERNEL);
++ if (!gdma_cq)
++ return -ENOMEM;
++
++ gdma_cq->cq.context = cq;
++ gdma_cq->type = GDMA_CQ;
++ gdma_cq->cq.callback = mana_ib_cq_handler;
++ gdma_cq->id = cq->id;
++ gc->cq_table[cq->id] = gdma_cq;
++ return 0;
++}
+diff --git a/drivers/infiniband/hw/mana/main.c b/drivers/infiniband/hw/mana/main.c
+index faca092456fa3..71e33feee61bb 100644
+--- a/drivers/infiniband/hw/mana/main.c
++++ b/drivers/infiniband/hw/mana/main.c
+@@ -8,13 +8,10 @@
+ void mana_ib_uncfg_vport(struct mana_ib_dev *dev, struct mana_ib_pd *pd,
+ u32 port)
+ {
+- struct gdma_dev *gd = &dev->gdma_dev->gdma_context->mana;
+ struct mana_port_context *mpc;
+ struct net_device *ndev;
+- struct mana_context *mc;
+
+- mc = gd->driver_data;
+- ndev = mc->ports[port];
++ ndev = mana_ib_get_netdev(&dev->ib_dev, port);
+ mpc = netdev_priv(ndev);
+
+ mutex_lock(&pd->vport_mutex);
+@@ -31,14 +28,11 @@ void mana_ib_uncfg_vport(struct mana_ib_dev *dev, struct mana_ib_pd *pd,
+ int mana_ib_cfg_vport(struct mana_ib_dev *dev, u32 port, struct mana_ib_pd *pd,
+ u32 doorbell_id)
+ {
+- struct gdma_dev *mdev = &dev->gdma_dev->gdma_context->mana;
+ struct mana_port_context *mpc;
+- struct mana_context *mc;
+ struct net_device *ndev;
+ int err;
+
+- mc = mdev->driver_data;
+- ndev = mc->ports[port];
++ ndev = mana_ib_get_netdev(&dev->ib_dev, port);
+ mpc = netdev_priv(ndev);
+
+ mutex_lock(&pd->vport_mutex);
+@@ -79,17 +73,17 @@ int mana_ib_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
+ struct gdma_create_pd_req req = {};
+ enum gdma_pd_flags flags = 0;
+ struct mana_ib_dev *dev;
+- struct gdma_dev *mdev;
++ struct gdma_context *gc;
+ int err;
+
+ dev = container_of(ibdev, struct mana_ib_dev, ib_dev);
+- mdev = dev->gdma_dev;
++ gc = mdev_to_gc(dev);
+
+ mana_gd_init_req_hdr(&req.hdr, GDMA_CREATE_PD, sizeof(req),
+ sizeof(resp));
+
+ req.flags = flags;
+- err = mana_gd_send_request(mdev->gdma_context, sizeof(req), &req,
++ err = mana_gd_send_request(gc, sizeof(req), &req,
+ sizeof(resp), &resp);
+
+ if (err || resp.hdr.status) {
+@@ -119,17 +113,17 @@ int mana_ib_dealloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
+ struct gdma_destory_pd_resp resp = {};
+ struct gdma_destroy_pd_req req = {};
+ struct mana_ib_dev *dev;
+- struct gdma_dev *mdev;
++ struct gdma_context *gc;
+ int err;
+
+ dev = container_of(ibdev, struct mana_ib_dev, ib_dev);
+- mdev = dev->gdma_dev;
++ gc = mdev_to_gc(dev);
+
+ mana_gd_init_req_hdr(&req.hdr, GDMA_DESTROY_PD, sizeof(req),
+ sizeof(resp));
+
+ req.pd_handle = pd->pd_handle;
+- err = mana_gd_send_request(mdev->gdma_context, sizeof(req), &req,
++ err = mana_gd_send_request(gc, sizeof(req), &req,
+ sizeof(resp), &resp);
+
+ if (err || resp.hdr.status) {
+@@ -206,13 +200,11 @@ int mana_ib_alloc_ucontext(struct ib_ucontext *ibcontext,
+ struct ib_device *ibdev = ibcontext->device;
+ struct mana_ib_dev *mdev;
+ struct gdma_context *gc;
+- struct gdma_dev *dev;
+ int doorbell_page;
+ int ret;
+
+ mdev = container_of(ibdev, struct mana_ib_dev, ib_dev);
+- dev = mdev->gdma_dev;
+- gc = dev->gdma_context;
++ gc = mdev_to_gc(mdev);
+
+ /* Allocate a doorbell page index */
+ ret = mana_gd_allocate_doorbell_page(gc, &doorbell_page);
+@@ -238,7 +230,7 @@ void mana_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
+ int ret;
+
+ mdev = container_of(ibdev, struct mana_ib_dev, ib_dev);
+- gc = mdev->gdma_dev->gdma_context;
++ gc = mdev_to_gc(mdev);
+
+ ret = mana_gd_destroy_doorbell_page(gc, mana_ucontext->doorbell);
+ if (ret)
+@@ -309,8 +301,8 @@ mana_ib_gd_add_dma_region(struct mana_ib_dev *dev, struct gdma_context *gc,
+ return 0;
+ }
+
+-int mana_ib_gd_create_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem,
+- mana_handle_t *gdma_region)
++static int mana_ib_gd_create_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem,
++ mana_handle_t *gdma_region, unsigned long page_sz)
+ {
+ struct gdma_dma_region_add_pages_req *add_req = NULL;
+ size_t num_pages_processed = 0, num_pages_to_handle;
+@@ -322,23 +314,14 @@ int mana_ib_gd_create_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem,
+ size_t max_pgs_create_cmd;
+ struct gdma_context *gc;
+ size_t num_pages_total;
+- struct gdma_dev *mdev;
+- unsigned long page_sz;
+ unsigned int tail = 0;
+ u64 *page_addr_list;
+ void *request_buf;
+ int err;
+
+- mdev = dev->gdma_dev;
+- gc = mdev->gdma_context;
++ gc = mdev_to_gc(dev);
+ hwc = gc->hwc.driver_data;
+
+- /* Hardware requires dma region to align to chosen page size */
+- page_sz = ib_umem_find_best_pgsz(umem, PAGE_SZ_BM, 0);
+- if (!page_sz) {
+- ibdev_dbg(&dev->ib_dev, "failed to find page size.\n");
+- return -ENOMEM;
+- }
+ num_pages_total = ib_umem_num_dma_blocks(umem, page_sz);
+
+ max_pgs_create_cmd =
+@@ -358,7 +341,7 @@ int mana_ib_gd_create_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem,
+ sizeof(struct gdma_create_dma_region_resp));
+
+ create_req->length = umem->length;
+- create_req->offset_in_page = umem->address & (page_sz - 1);
++ create_req->offset_in_page = ib_umem_dma_offset(umem, page_sz);
+ create_req->gdma_page_type = order_base_2(page_sz) - PAGE_SHIFT;
+ create_req->page_count = num_pages_total;
+
+@@ -424,12 +407,39 @@ int mana_ib_gd_create_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem,
+ return err;
+ }
+
++int mana_ib_create_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem,
++ mana_handle_t *gdma_region, u64 virt)
++{
++ unsigned long page_sz;
++
++ page_sz = ib_umem_find_best_pgsz(umem, PAGE_SZ_BM, virt);
++ if (!page_sz) {
++ ibdev_dbg(&dev->ib_dev, "Failed to find page size.\n");
++ return -EINVAL;
++ }
++
++ return mana_ib_gd_create_dma_region(dev, umem, gdma_region, page_sz);
++}
++
++int mana_ib_create_zero_offset_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem,
++ mana_handle_t *gdma_region)
++{
++ unsigned long page_sz;
++
++ /* Hardware requires dma region to align to chosen page size */
++ page_sz = ib_umem_find_best_pgoff(umem, PAGE_SZ_BM, 0);
++ if (!page_sz) {
++ ibdev_dbg(&dev->ib_dev, "Failed to find page size.\n");
++ return -EINVAL;
++ }
++
++ return mana_ib_gd_create_dma_region(dev, umem, gdma_region, page_sz);
++}
++
+ int mana_ib_gd_destroy_dma_region(struct mana_ib_dev *dev, u64 gdma_region)
+ {
+- struct gdma_dev *mdev = dev->gdma_dev;
+- struct gdma_context *gc;
++ struct gdma_context *gc = mdev_to_gc(dev);
+
+- gc = mdev->gdma_context;
+ ibdev_dbg(&dev->ib_dev, "destroy dma region 0x%llx\n", gdma_region);
+
+ return mana_gd_destroy_dma_region(gc, gdma_region);
+@@ -447,7 +457,7 @@ int mana_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma)
+ int ret;
+
+ mdev = container_of(ibdev, struct mana_ib_dev, ib_dev);
+- gc = mdev->gdma_dev->gdma_context;
++ gc = mdev_to_gc(mdev);
+
+ if (vma->vm_pgoff != 0) {
+ ibdev_dbg(ibdev, "Unexpected vm_pgoff %lu\n", vma->vm_pgoff);
+@@ -531,7 +541,7 @@ int mana_ib_gd_query_adapter_caps(struct mana_ib_dev *dev)
+ req.hdr.resp.msg_version = GDMA_MESSAGE_V3;
+ req.hdr.dev_id = dev->gdma_dev->dev_id;
+
+- err = mana_gd_send_request(dev->gdma_dev->gdma_context, sizeof(req),
++ err = mana_gd_send_request(mdev_to_gc(dev), sizeof(req),
+ &req, sizeof(resp), &resp);
+
+ if (err) {
+diff --git a/drivers/infiniband/hw/mana/mana_ib.h b/drivers/infiniband/hw/mana/mana_ib.h
+index 6bdc0f5498d5b..f83390eebb7d7 100644
+--- a/drivers/infiniband/hw/mana/mana_ib.h
++++ b/drivers/infiniband/hw/mana/mana_ib.h
+@@ -142,8 +142,29 @@ struct mana_ib_query_adapter_caps_resp {
+ u32 max_inline_data_size;
+ }; /* HW Data */
+
+-int mana_ib_gd_create_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem,
+- mana_handle_t *gdma_region);
++static inline struct gdma_context *mdev_to_gc(struct mana_ib_dev *mdev)
++{
++ return mdev->gdma_dev->gdma_context;
++}
++
++static inline struct net_device *mana_ib_get_netdev(struct ib_device *ibdev, u32 port)
++{
++ struct mana_ib_dev *mdev = container_of(ibdev, struct mana_ib_dev, ib_dev);
++ struct gdma_context *gc = mdev_to_gc(mdev);
++ struct mana_context *mc = gc->mana.driver_data;
++
++ if (port < 1 || port > mc->num_ports)
++ return NULL;
++ return mc->ports[port - 1];
++}
++
++int mana_ib_install_cq_cb(struct mana_ib_dev *mdev, struct mana_ib_cq *cq);
++
++int mana_ib_create_zero_offset_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem,
++ mana_handle_t *gdma_region);
++
++int mana_ib_create_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem,
++ mana_handle_t *gdma_region, u64 virt);
+
+ int mana_ib_gd_destroy_dma_region(struct mana_ib_dev *dev,
+ mana_handle_t gdma_region);
+@@ -210,6 +231,4 @@ int mana_ib_query_gid(struct ib_device *ibdev, u32 port, int index,
+ void mana_ib_disassociate_ucontext(struct ib_ucontext *ibcontext);
+
+ int mana_ib_gd_query_adapter_caps(struct mana_ib_dev *mdev);
+-
+-void mana_ib_cq_handler(void *ctx, struct gdma_queue *gdma_cq);
+ #endif
+diff --git a/drivers/infiniband/hw/mana/mr.c b/drivers/infiniband/hw/mana/mr.c
+index 351207c60eb65..b70b13484f097 100644
+--- a/drivers/infiniband/hw/mana/mr.c
++++ b/drivers/infiniband/hw/mana/mr.c
+@@ -30,12 +30,9 @@ static int mana_ib_gd_create_mr(struct mana_ib_dev *dev, struct mana_ib_mr *mr,
+ {
+ struct gdma_create_mr_response resp = {};
+ struct gdma_create_mr_request req = {};
+- struct gdma_dev *mdev = dev->gdma_dev;
+- struct gdma_context *gc;
++ struct gdma_context *gc = mdev_to_gc(dev);
+ int err;
+
+- gc = mdev->gdma_context;
+-
+ mana_gd_init_req_hdr(&req.hdr, GDMA_CREATE_MR, sizeof(req),
+ sizeof(resp));
+ req.pd_handle = mr_params->pd_handle;
+@@ -77,12 +74,9 @@ static int mana_ib_gd_destroy_mr(struct mana_ib_dev *dev, u64 mr_handle)
+ {
+ struct gdma_destroy_mr_response resp = {};
+ struct gdma_destroy_mr_request req = {};
+- struct gdma_dev *mdev = dev->gdma_dev;
+- struct gdma_context *gc;
++ struct gdma_context *gc = mdev_to_gc(dev);
+ int err;
+
+- gc = mdev->gdma_context;
+-
+ mana_gd_init_req_hdr(&req.hdr, GDMA_DESTROY_MR, sizeof(req),
+ sizeof(resp));
+
+@@ -133,7 +127,7 @@ struct ib_mr *mana_ib_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 length,
+ goto err_free;
+ }
+
+- err = mana_ib_gd_create_dma_region(dev, mr->umem, &dma_region_handle);
++ err = mana_ib_create_dma_region(dev, mr->umem, &dma_region_handle, iova);
+ if (err) {
+ ibdev_dbg(ibdev, "Failed create dma region for user-mr, %d\n",
+ err);
+@@ -141,7 +135,7 @@ struct ib_mr *mana_ib_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 length,
+ }
+
+ ibdev_dbg(ibdev,
+- "mana_ib_gd_create_dma_region ret %d gdma_region %llx\n", err,
++ "create_dma_region ret %d gdma_region %llx\n", err,
+ dma_region_handle);
+
+ mr_params.pd_handle = pd->pd_handle;
+@@ -164,8 +158,7 @@ struct ib_mr *mana_ib_reg_user_mr(struct ib_pd *ibpd, u64 start, u64 length,
+ return &mr->ibmr;
+
+ err_dma_region:
+- mana_gd_destroy_dma_region(dev->gdma_dev->gdma_context,
+- dma_region_handle);
++ mana_gd_destroy_dma_region(mdev_to_gc(dev), dma_region_handle);
+
+ err_umem:
+ ib_umem_release(mr->umem);
+diff --git a/drivers/infiniband/hw/mana/qp.c b/drivers/infiniband/hw/mana/qp.c
+index 21ac9fcadf3f2..6e7627745c957 100644
+--- a/drivers/infiniband/hw/mana/qp.c
++++ b/drivers/infiniband/hw/mana/qp.c
+@@ -17,12 +17,10 @@ static int mana_ib_cfg_vport_steering(struct mana_ib_dev *dev,
+ struct mana_cfg_rx_steer_resp resp = {};
+ mana_handle_t *req_indir_tab;
+ struct gdma_context *gc;
+- struct gdma_dev *mdev;
+ u32 req_buf_size;
+ int i, err;
+
+- gc = dev->gdma_dev->gdma_context;
+- mdev = &gc->mana;
++ gc = mdev_to_gc(dev);
+
+ req_buf_size =
+ sizeof(*req) + sizeof(mana_handle_t) * MANA_INDIRECT_TABLE_SIZE;
+@@ -39,7 +37,7 @@ static int mana_ib_cfg_vport_steering(struct mana_ib_dev *dev,
+ req->rx_enable = 1;
+ req->update_default_rxobj = 1;
+ req->default_rxobj = default_rxobj;
+- req->hdr.dev_id = mdev->dev_id;
++ req->hdr.dev_id = gc->mana.dev_id;
+
+ /* If there are more than 1 entries in indirection table, enable RSS */
+ if (log_ind_tbl_size)
+@@ -99,20 +97,17 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd,
+ struct mana_ib_qp *qp = container_of(ibqp, struct mana_ib_qp, ibqp);
+ struct mana_ib_dev *mdev =
+ container_of(pd->device, struct mana_ib_dev, ib_dev);
++ struct gdma_context *gc = mdev_to_gc(mdev);
+ struct ib_rwq_ind_table *ind_tbl = attr->rwq_ind_tbl;
+ struct mana_ib_create_qp_rss_resp resp = {};
+ struct mana_ib_create_qp_rss ucmd = {};
+ struct gdma_queue **gdma_cq_allocated;
+ mana_handle_t *mana_ind_table;
+ struct mana_port_context *mpc;
+- struct gdma_queue *gdma_cq;
+ unsigned int ind_tbl_size;
+- struct mana_context *mc;
+ struct net_device *ndev;
+- struct gdma_context *gc;
+ struct mana_ib_cq *cq;
+ struct mana_ib_wq *wq;
+- struct gdma_dev *gd;
+ struct mana_eq *eq;
+ struct ib_cq *ibcq;
+ struct ib_wq *ibwq;
+@@ -120,10 +115,6 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd,
+ u32 port;
+ int ret;
+
+- gc = mdev->gdma_dev->gdma_context;
+- gd = &gc->mana;
+- mc = gd->driver_data;
+-
+ if (!udata || udata->inlen < sizeof(ucmd))
+ return -EINVAL;
+
+@@ -166,12 +157,12 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd,
+
+ /* IB ports start with 1, MANA start with 0 */
+ port = ucmd.port;
+- if (port < 1 || port > mc->num_ports) {
++ ndev = mana_ib_get_netdev(pd->device, port);
++ if (!ndev) {
+ ibdev_dbg(&mdev->ib_dev, "Invalid port %u in creating qp\n",
+ port);
+ return -EINVAL;
+ }
+- ndev = mc->ports[port - 1];
+ mpc = netdev_priv(ndev);
+
+ ibdev_dbg(&mdev->ib_dev, "rx_hash_function %d port %d\n",
+@@ -209,7 +200,7 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd,
+ cq_spec.gdma_region = cq->gdma_region;
+ cq_spec.queue_size = cq->cqe * COMP_ENTRY_SIZE;
+ cq_spec.modr_ctx_id = 0;
+- eq = &mc->eqs[cq->comp_vector % gc->max_num_queues];
++ eq = &mpc->ac->eqs[cq->comp_vector % gc->max_num_queues];
+ cq_spec.attached_eq = eq->eq->id;
+
+ ret = mana_create_wq_obj(mpc, mpc->port_handle, GDMA_RQ,
+@@ -237,19 +228,11 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd,
+ mana_ind_table[i] = wq->rx_object;
+
+ /* Create CQ table entry */
+- WARN_ON(gc->cq_table[cq->id]);
+- gdma_cq = kzalloc(sizeof(*gdma_cq), GFP_KERNEL);
+- if (!gdma_cq) {
+- ret = -ENOMEM;
++ ret = mana_ib_install_cq_cb(mdev, cq);
++ if (ret)
+ goto fail;
+- }
+- gdma_cq_allocated[i] = gdma_cq;
+
+- gdma_cq->cq.context = cq;
+- gdma_cq->type = GDMA_CQ;
+- gdma_cq->cq.callback = mana_ib_cq_handler;
+- gdma_cq->id = cq->id;
+- gc->cq_table[cq->id] = gdma_cq;
++ gdma_cq_allocated[i] = gc->cq_table[cq->id];
+ }
+ resp.num_entries = i;
+
+@@ -306,14 +289,13 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+ struct mana_ib_ucontext *mana_ucontext =
+ rdma_udata_to_drv_context(udata, struct mana_ib_ucontext,
+ ibucontext);
+- struct gdma_dev *gd = &mdev->gdma_dev->gdma_context->mana;
++ struct gdma_context *gc = mdev_to_gc(mdev);
+ struct mana_ib_create_qp_resp resp = {};
+ struct mana_ib_create_qp ucmd = {};
+ struct gdma_queue *gdma_cq = NULL;
+ struct mana_obj_spec wq_spec = {};
+ struct mana_obj_spec cq_spec = {};
+ struct mana_port_context *mpc;
+- struct mana_context *mc;
+ struct net_device *ndev;
+ struct ib_umem *umem;
+ struct mana_eq *eq;
+@@ -321,8 +303,6 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+ u32 port;
+ int err;
+
+- mc = gd->driver_data;
+-
+ if (!mana_ucontext || udata->inlen < sizeof(ucmd))
+ return -EINVAL;
+
+@@ -333,11 +313,6 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+ return err;
+ }
+
+- /* IB ports start with 1, MANA Ethernet ports start with 0 */
+- port = ucmd.port;
+- if (port < 1 || port > mc->num_ports)
+- return -EINVAL;
+-
+ if (attr->cap.max_send_wr > mdev->adapter_caps.max_qp_wr) {
+ ibdev_dbg(&mdev->ib_dev,
+ "Requested max_send_wr %d exceeding limit\n",
+@@ -352,11 +327,17 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+ return -EINVAL;
+ }
+
+- ndev = mc->ports[port - 1];
++ port = ucmd.port;
++ ndev = mana_ib_get_netdev(ibpd->device, port);
++ if (!ndev) {
++ ibdev_dbg(&mdev->ib_dev, "Invalid port %u in creating qp\n",
++ port);
++ return -EINVAL;
++ }
+ mpc = netdev_priv(ndev);
+ ibdev_dbg(&mdev->ib_dev, "port %u ndev %p mpc %p\n", port, ndev, mpc);
+
+- err = mana_ib_cfg_vport(mdev, port - 1, pd, mana_ucontext->doorbell);
++ err = mana_ib_cfg_vport(mdev, port, pd, mana_ucontext->doorbell);
+ if (err)
+ return -ENODEV;
+
+@@ -376,8 +357,8 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+ }
+ qp->sq_umem = umem;
+
+- err = mana_ib_gd_create_dma_region(mdev, qp->sq_umem,
+- &qp->sq_gdma_region);
++ err = mana_ib_create_zero_offset_dma_region(mdev, qp->sq_umem,
++ &qp->sq_gdma_region);
+ if (err) {
+ ibdev_dbg(&mdev->ib_dev,
+ "Failed to create dma region for create qp-raw, %d\n",
+@@ -386,7 +367,7 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+ }
+
+ ibdev_dbg(&mdev->ib_dev,
+- "mana_ib_gd_create_dma_region ret %d gdma_region 0x%llx\n",
++ "create_dma_region ret %d gdma_region 0x%llx\n",
+ err, qp->sq_gdma_region);
+
+ /* Create a WQ on the same port handle used by the Ethernet */
+@@ -396,8 +377,8 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+ cq_spec.gdma_region = send_cq->gdma_region;
+ cq_spec.queue_size = send_cq->cqe * COMP_ENTRY_SIZE;
+ cq_spec.modr_ctx_id = 0;
+- eq_vec = send_cq->comp_vector % gd->gdma_context->max_num_queues;
+- eq = &mc->eqs[eq_vec];
++ eq_vec = send_cq->comp_vector % gc->max_num_queues;
++ eq = &mpc->ac->eqs[eq_vec];
+ cq_spec.attached_eq = eq->eq->id;
+
+ err = mana_create_wq_obj(mpc, mpc->port_handle, GDMA_SQ, &wq_spec,
+@@ -417,18 +398,9 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+ send_cq->id = cq_spec.queue_index;
+
+ /* Create CQ table entry */
+- WARN_ON(gd->gdma_context->cq_table[send_cq->id]);
+- gdma_cq = kzalloc(sizeof(*gdma_cq), GFP_KERNEL);
+- if (!gdma_cq) {
+- err = -ENOMEM;
++ err = mana_ib_install_cq_cb(mdev, send_cq);
++ if (err)
+ goto err_destroy_wq_obj;
+- }
+-
+- gdma_cq->cq.context = send_cq;
+- gdma_cq->type = GDMA_CQ;
+- gdma_cq->cq.callback = mana_ib_cq_handler;
+- gdma_cq->id = send_cq->id;
+- gd->gdma_context->cq_table[send_cq->id] = gdma_cq;
+
+ ibdev_dbg(&mdev->ib_dev,
+ "ret %d qp->tx_object 0x%llx sq id %llu cq id %llu\n", err,
+@@ -450,7 +422,7 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+
+ err_release_gdma_cq:
+ kfree(gdma_cq);
+- gd->gdma_context->cq_table[send_cq->id] = NULL;
++ gc->cq_table[send_cq->id] = NULL;
+
+ err_destroy_wq_obj:
+ mana_destroy_wq_obj(mpc, GDMA_SQ, qp->tx_object);
+@@ -462,7 +434,7 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+ ib_umem_release(umem);
+
+ err_free_vport:
+- mana_ib_uncfg_vport(mdev, pd, port - 1);
++ mana_ib_uncfg_vport(mdev, pd, port);
+
+ return err;
+ }
+@@ -500,16 +472,13 @@ static int mana_ib_destroy_qp_rss(struct mana_ib_qp *qp,
+ {
+ struct mana_ib_dev *mdev =
+ container_of(qp->ibqp.device, struct mana_ib_dev, ib_dev);
+- struct gdma_dev *gd = &mdev->gdma_dev->gdma_context->mana;
+ struct mana_port_context *mpc;
+- struct mana_context *mc;
+ struct net_device *ndev;
+ struct mana_ib_wq *wq;
+ struct ib_wq *ibwq;
+ int i;
+
+- mc = gd->driver_data;
+- ndev = mc->ports[qp->port - 1];
++ ndev = mana_ib_get_netdev(qp->ibqp.device, qp->port);
+ mpc = netdev_priv(ndev);
+
+ for (i = 0; i < (1 << ind_tbl->log_ind_tbl_size); i++) {
+@@ -527,15 +496,12 @@ static int mana_ib_destroy_qp_raw(struct mana_ib_qp *qp, struct ib_udata *udata)
+ {
+ struct mana_ib_dev *mdev =
+ container_of(qp->ibqp.device, struct mana_ib_dev, ib_dev);
+- struct gdma_dev *gd = &mdev->gdma_dev->gdma_context->mana;
+ struct ib_pd *ibpd = qp->ibqp.pd;
+ struct mana_port_context *mpc;
+- struct mana_context *mc;
+ struct net_device *ndev;
+ struct mana_ib_pd *pd;
+
+- mc = gd->driver_data;
+- ndev = mc->ports[qp->port - 1];
++ ndev = mana_ib_get_netdev(qp->ibqp.device, qp->port);
+ mpc = netdev_priv(ndev);
+ pd = container_of(ibpd, struct mana_ib_pd, ibpd);
+
+@@ -546,7 +512,7 @@ static int mana_ib_destroy_qp_raw(struct mana_ib_qp *qp, struct ib_udata *udata)
+ ib_umem_release(qp->sq_umem);
+ }
+
+- mana_ib_uncfg_vport(mdev, pd, qp->port - 1);
++ mana_ib_uncfg_vport(mdev, pd, qp->port);
+
+ return 0;
+ }
+diff --git a/drivers/infiniband/hw/mana/wq.c b/drivers/infiniband/hw/mana/wq.c
+index 372d361510e0c..7c9c699625734 100644
+--- a/drivers/infiniband/hw/mana/wq.c
++++ b/drivers/infiniband/hw/mana/wq.c
+@@ -46,7 +46,7 @@ struct ib_wq *mana_ib_create_wq(struct ib_pd *pd,
+ wq->wq_buf_size = ucmd.wq_buf_size;
+ wq->rx_object = INVALID_MANA_HANDLE;
+
+- err = mana_ib_gd_create_dma_region(mdev, wq->umem, &wq->gdma_region);
++ err = mana_ib_create_zero_offset_dma_region(mdev, wq->umem, &wq->gdma_region);
+ if (err) {
+ ibdev_dbg(&mdev->ib_dev,
+ "Failed to create dma region for create wq, %d\n",
+@@ -55,7 +55,7 @@ struct ib_wq *mana_ib_create_wq(struct ib_pd *pd,
+ }
+
+ ibdev_dbg(&mdev->ib_dev,
+- "mana_ib_gd_create_dma_region ret %d gdma_region 0x%llx\n",
++ "create_dma_region ret %d gdma_region 0x%llx\n",
+ err, wq->gdma_region);
+
+ /* WQ ID is returned at wq_create time, doesn't know the value yet */
+diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c
+index d3c436ead6946..4aa80c9388f05 100644
+--- a/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c
++++ b/drivers/infiniband/ulp/rtrs/rtrs-clt-sysfs.c
+@@ -133,7 +133,7 @@ static ssize_t mpath_policy_store(struct device *dev,
+
+ /* distinguish "mi" and "min-latency" with length */
+ len = strnlen(buf, NAME_MAX);
+- if (buf[len - 1] == '\n')
++ if (len && buf[len - 1] == '\n')
+ len--;
+
+ if (!strncasecmp(buf, "round-robin", 11) ||
+diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
+index 040234c01be4d..9632afbd727b6 100644
+--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
+@@ -3209,7 +3209,6 @@ static int srpt_add_one(struct ib_device *device)
+
+ INIT_IB_EVENT_HANDLER(&sdev->event_handler, sdev->device,
+ srpt_event_handler);
+- ib_register_event_handler(&sdev->event_handler);
+
+ for (i = 1; i <= sdev->device->phys_port_cnt; i++) {
+ sport = &sdev->port[i - 1];
+@@ -3232,6 +3231,7 @@ static int srpt_add_one(struct ib_device *device)
+ }
+ }
+
++ ib_register_event_handler(&sdev->event_handler);
+ spin_lock(&srpt_dev_lock);
+ list_add_tail(&sdev->list, &srpt_dev_list);
+ spin_unlock(&srpt_dev_lock);
+@@ -3242,7 +3242,6 @@ static int srpt_add_one(struct ib_device *device)
+
+ err_port:
+ srpt_unregister_mad_agent(sdev, i);
+- ib_unregister_event_handler(&sdev->event_handler);
+ err_cm:
+ if (sdev->cm_id)
+ ib_destroy_cm_id(sdev->cm_id);
+diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c
+index 36aeeae776110..9ca5a743f19fe 100644
+--- a/drivers/input/misc/iqs7222.c
++++ b/drivers/input/misc/iqs7222.c
+@@ -620,6 +620,118 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = {
+ },
+ },
+ },
++ {
++ .prod_num = IQS7222_PROD_NUM_D,
++ .fw_major = 1,
++ .fw_minor = 2,
++ .touch_link = 1770,
++ .allow_offset = 9,
++ .event_offset = 10,
++ .comms_offset = 11,
++ .reg_grps = {
++ [IQS7222_REG_GRP_STAT] = {
++ .base = IQS7222_SYS_STATUS,
++ .num_row = 1,
++ .num_col = 7,
++ },
++ [IQS7222_REG_GRP_CYCLE] = {
++ .base = 0x8000,
++ .num_row = 7,
++ .num_col = 2,
++ },
++ [IQS7222_REG_GRP_GLBL] = {
++ .base = 0x8700,
++ .num_row = 1,
++ .num_col = 3,
++ },
++ [IQS7222_REG_GRP_BTN] = {
++ .base = 0x9000,
++ .num_row = 14,
++ .num_col = 3,
++ },
++ [IQS7222_REG_GRP_CHAN] = {
++ .base = 0xA000,
++ .num_row = 14,
++ .num_col = 4,
++ },
++ [IQS7222_REG_GRP_FILT] = {
++ .base = 0xAE00,
++ .num_row = 1,
++ .num_col = 2,
++ },
++ [IQS7222_REG_GRP_TPAD] = {
++ .base = 0xB000,
++ .num_row = 1,
++ .num_col = 24,
++ },
++ [IQS7222_REG_GRP_GPIO] = {
++ .base = 0xC000,
++ .num_row = 3,
++ .num_col = 3,
++ },
++ [IQS7222_REG_GRP_SYS] = {
++ .base = IQS7222_SYS_SETUP,
++ .num_row = 1,
++ .num_col = 12,
++ },
++ },
++ },
++ {
++ .prod_num = IQS7222_PROD_NUM_D,
++ .fw_major = 1,
++ .fw_minor = 1,
++ .touch_link = 1774,
++ .allow_offset = 9,
++ .event_offset = 10,
++ .comms_offset = 11,
++ .reg_grps = {
++ [IQS7222_REG_GRP_STAT] = {
++ .base = IQS7222_SYS_STATUS,
++ .num_row = 1,
++ .num_col = 7,
++ },
++ [IQS7222_REG_GRP_CYCLE] = {
++ .base = 0x8000,
++ .num_row = 7,
++ .num_col = 2,
++ },
++ [IQS7222_REG_GRP_GLBL] = {
++ .base = 0x8700,
++ .num_row = 1,
++ .num_col = 3,
++ },
++ [IQS7222_REG_GRP_BTN] = {
++ .base = 0x9000,
++ .num_row = 14,
++ .num_col = 3,
++ },
++ [IQS7222_REG_GRP_CHAN] = {
++ .base = 0xA000,
++ .num_row = 14,
++ .num_col = 4,
++ },
++ [IQS7222_REG_GRP_FILT] = {
++ .base = 0xAE00,
++ .num_row = 1,
++ .num_col = 2,
++ },
++ [IQS7222_REG_GRP_TPAD] = {
++ .base = 0xB000,
++ .num_row = 1,
++ .num_col = 24,
++ },
++ [IQS7222_REG_GRP_GPIO] = {
++ .base = 0xC000,
++ .num_row = 3,
++ .num_col = 3,
++ },
++ [IQS7222_REG_GRP_SYS] = {
++ .base = IQS7222_SYS_SETUP,
++ .num_row = 1,
++ .num_col = 12,
++ },
++ },
++ },
+ {
+ .prod_num = IQS7222_PROD_NUM_D,
+ .fw_major = 0,
+diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
+index 9a29d742617e3..9dbb55e745bd9 100644
+--- a/drivers/iommu/Kconfig
++++ b/drivers/iommu/Kconfig
+@@ -196,7 +196,7 @@ source "drivers/iommu/iommufd/Kconfig"
+ config IRQ_REMAP
+ bool "Support for Interrupt Remapping"
+ depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI
+- select DMAR_TABLE
++ select DMAR_TABLE if INTEL_IOMMU
+ help
+ Supports Interrupt remapping for IO-APIC and MSI devices.
+ To use x2apic mode in the CPU's which support x2APIC enhancements or
+diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
+index c83bd0c2a1c92..40979b0f5250f 100644
+--- a/drivers/iommu/amd/init.c
++++ b/drivers/iommu/amd/init.c
+@@ -2068,6 +2068,9 @@ static int __init iommu_init_pci(struct amd_iommu *iommu)
+ /* Prevent binding other PCI device drivers to IOMMU devices */
+ iommu->dev->match_driver = false;
+
++ /* ACPI _PRT won't have an IRQ for IOMMU */
++ iommu->dev->irq_managed = 1;
++
+ pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET,
+ &iommu->cap);
+
+diff --git a/drivers/iommu/intel/Makefile b/drivers/iommu/intel/Makefile
+index 5dabf081a7793..5402b699a1229 100644
+--- a/drivers/iommu/intel/Makefile
++++ b/drivers/iommu/intel/Makefile
+@@ -5,5 +5,7 @@ obj-$(CONFIG_DMAR_TABLE) += trace.o cap_audit.o
+ obj-$(CONFIG_DMAR_PERF) += perf.o
+ obj-$(CONFIG_INTEL_IOMMU_DEBUGFS) += debugfs.o
+ obj-$(CONFIG_INTEL_IOMMU_SVM) += svm.o
++ifdef CONFIG_INTEL_IOMMU
+ obj-$(CONFIG_IRQ_REMAP) += irq_remapping.o
++endif
+ obj-$(CONFIG_INTEL_IOMMU_PERF_EVENTS) += perfmon.o
+diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
+index 23cb80d62a9ab..36d7427b12026 100644
+--- a/drivers/iommu/intel/dmar.c
++++ b/drivers/iommu/intel/dmar.c
+@@ -1095,7 +1095,9 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
+ iommu->agaw = agaw;
+ iommu->msagaw = msagaw;
+ iommu->segment = drhd->segment;
+-
++ iommu->device_rbtree = RB_ROOT;
++ spin_lock_init(&iommu->device_rbtree_lock);
++ mutex_init(&iommu->iopf_lock);
+ iommu->node = NUMA_NO_NODE;
+
+ ver = readl(iommu->reg + DMAR_VER_REG);
+@@ -1271,6 +1273,8 @@ static int qi_check_fault(struct intel_iommu *iommu, int index, int wait_index)
+ {
+ u32 fault;
+ int head, tail;
++ struct device *dev;
++ u64 iqe_err, ite_sid;
+ struct q_inval *qi = iommu->qi;
+ int shift = qi_shift(iommu);
+
+@@ -1315,6 +1319,13 @@ static int qi_check_fault(struct intel_iommu *iommu, int index, int wait_index)
+ tail = readl(iommu->reg + DMAR_IQT_REG);
+ tail = ((tail >> shift) - 1 + QI_LENGTH) % QI_LENGTH;
+
++ /*
++ * SID field is valid only when the ITE field is Set in FSTS_REG
++ * see Intel VT-d spec r4.1, section 11.4.9.9
++ */
++ iqe_err = dmar_readq(iommu->reg + DMAR_IQER_REG);
++ ite_sid = DMAR_IQER_REG_ITESID(iqe_err);
++
+ writel(DMA_FSTS_ITE, iommu->reg + DMAR_FSTS_REG);
+ pr_info("Invalidation Time-out Error (ITE) cleared\n");
+
+@@ -1324,6 +1335,19 @@ static int qi_check_fault(struct intel_iommu *iommu, int index, int wait_index)
+ head = (head - 2 + QI_LENGTH) % QI_LENGTH;
+ } while (head != tail);
+
++ /*
++ * If device was released or isn't present, no need to retry
++ * the ATS invalidate request anymore.
++ *
++ * 0 value of ite_sid means old VT-d device, no ite_sid value.
++ * see Intel VT-d spec r4.1, section 11.4.9.9
++ */
++ if (ite_sid) {
++ dev = device_rbtree_find(iommu, ite_sid);
++ if (!dev || !dev_is_pci(dev) ||
++ !pci_device_is_present(to_pci_dev(dev)))
++ return -ETIMEDOUT;
++ }
+ if (qi->desc_status[wait_index] == QI_ABORT)
+ return -EAGAIN;
+ }
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index 11652e0bcab3a..5dba58f322f03 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -97,6 +97,81 @@ static phys_addr_t root_entry_uctp(struct root_entry *re)
+ return re->hi & VTD_PAGE_MASK;
+ }
+
++static int device_rid_cmp_key(const void *key, const struct rb_node *node)
++{
++ struct device_domain_info *info =
++ rb_entry(node, struct device_domain_info, node);
++ const u16 *rid_lhs = key;
++
++ if (*rid_lhs < PCI_DEVID(info->bus, info->devfn))
++ return -1;
++
++ if (*rid_lhs > PCI_DEVID(info->bus, info->devfn))
++ return 1;
++
++ return 0;
++}
++
++static int device_rid_cmp(struct rb_node *lhs, const struct rb_node *rhs)
++{
++ struct device_domain_info *info =
++ rb_entry(lhs, struct device_domain_info, node);
++ u16 key = PCI_DEVID(info->bus, info->devfn);
++
++ return device_rid_cmp_key(&key, rhs);
++}
++
++/*
++ * Looks up an IOMMU-probed device using its source ID.
++ *
++ * Returns the pointer to the device if there is a match. Otherwise,
++ * returns NULL.
++ *
++ * Note that this helper doesn't guarantee that the device won't be
++ * released by the iommu subsystem after being returned. The caller
++ * should use its own synchronization mechanism to avoid the device
++ * being released during its use if its possibly the case.
++ */
++struct device *device_rbtree_find(struct intel_iommu *iommu, u16 rid)
++{
++ struct device_domain_info *info = NULL;
++ struct rb_node *node;
++ unsigned long flags;
++
++ spin_lock_irqsave(&iommu->device_rbtree_lock, flags);
++ node = rb_find(&rid, &iommu->device_rbtree, device_rid_cmp_key);
++ if (node)
++ info = rb_entry(node, struct device_domain_info, node);
++ spin_unlock_irqrestore(&iommu->device_rbtree_lock, flags);
++
++ return info ? info->dev : NULL;
++}
++
++static int device_rbtree_insert(struct intel_iommu *iommu,
++ struct device_domain_info *info)
++{
++ struct rb_node *curr;
++ unsigned long flags;
++
++ spin_lock_irqsave(&iommu->device_rbtree_lock, flags);
++ curr = rb_find_add(&info->node, &iommu->device_rbtree, device_rid_cmp);
++ spin_unlock_irqrestore(&iommu->device_rbtree_lock, flags);
++ if (WARN_ON(curr))
++ return -EEXIST;
++
++ return 0;
++}
++
++static void device_rbtree_remove(struct device_domain_info *info)
++{
++ struct intel_iommu *iommu = info->iommu;
++ unsigned long flags;
++
++ spin_lock_irqsave(&iommu->device_rbtree_lock, flags);
++ rb_erase(&info->node, &iommu->device_rbtree);
++ spin_unlock_irqrestore(&iommu->device_rbtree_lock, flags);
++}
++
+ /*
+ * This domain is a statically identity mapping domain.
+ * 1. This domain creats a static 1:1 mapping to all usable memory.
+@@ -3799,30 +3874,6 @@ static void domain_context_clear(struct device_domain_info *info)
+ &domain_context_clear_one_cb, info);
+ }
+
+-static void dmar_remove_one_dev_info(struct device *dev)
+-{
+- struct device_domain_info *info = dev_iommu_priv_get(dev);
+- struct dmar_domain *domain = info->domain;
+- struct intel_iommu *iommu = info->iommu;
+- unsigned long flags;
+-
+- if (!dev_is_real_dma_subdevice(info->dev)) {
+- if (dev_is_pci(info->dev) && sm_supported(iommu))
+- intel_pasid_tear_down_entry(iommu, info->dev,
+- IOMMU_NO_PASID, false);
+-
+- iommu_disable_pci_caps(info);
+- domain_context_clear(info);
+- }
+-
+- spin_lock_irqsave(&domain->lock, flags);
+- list_del(&info->link);
+- spin_unlock_irqrestore(&domain->lock, flags);
+-
+- domain_detach_iommu(domain, iommu);
+- info->domain = NULL;
+-}
+-
+ /*
+ * Clear the page table pointer in context or pasid table entries so that
+ * all DMA requests without PASID from the device are blocked. If the page
+@@ -4330,26 +4381,42 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev)
+ }
+
+ dev_iommu_priv_set(dev, info);
++ ret = device_rbtree_insert(iommu, info);
++ if (ret)
++ goto free;
+
+ if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) {
+ ret = intel_pasid_alloc_table(dev);
+ if (ret) {
+ dev_err(dev, "PASID table allocation failed\n");
+- kfree(info);
+- return ERR_PTR(ret);
++ goto clear_rbtree;
+ }
+ }
+
+ intel_iommu_debugfs_create_dev(info);
+
+ return &iommu->iommu;
++clear_rbtree:
++ device_rbtree_remove(info);
++free:
++ kfree(info);
++
++ return ERR_PTR(ret);
+ }
+
+ static void intel_iommu_release_device(struct device *dev)
+ {
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
++ struct intel_iommu *iommu = info->iommu;
++
++ mutex_lock(&iommu->iopf_lock);
++ device_rbtree_remove(info);
++ mutex_unlock(&iommu->iopf_lock);
++
++ if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev) &&
++ !context_copied(iommu, info->bus, info->devfn))
++ intel_pasid_teardown_sm_context(dev);
+
+- dmar_remove_one_dev_info(dev);
+ intel_pasid_free_table(dev);
+ intel_iommu_debugfs_remove_dev(info);
+ kfree(info);
+@@ -4855,6 +4922,7 @@ static const struct iommu_dirty_ops intel_dirty_ops = {
+
+ const struct iommu_ops intel_iommu_ops = {
+ .blocked_domain = &blocking_domain,
++ .release_domain = &blocking_domain,
+ .capable = intel_iommu_capable,
+ .hw_info = intel_iommu_hw_info,
+ .domain_alloc = intel_iommu_domain_alloc,
+diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
+index 4145c04cb1c68..cd267ba64eda1 100644
+--- a/drivers/iommu/intel/iommu.h
++++ b/drivers/iommu/intel/iommu.h
+@@ -719,9 +719,16 @@ struct intel_iommu {
+ #endif
+ struct iopf_queue *iopf_queue;
+ unsigned char iopfq_name[16];
++ /* Synchronization between fault report and iommu device release. */
++ struct mutex iopf_lock;
+ struct q_inval *qi; /* Queued invalidation info */
+ u32 iommu_state[MAX_SR_DMAR_REGS]; /* Store iommu states between suspend and resume.*/
+
++ /* rb tree for all probed devices */
++ struct rb_root device_rbtree;
++ /* protect the device_rbtree */
++ spinlock_t device_rbtree_lock;
++
+ #ifdef CONFIG_IRQ_REMAP
+ struct ir_table *ir_table; /* Interrupt remapping info */
+ struct irq_domain *ir_domain;
+@@ -755,6 +762,8 @@ struct device_domain_info {
+ struct intel_iommu *iommu; /* IOMMU used by this device */
+ struct dmar_domain *domain; /* pointer to domain */
+ struct pasid_table *pasid_table; /* pasid table */
++ /* device tracking node(lookup by PCI RID) */
++ struct rb_node node;
+ #ifdef CONFIG_INTEL_IOMMU_DEBUGFS
+ struct dentry *debugfs_dentry; /* pointer to device directory dentry */
+ #endif
+@@ -1081,6 +1090,7 @@ void free_pgtable_page(void *vaddr);
+ void iommu_flush_write_buffer(struct intel_iommu *iommu);
+ struct iommu_domain *intel_nested_domain_alloc(struct iommu_domain *parent,
+ const struct iommu_user_data *user_data);
++struct device *device_rbtree_find(struct intel_iommu *iommu, u16 rid);
+
+ #ifdef CONFIG_INTEL_IOMMU_SVM
+ void intel_svm_check(struct intel_iommu *iommu);
+diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
+index 108158e2b907d..a51e895d9a178 100644
+--- a/drivers/iommu/intel/pasid.c
++++ b/drivers/iommu/intel/pasid.c
+@@ -214,6 +214,9 @@ devtlb_invalidation_with_pasid(struct intel_iommu *iommu,
+ if (!info || !info->ats_enabled)
+ return;
+
++ if (pci_dev_is_disconnected(to_pci_dev(dev)))
++ return;
++
+ sid = info->bus << 8 | info->devfn;
+ qdep = info->ats_qdep;
+ pfsid = info->pfsid;
+@@ -667,3 +670,67 @@ int intel_pasid_setup_nested(struct intel_iommu *iommu, struct device *dev,
+
+ return 0;
+ }
++
++/*
++ * Interfaces to setup or teardown a pasid table to the scalable-mode
++ * context table entry:
++ */
++
++static void device_pasid_table_teardown(struct device *dev, u8 bus, u8 devfn)
++{
++ struct device_domain_info *info = dev_iommu_priv_get(dev);
++ struct intel_iommu *iommu = info->iommu;
++ struct context_entry *context;
++
++ spin_lock(&iommu->lock);
++ context = iommu_context_addr(iommu, bus, devfn, false);
++ if (!context) {
++ spin_unlock(&iommu->lock);
++ return;
++ }
++
++ context_clear_entry(context);
++ __iommu_flush_cache(iommu, context, sizeof(*context));
++ spin_unlock(&iommu->lock);
++
++ /*
++ * Cache invalidation for changes to a scalable-mode context table
++ * entry.
++ *
++ * Section 6.5.3.3 of the VT-d spec:
++ * - Device-selective context-cache invalidation;
++ * - Domain-selective PASID-cache invalidation to affected domains
++ * (can be skipped if all PASID entries were not-present);
++ * - Domain-selective IOTLB invalidation to affected domains;
++ * - Global Device-TLB invalidation to affected functions.
++ *
++ * The iommu has been parked in the blocking state. All domains have
++ * been detached from the device or PASID. The PASID and IOTLB caches
++ * have been invalidated during the domain detach path.
++ */
++ iommu->flush.flush_context(iommu, 0, PCI_DEVID(bus, devfn),
++ DMA_CCMD_MASK_NOBIT, DMA_CCMD_DEVICE_INVL);
++ devtlb_invalidation_with_pasid(iommu, dev, IOMMU_NO_PASID);
++}
++
++static int pci_pasid_table_teardown(struct pci_dev *pdev, u16 alias, void *data)
++{
++ struct device *dev = data;
++
++ if (dev == &pdev->dev)
++ device_pasid_table_teardown(dev, PCI_BUS_NUM(alias), alias & 0xff);
++
++ return 0;
++}
++
++void intel_pasid_teardown_sm_context(struct device *dev)
++{
++ struct device_domain_info *info = dev_iommu_priv_get(dev);
++
++ if (!dev_is_pci(dev)) {
++ device_pasid_table_teardown(dev, info->bus, info->devfn);
++ return;
++ }
++
++ pci_for_each_dma_alias(to_pci_dev(dev), pci_pasid_table_teardown, dev);
++}
+diff --git a/drivers/iommu/intel/pasid.h b/drivers/iommu/intel/pasid.h
+index 487ede039bdde..42fda97fd8516 100644
+--- a/drivers/iommu/intel/pasid.h
++++ b/drivers/iommu/intel/pasid.h
+@@ -318,4 +318,5 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu,
+ bool fault_ignore);
+ void intel_pasid_setup_page_snoop_control(struct intel_iommu *iommu,
+ struct device *dev, u32 pasid);
++void intel_pasid_teardown_sm_context(struct device *dev);
+ #endif /* __INTEL_PASID_H */
+diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
+index 40edd282903fb..ec47ec81f0ecd 100644
+--- a/drivers/iommu/intel/svm.c
++++ b/drivers/iommu/intel/svm.c
+@@ -650,7 +650,7 @@ static irqreturn_t prq_event_thread(int irq, void *d)
+ struct intel_iommu *iommu = d;
+ struct page_req_dsc *req;
+ int head, tail, handled;
+- struct pci_dev *pdev;
++ struct device *dev;
+ u64 address;
+
+ /*
+@@ -696,23 +696,24 @@ static irqreturn_t prq_event_thread(int irq, void *d)
+ if (unlikely(req->lpig && !req->rd_req && !req->wr_req))
+ goto prq_advance;
+
+- pdev = pci_get_domain_bus_and_slot(iommu->segment,
+- PCI_BUS_NUM(req->rid),
+- req->rid & 0xff);
+ /*
+ * If prq is to be handled outside iommu driver via receiver of
+ * the fault notifiers, we skip the page response here.
+ */
+- if (!pdev)
++ mutex_lock(&iommu->iopf_lock);
++ dev = device_rbtree_find(iommu, req->rid);
++ if (!dev) {
++ mutex_unlock(&iommu->iopf_lock);
+ goto bad_req;
++ }
+
+- if (intel_svm_prq_report(iommu, &pdev->dev, req))
++ if (intel_svm_prq_report(iommu, dev, req))
+ handle_bad_prq_event(iommu, req, QI_RESP_INVALID);
+ else
+- trace_prq_report(iommu, &pdev->dev, req->qw_0, req->qw_1,
++ trace_prq_report(iommu, dev, req->qw_0, req->qw_1,
+ req->priv_data[0], req->priv_data[1],
+ iommu->prq_seq_number++);
+- pci_dev_put(pdev);
++ mutex_unlock(&iommu->iopf_lock);
+ prq_advance:
+ head = (head + sizeof(*req)) & PRQ_RING_MASK;
+ }
+diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
+index d14413916f93a..cd1210026ac53 100644
+--- a/drivers/iommu/iommu.c
++++ b/drivers/iommu/iommu.c
+@@ -463,13 +463,24 @@ static void iommu_deinit_device(struct device *dev)
+
+ /*
+ * release_device() must stop using any attached domain on the device.
+- * If there are still other devices in the group they are not effected
++ * If there are still other devices in the group, they are not affected
+ * by this callback.
+ *
+- * The IOMMU driver must set the device to either an identity or
+- * blocking translation and stop using any domain pointer, as it is
+- * going to be freed.
++ * If the iommu driver provides release_domain, the core code ensures
++ * that domain is attached prior to calling release_device. Drivers can
++ * use this to enforce a translation on the idle iommu. Typically, the
++ * global static blocked_domain is a good choice.
++ *
++ * Otherwise, the iommu driver must set the device to either an identity
++ * or a blocking translation in release_device() and stop using any
++ * domain pointer, as it is going to be freed.
++ *
++ * Regardless, if a delayed attach never occurred, then the release
++ * should still avoid touching any hardware configuration either.
+ */
++ if (!dev->iommu->attach_deferred && ops->release_domain)
++ ops->release_domain->ops->attach_dev(ops->release_domain, dev);
++
+ if (ops->release_device)
+ ops->release_device(dev);
+
+diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c
+index 83314b9d8f38b..ee59647c20501 100644
+--- a/drivers/iommu/irq_remapping.c
++++ b/drivers/iommu/irq_remapping.c
+@@ -99,7 +99,8 @@ int __init irq_remapping_prepare(void)
+ if (disable_irq_remap)
+ return -ENOSYS;
+
+- if (intel_irq_remap_ops.prepare() == 0)
++ if (IS_ENABLED(CONFIG_INTEL_IOMMU) &&
++ intel_irq_remap_ops.prepare() == 0)
+ remap_ops = &intel_irq_remap_ops;
+ else if (IS_ENABLED(CONFIG_AMD_IOMMU) &&
+ amd_iommu_irq_ops.prepare() == 0)
+diff --git a/drivers/leds/flash/leds-sgm3140.c b/drivers/leds/flash/leds-sgm3140.c
+index eb648ff54b4e5..db0ac6641954e 100644
+--- a/drivers/leds/flash/leds-sgm3140.c
++++ b/drivers/leds/flash/leds-sgm3140.c
+@@ -114,8 +114,11 @@ static int sgm3140_brightness_set(struct led_classdev *led_cdev,
+ "failed to enable regulator: %d\n", ret);
+ return ret;
+ }
++ gpiod_set_value_cansleep(priv->flash_gpio, 0);
+ gpiod_set_value_cansleep(priv->enable_gpio, 1);
+ } else {
++ del_timer_sync(&priv->powerdown_timer);
++ gpiod_set_value_cansleep(priv->flash_gpio, 0);
+ gpiod_set_value_cansleep(priv->enable_gpio, 0);
+ ret = regulator_disable(priv->vin_regulator);
+ if (ret) {
+diff --git a/drivers/leds/leds-aw2013.c b/drivers/leds/leds-aw2013.c
+index 91f44b23cb113..17235a5e576ae 100644
+--- a/drivers/leds/leds-aw2013.c
++++ b/drivers/leds/leds-aw2013.c
+@@ -405,6 +405,7 @@ static int aw2013_probe(struct i2c_client *client)
+ chip->regulators);
+
+ error:
++ mutex_unlock(&chip->mutex);
+ mutex_destroy(&chip->mutex);
+ return ret;
+ }
+diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
+index 13c65b7e1ed63..f5541b8f6320c 100644
+--- a/drivers/md/dm-bufio.c
++++ b/drivers/md/dm-bufio.c
+@@ -1315,7 +1315,7 @@ static void use_dmio(struct dm_buffer *b, enum req_op op, sector_t sector,
+ io_req.mem.ptr.vma = (char *)b->data + offset;
+ }
+
+- r = dm_io(&io_req, 1, ®ion, NULL);
++ r = dm_io(&io_req, 1, ®ion, NULL, IOPRIO_DEFAULT);
+ if (unlikely(r))
+ b->end_io(b, errno_to_blk_status(r));
+ }
+@@ -2167,7 +2167,7 @@ int dm_bufio_issue_flush(struct dm_bufio_client *c)
+ if (WARN_ON_ONCE(dm_bufio_in_request()))
+ return -EINVAL;
+
+- return dm_io(&io_req, 1, &io_reg, NULL);
++ return dm_io(&io_req, 1, &io_reg, NULL, IOPRIO_DEFAULT);
+ }
+ EXPORT_SYMBOL_GPL(dm_bufio_issue_flush);
+
+@@ -2191,7 +2191,7 @@ int dm_bufio_issue_discard(struct dm_bufio_client *c, sector_t block, sector_t c
+ if (WARN_ON_ONCE(dm_bufio_in_request()))
+ return -EINVAL; /* discards are optional */
+
+- return dm_io(&io_req, 1, &io_reg, NULL);
++ return dm_io(&io_req, 1, &io_reg, NULL, IOPRIO_DEFAULT);
+ }
+ EXPORT_SYMBOL_GPL(dm_bufio_issue_discard);
+
+diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
+index 1fc901df84eb1..47cf1ab34941f 100644
+--- a/drivers/md/dm-integrity.c
++++ b/drivers/md/dm-integrity.c
+@@ -555,7 +555,7 @@ static int sync_rw_sb(struct dm_integrity_c *ic, blk_opf_t opf)
+ }
+ }
+
+- r = dm_io(&io_req, 1, &io_loc, NULL);
++ r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
+ if (unlikely(r))
+ return r;
+
+@@ -1073,7 +1073,7 @@ static void rw_journal_sectors(struct dm_integrity_c *ic, blk_opf_t opf,
+ io_loc.sector = ic->start + SB_SECTORS + sector;
+ io_loc.count = n_sectors;
+
+- r = dm_io(&io_req, 1, &io_loc, NULL);
++ r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
+ if (unlikely(r)) {
+ dm_integrity_io_error(ic, (opf & REQ_OP_MASK) == REQ_OP_READ ?
+ "reading journal" : "writing journal", r);
+@@ -1190,7 +1190,7 @@ static void copy_from_journal(struct dm_integrity_c *ic, unsigned int section, u
+ io_loc.sector = target;
+ io_loc.count = n_sectors;
+
+- r = dm_io(&io_req, 1, &io_loc, NULL);
++ r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
+ if (unlikely(r)) {
+ WARN_ONCE(1, "asynchronous dm_io failed: %d", r);
+ fn(-1UL, data);
+@@ -1519,7 +1519,7 @@ static void dm_integrity_flush_buffers(struct dm_integrity_c *ic, bool flush_dat
+ fr.io_reg.count = 0,
+ fr.ic = ic;
+ init_completion(&fr.comp);
+- r = dm_io(&fr.io_req, 1, &fr.io_reg, NULL);
++ r = dm_io(&fr.io_req, 1, &fr.io_reg, NULL, IOPRIO_DEFAULT);
+ BUG_ON(r);
+ }
+
+@@ -1699,7 +1699,6 @@ static noinline void integrity_recheck(struct dm_integrity_io *dio, char *checks
+ struct bio_vec bv;
+ sector_t sector, logical_sector, area, offset;
+ struct page *page;
+- void *buffer;
+
+ get_area_and_offset(ic, dio->range.logical_sector, &area, &offset);
+ dio->metadata_block = get_metadata_sector_and_offset(ic, area, offset,
+@@ -1708,13 +1707,14 @@ static noinline void integrity_recheck(struct dm_integrity_io *dio, char *checks
+ logical_sector = dio->range.logical_sector;
+
+ page = mempool_alloc(&ic->recheck_pool, GFP_NOIO);
+- buffer = page_to_virt(page);
+
+ __bio_for_each_segment(bv, bio, iter, dio->bio_details.bi_iter) {
+ unsigned pos = 0;
+
+ do {
++ sector_t alignment;
+ char *mem;
++ char *buffer = page_to_virt(page);
+ int r;
+ struct dm_io_request io_req;
+ struct dm_io_region io_loc;
+@@ -1727,7 +1727,15 @@ static noinline void integrity_recheck(struct dm_integrity_io *dio, char *checks
+ io_loc.sector = sector;
+ io_loc.count = ic->sectors_per_block;
+
+- r = dm_io(&io_req, 1, &io_loc, NULL);
++ /* Align the bio to logical block size */
++ alignment = dio->range.logical_sector | bio_sectors(bio) | (PAGE_SIZE >> SECTOR_SHIFT);
++ alignment &= -alignment;
++ io_loc.sector = round_down(io_loc.sector, alignment);
++ io_loc.count += sector - io_loc.sector;
++ buffer += (sector - io_loc.sector) << SECTOR_SHIFT;
++ io_loc.count = round_up(io_loc.count, alignment);
++
++ r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
+ if (unlikely(r)) {
+ dio->bi_status = errno_to_blk_status(r);
+ goto free_ret;
+@@ -1848,12 +1856,12 @@ static void integrity_metadata(struct work_struct *w)
+ r = dm_integrity_rw_tag(ic, checksums, &dio->metadata_block, &dio->metadata_offset,
+ checksums_ptr - checksums, dio->op == REQ_OP_READ ? TAG_CMP : TAG_WRITE);
+ if (unlikely(r)) {
++ if (likely(checksums != checksums_onstack))
++ kfree(checksums);
+ if (r > 0) {
+- integrity_recheck(dio, checksums);
++ integrity_recheck(dio, checksums_onstack);
+ goto skip_io;
+ }
+- if (likely(checksums != checksums_onstack))
+- kfree(checksums);
+ goto error;
+ }
+
+@@ -2806,7 +2814,7 @@ static void integrity_recalc(struct work_struct *w)
+ io_loc.sector = get_data_sector(ic, area, offset);
+ io_loc.count = n_sectors;
+
+- r = dm_io(&io_req, 1, &io_loc, NULL);
++ r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
+ if (unlikely(r)) {
+ dm_integrity_io_error(ic, "reading data", r);
+ goto err;
+diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
+index f053ce2458147..7409490259d1d 100644
+--- a/drivers/md/dm-io.c
++++ b/drivers/md/dm-io.c
+@@ -305,7 +305,7 @@ static void km_dp_init(struct dpages *dp, void *data)
+ */
+ static void do_region(const blk_opf_t opf, unsigned int region,
+ struct dm_io_region *where, struct dpages *dp,
+- struct io *io)
++ struct io *io, unsigned short ioprio)
+ {
+ struct bio *bio;
+ struct page *page;
+@@ -354,6 +354,7 @@ static void do_region(const blk_opf_t opf, unsigned int region,
+ &io->client->bios);
+ bio->bi_iter.bi_sector = where->sector + (where->count - remaining);
+ bio->bi_end_io = endio;
++ bio->bi_ioprio = ioprio;
+ store_io_and_region_in_bio(bio, io, region);
+
+ if (op == REQ_OP_DISCARD || op == REQ_OP_WRITE_ZEROES) {
+@@ -383,7 +384,7 @@ static void do_region(const blk_opf_t opf, unsigned int region,
+
+ static void dispatch_io(blk_opf_t opf, unsigned int num_regions,
+ struct dm_io_region *where, struct dpages *dp,
+- struct io *io, int sync)
++ struct io *io, int sync, unsigned short ioprio)
+ {
+ int i;
+ struct dpages old_pages = *dp;
+@@ -400,7 +401,7 @@ static void dispatch_io(blk_opf_t opf, unsigned int num_regions,
+ for (i = 0; i < num_regions; i++) {
+ *dp = old_pages;
+ if (where[i].count || (opf & REQ_PREFLUSH))
+- do_region(opf, i, where + i, dp, io);
++ do_region(opf, i, where + i, dp, io, ioprio);
+ }
+
+ /*
+@@ -425,7 +426,7 @@ static void sync_io_complete(unsigned long error, void *context)
+
+ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
+ struct dm_io_region *where, blk_opf_t opf, struct dpages *dp,
+- unsigned long *error_bits)
++ unsigned long *error_bits, unsigned short ioprio)
+ {
+ struct io *io;
+ struct sync_io sio;
+@@ -447,7 +448,7 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
+ io->vma_invalidate_address = dp->vma_invalidate_address;
+ io->vma_invalidate_size = dp->vma_invalidate_size;
+
+- dispatch_io(opf, num_regions, where, dp, io, 1);
++ dispatch_io(opf, num_regions, where, dp, io, 1, ioprio);
+
+ wait_for_completion_io(&sio.wait);
+
+@@ -459,7 +460,8 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions,
+
+ static int async_io(struct dm_io_client *client, unsigned int num_regions,
+ struct dm_io_region *where, blk_opf_t opf,
+- struct dpages *dp, io_notify_fn fn, void *context)
++ struct dpages *dp, io_notify_fn fn, void *context,
++ unsigned short ioprio)
+ {
+ struct io *io;
+
+@@ -479,7 +481,7 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions,
+ io->vma_invalidate_address = dp->vma_invalidate_address;
+ io->vma_invalidate_size = dp->vma_invalidate_size;
+
+- dispatch_io(opf, num_regions, where, dp, io, 0);
++ dispatch_io(opf, num_regions, where, dp, io, 0, ioprio);
+ return 0;
+ }
+
+@@ -521,7 +523,8 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp,
+ }
+
+ int dm_io(struct dm_io_request *io_req, unsigned int num_regions,
+- struct dm_io_region *where, unsigned long *sync_error_bits)
++ struct dm_io_region *where, unsigned long *sync_error_bits,
++ unsigned short ioprio)
+ {
+ int r;
+ struct dpages dp;
+@@ -532,11 +535,11 @@ int dm_io(struct dm_io_request *io_req, unsigned int num_regions,
+
+ if (!io_req->notify.fn)
+ return sync_io(io_req->client, num_regions, where,
+- io_req->bi_opf, &dp, sync_error_bits);
++ io_req->bi_opf, &dp, sync_error_bits, ioprio);
+
+ return async_io(io_req->client, num_regions, where,
+ io_req->bi_opf, &dp, io_req->notify.fn,
+- io_req->notify.context);
++ io_req->notify.context, ioprio);
+ }
+ EXPORT_SYMBOL(dm_io);
+
+diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
+index 36bcfdccae046..6ea75436a433a 100644
+--- a/drivers/md/dm-kcopyd.c
++++ b/drivers/md/dm-kcopyd.c
+@@ -578,9 +578,9 @@ static int run_io_job(struct kcopyd_job *job)
+ io_job_start(job->kc->throttle);
+
+ if (job->op == REQ_OP_READ)
+- r = dm_io(&io_req, 1, &job->source, NULL);
++ r = dm_io(&io_req, 1, &job->source, NULL, IOPRIO_DEFAULT);
+ else
+- r = dm_io(&io_req, job->num_dests, job->dests, NULL);
++ r = dm_io(&io_req, job->num_dests, job->dests, NULL, IOPRIO_DEFAULT);
+
+ return r;
+ }
+diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
+index f9f84236dfcd7..f7f9c2100937b 100644
+--- a/drivers/md/dm-log.c
++++ b/drivers/md/dm-log.c
+@@ -300,7 +300,7 @@ static int rw_header(struct log_c *lc, enum req_op op)
+ {
+ lc->io_req.bi_opf = op;
+
+- return dm_io(&lc->io_req, 1, &lc->header_location, NULL);
++ return dm_io(&lc->io_req, 1, &lc->header_location, NULL, IOPRIO_DEFAULT);
+ }
+
+ static int flush_header(struct log_c *lc)
+@@ -313,7 +313,7 @@ static int flush_header(struct log_c *lc)
+
+ lc->io_req.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+
+- return dm_io(&lc->io_req, 1, &null_location, NULL);
++ return dm_io(&lc->io_req, 1, &null_location, NULL, IOPRIO_DEFAULT);
+ }
+
+ static int read_header(struct log_c *log)
+diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
+index eb009d6bb03a1..13eb47b997f94 100644
+--- a/drivers/md/dm-raid.c
++++ b/drivers/md/dm-raid.c
+@@ -3329,14 +3329,14 @@ static int raid_map(struct dm_target *ti, struct bio *bio)
+ struct mddev *mddev = &rs->md;
+
+ /*
+- * If we're reshaping to add disk(s)), ti->len and
++ * If we're reshaping to add disk(s), ti->len and
+ * mddev->array_sectors will differ during the process
+ * (ti->len > mddev->array_sectors), so we have to requeue
+ * bios with addresses > mddev->array_sectors here or
+ * there will occur accesses past EOD of the component
+ * data images thus erroring the raid set.
+ */
+- if (unlikely(bio_end_sector(bio) > mddev->array_sectors))
++ if (unlikely(bio_has_data(bio) && bio_end_sector(bio) > mddev->array_sectors))
+ return DM_MAPIO_REQUEUE;
+
+ md_handle_request(mddev, bio);
+diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
+index ddcb2bc4a6179..9511dae5b556a 100644
+--- a/drivers/md/dm-raid1.c
++++ b/drivers/md/dm-raid1.c
+@@ -278,7 +278,7 @@ static int mirror_flush(struct dm_target *ti)
+ }
+
+ error_bits = -1;
+- dm_io(&io_req, ms->nr_mirrors, io, &error_bits);
++ dm_io(&io_req, ms->nr_mirrors, io, &error_bits, IOPRIO_DEFAULT);
+ if (unlikely(error_bits != 0)) {
+ for (i = 0; i < ms->nr_mirrors; i++)
+ if (test_bit(i, &error_bits))
+@@ -554,7 +554,7 @@ static void read_async_bio(struct mirror *m, struct bio *bio)
+
+ map_region(&io, m, bio);
+ bio_set_m(bio, m);
+- BUG_ON(dm_io(&io_req, 1, &io, NULL));
++ BUG_ON(dm_io(&io_req, 1, &io, NULL, IOPRIO_DEFAULT));
+ }
+
+ static inline int region_in_sync(struct mirror_set *ms, region_t region,
+@@ -681,7 +681,7 @@ static void do_write(struct mirror_set *ms, struct bio *bio)
+ */
+ bio_set_m(bio, get_default_mirror(ms));
+
+- BUG_ON(dm_io(&io_req, ms->nr_mirrors, io, NULL));
++ BUG_ON(dm_io(&io_req, ms->nr_mirrors, io, NULL, IOPRIO_DEFAULT));
+ }
+
+ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
+diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
+index 15649921f2a9b..568d10842b1f4 100644
+--- a/drivers/md/dm-snap-persistent.c
++++ b/drivers/md/dm-snap-persistent.c
+@@ -223,7 +223,7 @@ static void do_metadata(struct work_struct *work)
+ {
+ struct mdata_req *req = container_of(work, struct mdata_req, work);
+
+- req->result = dm_io(req->io_req, 1, req->where, NULL);
++ req->result = dm_io(req->io_req, 1, req->where, NULL, IOPRIO_DEFAULT);
+ }
+
+ /*
+@@ -247,7 +247,7 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, blk_opf_t opf,
+ struct mdata_req req;
+
+ if (!metadata)
+- return dm_io(&io_req, 1, &where, NULL);
++ return dm_io(&io_req, 1, &where, NULL, IOPRIO_DEFAULT);
+
+ req.where = &where;
+ req.io_req = &io_req;
+diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
+index 1b591bfa90d5d..abc008bae9020 100644
+--- a/drivers/md/dm-verity-target.c
++++ b/drivers/md/dm-verity-target.c
+@@ -511,7 +511,7 @@ static noinline int verity_recheck(struct dm_verity *v, struct dm_verity_io *io,
+ io_loc.bdev = v->data_dev->bdev;
+ io_loc.sector = cur_block << (v->data_dev_block_bits - SECTOR_SHIFT);
+ io_loc.count = 1 << (v->data_dev_block_bits - SECTOR_SHIFT);
+- r = dm_io(&io_req, 1, &io_loc, NULL);
++ r = dm_io(&io_req, 1, &io_loc, NULL, IOPRIO_DEFAULT);
+ if (unlikely(r))
+ goto free_ret;
+
+diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
+index b463c28c39ad3..01ab141bc51e3 100644
+--- a/drivers/md/dm-writecache.c
++++ b/drivers/md/dm-writecache.c
+@@ -531,7 +531,7 @@ static void ssd_commit_flushed(struct dm_writecache *wc, bool wait_for_ios)
+ req.notify.context = &endio;
+
+ /* writing via async dm-io (implied by notify.fn above) won't return an error */
+- (void) dm_io(&req, 1, ®ion, NULL);
++ (void) dm_io(&req, 1, ®ion, NULL, IOPRIO_DEFAULT);
+ i = j;
+ }
+
+@@ -568,7 +568,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc)
+ req.notify.fn = NULL;
+ req.notify.context = NULL;
+
+- r = dm_io(&req, 1, ®ion, NULL);
++ r = dm_io(&req, 1, ®ion, NULL, IOPRIO_DEFAULT);
+ if (unlikely(r))
+ writecache_error(wc, r, "error writing superblock");
+ }
+@@ -596,7 +596,7 @@ static void writecache_disk_flush(struct dm_writecache *wc, struct dm_dev *dev)
+ req.client = wc->dm_io;
+ req.notify.fn = NULL;
+
+- r = dm_io(&req, 1, ®ion, NULL);
++ r = dm_io(&req, 1, ®ion, NULL, IOPRIO_DEFAULT);
+ if (unlikely(r))
+ writecache_error(wc, r, "error flushing metadata: %d", r);
+ }
+@@ -990,7 +990,7 @@ static int writecache_read_metadata(struct dm_writecache *wc, sector_t n_sectors
+ req.client = wc->dm_io;
+ req.notify.fn = NULL;
+
+- return dm_io(&req, 1, ®ion, NULL);
++ return dm_io(&req, 1, ®ion, NULL, IOPRIO_DEFAULT);
+ }
+
+ static void writecache_resume(struct dm_target *ti)
+diff --git a/drivers/md/dm.c b/drivers/md/dm.c
+index 8dcabf84d866e..0dc3650c7f4ca 100644
+--- a/drivers/md/dm.c
++++ b/drivers/md/dm.c
+@@ -2945,6 +2945,9 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned int suspend
+
+ static void __dm_internal_resume(struct mapped_device *md)
+ {
++ int r;
++ struct dm_table *map;
++
+ BUG_ON(!md->internal_suspend_count);
+
+ if (--md->internal_suspend_count)
+@@ -2953,12 +2956,23 @@ static void __dm_internal_resume(struct mapped_device *md)
+ if (dm_suspended_md(md))
+ goto done; /* resume from nested suspend */
+
+- /*
+- * NOTE: existing callers don't need to call dm_table_resume_targets
+- * (which may fail -- so best to avoid it for now by passing NULL map)
+- */
+- (void) __dm_resume(md, NULL);
+-
++ map = rcu_dereference_protected(md->map, lockdep_is_held(&md->suspend_lock));
++ r = __dm_resume(md, map);
++ if (r) {
++ /*
++ * If a preresume method of some target failed, we are in a
++ * tricky situation. We can't return an error to the caller. We
++ * can't fake success because then the "resume" and
++ * "postsuspend" methods would not be paired correctly, and it
++ * would break various targets, for example it would cause list
++ * corruption in the "origin" target.
++ *
++ * So, we fake normal suspend here, to make sure that the
++ * "resume" and "postsuspend" methods will be paired correctly.
++ */
++ DMERR("Preresume method failed: %d", r);
++ set_bit(DMF_SUSPENDED, &md->flags);
++ }
+ done:
+ clear_bit(DMF_SUSPENDED_INTERNALLY, &md->flags);
+ smp_mb__after_atomic();
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 9e41a9aaba8b5..d344e6fa3b26f 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -2566,6 +2566,7 @@ static int bind_rdev_to_array(struct md_rdev *rdev, struct mddev *mddev)
+ fail:
+ pr_warn("md: failed to register dev-%s for %s\n",
+ b, mdname(mddev));
++ mddev_destroy_serial_pool(mddev, rdev);
+ return err;
+ }
+
+@@ -6278,7 +6279,15 @@ static void md_clean(struct mddev *mddev)
+ mddev->persistent = 0;
+ mddev->level = LEVEL_NONE;
+ mddev->clevel[0] = 0;
+- mddev->flags = 0;
++ /*
++ * Don't clear MD_CLOSING, or mddev can be opened again.
++ * 'hold_active != 0' means mddev is still in the creation
++ * process and will be used later.
++ */
++ if (mddev->hold_active)
++ mddev->flags = 0;
++ else
++ mddev->flags &= BIT_ULL_MASK(MD_CLOSING);
+ mddev->sb_flags = 0;
+ mddev->ro = MD_RDWR;
+ mddev->metadata_type[0] = 0;
+@@ -7624,7 +7633,6 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
+ int err = 0;
+ void __user *argp = (void __user *)arg;
+ struct mddev *mddev = NULL;
+- bool did_set_md_closing = false;
+
+ if (!md_ioctl_valid(cmd))
+ return -ENOTTY;
+@@ -7708,7 +7716,6 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
+ err = -EBUSY;
+ goto out;
+ }
+- did_set_md_closing = true;
+ mutex_unlock(&mddev->open_mutex);
+ sync_blockdev(bdev);
+ }
+@@ -7850,7 +7857,7 @@ static int md_ioctl(struct block_device *bdev, blk_mode_t mode,
+ mddev_unlock(mddev);
+
+ out:
+- if(did_set_md_closing)
++ if (cmd == STOP_ARRAY_RO || (err && cmd == STOP_ARRAY))
+ clear_bit(MD_CLOSING, &mddev->flags);
+ return err;
+ }
+diff --git a/drivers/md/md.h b/drivers/md/md.h
+index 8d881cc597992..27d187ca6258a 100644
+--- a/drivers/md/md.h
++++ b/drivers/md/md.h
+@@ -207,6 +207,7 @@ enum flag_bits {
+ * check if there is collision between raid1
+ * serial bios.
+ */
++ Nonrot, /* non-rotational device (SSD) */
+ };
+
+ static inline int is_badblock(struct md_rdev *rdev, sector_t s, int sectors,
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 286f8b16c7bde..82c9bb404ccca 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -601,14 +601,12 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
+ const sector_t this_sector = r1_bio->sector;
+ int sectors;
+ int best_good_sectors;
+- int best_disk, best_dist_disk, best_pending_disk;
+- int has_nonrot_disk;
++ int best_disk, best_dist_disk, best_pending_disk, sequential_disk;
+ int disk;
+ sector_t best_dist;
+ unsigned int min_pending;
+ struct md_rdev *rdev;
+ int choose_first;
+- int choose_next_idle;
+
+ /*
+ * Check if we can balance. We can balance on the whole
+@@ -619,12 +617,11 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
+ sectors = r1_bio->sectors;
+ best_disk = -1;
+ best_dist_disk = -1;
++ sequential_disk = -1;
+ best_dist = MaxSector;
+ best_pending_disk = -1;
+ min_pending = UINT_MAX;
+ best_good_sectors = 0;
+- has_nonrot_disk = 0;
+- choose_next_idle = 0;
+ clear_bit(R1BIO_FailFast, &r1_bio->state);
+
+ if ((conf->mddev->recovery_cp < this_sector + sectors) ||
+@@ -640,7 +637,6 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
+ sector_t first_bad;
+ int bad_sectors;
+ unsigned int pending;
+- bool nonrot;
+
+ rdev = conf->mirrors[disk].rdev;
+ if (r1_bio->bios[disk] == IO_BLOCKED
+@@ -706,8 +702,6 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
+ /* At least two disks to choose from so failfast is OK */
+ set_bit(R1BIO_FailFast, &r1_bio->state);
+
+- nonrot = bdev_nonrot(rdev->bdev);
+- has_nonrot_disk |= nonrot;
+ pending = atomic_read(&rdev->nr_pending);
+ dist = abs(this_sector - conf->mirrors[disk].head_position);
+ if (choose_first) {
+@@ -720,7 +714,6 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
+ int opt_iosize = bdev_io_opt(rdev->bdev) >> 9;
+ struct raid1_info *mirror = &conf->mirrors[disk];
+
+- best_disk = disk;
+ /*
+ * If buffered sequential IO size exceeds optimal
+ * iosize, check if there is idle disk. If yes, choose
+@@ -734,20 +727,27 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
+ * small, but not a big deal since when the second disk
+ * starts IO, the first disk is likely still busy.
+ */
+- if (nonrot && opt_iosize > 0 &&
++ if (test_bit(Nonrot, &rdev->flags) && opt_iosize > 0 &&
+ mirror->seq_start != MaxSector &&
+ mirror->next_seq_sect > opt_iosize &&
+ mirror->next_seq_sect - opt_iosize >=
+ mirror->seq_start) {
+- choose_next_idle = 1;
+- continue;
++ /*
++ * Add 'pending' to avoid choosing this disk if
++ * there is other idle disk.
++ */
++ pending++;
++ /*
++ * If there is no other idle disk, this disk
++ * will be chosen.
++ */
++ sequential_disk = disk;
++ } else {
++ best_disk = disk;
++ break;
+ }
+- break;
+ }
+
+- if (choose_next_idle)
+- continue;
+-
+ if (min_pending > pending) {
+ min_pending = pending;
+ best_pending_disk = disk;
+@@ -759,6 +759,13 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
+ }
+ }
+
++ /*
++ * sequential IO size exceeds optimal iosize, however, there is no other
++ * idle disk, so choose the sequential disk.
++ */
++ if (best_disk == -1 && min_pending != 0)
++ best_disk = sequential_disk;
++
+ /*
+ * If all disks are rotational, choose the closest disk. If any disk is
+ * non-rotational, choose the disk with less pending request even the
+@@ -766,7 +773,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
+ * mixed ratation/non-rotational disks depending on workload.
+ */
+ if (best_disk == -1) {
+- if (has_nonrot_disk || min_pending == 0)
++ if (READ_ONCE(conf->nonrot_disks) || min_pending == 0)
+ best_disk = best_pending_disk;
+ else
+ best_disk = best_dist_disk;
+@@ -1760,6 +1767,52 @@ static int raid1_spare_active(struct mddev *mddev)
+ return count;
+ }
+
++static bool raid1_add_conf(struct r1conf *conf, struct md_rdev *rdev, int disk,
++ bool replacement)
++{
++ struct raid1_info *info = conf->mirrors + disk;
++
++ if (replacement)
++ info += conf->raid_disks;
++
++ if (info->rdev)
++ return false;
++
++ if (bdev_nonrot(rdev->bdev)) {
++ set_bit(Nonrot, &rdev->flags);
++ WRITE_ONCE(conf->nonrot_disks, conf->nonrot_disks + 1);
++ }
++
++ rdev->raid_disk = disk;
++ info->head_position = 0;
++ info->seq_start = MaxSector;
++ WRITE_ONCE(info->rdev, rdev);
++
++ return true;
++}
++
++static bool raid1_remove_conf(struct r1conf *conf, int disk)
++{
++ struct raid1_info *info = conf->mirrors + disk;
++ struct md_rdev *rdev = info->rdev;
++
++ if (!rdev || test_bit(In_sync, &rdev->flags) ||
++ atomic_read(&rdev->nr_pending))
++ return false;
++
++ /* Only remove non-faulty devices if recovery is not possible. */
++ if (!test_bit(Faulty, &rdev->flags) &&
++ rdev->mddev->recovery_disabled != conf->recovery_disabled &&
++ rdev->mddev->degraded < conf->raid_disks)
++ return false;
++
++ if (test_and_clear_bit(Nonrot, &rdev->flags))
++ WRITE_ONCE(conf->nonrot_disks, conf->nonrot_disks - 1);
++
++ WRITE_ONCE(info->rdev, NULL);
++ return true;
++}
++
+ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
+ {
+ struct r1conf *conf = mddev->private;
+@@ -1795,15 +1848,13 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
+ disk_stack_limits(mddev->gendisk, rdev->bdev,
+ rdev->data_offset << 9);
+
+- p->head_position = 0;
+- rdev->raid_disk = mirror;
++ raid1_add_conf(conf, rdev, mirror, false);
+ err = 0;
+ /* As all devices are equivalent, we don't need a full recovery
+ * if this was recently any drive of the array
+ */
+ if (rdev->saved_raid_disk < 0)
+ conf->fullsync = 1;
+- WRITE_ONCE(p->rdev, rdev);
+ break;
+ }
+ if (test_bit(WantReplacement, &p->rdev->flags) &&
+@@ -1813,13 +1864,11 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
+
+ if (err && repl_slot >= 0) {
+ /* Add this device as a replacement */
+- p = conf->mirrors + repl_slot;
+ clear_bit(In_sync, &rdev->flags);
+ set_bit(Replacement, &rdev->flags);
+- rdev->raid_disk = repl_slot;
++ raid1_add_conf(conf, rdev, repl_slot, true);
+ err = 0;
+ conf->fullsync = 1;
+- WRITE_ONCE(p[conf->raid_disks].rdev, rdev);
+ }
+
+ print_conf(conf);
+@@ -1836,27 +1885,20 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
+ if (unlikely(number >= conf->raid_disks))
+ goto abort;
+
+- if (rdev != p->rdev)
+- p = conf->mirrors + conf->raid_disks + number;
++ if (rdev != p->rdev) {
++ number += conf->raid_disks;
++ p = conf->mirrors + number;
++ }
+
+ print_conf(conf);
+ if (rdev == p->rdev) {
+- if (test_bit(In_sync, &rdev->flags) ||
+- atomic_read(&rdev->nr_pending)) {
+- err = -EBUSY;
+- goto abort;
+- }
+- /* Only remove non-faulty devices if recovery
+- * is not possible.
+- */
+- if (!test_bit(Faulty, &rdev->flags) &&
+- mddev->recovery_disabled != conf->recovery_disabled &&
+- mddev->degraded < conf->raid_disks) {
++ if (!raid1_remove_conf(conf, number)) {
+ err = -EBUSY;
+ goto abort;
+ }
+- WRITE_ONCE(p->rdev, NULL);
+- if (conf->mirrors[conf->raid_disks + number].rdev) {
++
++ if (number < conf->raid_disks &&
++ conf->mirrors[conf->raid_disks + number].rdev) {
+ /* We just removed a device that is being replaced.
+ * Move down the replacement. We drain all IO before
+ * doing this to avoid confusion.
+@@ -3006,23 +3048,17 @@ static struct r1conf *setup_conf(struct mddev *mddev)
+
+ err = -EINVAL;
+ spin_lock_init(&conf->device_lock);
++ conf->raid_disks = mddev->raid_disks;
+ rdev_for_each(rdev, mddev) {
+ int disk_idx = rdev->raid_disk;
+- if (disk_idx >= mddev->raid_disks
+- || disk_idx < 0)
++
++ if (disk_idx >= conf->raid_disks || disk_idx < 0)
+ continue;
+- if (test_bit(Replacement, &rdev->flags))
+- disk = conf->mirrors + mddev->raid_disks + disk_idx;
+- else
+- disk = conf->mirrors + disk_idx;
+
+- if (disk->rdev)
++ if (!raid1_add_conf(conf, rdev, disk_idx,
++ test_bit(Replacement, &rdev->flags)))
+ goto abort;
+- disk->rdev = rdev;
+- disk->head_position = 0;
+- disk->seq_start = MaxSector;
+ }
+- conf->raid_disks = mddev->raid_disks;
+ conf->mddev = mddev;
+ INIT_LIST_HEAD(&conf->retry_list);
+ INIT_LIST_HEAD(&conf->bio_end_io_list);
+diff --git a/drivers/md/raid1.h b/drivers/md/raid1.h
+index 14d4211a123a8..5300cbaa58a41 100644
+--- a/drivers/md/raid1.h
++++ b/drivers/md/raid1.h
+@@ -71,6 +71,7 @@ struct r1conf {
+ * allow for replacements.
+ */
+ int raid_disks;
++ int nonrot_disks;
+
+ spinlock_t device_lock;
+
+diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
+index a366566f22c3b..642c48e8c1f58 100644
+--- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
++++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
+@@ -113,6 +113,7 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
+ {
+ unsigned pat;
+ unsigned plane;
++ int ret = 0;
+
+ tpg->max_line_width = max_w;
+ for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++) {
+@@ -121,14 +122,18 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
+
+ tpg->lines[pat][plane] =
+ vzalloc(array3_size(max_w, 2, pixelsz));
+- if (!tpg->lines[pat][plane])
+- return -ENOMEM;
++ if (!tpg->lines[pat][plane]) {
++ ret = -ENOMEM;
++ goto free_lines;
++ }
+ if (plane == 0)
+ continue;
+ tpg->downsampled_lines[pat][plane] =
+ vzalloc(array3_size(max_w, 2, pixelsz));
+- if (!tpg->downsampled_lines[pat][plane])
+- return -ENOMEM;
++ if (!tpg->downsampled_lines[pat][plane]) {
++ ret = -ENOMEM;
++ goto free_lines;
++ }
+ }
+ }
+ for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
+@@ -136,18 +141,45 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
+
+ tpg->contrast_line[plane] =
+ vzalloc(array_size(pixelsz, max_w));
+- if (!tpg->contrast_line[plane])
+- return -ENOMEM;
++ if (!tpg->contrast_line[plane]) {
++ ret = -ENOMEM;
++ goto free_contrast_line;
++ }
+ tpg->black_line[plane] =
+ vzalloc(array_size(pixelsz, max_w));
+- if (!tpg->black_line[plane])
+- return -ENOMEM;
++ if (!tpg->black_line[plane]) {
++ ret = -ENOMEM;
++ goto free_contrast_line;
++ }
+ tpg->random_line[plane] =
+ vzalloc(array3_size(max_w, 2, pixelsz));
+- if (!tpg->random_line[plane])
+- return -ENOMEM;
++ if (!tpg->random_line[plane]) {
++ ret = -ENOMEM;
++ goto free_contrast_line;
++ }
+ }
+ return 0;
++
++free_contrast_line:
++ for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
++ vfree(tpg->contrast_line[plane]);
++ vfree(tpg->black_line[plane]);
++ vfree(tpg->random_line[plane]);
++ tpg->contrast_line[plane] = NULL;
++ tpg->black_line[plane] = NULL;
++ tpg->random_line[plane] = NULL;
++ }
++free_lines:
++ for (pat = 0; pat < TPG_MAX_PAT_LINES; pat++)
++ for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
++ vfree(tpg->lines[pat][plane]);
++ tpg->lines[pat][plane] = NULL;
++ if (plane == 0)
++ continue;
++ vfree(tpg->downsampled_lines[pat][plane]);
++ tpg->downsampled_lines[pat][plane] = NULL;
++ }
++ return ret;
+ }
+ EXPORT_SYMBOL_GPL(tpg_alloc);
+
+diff --git a/drivers/media/dvb-core/dvbdev.c b/drivers/media/dvb-core/dvbdev.c
+index 49f0eb7d0b9d3..733d0bc4b4cc3 100644
+--- a/drivers/media/dvb-core/dvbdev.c
++++ b/drivers/media/dvb-core/dvbdev.c
+@@ -490,6 +490,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ dvbdevfops = kmemdup(template->fops, sizeof(*dvbdevfops), GFP_KERNEL);
+ if (!dvbdevfops) {
+ kfree(dvbdev);
++ *pdvbdev = NULL;
+ mutex_unlock(&dvbdev_register_lock);
+ return -ENOMEM;
+ }
+@@ -498,6 +499,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ if (!new_node) {
+ kfree(dvbdevfops);
+ kfree(dvbdev);
++ *pdvbdev = NULL;
+ mutex_unlock(&dvbdev_register_lock);
+ return -ENOMEM;
+ }
+@@ -531,6 +533,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ }
+ list_del(&dvbdev->list_head);
+ kfree(dvbdev);
++ *pdvbdev = NULL;
+ up_write(&minor_rwsem);
+ mutex_unlock(&dvbdev_register_lock);
+ return -EINVAL;
+@@ -553,6 +556,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ dvb_media_device_free(dvbdev);
+ list_del(&dvbdev->list_head);
+ kfree(dvbdev);
++ *pdvbdev = NULL;
+ mutex_unlock(&dvbdev_register_lock);
+ return ret;
+ }
+@@ -571,6 +575,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
+ dvb_media_device_free(dvbdev);
+ list_del(&dvbdev->list_head);
+ kfree(dvbdev);
++ *pdvbdev = NULL;
+ mutex_unlock(&dvbdev_register_lock);
+ return PTR_ERR(clsdev);
+ }
+diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c
+index 48326434488c4..72540ef4e5f88 100644
+--- a/drivers/media/dvb-frontends/stv0367.c
++++ b/drivers/media/dvb-frontends/stv0367.c
+@@ -118,50 +118,32 @@ static const s32 stv0367cab_RF_LookUp2[RF_LOOKUP_TABLE2_SIZE][RF_LOOKUP_TABLE2_S
+ }
+ };
+
+-static
+-int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len)
++static noinline_for_stack
++int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data)
+ {
+- u8 buf[MAX_XFER_SIZE];
++ u8 buf[3] = { MSB(reg), LSB(reg), data };
+ struct i2c_msg msg = {
+ .addr = state->config->demod_address,
+ .flags = 0,
+ .buf = buf,
+- .len = len + 2
++ .len = 3,
+ };
+ int ret;
+
+- if (2 + len > sizeof(buf)) {
+- printk(KERN_WARNING
+- "%s: i2c wr reg=%04x: len=%d is too big!\n",
+- KBUILD_MODNAME, reg, len);
+- return -EINVAL;
+- }
+-
+-
+- buf[0] = MSB(reg);
+- buf[1] = LSB(reg);
+- memcpy(buf + 2, data, len);
+-
+ if (i2cdebug)
+ printk(KERN_DEBUG "%s: [%02x] %02x: %02x\n", __func__,
+- state->config->demod_address, reg, buf[2]);
++ state->config->demod_address, reg, data);
+
+ ret = i2c_transfer(state->i2c, &msg, 1);
+ if (ret != 1)
+ printk(KERN_ERR "%s: i2c write error! ([%02x] %02x: %02x)\n",
+- __func__, state->config->demod_address, reg, buf[2]);
++ __func__, state->config->demod_address, reg, data);
+
+ return (ret != 1) ? -EREMOTEIO : 0;
+ }
+
+-static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data)
+-{
+- u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+-
+- return stv0367_writeregs(state, reg, &tmp, 1);
+-}
+-
+-static u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
++static noinline_for_stack
++u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
+ {
+ u8 b0[] = { 0, 0 };
+ u8 b1[] = { 0 };
+diff --git a/drivers/media/i2c/imx290.c b/drivers/media/i2c/imx290.c
+index 9967f34774334..4150e6e4b9a63 100644
+--- a/drivers/media/i2c/imx290.c
++++ b/drivers/media/i2c/imx290.c
+@@ -150,10 +150,10 @@
+
+ #define IMX290_PIXEL_ARRAY_WIDTH 1945
+ #define IMX290_PIXEL_ARRAY_HEIGHT 1097
+-#define IMX920_PIXEL_ARRAY_MARGIN_LEFT 12
+-#define IMX920_PIXEL_ARRAY_MARGIN_RIGHT 13
+-#define IMX920_PIXEL_ARRAY_MARGIN_TOP 8
+-#define IMX920_PIXEL_ARRAY_MARGIN_BOTTOM 9
++#define IMX290_PIXEL_ARRAY_MARGIN_LEFT 12
++#define IMX290_PIXEL_ARRAY_MARGIN_RIGHT 13
++#define IMX290_PIXEL_ARRAY_MARGIN_TOP 8
++#define IMX290_PIXEL_ARRAY_MARGIN_BOTTOM 9
+ #define IMX290_PIXEL_ARRAY_RECORDING_WIDTH 1920
+ #define IMX290_PIXEL_ARRAY_RECORDING_HEIGHT 1080
+
+@@ -1161,10 +1161,10 @@ static int imx290_get_selection(struct v4l2_subdev *sd,
+ * The sensor moves the readout by 1 pixel based on flips to
+ * keep the Bayer order the same.
+ */
+- sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP
++ sel->r.top = IMX290_PIXEL_ARRAY_MARGIN_TOP
+ + (IMX290_PIXEL_ARRAY_RECORDING_HEIGHT - format->height) / 2
+ + imx290->vflip->val;
+- sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT
++ sel->r.left = IMX290_PIXEL_ARRAY_MARGIN_LEFT
+ + (IMX290_PIXEL_ARRAY_RECORDING_WIDTH - format->width) / 2
+ + imx290->hflip->val;
+ sel->r.width = format->width;
+@@ -1183,8 +1183,8 @@ static int imx290_get_selection(struct v4l2_subdev *sd,
+ return 0;
+
+ case V4L2_SEL_TGT_CROP_DEFAULT:
+- sel->r.top = IMX920_PIXEL_ARRAY_MARGIN_TOP;
+- sel->r.left = IMX920_PIXEL_ARRAY_MARGIN_LEFT;
++ sel->r.top = IMX290_PIXEL_ARRAY_MARGIN_TOP;
++ sel->r.left = IMX290_PIXEL_ARRAY_MARGIN_LEFT;
+ sel->r.width = IMX290_PIXEL_ARRAY_RECORDING_WIDTH;
+ sel->r.height = IMX290_PIXEL_ARRAY_RECORDING_HEIGHT;
+
+diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c
+index 2785935da497b..558152575d102 100644
+--- a/drivers/media/i2c/tc358743.c
++++ b/drivers/media/i2c/tc358743.c
+@@ -2091,9 +2091,6 @@ static int tc358743_probe(struct i2c_client *client)
+ state->mbus_fmt_code = MEDIA_BUS_FMT_RGB888_1X24;
+
+ sd->dev = &client->dev;
+- err = v4l2_async_register_subdev(sd);
+- if (err < 0)
+- goto err_hdl;
+
+ mutex_init(&state->confctl_mutex);
+
+@@ -2151,6 +2148,10 @@ static int tc358743_probe(struct i2c_client *client)
+ if (err)
+ goto err_work_queues;
+
++ err = v4l2_async_register_subdev(sd);
++ if (err < 0)
++ goto err_work_queues;
++
+ v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
+ client->addr << 1, client->adapter->name);
+
+diff --git a/drivers/media/pci/intel/ivsc/mei_csi.c b/drivers/media/pci/intel/ivsc/mei_csi.c
+index 15b905f66ab72..3c74d06a27fad 100644
+--- a/drivers/media/pci/intel/ivsc/mei_csi.c
++++ b/drivers/media/pci/intel/ivsc/mei_csi.c
+@@ -71,8 +71,8 @@ enum ivsc_privacy_status {
+ };
+
+ enum csi_pads {
+- CSI_PAD_SOURCE,
+ CSI_PAD_SINK,
++ CSI_PAD_SOURCE,
+ CSI_NUM_PADS
+ };
+
+@@ -587,7 +587,7 @@ static int mei_csi_notify_bound(struct v4l2_async_notifier *notifier,
+ csi->remote_pad = pad;
+
+ return media_create_pad_link(&subdev->entity, pad,
+- &csi->subdev.entity, 1,
++ &csi->subdev.entity, CSI_PAD_SINK,
+ MEDIA_LNK_FL_ENABLED |
+ MEDIA_LNK_FL_IMMUTABLE);
+ }
+diff --git a/drivers/media/pci/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c
+index 230b104a7cdf0..a47c5850ef875 100644
+--- a/drivers/media/pci/ttpci/budget-av.c
++++ b/drivers/media/pci/ttpci/budget-av.c
+@@ -1463,7 +1463,8 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
+ budget_av->has_saa7113 = 1;
+ err = saa7146_vv_init(dev, &vv_data);
+ if (err != 0) {
+- /* fixme: proper cleanup here */
++ ttpci_budget_deinit(&budget_av->budget);
++ kfree(budget_av);
+ ERR("cannot init vv subsystem\n");
+ return err;
+ }
+@@ -1472,9 +1473,10 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
+ vv_data.vid_ops.vidioc_s_input = vidioc_s_input;
+
+ if ((err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_VIDEO))) {
+- /* fixme: proper cleanup here */
+- ERR("cannot register capture v4l2 device\n");
+ saa7146_vv_release(dev);
++ ttpci_budget_deinit(&budget_av->budget);
++ kfree(budget_av);
++ ERR("cannot register capture v4l2 device\n");
+ return err;
+ }
+
+diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
+index fead5426830e8..0ea5fa956fe9a 100644
+--- a/drivers/media/platform/cadence/cdns-csi2rx.c
++++ b/drivers/media/platform/cadence/cdns-csi2rx.c
+@@ -468,7 +468,7 @@ static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
+ struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev);
+
+ csi2rx->source_pad = media_entity_get_fwnode_pad(&s_subdev->entity,
+- s_subdev->fwnode,
++ asd->match.fwnode,
+ MEDIA_PAD_FL_SOURCE);
+ if (csi2rx->source_pad < 0) {
+ dev_err(csi2rx->dev, "Couldn't find output pad for subdev %s\n",
+diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_vpu.c b/drivers/media/platform/mediatek/mdp/mtk_mdp_vpu.c
+index b065ccd069140..378a1cba0144f 100644
+--- a/drivers/media/platform/mediatek/mdp/mtk_mdp_vpu.c
++++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_vpu.c
+@@ -26,7 +26,7 @@ static void mtk_mdp_vpu_handle_init_ack(const struct mdp_ipi_comm_ack *msg)
+ vpu->inst_addr = msg->vpu_inst_addr;
+ }
+
+-static void mtk_mdp_vpu_ipi_handler(const void *data, unsigned int len,
++static void mtk_mdp_vpu_ipi_handler(void *data, unsigned int len,
+ void *priv)
+ {
+ const struct mdp_ipi_comm_ack *msg = data;
+diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c
+index 9f6e4b59455da..4c34344dc7dcb 100644
+--- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c
++++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c
+@@ -29,15 +29,7 @@ static int mtk_vcodec_vpu_set_ipi_register(struct mtk_vcodec_fw *fw, int id,
+ mtk_vcodec_ipi_handler handler,
+ const char *name, void *priv)
+ {
+- /*
+- * The handler we receive takes a void * as its first argument. We
+- * cannot change this because it needs to be passed down to the rproc
+- * subsystem when SCP is used. VPU takes a const argument, which is
+- * more constrained, so the conversion below is safe.
+- */
+- ipi_handler_t handler_const = (ipi_handler_t)handler;
+-
+- return vpu_ipi_register(fw->pdev, id, handler_const, name, priv);
++ return vpu_ipi_register(fw->pdev, id, handler, name, priv);
+ }
+
+ static int mtk_vcodec_vpu_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf,
+diff --git a/drivers/media/platform/mediatek/vpu/mtk_vpu.c b/drivers/media/platform/mediatek/vpu/mtk_vpu.c
+index 7243604a82a5b..724ae7c2ab3ba 100644
+--- a/drivers/media/platform/mediatek/vpu/mtk_vpu.c
++++ b/drivers/media/platform/mediatek/vpu/mtk_vpu.c
+@@ -635,7 +635,7 @@ int vpu_load_firmware(struct platform_device *pdev)
+ }
+ EXPORT_SYMBOL_GPL(vpu_load_firmware);
+
+-static void vpu_init_ipi_handler(const void *data, unsigned int len, void *priv)
++static void vpu_init_ipi_handler(void *data, unsigned int len, void *priv)
+ {
+ struct mtk_vpu *vpu = priv;
+ const struct vpu_run *run = data;
+diff --git a/drivers/media/platform/mediatek/vpu/mtk_vpu.h b/drivers/media/platform/mediatek/vpu/mtk_vpu.h
+index a56053ff135af..da05f3e740810 100644
+--- a/drivers/media/platform/mediatek/vpu/mtk_vpu.h
++++ b/drivers/media/platform/mediatek/vpu/mtk_vpu.h
+@@ -17,7 +17,7 @@
+ * VPU interfaces with other blocks by share memory and interrupt.
+ */
+
+-typedef void (*ipi_handler_t) (const void *data,
++typedef void (*ipi_handler_t) (void *data,
+ unsigned int len,
+ void *priv);
+
+diff --git a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
+index 954fabec27f63..a1c35a2b68ed9 100644
+--- a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
++++ b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c
+@@ -66,6 +66,7 @@ static void deinterlace_device_run(void *priv)
+ struct vb2_v4l2_buffer *src, *dst;
+ unsigned int hstep, vstep;
+ dma_addr_t addr;
++ int i;
+
+ src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+ dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+@@ -160,6 +161,26 @@ static void deinterlace_device_run(void *priv)
+ deinterlace_write(dev, DEINTERLACE_CH1_HORZ_FACT, hstep);
+ deinterlace_write(dev, DEINTERLACE_CH1_VERT_FACT, vstep);
+
++ /* neutral filter coefficients */
++ deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
++ DEINTERLACE_FRM_CTRL_COEF_ACCESS);
++ readl_poll_timeout(dev->base + DEINTERLACE_STATUS, val,
++ val & DEINTERLACE_STATUS_COEF_STATUS, 2, 40);
++
++ for (i = 0; i < 32; i++) {
++ deinterlace_write(dev, DEINTERLACE_CH0_HORZ_COEF0 + i * 4,
++ DEINTERLACE_IDENTITY_COEF);
++ deinterlace_write(dev, DEINTERLACE_CH0_VERT_COEF + i * 4,
++ DEINTERLACE_IDENTITY_COEF);
++ deinterlace_write(dev, DEINTERLACE_CH1_HORZ_COEF0 + i * 4,
++ DEINTERLACE_IDENTITY_COEF);
++ deinterlace_write(dev, DEINTERLACE_CH1_VERT_COEF + i * 4,
++ DEINTERLACE_IDENTITY_COEF);
++ }
++
++ deinterlace_clr_set_bits(dev, DEINTERLACE_FRM_CTRL,
++ DEINTERLACE_FRM_CTRL_COEF_ACCESS, 0);
++
+ deinterlace_clr_set_bits(dev, DEINTERLACE_FIELD_CTRL,
+ DEINTERLACE_FIELD_CTRL_FIELD_CNT_MSK,
+ DEINTERLACE_FIELD_CTRL_FIELD_CNT(ctx->field));
+@@ -248,7 +269,6 @@ static irqreturn_t deinterlace_irq(int irq, void *data)
+ static void deinterlace_init(struct deinterlace_dev *dev)
+ {
+ u32 val;
+- int i;
+
+ deinterlace_write(dev, DEINTERLACE_BYPASS,
+ DEINTERLACE_BYPASS_CSC);
+@@ -284,27 +304,7 @@ static void deinterlace_init(struct deinterlace_dev *dev)
+
+ deinterlace_clr_set_bits(dev, DEINTERLACE_CHROMA_DIFF,
+ DEINTERLACE_CHROMA_DIFF_TH_MSK,
+- DEINTERLACE_CHROMA_DIFF_TH(5));
+-
+- /* neutral filter coefficients */
+- deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL,
+- DEINTERLACE_FRM_CTRL_COEF_ACCESS);
+- readl_poll_timeout(dev->base + DEINTERLACE_STATUS, val,
+- val & DEINTERLACE_STATUS_COEF_STATUS, 2, 40);
+-
+- for (i = 0; i < 32; i++) {
+- deinterlace_write(dev, DEINTERLACE_CH0_HORZ_COEF0 + i * 4,
+- DEINTERLACE_IDENTITY_COEF);
+- deinterlace_write(dev, DEINTERLACE_CH0_VERT_COEF + i * 4,
+- DEINTERLACE_IDENTITY_COEF);
+- deinterlace_write(dev, DEINTERLACE_CH1_HORZ_COEF0 + i * 4,
+- DEINTERLACE_IDENTITY_COEF);
+- deinterlace_write(dev, DEINTERLACE_CH1_VERT_COEF + i * 4,
+- DEINTERLACE_IDENTITY_COEF);
+- }
+-
+- deinterlace_clr_set_bits(dev, DEINTERLACE_FRM_CTRL,
+- DEINTERLACE_FRM_CTRL_COEF_ACCESS, 0);
++ DEINTERLACE_CHROMA_DIFF_TH(31));
+ }
+
+ static inline struct deinterlace_ctx *deinterlace_file2ctx(struct file *file)
+@@ -929,11 +929,18 @@ static int deinterlace_runtime_resume(struct device *device)
+ return ret;
+ }
+
++ ret = reset_control_deassert(dev->rstc);
++ if (ret) {
++ dev_err(dev->dev, "Failed to apply reset\n");
++
++ goto err_exclusive_rate;
++ }
++
+ ret = clk_prepare_enable(dev->bus_clk);
+ if (ret) {
+ dev_err(dev->dev, "Failed to enable bus clock\n");
+
+- goto err_exclusive_rate;
++ goto err_rst;
+ }
+
+ ret = clk_prepare_enable(dev->mod_clk);
+@@ -950,23 +957,16 @@ static int deinterlace_runtime_resume(struct device *device)
+ goto err_mod_clk;
+ }
+
+- ret = reset_control_deassert(dev->rstc);
+- if (ret) {
+- dev_err(dev->dev, "Failed to apply reset\n");
+-
+- goto err_ram_clk;
+- }
+-
+ deinterlace_init(dev);
+
+ return 0;
+
+-err_ram_clk:
+- clk_disable_unprepare(dev->ram_clk);
+ err_mod_clk:
+ clk_disable_unprepare(dev->mod_clk);
+ err_bus_clk:
+ clk_disable_unprepare(dev->bus_clk);
++err_rst:
++ reset_control_assert(dev->rstc);
+ err_exclusive_rate:
+ clk_rate_exclusive_put(dev->mod_clk);
+
+@@ -977,11 +977,12 @@ static int deinterlace_runtime_suspend(struct device *device)
+ {
+ struct deinterlace_dev *dev = dev_get_drvdata(device);
+
+- reset_control_assert(dev->rstc);
+-
+ clk_disable_unprepare(dev->ram_clk);
+ clk_disable_unprepare(dev->mod_clk);
+ clk_disable_unprepare(dev->bus_clk);
++
++ reset_control_assert(dev->rstc);
++
+ clk_rate_exclusive_put(dev->mod_clk);
+
+ return 0;
+diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
+index 4d037c92af7c5..bae76023cf71d 100644
+--- a/drivers/media/usb/em28xx/em28xx-cards.c
++++ b/drivers/media/usb/em28xx/em28xx-cards.c
+@@ -4094,6 +4094,10 @@ static int em28xx_usb_probe(struct usb_interface *intf,
+ * topology will likely change after the load of the em28xx subdrivers.
+ */
+ #ifdef CONFIG_MEDIA_CONTROLLER
++ /*
++ * No need to check the return value, the device will still be
++ * usable without media controller API.
++ */
+ retval = media_device_register(dev->media_dev);
+ #endif
+
+diff --git a/drivers/media/usb/go7007/go7007-driver.c b/drivers/media/usb/go7007/go7007-driver.c
+index 0c24e29843048..eb03f98b2ef11 100644
+--- a/drivers/media/usb/go7007/go7007-driver.c
++++ b/drivers/media/usb/go7007/go7007-driver.c
+@@ -80,7 +80,7 @@ static int go7007_load_encoder(struct go7007 *go)
+ const struct firmware *fw_entry;
+ char fw_name[] = "go7007/go7007fw.bin";
+ void *bounce;
+- int fw_len, rv = 0;
++ int fw_len;
+ u16 intr_val, intr_data;
+
+ if (go->boot_fw == NULL) {
+@@ -109,9 +109,11 @@ static int go7007_load_encoder(struct go7007 *go)
+ go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
+ (intr_val & ~0x1) != 0x5a5a) {
+ v4l2_err(go, "error transferring firmware\n");
+- rv = -1;
++ kfree(go->boot_fw);
++ go->boot_fw = NULL;
++ return -1;
+ }
+- return rv;
++ return 0;
+ }
+
+ MODULE_FIRMWARE("go7007/go7007fw.bin");
+diff --git a/drivers/media/usb/go7007/go7007-usb.c b/drivers/media/usb/go7007/go7007-usb.c
+index eeb85981e02b6..762c13e49bfa5 100644
+--- a/drivers/media/usb/go7007/go7007-usb.c
++++ b/drivers/media/usb/go7007/go7007-usb.c
+@@ -1201,7 +1201,9 @@ static int go7007_usb_probe(struct usb_interface *intf,
+ u16 channel;
+
+ /* read channel number from GPIO[1:0] */
+- go7007_read_addr(go, 0x3c81, &channel);
++ if (go7007_read_addr(go, 0x3c81, &channel))
++ goto allocfail;
++
+ channel &= 0x3;
+ go->board_id = GO7007_BOARDID_ADLINK_MPG24;
+ usb->board = board = &board_adlink_mpg24;
+diff --git a/drivers/media/usb/pvrusb2/pvrusb2-context.c b/drivers/media/usb/pvrusb2/pvrusb2-context.c
+index 1764674de98bc..73c95ba2328a4 100644
+--- a/drivers/media/usb/pvrusb2/pvrusb2-context.c
++++ b/drivers/media/usb/pvrusb2/pvrusb2-context.c
+@@ -90,8 +90,10 @@ static void pvr2_context_destroy(struct pvr2_context *mp)
+ }
+
+
+-static void pvr2_context_notify(struct pvr2_context *mp)
++static void pvr2_context_notify(void *ptr)
+ {
++ struct pvr2_context *mp = ptr;
++
+ pvr2_context_set_notify(mp,!0);
+ }
+
+@@ -106,9 +108,7 @@ static void pvr2_context_check(struct pvr2_context *mp)
+ pvr2_trace(PVR2_TRACE_CTXT,
+ "pvr2_context %p (initialize)", mp);
+ /* Finish hardware initialization */
+- if (pvr2_hdw_initialize(mp->hdw,
+- (void (*)(void *))pvr2_context_notify,
+- mp)) {
++ if (pvr2_hdw_initialize(mp->hdw, pvr2_context_notify, mp)) {
+ mp->video_stream.stream =
+ pvr2_hdw_get_video_stream(mp->hdw);
+ /* Trigger interface initialization. By doing this
+@@ -267,9 +267,9 @@ static void pvr2_context_exit(struct pvr2_context *mp)
+ void pvr2_context_disconnect(struct pvr2_context *mp)
+ {
+ pvr2_hdw_disconnect(mp->hdw);
+- mp->disconnect_flag = !0;
+ if (!pvr2_context_shutok())
+ pvr2_context_notify(mp);
++ mp->disconnect_flag = !0;
+ }
+
+
+diff --git a/drivers/media/usb/pvrusb2/pvrusb2-dvb.c b/drivers/media/usb/pvrusb2/pvrusb2-dvb.c
+index 26811efe0fb58..9a9bae21c6147 100644
+--- a/drivers/media/usb/pvrusb2/pvrusb2-dvb.c
++++ b/drivers/media/usb/pvrusb2/pvrusb2-dvb.c
+@@ -88,8 +88,10 @@ static int pvr2_dvb_feed_thread(void *data)
+ return stat;
+ }
+
+-static void pvr2_dvb_notify(struct pvr2_dvb_adapter *adap)
++static void pvr2_dvb_notify(void *ptr)
+ {
++ struct pvr2_dvb_adapter *adap = ptr;
++
+ wake_up(&adap->buffer_wait_data);
+ }
+
+@@ -149,7 +151,7 @@ static int pvr2_dvb_stream_do_start(struct pvr2_dvb_adapter *adap)
+ }
+
+ pvr2_stream_set_callback(pvr->video_stream.stream,
+- (pvr2_stream_callback) pvr2_dvb_notify, adap);
++ pvr2_dvb_notify, adap);
+
+ ret = pvr2_stream_set_buffer_count(stream, PVR2_DVB_BUFFER_COUNT);
+ if (ret < 0) return ret;
+diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
+index c04ab7258d645..d608b793fa847 100644
+--- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
++++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
+@@ -1033,8 +1033,10 @@ static int pvr2_v4l2_open(struct file *file)
+ }
+
+
+-static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
++static void pvr2_v4l2_notify(void *ptr)
+ {
++ struct pvr2_v4l2_fh *fhp = ptr;
++
+ wake_up(&fhp->wait_data);
+ }
+
+@@ -1067,7 +1069,7 @@ static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
+
+ hdw = fh->channel.mc_head->hdw;
+ sp = fh->pdi->stream->stream;
+- pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
++ pvr2_stream_set_callback(sp, pvr2_v4l2_notify, fh);
+ pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
+ if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
+ return pvr2_ioread_set_enabled(fh->rhp,!0);
+@@ -1198,11 +1200,6 @@ static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
+ dip->minor_type = pvr2_v4l_type_video;
+ nr_ptr = video_nr;
+ caps |= V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO;
+- if (!dip->stream) {
+- pr_err(KBUILD_MODNAME
+- ": Failed to set up pvrusb2 v4l video dev due to missing stream instance\n");
+- return;
+- }
+ break;
+ case VFL_TYPE_VBI:
+ dip->config = pvr2_config_vbi;
+diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
+index 62a583040cd48..702f1c8bd2ab3 100644
+--- a/drivers/media/usb/usbtv/usbtv-video.c
++++ b/drivers/media/usb/usbtv/usbtv-video.c
+@@ -963,15 +963,8 @@ int usbtv_video_init(struct usbtv *usbtv)
+
+ void usbtv_video_free(struct usbtv *usbtv)
+ {
+- mutex_lock(&usbtv->vb2q_lock);
+- mutex_lock(&usbtv->v4l2_lock);
+-
+- usbtv_stop(usbtv);
+ vb2_video_unregister_device(&usbtv->vdev);
+ v4l2_device_disconnect(&usbtv->v4l2_dev);
+
+- mutex_unlock(&usbtv->v4l2_lock);
+- mutex_unlock(&usbtv->vb2q_lock);
+-
+ v4l2_device_put(&usbtv->v4l2_dev);
+ }
+diff --git a/drivers/media/v4l2-core/v4l2-cci.c b/drivers/media/v4l2-core/v4l2-cci.c
+index 10005c80f43b5..ee3475bed37fa 100644
+--- a/drivers/media/v4l2-core/v4l2-cci.c
++++ b/drivers/media/v4l2-core/v4l2-cci.c
+@@ -32,7 +32,7 @@ int cci_read(struct regmap *map, u32 reg, u64 *val, int *err)
+
+ ret = regmap_bulk_read(map, reg, buf, len);
+ if (ret) {
+- dev_err(regmap_get_device(map), "Error reading reg 0x%4x: %d\n",
++ dev_err(regmap_get_device(map), "Error reading reg 0x%04x: %d\n",
+ reg, ret);
+ goto out;
+ }
+@@ -131,7 +131,7 @@ int cci_write(struct regmap *map, u32 reg, u64 val, int *err)
+
+ ret = regmap_bulk_write(map, reg, buf, len);
+ if (ret)
+- dev_err(regmap_get_device(map), "Error writing reg 0x%4x: %d\n",
++ dev_err(regmap_get_device(map), "Error writing reg 0x%04x: %d\n",
+ reg, ret);
+
+ out:
+diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
+index 9e983176542be..75517134a5e94 100644
+--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
++++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
+@@ -1087,11 +1087,17 @@ static int v4l2_m2m_register_entity(struct media_device *mdev,
+ entity->function = function;
+
+ ret = media_entity_pads_init(entity, num_pads, pads);
+- if (ret)
++ if (ret) {
++ kfree(entity->name);
++ entity->name = NULL;
+ return ret;
++ }
+ ret = media_device_register_entity(mdev, entity);
+- if (ret)
++ if (ret) {
++ kfree(entity->name);
++ entity->name = NULL;
+ return ret;
++ }
+
+ return 0;
+ }
+diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c
+index abff87f917cb4..b8a7af2d36c11 100644
+--- a/drivers/memory/tegra/tegra234.c
++++ b/drivers/memory/tegra/tegra234.c
+@@ -121,7 +121,7 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_DLA1RDB,
+- .name = "dla0rdb",
++ .name = "dla1rdb",
+ .sid = TEGRA234_SID_NVDLA1,
+ .regs = {
+ .sid = {
+@@ -407,7 +407,7 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_DLA1RDB1,
+- .name = "dla0rdb1",
++ .name = "dla1rdb1",
+ .sid = TEGRA234_SID_NVDLA1,
+ .regs = {
+ .sid = {
+@@ -417,7 +417,7 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_DLA1WRB,
+- .name = "dla0wrb",
++ .name = "dla1wrb",
+ .sid = TEGRA234_SID_NVDLA1,
+ .regs = {
+ .sid = {
+@@ -699,7 +699,7 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_DLA1RDA,
+- .name = "dla0rda",
++ .name = "dla1rda",
+ .sid = TEGRA234_SID_NVDLA1,
+ .regs = {
+ .sid = {
+@@ -709,7 +709,7 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_DLA1FALRDB,
+- .name = "dla0falrdb",
++ .name = "dla1falrdb",
+ .sid = TEGRA234_SID_NVDLA1,
+ .regs = {
+ .sid = {
+@@ -719,7 +719,7 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_DLA1WRA,
+- .name = "dla0wra",
++ .name = "dla1wra",
+ .sid = TEGRA234_SID_NVDLA1,
+ .regs = {
+ .sid = {
+@@ -729,7 +729,7 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_DLA1FALWRB,
+- .name = "dla0falwrb",
++ .name = "dla1falwrb",
+ .sid = TEGRA234_SID_NVDLA1,
+ .regs = {
+ .sid = {
+@@ -917,7 +917,7 @@ static const struct tegra_mc_client tegra234_mc_clients[] = {
+ },
+ }, {
+ .id = TEGRA234_MEMORY_CLIENT_DLA1RDA1,
+- .name = "dla0rda1",
++ .name = "dla1rda1",
+ .sid = TEGRA234_SID_NVDLA1,
+ .regs = {
+ .sid = {
+diff --git a/drivers/mfd/altera-sysmgr.c b/drivers/mfd/altera-sysmgr.c
+index 0e52bd2ebd74b..fb5f988e61f37 100644
+--- a/drivers/mfd/altera-sysmgr.c
++++ b/drivers/mfd/altera-sysmgr.c
+@@ -109,7 +109,9 @@ struct regmap *altr_sysmgr_regmap_lookup_by_phandle(struct device_node *np,
+
+ dev = driver_find_device_by_of_node(&altr_sysmgr_driver.driver,
+ (void *)sysmgr_np);
+- of_node_put(sysmgr_np);
++ if (property)
++ of_node_put(sysmgr_np);
++
+ if (!dev)
+ return ERR_PTR(-EPROBE_DEFER);
+
+diff --git a/drivers/mfd/cs42l43.c b/drivers/mfd/cs42l43.c
+index 7b6d07cbe6fc6..1cea3f8f467d4 100644
+--- a/drivers/mfd/cs42l43.c
++++ b/drivers/mfd/cs42l43.c
+@@ -84,7 +84,7 @@ const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS] = {
+ { CS42L43_DRV_CTRL_5, 0x136C00C0 },
+ { CS42L43_GPIO_CTRL1, 0x00000707 },
+ { CS42L43_GPIO_CTRL2, 0x00000000 },
+- { CS42L43_GPIO_FN_SEL, 0x00000000 },
++ { CS42L43_GPIO_FN_SEL, 0x00000004 },
+ { CS42L43_MCLK_SRC_SEL, 0x00000000 },
+ { CS42L43_SAMPLE_RATE1, 0x00000003 },
+ { CS42L43_SAMPLE_RATE2, 0x00000003 },
+@@ -131,38 +131,38 @@ const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS] = {
+ { CS42L43_ASP_TX_CH4_CTRL, 0x00170091 },
+ { CS42L43_ASP_TX_CH5_CTRL, 0x001700C1 },
+ { CS42L43_ASP_TX_CH6_CTRL, 0x001700F1 },
+- { CS42L43_ASPTX1_INPUT, 0x00800000 },
+- { CS42L43_ASPTX2_INPUT, 0x00800000 },
+- { CS42L43_ASPTX3_INPUT, 0x00800000 },
+- { CS42L43_ASPTX4_INPUT, 0x00800000 },
+- { CS42L43_ASPTX5_INPUT, 0x00800000 },
+- { CS42L43_ASPTX6_INPUT, 0x00800000 },
+- { CS42L43_SWIRE_DP1_CH1_INPUT, 0x00800000 },
+- { CS42L43_SWIRE_DP1_CH2_INPUT, 0x00800000 },
+- { CS42L43_SWIRE_DP1_CH3_INPUT, 0x00800000 },
+- { CS42L43_SWIRE_DP1_CH4_INPUT, 0x00800000 },
+- { CS42L43_SWIRE_DP2_CH1_INPUT, 0x00800000 },
+- { CS42L43_SWIRE_DP2_CH2_INPUT, 0x00800000 },
+- { CS42L43_SWIRE_DP3_CH1_INPUT, 0x00800000 },
+- { CS42L43_SWIRE_DP3_CH2_INPUT, 0x00800000 },
+- { CS42L43_SWIRE_DP4_CH1_INPUT, 0x00800000 },
+- { CS42L43_SWIRE_DP4_CH2_INPUT, 0x00800000 },
+- { CS42L43_ASRC_INT1_INPUT1, 0x00800000 },
+- { CS42L43_ASRC_INT2_INPUT1, 0x00800000 },
+- { CS42L43_ASRC_INT3_INPUT1, 0x00800000 },
+- { CS42L43_ASRC_INT4_INPUT1, 0x00800000 },
+- { CS42L43_ASRC_DEC1_INPUT1, 0x00800000 },
+- { CS42L43_ASRC_DEC2_INPUT1, 0x00800000 },
+- { CS42L43_ASRC_DEC3_INPUT1, 0x00800000 },
+- { CS42L43_ASRC_DEC4_INPUT1, 0x00800000 },
+- { CS42L43_ISRC1INT1_INPUT1, 0x00800000 },
+- { CS42L43_ISRC1INT2_INPUT1, 0x00800000 },
+- { CS42L43_ISRC1DEC1_INPUT1, 0x00800000 },
+- { CS42L43_ISRC1DEC2_INPUT1, 0x00800000 },
+- { CS42L43_ISRC2INT1_INPUT1, 0x00800000 },
+- { CS42L43_ISRC2INT2_INPUT1, 0x00800000 },
+- { CS42L43_ISRC2DEC1_INPUT1, 0x00800000 },
+- { CS42L43_ISRC2DEC2_INPUT1, 0x00800000 },
++ { CS42L43_ASPTX1_INPUT, 0x00000000 },
++ { CS42L43_ASPTX2_INPUT, 0x00000000 },
++ { CS42L43_ASPTX3_INPUT, 0x00000000 },
++ { CS42L43_ASPTX4_INPUT, 0x00000000 },
++ { CS42L43_ASPTX5_INPUT, 0x00000000 },
++ { CS42L43_ASPTX6_INPUT, 0x00000000 },
++ { CS42L43_SWIRE_DP1_CH1_INPUT, 0x00000000 },
++ { CS42L43_SWIRE_DP1_CH2_INPUT, 0x00000000 },
++ { CS42L43_SWIRE_DP1_CH3_INPUT, 0x00000000 },
++ { CS42L43_SWIRE_DP1_CH4_INPUT, 0x00000000 },
++ { CS42L43_SWIRE_DP2_CH1_INPUT, 0x00000000 },
++ { CS42L43_SWIRE_DP2_CH2_INPUT, 0x00000000 },
++ { CS42L43_SWIRE_DP3_CH1_INPUT, 0x00000000 },
++ { CS42L43_SWIRE_DP3_CH2_INPUT, 0x00000000 },
++ { CS42L43_SWIRE_DP4_CH1_INPUT, 0x00000000 },
++ { CS42L43_SWIRE_DP4_CH2_INPUT, 0x00000000 },
++ { CS42L43_ASRC_INT1_INPUT1, 0x00000000 },
++ { CS42L43_ASRC_INT2_INPUT1, 0x00000000 },
++ { CS42L43_ASRC_INT3_INPUT1, 0x00000000 },
++ { CS42L43_ASRC_INT4_INPUT1, 0x00000000 },
++ { CS42L43_ASRC_DEC1_INPUT1, 0x00000000 },
++ { CS42L43_ASRC_DEC2_INPUT1, 0x00000000 },
++ { CS42L43_ASRC_DEC3_INPUT1, 0x00000000 },
++ { CS42L43_ASRC_DEC4_INPUT1, 0x00000000 },
++ { CS42L43_ISRC1INT1_INPUT1, 0x00000000 },
++ { CS42L43_ISRC1INT2_INPUT1, 0x00000000 },
++ { CS42L43_ISRC1DEC1_INPUT1, 0x00000000 },
++ { CS42L43_ISRC1DEC2_INPUT1, 0x00000000 },
++ { CS42L43_ISRC2INT1_INPUT1, 0x00000000 },
++ { CS42L43_ISRC2INT2_INPUT1, 0x00000000 },
++ { CS42L43_ISRC2DEC1_INPUT1, 0x00000000 },
++ { CS42L43_ISRC2DEC2_INPUT1, 0x00000000 },
+ { CS42L43_EQ1MIX_INPUT1, 0x00800000 },
+ { CS42L43_EQ1MIX_INPUT2, 0x00800000 },
+ { CS42L43_EQ1MIX_INPUT3, 0x00800000 },
+@@ -171,8 +171,8 @@ const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS] = {
+ { CS42L43_EQ2MIX_INPUT2, 0x00800000 },
+ { CS42L43_EQ2MIX_INPUT3, 0x00800000 },
+ { CS42L43_EQ2MIX_INPUT4, 0x00800000 },
+- { CS42L43_SPDIF1_INPUT1, 0x00800000 },
+- { CS42L43_SPDIF2_INPUT1, 0x00800000 },
++ { CS42L43_SPDIF1_INPUT1, 0x00000000 },
++ { CS42L43_SPDIF2_INPUT1, 0x00000000 },
+ { CS42L43_AMP1MIX_INPUT1, 0x00800000 },
+ { CS42L43_AMP1MIX_INPUT2, 0x00800000 },
+ { CS42L43_AMP1MIX_INPUT3, 0x00800000 },
+@@ -217,7 +217,7 @@ const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS] = {
+ { CS42L43_CTRL_REG, 0x00000006 },
+ { CS42L43_FDIV_FRAC, 0x40000000 },
+ { CS42L43_CAL_RATIO, 0x00000080 },
+- { CS42L43_SPI_CLK_CONFIG1, 0x00000000 },
++ { CS42L43_SPI_CLK_CONFIG1, 0x00000001 },
+ { CS42L43_SPI_CONFIG1, 0x00000000 },
+ { CS42L43_SPI_CONFIG2, 0x00000000 },
+ { CS42L43_SPI_CONFIG3, 0x00000001 },
+diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
+index c9550368d9ea5..7d0e91164cbaa 100644
+--- a/drivers/mfd/syscon.c
++++ b/drivers/mfd/syscon.c
+@@ -238,7 +238,9 @@ struct regmap *syscon_regmap_lookup_by_phandle(struct device_node *np,
+ return ERR_PTR(-ENODEV);
+
+ regmap = syscon_node_to_regmap(syscon_np);
+- of_node_put(syscon_np);
++
++ if (property)
++ of_node_put(syscon_np);
+
+ return regmap;
+ }
+diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c
+index 55f7db490d3bb..682c62c635b63 100644
+--- a/drivers/misc/mei/vsc-tp.c
++++ b/drivers/misc/mei/vsc-tp.c
+@@ -25,7 +25,8 @@
+ #define VSC_TP_ROM_BOOTUP_DELAY_MS 10
+ #define VSC_TP_ROM_XFER_POLL_TIMEOUT_US (500 * USEC_PER_MSEC)
+ #define VSC_TP_ROM_XFER_POLL_DELAY_US (20 * USEC_PER_MSEC)
+-#define VSC_TP_WAIT_FW_ASSERTED_TIMEOUT (2 * HZ)
++#define VSC_TP_WAIT_FW_POLL_TIMEOUT (2 * HZ)
++#define VSC_TP_WAIT_FW_POLL_DELAY_US (20 * USEC_PER_MSEC)
+ #define VSC_TP_MAX_XFER_COUNT 5
+
+ #define VSC_TP_PACKET_SYNC 0x31
+@@ -101,13 +102,15 @@ static int vsc_tp_wakeup_request(struct vsc_tp *tp)
+ gpiod_set_value_cansleep(tp->wakeupfw, 0);
+
+ ret = wait_event_timeout(tp->xfer_wait,
+- atomic_read(&tp->assert_cnt) &&
+- gpiod_get_value_cansleep(tp->wakeuphost),
+- VSC_TP_WAIT_FW_ASSERTED_TIMEOUT);
++ atomic_read(&tp->assert_cnt),
++ VSC_TP_WAIT_FW_POLL_TIMEOUT);
+ if (!ret)
+ return -ETIMEDOUT;
+
+- return 0;
++ return read_poll_timeout(gpiod_get_value_cansleep, ret, ret,
++ VSC_TP_WAIT_FW_POLL_DELAY_US,
++ VSC_TP_WAIT_FW_POLL_TIMEOUT, false,
++ tp->wakeuphost);
+ }
+
+ static void vsc_tp_wakeup_release(struct vsc_tp *tp)
+@@ -416,8 +419,6 @@ static irqreturn_t vsc_tp_isr(int irq, void *data)
+
+ atomic_inc(&tp->assert_cnt);
+
+- wake_up(&tp->xfer_wait);
+-
+ return IRQ_WAKE_THREAD;
+ }
+
+@@ -425,6 +426,8 @@ static irqreturn_t vsc_tp_thread_isr(int irq, void *data)
+ {
+ struct vsc_tp *tp = data;
+
++ wake_up(&tp->xfer_wait);
++
+ if (tp->event_notify)
+ tp->event_notify(tp->event_notify_context);
+
+diff --git a/drivers/mmc/host/wmt-sdmmc.c b/drivers/mmc/host/wmt-sdmmc.c
+index 77d5f1d244899..860380931b6cd 100644
+--- a/drivers/mmc/host/wmt-sdmmc.c
++++ b/drivers/mmc/host/wmt-sdmmc.c
+@@ -883,7 +883,6 @@ static void wmt_mci_remove(struct platform_device *pdev)
+ {
+ struct mmc_host *mmc;
+ struct wmt_mci_priv *priv;
+- struct resource *res;
+ u32 reg_tmp;
+
+ mmc = platform_get_drvdata(pdev);
+@@ -911,9 +910,6 @@ static void wmt_mci_remove(struct platform_device *pdev)
+ clk_disable_unprepare(priv->clk_sdmmc);
+ clk_put(priv->clk_sdmmc);
+
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- release_mem_region(res->start, resource_size(res));
+-
+ mmc_free_host(mmc);
+
+ dev_info(&pdev->dev, "WMT MCI device removed\n");
+diff --git a/drivers/mtd/maps/physmap-core.c b/drivers/mtd/maps/physmap-core.c
+index 746a27d15d440..96eb2e782c382 100644
+--- a/drivers/mtd/maps/physmap-core.c
++++ b/drivers/mtd/maps/physmap-core.c
+@@ -518,7 +518,7 @@ static int physmap_flash_probe(struct platform_device *dev)
+ if (!info->maps[i].phys)
+ info->maps[i].phys = res->start;
+
+- info->win_order = get_bitmask_order(resource_size(res)) - 1;
++ info->win_order = fls64(resource_size(res)) - 1;
+ info->maps[i].size = BIT(info->win_order +
+ (info->gpios ?
+ info->gpios->ndescs : 0));
+diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c
+index f58cfb15d6e85..b69dade3f7ad0 100644
+--- a/drivers/mtd/maps/sun_uflash.c
++++ b/drivers/mtd/maps/sun_uflash.c
+@@ -47,7 +47,7 @@ struct map_info uflash_map_templ = {
+ .bankwidth = UFLASH_BUSWIDTH,
+ };
+
+-int uflash_devinit(struct platform_device *op, struct device_node *dp)
++static int uflash_devinit(struct platform_device *op, struct device_node *dp)
+ {
+ struct uflash_dev *up;
+
+diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+index 8faca43ae1ff9..b8e70fc64348e 100644
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+@@ -625,7 +625,7 @@ enum {
+ /* Only for v7.2 */
+ #define ACC_CONTROL_ECC_EXT_SHIFT 13
+
+-static u8 brcmnand_status(struct brcmnand_host *host);
++static int brcmnand_status(struct brcmnand_host *host);
+
+ static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl)
+ {
+@@ -1690,7 +1690,7 @@ static int brcmnand_waitfunc(struct nand_chip *chip)
+ INTFC_FLASH_STATUS;
+ }
+
+-static u8 brcmnand_status(struct brcmnand_host *host)
++static int brcmnand_status(struct brcmnand_host *host)
+ {
+ struct nand_chip *chip = &host->chip;
+ struct mtd_info *mtd = nand_to_mtd(chip);
+@@ -1701,7 +1701,7 @@ static u8 brcmnand_status(struct brcmnand_host *host)
+ return brcmnand_waitfunc(chip);
+ }
+
+-static u8 brcmnand_reset(struct brcmnand_host *host)
++static int brcmnand_reset(struct brcmnand_host *host)
+ {
+ struct nand_chip *chip = &host->chip;
+
+@@ -2433,7 +2433,11 @@ static int brcmnand_exec_op(struct nand_chip *chip,
+
+ if (brcmnand_op_is_status(op)) {
+ status = op->instrs[1].ctx.data.buf.in;
+- *status = brcmnand_status(host);
++ ret = brcmnand_status(host);
++ if (ret < 0)
++ return ret;
++
++ *status = ret & 0xFF;
+
+ return 0;
+ }
+diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c
+index 488fd452611a6..677fcb03f9bef 100644
+--- a/drivers/mtd/nand/raw/lpc32xx_mlc.c
++++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c
+@@ -303,8 +303,9 @@ static int lpc32xx_nand_device_ready(struct nand_chip *nand_chip)
+ return 0;
+ }
+
+-static irqreturn_t lpc3xxx_nand_irq(int irq, struct lpc32xx_nand_host *host)
++static irqreturn_t lpc3xxx_nand_irq(int irq, void *data)
+ {
++ struct lpc32xx_nand_host *host = data;
+ uint8_t sr;
+
+ /* Clear interrupt flag by reading status */
+@@ -780,7 +781,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev)
+ goto release_dma_chan;
+ }
+
+- if (request_irq(host->irq, (irq_handler_t)&lpc3xxx_nand_irq,
++ if (request_irq(host->irq, &lpc3xxx_nand_irq,
+ IRQF_TRIGGER_HIGH, DRV_NAME, host)) {
+ dev_err(&pdev->dev, "Error requesting NAND IRQ\n");
+ res = -ENXIO;
+diff --git a/drivers/mtd/nand/spi/esmt.c b/drivers/mtd/nand/spi/esmt.c
+index 31c439a557b18..4597a82de23a4 100644
+--- a/drivers/mtd/nand/spi/esmt.c
++++ b/drivers/mtd/nand/spi/esmt.c
+@@ -104,7 +104,8 @@ static const struct mtd_ooblayout_ops f50l1g41lb_ooblayout = {
+
+ static const struct spinand_info esmt_c8_spinand_table[] = {
+ SPINAND_INFO("F50L1G41LB",
+- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01),
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01, 0x7f,
++ 0x7f, 0x7f),
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+ NAND_ECCREQ(1, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -113,7 +114,8 @@ static const struct spinand_info esmt_c8_spinand_table[] = {
+ 0,
+ SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)),
+ SPINAND_INFO("F50D1G41LB",
+- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x11),
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x11, 0x7f,
++ 0x7f, 0x7f),
+ NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
+ NAND_ECCREQ(1, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+@@ -122,7 +124,8 @@ static const struct spinand_info esmt_c8_spinand_table[] = {
+ 0,
+ SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)),
+ SPINAND_INFO("F50D2G41KA",
+- SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x51),
++ SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x51, 0x7f,
++ 0x7f, 0x7f),
+ NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
+ NAND_ECCREQ(8, 512),
+ SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
+diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
+index 16ecc11c7f62a..2395b1225cc8a 100644
+--- a/drivers/net/can/m_can/m_can.c
++++ b/drivers/net/can/m_can/m_can.c
+@@ -418,6 +418,13 @@ static void m_can_config_endisable(struct m_can_classdev *cdev, bool enable)
+
+ static inline void m_can_enable_all_interrupts(struct m_can_classdev *cdev)
+ {
++ if (!cdev->net->irq) {
++ dev_dbg(cdev->dev, "Start hrtimer\n");
++ hrtimer_start(&cdev->hrtimer,
++ ms_to_ktime(HRTIMER_POLL_INTERVAL_MS),
++ HRTIMER_MODE_REL_PINNED);
++ }
++
+ /* Only interrupt line 0 is used in this driver */
+ m_can_write(cdev, M_CAN_ILE, ILE_EINT0);
+ }
+@@ -425,6 +432,11 @@ static inline void m_can_enable_all_interrupts(struct m_can_classdev *cdev)
+ static inline void m_can_disable_all_interrupts(struct m_can_classdev *cdev)
+ {
+ m_can_write(cdev, M_CAN_ILE, 0x0);
++
++ if (!cdev->net->irq) {
++ dev_dbg(cdev->dev, "Stop hrtimer\n");
++ hrtimer_cancel(&cdev->hrtimer);
++ }
+ }
+
+ /* Retrieve internal timestamp counter from TSCV.TSC, and shift it to 32-bit
+@@ -1417,12 +1429,6 @@ static int m_can_start(struct net_device *dev)
+
+ m_can_enable_all_interrupts(cdev);
+
+- if (!dev->irq) {
+- dev_dbg(cdev->dev, "Start hrtimer\n");
+- hrtimer_start(&cdev->hrtimer, ms_to_ktime(HRTIMER_POLL_INTERVAL_MS),
+- HRTIMER_MODE_REL_PINNED);
+- }
+-
+ return 0;
+ }
+
+@@ -1577,11 +1583,6 @@ static void m_can_stop(struct net_device *dev)
+ {
+ struct m_can_classdev *cdev = netdev_priv(dev);
+
+- if (!dev->irq) {
+- dev_dbg(cdev->dev, "Stop hrtimer\n");
+- hrtimer_cancel(&cdev->hrtimer);
+- }
+-
+ /* disable all interrupts */
+ m_can_disable_all_interrupts(cdev);
+
+diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
+index 245dfb7a7a315..25a49708f4842 100644
+--- a/drivers/net/dsa/microchip/ksz_common.c
++++ b/drivers/net/dsa/microchip/ksz_common.c
+@@ -2185,6 +2185,8 @@ static int ksz_pirq_setup(struct ksz_device *dev, u8 p)
+ return ksz_irq_common_setup(dev, pirq);
+ }
+
++static int ksz_parse_drive_strength(struct ksz_device *dev);
++
+ static int ksz_setup(struct dsa_switch *ds)
+ {
+ struct ksz_device *dev = ds->priv;
+@@ -2206,6 +2208,10 @@ static int ksz_setup(struct dsa_switch *ds)
+ return ret;
+ }
+
++ ret = ksz_parse_drive_strength(dev);
++ if (ret)
++ return ret;
++
+ /* set broadcast storm protection 10% rate */
+ regmap_update_bits(ksz_regmap_16(dev), regs[S_BROADCAST_CTRL],
+ BROADCAST_STORM_RATE,
+@@ -4242,10 +4248,6 @@ int ksz_switch_register(struct ksz_device *dev)
+ for (port_num = 0; port_num < dev->info->port_cnt; ++port_num)
+ dev->ports[port_num].interface = PHY_INTERFACE_MODE_NA;
+ if (dev->dev->of_node) {
+- ret = ksz_parse_drive_strength(dev);
+- if (ret)
+- return ret;
+-
+ ret = of_get_phy_mode(dev->dev->of_node, &interface);
+ if (ret == 0)
+ dev->compat_interface = interface;
+diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
+index 3c1f657593a8f..40ae44c9945b1 100644
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -998,20 +998,56 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)
+ mutex_unlock(&priv->reg_mutex);
+ }
+
++/* On page 205, section "8.6.3 Frame filtering" of the active standard, IEEE Std
++ * 802.1Q™-2022, it is stated that frames with 01:80:C2:00:00:00-0F as MAC DA
++ * must only be propagated to C-VLAN and MAC Bridge components. That means
++ * VLAN-aware and VLAN-unaware bridges. On the switch designs with CPU ports,
++ * these frames are supposed to be processed by the CPU (software). So we make
++ * the switch only forward them to the CPU port. And if received from a CPU
++ * port, forward to a single port. The software is responsible of making the
++ * switch conform to the latter by setting a single port as destination port on
++ * the special tag.
++ *
++ * This switch intellectual property cannot conform to this part of the standard
++ * fully. Whilst the REV_UN frame tag covers the remaining :04-0D and :0F MAC
++ * DAs, it also includes :22-FF which the scope of propagation is not supposed
++ * to be restricted for these MAC DAs.
++ */
+ static void
+ mt753x_trap_frames(struct mt7530_priv *priv)
+ {
+- /* Trap BPDUs to the CPU port(s) */
+- mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
++ /* Trap 802.1X PAE frames and BPDUs to the CPU port(s) and egress them
++ * VLAN-untagged.
++ */
++ mt7530_rmw(priv, MT753X_BPC, MT753X_PAE_EG_TAG_MASK |
++ MT753X_PAE_PORT_FW_MASK | MT753X_BPDU_EG_TAG_MASK |
++ MT753X_BPDU_PORT_FW_MASK,
++ MT753X_PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY) |
++ MT753X_BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+ MT753X_BPDU_CPU_ONLY);
+
+- /* Trap 802.1X PAE frames to the CPU port(s) */
+- mt7530_rmw(priv, MT753X_BPC, MT753X_PAE_PORT_FW_MASK,
+- MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY));
++ /* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and egress
++ * them VLAN-untagged.
++ */
++ mt7530_rmw(priv, MT753X_RGAC1, MT753X_R02_EG_TAG_MASK |
++ MT753X_R02_PORT_FW_MASK | MT753X_R01_EG_TAG_MASK |
++ MT753X_R01_PORT_FW_MASK,
++ MT753X_R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_R02_PORT_FW(MT753X_BPDU_CPU_ONLY) |
++ MT753X_R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_BPDU_CPU_ONLY);
+
+- /* Trap LLDP frames with :0E MAC DA to the CPU port(s) */
+- mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_PORT_FW_MASK,
+- MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY));
++ /* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and egress
++ * them VLAN-untagged.
++ */
++ mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_EG_TAG_MASK |
++ MT753X_R0E_PORT_FW_MASK | MT753X_R03_EG_TAG_MASK |
++ MT753X_R03_PORT_FW_MASK,
++ MT753X_R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY) |
++ MT753X_R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_BPDU_CPU_ONLY);
+ }
+
+ static int
+@@ -2243,11 +2279,11 @@ mt7530_setup(struct dsa_switch *ds)
+ */
+ if (priv->mcm) {
+ reset_control_assert(priv->rstc);
+- usleep_range(1000, 1100);
++ usleep_range(5000, 5100);
+ reset_control_deassert(priv->rstc);
+ } else {
+ gpiod_set_value_cansleep(priv->reset, 0);
+- usleep_range(1000, 1100);
++ usleep_range(5000, 5100);
+ gpiod_set_value_cansleep(priv->reset, 1);
+ }
+
+@@ -2449,11 +2485,11 @@ mt7531_setup(struct dsa_switch *ds)
+ */
+ if (priv->mcm) {
+ reset_control_assert(priv->rstc);
+- usleep_range(1000, 1100);
++ usleep_range(5000, 5100);
+ reset_control_deassert(priv->rstc);
+ } else {
+ gpiod_set_value_cansleep(priv->reset, 0);
+- usleep_range(1000, 1100);
++ usleep_range(5000, 5100);
+ gpiod_set_value_cansleep(priv->reset, 1);
+ }
+
+diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
+index 17e42d30fff4b..75bc9043c8c0a 100644
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -65,14 +65,33 @@ enum mt753x_id {
+
+ /* Registers for BPDU and PAE frame control*/
+ #define MT753X_BPC 0x24
+-#define MT753X_BPDU_PORT_FW_MASK GENMASK(2, 0)
++#define MT753X_PAE_EG_TAG_MASK GENMASK(24, 22)
++#define MT753X_PAE_EG_TAG(x) FIELD_PREP(MT753X_PAE_EG_TAG_MASK, x)
+ #define MT753X_PAE_PORT_FW_MASK GENMASK(18, 16)
+ #define MT753X_PAE_PORT_FW(x) FIELD_PREP(MT753X_PAE_PORT_FW_MASK, x)
++#define MT753X_BPDU_EG_TAG_MASK GENMASK(8, 6)
++#define MT753X_BPDU_EG_TAG(x) FIELD_PREP(MT753X_BPDU_EG_TAG_MASK, x)
++#define MT753X_BPDU_PORT_FW_MASK GENMASK(2, 0)
++
++/* Register for :01 and :02 MAC DA frame control */
++#define MT753X_RGAC1 0x28
++#define MT753X_R02_EG_TAG_MASK GENMASK(24, 22)
++#define MT753X_R02_EG_TAG(x) FIELD_PREP(MT753X_R02_EG_TAG_MASK, x)
++#define MT753X_R02_PORT_FW_MASK GENMASK(18, 16)
++#define MT753X_R02_PORT_FW(x) FIELD_PREP(MT753X_R02_PORT_FW_MASK, x)
++#define MT753X_R01_EG_TAG_MASK GENMASK(8, 6)
++#define MT753X_R01_EG_TAG(x) FIELD_PREP(MT753X_R01_EG_TAG_MASK, x)
++#define MT753X_R01_PORT_FW_MASK GENMASK(2, 0)
+
+ /* Register for :03 and :0E MAC DA frame control */
+ #define MT753X_RGAC2 0x2c
++#define MT753X_R0E_EG_TAG_MASK GENMASK(24, 22)
++#define MT753X_R0E_EG_TAG(x) FIELD_PREP(MT753X_R0E_EG_TAG_MASK, x)
+ #define MT753X_R0E_PORT_FW_MASK GENMASK(18, 16)
+ #define MT753X_R0E_PORT_FW(x) FIELD_PREP(MT753X_R0E_PORT_FW_MASK, x)
++#define MT753X_R03_EG_TAG_MASK GENMASK(8, 6)
++#define MT753X_R03_EG_TAG(x) FIELD_PREP(MT753X_R03_EG_TAG_MASK, x)
++#define MT753X_R03_PORT_FW_MASK GENMASK(2, 0)
+
+ enum mt753x_bpdu_port_fw {
+ MT753X_BPDU_FOLLOW_MFC,
+@@ -253,6 +272,7 @@ enum mt7530_port_mode {
+ enum mt7530_vlan_port_eg_tag {
+ MT7530_VLAN_EG_DISABLED = 0,
+ MT7530_VLAN_EG_CONSISTENT = 1,
++ MT7530_VLAN_EG_UNTAGGED = 4,
+ };
+
+ enum mt7530_vlan_port_attr {
+diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
+index 1c0a7828d397b..5482015411f2f 100644
+--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
++++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
+@@ -2670,22 +2670,6 @@ static netdev_tx_t ena_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ return NETDEV_TX_OK;
+ }
+
+-static u16 ena_select_queue(struct net_device *dev, struct sk_buff *skb,
+- struct net_device *sb_dev)
+-{
+- u16 qid;
+- /* we suspect that this is good for in--kernel network services that
+- * want to loop incoming skb rx to tx in normal user generated traffic,
+- * most probably we will not get to this
+- */
+- if (skb_rx_queue_recorded(skb))
+- qid = skb_get_rx_queue(skb);
+- else
+- qid = netdev_pick_tx(dev, skb, NULL);
+-
+- return qid;
+-}
+-
+ static void ena_config_host_info(struct ena_com_dev *ena_dev, struct pci_dev *pdev)
+ {
+ struct device *dev = &pdev->dev;
+@@ -2863,7 +2847,6 @@ static const struct net_device_ops ena_netdev_ops = {
+ .ndo_open = ena_open,
+ .ndo_stop = ena_close,
+ .ndo_start_xmit = ena_start_xmit,
+- .ndo_select_queue = ena_select_queue,
+ .ndo_get_stats64 = ena_get_stats64,
+ .ndo_tx_timeout = ena_tx_timeout,
+ .ndo_change_mtu = ena_change_mtu,
+diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+index d8b1824c334d3..0bc1367fd6492 100644
+--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
+@@ -1002,9 +1002,6 @@ static inline void bnx2x_set_fw_mac_addr(__le16 *fw_hi, __le16 *fw_mid,
+ static inline void bnx2x_free_rx_mem_pool(struct bnx2x *bp,
+ struct bnx2x_alloc_pool *pool)
+ {
+- if (!pool->page)
+- return;
+-
+ put_page(pool->page);
+
+ pool->page = NULL;
+@@ -1015,6 +1012,9 @@ static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
+ {
+ int i;
+
++ if (!fp->page_pool.page)
++ return;
++
+ if (fp->mode == TPA_MODE_DISABLED)
+ return;
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c b/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c
+index 3b6dbf158b98d..f72dc0cee30e5 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_dcbnl.c
+@@ -76,7 +76,7 @@ static int hns3_dcbnl_ieee_delapp(struct net_device *ndev, struct dcb_app *app)
+ if (hns3_nic_resetting(ndev))
+ return -EBUSY;
+
+- if (h->kinfo.dcb_ops->ieee_setapp)
++ if (h->kinfo.dcb_ops->ieee_delapp)
+ return h->kinfo.dcb_ops->ieee_delapp(h, app);
+
+ return -EOPNOTSUPP;
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index 5ea9e59569eff..609d3799d7738 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -2890,7 +2890,10 @@ static int hclge_mac_init(struct hclge_dev *hdev)
+ int ret;
+
+ hdev->support_sfp_query = true;
+- hdev->hw.mac.duplex = HCLGE_MAC_FULL;
++
++ if (!test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state))
++ hdev->hw.mac.duplex = HCLGE_MAC_FULL;
++
+ ret = hclge_cfg_mac_speed_dup_hw(hdev, hdev->hw.mac.speed,
+ hdev->hw.mac.duplex, hdev->hw.mac.lane_num);
+ if (ret)
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c
+index 80a2a0073d97a..507d7ce26d831 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c
+@@ -108,7 +108,7 @@ void hclge_ptp_get_rx_hwts(struct hnae3_handle *handle, struct sk_buff *skb,
+ u64 ns = nsec;
+ u32 sec_h;
+
+- if (!test_bit(HCLGE_PTP_FLAG_RX_EN, &hdev->ptp->flags))
++ if (!hdev->ptp || !test_bit(HCLGE_PTP_FLAG_RX_EN, &hdev->ptp->flags))
+ return;
+
+ /* Since the BD does not have enough space for the higher 16 bits of
+diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
+index df6a68ab747ee..6d256dbcb77d0 100644
+--- a/drivers/net/ethernet/intel/ice/ice_main.c
++++ b/drivers/net/ethernet/intel/ice/ice_main.c
+@@ -6737,6 +6737,7 @@ static void ice_update_vsi_ring_stats(struct ice_vsi *vsi)
+ {
+ struct rtnl_link_stats64 *net_stats, *stats_prev;
+ struct rtnl_link_stats64 *vsi_stats;
++ struct ice_pf *pf = vsi->back;
+ u64 pkts, bytes;
+ int i;
+
+@@ -6782,21 +6783,18 @@ static void ice_update_vsi_ring_stats(struct ice_vsi *vsi)
+ net_stats = &vsi->net_stats;
+ stats_prev = &vsi->net_stats_prev;
+
+- /* clear prev counters after reset */
+- if (vsi_stats->tx_packets < stats_prev->tx_packets ||
+- vsi_stats->rx_packets < stats_prev->rx_packets) {
+- stats_prev->tx_packets = 0;
+- stats_prev->tx_bytes = 0;
+- stats_prev->rx_packets = 0;
+- stats_prev->rx_bytes = 0;
++ /* Update netdev counters, but keep in mind that values could start at
++ * random value after PF reset. And as we increase the reported stat by
++ * diff of Prev-Cur, we need to be sure that Prev is valid. If it's not,
++ * let's skip this round.
++ */
++ if (likely(pf->stat_prev_loaded)) {
++ net_stats->tx_packets += vsi_stats->tx_packets - stats_prev->tx_packets;
++ net_stats->tx_bytes += vsi_stats->tx_bytes - stats_prev->tx_bytes;
++ net_stats->rx_packets += vsi_stats->rx_packets - stats_prev->rx_packets;
++ net_stats->rx_bytes += vsi_stats->rx_bytes - stats_prev->rx_bytes;
+ }
+
+- /* update netdev counters */
+- net_stats->tx_packets += vsi_stats->tx_packets - stats_prev->tx_packets;
+- net_stats->tx_bytes += vsi_stats->tx_bytes - stats_prev->tx_bytes;
+- net_stats->rx_packets += vsi_stats->rx_packets - stats_prev->rx_packets;
+- net_stats->rx_bytes += vsi_stats->rx_bytes - stats_prev->rx_bytes;
+-
+ stats_prev->tx_packets = vsi_stats->tx_packets;
+ stats_prev->tx_bytes = vsi_stats->tx_bytes;
+ stats_prev->rx_packets = vsi_stats->rx_packets;
+diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
+index cebb44f51d5f5..7662c42e35c11 100644
+--- a/drivers/net/ethernet/intel/igb/igb_main.c
++++ b/drivers/net/ethernet/intel/igb/igb_main.c
+@@ -6985,44 +6985,31 @@ static void igb_extts(struct igb_adapter *adapter, int tsintr_tt)
+ static void igb_tsync_interrupt(struct igb_adapter *adapter)
+ {
+ struct e1000_hw *hw = &adapter->hw;
+- u32 ack = 0, tsicr = rd32(E1000_TSICR);
++ u32 tsicr = rd32(E1000_TSICR);
+ struct ptp_clock_event event;
+
+ if (tsicr & TSINTR_SYS_WRAP) {
+ event.type = PTP_CLOCK_PPS;
+ if (adapter->ptp_caps.pps)
+ ptp_clock_event(adapter->ptp_clock, &event);
+- ack |= TSINTR_SYS_WRAP;
+ }
+
+ if (tsicr & E1000_TSICR_TXTS) {
+ /* retrieve hardware timestamp */
+ schedule_work(&adapter->ptp_tx_work);
+- ack |= E1000_TSICR_TXTS;
+ }
+
+- if (tsicr & TSINTR_TT0) {
++ if (tsicr & TSINTR_TT0)
+ igb_perout(adapter, 0);
+- ack |= TSINTR_TT0;
+- }
+
+- if (tsicr & TSINTR_TT1) {
++ if (tsicr & TSINTR_TT1)
+ igb_perout(adapter, 1);
+- ack |= TSINTR_TT1;
+- }
+
+- if (tsicr & TSINTR_AUTT0) {
++ if (tsicr & TSINTR_AUTT0)
+ igb_extts(adapter, 0);
+- ack |= TSINTR_AUTT0;
+- }
+
+- if (tsicr & TSINTR_AUTT1) {
++ if (tsicr & TSINTR_AUTT1)
+ igb_extts(adapter, 1);
+- ack |= TSINTR_AUTT1;
+- }
+-
+- /* acknowledge the interrupts */
+- wr32(E1000_TSICR, ack);
+ }
+
+ static irqreturn_t igb_msix_other(int irq, void *data)
+diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
+index 81c21a893ede9..e447ba0370568 100644
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -5302,25 +5302,22 @@ igc_features_check(struct sk_buff *skb, struct net_device *dev,
+
+ static void igc_tsync_interrupt(struct igc_adapter *adapter)
+ {
+- u32 ack, tsauxc, sec, nsec, tsicr;
+ struct igc_hw *hw = &adapter->hw;
++ u32 tsauxc, sec, nsec, tsicr;
+ struct ptp_clock_event event;
+ struct timespec64 ts;
+
+ tsicr = rd32(IGC_TSICR);
+- ack = 0;
+
+ if (tsicr & IGC_TSICR_SYS_WRAP) {
+ event.type = PTP_CLOCK_PPS;
+ if (adapter->ptp_caps.pps)
+ ptp_clock_event(adapter->ptp_clock, &event);
+- ack |= IGC_TSICR_SYS_WRAP;
+ }
+
+ if (tsicr & IGC_TSICR_TXTS) {
+ /* retrieve hardware timestamp */
+ igc_ptp_tx_tstamp_event(adapter);
+- ack |= IGC_TSICR_TXTS;
+ }
+
+ if (tsicr & IGC_TSICR_TT0) {
+@@ -5334,7 +5331,6 @@ static void igc_tsync_interrupt(struct igc_adapter *adapter)
+ wr32(IGC_TSAUXC, tsauxc);
+ adapter->perout[0].start = ts;
+ spin_unlock(&adapter->tmreg_lock);
+- ack |= IGC_TSICR_TT0;
+ }
+
+ if (tsicr & IGC_TSICR_TT1) {
+@@ -5348,7 +5344,6 @@ static void igc_tsync_interrupt(struct igc_adapter *adapter)
+ wr32(IGC_TSAUXC, tsauxc);
+ adapter->perout[1].start = ts;
+ spin_unlock(&adapter->tmreg_lock);
+- ack |= IGC_TSICR_TT1;
+ }
+
+ if (tsicr & IGC_TSICR_AUTT0) {
+@@ -5358,7 +5353,6 @@ static void igc_tsync_interrupt(struct igc_adapter *adapter)
+ event.index = 0;
+ event.timestamp = sec * NSEC_PER_SEC + nsec;
+ ptp_clock_event(adapter->ptp_clock, &event);
+- ack |= IGC_TSICR_AUTT0;
+ }
+
+ if (tsicr & IGC_TSICR_AUTT1) {
+@@ -5368,11 +5362,7 @@ static void igc_tsync_interrupt(struct igc_adapter *adapter)
+ event.index = 1;
+ event.timestamp = sec * NSEC_PER_SEC + nsec;
+ ptp_clock_event(adapter->ptp_clock, &event);
+- ack |= IGC_TSICR_AUTT1;
+ }
+-
+- /* acknowledge the interrupts */
+- wr32(IGC_TSICR, ack);
+ }
+
+ /**
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+index 6c70c84986904..3c0f55b3e48ea 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+@@ -1338,7 +1338,7 @@ static irqreturn_t cgx_fwi_event_handler(int irq, void *data)
+
+ /* Release thread waiting for completion */
+ lmac->cmd_pend = false;
+- wake_up_interruptible(&lmac->wq_cmd_cmplt);
++ wake_up(&lmac->wq_cmd_cmplt);
+ break;
+ case CGX_EVT_ASYNC:
+ if (cgx_event_is_linkevent(event))
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.c b/drivers/net/ethernet/marvell/octeontx2/af/mbox.c
+index b92264d0a77e7..1e5aa53975040 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.c
+@@ -214,11 +214,12 @@ int otx2_mbox_busy_poll_for_rsp(struct otx2_mbox *mbox, int devid)
+ }
+ EXPORT_SYMBOL(otx2_mbox_busy_poll_for_rsp);
+
+-void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid)
++static void otx2_mbox_msg_send_data(struct otx2_mbox *mbox, int devid, u64 data)
+ {
+ struct otx2_mbox_dev *mdev = &mbox->dev[devid];
+ struct mbox_hdr *tx_hdr, *rx_hdr;
+ void *hw_mbase = mdev->hwbase;
++ u64 intr_val;
+
+ tx_hdr = hw_mbase + mbox->tx_start;
+ rx_hdr = hw_mbase + mbox->rx_start;
+@@ -254,14 +255,52 @@ void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid)
+
+ spin_unlock(&mdev->mbox_lock);
+
++ /* Check if interrupt pending */
++ intr_val = readq((void __iomem *)mbox->reg_base +
++ (mbox->trigger | (devid << mbox->tr_shift)));
++
++ intr_val |= data;
+ /* The interrupt should be fired after num_msgs is written
+ * to the shared memory
+ */
+- writeq(1, (void __iomem *)mbox->reg_base +
++ writeq(intr_val, (void __iomem *)mbox->reg_base +
+ (mbox->trigger | (devid << mbox->tr_shift)));
+ }
++
++void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid)
++{
++ otx2_mbox_msg_send_data(mbox, devid, MBOX_DOWN_MSG);
++}
+ EXPORT_SYMBOL(otx2_mbox_msg_send);
+
++void otx2_mbox_msg_send_up(struct otx2_mbox *mbox, int devid)
++{
++ otx2_mbox_msg_send_data(mbox, devid, MBOX_UP_MSG);
++}
++EXPORT_SYMBOL(otx2_mbox_msg_send_up);
++
++bool otx2_mbox_wait_for_zero(struct otx2_mbox *mbox, int devid)
++{
++ u64 data;
++
++ data = readq((void __iomem *)mbox->reg_base +
++ (mbox->trigger | (devid << mbox->tr_shift)));
++
++ /* If data is non-zero wait for ~1ms and return to caller
++ * whether data has changed to zero or not after the wait.
++ */
++ if (!data)
++ return true;
++
++ usleep_range(950, 1000);
++
++ data = readq((void __iomem *)mbox->reg_base +
++ (mbox->trigger | (devid << mbox->tr_shift)));
++
++ return data == 0;
++}
++EXPORT_SYMBOL(otx2_mbox_wait_for_zero);
++
+ struct mbox_msghdr *otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid,
+ int size, int size_rsp)
+ {
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+index edeb0f7373121..98e203a0e26b6 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+@@ -16,6 +16,9 @@
+
+ #define MBOX_SIZE SZ_64K
+
++#define MBOX_DOWN_MSG 1
++#define MBOX_UP_MSG 2
++
+ /* AF/PF: PF initiated, PF/VF VF initiated */
+ #define MBOX_DOWN_RX_START 0
+ #define MBOX_DOWN_RX_SIZE (46 * SZ_1K)
+@@ -101,6 +104,7 @@ int otx2_mbox_regions_init(struct otx2_mbox *mbox, void __force **hwbase,
+ struct pci_dev *pdev, void __force *reg_base,
+ int direction, int ndevs, unsigned long *bmap);
+ void otx2_mbox_msg_send(struct otx2_mbox *mbox, int devid);
++void otx2_mbox_msg_send_up(struct otx2_mbox *mbox, int devid);
+ int otx2_mbox_wait_for_rsp(struct otx2_mbox *mbox, int devid);
+ int otx2_mbox_busy_poll_for_rsp(struct otx2_mbox *mbox, int devid);
+ struct mbox_msghdr *otx2_mbox_alloc_msg_rsp(struct otx2_mbox *mbox, int devid,
+@@ -118,6 +122,8 @@ static inline struct mbox_msghdr *otx2_mbox_alloc_msg(struct otx2_mbox *mbox,
+ return otx2_mbox_alloc_msg_rsp(mbox, devid, size, 0);
+ }
+
++bool otx2_mbox_wait_for_zero(struct otx2_mbox *mbox, int devid);
++
+ /* Mailbox message types */
+ #define MBOX_MSG_MASK 0xFFFF
+ #define MBOX_MSG_INVALID 0xFFFE
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c b/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c
+index dfd23580e3b8e..d39d86e694ccf 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/mcs_rvu_if.c
+@@ -121,13 +121,17 @@ int mcs_add_intr_wq_entry(struct mcs *mcs, struct mcs_intr_event *event)
+ static int mcs_notify_pfvf(struct mcs_intr_event *event, struct rvu *rvu)
+ {
+ struct mcs_intr_info *req;
+- int err, pf;
++ int pf;
+
+ pf = rvu_get_pf(event->pcifunc);
+
++ mutex_lock(&rvu->mbox_lock);
++
+ req = otx2_mbox_alloc_msg_mcs_intr_notify(rvu, pf);
+- if (!req)
++ if (!req) {
++ mutex_unlock(&rvu->mbox_lock);
+ return -ENOMEM;
++ }
+
+ req->mcs_id = event->mcs_id;
+ req->intr_mask = event->intr_mask;
+@@ -135,10 +139,11 @@ static int mcs_notify_pfvf(struct mcs_intr_event *event, struct rvu *rvu)
+ req->hdr.pcifunc = event->pcifunc;
+ req->lmac_id = event->lmac_id;
+
+- otx2_mbox_msg_send(&rvu->afpf_wq_info.mbox_up, pf);
+- err = otx2_mbox_wait_for_rsp(&rvu->afpf_wq_info.mbox_up, pf);
+- if (err)
+- dev_warn(rvu->dev, "MCS notification to pf %d failed\n", pf);
++ otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pf);
++
++ otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pf);
++
++ mutex_unlock(&rvu->mbox_lock);
+
+ return 0;
+ }
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+index 5c1d04a3c559b..6a911ea0cff9b 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+@@ -2117,7 +2117,7 @@ MBOX_MESSAGES
+ }
+ }
+
+-static void __rvu_mbox_handler(struct rvu_work *mwork, int type)
++static void __rvu_mbox_handler(struct rvu_work *mwork, int type, bool poll)
+ {
+ struct rvu *rvu = mwork->rvu;
+ int offset, err, id, devid;
+@@ -2184,6 +2184,9 @@ static void __rvu_mbox_handler(struct rvu_work *mwork, int type)
+ }
+ mw->mbox_wrk[devid].num_msgs = 0;
+
++ if (poll)
++ otx2_mbox_wait_for_zero(mbox, devid);
++
+ /* Send mbox responses to VF/PF */
+ otx2_mbox_msg_send(mbox, devid);
+ }
+@@ -2191,15 +2194,18 @@ static void __rvu_mbox_handler(struct rvu_work *mwork, int type)
+ static inline void rvu_afpf_mbox_handler(struct work_struct *work)
+ {
+ struct rvu_work *mwork = container_of(work, struct rvu_work, work);
++ struct rvu *rvu = mwork->rvu;
+
+- __rvu_mbox_handler(mwork, TYPE_AFPF);
++ mutex_lock(&rvu->mbox_lock);
++ __rvu_mbox_handler(mwork, TYPE_AFPF, true);
++ mutex_unlock(&rvu->mbox_lock);
+ }
+
+ static inline void rvu_afvf_mbox_handler(struct work_struct *work)
+ {
+ struct rvu_work *mwork = container_of(work, struct rvu_work, work);
+
+- __rvu_mbox_handler(mwork, TYPE_AFVF);
++ __rvu_mbox_handler(mwork, TYPE_AFVF, false);
+ }
+
+ static void __rvu_mbox_up_handler(struct rvu_work *mwork, int type)
+@@ -2374,6 +2380,8 @@ static int rvu_mbox_init(struct rvu *rvu, struct mbox_wq_info *mw,
+ }
+ }
+
++ mutex_init(&rvu->mbox_lock);
++
+ mbox_regions = kcalloc(num, sizeof(void *), GFP_KERNEL);
+ if (!mbox_regions) {
+ err = -ENOMEM;
+@@ -2523,10 +2531,9 @@ static void rvu_queue_work(struct mbox_wq_info *mw, int first,
+ }
+ }
+
+-static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq)
++static irqreturn_t rvu_mbox_pf_intr_handler(int irq, void *rvu_irq)
+ {
+ struct rvu *rvu = (struct rvu *)rvu_irq;
+- int vfs = rvu->vfs;
+ u64 intr;
+
+ intr = rvu_read64(rvu, BLKADDR_RVUM, RVU_AF_PFAF_MBOX_INT);
+@@ -2540,6 +2547,18 @@ static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq)
+
+ rvu_queue_work(&rvu->afpf_wq_info, 0, rvu->hw->total_pfs, intr);
+
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t rvu_mbox_intr_handler(int irq, void *rvu_irq)
++{
++ struct rvu *rvu = (struct rvu *)rvu_irq;
++ int vfs = rvu->vfs;
++ u64 intr;
++
++ /* Sync with mbox memory region */
++ rmb();
++
+ /* Handle VF interrupts */
+ if (vfs > 64) {
+ intr = rvupf_read64(rvu, RVU_PF_VFPF_MBOX_INTX(1));
+@@ -2881,7 +2900,7 @@ static int rvu_register_interrupts(struct rvu *rvu)
+ /* Register mailbox interrupt handler */
+ sprintf(&rvu->irq_name[RVU_AF_INT_VEC_MBOX * NAME_SIZE], "RVUAF Mbox");
+ ret = request_irq(pci_irq_vector(rvu->pdev, RVU_AF_INT_VEC_MBOX),
+- rvu_mbox_intr_handler, 0,
++ rvu_mbox_pf_intr_handler, 0,
+ &rvu->irq_name[RVU_AF_INT_VEC_MBOX * NAME_SIZE], rvu);
+ if (ret) {
+ dev_err(rvu->dev,
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+index 43be37dd1f325..d44a400e1b502 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+@@ -570,6 +570,8 @@ struct rvu {
+ spinlock_t mcs_intrq_lock;
+ /* CPT interrupt lock */
+ spinlock_t cpt_intr_lock;
++
++ struct mutex mbox_lock; /* Serialize mbox up and down msgs */
+ };
+
+ static inline void rvu_write64(struct rvu *rvu, u64 block, u64 offset, u64 val)
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+index 38acdc7a73bbe..72e060cf6b618 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+@@ -232,7 +232,7 @@ static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu)
+ struct cgx_link_user_info *linfo;
+ struct cgx_link_info_msg *msg;
+ unsigned long pfmap;
+- int err, pfid;
++ int pfid;
+
+ linfo = &event->link_uinfo;
+ pfmap = cgxlmac_to_pfmap(rvu, event->cgx_id, event->lmac_id);
+@@ -255,16 +255,22 @@ static void cgx_notify_pfs(struct cgx_link_event *event, struct rvu *rvu)
+ continue;
+ }
+
++ mutex_lock(&rvu->mbox_lock);
++
+ /* Send mbox message to PF */
+ msg = otx2_mbox_alloc_msg_cgx_link_event(rvu, pfid);
+- if (!msg)
++ if (!msg) {
++ mutex_unlock(&rvu->mbox_lock);
+ continue;
++ }
++
+ msg->link_info = *linfo;
+- otx2_mbox_msg_send(&rvu->afpf_wq_info.mbox_up, pfid);
+- err = otx2_mbox_wait_for_rsp(&rvu->afpf_wq_info.mbox_up, pfid);
+- if (err)
+- dev_warn(rvu->dev, "notification to pf %d failed\n",
+- pfid);
++
++ otx2_mbox_wait_for_zero(&rvu->afpf_wq_info.mbox_up, pfid);
++
++ otx2_mbox_msg_send_up(&rvu->afpf_wq_info.mbox_up, pfid);
++
++ mutex_unlock(&rvu->mbox_lock);
+ } while (pfmap);
+ }
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
+index 1e6fbd98423dc..96c04f7d93f8b 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
+@@ -1235,8 +1235,8 @@ static int rvu_af_dl_dwrr_mtu_get(struct devlink *devlink, u32 id,
+ enum rvu_af_dl_param_id {
+ RVU_AF_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
+ RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,
+- RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
+ RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,
++ RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
+ RVU_AF_DEVLINK_PARAM_ID_NIX_MAXLF,
+ };
+
+@@ -1434,15 +1434,6 @@ static const struct devlink_param rvu_af_dl_params[] = {
+ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+ rvu_af_dl_dwrr_mtu_get, rvu_af_dl_dwrr_mtu_set,
+ rvu_af_dl_dwrr_mtu_validate),
+-};
+-
+-static const struct devlink_param rvu_af_dl_param_exact_match[] = {
+- DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
+- "npc_exact_feature_disable", DEVLINK_PARAM_TYPE_STRING,
+- BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+- rvu_af_npc_exact_feature_get,
+- rvu_af_npc_exact_feature_disable,
+- rvu_af_npc_exact_feature_validate),
+ DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT,
+ "npc_mcam_high_zone_percent", DEVLINK_PARAM_TYPE_U8,
+ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+@@ -1457,6 +1448,15 @@ static const struct devlink_param rvu_af_dl_param_exact_match[] = {
+ rvu_af_dl_nix_maxlf_validate),
+ };
+
++static const struct devlink_param rvu_af_dl_param_exact_match[] = {
++ DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
++ "npc_exact_feature_disable", DEVLINK_PARAM_TYPE_STRING,
++ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
++ rvu_af_npc_exact_feature_get,
++ rvu_af_npc_exact_feature_disable,
++ rvu_af_npc_exact_feature_validate),
++};
++
+ /* Devlink switch mode */
+ static int rvu_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
+ {
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+index 02d0b707aea5b..a85ac039d779b 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+@@ -1592,7 +1592,7 @@ int otx2_detach_resources(struct mbox *mbox)
+ detach->partial = false;
+
+ /* Send detach request to AF */
+- otx2_mbox_msg_send(&mbox->mbox, 0);
++ otx2_sync_mbox_msg(mbox);
+ mutex_unlock(&mbox->lock);
+ return 0;
+ }
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+index 06910307085ef..7e16a341ec588 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+@@ -815,7 +815,7 @@ static inline int otx2_sync_mbox_up_msg(struct mbox *mbox, int devid)
+
+ if (!otx2_mbox_nonempty(&mbox->mbox_up, devid))
+ return 0;
+- otx2_mbox_msg_send(&mbox->mbox_up, devid);
++ otx2_mbox_msg_send_up(&mbox->mbox_up, devid);
+ err = otx2_mbox_wait_for_rsp(&mbox->mbox_up, devid);
+ if (err)
+ return err;
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+index e5fe67e738655..b40bd0e467514 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+@@ -292,8 +292,8 @@ static int otx2_pf_flr_init(struct otx2_nic *pf, int num_vfs)
+ return 0;
+ }
+
+-static void otx2_queue_work(struct mbox *mw, struct workqueue_struct *mbox_wq,
+- int first, int mdevs, u64 intr, int type)
++static void otx2_queue_vf_work(struct mbox *mw, struct workqueue_struct *mbox_wq,
++ int first, int mdevs, u64 intr)
+ {
+ struct otx2_mbox_dev *mdev;
+ struct otx2_mbox *mbox;
+@@ -307,40 +307,26 @@ static void otx2_queue_work(struct mbox *mw, struct workqueue_struct *mbox_wq,
+
+ mbox = &mw->mbox;
+ mdev = &mbox->dev[i];
+- if (type == TYPE_PFAF)
+- otx2_sync_mbox_bbuf(mbox, i);
+ hdr = mdev->mbase + mbox->rx_start;
+ /* The hdr->num_msgs is set to zero immediately in the interrupt
+- * handler to ensure that it holds a correct value next time
+- * when the interrupt handler is called.
+- * pf->mbox.num_msgs holds the data for use in pfaf_mbox_handler
+- * pf>mbox.up_num_msgs holds the data for use in
+- * pfaf_mbox_up_handler.
++ * handler to ensure that it holds a correct value next time
++ * when the interrupt handler is called. pf->mw[i].num_msgs
++ * holds the data for use in otx2_pfvf_mbox_handler and
++ * pf->mw[i].up_num_msgs holds the data for use in
++ * otx2_pfvf_mbox_up_handler.
+ */
+ if (hdr->num_msgs) {
+ mw[i].num_msgs = hdr->num_msgs;
+ hdr->num_msgs = 0;
+- if (type == TYPE_PFAF)
+- memset(mbox->hwbase + mbox->rx_start, 0,
+- ALIGN(sizeof(struct mbox_hdr),
+- sizeof(u64)));
+-
+ queue_work(mbox_wq, &mw[i].mbox_wrk);
+ }
+
+ mbox = &mw->mbox_up;
+ mdev = &mbox->dev[i];
+- if (type == TYPE_PFAF)
+- otx2_sync_mbox_bbuf(mbox, i);
+ hdr = mdev->mbase + mbox->rx_start;
+ if (hdr->num_msgs) {
+ mw[i].up_num_msgs = hdr->num_msgs;
+ hdr->num_msgs = 0;
+- if (type == TYPE_PFAF)
+- memset(mbox->hwbase + mbox->rx_start, 0,
+- ALIGN(sizeof(struct mbox_hdr),
+- sizeof(u64)));
+-
+ queue_work(mbox_wq, &mw[i].mbox_up_wrk);
+ }
+ }
+@@ -356,8 +342,10 @@ static void otx2_forward_msg_pfvf(struct otx2_mbox_dev *mdev,
+ /* Msgs are already copied, trigger VF's mbox irq */
+ smp_wmb();
+
++ otx2_mbox_wait_for_zero(pfvf_mbox, devid);
++
+ offset = pfvf_mbox->trigger | (devid << pfvf_mbox->tr_shift);
+- writeq(1, (void __iomem *)pfvf_mbox->reg_base + offset);
++ writeq(MBOX_DOWN_MSG, (void __iomem *)pfvf_mbox->reg_base + offset);
+
+ /* Restore VF's mbox bounce buffer region address */
+ src_mdev->mbase = bbuf_base;
+@@ -547,7 +535,7 @@ static void otx2_pfvf_mbox_up_handler(struct work_struct *work)
+ end:
+ offset = mbox->rx_start + msg->next_msgoff;
+ if (mdev->msgs_acked == (vf_mbox->up_num_msgs - 1))
+- __otx2_mbox_reset(mbox, 0);
++ __otx2_mbox_reset(mbox, vf_idx);
+ mdev->msgs_acked++;
+ }
+ }
+@@ -564,8 +552,7 @@ static irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq)
+ if (vfs > 64) {
+ intr = otx2_read64(pf, RVU_PF_VFPF_MBOX_INTX(1));
+ otx2_write64(pf, RVU_PF_VFPF_MBOX_INTX(1), intr);
+- otx2_queue_work(mbox, pf->mbox_pfvf_wq, 64, vfs, intr,
+- TYPE_PFVF);
++ otx2_queue_vf_work(mbox, pf->mbox_pfvf_wq, 64, vfs, intr);
+ if (intr)
+ trace_otx2_msg_interrupt(mbox->mbox.pdev, "VF(s) to PF", intr);
+ vfs = 64;
+@@ -574,7 +561,7 @@ static irqreturn_t otx2_pfvf_mbox_intr_handler(int irq, void *pf_irq)
+ intr = otx2_read64(pf, RVU_PF_VFPF_MBOX_INTX(0));
+ otx2_write64(pf, RVU_PF_VFPF_MBOX_INTX(0), intr);
+
+- otx2_queue_work(mbox, pf->mbox_pfvf_wq, 0, vfs, intr, TYPE_PFVF);
++ otx2_queue_vf_work(mbox, pf->mbox_pfvf_wq, 0, vfs, intr);
+
+ if (intr)
+ trace_otx2_msg_interrupt(mbox->mbox.pdev, "VF(s) to PF", intr);
+@@ -597,8 +584,9 @@ static int otx2_pfvf_mbox_init(struct otx2_nic *pf, int numvfs)
+ if (!pf->mbox_pfvf)
+ return -ENOMEM;
+
+- pf->mbox_pfvf_wq = alloc_ordered_workqueue("otx2_pfvf_mailbox",
+- WQ_HIGHPRI | WQ_MEM_RECLAIM);
++ pf->mbox_pfvf_wq = alloc_workqueue("otx2_pfvf_mailbox",
++ WQ_UNBOUND | WQ_HIGHPRI |
++ WQ_MEM_RECLAIM, 0);
+ if (!pf->mbox_pfvf_wq)
+ return -ENOMEM;
+
+@@ -821,20 +809,22 @@ static void otx2_pfaf_mbox_handler(struct work_struct *work)
+ struct mbox *af_mbox;
+ struct otx2_nic *pf;
+ int offset, id;
++ u16 num_msgs;
+
+ af_mbox = container_of(work, struct mbox, mbox_wrk);
+ mbox = &af_mbox->mbox;
+ mdev = &mbox->dev[0];
+ rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
++ num_msgs = rsp_hdr->num_msgs;
+
+ offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);
+ pf = af_mbox->pfvf;
+
+- for (id = 0; id < af_mbox->num_msgs; id++) {
++ for (id = 0; id < num_msgs; id++) {
+ msg = (struct mbox_msghdr *)(mdev->mbase + offset);
+ otx2_process_pfaf_mbox_msg(pf, msg);
+ offset = mbox->rx_start + msg->next_msgoff;
+- if (mdev->msgs_acked == (af_mbox->num_msgs - 1))
++ if (mdev->msgs_acked == (num_msgs - 1))
+ __otx2_mbox_reset(mbox, 0);
+ mdev->msgs_acked++;
+ }
+@@ -945,12 +935,14 @@ static void otx2_pfaf_mbox_up_handler(struct work_struct *work)
+ int offset, id, devid = 0;
+ struct mbox_hdr *rsp_hdr;
+ struct mbox_msghdr *msg;
++ u16 num_msgs;
+
+ rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
++ num_msgs = rsp_hdr->num_msgs;
+
+ offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);
+
+- for (id = 0; id < af_mbox->up_num_msgs; id++) {
++ for (id = 0; id < num_msgs; id++) {
+ msg = (struct mbox_msghdr *)(mdev->mbase + offset);
+
+ devid = msg->pcifunc & RVU_PFVF_FUNC_MASK;
+@@ -959,10 +951,11 @@ static void otx2_pfaf_mbox_up_handler(struct work_struct *work)
+ otx2_process_mbox_msg_up(pf, msg);
+ offset = mbox->rx_start + msg->next_msgoff;
+ }
+- if (devid) {
++ /* Forward to VF iff VFs are really present */
++ if (devid && pci_num_vf(pf->pdev)) {
+ otx2_forward_vf_mbox_msgs(pf, &pf->mbox.mbox_up,
+ MBOX_DIR_PFVF_UP, devid - 1,
+- af_mbox->up_num_msgs);
++ num_msgs);
+ return;
+ }
+
+@@ -972,16 +965,49 @@ static void otx2_pfaf_mbox_up_handler(struct work_struct *work)
+ static irqreturn_t otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq)
+ {
+ struct otx2_nic *pf = (struct otx2_nic *)pf_irq;
+- struct mbox *mbox;
++ struct mbox *mw = &pf->mbox;
++ struct otx2_mbox_dev *mdev;
++ struct otx2_mbox *mbox;
++ struct mbox_hdr *hdr;
++ u64 mbox_data;
+
+ /* Clear the IRQ */
+ otx2_write64(pf, RVU_PF_INT, BIT_ULL(0));
+
+- mbox = &pf->mbox;
+
+- trace_otx2_msg_interrupt(mbox->mbox.pdev, "AF to PF", BIT_ULL(0));
++ mbox_data = otx2_read64(pf, RVU_PF_PFAF_MBOX0);
++
++ if (mbox_data & MBOX_UP_MSG) {
++ mbox_data &= ~MBOX_UP_MSG;
++ otx2_write64(pf, RVU_PF_PFAF_MBOX0, mbox_data);
++
++ mbox = &mw->mbox_up;
++ mdev = &mbox->dev[0];
++ otx2_sync_mbox_bbuf(mbox, 0);
++
++ hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
++ if (hdr->num_msgs)
++ queue_work(pf->mbox_wq, &mw->mbox_up_wrk);
++
++ trace_otx2_msg_interrupt(pf->pdev, "UP message from AF to PF",
++ BIT_ULL(0));
++ }
++
++ if (mbox_data & MBOX_DOWN_MSG) {
++ mbox_data &= ~MBOX_DOWN_MSG;
++ otx2_write64(pf, RVU_PF_PFAF_MBOX0, mbox_data);
++
++ mbox = &mw->mbox;
++ mdev = &mbox->dev[0];
++ otx2_sync_mbox_bbuf(mbox, 0);
++
++ hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
++ if (hdr->num_msgs)
++ queue_work(pf->mbox_wq, &mw->mbox_wrk);
+
+- otx2_queue_work(mbox, pf->mbox_wq, 0, 1, 1, TYPE_PFAF);
++ trace_otx2_msg_interrupt(pf->pdev, "DOWN reply from AF to PF",
++ BIT_ULL(0));
++ }
+
+ return IRQ_HANDLED;
+ }
+@@ -3087,6 +3113,7 @@ static void otx2_vf_link_event_task(struct work_struct *work)
+ struct otx2_vf_config *config;
+ struct cgx_link_info_msg *req;
+ struct mbox_msghdr *msghdr;
++ struct delayed_work *dwork;
+ struct otx2_nic *pf;
+ int vf_idx;
+
+@@ -3095,10 +3122,24 @@ static void otx2_vf_link_event_task(struct work_struct *work)
+ vf_idx = config - config->pf->vf_configs;
+ pf = config->pf;
+
++ if (config->intf_down)
++ return;
++
++ mutex_lock(&pf->mbox.lock);
++
++ dwork = &config->link_event_work;
++
++ if (!otx2_mbox_wait_for_zero(&pf->mbox_pfvf[0].mbox_up, vf_idx)) {
++ schedule_delayed_work(dwork, msecs_to_jiffies(100));
++ mutex_unlock(&pf->mbox.lock);
++ return;
++ }
++
+ msghdr = otx2_mbox_alloc_msg_rsp(&pf->mbox_pfvf[0].mbox_up, vf_idx,
+ sizeof(*req), sizeof(struct msg_rsp));
+ if (!msghdr) {
+ dev_err(pf->dev, "Failed to create VF%d link event\n", vf_idx);
++ mutex_unlock(&pf->mbox.lock);
+ return;
+ }
+
+@@ -3107,7 +3148,11 @@ static void otx2_vf_link_event_task(struct work_struct *work)
+ req->hdr.sig = OTX2_MBOX_REQ_SIG;
+ memcpy(&req->link_info, &pf->linfo, sizeof(req->link_info));
+
++ otx2_mbox_wait_for_zero(&pf->mbox_pfvf[0].mbox_up, vf_idx);
++
+ otx2_sync_mbox_up_msg(&pf->mbox_pfvf[0], vf_idx);
++
++ mutex_unlock(&pf->mbox.lock);
+ }
+
+ static int otx2_sriov_enable(struct pci_dev *pdev, int numvfs)
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+index 35e06048356f4..cf0aa16d75407 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+@@ -89,16 +89,20 @@ static void otx2vf_vfaf_mbox_handler(struct work_struct *work)
+ struct otx2_mbox *mbox;
+ struct mbox *af_mbox;
+ int offset, id;
++ u16 num_msgs;
+
+ af_mbox = container_of(work, struct mbox, mbox_wrk);
+ mbox = &af_mbox->mbox;
+ mdev = &mbox->dev[0];
+ rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
+- if (af_mbox->num_msgs == 0)
++ num_msgs = rsp_hdr->num_msgs;
++
++ if (num_msgs == 0)
+ return;
++
+ offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);
+
+- for (id = 0; id < af_mbox->num_msgs; id++) {
++ for (id = 0; id < num_msgs; id++) {
+ msg = (struct mbox_msghdr *)(mdev->mbase + offset);
+ otx2vf_process_vfaf_mbox_msg(af_mbox->pfvf, msg);
+ offset = mbox->rx_start + msg->next_msgoff;
+@@ -151,6 +155,7 @@ static void otx2vf_vfaf_mbox_up_handler(struct work_struct *work)
+ struct mbox *vf_mbox;
+ struct otx2_nic *vf;
+ int offset, id;
++ u16 num_msgs;
+
+ vf_mbox = container_of(work, struct mbox, mbox_up_wrk);
+ vf = vf_mbox->pfvf;
+@@ -158,12 +163,14 @@ static void otx2vf_vfaf_mbox_up_handler(struct work_struct *work)
+ mdev = &mbox->dev[0];
+
+ rsp_hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
+- if (vf_mbox->up_num_msgs == 0)
++ num_msgs = rsp_hdr->num_msgs;
++
++ if (num_msgs == 0)
+ return;
+
+ offset = mbox->rx_start + ALIGN(sizeof(*rsp_hdr), MBOX_MSG_ALIGN);
+
+- for (id = 0; id < vf_mbox->up_num_msgs; id++) {
++ for (id = 0; id < num_msgs; id++) {
+ msg = (struct mbox_msghdr *)(mdev->mbase + offset);
+ otx2vf_process_mbox_msg_up(vf, msg);
+ offset = mbox->rx_start + msg->next_msgoff;
+@@ -178,40 +185,48 @@ static irqreturn_t otx2vf_vfaf_mbox_intr_handler(int irq, void *vf_irq)
+ struct otx2_mbox_dev *mdev;
+ struct otx2_mbox *mbox;
+ struct mbox_hdr *hdr;
++ u64 mbox_data;
+
+ /* Clear the IRQ */
+ otx2_write64(vf, RVU_VF_INT, BIT_ULL(0));
+
++ mbox_data = otx2_read64(vf, RVU_VF_VFPF_MBOX0);
++
+ /* Read latest mbox data */
+ smp_rmb();
+
+- /* Check for PF => VF response messages */
+- mbox = &vf->mbox.mbox;
+- mdev = &mbox->dev[0];
+- otx2_sync_mbox_bbuf(mbox, 0);
++ if (mbox_data & MBOX_DOWN_MSG) {
++ mbox_data &= ~MBOX_DOWN_MSG;
++ otx2_write64(vf, RVU_VF_VFPF_MBOX0, mbox_data);
++
++ /* Check for PF => VF response messages */
++ mbox = &vf->mbox.mbox;
++ mdev = &mbox->dev[0];
++ otx2_sync_mbox_bbuf(mbox, 0);
+
+- trace_otx2_msg_interrupt(mbox->pdev, "PF to VF", BIT_ULL(0));
++ hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
++ if (hdr->num_msgs)
++ queue_work(vf->mbox_wq, &vf->mbox.mbox_wrk);
+
+- hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
+- if (hdr->num_msgs) {
+- vf->mbox.num_msgs = hdr->num_msgs;
+- hdr->num_msgs = 0;
+- memset(mbox->hwbase + mbox->rx_start, 0,
+- ALIGN(sizeof(struct mbox_hdr), sizeof(u64)));
+- queue_work(vf->mbox_wq, &vf->mbox.mbox_wrk);
++ trace_otx2_msg_interrupt(mbox->pdev, "DOWN reply from PF to VF",
++ BIT_ULL(0));
+ }
+- /* Check for PF => VF notification messages */
+- mbox = &vf->mbox.mbox_up;
+- mdev = &mbox->dev[0];
+- otx2_sync_mbox_bbuf(mbox, 0);
+
+- hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
+- if (hdr->num_msgs) {
+- vf->mbox.up_num_msgs = hdr->num_msgs;
+- hdr->num_msgs = 0;
+- memset(mbox->hwbase + mbox->rx_start, 0,
+- ALIGN(sizeof(struct mbox_hdr), sizeof(u64)));
+- queue_work(vf->mbox_wq, &vf->mbox.mbox_up_wrk);
++ if (mbox_data & MBOX_UP_MSG) {
++ mbox_data &= ~MBOX_UP_MSG;
++ otx2_write64(vf, RVU_VF_VFPF_MBOX0, mbox_data);
++
++ /* Check for PF => VF notification messages */
++ mbox = &vf->mbox.mbox_up;
++ mdev = &mbox->dev[0];
++ otx2_sync_mbox_bbuf(mbox, 0);
++
++ hdr = (struct mbox_hdr *)(mdev->mbase + mbox->rx_start);
++ if (hdr->num_msgs)
++ queue_work(vf->mbox_wq, &vf->mbox.mbox_up_wrk);
++
++ trace_otx2_msg_interrupt(mbox->pdev, "UP message from PF to VF",
++ BIT_ULL(0));
+ }
+
+ return IRQ_HANDLED;
+@@ -760,8 +775,8 @@ static void otx2vf_remove(struct pci_dev *pdev)
+ otx2_mcam_flow_del(vf);
+ otx2_shutdown_tc(vf);
+ otx2_shutdown_qos(vf);
+- otx2vf_disable_mbox_intr(vf);
+ otx2_detach_resources(&vf->mbox);
++ otx2vf_disable_mbox_intr(vf);
+ free_percpu(vf->hw.lmt_info);
+ if (test_bit(CN10K_LMTST, &vf->hw.cap_flag))
+ qmem_free(vf->dev, vf->dync_lmt);
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+index de123350bd46b..caa13b9cedff0 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -677,8 +677,7 @@ static int mtk_mac_finish(struct phylink_config *config, unsigned int mode,
+ mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+ mcr_new = mcr_cur;
+ mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
+- MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK |
+- MAC_MCR_RX_FIFO_CLR_DIS;
++ MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_RX_FIFO_CLR_DIS;
+
+ /* Only update control register when needed! */
+ if (mcr_new != mcr_cur)
+@@ -694,7 +693,7 @@ static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode,
+ phylink_config);
+ u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+
+- mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN);
++ mcr &= ~(MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK);
+ mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+ }
+
+@@ -803,7 +802,7 @@ static void mtk_mac_link_up(struct phylink_config *config,
+ if (rx_pause)
+ mcr |= MAC_MCR_FORCE_RX_FC;
+
+- mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN;
++ mcr |= MAC_MCR_TX_EN | MAC_MCR_RX_EN | MAC_MCR_FORCE_LINK;
+ mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+ }
+
+diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
+index b2a5d9c3733d4..6ce0db3a1a920 100644
+--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
++++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
+@@ -994,7 +994,7 @@ void mtk_ppe_start(struct mtk_ppe *ppe)
+ MTK_PPE_KEEPALIVE_DISABLE) |
+ FIELD_PREP(MTK_PPE_TB_CFG_HASH_MODE, 1) |
+ FIELD_PREP(MTK_PPE_TB_CFG_SCAN_MODE,
+- MTK_PPE_SCAN_MODE_KEEPALIVE_AGE) |
++ MTK_PPE_SCAN_MODE_CHECK_AGE) |
+ FIELD_PREP(MTK_PPE_TB_CFG_ENTRY_NUM,
+ MTK_PPE_ENTRIES_SHIFT);
+ if (mtk_is_netsys_v2_or_greater(ppe->eth))
+@@ -1090,17 +1090,21 @@ int mtk_ppe_stop(struct mtk_ppe *ppe)
+
+ mtk_ppe_cache_enable(ppe, false);
+
+- /* disable offload engine */
+- ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN);
+- ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0);
+-
+ /* disable aging */
+ val = MTK_PPE_TB_CFG_AGE_NON_L4 |
+ MTK_PPE_TB_CFG_AGE_UNBIND |
+ MTK_PPE_TB_CFG_AGE_TCP |
+ MTK_PPE_TB_CFG_AGE_UDP |
+- MTK_PPE_TB_CFG_AGE_TCP_FIN;
++ MTK_PPE_TB_CFG_AGE_TCP_FIN |
++ MTK_PPE_TB_CFG_SCAN_MODE;
+ ppe_clear(ppe, MTK_PPE_TB_CFG, val);
+
+- return mtk_ppe_wait_busy(ppe);
++ if (mtk_ppe_wait_busy(ppe))
++ return -ETIMEDOUT;
++
++ /* disable offload engine */
++ ppe_clear(ppe, MTK_PPE_GLO_CFG, MTK_PPE_GLO_CFG_EN);
++ ppe_w32(ppe, MTK_PPE_FLOW_CFG, 0);
++
++ return 0;
+ }
+diff --git a/drivers/net/ethernet/netronome/nfp/flower/lag_conf.c b/drivers/net/ethernet/netronome/nfp/flower/lag_conf.c
+index 361d7c495e2d8..2c7bd6e80d993 100644
+--- a/drivers/net/ethernet/netronome/nfp/flower/lag_conf.c
++++ b/drivers/net/ethernet/netronome/nfp/flower/lag_conf.c
+@@ -337,6 +337,11 @@ static void nfp_fl_lag_do_work(struct work_struct *work)
+
+ acti_netdevs = kmalloc_array(entry->slave_cnt,
+ sizeof(*acti_netdevs), GFP_KERNEL);
++ if (!acti_netdevs) {
++ schedule_delayed_work(&lag->work,
++ NFP_FL_LAG_DELAY);
++ continue;
++ }
+
+ /* Include sanity check in the loop. It may be that a bond has
+ * changed between processing the last notification and the
+diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
+index 1b84d495d14e8..29997e4b2d6ca 100644
+--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
+@@ -556,7 +556,7 @@ static int txgbe_clock_register(struct txgbe *txgbe)
+ char clk_name[32];
+ struct clk *clk;
+
+- snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d",
++ snprintf(clk_name, sizeof(clk_name), "i2c_dw.%d",
+ pci_dev_id(pdev));
+
+ clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000);
+diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c
+index b7cb71817780c..29e1cbea6dc0c 100644
+--- a/drivers/net/phy/dp83822.c
++++ b/drivers/net/phy/dp83822.c
+@@ -380,7 +380,7 @@ static int dp83822_config_init(struct phy_device *phydev)
+ {
+ struct dp83822_private *dp83822 = phydev->priv;
+ struct device *dev = &phydev->mdio.dev;
+- int rgmii_delay;
++ int rgmii_delay = 0;
+ s32 rx_int_delay;
+ s32 tx_int_delay;
+ int err = 0;
+@@ -390,30 +390,33 @@ static int dp83822_config_init(struct phy_device *phydev)
+ rx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,
+ true);
+
+- if (rx_int_delay <= 0)
+- rgmii_delay = 0;
+- else
+- rgmii_delay = DP83822_RX_CLK_SHIFT;
++ /* Set DP83822_RX_CLK_SHIFT to enable rx clk internal delay */
++ if (rx_int_delay > 0)
++ rgmii_delay |= DP83822_RX_CLK_SHIFT;
+
+ tx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,
+ false);
++
++ /* Set DP83822_TX_CLK_SHIFT to disable tx clk internal delay */
+ if (tx_int_delay <= 0)
+- rgmii_delay &= ~DP83822_TX_CLK_SHIFT;
+- else
+ rgmii_delay |= DP83822_TX_CLK_SHIFT;
+
+- if (rgmii_delay) {
+- err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,
+- MII_DP83822_RCSR, rgmii_delay);
+- if (err)
+- return err;
+- }
++ err = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR,
++ DP83822_RX_CLK_SHIFT | DP83822_TX_CLK_SHIFT, rgmii_delay);
++ if (err)
++ return err;
++
++ err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,
++ MII_DP83822_RCSR, DP83822_RGMII_MODE_EN);
+
+- phy_set_bits_mmd(phydev, DP83822_DEVADDR,
+- MII_DP83822_RCSR, DP83822_RGMII_MODE_EN);
++ if (err)
++ return err;
+ } else {
+- phy_clear_bits_mmd(phydev, DP83822_DEVADDR,
+- MII_DP83822_RCSR, DP83822_RGMII_MODE_EN);
++ err = phy_clear_bits_mmd(phydev, DP83822_DEVADDR,
++ MII_DP83822_RCSR, DP83822_RGMII_MODE_EN);
++
++ if (err)
++ return err;
+ }
+
+ if (dp83822->fx_enabled) {
+diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
+index 3611ea64875ef..6125418ca93f3 100644
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -2706,8 +2706,8 @@ EXPORT_SYMBOL(genphy_resume);
+ int genphy_loopback(struct phy_device *phydev, bool enable)
+ {
+ if (enable) {
+- u16 val, ctl = BMCR_LOOPBACK;
+- int ret;
++ u16 ctl = BMCR_LOOPBACK;
++ int ret, val;
+
+ ctl |= mii_bmcr_encode_fixed(phydev->speed, phydev->duplex);
+
+@@ -2959,7 +2959,7 @@ s32 phy_get_internal_delay(struct phy_device *phydev, struct device *dev,
+ if (delay < 0)
+ return delay;
+
+- if (delay && size == 0)
++ if (size == 0)
+ return delay;
+
+ if (delay < delay_values[0] || delay > delay_values[size - 1]) {
+diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
+index 0d0672d2a6545..51fe00c2b896e 100644
+--- a/drivers/net/usb/r8152.c
++++ b/drivers/net/usb/r8152.c
+@@ -10078,7 +10078,7 @@ static int rtl8152_cfgselector_choose_configuration(struct usb_device *udev)
+ * driver supports it.
+ */
+ if (__rtl_get_hw_ver(udev) == RTL_VER_UNKNOWN)
+- return 0;
++ return -ENODEV;
+
+ /* The vendor mode is not always config #1, so to find it out. */
+ c = udev->config;
+diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c
+index 143bd4ab160df..57947a5590cca 100644
+--- a/drivers/net/usb/sr9800.c
++++ b/drivers/net/usb/sr9800.c
+@@ -737,7 +737,9 @@ static int sr9800_bind(struct usbnet *dev, struct usb_interface *intf)
+
+ data->eeprom_len = SR9800_EEPROM_LEN;
+
+- usbnet_get_endpoints(dev, intf);
++ ret = usbnet_get_endpoints(dev, intf);
++ if (ret)
++ goto out;
+
+ /* LED Setting Rule :
+ * AABB:CCDD
+diff --git a/drivers/net/veth.c b/drivers/net/veth.c
+index cd4a6fe458f95..f0b2c4d5fe43a 100644
+--- a/drivers/net/veth.c
++++ b/drivers/net/veth.c
+@@ -1533,8 +1533,6 @@ static netdev_features_t veth_fix_features(struct net_device *dev,
+ if (peer_priv->_xdp_prog)
+ features &= ~NETIF_F_GSO_SOFTWARE;
+ }
+- if (priv->_xdp_prog)
+- features |= NETIF_F_GRO;
+
+ return features;
+ }
+@@ -1638,14 +1636,6 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
+ }
+
+ if (!old_prog) {
+- if (!veth_gro_requested(dev)) {
+- /* user-space did not require GRO, but adding
+- * XDP is supposed to get GRO working
+- */
+- dev->features |= NETIF_F_GRO;
+- netdev_features_change(dev);
+- }
+-
+ peer->hw_features &= ~NETIF_F_GSO_SOFTWARE;
+ peer->max_mtu = max_mtu;
+ }
+@@ -1661,14 +1651,6 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
+ if (dev->flags & IFF_UP)
+ veth_disable_xdp(dev);
+
+- /* if user-space did not require GRO, since adding XDP
+- * enabled it, clear it now
+- */
+- if (!veth_gro_requested(dev)) {
+- dev->features &= ~NETIF_F_GRO;
+- netdev_features_change(dev);
+- }
+-
+ if (peer) {
+ peer->hw_features |= NETIF_F_GSO_SOFTWARE;
+ peer->max_mtu = ETH_MAX_MTU;
+diff --git a/drivers/net/vmxnet3/vmxnet3_xdp.c b/drivers/net/vmxnet3/vmxnet3_xdp.c
+index 80ddaff759d47..a6c787454a1ae 100644
+--- a/drivers/net/vmxnet3/vmxnet3_xdp.c
++++ b/drivers/net/vmxnet3/vmxnet3_xdp.c
+@@ -382,12 +382,12 @@ vmxnet3_process_xdp(struct vmxnet3_adapter *adapter,
+ page = rbi->page;
+ dma_sync_single_for_cpu(&adapter->pdev->dev,
+ page_pool_get_dma_addr(page) +
+- rq->page_pool->p.offset, rcd->len,
++ rq->page_pool->p.offset, rbi->len,
+ page_pool_get_dma_dir(rq->page_pool));
+
+- xdp_init_buff(&xdp, rbi->len, &rq->xdp_rxq);
++ xdp_init_buff(&xdp, PAGE_SIZE, &rq->xdp_rxq);
+ xdp_prepare_buff(&xdp, page_address(page), rq->page_pool->p.offset,
+- rcd->len, false);
++ rbi->len, false);
+ xdp_buff_clear_frags_flag(&xdp);
+
+ xdp_prog = rcu_dereference(rq->adapter->xdp_bpf_prog);
+diff --git a/drivers/net/wireguard/receive.c b/drivers/net/wireguard/receive.c
+index a176653c88616..db01ec03bda00 100644
+--- a/drivers/net/wireguard/receive.c
++++ b/drivers/net/wireguard/receive.c
+@@ -251,7 +251,7 @@ static bool decrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair)
+
+ if (unlikely(!READ_ONCE(keypair->receiving.is_valid) ||
+ wg_birthdate_has_expired(keypair->receiving.birthdate, REJECT_AFTER_TIME) ||
+- keypair->receiving_counter.counter >= REJECT_AFTER_MESSAGES)) {
++ READ_ONCE(keypair->receiving_counter.counter) >= REJECT_AFTER_MESSAGES)) {
+ WRITE_ONCE(keypair->receiving.is_valid, false);
+ return false;
+ }
+@@ -318,7 +318,7 @@ static bool counter_validate(struct noise_replay_counter *counter, u64 their_cou
+ for (i = 1; i <= top; ++i)
+ counter->backtrack[(i + index_current) &
+ ((COUNTER_BITS_TOTAL / BITS_PER_LONG) - 1)] = 0;
+- counter->counter = their_counter;
++ WRITE_ONCE(counter->counter, their_counter);
+ }
+
+ index &= (COUNTER_BITS_TOTAL / BITS_PER_LONG) - 1;
+@@ -463,7 +463,7 @@ int wg_packet_rx_poll(struct napi_struct *napi, int budget)
+ net_dbg_ratelimited("%s: Packet has invalid nonce %llu (max %llu)\n",
+ peer->device->dev->name,
+ PACKET_CB(skb)->nonce,
+- keypair->receiving_counter.counter);
++ READ_ONCE(keypair->receiving_counter.counter));
+ goto next;
+ }
+
+diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+index 6b6aa3c367448..0ce08e9a0a3d2 100644
+--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
++++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+@@ -851,6 +851,10 @@ ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb,
+ }
+
+ ev = tb[WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_EVENT];
++ if (!ev) {
++ kfree(tb);
++ return -EPROTO;
++ }
+
+ arg->desc_id = ev->desc_id;
+ arg->status = ev->status;
+diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
+index 02e160d831bed..cd829ec70d76b 100644
+--- a/drivers/net/wireless/ath/ath11k/core.h
++++ b/drivers/net/wireless/ath/ath11k/core.h
+@@ -918,6 +918,7 @@ struct ath11k_base {
+ * This may or may not be used during the runtime
+ */
+ struct ieee80211_regdomain *new_regd[MAX_RADIOS];
++ struct cur_regulatory_info *reg_info_store;
+
+ /* Current DFS Regulatory */
+ enum ath11k_dfs_region dfs_region;
+diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
+index b13525bbbb808..cc80310088ce1 100644
+--- a/drivers/net/wireless/ath/ath11k/mac.c
++++ b/drivers/net/wireless/ath/ath11k/mac.c
+@@ -2297,6 +2297,8 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
+ mcs_160_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160);
+ mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
+
++ /* Initialize rx_mcs_160 to 9 which is an invalid value */
++ rx_mcs_160 = 9;
+ if (support_160) {
+ for (i = 7; i >= 0; i--) {
+ u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3;
+@@ -2308,6 +2310,8 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
+ }
+ }
+
++ /* Initialize rx_mcs_80 to 9 which is an invalid value */
++ rx_mcs_80 = 9;
+ for (i = 7; i >= 0; i--) {
+ u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3;
+
+@@ -3026,7 +3030,14 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
+
+ rcu_read_unlock();
+
++ if (!ath11k_mac_vif_recalc_sta_he_txbf(ar, vif, &he_cap)) {
++ ath11k_warn(ar->ab, "failed to recalc he txbf for vdev %i on bss %pM\n",
++ arvif->vdev_id, bss_conf->bssid);
++ return;
++ }
++
+ peer_arg.is_assoc = true;
++
+ ret = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
+ if (ret) {
+ ath11k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n",
+@@ -3049,12 +3060,6 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
+ return;
+ }
+
+- if (!ath11k_mac_vif_recalc_sta_he_txbf(ar, vif, &he_cap)) {
+- ath11k_warn(ar->ab, "failed to recalc he txbf for vdev %i on bss %pM\n",
+- arvif->vdev_id, bss_conf->bssid);
+- return;
+- }
+-
+ WARN_ON(arvif->is_up);
+
+ arvif->aid = vif->cfg.aid;
+diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c
+index b4fd4d2107c71..d4fd3509e608c 100644
+--- a/drivers/net/wireless/ath/ath11k/reg.c
++++ b/drivers/net/wireless/ath/ath11k/reg.c
+@@ -618,25 +618,68 @@ ath11k_reg_update_weather_radar_band(struct ath11k_base *ab,
+ *rule_idx = i;
+ }
+
++enum wmi_reg_6ghz_ap_type
++ath11k_reg_ap_pwr_convert(enum ieee80211_ap_reg_power power_type)
++{
++ switch (power_type) {
++ case IEEE80211_REG_LPI_AP:
++ return WMI_REG_INDOOR_AP;
++ case IEEE80211_REG_SP_AP:
++ return WMI_REG_STANDARD_POWER_AP;
++ case IEEE80211_REG_VLP_AP:
++ return WMI_REG_VERY_LOW_POWER_AP;
++ default:
++ return WMI_REG_MAX_AP_TYPE;
++ }
++}
++
+ struct ieee80211_regdomain *
+ ath11k_reg_build_regd(struct ath11k_base *ab,
+- struct cur_regulatory_info *reg_info, bool intersect)
++ struct cur_regulatory_info *reg_info, bool intersect,
++ enum wmi_vdev_type vdev_type,
++ enum ieee80211_ap_reg_power power_type)
+ {
+ struct ieee80211_regdomain *tmp_regd, *default_regd, *new_regd = NULL;
+- struct cur_reg_rule *reg_rule;
++ struct cur_reg_rule *reg_rule, *reg_rule_6ghz;
+ u8 i = 0, j = 0, k = 0;
+ u8 num_rules;
+ u16 max_bw;
+- u32 flags;
++ u32 flags, reg_6ghz_number, max_bw_6ghz;
+ char alpha2[3];
+
+ num_rules = reg_info->num_5ghz_reg_rules + reg_info->num_2ghz_reg_rules;
+
+- /* FIXME: Currently taking reg rules for 6 GHz only from Indoor AP mode list.
+- * This can be updated after complete 6 GHz regulatory support is added.
+- */
+- if (reg_info->is_ext_reg_event)
+- num_rules += reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP];
++ if (reg_info->is_ext_reg_event) {
++ if (vdev_type == WMI_VDEV_TYPE_STA) {
++ enum wmi_reg_6ghz_ap_type ap_type;
++
++ ap_type = ath11k_reg_ap_pwr_convert(power_type);
++
++ if (ap_type == WMI_REG_MAX_AP_TYPE)
++ ap_type = WMI_REG_INDOOR_AP;
++
++ reg_6ghz_number = reg_info->num_6ghz_rules_client
++ [ap_type][WMI_REG_DEFAULT_CLIENT];
++
++ if (reg_6ghz_number == 0) {
++ ap_type = WMI_REG_INDOOR_AP;
++ reg_6ghz_number = reg_info->num_6ghz_rules_client
++ [ap_type][WMI_REG_DEFAULT_CLIENT];
++ }
++
++ reg_rule_6ghz = reg_info->reg_rules_6ghz_client_ptr
++ [ap_type][WMI_REG_DEFAULT_CLIENT];
++ max_bw_6ghz = reg_info->max_bw_6ghz_client
++ [ap_type][WMI_REG_DEFAULT_CLIENT];
++ } else {
++ reg_6ghz_number = reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP];
++ reg_rule_6ghz =
++ reg_info->reg_rules_6ghz_ap_ptr[WMI_REG_INDOOR_AP];
++ max_bw_6ghz = reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP];
++ }
++
++ num_rules += reg_6ghz_number;
++ }
+
+ if (!num_rules)
+ goto ret;
+@@ -683,13 +726,10 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
+ * per other BW rule flags we pass from here
+ */
+ flags = NL80211_RRF_AUTO_BW;
+- } else if (reg_info->is_ext_reg_event &&
+- reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP] &&
+- (k < reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP])) {
+- reg_rule = reg_info->reg_rules_6ghz_ap_ptr[WMI_REG_INDOOR_AP] +
+- k++;
+- max_bw = min_t(u16, reg_rule->max_bw,
+- reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP]);
++ } else if (reg_info->is_ext_reg_event && reg_6ghz_number &&
++ k < reg_6ghz_number) {
++ reg_rule = reg_rule_6ghz + k++;
++ max_bw = min_t(u16, reg_rule->max_bw, max_bw_6ghz);
+ flags = NL80211_RRF_AUTO_BW;
+ } else {
+ break;
+@@ -758,6 +798,159 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
+ return new_regd;
+ }
+
++static bool ath11k_reg_is_world_alpha(char *alpha)
++{
++ if (alpha[0] == '0' && alpha[1] == '0')
++ return true;
++
++ if (alpha[0] == 'n' && alpha[1] == 'a')
++ return true;
++
++ return false;
++}
++
++static enum wmi_vdev_type ath11k_reg_get_ar_vdev_type(struct ath11k *ar)
++{
++ struct ath11k_vif *arvif;
++
++ /* Currently each struct ath11k maps to one struct ieee80211_hw/wiphy
++ * and one struct ieee80211_regdomain, so it could only store one group
++ * reg rules. It means multi-interface concurrency in the same ath11k is
++ * not support for the regdomain. So get the vdev type of the first entry
++ * now. After concurrency support for the regdomain, this should change.
++ */
++ arvif = list_first_entry_or_null(&ar->arvifs, struct ath11k_vif, list);
++ if (arvif)
++ return arvif->vdev_type;
++
++ return WMI_VDEV_TYPE_UNSPEC;
++}
++
++int ath11k_reg_handle_chan_list(struct ath11k_base *ab,
++ struct cur_regulatory_info *reg_info,
++ enum ieee80211_ap_reg_power power_type)
++{
++ struct ieee80211_regdomain *regd;
++ bool intersect = false;
++ int pdev_idx;
++ struct ath11k *ar;
++ enum wmi_vdev_type vdev_type;
++
++ ath11k_dbg(ab, ATH11K_DBG_WMI, "event reg handle chan list");
++
++ if (reg_info->status_code != REG_SET_CC_STATUS_PASS) {
++ /* In case of failure to set the requested ctry,
++ * fw retains the current regd. We print a failure info
++ * and return from here.
++ */
++ ath11k_warn(ab, "Failed to set the requested Country regulatory setting\n");
++ return -EINVAL;
++ }
++
++ pdev_idx = reg_info->phy_id;
++
++ /* Avoid default reg rule updates sent during FW recovery if
++ * it is already available
++ */
++ spin_lock_bh(&ab->base_lock);
++ if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags) &&
++ ab->default_regd[pdev_idx]) {
++ spin_unlock_bh(&ab->base_lock);
++ goto retfail;
++ }
++ spin_unlock_bh(&ab->base_lock);
++
++ if (pdev_idx >= ab->num_radios) {
++ /* Process the event for phy0 only if single_pdev_only
++ * is true. If pdev_idx is valid but not 0, discard the
++ * event. Otherwise, it goes to fallback. In either case
++ * ath11k_reg_reset_info() needs to be called to avoid
++ * memory leak issue.
++ */
++ ath11k_reg_reset_info(reg_info);
++
++ if (ab->hw_params.single_pdev_only &&
++ pdev_idx < ab->hw_params.num_rxmda_per_pdev)
++ return 0;
++ goto fallback;
++ }
++
++ /* Avoid multiple overwrites to default regd, during core
++ * stop-start after mac registration.
++ */
++ if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
++ !memcmp((char *)ab->default_regd[pdev_idx]->alpha2,
++ (char *)reg_info->alpha2, 2))
++ goto retfail;
++
++ /* Intersect new rules with default regd if a new country setting was
++ * requested, i.e a default regd was already set during initialization
++ * and the regd coming from this event has a valid country info.
++ */
++ if (ab->default_regd[pdev_idx] &&
++ !ath11k_reg_is_world_alpha((char *)
++ ab->default_regd[pdev_idx]->alpha2) &&
++ !ath11k_reg_is_world_alpha((char *)reg_info->alpha2))
++ intersect = true;
++
++ ar = ab->pdevs[pdev_idx].ar;
++ vdev_type = ath11k_reg_get_ar_vdev_type(ar);
++
++ ath11k_dbg(ab, ATH11K_DBG_WMI,
++ "wmi handle chan list power type %d vdev type %d intersect %d\n",
++ power_type, vdev_type, intersect);
++
++ regd = ath11k_reg_build_regd(ab, reg_info, intersect, vdev_type, power_type);
++ if (!regd) {
++ ath11k_warn(ab, "failed to build regd from reg_info\n");
++ goto fallback;
++ }
++
++ if (power_type == IEEE80211_REG_UNSET_AP) {
++ ath11k_reg_reset_info(&ab->reg_info_store[pdev_idx]);
++ ab->reg_info_store[pdev_idx] = *reg_info;
++ }
++
++ spin_lock_bh(&ab->base_lock);
++ if (ab->default_regd[pdev_idx]) {
++ /* The initial rules from FW after WMI Init is to build
++ * the default regd. From then on, any rules updated for
++ * the pdev could be due to user reg changes.
++ * Free previously built regd before assigning the newly
++ * generated regd to ar. NULL pointer handling will be
++ * taken care by kfree itself.
++ */
++ ar = ab->pdevs[pdev_idx].ar;
++ kfree(ab->new_regd[pdev_idx]);
++ ab->new_regd[pdev_idx] = regd;
++ queue_work(ab->workqueue, &ar->regd_update_work);
++ } else {
++ /* This regd would be applied during mac registration and is
++ * held constant throughout for regd intersection purpose
++ */
++ ab->default_regd[pdev_idx] = regd;
++ }
++ ab->dfs_region = reg_info->dfs_region;
++ spin_unlock_bh(&ab->base_lock);
++
++ return 0;
++
++fallback:
++ /* Fallback to older reg (by sending previous country setting
++ * again if fw has succeeded and we failed to process here.
++ * The Regdomain should be uniform across driver and fw. Since the
++ * FW has processed the command and sent a success status, we expect
++ * this function to succeed as well. If it doesn't, CTRY needs to be
++ * reverted at the fw and the old SCAN_CHAN_LIST cmd needs to be sent.
++ */
++ /* TODO: This is rare, but still should also be handled */
++ WARN_ON(1);
++
++retfail:
++
++ return -EINVAL;
++}
++
+ void ath11k_regd_update_work(struct work_struct *work)
+ {
+ struct ath11k *ar = container_of(work, struct ath11k,
+@@ -781,10 +974,36 @@ void ath11k_reg_init(struct ath11k *ar)
+ ar->hw->wiphy->reg_notifier = ath11k_reg_notifier;
+ }
+
++void ath11k_reg_reset_info(struct cur_regulatory_info *reg_info)
++{
++ int i, j;
++
++ if (!reg_info)
++ return;
++
++ kfree(reg_info->reg_rules_2ghz_ptr);
++ kfree(reg_info->reg_rules_5ghz_ptr);
++
++ for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) {
++ kfree(reg_info->reg_rules_6ghz_ap_ptr[i]);
++
++ for (j = 0; j < WMI_REG_MAX_CLIENT_TYPE; j++)
++ kfree(reg_info->reg_rules_6ghz_client_ptr[i][j]);
++ }
++
++ memset(reg_info, 0, sizeof(*reg_info));
++}
++
+ void ath11k_reg_free(struct ath11k_base *ab)
+ {
+ int i;
+
++ for (i = 0; i < ab->num_radios; i++)
++ ath11k_reg_reset_info(&ab->reg_info_store[i]);
++
++ kfree(ab->reg_info_store);
++ ab->reg_info_store = NULL;
++
+ for (i = 0; i < ab->hw_params.max_radios; i++) {
+ kfree(ab->default_regd[i]);
+ kfree(ab->new_regd[i]);
+diff --git a/drivers/net/wireless/ath/ath11k/reg.h b/drivers/net/wireless/ath/ath11k/reg.h
+index f28902f85e419..64edb794260ab 100644
+--- a/drivers/net/wireless/ath/ath11k/reg.h
++++ b/drivers/net/wireless/ath/ath11k/reg.h
+@@ -30,11 +30,20 @@ enum ath11k_dfs_region {
+
+ /* ATH11K Regulatory API's */
+ void ath11k_reg_init(struct ath11k *ar);
++void ath11k_reg_reset_info(struct cur_regulatory_info *reg_info);
+ void ath11k_reg_free(struct ath11k_base *ab);
+ void ath11k_regd_update_work(struct work_struct *work);
+ struct ieee80211_regdomain *
+ ath11k_reg_build_regd(struct ath11k_base *ab,
+- struct cur_regulatory_info *reg_info, bool intersect);
++ struct cur_regulatory_info *reg_info, bool intersect,
++ enum wmi_vdev_type vdev_type,
++ enum ieee80211_ap_reg_power power_type);
+ int ath11k_regd_update(struct ath11k *ar);
+ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait);
++enum wmi_reg_6ghz_ap_type
++ath11k_reg_ap_pwr_convert(enum ieee80211_ap_reg_power power_type);
++int ath11k_reg_handle_chan_list(struct ath11k_base *ab,
++ struct cur_regulatory_info *reg_info,
++ enum ieee80211_ap_reg_power power_type);
++
+ #endif
+diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
+index 8a65fa04b48d9..442afda7ec885 100644
+--- a/drivers/net/wireless/ath/ath11k/wmi.c
++++ b/drivers/net/wireless/ath/ath11k/wmi.c
+@@ -4749,6 +4749,14 @@ static int ath11k_wmi_tlv_ext_soc_hal_reg_caps_parse(struct ath11k_base *soc,
+ soc->pdevs[0].pdev_id = 0;
+ }
+
++ if (!soc->reg_info_store) {
++ soc->reg_info_store = kcalloc(soc->num_radios,
++ sizeof(*soc->reg_info_store),
++ GFP_ATOMIC);
++ if (!soc->reg_info_store)
++ return -ENOMEM;
++ }
++
+ return 0;
+ }
+
+@@ -7060,32 +7068,15 @@ static void ath11k_wmi_htc_tx_complete(struct ath11k_base *ab,
+ wake_up(&wmi->tx_ce_desc_wq);
+ }
+
+-static bool ath11k_reg_is_world_alpha(char *alpha)
+-{
+- if (alpha[0] == '0' && alpha[1] == '0')
+- return true;
+-
+- if (alpha[0] == 'n' && alpha[1] == 'a')
+- return true;
+-
+- return false;
+-}
+-
+-static int ath11k_reg_chan_list_event(struct ath11k_base *ab,
+- struct sk_buff *skb,
++static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *skb,
+ enum wmi_reg_chan_list_cmd_type id)
+ {
+- struct cur_regulatory_info *reg_info = NULL;
+- struct ieee80211_regdomain *regd = NULL;
+- bool intersect = false;
+- int ret = 0, pdev_idx, i, j;
+- struct ath11k *ar;
++ struct cur_regulatory_info *reg_info;
++ int ret;
+
+ reg_info = kzalloc(sizeof(*reg_info), GFP_ATOMIC);
+- if (!reg_info) {
+- ret = -ENOMEM;
+- goto fallback;
+- }
++ if (!reg_info)
++ return -ENOMEM;
+
+ if (id == WMI_REG_CHAN_LIST_CC_ID)
+ ret = ath11k_pull_reg_chan_list_update_ev(ab, skb, reg_info);
+@@ -7093,118 +7084,22 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab,
+ ret = ath11k_pull_reg_chan_list_ext_update_ev(ab, skb, reg_info);
+
+ if (ret) {
+- ath11k_warn(ab, "failed to extract regulatory info from received event\n");
+- goto fallback;
+- }
+-
+- ath11k_dbg(ab, ATH11K_DBG_WMI, "event reg chan list id %d", id);
+-
+- if (reg_info->status_code != REG_SET_CC_STATUS_PASS) {
+- /* In case of failure to set the requested ctry,
+- * fw retains the current regd. We print a failure info
+- * and return from here.
+- */
+- ath11k_warn(ab, "Failed to set the requested Country regulatory setting\n");
+- goto mem_free;
+- }
+-
+- pdev_idx = reg_info->phy_id;
+-
+- /* Avoid default reg rule updates sent during FW recovery if
+- * it is already available
+- */
+- spin_lock(&ab->base_lock);
+- if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags) &&
+- ab->default_regd[pdev_idx]) {
+- spin_unlock(&ab->base_lock);
++ ath11k_warn(ab, "failed to extract regulatory info\n");
+ goto mem_free;
+ }
+- spin_unlock(&ab->base_lock);
+
+- if (pdev_idx >= ab->num_radios) {
+- /* Process the event for phy0 only if single_pdev_only
+- * is true. If pdev_idx is valid but not 0, discard the
+- * event. Otherwise, it goes to fallback.
+- */
+- if (ab->hw_params.single_pdev_only &&
+- pdev_idx < ab->hw_params.num_rxmda_per_pdev)
+- goto mem_free;
+- else
+- goto fallback;
+- }
+-
+- /* Avoid multiple overwrites to default regd, during core
+- * stop-start after mac registration.
+- */
+- if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
+- !memcmp((char *)ab->default_regd[pdev_idx]->alpha2,
+- (char *)reg_info->alpha2, 2))
++ ret = ath11k_reg_handle_chan_list(ab, reg_info, IEEE80211_REG_UNSET_AP);
++ if (ret) {
++ ath11k_warn(ab, "failed to process regulatory info %d\n", ret);
+ goto mem_free;
+-
+- /* Intersect new rules with default regd if a new country setting was
+- * requested, i.e a default regd was already set during initialization
+- * and the regd coming from this event has a valid country info.
+- */
+- if (ab->default_regd[pdev_idx] &&
+- !ath11k_reg_is_world_alpha((char *)
+- ab->default_regd[pdev_idx]->alpha2) &&
+- !ath11k_reg_is_world_alpha((char *)reg_info->alpha2))
+- intersect = true;
+-
+- regd = ath11k_reg_build_regd(ab, reg_info, intersect);
+- if (!regd) {
+- ath11k_warn(ab, "failed to build regd from reg_info\n");
+- goto fallback;
+- }
+-
+- spin_lock(&ab->base_lock);
+- if (ab->default_regd[pdev_idx]) {
+- /* The initial rules from FW after WMI Init is to build
+- * the default regd. From then on, any rules updated for
+- * the pdev could be due to user reg changes.
+- * Free previously built regd before assigning the newly
+- * generated regd to ar. NULL pointer handling will be
+- * taken care by kfree itself.
+- */
+- ar = ab->pdevs[pdev_idx].ar;
+- kfree(ab->new_regd[pdev_idx]);
+- ab->new_regd[pdev_idx] = regd;
+- queue_work(ab->workqueue, &ar->regd_update_work);
+- } else {
+- /* This regd would be applied during mac registration and is
+- * held constant throughout for regd intersection purpose
+- */
+- ab->default_regd[pdev_idx] = regd;
+ }
+- ab->dfs_region = reg_info->dfs_region;
+- spin_unlock(&ab->base_lock);
+
+- goto mem_free;
++ kfree(reg_info);
++ return 0;
+
+-fallback:
+- /* Fallback to older reg (by sending previous country setting
+- * again if fw has succeeded and we failed to process here.
+- * The Regdomain should be uniform across driver and fw. Since the
+- * FW has processed the command and sent a success status, we expect
+- * this function to succeed as well. If it doesn't, CTRY needs to be
+- * reverted at the fw and the old SCAN_CHAN_LIST cmd needs to be sent.
+- */
+- /* TODO: This is rare, but still should also be handled */
+- WARN_ON(1);
+ mem_free:
+- if (reg_info) {
+- kfree(reg_info->reg_rules_2ghz_ptr);
+- kfree(reg_info->reg_rules_5ghz_ptr);
+- if (reg_info->is_ext_reg_event) {
+- for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++)
+- kfree(reg_info->reg_rules_6ghz_ap_ptr[i]);
+-
+- for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++)
+- for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++)
+- kfree(reg_info->reg_rules_6ghz_client_ptr[j][i]);
+- }
+- kfree(reg_info);
+- }
++ ath11k_reg_reset_info(reg_info);
++ kfree(reg_info);
+ return ret;
+ }
+
+diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
+index ff0a9a92beeb0..cd2098d78e861 100644
+--- a/drivers/net/wireless/ath/ath11k/wmi.h
++++ b/drivers/net/wireless/ath/ath11k/wmi.h
+@@ -4951,6 +4951,7 @@ struct ath11k_targ_cap {
+ };
+
+ enum wmi_vdev_type {
++ WMI_VDEV_TYPE_UNSPEC = 0,
+ WMI_VDEV_TYPE_AP = 1,
+ WMI_VDEV_TYPE_STA = 2,
+ WMI_VDEV_TYPE_IBSS = 3,
+diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
+index 8458dc292821a..01fb9b2ae4314 100644
+--- a/drivers/net/wireless/ath/ath12k/core.h
++++ b/drivers/net/wireless/ath/ath12k/core.h
+@@ -420,7 +420,7 @@ struct ath12k_sta {
+ };
+
+ #define ATH12K_MIN_5G_FREQ 4150
+-#define ATH12K_MIN_6G_FREQ 5945
++#define ATH12K_MIN_6G_FREQ 5925
+ #define ATH12K_MAX_6G_FREQ 7115
+ #define ATH12K_NUM_CHANS 100
+ #define ATH12K_MAX_5G_CHAN 173
+diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c
+index a489369d80687..1bdab8604db94 100644
+--- a/drivers/net/wireless/ath/ath12k/hal.c
++++ b/drivers/net/wireless/ath/ath12k/hal.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: BSD-3-Clause-Clear
+ /*
+ * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
++ * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+ #include <linux/dma-mapping.h>
+ #include "hal_tx.h"
+@@ -449,8 +449,8 @@ static u8 *ath12k_hw_qcn9274_rx_desc_mpdu_start_addr2(struct hal_rx_desc *desc)
+
+ static bool ath12k_hw_qcn9274_rx_desc_is_da_mcbc(struct hal_rx_desc *desc)
+ {
+- return __le16_to_cpu(desc->u.qcn9274.msdu_end.info5) &
+- RX_MSDU_END_INFO5_DA_IS_MCBC;
++ return __le32_to_cpu(desc->u.qcn9274.mpdu_start.info6) &
++ RX_MPDU_START_INFO6_MCAST_BCAST;
+ }
+
+ static void ath12k_hw_qcn9274_rx_desc_get_dot11_hdr(struct hal_rx_desc *desc,
+diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
+index 88cec54c6c2e6..b965fc46ad89a 100644
+--- a/drivers/net/wireless/ath/ath12k/mac.c
++++ b/drivers/net/wireless/ath/ath12k/mac.c
+@@ -5269,7 +5269,7 @@ ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif)
+ do {
+ if (ab->free_vdev_stats_id_map & (1LL << vdev_stats_id)) {
+ vdev_stats_id++;
+- if (vdev_stats_id <= ATH12K_INVAL_VDEV_STATS_ID) {
++ if (vdev_stats_id >= ATH12K_MAX_VDEV_STATS_ID) {
+ vdev_stats_id = ATH12K_INVAL_VDEV_STATS_ID;
+ break;
+ }
+@@ -7198,7 +7198,7 @@ static int ath12k_mac_setup_channels_rates(struct ath12k *ar,
+ }
+
+ if (supported_bands & WMI_HOST_WLAN_5G_CAP) {
+- if (reg_cap->high_5ghz_chan >= ATH12K_MAX_6G_FREQ) {
++ if (reg_cap->high_5ghz_chan >= ATH12K_MIN_6G_FREQ) {
+ channels = kmemdup(ath12k_6ghz_channels,
+ sizeof(ath12k_6ghz_channels), GFP_KERNEL);
+ if (!channels) {
+diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c
+index f924bc13ccff5..29542c46b0941 100644
+--- a/drivers/net/wireless/ath/ath12k/reg.c
++++ b/drivers/net/wireless/ath/ath12k/reg.c
+@@ -103,7 +103,7 @@ int ath12k_reg_update_chan_list(struct ath12k *ar)
+
+ bands = hw->wiphy->bands;
+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
+- if (!bands[band])
++ if (!(ar->mac.sbands[band].channels && bands[band]))
+ continue;
+
+ for (i = 0; i < bands[band]->n_channels; i++) {
+@@ -129,7 +129,7 @@ int ath12k_reg_update_chan_list(struct ath12k *ar)
+ ch = arg->channel;
+
+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
+- if (!bands[band])
++ if (!(ar->mac.sbands[band].channels && bands[band]))
+ continue;
+
+ for (i = 0; i < bands[band]->n_channels; i++) {
+diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
+index 237f4ec2cffd7..6c33e898b3000 100644
+--- a/drivers/net/wireless/ath/ath9k/htc.h
++++ b/drivers/net/wireless/ath/ath9k/htc.h
+@@ -306,7 +306,6 @@ struct ath9k_htc_tx {
+ DECLARE_BITMAP(tx_slot, MAX_TX_BUF_NUM);
+ struct timer_list cleanup_timer;
+ spinlock_t tx_lock;
+- bool initialized;
+ };
+
+ struct ath9k_htc_tx_ctl {
+@@ -515,6 +514,7 @@ struct ath9k_htc_priv {
+ unsigned long ps_usecount;
+ bool ps_enabled;
+ bool ps_idle;
++ bool initialized;
+
+ #ifdef CONFIG_MAC80211_LEDS
+ enum led_brightness brightness;
+diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+index 0aa5bdeb44a1b..3633f9eb2c559 100644
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+@@ -966,6 +966,10 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
+
+ htc_handle->drv_priv = priv;
+
++ /* Allow ath9k_wmi_event_tasklet() to operate. */
++ smp_wmb();
++ priv->initialized = true;
++
+ return 0;
+
+ err_init:
+diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+index efcaeccb055aa..ce9c04e418b8d 100644
+--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
++++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+@@ -815,10 +815,6 @@ int ath9k_tx_init(struct ath9k_htc_priv *priv)
+ skb_queue_head_init(&priv->tx.data_vo_queue);
+ skb_queue_head_init(&priv->tx.tx_failed);
+
+- /* Allow ath9k_wmi_event_tasklet(WMI_TXSTATUS_EVENTID) to operate. */
+- smp_wmb();
+- priv->tx.initialized = true;
+-
+ return 0;
+ }
+
+diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
+index 1476b42b52a91..805ad31edba2b 100644
+--- a/drivers/net/wireless/ath/ath9k/wmi.c
++++ b/drivers/net/wireless/ath/ath9k/wmi.c
+@@ -155,6 +155,12 @@ void ath9k_wmi_event_tasklet(struct tasklet_struct *t)
+ }
+ spin_unlock_irqrestore(&wmi->wmi_lock, flags);
+
++ /* Check if ath9k_htc_probe_device() completed. */
++ if (!data_race(priv->initialized)) {
++ kfree_skb(skb);
++ continue;
++ }
++
+ hdr = (struct wmi_cmd_hdr *) skb->data;
+ cmd_id = be16_to_cpu(hdr->command_id);
+ wmi_event = skb_pull(skb, sizeof(struct wmi_cmd_hdr));
+@@ -169,10 +175,6 @@ void ath9k_wmi_event_tasklet(struct tasklet_struct *t)
+ &wmi->drv_priv->fatal_work);
+ break;
+ case WMI_TXSTATUS_EVENTID:
+- /* Check if ath9k_tx_init() completed. */
+- if (!data_race(priv->tx.initialized))
+- break;
+-
+ spin_lock_bh(&priv->tx.tx_lock);
+ if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
+ spin_unlock_bh(&priv->tx.tx_lock);
+diff --git a/drivers/net/wireless/broadcom/b43/b43.h b/drivers/net/wireless/broadcom/b43/b43.h
+index 67b4bac048e58..c0d8fc0b22fb2 100644
+--- a/drivers/net/wireless/broadcom/b43/b43.h
++++ b/drivers/net/wireless/broadcom/b43/b43.h
+@@ -1082,6 +1082,22 @@ static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
+ return dev->__using_pio_transfers;
+ }
+
++static inline void b43_wake_queue(struct b43_wldev *dev, int queue_prio)
++{
++ if (dev->qos_enabled)
++ ieee80211_wake_queue(dev->wl->hw, queue_prio);
++ else
++ ieee80211_wake_queue(dev->wl->hw, 0);
++}
++
++static inline void b43_stop_queue(struct b43_wldev *dev, int queue_prio)
++{
++ if (dev->qos_enabled)
++ ieee80211_stop_queue(dev->wl->hw, queue_prio);
++ else
++ ieee80211_stop_queue(dev->wl->hw, 0);
++}
++
+ /* Message printing */
+ __printf(2, 3) void b43info(struct b43_wl *wl, const char *fmt, ...);
+ __printf(2, 3) void b43err(struct b43_wl *wl, const char *fmt, ...);
+diff --git a/drivers/net/wireless/broadcom/b43/dma.c b/drivers/net/wireless/broadcom/b43/dma.c
+index 760d1a28edc6c..6ac7dcebfff9d 100644
+--- a/drivers/net/wireless/broadcom/b43/dma.c
++++ b/drivers/net/wireless/broadcom/b43/dma.c
+@@ -1399,7 +1399,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
+ should_inject_overflow(ring)) {
+ /* This TX ring is full. */
+ unsigned int skb_mapping = skb_get_queue_mapping(skb);
+- ieee80211_stop_queue(dev->wl->hw, skb_mapping);
++ b43_stop_queue(dev, skb_mapping);
+ dev->wl->tx_queue_stopped[skb_mapping] = true;
+ ring->stopped = true;
+ if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
+@@ -1570,7 +1570,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
+ } else {
+ /* If the driver queue is running wake the corresponding
+ * mac80211 queue. */
+- ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
++ b43_wake_queue(dev, ring->queue_prio);
+ if (b43_debug(dev, B43_DBG_DMAVERBOSE)) {
+ b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index);
+ }
+diff --git a/drivers/net/wireless/broadcom/b43/main.c b/drivers/net/wireless/broadcom/b43/main.c
+index 92ca0b2ca286d..effb6c23f8257 100644
+--- a/drivers/net/wireless/broadcom/b43/main.c
++++ b/drivers/net/wireless/broadcom/b43/main.c
+@@ -2587,7 +2587,8 @@ static void b43_request_firmware(struct work_struct *work)
+
+ start_ieee80211:
+ wl->hw->queues = B43_QOS_QUEUE_NUM;
+- if (!modparam_qos || dev->fw.opensource)
++ if (!modparam_qos || dev->fw.opensource ||
++ dev->dev->chip_id == BCMA_CHIP_ID_BCM4331)
+ wl->hw->queues = 1;
+
+ err = ieee80211_register_hw(wl->hw);
+@@ -3603,7 +3604,7 @@ static void b43_tx_work(struct work_struct *work)
+ err = b43_dma_tx(dev, skb);
+ if (err == -ENOSPC) {
+ wl->tx_queue_stopped[queue_num] = true;
+- ieee80211_stop_queue(wl->hw, queue_num);
++ b43_stop_queue(dev, queue_num);
+ skb_queue_head(&wl->tx_queue[queue_num], skb);
+ break;
+ }
+@@ -3627,6 +3628,7 @@ static void b43_op_tx(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
+ {
+ struct b43_wl *wl = hw_to_b43_wl(hw);
++ u16 skb_queue_mapping;
+
+ if (unlikely(skb->len < 2 + 2 + 6)) {
+ /* Too short, this can't be a valid frame. */
+@@ -3635,12 +3637,12 @@ static void b43_op_tx(struct ieee80211_hw *hw,
+ }
+ B43_WARN_ON(skb_shinfo(skb)->nr_frags);
+
+- skb_queue_tail(&wl->tx_queue[skb->queue_mapping], skb);
+- if (!wl->tx_queue_stopped[skb->queue_mapping]) {
++ skb_queue_mapping = skb_get_queue_mapping(skb);
++ skb_queue_tail(&wl->tx_queue[skb_queue_mapping], skb);
++ if (!wl->tx_queue_stopped[skb_queue_mapping])
+ ieee80211_queue_work(wl->hw, &wl->tx_work);
+- } else {
+- ieee80211_stop_queue(wl->hw, skb->queue_mapping);
+- }
++ else
++ b43_stop_queue(wl->current_dev, skb_queue_mapping);
+ }
+
+ static void b43_qos_params_upload(struct b43_wldev *dev,
+diff --git a/drivers/net/wireless/broadcom/b43/pio.c b/drivers/net/wireless/broadcom/b43/pio.c
+index 0cf70fdb60a6a..e41f2f5b4c266 100644
+--- a/drivers/net/wireless/broadcom/b43/pio.c
++++ b/drivers/net/wireless/broadcom/b43/pio.c
+@@ -525,7 +525,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
+ if (total_len > (q->buffer_size - q->buffer_used)) {
+ /* Not enough memory on the queue. */
+ err = -EBUSY;
+- ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
++ b43_stop_queue(dev, skb_get_queue_mapping(skb));
+ q->stopped = true;
+ goto out;
+ }
+@@ -552,7 +552,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
+ if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
+ (q->free_packet_slots == 0)) {
+ /* The queue is full. */
+- ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb));
++ b43_stop_queue(dev, skb_get_queue_mapping(skb));
+ q->stopped = true;
+ }
+
+@@ -587,7 +587,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
+ list_add(&pack->list, &q->packets_list);
+
+ if (q->stopped) {
+- ieee80211_wake_queue(dev->wl->hw, q->queue_prio);
++ b43_wake_queue(dev, q->queue_prio);
+ q->stopped = false;
+ }
+ }
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+index 28d6a30cc0106..1a5d7494f5e80 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -4322,6 +4322,9 @@ brcmf_pmksa_v3_op(struct brcmf_if *ifp, struct cfg80211_pmksa *pmksa,
+ int ret;
+
+ pmk_op = kzalloc(sizeof(*pmk_op), GFP_KERNEL);
++ if (!pmk_op)
++ return -ENOMEM;
++
+ pmk_op->version = cpu_to_le16(BRCMF_PMKSA_VER_3);
+
+ if (!pmksa) {
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_cmn.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_cmn.c
+index ccc621b8ed9f2..4a1fe982a948e 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_cmn.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_cmn.c
+@@ -383,8 +383,9 @@ struct shared_phy *wlc_phy_shared_attach(struct shared_phy_params *shp)
+ return sh;
+ }
+
+-static void wlc_phy_timercb_phycal(struct brcms_phy *pi)
++static void wlc_phy_timercb_phycal(void *ptr)
+ {
++ struct brcms_phy *pi = ptr;
+ uint delay = 5;
+
+ if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.c
+index a0de5db0cd646..b723817915365 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.c
+@@ -57,12 +57,11 @@ void wlc_phy_shim_detach(struct phy_shim_info *physhim)
+ }
+
+ struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
+- void (*fn)(struct brcms_phy *pi),
++ void (*fn)(void *pi),
+ void *arg, const char *name)
+ {
+ return (struct wlapi_timer *)
+- brcms_init_timer(physhim->wl, (void (*)(void *))fn,
+- arg, name);
++ brcms_init_timer(physhim->wl, fn, arg, name);
+ }
+
+ void wlapi_free_timer(struct wlapi_timer *t)
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.h b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.h
+index dd8774717adee..27d0934e600ed 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy_shim.h
+@@ -131,7 +131,7 @@ void wlc_phy_shim_detach(struct phy_shim_info *physhim);
+
+ /* PHY to WL utility functions */
+ struct wlapi_timer *wlapi_init_timer(struct phy_shim_info *physhim,
+- void (*fn)(struct brcms_phy *pi),
++ void (*fn)(void *pi),
+ void *arg, const char *name);
+ void wlapi_free_timer(struct wlapi_timer *t);
+ void wlapi_add_timer(struct wlapi_timer *t, uint ms, int periodic);
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+index dcc4810cb3247..e161b44539069 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c
+@@ -767,7 +767,7 @@ int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
+ * from index 1, so the maximum value allowed here is
+ * ACPI_SAR_PROFILES_NUM - 1.
+ */
+- if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) {
++ if (n_profiles >= ACPI_SAR_PROFILE_NUM) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+@@ -1296,7 +1296,6 @@ void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
+ if (IS_ERR(data))
+ return;
+
+- /* try to read wtas table revision 1 or revision 0*/
+ wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
+ ACPI_WPFC_WIFI_DATA_SIZE,
+ &tbl_rev);
+@@ -1306,13 +1305,14 @@ void iwl_acpi_get_phy_filters(struct iwl_fw_runtime *fwrt,
+ if (tbl_rev != 0)
+ goto out_free;
+
+- BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) != ACPI_WPFC_WIFI_DATA_SIZE);
++ BUILD_BUG_ON(ARRAY_SIZE(filters->filter_cfg_chains) !=
++ ACPI_WPFC_WIFI_DATA_SIZE - 1);
+
+ for (i = 0; i < ARRAY_SIZE(filters->filter_cfg_chains); i++) {
+- if (wifi_pkg->package.elements[i].type != ACPI_TYPE_INTEGER)
+- return;
++ if (wifi_pkg->package.elements[i + 1].type != ACPI_TYPE_INTEGER)
++ goto out_free;
+ tmp.filter_cfg_chains[i] =
+- cpu_to_le32(wifi_pkg->package.elements[i].integer.value);
++ cpu_to_le32(wifi_pkg->package.elements[i + 1].integer.value);
+ }
+
+ IWL_DEBUG_RADIO(fwrt, "Loaded WPFC filter config from ACPI\n");
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
+index e9277f6f35821..39106ccb4b9b6 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
++++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h
+@@ -56,7 +56,7 @@
+ #define ACPI_EWRD_WIFI_DATA_SIZE_REV2 ((ACPI_SAR_PROFILE_NUM - 1) * \
+ ACPI_SAR_NUM_CHAINS_REV2 * \
+ ACPI_SAR_NUM_SUB_BANDS_REV2 + 3)
+-#define ACPI_WPFC_WIFI_DATA_SIZE 4 /* 4 filter config words */
++#define ACPI_WPFC_WIFI_DATA_SIZE 5 /* domain and 4 filter config words */
+
+ /* revision 0 and 1 are identical, except for the semantics in the FW */
+ #define ACPI_GEO_NUM_BANDS_REV0 2
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
+index 650e4bde9c17b..56ee0ceed78ab 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
+@@ -255,21 +255,27 @@ static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len)
+ struct pnvm_sku_package *package;
+ u8 *image = NULL;
+
+- /* First attempt to get the PNVM from BIOS */
+- package = iwl_uefi_get_pnvm(trans_p, len);
+- if (!IS_ERR_OR_NULL(package)) {
+- if (*len >= sizeof(*package)) {
+- /* we need only the data */
+- *len -= sizeof(*package);
+- image = kmemdup(package->data, *len, GFP_KERNEL);
++ /* Get PNVM from BIOS for non-Intel SKU */
++ if (trans_p->sku_id[2]) {
++ package = iwl_uefi_get_pnvm(trans_p, len);
++ if (!IS_ERR_OR_NULL(package)) {
++ if (*len >= sizeof(*package)) {
++ /* we need only the data */
++ *len -= sizeof(*package);
++ image = kmemdup(package->data,
++ *len, GFP_KERNEL);
++ }
++ /*
++ * free package regardless of whether kmemdup
++ * succeeded
++ */
++ kfree(package);
++ if (image)
++ return image;
+ }
+- /* free package regardless of whether kmemdup succeeded */
+- kfree(package);
+- if (image)
+- return image;
+ }
+
+- /* If it's not available, try from the filesystem */
++ /* If it's not available, or for Intel SKU, try from the filesystem */
+ if (iwl_pnvm_get_from_fs(trans_p, &image, len))
+ return NULL;
+ return image;
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+index 357727774db90..baabb8e321f8d 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
++++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+@@ -173,9 +173,9 @@ struct iwl_fw_runtime {
+ struct iwl_sar_offset_mapping_cmd sgom_table;
+ bool sgom_enabled;
+ u8 reduced_power_flags;
+- bool uats_enabled;
+ struct iwl_uats_table_cmd uats_table;
+ #endif
++ bool uats_enabled;
+ };
+
+ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+index 72075720969c0..3442dfab50b53 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c
+@@ -103,6 +103,12 @@ static int iwl_dbg_tlv_alloc_debug_info(struct iwl_trans *trans,
+ if (le32_to_cpu(tlv->length) != sizeof(*debug_info))
+ return -EINVAL;
+
++ /* we use this as a string, ensure input was NUL terminated */
++ if (strnlen(debug_info->debug_cfg_name,
++ sizeof(debug_info->debug_cfg_name)) ==
++ sizeof(debug_info->debug_cfg_name))
++ return -EINVAL;
++
+ IWL_DEBUG_FW(trans, "WRT: Loading debug cfg: %s\n",
+ debug_info->debug_cfg_name);
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+index 2f6774ec37b22..501a8cc2134cf 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c
+@@ -2097,7 +2097,7 @@ struct iwl_nvm_data *iwl_get_nvm(struct iwl_trans *trans,
+ !!(mac_flags & NVM_MAC_SKU_FLAGS_BAND_5_2_ENABLED);
+ nvm->sku_cap_mimo_disabled =
+ !!(mac_flags & NVM_MAC_SKU_FLAGS_MIMO_DISABLED);
+- if (CSR_HW_RFID_TYPE(trans->hw_rf_id) == IWL_CFG_RF_TYPE_FM)
++ if (CSR_HW_RFID_TYPE(trans->hw_rf_id) >= IWL_CFG_RF_TYPE_FM)
+ nvm->sku_cap_11be_enable = true;
+
+ /* Initialize PHY sku data */
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+index 05b64176859e8..2a08369238f23 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+@@ -461,12 +461,10 @@ static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm,
+ struct wowlan_key_rsc_v5_data data = {};
+ int i;
+
+- data.rsc = kmalloc(sizeof(*data.rsc), GFP_KERNEL);
++ data.rsc = kzalloc(sizeof(*data.rsc), GFP_KERNEL);
+ if (!data.rsc)
+ return -ENOMEM;
+
+- memset(data.rsc, 0xff, sizeof(*data.rsc));
+-
+ for (i = 0; i < ARRAY_SIZE(data.rsc->mcast_key_id_map); i++)
+ data.rsc->mcast_key_id_map[i] =
+ IWL_MCAST_KEY_MAP_INVALID;
+@@ -2200,7 +2198,10 @@ static void iwl_mvm_convert_gtk_v3(struct iwl_wowlan_status_data *status,
+ static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,
+ struct iwl_wowlan_igtk_status *data)
+ {
++ int i;
++
+ BUILD_BUG_ON(sizeof(status->igtk.key) < sizeof(data->key));
++ BUILD_BUG_ON(sizeof(status->igtk.ipn) != sizeof(data->ipn));
+
+ if (!data->key_len)
+ return;
+@@ -2212,7 +2213,10 @@ static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,
+ + WOWLAN_IGTK_MIN_INDEX;
+
+ memcpy(status->igtk.key, data->key, sizeof(data->key));
+- memcpy(status->igtk.ipn, data->ipn, sizeof(data->ipn));
++
++ /* mac80211 expects big endian for memcmp() to work, convert */
++ for (i = 0; i < sizeof(data->ipn); i++)
++ status->igtk.ipn[i] = data->ipn[sizeof(data->ipn) - i - 1];
+ }
+
+ static void iwl_mvm_convert_bigtk(struct iwl_wowlan_status_data *status,
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+index 53e26c3c3a9af..f60d4258e1b95 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+@@ -3698,6 +3698,19 @@ iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm,
+ if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
+ mvmvif->ap_sta = sta;
+
++ /*
++ * Initialize the rates here already - this really tells
++ * the firmware only what the supported legacy rates are
++ * (may be) since it's initialized already from what the
++ * AP advertised in the beacon/probe response. This will
++ * allow the firmware to send auth/assoc frames with one
++ * of the supported rates already, rather than having to
++ * use a mandatory rate.
++ * If we're the AP, we'll just assume mandatory rates at
++ * this point, but we know nothing about the STA anyway.
++ */
++ iwl_mvm_rs_rate_init_all_links(mvm, vif, sta);
++
+ return 0;
+ }
+
+@@ -3796,13 +3809,17 @@ iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm,
+
+ mvm_sta->authorized = true;
+
+- iwl_mvm_rs_rate_init_all_links(mvm, vif, sta);
+-
+ /* MFP is set by default before the station is authorized.
+ * Clear it here in case it's not used.
+ */
+- if (!sta->mfp)
+- return callbacks->update_sta(mvm, vif, sta);
++ if (!sta->mfp) {
++ int ret = callbacks->update_sta(mvm, vif, sta);
++
++ if (ret)
++ return ret;
++ }
++
++ iwl_mvm_rs_rate_init_all_links(mvm, vif, sta);
+
+ return 0;
+ }
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+index ea3e9e9c6e26c..fe4b39b19a612 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ /*
+- * Copyright (C) 2022 - 2023 Intel Corporation
++ * Copyright (C) 2022 - 2024 Intel Corporation
+ */
+ #include <linux/kernel.h>
+ #include <net/mac80211.h>
+@@ -62,11 +62,13 @@ u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
+ struct ieee80211_key_conf *keyconf)
+ {
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
++ bool pairwise = keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE;
++ bool igtk = keyconf->keyidx == 4 || keyconf->keyidx == 5;
+ u32 flags = 0;
+
+ lockdep_assert_held(&mvm->mutex);
+
+- if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
++ if (!pairwise)
+ flags |= IWL_SEC_KEY_FLAG_MCAST_KEY;
+
+ switch (keyconf->cipher) {
+@@ -96,12 +98,14 @@ u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm,
+ if (!sta && vif->type == NL80211_IFTYPE_STATION)
+ sta = mvmvif->ap_sta;
+
+- /* Set the MFP flag also for an AP interface where the key is an IGTK
+- * key as in such a case the station would always be NULL
++ /*
++ * If we are installing an iGTK (in AP or STA mode), we need to tell
++ * the firmware this key will en/decrypt MGMT frames.
++ * Same goes if we are installing a pairwise key for an MFP station.
++ * In case we're installing a groupwise key (which is not an iGTK),
++ * then, we will not use this key for MGMT frames.
+ */
+- if ((!IS_ERR_OR_NULL(sta) && sta->mfp) ||
+- (vif->type == NL80211_IFTYPE_AP &&
+- (keyconf->keyidx == 4 || keyconf->keyidx == 5)))
++ if ((!IS_ERR_OR_NULL(sta) && sta->mfp && pairwise) || igtk)
+ flags |= IWL_SEC_KEY_FLAG_MFP;
+
+ return flags;
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
+index f313a8d771e42..ad78c69cc6cb7 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c
+@@ -167,7 +167,7 @@ static int iwl_mvm_mld_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
+ iwl_mvm_mld_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
+
+ cmd.filter_flags = cpu_to_le32(MAC_CFG_FILTER_PROMISC |
+- MAC_FILTER_IN_CONTROL_AND_MGMT |
++ MAC_CFG_FILTER_ACCEPT_CONTROL_AND_MGMT |
+ MAC_CFG_FILTER_ACCEPT_BEACON |
+ MAC_CFG_FILTER_ACCEPT_PROBE_REQ |
+ MAC_CFG_FILTER_ACCEPT_GRP);
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+index 81dbef6947f55..fe0fa9ff533d7 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+@@ -121,7 +121,7 @@ struct iwl_mvm_time_event_data {
+ * if the te is in the time event list or not (when id == TE_MAX)
+ */
+ u32 id;
+- u8 link_id;
++ s8 link_id;
+ };
+
+ /* Power management */
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+index af15d470c69bd..7bf2a5947e5e9 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+@@ -282,6 +282,7 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
+ u32 status,
+ struct ieee80211_rx_status *stats)
+ {
++ struct wireless_dev *wdev;
+ struct iwl_mvm_sta *mvmsta;
+ struct iwl_mvm_vif *mvmvif;
+ u8 keyid;
+@@ -303,9 +304,15 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
+ if (!ieee80211_is_beacon(hdr->frame_control))
+ return 0;
+
++ if (!sta)
++ return -1;
++
++ mvmsta = iwl_mvm_sta_from_mac80211(sta);
++ mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
++
+ /* key mismatch - will also report !MIC_OK but we shouldn't count it */
+ if (!(status & IWL_RX_MPDU_STATUS_KEY_VALID))
+- return -1;
++ goto report;
+
+ /* good cases */
+ if (likely(status & IWL_RX_MPDU_STATUS_MIC_OK &&
+@@ -314,13 +321,6 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
+ return 0;
+ }
+
+- if (!sta)
+- return -1;
+-
+- mvmsta = iwl_mvm_sta_from_mac80211(sta);
+-
+- mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
+-
+ /*
+ * both keys will have the same cipher and MIC length, use
+ * whichever one is available
+@@ -329,11 +329,11 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
+ if (!key) {
+ key = rcu_dereference(mvmvif->bcn_prot.keys[1]);
+ if (!key)
+- return -1;
++ goto report;
+ }
+
+ if (len < key->icv_len + IEEE80211_GMAC_PN_LEN + 2)
+- return -1;
++ goto report;
+
+ /* get the real key ID */
+ keyid = frame[len - key->icv_len - IEEE80211_GMAC_PN_LEN - 2];
+@@ -347,7 +347,7 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
+ return -1;
+ key = rcu_dereference(mvmvif->bcn_prot.keys[keyid - 6]);
+ if (!key)
+- return -1;
++ goto report;
+ }
+
+ /* Report status to mac80211 */
+@@ -355,6 +355,10 @@ static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta,
+ ieee80211_key_mic_failure(key);
+ else if (status & IWL_RX_MPDU_STATUS_REPLAY_ERROR)
+ ieee80211_key_replay(key);
++report:
++ wdev = ieee80211_vif_to_wdev(mvmsta->vif);
++ if (wdev->netdev)
++ cfg80211_rx_unprot_mlme_mgmt(wdev->netdev, (void *)hdr, len);
+
+ return -1;
+ }
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+index 2e653a417d626..da00ef6e4fbcf 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+@@ -692,7 +692,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
+ /* Determine whether mac or link id should be used, and validate the link id */
+ static int iwl_mvm_get_session_prot_id(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+- u32 link_id)
++ s8 link_id)
+ {
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ int ver = iwl_fw_lookup_cmd_ver(mvm->fw,
+@@ -706,8 +706,7 @@ static int iwl_mvm_get_session_prot_id(struct iwl_mvm *mvm,
+ "Invalid link ID for session protection: %u\n", link_id))
+ return -EINVAL;
+
+- if (WARN(ieee80211_vif_is_mld(vif) &&
+- !(vif->active_links & BIT(link_id)),
++ if (WARN(!mvmvif->link[link_id]->active,
+ "Session Protection on an inactive link: %u\n", link_id))
+ return -EINVAL;
+
+@@ -716,7 +715,7 @@ static int iwl_mvm_get_session_prot_id(struct iwl_mvm *mvm,
+
+ static void iwl_mvm_cancel_session_protection(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+- u32 id, u32 link_id)
++ u32 id, s8 link_id)
+ {
+ int mac_link_id = iwl_mvm_get_session_prot_id(mvm, vif, link_id);
+ struct iwl_mvm_session_prot_cmd cmd = {
+@@ -745,7 +744,7 @@ static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif = te_data->vif;
+ struct iwl_mvm_vif *mvmvif;
+ enum nl80211_iftype iftype;
+- unsigned int link_id;
++ s8 link_id;
+
+ if (!vif)
+ return false;
+@@ -1297,7 +1296,7 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
+ struct iwl_mvm_time_event_data *te_data = &mvmvif->time_event_data;
+ const u16 notif[] = { WIDE_ID(MAC_CONF_GROUP, SESSION_PROTECTION_NOTIF) };
+ struct iwl_notification_wait wait_notif;
+- int mac_link_id = iwl_mvm_get_session_prot_id(mvm, vif, link_id);
++ int mac_link_id = iwl_mvm_get_session_prot_id(mvm, vif, (s8)link_id);
+ struct iwl_mvm_session_prot_cmd cmd = {
+ .id_and_color = cpu_to_le32(mac_link_id),
+ .action = cpu_to_le32(FW_CTXT_ACTION_ADD),
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+index 461f26d9214e4..930742e75c02a 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ /*
+- * Copyright (C) 2012-2014, 2018-2023 Intel Corporation
++ * Copyright (C) 2012-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016-2017 Intel Deutschland GmbH
+ */
+@@ -1636,12 +1636,18 @@ static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm,
+ * of the batch. This is why the SSN of the SCD is written at the end of the
+ * whole struct at a variable offset. This function knows how to cope with the
+ * variable offset and returns the SSN of the SCD.
++ *
++ * For 22000-series and lower, this is just 12 bits. For later, 16 bits.
+ */
+ static inline u32 iwl_mvm_get_scd_ssn(struct iwl_mvm *mvm,
+ struct iwl_mvm_tx_resp *tx_resp)
+ {
+- return le32_to_cpup((__le32 *)iwl_mvm_get_agg_status(mvm, tx_resp) +
+- tx_resp->frame_count) & 0xfff;
++ u32 val = le32_to_cpup((__le32 *)iwl_mvm_get_agg_status(mvm, tx_resp) +
++ tx_resp->frame_count);
++
++ if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)
++ return val & 0xFFFF;
++ return val & 0xFFF;
+ }
+
+ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
+diff --git a/drivers/net/wireless/marvell/libertas/cmd.c b/drivers/net/wireless/marvell/libertas/cmd.c
+index 104d2b6dc9af6..5a525da434c28 100644
+--- a/drivers/net/wireless/marvell/libertas/cmd.c
++++ b/drivers/net/wireless/marvell/libertas/cmd.c
+@@ -1132,7 +1132,7 @@ int lbs_allocate_cmd_buffer(struct lbs_private *priv)
+ if (!cmdarray[i].cmdbuf) {
+ lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
+ ret = -1;
+- goto done;
++ goto free_cmd_array;
+ }
+ }
+
+@@ -1140,8 +1140,17 @@ int lbs_allocate_cmd_buffer(struct lbs_private *priv)
+ init_waitqueue_head(&cmdarray[i].cmdwait_q);
+ lbs_cleanup_and_insert_cmd(priv, &cmdarray[i]);
+ }
+- ret = 0;
++ return 0;
+
++free_cmd_array:
++ for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
++ if (cmdarray[i].cmdbuf) {
++ kfree(cmdarray[i].cmdbuf);
++ cmdarray[i].cmdbuf = NULL;
++ }
++ }
++ kfree(priv->cmd_array);
++ priv->cmd_array = NULL;
+ done:
+ return ret;
+ }
+diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c
+index f9c9fec7c792a..d14a0f4c1b6d7 100644
+--- a/drivers/net/wireless/marvell/mwifiex/debugfs.c
++++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c
+@@ -970,9 +970,6 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv)
+ priv->dfs_dev_dir = debugfs_create_dir(priv->netdev->name,
+ mwifiex_dfs_dir);
+
+- if (!priv->dfs_dev_dir)
+- return;
+-
+ MWIFIEX_DFS_ADD_FILE(info);
+ MWIFIEX_DFS_ADD_FILE(debug);
+ MWIFIEX_DFS_ADD_FILE(getlog);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+index 3a20ba0d24928..ae19174b46ee5 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+@@ -66,7 +66,7 @@ int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,
+
+ if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||
+ (is_mt7921(dev) && addr == 0x900000) ||
+- (is_mt7925(dev) && addr == 0x900000) ||
++ (is_mt7925(dev) && (addr == 0x900000 || addr == 0xe0002800)) ||
+ (is_mt7996(dev) && addr == 0x900000) ||
+ (is_mt7992(dev) && addr == 0x900000))
+ cmd = MCU_CMD(PATCH_START_REQ);
+@@ -2101,7 +2101,7 @@ mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
+ int j, msg_len, num_ch;
+ struct sk_buff *skb;
+
+- num_ch = i == batch_size - 1 ? n_chan % batch_len : batch_len;
++ num_ch = i == batch_size - 1 ? n_chan - i * batch_len : batch_len;
+ msg_len = sizeof(tx_power_tlv) + num_ch * sizeof(sku_tlbv);
+ skb = mt76_mcu_msg_alloc(dev, NULL, msg_len);
+ if (!skb) {
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+index ae6d0179727df..657a4d1f856b2 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+@@ -808,6 +808,7 @@ enum {
+ STA_REC_MLD = 0x20,
+ STA_REC_EHT = 0x22,
+ STA_REC_PN_INFO = 0x26,
++ STA_REC_KEY_V3 = 0x27,
+ STA_REC_HDRT = 0x28,
+ STA_REC_HDR_TRANS = 0x2B,
+ STA_REC_MAX_NUM
+@@ -935,6 +936,9 @@ enum {
+ PHY_TYPE_INDEX_NUM
+ };
+
++#define HR_DSSS_ERP_BASIC_RATE GENMASK(3, 0)
++#define OFDM_BASIC_RATE (BIT(6) | BIT(8) | BIT(10))
++
+ #define PHY_TYPE_BIT_HR_DSSS BIT(PHY_TYPE_HR_DSSS_INDEX)
+ #define PHY_TYPE_BIT_ERP BIT(PHY_TYPE_ERP_INDEX)
+ #define PHY_TYPE_BIT_OFDM BIT(PHY_TYPE_OFDM_INDEX)
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+index f5582477c7e4c..8b4ce32a2cd12 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+@@ -1272,7 +1272,7 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
+ .mtcl_conf = mt792x_acpi_get_mtcl_conf(&dev->phy, alpha2),
+ };
+ int ret, valid_cnt = 0;
+- u16 buf_len = 0;
++ u32 buf_len = 0;
+ u8 *pos;
+
+ if (!clc)
+@@ -1283,7 +1283,7 @@ int __mt7921_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,
+ if (mt76_find_power_limits_node(&dev->mt76))
+ req.cap |= CLC_CAP_DTS_EN;
+
+- buf_len = le16_to_cpu(clc->len) - sizeof(*clc);
++ buf_len = le32_to_cpu(clc->len) - sizeof(*clc);
+ pos = clc->data;
+ while (buf_len > 16) {
+ struct mt7921_clc_rule *rule = (struct mt7921_clc_rule *)pos;
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+index dde26f3274783..82cf3ce90b52f 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+@@ -387,6 +387,7 @@ static void mt7921_pci_remove(struct pci_dev *pdev)
+ struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
+
+ mt7921e_unregister_device(dev);
++ set_bit(MT76_REMOVED, &mdev->phy.state);
+ devm_free_irq(&pdev->dev, pdev->irq, dev);
+ mt76_free_device(&dev->mt76);
+ pci_free_irq_vectors(pdev);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+index 125a1be3cb64c..6179798a8845a 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+@@ -359,6 +359,7 @@ mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+ mvif->sta.wcid.phy_idx = mvif->mt76.band_idx;
+ mvif->sta.wcid.hw_key_idx = -1;
+ mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
++ mvif->sta.vif = mvif;
+ mt76_wcid_init(&mvif->sta.wcid);
+
+ mt7925_mac_wtbl_update(dev, idx,
+@@ -526,7 +527,7 @@ static int mt7925_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ if (cmd == SET_KEY && !mvif->mt76.cipher) {
+ struct mt792x_phy *phy = mt792x_hw_phy(hw);
+
+- mvif->mt76.cipher = mt76_connac_mcu_get_cipher(key->cipher);
++ mvif->mt76.cipher = mt7925_mcu_get_cipher(key->cipher);
+ mt7925_mcu_add_bss_info(phy, mvif->mt76.ctx, vif, sta, true);
+ }
+
+@@ -710,7 +711,7 @@ static void mt7925_bss_info_changed(struct ieee80211_hw *hw,
+
+ if (slottime != phy->slottime) {
+ phy->slottime = slottime;
+- mt792x_mac_set_timeing(phy);
++ mt7925_mcu_set_timing(phy, vif);
+ }
+ }
+
+@@ -1273,6 +1274,25 @@ mt7925_channel_switch_beacon(struct ieee80211_hw *hw,
+ mt792x_mutex_release(dev);
+ }
+
++static int
++mt7925_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
++ unsigned int link_id, u16 queue,
++ const struct ieee80211_tx_queue_params *params)
++{
++ struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
++ static const u8 mq_to_aci[] = {
++ [IEEE80211_AC_VO] = 3,
++ [IEEE80211_AC_VI] = 2,
++ [IEEE80211_AC_BE] = 0,
++ [IEEE80211_AC_BK] = 1,
++ };
++
++ /* firmware uses access class index */
++ mvif->queue_params[mq_to_aci[queue]] = *params;
++
++ return 0;
++}
++
+ static int
+ mt7925_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *link_conf)
+@@ -1396,7 +1416,7 @@ const struct ieee80211_ops mt7925_ops = {
+ .add_interface = mt7925_add_interface,
+ .remove_interface = mt792x_remove_interface,
+ .config = mt7925_config,
+- .conf_tx = mt792x_conf_tx,
++ .conf_tx = mt7925_conf_tx,
+ .configure_filter = mt7925_configure_filter,
+ .bss_info_changed = mt7925_bss_info_changed,
+ .start_ap = mt7925_start_ap,
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+index c5fd7116929b7..e1dd89a7a79ca 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+@@ -814,6 +814,7 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+ {
++ struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
+ struct sta_rec_hdr_trans *hdr_trans;
+ struct mt76_wcid *wcid;
+ struct tlv *tlv;
+@@ -827,7 +828,11 @@ mt7925_mcu_sta_hdr_trans_tlv(struct sk_buff *skb,
+ else
+ hdr_trans->from_ds = true;
+
+- wcid = (struct mt76_wcid *)sta->drv_priv;
++ if (sta)
++ wcid = (struct mt76_wcid *)sta->drv_priv;
++ else
++ wcid = &mvif->sta.wcid;
++
+ if (!wcid)
+ return;
+
+@@ -895,7 +900,7 @@ int mt7925_mcu_set_tx(struct mt792x_dev *dev, struct ieee80211_vif *vif)
+
+ e = (struct edca *)tlv;
+ e->set = WMM_PARAM_SET;
+- e->queue = ac + mvif->mt76.wmm_idx * MT76_CONNAC_MAX_WMM_SETS;
++ e->queue = ac;
+ e->aifs = q->aifs;
+ e->txop = cpu_to_le16(q->txop);
+
+@@ -921,61 +926,67 @@ mt7925_mcu_sta_key_tlv(struct mt76_wcid *wcid,
+ struct ieee80211_key_conf *key,
+ enum set_key_cmd cmd)
+ {
++ struct mt792x_sta *msta = container_of(wcid, struct mt792x_sta, wcid);
+ struct sta_rec_sec_uni *sec;
++ struct mt792x_vif *mvif = msta->vif;
++ struct ieee80211_sta *sta;
++ struct ieee80211_vif *vif;
+ struct tlv *tlv;
+
+- tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec));
++ sta = msta == &mvif->sta ?
++ NULL :
++ container_of((void *)msta, struct ieee80211_sta, drv_priv);
++ vif = container_of((void *)mvif, struct ieee80211_vif, drv_priv);
++
++ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V3, sizeof(*sec));
+ sec = (struct sta_rec_sec_uni *)tlv;
+- sec->add = cmd;
++ sec->bss_idx = mvif->mt76.idx;
++ sec->is_authenticator = 0;
++ sec->mgmt_prot = 0;
++ sec->wlan_idx = (u8)wcid->idx;
++
++ if (sta) {
++ sec->tx_key = 1;
++ sec->key_type = 1;
++ memcpy(sec->peer_addr, sta->addr, ETH_ALEN);
++ } else {
++ memcpy(sec->peer_addr, vif->bss_conf.bssid, ETH_ALEN);
++ }
+
+ if (cmd == SET_KEY) {
+- struct sec_key_uni *sec_key;
+ u8 cipher;
+
+- cipher = mt76_connac_mcu_get_cipher(key->cipher);
+- if (cipher == MCU_CIPHER_NONE)
++ sec->add = 1;
++ cipher = mt7925_mcu_get_cipher(key->cipher);
++ if (cipher == CONNAC3_CIPHER_NONE)
+ return -EOPNOTSUPP;
+
+- sec_key = &sec->key[0];
+- sec_key->cipher_len = sizeof(*sec_key);
+-
+- if (cipher == MCU_CIPHER_BIP_CMAC_128) {
+- sec_key->wlan_idx = cpu_to_le16(wcid->idx);
+- sec_key->cipher_id = MCU_CIPHER_AES_CCMP;
+- sec_key->key_id = sta_key_conf->keyidx;
+- sec_key->key_len = 16;
+- memcpy(sec_key->key, sta_key_conf->key, 16);
+-
+- sec_key = &sec->key[1];
+- sec_key->wlan_idx = cpu_to_le16(wcid->idx);
+- sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128;
+- sec_key->cipher_len = sizeof(*sec_key);
+- sec_key->key_len = 16;
+- memcpy(sec_key->key, key->key, 16);
+- sec->n_cipher = 2;
++ if (cipher == CONNAC3_CIPHER_BIP_CMAC_128) {
++ sec->cipher_id = CONNAC3_CIPHER_BIP_CMAC_128;
++ sec->key_id = sta_key_conf->keyidx;
++ sec->key_len = 32;
++ memcpy(sec->key, sta_key_conf->key, 16);
++ memcpy(sec->key + 16, key->key, 16);
+ } else {
+- sec_key->wlan_idx = cpu_to_le16(wcid->idx);
+- sec_key->cipher_id = cipher;
+- sec_key->key_id = key->keyidx;
+- sec_key->key_len = key->keylen;
+- memcpy(sec_key->key, key->key, key->keylen);
++ sec->cipher_id = cipher;
++ sec->key_id = key->keyidx;
++ sec->key_len = key->keylen;
++ memcpy(sec->key, key->key, key->keylen);
+
+- if (cipher == MCU_CIPHER_TKIP) {
++ if (cipher == CONNAC3_CIPHER_TKIP) {
+ /* Rx/Tx MIC keys are swapped */
+- memcpy(sec_key->key + 16, key->key + 24, 8);
+- memcpy(sec_key->key + 24, key->key + 16, 8);
++ memcpy(sec->key + 16, key->key + 24, 8);
++ memcpy(sec->key + 24, key->key + 16, 8);
+ }
+
+ /* store key_conf for BIP batch update */
+- if (cipher == MCU_CIPHER_AES_CCMP) {
++ if (cipher == CONNAC3_CIPHER_AES_CCMP) {
+ memcpy(sta_key_conf->key, key->key, key->keylen);
+ sta_key_conf->keyidx = key->keyidx;
+ }
+-
+- sec->n_cipher = 1;
+ }
+ } else {
+- sec->n_cipher = 0;
++ sec->add = 0;
+ }
+
+ return 0;
+@@ -1460,12 +1471,10 @@ mt7925_mcu_sta_phy_tlv(struct sk_buff *skb,
+ struct tlv *tlv;
+ u8 af = 0, mm = 0;
+
+- if (!sta->deflink.ht_cap.ht_supported && !sta->deflink.he_6ghz_capa.capa)
+- return;
+-
+ tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PHY, sizeof(*phy));
+ phy = (struct sta_rec_phy *)tlv;
+ phy->phy_type = mt76_connac_get_phy_mode_v2(mvif->phy->mt76, vif, chandef->chan->band, sta);
++ phy->basic_rate = cpu_to_le16((u16)vif->bss_conf.basic_rates);
+ if (sta->deflink.ht_cap.ht_supported) {
+ af = sta->deflink.ht_cap.ampdu_factor;
+ mm = sta->deflink.ht_cap.ampdu_density;
+@@ -1573,8 +1582,6 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
+ {
+ struct mt76_vif *mvif = (struct mt76_vif *)info->vif->drv_priv;
+ struct mt76_dev *dev = phy->dev;
+- struct wtbl_req_hdr *wtbl_hdr;
+- struct tlv *sta_wtbl;
+ struct sk_buff *skb;
+
+ skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, info->wcid,
+@@ -1598,30 +1605,11 @@ mt7925_mcu_sta_cmd(struct mt76_phy *phy,
+ mt7925_mcu_sta_state_v2_tlv(phy, skb, info->sta,
+ info->vif, info->rcpi,
+ info->state);
+- mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->sta);
+ mt7925_mcu_sta_mld_tlv(skb, info->vif, info->sta);
+ }
+
+- sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,
+- sizeof(struct tlv));
+-
+- wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, info->wcid,
+- WTBL_RESET_AND_SET,
+- sta_wtbl, &skb);
+- if (IS_ERR(wtbl_hdr))
+- return PTR_ERR(wtbl_hdr);
+-
+- if (info->enable) {
+- mt76_connac_mcu_wtbl_generic_tlv(dev, skb, info->vif,
+- info->sta, sta_wtbl,
+- wtbl_hdr);
+- mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, info->vif, info->wcid,
+- sta_wtbl, wtbl_hdr);
+- if (info->sta)
+- mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta,
+- sta_wtbl, wtbl_hdr,
+- true, true);
+- }
++ if (info->enable)
++ mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->sta);
+
+ return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);
+ }
+@@ -2049,9 +2037,9 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb,
+ struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->chandef;
+ enum nl80211_band band = chandef->chan->band;
+ struct mt76_connac_bss_basic_tlv *basic_req;
+- u8 idx, basic_phy;
+ struct tlv *tlv;
+ int conn_type;
++ u8 idx;
+
+ tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_BASIC, sizeof(*basic_req));
+ basic_req = (struct mt76_connac_bss_basic_tlv *)tlv;
+@@ -2062,8 +2050,10 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb,
+
+ basic_req->phymode_ext = mt7925_get_phy_mode_ext(phy, vif, band, sta);
+
+- basic_phy = mt76_connac_get_phy_mode_v2(phy, vif, band, sta);
+- basic_req->nonht_basic_phy = cpu_to_le16(basic_phy);
++ if (band == NL80211_BAND_2GHZ)
++ basic_req->nonht_basic_phy = cpu_to_le16(PHY_TYPE_ERP_INDEX);
++ else
++ basic_req->nonht_basic_phy = cpu_to_le16(PHY_TYPE_OFDM_INDEX);
+
+ memcpy(basic_req->bssid, vif->bss_conf.bssid, ETH_ALEN);
+ basic_req->phymode = mt76_connac_get_phy_mode(phy, vif, band, sta);
+@@ -2122,21 +2112,21 @@ mt7925_mcu_bss_sec_tlv(struct sk_buff *skb, struct ieee80211_vif *vif)
+ sec = (struct bss_sec_tlv *)tlv;
+
+ switch (mvif->cipher) {
+- case MCU_CIPHER_GCMP_256:
+- case MCU_CIPHER_GCMP:
++ case CONNAC3_CIPHER_GCMP_256:
++ case CONNAC3_CIPHER_GCMP:
+ sec->mode = MODE_WPA3_SAE;
+ sec->status = 8;
+ break;
+- case MCU_CIPHER_AES_CCMP:
++ case CONNAC3_CIPHER_AES_CCMP:
+ sec->mode = MODE_WPA2_PSK;
+ sec->status = 6;
+ break;
+- case MCU_CIPHER_TKIP:
++ case CONNAC3_CIPHER_TKIP:
+ sec->mode = MODE_WPA2_PSK;
+ sec->status = 4;
+ break;
+- case MCU_CIPHER_WEP104:
+- case MCU_CIPHER_WEP40:
++ case CONNAC3_CIPHER_WEP104:
++ case CONNAC3_CIPHER_WEP40:
+ sec->mode = MODE_SHARED;
+ sec->status = 0;
+ break;
+@@ -2167,6 +2157,11 @@ mt7925_mcu_bss_bmc_tlv(struct sk_buff *skb, struct mt792x_phy *phy,
+
+ bmc = (struct bss_rate_tlv *)tlv;
+
++ if (band == NL80211_BAND_2GHZ)
++ bmc->basic_rate = cpu_to_le16(HR_DSSS_ERP_BASIC_RATE);
++ else
++ bmc->basic_rate = cpu_to_le16(OFDM_BASIC_RATE);
++
+ bmc->short_preamble = (band == NL80211_BAND_2GHZ);
+ bmc->bc_fixed_rate = idx;
+ bmc->mc_fixed_rate = idx;
+@@ -2249,6 +2244,38 @@ mt7925_mcu_bss_color_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
+ vif->bss_conf.he_bss_color.color : 0;
+ }
+
++static void
++mt7925_mcu_bss_ifs_tlv(struct sk_buff *skb, struct ieee80211_vif *vif)
++{
++ struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
++ struct mt792x_phy *phy = mvif->phy;
++ struct bss_ifs_time_tlv *ifs_time;
++ struct tlv *tlv;
++
++ tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_IFS_TIME, sizeof(*ifs_time));
++ ifs_time = (struct bss_ifs_time_tlv *)tlv;
++ ifs_time->slot_valid = true;
++ ifs_time->slot_time = cpu_to_le16(phy->slottime);
++}
++
++int mt7925_mcu_set_timing(struct mt792x_phy *phy,
++ struct ieee80211_vif *vif)
++{
++ struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
++ struct mt792x_dev *dev = phy->dev;
++ struct sk_buff *skb;
++
++ skb = __mt7925_mcu_alloc_bss_req(&dev->mt76, &mvif->mt76,
++ MT7925_BSS_UPDATE_MAX_SIZE);
++ if (IS_ERR(skb))
++ return PTR_ERR(skb);
++
++ mt7925_mcu_bss_ifs_tlv(skb, vif);
++
++ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
++ MCU_UNI_CMD(BSS_INFO_UPDATE), true);
++}
++
+ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
+ struct ieee80211_chanctx_conf *ctx,
+ struct ieee80211_vif *vif,
+@@ -2273,6 +2300,7 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
+ mt7925_mcu_bss_bmc_tlv(skb, phy, ctx, vif, sta);
+ mt7925_mcu_bss_qos_tlv(skb, vif);
+ mt7925_mcu_bss_mld_tlv(skb, vif, sta);
++ mt7925_mcu_bss_ifs_tlv(skb, vif);
+
+ if (vif->bss_conf.he_support) {
+ mt7925_mcu_bss_he_tlv(skb, vif, phy);
+@@ -2845,12 +2873,16 @@ int mt7925_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,
+ if (cmd & __MCU_CMD_FIELD_UNI) {
+ uni_txd = (struct mt76_connac2_mcu_uni_txd *)txd;
+ uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd));
+- uni_txd->option = MCU_CMD_UNI_EXT_ACK;
+ uni_txd->cid = cpu_to_le16(mcu_cmd);
+ uni_txd->s2d_index = MCU_S2D_H2N;
+ uni_txd->pkt_type = MCU_PKT_ID;
+ uni_txd->seq = seq;
+
++ if (cmd & __MCU_CMD_FIELD_QUERY)
++ uni_txd->option = MCU_CMD_UNI_QUERY_ACK;
++ else
++ uni_txd->option = MCU_CMD_UNI_EXT_ACK;
++
+ goto exit;
+ }
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
+index 3c41e21303b1f..2cf39276118eb 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
+@@ -159,6 +159,20 @@ enum {
+ UNI_EVENT_SCAN_DONE_NLO = 3,
+ };
+
++enum connac3_mcu_cipher_type {
++ CONNAC3_CIPHER_NONE = 0,
++ CONNAC3_CIPHER_WEP40 = 1,
++ CONNAC3_CIPHER_TKIP = 2,
++ CONNAC3_CIPHER_AES_CCMP = 4,
++ CONNAC3_CIPHER_WEP104 = 5,
++ CONNAC3_CIPHER_BIP_CMAC_128 = 6,
++ CONNAC3_CIPHER_WEP128 = 7,
++ CONNAC3_CIPHER_WAPI = 8,
++ CONNAC3_CIPHER_CCMP_256 = 10,
++ CONNAC3_CIPHER_GCMP = 11,
++ CONNAC3_CIPHER_GCMP_256 = 12,
++};
++
+ struct mt7925_mcu_scan_chinfo_event {
+ u8 nr_chan;
+ u8 alpha2[3];
+@@ -334,7 +348,8 @@ struct bss_req_hdr {
+ struct bss_rate_tlv {
+ __le16 tag;
+ __le16 len;
+- u8 __rsv1[4];
++ u8 __rsv1[2];
++ __le16 basic_rate;
+ __le16 bc_trans;
+ __le16 mc_trans;
+ u8 short_preamble;
+@@ -382,25 +397,22 @@ struct sta_rec_eht {
+ u8 _rsv2[3];
+ } __packed;
+
+-struct sec_key_uni {
+- __le16 wlan_idx;
+- u8 mgmt_prot;
+- u8 cipher_id;
+- u8 cipher_len;
+- u8 key_id;
+- u8 key_len;
+- u8 need_resp;
+- u8 key[32];
+-} __packed;
+-
+ struct sta_rec_sec_uni {
+ __le16 tag;
+ __le16 len;
+ u8 add;
+- u8 n_cipher;
+- u8 rsv[2];
+-
+- struct sec_key_uni key[2];
++ u8 tx_key;
++ u8 key_type;
++ u8 is_authenticator;
++ u8 peer_addr[6];
++ u8 bss_idx;
++ u8 cipher_id;
++ u8 key_id;
++ u8 key_len;
++ u8 wlan_idx;
++ u8 mgmt_prot;
++ u8 key[32];
++ u8 key_rsc[16];
+ } __packed;
+
+ struct sta_rec_hdr_trans {
+@@ -428,6 +440,22 @@ struct sta_rec_mld {
+ } __packed link[2];
+ } __packed;
+
++struct bss_ifs_time_tlv {
++ __le16 tag;
++ __le16 len;
++ u8 slot_valid;
++ u8 sifs_valid;
++ u8 rifs_valid;
++ u8 eifs_valid;
++ __le16 slot_time;
++ __le16 sifs_time;
++ __le16 rifs_time;
++ __le16 eifs_time;
++ u8 eifs_cck_valid;
++ u8 rsv;
++ __le16 eifs_cck_time;
++} __packed;
++
+ #define MT7925_STA_UPDATE_MAX_SIZE (sizeof(struct sta_req_hdr) + \
+ sizeof(struct sta_rec_basic) + \
+ sizeof(struct sta_rec_bf) + \
+@@ -440,7 +468,7 @@ struct sta_rec_mld {
+ sizeof(struct sta_rec_bfee) + \
+ sizeof(struct sta_rec_phy) + \
+ sizeof(struct sta_rec_ra) + \
+- sizeof(struct sta_rec_sec) + \
++ sizeof(struct sta_rec_sec_uni) + \
+ sizeof(struct sta_rec_ra_fixed) + \
+ sizeof(struct sta_rec_he_6g_capa) + \
+ sizeof(struct sta_rec_eht) + \
+@@ -455,6 +483,7 @@ struct sta_rec_mld {
+ sizeof(struct bss_mld_tlv) + \
+ sizeof(struct bss_info_uni_he) + \
+ sizeof(struct bss_info_uni_bss_color) + \
++ sizeof(struct bss_ifs_time_tlv) + \
+ sizeof(struct tlv))
+
+ #define MT_CONNAC3_SKU_POWER_LIMIT 449
+@@ -509,6 +538,33 @@ struct mt7925_wow_pattern_tlv {
+ u8 rsv[4];
+ } __packed;
+
++static inline enum connac3_mcu_cipher_type
++mt7925_mcu_get_cipher(int cipher)
++{
++ switch (cipher) {
++ case WLAN_CIPHER_SUITE_WEP40:
++ return CONNAC3_CIPHER_WEP40;
++ case WLAN_CIPHER_SUITE_WEP104:
++ return CONNAC3_CIPHER_WEP104;
++ case WLAN_CIPHER_SUITE_TKIP:
++ return CONNAC3_CIPHER_TKIP;
++ case WLAN_CIPHER_SUITE_AES_CMAC:
++ return CONNAC3_CIPHER_BIP_CMAC_128;
++ case WLAN_CIPHER_SUITE_CCMP:
++ return CONNAC3_CIPHER_AES_CCMP;
++ case WLAN_CIPHER_SUITE_CCMP_256:
++ return CONNAC3_CIPHER_CCMP_256;
++ case WLAN_CIPHER_SUITE_GCMP:
++ return CONNAC3_CIPHER_GCMP;
++ case WLAN_CIPHER_SUITE_GCMP_256:
++ return CONNAC3_CIPHER_GCMP_256;
++ case WLAN_CIPHER_SUITE_SMS4:
++ return CONNAC3_CIPHER_WAPI;
++ default:
++ return CONNAC3_CIPHER_NONE;
++ }
++}
++
+ int mt7925_mcu_set_dbdc(struct mt76_phy *phy);
+ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,
+ struct ieee80211_scan_request *scan_req);
+@@ -525,6 +581,8 @@ int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ int enable);
++int mt7925_mcu_set_timing(struct mt792x_phy *phy,
++ struct ieee80211_vif *vif);
+ int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable);
+ int mt7925_mcu_set_channel_domain(struct mt76_phy *phy);
+ int mt7925_mcu_set_radio_en(struct mt792x_phy *phy, bool enable);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+index 1fd99a8565415..07b74d492ce15 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+@@ -386,6 +386,8 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
+
+ dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
+
++ mt76_rmw_field(dev, MT_HW_EMI_CTL, MT_HW_EMI_CTL_SLPPROT_EN, 1);
++
+ ret = mt792x_wfsys_reset(dev);
+ if (ret)
+ goto err_free_dev;
+@@ -425,6 +427,7 @@ static void mt7925_pci_remove(struct pci_dev *pdev)
+ struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
+
+ mt7925e_unregister_device(dev);
++ set_bit(MT76_REMOVED, &mdev->phy.state);
+ devm_free_irq(&pdev->dev, pdev->irq, dev);
+ mt76_free_device(&dev->mt76);
+ pci_free_irq_vectors(pdev);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c
+index e7afea87e82e2..8fee3d481df0d 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c
++++ b/drivers/net/wireless/mediatek/mt76/mt792x_acpi_sar.c
+@@ -66,13 +66,15 @@ mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len)
+ }
+
+ /* MTCL : Country List Table for 6G band */
+-static void
++static int
+ mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version)
+ {
+- if (mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, NULL) < 0)
+- *version = 1;
+- else
+- *version = 2;
++ int ret;
++
++ *version = ((ret = mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, NULL)) < 0)
++ ? 1 : 2;
++
++ return ret;
+ }
+
+ /* MTDS : Dynamic SAR Power Table */
+@@ -166,16 +168,16 @@ int mt792x_init_acpi_sar(struct mt792x_dev *dev)
+ if (!asar)
+ return -ENOMEM;
+
+- mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver);
++ ret = mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver);
++ if (ret) {
++ devm_kfree(dev->mt76.dev, asar->countrylist);
++ asar->countrylist = NULL;
++ }
+
+- /* MTDS is mandatory. Return error if table is invalid */
+ ret = mt792x_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver);
+ if (ret) {
+ devm_kfree(dev->mt76.dev, asar->dyn);
+- devm_kfree(dev->mt76.dev, asar->countrylist);
+- devm_kfree(dev->mt76.dev, asar);
+-
+- return ret;
++ asar->dyn = NULL;
+ }
+
+ /* MTGS is optional */
+@@ -290,7 +292,7 @@ int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default)
+ const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
+ int i;
+
+- if (!phy->acpisar)
++ if (!phy->acpisar || !((struct mt792x_acpi_sar *)phy->acpisar)->dyn)
+ return 0;
+
+ /* When ACPI SAR enabled in HW, we should apply rules for .frp
+diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
+index c42101aa9e45e..9ac5161dfff8c 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c
++++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
+@@ -354,6 +354,7 @@ static const char mt792x_gstrings_stats[][ETH_GSTRING_LEN] = {
+ "v_tx_bw_40",
+ "v_tx_bw_80",
+ "v_tx_bw_160",
++ "v_tx_bw_320",
+ "v_tx_mcs_0",
+ "v_tx_mcs_1",
+ "v_tx_mcs_2",
+diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
+index 488326ce5ed4d..5cc2d59b774af 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
++++ b/drivers/net/wireless/mediatek/mt76/mt792x_dma.c
+@@ -12,6 +12,8 @@ irqreturn_t mt792x_irq_handler(int irq, void *dev_instance)
+ {
+ struct mt792x_dev *dev = dev_instance;
+
++ if (test_bit(MT76_REMOVED, &dev->mt76.phy.state))
++ return IRQ_NONE;
+ mt76_wr(dev, dev->irq_map->host_irq_enable, 0);
+
+ if (!test_bit(MT76_STATE_INITIALIZED, &dev->mphy.state))
+@@ -123,14 +125,13 @@ static void mt792x_dma_prefetch(struct mt792x_dev *dev)
+
+ int mt792x_dma_enable(struct mt792x_dev *dev)
+ {
+- if (is_mt7925(&dev->mt76))
+- mt76_rmw(dev, MT_UWFDMA0_GLO_CFG_EXT1, BIT(28), BIT(28));
+-
+ /* configure perfetch settings */
+ mt792x_dma_prefetch(dev);
+
+ /* reset dma idx */
+ mt76_wr(dev, MT_WFDMA0_RST_DTX_PTR, ~0);
++ if (is_mt7925(&dev->mt76))
++ mt76_wr(dev, MT_WFDMA0_RST_DRX_PTR, ~0);
+
+ /* configure delay interrupt */
+ mt76_wr(dev, MT_WFDMA0_PRI_DLY_INT_CFG0, 0);
+@@ -140,12 +141,20 @@ int mt792x_dma_enable(struct mt792x_dev *dev)
+ MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN |
+ MT_WFDMA0_GLO_CFG_CLK_GAT_DIS |
+ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
++ FIELD_PREP(MT_WFDMA0_GLO_CFG_DMA_SIZE, 3) |
++ MT_WFDMA0_GLO_CFG_FIFO_DIS_CHECK |
++ MT_WFDMA0_GLO_CFG_RX_WB_DDONE |
+ MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN |
+ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
+
+ mt76_set(dev, MT_WFDMA0_GLO_CFG,
+ MT_WFDMA0_GLO_CFG_TX_DMA_EN | MT_WFDMA0_GLO_CFG_RX_DMA_EN);
+
++ if (is_mt7925(&dev->mt76)) {
++ mt76_rmw(dev, MT_UWFDMA0_GLO_CFG_EXT1, BIT(28), BIT(28));
++ mt76_set(dev, MT_WFDMA0_INT_RX_PRI, 0x0F00);
++ mt76_set(dev, MT_WFDMA0_INT_TX_PRI, 0x7F00);
++ }
+ mt76_set(dev, MT_WFDMA_DUMMY_CR, MT_WFDMA_NEED_REINIT);
+
+ /* enable interrupts for TX/RX rings */
+diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
+index a99af23e4b564..458cfd0260b13 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
++++ b/drivers/net/wireless/mediatek/mt76/mt792x_regs.h
+@@ -292,9 +292,12 @@
+ #define MT_WFDMA0_GLO_CFG_TX_DMA_BUSY BIT(1)
+ #define MT_WFDMA0_GLO_CFG_RX_DMA_EN BIT(2)
+ #define MT_WFDMA0_GLO_CFG_RX_DMA_BUSY BIT(3)
++#define MT_WFDMA0_GLO_CFG_DMA_SIZE GENMASK(5, 4)
+ #define MT_WFDMA0_GLO_CFG_TX_WB_DDONE BIT(6)
+ #define MT_WFDMA0_GLO_CFG_FW_DWLD_BYPASS_DMASHDL BIT(9)
++#define MT_WFDMA0_GLO_CFG_FIFO_DIS_CHECK BIT(11)
+ #define MT_WFDMA0_GLO_CFG_FIFO_LITTLE_ENDIAN BIT(12)
++#define MT_WFDMA0_GLO_CFG_RX_WB_DDONE BIT(13)
+ #define MT_WFDMA0_GLO_CFG_CSR_DISP_BASE_PTR_CHAIN_EN BIT(15)
+ #define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 BIT(21)
+ #define MT_WFDMA0_GLO_CFG_OMIT_RX_INFO BIT(27)
+@@ -322,6 +325,8 @@
+
+ #define MT_WFDMA0_RST_DTX_PTR MT_WFDMA0(0x20c)
+ #define MT_WFDMA0_RST_DRX_PTR MT_WFDMA0(0x280)
++#define MT_WFDMA0_INT_RX_PRI MT_WFDMA0(0x298)
++#define MT_WFDMA0_INT_TX_PRI MT_WFDMA0(0x29c)
+ #define MT_WFDMA0_GLO_CFG_EXT0 MT_WFDMA0(0x2b0)
+ #define MT_WFDMA0_CSR_TX_DMASHDL_ENABLE BIT(6)
+ #define MT_WFDMA0_PRI_DLY_INT_CFG0 MT_WFDMA0(0x2f0)
+@@ -389,6 +394,9 @@
+ #define MT_HW_CHIPID 0x70010200
+ #define MT_HW_REV 0x70010204
+
++#define MT_HW_EMI_CTL 0x18011100
++#define MT_HW_EMI_CTL_SLPPROT_EN BIT(1)
++
+ #define MT_PCIE_MAC_BASE 0x10000
+ #define MT_PCIE_MAC(ofs) (MT_PCIE_MAC_BASE + (ofs))
+ #define MT_PCIE_MAC_INT_ENABLE MT_PCIE_MAC(0x188)
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
+index 483ad81b6eec6..fe37110e66875 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/dma.c
+@@ -237,7 +237,8 @@ void mt7996_dma_start(struct mt7996_dev *dev, bool reset, bool wed_reset)
+ MT_WFDMA0_GLO_CFG_TX_DMA_EN |
+ MT_WFDMA0_GLO_CFG_RX_DMA_EN |
+ MT_WFDMA0_GLO_CFG_OMIT_TX_INFO |
+- MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2);
++ MT_WFDMA0_GLO_CFG_OMIT_RX_INFO_PFET2 |
++ MT_WFDMA0_GLO_CFG_EXT_EN);
+
+ if (dev->hif2)
+ mt76_set(dev, MT_WFDMA0_GLO_CFG + hif1_ofs,
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
+index 0cf0d1fe420a2..a929c657be1c4 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
+@@ -493,7 +493,7 @@ static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
+
+ void mt7996_mac_init(struct mt7996_dev *dev)
+ {
+-#define HIF_TXD_V2_1 4
++#define HIF_TXD_V2_1 0x21
+ int i;
+
+ mt76_clear(dev, MT_MDP_DCR2, MT_MDP_DCR2_RX_TRANS_SHORT);
+@@ -1012,11 +1012,12 @@ mt7996_set_stream_he_txbf_caps(struct mt7996_phy *phy,
+ /* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */
+ elem->phy_cap_info[7] |= min_t(int, sts - 1, 2) << 3;
+
+- if (vif != NL80211_IFTYPE_AP)
++ if (!(vif == NL80211_IFTYPE_AP || vif == NL80211_IFTYPE_STATION))
+ return;
+
+ elem->phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_SU_BEAMFORMER;
+- elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
++ if (vif == NL80211_IFTYPE_AP)
++ elem->phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_MU_BEAMFORMER;
+
+ c = FIELD_PREP(IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK,
+ sts - 1) |
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+index 53258488d49f3..63d34844c1223 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+@@ -1188,25 +1188,28 @@ mt7996_mac_add_txs_skb(struct mt7996_dev *dev, struct mt76_wcid *wcid,
+ struct ieee80211_tx_info *info;
+ struct sk_buff_head list;
+ struct rate_info rate = {};
+- struct sk_buff *skb;
++ struct sk_buff *skb = NULL;
+ bool cck = false;
+ u32 txrate, txs, mode, stbc;
+
+ txs = le32_to_cpu(txs_data[0]);
+
+ mt76_tx_status_lock(mdev, &list);
+- skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
+
+- if (skb) {
+- info = IEEE80211_SKB_CB(skb);
+- if (!(txs & MT_TXS0_ACK_ERROR_MASK))
+- info->flags |= IEEE80211_TX_STAT_ACK;
++ /* only report MPDU TXS */
++ if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) == 0) {
++ skb = mt76_tx_status_skb_get(mdev, wcid, pid, &list);
++ if (skb) {
++ info = IEEE80211_SKB_CB(skb);
++ if (!(txs & MT_TXS0_ACK_ERROR_MASK))
++ info->flags |= IEEE80211_TX_STAT_ACK;
+
+- info->status.ampdu_len = 1;
+- info->status.ampdu_ack_len =
+- !!(info->flags & IEEE80211_TX_STAT_ACK);
++ info->status.ampdu_len = 1;
++ info->status.ampdu_ack_len =
++ !!(info->flags & IEEE80211_TX_STAT_ACK);
+
+- info->status.rates[0].idx = -1;
++ info->status.rates[0].idx = -1;
++ }
+ }
+
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed) && wcid->sta) {
+@@ -2527,6 +2530,34 @@ static int mt7996_mac_check_twt_req(struct ieee80211_twt_setup *twt)
+ return 0;
+ }
+
++static bool
++mt7996_mac_twt_param_equal(struct mt7996_sta *msta,
++ struct ieee80211_twt_params *twt_agrt)
++{
++ u16 type = le16_to_cpu(twt_agrt->req_type);
++ u8 exp;
++ int i;
++
++ exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, type);
++ for (i = 0; i < MT7996_MAX_STA_TWT_AGRT; i++) {
++ struct mt7996_twt_flow *f;
++
++ if (!(msta->twt.flowid_mask & BIT(i)))
++ continue;
++
++ f = &msta->twt.flow[i];
++ if (f->duration == twt_agrt->min_twt_dur &&
++ f->mantissa == twt_agrt->mantissa &&
++ f->exp == exp &&
++ f->protection == !!(type & IEEE80211_TWT_REQTYPE_PROTECTION) &&
++ f->flowtype == !!(type & IEEE80211_TWT_REQTYPE_FLOWTYPE) &&
++ f->trigger == !!(type & IEEE80211_TWT_REQTYPE_TRIGGER))
++ return true;
++ }
++
++ return false;
++}
++
+ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ struct ieee80211_twt_setup *twt)
+@@ -2538,8 +2569,7 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
+ enum ieee80211_twt_setup_cmd sta_setup_cmd;
+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
+ struct mt7996_twt_flow *flow;
+- int flowid, table_id;
+- u8 exp;
++ u8 flowid, table_id, exp;
+
+ if (mt7996_mac_check_twt_req(twt))
+ goto out;
+@@ -2552,9 +2582,19 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
+ if (hweight8(msta->twt.flowid_mask) == ARRAY_SIZE(msta->twt.flow))
+ goto unlock;
+
++ if (twt_agrt->min_twt_dur < MT7996_MIN_TWT_DUR) {
++ setup_cmd = TWT_SETUP_CMD_DICTATE;
++ twt_agrt->min_twt_dur = MT7996_MIN_TWT_DUR;
++ goto unlock;
++ }
++
++ if (mt7996_mac_twt_param_equal(msta, twt_agrt))
++ goto unlock;
++
+ flowid = ffs(~msta->twt.flowid_mask) - 1;
+- le16p_replace_bits(&twt_agrt->req_type, flowid,
+- IEEE80211_TWT_REQTYPE_FLOWID);
++ twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_FLOWID);
++ twt_agrt->req_type |= le16_encode_bits(flowid,
++ IEEE80211_TWT_REQTYPE_FLOWID);
+
+ table_id = ffs(~dev->twt.table_mask) - 1;
+ exp = FIELD_GET(IEEE80211_TWT_REQTYPE_WAKE_INT_EXP, req_type);
+@@ -2601,10 +2641,10 @@ void mt7996_mac_add_twt_setup(struct ieee80211_hw *hw,
+ unlock:
+ mutex_unlock(&dev->mt76.mutex);
+ out:
+- le16p_replace_bits(&twt_agrt->req_type, setup_cmd,
+- IEEE80211_TWT_REQTYPE_SETUP_CMD);
+- twt->control = (twt->control & IEEE80211_TWT_CONTROL_WAKE_DUR_UNIT) |
+- (twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED);
++ twt_agrt->req_type &= ~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD);
++ twt_agrt->req_type |=
++ le16_encode_bits(setup_cmd, IEEE80211_TWT_REQTYPE_SETUP_CMD);
++ twt->control = twt->control & IEEE80211_TWT_CONTROL_RX_DISABLED;
+ }
+
+ void mt7996_mac_twt_teardown_flow(struct mt7996_dev *dev,
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+index 699be57309c2e..9e70b960086ac 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+@@ -1240,6 +1240,9 @@ mt7996_mcu_sta_he_6g_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+ static void
+ mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+ {
++ struct mt7996_sta *msta = (struct mt7996_sta *)sta->drv_priv;
++ struct ieee80211_vif *vif = container_of((void *)msta->vif,
++ struct ieee80211_vif, drv_priv);
+ struct ieee80211_eht_mcs_nss_supp *mcs_map;
+ struct ieee80211_eht_cap_elem_fixed *elem;
+ struct sta_rec_eht *eht;
+@@ -1259,8 +1262,17 @@ mt7996_mcu_sta_eht_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+ eht->phy_cap = cpu_to_le64(*(u64 *)elem->phy_cap_info);
+ eht->phy_cap_ext = cpu_to_le64(elem->phy_cap_info[8]);
+
+- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
+- memcpy(eht->mcs_map_bw20, &mcs_map->only_20mhz, sizeof(eht->mcs_map_bw20));
++ if (vif->type != NL80211_IFTYPE_STATION &&
++ (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
++ (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G |
++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
++ IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)) == 0) {
++ memcpy(eht->mcs_map_bw20, &mcs_map->only_20mhz,
++ sizeof(eht->mcs_map_bw20));
++ return;
++ }
++
+ memcpy(eht->mcs_map_bw80, &mcs_map->bw._80, sizeof(eht->mcs_map_bw80));
+ memcpy(eht->mcs_map_bw160, &mcs_map->bw._160, sizeof(eht->mcs_map_bw160));
+ memcpy(eht->mcs_map_bw320, &mcs_map->bw._320, sizeof(eht->mcs_map_bw320));
+@@ -3539,7 +3551,7 @@ int mt7996_mcu_get_eeprom(struct mt7996_dev *dev, u32 offset)
+ u32 addr = le32_to_cpu(*(__le32 *)(skb->data + 12));
+ u8 *buf = (u8 *)dev->mt76.eeprom.data + addr;
+
+- skb_pull(skb, 64);
++ skb_pull(skb, 48);
+ memcpy(buf, skb->data, MT7996_EEPROM_BLOCK_SIZE);
+ }
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+index bc73bcb47bf02..8154ad37827f0 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+@@ -53,6 +53,7 @@
+
+ #define MT7996_MAX_TWT_AGRT 16
+ #define MT7996_MAX_STA_TWT_AGRT 8
++#define MT7996_MIN_TWT_DUR 64
+ #define MT7996_MAX_QUEUE (__MT_RXQ_MAX + __MT_MCUQ_MAX + 3)
+
+ /* NOTE: used to map mt76_rates. idx may change if firmware expands table */
+@@ -320,7 +321,7 @@ struct mt7996_dev {
+ struct rchan *relay_fwlog;
+
+ struct {
+- u8 table_mask;
++ u16 table_mask;
+ u8 n_agrt;
+ } twt;
+
+diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
+index ad2509d8c99a4..f03fd15c0c97a 100644
+--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c
++++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
+@@ -1609,7 +1609,6 @@ static int del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
+ cfg80211_unregister_netdevice(vif->ndev);
+ vif->monitor_flag = 0;
+
+- wilc_set_operation_mode(vif, 0, 0, 0);
+ mutex_lock(&wl->vif_mutex);
+ list_del_rcu(&vif->list);
+ wl->vif_num--;
+@@ -1804,15 +1803,24 @@ int wilc_cfg80211_init(struct wilc **wilc, struct device *dev, int io_type,
+ INIT_LIST_HEAD(&wl->rxq_head.list);
+ INIT_LIST_HEAD(&wl->vif_list);
+
++ wl->hif_workqueue = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM,
++ wiphy_name(wl->wiphy));
++ if (!wl->hif_workqueue) {
++ ret = -ENOMEM;
++ goto free_cfg;
++ }
+ vif = wilc_netdev_ifc_init(wl, "wlan%d", WILC_STATION_MODE,
+ NL80211_IFTYPE_STATION, false);
+ if (IS_ERR(vif)) {
+ ret = PTR_ERR(vif);
+- goto free_cfg;
++ goto free_hq;
+ }
+
+ return 0;
+
++free_hq:
++ destroy_workqueue(wl->hif_workqueue);
++
+ free_cfg:
+ wilc_wlan_cfg_deinit(wl);
+
+diff --git a/drivers/net/wireless/microchip/wilc1000/hif.c b/drivers/net/wireless/microchip/wilc1000/hif.c
+index 839f142663e86..d2b8c26308198 100644
+--- a/drivers/net/wireless/microchip/wilc1000/hif.c
++++ b/drivers/net/wireless/microchip/wilc1000/hif.c
+@@ -377,38 +377,49 @@ struct wilc_join_bss_param *
+ wilc_parse_join_bss_param(struct cfg80211_bss *bss,
+ struct cfg80211_crypto_settings *crypto)
+ {
+- struct wilc_join_bss_param *param;
+- struct ieee80211_p2p_noa_attr noa_attr;
+- u8 rates_len = 0;
+- const u8 *tim_elm, *ssid_elm, *rates_ie, *supp_rates_ie;
++ const u8 *ies_data, *tim_elm, *ssid_elm, *rates_ie, *supp_rates_ie;
+ const u8 *ht_ie, *wpa_ie, *wmm_ie, *rsn_ie;
++ struct ieee80211_p2p_noa_attr noa_attr;
++ const struct cfg80211_bss_ies *ies;
++ struct wilc_join_bss_param *param;
++ u8 rates_len = 0, ies_len;
+ int ret;
+- const struct cfg80211_bss_ies *ies = rcu_dereference(bss->ies);
+
+ param = kzalloc(sizeof(*param), GFP_KERNEL);
+ if (!param)
+ return NULL;
+
++ rcu_read_lock();
++ ies = rcu_dereference(bss->ies);
++ ies_data = kmemdup(ies->data, ies->len, GFP_ATOMIC);
++ if (!ies_data) {
++ rcu_read_unlock();
++ kfree(param);
++ return NULL;
++ }
++ ies_len = ies->len;
++ rcu_read_unlock();
++
+ param->beacon_period = cpu_to_le16(bss->beacon_interval);
+ param->cap_info = cpu_to_le16(bss->capability);
+ param->bss_type = WILC_FW_BSS_TYPE_INFRA;
+ param->ch = ieee80211_frequency_to_channel(bss->channel->center_freq);
+ ether_addr_copy(param->bssid, bss->bssid);
+
+- ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len);
++ ssid_elm = cfg80211_find_ie(WLAN_EID_SSID, ies_data, ies_len);
+ if (ssid_elm) {
+ if (ssid_elm[1] <= IEEE80211_MAX_SSID_LEN)
+ memcpy(param->ssid, ssid_elm + 2, ssid_elm[1]);
+ }
+
+- tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies->data, ies->len);
++ tim_elm = cfg80211_find_ie(WLAN_EID_TIM, ies_data, ies_len);
+ if (tim_elm && tim_elm[1] >= 2)
+ param->dtim_period = tim_elm[3];
+
+ memset(param->p_suites, 0xFF, 3);
+ memset(param->akm_suites, 0xFF, 3);
+
+- rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies->data, ies->len);
++ rates_ie = cfg80211_find_ie(WLAN_EID_SUPP_RATES, ies_data, ies_len);
+ if (rates_ie) {
+ rates_len = rates_ie[1];
+ if (rates_len > WILC_MAX_RATES_SUPPORTED)
+@@ -419,7 +430,7 @@ wilc_parse_join_bss_param(struct cfg80211_bss *bss,
+
+ if (rates_len < WILC_MAX_RATES_SUPPORTED) {
+ supp_rates_ie = cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
+- ies->data, ies->len);
++ ies_data, ies_len);
+ if (supp_rates_ie) {
+ u8 ext_rates = supp_rates_ie[1];
+
+@@ -434,11 +445,11 @@ wilc_parse_join_bss_param(struct cfg80211_bss *bss,
+ }
+ }
+
+- ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies->data, ies->len);
++ ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies_data, ies_len);
+ if (ht_ie)
+ param->ht_capable = true;
+
+- ret = cfg80211_get_p2p_attr(ies->data, ies->len,
++ ret = cfg80211_get_p2p_attr(ies_data, ies_len,
+ IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
+ (u8 *)&noa_attr, sizeof(noa_attr));
+ if (ret > 0) {
+@@ -462,7 +473,7 @@ wilc_parse_join_bss_param(struct cfg80211_bss *bss,
+ }
+ wmm_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+ WLAN_OUI_TYPE_MICROSOFT_WMM,
+- ies->data, ies->len);
++ ies_data, ies_len);
+ if (wmm_ie) {
+ struct ieee80211_wmm_param_ie *ie;
+
+@@ -477,13 +488,13 @@ wilc_parse_join_bss_param(struct cfg80211_bss *bss,
+
+ wpa_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
+ WLAN_OUI_TYPE_MICROSOFT_WPA,
+- ies->data, ies->len);
++ ies_data, ies_len);
+ if (wpa_ie) {
+ param->mode_802_11i = 1;
+ param->rsn_found = true;
+ }
+
+- rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, ies->data, ies->len);
++ rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, ies_data, ies_len);
+ if (rsn_ie) {
+ int rsn_ie_len = sizeof(struct element) + rsn_ie[1];
+ int offset = 8;
+@@ -517,6 +528,7 @@ wilc_parse_join_bss_param(struct cfg80211_bss *bss,
+ param->akm_suites[i] = crypto->akm_suites[i] & 0xFF;
+ }
+
++ kfree(ies_data);
+ return (void *)param;
+ }
+
+diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c
+index 81e8f25863f5b..6068699e44109 100644
+--- a/drivers/net/wireless/microchip/wilc1000/netdev.c
++++ b/drivers/net/wireless/microchip/wilc1000/netdev.c
+@@ -890,8 +890,7 @@ static const struct net_device_ops wilc_netdev_ops = {
+
+ void wilc_netdev_cleanup(struct wilc *wilc)
+ {
+- struct wilc_vif *vif;
+- int srcu_idx, ifc_cnt = 0;
++ struct wilc_vif *vif, *vif_tmp;
+
+ if (!wilc)
+ return;
+@@ -901,32 +900,19 @@ void wilc_netdev_cleanup(struct wilc *wilc)
+ wilc->firmware = NULL;
+ }
+
+- srcu_idx = srcu_read_lock(&wilc->srcu);
+- list_for_each_entry_rcu(vif, &wilc->vif_list, list) {
++ list_for_each_entry_safe(vif, vif_tmp, &wilc->vif_list, list) {
++ mutex_lock(&wilc->vif_mutex);
++ list_del_rcu(&vif->list);
++ wilc->vif_num--;
++ mutex_unlock(&wilc->vif_mutex);
++ synchronize_srcu(&wilc->srcu);
+ if (vif->ndev)
+ unregister_netdev(vif->ndev);
+ }
+- srcu_read_unlock(&wilc->srcu, srcu_idx);
+
+ wilc_wfi_deinit_mon_interface(wilc, false);
+ destroy_workqueue(wilc->hif_workqueue);
+
+- while (ifc_cnt < WILC_NUM_CONCURRENT_IFC) {
+- mutex_lock(&wilc->vif_mutex);
+- if (wilc->vif_num <= 0) {
+- mutex_unlock(&wilc->vif_mutex);
+- break;
+- }
+- vif = wilc_get_wl_to_vif(wilc);
+- if (!IS_ERR(vif))
+- list_del_rcu(&vif->list);
+-
+- wilc->vif_num--;
+- mutex_unlock(&wilc->vif_mutex);
+- synchronize_srcu(&wilc->srcu);
+- ifc_cnt++;
+- }
+-
+ wilc_wlan_cfg_deinit(wilc);
+ wlan_deinit_locks(wilc);
+ wiphy_unregister(wilc->wiphy);
+@@ -989,13 +975,6 @@ struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
+ goto error;
+ }
+
+- wl->hif_workqueue = alloc_ordered_workqueue("%s-wq", WQ_MEM_RECLAIM,
+- ndev->name);
+- if (!wl->hif_workqueue) {
+- ret = -ENOMEM;
+- goto unregister_netdev;
+- }
+-
+ ndev->needs_free_netdev = true;
+ vif->iftype = vif_type;
+ vif->idx = wilc_get_available_idx(wl);
+@@ -1008,12 +987,11 @@ struct wilc_vif *wilc_netdev_ifc_init(struct wilc *wl, const char *name,
+
+ return vif;
+
+-unregister_netdev:
++error:
+ if (rtnl_locked)
+ cfg80211_unregister_netdevice(ndev);
+ else
+ unregister_netdev(ndev);
+- error:
+ free_netdev(ndev);
+ return ERR_PTR(ret);
+ }
+diff --git a/drivers/net/wireless/microchip/wilc1000/spi.c b/drivers/net/wireless/microchip/wilc1000/spi.c
+index 1d8b241ce43ca..6a82b6ca2769e 100644
+--- a/drivers/net/wireless/microchip/wilc1000/spi.c
++++ b/drivers/net/wireless/microchip/wilc1000/spi.c
+@@ -192,11 +192,11 @@ static void wilc_wlan_power(struct wilc *wilc, bool on)
+ /* assert ENABLE: */
+ gpiod_set_value(gpios->enable, 1);
+ mdelay(5);
+- /* assert RESET: */
+- gpiod_set_value(gpios->reset, 1);
+- } else {
+ /* deassert RESET: */
+ gpiod_set_value(gpios->reset, 0);
++ } else {
++ /* assert RESET: */
++ gpiod_set_value(gpios->reset, 1);
+ /* deassert ENABLE: */
+ gpiod_set_value(gpios->enable, 0);
+ }
+diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+index 180907319e8cd..04df0f54aa667 100644
+--- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
++++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
+@@ -7304,6 +7304,7 @@ static void rtl8xxxu_stop(struct ieee80211_hw *hw)
+ if (priv->usb_interrupts)
+ rtl8xxxu_write32(priv, REG_USB_HIMR, 0);
+
++ cancel_work_sync(&priv->c2hcmd_work);
+ cancel_delayed_work_sync(&priv->ra_watchdog);
+
+ rtl8xxxu_free_rx_resources(priv);
+diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c
+index 6d22628129d0d..ffba6b88f392c 100644
+--- a/drivers/net/wireless/realtek/rtw88/main.c
++++ b/drivers/net/wireless/realtek/rtw88/main.c
+@@ -2032,8 +2032,6 @@ static int rtw_chip_board_info_setup(struct rtw_dev *rtwdev)
+ rtw_phy_setup_phy_cond(rtwdev, hal->pkg_type);
+
+ rtw_phy_init_tx_power(rtwdev);
+- if (rfe_def->agc_btg_tbl)
+- rtw_load_table(rtwdev, rfe_def->agc_btg_tbl);
+ rtw_load_table(rtwdev, rfe_def->phy_pg_tbl);
+ rtw_load_table(rtwdev, rfe_def->txpwr_lmt_tbl);
+ rtw_phy_tx_power_by_rate_config(hal);
+diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c
+index 128e75a81bf3c..37ef80c9091db 100644
+--- a/drivers/net/wireless/realtek/rtw88/phy.c
++++ b/drivers/net/wireless/realtek/rtw88/phy.c
+@@ -1761,12 +1761,15 @@ static void rtw_load_rfk_table(struct rtw_dev *rtwdev)
+
+ void rtw_phy_load_tables(struct rtw_dev *rtwdev)
+ {
++ const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev);
+ const struct rtw_chip_info *chip = rtwdev->chip;
+ u8 rf_path;
+
+ rtw_load_table(rtwdev, chip->mac_tbl);
+ rtw_load_table(rtwdev, chip->bb_tbl);
+ rtw_load_table(rtwdev, chip->agc_tbl);
++ if (rfe_def->agc_btg_tbl)
++ rtw_load_table(rtwdev, rfe_def->agc_btg_tbl);
+ rtw_load_rfk_table(rtwdev);
+
+ for (rf_path = 0; rf_path < rtwdev->hal.rf_path_num; rf_path++) {
+diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+index 429bb420b0563..fe5d8e1883509 100644
+--- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c
+@@ -773,9 +773,9 @@ static void rtw8821c_false_alarm_statistics(struct rtw_dev *rtwdev)
+
+ dm_info->cck_fa_cnt = cck_fa_cnt;
+ dm_info->ofdm_fa_cnt = ofdm_fa_cnt;
++ dm_info->total_fa_cnt = ofdm_fa_cnt;
+ if (cck_enable)
+ dm_info->total_fa_cnt += cck_fa_cnt;
+- dm_info->total_fa_cnt = ofdm_fa_cnt;
+
+ crc32_cnt = rtw_read32(rtwdev, REG_CRC_CCK);
+ dm_info->cck_ok_cnt = FIELD_GET(GENMASK(15, 0), crc32_cnt);
+diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
+index e6ab1ac6d7093..a0188511099a1 100644
+--- a/drivers/net/wireless/realtek/rtw88/usb.c
++++ b/drivers/net/wireless/realtek/rtw88/usb.c
+@@ -33,6 +33,36 @@ static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb,
+ rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data);
+ }
+
++static void rtw_usb_reg_sec(struct rtw_dev *rtwdev, u32 addr, __le32 *data)
++{
++ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
++ struct usb_device *udev = rtwusb->udev;
++ bool reg_on_section = false;
++ u16 t_reg = 0x4e0;
++ u8 t_len = 1;
++ int status;
++
++ /* There are three sections:
++ * 1. on (0x00~0xFF; 0x1000~0x10FF): this section is always powered on
++ * 2. off (< 0xFE00, excluding "on" section): this section could be
++ * powered off
++ * 3. local (>= 0xFE00): usb specific registers section
++ */
++ if (addr <= 0xff || (addr >= 0x1000 && addr <= 0x10ff))
++ reg_on_section = true;
++
++ if (!reg_on_section)
++ return;
++
++ status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
++ RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE,
++ t_reg, 0, data, t_len, 500);
++
++ if (status != t_len && status != -ENODEV)
++ rtw_err(rtwdev, "%s: reg 0x%x, usb write %u fail, status: %d\n",
++ __func__, t_reg, t_len, status);
++}
++
+ static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len)
+ {
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+@@ -58,6 +88,11 @@ static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len)
+ rtw_err(rtwdev, "read register 0x%x failed with %d\n",
+ addr, ret);
+
++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C ||
++ rtwdev->chip->id == RTW_CHIP_TYPE_8822B ||
++ rtwdev->chip->id == RTW_CHIP_TYPE_8821C)
++ rtw_usb_reg_sec(rtwdev, addr, data);
++
+ return le32_to_cpu(*data);
+ }
+
+@@ -102,6 +137,11 @@ static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len)
+ if (ret < 0 && ret != -ENODEV && count++ < 4)
+ rtw_err(rtwdev, "write register 0x%x failed with %d\n",
+ addr, ret);
++
++ if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C ||
++ rtwdev->chip->id == RTW_CHIP_TYPE_8822B ||
++ rtwdev->chip->id == RTW_CHIP_TYPE_8821C)
++ rtw_usb_reg_sec(rtwdev, addr, data);
+ }
+
+ static void rtw_usb_write8(struct rtw_dev *rtwdev, u32 addr, u8 val)
+diff --git a/drivers/net/wireless/silabs/wfx/sta.c b/drivers/net/wireless/silabs/wfx/sta.c
+index 537caf9d914a7..bb4446b88c12b 100644
+--- a/drivers/net/wireless/silabs/wfx/sta.c
++++ b/drivers/net/wireless/silabs/wfx/sta.c
+@@ -344,6 +344,7 @@ static int wfx_set_mfp_ap(struct wfx_vif *wvif)
+ const int pairwise_cipher_suite_count_offset = 8 / sizeof(u16);
+ const int pairwise_cipher_suite_size = 4 / sizeof(u16);
+ const int akm_suite_size = 4 / sizeof(u16);
++ int ret = -EINVAL;
+ const u16 *ptr;
+
+ if (unlikely(!skb))
+@@ -352,22 +353,26 @@ static int wfx_set_mfp_ap(struct wfx_vif *wvif)
+ ptr = (u16 *)cfg80211_find_ie(WLAN_EID_RSN, skb->data + ieoffset,
+ skb->len - ieoffset);
+ if (unlikely(!ptr))
+- return -EINVAL;
++ goto free_skb;
+
+ ptr += pairwise_cipher_suite_count_offset;
+ if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
+- return -EINVAL;
++ goto free_skb;
+
+ ptr += 1 + pairwise_cipher_suite_size * *ptr;
+ if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
+- return -EINVAL;
++ goto free_skb;
+
+ ptr += 1 + akm_suite_size * *ptr;
+ if (WARN_ON(ptr > (u16 *)skb_tail_pointer(skb)))
+- return -EINVAL;
++ goto free_skb;
+
+ wfx_hif_set_mfp(wvif, *ptr & BIT(7), *ptr & BIT(6));
+- return 0;
++ ret = 0;
++
++free_skb:
++ dev_kfree_skb(skb);
++ return ret;
+ }
+
+ int wfx_start_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+diff --git a/drivers/ntb/core.c b/drivers/ntb/core.c
+index 27dd93deff6e5..d702bee780826 100644
+--- a/drivers/ntb/core.c
++++ b/drivers/ntb/core.c
+@@ -100,6 +100,8 @@ EXPORT_SYMBOL(ntb_unregister_client);
+
+ int ntb_register_device(struct ntb_dev *ntb)
+ {
++ int ret;
++
+ if (!ntb)
+ return -EINVAL;
+ if (!ntb->pdev)
+@@ -120,7 +122,11 @@ int ntb_register_device(struct ntb_dev *ntb)
+ ntb->ctx_ops = NULL;
+ spin_lock_init(&ntb->ctx_lock);
+
+- return device_register(&ntb->dev);
++ ret = device_register(&ntb->dev);
++ if (ret)
++ put_device(&ntb->dev);
++
++ return ret;
+ }
+ EXPORT_SYMBOL(ntb_register_device);
+
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index 0a96362912ced..fe3627c5bdc99 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -4359,7 +4359,8 @@ int nvme_alloc_admin_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set,
+ set->ops = ops;
+ set->queue_depth = NVME_AQ_MQ_TAG_DEPTH;
+ if (ctrl->ops->flags & NVME_F_FABRICS)
+- set->reserved_tags = NVMF_RESERVED_TAGS;
++ /* Reserved for fabric connect and keep alive */
++ set->reserved_tags = 2;
+ set->numa_node = ctrl->numa_node;
+ set->flags = BLK_MQ_F_NO_SCHED;
+ if (ctrl->ops->flags & NVME_F_BLOCKING)
+@@ -4428,7 +4429,8 @@ int nvme_alloc_io_tag_set(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set,
+ if (ctrl->quirks & NVME_QUIRK_SHARED_TAGS)
+ set->reserved_tags = NVME_AQ_DEPTH;
+ else if (ctrl->ops->flags & NVME_F_FABRICS)
+- set->reserved_tags = NVMF_RESERVED_TAGS;
++ /* Reserved for fabric connect */
++ set->reserved_tags = 1;
+ set->numa_node = ctrl->numa_node;
+ set->flags = BLK_MQ_F_SHOULD_MERGE;
+ if (ctrl->ops->flags & NVME_F_BLOCKING)
+diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h
+index 06cc54851b1be..37c974c38dcb0 100644
+--- a/drivers/nvme/host/fabrics.h
++++ b/drivers/nvme/host/fabrics.h
+@@ -18,13 +18,6 @@
+ /* default is -1: the fail fast mechanism is disabled */
+ #define NVMF_DEF_FAIL_FAST_TMO -1
+
+-/*
+- * Reserved one command for internal usage. This command is used for sending
+- * the connect command, as well as for the keep alive command on the admin
+- * queue once live.
+- */
+-#define NVMF_RESERVED_TAGS 1
+-
+ /*
+ * Define a host as seen by the target. We allocate one at boot, but also
+ * allow the override it when creating controllers. This is both to provide
+diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c
+index f2832f70e7e0a..09fcaa519e5bc 100644
+--- a/drivers/nvme/host/sysfs.c
++++ b/drivers/nvme/host/sysfs.c
+@@ -221,14 +221,11 @@ static int ns_update_nuse(struct nvme_ns *ns)
+
+ ret = nvme_identify_ns(ns->ctrl, ns->head->ns_id, &id);
+ if (ret)
+- goto out_free_id;
++ return ret;
+
+ ns->head->nuse = le64_to_cpu(id->nuse);
+-
+-out_free_id:
+ kfree(id);
+-
+- return ret;
++ return 0;
+ }
+
+ static ssize_t nuse_show(struct device *dev, struct device_attribute *attr,
+diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c
+index ec030b19164a3..f157fb50be50c 100644
+--- a/drivers/opp/debugfs.c
++++ b/drivers/opp/debugfs.c
+@@ -37,10 +37,12 @@ static ssize_t bw_name_read(struct file *fp, char __user *userbuf,
+ size_t count, loff_t *ppos)
+ {
+ struct icc_path *path = fp->private_data;
++ const char *name = icc_get_name(path);
+ char buf[64];
+- int i;
++ int i = 0;
+
+- i = scnprintf(buf, sizeof(buf), "%.62s\n", icc_get_name(path));
++ if (name)
++ i = scnprintf(buf, sizeof(buf), "%.62s\n", name);
+
+ return simple_read_from_buffer(userbuf, count, ppos, buf, i);
+ }
+diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
+index 5b0730c3891b8..c08683febdd40 100644
+--- a/drivers/pci/controller/pcie-brcmstb.c
++++ b/drivers/pci/controller/pcie-brcmstb.c
+@@ -336,7 +336,7 @@ static int brcm_pcie_mdio_write(void __iomem *base, u8 port,
+ readl(base + PCIE_RC_DL_MDIO_ADDR);
+ writel(MDIO_DATA_DONE_MASK | wrdata, base + PCIE_RC_DL_MDIO_WR_DATA);
+
+- err = readw_poll_timeout_atomic(base + PCIE_RC_DL_MDIO_WR_DATA, data,
++ err = readl_poll_timeout_atomic(base + PCIE_RC_DL_MDIO_WR_DATA, data,
+ MDIO_WT_DONE(data), 10, 100);
+ return err;
+ }
+diff --git a/drivers/pci/endpoint/functions/pci-epf-vntb.c b/drivers/pci/endpoint/functions/pci-epf-vntb.c
+index e75a2af77328e..5b84821c0d602 100644
+--- a/drivers/pci/endpoint/functions/pci-epf-vntb.c
++++ b/drivers/pci/endpoint/functions/pci-epf-vntb.c
+@@ -1275,15 +1275,11 @@ static int pci_vntb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ ret = ntb_register_device(&ndev->ntb);
+ if (ret) {
+ dev_err(dev, "Failed to register NTB device\n");
+- goto err_register_dev;
++ return ret;
+ }
+
+ dev_dbg(dev, "PCI Virtual NTB driver loaded\n");
+ return 0;
+-
+-err_register_dev:
+- put_device(&ndev->ntb.dev);
+- return -EINVAL;
+ }
+
+ static struct pci_device_id pci_vntb_table[] = {
+diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
+index 0c361561b855c..4f47a13cb500f 100644
+--- a/drivers/pci/p2pdma.c
++++ b/drivers/pci/p2pdma.c
+@@ -661,7 +661,7 @@ calc_map_type_and_dist(struct pci_dev *provider, struct pci_dev *client,
+ p2pdma = rcu_dereference(provider->p2pdma);
+ if (p2pdma)
+ xa_store(&p2pdma->map_types, map_types_idx(client),
+- xa_mk_value(map_type), GFP_KERNEL);
++ xa_mk_value(map_type), GFP_ATOMIC);
+ rcu_read_unlock();
+ return map_type;
+ }
+diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
+index e9750b1b19bad..bfc56f7bee1c9 100644
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -368,11 +368,6 @@ static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
+ return 0;
+ }
+
+-static inline bool pci_dev_is_disconnected(const struct pci_dev *dev)
+-{
+- return dev->error_state == pci_channel_io_perm_failure;
+-}
+-
+ /* pci_dev priv_flags */
+ #define PCI_DEV_ADDED 0
+ #define PCI_DPC_RECOVERED 1
+diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c
+index 94111e4382413..e5d7c12854fa0 100644
+--- a/drivers/pci/pcie/dpc.c
++++ b/drivers/pci/pcie/dpc.c
+@@ -234,7 +234,7 @@ static void dpc_process_rp_pio_error(struct pci_dev *pdev)
+
+ for (i = 0; i < pdev->dpc_rp_log_size - 5; i++) {
+ pci_read_config_dword(pdev,
+- cap + PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG, &prefix);
++ cap + PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG + i * 4, &prefix);
+ pci_err(pdev, "TLP Prefix Header: dw%d, %#010x\n", i, prefix);
+ }
+ clear_status:
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index d797df6e5f3e9..2ebbe51a7efe0 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -5527,6 +5527,7 @@ static void quirk_no_ext_tags(struct pci_dev *pdev)
+
+ pci_walk_bus(bridge->bus, pci_configure_extended_tags, NULL);
+ }
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_3WARE, 0x1004, quirk_no_ext_tags);
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0132, quirk_no_ext_tags);
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0140, quirk_no_ext_tags);
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0141, quirk_no_ext_tags);
+diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
+index 1804794d0e686..5a4adf6c04cf8 100644
+--- a/drivers/pci/switch/switchtec.c
++++ b/drivers/pci/switch/switchtec.c
+@@ -1672,7 +1672,7 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
+ rc = switchtec_init_isr(stdev);
+ if (rc) {
+ dev_err(&stdev->dev, "failed to init isr.\n");
+- goto err_put;
++ goto err_exit_pci;
+ }
+
+ iowrite32(SWITCHTEC_EVENT_CLEAR |
+@@ -1693,6 +1693,8 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
+
+ err_devadd:
+ stdev_kill(stdev);
++err_exit_pci:
++ switchtec_exit_pci(stdev);
+ err_put:
+ ida_free(&switchtec_minor_ida, MINOR(stdev->dev.devt));
+ put_device(&stdev->dev);
+diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile
+index ffd609ac62336..eb60e950ad533 100644
+--- a/drivers/phy/qualcomm/Makefile
++++ b/drivers/phy/qualcomm/Makefile
+@@ -7,7 +7,7 @@ obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
+ obj-$(CONFIG_PHY_QCOM_M31_USB) += phy-qcom-m31.o
+ obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o
+
+-obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o
++obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o
+ obj-$(CONFIG_PHY_QCOM_QMP_PCIE) += phy-qcom-qmp-pcie.o
+ obj-$(CONFIG_PHY_QCOM_QMP_PCIE_8996) += phy-qcom-qmp-pcie-msm8996.o
+ obj-$(CONFIG_PHY_QCOM_QMP_UFS) += phy-qcom-qmp-ufs.o
+diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
+index 5c003988c35d3..4c32304dae87f 100644
+--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
+@@ -121,15 +121,6 @@ static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
+ [QPHY_PCS_MISC_CLAMP_ENABLE] = QPHY_V3_PCS_MISC_CLAMP_ENABLE,
+ };
+
+-static const unsigned int qmp_v3_usb3phy_regs_layout_qcm2290[QPHY_LAYOUT_SIZE] = {
+- [QPHY_SW_RESET] = QPHY_V3_PCS_SW_RESET,
+- [QPHY_START_CTRL] = QPHY_V3_PCS_START_CONTROL,
+- [QPHY_PCS_STATUS] = QPHY_V3_PCS_PCS_STATUS,
+- [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V3_PCS_AUTONOMOUS_MODE_CTRL,
+- [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V3_PCS_LFPS_RXTERM_IRQ_CLEAR,
+- [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V3_PCS_POWER_DOWN_CONTROL,
+-};
+-
+ static const unsigned int qmp_v4_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
+ [QPHY_SW_RESET] = QPHY_V4_PCS_SW_RESET,
+ [QPHY_START_CTRL] = QPHY_V4_PCS_START_CONTROL,
+@@ -514,115 +505,6 @@ static const struct qmp_phy_init_tbl qmp_v3_usb3_uniphy_pcs_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V3_PCS_REFGEN_REQ_CONFIG2, 0x60),
+ };
+
+-static const struct qmp_phy_init_tbl msm8998_usb3_serdes_tbl[] = {
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x06),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_INITVAL, 0x80),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85),
+- QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07),
+-};
+-
+-static const struct qmp_phy_init_tbl msm8998_usb3_tx_tbl[] = {
+- QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10),
+- QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12),
+- QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16),
+- QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00),
+-};
+-
+-static const struct qmp_phy_init_tbl msm8998_usb3_rx_tbl[] = {
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x07),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x43),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x03),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x05),
+-};
+-
+-static const struct qmp_phy_init_tbl msm8998_usb3_pcs_tbl[] = {
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x0d),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x8a),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
+-};
+-
+ static const struct qmp_phy_init_tbl sm8150_usb3_uniphy_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_SYSCLK_EN_SEL, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V4_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
+@@ -1089,99 +971,6 @@ static const struct qmp_phy_init_tbl sm8350_usb3_uniphy_pcs_usb_tbl[] = {
+ QMP_PHY_INIT_CFG(QPHY_V5_PCS_USB3_LFPS_DET_HIGH_COUNT_VAL, 0xf8),
+ };
+
+-static const struct qmp_phy_init_tbl qcm2290_usb3_serdes_tbl[] = {
+- QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14),
+- QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
+- QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30),
+- QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06),
+- QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL2, 0x08),
+- QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
+- QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01),
+- QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
+- QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55),
+- QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55),
+- QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03),
+- QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
+- QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
+- QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
+- QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
+- QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a),
+- QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15),
+- QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34),
+- QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a),
+- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01),
+- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
+- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01),
+- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde),
+- QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07),
+- QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
+- QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06),
+- QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_INITVAL, 0x80),
+- QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x01),
+-};
+-
+-static const struct qmp_phy_init_tbl qcm2290_usb3_tx_tbl[] = {
+- QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10),
+- QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12),
+- QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6),
+- QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x00),
+-};
+-
+-static const struct qmp_phy_init_tbl qcm2290_usb3_rx_tbl[] = {
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0a),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00),
+- QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x00),
+-};
+-
+-static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = {
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00),
+- QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88),
+-};
+-
+ static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_serdes_tbl[] = {
+ QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0x1a),
+ QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11),
+@@ -1579,16 +1368,6 @@ static const struct qmp_usb_offsets qmp_usb_offsets_v3_msm8996 = {
+ .rx = 0x400,
+ };
+
+-static const struct qmp_usb_offsets qmp_usb_offsets_v3_qcm2290 = {
+- .serdes = 0x0,
+- .pcs = 0xc00,
+- .pcs_misc = 0xa00,
+- .tx = 0x200,
+- .rx = 0x400,
+- .tx2 = 0x600,
+- .rx2 = 0x800,
+-};
+-
+ static const struct qmp_usb_offsets qmp_usb_offsets_v4 = {
+ .serdes = 0,
+ .pcs = 0x0800,
+@@ -1753,24 +1532,6 @@ static const struct qmp_phy_cfg qmp_v3_usb3_uniphy_cfg = {
+ .has_pwrdn_delay = true,
+ };
+
+-static const struct qmp_phy_cfg msm8998_usb3phy_cfg = {
+- .lanes = 2,
+-
+- .offsets = &qmp_usb_offsets_v3_qcm2290,
+-
+- .serdes_tbl = msm8998_usb3_serdes_tbl,
+- .serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl),
+- .tx_tbl = msm8998_usb3_tx_tbl,
+- .tx_tbl_num = ARRAY_SIZE(msm8998_usb3_tx_tbl),
+- .rx_tbl = msm8998_usb3_rx_tbl,
+- .rx_tbl_num = ARRAY_SIZE(msm8998_usb3_rx_tbl),
+- .pcs_tbl = msm8998_usb3_pcs_tbl,
+- .pcs_tbl_num = ARRAY_SIZE(msm8998_usb3_pcs_tbl),
+- .vreg_list = qmp_phy_vreg_l,
+- .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+- .regs = qmp_v3_usb3phy_regs_layout,
+-};
+-
+ static const struct qmp_phy_cfg sm8150_usb3_uniphy_cfg = {
+ .lanes = 1,
+
+@@ -1908,24 +1669,6 @@ static const struct qmp_phy_cfg sm8350_usb3_uniphy_cfg = {
+ .has_pwrdn_delay = true,
+ };
+
+-static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = {
+- .lanes = 2,
+-
+- .offsets = &qmp_usb_offsets_v3_qcm2290,
+-
+- .serdes_tbl = qcm2290_usb3_serdes_tbl,
+- .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl),
+- .tx_tbl = qcm2290_usb3_tx_tbl,
+- .tx_tbl_num = ARRAY_SIZE(qcm2290_usb3_tx_tbl),
+- .rx_tbl = qcm2290_usb3_rx_tbl,
+- .rx_tbl_num = ARRAY_SIZE(qcm2290_usb3_rx_tbl),
+- .pcs_tbl = qcm2290_usb3_pcs_tbl,
+- .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl),
+- .vreg_list = qmp_phy_vreg_l,
+- .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
+- .regs = qmp_v3_usb3phy_regs_layout_qcm2290,
+-};
+-
+ static const struct qmp_phy_cfg x1e80100_usb3_uniphy_cfg = {
+ .lanes = 1,
+
+@@ -2599,12 +2342,6 @@ static const struct of_device_id qmp_usb_of_match_table[] = {
+ }, {
+ .compatible = "qcom,msm8996-qmp-usb3-phy",
+ .data = &msm8996_usb3phy_cfg,
+- }, {
+- .compatible = "qcom,msm8998-qmp-usb3-phy",
+- .data = &msm8998_usb3phy_cfg,
+- }, {
+- .compatible = "qcom,qcm2290-qmp-usb3-phy",
+- .data = &qcm2290_usb3phy_cfg,
+ }, {
+ .compatible = "qcom,sa8775p-qmp-usb3-uni-phy",
+ .data = &sa8775p_usb3_uniphy_cfg,
+@@ -2623,9 +2360,6 @@ static const struct of_device_id qmp_usb_of_match_table[] = {
+ }, {
+ .compatible = "qcom,sdx75-qmp-usb3-uni-phy",
+ .data = &sdx75_usb3_uniphy_cfg,
+- }, {
+- .compatible = "qcom,sm6115-qmp-usb3-phy",
+- .data = &qcm2290_usb3phy_cfg,
+ }, {
+ .compatible = "qcom,sm8150-qmp-usb3-uni-phy",
+ .data = &sm8150_usb3_uniphy_cfg,
+diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
+new file mode 100644
+index 0000000000000..3a4b4849db0f5
+--- /dev/null
++++ b/drivers/phy/qualcomm/phy-qcom-qmp-usbc.c
+@@ -0,0 +1,1195 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
++ */
++
++#include <linux/clk.h>
++#include <linux/clk-provider.h>
++#include <linux/delay.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/iopoll.h>
++#include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_address.h>
++#include <linux/phy/phy.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/regulator/consumer.h>
++#include <linux/reset.h>
++#include <linux/slab.h>
++#include <linux/usb/typec.h>
++#include <linux/usb/typec_mux.h>
++
++#include "phy-qcom-qmp.h"
++#include "phy-qcom-qmp-pcs-misc-v3.h"
++
++/* QPHY_SW_RESET bit */
++#define SW_RESET BIT(0)
++/* QPHY_POWER_DOWN_CONTROL */
++#define SW_PWRDN BIT(0)
++/* QPHY_START_CONTROL bits */
++#define SERDES_START BIT(0)
++#define PCS_START BIT(1)
++/* QPHY_PCS_STATUS bit */
++#define PHYSTATUS BIT(6)
++
++/* QPHY_V3_DP_COM_RESET_OVRD_CTRL register bits */
++/* DP PHY soft reset */
++#define SW_DPPHY_RESET BIT(0)
++/* mux to select DP PHY reset control, 0:HW control, 1: software reset */
++#define SW_DPPHY_RESET_MUX BIT(1)
++/* USB3 PHY soft reset */
++#define SW_USB3PHY_RESET BIT(2)
++/* mux to select USB3 PHY reset control, 0:HW control, 1: software reset */
++#define SW_USB3PHY_RESET_MUX BIT(3)
++
++/* QPHY_V3_DP_COM_PHY_MODE_CTRL register bits */
++#define USB3_MODE BIT(0) /* enables USB3 mode */
++#define DP_MODE BIT(1) /* enables DP mode */
++
++/* QPHY_PCS_AUTONOMOUS_MODE_CTRL register bits */
++#define ARCVR_DTCT_EN BIT(0)
++#define ALFPS_DTCT_EN BIT(1)
++#define ARCVR_DTCT_EVENT_SEL BIT(4)
++
++/* QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR register bits */
++#define IRQ_CLEAR BIT(0)
++
++#define PHY_INIT_COMPLETE_TIMEOUT 10000
++
++struct qmp_phy_init_tbl {
++ unsigned int offset;
++ unsigned int val;
++ /*
++ * mask of lanes for which this register is written
++ * for cases when second lane needs different values
++ */
++ u8 lane_mask;
++};
++
++#define QMP_PHY_INIT_CFG(o, v) \
++ { \
++ .offset = o, \
++ .val = v, \
++ .lane_mask = 0xff, \
++ }
++
++#define QMP_PHY_INIT_CFG_LANE(o, v, l) \
++ { \
++ .offset = o, \
++ .val = v, \
++ .lane_mask = l, \
++ }
++
++/* set of registers with offsets different per-PHY */
++enum qphy_reg_layout {
++ /* PCS registers */
++ QPHY_SW_RESET,
++ QPHY_START_CTRL,
++ QPHY_PCS_STATUS,
++ QPHY_PCS_AUTONOMOUS_MODE_CTRL,
++ QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR,
++ QPHY_PCS_POWER_DOWN_CONTROL,
++ /* Keep last to ensure regs_layout arrays are properly initialized */
++ QPHY_LAYOUT_SIZE
++};
++
++static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
++ [QPHY_SW_RESET] = QPHY_V3_PCS_SW_RESET,
++ [QPHY_START_CTRL] = QPHY_V3_PCS_START_CONTROL,
++ [QPHY_PCS_STATUS] = QPHY_V3_PCS_PCS_STATUS,
++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V3_PCS_AUTONOMOUS_MODE_CTRL,
++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V3_PCS_LFPS_RXTERM_IRQ_CLEAR,
++ [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V3_PCS_POWER_DOWN_CONTROL,
++};
++
++static const unsigned int qmp_v3_usb3phy_regs_layout_qcm2290[QPHY_LAYOUT_SIZE] = {
++ [QPHY_SW_RESET] = QPHY_V3_PCS_SW_RESET,
++ [QPHY_START_CTRL] = QPHY_V3_PCS_START_CONTROL,
++ [QPHY_PCS_STATUS] = QPHY_V3_PCS_PCS_STATUS,
++ [QPHY_PCS_AUTONOMOUS_MODE_CTRL] = QPHY_V3_PCS_AUTONOMOUS_MODE_CTRL,
++ [QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR] = QPHY_V3_PCS_LFPS_RXTERM_IRQ_CLEAR,
++ [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V3_PCS_POWER_DOWN_CONTROL,
++};
++
++static const struct qmp_phy_init_tbl msm8998_usb3_serdes_tbl[] = {
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CLK_SELECT, 0x30),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x04),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYSCLK_EN_SEL, 0x14),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SYS_CLK_CTRL, 0x06),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_RESETSM_CNTRL2, 0x08),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_CONFIG, 0x06),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SVS_MODE_CLK_SEL, 0x01),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_HSCLK_SEL, 0x80),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DEC_START_MODE0, 0x82),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START1_MODE0, 0xab),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START2_MODE0, 0xea),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_DIV_FRAC_START3_MODE0, 0x02),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CP_CTRL_MODE0, 0x06),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x36),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, 0x3f),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE2_MODE0, 0x01),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE1_MODE0, 0xc9),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORECLK_DIV_MODE0, 0x0a),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP3_MODE0, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP2_MODE0, 0x34),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP1_MODE0, 0x15),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_EN, 0x04),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CORE_CLK_EN, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_LOCK_CMP_CFG, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_VCO_TUNE_MAP, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_BG_TIMER, 0x0a),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_PLL_IVCO, 0x07),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_INTEGLOOP_INITVAL, 0x80),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_CMN_MODE, 0x01),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_EN_CENTER, 0x01),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER1, 0x31),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_PER2, 0x01),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER1, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_ADJ_PER2, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE1, 0x85),
++ QMP_PHY_INIT_CFG(QSERDES_V3_COM_SSC_STEP_SIZE2, 0x07),
++};
++
++static const struct qmp_phy_init_tbl msm8998_usb3_tx_tbl[] = {
++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10),
++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12),
++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0x16),
++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00),
++};
++
++static const struct qmp_phy_init_tbl msm8998_usb3_rx_tbl[] = {
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x07),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x43),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x1c),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x03),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x05),
++};
++
++static const struct qmp_phy_init_tbl msm8998_usb3_pcs_tbl[] = {
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x40),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_POWER_STATE_CONFIG2, 0x1b),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V1, 0x9f),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V2, 0xb7),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V3, 0x4e),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V4, 0x65),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_LS, 0x6b),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x15),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0d),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V1, 0x15),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V1, 0x0d),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V2, 0x15),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V2, 0x0d),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V3, 0x15),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V3, 0x0d),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V4, 0x15),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V4, 0x0d),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_LS, 0x15),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_LS, 0x0d),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RATE_SLEW_CNTRL, 0x02),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x8a),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
++};
++
++static const struct qmp_phy_init_tbl qcm2290_usb3_serdes_tbl[] = {
++ QMP_PHY_INIT_CFG(QSERDES_COM_SYSCLK_EN_SEL, 0x14),
++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x08),
++ QMP_PHY_INIT_CFG(QSERDES_COM_CLK_SELECT, 0x30),
++ QMP_PHY_INIT_CFG(QSERDES_COM_SYS_CLK_CTRL, 0x06),
++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_COM_RESETSM_CNTRL2, 0x08),
++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TRIM, 0x0f),
++ QMP_PHY_INIT_CFG(QSERDES_COM_SVS_MODE_CLK_SEL, 0x01),
++ QMP_PHY_INIT_CFG(QSERDES_COM_HSCLK_SEL, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_COM_DEC_START_MODE0, 0x82),
++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START1_MODE0, 0x55),
++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START2_MODE0, 0x55),
++ QMP_PHY_INIT_CFG(QSERDES_COM_DIV_FRAC_START3_MODE0, 0x03),
++ QMP_PHY_INIT_CFG(QSERDES_COM_CP_CTRL_MODE0, 0x0b),
++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_RCTRL_MODE0, 0x16),
++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_CCTRL_MODE0, 0x28),
++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN0_MODE0, 0x80),
++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_GAIN1_MODE0, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_COM_CORECLK_DIV, 0x0a),
++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP1_MODE0, 0x15),
++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP2_MODE0, 0x34),
++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP3_MODE0, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_EN, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_COM_CORE_CLK_EN, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_COM_LOCK_CMP_CFG, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_COM_VCO_TUNE_MAP, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_COM_BG_TIMER, 0x0a),
++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_EN_CENTER, 0x01),
++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER1, 0x31),
++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_PER2, 0x01),
++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER1, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_ADJ_PER2, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE1, 0xde),
++ QMP_PHY_INIT_CFG(QSERDES_COM_SSC_STEP_SIZE2, 0x07),
++ QMP_PHY_INIT_CFG(QSERDES_COM_PLL_IVCO, 0x0f),
++ QMP_PHY_INIT_CFG(QSERDES_COM_CMN_CONFIG, 0x06),
++ QMP_PHY_INIT_CFG(QSERDES_COM_INTEGLOOP_INITVAL, 0x80),
++ QMP_PHY_INIT_CFG(QSERDES_COM_BIAS_EN_CTRL_BY_PSM, 0x01),
++};
++
++static const struct qmp_phy_init_tbl qcm2290_usb3_tx_tbl[] = {
++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_HIGHZ_DRVR_EN, 0x10),
++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RCV_DETECT_LVL_2, 0x12),
++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_LANE_MODE_1, 0xc6),
++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_TX, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_TX_RES_CODE_LANE_OFFSET_RX, 0x00),
++};
++
++static const struct qmp_phy_init_tbl qcm2290_usb3_rx_tbl[] = {
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_FO_GAIN, 0x0b),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_PI_CONTROLS, 0x80),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_LOW, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_FO_GAIN, 0x0a),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_GAIN, 0x06),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x75),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL2, 0x02),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4e),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQU_ADAPTOR_CNTRL4, 0x18),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x77),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x80),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_VGA_CAL_CNTRL2, 0x0a),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_CNTRL, 0x03),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_DEGLITCH_CNTRL, 0x16),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_SIGDET_ENABLES, 0x00),
++ QMP_PHY_INIT_CFG(QSERDES_V3_RX_RX_MODE_00, 0x00),
++};
++
++static const struct qmp_phy_init_tbl qcm2290_usb3_pcs_tbl[] = {
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXMGN_V0, 0x9f),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M6DB_V0, 0x17),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TXDEEMPH_M3P5DB_V0, 0x0f),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL2, 0x83),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNTRL1, 0x02),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_L, 0x09),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_CNT_VAL_H_TOL, 0xa2),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_FLL_MAN_CODE, 0x85),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG1, 0xd1),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG2, 0x1f),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LOCK_DETECT_CONFIG3, 0x47),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_WAIT_TIME, 0x75),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RXEQTRAINING_RUN_TIME, 0x13),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_LFPS_TX_ECSTART_EQTLOCK, 0x86),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_PWRUP_RESET_DLY_TIME_AUXCLK, 0x04),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_TSYNC_RSYNC_TIME, 0x44),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_L, 0xe7),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_P1U2_H, 0x03),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_L, 0x40),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RCVR_DTCT_DLY_U3_H, 0x00),
++ QMP_PHY_INIT_CFG(QPHY_V3_PCS_RX_SIGDET_LVL, 0x88),
++};
++
++struct qmp_usbc_offsets {
++ u16 serdes;
++ u16 pcs;
++ u16 pcs_misc;
++ u16 tx;
++ u16 rx;
++ /* for PHYs with >= 2 lanes */
++ u16 tx2;
++ u16 rx2;
++};
++
++/* struct qmp_phy_cfg - per-PHY initialization config */
++struct qmp_phy_cfg {
++ const struct qmp_usbc_offsets *offsets;
++
++ /* Init sequence for PHY blocks - serdes, tx, rx, pcs */
++ const struct qmp_phy_init_tbl *serdes_tbl;
++ int serdes_tbl_num;
++ const struct qmp_phy_init_tbl *tx_tbl;
++ int tx_tbl_num;
++ const struct qmp_phy_init_tbl *rx_tbl;
++ int rx_tbl_num;
++ const struct qmp_phy_init_tbl *pcs_tbl;
++ int pcs_tbl_num;
++
++ /* regulators to be requested */
++ const char * const *vreg_list;
++ int num_vregs;
++
++ /* array of registers with different offsets */
++ const unsigned int *regs;
++
++ /* true, if PHY needs delay after POWER_DOWN */
++ bool has_pwrdn_delay;
++};
++
++struct qmp_usbc {
++ struct device *dev;
++
++ const struct qmp_phy_cfg *cfg;
++
++ void __iomem *serdes;
++ void __iomem *pcs;
++ void __iomem *pcs_misc;
++ void __iomem *tx;
++ void __iomem *rx;
++ void __iomem *tx2;
++ void __iomem *rx2;
++
++ struct regmap *tcsr_map;
++ u32 vls_clamp_reg;
++
++ struct clk *pipe_clk;
++ struct clk_bulk_data *clks;
++ int num_clks;
++ int num_resets;
++ struct reset_control_bulk_data *resets;
++ struct regulator_bulk_data *vregs;
++
++ struct mutex phy_mutex;
++
++ enum phy_mode mode;
++ unsigned int usb_init_count;
++
++ struct phy *phy;
++
++ struct clk_fixed_rate pipe_clk_fixed;
++
++ struct typec_switch_dev *sw;
++ enum typec_orientation orientation;
++};
++
++static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val)
++{
++ u32 reg;
++
++ reg = readl(base + offset);
++ reg |= val;
++ writel(reg, base + offset);
++
++ /* ensure that above write is through */
++ readl(base + offset);
++}
++
++static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val)
++{
++ u32 reg;
++
++ reg = readl(base + offset);
++ reg &= ~val;
++ writel(reg, base + offset);
++
++ /* ensure that above write is through */
++ readl(base + offset);
++}
++
++/* list of clocks required by phy */
++static const char * const qmp_usbc_phy_clk_l[] = {
++ "aux", "cfg_ahb", "ref", "com_aux",
++};
++
++/* list of resets */
++static const char * const usb3phy_legacy_reset_l[] = {
++ "phy", "common",
++};
++
++static const char * const usb3phy_reset_l[] = {
++ "phy_phy", "phy",
++};
++
++/* list of regulators */
++static const char * const qmp_phy_vreg_l[] = {
++ "vdda-phy", "vdda-pll",
++};
++
++static const struct qmp_usbc_offsets qmp_usbc_offsets_v3_qcm2290 = {
++ .serdes = 0x0,
++ .pcs = 0xc00,
++ .pcs_misc = 0xa00,
++ .tx = 0x200,
++ .rx = 0x400,
++ .tx2 = 0x600,
++ .rx2 = 0x800,
++};
++
++static const struct qmp_phy_cfg msm8998_usb3phy_cfg = {
++ .offsets = &qmp_usbc_offsets_v3_qcm2290,
++
++ .serdes_tbl = msm8998_usb3_serdes_tbl,
++ .serdes_tbl_num = ARRAY_SIZE(msm8998_usb3_serdes_tbl),
++ .tx_tbl = msm8998_usb3_tx_tbl,
++ .tx_tbl_num = ARRAY_SIZE(msm8998_usb3_tx_tbl),
++ .rx_tbl = msm8998_usb3_rx_tbl,
++ .rx_tbl_num = ARRAY_SIZE(msm8998_usb3_rx_tbl),
++ .pcs_tbl = msm8998_usb3_pcs_tbl,
++ .pcs_tbl_num = ARRAY_SIZE(msm8998_usb3_pcs_tbl),
++ .vreg_list = qmp_phy_vreg_l,
++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
++ .regs = qmp_v3_usb3phy_regs_layout,
++};
++
++static const struct qmp_phy_cfg qcm2290_usb3phy_cfg = {
++ .offsets = &qmp_usbc_offsets_v3_qcm2290,
++
++ .serdes_tbl = qcm2290_usb3_serdes_tbl,
++ .serdes_tbl_num = ARRAY_SIZE(qcm2290_usb3_serdes_tbl),
++ .tx_tbl = qcm2290_usb3_tx_tbl,
++ .tx_tbl_num = ARRAY_SIZE(qcm2290_usb3_tx_tbl),
++ .rx_tbl = qcm2290_usb3_rx_tbl,
++ .rx_tbl_num = ARRAY_SIZE(qcm2290_usb3_rx_tbl),
++ .pcs_tbl = qcm2290_usb3_pcs_tbl,
++ .pcs_tbl_num = ARRAY_SIZE(qcm2290_usb3_pcs_tbl),
++ .vreg_list = qmp_phy_vreg_l,
++ .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l),
++ .regs = qmp_v3_usb3phy_regs_layout_qcm2290,
++};
++
++static void qmp_usbc_configure_lane(void __iomem *base,
++ const struct qmp_phy_init_tbl tbl[],
++ int num,
++ u8 lane_mask)
++{
++ int i;
++ const struct qmp_phy_init_tbl *t = tbl;
++
++ if (!t)
++ return;
++
++ for (i = 0; i < num; i++, t++) {
++ if (!(t->lane_mask & lane_mask))
++ continue;
++
++ writel(t->val, base + t->offset);
++ }
++}
++
++static void qmp_usbc_configure(void __iomem *base,
++ const struct qmp_phy_init_tbl tbl[],
++ int num)
++{
++ qmp_usbc_configure_lane(base, tbl, num, 0xff);
++}
++
++static int qmp_usbc_init(struct phy *phy)
++{
++ struct qmp_usbc *qmp = phy_get_drvdata(phy);
++ const struct qmp_phy_cfg *cfg = qmp->cfg;
++ void __iomem *pcs = qmp->pcs;
++ u32 val = 0;
++ int ret;
++
++ ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs);
++ if (ret) {
++ dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret);
++ return ret;
++ }
++
++ ret = reset_control_bulk_assert(qmp->num_resets, qmp->resets);
++ if (ret) {
++ dev_err(qmp->dev, "reset assert failed\n");
++ goto err_disable_regulators;
++ }
++
++ ret = reset_control_bulk_deassert(qmp->num_resets, qmp->resets);
++ if (ret) {
++ dev_err(qmp->dev, "reset deassert failed\n");
++ goto err_disable_regulators;
++ }
++
++ ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
++ if (ret)
++ goto err_assert_reset;
++
++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], SW_PWRDN);
++
++#define SW_PORTSELECT_VAL BIT(0)
++#define SW_PORTSELECT_MUX BIT(1)
++ /* Use software based port select and switch on typec orientation */
++ val = SW_PORTSELECT_MUX;
++ if (qmp->orientation == TYPEC_ORIENTATION_REVERSE)
++ val |= SW_PORTSELECT_VAL;
++ writel(val, qmp->pcs_misc);
++
++ return 0;
++
++err_assert_reset:
++ reset_control_bulk_assert(qmp->num_resets, qmp->resets);
++err_disable_regulators:
++ regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
++
++ return ret;
++}
++
++static int qmp_usbc_exit(struct phy *phy)
++{
++ struct qmp_usbc *qmp = phy_get_drvdata(phy);
++ const struct qmp_phy_cfg *cfg = qmp->cfg;
++
++ reset_control_bulk_assert(qmp->num_resets, qmp->resets);
++
++ clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
++
++ regulator_bulk_disable(cfg->num_vregs, qmp->vregs);
++
++ return 0;
++}
++
++static int qmp_usbc_power_on(struct phy *phy)
++{
++ struct qmp_usbc *qmp = phy_get_drvdata(phy);
++ const struct qmp_phy_cfg *cfg = qmp->cfg;
++ void __iomem *status;
++ unsigned int val;
++ int ret;
++
++ qmp_usbc_configure(qmp->serdes, cfg->serdes_tbl, cfg->serdes_tbl_num);
++
++ ret = clk_prepare_enable(qmp->pipe_clk);
++ if (ret) {
++ dev_err(qmp->dev, "pipe_clk enable failed err=%d\n", ret);
++ return ret;
++ }
++
++ /* Tx, Rx, and PCS configurations */
++ qmp_usbc_configure_lane(qmp->tx, cfg->tx_tbl, cfg->tx_tbl_num, 1);
++ qmp_usbc_configure_lane(qmp->rx, cfg->rx_tbl, cfg->rx_tbl_num, 1);
++
++ qmp_usbc_configure_lane(qmp->tx2, cfg->tx_tbl, cfg->tx_tbl_num, 2);
++ qmp_usbc_configure_lane(qmp->rx2, cfg->rx_tbl, cfg->rx_tbl_num, 2);
++
++ qmp_usbc_configure(qmp->pcs, cfg->pcs_tbl, cfg->pcs_tbl_num);
++
++ if (cfg->has_pwrdn_delay)
++ usleep_range(10, 20);
++
++ /* Pull PHY out of reset state */
++ qphy_clrbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
++
++ /* start SerDes and Phy-Coding-Sublayer */
++ qphy_setbits(qmp->pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START);
++
++ status = qmp->pcs + cfg->regs[QPHY_PCS_STATUS];
++ ret = readl_poll_timeout(status, val, !(val & PHYSTATUS), 200,
++ PHY_INIT_COMPLETE_TIMEOUT);
++ if (ret) {
++ dev_err(qmp->dev, "phy initialization timed-out\n");
++ goto err_disable_pipe_clk;
++ }
++
++ return 0;
++
++err_disable_pipe_clk:
++ clk_disable_unprepare(qmp->pipe_clk);
++
++ return ret;
++}
++
++static int qmp_usbc_power_off(struct phy *phy)
++{
++ struct qmp_usbc *qmp = phy_get_drvdata(phy);
++ const struct qmp_phy_cfg *cfg = qmp->cfg;
++
++ clk_disable_unprepare(qmp->pipe_clk);
++
++ /* PHY reset */
++ qphy_setbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET);
++
++ /* stop SerDes and Phy-Coding-Sublayer */
++ qphy_clrbits(qmp->pcs, cfg->regs[QPHY_START_CTRL],
++ SERDES_START | PCS_START);
++
++ /* Put PHY into POWER DOWN state: active low */
++ qphy_clrbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL],
++ SW_PWRDN);
++
++ return 0;
++}
++
++static int qmp_usbc_enable(struct phy *phy)
++{
++ struct qmp_usbc *qmp = phy_get_drvdata(phy);
++ int ret;
++
++ mutex_lock(&qmp->phy_mutex);
++
++ ret = qmp_usbc_init(phy);
++ if (ret)
++ goto out_unlock;
++
++ ret = qmp_usbc_power_on(phy);
++ if (ret) {
++ qmp_usbc_exit(phy);
++ goto out_unlock;
++ }
++
++ qmp->usb_init_count++;
++out_unlock:
++ mutex_unlock(&qmp->phy_mutex);
++
++ return ret;
++}
++
++static int qmp_usbc_disable(struct phy *phy)
++{
++ struct qmp_usbc *qmp = phy_get_drvdata(phy);
++ int ret;
++
++ qmp->usb_init_count--;
++ ret = qmp_usbc_power_off(phy);
++ if (ret)
++ return ret;
++ return qmp_usbc_exit(phy);
++}
++
++static int qmp_usbc_set_mode(struct phy *phy, enum phy_mode mode, int submode)
++{
++ struct qmp_usbc *qmp = phy_get_drvdata(phy);
++
++ qmp->mode = mode;
++
++ return 0;
++}
++
++static const struct phy_ops qmp_usbc_phy_ops = {
++ .init = qmp_usbc_enable,
++ .exit = qmp_usbc_disable,
++ .set_mode = qmp_usbc_set_mode,
++ .owner = THIS_MODULE,
++};
++
++static void qmp_usbc_enable_autonomous_mode(struct qmp_usbc *qmp)
++{
++ const struct qmp_phy_cfg *cfg = qmp->cfg;
++ void __iomem *pcs = qmp->pcs;
++ u32 intr_mask;
++
++ if (qmp->mode == PHY_MODE_USB_HOST_SS ||
++ qmp->mode == PHY_MODE_USB_DEVICE_SS)
++ intr_mask = ARCVR_DTCT_EN | ALFPS_DTCT_EN;
++ else
++ intr_mask = ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL;
++
++ /* Clear any pending interrupts status */
++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
++ /* Writing 1 followed by 0 clears the interrupt */
++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
++
++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
++ ARCVR_DTCT_EN | ALFPS_DTCT_EN | ARCVR_DTCT_EVENT_SEL);
++
++ /* Enable required PHY autonomous mode interrupts */
++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL], intr_mask);
++
++ /* Enable i/o clamp_n for autonomous mode */
++ if (qmp->tcsr_map && qmp->vls_clamp_reg)
++ regmap_write(qmp->tcsr_map, qmp->vls_clamp_reg, 1);
++}
++
++static void qmp_usbc_disable_autonomous_mode(struct qmp_usbc *qmp)
++{
++ const struct qmp_phy_cfg *cfg = qmp->cfg;
++ void __iomem *pcs = qmp->pcs;
++
++ /* Disable i/o clamp_n on resume for normal mode */
++ if (qmp->tcsr_map && qmp->vls_clamp_reg)
++ regmap_write(qmp->tcsr_map, qmp->vls_clamp_reg, 0);
++
++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_AUTONOMOUS_MODE_CTRL],
++ ARCVR_DTCT_EN | ARCVR_DTCT_EVENT_SEL | ALFPS_DTCT_EN);
++
++ qphy_setbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
++ /* Writing 1 followed by 0 clears the interrupt */
++ qphy_clrbits(pcs, cfg->regs[QPHY_PCS_LFPS_RXTERM_IRQ_CLEAR], IRQ_CLEAR);
++}
++
++static int __maybe_unused qmp_usbc_runtime_suspend(struct device *dev)
++{
++ struct qmp_usbc *qmp = dev_get_drvdata(dev);
++
++ dev_vdbg(dev, "Suspending QMP phy, mode:%d\n", qmp->mode);
++
++ if (!qmp->phy->init_count) {
++ dev_vdbg(dev, "PHY not initialized, bailing out\n");
++ return 0;
++ }
++
++ qmp_usbc_enable_autonomous_mode(qmp);
++
++ clk_disable_unprepare(qmp->pipe_clk);
++ clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
++
++ return 0;
++}
++
++static int __maybe_unused qmp_usbc_runtime_resume(struct device *dev)
++{
++ struct qmp_usbc *qmp = dev_get_drvdata(dev);
++ int ret = 0;
++
++ dev_vdbg(dev, "Resuming QMP phy, mode:%d\n", qmp->mode);
++
++ if (!qmp->phy->init_count) {
++ dev_vdbg(dev, "PHY not initialized, bailing out\n");
++ return 0;
++ }
++
++ ret = clk_bulk_prepare_enable(qmp->num_clks, qmp->clks);
++ if (ret)
++ return ret;
++
++ ret = clk_prepare_enable(qmp->pipe_clk);
++ if (ret) {
++ dev_err(dev, "pipe_clk enable failed, err=%d\n", ret);
++ clk_bulk_disable_unprepare(qmp->num_clks, qmp->clks);
++ return ret;
++ }
++
++ qmp_usbc_disable_autonomous_mode(qmp);
++
++ return 0;
++}
++
++static const struct dev_pm_ops qmp_usbc_pm_ops = {
++ SET_RUNTIME_PM_OPS(qmp_usbc_runtime_suspend,
++ qmp_usbc_runtime_resume, NULL)
++};
++
++static int qmp_usbc_vreg_init(struct qmp_usbc *qmp)
++{
++ const struct qmp_phy_cfg *cfg = qmp->cfg;
++ struct device *dev = qmp->dev;
++ int num = cfg->num_vregs;
++ int i;
++
++ qmp->vregs = devm_kcalloc(dev, num, sizeof(*qmp->vregs), GFP_KERNEL);
++ if (!qmp->vregs)
++ return -ENOMEM;
++
++ for (i = 0; i < num; i++)
++ qmp->vregs[i].supply = cfg->vreg_list[i];
++
++ return devm_regulator_bulk_get(dev, num, qmp->vregs);
++}
++
++static int qmp_usbc_reset_init(struct qmp_usbc *qmp,
++ const char *const *reset_list,
++ int num_resets)
++{
++ struct device *dev = qmp->dev;
++ int i;
++ int ret;
++
++ qmp->resets = devm_kcalloc(dev, num_resets,
++ sizeof(*qmp->resets), GFP_KERNEL);
++ if (!qmp->resets)
++ return -ENOMEM;
++
++ for (i = 0; i < num_resets; i++)
++ qmp->resets[i].id = reset_list[i];
++
++ qmp->num_resets = num_resets;
++
++ ret = devm_reset_control_bulk_get_exclusive(dev, num_resets, qmp->resets);
++ if (ret)
++ return dev_err_probe(dev, ret, "failed to get resets\n");
++
++ return 0;
++}
++
++static int qmp_usbc_clk_init(struct qmp_usbc *qmp)
++{
++ struct device *dev = qmp->dev;
++ int num = ARRAY_SIZE(qmp_usbc_phy_clk_l);
++ int i;
++
++ qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL);
++ if (!qmp->clks)
++ return -ENOMEM;
++
++ for (i = 0; i < num; i++)
++ qmp->clks[i].id = qmp_usbc_phy_clk_l[i];
++
++ qmp->num_clks = num;
++
++ return devm_clk_bulk_get_optional(dev, num, qmp->clks);
++}
++
++static void phy_clk_release_provider(void *res)
++{
++ of_clk_del_provider(res);
++}
++
++/*
++ * Register a fixed rate pipe clock.
++ *
++ * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
++ * controls it. The <s>_pipe_clk coming out of the GCC is requested
++ * by the PHY driver for its operations.
++ * We register the <s>_pipe_clksrc here. The gcc driver takes care
++ * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk.
++ * Below picture shows this relationship.
++ *
++ * +---------------+
++ * | PHY block |<<---------------------------------------+
++ * | | |
++ * | +-------+ | +-----+ |
++ * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
++ * clk | +-------+ | +-----+
++ * +---------------+
++ */
++static int phy_pipe_clk_register(struct qmp_usbc *qmp, struct device_node *np)
++{
++ struct clk_fixed_rate *fixed = &qmp->pipe_clk_fixed;
++ struct clk_init_data init = { };
++ int ret;
++
++ ret = of_property_read_string(np, "clock-output-names", &init.name);
++ if (ret) {
++ dev_err(qmp->dev, "%pOFn: No clock-output-names\n", np);
++ return ret;
++ }
++
++ init.ops = &clk_fixed_rate_ops;
++
++ /* controllers using QMP phys use 125MHz pipe clock interface */
++ fixed->fixed_rate = 125000000;
++ fixed->hw.init = &init;
++
++ ret = devm_clk_hw_register(qmp->dev, &fixed->hw);
++ if (ret)
++ return ret;
++
++ ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &fixed->hw);
++ if (ret)
++ return ret;
++
++ /*
++ * Roll a devm action because the clock provider is the child node, but
++ * the child node is not actually a device.
++ */
++ return devm_add_action_or_reset(qmp->dev, phy_clk_release_provider, np);
++}
++
++#if IS_ENABLED(CONFIG_TYPEC)
++static int qmp_usbc_typec_switch_set(struct typec_switch_dev *sw,
++ enum typec_orientation orientation)
++{
++ struct qmp_usbc *qmp = typec_switch_get_drvdata(sw);
++
++ if (orientation == qmp->orientation || orientation == TYPEC_ORIENTATION_NONE)
++ return 0;
++
++ mutex_lock(&qmp->phy_mutex);
++ qmp->orientation = orientation;
++
++ if (qmp->usb_init_count) {
++ qmp_usbc_power_off(qmp->phy);
++ qmp_usbc_exit(qmp->phy);
++
++ qmp_usbc_init(qmp->phy);
++ qmp_usbc_power_on(qmp->phy);
++ }
++
++ mutex_unlock(&qmp->phy_mutex);
++
++ return 0;
++}
++
++static void qmp_usbc_typec_unregister(void *data)
++{
++ struct qmp_usbc *qmp = data;
++
++ typec_switch_unregister(qmp->sw);
++}
++
++static int qmp_usbc_typec_switch_register(struct qmp_usbc *qmp)
++{
++ struct typec_switch_desc sw_desc = {};
++ struct device *dev = qmp->dev;
++
++ sw_desc.drvdata = qmp;
++ sw_desc.fwnode = dev->fwnode;
++ sw_desc.set = qmp_usbc_typec_switch_set;
++ qmp->sw = typec_switch_register(dev, &sw_desc);
++ if (IS_ERR(qmp->sw)) {
++ dev_err(dev, "Unable to register typec switch: %pe\n", qmp->sw);
++ return PTR_ERR(qmp->sw);
++ }
++
++ return devm_add_action_or_reset(dev, qmp_usbc_typec_unregister, qmp);
++}
++#else
++static int qmp_usbc_typec_switch_register(struct qmp_usbc *qmp)
++{
++ return 0;
++}
++#endif
++
++static int qmp_usbc_parse_dt_legacy(struct qmp_usbc *qmp, struct device_node *np)
++{
++ struct platform_device *pdev = to_platform_device(qmp->dev);
++ struct device *dev = qmp->dev;
++ int ret;
++
++ qmp->serdes = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(qmp->serdes))
++ return PTR_ERR(qmp->serdes);
++
++ /*
++ * Get memory resources for the PHY:
++ * Resources are indexed as: tx -> 0; rx -> 1; pcs -> 2.
++ * For dual lane PHYs: tx2 -> 3, rx2 -> 4, pcs_misc (optional) -> 5
++ * For single lane PHYs: pcs_misc (optional) -> 3.
++ */
++ qmp->tx = devm_of_iomap(dev, np, 0, NULL);
++ if (IS_ERR(qmp->tx))
++ return PTR_ERR(qmp->tx);
++
++ qmp->rx = devm_of_iomap(dev, np, 1, NULL);
++ if (IS_ERR(qmp->rx))
++ return PTR_ERR(qmp->rx);
++
++ qmp->pcs = devm_of_iomap(dev, np, 2, NULL);
++ if (IS_ERR(qmp->pcs))
++ return PTR_ERR(qmp->pcs);
++
++ qmp->tx2 = devm_of_iomap(dev, np, 3, NULL);
++ if (IS_ERR(qmp->tx2))
++ return PTR_ERR(qmp->tx2);
++
++ qmp->rx2 = devm_of_iomap(dev, np, 4, NULL);
++ if (IS_ERR(qmp->rx2))
++ return PTR_ERR(qmp->rx2);
++
++ qmp->pcs_misc = devm_of_iomap(dev, np, 5, NULL);
++ if (IS_ERR(qmp->pcs_misc)) {
++ dev_vdbg(dev, "PHY pcs_misc-reg not used\n");
++ qmp->pcs_misc = NULL;
++ }
++
++ qmp->pipe_clk = devm_get_clk_from_child(dev, np, NULL);
++ if (IS_ERR(qmp->pipe_clk)) {
++ return dev_err_probe(dev, PTR_ERR(qmp->pipe_clk),
++ "failed to get pipe clock\n");
++ }
++
++ ret = devm_clk_bulk_get_all(qmp->dev, &qmp->clks);
++ if (ret < 0)
++ return ret;
++
++ qmp->num_clks = ret;
++
++ ret = qmp_usbc_reset_init(qmp, usb3phy_legacy_reset_l,
++ ARRAY_SIZE(usb3phy_legacy_reset_l));
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++static int qmp_usbc_parse_dt(struct qmp_usbc *qmp)
++{
++ struct platform_device *pdev = to_platform_device(qmp->dev);
++ const struct qmp_phy_cfg *cfg = qmp->cfg;
++ const struct qmp_usbc_offsets *offs = cfg->offsets;
++ struct device *dev = qmp->dev;
++ void __iomem *base;
++ int ret;
++
++ if (!offs)
++ return -EINVAL;
++
++ base = devm_platform_ioremap_resource(pdev, 0);
++ if (IS_ERR(base))
++ return PTR_ERR(base);
++
++ qmp->serdes = base + offs->serdes;
++ qmp->pcs = base + offs->pcs;
++ if (offs->pcs_misc)
++ qmp->pcs_misc = base + offs->pcs_misc;
++ qmp->tx = base + offs->tx;
++ qmp->rx = base + offs->rx;
++
++ qmp->tx2 = base + offs->tx2;
++ qmp->rx2 = base + offs->rx2;
++
++ ret = qmp_usbc_clk_init(qmp);
++ if (ret)
++ return ret;
++
++ qmp->pipe_clk = devm_clk_get(dev, "pipe");
++ if (IS_ERR(qmp->pipe_clk)) {
++ return dev_err_probe(dev, PTR_ERR(qmp->pipe_clk),
++ "failed to get pipe clock\n");
++ }
++
++ ret = qmp_usbc_reset_init(qmp, usb3phy_reset_l,
++ ARRAY_SIZE(usb3phy_reset_l));
++ if (ret)
++ return ret;
++
++ return 0;
++}
++
++static int qmp_usbc_parse_vls_clamp(struct qmp_usbc *qmp)
++{
++ struct of_phandle_args tcsr_args;
++ struct device *dev = qmp->dev;
++ int ret;
++
++ /* for backwards compatibility ignore if there is no property */
++ ret = of_parse_phandle_with_fixed_args(dev->of_node, "qcom,tcsr-reg", 1, 0,
++ &tcsr_args);
++ if (ret == -ENOENT)
++ return 0;
++ else if (ret < 0)
++ return dev_err_probe(dev, ret, "Failed to parse qcom,tcsr-reg\n");
++
++ qmp->tcsr_map = syscon_node_to_regmap(tcsr_args.np);
++ of_node_put(tcsr_args.np);
++ if (IS_ERR(qmp->tcsr_map))
++ return PTR_ERR(qmp->tcsr_map);
++
++ qmp->vls_clamp_reg = tcsr_args.args[0];
++
++ return 0;
++}
++
++static int qmp_usbc_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct phy_provider *phy_provider;
++ struct device_node *np;
++ struct qmp_usbc *qmp;
++ int ret;
++
++ qmp = devm_kzalloc(dev, sizeof(*qmp), GFP_KERNEL);
++ if (!qmp)
++ return -ENOMEM;
++
++ qmp->dev = dev;
++
++ qmp->orientation = TYPEC_ORIENTATION_NORMAL;
++
++ qmp->cfg = of_device_get_match_data(dev);
++ if (!qmp->cfg)
++ return -EINVAL;
++
++ mutex_init(&qmp->phy_mutex);
++
++ ret = qmp_usbc_vreg_init(qmp);
++ if (ret)
++ return ret;
++
++ ret = qmp_usbc_typec_switch_register(qmp);
++ if (ret)
++ return ret;
++
++ ret = qmp_usbc_parse_vls_clamp(qmp);
++ if (ret)
++ return ret;
++
++ /* Check for legacy binding with child node. */
++ np = of_get_child_by_name(dev->of_node, "phy");
++ if (np) {
++ ret = qmp_usbc_parse_dt_legacy(qmp, np);
++ } else {
++ np = of_node_get(dev->of_node);
++ ret = qmp_usbc_parse_dt(qmp);
++ }
++ if (ret)
++ goto err_node_put;
++
++ pm_runtime_set_active(dev);
++ ret = devm_pm_runtime_enable(dev);
++ if (ret)
++ goto err_node_put;
++ /*
++ * Prevent runtime pm from being ON by default. Users can enable
++ * it using power/control in sysfs.
++ */
++ pm_runtime_forbid(dev);
++
++ ret = phy_pipe_clk_register(qmp, np);
++ if (ret)
++ goto err_node_put;
++
++ qmp->phy = devm_phy_create(dev, np, &qmp_usbc_phy_ops);
++ if (IS_ERR(qmp->phy)) {
++ ret = PTR_ERR(qmp->phy);
++ dev_err(dev, "failed to create PHY: %d\n", ret);
++ goto err_node_put;
++ }
++
++ phy_set_drvdata(qmp->phy, qmp);
++
++ of_node_put(np);
++
++ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
++
++ return PTR_ERR_OR_ZERO(phy_provider);
++
++err_node_put:
++ of_node_put(np);
++ return ret;
++}
++
++static const struct of_device_id qmp_usbc_of_match_table[] = {
++ {
++ .compatible = "qcom,msm8998-qmp-usb3-phy",
++ .data = &msm8998_usb3phy_cfg,
++ }, {
++ .compatible = "qcom,qcm2290-qmp-usb3-phy",
++ .data = &qcm2290_usb3phy_cfg,
++ }, {
++ .compatible = "qcom,sm6115-qmp-usb3-phy",
++ .data = &qcm2290_usb3phy_cfg,
++ },
++ { },
++};
++MODULE_DEVICE_TABLE(of, qmp_usbc_of_match_table);
++
++static struct platform_driver qmp_usbc_driver = {
++ .probe = qmp_usbc_probe,
++ .driver = {
++ .name = "qcom-qmp-usbc-phy",
++ .pm = &qmp_usbc_pm_ops,
++ .of_match_table = qmp_usbc_of_match_table,
++ },
++};
++
++module_platform_driver(qmp_usbc_driver);
++
++MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>");
++MODULE_DESCRIPTION("Qualcomm QMP USB-C PHY driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8186.c b/drivers/pinctrl/mediatek/pinctrl-mt8186.c
+index 7be591591cce5..dd19e74856a92 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8186.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8186.c
+@@ -1198,7 +1198,6 @@ static const struct mtk_pin_reg_calc mt8186_reg_cals[PINCTRL_PIN_REG_MAX] = {
+ [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt8186_pin_dir_range),
+ [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt8186_pin_di_range),
+ [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt8186_pin_do_range),
+- [PINCTRL_PIN_REG_SR] = MTK_RANGE(mt8186_pin_dir_range),
+ [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt8186_pin_smt_range),
+ [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt8186_pin_ies_range),
+ [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt8186_pin_pu_range),
+diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8192.c b/drivers/pinctrl/mediatek/pinctrl-mt8192.c
+index e3a76381f7f4e..3f8a9dbcb7041 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-mt8192.c
++++ b/drivers/pinctrl/mediatek/pinctrl-mt8192.c
+@@ -1379,7 +1379,6 @@ static const struct mtk_pin_reg_calc mt8192_reg_cals[PINCTRL_PIN_REG_MAX] = {
+ [PINCTRL_PIN_REG_DIR] = MTK_RANGE(mt8192_pin_dir_range),
+ [PINCTRL_PIN_REG_DI] = MTK_RANGE(mt8192_pin_di_range),
+ [PINCTRL_PIN_REG_DO] = MTK_RANGE(mt8192_pin_do_range),
+- [PINCTRL_PIN_REG_SR] = MTK_RANGE(mt8192_pin_dir_range),
+ [PINCTRL_PIN_REG_SMT] = MTK_RANGE(mt8192_pin_smt_range),
+ [PINCTRL_PIN_REG_IES] = MTK_RANGE(mt8192_pin_ies_range),
+ [PINCTRL_PIN_REG_PU] = MTK_RANGE(mt8192_pin_pu_range),
+diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+index 7911353ac97d5..4f7c4af4f93cb 100644
+--- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c
++++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c
+@@ -1579,8 +1579,10 @@ static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned function,
+ * Then mask the pins that need to be sleeping now when we're
+ * switching to the ALT C function.
+ */
+- for (i = 0; i < g->grp.npins; i++)
+- slpm[g->grp.pins[i] / NMK_GPIO_PER_CHIP] &= ~BIT(g->grp.pins[i]);
++ for (i = 0; i < g->grp.npins; i++) {
++ unsigned int bit = g->grp.pins[i] % NMK_GPIO_PER_CHIP;
++ slpm[g->grp.pins[i] / NMK_GPIO_PER_CHIP] &= ~BIT(bit);
++ }
+ nmk_gpio_glitch_slpm_init(slpm);
+ }
+
+diff --git a/drivers/pinctrl/renesas/core.c b/drivers/pinctrl/renesas/core.c
+index 93e51abbf519a..d1e92bbed33ad 100644
+--- a/drivers/pinctrl/renesas/core.c
++++ b/drivers/pinctrl/renesas/core.c
+@@ -731,10 +731,12 @@ static int sh_pfc_resume_noirq(struct device *dev)
+ sh_pfc_walk_regs(pfc, sh_pfc_restore_reg);
+ return 0;
+ }
++#define pm_psci_sleep_ptr(_ptr) pm_sleep_ptr(_ptr)
+ #else
+ static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; }
+ static int sh_pfc_suspend_noirq(struct device *dev) { return 0; }
+ static int sh_pfc_resume_noirq(struct device *dev) { return 0; }
++#define pm_psci_sleep_ptr(_ptr) PTR_IF(false, (_ptr))
+ #endif /* CONFIG_ARM_PSCI_FW */
+
+ static DEFINE_NOIRQ_DEV_PM_OPS(sh_pfc_pm, sh_pfc_suspend_noirq, sh_pfc_resume_noirq);
+@@ -1415,7 +1417,7 @@ static struct platform_driver sh_pfc_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .of_match_table = of_match_ptr(sh_pfc_of_table),
+- .pm = pm_sleep_ptr(&sh_pfc_pm),
++ .pm = pm_psci_sleep_ptr(&sh_pfc_pm),
+ },
+ };
+
+diff --git a/drivers/pinctrl/renesas/pfc-r8a779g0.c b/drivers/pinctrl/renesas/pfc-r8a779g0.c
+index acdea6ac15253..d2de526a3b588 100644
+--- a/drivers/pinctrl/renesas/pfc-r8a779g0.c
++++ b/drivers/pinctrl/renesas/pfc-r8a779g0.c
+@@ -2384,6 +2384,14 @@ static const unsigned int scif_clk_mux[] = {
+ SCIF_CLK_MARK,
+ };
+
++static const unsigned int scif_clk2_pins[] = {
++ /* SCIF_CLK2 */
++ RCAR_GP_PIN(8, 11),
++};
++static const unsigned int scif_clk2_mux[] = {
++ SCIF_CLK2_MARK,
++};
++
+ /* - SSI ------------------------------------------------- */
+ static const unsigned int ssi_data_pins[] = {
+ /* SSI_SD */
+@@ -2694,6 +2702,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
+ SH_PFC_PIN_GROUP(scif4_clk),
+ SH_PFC_PIN_GROUP(scif4_ctrl),
+ SH_PFC_PIN_GROUP(scif_clk),
++ SH_PFC_PIN_GROUP(scif_clk2),
+
+ SH_PFC_PIN_GROUP(ssi_data),
+ SH_PFC_PIN_GROUP(ssi_ctrl),
+@@ -3015,6 +3024,10 @@ static const char * const scif_clk_groups[] = {
+ "scif_clk",
+ };
+
++static const char * const scif_clk2_groups[] = {
++ "scif_clk2",
++};
++
+ static const char * const ssi_groups[] = {
+ "ssi_data",
+ "ssi_ctrl",
+@@ -3102,6 +3115,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
+ SH_PFC_FUNCTION(scif3),
+ SH_PFC_FUNCTION(scif4),
+ SH_PFC_FUNCTION(scif_clk),
++ SH_PFC_FUNCTION(scif_clk2),
+
+ SH_PFC_FUNCTION(ssi),
+
+diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
+index 80fb5011c7bbc..01ef6921cb35c 100644
+--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
++++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
+@@ -447,6 +447,16 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+ name = np->name;
+ }
+
++ if (num_configs) {
++ ret = rzg2l_map_add_config(&maps[idx], name,
++ PIN_MAP_TYPE_CONFIGS_GROUP,
++ configs, num_configs);
++ if (ret < 0)
++ goto done;
++
++ idx++;
++ }
++
+ mutex_lock(&pctrl->mutex);
+
+ /* Register a single pin group listing all the pins we read from DT */
+@@ -474,16 +484,6 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+ maps[idx].data.mux.function = name;
+ idx++;
+
+- if (num_configs) {
+- ret = rzg2l_map_add_config(&maps[idx], name,
+- PIN_MAP_TYPE_CONFIGS_GROUP,
+- configs, num_configs);
+- if (ret < 0)
+- goto remove_group;
+-
+- idx++;
+- }
+-
+ dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux);
+ ret = 0;
+ goto done;
+diff --git a/drivers/platform/x86/amd/pmf/tee-if.c b/drivers/platform/x86/amd/pmf/tee-if.c
+index dcbe8f85e1229..4ebfe0f5a7fb2 100644
+--- a/drivers/platform/x86/amd/pmf/tee-if.c
++++ b/drivers/platform/x86/amd/pmf/tee-if.c
+@@ -249,8 +249,8 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
+ u32 cookie, length;
+ int res;
+
+- cookie = readl(dev->policy_buf + POLICY_COOKIE_OFFSET);
+- length = readl(dev->policy_buf + POLICY_COOKIE_LEN);
++ cookie = *(u32 *)(dev->policy_buf + POLICY_COOKIE_OFFSET);
++ length = *(u32 *)(dev->policy_buf + POLICY_COOKIE_LEN);
+
+ if (cookie != POLICY_SIGN_COOKIE || !length) {
+ dev_dbg(dev->dev, "cookie doesn't match\n");
+diff --git a/drivers/platform/x86/intel/pmc/arl.c b/drivers/platform/x86/intel/pmc/arl.c
+index 683ae828276b8..34b4cd23bfe59 100644
+--- a/drivers/platform/x86/intel/pmc/arl.c
++++ b/drivers/platform/x86/intel/pmc/arl.c
+@@ -673,6 +673,7 @@ static struct pmc_info arl_pmc_info_list[] = {
+ };
+
+ #define ARL_NPU_PCI_DEV 0xad1d
++#define ARL_GNA_PCI_DEV 0xae4c
+ /*
+ * Set power state of select devices that do not have drivers to D3
+ * so that they do not block Package C entry.
+@@ -680,6 +681,7 @@ static struct pmc_info arl_pmc_info_list[] = {
+ static void arl_d3_fixup(void)
+ {
+ pmc_core_set_device_d3(ARL_NPU_PCI_DEV);
++ pmc_core_set_device_d3(ARL_GNA_PCI_DEV);
+ }
+
+ static int arl_resume(struct pmc_dev *pmcdev)
+diff --git a/drivers/platform/x86/intel/pmc/lnl.c b/drivers/platform/x86/intel/pmc/lnl.c
+index abad17cdd3d78..068d72504683f 100644
+--- a/drivers/platform/x86/intel/pmc/lnl.c
++++ b/drivers/platform/x86/intel/pmc/lnl.c
+@@ -13,21 +13,6 @@
+
+ #include "core.h"
+
+-#define SOCM_LPM_REQ_GUID 0x11594920
+-
+-#define PMC_DEVID_SOCM 0xa87f
+-
+-static const u8 LNL_LPM_REG_INDEX[] = {0, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20};
+-
+-static struct pmc_info lnl_pmc_info_list[] = {
+- {
+- .guid = SOCM_LPM_REQ_GUID,
+- .devid = PMC_DEVID_SOCM,
+- .map = &lnl_socm_reg_map,
+- },
+- {}
+-};
+-
+ const struct pmc_bit_map lnl_ltr_show_map[] = {
+ {"SOUTHPORT_A", CNP_PMC_LTR_SPA},
+ {"SOUTHPORT_B", CNP_PMC_LTR_SPB},
+@@ -490,7 +475,6 @@ const struct pmc_reg_map lnl_socm_reg_map = {
+ .lpm_sts = lnl_lpm_maps,
+ .lpm_status_offset = MTL_LPM_STATUS_OFFSET,
+ .lpm_live_status_offset = MTL_LPM_LIVE_STATUS_OFFSET,
+- .lpm_reg_index = LNL_LPM_REG_INDEX,
+ };
+
+ #define LNL_NPU_PCI_DEV 0x643e
+@@ -517,33 +501,19 @@ static int lnl_resume(struct pmc_dev *pmcdev)
+ int lnl_core_init(struct pmc_dev *pmcdev)
+ {
+ int ret;
+- int func = 2;
+- bool ssram_init = true;
+ struct pmc *pmc = pmcdev->pmcs[PMC_IDX_SOC];
+
+ lnl_d3_fixup();
+
+ pmcdev->suspend = cnl_suspend;
+ pmcdev->resume = lnl_resume;
+- pmcdev->regmap_list = lnl_pmc_info_list;
+- ret = pmc_core_ssram_init(pmcdev, func);
+-
+- /* If regbase not assigned, set map and discover using legacy method */
+- if (ret) {
+- ssram_init = false;
+- pmc->map = &lnl_socm_reg_map;
+- ret = get_primary_reg_base(pmc);
+- if (ret)
+- return ret;
+- }
+
+- pmc_core_get_low_power_modes(pmcdev);
++ pmc->map = &lnl_socm_reg_map;
++ ret = get_primary_reg_base(pmc);
++ if (ret)
++ return ret;
+
+- if (ssram_init) {
+- ret = pmc_core_ssram_get_lpm_reqs(pmcdev);
+- if (ret)
+- return ret;
+- }
++ pmc_core_get_low_power_modes(pmcdev);
+
+ return 0;
+ }
+diff --git a/drivers/pmdomain/qcom/rpmhpd.c b/drivers/pmdomain/qcom/rpmhpd.c
+index 47df910645f66..de9121ef4216b 100644
+--- a/drivers/pmdomain/qcom/rpmhpd.c
++++ b/drivers/pmdomain/qcom/rpmhpd.c
+@@ -217,7 +217,6 @@ static struct rpmhpd *sa8540p_rpmhpds[] = {
+ [SC8280XP_CX] = &cx,
+ [SC8280XP_CX_AO] = &cx_ao,
+ [SC8280XP_EBI] = &ebi,
+- [SC8280XP_GFX] = &gfx,
+ [SC8280XP_LCX] = &lcx,
+ [SC8280XP_LMX] = &lmx,
+ [SC8280XP_MMCX] = &mmcx,
+diff --git a/drivers/power/supply/mm8013.c b/drivers/power/supply/mm8013.c
+index caa272b035649..20c1651ca38e0 100644
+--- a/drivers/power/supply/mm8013.c
++++ b/drivers/power/supply/mm8013.c
+@@ -71,7 +71,6 @@ static int mm8013_checkdevice(struct mm8013_chip *chip)
+
+ static enum power_supply_property mm8013_battery_props[] = {
+ POWER_SUPPLY_PROP_CAPACITY,
+- POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+@@ -103,16 +102,6 @@ static int mm8013_get_property(struct power_supply *psy,
+
+ val->intval = regval;
+ break;
+- case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
+- ret = regmap_read(chip->regmap, REG_FLAGS, ®val);
+- if (ret < 0)
+- return ret;
+-
+- if (regval & MM8013_FLAG_CHG_INH)
+- val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE;
+- else
+- val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO;
+- break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ ret = regmap_read(chip->regmap, REG_FULL_CHARGE_CAPACITY, ®val);
+ if (ret < 0)
+@@ -187,6 +176,8 @@ static int mm8013_get_property(struct power_supply *psy,
+
+ if (regval & MM8013_FLAG_DSG)
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
++ else if (regval & MM8013_FLAG_CHG_INH)
++ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ else if (regval & MM8013_FLAG_CHG)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (regval & MM8013_FLAG_FC)
+diff --git a/drivers/powercap/dtpm_cpu.c b/drivers/powercap/dtpm_cpu.c
+index 9193c3b8edebe..ae7ee611978ba 100644
+--- a/drivers/powercap/dtpm_cpu.c
++++ b/drivers/powercap/dtpm_cpu.c
+@@ -219,7 +219,7 @@ static int __dtpm_cpu_setup(int cpu, struct dtpm *parent)
+ ret = freq_qos_add_request(&policy->constraints,
+ &dtpm_cpu->qos_req, FREQ_QOS_MAX,
+ pd->table[pd->nr_perf_states - 1].frequency);
+- if (ret)
++ if (ret < 0)
+ goto out_dtpm_unregister;
+
+ cpufreq_cpu_put(policy);
+diff --git a/drivers/pwm/pwm-atmel-hlcdc.c b/drivers/pwm/pwm-atmel-hlcdc.c
+index 3f2c5031a3ba8..1f6fc9a9fcf3e 100644
+--- a/drivers/pwm/pwm-atmel-hlcdc.c
++++ b/drivers/pwm/pwm-atmel-hlcdc.c
+@@ -185,7 +185,7 @@ static int atmel_hlcdc_pwm_suspend(struct device *dev)
+ struct atmel_hlcdc_pwm *atmel = dev_get_drvdata(dev);
+
+ /* Keep the periph clock enabled if the PWM is still running. */
+- if (pwm_is_enabled(&atmel->chip.pwms[0]))
++ if (!pwm_is_enabled(&atmel->chip.pwms[0]))
+ clk_disable_unprepare(atmel->hlcdc->periph_clk);
+
+ return 0;
+diff --git a/drivers/pwm/pwm-dwc.c b/drivers/pwm/pwm-dwc.c
+index 4929354f8cd95..a4a057ae03ea2 100644
+--- a/drivers/pwm/pwm-dwc.c
++++ b/drivers/pwm/pwm-dwc.c
+@@ -120,7 +120,7 @@ static struct pci_driver dwc_pwm_driver = {
+ .remove = dwc_pwm_remove,
+ .id_table = dwc_pwm_id_table,
+ .driver = {
+- .pm = pm_ptr(&dwc_pwm_pm_ops),
++ .pm = pm_sleep_ptr(&dwc_pwm_pm_ops),
+ },
+ };
+
+diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c
+index 6cf55cf34d39f..69b1113c6b821 100644
+--- a/drivers/pwm/pwm-sti.c
++++ b/drivers/pwm/pwm-sti.c
+@@ -395,8 +395,17 @@ static int sti_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
+ static int sti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+ {
++ struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
++ struct sti_pwm_compat_data *cdata = pc->cdata;
++ struct device *dev = pc->dev;
+ int err;
+
++ if (pwm->hwpwm >= cdata->pwm_num_devs) {
++ dev_err(dev, "device %u is not valid for pwm mode\n",
++ pwm->hwpwm);
++ return -EINVAL;
++ }
++
+ if (state->polarity != PWM_POLARITY_NORMAL)
+ return -EINVAL;
+
+@@ -646,7 +655,7 @@ static int sti_pwm_probe(struct platform_device *pdev)
+
+ pc->chip.dev = dev;
+ pc->chip.ops = &sti_pwm_ops;
+- pc->chip.npwm = pc->cdata->pwm_num_devs;
++ pc->chip.npwm = max(cdata->pwm_num_devs, cdata->cpt_num_devs);
+
+ for (i = 0; i < cdata->cpt_num_devs; i++) {
+ struct sti_cpt_ddata *ddata = &cdata->ddata[i];
+diff --git a/drivers/regulator/userspace-consumer.c b/drivers/regulator/userspace-consumer.c
+index 53d1b9d6f69c5..86a626a4f610a 100644
+--- a/drivers/regulator/userspace-consumer.c
++++ b/drivers/regulator/userspace-consumer.c
+@@ -208,6 +208,7 @@ static const struct of_device_id regulator_userspace_consumer_of_match[] = {
+ { .compatible = "regulator-output", },
+ {},
+ };
++MODULE_DEVICE_TABLE(of, regulator_userspace_consumer_of_match);
+
+ static struct platform_driver regulator_userspace_consumer_driver = {
+ .probe = regulator_userspace_consumer_probe,
+diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
+index 4f469f0bcf8b2..10b442c6f6323 100644
+--- a/drivers/remoteproc/stm32_rproc.c
++++ b/drivers/remoteproc/stm32_rproc.c
+@@ -120,7 +120,7 @@ static int stm32_rproc_mem_alloc(struct rproc *rproc,
+ void *va;
+
+ dev_dbg(dev, "map memory: %pad+%zx\n", &mem->dma, mem->len);
+- va = ioremap_wc(mem->dma, mem->len);
++ va = (__force void *)ioremap_wc(mem->dma, mem->len);
+ if (IS_ERR_OR_NULL(va)) {
+ dev_err(dev, "Unable to map memory region: %pad+0x%zx\n",
+ &mem->dma, mem->len);
+@@ -137,7 +137,7 @@ static int stm32_rproc_mem_release(struct rproc *rproc,
+ struct rproc_mem_entry *mem)
+ {
+ dev_dbg(rproc->dev.parent, "unmap memory: %pa\n", &mem->dma);
+- iounmap(mem->va);
++ iounmap((__force __iomem void *)mem->va);
+
+ return 0;
+ }
+@@ -657,7 +657,7 @@ stm32_rproc_get_loaded_rsc_table(struct rproc *rproc, size_t *table_sz)
+ * entire area by overwriting it with the initial values stored in rproc->clean_table.
+ */
+ *table_sz = RSC_TBL_SIZE;
+- return (struct resource_table *)ddata->rsc_va;
++ return (__force struct resource_table *)ddata->rsc_va;
+ }
+
+ static const struct rproc_ops st_rproc_ops = {
+diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
+index e37a4341f442d..c63e32d012f23 100644
+--- a/drivers/rtc/Kconfig
++++ b/drivers/rtc/Kconfig
+@@ -1858,7 +1858,8 @@ config RTC_DRV_MT2712
+
+ config RTC_DRV_MT6397
+ tristate "MediaTek PMIC based RTC"
+- depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN)
++ depends on MFD_MT6397 || COMPILE_TEST
++ select IRQ_DOMAIN
+ help
+ This selects the MediaTek(R) RTC driver. RTC is part of MediaTek
+ MT6397 PMIC. You should enable MT6397 PMIC MFD before select
+diff --git a/drivers/rtc/lib_test.c b/drivers/rtc/lib_test.c
+index d5caf36c56cdc..225c859d6da55 100644
+--- a/drivers/rtc/lib_test.c
++++ b/drivers/rtc/lib_test.c
+@@ -54,7 +54,7 @@ static void rtc_time64_to_tm_test_date_range(struct kunit *test)
+
+ days = div_s64(secs, 86400);
+
+- #define FAIL_MSG "%d/%02d/%02d (%2d) : %ld", \
++ #define FAIL_MSG "%d/%02d/%02d (%2d) : %lld", \
+ year, month, mday, yday, days
+
+ KUNIT_ASSERT_EQ_MSG(test, year - 1900, result.tm_year, FAIL_MSG);
+diff --git a/drivers/rtc/rtc-max31335.c b/drivers/rtc/rtc-max31335.c
+index 402fda8fd5488..a2441e5c2c74d 100644
+--- a/drivers/rtc/rtc-max31335.c
++++ b/drivers/rtc/rtc-max31335.c
+@@ -204,7 +204,7 @@ static bool max31335_volatile_reg(struct device *dev, unsigned int reg)
+ return true;
+
+ /* interrupt status register */
+- if (reg == MAX31335_INT_EN1_A1IE)
++ if (reg == MAX31335_STATUS1)
+ return true;
+
+ /* temperature registers */
+diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
+index 7327e81352e9c..30851faade97b 100644
+--- a/drivers/s390/block/dasd.c
++++ b/drivers/s390/block/dasd.c
+@@ -8,9 +8,6 @@
+ * Copyright IBM Corp. 1999, 2009
+ */
+
+-#define KMSG_COMPONENT "dasd"
+-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+-
+ #include <linux/kmod.h>
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+@@ -3402,8 +3399,7 @@ static void dasd_generic_auto_online(void *data, async_cookie_t cookie)
+
+ ret = ccw_device_set_online(cdev);
+ if (ret)
+- pr_warn("%s: Setting the DASD online failed with rc=%d\n",
+- dev_name(&cdev->dev), ret);
++ dev_warn(&cdev->dev, "Setting the DASD online failed with rc=%d\n", ret);
+ }
+
+ /*
+@@ -3490,8 +3486,11 @@ int dasd_generic_set_online(struct ccw_device *cdev,
+ {
+ struct dasd_discipline *discipline;
+ struct dasd_device *device;
++ struct device *dev;
+ int rc;
+
++ dev = &cdev->dev;
++
+ /* first online clears initial online feature flag */
+ dasd_set_feature(cdev, DASD_FEATURE_INITIAL_ONLINE, 0);
+ device = dasd_create_device(cdev);
+@@ -3504,11 +3503,10 @@ int dasd_generic_set_online(struct ccw_device *cdev,
+ /* Try to load the required module. */
+ rc = request_module(DASD_DIAG_MOD);
+ if (rc) {
+- pr_warn("%s Setting the DASD online failed "
+- "because the required module %s "
+- "could not be loaded (rc=%d)\n",
+- dev_name(&cdev->dev), DASD_DIAG_MOD,
+- rc);
++ dev_warn(dev, "Setting the DASD online failed "
++ "because the required module %s "
++ "could not be loaded (rc=%d)\n",
++ DASD_DIAG_MOD, rc);
+ dasd_delete_device(device);
+ return -ENODEV;
+ }
+@@ -3516,8 +3514,7 @@ int dasd_generic_set_online(struct ccw_device *cdev,
+ /* Module init could have failed, so check again here after
+ * request_module(). */
+ if (!dasd_diag_discipline_pointer) {
+- pr_warn("%s Setting the DASD online failed because of missing DIAG discipline\n",
+- dev_name(&cdev->dev));
++ dev_warn(dev, "Setting the DASD online failed because of missing DIAG discipline\n");
+ dasd_delete_device(device);
+ return -ENODEV;
+ }
+@@ -3527,37 +3524,33 @@ int dasd_generic_set_online(struct ccw_device *cdev,
+ dasd_delete_device(device);
+ return -EINVAL;
+ }
++ device->base_discipline = base_discipline;
+ if (!try_module_get(discipline->owner)) {
+- module_put(base_discipline->owner);
+ dasd_delete_device(device);
+ return -EINVAL;
+ }
+- device->base_discipline = base_discipline;
+ device->discipline = discipline;
+
+ /* check_device will allocate block device if necessary */
+ rc = discipline->check_device(device);
+ if (rc) {
+- pr_warn("%s Setting the DASD online with discipline %s failed with rc=%i\n",
+- dev_name(&cdev->dev), discipline->name, rc);
+- module_put(discipline->owner);
+- module_put(base_discipline->owner);
++ dev_warn(dev, "Setting the DASD online with discipline %s failed with rc=%i\n",
++ discipline->name, rc);
+ dasd_delete_device(device);
+ return rc;
+ }
+
+ dasd_set_target_state(device, DASD_STATE_ONLINE);
+ if (device->state <= DASD_STATE_KNOWN) {
+- pr_warn("%s Setting the DASD online failed because of a missing discipline\n",
+- dev_name(&cdev->dev));
++ dev_warn(dev, "Setting the DASD online failed because of a missing discipline\n");
+ rc = -ENODEV;
+ dasd_set_target_state(device, DASD_STATE_NEW);
+ if (device->block)
+ dasd_free_block(device->block);
+ dasd_delete_device(device);
+- } else
+- pr_debug("dasd_generic device %s found\n",
+- dev_name(&cdev->dev));
++ } else {
++ dev_dbg(dev, "dasd_generic device found\n");
++ }
+
+ wait_event(dasd_init_waitq, _wait_for_device(device));
+
+@@ -3568,10 +3561,13 @@ EXPORT_SYMBOL_GPL(dasd_generic_set_online);
+
+ int dasd_generic_set_offline(struct ccw_device *cdev)
+ {
++ int max_count, open_count, rc;
+ struct dasd_device *device;
+ struct dasd_block *block;
+- int max_count, open_count, rc;
+ unsigned long flags;
++ struct device *dev;
++
++ dev = &cdev->dev;
+
+ rc = 0;
+ spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
+@@ -3592,11 +3588,10 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
+ open_count = atomic_read(&device->block->open_count);
+ if (open_count > max_count) {
+ if (open_count > 0)
+- pr_warn("%s: The DASD cannot be set offline with open count %i\n",
+- dev_name(&cdev->dev), open_count);
++ dev_warn(dev, "The DASD cannot be set offline with open count %i\n",
++ open_count);
+ else
+- pr_warn("%s: The DASD cannot be set offline while it is in use\n",
+- dev_name(&cdev->dev));
++ dev_warn(dev, "The DASD cannot be set offline while it is in use\n");
+ rc = -EBUSY;
+ goto out_err;
+ }
+@@ -3956,8 +3951,8 @@ static int dasd_handle_autoquiesce(struct dasd_device *device,
+ if (dasd_eer_enabled(device))
+ dasd_eer_write(device, NULL, DASD_EER_AUTOQUIESCE);
+
+- pr_info("%s: The DASD has been put in the quiesce state\n",
+- dev_name(&device->cdev->dev));
++ dev_info(&device->cdev->dev,
++ "The DASD has been put in the quiesce state\n");
+ dasd_device_set_stop_bits(device, DASD_STOPPED_QUIESCE);
+
+ if (device->features & DASD_FEATURE_REQUEUEQUIESCE)
+diff --git a/drivers/scsi/bfa/bfa.h b/drivers/scsi/bfa/bfa.h
+index 7bd2ba1ad4d11..f30fe324e6ecc 100644
+--- a/drivers/scsi/bfa/bfa.h
++++ b/drivers/scsi/bfa/bfa.h
+@@ -20,7 +20,6 @@
+ struct bfa_s;
+
+ typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m);
+-typedef void (*bfa_cb_cbfn_status_t) (void *cbarg, bfa_status_t status);
+
+ /*
+ * Interrupt message handlers
+@@ -437,4 +436,12 @@ struct bfa_cb_pending_q_s {
+ (__qe)->data = (__data); \
+ } while (0)
+
++#define bfa_pending_q_init_status(__qe, __cbfn, __cbarg, __data) do { \
++ bfa_q_qe_init(&((__qe)->hcb_qe.qe)); \
++ (__qe)->hcb_qe.cbfn_status = (__cbfn); \
++ (__qe)->hcb_qe.cbarg = (__cbarg); \
++ (__qe)->hcb_qe.pre_rmv = BFA_TRUE; \
++ (__qe)->data = (__data); \
++} while (0)
++
+ #endif /* __BFA_H__ */
+diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c
+index 6846ca8f7313c..3438d0b8ba062 100644
+--- a/drivers/scsi/bfa/bfa_core.c
++++ b/drivers/scsi/bfa/bfa_core.c
+@@ -1907,15 +1907,13 @@ bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q)
+ struct list_head *qe;
+ struct list_head *qen;
+ struct bfa_cb_qe_s *hcb_qe;
+- bfa_cb_cbfn_status_t cbfn;
+
+ list_for_each_safe(qe, qen, comp_q) {
+ hcb_qe = (struct bfa_cb_qe_s *) qe;
+ if (hcb_qe->pre_rmv) {
+ /* qe is invalid after return, dequeue before cbfn() */
+ list_del(qe);
+- cbfn = (bfa_cb_cbfn_status_t)(hcb_qe->cbfn);
+- cbfn(hcb_qe->cbarg, hcb_qe->fw_status);
++ hcb_qe->cbfn_status(hcb_qe->cbarg, hcb_qe->fw_status);
+ } else
+ hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE);
+ }
+diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
+index 933a1c3890ff5..5e568d6d7b261 100644
+--- a/drivers/scsi/bfa/bfa_ioc.h
++++ b/drivers/scsi/bfa/bfa_ioc.h
+@@ -361,14 +361,18 @@ struct bfa_reqq_wait_s {
+ void *cbarg;
+ };
+
+-typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
++typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete);
++typedef void (*bfa_cb_cbfn_status_t) (void *cbarg, bfa_status_t status);
+
+ /*
+ * Generic BFA callback element.
+ */
+ struct bfa_cb_qe_s {
+ struct list_head qe;
+- bfa_cb_cbfn_t cbfn;
++ union {
++ bfa_cb_cbfn_status_t cbfn_status;
++ bfa_cb_cbfn_t cbfn;
++ };
+ bfa_boolean_t once;
+ bfa_boolean_t pre_rmv; /* set for stack based qe(s) */
+ bfa_status_t fw_status; /* to access fw status in comp proc */
+diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
+index d4ceca2d435ee..54bd11e6d5933 100644
+--- a/drivers/scsi/bfa/bfad_bsg.c
++++ b/drivers/scsi/bfa/bfad_bsg.c
+@@ -2135,8 +2135,7 @@ bfad_iocmd_fcport_get_stats(struct bfad_s *bfad, void *cmd)
+ struct bfa_cb_pending_q_s cb_qe;
+
+ init_completion(&fcomp.comp);
+- bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
+- &fcomp, &iocmd->stats);
++ bfa_pending_q_init_status(&cb_qe, bfad_hcb_comp, &fcomp, &iocmd->stats);
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fcport_get_stats(&bfad->bfa, &cb_qe);
+ spin_unlock_irqrestore(&bfad->bfad_lock, flags);
+@@ -2159,7 +2158,7 @@ bfad_iocmd_fcport_reset_stats(struct bfad_s *bfad, void *cmd)
+ struct bfa_cb_pending_q_s cb_qe;
+
+ init_completion(&fcomp.comp);
+- bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp, &fcomp, NULL);
++ bfa_pending_q_init_status(&cb_qe, bfad_hcb_comp, &fcomp, NULL);
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ iocmd->status = bfa_fcport_clear_stats(&bfad->bfa, &cb_qe);
+@@ -2443,8 +2442,7 @@ bfad_iocmd_qos_get_stats(struct bfad_s *bfad, void *cmd)
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
+
+ init_completion(&fcomp.comp);
+- bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
+- &fcomp, &iocmd->stats);
++ bfa_pending_q_init_status(&cb_qe, bfad_hcb_comp, &fcomp, &iocmd->stats);
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
+@@ -2474,8 +2472,7 @@ bfad_iocmd_qos_reset_stats(struct bfad_s *bfad, void *cmd)
+ struct bfa_fcport_s *fcport = BFA_FCPORT_MOD(&bfad->bfa);
+
+ init_completion(&fcomp.comp);
+- bfa_pending_q_init(&cb_qe, (bfa_cb_cbfn_t)bfad_hcb_comp,
+- &fcomp, NULL);
++ bfa_pending_q_init_status(&cb_qe, bfad_hcb_comp, &fcomp, NULL);
+
+ spin_lock_irqsave(&bfad->bfad_lock, flags);
+ WARN_ON(!bfa_ioc_get_fcmode(&bfad->bfa.ioc));
+diff --git a/drivers/scsi/csiostor/csio_defs.h b/drivers/scsi/csiostor/csio_defs.h
+index c38017b4af982..e50e93e7fe5a1 100644
+--- a/drivers/scsi/csiostor/csio_defs.h
++++ b/drivers/scsi/csiostor/csio_defs.h
+@@ -73,7 +73,21 @@ csio_list_deleted(struct list_head *list)
+ #define csio_list_prev(elem) (((struct list_head *)(elem))->prev)
+
+ /* State machine */
+-typedef void (*csio_sm_state_t)(void *, uint32_t);
++struct csio_lnode;
++
++/* State machine evets */
++enum csio_ln_ev {
++ CSIO_LNE_NONE = (uint32_t)0,
++ CSIO_LNE_LINKUP,
++ CSIO_LNE_FAB_INIT_DONE,
++ CSIO_LNE_LINK_DOWN,
++ CSIO_LNE_DOWN_LINK,
++ CSIO_LNE_LOGO,
++ CSIO_LNE_CLOSE,
++ CSIO_LNE_MAX_EVENT,
++};
++
++typedef void (*csio_sm_state_t)(struct csio_lnode *ln, enum csio_ln_ev evt);
+
+ struct csio_sm {
+ struct list_head sm_list;
+@@ -83,7 +97,7 @@ struct csio_sm {
+ static inline void
+ csio_set_state(void *smp, void *state)
+ {
+- ((struct csio_sm *)smp)->sm_state = (csio_sm_state_t)state;
++ ((struct csio_sm *)smp)->sm_state = state;
+ }
+
+ static inline void
+diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c
+index d5ac938970232..5b3ffefae476d 100644
+--- a/drivers/scsi/csiostor/csio_lnode.c
++++ b/drivers/scsi/csiostor/csio_lnode.c
+@@ -1095,7 +1095,7 @@ csio_handle_link_down(struct csio_hw *hw, uint8_t portid, uint32_t fcfi,
+ int
+ csio_is_lnode_ready(struct csio_lnode *ln)
+ {
+- return (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_ready));
++ return (csio_get_state(ln) == csio_lns_ready);
+ }
+
+ /*****************************************************************************/
+@@ -1366,15 +1366,15 @@ csio_free_fcfinfo(struct kref *kref)
+ void
+ csio_lnode_state_to_str(struct csio_lnode *ln, int8_t *str)
+ {
+- if (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_uninit)) {
++ if (csio_get_state(ln) == csio_lns_uninit) {
+ strcpy(str, "UNINIT");
+ return;
+ }
+- if (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_ready)) {
++ if (csio_get_state(ln) == csio_lns_ready) {
+ strcpy(str, "READY");
+ return;
+ }
+- if (csio_get_state(ln) == ((csio_sm_state_t)csio_lns_offline)) {
++ if (csio_get_state(ln) == csio_lns_offline) {
+ strcpy(str, "OFFLINE");
+ return;
+ }
+diff --git a/drivers/scsi/csiostor/csio_lnode.h b/drivers/scsi/csiostor/csio_lnode.h
+index 372a67d122d38..607698a0f0631 100644
+--- a/drivers/scsi/csiostor/csio_lnode.h
++++ b/drivers/scsi/csiostor/csio_lnode.h
+@@ -53,19 +53,6 @@
+ extern int csio_fcoe_rnodes;
+ extern int csio_fdmi_enable;
+
+-/* State machine evets */
+-enum csio_ln_ev {
+- CSIO_LNE_NONE = (uint32_t)0,
+- CSIO_LNE_LINKUP,
+- CSIO_LNE_FAB_INIT_DONE,
+- CSIO_LNE_LINK_DOWN,
+- CSIO_LNE_DOWN_LINK,
+- CSIO_LNE_LOGO,
+- CSIO_LNE_CLOSE,
+- CSIO_LNE_MAX_EVENT,
+-};
+-
+-
+ struct csio_fcf_info {
+ struct list_head list;
+ uint8_t priority;
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index bbb7b2d9ffcfb..1abc62b07d24c 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1962,9 +1962,17 @@ static bool hisi_sas_internal_abort_timeout(struct sas_task *task,
+ struct hisi_sas_internal_abort_data *timeout = data;
+
+ if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0].itct) {
+- down(&hisi_hba->sem);
++ /*
++ * If timeout occurs in device gone scenario, to avoid
++ * circular dependency like:
++ * hisi_sas_dev_gone() -> down() -> ... ->
++ * hisi_sas_internal_abort_timeout() -> down().
++ */
++ if (!timeout->rst_ha_timeout)
++ down(&hisi_hba->sem);
+ hisi_hba->hw->debugfs_snapshot_regs(hisi_hba);
+- up(&hisi_hba->sem);
++ if (!timeout->rst_ha_timeout)
++ up(&hisi_hba->sem);
+ }
+
+ if (task->task_state_flags & SAS_TASK_STATE_DONE) {
+diff --git a/drivers/soc/fsl/dpio/dpio-service.c b/drivers/soc/fsl/dpio/dpio-service.c
+index 1d2b27e3ea63f..b811446e0fa55 100644
+--- a/drivers/soc/fsl/dpio/dpio-service.c
++++ b/drivers/soc/fsl/dpio/dpio-service.c
+@@ -523,7 +523,7 @@ int dpaa2_io_service_enqueue_multiple_desc_fq(struct dpaa2_io *d,
+ struct qbman_eq_desc *ed;
+ int i, ret;
+
+- ed = kcalloc(sizeof(struct qbman_eq_desc), 32, GFP_KERNEL);
++ ed = kcalloc(32, sizeof(struct qbman_eq_desc), GFP_KERNEL);
+ if (!ed)
+ return -ENOMEM;
+
+diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
+index 4ca88eaebf06a..cbef0dea1d5d7 100644
+--- a/drivers/soc/qcom/llcc-qcom.c
++++ b/drivers/soc/qcom/llcc-qcom.c
+@@ -859,6 +859,8 @@ static int llcc_update_act_ctrl(u32 sid,
+ ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg,
+ slice_status, !(slice_status & status),
+ 0, LLCC_STATUS_READ_DELAY);
++ if (ret)
++ return ret;
+
+ if (drv_data->version >= LLCC_VERSION_4_1_0_0)
+ ret = regmap_write(drv_data->bcast_regmap, act_clear_reg,
+diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
+index 6349a0debeb57..a980020ab854f 100644
+--- a/drivers/soc/qcom/socinfo.c
++++ b/drivers/soc/qcom/socinfo.c
+@@ -124,7 +124,7 @@ static const char *const pmic_models[] = {
+ [50] = "PM8350B",
+ [51] = "PMR735A",
+ [52] = "PMR735B",
+- [55] = "PM2250",
++ [55] = "PM4125",
+ [58] = "PM8450",
+ [65] = "PM8010",
+ [69] = "PM8550VS",
+diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c
+index 11991eb126364..079035db7dd85 100644
+--- a/drivers/spi/spi-fsl-lpspi.c
++++ b/drivers/spi/spi-fsl-lpspi.c
+@@ -830,11 +830,11 @@ static int fsl_lpspi_probe(struct platform_device *pdev)
+
+ is_target = of_property_read_bool((&pdev->dev)->of_node, "spi-slave");
+ if (is_target)
+- controller = spi_alloc_target(&pdev->dev,
+- sizeof(struct fsl_lpspi_data));
++ controller = devm_spi_alloc_target(&pdev->dev,
++ sizeof(struct fsl_lpspi_data));
+ else
+- controller = spi_alloc_host(&pdev->dev,
+- sizeof(struct fsl_lpspi_data));
++ controller = devm_spi_alloc_host(&pdev->dev,
++ sizeof(struct fsl_lpspi_data));
+
+ if (!controller)
+ return -ENOMEM;
+diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
+index 833a1bb7a9143..c3e5cee18bea7 100644
+--- a/drivers/spi/spi-imx.c
++++ b/drivers/spi/spi-imx.c
+@@ -668,8 +668,8 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx,
+ ctrl |= (MX51_ECSPI_CTRL_MAX_BURST * BITS_PER_BYTE - 1)
+ << MX51_ECSPI_CTRL_BL_OFFSET;
+ else
+- ctrl |= spi_imx->count / DIV_ROUND_UP(spi_imx->bits_per_word,
+- BITS_PER_BYTE) * spi_imx->bits_per_word
++ ctrl |= (spi_imx->count / DIV_ROUND_UP(spi_imx->bits_per_word,
++ BITS_PER_BYTE) * spi_imx->bits_per_word - 1)
+ << MX51_ECSPI_CTRL_BL_OFFSET;
+ }
+ }
+diff --git a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
+index 2dc8ceb85374b..17b8baf749e6a 100644
+--- a/drivers/spi/spi-mem.c
++++ b/drivers/spi/spi-mem.c
+@@ -297,6 +297,49 @@ static void spi_mem_access_end(struct spi_mem *mem)
+ pm_runtime_put(ctlr->dev.parent);
+ }
+
++static void spi_mem_add_op_stats(struct spi_statistics __percpu *pcpu_stats,
++ const struct spi_mem_op *op, int exec_op_ret)
++{
++ struct spi_statistics *stats;
++ u64 len, l2len;
++
++ get_cpu();
++ stats = this_cpu_ptr(pcpu_stats);
++ u64_stats_update_begin(&stats->syncp);
++
++ /*
++ * We do not have the concept of messages or transfers. Let's consider
++ * that one operation is equivalent to one message and one transfer.
++ */
++ u64_stats_inc(&stats->messages);
++ u64_stats_inc(&stats->transfers);
++
++ /* Use the sum of all lengths as bytes count and histogram value. */
++ len = op->cmd.nbytes + op->addr.nbytes;
++ len += op->dummy.nbytes + op->data.nbytes;
++ u64_stats_add(&stats->bytes, len);
++ l2len = min(fls(len), SPI_STATISTICS_HISTO_SIZE) - 1;
++ u64_stats_inc(&stats->transfer_bytes_histo[l2len]);
++
++ /* Only account for data bytes as transferred bytes. */
++ if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_OUT)
++ u64_stats_add(&stats->bytes_tx, op->data.nbytes);
++ if (op->data.nbytes && op->data.dir == SPI_MEM_DATA_IN)
++ u64_stats_add(&stats->bytes_rx, op->data.nbytes);
++
++ /*
++ * A timeout is not an error, following the same behavior as
++ * spi_transfer_one_message().
++ */
++ if (exec_op_ret == -ETIMEDOUT)
++ u64_stats_inc(&stats->timedout);
++ else if (exec_op_ret)
++ u64_stats_inc(&stats->errors);
++
++ u64_stats_update_end(&stats->syncp);
++ put_cpu();
++}
++
+ /**
+ * spi_mem_exec_op() - Execute a memory operation
+ * @mem: the SPI memory
+@@ -339,8 +382,12 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
+ * read path) and expect the core to use the regular SPI
+ * interface in other cases.
+ */
+- if (!ret || ret != -ENOTSUPP || ret != -EOPNOTSUPP)
++ if (!ret || (ret != -ENOTSUPP && ret != -EOPNOTSUPP)) {
++ spi_mem_add_op_stats(ctlr->pcpu_statistics, op, ret);
++ spi_mem_add_op_stats(mem->spi->pcpu_statistics, op, ret);
++
+ return ret;
++ }
+ }
+
+ tmpbufsize = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
+diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c
+index 8d5d170d49cc4..109dac2e69df2 100644
+--- a/drivers/spi/spi-mt65xx.c
++++ b/drivers/spi/spi-mt65xx.c
+@@ -787,17 +787,19 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
+ mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, len);
+ mtk_spi_setup_packet(host);
+
+- cnt = mdata->xfer_len / 4;
+- iowrite32_rep(mdata->base + SPI_TX_DATA_REG,
+- trans->tx_buf + mdata->num_xfered, cnt);
++ if (trans->tx_buf) {
++ cnt = mdata->xfer_len / 4;
++ iowrite32_rep(mdata->base + SPI_TX_DATA_REG,
++ trans->tx_buf + mdata->num_xfered, cnt);
+
+- remainder = mdata->xfer_len % 4;
+- if (remainder > 0) {
+- reg_val = 0;
+- memcpy(®_val,
+- trans->tx_buf + (cnt * 4) + mdata->num_xfered,
+- remainder);
+- writel(reg_val, mdata->base + SPI_TX_DATA_REG);
++ remainder = mdata->xfer_len % 4;
++ if (remainder > 0) {
++ reg_val = 0;
++ memcpy(®_val,
++ trans->tx_buf + (cnt * 4) + mdata->num_xfered,
++ remainder);
++ writel(reg_val, mdata->base + SPI_TX_DATA_REG);
++ }
+ }
+
+ mtk_spi_enable_transfer(host);
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index f2170f4b50775..46f1535487608 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -1042,10 +1042,14 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
+ if (spi->mode & SPI_CS_HIGH)
+ enable = !enable;
+
+- if (spi_is_csgpiod(spi)) {
+- if (!spi->controller->set_cs_timing && !activate)
+- spi_delay_exec(&spi->cs_hold, NULL);
++ /*
++ * Handle chip select delays for GPIO based CS or controllers without
++ * programmable chip select timing.
++ */
++ if ((spi_is_csgpiod(spi) || !spi->controller->set_cs_timing) && !activate)
++ spi_delay_exec(&spi->cs_hold, NULL);
+
++ if (spi_is_csgpiod(spi)) {
+ if (!(spi->mode & SPI_NO_CS)) {
+ /*
+ * Historically ACPI has no means of the GPIO polarity and
+@@ -1079,16 +1083,16 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
+ if ((spi->controller->flags & SPI_CONTROLLER_GPIO_SS) &&
+ spi->controller->set_cs)
+ spi->controller->set_cs(spi, !enable);
+-
+- if (!spi->controller->set_cs_timing) {
+- if (activate)
+- spi_delay_exec(&spi->cs_setup, NULL);
+- else
+- spi_delay_exec(&spi->cs_inactive, NULL);
+- }
+ } else if (spi->controller->set_cs) {
+ spi->controller->set_cs(spi, !enable);
+ }
++
++ if (spi_is_csgpiod(spi) || !spi->controller->set_cs_timing) {
++ if (activate)
++ spi_delay_exec(&spi->cs_setup, NULL);
++ else
++ spi_delay_exec(&spi->cs_inactive, NULL);
++ }
+ }
+
+ #ifdef CONFIG_HAS_DMA
+@@ -1747,13 +1751,37 @@ static int __spi_pump_transfer_message(struct spi_controller *ctlr,
+
+ trace_spi_message_start(msg);
+
+- ret = spi_split_transfers_maxsize(ctlr, msg,
+- spi_max_transfer_size(msg->spi),
+- GFP_KERNEL | GFP_DMA);
+- if (ret) {
+- msg->status = ret;
+- spi_finalize_current_message(ctlr);
+- return ret;
++ /*
++ * If an SPI controller does not support toggling the CS line on each
++ * transfer (indicated by the SPI_CS_WORD flag) or we are using a GPIO
++ * for the CS line, we can emulate the CS-per-word hardware function by
++ * splitting transfers into one-word transfers and ensuring that
++ * cs_change is set for each transfer.
++ */
++ if ((msg->spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) ||
++ spi_is_csgpiod(msg->spi))) {
++ ret = spi_split_transfers_maxwords(ctlr, msg, 1, GFP_KERNEL);
++ if (ret) {
++ msg->status = ret;
++ spi_finalize_current_message(ctlr);
++ return ret;
++ }
++
++ list_for_each_entry(xfer, &msg->transfers, transfer_list) {
++ /* Don't change cs_change on the last entry in the list */
++ if (list_is_last(&xfer->transfer_list, &msg->transfers))
++ break;
++ xfer->cs_change = 1;
++ }
++ } else {
++ ret = spi_split_transfers_maxsize(ctlr, msg,
++ spi_max_transfer_size(msg->spi),
++ GFP_KERNEL | GFP_DMA);
++ if (ret) {
++ msg->status = ret;
++ spi_finalize_current_message(ctlr);
++ return ret;
++ }
+ }
+
+ if (ctlr->prepare_message) {
+@@ -4063,33 +4091,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
+ if (list_empty(&message->transfers))
+ return -EINVAL;
+
+- /*
+- * If an SPI controller does not support toggling the CS line on each
+- * transfer (indicated by the SPI_CS_WORD flag) or we are using a GPIO
+- * for the CS line, we can emulate the CS-per-word hardware function by
+- * splitting transfers into one-word transfers and ensuring that
+- * cs_change is set for each transfer.
+- */
+- if ((spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) ||
+- spi_is_csgpiod(spi))) {
+- size_t maxsize = BITS_TO_BYTES(spi->bits_per_word);
+- int ret;
+-
+- /* spi_split_transfers_maxsize() requires message->spi */
+- message->spi = spi;
+-
+- ret = spi_split_transfers_maxsize(ctlr, message, maxsize,
+- GFP_KERNEL);
+- if (ret)
+- return ret;
+-
+- list_for_each_entry(xfer, &message->transfers, transfer_list) {
+- /* Don't change cs_change on the last entry in the list */
+- if (list_is_last(&xfer->transfer_list, &message->transfers))
+- break;
+- xfer->cs_change = 1;
+- }
+- }
++ message->spi = spi;
+
+ /*
+ * Half-duplex links include original MicroWire, and ones with
+@@ -4214,8 +4216,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message)
+ if (!ctlr->transfer)
+ return -ENOTSUPP;
+
+- message->spi = spi;
+-
+ SPI_STATISTICS_INCREMENT_FIELD(ctlr->pcpu_statistics, spi_async);
+ SPI_STATISTICS_INCREMENT_FIELD(spi->pcpu_statistics, spi_async);
+
+@@ -4395,8 +4395,6 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message)
+ if (status != 0)
+ return status;
+
+- message->spi = spi;
+-
+ SPI_STATISTICS_INCREMENT_FIELD(ctlr->pcpu_statistics, spi_sync);
+ SPI_STATISTICS_INCREMENT_FIELD(spi->pcpu_statistics, spi_sync);
+
+diff --git a/drivers/staging/greybus/light.c b/drivers/staging/greybus/light.c
+index 87d36948c6106..c6bd86a5335ab 100644
+--- a/drivers/staging/greybus/light.c
++++ b/drivers/staging/greybus/light.c
+@@ -100,15 +100,15 @@ static struct led_classdev *get_channel_cdev(struct gb_channel *channel)
+ static struct gb_channel *get_channel_from_mode(struct gb_light *light,
+ u32 mode)
+ {
+- struct gb_channel *channel = NULL;
++ struct gb_channel *channel;
+ int i;
+
+ for (i = 0; i < light->channels_count; i++) {
+ channel = &light->channels[i];
+- if (channel && channel->mode == mode)
+- break;
++ if (channel->mode == mode)
++ return channel;
+ }
+- return channel;
++ return NULL;
+ }
+
+ static int __gb_lights_flash_intensity_set(struct gb_channel *channel,
+diff --git a/drivers/staging/media/imx/imx-media-csc-scaler.c b/drivers/staging/media/imx/imx-media-csc-scaler.c
+index 1fd39a2fca98a..95cca281e8a37 100644
+--- a/drivers/staging/media/imx/imx-media-csc-scaler.c
++++ b/drivers/staging/media/imx/imx-media-csc-scaler.c
+@@ -803,6 +803,7 @@ static int ipu_csc_scaler_release(struct file *file)
+
+ dev_dbg(priv->dev, "Releasing instance %p\n", ctx);
+
++ v4l2_ctrl_handler_free(&ctx->ctrl_hdlr);
+ v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+ v4l2_fh_del(&ctx->fh);
+ v4l2_fh_exit(&ctx->fh);
+diff --git a/drivers/staging/media/starfive/camss/stf-capture.c b/drivers/staging/media/starfive/camss/stf-capture.c
+index 70c24b050a1b5..ec5169e7b3918 100644
+--- a/drivers/staging/media/starfive/camss/stf-capture.c
++++ b/drivers/staging/media/starfive/camss/stf-capture.c
+@@ -20,28 +20,28 @@ static const struct stfcamss_format_info stf_wr_fmts[] = {
+ .pixelformat = V4L2_PIX_FMT_SRGGB10,
+ .planes = 1,
+ .vsub = { 1 },
+- .bpp = 10,
++ .bpp = 16,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .pixelformat = V4L2_PIX_FMT_SGRBG10,
+ .planes = 1,
+ .vsub = { 1 },
+- .bpp = 10,
++ .bpp = 16,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SGBRG10_1X10,
+ .pixelformat = V4L2_PIX_FMT_SGBRG10,
+ .planes = 1,
+ .vsub = { 1 },
+- .bpp = 10,
++ .bpp = 16,
+ },
+ {
+ .code = MEDIA_BUS_FMT_SBGGR10_1X10,
+ .pixelformat = V4L2_PIX_FMT_SBGGR10,
+ .planes = 1,
+ .vsub = { 1 },
+- .bpp = 10,
++ .bpp = 16,
+ },
+ };
+
+diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+index 52e94c8f2f01a..780da4a8b5af1 100644
+--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c
+@@ -427,11 +427,11 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
+ unsigned int ctb_addr_x, ctb_addr_y;
+ struct cedrus_buffer *cedrus_buf;
+ dma_addr_t src_buf_addr;
+- dma_addr_t src_buf_end_addr;
+ u32 chroma_log2_weight_denom;
+ u32 num_entry_point_offsets;
+ u32 output_pic_list_index;
+ u32 pic_order_cnt[2];
++ size_t slice_bytes;
+ u8 padding;
+ int count;
+ u32 reg;
+@@ -443,6 +443,7 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
+ pred_weight_table = &slice_params->pred_weight_table;
+ num_entry_point_offsets = slice_params->num_entry_point_offsets;
+ cedrus_buf = vb2_to_cedrus_buffer(&run->dst->vb2_buf);
++ slice_bytes = vb2_get_plane_payload(&run->src->vb2_buf, 0);
+
+ /*
+ * If entry points offsets are present, we should get them
+@@ -490,7 +491,7 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
+
+ cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, 0);
+
+- reg = slice_params->bit_size;
++ reg = slice_bytes * 8;
+ cedrus_write(dev, VE_DEC_H265_BITS_LEN, reg);
+
+ /* Source beginning and end addresses. */
+@@ -504,10 +505,7 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
+
+ cedrus_write(dev, VE_DEC_H265_BITS_ADDR, reg);
+
+- src_buf_end_addr = src_buf_addr +
+- DIV_ROUND_UP(slice_params->bit_size, 8);
+-
+- reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr);
++ reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_addr + slice_bytes);
+ cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg);
+
+ /* Coding tree block address */
+diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
+index 98d9c80bd4c62..fd4bd650c77a6 100644
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -719,8 +719,10 @@ static int lvts_calibration_read(struct device *dev, struct lvts_domain *lvts_td
+
+ lvts_td->calib = devm_krealloc(dev, lvts_td->calib,
+ lvts_td->calib_len + len, GFP_KERNEL);
+- if (!lvts_td->calib)
++ if (!lvts_td->calib) {
++ kfree(efuse);
+ return -ENOMEM;
++ }
+
+ memcpy(lvts_td->calib + lvts_td->calib_len, efuse, len);
+
+diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
+index ccc2eea7f9f54..404f01cca4dab 100644
+--- a/drivers/thermal/qoriq_thermal.c
++++ b/drivers/thermal/qoriq_thermal.c
+@@ -57,6 +57,9 @@
+ #define REGS_TTRnCR(n) (0xf10 + 4 * (n)) /* Temperature Range n
+ * Control Register
+ */
++#define NUM_TTRCR_V1 4
++#define NUM_TTRCR_MAX 16
++
+ #define REGS_IPBRR(n) (0xbf8 + 4 * (n)) /* IP Block Revision
+ * Register n
+ */
+@@ -71,6 +74,7 @@ struct qoriq_sensor {
+
+ struct qoriq_tmu_data {
+ int ver;
++ u32 ttrcr[NUM_TTRCR_MAX];
+ struct regmap *regmap;
+ struct clk *clk;
+ struct qoriq_sensor sensor[SITES_MAX];
+@@ -182,17 +186,17 @@ static int qoriq_tmu_calibration(struct device *dev,
+ struct qoriq_tmu_data *data)
+ {
+ int i, val, len;
+- u32 range[4];
+ const u32 *calibration;
+ struct device_node *np = dev->of_node;
+
+ len = of_property_count_u32_elems(np, "fsl,tmu-range");
+- if (len < 0 || len > 4) {
++ if (len < 0 || (data->ver == TMU_VER1 && len > NUM_TTRCR_V1) ||
++ (data->ver > TMU_VER1 && len > NUM_TTRCR_MAX)) {
+ dev_err(dev, "invalid range data.\n");
+ return len;
+ }
+
+- val = of_property_read_u32_array(np, "fsl,tmu-range", range, len);
++ val = of_property_read_u32_array(np, "fsl,tmu-range", data->ttrcr, len);
+ if (val != 0) {
+ dev_err(dev, "failed to read range data.\n");
+ return val;
+@@ -200,7 +204,7 @@ static int qoriq_tmu_calibration(struct device *dev,
+
+ /* Init temperature range registers */
+ for (i = 0; i < len; i++)
+- regmap_write(data->regmap, REGS_TTRnCR(i), range[i]);
++ regmap_write(data->regmap, REGS_TTRnCR(i), data->ttrcr[i]);
+
+ calibration = of_get_property(np, "fsl,tmu-calibration", &len);
+ if (calibration == NULL || len % 8) {
+diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c
+index aac80b69a069c..afbf7738c7c47 100644
+--- a/drivers/tty/mips_ejtag_fdc.c
++++ b/drivers/tty/mips_ejtag_fdc.c
+@@ -309,7 +309,7 @@ static void mips_ejtag_fdc_console_write(struct console *c, const char *s,
+ unsigned int i, buf_len, cpu;
+ bool done_cr = false;
+ char buf[4];
+- const char *buf_ptr = buf;
++ const u8 *buf_ptr = buf;
+ /* Number of bytes of input data encoded up to each byte in buf */
+ u8 inc[4];
+
+diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
+index 23366f868ae3a..dab94835b6f5f 100644
+--- a/drivers/tty/serial/8250/8250_exar.c
++++ b/drivers/tty/serial/8250/8250_exar.c
+@@ -753,6 +753,7 @@ static void exar_pci_remove(struct pci_dev *pcidev)
+ for (i = 0; i < priv->nr; i++)
+ serial8250_unregister_port(priv->line[i]);
+
++ /* Ensure that every init quirk is properly torn down */
+ if (priv->board->exit)
+ priv->board->exit(pcidev);
+ }
+@@ -767,10 +768,6 @@ static int __maybe_unused exar_suspend(struct device *dev)
+ if (priv->line[i] >= 0)
+ serial8250_suspend_port(priv->line[i]);
+
+- /* Ensure that every init quirk is properly torn down */
+- if (priv->board->exit)
+- priv->board->exit(pcidev);
+-
+ return 0;
+ }
+
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index 10bf6d75bf9ee..f70e2c277ab7e 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -1461,7 +1461,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
+ if (!ret)
+ return 0;
+
+- dev_err(dev, "Unable to reguest IRQ %i\n", irq);
++ dev_err(dev, "Unable to request IRQ %i\n", irq);
+
+ out_uart:
+ for (i = 0; i < devtype->nr; i++) {
+diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
+index 71d17d804fdab..6fdb32b833466 100644
+--- a/drivers/tty/serial/samsung_tty.c
++++ b/drivers/tty/serial/samsung_tty.c
+@@ -987,11 +987,10 @@ static unsigned int s3c24xx_serial_tx_empty(struct uart_port *port)
+ if ((ufstat & info->tx_fifomask) != 0 ||
+ (ufstat & info->tx_fifofull))
+ return 0;
+-
+- return 1;
++ return TIOCSER_TEMT;
+ }
+
+- return s3c24xx_serial_txempty_nofifo(port);
++ return s3c24xx_serial_txempty_nofifo(port) ? TIOCSER_TEMT : 0;
+ }
+
+ /* no modem control lines */
+diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
+index 38a765eadbe2b..52e6ca1ba21df 100644
+--- a/drivers/tty/vt/vt.c
++++ b/drivers/tty/vt/vt.c
+@@ -2469,7 +2469,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
+ }
+ return;
+ case EScsiignore:
+- if (c >= 20 && c <= 0x3f)
++ if (c >= 0x20 && c <= 0x3f)
+ return;
+ vc->vc_state = ESnormal;
+ return;
+diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c
+index 12e76bb62c209..19bbc38f3d35d 100644
+--- a/drivers/usb/gadget/udc/net2272.c
++++ b/drivers/usb/gadget/udc/net2272.c
+@@ -2650,7 +2650,7 @@ net2272_plat_probe(struct platform_device *pdev)
+ goto err_req;
+ }
+
+- ret = net2272_probe_fin(dev, IRQF_TRIGGER_LOW);
++ ret = net2272_probe_fin(dev, irqflags);
+ if (ret)
+ goto err_io;
+
+diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
+index a7716202a8dd5..450adaca68eeb 100644
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -2533,7 +2533,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
+ if (xhci_add_interrupter(xhci, ir, 0))
+ goto fail;
+
+- xhci->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX;
++ ir->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX;
+
+ /*
+ * XXX: Might need to set the Interrupter Moderation Register to
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 4f64b814d4aa2..61bd29dd71a2f 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -3022,9 +3022,6 @@ static int xhci_handle_event(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
+ return 0;
+ }
+
+- /* Update SW event ring dequeue pointer */
+- inc_deq(xhci, ir->event_ring);
+-
+ /* Are there more items on the event ring? Caller will call us again to
+ * check.
+ */
+@@ -3038,30 +3035,26 @@ static int xhci_handle_event(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
+ */
+ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
+ struct xhci_interrupter *ir,
+- union xhci_trb *event_ring_deq,
+ bool clear_ehb)
+ {
+ u64 temp_64;
+ dma_addr_t deq;
+
+ temp_64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
+- /* If necessary, update the HW's version of the event ring deq ptr. */
+- if (event_ring_deq != ir->event_ring->dequeue) {
+- deq = xhci_trb_virt_to_dma(ir->event_ring->deq_seg,
+- ir->event_ring->dequeue);
+- if (deq == 0)
+- xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr\n");
+- /*
+- * Per 4.9.4, Software writes to the ERDP register shall
+- * always advance the Event Ring Dequeue Pointer value.
+- */
+- if ((temp_64 & ERST_PTR_MASK) == (deq & ERST_PTR_MASK))
+- return;
++ deq = xhci_trb_virt_to_dma(ir->event_ring->deq_seg,
++ ir->event_ring->dequeue);
++ if (deq == 0)
++ xhci_warn(xhci, "WARN something wrong with SW event ring dequeue ptr\n");
++ /*
++ * Per 4.9.4, Software writes to the ERDP register shall always advance
++ * the Event Ring Dequeue Pointer value.
++ */
++ if ((temp_64 & ERST_PTR_MASK) == (deq & ERST_PTR_MASK) && !clear_ehb)
++ return;
+
+- /* Update HC event ring dequeue pointer */
+- temp_64 = ir->event_ring->deq_seg->num & ERST_DESI_MASK;
+- temp_64 |= deq & ERST_PTR_MASK;
+- }
++ /* Update HC event ring dequeue pointer */
++ temp_64 = ir->event_ring->deq_seg->num & ERST_DESI_MASK;
++ temp_64 |= deq & ERST_PTR_MASK;
+
+ /* Clear the event handler busy flag (RW1C) */
+ if (clear_ehb)
+@@ -3069,6 +3062,19 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
+ xhci_write_64(xhci, temp_64, &ir->ir_set->erst_dequeue);
+ }
+
++/* Clear the interrupt pending bit for a specific interrupter. */
++static void xhci_clear_interrupt_pending(struct xhci_hcd *xhci,
++ struct xhci_interrupter *ir)
++{
++ if (!ir->ip_autoclear) {
++ u32 irq_pending;
++
++ irq_pending = readl(&ir->ir_set->irq_pending);
++ irq_pending |= IMAN_IP;
++ writel(irq_pending, &ir->ir_set->irq_pending);
++ }
++}
++
+ /*
+ * xHCI spec says we can get an interrupt, and if the HC has an error condition,
+ * we might get bad data out of the event ring. Section 4.10.2.7 has a list of
+@@ -3077,7 +3083,6 @@ static void xhci_update_erst_dequeue(struct xhci_hcd *xhci,
+ irqreturn_t xhci_irq(struct usb_hcd *hcd)
+ {
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+- union xhci_trb *event_ring_deq;
+ struct xhci_interrupter *ir;
+ irqreturn_t ret = IRQ_NONE;
+ u64 temp_64;
+@@ -3118,12 +3123,8 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
+
+ /* This is the handler of the primary interrupter */
+ ir = xhci->interrupters[0];
+- if (!hcd->msi_enabled) {
+- u32 irq_pending;
+- irq_pending = readl(&ir->ir_set->irq_pending);
+- irq_pending |= IMAN_IP;
+- writel(irq_pending, &ir->ir_set->irq_pending);
+- }
++
++ xhci_clear_interrupt_pending(xhci, ir);
+
+ if (xhci->xhc_state & XHCI_STATE_DYING ||
+ xhci->xhc_state & XHCI_STATE_HALTED) {
+@@ -3139,24 +3140,28 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
+ goto out;
+ }
+
+- event_ring_deq = ir->event_ring->dequeue;
+ /* FIXME this should be a delayed service routine
+ * that clears the EHB.
+ */
+ while (xhci_handle_event(xhci, ir) > 0) {
+- if (event_loop++ < TRBS_PER_SEGMENT / 2)
+- continue;
+- xhci_update_erst_dequeue(xhci, ir, event_ring_deq, false);
+- event_ring_deq = ir->event_ring->dequeue;
++ /*
++ * If half a segment of events have been handled in one go then
++ * update ERDP, and force isoc trbs to interrupt more often
++ */
++ if (event_loop++ > TRBS_PER_SEGMENT / 2) {
++ xhci_update_erst_dequeue(xhci, ir, false);
+
+- /* ring is half-full, force isoc trbs to interrupt more often */
+- if (xhci->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN)
+- xhci->isoc_bei_interval = xhci->isoc_bei_interval / 2;
++ if (ir->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN)
++ ir->isoc_bei_interval = ir->isoc_bei_interval / 2;
+
+- event_loop = 0;
++ event_loop = 0;
++ }
++
++ /* Update SW event ring dequeue pointer */
++ inc_deq(xhci, ir->event_ring);
+ }
+
+- xhci_update_erst_dequeue(xhci, ir, event_ring_deq, true);
++ xhci_update_erst_dequeue(xhci, ir, true);
+ ret = IRQ_HANDLED;
+
+ out:
+@@ -4019,7 +4024,8 @@ static int xhci_get_isoc_frame_id(struct xhci_hcd *xhci,
+ }
+
+ /* Check if we should generate event interrupt for a TD in an isoc URB */
+-static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i)
++static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i,
++ struct xhci_interrupter *ir)
+ {
+ if (xhci->hci_version < 0x100)
+ return false;
+@@ -4030,8 +4036,8 @@ static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i)
+ * If AVOID_BEI is set the host handles full event rings poorly,
+ * generate an event at least every 8th TD to clear the event ring
+ */
+- if (i && xhci->quirks & XHCI_AVOID_BEI)
+- return !!(i % xhci->isoc_bei_interval);
++ if (i && ir->isoc_bei_interval && xhci->quirks & XHCI_AVOID_BEI)
++ return !!(i % ir->isoc_bei_interval);
+
+ return true;
+ }
+@@ -4040,6 +4046,7 @@ static bool trb_block_event_intr(struct xhci_hcd *xhci, int num_tds, int i)
+ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
+ struct urb *urb, int slot_id, unsigned int ep_index)
+ {
++ struct xhci_interrupter *ir;
+ struct xhci_ring *ep_ring;
+ struct urb_priv *urb_priv;
+ struct xhci_td *td;
+@@ -4057,6 +4064,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
+
+ xep = &xhci->devs[slot_id]->eps[ep_index];
+ ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
++ ir = xhci->interrupters[0];
+
+ num_tds = urb->number_of_packets;
+ if (num_tds < 1) {
+@@ -4144,7 +4152,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
+ td->last_trb = ep_ring->enqueue;
+ td->last_trb_seg = ep_ring->enq_seg;
+ field |= TRB_IOC;
+- if (trb_block_event_intr(xhci, num_tds, i))
++ if (trb_block_event_intr(xhci, num_tds, i, ir))
+ field |= TRB_BEI;
+ }
+ /* Calculate TRB length */
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index c057c42c36f4c..0886829d53e51 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -538,6 +538,9 @@ int xhci_run(struct usb_hcd *hcd)
+ */
+
+ hcd->uses_new_polling = 1;
++ if (hcd->msi_enabled)
++ ir->ip_autoclear = true;
++
+ if (!usb_hcd_is_primary_hcd(hcd))
+ return xhci_run_finished(xhci);
+
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index 6f82d404883f9..bf05103aa68a0 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1688,6 +1688,8 @@ struct xhci_interrupter {
+ struct xhci_erst erst;
+ struct xhci_intr_reg __iomem *ir_set;
+ unsigned int intr_num;
++ bool ip_autoclear;
++ u32 isoc_bei_interval;
+ /* For interrupter registers save and restore over suspend/resume */
+ u32 s3_irq_pending;
+ u32 s3_irq_control;
+@@ -1760,7 +1762,6 @@ struct xhci_hcd {
+ u8 isoc_threshold;
+ /* imod_interval in ns (I * 250ns) */
+ u32 imod_interval;
+- u32 isoc_bei_interval;
+ int event_ring_max;
+ /* 4KB min, 128MB max */
+ int page_size;
+diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
+index 9ab50f26db607..16494030209ea 100644
+--- a/drivers/usb/phy/phy-generic.c
++++ b/drivers/usb/phy/phy-generic.c
+@@ -274,6 +274,13 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop)
+ return dev_err_probe(dev, PTR_ERR(nop->vbus_draw),
+ "could not get vbus regulator\n");
+
++ nop->vbus_draw = devm_regulator_get_exclusive(dev, "vbus");
++ if (PTR_ERR(nop->vbus_draw) == -ENODEV)
++ nop->vbus_draw = NULL;
++ if (IS_ERR(nop->vbus_draw))
++ return dev_err_probe(dev, PTR_ERR(nop->vbus_draw),
++ "could not get vbus regulator\n");
++
+ nop->dev = dev;
+ nop->phy.dev = nop->dev;
+ nop->phy.label = "nop-xceiv";
+diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
+index 778821bab7d93..ecfc16151d619 100644
+--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
++++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
+@@ -151,8 +151,6 @@ static void teardown_driver(struct mlx5_vdpa_net *ndev);
+
+ static bool mlx5_vdpa_debug;
+
+-#define MLX5_CVQ_MAX_ENT 16
+-
+ #define MLX5_LOG_VIO_FLAG(_feature) \
+ do { \
+ if (features & BIT_ULL(_feature)) \
+@@ -2276,9 +2274,16 @@ static void mlx5_vdpa_set_vq_num(struct vdpa_device *vdev, u16 idx, u32 num)
+ struct mlx5_vdpa_net *ndev = to_mlx5_vdpa_ndev(mvdev);
+ struct mlx5_vdpa_virtqueue *mvq;
+
+- if (!is_index_valid(mvdev, idx) || is_ctrl_vq_idx(mvdev, idx))
++ if (!is_index_valid(mvdev, idx))
+ return;
+
++ if (is_ctrl_vq_idx(mvdev, idx)) {
++ struct mlx5_control_vq *cvq = &mvdev->cvq;
++
++ cvq->vring.vring.num = num;
++ return;
++ }
++
+ mvq = &ndev->vqs[idx];
+ mvq->num_ent = num;
+ }
+@@ -2963,7 +2968,7 @@ static int setup_cvq_vring(struct mlx5_vdpa_dev *mvdev)
+ u16 idx = cvq->vring.last_avail_idx;
+
+ err = vringh_init_iotlb(&cvq->vring, mvdev->actual_features,
+- MLX5_CVQ_MAX_ENT, false,
++ cvq->vring.vring.num, false,
+ (struct vring_desc *)(uintptr_t)cvq->desc_addr,
+ (struct vring_avail *)(uintptr_t)cvq->driver_addr,
+ (struct vring_used *)(uintptr_t)cvq->device_addr);
+diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c
+index be2925d0d2836..18584ce70bf07 100644
+--- a/drivers/vdpa/vdpa_sim/vdpa_sim.c
++++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c
+@@ -160,7 +160,7 @@ static void vdpasim_do_reset(struct vdpasim *vdpasim, u32 flags)
+ }
+ }
+
+- vdpasim->running = true;
++ vdpasim->running = false;
+ spin_unlock(&vdpasim->iommu_lock);
+
+ vdpasim->features = 0;
+@@ -483,6 +483,7 @@ static void vdpasim_set_status(struct vdpa_device *vdpa, u8 status)
+
+ mutex_lock(&vdpasim->mutex);
+ vdpasim->status = status;
++ vdpasim->running = (status & VIRTIO_CONFIG_S_DRIVER_OK) != 0;
+ mutex_unlock(&vdpasim->mutex);
+ }
+
+diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c
+index 1cdc8543310b4..b8ff7046510eb 100644
+--- a/drivers/video/backlight/da9052_bl.c
++++ b/drivers/video/backlight/da9052_bl.c
+@@ -117,6 +117,7 @@ static int da9052_backlight_probe(struct platform_device *pdev)
+ wleds->led_reg = platform_get_device_id(pdev)->driver_data;
+ wleds->state = DA9052_WLEDS_OFF;
+
++ memset(&props, 0, sizeof(struct backlight_properties));
+ props.type = BACKLIGHT_RAW;
+ props.max_brightness = DA9052_MAX_BRIGHTNESS;
+
+diff --git a/drivers/video/backlight/hx8357.c b/drivers/video/backlight/hx8357.c
+index d7298376cf74d..bf18337ff0c2c 100644
+--- a/drivers/video/backlight/hx8357.c
++++ b/drivers/video/backlight/hx8357.c
+@@ -609,11 +609,13 @@ static int hx8357_probe(struct spi_device *spi)
+ lcd->im_pins = devm_gpiod_get_array_optional(dev, "im", GPIOD_OUT_LOW);
+ if (IS_ERR(lcd->im_pins))
+ return dev_err_probe(dev, PTR_ERR(lcd->im_pins), "failed to request im GPIOs\n");
+- if (lcd->im_pins->ndescs < HX8357_NUM_IM_PINS)
+- return dev_err_probe(dev, -EINVAL, "not enough im GPIOs\n");
++ if (lcd->im_pins) {
++ if (lcd->im_pins->ndescs < HX8357_NUM_IM_PINS)
++ return dev_err_probe(dev, -EINVAL, "not enough im GPIOs\n");
+
+- for (i = 0; i < HX8357_NUM_IM_PINS; i++)
+- gpiod_set_consumer_name(lcd->im_pins->desc[i], "im_pins");
++ for (i = 0; i < HX8357_NUM_IM_PINS; i++)
++ gpiod_set_consumer_name(lcd->im_pins->desc[i], "im_pins");
++ }
+
+ lcdev = devm_lcd_device_register(&spi->dev, "mxsfb", &spi->dev, lcd,
+ &hx8357_ops);
+diff --git a/drivers/video/backlight/ktz8866.c b/drivers/video/backlight/ktz8866.c
+index 9c980f2571ee3..014877b5a9848 100644
+--- a/drivers/video/backlight/ktz8866.c
++++ b/drivers/video/backlight/ktz8866.c
+@@ -97,20 +97,20 @@ static void ktz8866_init(struct ktz8866 *ktz)
+ {
+ unsigned int val = 0;
+
+- if (of_property_read_u32(ktz->client->dev.of_node, "current-num-sinks", &val))
++ if (!of_property_read_u32(ktz->client->dev.of_node, "current-num-sinks", &val))
+ ktz8866_write(ktz, BL_EN, BIT(val) - 1);
+ else
+ /* Enable all 6 current sinks if the number of current sinks isn't specified. */
+ ktz8866_write(ktz, BL_EN, BIT(6) - 1);
+
+- if (of_property_read_u32(ktz->client->dev.of_node, "kinetic,current-ramp-delay-ms", &val)) {
++ if (!of_property_read_u32(ktz->client->dev.of_node, "kinetic,current-ramp-delay-ms", &val)) {
+ if (val <= 128)
+ ktz8866_write(ktz, BL_CFG2, BIT(7) | (ilog2(val) << 3) | PWM_HYST);
+ else
+ ktz8866_write(ktz, BL_CFG2, BIT(7) | ((5 + val / 64) << 3) | PWM_HYST);
+ }
+
+- if (of_property_read_u32(ktz->client->dev.of_node, "kinetic,led-enable-ramp-delay-ms", &val)) {
++ if (!of_property_read_u32(ktz->client->dev.of_node, "kinetic,led-enable-ramp-delay-ms", &val)) {
+ if (val == 0)
+ ktz8866_write(ktz, BL_DIMMING, 0);
+ else {
+diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c
+index a3412c936ca28..26ff4178cc161 100644
+--- a/drivers/video/backlight/lm3630a_bl.c
++++ b/drivers/video/backlight/lm3630a_bl.c
+@@ -233,7 +233,7 @@ static int lm3630a_bank_a_get_brightness(struct backlight_device *bl)
+ if (rval < 0)
+ goto out_i2c_err;
+ brightness |= rval;
+- goto out;
++ return brightness;
+ }
+
+ /* disable sleep */
+@@ -244,11 +244,8 @@ static int lm3630a_bank_a_get_brightness(struct backlight_device *bl)
+ rval = lm3630a_read(pchip, REG_BRT_A);
+ if (rval < 0)
+ goto out_i2c_err;
+- brightness = rval;
++ return rval;
+
+-out:
+- bl->props.brightness = brightness;
+- return bl->props.brightness;
+ out_i2c_err:
+ dev_err(pchip->dev, "i2c failed to access register\n");
+ return 0;
+@@ -310,7 +307,7 @@ static int lm3630a_bank_b_get_brightness(struct backlight_device *bl)
+ if (rval < 0)
+ goto out_i2c_err;
+ brightness |= rval;
+- goto out;
++ return brightness;
+ }
+
+ /* disable sleep */
+@@ -321,11 +318,8 @@ static int lm3630a_bank_b_get_brightness(struct backlight_device *bl)
+ rval = lm3630a_read(pchip, REG_BRT_B);
+ if (rval < 0)
+ goto out_i2c_err;
+- brightness = rval;
++ return rval;
+
+-out:
+- bl->props.brightness = brightness;
+- return bl->props.brightness;
+ out_i2c_err:
+ dev_err(pchip->dev, "i2c failed to access register\n");
+ return 0;
+@@ -343,6 +337,7 @@ static int lm3630a_backlight_register(struct lm3630a_chip *pchip)
+ struct backlight_properties props;
+ const char *label;
+
++ memset(&props, 0, sizeof(struct backlight_properties));
+ props.type = BACKLIGHT_RAW;
+ if (pdata->leda_ctrl != LM3630A_LEDA_DISABLE) {
+ props.brightness = pdata->leda_init_brt;
+diff --git a/drivers/video/backlight/lm3639_bl.c b/drivers/video/backlight/lm3639_bl.c
+index 5246c171497d6..564f62acd7211 100644
+--- a/drivers/video/backlight/lm3639_bl.c
++++ b/drivers/video/backlight/lm3639_bl.c
+@@ -338,6 +338,7 @@ static int lm3639_probe(struct i2c_client *client)
+ }
+
+ /* backlight */
++ memset(&props, 0, sizeof(struct backlight_properties));
+ props.type = BACKLIGHT_RAW;
+ props.brightness = pdata->init_brt_led;
+ props.max_brightness = pdata->max_brt_led;
+diff --git a/drivers/video/backlight/lp8788_bl.c b/drivers/video/backlight/lp8788_bl.c
+index d1a14b0db265b..31f97230ee506 100644
+--- a/drivers/video/backlight/lp8788_bl.c
++++ b/drivers/video/backlight/lp8788_bl.c
+@@ -191,6 +191,7 @@ static int lp8788_backlight_register(struct lp8788_bl *bl)
+ int init_brt;
+ char *name;
+
++ memset(&props, 0, sizeof(struct backlight_properties));
+ props.type = BACKLIGHT_PLATFORM;
+ props.max_brightness = MAX_BRIGHTNESS;
+
+diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c
+index 6f58ee276ad1b..028a565250476 100644
+--- a/drivers/video/fbdev/simplefb.c
++++ b/drivers/video/fbdev/simplefb.c
+@@ -470,7 +470,7 @@ static int simplefb_attach_genpds(struct simplefb_par *par,
+ if (err == -ENOENT)
+ return 0;
+
+- dev_info(dev, "failed to parse power-domains: %d\n", err);
++ dev_err(dev, "failed to parse power-domains: %d\n", err);
+ return err;
+ }
+
+diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
+index 49299b1f9ec74..6f7e5010a6735 100644
+--- a/drivers/virtio/virtio_ring.c
++++ b/drivers/virtio/virtio_ring.c
+@@ -1340,7 +1340,7 @@ static int virtqueue_add_indirect_packed(struct vring_virtqueue *vq,
+ sizeof(struct vring_packed_desc));
+ vq->packed.vring.desc[head].id = cpu_to_le16(id);
+
+- if (vq->do_unmap) {
++ if (vq->use_dma_api) {
+ vq->packed.desc_extra[id].addr = addr;
+ vq->packed.desc_extra[id].len = total_sg *
+ sizeof(struct vring_packed_desc);
+@@ -1481,7 +1481,7 @@ static inline int virtqueue_add_packed(struct virtqueue *_vq,
+ desc[i].len = cpu_to_le32(sg->length);
+ desc[i].id = cpu_to_le16(id);
+
+- if (unlikely(vq->do_unmap)) {
++ if (unlikely(vq->use_dma_api)) {
+ vq->packed.desc_extra[curr].addr = addr;
+ vq->packed.desc_extra[curr].len = sg->length;
+ vq->packed.desc_extra[curr].flags =
+@@ -1615,7 +1615,7 @@ static void detach_buf_packed(struct vring_virtqueue *vq,
+ vq->free_head = id;
+ vq->vq.num_free += state->num;
+
+- if (unlikely(vq->do_unmap)) {
++ if (unlikely(vq->use_dma_api)) {
+ curr = id;
+ for (i = 0; i < state->num; i++) {
+ vring_unmap_extra_packed(vq,
+diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wdt.c
+index e28ead24c520e..df68ae4acbd7e 100644
+--- a/drivers/watchdog/starfive-wdt.c
++++ b/drivers/watchdog/starfive-wdt.c
+@@ -494,8 +494,13 @@ static int starfive_wdt_probe(struct platform_device *pdev)
+ if (ret)
+ goto err_exit;
+
+- if (!early_enable)
+- pm_runtime_put_sync(&pdev->dev);
++ if (!early_enable) {
++ if (pm_runtime_enabled(&pdev->dev)) {
++ ret = pm_runtime_put_sync(&pdev->dev);
++ if (ret)
++ goto err_exit;
++ }
++ }
+
+ return 0;
+
+diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
+index d9fd50df9802c..5404e03876202 100644
+--- a/drivers/watchdog/stm32_iwdg.c
++++ b/drivers/watchdog/stm32_iwdg.c
+@@ -20,6 +20,8 @@
+ #include <linux/platform_device.h>
+ #include <linux/watchdog.h>
+
++#define DEFAULT_TIMEOUT 10
++
+ /* IWDG registers */
+ #define IWDG_KR 0x00 /* Key register */
+ #define IWDG_PR 0x04 /* Prescaler Register */
+@@ -248,6 +250,7 @@ static int stm32_iwdg_probe(struct platform_device *pdev)
+ wdd->parent = dev;
+ wdd->info = &stm32_iwdg_info;
+ wdd->ops = &stm32_iwdg_ops;
++ wdd->timeout = DEFAULT_TIMEOUT;
+ wdd->min_timeout = DIV_ROUND_UP((RLR_MIN + 1) * PR_MIN, wdt->rate);
+ wdd->max_hw_heartbeat_ms = ((RLR_MAX + 1) * wdt->data->max_prescaler *
+ 1000) / wdt->rate;
+diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
+index 3b9f080109d7e..27553673e46bc 100644
+--- a/drivers/xen/events/events_base.c
++++ b/drivers/xen/events/events_base.c
+@@ -1190,7 +1190,7 @@ int xen_pirq_from_irq(unsigned irq)
+ EXPORT_SYMBOL_GPL(xen_pirq_from_irq);
+
+ static int bind_evtchn_to_irq_chip(evtchn_port_t evtchn, struct irq_chip *chip,
+- struct xenbus_device *dev)
++ struct xenbus_device *dev, bool shared)
+ {
+ int ret = -ENOMEM;
+ struct irq_info *info;
+@@ -1224,7 +1224,8 @@ static int bind_evtchn_to_irq_chip(evtchn_port_t evtchn, struct irq_chip *chip,
+ */
+ bind_evtchn_to_cpu(info, 0, false);
+ } else if (!WARN_ON(info->type != IRQT_EVTCHN)) {
+- info->refcnt++;
++ if (shared && !WARN_ON(info->refcnt < 0))
++ info->refcnt++;
+ }
+
+ ret = info->irq;
+@@ -1237,13 +1238,13 @@ static int bind_evtchn_to_irq_chip(evtchn_port_t evtchn, struct irq_chip *chip,
+
+ int bind_evtchn_to_irq(evtchn_port_t evtchn)
+ {
+- return bind_evtchn_to_irq_chip(evtchn, &xen_dynamic_chip, NULL);
++ return bind_evtchn_to_irq_chip(evtchn, &xen_dynamic_chip, NULL, false);
+ }
+ EXPORT_SYMBOL_GPL(bind_evtchn_to_irq);
+
+ int bind_evtchn_to_irq_lateeoi(evtchn_port_t evtchn)
+ {
+- return bind_evtchn_to_irq_chip(evtchn, &xen_lateeoi_chip, NULL);
++ return bind_evtchn_to_irq_chip(evtchn, &xen_lateeoi_chip, NULL, false);
+ }
+ EXPORT_SYMBOL_GPL(bind_evtchn_to_irq_lateeoi);
+
+@@ -1295,7 +1296,8 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
+
+ static int bind_interdomain_evtchn_to_irq_chip(struct xenbus_device *dev,
+ evtchn_port_t remote_port,
+- struct irq_chip *chip)
++ struct irq_chip *chip,
++ bool shared)
+ {
+ struct evtchn_bind_interdomain bind_interdomain;
+ int err;
+@@ -1307,14 +1309,14 @@ static int bind_interdomain_evtchn_to_irq_chip(struct xenbus_device *dev,
+ &bind_interdomain);
+
+ return err ? : bind_evtchn_to_irq_chip(bind_interdomain.local_port,
+- chip, dev);
++ chip, dev, shared);
+ }
+
+ int bind_interdomain_evtchn_to_irq_lateeoi(struct xenbus_device *dev,
+ evtchn_port_t remote_port)
+ {
+ return bind_interdomain_evtchn_to_irq_chip(dev, remote_port,
+- &xen_lateeoi_chip);
++ &xen_lateeoi_chip, false);
+ }
+ EXPORT_SYMBOL_GPL(bind_interdomain_evtchn_to_irq_lateeoi);
+
+@@ -1430,7 +1432,8 @@ static int bind_evtchn_to_irqhandler_chip(evtchn_port_t evtchn,
+ {
+ int irq, retval;
+
+- irq = bind_evtchn_to_irq_chip(evtchn, chip, NULL);
++ irq = bind_evtchn_to_irq_chip(evtchn, chip, NULL,
++ irqflags & IRQF_SHARED);
+ if (irq < 0)
+ return irq;
+ retval = request_irq(irq, handler, irqflags, devname, dev_id);
+@@ -1471,7 +1474,8 @@ static int bind_interdomain_evtchn_to_irqhandler_chip(
+ {
+ int irq, retval;
+
+- irq = bind_interdomain_evtchn_to_irq_chip(dev, remote_port, chip);
++ irq = bind_interdomain_evtchn_to_irq_chip(dev, remote_port, chip,
++ irqflags & IRQF_SHARED);
+ if (irq < 0)
+ return irq;
+
+diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c
+index 59717628ca42b..f6a2216c2c870 100644
+--- a/drivers/xen/evtchn.c
++++ b/drivers/xen/evtchn.c
+@@ -85,6 +85,7 @@ struct user_evtchn {
+ struct per_user_data *user;
+ evtchn_port_t port;
+ bool enabled;
++ bool unbinding;
+ };
+
+ static void evtchn_free_ring(evtchn_port_t *ring)
+@@ -164,6 +165,10 @@ static irqreturn_t evtchn_interrupt(int irq, void *data)
+ struct per_user_data *u = evtchn->user;
+ unsigned int prod, cons;
+
++ /* Handler might be called when tearing down the IRQ. */
++ if (evtchn->unbinding)
++ return IRQ_HANDLED;
++
+ WARN(!evtchn->enabled,
+ "Interrupt for port %u, but apparently not enabled; per-user %p\n",
+ evtchn->port, u);
+@@ -421,6 +426,7 @@ static void evtchn_unbind_from_user(struct per_user_data *u,
+
+ BUG_ON(irq < 0);
+
++ evtchn->unbinding = true;
+ unbind_from_irqhandler(irq, evtchn);
+
+ del_evtchn(u, evtchn);
+diff --git a/fs/afs/dir.c b/fs/afs/dir.c
+index 8a67fc427e748..67afe68972d5c 100644
+--- a/fs/afs/dir.c
++++ b/fs/afs/dir.c
+@@ -474,16 +474,6 @@ static int afs_dir_iterate_block(struct afs_vnode *dvnode,
+ continue;
+ }
+
+- /* Don't expose silly rename entries to userspace. */
+- if (nlen > 6 &&
+- dire->u.name[0] == '.' &&
+- ctx->actor != afs_lookup_filldir &&
+- ctx->actor != afs_lookup_one_filldir &&
+- memcmp(dire->u.name, ".__afs", 6) == 0) {
+- ctx->pos = blkoff + next * sizeof(union afs_xdr_dirent);
+- continue;
+- }
+-
+ /* found the next entry */
+ if (!dir_emit(ctx, dire->u.name, nlen,
+ ntohl(dire->u.vnode),
+diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c
+index 700a27bc8c257..ed04bd1eeae89 100644
+--- a/fs/afs/rotate.c
++++ b/fs/afs/rotate.c
+@@ -602,6 +602,8 @@ bool afs_select_fileserver(struct afs_operation *op)
+ goto wait_for_more_probe_results;
+
+ alist = op->estate->addresses;
++ best_prio = -1;
++ addr_index = 0;
+ for (i = 0; i < alist->nr_addrs; i++) {
+ if (alist->addrs[i].prio > best_prio) {
+ addr_index = i;
+@@ -609,9 +611,7 @@ bool afs_select_fileserver(struct afs_operation *op)
+ }
+ }
+
+- addr_index = READ_ONCE(alist->preferred);
+- if (!test_bit(addr_index, &set))
+- addr_index = __ffs(set);
++ alist->preferred = addr_index;
+
+ op->addr_index = addr_index;
+ set_bit(addr_index, &op->addr_tried);
+@@ -656,12 +656,6 @@ bool afs_select_fileserver(struct afs_operation *op)
+ next_server:
+ trace_afs_rotate(op, afs_rotate_trace_next_server, 0);
+ _debug("next");
+- ASSERT(op->estate);
+- alist = op->estate->addresses;
+- if (op->call_responded &&
+- op->addr_index != READ_ONCE(alist->preferred) &&
+- test_bit(alist->preferred, &op->addr_tried))
+- WRITE_ONCE(alist->preferred, op->addr_index);
+ op->estate = NULL;
+ goto pick_server;
+
+@@ -690,14 +684,7 @@ bool afs_select_fileserver(struct afs_operation *op)
+ failed:
+ trace_afs_rotate(op, afs_rotate_trace_failed, 0);
+ op->flags |= AFS_OPERATION_STOP;
+- if (op->estate) {
+- alist = op->estate->addresses;
+- if (op->call_responded &&
+- op->addr_index != READ_ONCE(alist->preferred) &&
+- test_bit(alist->preferred, &op->addr_tried))
+- WRITE_ONCE(alist->preferred, op->addr_index);
+- op->estate = NULL;
+- }
++ op->estate = NULL;
+ _leave(" = f [failed %d]", afs_op_error(op));
+ return false;
+ }
+diff --git a/fs/afs/validation.c b/fs/afs/validation.c
+index 46b37f2cce7d9..32a53fc8dfb26 100644
+--- a/fs/afs/validation.c
++++ b/fs/afs/validation.c
+@@ -122,6 +122,9 @@ bool afs_check_validity(const struct afs_vnode *vnode)
+ const struct afs_volume *volume = vnode->volume;
+ time64_t deadline = ktime_get_real_seconds() + 10;
+
++ if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
++ return true;
++
+ if (atomic_read(&volume->cb_v_check) != atomic_read(&volume->cb_v_break) ||
+ atomic64_read(&vnode->cb_expires_at) <= deadline ||
+ volume->cb_expires_at <= deadline ||
+@@ -389,12 +392,17 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
+ key_serial(key));
+
+ if (afs_check_validity(vnode))
+- return 0;
++ return test_bit(AFS_VNODE_DELETED, &vnode->flags) ? -ESTALE : 0;
+
+ ret = down_write_killable(&vnode->validate_lock);
+ if (ret < 0)
+ goto error;
+
++ if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
++ ret = -ESTALE;
++ goto error_unlock;
++ }
++
+ /* Validate a volume after the v_break has changed or the volume
+ * callback expired. We only want to do this once per volume per
+ * v_break change. The actual work will be done when parsing the
+@@ -448,12 +456,6 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
+ vnode->cb_ro_snapshot = cb_ro_snapshot;
+ vnode->cb_scrub = cb_scrub;
+
+- if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
+- _debug("file already deleted");
+- ret = -ESTALE;
+- goto error_unlock;
+- }
+-
+ /* if the vnode's data version number changed then its contents are
+ * different */
+ zap |= test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index 8b4bef05e2221..7761d7d93ba98 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -2453,12 +2453,65 @@ int try_release_extent_mapping(struct page *page, gfp_t mask)
+ return try_release_extent_state(tree, page, mask);
+ }
+
++struct btrfs_fiemap_entry {
++ u64 offset;
++ u64 phys;
++ u64 len;
++ u32 flags;
++};
++
+ /*
+- * To cache previous fiemap extent
++ * Indicate the caller of emit_fiemap_extent() that it needs to unlock the file
++ * range from the inode's io tree, unlock the subvolume tree search path, flush
++ * the fiemap cache and relock the file range and research the subvolume tree.
++ * The value here is something negative that can't be confused with a valid
++ * errno value and different from 1 because that's also a return value from
++ * fiemap_fill_next_extent() and also it's often used to mean some btree search
++ * did not find a key, so make it some distinct negative value.
++ */
++#define BTRFS_FIEMAP_FLUSH_CACHE (-(MAX_ERRNO + 1))
++
++/*
++ * Used to:
++ *
++ * - Cache the next entry to be emitted to the fiemap buffer, so that we can
++ * merge extents that are contiguous and can be grouped as a single one;
+ *
+- * Will be used for merging fiemap extent
++ * - Store extents ready to be written to the fiemap buffer in an intermediary
++ * buffer. This intermediary buffer is to ensure that in case the fiemap
++ * buffer is memory mapped to the fiemap target file, we don't deadlock
++ * during btrfs_page_mkwrite(). This is because during fiemap we are locking
++ * an extent range in order to prevent races with delalloc flushing and
++ * ordered extent completion, which is needed in order to reliably detect
++ * delalloc in holes and prealloc extents. And this can lead to a deadlock
++ * if the fiemap buffer is memory mapped to the file we are running fiemap
++ * against (a silly, useless in practice scenario, but possible) because
++ * btrfs_page_mkwrite() will try to lock the same extent range.
+ */
+ struct fiemap_cache {
++ /* An array of ready fiemap entries. */
++ struct btrfs_fiemap_entry *entries;
++ /* Number of entries in the entries array. */
++ int entries_size;
++ /* Index of the next entry in the entries array to write to. */
++ int entries_pos;
++ /*
++ * Once the entries array is full, this indicates what's the offset for
++ * the next file extent item we must search for in the inode's subvolume
++ * tree after unlocking the extent range in the inode's io tree and
++ * releasing the search path.
++ */
++ u64 next_search_offset;
++ /*
++ * This matches struct fiemap_extent_info::fi_mapped_extents, we use it
++ * to count ourselves emitted extents and stop instead of relying on
++ * fiemap_fill_next_extent() because we buffer ready fiemap entries at
++ * the @entries array, and we want to stop as soon as we hit the max
++ * amount of extents to map, not just to save time but also to make the
++ * logic at extent_fiemap() simpler.
++ */
++ unsigned int extents_mapped;
++ /* Fields for the cached extent (unsubmitted, not ready, extent). */
+ u64 offset;
+ u64 phys;
+ u64 len;
+@@ -2466,6 +2519,28 @@ struct fiemap_cache {
+ bool cached;
+ };
+
++static int flush_fiemap_cache(struct fiemap_extent_info *fieinfo,
++ struct fiemap_cache *cache)
++{
++ for (int i = 0; i < cache->entries_pos; i++) {
++ struct btrfs_fiemap_entry *entry = &cache->entries[i];
++ int ret;
++
++ ret = fiemap_fill_next_extent(fieinfo, entry->offset,
++ entry->phys, entry->len,
++ entry->flags);
++ /*
++ * Ignore 1 (reached max entries) because we keep track of that
++ * ourselves in emit_fiemap_extent().
++ */
++ if (ret < 0)
++ return ret;
++ }
++ cache->entries_pos = 0;
++
++ return 0;
++}
++
+ /*
+ * Helper to submit fiemap extent.
+ *
+@@ -2480,8 +2555,8 @@ static int emit_fiemap_extent(struct fiemap_extent_info *fieinfo,
+ struct fiemap_cache *cache,
+ u64 offset, u64 phys, u64 len, u32 flags)
+ {
++ struct btrfs_fiemap_entry *entry;
+ u64 cache_end;
+- int ret = 0;
+
+ /* Set at the end of extent_fiemap(). */
+ ASSERT((flags & FIEMAP_EXTENT_LAST) == 0);
+@@ -2494,7 +2569,9 @@ static int emit_fiemap_extent(struct fiemap_extent_info *fieinfo,
+ * find an extent that starts at an offset behind the end offset of the
+ * previous extent we processed. This happens if fiemap is called
+ * without FIEMAP_FLAG_SYNC and there are ordered extents completing
+- * while we call btrfs_next_leaf() (through fiemap_next_leaf_item()).
++ * after we had to unlock the file range, release the search path, emit
++ * the fiemap extents stored in the buffer (cache->entries array) and
++ * the lock the remainder of the range and re-search the btree.
+ *
+ * For example we are in leaf X processing its last item, which is the
+ * file extent item for file range [512K, 1M[, and after
+@@ -2607,11 +2684,35 @@ static int emit_fiemap_extent(struct fiemap_extent_info *fieinfo,
+
+ emit:
+ /* Not mergeable, need to submit cached one */
+- ret = fiemap_fill_next_extent(fieinfo, cache->offset, cache->phys,
+- cache->len, cache->flags);
+- cache->cached = false;
+- if (ret)
+- return ret;
++
++ if (cache->entries_pos == cache->entries_size) {
++ /*
++ * We will need to research for the end offset of the last
++ * stored extent and not from the current offset, because after
++ * unlocking the range and releasing the path, if there's a hole
++ * between that end offset and this current offset, a new extent
++ * may have been inserted due to a new write, so we don't want
++ * to miss it.
++ */
++ entry = &cache->entries[cache->entries_size - 1];
++ cache->next_search_offset = entry->offset + entry->len;
++ cache->cached = false;
++
++ return BTRFS_FIEMAP_FLUSH_CACHE;
++ }
++
++ entry = &cache->entries[cache->entries_pos];
++ entry->offset = cache->offset;
++ entry->phys = cache->phys;
++ entry->len = cache->len;
++ entry->flags = cache->flags;
++ cache->entries_pos++;
++ cache->extents_mapped++;
++
++ if (cache->extents_mapped == fieinfo->fi_extents_max) {
++ cache->cached = false;
++ return 1;
++ }
+ assign:
+ cache->cached = true;
+ cache->offset = offset;
+@@ -2737,8 +2838,8 @@ static int fiemap_search_slot(struct btrfs_inode *inode, struct btrfs_path *path
+ * neighbour leaf).
+ * We also need the private clone because holding a read lock on an
+ * extent buffer of the subvolume's b+tree will make lockdep unhappy
+- * when we call fiemap_fill_next_extent(), because that may cause a page
+- * fault when filling the user space buffer with fiemap data.
++ * when we check if extents are shared, as backref walking may need to
++ * lock the same leaf we are processing.
+ */
+ clone = btrfs_clone_extent_buffer(path->nodes[0]);
+ if (!clone)
+@@ -2778,34 +2879,16 @@ static int fiemap_process_hole(struct btrfs_inode *inode,
+ * it beyond i_size.
+ */
+ while (cur_offset < end && cur_offset < i_size) {
+- struct extent_state *cached_state = NULL;
+ u64 delalloc_start;
+ u64 delalloc_end;
+ u64 prealloc_start;
+- u64 lockstart;
+- u64 lockend;
+ u64 prealloc_len = 0;
+ bool delalloc;
+
+- lockstart = round_down(cur_offset, inode->root->fs_info->sectorsize);
+- lockend = round_up(end, inode->root->fs_info->sectorsize);
+-
+- /*
+- * We are only locking for the delalloc range because that's the
+- * only thing that can change here. With fiemap we have a lock
+- * on the inode, so no buffered or direct writes can happen.
+- *
+- * However mmaps and normal page writeback will cause this to
+- * change arbitrarily. We have to lock the extent lock here to
+- * make sure that nobody messes with the tree while we're doing
+- * btrfs_find_delalloc_in_range.
+- */
+- lock_extent(&inode->io_tree, lockstart, lockend, &cached_state);
+ delalloc = btrfs_find_delalloc_in_range(inode, cur_offset, end,
+ delalloc_cached_state,
+ &delalloc_start,
+ &delalloc_end);
+- unlock_extent(&inode->io_tree, lockstart, lockend, &cached_state);
+ if (!delalloc)
+ break;
+
+@@ -2973,6 +3056,7 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
+ u64 start, u64 len)
+ {
+ const u64 ino = btrfs_ino(inode);
++ struct extent_state *cached_state = NULL;
+ struct extent_state *delalloc_cached_state = NULL;
+ struct btrfs_path *path;
+ struct fiemap_cache cache = { 0 };
+@@ -2985,26 +3069,33 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
+ bool stopped = false;
+ int ret;
+
++ cache.entries_size = PAGE_SIZE / sizeof(struct btrfs_fiemap_entry);
++ cache.entries = kmalloc_array(cache.entries_size,
++ sizeof(struct btrfs_fiemap_entry),
++ GFP_KERNEL);
+ backref_ctx = btrfs_alloc_backref_share_check_ctx();
+ path = btrfs_alloc_path();
+- if (!backref_ctx || !path) {
++ if (!cache.entries || !backref_ctx || !path) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
++restart:
+ range_start = round_down(start, sectorsize);
+ range_end = round_up(start + len, sectorsize);
+ prev_extent_end = range_start;
+
++ lock_extent(&inode->io_tree, range_start, range_end, &cached_state);
++
+ ret = fiemap_find_last_extent_offset(inode, path, &last_extent_end);
+ if (ret < 0)
+- goto out;
++ goto out_unlock;
+ btrfs_release_path(path);
+
+ path->reada = READA_FORWARD;
+ ret = fiemap_search_slot(inode, path, range_start);
+ if (ret < 0) {
+- goto out;
++ goto out_unlock;
+ } else if (ret > 0) {
+ /*
+ * No file extent item found, but we may have delalloc between
+@@ -3051,7 +3142,7 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
+ backref_ctx, 0, 0, 0,
+ prev_extent_end, hole_end);
+ if (ret < 0) {
+- goto out;
++ goto out_unlock;
+ } else if (ret > 0) {
+ /* fiemap_fill_next_extent() told us to stop. */
+ stopped = true;
+@@ -3107,7 +3198,7 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
+ extent_gen,
+ backref_ctx);
+ if (ret < 0)
+- goto out;
++ goto out_unlock;
+ else if (ret > 0)
+ flags |= FIEMAP_EXTENT_SHARED;
+ }
+@@ -3118,9 +3209,9 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
+ }
+
+ if (ret < 0) {
+- goto out;
++ goto out_unlock;
+ } else if (ret > 0) {
+- /* fiemap_fill_next_extent() told us to stop. */
++ /* emit_fiemap_extent() told us to stop. */
+ stopped = true;
+ break;
+ }
+@@ -3129,12 +3220,12 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
+ next_item:
+ if (fatal_signal_pending(current)) {
+ ret = -EINTR;
+- goto out;
++ goto out_unlock;
+ }
+
+ ret = fiemap_next_leaf_item(inode, path);
+ if (ret < 0) {
+- goto out;
++ goto out_unlock;
+ } else if (ret > 0) {
+ /* No more file extent items for this inode. */
+ break;
+@@ -3143,22 +3234,12 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
+ }
+
+ check_eof_delalloc:
+- /*
+- * Release (and free) the path before emitting any final entries to
+- * fiemap_fill_next_extent() to keep lockdep happy. This is because
+- * once we find no more file extent items exist, we may have a
+- * non-cloned leaf, and fiemap_fill_next_extent() can trigger page
+- * faults when copying data to the user space buffer.
+- */
+- btrfs_free_path(path);
+- path = NULL;
+-
+ if (!stopped && prev_extent_end < range_end) {
+ ret = fiemap_process_hole(inode, fieinfo, &cache,
+ &delalloc_cached_state, backref_ctx,
+ 0, 0, 0, prev_extent_end, range_end - 1);
+ if (ret < 0)
+- goto out;
++ goto out_unlock;
+ prev_extent_end = range_end;
+ }
+
+@@ -3166,28 +3247,16 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
+ const u64 i_size = i_size_read(&inode->vfs_inode);
+
+ if (prev_extent_end < i_size) {
+- struct extent_state *cached_state = NULL;
+ u64 delalloc_start;
+ u64 delalloc_end;
+- u64 lockstart;
+- u64 lockend;
+ bool delalloc;
+
+- lockstart = round_down(prev_extent_end, sectorsize);
+- lockend = round_up(i_size, sectorsize);
+-
+- /*
+- * See the comment in fiemap_process_hole as to why
+- * we're doing the locking here.
+- */
+- lock_extent(&inode->io_tree, lockstart, lockend, &cached_state);
+ delalloc = btrfs_find_delalloc_in_range(inode,
+ prev_extent_end,
+ i_size - 1,
+ &delalloc_cached_state,
+ &delalloc_start,
+ &delalloc_end);
+- unlock_extent(&inode->io_tree, lockstart, lockend, &cached_state);
+ if (!delalloc)
+ cache.flags |= FIEMAP_EXTENT_LAST;
+ } else {
+@@ -3195,9 +3264,39 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
+ }
+ }
+
++out_unlock:
++ unlock_extent(&inode->io_tree, range_start, range_end, &cached_state);
++
++ if (ret == BTRFS_FIEMAP_FLUSH_CACHE) {
++ btrfs_release_path(path);
++ ret = flush_fiemap_cache(fieinfo, &cache);
++ if (ret)
++ goto out;
++ len -= cache.next_search_offset - start;
++ start = cache.next_search_offset;
++ goto restart;
++ } else if (ret < 0) {
++ goto out;
++ }
++
++ /*
++ * Must free the path before emitting to the fiemap buffer because we
++ * may have a non-cloned leaf and if the fiemap buffer is memory mapped
++ * to a file, a write into it (through btrfs_page_mkwrite()) may trigger
++ * waiting for an ordered extent that in order to complete needs to
++ * modify that leaf, therefore leading to a deadlock.
++ */
++ btrfs_free_path(path);
++ path = NULL;
++
++ ret = flush_fiemap_cache(fieinfo, &cache);
++ if (ret)
++ goto out;
++
+ ret = emit_last_fiemap_cache(fieinfo, &cache);
+ out:
+ free_extent_state(delalloc_cached_state);
++ kfree(cache.entries);
+ btrfs_free_backref_share_ctx(backref_ctx);
+ btrfs_free_path(path);
+ return ret;
+diff --git a/fs/ceph/file.c b/fs/ceph/file.c
+index abe8028d95bf4..3d1cd079dbf16 100644
+--- a/fs/ceph/file.c
++++ b/fs/ceph/file.c
+@@ -1138,7 +1138,12 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
+ }
+
+ idx = 0;
+- left = ret > 0 ? ret : 0;
++ if (ret <= 0)
++ left = 0;
++ else if (off + ret > i_size)
++ left = i_size - off;
++ else
++ left = ret;
+ while (left > 0) {
+ size_t plen, copied;
+
+@@ -1167,15 +1172,13 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
+ }
+
+ if (ret > 0) {
+- if (off > *ki_pos) {
+- if (off >= i_size) {
+- *retry_op = CHECK_EOF;
+- ret = i_size - *ki_pos;
+- *ki_pos = i_size;
+- } else {
+- ret = off - *ki_pos;
+- *ki_pos = off;
+- }
++ if (off >= i_size) {
++ *retry_op = CHECK_EOF;
++ ret = i_size - *ki_pos;
++ *ki_pos = i_size;
++ } else {
++ ret = off - *ki_pos;
++ *ki_pos = off;
+ }
+
+ if (last_objver)
+diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c
+index 89a7c2453aae6..122a4753ecea4 100644
+--- a/fs/erofs/fscache.c
++++ b/fs/erofs/fscache.c
+@@ -3,6 +3,7 @@
+ * Copyright (C) 2022, Alibaba Cloud
+ * Copyright (C) 2022, Bytedance Inc. All rights reserved.
+ */
++#include <linux/pseudo_fs.h>
+ #include <linux/fscache.h>
+ #include "internal.h"
+
+@@ -12,6 +13,18 @@ static LIST_HEAD(erofs_domain_list);
+ static LIST_HEAD(erofs_domain_cookies_list);
+ static struct vfsmount *erofs_pseudo_mnt;
+
++static int erofs_anon_init_fs_context(struct fs_context *fc)
++{
++ return init_pseudo(fc, EROFS_SUPER_MAGIC) ? 0 : -ENOMEM;
++}
++
++static struct file_system_type erofs_anon_fs_type = {
++ .owner = THIS_MODULE,
++ .name = "pseudo_erofs",
++ .init_fs_context = erofs_anon_init_fs_context,
++ .kill_sb = kill_anon_super,
++};
++
+ struct erofs_fscache_request {
+ struct erofs_fscache_request *primary;
+ struct netfs_cache_resources cache_resources;
+@@ -381,7 +394,7 @@ static int erofs_fscache_init_domain(struct super_block *sb)
+ goto out;
+
+ if (!erofs_pseudo_mnt) {
+- struct vfsmount *mnt = kern_mount(&erofs_fs_type);
++ struct vfsmount *mnt = kern_mount(&erofs_anon_fs_type);
+ if (IS_ERR(mnt)) {
+ err = PTR_ERR(mnt);
+ goto out;
+diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
+index b0409badb0172..410f5af623540 100644
+--- a/fs/erofs/internal.h
++++ b/fs/erofs/internal.h
+@@ -385,7 +385,6 @@ struct erofs_map_dev {
+ unsigned int m_deviceid;
+ };
+
+-extern struct file_system_type erofs_fs_type;
+ extern const struct super_operations erofs_sops;
+
+ extern const struct address_space_operations erofs_raw_access_aops;
+diff --git a/fs/erofs/super.c b/fs/erofs/super.c
+index 5f60f163bd56e..24788c230b494 100644
+--- a/fs/erofs/super.c
++++ b/fs/erofs/super.c
+@@ -579,13 +579,6 @@ static const struct export_operations erofs_export_ops = {
+ .get_parent = erofs_get_parent,
+ };
+
+-static int erofs_fc_fill_pseudo_super(struct super_block *sb, struct fs_context *fc)
+-{
+- static const struct tree_descr empty_descr = {""};
+-
+- return simple_fill_super(sb, EROFS_SUPER_MAGIC, &empty_descr);
+-}
+-
+ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
+ {
+ struct inode *inode;
+@@ -712,11 +705,6 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
+ return 0;
+ }
+
+-static int erofs_fc_anon_get_tree(struct fs_context *fc)
+-{
+- return get_tree_nodev(fc, erofs_fc_fill_pseudo_super);
+-}
+-
+ static int erofs_fc_get_tree(struct fs_context *fc)
+ {
+ struct erofs_fs_context *ctx = fc->fs_private;
+@@ -789,20 +777,10 @@ static const struct fs_context_operations erofs_context_ops = {
+ .free = erofs_fc_free,
+ };
+
+-static const struct fs_context_operations erofs_anon_context_ops = {
+- .get_tree = erofs_fc_anon_get_tree,
+-};
+-
+ static int erofs_init_fs_context(struct fs_context *fc)
+ {
+ struct erofs_fs_context *ctx;
+
+- /* pseudo mount for anon inodes */
+- if (fc->sb_flags & SB_KERNMOUNT) {
+- fc->ops = &erofs_anon_context_ops;
+- return 0;
+- }
+-
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+@@ -824,12 +802,6 @@ static void erofs_kill_sb(struct super_block *sb)
+ {
+ struct erofs_sb_info *sbi;
+
+- /* pseudo mount for anon inodes */
+- if (sb->s_flags & SB_KERNMOUNT) {
+- kill_anon_super(sb);
+- return;
+- }
+-
+ if (erofs_is_fscache_mode(sb))
+ kill_anon_super(sb);
+ else
+@@ -868,7 +840,7 @@ static void erofs_put_super(struct super_block *sb)
+ erofs_fscache_unregister_fs(sb);
+ }
+
+-struct file_system_type erofs_fs_type = {
++static struct file_system_type erofs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "erofs",
+ .init_fs_context = erofs_init_fs_context,
+diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
+index 677a9ad45dcb7..f38bdd46e4f77 100644
+--- a/fs/ext2/ext2.h
++++ b/fs/ext2/ext2.h
+@@ -674,7 +674,7 @@ struct ext2_inode_info {
+ struct inode vfs_inode;
+ struct list_head i_orphan; /* unlinked but open inodes */
+ #ifdef CONFIG_QUOTA
+- struct dquot *i_dquot[MAXQUOTAS];
++ struct dquot __rcu *i_dquot[MAXQUOTAS];
+ #endif
+ };
+
+diff --git a/fs/ext2/super.c b/fs/ext2/super.c
+index 01f9addc8b1f6..6d8587505cea3 100644
+--- a/fs/ext2/super.c
++++ b/fs/ext2/super.c
+@@ -320,7 +320,7 @@ static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data, siz
+ static ssize_t ext2_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off);
+ static int ext2_quota_on(struct super_block *sb, int type, int format_id,
+ const struct path *path);
+-static struct dquot **ext2_get_dquots(struct inode *inode)
++static struct dquot __rcu **ext2_get_dquots(struct inode *inode)
+ {
+ return EXT2_I(inode)->i_dquot;
+ }
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 023571f8dd1b4..4fb938ba3f359 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1158,7 +1158,7 @@ struct ext4_inode_info {
+ tid_t i_datasync_tid;
+
+ #ifdef CONFIG_QUOTA
+- struct dquot *i_dquot[MAXQUOTAS];
++ struct dquot __rcu *i_dquot[MAXQUOTAS];
+ #endif
+
+ /* Precomputed uuid+inum+igen checksum for seeding inode checksums */
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 0f931d0c227da..32bd83adf0bb8 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1600,7 +1600,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
+ static int ext4_quota_enable(struct super_block *sb, int type, int format_id,
+ unsigned int flags);
+
+-static struct dquot **ext4_get_dquots(struct inode *inode)
++static struct dquot __rcu **ext4_get_dquots(struct inode *inode)
+ {
+ return EXT4_I(inode)->i_dquot;
+ }
+diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
+index b0597a539fc54..9afc8d24dc369 100644
+--- a/fs/f2fs/checkpoint.c
++++ b/fs/f2fs/checkpoint.c
+@@ -1587,8 +1587,9 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+ */
+ if (f2fs_sb_has_encrypt(sbi) || f2fs_sb_has_verity(sbi) ||
+ f2fs_sb_has_compression(sbi))
+- invalidate_mapping_pages(META_MAPPING(sbi),
+- MAIN_BLKADDR(sbi), MAX_BLKADDR(sbi) - 1);
++ f2fs_bug_on(sbi,
++ invalidate_inode_pages2_range(META_MAPPING(sbi),
++ MAIN_BLKADDR(sbi), MAX_BLKADDR(sbi) - 1));
+
+ f2fs_release_ino_entry(sbi, false);
+
+diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
+index 531517dac0796..15f330d8fdb93 100644
+--- a/fs/f2fs/compress.c
++++ b/fs/f2fs/compress.c
+@@ -1418,6 +1418,8 @@ void f2fs_compress_write_end_io(struct bio *bio, struct page *page)
+ struct f2fs_sb_info *sbi = bio->bi_private;
+ struct compress_io_ctx *cic =
+ (struct compress_io_ctx *)page_private(page);
++ enum count_type type = WB_DATA_TYPE(page,
++ f2fs_is_compressed_page(page));
+ int i;
+
+ if (unlikely(bio->bi_status))
+@@ -1425,7 +1427,7 @@ void f2fs_compress_write_end_io(struct bio *bio, struct page *page)
+
+ f2fs_compress_free_page(page);
+
+- dec_page_count(sbi, F2FS_WB_DATA);
++ dec_page_count(sbi, type);
+
+ if (atomic_dec_return(&cic->pending_pages))
+ return;
+@@ -1441,12 +1443,14 @@ void f2fs_compress_write_end_io(struct bio *bio, struct page *page)
+ }
+
+ static int f2fs_write_raw_pages(struct compress_ctx *cc,
+- int *submitted,
++ int *submitted_p,
+ struct writeback_control *wbc,
+ enum iostat_type io_type)
+ {
+ struct address_space *mapping = cc->inode->i_mapping;
+- int _submitted, compr_blocks, ret, i;
++ struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
++ int submitted, compr_blocks, i;
++ int ret = 0;
+
+ compr_blocks = f2fs_compressed_blocks(cc);
+
+@@ -1461,6 +1465,10 @@ static int f2fs_write_raw_pages(struct compress_ctx *cc,
+ if (compr_blocks < 0)
+ return compr_blocks;
+
++ /* overwrite compressed cluster w/ normal cluster */
++ if (compr_blocks > 0)
++ f2fs_lock_op(sbi);
++
+ for (i = 0; i < cc->cluster_size; i++) {
+ if (!cc->rpages[i])
+ continue;
+@@ -1485,7 +1493,7 @@ static int f2fs_write_raw_pages(struct compress_ctx *cc,
+ if (!clear_page_dirty_for_io(cc->rpages[i]))
+ goto continue_unlock;
+
+- ret = f2fs_write_single_data_page(cc->rpages[i], &_submitted,
++ ret = f2fs_write_single_data_page(cc->rpages[i], &submitted,
+ NULL, NULL, wbc, io_type,
+ compr_blocks, false);
+ if (ret) {
+@@ -1493,26 +1501,29 @@ static int f2fs_write_raw_pages(struct compress_ctx *cc,
+ unlock_page(cc->rpages[i]);
+ ret = 0;
+ } else if (ret == -EAGAIN) {
++ ret = 0;
+ /*
+ * for quota file, just redirty left pages to
+ * avoid deadlock caused by cluster update race
+ * from foreground operation.
+ */
+ if (IS_NOQUOTA(cc->inode))
+- return 0;
+- ret = 0;
++ goto out;
+ f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT);
+ goto retry_write;
+ }
+- return ret;
++ goto out;
+ }
+
+- *submitted += _submitted;
++ *submitted_p += submitted;
+ }
+
+- f2fs_balance_fs(F2FS_M_SB(mapping), true);
++out:
++ if (compr_blocks > 0)
++ f2fs_unlock_op(sbi);
+
+- return 0;
++ f2fs_balance_fs(sbi, true);
++ return ret;
+ }
+
+ int f2fs_write_multi_pages(struct compress_ctx *cc,
+@@ -1806,16 +1817,18 @@ void f2fs_put_page_dic(struct page *page, bool in_task)
+ * check whether cluster blocks are contiguous, and add extent cache entry
+ * only if cluster blocks are logically and physically contiguous.
+ */
+-unsigned int f2fs_cluster_blocks_are_contiguous(struct dnode_of_data *dn)
++unsigned int f2fs_cluster_blocks_are_contiguous(struct dnode_of_data *dn,
++ unsigned int ofs_in_node)
+ {
+- bool compressed = f2fs_data_blkaddr(dn) == COMPRESS_ADDR;
++ bool compressed = data_blkaddr(dn->inode, dn->node_page,
++ ofs_in_node) == COMPRESS_ADDR;
+ int i = compressed ? 1 : 0;
+ block_t first_blkaddr = data_blkaddr(dn->inode, dn->node_page,
+- dn->ofs_in_node + i);
++ ofs_in_node + i);
+
+ for (i += 1; i < F2FS_I(dn->inode)->i_cluster_size; i++) {
+ block_t blkaddr = data_blkaddr(dn->inode, dn->node_page,
+- dn->ofs_in_node + i);
++ ofs_in_node + i);
+
+ if (!__is_valid_data_blkaddr(blkaddr))
+ break;
+diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
+index 26e317696b338..05158f89ef32d 100644
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -48,7 +48,7 @@ void f2fs_destroy_bioset(void)
+ bioset_exit(&f2fs_bioset);
+ }
+
+-static bool __is_cp_guaranteed(struct page *page)
++bool f2fs_is_cp_guaranteed(struct page *page)
+ {
+ struct address_space *mapping = page->mapping;
+ struct inode *inode;
+@@ -65,8 +65,6 @@ static bool __is_cp_guaranteed(struct page *page)
+ S_ISDIR(inode->i_mode))
+ return true;
+
+- if (f2fs_is_compressed_page(page))
+- return false;
+ if ((S_ISREG(inode->i_mode) && IS_NOQUOTA(inode)) ||
+ page_private_gcing(page))
+ return true;
+@@ -338,7 +336,7 @@ static void f2fs_write_end_io(struct bio *bio)
+
+ bio_for_each_segment_all(bvec, bio, iter_all) {
+ struct page *page = bvec->bv_page;
+- enum count_type type = WB_DATA_TYPE(page);
++ enum count_type type = WB_DATA_TYPE(page, false);
+
+ if (page_private_dummy(page)) {
+ clear_page_private_dummy(page);
+@@ -762,7 +760,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
+ wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE);
+
+ inc_page_count(fio->sbi, is_read_io(fio->op) ?
+- __read_io_type(page) : WB_DATA_TYPE(fio->page));
++ __read_io_type(page) : WB_DATA_TYPE(fio->page, false));
+
+ if (is_read_io(bio_op(bio)))
+ f2fs_submit_read_bio(fio->sbi, bio, fio->type);
+@@ -973,7 +971,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
+ if (fio->io_wbc)
+ wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE);
+
+- inc_page_count(fio->sbi, WB_DATA_TYPE(page));
++ inc_page_count(fio->sbi, WB_DATA_TYPE(page, false));
+
+ *fio->last_block = fio->new_blkaddr;
+ *fio->bio = bio;
+@@ -1007,11 +1005,12 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
+ enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
+ struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
+ struct page *bio_page;
++ enum count_type type;
+
+ f2fs_bug_on(sbi, is_read_io(fio->op));
+
+ f2fs_down_write(&io->io_rwsem);
+-
++next:
+ #ifdef CONFIG_BLK_DEV_ZONED
+ if (f2fs_sb_has_blkzoned(sbi) && btype < META && io->zone_pending_bio) {
+ wait_for_completion_io(&io->zone_wait);
+@@ -1021,7 +1020,6 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
+ }
+ #endif
+
+-next:
+ if (fio->in_list) {
+ spin_lock(&io->io_lock);
+ if (list_empty(&io->io_list)) {
+@@ -1046,7 +1044,8 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
+ /* set submitted = true as a return value */
+ fio->submitted = 1;
+
+- inc_page_count(sbi, WB_DATA_TYPE(bio_page));
++ type = WB_DATA_TYPE(bio_page, fio->compressed_page);
++ inc_page_count(sbi, type);
+
+ if (io->bio &&
+ (!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio,
+@@ -1059,7 +1058,8 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
+ if (F2FS_IO_ALIGNED(sbi) &&
+ (fio->type == DATA || fio->type == NODE) &&
+ fio->new_blkaddr & F2FS_IO_SIZE_MASK(sbi)) {
+- dec_page_count(sbi, WB_DATA_TYPE(bio_page));
++ dec_page_count(sbi, WB_DATA_TYPE(bio_page,
++ fio->compressed_page));
+ fio->retry = 1;
+ goto skip;
+ }
+@@ -1080,10 +1080,6 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
+ io->last_block_in_bio = fio->new_blkaddr;
+
+ trace_f2fs_submit_page_write(fio->page, fio);
+-skip:
+- if (fio->in_list)
+- goto next;
+-out:
+ #ifdef CONFIG_BLK_DEV_ZONED
+ if (f2fs_sb_has_blkzoned(sbi) && btype < META &&
+ is_end_zone_blkaddr(sbi, fio->new_blkaddr)) {
+@@ -1096,6 +1092,10 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
+ __submit_merged_bio(io);
+ }
+ #endif
++skip:
++ if (fio->in_list)
++ goto next;
++out:
+ if (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN) ||
+ !f2fs_is_checkpoint_ready(sbi))
+ __submit_merged_bio(io);
+@@ -1218,7 +1218,8 @@ int f2fs_reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count)
+
+ if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC)))
+ return -EPERM;
+- if (unlikely((err = inc_valid_block_count(sbi, dn->inode, &count))))
++ err = inc_valid_block_count(sbi, dn->inode, &count, true);
++ if (unlikely(err))
+ return err;
+
+ trace_f2fs_reserve_new_blocks(dn->inode, dn->nid,
+@@ -1475,7 +1476,7 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
+
+ dn->data_blkaddr = f2fs_data_blkaddr(dn);
+ if (dn->data_blkaddr == NULL_ADDR) {
+- err = inc_valid_block_count(sbi, dn->inode, &count);
++ err = inc_valid_block_count(sbi, dn->inode, &count, true);
+ if (unlikely(err))
+ return err;
+ }
+@@ -2838,7 +2839,7 @@ int f2fs_write_single_data_page(struct page *page, int *submitted,
+ .encrypted_page = NULL,
+ .submitted = 0,
+ .compr_blocks = compr_blocks,
+- .need_lock = LOCK_RETRY,
++ .need_lock = compr_blocks ? LOCK_DONE : LOCK_RETRY,
+ .post_read = f2fs_post_read_required(inode) ? 1 : 0,
+ .io_type = io_type,
+ .io_wbc = wbc,
+@@ -2919,6 +2920,7 @@ int f2fs_write_single_data_page(struct page *page, int *submitted,
+ if (err == -EAGAIN) {
+ err = f2fs_do_write_data_page(&fio);
+ if (err == -EAGAIN) {
++ f2fs_bug_on(sbi, compr_blocks);
+ fio.need_lock = LOCK_REQ;
+ err = f2fs_do_write_data_page(&fio);
+ }
+diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
+index 042593aed1ec0..1b937f7d0414f 100644
+--- a/fs/f2fs/dir.c
++++ b/fs/f2fs/dir.c
+@@ -830,13 +830,14 @@ int f2fs_do_add_link(struct inode *dir, const struct qstr *name,
+ return err;
+ }
+
+-int f2fs_do_tmpfile(struct inode *inode, struct inode *dir)
++int f2fs_do_tmpfile(struct inode *inode, struct inode *dir,
++ struct f2fs_filename *fname)
+ {
+ struct page *page;
+ int err = 0;
+
+ f2fs_down_write(&F2FS_I(inode)->i_sem);
+- page = f2fs_init_inode_metadata(inode, dir, NULL, NULL);
++ page = f2fs_init_inode_metadata(inode, dir, fname, NULL);
+ if (IS_ERR(page)) {
+ err = PTR_ERR(page);
+ goto fail;
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index 65294e3b0bef8..5a6c35d70c7ad 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -75,6 +75,11 @@ struct f2fs_fault_info {
+
+ extern const char *f2fs_fault_name[FAULT_MAX];
+ #define IS_FAULT_SET(fi, type) ((fi)->inject_type & BIT(type))
++
++/* maximum retry count for injected failure */
++#define DEFAULT_FAILURE_RETRY_COUNT 8
++#else
++#define DEFAULT_FAILURE_RETRY_COUNT 1
+ #endif
+
+ /*
+@@ -829,7 +834,7 @@ struct f2fs_inode_info {
+ spinlock_t i_size_lock; /* protect last_disk_size */
+
+ #ifdef CONFIG_QUOTA
+- struct dquot *i_dquot[MAXQUOTAS];
++ struct dquot __rcu *i_dquot[MAXQUOTAS];
+
+ /* quota space reservation, managed internally by quota code */
+ qsize_t i_reserved_quota;
+@@ -1080,7 +1085,8 @@ struct f2fs_sm_info {
+ * f2fs monitors the number of several block types such as on-writeback,
+ * dirty dentry blocks, dirty node blocks, and dirty meta blocks.
+ */
+-#define WB_DATA_TYPE(p) (__is_cp_guaranteed(p) ? F2FS_WB_CP_DATA : F2FS_WB_DATA)
++#define WB_DATA_TYPE(p, f) \
++ (f || f2fs_is_cp_guaranteed(p) ? F2FS_WB_CP_DATA : F2FS_WB_DATA)
+ enum count_type {
+ F2FS_DIRTY_DENTS,
+ F2FS_DIRTY_DATA,
+@@ -2251,7 +2257,7 @@ static inline bool __allow_reserved_blocks(struct f2fs_sb_info *sbi,
+
+ static inline void f2fs_i_blocks_write(struct inode *, block_t, bool, bool);
+ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
+- struct inode *inode, blkcnt_t *count)
++ struct inode *inode, blkcnt_t *count, bool partial)
+ {
+ blkcnt_t diff = 0, release = 0;
+ block_t avail_user_block_count;
+@@ -2291,6 +2297,11 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
+ avail_user_block_count = 0;
+ }
+ if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) {
++ if (!partial) {
++ spin_unlock(&sbi->stat_lock);
++ goto enospc;
++ }
++
+ diff = sbi->total_valid_block_count - avail_user_block_count;
+ if (diff > *count)
+ diff = *count;
+@@ -3464,11 +3475,9 @@ bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
+ static inline void verify_blkaddr(struct f2fs_sb_info *sbi,
+ block_t blkaddr, int type)
+ {
+- if (!f2fs_is_valid_blkaddr(sbi, blkaddr, type)) {
++ if (!f2fs_is_valid_blkaddr(sbi, blkaddr, type))
+ f2fs_err(sbi, "invalid blkaddr: %u, type: %d, run fsck to fix.",
+ blkaddr, type);
+- f2fs_bug_on(sbi, 1);
+- }
+ }
+
+ static inline bool __is_valid_data_blkaddr(block_t blkaddr)
+@@ -3570,7 +3579,8 @@ int f2fs_do_add_link(struct inode *dir, const struct qstr *name,
+ struct inode *inode, nid_t ino, umode_t mode);
+ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
+ struct inode *dir, struct inode *inode);
+-int f2fs_do_tmpfile(struct inode *inode, struct inode *dir);
++int f2fs_do_tmpfile(struct inode *inode, struct inode *dir,
++ struct f2fs_filename *fname);
+ bool f2fs_empty_dir(struct inode *dir);
+
+ static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
+@@ -3804,6 +3814,7 @@ void f2fs_init_ckpt_req_control(struct f2fs_sb_info *sbi);
+ */
+ int __init f2fs_init_bioset(void);
+ void f2fs_destroy_bioset(void);
++bool f2fs_is_cp_guaranteed(struct page *page);
+ int f2fs_init_bio_entry_cache(void);
+ void f2fs_destroy_bio_entry_cache(void);
+ void f2fs_submit_read_bio(struct f2fs_sb_info *sbi, struct bio *bio,
+@@ -4287,7 +4298,8 @@ struct decompress_io_ctx *f2fs_alloc_dic(struct compress_ctx *cc);
+ void f2fs_decompress_end_io(struct decompress_io_ctx *dic, bool failed,
+ bool in_task);
+ void f2fs_put_page_dic(struct page *page, bool in_task);
+-unsigned int f2fs_cluster_blocks_are_contiguous(struct dnode_of_data *dn);
++unsigned int f2fs_cluster_blocks_are_contiguous(struct dnode_of_data *dn,
++ unsigned int ofs_in_node);
+ int f2fs_init_compress_ctx(struct compress_ctx *cc);
+ void f2fs_destroy_compress_ctx(struct compress_ctx *cc, bool reuse);
+ void f2fs_init_compress_info(struct f2fs_sb_info *sbi);
+@@ -4344,7 +4356,8 @@ static inline void f2fs_put_page_dic(struct page *page, bool in_task)
+ {
+ WARN_ON_ONCE(1);
+ }
+-static inline unsigned int f2fs_cluster_blocks_are_contiguous(struct dnode_of_data *dn) { return 0; }
++static inline unsigned int f2fs_cluster_blocks_are_contiguous(
++ struct dnode_of_data *dn, unsigned int ofs_in_node) { return 0; }
+ static inline bool f2fs_sanity_check_cluster(struct dnode_of_data *dn) { return false; }
+ static inline int f2fs_init_compress_inode(struct f2fs_sb_info *sbi) { return 0; }
+ static inline void f2fs_destroy_compress_inode(struct f2fs_sb_info *sbi) { }
+@@ -4401,15 +4414,24 @@ static inline bool f2fs_disable_compressed_file(struct inode *inode)
+ {
+ struct f2fs_inode_info *fi = F2FS_I(inode);
+
+- if (!f2fs_compressed_file(inode))
++ f2fs_down_write(&F2FS_I(inode)->i_sem);
++
++ if (!f2fs_compressed_file(inode)) {
++ f2fs_up_write(&F2FS_I(inode)->i_sem);
+ return true;
+- if (S_ISREG(inode->i_mode) && F2FS_HAS_BLOCKS(inode))
++ }
++ if (f2fs_is_mmap_file(inode) ||
++ (S_ISREG(inode->i_mode) && F2FS_HAS_BLOCKS(inode))) {
++ f2fs_up_write(&F2FS_I(inode)->i_sem);
+ return false;
++ }
+
+ fi->i_flags &= ~F2FS_COMPR_FL;
+ stat_dec_compr_inode(inode);
+ clear_inode_flag(inode, FI_COMPRESSED_FILE);
+ f2fs_mark_inode_dirty_sync(inode, true);
++
++ f2fs_up_write(&F2FS_I(inode)->i_sem);
+ return true;
+ }
+
+@@ -4613,10 +4635,36 @@ static inline bool f2fs_is_readonly(struct f2fs_sb_info *sbi)
+ return f2fs_sb_has_readonly(sbi) || f2fs_readonly(sbi->sb);
+ }
+
++static inline void f2fs_truncate_meta_inode_pages(struct f2fs_sb_info *sbi,
++ block_t blkaddr, unsigned int cnt)
++{
++ bool need_submit = false;
++ int i = 0;
++
++ do {
++ struct page *page;
++
++ page = find_get_page(META_MAPPING(sbi), blkaddr + i);
++ if (page) {
++ if (PageWriteback(page))
++ need_submit = true;
++ f2fs_put_page(page, 0);
++ }
++ } while (++i < cnt && !need_submit);
++
++ if (need_submit)
++ f2fs_submit_merged_write_cond(sbi, sbi->meta_inode,
++ NULL, 0, DATA);
++
++ truncate_inode_pages_range(META_MAPPING(sbi),
++ F2FS_BLK_TO_BYTES((loff_t)blkaddr),
++ F2FS_BLK_END_BYTES((loff_t)(blkaddr + cnt - 1)));
++}
++
+ static inline void f2fs_invalidate_internal_cache(struct f2fs_sb_info *sbi,
+ block_t blkaddr)
+ {
+- invalidate_mapping_pages(META_MAPPING(sbi), blkaddr, blkaddr);
++ f2fs_truncate_meta_inode_pages(sbi, blkaddr, 1);
+ f2fs_invalidate_compress_page(sbi, blkaddr);
+ }
+
+diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
+index b58ab1157b7ef..51970b345eeee 100644
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -39,6 +39,7 @@
+ static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf)
+ {
+ struct inode *inode = file_inode(vmf->vma->vm_file);
++ vm_flags_t flags = vmf->vma->vm_flags;
+ vm_fault_t ret;
+
+ ret = filemap_fault(vmf);
+@@ -46,7 +47,7 @@ static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf)
+ f2fs_update_iostat(F2FS_I_SB(inode), inode,
+ APP_MAPPED_READ_IO, F2FS_BLKSIZE);
+
+- trace_f2fs_filemap_fault(inode, vmf->pgoff, vmf->vma->vm_flags, ret);
++ trace_f2fs_filemap_fault(inode, vmf->pgoff, flags, ret);
+
+ return ret;
+ }
+@@ -3588,10 +3589,10 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg)
+ return ret;
+ }
+
+-static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count)
++static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count,
++ unsigned int *reserved_blocks)
+ {
+ struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
+- unsigned int reserved_blocks = 0;
+ int cluster_size = F2FS_I(dn->inode)->i_cluster_size;
+ block_t blkaddr;
+ int i;
+@@ -3614,40 +3615,53 @@ static int reserve_compress_blocks(struct dnode_of_data *dn, pgoff_t count)
+ blkcnt_t reserved;
+ int ret;
+
+- for (i = 0; i < cluster_size; i++, dn->ofs_in_node++) {
+- blkaddr = f2fs_data_blkaddr(dn);
++ for (i = 0; i < cluster_size; i++) {
++ blkaddr = data_blkaddr(dn->inode, dn->node_page,
++ dn->ofs_in_node + i);
+
+ if (i == 0) {
+- if (blkaddr == COMPRESS_ADDR)
+- continue;
+- dn->ofs_in_node += cluster_size;
+- goto next;
++ if (blkaddr != COMPRESS_ADDR) {
++ dn->ofs_in_node += cluster_size;
++ goto next;
++ }
++ continue;
+ }
+
+- if (__is_valid_data_blkaddr(blkaddr)) {
++ /*
++ * compressed cluster was not released due to it
++ * fails in release_compress_blocks(), so NEW_ADDR
++ * is a possible case.
++ */
++ if (blkaddr == NEW_ADDR ||
++ __is_valid_data_blkaddr(blkaddr)) {
+ compr_blocks++;
+ continue;
+ }
+-
+- f2fs_set_data_blkaddr(dn, NEW_ADDR);
+ }
+
+ reserved = cluster_size - compr_blocks;
+- ret = inc_valid_block_count(sbi, dn->inode, &reserved);
+- if (ret)
++
++ /* for the case all blocks in cluster were reserved */
++ if (reserved == 1)
++ goto next;
++
++ ret = inc_valid_block_count(sbi, dn->inode, &reserved, false);
++ if (unlikely(ret))
+ return ret;
+
+- if (reserved != cluster_size - compr_blocks)
+- return -ENOSPC;
++ for (i = 0; i < cluster_size; i++, dn->ofs_in_node++) {
++ if (f2fs_data_blkaddr(dn) == NULL_ADDR)
++ f2fs_set_data_blkaddr(dn, NEW_ADDR);
++ }
+
+ f2fs_i_compr_blocks_update(dn->inode, compr_blocks, true);
+
+- reserved_blocks += reserved;
++ *reserved_blocks += reserved;
+ next:
+ count -= cluster_size;
+ }
+
+- return reserved_blocks;
++ return 0;
+ }
+
+ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
+@@ -3671,9 +3685,6 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
+ if (ret)
+ return ret;
+
+- if (atomic_read(&F2FS_I(inode)->i_compr_blocks))
+- goto out;
+-
+ f2fs_balance_fs(sbi, true);
+
+ inode_lock(inode);
+@@ -3683,6 +3694,9 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
+ goto unlock_inode;
+ }
+
++ if (atomic_read(&F2FS_I(inode)->i_compr_blocks))
++ goto unlock_inode;
++
+ f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
+ filemap_invalidate_lock(inode->i_mapping);
+
+@@ -3708,7 +3722,7 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
+ count = min(end_offset - dn.ofs_in_node, last_idx - page_idx);
+ count = round_up(count, F2FS_I(inode)->i_cluster_size);
+
+- ret = reserve_compress_blocks(&dn, count);
++ ret = reserve_compress_blocks(&dn, count, &reserved_blocks);
+
+ f2fs_put_dnode(&dn);
+
+@@ -3716,23 +3730,21 @@ static int f2fs_reserve_compress_blocks(struct file *filp, unsigned long arg)
+ break;
+
+ page_idx += count;
+- reserved_blocks += ret;
+ }
+
+ filemap_invalidate_unlock(inode->i_mapping);
+ f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
+
+- if (ret >= 0) {
++ if (!ret) {
+ clear_inode_flag(inode, FI_COMPRESS_RELEASED);
+ inode_set_ctime_current(inode);
+ f2fs_mark_inode_dirty_sync(inode, true);
+ }
+ unlock_inode:
+ inode_unlock(inode);
+-out:
+ mnt_drop_write_file(filp);
+
+- if (ret >= 0) {
++ if (!ret) {
+ ret = put_user(reserved_blocks, (u64 __user *)arg);
+ } else if (reserved_blocks &&
+ atomic_read(&F2FS_I(inode)->i_compr_blocks)) {
+@@ -3981,16 +3993,20 @@ static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg)
+ sizeof(option)))
+ return -EFAULT;
+
+- if (!f2fs_compressed_file(inode) ||
+- option.log_cluster_size < MIN_COMPRESS_LOG_SIZE ||
+- option.log_cluster_size > MAX_COMPRESS_LOG_SIZE ||
+- option.algorithm >= COMPRESS_MAX)
++ if (option.log_cluster_size < MIN_COMPRESS_LOG_SIZE ||
++ option.log_cluster_size > MAX_COMPRESS_LOG_SIZE ||
++ option.algorithm >= COMPRESS_MAX)
+ return -EINVAL;
+
+ file_start_write(filp);
+ inode_lock(inode);
+
+ f2fs_down_write(&F2FS_I(inode)->i_sem);
++ if (!f2fs_compressed_file(inode)) {
++ ret = -EINVAL;
++ goto out;
++ }
++
+ if (f2fs_is_mmap_file(inode) || get_dirty_pages(inode)) {
+ ret = -EBUSY;
+ goto out;
+diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
+index b3bb815fc6aa4..550cc811e008a 100644
+--- a/fs/f2fs/namei.c
++++ b/fs/f2fs/namei.c
+@@ -852,7 +852,7 @@ static int f2fs_mknod(struct mnt_idmap *idmap, struct inode *dir,
+
+ static int __f2fs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
+ struct file *file, umode_t mode, bool is_whiteout,
+- struct inode **new_inode)
++ struct inode **new_inode, struct f2fs_filename *fname)
+ {
+ struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
+ struct inode *inode;
+@@ -880,7 +880,7 @@ static int __f2fs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
+ if (err)
+ goto out;
+
+- err = f2fs_do_tmpfile(inode, dir);
++ err = f2fs_do_tmpfile(inode, dir, fname);
+ if (err)
+ goto release_out;
+
+@@ -931,22 +931,24 @@ static int f2fs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
+ if (!f2fs_is_checkpoint_ready(sbi))
+ return -ENOSPC;
+
+- err = __f2fs_tmpfile(idmap, dir, file, mode, false, NULL);
++ err = __f2fs_tmpfile(idmap, dir, file, mode, false, NULL, NULL);
+
+ return finish_open_simple(file, err);
+ }
+
+ static int f2fs_create_whiteout(struct mnt_idmap *idmap,
+- struct inode *dir, struct inode **whiteout)
++ struct inode *dir, struct inode **whiteout,
++ struct f2fs_filename *fname)
+ {
+- return __f2fs_tmpfile(idmap, dir, NULL,
+- S_IFCHR | WHITEOUT_MODE, true, whiteout);
++ return __f2fs_tmpfile(idmap, dir, NULL, S_IFCHR | WHITEOUT_MODE,
++ true, whiteout, fname);
+ }
+
+ int f2fs_get_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
+ struct inode **new_inode)
+ {
+- return __f2fs_tmpfile(idmap, dir, NULL, S_IFREG, false, new_inode);
++ return __f2fs_tmpfile(idmap, dir, NULL, S_IFREG,
++ false, new_inode, NULL);
+ }
+
+ static int f2fs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
+@@ -990,7 +992,14 @@ static int f2fs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
+ }
+
+ if (flags & RENAME_WHITEOUT) {
+- err = f2fs_create_whiteout(idmap, old_dir, &whiteout);
++ struct f2fs_filename fname;
++
++ err = f2fs_setup_filename(old_dir, &old_dentry->d_name,
++ 0, &fname);
++ if (err)
++ return err;
++
++ err = f2fs_create_whiteout(idmap, old_dir, &whiteout, &fname);
+ if (err)
+ return err;
+ }
+diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
+index 9b546fd210100..2ea9c99e7dcb7 100644
+--- a/fs/f2fs/node.c
++++ b/fs/f2fs/node.c
+@@ -852,21 +852,29 @@ int f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
+
+ if (is_inode_flag_set(dn->inode, FI_COMPRESSED_FILE) &&
+ f2fs_sb_has_readonly(sbi)) {
+- unsigned int c_len = f2fs_cluster_blocks_are_contiguous(dn);
++ unsigned int cluster_size = F2FS_I(dn->inode)->i_cluster_size;
++ unsigned int ofs_in_node = dn->ofs_in_node;
++ pgoff_t fofs = index;
++ unsigned int c_len;
+ block_t blkaddr;
+
++ /* should align fofs and ofs_in_node to cluster_size */
++ if (fofs % cluster_size) {
++ fofs = round_down(fofs, cluster_size);
++ ofs_in_node = round_down(ofs_in_node, cluster_size);
++ }
++
++ c_len = f2fs_cluster_blocks_are_contiguous(dn, ofs_in_node);
+ if (!c_len)
+ goto out;
+
+- blkaddr = f2fs_data_blkaddr(dn);
++ blkaddr = data_blkaddr(dn->inode, dn->node_page, ofs_in_node);
+ if (blkaddr == COMPRESS_ADDR)
+ blkaddr = data_blkaddr(dn->inode, dn->node_page,
+- dn->ofs_in_node + 1);
++ ofs_in_node + 1);
+
+ f2fs_update_read_extent_tree_range_compressed(dn->inode,
+- index, blkaddr,
+- F2FS_I(dn->inode)->i_cluster_size,
+- c_len);
++ fofs, blkaddr, cluster_size, c_len);
+ }
+ out:
+ return 0;
+diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
+index d0f24ccbd1ac6..aad1d1a9b3d64 100644
+--- a/fs/f2fs/recovery.c
++++ b/fs/f2fs/recovery.c
+@@ -611,6 +611,19 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
+ return 0;
+ }
+
++static int f2fs_reserve_new_block_retry(struct dnode_of_data *dn)
++{
++ int i, err = 0;
++
++ for (i = DEFAULT_FAILURE_RETRY_COUNT; i > 0; i--) {
++ err = f2fs_reserve_new_block(dn);
++ if (!err)
++ break;
++ }
++
++ return err;
++}
++
+ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
+ struct page *page)
+ {
+@@ -712,14 +725,8 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
+ */
+ if (dest == NEW_ADDR) {
+ f2fs_truncate_data_blocks_range(&dn, 1);
+- do {
+- err = f2fs_reserve_new_block(&dn);
+- if (err == -ENOSPC) {
+- f2fs_bug_on(sbi, 1);
+- break;
+- }
+- } while (err &&
+- IS_ENABLED(CONFIG_F2FS_FAULT_INJECTION));
++
++ err = f2fs_reserve_new_block_retry(&dn);
+ if (err)
+ goto err;
+ continue;
+@@ -727,16 +734,8 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
+
+ /* dest is valid block, try to recover from src to dest */
+ if (f2fs_is_valid_blkaddr(sbi, dest, META_POR)) {
+-
+ if (src == NULL_ADDR) {
+- do {
+- err = f2fs_reserve_new_block(&dn);
+- if (err == -ENOSPC) {
+- f2fs_bug_on(sbi, 1);
+- break;
+- }
+- } while (err &&
+- IS_ENABLED(CONFIG_F2FS_FAULT_INJECTION));
++ err = f2fs_reserve_new_block_retry(&dn);
+ if (err)
+ goto err;
+ }
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+index 4c8836ded90fc..60531f50f37fe 100644
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -248,7 +248,7 @@ static int __replace_atomic_write_block(struct inode *inode, pgoff_t index,
+ } else {
+ blkcnt_t count = 1;
+
+- err = inc_valid_block_count(sbi, inode, &count);
++ err = inc_valid_block_count(sbi, inode, &count, true);
+ if (err) {
+ f2fs_put_dnode(&dn);
+ return err;
+@@ -3491,12 +3491,12 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
+ locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr));
+ locate_dirty_segment(sbi, GET_SEGNO(sbi, *new_blkaddr));
+
+- if (IS_DATASEG(type))
++ if (IS_DATASEG(curseg->seg_type))
+ atomic64_inc(&sbi->allocated_data_blocks);
+
+ up_write(&sit_i->sentry_lock);
+
+- if (page && IS_NODESEG(type)) {
++ if (page && IS_NODESEG(curseg->seg_type)) {
+ fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg));
+
+ f2fs_inode_chksum_set(sbi, page);
+@@ -3653,8 +3653,7 @@ int f2fs_inplace_write_data(struct f2fs_io_info *fio)
+ }
+
+ if (fio->post_read)
+- invalidate_mapping_pages(META_MAPPING(sbi),
+- fio->new_blkaddr, fio->new_blkaddr);
++ f2fs_truncate_meta_inode_pages(sbi, fio->new_blkaddr, 1);
+
+ stat_inc_inplace_blocks(fio->sbi);
+
+@@ -3844,7 +3843,7 @@ void f2fs_wait_on_block_writeback_range(struct inode *inode, block_t blkaddr,
+ for (i = 0; i < len; i++)
+ f2fs_wait_on_block_writeback(inode, blkaddr + i);
+
+- invalidate_mapping_pages(META_MAPPING(sbi), blkaddr, blkaddr + len - 1);
++ f2fs_truncate_meta_inode_pages(sbi, blkaddr, len);
+ }
+
+ static int read_compacted_summaries(struct f2fs_sb_info *sbi)
+diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
+index 8129be788bd56..c77a562831493 100644
+--- a/fs/f2fs/segment.h
++++ b/fs/f2fs/segment.h
+@@ -573,23 +573,22 @@ static inline bool has_curseg_enough_space(struct f2fs_sb_info *sbi,
+ unsigned int node_blocks, unsigned int dent_blocks)
+ {
+
+- unsigned int segno, left_blocks;
++ unsigned segno, left_blocks;
+ int i;
+
+- /* check current node segment */
++ /* check current node sections in the worst case. */
+ for (i = CURSEG_HOT_NODE; i <= CURSEG_COLD_NODE; i++) {
+ segno = CURSEG_I(sbi, i)->segno;
+- left_blocks = f2fs_usable_blks_in_seg(sbi, segno) -
+- get_seg_entry(sbi, segno)->ckpt_valid_blocks;
+-
++ left_blocks = CAP_BLKS_PER_SEC(sbi) -
++ get_ckpt_valid_blocks(sbi, segno, true);
+ if (node_blocks > left_blocks)
+ return false;
+ }
+
+- /* check current data segment */
++ /* check current data section for dentry blocks. */
+ segno = CURSEG_I(sbi, CURSEG_HOT_DATA)->segno;
+- left_blocks = f2fs_usable_blks_in_seg(sbi, segno) -
+- get_seg_entry(sbi, segno)->ckpt_valid_blocks;
++ left_blocks = CAP_BLKS_PER_SEC(sbi) -
++ get_ckpt_valid_blocks(sbi, segno, true);
+ if (dent_blocks > left_blocks)
+ return false;
+ return true;
+@@ -638,7 +637,7 @@ static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi,
+
+ if (free_secs > upper_secs)
+ return false;
+- else if (free_secs <= lower_secs)
++ if (free_secs <= lower_secs)
+ return true;
+ return !curseg_space;
+ }
+diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
+index d45ab0992ae59..4ba613ed3a179 100644
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -663,7 +663,7 @@ static int f2fs_set_lz4hc_level(struct f2fs_sb_info *sbi, const char *str)
+ #ifdef CONFIG_F2FS_FS_ZSTD
+ static int f2fs_set_zstd_level(struct f2fs_sb_info *sbi, const char *str)
+ {
+- unsigned int level;
++ int level;
+ int len = 4;
+
+ if (strlen(str) == len) {
+@@ -677,9 +677,15 @@ static int f2fs_set_zstd_level(struct f2fs_sb_info *sbi, const char *str)
+ f2fs_info(sbi, "wrong format, e.g. <alg_name>:<compr_level>");
+ return -EINVAL;
+ }
+- if (kstrtouint(str + 1, 10, &level))
++ if (kstrtoint(str + 1, 10, &level))
+ return -EINVAL;
+
++ /* f2fs does not support negative compress level now */
++ if (level < 0) {
++ f2fs_info(sbi, "do not support negative compress level: %d", level);
++ return -ERANGE;
++ }
++
+ if (!f2fs_is_compress_level_valid(COMPRESS_ZSTD, level)) {
+ f2fs_info(sbi, "invalid zstd compress level: %d", level);
+ return -EINVAL;
+@@ -2768,7 +2774,7 @@ int f2fs_dquot_initialize(struct inode *inode)
+ return dquot_initialize(inode);
+ }
+
+-static struct dquot **f2fs_get_dquots(struct inode *inode)
++static struct dquot __rcu **f2fs_get_dquots(struct inode *inode)
+ {
+ return F2FS_I(inode)->i_dquot;
+ }
+@@ -3930,11 +3936,6 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
+ return 0;
+
+ zone_sectors = bdev_zone_sectors(bdev);
+- if (!is_power_of_2(zone_sectors)) {
+- f2fs_err(sbi, "F2FS does not support non power of 2 zone sizes\n");
+- return -EINVAL;
+- }
+-
+ if (sbi->blocks_per_blkz && sbi->blocks_per_blkz !=
+ SECTOR_TO_BLOCK(zone_sectors))
+ return -EINVAL;
+diff --git a/fs/fcntl.c b/fs/fcntl.c
+index c80a6acad742f..3ff707bf2743a 100644
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -268,7 +268,7 @@ static int f_getowner_uids(struct file *filp, unsigned long arg)
+ }
+ #endif
+
+-static bool rw_hint_valid(enum rw_hint hint)
++static bool rw_hint_valid(u64 hint)
+ {
+ switch (hint) {
+ case RWH_WRITE_LIFE_NOT_SET:
+@@ -288,19 +288,17 @@ static long fcntl_rw_hint(struct file *file, unsigned int cmd,
+ {
+ struct inode *inode = file_inode(file);
+ u64 __user *argp = (u64 __user *)arg;
+- enum rw_hint hint;
+- u64 h;
++ u64 hint;
+
+ switch (cmd) {
+ case F_GET_RW_HINT:
+- h = inode->i_write_hint;
+- if (copy_to_user(argp, &h, sizeof(*argp)))
++ hint = inode->i_write_hint;
++ if (copy_to_user(argp, &hint, sizeof(*argp)))
+ return -EFAULT;
+ return 0;
+ case F_SET_RW_HINT:
+- if (copy_from_user(&h, argp, sizeof(h)))
++ if (copy_from_user(&hint, argp, sizeof(hint)))
+ return -EFAULT;
+- hint = (enum rw_hint) h;
+ if (!rw_hint_valid(hint))
+ return -EINVAL;
+
+diff --git a/fs/fhandle.c b/fs/fhandle.c
+index 18b3ba8dc8ead..57a12614addfd 100644
+--- a/fs/fhandle.c
++++ b/fs/fhandle.c
+@@ -36,7 +36,7 @@ static long do_sys_name_to_handle(const struct path *path,
+ if (f_handle.handle_bytes > MAX_HANDLE_SZ)
+ return -EINVAL;
+
+- handle = kmalloc(sizeof(struct file_handle) + f_handle.handle_bytes,
++ handle = kzalloc(sizeof(struct file_handle) + f_handle.handle_bytes,
+ GFP_KERNEL);
+ if (!handle)
+ return -ENOMEM;
+diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
+index b0cb704009963..ce9346099c72d 100644
+--- a/fs/hfsplus/wrapper.c
++++ b/fs/hfsplus/wrapper.c
+@@ -30,7 +30,7 @@ struct hfsplus_wd {
+ * @sector: block to read or write, for blocks of HFSPLUS_SECTOR_SIZE bytes
+ * @buf: buffer for I/O
+ * @data: output pointer for location of requested data
+- * @opf: request op flags
++ * @opf: I/O operation type and flags
+ *
+ * The unit of I/O is hfsplus_min_io_size(sb), which may be bigger than
+ * HFSPLUS_SECTOR_SIZE, and @buf must be sized accordingly. On reads
+diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
+index 093c4515b22a5..228fd2e05e12f 100644
+--- a/fs/iomap/buffered-io.c
++++ b/fs/iomap/buffered-io.c
+@@ -1833,16 +1833,10 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc,
+ if (unlikely(error)) {
+ /*
+ * Let the filesystem know what portion of the current page
+- * failed to map. If the page hasn't been added to ioend, it
+- * won't be affected by I/O completion and we must unlock it
+- * now.
++ * failed to map.
+ */
+ if (wpc->ops->discard_folio)
+ wpc->ops->discard_folio(folio, pos);
+- if (!count) {
+- folio_unlock(folio);
+- goto done;
+- }
+ }
+
+ /*
+@@ -1851,6 +1845,16 @@ iomap_writepage_map(struct iomap_writepage_ctx *wpc,
+ * all the dirty bits in the folio here.
+ */
+ iomap_clear_range_dirty(folio, 0, folio_size(folio));
++
++ /*
++ * If the page hasn't been added to the ioend, it won't be affected by
++ * I/O completion and we must unlock it now.
++ */
++ if (error && !count) {
++ folio_unlock(folio);
++ goto done;
++ }
++
+ folio_start_writeback(folio);
+ folio_unlock(folio);
+
+diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h
+index dd4264aa9bedd..10934f9a11be3 100644
+--- a/fs/jfs/jfs_incore.h
++++ b/fs/jfs/jfs_incore.h
+@@ -92,7 +92,7 @@ struct jfs_inode_info {
+ } link;
+ } u;
+ #ifdef CONFIG_QUOTA
+- struct dquot *i_dquot[MAXQUOTAS];
++ struct dquot __rcu *i_dquot[MAXQUOTAS];
+ #endif
+ u32 dev; /* will die when we get wide dev_t */
+ struct inode vfs_inode;
+diff --git a/fs/jfs/super.c b/fs/jfs/super.c
+index 8d8e556bd6104..ff135a43b5b7b 100644
+--- a/fs/jfs/super.c
++++ b/fs/jfs/super.c
+@@ -824,7 +824,7 @@ static ssize_t jfs_quota_write(struct super_block *sb, int type,
+ return len - towrite;
+ }
+
+-static struct dquot **jfs_get_dquots(struct inode *inode)
++static struct dquot __rcu **jfs_get_dquots(struct inode *inode)
+ {
+ return JFS_IP(inode)->i_dquot;
+ }
+diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
+index ef817a0475ffa..3e724cb7ef01d 100644
+--- a/fs/nfs/flexfilelayout/flexfilelayout.c
++++ b/fs/nfs/flexfilelayout/flexfilelayout.c
+@@ -2016,7 +2016,7 @@ static void ff_layout_cancel_io(struct pnfs_layout_segment *lseg)
+ for (idx = 0; idx < flseg->mirror_array_cnt; idx++) {
+ mirror = flseg->mirror_array[idx];
+ mirror_ds = mirror->mirror_ds;
+- if (!mirror_ds)
++ if (IS_ERR_OR_NULL(mirror_ds))
+ continue;
+ ds = mirror->mirror_ds->ds;
+ if (!ds)
+diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
+index 2d1bfee225c36..ddc1ee0319554 100644
+--- a/fs/nfs/fscache.c
++++ b/fs/nfs/fscache.c
+@@ -301,11 +301,11 @@ static void nfs_netfs_issue_read(struct netfs_io_subrequest *sreq)
+ struct inode *inode = sreq->rreq->inode;
+ struct nfs_open_context *ctx = sreq->rreq->netfs_priv;
+ struct page *page;
++ unsigned long idx;
+ int err;
+ pgoff_t start = (sreq->start + sreq->transferred) >> PAGE_SHIFT;
+ pgoff_t last = ((sreq->start + sreq->len -
+ sreq->transferred - 1) >> PAGE_SHIFT);
+- XA_STATE(xas, &sreq->rreq->mapping->i_pages, start);
+
+ nfs_pageio_init_read(&pgio, inode, false,
+ &nfs_async_read_completion_ops);
+@@ -316,19 +316,14 @@ static void nfs_netfs_issue_read(struct netfs_io_subrequest *sreq)
+
+ pgio.pg_netfs = netfs; /* used in completion */
+
+- xas_lock(&xas);
+- xas_for_each(&xas, page, last) {
++ xa_for_each_range(&sreq->rreq->mapping->i_pages, idx, page, start, last) {
+ /* nfs_read_add_folio() may schedule() due to pNFS layout and other RPCs */
+- xas_pause(&xas);
+- xas_unlock(&xas);
+ err = nfs_read_add_folio(&pgio, ctx, page_folio(page));
+ if (err < 0) {
+ netfs->error = err;
+ goto out;
+ }
+- xas_lock(&xas);
+ }
+- xas_unlock(&xas);
+ out:
+ nfs_pageio_complete_read(&pgio);
+ nfs_netfs_put(netfs);
+diff --git a/fs/nfs/nfs42.h b/fs/nfs/nfs42.h
+index b59876b01a1e3..0282d93c8bccb 100644
+--- a/fs/nfs/nfs42.h
++++ b/fs/nfs/nfs42.h
+@@ -55,11 +55,14 @@ int nfs42_proc_removexattr(struct inode *inode, const char *name);
+ * They would be 7 bytes long in the eventual buffer ("user.x\0"), and
+ * 8 bytes long XDR-encoded.
+ *
+- * Include the trailing eof word as well.
++ * Include the trailing eof word as well and make the result a multiple
++ * of 4 bytes.
+ */
+ static inline u32 nfs42_listxattr_xdrsize(u32 buflen)
+ {
+- return ((buflen / (XATTR_USER_PREFIX_LEN + 2)) * 8) + 4;
++ u32 size = 8 * buflen / (XATTR_USER_PREFIX_LEN + 2) + 4;
++
++ return (size + 3) & ~3;
+ }
+ #endif /* CONFIG_NFS_V4_2 */
+ #endif /* __LINUX_FS_NFS_NFS4_2_H */
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index 23819a7565085..b2ff8c7a21494 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -10615,29 +10615,33 @@ const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = {
+ static ssize_t nfs4_listxattr(struct dentry *dentry, char *list, size_t size)
+ {
+ ssize_t error, error2, error3;
++ size_t left = size;
+
+- error = generic_listxattr(dentry, list, size);
++ error = generic_listxattr(dentry, list, left);
+ if (error < 0)
+ return error;
+ if (list) {
+ list += error;
+- size -= error;
++ left -= error;
+ }
+
+- error2 = nfs4_listxattr_nfs4_label(d_inode(dentry), list, size);
++ error2 = nfs4_listxattr_nfs4_label(d_inode(dentry), list, left);
+ if (error2 < 0)
+ return error2;
+
+ if (list) {
+ list += error2;
+- size -= error2;
++ left -= error2;
+ }
+
+- error3 = nfs4_listxattr_nfs4_user(d_inode(dentry), list, size);
++ error3 = nfs4_listxattr_nfs4_user(d_inode(dentry), list, left);
+ if (error3 < 0)
+ return error3;
+
+- return error + error2 + error3;
++ error += error2 + error3;
++ if (size && error > size)
++ return -ERANGE;
++ return error;
+ }
+
+ static void nfs4_enable_swap(struct inode *inode)
+diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
+index 7600100ba26f0..432612d224374 100644
+--- a/fs/nfs/nfsroot.c
++++ b/fs/nfs/nfsroot.c
+@@ -175,10 +175,10 @@ static int __init root_nfs_cat(char *dest, const char *src,
+ size_t len = strlen(dest);
+
+ if (len && dest[len - 1] != ',')
+- if (strlcat(dest, ",", destlen) > destlen)
++ if (strlcat(dest, ",", destlen) >= destlen)
+ return -1;
+
+- if (strlcat(dest, src, destlen) > destlen)
++ if (strlcat(dest, src, destlen) >= destlen)
+ return -1;
+ return 0;
+ }
+diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
+index afd23910f3bff..88e061bd711b7 100644
+--- a/fs/nfs/pnfs_nfs.c
++++ b/fs/nfs/pnfs_nfs.c
+@@ -919,6 +919,8 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
+ dprintk("--> %s DS %s\n", __func__, ds->ds_remotestr);
+
+ list_for_each_entry(da, &ds->ds_addrs, da_node) {
++ char servername[48];
++
+ dprintk("%s: DS %s: trying address %s\n",
+ __func__, ds->ds_remotestr, da->da_remotestr);
+
+@@ -929,6 +931,7 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
+ .dstaddr = (struct sockaddr *)&da->da_addr,
+ .addrlen = da->da_addrlen,
+ .servername = clp->cl_hostname,
++ .xprtsec = clp->cl_xprtsec,
+ };
+ struct nfs4_add_xprt_data xprtdata = {
+ .clp = clp,
+@@ -938,10 +941,45 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
+ .data = &xprtdata,
+ };
+
+- if (da->da_transport != clp->cl_proto)
++ if (da->da_transport != clp->cl_proto &&
++ clp->cl_proto != XPRT_TRANSPORT_TCP_TLS)
+ continue;
++ if (da->da_transport == XPRT_TRANSPORT_TCP &&
++ mds_srv->nfs_client->cl_proto ==
++ XPRT_TRANSPORT_TCP_TLS) {
++ struct sockaddr *addr =
++ (struct sockaddr *)&da->da_addr;
++ struct sockaddr_in *sin =
++ (struct sockaddr_in *)&da->da_addr;
++ struct sockaddr_in6 *sin6 =
++ (struct sockaddr_in6 *)&da->da_addr;
++
++ /* for NFS with TLS we need to supply a correct
++ * servername of the trunked transport, not the
++ * servername of the main transport stored in
++ * clp->cl_hostname. And set the protocol to
++ * indicate to use TLS
++ */
++ servername[0] = '\0';
++ switch(addr->sa_family) {
++ case AF_INET:
++ snprintf(servername, sizeof(servername),
++ "%pI4", &sin->sin_addr.s_addr);
++ break;
++ case AF_INET6:
++ snprintf(servername, sizeof(servername),
++ "%pI6", &sin6->sin6_addr);
++ break;
++ default:
++ /* do not consider this address */
++ continue;
++ }
++ xprt_args.ident = XPRT_TRANSPORT_TCP_TLS;
++ xprt_args.servername = servername;
++ }
+ if (da->da_addr.ss_family != clp->cl_addr.ss_family)
+ continue;
++
+ /**
+ * Test this address for session trunking and
+ * add as an alias
+@@ -953,6 +991,10 @@ static int _nfs4_pnfs_v4_ds_connect(struct nfs_server *mds_srv,
+ if (xprtdata.cred)
+ put_cred(xprtdata.cred);
+ } else {
++ if (da->da_transport == XPRT_TRANSPORT_TCP &&
++ mds_srv->nfs_client->cl_proto ==
++ XPRT_TRANSPORT_TCP_TLS)
++ da->da_transport = XPRT_TRANSPORT_TCP_TLS;
+ clp = nfs4_set_ds_client(mds_srv,
+ &da->da_addr,
+ da->da_addrlen,
+diff --git a/fs/ocfs2/inode.h b/fs/ocfs2/inode.h
+index 82b28fdacc7e9..accf03d4765ed 100644
+--- a/fs/ocfs2/inode.h
++++ b/fs/ocfs2/inode.h
+@@ -65,7 +65,7 @@ struct ocfs2_inode_info
+ tid_t i_sync_tid;
+ tid_t i_datasync_tid;
+
+- struct dquot *i_dquot[MAXQUOTAS];
++ struct dquot __rcu *i_dquot[MAXQUOTAS];
+ };
+
+ /*
+diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
+index 6b906424902b4..1259fe02cd53b 100644
+--- a/fs/ocfs2/super.c
++++ b/fs/ocfs2/super.c
+@@ -122,7 +122,7 @@ static int ocfs2_susp_quotas(struct ocfs2_super *osb, int unsuspend);
+ static int ocfs2_enable_quotas(struct ocfs2_super *osb);
+ static void ocfs2_disable_quotas(struct ocfs2_super *osb);
+
+-static struct dquot **ocfs2_get_dquots(struct inode *inode)
++static struct dquot __rcu **ocfs2_get_dquots(struct inode *inode)
+ {
+ return OCFS2_I(inode)->i_dquot;
+ }
+diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
+index 8586e2f5d2439..0762575a1e708 100644
+--- a/fs/overlayfs/copy_up.c
++++ b/fs/overlayfs/copy_up.c
+@@ -234,11 +234,11 @@ static int ovl_verify_area(loff_t pos, loff_t pos2, loff_t len, loff_t totlen)
+ {
+ loff_t tmp;
+
+- if (WARN_ON_ONCE(pos != pos2))
++ if (pos != pos2)
+ return -EIO;
+- if (WARN_ON_ONCE(pos < 0 || len < 0 || totlen < 0))
++ if (pos < 0 || len < 0 || totlen < 0)
+ return -EIO;
+- if (WARN_ON_ONCE(check_add_overflow(pos, len, &tmp)))
++ if (check_add_overflow(pos, len, &tmp))
+ return -EIO;
+ return 0;
+ }
+diff --git a/fs/overlayfs/params.c b/fs/overlayfs/params.c
+index 112b4b12f8252..36dcc530ac286 100644
+--- a/fs/overlayfs/params.c
++++ b/fs/overlayfs/params.c
+@@ -280,12 +280,20 @@ static int ovl_mount_dir_check(struct fs_context *fc, const struct path *path,
+ {
+ struct ovl_fs_context *ctx = fc->fs_private;
+
+- if (ovl_dentry_weird(path->dentry))
+- return invalfc(fc, "filesystem on %s not supported", name);
+-
+ if (!d_is_dir(path->dentry))
+ return invalfc(fc, "%s is not a directory", name);
+
++ /*
++ * Root dentries of case-insensitive capable filesystems might
++ * not have the dentry operations set, but still be incompatible
++ * with overlayfs. Check explicitly to prevent post-mount
++ * failures.
++ */
++ if (sb_has_encoding(path->mnt->mnt_sb))
++ return invalfc(fc, "case-insensitive capable filesystem on %s not supported", name);
++
++ if (ovl_dentry_weird(path->dentry))
++ return invalfc(fc, "filesystem on %s not supported", name);
+
+ /*
+ * Check whether upper path is read-only here to report failures
+diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
+index d0d9bfdad30cc..56815799ce798 100644
+--- a/fs/pstore/inode.c
++++ b/fs/pstore/inode.c
+@@ -307,7 +307,6 @@ int pstore_put_backend_records(struct pstore_info *psi)
+ {
+ struct pstore_private *pos, *tmp;
+ struct dentry *root;
+- int rc = 0;
+
+ root = psinfo_lock_root();
+ if (!root)
+@@ -317,11 +316,8 @@ int pstore_put_backend_records(struct pstore_info *psi)
+ list_for_each_entry_safe(pos, tmp, &records_list, list) {
+ if (pos->record->psi == psi) {
+ list_del_init(&pos->list);
+- rc = simple_unlink(d_inode(root), pos->dentry);
+- if (WARN_ON(rc))
+- break;
+- d_drop(pos->dentry);
+- dput(pos->dentry);
++ d_invalidate(pos->dentry);
++ simple_unlink(d_inode(root), pos->dentry);
+ pos->dentry = NULL;
+ }
+ }
+@@ -329,7 +325,7 @@ int pstore_put_backend_records(struct pstore_info *psi)
+
+ inode_unlock(d_inode(root));
+
+- return rc;
++ return 0;
+ }
+
+ /*
+diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
+index 1f0c754416b64..51ff554dc875a 100644
+--- a/fs/quota/dquot.c
++++ b/fs/quota/dquot.c
+@@ -399,15 +399,17 @@ int dquot_mark_dquot_dirty(struct dquot *dquot)
+ EXPORT_SYMBOL(dquot_mark_dquot_dirty);
+
+ /* Dirtify all the dquots - this can block when journalling */
+-static inline int mark_all_dquot_dirty(struct dquot * const *dquot)
++static inline int mark_all_dquot_dirty(struct dquot __rcu * const *dquots)
+ {
+ int ret, err, cnt;
++ struct dquot *dquot;
+
+ ret = err = 0;
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+- if (dquot[cnt])
++ dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
++ if (dquot)
+ /* Even in case of error we have to continue */
+- ret = mark_dquot_dirty(dquot[cnt]);
++ ret = mark_dquot_dirty(dquot);
+ if (!err)
+ err = ret;
+ }
+@@ -998,14 +1000,14 @@ struct dquot *dqget(struct super_block *sb, struct kqid qid)
+ }
+ EXPORT_SYMBOL(dqget);
+
+-static inline struct dquot **i_dquot(struct inode *inode)
++static inline struct dquot __rcu **i_dquot(struct inode *inode)
+ {
+ return inode->i_sb->s_op->get_dquots(inode);
+ }
+
+ static int dqinit_needed(struct inode *inode, int type)
+ {
+- struct dquot * const *dquots;
++ struct dquot __rcu * const *dquots;
+ int cnt;
+
+ if (IS_NOQUOTA(inode))
+@@ -1095,14 +1097,16 @@ static void remove_dquot_ref(struct super_block *sb, int type)
+ */
+ spin_lock(&dq_data_lock);
+ if (!IS_NOQUOTA(inode)) {
+- struct dquot **dquots = i_dquot(inode);
+- struct dquot *dquot = dquots[type];
++ struct dquot __rcu **dquots = i_dquot(inode);
++ struct dquot *dquot = srcu_dereference_check(
++ dquots[type], &dquot_srcu,
++ lockdep_is_held(&dq_data_lock));
+
+ #ifdef CONFIG_QUOTA_DEBUG
+ if (unlikely(inode_get_rsv_space(inode) > 0))
+ reserved = 1;
+ #endif
+- dquots[type] = NULL;
++ rcu_assign_pointer(dquots[type], NULL);
+ if (dquot)
+ dqput(dquot);
+ }
+@@ -1455,7 +1459,8 @@ static int inode_quota_active(const struct inode *inode)
+ static int __dquot_initialize(struct inode *inode, int type)
+ {
+ int cnt, init_needed = 0;
+- struct dquot **dquots, *got[MAXQUOTAS] = {};
++ struct dquot __rcu **dquots;
++ struct dquot *got[MAXQUOTAS] = {};
+ struct super_block *sb = inode->i_sb;
+ qsize_t rsv;
+ int ret = 0;
+@@ -1530,7 +1535,7 @@ static int __dquot_initialize(struct inode *inode, int type)
+ if (!got[cnt])
+ continue;
+ if (!dquots[cnt]) {
+- dquots[cnt] = got[cnt];
++ rcu_assign_pointer(dquots[cnt], got[cnt]);
+ got[cnt] = NULL;
+ /*
+ * Make quota reservation system happy if someone
+@@ -1538,12 +1543,16 @@ static int __dquot_initialize(struct inode *inode, int type)
+ */
+ rsv = inode_get_rsv_space(inode);
+ if (unlikely(rsv)) {
++ struct dquot *dquot = srcu_dereference_check(
++ dquots[cnt], &dquot_srcu,
++ lockdep_is_held(&dq_data_lock));
++
+ spin_lock(&inode->i_lock);
+ /* Get reservation again under proper lock */
+ rsv = __inode_get_rsv_space(inode);
+- spin_lock(&dquots[cnt]->dq_dqb_lock);
+- dquots[cnt]->dq_dqb.dqb_rsvspace += rsv;
+- spin_unlock(&dquots[cnt]->dq_dqb_lock);
++ spin_lock(&dquot->dq_dqb_lock);
++ dquot->dq_dqb.dqb_rsvspace += rsv;
++ spin_unlock(&dquot->dq_dqb_lock);
+ spin_unlock(&inode->i_lock);
+ }
+ }
+@@ -1565,7 +1574,7 @@ EXPORT_SYMBOL(dquot_initialize);
+
+ bool dquot_initialize_needed(struct inode *inode)
+ {
+- struct dquot **dquots;
++ struct dquot __rcu **dquots;
+ int i;
+
+ if (!inode_quota_active(inode))
+@@ -1590,13 +1599,14 @@ EXPORT_SYMBOL(dquot_initialize_needed);
+ static void __dquot_drop(struct inode *inode)
+ {
+ int cnt;
+- struct dquot **dquots = i_dquot(inode);
++ struct dquot __rcu **dquots = i_dquot(inode);
+ struct dquot *put[MAXQUOTAS];
+
+ spin_lock(&dq_data_lock);
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+- put[cnt] = dquots[cnt];
+- dquots[cnt] = NULL;
++ put[cnt] = srcu_dereference_check(dquots[cnt], &dquot_srcu,
++ lockdep_is_held(&dq_data_lock));
++ rcu_assign_pointer(dquots[cnt], NULL);
+ }
+ spin_unlock(&dq_data_lock);
+ dqput_all(put);
+@@ -1604,7 +1614,7 @@ static void __dquot_drop(struct inode *inode)
+
+ void dquot_drop(struct inode *inode)
+ {
+- struct dquot * const *dquots;
++ struct dquot __rcu * const *dquots;
+ int cnt;
+
+ if (IS_NOQUOTA(inode))
+@@ -1677,7 +1687,8 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
+ int cnt, ret = 0, index;
+ struct dquot_warn warn[MAXQUOTAS];
+ int reserve = flags & DQUOT_SPACE_RESERVE;
+- struct dquot **dquots;
++ struct dquot __rcu **dquots;
++ struct dquot *dquot;
+
+ if (!inode_quota_active(inode)) {
+ if (reserve) {
+@@ -1697,27 +1708,26 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
+ index = srcu_read_lock(&dquot_srcu);
+ spin_lock(&inode->i_lock);
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+- if (!dquots[cnt])
++ dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
++ if (!dquot)
+ continue;
+ if (reserve) {
+- ret = dquot_add_space(dquots[cnt], 0, number, flags,
+- &warn[cnt]);
++ ret = dquot_add_space(dquot, 0, number, flags, &warn[cnt]);
+ } else {
+- ret = dquot_add_space(dquots[cnt], number, 0, flags,
+- &warn[cnt]);
++ ret = dquot_add_space(dquot, number, 0, flags, &warn[cnt]);
+ }
+ if (ret) {
+ /* Back out changes we already did */
+ for (cnt--; cnt >= 0; cnt--) {
+- if (!dquots[cnt])
++ dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
++ if (!dquot)
+ continue;
+- spin_lock(&dquots[cnt]->dq_dqb_lock);
++ spin_lock(&dquot->dq_dqb_lock);
+ if (reserve)
+- dquot_free_reserved_space(dquots[cnt],
+- number);
++ dquot_free_reserved_space(dquot, number);
+ else
+- dquot_decr_space(dquots[cnt], number);
+- spin_unlock(&dquots[cnt]->dq_dqb_lock);
++ dquot_decr_space(dquot, number);
++ spin_unlock(&dquot->dq_dqb_lock);
+ }
+ spin_unlock(&inode->i_lock);
+ goto out_flush_warn;
+@@ -1747,7 +1757,8 @@ int dquot_alloc_inode(struct inode *inode)
+ {
+ int cnt, ret = 0, index;
+ struct dquot_warn warn[MAXQUOTAS];
+- struct dquot * const *dquots;
++ struct dquot __rcu * const *dquots;
++ struct dquot *dquot;
+
+ if (!inode_quota_active(inode))
+ return 0;
+@@ -1758,17 +1769,19 @@ int dquot_alloc_inode(struct inode *inode)
+ index = srcu_read_lock(&dquot_srcu);
+ spin_lock(&inode->i_lock);
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+- if (!dquots[cnt])
++ dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
++ if (!dquot)
+ continue;
+- ret = dquot_add_inodes(dquots[cnt], 1, &warn[cnt]);
++ ret = dquot_add_inodes(dquot, 1, &warn[cnt]);
+ if (ret) {
+ for (cnt--; cnt >= 0; cnt--) {
+- if (!dquots[cnt])
++ dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
++ if (!dquot)
+ continue;
+ /* Back out changes we already did */
+- spin_lock(&dquots[cnt]->dq_dqb_lock);
+- dquot_decr_inodes(dquots[cnt], 1);
+- spin_unlock(&dquots[cnt]->dq_dqb_lock);
++ spin_lock(&dquot->dq_dqb_lock);
++ dquot_decr_inodes(dquot, 1);
++ spin_unlock(&dquot->dq_dqb_lock);
+ }
+ goto warn_put_all;
+ }
+@@ -1789,7 +1802,8 @@ EXPORT_SYMBOL(dquot_alloc_inode);
+ */
+ void dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
+ {
+- struct dquot **dquots;
++ struct dquot __rcu **dquots;
++ struct dquot *dquot;
+ int cnt, index;
+
+ if (!inode_quota_active(inode)) {
+@@ -1805,9 +1819,8 @@ void dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
+ spin_lock(&inode->i_lock);
+ /* Claim reserved quotas to allocated quotas */
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+- if (dquots[cnt]) {
+- struct dquot *dquot = dquots[cnt];
+-
++ dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
++ if (dquot) {
+ spin_lock(&dquot->dq_dqb_lock);
+ if (WARN_ON_ONCE(dquot->dq_dqb.dqb_rsvspace < number))
+ number = dquot->dq_dqb.dqb_rsvspace;
+@@ -1831,7 +1844,8 @@ EXPORT_SYMBOL(dquot_claim_space_nodirty);
+ */
+ void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
+ {
+- struct dquot **dquots;
++ struct dquot __rcu **dquots;
++ struct dquot *dquot;
+ int cnt, index;
+
+ if (!inode_quota_active(inode)) {
+@@ -1847,9 +1861,8 @@ void dquot_reclaim_space_nodirty(struct inode *inode, qsize_t number)
+ spin_lock(&inode->i_lock);
+ /* Claim reserved quotas to allocated quotas */
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+- if (dquots[cnt]) {
+- struct dquot *dquot = dquots[cnt];
+-
++ dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
++ if (dquot) {
+ spin_lock(&dquot->dq_dqb_lock);
+ if (WARN_ON_ONCE(dquot->dq_dqb.dqb_curspace < number))
+ number = dquot->dq_dqb.dqb_curspace;
+@@ -1875,7 +1888,8 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
+ {
+ unsigned int cnt;
+ struct dquot_warn warn[MAXQUOTAS];
+- struct dquot **dquots;
++ struct dquot __rcu **dquots;
++ struct dquot *dquot;
+ int reserve = flags & DQUOT_SPACE_RESERVE, index;
+
+ if (!inode_quota_active(inode)) {
+@@ -1896,17 +1910,18 @@ void __dquot_free_space(struct inode *inode, qsize_t number, int flags)
+ int wtype;
+
+ warn[cnt].w_type = QUOTA_NL_NOWARN;
+- if (!dquots[cnt])
++ dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
++ if (!dquot)
+ continue;
+- spin_lock(&dquots[cnt]->dq_dqb_lock);
+- wtype = info_bdq_free(dquots[cnt], number);
++ spin_lock(&dquot->dq_dqb_lock);
++ wtype = info_bdq_free(dquot, number);
+ if (wtype != QUOTA_NL_NOWARN)
+- prepare_warning(&warn[cnt], dquots[cnt], wtype);
++ prepare_warning(&warn[cnt], dquot, wtype);
+ if (reserve)
+- dquot_free_reserved_space(dquots[cnt], number);
++ dquot_free_reserved_space(dquot, number);
+ else
+- dquot_decr_space(dquots[cnt], number);
+- spin_unlock(&dquots[cnt]->dq_dqb_lock);
++ dquot_decr_space(dquot, number);
++ spin_unlock(&dquot->dq_dqb_lock);
+ }
+ if (reserve)
+ *inode_reserved_space(inode) -= number;
+@@ -1930,7 +1945,8 @@ void dquot_free_inode(struct inode *inode)
+ {
+ unsigned int cnt;
+ struct dquot_warn warn[MAXQUOTAS];
+- struct dquot * const *dquots;
++ struct dquot __rcu * const *dquots;
++ struct dquot *dquot;
+ int index;
+
+ if (!inode_quota_active(inode))
+@@ -1941,16 +1957,16 @@ void dquot_free_inode(struct inode *inode)
+ spin_lock(&inode->i_lock);
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+ int wtype;
+-
+ warn[cnt].w_type = QUOTA_NL_NOWARN;
+- if (!dquots[cnt])
++ dquot = srcu_dereference(dquots[cnt], &dquot_srcu);
++ if (!dquot)
+ continue;
+- spin_lock(&dquots[cnt]->dq_dqb_lock);
+- wtype = info_idq_free(dquots[cnt], 1);
++ spin_lock(&dquot->dq_dqb_lock);
++ wtype = info_idq_free(dquot, 1);
+ if (wtype != QUOTA_NL_NOWARN)
+- prepare_warning(&warn[cnt], dquots[cnt], wtype);
+- dquot_decr_inodes(dquots[cnt], 1);
+- spin_unlock(&dquots[cnt]->dq_dqb_lock);
++ prepare_warning(&warn[cnt], dquot, wtype);
++ dquot_decr_inodes(dquot, 1);
++ spin_unlock(&dquot->dq_dqb_lock);
+ }
+ spin_unlock(&inode->i_lock);
+ mark_all_dquot_dirty(dquots);
+@@ -1976,8 +1992,9 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
+ qsize_t cur_space;
+ qsize_t rsv_space = 0;
+ qsize_t inode_usage = 1;
++ struct dquot __rcu **dquots;
+ struct dquot *transfer_from[MAXQUOTAS] = {};
+- int cnt, ret = 0;
++ int cnt, index, ret = 0;
+ char is_valid[MAXQUOTAS] = {};
+ struct dquot_warn warn_to[MAXQUOTAS];
+ struct dquot_warn warn_from_inodes[MAXQUOTAS];
+@@ -2008,6 +2025,7 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
+ }
+ cur_space = __inode_get_bytes(inode);
+ rsv_space = __inode_get_rsv_space(inode);
++ dquots = i_dquot(inode);
+ /*
+ * Build the transfer_from list, check limits, and update usage in
+ * the target structures.
+@@ -2022,7 +2040,8 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
+ if (!sb_has_quota_active(inode->i_sb, cnt))
+ continue;
+ is_valid[cnt] = 1;
+- transfer_from[cnt] = i_dquot(inode)[cnt];
++ transfer_from[cnt] = srcu_dereference_check(dquots[cnt],
++ &dquot_srcu, lockdep_is_held(&dq_data_lock));
+ ret = dquot_add_inodes(transfer_to[cnt], inode_usage,
+ &warn_to[cnt]);
+ if (ret)
+@@ -2061,13 +2080,21 @@ int __dquot_transfer(struct inode *inode, struct dquot **transfer_to)
+ rsv_space);
+ spin_unlock(&transfer_from[cnt]->dq_dqb_lock);
+ }
+- i_dquot(inode)[cnt] = transfer_to[cnt];
++ rcu_assign_pointer(dquots[cnt], transfer_to[cnt]);
+ }
+ spin_unlock(&inode->i_lock);
+ spin_unlock(&dq_data_lock);
+
+- mark_all_dquot_dirty(transfer_from);
+- mark_all_dquot_dirty(transfer_to);
++ /*
++ * These arrays are local and we hold dquot references so we don't need
++ * the srcu protection but still take dquot_srcu to avoid warning in
++ * mark_all_dquot_dirty().
++ */
++ index = srcu_read_lock(&dquot_srcu);
++ mark_all_dquot_dirty((struct dquot __rcu **)transfer_from);
++ mark_all_dquot_dirty((struct dquot __rcu **)transfer_to);
++ srcu_read_unlock(&dquot_srcu, index);
++
+ flush_warnings(warn_to);
+ flush_warnings(warn_from_inodes);
+ flush_warnings(warn_from_space);
+diff --git a/fs/reiserfs/reiserfs.h b/fs/reiserfs/reiserfs.h
+index 725667880e626..b65549164590c 100644
+--- a/fs/reiserfs/reiserfs.h
++++ b/fs/reiserfs/reiserfs.h
+@@ -97,7 +97,7 @@ struct reiserfs_inode_info {
+ struct rw_semaphore i_xattr_sem;
+ #endif
+ #ifdef CONFIG_QUOTA
+- struct dquot *i_dquot[MAXQUOTAS];
++ struct dquot __rcu *i_dquot[MAXQUOTAS];
+ #endif
+
+ struct inode vfs_inode;
+diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
+index 67b5510beded2..7b3d5aeb2a6fe 100644
+--- a/fs/reiserfs/super.c
++++ b/fs/reiserfs/super.c
+@@ -802,7 +802,7 @@ static ssize_t reiserfs_quota_write(struct super_block *, int, const char *,
+ static ssize_t reiserfs_quota_read(struct super_block *, int, char *, size_t,
+ loff_t);
+
+-static struct dquot **reiserfs_get_dquots(struct inode *inode)
++static struct dquot __rcu **reiserfs_get_dquots(struct inode *inode)
+ {
+ return REISERFS_I(inode)->i_dquot;
+ }
+diff --git a/fs/select.c b/fs/select.c
+index 0ee55af1a55c2..d4d881d439dcd 100644
+--- a/fs/select.c
++++ b/fs/select.c
+@@ -476,7 +476,7 @@ static inline void wait_key_set(poll_table *wait, unsigned long in,
+ wait->_key |= POLLOUT_SET;
+ }
+
+-static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
++static noinline_for_stack int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
+ {
+ ktime_t expire, *to = NULL;
+ struct poll_wqueues table;
+diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
+index f391c9b803d84..98514f2f2d7b1 100644
+--- a/fs/smb/client/file.c
++++ b/fs/smb/client/file.c
+@@ -2624,20 +2624,20 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
+ * dirty pages if possible, but don't sleep while doing so.
+ */
+ static void cifs_extend_writeback(struct address_space *mapping,
++ struct xa_state *xas,
+ long *_count,
+ loff_t start,
+ int max_pages,
+- size_t max_len,
+- unsigned int *_len)
++ loff_t max_len,
++ size_t *_len)
+ {
+ struct folio_batch batch;
+ struct folio *folio;
+- unsigned int psize, nr_pages;
+- size_t len = *_len;
+- pgoff_t index = (start + len) / PAGE_SIZE;
++ unsigned int nr_pages;
++ pgoff_t index = (start + *_len) / PAGE_SIZE;
++ size_t len;
+ bool stop = true;
+ unsigned int i;
+- XA_STATE(xas, &mapping->i_pages, index);
+
+ folio_batch_init(&batch);
+
+@@ -2648,54 +2648,64 @@ static void cifs_extend_writeback(struct address_space *mapping,
+ */
+ rcu_read_lock();
+
+- xas_for_each(&xas, folio, ULONG_MAX) {
++ xas_for_each(xas, folio, ULONG_MAX) {
+ stop = true;
+- if (xas_retry(&xas, folio))
++ if (xas_retry(xas, folio))
+ continue;
+ if (xa_is_value(folio))
+ break;
+- if (folio->index != index)
++ if (folio->index != index) {
++ xas_reset(xas);
+ break;
++ }
++
+ if (!folio_try_get_rcu(folio)) {
+- xas_reset(&xas);
++ xas_reset(xas);
+ continue;
+ }
+ nr_pages = folio_nr_pages(folio);
+- if (nr_pages > max_pages)
++ if (nr_pages > max_pages) {
++ xas_reset(xas);
+ break;
++ }
+
+ /* Has the page moved or been split? */
+- if (unlikely(folio != xas_reload(&xas))) {
++ if (unlikely(folio != xas_reload(xas))) {
+ folio_put(folio);
++ xas_reset(xas);
+ break;
+ }
+
+ if (!folio_trylock(folio)) {
+ folio_put(folio);
++ xas_reset(xas);
+ break;
+ }
+- if (!folio_test_dirty(folio) || folio_test_writeback(folio)) {
++ if (!folio_test_dirty(folio) ||
++ folio_test_writeback(folio)) {
+ folio_unlock(folio);
+ folio_put(folio);
++ xas_reset(xas);
+ break;
+ }
+
+ max_pages -= nr_pages;
+- psize = folio_size(folio);
+- len += psize;
++ len = folio_size(folio);
+ stop = false;
+- if (max_pages <= 0 || len >= max_len || *_count <= 0)
+- stop = true;
+
+ index += nr_pages;
++ *_count -= nr_pages;
++ *_len += len;
++ if (max_pages <= 0 || *_len >= max_len || *_count <= 0)
++ stop = true;
++
+ if (!folio_batch_add(&batch, folio))
+ break;
+ if (stop)
+ break;
+ }
+
+- if (!stop)
+- xas_pause(&xas);
++ xas_pause(xas);
+ rcu_read_unlock();
+
+ /* Now, if we obtained any pages, we can shift them to being
+@@ -2712,16 +2722,12 @@ static void cifs_extend_writeback(struct address_space *mapping,
+ if (!folio_clear_dirty_for_io(folio))
+ WARN_ON(1);
+ folio_start_writeback(folio);
+-
+- *_count -= folio_nr_pages(folio);
+ folio_unlock(folio);
+ }
+
+ folio_batch_release(&batch);
+ cond_resched();
+ } while (!stop);
+-
+- *_len = len;
+ }
+
+ /*
+@@ -2729,8 +2735,10 @@ static void cifs_extend_writeback(struct address_space *mapping,
+ */
+ static ssize_t cifs_write_back_from_locked_folio(struct address_space *mapping,
+ struct writeback_control *wbc,
++ struct xa_state *xas,
+ struct folio *folio,
+- loff_t start, loff_t end)
++ unsigned long long start,
++ unsigned long long end)
+ {
+ struct inode *inode = mapping->host;
+ struct TCP_Server_Info *server;
+@@ -2739,17 +2747,18 @@ static ssize_t cifs_write_back_from_locked_folio(struct address_space *mapping,
+ struct cifs_credits credits_on_stack;
+ struct cifs_credits *credits = &credits_on_stack;
+ struct cifsFileInfo *cfile = NULL;
+- unsigned int xid, wsize, len;
+- loff_t i_size = i_size_read(inode);
+- size_t max_len;
++ unsigned long long i_size = i_size_read(inode), max_len;
++ unsigned int xid, wsize;
++ size_t len = folio_size(folio);
+ long count = wbc->nr_to_write;
+ int rc;
+
+ /* The folio should be locked, dirty and not undergoing writeback. */
++ if (!folio_clear_dirty_for_io(folio))
++ WARN_ON_ONCE(1);
+ folio_start_writeback(folio);
+
+ count -= folio_nr_pages(folio);
+- len = folio_size(folio);
+
+ xid = get_xid();
+ server = cifs_pick_channel(cifs_sb_master_tcon(cifs_sb)->ses);
+@@ -2779,9 +2788,10 @@ static ssize_t cifs_write_back_from_locked_folio(struct address_space *mapping,
+ wdata->server = server;
+ cfile = NULL;
+
+- /* Find all consecutive lockable dirty pages, stopping when we find a
+- * page that is not immediately lockable, is not dirty or is missing,
+- * or we reach the end of the range.
++ /* Find all consecutive lockable dirty pages that have contiguous
++ * written regions, stopping when we find a page that is not
++ * immediately lockable, is not dirty or is missing, or we reach the
++ * end of the range.
+ */
+ if (start < i_size) {
+ /* Trim the write to the EOF; the extra data is ignored. Also
+@@ -2801,19 +2811,18 @@ static ssize_t cifs_write_back_from_locked_folio(struct address_space *mapping,
+ max_pages -= folio_nr_pages(folio);
+
+ if (max_pages > 0)
+- cifs_extend_writeback(mapping, &count, start,
++ cifs_extend_writeback(mapping, xas, &count, start,
+ max_pages, max_len, &len);
+ }
+- len = min_t(loff_t, len, max_len);
+ }
+-
+- wdata->bytes = len;
++ len = min_t(unsigned long long, len, i_size - start);
+
+ /* We now have a contiguous set of dirty pages, each with writeback
+ * set; the first page is still locked at this point, but all the rest
+ * have been unlocked.
+ */
+ folio_unlock(folio);
++ wdata->bytes = len;
+
+ if (start < i_size) {
+ iov_iter_xarray(&wdata->iter, ITER_SOURCE, &mapping->i_pages,
+@@ -2864,102 +2873,118 @@ static ssize_t cifs_write_back_from_locked_folio(struct address_space *mapping,
+ /*
+ * write a region of pages back to the server
+ */
+-static int cifs_writepages_region(struct address_space *mapping,
+- struct writeback_control *wbc,
+- loff_t start, loff_t end, loff_t *_next)
++static ssize_t cifs_writepages_begin(struct address_space *mapping,
++ struct writeback_control *wbc,
++ struct xa_state *xas,
++ unsigned long long *_start,
++ unsigned long long end)
+ {
+- struct folio_batch fbatch;
++ struct folio *folio;
++ unsigned long long start = *_start;
++ ssize_t ret;
+ int skips = 0;
+
+- folio_batch_init(&fbatch);
+- do {
+- int nr;
+- pgoff_t index = start / PAGE_SIZE;
++search_again:
++ /* Find the first dirty page. */
++ rcu_read_lock();
+
+- nr = filemap_get_folios_tag(mapping, &index, end / PAGE_SIZE,
+- PAGECACHE_TAG_DIRTY, &fbatch);
+- if (!nr)
++ for (;;) {
++ folio = xas_find_marked(xas, end / PAGE_SIZE, PAGECACHE_TAG_DIRTY);
++ if (xas_retry(xas, folio) || xa_is_value(folio))
++ continue;
++ if (!folio)
+ break;
+
+- for (int i = 0; i < nr; i++) {
+- ssize_t ret;
+- struct folio *folio = fbatch.folios[i];
++ if (!folio_try_get_rcu(folio)) {
++ xas_reset(xas);
++ continue;
++ }
+
+-redo_folio:
+- start = folio_pos(folio); /* May regress with THPs */
++ if (unlikely(folio != xas_reload(xas))) {
++ folio_put(folio);
++ xas_reset(xas);
++ continue;
++ }
+
+- /* At this point we hold neither the i_pages lock nor the
+- * page lock: the page may be truncated or invalidated
+- * (changing page->mapping to NULL), or even swizzled
+- * back from swapper_space to tmpfs file mapping
+- */
+- if (wbc->sync_mode != WB_SYNC_NONE) {
+- ret = folio_lock_killable(folio);
+- if (ret < 0)
+- goto write_error;
+- } else {
+- if (!folio_trylock(folio))
+- goto skip_write;
+- }
++ xas_pause(xas);
++ break;
++ }
++ rcu_read_unlock();
++ if (!folio)
++ return 0;
+
+- if (folio->mapping != mapping ||
+- !folio_test_dirty(folio)) {
+- start += folio_size(folio);
+- folio_unlock(folio);
+- continue;
+- }
++ start = folio_pos(folio); /* May regress with THPs */
+
+- if (folio_test_writeback(folio) ||
+- folio_test_fscache(folio)) {
+- folio_unlock(folio);
+- if (wbc->sync_mode == WB_SYNC_NONE)
+- goto skip_write;
++ /* At this point we hold neither the i_pages lock nor the page lock:
++ * the page may be truncated or invalidated (changing page->mapping to
++ * NULL), or even swizzled back from swapper_space to tmpfs file
++ * mapping
++ */
++lock_again:
++ if (wbc->sync_mode != WB_SYNC_NONE) {
++ ret = folio_lock_killable(folio);
++ if (ret < 0)
++ return ret;
++ } else {
++ if (!folio_trylock(folio))
++ goto search_again;
++ }
+
+- folio_wait_writeback(folio);
++ if (folio->mapping != mapping ||
++ !folio_test_dirty(folio)) {
++ start += folio_size(folio);
++ folio_unlock(folio);
++ goto search_again;
++ }
++
++ if (folio_test_writeback(folio) ||
++ folio_test_fscache(folio)) {
++ folio_unlock(folio);
++ if (wbc->sync_mode != WB_SYNC_NONE) {
++ folio_wait_writeback(folio);
+ #ifdef CONFIG_CIFS_FSCACHE
+- folio_wait_fscache(folio);
++ folio_wait_fscache(folio);
+ #endif
+- goto redo_folio;
+- }
+-
+- if (!folio_clear_dirty_for_io(folio))
+- /* We hold the page lock - it should've been dirty. */
+- WARN_ON(1);
+-
+- ret = cifs_write_back_from_locked_folio(mapping, wbc, folio, start, end);
+- if (ret < 0)
+- goto write_error;
+-
+- start += ret;
+- continue;
+-
+-write_error:
+- folio_batch_release(&fbatch);
+- *_next = start;
+- return ret;
++ goto lock_again;
++ }
+
+-skip_write:
+- /*
+- * Too many skipped writes, or need to reschedule?
+- * Treat it as a write error without an error code.
+- */
++ start += folio_size(folio);
++ if (wbc->sync_mode == WB_SYNC_NONE) {
+ if (skips >= 5 || need_resched()) {
+ ret = 0;
+- goto write_error;
++ goto out;
+ }
+-
+- /* Otherwise, just skip that folio and go on to the next */
+ skips++;
+- start += folio_size(folio);
+- continue;
+ }
++ goto search_again;
++ }
+
+- folio_batch_release(&fbatch);
+- cond_resched();
+- } while (wbc->nr_to_write > 0);
++ ret = cifs_write_back_from_locked_folio(mapping, wbc, xas, folio, start, end);
++out:
++ if (ret > 0)
++ *_start = start + ret;
++ return ret;
++}
+
+- *_next = start;
+- return 0;
++/*
++ * Write a region of pages back to the server
++ */
++static int cifs_writepages_region(struct address_space *mapping,
++ struct writeback_control *wbc,
++ unsigned long long *_start,
++ unsigned long long end)
++{
++ ssize_t ret;
++
++ XA_STATE(xas, &mapping->i_pages, *_start / PAGE_SIZE);
++
++ do {
++ ret = cifs_writepages_begin(mapping, wbc, &xas, _start, end);
++ if (ret > 0 && wbc->nr_to_write > 0)
++ cond_resched();
++ } while (ret > 0 && wbc->nr_to_write > 0);
++
++ return ret > 0 ? 0 : ret;
+ }
+
+ /*
+@@ -2968,7 +2993,7 @@ static int cifs_writepages_region(struct address_space *mapping,
+ static int cifs_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
+ {
+- loff_t start, next;
++ loff_t start, end;
+ int ret;
+
+ /* We have to be careful as we can end up racing with setattr()
+@@ -2976,28 +3001,34 @@ static int cifs_writepages(struct address_space *mapping,
+ * to prevent it.
+ */
+
+- if (wbc->range_cyclic) {
++ if (wbc->range_cyclic && mapping->writeback_index) {
+ start = mapping->writeback_index * PAGE_SIZE;
+- ret = cifs_writepages_region(mapping, wbc, start, LLONG_MAX, &next);
+- if (ret == 0) {
+- mapping->writeback_index = next / PAGE_SIZE;
+- if (start > 0 && wbc->nr_to_write > 0) {
+- ret = cifs_writepages_region(mapping, wbc, 0,
+- start, &next);
+- if (ret == 0)
+- mapping->writeback_index =
+- next / PAGE_SIZE;
+- }
++ ret = cifs_writepages_region(mapping, wbc, &start, LLONG_MAX);
++ if (ret < 0)
++ goto out;
++
++ if (wbc->nr_to_write <= 0) {
++ mapping->writeback_index = start / PAGE_SIZE;
++ goto out;
+ }
++
++ start = 0;
++ end = mapping->writeback_index * PAGE_SIZE;
++ mapping->writeback_index = 0;
++ ret = cifs_writepages_region(mapping, wbc, &start, end);
++ if (ret == 0)
++ mapping->writeback_index = start / PAGE_SIZE;
+ } else if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) {
+- ret = cifs_writepages_region(mapping, wbc, 0, LLONG_MAX, &next);
++ start = 0;
++ ret = cifs_writepages_region(mapping, wbc, &start, LLONG_MAX);
+ if (wbc->nr_to_write > 0 && ret == 0)
+- mapping->writeback_index = next / PAGE_SIZE;
++ mapping->writeback_index = start / PAGE_SIZE;
+ } else {
+- ret = cifs_writepages_region(mapping, wbc,
+- wbc->range_start, wbc->range_end, &next);
++ start = wbc->range_start;
++ ret = cifs_writepages_region(mapping, wbc, &start, wbc->range_end);
+ }
+
++out:
+ return ret;
+ }
+
+diff --git a/include/drm/drm_fixed.h b/include/drm/drm_fixed.h
+index 6ea339d5de088..81572d32db0c2 100644
+--- a/include/drm/drm_fixed.h
++++ b/include/drm/drm_fixed.h
+@@ -71,7 +71,6 @@ static inline u32 dfixed_div(fixed20_12 A, fixed20_12 B)
+ }
+
+ #define DRM_FIXED_POINT 32
+-#define DRM_FIXED_POINT_HALF 16
+ #define DRM_FIXED_ONE (1ULL << DRM_FIXED_POINT)
+ #define DRM_FIXED_DECIMAL_MASK (DRM_FIXED_ONE - 1)
+ #define DRM_FIXED_DIGITS_MASK (~DRM_FIXED_DECIMAL_MASK)
+@@ -90,12 +89,12 @@ static inline int drm_fixp2int(s64 a)
+
+ static inline int drm_fixp2int_round(s64 a)
+ {
+- return drm_fixp2int(a + (1 << (DRM_FIXED_POINT_HALF - 1)));
++ return drm_fixp2int(a + DRM_FIXED_ONE / 2);
+ }
+
+ static inline int drm_fixp2int_ceil(s64 a)
+ {
+- if (a > 0)
++ if (a >= 0)
+ return drm_fixp2int(a + DRM_FIXED_ALMOST_ONE);
+ else
+ return drm_fixp2int(a - DRM_FIXED_ALMOST_ONE);
+diff --git a/include/drm/drm_kunit_helpers.h b/include/drm/drm_kunit_helpers.h
+index ba483c87f0e7b..3ae19892229db 100644
+--- a/include/drm/drm_kunit_helpers.h
++++ b/include/drm/drm_kunit_helpers.h
+@@ -3,6 +3,8 @@
+ #ifndef DRM_KUNIT_HELPERS_H_
+ #define DRM_KUNIT_HELPERS_H_
+
++#include <drm/drm_drv.h>
++
+ #include <linux/device.h>
+
+ #include <kunit/test.h>
+diff --git a/include/dt-bindings/clock/r8a779g0-cpg-mssr.h b/include/dt-bindings/clock/r8a779g0-cpg-mssr.h
+index 754c54a6eb06a..7850cdc62e285 100644
+--- a/include/dt-bindings/clock/r8a779g0-cpg-mssr.h
++++ b/include/dt-bindings/clock/r8a779g0-cpg-mssr.h
+@@ -86,5 +86,6 @@
+ #define R8A779G0_CLK_CPEX 74
+ #define R8A779G0_CLK_CBFUSA 75
+ #define R8A779G0_CLK_R 76
++#define R8A779G0_CLK_CP 77
+
+ #endif /* __DT_BINDINGS_CLOCK_R8A779G0_CPG_MSSR_H__ */
+diff --git a/include/linux/dm-io.h b/include/linux/dm-io.h
+index 7595142f3fc57..7b2968612b7e6 100644
+--- a/include/linux/dm-io.h
++++ b/include/linux/dm-io.h
+@@ -80,7 +80,8 @@ void dm_io_client_destroy(struct dm_io_client *client);
+ * error occurred doing io to the corresponding region.
+ */
+ int dm_io(struct dm_io_request *io_req, unsigned int num_regions,
+- struct dm_io_region *region, unsigned int long *sync_error_bits);
++ struct dm_io_region *region, unsigned int long *sync_error_bits,
++ unsigned short ioprio);
+
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_DM_IO_H */
+diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
+index 053137a0fe456..3f016d3c1ec4f 100644
+--- a/include/linux/f2fs_fs.h
++++ b/include/linux/f2fs_fs.h
+@@ -27,6 +27,7 @@
+
+ #define F2FS_BYTES_TO_BLK(bytes) ((bytes) >> F2FS_BLKSIZE_BITS)
+ #define F2FS_BLK_TO_BYTES(blk) ((blk) << F2FS_BLKSIZE_BITS)
++#define F2FS_BLK_END_BYTES(blk) (F2FS_BLK_TO_BYTES(blk + 1) - 1)
+
+ /* 0, 1(node nid), 2(meta nid) are reserved node id */
+ #define F2FS_RESERVED_NODE_NUM 3
+diff --git a/include/linux/filter.h b/include/linux/filter.h
+index 68fb6c8142fec..f537a394c42d0 100644
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -547,24 +547,27 @@ static inline bool insn_is_zext(const struct bpf_insn *insn)
+ __BPF_MAP(n, __BPF_DECL_ARGS, __BPF_N, u64, __ur_1, u64, __ur_2, \
+ u64, __ur_3, u64, __ur_4, u64, __ur_5)
+
+-#define BPF_CALL_x(x, name, ...) \
++#define BPF_CALL_x(x, attr, name, ...) \
+ static __always_inline \
+ u64 ____##name(__BPF_MAP(x, __BPF_DECL_ARGS, __BPF_V, __VA_ARGS__)); \
+ typedef u64 (*btf_##name)(__BPF_MAP(x, __BPF_DECL_ARGS, __BPF_V, __VA_ARGS__)); \
+- u64 name(__BPF_REG(x, __BPF_DECL_REGS, __BPF_N, __VA_ARGS__)); \
+- u64 name(__BPF_REG(x, __BPF_DECL_REGS, __BPF_N, __VA_ARGS__)) \
++ attr u64 name(__BPF_REG(x, __BPF_DECL_REGS, __BPF_N, __VA_ARGS__)); \
++ attr u64 name(__BPF_REG(x, __BPF_DECL_REGS, __BPF_N, __VA_ARGS__)) \
+ { \
+ return ((btf_##name)____##name)(__BPF_MAP(x,__BPF_CAST,__BPF_N,__VA_ARGS__));\
+ } \
+ static __always_inline \
+ u64 ____##name(__BPF_MAP(x, __BPF_DECL_ARGS, __BPF_V, __VA_ARGS__))
+
+-#define BPF_CALL_0(name, ...) BPF_CALL_x(0, name, __VA_ARGS__)
+-#define BPF_CALL_1(name, ...) BPF_CALL_x(1, name, __VA_ARGS__)
+-#define BPF_CALL_2(name, ...) BPF_CALL_x(2, name, __VA_ARGS__)
+-#define BPF_CALL_3(name, ...) BPF_CALL_x(3, name, __VA_ARGS__)
+-#define BPF_CALL_4(name, ...) BPF_CALL_x(4, name, __VA_ARGS__)
+-#define BPF_CALL_5(name, ...) BPF_CALL_x(5, name, __VA_ARGS__)
++#define __NOATTR
++#define BPF_CALL_0(name, ...) BPF_CALL_x(0, __NOATTR, name, __VA_ARGS__)
++#define BPF_CALL_1(name, ...) BPF_CALL_x(1, __NOATTR, name, __VA_ARGS__)
++#define BPF_CALL_2(name, ...) BPF_CALL_x(2, __NOATTR, name, __VA_ARGS__)
++#define BPF_CALL_3(name, ...) BPF_CALL_x(3, __NOATTR, name, __VA_ARGS__)
++#define BPF_CALL_4(name, ...) BPF_CALL_x(4, __NOATTR, name, __VA_ARGS__)
++#define BPF_CALL_5(name, ...) BPF_CALL_x(5, __NOATTR, name, __VA_ARGS__)
++
++#define NOTRACE_BPF_CALL_1(name, ...) BPF_CALL_x(1, notrace, name, __VA_ARGS__)
+
+ #define bpf_ctx_range(TYPE, MEMBER) \
+ offsetof(TYPE, MEMBER) ... offsetofend(TYPE, MEMBER) - 1
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 1fbc72c5f112c..08ecac9d7b8ba 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -2158,7 +2158,7 @@ struct super_operations {
+ #ifdef CONFIG_QUOTA
+ ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
+ ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+- struct dquot **(*get_dquots)(struct inode *);
++ struct dquot __rcu **(*get_dquots)(struct inode *);
+ #endif
+ long (*nr_cached_objects)(struct super_block *,
+ struct shrink_control *);
+@@ -3281,6 +3281,15 @@ extern int generic_check_addressable(unsigned, u64);
+
+ extern void generic_set_encrypted_ci_d_ops(struct dentry *dentry);
+
++static inline bool sb_has_encoding(const struct super_block *sb)
++{
++#if IS_ENABLED(CONFIG_UNICODE)
++ return !!sb->s_encoding;
++#else
++ return false;
++#endif
++}
++
+ int may_setattr(struct mnt_idmap *idmap, struct inode *inode,
+ unsigned int ia_valid);
+ int setattr_prepare(struct mnt_idmap *, struct dentry *, struct iattr *);
+diff --git a/include/linux/iommu.h b/include/linux/iommu.h
+index 5e27cb3a3be99..c948289f64d08 100644
+--- a/include/linux/iommu.h
++++ b/include/linux/iommu.h
+@@ -487,6 +487,7 @@ struct iommu_ops {
+ struct module *owner;
+ struct iommu_domain *identity_domain;
+ struct iommu_domain *blocked_domain;
++ struct iommu_domain *release_domain;
+ struct iommu_domain *default_domain;
+ };
+
+diff --git a/include/linux/moduleloader.h b/include/linux/moduleloader.h
+index 001b2ce83832e..89b1e0ed98114 100644
+--- a/include/linux/moduleloader.h
++++ b/include/linux/moduleloader.h
+@@ -115,6 +115,14 @@ int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *mod);
+
++#ifdef CONFIG_MODULES
++void flush_module_init_free_work(void);
++#else
++static inline void flush_module_init_free_work(void)
++{
++}
++#endif
++
+ /* Any cleanup needed when module leaves. */
+ void module_arch_cleanup(struct module *mod);
+
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index 78a09af89e39b..dba428b3a87a5 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -2144,6 +2144,7 @@ struct net_device {
+ struct pcpu_sw_netstats __percpu *tstats;
+ struct pcpu_dstats __percpu *dstats;
+ };
++ unsigned long state;
+ unsigned int flags;
+ unsigned short hard_header_len;
+ netdev_features_t features;
+@@ -2189,7 +2190,6 @@ struct net_device {
+ * part of the usual set specified in Space.c.
+ */
+
+- unsigned long state;
+
+ struct list_head dev_list;
+ struct list_head napi_list;
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index 7ab0d13672daf..213109d3c601d 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -2517,6 +2517,11 @@ static inline struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
+ return NULL;
+ }
+
++static inline bool pci_dev_is_disconnected(const struct pci_dev *dev)
++{
++ return dev->error_state == pci_channel_io_perm_failure;
++}
++
+ void pci_request_acs(void);
+ bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags);
+ bool pci_acs_path_enabled(struct pci_dev *start,
+diff --git a/include/linux/poll.h b/include/linux/poll.h
+index a9e0e1c2d1f2f..d1ea4f3714a84 100644
+--- a/include/linux/poll.h
++++ b/include/linux/poll.h
+@@ -14,11 +14,7 @@
+
+ /* ~832 bytes of stack space used max in sys_select/sys_poll before allocating
+ additional memory. */
+-#ifdef __clang__
+-#define MAX_STACK_ALLOC 768
+-#else
+ #define MAX_STACK_ALLOC 832
+-#endif
+ #define FRONTEND_STACK_ALLOC 256
+ #define SELECT_STACK_ALLOC FRONTEND_STACK_ALLOC
+ #define POLL_STACK_ALLOC FRONTEND_STACK_ALLOC
+diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
+index 0746b1b0b6639..9d69e4bd6f0a8 100644
+--- a/include/linux/rcupdate.h
++++ b/include/linux/rcupdate.h
+@@ -247,6 +247,37 @@ do { \
+ cond_resched(); \
+ } while (0)
+
++/**
++ * rcu_softirq_qs_periodic - Report RCU and RCU-Tasks quiescent states
++ * @old_ts: jiffies at start of processing.
++ *
++ * This helper is for long-running softirq handlers, such as NAPI threads in
++ * networking. The caller should initialize the variable passed in as @old_ts
++ * at the beginning of the softirq handler. When invoked frequently, this macro
++ * will invoke rcu_softirq_qs() every 100 milliseconds thereafter, which will
++ * provide both RCU and RCU-Tasks quiescent states. Note that this macro
++ * modifies its old_ts argument.
++ *
++ * Because regions of code that have disabled softirq act as RCU read-side
++ * critical sections, this macro should be invoked with softirq (and
++ * preemption) enabled.
++ *
++ * The macro is not needed when CONFIG_PREEMPT_RT is defined. RT kernels would
++ * have more chance to invoke schedule() calls and provide necessary quiescent
++ * states. As a contrast, calling cond_resched() only won't achieve the same
++ * effect because cond_resched() does not provide RCU-Tasks quiescent states.
++ */
++#define rcu_softirq_qs_periodic(old_ts) \
++do { \
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT) && \
++ time_after(jiffies, (old_ts) + HZ / 10)) { \
++ preempt_disable(); \
++ rcu_softirq_qs(); \
++ preempt_enable(); \
++ (old_ts) = jiffies; \
++ } \
++} while (0)
++
+ /*
+ * Infrastructure to implement the synchronize_() primitives in
+ * TREE_RCU and rcu_barrier_() primitives in TINY_RCU.
+diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
+index 2caa6b86106aa..66828dfc6e74e 100644
+--- a/include/linux/shmem_fs.h
++++ b/include/linux/shmem_fs.h
+@@ -37,7 +37,7 @@ struct shmem_inode_info {
+ unsigned int fsflags; /* for FS_IOC_[SG]ETFLAGS */
+ atomic_t stop_eviction; /* hold when working on inode */
+ #ifdef CONFIG_TMPFS_QUOTA
+- struct dquot *i_dquot[MAXQUOTAS];
++ struct dquot __rcu *i_dquot[MAXQUOTAS];
+ #endif
+ struct inode vfs_inode;
+ };
+diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
+index 2cc0a9606175f..515e7958c6c10 100644
+--- a/include/linux/workqueue.h
++++ b/include/linux/workqueue.h
+@@ -391,6 +391,13 @@ enum {
+ WQ_MAX_ACTIVE = 512, /* I like 512, better ideas? */
+ WQ_UNBOUND_MAX_ACTIVE = WQ_MAX_ACTIVE,
+ WQ_DFL_ACTIVE = WQ_MAX_ACTIVE / 2,
++
++ /*
++ * Per-node default cap on min_active. Unless explicitly set, min_active
++ * is set to min(max_active, WQ_DFL_MIN_ACTIVE). For more details, see
++ * workqueue_struct->min_active definition.
++ */
++ WQ_DFL_MIN_ACTIVE = 8,
+ };
+
+ /*
+@@ -433,11 +440,33 @@ extern struct workqueue_struct *system_freezable_power_efficient_wq;
+ * alloc_workqueue - allocate a workqueue
+ * @fmt: printf format for the name of the workqueue
+ * @flags: WQ_* flags
+- * @max_active: max in-flight work items per CPU, 0 for default
++ * @max_active: max in-flight work items, 0 for default
+ * remaining args: args for @fmt
+ *
+- * Allocate a workqueue with the specified parameters. For detailed
+- * information on WQ_* flags, please refer to
++ * For a per-cpu workqueue, @max_active limits the number of in-flight work
++ * items for each CPU. e.g. @max_active of 1 indicates that each CPU can be
++ * executing at most one work item for the workqueue.
++ *
++ * For unbound workqueues, @max_active limits the number of in-flight work items
++ * for the whole system. e.g. @max_active of 16 indicates that that there can be
++ * at most 16 work items executing for the workqueue in the whole system.
++ *
++ * As sharing the same active counter for an unbound workqueue across multiple
++ * NUMA nodes can be expensive, @max_active is distributed to each NUMA node
++ * according to the proportion of the number of online CPUs and enforced
++ * independently.
++ *
++ * Depending on online CPU distribution, a node may end up with per-node
++ * max_active which is significantly lower than @max_active, which can lead to
++ * deadlocks if the per-node concurrency limit is lower than the maximum number
++ * of interdependent work items for the workqueue.
++ *
++ * To guarantee forward progress regardless of online CPU distribution, the
++ * concurrency limit on every node is guaranteed to be equal to or greater than
++ * min_active which is set to min(@max_active, %WQ_DFL_MIN_ACTIVE). This means
++ * that the sum of per-node max_active's may be larger than @max_active.
++ *
++ * For detailed information on %WQ_* flags, please refer to
+ * Documentation/core-api/workqueue.rst.
+ *
+ * RETURNS:
+diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
+index 56719a26a46c3..bec8c3a1ed824 100644
+--- a/include/media/videobuf2-core.h
++++ b/include/media/videobuf2-core.h
+@@ -72,6 +72,10 @@ struct vb2_buffer;
+ * argument to other ops in this structure.
+ * @put_userptr: inform the allocator that a USERPTR buffer will no longer
+ * be used.
++ * @prepare: called every time the buffer is passed from userspace to the
++ * driver, useful for cache synchronisation, optional.
++ * @finish: called every time the buffer is passed back from the driver
++ * to the userspace, also optional.
+ * @attach_dmabuf: attach a shared &struct dma_buf for a hardware operation;
+ * used for DMABUF memory types; dev is the alloc device
+ * dbuf is the shared dma_buf; returns ERR_PTR() on failure;
+@@ -86,10 +90,6 @@ struct vb2_buffer;
+ * dmabuf.
+ * @unmap_dmabuf: releases access control to the dmabuf - allocator is notified
+ * that this driver is done using the dmabuf for now.
+- * @prepare: called every time the buffer is passed from userspace to the
+- * driver, useful for cache synchronisation, optional.
+- * @finish: called every time the buffer is passed back from the driver
+- * to the userspace, also optional.
+ * @vaddr: return a kernel virtual address to a given memory buffer
+ * associated with the passed private structure or NULL if no
+ * such mapping exists.
+@@ -484,7 +484,6 @@ struct vb2_buf_ops {
+ * caller. For example, for V4L2, it should match
+ * the types defined on &enum v4l2_buf_type.
+ * @io_modes: supported io methods (see &enum vb2_io_modes).
+- * @alloc_devs: &struct device memory type/allocator-specific per-plane device
+ * @dev: device to use for the default allocation context if the driver
+ * doesn't fill in the @alloc_devs array.
+ * @dma_attrs: DMA attributes to use for the DMA.
+@@ -553,6 +552,7 @@ struct vb2_buf_ops {
+ * VIDIOC_REQBUFS will ensure at least @min_queued_buffers
+ * buffers will be allocated. Note that VIDIOC_CREATE_BUFS will not
+ * modify the requested buffer count.
++ * @alloc_devs: &struct device memory type/allocator-specific per-plane device
+ */
+ /*
+ * Private elements (won't appear at the uAPI book):
+@@ -577,6 +577,9 @@ struct vb2_buf_ops {
+ * @waiting_for_buffers: used in poll() to check if vb2 is still waiting for
+ * buffers. Only set for capture queues if qbuf has not yet been
+ * called since poll() needs to return %EPOLLERR in that situation.
++ * @waiting_in_dqbuf: set by the core for the duration of a blocking DQBUF, when
++ * it has to wait for a buffer to become available with vb2_queue->lock
++ * released. Used to prevent destroying the queue by other threads.
+ * @is_multiplanar: set if buffer type is multiplanar
+ * @is_output: set if buffer type is output
+ * @copy_timestamp: set if vb2-core should set timestamps
+diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
+index bdee5d649cc61..0d231024570a3 100644
+--- a/include/net/bluetooth/hci.h
++++ b/include/net/bluetooth/hci.h
+@@ -393,7 +393,6 @@ enum {
+ HCI_LIMITED_PRIVACY,
+ HCI_RPA_EXPIRED,
+ HCI_RPA_RESOLVING,
+- HCI_HS_ENABLED,
+ HCI_LE_ENABLED,
+ HCI_ADVERTISING,
+ HCI_ADVERTISING_CONNECTABLE,
+@@ -437,7 +436,6 @@ enum {
+ #define HCI_NCMD_TIMEOUT msecs_to_jiffies(4000) /* 4 seconds */
+ #define HCI_ACL_TX_TIMEOUT msecs_to_jiffies(45000) /* 45 seconds */
+ #define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
+-#define HCI_POWER_OFF_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */
+ #define HCI_LE_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */
+ #define HCI_LE_AUTOCONN_TIMEOUT msecs_to_jiffies(4000) /* 4 seconds */
+
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index 8f8dd91737142..d1228857b1d0f 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -552,6 +552,7 @@ struct hci_dev {
+ __u32 req_status;
+ __u32 req_result;
+ struct sk_buff *req_skb;
++ struct sk_buff *req_rsp;
+
+ void *smp_data;
+ void *smp_bredr_data;
+diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h
+index 6efbc2152146b..e2582c2425449 100644
+--- a/include/net/bluetooth/hci_sync.h
++++ b/include/net/bluetooth/hci_sync.h
+@@ -42,7 +42,7 @@ int __hci_cmd_sync_status_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
+ void hci_cmd_sync_init(struct hci_dev *hdev);
+ void hci_cmd_sync_clear(struct hci_dev *hdev);
+ void hci_cmd_sync_cancel(struct hci_dev *hdev, int err);
+-void __hci_cmd_sync_cancel(struct hci_dev *hdev, int err);
++void hci_cmd_sync_cancel_sync(struct hci_dev *hdev, int err);
+
+ int hci_cmd_sync_submit(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
+ void *data, hci_cmd_sync_work_destroy_t destroy);
+diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
+index cf393e72d6ed6..92d7197f9a563 100644
+--- a/include/net/bluetooth/l2cap.h
++++ b/include/net/bluetooth/l2cap.h
+@@ -59,8 +59,6 @@
+ #define L2CAP_WAIT_ACK_POLL_PERIOD msecs_to_jiffies(200)
+ #define L2CAP_WAIT_ACK_TIMEOUT msecs_to_jiffies(10000)
+
+-#define L2CAP_A2MP_DEFAULT_MTU 670
+-
+ /* L2CAP socket address */
+ struct sockaddr_l2 {
+ sa_family_t l2_family;
+@@ -109,12 +107,6 @@ struct l2cap_conninfo {
+ #define L2CAP_ECHO_RSP 0x09
+ #define L2CAP_INFO_REQ 0x0a
+ #define L2CAP_INFO_RSP 0x0b
+-#define L2CAP_CREATE_CHAN_REQ 0x0c
+-#define L2CAP_CREATE_CHAN_RSP 0x0d
+-#define L2CAP_MOVE_CHAN_REQ 0x0e
+-#define L2CAP_MOVE_CHAN_RSP 0x0f
+-#define L2CAP_MOVE_CHAN_CFM 0x10
+-#define L2CAP_MOVE_CHAN_CFM_RSP 0x11
+ #define L2CAP_CONN_PARAM_UPDATE_REQ 0x12
+ #define L2CAP_CONN_PARAM_UPDATE_RSP 0x13
+ #define L2CAP_LE_CONN_REQ 0x14
+@@ -144,7 +136,6 @@ struct l2cap_conninfo {
+ /* L2CAP fixed channels */
+ #define L2CAP_FC_SIG_BREDR 0x02
+ #define L2CAP_FC_CONNLESS 0x04
+-#define L2CAP_FC_A2MP 0x08
+ #define L2CAP_FC_ATT 0x10
+ #define L2CAP_FC_SIG_LE 0x20
+ #define L2CAP_FC_SMP_LE 0x40
+@@ -267,7 +258,6 @@ struct l2cap_conn_rsp {
+ /* channel identifier */
+ #define L2CAP_CID_SIGNALING 0x0001
+ #define L2CAP_CID_CONN_LESS 0x0002
+-#define L2CAP_CID_A2MP 0x0003
+ #define L2CAP_CID_ATT 0x0004
+ #define L2CAP_CID_LE_SIGNALING 0x0005
+ #define L2CAP_CID_SMP 0x0006
+@@ -282,7 +272,6 @@ struct l2cap_conn_rsp {
+ #define L2CAP_CR_BAD_PSM 0x0002
+ #define L2CAP_CR_SEC_BLOCK 0x0003
+ #define L2CAP_CR_NO_MEM 0x0004
+-#define L2CAP_CR_BAD_AMP 0x0005
+ #define L2CAP_CR_INVALID_SCID 0x0006
+ #define L2CAP_CR_SCID_IN_USE 0x0007
+
+@@ -404,29 +393,6 @@ struct l2cap_info_rsp {
+ __u8 data[];
+ } __packed;
+
+-struct l2cap_create_chan_req {
+- __le16 psm;
+- __le16 scid;
+- __u8 amp_id;
+-} __packed;
+-
+-struct l2cap_create_chan_rsp {
+- __le16 dcid;
+- __le16 scid;
+- __le16 result;
+- __le16 status;
+-} __packed;
+-
+-struct l2cap_move_chan_req {
+- __le16 icid;
+- __u8 dest_amp_id;
+-} __packed;
+-
+-struct l2cap_move_chan_rsp {
+- __le16 icid;
+- __le16 result;
+-} __packed;
+-
+ #define L2CAP_MR_SUCCESS 0x0000
+ #define L2CAP_MR_PEND 0x0001
+ #define L2CAP_MR_BAD_ID 0x0002
+@@ -539,8 +505,6 @@ struct l2cap_seq_list {
+
+ struct l2cap_chan {
+ struct l2cap_conn *conn;
+- struct hci_conn *hs_hcon;
+- struct hci_chan *hs_hchan;
+ struct kref kref;
+ atomic_t nesting;
+
+@@ -591,12 +555,6 @@ struct l2cap_chan {
+ unsigned long conn_state;
+ unsigned long flags;
+
+- __u8 remote_amp_id;
+- __u8 local_amp_id;
+- __u8 move_id;
+- __u8 move_state;
+- __u8 move_role;
+-
+ __u16 next_tx_seq;
+ __u16 expected_ack_seq;
+ __u16 expected_tx_seq;
+diff --git a/include/soc/qcom/qcom-spmi-pmic.h b/include/soc/qcom/qcom-spmi-pmic.h
+index 17a0a8c3d6560..a62d500a6fdaf 100644
+--- a/include/soc/qcom/qcom-spmi-pmic.h
++++ b/include/soc/qcom/qcom-spmi-pmic.h
+@@ -49,7 +49,7 @@
+ #define PMK8350_SUBTYPE 0x2f
+ #define PMR735B_SUBTYPE 0x34
+ #define PM6350_SUBTYPE 0x36
+-#define PM2250_SUBTYPE 0x37
++#define PM4125_SUBTYPE 0x37
+
+ #define PMI8998_FAB_ID_SMIC 0x11
+ #define PMI8998_FAB_ID_GF 0x30
+diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
+index ef3810dee7efa..a8208492e8227 100644
+--- a/include/uapi/linux/virtio_pci.h
++++ b/include/uapi/linux/virtio_pci.h
+@@ -240,7 +240,7 @@ struct virtio_pci_cfg_cap {
+ #define VIRTIO_ADMIN_CMD_LEGACY_DEV_CFG_READ 0x5
+ #define VIRTIO_ADMIN_CMD_LEGACY_NOTIFY_INFO 0x6
+
+-struct __packed virtio_admin_cmd_hdr {
++struct virtio_admin_cmd_hdr {
+ __le16 opcode;
+ /*
+ * 1 - SR-IOV
+@@ -252,20 +252,20 @@ struct __packed virtio_admin_cmd_hdr {
+ __le64 group_member_id;
+ };
+
+-struct __packed virtio_admin_cmd_status {
++struct virtio_admin_cmd_status {
+ __le16 status;
+ __le16 status_qualifier;
+ /* Unused, reserved for future extensions. */
+ __u8 reserved2[4];
+ };
+
+-struct __packed virtio_admin_cmd_legacy_wr_data {
++struct virtio_admin_cmd_legacy_wr_data {
+ __u8 offset; /* Starting offset of the register(s) to write. */
+ __u8 reserved[7];
+ __u8 registers[];
+ };
+
+-struct __packed virtio_admin_cmd_legacy_rd_data {
++struct virtio_admin_cmd_legacy_rd_data {
+ __u8 offset; /* Starting offset of the register(s) to read. */
+ };
+
+@@ -275,7 +275,7 @@ struct __packed virtio_admin_cmd_legacy_rd_data {
+
+ #define VIRTIO_ADMIN_CMD_MAX_NOTIFY_INFO 4
+
+-struct __packed virtio_admin_cmd_notify_info_data {
++struct virtio_admin_cmd_notify_info_data {
+ __u8 flags; /* 0 = end of list, 1 = owner device, 2 = member device */
+ __u8 bar; /* BAR of the member or the owner device */
+ __u8 padding[6];
+diff --git a/init/main.c b/init/main.c
+index e24b0780fdff7..9e6ab6d593bd8 100644
+--- a/init/main.c
++++ b/init/main.c
+@@ -88,6 +88,7 @@
+ #include <linux/sched/task_stack.h>
+ #include <linux/context_tracking.h>
+ #include <linux/random.h>
++#include <linux/moduleloader.h>
+ #include <linux/list.h>
+ #include <linux/integrity.h>
+ #include <linux/proc_ns.h>
+@@ -1402,11 +1403,11 @@ static void mark_readonly(void)
+ if (rodata_enabled) {
+ /*
+ * load_module() results in W+X mappings, which are cleaned
+- * up with call_rcu(). Let's make sure that queued work is
++ * up with init_free_wq. Let's make sure that queued work is
+ * flushed so that we don't hit false positives looking for
+ * insecure pages which are W+X.
+ */
+- rcu_barrier();
++ flush_module_init_free_work();
+ mark_rodata_ro();
+ rodata_test();
+ } else
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index cd9a137ad6cef..9f938874c5e13 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -1176,12 +1176,11 @@ static void ctx_flush_and_put(struct io_ring_ctx *ctx, struct io_tw_state *ts)
+
+ static unsigned int handle_tw_list(struct llist_node *node,
+ struct io_ring_ctx **ctx,
+- struct io_tw_state *ts,
+- struct llist_node *last)
++ struct io_tw_state *ts)
+ {
+ unsigned int count = 0;
+
+- while (node && node != last) {
++ do {
+ struct llist_node *next = node->next;
+ struct io_kiocb *req = container_of(node, struct io_kiocb,
+ io_task_work.node);
+@@ -1205,7 +1204,7 @@ static unsigned int handle_tw_list(struct llist_node *node,
+ *ctx = NULL;
+ cond_resched();
+ }
+- }
++ } while (node);
+
+ return count;
+ }
+@@ -1224,22 +1223,6 @@ static inline struct llist_node *io_llist_xchg(struct llist_head *head,
+ return xchg(&head->first, new);
+ }
+
+-/**
+- * io_llist_cmpxchg - possibly swap all entries in a lock-less list
+- * @head: the head of lock-less list to delete all entries
+- * @old: expected old value of the first entry of the list
+- * @new: new entry as the head of the list
+- *
+- * perform a cmpxchg on the first entry of the list.
+- */
+-
+-static inline struct llist_node *io_llist_cmpxchg(struct llist_head *head,
+- struct llist_node *old,
+- struct llist_node *new)
+-{
+- return cmpxchg(&head->first, old, new);
+-}
+-
+ static __cold void io_fallback_tw(struct io_uring_task *tctx, bool sync)
+ {
+ struct llist_node *node = llist_del_all(&tctx->task_list);
+@@ -1274,9 +1257,7 @@ void tctx_task_work(struct callback_head *cb)
+ struct io_ring_ctx *ctx = NULL;
+ struct io_uring_task *tctx = container_of(cb, struct io_uring_task,
+ task_work);
+- struct llist_node fake = {};
+ struct llist_node *node;
+- unsigned int loops = 0;
+ unsigned int count = 0;
+
+ if (unlikely(current->flags & PF_EXITING)) {
+@@ -1284,21 +1265,9 @@ void tctx_task_work(struct callback_head *cb)
+ return;
+ }
+
+- do {
+- loops++;
+- node = io_llist_xchg(&tctx->task_list, &fake);
+- count += handle_tw_list(node, &ctx, &ts, &fake);
+-
+- /* skip expensive cmpxchg if there are items in the list */
+- if (READ_ONCE(tctx->task_list.first) != &fake)
+- continue;
+- if (ts.locked && !wq_list_empty(&ctx->submit_state.compl_reqs)) {
+- io_submit_flush_completions(ctx);
+- if (READ_ONCE(tctx->task_list.first) != &fake)
+- continue;
+- }
+- node = io_llist_cmpxchg(&tctx->task_list, &fake, NULL);
+- } while (node != &fake);
++ node = llist_del_all(&tctx->task_list);
++ if (node)
++ count = handle_tw_list(node, &ctx, &ts);
+
+ ctx_flush_and_put(ctx, &ts);
+
+@@ -1306,7 +1275,7 @@ void tctx_task_work(struct callback_head *cb)
+ if (unlikely(atomic_read(&tctx->in_cancel)))
+ io_uring_drop_tctx_refs(current);
+
+- trace_io_uring_task_work_run(tctx, count, loops);
++ trace_io_uring_task_work_run(tctx, count, 1);
+ }
+
+ static inline void io_req_local_work_add(struct io_kiocb *req, unsigned flags)
+@@ -1420,7 +1389,20 @@ static void __cold io_move_task_work_from_local(struct io_ring_ctx *ctx)
+ }
+ }
+
+-static int __io_run_local_work(struct io_ring_ctx *ctx, struct io_tw_state *ts)
++static bool io_run_local_work_continue(struct io_ring_ctx *ctx, int events,
++ int min_events)
++{
++ if (llist_empty(&ctx->work_llist))
++ return false;
++ if (events < min_events)
++ return true;
++ if (ctx->flags & IORING_SETUP_TASKRUN_FLAG)
++ atomic_or(IORING_SQ_TASKRUN, &ctx->rings->sq_flags);
++ return false;
++}
++
++static int __io_run_local_work(struct io_ring_ctx *ctx, struct io_tw_state *ts,
++ int min_events)
+ {
+ struct llist_node *node;
+ unsigned int loops = 0;
+@@ -1449,18 +1431,20 @@ static int __io_run_local_work(struct io_ring_ctx *ctx, struct io_tw_state *ts)
+ }
+ loops++;
+
+- if (!llist_empty(&ctx->work_llist))
++ if (io_run_local_work_continue(ctx, ret, min_events))
+ goto again;
+ if (ts->locked) {
+ io_submit_flush_completions(ctx);
+- if (!llist_empty(&ctx->work_llist))
++ if (io_run_local_work_continue(ctx, ret, min_events))
+ goto again;
+ }
++
+ trace_io_uring_local_work_run(ctx, ret, loops);
+ return ret;
+ }
+
+-static inline int io_run_local_work_locked(struct io_ring_ctx *ctx)
++static inline int io_run_local_work_locked(struct io_ring_ctx *ctx,
++ int min_events)
+ {
+ struct io_tw_state ts = { .locked = true, };
+ int ret;
+@@ -1468,20 +1452,20 @@ static inline int io_run_local_work_locked(struct io_ring_ctx *ctx)
+ if (llist_empty(&ctx->work_llist))
+ return 0;
+
+- ret = __io_run_local_work(ctx, &ts);
++ ret = __io_run_local_work(ctx, &ts, min_events);
+ /* shouldn't happen! */
+ if (WARN_ON_ONCE(!ts.locked))
+ mutex_lock(&ctx->uring_lock);
+ return ret;
+ }
+
+-static int io_run_local_work(struct io_ring_ctx *ctx)
++static int io_run_local_work(struct io_ring_ctx *ctx, int min_events)
+ {
+ struct io_tw_state ts = {};
+ int ret;
+
+ ts.locked = mutex_trylock(&ctx->uring_lock);
+- ret = __io_run_local_work(ctx, &ts);
++ ret = __io_run_local_work(ctx, &ts, min_events);
+ if (ts.locked)
+ mutex_unlock(&ctx->uring_lock);
+
+@@ -1677,7 +1661,7 @@ static int io_iopoll_check(struct io_ring_ctx *ctx, long min)
+ io_task_work_pending(ctx)) {
+ u32 tail = ctx->cached_cq_tail;
+
+- (void) io_run_local_work_locked(ctx);
++ (void) io_run_local_work_locked(ctx, min);
+
+ if (task_work_pending(current) ||
+ wq_list_empty(&ctx->iopoll_list)) {
+@@ -2520,7 +2504,7 @@ int io_run_task_work_sig(struct io_ring_ctx *ctx)
+ {
+ if (!llist_empty(&ctx->work_llist)) {
+ __set_current_state(TASK_RUNNING);
+- if (io_run_local_work(ctx) > 0)
++ if (io_run_local_work(ctx, INT_MAX) > 0)
+ return 0;
+ }
+ if (io_run_task_work() > 0)
+@@ -2543,7 +2527,7 @@ static bool current_pending_io(void)
+ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
+ struct io_wait_queue *iowq)
+ {
+- int io_wait, ret;
++ int ret;
+
+ if (unlikely(READ_ONCE(ctx->check_cq)))
+ return 1;
+@@ -2561,7 +2545,6 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
+ * can take into account that the task is waiting for IO - turns out
+ * to be important for low QD IO.
+ */
+- io_wait = current->in_iowait;
+ if (current_pending_io())
+ current->in_iowait = 1;
+ ret = 0;
+@@ -2569,7 +2552,7 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
+ schedule();
+ else if (!schedule_hrtimeout(&iowq->timeout, HRTIMER_MODE_ABS))
+ ret = -ETIME;
+- current->in_iowait = io_wait;
++ current->in_iowait = 0;
+ return ret;
+ }
+
+@@ -2588,7 +2571,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
+ if (!io_allowed_run_tw(ctx))
+ return -EEXIST;
+ if (!llist_empty(&ctx->work_llist))
+- io_run_local_work(ctx);
++ io_run_local_work(ctx, min_events);
+ io_run_task_work();
+ io_cqring_overflow_flush(ctx);
+ /* if user messes with these they will just get an early return */
+@@ -2626,11 +2609,10 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
+
+ trace_io_uring_cqring_wait(ctx, min_events);
+ do {
++ int nr_wait = (int) iowq.cq_tail - READ_ONCE(ctx->rings->cq.tail);
+ unsigned long check_cq;
+
+ if (ctx->flags & IORING_SETUP_DEFER_TASKRUN) {
+- int nr_wait = (int) iowq.cq_tail - READ_ONCE(ctx->rings->cq.tail);
+-
+ atomic_set(&ctx->cq_wait_nr, nr_wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ } else {
+@@ -2649,7 +2631,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
+ */
+ io_run_task_work();
+ if (!llist_empty(&ctx->work_llist))
+- io_run_local_work(ctx);
++ io_run_local_work(ctx, nr_wait);
+
+ /*
+ * Non-local task_work will be run on exit to userspace, but
+@@ -2720,7 +2702,7 @@ static void *__io_uaddr_map(struct page ***pages, unsigned short *npages,
+ struct page **page_array;
+ unsigned int nr_pages;
+ void *page_addr;
+- int ret, i;
++ int ret, i, pinned;
+
+ *npages = 0;
+
+@@ -2734,12 +2716,12 @@ static void *__io_uaddr_map(struct page ***pages, unsigned short *npages,
+ if (!page_array)
+ return ERR_PTR(-ENOMEM);
+
+- ret = pin_user_pages_fast(uaddr, nr_pages, FOLL_WRITE | FOLL_LONGTERM,
+- page_array);
+- if (ret != nr_pages) {
+-err:
+- io_pages_free(&page_array, ret > 0 ? ret : 0);
+- return ret < 0 ? ERR_PTR(ret) : ERR_PTR(-EFAULT);
++
++ pinned = pin_user_pages_fast(uaddr, nr_pages, FOLL_WRITE | FOLL_LONGTERM,
++ page_array);
++ if (pinned != nr_pages) {
++ ret = (pinned < 0) ? pinned : -EFAULT;
++ goto free_pages;
+ }
+
+ page_addr = page_address(page_array[0]);
+@@ -2753,7 +2735,7 @@ static void *__io_uaddr_map(struct page ***pages, unsigned short *npages,
+ * didn't support this feature.
+ */
+ if (PageHighMem(page_array[i]))
+- goto err;
++ goto free_pages;
+
+ /*
+ * No support for discontig pages for now, should either be a
+@@ -2762,13 +2744,17 @@ static void *__io_uaddr_map(struct page ***pages, unsigned short *npages,
+ * just fail them with EINVAL.
+ */
+ if (page_address(page_array[i]) != page_addr)
+- goto err;
++ goto free_pages;
+ page_addr += PAGE_SIZE;
+ }
+
+ *pages = page_array;
+ *npages = nr_pages;
+ return page_to_virt(page_array[0]);
++
++free_pages:
++ io_pages_free(&page_array, pinned > 0 ? pinned : 0);
++ return ERR_PTR(ret);
+ }
+
+ static void *io_rings_map(struct io_ring_ctx *ctx, unsigned long uaddr,
+@@ -3304,7 +3290,7 @@ static __cold bool io_uring_try_cancel_requests(struct io_ring_ctx *ctx,
+
+ if ((ctx->flags & IORING_SETUP_DEFER_TASKRUN) &&
+ io_allowed_defer_tw_run(ctx))
+- ret |= io_run_local_work(ctx) > 0;
++ ret |= io_run_local_work(ctx, INT_MAX) > 0;
+ ret |= io_cancel_defer_files(ctx, task, cancel_all);
+ mutex_lock(&ctx->uring_lock);
+ ret |= io_poll_remove_all(ctx, task, cancel_all);
+@@ -3666,7 +3652,7 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
+ * it should handle ownership problems if any.
+ */
+ if (ctx->flags & IORING_SETUP_DEFER_TASKRUN)
+- (void)io_run_local_work_locked(ctx);
++ (void)io_run_local_work_locked(ctx, min_complete);
+ }
+ mutex_unlock(&ctx->uring_lock);
+ }
+diff --git a/io_uring/net.c b/io_uring/net.c
+index 161622029147c..4aaeada03f1e7 100644
+--- a/io_uring/net.c
++++ b/io_uring/net.c
+@@ -204,16 +204,115 @@ static int io_setup_async_msg(struct io_kiocb *req,
+ return -EAGAIN;
+ }
+
++#ifdef CONFIG_COMPAT
++static int io_compat_msg_copy_hdr(struct io_kiocb *req,
++ struct io_async_msghdr *iomsg,
++ struct compat_msghdr *msg, int ddir)
++{
++ struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
++ struct compat_iovec __user *uiov;
++ int ret;
++
++ if (copy_from_user(msg, sr->umsg_compat, sizeof(*msg)))
++ return -EFAULT;
++
++ uiov = compat_ptr(msg->msg_iov);
++ if (req->flags & REQ_F_BUFFER_SELECT) {
++ compat_ssize_t clen;
++
++ iomsg->free_iov = NULL;
++ if (msg->msg_iovlen == 0) {
++ sr->len = 0;
++ } else if (msg->msg_iovlen > 1) {
++ return -EINVAL;
++ } else {
++ if (!access_ok(uiov, sizeof(*uiov)))
++ return -EFAULT;
++ if (__get_user(clen, &uiov->iov_len))
++ return -EFAULT;
++ if (clen < 0)
++ return -EINVAL;
++ sr->len = clen;
++ }
++
++ return 0;
++ }
++
++ iomsg->free_iov = iomsg->fast_iov;
++ ret = __import_iovec(ddir, (struct iovec __user *)uiov, msg->msg_iovlen,
++ UIO_FASTIOV, &iomsg->free_iov,
++ &iomsg->msg.msg_iter, true);
++ if (unlikely(ret < 0))
++ return ret;
++
++ return 0;
++}
++#endif
++
++static int io_msg_copy_hdr(struct io_kiocb *req, struct io_async_msghdr *iomsg,
++ struct user_msghdr *msg, int ddir)
++{
++ struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
++ int ret;
++
++ if (copy_from_user(msg, sr->umsg, sizeof(*sr->umsg)))
++ return -EFAULT;
++
++ if (req->flags & REQ_F_BUFFER_SELECT) {
++ if (msg->msg_iovlen == 0) {
++ sr->len = iomsg->fast_iov[0].iov_len = 0;
++ iomsg->fast_iov[0].iov_base = NULL;
++ iomsg->free_iov = NULL;
++ } else if (msg->msg_iovlen > 1) {
++ return -EINVAL;
++ } else {
++ if (copy_from_user(iomsg->fast_iov, msg->msg_iov,
++ sizeof(*msg->msg_iov)))
++ return -EFAULT;
++ sr->len = iomsg->fast_iov[0].iov_len;
++ iomsg->free_iov = NULL;
++ }
++
++ return 0;
++ }
++
++ iomsg->free_iov = iomsg->fast_iov;
++ ret = __import_iovec(ddir, msg->msg_iov, msg->msg_iovlen, UIO_FASTIOV,
++ &iomsg->free_iov, &iomsg->msg.msg_iter, false);
++ if (unlikely(ret < 0))
++ return ret;
++
++ return 0;
++}
++
+ static int io_sendmsg_copy_hdr(struct io_kiocb *req,
+ struct io_async_msghdr *iomsg)
+ {
+ struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
++ struct user_msghdr msg;
+ int ret;
+
+ iomsg->msg.msg_name = &iomsg->addr;
+- iomsg->free_iov = iomsg->fast_iov;
+- ret = sendmsg_copy_msghdr(&iomsg->msg, sr->umsg, sr->msg_flags,
+- &iomsg->free_iov);
++ iomsg->msg.msg_iter.nr_segs = 0;
++
++#ifdef CONFIG_COMPAT
++ if (unlikely(req->ctx->compat)) {
++ struct compat_msghdr cmsg;
++
++ ret = io_compat_msg_copy_hdr(req, iomsg, &cmsg, ITER_SOURCE);
++ if (unlikely(ret))
++ return ret;
++
++ return __get_compat_msghdr(&iomsg->msg, &cmsg, NULL);
++ }
++#endif
++
++ ret = io_msg_copy_hdr(req, iomsg, &msg, ITER_SOURCE);
++ if (unlikely(ret))
++ return ret;
++
++ ret = __copy_msghdr(&iomsg->msg, &msg, NULL);
++
+ /* save msg_control as sys_sendmsg() overwrites it */
+ sr->msg_control = iomsg->msg.msg_control_user;
+ return ret;
+@@ -435,142 +534,77 @@ int io_send(struct io_kiocb *req, unsigned int issue_flags)
+ return IOU_OK;
+ }
+
+-static bool io_recvmsg_multishot_overflow(struct io_async_msghdr *iomsg)
++static int io_recvmsg_mshot_prep(struct io_kiocb *req,
++ struct io_async_msghdr *iomsg,
++ int namelen, size_t controllen)
+ {
+- int hdr;
+-
+- if (iomsg->namelen < 0)
+- return true;
+- if (check_add_overflow((int)sizeof(struct io_uring_recvmsg_out),
+- iomsg->namelen, &hdr))
+- return true;
+- if (check_add_overflow(hdr, (int)iomsg->controllen, &hdr))
+- return true;
++ if ((req->flags & (REQ_F_APOLL_MULTISHOT|REQ_F_BUFFER_SELECT)) ==
++ (REQ_F_APOLL_MULTISHOT|REQ_F_BUFFER_SELECT)) {
++ int hdr;
++
++ if (unlikely(namelen < 0))
++ return -EOVERFLOW;
++ if (check_add_overflow(sizeof(struct io_uring_recvmsg_out),
++ namelen, &hdr))
++ return -EOVERFLOW;
++ if (check_add_overflow(hdr, controllen, &hdr))
++ return -EOVERFLOW;
++
++ iomsg->namelen = namelen;
++ iomsg->controllen = controllen;
++ return 0;
++ }
+
+- return false;
++ return 0;
+ }
+
+-static int __io_recvmsg_copy_hdr(struct io_kiocb *req,
+- struct io_async_msghdr *iomsg)
++static int io_recvmsg_copy_hdr(struct io_kiocb *req,
++ struct io_async_msghdr *iomsg)
+ {
+- struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
+ struct user_msghdr msg;
+ int ret;
+
+- if (copy_from_user(&msg, sr->umsg, sizeof(*sr->umsg)))
+- return -EFAULT;
+-
+- ret = __copy_msghdr(&iomsg->msg, &msg, &iomsg->uaddr);
+- if (ret)
+- return ret;
+-
+- if (req->flags & REQ_F_BUFFER_SELECT) {
+- if (msg.msg_iovlen == 0) {
+- sr->len = iomsg->fast_iov[0].iov_len = 0;
+- iomsg->fast_iov[0].iov_base = NULL;
+- iomsg->free_iov = NULL;
+- } else if (msg.msg_iovlen > 1) {
+- return -EINVAL;
+- } else {
+- if (copy_from_user(iomsg->fast_iov, msg.msg_iov, sizeof(*msg.msg_iov)))
+- return -EFAULT;
+- sr->len = iomsg->fast_iov[0].iov_len;
+- iomsg->free_iov = NULL;
+- }
+-
+- if (req->flags & REQ_F_APOLL_MULTISHOT) {
+- iomsg->namelen = msg.msg_namelen;
+- iomsg->controllen = msg.msg_controllen;
+- if (io_recvmsg_multishot_overflow(iomsg))
+- return -EOVERFLOW;
+- }
+- } else {
+- iomsg->free_iov = iomsg->fast_iov;
+- ret = __import_iovec(ITER_DEST, msg.msg_iov, msg.msg_iovlen, UIO_FASTIOV,
+- &iomsg->free_iov, &iomsg->msg.msg_iter,
+- false);
+- if (ret > 0)
+- ret = 0;
+- }
+-
+- return ret;
+-}
++ iomsg->msg.msg_name = &iomsg->addr;
++ iomsg->msg.msg_iter.nr_segs = 0;
+
+ #ifdef CONFIG_COMPAT
+-static int __io_compat_recvmsg_copy_hdr(struct io_kiocb *req,
+- struct io_async_msghdr *iomsg)
+-{
+- struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
+- struct compat_msghdr msg;
+- struct compat_iovec __user *uiov;
+- int ret;
+-
+- if (copy_from_user(&msg, sr->umsg_compat, sizeof(msg)))
+- return -EFAULT;
+-
+- ret = __get_compat_msghdr(&iomsg->msg, &msg, &iomsg->uaddr);
+- if (ret)
+- return ret;
++ if (unlikely(req->ctx->compat)) {
++ struct compat_msghdr cmsg;
+
+- uiov = compat_ptr(msg.msg_iov);
+- if (req->flags & REQ_F_BUFFER_SELECT) {
+- compat_ssize_t clen;
+-
+- iomsg->free_iov = NULL;
+- if (msg.msg_iovlen == 0) {
+- sr->len = 0;
+- } else if (msg.msg_iovlen > 1) {
+- return -EINVAL;
+- } else {
+- if (!access_ok(uiov, sizeof(*uiov)))
+- return -EFAULT;
+- if (__get_user(clen, &uiov->iov_len))
+- return -EFAULT;
+- if (clen < 0)
+- return -EINVAL;
+- sr->len = clen;
+- }
++ ret = io_compat_msg_copy_hdr(req, iomsg, &cmsg, ITER_DEST);
++ if (unlikely(ret))
++ return ret;
+
+- if (req->flags & REQ_F_APOLL_MULTISHOT) {
+- iomsg->namelen = msg.msg_namelen;
+- iomsg->controllen = msg.msg_controllen;
+- if (io_recvmsg_multishot_overflow(iomsg))
+- return -EOVERFLOW;
+- }
+- } else {
+- iomsg->free_iov = iomsg->fast_iov;
+- ret = __import_iovec(ITER_DEST, (struct iovec __user *)uiov, msg.msg_iovlen,
+- UIO_FASTIOV, &iomsg->free_iov,
+- &iomsg->msg.msg_iter, true);
+- if (ret < 0)
++ ret = __get_compat_msghdr(&iomsg->msg, &cmsg, &iomsg->uaddr);
++ if (unlikely(ret))
+ return ret;
+- }
+
+- return 0;
+-}
++ return io_recvmsg_mshot_prep(req, iomsg, cmsg.msg_namelen,
++ cmsg.msg_controllen);
++ }
+ #endif
+
+-static int io_recvmsg_copy_hdr(struct io_kiocb *req,
+- struct io_async_msghdr *iomsg)
+-{
+- iomsg->msg.msg_name = &iomsg->addr;
+- iomsg->msg.msg_iter.nr_segs = 0;
++ ret = io_msg_copy_hdr(req, iomsg, &msg, ITER_DEST);
++ if (unlikely(ret))
++ return ret;
+
+-#ifdef CONFIG_COMPAT
+- if (req->ctx->compat)
+- return __io_compat_recvmsg_copy_hdr(req, iomsg);
+-#endif
++ ret = __copy_msghdr(&iomsg->msg, &msg, &iomsg->uaddr);
++ if (unlikely(ret))
++ return ret;
+
+- return __io_recvmsg_copy_hdr(req, iomsg);
++ return io_recvmsg_mshot_prep(req, iomsg, msg.msg_namelen,
++ msg.msg_controllen);
+ }
+
+ int io_recvmsg_prep_async(struct io_kiocb *req)
+ {
++ struct io_async_msghdr *iomsg;
+ int ret;
+
+ if (!io_msg_alloc_async_prep(req))
+ return -ENOMEM;
+- ret = io_recvmsg_copy_hdr(req, req->async_data);
++ iomsg = req->async_data;
++ ret = io_recvmsg_copy_hdr(req, iomsg);
+ if (!ret)
+ req->flags |= REQ_F_NEED_CLEANUP;
+ return ret;
+diff --git a/io_uring/poll.c b/io_uring/poll.c
+index 7513afc7b702e..58b7556f621eb 100644
+--- a/io_uring/poll.c
++++ b/io_uring/poll.c
+@@ -995,7 +995,6 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
+ struct io_hash_bucket *bucket;
+ struct io_kiocb *preq;
+ int ret2, ret = 0;
+- struct io_tw_state ts = { .locked = true };
+
+ io_ring_submit_lock(ctx, issue_flags);
+ preq = io_poll_find(ctx, true, &cd, &ctx->cancel_table, &bucket);
+@@ -1044,7 +1043,8 @@ int io_poll_remove(struct io_kiocb *req, unsigned int issue_flags)
+
+ req_set_fail(preq);
+ io_req_set_res(preq, -ECANCELED, 0);
+- io_req_task_complete(preq, &ts);
++ preq->io_task_work.func = io_req_task_complete;
++ io_req_task_work_add(preq);
+ out:
+ io_ring_submit_unlock(ctx, issue_flags);
+ if (ret < 0) {
+diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
+index 5964711891767..92aa3cf0396b8 100644
+--- a/kernel/bpf/btf.c
++++ b/kernel/bpf/btf.c
+@@ -7009,6 +7009,8 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
+ args = (const struct btf_param *)(t + 1);
+ nargs = btf_type_vlen(t);
+ if (nargs > MAX_BPF_FUNC_REG_ARGS) {
++ if (!is_global)
++ return -EINVAL;
+ bpf_log(log, "Global function %s() with %d > %d args. Buggy compiler.\n",
+ tname, nargs, MAX_BPF_FUNC_REG_ARGS);
+ return -EINVAL;
+@@ -7018,6 +7020,8 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
+ while (btf_type_is_modifier(t))
+ t = btf_type_by_id(btf, t->type);
+ if (!btf_type_is_int(t) && !btf_is_any_enum(t)) {
++ if (!is_global)
++ return -EINVAL;
+ bpf_log(log,
+ "Global function %s() doesn't return scalar. Only those are supported.\n",
+ tname);
+@@ -7058,10 +7062,6 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
+
+ while (btf_type_is_modifier(t))
+ t = btf_type_by_id(btf, t->type);
+- if (btf_type_is_int(t) || btf_is_any_enum(t)) {
+- sub->args[i].arg_type = ARG_ANYTHING;
+- continue;
+- }
+ if (btf_type_is_ptr(t) && btf_get_prog_ctx_type(log, btf, t, prog_type, i)) {
+ sub->args[i].arg_type = ARG_PTR_TO_CTX;
+ continue;
+@@ -7091,6 +7091,12 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
+ bpf_log(log, "arg#%d marked as non-null, but is not a pointer type\n", i);
+ return -EINVAL;
+ }
++ if (btf_type_is_int(t) || btf_is_any_enum(t)) {
++ sub->args[i].arg_type = ARG_ANYTHING;
++ continue;
++ }
++ if (!is_global)
++ return -EINVAL;
+ bpf_log(log, "Arg#%d type %s in %s() is not supported yet.\n",
+ i, btf_type_str(t), tname);
+ return -EINVAL;
+diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
+index ea6843be2616c..026627226ec48 100644
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -888,7 +888,12 @@ static LIST_HEAD(pack_list);
+ * CONFIG_MMU=n. Use PAGE_SIZE in these cases.
+ */
+ #ifdef PMD_SIZE
+-#define BPF_PROG_PACK_SIZE (PMD_SIZE * num_possible_nodes())
++/* PMD_SIZE is really big for some archs. It doesn't make sense to
++ * reserve too much memory in one allocation. Hardcode BPF_PROG_PACK_SIZE to
++ * 2MiB * num_possible_nodes(). On most architectures PMD_SIZE will be
++ * greater than or equal to 2MB.
++ */
++#define BPF_PROG_PACK_SIZE (SZ_2M * num_possible_nodes())
+ #else
+ #define BPF_PROG_PACK_SIZE PAGE_SIZE
+ #endif
+diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c
+index ef82ffc90cbe9..8f1d390bcbdeb 100644
+--- a/kernel/bpf/cpumap.c
++++ b/kernel/bpf/cpumap.c
+@@ -262,6 +262,7 @@ static int cpu_map_bpf_prog_run(struct bpf_cpu_map_entry *rcpu, void **frames,
+ static int cpu_map_kthread_run(void *data)
+ {
+ struct bpf_cpu_map_entry *rcpu = data;
++ unsigned long last_qs = jiffies;
+
+ complete(&rcpu->kthread_running);
+ set_current_state(TASK_INTERRUPTIBLE);
+@@ -287,10 +288,12 @@ static int cpu_map_kthread_run(void *data)
+ if (__ptr_ring_empty(rcpu->queue)) {
+ schedule();
+ sched = 1;
++ last_qs = jiffies;
+ } else {
+ __set_current_state(TASK_RUNNING);
+ }
+ } else {
++ rcu_softirq_qs_periodic(last_qs);
+ sched = cond_resched();
+ }
+
+diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
+index a936c704d4e77..4e2cdbb5629f2 100644
+--- a/kernel/bpf/devmap.c
++++ b/kernel/bpf/devmap.c
+@@ -130,13 +130,14 @@ static int dev_map_init_map(struct bpf_dtab *dtab, union bpf_attr *attr)
+ bpf_map_init_from_attr(&dtab->map, attr);
+
+ if (attr->map_type == BPF_MAP_TYPE_DEVMAP_HASH) {
+- dtab->n_buckets = roundup_pow_of_two(dtab->map.max_entries);
+-
+- if (!dtab->n_buckets) /* Overflow check */
++ /* hash table size must be power of 2; roundup_pow_of_two() can
++ * overflow into UB on 32-bit arches, so check that first
++ */
++ if (dtab->map.max_entries > 1UL << 31)
+ return -EINVAL;
+- }
+
+- if (attr->map_type == BPF_MAP_TYPE_DEVMAP_HASH) {
++ dtab->n_buckets = roundup_pow_of_two(dtab->map.max_entries);
++
+ dtab->dev_index_head = dev_map_create_hash(dtab->n_buckets,
+ dtab->map.numa_node);
+ if (!dtab->dev_index_head)
+diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
+index 03a6a2500b6ab..3a088a5349bc0 100644
+--- a/kernel/bpf/hashtab.c
++++ b/kernel/bpf/hashtab.c
+@@ -499,7 +499,13 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
+ num_possible_cpus());
+ }
+
+- /* hash table size must be power of 2 */
++ /* hash table size must be power of 2; roundup_pow_of_two() can overflow
++ * into UB on 32-bit arches, so check that first
++ */
++ err = -E2BIG;
++ if (htab->map.max_entries > 1UL << 31)
++ goto free_htab;
++
+ htab->n_buckets = roundup_pow_of_two(htab->map.max_entries);
+
+ htab->elem_size = sizeof(struct htab_elem) +
+@@ -509,10 +515,8 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
+ else
+ htab->elem_size += round_up(htab->map.value_size, 8);
+
+- err = -E2BIG;
+- /* prevent zero size kmalloc and check for u32 overflow */
+- if (htab->n_buckets == 0 ||
+- htab->n_buckets > U32_MAX / sizeof(struct bucket))
++ /* check for u32 overflow */
++ if (htab->n_buckets > U32_MAX / sizeof(struct bucket))
+ goto free_htab;
+
+ err = bpf_map_init_elem_count(&htab->map);
+diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
+index d19cd863d294e..b10092754dde3 100644
+--- a/kernel/bpf/helpers.c
++++ b/kernel/bpf/helpers.c
+@@ -334,7 +334,7 @@ static inline void __bpf_spin_lock_irqsave(struct bpf_spin_lock *lock)
+ __this_cpu_write(irqsave_flags, flags);
+ }
+
+-notrace BPF_CALL_1(bpf_spin_lock, struct bpf_spin_lock *, lock)
++NOTRACE_BPF_CALL_1(bpf_spin_lock, struct bpf_spin_lock *, lock)
+ {
+ __bpf_spin_lock_irqsave(lock);
+ return 0;
+@@ -357,7 +357,7 @@ static inline void __bpf_spin_unlock_irqrestore(struct bpf_spin_lock *lock)
+ local_irq_restore(flags);
+ }
+
+-notrace BPF_CALL_1(bpf_spin_unlock, struct bpf_spin_lock *, lock)
++NOTRACE_BPF_CALL_1(bpf_spin_unlock, struct bpf_spin_lock *, lock)
+ {
+ __bpf_spin_unlock_irqrestore(lock);
+ return 0;
+diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
+index dff7ba5397015..c99f8e5234ac4 100644
+--- a/kernel/bpf/stackmap.c
++++ b/kernel/bpf/stackmap.c
+@@ -91,11 +91,14 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr)
+ } else if (value_size / 8 > sysctl_perf_event_max_stack)
+ return ERR_PTR(-EINVAL);
+
+- /* hash table size must be power of 2 */
+- n_buckets = roundup_pow_of_two(attr->max_entries);
+- if (!n_buckets)
++ /* hash table size must be power of 2; roundup_pow_of_two() can overflow
++ * into UB on 32-bit arches, so check that first
++ */
++ if (attr->max_entries > 1UL << 31)
+ return ERR_PTR(-E2BIG);
+
++ n_buckets = roundup_pow_of_two(attr->max_entries);
++
+ cost = n_buckets * sizeof(struct stack_map_bucket *) + sizeof(*smap);
+ smap = bpf_map_area_alloc(cost, bpf_map_attr_numa_node(attr));
+ if (!smap)
+diff --git a/kernel/module/main.c b/kernel/module/main.c
+index 36681911c05ac..b0b99348e1a8b 100644
+--- a/kernel/module/main.c
++++ b/kernel/module/main.c
+@@ -2489,6 +2489,11 @@ static void do_free_init(struct work_struct *w)
+ }
+ }
+
++void flush_module_init_free_work(void)
++{
++ flush_work(&init_free_wq);
++}
++
+ #undef MODULE_PARAM_PREFIX
+ #define MODULE_PARAM_PREFIX "module."
+ /* Default value for module->async_probe_requested */
+@@ -2593,8 +2598,8 @@ static noinline int do_init_module(struct module *mod)
+ * Note that module_alloc() on most architectures creates W+X page
+ * mappings which won't be cleaned up until do_free_init() runs. Any
+ * code such as mark_rodata_ro() which depends on those mappings to
+- * be cleaned up needs to sync with the queued work - ie
+- * rcu_barrier()
++ * be cleaned up needs to sync with the queued work by invoking
++ * flush_module_init_free_work().
+ */
+ if (llist_add(&freeinit->node, &init_free_list))
+ schedule_work(&init_free_wq);
+diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h
+index 6c2afee5ef620..ac2d9750e5f81 100644
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -130,6 +130,7 @@ struct printk_message {
+ };
+
+ bool other_cpu_in_panic(void);
++bool this_cpu_in_panic(void);
+ bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
+ bool is_extended, bool may_supress);
+
+diff --git a/kernel/printk/nbcon.c b/kernel/printk/nbcon.c
+index b96077152f49d..c8093bcc01fe6 100644
+--- a/kernel/printk/nbcon.c
++++ b/kernel/printk/nbcon.c
+@@ -140,39 +140,6 @@ static inline bool nbcon_state_try_cmpxchg(struct console *con, struct nbcon_sta
+ return atomic_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_state), &cur->atom, new->atom);
+ }
+
+-#ifdef CONFIG_64BIT
+-
+-#define __seq_to_nbcon_seq(seq) (seq)
+-#define __nbcon_seq_to_seq(seq) (seq)
+-
+-#else /* CONFIG_64BIT */
+-
+-#define __seq_to_nbcon_seq(seq) ((u32)seq)
+-
+-static inline u64 __nbcon_seq_to_seq(u32 nbcon_seq)
+-{
+- u64 seq;
+- u64 rb_next_seq;
+-
+- /*
+- * The provided sequence is only the lower 32 bits of the ringbuffer
+- * sequence. It needs to be expanded to 64bit. Get the next sequence
+- * number from the ringbuffer and fold it.
+- *
+- * Having a 32bit representation in the console is sufficient.
+- * If a console ever gets more than 2^31 records behind
+- * the ringbuffer then this is the least of the problems.
+- *
+- * Also the access to the ring buffer is always safe.
+- */
+- rb_next_seq = prb_next_seq(prb);
+- seq = rb_next_seq - ((u32)rb_next_seq - nbcon_seq);
+-
+- return seq;
+-}
+-
+-#endif /* CONFIG_64BIT */
+-
+ /**
+ * nbcon_seq_read - Read the current console sequence
+ * @con: Console to read the sequence of
+@@ -183,7 +150,7 @@ u64 nbcon_seq_read(struct console *con)
+ {
+ unsigned long nbcon_seq = atomic_long_read(&ACCESS_PRIVATE(con, nbcon_seq));
+
+- return __nbcon_seq_to_seq(nbcon_seq);
++ return __ulseq_to_u64seq(prb, nbcon_seq);
+ }
+
+ /**
+@@ -204,7 +171,7 @@ void nbcon_seq_force(struct console *con, u64 seq)
+ */
+ u64 valid_seq = max_t(u64, seq, prb_first_valid_seq(prb));
+
+- atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), __seq_to_nbcon_seq(valid_seq));
++ atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), __u64seq_to_ulseq(valid_seq));
+
+ /* Clear con->seq since nbcon consoles use con->nbcon_seq instead. */
+ con->seq = 0;
+@@ -223,11 +190,11 @@ void nbcon_seq_force(struct console *con, u64 seq)
+ */
+ static void nbcon_seq_try_update(struct nbcon_context *ctxt, u64 new_seq)
+ {
+- unsigned long nbcon_seq = __seq_to_nbcon_seq(ctxt->seq);
++ unsigned long nbcon_seq = __u64seq_to_ulseq(ctxt->seq);
+ struct console *con = ctxt->console;
+
+ if (atomic_long_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_seq), &nbcon_seq,
+- __seq_to_nbcon_seq(new_seq))) {
++ __u64seq_to_ulseq(new_seq))) {
+ ctxt->seq = new_seq;
+ } else {
+ ctxt->seq = nbcon_seq_read(con);
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index f2444b581e16c..72f6a564e832f 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -347,6 +347,29 @@ static bool panic_in_progress(void)
+ return unlikely(atomic_read(&panic_cpu) != PANIC_CPU_INVALID);
+ }
+
++/* Return true if a panic is in progress on the current CPU. */
++bool this_cpu_in_panic(void)
++{
++ /*
++ * We can use raw_smp_processor_id() here because it is impossible for
++ * the task to be migrated to the panic_cpu, or away from it. If
++ * panic_cpu has already been set, and we're not currently executing on
++ * that CPU, then we never will be.
++ */
++ return unlikely(atomic_read(&panic_cpu) == raw_smp_processor_id());
++}
++
++/*
++ * Return true if a panic is in progress on a remote CPU.
++ *
++ * On true, the local CPU should immediately release any printing resources
++ * that may be needed by the panic CPU.
++ */
++bool other_cpu_in_panic(void)
++{
++ return (panic_in_progress() && !this_cpu_in_panic());
++}
++
+ /*
+ * This is used for debugging the mess that is the VT code by
+ * keeping track if we have the console semaphore held. It's
+@@ -1846,10 +1869,23 @@ static bool console_waiter;
+ */
+ static void console_lock_spinning_enable(void)
+ {
++ /*
++ * Do not use spinning in panic(). The panic CPU wants to keep the lock.
++ * Non-panic CPUs abandon the flush anyway.
++ *
++ * Just keep the lockdep annotation. The panic-CPU should avoid
++ * taking console_owner_lock because it might cause a deadlock.
++ * This looks like the easiest way how to prevent false lockdep
++ * reports without handling races a lockless way.
++ */
++ if (panic_in_progress())
++ goto lockdep;
++
+ raw_spin_lock(&console_owner_lock);
+ console_owner = current;
+ raw_spin_unlock(&console_owner_lock);
+
++lockdep:
+ /* The waiter may spin on us after setting console_owner */
+ spin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);
+ }
+@@ -1874,6 +1910,22 @@ static int console_lock_spinning_disable_and_check(int cookie)
+ {
+ int waiter;
+
++ /*
++ * Ignore spinning waiters during panic() because they might get stopped
++ * or blocked at any time,
++ *
++ * It is safe because nobody is allowed to start spinning during panic
++ * in the first place. If there has been a waiter then non panic CPUs
++ * might stay spinning. They would get stopped anyway. The panic context
++ * will never start spinning and an interrupted spin on panic CPU will
++ * never continue.
++ */
++ if (panic_in_progress()) {
++ /* Keep lockdep happy. */
++ spin_release(&console_owner_dep_map, _THIS_IP_);
++ return 0;
++ }
++
+ raw_spin_lock(&console_owner_lock);
+ waiter = READ_ONCE(console_waiter);
+ console_owner = NULL;
+@@ -2601,26 +2653,6 @@ static int console_cpu_notify(unsigned int cpu)
+ return 0;
+ }
+
+-/*
+- * Return true if a panic is in progress on a remote CPU.
+- *
+- * On true, the local CPU should immediately release any printing resources
+- * that may be needed by the panic CPU.
+- */
+-bool other_cpu_in_panic(void)
+-{
+- if (!panic_in_progress())
+- return false;
+-
+- /*
+- * We can use raw_smp_processor_id() here because it is impossible for
+- * the task to be migrated to the panic_cpu, or away from it. If
+- * panic_cpu has already been set, and we're not currently executing on
+- * that CPU, then we never will be.
+- */
+- return atomic_read(&panic_cpu) != raw_smp_processor_id();
+-}
+-
+ /**
+ * console_lock - block the console subsystem from printing
+ *
+@@ -3761,7 +3793,7 @@ static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progre
+
+ might_sleep();
+
+- seq = prb_next_seq(prb);
++ seq = prb_next_reserve_seq(prb);
+
+ /* Flush the consoles so that records up to @seq are printed. */
+ console_lock();
+diff --git a/kernel/printk/printk_ringbuffer.c b/kernel/printk/printk_ringbuffer.c
+index fde338606ce83..f5a8bb606fe50 100644
+--- a/kernel/printk/printk_ringbuffer.c
++++ b/kernel/printk/printk_ringbuffer.c
+@@ -6,6 +6,7 @@
+ #include <linux/errno.h>
+ #include <linux/bug.h>
+ #include "printk_ringbuffer.h"
++#include "internal.h"
+
+ /**
+ * DOC: printk_ringbuffer overview
+@@ -303,6 +304,9 @@
+ *
+ * desc_push_tail:B / desc_reserve:D
+ * set descriptor reusable (state), then push descriptor tail (id)
++ *
++ * desc_update_last_finalized:A / desc_last_finalized_seq:A
++ * store finalized record, then set new highest finalized sequence number
+ */
+
+ #define DATA_SIZE(data_ring) _DATA_SIZE((data_ring)->size_bits)
+@@ -1441,20 +1445,118 @@ bool prb_reserve_in_last(struct prb_reserved_entry *e, struct printk_ringbuffer
+ return false;
+ }
+
++/*
++ * @last_finalized_seq value guarantees that all records up to and including
++ * this sequence number are finalized and can be read. The only exception are
++ * too old records which have already been overwritten.
++ *
++ * It is also guaranteed that @last_finalized_seq only increases.
++ *
++ * Be aware that finalized records following non-finalized records are not
++ * reported because they are not yet available to the reader. For example,
++ * a new record stored via printk() will not be available to a printer if
++ * it follows a record that has not been finalized yet. However, once that
++ * non-finalized record becomes finalized, @last_finalized_seq will be
++ * appropriately updated and the full set of finalized records will be
++ * available to the printer. And since each printk() caller will either
++ * directly print or trigger deferred printing of all available unprinted
++ * records, all printk() messages will get printed.
++ */
++static u64 desc_last_finalized_seq(struct printk_ringbuffer *rb)
++{
++ struct prb_desc_ring *desc_ring = &rb->desc_ring;
++ unsigned long ulseq;
++
++ /*
++ * Guarantee the sequence number is loaded before loading the
++ * associated record in order to guarantee that the record can be
++ * seen by this CPU. This pairs with desc_update_last_finalized:A.
++ */
++ ulseq = atomic_long_read_acquire(&desc_ring->last_finalized_seq
++ ); /* LMM(desc_last_finalized_seq:A) */
++
++ return __ulseq_to_u64seq(rb, ulseq);
++}
++
++static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,
++ struct printk_record *r, unsigned int *line_count);
++
++/*
++ * Check if there are records directly following @last_finalized_seq that are
++ * finalized. If so, update @last_finalized_seq to the latest of these
++ * records. It is not allowed to skip over records that are not yet finalized.
++ */
++static void desc_update_last_finalized(struct printk_ringbuffer *rb)
++{
++ struct prb_desc_ring *desc_ring = &rb->desc_ring;
++ u64 old_seq = desc_last_finalized_seq(rb);
++ unsigned long oldval;
++ unsigned long newval;
++ u64 finalized_seq;
++ u64 try_seq;
++
++try_again:
++ finalized_seq = old_seq;
++ try_seq = finalized_seq + 1;
++
++ /* Try to find later finalized records. */
++ while (_prb_read_valid(rb, &try_seq, NULL, NULL)) {
++ finalized_seq = try_seq;
++ try_seq++;
++ }
++
++ /* No update needed if no later finalized record was found. */
++ if (finalized_seq == old_seq)
++ return;
++
++ oldval = __u64seq_to_ulseq(old_seq);
++ newval = __u64seq_to_ulseq(finalized_seq);
++
++ /*
++ * Set the sequence number of a later finalized record that has been
++ * seen.
++ *
++ * Guarantee the record data is visible to other CPUs before storing
++ * its sequence number. This pairs with desc_last_finalized_seq:A.
++ *
++ * Memory barrier involvement:
++ *
++ * If desc_last_finalized_seq:A reads from
++ * desc_update_last_finalized:A, then desc_read:A reads from
++ * _prb_commit:B.
++ *
++ * Relies on:
++ *
++ * RELEASE from _prb_commit:B to desc_update_last_finalized:A
++ * matching
++ * ACQUIRE from desc_last_finalized_seq:A to desc_read:A
++ *
++ * Note: _prb_commit:B and desc_update_last_finalized:A can be
++ * different CPUs. However, the desc_update_last_finalized:A
++ * CPU (which performs the release) must have previously seen
++ * _prb_commit:B.
++ */
++ if (!atomic_long_try_cmpxchg_release(&desc_ring->last_finalized_seq,
++ &oldval, newval)) { /* LMM(desc_update_last_finalized:A) */
++ old_seq = __ulseq_to_u64seq(rb, oldval);
++ goto try_again;
++ }
++}
++
+ /*
+ * Attempt to finalize a specified descriptor. If this fails, the descriptor
+ * is either already final or it will finalize itself when the writer commits.
+ */
+-static void desc_make_final(struct prb_desc_ring *desc_ring, unsigned long id)
++static void desc_make_final(struct printk_ringbuffer *rb, unsigned long id)
+ {
++ struct prb_desc_ring *desc_ring = &rb->desc_ring;
+ unsigned long prev_state_val = DESC_SV(id, desc_committed);
+ struct prb_desc *d = to_desc(desc_ring, id);
+
+- atomic_long_cmpxchg_relaxed(&d->state_var, prev_state_val,
+- DESC_SV(id, desc_finalized)); /* LMM(desc_make_final:A) */
+-
+- /* Best effort to remember the last finalized @id. */
+- atomic_long_set(&desc_ring->last_finalized_id, id);
++ if (atomic_long_try_cmpxchg_relaxed(&d->state_var, &prev_state_val,
++ DESC_SV(id, desc_finalized))) { /* LMM(desc_make_final:A) */
++ desc_update_last_finalized(rb);
++ }
+ }
+
+ /**
+@@ -1550,7 +1652,7 @@ bool prb_reserve(struct prb_reserved_entry *e, struct printk_ringbuffer *rb,
+ * readers. (For seq==0 there is no previous descriptor.)
+ */
+ if (info->seq > 0)
+- desc_make_final(desc_ring, DESC_ID(id - 1));
++ desc_make_final(rb, DESC_ID(id - 1));
+
+ r->text_buf = data_alloc(rb, r->text_buf_size, &d->text_blk_lpos, id);
+ /* If text data allocation fails, a data-less record is committed. */
+@@ -1643,7 +1745,7 @@ void prb_commit(struct prb_reserved_entry *e)
+ */
+ head_id = atomic_long_read(&desc_ring->head_id); /* LMM(prb_commit:A) */
+ if (head_id != e->id)
+- desc_make_final(desc_ring, e->id);
++ desc_make_final(e->rb, e->id);
+ }
+
+ /**
+@@ -1663,12 +1765,9 @@ void prb_commit(struct prb_reserved_entry *e)
+ */
+ void prb_final_commit(struct prb_reserved_entry *e)
+ {
+- struct prb_desc_ring *desc_ring = &e->rb->desc_ring;
+-
+ _prb_commit(e, desc_finalized);
+
+- /* Best effort to remember the last finalized @id. */
+- atomic_long_set(&desc_ring->last_finalized_id, e->id);
++ desc_update_last_finalized(e->rb);
+ }
+
+ /*
+@@ -1832,7 +1931,7 @@ static int prb_read(struct printk_ringbuffer *rb, u64 seq,
+ }
+
+ /* Get the sequence number of the tail descriptor. */
+-static u64 prb_first_seq(struct printk_ringbuffer *rb)
++u64 prb_first_seq(struct printk_ringbuffer *rb)
+ {
+ struct prb_desc_ring *desc_ring = &rb->desc_ring;
+ enum desc_state d_state;
+@@ -1875,12 +1974,123 @@ static u64 prb_first_seq(struct printk_ringbuffer *rb)
+ return seq;
+ }
+
++/**
++ * prb_next_reserve_seq() - Get the sequence number after the most recently
++ * reserved record.
++ *
++ * @rb: The ringbuffer to get the sequence number from.
++ *
++ * This is the public function available to readers to see what sequence
++ * number will be assigned to the next reserved record.
++ *
++ * Note that depending on the situation, this value can be equal to or
++ * higher than the sequence number returned by prb_next_seq().
++ *
++ * Context: Any context.
++ * Return: The sequence number that will be assigned to the next record
++ * reserved.
++ */
++u64 prb_next_reserve_seq(struct printk_ringbuffer *rb)
++{
++ struct prb_desc_ring *desc_ring = &rb->desc_ring;
++ unsigned long last_finalized_id;
++ atomic_long_t *state_var;
++ u64 last_finalized_seq;
++ unsigned long head_id;
++ struct prb_desc desc;
++ unsigned long diff;
++ struct prb_desc *d;
++ int err;
++
++ /*
++ * It may not be possible to read a sequence number for @head_id.
++ * So the ID of @last_finailzed_seq is used to calculate what the
++ * sequence number of @head_id will be.
++ */
++
++try_again:
++ last_finalized_seq = desc_last_finalized_seq(rb);
++
++ /*
++ * @head_id is loaded after @last_finalized_seq to ensure that
++ * it points to the record with @last_finalized_seq or newer.
++ *
++ * Memory barrier involvement:
++ *
++ * If desc_last_finalized_seq:A reads from
++ * desc_update_last_finalized:A, then
++ * prb_next_reserve_seq:A reads from desc_reserve:D.
++ *
++ * Relies on:
++ *
++ * RELEASE from desc_reserve:D to desc_update_last_finalized:A
++ * matching
++ * ACQUIRE from desc_last_finalized_seq:A to prb_next_reserve_seq:A
++ *
++ * Note: desc_reserve:D and desc_update_last_finalized:A can be
++ * different CPUs. However, the desc_update_last_finalized:A CPU
++ * (which performs the release) must have previously seen
++ * desc_read:C, which implies desc_reserve:D can be seen.
++ */
++ head_id = atomic_long_read(&desc_ring->head_id); /* LMM(prb_next_reserve_seq:A) */
++
++ d = to_desc(desc_ring, last_finalized_seq);
++ state_var = &d->state_var;
++
++ /* Extract the ID, used to specify the descriptor to read. */
++ last_finalized_id = DESC_ID(atomic_long_read(state_var));
++
++ /* Ensure @last_finalized_id is correct. */
++ err = desc_read_finalized_seq(desc_ring, last_finalized_id, last_finalized_seq, &desc);
++
++ if (err == -EINVAL) {
++ if (last_finalized_seq == 0) {
++ /*
++ * No record has been finalized or even reserved yet.
++ *
++ * The @head_id is initialized such that the first
++ * increment will yield the first record (seq=0).
++ * Handle it separately to avoid a negative @diff
++ * below.
++ */
++ if (head_id == DESC0_ID(desc_ring->count_bits))
++ return 0;
++
++ /*
++ * One or more descriptors are already reserved. Use
++ * the descriptor ID of the first one (@seq=0) for
++ * the @diff below.
++ */
++ last_finalized_id = DESC0_ID(desc_ring->count_bits) + 1;
++ } else {
++ /* Record must have been overwritten. Try again. */
++ goto try_again;
++ }
++ }
++
++ /* Diff of known descriptor IDs to compute related sequence numbers. */
++ diff = head_id - last_finalized_id;
++
++ /*
++ * @head_id points to the most recently reserved record, but this
++ * function returns the sequence number that will be assigned to the
++ * next (not yet reserved) record. Thus +1 is needed.
++ */
++ return (last_finalized_seq + diff + 1);
++}
++
+ /*
+- * Non-blocking read of a record. Updates @seq to the last finalized record
+- * (which may have no data available).
++ * Non-blocking read of a record.
++ *
++ * On success @seq is updated to the record that was read and (if provided)
++ * @r and @line_count will contain the read/calculated data.
++ *
++ * On failure @seq is updated to a record that is not yet available to the
++ * reader, but it will be the next record available to the reader.
+ *
+- * See the description of prb_read_valid() and prb_read_valid_info()
+- * for details.
++ * Note: When the current CPU is in panic, this function will skip over any
++ * non-existent/non-finalized records in order to allow the panic CPU
++ * to print any and all records that have been finalized.
+ */
+ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,
+ struct printk_record *r, unsigned int *line_count)
+@@ -1899,12 +2109,32 @@ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,
+ *seq = tail_seq;
+
+ } else if (err == -ENOENT) {
+- /* Record exists, but no data available. Skip. */
++ /* Record exists, but the data was lost. Skip. */
+ (*seq)++;
+
+ } else {
+- /* Non-existent/non-finalized record. Must stop. */
+- return false;
++ /*
++ * Non-existent/non-finalized record. Must stop.
++ *
++ * For panic situations it cannot be expected that
++ * non-finalized records will become finalized. But
++ * there may be other finalized records beyond that
++ * need to be printed for a panic situation. If this
++ * is the panic CPU, skip this
++ * non-existent/non-finalized record unless it is
++ * at or beyond the head, in which case it is not
++ * possible to continue.
++ *
++ * Note that new messages printed on panic CPU are
++ * finalized when we are here. The only exception
++ * might be the last message without trailing newline.
++ * But it would have the sequence number returned
++ * by "prb_next_reserve_seq() - 1".
++ */
++ if (this_cpu_in_panic() && ((*seq + 1) < prb_next_reserve_seq(rb)))
++ (*seq)++;
++ else
++ return false;
+ }
+ }
+
+@@ -1932,7 +2162,7 @@ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq,
+ * On success, the reader must check r->info.seq to see which record was
+ * actually read. This allows the reader to detect dropped records.
+ *
+- * Failure means @seq refers to a not yet written record.
++ * Failure means @seq refers to a record not yet available to the reader.
+ */
+ bool prb_read_valid(struct printk_ringbuffer *rb, u64 seq,
+ struct printk_record *r)
+@@ -1962,7 +2192,7 @@ bool prb_read_valid(struct printk_ringbuffer *rb, u64 seq,
+ * On success, the reader must check info->seq to see which record meta data
+ * was actually read. This allows the reader to detect dropped records.
+ *
+- * Failure means @seq refers to a not yet written record.
++ * Failure means @seq refers to a record not yet available to the reader.
+ */
+ bool prb_read_valid_info(struct printk_ringbuffer *rb, u64 seq,
+ struct printk_info *info, unsigned int *line_count)
+@@ -2008,7 +2238,9 @@ u64 prb_first_valid_seq(struct printk_ringbuffer *rb)
+ * newest sequence number available to readers will be.
+ *
+ * This provides readers a sequence number to jump to if all currently
+- * available records should be skipped.
++ * available records should be skipped. It is guaranteed that all records
++ * previous to the returned value have been finalized and are (or were)
++ * available to the reader.
+ *
+ * Context: Any context.
+ * Return: The sequence number of the next newest (not yet available) record
+@@ -2016,34 +2248,19 @@ u64 prb_first_valid_seq(struct printk_ringbuffer *rb)
+ */
+ u64 prb_next_seq(struct printk_ringbuffer *rb)
+ {
+- struct prb_desc_ring *desc_ring = &rb->desc_ring;
+- enum desc_state d_state;
+- unsigned long id;
+ u64 seq;
+
+- /* Check if the cached @id still points to a valid @seq. */
+- id = atomic_long_read(&desc_ring->last_finalized_id);
+- d_state = desc_read(desc_ring, id, NULL, &seq, NULL);
++ seq = desc_last_finalized_seq(rb);
+
+- if (d_state == desc_finalized || d_state == desc_reusable) {
+- /*
+- * Begin searching after the last finalized record.
+- *
+- * On 0, the search must begin at 0 because of hack#2
+- * of the bootstrapping phase it is not known if a
+- * record at index 0 exists.
+- */
+- if (seq != 0)
+- seq++;
+- } else {
+- /*
+- * The information about the last finalized sequence number
+- * has gone. It should happen only when there is a flood of
+- * new messages and the ringbuffer is rapidly recycled.
+- * Give up and start from the beginning.
+- */
+- seq = 0;
+- }
++ /*
++ * Begin searching after the last finalized record.
++ *
++ * On 0, the search must begin at 0 because of hack#2
++ * of the bootstrapping phase it is not known if a
++ * record at index 0 exists.
++ */
++ if (seq != 0)
++ seq++;
+
+ /*
+ * The information about the last finalized @seq might be inaccurate.
+@@ -2085,7 +2302,7 @@ void prb_init(struct printk_ringbuffer *rb,
+ rb->desc_ring.infos = infos;
+ atomic_long_set(&rb->desc_ring.head_id, DESC0_ID(descbits));
+ atomic_long_set(&rb->desc_ring.tail_id, DESC0_ID(descbits));
+- atomic_long_set(&rb->desc_ring.last_finalized_id, DESC0_ID(descbits));
++ atomic_long_set(&rb->desc_ring.last_finalized_seq, 0);
+
+ rb->text_data_ring.size_bits = textbits;
+ rb->text_data_ring.data = text_buf;
+diff --git a/kernel/printk/printk_ringbuffer.h b/kernel/printk/printk_ringbuffer.h
+index 18cd25e489b89..cb887489d00f0 100644
+--- a/kernel/printk/printk_ringbuffer.h
++++ b/kernel/printk/printk_ringbuffer.h
+@@ -75,7 +75,7 @@ struct prb_desc_ring {
+ struct printk_info *infos;
+ atomic_long_t head_id;
+ atomic_long_t tail_id;
+- atomic_long_t last_finalized_id;
++ atomic_long_t last_finalized_seq;
+ };
+
+ /*
+@@ -259,7 +259,7 @@ static struct printk_ringbuffer name = { \
+ .infos = &_##name##_infos[0], \
+ .head_id = ATOMIC_INIT(DESC0_ID(descbits)), \
+ .tail_id = ATOMIC_INIT(DESC0_ID(descbits)), \
+- .last_finalized_id = ATOMIC_INIT(DESC0_ID(descbits)), \
++ .last_finalized_seq = ATOMIC_INIT(0), \
+ }, \
+ .text_data_ring = { \
+ .size_bits = (avgtextbits) + (descbits), \
+@@ -378,7 +378,41 @@ bool prb_read_valid(struct printk_ringbuffer *rb, u64 seq,
+ bool prb_read_valid_info(struct printk_ringbuffer *rb, u64 seq,
+ struct printk_info *info, unsigned int *line_count);
+
++u64 prb_first_seq(struct printk_ringbuffer *rb);
+ u64 prb_first_valid_seq(struct printk_ringbuffer *rb);
+ u64 prb_next_seq(struct printk_ringbuffer *rb);
++u64 prb_next_reserve_seq(struct printk_ringbuffer *rb);
++
++#ifdef CONFIG_64BIT
++
++#define __u64seq_to_ulseq(u64seq) (u64seq)
++#define __ulseq_to_u64seq(rb, ulseq) (ulseq)
++
++#else /* CONFIG_64BIT */
++
++#define __u64seq_to_ulseq(u64seq) ((u32)u64seq)
++
++static inline u64 __ulseq_to_u64seq(struct printk_ringbuffer *rb, u32 ulseq)
++{
++ u64 rb_first_seq = prb_first_seq(rb);
++ u64 seq;
++
++ /*
++ * The provided sequence is only the lower 32 bits of the ringbuffer
++ * sequence. It needs to be expanded to 64bit. Get the first sequence
++ * number from the ringbuffer and fold it.
++ *
++ * Having a 32bit representation in the console is sufficient.
++ * If a console ever gets more than 2^31 records behind
++ * the ringbuffer then this is the least of the problems.
++ *
++ * Also the access to the ring buffer is always safe.
++ */
++ seq = rb_first_seq - (s32)((u32)rb_first_seq - ulseq);
++
++ return seq;
++}
++
++#endif /* CONFIG_64BIT */
+
+ #endif /* _KERNEL_PRINTK_RINGBUFFER_H */
+diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
+index b2bccfd37c383..f2c10d351b597 100644
+--- a/kernel/rcu/tree.c
++++ b/kernel/rcu/tree.c
+@@ -4743,13 +4743,16 @@ static void __init rcu_start_exp_gp_kworkers(void)
+ rcu_exp_gp_kworker = kthread_create_worker(0, gp_kworker_name);
+ if (IS_ERR_OR_NULL(rcu_exp_gp_kworker)) {
+ pr_err("Failed to create %s!\n", gp_kworker_name);
++ rcu_exp_gp_kworker = NULL;
+ return;
+ }
+
+ rcu_exp_par_gp_kworker = kthread_create_worker(0, par_gp_kworker_name);
+ if (IS_ERR_OR_NULL(rcu_exp_par_gp_kworker)) {
+ pr_err("Failed to create %s!\n", par_gp_kworker_name);
++ rcu_exp_par_gp_kworker = NULL;
+ kthread_destroy_worker(rcu_exp_gp_kworker);
++ rcu_exp_gp_kworker = NULL;
+ return;
+ }
+
+diff --git a/kernel/rcu/tree_exp.h b/kernel/rcu/tree_exp.h
+index 2ac440bc7e10b..8107f818455da 100644
+--- a/kernel/rcu/tree_exp.h
++++ b/kernel/rcu/tree_exp.h
+@@ -428,7 +428,12 @@ static void sync_rcu_exp_select_node_cpus(struct kthread_work *wp)
+ __sync_rcu_exp_select_node_cpus(rewp);
+ }
+
+-static inline bool rcu_gp_par_worker_started(void)
++static inline bool rcu_exp_worker_started(void)
++{
++ return !!READ_ONCE(rcu_exp_gp_kworker);
++}
++
++static inline bool rcu_exp_par_worker_started(void)
+ {
+ return !!READ_ONCE(rcu_exp_par_gp_kworker);
+ }
+@@ -478,7 +483,12 @@ static void sync_rcu_exp_select_node_cpus(struct work_struct *wp)
+ __sync_rcu_exp_select_node_cpus(rewp);
+ }
+
+-static inline bool rcu_gp_par_worker_started(void)
++static inline bool rcu_exp_worker_started(void)
++{
++ return !!READ_ONCE(rcu_gp_wq);
++}
++
++static inline bool rcu_exp_par_worker_started(void)
+ {
+ return !!READ_ONCE(rcu_par_gp_wq);
+ }
+@@ -541,7 +551,7 @@ static void sync_rcu_exp_select_cpus(void)
+ rnp->exp_need_flush = false;
+ if (!READ_ONCE(rnp->expmask))
+ continue; /* Avoid early boot non-existent wq. */
+- if (!rcu_gp_par_worker_started() ||
++ if (!rcu_exp_par_worker_started() ||
+ rcu_scheduler_active != RCU_SCHEDULER_RUNNING ||
+ rcu_is_last_leaf_node(rnp)) {
+ /* No worker started yet or last leaf, do direct call. */
+@@ -956,7 +966,7 @@ static void rcu_exp_print_detail_task_stall_rnp(struct rcu_node *rnp)
+ */
+ void synchronize_rcu_expedited(void)
+ {
+- bool boottime = (rcu_scheduler_active == RCU_SCHEDULER_INIT);
++ bool use_worker;
+ unsigned long flags;
+ struct rcu_exp_work rew;
+ struct rcu_node *rnp;
+@@ -967,6 +977,9 @@ void synchronize_rcu_expedited(void)
+ lock_is_held(&rcu_sched_lock_map),
+ "Illegal synchronize_rcu_expedited() in RCU read-side critical section");
+
++ use_worker = (rcu_scheduler_active != RCU_SCHEDULER_INIT) &&
++ rcu_exp_worker_started();
++
+ /* Is the state is such that the call is a grace period? */
+ if (rcu_blocking_is_gp()) {
+ // Note well that this code runs with !PREEMPT && !SMP.
+@@ -996,7 +1009,7 @@ void synchronize_rcu_expedited(void)
+ return; /* Someone else did our work for us. */
+
+ /* Ensure that load happens before action based on it. */
+- if (unlikely(boottime)) {
++ if (unlikely(!use_worker)) {
+ /* Direct call during scheduler init and early_initcalls(). */
+ rcu_exp_sel_wait_wake(s);
+ } else {
+@@ -1014,7 +1027,7 @@ void synchronize_rcu_expedited(void)
+ /* Let the next expedited grace period start. */
+ mutex_unlock(&rcu_state.exp_mutex);
+
+- if (likely(!boottime))
++ if (likely(use_worker))
+ synchronize_rcu_expedited_destroy_work(&rew);
+ }
+ EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 533547e3c90a7..e2b4e0396af84 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -7289,7 +7289,7 @@ static int select_idle_core(struct task_struct *p, int core, struct cpumask *cpu
+ if (!available_idle_cpu(cpu)) {
+ idle = false;
+ if (*idle_cpu == -1) {
+- if (sched_idle_cpu(cpu) && cpumask_test_cpu(cpu, p->cpus_ptr)) {
++ if (sched_idle_cpu(cpu) && cpumask_test_cpu(cpu, cpus)) {
+ *idle_cpu = cpu;
+ break;
+ }
+@@ -7297,7 +7297,7 @@ static int select_idle_core(struct task_struct *p, int core, struct cpumask *cpu
+ }
+ break;
+ }
+- if (*idle_cpu == -1 && cpumask_test_cpu(cpu, p->cpus_ptr))
++ if (*idle_cpu == -1 && cpumask_test_cpu(cpu, cpus))
+ *idle_cpu = cpu;
+ }
+
+@@ -7311,13 +7311,19 @@ static int select_idle_core(struct task_struct *p, int core, struct cpumask *cpu
+ /*
+ * Scan the local SMT mask for idle CPUs.
+ */
+-static int select_idle_smt(struct task_struct *p, int target)
++static int select_idle_smt(struct task_struct *p, struct sched_domain *sd, int target)
+ {
+ int cpu;
+
+ for_each_cpu_and(cpu, cpu_smt_mask(target), p->cpus_ptr) {
+ if (cpu == target)
+ continue;
++ /*
++ * Check if the CPU is in the LLC scheduling domain of @target.
++ * Due to isolcpus, there is no guarantee that all the siblings are in the domain.
++ */
++ if (!cpumask_test_cpu(cpu, sched_domain_span(sd)))
++ continue;
+ if (available_idle_cpu(cpu) || sched_idle_cpu(cpu))
+ return cpu;
+ }
+@@ -7341,7 +7347,7 @@ static inline int select_idle_core(struct task_struct *p, int core, struct cpuma
+ return __select_idle_cpu(core, p);
+ }
+
+-static inline int select_idle_smt(struct task_struct *p, int target)
++static inline int select_idle_smt(struct task_struct *p, struct sched_domain *sd, int target)
+ {
+ return -1;
+ }
+@@ -7591,7 +7597,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
+ has_idle_core = test_idle_cores(target);
+
+ if (!has_idle_core && cpus_share_cache(prev, target)) {
+- i = select_idle_smt(p, prev);
++ i = select_idle_smt(p, sd, prev);
+ if ((unsigned int)i < nr_cpumask_bits)
+ return i;
+ }
+diff --git a/kernel/time/time_test.c b/kernel/time/time_test.c
+index ca058c8af6baf..3e5d422dd15cb 100644
+--- a/kernel/time/time_test.c
++++ b/kernel/time/time_test.c
+@@ -73,7 +73,7 @@ static void time64_to_tm_test_date_range(struct kunit *test)
+
+ days = div_s64(secs, 86400);
+
+- #define FAIL_MSG "%05ld/%02d/%02d (%2d) : %ld", \
++ #define FAIL_MSG "%05ld/%02d/%02d (%2d) : %lld", \
+ year, month, mdday, yday, days
+
+ KUNIT_ASSERT_EQ_MSG(test, year - 1900, result.tm_year, FAIL_MSG);
+diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
+index 266d02809dbb1..8aab7ed414907 100644
+--- a/kernel/time/timekeeping.c
++++ b/kernel/time/timekeeping.c
+@@ -1180,13 +1180,15 @@ static int adjust_historical_crosststamp(struct system_time_snapshot *history,
+ }
+
+ /*
+- * cycle_between - true if test occurs chronologically between before and after
++ * timestamp_in_interval - true if ts is chronologically in [start, end]
++ *
++ * True if ts occurs chronologically at or after start, and before or at end.
+ */
+-static bool cycle_between(u64 before, u64 test, u64 after)
++static bool timestamp_in_interval(u64 start, u64 end, u64 ts)
+ {
+- if (test > before && test < after)
++ if (ts >= start && ts <= end)
+ return true;
+- if (test < before && before > after)
++ if (start > end && (ts >= start || ts <= end))
+ return true;
+ return false;
+ }
+@@ -1246,7 +1248,7 @@ int get_device_system_crosststamp(int (*get_time_fn)
+ */
+ now = tk_clock_read(&tk->tkr_mono);
+ interval_start = tk->tkr_mono.cycle_last;
+- if (!cycle_between(interval_start, cycles, now)) {
++ if (!timestamp_in_interval(interval_start, now, cycles)) {
+ clock_was_set_seq = tk->clock_was_set_seq;
+ cs_was_changed_seq = tk->cs_was_changed_seq;
+ cycles = interval_start;
+@@ -1259,10 +1261,8 @@ int get_device_system_crosststamp(int (*get_time_fn)
+ tk_core.timekeeper.offs_real);
+ base_raw = tk->tkr_raw.base;
+
+- nsec_real = timekeeping_cycles_to_ns(&tk->tkr_mono,
+- system_counterval.cycles);
+- nsec_raw = timekeeping_cycles_to_ns(&tk->tkr_raw,
+- system_counterval.cycles);
++ nsec_real = timekeeping_cycles_to_ns(&tk->tkr_mono, cycles);
++ nsec_raw = timekeeping_cycles_to_ns(&tk->tkr_raw, cycles);
+ } while (read_seqcount_retry(&tk_core.seq, seq));
+
+ xtstamp->sys_realtime = ktime_add_ns(base_real, nsec_real);
+@@ -1277,13 +1277,13 @@ int get_device_system_crosststamp(int (*get_time_fn)
+ bool discontinuity;
+
+ /*
+- * Check that the counter value occurs after the provided
++ * Check that the counter value is not before the provided
+ * history reference and that the history doesn't cross a
+ * clocksource change
+ */
+ if (!history_begin ||
+- !cycle_between(history_begin->cycles,
+- system_counterval.cycles, cycles) ||
++ !timestamp_in_interval(history_begin->cycles,
++ cycles, system_counterval.cycles) ||
+ history_begin->cs_was_changed_seq != cs_was_changed_seq)
+ return -EINVAL;
+ partial_history_cycles = cycles - system_counterval.cycles;
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index 7b482a26d7419..ed8ebc9776016 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -108,7 +108,7 @@ enum {
+ RESCUER_NICE_LEVEL = MIN_NICE,
+ HIGHPRI_NICE_LEVEL = MIN_NICE,
+
+- WQ_NAME_LEN = 24,
++ WQ_NAME_LEN = 32,
+ };
+
+ /*
+@@ -122,6 +122,9 @@ enum {
+ *
+ * L: pool->lock protected. Access with pool->lock held.
+ *
++ * LN: pool->lock and wq_node_nr_active->lock protected for writes. Either for
++ * reads.
++ *
+ * K: Only modified by worker while holding pool->lock. Can be safely read by
+ * self, while holding pool->lock or from IRQ context if %current is the
+ * kworker.
+@@ -143,6 +146,9 @@ enum {
+ *
+ * WR: wq->mutex protected for writes. RCU protected for reads.
+ *
++ * WO: wq->mutex protected for writes. Updated with WRITE_ONCE() and can be read
++ * with READ_ONCE() without locking.
++ *
+ * MD: wq_mayday_lock protected.
+ *
+ * WD: Used internally by the watchdog.
+@@ -240,18 +246,18 @@ struct pool_workqueue {
+ * pwq->inactive_works instead of pool->worklist and marked with
+ * WORK_STRUCT_INACTIVE.
+ *
+- * All work items marked with WORK_STRUCT_INACTIVE do not participate
+- * in pwq->nr_active and all work items in pwq->inactive_works are
+- * marked with WORK_STRUCT_INACTIVE. But not all WORK_STRUCT_INACTIVE
+- * work items are in pwq->inactive_works. Some of them are ready to
+- * run in pool->worklist or worker->scheduled. Those work itmes are
+- * only struct wq_barrier which is used for flush_work() and should
+- * not participate in pwq->nr_active. For non-barrier work item, it
+- * is marked with WORK_STRUCT_INACTIVE iff it is in pwq->inactive_works.
++ * All work items marked with WORK_STRUCT_INACTIVE do not participate in
++ * nr_active and all work items in pwq->inactive_works are marked with
++ * WORK_STRUCT_INACTIVE. But not all WORK_STRUCT_INACTIVE work items are
++ * in pwq->inactive_works. Some of them are ready to run in
++ * pool->worklist or worker->scheduled. Those work itmes are only struct
++ * wq_barrier which is used for flush_work() and should not participate
++ * in nr_active. For non-barrier work item, it is marked with
++ * WORK_STRUCT_INACTIVE iff it is in pwq->inactive_works.
+ */
+ int nr_active; /* L: nr of active works */
+- int max_active; /* L: max active works */
+ struct list_head inactive_works; /* L: inactive works */
++ struct list_head pending_node; /* LN: node on wq_node_nr_active->pending_pwqs */
+ struct list_head pwqs_node; /* WR: node on wq->pwqs */
+ struct list_head mayday_node; /* MD: node on wq->maydays */
+
+@@ -278,6 +284,26 @@ struct wq_flusher {
+
+ struct wq_device;
+
++/*
++ * Unlike in a per-cpu workqueue where max_active limits its concurrency level
++ * on each CPU, in an unbound workqueue, max_active applies to the whole system.
++ * As sharing a single nr_active across multiple sockets can be very expensive,
++ * the counting and enforcement is per NUMA node.
++ *
++ * The following struct is used to enforce per-node max_active. When a pwq wants
++ * to start executing a work item, it should increment ->nr using
++ * tryinc_node_nr_active(). If acquisition fails due to ->nr already being over
++ * ->max, the pwq is queued on ->pending_pwqs. As in-flight work items finish
++ * and decrement ->nr, node_activate_pending_pwq() activates the pending pwqs in
++ * round-robin order.
++ */
++struct wq_node_nr_active {
++ int max; /* per-node max_active */
++ atomic_t nr; /* per-node nr_active */
++ raw_spinlock_t lock; /* nests inside pool locks */
++ struct list_head pending_pwqs; /* LN: pwqs with inactive works */
++};
++
+ /*
+ * The externally visible workqueue. It relays the issued work items to
+ * the appropriate worker_pool through its pool_workqueues.
+@@ -298,10 +324,15 @@ struct workqueue_struct {
+ struct worker *rescuer; /* MD: rescue worker */
+
+ int nr_drainers; /* WQ: drain in progress */
+- int saved_max_active; /* WQ: saved pwq max_active */
++
++ /* See alloc_workqueue() function comment for info on min/max_active */
++ int max_active; /* WO: max active works */
++ int min_active; /* WO: min active works */
++ int saved_max_active; /* WQ: saved max_active */
++ int saved_min_active; /* WQ: saved min_active */
+
+ struct workqueue_attrs *unbound_attrs; /* PW: only for unbound wqs */
+- struct pool_workqueue *dfl_pwq; /* PW: only for unbound wqs */
++ struct pool_workqueue __rcu *dfl_pwq; /* PW: only for unbound wqs */
+
+ #ifdef CONFIG_SYSFS
+ struct wq_device *wq_dev; /* I: for sysfs interface */
+@@ -323,6 +354,7 @@ struct workqueue_struct {
+ /* hot fields used during command issue, aligned to cacheline */
+ unsigned int flags ____cacheline_aligned; /* WQ: WQ_* flags */
+ struct pool_workqueue __percpu __rcu **cpu_pwq; /* I: per-cpu pwqs */
++ struct wq_node_nr_active *node_nr_active[]; /* I: per-node nr_active */
+ };
+
+ static struct kmem_cache *pwq_cache;
+@@ -632,6 +664,36 @@ static int worker_pool_assign_id(struct worker_pool *pool)
+ return ret;
+ }
+
++static struct pool_workqueue __rcu **
++unbound_pwq_slot(struct workqueue_struct *wq, int cpu)
++{
++ if (cpu >= 0)
++ return per_cpu_ptr(wq->cpu_pwq, cpu);
++ else
++ return &wq->dfl_pwq;
++}
++
++/* @cpu < 0 for dfl_pwq */
++static struct pool_workqueue *unbound_pwq(struct workqueue_struct *wq, int cpu)
++{
++ return rcu_dereference_check(*unbound_pwq_slot(wq, cpu),
++ lockdep_is_held(&wq_pool_mutex) ||
++ lockdep_is_held(&wq->mutex));
++}
++
++/**
++ * unbound_effective_cpumask - effective cpumask of an unbound workqueue
++ * @wq: workqueue of interest
++ *
++ * @wq->unbound_attrs->cpumask contains the cpumask requested by the user which
++ * is masked with wq_unbound_cpumask to determine the effective cpumask. The
++ * default pwq is always mapped to the pool with the current effective cpumask.
++ */
++static struct cpumask *unbound_effective_cpumask(struct workqueue_struct *wq)
++{
++ return unbound_pwq(wq, -1)->pool->attrs->__pod_cpumask;
++}
++
+ static unsigned int work_color_to_flags(int color)
+ {
+ return color << WORK_STRUCT_COLOR_SHIFT;
+@@ -1401,6 +1463,71 @@ work_func_t wq_worker_last_func(struct task_struct *task)
+ return worker->last_func;
+ }
+
++/**
++ * wq_node_nr_active - Determine wq_node_nr_active to use
++ * @wq: workqueue of interest
++ * @node: NUMA node, can be %NUMA_NO_NODE
++ *
++ * Determine wq_node_nr_active to use for @wq on @node. Returns:
++ *
++ * - %NULL for per-cpu workqueues as they don't need to use shared nr_active.
++ *
++ * - node_nr_active[nr_node_ids] if @node is %NUMA_NO_NODE.
++ *
++ * - Otherwise, node_nr_active[@node].
++ */
++static struct wq_node_nr_active *wq_node_nr_active(struct workqueue_struct *wq,
++ int node)
++{
++ if (!(wq->flags & WQ_UNBOUND))
++ return NULL;
++
++ if (node == NUMA_NO_NODE)
++ node = nr_node_ids;
++
++ return wq->node_nr_active[node];
++}
++
++/**
++ * wq_update_node_max_active - Update per-node max_actives to use
++ * @wq: workqueue to update
++ * @off_cpu: CPU that's going down, -1 if a CPU is not going down
++ *
++ * Update @wq->node_nr_active[]->max. @wq must be unbound. max_active is
++ * distributed among nodes according to the proportions of numbers of online
++ * cpus. The result is always between @wq->min_active and max_active.
++ */
++static void wq_update_node_max_active(struct workqueue_struct *wq, int off_cpu)
++{
++ struct cpumask *effective = unbound_effective_cpumask(wq);
++ int min_active = READ_ONCE(wq->min_active);
++ int max_active = READ_ONCE(wq->max_active);
++ int total_cpus, node;
++
++ lockdep_assert_held(&wq->mutex);
++
++ if (off_cpu >= 0 && !cpumask_test_cpu(off_cpu, effective))
++ off_cpu = -1;
++
++ total_cpus = cpumask_weight_and(effective, cpu_online_mask);
++ if (off_cpu >= 0)
++ total_cpus--;
++
++ for_each_node(node) {
++ int node_cpus;
++
++ node_cpus = cpumask_weight_and(effective, cpumask_of_node(node));
++ if (off_cpu >= 0 && cpu_to_node(off_cpu) == node)
++ node_cpus--;
++
++ wq_node_nr_active(wq, node)->max =
++ clamp(DIV_ROUND_UP(max_active * node_cpus, total_cpus),
++ min_active, max_active);
++ }
++
++ wq_node_nr_active(wq, NUMA_NO_NODE)->max = min_active;
++}
++
+ /**
+ * get_pwq - get an extra reference on the specified pool_workqueue
+ * @pwq: pool_workqueue to get
+@@ -1453,24 +1580,293 @@ static void put_pwq_unlocked(struct pool_workqueue *pwq)
+ }
+ }
+
+-static void pwq_activate_inactive_work(struct work_struct *work)
++static bool pwq_is_empty(struct pool_workqueue *pwq)
+ {
+- struct pool_workqueue *pwq = get_work_pwq(work);
++ return !pwq->nr_active && list_empty(&pwq->inactive_works);
++}
+
++static void __pwq_activate_work(struct pool_workqueue *pwq,
++ struct work_struct *work)
++{
++ unsigned long *wdb = work_data_bits(work);
++
++ WARN_ON_ONCE(!(*wdb & WORK_STRUCT_INACTIVE));
+ trace_workqueue_activate_work(work);
+ if (list_empty(&pwq->pool->worklist))
+ pwq->pool->watchdog_ts = jiffies;
+ move_linked_works(work, &pwq->pool->worklist, NULL);
+- __clear_bit(WORK_STRUCT_INACTIVE_BIT, work_data_bits(work));
++ __clear_bit(WORK_STRUCT_INACTIVE_BIT, wdb);
++}
++
++/**
++ * pwq_activate_work - Activate a work item if inactive
++ * @pwq: pool_workqueue @work belongs to
++ * @work: work item to activate
++ *
++ * Returns %true if activated. %false if already active.
++ */
++static bool pwq_activate_work(struct pool_workqueue *pwq,
++ struct work_struct *work)
++{
++ struct worker_pool *pool = pwq->pool;
++ struct wq_node_nr_active *nna;
++
++ lockdep_assert_held(&pool->lock);
++
++ if (!(*work_data_bits(work) & WORK_STRUCT_INACTIVE))
++ return false;
++
++ nna = wq_node_nr_active(pwq->wq, pool->node);
++ if (nna)
++ atomic_inc(&nna->nr);
++
+ pwq->nr_active++;
++ __pwq_activate_work(pwq, work);
++ return true;
++}
++
++static bool tryinc_node_nr_active(struct wq_node_nr_active *nna)
++{
++ int max = READ_ONCE(nna->max);
++
++ while (true) {
++ int old, tmp;
++
++ old = atomic_read(&nna->nr);
++ if (old >= max)
++ return false;
++ tmp = atomic_cmpxchg_relaxed(&nna->nr, old, old + 1);
++ if (tmp == old)
++ return true;
++ }
++}
++
++/**
++ * pwq_tryinc_nr_active - Try to increment nr_active for a pwq
++ * @pwq: pool_workqueue of interest
++ * @fill: max_active may have increased, try to increase concurrency level
++ *
++ * Try to increment nr_active for @pwq. Returns %true if an nr_active count is
++ * successfully obtained. %false otherwise.
++ */
++static bool pwq_tryinc_nr_active(struct pool_workqueue *pwq, bool fill)
++{
++ struct workqueue_struct *wq = pwq->wq;
++ struct worker_pool *pool = pwq->pool;
++ struct wq_node_nr_active *nna = wq_node_nr_active(wq, pool->node);
++ bool obtained = false;
++
++ lockdep_assert_held(&pool->lock);
++
++ if (!nna) {
++ /* per-cpu workqueue, pwq->nr_active is sufficient */
++ obtained = pwq->nr_active < READ_ONCE(wq->max_active);
++ goto out;
++ }
++
++ /*
++ * Unbound workqueue uses per-node shared nr_active $nna. If @pwq is
++ * already waiting on $nna, pwq_dec_nr_active() will maintain the
++ * concurrency level. Don't jump the line.
++ *
++ * We need to ignore the pending test after max_active has increased as
++ * pwq_dec_nr_active() can only maintain the concurrency level but not
++ * increase it. This is indicated by @fill.
++ */
++ if (!list_empty(&pwq->pending_node) && likely(!fill))
++ goto out;
++
++ obtained = tryinc_node_nr_active(nna);
++ if (obtained)
++ goto out;
++
++ /*
++ * Lockless acquisition failed. Lock, add ourself to $nna->pending_pwqs
++ * and try again. The smp_mb() is paired with the implied memory barrier
++ * of atomic_dec_return() in pwq_dec_nr_active() to ensure that either
++ * we see the decremented $nna->nr or they see non-empty
++ * $nna->pending_pwqs.
++ */
++ raw_spin_lock(&nna->lock);
++
++ if (list_empty(&pwq->pending_node))
++ list_add_tail(&pwq->pending_node, &nna->pending_pwqs);
++ else if (likely(!fill))
++ goto out_unlock;
++
++ smp_mb();
++
++ obtained = tryinc_node_nr_active(nna);
++
++ /*
++ * If @fill, @pwq might have already been pending. Being spuriously
++ * pending in cold paths doesn't affect anything. Let's leave it be.
++ */
++ if (obtained && likely(!fill))
++ list_del_init(&pwq->pending_node);
++
++out_unlock:
++ raw_spin_unlock(&nna->lock);
++out:
++ if (obtained)
++ pwq->nr_active++;
++ return obtained;
++}
++
++/**
++ * pwq_activate_first_inactive - Activate the first inactive work item on a pwq
++ * @pwq: pool_workqueue of interest
++ * @fill: max_active may have increased, try to increase concurrency level
++ *
++ * Activate the first inactive work item of @pwq if available and allowed by
++ * max_active limit.
++ *
++ * Returns %true if an inactive work item has been activated. %false if no
++ * inactive work item is found or max_active limit is reached.
++ */
++static bool pwq_activate_first_inactive(struct pool_workqueue *pwq, bool fill)
++{
++ struct work_struct *work =
++ list_first_entry_or_null(&pwq->inactive_works,
++ struct work_struct, entry);
++
++ if (work && pwq_tryinc_nr_active(pwq, fill)) {
++ __pwq_activate_work(pwq, work);
++ return true;
++ } else {
++ return false;
++ }
++}
++
++/**
++ * node_activate_pending_pwq - Activate a pending pwq on a wq_node_nr_active
++ * @nna: wq_node_nr_active to activate a pending pwq for
++ * @caller_pool: worker_pool the caller is locking
++ *
++ * Activate a pwq in @nna->pending_pwqs. Called with @caller_pool locked.
++ * @caller_pool may be unlocked and relocked to lock other worker_pools.
++ */
++static void node_activate_pending_pwq(struct wq_node_nr_active *nna,
++ struct worker_pool *caller_pool)
++{
++ struct worker_pool *locked_pool = caller_pool;
++ struct pool_workqueue *pwq;
++ struct work_struct *work;
++
++ lockdep_assert_held(&caller_pool->lock);
++
++ raw_spin_lock(&nna->lock);
++retry:
++ pwq = list_first_entry_or_null(&nna->pending_pwqs,
++ struct pool_workqueue, pending_node);
++ if (!pwq)
++ goto out_unlock;
++
++ /*
++ * If @pwq is for a different pool than @locked_pool, we need to lock
++ * @pwq->pool->lock. Let's trylock first. If unsuccessful, do the unlock
++ * / lock dance. For that, we also need to release @nna->lock as it's
++ * nested inside pool locks.
++ */
++ if (pwq->pool != locked_pool) {
++ raw_spin_unlock(&locked_pool->lock);
++ locked_pool = pwq->pool;
++ if (!raw_spin_trylock(&locked_pool->lock)) {
++ raw_spin_unlock(&nna->lock);
++ raw_spin_lock(&locked_pool->lock);
++ raw_spin_lock(&nna->lock);
++ goto retry;
++ }
++ }
++
++ /*
++ * $pwq may not have any inactive work items due to e.g. cancellations.
++ * Drop it from pending_pwqs and see if there's another one.
++ */
++ work = list_first_entry_or_null(&pwq->inactive_works,
++ struct work_struct, entry);
++ if (!work) {
++ list_del_init(&pwq->pending_node);
++ goto retry;
++ }
++
++ /*
++ * Acquire an nr_active count and activate the inactive work item. If
++ * $pwq still has inactive work items, rotate it to the end of the
++ * pending_pwqs so that we round-robin through them. This means that
++ * inactive work items are not activated in queueing order which is fine
++ * given that there has never been any ordering across different pwqs.
++ */
++ if (likely(tryinc_node_nr_active(nna))) {
++ pwq->nr_active++;
++ __pwq_activate_work(pwq, work);
++
++ if (list_empty(&pwq->inactive_works))
++ list_del_init(&pwq->pending_node);
++ else
++ list_move_tail(&pwq->pending_node, &nna->pending_pwqs);
++
++ /* if activating a foreign pool, make sure it's running */
++ if (pwq->pool != caller_pool)
++ kick_pool(pwq->pool);
++ }
++
++out_unlock:
++ raw_spin_unlock(&nna->lock);
++ if (locked_pool != caller_pool) {
++ raw_spin_unlock(&locked_pool->lock);
++ raw_spin_lock(&caller_pool->lock);
++ }
+ }
+
+-static void pwq_activate_first_inactive(struct pool_workqueue *pwq)
++/**
++ * pwq_dec_nr_active - Retire an active count
++ * @pwq: pool_workqueue of interest
++ *
++ * Decrement @pwq's nr_active and try to activate the first inactive work item.
++ * For unbound workqueues, this function may temporarily drop @pwq->pool->lock.
++ */
++static void pwq_dec_nr_active(struct pool_workqueue *pwq)
+ {
+- struct work_struct *work = list_first_entry(&pwq->inactive_works,
+- struct work_struct, entry);
++ struct worker_pool *pool = pwq->pool;
++ struct wq_node_nr_active *nna = wq_node_nr_active(pwq->wq, pool->node);
+
+- pwq_activate_inactive_work(work);
++ lockdep_assert_held(&pool->lock);
++
++ /*
++ * @pwq->nr_active should be decremented for both percpu and unbound
++ * workqueues.
++ */
++ pwq->nr_active--;
++
++ /*
++ * For a percpu workqueue, it's simple. Just need to kick the first
++ * inactive work item on @pwq itself.
++ */
++ if (!nna) {
++ pwq_activate_first_inactive(pwq, false);
++ return;
++ }
++
++ /*
++ * If @pwq is for an unbound workqueue, it's more complicated because
++ * multiple pwqs and pools may be sharing the nr_active count. When a
++ * pwq needs to wait for an nr_active count, it puts itself on
++ * $nna->pending_pwqs. The following atomic_dec_return()'s implied
++ * memory barrier is paired with smp_mb() in pwq_tryinc_nr_active() to
++ * guarantee that either we see non-empty pending_pwqs or they see
++ * decremented $nna->nr.
++ *
++ * $nna->max may change as CPUs come online/offline and @pwq->wq's
++ * max_active gets updated. However, it is guaranteed to be equal to or
++ * larger than @pwq->wq->min_active which is above zero unless freezing.
++ * This maintains the forward progress guarantee.
++ */
++ if (atomic_dec_return(&nna->nr) >= READ_ONCE(nna->max))
++ return;
++
++ if (!list_empty(&nna->pending_pwqs))
++ node_activate_pending_pwq(nna, pool);
+ }
+
+ /**
+@@ -1488,14 +1884,8 @@ static void pwq_dec_nr_in_flight(struct pool_workqueue *pwq, unsigned long work_
+ {
+ int color = get_work_color(work_data);
+
+- if (!(work_data & WORK_STRUCT_INACTIVE)) {
+- pwq->nr_active--;
+- if (!list_empty(&pwq->inactive_works)) {
+- /* one down, submit an inactive one */
+- if (pwq->nr_active < pwq->max_active)
+- pwq_activate_first_inactive(pwq);
+- }
+- }
++ if (!(work_data & WORK_STRUCT_INACTIVE))
++ pwq_dec_nr_active(pwq);
+
+ pwq->nr_in_flight[color]--;
+
+@@ -1608,8 +1998,7 @@ static int try_to_grab_pending(struct work_struct *work, bool is_dwork,
+ * management later on and cause stall. Make sure the work
+ * item is activated before grabbing.
+ */
+- if (*work_data_bits(work) & WORK_STRUCT_INACTIVE)
+- pwq_activate_inactive_work(work);
++ pwq_activate_work(pwq, work);
+
+ list_del_init(&work->entry);
+ pwq_dec_nr_in_flight(pwq, *work_data_bits(work));
+@@ -1793,12 +2182,16 @@ static void __queue_work(int cpu, struct workqueue_struct *wq,
+ pwq->nr_in_flight[pwq->work_color]++;
+ work_flags = work_color_to_flags(pwq->work_color);
+
+- if (likely(pwq->nr_active < pwq->max_active)) {
++ /*
++ * Limit the number of concurrently active work items to max_active.
++ * @work must also queue behind existing inactive work items to maintain
++ * ordering when max_active changes. See wq_adjust_max_active().
++ */
++ if (list_empty(&pwq->inactive_works) && pwq_tryinc_nr_active(pwq, false)) {
+ if (list_empty(&pool->worklist))
+ pool->watchdog_ts = jiffies;
+
+ trace_workqueue_activate_work(work);
+- pwq->nr_active++;
+ insert_work(pwq, work, &pool->worklist, work_flags);
+ kick_pool(pool);
+ } else {
+@@ -3027,7 +3420,7 @@ static void insert_wq_barrier(struct pool_workqueue *pwq,
+
+ barr->task = current;
+
+- /* The barrier work item does not participate in pwq->nr_active. */
++ /* The barrier work item does not participate in nr_active. */
+ work_flags |= WORK_STRUCT_INACTIVE;
+
+ /*
+@@ -3316,7 +3709,7 @@ void drain_workqueue(struct workqueue_struct *wq)
+ bool drained;
+
+ raw_spin_lock_irq(&pwq->pool->lock);
+- drained = !pwq->nr_active && list_empty(&pwq->inactive_works);
++ drained = pwq_is_empty(pwq);
+ raw_spin_unlock_irq(&pwq->pool->lock);
+
+ if (drained)
+@@ -3927,11 +4320,65 @@ static void wq_free_lockdep(struct workqueue_struct *wq)
+ }
+ #endif
+
++static void free_node_nr_active(struct wq_node_nr_active **nna_ar)
++{
++ int node;
++
++ for_each_node(node) {
++ kfree(nna_ar[node]);
++ nna_ar[node] = NULL;
++ }
++
++ kfree(nna_ar[nr_node_ids]);
++ nna_ar[nr_node_ids] = NULL;
++}
++
++static void init_node_nr_active(struct wq_node_nr_active *nna)
++{
++ atomic_set(&nna->nr, 0);
++ raw_spin_lock_init(&nna->lock);
++ INIT_LIST_HEAD(&nna->pending_pwqs);
++}
++
++/*
++ * Each node's nr_active counter will be accessed mostly from its own node and
++ * should be allocated in the node.
++ */
++static int alloc_node_nr_active(struct wq_node_nr_active **nna_ar)
++{
++ struct wq_node_nr_active *nna;
++ int node;
++
++ for_each_node(node) {
++ nna = kzalloc_node(sizeof(*nna), GFP_KERNEL, node);
++ if (!nna)
++ goto err_free;
++ init_node_nr_active(nna);
++ nna_ar[node] = nna;
++ }
++
++ /* [nr_node_ids] is used as the fallback */
++ nna = kzalloc_node(sizeof(*nna), GFP_KERNEL, NUMA_NO_NODE);
++ if (!nna)
++ goto err_free;
++ init_node_nr_active(nna);
++ nna_ar[nr_node_ids] = nna;
++
++ return 0;
++
++err_free:
++ free_node_nr_active(nna_ar);
++ return -ENOMEM;
++}
++
+ static void rcu_free_wq(struct rcu_head *rcu)
+ {
+ struct workqueue_struct *wq =
+ container_of(rcu, struct workqueue_struct, rcu);
+
++ if (wq->flags & WQ_UNBOUND)
++ free_node_nr_active(wq->node_nr_active);
++
+ wq_free_lockdep(wq);
+ free_percpu(wq->cpu_pwq);
+ free_workqueue_attrs(wq->unbound_attrs);
+@@ -4130,6 +4577,15 @@ static void pwq_release_workfn(struct kthread_work *work)
+ mutex_unlock(&wq_pool_mutex);
+ }
+
++ if (!list_empty(&pwq->pending_node)) {
++ struct wq_node_nr_active *nna =
++ wq_node_nr_active(pwq->wq, pwq->pool->node);
++
++ raw_spin_lock_irq(&nna->lock);
++ list_del_init(&pwq->pending_node);
++ raw_spin_unlock_irq(&nna->lock);
++ }
++
+ call_rcu(&pwq->rcu, rcu_free_pwq);
+
+ /*
+@@ -4142,50 +4598,6 @@ static void pwq_release_workfn(struct kthread_work *work)
+ }
+ }
+
+-/**
+- * pwq_adjust_max_active - update a pwq's max_active to the current setting
+- * @pwq: target pool_workqueue
+- *
+- * If @pwq isn't freezing, set @pwq->max_active to the associated
+- * workqueue's saved_max_active and activate inactive work items
+- * accordingly. If @pwq is freezing, clear @pwq->max_active to zero.
+- */
+-static void pwq_adjust_max_active(struct pool_workqueue *pwq)
+-{
+- struct workqueue_struct *wq = pwq->wq;
+- bool freezable = wq->flags & WQ_FREEZABLE;
+- unsigned long flags;
+-
+- /* for @wq->saved_max_active */
+- lockdep_assert_held(&wq->mutex);
+-
+- /* fast exit for non-freezable wqs */
+- if (!freezable && pwq->max_active == wq->saved_max_active)
+- return;
+-
+- /* this function can be called during early boot w/ irq disabled */
+- raw_spin_lock_irqsave(&pwq->pool->lock, flags);
+-
+- /*
+- * During [un]freezing, the caller is responsible for ensuring that
+- * this function is called at least once after @workqueue_freezing
+- * is updated and visible.
+- */
+- if (!freezable || !workqueue_freezing) {
+- pwq->max_active = wq->saved_max_active;
+-
+- while (!list_empty(&pwq->inactive_works) &&
+- pwq->nr_active < pwq->max_active)
+- pwq_activate_first_inactive(pwq);
+-
+- kick_pool(pwq->pool);
+- } else {
+- pwq->max_active = 0;
+- }
+-
+- raw_spin_unlock_irqrestore(&pwq->pool->lock, flags);
+-}
+-
+ /* initialize newly allocated @pwq which is associated with @wq and @pool */
+ static void init_pwq(struct pool_workqueue *pwq, struct workqueue_struct *wq,
+ struct worker_pool *pool)
+@@ -4199,6 +4611,7 @@ static void init_pwq(struct pool_workqueue *pwq, struct workqueue_struct *wq,
+ pwq->flush_color = -1;
+ pwq->refcnt = 1;
+ INIT_LIST_HEAD(&pwq->inactive_works);
++ INIT_LIST_HEAD(&pwq->pending_node);
+ INIT_LIST_HEAD(&pwq->pwqs_node);
+ INIT_LIST_HEAD(&pwq->mayday_node);
+ kthread_init_work(&pwq->release_work, pwq_release_workfn);
+@@ -4218,9 +4631,6 @@ static void link_pwq(struct pool_workqueue *pwq)
+ /* set the matching work_color */
+ pwq->work_color = wq->work_color;
+
+- /* sync max_active to the current setting */
+- pwq_adjust_max_active(pwq);
+-
+ /* link in @pwq */
+ list_add_rcu(&pwq->pwqs_node, &wq->pwqs);
+ }
+@@ -4289,10 +4699,11 @@ static void wq_calc_pod_cpumask(struct workqueue_attrs *attrs, int cpu,
+ "possible intersect\n");
+ }
+
+-/* install @pwq into @wq's cpu_pwq and return the old pwq */
++/* install @pwq into @wq and return the old pwq, @cpu < 0 for dfl_pwq */
+ static struct pool_workqueue *install_unbound_pwq(struct workqueue_struct *wq,
+ int cpu, struct pool_workqueue *pwq)
+ {
++ struct pool_workqueue __rcu **slot = unbound_pwq_slot(wq, cpu);
+ struct pool_workqueue *old_pwq;
+
+ lockdep_assert_held(&wq_pool_mutex);
+@@ -4301,8 +4712,8 @@ static struct pool_workqueue *install_unbound_pwq(struct workqueue_struct *wq,
+ /* link_pwq() can handle duplicate calls */
+ link_pwq(pwq);
+
+- old_pwq = rcu_access_pointer(*per_cpu_ptr(wq->cpu_pwq, cpu));
+- rcu_assign_pointer(*per_cpu_ptr(wq->cpu_pwq, cpu), pwq);
++ old_pwq = rcu_access_pointer(*slot);
++ rcu_assign_pointer(*slot, pwq);
+ return old_pwq;
+ }
+
+@@ -4402,14 +4813,14 @@ static void apply_wqattrs_commit(struct apply_wqattrs_ctx *ctx)
+
+ copy_workqueue_attrs(ctx->wq->unbound_attrs, ctx->attrs);
+
+- /* save the previous pwq and install the new one */
++ /* save the previous pwqs and install the new ones */
+ for_each_possible_cpu(cpu)
+ ctx->pwq_tbl[cpu] = install_unbound_pwq(ctx->wq, cpu,
+ ctx->pwq_tbl[cpu]);
++ ctx->dfl_pwq = install_unbound_pwq(ctx->wq, -1, ctx->dfl_pwq);
+
+- /* @dfl_pwq might not have been used, ensure it's linked */
+- link_pwq(ctx->dfl_pwq);
+- swap(ctx->wq->dfl_pwq, ctx->dfl_pwq);
++ /* update node_nr_active->max */
++ wq_update_node_max_active(ctx->wq, -1);
+
+ mutex_unlock(&ctx->wq->mutex);
+ }
+@@ -4519,9 +4930,7 @@ static void wq_update_pod(struct workqueue_struct *wq, int cpu,
+
+ /* nothing to do if the target cpumask matches the current pwq */
+ wq_calc_pod_cpumask(target_attrs, cpu, off_cpu);
+- pwq = rcu_dereference_protected(*per_cpu_ptr(wq->cpu_pwq, cpu),
+- lockdep_is_held(&wq_pool_mutex));
+- if (wqattrs_equal(target_attrs, pwq->pool->attrs))
++ if (wqattrs_equal(target_attrs, unbound_pwq(wq, cpu)->pool->attrs))
+ return;
+
+ /* create a new pwq */
+@@ -4539,10 +4948,11 @@ static void wq_update_pod(struct workqueue_struct *wq, int cpu,
+
+ use_dfl_pwq:
+ mutex_lock(&wq->mutex);
+- raw_spin_lock_irq(&wq->dfl_pwq->pool->lock);
+- get_pwq(wq->dfl_pwq);
+- raw_spin_unlock_irq(&wq->dfl_pwq->pool->lock);
+- old_pwq = install_unbound_pwq(wq, cpu, wq->dfl_pwq);
++ pwq = unbound_pwq(wq, -1);
++ raw_spin_lock_irq(&pwq->pool->lock);
++ get_pwq(pwq);
++ raw_spin_unlock_irq(&pwq->pool->lock);
++ old_pwq = install_unbound_pwq(wq, cpu, pwq);
+ out_unlock:
+ mutex_unlock(&wq->mutex);
+ put_pwq_unlocked(old_pwq);
+@@ -4580,10 +4990,13 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
+
+ cpus_read_lock();
+ if (wq->flags & __WQ_ORDERED) {
++ struct pool_workqueue *dfl_pwq;
++
+ ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]);
+ /* there should only be single pwq for ordering guarantee */
+- WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node ||
+- wq->pwqs.prev != &wq->dfl_pwq->pwqs_node),
++ dfl_pwq = rcu_access_pointer(wq->dfl_pwq);
++ WARN(!ret && (wq->pwqs.next != &dfl_pwq->pwqs_node ||
++ wq->pwqs.prev != &dfl_pwq->pwqs_node),
+ "ordering guarantee broken for workqueue %s\n", wq->name);
+ } else {
+ ret = apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]);
+@@ -4658,6 +5071,69 @@ static int init_rescuer(struct workqueue_struct *wq)
+ return 0;
+ }
+
++/**
++ * wq_adjust_max_active - update a wq's max_active to the current setting
++ * @wq: target workqueue
++ *
++ * If @wq isn't freezing, set @wq->max_active to the saved_max_active and
++ * activate inactive work items accordingly. If @wq is freezing, clear
++ * @wq->max_active to zero.
++ */
++static void wq_adjust_max_active(struct workqueue_struct *wq)
++{
++ bool activated;
++ int new_max, new_min;
++
++ lockdep_assert_held(&wq->mutex);
++
++ if ((wq->flags & WQ_FREEZABLE) && workqueue_freezing) {
++ new_max = 0;
++ new_min = 0;
++ } else {
++ new_max = wq->saved_max_active;
++ new_min = wq->saved_min_active;
++ }
++
++ if (wq->max_active == new_max && wq->min_active == new_min)
++ return;
++
++ /*
++ * Update @wq->max/min_active and then kick inactive work items if more
++ * active work items are allowed. This doesn't break work item ordering
++ * because new work items are always queued behind existing inactive
++ * work items if there are any.
++ */
++ WRITE_ONCE(wq->max_active, new_max);
++ WRITE_ONCE(wq->min_active, new_min);
++
++ if (wq->flags & WQ_UNBOUND)
++ wq_update_node_max_active(wq, -1);
++
++ if (new_max == 0)
++ return;
++
++ /*
++ * Round-robin through pwq's activating the first inactive work item
++ * until max_active is filled.
++ */
++ do {
++ struct pool_workqueue *pwq;
++
++ activated = false;
++ for_each_pwq(pwq, wq) {
++ unsigned long flags;
++
++ /* can be called during early boot w/ irq disabled */
++ raw_spin_lock_irqsave(&pwq->pool->lock, flags);
++ if (pwq_activate_first_inactive(pwq, true)) {
++ activated = true;
++ kick_pool(pwq->pool);
++ }
++ raw_spin_unlock_irqrestore(&pwq->pool->lock, flags);
++ }
++ } while (activated);
++}
++
+ __printf(1, 4)
+ struct workqueue_struct *alloc_workqueue(const char *fmt,
+ unsigned int flags,
+@@ -4665,7 +5141,8 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
+ {
+ va_list args;
+ struct workqueue_struct *wq;
+- struct pool_workqueue *pwq;
++ size_t wq_size;
++ int name_len;
+
+ /*
+ * Unbound && max_active == 1 used to imply ordered, which is no longer
+@@ -4681,7 +5158,12 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
+ flags |= WQ_UNBOUND;
+
+ /* allocate wq and format name */
+- wq = kzalloc(sizeof(*wq), GFP_KERNEL);
++ if (flags & WQ_UNBOUND)
++ wq_size = struct_size(wq, node_nr_active, nr_node_ids + 1);
++ else
++ wq_size = sizeof(*wq);
++
++ wq = kzalloc(wq_size, GFP_KERNEL);
+ if (!wq)
+ return NULL;
+
+@@ -4692,15 +5174,22 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
+ }
+
+ va_start(args, max_active);
+- vsnprintf(wq->name, sizeof(wq->name), fmt, args);
++ name_len = vsnprintf(wq->name, sizeof(wq->name), fmt, args);
+ va_end(args);
+
++ if (name_len >= WQ_NAME_LEN)
++ pr_warn_once("workqueue: name exceeds WQ_NAME_LEN. Truncating to: %s\n",
++ wq->name);
++
+ max_active = max_active ?: WQ_DFL_ACTIVE;
+ max_active = wq_clamp_max_active(max_active, flags, wq->name);
+
+ /* init wq */
+ wq->flags = flags;
+- wq->saved_max_active = max_active;
++ wq->max_active = max_active;
++ wq->min_active = min(max_active, WQ_DFL_MIN_ACTIVE);
++ wq->saved_max_active = wq->max_active;
++ wq->saved_min_active = wq->min_active;
+ mutex_init(&wq->mutex);
+ atomic_set(&wq->nr_pwqs_to_flush, 0);
+ INIT_LIST_HEAD(&wq->pwqs);
+@@ -4711,8 +5200,13 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
+ wq_init_lockdep(wq);
+ INIT_LIST_HEAD(&wq->list);
+
++ if (flags & WQ_UNBOUND) {
++ if (alloc_node_nr_active(wq->node_nr_active) < 0)
++ goto err_unreg_lockdep;
++ }
++
+ if (alloc_and_link_pwqs(wq) < 0)
+- goto err_unreg_lockdep;
++ goto err_free_node_nr_active;
+
+ if (wq_online && init_rescuer(wq) < 0)
+ goto err_destroy;
+@@ -4728,8 +5222,7 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
+ mutex_lock(&wq_pool_mutex);
+
+ mutex_lock(&wq->mutex);
+- for_each_pwq(pwq, wq)
+- pwq_adjust_max_active(pwq);
++ wq_adjust_max_active(wq);
+ mutex_unlock(&wq->mutex);
+
+ list_add_tail_rcu(&wq->list, &workqueues);
+@@ -4738,6 +5231,9 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
+
+ return wq;
+
++err_free_node_nr_active:
++ if (wq->flags & WQ_UNBOUND)
++ free_node_nr_active(wq->node_nr_active);
+ err_unreg_lockdep:
+ wq_unregister_lockdep(wq);
+ wq_free_lockdep(wq);
+@@ -4759,9 +5255,9 @@ static bool pwq_busy(struct pool_workqueue *pwq)
+ if (pwq->nr_in_flight[i])
+ return true;
+
+- if ((pwq != pwq->wq->dfl_pwq) && (pwq->refcnt > 1))
++ if ((pwq != rcu_access_pointer(pwq->wq->dfl_pwq)) && (pwq->refcnt > 1))
+ return true;
+- if (pwq->nr_active || !list_empty(&pwq->inactive_works))
++ if (!pwq_is_empty(pwq))
+ return true;
+
+ return false;
+@@ -4843,13 +5339,12 @@ void destroy_workqueue(struct workqueue_struct *wq)
+ rcu_read_lock();
+
+ for_each_possible_cpu(cpu) {
+- pwq = rcu_access_pointer(*per_cpu_ptr(wq->cpu_pwq, cpu));
+- RCU_INIT_POINTER(*per_cpu_ptr(wq->cpu_pwq, cpu), NULL);
+- put_pwq_unlocked(pwq);
++ put_pwq_unlocked(unbound_pwq(wq, cpu));
++ RCU_INIT_POINTER(*unbound_pwq_slot(wq, cpu), NULL);
+ }
+
+- put_pwq_unlocked(wq->dfl_pwq);
+- wq->dfl_pwq = NULL;
++ put_pwq_unlocked(unbound_pwq(wq, -1));
++ RCU_INIT_POINTER(*unbound_pwq_slot(wq, -1), NULL);
+
+ rcu_read_unlock();
+ }
+@@ -4860,15 +5355,14 @@ EXPORT_SYMBOL_GPL(destroy_workqueue);
+ * @wq: target workqueue
+ * @max_active: new max_active value.
+ *
+- * Set max_active of @wq to @max_active.
++ * Set max_active of @wq to @max_active. See the alloc_workqueue() function
++ * comment.
+ *
+ * CONTEXT:
+ * Don't call from IRQ context.
+ */
+ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)
+ {
+- struct pool_workqueue *pwq;
+-
+ /* disallow meddling with max_active for ordered workqueues */
+ if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))
+ return;
+@@ -4879,9 +5373,10 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)
+
+ wq->flags &= ~__WQ_ORDERED;
+ wq->saved_max_active = max_active;
++ if (wq->flags & WQ_UNBOUND)
++ wq->saved_min_active = min(wq->saved_min_active, max_active);
+
+- for_each_pwq(pwq, wq)
+- pwq_adjust_max_active(pwq);
++ wq_adjust_max_active(wq);
+
+ mutex_unlock(&wq->mutex);
+ }
+@@ -5128,8 +5623,8 @@ static void show_pwq(struct pool_workqueue *pwq)
+ pr_info(" pwq %d:", pool->id);
+ pr_cont_pool_info(pool);
+
+- pr_cont(" active=%d/%d refcnt=%d%s\n",
+- pwq->nr_active, pwq->max_active, pwq->refcnt,
++ pr_cont(" active=%d refcnt=%d%s\n",
++ pwq->nr_active, pwq->refcnt,
+ !list_empty(&pwq->mayday_node) ? " MAYDAY" : "");
+
+ hash_for_each(pool->busy_hash, bkt, worker, hentry) {
+@@ -5203,7 +5698,7 @@ void show_one_workqueue(struct workqueue_struct *wq)
+ unsigned long flags;
+
+ for_each_pwq(pwq, wq) {
+- if (pwq->nr_active || !list_empty(&pwq->inactive_works)) {
++ if (!pwq_is_empty(pwq)) {
+ idle = false;
+ break;
+ }
+@@ -5215,7 +5710,7 @@ void show_one_workqueue(struct workqueue_struct *wq)
+
+ for_each_pwq(pwq, wq) {
+ raw_spin_lock_irqsave(&pwq->pool->lock, flags);
+- if (pwq->nr_active || !list_empty(&pwq->inactive_works)) {
++ if (!pwq_is_empty(pwq)) {
+ /*
+ * Defer printing to avoid deadlocks in console
+ * drivers that queue work while holding locks
+@@ -5562,6 +6057,10 @@ int workqueue_online_cpu(unsigned int cpu)
+
+ for_each_cpu(tcpu, pt->pod_cpus[pt->cpu_pod[cpu]])
+ wq_update_pod(wq, tcpu, cpu, true);
++
++ mutex_lock(&wq->mutex);
++ wq_update_node_max_active(wq, -1);
++ mutex_unlock(&wq->mutex);
+ }
+ }
+
+@@ -5590,6 +6089,10 @@ int workqueue_offline_cpu(unsigned int cpu)
+
+ for_each_cpu(tcpu, pt->pod_cpus[pt->cpu_pod[cpu]])
+ wq_update_pod(wq, tcpu, cpu, false);
++
++ mutex_lock(&wq->mutex);
++ wq_update_node_max_active(wq, cpu);
++ mutex_unlock(&wq->mutex);
+ }
+ }
+ mutex_unlock(&wq_pool_mutex);
+@@ -5677,7 +6180,6 @@ EXPORT_SYMBOL_GPL(work_on_cpu_safe_key);
+ void freeze_workqueues_begin(void)
+ {
+ struct workqueue_struct *wq;
+- struct pool_workqueue *pwq;
+
+ mutex_lock(&wq_pool_mutex);
+
+@@ -5686,8 +6188,7 @@ void freeze_workqueues_begin(void)
+
+ list_for_each_entry(wq, &workqueues, list) {
+ mutex_lock(&wq->mutex);
+- for_each_pwq(pwq, wq)
+- pwq_adjust_max_active(pwq);
++ wq_adjust_max_active(wq);
+ mutex_unlock(&wq->mutex);
+ }
+
+@@ -5752,7 +6253,6 @@ bool freeze_workqueues_busy(void)
+ void thaw_workqueues(void)
+ {
+ struct workqueue_struct *wq;
+- struct pool_workqueue *pwq;
+
+ mutex_lock(&wq_pool_mutex);
+
+@@ -5764,8 +6264,7 @@ void thaw_workqueues(void)
+ /* restore max_active and repopulate worklist */
+ list_for_each_entry(wq, &workqueues, list) {
+ mutex_lock(&wq->mutex);
+- for_each_pwq(pwq, wq)
+- pwq_adjust_max_active(pwq);
++ wq_adjust_max_active(wq);
+ mutex_unlock(&wq->mutex);
+ }
+
+@@ -6874,8 +7373,12 @@ void __init workqueue_init_topology(void)
+ * combinations to apply per-pod sharing.
+ */
+ list_for_each_entry(wq, &workqueues, list) {
+- for_each_online_cpu(cpu) {
++ for_each_online_cpu(cpu)
+ wq_update_pod(wq, cpu, cpu, true);
++ if (wq->flags & WQ_UNBOUND) {
++ mutex_lock(&wq->mutex);
++ wq_update_node_max_active(wq, -1);
++ mutex_unlock(&wq->mutex);
+ }
+ }
+
+diff --git a/lib/cmdline_kunit.c b/lib/cmdline_kunit.c
+index d4572dbc91453..705b82736be08 100644
+--- a/lib/cmdline_kunit.c
++++ b/lib/cmdline_kunit.c
+@@ -124,7 +124,7 @@ static void cmdline_do_one_range_test(struct kunit *test, const char *in,
+ n, e[0], r[0]);
+
+ p = memchr_inv(&r[1], 0, sizeof(r) - sizeof(r[0]));
+- KUNIT_EXPECT_PTR_EQ_MSG(test, p, NULL, "in test %u at %u out of bound", n, p - r);
++ KUNIT_EXPECT_PTR_EQ_MSG(test, p, NULL, "in test %u at %td out of bound", n, p - r);
+ }
+
+ static void cmdline_test_range(struct kunit *test)
+diff --git a/lib/kunit/device.c b/lib/kunit/device.c
+index 644a38a1f5b1c..9ea399049749e 100644
+--- a/lib/kunit/device.c
++++ b/lib/kunit/device.c
+@@ -10,6 +10,7 @@
+ */
+
+ #include <linux/device.h>
++#include <linux/dma-mapping.h>
+
+ #include <kunit/test.h>
+ #include <kunit/device.h>
+@@ -133,6 +134,9 @@ static struct kunit_device *kunit_device_register_internal(struct kunit *test,
+ return ERR_PTR(err);
+ }
+
++ kunit_dev->dev.dma_mask = &kunit_dev->dev.coherent_dma_mask;
++ kunit_dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
++
+ kunit_add_action(test, device_unregister_wrapper, &kunit_dev->dev);
+
+ return kunit_dev;
+diff --git a/lib/kunit/executor_test.c b/lib/kunit/executor_test.c
+index 22d4ee86dbedd..3f7f967e3688e 100644
+--- a/lib/kunit/executor_test.c
++++ b/lib/kunit/executor_test.c
+@@ -129,7 +129,7 @@ static void parse_filter_attr_test(struct kunit *test)
+ GFP_KERNEL);
+ for (j = 0; j < filter_count; j++) {
+ parsed_filters[j] = kunit_next_attr_filter(&filter, &err);
+- KUNIT_ASSERT_EQ_MSG(test, err, 0, "failed to parse filter '%s'", filters[j]);
++ KUNIT_ASSERT_EQ_MSG(test, err, 0, "failed to parse filter from '%s'", filters);
+ }
+
+ KUNIT_EXPECT_STREQ(test, kunit_attr_filter_name(parsed_filters[0]), "speed");
+diff --git a/lib/memcpy_kunit.c b/lib/memcpy_kunit.c
+index 440aee705ccca..30e00ef0bf2e0 100644
+--- a/lib/memcpy_kunit.c
++++ b/lib/memcpy_kunit.c
+@@ -32,7 +32,7 @@ struct some_bytes {
+ BUILD_BUG_ON(sizeof(instance.data) != 32); \
+ for (size_t i = 0; i < sizeof(instance.data); i++) { \
+ KUNIT_ASSERT_EQ_MSG(test, instance.data[i], v, \
+- "line %d: '%s' not initialized to 0x%02x @ %d (saw 0x%02x)\n", \
++ "line %d: '%s' not initialized to 0x%02x @ %zu (saw 0x%02x)\n", \
+ __LINE__, #instance, v, i, instance.data[i]); \
+ } \
+ } while (0)
+@@ -41,7 +41,7 @@ struct some_bytes {
+ BUILD_BUG_ON(sizeof(one) != sizeof(two)); \
+ for (size_t i = 0; i < sizeof(one); i++) { \
+ KUNIT_EXPECT_EQ_MSG(test, one.data[i], two.data[i], \
+- "line %d: %s.data[%d] (0x%02x) != %s.data[%d] (0x%02x)\n", \
++ "line %d: %s.data[%zu] (0x%02x) != %s.data[%zu] (0x%02x)\n", \
+ __LINE__, #one, i, one.data[i], #two, i, two.data[i]); \
+ } \
+ kunit_info(test, "ok: " TEST_OP "() " name "\n"); \
+diff --git a/lib/stackdepot.c b/lib/stackdepot.c
+index 4a7055a63d9f8..c1ec2b4b6dabf 100644
+--- a/lib/stackdepot.c
++++ b/lib/stackdepot.c
+@@ -45,15 +45,16 @@
+ #define DEPOT_POOL_INDEX_BITS (DEPOT_HANDLE_BITS - DEPOT_OFFSET_BITS - \
+ STACK_DEPOT_EXTRA_BITS)
+ #define DEPOT_POOLS_CAP 8192
++/* The pool_index is offset by 1 so the first record does not have a 0 handle. */
+ #define DEPOT_MAX_POOLS \
+- (((1LL << (DEPOT_POOL_INDEX_BITS)) < DEPOT_POOLS_CAP) ? \
+- (1LL << (DEPOT_POOL_INDEX_BITS)) : DEPOT_POOLS_CAP)
++ (((1LL << (DEPOT_POOL_INDEX_BITS)) - 1 < DEPOT_POOLS_CAP) ? \
++ (1LL << (DEPOT_POOL_INDEX_BITS)) - 1 : DEPOT_POOLS_CAP)
+
+ /* Compact structure that stores a reference to a stack. */
+ union handle_parts {
+ depot_stack_handle_t handle;
+ struct {
+- u32 pool_index : DEPOT_POOL_INDEX_BITS;
++ u32 pool_index : DEPOT_POOL_INDEX_BITS; /* pool_index is offset by 1 */
+ u32 offset : DEPOT_OFFSET_BITS;
+ u32 extra : STACK_DEPOT_EXTRA_BITS;
+ };
+@@ -372,7 +373,7 @@ static struct stack_record *depot_pop_free_pool(void **prealloc, size_t size)
+ stack = current_pool + pool_offset;
+
+ /* Pre-initialize handle once. */
+- stack->handle.pool_index = pool_index;
++ stack->handle.pool_index = pool_index + 1;
+ stack->handle.offset = pool_offset >> DEPOT_STACK_ALIGN;
+ stack->handle.extra = 0;
+ INIT_LIST_HEAD(&stack->hash_list);
+@@ -483,18 +484,19 @@ static struct stack_record *depot_fetch_stack(depot_stack_handle_t handle)
+ const int pools_num_cached = READ_ONCE(pools_num);
+ union handle_parts parts = { .handle = handle };
+ void *pool;
++ u32 pool_index = parts.pool_index - 1;
+ size_t offset = parts.offset << DEPOT_STACK_ALIGN;
+ struct stack_record *stack;
+
+ lockdep_assert_not_held(&pool_lock);
+
+- if (parts.pool_index > pools_num_cached) {
++ if (pool_index >= pools_num_cached) {
+ WARN(1, "pool index %d out of bounds (%d) for stack id %08x\n",
+- parts.pool_index, pools_num_cached, handle);
++ pool_index, pools_num_cached, handle);
+ return NULL;
+ }
+
+- pool = stack_pools[parts.pool_index];
++ pool = stack_pools[pool_index];
+ if (WARN_ON(!pool))
+ return NULL;
+
+diff --git a/lib/test_blackhole_dev.c b/lib/test_blackhole_dev.c
+index 4c40580a99a36..f247089d63c08 100644
+--- a/lib/test_blackhole_dev.c
++++ b/lib/test_blackhole_dev.c
+@@ -29,7 +29,6 @@ static int __init test_blackholedev_init(void)
+ {
+ struct ipv6hdr *ip6h;
+ struct sk_buff *skb;
+- struct ethhdr *ethh;
+ struct udphdr *uh;
+ int data_len;
+ int ret;
+@@ -61,7 +60,7 @@ static int __init test_blackholedev_init(void)
+ ip6h->saddr = in6addr_loopback;
+ ip6h->daddr = in6addr_loopback;
+ /* Ether */
+- ethh = (struct ethhdr *)skb_push(skb, sizeof(struct ethhdr));
++ skb_push(skb, sizeof(struct ethhdr));
+ skb_set_mac_header(skb, 0);
+
+ skb->protocol = htons(ETH_P_IPV6);
+diff --git a/mm/shmem.c b/mm/shmem.c
+index d7c84ff621860..791a6dc163244 100644
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -311,7 +311,7 @@ static void shmem_disable_quotas(struct super_block *sb)
+ dquot_quota_off(sb, type);
+ }
+
+-static struct dquot **shmem_get_dquots(struct inode *inode)
++static struct dquot __rcu **shmem_get_dquots(struct inode *inode)
+ {
+ return SHMEM_I(inode)->i_dquot;
+ }
+diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
+index da7cac0a1b716..6b2b65a667008 100644
+--- a/net/bluetooth/Kconfig
++++ b/net/bluetooth/Kconfig
+@@ -62,14 +62,6 @@ source "net/bluetooth/cmtp/Kconfig"
+
+ source "net/bluetooth/hidp/Kconfig"
+
+-config BT_HS
+- bool "Bluetooth High Speed (HS) features"
+- depends on BT_BREDR
+- help
+- Bluetooth High Speed includes support for off-loading
+- Bluetooth connections via 802.11 (wifi) physical layer
+- available with Bluetooth version 3.0 or later.
+-
+ config BT_LE
+ bool "Bluetooth Low Energy (LE) features"
+ depends on BT
+diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
+index 141ac1fda0bfa..628d448d78be3 100644
+--- a/net/bluetooth/Makefile
++++ b/net/bluetooth/Makefile
+@@ -21,7 +21,6 @@ bluetooth-$(CONFIG_DEV_COREDUMP) += coredump.o
+
+ bluetooth-$(CONFIG_BT_BREDR) += sco.o
+ bluetooth-$(CONFIG_BT_LE) += iso.o
+-bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o
+ bluetooth-$(CONFIG_BT_LEDS) += leds.o
+ bluetooth-$(CONFIG_BT_MSFTEXT) += msft.o
+ bluetooth-$(CONFIG_BT_AOSPEXT) += aosp.o
+diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
+deleted file mode 100644
+index e7adb8a98cf90..0000000000000
+--- a/net/bluetooth/a2mp.c
++++ /dev/null
+@@ -1,1054 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-only
+-/*
+- Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved.
+- Copyright (c) 2011,2012 Intel Corp.
+-
+-*/
+-
+-#include <net/bluetooth/bluetooth.h>
+-#include <net/bluetooth/hci_core.h>
+-#include <net/bluetooth/l2cap.h>
+-
+-#include "hci_request.h"
+-#include "a2mp.h"
+-#include "amp.h"
+-
+-#define A2MP_FEAT_EXT 0x8000
+-
+-/* Global AMP Manager list */
+-static LIST_HEAD(amp_mgr_list);
+-static DEFINE_MUTEX(amp_mgr_list_lock);
+-
+-/* A2MP build & send command helper functions */
+-static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data)
+-{
+- struct a2mp_cmd *cmd;
+- int plen;
+-
+- plen = sizeof(*cmd) + len;
+- cmd = kzalloc(plen, GFP_KERNEL);
+- if (!cmd)
+- return NULL;
+-
+- cmd->code = code;
+- cmd->ident = ident;
+- cmd->len = cpu_to_le16(len);
+-
+- memcpy(cmd->data, data, len);
+-
+- return cmd;
+-}
+-
+-static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data)
+-{
+- struct l2cap_chan *chan = mgr->a2mp_chan;
+- struct a2mp_cmd *cmd;
+- u16 total_len = len + sizeof(*cmd);
+- struct kvec iv;
+- struct msghdr msg;
+-
+- cmd = __a2mp_build(code, ident, len, data);
+- if (!cmd)
+- return;
+-
+- iv.iov_base = cmd;
+- iv.iov_len = total_len;
+-
+- memset(&msg, 0, sizeof(msg));
+-
+- iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &iv, 1, total_len);
+-
+- l2cap_chan_send(chan, &msg, total_len);
+-
+- kfree(cmd);
+-}
+-
+-static u8 __next_ident(struct amp_mgr *mgr)
+-{
+- if (++mgr->ident == 0)
+- mgr->ident = 1;
+-
+- return mgr->ident;
+-}
+-
+-static struct amp_mgr *amp_mgr_lookup_by_state(u8 state)
+-{
+- struct amp_mgr *mgr;
+-
+- mutex_lock(&_mgr_list_lock);
+- list_for_each_entry(mgr, &_mgr_list, list) {
+- if (test_and_clear_bit(state, &mgr->state)) {
+- amp_mgr_get(mgr);
+- mutex_unlock(&_mgr_list_lock);
+- return mgr;
+- }
+- }
+- mutex_unlock(&_mgr_list_lock);
+-
+- return NULL;
+-}
+-
+-/* hci_dev_list shall be locked */
+-static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl)
+-{
+- struct hci_dev *hdev;
+- int i = 1;
+-
+- cl[0].id = AMP_ID_BREDR;
+- cl[0].type = AMP_TYPE_BREDR;
+- cl[0].status = AMP_STATUS_BLUETOOTH_ONLY;
+-
+- list_for_each_entry(hdev, &hci_dev_list, list) {
+- if (hdev->dev_type == HCI_AMP) {
+- cl[i].id = hdev->id;
+- cl[i].type = hdev->amp_type;
+- if (test_bit(HCI_UP, &hdev->flags))
+- cl[i].status = hdev->amp_status;
+- else
+- cl[i].status = AMP_STATUS_POWERED_DOWN;
+- i++;
+- }
+- }
+-}
+-
+-/* Processing A2MP messages */
+-static int a2mp_command_rej(struct amp_mgr *mgr, struct sk_buff *skb,
+- struct a2mp_cmd *hdr)
+-{
+- struct a2mp_cmd_rej *rej = (void *) skb->data;
+-
+- if (le16_to_cpu(hdr->len) < sizeof(*rej))
+- return -EINVAL;
+-
+- BT_DBG("ident %u reason %d", hdr->ident, le16_to_cpu(rej->reason));
+-
+- skb_pull(skb, sizeof(*rej));
+-
+- return 0;
+-}
+-
+-static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb,
+- struct a2mp_cmd *hdr)
+-{
+- struct a2mp_discov_req *req = (void *) skb->data;
+- u16 len = le16_to_cpu(hdr->len);
+- struct a2mp_discov_rsp *rsp;
+- u16 ext_feat;
+- u8 num_ctrl;
+- struct hci_dev *hdev;
+-
+- if (len < sizeof(*req))
+- return -EINVAL;
+-
+- skb_pull(skb, sizeof(*req));
+-
+- ext_feat = le16_to_cpu(req->ext_feat);
+-
+- BT_DBG("mtu %d efm 0x%4.4x", le16_to_cpu(req->mtu), ext_feat);
+-
+- /* check that packet is not broken for now */
+- while (ext_feat & A2MP_FEAT_EXT) {
+- if (len < sizeof(ext_feat))
+- return -EINVAL;
+-
+- ext_feat = get_unaligned_le16(skb->data);
+- BT_DBG("efm 0x%4.4x", ext_feat);
+- len -= sizeof(ext_feat);
+- skb_pull(skb, sizeof(ext_feat));
+- }
+-
+- read_lock(&hci_dev_list_lock);
+-
+- /* at minimum the BR/EDR needs to be listed */
+- num_ctrl = 1;
+-
+- list_for_each_entry(hdev, &hci_dev_list, list) {
+- if (hdev->dev_type == HCI_AMP)
+- num_ctrl++;
+- }
+-
+- len = struct_size(rsp, cl, num_ctrl);
+- rsp = kmalloc(len, GFP_ATOMIC);
+- if (!rsp) {
+- read_unlock(&hci_dev_list_lock);
+- return -ENOMEM;
+- }
+-
+- rsp->mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
+- rsp->ext_feat = 0;
+-
+- __a2mp_add_cl(mgr, rsp->cl);
+-
+- read_unlock(&hci_dev_list_lock);
+-
+- a2mp_send(mgr, A2MP_DISCOVER_RSP, hdr->ident, len, rsp);
+-
+- kfree(rsp);
+- return 0;
+-}
+-
+-static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+- struct a2mp_cmd *hdr)
+-{
+- struct a2mp_discov_rsp *rsp = (void *) skb->data;
+- u16 len = le16_to_cpu(hdr->len);
+- struct a2mp_cl *cl;
+- u16 ext_feat;
+- bool found = false;
+-
+- if (len < sizeof(*rsp))
+- return -EINVAL;
+-
+- len -= sizeof(*rsp);
+- skb_pull(skb, sizeof(*rsp));
+-
+- ext_feat = le16_to_cpu(rsp->ext_feat);
+-
+- BT_DBG("mtu %d efm 0x%4.4x", le16_to_cpu(rsp->mtu), ext_feat);
+-
+- /* check that packet is not broken for now */
+- while (ext_feat & A2MP_FEAT_EXT) {
+- if (len < sizeof(ext_feat))
+- return -EINVAL;
+-
+- ext_feat = get_unaligned_le16(skb->data);
+- BT_DBG("efm 0x%4.4x", ext_feat);
+- len -= sizeof(ext_feat);
+- skb_pull(skb, sizeof(ext_feat));
+- }
+-
+- cl = (void *) skb->data;
+- while (len >= sizeof(*cl)) {
+- BT_DBG("Remote AMP id %u type %u status %u", cl->id, cl->type,
+- cl->status);
+-
+- if (cl->id != AMP_ID_BREDR && cl->type != AMP_TYPE_BREDR) {
+- struct a2mp_info_req req;
+-
+- found = true;
+-
+- memset(&req, 0, sizeof(req));
+-
+- req.id = cl->id;
+- a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr),
+- sizeof(req), &req);
+- }
+-
+- len -= sizeof(*cl);
+- cl = skb_pull(skb, sizeof(*cl));
+- }
+-
+- /* Fall back to L2CAP init sequence */
+- if (!found) {
+- struct l2cap_conn *conn = mgr->l2cap_conn;
+- struct l2cap_chan *chan;
+-
+- mutex_lock(&conn->chan_lock);
+-
+- list_for_each_entry(chan, &conn->chan_l, list) {
+-
+- BT_DBG("chan %p state %s", chan,
+- state_to_string(chan->state));
+-
+- if (chan->scid == L2CAP_CID_A2MP)
+- continue;
+-
+- l2cap_chan_lock(chan);
+-
+- if (chan->state == BT_CONNECT)
+- l2cap_send_conn_req(chan);
+-
+- l2cap_chan_unlock(chan);
+- }
+-
+- mutex_unlock(&conn->chan_lock);
+- }
+-
+- return 0;
+-}
+-
+-static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb,
+- struct a2mp_cmd *hdr)
+-{
+- struct a2mp_cl *cl = (void *) skb->data;
+-
+- while (skb->len >= sizeof(*cl)) {
+- BT_DBG("Controller id %u type %u status %u", cl->id, cl->type,
+- cl->status);
+- cl = skb_pull(skb, sizeof(*cl));
+- }
+-
+- /* TODO send A2MP_CHANGE_RSP */
+-
+- return 0;
+-}
+-
+-static void read_local_amp_info_complete(struct hci_dev *hdev, u8 status,
+- u16 opcode)
+-{
+- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+-
+- a2mp_send_getinfo_rsp(hdev);
+-}
+-
+-static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
+- struct a2mp_cmd *hdr)
+-{
+- struct a2mp_info_req *req = (void *) skb->data;
+- struct hci_dev *hdev;
+- struct hci_request hreq;
+- int err = 0;
+-
+- if (le16_to_cpu(hdr->len) < sizeof(*req))
+- return -EINVAL;
+-
+- BT_DBG("id %u", req->id);
+-
+- hdev = hci_dev_get(req->id);
+- if (!hdev || hdev->dev_type != HCI_AMP) {
+- struct a2mp_info_rsp rsp;
+-
+- memset(&rsp, 0, sizeof(rsp));
+-
+- rsp.id = req->id;
+- rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+-
+- a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp),
+- &rsp);
+-
+- goto done;
+- }
+-
+- set_bit(READ_LOC_AMP_INFO, &mgr->state);
+- hci_req_init(&hreq, hdev);
+- hci_req_add(&hreq, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL);
+- err = hci_req_run(&hreq, read_local_amp_info_complete);
+- if (err < 0)
+- a2mp_send_getinfo_rsp(hdev);
+-
+-done:
+- if (hdev)
+- hci_dev_put(hdev);
+-
+- skb_pull(skb, sizeof(*req));
+- return 0;
+-}
+-
+-static int a2mp_getinfo_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+- struct a2mp_cmd *hdr)
+-{
+- struct a2mp_info_rsp *rsp = (struct a2mp_info_rsp *) skb->data;
+- struct a2mp_amp_assoc_req req;
+- struct amp_ctrl *ctrl;
+-
+- if (le16_to_cpu(hdr->len) < sizeof(*rsp))
+- return -EINVAL;
+-
+- BT_DBG("id %u status 0x%2.2x", rsp->id, rsp->status);
+-
+- if (rsp->status)
+- return -EINVAL;
+-
+- ctrl = amp_ctrl_add(mgr, rsp->id);
+- if (!ctrl)
+- return -ENOMEM;
+-
+- memset(&req, 0, sizeof(req));
+-
+- req.id = rsp->id;
+- a2mp_send(mgr, A2MP_GETAMPASSOC_REQ, __next_ident(mgr), sizeof(req),
+- &req);
+-
+- skb_pull(skb, sizeof(*rsp));
+- return 0;
+-}
+-
+-static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb,
+- struct a2mp_cmd *hdr)
+-{
+- struct a2mp_amp_assoc_req *req = (void *) skb->data;
+- struct hci_dev *hdev;
+- struct amp_mgr *tmp;
+-
+- if (le16_to_cpu(hdr->len) < sizeof(*req))
+- return -EINVAL;
+-
+- BT_DBG("id %u", req->id);
+-
+- /* Make sure that other request is not processed */
+- tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
+-
+- hdev = hci_dev_get(req->id);
+- if (!hdev || hdev->amp_type == AMP_TYPE_BREDR || tmp) {
+- struct a2mp_amp_assoc_rsp rsp;
+-
+- memset(&rsp, 0, sizeof(rsp));
+- rsp.id = req->id;
+-
+- if (tmp) {
+- rsp.status = A2MP_STATUS_COLLISION_OCCURED;
+- amp_mgr_put(tmp);
+- } else {
+- rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+- }
+-
+- a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp),
+- &rsp);
+-
+- goto done;
+- }
+-
+- amp_read_loc_assoc(hdev, mgr);
+-
+-done:
+- if (hdev)
+- hci_dev_put(hdev);
+-
+- skb_pull(skb, sizeof(*req));
+- return 0;
+-}
+-
+-static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+- struct a2mp_cmd *hdr)
+-{
+- struct a2mp_amp_assoc_rsp *rsp = (void *) skb->data;
+- u16 len = le16_to_cpu(hdr->len);
+- struct hci_dev *hdev;
+- struct amp_ctrl *ctrl;
+- struct hci_conn *hcon;
+- size_t assoc_len;
+-
+- if (len < sizeof(*rsp))
+- return -EINVAL;
+-
+- assoc_len = len - sizeof(*rsp);
+-
+- BT_DBG("id %u status 0x%2.2x assoc len %zu", rsp->id, rsp->status,
+- assoc_len);
+-
+- if (rsp->status)
+- return -EINVAL;
+-
+- /* Save remote ASSOC data */
+- ctrl = amp_ctrl_lookup(mgr, rsp->id);
+- if (ctrl) {
+- u8 *assoc;
+-
+- assoc = kmemdup(rsp->amp_assoc, assoc_len, GFP_KERNEL);
+- if (!assoc) {
+- amp_ctrl_put(ctrl);
+- return -ENOMEM;
+- }
+-
+- ctrl->assoc = assoc;
+- ctrl->assoc_len = assoc_len;
+- ctrl->assoc_rem_len = assoc_len;
+- ctrl->assoc_len_so_far = 0;
+-
+- amp_ctrl_put(ctrl);
+- }
+-
+- /* Create Phys Link */
+- hdev = hci_dev_get(rsp->id);
+- if (!hdev)
+- return -EINVAL;
+-
+- hcon = phylink_add(hdev, mgr, rsp->id, true);
+- if (!hcon)
+- goto done;
+-
+- BT_DBG("Created hcon %p: loc:%u -> rem:%u", hcon, hdev->id, rsp->id);
+-
+- mgr->bredr_chan->remote_amp_id = rsp->id;
+-
+- amp_create_phylink(hdev, mgr, hcon);
+-
+-done:
+- hci_dev_put(hdev);
+- skb_pull(skb, len);
+- return 0;
+-}
+-
+-static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
+- struct a2mp_cmd *hdr)
+-{
+- struct a2mp_physlink_req *req = (void *) skb->data;
+- struct a2mp_physlink_rsp rsp;
+- struct hci_dev *hdev;
+- struct hci_conn *hcon;
+- struct amp_ctrl *ctrl;
+-
+- if (le16_to_cpu(hdr->len) < sizeof(*req))
+- return -EINVAL;
+-
+- BT_DBG("local_id %u, remote_id %u", req->local_id, req->remote_id);
+-
+- memset(&rsp, 0, sizeof(rsp));
+-
+- rsp.local_id = req->remote_id;
+- rsp.remote_id = req->local_id;
+-
+- hdev = hci_dev_get(req->remote_id);
+- if (!hdev || hdev->amp_type == AMP_TYPE_BREDR) {
+- rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+- goto send_rsp;
+- }
+-
+- ctrl = amp_ctrl_lookup(mgr, rsp.remote_id);
+- if (!ctrl) {
+- ctrl = amp_ctrl_add(mgr, rsp.remote_id);
+- if (ctrl) {
+- amp_ctrl_get(ctrl);
+- } else {
+- rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
+- goto send_rsp;
+- }
+- }
+-
+- if (ctrl) {
+- size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req);
+- u8 *assoc;
+-
+- assoc = kmemdup(req->amp_assoc, assoc_len, GFP_KERNEL);
+- if (!assoc) {
+- amp_ctrl_put(ctrl);
+- hci_dev_put(hdev);
+- return -ENOMEM;
+- }
+-
+- ctrl->assoc = assoc;
+- ctrl->assoc_len = assoc_len;
+- ctrl->assoc_rem_len = assoc_len;
+- ctrl->assoc_len_so_far = 0;
+-
+- amp_ctrl_put(ctrl);
+- }
+-
+- hcon = phylink_add(hdev, mgr, req->local_id, false);
+- if (hcon) {
+- amp_accept_phylink(hdev, mgr, hcon);
+- rsp.status = A2MP_STATUS_SUCCESS;
+- } else {
+- rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
+- }
+-
+-send_rsp:
+- if (hdev)
+- hci_dev_put(hdev);
+-
+- /* Reply error now and success after HCI Write Remote AMP Assoc
+- command complete with success status
+- */
+- if (rsp.status != A2MP_STATUS_SUCCESS) {
+- a2mp_send(mgr, A2MP_CREATEPHYSLINK_RSP, hdr->ident,
+- sizeof(rsp), &rsp);
+- } else {
+- set_bit(WRITE_REMOTE_AMP_ASSOC, &mgr->state);
+- mgr->ident = hdr->ident;
+- }
+-
+- skb_pull(skb, le16_to_cpu(hdr->len));
+- return 0;
+-}
+-
+-static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
+- struct a2mp_cmd *hdr)
+-{
+- struct a2mp_physlink_req *req = (void *) skb->data;
+- struct a2mp_physlink_rsp rsp;
+- struct hci_dev *hdev;
+- struct hci_conn *hcon;
+-
+- if (le16_to_cpu(hdr->len) < sizeof(*req))
+- return -EINVAL;
+-
+- BT_DBG("local_id %u remote_id %u", req->local_id, req->remote_id);
+-
+- memset(&rsp, 0, sizeof(rsp));
+-
+- rsp.local_id = req->remote_id;
+- rsp.remote_id = req->local_id;
+- rsp.status = A2MP_STATUS_SUCCESS;
+-
+- hdev = hci_dev_get(req->remote_id);
+- if (!hdev) {
+- rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+- goto send_rsp;
+- }
+-
+- hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
+- &mgr->l2cap_conn->hcon->dst);
+- if (!hcon) {
+- bt_dev_err(hdev, "no phys link exist");
+- rsp.status = A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS;
+- goto clean;
+- }
+-
+- /* TODO Disconnect Phys Link here */
+-
+-clean:
+- hci_dev_put(hdev);
+-
+-send_rsp:
+- a2mp_send(mgr, A2MP_DISCONNPHYSLINK_RSP, hdr->ident, sizeof(rsp), &rsp);
+-
+- skb_pull(skb, sizeof(*req));
+- return 0;
+-}
+-
+-static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
+- struct a2mp_cmd *hdr)
+-{
+- BT_DBG("ident %u code 0x%2.2x", hdr->ident, hdr->code);
+-
+- skb_pull(skb, le16_to_cpu(hdr->len));
+- return 0;
+-}
+-
+-/* Handle A2MP signalling */
+-static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
+-{
+- struct a2mp_cmd *hdr;
+- struct amp_mgr *mgr = chan->data;
+- int err = 0;
+-
+- amp_mgr_get(mgr);
+-
+- while (skb->len >= sizeof(*hdr)) {
+- u16 len;
+-
+- hdr = (void *) skb->data;
+- len = le16_to_cpu(hdr->len);
+-
+- BT_DBG("code 0x%2.2x id %u len %u", hdr->code, hdr->ident, len);
+-
+- skb_pull(skb, sizeof(*hdr));
+-
+- if (len > skb->len || !hdr->ident) {
+- err = -EINVAL;
+- break;
+- }
+-
+- mgr->ident = hdr->ident;
+-
+- switch (hdr->code) {
+- case A2MP_COMMAND_REJ:
+- a2mp_command_rej(mgr, skb, hdr);
+- break;
+-
+- case A2MP_DISCOVER_REQ:
+- err = a2mp_discover_req(mgr, skb, hdr);
+- break;
+-
+- case A2MP_CHANGE_NOTIFY:
+- err = a2mp_change_notify(mgr, skb, hdr);
+- break;
+-
+- case A2MP_GETINFO_REQ:
+- err = a2mp_getinfo_req(mgr, skb, hdr);
+- break;
+-
+- case A2MP_GETAMPASSOC_REQ:
+- err = a2mp_getampassoc_req(mgr, skb, hdr);
+- break;
+-
+- case A2MP_CREATEPHYSLINK_REQ:
+- err = a2mp_createphyslink_req(mgr, skb, hdr);
+- break;
+-
+- case A2MP_DISCONNPHYSLINK_REQ:
+- err = a2mp_discphyslink_req(mgr, skb, hdr);
+- break;
+-
+- case A2MP_DISCOVER_RSP:
+- err = a2mp_discover_rsp(mgr, skb, hdr);
+- break;
+-
+- case A2MP_GETINFO_RSP:
+- err = a2mp_getinfo_rsp(mgr, skb, hdr);
+- break;
+-
+- case A2MP_GETAMPASSOC_RSP:
+- err = a2mp_getampassoc_rsp(mgr, skb, hdr);
+- break;
+-
+- case A2MP_CHANGE_RSP:
+- case A2MP_CREATEPHYSLINK_RSP:
+- case A2MP_DISCONNPHYSLINK_RSP:
+- err = a2mp_cmd_rsp(mgr, skb, hdr);
+- break;
+-
+- default:
+- BT_ERR("Unknown A2MP sig cmd 0x%2.2x", hdr->code);
+- err = -EINVAL;
+- break;
+- }
+- }
+-
+- if (err) {
+- struct a2mp_cmd_rej rej;
+-
+- memset(&rej, 0, sizeof(rej));
+-
+- rej.reason = cpu_to_le16(0);
+- hdr = (void *) skb->data;
+-
+- BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err);
+-
+- a2mp_send(mgr, A2MP_COMMAND_REJ, hdr->ident, sizeof(rej),
+- &rej);
+- }
+-
+- /* Always free skb and return success error code to prevent
+- from sending L2CAP Disconnect over A2MP channel */
+- kfree_skb(skb);
+-
+- amp_mgr_put(mgr);
+-
+- return 0;
+-}
+-
+-static void a2mp_chan_close_cb(struct l2cap_chan *chan)
+-{
+- l2cap_chan_put(chan);
+-}
+-
+-static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state,
+- int err)
+-{
+- struct amp_mgr *mgr = chan->data;
+-
+- if (!mgr)
+- return;
+-
+- BT_DBG("chan %p state %s", chan, state_to_string(state));
+-
+- chan->state = state;
+-
+- switch (state) {
+- case BT_CLOSED:
+- if (mgr)
+- amp_mgr_put(mgr);
+- break;
+- }
+-}
+-
+-static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan,
+- unsigned long hdr_len,
+- unsigned long len, int nb)
+-{
+- struct sk_buff *skb;
+-
+- skb = bt_skb_alloc(hdr_len + len, GFP_KERNEL);
+- if (!skb)
+- return ERR_PTR(-ENOMEM);
+-
+- return skb;
+-}
+-
+-static const struct l2cap_ops a2mp_chan_ops = {
+- .name = "L2CAP A2MP channel",
+- .recv = a2mp_chan_recv_cb,
+- .close = a2mp_chan_close_cb,
+- .state_change = a2mp_chan_state_change_cb,
+- .alloc_skb = a2mp_chan_alloc_skb_cb,
+-
+- /* Not implemented for A2MP */
+- .new_connection = l2cap_chan_no_new_connection,
+- .teardown = l2cap_chan_no_teardown,
+- .ready = l2cap_chan_no_ready,
+- .defer = l2cap_chan_no_defer,
+- .resume = l2cap_chan_no_resume,
+- .set_shutdown = l2cap_chan_no_set_shutdown,
+- .get_sndtimeo = l2cap_chan_no_get_sndtimeo,
+-};
+-
+-static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
+-{
+- struct l2cap_chan *chan;
+- int err;
+-
+- chan = l2cap_chan_create();
+- if (!chan)
+- return NULL;
+-
+- BT_DBG("chan %p", chan);
+-
+- chan->chan_type = L2CAP_CHAN_FIXED;
+- chan->scid = L2CAP_CID_A2MP;
+- chan->dcid = L2CAP_CID_A2MP;
+- chan->omtu = L2CAP_A2MP_DEFAULT_MTU;
+- chan->imtu = L2CAP_A2MP_DEFAULT_MTU;
+- chan->flush_to = L2CAP_DEFAULT_FLUSH_TO;
+-
+- chan->ops = &a2mp_chan_ops;
+-
+- l2cap_chan_set_defaults(chan);
+- chan->remote_max_tx = chan->max_tx;
+- chan->remote_tx_win = chan->tx_win;
+-
+- chan->retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
+- chan->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
+-
+- skb_queue_head_init(&chan->tx_q);
+-
+- chan->mode = L2CAP_MODE_ERTM;
+-
+- err = l2cap_ertm_init(chan);
+- if (err < 0) {
+- l2cap_chan_del(chan, 0);
+- return NULL;
+- }
+-
+- chan->conf_state = 0;
+-
+- if (locked)
+- __l2cap_chan_add(conn, chan);
+- else
+- l2cap_chan_add(conn, chan);
+-
+- chan->remote_mps = chan->omtu;
+- chan->mps = chan->omtu;
+-
+- chan->state = BT_CONNECTED;
+-
+- return chan;
+-}
+-
+-/* AMP Manager functions */
+-struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr)
+-{
+- BT_DBG("mgr %p orig refcnt %d", mgr, kref_read(&mgr->kref));
+-
+- kref_get(&mgr->kref);
+-
+- return mgr;
+-}
+-
+-static void amp_mgr_destroy(struct kref *kref)
+-{
+- struct amp_mgr *mgr = container_of(kref, struct amp_mgr, kref);
+-
+- BT_DBG("mgr %p", mgr);
+-
+- mutex_lock(&_mgr_list_lock);
+- list_del(&mgr->list);
+- mutex_unlock(&_mgr_list_lock);
+-
+- amp_ctrl_list_flush(mgr);
+- kfree(mgr);
+-}
+-
+-int amp_mgr_put(struct amp_mgr *mgr)
+-{
+- BT_DBG("mgr %p orig refcnt %d", mgr, kref_read(&mgr->kref));
+-
+- return kref_put(&mgr->kref, &_mgr_destroy);
+-}
+-
+-static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn, bool locked)
+-{
+- struct amp_mgr *mgr;
+- struct l2cap_chan *chan;
+-
+- mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
+- if (!mgr)
+- return NULL;
+-
+- BT_DBG("conn %p mgr %p", conn, mgr);
+-
+- mgr->l2cap_conn = conn;
+-
+- chan = a2mp_chan_open(conn, locked);
+- if (!chan) {
+- kfree(mgr);
+- return NULL;
+- }
+-
+- mgr->a2mp_chan = chan;
+- chan->data = mgr;
+-
+- conn->hcon->amp_mgr = mgr;
+-
+- kref_init(&mgr->kref);
+-
+- /* Remote AMP ctrl list initialization */
+- INIT_LIST_HEAD(&mgr->amp_ctrls);
+- mutex_init(&mgr->amp_ctrls_lock);
+-
+- mutex_lock(&_mgr_list_lock);
+- list_add(&mgr->list, &_mgr_list);
+- mutex_unlock(&_mgr_list_lock);
+-
+- return mgr;
+-}
+-
+-struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
+- struct sk_buff *skb)
+-{
+- struct amp_mgr *mgr;
+-
+- if (conn->hcon->type != ACL_LINK)
+- return NULL;
+-
+- mgr = amp_mgr_create(conn, false);
+- if (!mgr) {
+- BT_ERR("Could not create AMP manager");
+- return NULL;
+- }
+-
+- BT_DBG("mgr: %p chan %p", mgr, mgr->a2mp_chan);
+-
+- return mgr->a2mp_chan;
+-}
+-
+-void a2mp_send_getinfo_rsp(struct hci_dev *hdev)
+-{
+- struct amp_mgr *mgr;
+- struct a2mp_info_rsp rsp;
+-
+- mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_INFO);
+- if (!mgr)
+- return;
+-
+- BT_DBG("%s mgr %p", hdev->name, mgr);
+-
+- memset(&rsp, 0, sizeof(rsp));
+-
+- rsp.id = hdev->id;
+- rsp.status = A2MP_STATUS_INVALID_CTRL_ID;
+-
+- if (hdev->amp_type != AMP_TYPE_BREDR) {
+- rsp.status = 0;
+- rsp.total_bw = cpu_to_le32(hdev->amp_total_bw);
+- rsp.max_bw = cpu_to_le32(hdev->amp_max_bw);
+- rsp.min_latency = cpu_to_le32(hdev->amp_min_latency);
+- rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap);
+- rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size);
+- }
+-
+- a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp);
+- amp_mgr_put(mgr);
+-}
+-
+-void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status)
+-{
+- struct amp_mgr *mgr;
+- struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+- struct a2mp_amp_assoc_rsp *rsp;
+- size_t len;
+-
+- mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC);
+- if (!mgr)
+- return;
+-
+- BT_DBG("%s mgr %p", hdev->name, mgr);
+-
+- len = sizeof(struct a2mp_amp_assoc_rsp) + loc_assoc->len;
+- rsp = kzalloc(len, GFP_KERNEL);
+- if (!rsp) {
+- amp_mgr_put(mgr);
+- return;
+- }
+-
+- rsp->id = hdev->id;
+-
+- if (status) {
+- rsp->status = A2MP_STATUS_INVALID_CTRL_ID;
+- } else {
+- rsp->status = A2MP_STATUS_SUCCESS;
+- memcpy(rsp->amp_assoc, loc_assoc->data, loc_assoc->len);
+- }
+-
+- a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, mgr->ident, len, rsp);
+- amp_mgr_put(mgr);
+- kfree(rsp);
+-}
+-
+-void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status)
+-{
+- struct amp_mgr *mgr;
+- struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+- struct a2mp_physlink_req *req;
+- struct l2cap_chan *bredr_chan;
+- size_t len;
+-
+- mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC_FINAL);
+- if (!mgr)
+- return;
+-
+- len = sizeof(*req) + loc_assoc->len;
+-
+- BT_DBG("%s mgr %p assoc_len %zu", hdev->name, mgr, len);
+-
+- req = kzalloc(len, GFP_KERNEL);
+- if (!req) {
+- amp_mgr_put(mgr);
+- return;
+- }
+-
+- bredr_chan = mgr->bredr_chan;
+- if (!bredr_chan)
+- goto clean;
+-
+- req->local_id = hdev->id;
+- req->remote_id = bredr_chan->remote_amp_id;
+- memcpy(req->amp_assoc, loc_assoc->data, loc_assoc->len);
+-
+- a2mp_send(mgr, A2MP_CREATEPHYSLINK_REQ, __next_ident(mgr), len, req);
+-
+-clean:
+- amp_mgr_put(mgr);
+- kfree(req);
+-}
+-
+-void a2mp_send_create_phy_link_rsp(struct hci_dev *hdev, u8 status)
+-{
+- struct amp_mgr *mgr;
+- struct a2mp_physlink_rsp rsp;
+- struct hci_conn *hs_hcon;
+-
+- mgr = amp_mgr_lookup_by_state(WRITE_REMOTE_AMP_ASSOC);
+- if (!mgr)
+- return;
+-
+- memset(&rsp, 0, sizeof(rsp));
+-
+- hs_hcon = hci_conn_hash_lookup_state(hdev, AMP_LINK, BT_CONNECT);
+- if (!hs_hcon) {
+- rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
+- } else {
+- rsp.remote_id = hs_hcon->remote_id;
+- rsp.status = A2MP_STATUS_SUCCESS;
+- }
+-
+- BT_DBG("%s mgr %p hs_hcon %p status %u", hdev->name, mgr, hs_hcon,
+- status);
+-
+- rsp.local_id = hdev->id;
+- a2mp_send(mgr, A2MP_CREATEPHYSLINK_RSP, mgr->ident, sizeof(rsp), &rsp);
+- amp_mgr_put(mgr);
+-}
+-
+-void a2mp_discover_amp(struct l2cap_chan *chan)
+-{
+- struct l2cap_conn *conn = chan->conn;
+- struct amp_mgr *mgr = conn->hcon->amp_mgr;
+- struct a2mp_discov_req req;
+-
+- BT_DBG("chan %p conn %p mgr %p", chan, conn, mgr);
+-
+- if (!mgr) {
+- mgr = amp_mgr_create(conn, true);
+- if (!mgr)
+- return;
+- }
+-
+- mgr->bredr_chan = chan;
+-
+- memset(&req, 0, sizeof(req));
+-
+- req.mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
+- req.ext_feat = 0;
+- a2mp_send(mgr, A2MP_DISCOVER_REQ, 1, sizeof(req), &req);
+-}
+diff --git a/net/bluetooth/a2mp.h b/net/bluetooth/a2mp.h
+deleted file mode 100644
+index 2fd253a61a2a1..0000000000000
+--- a/net/bluetooth/a2mp.h
++++ /dev/null
+@@ -1,154 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-only */
+-/*
+- Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved.
+- Copyright (c) 2011,2012 Intel Corp.
+-
+-*/
+-
+-#ifndef __A2MP_H
+-#define __A2MP_H
+-
+-#include <net/bluetooth/l2cap.h>
+-
+-enum amp_mgr_state {
+- READ_LOC_AMP_INFO,
+- READ_LOC_AMP_ASSOC,
+- READ_LOC_AMP_ASSOC_FINAL,
+- WRITE_REMOTE_AMP_ASSOC,
+-};
+-
+-struct amp_mgr {
+- struct list_head list;
+- struct l2cap_conn *l2cap_conn;
+- struct l2cap_chan *a2mp_chan;
+- struct l2cap_chan *bredr_chan;
+- struct kref kref;
+- __u8 ident;
+- __u8 handle;
+- unsigned long state;
+- unsigned long flags;
+-
+- struct list_head amp_ctrls;
+- struct mutex amp_ctrls_lock;
+-};
+-
+-struct a2mp_cmd {
+- __u8 code;
+- __u8 ident;
+- __le16 len;
+- __u8 data[];
+-} __packed;
+-
+-/* A2MP command codes */
+-#define A2MP_COMMAND_REJ 0x01
+-struct a2mp_cmd_rej {
+- __le16 reason;
+- __u8 data[];
+-} __packed;
+-
+-#define A2MP_DISCOVER_REQ 0x02
+-struct a2mp_discov_req {
+- __le16 mtu;
+- __le16 ext_feat;
+-} __packed;
+-
+-struct a2mp_cl {
+- __u8 id;
+- __u8 type;
+- __u8 status;
+-} __packed;
+-
+-#define A2MP_DISCOVER_RSP 0x03
+-struct a2mp_discov_rsp {
+- __le16 mtu;
+- __le16 ext_feat;
+- struct a2mp_cl cl[];
+-} __packed;
+-
+-#define A2MP_CHANGE_NOTIFY 0x04
+-#define A2MP_CHANGE_RSP 0x05
+-
+-#define A2MP_GETINFO_REQ 0x06
+-struct a2mp_info_req {
+- __u8 id;
+-} __packed;
+-
+-#define A2MP_GETINFO_RSP 0x07
+-struct a2mp_info_rsp {
+- __u8 id;
+- __u8 status;
+- __le32 total_bw;
+- __le32 max_bw;
+- __le32 min_latency;
+- __le16 pal_cap;
+- __le16 assoc_size;
+-} __packed;
+-
+-#define A2MP_GETAMPASSOC_REQ 0x08
+-struct a2mp_amp_assoc_req {
+- __u8 id;
+-} __packed;
+-
+-#define A2MP_GETAMPASSOC_RSP 0x09
+-struct a2mp_amp_assoc_rsp {
+- __u8 id;
+- __u8 status;
+- __u8 amp_assoc[];
+-} __packed;
+-
+-#define A2MP_CREATEPHYSLINK_REQ 0x0A
+-#define A2MP_DISCONNPHYSLINK_REQ 0x0C
+-struct a2mp_physlink_req {
+- __u8 local_id;
+- __u8 remote_id;
+- __u8 amp_assoc[];
+-} __packed;
+-
+-#define A2MP_CREATEPHYSLINK_RSP 0x0B
+-#define A2MP_DISCONNPHYSLINK_RSP 0x0D
+-struct a2mp_physlink_rsp {
+- __u8 local_id;
+- __u8 remote_id;
+- __u8 status;
+-} __packed;
+-
+-/* A2MP response status */
+-#define A2MP_STATUS_SUCCESS 0x00
+-#define A2MP_STATUS_INVALID_CTRL_ID 0x01
+-#define A2MP_STATUS_UNABLE_START_LINK_CREATION 0x02
+-#define A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS 0x02
+-#define A2MP_STATUS_COLLISION_OCCURED 0x03
+-#define A2MP_STATUS_DISCONN_REQ_RECVD 0x04
+-#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05
+-#define A2MP_STATUS_SECURITY_VIOLATION 0x06
+-
+-struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr);
+-
+-#if IS_ENABLED(CONFIG_BT_HS)
+-int amp_mgr_put(struct amp_mgr *mgr);
+-struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
+- struct sk_buff *skb);
+-void a2mp_discover_amp(struct l2cap_chan *chan);
+-#else
+-static inline int amp_mgr_put(struct amp_mgr *mgr)
+-{
+- return 0;
+-}
+-
+-static inline struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
+- struct sk_buff *skb)
+-{
+- return NULL;
+-}
+-
+-static inline void a2mp_discover_amp(struct l2cap_chan *chan)
+-{
+-}
+-#endif
+-
+-void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
+-void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
+-void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status);
+-void a2mp_send_create_phy_link_rsp(struct hci_dev *hdev, u8 status);
+-
+-#endif /* __A2MP_H */
+diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
+index b93464ac3517f..67604ccec2f42 100644
+--- a/net/bluetooth/af_bluetooth.c
++++ b/net/bluetooth/af_bluetooth.c
+@@ -309,14 +309,11 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+ if (flags & MSG_OOB)
+ return -EOPNOTSUPP;
+
+- lock_sock(sk);
+-
+ skb = skb_recv_datagram(sk, flags, &err);
+ if (!skb) {
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ err = 0;
+
+- release_sock(sk);
+ return err;
+ }
+
+@@ -346,8 +343,6 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+
+ skb_free_datagram(sk, skb);
+
+- release_sock(sk);
+-
+ if (flags & MSG_TRUNC)
+ copied = skblen;
+
+@@ -570,10 +565,11 @@ int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ if (sk->sk_state == BT_LISTEN)
+ return -EINVAL;
+
+- lock_sock(sk);
++ spin_lock(&sk->sk_receive_queue.lock);
+ skb = skb_peek(&sk->sk_receive_queue);
+ amount = skb ? skb->len : 0;
+- release_sock(sk);
++ spin_unlock(&sk->sk_receive_queue.lock);
++
+ err = put_user(amount, (int __user *)arg);
+ break;
+
+diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
+deleted file mode 100644
+index 5d698f19868c5..0000000000000
+--- a/net/bluetooth/amp.c
++++ /dev/null
+@@ -1,590 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-only
+-/*
+- Copyright (c) 2011,2012 Intel Corp.
+-
+-*/
+-
+-#include <net/bluetooth/bluetooth.h>
+-#include <net/bluetooth/hci.h>
+-#include <net/bluetooth/hci_core.h>
+-#include <crypto/hash.h>
+-
+-#include "hci_request.h"
+-#include "a2mp.h"
+-#include "amp.h"
+-
+-/* Remote AMP Controllers interface */
+-void amp_ctrl_get(struct amp_ctrl *ctrl)
+-{
+- BT_DBG("ctrl %p orig refcnt %d", ctrl,
+- kref_read(&ctrl->kref));
+-
+- kref_get(&ctrl->kref);
+-}
+-
+-static void amp_ctrl_destroy(struct kref *kref)
+-{
+- struct amp_ctrl *ctrl = container_of(kref, struct amp_ctrl, kref);
+-
+- BT_DBG("ctrl %p", ctrl);
+-
+- kfree(ctrl->assoc);
+- kfree(ctrl);
+-}
+-
+-int amp_ctrl_put(struct amp_ctrl *ctrl)
+-{
+- BT_DBG("ctrl %p orig refcnt %d", ctrl,
+- kref_read(&ctrl->kref));
+-
+- return kref_put(&ctrl->kref, &_ctrl_destroy);
+-}
+-
+-struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id)
+-{
+- struct amp_ctrl *ctrl;
+-
+- ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+- if (!ctrl)
+- return NULL;
+-
+- kref_init(&ctrl->kref);
+- ctrl->id = id;
+-
+- mutex_lock(&mgr->amp_ctrls_lock);
+- list_add(&ctrl->list, &mgr->amp_ctrls);
+- mutex_unlock(&mgr->amp_ctrls_lock);
+-
+- BT_DBG("mgr %p ctrl %p", mgr, ctrl);
+-
+- return ctrl;
+-}
+-
+-void amp_ctrl_list_flush(struct amp_mgr *mgr)
+-{
+- struct amp_ctrl *ctrl, *n;
+-
+- BT_DBG("mgr %p", mgr);
+-
+- mutex_lock(&mgr->amp_ctrls_lock);
+- list_for_each_entry_safe(ctrl, n, &mgr->amp_ctrls, list) {
+- list_del(&ctrl->list);
+- amp_ctrl_put(ctrl);
+- }
+- mutex_unlock(&mgr->amp_ctrls_lock);
+-}
+-
+-struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id)
+-{
+- struct amp_ctrl *ctrl;
+-
+- BT_DBG("mgr %p id %u", mgr, id);
+-
+- mutex_lock(&mgr->amp_ctrls_lock);
+- list_for_each_entry(ctrl, &mgr->amp_ctrls, list) {
+- if (ctrl->id == id) {
+- amp_ctrl_get(ctrl);
+- mutex_unlock(&mgr->amp_ctrls_lock);
+- return ctrl;
+- }
+- }
+- mutex_unlock(&mgr->amp_ctrls_lock);
+-
+- return NULL;
+-}
+-
+-/* Physical Link interface */
+-static u8 __next_handle(struct amp_mgr *mgr)
+-{
+- if (++mgr->handle == 0)
+- mgr->handle = 1;
+-
+- return mgr->handle;
+-}
+-
+-struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
+- u8 remote_id, bool out)
+-{
+- bdaddr_t *dst = &mgr->l2cap_conn->hcon->dst;
+- struct hci_conn *hcon;
+- u8 role = out ? HCI_ROLE_MASTER : HCI_ROLE_SLAVE;
+-
+- hcon = hci_conn_add(hdev, AMP_LINK, dst, role, __next_handle(mgr));
+- if (!hcon)
+- return NULL;
+-
+- BT_DBG("hcon %p dst %pMR", hcon, dst);
+-
+- hcon->state = BT_CONNECT;
+- hcon->attempt++;
+- hcon->remote_id = remote_id;
+- hcon->amp_mgr = amp_mgr_get(mgr);
+-
+- return hcon;
+-}
+-
+-/* AMP crypto key generation interface */
+-static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
+-{
+- struct crypto_shash *tfm;
+- struct shash_desc *shash;
+- int ret;
+-
+- if (!ksize)
+- return -EINVAL;
+-
+- tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
+- if (IS_ERR(tfm)) {
+- BT_DBG("crypto_alloc_ahash failed: err %ld", PTR_ERR(tfm));
+- return PTR_ERR(tfm);
+- }
+-
+- ret = crypto_shash_setkey(tfm, key, ksize);
+- if (ret) {
+- BT_DBG("crypto_ahash_setkey failed: err %d", ret);
+- goto failed;
+- }
+-
+- shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
+- GFP_KERNEL);
+- if (!shash) {
+- ret = -ENOMEM;
+- goto failed;
+- }
+-
+- shash->tfm = tfm;
+-
+- ret = crypto_shash_digest(shash, plaintext, psize, output);
+-
+- kfree(shash);
+-
+-failed:
+- crypto_free_shash(tfm);
+- return ret;
+-}
+-
+-int phylink_gen_key(struct hci_conn *conn, u8 *data, u8 *len, u8 *type)
+-{
+- struct hci_dev *hdev = conn->hdev;
+- struct link_key *key;
+- u8 keybuf[HCI_AMP_LINK_KEY_SIZE];
+- u8 gamp_key[HCI_AMP_LINK_KEY_SIZE];
+- int err;
+-
+- if (!hci_conn_check_link_mode(conn))
+- return -EACCES;
+-
+- BT_DBG("conn %p key_type %d", conn, conn->key_type);
+-
+- /* Legacy key */
+- if (conn->key_type < 3) {
+- bt_dev_err(hdev, "legacy key type %u", conn->key_type);
+- return -EACCES;
+- }
+-
+- *type = conn->key_type;
+- *len = HCI_AMP_LINK_KEY_SIZE;
+-
+- key = hci_find_link_key(hdev, &conn->dst);
+- if (!key) {
+- BT_DBG("No Link key for conn %p dst %pMR", conn, &conn->dst);
+- return -EACCES;
+- }
+-
+- /* BR/EDR Link Key concatenated together with itself */
+- memcpy(&keybuf[0], key->val, HCI_LINK_KEY_SIZE);
+- memcpy(&keybuf[HCI_LINK_KEY_SIZE], key->val, HCI_LINK_KEY_SIZE);
+-
+- /* Derive Generic AMP Link Key (gamp) */
+- err = hmac_sha256(keybuf, HCI_AMP_LINK_KEY_SIZE, "gamp", 4, gamp_key);
+- if (err) {
+- bt_dev_err(hdev, "could not derive Generic AMP Key: err %d", err);
+- return err;
+- }
+-
+- if (conn->key_type == HCI_LK_DEBUG_COMBINATION) {
+- BT_DBG("Use Generic AMP Key (gamp)");
+- memcpy(data, gamp_key, HCI_AMP_LINK_KEY_SIZE);
+- return err;
+- }
+-
+- /* Derive Dedicated AMP Link Key: "802b" is 802.11 PAL keyID */
+- return hmac_sha256(gamp_key, HCI_AMP_LINK_KEY_SIZE, "802b", 4, data);
+-}
+-
+-static void read_local_amp_assoc_complete(struct hci_dev *hdev, u8 status,
+- u16 opcode, struct sk_buff *skb)
+-{
+- struct hci_rp_read_local_amp_assoc *rp = (void *)skb->data;
+- struct amp_assoc *assoc = &hdev->loc_assoc;
+- size_t rem_len, frag_len;
+-
+- BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+-
+- if (rp->status)
+- goto send_rsp;
+-
+- frag_len = skb->len - sizeof(*rp);
+- rem_len = __le16_to_cpu(rp->rem_len);
+-
+- if (rem_len > frag_len) {
+- BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len);
+-
+- memcpy(assoc->data + assoc->offset, rp->frag, frag_len);
+- assoc->offset += frag_len;
+-
+- /* Read other fragments */
+- amp_read_loc_assoc_frag(hdev, rp->phy_handle);
+-
+- return;
+- }
+-
+- memcpy(assoc->data + assoc->offset, rp->frag, rem_len);
+- assoc->len = assoc->offset + rem_len;
+- assoc->offset = 0;
+-
+-send_rsp:
+- /* Send A2MP Rsp when all fragments are received */
+- a2mp_send_getampassoc_rsp(hdev, rp->status);
+- a2mp_send_create_phy_link_req(hdev, rp->status);
+-}
+-
+-void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle)
+-{
+- struct hci_cp_read_local_amp_assoc cp;
+- struct amp_assoc *loc_assoc = &hdev->loc_assoc;
+- struct hci_request req;
+- int err;
+-
+- BT_DBG("%s handle %u", hdev->name, phy_handle);
+-
+- cp.phy_handle = phy_handle;
+- cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+- cp.len_so_far = cpu_to_le16(loc_assoc->offset);
+-
+- hci_req_init(&req, hdev);
+- hci_req_add(&req, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+- err = hci_req_run_skb(&req, read_local_amp_assoc_complete);
+- if (err < 0)
+- a2mp_send_getampassoc_rsp(hdev, A2MP_STATUS_INVALID_CTRL_ID);
+-}
+-
+-void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr)
+-{
+- struct hci_cp_read_local_amp_assoc cp;
+- struct hci_request req;
+- int err;
+-
+- memset(&hdev->loc_assoc, 0, sizeof(struct amp_assoc));
+- memset(&cp, 0, sizeof(cp));
+-
+- cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+-
+- set_bit(READ_LOC_AMP_ASSOC, &mgr->state);
+- hci_req_init(&req, hdev);
+- hci_req_add(&req, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+- err = hci_req_run_skb(&req, read_local_amp_assoc_complete);
+- if (err < 0)
+- a2mp_send_getampassoc_rsp(hdev, A2MP_STATUS_INVALID_CTRL_ID);
+-}
+-
+-void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
+- struct hci_conn *hcon)
+-{
+- struct hci_cp_read_local_amp_assoc cp;
+- struct amp_mgr *mgr = hcon->amp_mgr;
+- struct hci_request req;
+- int err;
+-
+- if (!mgr)
+- return;
+-
+- cp.phy_handle = hcon->handle;
+- cp.len_so_far = cpu_to_le16(0);
+- cp.max_len = cpu_to_le16(hdev->amp_assoc_size);
+-
+- set_bit(READ_LOC_AMP_ASSOC_FINAL, &mgr->state);
+-
+- /* Read Local AMP Assoc final link information data */
+- hci_req_init(&req, hdev);
+- hci_req_add(&req, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp);
+- err = hci_req_run_skb(&req, read_local_amp_assoc_complete);
+- if (err < 0)
+- a2mp_send_getampassoc_rsp(hdev, A2MP_STATUS_INVALID_CTRL_ID);
+-}
+-
+-static void write_remote_amp_assoc_complete(struct hci_dev *hdev, u8 status,
+- u16 opcode, struct sk_buff *skb)
+-{
+- struct hci_rp_write_remote_amp_assoc *rp = (void *)skb->data;
+-
+- BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x",
+- hdev->name, rp->status, rp->phy_handle);
+-
+- if (rp->status)
+- return;
+-
+- amp_write_rem_assoc_continue(hdev, rp->phy_handle);
+-}
+-
+-/* Write AMP Assoc data fragments, returns true with last fragment written*/
+-static bool amp_write_rem_assoc_frag(struct hci_dev *hdev,
+- struct hci_conn *hcon)
+-{
+- struct hci_cp_write_remote_amp_assoc *cp;
+- struct amp_mgr *mgr = hcon->amp_mgr;
+- struct amp_ctrl *ctrl;
+- struct hci_request req;
+- u16 frag_len, len;
+-
+- ctrl = amp_ctrl_lookup(mgr, hcon->remote_id);
+- if (!ctrl)
+- return false;
+-
+- if (!ctrl->assoc_rem_len) {
+- BT_DBG("all fragments are written");
+- ctrl->assoc_rem_len = ctrl->assoc_len;
+- ctrl->assoc_len_so_far = 0;
+-
+- amp_ctrl_put(ctrl);
+- return true;
+- }
+-
+- frag_len = min_t(u16, 248, ctrl->assoc_rem_len);
+- len = frag_len + sizeof(*cp);
+-
+- cp = kzalloc(len, GFP_KERNEL);
+- if (!cp) {
+- amp_ctrl_put(ctrl);
+- return false;
+- }
+-
+- BT_DBG("hcon %p ctrl %p frag_len %u assoc_len %u rem_len %u",
+- hcon, ctrl, frag_len, ctrl->assoc_len, ctrl->assoc_rem_len);
+-
+- cp->phy_handle = hcon->handle;
+- cp->len_so_far = cpu_to_le16(ctrl->assoc_len_so_far);
+- cp->rem_len = cpu_to_le16(ctrl->assoc_rem_len);
+- memcpy(cp->frag, ctrl->assoc, frag_len);
+-
+- ctrl->assoc_len_so_far += frag_len;
+- ctrl->assoc_rem_len -= frag_len;
+-
+- amp_ctrl_put(ctrl);
+-
+- hci_req_init(&req, hdev);
+- hci_req_add(&req, HCI_OP_WRITE_REMOTE_AMP_ASSOC, len, cp);
+- hci_req_run_skb(&req, write_remote_amp_assoc_complete);
+-
+- kfree(cp);
+-
+- return false;
+-}
+-
+-void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle)
+-{
+- struct hci_conn *hcon;
+-
+- BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
+-
+- hcon = hci_conn_hash_lookup_handle(hdev, handle);
+- if (!hcon)
+- return;
+-
+- /* Send A2MP create phylink rsp when all fragments are written */
+- if (amp_write_rem_assoc_frag(hdev, hcon))
+- a2mp_send_create_phy_link_rsp(hdev, 0);
+-}
+-
+-void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle)
+-{
+- struct hci_conn *hcon;
+-
+- BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle);
+-
+- hcon = hci_conn_hash_lookup_handle(hdev, handle);
+- if (!hcon)
+- return;
+-
+- BT_DBG("%s phy handle 0x%2.2x hcon %p", hdev->name, handle, hcon);
+-
+- amp_write_rem_assoc_frag(hdev, hcon);
+-}
+-
+-static void create_phylink_complete(struct hci_dev *hdev, u8 status,
+- u16 opcode)
+-{
+- struct hci_cp_create_phy_link *cp;
+-
+- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+-
+- cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK);
+- if (!cp)
+- return;
+-
+- hci_dev_lock(hdev);
+-
+- if (status) {
+- struct hci_conn *hcon;
+-
+- hcon = hci_conn_hash_lookup_handle(hdev, cp->phy_handle);
+- if (hcon)
+- hci_conn_del(hcon);
+- } else {
+- amp_write_remote_assoc(hdev, cp->phy_handle);
+- }
+-
+- hci_dev_unlock(hdev);
+-}
+-
+-void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+- struct hci_conn *hcon)
+-{
+- struct hci_cp_create_phy_link cp;
+- struct hci_request req;
+-
+- cp.phy_handle = hcon->handle;
+-
+- BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
+- hcon->handle);
+-
+- if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
+- &cp.key_type)) {
+- BT_DBG("Cannot create link key");
+- return;
+- }
+-
+- hci_req_init(&req, hdev);
+- hci_req_add(&req, HCI_OP_CREATE_PHY_LINK, sizeof(cp), &cp);
+- hci_req_run(&req, create_phylink_complete);
+-}
+-
+-static void accept_phylink_complete(struct hci_dev *hdev, u8 status,
+- u16 opcode)
+-{
+- struct hci_cp_accept_phy_link *cp;
+-
+- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+-
+- if (status)
+- return;
+-
+- cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK);
+- if (!cp)
+- return;
+-
+- amp_write_remote_assoc(hdev, cp->phy_handle);
+-}
+-
+-void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+- struct hci_conn *hcon)
+-{
+- struct hci_cp_accept_phy_link cp;
+- struct hci_request req;
+-
+- cp.phy_handle = hcon->handle;
+-
+- BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon,
+- hcon->handle);
+-
+- if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len,
+- &cp.key_type)) {
+- BT_DBG("Cannot create link key");
+- return;
+- }
+-
+- hci_req_init(&req, hdev);
+- hci_req_add(&req, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp);
+- hci_req_run(&req, accept_phylink_complete);
+-}
+-
+-void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon)
+-{
+- struct hci_dev *bredr_hdev = hci_dev_hold(bredr_hcon->hdev);
+- struct amp_mgr *mgr = hs_hcon->amp_mgr;
+- struct l2cap_chan *bredr_chan;
+-
+- BT_DBG("bredr_hcon %p hs_hcon %p mgr %p", bredr_hcon, hs_hcon, mgr);
+-
+- if (!bredr_hdev || !mgr || !mgr->bredr_chan)
+- return;
+-
+- bredr_chan = mgr->bredr_chan;
+-
+- l2cap_chan_lock(bredr_chan);
+-
+- set_bit(FLAG_EFS_ENABLE, &bredr_chan->flags);
+- bredr_chan->remote_amp_id = hs_hcon->remote_id;
+- bredr_chan->local_amp_id = hs_hcon->hdev->id;
+- bredr_chan->hs_hcon = hs_hcon;
+- bredr_chan->conn->mtu = hs_hcon->hdev->block_mtu;
+-
+- __l2cap_physical_cfm(bredr_chan, 0);
+-
+- l2cap_chan_unlock(bredr_chan);
+-
+- hci_dev_put(bredr_hdev);
+-}
+-
+-void amp_create_logical_link(struct l2cap_chan *chan)
+-{
+- struct hci_conn *hs_hcon = chan->hs_hcon;
+- struct hci_cp_create_accept_logical_link cp;
+- struct hci_dev *hdev;
+-
+- BT_DBG("chan %p hs_hcon %p dst %pMR", chan, hs_hcon,
+- &chan->conn->hcon->dst);
+-
+- if (!hs_hcon)
+- return;
+-
+- hdev = hci_dev_hold(chan->hs_hcon->hdev);
+- if (!hdev)
+- return;
+-
+- cp.phy_handle = hs_hcon->handle;
+-
+- cp.tx_flow_spec.id = chan->local_id;
+- cp.tx_flow_spec.stype = chan->local_stype;
+- cp.tx_flow_spec.msdu = cpu_to_le16(chan->local_msdu);
+- cp.tx_flow_spec.sdu_itime = cpu_to_le32(chan->local_sdu_itime);
+- cp.tx_flow_spec.acc_lat = cpu_to_le32(chan->local_acc_lat);
+- cp.tx_flow_spec.flush_to = cpu_to_le32(chan->local_flush_to);
+-
+- cp.rx_flow_spec.id = chan->remote_id;
+- cp.rx_flow_spec.stype = chan->remote_stype;
+- cp.rx_flow_spec.msdu = cpu_to_le16(chan->remote_msdu);
+- cp.rx_flow_spec.sdu_itime = cpu_to_le32(chan->remote_sdu_itime);
+- cp.rx_flow_spec.acc_lat = cpu_to_le32(chan->remote_acc_lat);
+- cp.rx_flow_spec.flush_to = cpu_to_le32(chan->remote_flush_to);
+-
+- if (hs_hcon->out)
+- hci_send_cmd(hdev, HCI_OP_CREATE_LOGICAL_LINK, sizeof(cp),
+- &cp);
+- else
+- hci_send_cmd(hdev, HCI_OP_ACCEPT_LOGICAL_LINK, sizeof(cp),
+- &cp);
+-
+- hci_dev_put(hdev);
+-}
+-
+-void amp_disconnect_logical_link(struct hci_chan *hchan)
+-{
+- struct hci_conn *hcon = hchan->conn;
+- struct hci_cp_disconn_logical_link cp;
+-
+- if (hcon->state != BT_CONNECTED) {
+- BT_DBG("hchan %p not connected", hchan);
+- return;
+- }
+-
+- cp.log_handle = cpu_to_le16(hchan->handle);
+- hci_send_cmd(hcon->hdev, HCI_OP_DISCONN_LOGICAL_LINK, sizeof(cp), &cp);
+-}
+-
+-void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason)
+-{
+- BT_DBG("hchan %p", hchan);
+-
+- hci_chan_del(hchan);
+-}
+diff --git a/net/bluetooth/amp.h b/net/bluetooth/amp.h
+deleted file mode 100644
+index 97c87abd129f6..0000000000000
+--- a/net/bluetooth/amp.h
++++ /dev/null
+@@ -1,60 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0-only */
+-/*
+- Copyright (c) 2011,2012 Intel Corp.
+-
+-*/
+-
+-#ifndef __AMP_H
+-#define __AMP_H
+-
+-struct amp_ctrl {
+- struct list_head list;
+- struct kref kref;
+- __u8 id;
+- __u16 assoc_len_so_far;
+- __u16 assoc_rem_len;
+- __u16 assoc_len;
+- __u8 *assoc;
+-};
+-
+-int amp_ctrl_put(struct amp_ctrl *ctrl);
+-void amp_ctrl_get(struct amp_ctrl *ctrl);
+-struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id);
+-struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id);
+-void amp_ctrl_list_flush(struct amp_mgr *mgr);
+-
+-struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
+- u8 remote_id, bool out);
+-
+-int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);
+-
+-void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
+-void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
+-void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
+- struct hci_conn *hcon);
+-void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+- struct hci_conn *hcon);
+-void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+- struct hci_conn *hcon);
+-
+-#if IS_ENABLED(CONFIG_BT_HS)
+-void amp_create_logical_link(struct l2cap_chan *chan);
+-void amp_disconnect_logical_link(struct hci_chan *hchan);
+-#else
+-static inline void amp_create_logical_link(struct l2cap_chan *chan)
+-{
+-}
+-
+-static inline void amp_disconnect_logical_link(struct hci_chan *hchan)
+-{
+-}
+-#endif
+-
+-void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
+-void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle);
+-void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon);
+-void amp_create_logical_link(struct l2cap_chan *chan);
+-void amp_disconnect_logical_link(struct hci_chan *hchan);
+-void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason);
+-
+-#endif /* __AMP_H */
+diff --git a/net/bluetooth/eir.c b/net/bluetooth/eir.c
+index 9214189279e80..1bc51e2b05a34 100644
+--- a/net/bluetooth/eir.c
++++ b/net/bluetooth/eir.c
+@@ -13,48 +13,33 @@
+
+ #define PNP_INFO_SVCLASS_ID 0x1200
+
+-static u8 eir_append_name(u8 *eir, u16 eir_len, u8 type, u8 *data, u8 data_len)
+-{
+- u8 name[HCI_MAX_SHORT_NAME_LENGTH + 1];
+-
+- /* If data is already NULL terminated just pass it directly */
+- if (data[data_len - 1] == '\0')
+- return eir_append_data(eir, eir_len, type, data, data_len);
+-
+- memcpy(name, data, HCI_MAX_SHORT_NAME_LENGTH);
+- name[HCI_MAX_SHORT_NAME_LENGTH] = '\0';
+-
+- return eir_append_data(eir, eir_len, type, name, sizeof(name));
+-}
+-
+ u8 eir_append_local_name(struct hci_dev *hdev, u8 *ptr, u8 ad_len)
+ {
+ size_t short_len;
+ size_t complete_len;
+
+- /* no space left for name (+ NULL + type + len) */
+- if ((max_adv_len(hdev) - ad_len) < HCI_MAX_SHORT_NAME_LENGTH + 3)
++ /* no space left for name (+ type + len) */
++ if ((max_adv_len(hdev) - ad_len) < HCI_MAX_SHORT_NAME_LENGTH + 2)
+ return ad_len;
+
+ /* use complete name if present and fits */
+ complete_len = strnlen(hdev->dev_name, sizeof(hdev->dev_name));
+ if (complete_len && complete_len <= HCI_MAX_SHORT_NAME_LENGTH)
+- return eir_append_name(ptr, ad_len, EIR_NAME_COMPLETE,
+- hdev->dev_name, complete_len + 1);
++ return eir_append_data(ptr, ad_len, EIR_NAME_COMPLETE,
++ hdev->dev_name, complete_len);
+
+ /* use short name if present */
+ short_len = strnlen(hdev->short_name, sizeof(hdev->short_name));
+ if (short_len)
+- return eir_append_name(ptr, ad_len, EIR_NAME_SHORT,
++ return eir_append_data(ptr, ad_len, EIR_NAME_SHORT,
+ hdev->short_name,
+- short_len == HCI_MAX_SHORT_NAME_LENGTH ?
+- short_len : short_len + 1);
++ short_len);
+
+ /* use shortened full name if present, we already know that name
+ * is longer then HCI_MAX_SHORT_NAME_LENGTH
+ */
+ if (complete_len)
+- return eir_append_name(ptr, ad_len, EIR_NAME_SHORT,
++ return eir_append_data(ptr, ad_len, EIR_NAME_SHORT,
+ hdev->dev_name,
+ HCI_MAX_SHORT_NAME_LENGTH);
+
+diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
+index a41d2693f4d8c..ba330114d38f7 100644
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -36,7 +36,6 @@
+
+ #include "hci_request.h"
+ #include "smp.h"
+-#include "a2mp.h"
+ #include "eir.h"
+
+ struct sco_param {
+@@ -1175,9 +1174,6 @@ void hci_conn_del(struct hci_conn *conn)
+ }
+ }
+
+- if (conn->amp_mgr)
+- amp_mgr_put(conn->amp_mgr);
+-
+ skb_queue_purge(&conn->data_q);
+
+ /* Remove the connection from the list and cleanup its remaining
+@@ -3014,7 +3010,7 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
+ case HCI_EV_LE_CONN_COMPLETE:
+ case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
+ case HCI_EVT_LE_CIS_ESTABLISHED:
+- hci_cmd_sync_cancel(hdev, -ECANCELED);
++ hci_cmd_sync_cancel(hdev, ECANCELED);
+ break;
+ }
+ }
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index 2821a42cefdc6..7d5334b529834 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -908,7 +908,7 @@ int hci_get_dev_info(void __user *arg)
+ else
+ flags = hdev->flags;
+
+- strcpy(di.name, hdev->name);
++ strscpy(di.name, hdev->name, sizeof(di.name));
+ di.bdaddr = hdev->bdaddr;
+ di.type = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4);
+ di.flags = flags;
+@@ -1491,11 +1491,12 @@ static void hci_cmd_timeout(struct work_struct *work)
+ struct hci_dev *hdev = container_of(work, struct hci_dev,
+ cmd_timer.work);
+
+- if (hdev->sent_cmd) {
+- struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data;
+- u16 opcode = __le16_to_cpu(sent->opcode);
++ if (hdev->req_skb) {
++ u16 opcode = hci_skb_opcode(hdev->req_skb);
+
+ bt_dev_err(hdev, "command 0x%4.4x tx timeout", opcode);
++
++ hci_cmd_sync_cancel_sync(hdev, ETIMEDOUT);
+ } else {
+ bt_dev_err(hdev, "command tx timeout");
+ }
+@@ -2795,6 +2796,7 @@ void hci_release_dev(struct hci_dev *hdev)
+ ida_destroy(&hdev->unset_handle_ida);
+ ida_simple_remove(&hci_index_ida, hdev->id);
+ kfree_skb(hdev->sent_cmd);
++ kfree_skb(hdev->req_skb);
+ kfree_skb(hdev->recv_event);
+ kfree(hdev);
+ }
+@@ -2826,6 +2828,23 @@ int hci_unregister_suspend_notifier(struct hci_dev *hdev)
+ return ret;
+ }
+
++/* Cancel ongoing command synchronously:
++ *
++ * - Cancel command timer
++ * - Reset command counter
++ * - Cancel command request
++ */
++static void hci_cancel_cmd_sync(struct hci_dev *hdev, int err)
++{
++ bt_dev_dbg(hdev, "err 0x%2.2x", err);
++
++ cancel_delayed_work_sync(&hdev->cmd_timer);
++ cancel_delayed_work_sync(&hdev->ncmd_timer);
++ atomic_set(&hdev->cmd_cnt, 1);
++
++ hci_cmd_sync_cancel_sync(hdev, -err);
++}
++
+ /* Suspend HCI device */
+ int hci_suspend_dev(struct hci_dev *hdev)
+ {
+@@ -2843,7 +2862,7 @@ int hci_suspend_dev(struct hci_dev *hdev)
+ return 0;
+
+ /* Cancel potentially blocking sync operation before suspend */
+- __hci_cmd_sync_cancel(hdev, -EHOSTDOWN);
++ hci_cancel_cmd_sync(hdev, -EHOSTDOWN);
+
+ hci_req_sync_lock(hdev);
+ ret = hci_suspend_sync(hdev);
+@@ -3107,21 +3126,33 @@ int __hci_cmd_send(struct hci_dev *hdev, u16 opcode, u32 plen,
+ EXPORT_SYMBOL(__hci_cmd_send);
+
+ /* Get data from the previously sent command */
+-void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
++static void *hci_cmd_data(struct sk_buff *skb, __u16 opcode)
+ {
+ struct hci_command_hdr *hdr;
+
+- if (!hdev->sent_cmd)
++ if (!skb || skb->len < HCI_COMMAND_HDR_SIZE)
+ return NULL;
+
+- hdr = (void *) hdev->sent_cmd->data;
++ hdr = (void *)skb->data;
+
+ if (hdr->opcode != cpu_to_le16(opcode))
+ return NULL;
+
+- BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
++ return skb->data + HCI_COMMAND_HDR_SIZE;
++}
++
++/* Get data from the previously sent command */
++void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
++{
++ void *data;
+
+- return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE;
++ /* Check if opcode matches last sent command */
++ data = hci_cmd_data(hdev->sent_cmd, opcode);
++ if (!data)
++ /* Check if opcode matches last request */
++ data = hci_cmd_data(hdev->req_skb, opcode);
++
++ return data;
+ }
+
+ /* Get data from last received event */
+@@ -4022,17 +4053,19 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
+ if (!status && !hci_req_is_complete(hdev))
+ return;
+
++ skb = hdev->req_skb;
++
+ /* If this was the last command in a request the complete
+- * callback would be found in hdev->sent_cmd instead of the
++ * callback would be found in hdev->req_skb instead of the
+ * command queue (hdev->cmd_q).
+ */
+- if (bt_cb(hdev->sent_cmd)->hci.req_flags & HCI_REQ_SKB) {
+- *req_complete_skb = bt_cb(hdev->sent_cmd)->hci.req_complete_skb;
++ if (skb && bt_cb(skb)->hci.req_flags & HCI_REQ_SKB) {
++ *req_complete_skb = bt_cb(skb)->hci.req_complete_skb;
+ return;
+ }
+
+- if (bt_cb(hdev->sent_cmd)->hci.req_complete) {
+- *req_complete = bt_cb(hdev->sent_cmd)->hci.req_complete;
++ if (skb && bt_cb(skb)->hci.req_complete) {
++ *req_complete = bt_cb(skb)->hci.req_complete;
+ return;
+ }
+
+@@ -4128,6 +4161,36 @@ static void hci_rx_work(struct work_struct *work)
+ }
+ }
+
++static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)
++{
++ int err;
++
++ bt_dev_dbg(hdev, "skb %p", skb);
++
++ kfree_skb(hdev->sent_cmd);
++
++ hdev->sent_cmd = skb_clone(skb, GFP_KERNEL);
++ if (!hdev->sent_cmd) {
++ skb_queue_head(&hdev->cmd_q, skb);
++ queue_work(hdev->workqueue, &hdev->cmd_work);
++ return;
++ }
++
++ err = hci_send_frame(hdev, skb);
++ if (err < 0) {
++ hci_cmd_sync_cancel_sync(hdev, err);
++ return;
++ }
++
++ if (hci_req_status_pend(hdev) &&
++ !hci_dev_test_and_set_flag(hdev, HCI_CMD_PENDING)) {
++ kfree_skb(hdev->req_skb);
++ hdev->req_skb = skb_clone(hdev->sent_cmd, GFP_KERNEL);
++ }
++
++ atomic_dec(&hdev->cmd_cnt);
++}
++
+ static void hci_cmd_work(struct work_struct *work)
+ {
+ struct hci_dev *hdev = container_of(work, struct hci_dev, cmd_work);
+@@ -4142,30 +4205,15 @@ static void hci_cmd_work(struct work_struct *work)
+ if (!skb)
+ return;
+
+- kfree_skb(hdev->sent_cmd);
+-
+- hdev->sent_cmd = skb_clone(skb, GFP_KERNEL);
+- if (hdev->sent_cmd) {
+- int res;
+- if (hci_req_status_pend(hdev))
+- hci_dev_set_flag(hdev, HCI_CMD_PENDING);
+- atomic_dec(&hdev->cmd_cnt);
++ hci_send_cmd_sync(hdev, skb);
+
+- res = hci_send_frame(hdev, skb);
+- if (res < 0)
+- __hci_cmd_sync_cancel(hdev, -res);
+-
+- rcu_read_lock();
+- if (test_bit(HCI_RESET, &hdev->flags) ||
+- hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE))
+- cancel_delayed_work(&hdev->cmd_timer);
+- else
+- queue_delayed_work(hdev->workqueue, &hdev->cmd_timer,
+- HCI_CMD_TIMEOUT);
+- rcu_read_unlock();
+- } else {
+- skb_queue_head(&hdev->cmd_q, skb);
+- queue_work(hdev->workqueue, &hdev->cmd_work);
+- }
++ rcu_read_lock();
++ if (test_bit(HCI_RESET, &hdev->flags) ||
++ hci_dev_test_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE))
++ cancel_delayed_work(&hdev->cmd_timer);
++ else
++ queue_delayed_work(hdev->workqueue, &hdev->cmd_timer,
++ HCI_CMD_TIMEOUT);
++ rcu_read_unlock();
+ }
+ }
+diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
+index 2a5f5a7d2412b..6275b14b56927 100644
+--- a/net/bluetooth/hci_event.c
++++ b/net/bluetooth/hci_event.c
+@@ -36,8 +36,6 @@
+ #include "hci_request.h"
+ #include "hci_debugfs.h"
+ #include "hci_codec.h"
+-#include "a2mp.h"
+-#include "amp.h"
+ #include "smp.h"
+ #include "msft.h"
+ #include "eir.h"
+@@ -2526,9 +2524,7 @@ static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
+ * Only those in BT_CONFIG or BT_CONNECTED states can be
+ * considered connected.
+ */
+- if (conn &&
+- (conn->state == BT_CONFIG || conn->state == BT_CONNECTED) &&
+- !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
++ if (conn && (conn->state == BT_CONFIG || conn->state == BT_CONNECTED))
+ mgmt_device_connected(hdev, conn, name, name_len);
+
+ if (discov->state == DISCOVERY_STOPPED)
+@@ -3556,8 +3552,6 @@ static void hci_remote_name_evt(struct hci_dev *hdev, void *data,
+
+ bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
+
+- hci_conn_check_pending(hdev);
+-
+ hci_dev_lock(hdev);
+
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
+@@ -3762,8 +3756,9 @@ static void hci_remote_features_evt(struct hci_dev *hdev, void *data,
+ bacpy(&cp.bdaddr, &conn->dst);
+ cp.pscan_rep_mode = 0x02;
+ hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
+- } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
++ } else {
+ mgmt_device_connected(hdev, conn, NULL, 0);
++ }
+
+ if (!hci_outgoing_auth_needed(hdev, conn)) {
+ conn->state = BT_CONNECTED;
+@@ -3936,6 +3931,11 @@ static u8 hci_cc_le_setup_iso_path(struct hci_dev *hdev, void *data,
+ * last.
+ */
+ hci_connect_cfm(conn, rp->status);
++
++ /* Notify device connected in case it is a BIG Sync */
++ if (!rp->status && test_bit(HCI_CONN_BIG_SYNC, &conn->flags))
++ mgmt_device_connected(hdev, conn, NULL, 0);
++
+ break;
+ }
+
+@@ -4381,7 +4381,7 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, void *data,
+ * (since for this kind of commands there will not be a command
+ * complete event).
+ */
+- if (ev->status || (hdev->sent_cmd && !hci_skb_event(hdev->sent_cmd))) {
++ if (ev->status || (hdev->req_skb && !hci_skb_event(hdev->req_skb))) {
+ hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
+ req_complete_skb);
+ if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
+@@ -5010,8 +5010,9 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev, void *data,
+ bacpy(&cp.bdaddr, &conn->dst);
+ cp.pscan_rep_mode = 0x02;
+ hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
+- } else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
++ } else {
+ mgmt_device_connected(hdev, conn, NULL, 0);
++ }
+
+ if (!hci_outgoing_auth_needed(hdev, conn)) {
+ conn->state = BT_CONNECTED;
+@@ -5984,8 +5985,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
+ goto unlock;
+ }
+
+- if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+- mgmt_device_connected(hdev, conn, NULL, 0);
++ mgmt_device_connected(hdev, conn, NULL, 0);
+
+ conn->sec_level = BT_SECURITY_LOW;
+ conn->state = BT_CONFIG;
+@@ -7214,6 +7214,9 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data,
+ /* Notify iso layer */
+ hci_connect_cfm(pa_sync, 0x00);
+
++ /* Notify MGMT layer */
++ mgmt_device_connected(hdev, pa_sync, NULL, 0);
++
+ unlock:
+ hci_dev_unlock(hdev);
+ }
+@@ -7324,10 +7327,10 @@ static void hci_le_meta_evt(struct hci_dev *hdev, void *data,
+ bt_dev_dbg(hdev, "subevent 0x%2.2x", ev->subevent);
+
+ /* Only match event if command OGF is for LE */
+- if (hdev->sent_cmd &&
+- hci_opcode_ogf(hci_skb_opcode(hdev->sent_cmd)) == 0x08 &&
+- hci_skb_event(hdev->sent_cmd) == ev->subevent) {
+- *opcode = hci_skb_opcode(hdev->sent_cmd);
++ if (hdev->req_skb &&
++ hci_opcode_ogf(hci_skb_opcode(hdev->req_skb)) == 0x08 &&
++ hci_skb_event(hdev->req_skb) == ev->subevent) {
++ *opcode = hci_skb_opcode(hdev->req_skb);
+ hci_req_cmd_complete(hdev, *opcode, 0x00, req_complete,
+ req_complete_skb);
+ }
+@@ -7714,10 +7717,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
+ }
+
+ /* Only match event if command OGF is not for LE */
+- if (hdev->sent_cmd &&
+- hci_opcode_ogf(hci_skb_opcode(hdev->sent_cmd)) != 0x08 &&
+- hci_skb_event(hdev->sent_cmd) == event) {
+- hci_req_cmd_complete(hdev, hci_skb_opcode(hdev->sent_cmd),
++ if (hdev->req_skb &&
++ hci_opcode_ogf(hci_skb_opcode(hdev->req_skb)) != 0x08 &&
++ hci_skb_event(hdev->req_skb) == event) {
++ hci_req_cmd_complete(hdev, hci_skb_opcode(hdev->req_skb),
+ status, &req_complete, &req_complete_skb);
+ req_evt = event;
+ }
+diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
+index 6e023b0104b03..00e02138003ec 100644
+--- a/net/bluetooth/hci_request.c
++++ b/net/bluetooth/hci_request.c
+@@ -895,7 +895,7 @@ void hci_request_setup(struct hci_dev *hdev)
+
+ void hci_request_cancel_all(struct hci_dev *hdev)
+ {
+- __hci_cmd_sync_cancel(hdev, ENODEV);
++ hci_cmd_sync_cancel_sync(hdev, ENODEV);
+
+ cancel_interleave_scan(hdev);
+ }
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 5716345a26dfb..684a6ac02b80d 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -32,6 +32,10 @@ static void hci_cmd_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode,
+ hdev->req_result = result;
+ hdev->req_status = HCI_REQ_DONE;
+
++ /* Free the request command so it is not used as response */
++ kfree_skb(hdev->req_skb);
++ hdev->req_skb = NULL;
++
+ if (skb) {
+ struct sock *sk = hci_skb_sk(skb);
+
+@@ -39,7 +43,7 @@ static void hci_cmd_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode,
+ if (sk)
+ sock_put(sk);
+
+- hdev->req_skb = skb_get(skb);
++ hdev->req_rsp = skb_get(skb);
+ }
+
+ wake_up_interruptible(&hdev->req_wait_q);
+@@ -187,8 +191,8 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
+
+ hdev->req_status = 0;
+ hdev->req_result = 0;
+- skb = hdev->req_skb;
+- hdev->req_skb = NULL;
++ skb = hdev->req_rsp;
++ hdev->req_rsp = NULL;
+
+ bt_dev_dbg(hdev, "end: err %d", err);
+
+@@ -584,7 +588,7 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
+ mutex_unlock(&hdev->cmd_sync_work_lock);
+ }
+
+-void __hci_cmd_sync_cancel(struct hci_dev *hdev, int err)
++void hci_cmd_sync_cancel(struct hci_dev *hdev, int err)
+ {
+ bt_dev_dbg(hdev, "err 0x%2.2x", err);
+
+@@ -592,15 +596,17 @@ void __hci_cmd_sync_cancel(struct hci_dev *hdev, int err)
+ hdev->req_result = err;
+ hdev->req_status = HCI_REQ_CANCELED;
+
+- cancel_delayed_work_sync(&hdev->cmd_timer);
+- cancel_delayed_work_sync(&hdev->ncmd_timer);
+- atomic_set(&hdev->cmd_cnt, 1);
+-
+- wake_up_interruptible(&hdev->req_wait_q);
++ queue_work(hdev->workqueue, &hdev->cmd_sync_cancel_work);
+ }
+ }
++EXPORT_SYMBOL(hci_cmd_sync_cancel);
+
+-void hci_cmd_sync_cancel(struct hci_dev *hdev, int err)
++/* Cancel ongoing command request synchronously:
++ *
++ * - Set result and mark status to HCI_REQ_CANCELED
++ * - Wakeup command sync thread
++ */
++void hci_cmd_sync_cancel_sync(struct hci_dev *hdev, int err)
+ {
+ bt_dev_dbg(hdev, "err 0x%2.2x", err);
+
+@@ -608,10 +614,10 @@ void hci_cmd_sync_cancel(struct hci_dev *hdev, int err)
+ hdev->req_result = err;
+ hdev->req_status = HCI_REQ_CANCELED;
+
+- queue_work(hdev->workqueue, &hdev->cmd_sync_cancel_work);
++ wake_up_interruptible(&hdev->req_wait_q);
+ }
+ }
+-EXPORT_SYMBOL(hci_cmd_sync_cancel);
++EXPORT_SYMBOL(hci_cmd_sync_cancel_sync);
+
+ /* Submit HCI command to be run in as cmd_sync_work:
+ *
+@@ -4834,6 +4840,11 @@ int hci_dev_open_sync(struct hci_dev *hdev)
+ hdev->sent_cmd = NULL;
+ }
+
++ if (hdev->req_skb) {
++ kfree_skb(hdev->req_skb);
++ hdev->req_skb = NULL;
++ }
++
+ clear_bit(HCI_RUNNING, &hdev->flags);
+ hci_sock_dev_event(hdev, HCI_DEV_CLOSE);
+
+@@ -4994,6 +5005,12 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+ hdev->sent_cmd = NULL;
+ }
+
++ /* Drop last request */
++ if (hdev->req_skb) {
++ kfree_skb(hdev->req_skb);
++ hdev->req_skb = NULL;
++ }
++
+ clear_bit(HCI_RUNNING, &hdev->flags);
+ hci_sock_dev_event(hdev, HCI_DEV_CLOSE);
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 656f49b299d20..ab5a9d42fae71 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -39,8 +39,6 @@
+ #include <net/bluetooth/l2cap.h>
+
+ #include "smp.h"
+-#include "a2mp.h"
+-#include "amp.h"
+
+ #define LE_FLOWCTL_MAX_CREDITS 65535
+
+@@ -167,24 +165,6 @@ static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn,
+ return NULL;
+ }
+
+-static struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn,
+- u8 ident)
+-{
+- struct l2cap_chan *c;
+-
+- mutex_lock(&conn->chan_lock);
+- c = __l2cap_get_chan_by_ident(conn, ident);
+- if (c) {
+- /* Only lock if chan reference is not 0 */
+- c = l2cap_chan_hold_unless_zero(c);
+- if (c)
+- l2cap_chan_lock(c);
+- }
+- mutex_unlock(&conn->chan_lock);
+-
+- return c;
+-}
+-
+ static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src,
+ u8 src_type)
+ {
+@@ -651,7 +631,6 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
+ chan->ops->teardown(chan, err);
+
+ if (conn) {
+- struct amp_mgr *mgr = conn->hcon->amp_mgr;
+ /* Delete from channel list */
+ list_del(&chan->list);
+
+@@ -666,16 +645,6 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err)
+ if (chan->chan_type != L2CAP_CHAN_FIXED ||
+ test_bit(FLAG_HOLD_HCI_CONN, &chan->flags))
+ hci_conn_drop(conn->hcon);
+-
+- if (mgr && mgr->bredr_chan == chan)
+- mgr->bredr_chan = NULL;
+- }
+-
+- if (chan->hs_hchan) {
+- struct hci_chan *hs_hchan = chan->hs_hchan;
+-
+- BT_DBG("chan %p disconnect hs_hchan %p", chan, hs_hchan);
+- amp_disconnect_logical_link(hs_hchan);
+ }
+
+ if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state))
+@@ -977,12 +946,6 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
+ hci_send_acl(conn->hchan, skb, flags);
+ }
+
+-static bool __chan_is_moving(struct l2cap_chan *chan)
+-{
+- return chan->move_state != L2CAP_MOVE_STABLE &&
+- chan->move_state != L2CAP_MOVE_WAIT_PREPARE;
+-}
+-
+ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
+ {
+ struct hci_conn *hcon = chan->conn->hcon;
+@@ -991,15 +954,6 @@ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb)
+ BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len,
+ skb->priority);
+
+- if (chan->hs_hcon && !__chan_is_moving(chan)) {
+- if (chan->hs_hchan)
+- hci_send_acl(chan->hs_hchan, skb, ACL_COMPLETE);
+- else
+- kfree_skb(skb);
+-
+- return;
+- }
+-
+ /* Use NO_FLUSH for LE links (where this is the only option) or
+ * if the BR/EDR link supports it and flushing has not been
+ * explicitly requested (through FLAG_FLUSHABLE).
+@@ -1180,9 +1134,6 @@ static void l2cap_send_sframe(struct l2cap_chan *chan,
+ if (!control->sframe)
+ return;
+
+- if (__chan_is_moving(chan))
+- return;
+-
+ if (test_and_clear_bit(CONN_SEND_FBIT, &chan->conn_state) &&
+ !control->poll)
+ control->final = 1;
+@@ -1237,40 +1188,6 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan)
+ return !test_bit(CONF_CONNECT_PEND, &chan->conf_state);
+ }
+
+-static bool __amp_capable(struct l2cap_chan *chan)
+-{
+- struct l2cap_conn *conn = chan->conn;
+- struct hci_dev *hdev;
+- bool amp_available = false;
+-
+- if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
+- return false;
+-
+- if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP))
+- return false;
+-
+- read_lock(&hci_dev_list_lock);
+- list_for_each_entry(hdev, &hci_dev_list, list) {
+- if (hdev->amp_type != AMP_TYPE_BREDR &&
+- test_bit(HCI_UP, &hdev->flags)) {
+- amp_available = true;
+- break;
+- }
+- }
+- read_unlock(&hci_dev_list_lock);
+-
+- if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED)
+- return amp_available;
+-
+- return false;
+-}
+-
+-static bool l2cap_check_efs(struct l2cap_chan *chan)
+-{
+- /* Check EFS parameters */
+- return true;
+-}
+-
+ void l2cap_send_conn_req(struct l2cap_chan *chan)
+ {
+ struct l2cap_conn *conn = chan->conn;
+@@ -1286,76 +1203,6 @@ void l2cap_send_conn_req(struct l2cap_chan *chan)
+ l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_REQ, sizeof(req), &req);
+ }
+
+-static void l2cap_send_create_chan_req(struct l2cap_chan *chan, u8 amp_id)
+-{
+- struct l2cap_create_chan_req req;
+- req.scid = cpu_to_le16(chan->scid);
+- req.psm = chan->psm;
+- req.amp_id = amp_id;
+-
+- chan->ident = l2cap_get_ident(chan->conn);
+-
+- l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_REQ,
+- sizeof(req), &req);
+-}
+-
+-static void l2cap_move_setup(struct l2cap_chan *chan)
+-{
+- struct sk_buff *skb;
+-
+- BT_DBG("chan %p", chan);
+-
+- if (chan->mode != L2CAP_MODE_ERTM)
+- return;
+-
+- __clear_retrans_timer(chan);
+- __clear_monitor_timer(chan);
+- __clear_ack_timer(chan);
+-
+- chan->retry_count = 0;
+- skb_queue_walk(&chan->tx_q, skb) {
+- if (bt_cb(skb)->l2cap.retries)
+- bt_cb(skb)->l2cap.retries = 1;
+- else
+- break;
+- }
+-
+- chan->expected_tx_seq = chan->buffer_seq;
+-
+- clear_bit(CONN_REJ_ACT, &chan->conn_state);
+- clear_bit(CONN_SREJ_ACT, &chan->conn_state);
+- l2cap_seq_list_clear(&chan->retrans_list);
+- l2cap_seq_list_clear(&chan->srej_list);
+- skb_queue_purge(&chan->srej_q);
+-
+- chan->tx_state = L2CAP_TX_STATE_XMIT;
+- chan->rx_state = L2CAP_RX_STATE_MOVE;
+-
+- set_bit(CONN_REMOTE_BUSY, &chan->conn_state);
+-}
+-
+-static void l2cap_move_done(struct l2cap_chan *chan)
+-{
+- u8 move_role = chan->move_role;
+- BT_DBG("chan %p", chan);
+-
+- chan->move_state = L2CAP_MOVE_STABLE;
+- chan->move_role = L2CAP_MOVE_ROLE_NONE;
+-
+- if (chan->mode != L2CAP_MODE_ERTM)
+- return;
+-
+- switch (move_role) {
+- case L2CAP_MOVE_ROLE_INITIATOR:
+- l2cap_tx(chan, NULL, NULL, L2CAP_EV_EXPLICIT_POLL);
+- chan->rx_state = L2CAP_RX_STATE_WAIT_F;
+- break;
+- case L2CAP_MOVE_ROLE_RESPONDER:
+- chan->rx_state = L2CAP_RX_STATE_WAIT_P;
+- break;
+- }
+-}
+-
+ static void l2cap_chan_ready(struct l2cap_chan *chan)
+ {
+ /* The channel may have already been flagged as connected in
+@@ -1505,10 +1352,7 @@ static void l2cap_le_start(struct l2cap_chan *chan)
+
+ static void l2cap_start_connection(struct l2cap_chan *chan)
+ {
+- if (__amp_capable(chan)) {
+- BT_DBG("chan %p AMP capable: discover AMPs", chan);
+- a2mp_discover_amp(chan);
+- } else if (chan->conn->hcon->type == LE_LINK) {
++ if (chan->conn->hcon->type == LE_LINK) {
+ l2cap_le_start(chan);
+ } else {
+ l2cap_send_conn_req(chan);
+@@ -1611,11 +1455,6 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
+ __clear_ack_timer(chan);
+ }
+
+- if (chan->scid == L2CAP_CID_A2MP) {
+- l2cap_state_change(chan, BT_DISCONN);
+- return;
+- }
+-
+ req.dcid = cpu_to_le16(chan->dcid);
+ req.scid = cpu_to_le16(chan->scid);
+ l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
+@@ -1754,11 +1593,6 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
+
+ l2cap_chan_lock(chan);
+
+- if (chan->scid == L2CAP_CID_A2MP) {
+- l2cap_chan_unlock(chan);
+- continue;
+- }
+-
+ if (hcon->type == LE_LINK) {
+ l2cap_le_start(chan);
+ } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
+@@ -2067,9 +1901,6 @@ static void l2cap_streaming_send(struct l2cap_chan *chan,
+
+ BT_DBG("chan %p, skbs %p", chan, skbs);
+
+- if (__chan_is_moving(chan))
+- return;
+-
+ skb_queue_splice_tail_init(skbs, &chan->tx_q);
+
+ while (!skb_queue_empty(&chan->tx_q)) {
+@@ -2112,9 +1943,6 @@ static int l2cap_ertm_send(struct l2cap_chan *chan)
+ if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
+ return 0;
+
+- if (__chan_is_moving(chan))
+- return 0;
+-
+ while (chan->tx_send_head &&
+ chan->unacked_frames < chan->remote_tx_win &&
+ chan->tx_state == L2CAP_TX_STATE_XMIT) {
+@@ -2180,9 +2008,6 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan)
+ if (test_bit(CONN_REMOTE_BUSY, &chan->conn_state))
+ return;
+
+- if (__chan_is_moving(chan))
+- return;
+-
+ while (chan->retrans_list.head != L2CAP_SEQ_LIST_CLEAR) {
+ seq = l2cap_seq_list_pop(&chan->retrans_list);
+
+@@ -2522,8 +2347,7 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan,
+ pdu_len = chan->conn->mtu;
+
+ /* Constrain PDU size for BR/EDR connections */
+- if (!chan->hs_hcon)
+- pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
++ pdu_len = min_t(size_t, pdu_len, L2CAP_BREDR_MAX_PAYLOAD);
+
+ /* Adjust for largest possible L2CAP overhead. */
+ if (chan->fcs)
+@@ -3287,11 +3111,6 @@ int l2cap_ertm_init(struct l2cap_chan *chan)
+
+ skb_queue_head_init(&chan->tx_q);
+
+- chan->local_amp_id = AMP_ID_BREDR;
+- chan->move_id = AMP_ID_BREDR;
+- chan->move_state = L2CAP_MOVE_STABLE;
+- chan->move_role = L2CAP_MOVE_ROLE_NONE;
+-
+ if (chan->mode != L2CAP_MODE_ERTM)
+ return 0;
+
+@@ -3326,52 +3145,19 @@ static inline __u8 l2cap_select_mode(__u8 mode, __u16 remote_feat_mask)
+
+ static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
+ {
+- return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
+- (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW));
++ return (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW);
+ }
+
+ static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
+ {
+- return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
+- (conn->feat_mask & L2CAP_FEAT_EXT_FLOW));
++ return (conn->feat_mask & L2CAP_FEAT_EXT_FLOW);
+ }
+
+ static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
+ struct l2cap_conf_rfc *rfc)
+ {
+- if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) {
+- u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to;
+-
+- /* Class 1 devices have must have ERTM timeouts
+- * exceeding the Link Supervision Timeout. The
+- * default Link Supervision Timeout for AMP
+- * controllers is 10 seconds.
+- *
+- * Class 1 devices use 0xffffffff for their
+- * best-effort flush timeout, so the clamping logic
+- * will result in a timeout that meets the above
+- * requirement. ERTM timeouts are 16-bit values, so
+- * the maximum timeout is 65.535 seconds.
+- */
+-
+- /* Convert timeout to milliseconds and round */
+- ertm_to = DIV_ROUND_UP_ULL(ertm_to, 1000);
+-
+- /* This is the recommended formula for class 2 devices
+- * that start ERTM timers when packets are sent to the
+- * controller.
+- */
+- ertm_to = 3 * ertm_to + 500;
+-
+- if (ertm_to > 0xffff)
+- ertm_to = 0xffff;
+-
+- rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
+- rfc->monitor_timeout = rfc->retrans_timeout;
+- } else {
+- rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
+- rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+- }
++ rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
++ rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+ }
+
+ static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
+@@ -3623,13 +3409,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data
+ case L2CAP_CONF_EWS:
+ if (olen != 2)
+ break;
+- if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP))
+- return -ECONNREFUSED;
+- set_bit(FLAG_EXT_CTRL, &chan->flags);
+- set_bit(CONF_EWS_RECV, &chan->conf_state);
+- chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW;
+- chan->remote_tx_win = val;
+- break;
++ return -ECONNREFUSED;
+
+ default:
+ if (hint)
+@@ -4027,11 +3807,7 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
+ rsp.dcid = cpu_to_le16(chan->scid);
+ rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
+ rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+-
+- if (chan->hs_hcon)
+- rsp_code = L2CAP_CREATE_CHAN_RSP;
+- else
+- rsp_code = L2CAP_CONN_RSP;
++ rsp_code = L2CAP_CONN_RSP;
+
+ BT_DBG("chan %p rsp_code %u", chan, rsp_code);
+
+@@ -4190,7 +3966,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
+ chan->dst_type = bdaddr_dst_type(conn->hcon);
+ chan->psm = psm;
+ chan->dcid = scid;
+- chan->local_amp_id = amp_id;
+
+ __l2cap_chan_add(conn, chan);
+
+@@ -4516,10 +4291,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
+ /* check compatibility */
+
+ /* Send rsp for BR/EDR channel */
+- if (!chan->hs_hcon)
+- l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
+- else
+- chan->ident = cmd->ident;
++ l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags);
+ }
+
+ unlock:
+@@ -4571,15 +4343,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
+ goto done;
+ }
+
+- if (!chan->hs_hcon) {
+- l2cap_send_efs_conf_rsp(chan, buf, cmd->ident,
+- 0);
+- } else {
+- if (l2cap_check_efs(chan)) {
+- amp_create_logical_link(chan);
+- chan->ident = cmd->ident;
+- }
+- }
++ l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, 0);
+ }
+ goto done;
+
+@@ -4750,9 +4514,6 @@ static inline int l2cap_information_req(struct l2cap_conn *conn,
+ if (!disable_ertm)
+ feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
+ | L2CAP_FEAT_FCS;
+- if (conn->local_fixed_chan & L2CAP_FC_A2MP)
+- feat_mask |= L2CAP_FEAT_EXT_FLOW
+- | L2CAP_FEAT_EXT_WINDOW;
+
+ put_unaligned_le32(feat_mask, rsp->data);
+ l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
+@@ -4841,751 +4602,6 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn,
+ return 0;
+ }
+
+-static int l2cap_create_channel_req(struct l2cap_conn *conn,
+- struct l2cap_cmd_hdr *cmd,
+- u16 cmd_len, void *data)
+-{
+- struct l2cap_create_chan_req *req = data;
+- struct l2cap_create_chan_rsp rsp;
+- struct l2cap_chan *chan;
+- struct hci_dev *hdev;
+- u16 psm, scid;
+-
+- if (cmd_len != sizeof(*req))
+- return -EPROTO;
+-
+- if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
+- return -EINVAL;
+-
+- psm = le16_to_cpu(req->psm);
+- scid = le16_to_cpu(req->scid);
+-
+- BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id);
+-
+- /* For controller id 0 make BR/EDR connection */
+- if (req->amp_id == AMP_ID_BREDR) {
+- l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
+- req->amp_id);
+- return 0;
+- }
+-
+- /* Validate AMP controller id */
+- hdev = hci_dev_get(req->amp_id);
+- if (!hdev)
+- goto error;
+-
+- if (hdev->dev_type != HCI_AMP || !test_bit(HCI_UP, &hdev->flags)) {
+- hci_dev_put(hdev);
+- goto error;
+- }
+-
+- chan = l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP,
+- req->amp_id);
+- if (chan) {
+- struct amp_mgr *mgr = conn->hcon->amp_mgr;
+- struct hci_conn *hs_hcon;
+-
+- hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK,
+- &conn->hcon->dst);
+- if (!hs_hcon) {
+- hci_dev_put(hdev);
+- cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
+- chan->dcid);
+- return 0;
+- }
+-
+- BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
+-
+- mgr->bredr_chan = chan;
+- chan->hs_hcon = hs_hcon;
+- chan->fcs = L2CAP_FCS_NONE;
+- conn->mtu = hdev->block_mtu;
+- }
+-
+- hci_dev_put(hdev);
+-
+- return 0;
+-
+-error:
+- rsp.dcid = 0;
+- rsp.scid = cpu_to_le16(scid);
+- rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP);
+- rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+-
+- l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP,
+- sizeof(rsp), &rsp);
+-
+- return 0;
+-}
+-
+-static void l2cap_send_move_chan_req(struct l2cap_chan *chan, u8 dest_amp_id)
+-{
+- struct l2cap_move_chan_req req;
+- u8 ident;
+-
+- BT_DBG("chan %p, dest_amp_id %d", chan, dest_amp_id);
+-
+- ident = l2cap_get_ident(chan->conn);
+- chan->ident = ident;
+-
+- req.icid = cpu_to_le16(chan->scid);
+- req.dest_amp_id = dest_amp_id;
+-
+- l2cap_send_cmd(chan->conn, ident, L2CAP_MOVE_CHAN_REQ, sizeof(req),
+- &req);
+-
+- __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
+-}
+-
+-static void l2cap_send_move_chan_rsp(struct l2cap_chan *chan, u16 result)
+-{
+- struct l2cap_move_chan_rsp rsp;
+-
+- BT_DBG("chan %p, result 0x%4.4x", chan, result);
+-
+- rsp.icid = cpu_to_le16(chan->dcid);
+- rsp.result = cpu_to_le16(result);
+-
+- l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_RSP,
+- sizeof(rsp), &rsp);
+-}
+-
+-static void l2cap_send_move_chan_cfm(struct l2cap_chan *chan, u16 result)
+-{
+- struct l2cap_move_chan_cfm cfm;
+-
+- BT_DBG("chan %p, result 0x%4.4x", chan, result);
+-
+- chan->ident = l2cap_get_ident(chan->conn);
+-
+- cfm.icid = cpu_to_le16(chan->scid);
+- cfm.result = cpu_to_le16(result);
+-
+- l2cap_send_cmd(chan->conn, chan->ident, L2CAP_MOVE_CHAN_CFM,
+- sizeof(cfm), &cfm);
+-
+- __set_chan_timer(chan, L2CAP_MOVE_TIMEOUT);
+-}
+-
+-static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid)
+-{
+- struct l2cap_move_chan_cfm cfm;
+-
+- BT_DBG("conn %p, icid 0x%4.4x", conn, icid);
+-
+- cfm.icid = cpu_to_le16(icid);
+- cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED);
+-
+- l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM,
+- sizeof(cfm), &cfm);
+-}
+-
+-static void l2cap_send_move_chan_cfm_rsp(struct l2cap_conn *conn, u8 ident,
+- u16 icid)
+-{
+- struct l2cap_move_chan_cfm_rsp rsp;
+-
+- BT_DBG("icid 0x%4.4x", icid);
+-
+- rsp.icid = cpu_to_le16(icid);
+- l2cap_send_cmd(conn, ident, L2CAP_MOVE_CHAN_CFM_RSP, sizeof(rsp), &rsp);
+-}
+-
+-static void __release_logical_link(struct l2cap_chan *chan)
+-{
+- chan->hs_hchan = NULL;
+- chan->hs_hcon = NULL;
+-
+- /* Placeholder - release the logical link */
+-}
+-
+-static void l2cap_logical_fail(struct l2cap_chan *chan)
+-{
+- /* Logical link setup failed */
+- if (chan->state != BT_CONNECTED) {
+- /* Create channel failure, disconnect */
+- l2cap_send_disconn_req(chan, ECONNRESET);
+- return;
+- }
+-
+- switch (chan->move_role) {
+- case L2CAP_MOVE_ROLE_RESPONDER:
+- l2cap_move_done(chan);
+- l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_SUPP);
+- break;
+- case L2CAP_MOVE_ROLE_INITIATOR:
+- if (chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_COMP ||
+- chan->move_state == L2CAP_MOVE_WAIT_LOGICAL_CFM) {
+- /* Remote has only sent pending or
+- * success responses, clean up
+- */
+- l2cap_move_done(chan);
+- }
+-
+- /* Other amp move states imply that the move
+- * has already aborted
+- */
+- l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+- break;
+- }
+-}
+-
+-static void l2cap_logical_finish_create(struct l2cap_chan *chan,
+- struct hci_chan *hchan)
+-{
+- struct l2cap_conf_rsp rsp;
+-
+- chan->hs_hchan = hchan;
+- chan->hs_hcon->l2cap_data = chan->conn;
+-
+- l2cap_send_efs_conf_rsp(chan, &rsp, chan->ident, 0);
+-
+- if (test_bit(CONF_INPUT_DONE, &chan->conf_state)) {
+- int err;
+-
+- set_default_fcs(chan);
+-
+- err = l2cap_ertm_init(chan);
+- if (err < 0)
+- l2cap_send_disconn_req(chan, -err);
+- else
+- l2cap_chan_ready(chan);
+- }
+-}
+-
+-static void l2cap_logical_finish_move(struct l2cap_chan *chan,
+- struct hci_chan *hchan)
+-{
+- chan->hs_hcon = hchan->conn;
+- chan->hs_hcon->l2cap_data = chan->conn;
+-
+- BT_DBG("move_state %d", chan->move_state);
+-
+- switch (chan->move_state) {
+- case L2CAP_MOVE_WAIT_LOGICAL_COMP:
+- /* Move confirm will be sent after a success
+- * response is received
+- */
+- chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
+- break;
+- case L2CAP_MOVE_WAIT_LOGICAL_CFM:
+- if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
+- chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
+- } else if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
+- chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
+- l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
+- } else if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
+- chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
+- l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
+- }
+- break;
+- default:
+- /* Move was not in expected state, free the channel */
+- __release_logical_link(chan);
+-
+- chan->move_state = L2CAP_MOVE_STABLE;
+- }
+-}
+-
+-/* Call with chan locked */
+-void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
+- u8 status)
+-{
+- BT_DBG("chan %p, hchan %p, status %d", chan, hchan, status);
+-
+- if (status) {
+- l2cap_logical_fail(chan);
+- __release_logical_link(chan);
+- return;
+- }
+-
+- if (chan->state != BT_CONNECTED) {
+- /* Ignore logical link if channel is on BR/EDR */
+- if (chan->local_amp_id != AMP_ID_BREDR)
+- l2cap_logical_finish_create(chan, hchan);
+- } else {
+- l2cap_logical_finish_move(chan, hchan);
+- }
+-}
+-
+-void l2cap_move_start(struct l2cap_chan *chan)
+-{
+- BT_DBG("chan %p", chan);
+-
+- if (chan->local_amp_id == AMP_ID_BREDR) {
+- if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED)
+- return;
+- chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
+- chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
+- /* Placeholder - start physical link setup */
+- } else {
+- chan->move_role = L2CAP_MOVE_ROLE_INITIATOR;
+- chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
+- chan->move_id = 0;
+- l2cap_move_setup(chan);
+- l2cap_send_move_chan_req(chan, 0);
+- }
+-}
+-
+-static void l2cap_do_create(struct l2cap_chan *chan, int result,
+- u8 local_amp_id, u8 remote_amp_id)
+-{
+- BT_DBG("chan %p state %s %u -> %u", chan, state_to_string(chan->state),
+- local_amp_id, remote_amp_id);
+-
+- chan->fcs = L2CAP_FCS_NONE;
+-
+- /* Outgoing channel on AMP */
+- if (chan->state == BT_CONNECT) {
+- if (result == L2CAP_CR_SUCCESS) {
+- chan->local_amp_id = local_amp_id;
+- l2cap_send_create_chan_req(chan, remote_amp_id);
+- } else {
+- /* Revert to BR/EDR connect */
+- l2cap_send_conn_req(chan);
+- }
+-
+- return;
+- }
+-
+- /* Incoming channel on AMP */
+- if (__l2cap_no_conn_pending(chan)) {
+- struct l2cap_conn_rsp rsp;
+- char buf[128];
+- rsp.scid = cpu_to_le16(chan->dcid);
+- rsp.dcid = cpu_to_le16(chan->scid);
+-
+- if (result == L2CAP_CR_SUCCESS) {
+- /* Send successful response */
+- rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS);
+- rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+- } else {
+- /* Send negative response */
+- rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM);
+- rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
+- }
+-
+- l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP,
+- sizeof(rsp), &rsp);
+-
+- if (result == L2CAP_CR_SUCCESS) {
+- l2cap_state_change(chan, BT_CONFIG);
+- set_bit(CONF_REQ_SENT, &chan->conf_state);
+- l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
+- L2CAP_CONF_REQ,
+- l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
+- chan->num_conf_req++;
+- }
+- }
+-}
+-
+-static void l2cap_do_move_initiate(struct l2cap_chan *chan, u8 local_amp_id,
+- u8 remote_amp_id)
+-{
+- l2cap_move_setup(chan);
+- chan->move_id = local_amp_id;
+- chan->move_state = L2CAP_MOVE_WAIT_RSP;
+-
+- l2cap_send_move_chan_req(chan, remote_amp_id);
+-}
+-
+-static void l2cap_do_move_respond(struct l2cap_chan *chan, int result)
+-{
+- struct hci_chan *hchan = NULL;
+-
+- /* Placeholder - get hci_chan for logical link */
+-
+- if (hchan) {
+- if (hchan->state == BT_CONNECTED) {
+- /* Logical link is ready to go */
+- chan->hs_hcon = hchan->conn;
+- chan->hs_hcon->l2cap_data = chan->conn;
+- chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
+- l2cap_send_move_chan_rsp(chan, L2CAP_MR_SUCCESS);
+-
+- l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
+- } else {
+- /* Wait for logical link to be ready */
+- chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
+- }
+- } else {
+- /* Logical link not available */
+- l2cap_send_move_chan_rsp(chan, L2CAP_MR_NOT_ALLOWED);
+- }
+-}
+-
+-static void l2cap_do_move_cancel(struct l2cap_chan *chan, int result)
+-{
+- if (chan->move_role == L2CAP_MOVE_ROLE_RESPONDER) {
+- u8 rsp_result;
+- if (result == -EINVAL)
+- rsp_result = L2CAP_MR_BAD_ID;
+- else
+- rsp_result = L2CAP_MR_NOT_ALLOWED;
+-
+- l2cap_send_move_chan_rsp(chan, rsp_result);
+- }
+-
+- chan->move_role = L2CAP_MOVE_ROLE_NONE;
+- chan->move_state = L2CAP_MOVE_STABLE;
+-
+- /* Restart data transmission */
+- l2cap_ertm_send(chan);
+-}
+-
+-/* Invoke with locked chan */
+-void __l2cap_physical_cfm(struct l2cap_chan *chan, int result)
+-{
+- u8 local_amp_id = chan->local_amp_id;
+- u8 remote_amp_id = chan->remote_amp_id;
+-
+- BT_DBG("chan %p, result %d, local_amp_id %d, remote_amp_id %d",
+- chan, result, local_amp_id, remote_amp_id);
+-
+- if (chan->state == BT_DISCONN || chan->state == BT_CLOSED)
+- return;
+-
+- if (chan->state != BT_CONNECTED) {
+- l2cap_do_create(chan, result, local_amp_id, remote_amp_id);
+- } else if (result != L2CAP_MR_SUCCESS) {
+- l2cap_do_move_cancel(chan, result);
+- } else {
+- switch (chan->move_role) {
+- case L2CAP_MOVE_ROLE_INITIATOR:
+- l2cap_do_move_initiate(chan, local_amp_id,
+- remote_amp_id);
+- break;
+- case L2CAP_MOVE_ROLE_RESPONDER:
+- l2cap_do_move_respond(chan, result);
+- break;
+- default:
+- l2cap_do_move_cancel(chan, result);
+- break;
+- }
+- }
+-}
+-
+-static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
+- struct l2cap_cmd_hdr *cmd,
+- u16 cmd_len, void *data)
+-{
+- struct l2cap_move_chan_req *req = data;
+- struct l2cap_move_chan_rsp rsp;
+- struct l2cap_chan *chan;
+- u16 icid = 0;
+- u16 result = L2CAP_MR_NOT_ALLOWED;
+-
+- if (cmd_len != sizeof(*req))
+- return -EPROTO;
+-
+- icid = le16_to_cpu(req->icid);
+-
+- BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
+-
+- if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
+- return -EINVAL;
+-
+- chan = l2cap_get_chan_by_dcid(conn, icid);
+- if (!chan) {
+- rsp.icid = cpu_to_le16(icid);
+- rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED);
+- l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP,
+- sizeof(rsp), &rsp);
+- return 0;
+- }
+-
+- chan->ident = cmd->ident;
+-
+- if (chan->scid < L2CAP_CID_DYN_START ||
+- chan->chan_policy == BT_CHANNEL_POLICY_BREDR_ONLY ||
+- (chan->mode != L2CAP_MODE_ERTM &&
+- chan->mode != L2CAP_MODE_STREAMING)) {
+- result = L2CAP_MR_NOT_ALLOWED;
+- goto send_move_response;
+- }
+-
+- if (chan->local_amp_id == req->dest_amp_id) {
+- result = L2CAP_MR_SAME_ID;
+- goto send_move_response;
+- }
+-
+- if (req->dest_amp_id != AMP_ID_BREDR) {
+- struct hci_dev *hdev;
+- hdev = hci_dev_get(req->dest_amp_id);
+- if (!hdev || hdev->dev_type != HCI_AMP ||
+- !test_bit(HCI_UP, &hdev->flags)) {
+- if (hdev)
+- hci_dev_put(hdev);
+-
+- result = L2CAP_MR_BAD_ID;
+- goto send_move_response;
+- }
+- hci_dev_put(hdev);
+- }
+-
+- /* Detect a move collision. Only send a collision response
+- * if this side has "lost", otherwise proceed with the move.
+- * The winner has the larger bd_addr.
+- */
+- if ((__chan_is_moving(chan) ||
+- chan->move_role != L2CAP_MOVE_ROLE_NONE) &&
+- bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) {
+- result = L2CAP_MR_COLLISION;
+- goto send_move_response;
+- }
+-
+- chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
+- l2cap_move_setup(chan);
+- chan->move_id = req->dest_amp_id;
+-
+- if (req->dest_amp_id == AMP_ID_BREDR) {
+- /* Moving to BR/EDR */
+- if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) {
+- chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
+- result = L2CAP_MR_PEND;
+- } else {
+- chan->move_state = L2CAP_MOVE_WAIT_CONFIRM;
+- result = L2CAP_MR_SUCCESS;
+- }
+- } else {
+- chan->move_state = L2CAP_MOVE_WAIT_PREPARE;
+- /* Placeholder - uncomment when amp functions are available */
+- /*amp_accept_physical(chan, req->dest_amp_id);*/
+- result = L2CAP_MR_PEND;
+- }
+-
+-send_move_response:
+- l2cap_send_move_chan_rsp(chan, result);
+-
+- l2cap_chan_unlock(chan);
+- l2cap_chan_put(chan);
+-
+- return 0;
+-}
+-
+-static void l2cap_move_continue(struct l2cap_conn *conn, u16 icid, u16 result)
+-{
+- struct l2cap_chan *chan;
+- struct hci_chan *hchan = NULL;
+-
+- chan = l2cap_get_chan_by_scid(conn, icid);
+- if (!chan) {
+- l2cap_send_move_chan_cfm_icid(conn, icid);
+- return;
+- }
+-
+- __clear_chan_timer(chan);
+- if (result == L2CAP_MR_PEND)
+- __set_chan_timer(chan, L2CAP_MOVE_ERTX_TIMEOUT);
+-
+- switch (chan->move_state) {
+- case L2CAP_MOVE_WAIT_LOGICAL_COMP:
+- /* Move confirm will be sent when logical link
+- * is complete.
+- */
+- chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
+- break;
+- case L2CAP_MOVE_WAIT_RSP_SUCCESS:
+- if (result == L2CAP_MR_PEND) {
+- break;
+- } else if (test_bit(CONN_LOCAL_BUSY,
+- &chan->conn_state)) {
+- chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY;
+- } else {
+- /* Logical link is up or moving to BR/EDR,
+- * proceed with move
+- */
+- chan->move_state = L2CAP_MOVE_WAIT_CONFIRM_RSP;
+- l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
+- }
+- break;
+- case L2CAP_MOVE_WAIT_RSP:
+- /* Moving to AMP */
+- if (result == L2CAP_MR_SUCCESS) {
+- /* Remote is ready, send confirm immediately
+- * after logical link is ready
+- */
+- chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_CFM;
+- } else {
+- /* Both logical link and move success
+- * are required to confirm
+- */
+- chan->move_state = L2CAP_MOVE_WAIT_LOGICAL_COMP;
+- }
+-
+- /* Placeholder - get hci_chan for logical link */
+- if (!hchan) {
+- /* Logical link not available */
+- l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+- break;
+- }
+-
+- /* If the logical link is not yet connected, do not
+- * send confirmation.
+- */
+- if (hchan->state != BT_CONNECTED)
+- break;
+-
+- /* Logical link is already ready to go */
+-
+- chan->hs_hcon = hchan->conn;
+- chan->hs_hcon->l2cap_data = chan->conn;
+-
+- if (result == L2CAP_MR_SUCCESS) {
+- /* Can confirm now */
+- l2cap_send_move_chan_cfm(chan, L2CAP_MC_CONFIRMED);
+- } else {
+- /* Now only need move success
+- * to confirm
+- */
+- chan->move_state = L2CAP_MOVE_WAIT_RSP_SUCCESS;
+- }
+-
+- l2cap_logical_cfm(chan, hchan, L2CAP_MR_SUCCESS);
+- break;
+- default:
+- /* Any other amp move state means the move failed. */
+- chan->move_id = chan->local_amp_id;
+- l2cap_move_done(chan);
+- l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+- }
+-
+- l2cap_chan_unlock(chan);
+- l2cap_chan_put(chan);
+-}
+-
+-static void l2cap_move_fail(struct l2cap_conn *conn, u8 ident, u16 icid,
+- u16 result)
+-{
+- struct l2cap_chan *chan;
+-
+- chan = l2cap_get_chan_by_ident(conn, ident);
+- if (!chan) {
+- /* Could not locate channel, icid is best guess */
+- l2cap_send_move_chan_cfm_icid(conn, icid);
+- return;
+- }
+-
+- __clear_chan_timer(chan);
+-
+- if (chan->move_role == L2CAP_MOVE_ROLE_INITIATOR) {
+- if (result == L2CAP_MR_COLLISION) {
+- chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
+- } else {
+- /* Cleanup - cancel move */
+- chan->move_id = chan->local_amp_id;
+- l2cap_move_done(chan);
+- }
+- }
+-
+- l2cap_send_move_chan_cfm(chan, L2CAP_MC_UNCONFIRMED);
+-
+- l2cap_chan_unlock(chan);
+- l2cap_chan_put(chan);
+-}
+-
+-static int l2cap_move_channel_rsp(struct l2cap_conn *conn,
+- struct l2cap_cmd_hdr *cmd,
+- u16 cmd_len, void *data)
+-{
+- struct l2cap_move_chan_rsp *rsp = data;
+- u16 icid, result;
+-
+- if (cmd_len != sizeof(*rsp))
+- return -EPROTO;
+-
+- icid = le16_to_cpu(rsp->icid);
+- result = le16_to_cpu(rsp->result);
+-
+- BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
+-
+- if (result == L2CAP_MR_SUCCESS || result == L2CAP_MR_PEND)
+- l2cap_move_continue(conn, icid, result);
+- else
+- l2cap_move_fail(conn, cmd->ident, icid, result);
+-
+- return 0;
+-}
+-
+-static int l2cap_move_channel_confirm(struct l2cap_conn *conn,
+- struct l2cap_cmd_hdr *cmd,
+- u16 cmd_len, void *data)
+-{
+- struct l2cap_move_chan_cfm *cfm = data;
+- struct l2cap_chan *chan;
+- u16 icid, result;
+-
+- if (cmd_len != sizeof(*cfm))
+- return -EPROTO;
+-
+- icid = le16_to_cpu(cfm->icid);
+- result = le16_to_cpu(cfm->result);
+-
+- BT_DBG("icid 0x%4.4x, result 0x%4.4x", icid, result);
+-
+- chan = l2cap_get_chan_by_dcid(conn, icid);
+- if (!chan) {
+- /* Spec requires a response even if the icid was not found */
+- l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
+- return 0;
+- }
+-
+- if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) {
+- if (result == L2CAP_MC_CONFIRMED) {
+- chan->local_amp_id = chan->move_id;
+- if (chan->local_amp_id == AMP_ID_BREDR)
+- __release_logical_link(chan);
+- } else {
+- chan->move_id = chan->local_amp_id;
+- }
+-
+- l2cap_move_done(chan);
+- }
+-
+- l2cap_send_move_chan_cfm_rsp(conn, cmd->ident, icid);
+-
+- l2cap_chan_unlock(chan);
+- l2cap_chan_put(chan);
+-
+- return 0;
+-}
+-
+-static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
+- struct l2cap_cmd_hdr *cmd,
+- u16 cmd_len, void *data)
+-{
+- struct l2cap_move_chan_cfm_rsp *rsp = data;
+- struct l2cap_chan *chan;
+- u16 icid;
+-
+- if (cmd_len != sizeof(*rsp))
+- return -EPROTO;
+-
+- icid = le16_to_cpu(rsp->icid);
+-
+- BT_DBG("icid 0x%4.4x", icid);
+-
+- chan = l2cap_get_chan_by_scid(conn, icid);
+- if (!chan)
+- return 0;
+-
+- __clear_chan_timer(chan);
+-
+- if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) {
+- chan->local_amp_id = chan->move_id;
+-
+- if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan)
+- __release_logical_link(chan);
+-
+- l2cap_move_done(chan);
+- }
+-
+- l2cap_chan_unlock(chan);
+- l2cap_chan_put(chan);
+-
+- return 0;
+-}
+-
+ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn,
+ struct l2cap_cmd_hdr *cmd,
+ u16 cmd_len, u8 *data)
+@@ -5745,7 +4761,6 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
+ break;
+
+ case L2CAP_CONN_RSP:
+- case L2CAP_CREATE_CHAN_RSP:
+ l2cap_connect_create_rsp(conn, cmd, cmd_len, data);
+ break;
+
+@@ -5780,26 +4795,6 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
+ l2cap_information_rsp(conn, cmd, cmd_len, data);
+ break;
+
+- case L2CAP_CREATE_CHAN_REQ:
+- err = l2cap_create_channel_req(conn, cmd, cmd_len, data);
+- break;
+-
+- case L2CAP_MOVE_CHAN_REQ:
+- err = l2cap_move_channel_req(conn, cmd, cmd_len, data);
+- break;
+-
+- case L2CAP_MOVE_CHAN_RSP:
+- l2cap_move_channel_rsp(conn, cmd, cmd_len, data);
+- break;
+-
+- case L2CAP_MOVE_CHAN_CFM:
+- err = l2cap_move_channel_confirm(conn, cmd, cmd_len, data);
+- break;
+-
+- case L2CAP_MOVE_CHAN_CFM_RSP:
+- l2cap_move_channel_confirm_rsp(conn, cmd, cmd_len, data);
+- break;
+-
+ default:
+ BT_ERR("Unknown BR/EDR signaling command 0x%2.2x", cmd->code);
+ err = -EINVAL;
+@@ -7051,8 +6046,8 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,
+ if (control->final) {
+ clear_bit(CONN_REMOTE_BUSY, &chan->conn_state);
+
+- if (!test_and_clear_bit(CONN_REJ_ACT, &chan->conn_state) &&
+- !__chan_is_moving(chan)) {
++ if (!test_and_clear_bit(CONN_REJ_ACT,
++ &chan->conn_state)) {
+ control->final = 0;
+ l2cap_retransmit_all(chan, control);
+ }
+@@ -7245,11 +6240,7 @@ static int l2cap_finish_move(struct l2cap_chan *chan)
+ BT_DBG("chan %p", chan);
+
+ chan->rx_state = L2CAP_RX_STATE_RECV;
+-
+- if (chan->hs_hcon)
+- chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
+- else
+- chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
++ chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
+
+ return l2cap_resegment(chan);
+ }
+@@ -7316,11 +6307,7 @@ static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
+ */
+ chan->next_tx_seq = control->reqseq;
+ chan->unacked_frames = 0;
+-
+- if (chan->hs_hcon)
+- chan->conn->mtu = chan->hs_hcon->hdev->block_mtu;
+- else
+- chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
++ chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
+
+ err = l2cap_resegment(chan);
+
+@@ -7672,21 +6659,10 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
+
+ chan = l2cap_get_chan_by_scid(conn, cid);
+ if (!chan) {
+- if (cid == L2CAP_CID_A2MP) {
+- chan = a2mp_channel_create(conn, skb);
+- if (!chan) {
+- kfree_skb(skb);
+- return;
+- }
+-
+- l2cap_chan_hold(chan);
+- l2cap_chan_lock(chan);
+- } else {
+- BT_DBG("unknown cid 0x%4.4x", cid);
+- /* Drop packet and return */
+- kfree_skb(skb);
+- return;
+- }
++ BT_DBG("unknown cid 0x%4.4x", cid);
++ /* Drop packet and return */
++ kfree_skb(skb);
++ return;
+ }
+
+ BT_DBG("chan %p, len %d", chan, skb->len);
+@@ -7887,10 +6863,6 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
+
+ conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
+
+- if (hcon->type == ACL_LINK &&
+- hci_dev_test_flag(hcon->hdev, HCI_HS_ENABLED))
+- conn->local_fixed_chan |= L2CAP_FC_A2MP;
+-
+ if (hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED) &&
+ (bredr_sc_enabled(hcon->hdev) ||
+ hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP)))
+@@ -8355,11 +7327,6 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
+ BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid,
+ state_to_string(chan->state));
+
+- if (chan->scid == L2CAP_CID_A2MP) {
+- l2cap_chan_unlock(chan);
+- continue;
+- }
+-
+ if (!status && encrypt)
+ chan->sec_level = hcon->sec_level;
+
+diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
+index e50d3d102078e..ee7a41d6994fc 100644
+--- a/net/bluetooth/l2cap_sock.c
++++ b/net/bluetooth/l2cap_sock.c
+@@ -1027,23 +1027,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (opt > BT_CHANNEL_POLICY_AMP_PREFERRED) {
+- err = -EINVAL;
+- break;
+- }
+-
+- if (chan->mode != L2CAP_MODE_ERTM &&
+- chan->mode != L2CAP_MODE_STREAMING) {
+- err = -EOPNOTSUPP;
+- break;
+- }
+-
+- chan->chan_policy = (u8) opt;
+-
+- if (sk->sk_state == BT_CONNECTED &&
+- chan->move_role == L2CAP_MOVE_ROLE_NONE)
+- l2cap_move_start(chan);
+-
++ err = -EOPNOTSUPP;
+ break;
+
+ case BT_SNDMTU:
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index ee3b4aad8bd8d..640d6d54ac6ba 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -835,8 +835,6 @@ static u32 get_supported_settings(struct hci_dev *hdev)
+
+ if (lmp_ssp_capable(hdev)) {
+ settings |= MGMT_SETTING_SSP;
+- if (IS_ENABLED(CONFIG_BT_HS))
+- settings |= MGMT_SETTING_HS;
+ }
+
+ if (lmp_sc_capable(hdev))
+@@ -901,9 +899,6 @@ static u32 get_current_settings(struct hci_dev *hdev)
+ if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
+ settings |= MGMT_SETTING_SSP;
+
+- if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
+- settings |= MGMT_SETTING_HS;
+-
+ if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
+ settings |= MGMT_SETTING_ADVERTISING;
+
+@@ -1409,7 +1404,7 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
+
+ /* Cancel potentially blocking sync operation before power off */
+ if (cp->val == 0x00) {
+- __hci_cmd_sync_cancel(hdev, -EHOSTDOWN);
++ hci_cmd_sync_cancel_sync(hdev, -EHOSTDOWN);
+ err = hci_cmd_sync_queue(hdev, set_powered_sync, cmd,
+ mgmt_set_powered_complete);
+ } else {
+@@ -1930,7 +1925,6 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
+
+ if (enable && hci_dev_test_and_clear_flag(hdev,
+ HCI_SSP_ENABLED)) {
+- hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
+ new_settings(hdev, NULL);
+ }
+
+@@ -1943,12 +1937,6 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
+ changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
+ } else {
+ changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
+-
+- if (!changed)
+- changed = hci_dev_test_and_clear_flag(hdev,
+- HCI_HS_ENABLED);
+- else
+- hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
+ }
+
+ mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
+@@ -2012,11 +2000,6 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
+ } else {
+ changed = hci_dev_test_and_clear_flag(hdev,
+ HCI_SSP_ENABLED);
+- if (!changed)
+- changed = hci_dev_test_and_clear_flag(hdev,
+- HCI_HS_ENABLED);
+- else
+- hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
+ }
+
+ err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
+@@ -2062,63 +2045,10 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
+
+ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
+ {
+- struct mgmt_mode *cp = data;
+- bool changed;
+- u8 status;
+- int err;
+-
+ bt_dev_dbg(hdev, "sock %p", sk);
+
+- if (!IS_ENABLED(CONFIG_BT_HS))
+- return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
++ return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
+ MGMT_STATUS_NOT_SUPPORTED);
+-
+- status = mgmt_bredr_support(hdev);
+- if (status)
+- return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
+-
+- if (!lmp_ssp_capable(hdev))
+- return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
+- MGMT_STATUS_NOT_SUPPORTED);
+-
+- if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
+- return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
+- MGMT_STATUS_REJECTED);
+-
+- if (cp->val != 0x00 && cp->val != 0x01)
+- return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
+- MGMT_STATUS_INVALID_PARAMS);
+-
+- hci_dev_lock(hdev);
+-
+- if (pending_find(MGMT_OP_SET_SSP, hdev)) {
+- err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
+- MGMT_STATUS_BUSY);
+- goto unlock;
+- }
+-
+- if (cp->val) {
+- changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
+- } else {
+- if (hdev_is_powered(hdev)) {
+- err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
+- MGMT_STATUS_REJECTED);
+- goto unlock;
+- }
+-
+- changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
+- }
+-
+- err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
+- if (err < 0)
+- goto unlock;
+-
+- if (changed)
+- err = new_settings(hdev, sk);
+-
+-unlock:
+- hci_dev_unlock(hdev);
+- return err;
+ }
+
+ static void set_le_complete(struct hci_dev *hdev, void *data, int err)
+@@ -3188,6 +3118,7 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
+ static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
+ {
+ switch (link_type) {
++ case ISO_LINK:
+ case LE_LINK:
+ switch (addr_type) {
+ case ADDR_LE_DEV_PUBLIC:
+@@ -6766,7 +6697,6 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
+ hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
+ hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
+ hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
+- hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
+ }
+
+ hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
+@@ -8470,7 +8400,7 @@ static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
+
+ static u8 calculate_name_len(struct hci_dev *hdev)
+ {
+- u8 buf[HCI_MAX_SHORT_NAME_LENGTH + 3];
++ u8 buf[HCI_MAX_SHORT_NAME_LENGTH + 2]; /* len + type + name */
+
+ return eir_append_local_name(hdev, buf, 0);
+ }
+@@ -9681,6 +9611,9 @@ void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
+ u16 eir_len = 0;
+ u32 flags = 0;
+
++ if (test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
++ return;
++
+ /* allocate buff for LE or BR/EDR adv */
+ if (conn->le_adv_data_len > 0)
+ skb = mgmt_alloc_skb(hdev, MGMT_EV_DEVICE_CONNECTED,
+@@ -9766,14 +9699,6 @@ void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ struct mgmt_ev_device_disconnected ev;
+ struct sock *sk = NULL;
+
+- /* The connection is still in hci_conn_hash so test for 1
+- * instead of 0 to know if this is the last one.
+- */
+- if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
+- cancel_delayed_work(&hdev->power_off);
+- queue_work(hdev->req_workqueue, &hdev->power_off.work);
+- }
+-
+ if (!mgmt_connected)
+ return;
+
+@@ -9830,14 +9755,6 @@ void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+ {
+ struct mgmt_ev_connect_failed ev;
+
+- /* The connection is still in hci_conn_hash so test for 1
+- * instead of 0 to know if this is the last one.
+- */
+- if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
+- cancel_delayed_work(&hdev->power_off);
+- queue_work(hdev->req_workqueue, &hdev->power_off.work);
+- }
+-
+ bacpy(&ev.addr.bdaddr, bdaddr);
+ ev.addr.type = link_to_bdaddr(link_type, addr_type);
+ ev.status = mgmt_status(status);
+diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
+index 630e3023273b2..9612c5d1b13f6 100644
+--- a/net/bluetooth/msft.c
++++ b/net/bluetooth/msft.c
+@@ -875,6 +875,7 @@ static int msft_add_address_filter_sync(struct hci_dev *hdev, void *data)
+ remove = true;
+ goto done;
+ }
++
+ cp->sub_opcode = MSFT_OP_LE_MONITOR_ADVERTISEMENT;
+ cp->rssi_high = address_filter->rssi_high;
+ cp->rssi_low = address_filter->rssi_low;
+@@ -887,6 +888,8 @@ static int msft_add_address_filter_sync(struct hci_dev *hdev, void *data)
+
+ skb = __hci_cmd_sync(hdev, hdev->msft_opcode, size, cp,
+ HCI_CMD_TIMEOUT);
++ kfree(cp);
++
+ if (IS_ERR(skb)) {
+ bt_dev_err(hdev, "Failed to enable address %pMR filter",
+ &address_filter->bdaddr);
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 76e6438f4858e..c9b8412f1c9d3 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -2261,7 +2261,7 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
+ rcu_read_lock();
+ again:
+ list_for_each_entry_rcu(ptype, ptype_list, list) {
+- if (ptype->ignore_outgoing)
++ if (READ_ONCE(ptype->ignore_outgoing))
+ continue;
+
+ /* Never send packets back to the socket
+@@ -6708,6 +6708,8 @@ static int napi_threaded_poll(void *data)
+ void *have;
+
+ while (!napi_thread_wait(napi)) {
++ unsigned long last_qs = jiffies;
++
+ for (;;) {
+ bool repoll = false;
+
+@@ -6732,6 +6734,7 @@ static int napi_threaded_poll(void *data)
+ if (!repoll)
+ break;
+
++ rcu_softirq_qs_periodic(last_qs);
+ cond_resched();
+ }
+ }
+@@ -11631,11 +11634,12 @@ static void __init net_dev_struct_check(void)
+
+ /* TXRX read-mostly hotpath */
+ CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, lstats);
++ CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, state);
+ CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, flags);
+ CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, hard_header_len);
+ CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, features);
+ CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_txrx, ip6_ptr);
+- CACHELINE_ASSERT_GROUP_SIZE(struct net_device, net_device_read_txrx, 38);
++ CACHELINE_ASSERT_GROUP_SIZE(struct net_device, net_device_read_txrx, 46);
+
+ /* RX read-mostly hotpath */
+ CACHELINE_ASSERT_GROUP_MEMBER(struct net_device, net_device_read_rx, ptype_specific);
+diff --git a/net/core/gso_test.c b/net/core/gso_test.c
+index 4c2e77bd12f4b..358c44680d917 100644
+--- a/net/core/gso_test.c
++++ b/net/core/gso_test.c
+@@ -225,7 +225,7 @@ static void gso_test_func(struct kunit *test)
+
+ segs = skb_segment(skb, features);
+ if (IS_ERR(segs)) {
+- KUNIT_FAIL(test, "segs error %lld", PTR_ERR(segs));
++ KUNIT_FAIL(test, "segs error %pe", segs);
+ goto free_gso_skb;
+ } else if (!segs) {
+ KUNIT_FAIL(test, "no segments");
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index edbbef563d4d9..71dee435d549d 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -6736,6 +6736,14 @@ static struct skb_ext *skb_ext_maybe_cow(struct skb_ext *old,
+ for (i = 0; i < sp->len; i++)
+ xfrm_state_hold(sp->xvec[i]);
+ }
++#endif
++#ifdef CONFIG_MCTP_FLOWS
++ if (old_active & (1 << SKB_EXT_MCTP)) {
++ struct mctp_flow *flow = skb_ext_get_ptr(old, SKB_EXT_MCTP);
++
++ if (flow->key)
++ refcount_inc(&flow->key->refs);
++ }
+ #endif
+ __skb_ext_put(old);
+ return new;
+diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c
+index b1e29e18d1d60..c53b731f2d672 100644
+--- a/net/core/sock_diag.c
++++ b/net/core/sock_diag.c
+@@ -193,7 +193,7 @@ int sock_diag_register(const struct sock_diag_handler *hndl)
+ if (sock_diag_handlers[hndl->family])
+ err = -EBUSY;
+ else
+- sock_diag_handlers[hndl->family] = hndl;
++ WRITE_ONCE(sock_diag_handlers[hndl->family], hndl);
+ mutex_unlock(&sock_diag_table_mutex);
+
+ return err;
+@@ -209,7 +209,7 @@ void sock_diag_unregister(const struct sock_diag_handler *hnld)
+
+ mutex_lock(&sock_diag_table_mutex);
+ BUG_ON(sock_diag_handlers[family] != hnld);
+- sock_diag_handlers[family] = NULL;
++ WRITE_ONCE(sock_diag_handlers[family], NULL);
+ mutex_unlock(&sock_diag_table_mutex);
+ }
+ EXPORT_SYMBOL_GPL(sock_diag_unregister);
+@@ -227,7 +227,7 @@ static int __sock_diag_cmd(struct sk_buff *skb, struct nlmsghdr *nlh)
+ return -EINVAL;
+ req->sdiag_family = array_index_nospec(req->sdiag_family, AF_MAX);
+
+- if (sock_diag_handlers[req->sdiag_family] == NULL)
++ if (READ_ONCE(sock_diag_handlers[req->sdiag_family]) == NULL)
+ sock_load_diag_module(req->sdiag_family, 0);
+
+ mutex_lock(&sock_diag_table_mutex);
+@@ -286,12 +286,12 @@ static int sock_diag_bind(struct net *net, int group)
+ switch (group) {
+ case SKNLGRP_INET_TCP_DESTROY:
+ case SKNLGRP_INET_UDP_DESTROY:
+- if (!sock_diag_handlers[AF_INET])
++ if (!READ_ONCE(sock_diag_handlers[AF_INET]))
+ sock_load_diag_module(AF_INET, 0);
+ break;
+ case SKNLGRP_INET6_TCP_DESTROY:
+ case SKNLGRP_INET6_UDP_DESTROY:
+- if (!sock_diag_handlers[AF_INET6])
++ if (!READ_ONCE(sock_diag_handlers[AF_INET6]))
+ sock_load_diag_module(AF_INET6, 0);
+ break;
+ }
+diff --git a/net/devlink/netlink.c b/net/devlink/netlink.c
+index 499885c8b9cae..593605c1b1ef4 100644
+--- a/net/devlink/netlink.c
++++ b/net/devlink/netlink.c
+@@ -193,12 +193,13 @@ devlink_get_from_attrs_lock(struct net *net, struct nlattr **attrs,
+ devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
+
+ devlinks_xa_for_each_registered_get(net, index, devlink) {
+- devl_dev_lock(devlink, dev_lock);
+- if (devl_is_registered(devlink) &&
+- strcmp(devlink->dev->bus->name, busname) == 0 &&
+- strcmp(dev_name(devlink->dev), devname) == 0)
+- return devlink;
+- devl_dev_unlock(devlink, dev_lock);
++ if (strcmp(devlink->dev->bus->name, busname) == 0 &&
++ strcmp(dev_name(devlink->dev), devname) == 0) {
++ devl_dev_lock(devlink, dev_lock);
++ if (devl_is_registered(devlink))
++ return devlink;
++ devl_dev_unlock(devlink, dev_lock);
++ }
+ devlink_put(devlink);
+ }
+
+diff --git a/net/devlink/netlink_gen.c b/net/devlink/netlink_gen.c
+index c81cf2dd154f3..f9786d51f68f9 100644
+--- a/net/devlink/netlink_gen.c
++++ b/net/devlink/netlink_gen.c
+@@ -198,7 +198,7 @@ static const struct nla_policy devlink_eswitch_set_nl_policy[DEVLINK_ATTR_ESWITC
+ [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
+ [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
+ [DEVLINK_ATTR_ESWITCH_MODE] = NLA_POLICY_MAX(NLA_U16, 1),
+- [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = NLA_POLICY_MAX(NLA_U16, 3),
++ [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = NLA_POLICY_MAX(NLA_U8, 3),
+ [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = NLA_POLICY_MAX(NLA_U8, 1),
+ };
+
+diff --git a/net/devlink/port.c b/net/devlink/port.c
+index 4b2d46ccfe484..118d130d2afd5 100644
+--- a/net/devlink/port.c
++++ b/net/devlink/port.c
+@@ -889,7 +889,7 @@ int devlink_nl_port_new_doit(struct sk_buff *skb, struct genl_info *info)
+ err = -ENOMEM;
+ goto err_out_port_del;
+ }
+- err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_NEW,
++ err = devlink_nl_port_fill(msg, devlink_port, DEVLINK_CMD_PORT_NEW,
+ info->snd_portid, info->snd_seq, 0, NULL);
+ if (WARN_ON_ONCE(err))
+ goto err_out_msg_free;
+diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
+index 6d14d935ee828..26329db09210b 100644
+--- a/net/hsr/hsr_framereg.c
++++ b/net/hsr/hsr_framereg.c
+@@ -228,6 +228,10 @@ struct hsr_node *hsr_get_node(struct hsr_port *port, struct list_head *node_db,
+ */
+ if (ethhdr->h_proto == htons(ETH_P_PRP) ||
+ ethhdr->h_proto == htons(ETH_P_HSR)) {
++ /* Check if skb contains hsr_ethhdr */
++ if (skb->mac_len < sizeof(struct hsr_ethhdr))
++ return NULL;
++
+ /* Use the existing sequence_nr from the tag as starting point
+ * for filtering duplicate frames.
+ */
+diff --git a/net/hsr/hsr_main.c b/net/hsr/hsr_main.c
+index cb83c8feb7465..9756e657bab97 100644
+--- a/net/hsr/hsr_main.c
++++ b/net/hsr/hsr_main.c
+@@ -148,14 +148,21 @@ static struct notifier_block hsr_nb = {
+
+ static int __init hsr_init(void)
+ {
+- int res;
++ int err;
+
+ BUILD_BUG_ON(sizeof(struct hsr_tag) != HSR_HLEN);
+
+- register_netdevice_notifier(&hsr_nb);
+- res = hsr_netlink_init();
++ err = register_netdevice_notifier(&hsr_nb);
++ if (err)
++ return err;
++
++ err = hsr_netlink_init();
++ if (err) {
++ unregister_netdevice_notifier(&hsr_nb);
++ return err;
++ }
+
+- return res;
++ return 0;
+ }
+
+ static void __exit hsr_exit(void)
+diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
+index 8e6b6aa0579e1..9804e9608a5a0 100644
+--- a/net/ipv4/inet_diag.c
++++ b/net/ipv4/inet_diag.c
+@@ -57,7 +57,7 @@ static const struct inet_diag_handler *inet_diag_lock_handler(int proto)
+ return ERR_PTR(-ENOENT);
+ }
+
+- if (!inet_diag_table[proto])
++ if (!READ_ONCE(inet_diag_table[proto]))
+ sock_load_diag_module(AF_INET, proto);
+
+ mutex_lock(&inet_diag_table_mutex);
+@@ -1503,7 +1503,7 @@ int inet_diag_register(const struct inet_diag_handler *h)
+ mutex_lock(&inet_diag_table_mutex);
+ err = -EEXIST;
+ if (!inet_diag_table[type]) {
+- inet_diag_table[type] = h;
++ WRITE_ONCE(inet_diag_table[type], h);
+ err = 0;
+ }
+ mutex_unlock(&inet_diag_table_mutex);
+@@ -1520,7 +1520,7 @@ void inet_diag_unregister(const struct inet_diag_handler *h)
+ return;
+
+ mutex_lock(&inet_diag_table_mutex);
+- inet_diag_table[type] = NULL;
++ WRITE_ONCE(inet_diag_table[type], NULL);
+ mutex_unlock(&inet_diag_table_mutex);
+ }
+ EXPORT_SYMBOL_GPL(inet_diag_unregister);
+diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
+index 308ff34002ea6..4e470f18487f6 100644
+--- a/net/ipv4/inet_hashtables.c
++++ b/net/ipv4/inet_hashtables.c
+@@ -1136,7 +1136,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
+ sock_prot_inuse_add(net, sk->sk_prot, -1);
+
+ spin_lock(lock);
+- sk_nulls_del_node_init_rcu(sk);
++ __sk_nulls_del_node_init_rcu(sk);
+ spin_unlock(lock);
+
+ sk->sk_hash = 0;
+diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
+index 5befa4de5b241..e8de45d34d56a 100644
+--- a/net/ipv4/inet_timewait_sock.c
++++ b/net/ipv4/inet_timewait_sock.c
+@@ -263,12 +263,12 @@ void __inet_twsk_schedule(struct inet_timewait_sock *tw, int timeo, bool rearm)
+ }
+ EXPORT_SYMBOL_GPL(__inet_twsk_schedule);
+
++/* Remove all non full sockets (TIME_WAIT and NEW_SYN_RECV) for dead netns */
+ void inet_twsk_purge(struct inet_hashinfo *hashinfo, int family)
+ {
+- struct inet_timewait_sock *tw;
+- struct sock *sk;
+ struct hlist_nulls_node *node;
+ unsigned int slot;
++ struct sock *sk;
+
+ for (slot = 0; slot <= hashinfo->ehash_mask; slot++) {
+ struct inet_ehash_bucket *head = &hashinfo->ehash[slot];
+@@ -277,38 +277,35 @@ void inet_twsk_purge(struct inet_hashinfo *hashinfo, int family)
+ rcu_read_lock();
+ restart:
+ sk_nulls_for_each_rcu(sk, node, &head->chain) {
+- if (sk->sk_state != TCP_TIME_WAIT) {
+- /* A kernel listener socket might not hold refcnt for net,
+- * so reqsk_timer_handler() could be fired after net is
+- * freed. Userspace listener and reqsk never exist here.
+- */
+- if (unlikely(sk->sk_state == TCP_NEW_SYN_RECV &&
+- hashinfo->pernet)) {
+- struct request_sock *req = inet_reqsk(sk);
+-
+- inet_csk_reqsk_queue_drop_and_put(req->rsk_listener, req);
+- }
++ int state = inet_sk_state_load(sk);
+
++ if ((1 << state) & ~(TCPF_TIME_WAIT |
++ TCPF_NEW_SYN_RECV))
+ continue;
+- }
+
+- tw = inet_twsk(sk);
+- if ((tw->tw_family != family) ||
+- refcount_read(&twsk_net(tw)->ns.count))
++ if (sk->sk_family != family ||
++ refcount_read(&sock_net(sk)->ns.count))
+ continue;
+
+- if (unlikely(!refcount_inc_not_zero(&tw->tw_refcnt)))
++ if (unlikely(!refcount_inc_not_zero(&sk->sk_refcnt)))
+ continue;
+
+- if (unlikely((tw->tw_family != family) ||
+- refcount_read(&twsk_net(tw)->ns.count))) {
+- inet_twsk_put(tw);
++ if (unlikely(sk->sk_family != family ||
++ refcount_read(&sock_net(sk)->ns.count))) {
++ sock_gen_put(sk);
+ goto restart;
+ }
+
+ rcu_read_unlock();
+ local_bh_disable();
+- inet_twsk_deschedule_put(tw);
++ if (state == TCP_TIME_WAIT) {
++ inet_twsk_deschedule_put(inet_twsk(sk));
++ } else {
++ struct request_sock *req = inet_reqsk(sk);
++
++ inet_csk_reqsk_queue_drop_and_put(req->rsk_listener,
++ req);
++ }
+ local_bh_enable();
+ goto restart_rcu;
+ }
+diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
+index 1b6981de3f295..7af36e4f1647d 100644
+--- a/net/ipv4/ip_tunnel.c
++++ b/net/ipv4/ip_tunnel.c
+@@ -378,7 +378,7 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
+ bool log_ecn_error)
+ {
+ const struct iphdr *iph = ip_hdr(skb);
+- int err;
++ int nh, err;
+
+ #ifdef CONFIG_NET_IPGRE_BROADCAST
+ if (ipv4_is_multicast(iph->daddr)) {
+@@ -404,8 +404,21 @@ int ip_tunnel_rcv(struct ip_tunnel *tunnel, struct sk_buff *skb,
+ tunnel->i_seqno = ntohl(tpi->seq) + 1;
+ }
+
++ /* Save offset of outer header relative to skb->head,
++ * because we are going to reset the network header to the inner header
++ * and might change skb->head.
++ */
++ nh = skb_network_header(skb) - skb->head;
++
+ skb_set_network_header(skb, (tunnel->dev->type == ARPHRD_ETHER) ? ETH_HLEN : 0);
+
++ if (!pskb_inet_may_pull(skb)) {
++ DEV_STATS_INC(tunnel->dev, rx_length_errors);
++ DEV_STATS_INC(tunnel->dev, rx_errors);
++ goto drop;
++ }
++ iph = (struct iphdr *)(skb->head + nh);
++
+ err = IP_ECN_decapsulate(iph, skb);
+ if (unlikely(err)) {
+ if (log_ecn_error)
+diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
+index 3622298365105..b53c36c473a5b 100644
+--- a/net/ipv4/ipmr.c
++++ b/net/ipv4/ipmr.c
+@@ -1603,9 +1603,11 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, sockptr_t optval,
+
+ if (copy_from_sockptr(&olr, optlen, sizeof(int)))
+ return -EFAULT;
+- olr = min_t(unsigned int, olr, sizeof(int));
+ if (olr < 0)
+ return -EINVAL;
++
++ olr = min_t(unsigned int, olr, sizeof(int));
++
+ if (copy_to_sockptr(optlen, &olr, sizeof(int)))
+ return -EFAULT;
+ if (copy_to_sockptr(optval, &val, olr))
+diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
+index aea89326c6979..288f1846b3518 100644
+--- a/net/ipv4/raw.c
++++ b/net/ipv4/raw.c
+@@ -350,6 +350,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
+ goto error;
+ skb_reserve(skb, hlen);
+
++ skb->protocol = htons(ETH_P_IP);
+ skb->priority = READ_ONCE(sk->sk_priority);
+ skb->mark = sockc->mark;
+ skb->tstamp = sockc->transmit_time;
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index c82dc42f57c65..a4f4185923144 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -4010,11 +4010,11 @@ int do_tcp_getsockopt(struct sock *sk, int level,
+ if (copy_from_sockptr(&len, optlen, sizeof(int)))
+ return -EFAULT;
+
+- len = min_t(unsigned int, len, sizeof(int));
+-
+ if (len < 0)
+ return -EINVAL;
+
++ len = min_t(unsigned int, len, sizeof(int));
++
+ switch (optname) {
+ case TCP_MAXSEG:
+ val = tp->mss_cache;
+diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
+index 9e85f2a0bddd4..0ecc7311dc6ce 100644
+--- a/net/ipv4/tcp_minisocks.c
++++ b/net/ipv4/tcp_minisocks.c
+@@ -398,10 +398,6 @@ void tcp_twsk_purge(struct list_head *net_exit_list, int family)
+ /* Even if tw_refcount == 1, we must clean up kernel reqsk */
+ inet_twsk_purge(net->ipv4.tcp_death_row.hashinfo, family);
+ } else if (!purged_once) {
+- /* The last refcount is decremented in tcp_sk_exit_batch() */
+- if (refcount_read(&net->ipv4.tcp_death_row.tw_refcount) == 1)
+- continue;
+-
+ inet_twsk_purge(&tcp_hashinfo, family);
+ purged_once = true;
+ }
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index e474b201900f9..17231c0f88302 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -2792,11 +2792,11 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname,
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+- len = min_t(unsigned int, len, sizeof(int));
+-
+ if (len < 0)
+ return -EINVAL;
+
++ len = min_t(unsigned int, len, sizeof(int));
++
+ switch (optname) {
+ case UDP_CORK:
+ val = udp_test_bit(CORK, sk);
+diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
+index 7523c4baef35e..52c04f0ac4981 100644
+--- a/net/ipv6/fib6_rules.c
++++ b/net/ipv6/fib6_rules.c
+@@ -449,6 +449,11 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
+ + nla_total_size(16); /* src */
+ }
+
++static void fib6_rule_flush_cache(struct fib_rules_ops *ops)
++{
++ rt_genid_bump_ipv6(ops->fro_net);
++}
++
+ static const struct fib_rules_ops __net_initconst fib6_rules_ops_template = {
+ .family = AF_INET6,
+ .rule_size = sizeof(struct fib6_rule),
+@@ -461,6 +466,7 @@ static const struct fib_rules_ops __net_initconst fib6_rules_ops_template = {
+ .compare = fib6_rule_compare,
+ .fill = fib6_rule_fill,
+ .nlmsg_payload = fib6_rule_nlmsg_payload,
++ .flush_cache = fib6_rule_flush_cache,
+ .nlgroup = RTNLGRP_IPV6_RULE,
+ .owner = THIS_MODULE,
+ .fro_net = &init_net,
+diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
+index bc6e0a0bad3c1..76ee1615ff2a0 100644
+--- a/net/ipv6/mcast.c
++++ b/net/ipv6/mcast.c
+@@ -2719,7 +2719,6 @@ void ipv6_mc_down(struct inet6_dev *idev)
+ /* Should stop work after group drop. or we will
+ * start work again in mld_ifc_event()
+ */
+- synchronize_net();
+ mld_query_stop_work(idev);
+ mld_report_stop_work(idev);
+
+diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
+index 1184d40167b86..eda933c097926 100644
+--- a/net/kcm/kcmsock.c
++++ b/net/kcm/kcmsock.c
+@@ -1152,10 +1152,11 @@ static int kcm_getsockopt(struct socket *sock, int level, int optname,
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+- len = min_t(unsigned int, len, sizeof(int));
+ if (len < 0)
+ return -EINVAL;
+
++ len = min_t(unsigned int, len, sizeof(int));
++
+ switch (optname) {
+ case KCM_RECV_DISABLE:
+ val = kcm->rx_disabled;
+diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
+index f011af6601c9c..6146e4e67bbb5 100644
+--- a/net/l2tp/l2tp_ppp.c
++++ b/net/l2tp/l2tp_ppp.c
+@@ -1356,11 +1356,11 @@ static int pppol2tp_getsockopt(struct socket *sock, int level, int optname,
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+- len = min_t(unsigned int, len, sizeof(int));
+-
+ if (len < 0)
+ return -EINVAL;
+
++ len = min_t(unsigned int, len, sizeof(int));
++
+ err = -ENOTCONN;
+ if (!sk->sk_user_data)
+ goto end;
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 2022a26eb8811..20d863370796d 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -7523,10 +7523,10 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
+ if (err)
+ goto err_clear;
+
+- if (req->link_id > 0)
++ if (req->link_id >= 0)
+ link = sdata_dereference(sdata->link[req->link_id], sdata);
+ else
+- link = sdata_dereference(sdata->link[0], sdata);
++ link = &sdata->deflink;
+
+ if (WARN_ON(!link)) {
+ err = -ENOLINK;
+diff --git a/net/mctp/route.c b/net/mctp/route.c
+index ceee44ea09d97..01c530dbc1a65 100644
+--- a/net/mctp/route.c
++++ b/net/mctp/route.c
+@@ -843,6 +843,9 @@ static int mctp_do_fragment_route(struct mctp_route *rt, struct sk_buff *skb,
+ /* copy message payload */
+ skb_copy_bits(skb, pos, skb_transport_header(skb2), size);
+
++ /* we need to copy the extensions, for MCTP flow data */
++ skb_ext_copy(skb2, skb);
++
+ /* do route */
+ rc = rt->output(rt, skb2);
+ if (rc)
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 1683dc196b592..6873c9815cd31 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -1211,7 +1211,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
+ if (flags & ~NFT_TABLE_F_MASK)
+ return -EOPNOTSUPP;
+
+- if (flags == ctx->table->flags)
++ if (flags == (ctx->table->flags & NFT_TABLE_F_MASK))
+ return 0;
+
+ if ((nft_table_has_owner(ctx->table) &&
+@@ -2619,19 +2619,6 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
+ }
+ }
+
+- if (nla[NFTA_CHAIN_COUNTERS]) {
+- if (!nft_is_base_chain(chain)) {
+- err = -EOPNOTSUPP;
+- goto err_hooks;
+- }
+-
+- stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
+- if (IS_ERR(stats)) {
+- err = PTR_ERR(stats);
+- goto err_hooks;
+- }
+- }
+-
+ if (!(table->flags & NFT_TABLE_F_DORMANT) &&
+ nft_is_base_chain(chain) &&
+ !list_empty(&hook.list)) {
+@@ -2646,6 +2633,20 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
+ }
+
+ unregister = true;
++
++ if (nla[NFTA_CHAIN_COUNTERS]) {
++ if (!nft_is_base_chain(chain)) {
++ err = -EOPNOTSUPP;
++ goto err_hooks;
++ }
++
++ stats = nft_stats_alloc(nla[NFTA_CHAIN_COUNTERS]);
++ if (IS_ERR(stats)) {
++ err = PTR_ERR(stats);
++ goto err_hooks;
++ }
++ }
++
+ err = -ENOMEM;
+ trans = nft_trans_alloc(ctx, NFT_MSG_NEWCHAIN,
+ sizeof(struct nft_trans_chain));
+diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
+index aa1d9e93a9a04..b3b282de802de 100644
+--- a/net/netfilter/nft_set_pipapo.c
++++ b/net/netfilter/nft_set_pipapo.c
+@@ -2244,8 +2244,6 @@ static void nft_pipapo_destroy(const struct nft_ctx *ctx,
+ if (m) {
+ rcu_barrier();
+
+- nft_set_pipapo_match_destroy(ctx, set, m);
+-
+ for_each_possible_cpu(cpu)
+ pipapo_free_scratch(m, cpu);
+ free_percpu(m->scratch);
+@@ -2257,8 +2255,7 @@ static void nft_pipapo_destroy(const struct nft_ctx *ctx,
+ if (priv->clone) {
+ m = priv->clone;
+
+- if (priv->dirty)
+- nft_set_pipapo_match_destroy(ctx, set, m);
++ nft_set_pipapo_match_destroy(ctx, set, m);
+
+ for_each_possible_cpu(cpu)
+ pipapo_free_scratch(priv->clone, cpu);
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
+index c9bbc26866907..e6a8701a38dbe 100644
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -3998,7 +3998,7 @@ packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval,
+ if (val < 0 || val > 1)
+ return -EINVAL;
+
+- po->prot_hook.ignore_outgoing = !!val;
++ WRITE_ONCE(po->prot_hook.ignore_outgoing, !!val);
+ return 0;
+ }
+ case PACKET_TX_HAS_OFF:
+@@ -4129,7 +4129,7 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
+ 0);
+ break;
+ case PACKET_IGNORE_OUTGOING:
+- val = po->prot_hook.ignore_outgoing;
++ val = READ_ONCE(po->prot_hook.ignore_outgoing);
+ break;
+ case PACKET_ROLLOVER_STATS:
+ if (!po->rollover)
+diff --git a/net/rds/send.c b/net/rds/send.c
+index 2899def23865f..09a2801106549 100644
+--- a/net/rds/send.c
++++ b/net/rds/send.c
+@@ -103,13 +103,12 @@ EXPORT_SYMBOL_GPL(rds_send_path_reset);
+
+ static int acquire_in_xmit(struct rds_conn_path *cp)
+ {
+- return test_and_set_bit(RDS_IN_XMIT, &cp->cp_flags) == 0;
++ return test_and_set_bit_lock(RDS_IN_XMIT, &cp->cp_flags) == 0;
+ }
+
+ static void release_in_xmit(struct rds_conn_path *cp)
+ {
+- clear_bit(RDS_IN_XMIT, &cp->cp_flags);
+- smp_mb__after_atomic();
++ clear_bit_unlock(RDS_IN_XMIT, &cp->cp_flags);
+ /*
+ * We don't use wait_on_bit()/wake_up_bit() because our waking is in a
+ * hot path and finding waiters is very rare. We don't want to walk
+diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
+index 31a8252bd09c9..ad99409c6325e 100644
+--- a/net/sched/sch_taprio.c
++++ b/net/sched/sch_taprio.c
+@@ -1008,7 +1008,8 @@ static const struct nla_policy entry_policy[TCA_TAPRIO_SCHED_ENTRY_MAX + 1] = {
+ };
+
+ static const struct nla_policy taprio_tc_policy[TCA_TAPRIO_TC_ENTRY_MAX + 1] = {
+- [TCA_TAPRIO_TC_ENTRY_INDEX] = { .type = NLA_U32 },
++ [TCA_TAPRIO_TC_ENTRY_INDEX] = NLA_POLICY_MAX(NLA_U32,
++ TC_QOPT_MAX_QUEUE),
+ [TCA_TAPRIO_TC_ENTRY_MAX_SDU] = { .type = NLA_U32 },
+ [TCA_TAPRIO_TC_ENTRY_FP] = NLA_POLICY_RANGE(NLA_U32,
+ TC_FP_EXPRESS,
+diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c
+index d435bffc61999..97ff11973c493 100644
+--- a/net/sunrpc/addr.c
++++ b/net/sunrpc/addr.c
+@@ -284,10 +284,10 @@ char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags)
+ }
+
+ if (snprintf(portbuf, sizeof(portbuf),
+- ".%u.%u", port >> 8, port & 0xff) > (int)sizeof(portbuf))
++ ".%u.%u", port >> 8, port & 0xff) >= (int)sizeof(portbuf))
+ return NULL;
+
+- if (strlcat(addrbuf, portbuf, sizeof(addrbuf)) > sizeof(addrbuf))
++ if (strlcat(addrbuf, portbuf, sizeof(addrbuf)) >= sizeof(addrbuf))
+ return NULL;
+
+ return kstrdup(addrbuf, gfp_flags);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index 64cff717c3d9b..3366505bc669a 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -398,6 +398,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
+ u64 seq_send64;
+ int keylen;
+ u32 time32;
++ int ret;
+
+ p = simple_get_bytes(p, end, &ctx->flags, sizeof(ctx->flags));
+ if (IS_ERR(p))
+@@ -450,8 +451,16 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx,
+ }
+ ctx->mech_used.len = gss_kerberos_mech.gm_oid.len;
+
+- return gss_krb5_import_ctx_v2(ctx, gfp_mask);
++ ret = gss_krb5_import_ctx_v2(ctx, gfp_mask);
++ if (ret) {
++ p = ERR_PTR(ret);
++ goto out_free;
++ }
+
++ return 0;
++
++out_free:
++ kfree(ctx->mech_used.data);
+ out_err:
+ return PTR_ERR(p);
+ }
+diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c
+index d79f12c2550ac..cb32ab9a83952 100644
+--- a/net/sunrpc/auth_gss/gss_rpc_xdr.c
++++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c
+@@ -250,8 +250,8 @@ static int gssx_dec_option_array(struct xdr_stream *xdr,
+
+ creds = kzalloc(sizeof(struct svc_cred), GFP_KERNEL);
+ if (!creds) {
+- kfree(oa->data);
+- return -ENOMEM;
++ err = -ENOMEM;
++ goto free_oa;
+ }
+
+ oa->data[0].option.data = CREDS_VALUE;
+@@ -265,29 +265,40 @@ static int gssx_dec_option_array(struct xdr_stream *xdr,
+
+ /* option buffer */
+ p = xdr_inline_decode(xdr, 4);
+- if (unlikely(p == NULL))
+- return -ENOSPC;
++ if (unlikely(p == NULL)) {
++ err = -ENOSPC;
++ goto free_creds;
++ }
+
+ length = be32_to_cpup(p);
+ p = xdr_inline_decode(xdr, length);
+- if (unlikely(p == NULL))
+- return -ENOSPC;
++ if (unlikely(p == NULL)) {
++ err = -ENOSPC;
++ goto free_creds;
++ }
+
+ if (length == sizeof(CREDS_VALUE) &&
+ memcmp(p, CREDS_VALUE, sizeof(CREDS_VALUE)) == 0) {
+ /* We have creds here. parse them */
+ err = gssx_dec_linux_creds(xdr, creds);
+ if (err)
+- return err;
++ goto free_creds;
+ oa->data[0].value.len = 1; /* presence */
+ } else {
+ /* consume uninteresting buffer */
+ err = gssx_dec_buffer(xdr, &dummy);
+ if (err)
+- return err;
++ goto free_creds;
+ }
+ }
+ return 0;
++
++free_creds:
++ kfree(creds);
++free_oa:
++ kfree(oa->data);
++ oa->data = NULL;
++ return err;
+ }
+
+ static int gssx_dec_status(struct xdr_stream *xdr,
+diff --git a/net/unix/garbage.c b/net/unix/garbage.c
+index 2a81880dac7b7..027c86e804f8a 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -198,7 +198,7 @@ void wait_for_unix_gc(void)
+ if (READ_ONCE(unix_tot_inflight) > UNIX_INFLIGHT_TRIGGER_GC &&
+ !READ_ONCE(gc_in_progress))
+ unix_gc();
+- wait_event(unix_gc_wait, gc_in_progress == false);
++ wait_event(unix_gc_wait, !READ_ONCE(gc_in_progress));
+ }
+
+ /* The external entry point: unix_gc() */
+diff --git a/net/wireless/scan.c b/net/wireless/scan.c
+index 389a52c29bfc7..f138f88be9048 100644
+--- a/net/wireless/scan.c
++++ b/net/wireless/scan.c
+@@ -2602,9 +2602,9 @@ cfg80211_defrag_mle(const struct element *mle, const u8 *ie, size_t ielen,
+ }
+
+ static u8
+-cfg80211_tbtt_info_for_mld_ap(const u8 *ie, size_t ielen, u8 mld_id, u8 link_id,
+- const struct ieee80211_neighbor_ap_info **ap_info,
+- const u8 **tbtt_info)
++cfg80211_rnr_info_for_mld_ap(const u8 *ie, size_t ielen, u8 mld_id, u8 link_id,
++ const struct ieee80211_neighbor_ap_info **ap_info,
++ u8 *param_ch_count)
+ {
+ const struct ieee80211_neighbor_ap_info *info;
+ const struct element *rnr;
+@@ -2661,7 +2661,9 @@ cfg80211_tbtt_info_for_mld_ap(const u8 *ie, size_t ielen, u8 mld_id, u8 link_id,
+ if (mld_id == mld_params->mld_id &&
+ link_id == lid) {
+ *ap_info = info;
+- *tbtt_info = pos;
++ *param_ch_count =
++ le16_get_bits(mld_params->params,
++ IEEE80211_RNR_MLD_PARAMS_BSS_CHANGE_COUNT);
+
+ return use_for;
+ }
+@@ -2674,6 +2676,103 @@ cfg80211_tbtt_info_for_mld_ap(const u8 *ie, size_t ielen, u8 mld_id, u8 link_id,
+ return 0;
+ }
+
++static struct element *
++cfg80211_gen_reporter_rnr(struct cfg80211_bss *source_bss, bool is_mbssid,
++ bool same_mld, u8 link_id, u8 bss_change_count,
++ gfp_t gfp)
++{
++ const struct cfg80211_bss_ies *ies;
++ struct ieee80211_neighbor_ap_info ap_info;
++ struct ieee80211_tbtt_info_ge_11 tbtt_info;
++ u32 short_ssid;
++ const struct element *elem;
++ struct element *res;
++
++ /*
++ * We only generate the RNR to permit ML lookups. For that we do not
++ * need an entry for the corresponding transmitting BSS, lets just skip
++ * it even though it would be easy to add.
++ */
++ if (!same_mld)
++ return NULL;
++
++ /* We could use tx_data->ies if we change cfg80211_calc_short_ssid */
++ rcu_read_lock();
++ ies = rcu_dereference(source_bss->ies);
++
++ ap_info.tbtt_info_len = offsetofend(typeof(tbtt_info), mld_params);
++ ap_info.tbtt_info_hdr =
++ u8_encode_bits(IEEE80211_TBTT_INFO_TYPE_TBTT,
++ IEEE80211_AP_INFO_TBTT_HDR_TYPE) |
++ u8_encode_bits(0, IEEE80211_AP_INFO_TBTT_HDR_COUNT);
++
++ ap_info.channel = ieee80211_frequency_to_channel(source_bss->channel->center_freq);
++
++ /* operating class */
++ elem = cfg80211_find_elem(WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
++ ies->data, ies->len);
++ if (elem && elem->datalen >= 1) {
++ ap_info.op_class = elem->data[0];
++ } else {
++ struct cfg80211_chan_def chandef;
++
++ /* The AP is not providing us with anything to work with. So
++ * make up a somewhat reasonable operating class, but don't
++ * bother with it too much as no one will ever use the
++ * information.
++ */
++ cfg80211_chandef_create(&chandef, source_bss->channel,
++ NL80211_CHAN_NO_HT);
++
++ if (!ieee80211_chandef_to_operating_class(&chandef,
++ &ap_info.op_class))
++ goto out_unlock;
++ }
++
++ /* Just set TBTT offset and PSD 20 to invalid/unknown */
++ tbtt_info.tbtt_offset = 255;
++ tbtt_info.psd_20 = IEEE80211_RNR_TBTT_PARAMS_PSD_RESERVED;
++
++ memcpy(tbtt_info.bssid, source_bss->bssid, ETH_ALEN);
++ if (cfg80211_calc_short_ssid(ies, &elem, &short_ssid))
++ goto out_unlock;
++
++ rcu_read_unlock();
++
++ tbtt_info.short_ssid = cpu_to_le32(short_ssid);
++
++ tbtt_info.bss_params = IEEE80211_RNR_TBTT_PARAMS_SAME_SSID;
++
++ if (is_mbssid) {
++ tbtt_info.bss_params |= IEEE80211_RNR_TBTT_PARAMS_MULTI_BSSID;
++ tbtt_info.bss_params |= IEEE80211_RNR_TBTT_PARAMS_TRANSMITTED_BSSID;
++ }
++
++ tbtt_info.mld_params.mld_id = 0;
++ tbtt_info.mld_params.params =
++ le16_encode_bits(link_id, IEEE80211_RNR_MLD_PARAMS_LINK_ID) |
++ le16_encode_bits(bss_change_count,
++ IEEE80211_RNR_MLD_PARAMS_BSS_CHANGE_COUNT);
++
++ res = kzalloc(struct_size(res, data,
++ sizeof(ap_info) + ap_info.tbtt_info_len),
++ gfp);
++ if (!res)
++ return NULL;
++
++ /* Copy the data */
++ res->id = WLAN_EID_REDUCED_NEIGHBOR_REPORT;
++ res->datalen = sizeof(ap_info) + ap_info.tbtt_info_len;
++ memcpy(res->data, &ap_info, sizeof(ap_info));
++ memcpy(res->data + sizeof(ap_info), &tbtt_info, ap_info.tbtt_info_len);
++
++ return res;
++
++out_unlock:
++ rcu_read_unlock();
++ return NULL;
++}
++
+ static void
+ cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy,
+ struct cfg80211_inform_single_bss_data *tx_data,
+@@ -2687,13 +2786,14 @@ cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy,
+ .source_bss = source_bss,
+ .bss_source = BSS_SOURCE_STA_PROFILE,
+ };
++ struct element *reporter_rnr = NULL;
+ struct ieee80211_multi_link_elem *ml_elem;
+ struct cfg80211_mle *mle;
+ u16 control;
+ u8 ml_common_len;
+- u8 *new_ie;
++ u8 *new_ie = NULL;
+ struct cfg80211_bss *bss;
+- int mld_id;
++ u8 mld_id, reporter_link_id, bss_change_count;
+ u16 seen_links = 0;
+ const u8 *pos;
+ u8 i;
+@@ -2715,8 +2815,14 @@ cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy,
+
+ ml_common_len = ml_elem->variable[0];
+
+- /* length + MLD MAC address + link ID info + BSS Params Change Count */
+- pos = ml_elem->variable + 1 + 6 + 1 + 1;
++ /* length + MLD MAC address */
++ pos = ml_elem->variable + 1 + 6;
++
++ reporter_link_id = pos[0];
++ pos += 1;
++
++ bss_change_count = pos[0];
++ pos += 1;
+
+ if (u16_get_bits(control, IEEE80211_MLC_BASIC_PRES_MED_SYNC_DELAY))
+ pos += 2;
+@@ -2747,17 +2853,28 @@ cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy,
+ if (!mle)
+ return;
+
++ /* No point in doing anything if there is no per-STA profile */
++ if (!mle->sta_prof[0])
++ goto out;
++
+ new_ie = kmalloc(IEEE80211_MAX_DATA_LEN, gfp);
+ if (!new_ie)
+ goto out;
+
++ reporter_rnr = cfg80211_gen_reporter_rnr(source_bss,
++ u16_get_bits(control,
++ IEEE80211_MLC_BASIC_PRES_MLD_ID),
++ mld_id == 0, reporter_link_id,
++ bss_change_count,
++ gfp);
++
+ for (i = 0; i < ARRAY_SIZE(mle->sta_prof) && mle->sta_prof[i]; i++) {
+ const struct ieee80211_neighbor_ap_info *ap_info;
+ enum nl80211_band band;
+ u32 freq;
+ const u8 *profile;
+- const u8 *tbtt_info;
+ ssize_t profile_len;
++ u8 param_ch_count;
+ u8 link_id, use_for;
+
+ if (!ieee80211_mle_basic_sta_prof_size_ok((u8 *)mle->sta_prof[i],
+@@ -2800,10 +2917,11 @@ cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy,
+ profile_len -= 2;
+
+ /* Find in RNR to look up channel information */
+- use_for = cfg80211_tbtt_info_for_mld_ap(tx_data->ie,
+- tx_data->ielen,
+- mld_id, link_id,
+- &ap_info, &tbtt_info);
++ use_for = cfg80211_rnr_info_for_mld_ap(tx_data->ie,
++ tx_data->ielen,
++ mld_id, link_id,
++ &ap_info,
++ ¶m_ch_count);
+ if (!use_for)
+ continue;
+
+@@ -2846,7 +2964,8 @@ cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy,
+ continue;
+
+ /* Copy the Basic Multi-Link element including the common
+- * information, and then fix up the link ID.
++ * information, and then fix up the link ID and BSS param
++ * change count.
+ * Note that the ML element length has been verified and we
+ * also checked that it contains the link ID.
+ */
+@@ -2857,10 +2976,21 @@ cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy,
+ sizeof(*ml_elem) + ml_common_len);
+
+ new_ie[data.ielen + sizeof(*ml_elem) + 1 + ETH_ALEN] = link_id;
++ new_ie[data.ielen + sizeof(*ml_elem) + 1 + ETH_ALEN + 1] =
++ param_ch_count;
+
+ data.ielen += sizeof(*ml_elem) + ml_common_len;
+
+- /* TODO: Add an RNR containing only the reporting AP */
++ if (reporter_rnr && (use_for & NL80211_BSS_USE_FOR_NORMAL)) {
++ if (data.ielen + sizeof(struct element) +
++ reporter_rnr->datalen > IEEE80211_MAX_DATA_LEN)
++ continue;
++
++ memcpy(new_ie + data.ielen, reporter_rnr,
++ sizeof(struct element) + reporter_rnr->datalen);
++ data.ielen += sizeof(struct element) +
++ reporter_rnr->datalen;
++ }
+
+ bss = cfg80211_inform_single_bss_data(wiphy, &data, gfp);
+ if (!bss)
+@@ -2869,6 +2999,7 @@ cfg80211_parse_ml_elem_sta_data(struct wiphy *wiphy,
+ }
+
+ out:
++ kfree(reporter_rnr);
+ kfree(new_ie);
+ kfree(mle);
+ }
+diff --git a/net/wireless/tests/scan.c b/net/wireless/tests/scan.c
+index 77854161cd22b..f9ea44aee9952 100644
+--- a/net/wireless/tests/scan.c
++++ b/net/wireless/tests/scan.c
+@@ -2,7 +2,7 @@
+ /*
+ * KUnit tests for inform_bss functions
+ *
+- * Copyright (C) 2023 Intel Corporation
++ * Copyright (C) 2023-2024 Intel Corporation
+ */
+ #include <linux/ieee80211.h>
+ #include <net/cfg80211.h>
+@@ -406,9 +406,27 @@ static struct inform_bss_ml_sta_case {
+ const char *desc;
+ int mld_id;
+ bool sta_prof_vendor_elems;
++ bool include_oper_class;
+ } inform_bss_ml_sta_cases[] = {
+- { .desc = "no_mld_id", .mld_id = 0, .sta_prof_vendor_elems = false },
+- { .desc = "mld_id_eq_1", .mld_id = 1, .sta_prof_vendor_elems = true },
++ {
++ .desc = "zero_mld_id",
++ .mld_id = 0,
++ .sta_prof_vendor_elems = false,
++ }, {
++ .desc = "zero_mld_id_with_oper_class",
++ .mld_id = 0,
++ .sta_prof_vendor_elems = false,
++ .include_oper_class = true,
++ }, {
++ .desc = "mld_id_eq_1",
++ .mld_id = 1,
++ .sta_prof_vendor_elems = true,
++ }, {
++ .desc = "mld_id_eq_1_with_oper_class",
++ .mld_id = 1,
++ .sta_prof_vendor_elems = true,
++ .include_oper_class = true,
++ },
+ };
+ KUNIT_ARRAY_PARAM_DESC(inform_bss_ml_sta, inform_bss_ml_sta_cases, desc)
+
+@@ -515,6 +533,12 @@ static void test_inform_bss_ml_sta(struct kunit *test)
+ skb_put_u8(input, 4);
+ skb_put_data(input, "TEST", 4);
+
++ if (params->include_oper_class) {
++ skb_put_u8(input, WLAN_EID_SUPPORTED_REGULATORY_CLASSES);
++ skb_put_u8(input, 1);
++ skb_put_u8(input, 81);
++ }
++
+ skb_put_u8(input, WLAN_EID_REDUCED_NEIGHBOR_REPORT);
+ skb_put_u8(input, sizeof(rnr));
+ skb_put_data(input, &rnr, sizeof(rnr));
+@@ -582,15 +606,21 @@ static void test_inform_bss_ml_sta(struct kunit *test)
+ KUNIT_EXPECT_EQ(test, ies->tsf, tsf + le64_to_cpu(sta_prof.tsf_offset));
+ /* Resulting length should be:
+ * SSID (inherited) + RNR (inherited) + vendor element(s) +
++ * operating class (if requested) +
++ * generated RNR (if MLD ID == 0) +
+ * MLE common info + MLE header and control
+ */
+ if (params->sta_prof_vendor_elems)
+ KUNIT_EXPECT_EQ(test, ies->len,
+ 6 + 2 + sizeof(rnr) + 2 + 160 + 2 + 165 +
++ (params->include_oper_class ? 3 : 0) +
++ (!params->mld_id ? 22 : 0) +
+ mle_basic_common_info.var_len + 5);
+ else
+ KUNIT_EXPECT_EQ(test, ies->len,
+ 6 + 2 + sizeof(rnr) + 2 + 155 +
++ (params->include_oper_class ? 3 : 0) +
++ (!params->mld_id ? 22 : 0) +
+ mle_basic_common_info.var_len + 5);
+ rcu_read_unlock();
+
+diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
+index f7a7c7798c3b2..d18d51412cc00 100644
+--- a/net/x25/af_x25.c
++++ b/net/x25/af_x25.c
+@@ -460,12 +460,12 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
+ if (get_user(len, optlen))
+ goto out;
+
+- len = min_t(unsigned int, len, sizeof(int));
+-
+ rc = -EINVAL;
+ if (len < 0)
+ goto out;
+
++ len = min_t(unsigned int, len, sizeof(int));
++
+ rc = -EFAULT;
+ if (put_user(len, optlen))
+ goto out;
+diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
+index 653e51ae39648..6346690d5c699 100644
+--- a/net/xfrm/xfrm_device.c
++++ b/net/xfrm/xfrm_device.c
+@@ -407,7 +407,8 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
+ struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+ struct net_device *dev = x->xso.dev;
+
+- if (!x->type_offload)
++ if (!x->type_offload ||
++ (x->xso.type == XFRM_DEV_OFFLOAD_UNSPECIFIED && x->encap))
+ return false;
+
+ if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET ||
+diff --git a/scripts/coccinelle/api/device_attr_show.cocci b/scripts/coccinelle/api/device_attr_show.cocci
+index 550d1d2fc02a9..dfcf9304195f3 100644
+--- a/scripts/coccinelle/api/device_attr_show.cocci
++++ b/scripts/coccinelle/api/device_attr_show.cocci
+@@ -28,7 +28,7 @@ ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
+
+ @rp depends on patch@
+ identifier show, dev, attr, buf;
+-expression BUF, SZ, FORMAT, STR;
++expression BUF, SZ, FORMAT;
+ @@
+
+ ssize_t show(struct device *dev, struct device_attribute *attr, char *buf)
+diff --git a/scripts/kconfig/lexer.l b/scripts/kconfig/lexer.l
+index cc386e4436834..2c2b3e6f248ca 100644
+--- a/scripts/kconfig/lexer.l
++++ b/scripts/kconfig/lexer.l
+@@ -302,8 +302,11 @@ static char *expand_token(const char *in, size_t n)
+ new_string();
+ append_string(in, n);
+
+- /* get the whole line because we do not know the end of token. */
+- while ((c = input()) != EOF) {
++ /*
++ * get the whole line because we do not know the end of token.
++ * input() returns 0 (not EOF!) when it reachs the end of file.
++ */
++ while ((c = input()) != 0) {
+ if (c == '\n') {
+ unput(c);
+ break;
+diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
+index 18320a248aa7d..78dcb0ea15582 100644
+--- a/sound/core/seq/seq_midi.c
++++ b/sound/core/seq/seq_midi.c
+@@ -113,6 +113,12 @@ static int dump_midi(struct snd_rawmidi_substream *substream, const char *buf, i
+ return 0;
+ }
+
++/* callback for snd_seq_dump_var_event(), bridging to dump_midi() */
++static int __dump_midi(void *ptr, void *buf, int count)
++{
++ return dump_midi(ptr, buf, count);
++}
++
+ static int event_process_midi(struct snd_seq_event *ev, int direct,
+ void *private_data, int atomic, int hop)
+ {
+@@ -132,7 +138,7 @@ static int event_process_midi(struct snd_seq_event *ev, int direct,
+ pr_debug("ALSA: seq_midi: invalid sysex event flags = 0x%x\n", ev->flags);
+ return 0;
+ }
+- snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)dump_midi, substream);
++ snd_seq_dump_var_event(ev, __dump_midi, substream);
+ snd_midi_event_reset_decode(msynth->parser);
+ } else {
+ if (msynth->parser == NULL)
+diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
+index 1b9260108e482..1678737f11be7 100644
+--- a/sound/core/seq/seq_virmidi.c
++++ b/sound/core/seq/seq_virmidi.c
+@@ -62,6 +62,13 @@ static void snd_virmidi_init_event(struct snd_virmidi *vmidi,
+ /*
+ * decode input event and put to read buffer of each opened file
+ */
++
++/* callback for snd_seq_dump_var_event(), bridging to snd_rawmidi_receive() */
++static int dump_to_rawmidi(void *ptr, void *buf, int count)
++{
++ return snd_rawmidi_receive(ptr, buf, count);
++}
++
+ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
+ struct snd_seq_event *ev,
+ bool atomic)
+@@ -80,7 +87,7 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
+ if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
+ if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE)
+ continue;
+- snd_seq_dump_var_event(ev, (snd_seq_dump_func_t)snd_rawmidi_receive, vmidi->substream);
++ snd_seq_dump_var_event(ev, dump_to_rawmidi, vmidi->substream);
+ snd_midi_event_reset_decode(vmidi->parser);
+ } else {
+ len = snd_midi_event_decode(vmidi->parser, msg, sizeof(msg), ev);
+diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c
+index e436d4dab317f..86ddaff915de1 100644
+--- a/sound/pci/hda/cs35l41_hda_property.c
++++ b/sound/pci/hda/cs35l41_hda_property.c
+@@ -210,6 +210,7 @@ static int generic_dsd_config(struct cs35l41_hda *cs35l41, struct device *physde
+ struct spi_device *spi;
+ bool dsd_found;
+ int ret;
++ int i;
+
+ for (cfg = cs35l41_config_table; cfg->ssid; cfg++) {
+ if (!strcasecmp(cfg->ssid, cs35l41->acpi_subsystem_id))
+@@ -295,16 +296,6 @@ static int generic_dsd_config(struct cs35l41_hda *cs35l41, struct device *physde
+ cs35l41->index = id == 0x40 ? 0 : 1;
+ }
+
+- if (cfg->num_amps == 3)
+- /* 3 amps means a center channel, so no duplicate channels */
+- cs35l41->channel_index = 0;
+- else
+- /*
+- * if 4 amps, there are duplicate channels, so they need different indexes
+- * if 2 amps, no duplicate channels, channel_index would be 0
+- */
+- cs35l41->channel_index = cs35l41->index / 2;
+-
+ cs35l41->reset_gpio = fwnode_gpiod_get_index(acpi_fwnode_handle(cs35l41->dacpi), "reset",
+ cs35l41->index, GPIOD_OUT_LOW,
+ "cs35l41-reset");
+@@ -312,6 +303,11 @@ static int generic_dsd_config(struct cs35l41_hda *cs35l41, struct device *physde
+
+ hw_cfg->spk_pos = cfg->channel[cs35l41->index];
+
++ cs35l41->channel_index = 0;
++ for (i = 0; i < cs35l41->index; i++)
++ if (cfg->channel[i] == hw_cfg->spk_pos)
++ cs35l41->channel_index++;
++
+ if (cfg->boost_type == INTERNAL) {
+ hw_cfg->bst_type = CS35L41_INT_BOOST;
+ hw_cfg->bst_ind = cfg->boost_ind_nanohenry;
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index a1facdb98d9a0..1dc5eb92ddcad 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -6696,6 +6696,60 @@ static void alc285_fixup_hp_spectre_x360(struct hda_codec *codec,
+ }
+ }
+
++static void alc285_fixup_hp_envy_x360(struct hda_codec *codec,
++ const struct hda_fixup *fix,
++ int action)
++{
++ static const struct coef_fw coefs[] = {
++ WRITE_COEF(0x08, 0x6a0c), WRITE_COEF(0x0d, 0xa023),
++ WRITE_COEF(0x10, 0x0320), WRITE_COEF(0x1a, 0x8c03),
++ WRITE_COEF(0x25, 0x1800), WRITE_COEF(0x26, 0x003a),
++ WRITE_COEF(0x28, 0x1dfe), WRITE_COEF(0x29, 0xb014),
++ WRITE_COEF(0x2b, 0x1dfe), WRITE_COEF(0x37, 0xfe15),
++ WRITE_COEF(0x38, 0x7909), WRITE_COEF(0x45, 0xd489),
++ WRITE_COEF(0x46, 0x00f4), WRITE_COEF(0x4a, 0x21e0),
++ WRITE_COEF(0x66, 0x03f0), WRITE_COEF(0x67, 0x1000),
++ WRITE_COEF(0x6e, 0x1005), { }
++ };
++
++ static const struct hda_pintbl pincfgs[] = {
++ { 0x12, 0xb7a60130 }, /* Internal microphone*/
++ { 0x14, 0x90170150 }, /* B&O soundbar speakers */
++ { 0x17, 0x90170153 }, /* Side speakers */
++ { 0x19, 0x03a11040 }, /* Headset microphone */
++ { }
++ };
++
++ switch (action) {
++ case HDA_FIXUP_ACT_PRE_PROBE:
++ snd_hda_apply_pincfgs(codec, pincfgs);
++
++ /* Fixes volume control problem for side speakers */
++ alc295_fixup_disable_dac3(codec, fix, action);
++
++ /* Fixes no sound from headset speaker */
++ snd_hda_codec_amp_stereo(codec, 0x21, HDA_OUTPUT, 0, -1, 0);
++
++ /* Auto-enable headset mic when plugged */
++ snd_hda_jack_set_gating_jack(codec, 0x19, 0x21);
++
++ /* Headset mic volume enhancement */
++ snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREF50);
++ break;
++ case HDA_FIXUP_ACT_INIT:
++ alc_process_coef_fw(codec, coefs);
++ break;
++ case HDA_FIXUP_ACT_BUILD:
++ rename_ctl(codec, "Bass Speaker Playback Volume",
++ "B&O-Tuned Playback Volume");
++ rename_ctl(codec, "Front Playback Switch",
++ "B&O Soundbar Playback Switch");
++ rename_ctl(codec, "Bass Speaker Playback Switch",
++ "Side Speaker Playback Switch");
++ break;
++ }
++}
++
+ /* for hda_fixup_thinkpad_acpi() */
+ #include "thinkpad_helper.c"
+
+@@ -7297,6 +7351,7 @@ enum {
+ ALC280_FIXUP_HP_9480M,
+ ALC245_FIXUP_HP_X360_AMP,
+ ALC285_FIXUP_HP_SPECTRE_X360_EB1,
++ ALC285_FIXUP_HP_ENVY_X360,
+ ALC288_FIXUP_DELL_HEADSET_MODE,
+ ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
+ ALC288_FIXUP_DELL_XPS_13,
+@@ -9273,6 +9328,12 @@ static const struct hda_fixup alc269_fixups[] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc285_fixup_hp_spectre_x360_eb1
+ },
++ [ALC285_FIXUP_HP_ENVY_X360] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc285_fixup_hp_envy_x360,
++ .chained = true,
++ .chain_id = ALC285_FIXUP_HP_GPIO_AMP_INIT,
++ },
+ [ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc285_fixup_ideapad_s740_coef,
+@@ -9861,6 +9922,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+ SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360),
+ SND_PCI_QUIRK(0x103c, 0x8537, "HP ProBook 440 G6", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
++ SND_PCI_QUIRK(0x103c, 0x85de, "HP Envy x360 13-ar0xxx", ALC285_FIXUP_HP_ENVY_X360),
+ SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+ SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+ SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
+@@ -10559,6 +10621,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
+ {.id = ALC295_FIXUP_HP_OMEN, .name = "alc295-hp-omen"},
+ {.id = ALC285_FIXUP_HP_SPECTRE_X360, .name = "alc285-hp-spectre-x360"},
+ {.id = ALC285_FIXUP_HP_SPECTRE_X360_EB1, .name = "alc285-hp-spectre-x360-eb1"},
++ {.id = ALC285_FIXUP_HP_ENVY_X360, .name = "alc285-hp-envy-x360"},
+ {.id = ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP, .name = "alc287-ideapad-bass-spk-amp"},
+ {.id = ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN, .name = "alc287-yoga9-bass-spk-pin"},
+ {.id = ALC623_FIXUP_LENOVO_THINKSTATION_P340, .name = "alc623-lenovo-thinkstation-p340"},
+diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c
+index 1bfb00102a77a..7aef93126ed0c 100644
+--- a/sound/pci/hda/tas2781_hda_i2c.c
++++ b/sound/pci/hda/tas2781_hda_i2c.c
+@@ -160,11 +160,13 @@ static void tas2781_hda_playback_hook(struct device *dev, int action)
+ pm_runtime_get_sync(dev);
+ mutex_lock(&tas_hda->priv->codec_lock);
+ tasdevice_tuning_switch(tas_hda->priv, 0);
++ tas_hda->priv->playback_started = true;
+ mutex_unlock(&tas_hda->priv->codec_lock);
+ break;
+ case HDA_GEN_PCM_ACT_CLOSE:
+ mutex_lock(&tas_hda->priv->codec_lock);
+ tasdevice_tuning_switch(tas_hda->priv, 1);
++ tas_hda->priv->playback_started = false;
+ mutex_unlock(&tas_hda->priv->codec_lock);
+
+ pm_runtime_mark_last_busy(dev);
+@@ -666,6 +668,7 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
+ tasdevice_save_calibration(tas_priv);
+
+ tasdevice_tuning_switch(tas_hda->priv, 0);
++ tas_hda->priv->playback_started = true;
+
+ out:
+ mutex_unlock(&tas_hda->priv->codec_lock);
+@@ -832,23 +835,19 @@ static void tas2781_hda_i2c_remove(struct i2c_client *clt)
+ static int tas2781_runtime_suspend(struct device *dev)
+ {
+ struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
+- int i;
+
+ dev_dbg(tas_hda->dev, "Runtime Suspend\n");
+
+ mutex_lock(&tas_hda->priv->codec_lock);
+
++ /* The driver powers up the amplifiers at module load time.
++ * Stop the playback if it's unused.
++ */
+ if (tas_hda->priv->playback_started) {
+ tasdevice_tuning_switch(tas_hda->priv, 1);
+ tas_hda->priv->playback_started = false;
+ }
+
+- for (i = 0; i < tas_hda->priv->ndev; i++) {
+- tas_hda->priv->tasdevice[i].cur_book = -1;
+- tas_hda->priv->tasdevice[i].cur_prog = -1;
+- tas_hda->priv->tasdevice[i].cur_conf = -1;
+- }
+-
+ mutex_unlock(&tas_hda->priv->codec_lock);
+
+ return 0;
+@@ -877,16 +876,16 @@ static int tas2781_runtime_resume(struct device *dev)
+ static int tas2781_system_suspend(struct device *dev)
+ {
+ struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
+- int ret;
+
+ dev_dbg(tas_hda->priv->dev, "System Suspend\n");
+
+- ret = pm_runtime_force_suspend(dev);
+- if (ret)
+- return ret;
++ mutex_lock(&tas_hda->priv->codec_lock);
+
+ /* Shutdown chip before system suspend */
+- tasdevice_tuning_switch(tas_hda->priv, 1);
++ if (tas_hda->priv->playback_started)
++ tasdevice_tuning_switch(tas_hda->priv, 1);
++
++ mutex_unlock(&tas_hda->priv->codec_lock);
+
+ /*
+ * Reset GPIO may be shared, so cannot reset here.
+@@ -898,13 +897,9 @@ static int tas2781_system_suspend(struct device *dev)
+ static int tas2781_system_resume(struct device *dev)
+ {
+ struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
+- int i, ret;
+-
+- dev_info(tas_hda->priv->dev, "System Resume\n");
++ int i;
+
+- ret = pm_runtime_force_resume(dev);
+- if (ret)
+- return ret;
++ dev_dbg(tas_hda->priv->dev, "System Resume\n");
+
+ mutex_lock(&tas_hda->priv->codec_lock);
+
+@@ -920,6 +915,10 @@ static int tas2781_system_resume(struct device *dev)
+ * calibrated data inside algo.
+ */
+ tasdevice_apply_calibration(tas_hda->priv);
++
++ if (tas_hda->priv->playback_started)
++ tasdevice_tuning_switch(tas_hda->priv, 0);
++
+ mutex_unlock(&tas_hda->priv->codec_lock);
+
+ return 0;
+diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c
+index 20b94814a0462..b86f65d420054 100644
+--- a/sound/soc/amd/acp/acp-sof-mach.c
++++ b/sound/soc/amd/acp/acp-sof-mach.c
+@@ -126,16 +126,14 @@ static int acp_sof_probe(struct platform_device *pdev)
+ if (dmi_id && dmi_id->driver_data)
+ acp_card_drvdata->tdm_mode = dmi_id->driver_data;
+
+- acp_sofdsp_dai_links_create(card);
++ ret = acp_sofdsp_dai_links_create(card);
++ if (ret)
++ return dev_err_probe(&pdev->dev, ret, "Failed to create DAI links\n");
+
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
+- if (ret) {
+- dev_err(&pdev->dev,
+- "devm_snd_soc_register_card(%s) failed: %d\n",
+- card->name, ret);
+- return ret;
+- }
+-
++ if (ret)
++ return dev_err_probe(&pdev->dev, ret,
++ "Failed to register card(%s)\n", card->name);
+ return 0;
+ }
+
+diff --git a/sound/soc/codecs/tlv320adc3xxx.c b/sound/soc/codecs/tlv320adc3xxx.c
+index 420bbf588efea..e100cc9f5c192 100644
+--- a/sound/soc/codecs/tlv320adc3xxx.c
++++ b/sound/soc/codecs/tlv320adc3xxx.c
+@@ -1429,7 +1429,7 @@ static int adc3xxx_i2c_probe(struct i2c_client *i2c)
+ return ret;
+ }
+
+-static void __exit adc3xxx_i2c_remove(struct i2c_client *client)
++static void adc3xxx_i2c_remove(struct i2c_client *client)
+ {
+ struct adc3xxx *adc3xxx = i2c_get_clientdata(client);
+
+@@ -1452,7 +1452,7 @@ static struct i2c_driver adc3xxx_i2c_driver = {
+ .of_match_table = tlv320adc3xxx_of_match,
+ },
+ .probe = adc3xxx_i2c_probe,
+- .remove = __exit_p(adc3xxx_i2c_remove),
++ .remove = adc3xxx_i2c_remove,
+ .id_table = adc3xxx_i2c_id,
+ };
+
+diff --git a/sound/soc/intel/boards/sof_ssp_common.h b/sound/soc/intel/boards/sof_ssp_common.h
+index 6d827103479b5..d24888bc99fde 100644
+--- a/sound/soc/intel/boards/sof_ssp_common.h
++++ b/sound/soc/intel/boards/sof_ssp_common.h
+@@ -67,6 +67,14 @@ enum sof_ssp_codec {
+
+ enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev);
+ enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev);
++
++#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SOF_SSP_COMMON)
+ const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type);
++#else
++static inline const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type)
++{
++ return NULL;
++}
++#endif
+
+ #endif /* __SOF_SSP_COMMON_H */
+diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c
+index 7109b81cc3d0a..5d1419ed7a62d 100644
+--- a/sound/soc/meson/aiu.c
++++ b/sound/soc/meson/aiu.c
+@@ -212,11 +212,12 @@ static const char * const aiu_spdif_ids[] = {
+ static int aiu_clk_get(struct device *dev)
+ {
+ struct aiu *aiu = dev_get_drvdata(dev);
++ struct clk *pclk;
+ int ret;
+
+- aiu->pclk = devm_clk_get(dev, "pclk");
+- if (IS_ERR(aiu->pclk))
+- return dev_err_probe(dev, PTR_ERR(aiu->pclk), "Can't get the aiu pclk\n");
++ pclk = devm_clk_get_enabled(dev, "pclk");
++ if (IS_ERR(pclk))
++ return dev_err_probe(dev, PTR_ERR(pclk), "Can't get the aiu pclk\n");
+
+ aiu->spdif_mclk = devm_clk_get(dev, "spdif_mclk");
+ if (IS_ERR(aiu->spdif_mclk))
+@@ -233,18 +234,6 @@ static int aiu_clk_get(struct device *dev)
+ if (ret)
+ return dev_err_probe(dev, ret, "Can't get the spdif clocks\n");
+
+- ret = clk_prepare_enable(aiu->pclk);
+- if (ret) {
+- dev_err(dev, "peripheral clock enable failed\n");
+- return ret;
+- }
+-
+- ret = devm_add_action_or_reset(dev,
+- (void(*)(void *))clk_disable_unprepare,
+- aiu->pclk);
+- if (ret)
+- dev_err(dev, "failed to add reset action on pclk");
+-
+ return ret;
+ }
+
+diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h
+index 393b6c2307e49..0f94c8bf60818 100644
+--- a/sound/soc/meson/aiu.h
++++ b/sound/soc/meson/aiu.h
+@@ -33,7 +33,6 @@ struct aiu_platform_data {
+ };
+
+ struct aiu {
+- struct clk *pclk;
+ struct clk *spdif_mclk;
+ struct aiu_interface i2s;
+ struct aiu_interface spdif;
+diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c
+index 1c3d433cefd23..2cedbce738373 100644
+--- a/sound/soc/meson/axg-tdm-interface.c
++++ b/sound/soc/meson/axg-tdm-interface.c
+@@ -12,6 +12,9 @@
+
+ #include "axg-tdm.h"
+
++/* Maximum bit clock frequency according the datasheets */
++#define MAX_SCLK 100000000 /* Hz */
++
+ enum {
+ TDM_IFACE_PAD,
+ TDM_IFACE_LOOPBACK,
+@@ -153,19 +156,27 @@ static int axg_tdm_iface_startup(struct snd_pcm_substream *substream,
+ return -EINVAL;
+ }
+
+- /* Apply component wide rate symmetry */
+ if (snd_soc_component_active(dai->component)) {
++ /* Apply component wide rate symmetry */
+ ret = snd_pcm_hw_constraint_single(substream->runtime,
+ SNDRV_PCM_HW_PARAM_RATE,
+ iface->rate);
+- if (ret < 0) {
+- dev_err(dai->dev,
+- "can't set iface rate constraint\n");
+- return ret;
+- }
++
++ } else {
++ /* Limit rate according to the slot number and width */
++ unsigned int max_rate =
++ MAX_SCLK / (iface->slots * iface->slot_width);
++ ret = snd_pcm_hw_constraint_minmax(substream->runtime,
++ SNDRV_PCM_HW_PARAM_RATE,
++ 0, max_rate);
+ }
+
+- return 0;
++ if (ret < 0)
++ dev_err(dai->dev, "can't set iface rate constraint\n");
++ else
++ ret = 0;
++
++ return ret;
+ }
+
+ static int axg_tdm_iface_set_stream(struct snd_pcm_substream *substream,
+@@ -264,8 +275,8 @@ static int axg_tdm_iface_set_sclk(struct snd_soc_dai *dai,
+ srate = iface->slots * iface->slot_width * params_rate(params);
+
+ if (!iface->mclk_rate) {
+- /* If no specific mclk is requested, default to bit clock * 4 */
+- clk_set_rate(iface->mclk, 4 * srate);
++ /* If no specific mclk is requested, default to bit clock * 2 */
++ clk_set_rate(iface->mclk, 2 * srate);
+ } else {
+ /* Check if we can actually get the bit clock from mclk */
+ if (iface->mclk_rate % srate) {
+diff --git a/sound/soc/meson/t9015.c b/sound/soc/meson/t9015.c
+index 9c6b4dac68932..571f65788c592 100644
+--- a/sound/soc/meson/t9015.c
++++ b/sound/soc/meson/t9015.c
+@@ -48,7 +48,6 @@
+ #define POWER_CFG 0x10
+
+ struct t9015 {
+- struct clk *pclk;
+ struct regulator *avdd;
+ };
+
+@@ -249,6 +248,7 @@ static int t9015_probe(struct platform_device *pdev)
+ struct t9015 *priv;
+ void __iomem *regs;
+ struct regmap *regmap;
++ struct clk *pclk;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+@@ -256,26 +256,14 @@ static int t9015_probe(struct platform_device *pdev)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, priv);
+
+- priv->pclk = devm_clk_get(dev, "pclk");
+- if (IS_ERR(priv->pclk))
+- return dev_err_probe(dev, PTR_ERR(priv->pclk), "failed to get core clock\n");
++ pclk = devm_clk_get_enabled(dev, "pclk");
++ if (IS_ERR(pclk))
++ return dev_err_probe(dev, PTR_ERR(pclk), "failed to get core clock\n");
+
+ priv->avdd = devm_regulator_get(dev, "AVDD");
+ if (IS_ERR(priv->avdd))
+ return dev_err_probe(dev, PTR_ERR(priv->avdd), "failed to AVDD\n");
+
+- ret = clk_prepare_enable(priv->pclk);
+- if (ret) {
+- dev_err(dev, "core clock enable failed\n");
+- return ret;
+- }
+-
+- ret = devm_add_action_or_reset(dev,
+- (void(*)(void *))clk_disable_unprepare,
+- priv->pclk);
+- if (ret)
+- return ret;
+-
+ ret = device_reset(dev);
+ if (ret) {
+ dev_err(dev, "reset failed\n");
+diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c
+index 860e66ec85e8a..9fa020ef7eab9 100644
+--- a/sound/soc/rockchip/rockchip_i2s_tdm.c
++++ b/sound/soc/rockchip/rockchip_i2s_tdm.c
+@@ -25,8 +25,6 @@
+ #define DEFAULT_MCLK_FS 256
+ #define CH_GRP_MAX 4 /* The max channel 8 / 2 */
+ #define MULTIPLEX_CH_MAX 10
+-#define CLK_PPM_MIN -1000
+-#define CLK_PPM_MAX 1000
+
+ #define TRCM_TXRX 0
+ #define TRCM_TX 1
+@@ -53,20 +51,6 @@ struct rk_i2s_tdm_dev {
+ struct clk *hclk;
+ struct clk *mclk_tx;
+ struct clk *mclk_rx;
+- /* The mclk_tx_src is parent of mclk_tx */
+- struct clk *mclk_tx_src;
+- /* The mclk_rx_src is parent of mclk_rx */
+- struct clk *mclk_rx_src;
+- /*
+- * The mclk_root0 and mclk_root1 are root parent and supplies for
+- * the different FS.
+- *
+- * e.g:
+- * mclk_root0 is VPLL0, used for FS=48000Hz
+- * mclk_root1 is VPLL1, used for FS=44100Hz
+- */
+- struct clk *mclk_root0;
+- struct clk *mclk_root1;
+ struct regmap *regmap;
+ struct regmap *grf;
+ struct snd_dmaengine_dai_dma_data capture_dma_data;
+@@ -76,19 +60,11 @@ struct rk_i2s_tdm_dev {
+ const struct rk_i2s_soc_data *soc_data;
+ bool is_master_mode;
+ bool io_multiplex;
+- bool mclk_calibrate;
+ bool tdm_mode;
+- unsigned int mclk_rx_freq;
+- unsigned int mclk_tx_freq;
+- unsigned int mclk_root0_freq;
+- unsigned int mclk_root1_freq;
+- unsigned int mclk_root0_initial_freq;
+- unsigned int mclk_root1_initial_freq;
+ unsigned int frame_width;
+ unsigned int clk_trcm;
+ unsigned int i2s_sdis[CH_GRP_MAX];
+ unsigned int i2s_sdos[CH_GRP_MAX];
+- int clk_ppm;
+ int refcount;
+ spinlock_t lock; /* xfer lock */
+ bool has_playback;
+@@ -114,12 +90,6 @@ static void i2s_tdm_disable_unprepare_mclk(struct rk_i2s_tdm_dev *i2s_tdm)
+ {
+ clk_disable_unprepare(i2s_tdm->mclk_tx);
+ clk_disable_unprepare(i2s_tdm->mclk_rx);
+- if (i2s_tdm->mclk_calibrate) {
+- clk_disable_unprepare(i2s_tdm->mclk_tx_src);
+- clk_disable_unprepare(i2s_tdm->mclk_rx_src);
+- clk_disable_unprepare(i2s_tdm->mclk_root0);
+- clk_disable_unprepare(i2s_tdm->mclk_root1);
+- }
+ }
+
+ /**
+@@ -142,29 +112,9 @@ static int i2s_tdm_prepare_enable_mclk(struct rk_i2s_tdm_dev *i2s_tdm)
+ ret = clk_prepare_enable(i2s_tdm->mclk_rx);
+ if (ret)
+ goto err_mclk_rx;
+- if (i2s_tdm->mclk_calibrate) {
+- ret = clk_prepare_enable(i2s_tdm->mclk_tx_src);
+- if (ret)
+- goto err_mclk_rx;
+- ret = clk_prepare_enable(i2s_tdm->mclk_rx_src);
+- if (ret)
+- goto err_mclk_rx_src;
+- ret = clk_prepare_enable(i2s_tdm->mclk_root0);
+- if (ret)
+- goto err_mclk_root0;
+- ret = clk_prepare_enable(i2s_tdm->mclk_root1);
+- if (ret)
+- goto err_mclk_root1;
+- }
+
+ return 0;
+
+-err_mclk_root1:
+- clk_disable_unprepare(i2s_tdm->mclk_root0);
+-err_mclk_root0:
+- clk_disable_unprepare(i2s_tdm->mclk_rx_src);
+-err_mclk_rx_src:
+- clk_disable_unprepare(i2s_tdm->mclk_tx_src);
+ err_mclk_rx:
+ clk_disable_unprepare(i2s_tdm->mclk_tx);
+ err_mclk_tx:
+@@ -564,159 +514,6 @@ static void rockchip_i2s_tdm_xfer_resume(struct snd_pcm_substream *substream,
+ I2S_XFER_RXS_START);
+ }
+
+-static int rockchip_i2s_tdm_clk_set_rate(struct rk_i2s_tdm_dev *i2s_tdm,
+- struct clk *clk, unsigned long rate,
+- int ppm)
+-{
+- unsigned long rate_target;
+- int delta, ret;
+-
+- if (ppm == i2s_tdm->clk_ppm)
+- return 0;
+-
+- if (ppm < 0)
+- delta = -1;
+- else
+- delta = 1;
+-
+- delta *= (int)div64_u64((u64)rate * (u64)abs(ppm) + 500000,
+- 1000000);
+-
+- rate_target = rate + delta;
+-
+- if (!rate_target)
+- return -EINVAL;
+-
+- ret = clk_set_rate(clk, rate_target);
+- if (ret)
+- return ret;
+-
+- i2s_tdm->clk_ppm = ppm;
+-
+- return 0;
+-}
+-
+-static int rockchip_i2s_tdm_calibrate_mclk(struct rk_i2s_tdm_dev *i2s_tdm,
+- struct snd_pcm_substream *substream,
+- unsigned int lrck_freq)
+-{
+- struct clk *mclk_root;
+- struct clk *mclk_parent;
+- unsigned int mclk_root_freq;
+- unsigned int mclk_root_initial_freq;
+- unsigned int mclk_parent_freq;
+- unsigned int div, delta;
+- u64 ppm;
+- int ret;
+-
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+- mclk_parent = i2s_tdm->mclk_tx_src;
+- else
+- mclk_parent = i2s_tdm->mclk_rx_src;
+-
+- switch (lrck_freq) {
+- case 8000:
+- case 16000:
+- case 24000:
+- case 32000:
+- case 48000:
+- case 64000:
+- case 96000:
+- case 192000:
+- mclk_root = i2s_tdm->mclk_root0;
+- mclk_root_freq = i2s_tdm->mclk_root0_freq;
+- mclk_root_initial_freq = i2s_tdm->mclk_root0_initial_freq;
+- mclk_parent_freq = DEFAULT_MCLK_FS * 192000;
+- break;
+- case 11025:
+- case 22050:
+- case 44100:
+- case 88200:
+- case 176400:
+- mclk_root = i2s_tdm->mclk_root1;
+- mclk_root_freq = i2s_tdm->mclk_root1_freq;
+- mclk_root_initial_freq = i2s_tdm->mclk_root1_initial_freq;
+- mclk_parent_freq = DEFAULT_MCLK_FS * 176400;
+- break;
+- default:
+- dev_err(i2s_tdm->dev, "Invalid LRCK frequency: %u Hz\n",
+- lrck_freq);
+- return -EINVAL;
+- }
+-
+- ret = clk_set_parent(mclk_parent, mclk_root);
+- if (ret)
+- return ret;
+-
+- ret = rockchip_i2s_tdm_clk_set_rate(i2s_tdm, mclk_root,
+- mclk_root_freq, 0);
+- if (ret)
+- return ret;
+-
+- delta = abs(mclk_root_freq % mclk_parent_freq - mclk_parent_freq);
+- ppm = div64_u64((uint64_t)delta * 1000000, (uint64_t)mclk_root_freq);
+-
+- if (ppm) {
+- div = DIV_ROUND_CLOSEST(mclk_root_initial_freq, mclk_parent_freq);
+- if (!div)
+- return -EINVAL;
+-
+- mclk_root_freq = mclk_parent_freq * round_up(div, 2);
+-
+- ret = clk_set_rate(mclk_root, mclk_root_freq);
+- if (ret)
+- return ret;
+-
+- i2s_tdm->mclk_root0_freq = clk_get_rate(i2s_tdm->mclk_root0);
+- i2s_tdm->mclk_root1_freq = clk_get_rate(i2s_tdm->mclk_root1);
+- }
+-
+- return clk_set_rate(mclk_parent, mclk_parent_freq);
+-}
+-
+-static int rockchip_i2s_tdm_set_mclk(struct rk_i2s_tdm_dev *i2s_tdm,
+- struct snd_pcm_substream *substream,
+- struct clk **mclk)
+-{
+- unsigned int mclk_freq;
+- int ret;
+-
+- if (i2s_tdm->clk_trcm) {
+- if (i2s_tdm->mclk_tx_freq != i2s_tdm->mclk_rx_freq) {
+- dev_err(i2s_tdm->dev,
+- "clk_trcm, tx: %d and rx: %d should be the same\n",
+- i2s_tdm->mclk_tx_freq,
+- i2s_tdm->mclk_rx_freq);
+- return -EINVAL;
+- }
+-
+- ret = clk_set_rate(i2s_tdm->mclk_tx, i2s_tdm->mclk_tx_freq);
+- if (ret)
+- return ret;
+-
+- ret = clk_set_rate(i2s_tdm->mclk_rx, i2s_tdm->mclk_rx_freq);
+- if (ret)
+- return ret;
+-
+- /* mclk_rx is also ok. */
+- *mclk = i2s_tdm->mclk_tx;
+- } else {
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+- *mclk = i2s_tdm->mclk_tx;
+- mclk_freq = i2s_tdm->mclk_tx_freq;
+- } else {
+- *mclk = i2s_tdm->mclk_rx;
+- mclk_freq = i2s_tdm->mclk_rx_freq;
+- }
+-
+- ret = clk_set_rate(*mclk, mclk_freq);
+- if (ret)
+- return ret;
+- }
+-
+- return 0;
+-}
+-
+ static int rockchip_i2s_ch_to_io(unsigned int ch, bool substream_capture)
+ {
+ if (substream_capture) {
+@@ -853,19 +650,17 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+ {
+ struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);
+- struct clk *mclk;
+- int ret = 0;
+ unsigned int val = 0;
+ unsigned int mclk_rate, bclk_rate, div_bclk = 4, div_lrck = 64;
++ int err;
+
+ if (i2s_tdm->is_master_mode) {
+- if (i2s_tdm->mclk_calibrate)
+- rockchip_i2s_tdm_calibrate_mclk(i2s_tdm, substream,
+- params_rate(params));
++ struct clk *mclk = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++ i2s_tdm->mclk_tx : i2s_tdm->mclk_rx;
+
+- ret = rockchip_i2s_tdm_set_mclk(i2s_tdm, substream, &mclk);
+- if (ret)
+- return ret;
++ err = clk_set_rate(mclk, DEFAULT_MCLK_FS * params_rate(params));
++ if (err)
++ return err;
+
+ mclk_rate = clk_get_rate(mclk);
+ bclk_rate = i2s_tdm->frame_width * params_rate(params);
+@@ -973,96 +768,6 @@ static int rockchip_i2s_tdm_trigger(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
+-static int rockchip_i2s_tdm_set_sysclk(struct snd_soc_dai *cpu_dai, int stream,
+- unsigned int freq, int dir)
+-{
+- struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai);
+-
+- /* Put set mclk rate into rockchip_i2s_tdm_set_mclk() */
+- if (i2s_tdm->clk_trcm) {
+- i2s_tdm->mclk_tx_freq = freq;
+- i2s_tdm->mclk_rx_freq = freq;
+- } else {
+- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+- i2s_tdm->mclk_tx_freq = freq;
+- else
+- i2s_tdm->mclk_rx_freq = freq;
+- }
+-
+- dev_dbg(i2s_tdm->dev, "The target mclk_%s freq is: %d\n",
+- stream ? "rx" : "tx", freq);
+-
+- return 0;
+-}
+-
+-static int rockchip_i2s_tdm_clk_compensation_info(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_info *uinfo)
+-{
+- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+- uinfo->count = 1;
+- uinfo->value.integer.min = CLK_PPM_MIN;
+- uinfo->value.integer.max = CLK_PPM_MAX;
+- uinfo->value.integer.step = 1;
+-
+- return 0;
+-}
+-
+-static int rockchip_i2s_tdm_clk_compensation_get(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
+- struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);
+-
+- ucontrol->value.integer.value[0] = i2s_tdm->clk_ppm;
+-
+- return 0;
+-}
+-
+-static int rockchip_i2s_tdm_clk_compensation_put(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct snd_soc_dai *dai = snd_kcontrol_chip(kcontrol);
+- struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);
+- int ret = 0, ppm = 0;
+- int changed = 0;
+- unsigned long old_rate;
+-
+- if (ucontrol->value.integer.value[0] < CLK_PPM_MIN ||
+- ucontrol->value.integer.value[0] > CLK_PPM_MAX)
+- return -EINVAL;
+-
+- ppm = ucontrol->value.integer.value[0];
+-
+- old_rate = clk_get_rate(i2s_tdm->mclk_root0);
+- ret = rockchip_i2s_tdm_clk_set_rate(i2s_tdm, i2s_tdm->mclk_root0,
+- i2s_tdm->mclk_root0_freq, ppm);
+- if (ret)
+- return ret;
+- if (old_rate != clk_get_rate(i2s_tdm->mclk_root0))
+- changed = 1;
+-
+- if (clk_is_match(i2s_tdm->mclk_root0, i2s_tdm->mclk_root1))
+- return changed;
+-
+- old_rate = clk_get_rate(i2s_tdm->mclk_root1);
+- ret = rockchip_i2s_tdm_clk_set_rate(i2s_tdm, i2s_tdm->mclk_root1,
+- i2s_tdm->mclk_root1_freq, ppm);
+- if (ret)
+- return ret;
+- if (old_rate != clk_get_rate(i2s_tdm->mclk_root1))
+- changed = 1;
+-
+- return changed;
+-}
+-
+-static struct snd_kcontrol_new rockchip_i2s_tdm_compensation_control = {
+- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+- .name = "PCM Clock Compensation in PPM",
+- .info = rockchip_i2s_tdm_clk_compensation_info,
+- .get = rockchip_i2s_tdm_clk_compensation_get,
+- .put = rockchip_i2s_tdm_clk_compensation_put,
+-};
+-
+ static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai)
+ {
+ struct rk_i2s_tdm_dev *i2s_tdm = snd_soc_dai_get_drvdata(dai);
+@@ -1072,9 +777,6 @@ static int rockchip_i2s_tdm_dai_probe(struct snd_soc_dai *dai)
+ if (i2s_tdm->has_playback)
+ snd_soc_dai_dma_data_set_playback(dai, &i2s_tdm->playback_dma_data);
+
+- if (i2s_tdm->mclk_calibrate)
+- snd_soc_add_dai_controls(dai, &rockchip_i2s_tdm_compensation_control, 1);
+-
+ return 0;
+ }
+
+@@ -1115,7 +817,6 @@ static const struct snd_soc_dai_ops rockchip_i2s_tdm_dai_ops = {
+ .probe = rockchip_i2s_tdm_dai_probe,
+ .hw_params = rockchip_i2s_tdm_hw_params,
+ .set_bclk_ratio = rockchip_i2s_tdm_set_bclk_ratio,
+- .set_sysclk = rockchip_i2s_tdm_set_sysclk,
+ .set_fmt = rockchip_i2s_tdm_set_fmt,
+ .set_tdm_slot = rockchip_dai_tdm_slot,
+ .trigger = rockchip_i2s_tdm_trigger,
+@@ -1444,35 +1145,6 @@ static void rockchip_i2s_tdm_path_config(struct rk_i2s_tdm_dev *i2s_tdm,
+ rockchip_i2s_tdm_tx_path_config(i2s_tdm, num);
+ }
+
+-static int rockchip_i2s_tdm_get_calibrate_mclks(struct rk_i2s_tdm_dev *i2s_tdm)
+-{
+- int num_mclks = 0;
+-
+- i2s_tdm->mclk_tx_src = devm_clk_get(i2s_tdm->dev, "mclk_tx_src");
+- if (!IS_ERR(i2s_tdm->mclk_tx_src))
+- num_mclks++;
+-
+- i2s_tdm->mclk_rx_src = devm_clk_get(i2s_tdm->dev, "mclk_rx_src");
+- if (!IS_ERR(i2s_tdm->mclk_rx_src))
+- num_mclks++;
+-
+- i2s_tdm->mclk_root0 = devm_clk_get(i2s_tdm->dev, "mclk_root0");
+- if (!IS_ERR(i2s_tdm->mclk_root0))
+- num_mclks++;
+-
+- i2s_tdm->mclk_root1 = devm_clk_get(i2s_tdm->dev, "mclk_root1");
+- if (!IS_ERR(i2s_tdm->mclk_root1))
+- num_mclks++;
+-
+- if (num_mclks < 4 && num_mclks != 0)
+- return -ENOENT;
+-
+- if (num_mclks == 4)
+- i2s_tdm->mclk_calibrate = 1;
+-
+- return 0;
+-}
+-
+ static int rockchip_i2s_tdm_path_prepare(struct rk_i2s_tdm_dev *i2s_tdm,
+ struct device_node *np,
+ bool is_rx_path)
+@@ -1610,11 +1282,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
+ i2s_tdm->io_multiplex =
+ of_property_read_bool(node, "rockchip,io-multiplex");
+
+- ret = rockchip_i2s_tdm_get_calibrate_mclks(i2s_tdm);
+- if (ret)
+- return dev_err_probe(i2s_tdm->dev, ret,
+- "mclk-calibrate clocks missing");
+-
+ regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(regs)) {
+ return dev_err_probe(i2s_tdm->dev, PTR_ERR(regs),
+@@ -1667,13 +1334,6 @@ static int rockchip_i2s_tdm_probe(struct platform_device *pdev)
+ goto err_disable_hclk;
+ }
+
+- if (i2s_tdm->mclk_calibrate) {
+- i2s_tdm->mclk_root0_initial_freq = clk_get_rate(i2s_tdm->mclk_root0);
+- i2s_tdm->mclk_root1_initial_freq = clk_get_rate(i2s_tdm->mclk_root1);
+- i2s_tdm->mclk_root0_freq = i2s_tdm->mclk_root0_initial_freq;
+- i2s_tdm->mclk_root1_freq = i2s_tdm->mclk_root1_initial_freq;
+- }
+-
+ pm_runtime_enable(&pdev->dev);
+
+ regmap_update_bits(i2s_tdm->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
+diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c
+index 14cf1a41fb0d1..9d103646973ad 100644
+--- a/sound/soc/sh/rz-ssi.c
++++ b/sound/soc/sh/rz-ssi.c
+@@ -1015,7 +1015,7 @@ static int rz_ssi_probe(struct platform_device *pdev)
+ dev_name(&pdev->dev), ssi);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+- "irq request error (dma_tx)\n");
++ "irq request error (dma_rt)\n");
+ } else {
+ if (ssi->irq_tx < 0)
+ return ssi->irq_tx;
+diff --git a/sound/soc/sof/amd/acp-loader.c b/sound/soc/sof/amd/acp-loader.c
+index e05eb7a86dd44..aad904839b817 100644
+--- a/sound/soc/sof/amd/acp-loader.c
++++ b/sound/soc/sof/amd/acp-loader.c
+@@ -173,7 +173,7 @@ int acp_dsp_pre_fw_run(struct snd_sof_dev *sdev)
+
+ adata = sdev->pdata->hw_pdata;
+
+- if (adata->signed_fw_image)
++ if (adata->quirks && adata->quirks->signed_fw_image)
+ size_fw = adata->fw_bin_size - ACP_FIRMWARE_SIGNATURE;
+ else
+ size_fw = adata->fw_bin_size;
+@@ -267,29 +267,49 @@ int acp_sof_load_signed_firmware(struct snd_sof_dev *sdev)
+ {
+ struct snd_sof_pdata *plat_data = sdev->pdata;
+ struct acp_dev_data *adata = plat_data->hw_pdata;
++ const char *fw_filename;
+ int ret;
+
+- ret = request_firmware(&sdev->basefw.fw, adata->fw_code_bin, sdev->dev);
++ fw_filename = kasprintf(GFP_KERNEL, "%s/%s",
++ plat_data->fw_filename_prefix,
++ adata->fw_code_bin);
++ if (!fw_filename)
++ return -ENOMEM;
++
++ ret = request_firmware(&sdev->basefw.fw, fw_filename, sdev->dev);
+ if (ret < 0) {
++ kfree(fw_filename);
+ dev_err(sdev->dev, "sof signed firmware code bin is missing\n");
+ return ret;
+ } else {
+- dev_dbg(sdev->dev, "request_firmware %s successful\n", adata->fw_code_bin);
++ dev_dbg(sdev->dev, "request_firmware %s successful\n", fw_filename);
+ }
++ kfree(fw_filename);
++
+ ret = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_IRAM, 0,
+- (void *)sdev->basefw.fw->data, sdev->basefw.fw->size);
++ (void *)sdev->basefw.fw->data,
++ sdev->basefw.fw->size);
++
++ fw_filename = kasprintf(GFP_KERNEL, "%s/%s",
++ plat_data->fw_filename_prefix,
++ adata->fw_data_bin);
++ if (!fw_filename)
++ return -ENOMEM;
+
+- ret = request_firmware(&adata->fw_dbin, adata->fw_data_bin, sdev->dev);
++ ret = request_firmware(&adata->fw_dbin, fw_filename, sdev->dev);
+ if (ret < 0) {
++ kfree(fw_filename);
+ dev_err(sdev->dev, "sof signed firmware data bin is missing\n");
+ return ret;
+
+ } else {
+- dev_dbg(sdev->dev, "request_firmware %s successful\n", adata->fw_data_bin);
++ dev_dbg(sdev->dev, "request_firmware %s successful\n", fw_filename);
+ }
++ kfree(fw_filename);
+
+ ret = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_DRAM, 0,
+- (void *)adata->fw_dbin->data, adata->fw_dbin->size);
++ (void *)adata->fw_dbin->data,
++ adata->fw_dbin->size);
+ return ret;
+ }
+ EXPORT_SYMBOL_NS(acp_sof_load_signed_firmware, SND_SOC_SOF_AMD_COMMON);
+diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c
+index 07632ae6ccf5e..4db8cdc91daae 100644
+--- a/sound/soc/sof/amd/acp.c
++++ b/sound/soc/sof/amd/acp.c
+@@ -20,12 +20,15 @@
+ #include "acp.h"
+ #include "acp-dsp-offset.h"
+
+-#define SECURED_FIRMWARE 1
+-
+ static bool enable_fw_debug;
+ module_param(enable_fw_debug, bool, 0444);
+ MODULE_PARM_DESC(enable_fw_debug, "Enable Firmware debug");
+
++static struct acp_quirk_entry quirk_valve_galileo = {
++ .signed_fw_image = true,
++ .skip_iram_dram_size_mod = true,
++};
++
+ const struct dmi_system_id acp_sof_quirk_table[] = {
+ {
+ /* Valve Jupiter device */
+@@ -34,7 +37,7 @@ const struct dmi_system_id acp_sof_quirk_table[] = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "Galileo"),
+ DMI_MATCH(DMI_PRODUCT_FAMILY, "Sephiroth"),
+ },
+- .driver_data = (void *)SECURED_FIRMWARE,
++ .driver_data = &quirk_valve_galileo,
+ },
+ {}
+ };
+@@ -255,7 +258,7 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
+ }
+ }
+
+- if (adata->signed_fw_image)
++ if (adata->quirks && adata->quirks->signed_fw_image)
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_DMA_INCLUDE_HDR, ACP_SHA_HEADER);
+
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SHA_DMA_STRT_ADDR, start_addr);
+@@ -279,7 +282,7 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
+ }
+
+ /* psp_send_cmd only required for vangogh platform (rev - 5) */
+- if (desc->rev == 5) {
++ if (desc->rev == 5 && !(adata->quirks && adata->quirks->skip_iram_dram_size_mod)) {
+ /* Modify IRAM and DRAM size */
+ ret = psp_send_cmd(adata, MBOX_ACP_IRAM_DRAM_FENCE_COMMAND | IRAM_DRAM_FENCE_2);
+ if (ret)
+@@ -493,7 +496,6 @@ EXPORT_SYMBOL_NS(amd_sof_acp_resume, SND_SOC_SOF_AMD_COMMON);
+ int amd_sof_acp_probe(struct snd_sof_dev *sdev)
+ {
+ struct pci_dev *pci = to_pci_dev(sdev->dev);
+- struct snd_sof_pdata *plat_data = sdev->pdata;
+ struct acp_dev_data *adata;
+ const struct sof_amd_acp_desc *chip;
+ const struct dmi_system_id *dmi_id;
+@@ -557,20 +559,29 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev)
+ sdev->debug_box.offset = sdev->host_box.offset + sdev->host_box.size;
+ sdev->debug_box.size = BOX_SIZE_1024;
+
+- adata->signed_fw_image = false;
+ dmi_id = dmi_first_match(acp_sof_quirk_table);
+- if (dmi_id && dmi_id->driver_data) {
+- adata->fw_code_bin = kasprintf(GFP_KERNEL, "%s/sof-%s-code.bin",
+- plat_data->fw_filename_prefix,
+- chip->name);
+- adata->fw_data_bin = kasprintf(GFP_KERNEL, "%s/sof-%s-data.bin",
+- plat_data->fw_filename_prefix,
+- chip->name);
+- adata->signed_fw_image = dmi_id->driver_data;
+-
+- dev_dbg(sdev->dev, "fw_code_bin:%s, fw_data_bin:%s\n", adata->fw_code_bin,
+- adata->fw_data_bin);
++ if (dmi_id) {
++ adata->quirks = dmi_id->driver_data;
++
++ if (adata->quirks->signed_fw_image) {
++ adata->fw_code_bin = devm_kasprintf(sdev->dev, GFP_KERNEL,
++ "sof-%s-code.bin",
++ chip->name);
++ if (!adata->fw_code_bin) {
++ ret = -ENOMEM;
++ goto free_ipc_irq;
++ }
++
++ adata->fw_data_bin = devm_kasprintf(sdev->dev, GFP_KERNEL,
++ "sof-%s-data.bin",
++ chip->name);
++ if (!adata->fw_data_bin) {
++ ret = -ENOMEM;
++ goto free_ipc_irq;
++ }
++ }
+ }
++
+ adata->enable_fw_debug = enable_fw_debug;
+ acp_memory_init(sdev);
+
+diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h
+index c645aee216fd0..7d4a8b6b3cc67 100644
+--- a/sound/soc/sof/amd/acp.h
++++ b/sound/soc/sof/amd/acp.h
+@@ -193,6 +193,11 @@ struct sof_amd_acp_desc {
+ u32 probe_reg_offset;
+ };
+
++struct acp_quirk_entry {
++ bool signed_fw_image;
++ bool skip_iram_dram_size_mod;
++};
++
+ /* Common device data struct for ACP devices */
+ struct acp_dev_data {
+ struct snd_sof_dev *dev;
+@@ -213,7 +218,7 @@ struct acp_dev_data {
+ u8 *data_buf;
+ dma_addr_t sram_dma_addr;
+ u8 *sram_data_buf;
+- bool signed_fw_image;
++ struct acp_quirk_entry *quirks;
+ struct dma_descriptor dscr_info[ACP_MAX_DESC];
+ struct acp_dsp_stream stream_buf[ACP_MAX_STREAM];
+ struct acp_dsp_stream *dtrace_stream;
+diff --git a/sound/soc/sof/amd/vangogh.c b/sound/soc/sof/amd/vangogh.c
+index de15d21aa6d98..bc6ffdb5471a5 100644
+--- a/sound/soc/sof/amd/vangogh.c
++++ b/sound/soc/sof/amd/vangogh.c
+@@ -143,6 +143,7 @@ EXPORT_SYMBOL_NS(sof_vangogh_ops, SND_SOC_SOF_AMD_COMMON);
+ int sof_vangogh_ops_init(struct snd_sof_dev *sdev)
+ {
+ const struct dmi_system_id *dmi_id;
++ struct acp_quirk_entry *quirks;
+
+ /* common defaults */
+ memcpy(&sof_vangogh_ops, &sof_acp_common_ops, sizeof(struct snd_sof_dsp_ops));
+@@ -151,8 +152,12 @@ int sof_vangogh_ops_init(struct snd_sof_dev *sdev)
+ sof_vangogh_ops.num_drv = ARRAY_SIZE(vangogh_sof_dai);
+
+ dmi_id = dmi_first_match(acp_sof_quirk_table);
+- if (dmi_id && dmi_id->driver_data)
+- sof_vangogh_ops.load_firmware = acp_sof_load_signed_firmware;
++ if (dmi_id) {
++ quirks = dmi_id->driver_data;
++
++ if (quirks->signed_fw_image)
++ sof_vangogh_ops.load_firmware = acp_sof_load_signed_firmware;
++ }
+
+ return 0;
+ }
+diff --git a/sound/soc/sof/fw-file-profile.c b/sound/soc/sof/fw-file-profile.c
+index 138a1ca2c4a85..b56b14232444c 100644
+--- a/sound/soc/sof/fw-file-profile.c
++++ b/sound/soc/sof/fw-file-profile.c
+@@ -89,6 +89,12 @@ static int sof_test_topology_file(struct device *dev,
+ return ret;
+ }
+
++static bool sof_platform_uses_generic_loader(struct snd_sof_dev *sdev)
++{
++ return (sdev->pdata->desc->ops->load_firmware == snd_sof_load_firmware_raw ||
++ sdev->pdata->desc->ops->load_firmware == snd_sof_load_firmware_memcpy);
++}
++
+ static int
+ sof_file_profile_for_ipc_type(struct snd_sof_dev *sdev,
+ enum sof_ipc_type ipc_type,
+@@ -130,7 +136,8 @@ sof_file_profile_for_ipc_type(struct snd_sof_dev *sdev,
+ * For default path and firmware name do a verification before
+ * continuing further.
+ */
+- if (base_profile->fw_path || base_profile->fw_name) {
++ if ((base_profile->fw_path || base_profile->fw_name) &&
++ sof_platform_uses_generic_loader(sdev)) {
+ ret = sof_test_firmware_file(dev, out_profile, &ipc_type);
+ if (ret)
+ return ret;
+@@ -181,7 +188,8 @@ sof_file_profile_for_ipc_type(struct snd_sof_dev *sdev,
+ out_profile->ipc_type = ipc_type;
+
+ /* Test only default firmware file */
+- if (!base_profile->fw_path && !base_profile->fw_name)
++ if ((!base_profile->fw_path && !base_profile->fw_name) &&
++ sof_platform_uses_generic_loader(sdev))
+ ret = sof_test_firmware_file(dev, out_profile, NULL);
+
+ if (!ret)
+@@ -267,7 +275,11 @@ static void sof_print_profile_info(struct snd_sof_dev *sdev,
+
+ dev_info(dev, "Firmware paths/files for ipc type %d:\n", profile->ipc_type);
+
+- dev_info(dev, " Firmware file: %s/%s\n", profile->fw_path, profile->fw_name);
++ /* The firmware path is only valid when generic loader is used */
++ if (sof_platform_uses_generic_loader(sdev))
++ dev_info(dev, " Firmware file: %s/%s\n",
++ profile->fw_path, profile->fw_name);
++
+ if (profile->fw_lib_path)
+ dev_info(dev, " Firmware lib path: %s\n", profile->fw_lib_path);
+ dev_info(dev, " Topology file: %s/%s\n", profile->tplg_path, profile->tplg_name);
+diff --git a/sound/soc/sof/ipc3-loader.c b/sound/soc/sof/ipc3-loader.c
+index 28218766d2114..6e3ef06721106 100644
+--- a/sound/soc/sof/ipc3-loader.c
++++ b/sound/soc/sof/ipc3-loader.c
+@@ -148,6 +148,8 @@ static size_t sof_ipc3_fw_parse_ext_man(struct snd_sof_dev *sdev)
+
+ head = (struct sof_ext_man_header *)fw->data;
+ remaining = head->full_size - head->header_size;
++ if (remaining < 0 || remaining > sdev->basefw.fw->size)
++ return -EINVAL;
+ ext_man_size = ipc3_fw_ext_man_size(sdev, fw);
+
+ /* Assert firmware starts with extended manifest */
+diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
+index 6de605a601e5f..bd114be537d7a 100644
+--- a/sound/usb/mixer_scarlett2.c
++++ b/sound/usb/mixer_scarlett2.c
+@@ -173,7 +173,12 @@
+
+ /* some gui mixers can't handle negative ctl values */
+ #define SCARLETT2_VOLUME_BIAS 127
+-#define SCARLETT2_GAIN_BIAS 70
++
++/* maximum preamp input gain and value
++ * values are from 0 to 70, preamp gain is from 0 to 69 dB
++ */
++#define SCARLETT2_MAX_GAIN_VALUE 70
++#define SCARLETT2_MAX_GAIN_DB 69
+
+ /* mixer range from -80dB to +6dB in 0.5dB steps */
+ #define SCARLETT2_MIXER_MIN_DB -80
+@@ -284,14 +289,22 @@ static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = {
+ "Mute Playback Switch", "Dim Playback Switch"
+ };
+
+-/* Autogain Status Values */
+-enum {
+- SCARLETT2_AUTOGAIN_STATUS_STOPPED,
+- SCARLETT2_AUTOGAIN_STATUS_RUNNING,
+- SCARLETT2_AUTOGAIN_STATUS_FAILED,
+- SCARLETT2_AUTOGAIN_STATUS_CANCELLED,
+- SCARLETT2_AUTOGAIN_STATUS_UNKNOWN,
+- SCARLETT2_AUTOGAIN_STATUS_COUNT
++/* The autogain_status is set based on the autogain_switch and
++ * raw_autogain_status values.
++ *
++ * If autogain_switch is set, autogain_status is set to 0 (Running).
++ * The other status values are from the raw_autogain_status value + 1.
++ */
++static const char *const scarlett2_autogain_status_texts[] = {
++ "Running",
++ "Success",
++ "SuccessDRover",
++ "WarnMinGainLimit",
++ "FailDRunder",
++ "FailMaxGainLimit",
++ "FailClipped",
++ "Cancelled",
++ "Invalid"
+ };
+
+ /* Power Status Values */
+@@ -415,7 +428,7 @@ enum {
+ SCARLETT2_CONFIG_INPUT_SELECT_SWITCH,
+ SCARLETT2_CONFIG_INPUT_LINK_SWITCH,
+ SCARLETT2_CONFIG_POWER_EXT,
+- SCARLETT2_CONFIG_POWER_STATUS,
++ SCARLETT2_CONFIG_POWER_LOW,
+ SCARLETT2_CONFIG_PCM_INPUT_SWITCH,
+ SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN,
+ SCARLETT2_CONFIG_COUNT
+@@ -723,8 +736,8 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4 = {
+ [SCARLETT2_CONFIG_POWER_EXT] = {
+ .offset = 0x168 },
+
+- [SCARLETT2_CONFIG_POWER_STATUS] = {
+- .offset = 0x66 }
++ [SCARLETT2_CONFIG_POWER_LOW] = {
++ .offset = 0x16d }
+ }
+ };
+
+@@ -2835,9 +2848,9 @@ static int scarlett2_autogain_is_running(struct scarlett2_data *private)
+ {
+ int i;
+
++ /* autogain_status[] is 0 if autogain is running */
+ for (i = 0; i < private->info->gain_input_count; i++)
+- if (private->autogain_status[i] ==
+- SCARLETT2_AUTOGAIN_STATUS_RUNNING)
++ if (!private->autogain_status[i])
+ return 1;
+
+ return 0;
+@@ -2867,25 +2880,25 @@ static int scarlett2_update_autogain(struct usb_mixer_interface *mixer)
+ return err;
+
+ /* Translate autogain_switch and raw_autogain_status into
+- * autogain_status
++ * autogain_status.
++ *
++ * When autogain_switch[] is set, the status is the first
++ * element in scarlett2_autogain_status_texts[] (Running). The
++ * subsequent elements correspond to the status value from the
++ * device (raw_autogain_status[]) + 1. The last element is
++ * "Invalid", in case the device reports a status outside the
++ * range of scarlett2_autogain_status_texts[].
+ */
+ for (i = 0; i < info->gain_input_count; i++)
+ if (private->autogain_switch[i])
++ private->autogain_status[i] = 0;
++ else if (raw_autogain_status[i] <
++ ARRAY_SIZE(scarlett2_autogain_status_texts) - 1)
+ private->autogain_status[i] =
+- SCARLETT2_AUTOGAIN_STATUS_RUNNING;
+- else if (raw_autogain_status[i] == 0)
+- private->autogain_status[i] =
+- SCARLETT2_AUTOGAIN_STATUS_STOPPED;
+- else if (raw_autogain_status[i] >= 2 &&
+- raw_autogain_status[i] <= 5)
+- private->autogain_status[i] =
+- SCARLETT2_AUTOGAIN_STATUS_FAILED;
+- else if (raw_autogain_status[i] == 6)
+- private->autogain_status[i] =
+- SCARLETT2_AUTOGAIN_STATUS_CANCELLED;
++ raw_autogain_status[i] + 1;
+ else
+ private->autogain_status[i] =
+- SCARLETT2_AUTOGAIN_STATUS_UNKNOWN;
++ ARRAY_SIZE(scarlett2_autogain_status_texts) - 1;
+
+ return 0;
+ }
+@@ -3111,12 +3124,10 @@ static int scarlett2_autogain_switch_ctl_put(
+ static int scarlett2_autogain_status_ctl_info(
+ struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
+ {
+- static const char *const values[SCARLETT2_AUTOGAIN_STATUS_COUNT] = {
+- "Stopped", "Running", "Failed", "Cancelled", "Unknown"
+- };
+-
+ return snd_ctl_enum_info(
+- uinfo, 1, SCARLETT2_AUTOGAIN_STATUS_COUNT, values);
++ uinfo, 1,
++ ARRAY_SIZE(scarlett2_autogain_status_texts),
++ scarlett2_autogain_status_texts);
+ }
+
+ static const struct snd_kcontrol_new scarlett2_autogain_switch_ctl = {
+@@ -3458,7 +3469,7 @@ static int scarlett2_input_gain_ctl_info(struct snd_kcontrol *kctl,
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = elem->channels;
+ uinfo->value.integer.min = 0;
+- uinfo->value.integer.max = SCARLETT2_GAIN_BIAS;
++ uinfo->value.integer.max = SCARLETT2_MAX_GAIN_VALUE;
+ uinfo->value.integer.step = 1;
+
+ unlock:
+@@ -3535,7 +3546,7 @@ static int scarlett2_input_gain_ctl_put(struct snd_kcontrol *kctl,
+ }
+
+ static const DECLARE_TLV_DB_MINMAX(
+- db_scale_scarlett2_gain, -SCARLETT2_GAIN_BIAS * 100, 0
++ db_scale_scarlett2_gain, 0, SCARLETT2_MAX_GAIN_DB * 100
+ );
+
+ static const struct snd_kcontrol_new scarlett2_input_gain_ctl = {
+@@ -6294,8 +6305,7 @@ static int scarlett2_update_power_status(struct usb_mixer_interface *mixer)
+ {
+ struct scarlett2_data *private = mixer->private_data;
+ int err;
+- u8 power_ext;
+- u8 power_status;
++ u8 power_ext, power_low;
+
+ private->power_status_updated = 0;
+
+@@ -6304,12 +6314,12 @@ static int scarlett2_update_power_status(struct usb_mixer_interface *mixer)
+ if (err < 0)
+ return err;
+
+- err = scarlett2_usb_get_config(mixer, SCARLETT2_CONFIG_POWER_STATUS,
+- 1, &power_status);
++ err = scarlett2_usb_get_config(mixer, SCARLETT2_CONFIG_POWER_LOW,
++ 1, &power_low);
+ if (err < 0)
+ return err;
+
+- if (power_status > 1)
++ if (power_low)
+ private->power_status = SCARLETT2_POWER_STATUS_FAIL;
+ else if (power_ext)
+ private->power_status = SCARLETT2_POWER_STATUS_EXT;
+diff --git a/sound/usb/stream.c b/sound/usb/stream.c
+index 3d4add94e367d..d5409f3879455 100644
+--- a/sound/usb/stream.c
++++ b/sound/usb/stream.c
+@@ -300,9 +300,12 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
+ c = 0;
+
+ if (bits) {
+- for (; bits && *maps; maps++, bits >>= 1)
++ for (; bits && *maps; maps++, bits >>= 1) {
+ if (bits & 1)
+ chmap->map[c++] = *maps;
++ if (c == chmap->channels)
++ break;
++ }
+ } else {
+ /* If we're missing wChannelConfig, then guess something
+ to make sure the channel map is not skipped entirely */
+diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c
+index cb46667a6b2e7..35b6859dd7c3d 100644
+--- a/tools/bpf/bpftool/link.c
++++ b/tools/bpf/bpftool/link.c
+@@ -977,7 +977,7 @@ static int do_show_link(int fd)
+ cookies = calloc(count, sizeof(__u64));
+ if (!cookies) {
+ p_err("mem alloc failed");
+- free(cookies);
++ free(ref_ctr_offsets);
+ free(offsets);
+ close(fd);
+ return -ENOMEM;
+diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
+index feb8e305804fc..9cb42a3366c07 100644
+--- a/tools/bpf/bpftool/prog.c
++++ b/tools/bpf/bpftool/prog.c
+@@ -2298,7 +2298,7 @@ static int profile_open_perf_events(struct profiler_bpf *obj)
+ int map_fd;
+
+ profile_perf_events = calloc(
+- sizeof(int), obj->rodata->num_cpu * obj->rodata->num_metric);
++ obj->rodata->num_cpu * obj->rodata->num_metric, sizeof(int));
+ if (!profile_perf_events) {
+ p_err("failed to allocate memory for perf_event array: %s",
+ strerror(errno));
+diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
+index 27a23196d58e1..d9520cb826b31 100644
+--- a/tools/bpf/resolve_btfids/main.c
++++ b/tools/bpf/resolve_btfids/main.c
+@@ -70,6 +70,7 @@
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <errno.h>
++#include <linux/btf_ids.h>
+ #include <linux/rbtree.h>
+ #include <linux/zalloc.h>
+ #include <linux/err.h>
+@@ -78,7 +79,7 @@
+ #include <subcmd/parse-options.h>
+
+ #define BTF_IDS_SECTION ".BTF_ids"
+-#define BTF_ID "__BTF_ID__"
++#define BTF_ID_PREFIX "__BTF_ID__"
+
+ #define BTF_STRUCT "struct"
+ #define BTF_UNION "union"
+@@ -89,6 +90,14 @@
+
+ #define ADDR_CNT 100
+
++#if __BYTE_ORDER == __LITTLE_ENDIAN
++# define ELFDATANATIVE ELFDATA2LSB
++#elif __BYTE_ORDER == __BIG_ENDIAN
++# define ELFDATANATIVE ELFDATA2MSB
++#else
++# error "Unknown machine endianness!"
++#endif
++
+ struct btf_id {
+ struct rb_node rb_node;
+ char *name;
+@@ -116,6 +125,7 @@ struct object {
+ int idlist_shndx;
+ size_t strtabidx;
+ unsigned long idlist_addr;
++ int encoding;
+ } efile;
+
+ struct rb_root sets;
+@@ -161,7 +171,7 @@ static int eprintf(int level, int var, const char *fmt, ...)
+
+ static bool is_btf_id(const char *name)
+ {
+- return name && !strncmp(name, BTF_ID, sizeof(BTF_ID) - 1);
++ return name && !strncmp(name, BTF_ID_PREFIX, sizeof(BTF_ID_PREFIX) - 1);
+ }
+
+ static struct btf_id *btf_id__find(struct rb_root *root, const char *name)
+@@ -319,6 +329,7 @@ static int elf_collect(struct object *obj)
+ {
+ Elf_Scn *scn = NULL;
+ size_t shdrstrndx;
++ GElf_Ehdr ehdr;
+ int idx = 0;
+ Elf *elf;
+ int fd;
+@@ -350,6 +361,13 @@ static int elf_collect(struct object *obj)
+ return -1;
+ }
+
++ if (gelf_getehdr(obj->efile.elf, &ehdr) == NULL) {
++ pr_err("FAILED cannot get ELF header: %s\n",
++ elf_errmsg(-1));
++ return -1;
++ }
++ obj->efile.encoding = ehdr.e_ident[EI_DATA];
++
+ /*
+ * Scan all the elf sections and look for save data
+ * from .BTF_ids section and symbols.
+@@ -441,7 +459,7 @@ static int symbols_collect(struct object *obj)
+ * __BTF_ID__TYPE__vfs_truncate__0
+ * prefix = ^
+ */
+- prefix = name + sizeof(BTF_ID) - 1;
++ prefix = name + sizeof(BTF_ID_PREFIX) - 1;
+
+ /* struct */
+ if (!strncmp(prefix, BTF_STRUCT, sizeof(BTF_STRUCT) - 1)) {
+@@ -649,19 +667,18 @@ static int cmp_id(const void *pa, const void *pb)
+ static int sets_patch(struct object *obj)
+ {
+ Elf_Data *data = obj->efile.idlist;
+- int *ptr = data->d_buf;
+ struct rb_node *next;
+
+ next = rb_first(&obj->sets);
+ while (next) {
+- unsigned long addr, idx;
++ struct btf_id_set8 *set8;
++ struct btf_id_set *set;
++ unsigned long addr, off;
+ struct btf_id *id;
+- int *base;
+- int cnt;
+
+ id = rb_entry(next, struct btf_id, rb_node);
+ addr = id->addr[0];
+- idx = addr - obj->efile.idlist_addr;
++ off = addr - obj->efile.idlist_addr;
+
+ /* sets are unique */
+ if (id->addr_cnt != 1) {
+@@ -670,14 +687,39 @@ static int sets_patch(struct object *obj)
+ return -1;
+ }
+
+- idx = idx / sizeof(int);
+- base = &ptr[idx] + (id->is_set8 ? 2 : 1);
+- cnt = ptr[idx];
++ if (id->is_set) {
++ set = data->d_buf + off;
++ qsort(set->ids, set->cnt, sizeof(set->ids[0]), cmp_id);
++ } else {
++ set8 = data->d_buf + off;
++ /*
++ * Make sure id is at the beginning of the pairs
++ * struct, otherwise the below qsort would not work.
++ */
++ BUILD_BUG_ON(set8->pairs != &set8->pairs[0].id);
++ qsort(set8->pairs, set8->cnt, sizeof(set8->pairs[0]), cmp_id);
+
+- pr_debug("sorting addr %5lu: cnt %6d [%s]\n",
+- (idx + 1) * sizeof(int), cnt, id->name);
++ /*
++ * When ELF endianness does not match endianness of the
++ * host, libelf will do the translation when updating
++ * the ELF. This, however, corrupts SET8 flags which are
++ * already in the target endianness. So, let's bswap
++ * them to the host endianness and libelf will then
++ * correctly translate everything.
++ */
++ if (obj->efile.encoding != ELFDATANATIVE) {
++ int i;
++
++ set8->flags = bswap_32(set8->flags);
++ for (i = 0; i < set8->cnt; i++) {
++ set8->pairs[i].flags =
++ bswap_32(set8->pairs[i].flags);
++ }
++ }
++ }
+
+- qsort(base, cnt, id->is_set8 ? sizeof(uint64_t) : sizeof(int), cmp_id);
++ pr_debug("sorting addr %5lu: cnt %6d [%s]\n",
++ off, id->is_set ? set->cnt : set8->cnt, id->name);
+
+ next = rb_next(next);
+ }
+diff --git a/tools/include/linux/btf_ids.h b/tools/include/linux/btf_ids.h
+index 2f882d5cb30f5..72535f00572f6 100644
+--- a/tools/include/linux/btf_ids.h
++++ b/tools/include/linux/btf_ids.h
+@@ -8,6 +8,15 @@ struct btf_id_set {
+ u32 ids[];
+ };
+
++struct btf_id_set8 {
++ u32 cnt;
++ u32 flags;
++ struct {
++ u32 id;
++ u32 flags;
++ } pairs[];
++};
++
+ #ifdef CONFIG_DEBUG_INFO_BTF
+
+ #include <linux/compiler.h> /* for __PASTE */
+diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
+index d0f53772bdc02..dad7917903d19 100644
+--- a/tools/lib/bpf/bpf.h
++++ b/tools/lib/bpf/bpf.h
+@@ -35,7 +35,7 @@
+ extern "C" {
+ #endif
+
+-int libbpf_set_memlock_rlim(size_t memlock_bytes);
++LIBBPF_API int libbpf_set_memlock_rlim(size_t memlock_bytes);
+
+ struct bpf_map_create_opts {
+ size_t sz; /* size of this struct for forward/backward compatibility */
+diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
+index afd09571c482b..92bca96587a4a 100644
+--- a/tools/lib/bpf/libbpf.c
++++ b/tools/lib/bpf/libbpf.c
+@@ -33,6 +33,7 @@
+ #include <linux/filter.h>
+ #include <linux/limits.h>
+ #include <linux/perf_event.h>
++#include <linux/bpf_perf_event.h>
+ #include <linux/ring_buffer.h>
+ #include <sys/epoll.h>
+ #include <sys/ioctl.h>
+@@ -70,6 +71,7 @@
+
+ static struct bpf_map *bpf_object__add_map(struct bpf_object *obj);
+ static bool prog_is_subprog(const struct bpf_object *obj, const struct bpf_program *prog);
++static int map_set_def_max_entries(struct bpf_map *map);
+
+ static const char * const attach_type_name[] = {
+ [BPF_CGROUP_INET_INGRESS] = "cgroup_inet_ingress",
+@@ -5172,6 +5174,9 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b
+
+ if (bpf_map_type__is_map_in_map(def->type)) {
+ if (map->inner_map) {
++ err = map_set_def_max_entries(map->inner_map);
++ if (err)
++ return err;
+ err = bpf_object__create_map(obj, map->inner_map, true);
+ if (err) {
+ pr_warn("map '%s': failed to create inner map: %d\n",
+@@ -6695,6 +6700,14 @@ static struct {
+ /* all other program types don't have "named" context structs */
+ };
+
++/* forward declarations for arch-specific underlying types of bpf_user_pt_regs_t typedef,
++ * for below __builtin_types_compatible_p() checks;
++ * with this approach we don't need any extra arch-specific #ifdef guards
++ */
++struct pt_regs;
++struct user_pt_regs;
++struct user_regs_struct;
++
+ static bool need_func_arg_type_fixup(const struct btf *btf, const struct bpf_program *prog,
+ const char *subprog_name, int arg_idx,
+ int arg_type_id, const char *ctx_name)
+@@ -6735,11 +6748,21 @@ static bool need_func_arg_type_fixup(const struct btf *btf, const struct bpf_pro
+ /* special cases */
+ switch (prog->type) {
+ case BPF_PROG_TYPE_KPROBE:
+- case BPF_PROG_TYPE_PERF_EVENT:
+ /* `struct pt_regs *` is expected, but we need to fix up */
+ if (btf_is_struct(t) && strcmp(tname, "pt_regs") == 0)
+ return true;
+ break;
++ case BPF_PROG_TYPE_PERF_EVENT:
++ if (__builtin_types_compatible_p(bpf_user_pt_regs_t, struct pt_regs) &&
++ btf_is_struct(t) && strcmp(tname, "pt_regs") == 0)
++ return true;
++ if (__builtin_types_compatible_p(bpf_user_pt_regs_t, struct user_pt_regs) &&
++ btf_is_struct(t) && strcmp(tname, "user_pt_regs") == 0)
++ return true;
++ if (__builtin_types_compatible_p(bpf_user_pt_regs_t, struct user_regs_struct) &&
++ btf_is_struct(t) && strcmp(tname, "user_regs_struct") == 0)
++ return true;
++ break;
+ case BPF_PROG_TYPE_RAW_TRACEPOINT:
+ case BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE:
+ /* allow u64* as ctx */
+diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
+index 27e4e320e1a69..878a0d0b51f5c 100644
+--- a/tools/lib/bpf/libbpf_internal.h
++++ b/tools/lib/bpf/libbpf_internal.h
+@@ -18,6 +18,20 @@
+ #include <libelf.h>
+ #include "relo_core.h"
+
++/* Android's libc doesn't support AT_EACCESS in faccessat() implementation
++ * ([0]), and just returns -EINVAL even if file exists and is accessible.
++ * See [1] for issues caused by this.
++ *
++ * So just redefine it to 0 on Android.
++ *
++ * [0] https://android.googlesource.com/platform/bionic/+/refs/heads/android13-release/libc/bionic/faccessat.cpp#50
++ * [1] https://github.com/libbpf/libbpf-bootstrap/issues/250#issuecomment-1911324250
++ */
++#ifdef __ANDROID__
++#undef AT_EACCESS
++#define AT_EACCESS 0
++#endif
++
+ /* make sure libbpf doesn't use kernel-only integer typedefs */
+ #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64
+
+diff --git a/tools/lib/bpf/netlink.c b/tools/lib/bpf/netlink.c
+index 090bcf6e3b3d5..68a2def171751 100644
+--- a/tools/lib/bpf/netlink.c
++++ b/tools/lib/bpf/netlink.c
+@@ -496,8 +496,8 @@ int bpf_xdp_query(int ifindex, int xdp_flags, struct bpf_xdp_query_opts *opts)
+ if (err)
+ return libbpf_err(err);
+
+- opts->feature_flags = md.flags;
+- opts->xdp_zc_max_segs = md.xdp_zc_max_segs;
++ OPTS_SET(opts, feature_flags, md.flags);
++ OPTS_SET(opts, xdp_zc_max_segs, md.xdp_zc_max_segs);
+
+ skip_feature_flags:
+ return 0;
+diff --git a/tools/objtool/check.c b/tools/objtool/check.c
+index 548ec3cd7c00c..c4c2f75eadfd9 100644
+--- a/tools/objtool/check.c
++++ b/tools/objtool/check.c
+@@ -3620,6 +3620,18 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
+ }
+
+ if (!save_insn->visited) {
++ /*
++ * If the restore hint insn is at the
++ * beginning of a basic block and was
++ * branched to from elsewhere, and the
++ * save insn hasn't been visited yet,
++ * defer following this branch for now.
++ * It will be seen later via the
++ * straight-line path.
++ */
++ if (!prev_insn)
++ return 0;
++
+ WARN_INSN(insn, "objtool isn't smart enough to handle this CFI save/restore combo");
+ return 1;
+ }
+diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
+index f8774a9b1377a..116db7874412d 100644
+--- a/tools/perf/Makefile.perf
++++ b/tools/perf/Makefile.perf
+@@ -1167,7 +1167,7 @@ bpf-skel:
+ endif # CONFIG_PERF_BPF_SKEL
+
+ bpf-skel-clean:
+- $(call QUIET_CLEAN, bpf-skel) $(RM) -r $(SKEL_TMP_OUT) $(SKELETONS)
++ $(call QUIET_CLEAN, bpf-skel) $(RM) -r $(SKEL_TMP_OUT) $(SKELETONS) $(SKEL_OUT)/vmlinux.h
+
+ clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean $(LIBSYMBOL)-clean $(LIBPERF)-clean arm64-sysreg-defs-clean fixdep-clean python-clean bpf-skel-clean tests-coresight-targets-clean
+ $(call QUIET_CLEAN, core-objs) $(RM) $(LIBPERF_A) $(OUTPUT)perf-archive $(OUTPUT)perf-iostat $(LANG_BINDINGS)
+diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
+index 86c9101251726..3ddd4381aebd2 100644
+--- a/tools/perf/builtin-record.c
++++ b/tools/perf/builtin-record.c
+@@ -1830,8 +1830,8 @@ static int
+ record__switch_output(struct record *rec, bool at_exit)
+ {
+ struct perf_data *data = &rec->data;
++ char *new_filename = NULL;
+ int fd, err;
+- char *new_filename;
+
+ /* Same Size: "2015122520103046"*/
+ char timestamp[] = "InvalidTimestamp";
+@@ -2472,6 +2472,11 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
+ if (data->is_pipe && rec->evlist->core.nr_entries == 1)
+ rec->opts.sample_id = true;
+
++ if (rec->timestamp_filename && perf_data__is_pipe(data)) {
++ rec->timestamp_filename = false;
++ pr_warning("WARNING: --timestamp-filename option is not available in pipe mode.\n");
++ }
++
+ evlist__uniquify_name(rec->evlist);
+
+ /* Debug message used by test scripts */
+diff --git a/tools/perf/pmu-events/arch/x86/amdzen4/cache.json b/tools/perf/pmu-events/arch/x86/amdzen4/cache.json
+index ecbe9660b2b31..e6d710cf3ce29 100644
+--- a/tools/perf/pmu-events/arch/x86/amdzen4/cache.json
++++ b/tools/perf/pmu-events/arch/x86/amdzen4/cache.json
+@@ -676,6 +676,10 @@
+ "EventCode": "0xac",
+ "BriefDescription": "Average sampled latency when data is sourced from DRAM in the same NUMA node.",
+ "UMask": "0x01",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -683,6 +687,10 @@
+ "EventCode": "0xac",
+ "BriefDescription": "Average sampled latency when data is sourced from DRAM in a different NUMA node.",
+ "UMask": "0x02",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -690,6 +698,10 @@
+ "EventCode": "0xac",
+ "BriefDescription": "Average sampled latency when data is sourced from another CCX's cache when the address was in the same NUMA node.",
+ "UMask": "0x04",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -697,6 +709,10 @@
+ "EventCode": "0xac",
+ "BriefDescription": "Average sampled latency when data is sourced from another CCX's cache when the address was in a different NUMA node.",
+ "UMask": "0x08",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -704,6 +720,10 @@
+ "EventCode": "0xac",
+ "BriefDescription": "Average sampled latency when data is sourced from extension memory (CXL) in the same NUMA node.",
+ "UMask": "0x10",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -711,6 +731,10 @@
+ "EventCode": "0xac",
+ "BriefDescription": "Average sampled latency when data is sourced from extension memory (CXL) in a different NUMA node.",
+ "UMask": "0x20",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -718,6 +742,10 @@
+ "EventCode": "0xac",
+ "BriefDescription": "Average sampled latency from all data sources.",
+ "UMask": "0x3f",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -725,6 +753,10 @@
+ "EventCode": "0xad",
+ "BriefDescription": "L3 cache fill requests sourced from DRAM in the same NUMA node.",
+ "UMask": "0x01",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -732,6 +764,10 @@
+ "EventCode": "0xad",
+ "BriefDescription": "L3 cache fill requests sourced from DRAM in a different NUMA node.",
+ "UMask": "0x02",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -739,6 +775,10 @@
+ "EventCode": "0xad",
+ "BriefDescription": "L3 cache fill requests sourced from another CCX's cache when the address was in the same NUMA node.",
+ "UMask": "0x04",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -746,6 +786,10 @@
+ "EventCode": "0xad",
+ "BriefDescription": "L3 cache fill requests sourced from another CCX's cache when the address was in a different NUMA node.",
+ "UMask": "0x08",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -753,6 +797,10 @@
+ "EventCode": "0xad",
+ "BriefDescription": "L3 cache fill requests sourced from extension memory (CXL) in the same NUMA node.",
+ "UMask": "0x10",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -760,6 +808,10 @@
+ "EventCode": "0xad",
+ "BriefDescription": "L3 cache fill requests sourced from extension memory (CXL) in a different NUMA node.",
+ "UMask": "0x20",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ },
+ {
+@@ -767,6 +819,10 @@
+ "EventCode": "0xad",
+ "BriefDescription": "L3 cache fill requests sourced from all data sources.",
+ "UMask": "0x3f",
++ "EnAllCores": "0x1",
++ "EnAllSlices": "0x1",
++ "SliceId": "0x3",
++ "ThreadMask": "0x3",
+ "Unit": "L3PMC"
+ }
+ ]
+diff --git a/tools/perf/pmu-events/jevents.py b/tools/perf/pmu-events/jevents.py
+index 53ab050c8fa43..ce846f29c08d6 100755
+--- a/tools/perf/pmu-events/jevents.py
++++ b/tools/perf/pmu-events/jevents.py
+@@ -356,6 +356,10 @@ class JsonEvent:
+ ('UMask', 'umask='),
+ ('NodeType', 'type='),
+ ('RdWrMask', 'rdwrmask='),
++ ('EnAllCores', 'enallcores='),
++ ('EnAllSlices', 'enallslices='),
++ ('SliceId', 'sliceid='),
++ ('ThreadMask', 'threadmask='),
+ ]
+ for key, value in event_fields:
+ if key in jd and jd[key] != '0':
+diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
+index c29d8a382b196..550675ce0b787 100644
+--- a/tools/perf/util/data.c
++++ b/tools/perf/util/data.c
+@@ -430,8 +430,6 @@ int perf_data__switch(struct perf_data *data,
+ {
+ int ret;
+
+- if (check_pipe(data))
+- return -EINVAL;
+ if (perf_data__is_read(data))
+ return -EINVAL;
+
+diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
+index 6d7c9c58a9bcb..727dae445da9f 100644
+--- a/tools/perf/util/evsel.c
++++ b/tools/perf/util/evsel.c
+@@ -2363,7 +2363,6 @@ int evsel__parse_sample(struct evsel *evsel, union perf_event *event,
+ data->period = evsel->core.attr.sample_period;
+ data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+ data->misc = event->header.misc;
+- data->id = -1ULL;
+ data->data_src = PERF_MEM_DATA_SRC_NONE;
+ data->vcpu = -1;
+
+diff --git a/tools/perf/util/expr.c b/tools/perf/util/expr.c
+index 7be23b3ac0821..b8875aac8f870 100644
+--- a/tools/perf/util/expr.c
++++ b/tools/perf/util/expr.c
+@@ -500,7 +500,25 @@ double expr__has_event(const struct expr_parse_ctx *ctx, bool compute_ids, const
+ tmp = evlist__new();
+ if (!tmp)
+ return NAN;
+- ret = parse_event(tmp, id) ? 0 : 1;
++
++ if (strchr(id, '@')) {
++ char *tmp_id, *p;
++
++ tmp_id = strdup(id);
++ if (!tmp_id) {
++ ret = NAN;
++ goto out;
++ }
++ p = strchr(tmp_id, '@');
++ *p = '/';
++ p = strrchr(tmp_id, '@');
++ *p = '/';
++ ret = parse_event(tmp, tmp_id) ? 0 : 1;
++ free(tmp_id);
++ } else {
++ ret = parse_event(tmp, id) ? 0 : 1;
++ }
++out:
+ evlist__delete(tmp);
+ return ret;
+ }
+diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
+index 3c9609944a2f3..6b82f4759ce69 100644
+--- a/tools/perf/util/pmu.c
++++ b/tools/perf/util/pmu.c
+@@ -1019,10 +1019,9 @@ struct perf_pmu *perf_pmu__lookup(struct list_head *pmus, int dirfd, const char
+ * type value and format definitions. Load both right
+ * now.
+ */
+- if (pmu_format(pmu, dirfd, name)) {
+- free(pmu);
+- return NULL;
+- }
++ if (pmu_format(pmu, dirfd, name))
++ goto err;
++
+ pmu->is_core = is_pmu_core(name);
+ pmu->cpus = pmu_cpumask(dirfd, name, pmu->is_core);
+
+@@ -1760,6 +1759,12 @@ bool pmu__name_match(const struct perf_pmu *pmu, const char *pmu_name)
+
+ bool perf_pmu__is_software(const struct perf_pmu *pmu)
+ {
++ const char *known_sw_pmus[] = {
++ "kprobe",
++ "msr",
++ "uprobe",
++ };
++
+ if (pmu->is_core || pmu->is_uncore || pmu->auxtrace)
+ return false;
+ switch (pmu->type) {
+@@ -1771,7 +1776,11 @@ bool perf_pmu__is_software(const struct perf_pmu *pmu)
+ case PERF_TYPE_BREAKPOINT: return true;
+ default: break;
+ }
+- return !strcmp(pmu->name, "kprobe") || !strcmp(pmu->name, "uprobe");
++ for (size_t i = 0; i < ARRAY_SIZE(known_sw_pmus); i++) {
++ if (!strcmp(pmu->name, known_sw_pmus[i]))
++ return true;
++ }
++ return false;
+ }
+
+ FILE *perf_pmu__open_file(const struct perf_pmu *pmu, const char *name)
+diff --git a/tools/perf/util/print-events.c b/tools/perf/util/print-events.c
+index 9e47712507cc2..b14d1a894abce 100644
+--- a/tools/perf/util/print-events.c
++++ b/tools/perf/util/print-events.c
+@@ -232,7 +232,6 @@ void print_sdt_events(const struct print_callbacks *print_cb, void *print_state)
+ bool is_event_supported(u8 type, u64 config)
+ {
+ bool ret = true;
+- int open_return;
+ struct evsel *evsel;
+ struct perf_event_attr attr = {
+ .type = type,
+@@ -246,20 +245,32 @@ bool is_event_supported(u8 type, u64 config)
+
+ evsel = evsel__new(&attr);
+ if (evsel) {
+- open_return = evsel__open(evsel, NULL, tmap);
+- ret = open_return >= 0;
++ ret = evsel__open(evsel, NULL, tmap) >= 0;
+
+- if (open_return == -EACCES) {
++ if (!ret) {
+ /*
+- * This happens if the paranoid value
++ * The event may fail to open if the paranoid value
+ * /proc/sys/kernel/perf_event_paranoid is set to 2
+- * Re-run with exclude_kernel set; we don't do that
+- * by default as some ARM machines do not support it.
+- *
++ * Re-run with exclude_kernel set; we don't do that by
++ * default as some ARM machines do not support it.
+ */
+ evsel->core.attr.exclude_kernel = 1;
+ ret = evsel__open(evsel, NULL, tmap) >= 0;
+ }
++
++ if (!ret) {
++ /*
++ * The event may fail to open if the PMU requires
++ * exclude_guest to be set (e.g. as the Apple M1 PMU
++ * requires).
++ * Re-run with exclude_guest set; we don't do that by
++ * default as it's equally legitimate for another PMU
++ * driver to require that exclude_guest is clear.
++ */
++ evsel->core.attr.exclude_guest = 1;
++ ret = evsel__open(evsel, NULL, tmap) >= 0;
++ }
++
+ evsel__delete(evsel);
+ }
+
+diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c
+index 034b496df2978..7addc34afcf5d 100644
+--- a/tools/perf/util/srcline.c
++++ b/tools/perf/util/srcline.c
+@@ -399,6 +399,8 @@ static void addr2line_subprocess_cleanup(struct child_process *a2l)
+ kill(a2l->pid, SIGKILL);
+ finish_command(a2l); /* ignore result, we don't care */
+ a2l->pid = -1;
++ close(a2l->in);
++ close(a2l->out);
+ }
+
+ free(a2l);
+diff --git a/tools/perf/util/stat-display.c b/tools/perf/util/stat-display.c
+index 8c61f8627ebc9..b7d00a538d703 100644
+--- a/tools/perf/util/stat-display.c
++++ b/tools/perf/util/stat-display.c
+@@ -560,7 +560,7 @@ static void print_metric_only(struct perf_stat_config *config,
+ if (color)
+ mlen += strlen(color) + sizeof(PERF_COLOR_RESET) - 1;
+
+- color_snprintf(str, sizeof(str), color ?: "", fmt, val);
++ color_snprintf(str, sizeof(str), color ?: "", fmt ?: "", val);
+ fprintf(out, "%*s ", mlen, str);
+ os->first = false;
+ }
+diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
+index e31426167852a..cf573ff3fa84f 100644
+--- a/tools/perf/util/stat-shadow.c
++++ b/tools/perf/util/stat-shadow.c
+@@ -414,12 +414,7 @@ static int prepare_metric(struct evsel **metric_events,
+ val = NAN;
+ source_count = 0;
+ } else {
+- /*
+- * If an event was scaled during stat gathering,
+- * reverse the scale before computing the
+- * metric.
+- */
+- val = aggr->counts.val * (1.0 / metric_events[i]->scale);
++ val = aggr->counts.val;
+ source_count = evsel__source_count(metric_events[i]);
+ }
+ }
+diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
+index e848579e61a86..ea3b431b97830 100644
+--- a/tools/perf/util/thread_map.c
++++ b/tools/perf/util/thread_map.c
+@@ -280,13 +280,13 @@ struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str)
+ threads->nr = ntasks;
+ }
+ out:
++ strlist__delete(slist);
+ if (threads)
+ refcount_set(&threads->refcnt, 1);
+ return threads;
+
+ out_free_threads:
+ zfree(&threads);
+- strlist__delete(slist);
+ goto out;
+ }
+
+diff --git a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
+index 91907b321f913..e7c9e1c7fde04 100644
+--- a/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
++++ b/tools/testing/selftests/bpf/bpf_testmod/bpf_testmod.c
+@@ -2,6 +2,7 @@
+ /* Copyright (c) 2020 Facebook */
+ #include <linux/btf.h>
+ #include <linux/btf_ids.h>
++#include <linux/delay.h>
+ #include <linux/error-injection.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+@@ -544,6 +545,14 @@ static int bpf_testmod_init(void)
+
+ static void bpf_testmod_exit(void)
+ {
++ /* Need to wait for all references to be dropped because
++ * bpf_kfunc_call_test_release() which currently resides in kernel can
++ * be called after bpf_testmod is unloaded. Once release function is
++ * moved into the module this wait can be removed.
++ */
++ while (refcount_read(&prog_test_struct.cnt) > 1)
++ msleep(20);
++
+ return sysfs_remove_bin_file(kernel_kobj, &bin_attr_bpf_testmod_file);
+ }
+
+diff --git a/tools/testing/selftests/bpf/prog_tests/lwt_redirect.c b/tools/testing/selftests/bpf/prog_tests/lwt_redirect.c
+index 59b38569f310b..2bc932a18c17e 100644
+--- a/tools/testing/selftests/bpf/prog_tests/lwt_redirect.c
++++ b/tools/testing/selftests/bpf/prog_tests/lwt_redirect.c
+@@ -203,6 +203,7 @@ static int setup_redirect_target(const char *target_dev, bool need_mac)
+ if (!ASSERT_GE(target_index, 0, "if_nametoindex"))
+ goto fail;
+
++ SYS(fail, "sysctl -w net.ipv6.conf.all.disable_ipv6=1");
+ SYS(fail, "ip link add link_err type dummy");
+ SYS(fail, "ip link set lo up");
+ SYS(fail, "ip addr add dev lo " LOCAL_SRC "/32");
+diff --git a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c
+index 518f143c5b0fe..dbe06aeaa2b27 100644
+--- a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c
++++ b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c
+@@ -188,6 +188,7 @@ static int netns_setup_links_and_routes(struct netns_setup_result *result)
+ {
+ struct nstoken *nstoken = NULL;
+ char src_fwd_addr[IFADDR_STR_LEN+1] = {};
++ char src_addr[IFADDR_STR_LEN + 1] = {};
+ int err;
+
+ if (result->dev_mode == MODE_VETH) {
+@@ -208,6 +209,9 @@ static int netns_setup_links_and_routes(struct netns_setup_result *result)
+ if (get_ifaddr("src_fwd", src_fwd_addr))
+ goto fail;
+
++ if (get_ifaddr("src", src_addr))
++ goto fail;
++
+ result->ifindex_src = if_nametoindex("src");
+ if (!ASSERT_GT(result->ifindex_src, 0, "ifindex_src"))
+ goto fail;
+@@ -270,6 +274,13 @@ static int netns_setup_links_and_routes(struct netns_setup_result *result)
+ SYS(fail, "ip route add " IP4_DST "/32 dev dst_fwd scope global");
+ SYS(fail, "ip route add " IP6_DST "/128 dev dst_fwd scope global");
+
++ if (result->dev_mode == MODE_VETH) {
++ SYS(fail, "ip neigh add " IP4_SRC " dev src_fwd lladdr %s", src_addr);
++ SYS(fail, "ip neigh add " IP6_SRC " dev src_fwd lladdr %s", src_addr);
++ SYS(fail, "ip neigh add " IP4_DST " dev dst_fwd lladdr %s", MAC_DST);
++ SYS(fail, "ip neigh add " IP6_DST " dev dst_fwd lladdr %s", MAC_DST);
++ }
++
+ close_netns(nstoken);
+
+ /** setup in 'dst' namespace */
+@@ -280,6 +291,7 @@ static int netns_setup_links_and_routes(struct netns_setup_result *result)
+ SYS(fail, "ip addr add " IP4_DST "/32 dev dst");
+ SYS(fail, "ip addr add " IP6_DST "/128 dev dst nodad");
+ SYS(fail, "ip link set dev dst up");
++ SYS(fail, "ip link set dev lo up");
+
+ SYS(fail, "ip route add " IP4_SRC "/32 dev dst scope global");
+ SYS(fail, "ip route add " IP4_NET "/16 dev dst scope global");
+@@ -457,7 +469,7 @@ static int set_forwarding(bool enable)
+ return 0;
+ }
+
+-static void rcv_tstamp(int fd, const char *expected, size_t s)
++static int __rcv_tstamp(int fd, const char *expected, size_t s, __u64 *tstamp)
+ {
+ struct __kernel_timespec pkt_ts = {};
+ char ctl[CMSG_SPACE(sizeof(pkt_ts))];
+@@ -478,7 +490,7 @@ static void rcv_tstamp(int fd, const char *expected, size_t s)
+
+ ret = recvmsg(fd, &msg, 0);
+ if (!ASSERT_EQ(ret, s, "recvmsg"))
+- return;
++ return -1;
+ ASSERT_STRNEQ(data, expected, s, "expected rcv data");
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+@@ -487,6 +499,12 @@ static void rcv_tstamp(int fd, const char *expected, size_t s)
+ memcpy(&pkt_ts, CMSG_DATA(cmsg), sizeof(pkt_ts));
+
+ pkt_ns = pkt_ts.tv_sec * NSEC_PER_SEC + pkt_ts.tv_nsec;
++ if (tstamp) {
++ /* caller will check the tstamp itself */
++ *tstamp = pkt_ns;
++ return 0;
++ }
++
+ ASSERT_NEQ(pkt_ns, 0, "pkt rcv tstamp");
+
+ ret = clock_gettime(CLOCK_REALTIME, &now_ts);
+@@ -496,6 +514,60 @@ static void rcv_tstamp(int fd, const char *expected, size_t s)
+ if (ASSERT_GE(now_ns, pkt_ns, "check rcv tstamp"))
+ ASSERT_LT(now_ns - pkt_ns, 5 * NSEC_PER_SEC,
+ "check rcv tstamp");
++ return 0;
++}
++
++static void rcv_tstamp(int fd, const char *expected, size_t s)
++{
++ __rcv_tstamp(fd, expected, s, NULL);
++}
++
++static int wait_netstamp_needed_key(void)
++{
++ int opt = 1, srv_fd = -1, cli_fd = -1, nretries = 0, err, n;
++ char buf[] = "testing testing";
++ struct nstoken *nstoken;
++ __u64 tstamp = 0;
++
++ nstoken = open_netns(NS_DST);
++ if (!nstoken)
++ return -1;
++
++ srv_fd = start_server(AF_INET6, SOCK_DGRAM, "::1", 0, 0);
++ if (!ASSERT_GE(srv_fd, 0, "start_server"))
++ goto done;
++
++ err = setsockopt(srv_fd, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
++ &opt, sizeof(opt));
++ if (!ASSERT_OK(err, "setsockopt(SO_TIMESTAMPNS_NEW)"))
++ goto done;
++
++ cli_fd = connect_to_fd(srv_fd, TIMEOUT_MILLIS);
++ if (!ASSERT_GE(cli_fd, 0, "connect_to_fd"))
++ goto done;
++
++again:
++ n = write(cli_fd, buf, sizeof(buf));
++ if (!ASSERT_EQ(n, sizeof(buf), "send to server"))
++ goto done;
++ err = __rcv_tstamp(srv_fd, buf, sizeof(buf), &tstamp);
++ if (!ASSERT_OK(err, "__rcv_tstamp"))
++ goto done;
++ if (!tstamp && nretries++ < 5) {
++ sleep(1);
++ printf("netstamp_needed_key retry#%d\n", nretries);
++ goto again;
++ }
++
++done:
++ if (!tstamp && srv_fd != -1) {
++ close(srv_fd);
++ srv_fd = -1;
++ }
++ if (cli_fd != -1)
++ close(cli_fd);
++ close_netns(nstoken);
++ return srv_fd;
+ }
+
+ static void snd_tstamp(int fd, char *b, size_t s)
+@@ -832,11 +904,20 @@ static void test_tc_redirect_dtime(struct netns_setup_result *setup_result)
+ {
+ struct test_tc_dtime *skel;
+ struct nstoken *nstoken;
+- int err;
++ int hold_tstamp_fd, err;
++
++ /* Hold a sk with the SOCK_TIMESTAMP set to ensure there
++ * is no delay in the kernel net_enable_timestamp().
++ * This ensures the following tests must have
++ * non zero rcv tstamp in the recvmsg().
++ */
++ hold_tstamp_fd = wait_netstamp_needed_key();
++ if (!ASSERT_GE(hold_tstamp_fd, 0, "wait_netstamp_needed_key"))
++ return;
+
+ skel = test_tc_dtime__open();
+ if (!ASSERT_OK_PTR(skel, "test_tc_dtime__open"))
+- return;
++ goto done;
+
+ skel->rodata->IFINDEX_SRC = setup_result->ifindex_src_fwd;
+ skel->rodata->IFINDEX_DST = setup_result->ifindex_dst_fwd;
+@@ -881,6 +962,7 @@ static void test_tc_redirect_dtime(struct netns_setup_result *setup_result)
+
+ done:
+ test_tc_dtime__destroy(skel);
++ close(hold_tstamp_fd);
+ }
+
+ static void test_tc_redirect_neigh_fib(struct netns_setup_result *setup_result)
+diff --git a/tools/testing/selftests/bpf/progs/test_map_in_map.c b/tools/testing/selftests/bpf/progs/test_map_in_map.c
+index f416032ba858b..b295f9b721bf8 100644
+--- a/tools/testing/selftests/bpf/progs/test_map_in_map.c
++++ b/tools/testing/selftests/bpf/progs/test_map_in_map.c
+@@ -21,6 +21,32 @@ struct {
+ __type(value, __u32);
+ } mim_hash SEC(".maps");
+
++/* The following three maps are used to test
++ * perf_event_array map can be an inner
++ * map of hash/array_of_maps.
++ */
++struct perf_event_array {
++ __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
++ __type(key, __u32);
++ __type(value, __u32);
++} inner_map0 SEC(".maps");
++
++struct {
++ __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
++ __uint(max_entries, 1);
++ __type(key, __u32);
++ __array(values, struct perf_event_array);
++} mim_array_pe SEC(".maps") = {
++ .values = {&inner_map0}};
++
++struct {
++ __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS);
++ __uint(max_entries, 1);
++ __type(key, __u32);
++ __array(values, struct perf_event_array);
++} mim_hash_pe SEC(".maps") = {
++ .values = {&inner_map0}};
++
+ SEC("xdp")
+ int xdp_mimtest0(struct xdp_md *ctx)
+ {
+diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c
+index 767e0693df106..dfbab214f4d1c 100644
+--- a/tools/testing/selftests/bpf/test_maps.c
++++ b/tools/testing/selftests/bpf/test_maps.c
+@@ -1190,7 +1190,11 @@ static void test_map_in_map(void)
+ goto out_map_in_map;
+ }
+
+- bpf_object__load(obj);
++ err = bpf_object__load(obj);
++ if (err) {
++ printf("Failed to load test prog\n");
++ goto out_map_in_map;
++ }
+
+ map = bpf_object__find_map_by_name(obj, "mim_array");
+ if (!map) {
+diff --git a/tools/testing/selftests/bpf/trace_helpers.c b/tools/testing/selftests/bpf/trace_helpers.c
+index 4faa898ff7fc4..27fd7ed3e4b0c 100644
+--- a/tools/testing/selftests/bpf/trace_helpers.c
++++ b/tools/testing/selftests/bpf/trace_helpers.c
+@@ -271,7 +271,7 @@ ssize_t get_uprobe_offset(const void *addr)
+ * addi r2,r2,XXXX
+ */
+ {
+- const u32 *insn = (const u32 *)(uintptr_t)addr;
++ const __u32 *insn = (const __u32 *)(uintptr_t)addr;
+
+ if ((((*insn & OP_RT_RA_MASK) == ADDIS_R2_R12) ||
+ ((*insn & OP_RT_RA_MASK) == LIS_R2)) &&
+diff --git a/tools/testing/selftests/net/forwarding/config b/tools/testing/selftests/net/forwarding/config
+index 697994a9278bb..8d7a1a004b7c3 100644
+--- a/tools/testing/selftests/net/forwarding/config
++++ b/tools/testing/selftests/net/forwarding/config
+@@ -6,14 +6,49 @@ CONFIG_IPV6_MULTIPLE_TABLES=y
+ CONFIG_NET_VRF=m
+ CONFIG_BPF_SYSCALL=y
+ CONFIG_CGROUP_BPF=y
++CONFIG_DUMMY=m
++CONFIG_IPV6=y
++CONFIG_IPV6_GRE=m
++CONFIG_IPV6_MROUTE=y
++CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
++CONFIG_IPV6_PIMSM_V2=y
++CONFIG_IP_MROUTE=y
++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
++CONFIG_IP_PIMSM_V1=y
++CONFIG_IP_PIMSM_V2=y
++CONFIG_MACVLAN=m
+ CONFIG_NET_ACT_CT=m
+ CONFIG_NET_ACT_MIRRED=m
+ CONFIG_NET_ACT_MPLS=m
++CONFIG_NET_ACT_PEDIT=m
++CONFIG_NET_ACT_POLICE=m
++CONFIG_NET_ACT_SAMPLE=m
++CONFIG_NET_ACT_SKBEDIT=m
++CONFIG_NET_ACT_TUNNEL_KEY=m
+ CONFIG_NET_ACT_VLAN=m
+ CONFIG_NET_CLS_FLOWER=m
+ CONFIG_NET_CLS_MATCHALL=m
++CONFIG_NET_CLS_BASIC=m
++CONFIG_NET_EMATCH=y
++CONFIG_NET_EMATCH_META=m
++CONFIG_NET_IPGRE=m
++CONFIG_NET_IPGRE_DEMUX=m
++CONFIG_NET_IPIP=m
++CONFIG_NET_SCH_ETS=m
+ CONFIG_NET_SCH_INGRESS=m
+ CONFIG_NET_ACT_GACT=m
++CONFIG_NET_SCH_PRIO=m
++CONFIG_NET_SCH_RED=m
++CONFIG_NET_SCH_TBF=m
++CONFIG_NET_TC_SKB_EXT=y
++CONFIG_NET_TEAM=y
++CONFIG_NET_TEAM_MODE_LOADBALANCE=y
++CONFIG_NETFILTER=y
++CONFIG_NF_CONNTRACK=m
++CONFIG_NF_FLOW_TABLE=m
++CONFIG_NF_TABLES=m
+ CONFIG_VETH=m
+ CONFIG_NAMESPACES=y
+ CONFIG_NET_NS=y
++CONFIG_VXLAN=m
++CONFIG_XFRM_USER=m
+diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh
+index ac97f07e5ce82..bd3f7d492af2b 100755
+--- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh
++++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh
+@@ -354,7 +354,7 @@ __ping_ipv4()
+
+ # Send 100 packets and verify that at least 100 packets hit the rule,
+ # to overcome ARP noise.
+- PING_COUNT=100 PING_TIMEOUT=11 ping_do $dev $dst_ip
++ PING_COUNT=100 PING_TIMEOUT=20 ping_do $dev $dst_ip
+ check_err $? "Ping failed"
+
+ tc_check_at_least_x_packets "dev $rp1 egress" 101 10 100
+@@ -410,7 +410,7 @@ __ping_ipv6()
+
+ # Send 100 packets and verify that at least 100 packets hit the rule,
+ # to overcome neighbor discovery noise.
+- PING_COUNT=100 PING_TIMEOUT=11 ping6_do $dev $dst_ip
++ PING_COUNT=100 PING_TIMEOUT=20 ping6_do $dev $dst_ip
+ check_err $? "Ping failed"
+
+ tc_check_at_least_x_packets "dev $rp1 egress" 101 100
+diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_ipv6.sh b/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_ipv6.sh
+index d880df89bc8bd..e83fde79f40d0 100755
+--- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_ipv6.sh
++++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1q_ipv6.sh
+@@ -457,7 +457,7 @@ __ping_ipv4()
+
+ # Send 100 packets and verify that at least 100 packets hit the rule,
+ # to overcome ARP noise.
+- PING_COUNT=100 PING_TIMEOUT=11 ping_do $dev $dst_ip
++ PING_COUNT=100 PING_TIMEOUT=20 ping_do $dev $dst_ip
+ check_err $? "Ping failed"
+
+ tc_check_at_least_x_packets "dev $rp1 egress" 101 10 100
+@@ -522,7 +522,7 @@ __ping_ipv6()
+
+ # Send 100 packets and verify that at least 100 packets hit the rule,
+ # to overcome neighbor discovery noise.
+- PING_COUNT=100 PING_TIMEOUT=11 ping6_do $dev $dst_ip
++ PING_COUNT=100 PING_TIMEOUT=20 ping6_do $dev $dst_ip
+ check_err $? "Ping failed"
+
+ tc_check_at_least_x_packets "dev $rp1 egress" 101 100
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-03-27 11:29 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-03-27 11:29 UTC (permalink / raw
To: gentoo-commits
commit: 699bdaa5be44a19510627f22cbf1d467e4d32dcb
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Wed Mar 27 11:29:24 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Wed Mar 27 11:29:24 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=699bdaa5
Bump BMQ Schedular to v6.8-r2
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 2 +-
5020_BMQ-and-PDS-io-scheduler-v6.8-r2.patch | 11502 ++++++++++++++++++++++++++
2 files changed, 11503 insertions(+), 1 deletion(-)
diff --git a/0000_README b/0000_README
index 5b18c2c3..a259dbf2 100644
--- a/0000_README
+++ b/0000_README
@@ -91,6 +91,6 @@ Patch: 5010_enable-cpu-optimizations-universal.patch
From: https://github.com/graysky2/kernel_compiler_patch
Desc: Kernel >= 5.15 patch enables gcc = v11.1+ optimizations for additional CPUs.
-Patch: 5020_BMQ-and-PDS-io-scheduler-v6.8-r0.patch
+Patch: 5020_BMQ-and-PDS-io-scheduler-v6.8-r2.patch
From: https://gitlab.com/alfredchen/projectc
Desc: BMQ(BitMap Queue) Scheduler. A new CPU scheduler developed from PDS(incld). Inspired by the scheduler in zircon.
diff --git a/5020_BMQ-and-PDS-io-scheduler-v6.8-r2.patch b/5020_BMQ-and-PDS-io-scheduler-v6.8-r2.patch
new file mode 100644
index 00000000..f0f8c11e
--- /dev/null
+++ b/5020_BMQ-and-PDS-io-scheduler-v6.8-r2.patch
@@ -0,0 +1,11502 @@
+diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
+index 6584a1f9bfe3..1ac9e0850c9c 100644
+--- a/Documentation/admin-guide/sysctl/kernel.rst
++++ b/Documentation/admin-guide/sysctl/kernel.rst
+@@ -1646,3 +1646,12 @@ is 10 seconds.
+
+ The softlockup threshold is (``2 * watchdog_thresh``). Setting this
+ tunable to zero will disable lockup detection altogether.
++
++yield_type:
++===========
++
++BMQ/PDS CPU scheduler only. This determines what type of yield calls
++to sched_yield() will be performed.
++
++ 0 - No yield.
++ 1 - Requeue task. (default)
+diff --git a/Documentation/scheduler/sched-BMQ.txt b/Documentation/scheduler/sched-BMQ.txt
+new file mode 100644
+index 000000000000..05c84eec0f31
+--- /dev/null
++++ b/Documentation/scheduler/sched-BMQ.txt
+@@ -0,0 +1,110 @@
++ BitMap queue CPU Scheduler
++ --------------------------
++
++CONTENT
++========
++
++ Background
++ Design
++ Overview
++ Task policy
++ Priority management
++ BitMap Queue
++ CPU Assignment and Migration
++
++
++Background
++==========
++
++BitMap Queue CPU scheduler, referred to as BMQ from here on, is an evolution
++of previous Priority and Deadline based Skiplist multiple queue scheduler(PDS),
++and inspired by Zircon scheduler. The goal of it is to keep the scheduler code
++simple, while efficiency and scalable for interactive tasks, such as desktop,
++movie playback and gaming etc.
++
++Design
++======
++
++Overview
++--------
++
++BMQ use per CPU run queue design, each CPU(logical) has it's own run queue,
++each CPU is responsible for scheduling the tasks that are putting into it's
++run queue.
++
++The run queue is a set of priority queues. Note that these queues are fifo
++queue for non-rt tasks or priority queue for rt tasks in data structure. See
++BitMap Queue below for details. BMQ is optimized for non-rt tasks in the fact
++that most applications are non-rt tasks. No matter the queue is fifo or
++priority, In each queue is an ordered list of runnable tasks awaiting execution
++and the data structures are the same. When it is time for a new task to run,
++the scheduler simply looks the lowest numbered queueue that contains a task,
++and runs the first task from the head of that queue. And per CPU idle task is
++also in the run queue, so the scheduler can always find a task to run on from
++its run queue.
++
++Each task will assigned the same timeslice(default 4ms) when it is picked to
++start running. Task will be reinserted at the end of the appropriate priority
++queue when it uses its whole timeslice. When the scheduler selects a new task
++from the priority queue it sets the CPU's preemption timer for the remainder of
++the previous timeslice. When that timer fires the scheduler will stop execution
++on that task, select another task and start over again.
++
++If a task blocks waiting for a shared resource then it's taken out of its
++priority queue and is placed in a wait queue for the shared resource. When it
++is unblocked it will be reinserted in the appropriate priority queue of an
++eligible CPU.
++
++Task policy
++-----------
++
++BMQ supports DEADLINE, FIFO, RR, NORMAL, BATCH and IDLE task policy like the
++mainline CFS scheduler. But BMQ is heavy optimized for non-rt task, that's
++NORMAL/BATCH/IDLE policy tasks. Below is the implementation detail of each
++policy.
++
++DEADLINE
++ It is squashed as priority 0 FIFO task.
++
++FIFO/RR
++ All RT tasks share one single priority queue in BMQ run queue designed. The
++complexity of insert operation is O(n). BMQ is not designed for system runs
++with major rt policy tasks.
++
++NORMAL/BATCH/IDLE
++ BATCH and IDLE tasks are treated as the same policy. They compete CPU with
++NORMAL policy tasks, but they just don't boost. To control the priority of
++NORMAL/BATCH/IDLE tasks, simply use nice level.
++
++ISO
++ ISO policy is not supported in BMQ. Please use nice level -20 NORMAL policy
++task instead.
++
++Priority management
++-------------------
++
++RT tasks have priority from 0-99. For non-rt tasks, there are three different
++factors used to determine the effective priority of a task. The effective
++priority being what is used to determine which queue it will be in.
++
++The first factor is simply the task’s static priority. Which is assigned from
++task's nice level, within [-20, 19] in userland's point of view and [0, 39]
++internally.
++
++The second factor is the priority boost. This is a value bounded between
++[-MAX_PRIORITY_ADJ, MAX_PRIORITY_ADJ] used to offset the base priority, it is
++modified by the following cases:
++
++*When a thread has used up its entire timeslice, always deboost its boost by
++increasing by one.
++*When a thread gives up cpu control(voluntary or non-voluntary) to reschedule,
++and its switch-in time(time after last switch and run) below the thredhold
++based on its priority boost, will boost its boost by decreasing by one buti is
++capped at 0 (won’t go negative).
++
++The intent in this system is to ensure that interactive threads are serviced
++quickly. These are usually the threads that interact directly with the user
++and cause user-perceivable latency. These threads usually do little work and
++spend most of their time blocked awaiting another user event. So they get the
++priority boost from unblocking while background threads that do most of the
++processing receive the priority penalty for using their entire timeslice.
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index 18550c071d71..fa8cf95568b6 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -481,7 +481,7 @@ static int proc_pid_schedstat(struct seq_file *m, struct pid_namespace *ns,
+ seq_puts(m, "0 0 0\n");
+ else
+ seq_printf(m, "%llu %llu %lu\n",
+- (unsigned long long)task->se.sum_exec_runtime,
++ (unsigned long long)tsk_seruntime(task),
+ (unsigned long long)task->sched_info.run_delay,
+ task->sched_info.pcount);
+
+diff --git a/include/asm-generic/resource.h b/include/asm-generic/resource.h
+index 8874f681b056..59eb72bf7d5f 100644
+--- a/include/asm-generic/resource.h
++++ b/include/asm-generic/resource.h
+@@ -23,7 +23,7 @@
+ [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY }, \
+ [RLIMIT_SIGPENDING] = { 0, 0 }, \
+ [RLIMIT_MSGQUEUE] = { MQ_BYTES_MAX, MQ_BYTES_MAX }, \
+- [RLIMIT_NICE] = { 0, 0 }, \
++ [RLIMIT_NICE] = { 30, 30 }, \
+ [RLIMIT_RTPRIO] = { 0, 0 }, \
+ [RLIMIT_RTTIME] = { RLIM_INFINITY, RLIM_INFINITY }, \
+ }
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index ffe8f618ab86..18058ad9ddae 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -771,8 +771,14 @@ struct task_struct {
+ unsigned int ptrace;
+
+ #ifdef CONFIG_SMP
+- int on_cpu;
+ struct __call_single_node wake_entry;
++#endif
++#if defined(CONFIG_SMP) || defined(CONFIG_SCHED_ALT)
++ int on_cpu;
++#endif
++
++#ifdef CONFIG_SMP
++#ifndef CONFIG_SCHED_ALT
+ unsigned int wakee_flips;
+ unsigned long wakee_flip_decay_ts;
+ struct task_struct *last_wakee;
+@@ -786,6 +792,7 @@ struct task_struct {
+ */
+ int recent_used_cpu;
+ int wake_cpu;
++#endif /* !CONFIG_SCHED_ALT */
+ #endif
+ int on_rq;
+
+@@ -794,6 +801,19 @@ struct task_struct {
+ int normal_prio;
+ unsigned int rt_priority;
+
++#ifdef CONFIG_SCHED_ALT
++ u64 last_ran;
++ s64 time_slice;
++ struct list_head sq_node;
++#ifdef CONFIG_SCHED_BMQ
++ int boost_prio;
++#endif /* CONFIG_SCHED_BMQ */
++#ifdef CONFIG_SCHED_PDS
++ u64 deadline;
++#endif /* CONFIG_SCHED_PDS */
++ /* sched_clock time spent running */
++ u64 sched_time;
++#else /* !CONFIG_SCHED_ALT */
+ struct sched_entity se;
+ struct sched_rt_entity rt;
+ struct sched_dl_entity dl;
+@@ -805,6 +825,7 @@ struct task_struct {
+ unsigned long core_cookie;
+ unsigned int core_occupation;
+ #endif
++#endif /* !CONFIG_SCHED_ALT */
+
+ #ifdef CONFIG_CGROUP_SCHED
+ struct task_group *sched_task_group;
+@@ -1564,6 +1585,15 @@ struct task_struct {
+ */
+ };
+
++#ifdef CONFIG_SCHED_ALT
++#define tsk_seruntime(t) ((t)->sched_time)
++/* replace the uncertian rt_timeout with 0UL */
++#define tsk_rttimeout(t) (0UL)
++#else /* CFS */
++#define tsk_seruntime(t) ((t)->se.sum_exec_runtime)
++#define tsk_rttimeout(t) ((t)->rt.timeout)
++#endif /* !CONFIG_SCHED_ALT */
++
+ #define TASK_REPORT_IDLE (TASK_REPORT + 1)
+ #define TASK_REPORT_MAX (TASK_REPORT_IDLE << 1)
+
+diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h
+index df3aca89d4f5..1df1f7635188 100644
+--- a/include/linux/sched/deadline.h
++++ b/include/linux/sched/deadline.h
+@@ -2,6 +2,25 @@
+ #ifndef _LINUX_SCHED_DEADLINE_H
+ #define _LINUX_SCHED_DEADLINE_H
+
++#ifdef CONFIG_SCHED_ALT
++
++static inline int dl_task(struct task_struct *p)
++{
++ return 0;
++}
++
++#ifdef CONFIG_SCHED_BMQ
++#define __tsk_deadline(p) (0UL)
++#endif
++
++#ifdef CONFIG_SCHED_PDS
++#define __tsk_deadline(p) ((((u64) ((p)->prio))<<56) | (p)->deadline)
++#endif
++
++#else
++
++#define __tsk_deadline(p) ((p)->dl.deadline)
++
+ /*
+ * SCHED_DEADLINE tasks has negative priorities, reflecting
+ * the fact that any of them has higher prio than RT and
+@@ -23,6 +42,7 @@ static inline int dl_task(struct task_struct *p)
+ {
+ return dl_prio(p->prio);
+ }
++#endif /* CONFIG_SCHED_ALT */
+
+ static inline bool dl_time_before(u64 a, u64 b)
+ {
+diff --git a/include/linux/sched/prio.h b/include/linux/sched/prio.h
+index ab83d85e1183..a9a1dfa99140 100644
+--- a/include/linux/sched/prio.h
++++ b/include/linux/sched/prio.h
+@@ -18,6 +18,32 @@
+ #define MAX_PRIO (MAX_RT_PRIO + NICE_WIDTH)
+ #define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2)
+
++#ifdef CONFIG_SCHED_ALT
++
++/* Undefine MAX_PRIO and DEFAULT_PRIO */
++#undef MAX_PRIO
++#undef DEFAULT_PRIO
++
++/* +/- priority levels from the base priority */
++#ifdef CONFIG_SCHED_BMQ
++#define MAX_PRIORITY_ADJ (12)
++
++#define MIN_NORMAL_PRIO (MAX_RT_PRIO)
++#define MAX_PRIO (MIN_NORMAL_PRIO + NICE_WIDTH)
++#define DEFAULT_PRIO (MIN_NORMAL_PRIO + NICE_WIDTH / 2)
++#endif
++
++#ifdef CONFIG_SCHED_PDS
++#define MAX_PRIORITY_ADJ (0)
++
++#define MIN_NORMAL_PRIO (128)
++#define NORMAL_PRIO_NUM (64)
++#define MAX_PRIO (MIN_NORMAL_PRIO + NORMAL_PRIO_NUM)
++#define DEFAULT_PRIO (MAX_PRIO - NICE_WIDTH / 2)
++#endif
++
++#endif /* CONFIG_SCHED_ALT */
++
+ /*
+ * Convert user-nice values [ -20 ... 0 ... 19 ]
+ * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
+diff --git a/include/linux/sched/rt.h b/include/linux/sched/rt.h
+index b2b9e6eb9683..09bd4d8758b2 100644
+--- a/include/linux/sched/rt.h
++++ b/include/linux/sched/rt.h
+@@ -24,8 +24,10 @@ static inline bool task_is_realtime(struct task_struct *tsk)
+
+ if (policy == SCHED_FIFO || policy == SCHED_RR)
+ return true;
++#ifndef CONFIG_SCHED_ALT
+ if (policy == SCHED_DEADLINE)
+ return true;
++#endif
+ return false;
+ }
+
+diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h
+index a6e04b4a21d7..66f5170037c3 100644
+--- a/include/linux/sched/topology.h
++++ b/include/linux/sched/topology.h
+@@ -238,7 +238,8 @@ static inline bool cpus_share_resources(int this_cpu, int that_cpu)
+
+ #endif /* !CONFIG_SMP */
+
+-#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)
++#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) && \
++ !defined(CONFIG_SCHED_ALT)
+ extern void rebuild_sched_domains_energy(void);
+ #else
+ static inline void rebuild_sched_domains_energy(void)
+diff --git a/init/Kconfig b/init/Kconfig
+index bee58f7468c3..81f568107a6b 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -638,6 +638,7 @@ config TASK_IO_ACCOUNTING
+
+ config PSI
+ bool "Pressure stall information tracking"
++ depends on !SCHED_ALT
+ select KERNFS
+ help
+ Collect metrics that indicate how overcommitted the CPU, memory,
+@@ -803,6 +804,7 @@ menu "Scheduler features"
+ config UCLAMP_TASK
+ bool "Enable utilization clamping for RT/FAIR tasks"
+ depends on CPU_FREQ_GOV_SCHEDUTIL
++ depends on !SCHED_ALT
+ help
+ This feature enables the scheduler to track the clamped utilization
+ of each CPU based on RUNNABLE tasks scheduled on that CPU.
+@@ -849,6 +851,35 @@ config UCLAMP_BUCKETS_COUNT
+
+ If in doubt, use the default value.
+
++menuconfig SCHED_ALT
++ bool "Alternative CPU Schedulers"
++ default y
++ help
++ This feature enable alternative CPU scheduler"
++
++if SCHED_ALT
++
++choice
++ prompt "Alternative CPU Scheduler"
++ default SCHED_BMQ
++
++config SCHED_BMQ
++ bool "BMQ CPU scheduler"
++ help
++ The BitMap Queue CPU scheduler for excellent interactivity and
++ responsiveness on the desktop and solid scalability on normal
++ hardware and commodity servers.
++
++config SCHED_PDS
++ bool "PDS CPU scheduler"
++ help
++ The Priority and Deadline based Skip list multiple queue CPU
++ Scheduler.
++
++endchoice
++
++endif
++
+ endmenu
+
+ #
+@@ -914,6 +945,7 @@ config NUMA_BALANCING
+ depends on ARCH_SUPPORTS_NUMA_BALANCING
+ depends on !ARCH_WANT_NUMA_VARIABLE_LOCALITY
+ depends on SMP && NUMA && MIGRATION && !PREEMPT_RT
++ depends on !SCHED_ALT
+ help
+ This option adds support for automatic NUMA aware memory/task placement.
+ The mechanism is quite primitive and is based on migrating memory when
+@@ -1011,6 +1043,7 @@ config FAIR_GROUP_SCHED
+ depends on CGROUP_SCHED
+ default CGROUP_SCHED
+
++if !SCHED_ALT
+ config CFS_BANDWIDTH
+ bool "CPU bandwidth provisioning for FAIR_GROUP_SCHED"
+ depends on FAIR_GROUP_SCHED
+@@ -1033,6 +1066,7 @@ config RT_GROUP_SCHED
+ realtime bandwidth for them.
+ See Documentation/scheduler/sched-rt-group.rst for more information.
+
++endif #!SCHED_ALT
+ endif #CGROUP_SCHED
+
+ config SCHED_MM_CID
+@@ -1281,6 +1315,7 @@ config CHECKPOINT_RESTORE
+
+ config SCHED_AUTOGROUP
+ bool "Automatic process group scheduling"
++ depends on !SCHED_ALT
+ select CGROUPS
+ select CGROUP_SCHED
+ select FAIR_GROUP_SCHED
+diff --git a/init/init_task.c b/init/init_task.c
+index 7ecb458eb3da..40d2e86da6f9 100644
+--- a/init/init_task.c
++++ b/init/init_task.c
+@@ -70,9 +70,15 @@ struct task_struct init_task __aligned(L1_CACHE_BYTES) = {
+ .stack = init_stack,
+ .usage = REFCOUNT_INIT(2),
+ .flags = PF_KTHREAD,
++#ifdef CONFIG_SCHED_ALT
++ .prio = DEFAULT_PRIO + MAX_PRIORITY_ADJ,
++ .static_prio = DEFAULT_PRIO,
++ .normal_prio = DEFAULT_PRIO + MAX_PRIORITY_ADJ,
++#else
+ .prio = MAX_PRIO - 20,
+ .static_prio = MAX_PRIO - 20,
+ .normal_prio = MAX_PRIO - 20,
++#endif
+ .policy = SCHED_NORMAL,
+ .cpus_ptr = &init_task.cpus_mask,
+ .user_cpus_ptr = NULL,
+@@ -84,6 +90,16 @@ struct task_struct init_task __aligned(L1_CACHE_BYTES) = {
+ .restart_block = {
+ .fn = do_no_restart_syscall,
+ },
++#ifdef CONFIG_SCHED_ALT
++ .sq_node = LIST_HEAD_INIT(init_task.sq_node),
++#ifdef CONFIG_SCHED_BMQ
++ .boost_prio = 0,
++#endif
++#ifdef CONFIG_SCHED_PDS
++ .deadline = 0,
++#endif
++ .time_slice = HZ,
++#else
+ .se = {
+ .group_node = LIST_HEAD_INIT(init_task.se.group_node),
+ },
+@@ -91,6 +107,7 @@ struct task_struct init_task __aligned(L1_CACHE_BYTES) = {
+ .run_list = LIST_HEAD_INIT(init_task.rt.run_list),
+ .time_slice = RR_TIMESLICE,
+ },
++#endif
+ .tasks = LIST_HEAD_INIT(init_task.tasks),
+ #ifdef CONFIG_SMP
+ .pushable_tasks = PLIST_NODE_INIT(init_task.pushable_tasks, MAX_PRIO),
+diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
+index c2f1fd95a821..41654679b1b2 100644
+--- a/kernel/Kconfig.preempt
++++ b/kernel/Kconfig.preempt
+@@ -117,7 +117,7 @@ config PREEMPT_DYNAMIC
+
+ config SCHED_CORE
+ bool "Core Scheduling for SMT"
+- depends on SCHED_SMT
++ depends on SCHED_SMT && !SCHED_ALT
+ help
+ This option permits Core Scheduling, a means of coordinated task
+ selection across SMT siblings. When enabled -- see
+diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
+index 927bef3a598a..69e748ec80ab 100644
+--- a/kernel/cgroup/cpuset.c
++++ b/kernel/cgroup/cpuset.c
+@@ -855,7 +855,7 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
+ return ret;
+ }
+
+-#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_ALT)
+ /*
+ * Helper routine for generate_sched_domains().
+ * Do cpusets a, b have overlapping effective cpus_allowed masks?
+@@ -1254,7 +1254,7 @@ static void rebuild_sched_domains_locked(void)
+ /* Have scheduler rebuild the domains */
+ partition_and_rebuild_sched_domains(ndoms, doms, attr);
+ }
+-#else /* !CONFIG_SMP */
++#else /* !CONFIG_SMP || CONFIG_SCHED_ALT */
+ static void rebuild_sched_domains_locked(void)
+ {
+ }
+@@ -3308,12 +3308,15 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
+ goto out_unlock;
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ if (dl_task(task)) {
+ cs->nr_migrate_dl_tasks++;
+ cs->sum_migrate_dl_bw += task->dl.dl_bw;
+ }
++#endif
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ if (!cs->nr_migrate_dl_tasks)
+ goto out_success;
+
+@@ -3334,6 +3337,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
+ }
+
+ out_success:
++#endif
+ /*
+ * Mark attach is in progress. This makes validate_change() fail
+ * changes which zero cpus/mems_allowed.
+@@ -3357,12 +3361,14 @@ static void cpuset_cancel_attach(struct cgroup_taskset *tset)
+ if (!cs->attach_in_progress)
+ wake_up(&cpuset_attach_wq);
+
++#ifndef CONFIG_SCHED_ALT
+ if (cs->nr_migrate_dl_tasks) {
+ int cpu = cpumask_any(cs->effective_cpus);
+
+ dl_bw_free(cpu, cs->sum_migrate_dl_bw);
+ reset_migrate_dl_data(cs);
+ }
++#endif
+
+ mutex_unlock(&cpuset_mutex);
+ }
+diff --git a/kernel/delayacct.c b/kernel/delayacct.c
+index 6f0c358e73d8..8111481ce8b1 100644
+--- a/kernel/delayacct.c
++++ b/kernel/delayacct.c
+@@ -150,7 +150,7 @@ int delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
+ */
+ t1 = tsk->sched_info.pcount;
+ t2 = tsk->sched_info.run_delay;
+- t3 = tsk->se.sum_exec_runtime;
++ t3 = tsk_seruntime(tsk);
+
+ d->cpu_count += t1;
+
+diff --git a/kernel/exit.c b/kernel/exit.c
+index dfb963d2f862..510f2dea00c4 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -176,7 +176,7 @@ static void __exit_signal(struct task_struct *tsk)
+ sig->curr_target = next_thread(tsk);
+ }
+
+- add_device_randomness((const void*) &tsk->se.sum_exec_runtime,
++ add_device_randomness((const void*) &tsk_seruntime(tsk),
+ sizeof(unsigned long long));
+
+ /*
+@@ -197,7 +197,7 @@ static void __exit_signal(struct task_struct *tsk)
+ sig->inblock += task_io_get_inblock(tsk);
+ sig->oublock += task_io_get_oublock(tsk);
+ task_io_accounting_add(&sig->ioac, &tsk->ioac);
+- sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
++ sig->sum_sched_runtime += tsk_seruntime(tsk);
+ sig->nr_threads--;
+ __unhash_process(tsk, group_dead);
+ write_sequnlock(&sig->stats_lock);
+diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
+index 4a10e8c16fd2..cfbbdd64b851 100644
+--- a/kernel/locking/rtmutex.c
++++ b/kernel/locking/rtmutex.c
+@@ -362,7 +362,7 @@ waiter_update_prio(struct rt_mutex_waiter *waiter, struct task_struct *task)
+ lockdep_assert(RB_EMPTY_NODE(&waiter->tree.entry));
+
+ waiter->tree.prio = __waiter_prio(task);
+- waiter->tree.deadline = task->dl.deadline;
++ waiter->tree.deadline = __tsk_deadline(task);
+ }
+
+ /*
+@@ -383,16 +383,20 @@ waiter_clone_prio(struct rt_mutex_waiter *waiter, struct task_struct *task)
+ * Only use with rt_waiter_node_{less,equal}()
+ */
+ #define task_to_waiter_node(p) \
+- &(struct rt_waiter_node){ .prio = __waiter_prio(p), .deadline = (p)->dl.deadline }
++ &(struct rt_waiter_node){ .prio = __waiter_prio(p), .deadline = __tsk_deadline(p) }
+ #define task_to_waiter(p) \
+ &(struct rt_mutex_waiter){ .tree = *task_to_waiter_node(p) }
+
+ static __always_inline int rt_waiter_node_less(struct rt_waiter_node *left,
+ struct rt_waiter_node *right)
+ {
++#ifdef CONFIG_SCHED_PDS
++ return (left->deadline < right->deadline);
++#else
+ if (left->prio < right->prio)
+ return 1;
+
++#ifndef CONFIG_SCHED_BMQ
+ /*
+ * If both waiters have dl_prio(), we check the deadlines of the
+ * associated tasks.
+@@ -401,16 +405,22 @@ static __always_inline int rt_waiter_node_less(struct rt_waiter_node *left,
+ */
+ if (dl_prio(left->prio))
+ return dl_time_before(left->deadline, right->deadline);
++#endif
+
+ return 0;
++#endif
+ }
+
+ static __always_inline int rt_waiter_node_equal(struct rt_waiter_node *left,
+ struct rt_waiter_node *right)
+ {
++#ifdef CONFIG_SCHED_PDS
++ return (left->deadline == right->deadline);
++#else
+ if (left->prio != right->prio)
+ return 0;
+
++#ifndef CONFIG_SCHED_BMQ
+ /*
+ * If both waiters have dl_prio(), we check the deadlines of the
+ * associated tasks.
+@@ -419,8 +429,10 @@ static __always_inline int rt_waiter_node_equal(struct rt_waiter_node *left,
+ */
+ if (dl_prio(left->prio))
+ return left->deadline == right->deadline;
++#endif
+
+ return 1;
++#endif
+ }
+
+ static inline bool rt_mutex_steal(struct rt_mutex_waiter *waiter,
+diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
+index 976092b7bd45..31d587c16ec1 100644
+--- a/kernel/sched/Makefile
++++ b/kernel/sched/Makefile
+@@ -28,7 +28,12 @@ endif
+ # These compilation units have roughly the same size and complexity - so their
+ # build parallelizes well and finishes roughly at once:
+ #
++ifdef CONFIG_SCHED_ALT
++obj-y += alt_core.o
++obj-$(CONFIG_SCHED_DEBUG) += alt_debug.o
++else
+ obj-y += core.o
+ obj-y += fair.o
++endif
+ obj-y += build_policy.o
+ obj-y += build_utility.o
+diff --git a/kernel/sched/alt_core.c b/kernel/sched/alt_core.c
+new file mode 100644
+index 000000000000..31fadbf46a7b
+--- /dev/null
++++ b/kernel/sched/alt_core.c
+@@ -0,0 +1,8944 @@
++/*
++ * kernel/sched/alt_core.c
++ *
++ * Core alternative kernel scheduler code and related syscalls
++ *
++ * Copyright (C) 1991-2002 Linus Torvalds
++ *
++ * 2009-08-13 Brainfuck deadline scheduling policy by Con Kolivas deletes
++ * a whole lot of those previous things.
++ * 2017-09-06 Priority and Deadline based Skip list multiple queue kernel
++ * scheduler by Alfred Chen.
++ * 2019-02-20 BMQ(BitMap Queue) kernel scheduler by Alfred Chen.
++ */
++#include <linux/sched/clock.h>
++#include <linux/sched/cputime.h>
++#include <linux/sched/debug.h>
++#include <linux/sched/hotplug.h>
++#include <linux/sched/init.h>
++#include <linux/sched/isolation.h>
++#include <linux/sched/loadavg.h>
++#include <linux/sched/mm.h>
++#include <linux/sched/nohz.h>
++#include <linux/sched/stat.h>
++#include <linux/sched/wake_q.h>
++
++#include <linux/blkdev.h>
++#include <linux/context_tracking.h>
++#include <linux/cpuset.h>
++#include <linux/delayacct.h>
++#include <linux/init_task.h>
++#include <linux/kcov.h>
++#include <linux/kprobes.h>
++#include <linux/nmi.h>
++#include <linux/rseq.h>
++#include <linux/scs.h>
++
++#include <uapi/linux/sched/types.h>
++
++#include <asm/irq_regs.h>
++#include <asm/switch_to.h>
++
++#define CREATE_TRACE_POINTS
++#include <trace/events/sched.h>
++#include <trace/events/ipi.h>
++#undef CREATE_TRACE_POINTS
++
++#include "sched.h"
++#include "smp.h"
++
++#include "pelt.h"
++
++#include "../../io_uring/io-wq.h"
++#include "../smpboot.h"
++
++EXPORT_TRACEPOINT_SYMBOL_GPL(ipi_send_cpu);
++EXPORT_TRACEPOINT_SYMBOL_GPL(ipi_send_cpumask);
++
++/*
++ * Export tracepoints that act as a bare tracehook (ie: have no trace event
++ * associated with them) to allow external modules to probe them.
++ */
++EXPORT_TRACEPOINT_SYMBOL_GPL(pelt_irq_tp);
++
++#ifdef CONFIG_SCHED_DEBUG
++#define sched_feat(x) (1)
++/*
++ * Print a warning if need_resched is set for the given duration (if
++ * LATENCY_WARN is enabled).
++ *
++ * If sysctl_resched_latency_warn_once is set, only one warning will be shown
++ * per boot.
++ */
++__read_mostly int sysctl_resched_latency_warn_ms = 100;
++__read_mostly int sysctl_resched_latency_warn_once = 1;
++#else
++#define sched_feat(x) (0)
++#endif /* CONFIG_SCHED_DEBUG */
++
++#define ALT_SCHED_VERSION "v6.8-r2"
++
++/*
++ * Compile time debug macro
++ * #define ALT_SCHED_DEBUG
++ */
++
++/* rt_prio(prio) defined in include/linux/sched/rt.h */
++#define rt_task(p) rt_prio((p)->prio)
++#define rt_policy(policy) ((policy) == SCHED_FIFO || (policy) == SCHED_RR)
++#define task_has_rt_policy(p) (rt_policy((p)->policy))
++
++#define STOP_PRIO (MAX_RT_PRIO - 1)
++
++/*
++ * Time slice
++ * (default: 4 msec, units: nanoseconds)
++ */
++unsigned int sysctl_sched_base_slice __read_mostly = (4 << 20);
++
++#ifdef CONFIG_SCHED_BMQ
++#include "bmq.h"
++#endif
++#ifdef CONFIG_SCHED_PDS
++#include "pds.h"
++#endif
++
++struct affinity_context {
++ const struct cpumask *new_mask;
++ struct cpumask *user_mask;
++ unsigned int flags;
++};
++
++/* Reschedule if less than this many μs left */
++#define RESCHED_NS (100 << 10)
++
++/**
++ * sched_yield_type - Type of sched_yield() will be performed.
++ * 0: No yield.
++ * 1: Requeue task. (default)
++ */
++int sched_yield_type __read_mostly = 1;
++
++#ifdef CONFIG_SMP
++static cpumask_t sched_rq_pending_mask ____cacheline_aligned_in_smp;
++
++DEFINE_PER_CPU_ALIGNED(cpumask_t [NR_CPU_AFFINITY_LEVELS], sched_cpu_topo_masks);
++DEFINE_PER_CPU_ALIGNED(cpumask_t *, sched_cpu_llc_mask);
++DEFINE_PER_CPU_ALIGNED(cpumask_t *, sched_cpu_topo_end_mask);
++
++#ifdef CONFIG_SCHED_SMT
++DEFINE_STATIC_KEY_FALSE(sched_smt_present);
++EXPORT_SYMBOL_GPL(sched_smt_present);
++#endif
++
++/*
++ * Keep a unique ID per domain (we use the first CPUs number in the cpumask of
++ * the domain), this allows us to quickly tell if two cpus are in the same cache
++ * domain, see cpus_share_cache().
++ */
++DEFINE_PER_CPU(int, sd_llc_id);
++#endif /* CONFIG_SMP */
++
++static DEFINE_MUTEX(sched_hotcpu_mutex);
++
++DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
++
++#ifndef prepare_arch_switch
++# define prepare_arch_switch(next) do { } while (0)
++#endif
++#ifndef finish_arch_post_lock_switch
++# define finish_arch_post_lock_switch() do { } while (0)
++#endif
++
++static cpumask_t sched_preempt_mask[SCHED_QUEUE_BITS + 1] ____cacheline_aligned_in_smp;
++
++static cpumask_t *const sched_idle_mask = &sched_preempt_mask[SCHED_QUEUE_BITS - 1];
++#ifdef CONFIG_SCHED_SMT
++static cpumask_t *const sched_sg_idle_mask = &sched_preempt_mask[SCHED_QUEUE_BITS];
++#endif
++
++/* task function */
++static inline const struct cpumask *task_user_cpus(struct task_struct *p)
++{
++ if (!p->user_cpus_ptr)
++ return cpu_possible_mask; /* &init_task.cpus_mask */
++ return p->user_cpus_ptr;
++}
++
++/* sched_queue related functions */
++static inline void sched_queue_init(struct sched_queue *q)
++{
++ int i;
++
++ bitmap_zero(q->bitmap, SCHED_QUEUE_BITS);
++ for(i = 0; i < SCHED_LEVELS; i++)
++ INIT_LIST_HEAD(&q->heads[i]);
++}
++
++/*
++ * Init idle task and put into queue structure of rq
++ * IMPORTANT: may be called multiple times for a single cpu
++ */
++static inline void sched_queue_init_idle(struct sched_queue *q,
++ struct task_struct *idle)
++{
++ INIT_LIST_HEAD(&q->heads[IDLE_TASK_SCHED_PRIO]);
++ list_add_tail(&idle->sq_node, &q->heads[IDLE_TASK_SCHED_PRIO]);
++ idle->on_rq = TASK_ON_RQ_QUEUED;
++}
++
++static inline void
++clear_recorded_preempt_mask(int pr, int low, int high, int cpu)
++{
++ if (low < pr && pr <= high)
++ cpumask_clear_cpu(cpu, sched_preempt_mask + pr);
++}
++
++static inline void
++set_recorded_preempt_mask(int pr, int low, int high, int cpu)
++{
++ if (low < pr && pr <= high)
++ cpumask_set_cpu(cpu, sched_preempt_mask + pr);
++}
++
++static atomic_t sched_prio_record = ATOMIC_INIT(0);
++
++/* water mark related functions */
++static inline void update_sched_preempt_mask(struct rq *rq)
++{
++ unsigned long prio = find_first_bit(rq->queue.bitmap, SCHED_QUEUE_BITS);
++ unsigned long last_prio = rq->prio;
++ int cpu, pr;
++
++ if (prio == last_prio)
++ return;
++
++ rq->prio = prio;
++#ifdef CONFIG_SCHED_PDS
++ rq->prio_idx = sched_prio2idx(rq->prio, rq);
++#endif
++ cpu = cpu_of(rq);
++ pr = atomic_read(&sched_prio_record);
++
++ if (prio < last_prio) {
++ if (IDLE_TASK_SCHED_PRIO == last_prio) {
++#ifdef CONFIG_SCHED_SMT
++ if (static_branch_likely(&sched_smt_present))
++ cpumask_andnot(sched_sg_idle_mask,
++ sched_sg_idle_mask, cpu_smt_mask(cpu));
++#endif
++ cpumask_clear_cpu(cpu, sched_idle_mask);
++ last_prio -= 2;
++ }
++ clear_recorded_preempt_mask(pr, prio, last_prio, cpu);
++
++ return;
++ }
++ /* last_prio < prio */
++ if (IDLE_TASK_SCHED_PRIO == prio) {
++#ifdef CONFIG_SCHED_SMT
++ if (static_branch_likely(&sched_smt_present) &&
++ cpumask_intersects(cpu_smt_mask(cpu), sched_idle_mask))
++ cpumask_or(sched_sg_idle_mask,
++ sched_sg_idle_mask, cpu_smt_mask(cpu));
++#endif
++ cpumask_set_cpu(cpu, sched_idle_mask);
++ prio -= 2;
++ }
++ set_recorded_preempt_mask(pr, last_prio, prio, cpu);
++}
++
++/*
++ * This routine assume that the idle task always in queue
++ */
++static inline struct task_struct *sched_rq_first_task(struct rq *rq)
++{
++ const struct list_head *head = &rq->queue.heads[sched_rq_prio_idx(rq)];
++
++ return list_first_entry(head, struct task_struct, sq_node);
++}
++
++static inline struct task_struct *
++sched_rq_next_task(struct task_struct *p, struct rq *rq)
++{
++ struct list_head *next = p->sq_node.next;
++
++ if (&rq->queue.heads[0] <= next && next < &rq->queue.heads[SCHED_LEVELS]) {
++ struct list_head *head;
++ unsigned long idx = next - &rq->queue.heads[0];
++
++ idx = find_next_bit(rq->queue.bitmap, SCHED_QUEUE_BITS, sched_idx2prio(idx, rq) + 1);
++ head = &rq->queue.heads[sched_prio2idx(idx, rq)];
++
++ return list_first_entry(head, struct task_struct, sq_node);
++ }
++
++ return list_next_entry(p, sq_node);
++}
++
++/*
++ * Serialization rules:
++ *
++ * Lock order:
++ *
++ * p->pi_lock
++ * rq->lock
++ * hrtimer_cpu_base->lock (hrtimer_start() for bandwidth controls)
++ *
++ * rq1->lock
++ * rq2->lock where: rq1 < rq2
++ *
++ * Regular state:
++ *
++ * Normal scheduling state is serialized by rq->lock. __schedule() takes the
++ * local CPU's rq->lock, it optionally removes the task from the runqueue and
++ * always looks at the local rq data structures to find the most eligible task
++ * to run next.
++ *
++ * Task enqueue is also under rq->lock, possibly taken from another CPU.
++ * Wakeups from another LLC domain might use an IPI to transfer the enqueue to
++ * the local CPU to avoid bouncing the runqueue state around [ see
++ * ttwu_queue_wakelist() ]
++ *
++ * Task wakeup, specifically wakeups that involve migration, are horribly
++ * complicated to avoid having to take two rq->locks.
++ *
++ * Special state:
++ *
++ * System-calls and anything external will use task_rq_lock() which acquires
++ * both p->pi_lock and rq->lock. As a consequence the state they change is
++ * stable while holding either lock:
++ *
++ * - sched_setaffinity()/
++ * set_cpus_allowed_ptr(): p->cpus_ptr, p->nr_cpus_allowed
++ * - set_user_nice(): p->se.load, p->*prio
++ * - __sched_setscheduler(): p->sched_class, p->policy, p->*prio,
++ * p->se.load, p->rt_priority,
++ * p->dl.dl_{runtime, deadline, period, flags, bw, density}
++ * - sched_setnuma(): p->numa_preferred_nid
++ * - sched_move_task(): p->sched_task_group
++ * - uclamp_update_active() p->uclamp*
++ *
++ * p->state <- TASK_*:
++ *
++ * is changed locklessly using set_current_state(), __set_current_state() or
++ * set_special_state(), see their respective comments, or by
++ * try_to_wake_up(). This latter uses p->pi_lock to serialize against
++ * concurrent self.
++ *
++ * p->on_rq <- { 0, 1 = TASK_ON_RQ_QUEUED, 2 = TASK_ON_RQ_MIGRATING }:
++ *
++ * is set by activate_task() and cleared by deactivate_task(), under
++ * rq->lock. Non-zero indicates the task is runnable, the special
++ * ON_RQ_MIGRATING state is used for migration without holding both
++ * rq->locks. It indicates task_cpu() is not stable, see task_rq_lock().
++ *
++ * p->on_cpu <- { 0, 1 }:
++ *
++ * is set by prepare_task() and cleared by finish_task() such that it will be
++ * set before p is scheduled-in and cleared after p is scheduled-out, both
++ * under rq->lock. Non-zero indicates the task is running on its CPU.
++ *
++ * [ The astute reader will observe that it is possible for two tasks on one
++ * CPU to have ->on_cpu = 1 at the same time. ]
++ *
++ * task_cpu(p): is changed by set_task_cpu(), the rules are:
++ *
++ * - Don't call set_task_cpu() on a blocked task:
++ *
++ * We don't care what CPU we're not running on, this simplifies hotplug,
++ * the CPU assignment of blocked tasks isn't required to be valid.
++ *
++ * - for try_to_wake_up(), called under p->pi_lock:
++ *
++ * This allows try_to_wake_up() to only take one rq->lock, see its comment.
++ *
++ * - for migration called under rq->lock:
++ * [ see task_on_rq_migrating() in task_rq_lock() ]
++ *
++ * o move_queued_task()
++ * o detach_task()
++ *
++ * - for migration called under double_rq_lock():
++ *
++ * o __migrate_swap_task()
++ * o push_rt_task() / pull_rt_task()
++ * o push_dl_task() / pull_dl_task()
++ * o dl_task_offline_migration()
++ *
++ */
++
++/*
++ * Context: p->pi_lock
++ */
++static inline struct rq
++*__task_access_lock(struct task_struct *p, raw_spinlock_t **plock)
++{
++ struct rq *rq;
++ for (;;) {
++ rq = task_rq(p);
++ if (p->on_cpu || task_on_rq_queued(p)) {
++ raw_spin_lock(&rq->lock);
++ if (likely((p->on_cpu || task_on_rq_queued(p))
++ && rq == task_rq(p))) {
++ *plock = &rq->lock;
++ return rq;
++ }
++ raw_spin_unlock(&rq->lock);
++ } else if (task_on_rq_migrating(p)) {
++ do {
++ cpu_relax();
++ } while (unlikely(task_on_rq_migrating(p)));
++ } else {
++ *plock = NULL;
++ return rq;
++ }
++ }
++}
++
++static inline void
++__task_access_unlock(struct task_struct *p, raw_spinlock_t *lock)
++{
++ if (NULL != lock)
++ raw_spin_unlock(lock);
++}
++
++static inline struct rq
++*task_access_lock_irqsave(struct task_struct *p, raw_spinlock_t **plock,
++ unsigned long *flags)
++{
++ struct rq *rq;
++ for (;;) {
++ rq = task_rq(p);
++ if (p->on_cpu || task_on_rq_queued(p)) {
++ raw_spin_lock_irqsave(&rq->lock, *flags);
++ if (likely((p->on_cpu || task_on_rq_queued(p))
++ && rq == task_rq(p))) {
++ *plock = &rq->lock;
++ return rq;
++ }
++ raw_spin_unlock_irqrestore(&rq->lock, *flags);
++ } else if (task_on_rq_migrating(p)) {
++ do {
++ cpu_relax();
++ } while (unlikely(task_on_rq_migrating(p)));
++ } else {
++ raw_spin_lock_irqsave(&p->pi_lock, *flags);
++ if (likely(!p->on_cpu && !p->on_rq &&
++ rq == task_rq(p))) {
++ *plock = &p->pi_lock;
++ return rq;
++ }
++ raw_spin_unlock_irqrestore(&p->pi_lock, *flags);
++ }
++ }
++}
++
++static inline void
++task_access_unlock_irqrestore(struct task_struct *p, raw_spinlock_t *lock,
++ unsigned long *flags)
++{
++ raw_spin_unlock_irqrestore(lock, *flags);
++}
++
++/*
++ * __task_rq_lock - lock the rq @p resides on.
++ */
++struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf)
++ __acquires(rq->lock)
++{
++ struct rq *rq;
++
++ lockdep_assert_held(&p->pi_lock);
++
++ for (;;) {
++ rq = task_rq(p);
++ raw_spin_lock(&rq->lock);
++ if (likely(rq == task_rq(p) && !task_on_rq_migrating(p)))
++ return rq;
++ raw_spin_unlock(&rq->lock);
++
++ while (unlikely(task_on_rq_migrating(p)))
++ cpu_relax();
++ }
++}
++
++/*
++ * task_rq_lock - lock p->pi_lock and lock the rq @p resides on.
++ */
++struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf)
++ __acquires(p->pi_lock)
++ __acquires(rq->lock)
++{
++ struct rq *rq;
++
++ for (;;) {
++ raw_spin_lock_irqsave(&p->pi_lock, rf->flags);
++ rq = task_rq(p);
++ raw_spin_lock(&rq->lock);
++ /*
++ * move_queued_task() task_rq_lock()
++ *
++ * ACQUIRE (rq->lock)
++ * [S] ->on_rq = MIGRATING [L] rq = task_rq()
++ * WMB (__set_task_cpu()) ACQUIRE (rq->lock);
++ * [S] ->cpu = new_cpu [L] task_rq()
++ * [L] ->on_rq
++ * RELEASE (rq->lock)
++ *
++ * If we observe the old CPU in task_rq_lock(), the acquire of
++ * the old rq->lock will fully serialize against the stores.
++ *
++ * If we observe the new CPU in task_rq_lock(), the address
++ * dependency headed by '[L] rq = task_rq()' and the acquire
++ * will pair with the WMB to ensure we then also see migrating.
++ */
++ if (likely(rq == task_rq(p) && !task_on_rq_migrating(p))) {
++ return rq;
++ }
++ raw_spin_unlock(&rq->lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags);
++
++ while (unlikely(task_on_rq_migrating(p)))
++ cpu_relax();
++ }
++}
++
++static inline void
++rq_lock_irqsave(struct rq *rq, struct rq_flags *rf)
++ __acquires(rq->lock)
++{
++ raw_spin_lock_irqsave(&rq->lock, rf->flags);
++}
++
++static inline void
++rq_unlock_irqrestore(struct rq *rq, struct rq_flags *rf)
++ __releases(rq->lock)
++{
++ raw_spin_unlock_irqrestore(&rq->lock, rf->flags);
++}
++
++DEFINE_LOCK_GUARD_1(rq_lock_irqsave, struct rq,
++ rq_lock_irqsave(_T->lock, &_T->rf),
++ rq_unlock_irqrestore(_T->lock, &_T->rf),
++ struct rq_flags rf)
++
++void raw_spin_rq_lock_nested(struct rq *rq, int subclass)
++{
++ raw_spinlock_t *lock;
++
++ /* Matches synchronize_rcu() in __sched_core_enable() */
++ preempt_disable();
++
++ for (;;) {
++ lock = __rq_lockp(rq);
++ raw_spin_lock_nested(lock, subclass);
++ if (likely(lock == __rq_lockp(rq))) {
++ /* preempt_count *MUST* be > 1 */
++ preempt_enable_no_resched();
++ return;
++ }
++ raw_spin_unlock(lock);
++ }
++}
++
++void raw_spin_rq_unlock(struct rq *rq)
++{
++ raw_spin_unlock(rq_lockp(rq));
++}
++
++/*
++ * RQ-clock updating methods:
++ */
++
++static void update_rq_clock_task(struct rq *rq, s64 delta)
++{
++/*
++ * In theory, the compile should just see 0 here, and optimize out the call
++ * to sched_rt_avg_update. But I don't trust it...
++ */
++ s64 __maybe_unused steal = 0, irq_delta = 0;
++
++#ifdef CONFIG_IRQ_TIME_ACCOUNTING
++ irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time;
++
++ /*
++ * Since irq_time is only updated on {soft,}irq_exit, we might run into
++ * this case when a previous update_rq_clock() happened inside a
++ * {soft,}irq region.
++ *
++ * When this happens, we stop ->clock_task and only update the
++ * prev_irq_time stamp to account for the part that fit, so that a next
++ * update will consume the rest. This ensures ->clock_task is
++ * monotonic.
++ *
++ * It does however cause some slight miss-attribution of {soft,}irq
++ * time, a more accurate solution would be to update the irq_time using
++ * the current rq->clock timestamp, except that would require using
++ * atomic ops.
++ */
++ if (irq_delta > delta)
++ irq_delta = delta;
++
++ rq->prev_irq_time += irq_delta;
++ delta -= irq_delta;
++ delayacct_irq(rq->curr, irq_delta);
++#endif
++#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
++ if (static_key_false((¶virt_steal_rq_enabled))) {
++ steal = paravirt_steal_clock(cpu_of(rq));
++ steal -= rq->prev_steal_time_rq;
++
++ if (unlikely(steal > delta))
++ steal = delta;
++
++ rq->prev_steal_time_rq += steal;
++ delta -= steal;
++ }
++#endif
++
++ rq->clock_task += delta;
++
++#ifdef CONFIG_HAVE_SCHED_AVG_IRQ
++ if ((irq_delta + steal))
++ update_irq_load_avg(rq, irq_delta + steal);
++#endif
++}
++
++static inline void update_rq_clock(struct rq *rq)
++{
++ s64 delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
++
++ if (unlikely(delta <= 0))
++ return;
++ rq->clock += delta;
++ sched_update_rq_clock(rq);
++ update_rq_clock_task(rq, delta);
++}
++
++/*
++ * RQ Load update routine
++ */
++#define RQ_LOAD_HISTORY_BITS (sizeof(s32) * 8ULL)
++#define RQ_UTIL_SHIFT (8)
++#define RQ_LOAD_HISTORY_TO_UTIL(l) (((l) >> (RQ_LOAD_HISTORY_BITS - 1 - RQ_UTIL_SHIFT)) & 0xff)
++
++#define LOAD_BLOCK(t) ((t) >> 17)
++#define LOAD_HALF_BLOCK(t) ((t) >> 16)
++#define BLOCK_MASK(t) ((t) & ((0x01 << 18) - 1))
++#define LOAD_BLOCK_BIT(b) (1UL << (RQ_LOAD_HISTORY_BITS - 1 - (b)))
++#define CURRENT_LOAD_BIT LOAD_BLOCK_BIT(0)
++
++static inline void rq_load_update(struct rq *rq)
++{
++ u64 time = rq->clock;
++ u64 delta = min(LOAD_BLOCK(time) - LOAD_BLOCK(rq->load_stamp),
++ RQ_LOAD_HISTORY_BITS - 1);
++ u64 prev = !!(rq->load_history & CURRENT_LOAD_BIT);
++ u64 curr = !!rq->nr_running;
++
++ if (delta) {
++ rq->load_history = rq->load_history >> delta;
++
++ if (delta < RQ_UTIL_SHIFT) {
++ rq->load_block += (~BLOCK_MASK(rq->load_stamp)) * prev;
++ if (!!LOAD_HALF_BLOCK(rq->load_block) ^ curr)
++ rq->load_history ^= LOAD_BLOCK_BIT(delta);
++ }
++
++ rq->load_block = BLOCK_MASK(time) * prev;
++ } else {
++ rq->load_block += (time - rq->load_stamp) * prev;
++ }
++ if (prev ^ curr)
++ rq->load_history ^= CURRENT_LOAD_BIT;
++ rq->load_stamp = time;
++}
++
++unsigned long rq_load_util(struct rq *rq, unsigned long max)
++{
++ return RQ_LOAD_HISTORY_TO_UTIL(rq->load_history) * (max >> RQ_UTIL_SHIFT);
++}
++
++#ifdef CONFIG_SMP
++unsigned long sched_cpu_util(int cpu)
++{
++ return rq_load_util(cpu_rq(cpu), arch_scale_cpu_capacity(cpu));
++}
++#endif /* CONFIG_SMP */
++
++#ifdef CONFIG_CPU_FREQ
++/**
++ * cpufreq_update_util - Take a note about CPU utilization changes.
++ * @rq: Runqueue to carry out the update for.
++ * @flags: Update reason flags.
++ *
++ * This function is called by the scheduler on the CPU whose utilization is
++ * being updated.
++ *
++ * It can only be called from RCU-sched read-side critical sections.
++ *
++ * The way cpufreq is currently arranged requires it to evaluate the CPU
++ * performance state (frequency/voltage) on a regular basis to prevent it from
++ * being stuck in a completely inadequate performance level for too long.
++ * That is not guaranteed to happen if the updates are only triggered from CFS
++ * and DL, though, because they may not be coming in if only RT tasks are
++ * active all the time (or there are RT tasks only).
++ *
++ * As a workaround for that issue, this function is called periodically by the
++ * RT sched class to trigger extra cpufreq updates to prevent it from stalling,
++ * but that really is a band-aid. Going forward it should be replaced with
++ * solutions targeted more specifically at RT tasks.
++ */
++static inline void cpufreq_update_util(struct rq *rq, unsigned int flags)
++{
++ struct update_util_data *data;
++
++#ifdef CONFIG_SMP
++ rq_load_update(rq);
++#endif
++ data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data,
++ cpu_of(rq)));
++ if (data)
++ data->func(data, rq_clock(rq), flags);
++}
++#else
++static inline void cpufreq_update_util(struct rq *rq, unsigned int flags)
++{
++#ifdef CONFIG_SMP
++ rq_load_update(rq);
++#endif
++}
++#endif /* CONFIG_CPU_FREQ */
++
++#ifdef CONFIG_NO_HZ_FULL
++/*
++ * Tick may be needed by tasks in the runqueue depending on their policy and
++ * requirements. If tick is needed, lets send the target an IPI to kick it out
++ * of nohz mode if necessary.
++ */
++static inline void sched_update_tick_dependency(struct rq *rq)
++{
++ int cpu = cpu_of(rq);
++
++ if (!tick_nohz_full_cpu(cpu))
++ return;
++
++ if (rq->nr_running < 2)
++ tick_nohz_dep_clear_cpu(cpu, TICK_DEP_BIT_SCHED);
++ else
++ tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_SCHED);
++}
++#else /* !CONFIG_NO_HZ_FULL */
++static inline void sched_update_tick_dependency(struct rq *rq) { }
++#endif
++
++bool sched_task_on_rq(struct task_struct *p)
++{
++ return task_on_rq_queued(p);
++}
++
++unsigned long get_wchan(struct task_struct *p)
++{
++ unsigned long ip = 0;
++ unsigned int state;
++
++ if (!p || p == current)
++ return 0;
++
++ /* Only get wchan if task is blocked and we can keep it that way. */
++ raw_spin_lock_irq(&p->pi_lock);
++ state = READ_ONCE(p->__state);
++ smp_rmb(); /* see try_to_wake_up() */
++ if (state != TASK_RUNNING && state != TASK_WAKING && !p->on_rq)
++ ip = __get_wchan(p);
++ raw_spin_unlock_irq(&p->pi_lock);
++
++ return ip;
++}
++
++/*
++ * Add/Remove/Requeue task to/from the runqueue routines
++ * Context: rq->lock
++ */
++#define __SCHED_DEQUEUE_TASK(p, rq, flags, func) \
++ sched_info_dequeue(rq, p); \
++ \
++ __list_del_entry(&p->sq_node); \
++ if (p->sq_node.prev == p->sq_node.next) { \
++ clear_bit(sched_idx2prio(p->sq_node.next - &rq->queue.heads[0], rq), \
++ rq->queue.bitmap); \
++ func; \
++ }
++
++#define __SCHED_ENQUEUE_TASK(p, rq, flags, func) \
++ sched_info_enqueue(rq, p); \
++ { \
++ int idx, prio; \
++ TASK_SCHED_PRIO_IDX(p, rq, idx, prio); \
++ list_add_tail(&p->sq_node, &rq->queue.heads[idx]); \
++ if (list_is_first(&p->sq_node, &rq->queue.heads[idx])) { \
++ set_bit(prio, rq->queue.bitmap); \
++ func; \
++ } \
++ }
++
++static inline void dequeue_task(struct task_struct *p, struct rq *rq, int flags)
++{
++#ifdef ALT_SCHED_DEBUG
++ lockdep_assert_held(&rq->lock);
++
++ /*printk(KERN_INFO "sched: dequeue(%d) %px %016llx\n", cpu_of(rq), p, p->deadline);*/
++ WARN_ONCE(task_rq(p) != rq, "sched: dequeue task reside on cpu%d from cpu%d\n",
++ task_cpu(p), cpu_of(rq));
++#endif
++
++ __SCHED_DEQUEUE_TASK(p, rq, flags, update_sched_preempt_mask(rq));
++ --rq->nr_running;
++#ifdef CONFIG_SMP
++ if (1 == rq->nr_running)
++ cpumask_clear_cpu(cpu_of(rq), &sched_rq_pending_mask);
++#endif
++
++ sched_update_tick_dependency(rq);
++}
++
++static inline void enqueue_task(struct task_struct *p, struct rq *rq, int flags)
++{
++#ifdef ALT_SCHED_DEBUG
++ lockdep_assert_held(&rq->lock);
++
++ /*printk(KERN_INFO "sched: enqueue(%d) %px %d\n", cpu_of(rq), p, p->prio);*/
++ WARN_ONCE(task_rq(p) != rq, "sched: enqueue task reside on cpu%d to cpu%d\n",
++ task_cpu(p), cpu_of(rq));
++#endif
++
++ __SCHED_ENQUEUE_TASK(p, rq, flags, update_sched_preempt_mask(rq));
++ ++rq->nr_running;
++#ifdef CONFIG_SMP
++ if (2 == rq->nr_running)
++ cpumask_set_cpu(cpu_of(rq), &sched_rq_pending_mask);
++#endif
++
++ sched_update_tick_dependency(rq);
++}
++
++static inline void requeue_task(struct task_struct *p, struct rq *rq)
++{
++ struct list_head *node = &p->sq_node;
++ int deq_idx, idx, prio;
++
++ TASK_SCHED_PRIO_IDX(p, rq, idx, prio);
++#ifdef ALT_SCHED_DEBUG
++ lockdep_assert_held(&rq->lock);
++ /*printk(KERN_INFO "sched: requeue(%d) %px %016llx\n", cpu_of(rq), p, p->deadline);*/
++ WARN_ONCE(task_rq(p) != rq, "sched: cpu[%d] requeue task reside on cpu%d\n",
++ cpu_of(rq), task_cpu(p));
++#endif
++ if (list_is_last(node, &rq->queue.heads[idx]))
++ return;
++
++ __list_del_entry(node);
++ if (node->prev == node->next && (deq_idx = node->next - &rq->queue.heads[0]) != idx)
++ clear_bit(sched_idx2prio(deq_idx, rq), rq->queue.bitmap);
++
++ list_add_tail(node, &rq->queue.heads[idx]);
++ if (list_is_first(node, &rq->queue.heads[idx]))
++ set_bit(prio, rq->queue.bitmap);
++ update_sched_preempt_mask(rq);
++}
++
++/*
++ * cmpxchg based fetch_or, macro so it works for different integer types
++ */
++#define fetch_or(ptr, mask) \
++ ({ \
++ typeof(ptr) _ptr = (ptr); \
++ typeof(mask) _mask = (mask); \
++ typeof(*_ptr) _val = *_ptr; \
++ \
++ do { \
++ } while (!try_cmpxchg(_ptr, &_val, _val | _mask)); \
++ _val; \
++})
++
++#if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG)
++/*
++ * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG,
++ * this avoids any races wrt polling state changes and thereby avoids
++ * spurious IPIs.
++ */
++static inline bool set_nr_and_not_polling(struct task_struct *p)
++{
++ struct thread_info *ti = task_thread_info(p);
++ return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG);
++}
++
++/*
++ * Atomically set TIF_NEED_RESCHED if TIF_POLLING_NRFLAG is set.
++ *
++ * If this returns true, then the idle task promises to call
++ * sched_ttwu_pending() and reschedule soon.
++ */
++static bool set_nr_if_polling(struct task_struct *p)
++{
++ struct thread_info *ti = task_thread_info(p);
++ typeof(ti->flags) val = READ_ONCE(ti->flags);
++
++ do {
++ if (!(val & _TIF_POLLING_NRFLAG))
++ return false;
++ if (val & _TIF_NEED_RESCHED)
++ return true;
++ } while (!try_cmpxchg(&ti->flags, &val, val | _TIF_NEED_RESCHED));
++
++ return true;
++}
++
++#else
++static inline bool set_nr_and_not_polling(struct task_struct *p)
++{
++ set_tsk_need_resched(p);
++ return true;
++}
++
++#ifdef CONFIG_SMP
++static inline bool set_nr_if_polling(struct task_struct *p)
++{
++ return false;
++}
++#endif
++#endif
++
++static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task)
++{
++ struct wake_q_node *node = &task->wake_q;
++
++ /*
++ * Atomically grab the task, if ->wake_q is !nil already it means
++ * it's already queued (either by us or someone else) and will get the
++ * wakeup due to that.
++ *
++ * In order to ensure that a pending wakeup will observe our pending
++ * state, even in the failed case, an explicit smp_mb() must be used.
++ */
++ smp_mb__before_atomic();
++ if (unlikely(cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL)))
++ return false;
++
++ /*
++ * The head is context local, there can be no concurrency.
++ */
++ *head->lastp = node;
++ head->lastp = &node->next;
++ return true;
++}
++
++/**
++ * wake_q_add() - queue a wakeup for 'later' waking.
++ * @head: the wake_q_head to add @task to
++ * @task: the task to queue for 'later' wakeup
++ *
++ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
++ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
++ * instantly.
++ *
++ * This function must be used as-if it were wake_up_process(); IOW the task
++ * must be ready to be woken at this location.
++ */
++void wake_q_add(struct wake_q_head *head, struct task_struct *task)
++{
++ if (__wake_q_add(head, task))
++ get_task_struct(task);
++}
++
++/**
++ * wake_q_add_safe() - safely queue a wakeup for 'later' waking.
++ * @head: the wake_q_head to add @task to
++ * @task: the task to queue for 'later' wakeup
++ *
++ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
++ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
++ * instantly.
++ *
++ * This function must be used as-if it were wake_up_process(); IOW the task
++ * must be ready to be woken at this location.
++ *
++ * This function is essentially a task-safe equivalent to wake_q_add(). Callers
++ * that already hold reference to @task can call the 'safe' version and trust
++ * wake_q to do the right thing depending whether or not the @task is already
++ * queued for wakeup.
++ */
++void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task)
++{
++ if (!__wake_q_add(head, task))
++ put_task_struct(task);
++}
++
++void wake_up_q(struct wake_q_head *head)
++{
++ struct wake_q_node *node = head->first;
++
++ while (node != WAKE_Q_TAIL) {
++ struct task_struct *task;
++
++ task = container_of(node, struct task_struct, wake_q);
++ /* task can safely be re-inserted now: */
++ node = node->next;
++ task->wake_q.next = NULL;
++
++ /*
++ * wake_up_process() executes a full barrier, which pairs with
++ * the queueing in wake_q_add() so as not to miss wakeups.
++ */
++ wake_up_process(task);
++ put_task_struct(task);
++ }
++}
++
++/*
++ * resched_curr - mark rq's current task 'to be rescheduled now'.
++ *
++ * On UP this means the setting of the need_resched flag, on SMP it
++ * might also involve a cross-CPU call to trigger the scheduler on
++ * the target CPU.
++ */
++static inline void resched_curr(struct rq *rq)
++{
++ struct task_struct *curr = rq->curr;
++ int cpu;
++
++ lockdep_assert_held(&rq->lock);
++
++ if (test_tsk_need_resched(curr))
++ return;
++
++ cpu = cpu_of(rq);
++ if (cpu == smp_processor_id()) {
++ set_tsk_need_resched(curr);
++ set_preempt_need_resched();
++ return;
++ }
++
++ if (set_nr_and_not_polling(curr))
++ smp_send_reschedule(cpu);
++ else
++ trace_sched_wake_idle_without_ipi(cpu);
++}
++
++void resched_cpu(int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++ unsigned long flags;
++
++ raw_spin_lock_irqsave(&rq->lock, flags);
++ if (cpu_online(cpu) || cpu == smp_processor_id())
++ resched_curr(cpu_rq(cpu));
++ raw_spin_unlock_irqrestore(&rq->lock, flags);
++}
++
++#ifdef CONFIG_SMP
++#ifdef CONFIG_NO_HZ_COMMON
++/*
++ * This routine will record that the CPU is going idle with tick stopped.
++ * This info will be used in performing idle load balancing in the future.
++ */
++void nohz_balance_enter_idle(int cpu) {}
++
++/*
++ * In the semi idle case, use the nearest busy CPU for migrating timers
++ * from an idle CPU. This is good for power-savings.
++ *
++ * We don't do similar optimization for completely idle system, as
++ * selecting an idle CPU will add more delays to the timers than intended
++ * (as that CPU's timer base may not be uptodate wrt jiffies etc).
++ */
++int get_nohz_timer_target(void)
++{
++ int i, cpu = smp_processor_id(), default_cpu = -1;
++ struct cpumask *mask;
++ const struct cpumask *hk_mask;
++
++ if (housekeeping_cpu(cpu, HK_TYPE_TIMER)) {
++ if (!idle_cpu(cpu))
++ return cpu;
++ default_cpu = cpu;
++ }
++
++ hk_mask = housekeeping_cpumask(HK_TYPE_TIMER);
++
++ for (mask = per_cpu(sched_cpu_topo_masks, cpu);
++ mask < per_cpu(sched_cpu_topo_end_mask, cpu); mask++)
++ for_each_cpu_and(i, mask, hk_mask)
++ if (!idle_cpu(i))
++ return i;
++
++ if (default_cpu == -1)
++ default_cpu = housekeeping_any_cpu(HK_TYPE_TIMER);
++ cpu = default_cpu;
++
++ return cpu;
++}
++
++/*
++ * When add_timer_on() enqueues a timer into the timer wheel of an
++ * idle CPU then this timer might expire before the next timer event
++ * which is scheduled to wake up that CPU. In case of a completely
++ * idle system the next event might even be infinite time into the
++ * future. wake_up_idle_cpu() ensures that the CPU is woken up and
++ * leaves the inner idle loop so the newly added timer is taken into
++ * account when the CPU goes back to idle and evaluates the timer
++ * wheel for the next timer event.
++ */
++static inline void wake_up_idle_cpu(int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ if (cpu == smp_processor_id())
++ return;
++
++ /*
++ * Set TIF_NEED_RESCHED and send an IPI if in the non-polling
++ * part of the idle loop. This forces an exit from the idle loop
++ * and a round trip to schedule(). Now this could be optimized
++ * because a simple new idle loop iteration is enough to
++ * re-evaluate the next tick. Provided some re-ordering of tick
++ * nohz functions that would need to follow TIF_NR_POLLING
++ * clearing:
++ *
++ * - On most archs, a simple fetch_or on ti::flags with a
++ * "0" value would be enough to know if an IPI needs to be sent.
++ *
++ * - x86 needs to perform a last need_resched() check between
++ * monitor and mwait which doesn't take timers into account.
++ * There a dedicated TIF_TIMER flag would be required to
++ * fetch_or here and be checked along with TIF_NEED_RESCHED
++ * before mwait().
++ *
++ * However, remote timer enqueue is not such a frequent event
++ * and testing of the above solutions didn't appear to report
++ * much benefits.
++ */
++ if (set_nr_and_not_polling(rq->idle))
++ smp_send_reschedule(cpu);
++ else
++ trace_sched_wake_idle_without_ipi(cpu);
++}
++
++static inline bool wake_up_full_nohz_cpu(int cpu)
++{
++ /*
++ * We just need the target to call irq_exit() and re-evaluate
++ * the next tick. The nohz full kick at least implies that.
++ * If needed we can still optimize that later with an
++ * empty IRQ.
++ */
++ if (cpu_is_offline(cpu))
++ return true; /* Don't try to wake offline CPUs. */
++ if (tick_nohz_full_cpu(cpu)) {
++ if (cpu != smp_processor_id() ||
++ tick_nohz_tick_stopped())
++ tick_nohz_full_kick_cpu(cpu);
++ return true;
++ }
++
++ return false;
++}
++
++void wake_up_nohz_cpu(int cpu)
++{
++ if (!wake_up_full_nohz_cpu(cpu))
++ wake_up_idle_cpu(cpu);
++}
++
++static void nohz_csd_func(void *info)
++{
++ struct rq *rq = info;
++ int cpu = cpu_of(rq);
++ unsigned int flags;
++
++ /*
++ * Release the rq::nohz_csd.
++ */
++ flags = atomic_fetch_andnot(NOHZ_KICK_MASK, nohz_flags(cpu));
++ WARN_ON(!(flags & NOHZ_KICK_MASK));
++
++ rq->idle_balance = idle_cpu(cpu);
++ if (rq->idle_balance && !need_resched()) {
++ rq->nohz_idle_balance = flags;
++ raise_softirq_irqoff(SCHED_SOFTIRQ);
++ }
++}
++
++#endif /* CONFIG_NO_HZ_COMMON */
++#endif /* CONFIG_SMP */
++
++static inline void wakeup_preempt(struct rq *rq)
++{
++ if (sched_rq_first_task(rq) != rq->curr)
++ resched_curr(rq);
++}
++
++static __always_inline
++int __task_state_match(struct task_struct *p, unsigned int state)
++{
++ if (READ_ONCE(p->__state) & state)
++ return 1;
++
++ if (READ_ONCE(p->saved_state) & state)
++ return -1;
++
++ return 0;
++}
++
++static __always_inline
++int task_state_match(struct task_struct *p, unsigned int state)
++{
++ /*
++ * Serialize against current_save_and_set_rtlock_wait_state(),
++ * current_restore_rtlock_saved_state(), and __refrigerator().
++ */
++ guard(raw_spinlock_irq)(&p->pi_lock);
++
++ return __task_state_match(p, state);
++}
++
++/*
++ * wait_task_inactive - wait for a thread to unschedule.
++ *
++ * Wait for the thread to block in any of the states set in @match_state.
++ * If it changes, i.e. @p might have woken up, then return zero. When we
++ * succeed in waiting for @p to be off its CPU, we return a positive number
++ * (its total switch count). If a second call a short while later returns the
++ * same number, the caller can be sure that @p has remained unscheduled the
++ * whole time.
++ *
++ * The caller must ensure that the task *will* unschedule sometime soon,
++ * else this function might spin for a *long* time. This function can't
++ * be called with interrupts off, or it may introduce deadlock with
++ * smp_call_function() if an IPI is sent by the same process we are
++ * waiting to become inactive.
++ */
++unsigned long wait_task_inactive(struct task_struct *p, unsigned int match_state)
++{
++ unsigned long flags;
++ int running, queued, match;
++ unsigned long ncsw;
++ struct rq *rq;
++ raw_spinlock_t *lock;
++
++ for (;;) {
++ rq = task_rq(p);
++
++ /*
++ * If the task is actively running on another CPU
++ * still, just relax and busy-wait without holding
++ * any locks.
++ *
++ * NOTE! Since we don't hold any locks, it's not
++ * even sure that "rq" stays as the right runqueue!
++ * But we don't care, since this will return false
++ * if the runqueue has changed and p is actually now
++ * running somewhere else!
++ */
++ while (task_on_cpu(p)) {
++ if (!task_state_match(p, match_state))
++ return 0;
++ cpu_relax();
++ }
++
++ /*
++ * Ok, time to look more closely! We need the rq
++ * lock now, to be *sure*. If we're wrong, we'll
++ * just go back and repeat.
++ */
++ task_access_lock_irqsave(p, &lock, &flags);
++ trace_sched_wait_task(p);
++ running = task_on_cpu(p);
++ queued = p->on_rq;
++ ncsw = 0;
++ if ((match = __task_state_match(p, match_state))) {
++ /*
++ * When matching on p->saved_state, consider this task
++ * still queued so it will wait.
++ */
++ if (match < 0)
++ queued = 1;
++ ncsw = p->nvcsw | LONG_MIN; /* sets MSB */
++ }
++ task_access_unlock_irqrestore(p, lock, &flags);
++
++ /*
++ * If it changed from the expected state, bail out now.
++ */
++ if (unlikely(!ncsw))
++ break;
++
++ /*
++ * Was it really running after all now that we
++ * checked with the proper locks actually held?
++ *
++ * Oops. Go back and try again..
++ */
++ if (unlikely(running)) {
++ cpu_relax();
++ continue;
++ }
++
++ /*
++ * It's not enough that it's not actively running,
++ * it must be off the runqueue _entirely_, and not
++ * preempted!
++ *
++ * So if it was still runnable (but just not actively
++ * running right now), it's preempted, and we should
++ * yield - it could be a while.
++ */
++ if (unlikely(queued)) {
++ ktime_t to = NSEC_PER_SEC / HZ;
++
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ schedule_hrtimeout(&to, HRTIMER_MODE_REL_HARD);
++ continue;
++ }
++
++ /*
++ * Ahh, all good. It wasn't running, and it wasn't
++ * runnable, which means that it will never become
++ * running in the future either. We're all done!
++ */
++ break;
++ }
++
++ return ncsw;
++}
++
++#ifdef CONFIG_SCHED_HRTICK
++/*
++ * Use HR-timers to deliver accurate preemption points.
++ */
++
++static void hrtick_clear(struct rq *rq)
++{
++ if (hrtimer_active(&rq->hrtick_timer))
++ hrtimer_cancel(&rq->hrtick_timer);
++}
++
++/*
++ * High-resolution timer tick.
++ * Runs from hardirq context with interrupts disabled.
++ */
++static enum hrtimer_restart hrtick(struct hrtimer *timer)
++{
++ struct rq *rq = container_of(timer, struct rq, hrtick_timer);
++
++ WARN_ON_ONCE(cpu_of(rq) != smp_processor_id());
++
++ raw_spin_lock(&rq->lock);
++ resched_curr(rq);
++ raw_spin_unlock(&rq->lock);
++
++ return HRTIMER_NORESTART;
++}
++
++/*
++ * Use hrtick when:
++ * - enabled by features
++ * - hrtimer is actually high res
++ */
++static inline int hrtick_enabled(struct rq *rq)
++{
++ /**
++ * Alt schedule FW doesn't support sched_feat yet
++ if (!sched_feat(HRTICK))
++ return 0;
++ */
++ if (!cpu_active(cpu_of(rq)))
++ return 0;
++ return hrtimer_is_hres_active(&rq->hrtick_timer);
++}
++
++#ifdef CONFIG_SMP
++
++static void __hrtick_restart(struct rq *rq)
++{
++ struct hrtimer *timer = &rq->hrtick_timer;
++ ktime_t time = rq->hrtick_time;
++
++ hrtimer_start(timer, time, HRTIMER_MODE_ABS_PINNED_HARD);
++}
++
++/*
++ * called from hardirq (IPI) context
++ */
++static void __hrtick_start(void *arg)
++{
++ struct rq *rq = arg;
++
++ raw_spin_lock(&rq->lock);
++ __hrtick_restart(rq);
++ raw_spin_unlock(&rq->lock);
++}
++
++/*
++ * Called to set the hrtick timer state.
++ *
++ * called with rq->lock held and irqs disabled
++ */
++static inline void hrtick_start(struct rq *rq, u64 delay)
++{
++ struct hrtimer *timer = &rq->hrtick_timer;
++ s64 delta;
++
++ /*
++ * Don't schedule slices shorter than 10000ns, that just
++ * doesn't make sense and can cause timer DoS.
++ */
++ delta = max_t(s64, delay, 10000LL);
++
++ rq->hrtick_time = ktime_add_ns(timer->base->get_time(), delta);
++
++ if (rq == this_rq())
++ __hrtick_restart(rq);
++ else
++ smp_call_function_single_async(cpu_of(rq), &rq->hrtick_csd);
++}
++
++#else
++/*
++ * Called to set the hrtick timer state.
++ *
++ * called with rq->lock held and irqs disabled
++ */
++static inline void hrtick_start(struct rq *rq, u64 delay)
++{
++ /*
++ * Don't schedule slices shorter than 10000ns, that just
++ * doesn't make sense. Rely on vruntime for fairness.
++ */
++ delay = max_t(u64, delay, 10000LL);
++ hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay),
++ HRTIMER_MODE_REL_PINNED_HARD);
++}
++#endif /* CONFIG_SMP */
++
++static void hrtick_rq_init(struct rq *rq)
++{
++#ifdef CONFIG_SMP
++ INIT_CSD(&rq->hrtick_csd, __hrtick_start, rq);
++#endif
++
++ hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
++ rq->hrtick_timer.function = hrtick;
++}
++#else /* CONFIG_SCHED_HRTICK */
++static inline int hrtick_enabled(struct rq *rq)
++{
++ return 0;
++}
++
++static inline void hrtick_clear(struct rq *rq)
++{
++}
++
++static inline void hrtick_rq_init(struct rq *rq)
++{
++}
++#endif /* CONFIG_SCHED_HRTICK */
++
++static inline int __normal_prio(int policy, int rt_prio, int static_prio)
++{
++ return rt_policy(policy) ? (MAX_RT_PRIO - 1 - rt_prio) :
++ static_prio + MAX_PRIORITY_ADJ;
++}
++
++/*
++ * Calculate the expected normal priority: i.e. priority
++ * without taking RT-inheritance into account. Might be
++ * boosted by interactivity modifiers. Changes upon fork,
++ * setprio syscalls, and whenever the interactivity
++ * estimator recalculates.
++ */
++static inline int normal_prio(struct task_struct *p)
++{
++ return __normal_prio(p->policy, p->rt_priority, p->static_prio);
++}
++
++/*
++ * Calculate the current priority, i.e. the priority
++ * taken into account by the scheduler. This value might
++ * be boosted by RT tasks as it will be RT if the task got
++ * RT-boosted. If not then it returns p->normal_prio.
++ */
++static int effective_prio(struct task_struct *p)
++{
++ p->normal_prio = normal_prio(p);
++ /*
++ * If we are RT tasks or we were boosted to RT priority,
++ * keep the priority unchanged. Otherwise, update priority
++ * to the normal priority:
++ */
++ if (!rt_prio(p->prio))
++ return p->normal_prio;
++ return p->prio;
++}
++
++/*
++ * activate_task - move a task to the runqueue.
++ *
++ * Context: rq->lock
++ */
++static void activate_task(struct task_struct *p, struct rq *rq)
++{
++ enqueue_task(p, rq, ENQUEUE_WAKEUP);
++
++ WRITE_ONCE(p->on_rq, TASK_ON_RQ_QUEUED);
++ ASSERT_EXCLUSIVE_WRITER(p->on_rq);
++
++ /*
++ * If in_iowait is set, the code below may not trigger any cpufreq
++ * utilization updates, so do it here explicitly with the IOWAIT flag
++ * passed.
++ */
++ cpufreq_update_util(rq, SCHED_CPUFREQ_IOWAIT * p->in_iowait);
++}
++
++/*
++ * deactivate_task - remove a task from the runqueue.
++ *
++ * Context: rq->lock
++ */
++static inline void deactivate_task(struct task_struct *p, struct rq *rq)
++{
++ WRITE_ONCE(p->on_rq, 0);
++ ASSERT_EXCLUSIVE_WRITER(p->on_rq);
++
++ dequeue_task(p, rq, DEQUEUE_SLEEP);
++
++ cpufreq_update_util(rq, 0);
++}
++
++static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
++{
++#ifdef CONFIG_SMP
++ /*
++ * After ->cpu is set up to a new value, task_access_lock(p, ...) can be
++ * successfully executed on another CPU. We must ensure that updates of
++ * per-task data have been completed by this moment.
++ */
++ smp_wmb();
++
++ WRITE_ONCE(task_thread_info(p)->cpu, cpu);
++#endif
++}
++
++static inline bool is_migration_disabled(struct task_struct *p)
++{
++#ifdef CONFIG_SMP
++ return p->migration_disabled;
++#else
++ return false;
++#endif
++}
++
++#define SCA_CHECK 0x01
++#define SCA_USER 0x08
++
++#ifdef CONFIG_SMP
++
++void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
++{
++#ifdef CONFIG_SCHED_DEBUG
++ unsigned int state = READ_ONCE(p->__state);
++
++ /*
++ * We should never call set_task_cpu() on a blocked task,
++ * ttwu() will sort out the placement.
++ */
++ WARN_ON_ONCE(state != TASK_RUNNING && state != TASK_WAKING && !p->on_rq);
++
++#ifdef CONFIG_LOCKDEP
++ /*
++ * The caller should hold either p->pi_lock or rq->lock, when changing
++ * a task's CPU. ->pi_lock for waking tasks, rq->lock for runnable tasks.
++ *
++ * sched_move_task() holds both and thus holding either pins the cgroup,
++ * see task_group().
++ */
++ WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) ||
++ lockdep_is_held(&task_rq(p)->lock)));
++#endif
++ /*
++ * Clearly, migrating tasks to offline CPUs is a fairly daft thing.
++ */
++ WARN_ON_ONCE(!cpu_online(new_cpu));
++
++ WARN_ON_ONCE(is_migration_disabled(p));
++#endif
++ trace_sched_migrate_task(p, new_cpu);
++
++ if (task_cpu(p) != new_cpu)
++ {
++ rseq_migrate(p);
++ perf_event_task_migrate(p);
++ }
++
++ __set_task_cpu(p, new_cpu);
++}
++
++#define MDF_FORCE_ENABLED 0x80
++
++static void
++__do_set_cpus_ptr(struct task_struct *p, const struct cpumask *new_mask)
++{
++ /*
++ * This here violates the locking rules for affinity, since we're only
++ * supposed to change these variables while holding both rq->lock and
++ * p->pi_lock.
++ *
++ * HOWEVER, it magically works, because ttwu() is the only code that
++ * accesses these variables under p->pi_lock and only does so after
++ * smp_cond_load_acquire(&p->on_cpu, !VAL), and we're in __schedule()
++ * before finish_task().
++ *
++ * XXX do further audits, this smells like something putrid.
++ */
++ SCHED_WARN_ON(!p->on_cpu);
++ p->cpus_ptr = new_mask;
++}
++
++void migrate_disable(void)
++{
++ struct task_struct *p = current;
++ int cpu;
++
++ if (p->migration_disabled) {
++ p->migration_disabled++;
++ return;
++ }
++
++ guard(preempt)();
++ cpu = smp_processor_id();
++ if (cpumask_test_cpu(cpu, &p->cpus_mask)) {
++ cpu_rq(cpu)->nr_pinned++;
++ p->migration_disabled = 1;
++ p->migration_flags &= ~MDF_FORCE_ENABLED;
++
++ /*
++ * Violates locking rules! see comment in __do_set_cpus_ptr().
++ */
++ if (p->cpus_ptr == &p->cpus_mask)
++ __do_set_cpus_ptr(p, cpumask_of(cpu));
++ }
++}
++EXPORT_SYMBOL_GPL(migrate_disable);
++
++void migrate_enable(void)
++{
++ struct task_struct *p = current;
++
++ if (0 == p->migration_disabled)
++ return;
++
++ if (p->migration_disabled > 1) {
++ p->migration_disabled--;
++ return;
++ }
++
++ if (WARN_ON_ONCE(!p->migration_disabled))
++ return;
++
++ /*
++ * Ensure stop_task runs either before or after this, and that
++ * __set_cpus_allowed_ptr(SCA_MIGRATE_ENABLE) doesn't schedule().
++ */
++ guard(preempt)();
++ /*
++ * Assumption: current should be running on allowed cpu
++ */
++ WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &p->cpus_mask));
++ if (p->cpus_ptr != &p->cpus_mask)
++ __do_set_cpus_ptr(p, &p->cpus_mask);
++ /*
++ * Mustn't clear migration_disabled() until cpus_ptr points back at the
++ * regular cpus_mask, otherwise things that race (eg.
++ * select_fallback_rq) get confused.
++ */
++ barrier();
++ p->migration_disabled = 0;
++ this_rq()->nr_pinned--;
++}
++EXPORT_SYMBOL_GPL(migrate_enable);
++
++static inline bool rq_has_pinned_tasks(struct rq *rq)
++{
++ return rq->nr_pinned;
++}
++
++/*
++ * Per-CPU kthreads are allowed to run on !active && online CPUs, see
++ * __set_cpus_allowed_ptr() and select_fallback_rq().
++ */
++static inline bool is_cpu_allowed(struct task_struct *p, int cpu)
++{
++ /* When not in the task's cpumask, no point in looking further. */
++ if (!cpumask_test_cpu(cpu, p->cpus_ptr))
++ return false;
++
++ /* migrate_disabled() must be allowed to finish. */
++ if (is_migration_disabled(p))
++ return cpu_online(cpu);
++
++ /* Non kernel threads are not allowed during either online or offline. */
++ if (!(p->flags & PF_KTHREAD))
++ return cpu_active(cpu) && task_cpu_possible(cpu, p);
++
++ /* KTHREAD_IS_PER_CPU is always allowed. */
++ if (kthread_is_per_cpu(p))
++ return cpu_online(cpu);
++
++ /* Regular kernel threads don't get to stay during offline. */
++ if (cpu_dying(cpu))
++ return false;
++
++ /* But are allowed during online. */
++ return cpu_online(cpu);
++}
++
++/*
++ * This is how migration works:
++ *
++ * 1) we invoke migration_cpu_stop() on the target CPU using
++ * stop_one_cpu().
++ * 2) stopper starts to run (implicitly forcing the migrated thread
++ * off the CPU)
++ * 3) it checks whether the migrated task is still in the wrong runqueue.
++ * 4) if it's in the wrong runqueue then the migration thread removes
++ * it and puts it into the right queue.
++ * 5) stopper completes and stop_one_cpu() returns and the migration
++ * is done.
++ */
++
++/*
++ * move_queued_task - move a queued task to new rq.
++ *
++ * Returns (locked) new rq. Old rq's lock is released.
++ */
++static struct rq *move_queued_task(struct rq *rq, struct task_struct *p, int
++ new_cpu)
++{
++ int src_cpu;
++
++ lockdep_assert_held(&rq->lock);
++
++ src_cpu = cpu_of(rq);
++ WRITE_ONCE(p->on_rq, TASK_ON_RQ_MIGRATING);
++ dequeue_task(p, rq, 0);
++ set_task_cpu(p, new_cpu);
++ raw_spin_unlock(&rq->lock);
++
++ rq = cpu_rq(new_cpu);
++
++ raw_spin_lock(&rq->lock);
++ WARN_ON_ONCE(task_cpu(p) != new_cpu);
++
++ sched_mm_cid_migrate_to(rq, p, src_cpu);
++
++ sched_task_sanity_check(p, rq);
++ enqueue_task(p, rq, 0);
++ WRITE_ONCE(p->on_rq, TASK_ON_RQ_QUEUED);
++ wakeup_preempt(rq);
++
++ return rq;
++}
++
++struct migration_arg {
++ struct task_struct *task;
++ int dest_cpu;
++};
++
++/*
++ * Move (not current) task off this CPU, onto the destination CPU. We're doing
++ * this because either it can't run here any more (set_cpus_allowed()
++ * away from this CPU, or CPU going down), or because we're
++ * attempting to rebalance this task on exec (sched_exec).
++ *
++ * So we race with normal scheduler movements, but that's OK, as long
++ * as the task is no longer on this CPU.
++ */
++static struct rq *__migrate_task(struct rq *rq, struct task_struct *p, int
++ dest_cpu)
++{
++ /* Affinity changed (again). */
++ if (!is_cpu_allowed(p, dest_cpu))
++ return rq;
++
++ return move_queued_task(rq, p, dest_cpu);
++}
++
++/*
++ * migration_cpu_stop - this will be executed by a highprio stopper thread
++ * and performs thread migration by bumping thread off CPU then
++ * 'pushing' onto another runqueue.
++ */
++static int migration_cpu_stop(void *data)
++{
++ struct migration_arg *arg = data;
++ struct task_struct *p = arg->task;
++ struct rq *rq = this_rq();
++ unsigned long flags;
++
++ /*
++ * The original target CPU might have gone down and we might
++ * be on another CPU but it doesn't matter.
++ */
++ local_irq_save(flags);
++ /*
++ * We need to explicitly wake pending tasks before running
++ * __migrate_task() such that we will not miss enforcing cpus_ptr
++ * during wakeups, see set_cpus_allowed_ptr()'s TASK_WAKING test.
++ */
++ flush_smp_call_function_queue();
++
++ raw_spin_lock(&p->pi_lock);
++ raw_spin_lock(&rq->lock);
++ /*
++ * If task_rq(p) != rq, it cannot be migrated here, because we're
++ * holding rq->lock, if p->on_rq == 0 it cannot get enqueued because
++ * we're holding p->pi_lock.
++ */
++ if (task_rq(p) == rq && task_on_rq_queued(p)) {
++ update_rq_clock(rq);
++ rq = __migrate_task(rq, p, arg->dest_cpu);
++ }
++ raw_spin_unlock(&rq->lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++
++ return 0;
++}
++
++static inline void
++set_cpus_allowed_common(struct task_struct *p, struct affinity_context *ctx)
++{
++ cpumask_copy(&p->cpus_mask, ctx->new_mask);
++ p->nr_cpus_allowed = cpumask_weight(ctx->new_mask);
++
++ /*
++ * Swap in a new user_cpus_ptr if SCA_USER flag set
++ */
++ if (ctx->flags & SCA_USER)
++ swap(p->user_cpus_ptr, ctx->user_mask);
++}
++
++static void
++__do_set_cpus_allowed(struct task_struct *p, struct affinity_context *ctx)
++{
++ lockdep_assert_held(&p->pi_lock);
++ set_cpus_allowed_common(p, ctx);
++}
++
++/*
++ * Used for kthread_bind() and select_fallback_rq(), in both cases the user
++ * affinity (if any) should be destroyed too.
++ */
++void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
++{
++ struct affinity_context ac = {
++ .new_mask = new_mask,
++ .user_mask = NULL,
++ .flags = SCA_USER, /* clear the user requested mask */
++ };
++ union cpumask_rcuhead {
++ cpumask_t cpumask;
++ struct rcu_head rcu;
++ };
++
++ __do_set_cpus_allowed(p, &ac);
++
++ /*
++ * Because this is called with p->pi_lock held, it is not possible
++ * to use kfree() here (when PREEMPT_RT=y), therefore punt to using
++ * kfree_rcu().
++ */
++ kfree_rcu((union cpumask_rcuhead *)ac.user_mask, rcu);
++}
++
++static cpumask_t *alloc_user_cpus_ptr(int node)
++{
++ /*
++ * See do_set_cpus_allowed() above for the rcu_head usage.
++ */
++ int size = max_t(int, cpumask_size(), sizeof(struct rcu_head));
++
++ return kmalloc_node(size, GFP_KERNEL, node);
++}
++
++int dup_user_cpus_ptr(struct task_struct *dst, struct task_struct *src,
++ int node)
++{
++ cpumask_t *user_mask;
++ unsigned long flags;
++
++ /*
++ * Always clear dst->user_cpus_ptr first as their user_cpus_ptr's
++ * may differ by now due to racing.
++ */
++ dst->user_cpus_ptr = NULL;
++
++ /*
++ * This check is racy and losing the race is a valid situation.
++ * It is not worth the extra overhead of taking the pi_lock on
++ * every fork/clone.
++ */
++ if (data_race(!src->user_cpus_ptr))
++ return 0;
++
++ user_mask = alloc_user_cpus_ptr(node);
++ if (!user_mask)
++ return -ENOMEM;
++
++ /*
++ * Use pi_lock to protect content of user_cpus_ptr
++ *
++ * Though unlikely, user_cpus_ptr can be reset to NULL by a concurrent
++ * do_set_cpus_allowed().
++ */
++ raw_spin_lock_irqsave(&src->pi_lock, flags);
++ if (src->user_cpus_ptr) {
++ swap(dst->user_cpus_ptr, user_mask);
++ cpumask_copy(dst->user_cpus_ptr, src->user_cpus_ptr);
++ }
++ raw_spin_unlock_irqrestore(&src->pi_lock, flags);
++
++ if (unlikely(user_mask))
++ kfree(user_mask);
++
++ return 0;
++}
++
++static inline struct cpumask *clear_user_cpus_ptr(struct task_struct *p)
++{
++ struct cpumask *user_mask = NULL;
++
++ swap(p->user_cpus_ptr, user_mask);
++
++ return user_mask;
++}
++
++void release_user_cpus_ptr(struct task_struct *p)
++{
++ kfree(clear_user_cpus_ptr(p));
++}
++
++#endif
++
++/**
++ * task_curr - is this task currently executing on a CPU?
++ * @p: the task in question.
++ *
++ * Return: 1 if the task is currently executing. 0 otherwise.
++ */
++inline int task_curr(const struct task_struct *p)
++{
++ return cpu_curr(task_cpu(p)) == p;
++}
++
++#ifdef CONFIG_SMP
++/***
++ * kick_process - kick a running thread to enter/exit the kernel
++ * @p: the to-be-kicked thread
++ *
++ * Cause a process which is running on another CPU to enter
++ * kernel-mode, without any delay. (to get signals handled.)
++ *
++ * NOTE: this function doesn't have to take the runqueue lock,
++ * because all it wants to ensure is that the remote task enters
++ * the kernel. If the IPI races and the task has been migrated
++ * to another CPU then no harm is done and the purpose has been
++ * achieved as well.
++ */
++void kick_process(struct task_struct *p)
++{
++ guard(preempt)();
++ int cpu = task_cpu(p);
++
++ if ((cpu != smp_processor_id()) && task_curr(p))
++ smp_send_reschedule(cpu);
++}
++EXPORT_SYMBOL_GPL(kick_process);
++
++/*
++ * ->cpus_ptr is protected by both rq->lock and p->pi_lock
++ *
++ * A few notes on cpu_active vs cpu_online:
++ *
++ * - cpu_active must be a subset of cpu_online
++ *
++ * - on CPU-up we allow per-CPU kthreads on the online && !active CPU,
++ * see __set_cpus_allowed_ptr(). At this point the newly online
++ * CPU isn't yet part of the sched domains, and balancing will not
++ * see it.
++ *
++ * - on cpu-down we clear cpu_active() to mask the sched domains and
++ * avoid the load balancer to place new tasks on the to be removed
++ * CPU. Existing tasks will remain running there and will be taken
++ * off.
++ *
++ * This means that fallback selection must not select !active CPUs.
++ * And can assume that any active CPU must be online. Conversely
++ * select_task_rq() below may allow selection of !active CPUs in order
++ * to satisfy the above rules.
++ */
++static int select_fallback_rq(int cpu, struct task_struct *p)
++{
++ int nid = cpu_to_node(cpu);
++ const struct cpumask *nodemask = NULL;
++ enum { cpuset, possible, fail } state = cpuset;
++ int dest_cpu;
++
++ /*
++ * If the node that the CPU is on has been offlined, cpu_to_node()
++ * will return -1. There is no CPU on the node, and we should
++ * select the CPU on the other node.
++ */
++ if (nid != -1) {
++ nodemask = cpumask_of_node(nid);
++
++ /* Look for allowed, online CPU in same node. */
++ for_each_cpu(dest_cpu, nodemask) {
++ if (is_cpu_allowed(p, dest_cpu))
++ return dest_cpu;
++ }
++ }
++
++ for (;;) {
++ /* Any allowed, online CPU? */
++ for_each_cpu(dest_cpu, p->cpus_ptr) {
++ if (!is_cpu_allowed(p, dest_cpu))
++ continue;
++ goto out;
++ }
++
++ /* No more Mr. Nice Guy. */
++ switch (state) {
++ case cpuset:
++ if (cpuset_cpus_allowed_fallback(p)) {
++ state = possible;
++ break;
++ }
++ fallthrough;
++ case possible:
++ /*
++ * XXX When called from select_task_rq() we only
++ * hold p->pi_lock and again violate locking order.
++ *
++ * More yuck to audit.
++ */
++ do_set_cpus_allowed(p, task_cpu_possible_mask(p));
++ state = fail;
++ break;
++
++ case fail:
++ BUG();
++ break;
++ }
++ }
++
++out:
++ if (state != cpuset) {
++ /*
++ * Don't tell them about moving exiting tasks or
++ * kernel threads (both mm NULL), since they never
++ * leave kernel.
++ */
++ if (p->mm && printk_ratelimit()) {
++ printk_deferred("process %d (%s) no longer affine to cpu%d\n",
++ task_pid_nr(p), p->comm, cpu);
++ }
++ }
++
++ return dest_cpu;
++}
++
++static inline void
++sched_preempt_mask_flush(cpumask_t *mask, int prio, int ref)
++{
++ int cpu;
++
++ cpumask_copy(mask, sched_preempt_mask + ref);
++ if (prio < ref) {
++ for_each_clear_bit(cpu, cpumask_bits(mask), nr_cpumask_bits) {
++ if (prio < cpu_rq(cpu)->prio)
++ cpumask_set_cpu(cpu, mask);
++ }
++ } else {
++ for_each_cpu_andnot(cpu, mask, sched_idle_mask) {
++ if (prio >= cpu_rq(cpu)->prio)
++ cpumask_clear_cpu(cpu, mask);
++ }
++ }
++}
++
++static inline int
++preempt_mask_check(cpumask_t *preempt_mask, cpumask_t *allow_mask, int prio)
++{
++ cpumask_t *mask = sched_preempt_mask + prio;
++ int pr = atomic_read(&sched_prio_record);
++
++ if (pr != prio && SCHED_QUEUE_BITS - 1 != prio) {
++ sched_preempt_mask_flush(mask, prio, pr);
++ atomic_set(&sched_prio_record, prio);
++ }
++
++ return cpumask_and(preempt_mask, allow_mask, mask);
++}
++
++static inline int select_task_rq(struct task_struct *p)
++{
++ cpumask_t allow_mask, mask;
++
++ if (unlikely(!cpumask_and(&allow_mask, p->cpus_ptr, cpu_active_mask)))
++ return select_fallback_rq(task_cpu(p), p);
++
++ if (
++#ifdef CONFIG_SCHED_SMT
++ cpumask_and(&mask, &allow_mask, sched_sg_idle_mask) ||
++#endif
++ cpumask_and(&mask, &allow_mask, sched_idle_mask) ||
++ preempt_mask_check(&mask, &allow_mask, task_sched_prio(p)))
++ return best_mask_cpu(task_cpu(p), &mask);
++
++ return best_mask_cpu(task_cpu(p), &allow_mask);
++}
++
++void sched_set_stop_task(int cpu, struct task_struct *stop)
++{
++ static struct lock_class_key stop_pi_lock;
++ struct sched_param stop_param = { .sched_priority = STOP_PRIO };
++ struct sched_param start_param = { .sched_priority = 0 };
++ struct task_struct *old_stop = cpu_rq(cpu)->stop;
++
++ if (stop) {
++ /*
++ * Make it appear like a SCHED_FIFO task, its something
++ * userspace knows about and won't get confused about.
++ *
++ * Also, it will make PI more or less work without too
++ * much confusion -- but then, stop work should not
++ * rely on PI working anyway.
++ */
++ sched_setscheduler_nocheck(stop, SCHED_FIFO, &stop_param);
++
++ /*
++ * The PI code calls rt_mutex_setprio() with ->pi_lock held to
++ * adjust the effective priority of a task. As a result,
++ * rt_mutex_setprio() can trigger (RT) balancing operations,
++ * which can then trigger wakeups of the stop thread to push
++ * around the current task.
++ *
++ * The stop task itself will never be part of the PI-chain, it
++ * never blocks, therefore that ->pi_lock recursion is safe.
++ * Tell lockdep about this by placing the stop->pi_lock in its
++ * own class.
++ */
++ lockdep_set_class(&stop->pi_lock, &stop_pi_lock);
++ }
++
++ cpu_rq(cpu)->stop = stop;
++
++ if (old_stop) {
++ /*
++ * Reset it back to a normal scheduling policy so that
++ * it can die in pieces.
++ */
++ sched_setscheduler_nocheck(old_stop, SCHED_NORMAL, &start_param);
++ }
++}
++
++static int affine_move_task(struct rq *rq, struct task_struct *p, int dest_cpu,
++ raw_spinlock_t *lock, unsigned long irq_flags)
++ __releases(rq->lock)
++ __releases(p->pi_lock)
++{
++ /* Can the task run on the task's current CPU? If so, we're done */
++ if (!cpumask_test_cpu(task_cpu(p), &p->cpus_mask)) {
++ if (p->migration_disabled) {
++ if (likely(p->cpus_ptr != &p->cpus_mask))
++ __do_set_cpus_ptr(p, &p->cpus_mask);
++ p->migration_disabled = 0;
++ p->migration_flags |= MDF_FORCE_ENABLED;
++ /* When p is migrate_disabled, rq->lock should be held */
++ rq->nr_pinned--;
++ }
++
++ if (task_on_cpu(p) || READ_ONCE(p->__state) == TASK_WAKING) {
++ struct migration_arg arg = { p, dest_cpu };
++
++ /* Need help from migration thread: drop lock and wait. */
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
++ stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg);
++ return 0;
++ }
++ if (task_on_rq_queued(p)) {
++ /*
++ * OK, since we're going to drop the lock immediately
++ * afterwards anyway.
++ */
++ update_rq_clock(rq);
++ rq = move_queued_task(rq, p, dest_cpu);
++ lock = &rq->lock;
++ }
++ }
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
++ return 0;
++}
++
++static int __set_cpus_allowed_ptr_locked(struct task_struct *p,
++ struct affinity_context *ctx,
++ struct rq *rq,
++ raw_spinlock_t *lock,
++ unsigned long irq_flags)
++{
++ const struct cpumask *cpu_allowed_mask = task_cpu_possible_mask(p);
++ const struct cpumask *cpu_valid_mask = cpu_active_mask;
++ bool kthread = p->flags & PF_KTHREAD;
++ int dest_cpu;
++ int ret = 0;
++
++ if (kthread || is_migration_disabled(p)) {
++ /*
++ * Kernel threads are allowed on online && !active CPUs,
++ * however, during cpu-hot-unplug, even these might get pushed
++ * away if not KTHREAD_IS_PER_CPU.
++ *
++ * Specifically, migration_disabled() tasks must not fail the
++ * cpumask_any_and_distribute() pick below, esp. so on
++ * SCA_MIGRATE_ENABLE, otherwise we'll not call
++ * set_cpus_allowed_common() and actually reset p->cpus_ptr.
++ */
++ cpu_valid_mask = cpu_online_mask;
++ }
++
++ if (!kthread && !cpumask_subset(ctx->new_mask, cpu_allowed_mask)) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ /*
++ * Must re-check here, to close a race against __kthread_bind(),
++ * sched_setaffinity() is not guaranteed to observe the flag.
++ */
++ if ((ctx->flags & SCA_CHECK) && (p->flags & PF_NO_SETAFFINITY)) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ if (cpumask_equal(&p->cpus_mask, ctx->new_mask))
++ goto out;
++
++ dest_cpu = cpumask_any_and(cpu_valid_mask, ctx->new_mask);
++ if (dest_cpu >= nr_cpu_ids) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ __do_set_cpus_allowed(p, ctx);
++
++ return affine_move_task(rq, p, dest_cpu, lock, irq_flags);
++
++out:
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
++
++ return ret;
++}
++
++/*
++ * Change a given task's CPU affinity. Migrate the thread to a
++ * is removed from the allowed bitmask.
++ *
++ * NOTE: the caller must have a valid reference to the task, the
++ * task must not exit() & deallocate itself prematurely. The
++ * call is not atomic; no spinlocks may be held.
++ */
++static int __set_cpus_allowed_ptr(struct task_struct *p,
++ struct affinity_context *ctx)
++{
++ unsigned long irq_flags;
++ struct rq *rq;
++ raw_spinlock_t *lock;
++
++ raw_spin_lock_irqsave(&p->pi_lock, irq_flags);
++ rq = __task_access_lock(p, &lock);
++ /*
++ * Masking should be skipped if SCA_USER or any of the SCA_MIGRATE_*
++ * flags are set.
++ */
++ if (p->user_cpus_ptr &&
++ !(ctx->flags & SCA_USER) &&
++ cpumask_and(rq->scratch_mask, ctx->new_mask, p->user_cpus_ptr))
++ ctx->new_mask = rq->scratch_mask;
++
++
++ return __set_cpus_allowed_ptr_locked(p, ctx, rq, lock, irq_flags);
++}
++
++int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
++{
++ struct affinity_context ac = {
++ .new_mask = new_mask,
++ .flags = 0,
++ };
++
++ return __set_cpus_allowed_ptr(p, &ac);
++}
++EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr);
++
++/*
++ * Change a given task's CPU affinity to the intersection of its current
++ * affinity mask and @subset_mask, writing the resulting mask to @new_mask.
++ * If user_cpus_ptr is defined, use it as the basis for restricting CPU
++ * affinity or use cpu_online_mask instead.
++ *
++ * If the resulting mask is empty, leave the affinity unchanged and return
++ * -EINVAL.
++ */
++static int restrict_cpus_allowed_ptr(struct task_struct *p,
++ struct cpumask *new_mask,
++ const struct cpumask *subset_mask)
++{
++ struct affinity_context ac = {
++ .new_mask = new_mask,
++ .flags = 0,
++ };
++ unsigned long irq_flags;
++ raw_spinlock_t *lock;
++ struct rq *rq;
++ int err;
++
++ raw_spin_lock_irqsave(&p->pi_lock, irq_flags);
++ rq = __task_access_lock(p, &lock);
++
++ if (!cpumask_and(new_mask, task_user_cpus(p), subset_mask)) {
++ err = -EINVAL;
++ goto err_unlock;
++ }
++
++ return __set_cpus_allowed_ptr_locked(p, &ac, rq, lock, irq_flags);
++
++err_unlock:
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
++ return err;
++}
++
++/*
++ * Restrict the CPU affinity of task @p so that it is a subset of
++ * task_cpu_possible_mask() and point @p->user_cpus_ptr to a copy of the
++ * old affinity mask. If the resulting mask is empty, we warn and walk
++ * up the cpuset hierarchy until we find a suitable mask.
++ */
++void force_compatible_cpus_allowed_ptr(struct task_struct *p)
++{
++ cpumask_var_t new_mask;
++ const struct cpumask *override_mask = task_cpu_possible_mask(p);
++
++ alloc_cpumask_var(&new_mask, GFP_KERNEL);
++
++ /*
++ * __migrate_task() can fail silently in the face of concurrent
++ * offlining of the chosen destination CPU, so take the hotplug
++ * lock to ensure that the migration succeeds.
++ */
++ cpus_read_lock();
++ if (!cpumask_available(new_mask))
++ goto out_set_mask;
++
++ if (!restrict_cpus_allowed_ptr(p, new_mask, override_mask))
++ goto out_free_mask;
++
++ /*
++ * We failed to find a valid subset of the affinity mask for the
++ * task, so override it based on its cpuset hierarchy.
++ */
++ cpuset_cpus_allowed(p, new_mask);
++ override_mask = new_mask;
++
++out_set_mask:
++ if (printk_ratelimit()) {
++ printk_deferred("Overriding affinity for process %d (%s) to CPUs %*pbl\n",
++ task_pid_nr(p), p->comm,
++ cpumask_pr_args(override_mask));
++ }
++
++ WARN_ON(set_cpus_allowed_ptr(p, override_mask));
++out_free_mask:
++ cpus_read_unlock();
++ free_cpumask_var(new_mask);
++}
++
++static int
++__sched_setaffinity(struct task_struct *p, struct affinity_context *ctx);
++
++/*
++ * Restore the affinity of a task @p which was previously restricted by a
++ * call to force_compatible_cpus_allowed_ptr().
++ *
++ * It is the caller's responsibility to serialise this with any calls to
++ * force_compatible_cpus_allowed_ptr(@p).
++ */
++void relax_compatible_cpus_allowed_ptr(struct task_struct *p)
++{
++ struct affinity_context ac = {
++ .new_mask = task_user_cpus(p),
++ .flags = 0,
++ };
++ int ret;
++
++ /*
++ * Try to restore the old affinity mask with __sched_setaffinity().
++ * Cpuset masking will be done there too.
++ */
++ ret = __sched_setaffinity(p, &ac);
++ WARN_ON_ONCE(ret);
++}
++
++#else /* CONFIG_SMP */
++
++static inline int select_task_rq(struct task_struct *p)
++{
++ return 0;
++}
++
++static inline int
++__set_cpus_allowed_ptr(struct task_struct *p,
++ struct affinity_context *ctx)
++{
++ return set_cpus_allowed_ptr(p, ctx->new_mask);
++}
++
++static inline bool rq_has_pinned_tasks(struct rq *rq)
++{
++ return false;
++}
++
++static inline cpumask_t *alloc_user_cpus_ptr(int node)
++{
++ return NULL;
++}
++
++#endif /* !CONFIG_SMP */
++
++static void
++ttwu_stat(struct task_struct *p, int cpu, int wake_flags)
++{
++ struct rq *rq;
++
++ if (!schedstat_enabled())
++ return;
++
++ rq = this_rq();
++
++#ifdef CONFIG_SMP
++ if (cpu == rq->cpu) {
++ __schedstat_inc(rq->ttwu_local);
++ __schedstat_inc(p->stats.nr_wakeups_local);
++ } else {
++ /** Alt schedule FW ToDo:
++ * How to do ttwu_wake_remote
++ */
++ }
++#endif /* CONFIG_SMP */
++
++ __schedstat_inc(rq->ttwu_count);
++ __schedstat_inc(p->stats.nr_wakeups);
++}
++
++/*
++ * Mark the task runnable.
++ */
++static inline void ttwu_do_wakeup(struct task_struct *p)
++{
++ WRITE_ONCE(p->__state, TASK_RUNNING);
++ trace_sched_wakeup(p);
++}
++
++static inline void
++ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags)
++{
++ if (p->sched_contributes_to_load)
++ rq->nr_uninterruptible--;
++
++ if (
++#ifdef CONFIG_SMP
++ !(wake_flags & WF_MIGRATED) &&
++#endif
++ p->in_iowait) {
++ delayacct_blkio_end(p);
++ atomic_dec(&task_rq(p)->nr_iowait);
++ }
++
++ activate_task(p, rq);
++ wakeup_preempt(rq);
++
++ ttwu_do_wakeup(p);
++}
++
++/*
++ * Consider @p being inside a wait loop:
++ *
++ * for (;;) {
++ * set_current_state(TASK_UNINTERRUPTIBLE);
++ *
++ * if (CONDITION)
++ * break;
++ *
++ * schedule();
++ * }
++ * __set_current_state(TASK_RUNNING);
++ *
++ * between set_current_state() and schedule(). In this case @p is still
++ * runnable, so all that needs doing is change p->state back to TASK_RUNNING in
++ * an atomic manner.
++ *
++ * By taking task_rq(p)->lock we serialize against schedule(), if @p->on_rq
++ * then schedule() must still happen and p->state can be changed to
++ * TASK_RUNNING. Otherwise we lost the race, schedule() has happened, and we
++ * need to do a full wakeup with enqueue.
++ *
++ * Returns: %true when the wakeup is done,
++ * %false otherwise.
++ */
++static int ttwu_runnable(struct task_struct *p, int wake_flags)
++{
++ struct rq *rq;
++ raw_spinlock_t *lock;
++ int ret = 0;
++
++ rq = __task_access_lock(p, &lock);
++ if (task_on_rq_queued(p)) {
++ if (!task_on_cpu(p)) {
++ /*
++ * When on_rq && !on_cpu the task is preempted, see if
++ * it should preempt the task that is current now.
++ */
++ update_rq_clock(rq);
++ wakeup_preempt(rq);
++ }
++ ttwu_do_wakeup(p);
++ ret = 1;
++ }
++ __task_access_unlock(p, lock);
++
++ return ret;
++}
++
++#ifdef CONFIG_SMP
++void sched_ttwu_pending(void *arg)
++{
++ struct llist_node *llist = arg;
++ struct rq *rq = this_rq();
++ struct task_struct *p, *t;
++ struct rq_flags rf;
++
++ if (!llist)
++ return;
++
++ rq_lock_irqsave(rq, &rf);
++ update_rq_clock(rq);
++
++ llist_for_each_entry_safe(p, t, llist, wake_entry.llist) {
++ if (WARN_ON_ONCE(p->on_cpu))
++ smp_cond_load_acquire(&p->on_cpu, !VAL);
++
++ if (WARN_ON_ONCE(task_cpu(p) != cpu_of(rq)))
++ set_task_cpu(p, cpu_of(rq));
++
++ ttwu_do_activate(rq, p, p->sched_remote_wakeup ? WF_MIGRATED : 0);
++ }
++
++ /*
++ * Must be after enqueueing at least once task such that
++ * idle_cpu() does not observe a false-negative -- if it does,
++ * it is possible for select_idle_siblings() to stack a number
++ * of tasks on this CPU during that window.
++ *
++ * It is ok to clear ttwu_pending when another task pending.
++ * We will receive IPI after local irq enabled and then enqueue it.
++ * Since now nr_running > 0, idle_cpu() will always get correct result.
++ */
++ WRITE_ONCE(rq->ttwu_pending, 0);
++ rq_unlock_irqrestore(rq, &rf);
++}
++
++/*
++ * Prepare the scene for sending an IPI for a remote smp_call
++ *
++ * Returns true if the caller can proceed with sending the IPI.
++ * Returns false otherwise.
++ */
++bool call_function_single_prep_ipi(int cpu)
++{
++ if (set_nr_if_polling(cpu_rq(cpu)->idle)) {
++ trace_sched_wake_idle_without_ipi(cpu);
++ return false;
++ }
++
++ return true;
++}
++
++/*
++ * Queue a task on the target CPUs wake_list and wake the CPU via IPI if
++ * necessary. The wakee CPU on receipt of the IPI will queue the task
++ * via sched_ttwu_wakeup() for activation so the wakee incurs the cost
++ * of the wakeup instead of the waker.
++ */
++static void __ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ p->sched_remote_wakeup = !!(wake_flags & WF_MIGRATED);
++
++ WRITE_ONCE(rq->ttwu_pending, 1);
++ __smp_call_single_queue(cpu, &p->wake_entry.llist);
++}
++
++static inline bool ttwu_queue_cond(struct task_struct *p, int cpu)
++{
++ /*
++ * Do not complicate things with the async wake_list while the CPU is
++ * in hotplug state.
++ */
++ if (!cpu_active(cpu))
++ return false;
++
++ /* Ensure the task will still be allowed to run on the CPU. */
++ if (!cpumask_test_cpu(cpu, p->cpus_ptr))
++ return false;
++
++ /*
++ * If the CPU does not share cache, then queue the task on the
++ * remote rqs wakelist to avoid accessing remote data.
++ */
++ if (!cpus_share_cache(smp_processor_id(), cpu))
++ return true;
++
++ if (cpu == smp_processor_id())
++ return false;
++
++ /*
++ * If the wakee cpu is idle, or the task is descheduling and the
++ * only running task on the CPU, then use the wakelist to offload
++ * the task activation to the idle (or soon-to-be-idle) CPU as
++ * the current CPU is likely busy. nr_running is checked to
++ * avoid unnecessary task stacking.
++ *
++ * Note that we can only get here with (wakee) p->on_rq=0,
++ * p->on_cpu can be whatever, we've done the dequeue, so
++ * the wakee has been accounted out of ->nr_running.
++ */
++ if (!cpu_rq(cpu)->nr_running)
++ return true;
++
++ return false;
++}
++
++static bool ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
++{
++ if (__is_defined(ALT_SCHED_TTWU_QUEUE) && ttwu_queue_cond(p, cpu)) {
++ sched_clock_cpu(cpu); /* Sync clocks across CPUs */
++ __ttwu_queue_wakelist(p, cpu, wake_flags);
++ return true;
++ }
++
++ return false;
++}
++
++void wake_up_if_idle(int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ guard(rcu)();
++ if (is_idle_task(rcu_dereference(rq->curr))) {
++ guard(raw_spinlock_irqsave)(&rq->lock);
++ if (is_idle_task(rq->curr))
++ resched_curr(rq);
++ }
++}
++
++bool cpus_share_cache(int this_cpu, int that_cpu)
++{
++ if (this_cpu == that_cpu)
++ return true;
++
++ return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu);
++}
++#else /* !CONFIG_SMP */
++
++static inline bool ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
++{
++ return false;
++}
++
++#endif /* CONFIG_SMP */
++
++static inline void ttwu_queue(struct task_struct *p, int cpu, int wake_flags)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ if (ttwu_queue_wakelist(p, cpu, wake_flags))
++ return;
++
++ raw_spin_lock(&rq->lock);
++ update_rq_clock(rq);
++ ttwu_do_activate(rq, p, wake_flags);
++ raw_spin_unlock(&rq->lock);
++}
++
++/*
++ * Invoked from try_to_wake_up() to check whether the task can be woken up.
++ *
++ * The caller holds p::pi_lock if p != current or has preemption
++ * disabled when p == current.
++ *
++ * The rules of saved_state:
++ *
++ * The related locking code always holds p::pi_lock when updating
++ * p::saved_state, which means the code is fully serialized in both cases.
++ *
++ * For PREEMPT_RT, the lock wait and lock wakeups happen via TASK_RTLOCK_WAIT.
++ * No other bits set. This allows to distinguish all wakeup scenarios.
++ *
++ * For FREEZER, the wakeup happens via TASK_FROZEN. No other bits set. This
++ * allows us to prevent early wakeup of tasks before they can be run on
++ * asymmetric ISA architectures (eg ARMv9).
++ */
++static __always_inline
++bool ttwu_state_match(struct task_struct *p, unsigned int state, int *success)
++{
++ int match;
++
++ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT)) {
++ WARN_ON_ONCE((state & TASK_RTLOCK_WAIT) &&
++ state != TASK_RTLOCK_WAIT);
++ }
++
++ *success = !!(match = __task_state_match(p, state));
++
++ /*
++ * Saved state preserves the task state across blocking on
++ * an RT lock or TASK_FREEZABLE tasks. If the state matches,
++ * set p::saved_state to TASK_RUNNING, but do not wake the task
++ * because it waits for a lock wakeup or __thaw_task(). Also
++ * indicate success because from the regular waker's point of
++ * view this has succeeded.
++ *
++ * After acquiring the lock the task will restore p::__state
++ * from p::saved_state which ensures that the regular
++ * wakeup is not lost. The restore will also set
++ * p::saved_state to TASK_RUNNING so any further tests will
++ * not result in false positives vs. @success
++ */
++ if (match < 0)
++ p->saved_state = TASK_RUNNING;
++
++ return match > 0;
++}
++
++/*
++ * Notes on Program-Order guarantees on SMP systems.
++ *
++ * MIGRATION
++ *
++ * The basic program-order guarantee on SMP systems is that when a task [t]
++ * migrates, all its activity on its old CPU [c0] happens-before any subsequent
++ * execution on its new CPU [c1].
++ *
++ * For migration (of runnable tasks) this is provided by the following means:
++ *
++ * A) UNLOCK of the rq(c0)->lock scheduling out task t
++ * B) migration for t is required to synchronize *both* rq(c0)->lock and
++ * rq(c1)->lock (if not at the same time, then in that order).
++ * C) LOCK of the rq(c1)->lock scheduling in task
++ *
++ * Transitivity guarantees that B happens after A and C after B.
++ * Note: we only require RCpc transitivity.
++ * Note: the CPU doing B need not be c0 or c1
++ *
++ * Example:
++ *
++ * CPU0 CPU1 CPU2
++ *
++ * LOCK rq(0)->lock
++ * sched-out X
++ * sched-in Y
++ * UNLOCK rq(0)->lock
++ *
++ * LOCK rq(0)->lock // orders against CPU0
++ * dequeue X
++ * UNLOCK rq(0)->lock
++ *
++ * LOCK rq(1)->lock
++ * enqueue X
++ * UNLOCK rq(1)->lock
++ *
++ * LOCK rq(1)->lock // orders against CPU2
++ * sched-out Z
++ * sched-in X
++ * UNLOCK rq(1)->lock
++ *
++ *
++ * BLOCKING -- aka. SLEEP + WAKEUP
++ *
++ * For blocking we (obviously) need to provide the same guarantee as for
++ * migration. However the means are completely different as there is no lock
++ * chain to provide order. Instead we do:
++ *
++ * 1) smp_store_release(X->on_cpu, 0) -- finish_task()
++ * 2) smp_cond_load_acquire(!X->on_cpu) -- try_to_wake_up()
++ *
++ * Example:
++ *
++ * CPU0 (schedule) CPU1 (try_to_wake_up) CPU2 (schedule)
++ *
++ * LOCK rq(0)->lock LOCK X->pi_lock
++ * dequeue X
++ * sched-out X
++ * smp_store_release(X->on_cpu, 0);
++ *
++ * smp_cond_load_acquire(&X->on_cpu, !VAL);
++ * X->state = WAKING
++ * set_task_cpu(X,2)
++ *
++ * LOCK rq(2)->lock
++ * enqueue X
++ * X->state = RUNNING
++ * UNLOCK rq(2)->lock
++ *
++ * LOCK rq(2)->lock // orders against CPU1
++ * sched-out Z
++ * sched-in X
++ * UNLOCK rq(2)->lock
++ *
++ * UNLOCK X->pi_lock
++ * UNLOCK rq(0)->lock
++ *
++ *
++ * However; for wakeups there is a second guarantee we must provide, namely we
++ * must observe the state that lead to our wakeup. That is, not only must our
++ * task observe its own prior state, it must also observe the stores prior to
++ * its wakeup.
++ *
++ * This means that any means of doing remote wakeups must order the CPU doing
++ * the wakeup against the CPU the task is going to end up running on. This,
++ * however, is already required for the regular Program-Order guarantee above,
++ * since the waking CPU is the one issueing the ACQUIRE (smp_cond_load_acquire).
++ *
++ */
++
++/**
++ * try_to_wake_up - wake up a thread
++ * @p: the thread to be awakened
++ * @state: the mask of task states that can be woken
++ * @wake_flags: wake modifier flags (WF_*)
++ *
++ * Conceptually does:
++ *
++ * If (@state & @p->state) @p->state = TASK_RUNNING.
++ *
++ * If the task was not queued/runnable, also place it back on a runqueue.
++ *
++ * This function is atomic against schedule() which would dequeue the task.
++ *
++ * It issues a full memory barrier before accessing @p->state, see the comment
++ * with set_current_state().
++ *
++ * Uses p->pi_lock to serialize against concurrent wake-ups.
++ *
++ * Relies on p->pi_lock stabilizing:
++ * - p->sched_class
++ * - p->cpus_ptr
++ * - p->sched_task_group
++ * in order to do migration, see its use of select_task_rq()/set_task_cpu().
++ *
++ * Tries really hard to only take one task_rq(p)->lock for performance.
++ * Takes rq->lock in:
++ * - ttwu_runnable() -- old rq, unavoidable, see comment there;
++ * - ttwu_queue() -- new rq, for enqueue of the task;
++ * - psi_ttwu_dequeue() -- much sadness :-( accounting will kill us.
++ *
++ * As a consequence we race really badly with just about everything. See the
++ * many memory barriers and their comments for details.
++ *
++ * Return: %true if @p->state changes (an actual wakeup was done),
++ * %false otherwise.
++ */
++int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
++{
++ guard(preempt)();
++ int cpu, success = 0;
++
++ if (p == current) {
++ /*
++ * We're waking current, this means 'p->on_rq' and 'task_cpu(p)
++ * == smp_processor_id()'. Together this means we can special
++ * case the whole 'p->on_rq && ttwu_runnable()' case below
++ * without taking any locks.
++ *
++ * In particular:
++ * - we rely on Program-Order guarantees for all the ordering,
++ * - we're serialized against set_special_state() by virtue of
++ * it disabling IRQs (this allows not taking ->pi_lock).
++ */
++ if (!ttwu_state_match(p, state, &success))
++ goto out;
++
++ trace_sched_waking(p);
++ ttwu_do_wakeup(p);
++ goto out;
++ }
++
++ /*
++ * If we are going to wake up a thread waiting for CONDITION we
++ * need to ensure that CONDITION=1 done by the caller can not be
++ * reordered with p->state check below. This pairs with smp_store_mb()
++ * in set_current_state() that the waiting thread does.
++ */
++ scoped_guard (raw_spinlock_irqsave, &p->pi_lock) {
++ smp_mb__after_spinlock();
++ if (!ttwu_state_match(p, state, &success))
++ break;
++
++ trace_sched_waking(p);
++
++ /*
++ * Ensure we load p->on_rq _after_ p->state, otherwise it would
++ * be possible to, falsely, observe p->on_rq == 0 and get stuck
++ * in smp_cond_load_acquire() below.
++ *
++ * sched_ttwu_pending() try_to_wake_up()
++ * STORE p->on_rq = 1 LOAD p->state
++ * UNLOCK rq->lock
++ *
++ * __schedule() (switch to task 'p')
++ * LOCK rq->lock smp_rmb();
++ * smp_mb__after_spinlock();
++ * UNLOCK rq->lock
++ *
++ * [task p]
++ * STORE p->state = UNINTERRUPTIBLE LOAD p->on_rq
++ *
++ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in
++ * __schedule(). See the comment for smp_mb__after_spinlock().
++ *
++ * A similar smp_rmb() lives in __task_needs_rq_lock().
++ */
++ smp_rmb();
++ if (READ_ONCE(p->on_rq) && ttwu_runnable(p, wake_flags))
++ break;
++
++#ifdef CONFIG_SMP
++ /*
++ * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be
++ * possible to, falsely, observe p->on_cpu == 0.
++ *
++ * One must be running (->on_cpu == 1) in order to remove oneself
++ * from the runqueue.
++ *
++ * __schedule() (switch to task 'p') try_to_wake_up()
++ * STORE p->on_cpu = 1 LOAD p->on_rq
++ * UNLOCK rq->lock
++ *
++ * __schedule() (put 'p' to sleep)
++ * LOCK rq->lock smp_rmb();
++ * smp_mb__after_spinlock();
++ * STORE p->on_rq = 0 LOAD p->on_cpu
++ *
++ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in
++ * __schedule(). See the comment for smp_mb__after_spinlock().
++ *
++ * Form a control-dep-acquire with p->on_rq == 0 above, to ensure
++ * schedule()'s deactivate_task() has 'happened' and p will no longer
++ * care about it's own p->state. See the comment in __schedule().
++ */
++ smp_acquire__after_ctrl_dep();
++
++ /*
++ * We're doing the wakeup (@success == 1), they did a dequeue (p->on_rq
++ * == 0), which means we need to do an enqueue, change p->state to
++ * TASK_WAKING such that we can unlock p->pi_lock before doing the
++ * enqueue, such as ttwu_queue_wakelist().
++ */
++ WRITE_ONCE(p->__state, TASK_WAKING);
++
++ /*
++ * If the owning (remote) CPU is still in the middle of schedule() with
++ * this task as prev, considering queueing p on the remote CPUs wake_list
++ * which potentially sends an IPI instead of spinning on p->on_cpu to
++ * let the waker make forward progress. This is safe because IRQs are
++ * disabled and the IPI will deliver after on_cpu is cleared.
++ *
++ * Ensure we load task_cpu(p) after p->on_cpu:
++ *
++ * set_task_cpu(p, cpu);
++ * STORE p->cpu = @cpu
++ * __schedule() (switch to task 'p')
++ * LOCK rq->lock
++ * smp_mb__after_spin_lock() smp_cond_load_acquire(&p->on_cpu)
++ * STORE p->on_cpu = 1 LOAD p->cpu
++ *
++ * to ensure we observe the correct CPU on which the task is currently
++ * scheduling.
++ */
++ if (smp_load_acquire(&p->on_cpu) &&
++ ttwu_queue_wakelist(p, task_cpu(p), wake_flags))
++ break;
++
++ /*
++ * If the owning (remote) CPU is still in the middle of schedule() with
++ * this task as prev, wait until it's done referencing the task.
++ *
++ * Pairs with the smp_store_release() in finish_task().
++ *
++ * This ensures that tasks getting woken will be fully ordered against
++ * their previous state and preserve Program Order.
++ */
++ smp_cond_load_acquire(&p->on_cpu, !VAL);
++
++ sched_task_ttwu(p);
++
++ if ((wake_flags & WF_CURRENT_CPU) &&
++ cpumask_test_cpu(smp_processor_id(), p->cpus_ptr))
++ cpu = smp_processor_id();
++ else
++ cpu = select_task_rq(p);
++
++ if (cpu != task_cpu(p)) {
++ if (p->in_iowait) {
++ delayacct_blkio_end(p);
++ atomic_dec(&task_rq(p)->nr_iowait);
++ }
++
++ wake_flags |= WF_MIGRATED;
++ set_task_cpu(p, cpu);
++ }
++#else
++ sched_task_ttwu(p);
++
++ cpu = task_cpu(p);
++#endif /* CONFIG_SMP */
++
++ ttwu_queue(p, cpu, wake_flags);
++ }
++out:
++ if (success)
++ ttwu_stat(p, task_cpu(p), wake_flags);
++
++ return success;
++}
++
++static bool __task_needs_rq_lock(struct task_struct *p)
++{
++ unsigned int state = READ_ONCE(p->__state);
++
++ /*
++ * Since pi->lock blocks try_to_wake_up(), we don't need rq->lock when
++ * the task is blocked. Make sure to check @state since ttwu() can drop
++ * locks at the end, see ttwu_queue_wakelist().
++ */
++ if (state == TASK_RUNNING || state == TASK_WAKING)
++ return true;
++
++ /*
++ * Ensure we load p->on_rq after p->__state, otherwise it would be
++ * possible to, falsely, observe p->on_rq == 0.
++ *
++ * See try_to_wake_up() for a longer comment.
++ */
++ smp_rmb();
++ if (p->on_rq)
++ return true;
++
++#ifdef CONFIG_SMP
++ /*
++ * Ensure the task has finished __schedule() and will not be referenced
++ * anymore. Again, see try_to_wake_up() for a longer comment.
++ */
++ smp_rmb();
++ smp_cond_load_acquire(&p->on_cpu, !VAL);
++#endif
++
++ return false;
++}
++
++/**
++ * task_call_func - Invoke a function on task in fixed state
++ * @p: Process for which the function is to be invoked, can be @current.
++ * @func: Function to invoke.
++ * @arg: Argument to function.
++ *
++ * Fix the task in it's current state by avoiding wakeups and or rq operations
++ * and call @func(@arg) on it. This function can use ->on_rq and task_curr()
++ * to work out what the state is, if required. Given that @func can be invoked
++ * with a runqueue lock held, it had better be quite lightweight.
++ *
++ * Returns:
++ * Whatever @func returns
++ */
++int task_call_func(struct task_struct *p, task_call_f func, void *arg)
++{
++ struct rq *rq = NULL;
++ struct rq_flags rf;
++ int ret;
++
++ raw_spin_lock_irqsave(&p->pi_lock, rf.flags);
++
++ if (__task_needs_rq_lock(p))
++ rq = __task_rq_lock(p, &rf);
++
++ /*
++ * At this point the task is pinned; either:
++ * - blocked and we're holding off wakeups (pi->lock)
++ * - woken, and we're holding off enqueue (rq->lock)
++ * - queued, and we're holding off schedule (rq->lock)
++ * - running, and we're holding off de-schedule (rq->lock)
++ *
++ * The called function (@func) can use: task_curr(), p->on_rq and
++ * p->__state to differentiate between these states.
++ */
++ ret = func(p, arg);
++
++ if (rq)
++ __task_rq_unlock(rq, &rf);
++
++ raw_spin_unlock_irqrestore(&p->pi_lock, rf.flags);
++ return ret;
++}
++
++/**
++ * cpu_curr_snapshot - Return a snapshot of the currently running task
++ * @cpu: The CPU on which to snapshot the task.
++ *
++ * Returns the task_struct pointer of the task "currently" running on
++ * the specified CPU. If the same task is running on that CPU throughout,
++ * the return value will be a pointer to that task's task_struct structure.
++ * If the CPU did any context switches even vaguely concurrently with the
++ * execution of this function, the return value will be a pointer to the
++ * task_struct structure of a randomly chosen task that was running on
++ * that CPU somewhere around the time that this function was executing.
++ *
++ * If the specified CPU was offline, the return value is whatever it
++ * is, perhaps a pointer to the task_struct structure of that CPU's idle
++ * task, but there is no guarantee. Callers wishing a useful return
++ * value must take some action to ensure that the specified CPU remains
++ * online throughout.
++ *
++ * This function executes full memory barriers before and after fetching
++ * the pointer, which permits the caller to confine this function's fetch
++ * with respect to the caller's accesses to other shared variables.
++ */
++struct task_struct *cpu_curr_snapshot(int cpu)
++{
++ struct task_struct *t;
++
++ smp_mb(); /* Pairing determined by caller's synchronization design. */
++ t = rcu_dereference(cpu_curr(cpu));
++ smp_mb(); /* Pairing determined by caller's synchronization design. */
++ return t;
++}
++
++/**
++ * wake_up_process - Wake up a specific process
++ * @p: The process to be woken up.
++ *
++ * Attempt to wake up the nominated process and move it to the set of runnable
++ * processes.
++ *
++ * Return: 1 if the process was woken up, 0 if it was already running.
++ *
++ * This function executes a full memory barrier before accessing the task state.
++ */
++int wake_up_process(struct task_struct *p)
++{
++ return try_to_wake_up(p, TASK_NORMAL, 0);
++}
++EXPORT_SYMBOL(wake_up_process);
++
++int wake_up_state(struct task_struct *p, unsigned int state)
++{
++ return try_to_wake_up(p, state, 0);
++}
++
++/*
++ * Perform scheduler related setup for a newly forked process p.
++ * p is forked by current.
++ *
++ * __sched_fork() is basic setup used by init_idle() too:
++ */
++static inline void __sched_fork(unsigned long clone_flags, struct task_struct *p)
++{
++ p->on_rq = 0;
++ p->on_cpu = 0;
++ p->utime = 0;
++ p->stime = 0;
++ p->sched_time = 0;
++
++#ifdef CONFIG_SCHEDSTATS
++ /* Even if schedstat is disabled, there should not be garbage */
++ memset(&p->stats, 0, sizeof(p->stats));
++#endif
++
++#ifdef CONFIG_PREEMPT_NOTIFIERS
++ INIT_HLIST_HEAD(&p->preempt_notifiers);
++#endif
++
++#ifdef CONFIG_COMPACTION
++ p->capture_control = NULL;
++#endif
++#ifdef CONFIG_SMP
++ p->wake_entry.u_flags = CSD_TYPE_TTWU;
++#endif
++ init_sched_mm_cid(p);
++}
++
++/*
++ * fork()/clone()-time setup:
++ */
++int sched_fork(unsigned long clone_flags, struct task_struct *p)
++{
++ __sched_fork(clone_flags, p);
++ /*
++ * We mark the process as NEW here. This guarantees that
++ * nobody will actually run it, and a signal or other external
++ * event cannot wake it up and insert it on the runqueue either.
++ */
++ p->__state = TASK_NEW;
++
++ /*
++ * Make sure we do not leak PI boosting priority to the child.
++ */
++ p->prio = current->normal_prio;
++
++ /*
++ * Revert to default priority/policy on fork if requested.
++ */
++ if (unlikely(p->sched_reset_on_fork)) {
++ if (task_has_rt_policy(p)) {
++ p->policy = SCHED_NORMAL;
++ p->static_prio = NICE_TO_PRIO(0);
++ p->rt_priority = 0;
++ } else if (PRIO_TO_NICE(p->static_prio) < 0)
++ p->static_prio = NICE_TO_PRIO(0);
++
++ p->prio = p->normal_prio = p->static_prio;
++
++ /*
++ * We don't need the reset flag anymore after the fork. It has
++ * fulfilled its duty:
++ */
++ p->sched_reset_on_fork = 0;
++ }
++
++#ifdef CONFIG_SCHED_INFO
++ if (unlikely(sched_info_on()))
++ memset(&p->sched_info, 0, sizeof(p->sched_info));
++#endif
++ init_task_preempt_count(p);
++
++ return 0;
++}
++
++void sched_cgroup_fork(struct task_struct *p, struct kernel_clone_args *kargs)
++{
++ unsigned long flags;
++ struct rq *rq;
++
++ /*
++ * Because we're not yet on the pid-hash, p->pi_lock isn't strictly
++ * required yet, but lockdep gets upset if rules are violated.
++ */
++ raw_spin_lock_irqsave(&p->pi_lock, flags);
++ /*
++ * Share the timeslice between parent and child, thus the
++ * total amount of pending timeslices in the system doesn't change,
++ * resulting in more scheduling fairness.
++ */
++ rq = this_rq();
++ raw_spin_lock(&rq->lock);
++
++ rq->curr->time_slice /= 2;
++ p->time_slice = rq->curr->time_slice;
++#ifdef CONFIG_SCHED_HRTICK
++ hrtick_start(rq, rq->curr->time_slice);
++#endif
++
++ if (p->time_slice < RESCHED_NS) {
++ p->time_slice = sysctl_sched_base_slice;
++ resched_curr(rq);
++ }
++ sched_task_fork(p, rq);
++ raw_spin_unlock(&rq->lock);
++
++ rseq_migrate(p);
++ /*
++ * We're setting the CPU for the first time, we don't migrate,
++ * so use __set_task_cpu().
++ */
++ __set_task_cpu(p, smp_processor_id());
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++}
++
++void sched_post_fork(struct task_struct *p)
++{
++}
++
++#ifdef CONFIG_SCHEDSTATS
++
++DEFINE_STATIC_KEY_FALSE(sched_schedstats);
++
++static void set_schedstats(bool enabled)
++{
++ if (enabled)
++ static_branch_enable(&sched_schedstats);
++ else
++ static_branch_disable(&sched_schedstats);
++}
++
++void force_schedstat_enabled(void)
++{
++ if (!schedstat_enabled()) {
++ pr_info("kernel profiling enabled schedstats, disable via kernel.sched_schedstats.\n");
++ static_branch_enable(&sched_schedstats);
++ }
++}
++
++static int __init setup_schedstats(char *str)
++{
++ int ret = 0;
++ if (!str)
++ goto out;
++
++ if (!strcmp(str, "enable")) {
++ set_schedstats(true);
++ ret = 1;
++ } else if (!strcmp(str, "disable")) {
++ set_schedstats(false);
++ ret = 1;
++ }
++out:
++ if (!ret)
++ pr_warn("Unable to parse schedstats=\n");
++
++ return ret;
++}
++__setup("schedstats=", setup_schedstats);
++
++#ifdef CONFIG_PROC_SYSCTL
++static int sysctl_schedstats(struct ctl_table *table, int write, void *buffer,
++ size_t *lenp, loff_t *ppos)
++{
++ struct ctl_table t;
++ int err;
++ int state = static_branch_likely(&sched_schedstats);
++
++ if (write && !capable(CAP_SYS_ADMIN))
++ return -EPERM;
++
++ t = *table;
++ t.data = &state;
++ err = proc_dointvec_minmax(&t, write, buffer, lenp, ppos);
++ if (err < 0)
++ return err;
++ if (write)
++ set_schedstats(state);
++ return err;
++}
++
++static struct ctl_table sched_core_sysctls[] = {
++ {
++ .procname = "sched_schedstats",
++ .data = NULL,
++ .maxlen = sizeof(unsigned int),
++ .mode = 0644,
++ .proc_handler = sysctl_schedstats,
++ .extra1 = SYSCTL_ZERO,
++ .extra2 = SYSCTL_ONE,
++ },
++ {}
++};
++static int __init sched_core_sysctl_init(void)
++{
++ register_sysctl_init("kernel", sched_core_sysctls);
++ return 0;
++}
++late_initcall(sched_core_sysctl_init);
++#endif /* CONFIG_PROC_SYSCTL */
++#endif /* CONFIG_SCHEDSTATS */
++
++/*
++ * wake_up_new_task - wake up a newly created task for the first time.
++ *
++ * This function will do some initial scheduler statistics housekeeping
++ * that must be done for every newly created context, then puts the task
++ * on the runqueue and wakes it.
++ */
++void wake_up_new_task(struct task_struct *p)
++{
++ unsigned long flags;
++ struct rq *rq;
++
++ raw_spin_lock_irqsave(&p->pi_lock, flags);
++ WRITE_ONCE(p->__state, TASK_RUNNING);
++ rq = cpu_rq(select_task_rq(p));
++#ifdef CONFIG_SMP
++ rseq_migrate(p);
++ /*
++ * Fork balancing, do it here and not earlier because:
++ * - cpus_ptr can change in the fork path
++ * - any previously selected CPU might disappear through hotplug
++ *
++ * Use __set_task_cpu() to avoid calling sched_class::migrate_task_rq,
++ * as we're not fully set-up yet.
++ */
++ __set_task_cpu(p, cpu_of(rq));
++#endif
++
++ raw_spin_lock(&rq->lock);
++ update_rq_clock(rq);
++
++ activate_task(p, rq);
++ trace_sched_wakeup_new(p);
++ wakeup_preempt(rq);
++
++ raw_spin_unlock(&rq->lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++}
++
++#ifdef CONFIG_PREEMPT_NOTIFIERS
++
++static DEFINE_STATIC_KEY_FALSE(preempt_notifier_key);
++
++void preempt_notifier_inc(void)
++{
++ static_branch_inc(&preempt_notifier_key);
++}
++EXPORT_SYMBOL_GPL(preempt_notifier_inc);
++
++void preempt_notifier_dec(void)
++{
++ static_branch_dec(&preempt_notifier_key);
++}
++EXPORT_SYMBOL_GPL(preempt_notifier_dec);
++
++/**
++ * preempt_notifier_register - tell me when current is being preempted & rescheduled
++ * @notifier: notifier struct to register
++ */
++void preempt_notifier_register(struct preempt_notifier *notifier)
++{
++ if (!static_branch_unlikely(&preempt_notifier_key))
++ WARN(1, "registering preempt_notifier while notifiers disabled\n");
++
++ hlist_add_head(¬ifier->link, ¤t->preempt_notifiers);
++}
++EXPORT_SYMBOL_GPL(preempt_notifier_register);
++
++/**
++ * preempt_notifier_unregister - no longer interested in preemption notifications
++ * @notifier: notifier struct to unregister
++ *
++ * This is *not* safe to call from within a preemption notifier.
++ */
++void preempt_notifier_unregister(struct preempt_notifier *notifier)
++{
++ hlist_del(¬ifier->link);
++}
++EXPORT_SYMBOL_GPL(preempt_notifier_unregister);
++
++static void __fire_sched_in_preempt_notifiers(struct task_struct *curr)
++{
++ struct preempt_notifier *notifier;
++
++ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link)
++ notifier->ops->sched_in(notifier, raw_smp_processor_id());
++}
++
++static __always_inline void fire_sched_in_preempt_notifiers(struct task_struct *curr)
++{
++ if (static_branch_unlikely(&preempt_notifier_key))
++ __fire_sched_in_preempt_notifiers(curr);
++}
++
++static void
++__fire_sched_out_preempt_notifiers(struct task_struct *curr,
++ struct task_struct *next)
++{
++ struct preempt_notifier *notifier;
++
++ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link)
++ notifier->ops->sched_out(notifier, next);
++}
++
++static __always_inline void
++fire_sched_out_preempt_notifiers(struct task_struct *curr,
++ struct task_struct *next)
++{
++ if (static_branch_unlikely(&preempt_notifier_key))
++ __fire_sched_out_preempt_notifiers(curr, next);
++}
++
++#else /* !CONFIG_PREEMPT_NOTIFIERS */
++
++static inline void fire_sched_in_preempt_notifiers(struct task_struct *curr)
++{
++}
++
++static inline void
++fire_sched_out_preempt_notifiers(struct task_struct *curr,
++ struct task_struct *next)
++{
++}
++
++#endif /* CONFIG_PREEMPT_NOTIFIERS */
++
++static inline void prepare_task(struct task_struct *next)
++{
++ /*
++ * Claim the task as running, we do this before switching to it
++ * such that any running task will have this set.
++ *
++ * See the smp_load_acquire(&p->on_cpu) case in ttwu() and
++ * its ordering comment.
++ */
++ WRITE_ONCE(next->on_cpu, 1);
++}
++
++static inline void finish_task(struct task_struct *prev)
++{
++#ifdef CONFIG_SMP
++ /*
++ * This must be the very last reference to @prev from this CPU. After
++ * p->on_cpu is cleared, the task can be moved to a different CPU. We
++ * must ensure this doesn't happen until the switch is completely
++ * finished.
++ *
++ * In particular, the load of prev->state in finish_task_switch() must
++ * happen before this.
++ *
++ * Pairs with the smp_cond_load_acquire() in try_to_wake_up().
++ */
++ smp_store_release(&prev->on_cpu, 0);
++#else
++ prev->on_cpu = 0;
++#endif
++}
++
++#ifdef CONFIG_SMP
++
++static void do_balance_callbacks(struct rq *rq, struct balance_callback *head)
++{
++ void (*func)(struct rq *rq);
++ struct balance_callback *next;
++
++ lockdep_assert_held(&rq->lock);
++
++ while (head) {
++ func = (void (*)(struct rq *))head->func;
++ next = head->next;
++ head->next = NULL;
++ head = next;
++
++ func(rq);
++ }
++}
++
++static void balance_push(struct rq *rq);
++
++/*
++ * balance_push_callback is a right abuse of the callback interface and plays
++ * by significantly different rules.
++ *
++ * Where the normal balance_callback's purpose is to be ran in the same context
++ * that queued it (only later, when it's safe to drop rq->lock again),
++ * balance_push_callback is specifically targeted at __schedule().
++ *
++ * This abuse is tolerated because it places all the unlikely/odd cases behind
++ * a single test, namely: rq->balance_callback == NULL.
++ */
++struct balance_callback balance_push_callback = {
++ .next = NULL,
++ .func = balance_push,
++};
++
++static inline struct balance_callback *
++__splice_balance_callbacks(struct rq *rq, bool split)
++{
++ struct balance_callback *head = rq->balance_callback;
++
++ if (likely(!head))
++ return NULL;
++
++ lockdep_assert_rq_held(rq);
++ /*
++ * Must not take balance_push_callback off the list when
++ * splice_balance_callbacks() and balance_callbacks() are not
++ * in the same rq->lock section.
++ *
++ * In that case it would be possible for __schedule() to interleave
++ * and observe the list empty.
++ */
++ if (split && head == &balance_push_callback)
++ head = NULL;
++ else
++ rq->balance_callback = NULL;
++
++ return head;
++}
++
++static inline struct balance_callback *splice_balance_callbacks(struct rq *rq)
++{
++ return __splice_balance_callbacks(rq, true);
++}
++
++static void __balance_callbacks(struct rq *rq)
++{
++ do_balance_callbacks(rq, __splice_balance_callbacks(rq, false));
++}
++
++static inline void balance_callbacks(struct rq *rq, struct balance_callback *head)
++{
++ unsigned long flags;
++
++ if (unlikely(head)) {
++ raw_spin_lock_irqsave(&rq->lock, flags);
++ do_balance_callbacks(rq, head);
++ raw_spin_unlock_irqrestore(&rq->lock, flags);
++ }
++}
++
++#else
++
++static inline void __balance_callbacks(struct rq *rq)
++{
++}
++
++static inline struct balance_callback *splice_balance_callbacks(struct rq *rq)
++{
++ return NULL;
++}
++
++static inline void balance_callbacks(struct rq *rq, struct balance_callback *head)
++{
++}
++
++#endif
++
++static inline void
++prepare_lock_switch(struct rq *rq, struct task_struct *next)
++{
++ /*
++ * Since the runqueue lock will be released by the next
++ * task (which is an invalid locking op but in the case
++ * of the scheduler it's an obvious special-case), so we
++ * do an early lockdep release here:
++ */
++ spin_release(&rq->lock.dep_map, _THIS_IP_);
++#ifdef CONFIG_DEBUG_SPINLOCK
++ /* this is a valid case when another task releases the spinlock */
++ rq->lock.owner = next;
++#endif
++}
++
++static inline void finish_lock_switch(struct rq *rq)
++{
++ /*
++ * If we are tracking spinlock dependencies then we have to
++ * fix up the runqueue lock - which gets 'carried over' from
++ * prev into current:
++ */
++ spin_acquire(&rq->lock.dep_map, 0, 0, _THIS_IP_);
++ __balance_callbacks(rq);
++ raw_spin_unlock_irq(&rq->lock);
++}
++
++/*
++ * NOP if the arch has not defined these:
++ */
++
++#ifndef prepare_arch_switch
++# define prepare_arch_switch(next) do { } while (0)
++#endif
++
++#ifndef finish_arch_post_lock_switch
++# define finish_arch_post_lock_switch() do { } while (0)
++#endif
++
++static inline void kmap_local_sched_out(void)
++{
++#ifdef CONFIG_KMAP_LOCAL
++ if (unlikely(current->kmap_ctrl.idx))
++ __kmap_local_sched_out();
++#endif
++}
++
++static inline void kmap_local_sched_in(void)
++{
++#ifdef CONFIG_KMAP_LOCAL
++ if (unlikely(current->kmap_ctrl.idx))
++ __kmap_local_sched_in();
++#endif
++}
++
++/**
++ * prepare_task_switch - prepare to switch tasks
++ * @rq: the runqueue preparing to switch
++ * @next: the task we are going to switch to.
++ *
++ * This is called with the rq lock held and interrupts off. It must
++ * be paired with a subsequent finish_task_switch after the context
++ * switch.
++ *
++ * prepare_task_switch sets up locking and calls architecture specific
++ * hooks.
++ */
++static inline void
++prepare_task_switch(struct rq *rq, struct task_struct *prev,
++ struct task_struct *next)
++{
++ kcov_prepare_switch(prev);
++ sched_info_switch(rq, prev, next);
++ perf_event_task_sched_out(prev, next);
++ rseq_preempt(prev);
++ fire_sched_out_preempt_notifiers(prev, next);
++ kmap_local_sched_out();
++ prepare_task(next);
++ prepare_arch_switch(next);
++}
++
++/**
++ * finish_task_switch - clean up after a task-switch
++ * @rq: runqueue associated with task-switch
++ * @prev: the thread we just switched away from.
++ *
++ * finish_task_switch must be called after the context switch, paired
++ * with a prepare_task_switch call before the context switch.
++ * finish_task_switch will reconcile locking set up by prepare_task_switch,
++ * and do any other architecture-specific cleanup actions.
++ *
++ * Note that we may have delayed dropping an mm in context_switch(). If
++ * so, we finish that here outside of the runqueue lock. (Doing it
++ * with the lock held can cause deadlocks; see schedule() for
++ * details.)
++ *
++ * The context switch have flipped the stack from under us and restored the
++ * local variables which were saved when this task called schedule() in the
++ * past. prev == current is still correct but we need to recalculate this_rq
++ * because prev may have moved to another CPU.
++ */
++static struct rq *finish_task_switch(struct task_struct *prev)
++ __releases(rq->lock)
++{
++ struct rq *rq = this_rq();
++ struct mm_struct *mm = rq->prev_mm;
++ unsigned int prev_state;
++
++ /*
++ * The previous task will have left us with a preempt_count of 2
++ * because it left us after:
++ *
++ * schedule()
++ * preempt_disable(); // 1
++ * __schedule()
++ * raw_spin_lock_irq(&rq->lock) // 2
++ *
++ * Also, see FORK_PREEMPT_COUNT.
++ */
++ if (WARN_ONCE(preempt_count() != 2*PREEMPT_DISABLE_OFFSET,
++ "corrupted preempt_count: %s/%d/0x%x\n",
++ current->comm, current->pid, preempt_count()))
++ preempt_count_set(FORK_PREEMPT_COUNT);
++
++ rq->prev_mm = NULL;
++
++ /*
++ * A task struct has one reference for the use as "current".
++ * If a task dies, then it sets TASK_DEAD in tsk->state and calls
++ * schedule one last time. The schedule call will never return, and
++ * the scheduled task must drop that reference.
++ *
++ * We must observe prev->state before clearing prev->on_cpu (in
++ * finish_task), otherwise a concurrent wakeup can get prev
++ * running on another CPU and we could rave with its RUNNING -> DEAD
++ * transition, resulting in a double drop.
++ */
++ prev_state = READ_ONCE(prev->__state);
++ vtime_task_switch(prev);
++ perf_event_task_sched_in(prev, current);
++ finish_task(prev);
++ tick_nohz_task_switch();
++ finish_lock_switch(rq);
++ finish_arch_post_lock_switch();
++ kcov_finish_switch(current);
++ /*
++ * kmap_local_sched_out() is invoked with rq::lock held and
++ * interrupts disabled. There is no requirement for that, but the
++ * sched out code does not have an interrupt enabled section.
++ * Restoring the maps on sched in does not require interrupts being
++ * disabled either.
++ */
++ kmap_local_sched_in();
++
++ fire_sched_in_preempt_notifiers(current);
++ /*
++ * When switching through a kernel thread, the loop in
++ * membarrier_{private,global}_expedited() may have observed that
++ * kernel thread and not issued an IPI. It is therefore possible to
++ * schedule between user->kernel->user threads without passing though
++ * switch_mm(). Membarrier requires a barrier after storing to
++ * rq->curr, before returning to userspace, so provide them here:
++ *
++ * - a full memory barrier for {PRIVATE,GLOBAL}_EXPEDITED, implicitly
++ * provided by mmdrop(),
++ * - a sync_core for SYNC_CORE.
++ */
++ if (mm) {
++ membarrier_mm_sync_core_before_usermode(mm);
++ mmdrop_sched(mm);
++ }
++ if (unlikely(prev_state == TASK_DEAD)) {
++ /* Task is done with its stack. */
++ put_task_stack(prev);
++
++ put_task_struct_rcu_user(prev);
++ }
++
++ return rq;
++}
++
++/**
++ * schedule_tail - first thing a freshly forked thread must call.
++ * @prev: the thread we just switched away from.
++ */
++asmlinkage __visible void schedule_tail(struct task_struct *prev)
++ __releases(rq->lock)
++{
++ /*
++ * New tasks start with FORK_PREEMPT_COUNT, see there and
++ * finish_task_switch() for details.
++ *
++ * finish_task_switch() will drop rq->lock() and lower preempt_count
++ * and the preempt_enable() will end up enabling preemption (on
++ * PREEMPT_COUNT kernels).
++ */
++
++ finish_task_switch(prev);
++ preempt_enable();
++
++ if (current->set_child_tid)
++ put_user(task_pid_vnr(current), current->set_child_tid);
++
++ calculate_sigpending();
++}
++
++/*
++ * context_switch - switch to the new MM and the new thread's register state.
++ */
++static __always_inline struct rq *
++context_switch(struct rq *rq, struct task_struct *prev,
++ struct task_struct *next)
++{
++ prepare_task_switch(rq, prev, next);
++
++ /*
++ * For paravirt, this is coupled with an exit in switch_to to
++ * combine the page table reload and the switch backend into
++ * one hypercall.
++ */
++ arch_start_context_switch(prev);
++
++ /*
++ * kernel -> kernel lazy + transfer active
++ * user -> kernel lazy + mmgrab() active
++ *
++ * kernel -> user switch + mmdrop() active
++ * user -> user switch
++ *
++ * switch_mm_cid() needs to be updated if the barriers provided
++ * by context_switch() are modified.
++ */
++ if (!next->mm) { // to kernel
++ enter_lazy_tlb(prev->active_mm, next);
++
++ next->active_mm = prev->active_mm;
++ if (prev->mm) // from user
++ mmgrab(prev->active_mm);
++ else
++ prev->active_mm = NULL;
++ } else { // to user
++ membarrier_switch_mm(rq, prev->active_mm, next->mm);
++ /*
++ * sys_membarrier() requires an smp_mb() between setting
++ * rq->curr / membarrier_switch_mm() and returning to userspace.
++ *
++ * The below provides this either through switch_mm(), or in
++ * case 'prev->active_mm == next->mm' through
++ * finish_task_switch()'s mmdrop().
++ */
++ switch_mm_irqs_off(prev->active_mm, next->mm, next);
++ lru_gen_use_mm(next->mm);
++
++ if (!prev->mm) { // from kernel
++ /* will mmdrop() in finish_task_switch(). */
++ rq->prev_mm = prev->active_mm;
++ prev->active_mm = NULL;
++ }
++ }
++
++ /* switch_mm_cid() requires the memory barriers above. */
++ switch_mm_cid(rq, prev, next);
++
++ prepare_lock_switch(rq, next);
++
++ /* Here we just switch the register state and the stack. */
++ switch_to(prev, next, prev);
++ barrier();
++
++ return finish_task_switch(prev);
++}
++
++/*
++ * nr_running, nr_uninterruptible and nr_context_switches:
++ *
++ * externally visible scheduler statistics: current number of runnable
++ * threads, total number of context switches performed since bootup.
++ */
++unsigned int nr_running(void)
++{
++ unsigned int i, sum = 0;
++
++ for_each_online_cpu(i)
++ sum += cpu_rq(i)->nr_running;
++
++ return sum;
++}
++
++/*
++ * Check if only the current task is running on the CPU.
++ *
++ * Caution: this function does not check that the caller has disabled
++ * preemption, thus the result might have a time-of-check-to-time-of-use
++ * race. The caller is responsible to use it correctly, for example:
++ *
++ * - from a non-preemptible section (of course)
++ *
++ * - from a thread that is bound to a single CPU
++ *
++ * - in a loop with very short iterations (e.g. a polling loop)
++ */
++bool single_task_running(void)
++{
++ return raw_rq()->nr_running == 1;
++}
++EXPORT_SYMBOL(single_task_running);
++
++unsigned long long nr_context_switches_cpu(int cpu)
++{
++ return cpu_rq(cpu)->nr_switches;
++}
++
++unsigned long long nr_context_switches(void)
++{
++ int i;
++ unsigned long long sum = 0;
++
++ for_each_possible_cpu(i)
++ sum += cpu_rq(i)->nr_switches;
++
++ return sum;
++}
++
++/*
++ * Consumers of these two interfaces, like for example the cpuidle menu
++ * governor, are using nonsensical data. Preferring shallow idle state selection
++ * for a CPU that has IO-wait which might not even end up running the task when
++ * it does become runnable.
++ */
++
++unsigned int nr_iowait_cpu(int cpu)
++{
++ return atomic_read(&cpu_rq(cpu)->nr_iowait);
++}
++
++/*
++ * IO-wait accounting, and how it's mostly bollocks (on SMP).
++ *
++ * The idea behind IO-wait account is to account the idle time that we could
++ * have spend running if it were not for IO. That is, if we were to improve the
++ * storage performance, we'd have a proportional reduction in IO-wait time.
++ *
++ * This all works nicely on UP, where, when a task blocks on IO, we account
++ * idle time as IO-wait, because if the storage were faster, it could've been
++ * running and we'd not be idle.
++ *
++ * This has been extended to SMP, by doing the same for each CPU. This however
++ * is broken.
++ *
++ * Imagine for instance the case where two tasks block on one CPU, only the one
++ * CPU will have IO-wait accounted, while the other has regular idle. Even
++ * though, if the storage were faster, both could've ran at the same time,
++ * utilising both CPUs.
++ *
++ * This means, that when looking globally, the current IO-wait accounting on
++ * SMP is a lower bound, by reason of under accounting.
++ *
++ * Worse, since the numbers are provided per CPU, they are sometimes
++ * interpreted per CPU, and that is nonsensical. A blocked task isn't strictly
++ * associated with any one particular CPU, it can wake to another CPU than it
++ * blocked on. This means the per CPU IO-wait number is meaningless.
++ *
++ * Task CPU affinities can make all that even more 'interesting'.
++ */
++
++unsigned int nr_iowait(void)
++{
++ unsigned int i, sum = 0;
++
++ for_each_possible_cpu(i)
++ sum += nr_iowait_cpu(i);
++
++ return sum;
++}
++
++#ifdef CONFIG_SMP
++
++/*
++ * sched_exec - execve() is a valuable balancing opportunity, because at
++ * this point the task has the smallest effective memory and cache
++ * footprint.
++ */
++void sched_exec(void)
++{
++}
++
++#endif
++
++DEFINE_PER_CPU(struct kernel_stat, kstat);
++DEFINE_PER_CPU(struct kernel_cpustat, kernel_cpustat);
++
++EXPORT_PER_CPU_SYMBOL(kstat);
++EXPORT_PER_CPU_SYMBOL(kernel_cpustat);
++
++static inline void update_curr(struct rq *rq, struct task_struct *p)
++{
++ s64 ns = rq->clock_task - p->last_ran;
++
++ p->sched_time += ns;
++ cgroup_account_cputime(p, ns);
++ account_group_exec_runtime(p, ns);
++
++ p->time_slice -= ns;
++ p->last_ran = rq->clock_task;
++}
++
++/*
++ * Return accounted runtime for the task.
++ * Return separately the current's pending runtime that have not been
++ * accounted yet.
++ */
++unsigned long long task_sched_runtime(struct task_struct *p)
++{
++ unsigned long flags;
++ struct rq *rq;
++ raw_spinlock_t *lock;
++ u64 ns;
++
++#if defined(CONFIG_64BIT) && defined(CONFIG_SMP)
++ /*
++ * 64-bit doesn't need locks to atomically read a 64-bit value.
++ * So we have a optimization chance when the task's delta_exec is 0.
++ * Reading ->on_cpu is racy, but this is ok.
++ *
++ * If we race with it leaving CPU, we'll take a lock. So we're correct.
++ * If we race with it entering CPU, unaccounted time is 0. This is
++ * indistinguishable from the read occurring a few cycles earlier.
++ * If we see ->on_cpu without ->on_rq, the task is leaving, and has
++ * been accounted, so we're correct here as well.
++ */
++ if (!p->on_cpu || !task_on_rq_queued(p))
++ return tsk_seruntime(p);
++#endif
++
++ rq = task_access_lock_irqsave(p, &lock, &flags);
++ /*
++ * Must be ->curr _and_ ->on_rq. If dequeued, we would
++ * project cycles that may never be accounted to this
++ * thread, breaking clock_gettime().
++ */
++ if (p == rq->curr && task_on_rq_queued(p)) {
++ update_rq_clock(rq);
++ update_curr(rq, p);
++ }
++ ns = tsk_seruntime(p);
++ task_access_unlock_irqrestore(p, lock, &flags);
++
++ return ns;
++}
++
++/* This manages tasks that have run out of timeslice during a scheduler_tick */
++static inline void scheduler_task_tick(struct rq *rq)
++{
++ struct task_struct *p = rq->curr;
++
++ if (is_idle_task(p))
++ return;
++
++ update_curr(rq, p);
++ cpufreq_update_util(rq, 0);
++
++ /*
++ * Tasks have less than RESCHED_NS of time slice left they will be
++ * rescheduled.
++ */
++ if (p->time_slice >= RESCHED_NS)
++ return;
++ set_tsk_need_resched(p);
++ set_preempt_need_resched();
++}
++
++#ifdef CONFIG_SCHED_DEBUG
++static u64 cpu_resched_latency(struct rq *rq)
++{
++ int latency_warn_ms = READ_ONCE(sysctl_resched_latency_warn_ms);
++ u64 resched_latency, now = rq_clock(rq);
++ static bool warned_once;
++
++ if (sysctl_resched_latency_warn_once && warned_once)
++ return 0;
++
++ if (!need_resched() || !latency_warn_ms)
++ return 0;
++
++ if (system_state == SYSTEM_BOOTING)
++ return 0;
++
++ if (!rq->last_seen_need_resched_ns) {
++ rq->last_seen_need_resched_ns = now;
++ rq->ticks_without_resched = 0;
++ return 0;
++ }
++
++ rq->ticks_without_resched++;
++ resched_latency = now - rq->last_seen_need_resched_ns;
++ if (resched_latency <= latency_warn_ms * NSEC_PER_MSEC)
++ return 0;
++
++ warned_once = true;
++
++ return resched_latency;
++}
++
++static int __init setup_resched_latency_warn_ms(char *str)
++{
++ long val;
++
++ if ((kstrtol(str, 0, &val))) {
++ pr_warn("Unable to set resched_latency_warn_ms\n");
++ return 1;
++ }
++
++ sysctl_resched_latency_warn_ms = val;
++ return 1;
++}
++__setup("resched_latency_warn_ms=", setup_resched_latency_warn_ms);
++#else
++static inline u64 cpu_resched_latency(struct rq *rq) { return 0; }
++#endif /* CONFIG_SCHED_DEBUG */
++
++/*
++ * This function gets called by the timer code, with HZ frequency.
++ * We call it with interrupts disabled.
++ */
++void scheduler_tick(void)
++{
++ int cpu __maybe_unused = smp_processor_id();
++ struct rq *rq = cpu_rq(cpu);
++ struct task_struct *curr = rq->curr;
++ u64 resched_latency;
++
++ if (housekeeping_cpu(cpu, HK_TYPE_TICK))
++ arch_scale_freq_tick();
++
++ sched_clock_tick();
++
++ raw_spin_lock(&rq->lock);
++ update_rq_clock(rq);
++
++ scheduler_task_tick(rq);
++ if (sched_feat(LATENCY_WARN))
++ resched_latency = cpu_resched_latency(rq);
++ calc_global_load_tick(rq);
++
++ task_tick_mm_cid(rq, rq->curr);
++
++ raw_spin_unlock(&rq->lock);
++
++ if (sched_feat(LATENCY_WARN) && resched_latency)
++ resched_latency_warn(cpu, resched_latency);
++
++ perf_event_task_tick();
++
++ if (curr->flags & PF_WQ_WORKER)
++ wq_worker_tick(curr);
++}
++
++#ifdef CONFIG_SCHED_SMT
++static inline int sg_balance_cpu_stop(void *data)
++{
++ struct rq *rq = this_rq();
++ struct task_struct *p = data;
++ cpumask_t tmp;
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ raw_spin_lock(&p->pi_lock);
++ raw_spin_lock(&rq->lock);
++
++ rq->active_balance = 0;
++ /* _something_ may have changed the task, double check again */
++ if (task_on_rq_queued(p) && task_rq(p) == rq &&
++ cpumask_and(&tmp, p->cpus_ptr, sched_sg_idle_mask) &&
++ !is_migration_disabled(p)) {
++ int cpu = cpu_of(rq);
++ int dcpu = __best_mask_cpu(&tmp, per_cpu(sched_cpu_llc_mask, cpu));
++ rq = move_queued_task(rq, p, dcpu);
++ }
++
++ raw_spin_unlock(&rq->lock);
++ raw_spin_unlock(&p->pi_lock);
++
++ local_irq_restore(flags);
++
++ return 0;
++}
++
++/* sg_balance_trigger - trigger slibing group balance for @cpu */
++static inline int sg_balance_trigger(struct rq *src_rq, const int cpu)
++{
++ struct rq *rq= cpu_rq(cpu);
++ unsigned long flags;
++ struct task_struct *p;
++ int res;
++
++ if (!raw_spin_trylock_irqsave(&rq->lock, flags))
++ return 0;
++
++ res = (1 == rq->nr_running) && \
++ !is_migration_disabled((p = sched_rq_first_task(rq))) && \
++ cpumask_intersects(p->cpus_ptr, sched_sg_idle_mask) && \
++ !rq->active_balance;
++ if (res)
++ rq->active_balance = 1;
++
++ raw_spin_unlock_irqrestore(&rq->lock, flags);
++
++ if (res) {
++ preempt_disable();
++ raw_spin_unlock(&src_rq->lock);
++
++ stop_one_cpu_nowait(cpu, sg_balance_cpu_stop, p,
++ &rq->active_balance_work);
++
++ raw_spin_lock(&src_rq->lock);
++ preempt_enable();
++ }
++
++ return res;
++}
++
++/*
++ * sg_balance - slibing group balance check for run queue @rq
++ */
++static inline void sg_balance(struct rq *rq)
++{
++ cpumask_t chk;
++
++ if (cpumask_andnot(&chk, cpu_active_mask, sched_idle_mask) &&
++ cpumask_andnot(&chk, &chk, &sched_rq_pending_mask)) {
++ int i, cpu = cpu_of(rq);
++
++ for_each_cpu_wrap(i, &chk, cpu) {
++ if (cpumask_subset(cpu_smt_mask(i), &chk) &&\
++ sg_balance_trigger(rq, i))
++ return;
++ }
++ }
++}
++
++static DEFINE_PER_CPU(struct balance_callback, sg_balance_head) = {
++ .func = sg_balance,
++};
++#endif /* CONFIG_SCHED_SMT */
++
++#ifdef CONFIG_NO_HZ_FULL
++
++struct tick_work {
++ int cpu;
++ atomic_t state;
++ struct delayed_work work;
++};
++/* Values for ->state, see diagram below. */
++#define TICK_SCHED_REMOTE_OFFLINE 0
++#define TICK_SCHED_REMOTE_OFFLINING 1
++#define TICK_SCHED_REMOTE_RUNNING 2
++
++/*
++ * State diagram for ->state:
++ *
++ *
++ * TICK_SCHED_REMOTE_OFFLINE
++ * | ^
++ * | |
++ * | | sched_tick_remote()
++ * | |
++ * | |
++ * +--TICK_SCHED_REMOTE_OFFLINING
++ * | ^
++ * | |
++ * sched_tick_start() | | sched_tick_stop()
++ * | |
++ * V |
++ * TICK_SCHED_REMOTE_RUNNING
++ *
++ *
++ * Other transitions get WARN_ON_ONCE(), except that sched_tick_remote()
++ * and sched_tick_start() are happy to leave the state in RUNNING.
++ */
++
++static struct tick_work __percpu *tick_work_cpu;
++
++static void sched_tick_remote(struct work_struct *work)
++{
++ struct delayed_work *dwork = to_delayed_work(work);
++ struct tick_work *twork = container_of(dwork, struct tick_work, work);
++ int cpu = twork->cpu;
++ struct rq *rq = cpu_rq(cpu);
++ int os;
++
++ /*
++ * Handle the tick only if it appears the remote CPU is running in full
++ * dynticks mode. The check is racy by nature, but missing a tick or
++ * having one too much is no big deal because the scheduler tick updates
++ * statistics and checks timeslices in a time-independent way, regardless
++ * of when exactly it is running.
++ */
++ if (tick_nohz_tick_stopped_cpu(cpu)) {
++ guard(raw_spinlock_irqsave)(&rq->lock);
++ struct task_struct *curr = rq->curr;
++
++ if (cpu_online(cpu)) {
++ update_rq_clock(rq);
++
++ if (!is_idle_task(curr)) {
++ /*
++ * Make sure the next tick runs within a
++ * reasonable amount of time.
++ */
++ u64 delta = rq_clock_task(rq) - curr->last_ran;
++ WARN_ON_ONCE(delta > (u64)NSEC_PER_SEC * 3);
++ }
++ scheduler_task_tick(rq);
++
++ calc_load_nohz_remote(rq);
++ }
++ }
++
++ /*
++ * Run the remote tick once per second (1Hz). This arbitrary
++ * frequency is large enough to avoid overload but short enough
++ * to keep scheduler internal stats reasonably up to date. But
++ * first update state to reflect hotplug activity if required.
++ */
++ os = atomic_fetch_add_unless(&twork->state, -1, TICK_SCHED_REMOTE_RUNNING);
++ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_OFFLINE);
++ if (os == TICK_SCHED_REMOTE_RUNNING)
++ queue_delayed_work(system_unbound_wq, dwork, HZ);
++}
++
++static void sched_tick_start(int cpu)
++{
++ int os;
++ struct tick_work *twork;
++
++ if (housekeeping_cpu(cpu, HK_TYPE_TICK))
++ return;
++
++ WARN_ON_ONCE(!tick_work_cpu);
++
++ twork = per_cpu_ptr(tick_work_cpu, cpu);
++ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_RUNNING);
++ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_RUNNING);
++ if (os == TICK_SCHED_REMOTE_OFFLINE) {
++ twork->cpu = cpu;
++ INIT_DELAYED_WORK(&twork->work, sched_tick_remote);
++ queue_delayed_work(system_unbound_wq, &twork->work, HZ);
++ }
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++static void sched_tick_stop(int cpu)
++{
++ struct tick_work *twork;
++ int os;
++
++ if (housekeeping_cpu(cpu, HK_TYPE_TICK))
++ return;
++
++ WARN_ON_ONCE(!tick_work_cpu);
++
++ twork = per_cpu_ptr(tick_work_cpu, cpu);
++ /* There cannot be competing actions, but don't rely on stop-machine. */
++ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_OFFLINING);
++ WARN_ON_ONCE(os != TICK_SCHED_REMOTE_RUNNING);
++ /* Don't cancel, as this would mess up the state machine. */
++}
++#endif /* CONFIG_HOTPLUG_CPU */
++
++int __init sched_tick_offload_init(void)
++{
++ tick_work_cpu = alloc_percpu(struct tick_work);
++ BUG_ON(!tick_work_cpu);
++ return 0;
++}
++
++#else /* !CONFIG_NO_HZ_FULL */
++static inline void sched_tick_start(int cpu) { }
++static inline void sched_tick_stop(int cpu) { }
++#endif
++
++#if defined(CONFIG_PREEMPTION) && (defined(CONFIG_DEBUG_PREEMPT) || \
++ defined(CONFIG_PREEMPT_TRACER))
++/*
++ * If the value passed in is equal to the current preempt count
++ * then we just disabled preemption. Start timing the latency.
++ */
++static inline void preempt_latency_start(int val)
++{
++ if (preempt_count() == val) {
++ unsigned long ip = get_lock_parent_ip();
++#ifdef CONFIG_DEBUG_PREEMPT
++ current->preempt_disable_ip = ip;
++#endif
++ trace_preempt_off(CALLER_ADDR0, ip);
++ }
++}
++
++void preempt_count_add(int val)
++{
++#ifdef CONFIG_DEBUG_PREEMPT
++ /*
++ * Underflow?
++ */
++ if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0)))
++ return;
++#endif
++ __preempt_count_add(val);
++#ifdef CONFIG_DEBUG_PREEMPT
++ /*
++ * Spinlock count overflowing soon?
++ */
++ DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >=
++ PREEMPT_MASK - 10);
++#endif
++ preempt_latency_start(val);
++}
++EXPORT_SYMBOL(preempt_count_add);
++NOKPROBE_SYMBOL(preempt_count_add);
++
++/*
++ * If the value passed in equals to the current preempt count
++ * then we just enabled preemption. Stop timing the latency.
++ */
++static inline void preempt_latency_stop(int val)
++{
++ if (preempt_count() == val)
++ trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip());
++}
++
++void preempt_count_sub(int val)
++{
++#ifdef CONFIG_DEBUG_PREEMPT
++ /*
++ * Underflow?
++ */
++ if (DEBUG_LOCKS_WARN_ON(val > preempt_count()))
++ return;
++ /*
++ * Is the spinlock portion underflowing?
++ */
++ if (DEBUG_LOCKS_WARN_ON((val < PREEMPT_MASK) &&
++ !(preempt_count() & PREEMPT_MASK)))
++ return;
++#endif
++
++ preempt_latency_stop(val);
++ __preempt_count_sub(val);
++}
++EXPORT_SYMBOL(preempt_count_sub);
++NOKPROBE_SYMBOL(preempt_count_sub);
++
++#else
++static inline void preempt_latency_start(int val) { }
++static inline void preempt_latency_stop(int val) { }
++#endif
++
++static inline unsigned long get_preempt_disable_ip(struct task_struct *p)
++{
++#ifdef CONFIG_DEBUG_PREEMPT
++ return p->preempt_disable_ip;
++#else
++ return 0;
++#endif
++}
++
++/*
++ * Print scheduling while atomic bug:
++ */
++static noinline void __schedule_bug(struct task_struct *prev)
++{
++ /* Save this before calling printk(), since that will clobber it */
++ unsigned long preempt_disable_ip = get_preempt_disable_ip(current);
++
++ if (oops_in_progress)
++ return;
++
++ printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n",
++ prev->comm, prev->pid, preempt_count());
++
++ debug_show_held_locks(prev);
++ print_modules();
++ if (irqs_disabled())
++ print_irqtrace_events(prev);
++ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT)) {
++ pr_err("Preemption disabled at:");
++ print_ip_sym(KERN_ERR, preempt_disable_ip);
++ }
++ check_panic_on_warn("scheduling while atomic");
++
++ dump_stack();
++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
++}
++
++/*
++ * Various schedule()-time debugging checks and statistics:
++ */
++static inline void schedule_debug(struct task_struct *prev, bool preempt)
++{
++#ifdef CONFIG_SCHED_STACK_END_CHECK
++ if (task_stack_end_corrupted(prev))
++ panic("corrupted stack end detected inside scheduler\n");
++
++ if (task_scs_end_corrupted(prev))
++ panic("corrupted shadow stack detected inside scheduler\n");
++#endif
++
++#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
++ if (!preempt && READ_ONCE(prev->__state) && prev->non_block_count) {
++ printk(KERN_ERR "BUG: scheduling in a non-blocking section: %s/%d/%i\n",
++ prev->comm, prev->pid, prev->non_block_count);
++ dump_stack();
++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
++ }
++#endif
++
++ if (unlikely(in_atomic_preempt_off())) {
++ __schedule_bug(prev);
++ preempt_count_set(PREEMPT_DISABLED);
++ }
++ rcu_sleep_check();
++ SCHED_WARN_ON(ct_state() == CONTEXT_USER);
++
++ profile_hit(SCHED_PROFILING, __builtin_return_address(0));
++
++ schedstat_inc(this_rq()->sched_count);
++}
++
++#ifdef ALT_SCHED_DEBUG
++void alt_sched_debug(void)
++{
++ printk(KERN_INFO "sched: pending: 0x%04lx, idle: 0x%04lx, sg_idle: 0x%04lx\n",
++ sched_rq_pending_mask.bits[0],
++ sched_idle_mask->bits[0],
++ sched_sg_idle_mask.bits[0]);
++}
++#else
++inline void alt_sched_debug(void) {}
++#endif
++
++#ifdef CONFIG_SMP
++
++#ifdef CONFIG_PREEMPT_RT
++#define SCHED_NR_MIGRATE_BREAK 8
++#else
++#define SCHED_NR_MIGRATE_BREAK 32
++#endif
++
++const_debug unsigned int sysctl_sched_nr_migrate = SCHED_NR_MIGRATE_BREAK;
++
++/*
++ * Migrate pending tasks in @rq to @dest_cpu
++ */
++static inline int
++migrate_pending_tasks(struct rq *rq, struct rq *dest_rq, const int dest_cpu)
++{
++ struct task_struct *p, *skip = rq->curr;
++ int nr_migrated = 0;
++ int nr_tries = min(rq->nr_running / 2, sysctl_sched_nr_migrate);
++
++ /* WA to check rq->curr is still on rq */
++ if (!task_on_rq_queued(skip))
++ return 0;
++
++ while (skip != rq->idle && nr_tries &&
++ (p = sched_rq_next_task(skip, rq)) != rq->idle) {
++ skip = sched_rq_next_task(p, rq);
++ if (cpumask_test_cpu(dest_cpu, p->cpus_ptr)) {
++ __SCHED_DEQUEUE_TASK(p, rq, 0, );
++ set_task_cpu(p, dest_cpu);
++ sched_task_sanity_check(p, dest_rq);
++ sched_mm_cid_migrate_to(dest_rq, p, cpu_of(rq));
++ __SCHED_ENQUEUE_TASK(p, dest_rq, 0, );
++ nr_migrated++;
++ }
++ nr_tries--;
++ }
++
++ return nr_migrated;
++}
++
++static inline int take_other_rq_tasks(struct rq *rq, int cpu)
++{
++ cpumask_t *topo_mask, *end_mask, chk;
++
++ if (unlikely(!rq->online))
++ return 0;
++
++ if (cpumask_empty(&sched_rq_pending_mask))
++ return 0;
++
++ topo_mask = per_cpu(sched_cpu_topo_masks, cpu);
++ end_mask = per_cpu(sched_cpu_topo_end_mask, cpu);
++ do {
++ int i;
++
++ if (!cpumask_and(&chk, &sched_rq_pending_mask, topo_mask))
++ continue;
++
++ for_each_cpu_wrap(i, &chk, cpu) {
++ int nr_migrated;
++ struct rq *src_rq;
++
++ src_rq = cpu_rq(i);
++ if (!do_raw_spin_trylock(&src_rq->lock))
++ continue;
++ spin_acquire(&src_rq->lock.dep_map,
++ SINGLE_DEPTH_NESTING, 1, _RET_IP_);
++
++ if ((nr_migrated = migrate_pending_tasks(src_rq, rq, cpu))) {
++ src_rq->nr_running -= nr_migrated;
++ if (src_rq->nr_running < 2)
++ cpumask_clear_cpu(i, &sched_rq_pending_mask);
++
++ spin_release(&src_rq->lock.dep_map, _RET_IP_);
++ do_raw_spin_unlock(&src_rq->lock);
++
++ rq->nr_running += nr_migrated;
++ if (rq->nr_running > 1)
++ cpumask_set_cpu(cpu, &sched_rq_pending_mask);
++
++ update_sched_preempt_mask(rq);
++ cpufreq_update_util(rq, 0);
++
++ return 1;
++ }
++
++ spin_release(&src_rq->lock.dep_map, _RET_IP_);
++ do_raw_spin_unlock(&src_rq->lock);
++ }
++ } while (++topo_mask < end_mask);
++
++ return 0;
++}
++#endif
++
++static inline void time_slice_expired(struct task_struct *p, struct rq *rq)
++{
++ p->time_slice = sysctl_sched_base_slice;
++
++ sched_task_renew(p, rq);
++
++ if (SCHED_FIFO != p->policy && task_on_rq_queued(p))
++ requeue_task(p, rq);
++}
++
++/*
++ * Timeslices below RESCHED_NS are considered as good as expired as there's no
++ * point rescheduling when there's so little time left.
++ */
++static inline void check_curr(struct task_struct *p, struct rq *rq)
++{
++ if (unlikely(rq->idle == p))
++ return;
++
++ update_curr(rq, p);
++
++ if (p->time_slice < RESCHED_NS)
++ time_slice_expired(p, rq);
++}
++
++static inline struct task_struct *
++choose_next_task(struct rq *rq, int cpu)
++{
++ struct task_struct *next = sched_rq_first_task(rq);
++
++ if (next == rq->idle) {
++#ifdef CONFIG_SMP
++ if (!take_other_rq_tasks(rq, cpu)) {
++#endif
++
++#ifdef CONFIG_SCHED_SMT
++ if (likely(rq->online) &&
++ cpumask_test_cpu(cpu, sched_sg_idle_mask))
++ __queue_balance_callback(rq, &per_cpu(sg_balance_head, cpu));
++#endif
++ schedstat_inc(rq->sched_goidle);
++ /*printk(KERN_INFO "sched: choose_next_task(%d) idle %px\n", cpu, next);*/
++ return next;
++#ifdef CONFIG_SMP
++ }
++ next = sched_rq_first_task(rq);
++#endif
++ }
++#ifdef CONFIG_HIGH_RES_TIMERS
++ hrtick_start(rq, next->time_slice);
++#endif
++ /*printk(KERN_INFO "sched: choose_next_task(%d) next %px\n", cpu, next);*/
++ return next;
++}
++
++/*
++ * Constants for the sched_mode argument of __schedule().
++ *
++ * The mode argument allows RT enabled kernels to differentiate a
++ * preemption from blocking on an 'sleeping' spin/rwlock. Note that
++ * SM_MASK_PREEMPT for !RT has all bits set, which allows the compiler to
++ * optimize the AND operation out and just check for zero.
++ */
++#define SM_NONE 0x0
++#define SM_PREEMPT 0x1
++#define SM_RTLOCK_WAIT 0x2
++
++#ifndef CONFIG_PREEMPT_RT
++# define SM_MASK_PREEMPT (~0U)
++#else
++# define SM_MASK_PREEMPT SM_PREEMPT
++#endif
++
++/*
++ * schedule() is the main scheduler function.
++ *
++ * The main means of driving the scheduler and thus entering this function are:
++ *
++ * 1. Explicit blocking: mutex, semaphore, waitqueue, etc.
++ *
++ * 2. TIF_NEED_RESCHED flag is checked on interrupt and userspace return
++ * paths. For example, see arch/x86/entry_64.S.
++ *
++ * To drive preemption between tasks, the scheduler sets the flag in timer
++ * interrupt handler scheduler_tick().
++ *
++ * 3. Wakeups don't really cause entry into schedule(). They add a
++ * task to the run-queue and that's it.
++ *
++ * Now, if the new task added to the run-queue preempts the current
++ * task, then the wakeup sets TIF_NEED_RESCHED and schedule() gets
++ * called on the nearest possible occasion:
++ *
++ * - If the kernel is preemptible (CONFIG_PREEMPTION=y):
++ *
++ * - in syscall or exception context, at the next outmost
++ * preempt_enable(). (this might be as soon as the wake_up()'s
++ * spin_unlock()!)
++ *
++ * - in IRQ context, return from interrupt-handler to
++ * preemptible context
++ *
++ * - If the kernel is not preemptible (CONFIG_PREEMPTION is not set)
++ * then at the next:
++ *
++ * - cond_resched() call
++ * - explicit schedule() call
++ * - return from syscall or exception to user-space
++ * - return from interrupt-handler to user-space
++ *
++ * WARNING: must be called with preemption disabled!
++ */
++static void __sched notrace __schedule(unsigned int sched_mode)
++{
++ struct task_struct *prev, *next;
++ unsigned long *switch_count;
++ unsigned long prev_state;
++ struct rq *rq;
++ int cpu;
++
++ cpu = smp_processor_id();
++ rq = cpu_rq(cpu);
++ prev = rq->curr;
++
++ schedule_debug(prev, !!sched_mode);
++
++ /* by passing sched_feat(HRTICK) checking which Alt schedule FW doesn't support */
++ hrtick_clear(rq);
++
++ local_irq_disable();
++ rcu_note_context_switch(!!sched_mode);
++
++ /*
++ * Make sure that signal_pending_state()->signal_pending() below
++ * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE)
++ * done by the caller to avoid the race with signal_wake_up():
++ *
++ * __set_current_state(@state) signal_wake_up()
++ * schedule() set_tsk_thread_flag(p, TIF_SIGPENDING)
++ * wake_up_state(p, state)
++ * LOCK rq->lock LOCK p->pi_state
++ * smp_mb__after_spinlock() smp_mb__after_spinlock()
++ * if (signal_pending_state()) if (p->state & @state)
++ *
++ * Also, the membarrier system call requires a full memory barrier
++ * after coming from user-space, before storing to rq->curr.
++ */
++ raw_spin_lock(&rq->lock);
++ smp_mb__after_spinlock();
++
++ update_rq_clock(rq);
++
++ switch_count = &prev->nivcsw;
++ /*
++ * We must load prev->state once (task_struct::state is volatile), such
++ * that we form a control dependency vs deactivate_task() below.
++ */
++ prev_state = READ_ONCE(prev->__state);
++ if (!(sched_mode & SM_MASK_PREEMPT) && prev_state) {
++ if (signal_pending_state(prev_state, prev)) {
++ WRITE_ONCE(prev->__state, TASK_RUNNING);
++ } else {
++ prev->sched_contributes_to_load =
++ (prev_state & TASK_UNINTERRUPTIBLE) &&
++ !(prev_state & TASK_NOLOAD) &&
++ !(prev_state & TASK_FROZEN);
++
++ if (prev->sched_contributes_to_load)
++ rq->nr_uninterruptible++;
++
++ /*
++ * __schedule() ttwu()
++ * prev_state = prev->state; if (p->on_rq && ...)
++ * if (prev_state) goto out;
++ * p->on_rq = 0; smp_acquire__after_ctrl_dep();
++ * p->state = TASK_WAKING
++ *
++ * Where __schedule() and ttwu() have matching control dependencies.
++ *
++ * After this, schedule() must not care about p->state any more.
++ */
++ sched_task_deactivate(prev, rq);
++ deactivate_task(prev, rq);
++
++ if (prev->in_iowait) {
++ atomic_inc(&rq->nr_iowait);
++ delayacct_blkio_start();
++ }
++ }
++ switch_count = &prev->nvcsw;
++ }
++
++ check_curr(prev, rq);
++
++ next = choose_next_task(rq, cpu);
++ clear_tsk_need_resched(prev);
++ clear_preempt_need_resched();
++#ifdef CONFIG_SCHED_DEBUG
++ rq->last_seen_need_resched_ns = 0;
++#endif
++
++ if (likely(prev != next)) {
++#ifdef CONFIG_SCHED_BMQ
++ rq->last_ts_switch = rq->clock;
++#endif
++ next->last_ran = rq->clock_task;
++
++ /*printk(KERN_INFO "sched: %px -> %px\n", prev, next);*/
++ rq->nr_switches++;
++ /*
++ * RCU users of rcu_dereference(rq->curr) may not see
++ * changes to task_struct made by pick_next_task().
++ */
++ RCU_INIT_POINTER(rq->curr, next);
++ /*
++ * The membarrier system call requires each architecture
++ * to have a full memory barrier after updating
++ * rq->curr, before returning to user-space.
++ *
++ * Here are the schemes providing that barrier on the
++ * various architectures:
++ * - mm ? switch_mm() : mmdrop() for x86, s390, sparc, PowerPC.
++ * switch_mm() rely on membarrier_arch_switch_mm() on PowerPC.
++ * - finish_lock_switch() for weakly-ordered
++ * architectures where spin_unlock is a full barrier,
++ * - switch_to() for arm64 (weakly-ordered, spin_unlock
++ * is a RELEASE barrier),
++ */
++ ++*switch_count;
++
++ trace_sched_switch(sched_mode & SM_MASK_PREEMPT, prev, next, prev_state);
++
++ /* Also unlocks the rq: */
++ rq = context_switch(rq, prev, next);
++
++ cpu = cpu_of(rq);
++ } else {
++ __balance_callbacks(rq);
++ raw_spin_unlock_irq(&rq->lock);
++ }
++}
++
++void __noreturn do_task_dead(void)
++{
++ /* Causes final put_task_struct in finish_task_switch(): */
++ set_special_state(TASK_DEAD);
++
++ /* Tell freezer to ignore us: */
++ current->flags |= PF_NOFREEZE;
++
++ __schedule(SM_NONE);
++ BUG();
++
++ /* Avoid "noreturn function does return" - but don't continue if BUG() is a NOP: */
++ for (;;)
++ cpu_relax();
++}
++
++static inline void sched_submit_work(struct task_struct *tsk)
++{
++ static DEFINE_WAIT_OVERRIDE_MAP(sched_map, LD_WAIT_CONFIG);
++ unsigned int task_flags;
++
++ /*
++ * Establish LD_WAIT_CONFIG context to ensure none of the code called
++ * will use a blocking primitive -- which would lead to recursion.
++ */
++ lock_map_acquire_try(&sched_map);
++
++ task_flags = tsk->flags;
++ /*
++ * If a worker goes to sleep, notify and ask workqueue whether it
++ * wants to wake up a task to maintain concurrency.
++ */
++ if (task_flags & PF_WQ_WORKER)
++ wq_worker_sleeping(tsk);
++ else if (task_flags & PF_IO_WORKER)
++ io_wq_worker_sleeping(tsk);
++
++ /*
++ * spinlock and rwlock must not flush block requests. This will
++ * deadlock if the callback attempts to acquire a lock which is
++ * already acquired.
++ */
++ SCHED_WARN_ON(current->__state & TASK_RTLOCK_WAIT);
++
++ /*
++ * If we are going to sleep and we have plugged IO queued,
++ * make sure to submit it to avoid deadlocks.
++ */
++ blk_flush_plug(tsk->plug, true);
++
++ lock_map_release(&sched_map);
++}
++
++static void sched_update_worker(struct task_struct *tsk)
++{
++ if (tsk->flags & (PF_WQ_WORKER | PF_IO_WORKER)) {
++ if (tsk->flags & PF_WQ_WORKER)
++ wq_worker_running(tsk);
++ else
++ io_wq_worker_running(tsk);
++ }
++}
++
++static __always_inline void __schedule_loop(unsigned int sched_mode)
++{
++ do {
++ preempt_disable();
++ __schedule(sched_mode);
++ sched_preempt_enable_no_resched();
++ } while (need_resched());
++}
++
++asmlinkage __visible void __sched schedule(void)
++{
++ struct task_struct *tsk = current;
++
++#ifdef CONFIG_RT_MUTEXES
++ lockdep_assert(!tsk->sched_rt_mutex);
++#endif
++
++ if (!task_is_running(tsk))
++ sched_submit_work(tsk);
++ __schedule_loop(SM_NONE);
++ sched_update_worker(tsk);
++}
++EXPORT_SYMBOL(schedule);
++
++/*
++ * synchronize_rcu_tasks() makes sure that no task is stuck in preempted
++ * state (have scheduled out non-voluntarily) by making sure that all
++ * tasks have either left the run queue or have gone into user space.
++ * As idle tasks do not do either, they must not ever be preempted
++ * (schedule out non-voluntarily).
++ *
++ * schedule_idle() is similar to schedule_preempt_disable() except that it
++ * never enables preemption because it does not call sched_submit_work().
++ */
++void __sched schedule_idle(void)
++{
++ /*
++ * As this skips calling sched_submit_work(), which the idle task does
++ * regardless because that function is a nop when the task is in a
++ * TASK_RUNNING state, make sure this isn't used someplace that the
++ * current task can be in any other state. Note, idle is always in the
++ * TASK_RUNNING state.
++ */
++ WARN_ON_ONCE(current->__state);
++ do {
++ __schedule(SM_NONE);
++ } while (need_resched());
++}
++
++#if defined(CONFIG_CONTEXT_TRACKING_USER) && !defined(CONFIG_HAVE_CONTEXT_TRACKING_USER_OFFSTACK)
++asmlinkage __visible void __sched schedule_user(void)
++{
++ /*
++ * If we come here after a random call to set_need_resched(),
++ * or we have been woken up remotely but the IPI has not yet arrived,
++ * we haven't yet exited the RCU idle mode. Do it here manually until
++ * we find a better solution.
++ *
++ * NB: There are buggy callers of this function. Ideally we
++ * should warn if prev_state != CONTEXT_USER, but that will trigger
++ * too frequently to make sense yet.
++ */
++ enum ctx_state prev_state = exception_enter();
++ schedule();
++ exception_exit(prev_state);
++}
++#endif
++
++/**
++ * schedule_preempt_disabled - called with preemption disabled
++ *
++ * Returns with preemption disabled. Note: preempt_count must be 1
++ */
++void __sched schedule_preempt_disabled(void)
++{
++ sched_preempt_enable_no_resched();
++ schedule();
++ preempt_disable();
++}
++
++#ifdef CONFIG_PREEMPT_RT
++void __sched notrace schedule_rtlock(void)
++{
++ __schedule_loop(SM_RTLOCK_WAIT);
++}
++NOKPROBE_SYMBOL(schedule_rtlock);
++#endif
++
++static void __sched notrace preempt_schedule_common(void)
++{
++ do {
++ /*
++ * Because the function tracer can trace preempt_count_sub()
++ * and it also uses preempt_enable/disable_notrace(), if
++ * NEED_RESCHED is set, the preempt_enable_notrace() called
++ * by the function tracer will call this function again and
++ * cause infinite recursion.
++ *
++ * Preemption must be disabled here before the function
++ * tracer can trace. Break up preempt_disable() into two
++ * calls. One to disable preemption without fear of being
++ * traced. The other to still record the preemption latency,
++ * which can also be traced by the function tracer.
++ */
++ preempt_disable_notrace();
++ preempt_latency_start(1);
++ __schedule(SM_PREEMPT);
++ preempt_latency_stop(1);
++ preempt_enable_no_resched_notrace();
++
++ /*
++ * Check again in case we missed a preemption opportunity
++ * between schedule and now.
++ */
++ } while (need_resched());
++}
++
++#ifdef CONFIG_PREEMPTION
++/*
++ * This is the entry point to schedule() from in-kernel preemption
++ * off of preempt_enable.
++ */
++asmlinkage __visible void __sched notrace preempt_schedule(void)
++{
++ /*
++ * If there is a non-zero preempt_count or interrupts are disabled,
++ * we do not want to preempt the current task. Just return..
++ */
++ if (likely(!preemptible()))
++ return;
++
++ preempt_schedule_common();
++}
++NOKPROBE_SYMBOL(preempt_schedule);
++EXPORT_SYMBOL(preempt_schedule);
++
++#ifdef CONFIG_PREEMPT_DYNAMIC
++#if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
++#ifndef preempt_schedule_dynamic_enabled
++#define preempt_schedule_dynamic_enabled preempt_schedule
++#define preempt_schedule_dynamic_disabled NULL
++#endif
++DEFINE_STATIC_CALL(preempt_schedule, preempt_schedule_dynamic_enabled);
++EXPORT_STATIC_CALL_TRAMP(preempt_schedule);
++#elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
++static DEFINE_STATIC_KEY_TRUE(sk_dynamic_preempt_schedule);
++void __sched notrace dynamic_preempt_schedule(void)
++{
++ if (!static_branch_unlikely(&sk_dynamic_preempt_schedule))
++ return;
++ preempt_schedule();
++}
++NOKPROBE_SYMBOL(dynamic_preempt_schedule);
++EXPORT_SYMBOL(dynamic_preempt_schedule);
++#endif
++#endif
++
++/**
++ * preempt_schedule_notrace - preempt_schedule called by tracing
++ *
++ * The tracing infrastructure uses preempt_enable_notrace to prevent
++ * recursion and tracing preempt enabling caused by the tracing
++ * infrastructure itself. But as tracing can happen in areas coming
++ * from userspace or just about to enter userspace, a preempt enable
++ * can occur before user_exit() is called. This will cause the scheduler
++ * to be called when the system is still in usermode.
++ *
++ * To prevent this, the preempt_enable_notrace will use this function
++ * instead of preempt_schedule() to exit user context if needed before
++ * calling the scheduler.
++ */
++asmlinkage __visible void __sched notrace preempt_schedule_notrace(void)
++{
++ enum ctx_state prev_ctx;
++
++ if (likely(!preemptible()))
++ return;
++
++ do {
++ /*
++ * Because the function tracer can trace preempt_count_sub()
++ * and it also uses preempt_enable/disable_notrace(), if
++ * NEED_RESCHED is set, the preempt_enable_notrace() called
++ * by the function tracer will call this function again and
++ * cause infinite recursion.
++ *
++ * Preemption must be disabled here before the function
++ * tracer can trace. Break up preempt_disable() into two
++ * calls. One to disable preemption without fear of being
++ * traced. The other to still record the preemption latency,
++ * which can also be traced by the function tracer.
++ */
++ preempt_disable_notrace();
++ preempt_latency_start(1);
++ /*
++ * Needs preempt disabled in case user_exit() is traced
++ * and the tracer calls preempt_enable_notrace() causing
++ * an infinite recursion.
++ */
++ prev_ctx = exception_enter();
++ __schedule(SM_PREEMPT);
++ exception_exit(prev_ctx);
++
++ preempt_latency_stop(1);
++ preempt_enable_no_resched_notrace();
++ } while (need_resched());
++}
++EXPORT_SYMBOL_GPL(preempt_schedule_notrace);
++
++#ifdef CONFIG_PREEMPT_DYNAMIC
++#if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
++#ifndef preempt_schedule_notrace_dynamic_enabled
++#define preempt_schedule_notrace_dynamic_enabled preempt_schedule_notrace
++#define preempt_schedule_notrace_dynamic_disabled NULL
++#endif
++DEFINE_STATIC_CALL(preempt_schedule_notrace, preempt_schedule_notrace_dynamic_enabled);
++EXPORT_STATIC_CALL_TRAMP(preempt_schedule_notrace);
++#elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
++static DEFINE_STATIC_KEY_TRUE(sk_dynamic_preempt_schedule_notrace);
++void __sched notrace dynamic_preempt_schedule_notrace(void)
++{
++ if (!static_branch_unlikely(&sk_dynamic_preempt_schedule_notrace))
++ return;
++ preempt_schedule_notrace();
++}
++NOKPROBE_SYMBOL(dynamic_preempt_schedule_notrace);
++EXPORT_SYMBOL(dynamic_preempt_schedule_notrace);
++#endif
++#endif
++
++#endif /* CONFIG_PREEMPTION */
++
++/*
++ * This is the entry point to schedule() from kernel preemption
++ * off of irq context.
++ * Note, that this is called and return with irqs disabled. This will
++ * protect us against recursive calling from irq.
++ */
++asmlinkage __visible void __sched preempt_schedule_irq(void)
++{
++ enum ctx_state prev_state;
++
++ /* Catch callers which need to be fixed */
++ BUG_ON(preempt_count() || !irqs_disabled());
++
++ prev_state = exception_enter();
++
++ do {
++ preempt_disable();
++ local_irq_enable();
++ __schedule(SM_PREEMPT);
++ local_irq_disable();
++ sched_preempt_enable_no_resched();
++ } while (need_resched());
++
++ exception_exit(prev_state);
++}
++
++int default_wake_function(wait_queue_entry_t *curr, unsigned mode, int wake_flags,
++ void *key)
++{
++ WARN_ON_ONCE(IS_ENABLED(CONFIG_SCHED_DEBUG) && wake_flags & ~(WF_SYNC|WF_CURRENT_CPU));
++ return try_to_wake_up(curr->private, mode, wake_flags);
++}
++EXPORT_SYMBOL(default_wake_function);
++
++static inline void check_task_changed(struct task_struct *p, struct rq *rq)
++{
++ /* Trigger resched if task sched_prio has been modified. */
++ if (task_on_rq_queued(p)) {
++ update_rq_clock(rq);
++ requeue_task(p, rq);
++ wakeup_preempt(rq);
++ }
++}
++
++static void __setscheduler_prio(struct task_struct *p, int prio)
++{
++ p->prio = prio;
++}
++
++#ifdef CONFIG_RT_MUTEXES
++
++/*
++ * Would be more useful with typeof()/auto_type but they don't mix with
++ * bit-fields. Since it's a local thing, use int. Keep the generic sounding
++ * name such that if someone were to implement this function we get to compare
++ * notes.
++ */
++#define fetch_and_set(x, v) ({ int _x = (x); (x) = (v); _x; })
++
++void rt_mutex_pre_schedule(void)
++{
++ lockdep_assert(!fetch_and_set(current->sched_rt_mutex, 1));
++ sched_submit_work(current);
++}
++
++void rt_mutex_schedule(void)
++{
++ lockdep_assert(current->sched_rt_mutex);
++ __schedule_loop(SM_NONE);
++}
++
++void rt_mutex_post_schedule(void)
++{
++ sched_update_worker(current);
++ lockdep_assert(fetch_and_set(current->sched_rt_mutex, 0));
++}
++
++static inline int __rt_effective_prio(struct task_struct *pi_task, int prio)
++{
++ if (pi_task)
++ prio = min(prio, pi_task->prio);
++
++ return prio;
++}
++
++static inline int rt_effective_prio(struct task_struct *p, int prio)
++{
++ struct task_struct *pi_task = rt_mutex_get_top_task(p);
++
++ return __rt_effective_prio(pi_task, prio);
++}
++
++/*
++ * rt_mutex_setprio - set the current priority of a task
++ * @p: task to boost
++ * @pi_task: donor task
++ *
++ * This function changes the 'effective' priority of a task. It does
++ * not touch ->normal_prio like __setscheduler().
++ *
++ * Used by the rt_mutex code to implement priority inheritance
++ * logic. Call site only calls if the priority of the task changed.
++ */
++void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task)
++{
++ int prio;
++ struct rq *rq;
++ raw_spinlock_t *lock;
++
++ /* XXX used to be waiter->prio, not waiter->task->prio */
++ prio = __rt_effective_prio(pi_task, p->normal_prio);
++
++ /*
++ * If nothing changed; bail early.
++ */
++ if (p->pi_top_task == pi_task && prio == p->prio)
++ return;
++
++ rq = __task_access_lock(p, &lock);
++ /*
++ * Set under pi_lock && rq->lock, such that the value can be used under
++ * either lock.
++ *
++ * Note that there is loads of tricky to make this pointer cache work
++ * right. rt_mutex_slowunlock()+rt_mutex_postunlock() work together to
++ * ensure a task is de-boosted (pi_task is set to NULL) before the
++ * task is allowed to run again (and can exit). This ensures the pointer
++ * points to a blocked task -- which guarantees the task is present.
++ */
++ p->pi_top_task = pi_task;
++
++ /*
++ * For FIFO/RR we only need to set prio, if that matches we're done.
++ */
++ if (prio == p->prio)
++ goto out_unlock;
++
++ /*
++ * Idle task boosting is a nono in general. There is one
++ * exception, when PREEMPT_RT and NOHZ is active:
++ *
++ * The idle task calls get_next_timer_interrupt() and holds
++ * the timer wheel base->lock on the CPU and another CPU wants
++ * to access the timer (probably to cancel it). We can safely
++ * ignore the boosting request, as the idle CPU runs this code
++ * with interrupts disabled and will complete the lock
++ * protected section without being interrupted. So there is no
++ * real need to boost.
++ */
++ if (unlikely(p == rq->idle)) {
++ WARN_ON(p != rq->curr);
++ WARN_ON(p->pi_blocked_on);
++ goto out_unlock;
++ }
++
++ trace_sched_pi_setprio(p, pi_task);
++
++ __setscheduler_prio(p, prio);
++
++ check_task_changed(p, rq);
++out_unlock:
++ /* Avoid rq from going away on us: */
++ preempt_disable();
++
++ __balance_callbacks(rq);
++ __task_access_unlock(p, lock);
++
++ preempt_enable();
++}
++#else
++static inline int rt_effective_prio(struct task_struct *p, int prio)
++{
++ return prio;
++}
++#endif
++
++void set_user_nice(struct task_struct *p, long nice)
++{
++ unsigned long flags;
++ struct rq *rq;
++ raw_spinlock_t *lock;
++
++ if (task_nice(p) == nice || nice < MIN_NICE || nice > MAX_NICE)
++ return;
++ /*
++ * We have to be careful, if called from sys_setpriority(),
++ * the task might be in the middle of scheduling on another CPU.
++ */
++ raw_spin_lock_irqsave(&p->pi_lock, flags);
++ rq = __task_access_lock(p, &lock);
++
++ p->static_prio = NICE_TO_PRIO(nice);
++ /*
++ * The RT priorities are set via sched_setscheduler(), but we still
++ * allow the 'normal' nice value to be set - but as expected
++ * it won't have any effect on scheduling until the task is
++ * not SCHED_NORMAL/SCHED_BATCH:
++ */
++ if (task_has_rt_policy(p))
++ goto out_unlock;
++
++ p->prio = effective_prio(p);
++
++ check_task_changed(p, rq);
++out_unlock:
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++}
++EXPORT_SYMBOL(set_user_nice);
++
++/*
++ * is_nice_reduction - check if nice value is an actual reduction
++ *
++ * Similar to can_nice() but does not perform a capability check.
++ *
++ * @p: task
++ * @nice: nice value
++ */
++static bool is_nice_reduction(const struct task_struct *p, const int nice)
++{
++ /* Convert nice value [19,-20] to rlimit style value [1,40]: */
++ int nice_rlim = nice_to_rlimit(nice);
++
++ return (nice_rlim <= task_rlimit(p, RLIMIT_NICE));
++}
++
++/*
++ * can_nice - check if a task can reduce its nice value
++ * @p: task
++ * @nice: nice value
++ */
++int can_nice(const struct task_struct *p, const int nice)
++{
++ return is_nice_reduction(p, nice) || capable(CAP_SYS_NICE);
++}
++
++#ifdef __ARCH_WANT_SYS_NICE
++
++/*
++ * sys_nice - change the priority of the current process.
++ * @increment: priority increment
++ *
++ * sys_setpriority is a more generic, but much slower function that
++ * does similar things.
++ */
++SYSCALL_DEFINE1(nice, int, increment)
++{
++ long nice, retval;
++
++ /*
++ * Setpriority might change our priority at the same moment.
++ * We don't have to worry. Conceptually one call occurs first
++ * and we have a single winner.
++ */
++
++ increment = clamp(increment, -NICE_WIDTH, NICE_WIDTH);
++ nice = task_nice(current) + increment;
++
++ nice = clamp_val(nice, MIN_NICE, MAX_NICE);
++ if (increment < 0 && !can_nice(current, nice))
++ return -EPERM;
++
++ retval = security_task_setnice(current, nice);
++ if (retval)
++ return retval;
++
++ set_user_nice(current, nice);
++ return 0;
++}
++
++#endif
++
++/**
++ * task_prio - return the priority value of a given task.
++ * @p: the task in question.
++ *
++ * Return: The priority value as seen by users in /proc.
++ *
++ * sched policy return value kernel prio user prio/nice
++ *
++ * (BMQ)normal, batch, idle[0 ... 53] [100 ... 139] 0/[-20 ... 19]/[-7 ... 7]
++ * (PDS)normal, batch, idle[0 ... 39] 100 0/[-20 ... 19]
++ * fifo, rr [-1 ... -100] [99 ... 0] [0 ... 99]
++ */
++int task_prio(const struct task_struct *p)
++{
++ return (p->prio < MAX_RT_PRIO) ? p->prio - MAX_RT_PRIO :
++ task_sched_prio_normal(p, task_rq(p));
++}
++
++/**
++ * idle_cpu - is a given CPU idle currently?
++ * @cpu: the processor in question.
++ *
++ * Return: 1 if the CPU is currently idle. 0 otherwise.
++ */
++int idle_cpu(int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ if (rq->curr != rq->idle)
++ return 0;
++
++ if (rq->nr_running)
++ return 0;
++
++#ifdef CONFIG_SMP
++ if (rq->ttwu_pending)
++ return 0;
++#endif
++
++ return 1;
++}
++
++/**
++ * idle_task - return the idle task for a given CPU.
++ * @cpu: the processor in question.
++ *
++ * Return: The idle task for the cpu @cpu.
++ */
++struct task_struct *idle_task(int cpu)
++{
++ return cpu_rq(cpu)->idle;
++}
++
++/**
++ * find_process_by_pid - find a process with a matching PID value.
++ * @pid: the pid in question.
++ *
++ * The task of @pid, if found. %NULL otherwise.
++ */
++static inline struct task_struct *find_process_by_pid(pid_t pid)
++{
++ return pid ? find_task_by_vpid(pid) : current;
++}
++
++static struct task_struct *find_get_task(pid_t pid)
++{
++ struct task_struct *p;
++ guard(rcu)();
++
++ p = find_process_by_pid(pid);
++ if (likely(p))
++ get_task_struct(p);
++
++ return p;
++}
++
++DEFINE_CLASS(find_get_task, struct task_struct *, if (_T) put_task_struct(_T),
++ find_get_task(pid), pid_t pid)
++
++/*
++ * sched_setparam() passes in -1 for its policy, to let the functions
++ * it calls know not to change it.
++ */
++#define SETPARAM_POLICY -1
++
++static void __setscheduler_params(struct task_struct *p,
++ const struct sched_attr *attr)
++{
++ int policy = attr->sched_policy;
++
++ if (policy == SETPARAM_POLICY)
++ policy = p->policy;
++
++ p->policy = policy;
++
++ /*
++ * allow normal nice value to be set, but will not have any
++ * effect on scheduling until the task not SCHED_NORMAL/
++ * SCHED_BATCH
++ */
++ p->static_prio = NICE_TO_PRIO(attr->sched_nice);
++
++ /*
++ * __sched_setscheduler() ensures attr->sched_priority == 0 when
++ * !rt_policy. Always setting this ensures that things like
++ * getparam()/getattr() don't report silly values for !rt tasks.
++ */
++ p->rt_priority = attr->sched_priority;
++ p->normal_prio = normal_prio(p);
++}
++
++/*
++ * check the target process has a UID that matches the current process's
++ */
++static bool check_same_owner(struct task_struct *p)
++{
++ const struct cred *cred = current_cred(), *pcred;
++ guard(rcu)();
++
++ pcred = __task_cred(p);
++ return (uid_eq(cred->euid, pcred->euid) ||
++ uid_eq(cred->euid, pcred->uid));
++}
++
++/*
++ * Allow unprivileged RT tasks to decrease priority.
++ * Only issue a capable test if needed and only once to avoid an audit
++ * event on permitted non-privileged operations:
++ */
++static int user_check_sched_setscheduler(struct task_struct *p,
++ const struct sched_attr *attr,
++ int policy, int reset_on_fork)
++{
++ if (rt_policy(policy)) {
++ unsigned long rlim_rtprio = task_rlimit(p, RLIMIT_RTPRIO);
++
++ /* Can't set/change the rt policy: */
++ if (policy != p->policy && !rlim_rtprio)
++ goto req_priv;
++
++ /* Can't increase priority: */
++ if (attr->sched_priority > p->rt_priority &&
++ attr->sched_priority > rlim_rtprio)
++ goto req_priv;
++ }
++
++ /* Can't change other user's priorities: */
++ if (!check_same_owner(p))
++ goto req_priv;
++
++ /* Normal users shall not reset the sched_reset_on_fork flag: */
++ if (p->sched_reset_on_fork && !reset_on_fork)
++ goto req_priv;
++
++ return 0;
++
++req_priv:
++ if (!capable(CAP_SYS_NICE))
++ return -EPERM;
++
++ return 0;
++}
++
++static int __sched_setscheduler(struct task_struct *p,
++ const struct sched_attr *attr,
++ bool user, bool pi)
++{
++ const struct sched_attr dl_squash_attr = {
++ .size = sizeof(struct sched_attr),
++ .sched_policy = SCHED_FIFO,
++ .sched_nice = 0,
++ .sched_priority = 99,
++ };
++ int oldpolicy = -1, policy = attr->sched_policy;
++ int retval, newprio;
++ struct balance_callback *head;
++ unsigned long flags;
++ struct rq *rq;
++ int reset_on_fork;
++ raw_spinlock_t *lock;
++
++ /* The pi code expects interrupts enabled */
++ BUG_ON(pi && in_interrupt());
++
++ /*
++ * Alt schedule FW supports SCHED_DEADLINE by squash it as prio 0 SCHED_FIFO
++ */
++ if (unlikely(SCHED_DEADLINE == policy)) {
++ attr = &dl_squash_attr;
++ policy = attr->sched_policy;
++ }
++recheck:
++ /* Double check policy once rq lock held */
++ if (policy < 0) {
++ reset_on_fork = p->sched_reset_on_fork;
++ policy = oldpolicy = p->policy;
++ } else {
++ reset_on_fork = !!(attr->sched_flags & SCHED_RESET_ON_FORK);
++
++ if (policy > SCHED_IDLE)
++ return -EINVAL;
++ }
++
++ if (attr->sched_flags & ~(SCHED_FLAG_ALL))
++ return -EINVAL;
++
++ /*
++ * Valid priorities for SCHED_FIFO and SCHED_RR are
++ * 1..MAX_RT_PRIO-1, valid priority for SCHED_NORMAL and
++ * SCHED_BATCH and SCHED_IDLE is 0.
++ */
++ if (attr->sched_priority < 0 ||
++ (p->mm && attr->sched_priority > MAX_RT_PRIO - 1) ||
++ (!p->mm && attr->sched_priority > MAX_RT_PRIO - 1))
++ return -EINVAL;
++ if ((SCHED_RR == policy || SCHED_FIFO == policy) !=
++ (attr->sched_priority != 0))
++ return -EINVAL;
++
++ if (user) {
++ retval = user_check_sched_setscheduler(p, attr, policy, reset_on_fork);
++ if (retval)
++ return retval;
++
++ retval = security_task_setscheduler(p);
++ if (retval)
++ return retval;
++ }
++
++ /*
++ * Make sure no PI-waiters arrive (or leave) while we are
++ * changing the priority of the task:
++ */
++ raw_spin_lock_irqsave(&p->pi_lock, flags);
++
++ /*
++ * To be able to change p->policy safely, task_access_lock()
++ * must be called.
++ * IF use task_access_lock() here:
++ * For the task p which is not running, reading rq->stop is
++ * racy but acceptable as ->stop doesn't change much.
++ * An enhancemnet can be made to read rq->stop saftly.
++ */
++ rq = __task_access_lock(p, &lock);
++
++ /*
++ * Changing the policy of the stop threads its a very bad idea
++ */
++ if (p == rq->stop) {
++ retval = -EINVAL;
++ goto unlock;
++ }
++
++ /*
++ * If not changing anything there's no need to proceed further:
++ */
++ if (unlikely(policy == p->policy)) {
++ if (rt_policy(policy) && attr->sched_priority != p->rt_priority)
++ goto change;
++ if (!rt_policy(policy) &&
++ NICE_TO_PRIO(attr->sched_nice) != p->static_prio)
++ goto change;
++
++ p->sched_reset_on_fork = reset_on_fork;
++ retval = 0;
++ goto unlock;
++ }
++change:
++
++ /* Re-check policy now with rq lock held */
++ if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
++ policy = oldpolicy = -1;
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++ goto recheck;
++ }
++
++ p->sched_reset_on_fork = reset_on_fork;
++
++ newprio = __normal_prio(policy, attr->sched_priority, NICE_TO_PRIO(attr->sched_nice));
++ if (pi) {
++ /*
++ * Take priority boosted tasks into account. If the new
++ * effective priority is unchanged, we just store the new
++ * normal parameters and do not touch the scheduler class and
++ * the runqueue. This will be done when the task deboost
++ * itself.
++ */
++ newprio = rt_effective_prio(p, newprio);
++ }
++
++ if (!(attr->sched_flags & SCHED_FLAG_KEEP_PARAMS)) {
++ __setscheduler_params(p, attr);
++ __setscheduler_prio(p, newprio);
++ }
++
++ check_task_changed(p, rq);
++
++ /* Avoid rq from going away on us: */
++ preempt_disable();
++ head = splice_balance_callbacks(rq);
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++
++ if (pi)
++ rt_mutex_adjust_pi(p);
++
++ /* Run balance callbacks after we've adjusted the PI chain: */
++ balance_callbacks(rq, head);
++ preempt_enable();
++
++ return 0;
++
++unlock:
++ __task_access_unlock(p, lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
++ return retval;
++}
++
++static int _sched_setscheduler(struct task_struct *p, int policy,
++ const struct sched_param *param, bool check)
++{
++ struct sched_attr attr = {
++ .sched_policy = policy,
++ .sched_priority = param->sched_priority,
++ .sched_nice = PRIO_TO_NICE(p->static_prio),
++ };
++
++ /* Fixup the legacy SCHED_RESET_ON_FORK hack. */
++ if ((policy != SETPARAM_POLICY) && (policy & SCHED_RESET_ON_FORK)) {
++ attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
++ policy &= ~SCHED_RESET_ON_FORK;
++ attr.sched_policy = policy;
++ }
++
++ return __sched_setscheduler(p, &attr, check, true);
++}
++
++/**
++ * sched_setscheduler - change the scheduling policy and/or RT priority of a thread.
++ * @p: the task in question.
++ * @policy: new policy.
++ * @param: structure containing the new RT priority.
++ *
++ * Use sched_set_fifo(), read its comment.
++ *
++ * Return: 0 on success. An error code otherwise.
++ *
++ * NOTE that the task may be already dead.
++ */
++int sched_setscheduler(struct task_struct *p, int policy,
++ const struct sched_param *param)
++{
++ return _sched_setscheduler(p, policy, param, true);
++}
++
++int sched_setattr(struct task_struct *p, const struct sched_attr *attr)
++{
++ return __sched_setscheduler(p, attr, true, true);
++}
++
++int sched_setattr_nocheck(struct task_struct *p, const struct sched_attr *attr)
++{
++ return __sched_setscheduler(p, attr, false, true);
++}
++EXPORT_SYMBOL_GPL(sched_setattr_nocheck);
++
++/**
++ * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace.
++ * @p: the task in question.
++ * @policy: new policy.
++ * @param: structure containing the new RT priority.
++ *
++ * Just like sched_setscheduler, only don't bother checking if the
++ * current context has permission. For example, this is needed in
++ * stop_machine(): we create temporary high priority worker threads,
++ * but our caller might not have that capability.
++ *
++ * Return: 0 on success. An error code otherwise.
++ */
++int sched_setscheduler_nocheck(struct task_struct *p, int policy,
++ const struct sched_param *param)
++{
++ return _sched_setscheduler(p, policy, param, false);
++}
++
++/*
++ * SCHED_FIFO is a broken scheduler model; that is, it is fundamentally
++ * incapable of resource management, which is the one thing an OS really should
++ * be doing.
++ *
++ * This is of course the reason it is limited to privileged users only.
++ *
++ * Worse still; it is fundamentally impossible to compose static priority
++ * workloads. You cannot take two correctly working static prio workloads
++ * and smash them together and still expect them to work.
++ *
++ * For this reason 'all' FIFO tasks the kernel creates are basically at:
++ *
++ * MAX_RT_PRIO / 2
++ *
++ * The administrator _MUST_ configure the system, the kernel simply doesn't
++ * know enough information to make a sensible choice.
++ */
++void sched_set_fifo(struct task_struct *p)
++{
++ struct sched_param sp = { .sched_priority = MAX_RT_PRIO / 2 };
++ WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0);
++}
++EXPORT_SYMBOL_GPL(sched_set_fifo);
++
++/*
++ * For when you don't much care about FIFO, but want to be above SCHED_NORMAL.
++ */
++void sched_set_fifo_low(struct task_struct *p)
++{
++ struct sched_param sp = { .sched_priority = 1 };
++ WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0);
++}
++EXPORT_SYMBOL_GPL(sched_set_fifo_low);
++
++void sched_set_normal(struct task_struct *p, int nice)
++{
++ struct sched_attr attr = {
++ .sched_policy = SCHED_NORMAL,
++ .sched_nice = nice,
++ };
++ WARN_ON_ONCE(sched_setattr_nocheck(p, &attr) != 0);
++}
++EXPORT_SYMBOL_GPL(sched_set_normal);
++
++static int
++do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
++{
++ struct sched_param lparam;
++
++ if (!param || pid < 0)
++ return -EINVAL;
++ if (copy_from_user(&lparam, param, sizeof(struct sched_param)))
++ return -EFAULT;
++
++ CLASS(find_get_task, p)(pid);
++ if (!p)
++ return -ESRCH;
++
++ return sched_setscheduler(p, policy, &lparam);
++}
++
++/*
++ * Mimics kernel/events/core.c perf_copy_attr().
++ */
++static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *attr)
++{
++ u32 size;
++ int ret;
++
++ /* Zero the full structure, so that a short copy will be nice: */
++ memset(attr, 0, sizeof(*attr));
++
++ ret = get_user(size, &uattr->size);
++ if (ret)
++ return ret;
++
++ /* ABI compatibility quirk: */
++ if (!size)
++ size = SCHED_ATTR_SIZE_VER0;
++
++ if (size < SCHED_ATTR_SIZE_VER0 || size > PAGE_SIZE)
++ goto err_size;
++
++ ret = copy_struct_from_user(attr, sizeof(*attr), uattr, size);
++ if (ret) {
++ if (ret == -E2BIG)
++ goto err_size;
++ return ret;
++ }
++
++ /*
++ * XXX: Do we want to be lenient like existing syscalls; or do we want
++ * to be strict and return an error on out-of-bounds values?
++ */
++ attr->sched_nice = clamp(attr->sched_nice, -20, 19);
++
++ /* sched/core.c uses zero here but we already know ret is zero */
++ return 0;
++
++err_size:
++ put_user(sizeof(*attr), &uattr->size);
++ return -E2BIG;
++}
++
++/**
++ * sys_sched_setscheduler - set/change the scheduler policy and RT priority
++ * @pid: the pid in question.
++ * @policy: new policy.
++ *
++ * Return: 0 on success. An error code otherwise.
++ * @param: structure containing the new RT priority.
++ */
++SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param)
++{
++ if (policy < 0)
++ return -EINVAL;
++
++ return do_sched_setscheduler(pid, policy, param);
++}
++
++/**
++ * sys_sched_setparam - set/change the RT priority of a thread
++ * @pid: the pid in question.
++ * @param: structure containing the new RT priority.
++ *
++ * Return: 0 on success. An error code otherwise.
++ */
++SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
++{
++ return do_sched_setscheduler(pid, SETPARAM_POLICY, param);
++}
++
++static void get_params(struct task_struct *p, struct sched_attr *attr)
++{
++ if (task_has_rt_policy(p))
++ attr->sched_priority = p->rt_priority;
++ else
++ attr->sched_nice = task_nice(p);
++}
++
++/**
++ * sys_sched_setattr - same as above, but with extended sched_attr
++ * @pid: the pid in question.
++ * @uattr: structure containing the extended parameters.
++ */
++SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr,
++ unsigned int, flags)
++{
++ struct sched_attr attr;
++ int retval;
++
++ if (!uattr || pid < 0 || flags)
++ return -EINVAL;
++
++ retval = sched_copy_attr(uattr, &attr);
++ if (retval)
++ return retval;
++
++ if ((int)attr.sched_policy < 0)
++ return -EINVAL;
++
++ CLASS(find_get_task, p)(pid);
++ if (!p)
++ return -ESRCH;
++
++ if (attr.sched_flags & SCHED_FLAG_KEEP_PARAMS)
++ get_params(p, &attr);
++
++ return sched_setattr(p, &attr);
++}
++
++/**
++ * sys_sched_getscheduler - get the policy (scheduling class) of a thread
++ * @pid: the pid in question.
++ *
++ * Return: On success, the policy of the thread. Otherwise, a negative error
++ * code.
++ */
++SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
++{
++ struct task_struct *p;
++ int retval = -EINVAL;
++
++ if (pid < 0)
++ return -ESRCH;
++
++ guard(rcu)();
++ p = find_process_by_pid(pid);
++ if (!p)
++ return -ESRCH;
++
++ retval = security_task_getscheduler(p);
++ if (!retval)
++ retval = p->policy;
++
++ return retval;
++}
++
++/**
++ * sys_sched_getscheduler - get the RT priority of a thread
++ * @pid: the pid in question.
++ * @param: structure containing the RT priority.
++ *
++ * Return: On success, 0 and the RT priority is in @param. Otherwise, an error
++ * code.
++ */
++SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
++{
++ struct sched_param lp = { .sched_priority = 0 };
++ struct task_struct *p;
++
++ if (!param || pid < 0)
++ return -EINVAL;
++
++ scoped_guard (rcu) {
++ int retval;
++
++ p = find_process_by_pid(pid);
++ if (!p)
++ return -EINVAL;
++
++ retval = security_task_getscheduler(p);
++ if (retval)
++ return retval;
++
++ if (task_has_rt_policy(p))
++ lp.sched_priority = p->rt_priority;
++ }
++
++ /*
++ * This one might sleep, we cannot do it with a spinlock held ...
++ */
++ return copy_to_user(param, &lp, sizeof(*param)) ? -EFAULT : 0;
++}
++
++/*
++ * Copy the kernel size attribute structure (which might be larger
++ * than what user-space knows about) to user-space.
++ *
++ * Note that all cases are valid: user-space buffer can be larger or
++ * smaller than the kernel-space buffer. The usual case is that both
++ * have the same size.
++ */
++static int
++sched_attr_copy_to_user(struct sched_attr __user *uattr,
++ struct sched_attr *kattr,
++ unsigned int usize)
++{
++ unsigned int ksize = sizeof(*kattr);
++
++ if (!access_ok(uattr, usize))
++ return -EFAULT;
++
++ /*
++ * sched_getattr() ABI forwards and backwards compatibility:
++ *
++ * If usize == ksize then we just copy everything to user-space and all is good.
++ *
++ * If usize < ksize then we only copy as much as user-space has space for,
++ * this keeps ABI compatibility as well. We skip the rest.
++ *
++ * If usize > ksize then user-space is using a newer version of the ABI,
++ * which part the kernel doesn't know about. Just ignore it - tooling can
++ * detect the kernel's knowledge of attributes from the attr->size value
++ * which is set to ksize in this case.
++ */
++ kattr->size = min(usize, ksize);
++
++ if (copy_to_user(uattr, kattr, kattr->size))
++ return -EFAULT;
++
++ return 0;
++}
++
++/**
++ * sys_sched_getattr - similar to sched_getparam, but with sched_attr
++ * @pid: the pid in question.
++ * @uattr: structure containing the extended parameters.
++ * @usize: sizeof(attr) for fwd/bwd comp.
++ * @flags: for future extension.
++ */
++SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
++ unsigned int, usize, unsigned int, flags)
++{
++ struct sched_attr kattr = { };
++ struct task_struct *p;
++ int retval;
++
++ if (!uattr || pid < 0 || usize > PAGE_SIZE ||
++ usize < SCHED_ATTR_SIZE_VER0 || flags)
++ return -EINVAL;
++
++ scoped_guard (rcu) {
++ p = find_process_by_pid(pid);
++ if (!p)
++ return -ESRCH;
++
++ retval = security_task_getscheduler(p);
++ if (retval)
++ return retval;
++
++ kattr.sched_policy = p->policy;
++ if (p->sched_reset_on_fork)
++ kattr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
++ get_params(p, &kattr);
++ kattr.sched_flags &= SCHED_FLAG_ALL;
++
++#ifdef CONFIG_UCLAMP_TASK
++ kattr.sched_util_min = p->uclamp_req[UCLAMP_MIN].value;
++ kattr.sched_util_max = p->uclamp_req[UCLAMP_MAX].value;
++#endif
++ }
++
++ return sched_attr_copy_to_user(uattr, &kattr, usize);
++}
++
++#ifdef CONFIG_SMP
++int dl_task_check_affinity(struct task_struct *p, const struct cpumask *mask)
++{
++ return 0;
++}
++#endif
++
++static int
++__sched_setaffinity(struct task_struct *p, struct affinity_context *ctx)
++{
++ int retval;
++ cpumask_var_t cpus_allowed, new_mask;
++
++ if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL))
++ return -ENOMEM;
++
++ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) {
++ retval = -ENOMEM;
++ goto out_free_cpus_allowed;
++ }
++
++ cpuset_cpus_allowed(p, cpus_allowed);
++ cpumask_and(new_mask, ctx->new_mask, cpus_allowed);
++
++ ctx->new_mask = new_mask;
++ ctx->flags |= SCA_CHECK;
++
++ retval = __set_cpus_allowed_ptr(p, ctx);
++ if (retval)
++ goto out_free_new_mask;
++
++ cpuset_cpus_allowed(p, cpus_allowed);
++ if (!cpumask_subset(new_mask, cpus_allowed)) {
++ /*
++ * We must have raced with a concurrent cpuset
++ * update. Just reset the cpus_allowed to the
++ * cpuset's cpus_allowed
++ */
++ cpumask_copy(new_mask, cpus_allowed);
++
++ /*
++ * If SCA_USER is set, a 2nd call to __set_cpus_allowed_ptr()
++ * will restore the previous user_cpus_ptr value.
++ *
++ * In the unlikely event a previous user_cpus_ptr exists,
++ * we need to further restrict the mask to what is allowed
++ * by that old user_cpus_ptr.
++ */
++ if (unlikely((ctx->flags & SCA_USER) && ctx->user_mask)) {
++ bool empty = !cpumask_and(new_mask, new_mask,
++ ctx->user_mask);
++
++ if (WARN_ON_ONCE(empty))
++ cpumask_copy(new_mask, cpus_allowed);
++ }
++ __set_cpus_allowed_ptr(p, ctx);
++ retval = -EINVAL;
++ }
++
++out_free_new_mask:
++ free_cpumask_var(new_mask);
++out_free_cpus_allowed:
++ free_cpumask_var(cpus_allowed);
++ return retval;
++}
++
++long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
++{
++ struct affinity_context ac;
++ struct cpumask *user_mask;
++ int retval;
++
++ CLASS(find_get_task, p)(pid);
++ if (!p)
++ return -ESRCH;
++
++ if (p->flags & PF_NO_SETAFFINITY)
++ return -EINVAL;
++
++ if (!check_same_owner(p)) {
++ guard(rcu)();
++ if (!ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE))
++ return -EPERM;
++ }
++
++ retval = security_task_setscheduler(p);
++ if (retval)
++ return retval;
++
++ /*
++ * With non-SMP configs, user_cpus_ptr/user_mask isn't used and
++ * alloc_user_cpus_ptr() returns NULL.
++ */
++ user_mask = alloc_user_cpus_ptr(NUMA_NO_NODE);
++ if (user_mask) {
++ cpumask_copy(user_mask, in_mask);
++ } else if (IS_ENABLED(CONFIG_SMP)) {
++ return -ENOMEM;
++ }
++
++ ac = (struct affinity_context){
++ .new_mask = in_mask,
++ .user_mask = user_mask,
++ .flags = SCA_USER,
++ };
++
++ retval = __sched_setaffinity(p, &ac);
++ kfree(ac.user_mask);
++
++ return retval;
++}
++
++static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len,
++ struct cpumask *new_mask)
++{
++ if (len < cpumask_size())
++ cpumask_clear(new_mask);
++ else if (len > cpumask_size())
++ len = cpumask_size();
++
++ return copy_from_user(new_mask, user_mask_ptr, len) ? -EFAULT : 0;
++}
++
++/**
++ * sys_sched_setaffinity - set the CPU affinity of a process
++ * @pid: pid of the process
++ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
++ * @user_mask_ptr: user-space pointer to the new CPU mask
++ *
++ * Return: 0 on success. An error code otherwise.
++ */
++SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len,
++ unsigned long __user *, user_mask_ptr)
++{
++ cpumask_var_t new_mask;
++ int retval;
++
++ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL))
++ return -ENOMEM;
++
++ retval = get_user_cpu_mask(user_mask_ptr, len, new_mask);
++ if (retval == 0)
++ retval = sched_setaffinity(pid, new_mask);
++ free_cpumask_var(new_mask);
++ return retval;
++}
++
++long sched_getaffinity(pid_t pid, cpumask_t *mask)
++{
++ struct task_struct *p;
++ int retval;
++
++ guard(rcu)();
++ p = find_process_by_pid(pid);
++ if (!p)
++ return -ESRCH;
++
++ retval = security_task_getscheduler(p);
++ if (retval)
++ return retval;
++
++ guard(raw_spinlock_irqsave)(&p->pi_lock);
++ cpumask_and(mask, &p->cpus_mask, cpu_active_mask);
++
++ return retval;
++}
++
++/**
++ * sys_sched_getaffinity - get the CPU affinity of a process
++ * @pid: pid of the process
++ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
++ * @user_mask_ptr: user-space pointer to hold the current CPU mask
++ *
++ * Return: size of CPU mask copied to user_mask_ptr on success. An
++ * error code otherwise.
++ */
++SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
++ unsigned long __user *, user_mask_ptr)
++{
++ int ret;
++ cpumask_var_t mask;
++
++ if ((len * BITS_PER_BYTE) < nr_cpu_ids)
++ return -EINVAL;
++ if (len & (sizeof(unsigned long)-1))
++ return -EINVAL;
++
++ if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
++ return -ENOMEM;
++
++ ret = sched_getaffinity(pid, mask);
++ if (ret == 0) {
++ unsigned int retlen = min(len, cpumask_size());
++
++ if (copy_to_user(user_mask_ptr, cpumask_bits(mask), retlen))
++ ret = -EFAULT;
++ else
++ ret = retlen;
++ }
++ free_cpumask_var(mask);
++
++ return ret;
++}
++
++static void do_sched_yield(void)
++{
++ struct rq *rq;
++ struct rq_flags rf;
++ struct task_struct *p;
++
++ if (!sched_yield_type)
++ return;
++
++ rq = this_rq_lock_irq(&rf);
++
++ schedstat_inc(rq->yld_count);
++
++ p = current;
++ if (rt_task(p)) {
++ if (task_on_rq_queued(p))
++ requeue_task(p, rq);
++ } else if (rq->nr_running > 1) {
++ do_sched_yield_type_1(p, rq);
++ if (task_on_rq_queued(p))
++ requeue_task(p, rq);
++ }
++
++ preempt_disable();
++ raw_spin_unlock_irq(&rq->lock);
++ sched_preempt_enable_no_resched();
++
++ schedule();
++}
++
++/**
++ * sys_sched_yield - yield the current processor to other threads.
++ *
++ * This function yields the current CPU to other tasks. If there are no
++ * other threads running on this CPU then this function will return.
++ *
++ * Return: 0.
++ */
++SYSCALL_DEFINE0(sched_yield)
++{
++ do_sched_yield();
++ return 0;
++}
++
++#if !defined(CONFIG_PREEMPTION) || defined(CONFIG_PREEMPT_DYNAMIC)
++int __sched __cond_resched(void)
++{
++ if (should_resched(0)) {
++ preempt_schedule_common();
++ return 1;
++ }
++ /*
++ * In preemptible kernels, ->rcu_read_lock_nesting tells the tick
++ * whether the current CPU is in an RCU read-side critical section,
++ * so the tick can report quiescent states even for CPUs looping
++ * in kernel context. In contrast, in non-preemptible kernels,
++ * RCU readers leave no in-memory hints, which means that CPU-bound
++ * processes executing in kernel context might never report an
++ * RCU quiescent state. Therefore, the following code causes
++ * cond_resched() to report a quiescent state, but only when RCU
++ * is in urgent need of one.
++ */
++#ifndef CONFIG_PREEMPT_RCU
++ rcu_all_qs();
++#endif
++ return 0;
++}
++EXPORT_SYMBOL(__cond_resched);
++#endif
++
++#ifdef CONFIG_PREEMPT_DYNAMIC
++#if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
++#define cond_resched_dynamic_enabled __cond_resched
++#define cond_resched_dynamic_disabled ((void *)&__static_call_return0)
++DEFINE_STATIC_CALL_RET0(cond_resched, __cond_resched);
++EXPORT_STATIC_CALL_TRAMP(cond_resched);
++
++#define might_resched_dynamic_enabled __cond_resched
++#define might_resched_dynamic_disabled ((void *)&__static_call_return0)
++DEFINE_STATIC_CALL_RET0(might_resched, __cond_resched);
++EXPORT_STATIC_CALL_TRAMP(might_resched);
++#elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
++static DEFINE_STATIC_KEY_FALSE(sk_dynamic_cond_resched);
++int __sched dynamic_cond_resched(void)
++{
++ klp_sched_try_switch();
++ if (!static_branch_unlikely(&sk_dynamic_cond_resched))
++ return 0;
++ return __cond_resched();
++}
++EXPORT_SYMBOL(dynamic_cond_resched);
++
++static DEFINE_STATIC_KEY_FALSE(sk_dynamic_might_resched);
++int __sched dynamic_might_resched(void)
++{
++ if (!static_branch_unlikely(&sk_dynamic_might_resched))
++ return 0;
++ return __cond_resched();
++}
++EXPORT_SYMBOL(dynamic_might_resched);
++#endif
++#endif
++
++/*
++ * __cond_resched_lock() - if a reschedule is pending, drop the given lock,
++ * call schedule, and on return reacquire the lock.
++ *
++ * This works OK both with and without CONFIG_PREEMPTION. We do strange low-level
++ * operations here to prevent schedule() from being called twice (once via
++ * spin_unlock(), once by hand).
++ */
++int __cond_resched_lock(spinlock_t *lock)
++{
++ int resched = should_resched(PREEMPT_LOCK_OFFSET);
++ int ret = 0;
++
++ lockdep_assert_held(lock);
++
++ if (spin_needbreak(lock) || resched) {
++ spin_unlock(lock);
++ if (!_cond_resched())
++ cpu_relax();
++ ret = 1;
++ spin_lock(lock);
++ }
++ return ret;
++}
++EXPORT_SYMBOL(__cond_resched_lock);
++
++int __cond_resched_rwlock_read(rwlock_t *lock)
++{
++ int resched = should_resched(PREEMPT_LOCK_OFFSET);
++ int ret = 0;
++
++ lockdep_assert_held_read(lock);
++
++ if (rwlock_needbreak(lock) || resched) {
++ read_unlock(lock);
++ if (!_cond_resched())
++ cpu_relax();
++ ret = 1;
++ read_lock(lock);
++ }
++ return ret;
++}
++EXPORT_SYMBOL(__cond_resched_rwlock_read);
++
++int __cond_resched_rwlock_write(rwlock_t *lock)
++{
++ int resched = should_resched(PREEMPT_LOCK_OFFSET);
++ int ret = 0;
++
++ lockdep_assert_held_write(lock);
++
++ if (rwlock_needbreak(lock) || resched) {
++ write_unlock(lock);
++ if (!_cond_resched())
++ cpu_relax();
++ ret = 1;
++ write_lock(lock);
++ }
++ return ret;
++}
++EXPORT_SYMBOL(__cond_resched_rwlock_write);
++
++#ifdef CONFIG_PREEMPT_DYNAMIC
++
++#ifdef CONFIG_GENERIC_ENTRY
++#include <linux/entry-common.h>
++#endif
++
++/*
++ * SC:cond_resched
++ * SC:might_resched
++ * SC:preempt_schedule
++ * SC:preempt_schedule_notrace
++ * SC:irqentry_exit_cond_resched
++ *
++ *
++ * NONE:
++ * cond_resched <- __cond_resched
++ * might_resched <- RET0
++ * preempt_schedule <- NOP
++ * preempt_schedule_notrace <- NOP
++ * irqentry_exit_cond_resched <- NOP
++ *
++ * VOLUNTARY:
++ * cond_resched <- __cond_resched
++ * might_resched <- __cond_resched
++ * preempt_schedule <- NOP
++ * preempt_schedule_notrace <- NOP
++ * irqentry_exit_cond_resched <- NOP
++ *
++ * FULL:
++ * cond_resched <- RET0
++ * might_resched <- RET0
++ * preempt_schedule <- preempt_schedule
++ * preempt_schedule_notrace <- preempt_schedule_notrace
++ * irqentry_exit_cond_resched <- irqentry_exit_cond_resched
++ */
++
++enum {
++ preempt_dynamic_undefined = -1,
++ preempt_dynamic_none,
++ preempt_dynamic_voluntary,
++ preempt_dynamic_full,
++};
++
++int preempt_dynamic_mode = preempt_dynamic_undefined;
++
++int sched_dynamic_mode(const char *str)
++{
++ if (!strcmp(str, "none"))
++ return preempt_dynamic_none;
++
++ if (!strcmp(str, "voluntary"))
++ return preempt_dynamic_voluntary;
++
++ if (!strcmp(str, "full"))
++ return preempt_dynamic_full;
++
++ return -EINVAL;
++}
++
++#if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
++#define preempt_dynamic_enable(f) static_call_update(f, f##_dynamic_enabled)
++#define preempt_dynamic_disable(f) static_call_update(f, f##_dynamic_disabled)
++#elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
++#define preempt_dynamic_enable(f) static_key_enable(&sk_dynamic_##f.key)
++#define preempt_dynamic_disable(f) static_key_disable(&sk_dynamic_##f.key)
++#else
++#error "Unsupported PREEMPT_DYNAMIC mechanism"
++#endif
++
++static DEFINE_MUTEX(sched_dynamic_mutex);
++static bool klp_override;
++
++static void __sched_dynamic_update(int mode)
++{
++ /*
++ * Avoid {NONE,VOLUNTARY} -> FULL transitions from ever ending up in
++ * the ZERO state, which is invalid.
++ */
++ if (!klp_override)
++ preempt_dynamic_enable(cond_resched);
++ preempt_dynamic_enable(cond_resched);
++ preempt_dynamic_enable(might_resched);
++ preempt_dynamic_enable(preempt_schedule);
++ preempt_dynamic_enable(preempt_schedule_notrace);
++ preempt_dynamic_enable(irqentry_exit_cond_resched);
++
++ switch (mode) {
++ case preempt_dynamic_none:
++ if (!klp_override)
++ preempt_dynamic_enable(cond_resched);
++ preempt_dynamic_disable(might_resched);
++ preempt_dynamic_disable(preempt_schedule);
++ preempt_dynamic_disable(preempt_schedule_notrace);
++ preempt_dynamic_disable(irqentry_exit_cond_resched);
++ if (mode != preempt_dynamic_mode)
++ pr_info("Dynamic Preempt: none\n");
++ break;
++
++ case preempt_dynamic_voluntary:
++ if (!klp_override)
++ preempt_dynamic_enable(cond_resched);
++ preempt_dynamic_enable(might_resched);
++ preempt_dynamic_disable(preempt_schedule);
++ preempt_dynamic_disable(preempt_schedule_notrace);
++ preempt_dynamic_disable(irqentry_exit_cond_resched);
++ if (mode != preempt_dynamic_mode)
++ pr_info("Dynamic Preempt: voluntary\n");
++ break;
++
++ case preempt_dynamic_full:
++ if (!klp_override)
++ preempt_dynamic_enable(cond_resched);
++ preempt_dynamic_disable(might_resched);
++ preempt_dynamic_enable(preempt_schedule);
++ preempt_dynamic_enable(preempt_schedule_notrace);
++ preempt_dynamic_enable(irqentry_exit_cond_resched);
++ if (mode != preempt_dynamic_mode)
++ pr_info("Dynamic Preempt: full\n");
++ break;
++ }
++
++ preempt_dynamic_mode = mode;
++}
++
++void sched_dynamic_update(int mode)
++{
++ mutex_lock(&sched_dynamic_mutex);
++ __sched_dynamic_update(mode);
++ mutex_unlock(&sched_dynamic_mutex);
++}
++
++#ifdef CONFIG_HAVE_PREEMPT_DYNAMIC_CALL
++
++static int klp_cond_resched(void)
++{
++ __klp_sched_try_switch();
++ return __cond_resched();
++}
++
++void sched_dynamic_klp_enable(void)
++{
++ mutex_lock(&sched_dynamic_mutex);
++
++ klp_override = true;
++ static_call_update(cond_resched, klp_cond_resched);
++
++ mutex_unlock(&sched_dynamic_mutex);
++}
++
++void sched_dynamic_klp_disable(void)
++{
++ mutex_lock(&sched_dynamic_mutex);
++
++ klp_override = false;
++ __sched_dynamic_update(preempt_dynamic_mode);
++
++ mutex_unlock(&sched_dynamic_mutex);
++}
++
++#endif /* CONFIG_HAVE_PREEMPT_DYNAMIC_CALL */
++
++
++static int __init setup_preempt_mode(char *str)
++{
++ int mode = sched_dynamic_mode(str);
++ if (mode < 0) {
++ pr_warn("Dynamic Preempt: unsupported mode: %s\n", str);
++ return 0;
++ }
++
++ sched_dynamic_update(mode);
++ return 1;
++}
++__setup("preempt=", setup_preempt_mode);
++
++static void __init preempt_dynamic_init(void)
++{
++ if (preempt_dynamic_mode == preempt_dynamic_undefined) {
++ if (IS_ENABLED(CONFIG_PREEMPT_NONE)) {
++ sched_dynamic_update(preempt_dynamic_none);
++ } else if (IS_ENABLED(CONFIG_PREEMPT_VOLUNTARY)) {
++ sched_dynamic_update(preempt_dynamic_voluntary);
++ } else {
++ /* Default static call setting, nothing to do */
++ WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPT));
++ preempt_dynamic_mode = preempt_dynamic_full;
++ pr_info("Dynamic Preempt: full\n");
++ }
++ }
++}
++
++#define PREEMPT_MODEL_ACCESSOR(mode) \
++ bool preempt_model_##mode(void) \
++ { \
++ WARN_ON_ONCE(preempt_dynamic_mode == preempt_dynamic_undefined); \
++ return preempt_dynamic_mode == preempt_dynamic_##mode; \
++ } \
++ EXPORT_SYMBOL_GPL(preempt_model_##mode)
++
++PREEMPT_MODEL_ACCESSOR(none);
++PREEMPT_MODEL_ACCESSOR(voluntary);
++PREEMPT_MODEL_ACCESSOR(full);
++
++#else /* !CONFIG_PREEMPT_DYNAMIC */
++
++static inline void preempt_dynamic_init(void) { }
++
++#endif /* #ifdef CONFIG_PREEMPT_DYNAMIC */
++
++/**
++ * yield - yield the current processor to other threads.
++ *
++ * Do not ever use this function, there's a 99% chance you're doing it wrong.
++ *
++ * The scheduler is at all times free to pick the calling task as the most
++ * eligible task to run, if removing the yield() call from your code breaks
++ * it, it's already broken.
++ *
++ * Typical broken usage is:
++ *
++ * while (!event)
++ * yield();
++ *
++ * where one assumes that yield() will let 'the other' process run that will
++ * make event true. If the current task is a SCHED_FIFO task that will never
++ * happen. Never use yield() as a progress guarantee!!
++ *
++ * If you want to use yield() to wait for something, use wait_event().
++ * If you want to use yield() to be 'nice' for others, use cond_resched().
++ * If you still want to use yield(), do not!
++ */
++void __sched yield(void)
++{
++ set_current_state(TASK_RUNNING);
++ do_sched_yield();
++}
++EXPORT_SYMBOL(yield);
++
++/**
++ * yield_to - yield the current processor to another thread in
++ * your thread group, or accelerate that thread toward the
++ * processor it's on.
++ * @p: target task
++ * @preempt: whether task preemption is allowed or not
++ *
++ * It's the caller's job to ensure that the target task struct
++ * can't go away on us before we can do any checks.
++ *
++ * In Alt schedule FW, yield_to is not supported.
++ *
++ * Return:
++ * true (>0) if we indeed boosted the target task.
++ * false (0) if we failed to boost the target.
++ * -ESRCH if there's no task to yield to.
++ */
++int __sched yield_to(struct task_struct *p, bool preempt)
++{
++ return 0;
++}
++EXPORT_SYMBOL_GPL(yield_to);
++
++int io_schedule_prepare(void)
++{
++ int old_iowait = current->in_iowait;
++
++ current->in_iowait = 1;
++ blk_flush_plug(current->plug, true);
++ return old_iowait;
++}
++
++void io_schedule_finish(int token)
++{
++ current->in_iowait = token;
++}
++
++/*
++ * This task is about to go to sleep on IO. Increment rq->nr_iowait so
++ * that process accounting knows that this is a task in IO wait state.
++ *
++ * But don't do that if it is a deliberate, throttling IO wait (this task
++ * has set its backing_dev_info: the queue against which it should throttle)
++ */
++
++long __sched io_schedule_timeout(long timeout)
++{
++ int token;
++ long ret;
++
++ token = io_schedule_prepare();
++ ret = schedule_timeout(timeout);
++ io_schedule_finish(token);
++
++ return ret;
++}
++EXPORT_SYMBOL(io_schedule_timeout);
++
++void __sched io_schedule(void)
++{
++ int token;
++
++ token = io_schedule_prepare();
++ schedule();
++ io_schedule_finish(token);
++}
++EXPORT_SYMBOL(io_schedule);
++
++/**
++ * sys_sched_get_priority_max - return maximum RT priority.
++ * @policy: scheduling class.
++ *
++ * Return: On success, this syscall returns the maximum
++ * rt_priority that can be used by a given scheduling class.
++ * On failure, a negative error code is returned.
++ */
++SYSCALL_DEFINE1(sched_get_priority_max, int, policy)
++{
++ int ret = -EINVAL;
++
++ switch (policy) {
++ case SCHED_FIFO:
++ case SCHED_RR:
++ ret = MAX_RT_PRIO - 1;
++ break;
++ case SCHED_NORMAL:
++ case SCHED_BATCH:
++ case SCHED_IDLE:
++ ret = 0;
++ break;
++ }
++ return ret;
++}
++
++/**
++ * sys_sched_get_priority_min - return minimum RT priority.
++ * @policy: scheduling class.
++ *
++ * Return: On success, this syscall returns the minimum
++ * rt_priority that can be used by a given scheduling class.
++ * On failure, a negative error code is returned.
++ */
++SYSCALL_DEFINE1(sched_get_priority_min, int, policy)
++{
++ int ret = -EINVAL;
++
++ switch (policy) {
++ case SCHED_FIFO:
++ case SCHED_RR:
++ ret = 1;
++ break;
++ case SCHED_NORMAL:
++ case SCHED_BATCH:
++ case SCHED_IDLE:
++ ret = 0;
++ break;
++ }
++ return ret;
++}
++
++static int sched_rr_get_interval(pid_t pid, struct timespec64 *t)
++{
++ struct task_struct *p;
++ int retval;
++
++ alt_sched_debug();
++
++ if (pid < 0)
++ return -EINVAL;
++
++ guard(rcu)();
++ p = find_process_by_pid(pid);
++ if (!p)
++ return -EINVAL;
++
++ retval = security_task_getscheduler(p);
++ if (retval)
++ return retval;
++
++ *t = ns_to_timespec64(sysctl_sched_base_slice);
++ return 0;
++}
++
++/**
++ * sys_sched_rr_get_interval - return the default timeslice of a process.
++ * @pid: pid of the process.
++ * @interval: userspace pointer to the timeslice value.
++ *
++ *
++ * Return: On success, 0 and the timeslice is in @interval. Otherwise,
++ * an error code.
++ */
++SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
++ struct __kernel_timespec __user *, interval)
++{
++ struct timespec64 t;
++ int retval = sched_rr_get_interval(pid, &t);
++
++ if (retval == 0)
++ retval = put_timespec64(&t, interval);
++
++ return retval;
++}
++
++#ifdef CONFIG_COMPAT_32BIT_TIME
++SYSCALL_DEFINE2(sched_rr_get_interval_time32, pid_t, pid,
++ struct old_timespec32 __user *, interval)
++{
++ struct timespec64 t;
++ int retval = sched_rr_get_interval(pid, &t);
++
++ if (retval == 0)
++ retval = put_old_timespec32(&t, interval);
++ return retval;
++}
++#endif
++
++void sched_show_task(struct task_struct *p)
++{
++ unsigned long free = 0;
++ int ppid;
++
++ if (!try_get_task_stack(p))
++ return;
++
++ pr_info("task:%-15.15s state:%c", p->comm, task_state_to_char(p));
++
++ if (task_is_running(p))
++ pr_cont(" running task ");
++#ifdef CONFIG_DEBUG_STACK_USAGE
++ free = stack_not_used(p);
++#endif
++ ppid = 0;
++ rcu_read_lock();
++ if (pid_alive(p))
++ ppid = task_pid_nr(rcu_dereference(p->real_parent));
++ rcu_read_unlock();
++ pr_cont(" stack:%-5lu pid:%-5d tgid:%-5d ppid:%-6d flags:0x%08lx\n",
++ free, task_pid_nr(p), task_tgid_nr(p),
++ ppid, read_task_thread_flags(p));
++
++ print_worker_info(KERN_INFO, p);
++ print_stop_info(KERN_INFO, p);
++ show_stack(p, NULL, KERN_INFO);
++ put_task_stack(p);
++}
++EXPORT_SYMBOL_GPL(sched_show_task);
++
++static inline bool
++state_filter_match(unsigned long state_filter, struct task_struct *p)
++{
++ unsigned int state = READ_ONCE(p->__state);
++
++ /* no filter, everything matches */
++ if (!state_filter)
++ return true;
++
++ /* filter, but doesn't match */
++ if (!(state & state_filter))
++ return false;
++
++ /*
++ * When looking for TASK_UNINTERRUPTIBLE skip TASK_IDLE (allows
++ * TASK_KILLABLE).
++ */
++ if (state_filter == TASK_UNINTERRUPTIBLE && (state & TASK_NOLOAD))
++ return false;
++
++ return true;
++}
++
++
++void show_state_filter(unsigned int state_filter)
++{
++ struct task_struct *g, *p;
++
++ rcu_read_lock();
++ for_each_process_thread(g, p) {
++ /*
++ * reset the NMI-timeout, listing all files on a slow
++ * console might take a lot of time:
++ * Also, reset softlockup watchdogs on all CPUs, because
++ * another CPU might be blocked waiting for us to process
++ * an IPI.
++ */
++ touch_nmi_watchdog();
++ touch_all_softlockup_watchdogs();
++ if (state_filter_match(state_filter, p))
++ sched_show_task(p);
++ }
++
++#ifdef CONFIG_SCHED_DEBUG
++ /* TODO: Alt schedule FW should support this
++ if (!state_filter)
++ sysrq_sched_debug_show();
++ */
++#endif
++ rcu_read_unlock();
++ /*
++ * Only show locks if all tasks are dumped:
++ */
++ if (!state_filter)
++ debug_show_all_locks();
++}
++
++void dump_cpu_task(int cpu)
++{
++ if (cpu == smp_processor_id() && in_hardirq()) {
++ struct pt_regs *regs;
++
++ regs = get_irq_regs();
++ if (regs) {
++ show_regs(regs);
++ return;
++ }
++ }
++
++ if (trigger_single_cpu_backtrace(cpu))
++ return;
++
++ pr_info("Task dump for CPU %d:\n", cpu);
++ sched_show_task(cpu_curr(cpu));
++}
++
++/**
++ * init_idle - set up an idle thread for a given CPU
++ * @idle: task in question
++ * @cpu: CPU the idle task belongs to
++ *
++ * NOTE: this function does not set the idle thread's NEED_RESCHED
++ * flag, to make booting more robust.
++ */
++void __init init_idle(struct task_struct *idle, int cpu)
++{
++#ifdef CONFIG_SMP
++ struct affinity_context ac = (struct affinity_context) {
++ .new_mask = cpumask_of(cpu),
++ .flags = 0,
++ };
++#endif
++ struct rq *rq = cpu_rq(cpu);
++ unsigned long flags;
++
++ __sched_fork(0, idle);
++
++ raw_spin_lock_irqsave(&idle->pi_lock, flags);
++ raw_spin_lock(&rq->lock);
++
++ idle->last_ran = rq->clock_task;
++ idle->__state = TASK_RUNNING;
++ /*
++ * PF_KTHREAD should already be set at this point; regardless, make it
++ * look like a proper per-CPU kthread.
++ */
++ idle->flags |= PF_KTHREAD | PF_NO_SETAFFINITY;
++ kthread_set_per_cpu(idle, cpu);
++
++ sched_queue_init_idle(&rq->queue, idle);
++
++#ifdef CONFIG_SMP
++ /*
++ * It's possible that init_idle() gets called multiple times on a task,
++ * in that case do_set_cpus_allowed() will not do the right thing.
++ *
++ * And since this is boot we can forgo the serialisation.
++ */
++ set_cpus_allowed_common(idle, &ac);
++#endif
++
++ /* Silence PROVE_RCU */
++ rcu_read_lock();
++ __set_task_cpu(idle, cpu);
++ rcu_read_unlock();
++
++ rq->idle = idle;
++ rcu_assign_pointer(rq->curr, idle);
++ idle->on_cpu = 1;
++
++ raw_spin_unlock(&rq->lock);
++ raw_spin_unlock_irqrestore(&idle->pi_lock, flags);
++
++ /* Set the preempt count _outside_ the spinlocks! */
++ init_idle_preempt_count(idle, cpu);
++
++ ftrace_graph_init_idle_task(idle, cpu);
++ vtime_init_idle(idle, cpu);
++#ifdef CONFIG_SMP
++ sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu);
++#endif
++}
++
++#ifdef CONFIG_SMP
++
++int cpuset_cpumask_can_shrink(const struct cpumask __maybe_unused *cur,
++ const struct cpumask __maybe_unused *trial)
++{
++ return 1;
++}
++
++int task_can_attach(struct task_struct *p)
++{
++ int ret = 0;
++
++ /*
++ * Kthreads which disallow setaffinity shouldn't be moved
++ * to a new cpuset; we don't want to change their CPU
++ * affinity and isolating such threads by their set of
++ * allowed nodes is unnecessary. Thus, cpusets are not
++ * applicable for such threads. This prevents checking for
++ * success of set_cpus_allowed_ptr() on all attached tasks
++ * before cpus_mask may be changed.
++ */
++ if (p->flags & PF_NO_SETAFFINITY)
++ ret = -EINVAL;
++
++ return ret;
++}
++
++bool sched_smp_initialized __read_mostly;
++
++#ifdef CONFIG_HOTPLUG_CPU
++/*
++ * Ensures that the idle task is using init_mm right before its CPU goes
++ * offline.
++ */
++void idle_task_exit(void)
++{
++ struct mm_struct *mm = current->active_mm;
++
++ BUG_ON(current != this_rq()->idle);
++
++ if (mm != &init_mm) {
++ switch_mm(mm, &init_mm, current);
++ finish_arch_post_lock_switch();
++ }
++
++ /* finish_cpu(), as ran on the BP, will clean up the active_mm state */
++}
++
++static int __balance_push_cpu_stop(void *arg)
++{
++ struct task_struct *p = arg;
++ struct rq *rq = this_rq();
++ struct rq_flags rf;
++ int cpu;
++
++ raw_spin_lock_irq(&p->pi_lock);
++ rq_lock(rq, &rf);
++
++ update_rq_clock(rq);
++
++ if (task_rq(p) == rq && task_on_rq_queued(p)) {
++ cpu = select_fallback_rq(rq->cpu, p);
++ rq = __migrate_task(rq, p, cpu);
++ }
++
++ rq_unlock(rq, &rf);
++ raw_spin_unlock_irq(&p->pi_lock);
++
++ put_task_struct(p);
++
++ return 0;
++}
++
++static DEFINE_PER_CPU(struct cpu_stop_work, push_work);
++
++/*
++ * This is enabled below SCHED_AP_ACTIVE; when !cpu_active(), but only
++ * effective when the hotplug motion is down.
++ */
++static void balance_push(struct rq *rq)
++{
++ struct task_struct *push_task = rq->curr;
++
++ lockdep_assert_held(&rq->lock);
++
++ /*
++ * Ensure the thing is persistent until balance_push_set(.on = false);
++ */
++ rq->balance_callback = &balance_push_callback;
++
++ /*
++ * Only active while going offline and when invoked on the outgoing
++ * CPU.
++ */
++ if (!cpu_dying(rq->cpu) || rq != this_rq())
++ return;
++
++ /*
++ * Both the cpu-hotplug and stop task are in this case and are
++ * required to complete the hotplug process.
++ */
++ if (kthread_is_per_cpu(push_task) ||
++ is_migration_disabled(push_task)) {
++
++ /*
++ * If this is the idle task on the outgoing CPU try to wake
++ * up the hotplug control thread which might wait for the
++ * last task to vanish. The rcuwait_active() check is
++ * accurate here because the waiter is pinned on this CPU
++ * and can't obviously be running in parallel.
++ *
++ * On RT kernels this also has to check whether there are
++ * pinned and scheduled out tasks on the runqueue. They
++ * need to leave the migrate disabled section first.
++ */
++ if (!rq->nr_running && !rq_has_pinned_tasks(rq) &&
++ rcuwait_active(&rq->hotplug_wait)) {
++ raw_spin_unlock(&rq->lock);
++ rcuwait_wake_up(&rq->hotplug_wait);
++ raw_spin_lock(&rq->lock);
++ }
++ return;
++ }
++
++ get_task_struct(push_task);
++ /*
++ * Temporarily drop rq->lock such that we can wake-up the stop task.
++ * Both preemption and IRQs are still disabled.
++ */
++ preempt_disable();
++ raw_spin_unlock(&rq->lock);
++ stop_one_cpu_nowait(rq->cpu, __balance_push_cpu_stop, push_task,
++ this_cpu_ptr(&push_work));
++ preempt_enable();
++ /*
++ * At this point need_resched() is true and we'll take the loop in
++ * schedule(). The next pick is obviously going to be the stop task
++ * which kthread_is_per_cpu() and will push this task away.
++ */
++ raw_spin_lock(&rq->lock);
++}
++
++static void balance_push_set(int cpu, bool on)
++{
++ struct rq *rq = cpu_rq(cpu);
++ struct rq_flags rf;
++
++ rq_lock_irqsave(rq, &rf);
++ if (on) {
++ WARN_ON_ONCE(rq->balance_callback);
++ rq->balance_callback = &balance_push_callback;
++ } else if (rq->balance_callback == &balance_push_callback) {
++ rq->balance_callback = NULL;
++ }
++ rq_unlock_irqrestore(rq, &rf);
++}
++
++/*
++ * Invoked from a CPUs hotplug control thread after the CPU has been marked
++ * inactive. All tasks which are not per CPU kernel threads are either
++ * pushed off this CPU now via balance_push() or placed on a different CPU
++ * during wakeup. Wait until the CPU is quiescent.
++ */
++static void balance_hotplug_wait(void)
++{
++ struct rq *rq = this_rq();
++
++ rcuwait_wait_event(&rq->hotplug_wait,
++ rq->nr_running == 1 && !rq_has_pinned_tasks(rq),
++ TASK_UNINTERRUPTIBLE);
++}
++
++#else
++
++static void balance_push(struct rq *rq)
++{
++}
++
++static void balance_push_set(int cpu, bool on)
++{
++}
++
++static inline void balance_hotplug_wait(void)
++{
++}
++#endif /* CONFIG_HOTPLUG_CPU */
++
++static void set_rq_offline(struct rq *rq)
++{
++ if (rq->online) {
++ update_rq_clock(rq);
++ rq->online = false;
++ }
++}
++
++static void set_rq_online(struct rq *rq)
++{
++ if (!rq->online)
++ rq->online = true;
++}
++
++/*
++ * used to mark begin/end of suspend/resume:
++ */
++static int num_cpus_frozen;
++
++/*
++ * Update cpusets according to cpu_active mask. If cpusets are
++ * disabled, cpuset_update_active_cpus() becomes a simple wrapper
++ * around partition_sched_domains().
++ *
++ * If we come here as part of a suspend/resume, don't touch cpusets because we
++ * want to restore it back to its original state upon resume anyway.
++ */
++static void cpuset_cpu_active(void)
++{
++ if (cpuhp_tasks_frozen) {
++ /*
++ * num_cpus_frozen tracks how many CPUs are involved in suspend
++ * resume sequence. As long as this is not the last online
++ * operation in the resume sequence, just build a single sched
++ * domain, ignoring cpusets.
++ */
++ partition_sched_domains(1, NULL, NULL);
++ if (--num_cpus_frozen)
++ return;
++ /*
++ * This is the last CPU online operation. So fall through and
++ * restore the original sched domains by considering the
++ * cpuset configurations.
++ */
++ cpuset_force_rebuild();
++ }
++
++ cpuset_update_active_cpus();
++}
++
++static int cpuset_cpu_inactive(unsigned int cpu)
++{
++ if (!cpuhp_tasks_frozen) {
++ cpuset_update_active_cpus();
++ } else {
++ num_cpus_frozen++;
++ partition_sched_domains(1, NULL, NULL);
++ }
++ return 0;
++}
++
++int sched_cpu_activate(unsigned int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++ unsigned long flags;
++
++ /*
++ * Clear the balance_push callback and prepare to schedule
++ * regular tasks.
++ */
++ balance_push_set(cpu, false);
++
++#ifdef CONFIG_SCHED_SMT
++ /*
++ * When going up, increment the number of cores with SMT present.
++ */
++ if (cpumask_weight(cpu_smt_mask(cpu)) == 2)
++ static_branch_inc_cpuslocked(&sched_smt_present);
++#endif
++ set_cpu_active(cpu, true);
++
++ if (sched_smp_initialized)
++ cpuset_cpu_active();
++
++ /*
++ * Put the rq online, if not already. This happens:
++ *
++ * 1) In the early boot process, because we build the real domains
++ * after all cpus have been brought up.
++ *
++ * 2) At runtime, if cpuset_cpu_active() fails to rebuild the
++ * domains.
++ */
++ raw_spin_lock_irqsave(&rq->lock, flags);
++ set_rq_online(rq);
++ raw_spin_unlock_irqrestore(&rq->lock, flags);
++
++ return 0;
++}
++
++int sched_cpu_deactivate(unsigned int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++ unsigned long flags;
++ int ret;
++
++ set_cpu_active(cpu, false);
++
++ /*
++ * From this point forward, this CPU will refuse to run any task that
++ * is not: migrate_disable() or KTHREAD_IS_PER_CPU, and will actively
++ * push those tasks away until this gets cleared, see
++ * sched_cpu_dying().
++ */
++ balance_push_set(cpu, true);
++
++ /*
++ * We've cleared cpu_active_mask, wait for all preempt-disabled and RCU
++ * users of this state to go away such that all new such users will
++ * observe it.
++ *
++ * Specifically, we rely on ttwu to no longer target this CPU, see
++ * ttwu_queue_cond() and is_cpu_allowed().
++ *
++ * Do sync before park smpboot threads to take care the rcu boost case.
++ */
++ synchronize_rcu();
++
++ raw_spin_lock_irqsave(&rq->lock, flags);
++ set_rq_offline(rq);
++ raw_spin_unlock_irqrestore(&rq->lock, flags);
++
++#ifdef CONFIG_SCHED_SMT
++ /*
++ * When going down, decrement the number of cores with SMT present.
++ */
++ if (cpumask_weight(cpu_smt_mask(cpu)) == 2) {
++ static_branch_dec_cpuslocked(&sched_smt_present);
++ if (!static_branch_likely(&sched_smt_present))
++ cpumask_clear(sched_sg_idle_mask);
++ }
++#endif
++
++ if (!sched_smp_initialized)
++ return 0;
++
++ ret = cpuset_cpu_inactive(cpu);
++ if (ret) {
++ balance_push_set(cpu, false);
++ set_cpu_active(cpu, true);
++ return ret;
++ }
++
++ return 0;
++}
++
++static void sched_rq_cpu_starting(unsigned int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++
++ rq->calc_load_update = calc_load_update;
++}
++
++int sched_cpu_starting(unsigned int cpu)
++{
++ sched_rq_cpu_starting(cpu);
++ sched_tick_start(cpu);
++ return 0;
++}
++
++#ifdef CONFIG_HOTPLUG_CPU
++
++/*
++ * Invoked immediately before the stopper thread is invoked to bring the
++ * CPU down completely. At this point all per CPU kthreads except the
++ * hotplug thread (current) and the stopper thread (inactive) have been
++ * either parked or have been unbound from the outgoing CPU. Ensure that
++ * any of those which might be on the way out are gone.
++ *
++ * If after this point a bound task is being woken on this CPU then the
++ * responsible hotplug callback has failed to do it's job.
++ * sched_cpu_dying() will catch it with the appropriate fireworks.
++ */
++int sched_cpu_wait_empty(unsigned int cpu)
++{
++ balance_hotplug_wait();
++ return 0;
++}
++
++/*
++ * Since this CPU is going 'away' for a while, fold any nr_active delta we
++ * might have. Called from the CPU stopper task after ensuring that the
++ * stopper is the last running task on the CPU, so nr_active count is
++ * stable. We need to take the teardown thread which is calling this into
++ * account, so we hand in adjust = 1 to the load calculation.
++ *
++ * Also see the comment "Global load-average calculations".
++ */
++static void calc_load_migrate(struct rq *rq)
++{
++ long delta = calc_load_fold_active(rq, 1);
++
++ if (delta)
++ atomic_long_add(delta, &calc_load_tasks);
++}
++
++static void dump_rq_tasks(struct rq *rq, const char *loglvl)
++{
++ struct task_struct *g, *p;
++ int cpu = cpu_of(rq);
++
++ lockdep_assert_held(&rq->lock);
++
++ printk("%sCPU%d enqueued tasks (%u total):\n", loglvl, cpu, rq->nr_running);
++ for_each_process_thread(g, p) {
++ if (task_cpu(p) != cpu)
++ continue;
++
++ if (!task_on_rq_queued(p))
++ continue;
++
++ printk("%s\tpid: %d, name: %s\n", loglvl, p->pid, p->comm);
++ }
++}
++
++int sched_cpu_dying(unsigned int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++ unsigned long flags;
++
++ /* Handle pending wakeups and then migrate everything off */
++ sched_tick_stop(cpu);
++
++ raw_spin_lock_irqsave(&rq->lock, flags);
++ if (rq->nr_running != 1 || rq_has_pinned_tasks(rq)) {
++ WARN(true, "Dying CPU not properly vacated!");
++ dump_rq_tasks(rq, KERN_WARNING);
++ }
++ raw_spin_unlock_irqrestore(&rq->lock, flags);
++
++ calc_load_migrate(rq);
++ hrtick_clear(rq);
++ return 0;
++}
++#endif
++
++#ifdef CONFIG_SMP
++static void sched_init_topology_cpumask_early(void)
++{
++ int cpu;
++ cpumask_t *tmp;
++
++ for_each_possible_cpu(cpu) {
++ /* init topo masks */
++ tmp = per_cpu(sched_cpu_topo_masks, cpu);
++
++ cpumask_copy(tmp, cpu_possible_mask);
++ per_cpu(sched_cpu_llc_mask, cpu) = tmp;
++ per_cpu(sched_cpu_topo_end_mask, cpu) = ++tmp;
++ }
++}
++
++#define TOPOLOGY_CPUMASK(name, mask, last)\
++ if (cpumask_and(topo, topo, mask)) { \
++ cpumask_copy(topo, mask); \
++ printk(KERN_INFO "sched: cpu#%02d topo: 0x%08lx - "#name, \
++ cpu, (topo++)->bits[0]); \
++ } \
++ if (!last) \
++ bitmap_complement(cpumask_bits(topo), cpumask_bits(mask), \
++ nr_cpumask_bits);
++
++static void sched_init_topology_cpumask(void)
++{
++ int cpu;
++ cpumask_t *topo;
++
++ for_each_online_cpu(cpu) {
++ /* take chance to reset time slice for idle tasks */
++ cpu_rq(cpu)->idle->time_slice = sysctl_sched_base_slice;
++
++ topo = per_cpu(sched_cpu_topo_masks, cpu);
++
++ bitmap_complement(cpumask_bits(topo), cpumask_bits(cpumask_of(cpu)),
++ nr_cpumask_bits);
++#ifdef CONFIG_SCHED_SMT
++ TOPOLOGY_CPUMASK(smt, topology_sibling_cpumask(cpu), false);
++#endif
++ per_cpu(sd_llc_id, cpu) = cpumask_first(cpu_coregroup_mask(cpu));
++ per_cpu(sched_cpu_llc_mask, cpu) = topo;
++ TOPOLOGY_CPUMASK(coregroup, cpu_coregroup_mask(cpu), false);
++
++ TOPOLOGY_CPUMASK(core, topology_core_cpumask(cpu), false);
++
++ TOPOLOGY_CPUMASK(others, cpu_online_mask, true);
++
++ per_cpu(sched_cpu_topo_end_mask, cpu) = topo;
++ printk(KERN_INFO "sched: cpu#%02d llc_id = %d, llc_mask idx = %d\n",
++ cpu, per_cpu(sd_llc_id, cpu),
++ (int) (per_cpu(sched_cpu_llc_mask, cpu) -
++ per_cpu(sched_cpu_topo_masks, cpu)));
++ }
++}
++#endif
++
++void __init sched_init_smp(void)
++{
++ /* Move init over to a non-isolated CPU */
++ if (set_cpus_allowed_ptr(current, housekeeping_cpumask(HK_TYPE_DOMAIN)) < 0)
++ BUG();
++ current->flags &= ~PF_NO_SETAFFINITY;
++
++ sched_init_topology_cpumask();
++
++ sched_smp_initialized = true;
++}
++
++static int __init migration_init(void)
++{
++ sched_cpu_starting(smp_processor_id());
++ return 0;
++}
++early_initcall(migration_init);
++
++#else
++void __init sched_init_smp(void)
++{
++ cpu_rq(0)->idle->time_slice = sysctl_sched_base_slice;
++}
++#endif /* CONFIG_SMP */
++
++int in_sched_functions(unsigned long addr)
++{
++ return in_lock_functions(addr) ||
++ (addr >= (unsigned long)__sched_text_start
++ && addr < (unsigned long)__sched_text_end);
++}
++
++#ifdef CONFIG_CGROUP_SCHED
++/*
++ * Default task group.
++ * Every task in system belongs to this group at bootup.
++ */
++struct task_group root_task_group;
++LIST_HEAD(task_groups);
++
++/* Cacheline aligned slab cache for task_group */
++static struct kmem_cache *task_group_cache __ro_after_init;
++#endif /* CONFIG_CGROUP_SCHED */
++
++void __init sched_init(void)
++{
++ int i;
++ struct rq *rq;
++
++ printk(KERN_INFO "sched/alt: "ALT_SCHED_NAME" CPU Scheduler "ALT_SCHED_VERSION\
++ " by Alfred Chen.\n");
++
++ wait_bit_init();
++
++#ifdef CONFIG_SMP
++ for (i = 0; i < SCHED_QUEUE_BITS; i++)
++ cpumask_copy(sched_preempt_mask + i, cpu_present_mask);
++#endif
++
++#ifdef CONFIG_CGROUP_SCHED
++ task_group_cache = KMEM_CACHE(task_group, 0);
++
++ list_add(&root_task_group.list, &task_groups);
++ INIT_LIST_HEAD(&root_task_group.children);
++ INIT_LIST_HEAD(&root_task_group.siblings);
++#endif /* CONFIG_CGROUP_SCHED */
++ for_each_possible_cpu(i) {
++ rq = cpu_rq(i);
++
++ sched_queue_init(&rq->queue);
++ rq->prio = IDLE_TASK_SCHED_PRIO;
++#ifdef CONFIG_SCHED_PDS
++ rq->prio_idx = rq->prio;
++#endif
++
++ raw_spin_lock_init(&rq->lock);
++ rq->nr_running = rq->nr_uninterruptible = 0;
++ rq->calc_load_active = 0;
++ rq->calc_load_update = jiffies + LOAD_FREQ;
++#ifdef CONFIG_SMP
++ rq->online = false;
++ rq->cpu = i;
++
++#ifdef CONFIG_SCHED_SMT
++ rq->active_balance = 0;
++#endif
++
++#ifdef CONFIG_NO_HZ_COMMON
++ INIT_CSD(&rq->nohz_csd, nohz_csd_func, rq);
++#endif
++ rq->balance_callback = &balance_push_callback;
++#ifdef CONFIG_HOTPLUG_CPU
++ rcuwait_init(&rq->hotplug_wait);
++#endif
++#endif /* CONFIG_SMP */
++ rq->nr_switches = 0;
++
++ hrtick_rq_init(rq);
++ atomic_set(&rq->nr_iowait, 0);
++
++ zalloc_cpumask_var_node(&rq->scratch_mask, GFP_KERNEL, cpu_to_node(i));
++ }
++#ifdef CONFIG_SMP
++ /* Set rq->online for cpu 0 */
++ cpu_rq(0)->online = true;
++#endif
++ /*
++ * The boot idle thread does lazy MMU switching as well:
++ */
++ mmgrab(&init_mm);
++ enter_lazy_tlb(&init_mm, current);
++
++ /*
++ * The idle task doesn't need the kthread struct to function, but it
++ * is dressed up as a per-CPU kthread and thus needs to play the part
++ * if we want to avoid special-casing it in code that deals with per-CPU
++ * kthreads.
++ */
++ WARN_ON(!set_kthread_struct(current));
++
++ /*
++ * Make us the idle thread. Technically, schedule() should not be
++ * called from this thread, however somewhere below it might be,
++ * but because we are the idle thread, we just pick up running again
++ * when this runqueue becomes "idle".
++ */
++ init_idle(current, smp_processor_id());
++
++ calc_load_update = jiffies + LOAD_FREQ;
++
++#ifdef CONFIG_SMP
++ idle_thread_set_boot_cpu();
++ balance_push_set(smp_processor_id(), false);
++
++ sched_init_topology_cpumask_early();
++#endif /* SMP */
++
++ preempt_dynamic_init();
++}
++
++#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
++
++void __might_sleep(const char *file, int line)
++{
++ unsigned int state = get_current_state();
++ /*
++ * Blocking primitives will set (and therefore destroy) current->state,
++ * since we will exit with TASK_RUNNING make sure we enter with it,
++ * otherwise we will destroy state.
++ */
++ WARN_ONCE(state != TASK_RUNNING && current->task_state_change,
++ "do not call blocking ops when !TASK_RUNNING; "
++ "state=%x set at [<%p>] %pS\n", state,
++ (void *)current->task_state_change,
++ (void *)current->task_state_change);
++
++ __might_resched(file, line, 0);
++}
++EXPORT_SYMBOL(__might_sleep);
++
++static void print_preempt_disable_ip(int preempt_offset, unsigned long ip)
++{
++ if (!IS_ENABLED(CONFIG_DEBUG_PREEMPT))
++ return;
++
++ if (preempt_count() == preempt_offset)
++ return;
++
++ pr_err("Preemption disabled at:");
++ print_ip_sym(KERN_ERR, ip);
++}
++
++static inline bool resched_offsets_ok(unsigned int offsets)
++{
++ unsigned int nested = preempt_count();
++
++ nested += rcu_preempt_depth() << MIGHT_RESCHED_RCU_SHIFT;
++
++ return nested == offsets;
++}
++
++void __might_resched(const char *file, int line, unsigned int offsets)
++{
++ /* Ratelimiting timestamp: */
++ static unsigned long prev_jiffy;
++
++ unsigned long preempt_disable_ip;
++
++ /* WARN_ON_ONCE() by default, no rate limit required: */
++ rcu_sleep_check();
++
++ if ((resched_offsets_ok(offsets) && !irqs_disabled() &&
++ !is_idle_task(current) && !current->non_block_count) ||
++ system_state == SYSTEM_BOOTING || system_state > SYSTEM_RUNNING ||
++ oops_in_progress)
++ return;
++ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
++ return;
++ prev_jiffy = jiffies;
++
++ /* Save this before calling printk(), since that will clobber it: */
++ preempt_disable_ip = get_preempt_disable_ip(current);
++
++ pr_err("BUG: sleeping function called from invalid context at %s:%d\n",
++ file, line);
++ pr_err("in_atomic(): %d, irqs_disabled(): %d, non_block: %d, pid: %d, name: %s\n",
++ in_atomic(), irqs_disabled(), current->non_block_count,
++ current->pid, current->comm);
++ pr_err("preempt_count: %x, expected: %x\n", preempt_count(),
++ offsets & MIGHT_RESCHED_PREEMPT_MASK);
++
++ if (IS_ENABLED(CONFIG_PREEMPT_RCU)) {
++ pr_err("RCU nest depth: %d, expected: %u\n",
++ rcu_preempt_depth(), offsets >> MIGHT_RESCHED_RCU_SHIFT);
++ }
++
++ if (task_stack_end_corrupted(current))
++ pr_emerg("Thread overran stack, or stack corrupted\n");
++
++ debug_show_held_locks(current);
++ if (irqs_disabled())
++ print_irqtrace_events(current);
++
++ print_preempt_disable_ip(offsets & MIGHT_RESCHED_PREEMPT_MASK,
++ preempt_disable_ip);
++
++ dump_stack();
++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
++}
++EXPORT_SYMBOL(__might_resched);
++
++void __cant_sleep(const char *file, int line, int preempt_offset)
++{
++ static unsigned long prev_jiffy;
++
++ if (irqs_disabled())
++ return;
++
++ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT))
++ return;
++
++ if (preempt_count() > preempt_offset)
++ return;
++
++ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
++ return;
++ prev_jiffy = jiffies;
++
++ printk(KERN_ERR "BUG: assuming atomic context at %s:%d\n", file, line);
++ printk(KERN_ERR "in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n",
++ in_atomic(), irqs_disabled(),
++ current->pid, current->comm);
++
++ debug_show_held_locks(current);
++ dump_stack();
++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
++}
++EXPORT_SYMBOL_GPL(__cant_sleep);
++
++#ifdef CONFIG_SMP
++void __cant_migrate(const char *file, int line)
++{
++ static unsigned long prev_jiffy;
++
++ if (irqs_disabled())
++ return;
++
++ if (is_migration_disabled(current))
++ return;
++
++ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT))
++ return;
++
++ if (preempt_count() > 0)
++ return;
++
++ if (current->migration_flags & MDF_FORCE_ENABLED)
++ return;
++
++ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
++ return;
++ prev_jiffy = jiffies;
++
++ pr_err("BUG: assuming non migratable context at %s:%d\n", file, line);
++ pr_err("in_atomic(): %d, irqs_disabled(): %d, migration_disabled() %u pid: %d, name: %s\n",
++ in_atomic(), irqs_disabled(), is_migration_disabled(current),
++ current->pid, current->comm);
++
++ debug_show_held_locks(current);
++ dump_stack();
++ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
++}
++EXPORT_SYMBOL_GPL(__cant_migrate);
++#endif
++#endif
++
++#ifdef CONFIG_MAGIC_SYSRQ
++void normalize_rt_tasks(void)
++{
++ struct task_struct *g, *p;
++ struct sched_attr attr = {
++ .sched_policy = SCHED_NORMAL,
++ };
++
++ read_lock(&tasklist_lock);
++ for_each_process_thread(g, p) {
++ /*
++ * Only normalize user tasks:
++ */
++ if (p->flags & PF_KTHREAD)
++ continue;
++
++ schedstat_set(p->stats.wait_start, 0);
++ schedstat_set(p->stats.sleep_start, 0);
++ schedstat_set(p->stats.block_start, 0);
++
++ if (!rt_task(p)) {
++ /*
++ * Renice negative nice level userspace
++ * tasks back to 0:
++ */
++ if (task_nice(p) < 0)
++ set_user_nice(p, 0);
++ continue;
++ }
++
++ __sched_setscheduler(p, &attr, false, false);
++ }
++ read_unlock(&tasklist_lock);
++}
++#endif /* CONFIG_MAGIC_SYSRQ */
++
++#if defined(CONFIG_KGDB_KDB)
++/*
++ * These functions are only useful for kdb.
++ *
++ * They can only be called when the whole system has been
++ * stopped - every CPU needs to be quiescent, and no scheduling
++ * activity can take place. Using them for anything else would
++ * be a serious bug, and as a result, they aren't even visible
++ * under any other configuration.
++ */
++
++/**
++ * curr_task - return the current task for a given CPU.
++ * @cpu: the processor in question.
++ *
++ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
++ *
++ * Return: The current task for @cpu.
++ */
++struct task_struct *curr_task(int cpu)
++{
++ return cpu_curr(cpu);
++}
++
++#endif /* defined(CONFIG_KGDB_KDB) */
++
++#ifdef CONFIG_CGROUP_SCHED
++static void sched_free_group(struct task_group *tg)
++{
++ kmem_cache_free(task_group_cache, tg);
++}
++
++static void sched_free_group_rcu(struct rcu_head *rhp)
++{
++ sched_free_group(container_of(rhp, struct task_group, rcu));
++}
++
++static void sched_unregister_group(struct task_group *tg)
++{
++ /*
++ * We have to wait for yet another RCU grace period to expire, as
++ * print_cfs_stats() might run concurrently.
++ */
++ call_rcu(&tg->rcu, sched_free_group_rcu);
++}
++
++/* allocate runqueue etc for a new task group */
++struct task_group *sched_create_group(struct task_group *parent)
++{
++ struct task_group *tg;
++
++ tg = kmem_cache_alloc(task_group_cache, GFP_KERNEL | __GFP_ZERO);
++ if (!tg)
++ return ERR_PTR(-ENOMEM);
++
++ return tg;
++}
++
++void sched_online_group(struct task_group *tg, struct task_group *parent)
++{
++}
++
++/* rcu callback to free various structures associated with a task group */
++static void sched_unregister_group_rcu(struct rcu_head *rhp)
++{
++ /* Now it should be safe to free those cfs_rqs: */
++ sched_unregister_group(container_of(rhp, struct task_group, rcu));
++}
++
++void sched_destroy_group(struct task_group *tg)
++{
++ /* Wait for possible concurrent references to cfs_rqs complete: */
++ call_rcu(&tg->rcu, sched_unregister_group_rcu);
++}
++
++void sched_release_group(struct task_group *tg)
++{
++}
++
++static inline struct task_group *css_tg(struct cgroup_subsys_state *css)
++{
++ return css ? container_of(css, struct task_group, css) : NULL;
++}
++
++static struct cgroup_subsys_state *
++cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
++{
++ struct task_group *parent = css_tg(parent_css);
++ struct task_group *tg;
++
++ if (!parent) {
++ /* This is early initialization for the top cgroup */
++ return &root_task_group.css;
++ }
++
++ tg = sched_create_group(parent);
++ if (IS_ERR(tg))
++ return ERR_PTR(-ENOMEM);
++ return &tg->css;
++}
++
++/* Expose task group only after completing cgroup initialization */
++static int cpu_cgroup_css_online(struct cgroup_subsys_state *css)
++{
++ struct task_group *tg = css_tg(css);
++ struct task_group *parent = css_tg(css->parent);
++
++ if (parent)
++ sched_online_group(tg, parent);
++ return 0;
++}
++
++static void cpu_cgroup_css_released(struct cgroup_subsys_state *css)
++{
++ struct task_group *tg = css_tg(css);
++
++ sched_release_group(tg);
++}
++
++static void cpu_cgroup_css_free(struct cgroup_subsys_state *css)
++{
++ struct task_group *tg = css_tg(css);
++
++ /*
++ * Relies on the RCU grace period between css_released() and this.
++ */
++ sched_unregister_group(tg);
++}
++
++#ifdef CONFIG_RT_GROUP_SCHED
++static int cpu_cgroup_can_attach(struct cgroup_taskset *tset)
++{
++ return 0;
++}
++#endif
++
++static void cpu_cgroup_attach(struct cgroup_taskset *tset)
++{
++}
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++static DEFINE_MUTEX(shares_mutex);
++
++static int sched_group_set_shares(struct task_group *tg, unsigned long shares)
++{
++ /*
++ * We can't change the weight of the root cgroup.
++ */
++ if (&root_task_group == tg)
++ return -EINVAL;
++
++ shares = clamp(shares, scale_load(MIN_SHARES), scale_load(MAX_SHARES));
++
++ mutex_lock(&shares_mutex);
++ if (tg->shares == shares)
++ goto done;
++
++ tg->shares = shares;
++done:
++ mutex_unlock(&shares_mutex);
++ return 0;
++}
++
++static int cpu_shares_write_u64(struct cgroup_subsys_state *css,
++ struct cftype *cftype, u64 shareval)
++{
++ if (shareval > scale_load_down(ULONG_MAX))
++ shareval = MAX_SHARES;
++ return sched_group_set_shares(css_tg(css), scale_load(shareval));
++}
++
++static u64 cpu_shares_read_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ struct task_group *tg = css_tg(css);
++
++ return (u64) scale_load_down(tg->shares);
++}
++#endif
++
++static s64 cpu_cfs_quota_read_s64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_cfs_quota_write_s64(struct cgroup_subsys_state *css,
++ struct cftype *cftype, s64 cfs_quota_us)
++{
++ return 0;
++}
++
++static u64 cpu_cfs_period_read_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_cfs_period_write_u64(struct cgroup_subsys_state *css,
++ struct cftype *cftype, u64 cfs_period_us)
++{
++ return 0;
++}
++
++static u64 cpu_cfs_burst_read_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_cfs_burst_write_u64(struct cgroup_subsys_state *css,
++ struct cftype *cftype, u64 cfs_burst_us)
++{
++ return 0;
++}
++
++static int cpu_cfs_stat_show(struct seq_file *sf, void *v)
++{
++ return 0;
++}
++
++static int cpu_cfs_local_stat_show(struct seq_file *sf, void *v)
++{
++ return 0;
++}
++
++static int cpu_rt_runtime_write(struct cgroup_subsys_state *css,
++ struct cftype *cft, s64 val)
++{
++ return 0;
++}
++
++static s64 cpu_rt_runtime_read(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_rt_period_write_uint(struct cgroup_subsys_state *css,
++ struct cftype *cftype, u64 rt_period_us)
++{
++ return 0;
++}
++
++static u64 cpu_rt_period_read_uint(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_uclamp_min_show(struct seq_file *sf, void *v)
++{
++ return 0;
++}
++
++static int cpu_uclamp_max_show(struct seq_file *sf, void *v)
++{
++ return 0;
++}
++
++static ssize_t cpu_uclamp_min_write(struct kernfs_open_file *of,
++ char *buf, size_t nbytes,
++ loff_t off)
++{
++ return nbytes;
++}
++
++static ssize_t cpu_uclamp_max_write(struct kernfs_open_file *of,
++ char *buf, size_t nbytes,
++ loff_t off)
++{
++ return nbytes;
++}
++
++static struct cftype cpu_legacy_files[] = {
++#ifdef CONFIG_FAIR_GROUP_SCHED
++ {
++ .name = "shares",
++ .read_u64 = cpu_shares_read_u64,
++ .write_u64 = cpu_shares_write_u64,
++ },
++#endif
++ {
++ .name = "cfs_quota_us",
++ .read_s64 = cpu_cfs_quota_read_s64,
++ .write_s64 = cpu_cfs_quota_write_s64,
++ },
++ {
++ .name = "cfs_period_us",
++ .read_u64 = cpu_cfs_period_read_u64,
++ .write_u64 = cpu_cfs_period_write_u64,
++ },
++ {
++ .name = "cfs_burst_us",
++ .read_u64 = cpu_cfs_burst_read_u64,
++ .write_u64 = cpu_cfs_burst_write_u64,
++ },
++ {
++ .name = "stat",
++ .seq_show = cpu_cfs_stat_show,
++ },
++ {
++ .name = "stat.local",
++ .seq_show = cpu_cfs_local_stat_show,
++ },
++ {
++ .name = "rt_runtime_us",
++ .read_s64 = cpu_rt_runtime_read,
++ .write_s64 = cpu_rt_runtime_write,
++ },
++ {
++ .name = "rt_period_us",
++ .read_u64 = cpu_rt_period_read_uint,
++ .write_u64 = cpu_rt_period_write_uint,
++ },
++ {
++ .name = "uclamp.min",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_uclamp_min_show,
++ .write = cpu_uclamp_min_write,
++ },
++ {
++ .name = "uclamp.max",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_uclamp_max_show,
++ .write = cpu_uclamp_max_write,
++ },
++ { } /* Terminate */
++};
++
++static u64 cpu_weight_read_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_weight_write_u64(struct cgroup_subsys_state *css,
++ struct cftype *cft, u64 weight)
++{
++ return 0;
++}
++
++static s64 cpu_weight_nice_read_s64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_weight_nice_write_s64(struct cgroup_subsys_state *css,
++ struct cftype *cft, s64 nice)
++{
++ return 0;
++}
++
++static s64 cpu_idle_read_s64(struct cgroup_subsys_state *css,
++ struct cftype *cft)
++{
++ return 0;
++}
++
++static int cpu_idle_write_s64(struct cgroup_subsys_state *css,
++ struct cftype *cft, s64 idle)
++{
++ return 0;
++}
++
++static int cpu_max_show(struct seq_file *sf, void *v)
++{
++ return 0;
++}
++
++static ssize_t cpu_max_write(struct kernfs_open_file *of,
++ char *buf, size_t nbytes, loff_t off)
++{
++ return nbytes;
++}
++
++static struct cftype cpu_files[] = {
++ {
++ .name = "weight",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .read_u64 = cpu_weight_read_u64,
++ .write_u64 = cpu_weight_write_u64,
++ },
++ {
++ .name = "weight.nice",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .read_s64 = cpu_weight_nice_read_s64,
++ .write_s64 = cpu_weight_nice_write_s64,
++ },
++ {
++ .name = "idle",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .read_s64 = cpu_idle_read_s64,
++ .write_s64 = cpu_idle_write_s64,
++ },
++ {
++ .name = "max",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_max_show,
++ .write = cpu_max_write,
++ },
++ {
++ .name = "max.burst",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .read_u64 = cpu_cfs_burst_read_u64,
++ .write_u64 = cpu_cfs_burst_write_u64,
++ },
++ {
++ .name = "uclamp.min",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_uclamp_min_show,
++ .write = cpu_uclamp_min_write,
++ },
++ {
++ .name = "uclamp.max",
++ .flags = CFTYPE_NOT_ON_ROOT,
++ .seq_show = cpu_uclamp_max_show,
++ .write = cpu_uclamp_max_write,
++ },
++ { } /* terminate */
++};
++
++static int cpu_extra_stat_show(struct seq_file *sf,
++ struct cgroup_subsys_state *css)
++{
++ return 0;
++}
++
++static int cpu_local_stat_show(struct seq_file *sf,
++ struct cgroup_subsys_state *css)
++{
++ return 0;
++}
++
++struct cgroup_subsys cpu_cgrp_subsys = {
++ .css_alloc = cpu_cgroup_css_alloc,
++ .css_online = cpu_cgroup_css_online,
++ .css_released = cpu_cgroup_css_released,
++ .css_free = cpu_cgroup_css_free,
++ .css_extra_stat_show = cpu_extra_stat_show,
++ .css_local_stat_show = cpu_local_stat_show,
++#ifdef CONFIG_RT_GROUP_SCHED
++ .can_attach = cpu_cgroup_can_attach,
++#endif
++ .attach = cpu_cgroup_attach,
++ .legacy_cftypes = cpu_legacy_files,
++ .dfl_cftypes = cpu_files,
++ .early_init = true,
++ .threaded = true,
++};
++#endif /* CONFIG_CGROUP_SCHED */
++
++#undef CREATE_TRACE_POINTS
++
++#ifdef CONFIG_SCHED_MM_CID
++
++#
++/*
++ * @cid_lock: Guarantee forward-progress of cid allocation.
++ *
++ * Concurrency ID allocation within a bitmap is mostly lock-free. The cid_lock
++ * is only used when contention is detected by the lock-free allocation so
++ * forward progress can be guaranteed.
++ */
++DEFINE_RAW_SPINLOCK(cid_lock);
++
++/*
++ * @use_cid_lock: Select cid allocation behavior: lock-free vs spinlock.
++ *
++ * When @use_cid_lock is 0, the cid allocation is lock-free. When contention is
++ * detected, it is set to 1 to ensure that all newly coming allocations are
++ * serialized by @cid_lock until the allocation which detected contention
++ * completes and sets @use_cid_lock back to 0. This guarantees forward progress
++ * of a cid allocation.
++ */
++int use_cid_lock;
++
++/*
++ * mm_cid remote-clear implements a lock-free algorithm to clear per-mm/cpu cid
++ * concurrently with respect to the execution of the source runqueue context
++ * switch.
++ *
++ * There is one basic properties we want to guarantee here:
++ *
++ * (1) Remote-clear should _never_ mark a per-cpu cid UNSET when it is actively
++ * used by a task. That would lead to concurrent allocation of the cid and
++ * userspace corruption.
++ *
++ * Provide this guarantee by introducing a Dekker memory ordering to guarantee
++ * that a pair of loads observe at least one of a pair of stores, which can be
++ * shown as:
++ *
++ * X = Y = 0
++ *
++ * w[X]=1 w[Y]=1
++ * MB MB
++ * r[Y]=y r[X]=x
++ *
++ * Which guarantees that x==0 && y==0 is impossible. But rather than using
++ * values 0 and 1, this algorithm cares about specific state transitions of the
++ * runqueue current task (as updated by the scheduler context switch), and the
++ * per-mm/cpu cid value.
++ *
++ * Let's introduce task (Y) which has task->mm == mm and task (N) which has
++ * task->mm != mm for the rest of the discussion. There are two scheduler state
++ * transitions on context switch we care about:
++ *
++ * (TSA) Store to rq->curr with transition from (N) to (Y)
++ *
++ * (TSB) Store to rq->curr with transition from (Y) to (N)
++ *
++ * On the remote-clear side, there is one transition we care about:
++ *
++ * (TMA) cmpxchg to *pcpu_cid to set the LAZY flag
++ *
++ * There is also a transition to UNSET state which can be performed from all
++ * sides (scheduler, remote-clear). It is always performed with a cmpxchg which
++ * guarantees that only a single thread will succeed:
++ *
++ * (TMB) cmpxchg to *pcpu_cid to mark UNSET
++ *
++ * Just to be clear, what we do _not_ want to happen is a transition to UNSET
++ * when a thread is actively using the cid (property (1)).
++ *
++ * Let's looks at the relevant combinations of TSA/TSB, and TMA transitions.
++ *
++ * Scenario A) (TSA)+(TMA) (from next task perspective)
++ *
++ * CPU0 CPU1
++ *
++ * Context switch CS-1 Remote-clear
++ * - store to rq->curr: (N)->(Y) (TSA) - cmpxchg to *pcpu_id to LAZY (TMA)
++ * (implied barrier after cmpxchg)
++ * - switch_mm_cid()
++ * - memory barrier (see switch_mm_cid()
++ * comment explaining how this barrier
++ * is combined with other scheduler
++ * barriers)
++ * - mm_cid_get (next)
++ * - READ_ONCE(*pcpu_cid) - rcu_dereference(src_rq->curr)
++ *
++ * This Dekker ensures that either task (Y) is observed by the
++ * rcu_dereference() or the LAZY flag is observed by READ_ONCE(), or both are
++ * observed.
++ *
++ * If task (Y) store is observed by rcu_dereference(), it means that there is
++ * still an active task on the cpu. Remote-clear will therefore not transition
++ * to UNSET, which fulfills property (1).
++ *
++ * If task (Y) is not observed, but the lazy flag is observed by READ_ONCE(),
++ * it will move its state to UNSET, which clears the percpu cid perhaps
++ * uselessly (which is not an issue for correctness). Because task (Y) is not
++ * observed, CPU1 can move ahead to set the state to UNSET. Because moving
++ * state to UNSET is done with a cmpxchg expecting that the old state has the
++ * LAZY flag set, only one thread will successfully UNSET.
++ *
++ * If both states (LAZY flag and task (Y)) are observed, the thread on CPU0
++ * will observe the LAZY flag and transition to UNSET (perhaps uselessly), and
++ * CPU1 will observe task (Y) and do nothing more, which is fine.
++ *
++ * What we are effectively preventing with this Dekker is a scenario where
++ * neither LAZY flag nor store (Y) are observed, which would fail property (1)
++ * because this would UNSET a cid which is actively used.
++ */
++
++void sched_mm_cid_migrate_from(struct task_struct *t)
++{
++ t->migrate_from_cpu = task_cpu(t);
++}
++
++static
++int __sched_mm_cid_migrate_from_fetch_cid(struct rq *src_rq,
++ struct task_struct *t,
++ struct mm_cid *src_pcpu_cid)
++{
++ struct mm_struct *mm = t->mm;
++ struct task_struct *src_task;
++ int src_cid, last_mm_cid;
++
++ if (!mm)
++ return -1;
++
++ last_mm_cid = t->last_mm_cid;
++ /*
++ * If the migrated task has no last cid, or if the current
++ * task on src rq uses the cid, it means the source cid does not need
++ * to be moved to the destination cpu.
++ */
++ if (last_mm_cid == -1)
++ return -1;
++ src_cid = READ_ONCE(src_pcpu_cid->cid);
++ if (!mm_cid_is_valid(src_cid) || last_mm_cid != src_cid)
++ return -1;
++
++ /*
++ * If we observe an active task using the mm on this rq, it means we
++ * are not the last task to be migrated from this cpu for this mm, so
++ * there is no need to move src_cid to the destination cpu.
++ */
++ rcu_read_lock();
++ src_task = rcu_dereference(src_rq->curr);
++ if (READ_ONCE(src_task->mm_cid_active) && src_task->mm == mm) {
++ rcu_read_unlock();
++ t->last_mm_cid = -1;
++ return -1;
++ }
++ rcu_read_unlock();
++
++ return src_cid;
++}
++
++static
++int __sched_mm_cid_migrate_from_try_steal_cid(struct rq *src_rq,
++ struct task_struct *t,
++ struct mm_cid *src_pcpu_cid,
++ int src_cid)
++{
++ struct task_struct *src_task;
++ struct mm_struct *mm = t->mm;
++ int lazy_cid;
++
++ if (src_cid == -1)
++ return -1;
++
++ /*
++ * Attempt to clear the source cpu cid to move it to the destination
++ * cpu.
++ */
++ lazy_cid = mm_cid_set_lazy_put(src_cid);
++ if (!try_cmpxchg(&src_pcpu_cid->cid, &src_cid, lazy_cid))
++ return -1;
++
++ /*
++ * The implicit barrier after cmpxchg per-mm/cpu cid before loading
++ * rq->curr->mm matches the scheduler barrier in context_switch()
++ * between store to rq->curr and load of prev and next task's
++ * per-mm/cpu cid.
++ *
++ * The implicit barrier after cmpxchg per-mm/cpu cid before loading
++ * rq->curr->mm_cid_active matches the barrier in
++ * sched_mm_cid_exit_signals(), sched_mm_cid_before_execve(), and
++ * sched_mm_cid_after_execve() between store to t->mm_cid_active and
++ * load of per-mm/cpu cid.
++ */
++
++ /*
++ * If we observe an active task using the mm on this rq after setting
++ * the lazy-put flag, this task will be responsible for transitioning
++ * from lazy-put flag set to MM_CID_UNSET.
++ */
++ scoped_guard (rcu) {
++ src_task = rcu_dereference(src_rq->curr);
++ if (READ_ONCE(src_task->mm_cid_active) && src_task->mm == mm) {
++ rcu_read_unlock();
++ /*
++ * We observed an active task for this mm, there is therefore
++ * no point in moving this cid to the destination cpu.
++ */
++ t->last_mm_cid = -1;
++ return -1;
++ }
++ }
++
++ /*
++ * The src_cid is unused, so it can be unset.
++ */
++ if (!try_cmpxchg(&src_pcpu_cid->cid, &lazy_cid, MM_CID_UNSET))
++ return -1;
++ return src_cid;
++}
++
++/*
++ * Migration to dst cpu. Called with dst_rq lock held.
++ * Interrupts are disabled, which keeps the window of cid ownership without the
++ * source rq lock held small.
++ */
++void sched_mm_cid_migrate_to(struct rq *dst_rq, struct task_struct *t, int src_cpu)
++{
++ struct mm_cid *src_pcpu_cid, *dst_pcpu_cid;
++ struct mm_struct *mm = t->mm;
++ int src_cid, dst_cid;
++ struct rq *src_rq;
++
++ lockdep_assert_rq_held(dst_rq);
++
++ if (!mm)
++ return;
++ if (src_cpu == -1) {
++ t->last_mm_cid = -1;
++ return;
++ }
++ /*
++ * Move the src cid if the dst cid is unset. This keeps id
++ * allocation closest to 0 in cases where few threads migrate around
++ * many cpus.
++ *
++ * If destination cid is already set, we may have to just clear
++ * the src cid to ensure compactness in frequent migrations
++ * scenarios.
++ *
++ * It is not useful to clear the src cid when the number of threads is
++ * greater or equal to the number of allowed cpus, because user-space
++ * can expect that the number of allowed cids can reach the number of
++ * allowed cpus.
++ */
++ dst_pcpu_cid = per_cpu_ptr(mm->pcpu_cid, cpu_of(dst_rq));
++ dst_cid = READ_ONCE(dst_pcpu_cid->cid);
++ if (!mm_cid_is_unset(dst_cid) &&
++ atomic_read(&mm->mm_users) >= t->nr_cpus_allowed)
++ return;
++ src_pcpu_cid = per_cpu_ptr(mm->pcpu_cid, src_cpu);
++ src_rq = cpu_rq(src_cpu);
++ src_cid = __sched_mm_cid_migrate_from_fetch_cid(src_rq, t, src_pcpu_cid);
++ if (src_cid == -1)
++ return;
++ src_cid = __sched_mm_cid_migrate_from_try_steal_cid(src_rq, t, src_pcpu_cid,
++ src_cid);
++ if (src_cid == -1)
++ return;
++ if (!mm_cid_is_unset(dst_cid)) {
++ __mm_cid_put(mm, src_cid);
++ return;
++ }
++ /* Move src_cid to dst cpu. */
++ mm_cid_snapshot_time(dst_rq, mm);
++ WRITE_ONCE(dst_pcpu_cid->cid, src_cid);
++}
++
++static void sched_mm_cid_remote_clear(struct mm_struct *mm, struct mm_cid *pcpu_cid,
++ int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++ struct task_struct *t;
++ int cid, lazy_cid;
++
++ cid = READ_ONCE(pcpu_cid->cid);
++ if (!mm_cid_is_valid(cid))
++ return;
++
++ /*
++ * Clear the cpu cid if it is set to keep cid allocation compact. If
++ * there happens to be other tasks left on the source cpu using this
++ * mm, the next task using this mm will reallocate its cid on context
++ * switch.
++ */
++ lazy_cid = mm_cid_set_lazy_put(cid);
++ if (!try_cmpxchg(&pcpu_cid->cid, &cid, lazy_cid))
++ return;
++
++ /*
++ * The implicit barrier after cmpxchg per-mm/cpu cid before loading
++ * rq->curr->mm matches the scheduler barrier in context_switch()
++ * between store to rq->curr and load of prev and next task's
++ * per-mm/cpu cid.
++ *
++ * The implicit barrier after cmpxchg per-mm/cpu cid before loading
++ * rq->curr->mm_cid_active matches the barrier in
++ * sched_mm_cid_exit_signals(), sched_mm_cid_before_execve(), and
++ * sched_mm_cid_after_execve() between store to t->mm_cid_active and
++ * load of per-mm/cpu cid.
++ */
++
++ /*
++ * If we observe an active task using the mm on this rq after setting
++ * the lazy-put flag, that task will be responsible for transitioning
++ * from lazy-put flag set to MM_CID_UNSET.
++ */
++ scoped_guard (rcu) {
++ t = rcu_dereference(rq->curr);
++ if (READ_ONCE(t->mm_cid_active) && t->mm == mm)
++ return;
++ }
++
++ /*
++ * The cid is unused, so it can be unset.
++ * Disable interrupts to keep the window of cid ownership without rq
++ * lock small.
++ */
++ scoped_guard (irqsave) {
++ if (try_cmpxchg(&pcpu_cid->cid, &lazy_cid, MM_CID_UNSET))
++ __mm_cid_put(mm, cid);
++ }
++}
++
++static void sched_mm_cid_remote_clear_old(struct mm_struct *mm, int cpu)
++{
++ struct rq *rq = cpu_rq(cpu);
++ struct mm_cid *pcpu_cid;
++ struct task_struct *curr;
++ u64 rq_clock;
++
++ /*
++ * rq->clock load is racy on 32-bit but one spurious clear once in a
++ * while is irrelevant.
++ */
++ rq_clock = READ_ONCE(rq->clock);
++ pcpu_cid = per_cpu_ptr(mm->pcpu_cid, cpu);
++
++ /*
++ * In order to take care of infrequently scheduled tasks, bump the time
++ * snapshot associated with this cid if an active task using the mm is
++ * observed on this rq.
++ */
++ scoped_guard (rcu) {
++ curr = rcu_dereference(rq->curr);
++ if (READ_ONCE(curr->mm_cid_active) && curr->mm == mm) {
++ WRITE_ONCE(pcpu_cid->time, rq_clock);
++ return;
++ }
++ }
++
++ if (rq_clock < pcpu_cid->time + SCHED_MM_CID_PERIOD_NS)
++ return;
++ sched_mm_cid_remote_clear(mm, pcpu_cid, cpu);
++}
++
++static void sched_mm_cid_remote_clear_weight(struct mm_struct *mm, int cpu,
++ int weight)
++{
++ struct mm_cid *pcpu_cid;
++ int cid;
++
++ pcpu_cid = per_cpu_ptr(mm->pcpu_cid, cpu);
++ cid = READ_ONCE(pcpu_cid->cid);
++ if (!mm_cid_is_valid(cid) || cid < weight)
++ return;
++ sched_mm_cid_remote_clear(mm, pcpu_cid, cpu);
++}
++
++static void task_mm_cid_work(struct callback_head *work)
++{
++ unsigned long now = jiffies, old_scan, next_scan;
++ struct task_struct *t = current;
++ struct cpumask *cidmask;
++ struct mm_struct *mm;
++ int weight, cpu;
++
++ SCHED_WARN_ON(t != container_of(work, struct task_struct, cid_work));
++
++ work->next = work; /* Prevent double-add */
++ if (t->flags & PF_EXITING)
++ return;
++ mm = t->mm;
++ if (!mm)
++ return;
++ old_scan = READ_ONCE(mm->mm_cid_next_scan);
++ next_scan = now + msecs_to_jiffies(MM_CID_SCAN_DELAY);
++ if (!old_scan) {
++ unsigned long res;
++
++ res = cmpxchg(&mm->mm_cid_next_scan, old_scan, next_scan);
++ if (res != old_scan)
++ old_scan = res;
++ else
++ old_scan = next_scan;
++ }
++ if (time_before(now, old_scan))
++ return;
++ if (!try_cmpxchg(&mm->mm_cid_next_scan, &old_scan, next_scan))
++ return;
++ cidmask = mm_cidmask(mm);
++ /* Clear cids that were not recently used. */
++ for_each_possible_cpu(cpu)
++ sched_mm_cid_remote_clear_old(mm, cpu);
++ weight = cpumask_weight(cidmask);
++ /*
++ * Clear cids that are greater or equal to the cidmask weight to
++ * recompact it.
++ */
++ for_each_possible_cpu(cpu)
++ sched_mm_cid_remote_clear_weight(mm, cpu, weight);
++}
++
++void init_sched_mm_cid(struct task_struct *t)
++{
++ struct mm_struct *mm = t->mm;
++ int mm_users = 0;
++
++ if (mm) {
++ mm_users = atomic_read(&mm->mm_users);
++ if (mm_users == 1)
++ mm->mm_cid_next_scan = jiffies + msecs_to_jiffies(MM_CID_SCAN_DELAY);
++ }
++ t->cid_work.next = &t->cid_work; /* Protect against double add */
++ init_task_work(&t->cid_work, task_mm_cid_work);
++}
++
++void task_tick_mm_cid(struct rq *rq, struct task_struct *curr)
++{
++ struct callback_head *work = &curr->cid_work;
++ unsigned long now = jiffies;
++
++ if (!curr->mm || (curr->flags & (PF_EXITING | PF_KTHREAD)) ||
++ work->next != work)
++ return;
++ if (time_before(now, READ_ONCE(curr->mm->mm_cid_next_scan)))
++ return;
++ task_work_add(curr, work, TWA_RESUME);
++}
++
++void sched_mm_cid_exit_signals(struct task_struct *t)
++{
++ struct mm_struct *mm = t->mm;
++ struct rq *rq;
++
++ if (!mm)
++ return;
++
++ preempt_disable();
++ rq = this_rq();
++ guard(rq_lock_irqsave)(rq);
++ preempt_enable_no_resched(); /* holding spinlock */
++ WRITE_ONCE(t->mm_cid_active, 0);
++ /*
++ * Store t->mm_cid_active before loading per-mm/cpu cid.
++ * Matches barrier in sched_mm_cid_remote_clear_old().
++ */
++ smp_mb();
++ mm_cid_put(mm);
++ t->last_mm_cid = t->mm_cid = -1;
++}
++
++void sched_mm_cid_before_execve(struct task_struct *t)
++{
++ struct mm_struct *mm = t->mm;
++ struct rq *rq;
++
++ if (!mm)
++ return;
++
++ preempt_disable();
++ rq = this_rq();
++ guard(rq_lock_irqsave)(rq);
++ preempt_enable_no_resched(); /* holding spinlock */
++ WRITE_ONCE(t->mm_cid_active, 0);
++ /*
++ * Store t->mm_cid_active before loading per-mm/cpu cid.
++ * Matches barrier in sched_mm_cid_remote_clear_old().
++ */
++ smp_mb();
++ mm_cid_put(mm);
++ t->last_mm_cid = t->mm_cid = -1;
++}
++
++void sched_mm_cid_after_execve(struct task_struct *t)
++{
++ struct mm_struct *mm = t->mm;
++ struct rq *rq;
++
++ if (!mm)
++ return;
++
++ preempt_disable();
++ rq = this_rq();
++ scoped_guard (rq_lock_irqsave, rq) {
++ preempt_enable_no_resched(); /* holding spinlock */
++ WRITE_ONCE(t->mm_cid_active, 1);
++ /*
++ * Store t->mm_cid_active before loading per-mm/cpu cid.
++ * Matches barrier in sched_mm_cid_remote_clear_old().
++ */
++ smp_mb();
++ t->last_mm_cid = t->mm_cid = mm_cid_get(rq, mm);
++ }
++ rseq_set_notify_resume(t);
++}
++
++void sched_mm_cid_fork(struct task_struct *t)
++{
++ WARN_ON_ONCE(!t->mm || t->mm_cid != -1);
++ t->mm_cid_active = 1;
++}
++#endif
+diff --git a/kernel/sched/alt_debug.c b/kernel/sched/alt_debug.c
+new file mode 100644
+index 000000000000..1dbd7eb6a434
+--- /dev/null
++++ b/kernel/sched/alt_debug.c
+@@ -0,0 +1,32 @@
++/*
++ * kernel/sched/alt_debug.c
++ *
++ * Print the alt scheduler debugging details
++ *
++ * Author: Alfred Chen
++ * Date : 2020
++ */
++#include "sched.h"
++#include "linux/sched/debug.h"
++
++/*
++ * This allows printing both to /proc/sched_debug and
++ * to the console
++ */
++#define SEQ_printf(m, x...) \
++ do { \
++ if (m) \
++ seq_printf(m, x); \
++ else \
++ pr_cont(x); \
++ } while (0)
++
++void proc_sched_show_task(struct task_struct *p, struct pid_namespace *ns,
++ struct seq_file *m)
++{
++ SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, task_pid_nr_ns(p, ns),
++ get_nr_threads(p));
++}
++
++void proc_sched_set_task(struct task_struct *p)
++{}
+diff --git a/kernel/sched/alt_sched.h b/kernel/sched/alt_sched.h
+new file mode 100644
+index 000000000000..ba1b7b805f1a
+--- /dev/null
++++ b/kernel/sched/alt_sched.h
+@@ -0,0 +1,975 @@
++#ifndef ALT_SCHED_H
++#define ALT_SCHED_H
++
++#include <linux/context_tracking.h>
++#include <linux/profile.h>
++#include <linux/stop_machine.h>
++#include <linux/syscalls.h>
++#include <linux/tick.h>
++
++#include <trace/events/power.h>
++#include <trace/events/sched.h>
++
++#include "../workqueue_internal.h"
++
++#include "cpupri.h"
++
++#ifdef CONFIG_CGROUP_SCHED
++/* task group related information */
++struct task_group {
++ struct cgroup_subsys_state css;
++
++ struct rcu_head rcu;
++ struct list_head list;
++
++ struct task_group *parent;
++ struct list_head siblings;
++ struct list_head children;
++#ifdef CONFIG_FAIR_GROUP_SCHED
++ unsigned long shares;
++#endif
++};
++
++extern struct task_group *sched_create_group(struct task_group *parent);
++extern void sched_online_group(struct task_group *tg,
++ struct task_group *parent);
++extern void sched_destroy_group(struct task_group *tg);
++extern void sched_release_group(struct task_group *tg);
++#endif /* CONFIG_CGROUP_SCHED */
++
++#define MIN_SCHED_NORMAL_PRIO (32)
++/*
++ * levels: RT(0-24), reserved(25-31), NORMAL(32-63), cpu idle task(64)
++ *
++ * -- BMQ --
++ * NORMAL: (lower boost range 12, NICE_WIDTH 40, higher boost range 12) / 2
++ * -- PDS --
++ * NORMAL: SCHED_EDGE_DELTA + ((NICE_WIDTH 40) / 2)
++ */
++#define SCHED_LEVELS (64 + 1)
++
++#define IDLE_TASK_SCHED_PRIO (SCHED_LEVELS - 1)
++
++#ifdef CONFIG_SCHED_DEBUG
++# define SCHED_WARN_ON(x) WARN_ONCE(x, #x)
++extern void resched_latency_warn(int cpu, u64 latency);
++#else
++# define SCHED_WARN_ON(x) ({ (void)(x), 0; })
++static inline void resched_latency_warn(int cpu, u64 latency) {}
++#endif
++
++/*
++ * Increase resolution of nice-level calculations for 64-bit architectures.
++ * The extra resolution improves shares distribution and load balancing of
++ * low-weight task groups (eg. nice +19 on an autogroup), deeper taskgroup
++ * hierarchies, especially on larger systems. This is not a user-visible change
++ * and does not change the user-interface for setting shares/weights.
++ *
++ * We increase resolution only if we have enough bits to allow this increased
++ * resolution (i.e. 64-bit). The costs for increasing resolution when 32-bit
++ * are pretty high and the returns do not justify the increased costs.
++ *
++ * Really only required when CONFIG_FAIR_GROUP_SCHED=y is also set, but to
++ * increase coverage and consistency always enable it on 64-bit platforms.
++ */
++#ifdef CONFIG_64BIT
++# define NICE_0_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT + SCHED_FIXEDPOINT_SHIFT)
++# define scale_load(w) ((w) << SCHED_FIXEDPOINT_SHIFT)
++# define scale_load_down(w) \
++({ \
++ unsigned long __w = (w); \
++ if (__w) \
++ __w = max(2UL, __w >> SCHED_FIXEDPOINT_SHIFT); \
++ __w; \
++})
++#else
++# define NICE_0_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT)
++# define scale_load(w) (w)
++# define scale_load_down(w) (w)
++#endif
++
++#ifdef CONFIG_FAIR_GROUP_SCHED
++#define ROOT_TASK_GROUP_LOAD NICE_0_LOAD
++
++/*
++ * A weight of 0 or 1 can cause arithmetics problems.
++ * A weight of a cfs_rq is the sum of weights of which entities
++ * are queued on this cfs_rq, so a weight of a entity should not be
++ * too large, so as the shares value of a task group.
++ * (The default weight is 1024 - so there's no practical
++ * limitation from this.)
++ */
++#define MIN_SHARES (1UL << 1)
++#define MAX_SHARES (1UL << 18)
++#endif
++
++/*
++ * Tunables that become constants when CONFIG_SCHED_DEBUG is off:
++ */
++#ifdef CONFIG_SCHED_DEBUG
++# define const_debug __read_mostly
++#else
++# define const_debug const
++#endif
++
++/* task_struct::on_rq states: */
++#define TASK_ON_RQ_QUEUED 1
++#define TASK_ON_RQ_MIGRATING 2
++
++static inline int task_on_rq_queued(struct task_struct *p)
++{
++ return p->on_rq == TASK_ON_RQ_QUEUED;
++}
++
++static inline int task_on_rq_migrating(struct task_struct *p)
++{
++ return READ_ONCE(p->on_rq) == TASK_ON_RQ_MIGRATING;
++}
++
++/* Wake flags. The first three directly map to some SD flag value */
++#define WF_EXEC 0x02 /* Wakeup after exec; maps to SD_BALANCE_EXEC */
++#define WF_FORK 0x04 /* Wakeup after fork; maps to SD_BALANCE_FORK */
++#define WF_TTWU 0x08 /* Wakeup; maps to SD_BALANCE_WAKE */
++
++#define WF_SYNC 0x10 /* Waker goes to sleep after wakeup */
++#define WF_MIGRATED 0x20 /* Internal use, task got migrated */
++#define WF_CURRENT_CPU 0x40 /* Prefer to move the wakee to the current CPU. */
++
++#ifdef CONFIG_SMP
++static_assert(WF_EXEC == SD_BALANCE_EXEC);
++static_assert(WF_FORK == SD_BALANCE_FORK);
++static_assert(WF_TTWU == SD_BALANCE_WAKE);
++#endif
++
++#define SCHED_QUEUE_BITS (SCHED_LEVELS - 1)
++
++struct sched_queue {
++ DECLARE_BITMAP(bitmap, SCHED_QUEUE_BITS);
++ struct list_head heads[SCHED_LEVELS];
++};
++
++struct rq;
++struct cpuidle_state;
++
++struct balance_callback {
++ struct balance_callback *next;
++ void (*func)(struct rq *rq);
++};
++
++/*
++ * This is the main, per-CPU runqueue data structure.
++ * This data should only be modified by the local cpu.
++ */
++struct rq {
++ /* runqueue lock: */
++ raw_spinlock_t lock;
++
++ struct task_struct __rcu *curr;
++ struct task_struct *idle;
++ struct task_struct *stop;
++ struct mm_struct *prev_mm;
++
++ struct sched_queue queue ____cacheline_aligned;
++#ifdef CONFIG_SCHED_PDS
++ u64 time_edge;
++ unsigned long prio_idx;
++#endif
++ unsigned long prio;
++
++ /* switch count */
++ u64 nr_switches;
++
++ atomic_t nr_iowait;
++
++#ifdef CONFIG_SCHED_DEBUG
++ u64 last_seen_need_resched_ns;
++ int ticks_without_resched;
++#endif
++
++#ifdef CONFIG_MEMBARRIER
++ int membarrier_state;
++#endif
++
++#ifdef CONFIG_SMP
++ int cpu; /* cpu of this runqueue */
++ bool online;
++
++ unsigned int ttwu_pending;
++ unsigned char nohz_idle_balance;
++ unsigned char idle_balance;
++
++#ifdef CONFIG_HAVE_SCHED_AVG_IRQ
++ struct sched_avg avg_irq;
++#endif
++
++#ifdef CONFIG_SCHED_SMT
++ int active_balance;
++ struct cpu_stop_work active_balance_work;
++#endif
++ struct balance_callback *balance_callback;
++#ifdef CONFIG_HOTPLUG_CPU
++ struct rcuwait hotplug_wait;
++#endif
++ unsigned int nr_pinned;
++
++#endif /* CONFIG_SMP */
++#ifdef CONFIG_IRQ_TIME_ACCOUNTING
++ u64 prev_irq_time;
++#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
++#ifdef CONFIG_PARAVIRT
++ u64 prev_steal_time;
++#endif /* CONFIG_PARAVIRT */
++#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
++ u64 prev_steal_time_rq;
++#endif /* CONFIG_PARAVIRT_TIME_ACCOUNTING */
++
++ /* For genenal cpu load util */
++ s32 load_history;
++ u64 load_block;
++ u64 load_stamp;
++
++ /* calc_load related fields */
++ unsigned long calc_load_update;
++ long calc_load_active;
++
++ /* Ensure that all clocks are in the same cache line */
++ u64 clock ____cacheline_aligned;
++ u64 clock_task;
++#ifdef CONFIG_SCHED_BMQ
++ u64 last_ts_switch;
++#endif
++
++ unsigned int nr_running;
++ unsigned long nr_uninterruptible;
++
++#ifdef CONFIG_SCHED_HRTICK
++#ifdef CONFIG_SMP
++ call_single_data_t hrtick_csd;
++#endif
++ struct hrtimer hrtick_timer;
++ ktime_t hrtick_time;
++#endif
++
++#ifdef CONFIG_SCHEDSTATS
++
++ /* latency stats */
++ struct sched_info rq_sched_info;
++ unsigned long long rq_cpu_time;
++ /* could above be rq->cfs_rq.exec_clock + rq->rt_rq.rt_runtime ? */
++
++ /* sys_sched_yield() stats */
++ unsigned int yld_count;
++
++ /* schedule() stats */
++ unsigned int sched_switch;
++ unsigned int sched_count;
++ unsigned int sched_goidle;
++
++ /* try_to_wake_up() stats */
++ unsigned int ttwu_count;
++ unsigned int ttwu_local;
++#endif /* CONFIG_SCHEDSTATS */
++
++#ifdef CONFIG_CPU_IDLE
++ /* Must be inspected within a rcu lock section */
++ struct cpuidle_state *idle_state;
++#endif
++
++#ifdef CONFIG_NO_HZ_COMMON
++#ifdef CONFIG_SMP
++ call_single_data_t nohz_csd;
++#endif
++ atomic_t nohz_flags;
++#endif /* CONFIG_NO_HZ_COMMON */
++
++ /* Scratch cpumask to be temporarily used under rq_lock */
++ cpumask_var_t scratch_mask;
++};
++
++extern unsigned int sysctl_sched_base_slice;
++
++extern unsigned long rq_load_util(struct rq *rq, unsigned long max);
++
++extern unsigned long calc_load_update;
++extern atomic_long_t calc_load_tasks;
++
++extern void calc_global_load_tick(struct rq *this_rq);
++extern long calc_load_fold_active(struct rq *this_rq, long adjust);
++
++DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
++#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu)))
++#define this_rq() this_cpu_ptr(&runqueues)
++#define task_rq(p) cpu_rq(task_cpu(p))
++#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
++#define raw_rq() raw_cpu_ptr(&runqueues)
++
++#ifdef CONFIG_SMP
++#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL)
++void register_sched_domain_sysctl(void);
++void unregister_sched_domain_sysctl(void);
++#else
++static inline void register_sched_domain_sysctl(void)
++{
++}
++static inline void unregister_sched_domain_sysctl(void)
++{
++}
++#endif
++
++extern bool sched_smp_initialized;
++
++enum {
++#ifdef CONFIG_SCHED_SMT
++ SMT_LEVEL_SPACE_HOLDER,
++#endif
++ COREGROUP_LEVEL_SPACE_HOLDER,
++ CORE_LEVEL_SPACE_HOLDER,
++ OTHER_LEVEL_SPACE_HOLDER,
++ NR_CPU_AFFINITY_LEVELS
++};
++
++DECLARE_PER_CPU_ALIGNED(cpumask_t [NR_CPU_AFFINITY_LEVELS], sched_cpu_topo_masks);
++
++static inline int
++__best_mask_cpu(const cpumask_t *cpumask, const cpumask_t *mask)
++{
++ int cpu;
++
++ while ((cpu = cpumask_any_and(cpumask, mask)) >= nr_cpu_ids)
++ mask++;
++
++ return cpu;
++}
++
++static inline int best_mask_cpu(int cpu, const cpumask_t *mask)
++{
++ return __best_mask_cpu(mask, per_cpu(sched_cpu_topo_masks, cpu));
++}
++
++extern void flush_smp_call_function_queue(void);
++
++#else /* !CONFIG_SMP */
++static inline void flush_smp_call_function_queue(void) { }
++#endif
++
++#ifndef arch_scale_freq_tick
++static __always_inline
++void arch_scale_freq_tick(void)
++{
++}
++#endif
++
++#ifndef arch_scale_freq_capacity
++static __always_inline
++unsigned long arch_scale_freq_capacity(int cpu)
++{
++ return SCHED_CAPACITY_SCALE;
++}
++#endif
++
++static inline u64 __rq_clock_broken(struct rq *rq)
++{
++ return READ_ONCE(rq->clock);
++}
++
++static inline u64 rq_clock(struct rq *rq)
++{
++ /*
++ * Relax lockdep_assert_held() checking as in VRQ, call to
++ * sched_info_xxxx() may not held rq->lock
++ * lockdep_assert_held(&rq->lock);
++ */
++ return rq->clock;
++}
++
++static inline u64 rq_clock_task(struct rq *rq)
++{
++ /*
++ * Relax lockdep_assert_held() checking as in VRQ, call to
++ * sched_info_xxxx() may not held rq->lock
++ * lockdep_assert_held(&rq->lock);
++ */
++ return rq->clock_task;
++}
++
++/*
++ * {de,en}queue flags:
++ *
++ * DEQUEUE_SLEEP - task is no longer runnable
++ * ENQUEUE_WAKEUP - task just became runnable
++ *
++ */
++
++#define DEQUEUE_SLEEP 0x01
++
++#define ENQUEUE_WAKEUP 0x01
++
++
++/*
++ * Below are scheduler API which using in other kernel code
++ * It use the dummy rq_flags
++ * ToDo : BMQ need to support these APIs for compatibility with mainline
++ * scheduler code.
++ */
++struct rq_flags {
++ unsigned long flags;
++};
++
++struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf)
++ __acquires(rq->lock);
++
++struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf)
++ __acquires(p->pi_lock)
++ __acquires(rq->lock);
++
++static inline void __task_rq_unlock(struct rq *rq, struct rq_flags *rf)
++ __releases(rq->lock)
++{
++ raw_spin_unlock(&rq->lock);
++}
++
++static inline void
++task_rq_unlock(struct rq *rq, struct task_struct *p, struct rq_flags *rf)
++ __releases(rq->lock)
++ __releases(p->pi_lock)
++{
++ raw_spin_unlock(&rq->lock);
++ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags);
++}
++
++static inline void
++rq_lock(struct rq *rq, struct rq_flags *rf)
++ __acquires(rq->lock)
++{
++ raw_spin_lock(&rq->lock);
++}
++
++static inline void
++rq_unlock(struct rq *rq, struct rq_flags *rf)
++ __releases(rq->lock)
++{
++ raw_spin_unlock(&rq->lock);
++}
++
++static inline void
++rq_lock_irq(struct rq *rq, struct rq_flags *rf)
++ __acquires(rq->lock)
++{
++ raw_spin_lock_irq(&rq->lock);
++}
++
++static inline void
++rq_unlock_irq(struct rq *rq, struct rq_flags *rf)
++ __releases(rq->lock)
++{
++ raw_spin_unlock_irq(&rq->lock);
++}
++
++static inline struct rq *
++this_rq_lock_irq(struct rq_flags *rf)
++ __acquires(rq->lock)
++{
++ struct rq *rq;
++
++ local_irq_disable();
++ rq = this_rq();
++ raw_spin_lock(&rq->lock);
++
++ return rq;
++}
++
++static inline raw_spinlock_t *__rq_lockp(struct rq *rq)
++{
++ return &rq->lock;
++}
++
++static inline raw_spinlock_t *rq_lockp(struct rq *rq)
++{
++ return __rq_lockp(rq);
++}
++
++static inline void lockdep_assert_rq_held(struct rq *rq)
++{
++ lockdep_assert_held(__rq_lockp(rq));
++}
++
++extern void raw_spin_rq_lock_nested(struct rq *rq, int subclass);
++extern void raw_spin_rq_unlock(struct rq *rq);
++
++static inline void raw_spin_rq_lock(struct rq *rq)
++{
++ raw_spin_rq_lock_nested(rq, 0);
++}
++
++static inline void raw_spin_rq_lock_irq(struct rq *rq)
++{
++ local_irq_disable();
++ raw_spin_rq_lock(rq);
++}
++
++static inline void raw_spin_rq_unlock_irq(struct rq *rq)
++{
++ raw_spin_rq_unlock(rq);
++ local_irq_enable();
++}
++
++static inline int task_current(struct rq *rq, struct task_struct *p)
++{
++ return rq->curr == p;
++}
++
++static inline bool task_on_cpu(struct task_struct *p)
++{
++ return p->on_cpu;
++}
++
++extern int task_running_nice(struct task_struct *p);
++
++extern struct static_key_false sched_schedstats;
++
++#ifdef CONFIG_CPU_IDLE
++static inline void idle_set_state(struct rq *rq,
++ struct cpuidle_state *idle_state)
++{
++ rq->idle_state = idle_state;
++}
++
++static inline struct cpuidle_state *idle_get_state(struct rq *rq)
++{
++ WARN_ON(!rcu_read_lock_held());
++ return rq->idle_state;
++}
++#else
++static inline void idle_set_state(struct rq *rq,
++ struct cpuidle_state *idle_state)
++{
++}
++
++static inline struct cpuidle_state *idle_get_state(struct rq *rq)
++{
++ return NULL;
++}
++#endif
++
++static inline int cpu_of(const struct rq *rq)
++{
++#ifdef CONFIG_SMP
++ return rq->cpu;
++#else
++ return 0;
++#endif
++}
++
++extern void resched_cpu(int cpu);
++
++#include "stats.h"
++
++#ifdef CONFIG_NO_HZ_COMMON
++#define NOHZ_BALANCE_KICK_BIT 0
++#define NOHZ_STATS_KICK_BIT 1
++
++#define NOHZ_BALANCE_KICK BIT(NOHZ_BALANCE_KICK_BIT)
++#define NOHZ_STATS_KICK BIT(NOHZ_STATS_KICK_BIT)
++
++#define NOHZ_KICK_MASK (NOHZ_BALANCE_KICK | NOHZ_STATS_KICK)
++
++#define nohz_flags(cpu) (&cpu_rq(cpu)->nohz_flags)
++
++/* TODO: needed?
++extern void nohz_balance_exit_idle(struct rq *rq);
++#else
++static inline void nohz_balance_exit_idle(struct rq *rq) { }
++*/
++#endif
++
++#ifdef CONFIG_IRQ_TIME_ACCOUNTING
++struct irqtime {
++ u64 total;
++ u64 tick_delta;
++ u64 irq_start_time;
++ struct u64_stats_sync sync;
++};
++
++DECLARE_PER_CPU(struct irqtime, cpu_irqtime);
++
++/*
++ * Returns the irqtime minus the softirq time computed by ksoftirqd.
++ * Otherwise ksoftirqd's sum_exec_runtime is substracted its own runtime
++ * and never move forward.
++ */
++static inline u64 irq_time_read(int cpu)
++{
++ struct irqtime *irqtime = &per_cpu(cpu_irqtime, cpu);
++ unsigned int seq;
++ u64 total;
++
++ do {
++ seq = __u64_stats_fetch_begin(&irqtime->sync);
++ total = irqtime->total;
++ } while (__u64_stats_fetch_retry(&irqtime->sync, seq));
++
++ return total;
++}
++#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
++
++#ifdef CONFIG_CPU_FREQ
++DECLARE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
++#endif /* CONFIG_CPU_FREQ */
++
++#ifdef CONFIG_NO_HZ_FULL
++extern int __init sched_tick_offload_init(void);
++#else
++static inline int sched_tick_offload_init(void) { return 0; }
++#endif
++
++#ifdef arch_scale_freq_capacity
++#ifndef arch_scale_freq_invariant
++#define arch_scale_freq_invariant() (true)
++#endif
++#else /* arch_scale_freq_capacity */
++#define arch_scale_freq_invariant() (false)
++#endif
++
++#ifdef CONFIG_SMP
++unsigned long sugov_effective_cpu_perf(int cpu, unsigned long actual,
++ unsigned long min,
++ unsigned long max);
++#endif /* CONFIG_SMP */
++
++extern void schedule_idle(void);
++
++#define cap_scale(v, s) ((v)*(s) >> SCHED_CAPACITY_SHIFT)
++
++/*
++ * !! For sched_setattr_nocheck() (kernel) only !!
++ *
++ * This is actually gross. :(
++ *
++ * It is used to make schedutil kworker(s) higher priority than SCHED_DEADLINE
++ * tasks, but still be able to sleep. We need this on platforms that cannot
++ * atomically change clock frequency. Remove once fast switching will be
++ * available on such platforms.
++ *
++ * SUGOV stands for SchedUtil GOVernor.
++ */
++#define SCHED_FLAG_SUGOV 0x10000000
++
++#ifdef CONFIG_MEMBARRIER
++/*
++ * The scheduler provides memory barriers required by membarrier between:
++ * - prior user-space memory accesses and store to rq->membarrier_state,
++ * - store to rq->membarrier_state and following user-space memory accesses.
++ * In the same way it provides those guarantees around store to rq->curr.
++ */
++static inline void membarrier_switch_mm(struct rq *rq,
++ struct mm_struct *prev_mm,
++ struct mm_struct *next_mm)
++{
++ int membarrier_state;
++
++ if (prev_mm == next_mm)
++ return;
++
++ membarrier_state = atomic_read(&next_mm->membarrier_state);
++ if (READ_ONCE(rq->membarrier_state) == membarrier_state)
++ return;
++
++ WRITE_ONCE(rq->membarrier_state, membarrier_state);
++}
++#else
++static inline void membarrier_switch_mm(struct rq *rq,
++ struct mm_struct *prev_mm,
++ struct mm_struct *next_mm)
++{
++}
++#endif
++
++#ifdef CONFIG_NUMA
++extern int sched_numa_find_closest(const struct cpumask *cpus, int cpu);
++#else
++static inline int sched_numa_find_closest(const struct cpumask *cpus, int cpu)
++{
++ return nr_cpu_ids;
++}
++#endif
++
++extern void swake_up_all_locked(struct swait_queue_head *q);
++extern void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait);
++
++extern int try_to_wake_up(struct task_struct *tsk, unsigned int state, int wake_flags);
++
++#ifdef CONFIG_PREEMPT_DYNAMIC
++extern int preempt_dynamic_mode;
++extern int sched_dynamic_mode(const char *str);
++extern void sched_dynamic_update(int mode);
++#endif
++
++static inline void nohz_run_idle_balance(int cpu) { }
++
++static inline
++unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util,
++ struct task_struct *p)
++{
++ return util;
++}
++
++static inline bool uclamp_rq_is_capped(struct rq *rq) { return false; }
++
++#ifdef CONFIG_SCHED_MM_CID
++
++#define SCHED_MM_CID_PERIOD_NS (100ULL * 1000000) /* 100ms */
++#define MM_CID_SCAN_DELAY 100 /* 100ms */
++
++extern raw_spinlock_t cid_lock;
++extern int use_cid_lock;
++
++extern void sched_mm_cid_migrate_from(struct task_struct *t);
++extern void sched_mm_cid_migrate_to(struct rq *dst_rq, struct task_struct *t, int src_cpu);
++extern void task_tick_mm_cid(struct rq *rq, struct task_struct *curr);
++extern void init_sched_mm_cid(struct task_struct *t);
++
++static inline void __mm_cid_put(struct mm_struct *mm, int cid)
++{
++ if (cid < 0)
++ return;
++ cpumask_clear_cpu(cid, mm_cidmask(mm));
++}
++
++/*
++ * The per-mm/cpu cid can have the MM_CID_LAZY_PUT flag set or transition to
++ * the MM_CID_UNSET state without holding the rq lock, but the rq lock needs to
++ * be held to transition to other states.
++ *
++ * State transitions synchronized with cmpxchg or try_cmpxchg need to be
++ * consistent across cpus, which prevents use of this_cpu_cmpxchg.
++ */
++static inline void mm_cid_put_lazy(struct task_struct *t)
++{
++ struct mm_struct *mm = t->mm;
++ struct mm_cid __percpu *pcpu_cid = mm->pcpu_cid;
++ int cid;
++
++ lockdep_assert_irqs_disabled();
++ cid = __this_cpu_read(pcpu_cid->cid);
++ if (!mm_cid_is_lazy_put(cid) ||
++ !try_cmpxchg(&this_cpu_ptr(pcpu_cid)->cid, &cid, MM_CID_UNSET))
++ return;
++ __mm_cid_put(mm, mm_cid_clear_lazy_put(cid));
++}
++
++static inline int mm_cid_pcpu_unset(struct mm_struct *mm)
++{
++ struct mm_cid __percpu *pcpu_cid = mm->pcpu_cid;
++ int cid, res;
++
++ lockdep_assert_irqs_disabled();
++ cid = __this_cpu_read(pcpu_cid->cid);
++ for (;;) {
++ if (mm_cid_is_unset(cid))
++ return MM_CID_UNSET;
++ /*
++ * Attempt transition from valid or lazy-put to unset.
++ */
++ res = cmpxchg(&this_cpu_ptr(pcpu_cid)->cid, cid, MM_CID_UNSET);
++ if (res == cid)
++ break;
++ cid = res;
++ }
++ return cid;
++}
++
++static inline void mm_cid_put(struct mm_struct *mm)
++{
++ int cid;
++
++ lockdep_assert_irqs_disabled();
++ cid = mm_cid_pcpu_unset(mm);
++ if (cid == MM_CID_UNSET)
++ return;
++ __mm_cid_put(mm, mm_cid_clear_lazy_put(cid));
++}
++
++static inline int __mm_cid_try_get(struct mm_struct *mm)
++{
++ struct cpumask *cpumask;
++ int cid;
++
++ cpumask = mm_cidmask(mm);
++ /*
++ * Retry finding first zero bit if the mask is temporarily
++ * filled. This only happens during concurrent remote-clear
++ * which owns a cid without holding a rq lock.
++ */
++ for (;;) {
++ cid = cpumask_first_zero(cpumask);
++ if (cid < nr_cpu_ids)
++ break;
++ cpu_relax();
++ }
++ if (cpumask_test_and_set_cpu(cid, cpumask))
++ return -1;
++ return cid;
++}
++
++/*
++ * Save a snapshot of the current runqueue time of this cpu
++ * with the per-cpu cid value, allowing to estimate how recently it was used.
++ */
++static inline void mm_cid_snapshot_time(struct rq *rq, struct mm_struct *mm)
++{
++ struct mm_cid *pcpu_cid = per_cpu_ptr(mm->pcpu_cid, cpu_of(rq));
++
++ lockdep_assert_rq_held(rq);
++ WRITE_ONCE(pcpu_cid->time, rq->clock);
++}
++
++static inline int __mm_cid_get(struct rq *rq, struct mm_struct *mm)
++{
++ int cid;
++
++ /*
++ * All allocations (even those using the cid_lock) are lock-free. If
++ * use_cid_lock is set, hold the cid_lock to perform cid allocation to
++ * guarantee forward progress.
++ */
++ if (!READ_ONCE(use_cid_lock)) {
++ cid = __mm_cid_try_get(mm);
++ if (cid >= 0)
++ goto end;
++ raw_spin_lock(&cid_lock);
++ } else {
++ raw_spin_lock(&cid_lock);
++ cid = __mm_cid_try_get(mm);
++ if (cid >= 0)
++ goto unlock;
++ }
++
++ /*
++ * cid concurrently allocated. Retry while forcing following
++ * allocations to use the cid_lock to ensure forward progress.
++ */
++ WRITE_ONCE(use_cid_lock, 1);
++ /*
++ * Set use_cid_lock before allocation. Only care about program order
++ * because this is only required for forward progress.
++ */
++ barrier();
++ /*
++ * Retry until it succeeds. It is guaranteed to eventually succeed once
++ * all newcoming allocations observe the use_cid_lock flag set.
++ */
++ do {
++ cid = __mm_cid_try_get(mm);
++ cpu_relax();
++ } while (cid < 0);
++ /*
++ * Allocate before clearing use_cid_lock. Only care about
++ * program order because this is for forward progress.
++ */
++ barrier();
++ WRITE_ONCE(use_cid_lock, 0);
++unlock:
++ raw_spin_unlock(&cid_lock);
++end:
++ mm_cid_snapshot_time(rq, mm);
++ return cid;
++}
++
++static inline int mm_cid_get(struct rq *rq, struct mm_struct *mm)
++{
++ struct mm_cid __percpu *pcpu_cid = mm->pcpu_cid;
++ struct cpumask *cpumask;
++ int cid;
++
++ lockdep_assert_rq_held(rq);
++ cpumask = mm_cidmask(mm);
++ cid = __this_cpu_read(pcpu_cid->cid);
++ if (mm_cid_is_valid(cid)) {
++ mm_cid_snapshot_time(rq, mm);
++ return cid;
++ }
++ if (mm_cid_is_lazy_put(cid)) {
++ if (try_cmpxchg(&this_cpu_ptr(pcpu_cid)->cid, &cid, MM_CID_UNSET))
++ __mm_cid_put(mm, mm_cid_clear_lazy_put(cid));
++ }
++ cid = __mm_cid_get(rq, mm);
++ __this_cpu_write(pcpu_cid->cid, cid);
++ return cid;
++}
++
++static inline void switch_mm_cid(struct rq *rq,
++ struct task_struct *prev,
++ struct task_struct *next)
++{
++ /*
++ * Provide a memory barrier between rq->curr store and load of
++ * {prev,next}->mm->pcpu_cid[cpu] on rq->curr->mm transition.
++ *
++ * Should be adapted if context_switch() is modified.
++ */
++ if (!next->mm) { // to kernel
++ /*
++ * user -> kernel transition does not guarantee a barrier, but
++ * we can use the fact that it performs an atomic operation in
++ * mmgrab().
++ */
++ if (prev->mm) // from user
++ smp_mb__after_mmgrab();
++ /*
++ * kernel -> kernel transition does not change rq->curr->mm
++ * state. It stays NULL.
++ */
++ } else { // to user
++ /*
++ * kernel -> user transition does not provide a barrier
++ * between rq->curr store and load of {prev,next}->mm->pcpu_cid[cpu].
++ * Provide it here.
++ */
++ if (!prev->mm) // from kernel
++ smp_mb();
++ /*
++ * user -> user transition guarantees a memory barrier through
++ * switch_mm() when current->mm changes. If current->mm is
++ * unchanged, no barrier is needed.
++ */
++ }
++ if (prev->mm_cid_active) {
++ mm_cid_snapshot_time(rq, prev->mm);
++ mm_cid_put_lazy(prev);
++ prev->mm_cid = -1;
++ }
++ if (next->mm_cid_active)
++ next->last_mm_cid = next->mm_cid = mm_cid_get(rq, next->mm);
++}
++
++#else
++static inline void switch_mm_cid(struct rq *rq, struct task_struct *prev, struct task_struct *next) { }
++static inline void sched_mm_cid_migrate_from(struct task_struct *t) { }
++static inline void sched_mm_cid_migrate_to(struct rq *dst_rq, struct task_struct *t, int src_cpu) { }
++static inline void task_tick_mm_cid(struct rq *rq, struct task_struct *curr) { }
++static inline void init_sched_mm_cid(struct task_struct *t) { }
++#endif
++
++#ifdef CONFIG_SMP
++extern struct balance_callback balance_push_callback;
++
++static inline void
++__queue_balance_callback(struct rq *rq,
++ struct balance_callback *head)
++{
++ lockdep_assert_rq_held(rq);
++
++ /*
++ * Don't (re)queue an already queued item; nor queue anything when
++ * balance_push() is active, see the comment with
++ * balance_push_callback.
++ */
++ if (unlikely(head->next || rq->balance_callback == &balance_push_callback))
++ return;
++
++ head->next = rq->balance_callback;
++ rq->balance_callback = head;
++}
++#endif /* CONFIG_SMP */
++
++#endif /* ALT_SCHED_H */
+diff --git a/kernel/sched/bmq.h b/kernel/sched/bmq.h
+new file mode 100644
+index 000000000000..f270fd1b9086
+--- /dev/null
++++ b/kernel/sched/bmq.h
+@@ -0,0 +1,102 @@
++#define ALT_SCHED_NAME "BMQ"
++
++/*
++ * BMQ only routines
++ */
++#define rq_switch_time(rq) ((rq)->clock - (rq)->last_ts_switch)
++#define boost_threshold(p) (sysctl_sched_base_slice >> ((20 - (p)->boost_prio) / 2))
++
++static inline void boost_task(struct task_struct *p)
++{
++ int limit;
++
++ switch (p->policy) {
++ case SCHED_NORMAL:
++ limit = -MAX_PRIORITY_ADJ;
++ break;
++ case SCHED_BATCH:
++ limit = 0;
++ break;
++ default:
++ return;
++ }
++
++ if (p->boost_prio > limit)
++ p->boost_prio--;
++}
++
++static inline void deboost_task(struct task_struct *p)
++{
++ if (p->boost_prio < MAX_PRIORITY_ADJ)
++ p->boost_prio++;
++}
++
++/*
++ * Common interfaces
++ */
++static inline void sched_timeslice_imp(const int timeslice_ms) {}
++
++/* This API is used in task_prio(), return value readed by human users */
++static inline int
++task_sched_prio_normal(const struct task_struct *p, const struct rq *rq)
++{
++ return p->prio + p->boost_prio - MAX_RT_PRIO;
++}
++
++static inline int task_sched_prio(const struct task_struct *p)
++{
++ return (p->prio < MAX_RT_PRIO)? (p->prio >> 2) :
++ MIN_SCHED_NORMAL_PRIO + (p->prio + p->boost_prio - MAX_RT_PRIO) / 2;
++}
++
++#define TASK_SCHED_PRIO_IDX(p, rq, idx, prio) \
++ prio = task_sched_prio(p); \
++ idx = prio;
++
++static inline int sched_prio2idx(int prio, struct rq *rq)
++{
++ return prio;
++}
++
++static inline int sched_idx2prio(int idx, struct rq *rq)
++{
++ return idx;
++}
++
++static inline int sched_rq_prio_idx(struct rq *rq)
++{
++ return rq->prio;
++}
++
++inline int task_running_nice(struct task_struct *p)
++{
++ return (p->prio + p->boost_prio > DEFAULT_PRIO + MAX_PRIORITY_ADJ);
++}
++
++static inline void sched_update_rq_clock(struct rq *rq) {}
++
++static inline void sched_task_renew(struct task_struct *p, const struct rq *rq)
++{
++ if (rq_switch_time(rq) > sysctl_sched_base_slice)
++ deboost_task(p);
++}
++
++static inline void sched_task_sanity_check(struct task_struct *p, struct rq *rq) {}
++static void sched_task_fork(struct task_struct *p, struct rq *rq) {}
++
++static inline void do_sched_yield_type_1(struct task_struct *p, struct rq *rq)
++{
++ p->boost_prio = MAX_PRIORITY_ADJ;
++}
++
++static inline void sched_task_ttwu(struct task_struct *p)
++{
++ if(this_rq()->clock_task - p->last_ran > sysctl_sched_base_slice)
++ boost_task(p);
++}
++
++static inline void sched_task_deactivate(struct task_struct *p, struct rq *rq)
++{
++ if (rq_switch_time(rq) < boost_threshold(p))
++ boost_task(p);
++}
+diff --git a/kernel/sched/build_policy.c b/kernel/sched/build_policy.c
+index d9dc9ab3773f..71a25540d65e 100644
+--- a/kernel/sched/build_policy.c
++++ b/kernel/sched/build_policy.c
+@@ -42,13 +42,19 @@
+
+ #include "idle.c"
+
++#ifndef CONFIG_SCHED_ALT
+ #include "rt.c"
++#endif
+
+ #ifdef CONFIG_SMP
++#ifndef CONFIG_SCHED_ALT
+ # include "cpudeadline.c"
++#endif
+ # include "pelt.c"
+ #endif
+
+ #include "cputime.c"
+-#include "deadline.c"
+
++#ifndef CONFIG_SCHED_ALT
++#include "deadline.c"
++#endif
+diff --git a/kernel/sched/build_utility.c b/kernel/sched/build_utility.c
+index 80a3df49ab47..bc17d5a6fc41 100644
+--- a/kernel/sched/build_utility.c
++++ b/kernel/sched/build_utility.c
+@@ -84,7 +84,9 @@
+
+ #ifdef CONFIG_SMP
+ # include "cpupri.c"
++#ifndef CONFIG_SCHED_ALT
+ # include "stop_task.c"
++#endif
+ # include "topology.c"
+ #endif
+
+diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
+index eece6244f9d2..3075127f9e95 100644
+--- a/kernel/sched/cpufreq_schedutil.c
++++ b/kernel/sched/cpufreq_schedutil.c
+@@ -197,12 +197,17 @@ unsigned long sugov_effective_cpu_perf(int cpu, unsigned long actual,
+
+ static void sugov_get_util(struct sugov_cpu *sg_cpu, unsigned long boost)
+ {
++#ifndef CONFIG_SCHED_ALT
+ unsigned long min, max, util = cpu_util_cfs_boost(sg_cpu->cpu);
+
+ util = effective_cpu_util(sg_cpu->cpu, util, &min, &max);
+ util = max(util, boost);
+ sg_cpu->bw_min = min;
+ sg_cpu->util = sugov_effective_cpu_perf(sg_cpu->cpu, util, min, max);
++#else /* CONFIG_SCHED_ALT */
++ sg_cpu->bw_min = 0;
++ sg_cpu->util = rq_load_util(cpu_rq(sg_cpu->cpu), arch_scale_cpu_capacity(sg_cpu->cpu));
++#endif /* CONFIG_SCHED_ALT */
+ }
+
+ /**
+@@ -343,8 +348,10 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; }
+ */
+ static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu)
+ {
++#ifndef CONFIG_SCHED_ALT
+ if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_min)
+ sg_cpu->sg_policy->limits_changed = true;
++#endif
+ }
+
+ static inline bool sugov_update_single_common(struct sugov_cpu *sg_cpu,
+@@ -676,6 +683,7 @@ static int sugov_kthread_create(struct sugov_policy *sg_policy)
+ }
+
+ ret = sched_setattr_nocheck(thread, &attr);
++
+ if (ret) {
+ kthread_stop(thread);
+ pr_warn("%s: failed to set SCHED_DEADLINE\n", __func__);
+diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
+index af7952f12e6c..6461cbbb734d 100644
+--- a/kernel/sched/cputime.c
++++ b/kernel/sched/cputime.c
+@@ -126,7 +126,7 @@ void account_user_time(struct task_struct *p, u64 cputime)
+ p->utime += cputime;
+ account_group_user_time(p, cputime);
+
+- index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER;
++ index = task_running_nice(p) ? CPUTIME_NICE : CPUTIME_USER;
+
+ /* Add user time to cpustat. */
+ task_group_account_field(p, index, cputime);
+@@ -150,7 +150,7 @@ void account_guest_time(struct task_struct *p, u64 cputime)
+ p->gtime += cputime;
+
+ /* Add guest time to cpustat. */
+- if (task_nice(p) > 0) {
++ if (task_running_nice(p)) {
+ task_group_account_field(p, CPUTIME_NICE, cputime);
+ cpustat[CPUTIME_GUEST_NICE] += cputime;
+ } else {
+@@ -288,7 +288,7 @@ static inline u64 account_other_time(u64 max)
+ #ifdef CONFIG_64BIT
+ static inline u64 read_sum_exec_runtime(struct task_struct *t)
+ {
+- return t->se.sum_exec_runtime;
++ return tsk_seruntime(t);
+ }
+ #else
+ static u64 read_sum_exec_runtime(struct task_struct *t)
+@@ -298,7 +298,7 @@ static u64 read_sum_exec_runtime(struct task_struct *t)
+ struct rq *rq;
+
+ rq = task_rq_lock(t, &rf);
+- ns = t->se.sum_exec_runtime;
++ ns = tsk_seruntime(t);
+ task_rq_unlock(rq, t, &rf);
+
+ return ns;
+@@ -630,7 +630,7 @@ void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev,
+ void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st)
+ {
+ struct task_cputime cputime = {
+- .sum_exec_runtime = p->se.sum_exec_runtime,
++ .sum_exec_runtime = tsk_seruntime(p),
+ };
+
+ if (task_cputime(p, &cputime.utime, &cputime.stime))
+diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
+index 8d5d98a5834d..15b9a02717ae 100644
+--- a/kernel/sched/debug.c
++++ b/kernel/sched/debug.c
+@@ -7,6 +7,7 @@
+ * Copyright(C) 2007, Red Hat, Inc., Ingo Molnar
+ */
+
++#ifndef CONFIG_SCHED_ALT
+ /*
+ * This allows printing both to /sys/kernel/debug/sched/debug and
+ * to the console
+@@ -215,6 +216,7 @@ static const struct file_operations sched_scaling_fops = {
+ };
+
+ #endif /* SMP */
++#endif /* !CONFIG_SCHED_ALT */
+
+ #ifdef CONFIG_PREEMPT_DYNAMIC
+
+@@ -278,6 +280,7 @@ static const struct file_operations sched_dynamic_fops = {
+
+ #endif /* CONFIG_PREEMPT_DYNAMIC */
+
++#ifndef CONFIG_SCHED_ALT
+ __read_mostly bool sched_debug_verbose;
+
+ #ifdef CONFIG_SMP
+@@ -332,6 +335,7 @@ static const struct file_operations sched_debug_fops = {
+ .llseek = seq_lseek,
+ .release = seq_release,
+ };
++#endif /* !CONFIG_SCHED_ALT */
+
+ static struct dentry *debugfs_sched;
+
+@@ -341,14 +345,17 @@ static __init int sched_init_debug(void)
+
+ debugfs_sched = debugfs_create_dir("sched", NULL);
+
++#ifndef CONFIG_SCHED_ALT
+ debugfs_create_file("features", 0644, debugfs_sched, NULL, &sched_feat_fops);
+ debugfs_create_file_unsafe("verbose", 0644, debugfs_sched, &sched_debug_verbose, &sched_verbose_fops);
++#endif /* !CONFIG_SCHED_ALT */
+ #ifdef CONFIG_PREEMPT_DYNAMIC
+ debugfs_create_file("preempt", 0644, debugfs_sched, NULL, &sched_dynamic_fops);
+ #endif
+
+ debugfs_create_u32("base_slice_ns", 0644, debugfs_sched, &sysctl_sched_base_slice);
+
++#ifndef CONFIG_SCHED_ALT
+ debugfs_create_u32("latency_warn_ms", 0644, debugfs_sched, &sysctl_resched_latency_warn_ms);
+ debugfs_create_u32("latency_warn_once", 0644, debugfs_sched, &sysctl_resched_latency_warn_once);
+
+@@ -373,11 +380,13 @@ static __init int sched_init_debug(void)
+ #endif
+
+ debugfs_create_file("debug", 0444, debugfs_sched, NULL, &sched_debug_fops);
++#endif /* !CONFIG_SCHED_ALT */
+
+ return 0;
+ }
+ late_initcall(sched_init_debug);
+
++#ifndef CONFIG_SCHED_ALT
+ #ifdef CONFIG_SMP
+
+ static cpumask_var_t sd_sysctl_cpus;
+@@ -1110,6 +1119,7 @@ void proc_sched_set_task(struct task_struct *p)
+ memset(&p->stats, 0, sizeof(p->stats));
+ #endif
+ }
++#endif /* !CONFIG_SCHED_ALT */
+
+ void resched_latency_warn(int cpu, u64 latency)
+ {
+diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
+index 31231925f1ec..c087311032f2 100644
+--- a/kernel/sched/idle.c
++++ b/kernel/sched/idle.c
+@@ -410,6 +410,7 @@ void cpu_startup_entry(enum cpuhp_state state)
+ do_idle();
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ /*
+ * idle-task scheduling class.
+ */
+@@ -531,3 +532,4 @@ DEFINE_SCHED_CLASS(idle) = {
+ .switched_to = switched_to_idle,
+ .update_curr = update_curr_idle,
+ };
++#endif
+diff --git a/kernel/sched/pds.h b/kernel/sched/pds.h
+new file mode 100644
+index 000000000000..f9de95e0ec0e
+--- /dev/null
++++ b/kernel/sched/pds.h
+@@ -0,0 +1,134 @@
++#define ALT_SCHED_NAME "PDS"
++
++static const u64 RT_MASK = ((1ULL << MIN_SCHED_NORMAL_PRIO) - 1);
++
++#define SCHED_NORMAL_PRIO_NUM (32)
++#define SCHED_EDGE_DELTA (SCHED_NORMAL_PRIO_NUM - NICE_WIDTH / 2)
++
++/* PDS assume SCHED_NORMAL_PRIO_NUM is power of 2 */
++#define SCHED_NORMAL_PRIO_MOD(x) ((x) & (SCHED_NORMAL_PRIO_NUM - 1))
++
++/* default time slice 4ms -> shift 22, 2 time slice slots -> shift 23 */
++static __read_mostly int sched_timeslice_shift = 23;
++
++/*
++ * Common interfaces
++ */
++static inline int
++task_sched_prio_normal(const struct task_struct *p, const struct rq *rq)
++{
++ u64 sched_dl = max(p->deadline, rq->time_edge);
++
++#ifdef ALT_SCHED_DEBUG
++ if (WARN_ONCE(sched_dl - rq->time_edge > NORMAL_PRIO_NUM - 1,
++ "pds: task_sched_prio_normal() delta %lld\n", sched_dl - rq->time_edge))
++ return SCHED_NORMAL_PRIO_NUM - 1;
++#endif
++
++ return sched_dl - rq->time_edge;
++}
++
++static inline int task_sched_prio(const struct task_struct *p)
++{
++ return (p->prio < MIN_NORMAL_PRIO) ? (p->prio >> 2) :
++ MIN_SCHED_NORMAL_PRIO + task_sched_prio_normal(p, task_rq(p));
++}
++
++#define TASK_SCHED_PRIO_IDX(p, rq, idx, prio) \
++ if (p->prio < MIN_NORMAL_PRIO) { \
++ prio = p->prio >> 2; \
++ idx = prio; \
++ } else { \
++ u64 sched_dl = max(p->deadline, rq->time_edge); \
++ prio = MIN_SCHED_NORMAL_PRIO + sched_dl - rq->time_edge; \
++ idx = MIN_SCHED_NORMAL_PRIO + SCHED_NORMAL_PRIO_MOD(sched_dl); \
++ }
++
++static inline int sched_prio2idx(int sched_prio, struct rq *rq)
++{
++ return (IDLE_TASK_SCHED_PRIO == sched_prio || sched_prio < MIN_SCHED_NORMAL_PRIO) ?
++ sched_prio :
++ MIN_SCHED_NORMAL_PRIO + SCHED_NORMAL_PRIO_MOD(sched_prio + rq->time_edge);
++}
++
++static inline int sched_idx2prio(int sched_idx, struct rq *rq)
++{
++ return (sched_idx < MIN_SCHED_NORMAL_PRIO) ?
++ sched_idx :
++ MIN_SCHED_NORMAL_PRIO + SCHED_NORMAL_PRIO_MOD(sched_idx - rq->time_edge);
++}
++
++static inline int sched_rq_prio_idx(struct rq *rq)
++{
++ return rq->prio_idx;
++}
++
++int task_running_nice(struct task_struct *p)
++{
++ return (p->prio > DEFAULT_PRIO);
++}
++
++static inline void sched_update_rq_clock(struct rq *rq)
++{
++ struct list_head head;
++ u64 old = rq->time_edge;
++ u64 now = rq->clock >> sched_timeslice_shift;
++ u64 prio, delta;
++ DECLARE_BITMAP(normal, SCHED_QUEUE_BITS);
++
++ if (now == old)
++ return;
++
++ rq->time_edge = now;
++ delta = min_t(u64, SCHED_NORMAL_PRIO_NUM, now - old);
++ INIT_LIST_HEAD(&head);
++
++ prio = MIN_SCHED_NORMAL_PRIO;
++ for_each_set_bit_from(prio, rq->queue.bitmap, MIN_SCHED_NORMAL_PRIO + delta)
++ list_splice_tail_init(rq->queue.heads + MIN_SCHED_NORMAL_PRIO +
++ SCHED_NORMAL_PRIO_MOD(prio + old), &head);
++
++ bitmap_shift_right(normal, rq->queue.bitmap, delta, SCHED_QUEUE_BITS);
++ if (!list_empty(&head)) {
++ u64 idx = MIN_SCHED_NORMAL_PRIO + SCHED_NORMAL_PRIO_MOD(now);
++
++ __list_splice(&head, rq->queue.heads + idx, rq->queue.heads[idx].next);
++ set_bit(MIN_SCHED_NORMAL_PRIO, normal);
++ }
++ bitmap_replace(rq->queue.bitmap, normal, rq->queue.bitmap,
++ (const unsigned long *)&RT_MASK, SCHED_QUEUE_BITS);
++
++ if (rq->prio < MIN_SCHED_NORMAL_PRIO || IDLE_TASK_SCHED_PRIO == rq->prio)
++ return;
++
++ rq->prio = max_t(u64, MIN_SCHED_NORMAL_PRIO, rq->prio - delta);
++ rq->prio_idx = sched_prio2idx(rq->prio, rq);
++}
++
++static inline void sched_task_renew(struct task_struct *p, const struct rq *rq)
++{
++ if (p->prio >= MIN_NORMAL_PRIO)
++ p->deadline = rq->time_edge + SCHED_EDGE_DELTA +
++ (p->static_prio - (MAX_PRIO - NICE_WIDTH)) / 2;
++}
++
++static inline void sched_task_sanity_check(struct task_struct *p, struct rq *rq)
++{
++ u64 max_dl = rq->time_edge + SCHED_EDGE_DELTA + NICE_WIDTH / 2 - 1;
++ if (unlikely(p->deadline > max_dl))
++ p->deadline = max_dl;
++}
++
++static void sched_task_fork(struct task_struct *p, struct rq *rq)
++{
++ sched_task_renew(p, rq);
++}
++
++static inline void do_sched_yield_type_1(struct task_struct *p, struct rq *rq)
++{
++ p->time_slice = sysctl_sched_base_slice;
++ sched_task_renew(p, rq);
++}
++
++static inline void sched_task_ttwu(struct task_struct *p) {}
++static inline void sched_task_deactivate(struct task_struct *p, struct rq *rq) {}
+diff --git a/kernel/sched/pelt.c b/kernel/sched/pelt.c
+index 63b6cf898220..9ca10ece4d3a 100644
+--- a/kernel/sched/pelt.c
++++ b/kernel/sched/pelt.c
+@@ -266,6 +266,7 @@ ___update_load_avg(struct sched_avg *sa, unsigned long load)
+ WRITE_ONCE(sa->util_avg, sa->util_sum / divider);
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ /*
+ * sched_entity:
+ *
+@@ -383,8 +384,9 @@ int update_dl_rq_load_avg(u64 now, struct rq *rq, int running)
+
+ return 0;
+ }
++#endif
+
+-#ifdef CONFIG_SCHED_THERMAL_PRESSURE
++#if defined(CONFIG_SCHED_THERMAL_PRESSURE) && !defined(CONFIG_SCHED_ALT)
+ /*
+ * thermal:
+ *
+diff --git a/kernel/sched/pelt.h b/kernel/sched/pelt.h
+index 9e1083465fbc..d35f050e8296 100644
+--- a/kernel/sched/pelt.h
++++ b/kernel/sched/pelt.h
+@@ -1,13 +1,15 @@
+ #ifdef CONFIG_SMP
+ #include "sched-pelt.h"
+
++#ifndef CONFIG_SCHED_ALT
+ int __update_load_avg_blocked_se(u64 now, struct sched_entity *se);
+ int __update_load_avg_se(u64 now, struct cfs_rq *cfs_rq, struct sched_entity *se);
+ int __update_load_avg_cfs_rq(u64 now, struct cfs_rq *cfs_rq);
+ int update_rt_rq_load_avg(u64 now, struct rq *rq, int running);
+ int update_dl_rq_load_avg(u64 now, struct rq *rq, int running);
++#endif
+
+-#ifdef CONFIG_SCHED_THERMAL_PRESSURE
++#if defined(CONFIG_SCHED_THERMAL_PRESSURE) && !defined(CONFIG_SCHED_ALT)
+ int update_thermal_load_avg(u64 now, struct rq *rq, u64 capacity);
+
+ static inline u64 thermal_load_avg(struct rq *rq)
+@@ -44,6 +46,7 @@ static inline u32 get_pelt_divider(struct sched_avg *avg)
+ return PELT_MIN_DIVIDER + avg->period_contrib;
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ static inline void cfs_se_util_change(struct sched_avg *avg)
+ {
+ unsigned int enqueued;
+@@ -180,9 +183,11 @@ static inline u64 cfs_rq_clock_pelt(struct cfs_rq *cfs_rq)
+ return rq_clock_pelt(rq_of(cfs_rq));
+ }
+ #endif
++#endif /* CONFIG_SCHED_ALT */
+
+ #else
+
++#ifndef CONFIG_SCHED_ALT
+ static inline int
+ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
+ {
+@@ -200,6 +205,7 @@ update_dl_rq_load_avg(u64 now, struct rq *rq, int running)
+ {
+ return 0;
+ }
++#endif
+
+ static inline int
+ update_thermal_load_avg(u64 now, struct rq *rq, u64 capacity)
+diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
+index 001fe047bd5d..a2fafb8f3306 100644
+--- a/kernel/sched/sched.h
++++ b/kernel/sched/sched.h
+@@ -5,6 +5,10 @@
+ #ifndef _KERNEL_SCHED_SCHED_H
+ #define _KERNEL_SCHED_SCHED_H
+
++#ifdef CONFIG_SCHED_ALT
++#include "alt_sched.h"
++#else
++
+ #include <linux/sched/affinity.h>
+ #include <linux/sched/autogroup.h>
+ #include <linux/sched/cpufreq.h>
+@@ -3473,4 +3477,9 @@ static inline void init_sched_mm_cid(struct task_struct *t) { }
+ extern u64 avg_vruntime(struct cfs_rq *cfs_rq);
+ extern int entity_eligible(struct cfs_rq *cfs_rq, struct sched_entity *se);
+
++static inline int task_running_nice(struct task_struct *p)
++{
++ return (task_nice(p) > 0);
++}
++#endif /* !CONFIG_SCHED_ALT */
+ #endif /* _KERNEL_SCHED_SCHED_H */
+diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c
+index 857f837f52cb..5486c63e4790 100644
+--- a/kernel/sched/stats.c
++++ b/kernel/sched/stats.c
+@@ -125,8 +125,10 @@ static int show_schedstat(struct seq_file *seq, void *v)
+ } else {
+ struct rq *rq;
+ #ifdef CONFIG_SMP
++#ifndef CONFIG_SCHED_ALT
+ struct sched_domain *sd;
+ int dcount = 0;
++#endif
+ #endif
+ cpu = (unsigned long)(v - 2);
+ rq = cpu_rq(cpu);
+@@ -143,6 +145,7 @@ static int show_schedstat(struct seq_file *seq, void *v)
+ seq_printf(seq, "\n");
+
+ #ifdef CONFIG_SMP
++#ifndef CONFIG_SCHED_ALT
+ /* domain-specific stats */
+ rcu_read_lock();
+ for_each_domain(cpu, sd) {
+@@ -171,6 +174,7 @@ static int show_schedstat(struct seq_file *seq, void *v)
+ sd->ttwu_move_balance);
+ }
+ rcu_read_unlock();
++#endif
+ #endif
+ }
+ return 0;
+diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h
+index 38f3698f5e5b..b9d597394316 100644
+--- a/kernel/sched/stats.h
++++ b/kernel/sched/stats.h
+@@ -89,6 +89,7 @@ static inline void rq_sched_info_depart (struct rq *rq, unsigned long long delt
+
+ #endif /* CONFIG_SCHEDSTATS */
+
++#ifndef CONFIG_SCHED_ALT
+ #ifdef CONFIG_FAIR_GROUP_SCHED
+ struct sched_entity_stats {
+ struct sched_entity se;
+@@ -105,6 +106,7 @@ __schedstats_from_se(struct sched_entity *se)
+ #endif
+ return &task_of(se)->stats;
+ }
++#endif /* CONFIG_SCHED_ALT */
+
+ #ifdef CONFIG_PSI
+ void psi_task_change(struct task_struct *task, int clear, int set);
+diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
+index 10d1391e7416..dc717683342e 100644
+--- a/kernel/sched/topology.c
++++ b/kernel/sched/topology.c
+@@ -3,6 +3,7 @@
+ * Scheduler topology setup/handling methods
+ */
+
++#ifndef CONFIG_SCHED_ALT
+ #include <linux/bsearch.h>
+
+ DEFINE_MUTEX(sched_domains_mutex);
+@@ -1445,8 +1446,10 @@ static void asym_cpu_capacity_scan(void)
+ */
+
+ static int default_relax_domain_level = -1;
++#endif /* CONFIG_SCHED_ALT */
+ int sched_domain_level_max;
+
++#ifndef CONFIG_SCHED_ALT
+ static int __init setup_relax_domain_level(char *str)
+ {
+ if (kstrtoint(str, 0, &default_relax_domain_level))
+@@ -1680,6 +1683,7 @@ sd_init(struct sched_domain_topology_level *tl,
+
+ return sd;
+ }
++#endif /* CONFIG_SCHED_ALT */
+
+ /*
+ * Topology list, bottom-up.
+@@ -1716,6 +1720,7 @@ void __init set_sched_topology(struct sched_domain_topology_level *tl)
+ sched_domain_topology_saved = NULL;
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ #ifdef CONFIG_NUMA
+
+ static const struct cpumask *sd_numa_mask(int cpu)
+@@ -2793,3 +2798,26 @@ void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
+ partition_sched_domains_locked(ndoms_new, doms_new, dattr_new);
+ mutex_unlock(&sched_domains_mutex);
+ }
++#else /* CONFIG_SCHED_ALT */
++void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
++ struct sched_domain_attr *dattr_new)
++{}
++
++#ifdef CONFIG_NUMA
++int sched_numa_find_closest(const struct cpumask *cpus, int cpu)
++{
++ return best_mask_cpu(cpu, cpus);
++}
++
++int sched_numa_find_nth_cpu(const struct cpumask *cpus, int cpu, int node)
++{
++ return cpumask_nth(cpu, cpus);
++}
++
++const struct cpumask *sched_numa_hop_mask(unsigned int node, unsigned int hops)
++{
++ return ERR_PTR(-EOPNOTSUPP);
++}
++EXPORT_SYMBOL_GPL(sched_numa_hop_mask);
++#endif /* CONFIG_NUMA */
++#endif
+diff --git a/kernel/sysctl.c b/kernel/sysctl.c
+index 157f7ce2942d..63083a9a2935 100644
+--- a/kernel/sysctl.c
++++ b/kernel/sysctl.c
+@@ -92,6 +92,10 @@ EXPORT_SYMBOL_GPL(sysctl_long_vals);
+
+ /* Constants used for minimum and maximum */
+
++#ifdef CONFIG_SCHED_ALT
++extern int sched_yield_type;
++#endif
++
+ #ifdef CONFIG_PERF_EVENTS
+ static const int six_hundred_forty_kb = 640 * 1024;
+ #endif
+@@ -1912,6 +1916,17 @@ static struct ctl_table kern_table[] = {
+ .proc_handler = proc_dointvec,
+ },
+ #endif
++#ifdef CONFIG_SCHED_ALT
++ {
++ .procname = "yield_type",
++ .data = &sched_yield_type,
++ .maxlen = sizeof (int),
++ .mode = 0644,
++ .proc_handler = &proc_dointvec_minmax,
++ .extra1 = SYSCTL_ZERO,
++ .extra2 = SYSCTL_TWO,
++ },
++#endif
+ #if defined(CONFIG_S390) && defined(CONFIG_SMP)
+ {
+ .procname = "spin_retry",
+diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
+index edb0f821dcea..bfc4a6afc77e 100644
+--- a/kernel/time/hrtimer.c
++++ b/kernel/time/hrtimer.c
+@@ -2092,8 +2092,10 @@ long hrtimer_nanosleep(ktime_t rqtp, const enum hrtimer_mode mode,
+ int ret = 0;
+ u64 slack;
+
++#ifndef CONFIG_SCHED_ALT
+ slack = current->timer_slack_ns;
+- if (rt_task(current))
++ if (dl_task(current) || rt_task(current))
++#endif
+ slack = 0;
+
+ hrtimer_init_sleeper_on_stack(&t, clockid, mode);
+diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
+index e9c6f9d0e42c..43ee0a94abdd 100644
+--- a/kernel/time/posix-cpu-timers.c
++++ b/kernel/time/posix-cpu-timers.c
+@@ -223,7 +223,7 @@ static void task_sample_cputime(struct task_struct *p, u64 *samples)
+ u64 stime, utime;
+
+ task_cputime(p, &utime, &stime);
+- store_samples(samples, stime, utime, p->se.sum_exec_runtime);
++ store_samples(samples, stime, utime, tsk_seruntime(p));
+ }
+
+ static void proc_sample_cputime_atomic(struct task_cputime_atomic *at,
+@@ -867,6 +867,7 @@ static void collect_posix_cputimers(struct posix_cputimers *pct, u64 *samples,
+ }
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ static inline void check_dl_overrun(struct task_struct *tsk)
+ {
+ if (tsk->dl.dl_overrun) {
+@@ -874,6 +875,7 @@ static inline void check_dl_overrun(struct task_struct *tsk)
+ send_signal_locked(SIGXCPU, SEND_SIG_PRIV, tsk, PIDTYPE_TGID);
+ }
+ }
++#endif
+
+ static bool check_rlimit(u64 time, u64 limit, int signo, bool rt, bool hard)
+ {
+@@ -901,8 +903,10 @@ static void check_thread_timers(struct task_struct *tsk,
+ u64 samples[CPUCLOCK_MAX];
+ unsigned long soft;
+
++#ifndef CONFIG_SCHED_ALT
+ if (dl_task(tsk))
+ check_dl_overrun(tsk);
++#endif
+
+ if (expiry_cache_is_inactive(pct))
+ return;
+@@ -916,7 +920,7 @@ static void check_thread_timers(struct task_struct *tsk,
+ soft = task_rlimit(tsk, RLIMIT_RTTIME);
+ if (soft != RLIM_INFINITY) {
+ /* Task RT timeout is accounted in jiffies. RTTIME is usec */
+- unsigned long rttime = tsk->rt.timeout * (USEC_PER_SEC / HZ);
++ unsigned long rttime = tsk_rttimeout(tsk) * (USEC_PER_SEC / HZ);
+ unsigned long hard = task_rlimit_max(tsk, RLIMIT_RTTIME);
+
+ /* At the hard limit, send SIGKILL. No further action. */
+@@ -1152,8 +1156,10 @@ static inline bool fastpath_timer_check(struct task_struct *tsk)
+ return true;
+ }
+
++#ifndef CONFIG_SCHED_ALT
+ if (dl_task(tsk) && tsk->dl.dl_overrun)
+ return true;
++#endif
+
+ return false;
+ }
+diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
+index 529590499b1f..d04bb99b4f0e 100644
+--- a/kernel/trace/trace_selftest.c
++++ b/kernel/trace/trace_selftest.c
+@@ -1155,10 +1155,15 @@ static int trace_wakeup_test_thread(void *data)
+ {
+ /* Make this a -deadline thread */
+ static const struct sched_attr attr = {
++#ifdef CONFIG_SCHED_ALT
++ /* No deadline on BMQ/PDS, use RR */
++ .sched_policy = SCHED_RR,
++#else
+ .sched_policy = SCHED_DEADLINE,
+ .sched_runtime = 100000ULL,
+ .sched_deadline = 10000000ULL,
+ .sched_period = 10000000ULL
++#endif
+ };
+ struct wakeup_test_data *x = data;
+
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index 7b482a26d741..e5b053326631 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -1120,6 +1120,7 @@ static bool kick_pool(struct worker_pool *pool)
+
+ p = worker->task;
+
++#ifndef CONFIG_SCHED_ALT
+ #ifdef CONFIG_SMP
+ /*
+ * Idle @worker is about to execute @work and waking up provides an
+@@ -1145,6 +1146,8 @@ static bool kick_pool(struct worker_pool *pool)
+ get_work_pwq(work)->stats[PWQ_STAT_REPATRIATED]++;
+ }
+ #endif
++#endif /* !CONFIG_SCHED_ALT */
++
+ wake_up_process(p);
+ return true;
+ }
+@@ -1269,7 +1272,11 @@ void wq_worker_running(struct task_struct *task)
+ * CPU intensive auto-detection cares about how long a work item hogged
+ * CPU without sleeping. Reset the starting timestamp on wakeup.
+ */
++#ifdef CONFIG_SCHED_ALT
++ worker->current_at = worker->task->sched_time;
++#else
+ worker->current_at = worker->task->se.sum_exec_runtime;
++#endif
+
+ WRITE_ONCE(worker->sleeping, 0);
+ }
+@@ -1354,7 +1361,11 @@ void wq_worker_tick(struct task_struct *task)
+ * We probably want to make this prettier in the future.
+ */
+ if ((worker->flags & WORKER_NOT_RUNNING) || READ_ONCE(worker->sleeping) ||
++#ifdef CONFIG_SCHED_ALT
++ worker->task->sched_time - worker->current_at <
++#else
+ worker->task->se.sum_exec_runtime - worker->current_at <
++#endif
+ wq_cpu_intensive_thresh_us * NSEC_PER_USEC)
+ return;
+
+@@ -2565,7 +2576,11 @@ __acquires(&pool->lock)
+ worker->current_work = work;
+ worker->current_func = work->func;
+ worker->current_pwq = pwq;
++#ifdef CONFIG_SCHED_ALT
++ worker->current_at = worker->task->sched_time;
++#else
+ worker->current_at = worker->task->se.sum_exec_runtime;
++#endif
+ work_data = *work_data_bits(work);
+ worker->current_color = get_work_color(work_data);
+
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-03-27 11:46 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-03-27 11:46 UTC (permalink / raw
To: gentoo-commits
commit: 43b13a167b08033a073085dcfb91b78cc13d8ad8
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Wed Mar 27 11:46:20 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Wed Mar 27 11:46:20 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=43b13a16
Remove old BMQ
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
5020_BMQ-and-PDS-io-scheduler-v6.8-r0.patch | 11504 --------------------------
1 file changed, 11504 deletions(-)
diff --git a/5020_BMQ-and-PDS-io-scheduler-v6.8-r0.patch b/5020_BMQ-and-PDS-io-scheduler-v6.8-r0.patch
deleted file mode 100644
index d914861f..00000000
--- a/5020_BMQ-and-PDS-io-scheduler-v6.8-r0.patch
+++ /dev/null
@@ -1,11504 +0,0 @@
-diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
-index 6584a1f9bfe3..226c79dd34cc 100644
---- a/Documentation/admin-guide/sysctl/kernel.rst
-+++ b/Documentation/admin-guide/sysctl/kernel.rst
-@@ -1646,3 +1646,13 @@ is 10 seconds.
-
- The softlockup threshold is (``2 * watchdog_thresh``). Setting this
- tunable to zero will disable lockup detection altogether.
-+
-+yield_type:
-+===========
-+
-+BMQ/PDS CPU scheduler only. This determines what type of yield calls
-+to sched_yield() will be performed.
-+
-+ 0 - No yield.
-+ 1 - Requeue task. (default)
-+ 2 - Set run queue skip task. Same as CFS.
-diff --git a/Documentation/scheduler/sched-BMQ.txt b/Documentation/scheduler/sched-BMQ.txt
-new file mode 100644
-index 000000000000..05c84eec0f31
---- /dev/null
-+++ b/Documentation/scheduler/sched-BMQ.txt
-@@ -0,0 +1,110 @@
-+ BitMap queue CPU Scheduler
-+ --------------------------
-+
-+CONTENT
-+========
-+
-+ Background
-+ Design
-+ Overview
-+ Task policy
-+ Priority management
-+ BitMap Queue
-+ CPU Assignment and Migration
-+
-+
-+Background
-+==========
-+
-+BitMap Queue CPU scheduler, referred to as BMQ from here on, is an evolution
-+of previous Priority and Deadline based Skiplist multiple queue scheduler(PDS),
-+and inspired by Zircon scheduler. The goal of it is to keep the scheduler code
-+simple, while efficiency and scalable for interactive tasks, such as desktop,
-+movie playback and gaming etc.
-+
-+Design
-+======
-+
-+Overview
-+--------
-+
-+BMQ use per CPU run queue design, each CPU(logical) has it's own run queue,
-+each CPU is responsible for scheduling the tasks that are putting into it's
-+run queue.
-+
-+The run queue is a set of priority queues. Note that these queues are fifo
-+queue for non-rt tasks or priority queue for rt tasks in data structure. See
-+BitMap Queue below for details. BMQ is optimized for non-rt tasks in the fact
-+that most applications are non-rt tasks. No matter the queue is fifo or
-+priority, In each queue is an ordered list of runnable tasks awaiting execution
-+and the data structures are the same. When it is time for a new task to run,
-+the scheduler simply looks the lowest numbered queueue that contains a task,
-+and runs the first task from the head of that queue. And per CPU idle task is
-+also in the run queue, so the scheduler can always find a task to run on from
-+its run queue.
-+
-+Each task will assigned the same timeslice(default 4ms) when it is picked to
-+start running. Task will be reinserted at the end of the appropriate priority
-+queue when it uses its whole timeslice. When the scheduler selects a new task
-+from the priority queue it sets the CPU's preemption timer for the remainder of
-+the previous timeslice. When that timer fires the scheduler will stop execution
-+on that task, select another task and start over again.
-+
-+If a task blocks waiting for a shared resource then it's taken out of its
-+priority queue and is placed in a wait queue for the shared resource. When it
-+is unblocked it will be reinserted in the appropriate priority queue of an
-+eligible CPU.
-+
-+Task policy
-+-----------
-+
-+BMQ supports DEADLINE, FIFO, RR, NORMAL, BATCH and IDLE task policy like the
-+mainline CFS scheduler. But BMQ is heavy optimized for non-rt task, that's
-+NORMAL/BATCH/IDLE policy tasks. Below is the implementation detail of each
-+policy.
-+
-+DEADLINE
-+ It is squashed as priority 0 FIFO task.
-+
-+FIFO/RR
-+ All RT tasks share one single priority queue in BMQ run queue designed. The
-+complexity of insert operation is O(n). BMQ is not designed for system runs
-+with major rt policy tasks.
-+
-+NORMAL/BATCH/IDLE
-+ BATCH and IDLE tasks are treated as the same policy. They compete CPU with
-+NORMAL policy tasks, but they just don't boost. To control the priority of
-+NORMAL/BATCH/IDLE tasks, simply use nice level.
-+
-+ISO
-+ ISO policy is not supported in BMQ. Please use nice level -20 NORMAL policy
-+task instead.
-+
-+Priority management
-+-------------------
-+
-+RT tasks have priority from 0-99. For non-rt tasks, there are three different
-+factors used to determine the effective priority of a task. The effective
-+priority being what is used to determine which queue it will be in.
-+
-+The first factor is simply the task’s static priority. Which is assigned from
-+task's nice level, within [-20, 19] in userland's point of view and [0, 39]
-+internally.
-+
-+The second factor is the priority boost. This is a value bounded between
-+[-MAX_PRIORITY_ADJ, MAX_PRIORITY_ADJ] used to offset the base priority, it is
-+modified by the following cases:
-+
-+*When a thread has used up its entire timeslice, always deboost its boost by
-+increasing by one.
-+*When a thread gives up cpu control(voluntary or non-voluntary) to reschedule,
-+and its switch-in time(time after last switch and run) below the thredhold
-+based on its priority boost, will boost its boost by decreasing by one buti is
-+capped at 0 (won’t go negative).
-+
-+The intent in this system is to ensure that interactive threads are serviced
-+quickly. These are usually the threads that interact directly with the user
-+and cause user-perceivable latency. These threads usually do little work and
-+spend most of their time blocked awaiting another user event. So they get the
-+priority boost from unblocking while background threads that do most of the
-+processing receive the priority penalty for using their entire timeslice.
-diff --git a/fs/proc/base.c b/fs/proc/base.c
-index 18550c071d71..fa8cf95568b6 100644
---- a/fs/proc/base.c
-+++ b/fs/proc/base.c
-@@ -481,7 +481,7 @@ static int proc_pid_schedstat(struct seq_file *m, struct pid_namespace *ns,
- seq_puts(m, "0 0 0\n");
- else
- seq_printf(m, "%llu %llu %lu\n",
-- (unsigned long long)task->se.sum_exec_runtime,
-+ (unsigned long long)tsk_seruntime(task),
- (unsigned long long)task->sched_info.run_delay,
- task->sched_info.pcount);
-
-diff --git a/include/asm-generic/resource.h b/include/asm-generic/resource.h
-index 8874f681b056..59eb72bf7d5f 100644
---- a/include/asm-generic/resource.h
-+++ b/include/asm-generic/resource.h
-@@ -23,7 +23,7 @@
- [RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY }, \
- [RLIMIT_SIGPENDING] = { 0, 0 }, \
- [RLIMIT_MSGQUEUE] = { MQ_BYTES_MAX, MQ_BYTES_MAX }, \
-- [RLIMIT_NICE] = { 0, 0 }, \
-+ [RLIMIT_NICE] = { 30, 30 }, \
- [RLIMIT_RTPRIO] = { 0, 0 }, \
- [RLIMIT_RTTIME] = { RLIM_INFINITY, RLIM_INFINITY }, \
- }
-diff --git a/include/linux/sched.h b/include/linux/sched.h
-index ffe8f618ab86..3c17bfa142b7 100644
---- a/include/linux/sched.h
-+++ b/include/linux/sched.h
-@@ -771,8 +771,14 @@ struct task_struct {
- unsigned int ptrace;
-
- #ifdef CONFIG_SMP
-- int on_cpu;
- struct __call_single_node wake_entry;
-+#endif
-+#if defined(CONFIG_SMP) || defined(CONFIG_SCHED_ALT)
-+ int on_cpu;
-+#endif
-+
-+#ifdef CONFIG_SMP
-+#ifndef CONFIG_SCHED_ALT
- unsigned int wakee_flips;
- unsigned long wakee_flip_decay_ts;
- struct task_struct *last_wakee;
-@@ -786,6 +792,7 @@ struct task_struct {
- */
- int recent_used_cpu;
- int wake_cpu;
-+#endif /* !CONFIG_SCHED_ALT */
- #endif
- int on_rq;
-
-@@ -794,6 +801,20 @@ struct task_struct {
- int normal_prio;
- unsigned int rt_priority;
-
-+#ifdef CONFIG_SCHED_ALT
-+ u64 last_ran;
-+ s64 time_slice;
-+ int sq_idx;
-+ struct list_head sq_node;
-+#ifdef CONFIG_SCHED_BMQ
-+ int boost_prio;
-+#endif /* CONFIG_SCHED_BMQ */
-+#ifdef CONFIG_SCHED_PDS
-+ u64 deadline;
-+#endif /* CONFIG_SCHED_PDS */
-+ /* sched_clock time spent running */
-+ u64 sched_time;
-+#else /* !CONFIG_SCHED_ALT */
- struct sched_entity se;
- struct sched_rt_entity rt;
- struct sched_dl_entity dl;
-@@ -805,6 +826,7 @@ struct task_struct {
- unsigned long core_cookie;
- unsigned int core_occupation;
- #endif
-+#endif /* !CONFIG_SCHED_ALT */
-
- #ifdef CONFIG_CGROUP_SCHED
- struct task_group *sched_task_group;
-@@ -1564,6 +1586,15 @@ struct task_struct {
- */
- };
-
-+#ifdef CONFIG_SCHED_ALT
-+#define tsk_seruntime(t) ((t)->sched_time)
-+/* replace the uncertian rt_timeout with 0UL */
-+#define tsk_rttimeout(t) (0UL)
-+#else /* CFS */
-+#define tsk_seruntime(t) ((t)->se.sum_exec_runtime)
-+#define tsk_rttimeout(t) ((t)->rt.timeout)
-+#endif /* !CONFIG_SCHED_ALT */
-+
- #define TASK_REPORT_IDLE (TASK_REPORT + 1)
- #define TASK_REPORT_MAX (TASK_REPORT_IDLE << 1)
-
-diff --git a/include/linux/sched/deadline.h b/include/linux/sched/deadline.h
-index df3aca89d4f5..1df1f7635188 100644
---- a/include/linux/sched/deadline.h
-+++ b/include/linux/sched/deadline.h
-@@ -2,6 +2,25 @@
- #ifndef _LINUX_SCHED_DEADLINE_H
- #define _LINUX_SCHED_DEADLINE_H
-
-+#ifdef CONFIG_SCHED_ALT
-+
-+static inline int dl_task(struct task_struct *p)
-+{
-+ return 0;
-+}
-+
-+#ifdef CONFIG_SCHED_BMQ
-+#define __tsk_deadline(p) (0UL)
-+#endif
-+
-+#ifdef CONFIG_SCHED_PDS
-+#define __tsk_deadline(p) ((((u64) ((p)->prio))<<56) | (p)->deadline)
-+#endif
-+
-+#else
-+
-+#define __tsk_deadline(p) ((p)->dl.deadline)
-+
- /*
- * SCHED_DEADLINE tasks has negative priorities, reflecting
- * the fact that any of them has higher prio than RT and
-@@ -23,6 +42,7 @@ static inline int dl_task(struct task_struct *p)
- {
- return dl_prio(p->prio);
- }
-+#endif /* CONFIG_SCHED_ALT */
-
- static inline bool dl_time_before(u64 a, u64 b)
- {
-diff --git a/include/linux/sched/prio.h b/include/linux/sched/prio.h
-index ab83d85e1183..a9a1dfa99140 100644
---- a/include/linux/sched/prio.h
-+++ b/include/linux/sched/prio.h
-@@ -18,6 +18,32 @@
- #define MAX_PRIO (MAX_RT_PRIO + NICE_WIDTH)
- #define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2)
-
-+#ifdef CONFIG_SCHED_ALT
-+
-+/* Undefine MAX_PRIO and DEFAULT_PRIO */
-+#undef MAX_PRIO
-+#undef DEFAULT_PRIO
-+
-+/* +/- priority levels from the base priority */
-+#ifdef CONFIG_SCHED_BMQ
-+#define MAX_PRIORITY_ADJ (12)
-+
-+#define MIN_NORMAL_PRIO (MAX_RT_PRIO)
-+#define MAX_PRIO (MIN_NORMAL_PRIO + NICE_WIDTH)
-+#define DEFAULT_PRIO (MIN_NORMAL_PRIO + NICE_WIDTH / 2)
-+#endif
-+
-+#ifdef CONFIG_SCHED_PDS
-+#define MAX_PRIORITY_ADJ (0)
-+
-+#define MIN_NORMAL_PRIO (128)
-+#define NORMAL_PRIO_NUM (64)
-+#define MAX_PRIO (MIN_NORMAL_PRIO + NORMAL_PRIO_NUM)
-+#define DEFAULT_PRIO (MAX_PRIO - NICE_WIDTH / 2)
-+#endif
-+
-+#endif /* CONFIG_SCHED_ALT */
-+
- /*
- * Convert user-nice values [ -20 ... 0 ... 19 ]
- * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
-diff --git a/include/linux/sched/rt.h b/include/linux/sched/rt.h
-index b2b9e6eb9683..09bd4d8758b2 100644
---- a/include/linux/sched/rt.h
-+++ b/include/linux/sched/rt.h
-@@ -24,8 +24,10 @@ static inline bool task_is_realtime(struct task_struct *tsk)
-
- if (policy == SCHED_FIFO || policy == SCHED_RR)
- return true;
-+#ifndef CONFIG_SCHED_ALT
- if (policy == SCHED_DEADLINE)
- return true;
-+#endif
- return false;
- }
-
-diff --git a/include/linux/sched/topology.h b/include/linux/sched/topology.h
-index a6e04b4a21d7..66f5170037c3 100644
---- a/include/linux/sched/topology.h
-+++ b/include/linux/sched/topology.h
-@@ -238,7 +238,8 @@ static inline bool cpus_share_resources(int this_cpu, int that_cpu)
-
- #endif /* !CONFIG_SMP */
-
--#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)
-+#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) && \
-+ !defined(CONFIG_SCHED_ALT)
- extern void rebuild_sched_domains_energy(void);
- #else
- static inline void rebuild_sched_domains_energy(void)
-diff --git a/init/Kconfig b/init/Kconfig
-index bee58f7468c3..81f568107a6b 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -638,6 +638,7 @@ config TASK_IO_ACCOUNTING
-
- config PSI
- bool "Pressure stall information tracking"
-+ depends on !SCHED_ALT
- select KERNFS
- help
- Collect metrics that indicate how overcommitted the CPU, memory,
-@@ -803,6 +804,7 @@ menu "Scheduler features"
- config UCLAMP_TASK
- bool "Enable utilization clamping for RT/FAIR tasks"
- depends on CPU_FREQ_GOV_SCHEDUTIL
-+ depends on !SCHED_ALT
- help
- This feature enables the scheduler to track the clamped utilization
- of each CPU based on RUNNABLE tasks scheduled on that CPU.
-@@ -849,6 +851,35 @@ config UCLAMP_BUCKETS_COUNT
-
- If in doubt, use the default value.
-
-+menuconfig SCHED_ALT
-+ bool "Alternative CPU Schedulers"
-+ default y
-+ help
-+ This feature enable alternative CPU scheduler"
-+
-+if SCHED_ALT
-+
-+choice
-+ prompt "Alternative CPU Scheduler"
-+ default SCHED_BMQ
-+
-+config SCHED_BMQ
-+ bool "BMQ CPU scheduler"
-+ help
-+ The BitMap Queue CPU scheduler for excellent interactivity and
-+ responsiveness on the desktop and solid scalability on normal
-+ hardware and commodity servers.
-+
-+config SCHED_PDS
-+ bool "PDS CPU scheduler"
-+ help
-+ The Priority and Deadline based Skip list multiple queue CPU
-+ Scheduler.
-+
-+endchoice
-+
-+endif
-+
- endmenu
-
- #
-@@ -914,6 +945,7 @@ config NUMA_BALANCING
- depends on ARCH_SUPPORTS_NUMA_BALANCING
- depends on !ARCH_WANT_NUMA_VARIABLE_LOCALITY
- depends on SMP && NUMA && MIGRATION && !PREEMPT_RT
-+ depends on !SCHED_ALT
- help
- This option adds support for automatic NUMA aware memory/task placement.
- The mechanism is quite primitive and is based on migrating memory when
-@@ -1011,6 +1043,7 @@ config FAIR_GROUP_SCHED
- depends on CGROUP_SCHED
- default CGROUP_SCHED
-
-+if !SCHED_ALT
- config CFS_BANDWIDTH
- bool "CPU bandwidth provisioning for FAIR_GROUP_SCHED"
- depends on FAIR_GROUP_SCHED
-@@ -1033,6 +1066,7 @@ config RT_GROUP_SCHED
- realtime bandwidth for them.
- See Documentation/scheduler/sched-rt-group.rst for more information.
-
-+endif #!SCHED_ALT
- endif #CGROUP_SCHED
-
- config SCHED_MM_CID
-@@ -1281,6 +1315,7 @@ config CHECKPOINT_RESTORE
-
- config SCHED_AUTOGROUP
- bool "Automatic process group scheduling"
-+ depends on !SCHED_ALT
- select CGROUPS
- select CGROUP_SCHED
- select FAIR_GROUP_SCHED
-diff --git a/init/init_task.c b/init/init_task.c
-index 7ecb458eb3da..9530a7173b37 100644
---- a/init/init_task.c
-+++ b/init/init_task.c
-@@ -70,9 +70,15 @@ struct task_struct init_task __aligned(L1_CACHE_BYTES) = {
- .stack = init_stack,
- .usage = REFCOUNT_INIT(2),
- .flags = PF_KTHREAD,
-+#ifdef CONFIG_SCHED_ALT
-+ .prio = DEFAULT_PRIO + MAX_PRIORITY_ADJ,
-+ .static_prio = DEFAULT_PRIO,
-+ .normal_prio = DEFAULT_PRIO + MAX_PRIORITY_ADJ,
-+#else
- .prio = MAX_PRIO - 20,
- .static_prio = MAX_PRIO - 20,
- .normal_prio = MAX_PRIO - 20,
-+#endif
- .policy = SCHED_NORMAL,
- .cpus_ptr = &init_task.cpus_mask,
- .user_cpus_ptr = NULL,
-@@ -84,6 +90,17 @@ struct task_struct init_task __aligned(L1_CACHE_BYTES) = {
- .restart_block = {
- .fn = do_no_restart_syscall,
- },
-+#ifdef CONFIG_SCHED_ALT
-+ .sq_node = LIST_HEAD_INIT(init_task.sq_node),
-+#ifdef CONFIG_SCHED_BMQ
-+ .boost_prio = 0,
-+ .sq_idx = 15,
-+#endif
-+#ifdef CONFIG_SCHED_PDS
-+ .deadline = 0,
-+#endif
-+ .time_slice = HZ,
-+#else
- .se = {
- .group_node = LIST_HEAD_INIT(init_task.se.group_node),
- },
-@@ -91,6 +108,7 @@ struct task_struct init_task __aligned(L1_CACHE_BYTES) = {
- .run_list = LIST_HEAD_INIT(init_task.rt.run_list),
- .time_slice = RR_TIMESLICE,
- },
-+#endif
- .tasks = LIST_HEAD_INIT(init_task.tasks),
- #ifdef CONFIG_SMP
- .pushable_tasks = PLIST_NODE_INIT(init_task.pushable_tasks, MAX_PRIO),
-diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
-index c2f1fd95a821..41654679b1b2 100644
---- a/kernel/Kconfig.preempt
-+++ b/kernel/Kconfig.preempt
-@@ -117,7 +117,7 @@ config PREEMPT_DYNAMIC
-
- config SCHED_CORE
- bool "Core Scheduling for SMT"
-- depends on SCHED_SMT
-+ depends on SCHED_SMT && !SCHED_ALT
- help
- This option permits Core Scheduling, a means of coordinated task
- selection across SMT siblings. When enabled -- see
-diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
-index 927bef3a598a..69e748ec80ab 100644
---- a/kernel/cgroup/cpuset.c
-+++ b/kernel/cgroup/cpuset.c
-@@ -855,7 +855,7 @@ static int validate_change(struct cpuset *cur, struct cpuset *trial)
- return ret;
- }
-
--#ifdef CONFIG_SMP
-+#if defined(CONFIG_SMP) && !defined(CONFIG_SCHED_ALT)
- /*
- * Helper routine for generate_sched_domains().
- * Do cpusets a, b have overlapping effective cpus_allowed masks?
-@@ -1254,7 +1254,7 @@ static void rebuild_sched_domains_locked(void)
- /* Have scheduler rebuild the domains */
- partition_and_rebuild_sched_domains(ndoms, doms, attr);
- }
--#else /* !CONFIG_SMP */
-+#else /* !CONFIG_SMP || CONFIG_SCHED_ALT */
- static void rebuild_sched_domains_locked(void)
- {
- }
-@@ -3308,12 +3308,15 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
- goto out_unlock;
- }
-
-+#ifndef CONFIG_SCHED_ALT
- if (dl_task(task)) {
- cs->nr_migrate_dl_tasks++;
- cs->sum_migrate_dl_bw += task->dl.dl_bw;
- }
-+#endif
- }
-
-+#ifndef CONFIG_SCHED_ALT
- if (!cs->nr_migrate_dl_tasks)
- goto out_success;
-
-@@ -3334,6 +3337,7 @@ static int cpuset_can_attach(struct cgroup_taskset *tset)
- }
-
- out_success:
-+#endif
- /*
- * Mark attach is in progress. This makes validate_change() fail
- * changes which zero cpus/mems_allowed.
-@@ -3357,12 +3361,14 @@ static void cpuset_cancel_attach(struct cgroup_taskset *tset)
- if (!cs->attach_in_progress)
- wake_up(&cpuset_attach_wq);
-
-+#ifndef CONFIG_SCHED_ALT
- if (cs->nr_migrate_dl_tasks) {
- int cpu = cpumask_any(cs->effective_cpus);
-
- dl_bw_free(cpu, cs->sum_migrate_dl_bw);
- reset_migrate_dl_data(cs);
- }
-+#endif
-
- mutex_unlock(&cpuset_mutex);
- }
-diff --git a/kernel/delayacct.c b/kernel/delayacct.c
-index 6f0c358e73d8..8111481ce8b1 100644
---- a/kernel/delayacct.c
-+++ b/kernel/delayacct.c
-@@ -150,7 +150,7 @@ int delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk)
- */
- t1 = tsk->sched_info.pcount;
- t2 = tsk->sched_info.run_delay;
-- t3 = tsk->se.sum_exec_runtime;
-+ t3 = tsk_seruntime(tsk);
-
- d->cpu_count += t1;
-
-diff --git a/kernel/exit.c b/kernel/exit.c
-index dfb963d2f862..510f2dea00c4 100644
---- a/kernel/exit.c
-+++ b/kernel/exit.c
-@@ -176,7 +176,7 @@ static void __exit_signal(struct task_struct *tsk)
- sig->curr_target = next_thread(tsk);
- }
-
-- add_device_randomness((const void*) &tsk->se.sum_exec_runtime,
-+ add_device_randomness((const void*) &tsk_seruntime(tsk),
- sizeof(unsigned long long));
-
- /*
-@@ -197,7 +197,7 @@ static void __exit_signal(struct task_struct *tsk)
- sig->inblock += task_io_get_inblock(tsk);
- sig->oublock += task_io_get_oublock(tsk);
- task_io_accounting_add(&sig->ioac, &tsk->ioac);
-- sig->sum_sched_runtime += tsk->se.sum_exec_runtime;
-+ sig->sum_sched_runtime += tsk_seruntime(tsk);
- sig->nr_threads--;
- __unhash_process(tsk, group_dead);
- write_sequnlock(&sig->stats_lock);
-diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
-index 4a10e8c16fd2..cfbbdd64b851 100644
---- a/kernel/locking/rtmutex.c
-+++ b/kernel/locking/rtmutex.c
-@@ -362,7 +362,7 @@ waiter_update_prio(struct rt_mutex_waiter *waiter, struct task_struct *task)
- lockdep_assert(RB_EMPTY_NODE(&waiter->tree.entry));
-
- waiter->tree.prio = __waiter_prio(task);
-- waiter->tree.deadline = task->dl.deadline;
-+ waiter->tree.deadline = __tsk_deadline(task);
- }
-
- /*
-@@ -383,16 +383,20 @@ waiter_clone_prio(struct rt_mutex_waiter *waiter, struct task_struct *task)
- * Only use with rt_waiter_node_{less,equal}()
- */
- #define task_to_waiter_node(p) \
-- &(struct rt_waiter_node){ .prio = __waiter_prio(p), .deadline = (p)->dl.deadline }
-+ &(struct rt_waiter_node){ .prio = __waiter_prio(p), .deadline = __tsk_deadline(p) }
- #define task_to_waiter(p) \
- &(struct rt_mutex_waiter){ .tree = *task_to_waiter_node(p) }
-
- static __always_inline int rt_waiter_node_less(struct rt_waiter_node *left,
- struct rt_waiter_node *right)
- {
-+#ifdef CONFIG_SCHED_PDS
-+ return (left->deadline < right->deadline);
-+#else
- if (left->prio < right->prio)
- return 1;
-
-+#ifndef CONFIG_SCHED_BMQ
- /*
- * If both waiters have dl_prio(), we check the deadlines of the
- * associated tasks.
-@@ -401,16 +405,22 @@ static __always_inline int rt_waiter_node_less(struct rt_waiter_node *left,
- */
- if (dl_prio(left->prio))
- return dl_time_before(left->deadline, right->deadline);
-+#endif
-
- return 0;
-+#endif
- }
-
- static __always_inline int rt_waiter_node_equal(struct rt_waiter_node *left,
- struct rt_waiter_node *right)
- {
-+#ifdef CONFIG_SCHED_PDS
-+ return (left->deadline == right->deadline);
-+#else
- if (left->prio != right->prio)
- return 0;
-
-+#ifndef CONFIG_SCHED_BMQ
- /*
- * If both waiters have dl_prio(), we check the deadlines of the
- * associated tasks.
-@@ -419,8 +429,10 @@ static __always_inline int rt_waiter_node_equal(struct rt_waiter_node *left,
- */
- if (dl_prio(left->prio))
- return left->deadline == right->deadline;
-+#endif
-
- return 1;
-+#endif
- }
-
- static inline bool rt_mutex_steal(struct rt_mutex_waiter *waiter,
-diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
-index 976092b7bd45..31d587c16ec1 100644
---- a/kernel/sched/Makefile
-+++ b/kernel/sched/Makefile
-@@ -28,7 +28,12 @@ endif
- # These compilation units have roughly the same size and complexity - so their
- # build parallelizes well and finishes roughly at once:
- #
-+ifdef CONFIG_SCHED_ALT
-+obj-y += alt_core.o
-+obj-$(CONFIG_SCHED_DEBUG) += alt_debug.o
-+else
- obj-y += core.o
- obj-y += fair.o
-+endif
- obj-y += build_policy.o
- obj-y += build_utility.o
-diff --git a/kernel/sched/alt_core.c b/kernel/sched/alt_core.c
-new file mode 100644
-index 000000000000..2745abb36a20
---- /dev/null
-+++ b/kernel/sched/alt_core.c
-@@ -0,0 +1,8960 @@
-+/*
-+ * kernel/sched/alt_core.c
-+ *
-+ * Core alternative kernel scheduler code and related syscalls
-+ *
-+ * Copyright (C) 1991-2002 Linus Torvalds
-+ *
-+ * 2009-08-13 Brainfuck deadline scheduling policy by Con Kolivas deletes
-+ * a whole lot of those previous things.
-+ * 2017-09-06 Priority and Deadline based Skip list multiple queue kernel
-+ * scheduler by Alfred Chen.
-+ * 2019-02-20 BMQ(BitMap Queue) kernel scheduler by Alfred Chen.
-+ */
-+#include <linux/sched/clock.h>
-+#include <linux/sched/cputime.h>
-+#include <linux/sched/debug.h>
-+#include <linux/sched/hotplug.h>
-+#include <linux/sched/init.h>
-+#include <linux/sched/isolation.h>
-+#include <linux/sched/loadavg.h>
-+#include <linux/sched/mm.h>
-+#include <linux/sched/nohz.h>
-+#include <linux/sched/stat.h>
-+#include <linux/sched/wake_q.h>
-+
-+#include <linux/blkdev.h>
-+#include <linux/context_tracking.h>
-+#include <linux/cpuset.h>
-+#include <linux/delayacct.h>
-+#include <linux/init_task.h>
-+#include <linux/kcov.h>
-+#include <linux/kprobes.h>
-+#include <linux/nmi.h>
-+#include <linux/rseq.h>
-+#include <linux/scs.h>
-+
-+#include <uapi/linux/sched/types.h>
-+
-+#include <asm/irq_regs.h>
-+#include <asm/switch_to.h>
-+
-+#define CREATE_TRACE_POINTS
-+#include <trace/events/sched.h>
-+#include <trace/events/ipi.h>
-+#undef CREATE_TRACE_POINTS
-+
-+#include "sched.h"
-+#include "smp.h"
-+
-+#include "pelt.h"
-+
-+#include "../../io_uring/io-wq.h"
-+#include "../smpboot.h"
-+
-+EXPORT_TRACEPOINT_SYMBOL_GPL(ipi_send_cpu);
-+EXPORT_TRACEPOINT_SYMBOL_GPL(ipi_send_cpumask);
-+
-+/*
-+ * Export tracepoints that act as a bare tracehook (ie: have no trace event
-+ * associated with them) to allow external modules to probe them.
-+ */
-+EXPORT_TRACEPOINT_SYMBOL_GPL(pelt_irq_tp);
-+
-+#ifdef CONFIG_SCHED_DEBUG
-+#define sched_feat(x) (1)
-+/*
-+ * Print a warning if need_resched is set for the given duration (if
-+ * LATENCY_WARN is enabled).
-+ *
-+ * If sysctl_resched_latency_warn_once is set, only one warning will be shown
-+ * per boot.
-+ */
-+__read_mostly int sysctl_resched_latency_warn_ms = 100;
-+__read_mostly int sysctl_resched_latency_warn_once = 1;
-+#else
-+#define sched_feat(x) (0)
-+#endif /* CONFIG_SCHED_DEBUG */
-+
-+#define ALT_SCHED_VERSION "v6.8-r0"
-+
-+/*
-+ * Compile time debug macro
-+ * #define ALT_SCHED_DEBUG
-+ */
-+
-+/* rt_prio(prio) defined in include/linux/sched/rt.h */
-+#define rt_task(p) rt_prio((p)->prio)
-+#define rt_policy(policy) ((policy) == SCHED_FIFO || (policy) == SCHED_RR)
-+#define task_has_rt_policy(p) (rt_policy((p)->policy))
-+
-+#define STOP_PRIO (MAX_RT_PRIO - 1)
-+
-+/*
-+ * Time slice
-+ * (default: 4 msec, units: nanoseconds)
-+ */
-+unsigned int sysctl_sched_base_slice __read_mostly = (4 << 20);
-+
-+static inline void requeue_task(struct task_struct *p, struct rq *rq, int idx);
-+
-+#ifdef CONFIG_SCHED_BMQ
-+#include "bmq.h"
-+#endif
-+#ifdef CONFIG_SCHED_PDS
-+#include "pds.h"
-+#endif
-+
-+struct affinity_context {
-+ const struct cpumask *new_mask;
-+ struct cpumask *user_mask;
-+ unsigned int flags;
-+};
-+
-+/* Reschedule if less than this many μs left */
-+#define RESCHED_NS (100 << 10)
-+
-+/**
-+ * sched_yield_type - Type of sched_yield() will be performed.
-+ * 0: No yield.
-+ * 1: Requeue task. (default)
-+ * 2: Set rq skip task. (Same as mainline)
-+ */
-+int sched_yield_type __read_mostly = 1;
-+
-+#ifdef CONFIG_SMP
-+static cpumask_t sched_rq_pending_mask ____cacheline_aligned_in_smp;
-+
-+DEFINE_PER_CPU_ALIGNED(cpumask_t [NR_CPU_AFFINITY_LEVELS], sched_cpu_topo_masks);
-+DEFINE_PER_CPU_ALIGNED(cpumask_t *, sched_cpu_llc_mask);
-+DEFINE_PER_CPU_ALIGNED(cpumask_t *, sched_cpu_topo_end_mask);
-+
-+#ifdef CONFIG_SCHED_SMT
-+DEFINE_STATIC_KEY_FALSE(sched_smt_present);
-+EXPORT_SYMBOL_GPL(sched_smt_present);
-+#endif
-+
-+/*
-+ * Keep a unique ID per domain (we use the first CPUs number in the cpumask of
-+ * the domain), this allows us to quickly tell if two cpus are in the same cache
-+ * domain, see cpus_share_cache().
-+ */
-+DEFINE_PER_CPU(int, sd_llc_id);
-+#endif /* CONFIG_SMP */
-+
-+static DEFINE_MUTEX(sched_hotcpu_mutex);
-+
-+DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
-+
-+#ifndef prepare_arch_switch
-+# define prepare_arch_switch(next) do { } while (0)
-+#endif
-+#ifndef finish_arch_post_lock_switch
-+# define finish_arch_post_lock_switch() do { } while (0)
-+#endif
-+
-+#ifdef CONFIG_SCHED_SMT
-+static cpumask_t sched_sg_idle_mask ____cacheline_aligned_in_smp;
-+#endif
-+static cpumask_t sched_preempt_mask[SCHED_QUEUE_BITS] ____cacheline_aligned_in_smp;
-+static cpumask_t *const sched_idle_mask = &sched_preempt_mask[0];
-+
-+/* task function */
-+static inline const struct cpumask *task_user_cpus(struct task_struct *p)
-+{
-+ if (!p->user_cpus_ptr)
-+ return cpu_possible_mask; /* &init_task.cpus_mask */
-+ return p->user_cpus_ptr;
-+}
-+
-+/* sched_queue related functions */
-+static inline void sched_queue_init(struct sched_queue *q)
-+{
-+ int i;
-+
-+ bitmap_zero(q->bitmap, SCHED_QUEUE_BITS);
-+ for(i = 0; i < SCHED_LEVELS; i++)
-+ INIT_LIST_HEAD(&q->heads[i]);
-+}
-+
-+/*
-+ * Init idle task and put into queue structure of rq
-+ * IMPORTANT: may be called multiple times for a single cpu
-+ */
-+static inline void sched_queue_init_idle(struct sched_queue *q,
-+ struct task_struct *idle)
-+{
-+ idle->sq_idx = IDLE_TASK_SCHED_PRIO;
-+ INIT_LIST_HEAD(&q->heads[idle->sq_idx]);
-+ list_add(&idle->sq_node, &q->heads[idle->sq_idx]);
-+}
-+
-+static inline void
-+clear_recorded_preempt_mask(int pr, int low, int high, int cpu)
-+{
-+ if (low < pr && pr <= high)
-+ cpumask_clear_cpu(cpu, sched_preempt_mask + SCHED_QUEUE_BITS - pr);
-+}
-+
-+static inline void
-+set_recorded_preempt_mask(int pr, int low, int high, int cpu)
-+{
-+ if (low < pr && pr <= high)
-+ cpumask_set_cpu(cpu, sched_preempt_mask + SCHED_QUEUE_BITS - pr);
-+}
-+
-+static atomic_t sched_prio_record = ATOMIC_INIT(0);
-+
-+/* water mark related functions */
-+static inline void update_sched_preempt_mask(struct rq *rq)
-+{
-+ unsigned long prio = find_first_bit(rq->queue.bitmap, SCHED_QUEUE_BITS);
-+ unsigned long last_prio = rq->prio;
-+ int cpu, pr;
-+
-+ if (prio == last_prio)
-+ return;
-+
-+ rq->prio = prio;
-+ cpu = cpu_of(rq);
-+ pr = atomic_read(&sched_prio_record);
-+
-+ if (prio < last_prio) {
-+ if (IDLE_TASK_SCHED_PRIO == last_prio) {
-+#ifdef CONFIG_SCHED_SMT
-+ if (static_branch_likely(&sched_smt_present))
-+ cpumask_andnot(&sched_sg_idle_mask,
-+ &sched_sg_idle_mask, cpu_smt_mask(cpu));
-+#endif
-+ cpumask_clear_cpu(cpu, sched_idle_mask);
-+ last_prio -= 2;
-+ }
-+ clear_recorded_preempt_mask(pr, prio, last_prio, cpu);
-+
-+ return;
-+ }
-+ /* last_prio < prio */
-+ if (IDLE_TASK_SCHED_PRIO == prio) {
-+#ifdef CONFIG_SCHED_SMT
-+ if (static_branch_likely(&sched_smt_present) &&
-+ cpumask_intersects(cpu_smt_mask(cpu), sched_idle_mask))
-+ cpumask_or(&sched_sg_idle_mask,
-+ &sched_sg_idle_mask, cpu_smt_mask(cpu));
-+#endif
-+ cpumask_set_cpu(cpu, sched_idle_mask);
-+ prio -= 2;
-+ }
-+ set_recorded_preempt_mask(pr, last_prio, prio, cpu);
-+}
-+
-+/*
-+ * This routine assume that the idle task always in queue
-+ */
-+static inline struct task_struct *sched_rq_first_task(struct rq *rq)
-+{
-+ const struct list_head *head = &rq->queue.heads[sched_prio2idx(rq->prio, rq)];
-+
-+ return list_first_entry(head, struct task_struct, sq_node);
-+}
-+
-+static inline struct task_struct *
-+sched_rq_next_task(struct task_struct *p, struct rq *rq)
-+{
-+ unsigned long idx = p->sq_idx;
-+ struct list_head *head = &rq->queue.heads[idx];
-+
-+ if (list_is_last(&p->sq_node, head)) {
-+ idx = find_next_bit(rq->queue.bitmap, SCHED_QUEUE_BITS,
-+ sched_idx2prio(idx, rq) + 1);
-+ head = &rq->queue.heads[sched_prio2idx(idx, rq)];
-+
-+ return list_first_entry(head, struct task_struct, sq_node);
-+ }
-+
-+ return list_next_entry(p, sq_node);
-+}
-+
-+static inline struct task_struct *rq_runnable_task(struct rq *rq)
-+{
-+ struct task_struct *next = sched_rq_first_task(rq);
-+
-+ if (unlikely(next == rq->skip))
-+ next = sched_rq_next_task(next, rq);
-+
-+ return next;
-+}
-+
-+/*
-+ * Serialization rules:
-+ *
-+ * Lock order:
-+ *
-+ * p->pi_lock
-+ * rq->lock
-+ * hrtimer_cpu_base->lock (hrtimer_start() for bandwidth controls)
-+ *
-+ * rq1->lock
-+ * rq2->lock where: rq1 < rq2
-+ *
-+ * Regular state:
-+ *
-+ * Normal scheduling state is serialized by rq->lock. __schedule() takes the
-+ * local CPU's rq->lock, it optionally removes the task from the runqueue and
-+ * always looks at the local rq data structures to find the most eligible task
-+ * to run next.
-+ *
-+ * Task enqueue is also under rq->lock, possibly taken from another CPU.
-+ * Wakeups from another LLC domain might use an IPI to transfer the enqueue to
-+ * the local CPU to avoid bouncing the runqueue state around [ see
-+ * ttwu_queue_wakelist() ]
-+ *
-+ * Task wakeup, specifically wakeups that involve migration, are horribly
-+ * complicated to avoid having to take two rq->locks.
-+ *
-+ * Special state:
-+ *
-+ * System-calls and anything external will use task_rq_lock() which acquires
-+ * both p->pi_lock and rq->lock. As a consequence the state they change is
-+ * stable while holding either lock:
-+ *
-+ * - sched_setaffinity()/
-+ * set_cpus_allowed_ptr(): p->cpus_ptr, p->nr_cpus_allowed
-+ * - set_user_nice(): p->se.load, p->*prio
-+ * - __sched_setscheduler(): p->sched_class, p->policy, p->*prio,
-+ * p->se.load, p->rt_priority,
-+ * p->dl.dl_{runtime, deadline, period, flags, bw, density}
-+ * - sched_setnuma(): p->numa_preferred_nid
-+ * - sched_move_task(): p->sched_task_group
-+ * - uclamp_update_active() p->uclamp*
-+ *
-+ * p->state <- TASK_*:
-+ *
-+ * is changed locklessly using set_current_state(), __set_current_state() or
-+ * set_special_state(), see their respective comments, or by
-+ * try_to_wake_up(). This latter uses p->pi_lock to serialize against
-+ * concurrent self.
-+ *
-+ * p->on_rq <- { 0, 1 = TASK_ON_RQ_QUEUED, 2 = TASK_ON_RQ_MIGRATING }:
-+ *
-+ * is set by activate_task() and cleared by deactivate_task(), under
-+ * rq->lock. Non-zero indicates the task is runnable, the special
-+ * ON_RQ_MIGRATING state is used for migration without holding both
-+ * rq->locks. It indicates task_cpu() is not stable, see task_rq_lock().
-+ *
-+ * p->on_cpu <- { 0, 1 }:
-+ *
-+ * is set by prepare_task() and cleared by finish_task() such that it will be
-+ * set before p is scheduled-in and cleared after p is scheduled-out, both
-+ * under rq->lock. Non-zero indicates the task is running on its CPU.
-+ *
-+ * [ The astute reader will observe that it is possible for two tasks on one
-+ * CPU to have ->on_cpu = 1 at the same time. ]
-+ *
-+ * task_cpu(p): is changed by set_task_cpu(), the rules are:
-+ *
-+ * - Don't call set_task_cpu() on a blocked task:
-+ *
-+ * We don't care what CPU we're not running on, this simplifies hotplug,
-+ * the CPU assignment of blocked tasks isn't required to be valid.
-+ *
-+ * - for try_to_wake_up(), called under p->pi_lock:
-+ *
-+ * This allows try_to_wake_up() to only take one rq->lock, see its comment.
-+ *
-+ * - for migration called under rq->lock:
-+ * [ see task_on_rq_migrating() in task_rq_lock() ]
-+ *
-+ * o move_queued_task()
-+ * o detach_task()
-+ *
-+ * - for migration called under double_rq_lock():
-+ *
-+ * o __migrate_swap_task()
-+ * o push_rt_task() / pull_rt_task()
-+ * o push_dl_task() / pull_dl_task()
-+ * o dl_task_offline_migration()
-+ *
-+ */
-+
-+/*
-+ * Context: p->pi_lock
-+ */
-+static inline struct rq
-+*__task_access_lock(struct task_struct *p, raw_spinlock_t **plock)
-+{
-+ struct rq *rq;
-+ for (;;) {
-+ rq = task_rq(p);
-+ if (p->on_cpu || task_on_rq_queued(p)) {
-+ raw_spin_lock(&rq->lock);
-+ if (likely((p->on_cpu || task_on_rq_queued(p))
-+ && rq == task_rq(p))) {
-+ *plock = &rq->lock;
-+ return rq;
-+ }
-+ raw_spin_unlock(&rq->lock);
-+ } else if (task_on_rq_migrating(p)) {
-+ do {
-+ cpu_relax();
-+ } while (unlikely(task_on_rq_migrating(p)));
-+ } else {
-+ *plock = NULL;
-+ return rq;
-+ }
-+ }
-+}
-+
-+static inline void
-+__task_access_unlock(struct task_struct *p, raw_spinlock_t *lock)
-+{
-+ if (NULL != lock)
-+ raw_spin_unlock(lock);
-+}
-+
-+static inline struct rq
-+*task_access_lock_irqsave(struct task_struct *p, raw_spinlock_t **plock,
-+ unsigned long *flags)
-+{
-+ struct rq *rq;
-+ for (;;) {
-+ rq = task_rq(p);
-+ if (p->on_cpu || task_on_rq_queued(p)) {
-+ raw_spin_lock_irqsave(&rq->lock, *flags);
-+ if (likely((p->on_cpu || task_on_rq_queued(p))
-+ && rq == task_rq(p))) {
-+ *plock = &rq->lock;
-+ return rq;
-+ }
-+ raw_spin_unlock_irqrestore(&rq->lock, *flags);
-+ } else if (task_on_rq_migrating(p)) {
-+ do {
-+ cpu_relax();
-+ } while (unlikely(task_on_rq_migrating(p)));
-+ } else {
-+ raw_spin_lock_irqsave(&p->pi_lock, *flags);
-+ if (likely(!p->on_cpu && !p->on_rq &&
-+ rq == task_rq(p))) {
-+ *plock = &p->pi_lock;
-+ return rq;
-+ }
-+ raw_spin_unlock_irqrestore(&p->pi_lock, *flags);
-+ }
-+ }
-+}
-+
-+static inline void
-+task_access_unlock_irqrestore(struct task_struct *p, raw_spinlock_t *lock,
-+ unsigned long *flags)
-+{
-+ raw_spin_unlock_irqrestore(lock, *flags);
-+}
-+
-+/*
-+ * __task_rq_lock - lock the rq @p resides on.
-+ */
-+struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf)
-+ __acquires(rq->lock)
-+{
-+ struct rq *rq;
-+
-+ lockdep_assert_held(&p->pi_lock);
-+
-+ for (;;) {
-+ rq = task_rq(p);
-+ raw_spin_lock(&rq->lock);
-+ if (likely(rq == task_rq(p) && !task_on_rq_migrating(p)))
-+ return rq;
-+ raw_spin_unlock(&rq->lock);
-+
-+ while (unlikely(task_on_rq_migrating(p)))
-+ cpu_relax();
-+ }
-+}
-+
-+/*
-+ * task_rq_lock - lock p->pi_lock and lock the rq @p resides on.
-+ */
-+struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf)
-+ __acquires(p->pi_lock)
-+ __acquires(rq->lock)
-+{
-+ struct rq *rq;
-+
-+ for (;;) {
-+ raw_spin_lock_irqsave(&p->pi_lock, rf->flags);
-+ rq = task_rq(p);
-+ raw_spin_lock(&rq->lock);
-+ /*
-+ * move_queued_task() task_rq_lock()
-+ *
-+ * ACQUIRE (rq->lock)
-+ * [S] ->on_rq = MIGRATING [L] rq = task_rq()
-+ * WMB (__set_task_cpu()) ACQUIRE (rq->lock);
-+ * [S] ->cpu = new_cpu [L] task_rq()
-+ * [L] ->on_rq
-+ * RELEASE (rq->lock)
-+ *
-+ * If we observe the old CPU in task_rq_lock(), the acquire of
-+ * the old rq->lock will fully serialize against the stores.
-+ *
-+ * If we observe the new CPU in task_rq_lock(), the address
-+ * dependency headed by '[L] rq = task_rq()' and the acquire
-+ * will pair with the WMB to ensure we then also see migrating.
-+ */
-+ if (likely(rq == task_rq(p) && !task_on_rq_migrating(p))) {
-+ return rq;
-+ }
-+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags);
-+
-+ while (unlikely(task_on_rq_migrating(p)))
-+ cpu_relax();
-+ }
-+}
-+
-+static inline void
-+rq_lock_irqsave(struct rq *rq, struct rq_flags *rf)
-+ __acquires(rq->lock)
-+{
-+ raw_spin_lock_irqsave(&rq->lock, rf->flags);
-+}
-+
-+static inline void
-+rq_unlock_irqrestore(struct rq *rq, struct rq_flags *rf)
-+ __releases(rq->lock)
-+{
-+ raw_spin_unlock_irqrestore(&rq->lock, rf->flags);
-+}
-+
-+DEFINE_LOCK_GUARD_1(rq_lock_irqsave, struct rq,
-+ rq_lock_irqsave(_T->lock, &_T->rf),
-+ rq_unlock_irqrestore(_T->lock, &_T->rf),
-+ struct rq_flags rf)
-+
-+void raw_spin_rq_lock_nested(struct rq *rq, int subclass)
-+{
-+ raw_spinlock_t *lock;
-+
-+ /* Matches synchronize_rcu() in __sched_core_enable() */
-+ preempt_disable();
-+
-+ for (;;) {
-+ lock = __rq_lockp(rq);
-+ raw_spin_lock_nested(lock, subclass);
-+ if (likely(lock == __rq_lockp(rq))) {
-+ /* preempt_count *MUST* be > 1 */
-+ preempt_enable_no_resched();
-+ return;
-+ }
-+ raw_spin_unlock(lock);
-+ }
-+}
-+
-+void raw_spin_rq_unlock(struct rq *rq)
-+{
-+ raw_spin_unlock(rq_lockp(rq));
-+}
-+
-+/*
-+ * RQ-clock updating methods:
-+ */
-+
-+static void update_rq_clock_task(struct rq *rq, s64 delta)
-+{
-+/*
-+ * In theory, the compile should just see 0 here, and optimize out the call
-+ * to sched_rt_avg_update. But I don't trust it...
-+ */
-+ s64 __maybe_unused steal = 0, irq_delta = 0;
-+
-+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
-+ irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time;
-+
-+ /*
-+ * Since irq_time is only updated on {soft,}irq_exit, we might run into
-+ * this case when a previous update_rq_clock() happened inside a
-+ * {soft,}irq region.
-+ *
-+ * When this happens, we stop ->clock_task and only update the
-+ * prev_irq_time stamp to account for the part that fit, so that a next
-+ * update will consume the rest. This ensures ->clock_task is
-+ * monotonic.
-+ *
-+ * It does however cause some slight miss-attribution of {soft,}irq
-+ * time, a more accurate solution would be to update the irq_time using
-+ * the current rq->clock timestamp, except that would require using
-+ * atomic ops.
-+ */
-+ if (irq_delta > delta)
-+ irq_delta = delta;
-+
-+ rq->prev_irq_time += irq_delta;
-+ delta -= irq_delta;
-+ delayacct_irq(rq->curr, irq_delta);
-+#endif
-+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
-+ if (static_key_false((¶virt_steal_rq_enabled))) {
-+ steal = paravirt_steal_clock(cpu_of(rq));
-+ steal -= rq->prev_steal_time_rq;
-+
-+ if (unlikely(steal > delta))
-+ steal = delta;
-+
-+ rq->prev_steal_time_rq += steal;
-+ delta -= steal;
-+ }
-+#endif
-+
-+ rq->clock_task += delta;
-+
-+#ifdef CONFIG_HAVE_SCHED_AVG_IRQ
-+ if ((irq_delta + steal))
-+ update_irq_load_avg(rq, irq_delta + steal);
-+#endif
-+}
-+
-+static inline void update_rq_clock(struct rq *rq)
-+{
-+ s64 delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
-+
-+ if (unlikely(delta <= 0))
-+ return;
-+ rq->clock += delta;
-+ sched_update_rq_clock(rq);
-+ update_rq_clock_task(rq, delta);
-+}
-+
-+/*
-+ * RQ Load update routine
-+ */
-+#define RQ_LOAD_HISTORY_BITS (sizeof(s32) * 8ULL)
-+#define RQ_UTIL_SHIFT (8)
-+#define RQ_LOAD_HISTORY_TO_UTIL(l) (((l) >> (RQ_LOAD_HISTORY_BITS - 1 - RQ_UTIL_SHIFT)) & 0xff)
-+
-+#define LOAD_BLOCK(t) ((t) >> 17)
-+#define LOAD_HALF_BLOCK(t) ((t) >> 16)
-+#define BLOCK_MASK(t) ((t) & ((0x01 << 18) - 1))
-+#define LOAD_BLOCK_BIT(b) (1UL << (RQ_LOAD_HISTORY_BITS - 1 - (b)))
-+#define CURRENT_LOAD_BIT LOAD_BLOCK_BIT(0)
-+
-+static inline void rq_load_update(struct rq *rq)
-+{
-+ u64 time = rq->clock;
-+ u64 delta = min(LOAD_BLOCK(time) - LOAD_BLOCK(rq->load_stamp),
-+ RQ_LOAD_HISTORY_BITS - 1);
-+ u64 prev = !!(rq->load_history & CURRENT_LOAD_BIT);
-+ u64 curr = !!rq->nr_running;
-+
-+ if (delta) {
-+ rq->load_history = rq->load_history >> delta;
-+
-+ if (delta < RQ_UTIL_SHIFT) {
-+ rq->load_block += (~BLOCK_MASK(rq->load_stamp)) * prev;
-+ if (!!LOAD_HALF_BLOCK(rq->load_block) ^ curr)
-+ rq->load_history ^= LOAD_BLOCK_BIT(delta);
-+ }
-+
-+ rq->load_block = BLOCK_MASK(time) * prev;
-+ } else {
-+ rq->load_block += (time - rq->load_stamp) * prev;
-+ }
-+ if (prev ^ curr)
-+ rq->load_history ^= CURRENT_LOAD_BIT;
-+ rq->load_stamp = time;
-+}
-+
-+unsigned long rq_load_util(struct rq *rq, unsigned long max)
-+{
-+ return RQ_LOAD_HISTORY_TO_UTIL(rq->load_history) * (max >> RQ_UTIL_SHIFT);
-+}
-+
-+#ifdef CONFIG_SMP
-+unsigned long sched_cpu_util(int cpu)
-+{
-+ return rq_load_util(cpu_rq(cpu), arch_scale_cpu_capacity(cpu));
-+}
-+#endif /* CONFIG_SMP */
-+
-+#ifdef CONFIG_CPU_FREQ
-+/**
-+ * cpufreq_update_util - Take a note about CPU utilization changes.
-+ * @rq: Runqueue to carry out the update for.
-+ * @flags: Update reason flags.
-+ *
-+ * This function is called by the scheduler on the CPU whose utilization is
-+ * being updated.
-+ *
-+ * It can only be called from RCU-sched read-side critical sections.
-+ *
-+ * The way cpufreq is currently arranged requires it to evaluate the CPU
-+ * performance state (frequency/voltage) on a regular basis to prevent it from
-+ * being stuck in a completely inadequate performance level for too long.
-+ * That is not guaranteed to happen if the updates are only triggered from CFS
-+ * and DL, though, because they may not be coming in if only RT tasks are
-+ * active all the time (or there are RT tasks only).
-+ *
-+ * As a workaround for that issue, this function is called periodically by the
-+ * RT sched class to trigger extra cpufreq updates to prevent it from stalling,
-+ * but that really is a band-aid. Going forward it should be replaced with
-+ * solutions targeted more specifically at RT tasks.
-+ */
-+static inline void cpufreq_update_util(struct rq *rq, unsigned int flags)
-+{
-+ struct update_util_data *data;
-+
-+#ifdef CONFIG_SMP
-+ rq_load_update(rq);
-+#endif
-+ data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data,
-+ cpu_of(rq)));
-+ if (data)
-+ data->func(data, rq_clock(rq), flags);
-+}
-+#else
-+static inline void cpufreq_update_util(struct rq *rq, unsigned int flags)
-+{
-+#ifdef CONFIG_SMP
-+ rq_load_update(rq);
-+#endif
-+}
-+#endif /* CONFIG_CPU_FREQ */
-+
-+#ifdef CONFIG_NO_HZ_FULL
-+/*
-+ * Tick may be needed by tasks in the runqueue depending on their policy and
-+ * requirements. If tick is needed, lets send the target an IPI to kick it out
-+ * of nohz mode if necessary.
-+ */
-+static inline void sched_update_tick_dependency(struct rq *rq)
-+{
-+ int cpu = cpu_of(rq);
-+
-+ if (!tick_nohz_full_cpu(cpu))
-+ return;
-+
-+ if (rq->nr_running < 2)
-+ tick_nohz_dep_clear_cpu(cpu, TICK_DEP_BIT_SCHED);
-+ else
-+ tick_nohz_dep_set_cpu(cpu, TICK_DEP_BIT_SCHED);
-+}
-+#else /* !CONFIG_NO_HZ_FULL */
-+static inline void sched_update_tick_dependency(struct rq *rq) { }
-+#endif
-+
-+bool sched_task_on_rq(struct task_struct *p)
-+{
-+ return task_on_rq_queued(p);
-+}
-+
-+unsigned long get_wchan(struct task_struct *p)
-+{
-+ unsigned long ip = 0;
-+ unsigned int state;
-+
-+ if (!p || p == current)
-+ return 0;
-+
-+ /* Only get wchan if task is blocked and we can keep it that way. */
-+ raw_spin_lock_irq(&p->pi_lock);
-+ state = READ_ONCE(p->__state);
-+ smp_rmb(); /* see try_to_wake_up() */
-+ if (state != TASK_RUNNING && state != TASK_WAKING && !p->on_rq)
-+ ip = __get_wchan(p);
-+ raw_spin_unlock_irq(&p->pi_lock);
-+
-+ return ip;
-+}
-+
-+/*
-+ * Add/Remove/Requeue task to/from the runqueue routines
-+ * Context: rq->lock
-+ */
-+#define __SCHED_DEQUEUE_TASK(p, rq, flags, func) \
-+ sched_info_dequeue(rq, p); \
-+ \
-+ list_del(&p->sq_node); \
-+ if (list_empty(&rq->queue.heads[p->sq_idx])) { \
-+ clear_bit(sched_idx2prio(p->sq_idx, rq), rq->queue.bitmap); \
-+ func; \
-+ }
-+
-+#define __SCHED_ENQUEUE_TASK(p, rq, flags) \
-+ sched_info_enqueue(rq, p); \
-+ \
-+ p->sq_idx = task_sched_prio_idx(p, rq); \
-+ list_add_tail(&p->sq_node, &rq->queue.heads[p->sq_idx]); \
-+ set_bit(sched_idx2prio(p->sq_idx, rq), rq->queue.bitmap);
-+
-+static inline void dequeue_task(struct task_struct *p, struct rq *rq, int flags)
-+{
-+#ifdef ALT_SCHED_DEBUG
-+ lockdep_assert_held(&rq->lock);
-+
-+ /*printk(KERN_INFO "sched: dequeue(%d) %px %016llx\n", cpu_of(rq), p, p->deadline);*/
-+ WARN_ONCE(task_rq(p) != rq, "sched: dequeue task reside on cpu%d from cpu%d\n",
-+ task_cpu(p), cpu_of(rq));
-+#endif
-+
-+ __SCHED_DEQUEUE_TASK(p, rq, flags, update_sched_preempt_mask(rq));
-+ --rq->nr_running;
-+#ifdef CONFIG_SMP
-+ if (1 == rq->nr_running)
-+ cpumask_clear_cpu(cpu_of(rq), &sched_rq_pending_mask);
-+#endif
-+
-+ sched_update_tick_dependency(rq);
-+}
-+
-+static inline void enqueue_task(struct task_struct *p, struct rq *rq, int flags)
-+{
-+#ifdef ALT_SCHED_DEBUG
-+ lockdep_assert_held(&rq->lock);
-+
-+ /*printk(KERN_INFO "sched: enqueue(%d) %px %d\n", cpu_of(rq), p, p->prio);*/
-+ WARN_ONCE(task_rq(p) != rq, "sched: enqueue task reside on cpu%d to cpu%d\n",
-+ task_cpu(p), cpu_of(rq));
-+#endif
-+
-+ __SCHED_ENQUEUE_TASK(p, rq, flags);
-+ update_sched_preempt_mask(rq);
-+ ++rq->nr_running;
-+#ifdef CONFIG_SMP
-+ if (2 == rq->nr_running)
-+ cpumask_set_cpu(cpu_of(rq), &sched_rq_pending_mask);
-+#endif
-+
-+ sched_update_tick_dependency(rq);
-+}
-+
-+static inline void requeue_task(struct task_struct *p, struct rq *rq, int idx)
-+{
-+#ifdef ALT_SCHED_DEBUG
-+ lockdep_assert_held(&rq->lock);
-+ /*printk(KERN_INFO "sched: requeue(%d) %px %016llx\n", cpu_of(rq), p, p->deadline);*/
-+ WARN_ONCE(task_rq(p) != rq, "sched: cpu[%d] requeue task reside on cpu%d\n",
-+ cpu_of(rq), task_cpu(p));
-+#endif
-+
-+ list_del(&p->sq_node);
-+ list_add_tail(&p->sq_node, &rq->queue.heads[idx]);
-+ if (idx != p->sq_idx) {
-+ if (list_empty(&rq->queue.heads[p->sq_idx]))
-+ clear_bit(sched_idx2prio(p->sq_idx, rq), rq->queue.bitmap);
-+ p->sq_idx = idx;
-+ set_bit(sched_idx2prio(p->sq_idx, rq), rq->queue.bitmap);
-+ update_sched_preempt_mask(rq);
-+ }
-+}
-+
-+/*
-+ * cmpxchg based fetch_or, macro so it works for different integer types
-+ */
-+#define fetch_or(ptr, mask) \
-+ ({ \
-+ typeof(ptr) _ptr = (ptr); \
-+ typeof(mask) _mask = (mask); \
-+ typeof(*_ptr) _val = *_ptr; \
-+ \
-+ do { \
-+ } while (!try_cmpxchg(_ptr, &_val, _val | _mask)); \
-+ _val; \
-+})
-+
-+#if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG)
-+/*
-+ * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG,
-+ * this avoids any races wrt polling state changes and thereby avoids
-+ * spurious IPIs.
-+ */
-+static inline bool set_nr_and_not_polling(struct task_struct *p)
-+{
-+ struct thread_info *ti = task_thread_info(p);
-+ return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG);
-+}
-+
-+/*
-+ * Atomically set TIF_NEED_RESCHED if TIF_POLLING_NRFLAG is set.
-+ *
-+ * If this returns true, then the idle task promises to call
-+ * sched_ttwu_pending() and reschedule soon.
-+ */
-+static bool set_nr_if_polling(struct task_struct *p)
-+{
-+ struct thread_info *ti = task_thread_info(p);
-+ typeof(ti->flags) val = READ_ONCE(ti->flags);
-+
-+ do {
-+ if (!(val & _TIF_POLLING_NRFLAG))
-+ return false;
-+ if (val & _TIF_NEED_RESCHED)
-+ return true;
-+ } while (!try_cmpxchg(&ti->flags, &val, val | _TIF_NEED_RESCHED));
-+
-+ return true;
-+}
-+
-+#else
-+static inline bool set_nr_and_not_polling(struct task_struct *p)
-+{
-+ set_tsk_need_resched(p);
-+ return true;
-+}
-+
-+#ifdef CONFIG_SMP
-+static inline bool set_nr_if_polling(struct task_struct *p)
-+{
-+ return false;
-+}
-+#endif
-+#endif
-+
-+static bool __wake_q_add(struct wake_q_head *head, struct task_struct *task)
-+{
-+ struct wake_q_node *node = &task->wake_q;
-+
-+ /*
-+ * Atomically grab the task, if ->wake_q is !nil already it means
-+ * it's already queued (either by us or someone else) and will get the
-+ * wakeup due to that.
-+ *
-+ * In order to ensure that a pending wakeup will observe our pending
-+ * state, even in the failed case, an explicit smp_mb() must be used.
-+ */
-+ smp_mb__before_atomic();
-+ if (unlikely(cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL)))
-+ return false;
-+
-+ /*
-+ * The head is context local, there can be no concurrency.
-+ */
-+ *head->lastp = node;
-+ head->lastp = &node->next;
-+ return true;
-+}
-+
-+/**
-+ * wake_q_add() - queue a wakeup for 'later' waking.
-+ * @head: the wake_q_head to add @task to
-+ * @task: the task to queue for 'later' wakeup
-+ *
-+ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
-+ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
-+ * instantly.
-+ *
-+ * This function must be used as-if it were wake_up_process(); IOW the task
-+ * must be ready to be woken at this location.
-+ */
-+void wake_q_add(struct wake_q_head *head, struct task_struct *task)
-+{
-+ if (__wake_q_add(head, task))
-+ get_task_struct(task);
-+}
-+
-+/**
-+ * wake_q_add_safe() - safely queue a wakeup for 'later' waking.
-+ * @head: the wake_q_head to add @task to
-+ * @task: the task to queue for 'later' wakeup
-+ *
-+ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
-+ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
-+ * instantly.
-+ *
-+ * This function must be used as-if it were wake_up_process(); IOW the task
-+ * must be ready to be woken at this location.
-+ *
-+ * This function is essentially a task-safe equivalent to wake_q_add(). Callers
-+ * that already hold reference to @task can call the 'safe' version and trust
-+ * wake_q to do the right thing depending whether or not the @task is already
-+ * queued for wakeup.
-+ */
-+void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task)
-+{
-+ if (!__wake_q_add(head, task))
-+ put_task_struct(task);
-+}
-+
-+void wake_up_q(struct wake_q_head *head)
-+{
-+ struct wake_q_node *node = head->first;
-+
-+ while (node != WAKE_Q_TAIL) {
-+ struct task_struct *task;
-+
-+ task = container_of(node, struct task_struct, wake_q);
-+ /* task can safely be re-inserted now: */
-+ node = node->next;
-+ task->wake_q.next = NULL;
-+
-+ /*
-+ * wake_up_process() executes a full barrier, which pairs with
-+ * the queueing in wake_q_add() so as not to miss wakeups.
-+ */
-+ wake_up_process(task);
-+ put_task_struct(task);
-+ }
-+}
-+
-+/*
-+ * resched_curr - mark rq's current task 'to be rescheduled now'.
-+ *
-+ * On UP this means the setting of the need_resched flag, on SMP it
-+ * might also involve a cross-CPU call to trigger the scheduler on
-+ * the target CPU.
-+ */
-+static inline void resched_curr(struct rq *rq)
-+{
-+ struct task_struct *curr = rq->curr;
-+ int cpu;
-+
-+ lockdep_assert_held(&rq->lock);
-+
-+ if (test_tsk_need_resched(curr))
-+ return;
-+
-+ cpu = cpu_of(rq);
-+ if (cpu == smp_processor_id()) {
-+ set_tsk_need_resched(curr);
-+ set_preempt_need_resched();
-+ return;
-+ }
-+
-+ if (set_nr_and_not_polling(curr))
-+ smp_send_reschedule(cpu);
-+ else
-+ trace_sched_wake_idle_without_ipi(cpu);
-+}
-+
-+void resched_cpu(int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ unsigned long flags;
-+
-+ raw_spin_lock_irqsave(&rq->lock, flags);
-+ if (cpu_online(cpu) || cpu == smp_processor_id())
-+ resched_curr(cpu_rq(cpu));
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+}
-+
-+#ifdef CONFIG_SMP
-+#ifdef CONFIG_NO_HZ_COMMON
-+/*
-+ * This routine will record that the CPU is going idle with tick stopped.
-+ * This info will be used in performing idle load balancing in the future.
-+ */
-+void nohz_balance_enter_idle(int cpu) {}
-+
-+/*
-+ * In the semi idle case, use the nearest busy CPU for migrating timers
-+ * from an idle CPU. This is good for power-savings.
-+ *
-+ * We don't do similar optimization for completely idle system, as
-+ * selecting an idle CPU will add more delays to the timers than intended
-+ * (as that CPU's timer base may not be uptodate wrt jiffies etc).
-+ */
-+int get_nohz_timer_target(void)
-+{
-+ int i, cpu = smp_processor_id(), default_cpu = -1;
-+ struct cpumask *mask;
-+ const struct cpumask *hk_mask;
-+
-+ if (housekeeping_cpu(cpu, HK_TYPE_TIMER)) {
-+ if (!idle_cpu(cpu))
-+ return cpu;
-+ default_cpu = cpu;
-+ }
-+
-+ hk_mask = housekeeping_cpumask(HK_TYPE_TIMER);
-+
-+ for (mask = per_cpu(sched_cpu_topo_masks, cpu) + 1;
-+ mask < per_cpu(sched_cpu_topo_end_mask, cpu); mask++)
-+ for_each_cpu_and(i, mask, hk_mask)
-+ if (!idle_cpu(i))
-+ return i;
-+
-+ if (default_cpu == -1)
-+ default_cpu = housekeeping_any_cpu(HK_TYPE_TIMER);
-+ cpu = default_cpu;
-+
-+ return cpu;
-+}
-+
-+/*
-+ * When add_timer_on() enqueues a timer into the timer wheel of an
-+ * idle CPU then this timer might expire before the next timer event
-+ * which is scheduled to wake up that CPU. In case of a completely
-+ * idle system the next event might even be infinite time into the
-+ * future. wake_up_idle_cpu() ensures that the CPU is woken up and
-+ * leaves the inner idle loop so the newly added timer is taken into
-+ * account when the CPU goes back to idle and evaluates the timer
-+ * wheel for the next timer event.
-+ */
-+static inline void wake_up_idle_cpu(int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+
-+ if (cpu == smp_processor_id())
-+ return;
-+
-+ /*
-+ * Set TIF_NEED_RESCHED and send an IPI if in the non-polling
-+ * part of the idle loop. This forces an exit from the idle loop
-+ * and a round trip to schedule(). Now this could be optimized
-+ * because a simple new idle loop iteration is enough to
-+ * re-evaluate the next tick. Provided some re-ordering of tick
-+ * nohz functions that would need to follow TIF_NR_POLLING
-+ * clearing:
-+ *
-+ * - On most archs, a simple fetch_or on ti::flags with a
-+ * "0" value would be enough to know if an IPI needs to be sent.
-+ *
-+ * - x86 needs to perform a last need_resched() check between
-+ * monitor and mwait which doesn't take timers into account.
-+ * There a dedicated TIF_TIMER flag would be required to
-+ * fetch_or here and be checked along with TIF_NEED_RESCHED
-+ * before mwait().
-+ *
-+ * However, remote timer enqueue is not such a frequent event
-+ * and testing of the above solutions didn't appear to report
-+ * much benefits.
-+ */
-+ if (set_nr_and_not_polling(rq->idle))
-+ smp_send_reschedule(cpu);
-+ else
-+ trace_sched_wake_idle_without_ipi(cpu);
-+}
-+
-+static inline bool wake_up_full_nohz_cpu(int cpu)
-+{
-+ /*
-+ * We just need the target to call irq_exit() and re-evaluate
-+ * the next tick. The nohz full kick at least implies that.
-+ * If needed we can still optimize that later with an
-+ * empty IRQ.
-+ */
-+ if (cpu_is_offline(cpu))
-+ return true; /* Don't try to wake offline CPUs. */
-+ if (tick_nohz_full_cpu(cpu)) {
-+ if (cpu != smp_processor_id() ||
-+ tick_nohz_tick_stopped())
-+ tick_nohz_full_kick_cpu(cpu);
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+void wake_up_nohz_cpu(int cpu)
-+{
-+ if (!wake_up_full_nohz_cpu(cpu))
-+ wake_up_idle_cpu(cpu);
-+}
-+
-+static void nohz_csd_func(void *info)
-+{
-+ struct rq *rq = info;
-+ int cpu = cpu_of(rq);
-+ unsigned int flags;
-+
-+ /*
-+ * Release the rq::nohz_csd.
-+ */
-+ flags = atomic_fetch_andnot(NOHZ_KICK_MASK, nohz_flags(cpu));
-+ WARN_ON(!(flags & NOHZ_KICK_MASK));
-+
-+ rq->idle_balance = idle_cpu(cpu);
-+ if (rq->idle_balance && !need_resched()) {
-+ rq->nohz_idle_balance = flags;
-+ raise_softirq_irqoff(SCHED_SOFTIRQ);
-+ }
-+}
-+
-+#endif /* CONFIG_NO_HZ_COMMON */
-+#endif /* CONFIG_SMP */
-+
-+static inline void wakeup_preempt(struct rq *rq)
-+{
-+ if (sched_rq_first_task(rq) != rq->curr)
-+ resched_curr(rq);
-+}
-+
-+static __always_inline
-+int __task_state_match(struct task_struct *p, unsigned int state)
-+{
-+ if (READ_ONCE(p->__state) & state)
-+ return 1;
-+
-+ if (READ_ONCE(p->saved_state) & state)
-+ return -1;
-+
-+ return 0;
-+}
-+
-+static __always_inline
-+int task_state_match(struct task_struct *p, unsigned int state)
-+{
-+ /*
-+ * Serialize against current_save_and_set_rtlock_wait_state(),
-+ * current_restore_rtlock_saved_state(), and __refrigerator().
-+ */
-+ guard(raw_spinlock_irq)(&p->pi_lock);
-+
-+ return __task_state_match(p, state);
-+}
-+
-+/*
-+ * wait_task_inactive - wait for a thread to unschedule.
-+ *
-+ * Wait for the thread to block in any of the states set in @match_state.
-+ * If it changes, i.e. @p might have woken up, then return zero. When we
-+ * succeed in waiting for @p to be off its CPU, we return a positive number
-+ * (its total switch count). If a second call a short while later returns the
-+ * same number, the caller can be sure that @p has remained unscheduled the
-+ * whole time.
-+ *
-+ * The caller must ensure that the task *will* unschedule sometime soon,
-+ * else this function might spin for a *long* time. This function can't
-+ * be called with interrupts off, or it may introduce deadlock with
-+ * smp_call_function() if an IPI is sent by the same process we are
-+ * waiting to become inactive.
-+ */
-+unsigned long wait_task_inactive(struct task_struct *p, unsigned int match_state)
-+{
-+ unsigned long flags;
-+ int running, queued, match;
-+ unsigned long ncsw;
-+ struct rq *rq;
-+ raw_spinlock_t *lock;
-+
-+ for (;;) {
-+ rq = task_rq(p);
-+
-+ /*
-+ * If the task is actively running on another CPU
-+ * still, just relax and busy-wait without holding
-+ * any locks.
-+ *
-+ * NOTE! Since we don't hold any locks, it's not
-+ * even sure that "rq" stays as the right runqueue!
-+ * But we don't care, since this will return false
-+ * if the runqueue has changed and p is actually now
-+ * running somewhere else!
-+ */
-+ while (task_on_cpu(p)) {
-+ if (!task_state_match(p, match_state))
-+ return 0;
-+ cpu_relax();
-+ }
-+
-+ /*
-+ * Ok, time to look more closely! We need the rq
-+ * lock now, to be *sure*. If we're wrong, we'll
-+ * just go back and repeat.
-+ */
-+ task_access_lock_irqsave(p, &lock, &flags);
-+ trace_sched_wait_task(p);
-+ running = task_on_cpu(p);
-+ queued = p->on_rq;
-+ ncsw = 0;
-+ if ((match = __task_state_match(p, match_state))) {
-+ /*
-+ * When matching on p->saved_state, consider this task
-+ * still queued so it will wait.
-+ */
-+ if (match < 0)
-+ queued = 1;
-+ ncsw = p->nvcsw | LONG_MIN; /* sets MSB */
-+ }
-+ task_access_unlock_irqrestore(p, lock, &flags);
-+
-+ /*
-+ * If it changed from the expected state, bail out now.
-+ */
-+ if (unlikely(!ncsw))
-+ break;
-+
-+ /*
-+ * Was it really running after all now that we
-+ * checked with the proper locks actually held?
-+ *
-+ * Oops. Go back and try again..
-+ */
-+ if (unlikely(running)) {
-+ cpu_relax();
-+ continue;
-+ }
-+
-+ /*
-+ * It's not enough that it's not actively running,
-+ * it must be off the runqueue _entirely_, and not
-+ * preempted!
-+ *
-+ * So if it was still runnable (but just not actively
-+ * running right now), it's preempted, and we should
-+ * yield - it could be a while.
-+ */
-+ if (unlikely(queued)) {
-+ ktime_t to = NSEC_PER_SEC / HZ;
-+
-+ set_current_state(TASK_UNINTERRUPTIBLE);
-+ schedule_hrtimeout(&to, HRTIMER_MODE_REL_HARD);
-+ continue;
-+ }
-+
-+ /*
-+ * Ahh, all good. It wasn't running, and it wasn't
-+ * runnable, which means that it will never become
-+ * running in the future either. We're all done!
-+ */
-+ break;
-+ }
-+
-+ return ncsw;
-+}
-+
-+#ifdef CONFIG_SCHED_HRTICK
-+/*
-+ * Use HR-timers to deliver accurate preemption points.
-+ */
-+
-+static void hrtick_clear(struct rq *rq)
-+{
-+ if (hrtimer_active(&rq->hrtick_timer))
-+ hrtimer_cancel(&rq->hrtick_timer);
-+}
-+
-+/*
-+ * High-resolution timer tick.
-+ * Runs from hardirq context with interrupts disabled.
-+ */
-+static enum hrtimer_restart hrtick(struct hrtimer *timer)
-+{
-+ struct rq *rq = container_of(timer, struct rq, hrtick_timer);
-+
-+ WARN_ON_ONCE(cpu_of(rq) != smp_processor_id());
-+
-+ raw_spin_lock(&rq->lock);
-+ resched_curr(rq);
-+ raw_spin_unlock(&rq->lock);
-+
-+ return HRTIMER_NORESTART;
-+}
-+
-+/*
-+ * Use hrtick when:
-+ * - enabled by features
-+ * - hrtimer is actually high res
-+ */
-+static inline int hrtick_enabled(struct rq *rq)
-+{
-+ /**
-+ * Alt schedule FW doesn't support sched_feat yet
-+ if (!sched_feat(HRTICK))
-+ return 0;
-+ */
-+ if (!cpu_active(cpu_of(rq)))
-+ return 0;
-+ return hrtimer_is_hres_active(&rq->hrtick_timer);
-+}
-+
-+#ifdef CONFIG_SMP
-+
-+static void __hrtick_restart(struct rq *rq)
-+{
-+ struct hrtimer *timer = &rq->hrtick_timer;
-+ ktime_t time = rq->hrtick_time;
-+
-+ hrtimer_start(timer, time, HRTIMER_MODE_ABS_PINNED_HARD);
-+}
-+
-+/*
-+ * called from hardirq (IPI) context
-+ */
-+static void __hrtick_start(void *arg)
-+{
-+ struct rq *rq = arg;
-+
-+ raw_spin_lock(&rq->lock);
-+ __hrtick_restart(rq);
-+ raw_spin_unlock(&rq->lock);
-+}
-+
-+/*
-+ * Called to set the hrtick timer state.
-+ *
-+ * called with rq->lock held and irqs disabled
-+ */
-+static inline void hrtick_start(struct rq *rq, u64 delay)
-+{
-+ struct hrtimer *timer = &rq->hrtick_timer;
-+ s64 delta;
-+
-+ /*
-+ * Don't schedule slices shorter than 10000ns, that just
-+ * doesn't make sense and can cause timer DoS.
-+ */
-+ delta = max_t(s64, delay, 10000LL);
-+
-+ rq->hrtick_time = ktime_add_ns(timer->base->get_time(), delta);
-+
-+ if (rq == this_rq())
-+ __hrtick_restart(rq);
-+ else
-+ smp_call_function_single_async(cpu_of(rq), &rq->hrtick_csd);
-+}
-+
-+#else
-+/*
-+ * Called to set the hrtick timer state.
-+ *
-+ * called with rq->lock held and irqs disabled
-+ */
-+static inline void hrtick_start(struct rq *rq, u64 delay)
-+{
-+ /*
-+ * Don't schedule slices shorter than 10000ns, that just
-+ * doesn't make sense. Rely on vruntime for fairness.
-+ */
-+ delay = max_t(u64, delay, 10000LL);
-+ hrtimer_start(&rq->hrtick_timer, ns_to_ktime(delay),
-+ HRTIMER_MODE_REL_PINNED_HARD);
-+}
-+#endif /* CONFIG_SMP */
-+
-+static void hrtick_rq_init(struct rq *rq)
-+{
-+#ifdef CONFIG_SMP
-+ INIT_CSD(&rq->hrtick_csd, __hrtick_start, rq);
-+#endif
-+
-+ hrtimer_init(&rq->hrtick_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
-+ rq->hrtick_timer.function = hrtick;
-+}
-+#else /* CONFIG_SCHED_HRTICK */
-+static inline int hrtick_enabled(struct rq *rq)
-+{
-+ return 0;
-+}
-+
-+static inline void hrtick_clear(struct rq *rq)
-+{
-+}
-+
-+static inline void hrtick_rq_init(struct rq *rq)
-+{
-+}
-+#endif /* CONFIG_SCHED_HRTICK */
-+
-+static inline int __normal_prio(int policy, int rt_prio, int static_prio)
-+{
-+ return rt_policy(policy) ? (MAX_RT_PRIO - 1 - rt_prio) :
-+ static_prio + MAX_PRIORITY_ADJ;
-+}
-+
-+/*
-+ * Calculate the expected normal priority: i.e. priority
-+ * without taking RT-inheritance into account. Might be
-+ * boosted by interactivity modifiers. Changes upon fork,
-+ * setprio syscalls, and whenever the interactivity
-+ * estimator recalculates.
-+ */
-+static inline int normal_prio(struct task_struct *p)
-+{
-+ return __normal_prio(p->policy, p->rt_priority, p->static_prio);
-+}
-+
-+/*
-+ * Calculate the current priority, i.e. the priority
-+ * taken into account by the scheduler. This value might
-+ * be boosted by RT tasks as it will be RT if the task got
-+ * RT-boosted. If not then it returns p->normal_prio.
-+ */
-+static int effective_prio(struct task_struct *p)
-+{
-+ p->normal_prio = normal_prio(p);
-+ /*
-+ * If we are RT tasks or we were boosted to RT priority,
-+ * keep the priority unchanged. Otherwise, update priority
-+ * to the normal priority:
-+ */
-+ if (!rt_prio(p->prio))
-+ return p->normal_prio;
-+ return p->prio;
-+}
-+
-+/*
-+ * activate_task - move a task to the runqueue.
-+ *
-+ * Context: rq->lock
-+ */
-+static void activate_task(struct task_struct *p, struct rq *rq)
-+{
-+ enqueue_task(p, rq, ENQUEUE_WAKEUP);
-+
-+ WRITE_ONCE(p->on_rq, TASK_ON_RQ_QUEUED);
-+ ASSERT_EXCLUSIVE_WRITER(p->on_rq);
-+
-+ /*
-+ * If in_iowait is set, the code below may not trigger any cpufreq
-+ * utilization updates, so do it here explicitly with the IOWAIT flag
-+ * passed.
-+ */
-+ cpufreq_update_util(rq, SCHED_CPUFREQ_IOWAIT * p->in_iowait);
-+}
-+
-+/*
-+ * deactivate_task - remove a task from the runqueue.
-+ *
-+ * Context: rq->lock
-+ */
-+static inline void deactivate_task(struct task_struct *p, struct rq *rq)
-+{
-+ WRITE_ONCE(p->on_rq, 0);
-+ ASSERT_EXCLUSIVE_WRITER(p->on_rq);
-+
-+ dequeue_task(p, rq, DEQUEUE_SLEEP);
-+
-+ cpufreq_update_util(rq, 0);
-+}
-+
-+static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
-+{
-+#ifdef CONFIG_SMP
-+ /*
-+ * After ->cpu is set up to a new value, task_access_lock(p, ...) can be
-+ * successfully executed on another CPU. We must ensure that updates of
-+ * per-task data have been completed by this moment.
-+ */
-+ smp_wmb();
-+
-+ WRITE_ONCE(task_thread_info(p)->cpu, cpu);
-+#endif
-+}
-+
-+static inline bool is_migration_disabled(struct task_struct *p)
-+{
-+#ifdef CONFIG_SMP
-+ return p->migration_disabled;
-+#else
-+ return false;
-+#endif
-+}
-+
-+#define SCA_CHECK 0x01
-+#define SCA_USER 0x08
-+
-+#ifdef CONFIG_SMP
-+
-+void set_task_cpu(struct task_struct *p, unsigned int new_cpu)
-+{
-+#ifdef CONFIG_SCHED_DEBUG
-+ unsigned int state = READ_ONCE(p->__state);
-+
-+ /*
-+ * We should never call set_task_cpu() on a blocked task,
-+ * ttwu() will sort out the placement.
-+ */
-+ WARN_ON_ONCE(state != TASK_RUNNING && state != TASK_WAKING && !p->on_rq);
-+
-+#ifdef CONFIG_LOCKDEP
-+ /*
-+ * The caller should hold either p->pi_lock or rq->lock, when changing
-+ * a task's CPU. ->pi_lock for waking tasks, rq->lock for runnable tasks.
-+ *
-+ * sched_move_task() holds both and thus holding either pins the cgroup,
-+ * see task_group().
-+ */
-+ WARN_ON_ONCE(debug_locks && !(lockdep_is_held(&p->pi_lock) ||
-+ lockdep_is_held(&task_rq(p)->lock)));
-+#endif
-+ /*
-+ * Clearly, migrating tasks to offline CPUs is a fairly daft thing.
-+ */
-+ WARN_ON_ONCE(!cpu_online(new_cpu));
-+
-+ WARN_ON_ONCE(is_migration_disabled(p));
-+#endif
-+ trace_sched_migrate_task(p, new_cpu);
-+
-+ if (task_cpu(p) != new_cpu)
-+ {
-+ rseq_migrate(p);
-+ perf_event_task_migrate(p);
-+ }
-+
-+ __set_task_cpu(p, new_cpu);
-+}
-+
-+#define MDF_FORCE_ENABLED 0x80
-+
-+static void
-+__do_set_cpus_ptr(struct task_struct *p, const struct cpumask *new_mask)
-+{
-+ /*
-+ * This here violates the locking rules for affinity, since we're only
-+ * supposed to change these variables while holding both rq->lock and
-+ * p->pi_lock.
-+ *
-+ * HOWEVER, it magically works, because ttwu() is the only code that
-+ * accesses these variables under p->pi_lock and only does so after
-+ * smp_cond_load_acquire(&p->on_cpu, !VAL), and we're in __schedule()
-+ * before finish_task().
-+ *
-+ * XXX do further audits, this smells like something putrid.
-+ */
-+ SCHED_WARN_ON(!p->on_cpu);
-+ p->cpus_ptr = new_mask;
-+}
-+
-+void migrate_disable(void)
-+{
-+ struct task_struct *p = current;
-+ int cpu;
-+
-+ if (p->migration_disabled) {
-+ p->migration_disabled++;
-+ return;
-+ }
-+
-+ guard(preempt)();
-+ cpu = smp_processor_id();
-+ if (cpumask_test_cpu(cpu, &p->cpus_mask)) {
-+ cpu_rq(cpu)->nr_pinned++;
-+ p->migration_disabled = 1;
-+ p->migration_flags &= ~MDF_FORCE_ENABLED;
-+
-+ /*
-+ * Violates locking rules! see comment in __do_set_cpus_ptr().
-+ */
-+ if (p->cpus_ptr == &p->cpus_mask)
-+ __do_set_cpus_ptr(p, cpumask_of(cpu));
-+ }
-+}
-+EXPORT_SYMBOL_GPL(migrate_disable);
-+
-+void migrate_enable(void)
-+{
-+ struct task_struct *p = current;
-+
-+ if (0 == p->migration_disabled)
-+ return;
-+
-+ if (p->migration_disabled > 1) {
-+ p->migration_disabled--;
-+ return;
-+ }
-+
-+ if (WARN_ON_ONCE(!p->migration_disabled))
-+ return;
-+
-+ /*
-+ * Ensure stop_task runs either before or after this, and that
-+ * __set_cpus_allowed_ptr(SCA_MIGRATE_ENABLE) doesn't schedule().
-+ */
-+ guard(preempt)();
-+ /*
-+ * Assumption: current should be running on allowed cpu
-+ */
-+ WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &p->cpus_mask));
-+ if (p->cpus_ptr != &p->cpus_mask)
-+ __do_set_cpus_ptr(p, &p->cpus_mask);
-+ /*
-+ * Mustn't clear migration_disabled() until cpus_ptr points back at the
-+ * regular cpus_mask, otherwise things that race (eg.
-+ * select_fallback_rq) get confused.
-+ */
-+ barrier();
-+ p->migration_disabled = 0;
-+ this_rq()->nr_pinned--;
-+}
-+EXPORT_SYMBOL_GPL(migrate_enable);
-+
-+static inline bool rq_has_pinned_tasks(struct rq *rq)
-+{
-+ return rq->nr_pinned;
-+}
-+
-+/*
-+ * Per-CPU kthreads are allowed to run on !active && online CPUs, see
-+ * __set_cpus_allowed_ptr() and select_fallback_rq().
-+ */
-+static inline bool is_cpu_allowed(struct task_struct *p, int cpu)
-+{
-+ /* When not in the task's cpumask, no point in looking further. */
-+ if (!cpumask_test_cpu(cpu, p->cpus_ptr))
-+ return false;
-+
-+ /* migrate_disabled() must be allowed to finish. */
-+ if (is_migration_disabled(p))
-+ return cpu_online(cpu);
-+
-+ /* Non kernel threads are not allowed during either online or offline. */
-+ if (!(p->flags & PF_KTHREAD))
-+ return cpu_active(cpu) && task_cpu_possible(cpu, p);
-+
-+ /* KTHREAD_IS_PER_CPU is always allowed. */
-+ if (kthread_is_per_cpu(p))
-+ return cpu_online(cpu);
-+
-+ /* Regular kernel threads don't get to stay during offline. */
-+ if (cpu_dying(cpu))
-+ return false;
-+
-+ /* But are allowed during online. */
-+ return cpu_online(cpu);
-+}
-+
-+/*
-+ * This is how migration works:
-+ *
-+ * 1) we invoke migration_cpu_stop() on the target CPU using
-+ * stop_one_cpu().
-+ * 2) stopper starts to run (implicitly forcing the migrated thread
-+ * off the CPU)
-+ * 3) it checks whether the migrated task is still in the wrong runqueue.
-+ * 4) if it's in the wrong runqueue then the migration thread removes
-+ * it and puts it into the right queue.
-+ * 5) stopper completes and stop_one_cpu() returns and the migration
-+ * is done.
-+ */
-+
-+/*
-+ * move_queued_task - move a queued task to new rq.
-+ *
-+ * Returns (locked) new rq. Old rq's lock is released.
-+ */
-+static struct rq *move_queued_task(struct rq *rq, struct task_struct *p, int
-+ new_cpu)
-+{
-+ int src_cpu;
-+
-+ lockdep_assert_held(&rq->lock);
-+
-+ src_cpu = cpu_of(rq);
-+ WRITE_ONCE(p->on_rq, TASK_ON_RQ_MIGRATING);
-+ dequeue_task(p, rq, 0);
-+ set_task_cpu(p, new_cpu);
-+ raw_spin_unlock(&rq->lock);
-+
-+ rq = cpu_rq(new_cpu);
-+
-+ raw_spin_lock(&rq->lock);
-+ WARN_ON_ONCE(task_cpu(p) != new_cpu);
-+
-+ sched_mm_cid_migrate_to(rq, p, src_cpu);
-+
-+ sched_task_sanity_check(p, rq);
-+ enqueue_task(p, rq, 0);
-+ WRITE_ONCE(p->on_rq, TASK_ON_RQ_QUEUED);
-+ wakeup_preempt(rq);
-+
-+ return rq;
-+}
-+
-+struct migration_arg {
-+ struct task_struct *task;
-+ int dest_cpu;
-+};
-+
-+/*
-+ * Move (not current) task off this CPU, onto the destination CPU. We're doing
-+ * this because either it can't run here any more (set_cpus_allowed()
-+ * away from this CPU, or CPU going down), or because we're
-+ * attempting to rebalance this task on exec (sched_exec).
-+ *
-+ * So we race with normal scheduler movements, but that's OK, as long
-+ * as the task is no longer on this CPU.
-+ */
-+static struct rq *__migrate_task(struct rq *rq, struct task_struct *p, int
-+ dest_cpu)
-+{
-+ /* Affinity changed (again). */
-+ if (!is_cpu_allowed(p, dest_cpu))
-+ return rq;
-+
-+ return move_queued_task(rq, p, dest_cpu);
-+}
-+
-+/*
-+ * migration_cpu_stop - this will be executed by a highprio stopper thread
-+ * and performs thread migration by bumping thread off CPU then
-+ * 'pushing' onto another runqueue.
-+ */
-+static int migration_cpu_stop(void *data)
-+{
-+ struct migration_arg *arg = data;
-+ struct task_struct *p = arg->task;
-+ struct rq *rq = this_rq();
-+ unsigned long flags;
-+
-+ /*
-+ * The original target CPU might have gone down and we might
-+ * be on another CPU but it doesn't matter.
-+ */
-+ local_irq_save(flags);
-+ /*
-+ * We need to explicitly wake pending tasks before running
-+ * __migrate_task() such that we will not miss enforcing cpus_ptr
-+ * during wakeups, see set_cpus_allowed_ptr()'s TASK_WAKING test.
-+ */
-+ flush_smp_call_function_queue();
-+
-+ raw_spin_lock(&p->pi_lock);
-+ raw_spin_lock(&rq->lock);
-+ /*
-+ * If task_rq(p) != rq, it cannot be migrated here, because we're
-+ * holding rq->lock, if p->on_rq == 0 it cannot get enqueued because
-+ * we're holding p->pi_lock.
-+ */
-+ if (task_rq(p) == rq && task_on_rq_queued(p)) {
-+ update_rq_clock(rq);
-+ rq = __migrate_task(rq, p, arg->dest_cpu);
-+ }
-+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+
-+ return 0;
-+}
-+
-+static inline void
-+set_cpus_allowed_common(struct task_struct *p, struct affinity_context *ctx)
-+{
-+ cpumask_copy(&p->cpus_mask, ctx->new_mask);
-+ p->nr_cpus_allowed = cpumask_weight(ctx->new_mask);
-+
-+ /*
-+ * Swap in a new user_cpus_ptr if SCA_USER flag set
-+ */
-+ if (ctx->flags & SCA_USER)
-+ swap(p->user_cpus_ptr, ctx->user_mask);
-+}
-+
-+static void
-+__do_set_cpus_allowed(struct task_struct *p, struct affinity_context *ctx)
-+{
-+ lockdep_assert_held(&p->pi_lock);
-+ set_cpus_allowed_common(p, ctx);
-+}
-+
-+/*
-+ * Used for kthread_bind() and select_fallback_rq(), in both cases the user
-+ * affinity (if any) should be destroyed too.
-+ */
-+void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
-+{
-+ struct affinity_context ac = {
-+ .new_mask = new_mask,
-+ .user_mask = NULL,
-+ .flags = SCA_USER, /* clear the user requested mask */
-+ };
-+ union cpumask_rcuhead {
-+ cpumask_t cpumask;
-+ struct rcu_head rcu;
-+ };
-+
-+ __do_set_cpus_allowed(p, &ac);
-+
-+ /*
-+ * Because this is called with p->pi_lock held, it is not possible
-+ * to use kfree() here (when PREEMPT_RT=y), therefore punt to using
-+ * kfree_rcu().
-+ */
-+ kfree_rcu((union cpumask_rcuhead *)ac.user_mask, rcu);
-+}
-+
-+static cpumask_t *alloc_user_cpus_ptr(int node)
-+{
-+ /*
-+ * See do_set_cpus_allowed() above for the rcu_head usage.
-+ */
-+ int size = max_t(int, cpumask_size(), sizeof(struct rcu_head));
-+
-+ return kmalloc_node(size, GFP_KERNEL, node);
-+}
-+
-+int dup_user_cpus_ptr(struct task_struct *dst, struct task_struct *src,
-+ int node)
-+{
-+ cpumask_t *user_mask;
-+ unsigned long flags;
-+
-+ /*
-+ * Always clear dst->user_cpus_ptr first as their user_cpus_ptr's
-+ * may differ by now due to racing.
-+ */
-+ dst->user_cpus_ptr = NULL;
-+
-+ /*
-+ * This check is racy and losing the race is a valid situation.
-+ * It is not worth the extra overhead of taking the pi_lock on
-+ * every fork/clone.
-+ */
-+ if (data_race(!src->user_cpus_ptr))
-+ return 0;
-+
-+ user_mask = alloc_user_cpus_ptr(node);
-+ if (!user_mask)
-+ return -ENOMEM;
-+
-+ /*
-+ * Use pi_lock to protect content of user_cpus_ptr
-+ *
-+ * Though unlikely, user_cpus_ptr can be reset to NULL by a concurrent
-+ * do_set_cpus_allowed().
-+ */
-+ raw_spin_lock_irqsave(&src->pi_lock, flags);
-+ if (src->user_cpus_ptr) {
-+ swap(dst->user_cpus_ptr, user_mask);
-+ cpumask_copy(dst->user_cpus_ptr, src->user_cpus_ptr);
-+ }
-+ raw_spin_unlock_irqrestore(&src->pi_lock, flags);
-+
-+ if (unlikely(user_mask))
-+ kfree(user_mask);
-+
-+ return 0;
-+}
-+
-+static inline struct cpumask *clear_user_cpus_ptr(struct task_struct *p)
-+{
-+ struct cpumask *user_mask = NULL;
-+
-+ swap(p->user_cpus_ptr, user_mask);
-+
-+ return user_mask;
-+}
-+
-+void release_user_cpus_ptr(struct task_struct *p)
-+{
-+ kfree(clear_user_cpus_ptr(p));
-+}
-+
-+#endif
-+
-+/**
-+ * task_curr - is this task currently executing on a CPU?
-+ * @p: the task in question.
-+ *
-+ * Return: 1 if the task is currently executing. 0 otherwise.
-+ */
-+inline int task_curr(const struct task_struct *p)
-+{
-+ return cpu_curr(task_cpu(p)) == p;
-+}
-+
-+#ifdef CONFIG_SMP
-+/***
-+ * kick_process - kick a running thread to enter/exit the kernel
-+ * @p: the to-be-kicked thread
-+ *
-+ * Cause a process which is running on another CPU to enter
-+ * kernel-mode, without any delay. (to get signals handled.)
-+ *
-+ * NOTE: this function doesn't have to take the runqueue lock,
-+ * because all it wants to ensure is that the remote task enters
-+ * the kernel. If the IPI races and the task has been migrated
-+ * to another CPU then no harm is done and the purpose has been
-+ * achieved as well.
-+ */
-+void kick_process(struct task_struct *p)
-+{
-+ guard(preempt)();
-+ int cpu = task_cpu(p);
-+
-+ if ((cpu != smp_processor_id()) && task_curr(p))
-+ smp_send_reschedule(cpu);
-+}
-+EXPORT_SYMBOL_GPL(kick_process);
-+
-+/*
-+ * ->cpus_ptr is protected by both rq->lock and p->pi_lock
-+ *
-+ * A few notes on cpu_active vs cpu_online:
-+ *
-+ * - cpu_active must be a subset of cpu_online
-+ *
-+ * - on CPU-up we allow per-CPU kthreads on the online && !active CPU,
-+ * see __set_cpus_allowed_ptr(). At this point the newly online
-+ * CPU isn't yet part of the sched domains, and balancing will not
-+ * see it.
-+ *
-+ * - on cpu-down we clear cpu_active() to mask the sched domains and
-+ * avoid the load balancer to place new tasks on the to be removed
-+ * CPU. Existing tasks will remain running there and will be taken
-+ * off.
-+ *
-+ * This means that fallback selection must not select !active CPUs.
-+ * And can assume that any active CPU must be online. Conversely
-+ * select_task_rq() below may allow selection of !active CPUs in order
-+ * to satisfy the above rules.
-+ */
-+static int select_fallback_rq(int cpu, struct task_struct *p)
-+{
-+ int nid = cpu_to_node(cpu);
-+ const struct cpumask *nodemask = NULL;
-+ enum { cpuset, possible, fail } state = cpuset;
-+ int dest_cpu;
-+
-+ /*
-+ * If the node that the CPU is on has been offlined, cpu_to_node()
-+ * will return -1. There is no CPU on the node, and we should
-+ * select the CPU on the other node.
-+ */
-+ if (nid != -1) {
-+ nodemask = cpumask_of_node(nid);
-+
-+ /* Look for allowed, online CPU in same node. */
-+ for_each_cpu(dest_cpu, nodemask) {
-+ if (is_cpu_allowed(p, dest_cpu))
-+ return dest_cpu;
-+ }
-+ }
-+
-+ for (;;) {
-+ /* Any allowed, online CPU? */
-+ for_each_cpu(dest_cpu, p->cpus_ptr) {
-+ if (!is_cpu_allowed(p, dest_cpu))
-+ continue;
-+ goto out;
-+ }
-+
-+ /* No more Mr. Nice Guy. */
-+ switch (state) {
-+ case cpuset:
-+ if (cpuset_cpus_allowed_fallback(p)) {
-+ state = possible;
-+ break;
-+ }
-+ fallthrough;
-+ case possible:
-+ /*
-+ * XXX When called from select_task_rq() we only
-+ * hold p->pi_lock and again violate locking order.
-+ *
-+ * More yuck to audit.
-+ */
-+ do_set_cpus_allowed(p, task_cpu_possible_mask(p));
-+ state = fail;
-+ break;
-+
-+ case fail:
-+ BUG();
-+ break;
-+ }
-+ }
-+
-+out:
-+ if (state != cpuset) {
-+ /*
-+ * Don't tell them about moving exiting tasks or
-+ * kernel threads (both mm NULL), since they never
-+ * leave kernel.
-+ */
-+ if (p->mm && printk_ratelimit()) {
-+ printk_deferred("process %d (%s) no longer affine to cpu%d\n",
-+ task_pid_nr(p), p->comm, cpu);
-+ }
-+ }
-+
-+ return dest_cpu;
-+}
-+
-+static inline void
-+sched_preempt_mask_flush(cpumask_t *mask, int prio)
-+{
-+ int cpu;
-+
-+ cpumask_copy(mask, sched_idle_mask);
-+
-+ for_each_clear_bit(cpu, cpumask_bits(mask), nr_cpumask_bits) {
-+ if (prio < cpu_rq(cpu)->prio)
-+ cpumask_set_cpu(cpu, mask);
-+ }
-+}
-+
-+static inline int
-+preempt_mask_check(struct task_struct *p, cpumask_t *allow_mask, cpumask_t *preempt_mask)
-+{
-+ int task_prio = task_sched_prio(p);
-+ cpumask_t *mask = sched_preempt_mask + SCHED_QUEUE_BITS - 1 - task_prio;
-+ int pr = atomic_read(&sched_prio_record);
-+
-+ if (pr != task_prio) {
-+ sched_preempt_mask_flush(mask, task_prio);
-+ atomic_set(&sched_prio_record, task_prio);
-+ }
-+
-+ return cpumask_and(preempt_mask, allow_mask, mask);
-+}
-+
-+static inline int select_task_rq(struct task_struct *p)
-+{
-+ cpumask_t allow_mask, mask;
-+
-+ if (unlikely(!cpumask_and(&allow_mask, p->cpus_ptr, cpu_active_mask)))
-+ return select_fallback_rq(task_cpu(p), p);
-+
-+ if (
-+#ifdef CONFIG_SCHED_SMT
-+ cpumask_and(&mask, &allow_mask, &sched_sg_idle_mask) ||
-+#endif
-+ cpumask_and(&mask, &allow_mask, sched_idle_mask) ||
-+ preempt_mask_check(p, &allow_mask, &mask))
-+ return best_mask_cpu(task_cpu(p), &mask);
-+
-+ return best_mask_cpu(task_cpu(p), &allow_mask);
-+}
-+
-+void sched_set_stop_task(int cpu, struct task_struct *stop)
-+{
-+ static struct lock_class_key stop_pi_lock;
-+ struct sched_param stop_param = { .sched_priority = STOP_PRIO };
-+ struct sched_param start_param = { .sched_priority = 0 };
-+ struct task_struct *old_stop = cpu_rq(cpu)->stop;
-+
-+ if (stop) {
-+ /*
-+ * Make it appear like a SCHED_FIFO task, its something
-+ * userspace knows about and won't get confused about.
-+ *
-+ * Also, it will make PI more or less work without too
-+ * much confusion -- but then, stop work should not
-+ * rely on PI working anyway.
-+ */
-+ sched_setscheduler_nocheck(stop, SCHED_FIFO, &stop_param);
-+
-+ /*
-+ * The PI code calls rt_mutex_setprio() with ->pi_lock held to
-+ * adjust the effective priority of a task. As a result,
-+ * rt_mutex_setprio() can trigger (RT) balancing operations,
-+ * which can then trigger wakeups of the stop thread to push
-+ * around the current task.
-+ *
-+ * The stop task itself will never be part of the PI-chain, it
-+ * never blocks, therefore that ->pi_lock recursion is safe.
-+ * Tell lockdep about this by placing the stop->pi_lock in its
-+ * own class.
-+ */
-+ lockdep_set_class(&stop->pi_lock, &stop_pi_lock);
-+ }
-+
-+ cpu_rq(cpu)->stop = stop;
-+
-+ if (old_stop) {
-+ /*
-+ * Reset it back to a normal scheduling policy so that
-+ * it can die in pieces.
-+ */
-+ sched_setscheduler_nocheck(old_stop, SCHED_NORMAL, &start_param);
-+ }
-+}
-+
-+static int affine_move_task(struct rq *rq, struct task_struct *p, int dest_cpu,
-+ raw_spinlock_t *lock, unsigned long irq_flags)
-+ __releases(rq->lock)
-+ __releases(p->pi_lock)
-+{
-+ /* Can the task run on the task's current CPU? If so, we're done */
-+ if (!cpumask_test_cpu(task_cpu(p), &p->cpus_mask)) {
-+ if (p->migration_disabled) {
-+ if (likely(p->cpus_ptr != &p->cpus_mask))
-+ __do_set_cpus_ptr(p, &p->cpus_mask);
-+ p->migration_disabled = 0;
-+ p->migration_flags |= MDF_FORCE_ENABLED;
-+ /* When p is migrate_disabled, rq->lock should be held */
-+ rq->nr_pinned--;
-+ }
-+
-+ if (task_on_cpu(p) || READ_ONCE(p->__state) == TASK_WAKING) {
-+ struct migration_arg arg = { p, dest_cpu };
-+
-+ /* Need help from migration thread: drop lock and wait. */
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
-+ stop_one_cpu(cpu_of(rq), migration_cpu_stop, &arg);
-+ return 0;
-+ }
-+ if (task_on_rq_queued(p)) {
-+ /*
-+ * OK, since we're going to drop the lock immediately
-+ * afterwards anyway.
-+ */
-+ update_rq_clock(rq);
-+ rq = move_queued_task(rq, p, dest_cpu);
-+ lock = &rq->lock;
-+ }
-+ }
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
-+ return 0;
-+}
-+
-+static int __set_cpus_allowed_ptr_locked(struct task_struct *p,
-+ struct affinity_context *ctx,
-+ struct rq *rq,
-+ raw_spinlock_t *lock,
-+ unsigned long irq_flags)
-+{
-+ const struct cpumask *cpu_allowed_mask = task_cpu_possible_mask(p);
-+ const struct cpumask *cpu_valid_mask = cpu_active_mask;
-+ bool kthread = p->flags & PF_KTHREAD;
-+ int dest_cpu;
-+ int ret = 0;
-+
-+ if (kthread || is_migration_disabled(p)) {
-+ /*
-+ * Kernel threads are allowed on online && !active CPUs,
-+ * however, during cpu-hot-unplug, even these might get pushed
-+ * away if not KTHREAD_IS_PER_CPU.
-+ *
-+ * Specifically, migration_disabled() tasks must not fail the
-+ * cpumask_any_and_distribute() pick below, esp. so on
-+ * SCA_MIGRATE_ENABLE, otherwise we'll not call
-+ * set_cpus_allowed_common() and actually reset p->cpus_ptr.
-+ */
-+ cpu_valid_mask = cpu_online_mask;
-+ }
-+
-+ if (!kthread && !cpumask_subset(ctx->new_mask, cpu_allowed_mask)) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ /*
-+ * Must re-check here, to close a race against __kthread_bind(),
-+ * sched_setaffinity() is not guaranteed to observe the flag.
-+ */
-+ if ((ctx->flags & SCA_CHECK) && (p->flags & PF_NO_SETAFFINITY)) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ if (cpumask_equal(&p->cpus_mask, ctx->new_mask))
-+ goto out;
-+
-+ dest_cpu = cpumask_any_and(cpu_valid_mask, ctx->new_mask);
-+ if (dest_cpu >= nr_cpu_ids) {
-+ ret = -EINVAL;
-+ goto out;
-+ }
-+
-+ __do_set_cpus_allowed(p, ctx);
-+
-+ return affine_move_task(rq, p, dest_cpu, lock, irq_flags);
-+
-+out:
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
-+
-+ return ret;
-+}
-+
-+/*
-+ * Change a given task's CPU affinity. Migrate the thread to a
-+ * is removed from the allowed bitmask.
-+ *
-+ * NOTE: the caller must have a valid reference to the task, the
-+ * task must not exit() & deallocate itself prematurely. The
-+ * call is not atomic; no spinlocks may be held.
-+ */
-+static int __set_cpus_allowed_ptr(struct task_struct *p,
-+ struct affinity_context *ctx)
-+{
-+ unsigned long irq_flags;
-+ struct rq *rq;
-+ raw_spinlock_t *lock;
-+
-+ raw_spin_lock_irqsave(&p->pi_lock, irq_flags);
-+ rq = __task_access_lock(p, &lock);
-+ /*
-+ * Masking should be skipped if SCA_USER or any of the SCA_MIGRATE_*
-+ * flags are set.
-+ */
-+ if (p->user_cpus_ptr &&
-+ !(ctx->flags & SCA_USER) &&
-+ cpumask_and(rq->scratch_mask, ctx->new_mask, p->user_cpus_ptr))
-+ ctx->new_mask = rq->scratch_mask;
-+
-+
-+ return __set_cpus_allowed_ptr_locked(p, ctx, rq, lock, irq_flags);
-+}
-+
-+int set_cpus_allowed_ptr(struct task_struct *p, const struct cpumask *new_mask)
-+{
-+ struct affinity_context ac = {
-+ .new_mask = new_mask,
-+ .flags = 0,
-+ };
-+
-+ return __set_cpus_allowed_ptr(p, &ac);
-+}
-+EXPORT_SYMBOL_GPL(set_cpus_allowed_ptr);
-+
-+/*
-+ * Change a given task's CPU affinity to the intersection of its current
-+ * affinity mask and @subset_mask, writing the resulting mask to @new_mask.
-+ * If user_cpus_ptr is defined, use it as the basis for restricting CPU
-+ * affinity or use cpu_online_mask instead.
-+ *
-+ * If the resulting mask is empty, leave the affinity unchanged and return
-+ * -EINVAL.
-+ */
-+static int restrict_cpus_allowed_ptr(struct task_struct *p,
-+ struct cpumask *new_mask,
-+ const struct cpumask *subset_mask)
-+{
-+ struct affinity_context ac = {
-+ .new_mask = new_mask,
-+ .flags = 0,
-+ };
-+ unsigned long irq_flags;
-+ raw_spinlock_t *lock;
-+ struct rq *rq;
-+ int err;
-+
-+ raw_spin_lock_irqsave(&p->pi_lock, irq_flags);
-+ rq = __task_access_lock(p, &lock);
-+
-+ if (!cpumask_and(new_mask, task_user_cpus(p), subset_mask)) {
-+ err = -EINVAL;
-+ goto err_unlock;
-+ }
-+
-+ return __set_cpus_allowed_ptr_locked(p, &ac, rq, lock, irq_flags);
-+
-+err_unlock:
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, irq_flags);
-+ return err;
-+}
-+
-+/*
-+ * Restrict the CPU affinity of task @p so that it is a subset of
-+ * task_cpu_possible_mask() and point @p->user_cpus_ptr to a copy of the
-+ * old affinity mask. If the resulting mask is empty, we warn and walk
-+ * up the cpuset hierarchy until we find a suitable mask.
-+ */
-+void force_compatible_cpus_allowed_ptr(struct task_struct *p)
-+{
-+ cpumask_var_t new_mask;
-+ const struct cpumask *override_mask = task_cpu_possible_mask(p);
-+
-+ alloc_cpumask_var(&new_mask, GFP_KERNEL);
-+
-+ /*
-+ * __migrate_task() can fail silently in the face of concurrent
-+ * offlining of the chosen destination CPU, so take the hotplug
-+ * lock to ensure that the migration succeeds.
-+ */
-+ cpus_read_lock();
-+ if (!cpumask_available(new_mask))
-+ goto out_set_mask;
-+
-+ if (!restrict_cpus_allowed_ptr(p, new_mask, override_mask))
-+ goto out_free_mask;
-+
-+ /*
-+ * We failed to find a valid subset of the affinity mask for the
-+ * task, so override it based on its cpuset hierarchy.
-+ */
-+ cpuset_cpus_allowed(p, new_mask);
-+ override_mask = new_mask;
-+
-+out_set_mask:
-+ if (printk_ratelimit()) {
-+ printk_deferred("Overriding affinity for process %d (%s) to CPUs %*pbl\n",
-+ task_pid_nr(p), p->comm,
-+ cpumask_pr_args(override_mask));
-+ }
-+
-+ WARN_ON(set_cpus_allowed_ptr(p, override_mask));
-+out_free_mask:
-+ cpus_read_unlock();
-+ free_cpumask_var(new_mask);
-+}
-+
-+static int
-+__sched_setaffinity(struct task_struct *p, struct affinity_context *ctx);
-+
-+/*
-+ * Restore the affinity of a task @p which was previously restricted by a
-+ * call to force_compatible_cpus_allowed_ptr().
-+ *
-+ * It is the caller's responsibility to serialise this with any calls to
-+ * force_compatible_cpus_allowed_ptr(@p).
-+ */
-+void relax_compatible_cpus_allowed_ptr(struct task_struct *p)
-+{
-+ struct affinity_context ac = {
-+ .new_mask = task_user_cpus(p),
-+ .flags = 0,
-+ };
-+ int ret;
-+
-+ /*
-+ * Try to restore the old affinity mask with __sched_setaffinity().
-+ * Cpuset masking will be done there too.
-+ */
-+ ret = __sched_setaffinity(p, &ac);
-+ WARN_ON_ONCE(ret);
-+}
-+
-+#else /* CONFIG_SMP */
-+
-+static inline int select_task_rq(struct task_struct *p)
-+{
-+ return 0;
-+}
-+
-+static inline int
-+__set_cpus_allowed_ptr(struct task_struct *p,
-+ struct affinity_context *ctx)
-+{
-+ return set_cpus_allowed_ptr(p, ctx->new_mask);
-+}
-+
-+static inline bool rq_has_pinned_tasks(struct rq *rq)
-+{
-+ return false;
-+}
-+
-+static inline cpumask_t *alloc_user_cpus_ptr(int node)
-+{
-+ return NULL;
-+}
-+
-+#endif /* !CONFIG_SMP */
-+
-+static void
-+ttwu_stat(struct task_struct *p, int cpu, int wake_flags)
-+{
-+ struct rq *rq;
-+
-+ if (!schedstat_enabled())
-+ return;
-+
-+ rq = this_rq();
-+
-+#ifdef CONFIG_SMP
-+ if (cpu == rq->cpu) {
-+ __schedstat_inc(rq->ttwu_local);
-+ __schedstat_inc(p->stats.nr_wakeups_local);
-+ } else {
-+ /** Alt schedule FW ToDo:
-+ * How to do ttwu_wake_remote
-+ */
-+ }
-+#endif /* CONFIG_SMP */
-+
-+ __schedstat_inc(rq->ttwu_count);
-+ __schedstat_inc(p->stats.nr_wakeups);
-+}
-+
-+/*
-+ * Mark the task runnable.
-+ */
-+static inline void ttwu_do_wakeup(struct task_struct *p)
-+{
-+ WRITE_ONCE(p->__state, TASK_RUNNING);
-+ trace_sched_wakeup(p);
-+}
-+
-+static inline void
-+ttwu_do_activate(struct rq *rq, struct task_struct *p, int wake_flags)
-+{
-+ if (p->sched_contributes_to_load)
-+ rq->nr_uninterruptible--;
-+
-+ if (
-+#ifdef CONFIG_SMP
-+ !(wake_flags & WF_MIGRATED) &&
-+#endif
-+ p->in_iowait) {
-+ delayacct_blkio_end(p);
-+ atomic_dec(&task_rq(p)->nr_iowait);
-+ }
-+
-+ activate_task(p, rq);
-+ wakeup_preempt(rq);
-+
-+ ttwu_do_wakeup(p);
-+}
-+
-+/*
-+ * Consider @p being inside a wait loop:
-+ *
-+ * for (;;) {
-+ * set_current_state(TASK_UNINTERRUPTIBLE);
-+ *
-+ * if (CONDITION)
-+ * break;
-+ *
-+ * schedule();
-+ * }
-+ * __set_current_state(TASK_RUNNING);
-+ *
-+ * between set_current_state() and schedule(). In this case @p is still
-+ * runnable, so all that needs doing is change p->state back to TASK_RUNNING in
-+ * an atomic manner.
-+ *
-+ * By taking task_rq(p)->lock we serialize against schedule(), if @p->on_rq
-+ * then schedule() must still happen and p->state can be changed to
-+ * TASK_RUNNING. Otherwise we lost the race, schedule() has happened, and we
-+ * need to do a full wakeup with enqueue.
-+ *
-+ * Returns: %true when the wakeup is done,
-+ * %false otherwise.
-+ */
-+static int ttwu_runnable(struct task_struct *p, int wake_flags)
-+{
-+ struct rq *rq;
-+ raw_spinlock_t *lock;
-+ int ret = 0;
-+
-+ rq = __task_access_lock(p, &lock);
-+ if (task_on_rq_queued(p)) {
-+ if (!task_on_cpu(p)) {
-+ /*
-+ * When on_rq && !on_cpu the task is preempted, see if
-+ * it should preempt the task that is current now.
-+ */
-+ update_rq_clock(rq);
-+ wakeup_preempt(rq);
-+ }
-+ ttwu_do_wakeup(p);
-+ ret = 1;
-+ }
-+ __task_access_unlock(p, lock);
-+
-+ return ret;
-+}
-+
-+#ifdef CONFIG_SMP
-+void sched_ttwu_pending(void *arg)
-+{
-+ struct llist_node *llist = arg;
-+ struct rq *rq = this_rq();
-+ struct task_struct *p, *t;
-+ struct rq_flags rf;
-+
-+ if (!llist)
-+ return;
-+
-+ rq_lock_irqsave(rq, &rf);
-+ update_rq_clock(rq);
-+
-+ llist_for_each_entry_safe(p, t, llist, wake_entry.llist) {
-+ if (WARN_ON_ONCE(p->on_cpu))
-+ smp_cond_load_acquire(&p->on_cpu, !VAL);
-+
-+ if (WARN_ON_ONCE(task_cpu(p) != cpu_of(rq)))
-+ set_task_cpu(p, cpu_of(rq));
-+
-+ ttwu_do_activate(rq, p, p->sched_remote_wakeup ? WF_MIGRATED : 0);
-+ }
-+
-+ /*
-+ * Must be after enqueueing at least once task such that
-+ * idle_cpu() does not observe a false-negative -- if it does,
-+ * it is possible for select_idle_siblings() to stack a number
-+ * of tasks on this CPU during that window.
-+ *
-+ * It is ok to clear ttwu_pending when another task pending.
-+ * We will receive IPI after local irq enabled and then enqueue it.
-+ * Since now nr_running > 0, idle_cpu() will always get correct result.
-+ */
-+ WRITE_ONCE(rq->ttwu_pending, 0);
-+ rq_unlock_irqrestore(rq, &rf);
-+}
-+
-+/*
-+ * Prepare the scene for sending an IPI for a remote smp_call
-+ *
-+ * Returns true if the caller can proceed with sending the IPI.
-+ * Returns false otherwise.
-+ */
-+bool call_function_single_prep_ipi(int cpu)
-+{
-+ if (set_nr_if_polling(cpu_rq(cpu)->idle)) {
-+ trace_sched_wake_idle_without_ipi(cpu);
-+ return false;
-+ }
-+
-+ return true;
-+}
-+
-+/*
-+ * Queue a task on the target CPUs wake_list and wake the CPU via IPI if
-+ * necessary. The wakee CPU on receipt of the IPI will queue the task
-+ * via sched_ttwu_wakeup() for activation so the wakee incurs the cost
-+ * of the wakeup instead of the waker.
-+ */
-+static void __ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+
-+ p->sched_remote_wakeup = !!(wake_flags & WF_MIGRATED);
-+
-+ WRITE_ONCE(rq->ttwu_pending, 1);
-+ __smp_call_single_queue(cpu, &p->wake_entry.llist);
-+}
-+
-+static inline bool ttwu_queue_cond(struct task_struct *p, int cpu)
-+{
-+ /*
-+ * Do not complicate things with the async wake_list while the CPU is
-+ * in hotplug state.
-+ */
-+ if (!cpu_active(cpu))
-+ return false;
-+
-+ /* Ensure the task will still be allowed to run on the CPU. */
-+ if (!cpumask_test_cpu(cpu, p->cpus_ptr))
-+ return false;
-+
-+ /*
-+ * If the CPU does not share cache, then queue the task on the
-+ * remote rqs wakelist to avoid accessing remote data.
-+ */
-+ if (!cpus_share_cache(smp_processor_id(), cpu))
-+ return true;
-+
-+ if (cpu == smp_processor_id())
-+ return false;
-+
-+ /*
-+ * If the wakee cpu is idle, or the task is descheduling and the
-+ * only running task on the CPU, then use the wakelist to offload
-+ * the task activation to the idle (or soon-to-be-idle) CPU as
-+ * the current CPU is likely busy. nr_running is checked to
-+ * avoid unnecessary task stacking.
-+ *
-+ * Note that we can only get here with (wakee) p->on_rq=0,
-+ * p->on_cpu can be whatever, we've done the dequeue, so
-+ * the wakee has been accounted out of ->nr_running.
-+ */
-+ if (!cpu_rq(cpu)->nr_running)
-+ return true;
-+
-+ return false;
-+}
-+
-+static bool ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
-+{
-+ if (__is_defined(ALT_SCHED_TTWU_QUEUE) && ttwu_queue_cond(p, cpu)) {
-+ sched_clock_cpu(cpu); /* Sync clocks across CPUs */
-+ __ttwu_queue_wakelist(p, cpu, wake_flags);
-+ return true;
-+ }
-+
-+ return false;
-+}
-+
-+void wake_up_if_idle(int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+
-+ guard(rcu)();
-+ if (is_idle_task(rcu_dereference(rq->curr))) {
-+ guard(raw_spinlock_irqsave)(&rq->lock);
-+ if (is_idle_task(rq->curr))
-+ resched_curr(rq);
-+ }
-+}
-+
-+bool cpus_share_cache(int this_cpu, int that_cpu)
-+{
-+ if (this_cpu == that_cpu)
-+ return true;
-+
-+ return per_cpu(sd_llc_id, this_cpu) == per_cpu(sd_llc_id, that_cpu);
-+}
-+#else /* !CONFIG_SMP */
-+
-+static inline bool ttwu_queue_wakelist(struct task_struct *p, int cpu, int wake_flags)
-+{
-+ return false;
-+}
-+
-+#endif /* CONFIG_SMP */
-+
-+static inline void ttwu_queue(struct task_struct *p, int cpu, int wake_flags)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+
-+ if (ttwu_queue_wakelist(p, cpu, wake_flags))
-+ return;
-+
-+ raw_spin_lock(&rq->lock);
-+ update_rq_clock(rq);
-+ ttwu_do_activate(rq, p, wake_flags);
-+ raw_spin_unlock(&rq->lock);
-+}
-+
-+/*
-+ * Invoked from try_to_wake_up() to check whether the task can be woken up.
-+ *
-+ * The caller holds p::pi_lock if p != current or has preemption
-+ * disabled when p == current.
-+ *
-+ * The rules of saved_state:
-+ *
-+ * The related locking code always holds p::pi_lock when updating
-+ * p::saved_state, which means the code is fully serialized in both cases.
-+ *
-+ * For PREEMPT_RT, the lock wait and lock wakeups happen via TASK_RTLOCK_WAIT.
-+ * No other bits set. This allows to distinguish all wakeup scenarios.
-+ *
-+ * For FREEZER, the wakeup happens via TASK_FROZEN. No other bits set. This
-+ * allows us to prevent early wakeup of tasks before they can be run on
-+ * asymmetric ISA architectures (eg ARMv9).
-+ */
-+static __always_inline
-+bool ttwu_state_match(struct task_struct *p, unsigned int state, int *success)
-+{
-+ int match;
-+
-+ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT)) {
-+ WARN_ON_ONCE((state & TASK_RTLOCK_WAIT) &&
-+ state != TASK_RTLOCK_WAIT);
-+ }
-+
-+ *success = !!(match = __task_state_match(p, state));
-+
-+ /*
-+ * Saved state preserves the task state across blocking on
-+ * an RT lock or TASK_FREEZABLE tasks. If the state matches,
-+ * set p::saved_state to TASK_RUNNING, but do not wake the task
-+ * because it waits for a lock wakeup or __thaw_task(). Also
-+ * indicate success because from the regular waker's point of
-+ * view this has succeeded.
-+ *
-+ * After acquiring the lock the task will restore p::__state
-+ * from p::saved_state which ensures that the regular
-+ * wakeup is not lost. The restore will also set
-+ * p::saved_state to TASK_RUNNING so any further tests will
-+ * not result in false positives vs. @success
-+ */
-+ if (match < 0)
-+ p->saved_state = TASK_RUNNING;
-+
-+ return match > 0;
-+}
-+
-+/*
-+ * Notes on Program-Order guarantees on SMP systems.
-+ *
-+ * MIGRATION
-+ *
-+ * The basic program-order guarantee on SMP systems is that when a task [t]
-+ * migrates, all its activity on its old CPU [c0] happens-before any subsequent
-+ * execution on its new CPU [c1].
-+ *
-+ * For migration (of runnable tasks) this is provided by the following means:
-+ *
-+ * A) UNLOCK of the rq(c0)->lock scheduling out task t
-+ * B) migration for t is required to synchronize *both* rq(c0)->lock and
-+ * rq(c1)->lock (if not at the same time, then in that order).
-+ * C) LOCK of the rq(c1)->lock scheduling in task
-+ *
-+ * Transitivity guarantees that B happens after A and C after B.
-+ * Note: we only require RCpc transitivity.
-+ * Note: the CPU doing B need not be c0 or c1
-+ *
-+ * Example:
-+ *
-+ * CPU0 CPU1 CPU2
-+ *
-+ * LOCK rq(0)->lock
-+ * sched-out X
-+ * sched-in Y
-+ * UNLOCK rq(0)->lock
-+ *
-+ * LOCK rq(0)->lock // orders against CPU0
-+ * dequeue X
-+ * UNLOCK rq(0)->lock
-+ *
-+ * LOCK rq(1)->lock
-+ * enqueue X
-+ * UNLOCK rq(1)->lock
-+ *
-+ * LOCK rq(1)->lock // orders against CPU2
-+ * sched-out Z
-+ * sched-in X
-+ * UNLOCK rq(1)->lock
-+ *
-+ *
-+ * BLOCKING -- aka. SLEEP + WAKEUP
-+ *
-+ * For blocking we (obviously) need to provide the same guarantee as for
-+ * migration. However the means are completely different as there is no lock
-+ * chain to provide order. Instead we do:
-+ *
-+ * 1) smp_store_release(X->on_cpu, 0) -- finish_task()
-+ * 2) smp_cond_load_acquire(!X->on_cpu) -- try_to_wake_up()
-+ *
-+ * Example:
-+ *
-+ * CPU0 (schedule) CPU1 (try_to_wake_up) CPU2 (schedule)
-+ *
-+ * LOCK rq(0)->lock LOCK X->pi_lock
-+ * dequeue X
-+ * sched-out X
-+ * smp_store_release(X->on_cpu, 0);
-+ *
-+ * smp_cond_load_acquire(&X->on_cpu, !VAL);
-+ * X->state = WAKING
-+ * set_task_cpu(X,2)
-+ *
-+ * LOCK rq(2)->lock
-+ * enqueue X
-+ * X->state = RUNNING
-+ * UNLOCK rq(2)->lock
-+ *
-+ * LOCK rq(2)->lock // orders against CPU1
-+ * sched-out Z
-+ * sched-in X
-+ * UNLOCK rq(2)->lock
-+ *
-+ * UNLOCK X->pi_lock
-+ * UNLOCK rq(0)->lock
-+ *
-+ *
-+ * However; for wakeups there is a second guarantee we must provide, namely we
-+ * must observe the state that lead to our wakeup. That is, not only must our
-+ * task observe its own prior state, it must also observe the stores prior to
-+ * its wakeup.
-+ *
-+ * This means that any means of doing remote wakeups must order the CPU doing
-+ * the wakeup against the CPU the task is going to end up running on. This,
-+ * however, is already required for the regular Program-Order guarantee above,
-+ * since the waking CPU is the one issueing the ACQUIRE (smp_cond_load_acquire).
-+ *
-+ */
-+
-+/**
-+ * try_to_wake_up - wake up a thread
-+ * @p: the thread to be awakened
-+ * @state: the mask of task states that can be woken
-+ * @wake_flags: wake modifier flags (WF_*)
-+ *
-+ * Conceptually does:
-+ *
-+ * If (@state & @p->state) @p->state = TASK_RUNNING.
-+ *
-+ * If the task was not queued/runnable, also place it back on a runqueue.
-+ *
-+ * This function is atomic against schedule() which would dequeue the task.
-+ *
-+ * It issues a full memory barrier before accessing @p->state, see the comment
-+ * with set_current_state().
-+ *
-+ * Uses p->pi_lock to serialize against concurrent wake-ups.
-+ *
-+ * Relies on p->pi_lock stabilizing:
-+ * - p->sched_class
-+ * - p->cpus_ptr
-+ * - p->sched_task_group
-+ * in order to do migration, see its use of select_task_rq()/set_task_cpu().
-+ *
-+ * Tries really hard to only take one task_rq(p)->lock for performance.
-+ * Takes rq->lock in:
-+ * - ttwu_runnable() -- old rq, unavoidable, see comment there;
-+ * - ttwu_queue() -- new rq, for enqueue of the task;
-+ * - psi_ttwu_dequeue() -- much sadness :-( accounting will kill us.
-+ *
-+ * As a consequence we race really badly with just about everything. See the
-+ * many memory barriers and their comments for details.
-+ *
-+ * Return: %true if @p->state changes (an actual wakeup was done),
-+ * %false otherwise.
-+ */
-+int try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
-+{
-+ guard(preempt)();
-+ int cpu, success = 0;
-+
-+ if (p == current) {
-+ /*
-+ * We're waking current, this means 'p->on_rq' and 'task_cpu(p)
-+ * == smp_processor_id()'. Together this means we can special
-+ * case the whole 'p->on_rq && ttwu_runnable()' case below
-+ * without taking any locks.
-+ *
-+ * In particular:
-+ * - we rely on Program-Order guarantees for all the ordering,
-+ * - we're serialized against set_special_state() by virtue of
-+ * it disabling IRQs (this allows not taking ->pi_lock).
-+ */
-+ if (!ttwu_state_match(p, state, &success))
-+ goto out;
-+
-+ trace_sched_waking(p);
-+ ttwu_do_wakeup(p);
-+ goto out;
-+ }
-+
-+ /*
-+ * If we are going to wake up a thread waiting for CONDITION we
-+ * need to ensure that CONDITION=1 done by the caller can not be
-+ * reordered with p->state check below. This pairs with smp_store_mb()
-+ * in set_current_state() that the waiting thread does.
-+ */
-+ scoped_guard (raw_spinlock_irqsave, &p->pi_lock) {
-+ smp_mb__after_spinlock();
-+ if (!ttwu_state_match(p, state, &success))
-+ break;
-+
-+ trace_sched_waking(p);
-+
-+ /*
-+ * Ensure we load p->on_rq _after_ p->state, otherwise it would
-+ * be possible to, falsely, observe p->on_rq == 0 and get stuck
-+ * in smp_cond_load_acquire() below.
-+ *
-+ * sched_ttwu_pending() try_to_wake_up()
-+ * STORE p->on_rq = 1 LOAD p->state
-+ * UNLOCK rq->lock
-+ *
-+ * __schedule() (switch to task 'p')
-+ * LOCK rq->lock smp_rmb();
-+ * smp_mb__after_spinlock();
-+ * UNLOCK rq->lock
-+ *
-+ * [task p]
-+ * STORE p->state = UNINTERRUPTIBLE LOAD p->on_rq
-+ *
-+ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in
-+ * __schedule(). See the comment for smp_mb__after_spinlock().
-+ *
-+ * A similar smp_rmb() lives in __task_needs_rq_lock().
-+ */
-+ smp_rmb();
-+ if (READ_ONCE(p->on_rq) && ttwu_runnable(p, wake_flags))
-+ break;
-+
-+#ifdef CONFIG_SMP
-+ /*
-+ * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be
-+ * possible to, falsely, observe p->on_cpu == 0.
-+ *
-+ * One must be running (->on_cpu == 1) in order to remove oneself
-+ * from the runqueue.
-+ *
-+ * __schedule() (switch to task 'p') try_to_wake_up()
-+ * STORE p->on_cpu = 1 LOAD p->on_rq
-+ * UNLOCK rq->lock
-+ *
-+ * __schedule() (put 'p' to sleep)
-+ * LOCK rq->lock smp_rmb();
-+ * smp_mb__after_spinlock();
-+ * STORE p->on_rq = 0 LOAD p->on_cpu
-+ *
-+ * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in
-+ * __schedule(). See the comment for smp_mb__after_spinlock().
-+ *
-+ * Form a control-dep-acquire with p->on_rq == 0 above, to ensure
-+ * schedule()'s deactivate_task() has 'happened' and p will no longer
-+ * care about it's own p->state. See the comment in __schedule().
-+ */
-+ smp_acquire__after_ctrl_dep();
-+
-+ /*
-+ * We're doing the wakeup (@success == 1), they did a dequeue (p->on_rq
-+ * == 0), which means we need to do an enqueue, change p->state to
-+ * TASK_WAKING such that we can unlock p->pi_lock before doing the
-+ * enqueue, such as ttwu_queue_wakelist().
-+ */
-+ WRITE_ONCE(p->__state, TASK_WAKING);
-+
-+ /*
-+ * If the owning (remote) CPU is still in the middle of schedule() with
-+ * this task as prev, considering queueing p on the remote CPUs wake_list
-+ * which potentially sends an IPI instead of spinning on p->on_cpu to
-+ * let the waker make forward progress. This is safe because IRQs are
-+ * disabled and the IPI will deliver after on_cpu is cleared.
-+ *
-+ * Ensure we load task_cpu(p) after p->on_cpu:
-+ *
-+ * set_task_cpu(p, cpu);
-+ * STORE p->cpu = @cpu
-+ * __schedule() (switch to task 'p')
-+ * LOCK rq->lock
-+ * smp_mb__after_spin_lock() smp_cond_load_acquire(&p->on_cpu)
-+ * STORE p->on_cpu = 1 LOAD p->cpu
-+ *
-+ * to ensure we observe the correct CPU on which the task is currently
-+ * scheduling.
-+ */
-+ if (smp_load_acquire(&p->on_cpu) &&
-+ ttwu_queue_wakelist(p, task_cpu(p), wake_flags))
-+ break;
-+
-+ /*
-+ * If the owning (remote) CPU is still in the middle of schedule() with
-+ * this task as prev, wait until it's done referencing the task.
-+ *
-+ * Pairs with the smp_store_release() in finish_task().
-+ *
-+ * This ensures that tasks getting woken will be fully ordered against
-+ * their previous state and preserve Program Order.
-+ */
-+ smp_cond_load_acquire(&p->on_cpu, !VAL);
-+
-+ sched_task_ttwu(p);
-+
-+ if ((wake_flags & WF_CURRENT_CPU) &&
-+ cpumask_test_cpu(smp_processor_id(), p->cpus_ptr))
-+ cpu = smp_processor_id();
-+ else
-+ cpu = select_task_rq(p);
-+
-+ if (cpu != task_cpu(p)) {
-+ if (p->in_iowait) {
-+ delayacct_blkio_end(p);
-+ atomic_dec(&task_rq(p)->nr_iowait);
-+ }
-+
-+ wake_flags |= WF_MIGRATED;
-+ set_task_cpu(p, cpu);
-+ }
-+#else
-+ sched_task_ttwu(p);
-+
-+ cpu = task_cpu(p);
-+#endif /* CONFIG_SMP */
-+
-+ ttwu_queue(p, cpu, wake_flags);
-+ }
-+out:
-+ if (success)
-+ ttwu_stat(p, task_cpu(p), wake_flags);
-+
-+ return success;
-+}
-+
-+static bool __task_needs_rq_lock(struct task_struct *p)
-+{
-+ unsigned int state = READ_ONCE(p->__state);
-+
-+ /*
-+ * Since pi->lock blocks try_to_wake_up(), we don't need rq->lock when
-+ * the task is blocked. Make sure to check @state since ttwu() can drop
-+ * locks at the end, see ttwu_queue_wakelist().
-+ */
-+ if (state == TASK_RUNNING || state == TASK_WAKING)
-+ return true;
-+
-+ /*
-+ * Ensure we load p->on_rq after p->__state, otherwise it would be
-+ * possible to, falsely, observe p->on_rq == 0.
-+ *
-+ * See try_to_wake_up() for a longer comment.
-+ */
-+ smp_rmb();
-+ if (p->on_rq)
-+ return true;
-+
-+#ifdef CONFIG_SMP
-+ /*
-+ * Ensure the task has finished __schedule() and will not be referenced
-+ * anymore. Again, see try_to_wake_up() for a longer comment.
-+ */
-+ smp_rmb();
-+ smp_cond_load_acquire(&p->on_cpu, !VAL);
-+#endif
-+
-+ return false;
-+}
-+
-+/**
-+ * task_call_func - Invoke a function on task in fixed state
-+ * @p: Process for which the function is to be invoked, can be @current.
-+ * @func: Function to invoke.
-+ * @arg: Argument to function.
-+ *
-+ * Fix the task in it's current state by avoiding wakeups and or rq operations
-+ * and call @func(@arg) on it. This function can use ->on_rq and task_curr()
-+ * to work out what the state is, if required. Given that @func can be invoked
-+ * with a runqueue lock held, it had better be quite lightweight.
-+ *
-+ * Returns:
-+ * Whatever @func returns
-+ */
-+int task_call_func(struct task_struct *p, task_call_f func, void *arg)
-+{
-+ struct rq *rq = NULL;
-+ struct rq_flags rf;
-+ int ret;
-+
-+ raw_spin_lock_irqsave(&p->pi_lock, rf.flags);
-+
-+ if (__task_needs_rq_lock(p))
-+ rq = __task_rq_lock(p, &rf);
-+
-+ /*
-+ * At this point the task is pinned; either:
-+ * - blocked and we're holding off wakeups (pi->lock)
-+ * - woken, and we're holding off enqueue (rq->lock)
-+ * - queued, and we're holding off schedule (rq->lock)
-+ * - running, and we're holding off de-schedule (rq->lock)
-+ *
-+ * The called function (@func) can use: task_curr(), p->on_rq and
-+ * p->__state to differentiate between these states.
-+ */
-+ ret = func(p, arg);
-+
-+ if (rq)
-+ __task_rq_unlock(rq, &rf);
-+
-+ raw_spin_unlock_irqrestore(&p->pi_lock, rf.flags);
-+ return ret;
-+}
-+
-+/**
-+ * cpu_curr_snapshot - Return a snapshot of the currently running task
-+ * @cpu: The CPU on which to snapshot the task.
-+ *
-+ * Returns the task_struct pointer of the task "currently" running on
-+ * the specified CPU. If the same task is running on that CPU throughout,
-+ * the return value will be a pointer to that task's task_struct structure.
-+ * If the CPU did any context switches even vaguely concurrently with the
-+ * execution of this function, the return value will be a pointer to the
-+ * task_struct structure of a randomly chosen task that was running on
-+ * that CPU somewhere around the time that this function was executing.
-+ *
-+ * If the specified CPU was offline, the return value is whatever it
-+ * is, perhaps a pointer to the task_struct structure of that CPU's idle
-+ * task, but there is no guarantee. Callers wishing a useful return
-+ * value must take some action to ensure that the specified CPU remains
-+ * online throughout.
-+ *
-+ * This function executes full memory barriers before and after fetching
-+ * the pointer, which permits the caller to confine this function's fetch
-+ * with respect to the caller's accesses to other shared variables.
-+ */
-+struct task_struct *cpu_curr_snapshot(int cpu)
-+{
-+ struct task_struct *t;
-+
-+ smp_mb(); /* Pairing determined by caller's synchronization design. */
-+ t = rcu_dereference(cpu_curr(cpu));
-+ smp_mb(); /* Pairing determined by caller's synchronization design. */
-+ return t;
-+}
-+
-+/**
-+ * wake_up_process - Wake up a specific process
-+ * @p: The process to be woken up.
-+ *
-+ * Attempt to wake up the nominated process and move it to the set of runnable
-+ * processes.
-+ *
-+ * Return: 1 if the process was woken up, 0 if it was already running.
-+ *
-+ * This function executes a full memory barrier before accessing the task state.
-+ */
-+int wake_up_process(struct task_struct *p)
-+{
-+ return try_to_wake_up(p, TASK_NORMAL, 0);
-+}
-+EXPORT_SYMBOL(wake_up_process);
-+
-+int wake_up_state(struct task_struct *p, unsigned int state)
-+{
-+ return try_to_wake_up(p, state, 0);
-+}
-+
-+/*
-+ * Perform scheduler related setup for a newly forked process p.
-+ * p is forked by current.
-+ *
-+ * __sched_fork() is basic setup used by init_idle() too:
-+ */
-+static inline void __sched_fork(unsigned long clone_flags, struct task_struct *p)
-+{
-+ p->on_rq = 0;
-+ p->on_cpu = 0;
-+ p->utime = 0;
-+ p->stime = 0;
-+ p->sched_time = 0;
-+
-+#ifdef CONFIG_SCHEDSTATS
-+ /* Even if schedstat is disabled, there should not be garbage */
-+ memset(&p->stats, 0, sizeof(p->stats));
-+#endif
-+
-+#ifdef CONFIG_PREEMPT_NOTIFIERS
-+ INIT_HLIST_HEAD(&p->preempt_notifiers);
-+#endif
-+
-+#ifdef CONFIG_COMPACTION
-+ p->capture_control = NULL;
-+#endif
-+#ifdef CONFIG_SMP
-+ p->wake_entry.u_flags = CSD_TYPE_TTWU;
-+#endif
-+ init_sched_mm_cid(p);
-+}
-+
-+/*
-+ * fork()/clone()-time setup:
-+ */
-+int sched_fork(unsigned long clone_flags, struct task_struct *p)
-+{
-+ __sched_fork(clone_flags, p);
-+ /*
-+ * We mark the process as NEW here. This guarantees that
-+ * nobody will actually run it, and a signal or other external
-+ * event cannot wake it up and insert it on the runqueue either.
-+ */
-+ p->__state = TASK_NEW;
-+
-+ /*
-+ * Make sure we do not leak PI boosting priority to the child.
-+ */
-+ p->prio = current->normal_prio;
-+
-+ /*
-+ * Revert to default priority/policy on fork if requested.
-+ */
-+ if (unlikely(p->sched_reset_on_fork)) {
-+ if (task_has_rt_policy(p)) {
-+ p->policy = SCHED_NORMAL;
-+ p->static_prio = NICE_TO_PRIO(0);
-+ p->rt_priority = 0;
-+ } else if (PRIO_TO_NICE(p->static_prio) < 0)
-+ p->static_prio = NICE_TO_PRIO(0);
-+
-+ p->prio = p->normal_prio = p->static_prio;
-+
-+ /*
-+ * We don't need the reset flag anymore after the fork. It has
-+ * fulfilled its duty:
-+ */
-+ p->sched_reset_on_fork = 0;
-+ }
-+
-+#ifdef CONFIG_SCHED_INFO
-+ if (unlikely(sched_info_on()))
-+ memset(&p->sched_info, 0, sizeof(p->sched_info));
-+#endif
-+ init_task_preempt_count(p);
-+
-+ return 0;
-+}
-+
-+void sched_cgroup_fork(struct task_struct *p, struct kernel_clone_args *kargs)
-+{
-+ unsigned long flags;
-+ struct rq *rq;
-+
-+ /*
-+ * Because we're not yet on the pid-hash, p->pi_lock isn't strictly
-+ * required yet, but lockdep gets upset if rules are violated.
-+ */
-+ raw_spin_lock_irqsave(&p->pi_lock, flags);
-+ /*
-+ * Share the timeslice between parent and child, thus the
-+ * total amount of pending timeslices in the system doesn't change,
-+ * resulting in more scheduling fairness.
-+ */
-+ rq = this_rq();
-+ raw_spin_lock(&rq->lock);
-+
-+ rq->curr->time_slice /= 2;
-+ p->time_slice = rq->curr->time_slice;
-+#ifdef CONFIG_SCHED_HRTICK
-+ hrtick_start(rq, rq->curr->time_slice);
-+#endif
-+
-+ if (p->time_slice < RESCHED_NS) {
-+ p->time_slice = sysctl_sched_base_slice;
-+ resched_curr(rq);
-+ }
-+ sched_task_fork(p, rq);
-+ raw_spin_unlock(&rq->lock);
-+
-+ rseq_migrate(p);
-+ /*
-+ * We're setting the CPU for the first time, we don't migrate,
-+ * so use __set_task_cpu().
-+ */
-+ __set_task_cpu(p, smp_processor_id());
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+}
-+
-+void sched_post_fork(struct task_struct *p)
-+{
-+}
-+
-+#ifdef CONFIG_SCHEDSTATS
-+
-+DEFINE_STATIC_KEY_FALSE(sched_schedstats);
-+
-+static void set_schedstats(bool enabled)
-+{
-+ if (enabled)
-+ static_branch_enable(&sched_schedstats);
-+ else
-+ static_branch_disable(&sched_schedstats);
-+}
-+
-+void force_schedstat_enabled(void)
-+{
-+ if (!schedstat_enabled()) {
-+ pr_info("kernel profiling enabled schedstats, disable via kernel.sched_schedstats.\n");
-+ static_branch_enable(&sched_schedstats);
-+ }
-+}
-+
-+static int __init setup_schedstats(char *str)
-+{
-+ int ret = 0;
-+ if (!str)
-+ goto out;
-+
-+ if (!strcmp(str, "enable")) {
-+ set_schedstats(true);
-+ ret = 1;
-+ } else if (!strcmp(str, "disable")) {
-+ set_schedstats(false);
-+ ret = 1;
-+ }
-+out:
-+ if (!ret)
-+ pr_warn("Unable to parse schedstats=\n");
-+
-+ return ret;
-+}
-+__setup("schedstats=", setup_schedstats);
-+
-+#ifdef CONFIG_PROC_SYSCTL
-+static int sysctl_schedstats(struct ctl_table *table, int write, void *buffer,
-+ size_t *lenp, loff_t *ppos)
-+{
-+ struct ctl_table t;
-+ int err;
-+ int state = static_branch_likely(&sched_schedstats);
-+
-+ if (write && !capable(CAP_SYS_ADMIN))
-+ return -EPERM;
-+
-+ t = *table;
-+ t.data = &state;
-+ err = proc_dointvec_minmax(&t, write, buffer, lenp, ppos);
-+ if (err < 0)
-+ return err;
-+ if (write)
-+ set_schedstats(state);
-+ return err;
-+}
-+
-+static struct ctl_table sched_core_sysctls[] = {
-+ {
-+ .procname = "sched_schedstats",
-+ .data = NULL,
-+ .maxlen = sizeof(unsigned int),
-+ .mode = 0644,
-+ .proc_handler = sysctl_schedstats,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_ONE,
-+ },
-+ {}
-+};
-+static int __init sched_core_sysctl_init(void)
-+{
-+ register_sysctl_init("kernel", sched_core_sysctls);
-+ return 0;
-+}
-+late_initcall(sched_core_sysctl_init);
-+#endif /* CONFIG_PROC_SYSCTL */
-+#endif /* CONFIG_SCHEDSTATS */
-+
-+/*
-+ * wake_up_new_task - wake up a newly created task for the first time.
-+ *
-+ * This function will do some initial scheduler statistics housekeeping
-+ * that must be done for every newly created context, then puts the task
-+ * on the runqueue and wakes it.
-+ */
-+void wake_up_new_task(struct task_struct *p)
-+{
-+ unsigned long flags;
-+ struct rq *rq;
-+
-+ raw_spin_lock_irqsave(&p->pi_lock, flags);
-+ WRITE_ONCE(p->__state, TASK_RUNNING);
-+ rq = cpu_rq(select_task_rq(p));
-+#ifdef CONFIG_SMP
-+ rseq_migrate(p);
-+ /*
-+ * Fork balancing, do it here and not earlier because:
-+ * - cpus_ptr can change in the fork path
-+ * - any previously selected CPU might disappear through hotplug
-+ *
-+ * Use __set_task_cpu() to avoid calling sched_class::migrate_task_rq,
-+ * as we're not fully set-up yet.
-+ */
-+ __set_task_cpu(p, cpu_of(rq));
-+#endif
-+
-+ raw_spin_lock(&rq->lock);
-+ update_rq_clock(rq);
-+
-+ activate_task(p, rq);
-+ trace_sched_wakeup_new(p);
-+ wakeup_preempt(rq);
-+
-+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+}
-+
-+#ifdef CONFIG_PREEMPT_NOTIFIERS
-+
-+static DEFINE_STATIC_KEY_FALSE(preempt_notifier_key);
-+
-+void preempt_notifier_inc(void)
-+{
-+ static_branch_inc(&preempt_notifier_key);
-+}
-+EXPORT_SYMBOL_GPL(preempt_notifier_inc);
-+
-+void preempt_notifier_dec(void)
-+{
-+ static_branch_dec(&preempt_notifier_key);
-+}
-+EXPORT_SYMBOL_GPL(preempt_notifier_dec);
-+
-+/**
-+ * preempt_notifier_register - tell me when current is being preempted & rescheduled
-+ * @notifier: notifier struct to register
-+ */
-+void preempt_notifier_register(struct preempt_notifier *notifier)
-+{
-+ if (!static_branch_unlikely(&preempt_notifier_key))
-+ WARN(1, "registering preempt_notifier while notifiers disabled\n");
-+
-+ hlist_add_head(¬ifier->link, ¤t->preempt_notifiers);
-+}
-+EXPORT_SYMBOL_GPL(preempt_notifier_register);
-+
-+/**
-+ * preempt_notifier_unregister - no longer interested in preemption notifications
-+ * @notifier: notifier struct to unregister
-+ *
-+ * This is *not* safe to call from within a preemption notifier.
-+ */
-+void preempt_notifier_unregister(struct preempt_notifier *notifier)
-+{
-+ hlist_del(¬ifier->link);
-+}
-+EXPORT_SYMBOL_GPL(preempt_notifier_unregister);
-+
-+static void __fire_sched_in_preempt_notifiers(struct task_struct *curr)
-+{
-+ struct preempt_notifier *notifier;
-+
-+ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link)
-+ notifier->ops->sched_in(notifier, raw_smp_processor_id());
-+}
-+
-+static __always_inline void fire_sched_in_preempt_notifiers(struct task_struct *curr)
-+{
-+ if (static_branch_unlikely(&preempt_notifier_key))
-+ __fire_sched_in_preempt_notifiers(curr);
-+}
-+
-+static void
-+__fire_sched_out_preempt_notifiers(struct task_struct *curr,
-+ struct task_struct *next)
-+{
-+ struct preempt_notifier *notifier;
-+
-+ hlist_for_each_entry(notifier, &curr->preempt_notifiers, link)
-+ notifier->ops->sched_out(notifier, next);
-+}
-+
-+static __always_inline void
-+fire_sched_out_preempt_notifiers(struct task_struct *curr,
-+ struct task_struct *next)
-+{
-+ if (static_branch_unlikely(&preempt_notifier_key))
-+ __fire_sched_out_preempt_notifiers(curr, next);
-+}
-+
-+#else /* !CONFIG_PREEMPT_NOTIFIERS */
-+
-+static inline void fire_sched_in_preempt_notifiers(struct task_struct *curr)
-+{
-+}
-+
-+static inline void
-+fire_sched_out_preempt_notifiers(struct task_struct *curr,
-+ struct task_struct *next)
-+{
-+}
-+
-+#endif /* CONFIG_PREEMPT_NOTIFIERS */
-+
-+static inline void prepare_task(struct task_struct *next)
-+{
-+ /*
-+ * Claim the task as running, we do this before switching to it
-+ * such that any running task will have this set.
-+ *
-+ * See the smp_load_acquire(&p->on_cpu) case in ttwu() and
-+ * its ordering comment.
-+ */
-+ WRITE_ONCE(next->on_cpu, 1);
-+}
-+
-+static inline void finish_task(struct task_struct *prev)
-+{
-+#ifdef CONFIG_SMP
-+ /*
-+ * This must be the very last reference to @prev from this CPU. After
-+ * p->on_cpu is cleared, the task can be moved to a different CPU. We
-+ * must ensure this doesn't happen until the switch is completely
-+ * finished.
-+ *
-+ * In particular, the load of prev->state in finish_task_switch() must
-+ * happen before this.
-+ *
-+ * Pairs with the smp_cond_load_acquire() in try_to_wake_up().
-+ */
-+ smp_store_release(&prev->on_cpu, 0);
-+#else
-+ prev->on_cpu = 0;
-+#endif
-+}
-+
-+#ifdef CONFIG_SMP
-+
-+static void do_balance_callbacks(struct rq *rq, struct balance_callback *head)
-+{
-+ void (*func)(struct rq *rq);
-+ struct balance_callback *next;
-+
-+ lockdep_assert_held(&rq->lock);
-+
-+ while (head) {
-+ func = (void (*)(struct rq *))head->func;
-+ next = head->next;
-+ head->next = NULL;
-+ head = next;
-+
-+ func(rq);
-+ }
-+}
-+
-+static void balance_push(struct rq *rq);
-+
-+/*
-+ * balance_push_callback is a right abuse of the callback interface and plays
-+ * by significantly different rules.
-+ *
-+ * Where the normal balance_callback's purpose is to be ran in the same context
-+ * that queued it (only later, when it's safe to drop rq->lock again),
-+ * balance_push_callback is specifically targeted at __schedule().
-+ *
-+ * This abuse is tolerated because it places all the unlikely/odd cases behind
-+ * a single test, namely: rq->balance_callback == NULL.
-+ */
-+struct balance_callback balance_push_callback = {
-+ .next = NULL,
-+ .func = balance_push,
-+};
-+
-+static inline struct balance_callback *
-+__splice_balance_callbacks(struct rq *rq, bool split)
-+{
-+ struct balance_callback *head = rq->balance_callback;
-+
-+ if (likely(!head))
-+ return NULL;
-+
-+ lockdep_assert_rq_held(rq);
-+ /*
-+ * Must not take balance_push_callback off the list when
-+ * splice_balance_callbacks() and balance_callbacks() are not
-+ * in the same rq->lock section.
-+ *
-+ * In that case it would be possible for __schedule() to interleave
-+ * and observe the list empty.
-+ */
-+ if (split && head == &balance_push_callback)
-+ head = NULL;
-+ else
-+ rq->balance_callback = NULL;
-+
-+ return head;
-+}
-+
-+static inline struct balance_callback *splice_balance_callbacks(struct rq *rq)
-+{
-+ return __splice_balance_callbacks(rq, true);
-+}
-+
-+static void __balance_callbacks(struct rq *rq)
-+{
-+ do_balance_callbacks(rq, __splice_balance_callbacks(rq, false));
-+}
-+
-+static inline void balance_callbacks(struct rq *rq, struct balance_callback *head)
-+{
-+ unsigned long flags;
-+
-+ if (unlikely(head)) {
-+ raw_spin_lock_irqsave(&rq->lock, flags);
-+ do_balance_callbacks(rq, head);
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+ }
-+}
-+
-+#else
-+
-+static inline void __balance_callbacks(struct rq *rq)
-+{
-+}
-+
-+static inline struct balance_callback *splice_balance_callbacks(struct rq *rq)
-+{
-+ return NULL;
-+}
-+
-+static inline void balance_callbacks(struct rq *rq, struct balance_callback *head)
-+{
-+}
-+
-+#endif
-+
-+static inline void
-+prepare_lock_switch(struct rq *rq, struct task_struct *next)
-+{
-+ /*
-+ * Since the runqueue lock will be released by the next
-+ * task (which is an invalid locking op but in the case
-+ * of the scheduler it's an obvious special-case), so we
-+ * do an early lockdep release here:
-+ */
-+ spin_release(&rq->lock.dep_map, _THIS_IP_);
-+#ifdef CONFIG_DEBUG_SPINLOCK
-+ /* this is a valid case when another task releases the spinlock */
-+ rq->lock.owner = next;
-+#endif
-+}
-+
-+static inline void finish_lock_switch(struct rq *rq)
-+{
-+ /*
-+ * If we are tracking spinlock dependencies then we have to
-+ * fix up the runqueue lock - which gets 'carried over' from
-+ * prev into current:
-+ */
-+ spin_acquire(&rq->lock.dep_map, 0, 0, _THIS_IP_);
-+ __balance_callbacks(rq);
-+ raw_spin_unlock_irq(&rq->lock);
-+}
-+
-+/*
-+ * NOP if the arch has not defined these:
-+ */
-+
-+#ifndef prepare_arch_switch
-+# define prepare_arch_switch(next) do { } while (0)
-+#endif
-+
-+#ifndef finish_arch_post_lock_switch
-+# define finish_arch_post_lock_switch() do { } while (0)
-+#endif
-+
-+static inline void kmap_local_sched_out(void)
-+{
-+#ifdef CONFIG_KMAP_LOCAL
-+ if (unlikely(current->kmap_ctrl.idx))
-+ __kmap_local_sched_out();
-+#endif
-+}
-+
-+static inline void kmap_local_sched_in(void)
-+{
-+#ifdef CONFIG_KMAP_LOCAL
-+ if (unlikely(current->kmap_ctrl.idx))
-+ __kmap_local_sched_in();
-+#endif
-+}
-+
-+/**
-+ * prepare_task_switch - prepare to switch tasks
-+ * @rq: the runqueue preparing to switch
-+ * @next: the task we are going to switch to.
-+ *
-+ * This is called with the rq lock held and interrupts off. It must
-+ * be paired with a subsequent finish_task_switch after the context
-+ * switch.
-+ *
-+ * prepare_task_switch sets up locking and calls architecture specific
-+ * hooks.
-+ */
-+static inline void
-+prepare_task_switch(struct rq *rq, struct task_struct *prev,
-+ struct task_struct *next)
-+{
-+ kcov_prepare_switch(prev);
-+ sched_info_switch(rq, prev, next);
-+ perf_event_task_sched_out(prev, next);
-+ rseq_preempt(prev);
-+ fire_sched_out_preempt_notifiers(prev, next);
-+ kmap_local_sched_out();
-+ prepare_task(next);
-+ prepare_arch_switch(next);
-+}
-+
-+/**
-+ * finish_task_switch - clean up after a task-switch
-+ * @rq: runqueue associated with task-switch
-+ * @prev: the thread we just switched away from.
-+ *
-+ * finish_task_switch must be called after the context switch, paired
-+ * with a prepare_task_switch call before the context switch.
-+ * finish_task_switch will reconcile locking set up by prepare_task_switch,
-+ * and do any other architecture-specific cleanup actions.
-+ *
-+ * Note that we may have delayed dropping an mm in context_switch(). If
-+ * so, we finish that here outside of the runqueue lock. (Doing it
-+ * with the lock held can cause deadlocks; see schedule() for
-+ * details.)
-+ *
-+ * The context switch have flipped the stack from under us and restored the
-+ * local variables which were saved when this task called schedule() in the
-+ * past. prev == current is still correct but we need to recalculate this_rq
-+ * because prev may have moved to another CPU.
-+ */
-+static struct rq *finish_task_switch(struct task_struct *prev)
-+ __releases(rq->lock)
-+{
-+ struct rq *rq = this_rq();
-+ struct mm_struct *mm = rq->prev_mm;
-+ unsigned int prev_state;
-+
-+ /*
-+ * The previous task will have left us with a preempt_count of 2
-+ * because it left us after:
-+ *
-+ * schedule()
-+ * preempt_disable(); // 1
-+ * __schedule()
-+ * raw_spin_lock_irq(&rq->lock) // 2
-+ *
-+ * Also, see FORK_PREEMPT_COUNT.
-+ */
-+ if (WARN_ONCE(preempt_count() != 2*PREEMPT_DISABLE_OFFSET,
-+ "corrupted preempt_count: %s/%d/0x%x\n",
-+ current->comm, current->pid, preempt_count()))
-+ preempt_count_set(FORK_PREEMPT_COUNT);
-+
-+ rq->prev_mm = NULL;
-+
-+ /*
-+ * A task struct has one reference for the use as "current".
-+ * If a task dies, then it sets TASK_DEAD in tsk->state and calls
-+ * schedule one last time. The schedule call will never return, and
-+ * the scheduled task must drop that reference.
-+ *
-+ * We must observe prev->state before clearing prev->on_cpu (in
-+ * finish_task), otherwise a concurrent wakeup can get prev
-+ * running on another CPU and we could rave with its RUNNING -> DEAD
-+ * transition, resulting in a double drop.
-+ */
-+ prev_state = READ_ONCE(prev->__state);
-+ vtime_task_switch(prev);
-+ perf_event_task_sched_in(prev, current);
-+ finish_task(prev);
-+ tick_nohz_task_switch();
-+ finish_lock_switch(rq);
-+ finish_arch_post_lock_switch();
-+ kcov_finish_switch(current);
-+ /*
-+ * kmap_local_sched_out() is invoked with rq::lock held and
-+ * interrupts disabled. There is no requirement for that, but the
-+ * sched out code does not have an interrupt enabled section.
-+ * Restoring the maps on sched in does not require interrupts being
-+ * disabled either.
-+ */
-+ kmap_local_sched_in();
-+
-+ fire_sched_in_preempt_notifiers(current);
-+ /*
-+ * When switching through a kernel thread, the loop in
-+ * membarrier_{private,global}_expedited() may have observed that
-+ * kernel thread and not issued an IPI. It is therefore possible to
-+ * schedule between user->kernel->user threads without passing though
-+ * switch_mm(). Membarrier requires a barrier after storing to
-+ * rq->curr, before returning to userspace, so provide them here:
-+ *
-+ * - a full memory barrier for {PRIVATE,GLOBAL}_EXPEDITED, implicitly
-+ * provided by mmdrop(),
-+ * - a sync_core for SYNC_CORE.
-+ */
-+ if (mm) {
-+ membarrier_mm_sync_core_before_usermode(mm);
-+ mmdrop_sched(mm);
-+ }
-+ if (unlikely(prev_state == TASK_DEAD)) {
-+ /* Task is done with its stack. */
-+ put_task_stack(prev);
-+
-+ put_task_struct_rcu_user(prev);
-+ }
-+
-+ return rq;
-+}
-+
-+/**
-+ * schedule_tail - first thing a freshly forked thread must call.
-+ * @prev: the thread we just switched away from.
-+ */
-+asmlinkage __visible void schedule_tail(struct task_struct *prev)
-+ __releases(rq->lock)
-+{
-+ /*
-+ * New tasks start with FORK_PREEMPT_COUNT, see there and
-+ * finish_task_switch() for details.
-+ *
-+ * finish_task_switch() will drop rq->lock() and lower preempt_count
-+ * and the preempt_enable() will end up enabling preemption (on
-+ * PREEMPT_COUNT kernels).
-+ */
-+
-+ finish_task_switch(prev);
-+ preempt_enable();
-+
-+ if (current->set_child_tid)
-+ put_user(task_pid_vnr(current), current->set_child_tid);
-+
-+ calculate_sigpending();
-+}
-+
-+/*
-+ * context_switch - switch to the new MM and the new thread's register state.
-+ */
-+static __always_inline struct rq *
-+context_switch(struct rq *rq, struct task_struct *prev,
-+ struct task_struct *next)
-+{
-+ prepare_task_switch(rq, prev, next);
-+
-+ /*
-+ * For paravirt, this is coupled with an exit in switch_to to
-+ * combine the page table reload and the switch backend into
-+ * one hypercall.
-+ */
-+ arch_start_context_switch(prev);
-+
-+ /*
-+ * kernel -> kernel lazy + transfer active
-+ * user -> kernel lazy + mmgrab() active
-+ *
-+ * kernel -> user switch + mmdrop() active
-+ * user -> user switch
-+ *
-+ * switch_mm_cid() needs to be updated if the barriers provided
-+ * by context_switch() are modified.
-+ */
-+ if (!next->mm) { // to kernel
-+ enter_lazy_tlb(prev->active_mm, next);
-+
-+ next->active_mm = prev->active_mm;
-+ if (prev->mm) // from user
-+ mmgrab(prev->active_mm);
-+ else
-+ prev->active_mm = NULL;
-+ } else { // to user
-+ membarrier_switch_mm(rq, prev->active_mm, next->mm);
-+ /*
-+ * sys_membarrier() requires an smp_mb() between setting
-+ * rq->curr / membarrier_switch_mm() and returning to userspace.
-+ *
-+ * The below provides this either through switch_mm(), or in
-+ * case 'prev->active_mm == next->mm' through
-+ * finish_task_switch()'s mmdrop().
-+ */
-+ switch_mm_irqs_off(prev->active_mm, next->mm, next);
-+ lru_gen_use_mm(next->mm);
-+
-+ if (!prev->mm) { // from kernel
-+ /* will mmdrop() in finish_task_switch(). */
-+ rq->prev_mm = prev->active_mm;
-+ prev->active_mm = NULL;
-+ }
-+ }
-+
-+ /* switch_mm_cid() requires the memory barriers above. */
-+ switch_mm_cid(rq, prev, next);
-+
-+ prepare_lock_switch(rq, next);
-+
-+ /* Here we just switch the register state and the stack. */
-+ switch_to(prev, next, prev);
-+ barrier();
-+
-+ return finish_task_switch(prev);
-+}
-+
-+/*
-+ * nr_running, nr_uninterruptible and nr_context_switches:
-+ *
-+ * externally visible scheduler statistics: current number of runnable
-+ * threads, total number of context switches performed since bootup.
-+ */
-+unsigned int nr_running(void)
-+{
-+ unsigned int i, sum = 0;
-+
-+ for_each_online_cpu(i)
-+ sum += cpu_rq(i)->nr_running;
-+
-+ return sum;
-+}
-+
-+/*
-+ * Check if only the current task is running on the CPU.
-+ *
-+ * Caution: this function does not check that the caller has disabled
-+ * preemption, thus the result might have a time-of-check-to-time-of-use
-+ * race. The caller is responsible to use it correctly, for example:
-+ *
-+ * - from a non-preemptible section (of course)
-+ *
-+ * - from a thread that is bound to a single CPU
-+ *
-+ * - in a loop with very short iterations (e.g. a polling loop)
-+ */
-+bool single_task_running(void)
-+{
-+ return raw_rq()->nr_running == 1;
-+}
-+EXPORT_SYMBOL(single_task_running);
-+
-+unsigned long long nr_context_switches_cpu(int cpu)
-+{
-+ return cpu_rq(cpu)->nr_switches;
-+}
-+
-+unsigned long long nr_context_switches(void)
-+{
-+ int i;
-+ unsigned long long sum = 0;
-+
-+ for_each_possible_cpu(i)
-+ sum += cpu_rq(i)->nr_switches;
-+
-+ return sum;
-+}
-+
-+/*
-+ * Consumers of these two interfaces, like for example the cpuidle menu
-+ * governor, are using nonsensical data. Preferring shallow idle state selection
-+ * for a CPU that has IO-wait which might not even end up running the task when
-+ * it does become runnable.
-+ */
-+
-+unsigned int nr_iowait_cpu(int cpu)
-+{
-+ return atomic_read(&cpu_rq(cpu)->nr_iowait);
-+}
-+
-+/*
-+ * IO-wait accounting, and how it's mostly bollocks (on SMP).
-+ *
-+ * The idea behind IO-wait account is to account the idle time that we could
-+ * have spend running if it were not for IO. That is, if we were to improve the
-+ * storage performance, we'd have a proportional reduction in IO-wait time.
-+ *
-+ * This all works nicely on UP, where, when a task blocks on IO, we account
-+ * idle time as IO-wait, because if the storage were faster, it could've been
-+ * running and we'd not be idle.
-+ *
-+ * This has been extended to SMP, by doing the same for each CPU. This however
-+ * is broken.
-+ *
-+ * Imagine for instance the case where two tasks block on one CPU, only the one
-+ * CPU will have IO-wait accounted, while the other has regular idle. Even
-+ * though, if the storage were faster, both could've ran at the same time,
-+ * utilising both CPUs.
-+ *
-+ * This means, that when looking globally, the current IO-wait accounting on
-+ * SMP is a lower bound, by reason of under accounting.
-+ *
-+ * Worse, since the numbers are provided per CPU, they are sometimes
-+ * interpreted per CPU, and that is nonsensical. A blocked task isn't strictly
-+ * associated with any one particular CPU, it can wake to another CPU than it
-+ * blocked on. This means the per CPU IO-wait number is meaningless.
-+ *
-+ * Task CPU affinities can make all that even more 'interesting'.
-+ */
-+
-+unsigned int nr_iowait(void)
-+{
-+ unsigned int i, sum = 0;
-+
-+ for_each_possible_cpu(i)
-+ sum += nr_iowait_cpu(i);
-+
-+ return sum;
-+}
-+
-+#ifdef CONFIG_SMP
-+
-+/*
-+ * sched_exec - execve() is a valuable balancing opportunity, because at
-+ * this point the task has the smallest effective memory and cache
-+ * footprint.
-+ */
-+void sched_exec(void)
-+{
-+}
-+
-+#endif
-+
-+DEFINE_PER_CPU(struct kernel_stat, kstat);
-+DEFINE_PER_CPU(struct kernel_cpustat, kernel_cpustat);
-+
-+EXPORT_PER_CPU_SYMBOL(kstat);
-+EXPORT_PER_CPU_SYMBOL(kernel_cpustat);
-+
-+static inline void update_curr(struct rq *rq, struct task_struct *p)
-+{
-+ s64 ns = rq->clock_task - p->last_ran;
-+
-+ p->sched_time += ns;
-+ cgroup_account_cputime(p, ns);
-+ account_group_exec_runtime(p, ns);
-+
-+ p->time_slice -= ns;
-+ p->last_ran = rq->clock_task;
-+}
-+
-+/*
-+ * Return accounted runtime for the task.
-+ * Return separately the current's pending runtime that have not been
-+ * accounted yet.
-+ */
-+unsigned long long task_sched_runtime(struct task_struct *p)
-+{
-+ unsigned long flags;
-+ struct rq *rq;
-+ raw_spinlock_t *lock;
-+ u64 ns;
-+
-+#if defined(CONFIG_64BIT) && defined(CONFIG_SMP)
-+ /*
-+ * 64-bit doesn't need locks to atomically read a 64-bit value.
-+ * So we have a optimization chance when the task's delta_exec is 0.
-+ * Reading ->on_cpu is racy, but this is ok.
-+ *
-+ * If we race with it leaving CPU, we'll take a lock. So we're correct.
-+ * If we race with it entering CPU, unaccounted time is 0. This is
-+ * indistinguishable from the read occurring a few cycles earlier.
-+ * If we see ->on_cpu without ->on_rq, the task is leaving, and has
-+ * been accounted, so we're correct here as well.
-+ */
-+ if (!p->on_cpu || !task_on_rq_queued(p))
-+ return tsk_seruntime(p);
-+#endif
-+
-+ rq = task_access_lock_irqsave(p, &lock, &flags);
-+ /*
-+ * Must be ->curr _and_ ->on_rq. If dequeued, we would
-+ * project cycles that may never be accounted to this
-+ * thread, breaking clock_gettime().
-+ */
-+ if (p == rq->curr && task_on_rq_queued(p)) {
-+ update_rq_clock(rq);
-+ update_curr(rq, p);
-+ }
-+ ns = tsk_seruntime(p);
-+ task_access_unlock_irqrestore(p, lock, &flags);
-+
-+ return ns;
-+}
-+
-+/* This manages tasks that have run out of timeslice during a scheduler_tick */
-+static inline void scheduler_task_tick(struct rq *rq)
-+{
-+ struct task_struct *p = rq->curr;
-+
-+ if (is_idle_task(p))
-+ return;
-+
-+ update_curr(rq, p);
-+ cpufreq_update_util(rq, 0);
-+
-+ /*
-+ * Tasks have less than RESCHED_NS of time slice left they will be
-+ * rescheduled.
-+ */
-+ if (p->time_slice >= RESCHED_NS)
-+ return;
-+ set_tsk_need_resched(p);
-+ set_preempt_need_resched();
-+}
-+
-+#ifdef CONFIG_SCHED_DEBUG
-+static u64 cpu_resched_latency(struct rq *rq)
-+{
-+ int latency_warn_ms = READ_ONCE(sysctl_resched_latency_warn_ms);
-+ u64 resched_latency, now = rq_clock(rq);
-+ static bool warned_once;
-+
-+ if (sysctl_resched_latency_warn_once && warned_once)
-+ return 0;
-+
-+ if (!need_resched() || !latency_warn_ms)
-+ return 0;
-+
-+ if (system_state == SYSTEM_BOOTING)
-+ return 0;
-+
-+ if (!rq->last_seen_need_resched_ns) {
-+ rq->last_seen_need_resched_ns = now;
-+ rq->ticks_without_resched = 0;
-+ return 0;
-+ }
-+
-+ rq->ticks_without_resched++;
-+ resched_latency = now - rq->last_seen_need_resched_ns;
-+ if (resched_latency <= latency_warn_ms * NSEC_PER_MSEC)
-+ return 0;
-+
-+ warned_once = true;
-+
-+ return resched_latency;
-+}
-+
-+static int __init setup_resched_latency_warn_ms(char *str)
-+{
-+ long val;
-+
-+ if ((kstrtol(str, 0, &val))) {
-+ pr_warn("Unable to set resched_latency_warn_ms\n");
-+ return 1;
-+ }
-+
-+ sysctl_resched_latency_warn_ms = val;
-+ return 1;
-+}
-+__setup("resched_latency_warn_ms=", setup_resched_latency_warn_ms);
-+#else
-+static inline u64 cpu_resched_latency(struct rq *rq) { return 0; }
-+#endif /* CONFIG_SCHED_DEBUG */
-+
-+/*
-+ * This function gets called by the timer code, with HZ frequency.
-+ * We call it with interrupts disabled.
-+ */
-+void scheduler_tick(void)
-+{
-+ int cpu __maybe_unused = smp_processor_id();
-+ struct rq *rq = cpu_rq(cpu);
-+ struct task_struct *curr = rq->curr;
-+ u64 resched_latency;
-+
-+ if (housekeeping_cpu(cpu, HK_TYPE_TICK))
-+ arch_scale_freq_tick();
-+
-+ sched_clock_tick();
-+
-+ raw_spin_lock(&rq->lock);
-+ update_rq_clock(rq);
-+
-+ scheduler_task_tick(rq);
-+ if (sched_feat(LATENCY_WARN))
-+ resched_latency = cpu_resched_latency(rq);
-+ calc_global_load_tick(rq);
-+
-+ task_tick_mm_cid(rq, rq->curr);
-+
-+ raw_spin_unlock(&rq->lock);
-+
-+ if (sched_feat(LATENCY_WARN) && resched_latency)
-+ resched_latency_warn(cpu, resched_latency);
-+
-+ perf_event_task_tick();
-+
-+ if (curr->flags & PF_WQ_WORKER)
-+ wq_worker_tick(curr);
-+}
-+
-+#ifdef CONFIG_SCHED_SMT
-+static inline int sg_balance_cpu_stop(void *data)
-+{
-+ struct rq *rq = this_rq();
-+ struct task_struct *p = data;
-+ cpumask_t tmp;
-+ unsigned long flags;
-+
-+ local_irq_save(flags);
-+
-+ raw_spin_lock(&p->pi_lock);
-+ raw_spin_lock(&rq->lock);
-+
-+ rq->active_balance = 0;
-+ /* _something_ may have changed the task, double check again */
-+ if (task_on_rq_queued(p) && task_rq(p) == rq &&
-+ cpumask_and(&tmp, p->cpus_ptr, &sched_sg_idle_mask) &&
-+ !is_migration_disabled(p)) {
-+ int cpu = cpu_of(rq);
-+ int dcpu = __best_mask_cpu(&tmp, per_cpu(sched_cpu_llc_mask, cpu));
-+ rq = move_queued_task(rq, p, dcpu);
-+ }
-+
-+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock(&p->pi_lock);
-+
-+ local_irq_restore(flags);
-+
-+ return 0;
-+}
-+
-+/* sg_balance_trigger - trigger slibing group balance for @cpu */
-+static inline int sg_balance_trigger(const int cpu)
-+{
-+ struct rq *rq= cpu_rq(cpu);
-+ unsigned long flags;
-+ struct task_struct *curr;
-+ int res;
-+
-+ if (!raw_spin_trylock_irqsave(&rq->lock, flags))
-+ return 0;
-+ curr = rq->curr;
-+ res = (!is_idle_task(curr)) && (1 == rq->nr_running) &&\
-+ cpumask_intersects(curr->cpus_ptr, &sched_sg_idle_mask) &&\
-+ !is_migration_disabled(curr) && (!rq->active_balance);
-+
-+ if (res)
-+ rq->active_balance = 1;
-+
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+
-+ if (res)
-+ stop_one_cpu_nowait(cpu, sg_balance_cpu_stop, curr,
-+ &rq->active_balance_work);
-+ return res;
-+}
-+
-+/*
-+ * sg_balance - slibing group balance check for run queue @rq
-+ */
-+static inline void sg_balance(struct rq *rq, int cpu)
-+{
-+ cpumask_t chk;
-+
-+ /* exit when cpu is offline */
-+ if (unlikely(!rq->online))
-+ return;
-+
-+ /*
-+ * Only cpu in slibing idle group will do the checking and then
-+ * find potential cpus which can migrate the current running task
-+ */
-+ if (cpumask_test_cpu(cpu, &sched_sg_idle_mask) &&
-+ cpumask_andnot(&chk, cpu_online_mask, sched_idle_mask) &&
-+ cpumask_andnot(&chk, &chk, &sched_rq_pending_mask)) {
-+ int i;
-+
-+ for_each_cpu_wrap(i, &chk, cpu) {
-+ if (!cpumask_intersects(cpu_smt_mask(i), sched_idle_mask) &&\
-+ sg_balance_trigger(i))
-+ return;
-+ }
-+ }
-+}
-+#endif /* CONFIG_SCHED_SMT */
-+
-+#ifdef CONFIG_NO_HZ_FULL
-+
-+struct tick_work {
-+ int cpu;
-+ atomic_t state;
-+ struct delayed_work work;
-+};
-+/* Values for ->state, see diagram below. */
-+#define TICK_SCHED_REMOTE_OFFLINE 0
-+#define TICK_SCHED_REMOTE_OFFLINING 1
-+#define TICK_SCHED_REMOTE_RUNNING 2
-+
-+/*
-+ * State diagram for ->state:
-+ *
-+ *
-+ * TICK_SCHED_REMOTE_OFFLINE
-+ * | ^
-+ * | |
-+ * | | sched_tick_remote()
-+ * | |
-+ * | |
-+ * +--TICK_SCHED_REMOTE_OFFLINING
-+ * | ^
-+ * | |
-+ * sched_tick_start() | | sched_tick_stop()
-+ * | |
-+ * V |
-+ * TICK_SCHED_REMOTE_RUNNING
-+ *
-+ *
-+ * Other transitions get WARN_ON_ONCE(), except that sched_tick_remote()
-+ * and sched_tick_start() are happy to leave the state in RUNNING.
-+ */
-+
-+static struct tick_work __percpu *tick_work_cpu;
-+
-+static void sched_tick_remote(struct work_struct *work)
-+{
-+ struct delayed_work *dwork = to_delayed_work(work);
-+ struct tick_work *twork = container_of(dwork, struct tick_work, work);
-+ int cpu = twork->cpu;
-+ struct rq *rq = cpu_rq(cpu);
-+ int os;
-+
-+ /*
-+ * Handle the tick only if it appears the remote CPU is running in full
-+ * dynticks mode. The check is racy by nature, but missing a tick or
-+ * having one too much is no big deal because the scheduler tick updates
-+ * statistics and checks timeslices in a time-independent way, regardless
-+ * of when exactly it is running.
-+ */
-+ if (tick_nohz_tick_stopped_cpu(cpu)) {
-+ guard(raw_spinlock_irqsave)(&rq->lock);
-+ struct task_struct *curr = rq->curr;
-+
-+ if (cpu_online(cpu)) {
-+ update_rq_clock(rq);
-+
-+ if (!is_idle_task(curr)) {
-+ /*
-+ * Make sure the next tick runs within a
-+ * reasonable amount of time.
-+ */
-+ u64 delta = rq_clock_task(rq) - curr->last_ran;
-+ WARN_ON_ONCE(delta > (u64)NSEC_PER_SEC * 3);
-+ }
-+ scheduler_task_tick(rq);
-+
-+ calc_load_nohz_remote(rq);
-+ }
-+ }
-+
-+ /*
-+ * Run the remote tick once per second (1Hz). This arbitrary
-+ * frequency is large enough to avoid overload but short enough
-+ * to keep scheduler internal stats reasonably up to date. But
-+ * first update state to reflect hotplug activity if required.
-+ */
-+ os = atomic_fetch_add_unless(&twork->state, -1, TICK_SCHED_REMOTE_RUNNING);
-+ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_OFFLINE);
-+ if (os == TICK_SCHED_REMOTE_RUNNING)
-+ queue_delayed_work(system_unbound_wq, dwork, HZ);
-+}
-+
-+static void sched_tick_start(int cpu)
-+{
-+ int os;
-+ struct tick_work *twork;
-+
-+ if (housekeeping_cpu(cpu, HK_TYPE_TICK))
-+ return;
-+
-+ WARN_ON_ONCE(!tick_work_cpu);
-+
-+ twork = per_cpu_ptr(tick_work_cpu, cpu);
-+ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_RUNNING);
-+ WARN_ON_ONCE(os == TICK_SCHED_REMOTE_RUNNING);
-+ if (os == TICK_SCHED_REMOTE_OFFLINE) {
-+ twork->cpu = cpu;
-+ INIT_DELAYED_WORK(&twork->work, sched_tick_remote);
-+ queue_delayed_work(system_unbound_wq, &twork->work, HZ);
-+ }
-+}
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+static void sched_tick_stop(int cpu)
-+{
-+ struct tick_work *twork;
-+ int os;
-+
-+ if (housekeeping_cpu(cpu, HK_TYPE_TICK))
-+ return;
-+
-+ WARN_ON_ONCE(!tick_work_cpu);
-+
-+ twork = per_cpu_ptr(tick_work_cpu, cpu);
-+ /* There cannot be competing actions, but don't rely on stop-machine. */
-+ os = atomic_xchg(&twork->state, TICK_SCHED_REMOTE_OFFLINING);
-+ WARN_ON_ONCE(os != TICK_SCHED_REMOTE_RUNNING);
-+ /* Don't cancel, as this would mess up the state machine. */
-+}
-+#endif /* CONFIG_HOTPLUG_CPU */
-+
-+int __init sched_tick_offload_init(void)
-+{
-+ tick_work_cpu = alloc_percpu(struct tick_work);
-+ BUG_ON(!tick_work_cpu);
-+ return 0;
-+}
-+
-+#else /* !CONFIG_NO_HZ_FULL */
-+static inline void sched_tick_start(int cpu) { }
-+static inline void sched_tick_stop(int cpu) { }
-+#endif
-+
-+#if defined(CONFIG_PREEMPTION) && (defined(CONFIG_DEBUG_PREEMPT) || \
-+ defined(CONFIG_PREEMPT_TRACER))
-+/*
-+ * If the value passed in is equal to the current preempt count
-+ * then we just disabled preemption. Start timing the latency.
-+ */
-+static inline void preempt_latency_start(int val)
-+{
-+ if (preempt_count() == val) {
-+ unsigned long ip = get_lock_parent_ip();
-+#ifdef CONFIG_DEBUG_PREEMPT
-+ current->preempt_disable_ip = ip;
-+#endif
-+ trace_preempt_off(CALLER_ADDR0, ip);
-+ }
-+}
-+
-+void preempt_count_add(int val)
-+{
-+#ifdef CONFIG_DEBUG_PREEMPT
-+ /*
-+ * Underflow?
-+ */
-+ if (DEBUG_LOCKS_WARN_ON((preempt_count() < 0)))
-+ return;
-+#endif
-+ __preempt_count_add(val);
-+#ifdef CONFIG_DEBUG_PREEMPT
-+ /*
-+ * Spinlock count overflowing soon?
-+ */
-+ DEBUG_LOCKS_WARN_ON((preempt_count() & PREEMPT_MASK) >=
-+ PREEMPT_MASK - 10);
-+#endif
-+ preempt_latency_start(val);
-+}
-+EXPORT_SYMBOL(preempt_count_add);
-+NOKPROBE_SYMBOL(preempt_count_add);
-+
-+/*
-+ * If the value passed in equals to the current preempt count
-+ * then we just enabled preemption. Stop timing the latency.
-+ */
-+static inline void preempt_latency_stop(int val)
-+{
-+ if (preempt_count() == val)
-+ trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip());
-+}
-+
-+void preempt_count_sub(int val)
-+{
-+#ifdef CONFIG_DEBUG_PREEMPT
-+ /*
-+ * Underflow?
-+ */
-+ if (DEBUG_LOCKS_WARN_ON(val > preempt_count()))
-+ return;
-+ /*
-+ * Is the spinlock portion underflowing?
-+ */
-+ if (DEBUG_LOCKS_WARN_ON((val < PREEMPT_MASK) &&
-+ !(preempt_count() & PREEMPT_MASK)))
-+ return;
-+#endif
-+
-+ preempt_latency_stop(val);
-+ __preempt_count_sub(val);
-+}
-+EXPORT_SYMBOL(preempt_count_sub);
-+NOKPROBE_SYMBOL(preempt_count_sub);
-+
-+#else
-+static inline void preempt_latency_start(int val) { }
-+static inline void preempt_latency_stop(int val) { }
-+#endif
-+
-+static inline unsigned long get_preempt_disable_ip(struct task_struct *p)
-+{
-+#ifdef CONFIG_DEBUG_PREEMPT
-+ return p->preempt_disable_ip;
-+#else
-+ return 0;
-+#endif
-+}
-+
-+/*
-+ * Print scheduling while atomic bug:
-+ */
-+static noinline void __schedule_bug(struct task_struct *prev)
-+{
-+ /* Save this before calling printk(), since that will clobber it */
-+ unsigned long preempt_disable_ip = get_preempt_disable_ip(current);
-+
-+ if (oops_in_progress)
-+ return;
-+
-+ printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n",
-+ prev->comm, prev->pid, preempt_count());
-+
-+ debug_show_held_locks(prev);
-+ print_modules();
-+ if (irqs_disabled())
-+ print_irqtrace_events(prev);
-+ if (IS_ENABLED(CONFIG_DEBUG_PREEMPT)) {
-+ pr_err("Preemption disabled at:");
-+ print_ip_sym(KERN_ERR, preempt_disable_ip);
-+ }
-+ check_panic_on_warn("scheduling while atomic");
-+
-+ dump_stack();
-+ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
-+}
-+
-+/*
-+ * Various schedule()-time debugging checks and statistics:
-+ */
-+static inline void schedule_debug(struct task_struct *prev, bool preempt)
-+{
-+#ifdef CONFIG_SCHED_STACK_END_CHECK
-+ if (task_stack_end_corrupted(prev))
-+ panic("corrupted stack end detected inside scheduler\n");
-+
-+ if (task_scs_end_corrupted(prev))
-+ panic("corrupted shadow stack detected inside scheduler\n");
-+#endif
-+
-+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
-+ if (!preempt && READ_ONCE(prev->__state) && prev->non_block_count) {
-+ printk(KERN_ERR "BUG: scheduling in a non-blocking section: %s/%d/%i\n",
-+ prev->comm, prev->pid, prev->non_block_count);
-+ dump_stack();
-+ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
-+ }
-+#endif
-+
-+ if (unlikely(in_atomic_preempt_off())) {
-+ __schedule_bug(prev);
-+ preempt_count_set(PREEMPT_DISABLED);
-+ }
-+ rcu_sleep_check();
-+ SCHED_WARN_ON(ct_state() == CONTEXT_USER);
-+
-+ profile_hit(SCHED_PROFILING, __builtin_return_address(0));
-+
-+ schedstat_inc(this_rq()->sched_count);
-+}
-+
-+#ifdef ALT_SCHED_DEBUG
-+void alt_sched_debug(void)
-+{
-+ printk(KERN_INFO "sched: pending: 0x%04lx, idle: 0x%04lx, sg_idle: 0x%04lx\n",
-+ sched_rq_pending_mask.bits[0],
-+ sched_idle_mask->bits[0],
-+ sched_sg_idle_mask.bits[0]);
-+}
-+#else
-+inline void alt_sched_debug(void) {}
-+#endif
-+
-+#ifdef CONFIG_SMP
-+
-+#ifdef CONFIG_PREEMPT_RT
-+#define SCHED_NR_MIGRATE_BREAK 8
-+#else
-+#define SCHED_NR_MIGRATE_BREAK 32
-+#endif
-+
-+const_debug unsigned int sysctl_sched_nr_migrate = SCHED_NR_MIGRATE_BREAK;
-+
-+/*
-+ * Migrate pending tasks in @rq to @dest_cpu
-+ */
-+static inline int
-+migrate_pending_tasks(struct rq *rq, struct rq *dest_rq, const int dest_cpu)
-+{
-+ struct task_struct *p, *skip = rq->curr;
-+ int nr_migrated = 0;
-+ int nr_tries = min(rq->nr_running / 2, sysctl_sched_nr_migrate);
-+
-+ /* WA to check rq->curr is still on rq */
-+ if (!task_on_rq_queued(skip))
-+ return 0;
-+
-+ while (skip != rq->idle && nr_tries &&
-+ (p = sched_rq_next_task(skip, rq)) != rq->idle) {
-+ skip = sched_rq_next_task(p, rq);
-+ if (cpumask_test_cpu(dest_cpu, p->cpus_ptr)) {
-+ __SCHED_DEQUEUE_TASK(p, rq, 0, );
-+ set_task_cpu(p, dest_cpu);
-+ sched_task_sanity_check(p, dest_rq);
-+ sched_mm_cid_migrate_to(dest_rq, p, cpu_of(rq));
-+ __SCHED_ENQUEUE_TASK(p, dest_rq, 0);
-+ nr_migrated++;
-+ }
-+ nr_tries--;
-+ }
-+
-+ return nr_migrated;
-+}
-+
-+static inline int take_other_rq_tasks(struct rq *rq, int cpu)
-+{
-+ struct cpumask *topo_mask, *end_mask;
-+
-+ if (unlikely(!rq->online))
-+ return 0;
-+
-+ if (cpumask_empty(&sched_rq_pending_mask))
-+ return 0;
-+
-+ topo_mask = per_cpu(sched_cpu_topo_masks, cpu) + 1;
-+ end_mask = per_cpu(sched_cpu_topo_end_mask, cpu);
-+ do {
-+ int i;
-+ for_each_cpu_and(i, &sched_rq_pending_mask, topo_mask) {
-+ int nr_migrated;
-+ struct rq *src_rq;
-+
-+ src_rq = cpu_rq(i);
-+ if (!do_raw_spin_trylock(&src_rq->lock))
-+ continue;
-+ spin_acquire(&src_rq->lock.dep_map,
-+ SINGLE_DEPTH_NESTING, 1, _RET_IP_);
-+
-+ if ((nr_migrated = migrate_pending_tasks(src_rq, rq, cpu))) {
-+ src_rq->nr_running -= nr_migrated;
-+ if (src_rq->nr_running < 2)
-+ cpumask_clear_cpu(i, &sched_rq_pending_mask);
-+
-+ spin_release(&src_rq->lock.dep_map, _RET_IP_);
-+ do_raw_spin_unlock(&src_rq->lock);
-+
-+ rq->nr_running += nr_migrated;
-+ if (rq->nr_running > 1)
-+ cpumask_set_cpu(cpu, &sched_rq_pending_mask);
-+
-+ update_sched_preempt_mask(rq);
-+ cpufreq_update_util(rq, 0);
-+
-+ return 1;
-+ }
-+
-+ spin_release(&src_rq->lock.dep_map, _RET_IP_);
-+ do_raw_spin_unlock(&src_rq->lock);
-+ }
-+ } while (++topo_mask < end_mask);
-+
-+ return 0;
-+}
-+#endif
-+
-+static inline void time_slice_expired(struct task_struct *p, struct rq *rq)
-+{
-+ p->time_slice = sysctl_sched_base_slice;
-+
-+ sched_task_renew(p, rq);
-+
-+ if (SCHED_FIFO != p->policy && task_on_rq_queued(p))
-+ requeue_task(p, rq, task_sched_prio_idx(p, rq));
-+}
-+
-+/*
-+ * Timeslices below RESCHED_NS are considered as good as expired as there's no
-+ * point rescheduling when there's so little time left.
-+ */
-+static inline void check_curr(struct task_struct *p, struct rq *rq)
-+{
-+ if (unlikely(rq->idle == p))
-+ return;
-+
-+ update_curr(rq, p);
-+
-+ if (p->time_slice < RESCHED_NS)
-+ time_slice_expired(p, rq);
-+}
-+
-+static inline struct task_struct *
-+choose_next_task(struct rq *rq, int cpu)
-+{
-+ struct task_struct *next;
-+
-+ if (unlikely(rq->skip)) {
-+ next = rq_runnable_task(rq);
-+ if (next == rq->idle) {
-+#ifdef CONFIG_SMP
-+ if (!take_other_rq_tasks(rq, cpu)) {
-+#endif
-+ rq->skip = NULL;
-+ schedstat_inc(rq->sched_goidle);
-+ return next;
-+#ifdef CONFIG_SMP
-+ }
-+ next = rq_runnable_task(rq);
-+#endif
-+ }
-+ rq->skip = NULL;
-+#ifdef CONFIG_HIGH_RES_TIMERS
-+ hrtick_start(rq, next->time_slice);
-+#endif
-+ return next;
-+ }
-+
-+ next = sched_rq_first_task(rq);
-+ if (next == rq->idle) {
-+#ifdef CONFIG_SMP
-+ if (!take_other_rq_tasks(rq, cpu)) {
-+#endif
-+ schedstat_inc(rq->sched_goidle);
-+ /*printk(KERN_INFO "sched: choose_next_task(%d) idle %px\n", cpu, next);*/
-+ return next;
-+#ifdef CONFIG_SMP
-+ }
-+ next = sched_rq_first_task(rq);
-+#endif
-+ }
-+#ifdef CONFIG_HIGH_RES_TIMERS
-+ hrtick_start(rq, next->time_slice);
-+#endif
-+ /*printk(KERN_INFO "sched: choose_next_task(%d) next %px\n", cpu, next);*/
-+ return next;
-+}
-+
-+/*
-+ * Constants for the sched_mode argument of __schedule().
-+ *
-+ * The mode argument allows RT enabled kernels to differentiate a
-+ * preemption from blocking on an 'sleeping' spin/rwlock. Note that
-+ * SM_MASK_PREEMPT for !RT has all bits set, which allows the compiler to
-+ * optimize the AND operation out and just check for zero.
-+ */
-+#define SM_NONE 0x0
-+#define SM_PREEMPT 0x1
-+#define SM_RTLOCK_WAIT 0x2
-+
-+#ifndef CONFIG_PREEMPT_RT
-+# define SM_MASK_PREEMPT (~0U)
-+#else
-+# define SM_MASK_PREEMPT SM_PREEMPT
-+#endif
-+
-+/*
-+ * schedule() is the main scheduler function.
-+ *
-+ * The main means of driving the scheduler and thus entering this function are:
-+ *
-+ * 1. Explicit blocking: mutex, semaphore, waitqueue, etc.
-+ *
-+ * 2. TIF_NEED_RESCHED flag is checked on interrupt and userspace return
-+ * paths. For example, see arch/x86/entry_64.S.
-+ *
-+ * To drive preemption between tasks, the scheduler sets the flag in timer
-+ * interrupt handler scheduler_tick().
-+ *
-+ * 3. Wakeups don't really cause entry into schedule(). They add a
-+ * task to the run-queue and that's it.
-+ *
-+ * Now, if the new task added to the run-queue preempts the current
-+ * task, then the wakeup sets TIF_NEED_RESCHED and schedule() gets
-+ * called on the nearest possible occasion:
-+ *
-+ * - If the kernel is preemptible (CONFIG_PREEMPTION=y):
-+ *
-+ * - in syscall or exception context, at the next outmost
-+ * preempt_enable(). (this might be as soon as the wake_up()'s
-+ * spin_unlock()!)
-+ *
-+ * - in IRQ context, return from interrupt-handler to
-+ * preemptible context
-+ *
-+ * - If the kernel is not preemptible (CONFIG_PREEMPTION is not set)
-+ * then at the next:
-+ *
-+ * - cond_resched() call
-+ * - explicit schedule() call
-+ * - return from syscall or exception to user-space
-+ * - return from interrupt-handler to user-space
-+ *
-+ * WARNING: must be called with preemption disabled!
-+ */
-+static void __sched notrace __schedule(unsigned int sched_mode)
-+{
-+ struct task_struct *prev, *next;
-+ unsigned long *switch_count;
-+ unsigned long prev_state;
-+ struct rq *rq;
-+ int cpu;
-+
-+ cpu = smp_processor_id();
-+ rq = cpu_rq(cpu);
-+ prev = rq->curr;
-+
-+ schedule_debug(prev, !!sched_mode);
-+
-+ /* by passing sched_feat(HRTICK) checking which Alt schedule FW doesn't support */
-+ hrtick_clear(rq);
-+
-+ local_irq_disable();
-+ rcu_note_context_switch(!!sched_mode);
-+
-+ /*
-+ * Make sure that signal_pending_state()->signal_pending() below
-+ * can't be reordered with __set_current_state(TASK_INTERRUPTIBLE)
-+ * done by the caller to avoid the race with signal_wake_up():
-+ *
-+ * __set_current_state(@state) signal_wake_up()
-+ * schedule() set_tsk_thread_flag(p, TIF_SIGPENDING)
-+ * wake_up_state(p, state)
-+ * LOCK rq->lock LOCK p->pi_state
-+ * smp_mb__after_spinlock() smp_mb__after_spinlock()
-+ * if (signal_pending_state()) if (p->state & @state)
-+ *
-+ * Also, the membarrier system call requires a full memory barrier
-+ * after coming from user-space, before storing to rq->curr.
-+ */
-+ raw_spin_lock(&rq->lock);
-+ smp_mb__after_spinlock();
-+
-+ update_rq_clock(rq);
-+
-+ switch_count = &prev->nivcsw;
-+ /*
-+ * We must load prev->state once (task_struct::state is volatile), such
-+ * that we form a control dependency vs deactivate_task() below.
-+ */
-+ prev_state = READ_ONCE(prev->__state);
-+ if (!(sched_mode & SM_MASK_PREEMPT) && prev_state) {
-+ if (signal_pending_state(prev_state, prev)) {
-+ WRITE_ONCE(prev->__state, TASK_RUNNING);
-+ } else {
-+ prev->sched_contributes_to_load =
-+ (prev_state & TASK_UNINTERRUPTIBLE) &&
-+ !(prev_state & TASK_NOLOAD) &&
-+ !(prev_state & TASK_FROZEN);
-+
-+ if (prev->sched_contributes_to_load)
-+ rq->nr_uninterruptible++;
-+
-+ /*
-+ * __schedule() ttwu()
-+ * prev_state = prev->state; if (p->on_rq && ...)
-+ * if (prev_state) goto out;
-+ * p->on_rq = 0; smp_acquire__after_ctrl_dep();
-+ * p->state = TASK_WAKING
-+ *
-+ * Where __schedule() and ttwu() have matching control dependencies.
-+ *
-+ * After this, schedule() must not care about p->state any more.
-+ */
-+ sched_task_deactivate(prev, rq);
-+ deactivate_task(prev, rq);
-+
-+ if (prev->in_iowait) {
-+ atomic_inc(&rq->nr_iowait);
-+ delayacct_blkio_start();
-+ }
-+ }
-+ switch_count = &prev->nvcsw;
-+ }
-+
-+ check_curr(prev, rq);
-+
-+ next = choose_next_task(rq, cpu);
-+ clear_tsk_need_resched(prev);
-+ clear_preempt_need_resched();
-+#ifdef CONFIG_SCHED_DEBUG
-+ rq->last_seen_need_resched_ns = 0;
-+#endif
-+
-+ if (likely(prev != next)) {
-+#ifdef CONFIG_SCHED_BMQ
-+ rq->last_ts_switch = rq->clock;
-+#endif
-+ next->last_ran = rq->clock_task;
-+
-+ /*printk(KERN_INFO "sched: %px -> %px\n", prev, next);*/
-+ rq->nr_switches++;
-+ /*
-+ * RCU users of rcu_dereference(rq->curr) may not see
-+ * changes to task_struct made by pick_next_task().
-+ */
-+ RCU_INIT_POINTER(rq->curr, next);
-+ /*
-+ * The membarrier system call requires each architecture
-+ * to have a full memory barrier after updating
-+ * rq->curr, before returning to user-space.
-+ *
-+ * Here are the schemes providing that barrier on the
-+ * various architectures:
-+ * - mm ? switch_mm() : mmdrop() for x86, s390, sparc, PowerPC.
-+ * switch_mm() rely on membarrier_arch_switch_mm() on PowerPC.
-+ * - finish_lock_switch() for weakly-ordered
-+ * architectures where spin_unlock is a full barrier,
-+ * - switch_to() for arm64 (weakly-ordered, spin_unlock
-+ * is a RELEASE barrier),
-+ */
-+ ++*switch_count;
-+
-+ trace_sched_switch(sched_mode & SM_MASK_PREEMPT, prev, next, prev_state);
-+
-+ /* Also unlocks the rq: */
-+ rq = context_switch(rq, prev, next);
-+
-+ cpu = cpu_of(rq);
-+ } else {
-+ __balance_callbacks(rq);
-+ raw_spin_unlock_irq(&rq->lock);
-+ }
-+
-+#ifdef CONFIG_SCHED_SMT
-+ sg_balance(rq, cpu);
-+#endif
-+}
-+
-+void __noreturn do_task_dead(void)
-+{
-+ /* Causes final put_task_struct in finish_task_switch(): */
-+ set_special_state(TASK_DEAD);
-+
-+ /* Tell freezer to ignore us: */
-+ current->flags |= PF_NOFREEZE;
-+
-+ __schedule(SM_NONE);
-+ BUG();
-+
-+ /* Avoid "noreturn function does return" - but don't continue if BUG() is a NOP: */
-+ for (;;)
-+ cpu_relax();
-+}
-+
-+static inline void sched_submit_work(struct task_struct *tsk)
-+{
-+ static DEFINE_WAIT_OVERRIDE_MAP(sched_map, LD_WAIT_CONFIG);
-+ unsigned int task_flags;
-+
-+ /*
-+ * Establish LD_WAIT_CONFIG context to ensure none of the code called
-+ * will use a blocking primitive -- which would lead to recursion.
-+ */
-+ lock_map_acquire_try(&sched_map);
-+
-+ task_flags = tsk->flags;
-+ /*
-+ * If a worker goes to sleep, notify and ask workqueue whether it
-+ * wants to wake up a task to maintain concurrency.
-+ */
-+ if (task_flags & PF_WQ_WORKER)
-+ wq_worker_sleeping(tsk);
-+ else if (task_flags & PF_IO_WORKER)
-+ io_wq_worker_sleeping(tsk);
-+
-+ /*
-+ * spinlock and rwlock must not flush block requests. This will
-+ * deadlock if the callback attempts to acquire a lock which is
-+ * already acquired.
-+ */
-+ SCHED_WARN_ON(current->__state & TASK_RTLOCK_WAIT);
-+
-+ /*
-+ * If we are going to sleep and we have plugged IO queued,
-+ * make sure to submit it to avoid deadlocks.
-+ */
-+ blk_flush_plug(tsk->plug, true);
-+
-+ lock_map_release(&sched_map);
-+}
-+
-+static void sched_update_worker(struct task_struct *tsk)
-+{
-+ if (tsk->flags & (PF_WQ_WORKER | PF_IO_WORKER)) {
-+ if (tsk->flags & PF_WQ_WORKER)
-+ wq_worker_running(tsk);
-+ else
-+ io_wq_worker_running(tsk);
-+ }
-+}
-+
-+static __always_inline void __schedule_loop(unsigned int sched_mode)
-+{
-+ do {
-+ preempt_disable();
-+ __schedule(sched_mode);
-+ sched_preempt_enable_no_resched();
-+ } while (need_resched());
-+}
-+
-+asmlinkage __visible void __sched schedule(void)
-+{
-+ struct task_struct *tsk = current;
-+
-+#ifdef CONFIG_RT_MUTEXES
-+ lockdep_assert(!tsk->sched_rt_mutex);
-+#endif
-+
-+ if (!task_is_running(tsk))
-+ sched_submit_work(tsk);
-+ __schedule_loop(SM_NONE);
-+ sched_update_worker(tsk);
-+}
-+EXPORT_SYMBOL(schedule);
-+
-+/*
-+ * synchronize_rcu_tasks() makes sure that no task is stuck in preempted
-+ * state (have scheduled out non-voluntarily) by making sure that all
-+ * tasks have either left the run queue or have gone into user space.
-+ * As idle tasks do not do either, they must not ever be preempted
-+ * (schedule out non-voluntarily).
-+ *
-+ * schedule_idle() is similar to schedule_preempt_disable() except that it
-+ * never enables preemption because it does not call sched_submit_work().
-+ */
-+void __sched schedule_idle(void)
-+{
-+ /*
-+ * As this skips calling sched_submit_work(), which the idle task does
-+ * regardless because that function is a nop when the task is in a
-+ * TASK_RUNNING state, make sure this isn't used someplace that the
-+ * current task can be in any other state. Note, idle is always in the
-+ * TASK_RUNNING state.
-+ */
-+ WARN_ON_ONCE(current->__state);
-+ do {
-+ __schedule(SM_NONE);
-+ } while (need_resched());
-+}
-+
-+#if defined(CONFIG_CONTEXT_TRACKING_USER) && !defined(CONFIG_HAVE_CONTEXT_TRACKING_USER_OFFSTACK)
-+asmlinkage __visible void __sched schedule_user(void)
-+{
-+ /*
-+ * If we come here after a random call to set_need_resched(),
-+ * or we have been woken up remotely but the IPI has not yet arrived,
-+ * we haven't yet exited the RCU idle mode. Do it here manually until
-+ * we find a better solution.
-+ *
-+ * NB: There are buggy callers of this function. Ideally we
-+ * should warn if prev_state != CONTEXT_USER, but that will trigger
-+ * too frequently to make sense yet.
-+ */
-+ enum ctx_state prev_state = exception_enter();
-+ schedule();
-+ exception_exit(prev_state);
-+}
-+#endif
-+
-+/**
-+ * schedule_preempt_disabled - called with preemption disabled
-+ *
-+ * Returns with preemption disabled. Note: preempt_count must be 1
-+ */
-+void __sched schedule_preempt_disabled(void)
-+{
-+ sched_preempt_enable_no_resched();
-+ schedule();
-+ preempt_disable();
-+}
-+
-+#ifdef CONFIG_PREEMPT_RT
-+void __sched notrace schedule_rtlock(void)
-+{
-+ __schedule_loop(SM_RTLOCK_WAIT);
-+}
-+NOKPROBE_SYMBOL(schedule_rtlock);
-+#endif
-+
-+static void __sched notrace preempt_schedule_common(void)
-+{
-+ do {
-+ /*
-+ * Because the function tracer can trace preempt_count_sub()
-+ * and it also uses preempt_enable/disable_notrace(), if
-+ * NEED_RESCHED is set, the preempt_enable_notrace() called
-+ * by the function tracer will call this function again and
-+ * cause infinite recursion.
-+ *
-+ * Preemption must be disabled here before the function
-+ * tracer can trace. Break up preempt_disable() into two
-+ * calls. One to disable preemption without fear of being
-+ * traced. The other to still record the preemption latency,
-+ * which can also be traced by the function tracer.
-+ */
-+ preempt_disable_notrace();
-+ preempt_latency_start(1);
-+ __schedule(SM_PREEMPT);
-+ preempt_latency_stop(1);
-+ preempt_enable_no_resched_notrace();
-+
-+ /*
-+ * Check again in case we missed a preemption opportunity
-+ * between schedule and now.
-+ */
-+ } while (need_resched());
-+}
-+
-+#ifdef CONFIG_PREEMPTION
-+/*
-+ * This is the entry point to schedule() from in-kernel preemption
-+ * off of preempt_enable.
-+ */
-+asmlinkage __visible void __sched notrace preempt_schedule(void)
-+{
-+ /*
-+ * If there is a non-zero preempt_count or interrupts are disabled,
-+ * we do not want to preempt the current task. Just return..
-+ */
-+ if (likely(!preemptible()))
-+ return;
-+
-+ preempt_schedule_common();
-+}
-+NOKPROBE_SYMBOL(preempt_schedule);
-+EXPORT_SYMBOL(preempt_schedule);
-+
-+#ifdef CONFIG_PREEMPT_DYNAMIC
-+#if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
-+#ifndef preempt_schedule_dynamic_enabled
-+#define preempt_schedule_dynamic_enabled preempt_schedule
-+#define preempt_schedule_dynamic_disabled NULL
-+#endif
-+DEFINE_STATIC_CALL(preempt_schedule, preempt_schedule_dynamic_enabled);
-+EXPORT_STATIC_CALL_TRAMP(preempt_schedule);
-+#elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
-+static DEFINE_STATIC_KEY_TRUE(sk_dynamic_preempt_schedule);
-+void __sched notrace dynamic_preempt_schedule(void)
-+{
-+ if (!static_branch_unlikely(&sk_dynamic_preempt_schedule))
-+ return;
-+ preempt_schedule();
-+}
-+NOKPROBE_SYMBOL(dynamic_preempt_schedule);
-+EXPORT_SYMBOL(dynamic_preempt_schedule);
-+#endif
-+#endif
-+
-+/**
-+ * preempt_schedule_notrace - preempt_schedule called by tracing
-+ *
-+ * The tracing infrastructure uses preempt_enable_notrace to prevent
-+ * recursion and tracing preempt enabling caused by the tracing
-+ * infrastructure itself. But as tracing can happen in areas coming
-+ * from userspace or just about to enter userspace, a preempt enable
-+ * can occur before user_exit() is called. This will cause the scheduler
-+ * to be called when the system is still in usermode.
-+ *
-+ * To prevent this, the preempt_enable_notrace will use this function
-+ * instead of preempt_schedule() to exit user context if needed before
-+ * calling the scheduler.
-+ */
-+asmlinkage __visible void __sched notrace preempt_schedule_notrace(void)
-+{
-+ enum ctx_state prev_ctx;
-+
-+ if (likely(!preemptible()))
-+ return;
-+
-+ do {
-+ /*
-+ * Because the function tracer can trace preempt_count_sub()
-+ * and it also uses preempt_enable/disable_notrace(), if
-+ * NEED_RESCHED is set, the preempt_enable_notrace() called
-+ * by the function tracer will call this function again and
-+ * cause infinite recursion.
-+ *
-+ * Preemption must be disabled here before the function
-+ * tracer can trace. Break up preempt_disable() into two
-+ * calls. One to disable preemption without fear of being
-+ * traced. The other to still record the preemption latency,
-+ * which can also be traced by the function tracer.
-+ */
-+ preempt_disable_notrace();
-+ preempt_latency_start(1);
-+ /*
-+ * Needs preempt disabled in case user_exit() is traced
-+ * and the tracer calls preempt_enable_notrace() causing
-+ * an infinite recursion.
-+ */
-+ prev_ctx = exception_enter();
-+ __schedule(SM_PREEMPT);
-+ exception_exit(prev_ctx);
-+
-+ preempt_latency_stop(1);
-+ preempt_enable_no_resched_notrace();
-+ } while (need_resched());
-+}
-+EXPORT_SYMBOL_GPL(preempt_schedule_notrace);
-+
-+#ifdef CONFIG_PREEMPT_DYNAMIC
-+#if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
-+#ifndef preempt_schedule_notrace_dynamic_enabled
-+#define preempt_schedule_notrace_dynamic_enabled preempt_schedule_notrace
-+#define preempt_schedule_notrace_dynamic_disabled NULL
-+#endif
-+DEFINE_STATIC_CALL(preempt_schedule_notrace, preempt_schedule_notrace_dynamic_enabled);
-+EXPORT_STATIC_CALL_TRAMP(preempt_schedule_notrace);
-+#elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
-+static DEFINE_STATIC_KEY_TRUE(sk_dynamic_preempt_schedule_notrace);
-+void __sched notrace dynamic_preempt_schedule_notrace(void)
-+{
-+ if (!static_branch_unlikely(&sk_dynamic_preempt_schedule_notrace))
-+ return;
-+ preempt_schedule_notrace();
-+}
-+NOKPROBE_SYMBOL(dynamic_preempt_schedule_notrace);
-+EXPORT_SYMBOL(dynamic_preempt_schedule_notrace);
-+#endif
-+#endif
-+
-+#endif /* CONFIG_PREEMPTION */
-+
-+/*
-+ * This is the entry point to schedule() from kernel preemption
-+ * off of irq context.
-+ * Note, that this is called and return with irqs disabled. This will
-+ * protect us against recursive calling from irq.
-+ */
-+asmlinkage __visible void __sched preempt_schedule_irq(void)
-+{
-+ enum ctx_state prev_state;
-+
-+ /* Catch callers which need to be fixed */
-+ BUG_ON(preempt_count() || !irqs_disabled());
-+
-+ prev_state = exception_enter();
-+
-+ do {
-+ preempt_disable();
-+ local_irq_enable();
-+ __schedule(SM_PREEMPT);
-+ local_irq_disable();
-+ sched_preempt_enable_no_resched();
-+ } while (need_resched());
-+
-+ exception_exit(prev_state);
-+}
-+
-+int default_wake_function(wait_queue_entry_t *curr, unsigned mode, int wake_flags,
-+ void *key)
-+{
-+ WARN_ON_ONCE(IS_ENABLED(CONFIG_SCHED_DEBUG) && wake_flags & ~(WF_SYNC|WF_CURRENT_CPU));
-+ return try_to_wake_up(curr->private, mode, wake_flags);
-+}
-+EXPORT_SYMBOL(default_wake_function);
-+
-+static inline void check_task_changed(struct task_struct *p, struct rq *rq)
-+{
-+ /* Trigger resched if task sched_prio has been modified. */
-+ if (task_on_rq_queued(p)) {
-+ int idx;
-+
-+ update_rq_clock(rq);
-+ idx = task_sched_prio_idx(p, rq);
-+ if (idx != p->sq_idx) {
-+ requeue_task(p, rq, idx);
-+ wakeup_preempt(rq);
-+ }
-+ }
-+}
-+
-+static void __setscheduler_prio(struct task_struct *p, int prio)
-+{
-+ p->prio = prio;
-+}
-+
-+#ifdef CONFIG_RT_MUTEXES
-+
-+/*
-+ * Would be more useful with typeof()/auto_type but they don't mix with
-+ * bit-fields. Since it's a local thing, use int. Keep the generic sounding
-+ * name such that if someone were to implement this function we get to compare
-+ * notes.
-+ */
-+#define fetch_and_set(x, v) ({ int _x = (x); (x) = (v); _x; })
-+
-+void rt_mutex_pre_schedule(void)
-+{
-+ lockdep_assert(!fetch_and_set(current->sched_rt_mutex, 1));
-+ sched_submit_work(current);
-+}
-+
-+void rt_mutex_schedule(void)
-+{
-+ lockdep_assert(current->sched_rt_mutex);
-+ __schedule_loop(SM_NONE);
-+}
-+
-+void rt_mutex_post_schedule(void)
-+{
-+ sched_update_worker(current);
-+ lockdep_assert(fetch_and_set(current->sched_rt_mutex, 0));
-+}
-+
-+static inline int __rt_effective_prio(struct task_struct *pi_task, int prio)
-+{
-+ if (pi_task)
-+ prio = min(prio, pi_task->prio);
-+
-+ return prio;
-+}
-+
-+static inline int rt_effective_prio(struct task_struct *p, int prio)
-+{
-+ struct task_struct *pi_task = rt_mutex_get_top_task(p);
-+
-+ return __rt_effective_prio(pi_task, prio);
-+}
-+
-+/*
-+ * rt_mutex_setprio - set the current priority of a task
-+ * @p: task to boost
-+ * @pi_task: donor task
-+ *
-+ * This function changes the 'effective' priority of a task. It does
-+ * not touch ->normal_prio like __setscheduler().
-+ *
-+ * Used by the rt_mutex code to implement priority inheritance
-+ * logic. Call site only calls if the priority of the task changed.
-+ */
-+void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task)
-+{
-+ int prio;
-+ struct rq *rq;
-+ raw_spinlock_t *lock;
-+
-+ /* XXX used to be waiter->prio, not waiter->task->prio */
-+ prio = __rt_effective_prio(pi_task, p->normal_prio);
-+
-+ /*
-+ * If nothing changed; bail early.
-+ */
-+ if (p->pi_top_task == pi_task && prio == p->prio)
-+ return;
-+
-+ rq = __task_access_lock(p, &lock);
-+ /*
-+ * Set under pi_lock && rq->lock, such that the value can be used under
-+ * either lock.
-+ *
-+ * Note that there is loads of tricky to make this pointer cache work
-+ * right. rt_mutex_slowunlock()+rt_mutex_postunlock() work together to
-+ * ensure a task is de-boosted (pi_task is set to NULL) before the
-+ * task is allowed to run again (and can exit). This ensures the pointer
-+ * points to a blocked task -- which guarantees the task is present.
-+ */
-+ p->pi_top_task = pi_task;
-+
-+ /*
-+ * For FIFO/RR we only need to set prio, if that matches we're done.
-+ */
-+ if (prio == p->prio)
-+ goto out_unlock;
-+
-+ /*
-+ * Idle task boosting is a nono in general. There is one
-+ * exception, when PREEMPT_RT and NOHZ is active:
-+ *
-+ * The idle task calls get_next_timer_interrupt() and holds
-+ * the timer wheel base->lock on the CPU and another CPU wants
-+ * to access the timer (probably to cancel it). We can safely
-+ * ignore the boosting request, as the idle CPU runs this code
-+ * with interrupts disabled and will complete the lock
-+ * protected section without being interrupted. So there is no
-+ * real need to boost.
-+ */
-+ if (unlikely(p == rq->idle)) {
-+ WARN_ON(p != rq->curr);
-+ WARN_ON(p->pi_blocked_on);
-+ goto out_unlock;
-+ }
-+
-+ trace_sched_pi_setprio(p, pi_task);
-+
-+ __setscheduler_prio(p, prio);
-+
-+ check_task_changed(p, rq);
-+out_unlock:
-+ /* Avoid rq from going away on us: */
-+ preempt_disable();
-+
-+ __balance_callbacks(rq);
-+ __task_access_unlock(p, lock);
-+
-+ preempt_enable();
-+}
-+#else
-+static inline int rt_effective_prio(struct task_struct *p, int prio)
-+{
-+ return prio;
-+}
-+#endif
-+
-+void set_user_nice(struct task_struct *p, long nice)
-+{
-+ unsigned long flags;
-+ struct rq *rq;
-+ raw_spinlock_t *lock;
-+
-+ if (task_nice(p) == nice || nice < MIN_NICE || nice > MAX_NICE)
-+ return;
-+ /*
-+ * We have to be careful, if called from sys_setpriority(),
-+ * the task might be in the middle of scheduling on another CPU.
-+ */
-+ raw_spin_lock_irqsave(&p->pi_lock, flags);
-+ rq = __task_access_lock(p, &lock);
-+
-+ p->static_prio = NICE_TO_PRIO(nice);
-+ /*
-+ * The RT priorities are set via sched_setscheduler(), but we still
-+ * allow the 'normal' nice value to be set - but as expected
-+ * it won't have any effect on scheduling until the task is
-+ * not SCHED_NORMAL/SCHED_BATCH:
-+ */
-+ if (task_has_rt_policy(p))
-+ goto out_unlock;
-+
-+ p->prio = effective_prio(p);
-+
-+ check_task_changed(p, rq);
-+out_unlock:
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+}
-+EXPORT_SYMBOL(set_user_nice);
-+
-+/*
-+ * is_nice_reduction - check if nice value is an actual reduction
-+ *
-+ * Similar to can_nice() but does not perform a capability check.
-+ *
-+ * @p: task
-+ * @nice: nice value
-+ */
-+static bool is_nice_reduction(const struct task_struct *p, const int nice)
-+{
-+ /* Convert nice value [19,-20] to rlimit style value [1,40]: */
-+ int nice_rlim = nice_to_rlimit(nice);
-+
-+ return (nice_rlim <= task_rlimit(p, RLIMIT_NICE));
-+}
-+
-+/*
-+ * can_nice - check if a task can reduce its nice value
-+ * @p: task
-+ * @nice: nice value
-+ */
-+int can_nice(const struct task_struct *p, const int nice)
-+{
-+ return is_nice_reduction(p, nice) || capable(CAP_SYS_NICE);
-+}
-+
-+#ifdef __ARCH_WANT_SYS_NICE
-+
-+/*
-+ * sys_nice - change the priority of the current process.
-+ * @increment: priority increment
-+ *
-+ * sys_setpriority is a more generic, but much slower function that
-+ * does similar things.
-+ */
-+SYSCALL_DEFINE1(nice, int, increment)
-+{
-+ long nice, retval;
-+
-+ /*
-+ * Setpriority might change our priority at the same moment.
-+ * We don't have to worry. Conceptually one call occurs first
-+ * and we have a single winner.
-+ */
-+
-+ increment = clamp(increment, -NICE_WIDTH, NICE_WIDTH);
-+ nice = task_nice(current) + increment;
-+
-+ nice = clamp_val(nice, MIN_NICE, MAX_NICE);
-+ if (increment < 0 && !can_nice(current, nice))
-+ return -EPERM;
-+
-+ retval = security_task_setnice(current, nice);
-+ if (retval)
-+ return retval;
-+
-+ set_user_nice(current, nice);
-+ return 0;
-+}
-+
-+#endif
-+
-+/**
-+ * task_prio - return the priority value of a given task.
-+ * @p: the task in question.
-+ *
-+ * Return: The priority value as seen by users in /proc.
-+ *
-+ * sched policy return value kernel prio user prio/nice
-+ *
-+ * (BMQ)normal, batch, idle[0 ... 53] [100 ... 139] 0/[-20 ... 19]/[-7 ... 7]
-+ * (PDS)normal, batch, idle[0 ... 39] 100 0/[-20 ... 19]
-+ * fifo, rr [-1 ... -100] [99 ... 0] [0 ... 99]
-+ */
-+int task_prio(const struct task_struct *p)
-+{
-+ return (p->prio < MAX_RT_PRIO) ? p->prio - MAX_RT_PRIO :
-+ task_sched_prio_normal(p, task_rq(p));
-+}
-+
-+/**
-+ * idle_cpu - is a given CPU idle currently?
-+ * @cpu: the processor in question.
-+ *
-+ * Return: 1 if the CPU is currently idle. 0 otherwise.
-+ */
-+int idle_cpu(int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+
-+ if (rq->curr != rq->idle)
-+ return 0;
-+
-+ if (rq->nr_running)
-+ return 0;
-+
-+#ifdef CONFIG_SMP
-+ if (rq->ttwu_pending)
-+ return 0;
-+#endif
-+
-+ return 1;
-+}
-+
-+/**
-+ * idle_task - return the idle task for a given CPU.
-+ * @cpu: the processor in question.
-+ *
-+ * Return: The idle task for the cpu @cpu.
-+ */
-+struct task_struct *idle_task(int cpu)
-+{
-+ return cpu_rq(cpu)->idle;
-+}
-+
-+/**
-+ * find_process_by_pid - find a process with a matching PID value.
-+ * @pid: the pid in question.
-+ *
-+ * The task of @pid, if found. %NULL otherwise.
-+ */
-+static inline struct task_struct *find_process_by_pid(pid_t pid)
-+{
-+ return pid ? find_task_by_vpid(pid) : current;
-+}
-+
-+static struct task_struct *find_get_task(pid_t pid)
-+{
-+ struct task_struct *p;
-+ guard(rcu)();
-+
-+ p = find_process_by_pid(pid);
-+ if (likely(p))
-+ get_task_struct(p);
-+
-+ return p;
-+}
-+
-+DEFINE_CLASS(find_get_task, struct task_struct *, if (_T) put_task_struct(_T),
-+ find_get_task(pid), pid_t pid)
-+
-+/*
-+ * sched_setparam() passes in -1 for its policy, to let the functions
-+ * it calls know not to change it.
-+ */
-+#define SETPARAM_POLICY -1
-+
-+static void __setscheduler_params(struct task_struct *p,
-+ const struct sched_attr *attr)
-+{
-+ int policy = attr->sched_policy;
-+
-+ if (policy == SETPARAM_POLICY)
-+ policy = p->policy;
-+
-+ p->policy = policy;
-+
-+ /*
-+ * allow normal nice value to be set, but will not have any
-+ * effect on scheduling until the task not SCHED_NORMAL/
-+ * SCHED_BATCH
-+ */
-+ p->static_prio = NICE_TO_PRIO(attr->sched_nice);
-+
-+ /*
-+ * __sched_setscheduler() ensures attr->sched_priority == 0 when
-+ * !rt_policy. Always setting this ensures that things like
-+ * getparam()/getattr() don't report silly values for !rt tasks.
-+ */
-+ p->rt_priority = attr->sched_priority;
-+ p->normal_prio = normal_prio(p);
-+}
-+
-+/*
-+ * check the target process has a UID that matches the current process's
-+ */
-+static bool check_same_owner(struct task_struct *p)
-+{
-+ const struct cred *cred = current_cred(), *pcred;
-+ guard(rcu)();
-+
-+ pcred = __task_cred(p);
-+ return (uid_eq(cred->euid, pcred->euid) ||
-+ uid_eq(cred->euid, pcred->uid));
-+}
-+
-+/*
-+ * Allow unprivileged RT tasks to decrease priority.
-+ * Only issue a capable test if needed and only once to avoid an audit
-+ * event on permitted non-privileged operations:
-+ */
-+static int user_check_sched_setscheduler(struct task_struct *p,
-+ const struct sched_attr *attr,
-+ int policy, int reset_on_fork)
-+{
-+ if (rt_policy(policy)) {
-+ unsigned long rlim_rtprio = task_rlimit(p, RLIMIT_RTPRIO);
-+
-+ /* Can't set/change the rt policy: */
-+ if (policy != p->policy && !rlim_rtprio)
-+ goto req_priv;
-+
-+ /* Can't increase priority: */
-+ if (attr->sched_priority > p->rt_priority &&
-+ attr->sched_priority > rlim_rtprio)
-+ goto req_priv;
-+ }
-+
-+ /* Can't change other user's priorities: */
-+ if (!check_same_owner(p))
-+ goto req_priv;
-+
-+ /* Normal users shall not reset the sched_reset_on_fork flag: */
-+ if (p->sched_reset_on_fork && !reset_on_fork)
-+ goto req_priv;
-+
-+ return 0;
-+
-+req_priv:
-+ if (!capable(CAP_SYS_NICE))
-+ return -EPERM;
-+
-+ return 0;
-+}
-+
-+static int __sched_setscheduler(struct task_struct *p,
-+ const struct sched_attr *attr,
-+ bool user, bool pi)
-+{
-+ const struct sched_attr dl_squash_attr = {
-+ .size = sizeof(struct sched_attr),
-+ .sched_policy = SCHED_FIFO,
-+ .sched_nice = 0,
-+ .sched_priority = 99,
-+ };
-+ int oldpolicy = -1, policy = attr->sched_policy;
-+ int retval, newprio;
-+ struct balance_callback *head;
-+ unsigned long flags;
-+ struct rq *rq;
-+ int reset_on_fork;
-+ raw_spinlock_t *lock;
-+
-+ /* The pi code expects interrupts enabled */
-+ BUG_ON(pi && in_interrupt());
-+
-+ /*
-+ * Alt schedule FW supports SCHED_DEADLINE by squash it as prio 0 SCHED_FIFO
-+ */
-+ if (unlikely(SCHED_DEADLINE == policy)) {
-+ attr = &dl_squash_attr;
-+ policy = attr->sched_policy;
-+ }
-+recheck:
-+ /* Double check policy once rq lock held */
-+ if (policy < 0) {
-+ reset_on_fork = p->sched_reset_on_fork;
-+ policy = oldpolicy = p->policy;
-+ } else {
-+ reset_on_fork = !!(attr->sched_flags & SCHED_RESET_ON_FORK);
-+
-+ if (policy > SCHED_IDLE)
-+ return -EINVAL;
-+ }
-+
-+ if (attr->sched_flags & ~(SCHED_FLAG_ALL))
-+ return -EINVAL;
-+
-+ /*
-+ * Valid priorities for SCHED_FIFO and SCHED_RR are
-+ * 1..MAX_RT_PRIO-1, valid priority for SCHED_NORMAL and
-+ * SCHED_BATCH and SCHED_IDLE is 0.
-+ */
-+ if (attr->sched_priority < 0 ||
-+ (p->mm && attr->sched_priority > MAX_RT_PRIO - 1) ||
-+ (!p->mm && attr->sched_priority > MAX_RT_PRIO - 1))
-+ return -EINVAL;
-+ if ((SCHED_RR == policy || SCHED_FIFO == policy) !=
-+ (attr->sched_priority != 0))
-+ return -EINVAL;
-+
-+ if (user) {
-+ retval = user_check_sched_setscheduler(p, attr, policy, reset_on_fork);
-+ if (retval)
-+ return retval;
-+
-+ retval = security_task_setscheduler(p);
-+ if (retval)
-+ return retval;
-+ }
-+
-+ /*
-+ * Make sure no PI-waiters arrive (or leave) while we are
-+ * changing the priority of the task:
-+ */
-+ raw_spin_lock_irqsave(&p->pi_lock, flags);
-+
-+ /*
-+ * To be able to change p->policy safely, task_access_lock()
-+ * must be called.
-+ * IF use task_access_lock() here:
-+ * For the task p which is not running, reading rq->stop is
-+ * racy but acceptable as ->stop doesn't change much.
-+ * An enhancemnet can be made to read rq->stop saftly.
-+ */
-+ rq = __task_access_lock(p, &lock);
-+
-+ /*
-+ * Changing the policy of the stop threads its a very bad idea
-+ */
-+ if (p == rq->stop) {
-+ retval = -EINVAL;
-+ goto unlock;
-+ }
-+
-+ /*
-+ * If not changing anything there's no need to proceed further:
-+ */
-+ if (unlikely(policy == p->policy)) {
-+ if (rt_policy(policy) && attr->sched_priority != p->rt_priority)
-+ goto change;
-+ if (!rt_policy(policy) &&
-+ NICE_TO_PRIO(attr->sched_nice) != p->static_prio)
-+ goto change;
-+
-+ p->sched_reset_on_fork = reset_on_fork;
-+ retval = 0;
-+ goto unlock;
-+ }
-+change:
-+
-+ /* Re-check policy now with rq lock held */
-+ if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) {
-+ policy = oldpolicy = -1;
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+ goto recheck;
-+ }
-+
-+ p->sched_reset_on_fork = reset_on_fork;
-+
-+ newprio = __normal_prio(policy, attr->sched_priority, NICE_TO_PRIO(attr->sched_nice));
-+ if (pi) {
-+ /*
-+ * Take priority boosted tasks into account. If the new
-+ * effective priority is unchanged, we just store the new
-+ * normal parameters and do not touch the scheduler class and
-+ * the runqueue. This will be done when the task deboost
-+ * itself.
-+ */
-+ newprio = rt_effective_prio(p, newprio);
-+ }
-+
-+ if (!(attr->sched_flags & SCHED_FLAG_KEEP_PARAMS)) {
-+ __setscheduler_params(p, attr);
-+ __setscheduler_prio(p, newprio);
-+ }
-+
-+ check_task_changed(p, rq);
-+
-+ /* Avoid rq from going away on us: */
-+ preempt_disable();
-+ head = splice_balance_callbacks(rq);
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+
-+ if (pi)
-+ rt_mutex_adjust_pi(p);
-+
-+ /* Run balance callbacks after we've adjusted the PI chain: */
-+ balance_callbacks(rq, head);
-+ preempt_enable();
-+
-+ return 0;
-+
-+unlock:
-+ __task_access_unlock(p, lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
-+ return retval;
-+}
-+
-+static int _sched_setscheduler(struct task_struct *p, int policy,
-+ const struct sched_param *param, bool check)
-+{
-+ struct sched_attr attr = {
-+ .sched_policy = policy,
-+ .sched_priority = param->sched_priority,
-+ .sched_nice = PRIO_TO_NICE(p->static_prio),
-+ };
-+
-+ /* Fixup the legacy SCHED_RESET_ON_FORK hack. */
-+ if ((policy != SETPARAM_POLICY) && (policy & SCHED_RESET_ON_FORK)) {
-+ attr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
-+ policy &= ~SCHED_RESET_ON_FORK;
-+ attr.sched_policy = policy;
-+ }
-+
-+ return __sched_setscheduler(p, &attr, check, true);
-+}
-+
-+/**
-+ * sched_setscheduler - change the scheduling policy and/or RT priority of a thread.
-+ * @p: the task in question.
-+ * @policy: new policy.
-+ * @param: structure containing the new RT priority.
-+ *
-+ * Use sched_set_fifo(), read its comment.
-+ *
-+ * Return: 0 on success. An error code otherwise.
-+ *
-+ * NOTE that the task may be already dead.
-+ */
-+int sched_setscheduler(struct task_struct *p, int policy,
-+ const struct sched_param *param)
-+{
-+ return _sched_setscheduler(p, policy, param, true);
-+}
-+
-+int sched_setattr(struct task_struct *p, const struct sched_attr *attr)
-+{
-+ return __sched_setscheduler(p, attr, true, true);
-+}
-+
-+int sched_setattr_nocheck(struct task_struct *p, const struct sched_attr *attr)
-+{
-+ return __sched_setscheduler(p, attr, false, true);
-+}
-+EXPORT_SYMBOL_GPL(sched_setattr_nocheck);
-+
-+/**
-+ * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace.
-+ * @p: the task in question.
-+ * @policy: new policy.
-+ * @param: structure containing the new RT priority.
-+ *
-+ * Just like sched_setscheduler, only don't bother checking if the
-+ * current context has permission. For example, this is needed in
-+ * stop_machine(): we create temporary high priority worker threads,
-+ * but our caller might not have that capability.
-+ *
-+ * Return: 0 on success. An error code otherwise.
-+ */
-+int sched_setscheduler_nocheck(struct task_struct *p, int policy,
-+ const struct sched_param *param)
-+{
-+ return _sched_setscheduler(p, policy, param, false);
-+}
-+
-+/*
-+ * SCHED_FIFO is a broken scheduler model; that is, it is fundamentally
-+ * incapable of resource management, which is the one thing an OS really should
-+ * be doing.
-+ *
-+ * This is of course the reason it is limited to privileged users only.
-+ *
-+ * Worse still; it is fundamentally impossible to compose static priority
-+ * workloads. You cannot take two correctly working static prio workloads
-+ * and smash them together and still expect them to work.
-+ *
-+ * For this reason 'all' FIFO tasks the kernel creates are basically at:
-+ *
-+ * MAX_RT_PRIO / 2
-+ *
-+ * The administrator _MUST_ configure the system, the kernel simply doesn't
-+ * know enough information to make a sensible choice.
-+ */
-+void sched_set_fifo(struct task_struct *p)
-+{
-+ struct sched_param sp = { .sched_priority = MAX_RT_PRIO / 2 };
-+ WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0);
-+}
-+EXPORT_SYMBOL_GPL(sched_set_fifo);
-+
-+/*
-+ * For when you don't much care about FIFO, but want to be above SCHED_NORMAL.
-+ */
-+void sched_set_fifo_low(struct task_struct *p)
-+{
-+ struct sched_param sp = { .sched_priority = 1 };
-+ WARN_ON_ONCE(sched_setscheduler_nocheck(p, SCHED_FIFO, &sp) != 0);
-+}
-+EXPORT_SYMBOL_GPL(sched_set_fifo_low);
-+
-+void sched_set_normal(struct task_struct *p, int nice)
-+{
-+ struct sched_attr attr = {
-+ .sched_policy = SCHED_NORMAL,
-+ .sched_nice = nice,
-+ };
-+ WARN_ON_ONCE(sched_setattr_nocheck(p, &attr) != 0);
-+}
-+EXPORT_SYMBOL_GPL(sched_set_normal);
-+
-+static int
-+do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
-+{
-+ struct sched_param lparam;
-+
-+ if (!param || pid < 0)
-+ return -EINVAL;
-+ if (copy_from_user(&lparam, param, sizeof(struct sched_param)))
-+ return -EFAULT;
-+
-+ CLASS(find_get_task, p)(pid);
-+ if (!p)
-+ return -ESRCH;
-+
-+ return sched_setscheduler(p, policy, &lparam);
-+}
-+
-+/*
-+ * Mimics kernel/events/core.c perf_copy_attr().
-+ */
-+static int sched_copy_attr(struct sched_attr __user *uattr, struct sched_attr *attr)
-+{
-+ u32 size;
-+ int ret;
-+
-+ /* Zero the full structure, so that a short copy will be nice: */
-+ memset(attr, 0, sizeof(*attr));
-+
-+ ret = get_user(size, &uattr->size);
-+ if (ret)
-+ return ret;
-+
-+ /* ABI compatibility quirk: */
-+ if (!size)
-+ size = SCHED_ATTR_SIZE_VER0;
-+
-+ if (size < SCHED_ATTR_SIZE_VER0 || size > PAGE_SIZE)
-+ goto err_size;
-+
-+ ret = copy_struct_from_user(attr, sizeof(*attr), uattr, size);
-+ if (ret) {
-+ if (ret == -E2BIG)
-+ goto err_size;
-+ return ret;
-+ }
-+
-+ /*
-+ * XXX: Do we want to be lenient like existing syscalls; or do we want
-+ * to be strict and return an error on out-of-bounds values?
-+ */
-+ attr->sched_nice = clamp(attr->sched_nice, -20, 19);
-+
-+ /* sched/core.c uses zero here but we already know ret is zero */
-+ return 0;
-+
-+err_size:
-+ put_user(sizeof(*attr), &uattr->size);
-+ return -E2BIG;
-+}
-+
-+/**
-+ * sys_sched_setscheduler - set/change the scheduler policy and RT priority
-+ * @pid: the pid in question.
-+ * @policy: new policy.
-+ *
-+ * Return: 0 on success. An error code otherwise.
-+ * @param: structure containing the new RT priority.
-+ */
-+SYSCALL_DEFINE3(sched_setscheduler, pid_t, pid, int, policy, struct sched_param __user *, param)
-+{
-+ if (policy < 0)
-+ return -EINVAL;
-+
-+ return do_sched_setscheduler(pid, policy, param);
-+}
-+
-+/**
-+ * sys_sched_setparam - set/change the RT priority of a thread
-+ * @pid: the pid in question.
-+ * @param: structure containing the new RT priority.
-+ *
-+ * Return: 0 on success. An error code otherwise.
-+ */
-+SYSCALL_DEFINE2(sched_setparam, pid_t, pid, struct sched_param __user *, param)
-+{
-+ return do_sched_setscheduler(pid, SETPARAM_POLICY, param);
-+}
-+
-+static void get_params(struct task_struct *p, struct sched_attr *attr)
-+{
-+ if (task_has_rt_policy(p))
-+ attr->sched_priority = p->rt_priority;
-+ else
-+ attr->sched_nice = task_nice(p);
-+}
-+
-+/**
-+ * sys_sched_setattr - same as above, but with extended sched_attr
-+ * @pid: the pid in question.
-+ * @uattr: structure containing the extended parameters.
-+ */
-+SYSCALL_DEFINE3(sched_setattr, pid_t, pid, struct sched_attr __user *, uattr,
-+ unsigned int, flags)
-+{
-+ struct sched_attr attr;
-+ int retval;
-+
-+ if (!uattr || pid < 0 || flags)
-+ return -EINVAL;
-+
-+ retval = sched_copy_attr(uattr, &attr);
-+ if (retval)
-+ return retval;
-+
-+ if ((int)attr.sched_policy < 0)
-+ return -EINVAL;
-+
-+ CLASS(find_get_task, p)(pid);
-+ if (!p)
-+ return -ESRCH;
-+
-+ if (attr.sched_flags & SCHED_FLAG_KEEP_PARAMS)
-+ get_params(p, &attr);
-+
-+ return sched_setattr(p, &attr);
-+}
-+
-+/**
-+ * sys_sched_getscheduler - get the policy (scheduling class) of a thread
-+ * @pid: the pid in question.
-+ *
-+ * Return: On success, the policy of the thread. Otherwise, a negative error
-+ * code.
-+ */
-+SYSCALL_DEFINE1(sched_getscheduler, pid_t, pid)
-+{
-+ struct task_struct *p;
-+ int retval = -EINVAL;
-+
-+ if (pid < 0)
-+ return -ESRCH;
-+
-+ guard(rcu)();
-+ p = find_process_by_pid(pid);
-+ if (!p)
-+ return -ESRCH;
-+
-+ retval = security_task_getscheduler(p);
-+ if (!retval)
-+ retval = p->policy;
-+
-+ return retval;
-+}
-+
-+/**
-+ * sys_sched_getscheduler - get the RT priority of a thread
-+ * @pid: the pid in question.
-+ * @param: structure containing the RT priority.
-+ *
-+ * Return: On success, 0 and the RT priority is in @param. Otherwise, an error
-+ * code.
-+ */
-+SYSCALL_DEFINE2(sched_getparam, pid_t, pid, struct sched_param __user *, param)
-+{
-+ struct sched_param lp = { .sched_priority = 0 };
-+ struct task_struct *p;
-+
-+ if (!param || pid < 0)
-+ return -EINVAL;
-+
-+ scoped_guard (rcu) {
-+ int retval;
-+
-+ p = find_process_by_pid(pid);
-+ if (!p)
-+ return -EINVAL;
-+
-+ retval = security_task_getscheduler(p);
-+ if (retval)
-+ return retval;
-+
-+ if (task_has_rt_policy(p))
-+ lp.sched_priority = p->rt_priority;
-+ }
-+
-+ /*
-+ * This one might sleep, we cannot do it with a spinlock held ...
-+ */
-+ return copy_to_user(param, &lp, sizeof(*param)) ? -EFAULT : 0;
-+}
-+
-+/*
-+ * Copy the kernel size attribute structure (which might be larger
-+ * than what user-space knows about) to user-space.
-+ *
-+ * Note that all cases are valid: user-space buffer can be larger or
-+ * smaller than the kernel-space buffer. The usual case is that both
-+ * have the same size.
-+ */
-+static int
-+sched_attr_copy_to_user(struct sched_attr __user *uattr,
-+ struct sched_attr *kattr,
-+ unsigned int usize)
-+{
-+ unsigned int ksize = sizeof(*kattr);
-+
-+ if (!access_ok(uattr, usize))
-+ return -EFAULT;
-+
-+ /*
-+ * sched_getattr() ABI forwards and backwards compatibility:
-+ *
-+ * If usize == ksize then we just copy everything to user-space and all is good.
-+ *
-+ * If usize < ksize then we only copy as much as user-space has space for,
-+ * this keeps ABI compatibility as well. We skip the rest.
-+ *
-+ * If usize > ksize then user-space is using a newer version of the ABI,
-+ * which part the kernel doesn't know about. Just ignore it - tooling can
-+ * detect the kernel's knowledge of attributes from the attr->size value
-+ * which is set to ksize in this case.
-+ */
-+ kattr->size = min(usize, ksize);
-+
-+ if (copy_to_user(uattr, kattr, kattr->size))
-+ return -EFAULT;
-+
-+ return 0;
-+}
-+
-+/**
-+ * sys_sched_getattr - similar to sched_getparam, but with sched_attr
-+ * @pid: the pid in question.
-+ * @uattr: structure containing the extended parameters.
-+ * @usize: sizeof(attr) for fwd/bwd comp.
-+ * @flags: for future extension.
-+ */
-+SYSCALL_DEFINE4(sched_getattr, pid_t, pid, struct sched_attr __user *, uattr,
-+ unsigned int, usize, unsigned int, flags)
-+{
-+ struct sched_attr kattr = { };
-+ struct task_struct *p;
-+ int retval;
-+
-+ if (!uattr || pid < 0 || usize > PAGE_SIZE ||
-+ usize < SCHED_ATTR_SIZE_VER0 || flags)
-+ return -EINVAL;
-+
-+ scoped_guard (rcu) {
-+ p = find_process_by_pid(pid);
-+ if (!p)
-+ return -ESRCH;
-+
-+ retval = security_task_getscheduler(p);
-+ if (retval)
-+ return retval;
-+
-+ kattr.sched_policy = p->policy;
-+ if (p->sched_reset_on_fork)
-+ kattr.sched_flags |= SCHED_FLAG_RESET_ON_FORK;
-+ get_params(p, &kattr);
-+ kattr.sched_flags &= SCHED_FLAG_ALL;
-+
-+#ifdef CONFIG_UCLAMP_TASK
-+ kattr.sched_util_min = p->uclamp_req[UCLAMP_MIN].value;
-+ kattr.sched_util_max = p->uclamp_req[UCLAMP_MAX].value;
-+#endif
-+ }
-+
-+ return sched_attr_copy_to_user(uattr, &kattr, usize);
-+}
-+
-+#ifdef CONFIG_SMP
-+int dl_task_check_affinity(struct task_struct *p, const struct cpumask *mask)
-+{
-+ return 0;
-+}
-+#endif
-+
-+static int
-+__sched_setaffinity(struct task_struct *p, struct affinity_context *ctx)
-+{
-+ int retval;
-+ cpumask_var_t cpus_allowed, new_mask;
-+
-+ if (!alloc_cpumask_var(&cpus_allowed, GFP_KERNEL))
-+ return -ENOMEM;
-+
-+ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) {
-+ retval = -ENOMEM;
-+ goto out_free_cpus_allowed;
-+ }
-+
-+ cpuset_cpus_allowed(p, cpus_allowed);
-+ cpumask_and(new_mask, ctx->new_mask, cpus_allowed);
-+
-+ ctx->new_mask = new_mask;
-+ ctx->flags |= SCA_CHECK;
-+
-+ retval = __set_cpus_allowed_ptr(p, ctx);
-+ if (retval)
-+ goto out_free_new_mask;
-+
-+ cpuset_cpus_allowed(p, cpus_allowed);
-+ if (!cpumask_subset(new_mask, cpus_allowed)) {
-+ /*
-+ * We must have raced with a concurrent cpuset
-+ * update. Just reset the cpus_allowed to the
-+ * cpuset's cpus_allowed
-+ */
-+ cpumask_copy(new_mask, cpus_allowed);
-+
-+ /*
-+ * If SCA_USER is set, a 2nd call to __set_cpus_allowed_ptr()
-+ * will restore the previous user_cpus_ptr value.
-+ *
-+ * In the unlikely event a previous user_cpus_ptr exists,
-+ * we need to further restrict the mask to what is allowed
-+ * by that old user_cpus_ptr.
-+ */
-+ if (unlikely((ctx->flags & SCA_USER) && ctx->user_mask)) {
-+ bool empty = !cpumask_and(new_mask, new_mask,
-+ ctx->user_mask);
-+
-+ if (WARN_ON_ONCE(empty))
-+ cpumask_copy(new_mask, cpus_allowed);
-+ }
-+ __set_cpus_allowed_ptr(p, ctx);
-+ retval = -EINVAL;
-+ }
-+
-+out_free_new_mask:
-+ free_cpumask_var(new_mask);
-+out_free_cpus_allowed:
-+ free_cpumask_var(cpus_allowed);
-+ return retval;
-+}
-+
-+long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
-+{
-+ struct affinity_context ac;
-+ struct cpumask *user_mask;
-+ int retval;
-+
-+ CLASS(find_get_task, p)(pid);
-+ if (!p)
-+ return -ESRCH;
-+
-+ if (p->flags & PF_NO_SETAFFINITY)
-+ return -EINVAL;
-+
-+ if (!check_same_owner(p)) {
-+ guard(rcu)();
-+ if (!ns_capable(__task_cred(p)->user_ns, CAP_SYS_NICE))
-+ return -EPERM;
-+ }
-+
-+ retval = security_task_setscheduler(p);
-+ if (retval)
-+ return retval;
-+
-+ /*
-+ * With non-SMP configs, user_cpus_ptr/user_mask isn't used and
-+ * alloc_user_cpus_ptr() returns NULL.
-+ */
-+ user_mask = alloc_user_cpus_ptr(NUMA_NO_NODE);
-+ if (user_mask) {
-+ cpumask_copy(user_mask, in_mask);
-+ } else if (IS_ENABLED(CONFIG_SMP)) {
-+ return -ENOMEM;
-+ }
-+
-+ ac = (struct affinity_context){
-+ .new_mask = in_mask,
-+ .user_mask = user_mask,
-+ .flags = SCA_USER,
-+ };
-+
-+ retval = __sched_setaffinity(p, &ac);
-+ kfree(ac.user_mask);
-+
-+ return retval;
-+}
-+
-+static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len,
-+ struct cpumask *new_mask)
-+{
-+ if (len < cpumask_size())
-+ cpumask_clear(new_mask);
-+ else if (len > cpumask_size())
-+ len = cpumask_size();
-+
-+ return copy_from_user(new_mask, user_mask_ptr, len) ? -EFAULT : 0;
-+}
-+
-+/**
-+ * sys_sched_setaffinity - set the CPU affinity of a process
-+ * @pid: pid of the process
-+ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
-+ * @user_mask_ptr: user-space pointer to the new CPU mask
-+ *
-+ * Return: 0 on success. An error code otherwise.
-+ */
-+SYSCALL_DEFINE3(sched_setaffinity, pid_t, pid, unsigned int, len,
-+ unsigned long __user *, user_mask_ptr)
-+{
-+ cpumask_var_t new_mask;
-+ int retval;
-+
-+ if (!alloc_cpumask_var(&new_mask, GFP_KERNEL))
-+ return -ENOMEM;
-+
-+ retval = get_user_cpu_mask(user_mask_ptr, len, new_mask);
-+ if (retval == 0)
-+ retval = sched_setaffinity(pid, new_mask);
-+ free_cpumask_var(new_mask);
-+ return retval;
-+}
-+
-+long sched_getaffinity(pid_t pid, cpumask_t *mask)
-+{
-+ struct task_struct *p;
-+ int retval;
-+
-+ guard(rcu)();
-+ p = find_process_by_pid(pid);
-+ if (!p)
-+ return -ESRCH;
-+
-+ retval = security_task_getscheduler(p);
-+ if (retval)
-+ return retval;
-+
-+ guard(raw_spinlock_irqsave)(&p->pi_lock);
-+ cpumask_and(mask, &p->cpus_mask, cpu_active_mask);
-+
-+ return retval;
-+}
-+
-+/**
-+ * sys_sched_getaffinity - get the CPU affinity of a process
-+ * @pid: pid of the process
-+ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
-+ * @user_mask_ptr: user-space pointer to hold the current CPU mask
-+ *
-+ * Return: size of CPU mask copied to user_mask_ptr on success. An
-+ * error code otherwise.
-+ */
-+SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
-+ unsigned long __user *, user_mask_ptr)
-+{
-+ int ret;
-+ cpumask_var_t mask;
-+
-+ if ((len * BITS_PER_BYTE) < nr_cpu_ids)
-+ return -EINVAL;
-+ if (len & (sizeof(unsigned long)-1))
-+ return -EINVAL;
-+
-+ if (!zalloc_cpumask_var(&mask, GFP_KERNEL))
-+ return -ENOMEM;
-+
-+ ret = sched_getaffinity(pid, mask);
-+ if (ret == 0) {
-+ unsigned int retlen = min(len, cpumask_size());
-+
-+ if (copy_to_user(user_mask_ptr, cpumask_bits(mask), retlen))
-+ ret = -EFAULT;
-+ else
-+ ret = retlen;
-+ }
-+ free_cpumask_var(mask);
-+
-+ return ret;
-+}
-+
-+static void do_sched_yield(void)
-+{
-+ struct rq *rq;
-+ struct rq_flags rf;
-+ struct task_struct *p;
-+
-+ if (!sched_yield_type)
-+ return;
-+
-+ rq = this_rq_lock_irq(&rf);
-+
-+ schedstat_inc(rq->yld_count);
-+
-+ p = current;
-+ if (rt_task(p)) {
-+ if (task_on_rq_queued(p))
-+ requeue_task(p, rq, task_sched_prio_idx(p, rq));
-+ } else if (rq->nr_running > 1) {
-+ if (1 == sched_yield_type) {
-+ do_sched_yield_type_1(p, rq);
-+ if (task_on_rq_queued(p))
-+ requeue_task(p, rq, task_sched_prio_idx(p, rq));
-+ } else if (2 == sched_yield_type) {
-+ rq->skip = p;
-+ }
-+ }
-+
-+ preempt_disable();
-+ raw_spin_unlock_irq(&rq->lock);
-+ sched_preempt_enable_no_resched();
-+
-+ schedule();
-+}
-+
-+/**
-+ * sys_sched_yield - yield the current processor to other threads.
-+ *
-+ * This function yields the current CPU to other tasks. If there are no
-+ * other threads running on this CPU then this function will return.
-+ *
-+ * Return: 0.
-+ */
-+SYSCALL_DEFINE0(sched_yield)
-+{
-+ do_sched_yield();
-+ return 0;
-+}
-+
-+#if !defined(CONFIG_PREEMPTION) || defined(CONFIG_PREEMPT_DYNAMIC)
-+int __sched __cond_resched(void)
-+{
-+ if (should_resched(0)) {
-+ preempt_schedule_common();
-+ return 1;
-+ }
-+ /*
-+ * In preemptible kernels, ->rcu_read_lock_nesting tells the tick
-+ * whether the current CPU is in an RCU read-side critical section,
-+ * so the tick can report quiescent states even for CPUs looping
-+ * in kernel context. In contrast, in non-preemptible kernels,
-+ * RCU readers leave no in-memory hints, which means that CPU-bound
-+ * processes executing in kernel context might never report an
-+ * RCU quiescent state. Therefore, the following code causes
-+ * cond_resched() to report a quiescent state, but only when RCU
-+ * is in urgent need of one.
-+ */
-+#ifndef CONFIG_PREEMPT_RCU
-+ rcu_all_qs();
-+#endif
-+ return 0;
-+}
-+EXPORT_SYMBOL(__cond_resched);
-+#endif
-+
-+#ifdef CONFIG_PREEMPT_DYNAMIC
-+#if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
-+#define cond_resched_dynamic_enabled __cond_resched
-+#define cond_resched_dynamic_disabled ((void *)&__static_call_return0)
-+DEFINE_STATIC_CALL_RET0(cond_resched, __cond_resched);
-+EXPORT_STATIC_CALL_TRAMP(cond_resched);
-+
-+#define might_resched_dynamic_enabled __cond_resched
-+#define might_resched_dynamic_disabled ((void *)&__static_call_return0)
-+DEFINE_STATIC_CALL_RET0(might_resched, __cond_resched);
-+EXPORT_STATIC_CALL_TRAMP(might_resched);
-+#elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
-+static DEFINE_STATIC_KEY_FALSE(sk_dynamic_cond_resched);
-+int __sched dynamic_cond_resched(void)
-+{
-+ klp_sched_try_switch();
-+ if (!static_branch_unlikely(&sk_dynamic_cond_resched))
-+ return 0;
-+ return __cond_resched();
-+}
-+EXPORT_SYMBOL(dynamic_cond_resched);
-+
-+static DEFINE_STATIC_KEY_FALSE(sk_dynamic_might_resched);
-+int __sched dynamic_might_resched(void)
-+{
-+ if (!static_branch_unlikely(&sk_dynamic_might_resched))
-+ return 0;
-+ return __cond_resched();
-+}
-+EXPORT_SYMBOL(dynamic_might_resched);
-+#endif
-+#endif
-+
-+/*
-+ * __cond_resched_lock() - if a reschedule is pending, drop the given lock,
-+ * call schedule, and on return reacquire the lock.
-+ *
-+ * This works OK both with and without CONFIG_PREEMPTION. We do strange low-level
-+ * operations here to prevent schedule() from being called twice (once via
-+ * spin_unlock(), once by hand).
-+ */
-+int __cond_resched_lock(spinlock_t *lock)
-+{
-+ int resched = should_resched(PREEMPT_LOCK_OFFSET);
-+ int ret = 0;
-+
-+ lockdep_assert_held(lock);
-+
-+ if (spin_needbreak(lock) || resched) {
-+ spin_unlock(lock);
-+ if (!_cond_resched())
-+ cpu_relax();
-+ ret = 1;
-+ spin_lock(lock);
-+ }
-+ return ret;
-+}
-+EXPORT_SYMBOL(__cond_resched_lock);
-+
-+int __cond_resched_rwlock_read(rwlock_t *lock)
-+{
-+ int resched = should_resched(PREEMPT_LOCK_OFFSET);
-+ int ret = 0;
-+
-+ lockdep_assert_held_read(lock);
-+
-+ if (rwlock_needbreak(lock) || resched) {
-+ read_unlock(lock);
-+ if (!_cond_resched())
-+ cpu_relax();
-+ ret = 1;
-+ read_lock(lock);
-+ }
-+ return ret;
-+}
-+EXPORT_SYMBOL(__cond_resched_rwlock_read);
-+
-+int __cond_resched_rwlock_write(rwlock_t *lock)
-+{
-+ int resched = should_resched(PREEMPT_LOCK_OFFSET);
-+ int ret = 0;
-+
-+ lockdep_assert_held_write(lock);
-+
-+ if (rwlock_needbreak(lock) || resched) {
-+ write_unlock(lock);
-+ if (!_cond_resched())
-+ cpu_relax();
-+ ret = 1;
-+ write_lock(lock);
-+ }
-+ return ret;
-+}
-+EXPORT_SYMBOL(__cond_resched_rwlock_write);
-+
-+#ifdef CONFIG_PREEMPT_DYNAMIC
-+
-+#ifdef CONFIG_GENERIC_ENTRY
-+#include <linux/entry-common.h>
-+#endif
-+
-+/*
-+ * SC:cond_resched
-+ * SC:might_resched
-+ * SC:preempt_schedule
-+ * SC:preempt_schedule_notrace
-+ * SC:irqentry_exit_cond_resched
-+ *
-+ *
-+ * NONE:
-+ * cond_resched <- __cond_resched
-+ * might_resched <- RET0
-+ * preempt_schedule <- NOP
-+ * preempt_schedule_notrace <- NOP
-+ * irqentry_exit_cond_resched <- NOP
-+ *
-+ * VOLUNTARY:
-+ * cond_resched <- __cond_resched
-+ * might_resched <- __cond_resched
-+ * preempt_schedule <- NOP
-+ * preempt_schedule_notrace <- NOP
-+ * irqentry_exit_cond_resched <- NOP
-+ *
-+ * FULL:
-+ * cond_resched <- RET0
-+ * might_resched <- RET0
-+ * preempt_schedule <- preempt_schedule
-+ * preempt_schedule_notrace <- preempt_schedule_notrace
-+ * irqentry_exit_cond_resched <- irqentry_exit_cond_resched
-+ */
-+
-+enum {
-+ preempt_dynamic_undefined = -1,
-+ preempt_dynamic_none,
-+ preempt_dynamic_voluntary,
-+ preempt_dynamic_full,
-+};
-+
-+int preempt_dynamic_mode = preempt_dynamic_undefined;
-+
-+int sched_dynamic_mode(const char *str)
-+{
-+ if (!strcmp(str, "none"))
-+ return preempt_dynamic_none;
-+
-+ if (!strcmp(str, "voluntary"))
-+ return preempt_dynamic_voluntary;
-+
-+ if (!strcmp(str, "full"))
-+ return preempt_dynamic_full;
-+
-+ return -EINVAL;
-+}
-+
-+#if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
-+#define preempt_dynamic_enable(f) static_call_update(f, f##_dynamic_enabled)
-+#define preempt_dynamic_disable(f) static_call_update(f, f##_dynamic_disabled)
-+#elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
-+#define preempt_dynamic_enable(f) static_key_enable(&sk_dynamic_##f.key)
-+#define preempt_dynamic_disable(f) static_key_disable(&sk_dynamic_##f.key)
-+#else
-+#error "Unsupported PREEMPT_DYNAMIC mechanism"
-+#endif
-+
-+static DEFINE_MUTEX(sched_dynamic_mutex);
-+static bool klp_override;
-+
-+static void __sched_dynamic_update(int mode)
-+{
-+ /*
-+ * Avoid {NONE,VOLUNTARY} -> FULL transitions from ever ending up in
-+ * the ZERO state, which is invalid.
-+ */
-+ if (!klp_override)
-+ preempt_dynamic_enable(cond_resched);
-+ preempt_dynamic_enable(cond_resched);
-+ preempt_dynamic_enable(might_resched);
-+ preempt_dynamic_enable(preempt_schedule);
-+ preempt_dynamic_enable(preempt_schedule_notrace);
-+ preempt_dynamic_enable(irqentry_exit_cond_resched);
-+
-+ switch (mode) {
-+ case preempt_dynamic_none:
-+ if (!klp_override)
-+ preempt_dynamic_enable(cond_resched);
-+ preempt_dynamic_disable(might_resched);
-+ preempt_dynamic_disable(preempt_schedule);
-+ preempt_dynamic_disable(preempt_schedule_notrace);
-+ preempt_dynamic_disable(irqentry_exit_cond_resched);
-+ if (mode != preempt_dynamic_mode)
-+ pr_info("Dynamic Preempt: none\n");
-+ break;
-+
-+ case preempt_dynamic_voluntary:
-+ if (!klp_override)
-+ preempt_dynamic_enable(cond_resched);
-+ preempt_dynamic_enable(might_resched);
-+ preempt_dynamic_disable(preempt_schedule);
-+ preempt_dynamic_disable(preempt_schedule_notrace);
-+ preempt_dynamic_disable(irqentry_exit_cond_resched);
-+ if (mode != preempt_dynamic_mode)
-+ pr_info("Dynamic Preempt: voluntary\n");
-+ break;
-+
-+ case preempt_dynamic_full:
-+ if (!klp_override)
-+ preempt_dynamic_enable(cond_resched);
-+ preempt_dynamic_disable(might_resched);
-+ preempt_dynamic_enable(preempt_schedule);
-+ preempt_dynamic_enable(preempt_schedule_notrace);
-+ preempt_dynamic_enable(irqentry_exit_cond_resched);
-+ if (mode != preempt_dynamic_mode)
-+ pr_info("Dynamic Preempt: full\n");
-+ break;
-+ }
-+
-+ preempt_dynamic_mode = mode;
-+}
-+
-+void sched_dynamic_update(int mode)
-+{
-+ mutex_lock(&sched_dynamic_mutex);
-+ __sched_dynamic_update(mode);
-+ mutex_unlock(&sched_dynamic_mutex);
-+}
-+
-+#ifdef CONFIG_HAVE_PREEMPT_DYNAMIC_CALL
-+
-+static int klp_cond_resched(void)
-+{
-+ __klp_sched_try_switch();
-+ return __cond_resched();
-+}
-+
-+void sched_dynamic_klp_enable(void)
-+{
-+ mutex_lock(&sched_dynamic_mutex);
-+
-+ klp_override = true;
-+ static_call_update(cond_resched, klp_cond_resched);
-+
-+ mutex_unlock(&sched_dynamic_mutex);
-+}
-+
-+void sched_dynamic_klp_disable(void)
-+{
-+ mutex_lock(&sched_dynamic_mutex);
-+
-+ klp_override = false;
-+ __sched_dynamic_update(preempt_dynamic_mode);
-+
-+ mutex_unlock(&sched_dynamic_mutex);
-+}
-+
-+#endif /* CONFIG_HAVE_PREEMPT_DYNAMIC_CALL */
-+
-+
-+static int __init setup_preempt_mode(char *str)
-+{
-+ int mode = sched_dynamic_mode(str);
-+ if (mode < 0) {
-+ pr_warn("Dynamic Preempt: unsupported mode: %s\n", str);
-+ return 0;
-+ }
-+
-+ sched_dynamic_update(mode);
-+ return 1;
-+}
-+__setup("preempt=", setup_preempt_mode);
-+
-+static void __init preempt_dynamic_init(void)
-+{
-+ if (preempt_dynamic_mode == preempt_dynamic_undefined) {
-+ if (IS_ENABLED(CONFIG_PREEMPT_NONE)) {
-+ sched_dynamic_update(preempt_dynamic_none);
-+ } else if (IS_ENABLED(CONFIG_PREEMPT_VOLUNTARY)) {
-+ sched_dynamic_update(preempt_dynamic_voluntary);
-+ } else {
-+ /* Default static call setting, nothing to do */
-+ WARN_ON_ONCE(!IS_ENABLED(CONFIG_PREEMPT));
-+ preempt_dynamic_mode = preempt_dynamic_full;
-+ pr_info("Dynamic Preempt: full\n");
-+ }
-+ }
-+}
-+
-+#define PREEMPT_MODEL_ACCESSOR(mode) \
-+ bool preempt_model_##mode(void) \
-+ { \
-+ WARN_ON_ONCE(preempt_dynamic_mode == preempt_dynamic_undefined); \
-+ return preempt_dynamic_mode == preempt_dynamic_##mode; \
-+ } \
-+ EXPORT_SYMBOL_GPL(preempt_model_##mode)
-+
-+PREEMPT_MODEL_ACCESSOR(none);
-+PREEMPT_MODEL_ACCESSOR(voluntary);
-+PREEMPT_MODEL_ACCESSOR(full);
-+
-+#else /* !CONFIG_PREEMPT_DYNAMIC */
-+
-+static inline void preempt_dynamic_init(void) { }
-+
-+#endif /* #ifdef CONFIG_PREEMPT_DYNAMIC */
-+
-+/**
-+ * yield - yield the current processor to other threads.
-+ *
-+ * Do not ever use this function, there's a 99% chance you're doing it wrong.
-+ *
-+ * The scheduler is at all times free to pick the calling task as the most
-+ * eligible task to run, if removing the yield() call from your code breaks
-+ * it, it's already broken.
-+ *
-+ * Typical broken usage is:
-+ *
-+ * while (!event)
-+ * yield();
-+ *
-+ * where one assumes that yield() will let 'the other' process run that will
-+ * make event true. If the current task is a SCHED_FIFO task that will never
-+ * happen. Never use yield() as a progress guarantee!!
-+ *
-+ * If you want to use yield() to wait for something, use wait_event().
-+ * If you want to use yield() to be 'nice' for others, use cond_resched().
-+ * If you still want to use yield(), do not!
-+ */
-+void __sched yield(void)
-+{
-+ set_current_state(TASK_RUNNING);
-+ do_sched_yield();
-+}
-+EXPORT_SYMBOL(yield);
-+
-+/**
-+ * yield_to - yield the current processor to another thread in
-+ * your thread group, or accelerate that thread toward the
-+ * processor it's on.
-+ * @p: target task
-+ * @preempt: whether task preemption is allowed or not
-+ *
-+ * It's the caller's job to ensure that the target task struct
-+ * can't go away on us before we can do any checks.
-+ *
-+ * In Alt schedule FW, yield_to is not supported.
-+ *
-+ * Return:
-+ * true (>0) if we indeed boosted the target task.
-+ * false (0) if we failed to boost the target.
-+ * -ESRCH if there's no task to yield to.
-+ */
-+int __sched yield_to(struct task_struct *p, bool preempt)
-+{
-+ return 0;
-+}
-+EXPORT_SYMBOL_GPL(yield_to);
-+
-+int io_schedule_prepare(void)
-+{
-+ int old_iowait = current->in_iowait;
-+
-+ current->in_iowait = 1;
-+ blk_flush_plug(current->plug, true);
-+ return old_iowait;
-+}
-+
-+void io_schedule_finish(int token)
-+{
-+ current->in_iowait = token;
-+}
-+
-+/*
-+ * This task is about to go to sleep on IO. Increment rq->nr_iowait so
-+ * that process accounting knows that this is a task in IO wait state.
-+ *
-+ * But don't do that if it is a deliberate, throttling IO wait (this task
-+ * has set its backing_dev_info: the queue against which it should throttle)
-+ */
-+
-+long __sched io_schedule_timeout(long timeout)
-+{
-+ int token;
-+ long ret;
-+
-+ token = io_schedule_prepare();
-+ ret = schedule_timeout(timeout);
-+ io_schedule_finish(token);
-+
-+ return ret;
-+}
-+EXPORT_SYMBOL(io_schedule_timeout);
-+
-+void __sched io_schedule(void)
-+{
-+ int token;
-+
-+ token = io_schedule_prepare();
-+ schedule();
-+ io_schedule_finish(token);
-+}
-+EXPORT_SYMBOL(io_schedule);
-+
-+/**
-+ * sys_sched_get_priority_max - return maximum RT priority.
-+ * @policy: scheduling class.
-+ *
-+ * Return: On success, this syscall returns the maximum
-+ * rt_priority that can be used by a given scheduling class.
-+ * On failure, a negative error code is returned.
-+ */
-+SYSCALL_DEFINE1(sched_get_priority_max, int, policy)
-+{
-+ int ret = -EINVAL;
-+
-+ switch (policy) {
-+ case SCHED_FIFO:
-+ case SCHED_RR:
-+ ret = MAX_RT_PRIO - 1;
-+ break;
-+ case SCHED_NORMAL:
-+ case SCHED_BATCH:
-+ case SCHED_IDLE:
-+ ret = 0;
-+ break;
-+ }
-+ return ret;
-+}
-+
-+/**
-+ * sys_sched_get_priority_min - return minimum RT priority.
-+ * @policy: scheduling class.
-+ *
-+ * Return: On success, this syscall returns the minimum
-+ * rt_priority that can be used by a given scheduling class.
-+ * On failure, a negative error code is returned.
-+ */
-+SYSCALL_DEFINE1(sched_get_priority_min, int, policy)
-+{
-+ int ret = -EINVAL;
-+
-+ switch (policy) {
-+ case SCHED_FIFO:
-+ case SCHED_RR:
-+ ret = 1;
-+ break;
-+ case SCHED_NORMAL:
-+ case SCHED_BATCH:
-+ case SCHED_IDLE:
-+ ret = 0;
-+ break;
-+ }
-+ return ret;
-+}
-+
-+static int sched_rr_get_interval(pid_t pid, struct timespec64 *t)
-+{
-+ struct task_struct *p;
-+ int retval;
-+
-+ alt_sched_debug();
-+
-+ if (pid < 0)
-+ return -EINVAL;
-+
-+ guard(rcu)();
-+ p = find_process_by_pid(pid);
-+ if (!p)
-+ return -EINVAL;
-+
-+ retval = security_task_getscheduler(p);
-+ if (retval)
-+ return retval;
-+
-+ *t = ns_to_timespec64(sysctl_sched_base_slice);
-+ return 0;
-+}
-+
-+/**
-+ * sys_sched_rr_get_interval - return the default timeslice of a process.
-+ * @pid: pid of the process.
-+ * @interval: userspace pointer to the timeslice value.
-+ *
-+ *
-+ * Return: On success, 0 and the timeslice is in @interval. Otherwise,
-+ * an error code.
-+ */
-+SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid,
-+ struct __kernel_timespec __user *, interval)
-+{
-+ struct timespec64 t;
-+ int retval = sched_rr_get_interval(pid, &t);
-+
-+ if (retval == 0)
-+ retval = put_timespec64(&t, interval);
-+
-+ return retval;
-+}
-+
-+#ifdef CONFIG_COMPAT_32BIT_TIME
-+SYSCALL_DEFINE2(sched_rr_get_interval_time32, pid_t, pid,
-+ struct old_timespec32 __user *, interval)
-+{
-+ struct timespec64 t;
-+ int retval = sched_rr_get_interval(pid, &t);
-+
-+ if (retval == 0)
-+ retval = put_old_timespec32(&t, interval);
-+ return retval;
-+}
-+#endif
-+
-+void sched_show_task(struct task_struct *p)
-+{
-+ unsigned long free = 0;
-+ int ppid;
-+
-+ if (!try_get_task_stack(p))
-+ return;
-+
-+ pr_info("task:%-15.15s state:%c", p->comm, task_state_to_char(p));
-+
-+ if (task_is_running(p))
-+ pr_cont(" running task ");
-+#ifdef CONFIG_DEBUG_STACK_USAGE
-+ free = stack_not_used(p);
-+#endif
-+ ppid = 0;
-+ rcu_read_lock();
-+ if (pid_alive(p))
-+ ppid = task_pid_nr(rcu_dereference(p->real_parent));
-+ rcu_read_unlock();
-+ pr_cont(" stack:%-5lu pid:%-5d tgid:%-5d ppid:%-6d flags:0x%08lx\n",
-+ free, task_pid_nr(p), task_tgid_nr(p),
-+ ppid, read_task_thread_flags(p));
-+
-+ print_worker_info(KERN_INFO, p);
-+ print_stop_info(KERN_INFO, p);
-+ show_stack(p, NULL, KERN_INFO);
-+ put_task_stack(p);
-+}
-+EXPORT_SYMBOL_GPL(sched_show_task);
-+
-+static inline bool
-+state_filter_match(unsigned long state_filter, struct task_struct *p)
-+{
-+ unsigned int state = READ_ONCE(p->__state);
-+
-+ /* no filter, everything matches */
-+ if (!state_filter)
-+ return true;
-+
-+ /* filter, but doesn't match */
-+ if (!(state & state_filter))
-+ return false;
-+
-+ /*
-+ * When looking for TASK_UNINTERRUPTIBLE skip TASK_IDLE (allows
-+ * TASK_KILLABLE).
-+ */
-+ if (state_filter == TASK_UNINTERRUPTIBLE && (state & TASK_NOLOAD))
-+ return false;
-+
-+ return true;
-+}
-+
-+
-+void show_state_filter(unsigned int state_filter)
-+{
-+ struct task_struct *g, *p;
-+
-+ rcu_read_lock();
-+ for_each_process_thread(g, p) {
-+ /*
-+ * reset the NMI-timeout, listing all files on a slow
-+ * console might take a lot of time:
-+ * Also, reset softlockup watchdogs on all CPUs, because
-+ * another CPU might be blocked waiting for us to process
-+ * an IPI.
-+ */
-+ touch_nmi_watchdog();
-+ touch_all_softlockup_watchdogs();
-+ if (state_filter_match(state_filter, p))
-+ sched_show_task(p);
-+ }
-+
-+#ifdef CONFIG_SCHED_DEBUG
-+ /* TODO: Alt schedule FW should support this
-+ if (!state_filter)
-+ sysrq_sched_debug_show();
-+ */
-+#endif
-+ rcu_read_unlock();
-+ /*
-+ * Only show locks if all tasks are dumped:
-+ */
-+ if (!state_filter)
-+ debug_show_all_locks();
-+}
-+
-+void dump_cpu_task(int cpu)
-+{
-+ if (cpu == smp_processor_id() && in_hardirq()) {
-+ struct pt_regs *regs;
-+
-+ regs = get_irq_regs();
-+ if (regs) {
-+ show_regs(regs);
-+ return;
-+ }
-+ }
-+
-+ if (trigger_single_cpu_backtrace(cpu))
-+ return;
-+
-+ pr_info("Task dump for CPU %d:\n", cpu);
-+ sched_show_task(cpu_curr(cpu));
-+}
-+
-+/**
-+ * init_idle - set up an idle thread for a given CPU
-+ * @idle: task in question
-+ * @cpu: CPU the idle task belongs to
-+ *
-+ * NOTE: this function does not set the idle thread's NEED_RESCHED
-+ * flag, to make booting more robust.
-+ */
-+void __init init_idle(struct task_struct *idle, int cpu)
-+{
-+#ifdef CONFIG_SMP
-+ struct affinity_context ac = (struct affinity_context) {
-+ .new_mask = cpumask_of(cpu),
-+ .flags = 0,
-+ };
-+#endif
-+ struct rq *rq = cpu_rq(cpu);
-+ unsigned long flags;
-+
-+ __sched_fork(0, idle);
-+
-+ raw_spin_lock_irqsave(&idle->pi_lock, flags);
-+ raw_spin_lock(&rq->lock);
-+
-+ idle->last_ran = rq->clock_task;
-+ idle->__state = TASK_RUNNING;
-+ /*
-+ * PF_KTHREAD should already be set at this point; regardless, make it
-+ * look like a proper per-CPU kthread.
-+ */
-+ idle->flags |= PF_KTHREAD | PF_NO_SETAFFINITY;
-+ kthread_set_per_cpu(idle, cpu);
-+
-+ sched_queue_init_idle(&rq->queue, idle);
-+
-+#ifdef CONFIG_SMP
-+ /*
-+ * It's possible that init_idle() gets called multiple times on a task,
-+ * in that case do_set_cpus_allowed() will not do the right thing.
-+ *
-+ * And since this is boot we can forgo the serialisation.
-+ */
-+ set_cpus_allowed_common(idle, &ac);
-+#endif
-+
-+ /* Silence PROVE_RCU */
-+ rcu_read_lock();
-+ __set_task_cpu(idle, cpu);
-+ rcu_read_unlock();
-+
-+ rq->idle = idle;
-+ rcu_assign_pointer(rq->curr, idle);
-+ idle->on_cpu = 1;
-+
-+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock_irqrestore(&idle->pi_lock, flags);
-+
-+ /* Set the preempt count _outside_ the spinlocks! */
-+ init_idle_preempt_count(idle, cpu);
-+
-+ ftrace_graph_init_idle_task(idle, cpu);
-+ vtime_init_idle(idle, cpu);
-+#ifdef CONFIG_SMP
-+ sprintf(idle->comm, "%s/%d", INIT_TASK_COMM, cpu);
-+#endif
-+}
-+
-+#ifdef CONFIG_SMP
-+
-+int cpuset_cpumask_can_shrink(const struct cpumask __maybe_unused *cur,
-+ const struct cpumask __maybe_unused *trial)
-+{
-+ return 1;
-+}
-+
-+int task_can_attach(struct task_struct *p)
-+{
-+ int ret = 0;
-+
-+ /*
-+ * Kthreads which disallow setaffinity shouldn't be moved
-+ * to a new cpuset; we don't want to change their CPU
-+ * affinity and isolating such threads by their set of
-+ * allowed nodes is unnecessary. Thus, cpusets are not
-+ * applicable for such threads. This prevents checking for
-+ * success of set_cpus_allowed_ptr() on all attached tasks
-+ * before cpus_mask may be changed.
-+ */
-+ if (p->flags & PF_NO_SETAFFINITY)
-+ ret = -EINVAL;
-+
-+ return ret;
-+}
-+
-+bool sched_smp_initialized __read_mostly;
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+/*
-+ * Ensures that the idle task is using init_mm right before its CPU goes
-+ * offline.
-+ */
-+void idle_task_exit(void)
-+{
-+ struct mm_struct *mm = current->active_mm;
-+
-+ BUG_ON(current != this_rq()->idle);
-+
-+ if (mm != &init_mm) {
-+ switch_mm(mm, &init_mm, current);
-+ finish_arch_post_lock_switch();
-+ }
-+
-+ /* finish_cpu(), as ran on the BP, will clean up the active_mm state */
-+}
-+
-+static int __balance_push_cpu_stop(void *arg)
-+{
-+ struct task_struct *p = arg;
-+ struct rq *rq = this_rq();
-+ struct rq_flags rf;
-+ int cpu;
-+
-+ raw_spin_lock_irq(&p->pi_lock);
-+ rq_lock(rq, &rf);
-+
-+ update_rq_clock(rq);
-+
-+ if (task_rq(p) == rq && task_on_rq_queued(p)) {
-+ cpu = select_fallback_rq(rq->cpu, p);
-+ rq = __migrate_task(rq, p, cpu);
-+ }
-+
-+ rq_unlock(rq, &rf);
-+ raw_spin_unlock_irq(&p->pi_lock);
-+
-+ put_task_struct(p);
-+
-+ return 0;
-+}
-+
-+static DEFINE_PER_CPU(struct cpu_stop_work, push_work);
-+
-+/*
-+ * This is enabled below SCHED_AP_ACTIVE; when !cpu_active(), but only
-+ * effective when the hotplug motion is down.
-+ */
-+static void balance_push(struct rq *rq)
-+{
-+ struct task_struct *push_task = rq->curr;
-+
-+ lockdep_assert_held(&rq->lock);
-+
-+ /*
-+ * Ensure the thing is persistent until balance_push_set(.on = false);
-+ */
-+ rq->balance_callback = &balance_push_callback;
-+
-+ /*
-+ * Only active while going offline and when invoked on the outgoing
-+ * CPU.
-+ */
-+ if (!cpu_dying(rq->cpu) || rq != this_rq())
-+ return;
-+
-+ /*
-+ * Both the cpu-hotplug and stop task are in this case and are
-+ * required to complete the hotplug process.
-+ */
-+ if (kthread_is_per_cpu(push_task) ||
-+ is_migration_disabled(push_task)) {
-+
-+ /*
-+ * If this is the idle task on the outgoing CPU try to wake
-+ * up the hotplug control thread which might wait for the
-+ * last task to vanish. The rcuwait_active() check is
-+ * accurate here because the waiter is pinned on this CPU
-+ * and can't obviously be running in parallel.
-+ *
-+ * On RT kernels this also has to check whether there are
-+ * pinned and scheduled out tasks on the runqueue. They
-+ * need to leave the migrate disabled section first.
-+ */
-+ if (!rq->nr_running && !rq_has_pinned_tasks(rq) &&
-+ rcuwait_active(&rq->hotplug_wait)) {
-+ raw_spin_unlock(&rq->lock);
-+ rcuwait_wake_up(&rq->hotplug_wait);
-+ raw_spin_lock(&rq->lock);
-+ }
-+ return;
-+ }
-+
-+ get_task_struct(push_task);
-+ /*
-+ * Temporarily drop rq->lock such that we can wake-up the stop task.
-+ * Both preemption and IRQs are still disabled.
-+ */
-+ preempt_disable();
-+ raw_spin_unlock(&rq->lock);
-+ stop_one_cpu_nowait(rq->cpu, __balance_push_cpu_stop, push_task,
-+ this_cpu_ptr(&push_work));
-+ preempt_enable();
-+ /*
-+ * At this point need_resched() is true and we'll take the loop in
-+ * schedule(). The next pick is obviously going to be the stop task
-+ * which kthread_is_per_cpu() and will push this task away.
-+ */
-+ raw_spin_lock(&rq->lock);
-+}
-+
-+static void balance_push_set(int cpu, bool on)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ struct rq_flags rf;
-+
-+ rq_lock_irqsave(rq, &rf);
-+ if (on) {
-+ WARN_ON_ONCE(rq->balance_callback);
-+ rq->balance_callback = &balance_push_callback;
-+ } else if (rq->balance_callback == &balance_push_callback) {
-+ rq->balance_callback = NULL;
-+ }
-+ rq_unlock_irqrestore(rq, &rf);
-+}
-+
-+/*
-+ * Invoked from a CPUs hotplug control thread after the CPU has been marked
-+ * inactive. All tasks which are not per CPU kernel threads are either
-+ * pushed off this CPU now via balance_push() or placed on a different CPU
-+ * during wakeup. Wait until the CPU is quiescent.
-+ */
-+static void balance_hotplug_wait(void)
-+{
-+ struct rq *rq = this_rq();
-+
-+ rcuwait_wait_event(&rq->hotplug_wait,
-+ rq->nr_running == 1 && !rq_has_pinned_tasks(rq),
-+ TASK_UNINTERRUPTIBLE);
-+}
-+
-+#else
-+
-+static void balance_push(struct rq *rq)
-+{
-+}
-+
-+static void balance_push_set(int cpu, bool on)
-+{
-+}
-+
-+static inline void balance_hotplug_wait(void)
-+{
-+}
-+#endif /* CONFIG_HOTPLUG_CPU */
-+
-+static void set_rq_offline(struct rq *rq)
-+{
-+ if (rq->online) {
-+ update_rq_clock(rq);
-+ rq->online = false;
-+ }
-+}
-+
-+static void set_rq_online(struct rq *rq)
-+{
-+ if (!rq->online)
-+ rq->online = true;
-+}
-+
-+/*
-+ * used to mark begin/end of suspend/resume:
-+ */
-+static int num_cpus_frozen;
-+
-+/*
-+ * Update cpusets according to cpu_active mask. If cpusets are
-+ * disabled, cpuset_update_active_cpus() becomes a simple wrapper
-+ * around partition_sched_domains().
-+ *
-+ * If we come here as part of a suspend/resume, don't touch cpusets because we
-+ * want to restore it back to its original state upon resume anyway.
-+ */
-+static void cpuset_cpu_active(void)
-+{
-+ if (cpuhp_tasks_frozen) {
-+ /*
-+ * num_cpus_frozen tracks how many CPUs are involved in suspend
-+ * resume sequence. As long as this is not the last online
-+ * operation in the resume sequence, just build a single sched
-+ * domain, ignoring cpusets.
-+ */
-+ partition_sched_domains(1, NULL, NULL);
-+ if (--num_cpus_frozen)
-+ return;
-+ /*
-+ * This is the last CPU online operation. So fall through and
-+ * restore the original sched domains by considering the
-+ * cpuset configurations.
-+ */
-+ cpuset_force_rebuild();
-+ }
-+
-+ cpuset_update_active_cpus();
-+}
-+
-+static int cpuset_cpu_inactive(unsigned int cpu)
-+{
-+ if (!cpuhp_tasks_frozen) {
-+ cpuset_update_active_cpus();
-+ } else {
-+ num_cpus_frozen++;
-+ partition_sched_domains(1, NULL, NULL);
-+ }
-+ return 0;
-+}
-+
-+int sched_cpu_activate(unsigned int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ unsigned long flags;
-+
-+ /*
-+ * Clear the balance_push callback and prepare to schedule
-+ * regular tasks.
-+ */
-+ balance_push_set(cpu, false);
-+
-+#ifdef CONFIG_SCHED_SMT
-+ /*
-+ * When going up, increment the number of cores with SMT present.
-+ */
-+ if (cpumask_weight(cpu_smt_mask(cpu)) == 2)
-+ static_branch_inc_cpuslocked(&sched_smt_present);
-+#endif
-+ set_cpu_active(cpu, true);
-+
-+ if (sched_smp_initialized)
-+ cpuset_cpu_active();
-+
-+ /*
-+ * Put the rq online, if not already. This happens:
-+ *
-+ * 1) In the early boot process, because we build the real domains
-+ * after all cpus have been brought up.
-+ *
-+ * 2) At runtime, if cpuset_cpu_active() fails to rebuild the
-+ * domains.
-+ */
-+ raw_spin_lock_irqsave(&rq->lock, flags);
-+ set_rq_online(rq);
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+
-+ return 0;
-+}
-+
-+int sched_cpu_deactivate(unsigned int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ unsigned long flags;
-+ int ret;
-+
-+ set_cpu_active(cpu, false);
-+
-+ /*
-+ * From this point forward, this CPU will refuse to run any task that
-+ * is not: migrate_disable() or KTHREAD_IS_PER_CPU, and will actively
-+ * push those tasks away until this gets cleared, see
-+ * sched_cpu_dying().
-+ */
-+ balance_push_set(cpu, true);
-+
-+ /*
-+ * We've cleared cpu_active_mask, wait for all preempt-disabled and RCU
-+ * users of this state to go away such that all new such users will
-+ * observe it.
-+ *
-+ * Specifically, we rely on ttwu to no longer target this CPU, see
-+ * ttwu_queue_cond() and is_cpu_allowed().
-+ *
-+ * Do sync before park smpboot threads to take care the rcu boost case.
-+ */
-+ synchronize_rcu();
-+
-+ raw_spin_lock_irqsave(&rq->lock, flags);
-+ set_rq_offline(rq);
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+
-+#ifdef CONFIG_SCHED_SMT
-+ /*
-+ * When going down, decrement the number of cores with SMT present.
-+ */
-+ if (cpumask_weight(cpu_smt_mask(cpu)) == 2) {
-+ static_branch_dec_cpuslocked(&sched_smt_present);
-+ if (!static_branch_likely(&sched_smt_present))
-+ cpumask_clear(&sched_sg_idle_mask);
-+ }
-+#endif
-+
-+ if (!sched_smp_initialized)
-+ return 0;
-+
-+ ret = cpuset_cpu_inactive(cpu);
-+ if (ret) {
-+ balance_push_set(cpu, false);
-+ set_cpu_active(cpu, true);
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static void sched_rq_cpu_starting(unsigned int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+
-+ rq->calc_load_update = calc_load_update;
-+}
-+
-+int sched_cpu_starting(unsigned int cpu)
-+{
-+ sched_rq_cpu_starting(cpu);
-+ sched_tick_start(cpu);
-+ return 0;
-+}
-+
-+#ifdef CONFIG_HOTPLUG_CPU
-+
-+/*
-+ * Invoked immediately before the stopper thread is invoked to bring the
-+ * CPU down completely. At this point all per CPU kthreads except the
-+ * hotplug thread (current) and the stopper thread (inactive) have been
-+ * either parked or have been unbound from the outgoing CPU. Ensure that
-+ * any of those which might be on the way out are gone.
-+ *
-+ * If after this point a bound task is being woken on this CPU then the
-+ * responsible hotplug callback has failed to do it's job.
-+ * sched_cpu_dying() will catch it with the appropriate fireworks.
-+ */
-+int sched_cpu_wait_empty(unsigned int cpu)
-+{
-+ balance_hotplug_wait();
-+ return 0;
-+}
-+
-+/*
-+ * Since this CPU is going 'away' for a while, fold any nr_active delta we
-+ * might have. Called from the CPU stopper task after ensuring that the
-+ * stopper is the last running task on the CPU, so nr_active count is
-+ * stable. We need to take the teardown thread which is calling this into
-+ * account, so we hand in adjust = 1 to the load calculation.
-+ *
-+ * Also see the comment "Global load-average calculations".
-+ */
-+static void calc_load_migrate(struct rq *rq)
-+{
-+ long delta = calc_load_fold_active(rq, 1);
-+
-+ if (delta)
-+ atomic_long_add(delta, &calc_load_tasks);
-+}
-+
-+static void dump_rq_tasks(struct rq *rq, const char *loglvl)
-+{
-+ struct task_struct *g, *p;
-+ int cpu = cpu_of(rq);
-+
-+ lockdep_assert_held(&rq->lock);
-+
-+ printk("%sCPU%d enqueued tasks (%u total):\n", loglvl, cpu, rq->nr_running);
-+ for_each_process_thread(g, p) {
-+ if (task_cpu(p) != cpu)
-+ continue;
-+
-+ if (!task_on_rq_queued(p))
-+ continue;
-+
-+ printk("%s\tpid: %d, name: %s\n", loglvl, p->pid, p->comm);
-+ }
-+}
-+
-+int sched_cpu_dying(unsigned int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ unsigned long flags;
-+
-+ /* Handle pending wakeups and then migrate everything off */
-+ sched_tick_stop(cpu);
-+
-+ raw_spin_lock_irqsave(&rq->lock, flags);
-+ if (rq->nr_running != 1 || rq_has_pinned_tasks(rq)) {
-+ WARN(true, "Dying CPU not properly vacated!");
-+ dump_rq_tasks(rq, KERN_WARNING);
-+ }
-+ raw_spin_unlock_irqrestore(&rq->lock, flags);
-+
-+ calc_load_migrate(rq);
-+ hrtick_clear(rq);
-+ return 0;
-+}
-+#endif
-+
-+#ifdef CONFIG_SMP
-+static void sched_init_topology_cpumask_early(void)
-+{
-+ int cpu;
-+ cpumask_t *tmp;
-+
-+ for_each_possible_cpu(cpu) {
-+ /* init topo masks */
-+ tmp = per_cpu(sched_cpu_topo_masks, cpu);
-+
-+ cpumask_copy(tmp, cpumask_of(cpu));
-+ tmp++;
-+ cpumask_copy(tmp, cpu_possible_mask);
-+ per_cpu(sched_cpu_llc_mask, cpu) = tmp;
-+ per_cpu(sched_cpu_topo_end_mask, cpu) = ++tmp;
-+ /*per_cpu(sd_llc_id, cpu) = cpu;*/
-+ }
-+}
-+
-+#define TOPOLOGY_CPUMASK(name, mask, last)\
-+ if (cpumask_and(topo, topo, mask)) { \
-+ cpumask_copy(topo, mask); \
-+ printk(KERN_INFO "sched: cpu#%02d topo: 0x%08lx - "#name, \
-+ cpu, (topo++)->bits[0]); \
-+ } \
-+ if (!last) \
-+ bitmap_complement(cpumask_bits(topo), cpumask_bits(mask), \
-+ nr_cpumask_bits);
-+
-+static void sched_init_topology_cpumask(void)
-+{
-+ int cpu;
-+ cpumask_t *topo;
-+
-+ for_each_online_cpu(cpu) {
-+ /* take chance to reset time slice for idle tasks */
-+ cpu_rq(cpu)->idle->time_slice = sysctl_sched_base_slice;
-+
-+ topo = per_cpu(sched_cpu_topo_masks, cpu) + 1;
-+
-+ bitmap_complement(cpumask_bits(topo), cpumask_bits(cpumask_of(cpu)),
-+ nr_cpumask_bits);
-+#ifdef CONFIG_SCHED_SMT
-+ TOPOLOGY_CPUMASK(smt, topology_sibling_cpumask(cpu), false);
-+#endif
-+ per_cpu(sd_llc_id, cpu) = cpumask_first(cpu_coregroup_mask(cpu));
-+ per_cpu(sched_cpu_llc_mask, cpu) = topo;
-+ TOPOLOGY_CPUMASK(coregroup, cpu_coregroup_mask(cpu), false);
-+
-+ TOPOLOGY_CPUMASK(core, topology_core_cpumask(cpu), false);
-+
-+ TOPOLOGY_CPUMASK(others, cpu_online_mask, true);
-+
-+ per_cpu(sched_cpu_topo_end_mask, cpu) = topo;
-+ printk(KERN_INFO "sched: cpu#%02d llc_id = %d, llc_mask idx = %d\n",
-+ cpu, per_cpu(sd_llc_id, cpu),
-+ (int) (per_cpu(sched_cpu_llc_mask, cpu) -
-+ per_cpu(sched_cpu_topo_masks, cpu)));
-+ }
-+}
-+#endif
-+
-+void __init sched_init_smp(void)
-+{
-+ /* Move init over to a non-isolated CPU */
-+ if (set_cpus_allowed_ptr(current, housekeeping_cpumask(HK_TYPE_DOMAIN)) < 0)
-+ BUG();
-+ current->flags &= ~PF_NO_SETAFFINITY;
-+
-+ sched_init_topology_cpumask();
-+
-+ sched_smp_initialized = true;
-+}
-+
-+static int __init migration_init(void)
-+{
-+ sched_cpu_starting(smp_processor_id());
-+ return 0;
-+}
-+early_initcall(migration_init);
-+
-+#else
-+void __init sched_init_smp(void)
-+{
-+ cpu_rq(0)->idle->time_slice = sysctl_sched_base_slice;
-+}
-+#endif /* CONFIG_SMP */
-+
-+int in_sched_functions(unsigned long addr)
-+{
-+ return in_lock_functions(addr) ||
-+ (addr >= (unsigned long)__sched_text_start
-+ && addr < (unsigned long)__sched_text_end);
-+}
-+
-+#ifdef CONFIG_CGROUP_SCHED
-+/*
-+ * Default task group.
-+ * Every task in system belongs to this group at bootup.
-+ */
-+struct task_group root_task_group;
-+LIST_HEAD(task_groups);
-+
-+/* Cacheline aligned slab cache for task_group */
-+static struct kmem_cache *task_group_cache __ro_after_init;
-+#endif /* CONFIG_CGROUP_SCHED */
-+
-+void __init sched_init(void)
-+{
-+ int i;
-+ struct rq *rq;
-+
-+ printk(KERN_INFO "sched/alt: "ALT_SCHED_NAME" CPU Scheduler "ALT_SCHED_VERSION\
-+ " by Alfred Chen.\n");
-+
-+ wait_bit_init();
-+
-+#ifdef CONFIG_SMP
-+ for (i = 0; i < SCHED_QUEUE_BITS; i++)
-+ cpumask_copy(sched_preempt_mask + i, cpu_present_mask);
-+#endif
-+
-+#ifdef CONFIG_CGROUP_SCHED
-+ task_group_cache = KMEM_CACHE(task_group, 0);
-+
-+ list_add(&root_task_group.list, &task_groups);
-+ INIT_LIST_HEAD(&root_task_group.children);
-+ INIT_LIST_HEAD(&root_task_group.siblings);
-+#endif /* CONFIG_CGROUP_SCHED */
-+ for_each_possible_cpu(i) {
-+ rq = cpu_rq(i);
-+
-+ sched_queue_init(&rq->queue);
-+ rq->prio = IDLE_TASK_SCHED_PRIO;
-+ rq->skip = NULL;
-+
-+ raw_spin_lock_init(&rq->lock);
-+ rq->nr_running = rq->nr_uninterruptible = 0;
-+ rq->calc_load_active = 0;
-+ rq->calc_load_update = jiffies + LOAD_FREQ;
-+#ifdef CONFIG_SMP
-+ rq->online = false;
-+ rq->cpu = i;
-+
-+#ifdef CONFIG_SCHED_SMT
-+ rq->active_balance = 0;
-+#endif
-+
-+#ifdef CONFIG_NO_HZ_COMMON
-+ INIT_CSD(&rq->nohz_csd, nohz_csd_func, rq);
-+#endif
-+ rq->balance_callback = &balance_push_callback;
-+#ifdef CONFIG_HOTPLUG_CPU
-+ rcuwait_init(&rq->hotplug_wait);
-+#endif
-+#endif /* CONFIG_SMP */
-+ rq->nr_switches = 0;
-+
-+ hrtick_rq_init(rq);
-+ atomic_set(&rq->nr_iowait, 0);
-+
-+ zalloc_cpumask_var_node(&rq->scratch_mask, GFP_KERNEL, cpu_to_node(i));
-+ }
-+#ifdef CONFIG_SMP
-+ /* Set rq->online for cpu 0 */
-+ cpu_rq(0)->online = true;
-+#endif
-+ /*
-+ * The boot idle thread does lazy MMU switching as well:
-+ */
-+ mmgrab(&init_mm);
-+ enter_lazy_tlb(&init_mm, current);
-+
-+ /*
-+ * The idle task doesn't need the kthread struct to function, but it
-+ * is dressed up as a per-CPU kthread and thus needs to play the part
-+ * if we want to avoid special-casing it in code that deals with per-CPU
-+ * kthreads.
-+ */
-+ WARN_ON(!set_kthread_struct(current));
-+
-+ /*
-+ * Make us the idle thread. Technically, schedule() should not be
-+ * called from this thread, however somewhere below it might be,
-+ * but because we are the idle thread, we just pick up running again
-+ * when this runqueue becomes "idle".
-+ */
-+ init_idle(current, smp_processor_id());
-+
-+ calc_load_update = jiffies + LOAD_FREQ;
-+
-+#ifdef CONFIG_SMP
-+ idle_thread_set_boot_cpu();
-+ balance_push_set(smp_processor_id(), false);
-+
-+ sched_init_topology_cpumask_early();
-+#endif /* SMP */
-+
-+ preempt_dynamic_init();
-+}
-+
-+#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
-+
-+void __might_sleep(const char *file, int line)
-+{
-+ unsigned int state = get_current_state();
-+ /*
-+ * Blocking primitives will set (and therefore destroy) current->state,
-+ * since we will exit with TASK_RUNNING make sure we enter with it,
-+ * otherwise we will destroy state.
-+ */
-+ WARN_ONCE(state != TASK_RUNNING && current->task_state_change,
-+ "do not call blocking ops when !TASK_RUNNING; "
-+ "state=%x set at [<%p>] %pS\n", state,
-+ (void *)current->task_state_change,
-+ (void *)current->task_state_change);
-+
-+ __might_resched(file, line, 0);
-+}
-+EXPORT_SYMBOL(__might_sleep);
-+
-+static void print_preempt_disable_ip(int preempt_offset, unsigned long ip)
-+{
-+ if (!IS_ENABLED(CONFIG_DEBUG_PREEMPT))
-+ return;
-+
-+ if (preempt_count() == preempt_offset)
-+ return;
-+
-+ pr_err("Preemption disabled at:");
-+ print_ip_sym(KERN_ERR, ip);
-+}
-+
-+static inline bool resched_offsets_ok(unsigned int offsets)
-+{
-+ unsigned int nested = preempt_count();
-+
-+ nested += rcu_preempt_depth() << MIGHT_RESCHED_RCU_SHIFT;
-+
-+ return nested == offsets;
-+}
-+
-+void __might_resched(const char *file, int line, unsigned int offsets)
-+{
-+ /* Ratelimiting timestamp: */
-+ static unsigned long prev_jiffy;
-+
-+ unsigned long preempt_disable_ip;
-+
-+ /* WARN_ON_ONCE() by default, no rate limit required: */
-+ rcu_sleep_check();
-+
-+ if ((resched_offsets_ok(offsets) && !irqs_disabled() &&
-+ !is_idle_task(current) && !current->non_block_count) ||
-+ system_state == SYSTEM_BOOTING || system_state > SYSTEM_RUNNING ||
-+ oops_in_progress)
-+ return;
-+ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
-+ return;
-+ prev_jiffy = jiffies;
-+
-+ /* Save this before calling printk(), since that will clobber it: */
-+ preempt_disable_ip = get_preempt_disable_ip(current);
-+
-+ pr_err("BUG: sleeping function called from invalid context at %s:%d\n",
-+ file, line);
-+ pr_err("in_atomic(): %d, irqs_disabled(): %d, non_block: %d, pid: %d, name: %s\n",
-+ in_atomic(), irqs_disabled(), current->non_block_count,
-+ current->pid, current->comm);
-+ pr_err("preempt_count: %x, expected: %x\n", preempt_count(),
-+ offsets & MIGHT_RESCHED_PREEMPT_MASK);
-+
-+ if (IS_ENABLED(CONFIG_PREEMPT_RCU)) {
-+ pr_err("RCU nest depth: %d, expected: %u\n",
-+ rcu_preempt_depth(), offsets >> MIGHT_RESCHED_RCU_SHIFT);
-+ }
-+
-+ if (task_stack_end_corrupted(current))
-+ pr_emerg("Thread overran stack, or stack corrupted\n");
-+
-+ debug_show_held_locks(current);
-+ if (irqs_disabled())
-+ print_irqtrace_events(current);
-+
-+ print_preempt_disable_ip(offsets & MIGHT_RESCHED_PREEMPT_MASK,
-+ preempt_disable_ip);
-+
-+ dump_stack();
-+ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
-+}
-+EXPORT_SYMBOL(__might_resched);
-+
-+void __cant_sleep(const char *file, int line, int preempt_offset)
-+{
-+ static unsigned long prev_jiffy;
-+
-+ if (irqs_disabled())
-+ return;
-+
-+ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT))
-+ return;
-+
-+ if (preempt_count() > preempt_offset)
-+ return;
-+
-+ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
-+ return;
-+ prev_jiffy = jiffies;
-+
-+ printk(KERN_ERR "BUG: assuming atomic context at %s:%d\n", file, line);
-+ printk(KERN_ERR "in_atomic(): %d, irqs_disabled(): %d, pid: %d, name: %s\n",
-+ in_atomic(), irqs_disabled(),
-+ current->pid, current->comm);
-+
-+ debug_show_held_locks(current);
-+ dump_stack();
-+ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
-+}
-+EXPORT_SYMBOL_GPL(__cant_sleep);
-+
-+#ifdef CONFIG_SMP
-+void __cant_migrate(const char *file, int line)
-+{
-+ static unsigned long prev_jiffy;
-+
-+ if (irqs_disabled())
-+ return;
-+
-+ if (is_migration_disabled(current))
-+ return;
-+
-+ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT))
-+ return;
-+
-+ if (preempt_count() > 0)
-+ return;
-+
-+ if (current->migration_flags & MDF_FORCE_ENABLED)
-+ return;
-+
-+ if (time_before(jiffies, prev_jiffy + HZ) && prev_jiffy)
-+ return;
-+ prev_jiffy = jiffies;
-+
-+ pr_err("BUG: assuming non migratable context at %s:%d\n", file, line);
-+ pr_err("in_atomic(): %d, irqs_disabled(): %d, migration_disabled() %u pid: %d, name: %s\n",
-+ in_atomic(), irqs_disabled(), is_migration_disabled(current),
-+ current->pid, current->comm);
-+
-+ debug_show_held_locks(current);
-+ dump_stack();
-+ add_taint(TAINT_WARN, LOCKDEP_STILL_OK);
-+}
-+EXPORT_SYMBOL_GPL(__cant_migrate);
-+#endif
-+#endif
-+
-+#ifdef CONFIG_MAGIC_SYSRQ
-+void normalize_rt_tasks(void)
-+{
-+ struct task_struct *g, *p;
-+ struct sched_attr attr = {
-+ .sched_policy = SCHED_NORMAL,
-+ };
-+
-+ read_lock(&tasklist_lock);
-+ for_each_process_thread(g, p) {
-+ /*
-+ * Only normalize user tasks:
-+ */
-+ if (p->flags & PF_KTHREAD)
-+ continue;
-+
-+ schedstat_set(p->stats.wait_start, 0);
-+ schedstat_set(p->stats.sleep_start, 0);
-+ schedstat_set(p->stats.block_start, 0);
-+
-+ if (!rt_task(p)) {
-+ /*
-+ * Renice negative nice level userspace
-+ * tasks back to 0:
-+ */
-+ if (task_nice(p) < 0)
-+ set_user_nice(p, 0);
-+ continue;
-+ }
-+
-+ __sched_setscheduler(p, &attr, false, false);
-+ }
-+ read_unlock(&tasklist_lock);
-+}
-+#endif /* CONFIG_MAGIC_SYSRQ */
-+
-+#if defined(CONFIG_KGDB_KDB)
-+/*
-+ * These functions are only useful for kdb.
-+ *
-+ * They can only be called when the whole system has been
-+ * stopped - every CPU needs to be quiescent, and no scheduling
-+ * activity can take place. Using them for anything else would
-+ * be a serious bug, and as a result, they aren't even visible
-+ * under any other configuration.
-+ */
-+
-+/**
-+ * curr_task - return the current task for a given CPU.
-+ * @cpu: the processor in question.
-+ *
-+ * ONLY VALID WHEN THE WHOLE SYSTEM IS STOPPED!
-+ *
-+ * Return: The current task for @cpu.
-+ */
-+struct task_struct *curr_task(int cpu)
-+{
-+ return cpu_curr(cpu);
-+}
-+
-+#endif /* defined(CONFIG_KGDB_KDB) */
-+
-+#ifdef CONFIG_CGROUP_SCHED
-+static void sched_free_group(struct task_group *tg)
-+{
-+ kmem_cache_free(task_group_cache, tg);
-+}
-+
-+static void sched_free_group_rcu(struct rcu_head *rhp)
-+{
-+ sched_free_group(container_of(rhp, struct task_group, rcu));
-+}
-+
-+static void sched_unregister_group(struct task_group *tg)
-+{
-+ /*
-+ * We have to wait for yet another RCU grace period to expire, as
-+ * print_cfs_stats() might run concurrently.
-+ */
-+ call_rcu(&tg->rcu, sched_free_group_rcu);
-+}
-+
-+/* allocate runqueue etc for a new task group */
-+struct task_group *sched_create_group(struct task_group *parent)
-+{
-+ struct task_group *tg;
-+
-+ tg = kmem_cache_alloc(task_group_cache, GFP_KERNEL | __GFP_ZERO);
-+ if (!tg)
-+ return ERR_PTR(-ENOMEM);
-+
-+ return tg;
-+}
-+
-+void sched_online_group(struct task_group *tg, struct task_group *parent)
-+{
-+}
-+
-+/* rcu callback to free various structures associated with a task group */
-+static void sched_unregister_group_rcu(struct rcu_head *rhp)
-+{
-+ /* Now it should be safe to free those cfs_rqs: */
-+ sched_unregister_group(container_of(rhp, struct task_group, rcu));
-+}
-+
-+void sched_destroy_group(struct task_group *tg)
-+{
-+ /* Wait for possible concurrent references to cfs_rqs complete: */
-+ call_rcu(&tg->rcu, sched_unregister_group_rcu);
-+}
-+
-+void sched_release_group(struct task_group *tg)
-+{
-+}
-+
-+static inline struct task_group *css_tg(struct cgroup_subsys_state *css)
-+{
-+ return css ? container_of(css, struct task_group, css) : NULL;
-+}
-+
-+static struct cgroup_subsys_state *
-+cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
-+{
-+ struct task_group *parent = css_tg(parent_css);
-+ struct task_group *tg;
-+
-+ if (!parent) {
-+ /* This is early initialization for the top cgroup */
-+ return &root_task_group.css;
-+ }
-+
-+ tg = sched_create_group(parent);
-+ if (IS_ERR(tg))
-+ return ERR_PTR(-ENOMEM);
-+ return &tg->css;
-+}
-+
-+/* Expose task group only after completing cgroup initialization */
-+static int cpu_cgroup_css_online(struct cgroup_subsys_state *css)
-+{
-+ struct task_group *tg = css_tg(css);
-+ struct task_group *parent = css_tg(css->parent);
-+
-+ if (parent)
-+ sched_online_group(tg, parent);
-+ return 0;
-+}
-+
-+static void cpu_cgroup_css_released(struct cgroup_subsys_state *css)
-+{
-+ struct task_group *tg = css_tg(css);
-+
-+ sched_release_group(tg);
-+}
-+
-+static void cpu_cgroup_css_free(struct cgroup_subsys_state *css)
-+{
-+ struct task_group *tg = css_tg(css);
-+
-+ /*
-+ * Relies on the RCU grace period between css_released() and this.
-+ */
-+ sched_unregister_group(tg);
-+}
-+
-+#ifdef CONFIG_RT_GROUP_SCHED
-+static int cpu_cgroup_can_attach(struct cgroup_taskset *tset)
-+{
-+ return 0;
-+}
-+#endif
-+
-+static void cpu_cgroup_attach(struct cgroup_taskset *tset)
-+{
-+}
-+
-+#ifdef CONFIG_FAIR_GROUP_SCHED
-+static DEFINE_MUTEX(shares_mutex);
-+
-+int sched_group_set_shares(struct task_group *tg, unsigned long shares)
-+{
-+ /*
-+ * We can't change the weight of the root cgroup.
-+ */
-+ if (&root_task_group == tg)
-+ return -EINVAL;
-+
-+ shares = clamp(shares, scale_load(MIN_SHARES), scale_load(MAX_SHARES));
-+
-+ mutex_lock(&shares_mutex);
-+ if (tg->shares == shares)
-+ goto done;
-+
-+ tg->shares = shares;
-+done:
-+ mutex_unlock(&shares_mutex);
-+ return 0;
-+}
-+
-+static int cpu_shares_write_u64(struct cgroup_subsys_state *css,
-+ struct cftype *cftype, u64 shareval)
-+{
-+ if (shareval > scale_load_down(ULONG_MAX))
-+ shareval = MAX_SHARES;
-+ return sched_group_set_shares(css_tg(css), scale_load(shareval));
-+}
-+
-+static u64 cpu_shares_read_u64(struct cgroup_subsys_state *css,
-+ struct cftype *cft)
-+{
-+ struct task_group *tg = css_tg(css);
-+
-+ return (u64) scale_load_down(tg->shares);
-+}
-+#endif
-+
-+static s64 cpu_cfs_quota_read_s64(struct cgroup_subsys_state *css,
-+ struct cftype *cft)
-+{
-+ return 0;
-+}
-+
-+static int cpu_cfs_quota_write_s64(struct cgroup_subsys_state *css,
-+ struct cftype *cftype, s64 cfs_quota_us)
-+{
-+ return 0;
-+}
-+
-+static u64 cpu_cfs_period_read_u64(struct cgroup_subsys_state *css,
-+ struct cftype *cft)
-+{
-+ return 0;
-+}
-+
-+static int cpu_cfs_period_write_u64(struct cgroup_subsys_state *css,
-+ struct cftype *cftype, u64 cfs_period_us)
-+{
-+ return 0;
-+}
-+
-+static u64 cpu_cfs_burst_read_u64(struct cgroup_subsys_state *css,
-+ struct cftype *cft)
-+{
-+ return 0;
-+}
-+
-+static int cpu_cfs_burst_write_u64(struct cgroup_subsys_state *css,
-+ struct cftype *cftype, u64 cfs_burst_us)
-+{
-+ return 0;
-+}
-+
-+static int cpu_cfs_stat_show(struct seq_file *sf, void *v)
-+{
-+ return 0;
-+}
-+
-+static int cpu_cfs_local_stat_show(struct seq_file *sf, void *v)
-+{
-+ return 0;
-+}
-+
-+static int cpu_rt_runtime_write(struct cgroup_subsys_state *css,
-+ struct cftype *cft, s64 val)
-+{
-+ return 0;
-+}
-+
-+static s64 cpu_rt_runtime_read(struct cgroup_subsys_state *css,
-+ struct cftype *cft)
-+{
-+ return 0;
-+}
-+
-+static int cpu_rt_period_write_uint(struct cgroup_subsys_state *css,
-+ struct cftype *cftype, u64 rt_period_us)
-+{
-+ return 0;
-+}
-+
-+static u64 cpu_rt_period_read_uint(struct cgroup_subsys_state *css,
-+ struct cftype *cft)
-+{
-+ return 0;
-+}
-+
-+static int cpu_uclamp_min_show(struct seq_file *sf, void *v)
-+{
-+ return 0;
-+}
-+
-+static int cpu_uclamp_max_show(struct seq_file *sf, void *v)
-+{
-+ return 0;
-+}
-+
-+static ssize_t cpu_uclamp_min_write(struct kernfs_open_file *of,
-+ char *buf, size_t nbytes,
-+ loff_t off)
-+{
-+ return nbytes;
-+}
-+
-+static ssize_t cpu_uclamp_max_write(struct kernfs_open_file *of,
-+ char *buf, size_t nbytes,
-+ loff_t off)
-+{
-+ return nbytes;
-+}
-+
-+static struct cftype cpu_legacy_files[] = {
-+#ifdef CONFIG_FAIR_GROUP_SCHED
-+ {
-+ .name = "shares",
-+ .read_u64 = cpu_shares_read_u64,
-+ .write_u64 = cpu_shares_write_u64,
-+ },
-+#endif
-+ {
-+ .name = "cfs_quota_us",
-+ .read_s64 = cpu_cfs_quota_read_s64,
-+ .write_s64 = cpu_cfs_quota_write_s64,
-+ },
-+ {
-+ .name = "cfs_period_us",
-+ .read_u64 = cpu_cfs_period_read_u64,
-+ .write_u64 = cpu_cfs_period_write_u64,
-+ },
-+ {
-+ .name = "cfs_burst_us",
-+ .read_u64 = cpu_cfs_burst_read_u64,
-+ .write_u64 = cpu_cfs_burst_write_u64,
-+ },
-+ {
-+ .name = "stat",
-+ .seq_show = cpu_cfs_stat_show,
-+ },
-+ {
-+ .name = "stat.local",
-+ .seq_show = cpu_cfs_local_stat_show,
-+ },
-+ {
-+ .name = "rt_runtime_us",
-+ .read_s64 = cpu_rt_runtime_read,
-+ .write_s64 = cpu_rt_runtime_write,
-+ },
-+ {
-+ .name = "rt_period_us",
-+ .read_u64 = cpu_rt_period_read_uint,
-+ .write_u64 = cpu_rt_period_write_uint,
-+ },
-+ {
-+ .name = "uclamp.min",
-+ .flags = CFTYPE_NOT_ON_ROOT,
-+ .seq_show = cpu_uclamp_min_show,
-+ .write = cpu_uclamp_min_write,
-+ },
-+ {
-+ .name = "uclamp.max",
-+ .flags = CFTYPE_NOT_ON_ROOT,
-+ .seq_show = cpu_uclamp_max_show,
-+ .write = cpu_uclamp_max_write,
-+ },
-+ { } /* Terminate */
-+};
-+
-+static u64 cpu_weight_read_u64(struct cgroup_subsys_state *css,
-+ struct cftype *cft)
-+{
-+ return 0;
-+}
-+
-+static int cpu_weight_write_u64(struct cgroup_subsys_state *css,
-+ struct cftype *cft, u64 weight)
-+{
-+ return 0;
-+}
-+
-+static s64 cpu_weight_nice_read_s64(struct cgroup_subsys_state *css,
-+ struct cftype *cft)
-+{
-+ return 0;
-+}
-+
-+static int cpu_weight_nice_write_s64(struct cgroup_subsys_state *css,
-+ struct cftype *cft, s64 nice)
-+{
-+ return 0;
-+}
-+
-+static s64 cpu_idle_read_s64(struct cgroup_subsys_state *css,
-+ struct cftype *cft)
-+{
-+ return 0;
-+}
-+
-+static int cpu_idle_write_s64(struct cgroup_subsys_state *css,
-+ struct cftype *cft, s64 idle)
-+{
-+ return 0;
-+}
-+
-+static int cpu_max_show(struct seq_file *sf, void *v)
-+{
-+ return 0;
-+}
-+
-+static ssize_t cpu_max_write(struct kernfs_open_file *of,
-+ char *buf, size_t nbytes, loff_t off)
-+{
-+ return nbytes;
-+}
-+
-+static struct cftype cpu_files[] = {
-+ {
-+ .name = "weight",
-+ .flags = CFTYPE_NOT_ON_ROOT,
-+ .read_u64 = cpu_weight_read_u64,
-+ .write_u64 = cpu_weight_write_u64,
-+ },
-+ {
-+ .name = "weight.nice",
-+ .flags = CFTYPE_NOT_ON_ROOT,
-+ .read_s64 = cpu_weight_nice_read_s64,
-+ .write_s64 = cpu_weight_nice_write_s64,
-+ },
-+ {
-+ .name = "idle",
-+ .flags = CFTYPE_NOT_ON_ROOT,
-+ .read_s64 = cpu_idle_read_s64,
-+ .write_s64 = cpu_idle_write_s64,
-+ },
-+ {
-+ .name = "max",
-+ .flags = CFTYPE_NOT_ON_ROOT,
-+ .seq_show = cpu_max_show,
-+ .write = cpu_max_write,
-+ },
-+ {
-+ .name = "max.burst",
-+ .flags = CFTYPE_NOT_ON_ROOT,
-+ .read_u64 = cpu_cfs_burst_read_u64,
-+ .write_u64 = cpu_cfs_burst_write_u64,
-+ },
-+ {
-+ .name = "uclamp.min",
-+ .flags = CFTYPE_NOT_ON_ROOT,
-+ .seq_show = cpu_uclamp_min_show,
-+ .write = cpu_uclamp_min_write,
-+ },
-+ {
-+ .name = "uclamp.max",
-+ .flags = CFTYPE_NOT_ON_ROOT,
-+ .seq_show = cpu_uclamp_max_show,
-+ .write = cpu_uclamp_max_write,
-+ },
-+ { } /* terminate */
-+};
-+
-+static int cpu_extra_stat_show(struct seq_file *sf,
-+ struct cgroup_subsys_state *css)
-+{
-+ return 0;
-+}
-+
-+static int cpu_local_stat_show(struct seq_file *sf,
-+ struct cgroup_subsys_state *css)
-+{
-+ return 0;
-+}
-+
-+struct cgroup_subsys cpu_cgrp_subsys = {
-+ .css_alloc = cpu_cgroup_css_alloc,
-+ .css_online = cpu_cgroup_css_online,
-+ .css_released = cpu_cgroup_css_released,
-+ .css_free = cpu_cgroup_css_free,
-+ .css_extra_stat_show = cpu_extra_stat_show,
-+ .css_local_stat_show = cpu_local_stat_show,
-+#ifdef CONFIG_RT_GROUP_SCHED
-+ .can_attach = cpu_cgroup_can_attach,
-+#endif
-+ .attach = cpu_cgroup_attach,
-+ .legacy_cftypes = cpu_legacy_files,
-+ .dfl_cftypes = cpu_files,
-+ .early_init = true,
-+ .threaded = true,
-+};
-+#endif /* CONFIG_CGROUP_SCHED */
-+
-+#undef CREATE_TRACE_POINTS
-+
-+#ifdef CONFIG_SCHED_MM_CID
-+
-+#
-+/*
-+ * @cid_lock: Guarantee forward-progress of cid allocation.
-+ *
-+ * Concurrency ID allocation within a bitmap is mostly lock-free. The cid_lock
-+ * is only used when contention is detected by the lock-free allocation so
-+ * forward progress can be guaranteed.
-+ */
-+DEFINE_RAW_SPINLOCK(cid_lock);
-+
-+/*
-+ * @use_cid_lock: Select cid allocation behavior: lock-free vs spinlock.
-+ *
-+ * When @use_cid_lock is 0, the cid allocation is lock-free. When contention is
-+ * detected, it is set to 1 to ensure that all newly coming allocations are
-+ * serialized by @cid_lock until the allocation which detected contention
-+ * completes and sets @use_cid_lock back to 0. This guarantees forward progress
-+ * of a cid allocation.
-+ */
-+int use_cid_lock;
-+
-+/*
-+ * mm_cid remote-clear implements a lock-free algorithm to clear per-mm/cpu cid
-+ * concurrently with respect to the execution of the source runqueue context
-+ * switch.
-+ *
-+ * There is one basic properties we want to guarantee here:
-+ *
-+ * (1) Remote-clear should _never_ mark a per-cpu cid UNSET when it is actively
-+ * used by a task. That would lead to concurrent allocation of the cid and
-+ * userspace corruption.
-+ *
-+ * Provide this guarantee by introducing a Dekker memory ordering to guarantee
-+ * that a pair of loads observe at least one of a pair of stores, which can be
-+ * shown as:
-+ *
-+ * X = Y = 0
-+ *
-+ * w[X]=1 w[Y]=1
-+ * MB MB
-+ * r[Y]=y r[X]=x
-+ *
-+ * Which guarantees that x==0 && y==0 is impossible. But rather than using
-+ * values 0 and 1, this algorithm cares about specific state transitions of the
-+ * runqueue current task (as updated by the scheduler context switch), and the
-+ * per-mm/cpu cid value.
-+ *
-+ * Let's introduce task (Y) which has task->mm == mm and task (N) which has
-+ * task->mm != mm for the rest of the discussion. There are two scheduler state
-+ * transitions on context switch we care about:
-+ *
-+ * (TSA) Store to rq->curr with transition from (N) to (Y)
-+ *
-+ * (TSB) Store to rq->curr with transition from (Y) to (N)
-+ *
-+ * On the remote-clear side, there is one transition we care about:
-+ *
-+ * (TMA) cmpxchg to *pcpu_cid to set the LAZY flag
-+ *
-+ * There is also a transition to UNSET state which can be performed from all
-+ * sides (scheduler, remote-clear). It is always performed with a cmpxchg which
-+ * guarantees that only a single thread will succeed:
-+ *
-+ * (TMB) cmpxchg to *pcpu_cid to mark UNSET
-+ *
-+ * Just to be clear, what we do _not_ want to happen is a transition to UNSET
-+ * when a thread is actively using the cid (property (1)).
-+ *
-+ * Let's looks at the relevant combinations of TSA/TSB, and TMA transitions.
-+ *
-+ * Scenario A) (TSA)+(TMA) (from next task perspective)
-+ *
-+ * CPU0 CPU1
-+ *
-+ * Context switch CS-1 Remote-clear
-+ * - store to rq->curr: (N)->(Y) (TSA) - cmpxchg to *pcpu_id to LAZY (TMA)
-+ * (implied barrier after cmpxchg)
-+ * - switch_mm_cid()
-+ * - memory barrier (see switch_mm_cid()
-+ * comment explaining how this barrier
-+ * is combined with other scheduler
-+ * barriers)
-+ * - mm_cid_get (next)
-+ * - READ_ONCE(*pcpu_cid) - rcu_dereference(src_rq->curr)
-+ *
-+ * This Dekker ensures that either task (Y) is observed by the
-+ * rcu_dereference() or the LAZY flag is observed by READ_ONCE(), or both are
-+ * observed.
-+ *
-+ * If task (Y) store is observed by rcu_dereference(), it means that there is
-+ * still an active task on the cpu. Remote-clear will therefore not transition
-+ * to UNSET, which fulfills property (1).
-+ *
-+ * If task (Y) is not observed, but the lazy flag is observed by READ_ONCE(),
-+ * it will move its state to UNSET, which clears the percpu cid perhaps
-+ * uselessly (which is not an issue for correctness). Because task (Y) is not
-+ * observed, CPU1 can move ahead to set the state to UNSET. Because moving
-+ * state to UNSET is done with a cmpxchg expecting that the old state has the
-+ * LAZY flag set, only one thread will successfully UNSET.
-+ *
-+ * If both states (LAZY flag and task (Y)) are observed, the thread on CPU0
-+ * will observe the LAZY flag and transition to UNSET (perhaps uselessly), and
-+ * CPU1 will observe task (Y) and do nothing more, which is fine.
-+ *
-+ * What we are effectively preventing with this Dekker is a scenario where
-+ * neither LAZY flag nor store (Y) are observed, which would fail property (1)
-+ * because this would UNSET a cid which is actively used.
-+ */
-+
-+void sched_mm_cid_migrate_from(struct task_struct *t)
-+{
-+ t->migrate_from_cpu = task_cpu(t);
-+}
-+
-+static
-+int __sched_mm_cid_migrate_from_fetch_cid(struct rq *src_rq,
-+ struct task_struct *t,
-+ struct mm_cid *src_pcpu_cid)
-+{
-+ struct mm_struct *mm = t->mm;
-+ struct task_struct *src_task;
-+ int src_cid, last_mm_cid;
-+
-+ if (!mm)
-+ return -1;
-+
-+ last_mm_cid = t->last_mm_cid;
-+ /*
-+ * If the migrated task has no last cid, or if the current
-+ * task on src rq uses the cid, it means the source cid does not need
-+ * to be moved to the destination cpu.
-+ */
-+ if (last_mm_cid == -1)
-+ return -1;
-+ src_cid = READ_ONCE(src_pcpu_cid->cid);
-+ if (!mm_cid_is_valid(src_cid) || last_mm_cid != src_cid)
-+ return -1;
-+
-+ /*
-+ * If we observe an active task using the mm on this rq, it means we
-+ * are not the last task to be migrated from this cpu for this mm, so
-+ * there is no need to move src_cid to the destination cpu.
-+ */
-+ rcu_read_lock();
-+ src_task = rcu_dereference(src_rq->curr);
-+ if (READ_ONCE(src_task->mm_cid_active) && src_task->mm == mm) {
-+ rcu_read_unlock();
-+ t->last_mm_cid = -1;
-+ return -1;
-+ }
-+ rcu_read_unlock();
-+
-+ return src_cid;
-+}
-+
-+static
-+int __sched_mm_cid_migrate_from_try_steal_cid(struct rq *src_rq,
-+ struct task_struct *t,
-+ struct mm_cid *src_pcpu_cid,
-+ int src_cid)
-+{
-+ struct task_struct *src_task;
-+ struct mm_struct *mm = t->mm;
-+ int lazy_cid;
-+
-+ if (src_cid == -1)
-+ return -1;
-+
-+ /*
-+ * Attempt to clear the source cpu cid to move it to the destination
-+ * cpu.
-+ */
-+ lazy_cid = mm_cid_set_lazy_put(src_cid);
-+ if (!try_cmpxchg(&src_pcpu_cid->cid, &src_cid, lazy_cid))
-+ return -1;
-+
-+ /*
-+ * The implicit barrier after cmpxchg per-mm/cpu cid before loading
-+ * rq->curr->mm matches the scheduler barrier in context_switch()
-+ * between store to rq->curr and load of prev and next task's
-+ * per-mm/cpu cid.
-+ *
-+ * The implicit barrier after cmpxchg per-mm/cpu cid before loading
-+ * rq->curr->mm_cid_active matches the barrier in
-+ * sched_mm_cid_exit_signals(), sched_mm_cid_before_execve(), and
-+ * sched_mm_cid_after_execve() between store to t->mm_cid_active and
-+ * load of per-mm/cpu cid.
-+ */
-+
-+ /*
-+ * If we observe an active task using the mm on this rq after setting
-+ * the lazy-put flag, this task will be responsible for transitioning
-+ * from lazy-put flag set to MM_CID_UNSET.
-+ */
-+ scoped_guard (rcu) {
-+ src_task = rcu_dereference(src_rq->curr);
-+ if (READ_ONCE(src_task->mm_cid_active) && src_task->mm == mm) {
-+ rcu_read_unlock();
-+ /*
-+ * We observed an active task for this mm, there is therefore
-+ * no point in moving this cid to the destination cpu.
-+ */
-+ t->last_mm_cid = -1;
-+ return -1;
-+ }
-+ }
-+
-+ /*
-+ * The src_cid is unused, so it can be unset.
-+ */
-+ if (!try_cmpxchg(&src_pcpu_cid->cid, &lazy_cid, MM_CID_UNSET))
-+ return -1;
-+ return src_cid;
-+}
-+
-+/*
-+ * Migration to dst cpu. Called with dst_rq lock held.
-+ * Interrupts are disabled, which keeps the window of cid ownership without the
-+ * source rq lock held small.
-+ */
-+void sched_mm_cid_migrate_to(struct rq *dst_rq, struct task_struct *t, int src_cpu)
-+{
-+ struct mm_cid *src_pcpu_cid, *dst_pcpu_cid;
-+ struct mm_struct *mm = t->mm;
-+ int src_cid, dst_cid;
-+ struct rq *src_rq;
-+
-+ lockdep_assert_rq_held(dst_rq);
-+
-+ if (!mm)
-+ return;
-+ if (src_cpu == -1) {
-+ t->last_mm_cid = -1;
-+ return;
-+ }
-+ /*
-+ * Move the src cid if the dst cid is unset. This keeps id
-+ * allocation closest to 0 in cases where few threads migrate around
-+ * many cpus.
-+ *
-+ * If destination cid is already set, we may have to just clear
-+ * the src cid to ensure compactness in frequent migrations
-+ * scenarios.
-+ *
-+ * It is not useful to clear the src cid when the number of threads is
-+ * greater or equal to the number of allowed cpus, because user-space
-+ * can expect that the number of allowed cids can reach the number of
-+ * allowed cpus.
-+ */
-+ dst_pcpu_cid = per_cpu_ptr(mm->pcpu_cid, cpu_of(dst_rq));
-+ dst_cid = READ_ONCE(dst_pcpu_cid->cid);
-+ if (!mm_cid_is_unset(dst_cid) &&
-+ atomic_read(&mm->mm_users) >= t->nr_cpus_allowed)
-+ return;
-+ src_pcpu_cid = per_cpu_ptr(mm->pcpu_cid, src_cpu);
-+ src_rq = cpu_rq(src_cpu);
-+ src_cid = __sched_mm_cid_migrate_from_fetch_cid(src_rq, t, src_pcpu_cid);
-+ if (src_cid == -1)
-+ return;
-+ src_cid = __sched_mm_cid_migrate_from_try_steal_cid(src_rq, t, src_pcpu_cid,
-+ src_cid);
-+ if (src_cid == -1)
-+ return;
-+ if (!mm_cid_is_unset(dst_cid)) {
-+ __mm_cid_put(mm, src_cid);
-+ return;
-+ }
-+ /* Move src_cid to dst cpu. */
-+ mm_cid_snapshot_time(dst_rq, mm);
-+ WRITE_ONCE(dst_pcpu_cid->cid, src_cid);
-+}
-+
-+static void sched_mm_cid_remote_clear(struct mm_struct *mm, struct mm_cid *pcpu_cid,
-+ int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ struct task_struct *t;
-+ int cid, lazy_cid;
-+
-+ cid = READ_ONCE(pcpu_cid->cid);
-+ if (!mm_cid_is_valid(cid))
-+ return;
-+
-+ /*
-+ * Clear the cpu cid if it is set to keep cid allocation compact. If
-+ * there happens to be other tasks left on the source cpu using this
-+ * mm, the next task using this mm will reallocate its cid on context
-+ * switch.
-+ */
-+ lazy_cid = mm_cid_set_lazy_put(cid);
-+ if (!try_cmpxchg(&pcpu_cid->cid, &cid, lazy_cid))
-+ return;
-+
-+ /*
-+ * The implicit barrier after cmpxchg per-mm/cpu cid before loading
-+ * rq->curr->mm matches the scheduler barrier in context_switch()
-+ * between store to rq->curr and load of prev and next task's
-+ * per-mm/cpu cid.
-+ *
-+ * The implicit barrier after cmpxchg per-mm/cpu cid before loading
-+ * rq->curr->mm_cid_active matches the barrier in
-+ * sched_mm_cid_exit_signals(), sched_mm_cid_before_execve(), and
-+ * sched_mm_cid_after_execve() between store to t->mm_cid_active and
-+ * load of per-mm/cpu cid.
-+ */
-+
-+ /*
-+ * If we observe an active task using the mm on this rq after setting
-+ * the lazy-put flag, that task will be responsible for transitioning
-+ * from lazy-put flag set to MM_CID_UNSET.
-+ */
-+ scoped_guard (rcu) {
-+ t = rcu_dereference(rq->curr);
-+ if (READ_ONCE(t->mm_cid_active) && t->mm == mm)
-+ return;
-+ }
-+
-+ /*
-+ * The cid is unused, so it can be unset.
-+ * Disable interrupts to keep the window of cid ownership without rq
-+ * lock small.
-+ */
-+ scoped_guard (irqsave) {
-+ if (try_cmpxchg(&pcpu_cid->cid, &lazy_cid, MM_CID_UNSET))
-+ __mm_cid_put(mm, cid);
-+ }
-+}
-+
-+static void sched_mm_cid_remote_clear_old(struct mm_struct *mm, int cpu)
-+{
-+ struct rq *rq = cpu_rq(cpu);
-+ struct mm_cid *pcpu_cid;
-+ struct task_struct *curr;
-+ u64 rq_clock;
-+
-+ /*
-+ * rq->clock load is racy on 32-bit but one spurious clear once in a
-+ * while is irrelevant.
-+ */
-+ rq_clock = READ_ONCE(rq->clock);
-+ pcpu_cid = per_cpu_ptr(mm->pcpu_cid, cpu);
-+
-+ /*
-+ * In order to take care of infrequently scheduled tasks, bump the time
-+ * snapshot associated with this cid if an active task using the mm is
-+ * observed on this rq.
-+ */
-+ scoped_guard (rcu) {
-+ curr = rcu_dereference(rq->curr);
-+ if (READ_ONCE(curr->mm_cid_active) && curr->mm == mm) {
-+ WRITE_ONCE(pcpu_cid->time, rq_clock);
-+ return;
-+ }
-+ }
-+
-+ if (rq_clock < pcpu_cid->time + SCHED_MM_CID_PERIOD_NS)
-+ return;
-+ sched_mm_cid_remote_clear(mm, pcpu_cid, cpu);
-+}
-+
-+static void sched_mm_cid_remote_clear_weight(struct mm_struct *mm, int cpu,
-+ int weight)
-+{
-+ struct mm_cid *pcpu_cid;
-+ int cid;
-+
-+ pcpu_cid = per_cpu_ptr(mm->pcpu_cid, cpu);
-+ cid = READ_ONCE(pcpu_cid->cid);
-+ if (!mm_cid_is_valid(cid) || cid < weight)
-+ return;
-+ sched_mm_cid_remote_clear(mm, pcpu_cid, cpu);
-+}
-+
-+static void task_mm_cid_work(struct callback_head *work)
-+{
-+ unsigned long now = jiffies, old_scan, next_scan;
-+ struct task_struct *t = current;
-+ struct cpumask *cidmask;
-+ struct mm_struct *mm;
-+ int weight, cpu;
-+
-+ SCHED_WARN_ON(t != container_of(work, struct task_struct, cid_work));
-+
-+ work->next = work; /* Prevent double-add */
-+ if (t->flags & PF_EXITING)
-+ return;
-+ mm = t->mm;
-+ if (!mm)
-+ return;
-+ old_scan = READ_ONCE(mm->mm_cid_next_scan);
-+ next_scan = now + msecs_to_jiffies(MM_CID_SCAN_DELAY);
-+ if (!old_scan) {
-+ unsigned long res;
-+
-+ res = cmpxchg(&mm->mm_cid_next_scan, old_scan, next_scan);
-+ if (res != old_scan)
-+ old_scan = res;
-+ else
-+ old_scan = next_scan;
-+ }
-+ if (time_before(now, old_scan))
-+ return;
-+ if (!try_cmpxchg(&mm->mm_cid_next_scan, &old_scan, next_scan))
-+ return;
-+ cidmask = mm_cidmask(mm);
-+ /* Clear cids that were not recently used. */
-+ for_each_possible_cpu(cpu)
-+ sched_mm_cid_remote_clear_old(mm, cpu);
-+ weight = cpumask_weight(cidmask);
-+ /*
-+ * Clear cids that are greater or equal to the cidmask weight to
-+ * recompact it.
-+ */
-+ for_each_possible_cpu(cpu)
-+ sched_mm_cid_remote_clear_weight(mm, cpu, weight);
-+}
-+
-+void init_sched_mm_cid(struct task_struct *t)
-+{
-+ struct mm_struct *mm = t->mm;
-+ int mm_users = 0;
-+
-+ if (mm) {
-+ mm_users = atomic_read(&mm->mm_users);
-+ if (mm_users == 1)
-+ mm->mm_cid_next_scan = jiffies + msecs_to_jiffies(MM_CID_SCAN_DELAY);
-+ }
-+ t->cid_work.next = &t->cid_work; /* Protect against double add */
-+ init_task_work(&t->cid_work, task_mm_cid_work);
-+}
-+
-+void task_tick_mm_cid(struct rq *rq, struct task_struct *curr)
-+{
-+ struct callback_head *work = &curr->cid_work;
-+ unsigned long now = jiffies;
-+
-+ if (!curr->mm || (curr->flags & (PF_EXITING | PF_KTHREAD)) ||
-+ work->next != work)
-+ return;
-+ if (time_before(now, READ_ONCE(curr->mm->mm_cid_next_scan)))
-+ return;
-+ task_work_add(curr, work, TWA_RESUME);
-+}
-+
-+void sched_mm_cid_exit_signals(struct task_struct *t)
-+{
-+ struct mm_struct *mm = t->mm;
-+ struct rq *rq;
-+
-+ if (!mm)
-+ return;
-+
-+ preempt_disable();
-+ rq = this_rq();
-+ guard(rq_lock_irqsave)(rq);
-+ preempt_enable_no_resched(); /* holding spinlock */
-+ WRITE_ONCE(t->mm_cid_active, 0);
-+ /*
-+ * Store t->mm_cid_active before loading per-mm/cpu cid.
-+ * Matches barrier in sched_mm_cid_remote_clear_old().
-+ */
-+ smp_mb();
-+ mm_cid_put(mm);
-+ t->last_mm_cid = t->mm_cid = -1;
-+}
-+
-+void sched_mm_cid_before_execve(struct task_struct *t)
-+{
-+ struct mm_struct *mm = t->mm;
-+ struct rq *rq;
-+
-+ if (!mm)
-+ return;
-+
-+ preempt_disable();
-+ rq = this_rq();
-+ guard(rq_lock_irqsave)(rq);
-+ preempt_enable_no_resched(); /* holding spinlock */
-+ WRITE_ONCE(t->mm_cid_active, 0);
-+ /*
-+ * Store t->mm_cid_active before loading per-mm/cpu cid.
-+ * Matches barrier in sched_mm_cid_remote_clear_old().
-+ */
-+ smp_mb();
-+ mm_cid_put(mm);
-+ t->last_mm_cid = t->mm_cid = -1;
-+}
-+
-+void sched_mm_cid_after_execve(struct task_struct *t)
-+{
-+ struct mm_struct *mm = t->mm;
-+ struct rq *rq;
-+
-+ if (!mm)
-+ return;
-+
-+ preempt_disable();
-+ rq = this_rq();
-+ scoped_guard (rq_lock_irqsave, rq) {
-+ preempt_enable_no_resched(); /* holding spinlock */
-+ WRITE_ONCE(t->mm_cid_active, 1);
-+ /*
-+ * Store t->mm_cid_active before loading per-mm/cpu cid.
-+ * Matches barrier in sched_mm_cid_remote_clear_old().
-+ */
-+ smp_mb();
-+ t->last_mm_cid = t->mm_cid = mm_cid_get(rq, mm);
-+ }
-+ rseq_set_notify_resume(t);
-+}
-+
-+void sched_mm_cid_fork(struct task_struct *t)
-+{
-+ WARN_ON_ONCE(!t->mm || t->mm_cid != -1);
-+ t->mm_cid_active = 1;
-+}
-+#endif
-diff --git a/kernel/sched/alt_debug.c b/kernel/sched/alt_debug.c
-new file mode 100644
-index 000000000000..1dbd7eb6a434
---- /dev/null
-+++ b/kernel/sched/alt_debug.c
-@@ -0,0 +1,32 @@
-+/*
-+ * kernel/sched/alt_debug.c
-+ *
-+ * Print the alt scheduler debugging details
-+ *
-+ * Author: Alfred Chen
-+ * Date : 2020
-+ */
-+#include "sched.h"
-+#include "linux/sched/debug.h"
-+
-+/*
-+ * This allows printing both to /proc/sched_debug and
-+ * to the console
-+ */
-+#define SEQ_printf(m, x...) \
-+ do { \
-+ if (m) \
-+ seq_printf(m, x); \
-+ else \
-+ pr_cont(x); \
-+ } while (0)
-+
-+void proc_sched_show_task(struct task_struct *p, struct pid_namespace *ns,
-+ struct seq_file *m)
-+{
-+ SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, task_pid_nr_ns(p, ns),
-+ get_nr_threads(p));
-+}
-+
-+void proc_sched_set_task(struct task_struct *p)
-+{}
-diff --git a/kernel/sched/alt_sched.h b/kernel/sched/alt_sched.h
-new file mode 100644
-index 000000000000..e9bfc67e8165
---- /dev/null
-+++ b/kernel/sched/alt_sched.h
-@@ -0,0 +1,954 @@
-+#ifndef ALT_SCHED_H
-+#define ALT_SCHED_H
-+
-+#include <linux/context_tracking.h>
-+#include <linux/profile.h>
-+#include <linux/stop_machine.h>
-+#include <linux/syscalls.h>
-+#include <linux/tick.h>
-+
-+#include <trace/events/power.h>
-+#include <trace/events/sched.h>
-+
-+#include "../workqueue_internal.h"
-+
-+#include "cpupri.h"
-+
-+#ifdef CONFIG_CGROUP_SCHED
-+/* task group related information */
-+struct task_group {
-+ struct cgroup_subsys_state css;
-+
-+ struct rcu_head rcu;
-+ struct list_head list;
-+
-+ struct task_group *parent;
-+ struct list_head siblings;
-+ struct list_head children;
-+#ifdef CONFIG_FAIR_GROUP_SCHED
-+ unsigned long shares;
-+#endif
-+};
-+
-+extern struct task_group *sched_create_group(struct task_group *parent);
-+extern void sched_online_group(struct task_group *tg,
-+ struct task_group *parent);
-+extern void sched_destroy_group(struct task_group *tg);
-+extern void sched_release_group(struct task_group *tg);
-+#endif /* CONFIG_CGROUP_SCHED */
-+
-+#define MIN_SCHED_NORMAL_PRIO (32)
-+/*
-+ * levels: RT(0-24), reserved(25-31), NORMAL(32-63), cpu idle task(64)
-+ *
-+ * -- BMQ --
-+ * NORMAL: (lower boost range 12, NICE_WIDTH 40, higher boost range 12) / 2
-+ * -- PDS --
-+ * NORMAL: SCHED_EDGE_DELTA + ((NICE_WIDTH 40) / 2)
-+ */
-+#define SCHED_LEVELS (64 + 1)
-+
-+#define IDLE_TASK_SCHED_PRIO (SCHED_LEVELS - 1)
-+
-+#ifdef CONFIG_SCHED_DEBUG
-+# define SCHED_WARN_ON(x) WARN_ONCE(x, #x)
-+extern void resched_latency_warn(int cpu, u64 latency);
-+#else
-+# define SCHED_WARN_ON(x) ({ (void)(x), 0; })
-+static inline void resched_latency_warn(int cpu, u64 latency) {}
-+#endif
-+
-+/*
-+ * Increase resolution of nice-level calculations for 64-bit architectures.
-+ * The extra resolution improves shares distribution and load balancing of
-+ * low-weight task groups (eg. nice +19 on an autogroup), deeper taskgroup
-+ * hierarchies, especially on larger systems. This is not a user-visible change
-+ * and does not change the user-interface for setting shares/weights.
-+ *
-+ * We increase resolution only if we have enough bits to allow this increased
-+ * resolution (i.e. 64-bit). The costs for increasing resolution when 32-bit
-+ * are pretty high and the returns do not justify the increased costs.
-+ *
-+ * Really only required when CONFIG_FAIR_GROUP_SCHED=y is also set, but to
-+ * increase coverage and consistency always enable it on 64-bit platforms.
-+ */
-+#ifdef CONFIG_64BIT
-+# define NICE_0_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT + SCHED_FIXEDPOINT_SHIFT)
-+# define scale_load(w) ((w) << SCHED_FIXEDPOINT_SHIFT)
-+# define scale_load_down(w) \
-+({ \
-+ unsigned long __w = (w); \
-+ if (__w) \
-+ __w = max(2UL, __w >> SCHED_FIXEDPOINT_SHIFT); \
-+ __w; \
-+})
-+#else
-+# define NICE_0_LOAD_SHIFT (SCHED_FIXEDPOINT_SHIFT)
-+# define scale_load(w) (w)
-+# define scale_load_down(w) (w)
-+#endif
-+
-+#ifdef CONFIG_FAIR_GROUP_SCHED
-+#define ROOT_TASK_GROUP_LOAD NICE_0_LOAD
-+
-+/*
-+ * A weight of 0 or 1 can cause arithmetics problems.
-+ * A weight of a cfs_rq is the sum of weights of which entities
-+ * are queued on this cfs_rq, so a weight of a entity should not be
-+ * too large, so as the shares value of a task group.
-+ * (The default weight is 1024 - so there's no practical
-+ * limitation from this.)
-+ */
-+#define MIN_SHARES (1UL << 1)
-+#define MAX_SHARES (1UL << 18)
-+#endif
-+
-+/*
-+ * Tunables that become constants when CONFIG_SCHED_DEBUG is off:
-+ */
-+#ifdef CONFIG_SCHED_DEBUG
-+# define const_debug __read_mostly
-+#else
-+# define const_debug const
-+#endif
-+
-+/* task_struct::on_rq states: */
-+#define TASK_ON_RQ_QUEUED 1
-+#define TASK_ON_RQ_MIGRATING 2
-+
-+static inline int task_on_rq_queued(struct task_struct *p)
-+{
-+ return p->on_rq == TASK_ON_RQ_QUEUED;
-+}
-+
-+static inline int task_on_rq_migrating(struct task_struct *p)
-+{
-+ return READ_ONCE(p->on_rq) == TASK_ON_RQ_MIGRATING;
-+}
-+
-+/* Wake flags. The first three directly map to some SD flag value */
-+#define WF_EXEC 0x02 /* Wakeup after exec; maps to SD_BALANCE_EXEC */
-+#define WF_FORK 0x04 /* Wakeup after fork; maps to SD_BALANCE_FORK */
-+#define WF_TTWU 0x08 /* Wakeup; maps to SD_BALANCE_WAKE */
-+
-+#define WF_SYNC 0x10 /* Waker goes to sleep after wakeup */
-+#define WF_MIGRATED 0x20 /* Internal use, task got migrated */
-+#define WF_CURRENT_CPU 0x40 /* Prefer to move the wakee to the current CPU. */
-+
-+#ifdef CONFIG_SMP
-+static_assert(WF_EXEC == SD_BALANCE_EXEC);
-+static_assert(WF_FORK == SD_BALANCE_FORK);
-+static_assert(WF_TTWU == SD_BALANCE_WAKE);
-+#endif
-+
-+#define SCHED_QUEUE_BITS (SCHED_LEVELS - 1)
-+
-+struct sched_queue {
-+ DECLARE_BITMAP(bitmap, SCHED_QUEUE_BITS);
-+ struct list_head heads[SCHED_LEVELS];
-+};
-+
-+struct rq;
-+struct cpuidle_state;
-+
-+struct balance_callback {
-+ struct balance_callback *next;
-+ void (*func)(struct rq *rq);
-+};
-+
-+/*
-+ * This is the main, per-CPU runqueue data structure.
-+ * This data should only be modified by the local cpu.
-+ */
-+struct rq {
-+ /* runqueue lock: */
-+ raw_spinlock_t lock;
-+
-+ struct task_struct __rcu *curr;
-+ struct task_struct *idle;
-+ struct task_struct *stop;
-+ struct task_struct *skip;
-+ struct mm_struct *prev_mm;
-+
-+ struct sched_queue queue;
-+#ifdef CONFIG_SCHED_PDS
-+ u64 time_edge;
-+#endif
-+ unsigned long prio;
-+
-+ /* switch count */
-+ u64 nr_switches;
-+
-+ atomic_t nr_iowait;
-+
-+#ifdef CONFIG_SCHED_DEBUG
-+ u64 last_seen_need_resched_ns;
-+ int ticks_without_resched;
-+#endif
-+
-+#ifdef CONFIG_MEMBARRIER
-+ int membarrier_state;
-+#endif
-+
-+#ifdef CONFIG_SMP
-+ int cpu; /* cpu of this runqueue */
-+ bool online;
-+
-+ unsigned int ttwu_pending;
-+ unsigned char nohz_idle_balance;
-+ unsigned char idle_balance;
-+
-+#ifdef CONFIG_HAVE_SCHED_AVG_IRQ
-+ struct sched_avg avg_irq;
-+#endif
-+
-+#ifdef CONFIG_SCHED_SMT
-+ int active_balance;
-+ struct cpu_stop_work active_balance_work;
-+#endif
-+ struct balance_callback *balance_callback;
-+#ifdef CONFIG_HOTPLUG_CPU
-+ struct rcuwait hotplug_wait;
-+#endif
-+ unsigned int nr_pinned;
-+
-+#endif /* CONFIG_SMP */
-+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
-+ u64 prev_irq_time;
-+#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
-+#ifdef CONFIG_PARAVIRT
-+ u64 prev_steal_time;
-+#endif /* CONFIG_PARAVIRT */
-+#ifdef CONFIG_PARAVIRT_TIME_ACCOUNTING
-+ u64 prev_steal_time_rq;
-+#endif /* CONFIG_PARAVIRT_TIME_ACCOUNTING */
-+
-+ /* For genenal cpu load util */
-+ s32 load_history;
-+ u64 load_block;
-+ u64 load_stamp;
-+
-+ /* calc_load related fields */
-+ unsigned long calc_load_update;
-+ long calc_load_active;
-+
-+ /* Ensure that all clocks are in the same cache line */
-+ u64 clock ____cacheline_aligned;
-+ u64 clock_task;
-+#ifdef CONFIG_SCHED_BMQ
-+ u64 last_ts_switch;
-+#endif
-+
-+ unsigned int nr_running;
-+ unsigned long nr_uninterruptible;
-+
-+#ifdef CONFIG_SCHED_HRTICK
-+#ifdef CONFIG_SMP
-+ call_single_data_t hrtick_csd;
-+#endif
-+ struct hrtimer hrtick_timer;
-+ ktime_t hrtick_time;
-+#endif
-+
-+#ifdef CONFIG_SCHEDSTATS
-+
-+ /* latency stats */
-+ struct sched_info rq_sched_info;
-+ unsigned long long rq_cpu_time;
-+ /* could above be rq->cfs_rq.exec_clock + rq->rt_rq.rt_runtime ? */
-+
-+ /* sys_sched_yield() stats */
-+ unsigned int yld_count;
-+
-+ /* schedule() stats */
-+ unsigned int sched_switch;
-+ unsigned int sched_count;
-+ unsigned int sched_goidle;
-+
-+ /* try_to_wake_up() stats */
-+ unsigned int ttwu_count;
-+ unsigned int ttwu_local;
-+#endif /* CONFIG_SCHEDSTATS */
-+
-+#ifdef CONFIG_CPU_IDLE
-+ /* Must be inspected within a rcu lock section */
-+ struct cpuidle_state *idle_state;
-+#endif
-+
-+#ifdef CONFIG_NO_HZ_COMMON
-+#ifdef CONFIG_SMP
-+ call_single_data_t nohz_csd;
-+#endif
-+ atomic_t nohz_flags;
-+#endif /* CONFIG_NO_HZ_COMMON */
-+
-+ /* Scratch cpumask to be temporarily used under rq_lock */
-+ cpumask_var_t scratch_mask;
-+};
-+
-+extern unsigned int sysctl_sched_base_slice;
-+
-+extern unsigned long rq_load_util(struct rq *rq, unsigned long max);
-+
-+extern unsigned long calc_load_update;
-+extern atomic_long_t calc_load_tasks;
-+
-+extern void calc_global_load_tick(struct rq *this_rq);
-+extern long calc_load_fold_active(struct rq *this_rq, long adjust);
-+
-+DECLARE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues);
-+#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu)))
-+#define this_rq() this_cpu_ptr(&runqueues)
-+#define task_rq(p) cpu_rq(task_cpu(p))
-+#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
-+#define raw_rq() raw_cpu_ptr(&runqueues)
-+
-+#ifdef CONFIG_SMP
-+#if defined(CONFIG_SCHED_DEBUG) && defined(CONFIG_SYSCTL)
-+void register_sched_domain_sysctl(void);
-+void unregister_sched_domain_sysctl(void);
-+#else
-+static inline void register_sched_domain_sysctl(void)
-+{
-+}
-+static inline void unregister_sched_domain_sysctl(void)
-+{
-+}
-+#endif
-+
-+extern bool sched_smp_initialized;
-+
-+enum {
-+ ITSELF_LEVEL_SPACE_HOLDER,
-+#ifdef CONFIG_SCHED_SMT
-+ SMT_LEVEL_SPACE_HOLDER,
-+#endif
-+ COREGROUP_LEVEL_SPACE_HOLDER,
-+ CORE_LEVEL_SPACE_HOLDER,
-+ OTHER_LEVEL_SPACE_HOLDER,
-+ NR_CPU_AFFINITY_LEVELS
-+};
-+
-+DECLARE_PER_CPU_ALIGNED(cpumask_t [NR_CPU_AFFINITY_LEVELS], sched_cpu_topo_masks);
-+
-+static inline int
-+__best_mask_cpu(const cpumask_t *cpumask, const cpumask_t *mask)
-+{
-+ int cpu;
-+
-+ while ((cpu = cpumask_any_and(cpumask, mask)) >= nr_cpu_ids)
-+ mask++;
-+
-+ return cpu;
-+}
-+
-+static inline int best_mask_cpu(int cpu, const cpumask_t *mask)
-+{
-+ return __best_mask_cpu(mask, per_cpu(sched_cpu_topo_masks, cpu));
-+}
-+
-+extern void flush_smp_call_function_queue(void);
-+
-+#else /* !CONFIG_SMP */
-+static inline void flush_smp_call_function_queue(void) { }
-+#endif
-+
-+#ifndef arch_scale_freq_tick
-+static __always_inline
-+void arch_scale_freq_tick(void)
-+{
-+}
-+#endif
-+
-+#ifndef arch_scale_freq_capacity
-+static __always_inline
-+unsigned long arch_scale_freq_capacity(int cpu)
-+{
-+ return SCHED_CAPACITY_SCALE;
-+}
-+#endif
-+
-+static inline u64 __rq_clock_broken(struct rq *rq)
-+{
-+ return READ_ONCE(rq->clock);
-+}
-+
-+static inline u64 rq_clock(struct rq *rq)
-+{
-+ /*
-+ * Relax lockdep_assert_held() checking as in VRQ, call to
-+ * sched_info_xxxx() may not held rq->lock
-+ * lockdep_assert_held(&rq->lock);
-+ */
-+ return rq->clock;
-+}
-+
-+static inline u64 rq_clock_task(struct rq *rq)
-+{
-+ /*
-+ * Relax lockdep_assert_held() checking as in VRQ, call to
-+ * sched_info_xxxx() may not held rq->lock
-+ * lockdep_assert_held(&rq->lock);
-+ */
-+ return rq->clock_task;
-+}
-+
-+/*
-+ * {de,en}queue flags:
-+ *
-+ * DEQUEUE_SLEEP - task is no longer runnable
-+ * ENQUEUE_WAKEUP - task just became runnable
-+ *
-+ */
-+
-+#define DEQUEUE_SLEEP 0x01
-+
-+#define ENQUEUE_WAKEUP 0x01
-+
-+
-+/*
-+ * Below are scheduler API which using in other kernel code
-+ * It use the dummy rq_flags
-+ * ToDo : BMQ need to support these APIs for compatibility with mainline
-+ * scheduler code.
-+ */
-+struct rq_flags {
-+ unsigned long flags;
-+};
-+
-+struct rq *__task_rq_lock(struct task_struct *p, struct rq_flags *rf)
-+ __acquires(rq->lock);
-+
-+struct rq *task_rq_lock(struct task_struct *p, struct rq_flags *rf)
-+ __acquires(p->pi_lock)
-+ __acquires(rq->lock);
-+
-+static inline void __task_rq_unlock(struct rq *rq, struct rq_flags *rf)
-+ __releases(rq->lock)
-+{
-+ raw_spin_unlock(&rq->lock);
-+}
-+
-+static inline void
-+task_rq_unlock(struct rq *rq, struct task_struct *p, struct rq_flags *rf)
-+ __releases(rq->lock)
-+ __releases(p->pi_lock)
-+{
-+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock_irqrestore(&p->pi_lock, rf->flags);
-+}
-+
-+static inline void
-+rq_lock(struct rq *rq, struct rq_flags *rf)
-+ __acquires(rq->lock)
-+{
-+ raw_spin_lock(&rq->lock);
-+}
-+
-+static inline void
-+rq_unlock(struct rq *rq, struct rq_flags *rf)
-+ __releases(rq->lock)
-+{
-+ raw_spin_unlock(&rq->lock);
-+}
-+
-+static inline void
-+rq_lock_irq(struct rq *rq, struct rq_flags *rf)
-+ __acquires(rq->lock)
-+{
-+ raw_spin_lock_irq(&rq->lock);
-+}
-+
-+static inline void
-+rq_unlock_irq(struct rq *rq, struct rq_flags *rf)
-+ __releases(rq->lock)
-+{
-+ raw_spin_unlock_irq(&rq->lock);
-+}
-+
-+static inline struct rq *
-+this_rq_lock_irq(struct rq_flags *rf)
-+ __acquires(rq->lock)
-+{
-+ struct rq *rq;
-+
-+ local_irq_disable();
-+ rq = this_rq();
-+ raw_spin_lock(&rq->lock);
-+
-+ return rq;
-+}
-+
-+static inline raw_spinlock_t *__rq_lockp(struct rq *rq)
-+{
-+ return &rq->lock;
-+}
-+
-+static inline raw_spinlock_t *rq_lockp(struct rq *rq)
-+{
-+ return __rq_lockp(rq);
-+}
-+
-+static inline void lockdep_assert_rq_held(struct rq *rq)
-+{
-+ lockdep_assert_held(__rq_lockp(rq));
-+}
-+
-+extern void raw_spin_rq_lock_nested(struct rq *rq, int subclass);
-+extern void raw_spin_rq_unlock(struct rq *rq);
-+
-+static inline void raw_spin_rq_lock(struct rq *rq)
-+{
-+ raw_spin_rq_lock_nested(rq, 0);
-+}
-+
-+static inline void raw_spin_rq_lock_irq(struct rq *rq)
-+{
-+ local_irq_disable();
-+ raw_spin_rq_lock(rq);
-+}
-+
-+static inline void raw_spin_rq_unlock_irq(struct rq *rq)
-+{
-+ raw_spin_rq_unlock(rq);
-+ local_irq_enable();
-+}
-+
-+static inline int task_current(struct rq *rq, struct task_struct *p)
-+{
-+ return rq->curr == p;
-+}
-+
-+static inline bool task_on_cpu(struct task_struct *p)
-+{
-+ return p->on_cpu;
-+}
-+
-+extern int task_running_nice(struct task_struct *p);
-+
-+extern struct static_key_false sched_schedstats;
-+
-+#ifdef CONFIG_CPU_IDLE
-+static inline void idle_set_state(struct rq *rq,
-+ struct cpuidle_state *idle_state)
-+{
-+ rq->idle_state = idle_state;
-+}
-+
-+static inline struct cpuidle_state *idle_get_state(struct rq *rq)
-+{
-+ WARN_ON(!rcu_read_lock_held());
-+ return rq->idle_state;
-+}
-+#else
-+static inline void idle_set_state(struct rq *rq,
-+ struct cpuidle_state *idle_state)
-+{
-+}
-+
-+static inline struct cpuidle_state *idle_get_state(struct rq *rq)
-+{
-+ return NULL;
-+}
-+#endif
-+
-+static inline int cpu_of(const struct rq *rq)
-+{
-+#ifdef CONFIG_SMP
-+ return rq->cpu;
-+#else
-+ return 0;
-+#endif
-+}
-+
-+extern void resched_cpu(int cpu);
-+
-+#include "stats.h"
-+
-+#ifdef CONFIG_NO_HZ_COMMON
-+#define NOHZ_BALANCE_KICK_BIT 0
-+#define NOHZ_STATS_KICK_BIT 1
-+
-+#define NOHZ_BALANCE_KICK BIT(NOHZ_BALANCE_KICK_BIT)
-+#define NOHZ_STATS_KICK BIT(NOHZ_STATS_KICK_BIT)
-+
-+#define NOHZ_KICK_MASK (NOHZ_BALANCE_KICK | NOHZ_STATS_KICK)
-+
-+#define nohz_flags(cpu) (&cpu_rq(cpu)->nohz_flags)
-+
-+/* TODO: needed?
-+extern void nohz_balance_exit_idle(struct rq *rq);
-+#else
-+static inline void nohz_balance_exit_idle(struct rq *rq) { }
-+*/
-+#endif
-+
-+#ifdef CONFIG_IRQ_TIME_ACCOUNTING
-+struct irqtime {
-+ u64 total;
-+ u64 tick_delta;
-+ u64 irq_start_time;
-+ struct u64_stats_sync sync;
-+};
-+
-+DECLARE_PER_CPU(struct irqtime, cpu_irqtime);
-+
-+/*
-+ * Returns the irqtime minus the softirq time computed by ksoftirqd.
-+ * Otherwise ksoftirqd's sum_exec_runtime is substracted its own runtime
-+ * and never move forward.
-+ */
-+static inline u64 irq_time_read(int cpu)
-+{
-+ struct irqtime *irqtime = &per_cpu(cpu_irqtime, cpu);
-+ unsigned int seq;
-+ u64 total;
-+
-+ do {
-+ seq = __u64_stats_fetch_begin(&irqtime->sync);
-+ total = irqtime->total;
-+ } while (__u64_stats_fetch_retry(&irqtime->sync, seq));
-+
-+ return total;
-+}
-+#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
-+
-+#ifdef CONFIG_CPU_FREQ
-+DECLARE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
-+#endif /* CONFIG_CPU_FREQ */
-+
-+#ifdef CONFIG_NO_HZ_FULL
-+extern int __init sched_tick_offload_init(void);
-+#else
-+static inline int sched_tick_offload_init(void) { return 0; }
-+#endif
-+
-+#ifdef arch_scale_freq_capacity
-+#ifndef arch_scale_freq_invariant
-+#define arch_scale_freq_invariant() (true)
-+#endif
-+#else /* arch_scale_freq_capacity */
-+#define arch_scale_freq_invariant() (false)
-+#endif
-+
-+#ifdef CONFIG_SMP
-+unsigned long sugov_effective_cpu_perf(int cpu, unsigned long actual,
-+ unsigned long min,
-+ unsigned long max);
-+#endif /* CONFIG_SMP */
-+
-+extern void schedule_idle(void);
-+
-+#define cap_scale(v, s) ((v)*(s) >> SCHED_CAPACITY_SHIFT)
-+
-+/*
-+ * !! For sched_setattr_nocheck() (kernel) only !!
-+ *
-+ * This is actually gross. :(
-+ *
-+ * It is used to make schedutil kworker(s) higher priority than SCHED_DEADLINE
-+ * tasks, but still be able to sleep. We need this on platforms that cannot
-+ * atomically change clock frequency. Remove once fast switching will be
-+ * available on such platforms.
-+ *
-+ * SUGOV stands for SchedUtil GOVernor.
-+ */
-+#define SCHED_FLAG_SUGOV 0x10000000
-+
-+#ifdef CONFIG_MEMBARRIER
-+/*
-+ * The scheduler provides memory barriers required by membarrier between:
-+ * - prior user-space memory accesses and store to rq->membarrier_state,
-+ * - store to rq->membarrier_state and following user-space memory accesses.
-+ * In the same way it provides those guarantees around store to rq->curr.
-+ */
-+static inline void membarrier_switch_mm(struct rq *rq,
-+ struct mm_struct *prev_mm,
-+ struct mm_struct *next_mm)
-+{
-+ int membarrier_state;
-+
-+ if (prev_mm == next_mm)
-+ return;
-+
-+ membarrier_state = atomic_read(&next_mm->membarrier_state);
-+ if (READ_ONCE(rq->membarrier_state) == membarrier_state)
-+ return;
-+
-+ WRITE_ONCE(rq->membarrier_state, membarrier_state);
-+}
-+#else
-+static inline void membarrier_switch_mm(struct rq *rq,
-+ struct mm_struct *prev_mm,
-+ struct mm_struct *next_mm)
-+{
-+}
-+#endif
-+
-+#ifdef CONFIG_NUMA
-+extern int sched_numa_find_closest(const struct cpumask *cpus, int cpu);
-+#else
-+static inline int sched_numa_find_closest(const struct cpumask *cpus, int cpu)
-+{
-+ return nr_cpu_ids;
-+}
-+#endif
-+
-+extern void swake_up_all_locked(struct swait_queue_head *q);
-+extern void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait);
-+
-+extern int try_to_wake_up(struct task_struct *tsk, unsigned int state, int wake_flags);
-+
-+#ifdef CONFIG_PREEMPT_DYNAMIC
-+extern int preempt_dynamic_mode;
-+extern int sched_dynamic_mode(const char *str);
-+extern void sched_dynamic_update(int mode);
-+#endif
-+
-+static inline void nohz_run_idle_balance(int cpu) { }
-+
-+static inline
-+unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util,
-+ struct task_struct *p)
-+{
-+ return util;
-+}
-+
-+static inline bool uclamp_rq_is_capped(struct rq *rq) { return false; }
-+
-+#ifdef CONFIG_SCHED_MM_CID
-+
-+#define SCHED_MM_CID_PERIOD_NS (100ULL * 1000000) /* 100ms */
-+#define MM_CID_SCAN_DELAY 100 /* 100ms */
-+
-+extern raw_spinlock_t cid_lock;
-+extern int use_cid_lock;
-+
-+extern void sched_mm_cid_migrate_from(struct task_struct *t);
-+extern void sched_mm_cid_migrate_to(struct rq *dst_rq, struct task_struct *t, int src_cpu);
-+extern void task_tick_mm_cid(struct rq *rq, struct task_struct *curr);
-+extern void init_sched_mm_cid(struct task_struct *t);
-+
-+static inline void __mm_cid_put(struct mm_struct *mm, int cid)
-+{
-+ if (cid < 0)
-+ return;
-+ cpumask_clear_cpu(cid, mm_cidmask(mm));
-+}
-+
-+/*
-+ * The per-mm/cpu cid can have the MM_CID_LAZY_PUT flag set or transition to
-+ * the MM_CID_UNSET state without holding the rq lock, but the rq lock needs to
-+ * be held to transition to other states.
-+ *
-+ * State transitions synchronized with cmpxchg or try_cmpxchg need to be
-+ * consistent across cpus, which prevents use of this_cpu_cmpxchg.
-+ */
-+static inline void mm_cid_put_lazy(struct task_struct *t)
-+{
-+ struct mm_struct *mm = t->mm;
-+ struct mm_cid __percpu *pcpu_cid = mm->pcpu_cid;
-+ int cid;
-+
-+ lockdep_assert_irqs_disabled();
-+ cid = __this_cpu_read(pcpu_cid->cid);
-+ if (!mm_cid_is_lazy_put(cid) ||
-+ !try_cmpxchg(&this_cpu_ptr(pcpu_cid)->cid, &cid, MM_CID_UNSET))
-+ return;
-+ __mm_cid_put(mm, mm_cid_clear_lazy_put(cid));
-+}
-+
-+static inline int mm_cid_pcpu_unset(struct mm_struct *mm)
-+{
-+ struct mm_cid __percpu *pcpu_cid = mm->pcpu_cid;
-+ int cid, res;
-+
-+ lockdep_assert_irqs_disabled();
-+ cid = __this_cpu_read(pcpu_cid->cid);
-+ for (;;) {
-+ if (mm_cid_is_unset(cid))
-+ return MM_CID_UNSET;
-+ /*
-+ * Attempt transition from valid or lazy-put to unset.
-+ */
-+ res = cmpxchg(&this_cpu_ptr(pcpu_cid)->cid, cid, MM_CID_UNSET);
-+ if (res == cid)
-+ break;
-+ cid = res;
-+ }
-+ return cid;
-+}
-+
-+static inline void mm_cid_put(struct mm_struct *mm)
-+{
-+ int cid;
-+
-+ lockdep_assert_irqs_disabled();
-+ cid = mm_cid_pcpu_unset(mm);
-+ if (cid == MM_CID_UNSET)
-+ return;
-+ __mm_cid_put(mm, mm_cid_clear_lazy_put(cid));
-+}
-+
-+static inline int __mm_cid_try_get(struct mm_struct *mm)
-+{
-+ struct cpumask *cpumask;
-+ int cid;
-+
-+ cpumask = mm_cidmask(mm);
-+ /*
-+ * Retry finding first zero bit if the mask is temporarily
-+ * filled. This only happens during concurrent remote-clear
-+ * which owns a cid without holding a rq lock.
-+ */
-+ for (;;) {
-+ cid = cpumask_first_zero(cpumask);
-+ if (cid < nr_cpu_ids)
-+ break;
-+ cpu_relax();
-+ }
-+ if (cpumask_test_and_set_cpu(cid, cpumask))
-+ return -1;
-+ return cid;
-+}
-+
-+/*
-+ * Save a snapshot of the current runqueue time of this cpu
-+ * with the per-cpu cid value, allowing to estimate how recently it was used.
-+ */
-+static inline void mm_cid_snapshot_time(struct rq *rq, struct mm_struct *mm)
-+{
-+ struct mm_cid *pcpu_cid = per_cpu_ptr(mm->pcpu_cid, cpu_of(rq));
-+
-+ lockdep_assert_rq_held(rq);
-+ WRITE_ONCE(pcpu_cid->time, rq->clock);
-+}
-+
-+static inline int __mm_cid_get(struct rq *rq, struct mm_struct *mm)
-+{
-+ int cid;
-+
-+ /*
-+ * All allocations (even those using the cid_lock) are lock-free. If
-+ * use_cid_lock is set, hold the cid_lock to perform cid allocation to
-+ * guarantee forward progress.
-+ */
-+ if (!READ_ONCE(use_cid_lock)) {
-+ cid = __mm_cid_try_get(mm);
-+ if (cid >= 0)
-+ goto end;
-+ raw_spin_lock(&cid_lock);
-+ } else {
-+ raw_spin_lock(&cid_lock);
-+ cid = __mm_cid_try_get(mm);
-+ if (cid >= 0)
-+ goto unlock;
-+ }
-+
-+ /*
-+ * cid concurrently allocated. Retry while forcing following
-+ * allocations to use the cid_lock to ensure forward progress.
-+ */
-+ WRITE_ONCE(use_cid_lock, 1);
-+ /*
-+ * Set use_cid_lock before allocation. Only care about program order
-+ * because this is only required for forward progress.
-+ */
-+ barrier();
-+ /*
-+ * Retry until it succeeds. It is guaranteed to eventually succeed once
-+ * all newcoming allocations observe the use_cid_lock flag set.
-+ */
-+ do {
-+ cid = __mm_cid_try_get(mm);
-+ cpu_relax();
-+ } while (cid < 0);
-+ /*
-+ * Allocate before clearing use_cid_lock. Only care about
-+ * program order because this is for forward progress.
-+ */
-+ barrier();
-+ WRITE_ONCE(use_cid_lock, 0);
-+unlock:
-+ raw_spin_unlock(&cid_lock);
-+end:
-+ mm_cid_snapshot_time(rq, mm);
-+ return cid;
-+}
-+
-+static inline int mm_cid_get(struct rq *rq, struct mm_struct *mm)
-+{
-+ struct mm_cid __percpu *pcpu_cid = mm->pcpu_cid;
-+ struct cpumask *cpumask;
-+ int cid;
-+
-+ lockdep_assert_rq_held(rq);
-+ cpumask = mm_cidmask(mm);
-+ cid = __this_cpu_read(pcpu_cid->cid);
-+ if (mm_cid_is_valid(cid)) {
-+ mm_cid_snapshot_time(rq, mm);
-+ return cid;
-+ }
-+ if (mm_cid_is_lazy_put(cid)) {
-+ if (try_cmpxchg(&this_cpu_ptr(pcpu_cid)->cid, &cid, MM_CID_UNSET))
-+ __mm_cid_put(mm, mm_cid_clear_lazy_put(cid));
-+ }
-+ cid = __mm_cid_get(rq, mm);
-+ __this_cpu_write(pcpu_cid->cid, cid);
-+ return cid;
-+}
-+
-+static inline void switch_mm_cid(struct rq *rq,
-+ struct task_struct *prev,
-+ struct task_struct *next)
-+{
-+ /*
-+ * Provide a memory barrier between rq->curr store and load of
-+ * {prev,next}->mm->pcpu_cid[cpu] on rq->curr->mm transition.
-+ *
-+ * Should be adapted if context_switch() is modified.
-+ */
-+ if (!next->mm) { // to kernel
-+ /*
-+ * user -> kernel transition does not guarantee a barrier, but
-+ * we can use the fact that it performs an atomic operation in
-+ * mmgrab().
-+ */
-+ if (prev->mm) // from user
-+ smp_mb__after_mmgrab();
-+ /*
-+ * kernel -> kernel transition does not change rq->curr->mm
-+ * state. It stays NULL.
-+ */
-+ } else { // to user
-+ /*
-+ * kernel -> user transition does not provide a barrier
-+ * between rq->curr store and load of {prev,next}->mm->pcpu_cid[cpu].
-+ * Provide it here.
-+ */
-+ if (!prev->mm) // from kernel
-+ smp_mb();
-+ /*
-+ * user -> user transition guarantees a memory barrier through
-+ * switch_mm() when current->mm changes. If current->mm is
-+ * unchanged, no barrier is needed.
-+ */
-+ }
-+ if (prev->mm_cid_active) {
-+ mm_cid_snapshot_time(rq, prev->mm);
-+ mm_cid_put_lazy(prev);
-+ prev->mm_cid = -1;
-+ }
-+ if (next->mm_cid_active)
-+ next->last_mm_cid = next->mm_cid = mm_cid_get(rq, next->mm);
-+}
-+
-+#else
-+static inline void switch_mm_cid(struct rq *rq, struct task_struct *prev, struct task_struct *next) { }
-+static inline void sched_mm_cid_migrate_from(struct task_struct *t) { }
-+static inline void sched_mm_cid_migrate_to(struct rq *dst_rq, struct task_struct *t, int src_cpu) { }
-+static inline void task_tick_mm_cid(struct rq *rq, struct task_struct *curr) { }
-+static inline void init_sched_mm_cid(struct task_struct *t) { }
-+#endif
-+
-+#endif /* ALT_SCHED_H */
-diff --git a/kernel/sched/bmq.h b/kernel/sched/bmq.h
-new file mode 100644
-index 000000000000..840009dc1e8d
---- /dev/null
-+++ b/kernel/sched/bmq.h
-@@ -0,0 +1,99 @@
-+#define ALT_SCHED_NAME "BMQ"
-+
-+/*
-+ * BMQ only routines
-+ */
-+#define rq_switch_time(rq) ((rq)->clock - (rq)->last_ts_switch)
-+#define boost_threshold(p) (sysctl_sched_base_slice >> ((14 - (p)->boost_prio) / 2))
-+
-+static inline void boost_task(struct task_struct *p)
-+{
-+ int limit;
-+
-+ switch (p->policy) {
-+ case SCHED_NORMAL:
-+ limit = -MAX_PRIORITY_ADJ;
-+ break;
-+ case SCHED_BATCH:
-+ case SCHED_IDLE:
-+ limit = 0;
-+ break;
-+ default:
-+ return;
-+ }
-+
-+ if (p->boost_prio > limit)
-+ p->boost_prio--;
-+}
-+
-+static inline void deboost_task(struct task_struct *p)
-+{
-+ if (p->boost_prio < MAX_PRIORITY_ADJ)
-+ p->boost_prio++;
-+}
-+
-+/*
-+ * Common interfaces
-+ */
-+static inline void sched_timeslice_imp(const int timeslice_ms) {}
-+
-+static inline int
-+task_sched_prio_normal(const struct task_struct *p, const struct rq *rq)
-+{
-+ return p->prio + p->boost_prio - MAX_RT_PRIO;
-+}
-+
-+static inline int task_sched_prio(const struct task_struct *p)
-+{
-+ return (p->prio < MAX_RT_PRIO)? (p->prio >> 2) :
-+ MIN_SCHED_NORMAL_PRIO + (p->prio + p->boost_prio - MAX_RT_PRIO) / 2;
-+}
-+
-+static inline int
-+task_sched_prio_idx(const struct task_struct *p, const struct rq *rq)
-+{
-+ return task_sched_prio(p);
-+}
-+
-+static inline int sched_prio2idx(int prio, struct rq *rq)
-+{
-+ return prio;
-+}
-+
-+static inline int sched_idx2prio(int idx, struct rq *rq)
-+{
-+ return idx;
-+}
-+
-+inline int task_running_nice(struct task_struct *p)
-+{
-+ return (p->prio + p->boost_prio > DEFAULT_PRIO + MAX_PRIORITY_ADJ);
-+}
-+
-+static inline void sched_update_rq_clock(struct rq *rq) {}
-+
-+static inline void sched_task_renew(struct task_struct *p, const struct rq *rq)
-+{
-+ if (rq_switch_time(rq) > sysctl_sched_base_slice)
-+ deboost_task(p);
-+}
-+
-+static inline void sched_task_sanity_check(struct task_struct *p, struct rq *rq) {}
-+static void sched_task_fork(struct task_struct *p, struct rq *rq) {}
-+
-+static inline void do_sched_yield_type_1(struct task_struct *p, struct rq *rq)
-+{
-+ p->boost_prio = MAX_PRIORITY_ADJ;
-+}
-+
-+static inline void sched_task_ttwu(struct task_struct *p)
-+{
-+ if(this_rq()->clock_task - p->last_ran > sysctl_sched_base_slice)
-+ boost_task(p);
-+}
-+
-+static inline void sched_task_deactivate(struct task_struct *p, struct rq *rq)
-+{
-+ if (rq_switch_time(rq) < boost_threshold(p))
-+ boost_task(p);
-+}
-diff --git a/kernel/sched/build_policy.c b/kernel/sched/build_policy.c
-index d9dc9ab3773f..71a25540d65e 100644
---- a/kernel/sched/build_policy.c
-+++ b/kernel/sched/build_policy.c
-@@ -42,13 +42,19 @@
-
- #include "idle.c"
-
-+#ifndef CONFIG_SCHED_ALT
- #include "rt.c"
-+#endif
-
- #ifdef CONFIG_SMP
-+#ifndef CONFIG_SCHED_ALT
- # include "cpudeadline.c"
-+#endif
- # include "pelt.c"
- #endif
-
- #include "cputime.c"
--#include "deadline.c"
-
-+#ifndef CONFIG_SCHED_ALT
-+#include "deadline.c"
-+#endif
-diff --git a/kernel/sched/build_utility.c b/kernel/sched/build_utility.c
-index 80a3df49ab47..bc17d5a6fc41 100644
---- a/kernel/sched/build_utility.c
-+++ b/kernel/sched/build_utility.c
-@@ -84,7 +84,9 @@
-
- #ifdef CONFIG_SMP
- # include "cpupri.c"
-+#ifndef CONFIG_SCHED_ALT
- # include "stop_task.c"
-+#endif
- # include "topology.c"
- #endif
-
-diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
-index eece6244f9d2..3075127f9e95 100644
---- a/kernel/sched/cpufreq_schedutil.c
-+++ b/kernel/sched/cpufreq_schedutil.c
-@@ -197,12 +197,17 @@ unsigned long sugov_effective_cpu_perf(int cpu, unsigned long actual,
-
- static void sugov_get_util(struct sugov_cpu *sg_cpu, unsigned long boost)
- {
-+#ifndef CONFIG_SCHED_ALT
- unsigned long min, max, util = cpu_util_cfs_boost(sg_cpu->cpu);
-
- util = effective_cpu_util(sg_cpu->cpu, util, &min, &max);
- util = max(util, boost);
- sg_cpu->bw_min = min;
- sg_cpu->util = sugov_effective_cpu_perf(sg_cpu->cpu, util, min, max);
-+#else /* CONFIG_SCHED_ALT */
-+ sg_cpu->bw_min = 0;
-+ sg_cpu->util = rq_load_util(cpu_rq(sg_cpu->cpu), arch_scale_cpu_capacity(sg_cpu->cpu));
-+#endif /* CONFIG_SCHED_ALT */
- }
-
- /**
-@@ -343,8 +348,10 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; }
- */
- static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu)
- {
-+#ifndef CONFIG_SCHED_ALT
- if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_min)
- sg_cpu->sg_policy->limits_changed = true;
-+#endif
- }
-
- static inline bool sugov_update_single_common(struct sugov_cpu *sg_cpu,
-@@ -676,6 +683,7 @@ static int sugov_kthread_create(struct sugov_policy *sg_policy)
- }
-
- ret = sched_setattr_nocheck(thread, &attr);
-+
- if (ret) {
- kthread_stop(thread);
- pr_warn("%s: failed to set SCHED_DEADLINE\n", __func__);
-diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c
-index af7952f12e6c..6461cbbb734d 100644
---- a/kernel/sched/cputime.c
-+++ b/kernel/sched/cputime.c
-@@ -126,7 +126,7 @@ void account_user_time(struct task_struct *p, u64 cputime)
- p->utime += cputime;
- account_group_user_time(p, cputime);
-
-- index = (task_nice(p) > 0) ? CPUTIME_NICE : CPUTIME_USER;
-+ index = task_running_nice(p) ? CPUTIME_NICE : CPUTIME_USER;
-
- /* Add user time to cpustat. */
- task_group_account_field(p, index, cputime);
-@@ -150,7 +150,7 @@ void account_guest_time(struct task_struct *p, u64 cputime)
- p->gtime += cputime;
-
- /* Add guest time to cpustat. */
-- if (task_nice(p) > 0) {
-+ if (task_running_nice(p)) {
- task_group_account_field(p, CPUTIME_NICE, cputime);
- cpustat[CPUTIME_GUEST_NICE] += cputime;
- } else {
-@@ -288,7 +288,7 @@ static inline u64 account_other_time(u64 max)
- #ifdef CONFIG_64BIT
- static inline u64 read_sum_exec_runtime(struct task_struct *t)
- {
-- return t->se.sum_exec_runtime;
-+ return tsk_seruntime(t);
- }
- #else
- static u64 read_sum_exec_runtime(struct task_struct *t)
-@@ -298,7 +298,7 @@ static u64 read_sum_exec_runtime(struct task_struct *t)
- struct rq *rq;
-
- rq = task_rq_lock(t, &rf);
-- ns = t->se.sum_exec_runtime;
-+ ns = tsk_seruntime(t);
- task_rq_unlock(rq, t, &rf);
-
- return ns;
-@@ -630,7 +630,7 @@ void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev,
- void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st)
- {
- struct task_cputime cputime = {
-- .sum_exec_runtime = p->se.sum_exec_runtime,
-+ .sum_exec_runtime = tsk_seruntime(p),
- };
-
- if (task_cputime(p, &cputime.utime, &cputime.stime))
-diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
-index 8d5d98a5834d..15b9a02717ae 100644
---- a/kernel/sched/debug.c
-+++ b/kernel/sched/debug.c
-@@ -7,6 +7,7 @@
- * Copyright(C) 2007, Red Hat, Inc., Ingo Molnar
- */
-
-+#ifndef CONFIG_SCHED_ALT
- /*
- * This allows printing both to /sys/kernel/debug/sched/debug and
- * to the console
-@@ -215,6 +216,7 @@ static const struct file_operations sched_scaling_fops = {
- };
-
- #endif /* SMP */
-+#endif /* !CONFIG_SCHED_ALT */
-
- #ifdef CONFIG_PREEMPT_DYNAMIC
-
-@@ -278,6 +280,7 @@ static const struct file_operations sched_dynamic_fops = {
-
- #endif /* CONFIG_PREEMPT_DYNAMIC */
-
-+#ifndef CONFIG_SCHED_ALT
- __read_mostly bool sched_debug_verbose;
-
- #ifdef CONFIG_SMP
-@@ -332,6 +335,7 @@ static const struct file_operations sched_debug_fops = {
- .llseek = seq_lseek,
- .release = seq_release,
- };
-+#endif /* !CONFIG_SCHED_ALT */
-
- static struct dentry *debugfs_sched;
-
-@@ -341,14 +345,17 @@ static __init int sched_init_debug(void)
-
- debugfs_sched = debugfs_create_dir("sched", NULL);
-
-+#ifndef CONFIG_SCHED_ALT
- debugfs_create_file("features", 0644, debugfs_sched, NULL, &sched_feat_fops);
- debugfs_create_file_unsafe("verbose", 0644, debugfs_sched, &sched_debug_verbose, &sched_verbose_fops);
-+#endif /* !CONFIG_SCHED_ALT */
- #ifdef CONFIG_PREEMPT_DYNAMIC
- debugfs_create_file("preempt", 0644, debugfs_sched, NULL, &sched_dynamic_fops);
- #endif
-
- debugfs_create_u32("base_slice_ns", 0644, debugfs_sched, &sysctl_sched_base_slice);
-
-+#ifndef CONFIG_SCHED_ALT
- debugfs_create_u32("latency_warn_ms", 0644, debugfs_sched, &sysctl_resched_latency_warn_ms);
- debugfs_create_u32("latency_warn_once", 0644, debugfs_sched, &sysctl_resched_latency_warn_once);
-
-@@ -373,11 +380,13 @@ static __init int sched_init_debug(void)
- #endif
-
- debugfs_create_file("debug", 0444, debugfs_sched, NULL, &sched_debug_fops);
-+#endif /* !CONFIG_SCHED_ALT */
-
- return 0;
- }
- late_initcall(sched_init_debug);
-
-+#ifndef CONFIG_SCHED_ALT
- #ifdef CONFIG_SMP
-
- static cpumask_var_t sd_sysctl_cpus;
-@@ -1110,6 +1119,7 @@ void proc_sched_set_task(struct task_struct *p)
- memset(&p->stats, 0, sizeof(p->stats));
- #endif
- }
-+#endif /* !CONFIG_SCHED_ALT */
-
- void resched_latency_warn(int cpu, u64 latency)
- {
-diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
-index 31231925f1ec..c087311032f2 100644
---- a/kernel/sched/idle.c
-+++ b/kernel/sched/idle.c
-@@ -410,6 +410,7 @@ void cpu_startup_entry(enum cpuhp_state state)
- do_idle();
- }
-
-+#ifndef CONFIG_SCHED_ALT
- /*
- * idle-task scheduling class.
- */
-@@ -531,3 +532,4 @@ DEFINE_SCHED_CLASS(idle) = {
- .switched_to = switched_to_idle,
- .update_curr = update_curr_idle,
- };
-+#endif
-diff --git a/kernel/sched/pds.h b/kernel/sched/pds.h
-new file mode 100644
-index 000000000000..c35dfb909f23
---- /dev/null
-+++ b/kernel/sched/pds.h
-@@ -0,0 +1,141 @@
-+#define ALT_SCHED_NAME "PDS"
-+
-+static const u64 RT_MASK = ((1ULL << MIN_SCHED_NORMAL_PRIO) - 1);
-+
-+#define SCHED_NORMAL_PRIO_NUM (32)
-+#define SCHED_EDGE_DELTA (SCHED_NORMAL_PRIO_NUM - NICE_WIDTH / 2)
-+
-+/* PDS assume NORMAL_PRIO_NUM is power of 2 */
-+#define SCHED_NORMAL_PRIO_MOD(x) ((x) & (SCHED_NORMAL_PRIO_NUM - 1))
-+
-+/* default time slice 4ms -> shift 22, 2 time slice slots -> shift 23 */
-+static __read_mostly int sched_timeslice_shift = 23;
-+
-+/*
-+ * Common interfaces
-+ */
-+static inline void sched_timeslice_imp(const int timeslice_ms)
-+{
-+ if (2 == timeslice_ms)
-+ sched_timeslice_shift = 22;
-+}
-+
-+static inline int
-+task_sched_prio_normal(const struct task_struct *p, const struct rq *rq)
-+{
-+ s64 delta = p->deadline - rq->time_edge + SCHED_EDGE_DELTA;
-+
-+#ifdef ALT_SCHED_DEBUG
-+ if (WARN_ONCE(delta > NORMAL_PRIO_NUM - 1,
-+ "pds: task_sched_prio_normal() delta %lld\n", delta))
-+ return SCHED_NORMAL_PRIO_NUM - 1;
-+#endif
-+
-+ return max(0LL, delta);
-+}
-+
-+static inline int task_sched_prio(const struct task_struct *p)
-+{
-+ return (p->prio < MIN_NORMAL_PRIO) ? (p->prio >> 2) :
-+ MIN_SCHED_NORMAL_PRIO + task_sched_prio_normal(p, task_rq(p));
-+}
-+
-+static inline int
-+task_sched_prio_idx(const struct task_struct *p, const struct rq *rq)
-+{
-+ u64 idx;
-+
-+ if (p->prio < MIN_NORMAL_PRIO)
-+ return p->prio >> 2;
-+
-+ idx = max(p->deadline + SCHED_EDGE_DELTA, rq->time_edge);
-+ /*printk(KERN_INFO "sched: task_sched_prio_idx edge:%llu, deadline=%llu idx=%llu\n", rq->time_edge, p->deadline, idx);*/
-+ return MIN_SCHED_NORMAL_PRIO + SCHED_NORMAL_PRIO_MOD(idx);
-+}
-+
-+static inline int sched_prio2idx(int sched_prio, struct rq *rq)
-+{
-+ return (IDLE_TASK_SCHED_PRIO == sched_prio || sched_prio < MIN_SCHED_NORMAL_PRIO) ?
-+ sched_prio :
-+ MIN_SCHED_NORMAL_PRIO + SCHED_NORMAL_PRIO_MOD(sched_prio + rq->time_edge);
-+}
-+
-+static inline int sched_idx2prio(int sched_idx, struct rq *rq)
-+{
-+ return (sched_idx < MIN_SCHED_NORMAL_PRIO) ?
-+ sched_idx :
-+ MIN_SCHED_NORMAL_PRIO + SCHED_NORMAL_PRIO_MOD(sched_idx - rq->time_edge);
-+}
-+
-+int task_running_nice(struct task_struct *p)
-+{
-+ return (p->prio > DEFAULT_PRIO);
-+}
-+
-+static inline void sched_update_rq_clock(struct rq *rq)
-+{
-+ struct list_head head;
-+ u64 old = rq->time_edge;
-+ u64 now = rq->clock >> sched_timeslice_shift;
-+ u64 prio, delta;
-+ DECLARE_BITMAP(normal, SCHED_QUEUE_BITS);
-+
-+ if (now == old)
-+ return;
-+
-+ rq->time_edge = now;
-+ delta = min_t(u64, SCHED_NORMAL_PRIO_NUM, now - old);
-+ INIT_LIST_HEAD(&head);
-+
-+ prio = MIN_SCHED_NORMAL_PRIO;
-+ for_each_set_bit_from(prio, rq->queue.bitmap, MIN_SCHED_NORMAL_PRIO + delta)
-+ list_splice_tail_init(rq->queue.heads + MIN_SCHED_NORMAL_PRIO +
-+ SCHED_NORMAL_PRIO_MOD(prio + old), &head);
-+
-+ bitmap_shift_right(normal, rq->queue.bitmap, delta, SCHED_QUEUE_BITS);
-+ if (!list_empty(&head)) {
-+ struct task_struct *p;
-+ u64 idx = MIN_SCHED_NORMAL_PRIO + SCHED_NORMAL_PRIO_MOD(now);
-+
-+ list_for_each_entry(p, &head, sq_node)
-+ p->sq_idx = idx;
-+
-+ list_splice(&head, rq->queue.heads + idx);
-+ set_bit(MIN_SCHED_NORMAL_PRIO, normal);
-+ }
-+ bitmap_replace(rq->queue.bitmap, normal, rq->queue.bitmap,
-+ (const unsigned long *)&RT_MASK, SCHED_QUEUE_BITS);
-+
-+ if (rq->prio < MIN_SCHED_NORMAL_PRIO || IDLE_TASK_SCHED_PRIO == rq->prio)
-+ return;
-+
-+ rq->prio = (rq->prio < MIN_SCHED_NORMAL_PRIO + delta) ?
-+ MIN_SCHED_NORMAL_PRIO : rq->prio - delta;
-+}
-+
-+static inline void sched_task_renew(struct task_struct *p, const struct rq *rq)
-+{
-+ if (p->prio >= MIN_NORMAL_PRIO)
-+ p->deadline = rq->time_edge + (p->static_prio - (MAX_PRIO - NICE_WIDTH)) / 2;
-+}
-+
-+static inline void sched_task_sanity_check(struct task_struct *p, struct rq *rq)
-+{
-+ u64 max_dl = rq->time_edge + NICE_WIDTH / 2 - 1;
-+ if (unlikely(p->deadline > max_dl))
-+ p->deadline = max_dl;
-+}
-+
-+static void sched_task_fork(struct task_struct *p, struct rq *rq)
-+{
-+ sched_task_renew(p, rq);
-+}
-+
-+static inline void do_sched_yield_type_1(struct task_struct *p, struct rq *rq)
-+{
-+ p->time_slice = sysctl_sched_base_slice;
-+ sched_task_renew(p, rq);
-+}
-+
-+static inline void sched_task_ttwu(struct task_struct *p) {}
-+static inline void sched_task_deactivate(struct task_struct *p, struct rq *rq) {}
-diff --git a/kernel/sched/pelt.c b/kernel/sched/pelt.c
-index 63b6cf898220..9ca10ece4d3a 100644
---- a/kernel/sched/pelt.c
-+++ b/kernel/sched/pelt.c
-@@ -266,6 +266,7 @@ ___update_load_avg(struct sched_avg *sa, unsigned long load)
- WRITE_ONCE(sa->util_avg, sa->util_sum / divider);
- }
-
-+#ifndef CONFIG_SCHED_ALT
- /*
- * sched_entity:
- *
-@@ -383,8 +384,9 @@ int update_dl_rq_load_avg(u64 now, struct rq *rq, int running)
-
- return 0;
- }
-+#endif
-
--#ifdef CONFIG_SCHED_THERMAL_PRESSURE
-+#if defined(CONFIG_SCHED_THERMAL_PRESSURE) && !defined(CONFIG_SCHED_ALT)
- /*
- * thermal:
- *
-diff --git a/kernel/sched/pelt.h b/kernel/sched/pelt.h
-index 9e1083465fbc..d35f050e8296 100644
---- a/kernel/sched/pelt.h
-+++ b/kernel/sched/pelt.h
-@@ -1,13 +1,15 @@
- #ifdef CONFIG_SMP
- #include "sched-pelt.h"
-
-+#ifndef CONFIG_SCHED_ALT
- int __update_load_avg_blocked_se(u64 now, struct sched_entity *se);
- int __update_load_avg_se(u64 now, struct cfs_rq *cfs_rq, struct sched_entity *se);
- int __update_load_avg_cfs_rq(u64 now, struct cfs_rq *cfs_rq);
- int update_rt_rq_load_avg(u64 now, struct rq *rq, int running);
- int update_dl_rq_load_avg(u64 now, struct rq *rq, int running);
-+#endif
-
--#ifdef CONFIG_SCHED_THERMAL_PRESSURE
-+#if defined(CONFIG_SCHED_THERMAL_PRESSURE) && !defined(CONFIG_SCHED_ALT)
- int update_thermal_load_avg(u64 now, struct rq *rq, u64 capacity);
-
- static inline u64 thermal_load_avg(struct rq *rq)
-@@ -44,6 +46,7 @@ static inline u32 get_pelt_divider(struct sched_avg *avg)
- return PELT_MIN_DIVIDER + avg->period_contrib;
- }
-
-+#ifndef CONFIG_SCHED_ALT
- static inline void cfs_se_util_change(struct sched_avg *avg)
- {
- unsigned int enqueued;
-@@ -180,9 +183,11 @@ static inline u64 cfs_rq_clock_pelt(struct cfs_rq *cfs_rq)
- return rq_clock_pelt(rq_of(cfs_rq));
- }
- #endif
-+#endif /* CONFIG_SCHED_ALT */
-
- #else
-
-+#ifndef CONFIG_SCHED_ALT
- static inline int
- update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
- {
-@@ -200,6 +205,7 @@ update_dl_rq_load_avg(u64 now, struct rq *rq, int running)
- {
- return 0;
- }
-+#endif
-
- static inline int
- update_thermal_load_avg(u64 now, struct rq *rq, u64 capacity)
-diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
-index 001fe047bd5d..a2fafb8f3306 100644
---- a/kernel/sched/sched.h
-+++ b/kernel/sched/sched.h
-@@ -5,6 +5,10 @@
- #ifndef _KERNEL_SCHED_SCHED_H
- #define _KERNEL_SCHED_SCHED_H
-
-+#ifdef CONFIG_SCHED_ALT
-+#include "alt_sched.h"
-+#else
-+
- #include <linux/sched/affinity.h>
- #include <linux/sched/autogroup.h>
- #include <linux/sched/cpufreq.h>
-@@ -3473,4 +3477,9 @@ static inline void init_sched_mm_cid(struct task_struct *t) { }
- extern u64 avg_vruntime(struct cfs_rq *cfs_rq);
- extern int entity_eligible(struct cfs_rq *cfs_rq, struct sched_entity *se);
-
-+static inline int task_running_nice(struct task_struct *p)
-+{
-+ return (task_nice(p) > 0);
-+}
-+#endif /* !CONFIG_SCHED_ALT */
- #endif /* _KERNEL_SCHED_SCHED_H */
-diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c
-index 857f837f52cb..5486c63e4790 100644
---- a/kernel/sched/stats.c
-+++ b/kernel/sched/stats.c
-@@ -125,8 +125,10 @@ static int show_schedstat(struct seq_file *seq, void *v)
- } else {
- struct rq *rq;
- #ifdef CONFIG_SMP
-+#ifndef CONFIG_SCHED_ALT
- struct sched_domain *sd;
- int dcount = 0;
-+#endif
- #endif
- cpu = (unsigned long)(v - 2);
- rq = cpu_rq(cpu);
-@@ -143,6 +145,7 @@ static int show_schedstat(struct seq_file *seq, void *v)
- seq_printf(seq, "\n");
-
- #ifdef CONFIG_SMP
-+#ifndef CONFIG_SCHED_ALT
- /* domain-specific stats */
- rcu_read_lock();
- for_each_domain(cpu, sd) {
-@@ -171,6 +174,7 @@ static int show_schedstat(struct seq_file *seq, void *v)
- sd->ttwu_move_balance);
- }
- rcu_read_unlock();
-+#endif
- #endif
- }
- return 0;
-diff --git a/kernel/sched/stats.h b/kernel/sched/stats.h
-index 38f3698f5e5b..b9d597394316 100644
---- a/kernel/sched/stats.h
-+++ b/kernel/sched/stats.h
-@@ -89,6 +89,7 @@ static inline void rq_sched_info_depart (struct rq *rq, unsigned long long delt
-
- #endif /* CONFIG_SCHEDSTATS */
-
-+#ifndef CONFIG_SCHED_ALT
- #ifdef CONFIG_FAIR_GROUP_SCHED
- struct sched_entity_stats {
- struct sched_entity se;
-@@ -105,6 +106,7 @@ __schedstats_from_se(struct sched_entity *se)
- #endif
- return &task_of(se)->stats;
- }
-+#endif /* CONFIG_SCHED_ALT */
-
- #ifdef CONFIG_PSI
- void psi_task_change(struct task_struct *task, int clear, int set);
-diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
-index 10d1391e7416..dc717683342e 100644
---- a/kernel/sched/topology.c
-+++ b/kernel/sched/topology.c
-@@ -3,6 +3,7 @@
- * Scheduler topology setup/handling methods
- */
-
-+#ifndef CONFIG_SCHED_ALT
- #include <linux/bsearch.h>
-
- DEFINE_MUTEX(sched_domains_mutex);
-@@ -1445,8 +1446,10 @@ static void asym_cpu_capacity_scan(void)
- */
-
- static int default_relax_domain_level = -1;
-+#endif /* CONFIG_SCHED_ALT */
- int sched_domain_level_max;
-
-+#ifndef CONFIG_SCHED_ALT
- static int __init setup_relax_domain_level(char *str)
- {
- if (kstrtoint(str, 0, &default_relax_domain_level))
-@@ -1680,6 +1683,7 @@ sd_init(struct sched_domain_topology_level *tl,
-
- return sd;
- }
-+#endif /* CONFIG_SCHED_ALT */
-
- /*
- * Topology list, bottom-up.
-@@ -1716,6 +1720,7 @@ void __init set_sched_topology(struct sched_domain_topology_level *tl)
- sched_domain_topology_saved = NULL;
- }
-
-+#ifndef CONFIG_SCHED_ALT
- #ifdef CONFIG_NUMA
-
- static const struct cpumask *sd_numa_mask(int cpu)
-@@ -2793,3 +2798,26 @@ void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
- partition_sched_domains_locked(ndoms_new, doms_new, dattr_new);
- mutex_unlock(&sched_domains_mutex);
- }
-+#else /* CONFIG_SCHED_ALT */
-+void partition_sched_domains(int ndoms_new, cpumask_var_t doms_new[],
-+ struct sched_domain_attr *dattr_new)
-+{}
-+
-+#ifdef CONFIG_NUMA
-+int sched_numa_find_closest(const struct cpumask *cpus, int cpu)
-+{
-+ return best_mask_cpu(cpu, cpus);
-+}
-+
-+int sched_numa_find_nth_cpu(const struct cpumask *cpus, int cpu, int node)
-+{
-+ return cpumask_nth(cpu, cpus);
-+}
-+
-+const struct cpumask *sched_numa_hop_mask(unsigned int node, unsigned int hops)
-+{
-+ return ERR_PTR(-EOPNOTSUPP);
-+}
-+EXPORT_SYMBOL_GPL(sched_numa_hop_mask);
-+#endif /* CONFIG_NUMA */
-+#endif
-diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index 157f7ce2942d..63083a9a2935 100644
---- a/kernel/sysctl.c
-+++ b/kernel/sysctl.c
-@@ -92,6 +92,10 @@ EXPORT_SYMBOL_GPL(sysctl_long_vals);
-
- /* Constants used for minimum and maximum */
-
-+#ifdef CONFIG_SCHED_ALT
-+extern int sched_yield_type;
-+#endif
-+
- #ifdef CONFIG_PERF_EVENTS
- static const int six_hundred_forty_kb = 640 * 1024;
- #endif
-@@ -1912,6 +1916,17 @@ static struct ctl_table kern_table[] = {
- .proc_handler = proc_dointvec,
- },
- #endif
-+#ifdef CONFIG_SCHED_ALT
-+ {
-+ .procname = "yield_type",
-+ .data = &sched_yield_type,
-+ .maxlen = sizeof (int),
-+ .mode = 0644,
-+ .proc_handler = &proc_dointvec_minmax,
-+ .extra1 = SYSCTL_ZERO,
-+ .extra2 = SYSCTL_TWO,
-+ },
-+#endif
- #if defined(CONFIG_S390) && defined(CONFIG_SMP)
- {
- .procname = "spin_retry",
-diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
-index edb0f821dcea..bfc4a6afc77e 100644
---- a/kernel/time/hrtimer.c
-+++ b/kernel/time/hrtimer.c
-@@ -2092,8 +2092,10 @@ long hrtimer_nanosleep(ktime_t rqtp, const enum hrtimer_mode mode,
- int ret = 0;
- u64 slack;
-
-+#ifndef CONFIG_SCHED_ALT
- slack = current->timer_slack_ns;
-- if (rt_task(current))
-+ if (dl_task(current) || rt_task(current))
-+#endif
- slack = 0;
-
- hrtimer_init_sleeper_on_stack(&t, clockid, mode);
-diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
-index e9c6f9d0e42c..43ee0a94abdd 100644
---- a/kernel/time/posix-cpu-timers.c
-+++ b/kernel/time/posix-cpu-timers.c
-@@ -223,7 +223,7 @@ static void task_sample_cputime(struct task_struct *p, u64 *samples)
- u64 stime, utime;
-
- task_cputime(p, &utime, &stime);
-- store_samples(samples, stime, utime, p->se.sum_exec_runtime);
-+ store_samples(samples, stime, utime, tsk_seruntime(p));
- }
-
- static void proc_sample_cputime_atomic(struct task_cputime_atomic *at,
-@@ -867,6 +867,7 @@ static void collect_posix_cputimers(struct posix_cputimers *pct, u64 *samples,
- }
- }
-
-+#ifndef CONFIG_SCHED_ALT
- static inline void check_dl_overrun(struct task_struct *tsk)
- {
- if (tsk->dl.dl_overrun) {
-@@ -874,6 +875,7 @@ static inline void check_dl_overrun(struct task_struct *tsk)
- send_signal_locked(SIGXCPU, SEND_SIG_PRIV, tsk, PIDTYPE_TGID);
- }
- }
-+#endif
-
- static bool check_rlimit(u64 time, u64 limit, int signo, bool rt, bool hard)
- {
-@@ -901,8 +903,10 @@ static void check_thread_timers(struct task_struct *tsk,
- u64 samples[CPUCLOCK_MAX];
- unsigned long soft;
-
-+#ifndef CONFIG_SCHED_ALT
- if (dl_task(tsk))
- check_dl_overrun(tsk);
-+#endif
-
- if (expiry_cache_is_inactive(pct))
- return;
-@@ -916,7 +920,7 @@ static void check_thread_timers(struct task_struct *tsk,
- soft = task_rlimit(tsk, RLIMIT_RTTIME);
- if (soft != RLIM_INFINITY) {
- /* Task RT timeout is accounted in jiffies. RTTIME is usec */
-- unsigned long rttime = tsk->rt.timeout * (USEC_PER_SEC / HZ);
-+ unsigned long rttime = tsk_rttimeout(tsk) * (USEC_PER_SEC / HZ);
- unsigned long hard = task_rlimit_max(tsk, RLIMIT_RTTIME);
-
- /* At the hard limit, send SIGKILL. No further action. */
-@@ -1152,8 +1156,10 @@ static inline bool fastpath_timer_check(struct task_struct *tsk)
- return true;
- }
-
-+#ifndef CONFIG_SCHED_ALT
- if (dl_task(tsk) && tsk->dl.dl_overrun)
- return true;
-+#endif
-
- return false;
- }
-diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
-index 529590499b1f..d04bb99b4f0e 100644
---- a/kernel/trace/trace_selftest.c
-+++ b/kernel/trace/trace_selftest.c
-@@ -1155,10 +1155,15 @@ static int trace_wakeup_test_thread(void *data)
- {
- /* Make this a -deadline thread */
- static const struct sched_attr attr = {
-+#ifdef CONFIG_SCHED_ALT
-+ /* No deadline on BMQ/PDS, use RR */
-+ .sched_policy = SCHED_RR,
-+#else
- .sched_policy = SCHED_DEADLINE,
- .sched_runtime = 100000ULL,
- .sched_deadline = 10000000ULL,
- .sched_period = 10000000ULL
-+#endif
- };
- struct wakeup_test_data *x = data;
-
-diff --git a/kernel/workqueue.c b/kernel/workqueue.c
-index 7b482a26d741..e5b053326631 100644
---- a/kernel/workqueue.c
-+++ b/kernel/workqueue.c
-@@ -1120,6 +1120,7 @@ static bool kick_pool(struct worker_pool *pool)
-
- p = worker->task;
-
-+#ifndef CONFIG_SCHED_ALT
- #ifdef CONFIG_SMP
- /*
- * Idle @worker is about to execute @work and waking up provides an
-@@ -1145,6 +1146,8 @@ static bool kick_pool(struct worker_pool *pool)
- get_work_pwq(work)->stats[PWQ_STAT_REPATRIATED]++;
- }
- #endif
-+#endif /* !CONFIG_SCHED_ALT */
-+
- wake_up_process(p);
- return true;
- }
-@@ -1269,7 +1272,11 @@ void wq_worker_running(struct task_struct *task)
- * CPU intensive auto-detection cares about how long a work item hogged
- * CPU without sleeping. Reset the starting timestamp on wakeup.
- */
-+#ifdef CONFIG_SCHED_ALT
-+ worker->current_at = worker->task->sched_time;
-+#else
- worker->current_at = worker->task->se.sum_exec_runtime;
-+#endif
-
- WRITE_ONCE(worker->sleeping, 0);
- }
-@@ -1354,7 +1361,11 @@ void wq_worker_tick(struct task_struct *task)
- * We probably want to make this prettier in the future.
- */
- if ((worker->flags & WORKER_NOT_RUNNING) || READ_ONCE(worker->sleeping) ||
-+#ifdef CONFIG_SCHED_ALT
-+ worker->task->sched_time - worker->current_at <
-+#else
- worker->task->se.sum_exec_runtime - worker->current_at <
-+#endif
- wq_cpu_intensive_thresh_us * NSEC_PER_USEC)
- return;
-
-@@ -2565,7 +2576,11 @@ __acquires(&pool->lock)
- worker->current_work = work;
- worker->current_func = work->func;
- worker->current_pwq = pwq;
-+#ifdef CONFIG_SCHED_ALT
-+ worker->current_at = worker->task->sched_time;
-+#else
- worker->current_at = worker->task->se.sum_exec_runtime;
-+#endif
- work_data = *work_data_bits(work);
- worker->current_color = get_work_color(work_data);
-
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-03 14:20 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-04-03 14:20 UTC (permalink / raw
To: gentoo-commits
commit: 8ec08a72981d71b80db83289cc474796dc40bbf8
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Wed Apr 3 14:20:16 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Wed Apr 3 14:20:16 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=8ec08a72
Linux patch 6.8.3
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1002_linux-6.8.3.patch | 18896 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 18900 insertions(+)
diff --git a/0000_README b/0000_README
index a259dbf2..b8286427 100644
--- a/0000_README
+++ b/0000_README
@@ -51,6 +51,10 @@ Patch: 1001_linux-6.8.2.patch
From: https://www.kernel.org
Desc: Linux 6.8.2
+Patch: 1002_linux-6.8.3.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.3
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1002_linux-6.8.3.patch b/1002_linux-6.8.3.patch
new file mode 100644
index 00000000..a7b085bc
--- /dev/null
+++ b/1002_linux-6.8.3.patch
@@ -0,0 +1,18896 @@
+diff --git a/Documentation/Makefile b/Documentation/Makefile
+index 3885bbe260eb2..99cb6cbccb135 100644
+--- a/Documentation/Makefile
++++ b/Documentation/Makefile
+@@ -111,7 +111,9 @@ $(YNL_INDEX): $(YNL_RST_FILES)
+ $(YNL_RST_DIR)/%.rst: $(YNL_YAML_DIR)/%.yaml $(YNL_TOOL)
+ $(Q)$(YNL_TOOL) -i $< -o $@
+
+-htmldocs: $(YNL_INDEX)
++htmldocs texinfodocs latexdocs epubdocs xmldocs: $(YNL_INDEX)
++
++htmldocs:
+ @$(srctree)/scripts/sphinx-pre-install --version-check
+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index 73062d47a462e..d2150bd3acc58 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -3340,9 +3340,7 @@
+
+ mem_encrypt= [X86-64] AMD Secure Memory Encryption (SME) control
+ Valid arguments: on, off
+- Default (depends on kernel configuration option):
+- on (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=y)
+- off (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=n)
++ Default: off
+ mem_encrypt=on: Activate SME
+ mem_encrypt=off: Do not activate SME
+
+diff --git a/Documentation/arch/x86/amd-memory-encryption.rst b/Documentation/arch/x86/amd-memory-encryption.rst
+index 07caa8fff852e..414bc7402ae7d 100644
+--- a/Documentation/arch/x86/amd-memory-encryption.rst
++++ b/Documentation/arch/x86/amd-memory-encryption.rst
+@@ -87,14 +87,14 @@ The state of SME in the Linux kernel can be documented as follows:
+ kernel is non-zero).
+
+ SME can also be enabled and activated in the BIOS. If SME is enabled and
+-activated in the BIOS, then all memory accesses will be encrypted and it will
+-not be necessary to activate the Linux memory encryption support. If the BIOS
+-merely enables SME (sets bit 23 of the MSR_AMD64_SYSCFG), then Linux can activate
+-memory encryption by default (CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT=y) or
+-by supplying mem_encrypt=on on the kernel command line. However, if BIOS does
+-not enable SME, then Linux will not be able to activate memory encryption, even
+-if configured to do so by default or the mem_encrypt=on command line parameter
+-is specified.
++activated in the BIOS, then all memory accesses will be encrypted and it
++will not be necessary to activate the Linux memory encryption support.
++
++If the BIOS merely enables SME (sets bit 23 of the MSR_AMD64_SYSCFG),
++then memory encryption can be enabled by supplying mem_encrypt=on on the
++kernel command line. However, if BIOS does not enable SME, then Linux
++will not be able to activate memory encryption, even if configured to do
++so by default or the mem_encrypt=on command line parameter is specified.
+
+ Secure Nested Paging (SNP)
+ ==========================
+diff --git a/Documentation/conf.py b/Documentation/conf.py
+index da64c9fb7e072..d148f3e8dd572 100644
+--- a/Documentation/conf.py
++++ b/Documentation/conf.py
+@@ -346,9 +346,9 @@ sys.stderr.write("Using %s theme\n" % html_theme)
+ html_static_path = ['sphinx-static']
+
+ # If true, Docutils "smart quotes" will be used to convert quotes and dashes
+-# to typographically correct entities. This will convert "--" to "—",
+-# which is not always what we want, so disable it.
+-smartquotes = False
++# to typographically correct entities. However, conversion of "--" to "—"
++# is not always what we want, so enable only quotes.
++smartquotes_action = 'q'
+
+ # Custom sidebar templates, maps document names to template names.
+ # Note that the RTD theme ignores this
+diff --git a/Documentation/userspace-api/media/mediactl/media-types.rst b/Documentation/userspace-api/media/mediactl/media-types.rst
+index 0ffeece1e0c8e..6332e8395263b 100644
+--- a/Documentation/userspace-api/media/mediactl/media-types.rst
++++ b/Documentation/userspace-api/media/mediactl/media-types.rst
+@@ -375,12 +375,11 @@ Types and flags used to represent the media graph elements
+ are origins of links.
+
+ * - ``MEDIA_PAD_FL_MUST_CONNECT``
+- - If this flag is set and the pad is linked to any other pad, then
+- at least one of those links must be enabled for the entity to be
+- able to stream. There could be temporary reasons (e.g. device
+- configuration dependent) for the pad to need enabled links even
+- when this flag isn't set; the absence of the flag doesn't imply
+- there is none.
++ - If this flag is set, then for this pad to be able to stream, it must
++ be connected by at least one enabled link. There could be temporary
++ reasons (e.g. device configuration dependent) for the pad to need
++ enabled links even when this flag isn't set; the absence of the flag
++ doesn't imply there is none.
+
+
+ One and only one of ``MEDIA_PAD_FL_SINK`` and ``MEDIA_PAD_FL_SOURCE``
+diff --git a/Makefile b/Makefile
+index 33d8e822f6f11..a78379891d221 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 2
++SUBLEVEL = 3
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 0af6709570d14..0d4e316a389e0 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -503,8 +503,8 @@ source "arch/arm/mm/Kconfig"
+
+ config IWMMXT
+ bool "Enable iWMMXt support"
+- depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4 || CPU_PJ4B
+- default y if PXA27x || PXA3xx || ARCH_MMP || CPU_PJ4 || CPU_PJ4B
++ depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK
++ default y if PXA27x || PXA3xx || ARCH_MMP
+ help
+ Enable support for iWMMXt context switching at run time if
+ running on a CPU that supports it.
+diff --git a/arch/arm/boot/dts/marvell/mmp2-brownstone.dts b/arch/arm/boot/dts/marvell/mmp2-brownstone.dts
+index 04f1ae1382e7a..bc64348b82185 100644
+--- a/arch/arm/boot/dts/marvell/mmp2-brownstone.dts
++++ b/arch/arm/boot/dts/marvell/mmp2-brownstone.dts
+@@ -28,7 +28,7 @@ &uart3 {
+ &twsi1 {
+ status = "okay";
+ pmic: max8925@3c {
+- compatible = "maxium,max8925";
++ compatible = "maxim,max8925";
+ reg = <0x3c>;
+ interrupts = <1>;
+ interrupt-parent = <&intcmux4>;
+diff --git a/arch/arm/include/asm/mman.h b/arch/arm/include/asm/mman.h
+new file mode 100644
+index 0000000000000..2189e507c8e08
+--- /dev/null
++++ b/arch/arm/include/asm/mman.h
+@@ -0,0 +1,14 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef __ASM_MMAN_H__
++#define __ASM_MMAN_H__
++
++#include <asm/system_info.h>
++#include <uapi/asm/mman.h>
++
++static inline bool arch_memory_deny_write_exec_supported(void)
++{
++ return cpu_architecture() >= CPU_ARCH_ARMv6;
++}
++#define arch_memory_deny_write_exec_supported arch_memory_deny_write_exec_supported
++
++#endif /* __ASM_MMAN_H__ */
+diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
+index 771264d4726a7..ae2f2b2b4e5ab 100644
+--- a/arch/arm/kernel/Makefile
++++ b/arch/arm/kernel/Makefile
+@@ -75,8 +75,6 @@ obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
+ obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o
+ obj-$(CONFIG_CPU_XSC3) += xscale-cp0.o
+ obj-$(CONFIG_CPU_MOHAWK) += xscale-cp0.o
+-obj-$(CONFIG_CPU_PJ4) += pj4-cp0.o
+-obj-$(CONFIG_CPU_PJ4B) += pj4-cp0.o
+ obj-$(CONFIG_IWMMXT) += iwmmxt.o
+ obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o
+ obj-$(CONFIG_HW_PERF_EVENTS) += perf_event_xscale.o perf_event_v6.o \
+diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
+index a0218c4867b9b..4a335d3c59690 100644
+--- a/arch/arm/kernel/iwmmxt.S
++++ b/arch/arm/kernel/iwmmxt.S
+@@ -18,18 +18,6 @@
+ #include <asm/assembler.h>
+ #include "iwmmxt.h"
+
+-#if defined(CONFIG_CPU_PJ4) || defined(CONFIG_CPU_PJ4B)
+-#define PJ4(code...) code
+-#define XSC(code...)
+-#elif defined(CONFIG_CPU_MOHAWK) || \
+- defined(CONFIG_CPU_XSC3) || \
+- defined(CONFIG_CPU_XSCALE)
+-#define PJ4(code...)
+-#define XSC(code...) code
+-#else
+-#error "Unsupported iWMMXt architecture"
+-#endif
+-
+ #define MMX_WR0 (0x00)
+ #define MMX_WR1 (0x08)
+ #define MMX_WR2 (0x10)
+@@ -81,17 +69,13 @@ ENDPROC(iwmmxt_undef_handler)
+ ENTRY(iwmmxt_task_enable)
+ inc_preempt_count r10, r3
+
+- XSC(mrc p15, 0, r2, c15, c1, 0)
+- PJ4(mrc p15, 0, r2, c1, c0, 2)
++ mrc p15, 0, r2, c15, c1, 0
+ @ CP0 and CP1 accessible?
+- XSC(tst r2, #0x3)
+- PJ4(tst r2, #0xf)
++ tst r2, #0x3
+ bne 4f @ if so no business here
+ @ enable access to CP0 and CP1
+- XSC(orr r2, r2, #0x3)
+- XSC(mcr p15, 0, r2, c15, c1, 0)
+- PJ4(orr r2, r2, #0xf)
+- PJ4(mcr p15, 0, r2, c1, c0, 2)
++ orr r2, r2, #0x3
++ mcr p15, 0, r2, c15, c1, 0
+
+ ldr r3, =concan_owner
+ ldr r2, [r0, #S_PC] @ current task pc value
+@@ -218,12 +202,9 @@ ENTRY(iwmmxt_task_disable)
+ bne 1f @ no: quit
+
+ @ enable access to CP0 and CP1
+- XSC(mrc p15, 0, r4, c15, c1, 0)
+- XSC(orr r4, r4, #0x3)
+- XSC(mcr p15, 0, r4, c15, c1, 0)
+- PJ4(mrc p15, 0, r4, c1, c0, 2)
+- PJ4(orr r4, r4, #0xf)
+- PJ4(mcr p15, 0, r4, c1, c0, 2)
++ mrc p15, 0, r4, c15, c1, 0
++ orr r4, r4, #0x3
++ mcr p15, 0, r4, c15, c1, 0
+
+ mov r0, #0 @ nothing to load
+ str r0, [r3] @ no more current owner
+@@ -232,10 +213,8 @@ ENTRY(iwmmxt_task_disable)
+ bl concan_save
+
+ @ disable access to CP0 and CP1
+- XSC(bic r4, r4, #0x3)
+- XSC(mcr p15, 0, r4, c15, c1, 0)
+- PJ4(bic r4, r4, #0xf)
+- PJ4(mcr p15, 0, r4, c1, c0, 2)
++ bic r4, r4, #0x3
++ mcr p15, 0, r4, c15, c1, 0
+
+ mrc p15, 0, r2, c2, c0, 0
+ mov r2, r2 @ cpwait
+@@ -330,11 +309,9 @@ ENDPROC(iwmmxt_task_restore)
+ */
+ ENTRY(iwmmxt_task_switch)
+
+- XSC(mrc p15, 0, r1, c15, c1, 0)
+- PJ4(mrc p15, 0, r1, c1, c0, 2)
++ mrc p15, 0, r1, c15, c1, 0
+ @ CP0 and CP1 accessible?
+- XSC(tst r1, #0x3)
+- PJ4(tst r1, #0xf)
++ tst r1, #0x3
+ bne 1f @ yes: block them for next task
+
+ ldr r2, =concan_owner
+@@ -344,10 +321,8 @@ ENTRY(iwmmxt_task_switch)
+ retne lr @ no: leave Concan disabled
+
+ 1: @ flip Concan access
+- XSC(eor r1, r1, #0x3)
+- XSC(mcr p15, 0, r1, c15, c1, 0)
+- PJ4(eor r1, r1, #0xf)
+- PJ4(mcr p15, 0, r1, c1, c0, 2)
++ eor r1, r1, #0x3
++ mcr p15, 0, r1, c15, c1, 0
+
+ mrc p15, 0, r1, c2, c0, 0
+ sub pc, lr, r1, lsr #32 @ cpwait and return
+diff --git a/arch/arm/kernel/pj4-cp0.c b/arch/arm/kernel/pj4-cp0.c
+deleted file mode 100644
+index 4bca8098c4ff5..0000000000000
+--- a/arch/arm/kernel/pj4-cp0.c
++++ /dev/null
+@@ -1,135 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-only
+-/*
+- * linux/arch/arm/kernel/pj4-cp0.c
+- *
+- * PJ4 iWMMXt coprocessor context switching and handling
+- *
+- * Copyright (c) 2010 Marvell International Inc.
+- */
+-
+-#include <linux/types.h>
+-#include <linux/kernel.h>
+-#include <linux/signal.h>
+-#include <linux/sched.h>
+-#include <linux/init.h>
+-#include <linux/io.h>
+-#include <asm/thread_notify.h>
+-#include <asm/cputype.h>
+-
+-static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t)
+-{
+- struct thread_info *thread = t;
+-
+- switch (cmd) {
+- case THREAD_NOTIFY_FLUSH:
+- /*
+- * flush_thread() zeroes thread->fpstate, so no need
+- * to do anything here.
+- *
+- * FALLTHROUGH: Ensure we don't try to overwrite our newly
+- * initialised state information on the first fault.
+- */
+-
+- case THREAD_NOTIFY_EXIT:
+- iwmmxt_task_release(thread);
+- break;
+-
+- case THREAD_NOTIFY_SWITCH:
+- iwmmxt_task_switch(thread);
+- break;
+- }
+-
+- return NOTIFY_DONE;
+-}
+-
+-static struct notifier_block __maybe_unused iwmmxt_notifier_block = {
+- .notifier_call = iwmmxt_do,
+-};
+-
+-
+-static u32 __init pj4_cp_access_read(void)
+-{
+- u32 value;
+-
+- __asm__ __volatile__ (
+- "mrc p15, 0, %0, c1, c0, 2\n\t"
+- : "=r" (value));
+- return value;
+-}
+-
+-static void __init pj4_cp_access_write(u32 value)
+-{
+- u32 temp;
+-
+- __asm__ __volatile__ (
+- "mcr p15, 0, %1, c1, c0, 2\n\t"
+-#ifdef CONFIG_THUMB2_KERNEL
+- "isb\n\t"
+-#else
+- "mrc p15, 0, %0, c1, c0, 2\n\t"
+- "mov %0, %0\n\t"
+- "sub pc, pc, #4\n\t"
+-#endif
+- : "=r" (temp) : "r" (value));
+-}
+-
+-static int __init pj4_get_iwmmxt_version(void)
+-{
+- u32 cp_access, wcid;
+-
+- cp_access = pj4_cp_access_read();
+- pj4_cp_access_write(cp_access | 0xf);
+-
+- /* check if coprocessor 0 and 1 are available */
+- if ((pj4_cp_access_read() & 0xf) != 0xf) {
+- pj4_cp_access_write(cp_access);
+- return -ENODEV;
+- }
+-
+- /* read iWMMXt coprocessor id register p1, c0 */
+- __asm__ __volatile__ ("mrc p1, 0, %0, c0, c0, 0\n" : "=r" (wcid));
+-
+- pj4_cp_access_write(cp_access);
+-
+- /* iWMMXt v1 */
+- if ((wcid & 0xffffff00) == 0x56051000)
+- return 1;
+- /* iWMMXt v2 */
+- if ((wcid & 0xffffff00) == 0x56052000)
+- return 2;
+-
+- return -EINVAL;
+-}
+-
+-/*
+- * Disable CP0/CP1 on boot, and let call_fpe() and the iWMMXt lazy
+- * switch code handle iWMMXt context switching.
+- */
+-static int __init pj4_cp0_init(void)
+-{
+- u32 __maybe_unused cp_access;
+- int vers;
+-
+- if (!cpu_is_pj4())
+- return 0;
+-
+- vers = pj4_get_iwmmxt_version();
+- if (vers < 0)
+- return 0;
+-
+-#ifndef CONFIG_IWMMXT
+- pr_info("PJ4 iWMMXt coprocessor detected, but kernel support is missing.\n");
+-#else
+- cp_access = pj4_cp_access_read() & ~0xf;
+- pj4_cp_access_write(cp_access);
+-
+- pr_info("PJ4 iWMMXt v%d coprocessor enabled.\n", vers);
+- elf_hwcap |= HWCAP_IWMMXT;
+- thread_register_notifier(&iwmmxt_notifier_block);
+- register_iwmmxt_undef_handler();
+-#endif
+-
+- return 0;
+-}
+-
+-late_initcall(pj4_cp0_init);
+diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
+index d19d140a10c7d..0749cf8a66371 100644
+--- a/arch/arm/mm/flush.c
++++ b/arch/arm/mm/flush.c
+@@ -296,6 +296,9 @@ void __sync_icache_dcache(pte_t pteval)
+ return;
+
+ folio = page_folio(pfn_to_page(pfn));
++ if (folio_test_reserved(folio))
++ return;
++
+ if (cache_is_vipt_aliasing())
+ mapping = folio_flush_mapping(folio);
+ else
+diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
+index ce0d24ee7eedb..7dc2c37716e84 100644
+--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
++++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
+@@ -2178,8 +2178,16 @@ pcie1: pcie@1c08000 {
+ ranges = <0x01000000 0x0 0x00000000 0x0 0x40200000 0x0 0x100000>,
+ <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>;
+
+- interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>;
+- interrupt-names = "msi";
++ interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>,
++ <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-names = "msi0", "msi1", "msi2", "msi3",
++ "msi4", "msi5", "msi6", "msi7";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 0 0 434 IRQ_TYPE_LEVEL_HIGH>,
+diff --git a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
+index a20d5d76af352..31e74160b8c13 100644
+--- a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
++++ b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
+@@ -938,8 +938,8 @@ &sound {
+ "TX DMIC3", "MIC BIAS1",
+ "TX SWR_INPUT0", "ADC1_OUTPUT",
+ "TX SWR_INPUT1", "ADC2_OUTPUT",
+- "TX SWR_INPUT2", "ADC3_OUTPUT",
+- "TX SWR_INPUT3", "ADC4_OUTPUT";
++ "TX SWR_INPUT0", "ADC3_OUTPUT",
++ "TX SWR_INPUT1", "ADC4_OUTPUT";
+
+ wcd-playback-dai-link {
+ link-name = "WCD Playback";
+diff --git a/arch/arm64/boot/dts/qcom/sm8550-mtp.dts b/arch/arm64/boot/dts/qcom/sm8550-mtp.dts
+index c1135ad5fa696..a26e169a802a4 100644
+--- a/arch/arm64/boot/dts/qcom/sm8550-mtp.dts
++++ b/arch/arm64/boot/dts/qcom/sm8550-mtp.dts
+@@ -874,7 +874,7 @@ &swr2 {
+ wcd_tx: codec@0,3 {
+ compatible = "sdw20217010d00";
+ reg = <0 3>;
+- qcom,tx-port-mapping = <1 1 2 3>;
++ qcom,tx-port-mapping = <2 2 3 4>;
+ };
+ };
+
+diff --git a/arch/arm64/boot/dts/qcom/sm8550-qrd.dts b/arch/arm64/boot/dts/qcom/sm8550-qrd.dts
+index d401d63e5c4d2..54dfee40d6059 100644
+--- a/arch/arm64/boot/dts/qcom/sm8550-qrd.dts
++++ b/arch/arm64/boot/dts/qcom/sm8550-qrd.dts
+@@ -978,7 +978,7 @@ &swr2 {
+ wcd_tx: codec@0,3 {
+ compatible = "sdw20217010d00";
+ reg = <0 3>;
+- qcom,tx-port-mapping = <1 1 2 3>;
++ qcom,tx-port-mapping = <2 2 3 4>;
+ };
+ };
+
+diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S
+index 1140051a0c455..1150b77fa281c 100644
+--- a/arch/hexagon/kernel/vmlinux.lds.S
++++ b/arch/hexagon/kernel/vmlinux.lds.S
+@@ -63,6 +63,7 @@ SECTIONS
+ STABS_DEBUG
+ DWARF_DEBUG
+ ELF_DETAILS
++ .hexagon.attributes 0 : { *(.hexagon.attributes) }
+
+ DISCARDS
+ }
+diff --git a/arch/loongarch/crypto/crc32-loongarch.c b/arch/loongarch/crypto/crc32-loongarch.c
+index a49e507af38c0..3eebea3a7b478 100644
+--- a/arch/loongarch/crypto/crc32-loongarch.c
++++ b/arch/loongarch/crypto/crc32-loongarch.c
+@@ -44,7 +44,6 @@ static u32 crc32_loongarch_hw(u32 crc_, const u8 *p, unsigned int len)
+
+ CRC32(crc, value, w);
+ p += sizeof(u32);
+- len -= sizeof(u32);
+ }
+
+ if (len & sizeof(u16)) {
+@@ -80,7 +79,6 @@ static u32 crc32c_loongarch_hw(u32 crc_, const u8 *p, unsigned int len)
+
+ CRC32C(crc, value, w);
+ p += sizeof(u32);
+- len -= sizeof(u32);
+ }
+
+ if (len & sizeof(u16)) {
+diff --git a/arch/loongarch/include/asm/Kbuild b/arch/loongarch/include/asm/Kbuild
+index 93783fa24f6e9..dede0b422cfb9 100644
+--- a/arch/loongarch/include/asm/Kbuild
++++ b/arch/loongarch/include/asm/Kbuild
+@@ -4,6 +4,7 @@ generic-y += mcs_spinlock.h
+ generic-y += parport.h
+ generic-y += early_ioremap.h
+ generic-y += qrwlock.h
++generic-y += qspinlock.h
+ generic-y += rwsem.h
+ generic-y += segment.h
+ generic-y += user.h
+diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h
+index c486c2341b662..4a8adcca329b8 100644
+--- a/arch/loongarch/include/asm/io.h
++++ b/arch/loongarch/include/asm/io.h
+@@ -71,6 +71,8 @@ extern void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t
+ #define memcpy_fromio(a, c, l) __memcpy_fromio((a), (c), (l))
+ #define memcpy_toio(c, a, l) __memcpy_toio((c), (a), (l))
+
++#define __io_aw() mmiowb()
++
+ #include <asm-generic/io.h>
+
+ #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
+diff --git a/arch/loongarch/include/asm/percpu.h b/arch/loongarch/include/asm/percpu.h
+index 9b36ac003f890..8f290e5546cf7 100644
+--- a/arch/loongarch/include/asm/percpu.h
++++ b/arch/loongarch/include/asm/percpu.h
+@@ -29,7 +29,12 @@ static inline void set_my_cpu_offset(unsigned long off)
+ __my_cpu_offset = off;
+ csr_write64(off, PERCPU_BASE_KS);
+ }
+-#define __my_cpu_offset __my_cpu_offset
++
++#define __my_cpu_offset \
++({ \
++ __asm__ __volatile__("":"+r"(__my_cpu_offset)); \
++ __my_cpu_offset; \
++})
+
+ #define PERCPU_OP(op, asm_op, c_op) \
+ static __always_inline unsigned long __percpu_##op(void *ptr, \
+diff --git a/arch/loongarch/include/asm/qspinlock.h b/arch/loongarch/include/asm/qspinlock.h
+deleted file mode 100644
+index 34f43f8ad5912..0000000000000
+--- a/arch/loongarch/include/asm/qspinlock.h
++++ /dev/null
+@@ -1,18 +0,0 @@
+-/* SPDX-License-Identifier: GPL-2.0 */
+-#ifndef _ASM_QSPINLOCK_H
+-#define _ASM_QSPINLOCK_H
+-
+-#include <asm-generic/qspinlock_types.h>
+-
+-#define queued_spin_unlock queued_spin_unlock
+-
+-static inline void queued_spin_unlock(struct qspinlock *lock)
+-{
+- compiletime_assert_atomic_type(lock->locked);
+- c_sync();
+- WRITE_ONCE(lock->locked, 0);
+-}
+-
+-#include <asm-generic/qspinlock.h>
+-
+-#endif /* _ASM_QSPINLOCK_H */
+diff --git a/arch/parisc/include/asm/assembly.h b/arch/parisc/include/asm/assembly.h
+index 5937d5edaba1e..000a28e1c5e8d 100644
+--- a/arch/parisc/include/asm/assembly.h
++++ b/arch/parisc/include/asm/assembly.h
+@@ -97,26 +97,28 @@
+ * version takes two arguments: a src and destination register.
+ * However, the source and destination registers can not be
+ * the same register.
++ *
++ * We use add,l to avoid clobbering the C/B bits in the PSW.
+ */
+
+ .macro tophys grvirt, grphys
+- ldil L%(__PAGE_OFFSET), \grphys
+- sub \grvirt, \grphys, \grphys
++ ldil L%(-__PAGE_OFFSET), \grphys
++ addl \grvirt, \grphys, \grphys
+ .endm
+-
++
+ .macro tovirt grphys, grvirt
+ ldil L%(__PAGE_OFFSET), \grvirt
+- add \grphys, \grvirt, \grvirt
++ addl \grphys, \grvirt, \grvirt
+ .endm
+
+ .macro tophys_r1 gr
+- ldil L%(__PAGE_OFFSET), %r1
+- sub \gr, %r1, \gr
++ ldil L%(-__PAGE_OFFSET), %r1
++ addl \gr, %r1, \gr
+ .endm
+-
++
+ .macro tovirt_r1 gr
+ ldil L%(__PAGE_OFFSET), %r1
+- add \gr, %r1, \gr
++ addl \gr, %r1, \gr
+ .endm
+
+ .macro delay value
+diff --git a/arch/parisc/include/asm/checksum.h b/arch/parisc/include/asm/checksum.h
+index 3c43baca7b397..2aceebcd695c8 100644
+--- a/arch/parisc/include/asm/checksum.h
++++ b/arch/parisc/include/asm/checksum.h
+@@ -40,7 +40,7 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
+ " addc %0, %5, %0\n"
+ " addc %0, %3, %0\n"
+ "1: ldws,ma 4(%1), %3\n"
+-" addib,< 0, %2, 1b\n"
++" addib,> -1, %2, 1b\n"
+ " addc %0, %3, %0\n"
+ "\n"
+ " extru %0, 31, 16, %4\n"
+@@ -126,6 +126,7 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ ** Try to keep 4 registers with "live" values ahead of the ALU.
+ */
+
++" depdi 0, 31, 32, %0\n"/* clear upper half of incoming checksum */
+ " ldd,ma 8(%1), %4\n" /* get 1st saddr word */
+ " ldd,ma 8(%2), %5\n" /* get 1st daddr word */
+ " add %4, %0, %0\n"
+@@ -137,8 +138,8 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ " add,dc %3, %0, %0\n" /* fold in proto+len | carry bit */
+ " extrd,u %0, 31, 32, %4\n"/* copy upper half down */
+ " depdi 0, 31, 32, %0\n"/* clear upper half */
+-" add %4, %0, %0\n" /* fold into 32-bits */
+-" addc 0, %0, %0\n" /* add carry */
++" add,dc %4, %0, %0\n" /* fold into 32-bits, plus carry */
++" addc 0, %0, %0\n" /* add final carry */
+
+ #else
+
+@@ -163,7 +164,8 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
+ " ldw,ma 4(%2), %7\n" /* 4th daddr */
+ " addc %6, %0, %0\n"
+ " addc %7, %0, %0\n"
+-" addc %3, %0, %0\n" /* fold in proto+len, catch carry */
++" addc %3, %0, %0\n" /* fold in proto+len */
++" addc 0, %0, %0\n" /* add carry */
+
+ #endif
+ : "=r" (sum), "=r" (saddr), "=r" (daddr), "=r" (len),
+diff --git a/arch/parisc/include/asm/mman.h b/arch/parisc/include/asm/mman.h
+new file mode 100644
+index 0000000000000..47c5a1991d103
+--- /dev/null
++++ b/arch/parisc/include/asm/mman.h
+@@ -0,0 +1,14 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef __ASM_MMAN_H__
++#define __ASM_MMAN_H__
++
++#include <uapi/asm/mman.h>
++
++/* PARISC cannot allow mdwe as it needs writable stacks */
++static inline bool arch_memory_deny_write_exec_supported(void)
++{
++ return false;
++}
++#define arch_memory_deny_write_exec_supported arch_memory_deny_write_exec_supported
++
++#endif /* __ASM_MMAN_H__ */
+diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
+index c520e551a1652..a8e75e5b884a7 100644
+--- a/arch/parisc/kernel/unaligned.c
++++ b/arch/parisc/kernel/unaligned.c
+@@ -169,6 +169,7 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
+ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
+ {
+ unsigned long saddr = regs->ior;
++ unsigned long shift, temp1;
+ __u64 val = 0;
+ ASM_EXCEPTIONTABLE_VAR(ret);
+
+@@ -180,25 +181,22 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
+
+ #ifdef CONFIG_64BIT
+ __asm__ __volatile__ (
+-" depd,z %3,60,3,%%r19\n" /* r19=(ofs&7)*8 */
+-" mtsp %4, %%sr1\n"
+-" depd %%r0,63,3,%3\n"
+-"1: ldd 0(%%sr1,%3),%0\n"
+-"2: ldd 8(%%sr1,%3),%%r20\n"
+-" subi 64,%%r19,%%r19\n"
+-" mtsar %%r19\n"
+-" shrpd %0,%%r20,%%sar,%0\n"
++" depd,z %2,60,3,%3\n" /* shift=(ofs&7)*8 */
++" mtsp %5, %%sr1\n"
++" depd %%r0,63,3,%2\n"
++"1: ldd 0(%%sr1,%2),%0\n"
++"2: ldd 8(%%sr1,%2),%4\n"
++" subi 64,%3,%3\n"
++" mtsar %3\n"
++" shrpd %0,%4,%%sar,%0\n"
+ "3: \n"
+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 3b, "%1")
+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT(2b, 3b, "%1")
+- : "=r" (val), "+r" (ret)
+- : "0" (val), "r" (saddr), "r" (regs->isr)
+- : "r19", "r20" );
++ : "+r" (val), "+r" (ret), "+r" (saddr), "=&r" (shift), "=&r" (temp1)
++ : "r" (regs->isr) );
+ #else
+- {
+- unsigned long shift, temp1;
+ __asm__ __volatile__ (
+-" zdep %2,29,2,%3\n" /* r19=(ofs&3)*8 */
++" zdep %2,29,2,%3\n" /* shift=(ofs&3)*8 */
+ " mtsp %5, %%sr1\n"
+ " dep %%r0,31,2,%2\n"
+ "1: ldw 0(%%sr1,%2),%0\n"
+@@ -214,7 +212,6 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
+ ASM_EXCEPTIONTABLE_ENTRY_EFAULT(3b, 4b, "%1")
+ : "+r" (val), "+r" (ret), "+r" (saddr), "=&r" (shift), "=&r" (temp1)
+ : "r" (regs->isr) );
+- }
+ #endif
+
+ DPRINTF("val = 0x%llx\n", val);
+diff --git a/arch/powerpc/include/asm/reg_fsl_emb.h b/arch/powerpc/include/asm/reg_fsl_emb.h
+index a21f529c43d96..8359c06d92d9f 100644
+--- a/arch/powerpc/include/asm/reg_fsl_emb.h
++++ b/arch/powerpc/include/asm/reg_fsl_emb.h
+@@ -12,9 +12,16 @@
+ #ifndef __ASSEMBLY__
+ /* Performance Monitor Registers */
+ #define mfpmr(rn) ({unsigned int rval; \
+- asm volatile("mfpmr %0," __stringify(rn) \
++ asm volatile(".machine push; " \
++ ".machine e300; " \
++ "mfpmr %0," __stringify(rn) ";" \
++ ".machine pop; " \
+ : "=r" (rval)); rval;})
+-#define mtpmr(rn, v) asm volatile("mtpmr " __stringify(rn) ",%0" : : "r" (v))
++#define mtpmr(rn, v) asm volatile(".machine push; " \
++ ".machine e300; " \
++ "mtpmr " __stringify(rn) ",%0; " \
++ ".machine pop; " \
++ : : "r" (v))
+ #endif /* __ASSEMBLY__ */
+
+ /* Freescale Book E Performance Monitor APU Registers */
+diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
+index 0b5878c3125b1..77364729a1b61 100644
+--- a/arch/powerpc/kernel/prom.c
++++ b/arch/powerpc/kernel/prom.c
+@@ -375,6 +375,18 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
+ if (IS_ENABLED(CONFIG_PPC64))
+ boot_cpu_hwid = be32_to_cpu(intserv[found_thread]);
+
++ if (nr_cpu_ids % nthreads != 0) {
++ set_nr_cpu_ids(ALIGN(nr_cpu_ids, nthreads));
++ pr_warn("nr_cpu_ids was not a multiple of threads_per_core, adjusted to %d\n",
++ nr_cpu_ids);
++ }
++
++ if (boot_cpuid >= nr_cpu_ids) {
++ set_nr_cpu_ids(min(CONFIG_NR_CPUS, ALIGN(boot_cpuid + 1, nthreads)));
++ pr_warn("Boot CPU %d >= nr_cpu_ids, adjusted nr_cpu_ids to %d\n",
++ boot_cpuid, nr_cpu_ids);
++ }
++
+ /*
+ * PAPR defines "logical" PVR values for cpus that
+ * meet various levels of the architecture:
+diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
+index 6eac63e79a899..0ab65eeb93ee3 100644
+--- a/arch/powerpc/lib/Makefile
++++ b/arch/powerpc/lib/Makefile
+@@ -76,7 +76,7 @@ obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o
+ obj-$(CONFIG_FTR_FIXUP_SELFTEST) += feature-fixups-test.o
+
+ obj-$(CONFIG_ALTIVEC) += xor_vmx.o xor_vmx_glue.o
+-CFLAGS_xor_vmx.o += -maltivec $(call cc-option,-mabi=altivec)
++CFLAGS_xor_vmx.o += -mhard-float -maltivec $(call cc-option,-mabi=altivec)
+ # Enable <altivec.h>
+ CFLAGS_xor_vmx.o += -isystem $(shell $(CC) -print-file-name=include)
+
+diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h
+index 0a7ffcfd59cda..e2eed8f97665f 100644
+--- a/arch/sparc/include/asm/parport.h
++++ b/arch/sparc/include/asm/parport.h
+@@ -1,256 +1,11 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+-/* parport.h: sparc64 specific parport initialization and dma.
+- *
+- * Copyright (C) 1999 Eddie C. Dost (ecd@skynet.be)
+- */
++#ifndef ___ASM_SPARC_PARPORT_H
++#define ___ASM_SPARC_PARPORT_H
+
+-#ifndef _ASM_SPARC64_PARPORT_H
+-#define _ASM_SPARC64_PARPORT_H 1
+-
+-#include <linux/of.h>
+-#include <linux/platform_device.h>
+-
+-#include <asm/ebus_dma.h>
+-#include <asm/ns87303.h>
+-#include <asm/prom.h>
+-
+-#define PARPORT_PC_MAX_PORTS PARPORT_MAX
+-
+-/*
+- * While sparc64 doesn't have an ISA DMA API, we provide something that looks
+- * close enough to make parport_pc happy
+- */
+-#define HAS_DMA
+-
+-#ifdef CONFIG_PARPORT_PC_FIFO
+-static DEFINE_SPINLOCK(dma_spin_lock);
+-
+-#define claim_dma_lock() \
+-({ unsigned long flags; \
+- spin_lock_irqsave(&dma_spin_lock, flags); \
+- flags; \
+-})
+-
+-#define release_dma_lock(__flags) \
+- spin_unlock_irqrestore(&dma_spin_lock, __flags);
++#if defined(__sparc__) && defined(__arch64__)
++#include <asm/parport_64.h>
++#else
++#include <asm-generic/parport.h>
++#endif
+ #endif
+
+-static struct sparc_ebus_info {
+- struct ebus_dma_info info;
+- unsigned int addr;
+- unsigned int count;
+- int lock;
+-
+- struct parport *port;
+-} sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
+-
+-static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
+-
+-static inline int request_dma(unsigned int dmanr, const char *device_id)
+-{
+- if (dmanr >= PARPORT_PC_MAX_PORTS)
+- return -EINVAL;
+- if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
+- return -EBUSY;
+- return 0;
+-}
+-
+-static inline void free_dma(unsigned int dmanr)
+-{
+- if (dmanr >= PARPORT_PC_MAX_PORTS) {
+- printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
+- return;
+- }
+- if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
+- printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
+- return;
+- }
+-}
+-
+-static inline void enable_dma(unsigned int dmanr)
+-{
+- ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
+-
+- if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info,
+- sparc_ebus_dmas[dmanr].addr,
+- sparc_ebus_dmas[dmanr].count))
+- BUG();
+-}
+-
+-static inline void disable_dma(unsigned int dmanr)
+-{
+- ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
+-}
+-
+-static inline void clear_dma_ff(unsigned int dmanr)
+-{
+- /* nothing */
+-}
+-
+-static inline void set_dma_mode(unsigned int dmanr, char mode)
+-{
+- ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
+-}
+-
+-static inline void set_dma_addr(unsigned int dmanr, unsigned int addr)
+-{
+- sparc_ebus_dmas[dmanr].addr = addr;
+-}
+-
+-static inline void set_dma_count(unsigned int dmanr, unsigned int count)
+-{
+- sparc_ebus_dmas[dmanr].count = count;
+-}
+-
+-static inline unsigned int get_dma_residue(unsigned int dmanr)
+-{
+- return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
+-}
+-
+-static int ecpp_probe(struct platform_device *op)
+-{
+- unsigned long base = op->resource[0].start;
+- unsigned long config = op->resource[1].start;
+- unsigned long d_base = op->resource[2].start;
+- unsigned long d_len;
+- struct device_node *parent;
+- struct parport *p;
+- int slot, err;
+-
+- parent = op->dev.of_node->parent;
+- if (of_node_name_eq(parent, "dma")) {
+- p = parport_pc_probe_port(base, base + 0x400,
+- op->archdata.irqs[0], PARPORT_DMA_NOFIFO,
+- op->dev.parent->parent, 0);
+- if (!p)
+- return -ENOMEM;
+- dev_set_drvdata(&op->dev, p);
+- return 0;
+- }
+-
+- for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) {
+- if (!test_and_set_bit(slot, dma_slot_map))
+- break;
+- }
+- err = -ENODEV;
+- if (slot >= PARPORT_PC_MAX_PORTS)
+- goto out_err;
+-
+- spin_lock_init(&sparc_ebus_dmas[slot].info.lock);
+-
+- d_len = (op->resource[2].end - d_base) + 1UL;
+- sparc_ebus_dmas[slot].info.regs =
+- of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA");
+-
+- if (!sparc_ebus_dmas[slot].info.regs)
+- goto out_clear_map;
+-
+- sparc_ebus_dmas[slot].info.flags = 0;
+- sparc_ebus_dmas[slot].info.callback = NULL;
+- sparc_ebus_dmas[slot].info.client_cookie = NULL;
+- sparc_ebus_dmas[slot].info.irq = 0xdeadbeef;
+- strcpy(sparc_ebus_dmas[slot].info.name, "parport");
+- if (ebus_dma_register(&sparc_ebus_dmas[slot].info))
+- goto out_unmap_regs;
+-
+- ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1);
+-
+- /* Configure IRQ to Push Pull, Level Low */
+- /* Enable ECP, set bit 2 of the CTR first */
+- outb(0x04, base + 0x02);
+- ns87303_modify(config, PCR,
+- PCR_EPP_ENABLE |
+- PCR_IRQ_ODRAIN,
+- PCR_ECP_ENABLE |
+- PCR_ECP_CLK_ENA |
+- PCR_IRQ_POLAR);
+-
+- /* CTR bit 5 controls direction of port */
+- ns87303_modify(config, PTR,
+- 0, PTR_LPT_REG_DIR);
+-
+- p = parport_pc_probe_port(base, base + 0x400,
+- op->archdata.irqs[0],
+- slot,
+- op->dev.parent,
+- 0);
+- err = -ENOMEM;
+- if (!p)
+- goto out_disable_irq;
+-
+- dev_set_drvdata(&op->dev, p);
+-
+- return 0;
+-
+-out_disable_irq:
+- ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
+- ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
+-
+-out_unmap_regs:
+- of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len);
+-
+-out_clear_map:
+- clear_bit(slot, dma_slot_map);
+-
+-out_err:
+- return err;
+-}
+-
+-static int ecpp_remove(struct platform_device *op)
+-{
+- struct parport *p = dev_get_drvdata(&op->dev);
+- int slot = p->dma;
+-
+- parport_pc_unregister_port(p);
+-
+- if (slot != PARPORT_DMA_NOFIFO) {
+- unsigned long d_base = op->resource[2].start;
+- unsigned long d_len;
+-
+- d_len = (op->resource[2].end - d_base) + 1UL;
+-
+- ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
+- ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
+- of_iounmap(&op->resource[2],
+- sparc_ebus_dmas[slot].info.regs,
+- d_len);
+- clear_bit(slot, dma_slot_map);
+- }
+-
+- return 0;
+-}
+-
+-static const struct of_device_id ecpp_match[] = {
+- {
+- .name = "ecpp",
+- },
+- {
+- .name = "parallel",
+- .compatible = "ecpp",
+- },
+- {
+- .name = "parallel",
+- .compatible = "ns87317-ecpp",
+- },
+- {
+- .name = "parallel",
+- .compatible = "pnpALI,1533,3",
+- },
+- {},
+-};
+-
+-static struct platform_driver ecpp_driver = {
+- .driver = {
+- .name = "ecpp",
+- .of_match_table = ecpp_match,
+- },
+- .probe = ecpp_probe,
+- .remove = ecpp_remove,
+-};
+-
+-static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
+-{
+- return platform_driver_register(&ecpp_driver);
+-}
+-
+-#endif /* !(_ASM_SPARC64_PARPORT_H */
+diff --git a/arch/sparc/include/asm/parport_64.h b/arch/sparc/include/asm/parport_64.h
+new file mode 100644
+index 0000000000000..0a7ffcfd59cda
+--- /dev/null
++++ b/arch/sparc/include/asm/parport_64.h
+@@ -0,0 +1,256 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/* parport.h: sparc64 specific parport initialization and dma.
++ *
++ * Copyright (C) 1999 Eddie C. Dost (ecd@skynet.be)
++ */
++
++#ifndef _ASM_SPARC64_PARPORT_H
++#define _ASM_SPARC64_PARPORT_H 1
++
++#include <linux/of.h>
++#include <linux/platform_device.h>
++
++#include <asm/ebus_dma.h>
++#include <asm/ns87303.h>
++#include <asm/prom.h>
++
++#define PARPORT_PC_MAX_PORTS PARPORT_MAX
++
++/*
++ * While sparc64 doesn't have an ISA DMA API, we provide something that looks
++ * close enough to make parport_pc happy
++ */
++#define HAS_DMA
++
++#ifdef CONFIG_PARPORT_PC_FIFO
++static DEFINE_SPINLOCK(dma_spin_lock);
++
++#define claim_dma_lock() \
++({ unsigned long flags; \
++ spin_lock_irqsave(&dma_spin_lock, flags); \
++ flags; \
++})
++
++#define release_dma_lock(__flags) \
++ spin_unlock_irqrestore(&dma_spin_lock, __flags);
++#endif
++
++static struct sparc_ebus_info {
++ struct ebus_dma_info info;
++ unsigned int addr;
++ unsigned int count;
++ int lock;
++
++ struct parport *port;
++} sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
++
++static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
++
++static inline int request_dma(unsigned int dmanr, const char *device_id)
++{
++ if (dmanr >= PARPORT_PC_MAX_PORTS)
++ return -EINVAL;
++ if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
++ return -EBUSY;
++ return 0;
++}
++
++static inline void free_dma(unsigned int dmanr)
++{
++ if (dmanr >= PARPORT_PC_MAX_PORTS) {
++ printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
++ return;
++ }
++ if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
++ printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
++ return;
++ }
++}
++
++static inline void enable_dma(unsigned int dmanr)
++{
++ ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
++
++ if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info,
++ sparc_ebus_dmas[dmanr].addr,
++ sparc_ebus_dmas[dmanr].count))
++ BUG();
++}
++
++static inline void disable_dma(unsigned int dmanr)
++{
++ ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
++}
++
++static inline void clear_dma_ff(unsigned int dmanr)
++{
++ /* nothing */
++}
++
++static inline void set_dma_mode(unsigned int dmanr, char mode)
++{
++ ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
++}
++
++static inline void set_dma_addr(unsigned int dmanr, unsigned int addr)
++{
++ sparc_ebus_dmas[dmanr].addr = addr;
++}
++
++static inline void set_dma_count(unsigned int dmanr, unsigned int count)
++{
++ sparc_ebus_dmas[dmanr].count = count;
++}
++
++static inline unsigned int get_dma_residue(unsigned int dmanr)
++{
++ return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
++}
++
++static int ecpp_probe(struct platform_device *op)
++{
++ unsigned long base = op->resource[0].start;
++ unsigned long config = op->resource[1].start;
++ unsigned long d_base = op->resource[2].start;
++ unsigned long d_len;
++ struct device_node *parent;
++ struct parport *p;
++ int slot, err;
++
++ parent = op->dev.of_node->parent;
++ if (of_node_name_eq(parent, "dma")) {
++ p = parport_pc_probe_port(base, base + 0x400,
++ op->archdata.irqs[0], PARPORT_DMA_NOFIFO,
++ op->dev.parent->parent, 0);
++ if (!p)
++ return -ENOMEM;
++ dev_set_drvdata(&op->dev, p);
++ return 0;
++ }
++
++ for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) {
++ if (!test_and_set_bit(slot, dma_slot_map))
++ break;
++ }
++ err = -ENODEV;
++ if (slot >= PARPORT_PC_MAX_PORTS)
++ goto out_err;
++
++ spin_lock_init(&sparc_ebus_dmas[slot].info.lock);
++
++ d_len = (op->resource[2].end - d_base) + 1UL;
++ sparc_ebus_dmas[slot].info.regs =
++ of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA");
++
++ if (!sparc_ebus_dmas[slot].info.regs)
++ goto out_clear_map;
++
++ sparc_ebus_dmas[slot].info.flags = 0;
++ sparc_ebus_dmas[slot].info.callback = NULL;
++ sparc_ebus_dmas[slot].info.client_cookie = NULL;
++ sparc_ebus_dmas[slot].info.irq = 0xdeadbeef;
++ strcpy(sparc_ebus_dmas[slot].info.name, "parport");
++ if (ebus_dma_register(&sparc_ebus_dmas[slot].info))
++ goto out_unmap_regs;
++
++ ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1);
++
++ /* Configure IRQ to Push Pull, Level Low */
++ /* Enable ECP, set bit 2 of the CTR first */
++ outb(0x04, base + 0x02);
++ ns87303_modify(config, PCR,
++ PCR_EPP_ENABLE |
++ PCR_IRQ_ODRAIN,
++ PCR_ECP_ENABLE |
++ PCR_ECP_CLK_ENA |
++ PCR_IRQ_POLAR);
++
++ /* CTR bit 5 controls direction of port */
++ ns87303_modify(config, PTR,
++ 0, PTR_LPT_REG_DIR);
++
++ p = parport_pc_probe_port(base, base + 0x400,
++ op->archdata.irqs[0],
++ slot,
++ op->dev.parent,
++ 0);
++ err = -ENOMEM;
++ if (!p)
++ goto out_disable_irq;
++
++ dev_set_drvdata(&op->dev, p);
++
++ return 0;
++
++out_disable_irq:
++ ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
++ ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
++
++out_unmap_regs:
++ of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len);
++
++out_clear_map:
++ clear_bit(slot, dma_slot_map);
++
++out_err:
++ return err;
++}
++
++static int ecpp_remove(struct platform_device *op)
++{
++ struct parport *p = dev_get_drvdata(&op->dev);
++ int slot = p->dma;
++
++ parport_pc_unregister_port(p);
++
++ if (slot != PARPORT_DMA_NOFIFO) {
++ unsigned long d_base = op->resource[2].start;
++ unsigned long d_len;
++
++ d_len = (op->resource[2].end - d_base) + 1UL;
++
++ ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
++ ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
++ of_iounmap(&op->resource[2],
++ sparc_ebus_dmas[slot].info.regs,
++ d_len);
++ clear_bit(slot, dma_slot_map);
++ }
++
++ return 0;
++}
++
++static const struct of_device_id ecpp_match[] = {
++ {
++ .name = "ecpp",
++ },
++ {
++ .name = "parallel",
++ .compatible = "ecpp",
++ },
++ {
++ .name = "parallel",
++ .compatible = "ns87317-ecpp",
++ },
++ {
++ .name = "parallel",
++ .compatible = "pnpALI,1533,3",
++ },
++ {},
++};
++
++static struct platform_driver ecpp_driver = {
++ .driver = {
++ .name = "ecpp",
++ .of_match_table = ecpp_match,
++ },
++ .probe = ecpp_probe,
++ .remove = ecpp_remove,
++};
++
++static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
++{
++ return platform_driver_register(&ecpp_driver);
++}
++
++#endif /* !(_ASM_SPARC64_PARPORT_H */
+diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
+index 17cdfdbf1f3b7..149adc0947530 100644
+--- a/arch/sparc/kernel/nmi.c
++++ b/arch/sparc/kernel/nmi.c
+@@ -279,7 +279,7 @@ static int __init setup_nmi_watchdog(char *str)
+ if (!strncmp(str, "panic", 5))
+ panic_on_timeout = 1;
+
+- return 0;
++ return 1;
+ }
+ __setup("nmi_watchdog=", setup_nmi_watchdog);
+
+diff --git a/arch/sparc/vdso/vma.c b/arch/sparc/vdso/vma.c
+index 136c78f28f8ba..1bbf4335de454 100644
+--- a/arch/sparc/vdso/vma.c
++++ b/arch/sparc/vdso/vma.c
+@@ -449,9 +449,8 @@ static __init int vdso_setup(char *s)
+ unsigned long val;
+
+ err = kstrtoul(s, 10, &val);
+- if (err)
+- return err;
+- vdso_enabled = val;
+- return 0;
++ if (!err)
++ vdso_enabled = val;
++ return 1;
+ }
+ __setup("vdso=", vdso_setup);
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 637e337c332e4..1847307056502 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -1539,19 +1539,6 @@ config AMD_MEM_ENCRYPT
+ This requires an AMD processor that supports Secure Memory
+ Encryption (SME).
+
+-config AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT
+- bool "Activate AMD Secure Memory Encryption (SME) by default"
+- depends on AMD_MEM_ENCRYPT
+- help
+- Say yes to have system memory encrypted by default if running on
+- an AMD processor that supports Secure Memory Encryption (SME).
+-
+- If set to Y, then the encryption of system memory can be
+- deactivated with the mem_encrypt=off command line option.
+-
+- If set to N, then the encryption of system memory can be
+- activated with the mem_encrypt=on command line option.
+-
+ # Common NUMA Features
+ config NUMA
+ bool "NUMA Memory Allocation and Scheduler Support"
+diff --git a/arch/x86/boot/compressed/efi_mixed.S b/arch/x86/boot/compressed/efi_mixed.S
+index f4e22ef774ab6..876fc6d46a131 100644
+--- a/arch/x86/boot/compressed/efi_mixed.S
++++ b/arch/x86/boot/compressed/efi_mixed.S
+@@ -15,10 +15,12 @@
+ */
+
+ #include <linux/linkage.h>
++#include <asm/asm-offsets.h>
+ #include <asm/msr.h>
+ #include <asm/page_types.h>
+ #include <asm/processor-flags.h>
+ #include <asm/segment.h>
++#include <asm/setup.h>
+
+ .code64
+ .text
+@@ -49,6 +51,11 @@ SYM_FUNC_START(startup_64_mixed_mode)
+ lea efi32_boot_args(%rip), %rdx
+ mov 0(%rdx), %edi
+ mov 4(%rdx), %esi
++
++ /* Switch to the firmware's stack */
++ movl efi32_boot_sp(%rip), %esp
++ andl $~7, %esp
++
+ #ifdef CONFIG_EFI_HANDOVER_PROTOCOL
+ mov 8(%rdx), %edx // saved bootparams pointer
+ test %edx, %edx
+@@ -144,6 +151,7 @@ SYM_FUNC_END(__efi64_thunk)
+ SYM_FUNC_START(efi32_stub_entry)
+ call 1f
+ 1: popl %ecx
++ leal (efi32_boot_args - 1b)(%ecx), %ebx
+
+ /* Clear BSS */
+ xorl %eax, %eax
+@@ -158,6 +166,7 @@ SYM_FUNC_START(efi32_stub_entry)
+ popl %ecx
+ popl %edx
+ popl %esi
++ movl %esi, 8(%ebx)
+ jmp efi32_entry
+ SYM_FUNC_END(efi32_stub_entry)
+ #endif
+@@ -234,8 +243,6 @@ SYM_FUNC_END(efi_enter32)
+ *
+ * Arguments: %ecx image handle
+ * %edx EFI system table pointer
+- * %esi struct bootparams pointer (or NULL when not using
+- * the EFI handover protocol)
+ *
+ * Since this is the point of no return for ordinary execution, no registers
+ * are considered live except for the function parameters. [Note that the EFI
+@@ -254,13 +261,25 @@ SYM_FUNC_START_LOCAL(efi32_entry)
+ /* Store firmware IDT descriptor */
+ sidtl (efi32_boot_idt - 1b)(%ebx)
+
++ /* Store firmware stack pointer */
++ movl %esp, (efi32_boot_sp - 1b)(%ebx)
++
+ /* Store boot arguments */
+ leal (efi32_boot_args - 1b)(%ebx), %ebx
+ movl %ecx, 0(%ebx)
+ movl %edx, 4(%ebx)
+- movl %esi, 8(%ebx)
+ movb $0x0, 12(%ebx) // efi_is64
+
++ /*
++ * Allocate some memory for a temporary struct boot_params, which only
++ * needs the minimal pieces that startup_32() relies on.
++ */
++ subl $PARAM_SIZE, %esp
++ movl %esp, %esi
++ movl $PAGE_SIZE, BP_kernel_alignment(%esi)
++ movl $_end - 1b, BP_init_size(%esi)
++ subl $startup_32 - 1b, BP_init_size(%esi)
++
+ /* Disable paging */
+ movl %cr0, %eax
+ btrl $X86_CR0_PG_BIT, %eax
+@@ -286,8 +305,7 @@ SYM_FUNC_START(efi32_pe_entry)
+
+ movl 8(%ebp), %ecx // image_handle
+ movl 12(%ebp), %edx // sys_table
+- xorl %esi, %esi
+- jmp efi32_entry // pass %ecx, %edx, %esi
++ jmp efi32_entry // pass %ecx, %edx
+ // no other registers remain live
+
+ 2: popl %edi // restore callee-save registers
+@@ -318,5 +336,6 @@ SYM_DATA_END(efi32_boot_idt)
+
+ SYM_DATA_LOCAL(efi32_boot_cs, .word 0)
+ SYM_DATA_LOCAL(efi32_boot_ds, .word 0)
++SYM_DATA_LOCAL(efi32_boot_sp, .long 0)
+ SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
+ SYM_DATA(efi_is64, .byte 1)
+diff --git a/arch/x86/coco/core.c b/arch/x86/coco/core.c
+index eeec9986570ed..d07be9d05cd03 100644
+--- a/arch/x86/coco/core.c
++++ b/arch/x86/coco/core.c
+@@ -14,7 +14,7 @@
+ #include <asm/processor.h>
+
+ enum cc_vendor cc_vendor __ro_after_init = CC_VENDOR_NONE;
+-static u64 cc_mask __ro_after_init;
++u64 cc_mask __ro_after_init;
+
+ static bool noinstr intel_cc_platform_has(enum cc_attr attr)
+ {
+@@ -148,8 +148,3 @@ u64 cc_mkdec(u64 val)
+ }
+ }
+ EXPORT_SYMBOL_GPL(cc_mkdec);
+-
+-__init void cc_set_mask(u64 mask)
+-{
+- cc_mask = mask;
+-}
+diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
+index 1f114d4bfe303..eb5c8539d657a 100644
+--- a/arch/x86/events/amd/core.c
++++ b/arch/x86/events/amd/core.c
+@@ -250,7 +250,7 @@ static const u64 amd_perfmon_event_map[PERF_COUNT_HW_MAX] =
+ /*
+ * AMD Performance Monitor Family 17h and later:
+ */
+-static const u64 amd_f17h_perfmon_event_map[PERF_COUNT_HW_MAX] =
++static const u64 amd_zen1_perfmon_event_map[PERF_COUNT_HW_MAX] =
+ {
+ [PERF_COUNT_HW_CPU_CYCLES] = 0x0076,
+ [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0,
+@@ -262,10 +262,24 @@ static const u64 amd_f17h_perfmon_event_map[PERF_COUNT_HW_MAX] =
+ [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x0187,
+ };
+
++static const u64 amd_zen2_perfmon_event_map[PERF_COUNT_HW_MAX] =
++{
++ [PERF_COUNT_HW_CPU_CYCLES] = 0x0076,
++ [PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0,
++ [PERF_COUNT_HW_CACHE_REFERENCES] = 0xff60,
++ [PERF_COUNT_HW_CACHE_MISSES] = 0x0964,
++ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x00c2,
++ [PERF_COUNT_HW_BRANCH_MISSES] = 0x00c3,
++ [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a9,
++};
++
+ static u64 amd_pmu_event_map(int hw_event)
+ {
+- if (boot_cpu_data.x86 >= 0x17)
+- return amd_f17h_perfmon_event_map[hw_event];
++ if (cpu_feature_enabled(X86_FEATURE_ZEN2) || boot_cpu_data.x86 >= 0x19)
++ return amd_zen2_perfmon_event_map[hw_event];
++
++ if (cpu_feature_enabled(X86_FEATURE_ZEN1))
++ return amd_zen1_perfmon_event_map[hw_event];
+
+ return amd_perfmon_event_map[hw_event];
+ }
+diff --git a/arch/x86/include/asm/asm-prototypes.h b/arch/x86/include/asm/asm-prototypes.h
+index b1a98fa38828e..0e82074517f6b 100644
+--- a/arch/x86/include/asm/asm-prototypes.h
++++ b/arch/x86/include/asm/asm-prototypes.h
+@@ -13,6 +13,7 @@
+ #include <asm/preempt.h>
+ #include <asm/asm.h>
+ #include <asm/gsseg.h>
++#include <asm/nospec-branch.h>
+
+ #ifndef CONFIG_X86_CMPXCHG64
+ extern void cmpxchg8b_emu(void);
+diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
+index fbcfec4dc4ccd..ca8eed1d496ab 100644
+--- a/arch/x86/include/asm/asm.h
++++ b/arch/x86/include/asm/asm.h
+@@ -113,6 +113,20 @@
+
+ #endif
+
++#ifndef __ASSEMBLY__
++#ifndef __pic__
++static __always_inline __pure void *rip_rel_ptr(void *p)
++{
++ asm("leaq %c1(%%rip), %0" : "=r"(p) : "i"(p));
++
++ return p;
++}
++#define RIP_REL_REF(var) (*(typeof(&(var)))rip_rel_ptr(&(var)))
++#else
++#define RIP_REL_REF(var) (var)
++#endif
++#endif
++
+ /*
+ * Macros to generate condition code outputs from inline assembly,
+ * The output operand must be type "bool".
+diff --git a/arch/x86/include/asm/coco.h b/arch/x86/include/asm/coco.h
+index 76c310b19b11d..18bbdda053221 100644
+--- a/arch/x86/include/asm/coco.h
++++ b/arch/x86/include/asm/coco.h
+@@ -2,6 +2,7 @@
+ #ifndef _ASM_X86_COCO_H
+ #define _ASM_X86_COCO_H
+
++#include <asm/asm.h>
+ #include <asm/types.h>
+
+ enum cc_vendor {
+@@ -12,7 +13,12 @@ enum cc_vendor {
+
+ #ifdef CONFIG_ARCH_HAS_CC_PLATFORM
+ extern enum cc_vendor cc_vendor;
+-void cc_set_mask(u64 mask);
++extern u64 cc_mask;
++static inline void cc_set_mask(u64 mask)
++{
++ RIP_REL_REF(cc_mask) = mask;
++}
++
+ u64 cc_mkenc(u64 val);
+ u64 cc_mkdec(u64 val);
+ #else
+diff --git a/arch/x86/include/asm/crash_core.h b/arch/x86/include/asm/crash_core.h
+index 76af98f4e8012..041020da8d561 100644
+--- a/arch/x86/include/asm/crash_core.h
++++ b/arch/x86/include/asm/crash_core.h
+@@ -39,4 +39,6 @@ static inline unsigned long crash_low_size_default(void)
+ #endif
+ }
+
++#define HAVE_ARCH_ADD_CRASH_RES_TO_IOMEM_EARLY
++
+ #endif /* _X86_CRASH_CORE_H */
+diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
+index 359ada486fa92..b31eb9fd59544 100644
+--- a/arch/x86/include/asm/mem_encrypt.h
++++ b/arch/x86/include/asm/mem_encrypt.h
+@@ -15,7 +15,8 @@
+ #include <linux/init.h>
+ #include <linux/cc_platform.h>
+
+-#include <asm/bootparam.h>
++#include <asm/asm.h>
++struct boot_params;
+
+ #ifdef CONFIG_X86_MEM_ENCRYPT
+ void __init mem_encrypt_init(void);
+@@ -58,6 +59,11 @@ void __init mem_encrypt_free_decrypted_mem(void);
+
+ void __init sev_es_init_vc_handling(void);
+
++static inline u64 sme_get_me_mask(void)
++{
++ return RIP_REL_REF(sme_me_mask);
++}
++
+ #define __bss_decrypted __section(".bss..decrypted")
+
+ #else /* !CONFIG_AMD_MEM_ENCRYPT */
+@@ -89,6 +95,8 @@ early_set_mem_enc_dec_hypercall(unsigned long vaddr, unsigned long size, bool en
+
+ static inline void mem_encrypt_free_decrypted_mem(void) { }
+
++static inline u64 sme_get_me_mask(void) { return 0; }
++
+ #define __bss_decrypted
+
+ #endif /* CONFIG_AMD_MEM_ENCRYPT */
+@@ -106,11 +114,6 @@ void add_encrypt_protection_map(void);
+
+ extern char __start_bss_decrypted[], __end_bss_decrypted[], __start_bss_decrypted_unused[];
+
+-static inline u64 sme_get_me_mask(void)
+-{
+- return sme_me_mask;
+-}
+-
+ #endif /* __ASSEMBLY__ */
+
+ #endif /* __X86_MEM_ENCRYPT_H__ */
+diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
+index 2aa52cab1e463..93c3e28dd8e0e 100644
+--- a/arch/x86/include/asm/nospec-branch.h
++++ b/arch/x86/include/asm/nospec-branch.h
+@@ -271,11 +271,20 @@
+ .Lskip_rsb_\@:
+ .endm
+
++/*
++ * The CALL to srso_alias_untrain_ret() must be patched in directly at
++ * the spot where untraining must be done, ie., srso_alias_untrain_ret()
++ * must be the target of a CALL instruction instead of indirectly
++ * jumping to a wrapper which then calls it. Therefore, this macro is
++ * called outside of __UNTRAIN_RET below, for the time being, before the
++ * kernel can support nested alternatives with arbitrary nesting.
++ */
++.macro CALL_UNTRAIN_RET
+ #if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_SRSO)
+-#define CALL_UNTRAIN_RET "call entry_untrain_ret"
+-#else
+-#define CALL_UNTRAIN_RET ""
++ ALTERNATIVE_2 "", "call entry_untrain_ret", X86_FEATURE_UNRET, \
++ "call srso_alias_untrain_ret", X86_FEATURE_SRSO_ALIAS
+ #endif
++.endm
+
+ /*
+ * Mitigate RETBleed for AMD/Hygon Zen uarch. Requires KERNEL CR3 because the
+@@ -291,8 +300,8 @@
+ .macro __UNTRAIN_RET ibpb_feature, call_depth_insns
+ #if defined(CONFIG_RETHUNK) || defined(CONFIG_CPU_IBPB_ENTRY)
+ VALIDATE_UNRET_END
+- ALTERNATIVE_3 "", \
+- CALL_UNTRAIN_RET, X86_FEATURE_UNRET, \
++ CALL_UNTRAIN_RET
++ ALTERNATIVE_2 "", \
+ "call entry_ibpb", \ibpb_feature, \
+ __stringify(\call_depth_insns), X86_FEATURE_CALL_DEPTH
+ #endif
+@@ -351,6 +360,8 @@ extern void retbleed_return_thunk(void);
+ static inline void retbleed_return_thunk(void) {}
+ #endif
+
++extern void srso_alias_untrain_ret(void);
++
+ #ifdef CONFIG_CPU_SRSO
+ extern void srso_return_thunk(void);
+ extern void srso_alias_return_thunk(void);
+diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
+index 5b4a1ce3d3680..36f905797075e 100644
+--- a/arch/x86/include/asm/sev.h
++++ b/arch/x86/include/asm/sev.h
+@@ -203,12 +203,12 @@ void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long padd
+ unsigned long npages);
+ void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
+ unsigned long npages);
+-void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op);
+ void snp_set_memory_shared(unsigned long vaddr, unsigned long npages);
+ void snp_set_memory_private(unsigned long vaddr, unsigned long npages);
+ void snp_set_wakeup_secondary_cpu(void);
+ bool snp_init(struct boot_params *bp);
+ void __init __noreturn snp_abort(void);
++void snp_dmi_setup(void);
+ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio);
+ void snp_accept_memory(phys_addr_t start, phys_addr_t end);
+ u64 snp_get_unsupported_features(u64 status);
+@@ -227,12 +227,12 @@ static inline void __init
+ early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr, unsigned long npages) { }
+ static inline void __init
+ early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr, unsigned long npages) { }
+-static inline void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op) { }
+ static inline void snp_set_memory_shared(unsigned long vaddr, unsigned long npages) { }
+ static inline void snp_set_memory_private(unsigned long vaddr, unsigned long npages) { }
+ static inline void snp_set_wakeup_secondary_cpu(void) { }
+ static inline bool snp_init(struct boot_params *bp) { return false; }
+ static inline void snp_abort(void) { }
++static inline void snp_dmi_setup(void) { }
+ static inline int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio)
+ {
+ return -ENOTTY;
+diff --git a/arch/x86/include/asm/suspend_32.h b/arch/x86/include/asm/suspend_32.h
+index a800abb1a9925..d8416b3bf832e 100644
+--- a/arch/x86/include/asm/suspend_32.h
++++ b/arch/x86/include/asm/suspend_32.h
+@@ -12,11 +12,6 @@
+
+ /* image of the saved processor state */
+ struct saved_context {
+- /*
+- * On x86_32, all segment registers except gs are saved at kernel
+- * entry in pt_regs.
+- */
+- u16 gs;
+ unsigned long cr0, cr2, cr3, cr4;
+ u64 misc_enable;
+ struct saved_msrs saved_msrs;
+@@ -27,6 +22,11 @@ struct saved_context {
+ unsigned long tr;
+ unsigned long safety;
+ unsigned long return_address;
++ /*
++ * On x86_32, all segment registers except gs are saved at kernel
++ * entry in pt_regs.
++ */
++ u16 gs;
+ bool misc_enable_saved;
+ } __attribute__((packed));
+
+diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
+index c878616a18b85..550dcbbbb1756 100644
+--- a/arch/x86/include/asm/x86_init.h
++++ b/arch/x86/include/asm/x86_init.h
+@@ -30,12 +30,13 @@ struct x86_init_mpparse {
+ * @reserve_resources: reserve the standard resources for the
+ * platform
+ * @memory_setup: platform specific memory setup
+- *
++ * @dmi_setup: platform specific DMI setup
+ */
+ struct x86_init_resources {
+ void (*probe_roms)(void);
+ void (*reserve_resources)(void);
+ char *(*memory_setup)(void);
++ void (*dmi_setup)(void);
+ };
+
+ /**
+diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
+index f3abca334199d..dfa8d0cf5e185 100644
+--- a/arch/x86/kernel/cpu/amd.c
++++ b/arch/x86/kernel/cpu/amd.c
+@@ -989,11 +989,11 @@ static bool cpu_has_zenbleed_microcode(void)
+ u32 good_rev = 0;
+
+ switch (boot_cpu_data.x86_model) {
+- case 0x30 ... 0x3f: good_rev = 0x0830107a; break;
+- case 0x60 ... 0x67: good_rev = 0x0860010b; break;
+- case 0x68 ... 0x6f: good_rev = 0x08608105; break;
+- case 0x70 ... 0x7f: good_rev = 0x08701032; break;
+- case 0xa0 ... 0xaf: good_rev = 0x08a00008; break;
++ case 0x30 ... 0x3f: good_rev = 0x0830107b; break;
++ case 0x60 ... 0x67: good_rev = 0x0860010c; break;
++ case 0x68 ... 0x6f: good_rev = 0x08608107; break;
++ case 0x70 ... 0x7f: good_rev = 0x08701033; break;
++ case 0xa0 ... 0xaf: good_rev = 0x08a00009; break;
+
+ default:
+ return false;
+diff --git a/arch/x86/kernel/eisa.c b/arch/x86/kernel/eisa.c
+index e963344b04490..53935b4d62e30 100644
+--- a/arch/x86/kernel/eisa.c
++++ b/arch/x86/kernel/eisa.c
+@@ -2,6 +2,7 @@
+ /*
+ * EISA specific code
+ */
++#include <linux/cc_platform.h>
+ #include <linux/ioport.h>
+ #include <linux/eisa.h>
+ #include <linux/io.h>
+@@ -12,7 +13,7 @@ static __init int eisa_bus_probe(void)
+ {
+ void __iomem *p;
+
+- if (xen_pv_domain() && !xen_initial_domain())
++ if ((xen_pv_domain() && !xen_initial_domain()) || cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+ return 0;
+
+ p = ioremap(0x0FFFD9, 4);
+diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
+index 117e74c44e756..33a214b1a4cec 100644
+--- a/arch/x86/kernel/fpu/xstate.c
++++ b/arch/x86/kernel/fpu/xstate.c
+@@ -178,10 +178,11 @@ void fpu__init_cpu_xstate(void)
+ * Must happen after CR4 setup and before xsetbv() to allow KVM
+ * lazy passthrough. Write independent of the dynamic state static
+ * key as that does not work on the boot CPU. This also ensures
+- * that any stale state is wiped out from XFD.
++ * that any stale state is wiped out from XFD. Reset the per CPU
++ * xfd cache too.
+ */
+ if (cpu_feature_enabled(X86_FEATURE_XFD))
+- wrmsrl(MSR_IA32_XFD, init_fpstate.xfd);
++ xfd_set_state(init_fpstate.xfd);
+
+ /*
+ * XCR_XFEATURE_ENABLED_MASK (aka. XCR0) sets user features
+diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h
+index 3518fb26d06b0..19ca623ffa2ac 100644
+--- a/arch/x86/kernel/fpu/xstate.h
++++ b/arch/x86/kernel/fpu/xstate.h
+@@ -148,20 +148,26 @@ static inline void xfd_validate_state(struct fpstate *fpstate, u64 mask, bool rs
+ #endif
+
+ #ifdef CONFIG_X86_64
++static inline void xfd_set_state(u64 xfd)
++{
++ wrmsrl(MSR_IA32_XFD, xfd);
++ __this_cpu_write(xfd_state, xfd);
++}
++
+ static inline void xfd_update_state(struct fpstate *fpstate)
+ {
+ if (fpu_state_size_dynamic()) {
+ u64 xfd = fpstate->xfd;
+
+- if (__this_cpu_read(xfd_state) != xfd) {
+- wrmsrl(MSR_IA32_XFD, xfd);
+- __this_cpu_write(xfd_state, xfd);
+- }
++ if (__this_cpu_read(xfd_state) != xfd)
++ xfd_set_state(xfd);
+ }
+ }
+
+ extern int __xfd_enable_feature(u64 which, struct fpu_guest *guest_fpu);
+ #else
++static inline void xfd_set_state(u64 xfd) { }
++
+ static inline void xfd_update_state(struct fpstate *fpstate) { }
+
+ static inline int __xfd_enable_feature(u64 which, struct fpu_guest *guest_fpu) {
+diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
+index a0ce46c0a2d88..a6a3475e1d609 100644
+--- a/arch/x86/kernel/kprobes/core.c
++++ b/arch/x86/kernel/kprobes/core.c
+@@ -335,7 +335,16 @@ static int can_probe(unsigned long paddr)
+ kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset,
+ bool *on_func_entry)
+ {
+- if (is_endbr(*(u32 *)addr)) {
++ u32 insn;
++
++ /*
++ * Since 'addr' is not guaranteed to be safe to access, use
++ * copy_from_kernel_nofault() to read the instruction:
++ */
++ if (copy_from_kernel_nofault(&insn, (void *)addr, sizeof(u32)))
++ return NULL;
++
++ if (is_endbr(insn)) {
+ *on_func_entry = !offset || offset == 4;
+ if (*on_func_entry)
+ offset = 4;
+diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
+index b223922248e9f..15c700d358700 100644
+--- a/arch/x86/kernel/mpparse.c
++++ b/arch/x86/kernel/mpparse.c
+@@ -196,12 +196,12 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
+ if (!smp_check_mpc(mpc, oem, str))
+ return 0;
+
+- /* Initialize the lapic mapping */
+- if (!acpi_lapic)
+- register_lapic_address(mpc->lapic);
+-
+- if (early)
++ if (early) {
++ /* Initialize the lapic mapping */
++ if (!acpi_lapic)
++ register_lapic_address(mpc->lapic);
+ return 1;
++ }
+
+ /* Now process the configuration blocks. */
+ while (count < mpc->length) {
+diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
+index 3082cf24b69e3..6da2cfa23c293 100644
+--- a/arch/x86/kernel/nmi.c
++++ b/arch/x86/kernel/nmi.c
+@@ -636,7 +636,7 @@ void nmi_backtrace_stall_check(const struct cpumask *btp)
+ msgp = nmi_check_stall_msg[idx];
+ if (nsp->idt_ignored_snap != READ_ONCE(nsp->idt_ignored) && (idx & 0x1))
+ modp = ", but OK because ignore_nmis was set";
+- if (nmi_seq & ~0x1)
++ if (nmi_seq & 0x1)
+ msghp = " (CPU currently in NMI handler function)";
+ else if (nsp->idt_nmi_seq_snap + 1 == nmi_seq)
+ msghp = " (CPU exited one NMI handler function)";
+diff --git a/arch/x86/kernel/probe_roms.c b/arch/x86/kernel/probe_roms.c
+index 319fef37d9dce..cc2c34ba7228a 100644
+--- a/arch/x86/kernel/probe_roms.c
++++ b/arch/x86/kernel/probe_roms.c
+@@ -203,16 +203,6 @@ void __init probe_roms(void)
+ unsigned char c;
+ int i;
+
+- /*
+- * The ROM memory range is not part of the e820 table and is therefore not
+- * pre-validated by BIOS. The kernel page table maps the ROM region as encrypted
+- * memory, and SNP requires encrypted memory to be validated before access.
+- * Do that here.
+- */
+- snp_prep_memory(video_rom_resource.start,
+- ((system_rom_resource.end + 1) - video_rom_resource.start),
+- SNP_PAGE_STATE_PRIVATE);
+-
+ /* video rom */
+ upper = adapter_rom_resources[0].start;
+ for (start = video_rom_resource.start; start < upper; start += 2048) {
+diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
+index 84201071dfacd..97dd702857413 100644
+--- a/arch/x86/kernel/setup.c
++++ b/arch/x86/kernel/setup.c
+@@ -9,7 +9,6 @@
+ #include <linux/console.h>
+ #include <linux/crash_dump.h>
+ #include <linux/dma-map-ops.h>
+-#include <linux/dmi.h>
+ #include <linux/efi.h>
+ #include <linux/ima.h>
+ #include <linux/init_ohci1394_dma.h>
+@@ -902,7 +901,7 @@ void __init setup_arch(char **cmdline_p)
+ efi_init();
+
+ reserve_ibft_region();
+- dmi_setup();
++ x86_init.resources.dmi_setup();
+
+ /*
+ * VMware detection requires dmi to be available, so this
+diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
+index 1d24ec6799157..0b04e3bfd72ae 100644
+--- a/arch/x86/kernel/sev-shared.c
++++ b/arch/x86/kernel/sev-shared.c
+@@ -556,9 +556,9 @@ static int snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_le
+ leaf->eax = leaf->ebx = leaf->ecx = leaf->edx = 0;
+
+ /* Skip post-processing for out-of-range zero leafs. */
+- if (!(leaf->fn <= cpuid_std_range_max ||
+- (leaf->fn >= 0x40000000 && leaf->fn <= cpuid_hyp_range_max) ||
+- (leaf->fn >= 0x80000000 && leaf->fn <= cpuid_ext_range_max)))
++ if (!(leaf->fn <= RIP_REL_REF(cpuid_std_range_max) ||
++ (leaf->fn >= 0x40000000 && leaf->fn <= RIP_REL_REF(cpuid_hyp_range_max)) ||
++ (leaf->fn >= 0x80000000 && leaf->fn <= RIP_REL_REF(cpuid_ext_range_max))))
+ return 0;
+ }
+
+@@ -1063,11 +1063,11 @@ static void __init setup_cpuid_table(const struct cc_blob_sev_info *cc_info)
+ const struct snp_cpuid_fn *fn = &cpuid_table->fn[i];
+
+ if (fn->eax_in == 0x0)
+- cpuid_std_range_max = fn->eax;
++ RIP_REL_REF(cpuid_std_range_max) = fn->eax;
+ else if (fn->eax_in == 0x40000000)
+- cpuid_hyp_range_max = fn->eax;
++ RIP_REL_REF(cpuid_hyp_range_max) = fn->eax;
+ else if (fn->eax_in == 0x80000000)
+- cpuid_ext_range_max = fn->eax;
++ RIP_REL_REF(cpuid_ext_range_max) = fn->eax;
+ }
+ }
+
+diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
+index c67285824e826..0f58242b54b86 100644
+--- a/arch/x86/kernel/sev.c
++++ b/arch/x86/kernel/sev.c
+@@ -23,6 +23,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ #include <linux/psp-sev.h>
++#include <linux/dmi.h>
+ #include <uapi/linux/sev-guest.h>
+
+ #include <asm/cpu_entry_area.h>
+@@ -748,7 +749,7 @@ void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long padd
+ * This eliminates worries about jump tables or checking boot_cpu_data
+ * in the cc_platform_has() function.
+ */
+- if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
++ if (!(RIP_REL_REF(sev_status) & MSR_AMD64_SEV_SNP_ENABLED))
+ return;
+
+ /*
+@@ -767,28 +768,13 @@ void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr
+ * This eliminates worries about jump tables or checking boot_cpu_data
+ * in the cc_platform_has() function.
+ */
+- if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
++ if (!(RIP_REL_REF(sev_status) & MSR_AMD64_SEV_SNP_ENABLED))
+ return;
+
+ /* Ask hypervisor to mark the memory pages shared in the RMP table. */
+ early_set_pages_state(vaddr, paddr, npages, SNP_PAGE_STATE_SHARED);
+ }
+
+-void __init snp_prep_memory(unsigned long paddr, unsigned int sz, enum psc_op op)
+-{
+- unsigned long vaddr, npages;
+-
+- vaddr = (unsigned long)__va(paddr);
+- npages = PAGE_ALIGN(sz) >> PAGE_SHIFT;
+-
+- if (op == SNP_PAGE_STATE_PRIVATE)
+- early_snp_set_memory_private(vaddr, paddr, npages);
+- else if (op == SNP_PAGE_STATE_SHARED)
+- early_snp_set_memory_shared(vaddr, paddr, npages);
+- else
+- WARN(1, "invalid memory op %d\n", op);
+-}
+-
+ static unsigned long __set_pages_state(struct snp_psc_desc *data, unsigned long vaddr,
+ unsigned long vaddr_end, int op)
+ {
+@@ -2112,6 +2098,17 @@ void __init __noreturn snp_abort(void)
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
+ }
+
++/*
++ * SEV-SNP guests should only execute dmi_setup() if EFI_CONFIG_TABLES are
++ * enabled, as the alternative (fallback) logic for DMI probing in the legacy
++ * ROM region can cause a crash since this region is not pre-validated.
++ */
++void __init snp_dmi_setup(void)
++{
++ if (efi_enabled(EFI_CONFIG_TABLES))
++ dmi_setup();
++}
++
+ static void dump_cpuid_table(void)
+ {
+ const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
+diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
+index a37ebd3b47736..3f0718b4a7d28 100644
+--- a/arch/x86/kernel/x86_init.c
++++ b/arch/x86/kernel/x86_init.c
+@@ -3,6 +3,7 @@
+ *
+ * For licencing details see kernel-base/COPYING
+ */
++#include <linux/dmi.h>
+ #include <linux/init.h>
+ #include <linux/ioport.h>
+ #include <linux/export.h>
+@@ -66,6 +67,7 @@ struct x86_init_ops x86_init __initdata = {
+ .probe_roms = probe_roms,
+ .reserve_resources = reserve_standard_io_resources,
+ .memory_setup = e820__memory_setup_default,
++ .dmi_setup = dmi_setup,
+ },
+
+ .mpparse = {
+diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
+index 3242f3da24576..75bc7d3f0022d 100644
+--- a/arch/x86/kvm/lapic.c
++++ b/arch/x86/kvm/lapic.c
+@@ -41,6 +41,7 @@
+ #include "ioapic.h"
+ #include "trace.h"
+ #include "x86.h"
++#include "xen.h"
+ #include "cpuid.h"
+ #include "hyperv.h"
+ #include "smm.h"
+@@ -499,8 +500,10 @@ static inline void apic_set_spiv(struct kvm_lapic *apic, u32 val)
+ }
+
+ /* Check if there are APF page ready requests pending */
+- if (enabled)
++ if (enabled) {
+ kvm_make_request(KVM_REQ_APF_READY, apic->vcpu);
++ kvm_xen_sw_enable_lapic(apic->vcpu);
++ }
+ }
+
+ static inline void kvm_apic_set_xapic_id(struct kvm_lapic *apic, u8 id)
+diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
+index 4b4e738c6f1b7..b0212ba2d87a6 100644
+--- a/arch/x86/kvm/xen.c
++++ b/arch/x86/kvm/xen.c
+@@ -493,7 +493,7 @@ void kvm_xen_update_runstate(struct kvm_vcpu *v, int state)
+ kvm_xen_update_runstate_guest(v, state == RUNSTATE_runnable);
+ }
+
+-static void kvm_xen_inject_vcpu_vector(struct kvm_vcpu *v)
++void kvm_xen_inject_vcpu_vector(struct kvm_vcpu *v)
+ {
+ struct kvm_lapic_irq irq = { };
+ int r;
+diff --git a/arch/x86/kvm/xen.h b/arch/x86/kvm/xen.h
+index f8f1fe22d0906..f5841d9000aeb 100644
+--- a/arch/x86/kvm/xen.h
++++ b/arch/x86/kvm/xen.h
+@@ -18,6 +18,7 @@ extern struct static_key_false_deferred kvm_xen_enabled;
+
+ int __kvm_xen_has_interrupt(struct kvm_vcpu *vcpu);
+ void kvm_xen_inject_pending_events(struct kvm_vcpu *vcpu);
++void kvm_xen_inject_vcpu_vector(struct kvm_vcpu *vcpu);
+ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data);
+ int kvm_xen_vcpu_get_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data);
+ int kvm_xen_hvm_set_attr(struct kvm *kvm, struct kvm_xen_hvm_attr *data);
+@@ -36,6 +37,19 @@ int kvm_xen_setup_evtchn(struct kvm *kvm,
+ const struct kvm_irq_routing_entry *ue);
+ void kvm_xen_update_tsc_info(struct kvm_vcpu *vcpu);
+
++static inline void kvm_xen_sw_enable_lapic(struct kvm_vcpu *vcpu)
++{
++ /*
++ * The local APIC is being enabled. If the per-vCPU upcall vector is
++ * set and the vCPU's evtchn_upcall_pending flag is set, inject the
++ * interrupt.
++ */
++ if (static_branch_unlikely(&kvm_xen_enabled.key) &&
++ vcpu->arch.xen.vcpu_info_cache.active &&
++ vcpu->arch.xen.upcall_vector && __kvm_xen_has_interrupt(vcpu))
++ kvm_xen_inject_vcpu_vector(vcpu);
++}
++
+ static inline bool kvm_xen_msr_enabled(struct kvm *kvm)
+ {
+ return static_branch_unlikely(&kvm_xen_enabled.key) &&
+@@ -101,6 +115,10 @@ static inline void kvm_xen_destroy_vcpu(struct kvm_vcpu *vcpu)
+ {
+ }
+
++static inline void kvm_xen_sw_enable_lapic(struct kvm_vcpu *vcpu)
++{
++}
++
+ static inline bool kvm_xen_msr_enabled(struct kvm *kvm)
+ {
+ return false;
+diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S
+index 7b2589877d065..1e59367b46813 100644
+--- a/arch/x86/lib/retpoline.S
++++ b/arch/x86/lib/retpoline.S
+@@ -163,6 +163,7 @@ SYM_CODE_START_NOALIGN(srso_alias_untrain_ret)
+ lfence
+ jmp srso_alias_return_thunk
+ SYM_FUNC_END(srso_alias_untrain_ret)
++__EXPORT_THUNK(srso_alias_untrain_ret)
+ .popsection
+
+ .pushsection .text..__x86.rethunk_safe
+@@ -224,10 +225,12 @@ SYM_CODE_START(srso_return_thunk)
+ SYM_CODE_END(srso_return_thunk)
+
+ #define JMP_SRSO_UNTRAIN_RET "jmp srso_untrain_ret"
+-#define JMP_SRSO_ALIAS_UNTRAIN_RET "jmp srso_alias_untrain_ret"
+ #else /* !CONFIG_CPU_SRSO */
+ #define JMP_SRSO_UNTRAIN_RET "ud2"
+-#define JMP_SRSO_ALIAS_UNTRAIN_RET "ud2"
++/* Dummy for the alternative in CALL_UNTRAIN_RET. */
++SYM_CODE_START(srso_alias_untrain_ret)
++ RET
++SYM_FUNC_END(srso_alias_untrain_ret)
+ #endif /* CONFIG_CPU_SRSO */
+
+ #ifdef CONFIG_CPU_UNRET_ENTRY
+@@ -319,9 +322,7 @@ SYM_FUNC_END(retbleed_untrain_ret)
+ #if defined(CONFIG_CPU_UNRET_ENTRY) || defined(CONFIG_CPU_SRSO)
+
+ SYM_FUNC_START(entry_untrain_ret)
+- ALTERNATIVE_2 JMP_RETBLEED_UNTRAIN_RET, \
+- JMP_SRSO_UNTRAIN_RET, X86_FEATURE_SRSO, \
+- JMP_SRSO_ALIAS_UNTRAIN_RET, X86_FEATURE_SRSO_ALIAS
++ ALTERNATIVE JMP_RETBLEED_UNTRAIN_RET, JMP_SRSO_UNTRAIN_RET, X86_FEATURE_SRSO
+ SYM_FUNC_END(entry_untrain_ret)
+ __EXPORT_THUNK(entry_untrain_ret)
+
+diff --git a/arch/x86/mm/mem_encrypt_amd.c b/arch/x86/mm/mem_encrypt_amd.c
+index 70b91de2e053a..94cd06d4b0af5 100644
+--- a/arch/x86/mm/mem_encrypt_amd.c
++++ b/arch/x86/mm/mem_encrypt_amd.c
+@@ -492,6 +492,24 @@ void __init sme_early_init(void)
+ */
+ if (sev_status & MSR_AMD64_SEV_ENABLED)
+ ia32_disable();
++
++ /*
++ * Override init functions that scan the ROM region in SEV-SNP guests,
++ * as this memory is not pre-validated and would thus cause a crash.
++ */
++ if (sev_status & MSR_AMD64_SEV_SNP_ENABLED) {
++ x86_init.mpparse.find_smp_config = x86_init_noop;
++ x86_init.pci.init_irq = x86_init_noop;
++ x86_init.resources.probe_roms = x86_init_noop;
++
++ /*
++ * DMI setup behavior for SEV-SNP guests depends on
++ * efi_enabled(EFI_CONFIG_TABLES), which hasn't been
++ * parsed yet. snp_dmi_setup() will run after that
++ * parsing has happened.
++ */
++ x86_init.resources.dmi_setup = snp_dmi_setup;
++ }
+ }
+
+ void __init mem_encrypt_free_decrypted_mem(void)
+diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c
+index 7f72472a34d6d..0166ab1780ccb 100644
+--- a/arch/x86/mm/mem_encrypt_identity.c
++++ b/arch/x86/mm/mem_encrypt_identity.c
+@@ -97,7 +97,6 @@ static char sme_workarea[2 * PMD_SIZE] __section(".init.scratch");
+
+ static char sme_cmdline_arg[] __initdata = "mem_encrypt";
+ static char sme_cmdline_on[] __initdata = "on";
+-static char sme_cmdline_off[] __initdata = "off";
+
+ static void __init sme_clear_pgd(struct sme_populate_pgd_data *ppd)
+ {
+@@ -305,7 +304,8 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
+ * instrumentation or checking boot_cpu_data in the cc_platform_has()
+ * function.
+ */
+- if (!sme_get_me_mask() || sev_status & MSR_AMD64_SEV_ENABLED)
++ if (!sme_get_me_mask() ||
++ RIP_REL_REF(sev_status) & MSR_AMD64_SEV_ENABLED)
+ return;
+
+ /*
+@@ -504,7 +504,7 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
+
+ void __init sme_enable(struct boot_params *bp)
+ {
+- const char *cmdline_ptr, *cmdline_arg, *cmdline_on, *cmdline_off;
++ const char *cmdline_ptr, *cmdline_arg, *cmdline_on;
+ unsigned int eax, ebx, ecx, edx;
+ unsigned long feature_mask;
+ unsigned long me_mask;
+@@ -542,11 +542,11 @@ void __init sme_enable(struct boot_params *bp)
+ me_mask = 1UL << (ebx & 0x3f);
+
+ /* Check the SEV MSR whether SEV or SME is enabled */
+- sev_status = __rdmsr(MSR_AMD64_SEV);
+- feature_mask = (sev_status & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT;
++ RIP_REL_REF(sev_status) = msr = __rdmsr(MSR_AMD64_SEV);
++ feature_mask = (msr & MSR_AMD64_SEV_ENABLED) ? AMD_SEV_BIT : AMD_SME_BIT;
+
+ /* The SEV-SNP CC blob should never be present unless SEV-SNP is enabled. */
+- if (snp && !(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
++ if (snp && !(msr & MSR_AMD64_SEV_SNP_ENABLED))
+ snp_abort();
+
+ /* Check if memory encryption is enabled */
+@@ -572,7 +572,6 @@ void __init sme_enable(struct boot_params *bp)
+ return;
+ } else {
+ /* SEV state cannot be controlled by a command line option */
+- sme_me_mask = me_mask;
+ goto out;
+ }
+
+@@ -587,28 +586,17 @@ void __init sme_enable(struct boot_params *bp)
+ asm ("lea sme_cmdline_on(%%rip), %0"
+ : "=r" (cmdline_on)
+ : "p" (sme_cmdline_on));
+- asm ("lea sme_cmdline_off(%%rip), %0"
+- : "=r" (cmdline_off)
+- : "p" (sme_cmdline_off));
+-
+- if (IS_ENABLED(CONFIG_AMD_MEM_ENCRYPT_ACTIVE_BY_DEFAULT))
+- sme_me_mask = me_mask;
+
+ cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr |
+ ((u64)bp->ext_cmd_line_ptr << 32));
+
+- if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0)
+- goto out;
+-
+- if (!strncmp(buffer, cmdline_on, sizeof(buffer)))
+- sme_me_mask = me_mask;
+- else if (!strncmp(buffer, cmdline_off, sizeof(buffer)))
+- sme_me_mask = 0;
++ if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0 ||
++ strncmp(buffer, cmdline_on, sizeof(buffer)))
++ return;
+
+ out:
+- if (sme_me_mask) {
+- physical_mask &= ~sme_me_mask;
+- cc_vendor = CC_VENDOR_AMD;
+- cc_set_mask(sme_me_mask);
+- }
++ RIP_REL_REF(sme_me_mask) = me_mask;
++ physical_mask &= ~me_mask;
++ cc_vendor = CC_VENDOR_AMD;
++ cc_set_mask(me_mask);
+ }
+diff --git a/block/bio.c b/block/bio.c
+index b9642a41f286e..b52b56067e792 100644
+--- a/block/bio.c
++++ b/block/bio.c
+@@ -1152,7 +1152,7 @@ void __bio_release_pages(struct bio *bio, bool mark_dirty)
+
+ bio_for_each_folio_all(fi, bio) {
+ struct page *page;
+- size_t done = 0;
++ size_t nr_pages;
+
+ if (mark_dirty) {
+ folio_lock(fi.folio);
+@@ -1160,10 +1160,11 @@ void __bio_release_pages(struct bio *bio, bool mark_dirty)
+ folio_unlock(fi.folio);
+ }
+ page = folio_page(fi.folio, fi.offset / PAGE_SIZE);
++ nr_pages = (fi.offset + fi.length - 1) / PAGE_SIZE -
++ fi.offset / PAGE_SIZE + 1;
+ do {
+ bio_release_page(bio, page++);
+- done += PAGE_SIZE;
+- } while (done < fi.length);
++ } while (--nr_pages != 0);
+ }
+ }
+ EXPORT_SYMBOL_GPL(__bio_release_pages);
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index 2dc01551e27c7..25d2f3239eb65 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -771,16 +771,11 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
+ /*
+ * Partial zone append completions cannot be supported as the
+ * BIO fragments may end up not being written sequentially.
+- * For such case, force the completed nbytes to be equal to
+- * the BIO size so that bio_advance() sets the BIO remaining
+- * size to 0 and we end up calling bio_endio() before returning.
+ */
+- if (bio->bi_iter.bi_size != nbytes) {
++ if (bio->bi_iter.bi_size != nbytes)
+ bio->bi_status = BLK_STS_IOERR;
+- nbytes = bio->bi_iter.bi_size;
+- } else {
++ else
+ bio->bi_iter.bi_sector = rq->__sector;
+- }
+ }
+
+ bio_advance(bio, nbytes);
+diff --git a/block/blk-settings.c b/block/blk-settings.c
+index 06ea91e51b8b2..5adadce084086 100644
+--- a/block/blk-settings.c
++++ b/block/blk-settings.c
+@@ -689,6 +689,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
+ t->zone_write_granularity = max(t->zone_write_granularity,
+ b->zone_write_granularity);
+ t->zoned = max(t->zoned, b->zoned);
++ if (!t->zoned) {
++ t->zone_write_granularity = 0;
++ t->max_zone_append_sectors = 0;
++ }
+ return ret;
+ }
+ EXPORT_SYMBOL(blk_stack_limits);
+diff --git a/block/mq-deadline.c b/block/mq-deadline.c
+index f958e79277b8b..02a916ba62ee7 100644
+--- a/block/mq-deadline.c
++++ b/block/mq-deadline.c
+@@ -646,9 +646,8 @@ static void dd_depth_updated(struct blk_mq_hw_ctx *hctx)
+ struct request_queue *q = hctx->queue;
+ struct deadline_data *dd = q->elevator->elevator_data;
+ struct blk_mq_tags *tags = hctx->sched_tags;
+- unsigned int shift = tags->bitmap_tags.sb.shift;
+
+- dd->async_depth = max(1U, 3 * (1U << shift) / 4);
++ dd->async_depth = max(1UL, 3 * q->nr_requests / 4);
+
+ sbitmap_queue_min_shallow_depth(&tags->bitmap_tags, dd->async_depth);
+ }
+diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c
+index 05402ef8964ed..8aecbe4637f36 100644
+--- a/crypto/asymmetric_keys/mscode_parser.c
++++ b/crypto/asymmetric_keys/mscode_parser.c
+@@ -75,6 +75,9 @@ int mscode_note_digest_algo(void *context, size_t hdrlen,
+
+ oid = look_up_OID(value, vlen);
+ switch (oid) {
++ case OID_sha1:
++ ctx->digest_algo = "sha1";
++ break;
+ case OID_sha256:
+ ctx->digest_algo = "sha256";
+ break;
+diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c
+index 5b08c50722d0f..231ad7b3789d5 100644
+--- a/crypto/asymmetric_keys/pkcs7_parser.c
++++ b/crypto/asymmetric_keys/pkcs7_parser.c
+@@ -227,6 +227,9 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
+ struct pkcs7_parse_context *ctx = context;
+
+ switch (ctx->last_oid) {
++ case OID_sha1:
++ ctx->sinfo->sig->hash_algo = "sha1";
++ break;
+ case OID_sha256:
+ ctx->sinfo->sig->hash_algo = "sha256";
+ break;
+@@ -278,6 +281,7 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
+ ctx->sinfo->sig->pkey_algo = "rsa";
+ ctx->sinfo->sig->encoding = "pkcs1";
+ break;
++ case OID_id_ecdsa_with_sha1:
+ case OID_id_ecdsa_with_sha224:
+ case OID_id_ecdsa_with_sha256:
+ case OID_id_ecdsa_with_sha384:
+diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
+index e5f22691febd5..e314fd57e6f88 100644
+--- a/crypto/asymmetric_keys/public_key.c
++++ b/crypto/asymmetric_keys/public_key.c
+@@ -115,7 +115,8 @@ software_key_determine_akcipher(const struct public_key *pkey,
+ */
+ if (!hash_algo)
+ return -EINVAL;
+- if (strcmp(hash_algo, "sha224") != 0 &&
++ if (strcmp(hash_algo, "sha1") != 0 &&
++ strcmp(hash_algo, "sha224") != 0 &&
+ strcmp(hash_algo, "sha256") != 0 &&
+ strcmp(hash_algo, "sha384") != 0 &&
+ strcmp(hash_algo, "sha512") != 0 &&
+diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c
+index 398983be77e8b..2deff81f8af50 100644
+--- a/crypto/asymmetric_keys/signature.c
++++ b/crypto/asymmetric_keys/signature.c
+@@ -115,7 +115,7 @@ EXPORT_SYMBOL_GPL(decrypt_blob);
+ * Sign the specified data blob using the private key specified by params->key.
+ * The signature is wrapped in an encoding if params->encoding is specified
+ * (eg. "pkcs1"). If the encoding needs to know the digest type, this can be
+- * passed through params->hash_algo (eg. "sha512").
++ * passed through params->hash_algo (eg. "sha1").
+ *
+ * Returns the length of the data placed in the signature buffer or an error.
+ */
+diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
+index 487204d394266..bb0bffa271b53 100644
+--- a/crypto/asymmetric_keys/x509_cert_parser.c
++++ b/crypto/asymmetric_keys/x509_cert_parser.c
+@@ -198,6 +198,10 @@ int x509_note_sig_algo(void *context, size_t hdrlen, unsigned char tag,
+ default:
+ return -ENOPKG; /* Unsupported combination */
+
++ case OID_sha1WithRSAEncryption:
++ ctx->cert->sig->hash_algo = "sha1";
++ goto rsa_pkcs1;
++
+ case OID_sha256WithRSAEncryption:
+ ctx->cert->sig->hash_algo = "sha256";
+ goto rsa_pkcs1;
+@@ -214,6 +218,10 @@ int x509_note_sig_algo(void *context, size_t hdrlen, unsigned char tag,
+ ctx->cert->sig->hash_algo = "sha224";
+ goto rsa_pkcs1;
+
++ case OID_id_ecdsa_with_sha1:
++ ctx->cert->sig->hash_algo = "sha1";
++ goto ecdsa;
++
+ case OID_id_rsassa_pkcs1_v1_5_with_sha3_256:
+ ctx->cert->sig->hash_algo = "sha3-256";
+ goto rsa_pkcs1;
+diff --git a/crypto/testmgr.h b/crypto/testmgr.h
+index 986f331a5fc24..12e1c892f3666 100644
+--- a/crypto/testmgr.h
++++ b/crypto/testmgr.h
+@@ -653,6 +653,30 @@ static const struct akcipher_testvec rsa_tv_template[] = {
+ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
+ {
+ .key =
++ "\x04\xf7\x46\xf8\x2f\x15\xf6\x22\x8e\xd7\x57\x4f\xcc\xe7\xbb\xc1"
++ "\xd4\x09\x73\xcf\xea\xd0\x15\x07\x3d\xa5\x8a\x8a\x95\x43\xe4\x68"
++ "\xea\xc6\x25\xc1\xc1\x01\x25\x4c\x7e\xc3\x3c\xa6\x04\x0a\xe7\x08"
++ "\x98",
++ .key_len = 49,
++ .params =
++ "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
++ "\xce\x3d\x03\x01\x01",
++ .param_len = 21,
++ .m =
++ "\xcd\xb9\xd2\x1c\xb7\x6f\xcd\x44\xb3\xfd\x63\xea\xa3\x66\x7f\xae"
++ "\x63\x85\xe7\x82",
++ .m_size = 20,
++ .algo = OID_id_ecdsa_with_sha1,
++ .c =
++ "\x30\x35\x02\x19\x00\xba\xe5\x93\x83\x6e\xb6\x3b\x63\xa0\x27\x91"
++ "\xc6\xf6\x7f\xc3\x09\xad\x59\xad\x88\x27\xd6\x92\x6b\x02\x18\x10"
++ "\x68\x01\x9d\xba\xce\x83\x08\xef\x95\x52\x7b\xa0\x0f\xe4\x18\x86"
++ "\x80\x6f\xa5\x79\x77\xda\xd0",
++ .c_size = 55,
++ .public_key_vec = true,
++ .siggen_sigver_test = true,
++ }, {
++ .key =
+ "\x04\xb6\x4b\xb1\xd1\xac\xba\x24\x8f\x65\xb2\x60\x00\x90\xbf\xbd"
+ "\x78\x05\x73\xe9\x79\x1d\x6f\x7c\x0b\xd2\xc3\x93\xa7\x28\xe1\x75"
+ "\xf7\xd5\x95\x1d\x28\x10\xc0\x75\x50\x5c\x1a\x4f\x3f\x8f\xa5\xee"
+@@ -756,6 +780,32 @@ static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = {
+ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
+ {
+ .key =
++ "\x04\xb9\x7b\xbb\xd7\x17\x64\xd2\x7e\xfc\x81\x5d\x87\x06\x83\x41"
++ "\x22\xd6\x9a\xaa\x87\x17\xec\x4f\x63\x55\x2f\x94\xba\xdd\x83\xe9"
++ "\x34\x4b\xf3\xe9\x91\x13\x50\xb6\xcb\xca\x62\x08\xe7\x3b\x09\xdc"
++ "\xc3\x63\x4b\x2d\xb9\x73\x53\xe4\x45\xe6\x7c\xad\xe7\x6b\xb0\xe8"
++ "\xaf",
++ .key_len = 65,
++ .params =
++ "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
++ "\xce\x3d\x03\x01\x07",
++ .param_len = 21,
++ .m =
++ "\xc2\x2b\x5f\x91\x78\x34\x26\x09\x42\x8d\x6f\x51\xb2\xc5\xaf\x4c"
++ "\x0b\xde\x6a\x42",
++ .m_size = 20,
++ .algo = OID_id_ecdsa_with_sha1,
++ .c =
++ "\x30\x46\x02\x21\x00\xf9\x25\xce\x9f\x3a\xa6\x35\x81\xcf\xd4\xe7"
++ "\xb7\xf0\x82\x56\x41\xf7\xd4\xad\x8d\x94\x5a\x69\x89\xee\xca\x6a"
++ "\x52\x0e\x48\x4d\xcc\x02\x21\x00\xd7\xe4\xef\x52\x66\xd3\x5b\x9d"
++ "\x8a\xfa\x54\x93\x29\xa7\x70\x86\xf1\x03\x03\xf3\x3b\xe2\x73\xf7"
++ "\xfb\x9d\x8b\xde\xd4\x8d\x6f\xad",
++ .c_size = 72,
++ .public_key_vec = true,
++ .siggen_sigver_test = true,
++ }, {
++ .key =
+ "\x04\x8b\x6d\xc0\x33\x8e\x2d\x8b\x67\xf5\xeb\xc4\x7f\xa0\xf5\xd9"
+ "\x7b\x03\xa5\x78\x9a\xb5\xea\x14\xe4\x23\xd0\xaf\xd7\x0e\x2e\xa0"
+ "\xc9\x8b\xdb\x95\xf8\xb3\xaf\xac\x00\x2c\x2c\x1f\x7a\xfd\x95\x88"
+@@ -866,6 +916,36 @@ static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = {
+
+ static const struct akcipher_testvec ecdsa_nist_p384_tv_template[] = {
+ {
++ .key = /* secp384r1(sha1) */
++ "\x04\x89\x25\xf3\x97\x88\xcb\xb0\x78\xc5\x72\x9a\x14\x6e\x7a\xb1"
++ "\x5a\xa5\x24\xf1\x95\x06\x9e\x28\xfb\xc4\xb9\xbe\x5a\x0d\xd9\x9f"
++ "\xf3\xd1\x4d\x2d\x07\x99\xbd\xda\xa7\x66\xec\xbb\xea\xba\x79\x42"
++ "\xc9\x34\x89\x6a\xe7\x0b\xc3\xf2\xfe\x32\x30\xbe\xba\xf9\xdf\x7e"
++ "\x4b\x6a\x07\x8e\x26\x66\x3f\x1d\xec\xa2\x57\x91\x51\xdd\x17\x0e"
++ "\x0b\x25\xd6\x80\x5c\x3b\xe6\x1a\x98\x48\x91\x45\x7a\x73\xb0\xc3"
++ "\xf1",
++ .key_len = 97,
++ .params =
++ "\x30\x10\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x05\x2b\x81\x04"
++ "\x00\x22",
++ .param_len = 18,
++ .m =
++ "\x12\x55\x28\xf0\x77\xd5\xb6\x21\x71\x32\x48\xcd\x28\xa8\x25\x22"
++ "\x3a\x69\xc1\x93",
++ .m_size = 20,
++ .algo = OID_id_ecdsa_with_sha1,
++ .c =
++ "\x30\x66\x02\x31\x00\xf5\x0f\x24\x4c\x07\x93\x6f\x21\x57\x55\x07"
++ "\x20\x43\x30\xde\xa0\x8d\x26\x8e\xae\x63\x3f\xbc\x20\x3a\xc6\xf1"
++ "\x32\x3c\xce\x70\x2b\x78\xf1\x4c\x26\xe6\x5b\x86\xcf\xec\x7c\x7e"
++ "\xd0\x87\xd7\xd7\x6e\x02\x31\x00\xcd\xbb\x7e\x81\x5d\x8f\x63\xc0"
++ "\x5f\x63\xb1\xbe\x5e\x4c\x0e\xa1\xdf\x28\x8c\x1b\xfa\xf9\x95\x88"
++ "\x74\xa0\x0f\xbf\xaf\xc3\x36\x76\x4a\xa1\x59\xf1\x1c\xa4\x58\x26"
++ "\x79\x12\x2a\xb7\xc5\x15\x92\xc5",
++ .c_size = 104,
++ .public_key_vec = true,
++ .siggen_sigver_test = true,
++ }, {
+ .key = /* secp384r1(sha224) */
+ "\x04\x69\x6c\xcf\x62\xee\xd0\x0d\xe5\xb5\x2f\x70\x54\xcf\x26\xa0"
+ "\xd9\x98\x8d\x92\x2a\xab\x9b\x11\xcb\x48\x18\xa1\xa9\x0d\xd5\x18"
+diff --git a/drivers/accessibility/speakup/synth.c b/drivers/accessibility/speakup/synth.c
+index eea2a2fa4f015..45f9061031338 100644
+--- a/drivers/accessibility/speakup/synth.c
++++ b/drivers/accessibility/speakup/synth.c
+@@ -208,8 +208,10 @@ void spk_do_flush(void)
+ wake_up_process(speakup_task);
+ }
+
+-void synth_write(const char *buf, size_t count)
++void synth_write(const char *_buf, size_t count)
+ {
++ const unsigned char *buf = (const unsigned char *) _buf;
++
+ while (count--)
+ synth_buffer_add(*buf++);
+ synth_start();
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index 682ff550ccfb9..df3fd6474bf21 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -671,19 +671,6 @@ MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets");
+ static void ahci_pci_save_initial_config(struct pci_dev *pdev,
+ struct ahci_host_priv *hpriv)
+ {
+- if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA) {
+- switch (pdev->device) {
+- case 0x1166:
+- dev_info(&pdev->dev, "ASM1166 has only six ports\n");
+- hpriv->saved_port_map = 0x3f;
+- break;
+- case 0x1064:
+- dev_info(&pdev->dev, "ASM1064 has only four ports\n");
+- hpriv->saved_port_map = 0xf;
+- break;
+- }
+- }
+-
+ if (pdev->vendor == PCI_VENDOR_ID_JMICRON && pdev->device == 0x2361) {
+ dev_info(&pdev->dev, "JMB361 has only one port\n");
+ hpriv->saved_port_map = 1;
+diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
+index b0d6e69c4a5b2..214b935c2ced7 100644
+--- a/drivers/ata/libata-eh.c
++++ b/drivers/ata/libata-eh.c
+@@ -712,8 +712,10 @@ void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
+ ehc->saved_ncq_enabled |= 1 << devno;
+
+ /* If we are resuming, wake up the device */
+- if (ap->pflags & ATA_PFLAG_RESUMING)
++ if (ap->pflags & ATA_PFLAG_RESUMING) {
++ dev->flags |= ATA_DFLAG_RESUMING;
+ ehc->i.dev_action[devno] |= ATA_EH_SET_ACTIVE;
++ }
+ }
+ }
+
+@@ -3169,6 +3171,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
+ return 0;
+
+ err:
++ dev->flags &= ~ATA_DFLAG_RESUMING;
+ *r_failed_dev = dev;
+ return rc;
+ }
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 0a0f483124c3a..2f4c588376410 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -4730,6 +4730,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+ struct ata_link *link;
+ struct ata_device *dev;
+ unsigned long flags;
++ bool do_resume;
+ int ret = 0;
+
+ mutex_lock(&ap->scsi_scan_mutex);
+@@ -4751,7 +4752,15 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+ if (scsi_device_get(sdev))
+ continue;
+
++ do_resume = dev->flags & ATA_DFLAG_RESUMING;
++
+ spin_unlock_irqrestore(ap->lock, flags);
++ if (do_resume) {
++ ret = scsi_resume_device(sdev);
++ if (ret == -EWOULDBLOCK)
++ goto unlock;
++ dev->flags &= ~ATA_DFLAG_RESUMING;
++ }
+ ret = scsi_rescan_device(sdev);
+ scsi_device_put(sdev);
+ spin_lock_irqsave(ap->lock, flags);
+diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
+index 42171f766dcba..5a5a9e978e85f 100644
+--- a/drivers/base/power/wakeirq.c
++++ b/drivers/base/power/wakeirq.c
+@@ -313,8 +313,10 @@ void dev_pm_enable_wake_irq_complete(struct device *dev)
+ return;
+
+ if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED &&
+- wirq->status & WAKE_IRQ_DEDICATED_REVERSE)
++ wirq->status & WAKE_IRQ_DEDICATED_REVERSE) {
+ enable_irq(wirq->irq);
++ wirq->status |= WAKE_IRQ_DEDICATED_ENABLED;
++ }
+ }
+
+ /**
+diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
+index 1d592ac413d1f..c19dc8a2987f3 100644
+--- a/drivers/bluetooth/btnxpuart.c
++++ b/drivers/bluetooth/btnxpuart.c
+@@ -1234,6 +1234,9 @@ static int btnxpuart_close(struct hci_dev *hdev)
+
+ ps_wakeup(nxpdev);
+ serdev_device_close(nxpdev->serdev);
++ skb_queue_purge(&nxpdev->txq);
++ kfree_skb(nxpdev->rx_skb);
++ nxpdev->rx_skb = NULL;
+ clear_bit(BTNXPUART_SERDEV_OPEN, &nxpdev->tx_state);
+ return 0;
+ }
+diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
+index 1b350412d8a6b..64c875657687d 100644
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -919,8 +919,6 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
+ int rc;
+ u32 int_status;
+
+- INIT_WORK(&priv->free_irq_work, tpm_tis_free_irq_func);
+-
+ rc = devm_request_threaded_irq(chip->dev.parent, irq, NULL,
+ tis_int_handler, IRQF_ONESHOT | flags,
+ dev_name(&chip->dev), chip);
+@@ -1132,6 +1130,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
+ priv->phy_ops = phy_ops;
+ priv->locality_count = 0;
+ mutex_init(&priv->locality_count_mutex);
++ INIT_WORK(&priv->free_irq_work, tpm_tis_free_irq_func);
+
+ dev_set_drvdata(&chip->dev, priv);
+
+diff --git a/drivers/clk/qcom/camcc-sc8280xp.c b/drivers/clk/qcom/camcc-sc8280xp.c
+index 3dcd79b015151..7f0ae9a5f28b2 100644
+--- a/drivers/clk/qcom/camcc-sc8280xp.c
++++ b/drivers/clk/qcom/camcc-sc8280xp.c
+@@ -630,6 +630,7 @@ static const struct freq_tbl ftbl_camcc_bps_clk_src[] = {
+ F(480000000, P_CAMCC_PLL7_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAMCC_PLL0_OUT_MAIN, 2, 0, 0),
+ F(760000000, P_CAMCC_PLL3_OUT_EVEN, 1, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_bps_clk_src = {
+@@ -654,6 +655,7 @@ static const struct freq_tbl ftbl_camcc_camnoc_axi_clk_src[] = {
+ F(320000000, P_CAMCC_PLL7_OUT_ODD, 1, 0, 0),
+ F(400000000, P_CAMCC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAMCC_PLL7_OUT_EVEN, 1, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_camnoc_axi_clk_src = {
+@@ -673,6 +675,7 @@ static struct clk_rcg2 camcc_camnoc_axi_clk_src = {
+ static const struct freq_tbl ftbl_camcc_cci_0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(37500000, P_CAMCC_PLL0_OUT_EVEN, 16, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_cci_0_clk_src = {
+@@ -735,6 +738,7 @@ static const struct freq_tbl ftbl_camcc_cphy_rx_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(240000000, P_CAMCC_PLL0_OUT_EVEN, 2.5, 0, 0),
+ F(400000000, P_CAMCC_PLL0_OUT_ODD, 1, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_cphy_rx_clk_src = {
+@@ -754,6 +758,7 @@ static struct clk_rcg2 camcc_cphy_rx_clk_src = {
+ static const struct freq_tbl ftbl_camcc_csi0phytimer_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(300000000, P_CAMCC_PLL0_OUT_EVEN, 2, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_csi0phytimer_clk_src = {
+@@ -818,6 +823,7 @@ static const struct freq_tbl ftbl_camcc_fast_ahb_clk_src[] = {
+ F(200000000, P_CAMCC_PLL0_OUT_EVEN, 3, 0, 0),
+ F(300000000, P_CAMCC_PLL0_OUT_MAIN, 4, 0, 0),
+ F(400000000, P_CAMCC_PLL0_OUT_MAIN, 3, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_fast_ahb_clk_src = {
+@@ -838,6 +844,7 @@ static const struct freq_tbl ftbl_camcc_icp_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(400000000, P_CAMCC_PLL0_OUT_ODD, 1, 0, 0),
+ F(600000000, P_CAMCC_PLL0_OUT_MAIN, 2, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_icp_clk_src = {
+@@ -860,6 +867,7 @@ static const struct freq_tbl ftbl_camcc_ife_0_clk_src[] = {
+ F(558000000, P_CAMCC_PLL3_OUT_EVEN, 1, 0, 0),
+ F(637000000, P_CAMCC_PLL3_OUT_EVEN, 1, 0, 0),
+ F(760000000, P_CAMCC_PLL3_OUT_EVEN, 1, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_ife_0_clk_src = {
+@@ -883,6 +891,7 @@ static const struct freq_tbl ftbl_camcc_ife_0_csid_clk_src[] = {
+ F(400000000, P_CAMCC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAMCC_PLL7_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAMCC_PLL0_OUT_MAIN, 2, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_ife_0_csid_clk_src = {
+@@ -905,6 +914,7 @@ static const struct freq_tbl ftbl_camcc_ife_1_clk_src[] = {
+ F(558000000, P_CAMCC_PLL4_OUT_EVEN, 1, 0, 0),
+ F(637000000, P_CAMCC_PLL4_OUT_EVEN, 1, 0, 0),
+ F(760000000, P_CAMCC_PLL4_OUT_EVEN, 1, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_ife_1_clk_src = {
+@@ -941,6 +951,7 @@ static const struct freq_tbl ftbl_camcc_ife_2_clk_src[] = {
+ F(558000000, P_CAMCC_PLL5_OUT_EVEN, 1, 0, 0),
+ F(637000000, P_CAMCC_PLL5_OUT_EVEN, 1, 0, 0),
+ F(760000000, P_CAMCC_PLL5_OUT_EVEN, 1, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_ife_2_clk_src = {
+@@ -962,6 +973,7 @@ static const struct freq_tbl ftbl_camcc_ife_2_csid_clk_src[] = {
+ F(400000000, P_CAMCC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAMCC_PLL7_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAMCC_PLL0_OUT_MAIN, 2, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_ife_2_csid_clk_src = {
+@@ -984,6 +996,7 @@ static const struct freq_tbl ftbl_camcc_ife_3_clk_src[] = {
+ F(558000000, P_CAMCC_PLL6_OUT_EVEN, 1, 0, 0),
+ F(637000000, P_CAMCC_PLL6_OUT_EVEN, 1, 0, 0),
+ F(760000000, P_CAMCC_PLL6_OUT_EVEN, 1, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_ife_3_clk_src = {
+@@ -1020,6 +1033,7 @@ static const struct freq_tbl ftbl_camcc_ife_lite_0_clk_src[] = {
+ F(400000000, P_CAMCC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAMCC_PLL7_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAMCC_PLL0_OUT_MAIN, 2, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_ife_lite_0_clk_src = {
+@@ -1140,6 +1154,7 @@ static const struct freq_tbl ftbl_camcc_ipe_0_clk_src[] = {
+ F(475000000, P_CAMCC_PLL1_OUT_EVEN, 1, 0, 0),
+ F(520000000, P_CAMCC_PLL1_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAMCC_PLL1_OUT_EVEN, 1, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_ipe_0_clk_src = {
+@@ -1163,6 +1178,7 @@ static const struct freq_tbl ftbl_camcc_jpeg_clk_src[] = {
+ F(400000000, P_CAMCC_PLL0_OUT_ODD, 1, 0, 0),
+ F(480000000, P_CAMCC_PLL7_OUT_EVEN, 1, 0, 0),
+ F(600000000, P_CAMCC_PLL0_OUT_MAIN, 2, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_jpeg_clk_src = {
+@@ -1184,6 +1200,7 @@ static const struct freq_tbl ftbl_camcc_lrme_clk_src[] = {
+ F(300000000, P_CAMCC_PLL0_OUT_EVEN, 2, 0, 0),
+ F(320000000, P_CAMCC_PLL7_OUT_ODD, 1, 0, 0),
+ F(400000000, P_CAMCC_PLL0_OUT_MAIN, 3, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_lrme_clk_src = {
+@@ -1204,6 +1221,7 @@ static const struct freq_tbl ftbl_camcc_mclk0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(24000000, P_CAMCC_PLL2_OUT_EARLY, 10, 1, 4),
+ F(64000000, P_CAMCC_PLL2_OUT_EARLY, 15, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_mclk0_clk_src = {
+@@ -1320,6 +1338,7 @@ static struct clk_rcg2 camcc_mclk7_clk_src = {
+
+ static const struct freq_tbl ftbl_camcc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_sleep_clk_src = {
+@@ -1339,6 +1358,7 @@ static struct clk_rcg2 camcc_sleep_clk_src = {
+ static const struct freq_tbl ftbl_camcc_slow_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(80000000, P_CAMCC_PLL7_OUT_EVEN, 6, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_slow_ahb_clk_src = {
+@@ -1357,6 +1377,7 @@ static struct clk_rcg2 camcc_slow_ahb_clk_src = {
+
+ static const struct freq_tbl ftbl_camcc_xo_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 camcc_xo_clk_src = {
+diff --git a/drivers/clk/qcom/gcc-ipq5018.c b/drivers/clk/qcom/gcc-ipq5018.c
+index e2bd54826a4ce..c1732d70e3a23 100644
+--- a/drivers/clk/qcom/gcc-ipq5018.c
++++ b/drivers/clk/qcom/gcc-ipq5018.c
+@@ -857,6 +857,7 @@ static struct clk_rcg2 lpass_sway_clk_src = {
+
+ static const struct freq_tbl ftbl_pcie0_aux_clk_src[] = {
+ F(2000000, P_XO, 12, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 pcie0_aux_clk_src = {
+@@ -1099,6 +1100,7 @@ static const struct freq_tbl ftbl_qpic_io_macro_clk_src[] = {
+ F(100000000, P_GPLL0, 8, 0, 0),
+ F(200000000, P_GPLL0, 4, 0, 0),
+ F(320000000, P_GPLL0, 2.5, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 qpic_io_macro_clk_src = {
+@@ -1194,6 +1196,7 @@ static struct clk_rcg2 ubi0_axi_clk_src = {
+ static const struct freq_tbl ftbl_ubi0_core_clk_src[] = {
+ F(850000000, P_UBI32_PLL, 1, 0, 0),
+ F(1000000000, P_UBI32_PLL, 1, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 ubi0_core_clk_src = {
+diff --git a/drivers/clk/qcom/gcc-ipq6018.c b/drivers/clk/qcom/gcc-ipq6018.c
+index b366912cd6480..ef1e2ce4804d2 100644
+--- a/drivers/clk/qcom/gcc-ipq6018.c
++++ b/drivers/clk/qcom/gcc-ipq6018.c
+@@ -1554,6 +1554,7 @@ static struct clk_regmap_div nss_ubi0_div_clk_src = {
+
+ static const struct freq_tbl ftbl_pcie_aux_clk_src[] = {
+ F(24000000, P_XO, 1, 0, 0),
++ { }
+ };
+
+ static const struct clk_parent_data gcc_xo_gpll0_core_pi_sleep_clk[] = {
+@@ -1734,6 +1735,7 @@ static const struct freq_tbl ftbl_sdcc_ice_core_clk_src[] = {
+ F(160000000, P_GPLL0, 5, 0, 0),
+ F(216000000, P_GPLL6, 5, 0, 0),
+ F(308570000, P_GPLL6, 3.5, 0, 0),
++ { }
+ };
+
+ static const struct clk_parent_data gcc_xo_gpll0_gpll6_gpll0_div2[] = {
+diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c
+index b7faf12a511a1..7bc679871f324 100644
+--- a/drivers/clk/qcom/gcc-ipq8074.c
++++ b/drivers/clk/qcom/gcc-ipq8074.c
+@@ -644,6 +644,7 @@ static struct clk_rcg2 pcie0_axi_clk_src = {
+
+ static const struct freq_tbl ftbl_pcie_aux_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
++ { }
+ };
+
+ static const struct clk_parent_data gcc_xo_gpll0_sleep_clk[] = {
+@@ -795,6 +796,7 @@ static const struct freq_tbl ftbl_sdcc_ice_core_clk_src[] = {
+ F(19200000, P_XO, 1, 0, 0),
+ F(160000000, P_GPLL0, 5, 0, 0),
+ F(308570000, P_GPLL6, 3.5, 0, 0),
++ { }
+ };
+
+ static const struct clk_parent_data gcc_xo_gpll0_gpll6_gpll0_div2[] = {
+diff --git a/drivers/clk/qcom/gcc-ipq9574.c b/drivers/clk/qcom/gcc-ipq9574.c
+index e8190108e1aef..0a3f846695b80 100644
+--- a/drivers/clk/qcom/gcc-ipq9574.c
++++ b/drivers/clk/qcom/gcc-ipq9574.c
+@@ -2082,6 +2082,7 @@ static struct clk_branch gcc_sdcc1_apps_clk = {
+ static const struct freq_tbl ftbl_sdcc_ice_core_clk_src[] = {
+ F(150000000, P_GPLL4, 8, 0, 0),
+ F(300000000, P_GPLL4, 4, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 sdcc1_ice_core_clk_src = {
+diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c
+index 725cd52d2398e..ea4c3bf4fb9bf 100644
+--- a/drivers/clk/qcom/gcc-sdm845.c
++++ b/drivers/clk/qcom/gcc-sdm845.c
+@@ -4037,3 +4037,4 @@ module_exit(gcc_sdm845_exit);
+ MODULE_DESCRIPTION("QTI GCC SDM845 Driver");
+ MODULE_LICENSE("GPL v2");
+ MODULE_ALIAS("platform:gcc-sdm845");
++MODULE_SOFTDEP("pre: rpmhpd");
+diff --git a/drivers/clk/qcom/mmcc-apq8084.c b/drivers/clk/qcom/mmcc-apq8084.c
+index 02fc21208dd14..c89700ab93f9c 100644
+--- a/drivers/clk/qcom/mmcc-apq8084.c
++++ b/drivers/clk/qcom/mmcc-apq8084.c
+@@ -348,6 +348,7 @@ static struct freq_tbl ftbl_mmss_axi_clk[] = {
+ F(333430000, P_MMPLL1, 3.5, 0, 0),
+ F(400000000, P_MMPLL0, 2, 0, 0),
+ F(466800000, P_MMPLL1, 2.5, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 mmss_axi_clk_src = {
+@@ -372,6 +373,7 @@ static struct freq_tbl ftbl_ocmemnoc_clk[] = {
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(228570000, P_MMPLL0, 3.5, 0, 0),
+ F(320000000, P_MMPLL0, 2.5, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 ocmemnoc_clk_src = {
+diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c
+index a31f6cf0c4e0c..36f460b78be2c 100644
+--- a/drivers/clk/qcom/mmcc-msm8974.c
++++ b/drivers/clk/qcom/mmcc-msm8974.c
+@@ -290,6 +290,7 @@ static struct freq_tbl ftbl_mmss_axi_clk[] = {
+ F(291750000, P_MMPLL1, 4, 0, 0),
+ F(400000000, P_MMPLL0, 2, 0, 0),
+ F(466800000, P_MMPLL1, 2.5, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 mmss_axi_clk_src = {
+@@ -314,6 +315,7 @@ static struct freq_tbl ftbl_ocmemnoc_clk[] = {
+ F(150000000, P_GPLL0, 4, 0, 0),
+ F(291750000, P_MMPLL1, 4, 0, 0),
+ F(400000000, P_MMPLL0, 2, 0, 0),
++ { }
+ };
+
+ static struct clk_rcg2 ocmemnoc_clk_src = {
+diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
+index 44a61dc6f9320..e1c773bb55359 100644
+--- a/drivers/clocksource/arm_global_timer.c
++++ b/drivers/clocksource/arm_global_timer.c
+@@ -32,7 +32,7 @@
+ #define GT_CONTROL_IRQ_ENABLE BIT(2) /* banked */
+ #define GT_CONTROL_AUTO_INC BIT(3) /* banked */
+ #define GT_CONTROL_PRESCALER_SHIFT 8
+-#define GT_CONTROL_PRESCALER_MAX 0xF
++#define GT_CONTROL_PRESCALER_MAX 0xFF
+ #define GT_CONTROL_PRESCALER_MASK (GT_CONTROL_PRESCALER_MAX << \
+ GT_CONTROL_PRESCALER_SHIFT)
+
+diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c
+index e66dcbd665665..79bb9a98baa7b 100644
+--- a/drivers/clocksource/timer-riscv.c
++++ b/drivers/clocksource/timer-riscv.c
+@@ -108,6 +108,9 @@ static int riscv_timer_starting_cpu(unsigned int cpu)
+ {
+ struct clock_event_device *ce = per_cpu_ptr(&riscv_clock_event, cpu);
+
++ /* Clear timer interrupt */
++ riscv_clock_event_stop();
++
+ ce->cpumask = cpumask_of(cpu);
+ ce->irq = riscv_clock_event_irq;
+ if (riscv_timer_cannot_wake_cpu)
+diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
+index 1791d37fbc53c..07f3419954396 100644
+--- a/drivers/cpufreq/amd-pstate.c
++++ b/drivers/cpufreq/amd-pstate.c
+@@ -570,7 +570,7 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
+ if (target_perf < capacity)
+ des_perf = DIV_ROUND_UP(cap_perf * target_perf, capacity);
+
+- min_perf = READ_ONCE(cpudata->highest_perf);
++ min_perf = READ_ONCE(cpudata->lowest_perf);
+ if (_min_perf < capacity)
+ min_perf = DIV_ROUND_UP(cap_perf * _min_perf, capacity);
+
+diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
+index 8bd6e5e8f121c..2d83bbc65dd0b 100644
+--- a/drivers/cpufreq/cpufreq-dt.c
++++ b/drivers/cpufreq/cpufreq-dt.c
+@@ -208,7 +208,7 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu)
+ if (!priv)
+ return -ENOMEM;
+
+- if (!alloc_cpumask_var(&priv->cpus, GFP_KERNEL))
++ if (!zalloc_cpumask_var(&priv->cpus, GFP_KERNEL))
+ return -ENOMEM;
+
+ cpumask_set_cpu(cpu, priv->cpus);
+diff --git a/drivers/crypto/intel/iaa/iaa_crypto_main.c b/drivers/crypto/intel/iaa/iaa_crypto_main.c
+index dfd3baf0a8d87..aa65c1791ce76 100644
+--- a/drivers/crypto/intel/iaa/iaa_crypto_main.c
++++ b/drivers/crypto/intel/iaa/iaa_crypto_main.c
+@@ -908,6 +908,8 @@ static int save_iaa_wq(struct idxd_wq *wq)
+ return -EINVAL;
+
+ cpus_per_iaa = (nr_nodes * nr_cpus_per_node) / nr_iaa;
++ if (!cpus_per_iaa)
++ cpus_per_iaa = 1;
+ out:
+ return 0;
+ }
+@@ -923,10 +925,12 @@ static void remove_iaa_wq(struct idxd_wq *wq)
+ }
+ }
+
+- if (nr_iaa)
++ if (nr_iaa) {
+ cpus_per_iaa = (nr_nodes * nr_cpus_per_node) / nr_iaa;
+- else
+- cpus_per_iaa = 0;
++ if (!cpus_per_iaa)
++ cpus_per_iaa = 1;
++ } else
++ cpus_per_iaa = 1;
+ }
+
+ static int wq_table_add_wqs(int iaa, int cpu)
+diff --git a/drivers/crypto/intel/qat/qat_common/adf_aer.c b/drivers/crypto/intel/qat/qat_common/adf_aer.c
+index a39e70bd4b21b..621d14ea3b81a 100644
+--- a/drivers/crypto/intel/qat/qat_common/adf_aer.c
++++ b/drivers/crypto/intel/qat/qat_common/adf_aer.c
+@@ -92,7 +92,8 @@ static void adf_device_reset_worker(struct work_struct *work)
+ if (adf_dev_restart(accel_dev)) {
+ /* The device hanged and we can't restart it so stop here */
+ dev_err(&GET_DEV(accel_dev), "Restart device failed\n");
+- if (reset_data->mode == ADF_DEV_RESET_ASYNC)
++ if (reset_data->mode == ADF_DEV_RESET_ASYNC ||
++ completion_done(&reset_data->compl))
+ kfree(reset_data);
+ WARN(1, "QAT: device restart failed. Device is unusable\n");
+ return;
+@@ -100,11 +101,19 @@ static void adf_device_reset_worker(struct work_struct *work)
+ adf_dev_restarted_notify(accel_dev);
+ clear_bit(ADF_STATUS_RESTARTING, &accel_dev->status);
+
+- /* The dev is back alive. Notify the caller if in sync mode */
+- if (reset_data->mode == ADF_DEV_RESET_SYNC)
+- complete(&reset_data->compl);
+- else
++ /*
++ * The dev is back alive. Notify the caller if in sync mode
++ *
++ * If device restart will take a more time than expected,
++ * the schedule_reset() function can timeout and exit. This can be
++ * detected by calling the completion_done() function. In this case
++ * the reset_data structure needs to be freed here.
++ */
++ if (reset_data->mode == ADF_DEV_RESET_ASYNC ||
++ completion_done(&reset_data->compl))
+ kfree(reset_data);
++ else
++ complete(&reset_data->compl);
+ }
+
+ static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev,
+@@ -137,8 +146,9 @@ static int adf_dev_aer_schedule_reset(struct adf_accel_dev *accel_dev,
+ dev_err(&GET_DEV(accel_dev),
+ "Reset device timeout expired\n");
+ ret = -EFAULT;
++ } else {
++ kfree(reset_data);
+ }
+- kfree(reset_data);
+ return ret;
+ }
+ return 0;
+diff --git a/drivers/crypto/intel/qat/qat_common/adf_rl.c b/drivers/crypto/intel/qat/qat_common/adf_rl.c
+index de1b214dba1f9..d4f2db3c53d8c 100644
+--- a/drivers/crypto/intel/qat/qat_common/adf_rl.c
++++ b/drivers/crypto/intel/qat/qat_common/adf_rl.c
+@@ -788,6 +788,24 @@ static void clear_sla(struct adf_rl *rl_data, struct rl_sla *sla)
+ sla_type_arr[node_id] = NULL;
+ }
+
++static void free_all_sla(struct adf_accel_dev *accel_dev)
++{
++ struct adf_rl *rl_data = accel_dev->rate_limiting;
++ int sla_id;
++
++ mutex_lock(&rl_data->rl_lock);
++
++ for (sla_id = 0; sla_id < RL_NODES_CNT_MAX; sla_id++) {
++ if (!rl_data->sla[sla_id])
++ continue;
++
++ kfree(rl_data->sla[sla_id]);
++ rl_data->sla[sla_id] = NULL;
++ }
++
++ mutex_unlock(&rl_data->rl_lock);
++}
++
+ /**
+ * add_update_sla() - handles the creation and the update of an SLA
+ * @accel_dev: pointer to acceleration device structure
+@@ -1155,7 +1173,7 @@ void adf_rl_stop(struct adf_accel_dev *accel_dev)
+ return;
+
+ adf_sysfs_rl_rm(accel_dev);
+- adf_rl_remove_sla_all(accel_dev, true);
++ free_all_sla(accel_dev);
+ }
+
+ void adf_rl_exit(struct adf_accel_dev *accel_dev)
+diff --git a/drivers/cxl/core/trace.h b/drivers/cxl/core/trace.h
+index bdf117a33744b..e5f13260fc524 100644
+--- a/drivers/cxl/core/trace.h
++++ b/drivers/cxl/core/trace.h
+@@ -646,18 +646,18 @@ u64 cxl_trace_hpa(struct cxl_region *cxlr, struct cxl_memdev *memdev, u64 dpa);
+
+ TRACE_EVENT(cxl_poison,
+
+- TP_PROTO(struct cxl_memdev *cxlmd, struct cxl_region *region,
++ TP_PROTO(struct cxl_memdev *cxlmd, struct cxl_region *cxlr,
+ const struct cxl_poison_record *record, u8 flags,
+ __le64 overflow_ts, enum cxl_poison_trace_type trace_type),
+
+- TP_ARGS(cxlmd, region, record, flags, overflow_ts, trace_type),
++ TP_ARGS(cxlmd, cxlr, record, flags, overflow_ts, trace_type),
+
+ TP_STRUCT__entry(
+ __string(memdev, dev_name(&cxlmd->dev))
+ __string(host, dev_name(cxlmd->dev.parent))
+ __field(u64, serial)
+ __field(u8, trace_type)
+- __string(region, region)
++ __string(region, cxlr ? dev_name(&cxlr->dev) : "")
+ __field(u64, overflow_ts)
+ __field(u64, hpa)
+ __field(u64, dpa)
+@@ -677,10 +677,10 @@ TRACE_EVENT(cxl_poison,
+ __entry->source = cxl_poison_record_source(record);
+ __entry->trace_type = trace_type;
+ __entry->flags = flags;
+- if (region) {
+- __assign_str(region, dev_name(®ion->dev));
+- memcpy(__entry->uuid, ®ion->params.uuid, 16);
+- __entry->hpa = cxl_trace_hpa(region, cxlmd,
++ if (cxlr) {
++ __assign_str(region, dev_name(&cxlr->dev));
++ memcpy(__entry->uuid, &cxlr->params.uuid, 16);
++ __entry->hpa = cxl_trace_hpa(cxlr, cxlmd,
+ __entry->dpa);
+ } else {
+ __assign_str(region, "");
+diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
+index 4fcda50acfa4a..1ea14e86a741b 100644
+--- a/drivers/firmware/efi/efi.c
++++ b/drivers/firmware/efi/efi.c
+@@ -203,6 +203,8 @@ static bool generic_ops_supported(void)
+
+ name_size = sizeof(name);
+
++ if (!efi.get_next_variable)
++ return false;
+ status = efi.get_next_variable(&name_size, &name, &guid);
+ if (status == EFI_UNSUPPORTED)
+ return false;
+diff --git a/drivers/firmware/efi/libstub/randomalloc.c b/drivers/firmware/efi/libstub/randomalloc.c
+index 4e96a855fdf47..c41e7b2091cdd 100644
+--- a/drivers/firmware/efi/libstub/randomalloc.c
++++ b/drivers/firmware/efi/libstub/randomalloc.c
+@@ -120,7 +120,7 @@ efi_status_t efi_random_alloc(unsigned long size,
+ continue;
+ }
+
+- target = round_up(md->phys_addr, align) + target_slot * align;
++ target = round_up(max_t(u64, md->phys_addr, alloc_min), align) + target_slot * align;
+ pages = size / EFI_PAGE_SIZE;
+
+ status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index c9857ee3880c2..dd80082aac1ac 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -487,6 +487,7 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ hdr->vid_mode = 0xffff;
+
+ hdr->type_of_loader = 0x21;
++ hdr->initrd_addr_max = INT_MAX;
+
+ /* Convert unicode cmdline to ascii */
+ cmdline_ptr = efi_convert_cmdline(image, &options_size);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
+index 55b65fc04b651..431ec72655ec8 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
+@@ -129,13 +129,25 @@ static const struct mmu_interval_notifier_ops amdgpu_hmm_hsa_ops = {
+ */
+ int amdgpu_hmm_register(struct amdgpu_bo *bo, unsigned long addr)
+ {
++ int r;
++
+ if (bo->kfd_bo)
+- return mmu_interval_notifier_insert(&bo->notifier, current->mm,
++ r = mmu_interval_notifier_insert(&bo->notifier, current->mm,
+ addr, amdgpu_bo_size(bo),
+ &amdgpu_hmm_hsa_ops);
+- return mmu_interval_notifier_insert(&bo->notifier, current->mm, addr,
+- amdgpu_bo_size(bo),
+- &amdgpu_hmm_gfx_ops);
++ else
++ r = mmu_interval_notifier_insert(&bo->notifier, current->mm, addr,
++ amdgpu_bo_size(bo),
++ &amdgpu_hmm_gfx_ops);
++ if (r)
++ /*
++ * Make sure amdgpu_hmm_unregister() doesn't call
++ * mmu_interval_notifier_remove() when the notifier isn't properly
++ * initialized.
++ */
++ bo->notifier.mm = NULL;
++
++ return r;
+ }
+
+ /**
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+index 5505d646f43aa..06f0a6534a94f 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+@@ -524,46 +524,58 @@ static ssize_t amdgpu_debugfs_mqd_read(struct file *f, char __user *buf,
+ {
+ struct amdgpu_ring *ring = file_inode(f)->i_private;
+ volatile u32 *mqd;
+- int r;
++ u32 *kbuf;
++ int r, i;
+ uint32_t value, result;
+
+ if (*pos & 3 || size & 3)
+ return -EINVAL;
+
+- result = 0;
++ kbuf = kmalloc(ring->mqd_size, GFP_KERNEL);
++ if (!kbuf)
++ return -ENOMEM;
+
+ r = amdgpu_bo_reserve(ring->mqd_obj, false);
+ if (unlikely(r != 0))
+- return r;
++ goto err_free;
+
+ r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&mqd);
+- if (r) {
+- amdgpu_bo_unreserve(ring->mqd_obj);
+- return r;
+- }
++ if (r)
++ goto err_unreserve;
+
++ /*
++ * Copy to local buffer to avoid put_user(), which might fault
++ * and acquire mmap_sem, under reservation_ww_class_mutex.
++ */
++ for (i = 0; i < ring->mqd_size/sizeof(u32); i++)
++ kbuf[i] = mqd[i];
++
++ amdgpu_bo_kunmap(ring->mqd_obj);
++ amdgpu_bo_unreserve(ring->mqd_obj);
++
++ result = 0;
+ while (size) {
+ if (*pos >= ring->mqd_size)
+- goto done;
++ break;
+
+- value = mqd[*pos/4];
++ value = kbuf[*pos/4];
+ r = put_user(value, (uint32_t *)buf);
+ if (r)
+- goto done;
++ goto err_free;
+ buf += 4;
+ result += 4;
+ size -= 4;
+ *pos += 4;
+ }
+
+-done:
+- amdgpu_bo_kunmap(ring->mqd_obj);
+- mqd = NULL;
+- amdgpu_bo_unreserve(ring->mqd_obj);
+- if (r)
+- return r;
+-
++ kfree(kbuf);
+ return result;
++
++err_unreserve:
++ amdgpu_bo_unreserve(ring->mqd_obj);
++err_free:
++ kfree(kbuf);
++ return r;
+ }
+
+ static const struct file_operations amdgpu_debugfs_mqd_fops = {
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+index 75c9fd2c6c2a1..b0ed10f4de609 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+@@ -869,6 +869,7 @@ static void amdgpu_ttm_gart_bind(struct amdgpu_device *adev,
+ amdgpu_gart_bind(adev, gtt->offset, ttm->num_pages,
+ gtt->ttm.dma_address, flags);
+ }
++ gtt->bound = true;
+ }
+
+ /*
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+index 80320b8603fc6..fedeba3e1250d 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+@@ -1473,7 +1473,7 @@ static inline void kfd_flush_tlb(struct kfd_process_device *pdd,
+
+ static inline bool kfd_flush_tlb_after_unmap(struct kfd_dev *dev)
+ {
+- return KFD_GC_VERSION(dev) > IP_VERSION(9, 4, 2) ||
++ return KFD_GC_VERSION(dev) >= IP_VERSION(9, 4, 2) ||
+ (KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 1) && dev->sdma_fw_version >= 18) ||
+ KFD_GC_VERSION(dev) == IP_VERSION(9, 4, 0);
+ }
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 8083e7156afcf..1eb0f82e9dfae 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -5199,6 +5199,10 @@ static inline void fill_dc_dirty_rect(struct drm_plane *plane,
+ * @new_plane_state: New state of @plane
+ * @crtc_state: New state of CRTC connected to the @plane
+ * @flip_addrs: DC flip tracking struct, which also tracts dirty rects
++ * @is_psr_su: Flag indicating whether Panel Self Refresh Selective Update (PSR SU) is enabled.
++ * If PSR SU is enabled and damage clips are available, only the regions of the screen
++ * that have changed will be updated. If PSR SU is not enabled,
++ * or if damage clips are not available, the entire screen will be updated.
+ * @dirty_regions_changed: dirty regions changed
+ *
+ * For PSR SU, DC informs the DMUB uController of dirty rectangle regions
+@@ -6252,9 +6256,8 @@ create_stream_for_sink(struct drm_connector *connector,
+
+ if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+ mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket);
+- else if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
+- stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
+- stream->signal == SIGNAL_TYPE_EDP) {
++
++ if (stream->link->psr_settings.psr_feature_enabled || stream->link->replay_settings.replay_feature_enabled) {
+ //
+ // should decide stream support vsc sdp colorimetry capability
+ // before building vsc info packet
+@@ -6270,9 +6273,8 @@ create_stream_for_sink(struct drm_connector *connector,
+ if (stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22)
+ tf = TRANSFER_FUNC_GAMMA_22;
+ mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space, tf);
++ aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY;
+
+- if (stream->link->psr_settings.psr_feature_enabled)
+- aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY;
+ }
+ finish:
+ dc_sink_release(sink);
+@@ -11136,18 +11138,24 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector,
+ if (!adev->dm.freesync_module)
+ goto update;
+
+- if (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT
+- || sink->sink_signal == SIGNAL_TYPE_EDP) {
++ if (edid && (sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT ||
++ sink->sink_signal == SIGNAL_TYPE_EDP)) {
+ bool edid_check_required = false;
+
+- if (edid) {
+- edid_check_required = is_dp_capable_without_timing_msa(
+- adev->dm.dc,
+- amdgpu_dm_connector);
++ if (is_dp_capable_without_timing_msa(adev->dm.dc,
++ amdgpu_dm_connector)) {
++ if (edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ) {
++ freesync_capable = true;
++ amdgpu_dm_connector->min_vfreq = connector->display_info.monitor_range.min_vfreq;
++ amdgpu_dm_connector->max_vfreq = connector->display_info.monitor_range.max_vfreq;
++ } else {
++ edid_check_required = edid->version > 1 ||
++ (edid->version == 1 &&
++ edid->revision > 1);
++ }
+ }
+
+- if (edid_check_required == true && (edid->version > 1 ||
+- (edid->version == 1 && edid->revision > 1))) {
++ if (edid_check_required) {
+ for (i = 0; i < 4; i++) {
+
+ timing = &edid->detailed_timings[i];
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
+index 1f08c6564c3bf..286ecd28cc6e6 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c
+@@ -141,9 +141,8 @@ bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream)
+ * amdgpu_dm_psr_enable() - enable psr f/w
+ * @stream: stream state
+ *
+- * Return: true if success
+ */
+-bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
++void amdgpu_dm_psr_enable(struct dc_stream_state *stream)
+ {
+ struct dc_link *link = stream->link;
+ unsigned int vsync_rate_hz = 0;
+@@ -190,7 +189,10 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state *stream)
+ if (link->psr_settings.psr_version < DC_PSR_VERSION_SU_1)
+ power_opt |= psr_power_opt_z10_static_screen;
+
+- return dc_link_set_psr_allow_active(link, &psr_enable, false, false, &power_opt);
++ dc_link_set_psr_allow_active(link, &psr_enable, false, false, &power_opt);
++
++ if (link->ctx->dc->caps.ips_support)
++ dc_allow_idle_optimizations(link->ctx->dc, true);
+ }
+
+ /*
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.h
+index 6806b3c9c84ba..1fdfd183c0d91 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.h
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.h
+@@ -32,7 +32,7 @@
+ #define AMDGPU_DM_PSR_ENTRY_DELAY 5
+
+ void amdgpu_dm_set_psr_caps(struct dc_link *link);
+-bool amdgpu_dm_psr_enable(struct dc_stream_state *stream);
++void amdgpu_dm_psr_enable(struct dc_stream_state *stream);
+ bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream);
+ bool amdgpu_dm_psr_disable(struct dc_stream_state *stream);
+ bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm);
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+index aadd07bc68c5d..bbdbc78161a00 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+@@ -216,6 +216,16 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
+ if (clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz > 1950)
+ clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz = 1950;
+
++ /* DPPCLK */
++ dcn32_init_single_clock(clk_mgr, PPCLK_DPPCLK,
++ &clk_mgr_base->bw_params->clk_table.entries[0].dppclk_mhz,
++ &num_entries_per_clk->num_dppclk_levels);
++ num_levels = num_entries_per_clk->num_dppclk_levels;
++ clk_mgr_base->bw_params->dc_mode_limit.dppclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DPPCLK);
++ //HW recommends limit of 1950 MHz in display clock for all DCN3.2.x
++ if (clk_mgr_base->bw_params->dc_mode_limit.dppclk_mhz > 1950)
++ clk_mgr_base->bw_params->dc_mode_limit.dppclk_mhz = 1950;
++
+ if (num_entries_per_clk->num_dcfclk_levels &&
+ num_entries_per_clk->num_dtbclk_levels &&
+ num_entries_per_clk->num_dispclk_levels)
+@@ -240,6 +250,10 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
+ = khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz);
+ }
+
++ for (i = 0; i < num_levels; i++)
++ if (clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz > 1950)
++ clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz = 1950;
++
+ /* Get UCLK, update bounding box */
+ clk_mgr_base->funcs->get_memclk_states_from_smu(clk_mgr_base);
+
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+index e648902592358..3db46bdc71a35 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+@@ -706,7 +706,7 @@ static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk
+ clock_table->NumFclkLevelsEnabled;
+ max_fclk = find_max_clk_value(clock_table->FclkClocks_Freq, num_fclk);
+
+- num_dcfclk = (clock_table->NumFclkLevelsEnabled > NUM_DCFCLK_DPM_LEVELS) ? NUM_DCFCLK_DPM_LEVELS :
++ num_dcfclk = (clock_table->NumDcfClkLevelsEnabled > NUM_DCFCLK_DPM_LEVELS) ? NUM_DCFCLK_DPM_LEVELS :
+ clock_table->NumDcfClkLevelsEnabled;
+ for (i = 0; i < num_dcfclk; i++) {
+ int j;
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index 2c424e435962d..3c3d613c5f00e 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -411,9 +411,14 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
+ * avoid conflicting with firmware updates.
+ */
+ if (dc->ctx->dce_version > DCE_VERSION_MAX)
+- if (dc->optimized_required || dc->wm_optimized_required)
++ if (dc->optimized_required)
+ return false;
+
++ if (!memcmp(&stream->adjust, adjust, sizeof(*adjust)))
++ return true;
++
++ dc_exit_ips_for_hw_access(dc);
++
+ stream->adjust.v_total_max = adjust->v_total_max;
+ stream->adjust.v_total_mid = adjust->v_total_mid;
+ stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num;
+@@ -454,6 +459,8 @@ bool dc_stream_get_last_used_drr_vtotal(struct dc *dc,
+
+ int i = 0;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ for (i = 0; i < MAX_PIPES; i++) {
+ struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+@@ -484,6 +491,8 @@ bool dc_stream_get_crtc_position(struct dc *dc,
+ bool ret = false;
+ struct crtc_position position;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ for (i = 0; i < MAX_PIPES; i++) {
+ struct pipe_ctx *pipe =
+ &dc->current_state->res_ctx.pipe_ctx[i];
+@@ -603,6 +612,8 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream,
+ if (pipe == NULL)
+ return false;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ /* By default, capture the full frame */
+ param.windowa_x_start = 0;
+ param.windowa_y_start = 0;
+@@ -662,6 +673,8 @@ bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream,
+ struct pipe_ctx *pipe;
+ struct timing_generator *tg;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe->stream == stream)
+@@ -686,6 +699,8 @@ void dc_stream_set_dyn_expansion(struct dc *dc, struct dc_stream_state *stream,
+ int i;
+ struct pipe_ctx *pipe_ctx;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ for (i = 0; i < MAX_PIPES; i++) {
+ if (dc->current_state->res_ctx.pipe_ctx[i].stream
+ == stream) {
+@@ -721,6 +736,8 @@ void dc_stream_set_dither_option(struct dc_stream_state *stream,
+ if (option > DITHER_OPTION_MAX)
+ return;
+
++ dc_exit_ips_for_hw_access(stream->ctx->dc);
++
+ stream->dither_option = option;
+
+ memset(¶ms, 0, sizeof(params));
+@@ -745,6 +762,8 @@ bool dc_stream_set_gamut_remap(struct dc *dc, const struct dc_stream_state *stre
+ bool ret = false;
+ struct pipe_ctx *pipes;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ for (i = 0; i < MAX_PIPES; i++) {
+ if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) {
+ pipes = &dc->current_state->res_ctx.pipe_ctx[i];
+@@ -762,6 +781,8 @@ bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream)
+ bool ret = false;
+ struct pipe_ctx *pipes;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ for (i = 0; i < MAX_PIPES; i++) {
+ if (dc->current_state->res_ctx.pipe_ctx[i].stream
+ == stream) {
+@@ -788,6 +809,8 @@ void dc_stream_set_static_screen_params(struct dc *dc,
+ struct pipe_ctx *pipes_affected[MAX_PIPES];
+ int num_pipes_affected = 0;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ for (i = 0; i < num_streams; i++) {
+ struct dc_stream_state *stream = streams[i];
+
+@@ -1282,6 +1305,54 @@ static void disable_vbios_mode_if_required(
+ }
+ }
+
++/**
++ * wait_for_blank_complete - wait for all active OPPs to finish pending blank
++ * pattern updates
++ *
++ * @dc: [in] dc reference
++ * @context: [in] hardware context in use
++ */
++static void wait_for_blank_complete(struct dc *dc,
++ struct dc_state *context)
++{
++ struct pipe_ctx *opp_head;
++ struct dce_hwseq *hws = dc->hwseq;
++ int i;
++
++ if (!hws->funcs.wait_for_blank_complete)
++ return;
++
++ for (i = 0; i < MAX_PIPES; i++) {
++ opp_head = &context->res_ctx.pipe_ctx[i];
++
++ if (!resource_is_pipe_type(opp_head, OPP_HEAD) ||
++ dc_state_get_pipe_subvp_type(context, opp_head) == SUBVP_PHANTOM)
++ continue;
++
++ hws->funcs.wait_for_blank_complete(opp_head->stream_res.opp);
++ }
++}
++
++static void wait_for_odm_update_pending_complete(struct dc *dc, struct dc_state *context)
++{
++ struct pipe_ctx *otg_master;
++ struct timing_generator *tg;
++ int i;
++
++ for (i = 0; i < MAX_PIPES; i++) {
++ otg_master = &context->res_ctx.pipe_ctx[i];
++ if (!resource_is_pipe_type(otg_master, OTG_MASTER) ||
++ dc_state_get_pipe_subvp_type(context, otg_master) == SUBVP_PHANTOM)
++ continue;
++ tg = otg_master->stream_res.tg;
++ if (tg->funcs->wait_odm_doublebuffer_pending_clear)
++ tg->funcs->wait_odm_doublebuffer_pending_clear(tg);
++ }
++
++ /* ODM update may require to reprogram blank pattern for each OPP */
++ wait_for_blank_complete(dc, context);
++}
++
+ static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
+ {
+ int i;
+@@ -1766,6 +1837,8 @@ void dc_enable_stereo(
+ int i, j;
+ struct pipe_ctx *pipe;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ for (i = 0; i < MAX_PIPES; i++) {
+ if (context != NULL) {
+ pipe = &context->res_ctx.pipe_ctx[i];
+@@ -1785,6 +1858,8 @@ void dc_enable_stereo(
+ void dc_trigger_sync(struct dc *dc, struct dc_state *context)
+ {
+ if (context->stream_count > 1 && !dc->debug.disable_timing_sync) {
++ dc_exit_ips_for_hw_access(dc);
++
+ enable_timing_multisync(dc, context);
+ program_timing_sync(dc, context);
+ }
+@@ -1969,6 +2044,11 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
+ context->stream_count == 0) {
+ /* Must wait for no flips to be pending before doing optimize bw */
+ wait_for_no_pipes_pending(dc, context);
++ /*
++ * optimized dispclk depends on ODM setup. Need to wait for ODM
++ * update pending complete before optimizing bandwidth.
++ */
++ wait_for_odm_update_pending_complete(dc, context);
+ /* pplib is notified if disp_num changed */
+ dc->hwss.optimize_bandwidth(dc, context);
+ /* Need to do otg sync again as otg could be out of sync due to otg
+@@ -2041,6 +2121,8 @@ enum dc_status dc_commit_streams(struct dc *dc,
+ if (!streams_changed(dc, streams, stream_count))
+ return res;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ DC_LOG_DC("%s: %d streams\n", __func__, stream_count);
+
+ for (i = 0; i < stream_count; i++) {
+@@ -2227,7 +2309,6 @@ void dc_post_update_surfaces_to_stream(struct dc *dc)
+ }
+
+ dc->optimized_required = false;
+- dc->wm_optimized_required = false;
+ }
+
+ bool dc_set_generic_gpio_for_stereo(bool enable,
+@@ -2650,8 +2731,6 @@ enum surface_update_type dc_check_update_surfaces_for_stream(
+ } else if (memcmp(&dc->current_state->bw_ctx.bw.dcn.clk, &dc->clk_mgr->clks, offsetof(struct dc_clocks, prev_p_state_change_support)) != 0) {
+ dc->optimized_required = true;
+ }
+-
+- dc->optimized_required |= dc->wm_optimized_required;
+ }
+
+ return type;
+@@ -2859,9 +2938,6 @@ static void copy_stream_update_to_stream(struct dc *dc,
+ if (update->vrr_active_fixed)
+ stream->vrr_active_fixed = *update->vrr_active_fixed;
+
+- if (update->crtc_timing_adjust)
+- stream->adjust = *update->crtc_timing_adjust;
+-
+ if (update->dpms_off)
+ stream->dpms_off = *update->dpms_off;
+
+@@ -3223,6 +3299,9 @@ static bool dc_dmub_should_send_dirty_rect_cmd(struct dc *dc, struct dc_stream_s
+ if (stream->link->replay_settings.config.replay_supported)
+ return true;
+
++ if (stream->ctx->dce_version >= DCN_VERSION_3_5 && stream->abm_level)
++ return true;
++
+ return false;
+ }
+
+@@ -3376,6 +3455,8 @@ static void commit_planes_for_stream_fast(struct dc *dc,
+ int i, j;
+ struct pipe_ctx *top_pipe_to_program = NULL;
+ struct dc_stream_status *stream_status = NULL;
++ dc_exit_ips_for_hw_access(dc);
++
+ dc_z10_restore(dc);
+
+ top_pipe_to_program = resource_get_otg_master_for_stream(
+@@ -3444,7 +3525,7 @@ static void commit_planes_for_stream_fast(struct dc *dc,
+ top_pipe_to_program->stream->update_flags.raw = 0;
+ }
+
+-static void wait_for_outstanding_hw_updates(struct dc *dc, const struct dc_state *dc_context)
++static void wait_for_outstanding_hw_updates(struct dc *dc, struct dc_state *dc_context)
+ {
+ /*
+ * This function calls HWSS to wait for any potentially double buffered
+@@ -3482,6 +3563,7 @@ static void wait_for_outstanding_hw_updates(struct dc *dc, const struct dc_state
+ }
+ }
+ }
++ wait_for_odm_update_pending_complete(dc, dc_context);
+ }
+
+ static void commit_planes_for_stream(struct dc *dc,
+@@ -3503,6 +3585,8 @@ static void commit_planes_for_stream(struct dc *dc,
+ // dc->current_state anymore, so we have to cache it before we apply
+ // the new SubVP context
+ subvp_prev_use = false;
++ dc_exit_ips_for_hw_access(dc);
++
+ dc_z10_restore(dc);
+ if (update_type == UPDATE_TYPE_FULL)
+ wait_for_outstanding_hw_updates(dc, context);
+@@ -4293,8 +4377,7 @@ static bool full_update_required(struct dc *dc,
+ stream_update->mst_bw_update ||
+ stream_update->func_shaper ||
+ stream_update->lut3d_func ||
+- stream_update->pending_test_pattern ||
+- stream_update->crtc_timing_adjust))
++ stream_update->pending_test_pattern))
+ return true;
+
+ if (stream) {
+@@ -4384,6 +4467,8 @@ bool dc_update_planes_and_stream(struct dc *dc,
+ bool is_plane_addition = 0;
+ bool is_fast_update_only;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ populate_fast_updates(fast_update, srf_updates, surface_count, stream_update);
+ is_fast_update_only = fast_update_only(dc, fast_update, srf_updates,
+ surface_count, stream_update, stream);
+@@ -4504,6 +4589,8 @@ void dc_commit_updates_for_stream(struct dc *dc,
+ int i, j;
+ struct dc_fast_update fast_update[MAX_SURFACES] = {0};
+
++ dc_exit_ips_for_hw_access(dc);
++
+ populate_fast_updates(fast_update, srf_updates, surface_count, stream_update);
+ stream_status = dc_stream_get_status(stream);
+ context = dc->current_state;
+@@ -4688,6 +4775,8 @@ void dc_set_power_state(
+ case DC_ACPI_CM_POWER_STATE_D0:
+ dc_state_construct(dc, dc->current_state);
+
++ dc_exit_ips_for_hw_access(dc);
++
+ dc_z10_restore(dc);
+
+ dc->hwss.init_hw(dc);
+@@ -4829,24 +4918,24 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow)
+ dc->idle_optimizations_allowed = allow;
+ }
+
+-bool dc_dmub_is_ips_idle_state(struct dc *dc)
++void dc_exit_ips_for_hw_access(struct dc *dc)
+ {
+- uint32_t idle_state = 0;
++ if (dc->caps.ips_support)
++ dc_allow_idle_optimizations(dc, false);
++}
+
++bool dc_dmub_is_ips_idle_state(struct dc *dc)
++{
+ if (dc->debug.disable_idle_power_optimizations)
+ return false;
+
+ if (!dc->caps.ips_support || (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL))
+ return false;
+
+- if (dc->hwss.get_idle_state)
+- idle_state = dc->hwss.get_idle_state(dc);
+-
+- if (!(idle_state & DMUB_IPS1_ALLOW_MASK) ||
+- !(idle_state & DMUB_IPS2_ALLOW_MASK))
+- return true;
++ if (!dc->ctx->dmub_srv)
++ return false;
+
+- return false;
++ return dc->ctx->dmub_srv->idle_allowed;
+ }
+
+ /* set min and max memory clock to lowest and highest DPM level, respectively */
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+index 180ac47868c22..5cc7f8da209c5 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+@@ -334,7 +334,8 @@ static void dc_state_free(struct kref *kref)
+
+ void dc_state_release(struct dc_state *state)
+ {
+- kref_put(&state->refcount, dc_state_free);
++ if (state != NULL)
++ kref_put(&state->refcount, dc_state_free);
+ }
+ /*
+ * dc_state_add_stream() - Add a new dc_stream_state to a dc_state.
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+index 54670e0b15189..51a970fcb5d05 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+@@ -423,6 +423,8 @@ bool dc_stream_add_writeback(struct dc *dc,
+ return false;
+ }
+
++ dc_exit_ips_for_hw_access(dc);
++
+ wb_info->dwb_params.out_transfer_func = stream->out_transfer_func;
+
+ dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
+@@ -493,6 +495,8 @@ bool dc_stream_fc_disable_writeback(struct dc *dc,
+ return false;
+ }
+
++ dc_exit_ips_for_hw_access(dc);
++
+ if (dwb->funcs->set_fc_enable)
+ dwb->funcs->set_fc_enable(dwb, DWB_FRAME_CAPTURE_DISABLE);
+
+@@ -542,6 +546,8 @@ bool dc_stream_remove_writeback(struct dc *dc,
+ return false;
+ }
+
++ dc_exit_ips_for_hw_access(dc);
++
+ /* disable writeback */
+ if (dc->hwss.disable_writeback) {
+ struct dwbc *dwb = dc->res_pool->dwbc[dwb_pipe_inst];
+@@ -557,6 +563,8 @@ bool dc_stream_warmup_writeback(struct dc *dc,
+ int num_dwb,
+ struct dc_writeback_info *wb_info)
+ {
++ dc_exit_ips_for_hw_access(dc);
++
+ if (dc->hwss.mmhubbub_warmup)
+ return dc->hwss.mmhubbub_warmup(dc, num_dwb, wb_info);
+ else
+@@ -569,6 +577,8 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream)
+ struct resource_context *res_ctx =
+ &dc->current_state->res_ctx;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ for (i = 0; i < MAX_PIPES; i++) {
+ struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
+
+@@ -597,6 +607,8 @@ bool dc_stream_send_dp_sdp(const struct dc_stream_state *stream,
+ dc = stream->ctx->dc;
+ res_ctx = &dc->current_state->res_ctx;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ for (i = 0; i < MAX_PIPES; i++) {
+ struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
+
+@@ -628,6 +640,8 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
+ struct resource_context *res_ctx =
+ &dc->current_state->res_ctx;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ for (i = 0; i < MAX_PIPES; i++) {
+ struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
+
+@@ -664,6 +678,8 @@ bool dc_stream_dmdata_status_done(struct dc *dc, struct dc_stream_state *stream)
+ if (i == MAX_PIPES)
+ return true;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ return dc->hwss.dmdata_status_done(pipe);
+ }
+
+@@ -698,6 +714,8 @@ bool dc_stream_set_dynamic_metadata(struct dc *dc,
+
+ pipe_ctx->stream->dmdata_address = attr->address;
+
++ dc_exit_ips_for_hw_access(dc);
++
+ dc->hwss.program_dmdata_engine(pipe_ctx);
+
+ if (hubp->funcs->dmdata_set_attributes != NULL &&
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
+index 19a2c7140ae84..19140fb65787c 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_surface.c
+@@ -161,6 +161,8 @@ const struct dc_plane_status *dc_plane_get_status(
+ break;
+ }
+
++ dc_exit_ips_for_hw_access(dc);
++
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe_ctx =
+ &dc->current_state->res_ctx.pipe_ctx[i];
+diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
+index c9317ea0258ea..f1342314f7f43 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc.h
++++ b/drivers/gpu/drm/amd/display/dc/dc.h
+@@ -1037,7 +1037,6 @@ struct dc {
+
+ /* Require to optimize clocks and bandwidth for added/removed planes */
+ bool optimized_required;
+- bool wm_optimized_required;
+ bool idle_optimizations_allowed;
+ bool enable_c20_dtm_b0;
+
+@@ -2325,6 +2324,7 @@ bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, struct dc_plane_
+ struct dc_cursor_attributes *cursor_attr);
+
+ void dc_allow_idle_optimizations(struct dc *dc, bool allow);
++void dc_exit_ips_for_hw_access(struct dc *dc);
+ bool dc_dmub_is_ips_idle_state(struct dc *dc);
+
+ /* set min and max memory clock to lowest and highest DPM level, respectively */
+diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
+index ee10941caa598..a23eebd9933b7 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
++++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
+@@ -139,7 +139,6 @@ union stream_update_flags {
+ uint32_t wb_update:1;
+ uint32_t dsc_changed : 1;
+ uint32_t mst_bw : 1;
+- uint32_t crtc_timing_adjust : 1;
+ uint32_t fams_changed : 1;
+ } bits;
+
+@@ -326,7 +325,6 @@ struct dc_stream_update {
+ struct dc_3dlut *lut3d_func;
+
+ struct test_pattern *pending_test_pattern;
+- struct dc_crtc_timing_adjust *crtc_timing_adjust;
+ };
+
+ bool dc_is_stream_unchanged(
+diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
+index 9900dda2eef5c..be2ac5c442a48 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
++++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
+@@ -1085,9 +1085,9 @@ struct replay_settings {
+ /* SMU optimization is enabled */
+ bool replay_smu_opt_enable;
+ /* Current Coasting vtotal */
+- uint16_t coasting_vtotal;
++ uint32_t coasting_vtotal;
+ /* Coasting vtotal table */
+- uint16_t coasting_vtotal_table[PR_COASTING_TYPE_NUM];
++ uint32_t coasting_vtotal_table[PR_COASTING_TYPE_NUM];
+ /* Maximum link off frame count */
+ enum replay_link_off_frame_count_level link_off_frame_count_level;
+ /* Replay pseudo vtotal for abm + ips on full screen video which can improve ips residency */
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c
+index 0dec57679269b..86bfed5dea2e2 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c
+@@ -377,6 +377,7 @@ static const struct opp_funcs dcn10_opp_funcs = {
+ .opp_set_disp_pattern_generator = NULL,
+ .opp_program_dpg_dimensions = NULL,
+ .dpg_is_blanked = NULL,
++ .dpg_is_pending = NULL,
+ .opp_destroy = opp1_destroy
+ };
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c
+index 0784d01986610..fbf1b6370eb23 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c
+@@ -337,6 +337,19 @@ bool opp2_dpg_is_blanked(struct output_pixel_processor *opp)
+ (double_buffer_pending == 0);
+ }
+
++bool opp2_dpg_is_pending(struct output_pixel_processor *opp)
++{
++ struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp);
++ uint32_t double_buffer_pending;
++ uint32_t dpg_en;
++
++ REG_GET(DPG_CONTROL, DPG_EN, &dpg_en);
++
++ REG_GET(DPG_STATUS, DPG_DOUBLE_BUFFER_PENDING, &double_buffer_pending);
++
++ return (dpg_en == 1 && double_buffer_pending == 1);
++}
++
+ void opp2_program_left_edge_extra_pixel (
+ struct output_pixel_processor *opp,
+ bool count)
+@@ -363,6 +376,7 @@ static struct opp_funcs dcn20_opp_funcs = {
+ .opp_set_disp_pattern_generator = opp2_set_disp_pattern_generator,
+ .opp_program_dpg_dimensions = opp2_program_dpg_dimensions,
+ .dpg_is_blanked = opp2_dpg_is_blanked,
++ .dpg_is_pending = opp2_dpg_is_pending,
+ .opp_dpg_set_blank_color = opp2_dpg_set_blank_color,
+ .opp_destroy = opp1_destroy,
+ .opp_program_left_edge_extra_pixel = opp2_program_left_edge_extra_pixel,
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.h
+index 3ab221bdd27dd..8f186abd558db 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.h
++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.h
+@@ -159,6 +159,8 @@ void opp2_program_dpg_dimensions(
+
+ bool opp2_dpg_is_blanked(struct output_pixel_processor *opp);
+
++bool opp2_dpg_is_pending(struct output_pixel_processor *opp);
++
+ void opp2_dpg_set_blank_color(
+ struct output_pixel_processor *opp,
+ const struct tg_color *color);
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_opp.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_opp.c
+index 8e77db46a4090..6a71ba3dfc632 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_opp.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_opp.c
+@@ -50,6 +50,7 @@ static struct opp_funcs dcn201_opp_funcs = {
+ .opp_set_disp_pattern_generator = opp2_set_disp_pattern_generator,
+ .opp_program_dpg_dimensions = opp2_program_dpg_dimensions,
+ .dpg_is_blanked = opp2_dpg_is_blanked,
++ .dpg_is_pending = opp2_dpg_is_pending,
+ .opp_dpg_set_blank_color = opp2_dpg_set_blank_color,
+ .opp_destroy = opp1_destroy,
+ .opp_program_left_edge_extra_pixel = opp2_program_left_edge_extra_pixel,
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
+index d1500b2238580..2f9da981a8bea 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.c
+@@ -44,6 +44,36 @@
+ #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
+
+
++void mpc3_mpc_init(struct mpc *mpc)
++{
++ struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
++ int opp_id;
++
++ mpc1_mpc_init(mpc);
++
++ for (opp_id = 0; opp_id < MAX_OPP; opp_id++) {
++ if (REG(MUX[opp_id]))
++ /* disable mpc out rate and flow control */
++ REG_UPDATE_2(MUX[opp_id], MPC_OUT_RATE_CONTROL_DISABLE,
++ 1, MPC_OUT_FLOW_CONTROL_COUNT, 0);
++ }
++}
++
++void mpc3_mpc_init_single_inst(struct mpc *mpc, unsigned int mpcc_id)
++{
++ struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
++
++ mpc1_mpc_init_single_inst(mpc, mpcc_id);
++
++ /* assuming mpc out mux is connected to opp with the same index at this
++ * point in time (e.g. transitioning from vbios to driver)
++ */
++ if (mpcc_id < MAX_OPP && REG(MUX[mpcc_id]))
++ /* disable mpc out rate and flow control */
++ REG_UPDATE_2(MUX[mpcc_id], MPC_OUT_RATE_CONTROL_DISABLE,
++ 1, MPC_OUT_FLOW_CONTROL_COUNT, 0);
++}
++
+ bool mpc3_is_dwb_idle(
+ struct mpc *mpc,
+ int dwb_id)
+@@ -80,25 +110,6 @@ void mpc3_disable_dwb_mux(
+ MPC_DWB0_MUX, 0xf);
+ }
+
+-void mpc3_set_out_rate_control(
+- struct mpc *mpc,
+- int opp_id,
+- bool enable,
+- bool rate_2x_mode,
+- struct mpc_dwb_flow_control *flow_control)
+-{
+- struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
+-
+- REG_UPDATE_2(MUX[opp_id],
+- MPC_OUT_RATE_CONTROL_DISABLE, !enable,
+- MPC_OUT_RATE_CONTROL, rate_2x_mode);
+-
+- if (flow_control)
+- REG_UPDATE_2(MUX[opp_id],
+- MPC_OUT_FLOW_CONTROL_MODE, flow_control->flow_ctrl_mode,
+- MPC_OUT_FLOW_CONTROL_COUNT, flow_control->flow_ctrl_cnt1);
+-}
+-
+ enum dc_lut_mode mpc3_get_ogam_current(struct mpc *mpc, int mpcc_id)
+ {
+ /*Contrary to DCN2 and DCN1 wherein a single status register field holds this info;
+@@ -1386,8 +1397,8 @@ static const struct mpc_funcs dcn30_mpc_funcs = {
+ .read_mpcc_state = mpc1_read_mpcc_state,
+ .insert_plane = mpc1_insert_plane,
+ .remove_mpcc = mpc1_remove_mpcc,
+- .mpc_init = mpc1_mpc_init,
+- .mpc_init_single_inst = mpc1_mpc_init_single_inst,
++ .mpc_init = mpc3_mpc_init,
++ .mpc_init_single_inst = mpc3_mpc_init_single_inst,
+ .update_blending = mpc2_update_blending,
+ .cursor_lock = mpc1_cursor_lock,
+ .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp,
+@@ -1404,7 +1415,6 @@ static const struct mpc_funcs dcn30_mpc_funcs = {
+ .set_dwb_mux = mpc3_set_dwb_mux,
+ .disable_dwb_mux = mpc3_disable_dwb_mux,
+ .is_dwb_idle = mpc3_is_dwb_idle,
+- .set_out_rate_control = mpc3_set_out_rate_control,
+ .set_gamut_remap = mpc3_set_gamut_remap,
+ .program_shaper = mpc3_program_shaper,
+ .acquire_rmu = mpcc3_acquire_rmu,
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h
+index 5198f2167c7c8..d3b904517a22d 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h
++++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h
+@@ -1007,6 +1007,13 @@ void dcn30_mpc_construct(struct dcn30_mpc *mpc30,
+ int num_mpcc,
+ int num_rmu);
+
++void mpc3_mpc_init(
++ struct mpc *mpc);
++
++void mpc3_mpc_init_single_inst(
++ struct mpc *mpc,
++ unsigned int mpcc_id);
++
+ bool mpc3_program_shaper(
+ struct mpc *mpc,
+ const struct pwl_params *params,
+@@ -1074,13 +1081,6 @@ bool mpc3_is_dwb_idle(
+ struct mpc *mpc,
+ int dwb_id);
+
+-void mpc3_set_out_rate_control(
+- struct mpc *mpc,
+- int opp_id,
+- bool enable,
+- bool rate_2x_mode,
+- struct mpc_dwb_flow_control *flow_control);
+-
+ void mpc3_power_on_ogam_lut(
+ struct mpc *mpc, int mpcc_id,
+ bool power_on);
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
+index e789e654c3870..e408e859b3556 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
+@@ -47,7 +47,7 @@ void mpc32_mpc_init(struct mpc *mpc)
+ struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc);
+ int mpcc_id;
+
+- mpc1_mpc_init(mpc);
++ mpc3_mpc_init(mpc);
+
+ if (mpc->ctx->dc->debug.enable_mem_low_power.bits.mpc) {
+ if (mpc30->mpc_mask->MPCC_MCM_SHAPER_MEM_LOW_PWR_MODE && mpc30->mpc_mask->MPCC_MCM_3DLUT_MEM_LOW_PWR_MODE) {
+@@ -991,7 +991,7 @@ static const struct mpc_funcs dcn32_mpc_funcs = {
+ .insert_plane = mpc1_insert_plane,
+ .remove_mpcc = mpc1_remove_mpcc,
+ .mpc_init = mpc32_mpc_init,
+- .mpc_init_single_inst = mpc1_mpc_init_single_inst,
++ .mpc_init_single_inst = mpc3_mpc_init_single_inst,
+ .update_blending = mpc2_update_blending,
+ .cursor_lock = mpc1_cursor_lock,
+ .get_mpcc_for_dpp = mpc1_get_mpcc_for_dpp,
+@@ -1008,7 +1008,6 @@ static const struct mpc_funcs dcn32_mpc_funcs = {
+ .set_dwb_mux = mpc3_set_dwb_mux,
+ .disable_dwb_mux = mpc3_disable_dwb_mux,
+ .is_dwb_idle = mpc3_is_dwb_idle,
+- .set_out_rate_control = mpc3_set_out_rate_control,
+ .set_gamut_remap = mpc3_set_gamut_remap,
+ .program_shaper = mpc32_program_shaper,
+ .program_3dlut = mpc32_program_3dlut,
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
+index 87760600e154d..f98def6c8c2d2 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c
+@@ -782,3 +782,9 @@ void dcn32_update_dml_pipes_odm_policy_based_on_context(struct dc *dc, struct dc
+ pipe_cnt++;
+ }
+ }
++
++void dcn32_override_min_req_dcfclk(struct dc *dc, struct dc_state *context)
++{
++ if (dcn32_subvp_in_use(dc, context) && context->bw_ctx.bw.dcn.clk.dcfclk_khz <= MIN_SUBVP_DCFCLK_KHZ)
++ context->bw_ctx.bw.dcn.clk.dcfclk_khz = MIN_SUBVP_DCFCLK_KHZ;
++}
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
+index 1ba6933d2b361..a20f28a5d2e7b 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c
+@@ -228,17 +228,13 @@ void dml2_init_socbb_params(struct dml2_context *dml2, const struct dc *in_dc, s
+ break;
+
+ case dml_project_dcn35:
++ case dml_project_dcn351:
+ out->num_chans = 4;
+ out->round_trip_ping_latency_dcfclk_cycles = 106;
+ out->smn_latency_us = 2;
+ out->dispclk_dppclk_vco_speed_mhz = 3600;
+ break;
+
+- case dml_project_dcn351:
+- out->num_chans = 16;
+- out->round_trip_ping_latency_dcfclk_cycles = 1100;
+- out->smn_latency_us = 2;
+- break;
+ }
+ /* ---Overrides if available--- */
+ if (dml2->config.bbox_overrides.dram_num_chan)
+@@ -824,13 +820,25 @@ static struct scaler_data get_scaler_data_for_plane(const struct dc_plane_state
+
+ static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned int location, const struct dc_stream_state *in)
+ {
++ dml_uint_t width, height;
++
++ if (in->timing.h_addressable > 3840)
++ width = 3840;
++ else
++ width = in->timing.h_addressable; // 4K max
++
++ if (in->timing.v_addressable > 2160)
++ height = 2160;
++ else
++ height = in->timing.v_addressable; // 4K max
++
+ out->CursorBPP[location] = dml_cur_32bit;
+ out->CursorWidth[location] = 256;
+
+ out->GPUVMMinPageSizeKBytes[location] = 256;
+
+- out->ViewportWidth[location] = in->timing.h_addressable;
+- out->ViewportHeight[location] = in->timing.v_addressable;
++ out->ViewportWidth[location] = width;
++ out->ViewportHeight[location] = height;
+ out->ViewportStationary[location] = false;
+ out->ViewportWidthChroma[location] = 0;
+ out->ViewportHeightChroma[location] = 0;
+@@ -849,7 +857,7 @@ static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned
+ out->HTapsChroma[location] = 0;
+ out->VTapsChroma[location] = 0;
+ out->SourceScan[location] = dml_rotation_0;
+- out->ScalerRecoutWidth[location] = in->timing.h_addressable;
++ out->ScalerRecoutWidth[location] = width;
+
+ out->LBBitPerPixel[location] = 57;
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c
+index 2a58a7687bdb5..72cca367062e1 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c
+@@ -703,13 +703,8 @@ static inline struct dml2_context *dml2_allocate_memory(void)
+ return (struct dml2_context *) kzalloc(sizeof(struct dml2_context), GFP_KERNEL);
+ }
+
+-bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2)
++static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2)
+ {
+- // Allocate Mode Lib Ctx
+- *dml2 = dml2_allocate_memory();
+-
+- if (!(*dml2))
+- return false;
+
+ // Store config options
+ (*dml2)->config = *config;
+@@ -737,9 +732,18 @@ bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options
+ initialize_dml2_soc_bbox(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.soc);
+
+ initialize_dml2_soc_states(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.soc, &(*dml2)->v20.dml_core_ctx.states);
++}
++
++bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2)
++{
++ // Allocate Mode Lib Ctx
++ *dml2 = dml2_allocate_memory();
++
++ if (!(*dml2))
++ return false;
++
++ dml2_init(in_dc, config, dml2);
+
+- /*Initialize DML20 instance which calls dml2_core_create, and core_dcn3_populate_informative*/
+- //dml2_initialize_instance(&(*dml_ctx)->v20.dml_init);
+ return true;
+ }
+
+@@ -779,3 +783,11 @@ bool dml2_create_copy(struct dml2_context **dst_dml2,
+
+ return true;
+ }
++
++void dml2_reinit(const struct dc *in_dc,
++ const struct dml2_configuration_options *config,
++ struct dml2_context **dml2)
++{
++
++ dml2_init(in_dc, config, dml2);
++}
+diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
+index ee0eb184eb6d7..cc662d682fd4d 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
++++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h
+@@ -214,6 +214,9 @@ void dml2_copy(struct dml2_context *dst_dml2,
+ struct dml2_context *src_dml2);
+ bool dml2_create_copy(struct dml2_context **dst_dml2,
+ struct dml2_context *src_dml2);
++void dml2_reinit(const struct dc *in_dc,
++ const struct dml2_configuration_options *config,
++ struct dml2_context **dml2);
+
+ /*
+ * dml2_validate - Determines if a display configuration is supported or not.
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+index 01493c49bd7a0..12af6bb9fead7 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
+@@ -1185,7 +1185,8 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
+ if (dccg) {
+ dccg->funcs->disable_symclk32_se(dccg, dp_hpo_inst);
+ dccg->funcs->set_dpstreamclk(dccg, REFCLK, tg->inst, dp_hpo_inst);
+- dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
++ if (dccg && dccg->funcs->set_dtbclk_dto)
++ dccg->funcs->set_dtbclk_dto(dccg, &dto_params);
+ }
+ } else if (dccg && dccg->funcs->disable_symclk_se) {
+ dccg->funcs->disable_symclk_se(dccg, stream_enc->stream_enc_inst,
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+index f614bc2806d86..c45f84aa320ef 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c
+@@ -3079,7 +3079,7 @@ void dcn10_prepare_bandwidth(
+ context,
+ false);
+
+- dc->wm_optimized_required = hubbub->funcs->program_watermarks(hubbub,
++ dc->optimized_required |= hubbub->funcs->program_watermarks(hubbub,
+ &context->bw_ctx.bw.dcn.watermarks,
+ dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
+ true);
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+index 931ac8ed7069d..868a086c72a2c 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+@@ -1392,6 +1392,11 @@ static void dcn20_detect_pipe_changes(struct dc_state *old_state,
+ return;
+ }
+
++ if (resource_is_pipe_type(new_pipe, OTG_MASTER) &&
++ resource_is_odm_topology_changed(new_pipe, old_pipe))
++ /* Detect odm changes */
++ new_pipe->update_flags.bits.odm = 1;
++
+ /* Exit on unchanged, unused pipe */
+ if (!old_pipe->plane_state && !new_pipe->plane_state)
+ return;
+@@ -1445,10 +1450,6 @@ static void dcn20_detect_pipe_changes(struct dc_state *old_state,
+
+ /* Detect top pipe only changes */
+ if (resource_is_pipe_type(new_pipe, OTG_MASTER)) {
+- /* Detect odm changes */
+- if (resource_is_odm_topology_changed(new_pipe, old_pipe))
+- new_pipe->update_flags.bits.odm = 1;
+-
+ /* Detect global sync changes */
+ if (old_pipe->pipe_dlg_param.vready_offset != new_pipe->pipe_dlg_param.vready_offset
+ || old_pipe->pipe_dlg_param.vstartup_start != new_pipe->pipe_dlg_param.vstartup_start
+@@ -1891,19 +1892,20 @@ void dcn20_program_front_end_for_ctx(
+ DC_LOGGER_INIT(dc->ctx->logger);
+ unsigned int prev_hubp_count = 0;
+ unsigned int hubp_count = 0;
++ struct pipe_ctx *pipe;
+
+ if (resource_is_pipe_topology_changed(dc->current_state, context))
+ resource_log_pipe_topology_update(dc, context);
+
+ if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
++ pipe = &context->res_ctx.pipe_ctx[i];
+
+- if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->plane_state) {
+- ASSERT(!pipe_ctx->plane_state->triplebuffer_flips);
++ if (!pipe->top_pipe && !pipe->prev_odm_pipe && pipe->plane_state) {
++ ASSERT(!pipe->plane_state->triplebuffer_flips);
+ /*turn off triple buffer for full update*/
+ dc->hwss.program_triplebuffer(
+- dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips);
++ dc, pipe, pipe->plane_state->triplebuffer_flips);
+ }
+ }
+ }
+@@ -1978,12 +1980,22 @@ void dcn20_program_front_end_for_ctx(
+ DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx);
+ }
+
++ /* update ODM for blanked OTG master pipes */
++ for (i = 0; i < dc->res_pool->pipe_count; i++) {
++ pipe = &context->res_ctx.pipe_ctx[i];
++ if (resource_is_pipe_type(pipe, OTG_MASTER) &&
++ !resource_is_pipe_type(pipe, DPP_PIPE) &&
++ pipe->update_flags.bits.odm &&
++ hws->funcs.update_odm)
++ hws->funcs.update_odm(dc, context, pipe);
++ }
++
+ /*
+ * Program all updated pipes, order matters for mpcc setup. Start with
+ * top pipe and program all pipes that follow in order
+ */
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+- struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
++ pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (pipe->plane_state && !pipe->top_pipe) {
+ while (pipe) {
+@@ -2022,17 +2034,6 @@ void dcn20_program_front_end_for_ctx(
+ context->stream_status[0].plane_count > 1) {
+ pipe->plane_res.hubp->funcs->hubp_wait_pipe_read_start(pipe->plane_res.hubp);
+ }
+-
+- /* when dynamic ODM is active, pipes must be reconfigured when all planes are
+- * disabled, as some transitions will leave software and hardware state
+- * mismatched.
+- */
+- if (dc->debug.enable_single_display_2to1_odm_policy &&
+- pipe->stream &&
+- pipe->update_flags.bits.disable &&
+- !pipe->prev_odm_pipe &&
+- hws->funcs.update_odm)
+- hws->funcs.update_odm(dc, context, pipe);
+ }
+ }
+
+@@ -2159,10 +2160,10 @@ void dcn20_prepare_bandwidth(
+ }
+
+ /* program dchubbub watermarks:
+- * For assigning wm_optimized_required, use |= operator since we don't want
++ * For assigning optimized_required, use |= operator since we don't want
+ * to clear the value if the optimize has not happened yet
+ */
+- dc->wm_optimized_required |= hubbub->funcs->program_watermarks(hubbub,
++ dc->optimized_required |= hubbub->funcs->program_watermarks(hubbub,
+ &context->bw_ctx.bw.dcn.watermarks,
+ dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
+ false);
+@@ -2175,10 +2176,10 @@ void dcn20_prepare_bandwidth(
+ if (hubbub->funcs->program_compbuf_size) {
+ if (context->bw_ctx.dml.ip.min_comp_buffer_size_kbytes) {
+ compbuf_size_kb = context->bw_ctx.dml.ip.min_comp_buffer_size_kbytes;
+- dc->wm_optimized_required |= (compbuf_size_kb != dc->current_state->bw_ctx.dml.ip.min_comp_buffer_size_kbytes);
++ dc->optimized_required |= (compbuf_size_kb != dc->current_state->bw_ctx.dml.ip.min_comp_buffer_size_kbytes);
+ } else {
+ compbuf_size_kb = context->bw_ctx.bw.dcn.compbuf_size_kb;
+- dc->wm_optimized_required |= (compbuf_size_kb != dc->current_state->bw_ctx.bw.dcn.compbuf_size_kb);
++ dc->optimized_required |= (compbuf_size_kb != dc->current_state->bw_ctx.bw.dcn.compbuf_size_kb);
+ }
+
+ hubbub->funcs->program_compbuf_size(hubbub, compbuf_size_kb, false);
+@@ -2344,7 +2345,7 @@ bool dcn20_wait_for_blank_complete(
+ int counter;
+
+ for (counter = 0; counter < 1000; counter++) {
+- if (opp->funcs->dpg_is_blanked(opp))
++ if (!opp->funcs->dpg_is_pending(opp))
+ break;
+
+ udelay(100);
+@@ -2355,7 +2356,7 @@ bool dcn20_wait_for_blank_complete(
+ return false;
+ }
+
+- return true;
++ return opp->funcs->dpg_is_blanked(opp);
+ }
+
+ bool dcn20_dmdata_status_done(struct pipe_ctx *pipe_ctx)
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+index c34c13e1e0a4e..55cf4c9e6aedf 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c
+@@ -663,10 +663,20 @@ void dcn30_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
+ if (pipe_ctx == NULL)
+ return;
+
+- if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && pipe_ctx->stream_res.stream_enc != NULL)
++ if (dc_is_hdmi_signal(pipe_ctx->stream->signal) && pipe_ctx->stream_res.stream_enc != NULL) {
+ pipe_ctx->stream_res.stream_enc->funcs->set_avmute(
+ pipe_ctx->stream_res.stream_enc,
+ enable);
++
++ /* Wait for two frame to make sure AV mute is sent out */
++ if (enable) {
++ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
++ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
++ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
++ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
++ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
++ }
++ }
+ }
+
+ void dcn30_update_info_frame(struct pipe_ctx *pipe_ctx)
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
+index 3a9cc8ac0c079..093f4387553ce 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c
+@@ -69,29 +69,6 @@
+ #define FN(reg_name, field_name) \
+ hws->shifts->field_name, hws->masks->field_name
+
+-static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
+- int opp_cnt)
+-{
+- bool hblank_halved = optc2_is_two_pixels_per_containter(&stream->timing);
+- int flow_ctrl_cnt;
+-
+- if (opp_cnt >= 2)
+- hblank_halved = true;
+-
+- flow_ctrl_cnt = stream->timing.h_total - stream->timing.h_addressable -
+- stream->timing.h_border_left -
+- stream->timing.h_border_right;
+-
+- if (hblank_halved)
+- flow_ctrl_cnt /= 2;
+-
+- /* ODM combine 4:1 case */
+- if (opp_cnt == 4)
+- flow_ctrl_cnt /= 2;
+-
+- return flow_ctrl_cnt;
+-}
+-
+ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
+ {
+ struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
+@@ -183,10 +160,6 @@ void dcn314_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx
+ struct pipe_ctx *odm_pipe;
+ int opp_cnt = 0;
+ int opp_inst[MAX_PIPES] = {0};
+- bool rate_control_2x_pclk = (pipe_ctx->stream->timing.flags.INTERLACE || optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing));
+- struct mpc_dwb_flow_control flow_control;
+- struct mpc *mpc = dc->res_pool->mpc;
+- int i;
+
+ opp_cnt = get_odm_config(pipe_ctx, opp_inst);
+
+@@ -199,20 +172,6 @@ void dcn314_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx
+ pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
+ pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
+
+- rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
+- flow_control.flow_ctrl_mode = 0;
+- flow_control.flow_ctrl_cnt0 = 0x80;
+- flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(pipe_ctx->stream, opp_cnt);
+- if (mpc->funcs->set_out_rate_control) {
+- for (i = 0; i < opp_cnt; ++i) {
+- mpc->funcs->set_out_rate_control(
+- mpc, opp_inst[i],
+- true,
+- rate_control_2x_pclk,
+- &flow_control);
+- }
+- }
+-
+ for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+ odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
+ odm_pipe->stream_res.opp,
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+index aa36d7a56ca8c..7668229438da2 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+@@ -966,29 +966,6 @@ void dcn32_init_hw(struct dc *dc)
+ }
+ }
+
+-static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
+- int opp_cnt)
+-{
+- bool hblank_halved = optc2_is_two_pixels_per_containter(&stream->timing);
+- int flow_ctrl_cnt;
+-
+- if (opp_cnt >= 2)
+- hblank_halved = true;
+-
+- flow_ctrl_cnt = stream->timing.h_total - stream->timing.h_addressable -
+- stream->timing.h_border_left -
+- stream->timing.h_border_right;
+-
+- if (hblank_halved)
+- flow_ctrl_cnt /= 2;
+-
+- /* ODM combine 4:1 case */
+- if (opp_cnt == 4)
+- flow_ctrl_cnt /= 2;
+-
+- return flow_ctrl_cnt;
+-}
+-
+ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
+ {
+ struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
+@@ -1103,10 +1080,6 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
+ struct pipe_ctx *odm_pipe;
+ int opp_cnt = 0;
+ int opp_inst[MAX_PIPES] = {0};
+- bool rate_control_2x_pclk = (pipe_ctx->stream->timing.flags.INTERLACE || optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing));
+- struct mpc_dwb_flow_control flow_control;
+- struct mpc *mpc = dc->res_pool->mpc;
+- int i;
+
+ opp_cnt = get_odm_config(pipe_ctx, opp_inst);
+
+@@ -1119,20 +1092,6 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
+ pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
+ pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
+
+- rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
+- flow_control.flow_ctrl_mode = 0;
+- flow_control.flow_ctrl_cnt0 = 0x80;
+- flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(pipe_ctx->stream, opp_cnt);
+- if (mpc->funcs->set_out_rate_control) {
+- for (i = 0; i < opp_cnt; ++i) {
+- mpc->funcs->set_out_rate_control(
+- mpc, opp_inst[i],
+- true,
+- rate_control_2x_pclk,
+- &flow_control);
+- }
+- }
+-
+ for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+ odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
+ odm_pipe->stream_res.opp,
+@@ -1156,6 +1115,13 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
+ dsc->funcs->dsc_disconnect(dsc);
+ }
+ }
++
++ if (!resource_is_pipe_type(pipe_ctx, DPP_PIPE))
++ /*
++ * blank pattern is generated by OPP, reprogram blank pattern
++ * due to OPP count change
++ */
++ dc->hwseq->funcs.blank_pixel_data(dc, pipe_ctx, true);
+ }
+
+ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div)
+@@ -1778,3 +1744,26 @@ void dcn32_prepare_bandwidth(struct dc *dc,
+ context->bw_ctx.bw.dcn.clk.p_state_change_support = p_state_change_support;
+ }
+ }
++
++void dcn32_interdependent_update_lock(struct dc *dc,
++ struct dc_state *context, bool lock)
++{
++ unsigned int i;
++ struct pipe_ctx *pipe;
++ struct timing_generator *tg;
++
++ for (i = 0; i < dc->res_pool->pipe_count; i++) {
++ pipe = &context->res_ctx.pipe_ctx[i];
++ tg = pipe->stream_res.tg;
++
++ if (!resource_is_pipe_type(pipe, OTG_MASTER) ||
++ !tg->funcs->is_tg_enabled(tg) ||
++ dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM)
++ continue;
++
++ if (lock)
++ dc->hwss.pipe_control_lock(dc, pipe, true);
++ else
++ dc->hwss.pipe_control_lock(dc, pipe, false);
++ }
++}
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h
+index 069e20bc87c0a..f55c11fc56ec7 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h
+@@ -129,4 +129,6 @@ bool dcn32_is_pipe_topology_transition_seamless(struct dc *dc,
+ void dcn32_prepare_bandwidth(struct dc *dc,
+ struct dc_state *context);
+
++void dcn32_interdependent_update_lock(struct dc *dc,
++ struct dc_state *context, bool lock);
+ #endif /* __DC_HWSS_DCN32_H__ */
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
+index e8ac94a005b83..03253faeaeac6 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c
+@@ -58,7 +58,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
+ .disable_plane = dcn20_disable_plane,
+ .disable_pixel_data = dcn20_disable_pixel_data,
+ .pipe_control_lock = dcn20_pipe_control_lock,
+- .interdependent_update_lock = dcn10_lock_all_pipes,
++ .interdependent_update_lock = dcn32_interdependent_update_lock,
+ .cursor_lock = dcn10_cursor_lock,
+ .prepare_bandwidth = dcn32_prepare_bandwidth,
+ .optimize_bandwidth = dcn20_optimize_bandwidth,
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+index 8b6c49622f3b6..1e67374b89978 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+@@ -358,29 +358,6 @@ void dcn35_init_hw(struct dc *dc)
+ }
+ }
+
+-static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
+- int opp_cnt)
+-{
+- bool hblank_halved = optc2_is_two_pixels_per_containter(&stream->timing);
+- int flow_ctrl_cnt;
+-
+- if (opp_cnt >= 2)
+- hblank_halved = true;
+-
+- flow_ctrl_cnt = stream->timing.h_total - stream->timing.h_addressable -
+- stream->timing.h_border_left -
+- stream->timing.h_border_right;
+-
+- if (hblank_halved)
+- flow_ctrl_cnt /= 2;
+-
+- /* ODM combine 4:1 case */
+- if (opp_cnt == 4)
+- flow_ctrl_cnt /= 2;
+-
+- return flow_ctrl_cnt;
+-}
+-
+ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
+ {
+ struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
+@@ -474,10 +451,6 @@ void dcn35_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
+ struct pipe_ctx *odm_pipe;
+ int opp_cnt = 0;
+ int opp_inst[MAX_PIPES] = {0};
+- bool rate_control_2x_pclk = (pipe_ctx->stream->timing.flags.INTERLACE || optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing));
+- struct mpc_dwb_flow_control flow_control;
+- struct mpc *mpc = dc->res_pool->mpc;
+- int i;
+
+ opp_cnt = get_odm_config(pipe_ctx, opp_inst);
+
+@@ -490,20 +463,6 @@ void dcn35_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
+ pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
+ pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
+
+- rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
+- flow_control.flow_ctrl_mode = 0;
+- flow_control.flow_ctrl_cnt0 = 0x80;
+- flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(pipe_ctx->stream, opp_cnt);
+- if (mpc->funcs->set_out_rate_control) {
+- for (i = 0; i < opp_cnt; ++i) {
+- mpc->funcs->set_out_rate_control(
+- mpc, opp_inst[i],
+- true,
+- rate_control_2x_pclk,
+- &flow_control);
+- }
+- }
+-
+ for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
+ odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
+ odm_pipe->stream_res.opp,
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
+index 7617fabbd16ee..0717920812d86 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h
+@@ -321,6 +321,9 @@ struct opp_funcs {
+ bool (*dpg_is_blanked)(
+ struct output_pixel_processor *opp);
+
++ bool (*dpg_is_pending)(struct output_pixel_processor *opp);
++
++
+ void (*opp_dpg_set_blank_color)(
+ struct output_pixel_processor *opp,
+ const struct tg_color *color);
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+index 9a00a99317b29..cad3e5f148cf5 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+@@ -333,6 +333,7 @@ struct timing_generator_funcs {
+
+ void (*init_odm)(struct timing_generator *tg);
+ void (*wait_drr_doublebuffer_pending_clear)(struct timing_generator *tg);
++ void (*wait_odm_doublebuffer_pending_clear)(struct timing_generator *tg);
+ };
+
+ #endif
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/link.h b/drivers/gpu/drm/amd/display/dc/inc/link.h
+index 26fe81f213da5..bf29fc58ea6a6 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/link.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/link.h
+@@ -285,12 +285,12 @@ struct link_service {
+ enum replay_FW_Message_type msg,
+ union dmub_replay_cmd_set *cmd_data);
+ bool (*edp_set_coasting_vtotal)(
+- struct dc_link *link, uint16_t coasting_vtotal);
++ struct dc_link *link, uint32_t coasting_vtotal);
+ bool (*edp_replay_residency)(const struct dc_link *link,
+ unsigned int *residency, const bool is_start,
+ const bool is_alpm);
+ bool (*edp_set_replay_power_opt_and_coasting_vtotal)(struct dc_link *link,
+- const unsigned int *power_opts, uint16_t coasting_vtotal);
++ const unsigned int *power_opts, uint32_t coasting_vtotal);
+
+ bool (*edp_wait_for_t12)(struct dc_link *link);
+ bool (*edp_is_ilr_optimization_required)(struct dc_link *link,
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+index f1489f4a40c12..d01b77fb9811a 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c
+@@ -1034,7 +1034,7 @@ bool edp_send_replay_cmd(struct dc_link *link,
+ return true;
+ }
+
+-bool edp_set_coasting_vtotal(struct dc_link *link, uint16_t coasting_vtotal)
++bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal)
+ {
+ struct dc *dc = link->ctx->dc;
+ struct dmub_replay *replay = dc->res_pool->replay;
+@@ -1073,7 +1073,7 @@ bool edp_replay_residency(const struct dc_link *link,
+ }
+
+ bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link,
+- const unsigned int *power_opts, uint16_t coasting_vtotal)
++ const unsigned int *power_opts, uint32_t coasting_vtotal)
+ {
+ struct dc *dc = link->ctx->dc;
+ struct dmub_replay *replay = dc->res_pool->replay;
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
+index 34e521af7bb48..a158c6234d422 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h
+@@ -59,12 +59,12 @@ bool edp_setup_replay(struct dc_link *link,
+ bool edp_send_replay_cmd(struct dc_link *link,
+ enum replay_FW_Message_type msg,
+ union dmub_replay_cmd_set *cmd_data);
+-bool edp_set_coasting_vtotal(struct dc_link *link, uint16_t coasting_vtotal);
++bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal);
+ bool edp_replay_residency(const struct dc_link *link,
+ unsigned int *residency, const bool is_start, const bool is_alpm);
+ bool edp_get_replay_state(const struct dc_link *link, uint64_t *state);
+ bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link,
+- const unsigned int *power_opts, uint16_t coasting_vtotal);
++ const unsigned int *power_opts, uint32_t coasting_vtotal);
+ bool edp_wait_for_t12(struct dc_link *link);
+ bool edp_is_ilr_optimization_required(struct dc_link *link,
+ struct dc_crtc_timing *crtc_timing);
+diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
+index ab81594a7fadc..6c2e84d3967fc 100644
+--- a/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
++++ b/drivers/gpu/drm/amd/display/dc/optc/dcn10/dcn10_optc.h
+@@ -557,7 +557,8 @@ struct dcn_optc_registers {
+ type OTG_CRC_DATA_STREAM_SPLIT_MODE;\
+ type OTG_CRC_DATA_FORMAT;\
+ type OTG_V_TOTAL_LAST_USED_BY_DRR;\
+- type OTG_DRR_TIMING_DBUF_UPDATE_PENDING;
++ type OTG_DRR_TIMING_DBUF_UPDATE_PENDING;\
++ type OTG_H_TIMING_DIV_MODE_DB_UPDATE_PENDING;
+
+ #define TG_REG_FIELD_LIST_DCN3_2(type) \
+ type OTG_H_TIMING_DIV_MODE_MANUAL;
+diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
+index 8234935433254..f07a4c7e48bc2 100644
+--- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
++++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
+@@ -122,6 +122,13 @@ void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combi
+ }
+ }
+
++void optc32_wait_odm_doublebuffer_pending_clear(struct timing_generator *tg)
++{
++ struct optc *optc1 = DCN10TG_FROM_TG(tg);
++
++ REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, OTG_H_TIMING_DIV_MODE_DB_UPDATE_PENDING, 0, 2, 50000);
++}
++
+ void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool manual_mode)
+ {
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+@@ -345,6 +352,7 @@ static struct timing_generator_funcs dcn32_tg_funcs = {
+ .set_odm_bypass = optc32_set_odm_bypass,
+ .set_odm_combine = optc32_set_odm_combine,
+ .get_odm_combine_segments = optc32_get_odm_combine_segments,
++ .wait_odm_doublebuffer_pending_clear = optc32_wait_odm_doublebuffer_pending_clear,
+ .set_h_timing_div_manual_mode = optc32_set_h_timing_div_manual_mode,
+ .get_optc_source = optc2_get_optc_source,
+ .set_out_mux = optc3_set_out_mux,
+diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
+index 8ce3b178cab06..0c2c146955619 100644
+--- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
++++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.h
+@@ -183,5 +183,6 @@ void optc32_set_h_timing_div_manual_mode(struct timing_generator *optc, bool man
+ void optc32_get_odm_combine_segments(struct timing_generator *tg, int *odm_combine_segments);
+ void optc32_set_odm_bypass(struct timing_generator *optc,
+ const struct dc_crtc_timing *dc_crtc_timing);
++void optc32_wait_odm_doublebuffer_pending_clear(struct timing_generator *tg);
+
+ #endif /* __DC_OPTC_DCN32_H__ */
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+index 6f10052caeef0..9042378fa8dfb 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+@@ -1771,6 +1771,7 @@ static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_val
+ dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);
+
+ dcn32_override_min_req_memclk(dc, context);
++ dcn32_override_min_req_dcfclk(dc, context);
+
+ BW_VAL_TRACE_END_WATERMARKS();
+
+@@ -1930,6 +1931,8 @@ static void dcn32_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw
+ {
+ DC_FP_START();
+ dcn32_update_bw_bounding_box_fpu(dc, bw_params);
++ if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2)
++ dml2_reinit(dc, &dc->dml2_options, &dc->current_state->bw_ctx.dml2);
+ DC_FP_END();
+ }
+
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h
+index 0c87b0fabba7d..2258c5c7212d8 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h
+@@ -42,6 +42,7 @@
+ #define SUBVP_ACTIVE_MARGIN_LIST_LEN 2
+ #define DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ 1800
+ #define DCN3_2_VMIN_DISPCLK_HZ 717000000
++#define MIN_SUBVP_DCFCLK_KHZ 400000
+
+ #define TO_DCN32_RES_POOL(pool)\
+ container_of(pool, struct dcn32_resource_pool, base)
+@@ -181,6 +182,8 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int
+
+ void dcn32_update_dml_pipes_odm_policy_based_on_context(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes);
+
++void dcn32_override_min_req_dcfclk(struct dc *dc, struct dc_state *context);
++
+ /* definitions for run time init of reg offsets */
+
+ /* CLK SRC */
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
+index 74412e5f03fef..f4dd6443a3551 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
+@@ -1581,6 +1581,8 @@ static void dcn321_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b
+ {
+ DC_FP_START();
+ dcn321_update_bw_bounding_box_fpu(dc, bw_params);
++ if (dc->debug.using_dml2 && dc->current_state && dc->current_state->bw_ctx.dml2)
++ dml2_reinit(dc, &dc->dml2_options, &dc->current_state->bw_ctx.dml2);
+ DC_FP_END();
+ }
+
+diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+index e699731ee68e9..bb1f69a54c148 100644
+--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
++++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+@@ -3133,6 +3133,14 @@ struct dmub_cmd_replay_set_coasting_vtotal_data {
+ * Currently the support is only for 0 or 1
+ */
+ uint8_t panel_inst;
++ /**
++ * 16-bit value dicated by driver that indicates the coasting vtotal high byte part.
++ */
++ uint16_t coasting_vtotal_high;
++ /**
++ * Explicit padding to 4 byte boundary.
++ */
++ uint8_t pad[2];
+ };
+
+ /**
+diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
+index 8c137d7c032e1..7c9805705fd38 100644
+--- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
++++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c
+@@ -513,6 +513,9 @@ enum mod_hdcp_status mod_hdcp_hdcp2_create_session(struct mod_hdcp *hdcp)
+ hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf;
+ memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory));
+
++ if (!display)
++ return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND;
++
+ hdcp_cmd->in_msg.hdcp2_create_session_v2.display_handle = display->index;
+
+ if (hdcp->connection.link.adjust.hdcp2.force_type == MOD_HDCP_FORCE_TYPE_0)
+diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+index 738ee763f24a5..84f9b412a4f11 100644
+--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
++++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+@@ -147,15 +147,12 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
+ }
+
+ /* VSC packet set to 4 for PSR-SU, or 2 for PSR1 */
+- if (stream->link->psr_settings.psr_feature_enabled) {
+- if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1)
+- vsc_packet_revision = vsc_packet_rev4;
+- else if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_1)
+- vsc_packet_revision = vsc_packet_rev2;
+- }
+-
+- if (stream->link->replay_settings.config.replay_supported)
++ if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1)
++ vsc_packet_revision = vsc_packet_rev4;
++ else if (stream->link->replay_settings.config.replay_supported)
+ vsc_packet_revision = vsc_packet_rev4;
++ else if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_1)
++ vsc_packet_revision = vsc_packet_rev2;
+
+ /* Update to revision 5 for extended colorimetry support */
+ if (stream->use_vsc_sdp_for_colorimetry)
+diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
+index e304e8435fb8f..2a3698fd2dc24 100644
+--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
++++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
+@@ -975,7 +975,7 @@ bool psr_su_set_dsc_slice_height(struct dc *dc, struct dc_link *link,
+
+ void set_replay_coasting_vtotal(struct dc_link *link,
+ enum replay_coasting_vtotal_type type,
+- uint16_t vtotal)
++ uint32_t vtotal)
+ {
+ link->replay_settings.coasting_vtotal_table[type] = vtotal;
+ }
+diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
+index bef4815e1703d..ff7e6f3cd6be2 100644
+--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
++++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h
+@@ -56,7 +56,7 @@ bool dmub_init_abm_config(struct resource_pool *res_pool,
+ void init_replay_config(struct dc_link *link, struct replay_config *pr_config);
+ void set_replay_coasting_vtotal(struct dc_link *link,
+ enum replay_coasting_vtotal_type type,
+- uint16_t vtotal);
++ uint32_t vtotal);
+ void set_replay_ips_full_screen_video_src_vtotal(struct dc_link *link, uint16_t vtotal);
+ void calculate_replay_link_off_frame_count(struct dc_link *link,
+ uint16_t vtotal, uint16_t htotal);
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+index 1d96eb274d72d..40ba7227cca58 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+@@ -1285,8 +1285,9 @@ static int arcturus_get_power_limit(struct smu_context *smu,
+ {
+ struct smu_11_0_powerplay_table *powerplay_table =
+ (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
++ struct smu_11_0_overdrive_table *od_settings = smu->od_settings;
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+- uint32_t power_limit, od_percent_upper, od_percent_lower;
++ uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
+
+ if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
+ /* the last hope to figure out the ppt limit */
+@@ -1303,12 +1304,16 @@ static int arcturus_get_power_limit(struct smu_context *smu,
+ if (default_power_limit)
+ *default_power_limit = power_limit;
+
+- if (smu->od_enabled)
+- od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
+- else
+- od_percent_upper = 0;
+-
+- od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
++ if (powerplay_table) {
++ if (smu->od_enabled &&
++ od_settings->cap[SMU_11_0_ODCAP_POWER_LIMIT]) {
++ od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
++ od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
++ } else if (od_settings->cap[SMU_11_0_ODCAP_POWER_LIMIT]) {
++ od_percent_upper = 0;
++ od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
++ }
++ }
+
+ dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
+ od_percent_upper, od_percent_lower, power_limit);
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+index ed189a3878ebe..836b1df799286 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+@@ -2339,7 +2339,7 @@ static int navi10_get_power_limit(struct smu_context *smu,
+ (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table;
+ struct smu_11_0_overdrive_table *od_settings = smu->od_settings;
+ PPTable_t *pptable = smu->smu_table.driver_pptable;
+- uint32_t power_limit, od_percent_upper, od_percent_lower;
++ uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
+
+ if (smu_v11_0_get_current_power_limit(smu, &power_limit)) {
+ /* the last hope to figure out the ppt limit */
+@@ -2356,13 +2356,16 @@ static int navi10_get_power_limit(struct smu_context *smu,
+ if (default_power_limit)
+ *default_power_limit = power_limit;
+
+- if (smu->od_enabled &&
+- navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT))
+- od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
+- else
+- od_percent_upper = 0;
+-
+- od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
++ if (powerplay_table) {
++ if (smu->od_enabled &&
++ navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) {
++ od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
++ od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
++ } else if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) {
++ od_percent_upper = 0;
++ od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_ODSETTING_POWERPERCENTAGE]);
++ }
++ }
+
+ dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
+ od_percent_upper, od_percent_lower, power_limit);
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+index e2ad2b972ab0b..1f18b61884f3f 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+@@ -617,6 +617,12 @@ static uint32_t sienna_cichlid_get_throttler_status_locked(struct smu_context *s
+ return throttler_status;
+ }
+
++static bool sienna_cichlid_is_od_feature_supported(struct smu_11_0_7_overdrive_table *od_table,
++ enum SMU_11_0_7_ODFEATURE_CAP cap)
++{
++ return od_table->cap[cap];
++}
++
+ static int sienna_cichlid_get_power_limit(struct smu_context *smu,
+ uint32_t *current_power_limit,
+ uint32_t *default_power_limit,
+@@ -625,7 +631,8 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu,
+ {
+ struct smu_11_0_7_powerplay_table *powerplay_table =
+ (struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table;
+- uint32_t power_limit, od_percent_upper, od_percent_lower;
++ struct smu_11_0_7_overdrive_table *od_settings = smu->od_settings;
++ uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
+ uint16_t *table_member;
+
+ GET_PPTABLE_MEMBER(SocketPowerLimitAc, &table_member);
+@@ -640,12 +647,16 @@ static int sienna_cichlid_get_power_limit(struct smu_context *smu,
+ if (default_power_limit)
+ *default_power_limit = power_limit;
+
+- if (smu->od_enabled)
+- od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
+- else
+- od_percent_upper = 0;
+-
+- od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
++ if (powerplay_table) {
++ if (smu->od_enabled &&
++ sienna_cichlid_is_od_feature_supported(od_settings, SMU_11_0_7_ODCAP_POWER_LIMIT)) {
++ od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
++ od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
++ } else if ((sienna_cichlid_is_od_feature_supported(od_settings, SMU_11_0_7_ODCAP_POWER_LIMIT))) {
++ od_percent_upper = 0;
++ od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]);
++ }
++ }
+
+ dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
+ od_percent_upper, od_percent_lower, power_limit);
+@@ -1250,12 +1261,6 @@ static bool sienna_cichlid_is_support_fine_grained_dpm(struct smu_context *smu,
+ return dpm_desc->SnapToDiscrete == 0;
+ }
+
+-static bool sienna_cichlid_is_od_feature_supported(struct smu_11_0_7_overdrive_table *od_table,
+- enum SMU_11_0_7_ODFEATURE_CAP cap)
+-{
+- return od_table->cap[cap];
+-}
+-
+ static void sienna_cichlid_get_od_setting_range(struct smu_11_0_7_overdrive_table *od_table,
+ enum SMU_11_0_7_ODSETTING_ID setting,
+ uint32_t *min, uint32_t *max)
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+index 9b80f18ea6c35..9c03296f92cdd 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+@@ -2356,7 +2356,7 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
+ (struct smu_13_0_0_powerplay_table *)table_context->power_play_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+ SkuTable_t *skutable = &pptable->SkuTable;
+- uint32_t power_limit, od_percent_upper, od_percent_lower;
++ uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
+ uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
+
+ if (smu_v13_0_get_current_power_limit(smu, &power_limit))
+@@ -2369,12 +2369,16 @@ static int smu_v13_0_0_get_power_limit(struct smu_context *smu,
+ if (default_power_limit)
+ *default_power_limit = power_limit;
+
+- if (smu->od_enabled)
+- od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_13_0_0_ODSETTING_POWERPERCENTAGE]);
+- else
+- od_percent_upper = 0;
+-
+- od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_13_0_0_ODSETTING_POWERPERCENTAGE]);
++ if (powerplay_table) {
++ if (smu->od_enabled &&
++ smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
++ od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_13_0_0_ODSETTING_POWERPERCENTAGE]);
++ od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_13_0_0_ODSETTING_POWERPERCENTAGE]);
++ } else if (smu_v13_0_0_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
++ od_percent_upper = 0;
++ od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_13_0_0_ODSETTING_POWERPERCENTAGE]);
++ }
++ }
+
+ dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
+ od_percent_upper, od_percent_lower, power_limit);
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+index 3dc7b60cb0754..7318964f1f148 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+@@ -2320,7 +2320,7 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
+ (struct smu_13_0_7_powerplay_table *)table_context->power_play_table;
+ PPTable_t *pptable = table_context->driver_pptable;
+ SkuTable_t *skutable = &pptable->SkuTable;
+- uint32_t power_limit, od_percent_upper, od_percent_lower;
++ uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
+ uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
+
+ if (smu_v13_0_get_current_power_limit(smu, &power_limit))
+@@ -2333,12 +2333,16 @@ static int smu_v13_0_7_get_power_limit(struct smu_context *smu,
+ if (default_power_limit)
+ *default_power_limit = power_limit;
+
+- if (smu->od_enabled)
+- od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
+- else
+- od_percent_upper = 0;
+-
+- od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
++ if (powerplay_table) {
++ if (smu->od_enabled &&
++ (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT))) {
++ od_percent_upper = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
++ od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
++ } else if (smu_v13_0_7_is_od_feature_supported(smu, PP_OD_FEATURE_PPT_BIT)) {
++ od_percent_upper = 0;
++ od_percent_lower = le32_to_cpu(powerplay_table->overdrive_table.min[SMU_13_0_7_ODSETTING_POWERPERCENTAGE]);
++ }
++ }
+
+ dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
+ od_percent_upper, od_percent_lower, power_limit);
+diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+index 273157428c827..97d4af3d13653 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+@@ -440,26 +440,24 @@ lt8912_connector_mode_valid(struct drm_connector *connector,
+
+ static int lt8912_connector_get_modes(struct drm_connector *connector)
+ {
+- struct edid *edid;
+- int ret = -1;
+- int num = 0;
++ const struct drm_edid *drm_edid;
+ struct lt8912 *lt = connector_to_lt8912(connector);
+ u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
++ int ret, num;
+
+- edid = drm_bridge_get_edid(lt->hdmi_port, connector);
+- if (edid) {
+- drm_connector_update_edid_property(connector, edid);
+- num = drm_add_edid_modes(connector, edid);
+- } else {
+- return ret;
+- }
++ drm_edid = drm_bridge_edid_read(lt->hdmi_port, connector);
++ drm_edid_connector_update(connector, drm_edid);
++ if (!drm_edid)
++ return 0;
++
++ num = drm_edid_connector_add_modes(connector);
+
+ ret = drm_display_info_set_bus_formats(&connector->display_info,
+ &bus_format, 1);
+- if (ret)
+- num = ret;
++ if (ret < 0)
++ num = 0;
+
+- kfree(edid);
++ drm_edid_free(drm_edid);
+ return num;
+ }
+
+diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
+index b1ca3a1100dab..26c188ce5f1c3 100644
+--- a/drivers/gpu/drm/display/drm_dp_helper.c
++++ b/drivers/gpu/drm/display/drm_dp_helper.c
+@@ -3982,6 +3982,13 @@ int drm_dp_bw_overhead(int lane_count, int hactive,
+ u32 overhead = 1000000;
+ int symbol_cycles;
+
++ if (lane_count == 0 || hactive == 0 || bpp_x16 == 0) {
++ DRM_DEBUG_KMS("Invalid BW overhead params: lane_count %d, hactive %d, bpp_x16 %d.%04d\n",
++ lane_count, hactive,
++ bpp_x16 >> 4, (bpp_x16 & 0xf) * 625);
++ return 0;
++ }
++
+ /*
+ * DP Standard v2.1 2.6.4.1
+ * SSC downspread and ref clock variation margin:
+diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
+index cee3188adf3d5..4f6f8c662d3fe 100644
+--- a/drivers/gpu/drm/drm_bridge.c
++++ b/drivers/gpu/drm/drm_bridge.c
+@@ -27,8 +27,9 @@
+ #include <linux/mutex.h>
+
+ #include <drm/drm_atomic_state_helper.h>
+-#include <drm/drm_debugfs.h>
+ #include <drm/drm_bridge.h>
++#include <drm/drm_debugfs.h>
++#include <drm/drm_edid.h>
+ #include <drm/drm_encoder.h>
+ #include <drm/drm_file.h>
+ #include <drm/drm_of.h>
+@@ -1206,6 +1207,47 @@ int drm_bridge_get_modes(struct drm_bridge *bridge,
+ }
+ EXPORT_SYMBOL_GPL(drm_bridge_get_modes);
+
++/**
++ * drm_bridge_edid_read - read the EDID data of the connected display
++ * @bridge: bridge control structure
++ * @connector: the connector to read EDID for
++ *
++ * If the bridge supports output EDID retrieval, as reported by the
++ * DRM_BRIDGE_OP_EDID bridge ops flag, call &drm_bridge_funcs.edid_read to get
++ * the EDID and return it. Otherwise return NULL.
++ *
++ * If &drm_bridge_funcs.edid_read is not set, fall back to using
++ * drm_bridge_get_edid() and wrapping it in struct drm_edid.
++ *
++ * RETURNS:
++ * The retrieved EDID on success, or NULL otherwise.
++ */
++const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge,
++ struct drm_connector *connector)
++{
++ if (!(bridge->ops & DRM_BRIDGE_OP_EDID))
++ return NULL;
++
++ /* Transitional: Fall back to ->get_edid. */
++ if (!bridge->funcs->edid_read) {
++ const struct drm_edid *drm_edid;
++ struct edid *edid;
++
++ edid = drm_bridge_get_edid(bridge, connector);
++ if (!edid)
++ return NULL;
++
++ drm_edid = drm_edid_alloc(edid, (edid->extensions + 1) * EDID_LENGTH);
++
++ kfree(edid);
++
++ return drm_edid;
++ }
++
++ return bridge->funcs->edid_read(bridge, connector);
++}
++EXPORT_SYMBOL_GPL(drm_bridge_edid_read);
++
+ /**
+ * drm_bridge_get_edid - get the EDID data of the connected display
+ * @bridge: bridge control structure
+@@ -1215,6 +1257,8 @@ EXPORT_SYMBOL_GPL(drm_bridge_get_modes);
+ * DRM_BRIDGE_OP_EDID bridge ops flag, call &drm_bridge_funcs.get_edid to
+ * get the EDID and return it. Otherwise return NULL.
+ *
++ * Deprecated. Prefer using drm_bridge_edid_read().
++ *
+ * RETURNS:
+ * The retrieved EDID on success, or NULL otherwise.
+ */
+diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
+index e814020bbcd3b..cfbe020de54e0 100644
+--- a/drivers/gpu/drm/drm_panel.c
++++ b/drivers/gpu/drm/drm_panel.c
+@@ -274,19 +274,24 @@ EXPORT_SYMBOL(drm_panel_disable);
+ * The modes probed from the panel are automatically added to the connector
+ * that the panel is attached to.
+ *
+- * Return: The number of modes available from the panel on success or a
+- * negative error code on failure.
++ * Return: The number of modes available from the panel on success, or 0 on
++ * failure (no modes).
+ */
+ int drm_panel_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+ {
+ if (!panel)
+- return -EINVAL;
++ return 0;
+
+- if (panel->funcs && panel->funcs->get_modes)
+- return panel->funcs->get_modes(panel, connector);
++ if (panel->funcs && panel->funcs->get_modes) {
++ int num;
+
+- return -EOPNOTSUPP;
++ num = panel->funcs->get_modes(panel, connector);
++ if (num > 0)
++ return num;
++ }
++
++ return 0;
+ }
+ EXPORT_SYMBOL(drm_panel_get_modes);
+
+diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
+index 23b4e9a3361d8..744cde9db246b 100644
+--- a/drivers/gpu/drm/drm_probe_helper.c
++++ b/drivers/gpu/drm/drm_probe_helper.c
+@@ -419,6 +419,13 @@ static int drm_helper_probe_get_modes(struct drm_connector *connector)
+
+ count = connector_funcs->get_modes(connector);
+
++ /* The .get_modes() callback should not return negative values. */
++ if (count < 0) {
++ drm_err(connector->dev, ".get_modes() returned %pe\n",
++ ERR_PTR(count));
++ count = 0;
++ }
++
+ /*
+ * Fallback for when DDC probe failed in drm_get_edid() and thus skipped
+ * override/firmware EDID.
+diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+index 6228ce6032482..9a2965741dab3 100644
+--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
++++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+@@ -494,7 +494,7 @@ static const struct drm_driver etnaviv_drm_driver = {
+ .desc = "etnaviv DRM",
+ .date = "20151214",
+ .major = 1,
+- .minor = 3,
++ .minor = 4,
+ };
+
+ /*
+diff --git a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c
+index 67201242438be..8665f2658d51b 100644
+--- a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c
++++ b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c
+@@ -265,6 +265,9 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
+ bool etnaviv_fill_identity_from_hwdb(struct etnaviv_gpu *gpu)
+ {
+ struct etnaviv_chip_identity *ident = &gpu->identity;
++ const u32 product_id = ident->product_id;
++ const u32 customer_id = ident->customer_id;
++ const u32 eco_id = ident->eco_id;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(etnaviv_chip_identities); i++) {
+@@ -278,6 +281,12 @@ bool etnaviv_fill_identity_from_hwdb(struct etnaviv_gpu *gpu)
+ etnaviv_chip_identities[i].eco_id == ~0U)) {
+ memcpy(ident, &etnaviv_chip_identities[i],
+ sizeof(*ident));
++
++ /* Restore some id values as ~0U aka 'don't care' might been used. */
++ ident->product_id = product_id;
++ ident->customer_id = customer_id;
++ ident->eco_id = eco_id;
++
+ return true;
+ }
+ }
+diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+index 00382f28748ac..f5bbba9ad2252 100644
+--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
++++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+@@ -316,14 +316,14 @@ static int vidi_get_modes(struct drm_connector *connector)
+ */
+ if (!ctx->raw_edid) {
+ DRM_DEV_DEBUG_KMS(ctx->dev, "raw_edid is null.\n");
+- return -EFAULT;
++ return 0;
+ }
+
+ edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
+ edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
+ if (!edid) {
+ DRM_DEV_DEBUG_KMS(ctx->dev, "failed to allocate edid\n");
+- return -ENOMEM;
++ return 0;
+ }
+
+ drm_connector_update_edid_property(connector, edid);
+diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
+index 43bed6cbaaea0..b1d02dec3774d 100644
+--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
++++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
+@@ -887,11 +887,11 @@ static int hdmi_get_modes(struct drm_connector *connector)
+ int ret;
+
+ if (!hdata->ddc_adpt)
+- return -ENODEV;
++ return 0;
+
+ edid = drm_get_edid(connector, hdata->ddc_adpt);
+ if (!edid)
+- return -ENODEV;
++ return 0;
+
+ hdata->dvi_mode = !connector->display_info.is_hdmi;
+ DRM_DEV_DEBUG_KMS(hdata->dev, "%s : width[%d] x height[%d]\n",
+diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
+index eda4a8b885904..ac456a2275dba 100644
+--- a/drivers/gpu/drm/i915/display/icl_dsi.c
++++ b/drivers/gpu/drm/i915/display/icl_dsi.c
+@@ -1155,7 +1155,6 @@ static void gen11_dsi_powerup_panel(struct intel_encoder *encoder)
+ }
+
+ intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_INIT_OTP);
+- intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON);
+
+ /* ensure all panel commands dispatched before enabling transcoder */
+ wait_for_cmds_dispatched_to_panel(encoder);
+@@ -1256,6 +1255,8 @@ static void gen11_dsi_enable(struct intel_atomic_state *state,
+ /* step6d: enable dsi transcoder */
+ gen11_dsi_enable_transcoder(encoder);
+
++ intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_DISPLAY_ON);
++
+ /* step7: enable backlight */
+ intel_backlight_enable(crtc_state, conn_state);
+ intel_dsi_vbt_exec_sequence(intel_dsi, MIPI_SEQ_BACKLIGHT_ON);
+diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
+index aa169b0055e97..eb9835d48d019 100644
+--- a/drivers/gpu/drm/i915/display/intel_bios.c
++++ b/drivers/gpu/drm/i915/display/intel_bios.c
+@@ -1952,16 +1952,12 @@ static int get_init_otp_deassert_fragment_len(struct drm_i915_private *i915,
+ * these devices we split the init OTP sequence into a deassert sequence and
+ * the actual init OTP part.
+ */
+-static void fixup_mipi_sequences(struct drm_i915_private *i915,
+- struct intel_panel *panel)
++static void vlv_fixup_mipi_sequences(struct drm_i915_private *i915,
++ struct intel_panel *panel)
+ {
+ u8 *init_otp;
+ int len;
+
+- /* Limit this to VLV for now. */
+- if (!IS_VALLEYVIEW(i915))
+- return;
+-
+ /* Limit this to v1 vid-mode sequences */
+ if (panel->vbt.dsi.config->is_cmd_mode ||
+ panel->vbt.dsi.seq_version != 1)
+@@ -1997,6 +1993,41 @@ static void fixup_mipi_sequences(struct drm_i915_private *i915,
+ panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] = init_otp + len - 1;
+ }
+
++/*
++ * Some machines (eg. Lenovo 82TQ) appear to have broken
++ * VBT sequences:
++ * - INIT_OTP is not present at all
++ * - what should be in INIT_OTP is in DISPLAY_ON
++ * - what should be in DISPLAY_ON is in BACKLIGHT_ON
++ * (along with the actual backlight stuff)
++ *
++ * To make those work we simply swap DISPLAY_ON and INIT_OTP.
++ *
++ * TODO: Do we need to limit this to specific machines,
++ * or examine the contents of the sequences to
++ * avoid false positives?
++ */
++static void icl_fixup_mipi_sequences(struct drm_i915_private *i915,
++ struct intel_panel *panel)
++{
++ if (!panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] &&
++ panel->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_ON]) {
++ drm_dbg_kms(&i915->drm, "Broken VBT: Swapping INIT_OTP and DISPLAY_ON sequences\n");
++
++ swap(panel->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP],
++ panel->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_ON]);
++ }
++}
++
++static void fixup_mipi_sequences(struct drm_i915_private *i915,
++ struct intel_panel *panel)
++{
++ if (DISPLAY_VER(i915) >= 11)
++ icl_fixup_mipi_sequences(i915, panel);
++ else if (IS_VALLEYVIEW(i915))
++ vlv_fixup_mipi_sequences(i915, panel);
++}
++
+ static void
+ parse_mipi_sequence(struct drm_i915_private *i915,
+ struct intel_panel *panel)
+@@ -3344,6 +3375,9 @@ bool intel_bios_encoder_supports_dp_dual_mode(const struct intel_bios_encoder_da
+ {
+ const struct child_device_config *child = &devdata->child;
+
++ if (!devdata)
++ return false;
++
+ if (!intel_bios_encoder_supports_dp(devdata) ||
+ !intel_bios_encoder_supports_hdmi(devdata))
+ return false;
+diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
+index 926e2de00eb58..2dde7ac88274d 100644
+--- a/drivers/gpu/drm/i915/display/intel_cursor.c
++++ b/drivers/gpu/drm/i915/display/intel_cursor.c
+@@ -35,12 +35,10 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state)
+ {
+ struct drm_i915_private *dev_priv =
+ to_i915(plane_state->uapi.plane->dev);
+- const struct drm_framebuffer *fb = plane_state->hw.fb;
+- struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+ u32 base;
+
+ if (DISPLAY_INFO(dev_priv)->cursor_needs_physical)
+- base = i915_gem_object_get_dma_address(obj, 0);
++ base = plane_state->phys_dma_addr;
+ else
+ base = intel_plane_ggtt_offset(plane_state);
+
+diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h
+index 99bdb833591ce..7862e7cefe027 100644
+--- a/drivers/gpu/drm/i915/display/intel_display_trace.h
++++ b/drivers/gpu/drm/i915/display/intel_display_trace.h
+@@ -411,7 +411,7 @@ TRACE_EVENT(intel_fbc_activate,
+ struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(plane->base.dev),
+ plane->pipe);
+ __assign_str(dev, __dev_name_kms(plane));
+- __assign_str(name, plane->base.name)
++ __assign_str(name, plane->base.name);
+ __entry->pipe = crtc->pipe;
+ __entry->frame = intel_crtc_get_vblank_counter(crtc);
+ __entry->scanline = intel_get_crtc_scanline(crtc);
+@@ -438,7 +438,7 @@ TRACE_EVENT(intel_fbc_deactivate,
+ struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(plane->base.dev),
+ plane->pipe);
+ __assign_str(dev, __dev_name_kms(plane));
+- __assign_str(name, plane->base.name)
++ __assign_str(name, plane->base.name);
+ __entry->pipe = crtc->pipe;
+ __entry->frame = intel_crtc_get_vblank_counter(crtc);
+ __entry->scanline = intel_get_crtc_scanline(crtc);
+@@ -465,7 +465,7 @@ TRACE_EVENT(intel_fbc_nuke,
+ struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(plane->base.dev),
+ plane->pipe);
+ __assign_str(dev, __dev_name_kms(plane));
+- __assign_str(name, plane->base.name)
++ __assign_str(name, plane->base.name);
+ __entry->pipe = crtc->pipe;
+ __entry->frame = intel_crtc_get_vblank_counter(crtc);
+ __entry->scanline = intel_get_crtc_scanline(crtc);
+diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
+index ac7fe6281afe3..9529f77b875b0 100644
+--- a/drivers/gpu/drm/i915/display/intel_display_types.h
++++ b/drivers/gpu/drm/i915/display/intel_display_types.h
+@@ -719,6 +719,7 @@ struct intel_plane_state {
+ #define PLANE_HAS_FENCE BIT(0)
+
+ struct intel_fb_view view;
++ u32 phys_dma_addr; /* for cursor_needs_physical */
+
+ /* Plane pxp decryption state */
+ bool decrypt;
+diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
+index ef57dad1a9cb7..87deb135c9ccb 100644
+--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
++++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
+@@ -2509,7 +2509,7 @@ static void icl_wrpll_params_populate(struct skl_wrpll_params *params,
+ static bool
+ ehl_combo_pll_div_frac_wa_needed(struct drm_i915_private *i915)
+ {
+- return (((IS_ELKHARTLAKE(i915) || IS_JASPERLAKE(i915)) &&
++ return ((IS_ELKHARTLAKE(i915) &&
+ IS_DISPLAY_STEP(i915, STEP_B0, STEP_FOREVER)) ||
+ IS_TIGERLAKE(i915) || IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) &&
+ i915->display.dpll.ref_clks.nssc == 38400;
+@@ -3308,6 +3308,8 @@ static int icl_compute_tc_phy_dplls(struct intel_atomic_state *state,
+ struct drm_i915_private *i915 = to_i915(state->base.dev);
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
++ const struct intel_crtc_state *old_crtc_state =
++ intel_atomic_get_old_crtc_state(state, crtc);
+ struct icl_port_dpll *port_dpll =
+ &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];
+ struct skl_wrpll_params pll_params = {};
+@@ -3326,7 +3328,11 @@ static int icl_compute_tc_phy_dplls(struct intel_atomic_state *state,
+ return ret;
+
+ /* this is mainly for the fastset check */
+- icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_MG_PHY);
++ if (old_crtc_state->shared_dpll &&
++ old_crtc_state->shared_dpll->info->id == DPLL_ID_ICL_TBTPLL)
++ icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT);
++ else
++ icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_MG_PHY);
+
+ crtc_state->port_clock = icl_ddi_mg_pll_get_freq(i915, NULL,
+ &port_dpll->hw_state);
+@@ -4023,7 +4029,8 @@ static const struct intel_shared_dpll_funcs mg_pll_funcs = {
+ static const struct dpll_info icl_plls[] = {
+ { .name = "DPLL 0", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL0, },
+ { .name = "DPLL 1", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL1, },
+- { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, },
++ { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL,
++ .flags = INTEL_DPLL_IS_ALT_PORT_DPLL, },
+ { .name = "MG PLL 1", .funcs = &mg_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, },
+ { .name = "MG PLL 2", .funcs = &mg_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, },
+ { .name = "MG PLL 3", .funcs = &mg_pll_funcs, .id = DPLL_ID_ICL_MGPLL3, },
+@@ -4068,7 +4075,8 @@ static const struct intel_shared_dpll_funcs dkl_pll_funcs = {
+ static const struct dpll_info tgl_plls[] = {
+ { .name = "DPLL 0", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL0, },
+ { .name = "DPLL 1", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL1, },
+- { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, },
++ { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL,
++ .flags = INTEL_DPLL_IS_ALT_PORT_DPLL, },
+ { .name = "TC PLL 1", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, },
+ { .name = "TC PLL 2", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, },
+ { .name = "TC PLL 3", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL3, },
+@@ -4141,7 +4149,8 @@ static const struct intel_dpll_mgr adls_pll_mgr = {
+ static const struct dpll_info adlp_plls[] = {
+ { .name = "DPLL 0", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL0, },
+ { .name = "DPLL 1", .funcs = &combo_pll_funcs, .id = DPLL_ID_ICL_DPLL1, },
+- { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL, },
++ { .name = "TBT PLL", .funcs = &tbt_pll_funcs, .id = DPLL_ID_ICL_TBTPLL,
++ .flags = INTEL_DPLL_IS_ALT_PORT_DPLL, },
+ { .name = "TC PLL 1", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL1, },
+ { .name = "TC PLL 2", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL2, },
+ { .name = "TC PLL 3", .funcs = &dkl_pll_funcs, .id = DPLL_ID_ICL_MGPLL3, },
+@@ -4465,31 +4474,29 @@ verify_single_dpll_state(struct drm_i915_private *i915,
+ struct intel_crtc *crtc,
+ const struct intel_crtc_state *new_crtc_state)
+ {
+- struct intel_dpll_hw_state dpll_hw_state;
++ struct intel_dpll_hw_state dpll_hw_state = {};
+ u8 pipe_mask;
+ bool active;
+
+- memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
+-
+- drm_dbg_kms(&i915->drm, "%s\n", pll->info->name);
+-
+ active = intel_dpll_get_hw_state(i915, pll, &dpll_hw_state);
+
+ if (!(pll->info->flags & INTEL_DPLL_ALWAYS_ON)) {
+ I915_STATE_WARN(i915, !pll->on && pll->active_mask,
+- "pll in active use but not on in sw tracking\n");
++ "%s: pll in active use but not on in sw tracking\n",
++ pll->info->name);
+ I915_STATE_WARN(i915, pll->on && !pll->active_mask,
+- "pll is on but not used by any active pipe\n");
++ "%s: pll is on but not used by any active pipe\n",
++ pll->info->name);
+ I915_STATE_WARN(i915, pll->on != active,
+- "pll on state mismatch (expected %i, found %i)\n",
+- pll->on, active);
++ "%s: pll on state mismatch (expected %i, found %i)\n",
++ pll->info->name, pll->on, active);
+ }
+
+ if (!crtc) {
+ I915_STATE_WARN(i915,
+ pll->active_mask & ~pll->state.pipe_mask,
+- "more active pll users than references: 0x%x vs 0x%x\n",
+- pll->active_mask, pll->state.pipe_mask);
++ "%s: more active pll users than references: 0x%x vs 0x%x\n",
++ pll->info->name, pll->active_mask, pll->state.pipe_mask);
+
+ return;
+ }
+@@ -4498,21 +4505,30 @@ verify_single_dpll_state(struct drm_i915_private *i915,
+
+ if (new_crtc_state->hw.active)
+ I915_STATE_WARN(i915, !(pll->active_mask & pipe_mask),
+- "pll active mismatch (expected pipe %c in active mask 0x%x)\n",
+- pipe_name(crtc->pipe), pll->active_mask);
++ "%s: pll active mismatch (expected pipe %c in active mask 0x%x)\n",
++ pll->info->name, pipe_name(crtc->pipe), pll->active_mask);
+ else
+ I915_STATE_WARN(i915, pll->active_mask & pipe_mask,
+- "pll active mismatch (didn't expect pipe %c in active mask 0x%x)\n",
+- pipe_name(crtc->pipe), pll->active_mask);
++ "%s: pll active mismatch (didn't expect pipe %c in active mask 0x%x)\n",
++ pll->info->name, pipe_name(crtc->pipe), pll->active_mask);
+
+ I915_STATE_WARN(i915, !(pll->state.pipe_mask & pipe_mask),
+- "pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n",
+- pipe_mask, pll->state.pipe_mask);
++ "%s: pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n",
++ pll->info->name, pipe_mask, pll->state.pipe_mask);
+
+ I915_STATE_WARN(i915,
+ pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state,
+ sizeof(dpll_hw_state)),
+- "pll hw state mismatch\n");
++ "%s: pll hw state mismatch\n",
++ pll->info->name);
++}
++
++static bool has_alt_port_dpll(const struct intel_shared_dpll *old_pll,
++ const struct intel_shared_dpll *new_pll)
++{
++ return old_pll && new_pll && old_pll != new_pll &&
++ (old_pll->info->flags & INTEL_DPLL_IS_ALT_PORT_DPLL ||
++ new_pll->info->flags & INTEL_DPLL_IS_ALT_PORT_DPLL);
+ }
+
+ void intel_shared_dpll_state_verify(struct intel_atomic_state *state,
+@@ -4534,11 +4550,15 @@ void intel_shared_dpll_state_verify(struct intel_atomic_state *state,
+ struct intel_shared_dpll *pll = old_crtc_state->shared_dpll;
+
+ I915_STATE_WARN(i915, pll->active_mask & pipe_mask,
+- "pll active mismatch (didn't expect pipe %c in active mask (0x%x))\n",
+- pipe_name(crtc->pipe), pll->active_mask);
+- I915_STATE_WARN(i915, pll->state.pipe_mask & pipe_mask,
+- "pll enabled crtcs mismatch (found pipe %c in enabled mask (0x%x))\n",
+- pipe_name(crtc->pipe), pll->state.pipe_mask);
++ "%s: pll active mismatch (didn't expect pipe %c in active mask (0x%x))\n",
++ pll->info->name, pipe_name(crtc->pipe), pll->active_mask);
++
++ /* TC ports have both MG/TC and TBT PLL referenced simultaneously */
++ I915_STATE_WARN(i915, !has_alt_port_dpll(old_crtc_state->shared_dpll,
++ new_crtc_state->shared_dpll) &&
++ pll->state.pipe_mask & pipe_mask,
++ "%s: pll enabled crtcs mismatch (found pipe %c in enabled mask (0x%x))\n",
++ pll->info->name, pipe_name(crtc->pipe), pll->state.pipe_mask);
+ }
+ }
+
+diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
+index 2e7ea0d8d3ffb..5cdec77cfd9d4 100644
+--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
++++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
+@@ -277,12 +277,16 @@ struct dpll_info {
+ enum intel_display_power_domain power_domain;
+
+ #define INTEL_DPLL_ALWAYS_ON (1 << 0)
++#define INTEL_DPLL_IS_ALT_PORT_DPLL (1 << 1)
+ /**
+ * @flags:
+ *
+ * INTEL_DPLL_ALWAYS_ON
+ * Inform the state checker that the DPLL is kept enabled even if
+ * not in use by any CRTC.
++ * INTEL_DPLL_IS_ALT_PORT_DPLL
++ * Inform the state checker that the DPLL can be used as a fallback
++ * (for TC->TBT fallback).
+ */
+ u32 flags;
+ };
+diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c
+index 482c28b5c2de5..54d9abeb2d8d6 100644
+--- a/drivers/gpu/drm/i915/display/intel_dsb.c
++++ b/drivers/gpu/drm/i915/display/intel_dsb.c
+@@ -340,6 +340,17 @@ static int intel_dsb_dewake_scanline(const struct intel_crtc_state *crtc_state)
+ return max(0, vblank_start - intel_usecs_to_scanlines(adjusted_mode, latency));
+ }
+
++static u32 dsb_chicken(struct intel_crtc *crtc)
++{
++ if (crtc->mode_flags & I915_MODE_FLAG_VRR)
++ return DSB_CTRL_WAIT_SAFE_WINDOW |
++ DSB_CTRL_NO_WAIT_VBLANK |
++ DSB_INST_WAIT_SAFE_WINDOW |
++ DSB_INST_NO_WAIT_VBLANK;
++ else
++ return 0;
++}
++
+ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
+ int dewake_scanline)
+ {
+@@ -361,6 +372,9 @@ static void _intel_dsb_commit(struct intel_dsb *dsb, u32 ctrl,
+ intel_de_write_fw(dev_priv, DSB_CTRL(pipe, dsb->id),
+ ctrl | DSB_ENABLE);
+
++ intel_de_write_fw(dev_priv, DSB_CHICKEN(pipe, dsb->id),
++ dsb_chicken(crtc));
++
+ intel_de_write_fw(dev_priv, DSB_HEAD(pipe, dsb->id),
+ intel_dsb_buffer_ggtt_offset(&dsb->dsb_buf));
+
+diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c b/drivers/gpu/drm/i915/display/intel_fb_pin.c
+index 7b42aef37d2f7..b6df9baf481b6 100644
+--- a/drivers/gpu/drm/i915/display/intel_fb_pin.c
++++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c
+@@ -255,6 +255,16 @@ int intel_plane_pin_fb(struct intel_plane_state *plane_state)
+ return PTR_ERR(vma);
+
+ plane_state->ggtt_vma = vma;
++
++ /*
++ * Pre-populate the dma address before we enter the vblank
++ * evade critical section as i915_gem_object_get_dma_address()
++ * will trigger might_sleep() even if it won't actually sleep,
++ * which is the case when the fb has already been pinned.
++ */
++ if (phys_cursor)
++ plane_state->phys_dma_addr =
++ i915_gem_object_get_dma_address(intel_fb_obj(fb), 0);
+ } else {
+ struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
+
+diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
+index 5d905f932cb4b..eb5bd07439020 100644
+--- a/drivers/gpu/drm/i915/display/intel_vrr.c
++++ b/drivers/gpu/drm/i915/display/intel_vrr.c
+@@ -187,10 +187,11 @@ void intel_vrr_set_transcoder_timings(const struct intel_crtc_state *crtc_state)
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+
+ /*
+- * TRANS_SET_CONTEXT_LATENCY with VRR enabled
+- * requires this chicken bit on ADL/DG2.
++ * This bit seems to have two meanings depending on the platform:
++ * TGL: generate VRR "safe window" for DSB vblank waits
++ * ADL/DG2: make TRANS_SET_CONTEXT_LATENCY effective with VRR
+ */
+- if (DISPLAY_VER(dev_priv) == 13)
++ if (IS_DISPLAY_VER(dev_priv, 12, 13))
+ intel_de_rmw(dev_priv, CHICKEN_TRANS(cpu_transcoder),
+ 0, PIPE_VBLANK_WITH_DELAY);
+
+diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c
+index 96bdb93a948d1..fb7bff27b45a3 100644
+--- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c
++++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c
+@@ -279,9 +279,6 @@ static int __engine_park(struct intel_wakeref *wf)
+ intel_engine_park_heartbeat(engine);
+ intel_breadcrumbs_park(engine->breadcrumbs);
+
+- /* Must be reset upon idling, or we may miss the busy wakeup. */
+- GEM_BUG_ON(engine->sched_engine->queue_priority_hint != INT_MIN);
+-
+ if (engine->park)
+ engine->park(engine);
+
+diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+index 42aade0faf2d1..b061a0a0d6b08 100644
+--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
++++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+@@ -3272,6 +3272,9 @@ static void execlists_park(struct intel_engine_cs *engine)
+ {
+ cancel_timer(&engine->execlists.timer);
+ cancel_timer(&engine->execlists.preempt);
++
++ /* Reset upon idling, or we may delay the busy wakeup. */
++ WRITE_ONCE(engine->sched_engine->queue_priority_hint, INT_MIN);
+ }
+
+ static void add_to_engine(struct i915_request *rq)
+diff --git a/drivers/gpu/drm/i915/i915_hwmon.c b/drivers/gpu/drm/i915/i915_hwmon.c
+index 8c3f443c8347e..b758fd110c204 100644
+--- a/drivers/gpu/drm/i915/i915_hwmon.c
++++ b/drivers/gpu/drm/i915/i915_hwmon.c
+@@ -72,12 +72,13 @@ hwm_locked_with_pm_intel_uncore_rmw(struct hwm_drvdata *ddat,
+ struct intel_uncore *uncore = ddat->uncore;
+ intel_wakeref_t wakeref;
+
+- mutex_lock(&hwmon->hwmon_lock);
++ with_intel_runtime_pm(uncore->rpm, wakeref) {
++ mutex_lock(&hwmon->hwmon_lock);
+
+- with_intel_runtime_pm(uncore->rpm, wakeref)
+ intel_uncore_rmw(uncore, reg, clear, set);
+
+- mutex_unlock(&hwmon->hwmon_lock);
++ mutex_unlock(&hwmon->hwmon_lock);
++ }
+ }
+
+ /*
+@@ -136,20 +137,21 @@ hwm_energy(struct hwm_drvdata *ddat, long *energy)
+ else
+ rgaddr = hwmon->rg.energy_status_all;
+
+- mutex_lock(&hwmon->hwmon_lock);
++ with_intel_runtime_pm(uncore->rpm, wakeref) {
++ mutex_lock(&hwmon->hwmon_lock);
+
+- with_intel_runtime_pm(uncore->rpm, wakeref)
+ reg_val = intel_uncore_read(uncore, rgaddr);
+
+- if (reg_val >= ei->reg_val_prev)
+- ei->accum_energy += reg_val - ei->reg_val_prev;
+- else
+- ei->accum_energy += UINT_MAX - ei->reg_val_prev + reg_val;
+- ei->reg_val_prev = reg_val;
++ if (reg_val >= ei->reg_val_prev)
++ ei->accum_energy += reg_val - ei->reg_val_prev;
++ else
++ ei->accum_energy += UINT_MAX - ei->reg_val_prev + reg_val;
++ ei->reg_val_prev = reg_val;
+
+- *energy = mul_u64_u32_shr(ei->accum_energy, SF_ENERGY,
+- hwmon->scl_shift_energy);
+- mutex_unlock(&hwmon->hwmon_lock);
++ *energy = mul_u64_u32_shr(ei->accum_energy, SF_ENERGY,
++ hwmon->scl_shift_energy);
++ mutex_unlock(&hwmon->hwmon_lock);
++ }
+ }
+
+ static ssize_t
+@@ -404,6 +406,7 @@ hwm_power_max_write(struct hwm_drvdata *ddat, long val)
+
+ /* Block waiting for GuC reset to complete when needed */
+ for (;;) {
++ wakeref = intel_runtime_pm_get(ddat->uncore->rpm);
+ mutex_lock(&hwmon->hwmon_lock);
+
+ prepare_to_wait(&ddat->waitq, &wait, TASK_INTERRUPTIBLE);
+@@ -417,14 +420,13 @@ hwm_power_max_write(struct hwm_drvdata *ddat, long val)
+ }
+
+ mutex_unlock(&hwmon->hwmon_lock);
++ intel_runtime_pm_put(ddat->uncore->rpm, wakeref);
+
+ schedule();
+ }
+ finish_wait(&ddat->waitq, &wait);
+ if (ret)
+- goto unlock;
+-
+- wakeref = intel_runtime_pm_get(ddat->uncore->rpm);
++ goto exit;
+
+ /* Disable PL1 limit and verify, because the limit cannot be disabled on all platforms */
+ if (val == PL1_DISABLE) {
+@@ -444,9 +446,8 @@ hwm_power_max_write(struct hwm_drvdata *ddat, long val)
+ intel_uncore_rmw(ddat->uncore, hwmon->rg.pkg_rapl_limit,
+ PKG_PWR_LIM_1_EN | PKG_PWR_LIM_1, nval);
+ exit:
+- intel_runtime_pm_put(ddat->uncore->rpm, wakeref);
+-unlock:
+ mutex_unlock(&hwmon->hwmon_lock);
++ intel_runtime_pm_put(ddat->uncore->rpm, wakeref);
+ return ret;
+ }
+
+diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
+index 27dc903f0553c..6f1c4e2a99fd2 100644
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -4597,7 +4597,7 @@
+ #define MTL_CHICKEN_TRANS(trans) _MMIO_TRANS((trans), \
+ _MTL_CHICKEN_TRANS_A, \
+ _MTL_CHICKEN_TRANS_B)
+-#define PIPE_VBLANK_WITH_DELAY REG_BIT(31) /* ADL/DG2 */
++#define PIPE_VBLANK_WITH_DELAY REG_BIT(31) /* tgl+ */
+ #define SKL_UNMASK_VBL_TO_PIPE_IN_SRD REG_BIT(30) /* skl+ */
+ #define HSW_FRAME_START_DELAY_MASK REG_GENMASK(28, 27)
+ #define HSW_FRAME_START_DELAY(x) REG_FIELD_PREP(HSW_FRAME_START_DELAY_MASK, x)
+diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
+index d09aad34ba37f..b70715b1411d6 100644
+--- a/drivers/gpu/drm/i915/i915_vma.c
++++ b/drivers/gpu/drm/i915/i915_vma.c
+@@ -34,6 +34,7 @@
+ #include "gt/intel_engine.h"
+ #include "gt/intel_engine_heartbeat.h"
+ #include "gt/intel_gt.h"
++#include "gt/intel_gt_pm.h"
+ #include "gt/intel_gt_requests.h"
+ #include "gt/intel_tlb.h"
+
+@@ -103,12 +104,42 @@ static inline struct i915_vma *active_to_vma(struct i915_active *ref)
+
+ static int __i915_vma_active(struct i915_active *ref)
+ {
+- return i915_vma_tryget(active_to_vma(ref)) ? 0 : -ENOENT;
++ struct i915_vma *vma = active_to_vma(ref);
++
++ if (!i915_vma_tryget(vma))
++ return -ENOENT;
++
++ /*
++ * Exclude global GTT VMA from holding a GT wakeref
++ * while active, otherwise GPU never goes idle.
++ */
++ if (!i915_vma_is_ggtt(vma)) {
++ /*
++ * Since we and our _retire() counterpart can be
++ * called asynchronously, storing a wakeref tracking
++ * handle inside struct i915_vma is not safe, and
++ * there is no other good place for that. Hence,
++ * use untracked variants of intel_gt_pm_get/put().
++ */
++ intel_gt_pm_get_untracked(vma->vm->gt);
++ }
++
++ return 0;
+ }
+
+ static void __i915_vma_retire(struct i915_active *ref)
+ {
+- i915_vma_put(active_to_vma(ref));
++ struct i915_vma *vma = active_to_vma(ref);
++
++ if (!i915_vma_is_ggtt(vma)) {
++ /*
++ * Since we can be called from atomic contexts,
++ * use an async variant of intel_gt_pm_put().
++ */
++ intel_gt_pm_put_async_untracked(vma->vm->gt);
++ }
++
++ i915_vma_put(vma);
+ }
+
+ static struct i915_vma *
+@@ -1404,7 +1435,7 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
+ struct i915_vma_work *work = NULL;
+ struct dma_fence *moving = NULL;
+ struct i915_vma_resource *vma_res = NULL;
+- intel_wakeref_t wakeref = 0;
++ intel_wakeref_t wakeref;
+ unsigned int bound;
+ int err;
+
+@@ -1424,8 +1455,14 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
+ if (err)
+ return err;
+
+- if (flags & PIN_GLOBAL)
+- wakeref = intel_runtime_pm_get(&vma->vm->i915->runtime_pm);
++ /*
++ * In case of a global GTT, we must hold a runtime-pm wakeref
++ * while global PTEs are updated. In other cases, we hold
++ * the rpm reference while the VMA is active. Since runtime
++ * resume may require allocations, which are forbidden inside
++ * vm->mutex, get the first rpm wakeref outside of the mutex.
++ */
++ wakeref = intel_runtime_pm_get(&vma->vm->i915->runtime_pm);
+
+ if (flags & vma->vm->bind_async_flags) {
+ /* lock VM */
+@@ -1561,8 +1598,7 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
+ if (work)
+ dma_fence_work_commit_imm(&work->base);
+ err_rpm:
+- if (wakeref)
+- intel_runtime_pm_put(&vma->vm->i915->runtime_pm, wakeref);
++ intel_runtime_pm_put(&vma->vm->i915->runtime_pm, wakeref);
+
+ if (moving)
+ dma_fence_put(moving);
+diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
+index 70349739dd89b..55dedd73f528c 100644
+--- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c
++++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
+@@ -72,14 +72,14 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector)
+ int ret;
+
+ if (!mode)
+- return -EINVAL;
++ return 0;
+
+ ret = of_get_drm_display_mode(np, &imxpd->mode,
+ &imxpd->bus_flags,
+ OF_USE_NATIVE_MODE);
+ if (ret) {
+ drm_mode_destroy(connector->dev, mode);
+- return ret;
++ return 0;
+ }
+
+ drm_mode_copy(mode, &imxpd->mode);
+diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c
+index 12feecf71e752..6fb65b01d7780 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_dmem.c
++++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c
+@@ -378,9 +378,9 @@ nouveau_dmem_evict_chunk(struct nouveau_dmem_chunk *chunk)
+ dma_addr_t *dma_addrs;
+ struct nouveau_fence *fence;
+
+- src_pfns = kcalloc(npages, sizeof(*src_pfns), GFP_KERNEL);
+- dst_pfns = kcalloc(npages, sizeof(*dst_pfns), GFP_KERNEL);
+- dma_addrs = kcalloc(npages, sizeof(*dma_addrs), GFP_KERNEL);
++ src_pfns = kvcalloc(npages, sizeof(*src_pfns), GFP_KERNEL | __GFP_NOFAIL);
++ dst_pfns = kvcalloc(npages, sizeof(*dst_pfns), GFP_KERNEL | __GFP_NOFAIL);
++ dma_addrs = kvcalloc(npages, sizeof(*dma_addrs), GFP_KERNEL | __GFP_NOFAIL);
+
+ migrate_device_range(src_pfns, chunk->pagemap.range.start >> PAGE_SHIFT,
+ npages);
+@@ -406,11 +406,11 @@ nouveau_dmem_evict_chunk(struct nouveau_dmem_chunk *chunk)
+ migrate_device_pages(src_pfns, dst_pfns, npages);
+ nouveau_dmem_fence_done(&fence);
+ migrate_device_finalize(src_pfns, dst_pfns, npages);
+- kfree(src_pfns);
+- kfree(dst_pfns);
++ kvfree(src_pfns);
++ kvfree(dst_pfns);
+ for (i = 0; i < npages; i++)
+ dma_unmap_page(chunk->drm->dev->dev, dma_addrs[i], PAGE_SIZE, DMA_BIDIRECTIONAL);
+- kfree(dma_addrs);
++ kvfree(dma_addrs);
+ }
+
+ void
+diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
+index 3c4f5a392b064..58c8161289fea 100644
+--- a/drivers/gpu/drm/scheduler/sched_entity.c
++++ b/drivers/gpu/drm/scheduler/sched_entity.c
+@@ -71,13 +71,19 @@ int drm_sched_entity_init(struct drm_sched_entity *entity,
+ entity->guilty = guilty;
+ entity->num_sched_list = num_sched_list;
+ entity->priority = priority;
++ /*
++ * It's perfectly valid to initialize an entity without having a valid
++ * scheduler attached. It's just not valid to use the scheduler before it
++ * is initialized itself.
++ */
+ entity->sched_list = num_sched_list > 1 ? sched_list : NULL;
+ RCU_INIT_POINTER(entity->last_scheduled, NULL);
+ RB_CLEAR_NODE(&entity->rb_tree_node);
+
+- if (!sched_list[0]->sched_rq) {
+- /* Warn drivers not to do this and to fix their DRM
+- * calling order.
++ if (num_sched_list && !sched_list[0]->sched_rq) {
++ /* Since every entry covered by num_sched_list
++ * should be non-NULL and therefore we warn drivers
++ * not to do this and to fix their DRM calling order.
+ */
+ pr_warn("%s: called with uninitialized scheduler\n", __func__);
+ } else if (num_sched_list) {
+diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
+index fd9fd3d15101c..0b3f4267130c4 100644
+--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
++++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
+@@ -294,7 +294,13 @@ pgprot_t ttm_io_prot(struct ttm_buffer_object *bo, struct ttm_resource *res,
+ enum ttm_caching caching;
+
+ man = ttm_manager_type(bo->bdev, res->mem_type);
+- caching = man->use_tt ? bo->ttm->caching : res->bus.caching;
++ if (man->use_tt) {
++ caching = bo->ttm->caching;
++ if (bo->ttm->page_flags & TTM_TT_FLAG_DECRYPTED)
++ tmp = pgprot_decrypted(tmp);
++ } else {
++ caching = res->bus.caching;
++ }
+
+ return ttm_prot_from_caching(caching, tmp);
+ }
+@@ -337,6 +343,8 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
+ .no_wait_gpu = false
+ };
+ struct ttm_tt *ttm = bo->ttm;
++ struct ttm_resource_manager *man =
++ ttm_manager_type(bo->bdev, bo->resource->mem_type);
+ pgprot_t prot;
+ int ret;
+
+@@ -346,7 +354,8 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
+ if (ret)
+ return ret;
+
+- if (num_pages == 1 && ttm->caching == ttm_cached) {
++ if (num_pages == 1 && ttm->caching == ttm_cached &&
++ !(man->use_tt && (ttm->page_flags & TTM_TT_FLAG_DECRYPTED))) {
+ /*
+ * We're mapping a single page, and the desired
+ * page protection is consistent with the bo.
+diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
+index e0a77671edd6c..43eaffa7faae3 100644
+--- a/drivers/gpu/drm/ttm/ttm_tt.c
++++ b/drivers/gpu/drm/ttm/ttm_tt.c
+@@ -31,11 +31,14 @@
+
+ #define pr_fmt(fmt) "[TTM] " fmt
+
++#include <linux/cc_platform.h>
+ #include <linux/sched.h>
+ #include <linux/shmem_fs.h>
+ #include <linux/file.h>
+ #include <linux/module.h>
+ #include <drm/drm_cache.h>
++#include <drm/drm_device.h>
++#include <drm/drm_util.h>
+ #include <drm/ttm/ttm_bo.h>
+ #include <drm/ttm/ttm_tt.h>
+
+@@ -60,6 +63,7 @@ static atomic_long_t ttm_dma32_pages_allocated;
+ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
+ {
+ struct ttm_device *bdev = bo->bdev;
++ struct drm_device *ddev = bo->base.dev;
+ uint32_t page_flags = 0;
+
+ dma_resv_assert_held(bo->base.resv);
+@@ -81,6 +85,15 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
+ pr_err("Illegal buffer object type\n");
+ return -EINVAL;
+ }
++ /*
++ * When using dma_alloc_coherent with memory encryption the
++ * mapped TT pages need to be decrypted or otherwise the drivers
++ * will end up sending encrypted mem to the gpu.
++ */
++ if (bdev->pool.use_dma_alloc && cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
++ page_flags |= TTM_TT_FLAG_DECRYPTED;
++ drm_info(ddev, "TT memory decryption enabled.");
++ }
+
+ bo->ttm = bdev->funcs->ttm_tt_create(bo, page_flags);
+ if (unlikely(bo->ttm == NULL))
+diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
+index f05e2c95a60d7..f827f26543641 100644
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -508,7 +508,7 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
+ edid = drm_get_edid(connector, vc4_hdmi->ddc);
+ cec_s_phys_addr_from_edid(vc4_hdmi->cec_adap, edid);
+ if (!edid)
+- return -ENODEV;
++ return 0;
+
+ drm_connector_update_edid_property(connector, edid);
+ ret = drm_add_edid_modes(connector, edid);
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+index d3e308fdfd5be..c7d90f96d16a6 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+@@ -1444,12 +1444,15 @@ static void vmw_debugfs_resource_managers_init(struct vmw_private *vmw)
+ root, "system_ttm");
+ ttm_resource_manager_create_debugfs(ttm_manager_type(&vmw->bdev, TTM_PL_VRAM),
+ root, "vram_ttm");
+- ttm_resource_manager_create_debugfs(ttm_manager_type(&vmw->bdev, VMW_PL_GMR),
+- root, "gmr_ttm");
+- ttm_resource_manager_create_debugfs(ttm_manager_type(&vmw->bdev, VMW_PL_MOB),
+- root, "mob_ttm");
+- ttm_resource_manager_create_debugfs(ttm_manager_type(&vmw->bdev, VMW_PL_SYSTEM),
+- root, "system_mob_ttm");
++ if (vmw->has_gmr)
++ ttm_resource_manager_create_debugfs(ttm_manager_type(&vmw->bdev, VMW_PL_GMR),
++ root, "gmr_ttm");
++ if (vmw->has_mob) {
++ ttm_resource_manager_create_debugfs(ttm_manager_type(&vmw->bdev, VMW_PL_MOB),
++ root, "mob_ttm");
++ ttm_resource_manager_create_debugfs(ttm_manager_type(&vmw->bdev, VMW_PL_SYSTEM),
++ root, "system_mob_ttm");
++ }
+ }
+
+ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+index 36987ef3fc300..5fef0b31c1179 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+@@ -447,7 +447,7 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,
+ vmw_res_type(ctx) == vmw_res_dx_context) {
+ for (i = 0; i < cotable_max; ++i) {
+ res = vmw_context_cotable(ctx, i);
+- if (IS_ERR(res))
++ if (IS_ERR_OR_NULL(res))
+ continue;
+
+ ret = vmw_execbuf_res_val_add(sw_context, res,
+@@ -1266,6 +1266,8 @@ static int vmw_cmd_dx_define_query(struct vmw_private *dev_priv,
+ return -EINVAL;
+
+ cotable_res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXQUERY);
++ if (IS_ERR_OR_NULL(cotable_res))
++ return cotable_res ? PTR_ERR(cotable_res) : -EINVAL;
+ ret = vmw_cotable_notify(cotable_res, cmd->body.queryId);
+
+ return ret;
+@@ -2484,6 +2486,8 @@ static int vmw_cmd_dx_view_define(struct vmw_private *dev_priv,
+ return ret;
+
+ res = vmw_context_cotable(ctx_node->ctx, vmw_view_cotables[view_type]);
++ if (IS_ERR_OR_NULL(res))
++ return res ? PTR_ERR(res) : -EINVAL;
+ ret = vmw_cotable_notify(res, cmd->defined_id);
+ if (unlikely(ret != 0))
+ return ret;
+@@ -2569,8 +2573,8 @@ static int vmw_cmd_dx_so_define(struct vmw_private *dev_priv,
+
+ so_type = vmw_so_cmd_to_type(header->id);
+ res = vmw_context_cotable(ctx_node->ctx, vmw_so_cotables[so_type]);
+- if (IS_ERR(res))
+- return PTR_ERR(res);
++ if (IS_ERR_OR_NULL(res))
++ return res ? PTR_ERR(res) : -EINVAL;
+ cmd = container_of(header, typeof(*cmd), header);
+ ret = vmw_cotable_notify(res, cmd->defined_id);
+
+@@ -2689,6 +2693,8 @@ static int vmw_cmd_dx_define_shader(struct vmw_private *dev_priv,
+ return -EINVAL;
+
+ res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXSHADER);
++ if (IS_ERR_OR_NULL(res))
++ return res ? PTR_ERR(res) : -EINVAL;
+ ret = vmw_cotable_notify(res, cmd->body.shaderId);
+ if (ret)
+ return ret;
+@@ -3010,6 +3016,8 @@ static int vmw_cmd_dx_define_streamoutput(struct vmw_private *dev_priv,
+ }
+
+ res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_STREAMOUTPUT);
++ if (IS_ERR_OR_NULL(res))
++ return res ? PTR_ERR(res) : -EINVAL;
+ ret = vmw_cotable_notify(res, cmd->body.soid);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+index b6f40781b907a..65be9e4a8992a 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+@@ -184,13 +184,12 @@ static u32 vmw_du_cursor_mob_size(u32 w, u32 h)
+ */
+ static u32 *vmw_du_cursor_plane_acquire_image(struct vmw_plane_state *vps)
+ {
+- bool is_iomem;
+ if (vps->surf) {
+ if (vps->surf_mapped)
+ return vmw_bo_map_and_cache(vps->surf->res.guest_memory_bo);
+ return vps->surf->snooper.image;
+ } else if (vps->bo)
+- return ttm_kmap_obj_virtual(&vps->bo->map, &is_iomem);
++ return vmw_bo_map_and_cache(vps->bo);
+ return NULL;
+ }
+
+@@ -652,22 +651,12 @@ vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane,
+ {
+ struct vmw_cursor_plane *vcp = vmw_plane_to_vcp(plane);
+ struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
+- bool is_iomem;
+
+ if (vps->surf_mapped) {
+ vmw_bo_unmap(vps->surf->res.guest_memory_bo);
+ vps->surf_mapped = false;
+ }
+
+- if (vps->bo && ttm_kmap_obj_virtual(&vps->bo->map, &is_iomem)) {
+- const int ret = ttm_bo_reserve(&vps->bo->tbo, true, false, NULL);
+-
+- if (likely(ret == 0)) {
+- ttm_bo_kunmap(&vps->bo->map);
+- ttm_bo_unreserve(&vps->bo->tbo);
+- }
+- }
+-
+ vmw_du_cursor_plane_unmap_cm(vps);
+ vmw_du_put_cursor_mob(vcp, vps);
+
+@@ -703,6 +692,10 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
+ int ret = 0;
+
+ if (vps->surf) {
++ if (vps->surf_mapped) {
++ vmw_bo_unmap(vps->surf->res.guest_memory_bo);
++ vps->surf_mapped = false;
++ }
+ vmw_surface_unreference(&vps->surf);
+ vps->surf = NULL;
+ }
+diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c
+index 7e924faeeea0b..1a6f2f51baae6 100644
+--- a/drivers/gpu/drm/xe/xe_query.c
++++ b/drivers/gpu/drm/xe/xe_query.c
+@@ -132,7 +132,7 @@ query_engine_cycles(struct xe_device *xe,
+ return -EINVAL;
+
+ eci = &resp.eci;
+- if (eci->gt_id > XE_MAX_GT_PER_TILE)
++ if (eci->gt_id >= XE_MAX_GT_PER_TILE)
+ return -EINVAL;
+
+ gt = xe_device_get_gt(xe, eci->gt_id);
+diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c
+index 2a7a4b6b00942..9b02b304c2f5d 100644
+--- a/drivers/hwmon/amc6821.c
++++ b/drivers/hwmon/amc6821.c
+@@ -934,10 +934,21 @@ static const struct i2c_device_id amc6821_id[] = {
+
+ MODULE_DEVICE_TABLE(i2c, amc6821_id);
+
++static const struct of_device_id __maybe_unused amc6821_of_match[] = {
++ {
++ .compatible = "ti,amc6821",
++ .data = (void *)amc6821,
++ },
++ { }
++};
++
++MODULE_DEVICE_TABLE(of, amc6821_of_match);
++
+ static struct i2c_driver amc6821_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "amc6821",
++ .of_match_table = of_match_ptr(amc6821_of_match),
+ },
+ .probe = amc6821_probe,
+ .id_table = amc6821_id,
+diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c
+index dd94667a623bd..1c0042fbbb548 100644
+--- a/drivers/iio/adc/rockchip_saradc.c
++++ b/drivers/iio/adc/rockchip_saradc.c
+@@ -52,7 +52,7 @@
+ #define SARADC2_START BIT(4)
+ #define SARADC2_SINGLE_MODE BIT(5)
+
+-#define SARADC2_CONV_CHANNELS GENMASK(15, 0)
++#define SARADC2_CONV_CHANNELS GENMASK(3, 0)
+
+ struct rockchip_saradc;
+
+@@ -102,12 +102,12 @@ static void rockchip_saradc_start_v2(struct rockchip_saradc *info, int chn)
+ writel_relaxed(0xc, info->regs + SARADC_T_DAS_SOC);
+ writel_relaxed(0x20, info->regs + SARADC_T_PD_SOC);
+ val = FIELD_PREP(SARADC2_EN_END_INT, 1);
+- val |= val << 16;
++ val |= SARADC2_EN_END_INT << 16;
+ writel_relaxed(val, info->regs + SARADC2_END_INT_EN);
+ val = FIELD_PREP(SARADC2_START, 1) |
+ FIELD_PREP(SARADC2_SINGLE_MODE, 1) |
+ FIELD_PREP(SARADC2_CONV_CHANNELS, chn);
+- val |= val << 16;
++ val |= (SARADC2_START | SARADC2_SINGLE_MODE | SARADC2_CONV_CHANNELS) << 16;
+ writel(val, info->regs + SARADC2_CONV_CON);
+ }
+
+diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
+index 50ccc4f1ef81c..639efa0c40721 100644
+--- a/drivers/iommu/dma-iommu.c
++++ b/drivers/iommu/dma-iommu.c
+@@ -1706,6 +1706,14 @@ static size_t iommu_dma_opt_mapping_size(void)
+ return iova_rcache_range();
+ }
+
++static size_t iommu_dma_max_mapping_size(struct device *dev)
++{
++ if (dev_is_untrusted(dev))
++ return swiotlb_max_mapping_size(dev);
++
++ return SIZE_MAX;
++}
++
+ static const struct dma_map_ops iommu_dma_ops = {
+ .flags = DMA_F_PCI_P2PDMA_SUPPORTED,
+ .alloc = iommu_dma_alloc,
+@@ -1728,6 +1736,7 @@ static const struct dma_map_ops iommu_dma_ops = {
+ .unmap_resource = iommu_dma_unmap_resource,
+ .get_merge_boundary = iommu_dma_get_merge_boundary,
+ .opt_mapping_size = iommu_dma_opt_mapping_size,
++ .max_mapping_size = iommu_dma_max_mapping_size,
+ };
+
+ /*
+diff --git a/drivers/irqchip/irq-renesas-rzg2l.c b/drivers/irqchip/irq-renesas-rzg2l.c
+index 9494fc26259c3..8803facbb3a2e 100644
+--- a/drivers/irqchip/irq-renesas-rzg2l.c
++++ b/drivers/irqchip/irq-renesas-rzg2l.c
+@@ -85,10 +85,9 @@ static struct rzg2l_irqc_priv *irq_data_to_priv(struct irq_data *data)
+ return data->domain->host_data;
+ }
+
+-static void rzg2l_irq_eoi(struct irq_data *d)
++static void rzg2l_clear_irq_int(struct rzg2l_irqc_priv *priv, unsigned int hwirq)
+ {
+- unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_IRQ_START;
+- struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
++ unsigned int hw_irq = hwirq - IRQC_IRQ_START;
+ u32 bit = BIT(hw_irq);
+ u32 iitsr, iscr;
+
+@@ -99,20 +98,30 @@ static void rzg2l_irq_eoi(struct irq_data *d)
+ * ISCR can only be cleared if the type is falling-edge, rising-edge or
+ * falling/rising-edge.
+ */
+- if ((iscr & bit) && (iitsr & IITSR_IITSEL_MASK(hw_irq)))
++ if ((iscr & bit) && (iitsr & IITSR_IITSEL_MASK(hw_irq))) {
+ writel_relaxed(iscr & ~bit, priv->base + ISCR);
++ /*
++ * Enforce that the posted write is flushed to prevent that the
++ * just handled interrupt is raised again.
++ */
++ readl_relaxed(priv->base + ISCR);
++ }
+ }
+
+-static void rzg2l_tint_eoi(struct irq_data *d)
++static void rzg2l_clear_tint_int(struct rzg2l_irqc_priv *priv, unsigned int hwirq)
+ {
+- unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_TINT_START;
+- struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
+- u32 bit = BIT(hw_irq);
++ u32 bit = BIT(hwirq - IRQC_TINT_START);
+ u32 reg;
+
+ reg = readl_relaxed(priv->base + TSCR);
+- if (reg & bit)
++ if (reg & bit) {
+ writel_relaxed(reg & ~bit, priv->base + TSCR);
++ /*
++ * Enforce that the posted write is flushed to prevent that the
++ * just handled interrupt is raised again.
++ */
++ readl_relaxed(priv->base + TSCR);
++ }
+ }
+
+ static void rzg2l_irqc_eoi(struct irq_data *d)
+@@ -122,9 +131,9 @@ static void rzg2l_irqc_eoi(struct irq_data *d)
+
+ raw_spin_lock(&priv->lock);
+ if (hw_irq >= IRQC_IRQ_START && hw_irq <= IRQC_IRQ_COUNT)
+- rzg2l_irq_eoi(d);
++ rzg2l_clear_irq_int(priv, hw_irq);
+ else if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ)
+- rzg2l_tint_eoi(d);
++ rzg2l_clear_tint_int(priv, hw_irq);
+ raw_spin_unlock(&priv->lock);
+ irq_chip_eoi_parent(d);
+ }
+@@ -172,8 +181,10 @@ static void rzg2l_irqc_irq_enable(struct irq_data *d)
+
+ static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
+ {
+- unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_IRQ_START;
+ struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
++ unsigned int hwirq = irqd_to_hwirq(d);
++ u32 iitseln = hwirq - IRQC_IRQ_START;
++ bool clear_irq_int = false;
+ u16 sense, tmp;
+
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+@@ -183,14 +194,17 @@ static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
+
+ case IRQ_TYPE_EDGE_FALLING:
+ sense = IITSR_IITSEL_EDGE_FALLING;
++ clear_irq_int = true;
+ break;
+
+ case IRQ_TYPE_EDGE_RISING:
+ sense = IITSR_IITSEL_EDGE_RISING;
++ clear_irq_int = true;
+ break;
+
+ case IRQ_TYPE_EDGE_BOTH:
+ sense = IITSR_IITSEL_EDGE_BOTH;
++ clear_irq_int = true;
+ break;
+
+ default:
+@@ -199,21 +213,40 @@ static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type)
+
+ raw_spin_lock(&priv->lock);
+ tmp = readl_relaxed(priv->base + IITSR);
+- tmp &= ~IITSR_IITSEL_MASK(hw_irq);
+- tmp |= IITSR_IITSEL(hw_irq, sense);
++ tmp &= ~IITSR_IITSEL_MASK(iitseln);
++ tmp |= IITSR_IITSEL(iitseln, sense);
++ if (clear_irq_int)
++ rzg2l_clear_irq_int(priv, hwirq);
+ writel_relaxed(tmp, priv->base + IITSR);
+ raw_spin_unlock(&priv->lock);
+
+ return 0;
+ }
+
++static u32 rzg2l_disable_tint_and_set_tint_source(struct irq_data *d, struct rzg2l_irqc_priv *priv,
++ u32 reg, u32 tssr_offset, u8 tssr_index)
++{
++ u32 tint = (u32)(uintptr_t)irq_data_get_irq_chip_data(d);
++ u32 tien = reg & (TIEN << TSSEL_SHIFT(tssr_offset));
++
++ /* Clear the relevant byte in reg */
++ reg &= ~(TSSEL_MASK << TSSEL_SHIFT(tssr_offset));
++ /* Set TINT and leave TIEN clear */
++ reg |= tint << TSSEL_SHIFT(tssr_offset);
++ writel_relaxed(reg, priv->base + TSSR(tssr_index));
++
++ return reg | tien;
++}
++
+ static int rzg2l_tint_set_edge(struct irq_data *d, unsigned int type)
+ {
+ struct rzg2l_irqc_priv *priv = irq_data_to_priv(d);
+ unsigned int hwirq = irqd_to_hwirq(d);
+ u32 titseln = hwirq - IRQC_TINT_START;
++ u32 tssr_offset = TSSR_OFFSET(titseln);
++ u8 tssr_index = TSSR_INDEX(titseln);
+ u8 index, sense;
+- u32 reg;
++ u32 reg, tssr;
+
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_RISING:
+@@ -235,10 +268,14 @@ static int rzg2l_tint_set_edge(struct irq_data *d, unsigned int type)
+ }
+
+ raw_spin_lock(&priv->lock);
++ tssr = readl_relaxed(priv->base + TSSR(tssr_index));
++ tssr = rzg2l_disable_tint_and_set_tint_source(d, priv, tssr, tssr_offset, tssr_index);
+ reg = readl_relaxed(priv->base + TITSR(index));
+ reg &= ~(IRQ_MASK << (titseln * TITSEL_WIDTH));
+ reg |= sense << (titseln * TITSEL_WIDTH);
+ writel_relaxed(reg, priv->base + TITSR(index));
++ rzg2l_clear_tint_int(priv, hwirq);
++ writel_relaxed(tssr, priv->base + TSSR(tssr_index));
+ raw_spin_unlock(&priv->lock);
+
+ return 0;
+diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c
+index 8e5475819590e..df1b1d8468e60 100644
+--- a/drivers/leds/trigger/ledtrig-netdev.c
++++ b/drivers/leds/trigger/ledtrig-netdev.c
+@@ -504,12 +504,12 @@ static int netdev_trig_notify(struct notifier_block *nb,
+ trigger_data->duplex = DUPLEX_UNKNOWN;
+ switch (evt) {
+ case NETDEV_CHANGENAME:
+- get_device_state(trigger_data);
+- fallthrough;
+ case NETDEV_REGISTER:
+ dev_put(trigger_data->net_dev);
+ dev_hold(dev);
+ trigger_data->net_dev = dev;
++ if (evt == NETDEV_CHANGENAME)
++ get_device_state(trigger_data);
+ break;
+ case NETDEV_UNREGISTER:
+ dev_put(trigger_data->net_dev);
+diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
+index 13eb47b997f94..d97355e9b9a6e 100644
+--- a/drivers/md/dm-raid.c
++++ b/drivers/md/dm-raid.c
+@@ -213,6 +213,7 @@ struct raid_dev {
+ #define RT_FLAG_RS_IN_SYNC 6
+ #define RT_FLAG_RS_RESYNCING 7
+ #define RT_FLAG_RS_GROW 8
++#define RT_FLAG_RS_FROZEN 9
+
+ /* Array elements of 64 bit needed for rebuild/failed disk bits */
+ #define DISKS_ARRAY_ELEMS ((MAX_RAID_DEVICES + (sizeof(uint64_t) * 8 - 1)) / sizeof(uint64_t) / 8)
+@@ -3240,11 +3241,12 @@ static int raid_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ rs->md.ro = 1;
+ rs->md.in_sync = 1;
+
+- /* Keep array frozen until resume. */
+- set_bit(MD_RECOVERY_FROZEN, &rs->md.recovery);
+-
+ /* Has to be held on running the array */
+ mddev_suspend_and_lock_nointr(&rs->md);
++
++ /* Keep array frozen until resume. */
++ md_frozen_sync_thread(&rs->md);
++
+ r = md_run(&rs->md);
+ rs->md.in_sync = 0; /* Assume already marked dirty */
+ if (r) {
+@@ -3339,7 +3341,8 @@ static int raid_map(struct dm_target *ti, struct bio *bio)
+ if (unlikely(bio_has_data(bio) && bio_end_sector(bio) > mddev->array_sectors))
+ return DM_MAPIO_REQUEUE;
+
+- md_handle_request(mddev, bio);
++ if (unlikely(!md_handle_request(mddev, bio)))
++ return DM_MAPIO_REQUEUE;
+
+ return DM_MAPIO_SUBMITTED;
+ }
+@@ -3718,21 +3721,33 @@ static int raid_message(struct dm_target *ti, unsigned int argc, char **argv,
+ {
+ struct raid_set *rs = ti->private;
+ struct mddev *mddev = &rs->md;
++ int ret = 0;
+
+ if (!mddev->pers || !mddev->pers->sync_request)
+ return -EINVAL;
+
+- if (!strcasecmp(argv[0], "frozen"))
+- set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+- else
+- clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
++ if (test_bit(RT_FLAG_RS_SUSPENDED, &rs->runtime_flags) ||
++ test_bit(RT_FLAG_RS_FROZEN, &rs->runtime_flags))
++ return -EBUSY;
+
+- if (!strcasecmp(argv[0], "idle") || !strcasecmp(argv[0], "frozen")) {
+- if (mddev->sync_thread) {
+- set_bit(MD_RECOVERY_INTR, &mddev->recovery);
+- md_reap_sync_thread(mddev);
+- }
+- } else if (decipher_sync_action(mddev, mddev->recovery) != st_idle)
++ if (!strcasecmp(argv[0], "frozen")) {
++ ret = mddev_lock(mddev);
++ if (ret)
++ return ret;
++
++ md_frozen_sync_thread(mddev);
++ mddev_unlock(mddev);
++ } else if (!strcasecmp(argv[0], "idle")) {
++ ret = mddev_lock(mddev);
++ if (ret)
++ return ret;
++
++ md_idle_sync_thread(mddev);
++ mddev_unlock(mddev);
++ }
++
++ clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
++ if (decipher_sync_action(mddev, mddev->recovery) != st_idle)
+ return -EBUSY;
+ else if (!strcasecmp(argv[0], "resync"))
+ ; /* MD_RECOVERY_NEEDED set below */
+@@ -3791,15 +3806,46 @@ static void raid_io_hints(struct dm_target *ti, struct queue_limits *limits)
+ blk_limits_io_opt(limits, chunk_size_bytes * mddev_data_stripes(rs));
+ }
+
++static void raid_presuspend(struct dm_target *ti)
++{
++ struct raid_set *rs = ti->private;
++ struct mddev *mddev = &rs->md;
++
++ /*
++ * From now on, disallow raid_message() to change sync_thread until
++ * resume, raid_postsuspend() is too late.
++ */
++ set_bit(RT_FLAG_RS_FROZEN, &rs->runtime_flags);
++
++ if (!reshape_interrupted(mddev))
++ return;
++
++ /*
++ * For raid456, if reshape is interrupted, IO across reshape position
++ * will never make progress, while caller will wait for IO to be done.
++ * Inform raid456 to handle those IO to prevent deadlock.
++ */
++ if (mddev->pers && mddev->pers->prepare_suspend)
++ mddev->pers->prepare_suspend(mddev);
++}
++
++static void raid_presuspend_undo(struct dm_target *ti)
++{
++ struct raid_set *rs = ti->private;
++
++ clear_bit(RT_FLAG_RS_FROZEN, &rs->runtime_flags);
++}
++
+ static void raid_postsuspend(struct dm_target *ti)
+ {
+ struct raid_set *rs = ti->private;
+
+ if (!test_and_set_bit(RT_FLAG_RS_SUSPENDED, &rs->runtime_flags)) {
+- /* Writes have to be stopped before suspending to avoid deadlocks. */
+- if (!test_bit(MD_RECOVERY_FROZEN, &rs->md.recovery))
+- md_stop_writes(&rs->md);
+-
++ /*
++ * sync_thread must be stopped during suspend, and writes have
++ * to be stopped before suspending to avoid deadlocks.
++ */
++ md_stop_writes(&rs->md);
+ mddev_suspend(&rs->md, false);
+ }
+ }
+@@ -4012,8 +4058,6 @@ static int raid_preresume(struct dm_target *ti)
+ }
+
+ /* Check for any resize/reshape on @rs and adjust/initiate */
+- /* Be prepared for mddev_resume() in raid_resume() */
+- set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+ if (mddev->recovery_cp && mddev->recovery_cp < MaxSector) {
+ set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
+ mddev->resync_min = mddev->recovery_cp;
+@@ -4047,7 +4091,9 @@ static void raid_resume(struct dm_target *ti)
+ * Take this opportunity to check whether any failed
+ * devices are reachable again.
+ */
++ mddev_lock_nointr(mddev);
+ attempt_restore_of_faulty_devices(rs);
++ mddev_unlock(mddev);
+ }
+
+ if (test_and_clear_bit(RT_FLAG_RS_SUSPENDED, &rs->runtime_flags)) {
+@@ -4055,10 +4101,13 @@ static void raid_resume(struct dm_target *ti)
+ if (mddev->delta_disks < 0)
+ rs_set_capacity(rs);
+
++ WARN_ON_ONCE(!test_bit(MD_RECOVERY_FROZEN, &mddev->recovery));
++ WARN_ON_ONCE(test_bit(MD_RECOVERY_RUNNING, &mddev->recovery));
++ clear_bit(RT_FLAG_RS_FROZEN, &rs->runtime_flags);
+ mddev_lock_nointr(mddev);
+- clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+ mddev->ro = 0;
+ mddev->in_sync = 0;
++ md_unfrozen_sync_thread(mddev);
+ mddev_unlock_and_resume(mddev);
+ }
+ }
+@@ -4074,6 +4123,8 @@ static struct target_type raid_target = {
+ .message = raid_message,
+ .iterate_devices = raid_iterate_devices,
+ .io_hints = raid_io_hints,
++ .presuspend = raid_presuspend,
++ .presuspend_undo = raid_presuspend_undo,
+ .postsuspend = raid_postsuspend,
+ .preresume = raid_preresume,
+ .resume = raid_resume,
+diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
+index bf7a574499a34..0ace06d1bee38 100644
+--- a/drivers/md/dm-snap.c
++++ b/drivers/md/dm-snap.c
+@@ -684,8 +684,10 @@ static void dm_exception_table_exit(struct dm_exception_table *et,
+ for (i = 0; i < size; i++) {
+ slot = et->table + i;
+
+- hlist_bl_for_each_entry_safe(ex, pos, n, slot, hash_list)
++ hlist_bl_for_each_entry_safe(ex, pos, n, slot, hash_list) {
+ kmem_cache_free(mem, ex);
++ cond_resched();
++ }
+ }
+
+ kvfree(et->table);
+diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
+index 9672f75c30503..a4976ceae8688 100644
+--- a/drivers/md/md-bitmap.c
++++ b/drivers/md/md-bitmap.c
+@@ -234,7 +234,8 @@ static int __write_sb_page(struct md_rdev *rdev, struct bitmap *bitmap,
+ sector_t doff;
+
+ bdev = (rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev;
+- if (pg_index == store->file_pages - 1) {
++ /* we compare length (page numbers), not page offset. */
++ if ((pg_index - store->sb_index) == store->file_pages - 1) {
+ unsigned int last_page_size = store->bytes & (PAGE_SIZE - 1);
+
+ if (last_page_size == 0)
+@@ -438,8 +439,8 @@ static void filemap_write_page(struct bitmap *bitmap, unsigned long pg_index,
+ struct page *page = store->filemap[pg_index];
+
+ if (mddev_is_clustered(bitmap->mddev)) {
+- pg_index += bitmap->cluster_slot *
+- DIV_ROUND_UP(store->bytes, PAGE_SIZE);
++ /* go to node bitmap area starting point */
++ pg_index += store->sb_index;
+ }
+
+ if (store->file)
+@@ -952,6 +953,7 @@ static void md_bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
+ unsigned long index = file_page_index(store, chunk);
+ unsigned long node_offset = 0;
+
++ index += store->sb_index;
+ if (mddev_is_clustered(bitmap->mddev))
+ node_offset = bitmap->cluster_slot * store->file_pages;
+
+@@ -982,6 +984,7 @@ static void md_bitmap_file_clear_bit(struct bitmap *bitmap, sector_t block)
+ unsigned long index = file_page_index(store, chunk);
+ unsigned long node_offset = 0;
+
++ index += store->sb_index;
+ if (mddev_is_clustered(bitmap->mddev))
+ node_offset = bitmap->cluster_slot * store->file_pages;
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index d344e6fa3b26f..f54012d684414 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -99,18 +99,6 @@ static void mddev_detach(struct mddev *mddev);
+ static void export_rdev(struct md_rdev *rdev, struct mddev *mddev);
+ static void md_wakeup_thread_directly(struct md_thread __rcu *thread);
+
+-enum md_ro_state {
+- MD_RDWR,
+- MD_RDONLY,
+- MD_AUTO_READ,
+- MD_MAX_STATE
+-};
+-
+-static bool md_is_rdwr(struct mddev *mddev)
+-{
+- return (mddev->ro == MD_RDWR);
+-}
+-
+ /*
+ * Default number of read corrections we'll attempt on an rdev
+ * before ejecting it from the array. We divide the read error
+@@ -378,7 +366,7 @@ static bool is_suspended(struct mddev *mddev, struct bio *bio)
+ return true;
+ }
+
+-void md_handle_request(struct mddev *mddev, struct bio *bio)
++bool md_handle_request(struct mddev *mddev, struct bio *bio)
+ {
+ check_suspended:
+ if (is_suspended(mddev, bio)) {
+@@ -386,7 +374,7 @@ void md_handle_request(struct mddev *mddev, struct bio *bio)
+ /* Bail out if REQ_NOWAIT is set for the bio */
+ if (bio->bi_opf & REQ_NOWAIT) {
+ bio_wouldblock_error(bio);
+- return;
++ return true;
+ }
+ for (;;) {
+ prepare_to_wait(&mddev->sb_wait, &__wait,
+@@ -402,10 +390,13 @@ void md_handle_request(struct mddev *mddev, struct bio *bio)
+
+ if (!mddev->pers->make_request(mddev, bio)) {
+ percpu_ref_put(&mddev->active_io);
++ if (!mddev->gendisk && mddev->pers->prepare_suspend)
++ return false;
+ goto check_suspended;
+ }
+
+ percpu_ref_put(&mddev->active_io);
++ return true;
+ }
+ EXPORT_SYMBOL(md_handle_request);
+
+@@ -4920,6 +4911,35 @@ static void stop_sync_thread(struct mddev *mddev, bool locked, bool check_seq)
+ mddev_lock_nointr(mddev);
+ }
+
++void md_idle_sync_thread(struct mddev *mddev)
++{
++ lockdep_assert_held(&mddev->reconfig_mutex);
++
++ clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
++ stop_sync_thread(mddev, true, true);
++}
++EXPORT_SYMBOL_GPL(md_idle_sync_thread);
++
++void md_frozen_sync_thread(struct mddev *mddev)
++{
++ lockdep_assert_held(&mddev->reconfig_mutex);
++
++ set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
++ stop_sync_thread(mddev, true, false);
++}
++EXPORT_SYMBOL_GPL(md_frozen_sync_thread);
++
++void md_unfrozen_sync_thread(struct mddev *mddev)
++{
++ lockdep_assert_held(&mddev->reconfig_mutex);
++
++ clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
++ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
++ md_wakeup_thread(mddev->thread);
++ sysfs_notify_dirent_safe(mddev->sysfs_action);
++}
++EXPORT_SYMBOL_GPL(md_unfrozen_sync_thread);
++
+ static void idle_sync_thread(struct mddev *mddev)
+ {
+ mutex_lock(&mddev->sync_mutex);
+@@ -6039,7 +6059,10 @@ int md_run(struct mddev *mddev)
+ pr_warn("True protection against single-disk failure might be compromised.\n");
+ }
+
+- mddev->recovery = 0;
++ /* dm-raid expect sync_thread to be frozen until resume */
++ if (mddev->gendisk)
++ mddev->recovery = 0;
++
+ /* may be over-ridden by personality */
+ mddev->resync_max_sectors = mddev->dev_sectors;
+
+@@ -6324,7 +6347,6 @@ static void md_clean(struct mddev *mddev)
+
+ static void __md_stop_writes(struct mddev *mddev)
+ {
+- stop_sync_thread(mddev, true, false);
+ del_timer_sync(&mddev->safemode_timer);
+
+ if (mddev->pers && mddev->pers->quiesce) {
+@@ -6349,6 +6371,8 @@ static void __md_stop_writes(struct mddev *mddev)
+ void md_stop_writes(struct mddev *mddev)
+ {
+ mddev_lock_nointr(mddev);
++ set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
++ stop_sync_thread(mddev, true, false);
+ __md_stop_writes(mddev);
+ mddev_unlock(mddev);
+ }
+@@ -8744,6 +8768,23 @@ void md_account_bio(struct mddev *mddev, struct bio **bio)
+ }
+ EXPORT_SYMBOL_GPL(md_account_bio);
+
++void md_free_cloned_bio(struct bio *bio)
++{
++ struct md_io_clone *md_io_clone = bio->bi_private;
++ struct bio *orig_bio = md_io_clone->orig_bio;
++ struct mddev *mddev = md_io_clone->mddev;
++
++ if (bio->bi_status && !orig_bio->bi_status)
++ orig_bio->bi_status = bio->bi_status;
++
++ if (md_io_clone->start_time)
++ bio_end_io_acct(orig_bio, md_io_clone->start_time);
++
++ bio_put(bio);
++ percpu_ref_put(&mddev->active_io);
++}
++EXPORT_SYMBOL_GPL(md_free_cloned_bio);
++
+ /* md_allow_write(mddev)
+ * Calling this ensures that the array is marked 'active' so that writes
+ * may proceed without blocking. It is important to call this before
+@@ -9277,9 +9318,14 @@ static bool md_spares_need_change(struct mddev *mddev)
+ {
+ struct md_rdev *rdev;
+
+- rdev_for_each(rdev, mddev)
+- if (rdev_removeable(rdev) || rdev_addable(rdev))
++ rcu_read_lock();
++ rdev_for_each_rcu(rdev, mddev) {
++ if (rdev_removeable(rdev) || rdev_addable(rdev)) {
++ rcu_read_unlock();
+ return true;
++ }
++ }
++ rcu_read_unlock();
+ return false;
+ }
+
+diff --git a/drivers/md/md.h b/drivers/md/md.h
+index 27d187ca6258a..375ad4a2df71d 100644
+--- a/drivers/md/md.h
++++ b/drivers/md/md.h
+@@ -559,6 +559,37 @@ enum recovery_flags {
+ MD_RESYNCING_REMOTE, /* remote node is running resync thread */
+ };
+
++enum md_ro_state {
++ MD_RDWR,
++ MD_RDONLY,
++ MD_AUTO_READ,
++ MD_MAX_STATE
++};
++
++static inline bool md_is_rdwr(struct mddev *mddev)
++{
++ return (mddev->ro == MD_RDWR);
++}
++
++static inline bool reshape_interrupted(struct mddev *mddev)
++{
++ /* reshape never start */
++ if (mddev->reshape_position == MaxSector)
++ return false;
++
++ /* interrupted */
++ if (!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
++ return true;
++
++ /* running reshape will be interrupted soon. */
++ if (test_bit(MD_RECOVERY_WAIT, &mddev->recovery) ||
++ test_bit(MD_RECOVERY_INTR, &mddev->recovery) ||
++ test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
++ return true;
++
++ return false;
++}
++
+ static inline int __must_check mddev_lock(struct mddev *mddev)
+ {
+ return mutex_lock_interruptible(&mddev->reconfig_mutex);
+@@ -618,6 +649,7 @@ struct md_personality
+ int (*start_reshape) (struct mddev *mddev);
+ void (*finish_reshape) (struct mddev *mddev);
+ void (*update_reshape_pos) (struct mddev *mddev);
++ void (*prepare_suspend) (struct mddev *mddev);
+ /* quiesce suspends or resumes internal processing.
+ * 1 - stop new actions and wait for action io to complete
+ * 0 - return to normal behaviour
+@@ -751,6 +783,7 @@ extern void md_finish_reshape(struct mddev *mddev);
+ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev,
+ struct bio *bio, sector_t start, sector_t size);
+ void md_account_bio(struct mddev *mddev, struct bio **bio);
++void md_free_cloned_bio(struct bio *bio);
+
+ extern bool __must_check md_flush_request(struct mddev *mddev, struct bio *bio);
+ extern void md_super_write(struct mddev *mddev, struct md_rdev *rdev,
+@@ -779,9 +812,12 @@ extern void md_stop_writes(struct mddev *mddev);
+ extern int md_rdev_init(struct md_rdev *rdev);
+ extern void md_rdev_clear(struct md_rdev *rdev);
+
+-extern void md_handle_request(struct mddev *mddev, struct bio *bio);
++extern bool md_handle_request(struct mddev *mddev, struct bio *bio);
+ extern int mddev_suspend(struct mddev *mddev, bool interruptible);
+ extern void mddev_resume(struct mddev *mddev);
++extern void md_idle_sync_thread(struct mddev *mddev);
++extern void md_frozen_sync_thread(struct mddev *mddev);
++extern void md_unfrozen_sync_thread(struct mddev *mddev);
+
+ extern void md_reload_sb(struct mddev *mddev, int raid_disk);
+ extern void md_update_sb(struct mddev *mddev, int force);
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 6a7a32f7fb912..69452e4394db0 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -36,6 +36,7 @@
+ */
+
+ #include <linux/blkdev.h>
++#include <linux/delay.h>
+ #include <linux/kthread.h>
+ #include <linux/raid/pq.h>
+ #include <linux/async_tx.h>
+@@ -760,6 +761,7 @@ enum stripe_result {
+ STRIPE_RETRY,
+ STRIPE_SCHEDULE_AND_RETRY,
+ STRIPE_FAIL,
++ STRIPE_WAIT_RESHAPE,
+ };
+
+ struct stripe_request_ctx {
+@@ -2412,7 +2414,7 @@ static int grow_one_stripe(struct r5conf *conf, gfp_t gfp)
+ atomic_inc(&conf->active_stripes);
+
+ raid5_release_stripe(sh);
+- conf->max_nr_stripes++;
++ WRITE_ONCE(conf->max_nr_stripes, conf->max_nr_stripes + 1);
+ return 1;
+ }
+
+@@ -2707,7 +2709,7 @@ static int drop_one_stripe(struct r5conf *conf)
+ shrink_buffers(sh);
+ free_stripe(conf->slab_cache, sh);
+ atomic_dec(&conf->active_stripes);
+- conf->max_nr_stripes--;
++ WRITE_ONCE(conf->max_nr_stripes, conf->max_nr_stripes - 1);
+ return 1;
+ }
+
+@@ -5946,7 +5948,8 @@ static enum stripe_result make_stripe_request(struct mddev *mddev,
+ if (ahead_of_reshape(mddev, logical_sector,
+ conf->reshape_safe)) {
+ spin_unlock_irq(&conf->device_lock);
+- return STRIPE_SCHEDULE_AND_RETRY;
++ ret = STRIPE_SCHEDULE_AND_RETRY;
++ goto out;
+ }
+ }
+ spin_unlock_irq(&conf->device_lock);
+@@ -6025,6 +6028,12 @@ static enum stripe_result make_stripe_request(struct mddev *mddev,
+
+ out_release:
+ raid5_release_stripe(sh);
++out:
++ if (ret == STRIPE_SCHEDULE_AND_RETRY && reshape_interrupted(mddev)) {
++ bi->bi_status = BLK_STS_RESOURCE;
++ ret = STRIPE_WAIT_RESHAPE;
++ pr_err_ratelimited("dm-raid456: io across reshape position while reshape can't make progress");
++ }
+ return ret;
+ }
+
+@@ -6146,7 +6155,7 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
+ while (1) {
+ res = make_stripe_request(mddev, conf, &ctx, logical_sector,
+ bi);
+- if (res == STRIPE_FAIL)
++ if (res == STRIPE_FAIL || res == STRIPE_WAIT_RESHAPE)
+ break;
+
+ if (res == STRIPE_RETRY)
+@@ -6184,6 +6193,11 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
+
+ if (rw == WRITE)
+ md_write_end(mddev);
++ if (res == STRIPE_WAIT_RESHAPE) {
++ md_free_cloned_bio(bi);
++ return false;
++ }
++
+ bio_endio(bi);
+ return true;
+ }
+@@ -6773,7 +6787,18 @@ static void raid5d(struct md_thread *thread)
+ spin_unlock_irq(&conf->device_lock);
+ md_check_recovery(mddev);
+ spin_lock_irq(&conf->device_lock);
++
++ /*
++ * Waiting on MD_SB_CHANGE_PENDING below may deadlock
++ * seeing md_check_recovery() is needed to clear
++ * the flag when using mdmon.
++ */
++ continue;
+ }
++
++ wait_event_lock_irq(mddev->sb_wait,
++ !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags),
++ conf->device_lock);
+ }
+ pr_debug("%d stripes handled\n", handled);
+
+@@ -6820,7 +6845,7 @@ raid5_set_cache_size(struct mddev *mddev, int size)
+ if (size <= 16 || size > 32768)
+ return -EINVAL;
+
+- conf->min_nr_stripes = size;
++ WRITE_ONCE(conf->min_nr_stripes, size);
+ mutex_lock(&conf->cache_size_mutex);
+ while (size < conf->max_nr_stripes &&
+ drop_one_stripe(conf))
+@@ -6832,7 +6857,7 @@ raid5_set_cache_size(struct mddev *mddev, int size)
+ mutex_lock(&conf->cache_size_mutex);
+ while (size > conf->max_nr_stripes)
+ if (!grow_one_stripe(conf, GFP_KERNEL)) {
+- conf->min_nr_stripes = conf->max_nr_stripes;
++ WRITE_ONCE(conf->min_nr_stripes, conf->max_nr_stripes);
+ result = -ENOMEM;
+ break;
+ }
+@@ -7390,11 +7415,13 @@ static unsigned long raid5_cache_count(struct shrinker *shrink,
+ struct shrink_control *sc)
+ {
+ struct r5conf *conf = shrink->private_data;
++ int max_stripes = READ_ONCE(conf->max_nr_stripes);
++ int min_stripes = READ_ONCE(conf->min_nr_stripes);
+
+- if (conf->max_nr_stripes < conf->min_nr_stripes)
++ if (max_stripes < min_stripes)
+ /* unlikely, but not impossible */
+ return 0;
+- return conf->max_nr_stripes - conf->min_nr_stripes;
++ return max_stripes - min_stripes;
+ }
+
+ static struct r5conf *setup_conf(struct mddev *mddev)
+@@ -8909,6 +8936,18 @@ static int raid5_start(struct mddev *mddev)
+ return r5l_start(conf->log);
+ }
+
++/*
++ * This is only used for dm-raid456, caller already frozen sync_thread, hence
++ * if rehsape is still in progress, io that is waiting for reshape can never be
++ * done now, hence wake up and handle those IO.
++ */
++static void raid5_prepare_suspend(struct mddev *mddev)
++{
++ struct r5conf *conf = mddev->private;
++
++ wake_up(&conf->wait_for_overlap);
++}
++
+ static struct md_personality raid6_personality =
+ {
+ .name = "raid6",
+@@ -8932,6 +8971,7 @@ static struct md_personality raid6_personality =
+ .quiesce = raid5_quiesce,
+ .takeover = raid6_takeover,
+ .change_consistency_policy = raid5_change_consistency_policy,
++ .prepare_suspend = raid5_prepare_suspend,
+ };
+ static struct md_personality raid5_personality =
+ {
+@@ -8956,6 +8996,7 @@ static struct md_personality raid5_personality =
+ .quiesce = raid5_quiesce,
+ .takeover = raid5_takeover,
+ .change_consistency_policy = raid5_change_consistency_policy,
++ .prepare_suspend = raid5_prepare_suspend,
+ };
+
+ static struct md_personality raid4_personality =
+@@ -8981,6 +9022,7 @@ static struct md_personality raid4_personality =
+ .quiesce = raid5_quiesce,
+ .takeover = raid4_takeover,
+ .change_consistency_policy = raid5_change_consistency_policy,
++ .prepare_suspend = raid5_prepare_suspend,
+ };
+
+ static int __init raid5_init(void)
+diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
+index 543a392f86357..0e28b9a7936ef 100644
+--- a/drivers/media/mc/mc-entity.c
++++ b/drivers/media/mc/mc-entity.c
+@@ -535,14 +535,15 @@ static int media_pipeline_walk_push(struct media_pipeline_walk *walk,
+
+ /*
+ * Move the top entry link cursor to the next link. If all links of the entry
+- * have been visited, pop the entry itself.
++ * have been visited, pop the entry itself. Return true if the entry has been
++ * popped.
+ */
+-static void media_pipeline_walk_pop(struct media_pipeline_walk *walk)
++static bool media_pipeline_walk_pop(struct media_pipeline_walk *walk)
+ {
+ struct media_pipeline_walk_entry *entry;
+
+ if (WARN_ON(walk->stack.top < 0))
+- return;
++ return false;
+
+ entry = media_pipeline_walk_top(walk);
+
+@@ -552,7 +553,7 @@ static void media_pipeline_walk_pop(struct media_pipeline_walk *walk)
+ walk->stack.top);
+
+ walk->stack.top--;
+- return;
++ return true;
+ }
+
+ entry->links = entry->links->next;
+@@ -560,6 +561,8 @@ static void media_pipeline_walk_pop(struct media_pipeline_walk *walk)
+ dev_dbg(walk->mdev->dev,
+ "media pipeline: moved entry %u to next link\n",
+ walk->stack.top);
++
++ return false;
+ }
+
+ /* Free all memory allocated while walking the pipeline. */
+@@ -605,30 +608,24 @@ static int media_pipeline_explore_next_link(struct media_pipeline *pipe,
+ struct media_pipeline_walk *walk)
+ {
+ struct media_pipeline_walk_entry *entry = media_pipeline_walk_top(walk);
+- struct media_pad *pad;
++ struct media_pad *origin;
+ struct media_link *link;
+ struct media_pad *local;
+ struct media_pad *remote;
++ bool last_link;
+ int ret;
+
+- pad = entry->pad;
++ origin = entry->pad;
+ link = list_entry(entry->links, typeof(*link), list);
+- media_pipeline_walk_pop(walk);
++ last_link = media_pipeline_walk_pop(walk);
+
+ dev_dbg(walk->mdev->dev,
+ "media pipeline: exploring link '%s':%u -> '%s':%u\n",
+ link->source->entity->name, link->source->index,
+ link->sink->entity->name, link->sink->index);
+
+- /* Skip links that are not enabled. */
+- if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
+- dev_dbg(walk->mdev->dev,
+- "media pipeline: skipping link (disabled)\n");
+- return 0;
+- }
+-
+ /* Get the local pad and remote pad. */
+- if (link->source->entity == pad->entity) {
++ if (link->source->entity == origin->entity) {
+ local = link->source;
+ remote = link->sink;
+ } else {
+@@ -640,25 +637,64 @@ static int media_pipeline_explore_next_link(struct media_pipeline *pipe,
+ * Skip links that originate from a different pad than the incoming pad
+ * that is not connected internally in the entity to the incoming pad.
+ */
+- if (pad != local &&
+- !media_entity_has_pad_interdep(pad->entity, pad->index, local->index)) {
++ if (origin != local &&
++ !media_entity_has_pad_interdep(origin->entity, origin->index,
++ local->index)) {
+ dev_dbg(walk->mdev->dev,
+ "media pipeline: skipping link (no route)\n");
+- return 0;
++ goto done;
+ }
+
+ /*
+- * Add the local and remote pads of the link to the pipeline and push
+- * them to the stack, if they're not already present.
++ * Add the local pad of the link to the pipeline and push it to the
++ * stack, if not already present.
+ */
+ ret = media_pipeline_add_pad(pipe, walk, local);
+ if (ret)
+ return ret;
+
++ /* Similarly, add the remote pad, but only if the link is enabled. */
++ if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
++ dev_dbg(walk->mdev->dev,
++ "media pipeline: skipping link (disabled)\n");
++ goto done;
++ }
++
+ ret = media_pipeline_add_pad(pipe, walk, remote);
+ if (ret)
+ return ret;
+
++done:
++ /*
++ * If we're done iterating over links, iterate over pads of the entity.
++ * This is necessary to discover pads that are not connected with any
++ * link. Those are dead ends from a pipeline exploration point of view,
++ * but are still part of the pipeline and need to be added to enable
++ * proper validation.
++ */
++ if (!last_link)
++ return 0;
++
++ dev_dbg(walk->mdev->dev,
++ "media pipeline: adding unconnected pads of '%s'\n",
++ local->entity->name);
++
++ media_entity_for_each_pad(origin->entity, local) {
++ /*
++ * Skip the origin pad (already handled), pad that have links
++ * (already discovered through iterating over links) and pads
++ * not internally connected.
++ */
++ if (origin == local || !local->num_links ||
++ !media_entity_has_pad_interdep(origin->entity, origin->index,
++ local->index))
++ continue;
++
++ ret = media_pipeline_add_pad(pipe, walk, local);
++ if (ret)
++ return ret;
++ }
++
+ return 0;
+ }
+
+@@ -770,7 +806,6 @@ __must_check int __media_pipeline_start(struct media_pad *pad,
+ struct media_pad *pad = ppad->pad;
+ struct media_entity *entity = pad->entity;
+ bool has_enabled_link = false;
+- bool has_link = false;
+ struct media_link *link;
+
+ dev_dbg(mdev->dev, "Validating pad '%s':%u\n", pad->entity->name,
+@@ -800,7 +835,6 @@ __must_check int __media_pipeline_start(struct media_pad *pad,
+ /* Record if the pad has links and enabled links. */
+ if (link->flags & MEDIA_LNK_FL_ENABLED)
+ has_enabled_link = true;
+- has_link = true;
+
+ /*
+ * Validate the link if it's enabled and has the
+@@ -838,7 +872,7 @@ __must_check int __media_pipeline_start(struct media_pad *pad,
+ * 3. If the pad has the MEDIA_PAD_FL_MUST_CONNECT flag set,
+ * ensure that it has either no link or an enabled link.
+ */
+- if ((pad->flags & MEDIA_PAD_FL_MUST_CONNECT) && has_link &&
++ if ((pad->flags & MEDIA_PAD_FL_MUST_CONNECT) &&
+ !has_enabled_link) {
+ dev_dbg(mdev->dev,
+ "Pad '%s':%u must be connected by an enabled link\n",
+@@ -1038,6 +1072,9 @@ static void __media_entity_remove_link(struct media_entity *entity,
+
+ /* Remove the reverse links for a data link. */
+ if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) == MEDIA_LNK_FL_DATA_LINK) {
++ link->source->num_links--;
++ link->sink->num_links--;
++
+ if (link->source->entity == entity)
+ remote = link->sink->entity;
+ else
+@@ -1092,6 +1129,11 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
+ struct media_link *link;
+ struct media_link *backlink;
+
++ if (flags & MEDIA_LNK_FL_LINK_TYPE)
++ return -EINVAL;
++
++ flags |= MEDIA_LNK_FL_DATA_LINK;
++
+ if (WARN_ON(!source || !sink) ||
+ WARN_ON(source_pad >= source->num_pads) ||
+ WARN_ON(sink_pad >= sink->num_pads))
+@@ -1107,7 +1149,7 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
+
+ link->source = &source->pads[source_pad];
+ link->sink = &sink->pads[sink_pad];
+- link->flags = flags & ~MEDIA_LNK_FL_INTERFACE_LINK;
++ link->flags = flags;
+
+ /* Initialize graph object embedded at the new link */
+ media_gobj_create(source->graph_obj.mdev, MEDIA_GRAPH_LINK,
+@@ -1138,6 +1180,9 @@ media_create_pad_link(struct media_entity *source, u16 source_pad,
+ sink->num_links++;
+ source->num_links++;
+
++ link->source->num_links++;
++ link->sink->num_links++;
++
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(media_create_pad_link);
+diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c
+index 575f173373887..93a55c97cd173 100644
+--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c
++++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c
+@@ -161,7 +161,6 @@ mxc_isi_crossbar_xlate_streams(struct mxc_isi_crossbar *xbar,
+
+ pad = media_pad_remote_pad_first(&xbar->pads[sink_pad]);
+ sd = media_entity_to_v4l2_subdev(pad->entity);
+-
+ if (!sd) {
+ dev_dbg(xbar->isi->dev,
+ "no entity connected to crossbar input %u\n",
+@@ -469,7 +468,8 @@ int mxc_isi_crossbar_init(struct mxc_isi_dev *isi)
+ }
+
+ for (i = 0; i < xbar->num_sinks; ++i)
+- xbar->pads[i].flags = MEDIA_PAD_FL_SINK;
++ xbar->pads[i].flags = MEDIA_PAD_FL_SINK
++ | MEDIA_PAD_FL_MUST_CONNECT;
+ for (i = 0; i < xbar->num_sources; ++i)
+ xbar->pads[i + xbar->num_sinks].flags = MEDIA_PAD_FL_SOURCE;
+
+diff --git a/drivers/media/tuners/xc4000.c b/drivers/media/tuners/xc4000.c
+index 57ded9ff3f043..29bc63021c5aa 100644
+--- a/drivers/media/tuners/xc4000.c
++++ b/drivers/media/tuners/xc4000.c
+@@ -1515,10 +1515,10 @@ static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
+ {
+ struct xc4000_priv *priv = fe->tuner_priv;
+
++ mutex_lock(&priv->lock);
+ *freq = priv->freq_hz + priv->freq_offset;
+
+ if (debug) {
+- mutex_lock(&priv->lock);
+ if ((priv->cur_fw.type
+ & (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) {
+ u16 snr = 0;
+@@ -1529,8 +1529,8 @@ static int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq)
+ return 0;
+ }
+ }
+- mutex_unlock(&priv->lock);
+ }
++ mutex_unlock(&priv->lock);
+
+ dprintk(1, "%s()\n", __func__);
+
+diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
+index e7a6e45b9fac2..4b023ee229cf1 100644
+--- a/drivers/mfd/Kconfig
++++ b/drivers/mfd/Kconfig
+@@ -1773,6 +1773,7 @@ config TWL4030_CORE
+ bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support"
+ depends on I2C=y
+ select IRQ_DOMAIN
++ select MFD_CORE
+ select REGMAP_I2C
+ help
+ Say yes here if you have TWL4030 / TWL6030 family chip on your board.
+diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
+index 4621d3950b8f9..8c00e0c695c5b 100644
+--- a/drivers/mfd/intel-lpss-pci.c
++++ b/drivers/mfd/intel-lpss-pci.c
+@@ -23,12 +23,22 @@
+
+ #include "intel-lpss.h"
+
+-/* Some DSDTs have an unused GEXP ACPI device conflicting with I2C4 resources */
+-static const struct pci_device_id ignore_resource_conflicts_ids[] = {
+- /* Microsoft Surface Go (version 1) I2C4 */
+- { PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1182), },
+- /* Microsoft Surface Go 2 I2C4 */
+- { PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1237), },
++static const struct pci_device_id quirk_ids[] = {
++ {
++ /* Microsoft Surface Go (version 1) I2C4 */
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1182),
++ .driver_data = QUIRK_IGNORE_RESOURCE_CONFLICTS,
++ },
++ {
++ /* Microsoft Surface Go 2 I2C4 */
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x9d64, 0x152d, 0x1237),
++ .driver_data = QUIRK_IGNORE_RESOURCE_CONFLICTS,
++ },
++ {
++ /* Dell XPS 9530 (2023) */
++ PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, 0x51fb, 0x1028, 0x0beb),
++ .driver_data = QUIRK_CLOCK_DIVIDER_UNITY,
++ },
+ { }
+ };
+
+@@ -36,6 +46,7 @@ static int intel_lpss_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+ {
+ const struct intel_lpss_platform_info *data = (void *)id->driver_data;
++ const struct pci_device_id *quirk_pci_info;
+ struct intel_lpss_platform_info *info;
+ int ret;
+
+@@ -55,8 +66,9 @@ static int intel_lpss_pci_probe(struct pci_dev *pdev,
+ info->mem = pci_resource_n(pdev, 0);
+ info->irq = pci_irq_vector(pdev, 0);
+
+- if (pci_match_id(ignore_resource_conflicts_ids, pdev))
+- info->ignore_resource_conflicts = true;
++ quirk_pci_info = pci_match_id(quirk_ids, pdev);
++ if (quirk_pci_info)
++ info->quirks = quirk_pci_info->driver_data;
+
+ pdev->d3cold_delay = 0;
+
+diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c
+index eff423f7dd284..2a9018112dfc8 100644
+--- a/drivers/mfd/intel-lpss.c
++++ b/drivers/mfd/intel-lpss.c
+@@ -300,6 +300,7 @@ static int intel_lpss_register_clock_divider(struct intel_lpss *lpss,
+ {
+ char name[32];
+ struct clk *tmp = *clk;
++ int ret;
+
+ snprintf(name, sizeof(name), "%s-enable", devname);
+ tmp = clk_register_gate(NULL, name, __clk_get_name(tmp), 0,
+@@ -316,6 +317,12 @@ static int intel_lpss_register_clock_divider(struct intel_lpss *lpss,
+ return PTR_ERR(tmp);
+ *clk = tmp;
+
++ if (lpss->info->quirks & QUIRK_CLOCK_DIVIDER_UNITY) {
++ ret = clk_set_rate(tmp, lpss->info->clk_rate);
++ if (ret)
++ return ret;
++ }
++
+ snprintf(name, sizeof(name), "%s-update", devname);
+ tmp = clk_register_gate(NULL, name, __clk_get_name(tmp),
+ CLK_SET_RATE_PARENT, lpss->priv, 31, 0, NULL);
+@@ -412,7 +419,7 @@ int intel_lpss_probe(struct device *dev,
+ return ret;
+
+ lpss->cell->swnode = info->swnode;
+- lpss->cell->ignore_resource_conflicts = info->ignore_resource_conflicts;
++ lpss->cell->ignore_resource_conflicts = info->quirks & QUIRK_IGNORE_RESOURCE_CONFLICTS;
+
+ intel_lpss_init_dev(lpss);
+
+diff --git a/drivers/mfd/intel-lpss.h b/drivers/mfd/intel-lpss.h
+index c1d72b117ed5e..6f8f668f4c6f0 100644
+--- a/drivers/mfd/intel-lpss.h
++++ b/drivers/mfd/intel-lpss.h
+@@ -11,16 +11,28 @@
+ #ifndef __MFD_INTEL_LPSS_H
+ #define __MFD_INTEL_LPSS_H
+
++#include <linux/bits.h>
+ #include <linux/pm.h>
+
++/*
++ * Some DSDTs have an unused GEXP ACPI device conflicting with I2C4 resources.
++ * Set to ignore resource conflicts with ACPI declared SystemMemory regions.
++ */
++#define QUIRK_IGNORE_RESOURCE_CONFLICTS BIT(0)
++/*
++ * Some devices have misconfigured clock divider due to a firmware bug.
++ * Set this to force the clock divider to 1:1 ratio.
++ */
++#define QUIRK_CLOCK_DIVIDER_UNITY BIT(1)
++
+ struct device;
+ struct resource;
+ struct software_node;
+
+ struct intel_lpss_platform_info {
+ struct resource *mem;
+- bool ignore_resource_conflicts;
+ int irq;
++ unsigned int quirks;
+ unsigned long clk_rate;
+ const char *clk_con_id;
+ const struct software_node *swnode;
+diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
+index 32d49100dff51..3564a0f63c9c7 100644
+--- a/drivers/mmc/core/block.c
++++ b/drivers/mmc/core/block.c
+@@ -413,7 +413,7 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
+ struct mmc_blk_ioc_data *idata;
+ int err;
+
+- idata = kmalloc(sizeof(*idata), GFP_KERNEL);
++ idata = kzalloc(sizeof(*idata), GFP_KERNEL);
+ if (!idata) {
+ err = -ENOMEM;
+ goto out;
+@@ -488,7 +488,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md,
+ if (idata->flags & MMC_BLK_IOC_DROP)
+ return 0;
+
+- if (idata->flags & MMC_BLK_IOC_SBC)
++ if (idata->flags & MMC_BLK_IOC_SBC && i > 0)
+ prev_idata = idatas[i - 1];
+
+ /*
+@@ -874,10 +874,11 @@ static const struct block_device_operations mmc_bdops = {
+ static int mmc_blk_part_switch_pre(struct mmc_card *card,
+ unsigned int part_type)
+ {
+- const unsigned int mask = EXT_CSD_PART_CONFIG_ACC_RPMB;
++ const unsigned int mask = EXT_CSD_PART_CONFIG_ACC_MASK;
++ const unsigned int rpmb = EXT_CSD_PART_CONFIG_ACC_RPMB;
+ int ret = 0;
+
+- if ((part_type & mask) == mask) {
++ if ((part_type & mask) == rpmb) {
+ if (card->ext_csd.cmdq_en) {
+ ret = mmc_cmdq_disable(card);
+ if (ret)
+@@ -892,10 +893,11 @@ static int mmc_blk_part_switch_pre(struct mmc_card *card,
+ static int mmc_blk_part_switch_post(struct mmc_card *card,
+ unsigned int part_type)
+ {
+- const unsigned int mask = EXT_CSD_PART_CONFIG_ACC_RPMB;
++ const unsigned int mask = EXT_CSD_PART_CONFIG_ACC_MASK;
++ const unsigned int rpmb = EXT_CSD_PART_CONFIG_ACC_RPMB;
+ int ret = 0;
+
+- if ((part_type & mask) == mask) {
++ if ((part_type & mask) == rpmb) {
+ mmc_retune_unpause(card->host);
+ if (card->reenable_cmdq && !card->ext_csd.cmdq_en)
+ ret = mmc_cmdq_enable(card);
+diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
+index a1f57af6acfb0..fa29460fd2903 100644
+--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
+@@ -933,6 +933,17 @@ static int dwcmshc_probe(struct platform_device *pdev)
+ return err;
+ }
+
++static void dwcmshc_disable_card_clk(struct sdhci_host *host)
++{
++ u16 ctrl;
++
++ ctrl = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
++ if (ctrl & SDHCI_CLOCK_CARD_EN) {
++ ctrl &= ~SDHCI_CLOCK_CARD_EN;
++ sdhci_writew(host, ctrl, SDHCI_CLOCK_CONTROL);
++ }
++}
++
+ static void dwcmshc_remove(struct platform_device *pdev)
+ {
+ struct sdhci_host *host = platform_get_drvdata(pdev);
+@@ -940,8 +951,14 @@ static void dwcmshc_remove(struct platform_device *pdev)
+ struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
+ struct rk35xx_priv *rk_priv = priv->priv;
+
++ pm_runtime_get_sync(&pdev->dev);
++ pm_runtime_disable(&pdev->dev);
++ pm_runtime_put_noidle(&pdev->dev);
++
+ sdhci_remove_host(host, 0);
+
++ dwcmshc_disable_card_clk(host);
++
+ clk_disable_unprepare(pltfm_host->clk);
+ clk_disable_unprepare(priv->bus_clk);
+ if (rk_priv)
+@@ -1033,17 +1050,6 @@ static void dwcmshc_enable_card_clk(struct sdhci_host *host)
+ }
+ }
+
+-static void dwcmshc_disable_card_clk(struct sdhci_host *host)
+-{
+- u16 ctrl;
+-
+- ctrl = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
+- if (ctrl & SDHCI_CLOCK_CARD_EN) {
+- ctrl &= ~SDHCI_CLOCK_CARD_EN;
+- sdhci_writew(host, ctrl, SDHCI_CLOCK_CONTROL);
+- }
+-}
+-
+ static int dwcmshc_runtime_suspend(struct device *dev)
+ {
+ struct sdhci_host *host = dev_get_drvdata(dev);
+diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c
+index e78faef67d7ab..94076b0955719 100644
+--- a/drivers/mmc/host/sdhci-omap.c
++++ b/drivers/mmc/host/sdhci-omap.c
+@@ -1439,6 +1439,9 @@ static int __maybe_unused sdhci_omap_runtime_suspend(struct device *dev)
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host);
+
++ if (host->tuning_mode != SDHCI_TUNING_MODE_3)
++ mmc_retune_needed(host->mmc);
++
+ if (omap_host->con != -EINVAL)
+ sdhci_runtime_suspend_host(host);
+
+diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c
+index be7f18fd4836a..c253d176db691 100644
+--- a/drivers/mmc/host/tmio_mmc_core.c
++++ b/drivers/mmc/host/tmio_mmc_core.c
+@@ -259,6 +259,8 @@ static void tmio_mmc_reset_work(struct work_struct *work)
+ else
+ mrq->cmd->error = -ETIMEDOUT;
+
++ /* No new calls yet, but disallow concurrent tmio_mmc_done_work() */
++ host->mrq = ERR_PTR(-EBUSY);
+ host->cmd = NULL;
+ host->data = NULL;
+
+diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c
+index cdb58aca59c08..2a96a87cf79ce 100644
+--- a/drivers/mtd/nand/raw/meson_nand.c
++++ b/drivers/mtd/nand/raw/meson_nand.c
+@@ -63,7 +63,7 @@
+ #define CMDRWGEN(cmd_dir, ran, bch, short_mode, page_size, pages) \
+ ( \
+ (cmd_dir) | \
+- ((ran) << 19) | \
++ (ran) | \
+ ((bch) << 14) | \
+ ((short_mode) << 13) | \
+ (((page_size) & 0x7f) << 6) | \
+diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
+index 3b3ce2926f5d1..2479fa98f9912 100644
+--- a/drivers/mtd/nand/raw/nand_base.c
++++ b/drivers/mtd/nand/raw/nand_base.c
+@@ -1211,21 +1211,36 @@ static int nand_lp_exec_read_page_op(struct nand_chip *chip, unsigned int page,
+ return nand_exec_op(chip, &op);
+ }
+
++static unsigned int rawnand_last_page_of_lun(unsigned int pages_per_lun, unsigned int lun)
++{
++ /* lun is expected to be very small */
++ return (lun * pages_per_lun) + pages_per_lun - 1;
++}
++
+ static void rawnand_cap_cont_reads(struct nand_chip *chip)
+ {
+ struct nand_memory_organization *memorg;
+- unsigned int pages_per_lun, first_lun, last_lun;
++ unsigned int ppl, first_lun, last_lun;
+
+ memorg = nanddev_get_memorg(&chip->base);
+- pages_per_lun = memorg->pages_per_eraseblock * memorg->eraseblocks_per_lun;
+- first_lun = chip->cont_read.first_page / pages_per_lun;
+- last_lun = chip->cont_read.last_page / pages_per_lun;
++ ppl = memorg->pages_per_eraseblock * memorg->eraseblocks_per_lun;
++ first_lun = chip->cont_read.first_page / ppl;
++ last_lun = chip->cont_read.last_page / ppl;
+
+ /* Prevent sequential cache reads across LUN boundaries */
+ if (first_lun != last_lun)
+- chip->cont_read.pause_page = first_lun * pages_per_lun + pages_per_lun - 1;
++ chip->cont_read.pause_page = rawnand_last_page_of_lun(ppl, first_lun);
+ else
+ chip->cont_read.pause_page = chip->cont_read.last_page;
++
++ if (chip->cont_read.first_page == chip->cont_read.pause_page) {
++ chip->cont_read.first_page++;
++ chip->cont_read.pause_page = min(chip->cont_read.last_page,
++ rawnand_last_page_of_lun(ppl, first_lun + 1));
++ }
++
++ if (chip->cont_read.first_page >= chip->cont_read.last_page)
++ chip->cont_read.ongoing = false;
+ }
+
+ static int nand_lp_exec_cont_read_page_op(struct nand_chip *chip, unsigned int page,
+@@ -1292,12 +1307,11 @@ static int nand_lp_exec_cont_read_page_op(struct nand_chip *chip, unsigned int p
+ if (!chip->cont_read.ongoing)
+ return 0;
+
+- if (page == chip->cont_read.pause_page &&
+- page != chip->cont_read.last_page) {
+- chip->cont_read.first_page = chip->cont_read.pause_page + 1;
+- rawnand_cap_cont_reads(chip);
+- } else if (page == chip->cont_read.last_page) {
++ if (page == chip->cont_read.last_page) {
+ chip->cont_read.ongoing = false;
++ } else if (page == chip->cont_read.pause_page) {
++ chip->cont_read.first_page++;
++ rawnand_cap_cont_reads(chip);
+ }
+
+ return 0;
+@@ -3466,30 +3480,36 @@ static void rawnand_enable_cont_reads(struct nand_chip *chip, unsigned int page,
+ u32 readlen, int col)
+ {
+ struct mtd_info *mtd = nand_to_mtd(chip);
+- unsigned int end_page, end_col;
++ unsigned int first_page, last_page;
+
+ chip->cont_read.ongoing = false;
+
+ if (!chip->controller->supported_op.cont_read)
+ return;
+
+- end_page = DIV_ROUND_UP(col + readlen, mtd->writesize);
+- end_col = (col + readlen) % mtd->writesize;
++ /*
++ * Don't bother making any calculations if the length is too small.
++ * Side effect: avoids possible integer underflows below.
++ */
++ if (readlen < (2 * mtd->writesize))
++ return;
+
++ /* Derive the page where continuous read should start (the first full page read) */
++ first_page = page;
+ if (col)
+- page++;
++ first_page++;
+
+- if (end_col && end_page)
+- end_page--;
++ /* Derive the page where continuous read should stop (the last full page read) */
++ last_page = page + ((col + readlen) / mtd->writesize) - 1;
+
+- if (page + 1 > end_page)
+- return;
+-
+- chip->cont_read.first_page = page;
+- chip->cont_read.last_page = end_page;
+- chip->cont_read.ongoing = true;
+-
+- rawnand_cap_cont_reads(chip);
++ /* Configure and enable continuous read when suitable */
++ if (first_page < last_page) {
++ chip->cont_read.first_page = first_page;
++ chip->cont_read.last_page = last_page;
++ chip->cont_read.ongoing = true;
++ /* May reset the ongoing flag */
++ rawnand_cap_cont_reads(chip);
++ }
+ }
+
+ static void rawnand_cont_read_skip_first_page(struct nand_chip *chip, unsigned int page)
+@@ -3498,10 +3518,7 @@ static void rawnand_cont_read_skip_first_page(struct nand_chip *chip, unsigned i
+ return;
+
+ chip->cont_read.first_page++;
+- if (chip->cont_read.first_page == chip->cont_read.pause_page)
+- chip->cont_read.first_page++;
+- if (chip->cont_read.first_page >= chip->cont_read.last_page)
+- chip->cont_read.ongoing = false;
++ rawnand_cap_cont_reads(chip);
+ }
+
+ /**
+@@ -3577,7 +3594,8 @@ static int nand_do_read_ops(struct nand_chip *chip, loff_t from,
+ oob = ops->oobbuf;
+ oob_required = oob ? 1 : 0;
+
+- rawnand_enable_cont_reads(chip, page, readlen, col);
++ if (likely(ops->mode != MTD_OPS_RAW))
++ rawnand_enable_cont_reads(chip, page, readlen, col);
+
+ while (1) {
+ struct mtd_ecc_stats ecc_stats = mtd->ecc_stats;
+@@ -5195,6 +5213,15 @@ static void rawnand_late_check_supported_ops(struct nand_chip *chip)
+ if (!nand_has_exec_op(chip))
+ return;
+
++ /*
++ * For now, continuous reads can only be used with the core page helpers.
++ * This can be extended later.
++ */
++ if (!(chip->ecc.read_page == nand_read_page_hwecc ||
++ chip->ecc.read_page == nand_read_page_syndrome ||
++ chip->ecc.read_page == nand_read_page_swecc))
++ return;
++
+ rawnand_check_cont_read_support(chip);
+ }
+
+diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
+index 2a728c31e6b85..9a4940874be5b 100644
+--- a/drivers/mtd/ubi/fastmap.c
++++ b/drivers/mtd/ubi/fastmap.c
+@@ -85,9 +85,10 @@ size_t ubi_calc_fm_size(struct ubi_device *ubi)
+ sizeof(struct ubi_fm_scan_pool) +
+ sizeof(struct ubi_fm_scan_pool) +
+ (ubi->peb_count * sizeof(struct ubi_fm_ec)) +
+- (sizeof(struct ubi_fm_eba) +
+- (ubi->peb_count * sizeof(__be32))) +
+- sizeof(struct ubi_fm_volhdr) * UBI_MAX_VOLUMES;
++ ((sizeof(struct ubi_fm_eba) +
++ sizeof(struct ubi_fm_volhdr)) *
++ (UBI_MAX_VOLUMES + UBI_INT_VOL_COUNT)) +
++ (ubi->peb_count * sizeof(__be32));
+ return roundup(size, ubi->leb_size);
+ }
+
+diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
+index f700f0e4f2ec4..6e5489e233dd2 100644
+--- a/drivers/mtd/ubi/vtbl.c
++++ b/drivers/mtd/ubi/vtbl.c
+@@ -791,6 +791,12 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai)
+ * The number of supported volumes is limited by the eraseblock size
+ * and by the UBI_MAX_VOLUMES constant.
+ */
++
++ if (ubi->leb_size < UBI_VTBL_RECORD_SIZE) {
++ ubi_err(ubi, "LEB size too small for a volume record");
++ return -EINVAL;
++ }
++
+ ubi->vtbl_slots = ubi->leb_size / UBI_VTBL_RECORD_SIZE;
+ if (ubi->vtbl_slots > UBI_MAX_VOLUMES)
+ ubi->vtbl_slots = UBI_MAX_VOLUMES;
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_trace.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_trace.h
+index 8510b88d49820..f3cd5a376eca9 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_trace.h
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_trace.h
+@@ -24,7 +24,7 @@ TRACE_EVENT(hclge_pf_mbx_get,
+ __field(u8, code)
+ __field(u8, subcode)
+ __string(pciname, pci_name(hdev->pdev))
+- __string(devname, &hdev->vport[0].nic.kinfo.netdev->name)
++ __string(devname, hdev->vport[0].nic.kinfo.netdev->name)
+ __array(u32, mbx_data, PF_GET_MBX_LEN)
+ ),
+
+@@ -33,7 +33,7 @@ TRACE_EVENT(hclge_pf_mbx_get,
+ __entry->code = req->msg.code;
+ __entry->subcode = req->msg.subcode;
+ __assign_str(pciname, pci_name(hdev->pdev));
+- __assign_str(devname, &hdev->vport[0].nic.kinfo.netdev->name);
++ __assign_str(devname, hdev->vport[0].nic.kinfo.netdev->name);
+ memcpy(__entry->mbx_data, req,
+ sizeof(struct hclge_mbx_vf_to_pf_cmd));
+ ),
+@@ -56,7 +56,7 @@ TRACE_EVENT(hclge_pf_mbx_send,
+ __field(u8, vfid)
+ __field(u16, code)
+ __string(pciname, pci_name(hdev->pdev))
+- __string(devname, &hdev->vport[0].nic.kinfo.netdev->name)
++ __string(devname, hdev->vport[0].nic.kinfo.netdev->name)
+ __array(u32, mbx_data, PF_SEND_MBX_LEN)
+ ),
+
+@@ -64,7 +64,7 @@ TRACE_EVENT(hclge_pf_mbx_send,
+ __entry->vfid = req->dest_vfid;
+ __entry->code = le16_to_cpu(req->msg.code);
+ __assign_str(pciname, pci_name(hdev->pdev));
+- __assign_str(devname, &hdev->vport[0].nic.kinfo.netdev->name);
++ __assign_str(devname, hdev->vport[0].nic.kinfo.netdev->name);
+ memcpy(__entry->mbx_data, req,
+ sizeof(struct hclge_mbx_pf_to_vf_cmd));
+ ),
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_trace.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_trace.h
+index 5d4895bb57a17..b259e95dd53c2 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_trace.h
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_trace.h
+@@ -23,7 +23,7 @@ TRACE_EVENT(hclge_vf_mbx_get,
+ __field(u8, vfid)
+ __field(u16, code)
+ __string(pciname, pci_name(hdev->pdev))
+- __string(devname, &hdev->nic.kinfo.netdev->name)
++ __string(devname, hdev->nic.kinfo.netdev->name)
+ __array(u32, mbx_data, VF_GET_MBX_LEN)
+ ),
+
+@@ -31,7 +31,7 @@ TRACE_EVENT(hclge_vf_mbx_get,
+ __entry->vfid = req->dest_vfid;
+ __entry->code = le16_to_cpu(req->msg.code);
+ __assign_str(pciname, pci_name(hdev->pdev));
+- __assign_str(devname, &hdev->nic.kinfo.netdev->name);
++ __assign_str(devname, hdev->nic.kinfo.netdev->name);
+ memcpy(__entry->mbx_data, req,
+ sizeof(struct hclge_mbx_pf_to_vf_cmd));
+ ),
+@@ -55,7 +55,7 @@ TRACE_EVENT(hclge_vf_mbx_send,
+ __field(u8, code)
+ __field(u8, subcode)
+ __string(pciname, pci_name(hdev->pdev))
+- __string(devname, &hdev->nic.kinfo.netdev->name)
++ __string(devname, hdev->nic.kinfo.netdev->name)
+ __array(u32, mbx_data, VF_SEND_MBX_LEN)
+ ),
+
+@@ -64,7 +64,7 @@ TRACE_EVENT(hclge_vf_mbx_send,
+ __entry->code = req->msg.code;
+ __entry->subcode = req->msg.subcode;
+ __assign_str(pciname, pci_name(hdev->pdev));
+- __assign_str(devname, &hdev->nic.kinfo.netdev->name);
++ __assign_str(devname, hdev->nic.kinfo.netdev->name);
+ memcpy(__entry->mbx_data, req,
+ sizeof(struct hclge_mbx_vf_to_pf_cmd));
+ ),
+diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c
+index 9df39cf8b0975..1072e2210aed3 100644
+--- a/drivers/net/ethernet/xilinx/ll_temac_main.c
++++ b/drivers/net/ethernet/xilinx/ll_temac_main.c
+@@ -1443,7 +1443,7 @@ static int temac_probe(struct platform_device *pdev)
+ }
+
+ /* map device registers */
+- lp->regs = devm_platform_ioremap_resource_byname(pdev, 0);
++ lp->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(lp->regs)) {
+ dev_err(&pdev->dev, "could not map TEMAC registers\n");
+ return -ENOMEM;
+diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
+index a62442a55774c..fdb89a505de3d 100644
+--- a/drivers/net/phy/at803x.c
++++ b/drivers/net/phy/at803x.c
+@@ -1503,7 +1503,7 @@ static int at8031_parse_dt(struct phy_device *phydev)
+
+ static int at8031_probe(struct phy_device *phydev)
+ {
+- struct at803x_priv *priv = phydev->priv;
++ struct at803x_priv *priv;
+ int mode_cfg;
+ int ccr;
+ int ret;
+@@ -1512,6 +1512,8 @@ static int at8031_probe(struct phy_device *phydev)
+ if (ret)
+ return ret;
+
++ priv = phydev->priv;
++
+ /* Only supported on AR8031/AR8033, the AR8030/AR8035 use strapping
+ * options.
+ */
+diff --git a/drivers/net/wireguard/netlink.c b/drivers/net/wireguard/netlink.c
+index e220d761b1f27..f7055180ba4aa 100644
+--- a/drivers/net/wireguard/netlink.c
++++ b/drivers/net/wireguard/netlink.c
+@@ -164,8 +164,8 @@ get_peer(struct wg_peer *peer, struct sk_buff *skb, struct dump_ctx *ctx)
+ if (!allowedips_node)
+ goto no_allowedips;
+ if (!ctx->allowedips_seq)
+- ctx->allowedips_seq = peer->device->peer_allowedips.seq;
+- else if (ctx->allowedips_seq != peer->device->peer_allowedips.seq)
++ ctx->allowedips_seq = ctx->wg->peer_allowedips.seq;
++ else if (ctx->allowedips_seq != ctx->wg->peer_allowedips.seq)
+ goto no_allowedips;
+
+ allowedips_nest = nla_nest_start(skb, WGPEER_A_ALLOWEDIPS);
+@@ -255,17 +255,17 @@ static int wg_get_device_dump(struct sk_buff *skb, struct netlink_callback *cb)
+ if (!peers_nest)
+ goto out;
+ ret = 0;
+- /* If the last cursor was removed via list_del_init in peer_remove, then
++ lockdep_assert_held(&wg->device_update_lock);
++ /* If the last cursor was removed in peer_remove or peer_remove_all, then
+ * we just treat this the same as there being no more peers left. The
+ * reason is that seq_nr should indicate to userspace that this isn't a
+ * coherent dump anyway, so they'll try again.
+ */
+ if (list_empty(&wg->peer_list) ||
+- (ctx->next_peer && list_empty(&ctx->next_peer->peer_list))) {
++ (ctx->next_peer && ctx->next_peer->is_dead)) {
+ nla_nest_cancel(skb, peers_nest);
+ goto out;
+ }
+- lockdep_assert_held(&wg->device_update_lock);
+ peer = list_prepare_entry(ctx->next_peer, &wg->peer_list, peer_list);
+ list_for_each_entry_continue(peer, &wg->peer_list, peer_list) {
+ if (get_peer(peer, skb, ctx)) {
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bca/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bca/core.c
+index ac3a36fa3640c..a963c242975ac 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bca/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bca/core.c
+@@ -7,21 +7,16 @@
+ #include <core.h>
+ #include <bus.h>
+ #include <fwvid.h>
++#include <feature.h>
+
+ #include "vops.h"
+
+-static int brcmf_bca_attach(struct brcmf_pub *drvr)
++static void brcmf_bca_feat_attach(struct brcmf_if *ifp)
+ {
+- pr_err("%s: executing\n", __func__);
+- return 0;
+-}
+-
+-static void brcmf_bca_detach(struct brcmf_pub *drvr)
+-{
+- pr_err("%s: executing\n", __func__);
++ /* SAE support not confirmed so disabling for now */
++ ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_SAE);
+ }
+
+ const struct brcmf_fwvid_ops brcmf_bca_ops = {
+- .attach = brcmf_bca_attach,
+- .detach = brcmf_bca_detach,
++ .feat_attach = brcmf_bca_feat_attach,
+ };
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+index 1a5d7494f5e80..625b7cb37f47b 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -32,6 +32,7 @@
+ #include "vendor.h"
+ #include "bus.h"
+ #include "common.h"
++#include "fwvid.h"
+
+ #define BRCMF_SCAN_IE_LEN_MAX 2048
+
+@@ -1179,8 +1180,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
+ scan_request = cfg->scan_request;
+ cfg->scan_request = NULL;
+
+- if (timer_pending(&cfg->escan_timeout))
+- del_timer_sync(&cfg->escan_timeout);
++ timer_delete_sync(&cfg->escan_timeout);
+
+ if (fw_abort) {
+ /* Do a scan abort to stop the driver's scan engine */
+@@ -1687,52 +1687,39 @@ static u16 brcmf_map_fw_linkdown_reason(const struct brcmf_event_msg *e)
+ return reason;
+ }
+
+-static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)
++int brcmf_set_wsec(struct brcmf_if *ifp, const u8 *key, u16 key_len, u16 flags)
+ {
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_wsec_pmk_le pmk;
+ int err;
+
++ if (key_len > sizeof(pmk.key)) {
++ bphy_err(drvr, "key must be less than %zu bytes\n",
++ sizeof(pmk.key));
++ return -EINVAL;
++ }
++
+ memset(&pmk, 0, sizeof(pmk));
+
+- /* pass pmk directly */
+- pmk.key_len = cpu_to_le16(pmk_len);
+- pmk.flags = cpu_to_le16(0);
+- memcpy(pmk.key, pmk_data, pmk_len);
++ /* pass key material directly */
++ pmk.key_len = cpu_to_le16(key_len);
++ pmk.flags = cpu_to_le16(flags);
++ memcpy(pmk.key, key, key_len);
+
+- /* store psk in firmware */
++ /* store key material in firmware */
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK,
+ &pmk, sizeof(pmk));
+ if (err < 0)
+ bphy_err(drvr, "failed to change PSK in firmware (len=%u)\n",
+- pmk_len);
++ key_len);
+
+ return err;
+ }
++BRCMF_EXPORT_SYMBOL_GPL(brcmf_set_wsec);
+
+-static int brcmf_set_sae_password(struct brcmf_if *ifp, const u8 *pwd_data,
+- u16 pwd_len)
++static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)
+ {
+- struct brcmf_pub *drvr = ifp->drvr;
+- struct brcmf_wsec_sae_pwd_le sae_pwd;
+- int err;
+-
+- if (pwd_len > BRCMF_WSEC_MAX_SAE_PASSWORD_LEN) {
+- bphy_err(drvr, "sae_password must be less than %d\n",
+- BRCMF_WSEC_MAX_SAE_PASSWORD_LEN);
+- return -EINVAL;
+- }
+-
+- sae_pwd.key_len = cpu_to_le16(pwd_len);
+- memcpy(sae_pwd.key, pwd_data, pwd_len);
+-
+- err = brcmf_fil_iovar_data_set(ifp, "sae_password", &sae_pwd,
+- sizeof(sae_pwd));
+- if (err < 0)
+- bphy_err(drvr, "failed to set SAE password in firmware (len=%u)\n",
+- pwd_len);
+-
+- return err;
++ return brcmf_set_wsec(ifp, pmk_data, pmk_len, 0);
+ }
+
+ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason,
+@@ -2503,8 +2490,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
+ bphy_err(drvr, "failed to clean up user-space RSNE\n");
+ goto done;
+ }
+- err = brcmf_set_sae_password(ifp, sme->crypto.sae_pwd,
+- sme->crypto.sae_pwd_len);
++ err = brcmf_fwvid_set_sae_password(ifp, &sme->crypto);
+ if (!err && sme->crypto.psk)
+ err = brcmf_set_pmk(ifp, sme->crypto.psk,
+ BRCMF_WSEC_MAX_PSK_LEN);
+@@ -5257,8 +5243,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
+ if (crypto->sae_pwd) {
+ brcmf_dbg(INFO, "using SAE offload\n");
+ profile->use_fwauth |= BIT(BRCMF_PROFILE_FWAUTH_SAE);
+- err = brcmf_set_sae_password(ifp, crypto->sae_pwd,
+- crypto->sae_pwd_len);
++ err = brcmf_fwvid_set_sae_password(ifp, crypto);
+ if (err < 0)
+ goto exit;
+ }
+@@ -5365,10 +5350,12 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev,
+ msleep(400);
+
+ if (profile->use_fwauth != BIT(BRCMF_PROFILE_FWAUTH_NONE)) {
++ struct cfg80211_crypto_settings crypto = {};
++
+ if (profile->use_fwauth & BIT(BRCMF_PROFILE_FWAUTH_PSK))
+ brcmf_set_pmk(ifp, NULL, 0);
+ if (profile->use_fwauth & BIT(BRCMF_PROFILE_FWAUTH_SAE))
+- brcmf_set_sae_password(ifp, NULL, 0);
++ brcmf_fwvid_set_sae_password(ifp, &crypto);
+ profile->use_fwauth = BIT(BRCMF_PROFILE_FWAUTH_NONE);
+ }
+
+@@ -8440,6 +8427,7 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
+ brcmf_btcoex_detach(cfg);
+ wiphy_unregister(cfg->wiphy);
+ wl_deinit_priv(cfg);
++ cancel_work_sync(&cfg->escan_timeout_work);
+ brcmf_free_wiphy(cfg->wiphy);
+ kfree(cfg);
+ }
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+index 0e1fa3f0dea2c..dc3a6a537507d 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+@@ -468,4 +468,6 @@ void brcmf_set_mpc(struct brcmf_if *ndev, int mpc);
+ void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
+ void brcmf_cfg80211_free_netdev(struct net_device *ndev);
+
++int brcmf_set_wsec(struct brcmf_if *ifp, const u8 *key, u16 key_len, u16 flags);
++
+ #endif /* BRCMFMAC_CFG80211_H */
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c
+index b75652ba9359f..bec5748310b9c 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c
+@@ -7,21 +7,36 @@
+ #include <core.h>
+ #include <bus.h>
+ #include <fwvid.h>
++#include <fwil.h>
+
+ #include "vops.h"
+
+-static int brcmf_cyw_attach(struct brcmf_pub *drvr)
++static int brcmf_cyw_set_sae_pwd(struct brcmf_if *ifp,
++ struct cfg80211_crypto_settings *crypto)
+ {
+- pr_err("%s: executing\n", __func__);
+- return 0;
+-}
++ struct brcmf_pub *drvr = ifp->drvr;
++ struct brcmf_wsec_sae_pwd_le sae_pwd;
++ u16 pwd_len = crypto->sae_pwd_len;
++ int err;
+
+-static void brcmf_cyw_detach(struct brcmf_pub *drvr)
+-{
+- pr_err("%s: executing\n", __func__);
++ if (pwd_len > BRCMF_WSEC_MAX_SAE_PASSWORD_LEN) {
++ bphy_err(drvr, "sae_password must be less than %d\n",
++ BRCMF_WSEC_MAX_SAE_PASSWORD_LEN);
++ return -EINVAL;
++ }
++
++ sae_pwd.key_len = cpu_to_le16(pwd_len);
++ memcpy(sae_pwd.key, crypto->sae_pwd, pwd_len);
++
++ err = brcmf_fil_iovar_data_set(ifp, "sae_password", &sae_pwd,
++ sizeof(sae_pwd));
++ if (err < 0)
++ bphy_err(drvr, "failed to set SAE password in firmware (len=%u)\n",
++ pwd_len);
++
++ return err;
+ }
+
+ const struct brcmf_fwvid_ops brcmf_cyw_ops = {
+- .attach = brcmf_cyw_attach,
+- .detach = brcmf_cyw_detach,
++ .set_sae_password = brcmf_cyw_set_sae_pwd,
+ };
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+index 6d10c9efbe93d..909a34a1ab503 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+@@ -13,6 +13,7 @@
+ #include "debug.h"
+ #include "fwil.h"
+ #include "fwil_types.h"
++#include "fwvid.h"
+ #include "feature.h"
+ #include "common.h"
+
+@@ -339,6 +340,8 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_SCAN_V2, "scan_ver");
+
++ brcmf_fwvid_feat_attach(ifp);
++
+ if (drvr->settings->feature_disable) {
+ brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
+ ifp->drvr->feat_flags,
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
+index 72fe8bce6eaf5..a9514d72f770b 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
+@@ -239,6 +239,7 @@ brcmf_fil_iovar_data_set(struct brcmf_if *ifp, const char *name, const void *dat
+ mutex_unlock(&drvr->proto_block);
+ return err;
+ }
++BRCMF_EXPORT_SYMBOL_GPL(brcmf_fil_iovar_data_set);
+
+ s32
+ brcmf_fil_iovar_data_get(struct brcmf_if *ifp, const char *name, void *data,
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+index 9d248ba1c0b2b..e74a23e11830c 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+@@ -584,7 +584,7 @@ struct brcmf_wsec_key_le {
+ struct brcmf_wsec_pmk_le {
+ __le16 key_len;
+ __le16 flags;
+- u8 key[2 * BRCMF_WSEC_MAX_PSK_LEN + 1];
++ u8 key[BRCMF_WSEC_MAX_SAE_PASSWORD_LEN];
+ };
+
+ /**
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwvid.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwvid.c
+index 86eafdb405419..b427782554b59 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwvid.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwvid.c
+@@ -89,8 +89,7 @@ int brcmf_fwvid_register_vendor(enum brcmf_fwvendor fwvid, struct module *vmod,
+ if (fwvid >= BRCMF_FWVENDOR_NUM)
+ return -ERANGE;
+
+- if (WARN_ON(!vmod) || WARN_ON(!vops) ||
+- WARN_ON(!vops->attach) || WARN_ON(!vops->detach))
++ if (WARN_ON(!vmod) || WARN_ON(!vops))
+ return -EINVAL;
+
+ if (WARN_ON(fwvid_list[fwvid].vmod))
+@@ -150,7 +149,7 @@ static inline int brcmf_fwvid_request_module(enum brcmf_fwvendor fwvid)
+ }
+ #endif
+
+-int brcmf_fwvid_attach_ops(struct brcmf_pub *drvr)
++int brcmf_fwvid_attach(struct brcmf_pub *drvr)
+ {
+ enum brcmf_fwvendor fwvid = drvr->bus_if->fwvid;
+ int ret;
+@@ -175,7 +174,7 @@ int brcmf_fwvid_attach_ops(struct brcmf_pub *drvr)
+ return ret;
+ }
+
+-void brcmf_fwvid_detach_ops(struct brcmf_pub *drvr)
++void brcmf_fwvid_detach(struct brcmf_pub *drvr)
+ {
+ enum brcmf_fwvendor fwvid = drvr->bus_if->fwvid;
+
+@@ -187,9 +186,10 @@ void brcmf_fwvid_detach_ops(struct brcmf_pub *drvr)
+
+ mutex_lock(&fwvid_list_lock);
+
+- drvr->vops = NULL;
+- list_del(&drvr->bus_if->list);
+-
++ if (drvr->vops) {
++ drvr->vops = NULL;
++ list_del(&drvr->bus_if->list);
++ }
+ mutex_unlock(&fwvid_list_lock);
+ }
+
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwvid.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwvid.h
+index 43df58bb70ad3..dac22534d0334 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwvid.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwvid.h
+@@ -6,12 +6,14 @@
+ #define FWVID_H_
+
+ #include "firmware.h"
++#include "cfg80211.h"
+
+ struct brcmf_pub;
++struct brcmf_if;
+
+ struct brcmf_fwvid_ops {
+- int (*attach)(struct brcmf_pub *drvr);
+- void (*detach)(struct brcmf_pub *drvr);
++ void (*feat_attach)(struct brcmf_if *ifp);
++ int (*set_sae_password)(struct brcmf_if *ifp, struct cfg80211_crypto_settings *crypto);
+ };
+
+ /* exported functions */
+@@ -20,28 +22,29 @@ int brcmf_fwvid_register_vendor(enum brcmf_fwvendor fwvid, struct module *mod,
+ int brcmf_fwvid_unregister_vendor(enum brcmf_fwvendor fwvid, struct module *mod);
+
+ /* core driver functions */
+-int brcmf_fwvid_attach_ops(struct brcmf_pub *drvr);
+-void brcmf_fwvid_detach_ops(struct brcmf_pub *drvr);
++int brcmf_fwvid_attach(struct brcmf_pub *drvr);
++void brcmf_fwvid_detach(struct brcmf_pub *drvr);
+ const char *brcmf_fwvid_vendor_name(struct brcmf_pub *drvr);
+
+-static inline int brcmf_fwvid_attach(struct brcmf_pub *drvr)
++static inline void brcmf_fwvid_feat_attach(struct brcmf_if *ifp)
+ {
+- int ret;
++ const struct brcmf_fwvid_ops *vops = ifp->drvr->vops;
+
+- ret = brcmf_fwvid_attach_ops(drvr);
+- if (ret)
+- return ret;
++ if (!vops->feat_attach)
++ return;
+
+- return drvr->vops->attach(drvr);
++ vops->feat_attach(ifp);
+ }
+
+-static inline void brcmf_fwvid_detach(struct brcmf_pub *drvr)
++static inline int brcmf_fwvid_set_sae_password(struct brcmf_if *ifp,
++ struct cfg80211_crypto_settings *crypto)
+ {
+- if (!drvr->vops)
+- return;
++ const struct brcmf_fwvid_ops *vops = ifp->drvr->vops;
++
++ if (!vops || !vops->set_sae_password)
++ return -EOPNOTSUPP;
+
+- drvr->vops->detach(drvr);
+- brcmf_fwvid_detach_ops(drvr);
++ return vops->set_sae_password(ifp, crypto);
+ }
+
+ #endif /* FWVID_H_ */
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c
+index 5573a47766ad5..fd593b93ad404 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c
+@@ -7,21 +7,17 @@
+ #include <core.h>
+ #include <bus.h>
+ #include <fwvid.h>
++#include <cfg80211.h>
+
+ #include "vops.h"
+
+-static int brcmf_wcc_attach(struct brcmf_pub *drvr)
++static int brcmf_wcc_set_sae_pwd(struct brcmf_if *ifp,
++ struct cfg80211_crypto_settings *crypto)
+ {
+- pr_debug("%s: executing\n", __func__);
+- return 0;
+-}
+-
+-static void brcmf_wcc_detach(struct brcmf_pub *drvr)
+-{
+- pr_debug("%s: executing\n", __func__);
++ return brcmf_set_wsec(ifp, crypto->sae_pwd, crypto->sae_pwd_len,
++ BRCMF_WSEC_PASSPHRASE);
+ }
+
+ const struct brcmf_fwvid_ops brcmf_wcc_ops = {
+- .attach = brcmf_wcc_attach,
+- .detach = brcmf_wcc_detach,
++ .set_sae_password = brcmf_wcc_set_sae_pwd,
+ };
+diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+index 80fda056e46a6..59f7a75c7201d 100644
+--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
++++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+@@ -3074,8 +3074,6 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
+ struct iwl_fw_dbg_params params = {0};
+ struct iwl_fwrt_dump_data *dump_data =
+ &fwrt->dump.wks[wk_idx].dump_data;
+- u32 policy;
+- u32 time_point;
+ if (!test_bit(wk_idx, &fwrt->dump.active_wks))
+ return;
+
+@@ -3106,13 +3104,16 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx)
+
+ iwl_fw_dbg_stop_restart_recording(fwrt, ¶ms, false);
+
+- policy = le32_to_cpu(dump_data->trig->apply_policy);
+- time_point = le32_to_cpu(dump_data->trig->time_point);
++ if (iwl_trans_dbg_ini_valid(fwrt->trans)) {
++ u32 policy = le32_to_cpu(dump_data->trig->apply_policy);
++ u32 time_point = le32_to_cpu(dump_data->trig->time_point);
+
+- if (policy & IWL_FW_INI_APPLY_POLICY_DUMP_COMPLETE_CMD) {
+- IWL_DEBUG_FW_INFO(fwrt, "WRT: sending dump complete\n");
+- iwl_send_dbg_dump_complete_cmd(fwrt, time_point, 0);
++ if (policy & IWL_FW_INI_APPLY_POLICY_DUMP_COMPLETE_CMD) {
++ IWL_DEBUG_FW_INFO(fwrt, "WRT: sending dump complete\n");
++ iwl_send_dbg_dump_complete_cmd(fwrt, time_point, 0);
++ }
+ }
++
+ if (fwrt->trans->dbg.last_tp_resetfw == IWL_FW_INI_RESET_FW_MODE_STOP_FW_ONLY)
+ iwl_force_nmi(fwrt->trans);
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+index e8b881596baf1..34b8771d1edac 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c
+@@ -735,7 +735,9 @@ void iwl_mvm_vif_dbgfs_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+ {
+ struct dentry *dbgfs_dir = vif->debugfs_dir;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+- char buf[100];
++ char buf[3 * 3 + 11 + (NL80211_WIPHY_NAME_MAXLEN + 1) +
++ (7 + IFNAMSIZ + 1) + 6 + 1];
++ char name[7 + IFNAMSIZ + 1];
+
+ /* this will happen in monitor mode */
+ if (!dbgfs_dir)
+@@ -748,10 +750,11 @@ void iwl_mvm_vif_dbgfs_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+ * find
+ * netdev:wlan0 -> ../../../ieee80211/phy0/netdev:wlan0/iwlmvm/
+ */
+- snprintf(buf, 100, "../../../%pd3/iwlmvm", dbgfs_dir);
++ snprintf(name, sizeof(name), "%pd", dbgfs_dir);
++ snprintf(buf, sizeof(buf), "../../../%pd3/iwlmvm", dbgfs_dir);
+
+- mvmvif->dbgfs_slink = debugfs_create_symlink(dbgfs_dir->d_name.name,
+- mvm->debugfs_dir, buf);
++ mvmvif->dbgfs_slink =
++ debugfs_create_symlink(name, mvm->debugfs_dir, buf);
+ }
+
+ void iwl_mvm_vif_dbgfs_rm_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+index f60d4258e1b95..e321d41d1aba2 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+@@ -354,7 +354,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
+ if (mvm->mld_api_is_used && mvm->nvm_data->sku_cap_11be_enable &&
+ !iwlwifi_mod_params.disable_11ax &&
+ !iwlwifi_mod_params.disable_11be)
+- hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;
++ hw->wiphy->flags |= WIPHY_FLAG_DISABLE_WEXT;
+
+ /* With MLD FW API, it tracks timing by itself,
+ * no need for any timing from the host
+diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c
+index 298663b035808..0c1c1ff31085c 100644
+--- a/drivers/net/wireless/realtek/rtw88/mac.c
++++ b/drivers/net/wireless/realtek/rtw88/mac.c
+@@ -309,6 +309,13 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
+ pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq;
+ ret = rtw_pwr_seq_parser(rtwdev, pwr_seq);
+
++ if (pwr_on && rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB) {
++ if (chip->id == RTW_CHIP_TYPE_8822C ||
++ chip->id == RTW_CHIP_TYPE_8822B ||
++ chip->id == RTW_CHIP_TYPE_8821C)
++ rtw_write8_clr(rtwdev, REG_SYS_STATUS1 + 1, BIT(0));
++ }
++
+ if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO)
+ rtw_write32(rtwdev, REG_SDIO_HIMR, imr);
+
+diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c
+index 7a5cbdc31ef79..e2c7d9f876836 100644
+--- a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c
++++ b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c
+@@ -9,24 +9,36 @@
+ #include "usb.h"
+
+ static const struct usb_device_id rtw_8821cu_id_table[] = {
+- { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82b, 0xff, 0xff, 0xff),
+- .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2006, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8731, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8811, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb820, 0xff, 0xff, 0xff),
+- .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
+- { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc821, 0xff, 0xff, 0xff),
+- .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82b, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc80c, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc811, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc820, 0xff, 0xff, 0xff),
+- .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc821, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82a, 0xff, 0xff, 0xff),
+- .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82b, 0xff, 0xff, 0xff),
+- .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */
+- { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc811, 0xff, 0xff, 0xff),
+- .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */
+- { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8811, 0xff, 0xff, 0xff),
+- .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */
+- { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2006, 0xff, 0xff, 0xff),
+- .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* TOTOLINK A650UA v3 */
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
++ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82c, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) },
++ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331d, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* D-Link */
++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xc811, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */
++ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd811, 0xff, 0xff, 0xff),
++ .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */
+ {},
+ };
+ MODULE_DEVICE_TABLE(usb, rtw_8821cu_id_table);
+diff --git a/drivers/nvmem/meson-efuse.c b/drivers/nvmem/meson-efuse.c
+index b922df99f9bc3..33678d0af2c24 100644
+--- a/drivers/nvmem/meson-efuse.c
++++ b/drivers/nvmem/meson-efuse.c
+@@ -47,7 +47,6 @@ static int meson_efuse_probe(struct platform_device *pdev)
+ struct nvmem_config *econfig;
+ struct clk *clk;
+ unsigned int size;
+- int ret;
+
+ sm_np = of_parse_phandle(pdev->dev.of_node, "secure-monitor", 0);
+ if (!sm_np) {
+@@ -60,27 +59,9 @@ static int meson_efuse_probe(struct platform_device *pdev)
+ if (!fw)
+ return -EPROBE_DEFER;
+
+- clk = devm_clk_get(dev, NULL);
+- if (IS_ERR(clk)) {
+- ret = PTR_ERR(clk);
+- if (ret != -EPROBE_DEFER)
+- dev_err(dev, "failed to get efuse gate");
+- return ret;
+- }
+-
+- ret = clk_prepare_enable(clk);
+- if (ret) {
+- dev_err(dev, "failed to enable gate");
+- return ret;
+- }
+-
+- ret = devm_add_action_or_reset(dev,
+- (void(*)(void *))clk_disable_unprepare,
+- clk);
+- if (ret) {
+- dev_err(dev, "failed to add disable callback");
+- return ret;
+- }
++ clk = devm_clk_get_enabled(dev, NULL);
++ if (IS_ERR(clk))
++ return dev_err_probe(dev, PTR_ERR(clk), "failed to get efuse gate");
+
+ if (meson_sm_call(fw, SM_EFUSE_USER_MAX, &size, 0, 0, 0, 0, 0) < 0) {
+ dev_err(dev, "failed to get max user");
+diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
+index 9a437cfce073c..746a11dcb67f1 100644
+--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
++++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
+@@ -629,8 +629,13 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
+ nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >>
+ PCI_REBAR_CTRL_NBAR_SHIFT;
+
++ /*
++ * PCIe r6.0, sec 7.8.6.2 require us to support at least one
++ * size in the range from 1 MB to 512 GB. Advertise support
++ * for 1 MB BAR size only.
++ */
+ for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL)
+- dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0);
++ dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, BIT(4));
+ }
+
+ /*
+diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
+index 2ce2a3bd932bd..23bb0eee5c411 100644
+--- a/drivers/pci/controller/dwc/pcie-qcom.c
++++ b/drivers/pci/controller/dwc/pcie-qcom.c
+@@ -53,6 +53,7 @@
+ #define PARF_SLV_ADDR_SPACE_SIZE 0x358
+ #define PARF_DEVICE_TYPE 0x1000
+ #define PARF_BDF_TO_SID_TABLE_N 0x2000
++#define PARF_BDF_TO_SID_CFG 0x2c00
+
+ /* ELBI registers */
+ #define ELBI_SYS_CTRL 0x04
+@@ -120,6 +121,9 @@
+ /* PARF_DEVICE_TYPE register fields */
+ #define DEVICE_TYPE_RC 0x4
+
++/* PARF_BDF_TO_SID_CFG fields */
++#define BDF_TO_SID_BYPASS BIT(0)
++
+ /* ELBI_SYS_CTRL register fields */
+ #define ELBI_SYS_CTRL_LT_ENABLE BIT(0)
+
+@@ -229,6 +233,7 @@ struct qcom_pcie_ops {
+
+ struct qcom_pcie_cfg {
+ const struct qcom_pcie_ops *ops;
++ bool no_l0s;
+ };
+
+ struct qcom_pcie {
+@@ -272,6 +277,26 @@ static int qcom_pcie_start_link(struct dw_pcie *pci)
+ return 0;
+ }
+
++static void qcom_pcie_clear_aspm_l0s(struct dw_pcie *pci)
++{
++ struct qcom_pcie *pcie = to_qcom_pcie(pci);
++ u16 offset;
++ u32 val;
++
++ if (!pcie->cfg->no_l0s)
++ return;
++
++ offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
++
++ dw_pcie_dbi_ro_wr_en(pci);
++
++ val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP);
++ val &= ~PCI_EXP_LNKCAP_ASPM_L0S;
++ writel(val, pci->dbi_base + offset + PCI_EXP_LNKCAP);
++
++ dw_pcie_dbi_ro_wr_dis(pci);
++}
++
+ static void qcom_pcie_clear_hpc(struct dw_pcie *pci)
+ {
+ u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+@@ -961,6 +986,7 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie)
+
+ static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)
+ {
++ qcom_pcie_clear_aspm_l0s(pcie->pci);
+ qcom_pcie_clear_hpc(pcie->pci);
+
+ return 0;
+@@ -1008,11 +1034,17 @@ static int qcom_pcie_config_sid_1_9_0(struct qcom_pcie *pcie)
+ u8 qcom_pcie_crc8_table[CRC8_TABLE_SIZE];
+ int i, nr_map, size = 0;
+ u32 smmu_sid_base;
++ u32 val;
+
+ of_get_property(dev->of_node, "iommu-map", &size);
+ if (!size)
+ return 0;
+
++ /* Enable BDF to SID translation by disabling bypass mode (default) */
++ val = readl(pcie->parf + PARF_BDF_TO_SID_CFG);
++ val &= ~BDF_TO_SID_BYPASS;
++ writel(val, pcie->parf + PARF_BDF_TO_SID_CFG);
++
+ map = kzalloc(size, GFP_KERNEL);
+ if (!map)
+ return -ENOMEM;
+@@ -1358,6 +1390,11 @@ static const struct qcom_pcie_cfg cfg_2_9_0 = {
+ .ops = &ops_2_9_0,
+ };
+
++static const struct qcom_pcie_cfg cfg_sc8280xp = {
++ .ops = &ops_1_9_0,
++ .no_l0s = true,
++};
++
+ static const struct dw_pcie_ops dw_pcie_ops = {
+ .link_up = qcom_pcie_link_up,
+ .start_link = qcom_pcie_start_link,
+@@ -1629,11 +1666,11 @@ static const struct of_device_id qcom_pcie_match[] = {
+ { .compatible = "qcom,pcie-ipq8074-gen3", .data = &cfg_2_9_0 },
+ { .compatible = "qcom,pcie-msm8996", .data = &cfg_2_3_2 },
+ { .compatible = "qcom,pcie-qcs404", .data = &cfg_2_4_0 },
+- { .compatible = "qcom,pcie-sa8540p", .data = &cfg_1_9_0 },
++ { .compatible = "qcom,pcie-sa8540p", .data = &cfg_sc8280xp },
+ { .compatible = "qcom,pcie-sa8775p", .data = &cfg_1_9_0},
+ { .compatible = "qcom,pcie-sc7280", .data = &cfg_1_9_0 },
+ { .compatible = "qcom,pcie-sc8180x", .data = &cfg_1_9_0 },
+- { .compatible = "qcom,pcie-sc8280xp", .data = &cfg_1_9_0 },
++ { .compatible = "qcom,pcie-sc8280xp", .data = &cfg_sc8280xp },
+ { .compatible = "qcom,pcie-sdm845", .data = &cfg_2_7_0 },
+ { .compatible = "qcom,pcie-sdx55", .data = &cfg_1_9_0 },
+ { .compatible = "qcom,pcie-sm8150", .data = &cfg_1_9_0 },
+diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
+index 1eaffff40b8d4..5992280e8110b 100644
+--- a/drivers/pci/controller/pci-hyperv.c
++++ b/drivers/pci/controller/pci-hyperv.c
+@@ -49,6 +49,7 @@
+ #include <linux/refcount.h>
+ #include <linux/irqdomain.h>
+ #include <linux/acpi.h>
++#include <linux/sizes.h>
+ #include <asm/mshyperv.h>
+
+ /*
+@@ -465,7 +466,7 @@ struct pci_eject_response {
+ u32 status;
+ } __packed;
+
+-static int pci_ring_size = (4 * PAGE_SIZE);
++static int pci_ring_size = VMBUS_RING_SIZE(SZ_16K);
+
+ /*
+ * Driver specific state.
+diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
+index 51ec9e7e784f0..9c59bf03d6579 100644
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -473,6 +473,13 @@ static void pci_device_remove(struct device *dev)
+
+ if (drv->remove) {
+ pm_runtime_get_sync(dev);
++ /*
++ * If the driver provides a .runtime_idle() callback and it has
++ * started to run already, it may continue to run in parallel
++ * with the code below, so wait until all of the runtime PM
++ * activity has completed.
++ */
++ pm_runtime_barrier(dev);
+ drv->remove(pci_dev);
+ pm_runtime_put_noidle(dev);
+ }
+diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
+index 59c90d04a609a..705893b5f7b09 100644
+--- a/drivers/pci/pcie/err.c
++++ b/drivers/pci/pcie/err.c
+@@ -13,6 +13,7 @@
+ #define dev_fmt(fmt) "AER: " fmt
+
+ #include <linux/pci.h>
++#include <linux/pm_runtime.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+@@ -85,6 +86,18 @@ static int report_error_detected(struct pci_dev *dev,
+ return 0;
+ }
+
++static int pci_pm_runtime_get_sync(struct pci_dev *pdev, void *data)
++{
++ pm_runtime_get_sync(&pdev->dev);
++ return 0;
++}
++
++static int pci_pm_runtime_put(struct pci_dev *pdev, void *data)
++{
++ pm_runtime_put(&pdev->dev);
++ return 0;
++}
++
+ static int report_frozen_detected(struct pci_dev *dev, void *data)
+ {
+ return report_error_detected(dev, pci_channel_io_frozen, data);
+@@ -207,6 +220,8 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ else
+ bridge = pci_upstream_bridge(dev);
+
++ pci_walk_bridge(bridge, pci_pm_runtime_get_sync, NULL);
++
+ pci_dbg(bridge, "broadcast error_detected message\n");
+ if (state == pci_channel_io_frozen) {
+ pci_walk_bridge(bridge, report_frozen_detected, &status);
+@@ -251,10 +266,15 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ pcie_clear_device_status(dev);
+ pci_aer_clear_nonfatal_status(dev);
+ }
++
++ pci_walk_bridge(bridge, pci_pm_runtime_put, NULL);
++
+ pci_info(bridge, "device recovery successful\n");
+ return status;
+
+ failed:
++ pci_walk_bridge(bridge, pci_pm_runtime_put, NULL);
++
+ pci_uevent_ers(bridge, PCI_ERS_RESULT_DISCONNECT);
+
+ /* TODO: Should kernel panic here? */
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index 2ebbe51a7efe0..eff7f5df08e27 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -6226,6 +6226,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2b, dpc_log_size);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2d, dpc_log_size);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2f, dpc_log_size);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a31, dpc_log_size);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa73f, dpc_log_size);
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa76e, dpc_log_size);
+ #endif
+
+ /*
+diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
+index 142ebe0247cc0..983a6e6173bd2 100644
+--- a/drivers/phy/tegra/xusb.c
++++ b/drivers/phy/tegra/xusb.c
+@@ -1531,6 +1531,19 @@ int tegra_xusb_padctl_get_usb3_companion(struct tegra_xusb_padctl *padctl,
+ }
+ EXPORT_SYMBOL_GPL(tegra_xusb_padctl_get_usb3_companion);
+
++int tegra_xusb_padctl_get_port_number(struct phy *phy)
++{
++ struct tegra_xusb_lane *lane;
++
++ if (!phy)
++ return -ENODEV;
++
++ lane = phy_get_drvdata(phy);
++
++ return lane->index;
++}
++EXPORT_SYMBOL_GPL(tegra_xusb_padctl_get_port_number);
++
+ MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
+ MODULE_DESCRIPTION("Tegra XUSB Pad Controller driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
+index 49f89b70dcecb..7f66ec73199a9 100644
+--- a/drivers/pinctrl/pinctrl-amd.c
++++ b/drivers/pinctrl/pinctrl-amd.c
+@@ -1159,7 +1159,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
+ }
+
+ ret = devm_request_irq(&pdev->dev, gpio_dev->irq, amd_gpio_irq_handler,
+- IRQF_SHARED | IRQF_ONESHOT, KBUILD_MODNAME, gpio_dev);
++ IRQF_SHARED | IRQF_COND_ONESHOT, KBUILD_MODNAME, gpio_dev);
+ if (ret)
+ goto out2;
+
+diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
+index e0f2829c15d6a..24619e80b2cce 100644
+--- a/drivers/pinctrl/qcom/Kconfig
++++ b/drivers/pinctrl/qcom/Kconfig
+@@ -125,7 +125,7 @@ config PINCTRL_SM8550_LPASS_LPI
+ platform.
+
+ config PINCTRL_SM8650_LPASS_LPI
+- tristate "Qualcomm Technologies Inc SM8550 LPASS LPI pin controller driver"
++ tristate "Qualcomm Technologies Inc SM8650 LPASS LPI pin controller driver"
+ depends on ARM64 || COMPILE_TEST
+ depends on PINCTRL_LPASS_LPI
+ help
+diff --git a/drivers/platform/x86/intel/tpmi.c b/drivers/platform/x86/intel/tpmi.c
+index e73cdea67fff8..910df7c654f48 100644
+--- a/drivers/platform/x86/intel/tpmi.c
++++ b/drivers/platform/x86/intel/tpmi.c
+@@ -96,7 +96,7 @@ struct intel_tpmi_pfs_entry {
+ */
+ struct intel_tpmi_pm_feature {
+ struct intel_tpmi_pfs_entry pfs_header;
+- unsigned int vsec_offset;
++ u64 vsec_offset;
+ struct intel_vsec_device *vsec_dev;
+ };
+
+@@ -376,7 +376,7 @@ static int tpmi_pfs_dbg_show(struct seq_file *s, void *unused)
+ read_blocked = feature_state.read_blocked ? 'Y' : 'N';
+ write_blocked = feature_state.write_blocked ? 'Y' : 'N';
+ }
+- seq_printf(s, "0x%02x\t\t0x%02x\t\t0x%04x\t\t0x%04x\t\t0x%02x\t\t0x%08x\t%c\t%c\t\t%c\t\t%c\n",
++ seq_printf(s, "0x%02x\t\t0x%02x\t\t0x%04x\t\t0x%04x\t\t0x%02x\t\t0x%016llx\t%c\t%c\t\t%c\t\t%c\n",
+ pfs->pfs_header.tpmi_id, pfs->pfs_header.num_entries,
+ pfs->pfs_header.entry_size, pfs->pfs_header.cap_offset,
+ pfs->pfs_header.attribute, pfs->vsec_offset, locked, disabled,
+@@ -395,7 +395,8 @@ static int tpmi_mem_dump_show(struct seq_file *s, void *unused)
+ struct intel_tpmi_pm_feature *pfs = s->private;
+ int count, ret = 0;
+ void __iomem *mem;
+- u32 off, size;
++ u32 size;
++ u64 off;
+ u8 *buffer;
+
+ size = TPMI_GET_SINGLE_ENTRY_SIZE(pfs);
+@@ -411,7 +412,7 @@ static int tpmi_mem_dump_show(struct seq_file *s, void *unused)
+ mutex_lock(&tpmi_dev_lock);
+
+ for (count = 0; count < pfs->pfs_header.num_entries; ++count) {
+- seq_printf(s, "TPMI Instance:%d offset:0x%x\n", count, off);
++ seq_printf(s, "TPMI Instance:%d offset:0x%llx\n", count, off);
+
+ mem = ioremap(off, size);
+ if (!mem) {
+diff --git a/drivers/powercap/intel_rapl_common.c b/drivers/powercap/intel_rapl_common.c
+index 2feed036c1cd4..9d3e102f1a76b 100644
+--- a/drivers/powercap/intel_rapl_common.c
++++ b/drivers/powercap/intel_rapl_common.c
+@@ -5,6 +5,7 @@
+ */
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
++#include <linux/cleanup.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/list.h>
+@@ -759,6 +760,11 @@ static int rapl_config(struct rapl_package *rp)
+ default:
+ return -EINVAL;
+ }
++
++ /* defaults_msr can be NULL on unsupported platforms */
++ if (!rp->priv->defaults || !rp->priv->rpi)
++ return -ENODEV;
++
+ return 0;
+ }
+
+@@ -1499,7 +1505,7 @@ static int rapl_detect_domains(struct rapl_package *rp)
+ }
+
+ /* called from CPU hotplug notifier, hotplug lock held */
+-void rapl_remove_package(struct rapl_package *rp)
++void rapl_remove_package_cpuslocked(struct rapl_package *rp)
+ {
+ struct rapl_domain *rd, *rd_package = NULL;
+
+@@ -1528,10 +1534,18 @@ void rapl_remove_package(struct rapl_package *rp)
+ list_del(&rp->plist);
+ kfree(rp);
+ }
++EXPORT_SYMBOL_GPL(rapl_remove_package_cpuslocked);
++
++void rapl_remove_package(struct rapl_package *rp)
++{
++ guard(cpus_read_lock)();
++ rapl_remove_package_cpuslocked(rp);
++}
+ EXPORT_SYMBOL_GPL(rapl_remove_package);
+
+ /* caller to ensure CPU hotplug lock is held */
+-struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv, bool id_is_cpu)
++struct rapl_package *rapl_find_package_domain_cpuslocked(int id, struct rapl_if_priv *priv,
++ bool id_is_cpu)
+ {
+ struct rapl_package *rp;
+ int uid;
+@@ -1549,10 +1563,17 @@ struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv,
+
+ return NULL;
+ }
++EXPORT_SYMBOL_GPL(rapl_find_package_domain_cpuslocked);
++
++struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv, bool id_is_cpu)
++{
++ guard(cpus_read_lock)();
++ return rapl_find_package_domain_cpuslocked(id, priv, id_is_cpu);
++}
+ EXPORT_SYMBOL_GPL(rapl_find_package_domain);
+
+ /* called from CPU hotplug notifier, hotplug lock held */
+-struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id_is_cpu)
++struct rapl_package *rapl_add_package_cpuslocked(int id, struct rapl_if_priv *priv, bool id_is_cpu)
+ {
+ struct rapl_package *rp;
+ int ret;
+@@ -1598,6 +1619,13 @@ struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id
+ kfree(rp);
+ return ERR_PTR(ret);
+ }
++EXPORT_SYMBOL_GPL(rapl_add_package_cpuslocked);
++
++struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id_is_cpu)
++{
++ guard(cpus_read_lock)();
++ return rapl_add_package_cpuslocked(id, priv, id_is_cpu);
++}
+ EXPORT_SYMBOL_GPL(rapl_add_package);
+
+ static void power_limit_state_save(void)
+diff --git a/drivers/powercap/intel_rapl_msr.c b/drivers/powercap/intel_rapl_msr.c
+index 250bd41a588c7..b4b6930cacb0b 100644
+--- a/drivers/powercap/intel_rapl_msr.c
++++ b/drivers/powercap/intel_rapl_msr.c
+@@ -73,9 +73,9 @@ static int rapl_cpu_online(unsigned int cpu)
+ {
+ struct rapl_package *rp;
+
+- rp = rapl_find_package_domain(cpu, rapl_msr_priv, true);
++ rp = rapl_find_package_domain_cpuslocked(cpu, rapl_msr_priv, true);
+ if (!rp) {
+- rp = rapl_add_package(cpu, rapl_msr_priv, true);
++ rp = rapl_add_package_cpuslocked(cpu, rapl_msr_priv, true);
+ if (IS_ERR(rp))
+ return PTR_ERR(rp);
+ }
+@@ -88,14 +88,14 @@ static int rapl_cpu_down_prep(unsigned int cpu)
+ struct rapl_package *rp;
+ int lead_cpu;
+
+- rp = rapl_find_package_domain(cpu, rapl_msr_priv, true);
++ rp = rapl_find_package_domain_cpuslocked(cpu, rapl_msr_priv, true);
+ if (!rp)
+ return 0;
+
+ cpumask_clear_cpu(cpu, &rp->cpumask);
+ lead_cpu = cpumask_first(&rp->cpumask);
+ if (lead_cpu >= nr_cpu_ids)
+- rapl_remove_package(rp);
++ rapl_remove_package_cpuslocked(rp);
+ else if (rp->lead_cpu == cpu)
+ rp->lead_cpu = lead_cpu;
+ return 0;
+diff --git a/drivers/powercap/intel_rapl_tpmi.c b/drivers/powercap/intel_rapl_tpmi.c
+index 891c90fefd8b7..f6b7f085977ce 100644
+--- a/drivers/powercap/intel_rapl_tpmi.c
++++ b/drivers/powercap/intel_rapl_tpmi.c
+@@ -40,6 +40,7 @@ enum tpmi_rapl_register {
+ TPMI_RAPL_REG_ENERGY_STATUS,
+ TPMI_RAPL_REG_PERF_STATUS,
+ TPMI_RAPL_REG_POWER_INFO,
++ TPMI_RAPL_REG_DOMAIN_INFO,
+ TPMI_RAPL_REG_INTERRUPT,
+ TPMI_RAPL_REG_MAX = 15,
+ };
+@@ -130,6 +131,12 @@ static void trp_release(struct tpmi_rapl_package *trp)
+ mutex_unlock(&tpmi_rapl_lock);
+ }
+
++/*
++ * Bit 0 of TPMI_RAPL_REG_DOMAIN_INFO indicates if the current package is a domain
++ * root or not. Only domain root packages can enumerate System (Psys) Domain.
++ */
++#define TPMI_RAPL_DOMAIN_ROOT BIT(0)
++
+ static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset)
+ {
+ u8 tpmi_domain_version;
+@@ -139,6 +146,7 @@ static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset)
+ enum rapl_domain_reg_id reg_id;
+ int tpmi_domain_size, tpmi_domain_flags;
+ u64 tpmi_domain_header = readq(trp->base + offset);
++ u64 tpmi_domain_info;
+
+ /* Domain Parent bits are ignored for now */
+ tpmi_domain_version = tpmi_domain_header & 0xff;
+@@ -169,6 +177,13 @@ static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset)
+ domain_type = RAPL_DOMAIN_PACKAGE;
+ break;
+ case TPMI_RAPL_DOMAIN_SYSTEM:
++ if (!(tpmi_domain_flags & BIT(TPMI_RAPL_REG_DOMAIN_INFO))) {
++ pr_warn(FW_BUG "System domain must support Domain Info register\n");
++ return -ENODEV;
++ }
++ tpmi_domain_info = readq(trp->base + offset + TPMI_RAPL_REG_DOMAIN_INFO);
++ if (!(tpmi_domain_info & TPMI_RAPL_DOMAIN_ROOT))
++ return 0;
+ domain_type = RAPL_DOMAIN_PLATFORM;
+ break;
+ case TPMI_RAPL_DOMAIN_MEMORY:
+diff --git a/drivers/pwm/pwm-img.c b/drivers/pwm/pwm-img.c
+index 5965ac35b32ea..54dbafc51627e 100644
+--- a/drivers/pwm/pwm-img.c
++++ b/drivers/pwm/pwm-img.c
+@@ -284,9 +284,9 @@ static int img_pwm_probe(struct platform_device *pdev)
+ return PTR_ERR(imgchip->sys_clk);
+ }
+
+- imgchip->pwm_clk = devm_clk_get(&pdev->dev, "imgchip");
++ imgchip->pwm_clk = devm_clk_get(&pdev->dev, "pwm");
+ if (IS_ERR(imgchip->pwm_clk)) {
+- dev_err(&pdev->dev, "failed to get imgchip clock\n");
++ dev_err(&pdev->dev, "failed to get pwm clock\n");
+ return PTR_ERR(imgchip->pwm_clk);
+ }
+
+diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
+index 83d76915a6ad6..25b66b113b695 100644
+--- a/drivers/remoteproc/remoteproc_virtio.c
++++ b/drivers/remoteproc/remoteproc_virtio.c
+@@ -351,6 +351,9 @@ static void rproc_virtio_dev_release(struct device *dev)
+
+ kfree(vdev);
+
++ of_reserved_mem_device_release(&rvdev->pdev->dev);
++ dma_release_coherent_memory(&rvdev->pdev->dev);
++
+ put_device(&rvdev->pdev->dev);
+ }
+
+@@ -584,9 +587,6 @@ static void rproc_virtio_remove(struct platform_device *pdev)
+ rproc_remove_subdev(rproc, &rvdev->subdev);
+ rproc_remove_rvdev(rvdev);
+
+- of_reserved_mem_device_release(&pdev->dev);
+- dma_release_coherent_memory(&pdev->dev);
+-
+ put_device(&rproc->dev);
+ }
+
+diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c
+index 74200f54dfff7..53ddae5ad890b 100644
+--- a/drivers/s390/crypto/zcrypt_api.c
++++ b/drivers/s390/crypto/zcrypt_api.c
+@@ -579,6 +579,7 @@ static inline struct zcrypt_queue *zcrypt_pick_queue(struct zcrypt_card *zc,
+ {
+ if (!zq || !try_module_get(zq->queue->ap_dev.device.driver->owner))
+ return NULL;
++ zcrypt_card_get(zc);
+ zcrypt_queue_get(zq);
+ get_device(&zq->queue->ap_dev.device);
+ atomic_add(weight, &zc->load);
+@@ -598,6 +599,7 @@ static inline void zcrypt_drop_queue(struct zcrypt_card *zc,
+ atomic_sub(weight, &zq->load);
+ put_device(&zq->queue->ap_dev.device);
+ zcrypt_queue_put(zq);
++ zcrypt_card_put(zc);
+ module_put(mod);
+ }
+
+diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
+index d7f51b84f3c78..445f4a220df3e 100644
+--- a/drivers/scsi/hosts.c
++++ b/drivers/scsi/hosts.c
+@@ -353,12 +353,13 @@ static void scsi_host_dev_release(struct device *dev)
+
+ if (shost->shost_state == SHOST_CREATED) {
+ /*
+- * Free the shost_dev device name here if scsi_host_alloc()
+- * and scsi_host_put() have been called but neither
++ * Free the shost_dev device name and remove the proc host dir
++ * here if scsi_host_{alloc,put}() have been called but neither
+ * scsi_host_add() nor scsi_remove_host() has been called.
+ * This avoids that the memory allocated for the shost_dev
+- * name is leaked.
++ * name as well as the proc dir structure are leaked.
+ */
++ scsi_proc_hostdir_rm(shost->hostt);
+ kfree(dev_name(&shost->shost_dev));
+ }
+
+diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
+index a2204674b6808..5c261005b74e4 100644
+--- a/drivers/scsi/libsas/sas_expander.c
++++ b/drivers/scsi/libsas/sas_expander.c
+@@ -1621,6 +1621,16 @@ int sas_discover_root_expander(struct domain_device *dev)
+
+ /* ---------- Domain revalidation ---------- */
+
++static void sas_get_sas_addr_and_dev_type(struct smp_disc_resp *disc_resp,
++ u8 *sas_addr,
++ enum sas_device_type *type)
++{
++ memcpy(sas_addr, disc_resp->disc.attached_sas_addr, SAS_ADDR_SIZE);
++ *type = to_dev_type(&disc_resp->disc);
++ if (*type == SAS_PHY_UNUSED)
++ memset(sas_addr, 0, SAS_ADDR_SIZE);
++}
++
+ static int sas_get_phy_discover(struct domain_device *dev,
+ int phy_id, struct smp_disc_resp *disc_resp)
+ {
+@@ -1674,13 +1684,8 @@ int sas_get_phy_attached_dev(struct domain_device *dev, int phy_id,
+ return -ENOMEM;
+
+ res = sas_get_phy_discover(dev, phy_id, disc_resp);
+- if (res == 0) {
+- memcpy(sas_addr, disc_resp->disc.attached_sas_addr,
+- SAS_ADDR_SIZE);
+- *type = to_dev_type(&disc_resp->disc);
+- if (*type == 0)
+- memset(sas_addr, 0, SAS_ADDR_SIZE);
+- }
++ if (res == 0)
++ sas_get_sas_addr_and_dev_type(disc_resp, sas_addr, type);
+ kfree(disc_resp);
+ return res;
+ }
+@@ -1940,6 +1945,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
+ struct expander_device *ex = &dev->ex_dev;
+ struct ex_phy *phy = &ex->ex_phy[phy_id];
+ enum sas_device_type type = SAS_PHY_UNUSED;
++ struct smp_disc_resp *disc_resp;
+ u8 sas_addr[SAS_ADDR_SIZE];
+ char msg[80] = "";
+ int res;
+@@ -1951,33 +1957,41 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
+ SAS_ADDR(dev->sas_addr), phy_id, msg);
+
+ memset(sas_addr, 0, SAS_ADDR_SIZE);
+- res = sas_get_phy_attached_dev(dev, phy_id, sas_addr, &type);
++ disc_resp = alloc_smp_resp(DISCOVER_RESP_SIZE);
++ if (!disc_resp)
++ return -ENOMEM;
++
++ res = sas_get_phy_discover(dev, phy_id, disc_resp);
+ switch (res) {
+ case SMP_RESP_NO_PHY:
+ phy->phy_state = PHY_NOT_PRESENT;
+ sas_unregister_devs_sas_addr(dev, phy_id, last);
+- return res;
++ goto out_free_resp;
+ case SMP_RESP_PHY_VACANT:
+ phy->phy_state = PHY_VACANT;
+ sas_unregister_devs_sas_addr(dev, phy_id, last);
+- return res;
++ goto out_free_resp;
+ case SMP_RESP_FUNC_ACC:
+ break;
+ case -ECOMM:
+ break;
+ default:
+- return res;
++ goto out_free_resp;
+ }
+
++ if (res == 0)
++ sas_get_sas_addr_and_dev_type(disc_resp, sas_addr, &type);
++
+ if ((SAS_ADDR(sas_addr) == 0) || (res == -ECOMM)) {
+ phy->phy_state = PHY_EMPTY;
+ sas_unregister_devs_sas_addr(dev, phy_id, last);
+ /*
+- * Even though the PHY is empty, for convenience we discover
+- * the PHY to update the PHY info, like negotiated linkrate.
++ * Even though the PHY is empty, for convenience we update
++ * the PHY info, like negotiated linkrate.
+ */
+- sas_ex_phy_discover(dev, phy_id);
+- return res;
++ if (res == 0)
++ sas_set_ex_phy(dev, phy_id, disc_resp);
++ goto out_free_resp;
+ } else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) &&
+ dev_type_flutter(type, phy->attached_dev_type)) {
+ struct domain_device *ata_dev = sas_ex_to_ata(dev, phy_id);
+@@ -1989,7 +2003,7 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
+ action = ", needs recovery";
+ pr_debug("ex %016llx phy%02d broadcast flutter%s\n",
+ SAS_ADDR(dev->sas_addr), phy_id, action);
+- return res;
++ goto out_free_resp;
+ }
+
+ /* we always have to delete the old device when we went here */
+@@ -1998,7 +2012,10 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id,
+ SAS_ADDR(phy->attached_sas_addr));
+ sas_unregister_devs_sas_addr(dev, phy_id, last);
+
+- return sas_discover_new(dev, phy_id);
++ res = sas_discover_new(dev, phy_id);
++out_free_resp:
++ kfree(disc_resp);
++ return res;
+ }
+
+ /**
+diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
+index 595dca92e8db5..2919579fa0846 100644
+--- a/drivers/scsi/lpfc/lpfc_bsg.c
++++ b/drivers/scsi/lpfc/lpfc_bsg.c
+@@ -3169,10 +3169,10 @@ lpfc_bsg_diag_loopback_run(struct bsg_job *job)
+ }
+
+ cmdwqe = &cmdiocbq->wqe;
+- memset(cmdwqe, 0, sizeof(union lpfc_wqe));
++ memset(cmdwqe, 0, sizeof(*cmdwqe));
+ if (phba->sli_rev < LPFC_SLI_REV4) {
+ rspwqe = &rspiocbq->wqe;
+- memset(rspwqe, 0, sizeof(union lpfc_wqe));
++ memset(rspwqe, 0, sizeof(*rspwqe));
+ }
+
+ INIT_LIST_HEAD(&head);
+diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
+index 425328d9c2d80..d41fea53e41e9 100644
+--- a/drivers/scsi/lpfc/lpfc_nvmet.c
++++ b/drivers/scsi/lpfc/lpfc_nvmet.c
+@@ -1586,7 +1586,7 @@ lpfc_nvmet_setup_io_context(struct lpfc_hba *phba)
+ wqe = &nvmewqe->wqe;
+
+ /* Initialize WQE */
+- memset(wqe, 0, sizeof(union lpfc_wqe));
++ memset(wqe, 0, sizeof(*wqe));
+
+ ctx_buf->iocbq->cmd_dmabuf = NULL;
+ spin_lock(&phba->sli4_hba.sgl_list_lock);
+diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
+index 44449c70a375f..76eeba435fd04 100644
+--- a/drivers/scsi/qla2xxx/qla_attr.c
++++ b/drivers/scsi/qla2xxx/qla_attr.c
+@@ -2741,7 +2741,13 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
+ return;
+
+ if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
+- qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
++ /* Will wait for wind down of adapter */
++ ql_dbg(ql_dbg_aer, fcport->vha, 0x900c,
++ "%s pci offline detected (id %06x)\n", __func__,
++ fcport->d_id.b24);
++ qla_pci_set_eeh_busy(fcport->vha);
++ qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24,
++ 0, WAIT_TARGET);
+ return;
+ }
+ }
+@@ -2763,7 +2769,11 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
+ vha = fcport->vha;
+
+ if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
+- qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
++ /* Will wait for wind down of adapter */
++ ql_dbg(ql_dbg_aer, fcport->vha, 0x900b,
++ "%s pci offline detected (id %06x)\n", __func__,
++ fcport->d_id.b24);
++ qla_pci_set_eeh_busy(vha);
+ qla2x00_eh_wait_for_pending_commands(fcport->vha, fcport->d_id.b24,
+ 0, WAIT_TARGET);
+ return;
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index deb642607deb6..2f49baf131e26 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -82,7 +82,7 @@ typedef union {
+ #include "qla_nvme.h"
+ #define QLA2XXX_DRIVER_NAME "qla2xxx"
+ #define QLA2XXX_APIDEV "ql2xapidev"
+-#define QLA2XXX_MANUFACTURER "Marvell Semiconductor, Inc."
++#define QLA2XXX_MANUFACTURER "Marvell"
+
+ /*
+ * We have MAILBOX_REGISTER_COUNT sized arrays in a few places,
+diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
+index 09cb9413670a5..7309310d2ab94 100644
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -44,7 +44,7 @@ extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
+ extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
+
+ extern int qla24xx_els_dcmd_iocb(scsi_qla_host_t *, int, port_id_t);
+-extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *, bool);
++extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *);
+ extern void qla2x00_els_dcmd2_free(scsi_qla_host_t *vha,
+ struct els_plogi *els_plogi);
+
+diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
+index a314cfc5b263f..8377624d76c98 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -1193,8 +1193,12 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
+ return rval;
+
+ done_free_sp:
+- /* ref: INIT */
+- kref_put(&sp->cmd_kref, qla2x00_sp_release);
++ /*
++ * use qla24xx_async_gnl_sp_done to purge all pending gnl request.
++ * kref_put is call behind the scene.
++ */
++ sp->u.iocb_cmd.u.mbx.in_mb[0] = MBS_COMMAND_ERROR;
++ qla24xx_async_gnl_sp_done(sp, QLA_COMMAND_ERROR);
+ fcport->flags &= ~(FCF_ASYNC_SENT);
+ done:
+ fcport->flags &= ~(FCF_ASYNC_ACTIVE);
+@@ -2665,6 +2669,40 @@ qla83xx_nic_core_fw_load(scsi_qla_host_t *vha)
+ return rval;
+ }
+
++static void qla_enable_fce_trace(scsi_qla_host_t *vha)
++{
++ int rval;
++ struct qla_hw_data *ha = vha->hw;
++
++ if (ha->fce) {
++ ha->flags.fce_enabled = 1;
++ memset(ha->fce, 0, fce_calc_size(ha->fce_bufs));
++ rval = qla2x00_enable_fce_trace(vha,
++ ha->fce_dma, ha->fce_bufs, ha->fce_mb, &ha->fce_bufs);
++
++ if (rval) {
++ ql_log(ql_log_warn, vha, 0x8033,
++ "Unable to reinitialize FCE (%d).\n", rval);
++ ha->flags.fce_enabled = 0;
++ }
++ }
++}
++
++static void qla_enable_eft_trace(scsi_qla_host_t *vha)
++{
++ int rval;
++ struct qla_hw_data *ha = vha->hw;
++
++ if (ha->eft) {
++ memset(ha->eft, 0, EFT_SIZE);
++ rval = qla2x00_enable_eft_trace(vha, ha->eft_dma, EFT_NUM_BUFFERS);
++
++ if (rval) {
++ ql_log(ql_log_warn, vha, 0x8034,
++ "Unable to reinitialize EFT (%d).\n", rval);
++ }
++ }
++}
+ /*
+ * qla2x00_initialize_adapter
+ * Initialize board.
+@@ -3668,9 +3706,8 @@ qla24xx_chip_diag(scsi_qla_host_t *vha)
+ }
+
+ static void
+-qla2x00_init_fce_trace(scsi_qla_host_t *vha)
++qla2x00_alloc_fce_trace(scsi_qla_host_t *vha)
+ {
+- int rval;
+ dma_addr_t tc_dma;
+ void *tc;
+ struct qla_hw_data *ha = vha->hw;
+@@ -3699,27 +3736,17 @@ qla2x00_init_fce_trace(scsi_qla_host_t *vha)
+ return;
+ }
+
+- rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS,
+- ha->fce_mb, &ha->fce_bufs);
+- if (rval) {
+- ql_log(ql_log_warn, vha, 0x00bf,
+- "Unable to initialize FCE (%d).\n", rval);
+- dma_free_coherent(&ha->pdev->dev, FCE_SIZE, tc, tc_dma);
+- return;
+- }
+-
+ ql_dbg(ql_dbg_init, vha, 0x00c0,
+ "Allocated (%d KB) for FCE...\n", FCE_SIZE / 1024);
+
+- ha->flags.fce_enabled = 1;
+ ha->fce_dma = tc_dma;
+ ha->fce = tc;
++ ha->fce_bufs = FCE_NUM_BUFFERS;
+ }
+
+ static void
+-qla2x00_init_eft_trace(scsi_qla_host_t *vha)
++qla2x00_alloc_eft_trace(scsi_qla_host_t *vha)
+ {
+- int rval;
+ dma_addr_t tc_dma;
+ void *tc;
+ struct qla_hw_data *ha = vha->hw;
+@@ -3744,14 +3771,6 @@ qla2x00_init_eft_trace(scsi_qla_host_t *vha)
+ return;
+ }
+
+- rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS);
+- if (rval) {
+- ql_log(ql_log_warn, vha, 0x00c2,
+- "Unable to initialize EFT (%d).\n", rval);
+- dma_free_coherent(&ha->pdev->dev, EFT_SIZE, tc, tc_dma);
+- return;
+- }
+-
+ ql_dbg(ql_dbg_init, vha, 0x00c3,
+ "Allocated (%d KB) EFT ...\n", EFT_SIZE / 1024);
+
+@@ -3759,13 +3778,6 @@ qla2x00_init_eft_trace(scsi_qla_host_t *vha)
+ ha->eft = tc;
+ }
+
+-static void
+-qla2x00_alloc_offload_mem(scsi_qla_host_t *vha)
+-{
+- qla2x00_init_fce_trace(vha);
+- qla2x00_init_eft_trace(vha);
+-}
+-
+ void
+ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
+ {
+@@ -3820,10 +3832,10 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
+ if (ha->tgt.atio_ring)
+ mq_size += ha->tgt.atio_q_length * sizeof(request_t);
+
+- qla2x00_init_fce_trace(vha);
++ qla2x00_alloc_fce_trace(vha);
+ if (ha->fce)
+ fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
+- qla2x00_init_eft_trace(vha);
++ qla2x00_alloc_eft_trace(vha);
+ if (ha->eft)
+ eft_size = EFT_SIZE;
+ }
+@@ -4253,7 +4265,6 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
+ struct qla_hw_data *ha = vha->hw;
+ struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
+ unsigned long flags;
+- uint16_t fw_major_version;
+ int done_once = 0;
+
+ if (IS_P3P_TYPE(ha)) {
+@@ -4320,7 +4331,6 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
+ goto failed;
+
+ enable_82xx_npiv:
+- fw_major_version = ha->fw_major_version;
+ if (IS_P3P_TYPE(ha))
+ qla82xx_check_md_needed(vha);
+ else
+@@ -4349,12 +4359,11 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
+ if (rval != QLA_SUCCESS)
+ goto failed;
+
+- if (!fw_major_version && !(IS_P3P_TYPE(ha)))
+- qla2x00_alloc_offload_mem(vha);
+-
+ if (ql2xallocfwdump && !(IS_P3P_TYPE(ha)))
+ qla2x00_alloc_fw_dump(vha);
+
++ qla_enable_fce_trace(vha);
++ qla_enable_eft_trace(vha);
+ } else {
+ goto failed;
+ }
+@@ -7487,12 +7496,12 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
+ int
+ qla2x00_abort_isp(scsi_qla_host_t *vha)
+ {
+- int rval;
+ uint8_t status = 0;
+ struct qla_hw_data *ha = vha->hw;
+ struct scsi_qla_host *vp, *tvp;
+ struct req_que *req = ha->req_q_map[0];
+ unsigned long flags;
++ fc_port_t *fcport;
+
+ if (vha->flags.online) {
+ qla2x00_abort_isp_cleanup(vha);
+@@ -7561,6 +7570,15 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
+ "ISP Abort - ISP reg disconnect post nvmram config, exiting.\n");
+ return status;
+ }
++
++ /* User may have updated [fcp|nvme] prefer in flash */
++ list_for_each_entry(fcport, &vha->vp_fcports, list) {
++ if (NVME_PRIORITY(ha, fcport))
++ fcport->do_prli_nvme = 1;
++ else
++ fcport->do_prli_nvme = 0;
++ }
++
+ if (!qla2x00_restart_isp(vha)) {
+ clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
+
+@@ -7581,31 +7599,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
+
+ if (IS_QLA81XX(ha) || IS_QLA8031(ha))
+ qla2x00_get_fw_version(vha);
+- if (ha->fce) {
+- ha->flags.fce_enabled = 1;
+- memset(ha->fce, 0,
+- fce_calc_size(ha->fce_bufs));
+- rval = qla2x00_enable_fce_trace(vha,
+- ha->fce_dma, ha->fce_bufs, ha->fce_mb,
+- &ha->fce_bufs);
+- if (rval) {
+- ql_log(ql_log_warn, vha, 0x8033,
+- "Unable to reinitialize FCE "
+- "(%d).\n", rval);
+- ha->flags.fce_enabled = 0;
+- }
+- }
+
+- if (ha->eft) {
+- memset(ha->eft, 0, EFT_SIZE);
+- rval = qla2x00_enable_eft_trace(vha,
+- ha->eft_dma, EFT_NUM_BUFFERS);
+- if (rval) {
+- ql_log(ql_log_warn, vha, 0x8034,
+- "Unable to reinitialize EFT "
+- "(%d).\n", rval);
+- }
+- }
+ } else { /* failed the ISP abort */
+ vha->flags.online = 1;
+ if (test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
+@@ -7655,6 +7649,14 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
+ atomic_inc(&vp->vref_count);
+ spin_unlock_irqrestore(&ha->vport_slock, flags);
+
++ /* User may have updated [fcp|nvme] prefer in flash */
++ list_for_each_entry(fcport, &vp->vp_fcports, list) {
++ if (NVME_PRIORITY(ha, fcport))
++ fcport->do_prli_nvme = 1;
++ else
++ fcport->do_prli_nvme = 0;
++ }
++
+ qla2x00_vp_abort_isp(vp);
+
+ spin_lock_irqsave(&ha->vport_slock, flags);
+diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
+index df90169f82440..0b41e8a066026 100644
+--- a/drivers/scsi/qla2xxx/qla_iocb.c
++++ b/drivers/scsi/qla2xxx/qla_iocb.c
+@@ -2587,6 +2587,33 @@ void
+ qla2x00_sp_release(struct kref *kref)
+ {
+ struct srb *sp = container_of(kref, struct srb, cmd_kref);
++ struct scsi_qla_host *vha = sp->vha;
++
++ switch (sp->type) {
++ case SRB_CT_PTHRU_CMD:
++ /* GPSC & GFPNID use fcport->ct_desc.ct_sns for both req & rsp */
++ if (sp->u.iocb_cmd.u.ctarg.req &&
++ (!sp->fcport ||
++ sp->u.iocb_cmd.u.ctarg.req != sp->fcport->ct_desc.ct_sns)) {
++ dma_free_coherent(&vha->hw->pdev->dev,
++ sp->u.iocb_cmd.u.ctarg.req_allocated_size,
++ sp->u.iocb_cmd.u.ctarg.req,
++ sp->u.iocb_cmd.u.ctarg.req_dma);
++ sp->u.iocb_cmd.u.ctarg.req = NULL;
++ }
++ if (sp->u.iocb_cmd.u.ctarg.rsp &&
++ (!sp->fcport ||
++ sp->u.iocb_cmd.u.ctarg.rsp != sp->fcport->ct_desc.ct_sns)) {
++ dma_free_coherent(&vha->hw->pdev->dev,
++ sp->u.iocb_cmd.u.ctarg.rsp_allocated_size,
++ sp->u.iocb_cmd.u.ctarg.rsp,
++ sp->u.iocb_cmd.u.ctarg.rsp_dma);
++ sp->u.iocb_cmd.u.ctarg.rsp = NULL;
++ }
++ break;
++ default:
++ break;
++ }
+
+ sp->free(sp);
+ }
+@@ -2610,7 +2637,8 @@ static void qla2x00_els_dcmd_sp_free(srb_t *sp)
+ {
+ struct srb_iocb *elsio = &sp->u.iocb_cmd;
+
+- kfree(sp->fcport);
++ if (sp->fcport)
++ qla2x00_free_fcport(sp->fcport);
+
+ if (elsio->u.els_logo.els_logo_pyld)
+ dma_free_coherent(&sp->vha->hw->pdev->dev, DMA_POOL_SIZE,
+@@ -2692,7 +2720,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
+ */
+ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+ if (!sp) {
+- kfree(fcport);
++ qla2x00_free_fcport(fcport);
+ ql_log(ql_log_info, vha, 0x70e6,
+ "SRB allocation failed\n");
+ return -ENOMEM;
+@@ -2723,6 +2751,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
+ if (!elsio->u.els_logo.els_logo_pyld) {
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
++ qla2x00_free_fcport(fcport);
+ return QLA_FUNCTION_FAILED;
+ }
+
+@@ -2747,6 +2776,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
+ if (rval != QLA_SUCCESS) {
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
++ qla2x00_free_fcport(fcport);
+ return QLA_FUNCTION_FAILED;
+ }
+
+@@ -3012,7 +3042,7 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res)
+
+ int
+ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+- fc_port_t *fcport, bool wait)
++ fc_port_t *fcport)
+ {
+ srb_t *sp;
+ struct srb_iocb *elsio = NULL;
+@@ -3027,8 +3057,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+ if (!sp) {
+ ql_log(ql_log_info, vha, 0x70e6,
+ "SRB allocation failed\n");
+- fcport->flags &= ~FCF_ASYNC_ACTIVE;
+- return -ENOMEM;
++ goto done;
+ }
+
+ fcport->flags |= FCF_ASYNC_SENT;
+@@ -3037,9 +3066,6 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+ ql_dbg(ql_dbg_io, vha, 0x3073,
+ "%s Enter: PLOGI portid=%06x\n", __func__, fcport->d_id.b24);
+
+- if (wait)
+- sp->flags = SRB_WAKEUP_ON_COMP;
+-
+ sp->type = SRB_ELS_DCMD;
+ sp->name = "ELS_DCMD";
+ sp->fcport = fcport;
+@@ -3055,7 +3081,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+
+ if (!elsio->u.els_plogi.els_plogi_pyld) {
+ rval = QLA_FUNCTION_FAILED;
+- goto out;
++ goto done_free_sp;
+ }
+
+ resp_ptr = elsio->u.els_plogi.els_resp_pyld =
+@@ -3064,7 +3090,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+
+ if (!elsio->u.els_plogi.els_resp_pyld) {
+ rval = QLA_FUNCTION_FAILED;
+- goto out;
++ goto done_free_sp;
+ }
+
+ ql_dbg(ql_dbg_io, vha, 0x3073, "PLOGI %p %p\n", ptr, resp_ptr);
+@@ -3080,7 +3106,6 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+
+ if (els_opcode == ELS_DCMD_PLOGI && DBELL_ACTIVE(vha)) {
+ struct fc_els_flogi *p = ptr;
+-
+ p->fl_csp.sp_features |= cpu_to_be16(FC_SP_FT_SEC);
+ }
+
+@@ -3089,10 +3114,11 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+ (uint8_t *)elsio->u.els_plogi.els_plogi_pyld,
+ sizeof(*elsio->u.els_plogi.els_plogi_pyld));
+
+- init_completion(&elsio->u.els_plogi.comp);
+ rval = qla2x00_start_sp(sp);
+ if (rval != QLA_SUCCESS) {
+- rval = QLA_FUNCTION_FAILED;
++ fcport->flags |= FCF_LOGIN_NEEDED;
++ set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
++ goto done_free_sp;
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0x3074,
+ "%s PLOGI sent, hdl=%x, loopid=%x, to port_id %06x from port_id %06x\n",
+@@ -3100,21 +3126,15 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
+ fcport->d_id.b24, vha->d_id.b24);
+ }
+
+- if (wait) {
+- wait_for_completion(&elsio->u.els_plogi.comp);
+-
+- if (elsio->u.els_plogi.comp_status != CS_COMPLETE)
+- rval = QLA_FUNCTION_FAILED;
+- } else {
+- goto done;
+- }
++ return rval;
+
+-out:
+- fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
++done_free_sp:
+ qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi);
+ /* ref: INIT */
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ done:
++ fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
++ qla2x00_set_fcport_disc_state(fcport, DSC_DELETED);
+ return rval;
+ }
+
+@@ -3918,7 +3938,7 @@ qla2x00_start_sp(srb_t *sp)
+ return -EAGAIN;
+ }
+
+- pkt = __qla2x00_alloc_iocbs(sp->qpair, sp);
++ pkt = qla2x00_alloc_iocbs_ready(sp->qpair, sp);
+ if (!pkt) {
+ rval = -EAGAIN;
+ ql_log(ql_log_warn, vha, 0x700c,
+diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
+index 21ec32b4fb280..0cd6f3e148824 100644
+--- a/drivers/scsi/qla2xxx/qla_mbx.c
++++ b/drivers/scsi/qla2xxx/qla_mbx.c
+@@ -194,7 +194,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
+ if (ha->flags.purge_mbox || chip_reset != ha->chip_reset ||
+ ha->flags.eeh_busy) {
+ ql_log(ql_log_warn, vha, 0xd035,
+- "Error detected: purge[%d] eeh[%d] cmd=0x%x, Exiting.\n",
++ "Purge mbox: purge[%d] eeh[%d] cmd=0x%x, Exiting.\n",
+ ha->flags.purge_mbox, ha->flags.eeh_busy, mcp->mb[0]);
+ rval = QLA_ABORTED;
+ goto premature_exit;
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index dd674378f2f39..1e2f52210f605 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -4602,6 +4602,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
+ ha->init_cb_dma = 0;
+ fail_free_vp_map:
+ kfree(ha->vp_map);
++ ha->vp_map = NULL;
+ fail:
+ ql_log(ql_log_fatal, NULL, 0x0030,
+ "Memory allocation failure.\n");
+@@ -5583,7 +5584,7 @@ qla2x00_do_work(struct scsi_qla_host *vha)
+ break;
+ case QLA_EVT_ELS_PLOGI:
+ qla24xx_els_dcmd2_iocb(vha, ELS_DCMD_PLOGI,
+- e->u.fcport.fcport, false);
++ e->u.fcport.fcport);
+ break;
+ case QLA_EVT_SA_REPLACE:
+ rc = qla24xx_issue_sa_replace_iocb(vha, e);
+diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
+index 2ef2dbac0db27..d7551b1443e4a 100644
+--- a/drivers/scsi/qla2xxx/qla_target.c
++++ b/drivers/scsi/qla2xxx/qla_target.c
+@@ -1062,6 +1062,16 @@ void qlt_free_session_done(struct work_struct *work)
+ "%s: sess %p logout completed\n", __func__, sess);
+ }
+
++ /* check for any straggling io left behind */
++ if (!(sess->flags & FCF_FCP2_DEVICE) &&
++ qla2x00_eh_wait_for_pending_commands(sess->vha, sess->d_id.b24, 0, WAIT_TARGET)) {
++ ql_log(ql_log_warn, vha, 0x3027,
++ "IO not return. Resetting.\n");
++ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
++ qla2xxx_wake_dpc(vha);
++ qla2x00_wait_for_chip_reset(vha);
++ }
++
+ if (sess->logo_ack_needed) {
+ sess->logo_ack_needed = 0;
+ qla24xx_async_notify_ack(vha, sess,
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 44680f65ea145..ca99be7341d9b 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -1619,6 +1619,40 @@ int scsi_add_device(struct Scsi_Host *host, uint channel,
+ }
+ EXPORT_SYMBOL(scsi_add_device);
+
++int scsi_resume_device(struct scsi_device *sdev)
++{
++ struct device *dev = &sdev->sdev_gendev;
++ int ret = 0;
++
++ device_lock(dev);
++
++ /*
++ * Bail out if the device or its queue are not running. Otherwise,
++ * the rescan may block waiting for commands to be executed, with us
++ * holding the device lock. This can result in a potential deadlock
++ * in the power management core code when system resume is on-going.
++ */
++ if (sdev->sdev_state != SDEV_RUNNING ||
++ blk_queue_pm_only(sdev->request_queue)) {
++ ret = -EWOULDBLOCK;
++ goto unlock;
++ }
++
++ if (dev->driver && try_module_get(dev->driver->owner)) {
++ struct scsi_driver *drv = to_scsi_driver(dev->driver);
++
++ if (drv->resume)
++ ret = drv->resume(dev);
++ module_put(dev->driver->owner);
++ }
++
++unlock:
++ device_unlock(dev);
++
++ return ret;
++}
++EXPORT_SYMBOL(scsi_resume_device);
++
+ int scsi_rescan_device(struct scsi_device *sdev)
+ {
+ struct device *dev = &sdev->sdev_gendev;
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index bdd0acf7fa3cb..d5d3eea006c13 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -3945,7 +3945,21 @@ static int sd_suspend_runtime(struct device *dev)
+ return sd_suspend_common(dev, true);
+ }
+
+-static int sd_resume(struct device *dev, bool runtime)
++static int sd_resume(struct device *dev)
++{
++ struct scsi_disk *sdkp = dev_get_drvdata(dev);
++
++ sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
++
++ if (opal_unlock_from_suspend(sdkp->opal_dev)) {
++ sd_printk(KERN_NOTICE, sdkp, "OPAL unlock failed\n");
++ return -EIO;
++ }
++
++ return 0;
++}
++
++static int sd_resume_common(struct device *dev, bool runtime)
+ {
+ struct scsi_disk *sdkp = dev_get_drvdata(dev);
+ int ret;
+@@ -3961,7 +3975,7 @@ static int sd_resume(struct device *dev, bool runtime)
+ sd_printk(KERN_NOTICE, sdkp, "Starting disk\n");
+ ret = sd_start_stop_device(sdkp, 1);
+ if (!ret) {
+- opal_unlock_from_suspend(sdkp->opal_dev);
++ sd_resume(dev);
+ sdkp->suspended = false;
+ }
+
+@@ -3980,7 +3994,7 @@ static int sd_resume_system(struct device *dev)
+ return 0;
+ }
+
+- return sd_resume(dev, false);
++ return sd_resume_common(dev, false);
+ }
+
+ static int sd_resume_runtime(struct device *dev)
+@@ -4007,7 +4021,7 @@ static int sd_resume_runtime(struct device *dev)
+ "Failed to clear sense data\n");
+ }
+
+- return sd_resume(dev, true);
++ return sd_resume_common(dev, true);
+ }
+
+ static const struct dev_pm_ops sd_pm_ops = {
+@@ -4030,6 +4044,7 @@ static struct scsi_driver sd_template = {
+ .pm = &sd_pm_ops,
+ },
+ .rescan = sd_rescan,
++ .resume = sd_resume,
+ .init_command = sd_init_command,
+ .uninit_command = sd_uninit_command,
+ .done = sd_done,
+diff --git a/drivers/slimbus/core.c b/drivers/slimbus/core.c
+index d43873bb5fe6d..01cbd46219810 100644
+--- a/drivers/slimbus/core.c
++++ b/drivers/slimbus/core.c
+@@ -436,8 +436,8 @@ static int slim_device_alloc_laddr(struct slim_device *sbdev,
+ if (ret < 0)
+ goto err;
+ } else if (report_present) {
+- ret = ida_simple_get(&ctrl->laddr_ida,
+- 0, SLIM_LA_MANAGER - 1, GFP_KERNEL);
++ ret = ida_alloc_max(&ctrl->laddr_ida,
++ SLIM_LA_MANAGER - 1, GFP_KERNEL);
+ if (ret < 0)
+ goto err;
+
+diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c
+index 739e4eee6b75c..7e9074519ad22 100644
+--- a/drivers/soc/fsl/qbman/qman.c
++++ b/drivers/soc/fsl/qbman/qman.c
+@@ -991,7 +991,7 @@ struct qman_portal {
+ /* linked-list of CSCN handlers. */
+ struct list_head cgr_cbs;
+ /* list lock */
+- spinlock_t cgr_lock;
++ raw_spinlock_t cgr_lock;
+ struct work_struct congestion_work;
+ struct work_struct mr_work;
+ char irqname[MAX_IRQNAME];
+@@ -1281,7 +1281,7 @@ static int qman_create_portal(struct qman_portal *portal,
+ /* if the given mask is NULL, assume all CGRs can be seen */
+ qman_cgrs_fill(&portal->cgrs[0]);
+ INIT_LIST_HEAD(&portal->cgr_cbs);
+- spin_lock_init(&portal->cgr_lock);
++ raw_spin_lock_init(&portal->cgr_lock);
+ INIT_WORK(&portal->congestion_work, qm_congestion_task);
+ INIT_WORK(&portal->mr_work, qm_mr_process_task);
+ portal->bits = 0;
+@@ -1456,11 +1456,14 @@ static void qm_congestion_task(struct work_struct *work)
+ union qm_mc_result *mcr;
+ struct qman_cgr *cgr;
+
+- spin_lock(&p->cgr_lock);
++ /*
++ * FIXME: QM_MCR_TIMEOUT is 10ms, which is too long for a raw spinlock!
++ */
++ raw_spin_lock_irq(&p->cgr_lock);
+ qm_mc_start(&p->p);
+ qm_mc_commit(&p->p, QM_MCC_VERB_QUERYCONGESTION);
+ if (!qm_mc_result_timeout(&p->p, &mcr)) {
+- spin_unlock(&p->cgr_lock);
++ raw_spin_unlock_irq(&p->cgr_lock);
+ dev_crit(p->config->dev, "QUERYCONGESTION timeout\n");
+ qman_p_irqsource_add(p, QM_PIRQ_CSCI);
+ return;
+@@ -1476,7 +1479,7 @@ static void qm_congestion_task(struct work_struct *work)
+ list_for_each_entry(cgr, &p->cgr_cbs, node)
+ if (cgr->cb && qman_cgrs_get(&c, cgr->cgrid))
+ cgr->cb(p, cgr, qman_cgrs_get(&rr, cgr->cgrid));
+- spin_unlock(&p->cgr_lock);
++ raw_spin_unlock_irq(&p->cgr_lock);
+ qman_p_irqsource_add(p, QM_PIRQ_CSCI);
+ }
+
+@@ -2440,7 +2443,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags,
+ preempt_enable();
+
+ cgr->chan = p->config->channel;
+- spin_lock(&p->cgr_lock);
++ raw_spin_lock_irq(&p->cgr_lock);
+
+ if (opts) {
+ struct qm_mcc_initcgr local_opts = *opts;
+@@ -2477,7 +2480,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags,
+ qman_cgrs_get(&p->cgrs[1], cgr->cgrid))
+ cgr->cb(p, cgr, 1);
+ out:
+- spin_unlock(&p->cgr_lock);
++ raw_spin_unlock_irq(&p->cgr_lock);
+ put_affine_portal();
+ return ret;
+ }
+@@ -2512,7 +2515,7 @@ int qman_delete_cgr(struct qman_cgr *cgr)
+ return -EINVAL;
+
+ memset(&local_opts, 0, sizeof(struct qm_mcc_initcgr));
+- spin_lock_irqsave(&p->cgr_lock, irqflags);
++ raw_spin_lock_irqsave(&p->cgr_lock, irqflags);
+ list_del(&cgr->node);
+ /*
+ * If there are no other CGR objects for this CGRID in the list,
+@@ -2537,7 +2540,7 @@ int qman_delete_cgr(struct qman_cgr *cgr)
+ /* add back to the list */
+ list_add(&cgr->node, &p->cgr_cbs);
+ release_lock:
+- spin_unlock_irqrestore(&p->cgr_lock, irqflags);
++ raw_spin_unlock_irqrestore(&p->cgr_lock, irqflags);
+ put_affine_portal();
+ return ret;
+ }
+@@ -2577,9 +2580,9 @@ static int qman_update_cgr(struct qman_cgr *cgr, struct qm_mcc_initcgr *opts)
+ if (!p)
+ return -EINVAL;
+
+- spin_lock_irqsave(&p->cgr_lock, irqflags);
++ raw_spin_lock_irqsave(&p->cgr_lock, irqflags);
+ ret = qm_modify_cgr(cgr, 0, opts);
+- spin_unlock_irqrestore(&p->cgr_lock, irqflags);
++ raw_spin_unlock_irqrestore(&p->cgr_lock, irqflags);
+ put_affine_portal();
+ return ret;
+ }
+diff --git a/drivers/staging/media/ipu3/ipu3-v4l2.c b/drivers/staging/media/ipu3/ipu3-v4l2.c
+index a66f034380c05..3df58eb3e8822 100644
+--- a/drivers/staging/media/ipu3/ipu3-v4l2.c
++++ b/drivers/staging/media/ipu3/ipu3-v4l2.c
+@@ -1069,6 +1069,11 @@ static int imgu_v4l2_subdev_register(struct imgu_device *imgu,
+ struct imgu_media_pipe *imgu_pipe = &imgu->imgu_pipe[pipe];
+
+ /* Initialize subdev media entity */
++ imgu_sd->subdev.entity.ops = &imgu_media_ops;
++ for (i = 0; i < IMGU_NODE_NUM; i++) {
++ imgu_sd->subdev_pads[i].flags = imgu_pipe->nodes[i].output ?
++ MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
++ }
+ r = media_entity_pads_init(&imgu_sd->subdev.entity, IMGU_NODE_NUM,
+ imgu_sd->subdev_pads);
+ if (r) {
+@@ -1076,11 +1081,6 @@ static int imgu_v4l2_subdev_register(struct imgu_device *imgu,
+ "failed initialize subdev media entity (%d)\n", r);
+ return r;
+ }
+- imgu_sd->subdev.entity.ops = &imgu_media_ops;
+- for (i = 0; i < IMGU_NODE_NUM; i++) {
+- imgu_sd->subdev_pads[i].flags = imgu_pipe->nodes[i].output ?
+- MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
+- }
+
+ /* Initialize subdev */
+ v4l2_subdev_init(&imgu_sd->subdev, &imgu_subdev_ops);
+@@ -1177,15 +1177,15 @@ static int imgu_v4l2_node_setup(struct imgu_device *imgu, unsigned int pipe,
+ }
+
+ /* Initialize media entities */
++ node->vdev_pad.flags = node->output ?
++ MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK;
++ vdev->entity.ops = NULL;
+ r = media_entity_pads_init(&vdev->entity, 1, &node->vdev_pad);
+ if (r) {
+ dev_err(dev, "failed initialize media entity (%d)\n", r);
+ mutex_destroy(&node->lock);
+ return r;
+ }
+- node->vdev_pad.flags = node->output ?
+- MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK;
+- vdev->entity.ops = NULL;
+
+ /* Initialize vbq */
+ vbq->type = node->vdev_fmt.type;
+diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+index 258aa0e37f554..4c3684dd902ed 100644
+--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
++++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+@@ -937,8 +937,9 @@ static int create_component(struct vchiq_mmal_instance *instance,
+ /* build component create message */
+ m.h.type = MMAL_MSG_TYPE_COMPONENT_CREATE;
+ m.u.component_create.client_component = component->client_component;
+- strncpy(m.u.component_create.name, name,
+- sizeof(m.u.component_create.name));
++ strscpy_pad(m.u.component_create.name, name,
++ sizeof(m.u.component_create.name));
++ m.u.component_create.pid = 0;
+
+ ret = send_synchronous_mmal_msg(instance, &m,
+ sizeof(m.u.component_create),
+diff --git a/drivers/thermal/devfreq_cooling.c b/drivers/thermal/devfreq_cooling.c
+index 262e62ab6cf2f..90b828bcca243 100644
+--- a/drivers/thermal/devfreq_cooling.c
++++ b/drivers/thermal/devfreq_cooling.c
+@@ -201,7 +201,7 @@ static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cd
+
+ res = dfc->power_ops->get_real_power(df, power, freq, voltage);
+ if (!res) {
+- state = dfc->capped_state;
++ state = dfc->max_state - dfc->capped_state;
+
+ /* Convert EM power into milli-Watts first */
+ dfc->res_util = dfc->em_pd->table[state].power;
+diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
+index 649f67fdf3454..d75fae7b7ed22 100644
+--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
++++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
+@@ -176,14 +176,14 @@ static int proc_thermal_get_zone_temp(struct thermal_zone_device *zone,
+ int *temp)
+ {
+ int cpu;
+- int curr_temp;
++ int curr_temp, ret;
+
+ *temp = 0;
+
+ for_each_online_cpu(cpu) {
+- curr_temp = intel_tcc_get_temp(cpu, false);
+- if (curr_temp < 0)
+- return curr_temp;
++ ret = intel_tcc_get_temp(cpu, &curr_temp, false);
++ if (ret < 0)
++ return ret;
+ if (!*temp || curr_temp > *temp)
+ *temp = curr_temp;
+ }
+diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c
+index 2f00fc3bf274a..e964a9375722a 100644
+--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c
++++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rapl.c
+@@ -27,9 +27,9 @@ static int rapl_mmio_cpu_online(unsigned int cpu)
+ if (topology_physical_package_id(cpu))
+ return 0;
+
+- rp = rapl_find_package_domain(cpu, &rapl_mmio_priv, true);
++ rp = rapl_find_package_domain_cpuslocked(cpu, &rapl_mmio_priv, true);
+ if (!rp) {
+- rp = rapl_add_package(cpu, &rapl_mmio_priv, true);
++ rp = rapl_add_package_cpuslocked(cpu, &rapl_mmio_priv, true);
+ if (IS_ERR(rp))
+ return PTR_ERR(rp);
+ }
+@@ -42,14 +42,14 @@ static int rapl_mmio_cpu_down_prep(unsigned int cpu)
+ struct rapl_package *rp;
+ int lead_cpu;
+
+- rp = rapl_find_package_domain(cpu, &rapl_mmio_priv, true);
++ rp = rapl_find_package_domain_cpuslocked(cpu, &rapl_mmio_priv, true);
+ if (!rp)
+ return 0;
+
+ cpumask_clear_cpu(cpu, &rp->cpumask);
+ lead_cpu = cpumask_first(&rp->cpumask);
+ if (lead_cpu >= nr_cpu_ids)
+- rapl_remove_package(rp);
++ rapl_remove_package_cpuslocked(rp);
+ else if (rp->lead_cpu == cpu)
+ rp->lead_cpu = lead_cpu;
+ return 0;
+diff --git a/drivers/thermal/intel/intel_tcc.c b/drivers/thermal/intel/intel_tcc.c
+index 2e5c741c41ca0..5e8b7f34b3951 100644
+--- a/drivers/thermal/intel/intel_tcc.c
++++ b/drivers/thermal/intel/intel_tcc.c
+@@ -103,18 +103,19 @@ EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, INTEL_TCC);
+ /**
+ * intel_tcc_get_temp() - returns the current temperature
+ * @cpu: cpu that the MSR should be run on, nagative value means any cpu.
++ * @temp: pointer to the memory for saving cpu temperature.
+ * @pkg: true: Package Thermal Sensor. false: Core Thermal Sensor.
+ *
+ * Get the current temperature returned by the CPU core/package level
+ * thermal sensor, in degrees C.
+ *
+- * Return: Temperature in degrees C on success, negative error code otherwise.
++ * Return: 0 on success, negative error code otherwise.
+ */
+-int intel_tcc_get_temp(int cpu, bool pkg)
++int intel_tcc_get_temp(int cpu, int *temp, bool pkg)
+ {
+ u32 low, high;
+ u32 msr = pkg ? MSR_IA32_PACKAGE_THERM_STATUS : MSR_IA32_THERM_STATUS;
+- int tjmax, temp, err;
++ int tjmax, err;
+
+ tjmax = intel_tcc_get_tjmax(cpu);
+ if (tjmax < 0)
+@@ -131,9 +132,8 @@ int intel_tcc_get_temp(int cpu, bool pkg)
+ if (!(low & BIT(31)))
+ return -ENODATA;
+
+- temp = tjmax - ((low >> 16) & 0x7f);
++ *temp = tjmax - ((low >> 16) & 0x7f);
+
+- /* Do not allow negative CPU temperature */
+- return temp >= 0 ? temp : -ENODATA;
++ return 0;
+ }
+ EXPORT_SYMBOL_NS_GPL(intel_tcc_get_temp, INTEL_TCC);
+diff --git a/drivers/thermal/intel/x86_pkg_temp_thermal.c b/drivers/thermal/intel/x86_pkg_temp_thermal.c
+index 11a7f8108bbbf..61c3d450ee605 100644
+--- a/drivers/thermal/intel/x86_pkg_temp_thermal.c
++++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c
+@@ -108,11 +108,11 @@ static struct zone_device *pkg_temp_thermal_get_dev(unsigned int cpu)
+ static int sys_get_curr_temp(struct thermal_zone_device *tzd, int *temp)
+ {
+ struct zone_device *zonedev = thermal_zone_device_priv(tzd);
+- int val;
++ int val, ret;
+
+- val = intel_tcc_get_temp(zonedev->cpu, true);
+- if (val < 0)
+- return val;
++ ret = intel_tcc_get_temp(zonedev->cpu, &val, true);
++ if (ret < 0)
++ return ret;
+
+ *temp = val * 1000;
+ pr_debug("sys_get_curr_temp %d\n", *temp);
+diff --git a/drivers/thermal/mediatek/auxadc_thermal.c b/drivers/thermal/mediatek/auxadc_thermal.c
+index 8b0edb2048443..9ee2e7283435a 100644
+--- a/drivers/thermal/mediatek/auxadc_thermal.c
++++ b/drivers/thermal/mediatek/auxadc_thermal.c
+@@ -690,6 +690,9 @@ static const struct mtk_thermal_data mt7986_thermal_data = {
+ .adcpnp = mt7986_adcpnp,
+ .sensor_mux_values = mt7986_mux_values,
+ .version = MTK_THERMAL_V3,
++ .apmixed_buffer_ctl_reg = APMIXED_SYS_TS_CON1,
++ .apmixed_buffer_ctl_mask = GENMASK(31, 6) | BIT(3),
++ .apmixed_buffer_ctl_set = BIT(0),
+ };
+
+ static bool mtk_thermal_temp_is_valid(int temp)
+diff --git a/drivers/thermal/thermal_trip.c b/drivers/thermal/thermal_trip.c
+index c875a26d5adf4..e6dcb8117cb07 100644
+--- a/drivers/thermal/thermal_trip.c
++++ b/drivers/thermal/thermal_trip.c
+@@ -65,7 +65,6 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz)
+ {
+ const struct thermal_trip *trip;
+ int low = -INT_MAX, high = INT_MAX;
+- bool same_trip = false;
+ int ret;
+
+ lockdep_assert_held(&tz->lock);
+@@ -74,36 +73,22 @@ void __thermal_zone_set_trips(struct thermal_zone_device *tz)
+ return;
+
+ for_each_trip(tz, trip) {
+- bool low_set = false;
+ int trip_low;
+
+ trip_low = trip->temperature - trip->hysteresis;
+
+- if (trip_low < tz->temperature && trip_low > low) {
++ if (trip_low < tz->temperature && trip_low > low)
+ low = trip_low;
+- low_set = true;
+- same_trip = false;
+- }
+
+ if (trip->temperature > tz->temperature &&
+- trip->temperature < high) {
++ trip->temperature < high)
+ high = trip->temperature;
+- same_trip = low_set;
+- }
+ }
+
+ /* No need to change trip points */
+ if (tz->prev_low_trip == low && tz->prev_high_trip == high)
+ return;
+
+- /*
+- * If "high" and "low" are the same, skip the change unless this is the
+- * first time.
+- */
+- if (same_trip && (tz->prev_low_trip != -INT_MAX ||
+- tz->prev_high_trip != INT_MAX))
+- return;
+-
+ tz->prev_low_trip = low;
+ tz->prev_high_trip = high;
+
+diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
+index 8ca061d3bbb92..1d65055dde276 100644
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -1329,9 +1329,6 @@ static void autoconfig_irq(struct uart_8250_port *up)
+ inb_p(ICP);
+ }
+
+- if (uart_console(port))
+- console_lock();
+-
+ /* forget possible initially masked and pending IRQ */
+ probe_irq_off(probe_irq_on());
+ save_mcr = serial8250_in_MCR(up);
+@@ -1371,9 +1368,6 @@ static void autoconfig_irq(struct uart_8250_port *up)
+ if (port->flags & UPF_FOURPORT)
+ outb_p(save_ICP, ICP);
+
+- if (uart_console(port))
+- console_unlock();
+-
+ port->irq = (irq > 0) ? irq : 0;
+ }
+
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index f70e2c277ab7e..198413df091b4 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -1635,13 +1635,16 @@ static unsigned short max310x_i2c_slave_addr(unsigned short addr,
+
+ static int max310x_i2c_probe(struct i2c_client *client)
+ {
+- const struct max310x_devtype *devtype =
+- device_get_match_data(&client->dev);
++ const struct max310x_devtype *devtype;
+ struct i2c_client *port_client;
+ struct regmap *regmaps[4];
+ unsigned int i;
+ u8 port_addr;
+
++ devtype = device_get_match_data(&client->dev);
++ if (!devtype)
++ return dev_err_probe(&client->dev, -ENODEV, "Failed to match device\n");
++
+ if (client->addr < devtype->slave_addr.min ||
+ client->addr > devtype->slave_addr.max)
+ return dev_err_probe(&client->dev, -EINVAL,
+diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
+index d6a58a9e072a1..ff85ebd3a007d 100644
+--- a/drivers/tty/serial/serial_core.c
++++ b/drivers/tty/serial/serial_core.c
+@@ -2608,7 +2608,12 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
+ port->type = PORT_UNKNOWN;
+ flags |= UART_CONFIG_TYPE;
+ }
++ /* Synchronize with possible boot console. */
++ if (uart_console(port))
++ console_lock();
+ port->ops->config_port(port, flags);
++ if (uart_console(port))
++ console_unlock();
+ }
+
+ if (port->type != PORT_UNKNOWN) {
+@@ -2616,6 +2621,10 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
+
+ uart_report_port(drv, port);
+
++ /* Synchronize with possible boot console. */
++ if (uart_console(port))
++ console_lock();
++
+ /* Power up port for set_mctrl() */
+ uart_change_pm(state, UART_PM_STATE_ON);
+
+@@ -2632,6 +2641,9 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
+
+ uart_rs485_config(port);
+
++ if (uart_console(port))
++ console_unlock();
++
+ /*
+ * If this driver supports console, and it hasn't been
+ * successfully registered yet, try to re-register it.
+diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
+index 39eef470f8fa5..3d43c7ac7a3f8 100644
+--- a/drivers/ufs/host/ufs-qcom.c
++++ b/drivers/ufs/host/ufs-qcom.c
+@@ -1196,8 +1196,10 @@ static int ufs_qcom_set_core_clk_ctrl(struct ufs_hba *hba, bool is_scale_up)
+
+ list_for_each_entry(clki, head, list) {
+ if (!IS_ERR_OR_NULL(clki->clk) &&
+- !strcmp(clki->name, "core_clk_unipro")) {
+- if (is_scale_up)
++ !strcmp(clki->name, "core_clk_unipro")) {
++ if (!clki->max_freq)
++ cycles_in_1us = 150; /* default for backwards compatibility */
++ else if (is_scale_up)
+ cycles_in_1us = ceil(clki->max_freq, (1000 * 1000));
+ else
+ cycles_in_1us = ceil(clk_get_rate(clki->clk), (1000 * 1000));
+diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
+index c553decb54610..c8262e2f29177 100644
+--- a/drivers/usb/class/cdc-wdm.c
++++ b/drivers/usb/class/cdc-wdm.c
+@@ -485,6 +485,7 @@ static ssize_t wdm_write
+ static int service_outstanding_interrupt(struct wdm_device *desc)
+ {
+ int rv = 0;
++ int used;
+
+ /* submit read urb only if the device is waiting for it */
+ if (!desc->resp_count || !--desc->resp_count)
+@@ -499,7 +500,10 @@ static int service_outstanding_interrupt(struct wdm_device *desc)
+ goto out;
+ }
+
+- set_bit(WDM_RESPONDING, &desc->flags);
++ used = test_and_set_bit(WDM_RESPONDING, &desc->flags);
++ if (used)
++ goto out;
++
+ spin_unlock_irq(&desc->iuspin);
+ rv = usb_submit_urb(desc->response, GFP_KERNEL);
+ spin_lock_irq(&desc->iuspin);
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index e38a4124f6102..64e54163f05e6 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -129,7 +129,6 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
+ #define HUB_DEBOUNCE_STEP 25
+ #define HUB_DEBOUNCE_STABLE 100
+
+-static void hub_release(struct kref *kref);
+ static int usb_reset_and_verify_device(struct usb_device *udev);
+ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state);
+ static bool hub_port_warm_reset_required(struct usb_hub *hub, int port1,
+@@ -691,14 +690,14 @@ static void kick_hub_wq(struct usb_hub *hub)
+ */
+ intf = to_usb_interface(hub->intfdev);
+ usb_autopm_get_interface_no_resume(intf);
+- kref_get(&hub->kref);
++ hub_get(hub);
+
+ if (queue_work(hub_wq, &hub->events))
+ return;
+
+ /* the work has already been scheduled */
+ usb_autopm_put_interface_async(intf);
+- kref_put(&hub->kref, hub_release);
++ hub_put(hub);
+ }
+
+ void usb_kick_hub_wq(struct usb_device *hdev)
+@@ -1066,7 +1065,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ goto init2;
+ goto init3;
+ }
+- kref_get(&hub->kref);
++ hub_get(hub);
+
+ /* The superspeed hub except for root hub has to use Hub Depth
+ * value as an offset into the route string to locate the bits
+@@ -1314,7 +1313,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ device_unlock(&hdev->dev);
+ }
+
+- kref_put(&hub->kref, hub_release);
++ hub_put(hub);
+ }
+
+ /* Implement the continuations for the delays above */
+@@ -1730,6 +1729,16 @@ static void hub_release(struct kref *kref)
+ kfree(hub);
+ }
+
++void hub_get(struct usb_hub *hub)
++{
++ kref_get(&hub->kref);
++}
++
++void hub_put(struct usb_hub *hub)
++{
++ kref_put(&hub->kref, hub_release);
++}
++
+ static unsigned highspeed_hubs;
+
+ static void hub_disconnect(struct usb_interface *intf)
+@@ -1778,7 +1787,7 @@ static void hub_disconnect(struct usb_interface *intf)
+
+ onboard_hub_destroy_pdevs(&hub->onboard_hub_devs);
+
+- kref_put(&hub->kref, hub_release);
++ hub_put(hub);
+ }
+
+ static bool hub_descriptor_is_sane(struct usb_host_interface *desc)
+@@ -5905,7 +5914,7 @@ static void hub_event(struct work_struct *work)
+
+ /* Balance the stuff in kick_hub_wq() and allow autosuspend */
+ usb_autopm_put_interface(intf);
+- kref_put(&hub->kref, hub_release);
++ hub_put(hub);
+
+ kcov_remote_stop();
+ }
+diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
+index 43ce21c96a511..183b69dc29554 100644
+--- a/drivers/usb/core/hub.h
++++ b/drivers/usb/core/hub.h
+@@ -129,6 +129,8 @@ extern void usb_hub_remove_port_device(struct usb_hub *hub,
+ extern int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub,
+ int port1, bool set);
+ extern struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev);
++extern void hub_get(struct usb_hub *hub);
++extern void hub_put(struct usb_hub *hub);
+ extern int hub_port_debounce(struct usb_hub *hub, int port1,
+ bool must_be_connected);
+ extern int usb_clear_port_feature(struct usb_device *hdev,
+diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
+index 4d63496f98b6c..a5776531ba4d3 100644
+--- a/drivers/usb/core/port.c
++++ b/drivers/usb/core/port.c
+@@ -55,11 +55,22 @@ static ssize_t disable_show(struct device *dev,
+ u16 portstatus, unused;
+ bool disabled;
+ int rc;
++ struct kernfs_node *kn;
+
++ hub_get(hub);
+ rc = usb_autopm_get_interface(intf);
+ if (rc < 0)
+- return rc;
++ goto out_hub_get;
+
++ /*
++ * Prevent deadlock if another process is concurrently
++ * trying to unregister hdev.
++ */
++ kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
++ if (!kn) {
++ rc = -ENODEV;
++ goto out_autopm;
++ }
+ usb_lock_device(hdev);
+ if (hub->disconnected) {
+ rc = -ENODEV;
+@@ -69,9 +80,13 @@ static ssize_t disable_show(struct device *dev,
+ usb_hub_port_status(hub, port1, &portstatus, &unused);
+ disabled = !usb_port_is_power_on(hub, portstatus);
+
+-out_hdev_lock:
++ out_hdev_lock:
+ usb_unlock_device(hdev);
++ sysfs_unbreak_active_protection(kn);
++ out_autopm:
+ usb_autopm_put_interface(intf);
++ out_hub_get:
++ hub_put(hub);
+
+ if (rc)
+ return rc;
+@@ -89,15 +104,26 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr,
+ int port1 = port_dev->portnum;
+ bool disabled;
+ int rc;
++ struct kernfs_node *kn;
+
+ rc = kstrtobool(buf, &disabled);
+ if (rc)
+ return rc;
+
++ hub_get(hub);
+ rc = usb_autopm_get_interface(intf);
+ if (rc < 0)
+- return rc;
++ goto out_hub_get;
+
++ /*
++ * Prevent deadlock if another process is concurrently
++ * trying to unregister hdev.
++ */
++ kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
++ if (!kn) {
++ rc = -ENODEV;
++ goto out_autopm;
++ }
+ usb_lock_device(hdev);
+ if (hub->disconnected) {
+ rc = -ENODEV;
+@@ -118,9 +144,13 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr,
+ if (!rc)
+ rc = count;
+
+-out_hdev_lock:
++ out_hdev_lock:
+ usb_unlock_device(hdev);
++ sysfs_unbreak_active_protection(kn);
++ out_autopm:
+ usb_autopm_put_interface(intf);
++ out_hub_get:
++ hub_put(hub);
+
+ return rc;
+ }
+diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
+index 5d21718afb05c..f91f543ec636d 100644
+--- a/drivers/usb/core/sysfs.c
++++ b/drivers/usb/core/sysfs.c
+@@ -1168,14 +1168,24 @@ static ssize_t interface_authorized_store(struct device *dev,
+ {
+ struct usb_interface *intf = to_usb_interface(dev);
+ bool val;
++ struct kernfs_node *kn;
+
+ if (kstrtobool(buf, &val) != 0)
+ return -EINVAL;
+
+- if (val)
++ if (val) {
+ usb_authorize_interface(intf);
+- else
+- usb_deauthorize_interface(intf);
++ } else {
++ /*
++ * Prevent deadlock if another process is concurrently
++ * trying to unregister intf.
++ */
++ kn = sysfs_break_active_protection(&dev->kobj, &attr->attr);
++ if (kn) {
++ usb_deauthorize_interface(intf);
++ sysfs_unbreak_active_protection(kn);
++ }
++ }
+
+ return count;
+ }
+diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
+index c92a1da46a014..a141f83aba0cc 100644
+--- a/drivers/usb/dwc2/core.h
++++ b/drivers/usb/dwc2/core.h
+@@ -729,8 +729,14 @@ struct dwc2_dregs_backup {
+ * struct dwc2_hregs_backup - Holds host registers state before
+ * entering partial power down
+ * @hcfg: Backup of HCFG register
++ * @hflbaddr: Backup of HFLBADDR register
+ * @haintmsk: Backup of HAINTMSK register
++ * @hcchar: Backup of HCCHAR register
++ * @hcsplt: Backup of HCSPLT register
+ * @hcintmsk: Backup of HCINTMSK register
++ * @hctsiz: Backup of HCTSIZ register
++ * @hdma: Backup of HCDMA register
++ * @hcdmab: Backup of HCDMAB register
+ * @hprt0: Backup of HPTR0 register
+ * @hfir: Backup of HFIR register
+ * @hptxfsiz: Backup of HPTXFSIZ register
+@@ -738,8 +744,14 @@ struct dwc2_dregs_backup {
+ */
+ struct dwc2_hregs_backup {
+ u32 hcfg;
++ u32 hflbaddr;
+ u32 haintmsk;
++ u32 hcchar[MAX_EPS_CHANNELS];
++ u32 hcsplt[MAX_EPS_CHANNELS];
+ u32 hcintmsk[MAX_EPS_CHANNELS];
++ u32 hctsiz[MAX_EPS_CHANNELS];
++ u32 hcidma[MAX_EPS_CHANNELS];
++ u32 hcidmab[MAX_EPS_CHANNELS];
+ u32 hprt0;
+ u32 hfir;
+ u32 hptxfsiz;
+@@ -1086,6 +1098,7 @@ struct dwc2_hsotg {
+ bool needs_byte_swap;
+
+ /* DWC OTG HW Release versions */
++#define DWC2_CORE_REV_4_30a 0x4f54430a
+ #define DWC2_CORE_REV_2_71a 0x4f54271a
+ #define DWC2_CORE_REV_2_72a 0x4f54272a
+ #define DWC2_CORE_REV_2_80a 0x4f54280a
+@@ -1323,6 +1336,7 @@ int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg);
+ int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg);
+
+ void dwc2_enable_acg(struct dwc2_hsotg *hsotg);
++void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg, bool remotewakeup);
+
+ /* This function should be called on every hardware interrupt. */
+ irqreturn_t dwc2_handle_common_intr(int irq, void *dev);
+diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
+index 158ede7538548..26d752a4c3ca9 100644
+--- a/drivers/usb/dwc2/core_intr.c
++++ b/drivers/usb/dwc2/core_intr.c
+@@ -297,7 +297,8 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
+
+ /* Exit gadget mode clock gating. */
+ if (hsotg->params.power_down ==
+- DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
++ DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended &&
++ !hsotg->params.no_clock_gating)
+ dwc2_gadget_exit_clock_gating(hsotg, 0);
+ }
+
+@@ -322,10 +323,11 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
+ * @hsotg: Programming view of DWC_otg controller
+ *
+ */
+-static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
++void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg, bool remotewakeup)
+ {
+ u32 glpmcfg;
+- u32 i = 0;
++ u32 pcgctl;
++ u32 dctl;
+
+ if (hsotg->lx_state != DWC2_L1) {
+ dev_err(hsotg->dev, "Core isn't in DWC2_L1 state\n");
+@@ -334,37 +336,57 @@ static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
+
+ glpmcfg = dwc2_readl(hsotg, GLPMCFG);
+ if (dwc2_is_device_mode(hsotg)) {
+- dev_dbg(hsotg->dev, "Exit from L1 state\n");
++ dev_dbg(hsotg->dev, "Exit from L1 state, remotewakeup=%d\n", remotewakeup);
+ glpmcfg &= ~GLPMCFG_ENBLSLPM;
+- glpmcfg &= ~GLPMCFG_HIRD_THRES_EN;
++ glpmcfg &= ~GLPMCFG_HIRD_THRES_MASK;
+ dwc2_writel(hsotg, glpmcfg, GLPMCFG);
+
+- do {
+- glpmcfg = dwc2_readl(hsotg, GLPMCFG);
++ pcgctl = dwc2_readl(hsotg, PCGCTL);
++ pcgctl &= ~PCGCTL_ENBL_SLEEP_GATING;
++ dwc2_writel(hsotg, pcgctl, PCGCTL);
+
+- if (!(glpmcfg & (GLPMCFG_COREL1RES_MASK |
+- GLPMCFG_L1RESUMEOK | GLPMCFG_SLPSTS)))
+- break;
++ glpmcfg = dwc2_readl(hsotg, GLPMCFG);
++ if (glpmcfg & GLPMCFG_ENBESL) {
++ glpmcfg |= GLPMCFG_RSTRSLPSTS;
++ dwc2_writel(hsotg, glpmcfg, GLPMCFG);
++ }
++
++ if (remotewakeup) {
++ if (dwc2_hsotg_wait_bit_set(hsotg, GLPMCFG, GLPMCFG_L1RESUMEOK, 1000)) {
++ dev_warn(hsotg->dev, "%s: timeout GLPMCFG_L1RESUMEOK\n", __func__);
++ goto fail;
++ return;
++ }
++
++ dctl = dwc2_readl(hsotg, DCTL);
++ dctl |= DCTL_RMTWKUPSIG;
++ dwc2_writel(hsotg, dctl, DCTL);
+
+- udelay(1);
+- } while (++i < 200);
++ if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS, GINTSTS_WKUPINT, 1000)) {
++ dev_warn(hsotg->dev, "%s: timeout GINTSTS_WKUPINT\n", __func__);
++ goto fail;
++ return;
++ }
++ }
+
+- if (i == 200) {
+- dev_err(hsotg->dev, "Failed to exit L1 sleep state in 200us.\n");
++ glpmcfg = dwc2_readl(hsotg, GLPMCFG);
++ if (glpmcfg & GLPMCFG_COREL1RES_MASK || glpmcfg & GLPMCFG_SLPSTS ||
++ glpmcfg & GLPMCFG_L1RESUMEOK) {
++ goto fail;
+ return;
+ }
+- dwc2_gadget_init_lpm(hsotg);
++
++ /* Inform gadget to exit from L1 */
++ call_gadget(hsotg, resume);
++ /* Change to L0 state */
++ hsotg->lx_state = DWC2_L0;
++ hsotg->bus_suspended = false;
++fail: dwc2_gadget_init_lpm(hsotg);
+ } else {
+ /* TODO */
+ dev_err(hsotg->dev, "Host side LPM is not supported.\n");
+ return;
+ }
+-
+- /* Change to L0 state */
+- hsotg->lx_state = DWC2_L0;
+-
+- /* Inform gadget to exit from L1 */
+- call_gadget(hsotg, resume);
+ }
+
+ /*
+@@ -385,7 +407,7 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
+ dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
+
+ if (hsotg->lx_state == DWC2_L1) {
+- dwc2_wakeup_from_lpm_l1(hsotg);
++ dwc2_wakeup_from_lpm_l1(hsotg, false);
+ return;
+ }
+
+@@ -408,7 +430,8 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
+
+ /* Exit gadget mode clock gating. */
+ if (hsotg->params.power_down ==
+- DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
++ DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended &&
++ !hsotg->params.no_clock_gating)
+ dwc2_gadget_exit_clock_gating(hsotg, 0);
+ } else {
+ /* Change to L0 state */
+@@ -425,7 +448,8 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
+ }
+
+ if (hsotg->params.power_down ==
+- DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended)
++ DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended &&
++ !hsotg->params.no_clock_gating)
+ dwc2_host_exit_clock_gating(hsotg, 1);
+
+ /*
+diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
+index b517a7216de22..b2f6da5b65ccd 100644
+--- a/drivers/usb/dwc2/gadget.c
++++ b/drivers/usb/dwc2/gadget.c
+@@ -1415,6 +1415,10 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
+ ep->name, req, req->length, req->buf, req->no_interrupt,
+ req->zero, req->short_not_ok);
+
++ if (hs->lx_state == DWC2_L1) {
++ dwc2_wakeup_from_lpm_l1(hs, true);
++ }
++
+ /* Prevent new request submission when controller is suspended */
+ if (hs->lx_state != DWC2_L0) {
+ dev_dbg(hs->dev, "%s: submit request only in active state\n",
+@@ -3727,6 +3731,12 @@ static irqreturn_t dwc2_hsotg_irq(int irq, void *pw)
+ if (hsotg->in_ppd && hsotg->lx_state == DWC2_L2)
+ dwc2_exit_partial_power_down(hsotg, 0, true);
+
++ /* Exit gadget mode clock gating. */
++ if (hsotg->params.power_down ==
++ DWC2_POWER_DOWN_PARAM_NONE && hsotg->bus_suspended &&
++ !hsotg->params.no_clock_gating)
++ dwc2_gadget_exit_clock_gating(hsotg, 0);
++
+ hsotg->lx_state = DWC2_L0;
+ }
+
+diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
+index 35c7a4df8e717..dd5b1c5691e11 100644
+--- a/drivers/usb/dwc2/hcd.c
++++ b/drivers/usb/dwc2/hcd.c
+@@ -2701,8 +2701,11 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
+ hsotg->available_host_channels--;
+ }
+ qh = list_entry(qh_ptr, struct dwc2_qh, qh_list_entry);
+- if (dwc2_assign_and_init_hc(hsotg, qh))
++ if (dwc2_assign_and_init_hc(hsotg, qh)) {
++ if (hsotg->params.uframe_sched)
++ hsotg->available_host_channels++;
+ break;
++ }
+
+ /*
+ * Move the QH from the periodic ready schedule to the
+@@ -2735,8 +2738,11 @@ enum dwc2_transaction_type dwc2_hcd_select_transactions(
+ hsotg->available_host_channels--;
+ }
+
+- if (dwc2_assign_and_init_hc(hsotg, qh))
++ if (dwc2_assign_and_init_hc(hsotg, qh)) {
++ if (hsotg->params.uframe_sched)
++ hsotg->available_host_channels++;
+ break;
++ }
+
+ /*
+ * Move the QH from the non-periodic inactive schedule to the
+@@ -4143,6 +4149,8 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
+ urb->actual_length);
+
+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
++ if (!hsotg->params.dma_desc_enable)
++ urb->start_frame = qtd->qh->start_active_frame;
+ urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb);
+ for (i = 0; i < urb->number_of_packets; ++i) {
+ urb->iso_frame_desc[i].actual_length =
+@@ -4649,7 +4657,7 @@ static int _dwc2_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+ }
+
+ if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE &&
+- hsotg->bus_suspended) {
++ hsotg->bus_suspended && !hsotg->params.no_clock_gating) {
+ if (dwc2_is_device_mode(hsotg))
+ dwc2_gadget_exit_clock_gating(hsotg, 0);
+ else
+@@ -5406,9 +5414,16 @@ int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
+ /* Backup Host regs */
+ hr = &hsotg->hr_backup;
+ hr->hcfg = dwc2_readl(hsotg, HCFG);
++ hr->hflbaddr = dwc2_readl(hsotg, HFLBADDR);
+ hr->haintmsk = dwc2_readl(hsotg, HAINTMSK);
+- for (i = 0; i < hsotg->params.host_channels; ++i)
++ for (i = 0; i < hsotg->params.host_channels; ++i) {
++ hr->hcchar[i] = dwc2_readl(hsotg, HCCHAR(i));
++ hr->hcsplt[i] = dwc2_readl(hsotg, HCSPLT(i));
+ hr->hcintmsk[i] = dwc2_readl(hsotg, HCINTMSK(i));
++ hr->hctsiz[i] = dwc2_readl(hsotg, HCTSIZ(i));
++ hr->hcidma[i] = dwc2_readl(hsotg, HCDMA(i));
++ hr->hcidmab[i] = dwc2_readl(hsotg, HCDMAB(i));
++ }
+
+ hr->hprt0 = dwc2_read_hprt0(hsotg);
+ hr->hfir = dwc2_readl(hsotg, HFIR);
+@@ -5442,10 +5457,17 @@ int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
+ hr->valid = false;
+
+ dwc2_writel(hsotg, hr->hcfg, HCFG);
++ dwc2_writel(hsotg, hr->hflbaddr, HFLBADDR);
+ dwc2_writel(hsotg, hr->haintmsk, HAINTMSK);
+
+- for (i = 0; i < hsotg->params.host_channels; ++i)
++ for (i = 0; i < hsotg->params.host_channels; ++i) {
++ dwc2_writel(hsotg, hr->hcchar[i], HCCHAR(i));
++ dwc2_writel(hsotg, hr->hcsplt[i], HCSPLT(i));
+ dwc2_writel(hsotg, hr->hcintmsk[i], HCINTMSK(i));
++ dwc2_writel(hsotg, hr->hctsiz[i], HCTSIZ(i));
++ dwc2_writel(hsotg, hr->hcidma[i], HCDMA(i));
++ dwc2_writel(hsotg, hr->hcidmab[i], HCDMAB(i));
++ }
+
+ dwc2_writel(hsotg, hr->hprt0, HPRT0);
+ dwc2_writel(hsotg, hr->hfir, HFIR);
+@@ -5610,10 +5632,12 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup,
+ dwc2_writel(hsotg, hr->hcfg, HCFG);
+
+ /* De-assert Wakeup Logic */
+- gpwrdn = dwc2_readl(hsotg, GPWRDN);
+- gpwrdn &= ~GPWRDN_PMUACTV;
+- dwc2_writel(hsotg, gpwrdn, GPWRDN);
+- udelay(10);
++ if (!(rem_wakeup && hsotg->hw_params.snpsid >= DWC2_CORE_REV_4_30a)) {
++ gpwrdn = dwc2_readl(hsotg, GPWRDN);
++ gpwrdn &= ~GPWRDN_PMUACTV;
++ dwc2_writel(hsotg, gpwrdn, GPWRDN);
++ udelay(10);
++ }
+
+ hprt0 = hr->hprt0;
+ hprt0 |= HPRT0_PWR;
+@@ -5638,6 +5662,13 @@ int dwc2_host_exit_hibernation(struct dwc2_hsotg *hsotg, int rem_wakeup,
+ hprt0 |= HPRT0_RES;
+ dwc2_writel(hsotg, hprt0, HPRT0);
+
++ /* De-assert Wakeup Logic */
++ if ((rem_wakeup && hsotg->hw_params.snpsid >= DWC2_CORE_REV_4_30a)) {
++ gpwrdn = dwc2_readl(hsotg, GPWRDN);
++ gpwrdn &= ~GPWRDN_PMUACTV;
++ dwc2_writel(hsotg, gpwrdn, GPWRDN);
++ udelay(10);
++ }
+ /* Wait for Resume time and then program HPRT again */
+ mdelay(100);
+ hprt0 &= ~HPRT0_RES;
+diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c
+index 6b4d825e97a2d..79582b102c7ed 100644
+--- a/drivers/usb/dwc2/hcd_ddma.c
++++ b/drivers/usb/dwc2/hcd_ddma.c
+@@ -559,7 +559,7 @@ static void dwc2_init_isoc_dma_desc(struct dwc2_hsotg *hsotg,
+ idx = qh->td_last;
+ inc = qh->host_interval;
+ hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
+- cur_idx = dwc2_frame_list_idx(hsotg->frame_number);
++ cur_idx = idx;
+ next_idx = dwc2_desclist_idx_inc(qh->td_last, inc, qh->dev_speed);
+
+ /*
+@@ -866,6 +866,8 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
+ {
+ struct dwc2_dma_desc *dma_desc;
+ struct dwc2_hcd_iso_packet_desc *frame_desc;
++ u16 frame_desc_idx;
++ struct urb *usb_urb = qtd->urb->priv;
+ u16 remain = 0;
+ int rc = 0;
+
+@@ -878,8 +880,11 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
+ DMA_FROM_DEVICE);
+
+ dma_desc = &qh->desc_list[idx];
++ frame_desc_idx = (idx - qtd->isoc_td_first) & (usb_urb->number_of_packets - 1);
+
+- frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index_last];
++ frame_desc = &qtd->urb->iso_descs[frame_desc_idx];
++ if (idx == qtd->isoc_td_first)
++ usb_urb->start_frame = dwc2_hcd_get_frame_number(hsotg);
+ dma_desc->buf = (u32)(qtd->urb->dma + frame_desc->offset);
+ if (chan->ep_is_in)
+ remain = (dma_desc->status & HOST_DMA_ISOC_NBYTES_MASK) >>
+@@ -900,7 +905,7 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
+ frame_desc->status = 0;
+ }
+
+- if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
++ if (++qtd->isoc_frame_index == usb_urb->number_of_packets) {
+ /*
+ * urb->status is not used for isoc transfers here. The
+ * individual frame_desc status are used instead.
+@@ -1005,11 +1010,11 @@ static void dwc2_complete_isoc_xfer_ddma(struct dwc2_hsotg *hsotg,
+ return;
+ idx = dwc2_desclist_idx_inc(idx, qh->host_interval,
+ chan->speed);
+- if (!rc)
++ if (rc == 0)
+ continue;
+
+- if (rc == DWC2_CMPL_DONE)
+- break;
++ if (rc == DWC2_CMPL_DONE || rc == DWC2_CMPL_STOP)
++ goto stop_scan;
+
+ /* rc == DWC2_CMPL_STOP */
+
+diff --git a/drivers/usb/dwc2/hw.h b/drivers/usb/dwc2/hw.h
+index 13abdd5f67529..12f8c7f86dc98 100644
+--- a/drivers/usb/dwc2/hw.h
++++ b/drivers/usb/dwc2/hw.h
+@@ -698,7 +698,7 @@
+ #define TXSTS_QTOP_TOKEN_MASK (0x3 << 25)
+ #define TXSTS_QTOP_TOKEN_SHIFT 25
+ #define TXSTS_QTOP_TERMINATE BIT(24)
+-#define TXSTS_QSPCAVAIL_MASK (0xff << 16)
++#define TXSTS_QSPCAVAIL_MASK (0x7f << 16)
+ #define TXSTS_QSPCAVAIL_SHIFT 16
+ #define TXSTS_FSPCAVAIL_MASK (0xffff << 0)
+ #define TXSTS_FSPCAVAIL_SHIFT 0
+diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
+index b1d48019e944f..7b84416dfc2b1 100644
+--- a/drivers/usb/dwc2/platform.c
++++ b/drivers/usb/dwc2/platform.c
+@@ -331,7 +331,7 @@ static void dwc2_driver_remove(struct platform_device *dev)
+
+ /* Exit clock gating when driver is removed. */
+ if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE &&
+- hsotg->bus_suspended) {
++ hsotg->bus_suspended && !hsotg->params.no_clock_gating) {
+ if (dwc2_is_device_mode(hsotg))
+ dwc2_gadget_exit_clock_gating(hsotg, 0);
+ else
+diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
+index 3e55838c00014..31684cdaaae30 100644
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -1519,6 +1519,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
+ else
+ dwc->sysdev = dwc->dev;
+
++ dwc->sys_wakeup = device_may_wakeup(dwc->sysdev);
++
+ ret = device_property_read_string(dev, "usb-psy-name", &usb_psy_name);
+ if (ret >= 0) {
+ dwc->usb_psy = power_supply_get_by_name(usb_psy_name);
+diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
+index e120611a5174f..893b1e694efe1 100644
+--- a/drivers/usb/dwc3/core.h
++++ b/drivers/usb/dwc3/core.h
+@@ -1132,6 +1132,7 @@ struct dwc3_scratchpad_array {
+ * 3 - Reserved
+ * @dis_metastability_quirk: set to disable metastability quirk.
+ * @dis_split_quirk: set to disable split boundary.
++ * @sys_wakeup: set if the device may do system wakeup.
+ * @wakeup_configured: set if the device is configured for remote wakeup.
+ * @suspended: set to track suspend event due to U3/L2.
+ * @imod_interval: set the interrupt moderation interval in 250ns
+@@ -1355,6 +1356,7 @@ struct dwc3 {
+
+ unsigned dis_split_quirk:1;
+ unsigned async_callbacks:1;
++ unsigned sys_wakeup:1;
+ unsigned wakeup_configured:1;
+ unsigned suspended:1;
+
+diff --git a/drivers/usb/dwc3/dwc3-am62.c b/drivers/usb/dwc3/dwc3-am62.c
+index 90a587bc29b74..ea6e29091c0c9 100644
+--- a/drivers/usb/dwc3/dwc3-am62.c
++++ b/drivers/usb/dwc3/dwc3-am62.c
+@@ -267,21 +267,15 @@ static int dwc3_ti_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+-static int dwc3_ti_remove_core(struct device *dev, void *c)
+-{
+- struct platform_device *pdev = to_platform_device(dev);
+-
+- platform_device_unregister(pdev);
+- return 0;
+-}
+-
+ static void dwc3_ti_remove(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct dwc3_am62 *am62 = platform_get_drvdata(pdev);
+ u32 reg;
+
+- device_for_each_child(dev, NULL, dwc3_ti_remove_core);
++ pm_runtime_get_sync(dev);
++ device_init_wakeup(dev, false);
++ of_platform_depopulate(dev);
+
+ /* Clear mode valid bit */
+ reg = dwc3_ti_readl(am62, USBSS_MODE_CONTROL);
+@@ -289,7 +283,6 @@ static void dwc3_ti_remove(struct platform_device *pdev)
+ dwc3_ti_writel(am62, USBSS_MODE_CONTROL, reg);
+
+ pm_runtime_put_sync(dev);
+- clk_disable_unprepare(am62->usb2_refclk);
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+ }
+diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
+index 39564e17f3b07..497deed38c0c1 100644
+--- a/drivers/usb/dwc3/dwc3-pci.c
++++ b/drivers/usb/dwc3/dwc3-pci.c
+@@ -51,7 +51,6 @@
+ #define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1
+ #define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f
+ #define PCI_DEVICE_ID_INTEL_MTL 0x7e7e
+-#define PCI_DEVICE_ID_INTEL_ARLH 0x7ec1
+ #define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e
+ #define PCI_DEVICE_ID_INTEL_TGL 0x9a15
+ #define PCI_DEVICE_ID_AMD_MR 0x163a
+@@ -423,7 +422,6 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
+ { PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) },
+ { PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) },
+ { PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) },
+- { PCI_DEVICE_DATA(INTEL, ARLH, &dwc3_pci_intel_swnode) },
+ { PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) },
+ { PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) },
+
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 28f49400f3e8b..07820b1a88a24 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -2968,6 +2968,9 @@ static int dwc3_gadget_start(struct usb_gadget *g,
+ dwc->gadget_driver = driver;
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
++ if (dwc->sys_wakeup)
++ device_wakeup_enable(dwc->sysdev);
++
+ return 0;
+ }
+
+@@ -2983,6 +2986,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
+ struct dwc3 *dwc = gadget_to_dwc(g);
+ unsigned long flags;
+
++ if (dwc->sys_wakeup)
++ device_wakeup_disable(dwc->sysdev);
++
+ spin_lock_irqsave(&dwc->lock, flags);
+ dwc->gadget_driver = NULL;
+ dwc->max_cfg_eps = 0;
+@@ -4664,6 +4670,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)
+ else
+ dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed);
+
++ /* No system wakeup if no gadget driver bound */
++ if (dwc->sys_wakeup)
++ device_wakeup_disable(dwc->sysdev);
++
+ return 0;
+
+ err5:
+diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
+index 43230915323c7..f6a020d77fa18 100644
+--- a/drivers/usb/dwc3/host.c
++++ b/drivers/usb/dwc3/host.c
+@@ -123,6 +123,14 @@ int dwc3_host_init(struct dwc3 *dwc)
+ goto err;
+ }
+
++ if (dwc->sys_wakeup) {
++ /* Restore wakeup setting if switched from device */
++ device_wakeup_enable(dwc->sysdev);
++
++ /* Pass on wakeup setting to the new xhci platform device */
++ device_init_wakeup(&xhci->dev, true);
++ }
++
+ return 0;
+ err:
+ platform_device_put(xhci);
+@@ -131,6 +139,9 @@ int dwc3_host_init(struct dwc3 *dwc)
+
+ void dwc3_host_exit(struct dwc3 *dwc)
+ {
++ if (dwc->sys_wakeup)
++ device_init_wakeup(&dwc->xhci->dev, false);
++
+ platform_device_unregister(dwc->xhci);
+ dwc->xhci = NULL;
+ }
+diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
+index d59f94464b870..8ac29f7230fcd 100644
+--- a/drivers/usb/gadget/udc/core.c
++++ b/drivers/usb/gadget/udc/core.c
+@@ -292,7 +292,9 @@ int usb_ep_queue(struct usb_ep *ep,
+ {
+ int ret = 0;
+
+- if (WARN_ON_ONCE(!ep->enabled && ep->address)) {
++ if (!ep->enabled && ep->address) {
++ pr_debug("USB gadget: queue request to disabled ep 0x%x (%s)\n",
++ ep->address, ep->name);
+ ret = -ESHUTDOWN;
+ goto out;
+ }
+diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
+index cb85168fd00c2..7aa46d426f31b 100644
+--- a/drivers/usb/gadget/udc/tegra-xudc.c
++++ b/drivers/usb/gadget/udc/tegra-xudc.c
+@@ -3491,8 +3491,8 @@ static void tegra_xudc_device_params_init(struct tegra_xudc *xudc)
+
+ static int tegra_xudc_phy_get(struct tegra_xudc *xudc)
+ {
+- int err = 0, usb3;
+- unsigned int i;
++ int err = 0, usb3_companion_port;
++ unsigned int i, j;
+
+ xudc->utmi_phy = devm_kcalloc(xudc->dev, xudc->soc->num_phys,
+ sizeof(*xudc->utmi_phy), GFP_KERNEL);
+@@ -3520,7 +3520,7 @@ static int tegra_xudc_phy_get(struct tegra_xudc *xudc)
+ if (IS_ERR(xudc->utmi_phy[i])) {
+ err = PTR_ERR(xudc->utmi_phy[i]);
+ dev_err_probe(xudc->dev, err,
+- "failed to get usb2-%d PHY\n", i);
++ "failed to get PHY for phy-name usb2-%d\n", i);
+ goto clean_up;
+ } else if (xudc->utmi_phy[i]) {
+ /* Get usb-phy, if utmi phy is available */
+@@ -3539,19 +3539,30 @@ static int tegra_xudc_phy_get(struct tegra_xudc *xudc)
+ }
+
+ /* Get USB3 phy */
+- usb3 = tegra_xusb_padctl_get_usb3_companion(xudc->padctl, i);
+- if (usb3 < 0)
++ usb3_companion_port = tegra_xusb_padctl_get_usb3_companion(xudc->padctl, i);
++ if (usb3_companion_port < 0)
+ continue;
+
+- snprintf(phy_name, sizeof(phy_name), "usb3-%d", usb3);
+- xudc->usb3_phy[i] = devm_phy_optional_get(xudc->dev, phy_name);
+- if (IS_ERR(xudc->usb3_phy[i])) {
+- err = PTR_ERR(xudc->usb3_phy[i]);
+- dev_err_probe(xudc->dev, err,
+- "failed to get usb3-%d PHY\n", usb3);
+- goto clean_up;
+- } else if (xudc->usb3_phy[i])
+- dev_dbg(xudc->dev, "usb3-%d PHY registered", usb3);
++ for (j = 0; j < xudc->soc->num_phys; j++) {
++ snprintf(phy_name, sizeof(phy_name), "usb3-%d", j);
++ xudc->usb3_phy[i] = devm_phy_optional_get(xudc->dev, phy_name);
++ if (IS_ERR(xudc->usb3_phy[i])) {
++ err = PTR_ERR(xudc->usb3_phy[i]);
++ dev_err_probe(xudc->dev, err,
++ "failed to get PHY for phy-name usb3-%d\n", j);
++ goto clean_up;
++ } else if (xudc->usb3_phy[i]) {
++ int usb2_port =
++ tegra_xusb_padctl_get_port_number(xudc->utmi_phy[i]);
++ int usb3_port =
++ tegra_xusb_padctl_get_port_number(xudc->usb3_phy[i]);
++ if (usb3_port == usb3_companion_port) {
++ dev_dbg(xudc->dev, "USB2 port %d is paired with USB3 port %d for device mode port %d\n",
++ usb2_port, usb3_port, i);
++ break;
++ }
++ }
++ }
+ }
+
+ return err;
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 0886829d53e51..afccd58c9a75a 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -1220,6 +1220,8 @@ static int xhci_map_temp_buffer(struct usb_hcd *hcd, struct urb *urb)
+
+ temp = kzalloc_node(buf_len, GFP_ATOMIC,
+ dev_to_node(hcd->self.sysdev));
++ if (!temp)
++ return -ENOMEM;
+
+ if (usb_urb_dir_out(urb))
+ sg_pcopy_to_buffer(urb->sg, urb->num_sgs,
+diff --git a/drivers/usb/misc/usb-ljca.c b/drivers/usb/misc/usb-ljca.c
+index 35770e608c649..2d30fc1be3066 100644
+--- a/drivers/usb/misc/usb-ljca.c
++++ b/drivers/usb/misc/usb-ljca.c
+@@ -518,8 +518,10 @@ static int ljca_new_client_device(struct ljca_adapter *adap, u8 type, u8 id,
+ int ret;
+
+ client = kzalloc(sizeof *client, GFP_KERNEL);
+- if (!client)
++ if (!client) {
++ kfree(data);
+ return -ENOMEM;
++ }
+
+ client->type = type;
+ client->id = id;
+@@ -535,8 +537,10 @@ static int ljca_new_client_device(struct ljca_adapter *adap, u8 type, u8 id,
+ auxdev->dev.release = ljca_auxdev_release;
+
+ ret = auxiliary_device_init(auxdev);
+- if (ret)
++ if (ret) {
++ kfree(data);
+ goto err_free;
++ }
+
+ ljca_auxdev_acpi_bind(adap, auxdev, adr, id);
+
+@@ -590,12 +594,8 @@ static int ljca_enumerate_gpio(struct ljca_adapter *adap)
+ valid_pin[i] = get_unaligned_le32(&desc->bank_desc[i].valid_pins);
+ bitmap_from_arr32(gpio_info->valid_pin_map, valid_pin, gpio_num);
+
+- ret = ljca_new_client_device(adap, LJCA_CLIENT_GPIO, 0, "ljca-gpio",
++ return ljca_new_client_device(adap, LJCA_CLIENT_GPIO, 0, "ljca-gpio",
+ gpio_info, LJCA_GPIO_ACPI_ADR);
+- if (ret)
+- kfree(gpio_info);
+-
+- return ret;
+ }
+
+ static int ljca_enumerate_i2c(struct ljca_adapter *adap)
+@@ -629,10 +629,8 @@ static int ljca_enumerate_i2c(struct ljca_adapter *adap)
+ ret = ljca_new_client_device(adap, LJCA_CLIENT_I2C, i,
+ "ljca-i2c", i2c_info,
+ LJCA_I2C1_ACPI_ADR + i);
+- if (ret) {
+- kfree(i2c_info);
++ if (ret)
+ return ret;
+- }
+ }
+
+ return 0;
+@@ -669,10 +667,8 @@ static int ljca_enumerate_spi(struct ljca_adapter *adap)
+ ret = ljca_new_client_device(adap, LJCA_CLIENT_SPI, i,
+ "ljca-spi", spi_info,
+ LJCA_SPI1_ACPI_ADR + i);
+- if (ret) {
+- kfree(spi_info);
++ if (ret)
+ return ret;
+- }
+ }
+
+ return 0;
+diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
+index 16494030209ea..9ab50f26db607 100644
+--- a/drivers/usb/phy/phy-generic.c
++++ b/drivers/usb/phy/phy-generic.c
+@@ -274,13 +274,6 @@ int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_generic *nop)
+ return dev_err_probe(dev, PTR_ERR(nop->vbus_draw),
+ "could not get vbus regulator\n");
+
+- nop->vbus_draw = devm_regulator_get_exclusive(dev, "vbus");
+- if (PTR_ERR(nop->vbus_draw) == -ENODEV)
+- nop->vbus_draw = NULL;
+- if (IS_ERR(nop->vbus_draw))
+- return dev_err_probe(dev, PTR_ERR(nop->vbus_draw),
+- "could not get vbus regulator\n");
+-
+ nop->dev = dev;
+ nop->phy.dev = nop->dev;
+ nop->phy.label = "nop-xceiv";
+diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
+index 923e0ed85444b..21fd26609252b 100644
+--- a/drivers/usb/serial/cp210x.c
++++ b/drivers/usb/serial/cp210x.c
+@@ -56,6 +56,8 @@ static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */
+ { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
+ { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
++ { USB_DEVICE(0x04BF, 0x1301) }, /* TDK Corporation NC0110013M - Network Controller */
++ { USB_DEVICE(0x04BF, 0x1303) }, /* TDK Corporation MM0110113M - i3 Micro Module */
+ { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */
+ { USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */
+ { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
+@@ -144,6 +146,7 @@ static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
+ { USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */
+ { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */
++ { USB_DEVICE(0x10C4, 0x863C) }, /* MGP Instruments PDS100 */
+ { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
+ { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
+ { USB_DEVICE(0x10C4, 0x87ED) }, /* IMST USB-Stick for Smart Meter */
+@@ -177,6 +180,7 @@ static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */
+ { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */
+ { USB_DEVICE(0x10CE, 0xEA6A) }, /* Silicon Labs MobiData GPRS USB Modem 100EU */
++ { USB_DEVICE(0x11CA, 0x0212) }, /* Verifone USB to Printer (UART, CP2102) */
+ { USB_DEVICE(0x12B8, 0xEC60) }, /* Link G4 ECU */
+ { USB_DEVICE(0x12B8, 0xEC62) }, /* Link G4+ ECU */
+ { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
+diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
+index 13a56783830df..22d01a0f10fbc 100644
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -1077,6 +1077,8 @@ static const struct usb_device_id id_table_combined[] = {
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, FTDI_FALCONIA_JTAG_UNBUF_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
++ /* GMC devices */
++ { USB_DEVICE(GMC_VID, GMC_Z216C_PID) },
+ { } /* Terminating entry */
+ };
+
+diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
+index 21a2b5a25fc09..5ee60ba2a73cd 100644
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -1606,3 +1606,9 @@
+ #define UBLOX_VID 0x1546
+ #define UBLOX_C099F9P_ZED_PID 0x0502
+ #define UBLOX_C099F9P_ODIN_PID 0x0503
++
++/*
++ * GMC devices
++ */
++#define GMC_VID 0x1cd7
++#define GMC_Z216C_PID 0x0217 /* GMC Z216C Adapter IR-USB */
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index 2ae124c49d448..55a65d941ccbf 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -613,6 +613,11 @@ static void option_instat_callback(struct urb *urb);
+ /* Luat Air72*U series based on UNISOC UIS8910 uses UNISOC's vendor ID */
+ #define LUAT_PRODUCT_AIR720U 0x4e00
+
++/* MeiG Smart Technology products */
++#define MEIGSMART_VENDOR_ID 0x2dee
++/* MeiG Smart SLM320 based on UNISOC UIS8910 */
++#define MEIGSMART_PRODUCT_SLM320 0x4d41
++
+ /* Device flags */
+
+ /* Highest interface number which can be used with NCTRL() and RSVD() */
+@@ -2282,6 +2287,7 @@ static const struct usb_device_id option_ids[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
++ { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM320, 0xff, 0, 0) },
+ { } /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(usb, option_ids);
+diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
+index 71ace274761f1..08953f0d4532a 100644
+--- a/drivers/usb/storage/uas.c
++++ b/drivers/usb/storage/uas.c
+@@ -533,7 +533,7 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
+ * daft to me.
+ */
+
+-static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp)
++static int uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp)
+ {
+ struct uas_dev_info *devinfo = cmnd->device->hostdata;
+ struct urb *urb;
+@@ -541,30 +541,28 @@ static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp)
+
+ urb = uas_alloc_sense_urb(devinfo, gfp, cmnd);
+ if (!urb)
+- return NULL;
++ return -ENOMEM;
+ usb_anchor_urb(urb, &devinfo->sense_urbs);
+ err = usb_submit_urb(urb, gfp);
+ if (err) {
+ usb_unanchor_urb(urb);
+ uas_log_cmd_state(cmnd, "sense submit err", err);
+ usb_free_urb(urb);
+- return NULL;
+ }
+- return urb;
++ return err;
+ }
+
+ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
+ struct uas_dev_info *devinfo)
+ {
+ struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd);
+- struct urb *urb;
+ int err;
+
+ lockdep_assert_held(&devinfo->lock);
+ if (cmdinfo->state & SUBMIT_STATUS_URB) {
+- urb = uas_submit_sense_urb(cmnd, GFP_ATOMIC);
+- if (!urb)
+- return SCSI_MLQUEUE_DEVICE_BUSY;
++ err = uas_submit_sense_urb(cmnd, GFP_ATOMIC);
++ if (err)
++ return err;
+ cmdinfo->state &= ~SUBMIT_STATUS_URB;
+ }
+
+@@ -572,7 +570,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
+ cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC,
+ cmnd, DMA_FROM_DEVICE);
+ if (!cmdinfo->data_in_urb)
+- return SCSI_MLQUEUE_DEVICE_BUSY;
++ return -ENOMEM;
+ cmdinfo->state &= ~ALLOC_DATA_IN_URB;
+ }
+
+@@ -582,7 +580,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
+ if (err) {
+ usb_unanchor_urb(cmdinfo->data_in_urb);
+ uas_log_cmd_state(cmnd, "data in submit err", err);
+- return SCSI_MLQUEUE_DEVICE_BUSY;
++ return err;
+ }
+ cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
+ cmdinfo->state |= DATA_IN_URB_INFLIGHT;
+@@ -592,7 +590,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
+ cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC,
+ cmnd, DMA_TO_DEVICE);
+ if (!cmdinfo->data_out_urb)
+- return SCSI_MLQUEUE_DEVICE_BUSY;
++ return -ENOMEM;
+ cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
+ }
+
+@@ -602,7 +600,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
+ if (err) {
+ usb_unanchor_urb(cmdinfo->data_out_urb);
+ uas_log_cmd_state(cmnd, "data out submit err", err);
+- return SCSI_MLQUEUE_DEVICE_BUSY;
++ return err;
+ }
+ cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
+ cmdinfo->state |= DATA_OUT_URB_INFLIGHT;
+@@ -611,7 +609,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
+ if (cmdinfo->state & ALLOC_CMD_URB) {
+ cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, GFP_ATOMIC, cmnd);
+ if (!cmdinfo->cmd_urb)
+- return SCSI_MLQUEUE_DEVICE_BUSY;
++ return -ENOMEM;
+ cmdinfo->state &= ~ALLOC_CMD_URB;
+ }
+
+@@ -621,7 +619,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
+ if (err) {
+ usb_unanchor_urb(cmdinfo->cmd_urb);
+ uas_log_cmd_state(cmnd, "cmd submit err", err);
+- return SCSI_MLQUEUE_DEVICE_BUSY;
++ return err;
+ }
+ cmdinfo->cmd_urb = NULL;
+ cmdinfo->state &= ~SUBMIT_CMD_URB;
+@@ -698,7 +696,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd)
+ * of queueing, no matter how fatal the error
+ */
+ if (err == -ENODEV) {
+- set_host_byte(cmnd, DID_ERROR);
++ set_host_byte(cmnd, DID_NO_CONNECT);
+ scsi_done(cmnd);
+ goto zombie;
+ }
+diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
+index 015aa92533536..e6a100376f09f 100644
+--- a/drivers/usb/typec/class.c
++++ b/drivers/usb/typec/class.c
+@@ -1310,6 +1310,7 @@ static ssize_t select_usb_power_delivery_store(struct device *dev,
+ {
+ struct typec_port *port = to_typec_port(dev);
+ struct usb_power_delivery *pd;
++ int ret;
+
+ if (!port->ops || !port->ops->pd_set)
+ return -EOPNOTSUPP;
+@@ -1318,7 +1319,11 @@ static ssize_t select_usb_power_delivery_store(struct device *dev,
+ if (!pd)
+ return -EINVAL;
+
+- return port->ops->pd_set(port, pd);
++ ret = port->ops->pd_set(port, pd);
++ if (ret)
++ return ret;
++
++ return size;
+ }
+
+ static ssize_t select_usb_power_delivery_show(struct device *dev,
+diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
+index 0965972310275..f81699537312a 100644
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -6117,7 +6117,7 @@ static int tcpm_pd_set(struct typec_port *p, struct usb_power_delivery *pd)
+
+ if (data->source_desc.pdo[0]) {
+ for (i = 0; i < PDO_MAX_OBJECTS && data->source_desc.pdo[i]; i++)
+- port->snk_pdo[i] = data->source_desc.pdo[i];
++ port->src_pdo[i] = data->source_desc.pdo[i];
+ port->nr_src_pdo = i + 1;
+ }
+
+@@ -6166,7 +6166,9 @@ static int tcpm_pd_set(struct typec_port *p, struct usb_power_delivery *pd)
+
+ port->port_source_caps = data->source_cap;
+ port->port_sink_caps = data->sink_cap;
++ typec_port_set_usb_power_delivery(p, NULL);
+ port->selected_pd = pd;
++ typec_port_set_usb_power_delivery(p, port->selected_pd);
+ unlock:
+ mutex_unlock(&port->lock);
+ return ret;
+@@ -6199,9 +6201,7 @@ static void tcpm_port_unregister_pd(struct tcpm_port *port)
+ port->port_source_caps = NULL;
+ for (i = 0; i < port->pd_count; i++) {
+ usb_power_delivery_unregister_capabilities(port->pd_list[i]->sink_cap);
+- kfree(port->pd_list[i]->sink_cap);
+ usb_power_delivery_unregister_capabilities(port->pd_list[i]->source_cap);
+- kfree(port->pd_list[i]->source_cap);
+ devm_kfree(port->dev, port->pd_list[i]);
+ port->pd_list[i] = NULL;
+ usb_power_delivery_unregister(port->pds[i]);
+diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
+index 14f5a7bfae2e9..0bfe5e906e543 100644
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -138,8 +138,12 @@ static int ucsi_exec_command(struct ucsi *ucsi, u64 cmd)
+ if (!(cci & UCSI_CCI_COMMAND_COMPLETE))
+ return -EIO;
+
+- if (cci & UCSI_CCI_NOT_SUPPORTED)
++ if (cci & UCSI_CCI_NOT_SUPPORTED) {
++ if (ucsi_acknowledge_command(ucsi) < 0)
++ dev_err(ucsi->dev,
++ "ACK of unsupported command failed\n");
+ return -EOPNOTSUPP;
++ }
+
+ if (cci & UCSI_CCI_ERROR) {
+ if (cmd == UCSI_GET_ERROR_STATUS)
+@@ -936,11 +940,11 @@ static void ucsi_handle_connector_change(struct work_struct *work)
+ if (con->status.change & UCSI_CONSTAT_CAM_CHANGE)
+ ucsi_partner_task(con, ucsi_check_altmodes, 1, 0);
+
+- clear_bit(EVENT_PENDING, &con->ucsi->flags);
+-
+ mutex_lock(&ucsi->ppm_lock);
++ clear_bit(EVENT_PENDING, &con->ucsi->flags);
+ ret = ucsi_acknowledge_connector_change(ucsi);
+ mutex_unlock(&ucsi->ppm_lock);
++
+ if (ret)
+ dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret);
+
+@@ -981,13 +985,47 @@ static int ucsi_reset_connector(struct ucsi_connector *con, bool hard)
+
+ static int ucsi_reset_ppm(struct ucsi *ucsi)
+ {
+- u64 command = UCSI_PPM_RESET;
++ u64 command;
+ unsigned long tmo;
+ u32 cci;
+ int ret;
+
+ mutex_lock(&ucsi->ppm_lock);
+
++ ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci));
++ if (ret < 0)
++ goto out;
++
++ /*
++ * If UCSI_CCI_RESET_COMPLETE is already set we must clear
++ * the flag before we start another reset. Send a
++ * UCSI_SET_NOTIFICATION_ENABLE command to achieve this.
++ * Ignore a timeout and try the reset anyway if this fails.
++ */
++ if (cci & UCSI_CCI_RESET_COMPLETE) {
++ command = UCSI_SET_NOTIFICATION_ENABLE;
++ ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command,
++ sizeof(command));
++ if (ret < 0)
++ goto out;
++
++ tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS);
++ do {
++ ret = ucsi->ops->read(ucsi, UCSI_CCI,
++ &cci, sizeof(cci));
++ if (ret < 0)
++ goto out;
++ if (cci & UCSI_CCI_COMMAND_COMPLETE)
++ break;
++ if (time_is_before_jiffies(tmo))
++ break;
++ msleep(20);
++ } while (1);
++
++ WARN_ON(cci & UCSI_CCI_RESET_COMPLETE);
++ }
++
++ command = UCSI_PPM_RESET;
+ ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command,
+ sizeof(command));
+ if (ret < 0)
+diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
+index 6478016d5cb8b..4550f3e8cfe9c 100644
+--- a/drivers/usb/typec/ucsi/ucsi.h
++++ b/drivers/usb/typec/ucsi/ucsi.h
+@@ -221,12 +221,12 @@ struct ucsi_cable_property {
+ #define UCSI_CABLE_PROP_FLAG_VBUS_IN_CABLE BIT(0)
+ #define UCSI_CABLE_PROP_FLAG_ACTIVE_CABLE BIT(1)
+ #define UCSI_CABLE_PROP_FLAG_DIRECTIONALITY BIT(2)
+-#define UCSI_CABLE_PROP_FLAG_PLUG_TYPE(_f_) ((_f_) & GENMASK(3, 0))
++#define UCSI_CABLE_PROP_FLAG_PLUG_TYPE(_f_) (((_f_) & GENMASK(4, 3)) >> 3)
+ #define UCSI_CABLE_PROPERTY_PLUG_TYPE_A 0
+ #define UCSI_CABLE_PROPERTY_PLUG_TYPE_B 1
+ #define UCSI_CABLE_PROPERTY_PLUG_TYPE_C 2
+ #define UCSI_CABLE_PROPERTY_PLUG_OTHER 3
+-#define UCSI_CABLE_PROP_MODE_SUPPORT BIT(5)
++#define UCSI_CABLE_PROP_FLAG_MODE_SUPPORT BIT(5)
+ u8 latency;
+ } __packed;
+
+diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c
+index 928eacbeb21ac..7b3ac133ef861 100644
+--- a/drivers/usb/typec/ucsi/ucsi_acpi.c
++++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
+@@ -23,10 +23,11 @@ struct ucsi_acpi {
+ void *base;
+ struct completion complete;
+ unsigned long flags;
++#define UCSI_ACPI_SUPPRESS_EVENT 0
++#define UCSI_ACPI_COMMAND_PENDING 1
++#define UCSI_ACPI_ACK_PENDING 2
+ guid_t guid;
+ u64 cmd;
+- bool dell_quirk_probed;
+- bool dell_quirk_active;
+ };
+
+ static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func)
+@@ -79,9 +80,9 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset,
+ int ret;
+
+ if (ack)
+- set_bit(ACK_PENDING, &ua->flags);
++ set_bit(UCSI_ACPI_ACK_PENDING, &ua->flags);
+ else
+- set_bit(COMMAND_PENDING, &ua->flags);
++ set_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags);
+
+ ret = ucsi_acpi_async_write(ucsi, offset, val, val_len);
+ if (ret)
+@@ -92,9 +93,9 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset,
+
+ out_clear_bit:
+ if (ack)
+- clear_bit(ACK_PENDING, &ua->flags);
++ clear_bit(UCSI_ACPI_ACK_PENDING, &ua->flags);
+ else
+- clear_bit(COMMAND_PENDING, &ua->flags);
++ clear_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags);
+
+ return ret;
+ }
+@@ -129,51 +130,40 @@ static const struct ucsi_operations ucsi_zenbook_ops = {
+ };
+
+ /*
+- * Some Dell laptops expect that an ACK command with the
+- * UCSI_ACK_CONNECTOR_CHANGE bit set is followed by a (separate)
+- * ACK command that only has the UCSI_ACK_COMMAND_COMPLETE bit set.
+- * If this is not done events are not delivered to OSPM and
+- * subsequent commands will timeout.
++ * Some Dell laptops don't like ACK commands with the
++ * UCSI_ACK_CONNECTOR_CHANGE but not the UCSI_ACK_COMMAND_COMPLETE
++ * bit set. To work around this send a dummy command and bundle the
++ * UCSI_ACK_CONNECTOR_CHANGE with the UCSI_ACK_COMMAND_COMPLETE
++ * for the dummy command.
+ */
+ static int
+ ucsi_dell_sync_write(struct ucsi *ucsi, unsigned int offset,
+ const void *val, size_t val_len)
+ {
+ struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
+- u64 cmd = *(u64 *)val, ack = 0;
++ u64 cmd = *(u64 *)val;
++ u64 dummycmd = UCSI_GET_CAPABILITY;
+ int ret;
+
+- if (UCSI_COMMAND(cmd) == UCSI_ACK_CC_CI &&
+- cmd & UCSI_ACK_CONNECTOR_CHANGE)
+- ack = UCSI_ACK_CC_CI | UCSI_ACK_COMMAND_COMPLETE;
+-
+- ret = ucsi_acpi_sync_write(ucsi, offset, val, val_len);
+- if (ret != 0)
+- return ret;
+- if (ack == 0)
+- return ret;
+-
+- if (!ua->dell_quirk_probed) {
+- ua->dell_quirk_probed = true;
+-
+- cmd = UCSI_GET_CAPABILITY;
+- ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd,
+- sizeof(cmd));
+- if (ret == 0)
+- return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL,
+- &ack, sizeof(ack));
+- if (ret != -ETIMEDOUT)
++ if (cmd == (UCSI_ACK_CC_CI | UCSI_ACK_CONNECTOR_CHANGE)) {
++ cmd |= UCSI_ACK_COMMAND_COMPLETE;
++
++ /*
++ * The UCSI core thinks it is sending a connector change ack
++ * and will accept new connector change events. We don't want
++ * this to happen for the dummy command as its response will
++ * still report the very event that the core is trying to clear.
++ */
++ set_bit(UCSI_ACPI_SUPPRESS_EVENT, &ua->flags);
++ ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &dummycmd,
++ sizeof(dummycmd));
++ clear_bit(UCSI_ACPI_SUPPRESS_EVENT, &ua->flags);
++
++ if (ret < 0)
+ return ret;
+-
+- ua->dell_quirk_active = true;
+- dev_err(ua->dev, "Firmware bug: Additional ACK required after ACKing a connector change.\n");
+- dev_err(ua->dev, "Firmware bug: Enabling workaround\n");
+ }
+
+- if (!ua->dell_quirk_active)
+- return ret;
+-
+- return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &ack, sizeof(ack));
++ return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd));
+ }
+
+ static const struct ucsi_operations ucsi_dell_ops = {
+@@ -209,13 +199,14 @@ static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data)
+ if (ret)
+ return;
+
+- if (UCSI_CCI_CONNECTOR(cci))
++ if (UCSI_CCI_CONNECTOR(cci) &&
++ !test_bit(UCSI_ACPI_SUPPRESS_EVENT, &ua->flags))
+ ucsi_connector_change(ua->ucsi, UCSI_CCI_CONNECTOR(cci));
+
+ if (cci & UCSI_CCI_ACK_COMPLETE && test_bit(ACK_PENDING, &ua->flags))
+ complete(&ua->complete);
+ if (cci & UCSI_CCI_COMMAND_COMPLETE &&
+- test_bit(COMMAND_PENDING, &ua->flags))
++ test_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags))
+ complete(&ua->complete);
+ }
+
+diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c
+index faccc942b381b..5d098e71f1bb7 100644
+--- a/drivers/usb/typec/ucsi/ucsi_glink.c
++++ b/drivers/usb/typec/ucsi/ucsi_glink.c
+@@ -255,6 +255,20 @@ static void pmic_glink_ucsi_notify(struct work_struct *work)
+ static void pmic_glink_ucsi_register(struct work_struct *work)
+ {
+ struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, register_work);
++ int orientation;
++ int i;
++
++ for (i = 0; i < PMIC_GLINK_MAX_PORTS; i++) {
++ if (!ucsi->port_orientation[i])
++ continue;
++ orientation = gpiod_get_value(ucsi->port_orientation[i]);
++
++ if (orientation >= 0) {
++ typec_switch_set(ucsi->port_switch[i],
++ orientation ? TYPEC_ORIENTATION_REVERSE
++ : TYPEC_ORIENTATION_NORMAL);
++ }
++ }
+
+ ucsi_register(ucsi->ucsi);
+ }
+diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c b/drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c
+index d62fbfff20b82..82b2afa9b7e31 100644
+--- a/drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c
++++ b/drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c
+@@ -141,13 +141,14 @@ static int vfio_fsl_mc_set_irq_trigger(struct vfio_fsl_mc_device *vdev,
+ irq = &vdev->mc_irqs[index];
+
+ if (flags & VFIO_IRQ_SET_DATA_NONE) {
+- vfio_fsl_mc_irq_handler(hwirq, irq);
++ if (irq->trigger)
++ eventfd_signal(irq->trigger);
+
+ } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+ u8 trigger = *(u8 *)data;
+
+- if (trigger)
+- vfio_fsl_mc_irq_handler(hwirq, irq);
++ if (trigger && irq->trigger)
++ eventfd_signal(irq->trigger);
+ }
+
+ return 0;
+diff --git a/drivers/vfio/pci/pds/lm.c b/drivers/vfio/pci/pds/lm.c
+index 79fe2e66bb498..6b94cc0bf45b4 100644
+--- a/drivers/vfio/pci/pds/lm.c
++++ b/drivers/vfio/pci/pds/lm.c
+@@ -92,8 +92,10 @@ static void pds_vfio_put_lm_file(struct pds_vfio_lm_file *lm_file)
+ {
+ mutex_lock(&lm_file->lock);
+
++ lm_file->disabled = true;
+ lm_file->size = 0;
+ lm_file->alloc_size = 0;
++ lm_file->filep->f_pos = 0;
+
+ /* Free scatter list of file pages */
+ sg_free_table(&lm_file->sg_table);
+@@ -183,6 +185,12 @@ static ssize_t pds_vfio_save_read(struct file *filp, char __user *buf,
+ pos = &filp->f_pos;
+
+ mutex_lock(&lm_file->lock);
++
++ if (lm_file->disabled) {
++ done = -ENODEV;
++ goto out_unlock;
++ }
++
+ if (*pos > lm_file->size) {
+ done = -EINVAL;
+ goto out_unlock;
+@@ -283,6 +291,11 @@ static ssize_t pds_vfio_restore_write(struct file *filp, const char __user *buf,
+
+ mutex_lock(&lm_file->lock);
+
++ if (lm_file->disabled) {
++ done = -ENODEV;
++ goto out_unlock;
++ }
++
+ while (len) {
+ size_t page_offset;
+ struct page *page;
+diff --git a/drivers/vfio/pci/pds/lm.h b/drivers/vfio/pci/pds/lm.h
+index 13be893198b74..9511b1afc6a11 100644
+--- a/drivers/vfio/pci/pds/lm.h
++++ b/drivers/vfio/pci/pds/lm.h
+@@ -27,6 +27,7 @@ struct pds_vfio_lm_file {
+ struct scatterlist *last_offset_sg; /* Iterator */
+ unsigned int sg_last_entry;
+ unsigned long last_offset;
++ bool disabled;
+ };
+
+ struct pds_vfio_pci_device;
+diff --git a/drivers/vfio/pci/pds/vfio_dev.c b/drivers/vfio/pci/pds/vfio_dev.c
+index 4c351c59d05a9..a286ebcc71126 100644
+--- a/drivers/vfio/pci/pds/vfio_dev.c
++++ b/drivers/vfio/pci/pds/vfio_dev.c
+@@ -32,9 +32,9 @@ void pds_vfio_state_mutex_unlock(struct pds_vfio_pci_device *pds_vfio)
+ mutex_lock(&pds_vfio->reset_mutex);
+ if (pds_vfio->deferred_reset) {
+ pds_vfio->deferred_reset = false;
++ pds_vfio_put_restore_file(pds_vfio);
++ pds_vfio_put_save_file(pds_vfio);
+ if (pds_vfio->state == VFIO_DEVICE_STATE_ERROR) {
+- pds_vfio_put_restore_file(pds_vfio);
+- pds_vfio_put_save_file(pds_vfio);
+ pds_vfio_dirty_disable(pds_vfio, false);
+ }
+ pds_vfio->state = pds_vfio->deferred_reset_state;
+diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c
+index 237beac838097..fb5392b749fff 100644
+--- a/drivers/vfio/pci/vfio_pci_intrs.c
++++ b/drivers/vfio/pci/vfio_pci_intrs.c
+@@ -90,22 +90,28 @@ static void vfio_send_intx_eventfd(void *opaque, void *unused)
+
+ if (likely(is_intx(vdev) && !vdev->virq_disabled)) {
+ struct vfio_pci_irq_ctx *ctx;
++ struct eventfd_ctx *trigger;
+
+ ctx = vfio_irq_ctx_get(vdev, 0);
+ if (WARN_ON_ONCE(!ctx))
+ return;
+- eventfd_signal(ctx->trigger);
++
++ trigger = READ_ONCE(ctx->trigger);
++ if (likely(trigger))
++ eventfd_signal(trigger);
+ }
+ }
+
+ /* Returns true if the INTx vfio_pci_irq_ctx.masked value is changed. */
+-bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)
++static bool __vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)
+ {
+ struct pci_dev *pdev = vdev->pdev;
+ struct vfio_pci_irq_ctx *ctx;
+ unsigned long flags;
+ bool masked_changed = false;
+
++ lockdep_assert_held(&vdev->igate);
++
+ spin_lock_irqsave(&vdev->irqlock, flags);
+
+ /*
+@@ -143,6 +149,17 @@ bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)
+ return masked_changed;
+ }
+
++bool vfio_pci_intx_mask(struct vfio_pci_core_device *vdev)
++{
++ bool mask_changed;
++
++ mutex_lock(&vdev->igate);
++ mask_changed = __vfio_pci_intx_mask(vdev);
++ mutex_unlock(&vdev->igate);
++
++ return mask_changed;
++}
++
+ /*
+ * If this is triggered by an eventfd, we can't call eventfd_signal
+ * or else we'll deadlock on the eventfd wait queue. Return >0 when
+@@ -194,12 +211,21 @@ static int vfio_pci_intx_unmask_handler(void *opaque, void *unused)
+ return ret;
+ }
+
+-void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)
++static void __vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)
+ {
++ lockdep_assert_held(&vdev->igate);
++
+ if (vfio_pci_intx_unmask_handler(vdev, NULL) > 0)
+ vfio_send_intx_eventfd(vdev, NULL);
+ }
+
++void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev)
++{
++ mutex_lock(&vdev->igate);
++ __vfio_pci_intx_unmask(vdev);
++ mutex_unlock(&vdev->igate);
++}
++
+ static irqreturn_t vfio_intx_handler(int irq, void *dev_id)
+ {
+ struct vfio_pci_core_device *vdev = dev_id;
+@@ -231,97 +257,100 @@ static irqreturn_t vfio_intx_handler(int irq, void *dev_id)
+ return ret;
+ }
+
+-static int vfio_intx_enable(struct vfio_pci_core_device *vdev)
++static int vfio_intx_enable(struct vfio_pci_core_device *vdev,
++ struct eventfd_ctx *trigger)
+ {
++ struct pci_dev *pdev = vdev->pdev;
+ struct vfio_pci_irq_ctx *ctx;
++ unsigned long irqflags;
++ char *name;
++ int ret;
+
+ if (!is_irq_none(vdev))
+ return -EINVAL;
+
+- if (!vdev->pdev->irq)
++ if (!pdev->irq)
+ return -ENODEV;
+
++ name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)", pci_name(pdev));
++ if (!name)
++ return -ENOMEM;
++
+ ctx = vfio_irq_ctx_alloc(vdev, 0);
+ if (!ctx)
+ return -ENOMEM;
+
++ ctx->name = name;
++ ctx->trigger = trigger;
++
+ /*
+- * If the virtual interrupt is masked, restore it. Devices
+- * supporting DisINTx can be masked at the hardware level
+- * here, non-PCI-2.3 devices will have to wait until the
+- * interrupt is enabled.
++ * Fill the initial masked state based on virq_disabled. After
++ * enable, changing the DisINTx bit in vconfig directly changes INTx
++ * masking. igate prevents races during setup, once running masked
++ * is protected via irqlock.
++ *
++ * Devices supporting DisINTx also reflect the current mask state in
++ * the physical DisINTx bit, which is not affected during IRQ setup.
++ *
++ * Devices without DisINTx support require an exclusive interrupt.
++ * IRQ masking is performed at the IRQ chip. Again, igate protects
++ * against races during setup and IRQ handlers and irqfds are not
++ * yet active, therefore masked is stable and can be used to
++ * conditionally auto-enable the IRQ.
++ *
++ * irq_type must be stable while the IRQ handler is registered,
++ * therefore it must be set before request_irq().
+ */
+ ctx->masked = vdev->virq_disabled;
+- if (vdev->pci_2_3)
+- pci_intx(vdev->pdev, !ctx->masked);
++ if (vdev->pci_2_3) {
++ pci_intx(pdev, !ctx->masked);
++ irqflags = IRQF_SHARED;
++ } else {
++ irqflags = ctx->masked ? IRQF_NO_AUTOEN : 0;
++ }
+
+ vdev->irq_type = VFIO_PCI_INTX_IRQ_INDEX;
+
++ ret = request_irq(pdev->irq, vfio_intx_handler,
++ irqflags, ctx->name, vdev);
++ if (ret) {
++ vdev->irq_type = VFIO_PCI_NUM_IRQS;
++ kfree(name);
++ vfio_irq_ctx_free(vdev, ctx, 0);
++ return ret;
++ }
++
+ return 0;
+ }
+
+-static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev, int fd)
++static int vfio_intx_set_signal(struct vfio_pci_core_device *vdev,
++ struct eventfd_ctx *trigger)
+ {
+ struct pci_dev *pdev = vdev->pdev;
+- unsigned long irqflags = IRQF_SHARED;
+ struct vfio_pci_irq_ctx *ctx;
+- struct eventfd_ctx *trigger;
+- unsigned long flags;
+- int ret;
++ struct eventfd_ctx *old;
+
+ ctx = vfio_irq_ctx_get(vdev, 0);
+ if (WARN_ON_ONCE(!ctx))
+ return -EINVAL;
+
+- if (ctx->trigger) {
+- free_irq(pdev->irq, vdev);
+- kfree(ctx->name);
+- eventfd_ctx_put(ctx->trigger);
+- ctx->trigger = NULL;
+- }
+-
+- if (fd < 0) /* Disable only */
+- return 0;
++ old = ctx->trigger;
+
+- ctx->name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-intx(%s)",
+- pci_name(pdev));
+- if (!ctx->name)
+- return -ENOMEM;
++ WRITE_ONCE(ctx->trigger, trigger);
+
+- trigger = eventfd_ctx_fdget(fd);
+- if (IS_ERR(trigger)) {
+- kfree(ctx->name);
+- return PTR_ERR(trigger);
++ /* Releasing an old ctx requires synchronizing in-flight users */
++ if (old) {
++ synchronize_irq(pdev->irq);
++ vfio_virqfd_flush_thread(&ctx->unmask);
++ eventfd_ctx_put(old);
+ }
+
+- ctx->trigger = trigger;
+-
+- if (!vdev->pci_2_3)
+- irqflags = 0;
+-
+- ret = request_irq(pdev->irq, vfio_intx_handler,
+- irqflags, ctx->name, vdev);
+- if (ret) {
+- ctx->trigger = NULL;
+- kfree(ctx->name);
+- eventfd_ctx_put(trigger);
+- return ret;
+- }
+-
+- /*
+- * INTx disable will stick across the new irq setup,
+- * disable_irq won't.
+- */
+- spin_lock_irqsave(&vdev->irqlock, flags);
+- if (!vdev->pci_2_3 && ctx->masked)
+- disable_irq_nosync(pdev->irq);
+- spin_unlock_irqrestore(&vdev->irqlock, flags);
+-
+ return 0;
+ }
+
+ static void vfio_intx_disable(struct vfio_pci_core_device *vdev)
+ {
++ struct pci_dev *pdev = vdev->pdev;
+ struct vfio_pci_irq_ctx *ctx;
+
+ ctx = vfio_irq_ctx_get(vdev, 0);
+@@ -329,10 +358,13 @@ static void vfio_intx_disable(struct vfio_pci_core_device *vdev)
+ if (ctx) {
+ vfio_virqfd_disable(&ctx->unmask);
+ vfio_virqfd_disable(&ctx->mask);
++ free_irq(pdev->irq, vdev);
++ if (ctx->trigger)
++ eventfd_ctx_put(ctx->trigger);
++ kfree(ctx->name);
++ vfio_irq_ctx_free(vdev, ctx, 0);
+ }
+- vfio_intx_set_signal(vdev, -1);
+ vdev->irq_type = VFIO_PCI_NUM_IRQS;
+- vfio_irq_ctx_free(vdev, ctx, 0);
+ }
+
+ /*
+@@ -560,11 +592,11 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_core_device *vdev,
+ return -EINVAL;
+
+ if (flags & VFIO_IRQ_SET_DATA_NONE) {
+- vfio_pci_intx_unmask(vdev);
++ __vfio_pci_intx_unmask(vdev);
+ } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+ uint8_t unmask = *(uint8_t *)data;
+ if (unmask)
+- vfio_pci_intx_unmask(vdev);
++ __vfio_pci_intx_unmask(vdev);
+ } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+ struct vfio_pci_irq_ctx *ctx = vfio_irq_ctx_get(vdev, 0);
+ int32_t fd = *(int32_t *)data;
+@@ -591,11 +623,11 @@ static int vfio_pci_set_intx_mask(struct vfio_pci_core_device *vdev,
+ return -EINVAL;
+
+ if (flags & VFIO_IRQ_SET_DATA_NONE) {
+- vfio_pci_intx_mask(vdev);
++ __vfio_pci_intx_mask(vdev);
+ } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+ uint8_t mask = *(uint8_t *)data;
+ if (mask)
+- vfio_pci_intx_mask(vdev);
++ __vfio_pci_intx_mask(vdev);
+ } else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+ return -ENOTTY; /* XXX implement me */
+ }
+@@ -616,19 +648,23 @@ static int vfio_pci_set_intx_trigger(struct vfio_pci_core_device *vdev,
+ return -EINVAL;
+
+ if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
++ struct eventfd_ctx *trigger = NULL;
+ int32_t fd = *(int32_t *)data;
+ int ret;
+
+- if (is_intx(vdev))
+- return vfio_intx_set_signal(vdev, fd);
++ if (fd >= 0) {
++ trigger = eventfd_ctx_fdget(fd);
++ if (IS_ERR(trigger))
++ return PTR_ERR(trigger);
++ }
+
+- ret = vfio_intx_enable(vdev);
+- if (ret)
+- return ret;
++ if (is_intx(vdev))
++ ret = vfio_intx_set_signal(vdev, trigger);
++ else
++ ret = vfio_intx_enable(vdev, trigger);
+
+- ret = vfio_intx_set_signal(vdev, fd);
+- if (ret)
+- vfio_intx_disable(vdev);
++ if (ret && trigger)
++ eventfd_ctx_put(trigger);
+
+ return ret;
+ }
+diff --git a/drivers/vfio/platform/vfio_platform_irq.c b/drivers/vfio/platform/vfio_platform_irq.c
+index 61a1bfb68ac78..ef41ecef83af1 100644
+--- a/drivers/vfio/platform/vfio_platform_irq.c
++++ b/drivers/vfio/platform/vfio_platform_irq.c
+@@ -136,6 +136,16 @@ static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
+ return 0;
+ }
+
++/*
++ * The trigger eventfd is guaranteed valid in the interrupt path
++ * and protected by the igate mutex when triggered via ioctl.
++ */
++static void vfio_send_eventfd(struct vfio_platform_irq *irq_ctx)
++{
++ if (likely(irq_ctx->trigger))
++ eventfd_signal(irq_ctx->trigger);
++}
++
+ static irqreturn_t vfio_automasked_irq_handler(int irq, void *dev_id)
+ {
+ struct vfio_platform_irq *irq_ctx = dev_id;
+@@ -155,7 +165,7 @@ static irqreturn_t vfio_automasked_irq_handler(int irq, void *dev_id)
+ spin_unlock_irqrestore(&irq_ctx->lock, flags);
+
+ if (ret == IRQ_HANDLED)
+- eventfd_signal(irq_ctx->trigger);
++ vfio_send_eventfd(irq_ctx);
+
+ return ret;
+ }
+@@ -164,52 +174,40 @@ static irqreturn_t vfio_irq_handler(int irq, void *dev_id)
+ {
+ struct vfio_platform_irq *irq_ctx = dev_id;
+
+- eventfd_signal(irq_ctx->trigger);
++ vfio_send_eventfd(irq_ctx);
+
+ return IRQ_HANDLED;
+ }
+
+ static int vfio_set_trigger(struct vfio_platform_device *vdev, int index,
+- int fd, irq_handler_t handler)
++ int fd)
+ {
+ struct vfio_platform_irq *irq = &vdev->irqs[index];
+ struct eventfd_ctx *trigger;
+- int ret;
+
+ if (irq->trigger) {
+- irq_clear_status_flags(irq->hwirq, IRQ_NOAUTOEN);
+- free_irq(irq->hwirq, irq);
+- kfree(irq->name);
++ disable_irq(irq->hwirq);
+ eventfd_ctx_put(irq->trigger);
+ irq->trigger = NULL;
+ }
+
+ if (fd < 0) /* Disable only */
+ return 0;
+- irq->name = kasprintf(GFP_KERNEL_ACCOUNT, "vfio-irq[%d](%s)",
+- irq->hwirq, vdev->name);
+- if (!irq->name)
+- return -ENOMEM;
+
+ trigger = eventfd_ctx_fdget(fd);
+- if (IS_ERR(trigger)) {
+- kfree(irq->name);
++ if (IS_ERR(trigger))
+ return PTR_ERR(trigger);
+- }
+
+ irq->trigger = trigger;
+
+- irq_set_status_flags(irq->hwirq, IRQ_NOAUTOEN);
+- ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
+- if (ret) {
+- kfree(irq->name);
+- eventfd_ctx_put(trigger);
+- irq->trigger = NULL;
+- return ret;
+- }
+-
+- if (!irq->masked)
+- enable_irq(irq->hwirq);
++ /*
++ * irq->masked effectively provides nested disables within the overall
++ * enable relative to trigger. Specifically request_irq() is called
++ * with NO_AUTOEN, therefore the IRQ is initially disabled. The user
++ * may only further disable the IRQ with a MASK operations because
++ * irq->masked is initially false.
++ */
++ enable_irq(irq->hwirq);
+
+ return 0;
+ }
+@@ -228,7 +226,7 @@ static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
+ handler = vfio_irq_handler;
+
+ if (!count && (flags & VFIO_IRQ_SET_DATA_NONE))
+- return vfio_set_trigger(vdev, index, -1, handler);
++ return vfio_set_trigger(vdev, index, -1);
+
+ if (start != 0 || count != 1)
+ return -EINVAL;
+@@ -236,7 +234,7 @@ static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
+ if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+ int32_t fd = *(int32_t *)data;
+
+- return vfio_set_trigger(vdev, index, fd, handler);
++ return vfio_set_trigger(vdev, index, fd);
+ }
+
+ if (flags & VFIO_IRQ_SET_DATA_NONE) {
+@@ -260,6 +258,14 @@ int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
+ unsigned start, unsigned count, uint32_t flags,
+ void *data) = NULL;
+
++ /*
++ * For compatibility, errors from request_irq() are local to the
++ * SET_IRQS path and reflected in the name pointer. This allows,
++ * for example, polling mode fallback for an exclusive IRQ failure.
++ */
++ if (IS_ERR(vdev->irqs[index].name))
++ return PTR_ERR(vdev->irqs[index].name);
++
+ switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
+ case VFIO_IRQ_SET_ACTION_MASK:
+ func = vfio_platform_set_irq_mask;
+@@ -280,7 +286,7 @@ int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
+
+ int vfio_platform_irq_init(struct vfio_platform_device *vdev)
+ {
+- int cnt = 0, i;
++ int cnt = 0, i, ret = 0;
+
+ while (vdev->get_irq(vdev, cnt) >= 0)
+ cnt++;
+@@ -292,37 +298,70 @@ int vfio_platform_irq_init(struct vfio_platform_device *vdev)
+
+ for (i = 0; i < cnt; i++) {
+ int hwirq = vdev->get_irq(vdev, i);
++ irq_handler_t handler = vfio_irq_handler;
+
+- if (hwirq < 0)
++ if (hwirq < 0) {
++ ret = -EINVAL;
+ goto err;
++ }
+
+ spin_lock_init(&vdev->irqs[i].lock);
+
+ vdev->irqs[i].flags = VFIO_IRQ_INFO_EVENTFD;
+
+- if (irq_get_trigger_type(hwirq) & IRQ_TYPE_LEVEL_MASK)
++ if (irq_get_trigger_type(hwirq) & IRQ_TYPE_LEVEL_MASK) {
+ vdev->irqs[i].flags |= VFIO_IRQ_INFO_MASKABLE
+ | VFIO_IRQ_INFO_AUTOMASKED;
++ handler = vfio_automasked_irq_handler;
++ }
+
+ vdev->irqs[i].count = 1;
+ vdev->irqs[i].hwirq = hwirq;
+ vdev->irqs[i].masked = false;
++ vdev->irqs[i].name = kasprintf(GFP_KERNEL_ACCOUNT,
++ "vfio-irq[%d](%s)", hwirq,
++ vdev->name);
++ if (!vdev->irqs[i].name) {
++ ret = -ENOMEM;
++ goto err;
++ }
++
++ ret = request_irq(hwirq, handler, IRQF_NO_AUTOEN,
++ vdev->irqs[i].name, &vdev->irqs[i]);
++ if (ret) {
++ kfree(vdev->irqs[i].name);
++ vdev->irqs[i].name = ERR_PTR(ret);
++ }
+ }
+
+ vdev->num_irqs = cnt;
+
+ return 0;
+ err:
++ for (--i; i >= 0; i--) {
++ if (!IS_ERR(vdev->irqs[i].name)) {
++ free_irq(vdev->irqs[i].hwirq, &vdev->irqs[i]);
++ kfree(vdev->irqs[i].name);
++ }
++ }
+ kfree(vdev->irqs);
+- return -EINVAL;
++ return ret;
+ }
+
+ void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
+ {
+ int i;
+
+- for (i = 0; i < vdev->num_irqs; i++)
+- vfio_set_trigger(vdev, i, -1, NULL);
++ for (i = 0; i < vdev->num_irqs; i++) {
++ vfio_virqfd_disable(&vdev->irqs[i].mask);
++ vfio_virqfd_disable(&vdev->irqs[i].unmask);
++ if (!IS_ERR(vdev->irqs[i].name)) {
++ free_irq(vdev->irqs[i].hwirq, &vdev->irqs[i]);
++ if (vdev->irqs[i].trigger)
++ eventfd_ctx_put(vdev->irqs[i].trigger);
++ kfree(vdev->irqs[i].name);
++ }
++ }
+
+ vdev->num_irqs = 0;
+ kfree(vdev->irqs);
+diff --git a/drivers/vfio/virqfd.c b/drivers/vfio/virqfd.c
+index 29c564b7a6e13..5322691338019 100644
+--- a/drivers/vfio/virqfd.c
++++ b/drivers/vfio/virqfd.c
+@@ -101,6 +101,13 @@ static void virqfd_inject(struct work_struct *work)
+ virqfd->thread(virqfd->opaque, virqfd->data);
+ }
+
++static void virqfd_flush_inject(struct work_struct *work)
++{
++ struct virqfd *virqfd = container_of(work, struct virqfd, flush_inject);
++
++ flush_work(&virqfd->inject);
++}
++
+ int vfio_virqfd_enable(void *opaque,
+ int (*handler)(void *, void *),
+ void (*thread)(void *, void *),
+@@ -124,6 +131,7 @@ int vfio_virqfd_enable(void *opaque,
+
+ INIT_WORK(&virqfd->shutdown, virqfd_shutdown);
+ INIT_WORK(&virqfd->inject, virqfd_inject);
++ INIT_WORK(&virqfd->flush_inject, virqfd_flush_inject);
+
+ irqfd = fdget(fd);
+ if (!irqfd.file) {
+@@ -213,3 +221,16 @@ void vfio_virqfd_disable(struct virqfd **pvirqfd)
+ flush_workqueue(vfio_irqfd_cleanup_wq);
+ }
+ EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
++
++void vfio_virqfd_flush_thread(struct virqfd **pvirqfd)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&virqfd_lock, flags);
++ if (*pvirqfd && (*pvirqfd)->thread)
++ queue_work(vfio_irqfd_cleanup_wq, &(*pvirqfd)->flush_inject);
++ spin_unlock_irqrestore(&virqfd_lock, flags);
++
++ flush_workqueue(vfio_irqfd_cleanup_wq);
++}
++EXPORT_SYMBOL_GPL(vfio_virqfd_flush_thread);
+diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
+index 2d0bcc1d786e5..ba4ab33f6094b 100644
+--- a/drivers/video/fbdev/Kconfig
++++ b/drivers/video/fbdev/Kconfig
+@@ -501,6 +501,7 @@ config FB_SBUS_HELPERS
+ select FB_CFB_COPYAREA
+ select FB_CFB_FILLRECT
+ select FB_CFB_IMAGEBLIT
++ select FB_IOMEM_FOPS
+
+ config FB_BW2
+ bool "BWtwo support"
+@@ -521,6 +522,7 @@ config FB_CG6
+ depends on (FB = y) && (SPARC && FB_SBUS)
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
++ select FB_IOMEM_FOPS
+ help
+ This is the frame buffer device driver for the CGsix (GX, TurboGX)
+ frame buffer.
+@@ -530,6 +532,7 @@ config FB_FFB
+ depends on FB_SBUS && SPARC64
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
++ select FB_IOMEM_FOPS
+ help
+ This is the frame buffer device driver for the Creator, Creator3D,
+ and Elite3D graphics boards.
+diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
+index f4080692b3513..f513ee21b1c18 100644
+--- a/drivers/virtio/virtio.c
++++ b/drivers/virtio/virtio.c
+@@ -510,8 +510,10 @@ int virtio_device_freeze(struct virtio_device *dev)
+
+ if (drv && drv->freeze) {
+ ret = drv->freeze(dev);
+- if (ret)
++ if (ret) {
++ virtio_config_enable(dev);
+ return ret;
++ }
+ }
+
+ if (dev->config->destroy_avq)
+diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
+index 378d9103a2072..be70acea87ed2 100644
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -1550,7 +1550,8 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
+ * needing to allocate extents from the block group.
+ */
+ used = btrfs_space_info_used(space_info, true);
+- if (space_info->total_bytes - block_group->length < used) {
++ if (space_info->total_bytes - block_group->length < used &&
++ block_group->zone_unusable < block_group->length) {
+ /*
+ * Add a reference for the list, compensate for the ref
+ * drop under the "next" label for the
+diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
+index 68345f73d429a..0041613a36ae5 100644
+--- a/fs/btrfs/compression.c
++++ b/fs/btrfs/compression.c
+@@ -284,7 +284,7 @@ static void end_bbio_comprssed_read(struct btrfs_bio *bbio)
+ static noinline void end_compressed_writeback(const struct compressed_bio *cb)
+ {
+ struct inode *inode = &cb->bbio.inode->vfs_inode;
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ unsigned long index = cb->start >> PAGE_SHIFT;
+ unsigned long end_index = (cb->start + cb->len - 1) >> PAGE_SHIFT;
+ struct folio_batch fbatch;
+@@ -415,7 +415,7 @@ static noinline int add_ra_bio_pages(struct inode *inode,
+ struct compressed_bio *cb,
+ int *memstall, unsigned long *pflags)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ unsigned long end_index;
+ struct bio *orig_bio = &cb->orig_bbio->bio;
+ u64 cur = cb->orig_bbio->file_offset + orig_bio->bi_iter.bi_size;
+@@ -441,7 +441,7 @@ static noinline int add_ra_bio_pages(struct inode *inode,
+ * This makes readahead less effective, so here disable readahead for
+ * subpage for now, until full compressed write is supported.
+ */
+- if (btrfs_sb(inode->i_sb)->sectorsize < PAGE_SIZE)
++ if (fs_info->sectorsize < PAGE_SIZE)
+ return 0;
+
+ end_index = (i_size_read(inode) - 1) >> PAGE_SHIFT;
+@@ -1039,7 +1039,7 @@ static int btrfs_decompress_bio(struct compressed_bio *cb)
+ int btrfs_decompress(int type, const u8 *data_in, struct page *dest_page,
+ unsigned long dest_pgoff, size_t srclen, size_t destlen)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(dest_page->mapping->host->i_sb);
++ struct btrfs_fs_info *fs_info = page_to_fs_info(dest_page);
+ struct list_head *workspace;
+ const u32 sectorsize = fs_info->sectorsize;
+ int ret;
+diff --git a/fs/btrfs/defrag.c b/fs/btrfs/defrag.c
+index 5b0b645714183..a77be9896dbd1 100644
+--- a/fs/btrfs/defrag.c
++++ b/fs/btrfs/defrag.c
+@@ -810,7 +810,7 @@ static u32 get_extent_max_capacity(const struct btrfs_fs_info *fs_info,
+ static bool defrag_check_next_extent(struct inode *inode, struct extent_map *em,
+ u32 extent_thresh, u64 newer_than, bool locked)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct extent_map *next;
+ bool ret = false;
+
+@@ -1366,7 +1366,7 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra,
+ struct btrfs_ioctl_defrag_range_args *range,
+ u64 newer_than, unsigned long max_to_defrag)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ unsigned long sectors_defragged = 0;
+ u64 isize = i_size_read(inode);
+ u64 cur;
+diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
+index c843563914cad..256782122482a 100644
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -498,15 +498,15 @@ static int btree_migrate_folio(struct address_space *mapping,
+ static int btree_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
+ {
+- struct btrfs_fs_info *fs_info;
+ int ret;
+
+ if (wbc->sync_mode == WB_SYNC_NONE) {
++ struct btrfs_fs_info *fs_info;
+
+ if (wbc->for_kupdate)
+ return 0;
+
+- fs_info = BTRFS_I(mapping->host)->root->fs_info;
++ fs_info = inode_to_fs_info(mapping->host);
+ /* this is a bit racy, but that's ok */
+ ret = __percpu_counter_compare(&fs_info->dirty_metadata_bytes,
+ BTRFS_DIRTY_METADATA_THRESH,
+@@ -529,11 +529,12 @@ static void btree_invalidate_folio(struct folio *folio, size_t offset,
+ size_t length)
+ {
+ struct extent_io_tree *tree;
+- tree = &BTRFS_I(folio->mapping->host)->io_tree;
++
++ tree = &folio_to_inode(folio)->io_tree;
+ extent_invalidate_folio(tree, folio, offset);
+ btree_release_folio(folio, GFP_NOFS);
+ if (folio_get_private(folio)) {
+- btrfs_warn(BTRFS_I(folio->mapping->host)->root->fs_info,
++ btrfs_warn(folio_to_fs_info(folio),
+ "folio private not zero on folio %llu",
+ (unsigned long long)folio_pos(folio));
+ folio_detach_private(folio);
+@@ -544,7 +545,7 @@ static void btree_invalidate_folio(struct folio *folio, size_t offset,
+ static bool btree_dirty_folio(struct address_space *mapping,
+ struct folio *folio)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(mapping->host->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(mapping->host);
+ struct btrfs_subpage_info *spi = fs_info->subpage_info;
+ struct btrfs_subpage *subpage;
+ struct extent_buffer *eb;
+@@ -2839,6 +2840,7 @@ static int init_mount_fs_info(struct btrfs_fs_info *fs_info, struct super_block
+ int ret;
+
+ fs_info->sb = sb;
++ /* Temporary fixed values for block size until we read the superblock. */
+ sb->s_blocksize = BTRFS_BDEV_BLOCKSIZE;
+ sb->s_blocksize_bits = blksize_bits(BTRFS_BDEV_BLOCKSIZE);
+
+@@ -3356,6 +3358,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
+ sb->s_bdi->ra_pages *= btrfs_super_num_devices(disk_super);
+ sb->s_bdi->ra_pages = max(sb->s_bdi->ra_pages, SZ_4M / PAGE_SIZE);
+
++ /* Update the values for the current filesystem. */
+ sb->s_blocksize = sectorsize;
+ sb->s_blocksize_bits = blksize_bits(sectorsize);
+ memcpy(&sb->s_uuid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE);
+diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
+index 744a02b7fd671..63d4cc338b81a 100644
+--- a/fs/btrfs/export.c
++++ b/fs/btrfs/export.c
+@@ -215,7 +215,7 @@ static int btrfs_get_name(struct dentry *parent, char *name,
+ {
+ struct inode *inode = d_inode(child);
+ struct inode *dir = d_inode(parent);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_path *path;
+ struct btrfs_root *root = BTRFS_I(dir)->root;
+ struct btrfs_inode_ref *iref;
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index 7761d7d93ba98..77260cb9d0b2b 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -207,7 +207,7 @@ static void __process_pages_contig(struct address_space *mapping,
+ struct page *locked_page, u64 start, u64 end,
+ unsigned long page_ops)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(mapping->host->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(mapping->host);
+ pgoff_t start_index = start >> PAGE_SHIFT;
+ pgoff_t end_index = end >> PAGE_SHIFT;
+ pgoff_t index = start_index;
+@@ -251,7 +251,7 @@ static noinline int lock_delalloc_pages(struct inode *inode,
+ u64 start,
+ u64 end)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct address_space *mapping = inode->i_mapping;
+ pgoff_t start_index = start >> PAGE_SHIFT;
+ pgoff_t end_index = end >> PAGE_SHIFT;
+@@ -323,7 +323,7 @@ noinline_for_stack bool find_lock_delalloc_range(struct inode *inode,
+ struct page *locked_page, u64 *start,
+ u64 *end)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
+ const u64 orig_start = *start;
+ const u64 orig_end = *end;
+@@ -433,7 +433,7 @@ static bool btrfs_verify_page(struct page *page, u64 start)
+
+ static void end_page_read(struct page *page, bool uptodate, u64 start, u32 len)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb);
++ struct btrfs_fs_info *fs_info = page_to_fs_info(page);
+ struct folio *folio = page_folio(page);
+
+ ASSERT(page_offset(page) <= start &&
+@@ -827,7 +827,7 @@ static void submit_extent_page(struct btrfs_bio_ctrl *bio_ctrl,
+ u64 disk_bytenr, struct page *page,
+ size_t size, unsigned long pg_offset)
+ {
+- struct btrfs_inode *inode = BTRFS_I(page->mapping->host);
++ struct btrfs_inode *inode = page_to_inode(page);
+
+ ASSERT(pg_offset + size <= PAGE_SIZE);
+ ASSERT(bio_ctrl->end_io_func);
+@@ -936,17 +936,21 @@ static int attach_extent_buffer_folio(struct extent_buffer *eb,
+
+ int set_page_extent_mapped(struct page *page)
+ {
+- struct folio *folio = page_folio(page);
++ return set_folio_extent_mapped(page_folio(page));
++}
++
++int set_folio_extent_mapped(struct folio *folio)
++{
+ struct btrfs_fs_info *fs_info;
+
+- ASSERT(page->mapping);
++ ASSERT(folio->mapping);
+
+ if (folio_test_private(folio))
+ return 0;
+
+- fs_info = btrfs_sb(page->mapping->host->i_sb);
++ fs_info = folio_to_fs_info(folio);
+
+- if (btrfs_is_subpage(fs_info, page->mapping))
++ if (btrfs_is_subpage(fs_info, folio->mapping))
+ return btrfs_attach_subpage(fs_info, folio, BTRFS_SUBPAGE_DATA);
+
+ folio_attach_private(folio, (void *)EXTENT_FOLIO_PRIVATE);
+@@ -963,7 +967,7 @@ void clear_page_extent_mapped(struct page *page)
+ if (!folio_test_private(folio))
+ return;
+
+- fs_info = btrfs_sb(page->mapping->host->i_sb);
++ fs_info = page_to_fs_info(page);
+ if (btrfs_is_subpage(fs_info, page->mapping))
+ return btrfs_detach_subpage(fs_info, folio);
+
+@@ -1007,7 +1011,7 @@ static int btrfs_do_readpage(struct page *page, struct extent_map **em_cached,
+ struct btrfs_bio_ctrl *bio_ctrl, u64 *prev_em_start)
+ {
+ struct inode *inode = page->mapping->host;
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ u64 start = page_offset(page);
+ const u64 end = start + PAGE_SIZE - 1;
+ u64 cur = start;
+@@ -1018,7 +1022,7 @@ static int btrfs_do_readpage(struct page *page, struct extent_map **em_cached,
+ int ret = 0;
+ size_t pg_offset = 0;
+ size_t iosize;
+- size_t blocksize = inode->i_sb->s_blocksize;
++ size_t blocksize = fs_info->sectorsize;
+ struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
+
+ ret = set_page_extent_mapped(page);
+@@ -1157,7 +1161,7 @@ static int btrfs_do_readpage(struct page *page, struct extent_map **em_cached,
+ int btrfs_read_folio(struct file *file, struct folio *folio)
+ {
+ struct page *page = &folio->page;
+- struct btrfs_inode *inode = BTRFS_I(page->mapping->host);
++ struct btrfs_inode *inode = page_to_inode(page);
+ u64 start = page_offset(page);
+ u64 end = start + PAGE_SIZE - 1;
+ struct btrfs_bio_ctrl bio_ctrl = { .opf = REQ_OP_READ };
+@@ -1180,7 +1184,7 @@ static inline void contiguous_readpages(struct page *pages[], int nr_pages,
+ struct btrfs_bio_ctrl *bio_ctrl,
+ u64 *prev_em_start)
+ {
+- struct btrfs_inode *inode = BTRFS_I(pages[0]->mapping->host);
++ struct btrfs_inode *inode = page_to_inode(pages[0]);
+ int index;
+
+ btrfs_lock_and_flush_ordered_range(inode, start, end, NULL);
+@@ -1766,7 +1770,7 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb,
+ */
+ static int submit_eb_subpage(struct page *page, struct writeback_control *wbc)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb);
++ struct btrfs_fs_info *fs_info = page_to_fs_info(page);
+ struct folio *folio = page_folio(page);
+ int submitted = 0;
+ u64 page_start = page_offset(page);
+@@ -1857,7 +1861,7 @@ static int submit_eb_page(struct page *page, struct btrfs_eb_write_context *ctx)
+ if (!folio_test_private(folio))
+ return 0;
+
+- if (btrfs_sb(page->mapping->host->i_sb)->nodesize < PAGE_SIZE)
++ if (page_to_fs_info(page)->nodesize < PAGE_SIZE)
+ return submit_eb_subpage(page, wbc);
+
+ spin_lock(&mapping->i_private_lock);
+@@ -1915,7 +1919,7 @@ int btree_write_cache_pages(struct address_space *mapping,
+ struct writeback_control *wbc)
+ {
+ struct btrfs_eb_write_context ctx = { .wbc = wbc };
+- struct btrfs_fs_info *fs_info = BTRFS_I(mapping->host)->root->fs_info;
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(mapping->host);
+ int ret = 0;
+ int done = 0;
+ int nr_to_write_done = 0;
+@@ -2203,7 +2207,7 @@ void extent_write_locked_range(struct inode *inode, struct page *locked_page,
+ bool found_error = false;
+ int ret = 0;
+ struct address_space *mapping = inode->i_mapping;
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ const u32 sectorsize = fs_info->sectorsize;
+ loff_t i_size = i_size_read(inode);
+ u64 cur = start;
+@@ -2309,7 +2313,7 @@ int extent_invalidate_folio(struct extent_io_tree *tree,
+ struct extent_state *cached_state = NULL;
+ u64 start = folio_pos(folio);
+ u64 end = start + folio_size(folio) - 1;
+- size_t blocksize = folio->mapping->host->i_sb->s_blocksize;
++ size_t blocksize = folio_to_fs_info(folio)->sectorsize;
+
+ /* This function is only called for the btree inode */
+ ASSERT(tree->owner == IO_TREE_BTREE_INODE_IO);
+@@ -2378,7 +2382,7 @@ int try_release_extent_mapping(struct page *page, gfp_t mask)
+ struct extent_map *em;
+ u64 start = page_offset(page);
+ u64 end = start + PAGE_SIZE - 1;
+- struct btrfs_inode *btrfs_inode = BTRFS_I(page->mapping->host);
++ struct btrfs_inode *btrfs_inode = page_to_inode(page);
+ struct extent_io_tree *tree = &btrfs_inode->io_tree;
+ struct extent_map_tree *map = &btrfs_inode->extent_tree;
+
+@@ -4315,6 +4319,19 @@ int read_extent_buffer_pages(struct extent_buffer *eb, int wait, int mirror_num,
+ if (test_and_set_bit(EXTENT_BUFFER_READING, &eb->bflags))
+ goto done;
+
++ /*
++ * Between the initial test_bit(EXTENT_BUFFER_UPTODATE) and the above
++ * test_and_set_bit(EXTENT_BUFFER_READING), someone else could have
++ * started and finished reading the same eb. In this case, UPTODATE
++ * will now be set, and we shouldn't read it in again.
++ */
++ if (unlikely(test_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags))) {
++ clear_bit(EXTENT_BUFFER_READING, &eb->bflags);
++ smp_mb__after_atomic();
++ wake_up_bit(&eb->bflags, EXTENT_BUFFER_READING);
++ return 0;
++ }
++
+ clear_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags);
+ eb->read_mirror = 0;
+ check_buffer_tree_ref(eb);
+@@ -4936,7 +4953,7 @@ static struct extent_buffer *get_next_extent_buffer(
+
+ static int try_release_subpage_extent_buffer(struct page *page)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb);
++ struct btrfs_fs_info *fs_info = page_to_fs_info(page);
+ u64 cur = page_offset(page);
+ const u64 end = page_offset(page) + PAGE_SIZE;
+ int ret;
+@@ -5009,7 +5026,7 @@ int try_release_extent_buffer(struct page *page)
+ struct folio *folio = page_folio(page);
+ struct extent_buffer *eb;
+
+- if (btrfs_sb(page->mapping->host->i_sb)->nodesize < PAGE_SIZE)
++ if (page_to_fs_info(page)->nodesize < PAGE_SIZE)
+ return try_release_subpage_extent_buffer(page);
+
+ /*
+diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
+index 46050500529bf..2c9d6570b0a38 100644
+--- a/fs/btrfs/extent_io.h
++++ b/fs/btrfs/extent_io.h
+@@ -221,6 +221,7 @@ int btree_write_cache_pages(struct address_space *mapping,
+ void extent_readahead(struct readahead_control *rac);
+ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
+ u64 start, u64 len);
++int set_folio_extent_mapped(struct folio *folio);
+ int set_page_extent_mapped(struct page *page);
+ void clear_page_extent_mapped(struct page *page);
+
+diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
+index b61099bf97a82..76378382dd8c4 100644
+--- a/fs/btrfs/extent_map.c
++++ b/fs/btrfs/extent_map.c
+@@ -291,6 +291,10 @@ static void try_merge_map(struct extent_map_tree *tree, struct extent_map *em)
+ * Called after an extent has been written to disk properly. Set the generation
+ * to the generation that actually added the file item to the inode so we know
+ * we need to sync this extent when we call fsync().
++ *
++ * Returns: 0 on success
++ * -ENOENT when the extent is not found in the tree
++ * -EUCLEAN if the found extent does not match the expected start
+ */
+ int unpin_extent_cache(struct btrfs_inode *inode, u64 start, u64 len, u64 gen)
+ {
+@@ -307,15 +311,19 @@ int unpin_extent_cache(struct btrfs_inode *inode, u64 start, u64 len, u64 gen)
+ btrfs_warn(fs_info,
+ "no extent map found for inode %llu (root %lld) when unpinning extent range [%llu, %llu), generation %llu",
+ btrfs_ino(inode), btrfs_root_id(inode->root),
+- start, len, gen);
++ start, start + len, gen);
++ ret = -ENOENT;
+ goto out;
+ }
+
+- if (WARN_ON(em->start != start))
++ if (WARN_ON(em->start != start)) {
+ btrfs_warn(fs_info,
+ "found extent map for inode %llu (root %lld) with unexpected start offset %llu when unpinning extent range [%llu, %llu), generation %llu",
+ btrfs_ino(inode), btrfs_root_id(inode->root),
+- em->start, start, len, gen);
++ em->start, start, start + len, gen);
++ ret = -EUCLEAN;
++ goto out;
++ }
+
+ em->generation = gen;
+ em->flags &= ~EXTENT_FLAG_PINNED;
+@@ -334,9 +342,9 @@ int unpin_extent_cache(struct btrfs_inode *inode, u64 start, u64 len, u64 gen)
+ em->mod_len = em->len;
+ }
+
+- free_extent_map(em);
+ out:
+ write_unlock(&tree->lock);
++ free_extent_map(em);
+ return ret;
+
+ }
+diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
+index 38dfcac476099..616790d6e5028 100644
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -1137,7 +1137,7 @@ static int btrfs_write_check(struct kiocb *iocb, struct iov_iter *from,
+ {
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ loff_t pos = iocb->ki_pos;
+ int ret;
+ loff_t oldsize;
+@@ -1185,7 +1185,7 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
+ struct file *file = iocb->ki_filp;
+ loff_t pos;
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct page **pages = NULL;
+ struct extent_changeset *data_reserved = NULL;
+ u64 release_bytes = 0;
+@@ -1461,7 +1461,7 @@ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
+ {
+ struct file *file = iocb->ki_filp;
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ loff_t pos;
+ ssize_t written = 0;
+ ssize_t written_buffered;
+@@ -1787,7 +1787,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
+ {
+ struct dentry *dentry = file_dentry(file);
+ struct inode *inode = d_inode(dentry);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_trans_handle *trans;
+ struct btrfs_log_ctx ctx;
+@@ -2593,7 +2593,7 @@ int btrfs_replace_file_extents(struct btrfs_inode *inode,
+ static int btrfs_punch_hole(struct file *file, loff_t offset, loff_t len)
+ {
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct extent_state *cached_state = NULL;
+ struct btrfs_path *path;
+@@ -3049,7 +3049,7 @@ static long btrfs_fallocate(struct file *file, int mode,
+ int ret;
+
+ /* Do not allow fallocate in ZONED mode */
+- if (btrfs_is_zoned(btrfs_sb(inode->i_sb)))
++ if (btrfs_is_zoned(inode_to_fs_info(inode)))
+ return -EOPNOTSUPP;
+
+ alloc_start = round_down(offset, blocksize);
+@@ -3754,7 +3754,7 @@ static ssize_t btrfs_direct_read(struct kiocb *iocb, struct iov_iter *to)
+ if (fsverity_active(inode))
+ return 0;
+
+- if (check_direct_read(btrfs_sb(inode->i_sb), to, iocb->ki_pos))
++ if (check_direct_read(inode_to_fs_info(inode), to, iocb->ki_pos))
+ return 0;
+
+ btrfs_inode_lock(BTRFS_I(inode), BTRFS_ILOCK_SHARED);
+diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
+index d372c7ce0e6b4..815bb146b1a5e 100644
+--- a/fs/btrfs/free-space-cache.c
++++ b/fs/btrfs/free-space-cache.c
+@@ -399,7 +399,7 @@ static int io_ctl_init(struct btrfs_io_ctl *io_ctl, struct inode *inode,
+ return -ENOMEM;
+
+ io_ctl->num_pages = num_pages;
+- io_ctl->fs_info = btrfs_sb(inode->i_sb);
++ io_ctl->fs_info = inode_to_fs_info(inode);
+ io_ctl->inode = inode;
+
+ return 0;
+diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h
+index f8bb73d6ab68c..bd59cf0aae267 100644
+--- a/fs/btrfs/fs.h
++++ b/fs/btrfs/fs.h
+@@ -829,6 +829,17 @@ struct btrfs_fs_info {
+ #endif
+ };
+
++#define page_to_inode(_page) (BTRFS_I(_Generic((_page), \
++ struct page *: (_page))->mapping->host))
++#define folio_to_inode(_folio) (BTRFS_I(_Generic((_folio), \
++ struct folio *: (_folio))->mapping->host))
++
++#define page_to_fs_info(_page) (page_to_inode(_page)->root->fs_info)
++#define folio_to_fs_info(_folio) (folio_to_inode(_folio)->root->fs_info)
++
++#define inode_to_fs_info(_inode) (BTRFS_I(_Generic((_inode), \
++ struct inode *: (_inode)))->root->fs_info)
++
+ static inline u64 btrfs_get_fs_generation(const struct btrfs_fs_info *fs_info)
+ {
+ return READ_ONCE(fs_info->generation);
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 4795738d5785b..5ceb995709b56 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -2829,7 +2829,7 @@ static void btrfs_writepage_fixup_worker(struct btrfs_work *work)
+ int btrfs_writepage_cow_fixup(struct page *page)
+ {
+ struct inode *inode = page->mapping->host;
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_writepage_fixup *fixup;
+
+ /* This page has ordered extent covering it already */
+@@ -3127,8 +3127,13 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
+ ordered_extent->disk_num_bytes);
+ }
+ }
+- unpin_extent_cache(inode, ordered_extent->file_offset,
+- ordered_extent->num_bytes, trans->transid);
++ if (ret < 0) {
++ btrfs_abort_transaction(trans, ret);
++ goto out;
++ }
++
++ ret = unpin_extent_cache(inode, ordered_extent->file_offset,
++ ordered_extent->num_bytes, trans->transid);
+ if (ret < 0) {
+ btrfs_abort_transaction(trans, ret);
+ goto out;
+@@ -3254,7 +3259,7 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
+
+ int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered)
+ {
+- if (btrfs_is_zoned(btrfs_sb(ordered->inode->i_sb)) &&
++ if (btrfs_is_zoned(inode_to_fs_info(ordered->inode)) &&
+ !test_bit(BTRFS_ORDERED_IOERR, &ordered->flags) &&
+ list_empty(&ordered->bioc_list))
+ btrfs_finish_ordered_zoned(ordered);
+@@ -3739,7 +3744,7 @@ static noinline int acls_after_inode_item(struct extent_buffer *leaf,
+ static int btrfs_read_locked_inode(struct inode *inode,
+ struct btrfs_path *in_path)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_path *path = in_path;
+ struct extent_buffer *leaf;
+ struct btrfs_inode_item *inode_item;
+@@ -4464,8 +4469,8 @@ static void btrfs_prune_dentries(struct btrfs_root *root)
+
+ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(dentry->d_sb);
+ struct btrfs_root *root = dir->root;
++ struct btrfs_fs_info *fs_info = root->fs_info;
+ struct inode *inode = d_inode(dentry);
+ struct btrfs_root *dest = BTRFS_I(inode)->root;
+ struct btrfs_trans_handle *trans;
+@@ -5019,7 +5024,7 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
+ btrfs_drew_write_unlock(&root->snapshot_lock);
+ btrfs_end_transaction(trans);
+ } else {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+
+ if (btrfs_is_zoned(fs_info)) {
+ ret = btrfs_wait_ordered_range(inode,
+@@ -5222,7 +5227,7 @@ static struct btrfs_trans_handle *evict_refill_and_join(struct btrfs_root *root,
+
+ void btrfs_evict_inode(struct inode *inode)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info;
+ struct btrfs_trans_handle *trans;
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_block_rsv *rsv = NULL;
+@@ -5236,6 +5241,7 @@ void btrfs_evict_inode(struct inode *inode)
+ return;
+ }
+
++ fs_info = inode_to_fs_info(inode);
+ evict_inode_truncate_pages(inode);
+
+ if (inode->i_nlink &&
+@@ -5661,7 +5667,7 @@ static inline u8 btrfs_inode_type(struct inode *inode)
+
+ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(dir);
+ struct inode *inode;
+ struct btrfs_root *root = BTRFS_I(dir)->root;
+ struct btrfs_root *sub_root = root;
+@@ -6200,7 +6206,7 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans,
+ struct inode *dir = args->dir;
+ struct inode *inode = args->inode;
+ const struct fscrypt_str *name = args->orphan ? NULL : &args->fname.disk_name;
+- struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(dir);
+ struct btrfs_root *root;
+ struct btrfs_inode_item *inode_item;
+ struct btrfs_key *location;
+@@ -6522,7 +6528,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
+ static int btrfs_create_common(struct inode *dir, struct dentry *dentry,
+ struct inode *inode)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(dir);
+ struct btrfs_root *root = BTRFS_I(dir)->root;
+ struct btrfs_new_inode_args new_inode_args = {
+ .dir = dir,
+@@ -6592,7 +6598,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
+ struct btrfs_trans_handle *trans = NULL;
+ struct btrfs_root *root = BTRFS_I(dir)->root;
+ struct inode *inode = d_inode(old_dentry);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct fscrypt_name fname;
+ u64 index;
+ int err;
+@@ -7078,7 +7084,7 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,
+ u64 *orig_start, u64 *orig_block_len,
+ u64 *ram_bytes, bool nowait, bool strict)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct can_nocow_file_extent_args nocow_args = { 0 };
+ struct btrfs_path *path;
+ int ret;
+@@ -7317,7 +7323,7 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
+ unsigned int iomap_flags)
+ {
+ const bool nowait = (iomap_flags & IOMAP_NOWAIT);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct extent_map *em = *map;
+ int type;
+ u64 block_start, orig_start, orig_block_len, ram_bytes;
+@@ -7457,7 +7463,7 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
+ struct iomap *srcmap)
+ {
+ struct iomap_iter *iter = container_of(iomap, struct iomap_iter, iomap);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct extent_map *em;
+ struct extent_state *cached_state = NULL;
+ struct btrfs_dio_data *dio_data = iter->private;
+@@ -7903,7 +7909,7 @@ static void btrfs_readahead(struct readahead_control *rac)
+ */
+ static void wait_subpage_spinlock(struct page *page)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(page->mapping->host->i_sb);
++ struct btrfs_fs_info *fs_info = page_to_fs_info(page);
+ struct folio *folio = page_folio(page);
+ struct btrfs_subpage *subpage;
+
+@@ -7970,7 +7976,7 @@ static int btrfs_migrate_folio(struct address_space *mapping,
+ static void btrfs_invalidate_folio(struct folio *folio, size_t offset,
+ size_t length)
+ {
+- struct btrfs_inode *inode = BTRFS_I(folio->mapping->host);
++ struct btrfs_inode *inode = folio_to_inode(folio);
+ struct btrfs_fs_info *fs_info = inode->root->fs_info;
+ struct extent_io_tree *tree = &inode->io_tree;
+ struct extent_state *cached_state = NULL;
+@@ -8154,7 +8160,7 @@ vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf)
+ struct page *page = vmf->page;
+ struct folio *folio = page_folio(page);
+ struct inode *inode = file_inode(vmf->vma->vm_file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
+ struct btrfs_ordered_extent *ordered;
+ struct extent_state *cached_state = NULL;
+@@ -8723,7 +8729,7 @@ static int btrfs_getattr(struct mnt_idmap *idmap,
+ u64 delalloc_bytes;
+ u64 inode_bytes;
+ struct inode *inode = d_inode(path->dentry);
+- u32 blocksize = inode->i_sb->s_blocksize;
++ u32 blocksize = btrfs_sb(inode->i_sb)->sectorsize;
+ u32 bi_flags = BTRFS_I(inode)->flags;
+ u32 bi_ro_flags = BTRFS_I(inode)->ro_flags;
+
+@@ -8763,7 +8769,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
+ struct inode *new_dir,
+ struct dentry *new_dentry)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(old_dir->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(old_dir);
+ struct btrfs_trans_handle *trans;
+ unsigned int trans_num_items;
+ struct btrfs_root *root = BTRFS_I(old_dir)->root;
+@@ -9015,7 +9021,7 @@ static int btrfs_rename(struct mnt_idmap *idmap,
+ struct inode *new_dir, struct dentry *new_dentry,
+ unsigned int flags)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(old_dir->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(old_dir);
+ struct btrfs_new_inode_args whiteout_args = {
+ .dir = old_dir,
+ .dentry = old_dentry,
+@@ -9457,7 +9463,7 @@ int btrfs_start_delalloc_roots(struct btrfs_fs_info *fs_info, long nr,
+ static int btrfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
+ struct dentry *dentry, const char *symname)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(dir);
+ struct btrfs_trans_handle *trans;
+ struct btrfs_root *root = BTRFS_I(dir)->root;
+ struct btrfs_path *path;
+@@ -9638,7 +9644,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
+ loff_t actual_len, u64 *alloc_hint,
+ struct btrfs_trans_handle *trans)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct extent_map *em;
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_key ins;
+@@ -9790,7 +9796,7 @@ static int btrfs_permission(struct mnt_idmap *idmap,
+ static int btrfs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
+ struct file *file, umode_t mode)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(dir);
+ struct btrfs_trans_handle *trans;
+ struct btrfs_root *root = BTRFS_I(dir)->root;
+ struct inode *inode;
+diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
+index 9d1eac15e09e1..bd19aed66605a 100644
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -247,7 +247,7 @@ int btrfs_fileattr_set(struct mnt_idmap *idmap,
+ struct dentry *dentry, struct fileattr *fa)
+ {
+ struct inode *inode = d_inode(dentry);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_inode *binode = BTRFS_I(inode);
+ struct btrfs_root *root = binode->root;
+ struct btrfs_trans_handle *trans;
+@@ -528,7 +528,7 @@ static noinline int btrfs_ioctl_fitrim(struct btrfs_fs_info *fs_info,
+ * block group is in the logical address space, which can be any
+ * sectorsize aligned bytenr in the range [0, U64_MAX].
+ */
+- if (range.len < fs_info->sb->s_blocksize)
++ if (range.len < fs_info->sectorsize)
+ return -EINVAL;
+
+ range.minlen = max(range.minlen, minlen);
+@@ -584,7 +584,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
+ struct inode *dir, struct dentry *dentry,
+ struct btrfs_qgroup_inherit *inherit)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(dir);
+ struct btrfs_trans_handle *trans;
+ struct btrfs_key key;
+ struct btrfs_root_item *root_item;
+@@ -776,7 +776,7 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
+ struct dentry *dentry, bool readonly,
+ struct btrfs_qgroup_inherit *inherit)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(dir);
+ struct inode *inode;
+ struct btrfs_pending_snapshot *pending_snapshot;
+ unsigned int trans_num_items;
+@@ -962,7 +962,7 @@ static noinline int btrfs_mksubvol(const struct path *parent,
+ struct btrfs_qgroup_inherit *inherit)
+ {
+ struct inode *dir = d_inode(parent->dentry);
+- struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(dir);
+ struct dentry *dentry;
+ struct fscrypt_str name_str = FSTR_INIT((char *)name, namelen);
+ int error;
+@@ -1097,7 +1097,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
+ {
+ BTRFS_DEV_LOOKUP_ARGS(args);
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ u64 new_size;
+ u64 old_size;
+ u64 devid = 1;
+@@ -1362,7 +1362,7 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
+ if (vol_args->flags & BTRFS_SUBVOL_RDONLY)
+ readonly = true;
+ if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
+- u64 nums;
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(file_inode(file));
+
+ if (vol_args->size < sizeof(*inherit) ||
+ vol_args->size > PAGE_SIZE) {
+@@ -1375,19 +1375,9 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
+ goto free_args;
+ }
+
+- if (inherit->num_qgroups > PAGE_SIZE ||
+- inherit->num_ref_copies > PAGE_SIZE ||
+- inherit->num_excl_copies > PAGE_SIZE) {
+- ret = -EINVAL;
+- goto free_inherit;
+- }
+-
+- nums = inherit->num_qgroups + 2 * inherit->num_ref_copies +
+- 2 * inherit->num_excl_copies;
+- if (vol_args->size != struct_size(inherit, qgroups, nums)) {
+- ret = -EINVAL;
++ ret = btrfs_qgroup_check_inherit(fs_info, inherit, vol_args->size);
++ if (ret < 0)
+ goto free_inherit;
+- }
+ }
+
+ ret = __btrfs_ioctl_snap_create(file, file_mnt_idmap(file),
+@@ -1405,7 +1395,7 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
+ static noinline int btrfs_ioctl_subvol_getflags(struct inode *inode,
+ void __user *arg)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ int ret = 0;
+ u64 flags = 0;
+@@ -1428,7 +1418,7 @@ static noinline int btrfs_ioctl_subvol_setflags(struct file *file,
+ void __user *arg)
+ {
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_trans_handle *trans;
+ u64 root_flags;
+@@ -1675,7 +1665,7 @@ static noinline int search_ioctl(struct inode *inode,
+ u64 *buf_size,
+ char __user *ubuf)
+ {
+- struct btrfs_fs_info *info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *info = inode_to_fs_info(inode);
+ struct btrfs_root *root;
+ struct btrfs_key key;
+ struct btrfs_path *path;
+@@ -2346,9 +2336,9 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
+ bool destroy_v2)
+ {
+ struct dentry *parent = file->f_path.dentry;
+- struct btrfs_fs_info *fs_info = btrfs_sb(parent->d_sb);
+ struct dentry *dentry;
+ struct inode *dir = d_inode(parent);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(dir);
+ struct inode *inode;
+ struct btrfs_root *root = BTRFS_I(dir)->root;
+ struct btrfs_root *dest = NULL;
+@@ -2696,7 +2686,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
+ {
+ BTRFS_DEV_LOOKUP_ARGS(args);
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_ioctl_vol_args_v2 *vol_args;
+ struct bdev_handle *bdev_handle = NULL;
+ int ret;
+@@ -2761,7 +2751,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
+ {
+ BTRFS_DEV_LOOKUP_ARGS(args);
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_ioctl_vol_args *vol_args;
+ struct bdev_handle *bdev_handle = NULL;
+ int ret;
+@@ -2904,7 +2894,7 @@ static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info,
+ static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp)
+ {
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_root *new_root;
+ struct btrfs_dir_item *di;
+@@ -3178,7 +3168,7 @@ static noinline long btrfs_ioctl_wait_sync(struct btrfs_fs_info *fs_info,
+
+ static long btrfs_ioctl_scrub(struct file *file, void __user *arg)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(file_inode(file)->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(file_inode(file));
+ struct btrfs_ioctl_scrub_args *sa;
+ int ret;
+
+@@ -3696,7 +3686,7 @@ static long btrfs_ioctl_balance_progress(struct btrfs_fs_info *fs_info,
+ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
+ {
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_ioctl_quota_ctl_args *sa;
+ int ret;
+
+@@ -3738,7 +3728,7 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
+ static long btrfs_ioctl_qgroup_assign(struct file *file, void __user *arg)
+ {
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_ioctl_qgroup_assign_args *sa;
+ struct btrfs_trans_handle *trans;
+@@ -3894,7 +3884,7 @@ static long btrfs_ioctl_qgroup_limit(struct file *file, void __user *arg)
+ static long btrfs_ioctl_quota_rescan(struct file *file, void __user *arg)
+ {
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_ioctl_quota_rescan_args *qsa;
+ int ret;
+
+@@ -3958,7 +3948,7 @@ static long _btrfs_ioctl_set_received_subvol(struct file *file,
+ struct btrfs_ioctl_received_subvol_args *sa)
+ {
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_root_item *root_item = &root->root_item;
+ struct btrfs_trans_handle *trans;
+@@ -4146,7 +4136,7 @@ static int btrfs_ioctl_get_fslabel(struct btrfs_fs_info *fs_info,
+ static int btrfs_ioctl_set_fslabel(struct file *file, void __user *arg)
+ {
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_super_block *super_block = fs_info->super_copy;
+ struct btrfs_trans_handle *trans;
+@@ -4289,7 +4279,7 @@ check_feature_bits(fs_info, FEAT_##mask_base, change_mask, flags, \
+ static int btrfs_ioctl_set_features(struct file *file, void __user *arg)
+ {
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ struct btrfs_super_block *super_block = fs_info->super_copy;
+ struct btrfs_ioctl_feature_flags flags[2];
+@@ -4580,7 +4570,7 @@ long btrfs_ioctl(struct file *file, unsigned int
+ cmd, unsigned long arg)
+ {
+ struct inode *inode = file_inode(file);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+ void __user *argp = (void __user *)arg;
+
+diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c
+index e43bc0fdc74ec..3e5d3b7028e8b 100644
+--- a/fs/btrfs/lzo.c
++++ b/fs/btrfs/lzo.c
+@@ -214,7 +214,7 @@ int lzo_compress_pages(struct list_head *ws, struct address_space *mapping,
+ unsigned long *total_in, unsigned long *total_out)
+ {
+ struct workspace *workspace = list_entry(ws, struct workspace, list);
+- const u32 sectorsize = btrfs_sb(mapping->host->i_sb)->sectorsize;
++ const u32 sectorsize = inode_to_fs_info(mapping->host)->sectorsize;
+ struct page *page_in = NULL;
+ char *sizes_ptr;
+ const unsigned long max_nr_page = *out_pages;
+@@ -429,7 +429,7 @@ int lzo_decompress(struct list_head *ws, const u8 *data_in,
+ size_t destlen)
+ {
+ struct workspace *workspace = list_entry(ws, struct workspace, list);
+- struct btrfs_fs_info *fs_info = btrfs_sb(dest_page->mapping->host->i_sb);
++ struct btrfs_fs_info *fs_info = page_to_fs_info(dest_page);
+ const u32 sectorsize = fs_info->sectorsize;
+ size_t in_len;
+ size_t out_len;
+diff --git a/fs/btrfs/props.c b/fs/btrfs/props.c
+index f9bf591a07187..ac4a0af2b5543 100644
+--- a/fs/btrfs/props.c
++++ b/fs/btrfs/props.c
+@@ -302,7 +302,7 @@ static int prop_compression_validate(const struct btrfs_inode *inode,
+ static int prop_compression_apply(struct inode *inode, const char *value,
+ size_t len)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ int type;
+
+ /* Reset to defaults */
+diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
+index 5470e1cdf10c5..a78c6694959aa 100644
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -2959,11 +2959,6 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans)
+ ctx.roots = NULL;
+ }
+
+- /* Free the reserved data space */
+- btrfs_qgroup_free_refroot(fs_info,
+- record->data_rsv_refroot,
+- record->data_rsv,
+- BTRFS_QGROUP_RSV_DATA);
+ /*
+ * Use BTRFS_SEQ_LAST as time_seq to do special search,
+ * which doesn't lock tree or delayed_refs and search
+@@ -2987,6 +2982,11 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans)
+ record->old_roots = NULL;
+ new_roots = NULL;
+ }
++ /* Free the reserved data space */
++ btrfs_qgroup_free_refroot(fs_info,
++ record->data_rsv_refroot,
++ record->data_rsv,
++ BTRFS_QGROUP_RSV_DATA);
+ cleanup:
+ ulist_free(record->old_roots);
+ ulist_free(new_roots);
+@@ -3048,6 +3048,57 @@ int btrfs_run_qgroups(struct btrfs_trans_handle *trans)
+ return ret;
+ }
+
++int btrfs_qgroup_check_inherit(struct btrfs_fs_info *fs_info,
++ struct btrfs_qgroup_inherit *inherit,
++ size_t size)
++{
++ if (inherit->flags & ~BTRFS_QGROUP_INHERIT_FLAGS_SUPP)
++ return -EOPNOTSUPP;
++ if (size < sizeof(*inherit) || size > PAGE_SIZE)
++ return -EINVAL;
++
++ /*
++ * In the past we allowed btrfs_qgroup_inherit to specify to copy
++ * rfer/excl numbers directly from other qgroups. This behavior has
++ * been disabled in userspace for a very long time, but here we should
++ * also disable it in kernel, as this behavior is known to mark qgroup
++ * inconsistent, and a rescan would wipe out the changes anyway.
++ *
++ * Reject any btrfs_qgroup_inherit with num_ref_copies or num_excl_copies.
++ */
++ if (inherit->num_ref_copies > 0 || inherit->num_excl_copies > 0)
++ return -EINVAL;
++
++ if (inherit->num_qgroups > PAGE_SIZE)
++ return -EINVAL;
++
++ if (size != struct_size(inherit, qgroups, inherit->num_qgroups))
++ return -EINVAL;
++
++ /*
++ * Now check all the remaining qgroups, they should all:
++ *
++ * - Exist
++ * - Be higher level qgroups.
++ */
++ for (int i = 0; i < inherit->num_qgroups; i++) {
++ struct btrfs_qgroup *qgroup;
++ u64 qgroupid = inherit->qgroups[i];
++
++ if (btrfs_qgroup_level(qgroupid) == 0)
++ return -EINVAL;
++
++ spin_lock(&fs_info->qgroup_lock);
++ qgroup = find_qgroup_rb(fs_info, qgroupid);
++ if (!qgroup) {
++ spin_unlock(&fs_info->qgroup_lock);
++ return -ENOENT;
++ }
++ spin_unlock(&fs_info->qgroup_lock);
++ }
++ return 0;
++}
++
+ static int qgroup_auto_inherit(struct btrfs_fs_info *fs_info,
+ u64 inode_rootid,
+ struct btrfs_qgroup_inherit **inherit)
+diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h
+index be18c862e64ed..45a7d8920d039 100644
+--- a/fs/btrfs/qgroup.h
++++ b/fs/btrfs/qgroup.h
+@@ -341,6 +341,9 @@ int btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans, u64 bytenr,
+ struct ulist *new_roots);
+ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans);
+ int btrfs_run_qgroups(struct btrfs_trans_handle *trans);
++int btrfs_qgroup_check_inherit(struct btrfs_fs_info *fs_info,
++ struct btrfs_qgroup_inherit *inherit,
++ size_t size);
+ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
+ u64 objectid, u64 inode_rootid,
+ struct btrfs_qgroup_inherit *inherit);
+diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c
+index ae90894dc7dc7..08d0fb46ceec4 100644
+--- a/fs/btrfs/reflink.c
++++ b/fs/btrfs/reflink.c
+@@ -174,7 +174,7 @@ static int clone_copy_inline_extent(struct inode *dst,
+ char *inline_data,
+ struct btrfs_trans_handle **trans_out)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(dst->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(dst);
+ struct btrfs_root *root = BTRFS_I(dst)->root;
+ const u64 aligned_end = ALIGN(new_key->offset + datal,
+ fs_info->sectorsize);
+@@ -337,7 +337,7 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
+ const u64 off, const u64 olen, const u64 olen_aligned,
+ const u64 destoff, int no_time_update)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ struct btrfs_path *path = NULL;
+ struct extent_buffer *leaf;
+ struct btrfs_trans_handle *trans;
+@@ -663,7 +663,7 @@ static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 len,
+ struct inode *dst, u64 dst_loff)
+ {
+ struct btrfs_fs_info *fs_info = BTRFS_I(src)->root->fs_info;
+- const u64 bs = fs_info->sb->s_blocksize;
++ const u64 bs = fs_info->sectorsize;
+ int ret;
+
+ /*
+@@ -726,11 +726,11 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
+ {
+ struct inode *inode = file_inode(file);
+ struct inode *src = file_inode(file_src);
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ int ret;
+ int wb_ret;
+ u64 len = olen;
+- u64 bs = fs_info->sb->s_blocksize;
++ u64 bs = fs_info->sectorsize;
+
+ /*
+ * VFS's generic_remap_file_range_prep() protects us from cloning the
+@@ -796,7 +796,7 @@ static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in,
+ {
+ struct inode *inode_in = file_inode(file_in);
+ struct inode *inode_out = file_inode(file_out);
+- u64 bs = BTRFS_I(inode_out)->root->fs_info->sb->s_blocksize;
++ u64 bs = BTRFS_I(inode_out)->root->fs_info->sectorsize;
+ u64 wb_len;
+ int ret;
+
+diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
+index abe594f77f99c..2fca67f2b39b9 100644
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -2987,7 +2987,7 @@ static int relocate_one_page(struct inode *inode, struct file_ra_state *ra,
+ const struct file_extent_cluster *cluster,
+ int *cluster_nr, unsigned long page_index)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
++ struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
+ u64 offset = BTRFS_I(inode)->index_cnt;
+ const unsigned long last_index = (cluster->end - offset) >> PAGE_SHIFT;
+ gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
+diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
+index 0123d27289237..9e87a6adc580b 100644
+--- a/fs/btrfs/scrub.c
++++ b/fs/btrfs/scrub.c
+@@ -2805,7 +2805,17 @@ static noinline_for_stack int scrub_supers(struct scrub_ctx *sctx,
+ gen = btrfs_get_last_trans_committed(fs_info);
+
+ for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
+- bytenr = btrfs_sb_offset(i);
++ ret = btrfs_sb_log_location(scrub_dev, i, 0, &bytenr);
++ if (ret == -ENOENT)
++ break;
++
++ if (ret) {
++ spin_lock(&sctx->stat_lock);
++ sctx->stat.super_errors++;
++ spin_unlock(&sctx->stat_lock);
++ continue;
++ }
++
+ if (bytenr + BTRFS_SUPER_INFO_SIZE >
+ scrub_dev->commit_total_bytes)
+ break;
+diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
+index e48a063ef0851..e9516509b2761 100644
+--- a/fs/btrfs/send.c
++++ b/fs/btrfs/send.c
+@@ -6140,7 +6140,7 @@ static int send_write_or_clone(struct send_ctx *sctx,
+ int ret = 0;
+ u64 offset = key->offset;
+ u64 end;
+- u64 bs = sctx->send_root->fs_info->sb->s_blocksize;
++ u64 bs = sctx->send_root->fs_info->sectorsize;
+
+ end = min_t(u64, btrfs_file_extent_end(path), sctx->cur_inode_size);
+ if (offset >= end)
+diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
+index 101f786963d4d..c45fdaf24cd1c 100644
+--- a/fs/btrfs/super.c
++++ b/fs/btrfs/super.c
+@@ -1767,7 +1767,7 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
+ buf->f_bavail = 0;
+
+ buf->f_type = BTRFS_SUPER_MAGIC;
+- buf->f_bsize = dentry->d_sb->s_blocksize;
++ buf->f_bsize = fs_info->sectorsize;
+ buf->f_namelen = BTRFS_NAME_LEN;
+
+ /* We treat it as constant endianness (it doesn't matter _which_)
+diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
+index d67785be2c778..5ccbb5f998175 100644
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -694,6 +694,16 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
+ device->bdev = bdev_handle->bdev;
+ clear_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
+
++ if (device->devt != device->bdev->bd_dev) {
++ btrfs_warn(NULL,
++ "device %s maj:min changed from %d:%d to %d:%d",
++ device->name->str, MAJOR(device->devt),
++ MINOR(device->devt), MAJOR(device->bdev->bd_dev),
++ MINOR(device->bdev->bd_dev));
++
++ device->devt = device->bdev->bd_dev;
++ }
++
+ fs_devices->open_devices++;
+ if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state) &&
+ device->devid != BTRFS_DEV_REPLACE_DEVID) {
+@@ -1301,6 +1311,47 @@ int btrfs_forget_devices(dev_t devt)
+ return ret;
+ }
+
++static bool btrfs_skip_registration(struct btrfs_super_block *disk_super,
++ const char *path, dev_t devt,
++ bool mount_arg_dev)
++{
++ struct btrfs_fs_devices *fs_devices;
++
++ /*
++ * Do not skip device registration for mounted devices with matching
++ * maj:min but different paths. Booting without initrd relies on
++ * /dev/root initially, later replaced with the actual root device.
++ * A successful scan ensures grub2-probe selects the correct device.
++ */
++ list_for_each_entry(fs_devices, &fs_uuids, fs_list) {
++ struct btrfs_device *device;
++
++ mutex_lock(&fs_devices->device_list_mutex);
++
++ if (!fs_devices->opened) {
++ mutex_unlock(&fs_devices->device_list_mutex);
++ continue;
++ }
++
++ list_for_each_entry(device, &fs_devices->devices, dev_list) {
++ if (device->bdev && (device->bdev->bd_dev == devt) &&
++ strcmp(device->name->str, path) != 0) {
++ mutex_unlock(&fs_devices->device_list_mutex);
++
++ /* Do not skip registration. */
++ return false;
++ }
++ }
++ mutex_unlock(&fs_devices->device_list_mutex);
++ }
++
++ if (!mount_arg_dev && btrfs_super_num_devices(disk_super) == 1 &&
++ !(btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_SEEDING))
++ return true;
++
++ return false;
++}
++
+ /*
+ * Look for a btrfs signature on a device. This may be called out of the mount path
+ * and we are not allowed to call set_blocksize during the scan. The superblock
+@@ -1357,18 +1408,14 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, blk_mode_t flags,
+ goto error_bdev_put;
+ }
+
+- if (!mount_arg_dev && btrfs_super_num_devices(disk_super) == 1 &&
+- !(btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_SEEDING)) {
+- dev_t devt;
++ if (btrfs_skip_registration(disk_super, path, bdev_handle->bdev->bd_dev,
++ mount_arg_dev)) {
++ pr_debug("BTRFS: skip registering single non-seed device %s (%d:%d)\n",
++ path, MAJOR(bdev_handle->bdev->bd_dev),
++ MINOR(bdev_handle->bdev->bd_dev));
+
+- ret = lookup_bdev(path, &devt);
+- if (ret)
+- btrfs_warn(NULL, "lookup bdev failed for path %s: %d",
+- path, ret);
+- else
+- btrfs_free_stale_devices(devt, NULL);
++ btrfs_free_stale_devices(bdev_handle->bdev->bd_dev, NULL);
+
+- pr_debug("BTRFS: skip registering single non-seed device %s\n", path);
+ device = NULL;
+ goto free_disk_super;
+ }
+@@ -1403,7 +1450,7 @@ static bool contains_pending_extent(struct btrfs_device *device, u64 *start,
+
+ if (in_range(physical_start, *start, len) ||
+ in_range(*start, physical_start,
+- physical_end - physical_start)) {
++ physical_end + 1 - physical_start)) {
+ *start = physical_end + 1;
+ return true;
+ }
+diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
+index 5f750fa53a2b2..9729fa29c79aa 100644
+--- a/fs/btrfs/zoned.c
++++ b/fs/btrfs/zoned.c
+@@ -1563,11 +1563,7 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
+ if (!map)
+ return -EINVAL;
+
+- cache->physical_map = btrfs_clone_chunk_map(map, GFP_NOFS);
+- if (!cache->physical_map) {
+- ret = -ENOMEM;
+- goto out;
+- }
++ cache->physical_map = map;
+
+ zone_info = kcalloc(map->num_stripes, sizeof(*zone_info), GFP_NOFS);
+ if (!zone_info) {
+@@ -1679,7 +1675,6 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
+ }
+ bitmap_free(active);
+ kfree(zone_info);
+- btrfs_free_chunk_map(map);
+
+ return ret;
+ }
+@@ -2164,6 +2159,7 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
+ struct btrfs_chunk_map *map;
+ const bool is_metadata = (block_group->flags &
+ (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM));
++ struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
+ int ret = 0;
+ int i;
+
+@@ -2239,6 +2235,7 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
+ btrfs_clear_data_reloc_bg(block_group);
+ spin_unlock(&block_group->lock);
+
++ down_read(&dev_replace->rwsem);
+ map = block_group->physical_map;
+ for (i = 0; i < map->num_stripes; i++) {
+ struct btrfs_device *device = map->stripes[i].dev;
+@@ -2253,13 +2250,16 @@ static int do_zone_finish(struct btrfs_block_group *block_group, bool fully_writ
+ zinfo->zone_size >> SECTOR_SHIFT,
+ GFP_NOFS);
+
+- if (ret)
++ if (ret) {
++ up_read(&dev_replace->rwsem);
+ return ret;
++ }
+
+ if (!(block_group->flags & BTRFS_BLOCK_GROUP_DATA))
+ zinfo->reserved_active_zones++;
+ btrfs_dev_clear_active_zone(device, physical);
+ }
++ up_read(&dev_replace->rwsem);
+
+ if (!fully_written)
+ btrfs_dec_block_group_ro(block_group);
+diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
+index 034a617cb1a5e..a40da00654336 100644
+--- a/fs/debugfs/inode.c
++++ b/fs/debugfs/inode.c
+@@ -751,13 +751,28 @@ static void __debugfs_file_removed(struct dentry *dentry)
+ if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
+ return;
+
+- /* if we hit zero, just wait for all to finish */
+- if (!refcount_dec_and_test(&fsd->active_users)) {
+- wait_for_completion(&fsd->active_users_drained);
++ /* if this was the last reference, we're done */
++ if (refcount_dec_and_test(&fsd->active_users))
+ return;
+- }
+
+- /* if we didn't hit zero, try to cancel any we can */
++ /*
++ * If there's still a reference, the code that obtained it can
++ * be in different states:
++ * - The common case of not using cancellations, or already
++ * after debugfs_leave_cancellation(), where we just need
++ * to wait for debugfs_file_put() which signals the completion;
++ * - inside a cancellation section, i.e. between
++ * debugfs_enter_cancellation() and debugfs_leave_cancellation(),
++ * in which case we need to trigger the ->cancel() function,
++ * and then wait for debugfs_file_put() just like in the
++ * previous case;
++ * - before debugfs_enter_cancellation() (but obviously after
++ * debugfs_file_get()), in which case we may not see the
++ * cancellation in the list on the first round of the loop,
++ * but debugfs_enter_cancellation() signals the completion
++ * after adding it, so this code gets woken up to call the
++ * ->cancel() function.
++ */
+ while (refcount_read(&fsd->active_users)) {
+ struct debugfs_cancellation *c;
+
+diff --git a/fs/dlm/user.c b/fs/dlm/user.c
+index 695e691b38b31..9f9b68448830e 100644
+--- a/fs/dlm/user.c
++++ b/fs/dlm/user.c
+@@ -806,7 +806,7 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
+ struct dlm_lkb *lkb;
+ DECLARE_WAITQUEUE(wait, current);
+ struct dlm_callback *cb;
+- int rv, copy_lvb = 0;
++ int rv, ret, copy_lvb = 0;
+ int old_mode, new_mode;
+
+ if (count == sizeof(struct dlm_device_version)) {
+@@ -906,9 +906,9 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
+ trace_dlm_ast(lkb->lkb_resource->res_ls, lkb);
+ }
+
+- rv = copy_result_to_user(lkb->lkb_ua,
+- test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
+- cb->flags, cb->mode, copy_lvb, buf, count);
++ ret = copy_result_to_user(lkb->lkb_ua,
++ test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
++ cb->flags, cb->mode, copy_lvb, buf, count);
+
+ kref_put(&cb->ref, dlm_release_callback);
+
+@@ -916,7 +916,7 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
+ if (rv == DLM_DEQUEUE_CALLBACK_LAST)
+ dlm_put_lkb(lkb);
+
+- return rv;
++ return ret;
+ }
+
+ static __poll_t device_poll(struct file *file, poll_table *wait)
+diff --git a/fs/exec.c b/fs/exec.c
+index af4fbb61cd53e..5ee2545c3e183 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -895,6 +895,7 @@ int transfer_args_to_stack(struct linux_binprm *bprm,
+ goto out;
+ }
+
++ bprm->exec += *sp_location - MAX_ARG_PAGES * PAGE_SIZE;
+ *sp_location = sp;
+
+ out:
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index e4f7cf9d89c45..70836e25418ab 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -5169,10 +5169,16 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ .fe_len = ac->ac_orig_goal_len,
+ };
+ loff_t orig_goal_end = extent_logical_end(sbi, &ex);
++ loff_t o_ex_end = extent_logical_end(sbi, &ac->ac_o_ex);
+
+- /* we can't allocate as much as normalizer wants.
+- * so, found space must get proper lstart
+- * to cover original request */
++ /*
++ * We can't allocate as much as normalizer wants, so we try
++ * to get proper lstart to cover the original request, except
++ * when the goal doesn't cover the original request as below:
++ *
++ * orig_ex:2045/2055(10), isize:8417280 -> normalized:0/2048
++ * best_ex:0/200(200) -> adjusted: 1848/2048(200)
++ */
+ BUG_ON(ac->ac_g_ex.fe_logical > ac->ac_o_ex.fe_logical);
+ BUG_ON(ac->ac_g_ex.fe_len < ac->ac_o_ex.fe_len);
+
+@@ -5184,7 +5190,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ * 1. Check if best ex can be kept at end of goal (before
+ * cr_best_avail trimmed it) and still cover original start
+ * 2. Else, check if best ex can be kept at start of goal and
+- * still cover original start
++ * still cover original end
+ * 3. Else, keep the best ex at start of original request.
+ */
+ ex.fe_len = ac->ac_b_ex.fe_len;
+@@ -5194,7 +5200,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ goto adjust_bex;
+
+ ex.fe_logical = ac->ac_g_ex.fe_logical;
+- if (ac->ac_o_ex.fe_logical < extent_logical_end(sbi, &ex))
++ if (o_ex_end <= extent_logical_end(sbi, &ex))
+ goto adjust_bex;
+
+ ex.fe_logical = ac->ac_o_ex.fe_logical;
+@@ -5202,7 +5208,6 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
+ ac->ac_b_ex.fe_logical = ex.fe_logical;
+
+ BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical);
+- BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len);
+ BUG_ON(extent_logical_end(sbi, &ex) > orig_goal_end);
+ }
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 4d4a5a32e310d..3c0d12382e060 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1602,7 +1602,8 @@ static int ext4_flex_group_add(struct super_block *sb,
+ int gdb_num = group / EXT4_DESC_PER_BLOCK(sb);
+ int gdb_num_end = ((group + flex_gd->count - 1) /
+ EXT4_DESC_PER_BLOCK(sb));
+- int meta_bg = ext4_has_feature_meta_bg(sb);
++ int meta_bg = ext4_has_feature_meta_bg(sb) &&
++ gdb_num >= le32_to_cpu(es->s_first_meta_bg);
+ sector_t padding_blocks = meta_bg ? 0 : sbi->s_sbh->b_blocknr -
+ ext4_group_first_block_no(sb, 0);
+
+diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
+index 5a6c35d70c7ad..6610ff6d7e6cc 100644
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -3032,6 +3032,7 @@ static inline void __mark_inode_dirty_flag(struct inode *inode,
+ case FI_INLINE_DOTS:
+ case FI_PIN_FILE:
+ case FI_COMPRESS_RELEASED:
++ case FI_ATOMIC_COMMITTED:
+ f2fs_mark_inode_dirty_sync(inode, true);
+ }
+ }
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+index 60531f50f37fe..6d5774093452f 100644
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -192,6 +192,9 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean)
+ if (!f2fs_is_atomic_file(inode))
+ return;
+
++ if (clean)
++ truncate_inode_pages_final(inode->i_mapping);
++
+ release_atomic_write_cnt(inode);
+ clear_inode_flag(inode, FI_ATOMIC_COMMITTED);
+ clear_inode_flag(inode, FI_ATOMIC_REPLACE);
+@@ -201,7 +204,6 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean)
+ F2FS_I(inode)->atomic_write_task = NULL;
+
+ if (clean) {
+- truncate_inode_pages_final(inode->i_mapping);
+ f2fs_i_size_write(inode, fi->original_i_size);
+ fi->original_i_size = 0;
+ }
+diff --git a/fs/fat/nfs.c b/fs/fat/nfs.c
+index c52e63e10d35c..509eea96a457d 100644
+--- a/fs/fat/nfs.c
++++ b/fs/fat/nfs.c
+@@ -130,6 +130,12 @@ fat_encode_fh_nostale(struct inode *inode, __u32 *fh, int *lenp,
+ fid->parent_i_gen = parent->i_generation;
+ type = FILEID_FAT_WITH_PARENT;
+ *lenp = FAT_FID_SIZE_WITH_PARENT;
++ } else {
++ /*
++ * We need to initialize this field because the fh is actually
++ * 12 bytes long
++ */
++ fid->parent_i_pos_hi = 0;
+ }
+
+ return type;
+diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
+index d19cbf34c6341..9307bb4393b8f 100644
+--- a/fs/fuse/dir.c
++++ b/fs/fuse/dir.c
+@@ -391,6 +391,10 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
+ err = -EIO;
+ if (fuse_invalid_attr(&outarg->attr))
+ goto out_put_forget;
++ if (outarg->nodeid == FUSE_ROOT_ID && outarg->generation != 0) {
++ pr_warn_once("root generation should be zero\n");
++ outarg->generation = 0;
++ }
+
+ *inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
+ &outarg->attr, ATTR_TIMEOUT(outarg),
+@@ -1210,7 +1214,7 @@ static int fuse_do_statx(struct inode *inode, struct file *file,
+ if (((sx->mask & STATX_SIZE) && !fuse_valid_size(sx->size)) ||
+ ((sx->mask & STATX_TYPE) && (!fuse_valid_type(sx->mode) ||
+ inode_wrong_type(inode, sx->mode)))) {
+- make_bad_inode(inode);
++ fuse_make_bad(inode);
+ return -EIO;
+ }
+
+diff --git a/fs/fuse/file.c b/fs/fuse/file.c
+index 148a71b8b4d0e..b9cff9b6ca1b8 100644
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -2468,7 +2468,8 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
+ return fuse_dax_mmap(file, vma);
+
+ if (ff->open_flags & FOPEN_DIRECT_IO) {
+- /* Can't provide the coherency needed for MAP_SHARED
++ /*
++ * Can't provide the coherency needed for MAP_SHARED
+ * if FUSE_DIRECT_IO_ALLOW_MMAP isn't set.
+ */
+ if ((vma->vm_flags & VM_MAYSHARE) && !fc->direct_io_allow_mmap)
+@@ -2476,7 +2477,10 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
+
+ invalidate_inode_pages2(file->f_mapping);
+
+- return generic_file_mmap(file, vma);
++ if (!(vma->vm_flags & VM_MAYSHARE)) {
++ /* MAP_PRIVATE */
++ return generic_file_mmap(file, vma);
++ }
+ }
+
+ if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
+diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
+index bcbe344888627..20924e799c9f5 100644
+--- a/fs/fuse/fuse_i.h
++++ b/fs/fuse/fuse_i.h
+@@ -940,7 +940,6 @@ static inline bool fuse_stale_inode(const struct inode *inode, int generation,
+
+ static inline void fuse_make_bad(struct inode *inode)
+ {
+- remove_inode_hash(inode);
+ set_bit(FUSE_I_BAD, &get_fuse_inode(inode)->state);
+ }
+
+diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
+index 516ea2979a90f..f73865751c732 100644
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -469,8 +469,11 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid,
+ } else if (fuse_stale_inode(inode, generation, attr)) {
+ /* nodeid was reused, any I/O on the old inode should fail */
+ fuse_make_bad(inode);
+- iput(inode);
+- goto retry;
++ if (inode != d_inode(sb->s_root)) {
++ remove_inode_hash(inode);
++ iput(inode);
++ goto retry;
++ }
+ }
+ fi = get_fuse_inode(inode);
+ spin_lock(&fi->lock);
+diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
+index c03926a1cc73b..d8cd4f69e33a0 100644
+--- a/fs/nfs/direct.c
++++ b/fs/nfs/direct.c
+@@ -667,10 +667,17 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq)
+ LIST_HEAD(mds_list);
+
+ nfs_init_cinfo_from_dreq(&cinfo, dreq);
++ nfs_commit_begin(cinfo.mds);
+ nfs_scan_commit(dreq->inode, &mds_list, &cinfo);
+ res = nfs_generic_commit_list(dreq->inode, &mds_list, 0, &cinfo);
+- if (res < 0) /* res == -ENOMEM */
+- nfs_direct_write_reschedule(dreq);
++ if (res < 0) { /* res == -ENOMEM */
++ spin_lock(&dreq->lock);
++ if (dreq->flags == 0)
++ dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
++ spin_unlock(&dreq->lock);
++ }
++ if (nfs_commit_end(cinfo.mds))
++ nfs_direct_write_complete(dreq);
+ }
+
+ static void nfs_direct_write_clear_reqs(struct nfs_direct_req *dreq)
+diff --git a/fs/nfs/read.c b/fs/nfs/read.c
+index 7dc21a48e3e7b..a142287d86f68 100644
+--- a/fs/nfs/read.c
++++ b/fs/nfs/read.c
+@@ -305,6 +305,8 @@ int nfs_read_add_folio(struct nfs_pageio_descriptor *pgio,
+ new = nfs_page_create_from_folio(ctx, folio, 0, aligned_len);
+ if (IS_ERR(new)) {
+ error = PTR_ERR(new);
++ if (nfs_netfs_folio_unlock(folio))
++ folio_unlock(folio);
+ goto out;
+ }
+
+diff --git a/fs/nfs/write.c b/fs/nfs/write.c
+index bb79d3a886ae8..5d9dc6c053255 100644
+--- a/fs/nfs/write.c
++++ b/fs/nfs/write.c
+@@ -1650,7 +1650,7 @@ static int wait_on_commit(struct nfs_mds_commit_info *cinfo)
+ !atomic_read(&cinfo->rpcs_out));
+ }
+
+-static void nfs_commit_begin(struct nfs_mds_commit_info *cinfo)
++void nfs_commit_begin(struct nfs_mds_commit_info *cinfo)
+ {
+ atomic_inc(&cinfo->rpcs_out);
+ }
+diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
+index d1e8cf079b0f4..2cd57033791ff 100644
+--- a/fs/nfsd/trace.h
++++ b/fs/nfsd/trace.h
+@@ -843,7 +843,7 @@ DECLARE_EVENT_CLASS(nfsd_clid_class,
+ __array(unsigned char, addr, sizeof(struct sockaddr_in6))
+ __field(unsigned long, flavor)
+ __array(unsigned char, verifier, NFS4_VERIFIER_SIZE)
+- __string_len(name, name, clp->cl_name.len)
++ __string_len(name, clp->cl_name.data, clp->cl_name.len)
+ ),
+ TP_fast_assign(
+ __entry->cl_boot = clp->cl_clientid.cl_boot;
+diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c
+index 13592e82eaf68..65659fa0372e6 100644
+--- a/fs/nilfs2/btree.c
++++ b/fs/nilfs2/btree.c
+@@ -724,7 +724,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
+ dat = nilfs_bmap_get_dat(btree);
+ ret = nilfs_dat_translate(dat, ptr, &blocknr);
+ if (ret < 0)
+- goto out;
++ goto dat_error;
+ ptr = blocknr;
+ }
+ cnt = 1;
+@@ -743,7 +743,7 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
+ if (dat) {
+ ret = nilfs_dat_translate(dat, ptr2, &blocknr);
+ if (ret < 0)
+- goto out;
++ goto dat_error;
+ ptr2 = blocknr;
+ }
+ if (ptr2 != ptr + cnt || ++cnt == maxblocks)
+@@ -781,6 +781,11 @@ static int nilfs_btree_lookup_contig(const struct nilfs_bmap *btree,
+ out:
+ nilfs_btree_free_path(path);
+ return ret;
++
++ dat_error:
++ if (ret == -ENOENT)
++ ret = -EINVAL; /* Notify bmap layer of metadata corruption */
++ goto out;
+ }
+
+ static void nilfs_btree_promote_key(struct nilfs_bmap *btree,
+diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c
+index 4c85914f2abc3..893ab36824cc2 100644
+--- a/fs/nilfs2/direct.c
++++ b/fs/nilfs2/direct.c
+@@ -66,7 +66,7 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
+ dat = nilfs_bmap_get_dat(direct);
+ ret = nilfs_dat_translate(dat, ptr, &blocknr);
+ if (ret < 0)
+- return ret;
++ goto dat_error;
+ ptr = blocknr;
+ }
+
+@@ -79,7 +79,7 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
+ if (dat) {
+ ret = nilfs_dat_translate(dat, ptr2, &blocknr);
+ if (ret < 0)
+- return ret;
++ goto dat_error;
+ ptr2 = blocknr;
+ }
+ if (ptr2 != ptr + cnt)
+@@ -87,6 +87,11 @@ static int nilfs_direct_lookup_contig(const struct nilfs_bmap *direct,
+ }
+ *ptrp = ptr;
+ return cnt;
++
++ dat_error:
++ if (ret == -ENOENT)
++ ret = -EINVAL; /* Notify bmap layer of metadata corruption */
++ return ret;
+ }
+
+ static __u64
+diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
+index 9c334c722fc1c..5a888b2c1803d 100644
+--- a/fs/nilfs2/inode.c
++++ b/fs/nilfs2/inode.c
+@@ -112,7 +112,7 @@ int nilfs_get_block(struct inode *inode, sector_t blkoff,
+ "%s (ino=%lu): a race condition while inserting a data block at offset=%llu",
+ __func__, inode->i_ino,
+ (unsigned long long)blkoff);
+- err = 0;
++ err = -EAGAIN;
+ }
+ nilfs_transaction_abort(inode->i_sb);
+ goto out;
+diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
+index 3de5047a7ff98..a0017724d5239 100644
+--- a/fs/smb/client/cached_dir.c
++++ b/fs/smb/client/cached_dir.c
+@@ -239,7 +239,8 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
+ .tcon = tcon,
+ .path = path,
+ .create_options = cifs_create_options(cifs_sb, CREATE_NOT_FILE),
+- .desired_access = FILE_READ_DATA | FILE_READ_ATTRIBUTES,
++ .desired_access = FILE_READ_DATA | FILE_READ_ATTRIBUTES |
++ FILE_READ_EA,
+ .disposition = FILE_OPEN,
+ .fid = pfid,
+ .replay = !!(retries),
+diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c
+index 3e4209f41c18f..23d2622b969f0 100644
+--- a/fs/smb/client/cifs_debug.c
++++ b/fs/smb/client/cifs_debug.c
+@@ -488,6 +488,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
+ ses->ses_count, ses->serverOS, ses->serverNOS,
+ ses->capabilities, ses->ses_status);
+ }
++ if (ses->expired_pwd)
++ seq_puts(m, "password no longer valid ");
+ spin_unlock(&ses->ses_lock);
+
+ seq_printf(m, "\n\tSecurity type: %s ",
+diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
+index 53c75cfb33ab9..06e81afe31c14 100644
+--- a/fs/smb/client/cifsglob.h
++++ b/fs/smb/client/cifsglob.h
+@@ -346,6 +346,9 @@ struct smb_version_operations {
+ /* informational QFS call */
+ void (*qfs_tcon)(const unsigned int, struct cifs_tcon *,
+ struct cifs_sb_info *);
++ /* query for server interfaces */
++ int (*query_server_interfaces)(const unsigned int, struct cifs_tcon *,
++ bool);
+ /* check if a path is accessible or not */
+ int (*is_path_accessible)(const unsigned int, struct cifs_tcon *,
+ struct cifs_sb_info *, const char *);
+@@ -1066,6 +1069,7 @@ struct cifs_ses {
+ enum securityEnum sectype; /* what security flavor was specified? */
+ bool sign; /* is signing required? */
+ bool domainAuto:1;
++ bool expired_pwd; /* track if access denied or expired pwd so can know if need to update */
+ unsigned int flags;
+ __u16 session_flags;
+ __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
+diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
+index a841bf4967fa4..58cfbd450a55e 100644
+--- a/fs/smb/client/cifsproto.h
++++ b/fs/smb/client/cifsproto.h
+@@ -144,7 +144,8 @@ extern int cifs_reconnect(struct TCP_Server_Info *server,
+ extern int checkSMB(char *buf, unsigned int len, struct TCP_Server_Info *srvr);
+ extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
+ extern bool backup_cred(struct cifs_sb_info *);
+-extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
++extern bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 eof,
++ bool from_readdir);
+ extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
+ unsigned int bytes_written);
+ extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, int);
+@@ -201,7 +202,8 @@ extern void cifs_unix_basic_to_fattr(struct cifs_fattr *fattr,
+ struct cifs_sb_info *cifs_sb);
+ extern void cifs_dir_info_to_fattr(struct cifs_fattr *, FILE_DIRECTORY_INFO *,
+ struct cifs_sb_info *);
+-extern int cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr);
++extern int cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
++ bool from_readdir);
+ extern struct inode *cifs_iget(struct super_block *sb,
+ struct cifs_fattr *fattr);
+
+diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
+index ac9595504f4b1..2341604606157 100644
+--- a/fs/smb/client/connect.c
++++ b/fs/smb/client/connect.c
+@@ -123,12 +123,16 @@ static void smb2_query_server_interfaces(struct work_struct *work)
+ struct cifs_tcon *tcon = container_of(work,
+ struct cifs_tcon,
+ query_interfaces.work);
++ struct TCP_Server_Info *server = tcon->ses->server;
+
+ /*
+ * query server network interfaces, in case they change
+ */
++ if (!server->ops->query_server_interfaces)
++ return;
++
+ xid = get_xid();
+- rc = SMB3_request_interfaces(xid, tcon, false);
++ rc = server->ops->query_server_interfaces(xid, tcon, false);
+ free_xid(xid);
+
+ if (rc) {
+diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
+index 98514f2f2d7b1..9d42a39009076 100644
+--- a/fs/smb/client/file.c
++++ b/fs/smb/client/file.c
+@@ -329,7 +329,7 @@ int cifs_posix_open(const char *full_path, struct inode **pinode,
+ }
+ } else {
+ cifs_revalidate_mapping(*pinode);
+- rc = cifs_fattr_to_inode(*pinode, &fattr);
++ rc = cifs_fattr_to_inode(*pinode, &fattr, false);
+ }
+
+ posix_open_ret:
+@@ -4769,12 +4769,14 @@ static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
+ refreshing the inode only on increases in the file size
+ but this is tricky to do without racing with writebehind
+ page caching in the current Linux kernel design */
+-bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file)
++bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file,
++ bool from_readdir)
+ {
+ if (!cifsInode)
+ return true;
+
+- if (is_inode_writable(cifsInode)) {
++ if (is_inode_writable(cifsInode) ||
++ ((cifsInode->oplock & CIFS_CACHE_RW_FLG) != 0 && from_readdir)) {
+ /* This inode is open for write at least once */
+ struct cifs_sb_info *cifs_sb;
+
+diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
+index 4b2f5aa2ea0e1..415e87635d5aa 100644
+--- a/fs/smb/client/fs_context.c
++++ b/fs/smb/client/fs_context.c
+@@ -772,7 +772,7 @@ static void smb3_fs_context_free(struct fs_context *fc)
+ */
+ static int smb3_verify_reconfigure_ctx(struct fs_context *fc,
+ struct smb3_fs_context *new_ctx,
+- struct smb3_fs_context *old_ctx)
++ struct smb3_fs_context *old_ctx, bool need_recon)
+ {
+ if (new_ctx->posix_paths != old_ctx->posix_paths) {
+ cifs_errorf(fc, "can not change posixpaths during remount\n");
+@@ -798,8 +798,15 @@ static int smb3_verify_reconfigure_ctx(struct fs_context *fc,
+ }
+ if (new_ctx->password &&
+ (!old_ctx->password || strcmp(new_ctx->password, old_ctx->password))) {
+- cifs_errorf(fc, "can not change password during remount\n");
+- return -EINVAL;
++ if (need_recon == false) {
++ cifs_errorf(fc,
++ "can not change password of active session during remount\n");
++ return -EINVAL;
++ } else if (old_ctx->sectype == Kerberos) {
++ cifs_errorf(fc,
++ "can not change password for Kerberos via remount\n");
++ return -EINVAL;
++ }
+ }
+ if (new_ctx->domainname &&
+ (!old_ctx->domainname || strcmp(new_ctx->domainname, old_ctx->domainname))) {
+@@ -843,9 +850,14 @@ static int smb3_reconfigure(struct fs_context *fc)
+ struct smb3_fs_context *ctx = smb3_fc2context(fc);
+ struct dentry *root = fc->root;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
++ struct cifs_ses *ses = cifs_sb_master_tcon(cifs_sb)->ses;
++ bool need_recon = false;
+ int rc;
+
+- rc = smb3_verify_reconfigure_ctx(fc, ctx, cifs_sb->ctx);
++ if (ses->expired_pwd)
++ need_recon = true;
++
++ rc = smb3_verify_reconfigure_ctx(fc, ctx, cifs_sb->ctx, need_recon);
+ if (rc)
+ return rc;
+
+@@ -858,7 +870,12 @@ static int smb3_reconfigure(struct fs_context *fc)
+ STEAL_STRING(cifs_sb, ctx, UNC);
+ STEAL_STRING(cifs_sb, ctx, source);
+ STEAL_STRING(cifs_sb, ctx, username);
+- STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
++ if (need_recon == false)
++ STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
++ else {
++ kfree_sensitive(ses->password);
++ ses->password = kstrdup(ctx->password, GFP_KERNEL);
++ }
+ STEAL_STRING(cifs_sb, ctx, domainname);
+ STEAL_STRING(cifs_sb, ctx, nodename);
+ STEAL_STRING(cifs_sb, ctx, iocharset);
+diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
+index d02f8ba29cb5b..7f28edf4b20f3 100644
+--- a/fs/smb/client/inode.c
++++ b/fs/smb/client/inode.c
+@@ -147,7 +147,8 @@ cifs_nlink_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
+
+ /* populate an inode with info from a cifs_fattr struct */
+ int
+-cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
++cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
++ bool from_readdir)
+ {
+ struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+@@ -199,7 +200,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
+ * Can't safely change the file size here if the client is writing to
+ * it due to potential races.
+ */
+- if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
++ if (is_size_safe_to_change(cifs_i, fattr->cf_eof, from_readdir)) {
+ i_size_write(inode, fattr->cf_eof);
+
+ /*
+@@ -368,7 +369,7 @@ static int update_inode_info(struct super_block *sb,
+ CIFS_I(*inode)->time = 0; /* force reval */
+ return -ESTALE;
+ }
+- return cifs_fattr_to_inode(*inode, fattr);
++ return cifs_fattr_to_inode(*inode, fattr, false);
+ }
+
+ #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+@@ -403,7 +404,7 @@ cifs_get_file_info_unix(struct file *filp)
+ } else
+ goto cifs_gfiunix_out;
+
+- rc = cifs_fattr_to_inode(inode, &fattr);
++ rc = cifs_fattr_to_inode(inode, &fattr, false);
+
+ cifs_gfiunix_out:
+ free_xid(xid);
+@@ -934,7 +935,7 @@ cifs_get_file_info(struct file *filp)
+ fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
+ fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
+ /* if filetype is different, return error */
+- rc = cifs_fattr_to_inode(inode, &fattr);
++ rc = cifs_fattr_to_inode(inode, &fattr, false);
+ cgfi_exit:
+ cifs_free_open_info(&data);
+ free_xid(xid);
+@@ -1491,7 +1492,7 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
+ }
+
+ /* can't fail - see cifs_find_inode() */
+- cifs_fattr_to_inode(inode, fattr);
++ cifs_fattr_to_inode(inode, fattr, false);
+ if (sb->s_flags & SB_NOATIME)
+ inode->i_flags |= S_NOATIME | S_NOCMTIME;
+ if (inode->i_state & I_NEW) {
+diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c
+index b520eea7bfce8..132ae7d884a97 100644
+--- a/fs/smb/client/readdir.c
++++ b/fs/smb/client/readdir.c
+@@ -148,7 +148,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
+ rc = -ESTALE;
+ }
+ }
+- if (!rc && !cifs_fattr_to_inode(inode, fattr)) {
++ if (!rc && !cifs_fattr_to_inode(inode, fattr, true)) {
+ dput(dentry);
+ return;
+ }
+diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c
+index 8f37373fd3334..3216f786908fb 100644
+--- a/fs/smb/client/sess.c
++++ b/fs/smb/client/sess.c
+@@ -230,7 +230,7 @@ int cifs_try_adding_channels(struct cifs_ses *ses)
+ spin_lock(&ses->iface_lock);
+ if (!ses->iface_count) {
+ spin_unlock(&ses->iface_lock);
+- cifs_dbg(VFS, "server %s does not advertise interfaces\n",
++ cifs_dbg(ONCE, "server %s does not advertise interfaces\n",
+ ses->server->hostname);
+ break;
+ }
+@@ -396,7 +396,7 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
+ spin_lock(&ses->iface_lock);
+ if (!ses->iface_count) {
+ spin_unlock(&ses->iface_lock);
+- cifs_dbg(VFS, "server %s does not advertise interfaces\n", ses->server->hostname);
++ cifs_dbg(ONCE, "server %s does not advertise interfaces\n", ses->server->hostname);
+ return;
+ }
+
+diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
+index 4695433fcf397..3b8896987197e 100644
+--- a/fs/smb/client/smb2ops.c
++++ b/fs/smb/client/smb2ops.c
+@@ -5538,6 +5538,7 @@ struct smb_version_operations smb30_operations = {
+ .tree_connect = SMB2_tcon,
+ .tree_disconnect = SMB2_tdis,
+ .qfs_tcon = smb3_qfs_tcon,
++ .query_server_interfaces = SMB3_request_interfaces,
+ .is_path_accessible = smb2_is_path_accessible,
+ .can_echo = smb2_can_echo,
+ .echo = SMB2_echo,
+@@ -5653,6 +5654,7 @@ struct smb_version_operations smb311_operations = {
+ .tree_connect = SMB2_tcon,
+ .tree_disconnect = SMB2_tdis,
+ .qfs_tcon = smb3_qfs_tcon,
++ .query_server_interfaces = SMB3_request_interfaces,
+ .is_path_accessible = smb2_is_path_accessible,
+ .can_echo = smb2_can_echo,
+ .echo = SMB2_echo,
+diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
+index 608ee05491e26..92c3710df6159 100644
+--- a/fs/smb/client/smb2pdu.c
++++ b/fs/smb/client/smb2pdu.c
+@@ -409,14 +409,15 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+ spin_unlock(&ses->ses_lock);
+
+ if (!rc &&
+- (server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL)) {
++ (server->capabilities & SMB2_GLOBAL_CAP_MULTI_CHANNEL) &&
++ server->ops->query_server_interfaces) {
+ mutex_unlock(&ses->session_mutex);
+
+ /*
+ * query server network interfaces, in case they change
+ */
+ xid = get_xid();
+- rc = SMB3_request_interfaces(xid, tcon, false);
++ rc = server->ops->query_server_interfaces(xid, tcon, false);
+ free_xid(xid);
+
+ if (rc == -EOPNOTSUPP && ses->chan_count > 1) {
+@@ -1536,6 +1537,11 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
+ &sess_data->buf0_type,
+ CIFS_LOG_ERROR | CIFS_SESS_OP, &rsp_iov);
+ cifs_small_buf_release(sess_data->iov[0].iov_base);
++ if (rc == 0)
++ sess_data->ses->expired_pwd = false;
++ else if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED))
++ sess_data->ses->expired_pwd = true;
++
+ memcpy(&sess_data->iov[0], &rsp_iov, sizeof(struct kvec));
+
+ return rc;
+diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c
+index 03dded29a9804..727cb49926ee5 100644
+--- a/fs/smb/server/smb2misc.c
++++ b/fs/smb/server/smb2misc.c
+@@ -101,13 +101,17 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
+ *len = le16_to_cpu(((struct smb2_sess_setup_req *)hdr)->SecurityBufferLength);
+ break;
+ case SMB2_TREE_CONNECT:
+- *off = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset);
++ *off = max_t(unsigned short int,
++ le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathOffset),
++ offsetof(struct smb2_tree_connect_req, Buffer));
+ *len = le16_to_cpu(((struct smb2_tree_connect_req *)hdr)->PathLength);
+ break;
+ case SMB2_CREATE:
+ {
+ unsigned short int name_off =
+- le16_to_cpu(((struct smb2_create_req *)hdr)->NameOffset);
++ max_t(unsigned short int,
++ le16_to_cpu(((struct smb2_create_req *)hdr)->NameOffset),
++ offsetof(struct smb2_create_req, Buffer));
+ unsigned short int name_len =
+ le16_to_cpu(((struct smb2_create_req *)hdr)->NameLength);
+
+@@ -128,11 +132,15 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
+ break;
+ }
+ case SMB2_QUERY_INFO:
+- *off = le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset);
++ *off = max_t(unsigned int,
++ le16_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferOffset),
++ offsetof(struct smb2_query_info_req, Buffer));
+ *len = le32_to_cpu(((struct smb2_query_info_req *)hdr)->InputBufferLength);
+ break;
+ case SMB2_SET_INFO:
+- *off = le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset);
++ *off = max_t(unsigned int,
++ le16_to_cpu(((struct smb2_set_info_req *)hdr)->BufferOffset),
++ offsetof(struct smb2_set_info_req, Buffer));
+ *len = le32_to_cpu(((struct smb2_set_info_req *)hdr)->BufferLength);
+ break;
+ case SMB2_READ:
+@@ -142,7 +150,7 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
+ case SMB2_WRITE:
+ if (((struct smb2_write_req *)hdr)->DataOffset ||
+ ((struct smb2_write_req *)hdr)->Length) {
+- *off = max_t(unsigned int,
++ *off = max_t(unsigned short int,
+ le16_to_cpu(((struct smb2_write_req *)hdr)->DataOffset),
+ offsetof(struct smb2_write_req, Buffer));
+ *len = le32_to_cpu(((struct smb2_write_req *)hdr)->Length);
+@@ -153,7 +161,9 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
+ *len = le16_to_cpu(((struct smb2_write_req *)hdr)->WriteChannelInfoLength);
+ break;
+ case SMB2_QUERY_DIRECTORY:
+- *off = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffset);
++ *off = max_t(unsigned short int,
++ le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameOffset),
++ offsetof(struct smb2_query_directory_req, Buffer));
+ *len = le16_to_cpu(((struct smb2_query_directory_req *)hdr)->FileNameLength);
+ break;
+ case SMB2_LOCK:
+@@ -168,7 +178,9 @@ static int smb2_get_data_area_len(unsigned int *off, unsigned int *len,
+ break;
+ }
+ case SMB2_IOCTL:
+- *off = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset);
++ *off = max_t(unsigned int,
++ le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputOffset),
++ offsetof(struct smb2_ioctl_req, Buffer));
+ *len = le32_to_cpu(((struct smb2_ioctl_req *)hdr)->InputCount);
+ break;
+ default:
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index 0c97d3c860726..88db6e207e0ee 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -1951,7 +1951,7 @@ int smb2_tree_connect(struct ksmbd_work *work)
+
+ WORK_BUFFERS(work, req, rsp);
+
+- treename = smb_strndup_from_utf16(req->Buffer,
++ treename = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->PathOffset),
+ le16_to_cpu(req->PathLength), true,
+ conn->local_nls);
+ if (IS_ERR(treename)) {
+@@ -2704,7 +2704,7 @@ int smb2_open(struct ksmbd_work *work)
+ goto err_out2;
+ }
+
+- name = smb2_get_name(req->Buffer,
++ name = smb2_get_name((char *)req + le16_to_cpu(req->NameOffset),
+ le16_to_cpu(req->NameLength),
+ work->conn->local_nls);
+ if (IS_ERR(name)) {
+@@ -3828,11 +3828,16 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
+ }
+
+ ksmbd_kstat.kstat = &kstat;
+- if (priv->info_level != FILE_NAMES_INFORMATION)
+- ksmbd_vfs_fill_dentry_attrs(priv->work,
+- idmap,
+- dent,
+- &ksmbd_kstat);
++ if (priv->info_level != FILE_NAMES_INFORMATION) {
++ rc = ksmbd_vfs_fill_dentry_attrs(priv->work,
++ idmap,
++ dent,
++ &ksmbd_kstat);
++ if (rc) {
++ dput(dent);
++ continue;
++ }
++ }
+
+ rc = smb2_populate_readdir_entry(priv->work->conn,
+ priv->info_level,
+@@ -4075,7 +4080,7 @@ int smb2_query_dir(struct ksmbd_work *work)
+ }
+
+ srch_flag = req->Flags;
+- srch_ptr = smb_strndup_from_utf16(req->Buffer,
++ srch_ptr = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->FileNameOffset),
+ le16_to_cpu(req->FileNameLength), 1,
+ conn->local_nls);
+ if (IS_ERR(srch_ptr)) {
+@@ -4335,7 +4340,8 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp,
+ sizeof(struct smb2_ea_info_req))
+ return -EINVAL;
+
+- ea_req = (struct smb2_ea_info_req *)req->Buffer;
++ ea_req = (struct smb2_ea_info_req *)((char *)req +
++ le16_to_cpu(req->InputBufferOffset));
+ } else {
+ /* need to send all EAs, if no specific EA is requested*/
+ if (le32_to_cpu(req->Flags) & SL_RETURN_SINGLE_ENTRY)
+@@ -4480,6 +4486,7 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
+ struct smb2_file_basic_info *basic_info;
+ struct kstat stat;
+ u64 time;
++ int ret;
+
+ if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
+ pr_err("no right to read the attributes : 0x%x\n",
+@@ -4487,9 +4494,12 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
+ return -EACCES;
+ }
+
++ ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
++ AT_STATX_SYNC_AS_STAT);
++ if (ret)
++ return ret;
++
+ basic_info = (struct smb2_file_basic_info *)rsp->Buffer;
+- generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS,
+- file_inode(fp->filp), &stat);
+ basic_info->CreationTime = cpu_to_le64(fp->create_time);
+ time = ksmbd_UnixTimeToNT(stat.atime);
+ basic_info->LastAccessTime = cpu_to_le64(time);
+@@ -4504,27 +4514,31 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp,
+ return 0;
+ }
+
+-static void get_file_standard_info(struct smb2_query_info_rsp *rsp,
+- struct ksmbd_file *fp, void *rsp_org)
++static int get_file_standard_info(struct smb2_query_info_rsp *rsp,
++ struct ksmbd_file *fp, void *rsp_org)
+ {
+ struct smb2_file_standard_info *sinfo;
+ unsigned int delete_pending;
+- struct inode *inode;
+ struct kstat stat;
++ int ret;
+
+- inode = file_inode(fp->filp);
+- generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS, inode, &stat);
++ ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
++ AT_STATX_SYNC_AS_STAT);
++ if (ret)
++ return ret;
+
+ sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
+ delete_pending = ksmbd_inode_pending_delete(fp);
+
+- sinfo->AllocationSize = cpu_to_le64(inode->i_blocks << 9);
++ sinfo->AllocationSize = cpu_to_le64(stat.blocks << 9);
+ sinfo->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
+ sinfo->NumberOfLinks = cpu_to_le32(get_nlink(&stat) - delete_pending);
+ sinfo->DeletePending = delete_pending;
+ sinfo->Directory = S_ISDIR(stat.mode) ? 1 : 0;
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_standard_info));
++
++ return 0;
+ }
+
+ static void get_file_alignment_info(struct smb2_query_info_rsp *rsp,
+@@ -4546,11 +4560,11 @@ static int get_file_all_info(struct ksmbd_work *work,
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_file_all_info *file_info;
+ unsigned int delete_pending;
+- struct inode *inode;
+ struct kstat stat;
+ int conv_len;
+ char *filename;
+ u64 time;
++ int ret;
+
+ if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
+ ksmbd_debug(SMB, "no right to read the attributes : 0x%x\n",
+@@ -4562,8 +4576,10 @@ static int get_file_all_info(struct ksmbd_work *work,
+ if (IS_ERR(filename))
+ return PTR_ERR(filename);
+
+- inode = file_inode(fp->filp);
+- generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS, inode, &stat);
++ ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
++ AT_STATX_SYNC_AS_STAT);
++ if (ret)
++ return ret;
+
+ ksmbd_debug(SMB, "filename = %s\n", filename);
+ delete_pending = ksmbd_inode_pending_delete(fp);
+@@ -4579,7 +4595,7 @@ static int get_file_all_info(struct ksmbd_work *work,
+ file_info->Attributes = fp->f_ci->m_fattr;
+ file_info->Pad1 = 0;
+ file_info->AllocationSize =
+- cpu_to_le64(inode->i_blocks << 9);
++ cpu_to_le64(stat.blocks << 9);
+ file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
+ file_info->NumberOfLinks =
+ cpu_to_le32(get_nlink(&stat) - delete_pending);
+@@ -4623,10 +4639,10 @@ static void get_file_alternate_info(struct ksmbd_work *work,
+ cpu_to_le32(sizeof(struct smb2_file_alt_name_info) + conv_len);
+ }
+
+-static void get_file_stream_info(struct ksmbd_work *work,
+- struct smb2_query_info_rsp *rsp,
+- struct ksmbd_file *fp,
+- void *rsp_org)
++static int get_file_stream_info(struct ksmbd_work *work,
++ struct smb2_query_info_rsp *rsp,
++ struct ksmbd_file *fp,
++ void *rsp_org)
+ {
+ struct ksmbd_conn *conn = work->conn;
+ struct smb2_file_stream_info *file_info;
+@@ -4637,9 +4653,13 @@ static void get_file_stream_info(struct ksmbd_work *work,
+ int nbytes = 0, streamlen, stream_name_len, next, idx = 0;
+ int buf_free_len;
+ struct smb2_query_info_req *req = ksmbd_req_buf_next(work);
++ int ret;
++
++ ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
++ AT_STATX_SYNC_AS_STAT);
++ if (ret)
++ return ret;
+
+- generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS,
+- file_inode(fp->filp), &stat);
+ file_info = (struct smb2_file_stream_info *)rsp->Buffer;
+
+ buf_free_len =
+@@ -4720,29 +4740,37 @@ static void get_file_stream_info(struct ksmbd_work *work,
+ kvfree(xattr_list);
+
+ rsp->OutputBufferLength = cpu_to_le32(nbytes);
++
++ return 0;
+ }
+
+-static void get_file_internal_info(struct smb2_query_info_rsp *rsp,
+- struct ksmbd_file *fp, void *rsp_org)
++static int get_file_internal_info(struct smb2_query_info_rsp *rsp,
++ struct ksmbd_file *fp, void *rsp_org)
+ {
+ struct smb2_file_internal_info *file_info;
+ struct kstat stat;
++ int ret;
++
++ ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
++ AT_STATX_SYNC_AS_STAT);
++ if (ret)
++ return ret;
+
+- generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS,
+- file_inode(fp->filp), &stat);
+ file_info = (struct smb2_file_internal_info *)rsp->Buffer;
+ file_info->IndexNumber = cpu_to_le64(stat.ino);
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_internal_info));
++
++ return 0;
+ }
+
+ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp, void *rsp_org)
+ {
+ struct smb2_file_ntwrk_info *file_info;
+- struct inode *inode;
+ struct kstat stat;
+ u64 time;
++ int ret;
+
+ if (!(fp->daccess & FILE_READ_ATTRIBUTES_LE)) {
+ pr_err("no right to read the attributes : 0x%x\n",
+@@ -4750,10 +4778,12 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
+ return -EACCES;
+ }
+
+- file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer;
++ ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
++ AT_STATX_SYNC_AS_STAT);
++ if (ret)
++ return ret;
+
+- inode = file_inode(fp->filp);
+- generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS, inode, &stat);
++ file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer;
+
+ file_info->CreationTime = cpu_to_le64(fp->create_time);
+ time = ksmbd_UnixTimeToNT(stat.atime);
+@@ -4763,8 +4793,7 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
+ time = ksmbd_UnixTimeToNT(stat.ctime);
+ file_info->ChangeTime = cpu_to_le64(time);
+ file_info->Attributes = fp->f_ci->m_fattr;
+- file_info->AllocationSize =
+- cpu_to_le64(inode->i_blocks << 9);
++ file_info->AllocationSize = cpu_to_le64(stat.blocks << 9);
+ file_info->EndOfFile = S_ISDIR(stat.mode) ? 0 : cpu_to_le64(stat.size);
+ file_info->Reserved = cpu_to_le32(0);
+ rsp->OutputBufferLength =
+@@ -4804,14 +4833,17 @@ static void get_file_mode_info(struct smb2_query_info_rsp *rsp,
+ cpu_to_le32(sizeof(struct smb2_file_mode_info));
+ }
+
+-static void get_file_compression_info(struct smb2_query_info_rsp *rsp,
+- struct ksmbd_file *fp, void *rsp_org)
++static int get_file_compression_info(struct smb2_query_info_rsp *rsp,
++ struct ksmbd_file *fp, void *rsp_org)
+ {
+ struct smb2_file_comp_info *file_info;
+ struct kstat stat;
++ int ret;
+
+- generic_fillattr(file_mnt_idmap(fp->filp), STATX_BASIC_STATS,
+- file_inode(fp->filp), &stat);
++ ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
++ AT_STATX_SYNC_AS_STAT);
++ if (ret)
++ return ret;
+
+ file_info = (struct smb2_file_comp_info *)rsp->Buffer;
+ file_info->CompressedFileSize = cpu_to_le64(stat.blocks << 9);
+@@ -4823,6 +4855,8 @@ static void get_file_compression_info(struct smb2_query_info_rsp *rsp,
+
+ rsp->OutputBufferLength =
+ cpu_to_le32(sizeof(struct smb2_file_comp_info));
++
++ return 0;
+ }
+
+ static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp,
+@@ -4844,7 +4878,7 @@ static int get_file_attribute_tag_info(struct smb2_query_info_rsp *rsp,
+ return 0;
+ }
+
+-static void find_file_posix_info(struct smb2_query_info_rsp *rsp,
++static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
+ struct ksmbd_file *fp, void *rsp_org)
+ {
+ struct smb311_posix_qinfo *file_info;
+@@ -4852,24 +4886,31 @@ static void find_file_posix_info(struct smb2_query_info_rsp *rsp,
+ struct mnt_idmap *idmap = file_mnt_idmap(fp->filp);
+ vfsuid_t vfsuid = i_uid_into_vfsuid(idmap, inode);
+ vfsgid_t vfsgid = i_gid_into_vfsgid(idmap, inode);
++ struct kstat stat;
+ u64 time;
+ int out_buf_len = sizeof(struct smb311_posix_qinfo) + 32;
++ int ret;
++
++ ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
++ AT_STATX_SYNC_AS_STAT);
++ if (ret)
++ return ret;
+
+ file_info = (struct smb311_posix_qinfo *)rsp->Buffer;
+ file_info->CreationTime = cpu_to_le64(fp->create_time);
+- time = ksmbd_UnixTimeToNT(inode_get_atime(inode));
++ time = ksmbd_UnixTimeToNT(stat.atime);
+ file_info->LastAccessTime = cpu_to_le64(time);
+- time = ksmbd_UnixTimeToNT(inode_get_mtime(inode));
++ time = ksmbd_UnixTimeToNT(stat.mtime);
+ file_info->LastWriteTime = cpu_to_le64(time);
+- time = ksmbd_UnixTimeToNT(inode_get_ctime(inode));
++ time = ksmbd_UnixTimeToNT(stat.ctime);
+ file_info->ChangeTime = cpu_to_le64(time);
+ file_info->DosAttributes = fp->f_ci->m_fattr;
+- file_info->Inode = cpu_to_le64(inode->i_ino);
+- file_info->EndOfFile = cpu_to_le64(inode->i_size);
+- file_info->AllocationSize = cpu_to_le64(inode->i_blocks << 9);
+- file_info->HardLinks = cpu_to_le32(inode->i_nlink);
+- file_info->Mode = cpu_to_le32(inode->i_mode & 0777);
+- file_info->DeviceId = cpu_to_le32(inode->i_rdev);
++ file_info->Inode = cpu_to_le64(stat.ino);
++ file_info->EndOfFile = cpu_to_le64(stat.size);
++ file_info->AllocationSize = cpu_to_le64(stat.blocks << 9);
++ file_info->HardLinks = cpu_to_le32(stat.nlink);
++ file_info->Mode = cpu_to_le32(stat.mode & 0777);
++ file_info->DeviceId = cpu_to_le32(stat.rdev);
+
+ /*
+ * Sids(32) contain two sids(Domain sid(16), UNIX group sid(16)).
+@@ -4882,6 +4923,8 @@ static void find_file_posix_info(struct smb2_query_info_rsp *rsp,
+ SIDUNIX_GROUP, (struct smb_sid *)&file_info->Sids[16]);
+
+ rsp->OutputBufferLength = cpu_to_le32(out_buf_len);
++
++ return 0;
+ }
+
+ static int smb2_get_info_file(struct ksmbd_work *work,
+@@ -4930,7 +4973,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
+ break;
+
+ case FILE_STANDARD_INFORMATION:
+- get_file_standard_info(rsp, fp, work->response_buf);
++ rc = get_file_standard_info(rsp, fp, work->response_buf);
+ break;
+
+ case FILE_ALIGNMENT_INFORMATION:
+@@ -4946,11 +4989,11 @@ static int smb2_get_info_file(struct ksmbd_work *work,
+ break;
+
+ case FILE_STREAM_INFORMATION:
+- get_file_stream_info(work, rsp, fp, work->response_buf);
++ rc = get_file_stream_info(work, rsp, fp, work->response_buf);
+ break;
+
+ case FILE_INTERNAL_INFORMATION:
+- get_file_internal_info(rsp, fp, work->response_buf);
++ rc = get_file_internal_info(rsp, fp, work->response_buf);
+ break;
+
+ case FILE_NETWORK_OPEN_INFORMATION:
+@@ -4974,7 +5017,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
+ break;
+
+ case FILE_COMPRESSION_INFORMATION:
+- get_file_compression_info(rsp, fp, work->response_buf);
++ rc = get_file_compression_info(rsp, fp, work->response_buf);
+ break;
+
+ case FILE_ATTRIBUTE_TAG_INFORMATION:
+@@ -4985,7 +5028,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
+ pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
+ rc = -EOPNOTSUPP;
+ } else {
+- find_file_posix_info(rsp, fp, work->response_buf);
++ rc = find_file_posix_info(rsp, fp, work->response_buf);
+ }
+ break;
+ default:
+@@ -5398,7 +5441,6 @@ int smb2_close(struct ksmbd_work *work)
+ struct smb2_close_rsp *rsp;
+ struct ksmbd_conn *conn = work->conn;
+ struct ksmbd_file *fp;
+- struct inode *inode;
+ u64 time;
+ int err = 0;
+
+@@ -5453,24 +5495,33 @@ int smb2_close(struct ksmbd_work *work)
+ rsp->Reserved = 0;
+
+ if (req->Flags == SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB) {
++ struct kstat stat;
++ int ret;
++
+ fp = ksmbd_lookup_fd_fast(work, volatile_id);
+ if (!fp) {
+ err = -ENOENT;
+ goto out;
+ }
+
+- inode = file_inode(fp->filp);
++ ret = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
++ AT_STATX_SYNC_AS_STAT);
++ if (ret) {
++ ksmbd_fd_put(work, fp);
++ goto out;
++ }
++
+ rsp->Flags = SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB;
+- rsp->AllocationSize = S_ISDIR(inode->i_mode) ? 0 :
+- cpu_to_le64(inode->i_blocks << 9);
+- rsp->EndOfFile = cpu_to_le64(inode->i_size);
++ rsp->AllocationSize = S_ISDIR(stat.mode) ? 0 :
++ cpu_to_le64(stat.blocks << 9);
++ rsp->EndOfFile = cpu_to_le64(stat.size);
+ rsp->Attributes = fp->f_ci->m_fattr;
+ rsp->CreationTime = cpu_to_le64(fp->create_time);
+- time = ksmbd_UnixTimeToNT(inode_get_atime(inode));
++ time = ksmbd_UnixTimeToNT(stat.atime);
+ rsp->LastAccessTime = cpu_to_le64(time);
+- time = ksmbd_UnixTimeToNT(inode_get_mtime(inode));
++ time = ksmbd_UnixTimeToNT(stat.mtime);
+ rsp->LastWriteTime = cpu_to_le64(time);
+- time = ksmbd_UnixTimeToNT(inode_get_ctime(inode));
++ time = ksmbd_UnixTimeToNT(stat.ctime);
+ rsp->ChangeTime = cpu_to_le64(time);
+ ksmbd_fd_put(work, fp);
+ } else {
+@@ -5759,15 +5810,21 @@ static int set_file_allocation_info(struct ksmbd_work *work,
+
+ loff_t alloc_blks;
+ struct inode *inode;
++ struct kstat stat;
+ int rc;
+
+ if (!(fp->daccess & FILE_WRITE_DATA_LE))
+ return -EACCES;
+
++ rc = vfs_getattr(&fp->filp->f_path, &stat, STATX_BASIC_STATS,
++ AT_STATX_SYNC_AS_STAT);
++ if (rc)
++ return rc;
++
+ alloc_blks = (le64_to_cpu(file_alloc_info->AllocationSize) + 511) >> 9;
+ inode = file_inode(fp->filp);
+
+- if (alloc_blks > inode->i_blocks) {
++ if (alloc_blks > stat.blocks) {
+ smb_break_all_levII_oplock(work, fp, 1);
+ rc = vfs_fallocate(fp->filp, FALLOC_FL_KEEP_SIZE, 0,
+ alloc_blks * 512);
+@@ -5775,7 +5832,7 @@ static int set_file_allocation_info(struct ksmbd_work *work,
+ pr_err("vfs_fallocate is failed : %d\n", rc);
+ return rc;
+ }
+- } else if (alloc_blks < inode->i_blocks) {
++ } else if (alloc_blks < stat.blocks) {
+ loff_t size;
+
+ /*
+@@ -5930,6 +5987,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+ struct ksmbd_share_config *share)
+ {
+ unsigned int buf_len = le32_to_cpu(req->BufferLength);
++ char *buffer = (char *)req + le16_to_cpu(req->BufferOffset);
+
+ switch (req->FileInfoClass) {
+ case FILE_BASIC_INFORMATION:
+@@ -5937,7 +5995,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+ if (buf_len < sizeof(struct smb2_file_basic_info))
+ return -EINVAL;
+
+- return set_file_basic_info(fp, (struct smb2_file_basic_info *)req->Buffer, share);
++ return set_file_basic_info(fp, (struct smb2_file_basic_info *)buffer, share);
+ }
+ case FILE_ALLOCATION_INFORMATION:
+ {
+@@ -5945,7 +6003,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+ return -EINVAL;
+
+ return set_file_allocation_info(work, fp,
+- (struct smb2_file_alloc_info *)req->Buffer);
++ (struct smb2_file_alloc_info *)buffer);
+ }
+ case FILE_END_OF_FILE_INFORMATION:
+ {
+@@ -5953,7 +6011,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+ return -EINVAL;
+
+ return set_end_of_file_info(work, fp,
+- (struct smb2_file_eof_info *)req->Buffer);
++ (struct smb2_file_eof_info *)buffer);
+ }
+ case FILE_RENAME_INFORMATION:
+ {
+@@ -5961,7 +6019,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+ return -EINVAL;
+
+ return set_rename_info(work, fp,
+- (struct smb2_file_rename_info *)req->Buffer,
++ (struct smb2_file_rename_info *)buffer,
+ buf_len);
+ }
+ case FILE_LINK_INFORMATION:
+@@ -5970,7 +6028,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+ return -EINVAL;
+
+ return smb2_create_link(work, work->tcon->share_conf,
+- (struct smb2_file_link_info *)req->Buffer,
++ (struct smb2_file_link_info *)buffer,
+ buf_len, fp->filp,
+ work->conn->local_nls);
+ }
+@@ -5980,7 +6038,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+ return -EINVAL;
+
+ return set_file_disposition_info(fp,
+- (struct smb2_file_disposition_info *)req->Buffer);
++ (struct smb2_file_disposition_info *)buffer);
+ }
+ case FILE_FULL_EA_INFORMATION:
+ {
+@@ -5993,7 +6051,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+ if (buf_len < sizeof(struct smb2_ea_info))
+ return -EINVAL;
+
+- return smb2_set_ea((struct smb2_ea_info *)req->Buffer,
++ return smb2_set_ea((struct smb2_ea_info *)buffer,
+ buf_len, &fp->filp->f_path, true);
+ }
+ case FILE_POSITION_INFORMATION:
+@@ -6001,14 +6059,14 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
+ if (buf_len < sizeof(struct smb2_file_pos_info))
+ return -EINVAL;
+
+- return set_file_position_info(fp, (struct smb2_file_pos_info *)req->Buffer);
++ return set_file_position_info(fp, (struct smb2_file_pos_info *)buffer);
+ }
+ case FILE_MODE_INFORMATION:
+ {
+ if (buf_len < sizeof(struct smb2_file_mode_info))
+ return -EINVAL;
+
+- return set_file_mode_info(fp, (struct smb2_file_mode_info *)req->Buffer);
++ return set_file_mode_info(fp, (struct smb2_file_mode_info *)buffer);
+ }
+ }
+
+@@ -6089,7 +6147,7 @@ int smb2_set_info(struct ksmbd_work *work)
+ }
+ rc = smb2_set_info_sec(fp,
+ le32_to_cpu(req->AdditionalInformation),
+- req->Buffer,
++ (char *)req + le16_to_cpu(req->BufferOffset),
+ le32_to_cpu(req->BufferLength));
+ ksmbd_revert_fsids(work);
+ break;
+@@ -7535,7 +7593,7 @@ static int fsctl_pipe_transceive(struct ksmbd_work *work, u64 id,
+ struct smb2_ioctl_rsp *rsp)
+ {
+ struct ksmbd_rpc_command *rpc_resp;
+- char *data_buf = (char *)&req->Buffer[0];
++ char *data_buf = (char *)req + le32_to_cpu(req->InputOffset);
+ int nbytes = 0;
+
+ rpc_resp = ksmbd_rpc_ioctl(work->sess, id, data_buf,
+@@ -7648,6 +7706,7 @@ int smb2_ioctl(struct ksmbd_work *work)
+ u64 id = KSMBD_NO_FID;
+ struct ksmbd_conn *conn = work->conn;
+ int ret = 0;
++ char *buffer;
+
+ if (work->next_smb2_rcv_hdr_off) {
+ req = ksmbd_req_buf_next(work);
+@@ -7670,6 +7729,8 @@ int smb2_ioctl(struct ksmbd_work *work)
+ goto out;
+ }
+
++ buffer = (char *)req + le32_to_cpu(req->InputOffset);
++
+ cnt_code = le32_to_cpu(req->CtlCode);
+ ret = smb2_calc_max_out_buf_len(work, 48,
+ le32_to_cpu(req->MaxOutputResponse));
+@@ -7727,7 +7788,7 @@ int smb2_ioctl(struct ksmbd_work *work)
+ }
+
+ ret = fsctl_validate_negotiate_info(conn,
+- (struct validate_negotiate_info_req *)&req->Buffer[0],
++ (struct validate_negotiate_info_req *)buffer,
+ (struct validate_negotiate_info_rsp *)&rsp->Buffer[0],
+ in_buf_len);
+ if (ret < 0)
+@@ -7780,7 +7841,7 @@ int smb2_ioctl(struct ksmbd_work *work)
+ rsp->VolatileFileId = req->VolatileFileId;
+ rsp->PersistentFileId = req->PersistentFileId;
+ fsctl_copychunk(work,
+- (struct copychunk_ioctl_req *)&req->Buffer[0],
++ (struct copychunk_ioctl_req *)buffer,
+ le32_to_cpu(req->CtlCode),
+ le32_to_cpu(req->InputCount),
+ req->VolatileFileId,
+@@ -7793,8 +7854,7 @@ int smb2_ioctl(struct ksmbd_work *work)
+ goto out;
+ }
+
+- ret = fsctl_set_sparse(work, id,
+- (struct file_sparse *)&req->Buffer[0]);
++ ret = fsctl_set_sparse(work, id, (struct file_sparse *)buffer);
+ if (ret < 0)
+ goto out;
+ break;
+@@ -7817,7 +7877,7 @@ int smb2_ioctl(struct ksmbd_work *work)
+ }
+
+ zero_data =
+- (struct file_zero_data_information *)&req->Buffer[0];
++ (struct file_zero_data_information *)buffer;
+
+ off = le64_to_cpu(zero_data->FileOffset);
+ bfz = le64_to_cpu(zero_data->BeyondFinalZero);
+@@ -7848,7 +7908,7 @@ int smb2_ioctl(struct ksmbd_work *work)
+ }
+
+ ret = fsctl_query_allocated_ranges(work, id,
+- (struct file_allocated_range_buffer *)&req->Buffer[0],
++ (struct file_allocated_range_buffer *)buffer,
+ (struct file_allocated_range_buffer *)&rsp->Buffer[0],
+ out_buf_len /
+ sizeof(struct file_allocated_range_buffer), &nbytes);
+@@ -7892,7 +7952,7 @@ int smb2_ioctl(struct ksmbd_work *work)
+ goto out;
+ }
+
+- dup_ext = (struct duplicate_extents_to_file *)&req->Buffer[0];
++ dup_ext = (struct duplicate_extents_to_file *)buffer;
+
+ fp_in = ksmbd_lookup_fd_slow(work, dup_ext->VolatileFileHandle,
+ dup_ext->PersistentFileHandle);
+diff --git a/fs/smb/server/smb_common.c b/fs/smb/server/smb_common.c
+index 7c98bf699772f..fcaf373cc0080 100644
+--- a/fs/smb/server/smb_common.c
++++ b/fs/smb/server/smb_common.c
+@@ -457,10 +457,13 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
+ }
+
+ ksmbd_kstat.kstat = &kstat;
+- ksmbd_vfs_fill_dentry_attrs(work,
+- idmap,
+- dentry,
+- &ksmbd_kstat);
++ rc = ksmbd_vfs_fill_dentry_attrs(work,
++ idmap,
++ dentry,
++ &ksmbd_kstat);
++ if (rc)
++ break;
++
+ rc = fn(conn, info_level, d_info, &ksmbd_kstat);
+ if (rc)
+ break;
+diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c
+index a6961bfe3e139..2e992fadeaa7d 100644
+--- a/fs/smb/server/vfs.c
++++ b/fs/smb/server/vfs.c
+@@ -1682,11 +1682,19 @@ int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
+ struct dentry *dentry,
+ struct ksmbd_kstat *ksmbd_kstat)
+ {
++ struct ksmbd_share_config *share_conf = work->tcon->share_conf;
+ u64 time;
+ int rc;
++ struct path path = {
++ .mnt = share_conf->vfs_path.mnt,
++ .dentry = dentry,
++ };
+
+- generic_fillattr(idmap, STATX_BASIC_STATS, d_inode(dentry),
+- ksmbd_kstat->kstat);
++ rc = vfs_getattr(&path, ksmbd_kstat->kstat,
++ STATX_BASIC_STATS | STATX_BTIME,
++ AT_STATX_SYNC_AS_STAT);
++ if (rc)
++ return rc;
+
+ time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime);
+ ksmbd_kstat->create_time = time;
+diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
+index e413a9cf8ee38..6b3db00d9b121 100644
+--- a/fs/ubifs/dir.c
++++ b/fs/ubifs/dir.c
+@@ -1134,6 +1134,8 @@ static int ubifs_mknod(struct mnt_idmap *idmap, struct inode *dir,
+ dir_ui->ui_size = dir->i_size;
+ mutex_unlock(&dir_ui->ui_mutex);
+ out_inode:
++ /* Free inode->i_link before inode is marked as bad. */
++ fscrypt_free_inode(inode);
+ make_bad_inode(inode);
+ iput(inode);
+ out_fname:
+diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
+index 5029eb3390a56..d0694b83dd02c 100644
+--- a/fs/ubifs/file.c
++++ b/fs/ubifs/file.c
+@@ -261,9 +261,6 @@ static int write_begin_slow(struct address_space *mapping,
+ return err;
+ }
+ }
+-
+- SetPageUptodate(page);
+- ClearPageError(page);
+ }
+
+ if (PagePrivate(page))
+@@ -463,9 +460,6 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
+ return err;
+ }
+ }
+-
+- SetPageUptodate(page);
+- ClearPageError(page);
+ }
+
+ err = allocate_budget(c, page, ui, appending);
+@@ -475,10 +469,8 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping,
+ * If we skipped reading the page because we were going to
+ * write all of it, then it is not up to date.
+ */
+- if (skipped_read) {
++ if (skipped_read)
+ ClearPageChecked(page);
+- ClearPageUptodate(page);
+- }
+ /*
+ * Budgeting failed which means it would have to force
+ * write-back but didn't, because we set the @fast flag in the
+@@ -569,6 +561,9 @@ static int ubifs_write_end(struct file *file, struct address_space *mapping,
+ goto out;
+ }
+
++ if (len == PAGE_SIZE)
++ SetPageUptodate(page);
++
+ if (!PagePrivate(page)) {
+ attach_page_private(page, (void *)1);
+ atomic_long_inc(&c->dirty_pg_cnt);
+diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
+index e39da5807ba71..b7aed3ead705b 100644
+--- a/include/drm/drm_bridge.h
++++ b/include/drm/drm_bridge.h
+@@ -557,6 +557,37 @@ struct drm_bridge_funcs {
+ int (*get_modes)(struct drm_bridge *bridge,
+ struct drm_connector *connector);
+
++ /**
++ * @edid_read:
++ *
++ * Read the EDID data of the connected display.
++ *
++ * The @edid_read callback is the preferred way of reporting mode
++ * information for a display connected to the bridge output. Bridges
++ * that support reading EDID shall implement this callback and leave
++ * the @get_modes callback unimplemented.
++ *
++ * The caller of this operation shall first verify the output
++ * connection status and refrain from reading EDID from a disconnected
++ * output.
++ *
++ * This callback is optional. Bridges that implement it shall set the
++ * DRM_BRIDGE_OP_EDID flag in their &drm_bridge->ops.
++ *
++ * The connector parameter shall be used for the sole purpose of EDID
++ * retrieval, and shall not be stored internally by bridge drivers for
++ * future usage.
++ *
++ * RETURNS:
++ *
++ * An edid structure newly allocated with drm_edid_alloc() or returned
++ * from drm_edid_read() family of functions on success, or NULL
++ * otherwise. The caller is responsible for freeing the returned edid
++ * structure with drm_edid_free().
++ */
++ const struct drm_edid *(*edid_read)(struct drm_bridge *bridge,
++ struct drm_connector *connector);
++
+ /**
+ * @get_edid:
+ *
+@@ -888,6 +919,8 @@ drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge,
+ enum drm_connector_status drm_bridge_detect(struct drm_bridge *bridge);
+ int drm_bridge_get_modes(struct drm_bridge *bridge,
+ struct drm_connector *connector);
++const struct drm_edid *drm_bridge_edid_read(struct drm_bridge *bridge,
++ struct drm_connector *connector);
+ struct edid *drm_bridge_get_edid(struct drm_bridge *bridge,
+ struct drm_connector *connector);
+ void drm_bridge_hpd_enable(struct drm_bridge *bridge,
+diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h
+index 881b03e4dc288..9ed42469540eb 100644
+--- a/include/drm/drm_modeset_helper_vtables.h
++++ b/include/drm/drm_modeset_helper_vtables.h
+@@ -898,7 +898,8 @@ struct drm_connector_helper_funcs {
+ *
+ * RETURNS:
+ *
+- * The number of modes added by calling drm_mode_probed_add().
++ * The number of modes added by calling drm_mode_probed_add(). Return 0
++ * on failures (no modes) instead of negative error codes.
+ */
+ int (*get_modes)(struct drm_connector *connector);
+
+diff --git a/include/drm/ttm/ttm_tt.h b/include/drm/ttm/ttm_tt.h
+index a4eff85b1f449..2b9d856ff388d 100644
+--- a/include/drm/ttm/ttm_tt.h
++++ b/include/drm/ttm/ttm_tt.h
+@@ -79,6 +79,12 @@ struct ttm_tt {
+ * page_flags = TTM_TT_FLAG_EXTERNAL |
+ * TTM_TT_FLAG_EXTERNAL_MAPPABLE;
+ *
++ * TTM_TT_FLAG_DECRYPTED: The mapped ttm pages should be marked as
++ * not encrypted. The framework will try to match what the dma layer
++ * is doing, but note that it is a little fragile because ttm page
++ * fault handling abuses the DMA api a bit and dma_map_attrs can't be
++ * used to assure pgprot always matches.
++ *
+ * TTM_TT_FLAG_PRIV_POPULATED: TTM internal only. DO NOT USE. This is
+ * set by TTM after ttm_tt_populate() has successfully returned, and is
+ * then unset when TTM calls ttm_tt_unpopulate().
+@@ -87,8 +93,9 @@ struct ttm_tt {
+ #define TTM_TT_FLAG_ZERO_ALLOC BIT(1)
+ #define TTM_TT_FLAG_EXTERNAL BIT(2)
+ #define TTM_TT_FLAG_EXTERNAL_MAPPABLE BIT(3)
++#define TTM_TT_FLAG_DECRYPTED BIT(4)
+
+-#define TTM_TT_FLAG_PRIV_POPULATED BIT(4)
++#define TTM_TT_FLAG_PRIV_POPULATED BIT(5)
+ uint32_t page_flags;
+ /** @num_pages: Number of pages in the page array. */
+ uint32_t num_pages;
+diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
+index afda5f24d3ddc..320fab7d2e940 100644
+--- a/include/linux/cpufreq.h
++++ b/include/linux/cpufreq.h
+@@ -1021,6 +1021,18 @@ static inline int cpufreq_table_find_index_c(struct cpufreq_policy *policy,
+ efficiencies);
+ }
+
++static inline bool cpufreq_is_in_limits(struct cpufreq_policy *policy, int idx)
++{
++ unsigned int freq;
++
++ if (idx < 0)
++ return false;
++
++ freq = policy->freq_table[idx].frequency;
++
++ return freq == clamp_val(freq, policy->min, policy->max);
++}
++
+ static inline int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+@@ -1054,7 +1066,8 @@ static inline int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
+ return 0;
+ }
+
+- if (idx < 0 && efficiencies) {
++ /* Limit frequency index to honor policy->min/max */
++ if (!cpufreq_is_in_limits(policy, idx) && efficiencies) {
+ efficiencies = false;
+ goto retry;
+ }
+diff --git a/include/linux/framer/framer.h b/include/linux/framer/framer.h
+index 9a9b88962c296..2b85fe9e7f9a7 100644
+--- a/include/linux/framer/framer.h
++++ b/include/linux/framer/framer.h
+@@ -181,12 +181,12 @@ static inline int framer_notifier_unregister(struct framer *framer,
+ return -ENOSYS;
+ }
+
+-struct framer *framer_get(struct device *dev, const char *con_id)
++static inline struct framer *framer_get(struct device *dev, const char *con_id)
+ {
+ return ERR_PTR(-ENOSYS);
+ }
+
+-void framer_put(struct device *dev, struct framer *framer)
++static inline void framer_put(struct device *dev, struct framer *framer)
+ {
+ }
+
+diff --git a/include/linux/intel_rapl.h b/include/linux/intel_rapl.h
+index 33f21bd85dbf2..f3196f82fd8a1 100644
+--- a/include/linux/intel_rapl.h
++++ b/include/linux/intel_rapl.h
+@@ -178,6 +178,12 @@ struct rapl_package {
+ struct rapl_if_priv *priv;
+ };
+
++struct rapl_package *rapl_find_package_domain_cpuslocked(int id, struct rapl_if_priv *priv,
++ bool id_is_cpu);
++struct rapl_package *rapl_add_package_cpuslocked(int id, struct rapl_if_priv *priv,
++ bool id_is_cpu);
++void rapl_remove_package_cpuslocked(struct rapl_package *rp);
++
+ struct rapl_package *rapl_find_package_domain(int id, struct rapl_if_priv *priv, bool id_is_cpu);
+ struct rapl_package *rapl_add_package(int id, struct rapl_if_priv *priv, bool id_is_cpu);
+ void rapl_remove_package(struct rapl_package *rp);
+diff --git a/include/linux/intel_tcc.h b/include/linux/intel_tcc.h
+index f422612c28d6b..8ff8eabb4a987 100644
+--- a/include/linux/intel_tcc.h
++++ b/include/linux/intel_tcc.h
+@@ -13,6 +13,6 @@
+ int intel_tcc_get_tjmax(int cpu);
+ int intel_tcc_get_offset(int cpu);
+ int intel_tcc_set_offset(int cpu, int offset);
+-int intel_tcc_get_temp(int cpu, bool pkg);
++int intel_tcc_get_temp(int cpu, int *temp, bool pkg);
+
+ #endif /* __INTEL_TCC_H__ */
+diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
+index 76121c2bb4f82..5c9bdd3ffccc8 100644
+--- a/include/linux/interrupt.h
++++ b/include/linux/interrupt.h
+@@ -67,6 +67,8 @@
+ * later.
+ * IRQF_NO_DEBUG - Exclude from runnaway detection for IPI and similar handlers,
+ * depends on IRQF_PERCPU.
++ * IRQF_COND_ONESHOT - Agree to do IRQF_ONESHOT if already set for a shared
++ * interrupt.
+ */
+ #define IRQF_SHARED 0x00000080
+ #define IRQF_PROBE_SHARED 0x00000100
+@@ -82,6 +84,7 @@
+ #define IRQF_COND_SUSPEND 0x00040000
+ #define IRQF_NO_AUTOEN 0x00080000
+ #define IRQF_NO_DEBUG 0x00100000
++#define IRQF_COND_ONESHOT 0x00200000
+
+ #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD)
+
+diff --git a/include/linux/libata.h b/include/linux/libata.h
+index 26d68115afb82..324d792e7c786 100644
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -107,6 +107,7 @@ enum {
+
+ ATA_DFLAG_NCQ_PRIO_ENABLED = (1 << 20), /* Priority cmds sent to dev */
+ ATA_DFLAG_CDL_ENABLED = (1 << 21), /* cmd duration limits is enabled */
++ ATA_DFLAG_RESUMING = (1 << 22), /* Device is resuming */
+ ATA_DFLAG_DETACH = (1 << 24),
+ ATA_DFLAG_DETACHED = (1 << 25),
+ ATA_DFLAG_DA = (1 << 26), /* device supports Device Attention */
+diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
+index 76458b6d53da7..f9b5baf1b5f46 100644
+--- a/include/linux/lsm_hook_defs.h
++++ b/include/linux/lsm_hook_defs.h
+@@ -265,9 +265,9 @@ LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb)
+ LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry,
+ struct inode *inode)
+ LSM_HOOK(int, -EOPNOTSUPP, getselfattr, unsigned int attr,
+- struct lsm_ctx __user *ctx, size_t *size, u32 flags)
++ struct lsm_ctx __user *ctx, u32 *size, u32 flags)
+ LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr,
+- struct lsm_ctx *ctx, size_t size, u32 flags)
++ struct lsm_ctx *ctx, u32 size, u32 flags)
+ LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name,
+ char **value)
+ LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size)
+diff --git a/include/linux/mman.h b/include/linux/mman.h
+index dc7048824be81..bcb201ab7a412 100644
+--- a/include/linux/mman.h
++++ b/include/linux/mman.h
+@@ -162,6 +162,14 @@ calc_vm_flag_bits(unsigned long flags)
+
+ unsigned long vm_commit_limit(void);
+
++#ifndef arch_memory_deny_write_exec_supported
++static inline bool arch_memory_deny_write_exec_supported(void)
++{
++ return true;
++}
++#define arch_memory_deny_write_exec_supported arch_memory_deny_write_exec_supported
++#endif
++
+ /*
+ * Denies creating a writable executable mapping or gaining executable permissions.
+ *
+diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
+index badb4c1ac079e..5c19ead604996 100644
+--- a/include/linux/mtd/spinand.h
++++ b/include/linux/mtd/spinand.h
+@@ -169,7 +169,7 @@
+ struct spinand_op;
+ struct spinand_device;
+
+-#define SPINAND_MAX_ID_LEN 4
++#define SPINAND_MAX_ID_LEN 5
+ /*
+ * For erase, write and read operation, we got the following timings :
+ * tBERS (erase) 1ms to 4ms
+diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
+index f5ce7b1011461..d59116ac82099 100644
+--- a/include/linux/nfs_fs.h
++++ b/include/linux/nfs_fs.h
+@@ -611,6 +611,7 @@ int nfs_wb_folio_cancel(struct inode *inode, struct folio *folio);
+ extern int nfs_commit_inode(struct inode *, int);
+ extern struct nfs_commit_data *nfs_commitdata_alloc(void);
+ extern void nfs_commit_free(struct nfs_commit_data *data);
++void nfs_commit_begin(struct nfs_mds_commit_info *cinfo);
+ bool nfs_commit_end(struct nfs_mds_commit_info *cinfo);
+
+ static inline bool nfs_have_writebacks(const struct inode *inode)
+diff --git a/include/linux/oid_registry.h b/include/linux/oid_registry.h
+index 3921fbed0b286..51421fdbb0bad 100644
+--- a/include/linux/oid_registry.h
++++ b/include/linux/oid_registry.h
+@@ -17,10 +17,12 @@
+ * build_OID_registry.pl to generate the data for look_up_OID().
+ */
+ enum OID {
++ OID_id_dsa_with_sha1, /* 1.2.840.10030.4.3 */
+ OID_id_dsa, /* 1.2.840.10040.4.1 */
+ OID_id_ecPublicKey, /* 1.2.840.10045.2.1 */
+ OID_id_prime192v1, /* 1.2.840.10045.3.1.1 */
+ OID_id_prime256v1, /* 1.2.840.10045.3.1.7 */
++ OID_id_ecdsa_with_sha1, /* 1.2.840.10045.4.1 */
+ OID_id_ecdsa_with_sha224, /* 1.2.840.10045.4.3.1 */
+ OID_id_ecdsa_with_sha256, /* 1.2.840.10045.4.3.2 */
+ OID_id_ecdsa_with_sha384, /* 1.2.840.10045.4.3.3 */
+@@ -28,6 +30,7 @@ enum OID {
+
+ /* PKCS#1 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-1(1)} */
+ OID_rsaEncryption, /* 1.2.840.113549.1.1.1 */
++ OID_sha1WithRSAEncryption, /* 1.2.840.113549.1.1.5 */
+ OID_sha256WithRSAEncryption, /* 1.2.840.113549.1.1.11 */
+ OID_sha384WithRSAEncryption, /* 1.2.840.113549.1.1.12 */
+ OID_sha512WithRSAEncryption, /* 1.2.840.113549.1.1.13 */
+@@ -64,6 +67,7 @@ enum OID {
+ OID_PKU2U, /* 1.3.5.1.5.2.7 */
+ OID_Scram, /* 1.3.6.1.5.5.14 */
+ OID_certAuthInfoAccess, /* 1.3.6.1.5.5.7.1.1 */
++ OID_sha1, /* 1.3.14.3.2.26 */
+ OID_id_ansip384r1, /* 1.3.132.0.34 */
+ OID_sha256, /* 2.16.840.1.101.3.4.2.1 */
+ OID_sha384, /* 2.16.840.1.101.3.4.2.2 */
+diff --git a/include/linux/phy/tegra/xusb.h b/include/linux/phy/tegra/xusb.h
+index 70998e6dd6fdc..6ca51e0080ec0 100644
+--- a/include/linux/phy/tegra/xusb.h
++++ b/include/linux/phy/tegra/xusb.h
+@@ -26,6 +26,7 @@ void tegra_phy_xusb_utmi_pad_power_down(struct phy *phy);
+ int tegra_phy_xusb_utmi_port_reset(struct phy *phy);
+ int tegra_xusb_padctl_get_usb3_companion(struct tegra_xusb_padctl *padctl,
+ unsigned int port);
++int tegra_xusb_padctl_get_port_number(struct phy *phy);
+ int tegra_xusb_padctl_enable_phy_sleepwalk(struct tegra_xusb_padctl *padctl, struct phy *phy,
+ enum usb_device_speed speed);
+ int tegra_xusb_padctl_disable_phy_sleepwalk(struct tegra_xusb_padctl *padctl, struct phy *phy);
+diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h
+index fa802db216f94..dc5ae4e96aee0 100644
+--- a/include/linux/ring_buffer.h
++++ b/include/linux/ring_buffer.h
+@@ -98,7 +98,9 @@ __ring_buffer_alloc(unsigned long size, unsigned flags, struct lock_class_key *k
+ __ring_buffer_alloc((size), (flags), &__key); \
+ })
+
+-int ring_buffer_wait(struct trace_buffer *buffer, int cpu, int full);
++typedef bool (*ring_buffer_cond_fn)(void *data);
++int ring_buffer_wait(struct trace_buffer *buffer, int cpu, int full,
++ ring_buffer_cond_fn cond, void *data);
+ __poll_t ring_buffer_poll_wait(struct trace_buffer *buffer, int cpu,
+ struct file *filp, poll_table *poll_table, int full);
+ void ring_buffer_wake_waiters(struct trace_buffer *buffer, int cpu);
+diff --git a/include/linux/security.h b/include/linux/security.h
+index d0eb20f90b264..3180d823e0233 100644
+--- a/include/linux/security.h
++++ b/include/linux/security.h
+@@ -478,9 +478,9 @@ int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
+ unsigned nsops, int alter);
+ void security_d_instantiate(struct dentry *dentry, struct inode *inode);
+ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
+- size_t __user *size, u32 flags);
++ u32 __user *size, u32 flags);
+ int security_setselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
+- size_t size, u32 flags);
++ u32 size, u32 flags);
+ int security_getprocattr(struct task_struct *p, int lsmid, const char *name,
+ char **value);
+ int security_setprocattr(int lsmid, const char *name, void *value, size_t size);
+@@ -494,7 +494,7 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
+ int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
+ int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
+ int security_locked_down(enum lockdown_reason what);
+-int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len,
++int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len,
+ void *val, size_t val_len, u64 id, u64 flags);
+ #else /* CONFIG_SECURITY */
+
+@@ -1434,7 +1434,7 @@ static inline int security_locked_down(enum lockdown_reason what)
+ return 0;
+ }
+ static inline int lsm_fill_user_ctx(struct lsm_ctx __user *uctx,
+- size_t *uctx_len, void *val, size_t val_len,
++ u32 *uctx_len, void *val, size_t val_len,
+ u64 id, u64 flags)
+ {
+ return -EOPNOTSUPP;
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+index 55b1f3ba48ac1..bb0f2d4ac62f6 100644
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -786,7 +786,8 @@ enum UART_TX_FLAGS {
+ if (pending < WAKEUP_CHARS) { \
+ uart_write_wakeup(__port); \
+ \
+- if (!((flags) & UART_TX_NOSTOP) && pending == 0) \
++ if (!((flags) & UART_TX_NOSTOP) && pending == 0 && \
++ __port->ops->tx_empty(__port)) \
+ __port->ops->stop_tx(__port); \
+ } \
+ \
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index 2dde34c29203b..d9a1ccfb57080 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -3448,6 +3448,16 @@ static inline void skb_frag_ref(struct sk_buff *skb, int f)
+
+ bool napi_pp_put_page(struct page *page, bool napi_safe);
+
++static inline void
++skb_page_unref(const struct sk_buff *skb, struct page *page, bool napi_safe)
++{
++#ifdef CONFIG_PAGE_POOL
++ if (skb->pp_recycle && napi_pp_put_page(page, napi_safe))
++ return;
++#endif
++ put_page(page);
++}
++
+ static inline void
+ napi_frag_unref(skb_frag_t *frag, bool recycle, bool napi_safe)
+ {
+diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
+index 77eb9b0e76850..e619ac10cd234 100644
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -960,10 +960,10 @@ asmlinkage long sys_cachestat(unsigned int fd,
+ struct cachestat __user *cstat, unsigned int flags);
+ asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags);
+ asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx,
+- size_t *size, __u32 flags);
++ u32 *size, u32 flags);
+ asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx,
+- size_t size, __u32 flags);
+-asmlinkage long sys_lsm_list_modules(u64 *ids, size_t *size, u32 flags);
++ u32 size, u32 flags);
++asmlinkage long sys_lsm_list_modules(u64 *ids, u32 *size, u32 flags);
+
+ /*
+ * Architecture-specific system calls
+diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
+index d68ff9b1247f9..fc6d0af56bb17 100644
+--- a/include/linux/trace_events.h
++++ b/include/linux/trace_events.h
+@@ -103,13 +103,16 @@ struct trace_iterator {
+ unsigned int temp_size;
+ char *fmt; /* modified format holder */
+ unsigned int fmt_size;
+- long wait_index;
++ atomic_t wait_index;
+
+ /* trace_seq for __print_flags() and __print_symbolic() etc. */
+ struct trace_seq tmp_seq;
+
+ cpumask_var_t started;
+
++ /* Set when the file is closed to prevent new waiters */
++ bool closed;
++
+ /* it's true when current open file is snapshot */
+ bool snapshot;
+
+diff --git a/include/linux/vfio.h b/include/linux/vfio.h
+index 89b265bc6ec31..8b1a298204091 100644
+--- a/include/linux/vfio.h
++++ b/include/linux/vfio.h
+@@ -356,6 +356,7 @@ struct virqfd {
+ wait_queue_entry_t wait;
+ poll_table pt;
+ struct work_struct shutdown;
++ struct work_struct flush_inject;
+ struct virqfd **pvirqfd;
+ };
+
+@@ -363,5 +364,6 @@ int vfio_virqfd_enable(void *opaque, int (*handler)(void *, void *),
+ void (*thread)(void *, void *), void *data,
+ struct virqfd **pvirqfd, int fd);
+ void vfio_virqfd_disable(struct virqfd **pvirqfd);
++void vfio_virqfd_flush_thread(struct virqfd **pvirqfd);
+
+ #endif /* VFIO_H */
+diff --git a/include/media/media-entity.h b/include/media/media-entity.h
+index 2b6cd343ee9e0..4d95893c89846 100644
+--- a/include/media/media-entity.h
++++ b/include/media/media-entity.h
+@@ -225,6 +225,7 @@ enum media_pad_signal_type {
+ * @graph_obj: Embedded structure containing the media object common data
+ * @entity: Entity this pad belongs to
+ * @index: Pad index in the entity pads array, numbered from 0 to n
++ * @num_links: Number of links connected to this pad
+ * @sig_type: Type of the signal inside a media pad
+ * @flags: Pad flags, as defined in
+ * :ref:`include/uapi/linux/media.h <media_header>`
+@@ -236,6 +237,7 @@ struct media_pad {
+ struct media_gobj graph_obj; /* must be first field in struct */
+ struct media_entity *entity;
+ u16 index;
++ u16 num_links;
+ enum media_pad_signal_type sig_type;
+ unsigned long flags;
+
+diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
+index 2b54fdd8ca15a..0180eaec457bf 100644
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -4972,6 +4972,7 @@ struct cfg80211_ops {
+ * set this flag to update channels on beacon hints.
+ * @WIPHY_FLAG_SUPPORTS_NSTR_NONPRIMARY: support connection to non-primary link
+ * of an NSTR mobile AP MLD.
++ * @WIPHY_FLAG_DISABLE_WEXT: disable wireless extensions for this device
+ */
+ enum wiphy_flags {
+ WIPHY_FLAG_SUPPORTS_EXT_KEK_KCK = BIT(0),
+@@ -4983,6 +4984,7 @@ enum wiphy_flags {
+ WIPHY_FLAG_4ADDR_STATION = BIT(6),
+ WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7),
+ WIPHY_FLAG_IBSS_RSN = BIT(8),
++ WIPHY_FLAG_DISABLE_WEXT = BIT(9),
+ WIPHY_FLAG_MESH_AUTH = BIT(10),
+ WIPHY_FLAG_SUPPORTS_EXT_KCK_32 = BIT(11),
+ WIPHY_FLAG_SUPPORTS_NSTR_NONPRIMARY = BIT(12),
+diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
+index cd95711b12b8e..76d2cd2e2b309 100644
+--- a/include/net/cfg802154.h
++++ b/include/net/cfg802154.h
+@@ -401,6 +401,7 @@ struct ieee802154_llsec_key {
+
+ struct ieee802154_llsec_key_entry {
+ struct list_head list;
++ struct rcu_head rcu;
+
+ struct ieee802154_llsec_key_id id;
+ struct ieee802154_llsec_key *key;
+diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h
+index 4ce1988b2ba01..f40915d2eceef 100644
+--- a/include/scsi/scsi_driver.h
++++ b/include/scsi/scsi_driver.h
+@@ -12,6 +12,7 @@ struct request;
+ struct scsi_driver {
+ struct device_driver gendrv;
+
++ int (*resume)(struct device *);
+ void (*rescan)(struct device *);
+ blk_status_t (*init_command)(struct scsi_cmnd *);
+ void (*uninit_command)(struct scsi_cmnd *);
+diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
+index 3b907fc2ef08f..510f594b06368 100644
+--- a/include/scsi/scsi_host.h
++++ b/include/scsi/scsi_host.h
+@@ -767,6 +767,7 @@ scsi_template_proc_dir(const struct scsi_host_template *sht);
+ #define scsi_template_proc_dir(sht) NULL
+ #endif
+ extern void scsi_scan_host(struct Scsi_Host *);
++extern int scsi_resume_device(struct scsi_device *sdev);
+ extern int scsi_rescan_device(struct scsi_device *sdev);
+ extern void scsi_remove_host(struct Scsi_Host *);
+ extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *);
+diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
+index f8bc34a6bcfa2..cdf6ad872149c 100644
+--- a/include/uapi/linux/btrfs.h
++++ b/include/uapi/linux/btrfs.h
+@@ -92,6 +92,7 @@ struct btrfs_qgroup_limit {
+ * struct btrfs_qgroup_inherit.flags
+ */
+ #define BTRFS_QGROUP_INHERIT_SET_LIMITS (1ULL << 0)
++#define BTRFS_QGROUP_INHERIT_FLAGS_SUPP (BTRFS_QGROUP_INHERIT_SET_LIMITS)
+
+ struct btrfs_qgroup_inherit {
+ __u64 flags;
+diff --git a/init/initramfs.c b/init/initramfs.c
+index 76deb48c38cb1..b607d3463b477 100644
+--- a/init/initramfs.c
++++ b/init/initramfs.c
+@@ -683,7 +683,7 @@ static void __init populate_initrd_image(char *err)
+
+ printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n",
+ err);
+- file = filp_open("/initrd.image", O_WRONLY | O_CREAT, 0700);
++ file = filp_open("/initrd.image", O_WRONLY|O_CREAT|O_LARGEFILE, 0700);
+ if (IS_ERR(file))
+ return;
+
+diff --git a/io_uring/futex.c b/io_uring/futex.c
+index 3c3575303c3d0..792a03df58dea 100644
+--- a/io_uring/futex.c
++++ b/io_uring/futex.c
+@@ -159,6 +159,7 @@ bool io_futex_remove_all(struct io_ring_ctx *ctx, struct task_struct *task,
+ hlist_for_each_entry_safe(req, tmp, &ctx->futex_list, hash_node) {
+ if (!io_match_task_safe(req, task, cancel_all))
+ continue;
++ hlist_del_init(&req->hash_node);
+ __io_futex_cancel(ctx, req);
+ found = true;
+ }
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index 9f938874c5e13..adf944bb5a2fe 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -2776,14 +2776,15 @@ static void io_rings_free(struct io_ring_ctx *ctx)
+ if (!(ctx->flags & IORING_SETUP_NO_MMAP)) {
+ io_mem_free(ctx->rings);
+ io_mem_free(ctx->sq_sqes);
+- ctx->rings = NULL;
+- ctx->sq_sqes = NULL;
+ } else {
+ io_pages_free(&ctx->ring_pages, ctx->n_ring_pages);
+ ctx->n_ring_pages = 0;
+ io_pages_free(&ctx->sqe_pages, ctx->n_sqe_pages);
+ ctx->n_sqe_pages = 0;
+ }
++
++ ctx->rings = NULL;
++ ctx->sq_sqes = NULL;
+ }
+
+ void *io_mem_alloc(size_t size)
+diff --git a/io_uring/net.c b/io_uring/net.c
+index 4aaeada03f1e7..5a4001139e288 100644
+--- a/io_uring/net.c
++++ b/io_uring/net.c
+@@ -87,7 +87,7 @@ static inline bool io_check_multishot(struct io_kiocb *req,
+ * generic paths but multipoll may decide to post extra cqes.
+ */
+ return !(issue_flags & IO_URING_F_IOWQ) ||
+- !(issue_flags & IO_URING_F_MULTISHOT) ||
++ !(req->flags & REQ_F_APOLL_MULTISHOT) ||
+ !req->ctx->task_complete;
+ }
+
+@@ -915,7 +915,8 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
+ kfree(kmsg->free_iov);
+ io_netmsg_recycle(req, issue_flags);
+ req->flags &= ~REQ_F_NEED_CLEANUP;
+- }
++ } else if (ret == -EAGAIN)
++ return io_setup_async_msg(req, kmsg, issue_flags);
+
+ return ret;
+ }
+diff --git a/io_uring/poll.c b/io_uring/poll.c
+index 58b7556f621eb..c6f4789623cb2 100644
+--- a/io_uring/poll.c
++++ b/io_uring/poll.c
+@@ -539,14 +539,6 @@ static void __io_queue_proc(struct io_poll *poll, struct io_poll_table *pt,
+ poll->wait.private = (void *) wqe_private;
+
+ if (poll->events & EPOLLEXCLUSIVE) {
+- /*
+- * Exclusive waits may only wake a limited amount of entries
+- * rather than all of them, this may interfere with lazy
+- * wake if someone does wait(events > 1). Ensure we don't do
+- * lazy wake for those, as we need to process each one as they
+- * come in.
+- */
+- req->flags |= REQ_F_POLL_NO_LAZY;
+ add_wait_queue_exclusive(head, &poll->wait);
+ } else {
+ add_wait_queue(head, &poll->wait);
+@@ -618,6 +610,17 @@ static int __io_arm_poll_handler(struct io_kiocb *req,
+ if (issue_flags & IO_URING_F_UNLOCKED)
+ req->flags &= ~REQ_F_HASH_LOCKED;
+
++
++ /*
++ * Exclusive waits may only wake a limited amount of entries
++ * rather than all of them, this may interfere with lazy
++ * wake if someone does wait(events > 1). Ensure we don't do
++ * lazy wake for those, as we need to process each one as they
++ * come in.
++ */
++ if (poll->events & EPOLLEXCLUSIVE)
++ req->flags |= REQ_F_POLL_NO_LAZY;
++
+ mask = vfs_poll(req->file, &ipt->pt) & poll->events;
+
+ if (unlikely(ipt->error || !ipt->nr_entries)) {
+diff --git a/io_uring/rw.c b/io_uring/rw.c
+index d5e79d9bdc717..2b84ce8a8a677 100644
+--- a/io_uring/rw.c
++++ b/io_uring/rw.c
+@@ -932,6 +932,8 @@ int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags)
+ */
+ if (!file_can_poll(req->file))
+ return -EBADFD;
++ if (issue_flags & IO_URING_F_IOWQ)
++ return -EAGAIN;
+
+ ret = __io_read(req, issue_flags);
+
+@@ -946,6 +948,8 @@ int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags)
+ */
+ if (io_kbuf_recycle(req, issue_flags))
+ rw->len = 0;
++ if (issue_flags & IO_URING_F_MULTISHOT)
++ return IOU_ISSUE_SKIP_COMPLETE;
+ return -EAGAIN;
+ }
+
+diff --git a/io_uring/waitid.c b/io_uring/waitid.c
+index 6f851978606d9..77d340666cb95 100644
+--- a/io_uring/waitid.c
++++ b/io_uring/waitid.c
+@@ -125,12 +125,6 @@ static void io_waitid_complete(struct io_kiocb *req, int ret)
+
+ lockdep_assert_held(&req->ctx->uring_lock);
+
+- /*
+- * Did cancel find it meanwhile?
+- */
+- if (hlist_unhashed(&req->hash_node))
+- return;
+-
+ hlist_del_init(&req->hash_node);
+
+ ret = io_waitid_finish(req, ret);
+@@ -202,6 +196,7 @@ bool io_waitid_remove_all(struct io_ring_ctx *ctx, struct task_struct *task,
+ hlist_for_each_entry_safe(req, tmp, &ctx->waitid_list, hash_node) {
+ if (!io_match_task_safe(req, task, cancel_all))
+ continue;
++ hlist_del_init(&req->hash_node);
+ __io_waitid_cancel(ctx, req);
+ found = true;
+ }
+diff --git a/kernel/bounds.c b/kernel/bounds.c
+index b529182e8b04f..c5a9fcd2d6228 100644
+--- a/kernel/bounds.c
++++ b/kernel/bounds.c
+@@ -19,7 +19,7 @@ int main(void)
+ DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS);
+ DEFINE(MAX_NR_ZONES, __MAX_NR_ZONES);
+ #ifdef CONFIG_SMP
+- DEFINE(NR_CPUS_BITS, ilog2(CONFIG_NR_CPUS));
++ DEFINE(NR_CPUS_BITS, bits_per(CONFIG_NR_CPUS));
+ #endif
+ DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t));
+ #ifdef CONFIG_LRU_GEN
+diff --git a/kernel/crash_core.c b/kernel/crash_core.c
+index 75cd6a736d030..40bd908e0a81b 100644
+--- a/kernel/crash_core.c
++++ b/kernel/crash_core.c
+@@ -376,6 +376,9 @@ static int __init reserve_crashkernel_low(unsigned long long low_size)
+
+ crashk_low_res.start = low_base;
+ crashk_low_res.end = low_base + low_size - 1;
++#ifdef HAVE_ARCH_ADD_CRASH_RES_TO_IOMEM_EARLY
++ insert_resource(&iomem_resource, &crashk_low_res);
++#endif
+ #endif
+ return 0;
+ }
+@@ -457,8 +460,12 @@ void __init reserve_crashkernel_generic(char *cmdline,
+
+ crashk_res.start = crash_base;
+ crashk_res.end = crash_base + crash_size - 1;
++#ifdef HAVE_ARCH_ADD_CRASH_RES_TO_IOMEM_EARLY
++ insert_resource(&iomem_resource, &crashk_res);
++#endif
+ }
+
++#ifndef HAVE_ARCH_ADD_CRASH_RES_TO_IOMEM_EARLY
+ static __init int insert_crashkernel_resources(void)
+ {
+ if (crashk_res.start < crashk_res.end)
+@@ -471,6 +478,7 @@ static __init int insert_crashkernel_resources(void)
+ }
+ early_initcall(insert_crashkernel_resources);
+ #endif
++#endif
+
+ int crash_prepare_elf64_headers(struct crash_mem *mem, int need_kernel_map,
+ void **addr, unsigned long *sz)
+diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
+index b079a9a8e0879..877c4b8fad195 100644
+--- a/kernel/dma/swiotlb.c
++++ b/kernel/dma/swiotlb.c
+@@ -981,8 +981,7 @@ static int swiotlb_search_pool_area(struct device *dev, struct io_tlb_pool *pool
+ dma_addr_t tbl_dma_addr =
+ phys_to_dma_unencrypted(dev, pool->start) & boundary_mask;
+ unsigned long max_slots = get_max_slots(boundary_mask);
+- unsigned int iotlb_align_mask =
+- dma_get_min_align_mask(dev) | alloc_align_mask;
++ unsigned int iotlb_align_mask = dma_get_min_align_mask(dev);
+ unsigned int nslots = nr_slots(alloc_size), stride;
+ unsigned int offset = swiotlb_align_offset(dev, orig_addr);
+ unsigned int index, slots_checked, count = 0, i;
+@@ -994,18 +993,25 @@ static int swiotlb_search_pool_area(struct device *dev, struct io_tlb_pool *pool
+ BUG_ON(area_index >= pool->nareas);
+
+ /*
+- * For allocations of PAGE_SIZE or larger only look for page aligned
+- * allocations.
++ * Ensure that the allocation is at least slot-aligned and update
++ * 'iotlb_align_mask' to ignore bits that will be preserved when
++ * offsetting into the allocation.
+ */
+- if (alloc_size >= PAGE_SIZE)
+- iotlb_align_mask |= ~PAGE_MASK;
+- iotlb_align_mask &= ~(IO_TLB_SIZE - 1);
++ alloc_align_mask |= (IO_TLB_SIZE - 1);
++ iotlb_align_mask &= ~alloc_align_mask;
+
+ /*
+ * For mappings with an alignment requirement don't bother looping to
+ * unaligned slots once we found an aligned one.
+ */
+- stride = (iotlb_align_mask >> IO_TLB_SHIFT) + 1;
++ stride = get_max_slots(max(alloc_align_mask, iotlb_align_mask));
++
++ /*
++ * For allocations of PAGE_SIZE or larger only look for page aligned
++ * allocations.
++ */
++ if (alloc_size >= PAGE_SIZE)
++ stride = umax(stride, PAGE_SHIFT - IO_TLB_SHIFT + 1);
+
+ spin_lock_irqsave(&area->lock, flags);
+ if (unlikely(nslots > pool->area_nslabs - area->used))
+@@ -1015,11 +1021,14 @@ static int swiotlb_search_pool_area(struct device *dev, struct io_tlb_pool *pool
+ index = area->index;
+
+ for (slots_checked = 0; slots_checked < pool->area_nslabs; ) {
++ phys_addr_t tlb_addr;
++
+ slot_index = slot_base + index;
++ tlb_addr = slot_addr(tbl_dma_addr, slot_index);
+
+- if (orig_addr &&
+- (slot_addr(tbl_dma_addr, slot_index) &
+- iotlb_align_mask) != (orig_addr & iotlb_align_mask)) {
++ if ((tlb_addr & alloc_align_mask) ||
++ (orig_addr && (tlb_addr & iotlb_align_mask) !=
++ (orig_addr & iotlb_align_mask))) {
+ index = wrap_area_index(pool, index + 1);
+ slots_checked++;
+ continue;
+@@ -1631,12 +1640,14 @@ struct page *swiotlb_alloc(struct device *dev, size_t size)
+ struct io_tlb_mem *mem = dev->dma_io_tlb_mem;
+ struct io_tlb_pool *pool;
+ phys_addr_t tlb_addr;
++ unsigned int align;
+ int index;
+
+ if (!mem)
+ return NULL;
+
+- index = swiotlb_find_slots(dev, 0, size, 0, &pool);
++ align = (1 << (get_order(size) + PAGE_SHIFT)) - 1;
++ index = swiotlb_find_slots(dev, 0, size, align, &pool);
+ if (index == -1)
+ return NULL;
+
+diff --git a/kernel/entry/common.c b/kernel/entry/common.c
+index 88cb3c88aaa5c..90843cc385880 100644
+--- a/kernel/entry/common.c
++++ b/kernel/entry/common.c
+@@ -57,8 +57,14 @@ long syscall_trace_enter(struct pt_regs *regs, long syscall,
+ /* Either of the above might have changed the syscall number */
+ syscall = syscall_get_nr(current, regs);
+
+- if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
++ if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT)) {
+ trace_sys_enter(regs, syscall);
++ /*
++ * Probes or BPF hooks in the tracepoint may have changed the
++ * system call number as well.
++ */
++ syscall = syscall_get_nr(current, regs);
++ }
+
+ syscall_enter_audit(regs, syscall);
+
+diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
+index 1782f90cd8c6c..7389add52791f 100644
+--- a/kernel/irq/manage.c
++++ b/kernel/irq/manage.c
+@@ -1642,8 +1642,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
+ }
+
+ if (!((old->flags & new->flags) & IRQF_SHARED) ||
+- (oldtype != (new->flags & IRQF_TRIGGER_MASK)) ||
+- ((old->flags ^ new->flags) & IRQF_ONESHOT))
++ (oldtype != (new->flags & IRQF_TRIGGER_MASK)))
++ goto mismatch;
++
++ if ((old->flags & IRQF_ONESHOT) &&
++ (new->flags & IRQF_COND_ONESHOT))
++ new->flags |= IRQF_ONESHOT;
++ else if ((old->flags ^ new->flags) & IRQF_ONESHOT)
+ goto mismatch;
+
+ /* All handlers must agree on per-cpuness */
+diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig
+index 0ea1b2970a23b..28db5b7589eb2 100644
+--- a/kernel/module/Kconfig
++++ b/kernel/module/Kconfig
+@@ -236,6 +236,10 @@ choice
+ possible to load a signed module containing the algorithm to check
+ the signature on that module.
+
++config MODULE_SIG_SHA1
++ bool "Sign modules with SHA-1"
++ select CRYPTO_SHA1
++
+ config MODULE_SIG_SHA256
+ bool "Sign modules with SHA-256"
+ select CRYPTO_SHA256
+@@ -265,6 +269,7 @@ endchoice
+ config MODULE_SIG_HASH
+ string
+ depends on MODULE_SIG || IMA_APPRAISE_MODSIG
++ default "sha1" if MODULE_SIG_SHA1
+ default "sha256" if MODULE_SIG_SHA256
+ default "sha384" if MODULE_SIG_SHA384
+ default "sha512" if MODULE_SIG_SHA512
+diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
+index fa3bf161d13f7..a718067deecee 100644
+--- a/kernel/power/suspend.c
++++ b/kernel/power/suspend.c
+@@ -192,6 +192,7 @@ static int __init mem_sleep_default_setup(char *str)
+ if (mem_sleep_labels[state] &&
+ !strcmp(str, mem_sleep_labels[state])) {
+ mem_sleep_default = state;
++ mem_sleep_current = state;
+ break;
+ }
+
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index 72f6a564e832f..7a835b277e98d 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2026,6 +2026,12 @@ static int console_trylock_spinning(void)
+ */
+ mutex_acquire(&console_lock_dep_map, 0, 1, _THIS_IP_);
+
++ /*
++ * Update @console_may_schedule for trylock because the previous
++ * owner may have been schedulable.
++ */
++ console_may_schedule = 0;
++
+ return 1;
+ }
+
+@@ -3295,6 +3301,21 @@ static int __init keep_bootcon_setup(char *str)
+
+ early_param("keep_bootcon", keep_bootcon_setup);
+
++static int console_call_setup(struct console *newcon, char *options)
++{
++ int err;
++
++ if (!newcon->setup)
++ return 0;
++
++ /* Synchronize with possible boot console. */
++ console_lock();
++ err = newcon->setup(newcon, options);
++ console_unlock();
++
++ return err;
++}
++
+ /*
+ * This is called by register_console() to try to match
+ * the newly registered console with any of the ones selected
+@@ -3330,8 +3351,8 @@ static int try_enable_preferred_console(struct console *newcon,
+ if (_braille_register_console(newcon, c))
+ return 0;
+
+- if (newcon->setup &&
+- (err = newcon->setup(newcon, c->options)) != 0)
++ err = console_call_setup(newcon, c->options);
++ if (err)
+ return err;
+ }
+ newcon->flags |= CON_ENABLED;
+@@ -3357,7 +3378,7 @@ static void try_enable_default_console(struct console *newcon)
+ if (newcon->index < 0)
+ newcon->index = 0;
+
+- if (newcon->setup && newcon->setup(newcon, NULL) != 0)
++ if (console_call_setup(newcon, NULL) != 0)
+ return;
+
+ newcon->flags |= CON_ENABLED;
+diff --git a/kernel/sys.c b/kernel/sys.c
+index f8e543f1e38a0..8bb106a56b3a5 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -2408,8 +2408,11 @@ static inline int prctl_set_mdwe(unsigned long bits, unsigned long arg3,
+ if (bits & PR_MDWE_NO_INHERIT && !(bits & PR_MDWE_REFUSE_EXEC_GAIN))
+ return -EINVAL;
+
+- /* PARISC cannot allow mdwe as it needs writable stacks */
+- if (IS_ENABLED(CONFIG_PARISC))
++ /*
++ * EOPNOTSUPP might be more appropriate here in principle, but
++ * existing userspace depends on EINVAL specifically.
++ */
++ if (!arch_memory_deny_write_exec_supported())
+ return -EINVAL;
+
+ current_bits = get_current_mdwe();
+diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c
+index 9de66bbbb3d15..4782edcbe7b9b 100644
+--- a/kernel/time/posix-clock.c
++++ b/kernel/time/posix-clock.c
+@@ -129,15 +129,17 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
+ goto out;
+ }
+ pccontext->clk = clk;
+- fp->private_data = pccontext;
+- if (clk->ops.open)
++ if (clk->ops.open) {
+ err = clk->ops.open(pccontext, fp->f_mode);
+- else
+- err = 0;
+-
+- if (!err) {
+- get_device(clk->dev);
++ if (err) {
++ kfree(pccontext);
++ goto out;
++ }
+ }
++
++ fp->private_data = pccontext;
++ get_device(clk->dev);
++ err = 0;
+ out:
+ up_read(&clk->rwsem);
+ return err;
+diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
+index aa332ace108b1..43060a7ae15e7 100644
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -384,6 +384,7 @@ struct rb_irq_work {
+ struct irq_work work;
+ wait_queue_head_t waiters;
+ wait_queue_head_t full_waiters;
++ atomic_t seq;
+ bool waiters_pending;
+ bool full_waiters_pending;
+ bool wakeup_full;
+@@ -753,6 +754,9 @@ static void rb_wake_up_waiters(struct irq_work *work)
+ {
+ struct rb_irq_work *rbwork = container_of(work, struct rb_irq_work, work);
+
++ /* For waiters waiting for the first wake up */
++ (void)atomic_fetch_inc_release(&rbwork->seq);
++
+ wake_up_all(&rbwork->waiters);
+ if (rbwork->full_waiters_pending || rbwork->wakeup_full) {
+ /* Only cpu_buffer sets the above flags */
+@@ -834,51 +838,24 @@ static bool rb_watermark_hit(struct trace_buffer *buffer, int cpu, int full)
+ pagebusy = cpu_buffer->reader_page == cpu_buffer->commit_page;
+ ret = !pagebusy && full_hit(buffer, cpu, full);
+
+- if (!cpu_buffer->shortest_full ||
+- cpu_buffer->shortest_full > full)
+- cpu_buffer->shortest_full = full;
++ if (!ret && (!cpu_buffer->shortest_full ||
++ cpu_buffer->shortest_full > full)) {
++ cpu_buffer->shortest_full = full;
++ }
+ raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
+ }
+ return ret;
+ }
+
+-/**
+- * ring_buffer_wait - wait for input to the ring buffer
+- * @buffer: buffer to wait on
+- * @cpu: the cpu buffer to wait on
+- * @full: wait until the percentage of pages are available, if @cpu != RING_BUFFER_ALL_CPUS
+- *
+- * If @cpu == RING_BUFFER_ALL_CPUS then the task will wake up as soon
+- * as data is added to any of the @buffer's cpu buffers. Otherwise
+- * it will wait for data to be added to a specific cpu buffer.
+- */
+-int ring_buffer_wait(struct trace_buffer *buffer, int cpu, int full)
++static inline bool
++rb_wait_cond(struct rb_irq_work *rbwork, struct trace_buffer *buffer,
++ int cpu, int full, ring_buffer_cond_fn cond, void *data)
+ {
+- struct ring_buffer_per_cpu *cpu_buffer;
+- DEFINE_WAIT(wait);
+- struct rb_irq_work *work;
+- int ret = 0;
+-
+- /*
+- * Depending on what the caller is waiting for, either any
+- * data in any cpu buffer, or a specific buffer, put the
+- * caller on the appropriate wait queue.
+- */
+- if (cpu == RING_BUFFER_ALL_CPUS) {
+- work = &buffer->irq_work;
+- /* Full only makes sense on per cpu reads */
+- full = 0;
+- } else {
+- if (!cpumask_test_cpu(cpu, buffer->cpumask))
+- return -ENODEV;
+- cpu_buffer = buffer->buffers[cpu];
+- work = &cpu_buffer->irq_work;
+- }
++ if (rb_watermark_hit(buffer, cpu, full))
++ return true;
+
+- if (full)
+- prepare_to_wait(&work->full_waiters, &wait, TASK_INTERRUPTIBLE);
+- else
+- prepare_to_wait(&work->waiters, &wait, TASK_INTERRUPTIBLE);
++ if (cond(data))
++ return true;
+
+ /*
+ * The events can happen in critical sections where
+@@ -901,27 +878,82 @@ int ring_buffer_wait(struct trace_buffer *buffer, int cpu, int full)
+ * a task has been queued. It's OK for spurious wake ups.
+ */
+ if (full)
+- work->full_waiters_pending = true;
++ rbwork->full_waiters_pending = true;
+ else
+- work->waiters_pending = true;
++ rbwork->waiters_pending = true;
+
+- if (rb_watermark_hit(buffer, cpu, full))
+- goto out;
++ return false;
++}
+
+- if (signal_pending(current)) {
+- ret = -EINTR;
+- goto out;
++struct rb_wait_data {
++ struct rb_irq_work *irq_work;
++ int seq;
++};
++
++/*
++ * The default wait condition for ring_buffer_wait() is to just to exit the
++ * wait loop the first time it is woken up.
++ */
++static bool rb_wait_once(void *data)
++{
++ struct rb_wait_data *rdata = data;
++ struct rb_irq_work *rbwork = rdata->irq_work;
++
++ return atomic_read_acquire(&rbwork->seq) != rdata->seq;
++}
++
++/**
++ * ring_buffer_wait - wait for input to the ring buffer
++ * @buffer: buffer to wait on
++ * @cpu: the cpu buffer to wait on
++ * @full: wait until the percentage of pages are available, if @cpu != RING_BUFFER_ALL_CPUS
++ * @cond: condition function to break out of wait (NULL to run once)
++ * @data: the data to pass to @cond.
++ *
++ * If @cpu == RING_BUFFER_ALL_CPUS then the task will wake up as soon
++ * as data is added to any of the @buffer's cpu buffers. Otherwise
++ * it will wait for data to be added to a specific cpu buffer.
++ */
++int ring_buffer_wait(struct trace_buffer *buffer, int cpu, int full,
++ ring_buffer_cond_fn cond, void *data)
++{
++ struct ring_buffer_per_cpu *cpu_buffer;
++ struct wait_queue_head *waitq;
++ struct rb_irq_work *rbwork;
++ struct rb_wait_data rdata;
++ int ret = 0;
++
++ /*
++ * Depending on what the caller is waiting for, either any
++ * data in any cpu buffer, or a specific buffer, put the
++ * caller on the appropriate wait queue.
++ */
++ if (cpu == RING_BUFFER_ALL_CPUS) {
++ rbwork = &buffer->irq_work;
++ /* Full only makes sense on per cpu reads */
++ full = 0;
++ } else {
++ if (!cpumask_test_cpu(cpu, buffer->cpumask))
++ return -ENODEV;
++ cpu_buffer = buffer->buffers[cpu];
++ rbwork = &cpu_buffer->irq_work;
+ }
+
+- schedule();
+- out:
+ if (full)
+- finish_wait(&work->full_waiters, &wait);
++ waitq = &rbwork->full_waiters;
+ else
+- finish_wait(&work->waiters, &wait);
++ waitq = &rbwork->waiters;
++
++ /* Set up to exit loop as soon as it is woken */
++ if (!cond) {
++ cond = rb_wait_once;
++ rdata.irq_work = rbwork;
++ rdata.seq = atomic_read_acquire(&rbwork->seq);
++ data = &rdata;
++ }
+
+- if (!ret && !rb_watermark_hit(buffer, cpu, full) && signal_pending(current))
+- ret = -EINTR;
++ ret = wait_event_interruptible((*waitq),
++ rb_wait_cond(rbwork, buffer, cpu, full, cond, data));
+
+ return ret;
+ }
+@@ -964,16 +996,32 @@ __poll_t ring_buffer_poll_wait(struct trace_buffer *buffer, int cpu,
+ poll_wait(filp, &rbwork->full_waiters, poll_table);
+
+ raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
+- rbwork->full_waiters_pending = true;
+ if (!cpu_buffer->shortest_full ||
+ cpu_buffer->shortest_full > full)
+ cpu_buffer->shortest_full = full;
+ raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
+- } else {
+- poll_wait(filp, &rbwork->waiters, poll_table);
+- rbwork->waiters_pending = true;
++ if (full_hit(buffer, cpu, full))
++ return EPOLLIN | EPOLLRDNORM;
++ /*
++ * Only allow full_waiters_pending update to be seen after
++ * the shortest_full is set. If the writer sees the
++ * full_waiters_pending flag set, it will compare the
++ * amount in the ring buffer to shortest_full. If the amount
++ * in the ring buffer is greater than the shortest_full
++ * percent, it will call the irq_work handler to wake up
++ * this list. The irq_handler will reset shortest_full
++ * back to zero. That's done under the reader_lock, but
++ * the below smp_mb() makes sure that the update to
++ * full_waiters_pending doesn't leak up into the above.
++ */
++ smp_mb();
++ rbwork->full_waiters_pending = true;
++ return 0;
+ }
+
++ poll_wait(filp, &rbwork->waiters, poll_table);
++ rbwork->waiters_pending = true;
++
+ /*
+ * There's a tight race between setting the waiters_pending and
+ * checking if the ring buffer is empty. Once the waiters_pending bit
+@@ -989,9 +1037,6 @@ __poll_t ring_buffer_poll_wait(struct trace_buffer *buffer, int cpu,
+ */
+ smp_mb();
+
+- if (full)
+- return full_hit(buffer, cpu, full) ? EPOLLIN | EPOLLRDNORM : 0;
+-
+ if ((cpu == RING_BUFFER_ALL_CPUS && !ring_buffer_empty(buffer)) ||
+ (cpu != RING_BUFFER_ALL_CPUS && !ring_buffer_empty_cpu(buffer, cpu)))
+ return EPOLLIN | EPOLLRDNORM;
+diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
+index c9c8983073485..d390fea3a6a52 100644
+--- a/kernel/trace/trace.c
++++ b/kernel/trace/trace.c
+@@ -1955,15 +1955,36 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
+
+ #endif /* CONFIG_TRACER_MAX_TRACE */
+
++struct pipe_wait {
++ struct trace_iterator *iter;
++ int wait_index;
++};
++
++static bool wait_pipe_cond(void *data)
++{
++ struct pipe_wait *pwait = data;
++ struct trace_iterator *iter = pwait->iter;
++
++ if (atomic_read_acquire(&iter->wait_index) != pwait->wait_index)
++ return true;
++
++ return iter->closed;
++}
++
+ static int wait_on_pipe(struct trace_iterator *iter, int full)
+ {
++ struct pipe_wait pwait;
+ int ret;
+
+ /* Iterators are static, they should be filled or empty */
+ if (trace_buffer_iter(iter, iter->cpu_file))
+ return 0;
+
+- ret = ring_buffer_wait(iter->array_buffer->buffer, iter->cpu_file, full);
++ pwait.wait_index = atomic_read_acquire(&iter->wait_index);
++ pwait.iter = iter;
++
++ ret = ring_buffer_wait(iter->array_buffer->buffer, iter->cpu_file, full,
++ wait_pipe_cond, &pwait);
+
+ #ifdef CONFIG_TRACER_MAX_TRACE
+ /*
+@@ -8398,9 +8419,9 @@ static int tracing_buffers_flush(struct file *file, fl_owner_t id)
+ struct ftrace_buffer_info *info = file->private_data;
+ struct trace_iterator *iter = &info->iter;
+
+- iter->wait_index++;
++ iter->closed = true;
+ /* Make sure the waiters see the new wait_index */
+- smp_wmb();
++ (void)atomic_fetch_inc_release(&iter->wait_index);
+
+ ring_buffer_wake_waiters(iter->array_buffer->buffer, iter->cpu_file);
+
+@@ -8500,6 +8521,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
+ .spd_release = buffer_spd_release,
+ };
+ struct buffer_ref *ref;
++ bool woken = false;
+ int page_size;
+ int entries, i;
+ ssize_t ret = 0;
+@@ -8573,17 +8595,17 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
+
+ /* did we read anything? */
+ if (!spd.nr_pages) {
+- long wait_index;
+
+ if (ret)
+ goto out;
+
++ if (woken)
++ goto out;
++
+ ret = -EAGAIN;
+ if ((file->f_flags & O_NONBLOCK) || (flags & SPLICE_F_NONBLOCK))
+ goto out;
+
+- wait_index = READ_ONCE(iter->wait_index);
+-
+ ret = wait_on_pipe(iter, iter->snapshot ? 0 : iter->tr->buffer_percent);
+ if (ret)
+ goto out;
+@@ -8592,10 +8614,8 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos,
+ if (!tracer_tracing_is_on(iter->tr))
+ goto out;
+
+- /* Make sure we see the new wait_index */
+- smp_rmb();
+- if (wait_index != iter->wait_index)
+- goto out;
++ /* Iterate one more time to collect any new data then exit */
++ woken = true;
+
+ goto again;
+ }
+@@ -8618,9 +8638,8 @@ static long tracing_buffers_ioctl(struct file *file, unsigned int cmd, unsigned
+
+ mutex_lock(&trace_types_lock);
+
+- iter->wait_index++;
+ /* Make sure the waiters see the new wait_index */
+- smp_wmb();
++ (void)atomic_fetch_inc_release(&iter->wait_index);
+
+ ring_buffer_wake_waiters(iter->array_buffer->buffer, iter->cpu_file);
+
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index ed8ebc9776016..781900b148b67 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -7186,7 +7186,7 @@ void __init workqueue_init_early(void)
+ WQ_FREEZABLE, 0);
+ system_power_efficient_wq = alloc_workqueue("events_power_efficient",
+ WQ_POWER_EFFICIENT, 0);
+- system_freezable_power_efficient_wq = alloc_workqueue("events_freezable_power_efficient",
++ system_freezable_power_efficient_wq = alloc_workqueue("events_freezable_pwr_efficient",
+ WQ_FREEZABLE | WQ_POWER_EFFICIENT,
+ 0);
+ BUG_ON(!system_wq || !system_highpri_wq || !system_long_wq ||
+diff --git a/lib/pci_iomap.c b/lib/pci_iomap.c
+index ce39ce9f3526e..2829ddb0e316b 100644
+--- a/lib/pci_iomap.c
++++ b/lib/pci_iomap.c
+@@ -170,8 +170,8 @@ void pci_iounmap(struct pci_dev *dev, void __iomem *p)
+
+ if (addr >= start && addr < start + IO_SPACE_LIMIT)
+ return;
+- iounmap(p);
+ #endif
++ iounmap(p);
+ }
+ EXPORT_SYMBOL(pci_iounmap);
+
+diff --git a/mm/filemap.c b/mm/filemap.c
+index 4a30de98a8c75..b5e8dd536ae89 100644
+--- a/mm/filemap.c
++++ b/mm/filemap.c
+@@ -4153,7 +4153,23 @@ static void filemap_cachestat(struct address_space *mapping,
+ /* shmem file - in swap cache */
+ swp_entry_t swp = radix_to_swp_entry(folio);
+
++ /* swapin error results in poisoned entry */
++ if (non_swap_entry(swp))
++ goto resched;
++
++ /*
++ * Getting a swap entry from the shmem
++ * inode means we beat
++ * shmem_unuse(). rcu_read_lock()
++ * ensures swapoff waits for us before
++ * freeing the swapper space. However,
++ * we can race with swapping and
++ * invalidation, so there might not be
++ * a shadow in the swapcache (yet).
++ */
+ shadow = get_shadow_from_swap_cache(swp);
++ if (!shadow)
++ goto resched;
+ }
+ #endif
+ if (workingset_test_recent(shadow, true, &workingset))
+diff --git a/mm/kasan/kasan_test.c b/mm/kasan/kasan_test.c
+index 971cfff4ca0b7..e26a2583a6643 100644
+--- a/mm/kasan/kasan_test.c
++++ b/mm/kasan/kasan_test.c
+@@ -440,7 +440,8 @@ static void kmalloc_oob_16(struct kunit *test)
+ /* This test is specifically crafted for the generic mode. */
+ KASAN_TEST_NEEDS_CONFIG_ON(test, CONFIG_KASAN_GENERIC);
+
+- ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL);
++ /* RELOC_HIDE to prevent gcc from warning about short alloc */
++ ptr1 = RELOC_HIDE(kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL), 0);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr1);
+
+ ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
+diff --git a/mm/memtest.c b/mm/memtest.c
+index 32f3e9dda8370..c2c609c391199 100644
+--- a/mm/memtest.c
++++ b/mm/memtest.c
+@@ -51,10 +51,10 @@ static void __init memtest(u64 pattern, phys_addr_t start_phys, phys_addr_t size
+ last_bad = 0;
+
+ for (p = start; p < end; p++)
+- *p = pattern;
++ WRITE_ONCE(*p, pattern);
+
+ for (p = start; p < end; p++, start_phys_aligned += incr) {
+- if (*p == pattern)
++ if (READ_ONCE(*p) == pattern)
+ continue;
+ if (start_phys_aligned == last_bad + incr) {
+ last_bad += incr;
+diff --git a/mm/shmem_quota.c b/mm/shmem_quota.c
+index 062d1c1097ae3..ce514e700d2f6 100644
+--- a/mm/shmem_quota.c
++++ b/mm/shmem_quota.c
+@@ -116,7 +116,7 @@ static int shmem_free_file_info(struct super_block *sb, int type)
+ static int shmem_get_next_id(struct super_block *sb, struct kqid *qid)
+ {
+ struct mem_dqinfo *info = sb_dqinfo(sb, qid->type);
+- struct rb_node *node = ((struct rb_root *)info->dqi_priv)->rb_node;
++ struct rb_node *node;
+ qid_t id = from_kqid(&init_user_ns, *qid);
+ struct quota_info *dqopt = sb_dqopt(sb);
+ struct quota_id *entry = NULL;
+@@ -126,6 +126,7 @@ static int shmem_get_next_id(struct super_block *sb, struct kqid *qid)
+ return -ESRCH;
+
+ down_read(&dqopt->dqio_sem);
++ node = ((struct rb_root *)info->dqi_priv)->rb_node;
+ while (node) {
+ entry = rb_entry(node, struct quota_id, node);
+
+@@ -165,7 +166,7 @@ static int shmem_get_next_id(struct super_block *sb, struct kqid *qid)
+ static int shmem_acquire_dquot(struct dquot *dquot)
+ {
+ struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type);
+- struct rb_node **n = &((struct rb_root *)info->dqi_priv)->rb_node;
++ struct rb_node **n;
+ struct shmem_sb_info *sbinfo = dquot->dq_sb->s_fs_info;
+ struct rb_node *parent = NULL, *new_node = NULL;
+ struct quota_id *new_entry, *entry;
+@@ -176,6 +177,8 @@ static int shmem_acquire_dquot(struct dquot *dquot)
+ mutex_lock(&dquot->dq_lock);
+
+ down_write(&dqopt->dqio_sem);
++ n = &((struct rb_root *)info->dqi_priv)->rb_node;
++
+ while (*n) {
+ parent = *n;
+ entry = rb_entry(parent, struct quota_id, node);
+@@ -264,7 +267,7 @@ static bool shmem_is_empty_dquot(struct dquot *dquot)
+ static int shmem_release_dquot(struct dquot *dquot)
+ {
+ struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type);
+- struct rb_node *node = ((struct rb_root *)info->dqi_priv)->rb_node;
++ struct rb_node *node;
+ qid_t id = from_kqid(&init_user_ns, dquot->dq_id);
+ struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
+ struct quota_id *entry = NULL;
+@@ -275,6 +278,7 @@ static int shmem_release_dquot(struct dquot *dquot)
+ goto out_dqlock;
+
+ down_write(&dqopt->dqio_sem);
++ node = ((struct rb_root *)info->dqi_priv)->rb_node;
+ while (node) {
+ entry = rb_entry(node, struct quota_id, node);
+
+diff --git a/mm/swapfile.c b/mm/swapfile.c
+index 746aa9da53025..6fe0cc25535f5 100644
+--- a/mm/swapfile.c
++++ b/mm/swapfile.c
+@@ -1227,6 +1227,11 @@ static unsigned char __swap_entry_free_locked(struct swap_info_struct *p,
+ * with get_swap_device() and put_swap_device(), unless the swap
+ * functions call get/put_swap_device() by themselves.
+ *
++ * Note that when only holding the PTL, swapoff might succeed immediately
++ * after freeing a swap entry. Therefore, immediately after
++ * __swap_entry_free(), the swap info might become stale and should not
++ * be touched without a prior get_swap_device().
++ *
+ * Check whether swap entry is valid in the swap device. If so,
+ * return pointer to swap_info_struct, and keep the swap entry valid
+ * via preventing the swap device from being swapoff, until
+@@ -1604,13 +1609,19 @@ int free_swap_and_cache(swp_entry_t entry)
+ if (non_swap_entry(entry))
+ return 1;
+
+- p = _swap_info_get(entry);
++ p = get_swap_device(entry);
+ if (p) {
++ if (WARN_ON(data_race(!p->swap_map[swp_offset(entry)]))) {
++ put_swap_device(p);
++ return 0;
++ }
++
+ count = __swap_entry_free(p, entry);
+ if (count == SWAP_HAS_CACHE &&
+ !swap_page_trans_huge_swapped(p, entry))
+ __try_to_reclaim_swap(p, swp_offset(entry),
+ TTRS_UNMAPPED | TTRS_FULL);
++ put_swap_device(p);
+ }
+ return p != NULL;
+ }
+diff --git a/mm/zswap.c b/mm/zswap.c
+index db4625af65fb7..e9c04387195fa 100644
+--- a/mm/zswap.c
++++ b/mm/zswap.c
+@@ -645,6 +645,14 @@ static unsigned long zswap_shrinker_count(struct shrinker *shrinker,
+ if (!zswap_shrinker_enabled || !mem_cgroup_zswap_writeback_enabled(memcg))
+ return 0;
+
++ /*
++ * The shrinker resumes swap writeback, which will enter block
++ * and may enter fs. XXX: Harmonize with vmscan.c __GFP_FS
++ * rules (may_enter_fs()), which apply on a per-folio basis.
++ */
++ if (!gfp_has_io_fs(sc->gfp_mask))
++ return 0;
++
+ #ifdef CONFIG_MEMCG_KMEM
+ mem_cgroup_flush_stats(memcg);
+ nr_backing = memcg_page_state(memcg, MEMCG_ZSWAP_B) >> PAGE_SHIFT;
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index 7d5334b529834..0592369579ab2 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -2842,7 +2842,7 @@ static void hci_cancel_cmd_sync(struct hci_dev *hdev, int err)
+ cancel_delayed_work_sync(&hdev->ncmd_timer);
+ atomic_set(&hdev->cmd_cnt, 1);
+
+- hci_cmd_sync_cancel_sync(hdev, -err);
++ hci_cmd_sync_cancel_sync(hdev, err);
+ }
+
+ /* Suspend HCI device */
+@@ -2862,7 +2862,7 @@ int hci_suspend_dev(struct hci_dev *hdev)
+ return 0;
+
+ /* Cancel potentially blocking sync operation before suspend */
+- hci_cancel_cmd_sync(hdev, -EHOSTDOWN);
++ hci_cancel_cmd_sync(hdev, EHOSTDOWN);
+
+ hci_req_sync_lock(hdev);
+ ret = hci_suspend_sync(hdev);
+@@ -4178,7 +4178,7 @@ static void hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)
+
+ err = hci_send_frame(hdev, skb);
+ if (err < 0) {
+- hci_cmd_sync_cancel_sync(hdev, err);
++ hci_cmd_sync_cancel_sync(hdev, -err);
+ return;
+ }
+
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 684a6ac02b80d..44ca5ea223e3f 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -611,7 +611,10 @@ void hci_cmd_sync_cancel_sync(struct hci_dev *hdev, int err)
+ bt_dev_dbg(hdev, "err 0x%2.2x", err);
+
+ if (hdev->req_status == HCI_REQ_PEND) {
+- hdev->req_result = err;
++ /* req_result is __u32 so error must be positive to be properly
++ * propagated.
++ */
++ hdev->req_result = err < 0 ? -err : err;
+ hdev->req_status = HCI_REQ_CANCELED;
+
+ wake_up_interruptible(&hdev->req_wait_q);
+diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
+index 4dd9e50406720..d33d124218140 100644
+--- a/net/ipv4/esp4.c
++++ b/net/ipv4/esp4.c
+@@ -95,7 +95,7 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,
+ __alignof__(struct scatterlist));
+ }
+
+-static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
++static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)
+ {
+ struct crypto_aead *aead = x->data;
+ int extralen = 0;
+@@ -114,7 +114,7 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
+ */
+ if (req->src != req->dst)
+ for (sg = sg_next(req->src); sg; sg = sg_next(sg))
+- put_page(sg_page(sg));
++ skb_page_unref(skb, sg_page(sg), false);
+ }
+
+ #ifdef CONFIG_INET_ESPINTCP
+@@ -260,7 +260,7 @@ static void esp_output_done(void *data, int err)
+ }
+
+ tmp = ESP_SKB_CB(skb)->tmp;
+- esp_ssg_unref(x, tmp);
++ esp_ssg_unref(x, tmp, skb);
+ kfree(tmp);
+
+ if (xo && (xo->flags & XFRM_DEV_RESUME)) {
+@@ -639,7 +639,7 @@ int esp_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
+ }
+
+ if (sg != dsg)
+- esp_ssg_unref(x, tmp);
++ esp_ssg_unref(x, tmp, skb);
+
+ if (!err && x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP)
+ err = esp_output_tail_tcp(x, skb);
+diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
+index 6e6efe026cdcc..7371886d4f9f4 100644
+--- a/net/ipv6/esp6.c
++++ b/net/ipv6/esp6.c
+@@ -112,7 +112,7 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,
+ __alignof__(struct scatterlist));
+ }
+
+-static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
++static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)
+ {
+ struct crypto_aead *aead = x->data;
+ int extralen = 0;
+@@ -131,7 +131,7 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp)
+ */
+ if (req->src != req->dst)
+ for (sg = sg_next(req->src); sg; sg = sg_next(sg))
+- put_page(sg_page(sg));
++ skb_page_unref(skb, sg_page(sg), false);
+ }
+
+ #ifdef CONFIG_INET6_ESPINTCP
+@@ -294,7 +294,7 @@ static void esp_output_done(void *data, int err)
+ }
+
+ tmp = ESP_SKB_CB(skb)->tmp;
+- esp_ssg_unref(x, tmp);
++ esp_ssg_unref(x, tmp, skb);
+ kfree(tmp);
+
+ esp_output_encap_csum(skb);
+@@ -677,7 +677,7 @@ int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
+ }
+
+ if (sg != dsg)
+- esp_ssg_unref(x, tmp);
++ esp_ssg_unref(x, tmp, skb);
+
+ if (!err && x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP)
+ err = esp_output_tail_tcp(x, skb);
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 327682995c926..1d43a80064721 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -1869,7 +1869,7 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
+ sband->band);
+ }
+
+- ieee80211_sta_set_rx_nss(link_sta);
++ ieee80211_sta_init_nss(link_sta);
+
+ return ret;
+ }
+@@ -2164,15 +2164,14 @@ static int ieee80211_change_station(struct wiphy *wiphy,
+ }
+
+ if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+- sta->sdata->u.vlan.sta) {
+- ieee80211_clear_fast_rx(sta);
++ sta->sdata->u.vlan.sta)
+ RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL);
+- }
+
+ if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
+ ieee80211_vif_dec_num_mcast(sta->sdata);
+
+ sta->sdata = vlansdata;
++ ieee80211_check_fast_rx(sta);
+ ieee80211_check_fast_xmit(sta);
+
+ if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
+diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
+index 0b2b53550bd99..a18361afea249 100644
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -2112,7 +2112,7 @@ enum ieee80211_sta_rx_bandwidth
+ ieee80211_sta_cap_rx_bw(struct link_sta_info *link_sta);
+ enum ieee80211_sta_rx_bandwidth
+ ieee80211_sta_cur_vht_bw(struct link_sta_info *link_sta);
+-void ieee80211_sta_set_rx_nss(struct link_sta_info *link_sta);
++void ieee80211_sta_init_nss(struct link_sta_info *link_sta);
+ enum ieee80211_sta_rx_bandwidth
+ ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width);
+ enum nl80211_chan_width
+diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
+index 9d33fd2377c88..0efdaa8f2a92e 100644
+--- a/net/mac80211/rate.c
++++ b/net/mac80211/rate.c
+@@ -37,7 +37,7 @@ void rate_control_rate_init(struct sta_info *sta)
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+
+- ieee80211_sta_set_rx_nss(&sta->deflink);
++ ieee80211_sta_init_nss(&sta->deflink);
+
+ if (!ref)
+ return;
+diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
+index 5ef1554f991f6..ac4c7a6f962ea 100644
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -3,7 +3,7 @@
+ * Copyright 2002-2005, Devicescape Software, Inc.
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015-2017 Intel Deutschland GmbH
+- * Copyright(c) 2020-2023 Intel Corporation
++ * Copyright(c) 2020-2024 Intel Corporation
+ */
+
+ #ifndef STA_INFO_H
+@@ -482,6 +482,8 @@ struct ieee80211_fragment_cache {
+ * same for non-MLD STA. This is used as key for searching link STA
+ * @link_id: Link ID uniquely identifying the link STA. This is 0 for non-MLD
+ * and set to the corresponding vif LinkId for MLD STA
++ * @op_mode_nss: NSS limit as set by operating mode notification, or 0
++ * @capa_nss: NSS limit as determined by local and peer capabilities
+ * @link_hash_node: hash node for rhashtable
+ * @sta: Points to the STA info
+ * @gtk: group keys negotiated with this station, if any
+@@ -518,6 +520,8 @@ struct link_sta_info {
+ u8 addr[ETH_ALEN];
+ u8 link_id;
+
++ u8 op_mode_nss, capa_nss;
++
+ struct rhlist_head link_hash_node;
+
+ struct sta_info *sta;
+diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
+index b3a5c3e96a720..bc13b1419981a 100644
+--- a/net/mac80211/vht.c
++++ b/net/mac80211/vht.c
+@@ -4,7 +4,7 @@
+ *
+ * Portions of this file
+ * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
+- * Copyright (C) 2018 - 2023 Intel Corporation
++ * Copyright (C) 2018 - 2024 Intel Corporation
+ */
+
+ #include <linux/ieee80211.h>
+@@ -541,15 +541,11 @@ ieee80211_sta_cur_vht_bw(struct link_sta_info *link_sta)
+ return bw;
+ }
+
+-void ieee80211_sta_set_rx_nss(struct link_sta_info *link_sta)
++void ieee80211_sta_init_nss(struct link_sta_info *link_sta)
+ {
+ u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, eht_rx_nss = 0, rx_nss;
+ bool support_160;
+
+- /* if we received a notification already don't overwrite it */
+- if (link_sta->pub->rx_nss)
+- return;
+-
+ if (link_sta->pub->eht_cap.has_eht) {
+ int i;
+ const u8 *rx_nss_mcs = (void *)&link_sta->pub->eht_cap.eht_mcs_nss_supp;
+@@ -627,7 +623,15 @@ void ieee80211_sta_set_rx_nss(struct link_sta_info *link_sta)
+ rx_nss = max(vht_rx_nss, ht_rx_nss);
+ rx_nss = max(he_rx_nss, rx_nss);
+ rx_nss = max(eht_rx_nss, rx_nss);
+- link_sta->pub->rx_nss = max_t(u8, 1, rx_nss);
++ rx_nss = max_t(u8, 1, rx_nss);
++ link_sta->capa_nss = rx_nss;
++
++ /* that shouldn't be set yet, but we can handle it anyway */
++ if (link_sta->op_mode_nss)
++ link_sta->pub->rx_nss =
++ min_t(u8, rx_nss, link_sta->op_mode_nss);
++ else
++ link_sta->pub->rx_nss = rx_nss;
+ }
+
+ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
+@@ -637,7 +641,7 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
+ enum ieee80211_sta_rx_bandwidth new_bw;
+ struct sta_opmode_info sta_opmode = {};
+ u32 changed = 0;
+- u8 nss, cur_nss;
++ u8 nss;
+
+ /* ignore - no support for BF yet */
+ if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF)
+@@ -647,23 +651,17 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
+ nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT;
+ nss += 1;
+
+- if (link_sta->pub->rx_nss != nss) {
+- cur_nss = link_sta->pub->rx_nss;
+- /* Reset rx_nss and call ieee80211_sta_set_rx_nss() which
+- * will set the same to max nss value calculated based on capability.
+- */
+- link_sta->pub->rx_nss = 0;
+- ieee80211_sta_set_rx_nss(link_sta);
+- /* Do not allow an nss change to rx_nss greater than max_nss
+- * negotiated and capped to APs capability during association.
+- */
+- if (nss <= link_sta->pub->rx_nss) {
+- link_sta->pub->rx_nss = nss;
+- sta_opmode.rx_nss = nss;
+- changed |= IEEE80211_RC_NSS_CHANGED;
+- sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED;
++ if (link_sta->op_mode_nss != nss) {
++ if (nss <= link_sta->capa_nss) {
++ link_sta->op_mode_nss = nss;
++
++ if (nss != link_sta->pub->rx_nss) {
++ link_sta->pub->rx_nss = nss;
++ changed |= IEEE80211_RC_NSS_CHANGED;
++ sta_opmode.rx_nss = link_sta->pub->rx_nss;
++ sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED;
++ }
+ } else {
+- link_sta->pub->rx_nss = cur_nss;
+ pr_warn_ratelimited("Ignoring NSS change in VHT Operating Mode Notification from %pM with invalid nss %d",
+ link_sta->pub->addr, nss);
+ }
+diff --git a/net/mac802154/llsec.c b/net/mac802154/llsec.c
+index 8d2eabc71bbeb..f13b07ebfb98a 100644
+--- a/net/mac802154/llsec.c
++++ b/net/mac802154/llsec.c
+@@ -265,19 +265,27 @@ int mac802154_llsec_key_add(struct mac802154_llsec *sec,
+ return -ENOMEM;
+ }
+
++static void mac802154_llsec_key_del_rcu(struct rcu_head *rcu)
++{
++ struct ieee802154_llsec_key_entry *pos;
++ struct mac802154_llsec_key *mkey;
++
++ pos = container_of(rcu, struct ieee802154_llsec_key_entry, rcu);
++ mkey = container_of(pos->key, struct mac802154_llsec_key, key);
++
++ llsec_key_put(mkey);
++ kfree_sensitive(pos);
++}
++
+ int mac802154_llsec_key_del(struct mac802154_llsec *sec,
+ const struct ieee802154_llsec_key_id *key)
+ {
+ struct ieee802154_llsec_key_entry *pos;
+
+ list_for_each_entry(pos, &sec->table.keys, list) {
+- struct mac802154_llsec_key *mkey;
+-
+- mkey = container_of(pos->key, struct mac802154_llsec_key, key);
+-
+ if (llsec_key_id_equal(&pos->id, key)) {
+ list_del_rcu(&pos->list);
+- llsec_key_put(mkey);
++ call_rcu(&pos->rcu, mac802154_llsec_key_del_rcu);
+ return 0;
+ }
+ }
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 6873c9815cd31..ec6266c1972c0 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -5008,6 +5008,9 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
+ if ((flags & (NFT_SET_CONSTANT | NFT_SET_TIMEOUT)) ==
+ (NFT_SET_CONSTANT | NFT_SET_TIMEOUT))
+ return -EOPNOTSUPP;
++ if ((flags & (NFT_SET_CONSTANT | NFT_SET_TIMEOUT)) ==
++ (NFT_SET_CONSTANT | NFT_SET_TIMEOUT))
++ return -EOPNOTSUPP;
+ }
+
+ desc.dtype = 0;
+diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
+index a161c64d1765e..838ad6541a17d 100644
+--- a/net/wireless/wext-core.c
++++ b/net/wireless/wext-core.c
+@@ -4,6 +4,7 @@
+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
+ * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
+ * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
++ * Copyright (C) 2024 Intel Corporation
+ *
+ * (As all part of the Linux kernel, this file is GPL)
+ */
+@@ -662,7 +663,8 @@ struct iw_statistics *get_wireless_stats(struct net_device *dev)
+ dev->ieee80211_ptr->wiphy->wext &&
+ dev->ieee80211_ptr->wiphy->wext->get_wireless_stats) {
+ wireless_warn_cfg80211_wext();
+- if (dev->ieee80211_ptr->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO)
++ if (dev->ieee80211_ptr->wiphy->flags & (WIPHY_FLAG_SUPPORTS_MLO |
++ WIPHY_FLAG_DISABLE_WEXT))
+ return NULL;
+ return dev->ieee80211_ptr->wiphy->wext->get_wireless_stats(dev);
+ }
+@@ -704,7 +706,8 @@ static iw_handler get_handler(struct net_device *dev, unsigned int cmd)
+ #ifdef CONFIG_CFG80211_WEXT
+ if (dev->ieee80211_ptr && dev->ieee80211_ptr->wiphy) {
+ wireless_warn_cfg80211_wext();
+- if (dev->ieee80211_ptr->wiphy->flags & WIPHY_FLAG_SUPPORTS_MLO)
++ if (dev->ieee80211_ptr->wiphy->flags & (WIPHY_FLAG_SUPPORTS_MLO |
++ WIPHY_FLAG_DISABLE_WEXT))
+ return NULL;
+ handlers = dev->ieee80211_ptr->wiphy->wext;
+ }
+diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
+index a9e552a1e9105..2f25a1de129d1 100644
+--- a/scripts/Makefile.extrawarn
++++ b/scripts/Makefile.extrawarn
+@@ -132,6 +132,8 @@ KBUILD_CFLAGS += $(call cc-disable-warning, pointer-to-enum-cast)
+ KBUILD_CFLAGS += -Wno-tautological-constant-out-of-range-compare
+ KBUILD_CFLAGS += $(call cc-disable-warning, unaligned-access)
+ KBUILD_CFLAGS += $(call cc-disable-warning, cast-function-type-strict)
++KBUILD_CFLAGS += -Wno-enum-compare-conditional
++KBUILD_CFLAGS += -Wno-enum-enum-conversion
+ endif
+
+ endif
+diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
+index 9a3dcaafb5b1e..cef8c466af80d 100644
+--- a/security/apparmor/lsm.c
++++ b/security/apparmor/lsm.c
+@@ -779,7 +779,7 @@ static int apparmor_sb_pivotroot(const struct path *old_path,
+ }
+
+ static int apparmor_getselfattr(unsigned int attr, struct lsm_ctx __user *lx,
+- size_t *size, u32 flags)
++ u32 *size, u32 flags)
+ {
+ int error = -ENOENT;
+ struct aa_task_ctx *ctx = task_ctx(current);
+@@ -924,7 +924,7 @@ static int do_setattr(u64 attr, void *value, size_t size)
+ }
+
+ static int apparmor_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
+- size_t size, u32 flags)
++ u32 size, u32 flags)
+ {
+ int rc;
+
+diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c
+index 898358f57fa08..6788e73b6681b 100644
+--- a/security/landlock/syscalls.c
++++ b/security/landlock/syscalls.c
+@@ -33,6 +33,18 @@
+ #include "ruleset.h"
+ #include "setup.h"
+
++static bool is_initialized(void)
++{
++ if (likely(landlock_initialized))
++ return true;
++
++ pr_warn_once(
++ "Disabled but requested by user space. "
++ "You should enable Landlock at boot time: "
++ "https://docs.kernel.org/userspace-api/landlock.html#boot-time-configuration\n");
++ return false;
++}
++
+ /**
+ * copy_min_struct_from_user - Safe future-proof argument copying
+ *
+@@ -173,7 +185,7 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
+ /* Build-time checks. */
+ build_check_abi();
+
+- if (!landlock_initialized)
++ if (!is_initialized())
+ return -EOPNOTSUPP;
+
+ if (flags) {
+@@ -398,7 +410,7 @@ SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd,
+ struct landlock_ruleset *ruleset;
+ int err;
+
+- if (!landlock_initialized)
++ if (!is_initialized())
+ return -EOPNOTSUPP;
+
+ /* No flag for now. */
+@@ -458,7 +470,7 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
+ struct landlock_cred_security *new_llcred;
+ int err;
+
+- if (!landlock_initialized)
++ if (!is_initialized())
+ return -EOPNOTSUPP;
+
+ /*
+diff --git a/security/lsm_syscalls.c b/security/lsm_syscalls.c
+index 5d391b1f7e694..8440948a690c9 100644
+--- a/security/lsm_syscalls.c
++++ b/security/lsm_syscalls.c
+@@ -53,7 +53,7 @@ u64 lsm_name_to_attr(const char *name)
+ * value indicating the reason for the error is returned.
+ */
+ SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *,
+- ctx, size_t, size, u32, flags)
++ ctx, u32, size, u32, flags)
+ {
+ return security_setselfattr(attr, ctx, size, flags);
+ }
+@@ -75,7 +75,7 @@ SYSCALL_DEFINE4(lsm_set_self_attr, unsigned int, attr, struct lsm_ctx __user *,
+ * a negative value indicating the error is returned.
+ */
+ SYSCALL_DEFINE4(lsm_get_self_attr, unsigned int, attr, struct lsm_ctx __user *,
+- ctx, size_t __user *, size, u32, flags)
++ ctx, u32 __user *, size, u32, flags)
+ {
+ return security_getselfattr(attr, ctx, size, flags);
+ }
+@@ -93,11 +93,11 @@ SYSCALL_DEFINE4(lsm_get_self_attr, unsigned int, attr, struct lsm_ctx __user *,
+ * required size. In all other cases a negative value indicating the
+ * error is returned.
+ */
+-SYSCALL_DEFINE3(lsm_list_modules, u64 __user *, ids, size_t __user *, size,
++SYSCALL_DEFINE3(lsm_list_modules, u64 __user *, ids, u32 __user *, size,
+ u32, flags)
+ {
+- size_t total_size = lsm_active_cnt * sizeof(*ids);
+- size_t usize;
++ u32 total_size = lsm_active_cnt * sizeof(*ids);
++ u32 usize;
+ int i;
+
+ if (flags)
+diff --git a/security/security.c b/security/security.c
+index 7035ee35a3930..a344b8fa5530d 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -780,12 +780,14 @@ static int lsm_superblock_alloc(struct super_block *sb)
+ * @id: LSM id
+ * @flags: LSM defined flags
+ *
+- * Fill all of the fields in a userspace lsm_ctx structure.
++ * Fill all of the fields in a userspace lsm_ctx structure. If @uctx is NULL
++ * simply calculate the required size to output via @utc_len and return
++ * success.
+ *
+ * Returns 0 on success, -E2BIG if userspace buffer is not large enough,
+ * -EFAULT on a copyout error, -ENOMEM if memory can't be allocated.
+ */
+-int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len,
++int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len,
+ void *val, size_t val_len,
+ u64 id, u64 flags)
+ {
+@@ -799,6 +801,10 @@ int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, size_t *uctx_len,
+ goto out;
+ }
+
++ /* no buffer - return success/0 and set @uctx_len to the req size */
++ if (!uctx)
++ goto out;
++
+ nctx = kzalloc(nctx_len, GFP_KERNEL);
+ if (nctx == NULL) {
+ rc = -ENOMEM;
+@@ -3918,14 +3924,14 @@ EXPORT_SYMBOL(security_d_instantiate);
+ * If @size is insufficient to contain the data -E2BIG is returned.
+ */
+ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
+- size_t __user *size, u32 flags)
++ u32 __user *size, u32 flags)
+ {
+ struct security_hook_list *hp;
+ struct lsm_ctx lctx = { .id = LSM_ID_UNDEF, };
+ u8 __user *base = (u8 __user *)uctx;
+- size_t total = 0;
+- size_t entrysize;
+- size_t left;
++ u32 entrysize;
++ u32 total = 0;
++ u32 left;
+ bool toobig = false;
+ bool single = false;
+ int count = 0;
+@@ -4011,7 +4017,7 @@ int security_getselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
+ * LSM specific failure.
+ */
+ int security_setselfattr(unsigned int attr, struct lsm_ctx __user *uctx,
+- size_t size, u32 flags)
++ u32 size, u32 flags)
+ {
+ struct security_hook_list *hp;
+ struct lsm_ctx *lctx;
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index 338b023a8c3ed..71e6e7079d7f7 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -6556,7 +6556,7 @@ static int selinux_lsm_setattr(u64 attr, void *value, size_t size)
+ * There will only ever be one attribute.
+ */
+ static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
+- size_t *size, u32 flags)
++ u32 *size, u32 flags)
+ {
+ int rc;
+ char *val = NULL;
+@@ -6571,7 +6571,7 @@ static int selinux_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
+ }
+
+ static int selinux_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
+- size_t size, u32 flags)
++ u32 size, u32 flags)
+ {
+ int rc;
+
+diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
+index 0fdbf04cc2583..6f9a80783a5a3 100644
+--- a/security/smack/smack_lsm.c
++++ b/security/smack/smack_lsm.c
+@@ -1314,7 +1314,8 @@ static int smack_inode_setxattr(struct mnt_idmap *idmap,
+ check_star = 1;
+ } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
+ check_priv = 1;
+- if (size != TRANS_TRUE_SIZE ||
++ if (!S_ISDIR(d_backing_inode(dentry)->i_mode) ||
++ size != TRANS_TRUE_SIZE ||
+ strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
+ rc = -EINVAL;
+ } else
+@@ -2855,6 +2856,15 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
+ if (value == NULL || size > SMK_LONGLABEL || size == 0)
+ return -EINVAL;
+
++ if (strcmp(name, XATTR_SMACK_TRANSMUTE) == 0) {
++ if (!S_ISDIR(inode->i_mode) || size != TRANS_TRUE_SIZE ||
++ strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
++ return -EINVAL;
++
++ nsp->smk_flags |= SMK_INODE_TRANSMUTE;
++ return 0;
++ }
++
+ skp = smk_import_entry(value, size);
+ if (IS_ERR(skp))
+ return PTR_ERR(skp);
+@@ -3641,7 +3651,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
+ * There will only ever be one attribute.
+ */
+ static int smack_getselfattr(unsigned int attr, struct lsm_ctx __user *ctx,
+- size_t *size, u32 flags)
++ u32 *size, u32 flags)
+ {
+ int rc;
+ struct smack_known *skp;
+@@ -3762,7 +3772,7 @@ static int do_setattr(u64 attr, void *value, size_t size)
+ * Returns 0 on success, an error code otherwise.
+ */
+ static int smack_setselfattr(unsigned int attr, struct lsm_ctx *ctx,
+- size_t size, u32 flags)
++ u32 size, u32 flags)
+ {
+ int rc;
+
+diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c
+index 7aef93126ed0c..693c1b81a23c2 100644
+--- a/sound/pci/hda/tas2781_hda_i2c.c
++++ b/sound/pci/hda/tas2781_hda_i2c.c
+@@ -89,7 +89,7 @@ struct tas2781_hda {
+ struct snd_kcontrol *dsp_prog_ctl;
+ struct snd_kcontrol *dsp_conf_ctl;
+ struct snd_kcontrol *prof_ctl;
+- struct snd_kcontrol *snd_ctls[3];
++ struct snd_kcontrol *snd_ctls[2];
+ };
+
+ static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data)
+@@ -197,8 +197,12 @@ static int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol,
+ {
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+
++ mutex_lock(&tas_priv->codec_lock);
++
+ ucontrol->value.integer.value[0] = tas_priv->rcabin.profile_cfg_id;
+
++ mutex_unlock(&tas_priv->codec_lock);
++
+ return 0;
+ }
+
+@@ -212,11 +216,15 @@ static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
+
+ val = clamp(nr_profile, 0, max);
+
++ mutex_lock(&tas_priv->codec_lock);
++
+ if (tas_priv->rcabin.profile_cfg_id != val) {
+ tas_priv->rcabin.profile_cfg_id = val;
+ ret = 1;
+ }
+
++ mutex_unlock(&tas_priv->codec_lock);
++
+ return ret;
+ }
+
+@@ -253,8 +261,12 @@ static int tasdevice_program_get(struct snd_kcontrol *kcontrol,
+ {
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+
++ mutex_lock(&tas_priv->codec_lock);
++
+ ucontrol->value.integer.value[0] = tas_priv->cur_prog;
+
++ mutex_unlock(&tas_priv->codec_lock);
++
+ return 0;
+ }
+
+@@ -269,11 +281,15 @@ static int tasdevice_program_put(struct snd_kcontrol *kcontrol,
+
+ val = clamp(nr_program, 0, max);
+
++ mutex_lock(&tas_priv->codec_lock);
++
+ if (tas_priv->cur_prog != val) {
+ tas_priv->cur_prog = val;
+ ret = 1;
+ }
+
++ mutex_unlock(&tas_priv->codec_lock);
++
+ return ret;
+ }
+
+@@ -282,8 +298,12 @@ static int tasdevice_config_get(struct snd_kcontrol *kcontrol,
+ {
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+
++ mutex_lock(&tas_priv->codec_lock);
++
+ ucontrol->value.integer.value[0] = tas_priv->cur_conf;
+
++ mutex_unlock(&tas_priv->codec_lock);
++
+ return 0;
+ }
+
+@@ -298,33 +318,16 @@ static int tasdevice_config_put(struct snd_kcontrol *kcontrol,
+
+ val = clamp(nr_config, 0, max);
+
++ mutex_lock(&tas_priv->codec_lock);
++
+ if (tas_priv->cur_conf != val) {
+ tas_priv->cur_conf = val;
+ ret = 1;
+ }
+
+- return ret;
+-}
++ mutex_unlock(&tas_priv->codec_lock);
+
+-/*
+- * tas2781_digital_getvol - get the volum control
+- * @kcontrol: control pointer
+- * @ucontrol: User data
+- * Customer Kcontrol for tas2781 is primarily for regmap booking, paging
+- * depends on internal regmap mechanism.
+- * tas2781 contains book and page two-level register map, especially
+- * book switching will set the register BXXP00R7F, after switching to the
+- * correct book, then leverage the mechanism for paging to access the
+- * register.
+- */
+-static int tas2781_digital_getvol(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+- struct soc_mixer_control *mc =
+- (struct soc_mixer_control *)kcontrol->private_value;
+-
+- return tasdevice_digital_getvol(tas_priv, ucontrol, mc);
++ return ret;
+ }
+
+ static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,
+@@ -333,19 +336,15 @@ static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
++ int ret;
+
+- return tasdevice_amp_getvol(tas_priv, ucontrol, mc);
+-}
++ mutex_lock(&tas_priv->codec_lock);
+
+-static int tas2781_digital_putvol(struct snd_kcontrol *kcontrol,
+- struct snd_ctl_elem_value *ucontrol)
+-{
+- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+- struct soc_mixer_control *mc =
+- (struct soc_mixer_control *)kcontrol->private_value;
++ ret = tasdevice_amp_getvol(tas_priv, ucontrol, mc);
++
++ mutex_unlock(&tas_priv->codec_lock);
+
+- /* The check of the given value is in tasdevice_digital_putvol. */
+- return tasdevice_digital_putvol(tas_priv, ucontrol, mc);
++ return ret;
+ }
+
+ static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
+@@ -354,9 +353,16 @@ static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
++ int ret;
++
++ mutex_lock(&tas_priv->codec_lock);
+
+ /* The check of the given value is in tasdevice_amp_putvol. */
+- return tasdevice_amp_putvol(tas_priv, ucontrol, mc);
++ ret = tasdevice_amp_putvol(tas_priv, ucontrol, mc);
++
++ mutex_unlock(&tas_priv->codec_lock);
++
++ return ret;
+ }
+
+ static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
+@@ -364,10 +370,14 @@ static int tas2781_force_fwload_get(struct snd_kcontrol *kcontrol,
+ {
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+
++ mutex_lock(&tas_priv->codec_lock);
++
+ ucontrol->value.integer.value[0] = (int)tas_priv->force_fwload_status;
+ dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__,
+ tas_priv->force_fwload_status ? "ON" : "OFF");
+
++ mutex_unlock(&tas_priv->codec_lock);
++
+ return 0;
+ }
+
+@@ -377,6 +387,8 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+ bool change, val = (bool)ucontrol->value.integer.value[0];
+
++ mutex_lock(&tas_priv->codec_lock);
++
+ if (tas_priv->force_fwload_status == val)
+ change = false;
+ else {
+@@ -386,6 +398,8 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
+ dev_dbg(tas_priv->dev, "%s : Force FWload %s\n", __func__,
+ tas_priv->force_fwload_status ? "ON" : "OFF");
+
++ mutex_unlock(&tas_priv->codec_lock);
++
+ return change;
+ }
+
+@@ -393,9 +407,6 @@ static const struct snd_kcontrol_new tas2781_snd_controls[] = {
+ ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Gain", TAS2781_AMP_LEVEL,
+ 1, 0, 20, 0, tas2781_amp_getvol,
+ tas2781_amp_putvol, amp_vol_tlv),
+- ACARD_SINGLE_RANGE_EXT_TLV("Speaker Digital Gain", TAS2781_DVC_LVL,
+- 0, 0, 200, 1, tas2781_digital_getvol,
+- tas2781_digital_putvol, dvc_tlv),
+ ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load", 0,
+ tas2781_force_fwload_get, tas2781_force_fwload_put),
+ };
+diff --git a/sound/sh/aica.c b/sound/sh/aica.c
+index 320ac792c7fe2..3182c634464d4 100644
+--- a/sound/sh/aica.c
++++ b/sound/sh/aica.c
+@@ -278,7 +278,8 @@ static void run_spu_dma(struct work_struct *work)
+ dreamcastcard->clicks++;
+ if (unlikely(dreamcastcard->clicks >= AICA_PERIOD_NUMBER))
+ dreamcastcard->clicks %= AICA_PERIOD_NUMBER;
+- mod_timer(&dreamcastcard->timer, jiffies + 1);
++ if (snd_pcm_running(dreamcastcard->substream))
++ mod_timer(&dreamcastcard->timer, jiffies + 1);
+ }
+ }
+
+@@ -290,6 +291,8 @@ static void aica_period_elapsed(struct timer_list *t)
+ /*timer function - so cannot sleep */
+ int play_period;
+ struct snd_pcm_runtime *runtime;
++ if (!snd_pcm_running(substream))
++ return;
+ runtime = substream->runtime;
+ dreamcastcard = substream->pcm->private_data;
+ /* Have we played out an additional period? */
+@@ -350,12 +353,19 @@ static int snd_aicapcm_pcm_open(struct snd_pcm_substream
+ return 0;
+ }
+
++static int snd_aicapcm_pcm_sync_stop(struct snd_pcm_substream *substream)
++{
++ struct snd_card_aica *dreamcastcard = substream->pcm->private_data;
++
++ del_timer_sync(&dreamcastcard->timer);
++ cancel_work_sync(&dreamcastcard->spu_dma_work);
++ return 0;
++}
++
+ static int snd_aicapcm_pcm_close(struct snd_pcm_substream
+ *substream)
+ {
+ struct snd_card_aica *dreamcastcard = substream->pcm->private_data;
+- flush_work(&(dreamcastcard->spu_dma_work));
+- del_timer(&dreamcastcard->timer);
+ dreamcastcard->substream = NULL;
+ kfree(dreamcastcard->channel);
+ spu_disable();
+@@ -401,6 +411,7 @@ static const struct snd_pcm_ops snd_aicapcm_playback_ops = {
+ .prepare = snd_aicapcm_pcm_prepare,
+ .trigger = snd_aicapcm_pcm_trigger,
+ .pointer = snd_aicapcm_pcm_pointer,
++ .sync_stop = snd_aicapcm_pcm_sync_stop,
+ };
+
+ /* TO DO: set up to handle more than one pcm instance */
+diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
+index 90360f8b3e81b..1d1452c29ed02 100644
+--- a/sound/soc/amd/yc/acp6x-mach.c
++++ b/sound/soc/amd/yc/acp6x-mach.c
+@@ -199,13 +199,6 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "21HY"),
+ }
+ },
+- {
+- .driver_data = &acp6x_card,
+- .matches = {
+- DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+- DMI_MATCH(DMI_PRODUCT_NAME, "21J2"),
+- }
+- },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+diff --git a/sound/soc/amd/yc/pci-acp6x.c b/sound/soc/amd/yc/pci-acp6x.c
+index 694b8e3139024..7af6a349b1d41 100644
+--- a/sound/soc/amd/yc/pci-acp6x.c
++++ b/sound/soc/amd/yc/pci-acp6x.c
+@@ -162,7 +162,6 @@ static int snd_acp6x_probe(struct pci_dev *pci,
+ /* Yellow Carp device check */
+ switch (pci->revision) {
+ case 0x60:
+- case 0x63:
+ case 0x6f:
+ break;
+ default:
+diff --git a/tools/include/linux/btf_ids.h b/tools/include/linux/btf_ids.h
+index 72535f00572f6..72ea363d434db 100644
+--- a/tools/include/linux/btf_ids.h
++++ b/tools/include/linux/btf_ids.h
+@@ -3,6 +3,8 @@
+ #ifndef _LINUX_BTF_IDS_H
+ #define _LINUX_BTF_IDS_H
+
++#include <linux/types.h> /* for u32 */
++
+ struct btf_id_set {
+ u32 cnt;
+ u32 ids[];
+diff --git a/tools/testing/selftests/lsm/common.h b/tools/testing/selftests/lsm/common.h
+index d404329e5eeb7..06d12110d241b 100644
+--- a/tools/testing/selftests/lsm/common.h
++++ b/tools/testing/selftests/lsm/common.h
+@@ -7,7 +7,7 @@
+
+ #ifndef lsm_get_self_attr
+ static inline int lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx,
+- size_t *size, __u32 flags)
++ __u32 *size, __u32 flags)
+ {
+ return syscall(__NR_lsm_get_self_attr, attr, ctx, size, flags);
+ }
+@@ -15,14 +15,14 @@ static inline int lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx,
+
+ #ifndef lsm_set_self_attr
+ static inline int lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx,
+- size_t size, __u32 flags)
++ __u32 size, __u32 flags)
+ {
+ return syscall(__NR_lsm_set_self_attr, attr, ctx, size, flags);
+ }
+ #endif
+
+ #ifndef lsm_list_modules
+-static inline int lsm_list_modules(__u64 *ids, size_t *size, __u32 flags)
++static inline int lsm_list_modules(__u64 *ids, __u32 *size, __u32 flags)
+ {
+ return syscall(__NR_lsm_list_modules, ids, size, flags);
+ }
+diff --git a/tools/testing/selftests/lsm/lsm_get_self_attr_test.c b/tools/testing/selftests/lsm/lsm_get_self_attr_test.c
+index e0e313d9047a3..df215e4aa63fe 100644
+--- a/tools/testing/selftests/lsm/lsm_get_self_attr_test.c
++++ b/tools/testing/selftests/lsm/lsm_get_self_attr_test.c
+@@ -40,7 +40,7 @@ TEST(size_null_lsm_get_self_attr)
+ TEST(ctx_null_lsm_get_self_attr)
+ {
+ const long page_size = sysconf(_SC_PAGESIZE);
+- size_t size = page_size;
++ __u32 size = page_size;
+ int rc;
+
+ rc = lsm_get_self_attr(LSM_ATTR_CURRENT, NULL, &size, 0);
+@@ -57,7 +57,7 @@ TEST(size_too_small_lsm_get_self_attr)
+ {
+ const long page_size = sysconf(_SC_PAGESIZE);
+ struct lsm_ctx *ctx = calloc(page_size, 1);
+- size_t size = 1;
++ __u32 size = 1;
+
+ ASSERT_NE(NULL, ctx);
+ errno = 0;
+@@ -77,7 +77,7 @@ TEST(flags_zero_lsm_get_self_attr)
+ const long page_size = sysconf(_SC_PAGESIZE);
+ struct lsm_ctx *ctx = calloc(page_size, 1);
+ __u64 *syscall_lsms = calloc(page_size, 1);
+- size_t size;
++ __u32 size;
+ int lsmcount;
+ int i;
+
+@@ -117,7 +117,7 @@ TEST(flags_overset_lsm_get_self_attr)
+ {
+ const long page_size = sysconf(_SC_PAGESIZE);
+ struct lsm_ctx *ctx = calloc(page_size, 1);
+- size_t size;
++ __u32 size;
+
+ ASSERT_NE(NULL, ctx);
+
+@@ -140,7 +140,7 @@ TEST(flags_overset_lsm_get_self_attr)
+ TEST(basic_lsm_get_self_attr)
+ {
+ const long page_size = sysconf(_SC_PAGESIZE);
+- size_t size = page_size;
++ __u32 size = page_size;
+ struct lsm_ctx *ctx = calloc(page_size, 1);
+ struct lsm_ctx *tctx = NULL;
+ __u64 *syscall_lsms = calloc(page_size, 1);
+diff --git a/tools/testing/selftests/lsm/lsm_list_modules_test.c b/tools/testing/selftests/lsm/lsm_list_modules_test.c
+index 9df29b1e34978..868641dbb309c 100644
+--- a/tools/testing/selftests/lsm/lsm_list_modules_test.c
++++ b/tools/testing/selftests/lsm/lsm_list_modules_test.c
+@@ -31,7 +31,7 @@ TEST(size_null_lsm_list_modules)
+ TEST(ids_null_lsm_list_modules)
+ {
+ const long page_size = sysconf(_SC_PAGESIZE);
+- size_t size = page_size;
++ __u32 size = page_size;
+
+ errno = 0;
+ ASSERT_EQ(-1, lsm_list_modules(NULL, &size, 0));
+@@ -43,7 +43,7 @@ TEST(size_too_small_lsm_list_modules)
+ {
+ const long page_size = sysconf(_SC_PAGESIZE);
+ __u64 *syscall_lsms = calloc(page_size, 1);
+- size_t size = 1;
++ __u32 size = 1;
+
+ ASSERT_NE(NULL, syscall_lsms);
+ errno = 0;
+@@ -58,7 +58,7 @@ TEST(flags_set_lsm_list_modules)
+ {
+ const long page_size = sysconf(_SC_PAGESIZE);
+ __u64 *syscall_lsms = calloc(page_size, 1);
+- size_t size = page_size;
++ __u32 size = page_size;
+
+ ASSERT_NE(NULL, syscall_lsms);
+ errno = 0;
+@@ -72,7 +72,7 @@ TEST(flags_set_lsm_list_modules)
+ TEST(correct_lsm_list_modules)
+ {
+ const long page_size = sysconf(_SC_PAGESIZE);
+- size_t size = page_size;
++ __u32 size = page_size;
+ __u64 *syscall_lsms = calloc(page_size, 1);
+ char *sysfs_lsms = calloc(page_size, 1);
+ char *name;
+diff --git a/tools/testing/selftests/lsm/lsm_set_self_attr_test.c b/tools/testing/selftests/lsm/lsm_set_self_attr_test.c
+index e9712c6cf5962..66dec47e3ca3f 100644
+--- a/tools/testing/selftests/lsm/lsm_set_self_attr_test.c
++++ b/tools/testing/selftests/lsm/lsm_set_self_attr_test.c
+@@ -25,7 +25,7 @@ TEST(size_too_small_lsm_set_self_attr)
+ {
+ const long page_size = sysconf(_SC_PAGESIZE);
+ struct lsm_ctx *ctx = calloc(page_size, 1);
+- size_t size = page_size;
++ __u32 size = page_size;
+
+ ASSERT_NE(NULL, ctx);
+ if (attr_lsm_count()) {
+@@ -41,7 +41,7 @@ TEST(flags_zero_lsm_set_self_attr)
+ {
+ const long page_size = sysconf(_SC_PAGESIZE);
+ struct lsm_ctx *ctx = calloc(page_size, 1);
+- size_t size = page_size;
++ __u32 size = page_size;
+
+ ASSERT_NE(NULL, ctx);
+ if (attr_lsm_count()) {
+@@ -57,7 +57,7 @@ TEST(flags_overset_lsm_set_self_attr)
+ {
+ const long page_size = sysconf(_SC_PAGESIZE);
+ char *ctx = calloc(page_size, 1);
+- size_t size = page_size;
++ __u32 size = page_size;
+ struct lsm_ctx *tctx = (struct lsm_ctx *)ctx;
+
+ ASSERT_NE(NULL, ctx);
+diff --git a/tools/testing/selftests/mm/gup_test.c b/tools/testing/selftests/mm/gup_test.c
+index cbe99594d319b..18a49c70d4c63 100644
+--- a/tools/testing/selftests/mm/gup_test.c
++++ b/tools/testing/selftests/mm/gup_test.c
+@@ -203,7 +203,7 @@ int main(int argc, char **argv)
+ ksft_print_header();
+ ksft_set_plan(nthreads);
+
+- filed = open(file, O_RDWR|O_CREAT);
++ filed = open(file, O_RDWR|O_CREAT, 0664);
+ if (filed < 0)
+ ksft_exit_fail_msg("Unable to open %s: %s\n", file, strerror(errno));
+
+diff --git a/tools/testing/selftests/mm/soft-dirty.c b/tools/testing/selftests/mm/soft-dirty.c
+index cc5f144430d4d..7dbfa53d93a05 100644
+--- a/tools/testing/selftests/mm/soft-dirty.c
++++ b/tools/testing/selftests/mm/soft-dirty.c
+@@ -137,7 +137,7 @@ static void test_mprotect(int pagemap_fd, int pagesize, bool anon)
+ if (!map)
+ ksft_exit_fail_msg("anon mmap failed\n");
+ } else {
+- test_fd = open(fname, O_RDWR | O_CREAT);
++ test_fd = open(fname, O_RDWR | O_CREAT, 0664);
+ if (test_fd < 0) {
+ ksft_test_result_skip("Test %s open() file failed\n", __func__);
+ return;
+diff --git a/tools/testing/selftests/mm/split_huge_page_test.c b/tools/testing/selftests/mm/split_huge_page_test.c
+index 0e74635c8c3d9..dff3be23488b4 100644
+--- a/tools/testing/selftests/mm/split_huge_page_test.c
++++ b/tools/testing/selftests/mm/split_huge_page_test.c
+@@ -253,7 +253,7 @@ void split_file_backed_thp(void)
+ goto cleanup;
+ }
+
+- fd = open(testfile, O_CREAT|O_WRONLY);
++ fd = open(testfile, O_CREAT|O_WRONLY, 0664);
+ if (fd == -1) {
+ perror("Cannot open testing file\n");
+ goto cleanup;
+diff --git a/tools/testing/selftests/mm/uffd-common.c b/tools/testing/selftests/mm/uffd-common.c
+index b0ac0ec2356d6..7ad6ba660c7d6 100644
+--- a/tools/testing/selftests/mm/uffd-common.c
++++ b/tools/testing/selftests/mm/uffd-common.c
+@@ -18,6 +18,7 @@ bool test_uffdio_wp = true;
+ unsigned long long *count_verify;
+ uffd_test_ops_t *uffd_test_ops;
+ uffd_test_case_ops_t *uffd_test_case_ops;
++atomic_bool ready_for_fork;
+
+ static int uffd_mem_fd_create(off_t mem_size, bool hugetlb)
+ {
+@@ -518,6 +519,8 @@ void *uffd_poll_thread(void *arg)
+ pollfd[1].fd = pipefd[cpu*2];
+ pollfd[1].events = POLLIN;
+
++ ready_for_fork = true;
++
+ for (;;) {
+ ret = poll(pollfd, 2, -1);
+ if (ret <= 0) {
+diff --git a/tools/testing/selftests/mm/uffd-common.h b/tools/testing/selftests/mm/uffd-common.h
+index cb055282c89c9..cc5629c3d2aa1 100644
+--- a/tools/testing/selftests/mm/uffd-common.h
++++ b/tools/testing/selftests/mm/uffd-common.h
+@@ -32,6 +32,7 @@
+ #include <inttypes.h>
+ #include <stdint.h>
+ #include <sys/random.h>
++#include <stdatomic.h>
+
+ #include "../kselftest.h"
+ #include "vm_util.h"
+@@ -103,6 +104,7 @@ extern bool map_shared;
+ extern bool test_uffdio_wp;
+ extern unsigned long long *count_verify;
+ extern volatile bool test_uffdio_copy_eexist;
++extern atomic_bool ready_for_fork;
+
+ extern uffd_test_ops_t anon_uffd_test_ops;
+ extern uffd_test_ops_t shmem_uffd_test_ops;
+diff --git a/tools/testing/selftests/mm/uffd-unit-tests.c b/tools/testing/selftests/mm/uffd-unit-tests.c
+index 2b9f8cc52639d..21ec23206ab44 100644
+--- a/tools/testing/selftests/mm/uffd-unit-tests.c
++++ b/tools/testing/selftests/mm/uffd-unit-tests.c
+@@ -775,6 +775,8 @@ static void uffd_sigbus_test_common(bool wp)
+ char c;
+ struct uffd_args args = { 0 };
+
++ ready_for_fork = false;
++
+ fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
+
+ if (uffd_register(uffd, area_dst, nr_pages * page_size,
+@@ -790,6 +792,9 @@ static void uffd_sigbus_test_common(bool wp)
+ if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args))
+ err("uffd_poll_thread create");
+
++ while (!ready_for_fork)
++ ; /* Wait for the poll_thread to start executing before forking */
++
+ pid = fork();
+ if (pid < 0)
+ err("fork");
+@@ -829,6 +834,8 @@ static void uffd_events_test_common(bool wp)
+ char c;
+ struct uffd_args args = { 0 };
+
++ ready_for_fork = false;
++
+ fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
+ if (uffd_register(uffd, area_dst, nr_pages * page_size,
+ true, wp, false))
+@@ -838,6 +845,9 @@ static void uffd_events_test_common(bool wp)
+ if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args))
+ err("uffd_poll_thread create");
+
++ while (!ready_for_fork)
++ ; /* Wait for the poll_thread to start executing before forking */
++
+ pid = fork();
+ if (pid < 0)
+ err("fork");
+@@ -1427,7 +1437,8 @@ uffd_test_case_t uffd_tests[] = {
+ .uffd_fn = uffd_sigbus_wp_test,
+ .mem_targets = MEM_ALL,
+ .uffd_feature_required = UFFD_FEATURE_SIGBUS |
+- UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_PAGEFAULT_FLAG_WP,
++ UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_PAGEFAULT_FLAG_WP |
++ UFFD_FEATURE_WP_HUGETLBFS_SHMEM,
+ },
+ {
+ .name = "events",
+diff --git a/tools/testing/selftests/mqueue/setting b/tools/testing/selftests/mqueue/setting
+new file mode 100644
+index 0000000000000..a953c96aa16e1
+--- /dev/null
++++ b/tools/testing/selftests/mqueue/setting
+@@ -0,0 +1 @@
++timeout=180
+diff --git a/tools/testing/selftests/wireguard/qemu/arch/riscv32.config b/tools/testing/selftests/wireguard/qemu/arch/riscv32.config
+index 2fc36efb166dc..a7f8e8a956259 100644
+--- a/tools/testing/selftests/wireguard/qemu/arch/riscv32.config
++++ b/tools/testing/selftests/wireguard/qemu/arch/riscv32.config
+@@ -3,6 +3,7 @@ CONFIG_ARCH_RV32I=y
+ CONFIG_MMU=y
+ CONFIG_FPU=y
+ CONFIG_SOC_VIRT=y
++CONFIG_RISCV_ISA_FALLBACK=y
+ CONFIG_SERIAL_8250=y
+ CONFIG_SERIAL_8250_CONSOLE=y
+ CONFIG_SERIAL_OF_PLATFORM=y
+diff --git a/tools/testing/selftests/wireguard/qemu/arch/riscv64.config b/tools/testing/selftests/wireguard/qemu/arch/riscv64.config
+index dc266f3b19155..daeb3e5e09658 100644
+--- a/tools/testing/selftests/wireguard/qemu/arch/riscv64.config
++++ b/tools/testing/selftests/wireguard/qemu/arch/riscv64.config
+@@ -2,6 +2,7 @@ CONFIG_ARCH_RV64I=y
+ CONFIG_MMU=y
+ CONFIG_FPU=y
+ CONFIG_SOC_VIRT=y
++CONFIG_RISCV_ISA_FALLBACK=y
+ CONFIG_SERIAL_8250=y
+ CONFIG_SERIAL_8250_CONSOLE=y
+ CONFIG_SERIAL_OF_PLATFORM=y
+diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c
+index e033c79d528e0..28658b9e0d968 100644
+--- a/virt/kvm/async_pf.c
++++ b/virt/kvm/async_pf.c
+@@ -87,7 +87,27 @@ static void async_pf_execute(struct work_struct *work)
+ __kvm_vcpu_wake_up(vcpu);
+
+ mmput(mm);
+- kvm_put_kvm(vcpu->kvm);
++}
++
++static void kvm_flush_and_free_async_pf_work(struct kvm_async_pf *work)
++{
++ /*
++ * The async #PF is "done", but KVM must wait for the work item itself,
++ * i.e. async_pf_execute(), to run to completion. If KVM is a module,
++ * KVM must ensure *no* code owned by the KVM (the module) can be run
++ * after the last call to module_put(). Note, flushing the work item
++ * is always required when the item is taken off the completion queue.
++ * E.g. even if the vCPU handles the item in the "normal" path, the VM
++ * could be terminated before async_pf_execute() completes.
++ *
++ * Wake all events skip the queue and go straight done, i.e. don't
++ * need to be flushed (but sanity check that the work wasn't queued).
++ */
++ if (work->wakeup_all)
++ WARN_ON_ONCE(work->work.func);
++ else
++ flush_work(&work->work);
++ kmem_cache_free(async_pf_cache, work);
+ }
+
+ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu)
+@@ -114,7 +134,6 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu)
+ #else
+ if (cancel_work_sync(&work->work)) {
+ mmput(work->mm);
+- kvm_put_kvm(vcpu->kvm); /* == work->vcpu->kvm */
+ kmem_cache_free(async_pf_cache, work);
+ }
+ #endif
+@@ -126,7 +145,10 @@ void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu)
+ list_first_entry(&vcpu->async_pf.done,
+ typeof(*work), link);
+ list_del(&work->link);
+- kmem_cache_free(async_pf_cache, work);
++
++ spin_unlock(&vcpu->async_pf.lock);
++ kvm_flush_and_free_async_pf_work(work);
++ spin_lock(&vcpu->async_pf.lock);
+ }
+ spin_unlock(&vcpu->async_pf.lock);
+
+@@ -151,7 +173,7 @@ void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu)
+
+ list_del(&work->queue);
+ vcpu->async_pf.queued--;
+- kmem_cache_free(async_pf_cache, work);
++ kvm_flush_and_free_async_pf_work(work);
+ }
+ }
+
+@@ -186,7 +208,6 @@ bool kvm_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
+ work->arch = *arch;
+ work->mm = current->mm;
+ mmget(work->mm);
+- kvm_get_kvm(work->vcpu->kvm);
+
+ INIT_WORK(&work->work, async_pf_execute);
+
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-04 19:05 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-04-04 19:05 UTC (permalink / raw
To: gentoo-commits
commit: 0d78c2ebad9a1ed5fc2d9fddee412d3890647efc
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Thu Apr 4 19:04:59 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Thu Apr 4 19:04:59 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=0d78c2eb
Linux patch 6.8.4
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1003_linux-6.8.4.patch | 1218 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1222 insertions(+)
diff --git a/0000_README b/0000_README
index b8286427..36e97fef 100644
--- a/0000_README
+++ b/0000_README
@@ -55,6 +55,10 @@ Patch: 1002_linux-6.8.3.patch
From: https://www.kernel.org
Desc: Linux 6.8.3
+Patch: 1003_linux-6.8.4.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.4
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1003_linux-6.8.4.patch b/1003_linux-6.8.4.patch
new file mode 100644
index 00000000..82e75213
--- /dev/null
+++ b/1003_linux-6.8.4.patch
@@ -0,0 +1,1218 @@
+diff --git a/Makefile b/Makefile
+index a78379891d221..c436247d750c7 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 3
++SUBLEVEL = 4
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
+index 515e7958c6c10..2cc0a9606175f 100644
+--- a/include/linux/workqueue.h
++++ b/include/linux/workqueue.h
+@@ -391,13 +391,6 @@ enum {
+ WQ_MAX_ACTIVE = 512, /* I like 512, better ideas? */
+ WQ_UNBOUND_MAX_ACTIVE = WQ_MAX_ACTIVE,
+ WQ_DFL_ACTIVE = WQ_MAX_ACTIVE / 2,
+-
+- /*
+- * Per-node default cap on min_active. Unless explicitly set, min_active
+- * is set to min(max_active, WQ_DFL_MIN_ACTIVE). For more details, see
+- * workqueue_struct->min_active definition.
+- */
+- WQ_DFL_MIN_ACTIVE = 8,
+ };
+
+ /*
+@@ -440,33 +433,11 @@ extern struct workqueue_struct *system_freezable_power_efficient_wq;
+ * alloc_workqueue - allocate a workqueue
+ * @fmt: printf format for the name of the workqueue
+ * @flags: WQ_* flags
+- * @max_active: max in-flight work items, 0 for default
++ * @max_active: max in-flight work items per CPU, 0 for default
+ * remaining args: args for @fmt
+ *
+- * For a per-cpu workqueue, @max_active limits the number of in-flight work
+- * items for each CPU. e.g. @max_active of 1 indicates that each CPU can be
+- * executing at most one work item for the workqueue.
+- *
+- * For unbound workqueues, @max_active limits the number of in-flight work items
+- * for the whole system. e.g. @max_active of 16 indicates that that there can be
+- * at most 16 work items executing for the workqueue in the whole system.
+- *
+- * As sharing the same active counter for an unbound workqueue across multiple
+- * NUMA nodes can be expensive, @max_active is distributed to each NUMA node
+- * according to the proportion of the number of online CPUs and enforced
+- * independently.
+- *
+- * Depending on online CPU distribution, a node may end up with per-node
+- * max_active which is significantly lower than @max_active, which can lead to
+- * deadlocks if the per-node concurrency limit is lower than the maximum number
+- * of interdependent work items for the workqueue.
+- *
+- * To guarantee forward progress regardless of online CPU distribution, the
+- * concurrency limit on every node is guaranteed to be equal to or greater than
+- * min_active which is set to min(@max_active, %WQ_DFL_MIN_ACTIVE). This means
+- * that the sum of per-node max_active's may be larger than @max_active.
+- *
+- * For detailed information on %WQ_* flags, please refer to
++ * Allocate a workqueue with the specified parameters. For detailed
++ * information on WQ_* flags, please refer to
+ * Documentation/core-api/workqueue.rst.
+ *
+ * RETURNS:
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index 781900b148b67..7b482a26d7419 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -108,7 +108,7 @@ enum {
+ RESCUER_NICE_LEVEL = MIN_NICE,
+ HIGHPRI_NICE_LEVEL = MIN_NICE,
+
+- WQ_NAME_LEN = 32,
++ WQ_NAME_LEN = 24,
+ };
+
+ /*
+@@ -122,9 +122,6 @@ enum {
+ *
+ * L: pool->lock protected. Access with pool->lock held.
+ *
+- * LN: pool->lock and wq_node_nr_active->lock protected for writes. Either for
+- * reads.
+- *
+ * K: Only modified by worker while holding pool->lock. Can be safely read by
+ * self, while holding pool->lock or from IRQ context if %current is the
+ * kworker.
+@@ -146,9 +143,6 @@ enum {
+ *
+ * WR: wq->mutex protected for writes. RCU protected for reads.
+ *
+- * WO: wq->mutex protected for writes. Updated with WRITE_ONCE() and can be read
+- * with READ_ONCE() without locking.
+- *
+ * MD: wq_mayday_lock protected.
+ *
+ * WD: Used internally by the watchdog.
+@@ -246,18 +240,18 @@ struct pool_workqueue {
+ * pwq->inactive_works instead of pool->worklist and marked with
+ * WORK_STRUCT_INACTIVE.
+ *
+- * All work items marked with WORK_STRUCT_INACTIVE do not participate in
+- * nr_active and all work items in pwq->inactive_works are marked with
+- * WORK_STRUCT_INACTIVE. But not all WORK_STRUCT_INACTIVE work items are
+- * in pwq->inactive_works. Some of them are ready to run in
+- * pool->worklist or worker->scheduled. Those work itmes are only struct
+- * wq_barrier which is used for flush_work() and should not participate
+- * in nr_active. For non-barrier work item, it is marked with
+- * WORK_STRUCT_INACTIVE iff it is in pwq->inactive_works.
++ * All work items marked with WORK_STRUCT_INACTIVE do not participate
++ * in pwq->nr_active and all work items in pwq->inactive_works are
++ * marked with WORK_STRUCT_INACTIVE. But not all WORK_STRUCT_INACTIVE
++ * work items are in pwq->inactive_works. Some of them are ready to
++ * run in pool->worklist or worker->scheduled. Those work itmes are
++ * only struct wq_barrier which is used for flush_work() and should
++ * not participate in pwq->nr_active. For non-barrier work item, it
++ * is marked with WORK_STRUCT_INACTIVE iff it is in pwq->inactive_works.
+ */
+ int nr_active; /* L: nr of active works */
++ int max_active; /* L: max active works */
+ struct list_head inactive_works; /* L: inactive works */
+- struct list_head pending_node; /* LN: node on wq_node_nr_active->pending_pwqs */
+ struct list_head pwqs_node; /* WR: node on wq->pwqs */
+ struct list_head mayday_node; /* MD: node on wq->maydays */
+
+@@ -284,26 +278,6 @@ struct wq_flusher {
+
+ struct wq_device;
+
+-/*
+- * Unlike in a per-cpu workqueue where max_active limits its concurrency level
+- * on each CPU, in an unbound workqueue, max_active applies to the whole system.
+- * As sharing a single nr_active across multiple sockets can be very expensive,
+- * the counting and enforcement is per NUMA node.
+- *
+- * The following struct is used to enforce per-node max_active. When a pwq wants
+- * to start executing a work item, it should increment ->nr using
+- * tryinc_node_nr_active(). If acquisition fails due to ->nr already being over
+- * ->max, the pwq is queued on ->pending_pwqs. As in-flight work items finish
+- * and decrement ->nr, node_activate_pending_pwq() activates the pending pwqs in
+- * round-robin order.
+- */
+-struct wq_node_nr_active {
+- int max; /* per-node max_active */
+- atomic_t nr; /* per-node nr_active */
+- raw_spinlock_t lock; /* nests inside pool locks */
+- struct list_head pending_pwqs; /* LN: pwqs with inactive works */
+-};
+-
+ /*
+ * The externally visible workqueue. It relays the issued work items to
+ * the appropriate worker_pool through its pool_workqueues.
+@@ -324,15 +298,10 @@ struct workqueue_struct {
+ struct worker *rescuer; /* MD: rescue worker */
+
+ int nr_drainers; /* WQ: drain in progress */
+-
+- /* See alloc_workqueue() function comment for info on min/max_active */
+- int max_active; /* WO: max active works */
+- int min_active; /* WO: min active works */
+- int saved_max_active; /* WQ: saved max_active */
+- int saved_min_active; /* WQ: saved min_active */
++ int saved_max_active; /* WQ: saved pwq max_active */
+
+ struct workqueue_attrs *unbound_attrs; /* PW: only for unbound wqs */
+- struct pool_workqueue __rcu *dfl_pwq; /* PW: only for unbound wqs */
++ struct pool_workqueue *dfl_pwq; /* PW: only for unbound wqs */
+
+ #ifdef CONFIG_SYSFS
+ struct wq_device *wq_dev; /* I: for sysfs interface */
+@@ -354,7 +323,6 @@ struct workqueue_struct {
+ /* hot fields used during command issue, aligned to cacheline */
+ unsigned int flags ____cacheline_aligned; /* WQ: WQ_* flags */
+ struct pool_workqueue __percpu __rcu **cpu_pwq; /* I: per-cpu pwqs */
+- struct wq_node_nr_active *node_nr_active[]; /* I: per-node nr_active */
+ };
+
+ static struct kmem_cache *pwq_cache;
+@@ -664,36 +632,6 @@ static int worker_pool_assign_id(struct worker_pool *pool)
+ return ret;
+ }
+
+-static struct pool_workqueue __rcu **
+-unbound_pwq_slot(struct workqueue_struct *wq, int cpu)
+-{
+- if (cpu >= 0)
+- return per_cpu_ptr(wq->cpu_pwq, cpu);
+- else
+- return &wq->dfl_pwq;
+-}
+-
+-/* @cpu < 0 for dfl_pwq */
+-static struct pool_workqueue *unbound_pwq(struct workqueue_struct *wq, int cpu)
+-{
+- return rcu_dereference_check(*unbound_pwq_slot(wq, cpu),
+- lockdep_is_held(&wq_pool_mutex) ||
+- lockdep_is_held(&wq->mutex));
+-}
+-
+-/**
+- * unbound_effective_cpumask - effective cpumask of an unbound workqueue
+- * @wq: workqueue of interest
+- *
+- * @wq->unbound_attrs->cpumask contains the cpumask requested by the user which
+- * is masked with wq_unbound_cpumask to determine the effective cpumask. The
+- * default pwq is always mapped to the pool with the current effective cpumask.
+- */
+-static struct cpumask *unbound_effective_cpumask(struct workqueue_struct *wq)
+-{
+- return unbound_pwq(wq, -1)->pool->attrs->__pod_cpumask;
+-}
+-
+ static unsigned int work_color_to_flags(int color)
+ {
+ return color << WORK_STRUCT_COLOR_SHIFT;
+@@ -1463,71 +1401,6 @@ work_func_t wq_worker_last_func(struct task_struct *task)
+ return worker->last_func;
+ }
+
+-/**
+- * wq_node_nr_active - Determine wq_node_nr_active to use
+- * @wq: workqueue of interest
+- * @node: NUMA node, can be %NUMA_NO_NODE
+- *
+- * Determine wq_node_nr_active to use for @wq on @node. Returns:
+- *
+- * - %NULL for per-cpu workqueues as they don't need to use shared nr_active.
+- *
+- * - node_nr_active[nr_node_ids] if @node is %NUMA_NO_NODE.
+- *
+- * - Otherwise, node_nr_active[@node].
+- */
+-static struct wq_node_nr_active *wq_node_nr_active(struct workqueue_struct *wq,
+- int node)
+-{
+- if (!(wq->flags & WQ_UNBOUND))
+- return NULL;
+-
+- if (node == NUMA_NO_NODE)
+- node = nr_node_ids;
+-
+- return wq->node_nr_active[node];
+-}
+-
+-/**
+- * wq_update_node_max_active - Update per-node max_actives to use
+- * @wq: workqueue to update
+- * @off_cpu: CPU that's going down, -1 if a CPU is not going down
+- *
+- * Update @wq->node_nr_active[]->max. @wq must be unbound. max_active is
+- * distributed among nodes according to the proportions of numbers of online
+- * cpus. The result is always between @wq->min_active and max_active.
+- */
+-static void wq_update_node_max_active(struct workqueue_struct *wq, int off_cpu)
+-{
+- struct cpumask *effective = unbound_effective_cpumask(wq);
+- int min_active = READ_ONCE(wq->min_active);
+- int max_active = READ_ONCE(wq->max_active);
+- int total_cpus, node;
+-
+- lockdep_assert_held(&wq->mutex);
+-
+- if (off_cpu >= 0 && !cpumask_test_cpu(off_cpu, effective))
+- off_cpu = -1;
+-
+- total_cpus = cpumask_weight_and(effective, cpu_online_mask);
+- if (off_cpu >= 0)
+- total_cpus--;
+-
+- for_each_node(node) {
+- int node_cpus;
+-
+- node_cpus = cpumask_weight_and(effective, cpumask_of_node(node));
+- if (off_cpu >= 0 && cpu_to_node(off_cpu) == node)
+- node_cpus--;
+-
+- wq_node_nr_active(wq, node)->max =
+- clamp(DIV_ROUND_UP(max_active * node_cpus, total_cpus),
+- min_active, max_active);
+- }
+-
+- wq_node_nr_active(wq, NUMA_NO_NODE)->max = min_active;
+-}
+-
+ /**
+ * get_pwq - get an extra reference on the specified pool_workqueue
+ * @pwq: pool_workqueue to get
+@@ -1580,293 +1453,24 @@ static void put_pwq_unlocked(struct pool_workqueue *pwq)
+ }
+ }
+
+-static bool pwq_is_empty(struct pool_workqueue *pwq)
+-{
+- return !pwq->nr_active && list_empty(&pwq->inactive_works);
+-}
+-
+-static void __pwq_activate_work(struct pool_workqueue *pwq,
+- struct work_struct *work)
++static void pwq_activate_inactive_work(struct work_struct *work)
+ {
+- unsigned long *wdb = work_data_bits(work);
++ struct pool_workqueue *pwq = get_work_pwq(work);
+
+- WARN_ON_ONCE(!(*wdb & WORK_STRUCT_INACTIVE));
+ trace_workqueue_activate_work(work);
+ if (list_empty(&pwq->pool->worklist))
+ pwq->pool->watchdog_ts = jiffies;
+ move_linked_works(work, &pwq->pool->worklist, NULL);
+- __clear_bit(WORK_STRUCT_INACTIVE_BIT, wdb);
+-}
+-
+-/**
+- * pwq_activate_work - Activate a work item if inactive
+- * @pwq: pool_workqueue @work belongs to
+- * @work: work item to activate
+- *
+- * Returns %true if activated. %false if already active.
+- */
+-static bool pwq_activate_work(struct pool_workqueue *pwq,
+- struct work_struct *work)
+-{
+- struct worker_pool *pool = pwq->pool;
+- struct wq_node_nr_active *nna;
+-
+- lockdep_assert_held(&pool->lock);
+-
+- if (!(*work_data_bits(work) & WORK_STRUCT_INACTIVE))
+- return false;
+-
+- nna = wq_node_nr_active(pwq->wq, pool->node);
+- if (nna)
+- atomic_inc(&nna->nr);
+-
++ __clear_bit(WORK_STRUCT_INACTIVE_BIT, work_data_bits(work));
+ pwq->nr_active++;
+- __pwq_activate_work(pwq, work);
+- return true;
+-}
+-
+-static bool tryinc_node_nr_active(struct wq_node_nr_active *nna)
+-{
+- int max = READ_ONCE(nna->max);
+-
+- while (true) {
+- int old, tmp;
+-
+- old = atomic_read(&nna->nr);
+- if (old >= max)
+- return false;
+- tmp = atomic_cmpxchg_relaxed(&nna->nr, old, old + 1);
+- if (tmp == old)
+- return true;
+- }
+-}
+-
+-/**
+- * pwq_tryinc_nr_active - Try to increment nr_active for a pwq
+- * @pwq: pool_workqueue of interest
+- * @fill: max_active may have increased, try to increase concurrency level
+- *
+- * Try to increment nr_active for @pwq. Returns %true if an nr_active count is
+- * successfully obtained. %false otherwise.
+- */
+-static bool pwq_tryinc_nr_active(struct pool_workqueue *pwq, bool fill)
+-{
+- struct workqueue_struct *wq = pwq->wq;
+- struct worker_pool *pool = pwq->pool;
+- struct wq_node_nr_active *nna = wq_node_nr_active(wq, pool->node);
+- bool obtained = false;
+-
+- lockdep_assert_held(&pool->lock);
+-
+- if (!nna) {
+- /* per-cpu workqueue, pwq->nr_active is sufficient */
+- obtained = pwq->nr_active < READ_ONCE(wq->max_active);
+- goto out;
+- }
+-
+- /*
+- * Unbound workqueue uses per-node shared nr_active $nna. If @pwq is
+- * already waiting on $nna, pwq_dec_nr_active() will maintain the
+- * concurrency level. Don't jump the line.
+- *
+- * We need to ignore the pending test after max_active has increased as
+- * pwq_dec_nr_active() can only maintain the concurrency level but not
+- * increase it. This is indicated by @fill.
+- */
+- if (!list_empty(&pwq->pending_node) && likely(!fill))
+- goto out;
+-
+- obtained = tryinc_node_nr_active(nna);
+- if (obtained)
+- goto out;
+-
+- /*
+- * Lockless acquisition failed. Lock, add ourself to $nna->pending_pwqs
+- * and try again. The smp_mb() is paired with the implied memory barrier
+- * of atomic_dec_return() in pwq_dec_nr_active() to ensure that either
+- * we see the decremented $nna->nr or they see non-empty
+- * $nna->pending_pwqs.
+- */
+- raw_spin_lock(&nna->lock);
+-
+- if (list_empty(&pwq->pending_node))
+- list_add_tail(&pwq->pending_node, &nna->pending_pwqs);
+- else if (likely(!fill))
+- goto out_unlock;
+-
+- smp_mb();
+-
+- obtained = tryinc_node_nr_active(nna);
+-
+- /*
+- * If @fill, @pwq might have already been pending. Being spuriously
+- * pending in cold paths doesn't affect anything. Let's leave it be.
+- */
+- if (obtained && likely(!fill))
+- list_del_init(&pwq->pending_node);
+-
+-out_unlock:
+- raw_spin_unlock(&nna->lock);
+-out:
+- if (obtained)
+- pwq->nr_active++;
+- return obtained;
+-}
+-
+-/**
+- * pwq_activate_first_inactive - Activate the first inactive work item on a pwq
+- * @pwq: pool_workqueue of interest
+- * @fill: max_active may have increased, try to increase concurrency level
+- *
+- * Activate the first inactive work item of @pwq if available and allowed by
+- * max_active limit.
+- *
+- * Returns %true if an inactive work item has been activated. %false if no
+- * inactive work item is found or max_active limit is reached.
+- */
+-static bool pwq_activate_first_inactive(struct pool_workqueue *pwq, bool fill)
+-{
+- struct work_struct *work =
+- list_first_entry_or_null(&pwq->inactive_works,
+- struct work_struct, entry);
+-
+- if (work && pwq_tryinc_nr_active(pwq, fill)) {
+- __pwq_activate_work(pwq, work);
+- return true;
+- } else {
+- return false;
+- }
+-}
+-
+-/**
+- * node_activate_pending_pwq - Activate a pending pwq on a wq_node_nr_active
+- * @nna: wq_node_nr_active to activate a pending pwq for
+- * @caller_pool: worker_pool the caller is locking
+- *
+- * Activate a pwq in @nna->pending_pwqs. Called with @caller_pool locked.
+- * @caller_pool may be unlocked and relocked to lock other worker_pools.
+- */
+-static void node_activate_pending_pwq(struct wq_node_nr_active *nna,
+- struct worker_pool *caller_pool)
+-{
+- struct worker_pool *locked_pool = caller_pool;
+- struct pool_workqueue *pwq;
+- struct work_struct *work;
+-
+- lockdep_assert_held(&caller_pool->lock);
+-
+- raw_spin_lock(&nna->lock);
+-retry:
+- pwq = list_first_entry_or_null(&nna->pending_pwqs,
+- struct pool_workqueue, pending_node);
+- if (!pwq)
+- goto out_unlock;
+-
+- /*
+- * If @pwq is for a different pool than @locked_pool, we need to lock
+- * @pwq->pool->lock. Let's trylock first. If unsuccessful, do the unlock
+- * / lock dance. For that, we also need to release @nna->lock as it's
+- * nested inside pool locks.
+- */
+- if (pwq->pool != locked_pool) {
+- raw_spin_unlock(&locked_pool->lock);
+- locked_pool = pwq->pool;
+- if (!raw_spin_trylock(&locked_pool->lock)) {
+- raw_spin_unlock(&nna->lock);
+- raw_spin_lock(&locked_pool->lock);
+- raw_spin_lock(&nna->lock);
+- goto retry;
+- }
+- }
+-
+- /*
+- * $pwq may not have any inactive work items due to e.g. cancellations.
+- * Drop it from pending_pwqs and see if there's another one.
+- */
+- work = list_first_entry_or_null(&pwq->inactive_works,
+- struct work_struct, entry);
+- if (!work) {
+- list_del_init(&pwq->pending_node);
+- goto retry;
+- }
+-
+- /*
+- * Acquire an nr_active count and activate the inactive work item. If
+- * $pwq still has inactive work items, rotate it to the end of the
+- * pending_pwqs so that we round-robin through them. This means that
+- * inactive work items are not activated in queueing order which is fine
+- * given that there has never been any ordering across different pwqs.
+- */
+- if (likely(tryinc_node_nr_active(nna))) {
+- pwq->nr_active++;
+- __pwq_activate_work(pwq, work);
+-
+- if (list_empty(&pwq->inactive_works))
+- list_del_init(&pwq->pending_node);
+- else
+- list_move_tail(&pwq->pending_node, &nna->pending_pwqs);
+-
+- /* if activating a foreign pool, make sure it's running */
+- if (pwq->pool != caller_pool)
+- kick_pool(pwq->pool);
+- }
+-
+-out_unlock:
+- raw_spin_unlock(&nna->lock);
+- if (locked_pool != caller_pool) {
+- raw_spin_unlock(&locked_pool->lock);
+- raw_spin_lock(&caller_pool->lock);
+- }
+ }
+
+-/**
+- * pwq_dec_nr_active - Retire an active count
+- * @pwq: pool_workqueue of interest
+- *
+- * Decrement @pwq's nr_active and try to activate the first inactive work item.
+- * For unbound workqueues, this function may temporarily drop @pwq->pool->lock.
+- */
+-static void pwq_dec_nr_active(struct pool_workqueue *pwq)
++static void pwq_activate_first_inactive(struct pool_workqueue *pwq)
+ {
+- struct worker_pool *pool = pwq->pool;
+- struct wq_node_nr_active *nna = wq_node_nr_active(pwq->wq, pool->node);
++ struct work_struct *work = list_first_entry(&pwq->inactive_works,
++ struct work_struct, entry);
+
+- lockdep_assert_held(&pool->lock);
+-
+- /*
+- * @pwq->nr_active should be decremented for both percpu and unbound
+- * workqueues.
+- */
+- pwq->nr_active--;
+-
+- /*
+- * For a percpu workqueue, it's simple. Just need to kick the first
+- * inactive work item on @pwq itself.
+- */
+- if (!nna) {
+- pwq_activate_first_inactive(pwq, false);
+- return;
+- }
+-
+- /*
+- * If @pwq is for an unbound workqueue, it's more complicated because
+- * multiple pwqs and pools may be sharing the nr_active count. When a
+- * pwq needs to wait for an nr_active count, it puts itself on
+- * $nna->pending_pwqs. The following atomic_dec_return()'s implied
+- * memory barrier is paired with smp_mb() in pwq_tryinc_nr_active() to
+- * guarantee that either we see non-empty pending_pwqs or they see
+- * decremented $nna->nr.
+- *
+- * $nna->max may change as CPUs come online/offline and @pwq->wq's
+- * max_active gets updated. However, it is guaranteed to be equal to or
+- * larger than @pwq->wq->min_active which is above zero unless freezing.
+- * This maintains the forward progress guarantee.
+- */
+- if (atomic_dec_return(&nna->nr) >= READ_ONCE(nna->max))
+- return;
+-
+- if (!list_empty(&nna->pending_pwqs))
+- node_activate_pending_pwq(nna, pool);
++ pwq_activate_inactive_work(work);
+ }
+
+ /**
+@@ -1884,8 +1488,14 @@ static void pwq_dec_nr_in_flight(struct pool_workqueue *pwq, unsigned long work_
+ {
+ int color = get_work_color(work_data);
+
+- if (!(work_data & WORK_STRUCT_INACTIVE))
+- pwq_dec_nr_active(pwq);
++ if (!(work_data & WORK_STRUCT_INACTIVE)) {
++ pwq->nr_active--;
++ if (!list_empty(&pwq->inactive_works)) {
++ /* one down, submit an inactive one */
++ if (pwq->nr_active < pwq->max_active)
++ pwq_activate_first_inactive(pwq);
++ }
++ }
+
+ pwq->nr_in_flight[color]--;
+
+@@ -1998,7 +1608,8 @@ static int try_to_grab_pending(struct work_struct *work, bool is_dwork,
+ * management later on and cause stall. Make sure the work
+ * item is activated before grabbing.
+ */
+- pwq_activate_work(pwq, work);
++ if (*work_data_bits(work) & WORK_STRUCT_INACTIVE)
++ pwq_activate_inactive_work(work);
+
+ list_del_init(&work->entry);
+ pwq_dec_nr_in_flight(pwq, *work_data_bits(work));
+@@ -2182,16 +1793,12 @@ static void __queue_work(int cpu, struct workqueue_struct *wq,
+ pwq->nr_in_flight[pwq->work_color]++;
+ work_flags = work_color_to_flags(pwq->work_color);
+
+- /*
+- * Limit the number of concurrently active work items to max_active.
+- * @work must also queue behind existing inactive work items to maintain
+- * ordering when max_active changes. See wq_adjust_max_active().
+- */
+- if (list_empty(&pwq->inactive_works) && pwq_tryinc_nr_active(pwq, false)) {
++ if (likely(pwq->nr_active < pwq->max_active)) {
+ if (list_empty(&pool->worklist))
+ pool->watchdog_ts = jiffies;
+
+ trace_workqueue_activate_work(work);
++ pwq->nr_active++;
+ insert_work(pwq, work, &pool->worklist, work_flags);
+ kick_pool(pool);
+ } else {
+@@ -3420,7 +3027,7 @@ static void insert_wq_barrier(struct pool_workqueue *pwq,
+
+ barr->task = current;
+
+- /* The barrier work item does not participate in nr_active. */
++ /* The barrier work item does not participate in pwq->nr_active. */
+ work_flags |= WORK_STRUCT_INACTIVE;
+
+ /*
+@@ -3709,7 +3316,7 @@ void drain_workqueue(struct workqueue_struct *wq)
+ bool drained;
+
+ raw_spin_lock_irq(&pwq->pool->lock);
+- drained = pwq_is_empty(pwq);
++ drained = !pwq->nr_active && list_empty(&pwq->inactive_works);
+ raw_spin_unlock_irq(&pwq->pool->lock);
+
+ if (drained)
+@@ -4320,65 +3927,11 @@ static void wq_free_lockdep(struct workqueue_struct *wq)
+ }
+ #endif
+
+-static void free_node_nr_active(struct wq_node_nr_active **nna_ar)
+-{
+- int node;
+-
+- for_each_node(node) {
+- kfree(nna_ar[node]);
+- nna_ar[node] = NULL;
+- }
+-
+- kfree(nna_ar[nr_node_ids]);
+- nna_ar[nr_node_ids] = NULL;
+-}
+-
+-static void init_node_nr_active(struct wq_node_nr_active *nna)
+-{
+- atomic_set(&nna->nr, 0);
+- raw_spin_lock_init(&nna->lock);
+- INIT_LIST_HEAD(&nna->pending_pwqs);
+-}
+-
+-/*
+- * Each node's nr_active counter will be accessed mostly from its own node and
+- * should be allocated in the node.
+- */
+-static int alloc_node_nr_active(struct wq_node_nr_active **nna_ar)
+-{
+- struct wq_node_nr_active *nna;
+- int node;
+-
+- for_each_node(node) {
+- nna = kzalloc_node(sizeof(*nna), GFP_KERNEL, node);
+- if (!nna)
+- goto err_free;
+- init_node_nr_active(nna);
+- nna_ar[node] = nna;
+- }
+-
+- /* [nr_node_ids] is used as the fallback */
+- nna = kzalloc_node(sizeof(*nna), GFP_KERNEL, NUMA_NO_NODE);
+- if (!nna)
+- goto err_free;
+- init_node_nr_active(nna);
+- nna_ar[nr_node_ids] = nna;
+-
+- return 0;
+-
+-err_free:
+- free_node_nr_active(nna_ar);
+- return -ENOMEM;
+-}
+-
+ static void rcu_free_wq(struct rcu_head *rcu)
+ {
+ struct workqueue_struct *wq =
+ container_of(rcu, struct workqueue_struct, rcu);
+
+- if (wq->flags & WQ_UNBOUND)
+- free_node_nr_active(wq->node_nr_active);
+-
+ wq_free_lockdep(wq);
+ free_percpu(wq->cpu_pwq);
+ free_workqueue_attrs(wq->unbound_attrs);
+@@ -4577,15 +4130,6 @@ static void pwq_release_workfn(struct kthread_work *work)
+ mutex_unlock(&wq_pool_mutex);
+ }
+
+- if (!list_empty(&pwq->pending_node)) {
+- struct wq_node_nr_active *nna =
+- wq_node_nr_active(pwq->wq, pwq->pool->node);
+-
+- raw_spin_lock_irq(&nna->lock);
+- list_del_init(&pwq->pending_node);
+- raw_spin_unlock_irq(&nna->lock);
+- }
+-
+ call_rcu(&pwq->rcu, rcu_free_pwq);
+
+ /*
+@@ -4598,6 +4142,50 @@ static void pwq_release_workfn(struct kthread_work *work)
+ }
+ }
+
++/**
++ * pwq_adjust_max_active - update a pwq's max_active to the current setting
++ * @pwq: target pool_workqueue
++ *
++ * If @pwq isn't freezing, set @pwq->max_active to the associated
++ * workqueue's saved_max_active and activate inactive work items
++ * accordingly. If @pwq is freezing, clear @pwq->max_active to zero.
++ */
++static void pwq_adjust_max_active(struct pool_workqueue *pwq)
++{
++ struct workqueue_struct *wq = pwq->wq;
++ bool freezable = wq->flags & WQ_FREEZABLE;
++ unsigned long flags;
++
++ /* for @wq->saved_max_active */
++ lockdep_assert_held(&wq->mutex);
++
++ /* fast exit for non-freezable wqs */
++ if (!freezable && pwq->max_active == wq->saved_max_active)
++ return;
++
++ /* this function can be called during early boot w/ irq disabled */
++ raw_spin_lock_irqsave(&pwq->pool->lock, flags);
++
++ /*
++ * During [un]freezing, the caller is responsible for ensuring that
++ * this function is called at least once after @workqueue_freezing
++ * is updated and visible.
++ */
++ if (!freezable || !workqueue_freezing) {
++ pwq->max_active = wq->saved_max_active;
++
++ while (!list_empty(&pwq->inactive_works) &&
++ pwq->nr_active < pwq->max_active)
++ pwq_activate_first_inactive(pwq);
++
++ kick_pool(pwq->pool);
++ } else {
++ pwq->max_active = 0;
++ }
++
++ raw_spin_unlock_irqrestore(&pwq->pool->lock, flags);
++}
++
+ /* initialize newly allocated @pwq which is associated with @wq and @pool */
+ static void init_pwq(struct pool_workqueue *pwq, struct workqueue_struct *wq,
+ struct worker_pool *pool)
+@@ -4611,7 +4199,6 @@ static void init_pwq(struct pool_workqueue *pwq, struct workqueue_struct *wq,
+ pwq->flush_color = -1;
+ pwq->refcnt = 1;
+ INIT_LIST_HEAD(&pwq->inactive_works);
+- INIT_LIST_HEAD(&pwq->pending_node);
+ INIT_LIST_HEAD(&pwq->pwqs_node);
+ INIT_LIST_HEAD(&pwq->mayday_node);
+ kthread_init_work(&pwq->release_work, pwq_release_workfn);
+@@ -4631,6 +4218,9 @@ static void link_pwq(struct pool_workqueue *pwq)
+ /* set the matching work_color */
+ pwq->work_color = wq->work_color;
+
++ /* sync max_active to the current setting */
++ pwq_adjust_max_active(pwq);
++
+ /* link in @pwq */
+ list_add_rcu(&pwq->pwqs_node, &wq->pwqs);
+ }
+@@ -4699,11 +4289,10 @@ static void wq_calc_pod_cpumask(struct workqueue_attrs *attrs, int cpu,
+ "possible intersect\n");
+ }
+
+-/* install @pwq into @wq and return the old pwq, @cpu < 0 for dfl_pwq */
++/* install @pwq into @wq's cpu_pwq and return the old pwq */
+ static struct pool_workqueue *install_unbound_pwq(struct workqueue_struct *wq,
+ int cpu, struct pool_workqueue *pwq)
+ {
+- struct pool_workqueue __rcu **slot = unbound_pwq_slot(wq, cpu);
+ struct pool_workqueue *old_pwq;
+
+ lockdep_assert_held(&wq_pool_mutex);
+@@ -4712,8 +4301,8 @@ static struct pool_workqueue *install_unbound_pwq(struct workqueue_struct *wq,
+ /* link_pwq() can handle duplicate calls */
+ link_pwq(pwq);
+
+- old_pwq = rcu_access_pointer(*slot);
+- rcu_assign_pointer(*slot, pwq);
++ old_pwq = rcu_access_pointer(*per_cpu_ptr(wq->cpu_pwq, cpu));
++ rcu_assign_pointer(*per_cpu_ptr(wq->cpu_pwq, cpu), pwq);
+ return old_pwq;
+ }
+
+@@ -4813,14 +4402,14 @@ static void apply_wqattrs_commit(struct apply_wqattrs_ctx *ctx)
+
+ copy_workqueue_attrs(ctx->wq->unbound_attrs, ctx->attrs);
+
+- /* save the previous pwqs and install the new ones */
++ /* save the previous pwq and install the new one */
+ for_each_possible_cpu(cpu)
+ ctx->pwq_tbl[cpu] = install_unbound_pwq(ctx->wq, cpu,
+ ctx->pwq_tbl[cpu]);
+- ctx->dfl_pwq = install_unbound_pwq(ctx->wq, -1, ctx->dfl_pwq);
+
+- /* update node_nr_active->max */
+- wq_update_node_max_active(ctx->wq, -1);
++ /* @dfl_pwq might not have been used, ensure it's linked */
++ link_pwq(ctx->dfl_pwq);
++ swap(ctx->wq->dfl_pwq, ctx->dfl_pwq);
+
+ mutex_unlock(&ctx->wq->mutex);
+ }
+@@ -4930,7 +4519,9 @@ static void wq_update_pod(struct workqueue_struct *wq, int cpu,
+
+ /* nothing to do if the target cpumask matches the current pwq */
+ wq_calc_pod_cpumask(target_attrs, cpu, off_cpu);
+- if (wqattrs_equal(target_attrs, unbound_pwq(wq, cpu)->pool->attrs))
++ pwq = rcu_dereference_protected(*per_cpu_ptr(wq->cpu_pwq, cpu),
++ lockdep_is_held(&wq_pool_mutex));
++ if (wqattrs_equal(target_attrs, pwq->pool->attrs))
+ return;
+
+ /* create a new pwq */
+@@ -4948,11 +4539,10 @@ static void wq_update_pod(struct workqueue_struct *wq, int cpu,
+
+ use_dfl_pwq:
+ mutex_lock(&wq->mutex);
+- pwq = unbound_pwq(wq, -1);
+- raw_spin_lock_irq(&pwq->pool->lock);
+- get_pwq(pwq);
+- raw_spin_unlock_irq(&pwq->pool->lock);
+- old_pwq = install_unbound_pwq(wq, cpu, pwq);
++ raw_spin_lock_irq(&wq->dfl_pwq->pool->lock);
++ get_pwq(wq->dfl_pwq);
++ raw_spin_unlock_irq(&wq->dfl_pwq->pool->lock);
++ old_pwq = install_unbound_pwq(wq, cpu, wq->dfl_pwq);
+ out_unlock:
+ mutex_unlock(&wq->mutex);
+ put_pwq_unlocked(old_pwq);
+@@ -4990,13 +4580,10 @@ static int alloc_and_link_pwqs(struct workqueue_struct *wq)
+
+ cpus_read_lock();
+ if (wq->flags & __WQ_ORDERED) {
+- struct pool_workqueue *dfl_pwq;
+-
+ ret = apply_workqueue_attrs(wq, ordered_wq_attrs[highpri]);
+ /* there should only be single pwq for ordering guarantee */
+- dfl_pwq = rcu_access_pointer(wq->dfl_pwq);
+- WARN(!ret && (wq->pwqs.next != &dfl_pwq->pwqs_node ||
+- wq->pwqs.prev != &dfl_pwq->pwqs_node),
++ WARN(!ret && (wq->pwqs.next != &wq->dfl_pwq->pwqs_node ||
++ wq->pwqs.prev != &wq->dfl_pwq->pwqs_node),
+ "ordering guarantee broken for workqueue %s\n", wq->name);
+ } else {
+ ret = apply_workqueue_attrs(wq, unbound_std_wq_attrs[highpri]);
+@@ -5071,69 +4658,6 @@ static int init_rescuer(struct workqueue_struct *wq)
+ return 0;
+ }
+
+-/**
+- * wq_adjust_max_active - update a wq's max_active to the current setting
+- * @wq: target workqueue
+- *
+- * If @wq isn't freezing, set @wq->max_active to the saved_max_active and
+- * activate inactive work items accordingly. If @wq is freezing, clear
+- * @wq->max_active to zero.
+- */
+-static void wq_adjust_max_active(struct workqueue_struct *wq)
+-{
+- bool activated;
+- int new_max, new_min;
+-
+- lockdep_assert_held(&wq->mutex);
+-
+- if ((wq->flags & WQ_FREEZABLE) && workqueue_freezing) {
+- new_max = 0;
+- new_min = 0;
+- } else {
+- new_max = wq->saved_max_active;
+- new_min = wq->saved_min_active;
+- }
+-
+- if (wq->max_active == new_max && wq->min_active == new_min)
+- return;
+-
+- /*
+- * Update @wq->max/min_active and then kick inactive work items if more
+- * active work items are allowed. This doesn't break work item ordering
+- * because new work items are always queued behind existing inactive
+- * work items if there are any.
+- */
+- WRITE_ONCE(wq->max_active, new_max);
+- WRITE_ONCE(wq->min_active, new_min);
+-
+- if (wq->flags & WQ_UNBOUND)
+- wq_update_node_max_active(wq, -1);
+-
+- if (new_max == 0)
+- return;
+-
+- /*
+- * Round-robin through pwq's activating the first inactive work item
+- * until max_active is filled.
+- */
+- do {
+- struct pool_workqueue *pwq;
+-
+- activated = false;
+- for_each_pwq(pwq, wq) {
+- unsigned long flags;
+-
+- /* can be called during early boot w/ irq disabled */
+- raw_spin_lock_irqsave(&pwq->pool->lock, flags);
+- if (pwq_activate_first_inactive(pwq, true)) {
+- activated = true;
+- kick_pool(pwq->pool);
+- }
+- raw_spin_unlock_irqrestore(&pwq->pool->lock, flags);
+- }
+- } while (activated);
+-}
+-
+ __printf(1, 4)
+ struct workqueue_struct *alloc_workqueue(const char *fmt,
+ unsigned int flags,
+@@ -5141,8 +4665,7 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
+ {
+ va_list args;
+ struct workqueue_struct *wq;
+- size_t wq_size;
+- int name_len;
++ struct pool_workqueue *pwq;
+
+ /*
+ * Unbound && max_active == 1 used to imply ordered, which is no longer
+@@ -5158,12 +4681,7 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
+ flags |= WQ_UNBOUND;
+
+ /* allocate wq and format name */
+- if (flags & WQ_UNBOUND)
+- wq_size = struct_size(wq, node_nr_active, nr_node_ids + 1);
+- else
+- wq_size = sizeof(*wq);
+-
+- wq = kzalloc(wq_size, GFP_KERNEL);
++ wq = kzalloc(sizeof(*wq), GFP_KERNEL);
+ if (!wq)
+ return NULL;
+
+@@ -5174,22 +4692,15 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
+ }
+
+ va_start(args, max_active);
+- name_len = vsnprintf(wq->name, sizeof(wq->name), fmt, args);
++ vsnprintf(wq->name, sizeof(wq->name), fmt, args);
+ va_end(args);
+
+- if (name_len >= WQ_NAME_LEN)
+- pr_warn_once("workqueue: name exceeds WQ_NAME_LEN. Truncating to: %s\n",
+- wq->name);
+-
+ max_active = max_active ?: WQ_DFL_ACTIVE;
+ max_active = wq_clamp_max_active(max_active, flags, wq->name);
+
+ /* init wq */
+ wq->flags = flags;
+- wq->max_active = max_active;
+- wq->min_active = min(max_active, WQ_DFL_MIN_ACTIVE);
+- wq->saved_max_active = wq->max_active;
+- wq->saved_min_active = wq->min_active;
++ wq->saved_max_active = max_active;
+ mutex_init(&wq->mutex);
+ atomic_set(&wq->nr_pwqs_to_flush, 0);
+ INIT_LIST_HEAD(&wq->pwqs);
+@@ -5200,13 +4711,8 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
+ wq_init_lockdep(wq);
+ INIT_LIST_HEAD(&wq->list);
+
+- if (flags & WQ_UNBOUND) {
+- if (alloc_node_nr_active(wq->node_nr_active) < 0)
+- goto err_unreg_lockdep;
+- }
+-
+ if (alloc_and_link_pwqs(wq) < 0)
+- goto err_free_node_nr_active;
++ goto err_unreg_lockdep;
+
+ if (wq_online && init_rescuer(wq) < 0)
+ goto err_destroy;
+@@ -5222,7 +4728,8 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
+ mutex_lock(&wq_pool_mutex);
+
+ mutex_lock(&wq->mutex);
+- wq_adjust_max_active(wq);
++ for_each_pwq(pwq, wq)
++ pwq_adjust_max_active(pwq);
+ mutex_unlock(&wq->mutex);
+
+ list_add_tail_rcu(&wq->list, &workqueues);
+@@ -5231,9 +4738,6 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
+
+ return wq;
+
+-err_free_node_nr_active:
+- if (wq->flags & WQ_UNBOUND)
+- free_node_nr_active(wq->node_nr_active);
+ err_unreg_lockdep:
+ wq_unregister_lockdep(wq);
+ wq_free_lockdep(wq);
+@@ -5255,9 +4759,9 @@ static bool pwq_busy(struct pool_workqueue *pwq)
+ if (pwq->nr_in_flight[i])
+ return true;
+
+- if ((pwq != rcu_access_pointer(pwq->wq->dfl_pwq)) && (pwq->refcnt > 1))
++ if ((pwq != pwq->wq->dfl_pwq) && (pwq->refcnt > 1))
+ return true;
+- if (!pwq_is_empty(pwq))
++ if (pwq->nr_active || !list_empty(&pwq->inactive_works))
+ return true;
+
+ return false;
+@@ -5339,12 +4843,13 @@ void destroy_workqueue(struct workqueue_struct *wq)
+ rcu_read_lock();
+
+ for_each_possible_cpu(cpu) {
+- put_pwq_unlocked(unbound_pwq(wq, cpu));
+- RCU_INIT_POINTER(*unbound_pwq_slot(wq, cpu), NULL);
++ pwq = rcu_access_pointer(*per_cpu_ptr(wq->cpu_pwq, cpu));
++ RCU_INIT_POINTER(*per_cpu_ptr(wq->cpu_pwq, cpu), NULL);
++ put_pwq_unlocked(pwq);
+ }
+
+- put_pwq_unlocked(unbound_pwq(wq, -1));
+- RCU_INIT_POINTER(*unbound_pwq_slot(wq, -1), NULL);
++ put_pwq_unlocked(wq->dfl_pwq);
++ wq->dfl_pwq = NULL;
+
+ rcu_read_unlock();
+ }
+@@ -5355,14 +4860,15 @@ EXPORT_SYMBOL_GPL(destroy_workqueue);
+ * @wq: target workqueue
+ * @max_active: new max_active value.
+ *
+- * Set max_active of @wq to @max_active. See the alloc_workqueue() function
+- * comment.
++ * Set max_active of @wq to @max_active.
+ *
+ * CONTEXT:
+ * Don't call from IRQ context.
+ */
+ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)
+ {
++ struct pool_workqueue *pwq;
++
+ /* disallow meddling with max_active for ordered workqueues */
+ if (WARN_ON(wq->flags & __WQ_ORDERED_EXPLICIT))
+ return;
+@@ -5373,10 +4879,9 @@ void workqueue_set_max_active(struct workqueue_struct *wq, int max_active)
+
+ wq->flags &= ~__WQ_ORDERED;
+ wq->saved_max_active = max_active;
+- if (wq->flags & WQ_UNBOUND)
+- wq->saved_min_active = min(wq->saved_min_active, max_active);
+
+- wq_adjust_max_active(wq);
++ for_each_pwq(pwq, wq)
++ pwq_adjust_max_active(pwq);
+
+ mutex_unlock(&wq->mutex);
+ }
+@@ -5623,8 +5128,8 @@ static void show_pwq(struct pool_workqueue *pwq)
+ pr_info(" pwq %d:", pool->id);
+ pr_cont_pool_info(pool);
+
+- pr_cont(" active=%d refcnt=%d%s\n",
+- pwq->nr_active, pwq->refcnt,
++ pr_cont(" active=%d/%d refcnt=%d%s\n",
++ pwq->nr_active, pwq->max_active, pwq->refcnt,
+ !list_empty(&pwq->mayday_node) ? " MAYDAY" : "");
+
+ hash_for_each(pool->busy_hash, bkt, worker, hentry) {
+@@ -5698,7 +5203,7 @@ void show_one_workqueue(struct workqueue_struct *wq)
+ unsigned long flags;
+
+ for_each_pwq(pwq, wq) {
+- if (!pwq_is_empty(pwq)) {
++ if (pwq->nr_active || !list_empty(&pwq->inactive_works)) {
+ idle = false;
+ break;
+ }
+@@ -5710,7 +5215,7 @@ void show_one_workqueue(struct workqueue_struct *wq)
+
+ for_each_pwq(pwq, wq) {
+ raw_spin_lock_irqsave(&pwq->pool->lock, flags);
+- if (!pwq_is_empty(pwq)) {
++ if (pwq->nr_active || !list_empty(&pwq->inactive_works)) {
+ /*
+ * Defer printing to avoid deadlocks in console
+ * drivers that queue work while holding locks
+@@ -6057,10 +5562,6 @@ int workqueue_online_cpu(unsigned int cpu)
+
+ for_each_cpu(tcpu, pt->pod_cpus[pt->cpu_pod[cpu]])
+ wq_update_pod(wq, tcpu, cpu, true);
+-
+- mutex_lock(&wq->mutex);
+- wq_update_node_max_active(wq, -1);
+- mutex_unlock(&wq->mutex);
+ }
+ }
+
+@@ -6089,10 +5590,6 @@ int workqueue_offline_cpu(unsigned int cpu)
+
+ for_each_cpu(tcpu, pt->pod_cpus[pt->cpu_pod[cpu]])
+ wq_update_pod(wq, tcpu, cpu, false);
+-
+- mutex_lock(&wq->mutex);
+- wq_update_node_max_active(wq, cpu);
+- mutex_unlock(&wq->mutex);
+ }
+ }
+ mutex_unlock(&wq_pool_mutex);
+@@ -6180,6 +5677,7 @@ EXPORT_SYMBOL_GPL(work_on_cpu_safe_key);
+ void freeze_workqueues_begin(void)
+ {
+ struct workqueue_struct *wq;
++ struct pool_workqueue *pwq;
+
+ mutex_lock(&wq_pool_mutex);
+
+@@ -6188,7 +5686,8 @@ void freeze_workqueues_begin(void)
+
+ list_for_each_entry(wq, &workqueues, list) {
+ mutex_lock(&wq->mutex);
+- wq_adjust_max_active(wq);
++ for_each_pwq(pwq, wq)
++ pwq_adjust_max_active(pwq);
+ mutex_unlock(&wq->mutex);
+ }
+
+@@ -6253,6 +5752,7 @@ bool freeze_workqueues_busy(void)
+ void thaw_workqueues(void)
+ {
+ struct workqueue_struct *wq;
++ struct pool_workqueue *pwq;
+
+ mutex_lock(&wq_pool_mutex);
+
+@@ -6264,7 +5764,8 @@ void thaw_workqueues(void)
+ /* restore max_active and repopulate worklist */
+ list_for_each_entry(wq, &workqueues, list) {
+ mutex_lock(&wq->mutex);
+- wq_adjust_max_active(wq);
++ for_each_pwq(pwq, wq)
++ pwq_adjust_max_active(pwq);
+ mutex_unlock(&wq->mutex);
+ }
+
+@@ -7186,7 +6687,7 @@ void __init workqueue_init_early(void)
+ WQ_FREEZABLE, 0);
+ system_power_efficient_wq = alloc_workqueue("events_power_efficient",
+ WQ_POWER_EFFICIENT, 0);
+- system_freezable_power_efficient_wq = alloc_workqueue("events_freezable_pwr_efficient",
++ system_freezable_power_efficient_wq = alloc_workqueue("events_freezable_power_efficient",
+ WQ_FREEZABLE | WQ_POWER_EFFICIENT,
+ 0);
+ BUG_ON(!system_wq || !system_highpri_wq || !system_long_wq ||
+@@ -7373,12 +6874,8 @@ void __init workqueue_init_topology(void)
+ * combinations to apply per-pod sharing.
+ */
+ list_for_each_entry(wq, &workqueues, list) {
+- for_each_online_cpu(cpu)
++ for_each_online_cpu(cpu) {
+ wq_update_pod(wq, cpu, cpu, true);
+- if (wq->flags & WQ_UNBOUND) {
+- mutex_lock(&wq->mutex);
+- wq_update_node_max_active(wq, -1);
+- mutex_unlock(&wq->mutex);
+ }
+ }
+
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-04 19:22 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-04-04 19:22 UTC (permalink / raw
To: gentoo-commits
commit: f8b1656b3b322d7aa4d35ccd7d4739ebff2287ea
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Thu Apr 4 19:21:54 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Thu Apr 4 19:21:54 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=f8b1656b
BMQ Patch 6.8-r4 (USE=experimental)
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 2 +-
...atch => 5020_BMQ-and-PDS-io-scheduler-v6.8-r4.patch | 18 +++++++++---------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/0000_README b/0000_README
index 36e97fef..a4ecb94d 100644
--- a/0000_README
+++ b/0000_README
@@ -99,6 +99,6 @@ Patch: 5010_enable-cpu-optimizations-universal.patch
From: https://github.com/graysky2/kernel_compiler_patch
Desc: Kernel >= 5.15 patch enables gcc = v11.1+ optimizations for additional CPUs.
-Patch: 5020_BMQ-and-PDS-io-scheduler-v6.8-r2.patch
+Patch: 5020_BMQ-and-PDS-io-scheduler-v6.8-r4.patch
From: https://gitlab.com/alfredchen/projectc
Desc: BMQ(BitMap Queue) Scheduler. A new CPU scheduler developed from PDS(incld). Inspired by the scheduler in zircon.
diff --git a/5020_BMQ-and-PDS-io-scheduler-v6.8-r2.patch b/5020_BMQ-and-PDS-io-scheduler-v6.8-r4.patch
similarity index 99%
rename from 5020_BMQ-and-PDS-io-scheduler-v6.8-r2.patch
rename to 5020_BMQ-and-PDS-io-scheduler-v6.8-r4.patch
index f0f8c11e..6ade9048 100644
--- a/5020_BMQ-and-PDS-io-scheduler-v6.8-r2.patch
+++ b/5020_BMQ-and-PDS-io-scheduler-v6.8-r4.patch
@@ -663,10 +663,10 @@ index 976092b7bd45..31d587c16ec1 100644
obj-y += build_utility.o
diff --git a/kernel/sched/alt_core.c b/kernel/sched/alt_core.c
new file mode 100644
-index 000000000000..31fadbf46a7b
+index 000000000000..1044207ba0ad
--- /dev/null
+++ b/kernel/sched/alt_core.c
-@@ -0,0 +1,8944 @@
+@@ -0,0 +1,8945 @@
+/*
+ * kernel/sched/alt_core.c
+ *
@@ -745,7 +745,7 @@ index 000000000000..31fadbf46a7b
+#define sched_feat(x) (0)
+#endif /* CONFIG_SCHED_DEBUG */
+
-+#define ALT_SCHED_VERSION "v6.8-r2"
++#define ALT_SCHED_VERSION "v6.8-r4"
+
+/*
+ * Compile time debug macro
@@ -4920,8 +4920,8 @@ index 000000000000..31fadbf46a7b
+ stop_one_cpu_nowait(cpu, sg_balance_cpu_stop, p,
+ &rq->active_balance_work);
+
-+ raw_spin_lock(&src_rq->lock);
+ preempt_enable();
++ raw_spin_lock(&src_rq->lock);
+ }
+
+ return res;
@@ -6043,7 +6043,8 @@ index 000000000000..31fadbf46a7b
+ /* Avoid rq from going away on us: */
+ preempt_disable();
+
-+ __balance_callbacks(rq);
++ if (task_on_rq_queued(p))
++ __balance_callbacks(rq);
+ __task_access_unlock(p, lock);
+
+ preempt_enable();
@@ -10632,10 +10633,10 @@ index 000000000000..ba1b7b805f1a
+#endif /* ALT_SCHED_H */
diff --git a/kernel/sched/bmq.h b/kernel/sched/bmq.h
new file mode 100644
-index 000000000000..f270fd1b9086
+index 000000000000..b7c9813f6fa7
--- /dev/null
+++ b/kernel/sched/bmq.h
-@@ -0,0 +1,102 @@
+@@ -0,0 +1,101 @@
+#define ALT_SCHED_NAME "BMQ"
+
+/*
@@ -10715,8 +10716,7 @@ index 000000000000..f270fd1b9086
+
+static inline void sched_task_renew(struct task_struct *p, const struct rq *rq)
+{
-+ if (rq_switch_time(rq) > sysctl_sched_base_slice)
-+ deboost_task(p);
++ deboost_task(p);
+}
+
+static inline void sched_task_sanity_check(struct task_struct *p, struct rq *rq) {}
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-10 15:08 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-04-10 15:08 UTC (permalink / raw
To: gentoo-commits
commit: e3ba61c26d8c1c7a038d535ce9cde317e1c09797
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Wed Apr 10 15:08:04 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Wed Apr 10 15:08:04 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=e3ba61c2
Linux 6.8.5
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1004_linux-6.8.5.patch | 13982 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 13986 insertions(+)
diff --git a/0000_README b/0000_README
index a4ecb94d..d556a3be 100644
--- a/0000_README
+++ b/0000_README
@@ -59,6 +59,10 @@ Patch: 1003_linux-6.8.4.patch
From: https://www.kernel.org
Desc: Linux 6.8.4
+Patch: 1004_linux-6.8.5.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.5
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1004_linux-6.8.5.patch b/1004_linux-6.8.5.patch
new file mode 100644
index 00000000..af807239
--- /dev/null
+++ b/1004_linux-6.8.5.patch
@@ -0,0 +1,13982 @@
+diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst
+index 32a8893e56177..9edb2860a3e19 100644
+--- a/Documentation/admin-guide/hw-vuln/spectre.rst
++++ b/Documentation/admin-guide/hw-vuln/spectre.rst
+@@ -138,11 +138,10 @@ associated with the source address of the indirect branch. Specifically,
+ the BHB might be shared across privilege levels even in the presence of
+ Enhanced IBRS.
+
+-Currently the only known real-world BHB attack vector is via
+-unprivileged eBPF. Therefore, it's highly recommended to not enable
+-unprivileged eBPF, especially when eIBRS is used (without retpolines).
+-For a full mitigation against BHB attacks, it's recommended to use
+-retpolines (or eIBRS combined with retpolines).
++Previously the only known real-world BHB attack vector was via unprivileged
++eBPF. Further research has found attacks that don't require unprivileged eBPF.
++For a full mitigation against BHB attacks it is recommended to set BHI_DIS_S or
++use the BHB clearing sequence.
+
+ Attack scenarios
+ ----------------
+@@ -430,6 +429,23 @@ The possible values in this file are:
+ 'PBRSB-eIBRS: Not affected' CPU is not affected by PBRSB
+ =========================== =======================================================
+
++ - Branch History Injection (BHI) protection status:
++
++.. list-table::
++
++ * - BHI: Not affected
++ - System is not affected
++ * - BHI: Retpoline
++ - System is protected by retpoline
++ * - BHI: BHI_DIS_S
++ - System is protected by BHI_DIS_S
++ * - BHI: SW loop; KVM SW loop
++ - System is protected by software clearing sequence
++ * - BHI: Syscall hardening
++ - Syscalls are hardened against BHI
++ * - BHI: Syscall hardening; KVM: SW loop
++ - System is protected from userspace attacks by syscall hardening; KVM is protected by software clearing sequence
++
+ Full mitigation might require a microcode update from the CPU
+ vendor. When the necessary microcode is not available, the kernel will
+ report vulnerability.
+@@ -484,7 +500,11 @@ Spectre variant 2
+
+ Systems which support enhanced IBRS (eIBRS) enable IBRS protection once at
+ boot, by setting the IBRS bit, and they're automatically protected against
+- Spectre v2 variant attacks.
++ some Spectre v2 variant attacks. The BHB can still influence the choice of
++ indirect branch predictor entry, and although branch predictor entries are
++ isolated between modes when eIBRS is enabled, the BHB itself is not isolated
++ between modes. Systems which support BHI_DIS_S will set it to protect against
++ BHI attacks.
+
+ On Intel's enhanced IBRS systems, this includes cross-thread branch target
+ injections on SMT systems (STIBP). In other words, Intel eIBRS enables
+@@ -638,6 +658,22 @@ kernel command line.
+ spectre_v2=off. Spectre variant 1 mitigations
+ cannot be disabled.
+
++ spectre_bhi=
++
++ [X86] Control mitigation of Branch History Injection
++ (BHI) vulnerability. Syscalls are hardened against BHI
++ regardless of this setting. This setting affects the deployment
++ of the HW BHI control and the SW BHB clearing sequence.
++
++ on
++ unconditionally enable.
++ off
++ unconditionally disable.
++ auto
++ enable if hardware mitigation
++ control(BHI_DIS_S) is available, otherwise
++ enable alternate mitigation in KVM.
++
+ For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt
+
+ Mitigation selection guide
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index d2150bd3acc58..95efaccca4539 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -6031,6 +6031,18 @@
+ sonypi.*= [HW] Sony Programmable I/O Control Device driver
+ See Documentation/admin-guide/laptops/sonypi.rst
+
++ spectre_bhi= [X86] Control mitigation of Branch History Injection
++ (BHI) vulnerability. Syscalls are hardened against BHI
++ reglardless of this setting. This setting affects the
++ deployment of the HW BHI control and the SW BHB
++ clearing sequence.
++
++ on - unconditionally enable.
++ off - unconditionally disable.
++ auto - (default) enable hardware mitigation
++ (BHI_DIS_S) if available, otherwise enable
++ alternate mitigation in KVM.
++
+ spectre_v2= [X86] Control mitigation of Spectre variant 2
+ (indirect branch speculation) vulnerability.
+ The default operation protects the kernel from
+diff --git a/Makefile b/Makefile
+index c436247d750c7..f29a75b75861a 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 4
++SUBLEVEL = 5
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
+index 46aaeba286047..ebe37678102f0 100644
+--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
++++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
+@@ -943,6 +943,8 @@ bluetooth: bluetooth {
+ vddrf-supply = <&pp1300_l2c>;
+ vddch0-supply = <&pp3300_l10c>;
+ max-speed = <3200000>;
++
++ qcom,local-bd-address-broken;
+ };
+ };
+
+diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
+index e3bef38fc2e2d..964d0446dae9f 100644
+--- a/arch/arm64/kernel/ptrace.c
++++ b/arch/arm64/kernel/ptrace.c
+@@ -729,7 +729,6 @@ static void sve_init_header_from_task(struct user_sve_header *header,
+ {
+ unsigned int vq;
+ bool active;
+- bool fpsimd_only;
+ enum vec_type task_type;
+
+ memset(header, 0, sizeof(*header));
+@@ -745,12 +744,10 @@ static void sve_init_header_from_task(struct user_sve_header *header,
+ case ARM64_VEC_SVE:
+ if (test_tsk_thread_flag(target, TIF_SVE_VL_INHERIT))
+ header->flags |= SVE_PT_VL_INHERIT;
+- fpsimd_only = !test_tsk_thread_flag(target, TIF_SVE);
+ break;
+ case ARM64_VEC_SME:
+ if (test_tsk_thread_flag(target, TIF_SME_VL_INHERIT))
+ header->flags |= SVE_PT_VL_INHERIT;
+- fpsimd_only = false;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+@@ -758,7 +755,7 @@ static void sve_init_header_from_task(struct user_sve_header *header,
+ }
+
+ if (active) {
+- if (fpsimd_only) {
++ if (target->thread.fp_type == FP_STATE_FPSIMD) {
+ header->flags |= SVE_PT_REGS_FPSIMD;
+ } else {
+ header->flags |= SVE_PT_REGS_SVE;
+diff --git a/arch/arm64/kvm/hyp/nvhe/tlb.c b/arch/arm64/kvm/hyp/nvhe/tlb.c
+index a60fb13e21924..2fc68da4036d9 100644
+--- a/arch/arm64/kvm/hyp/nvhe/tlb.c
++++ b/arch/arm64/kvm/hyp/nvhe/tlb.c
+@@ -154,7 +154,8 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
+ /* Switch to requested VMID */
+ __tlb_switch_to_guest(mmu, &cxt, false);
+
+- __flush_s2_tlb_range_op(ipas2e1is, start, pages, stride, 0);
++ __flush_s2_tlb_range_op(ipas2e1is, start, pages, stride,
++ TLBI_TTL_UNKNOWN);
+
+ dsb(ish);
+ __tlbi(vmalle1is);
+diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
+index ab9d05fcf98b2..ce5cef7d73c41 100644
+--- a/arch/arm64/kvm/hyp/pgtable.c
++++ b/arch/arm64/kvm/hyp/pgtable.c
+@@ -829,12 +829,15 @@ static bool stage2_try_break_pte(const struct kvm_pgtable_visit_ctx *ctx,
+ * Perform the appropriate TLB invalidation based on the
+ * evicted pte value (if any).
+ */
+- if (kvm_pte_table(ctx->old, ctx->level))
+- kvm_tlb_flush_vmid_range(mmu, ctx->addr,
+- kvm_granule_size(ctx->level));
+- else if (kvm_pte_valid(ctx->old))
++ if (kvm_pte_table(ctx->old, ctx->level)) {
++ u64 size = kvm_granule_size(ctx->level);
++ u64 addr = ALIGN_DOWN(ctx->addr, size);
++
++ kvm_tlb_flush_vmid_range(mmu, addr, size);
++ } else if (kvm_pte_valid(ctx->old)) {
+ kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, mmu,
+ ctx->addr, ctx->level);
++ }
+ }
+
+ if (stage2_pte_is_counted(ctx->old))
+diff --git a/arch/arm64/kvm/hyp/vhe/tlb.c b/arch/arm64/kvm/hyp/vhe/tlb.c
+index b32e2940df7dc..1a60b95381e8e 100644
+--- a/arch/arm64/kvm/hyp/vhe/tlb.c
++++ b/arch/arm64/kvm/hyp/vhe/tlb.c
+@@ -171,7 +171,8 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
+ /* Switch to requested VMID */
+ __tlb_switch_to_guest(mmu, &cxt);
+
+- __flush_s2_tlb_range_op(ipas2e1is, start, pages, stride, 0);
++ __flush_s2_tlb_range_op(ipas2e1is, start, pages, stride,
++ TLBI_TTL_UNKNOWN);
+
+ dsb(ish);
+ __tlbi(vmalle1is);
+diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
+index d14504821b794..92270acfc00d4 100644
+--- a/arch/arm64/kvm/mmu.c
++++ b/arch/arm64/kvm/mmu.c
+@@ -1631,7 +1631,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
+ fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
+ is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
+
+- if (esr_fsc_is_permission_fault(esr)) {
++ if (esr_fsc_is_translation_fault(esr)) {
+ /* Beyond sanitised PARange (which is the IPA limit) */
+ if (fault_ipa >= BIT_ULL(get_kvm_ipa_limit())) {
+ kvm_inject_size_fault(vcpu);
+diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
+index 8955da5c47cf7..00217d8d034b7 100644
+--- a/arch/arm64/net/bpf_jit_comp.c
++++ b/arch/arm64/net/bpf_jit_comp.c
+@@ -876,7 +876,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
+ emit(A64_UXTH(is64, dst, dst), ctx);
+ break;
+ case 32:
+- emit(A64_REV32(is64, dst, dst), ctx);
++ emit(A64_REV32(0, dst, dst), ctx);
+ /* upper 32 bits already cleared */
+ break;
+ case 64:
+@@ -1189,7 +1189,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
+ } else {
+ emit_a64_mov_i(1, tmp, off, ctx);
+ if (sign_extend)
+- emit(A64_LDRSW(dst, src_adj, off_adj), ctx);
++ emit(A64_LDRSW(dst, src, tmp), ctx);
+ else
+ emit(A64_LDR32(dst, src, tmp), ctx);
+ }
+diff --git a/arch/powerpc/mm/book3s64/pgtable.c b/arch/powerpc/mm/book3s64/pgtable.c
+index 3438ab72c346b..d975fb5d7cbe4 100644
+--- a/arch/powerpc/mm/book3s64/pgtable.c
++++ b/arch/powerpc/mm/book3s64/pgtable.c
+@@ -130,7 +130,7 @@ void set_pud_at(struct mm_struct *mm, unsigned long addr,
+
+ WARN_ON(pte_hw_valid(pud_pte(*pudp)));
+ assert_spin_locked(pud_lockptr(mm, pudp));
+- WARN_ON(!(pud_large(pud)));
++ WARN_ON(!(pud_leaf(pud)));
+ #endif
+ trace_hugepage_set_pud(addr, pud_val(pud));
+ return set_pte_at(mm, addr, pudp_ptep(pudp), pud_pte(pud));
+diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h
+index ec0cab9fbddd0..72ec1d9bd3f31 100644
+--- a/arch/riscv/include/asm/uaccess.h
++++ b/arch/riscv/include/asm/uaccess.h
+@@ -319,7 +319,7 @@ unsigned long __must_check clear_user(void __user *to, unsigned long n)
+
+ #define __get_kernel_nofault(dst, src, type, err_label) \
+ do { \
+- long __kr_err; \
++ long __kr_err = 0; \
+ \
+ __get_user_nocheck(*((type *)(dst)), (type *)(src), __kr_err); \
+ if (unlikely(__kr_err)) \
+@@ -328,7 +328,7 @@ do { \
+
+ #define __put_kernel_nofault(dst, src, type, err_label) \
+ do { \
+- long __kr_err; \
++ long __kr_err = 0; \
+ \
+ __put_user_nocheck(*((type *)(src)), (type *)(dst), __kr_err); \
+ if (unlikely(__kr_err)) \
+diff --git a/arch/riscv/include/uapi/asm/auxvec.h b/arch/riscv/include/uapi/asm/auxvec.h
+index 10aaa83db89ef..95050ebe9ad00 100644
+--- a/arch/riscv/include/uapi/asm/auxvec.h
++++ b/arch/riscv/include/uapi/asm/auxvec.h
+@@ -34,7 +34,7 @@
+ #define AT_L3_CACHEGEOMETRY 47
+
+ /* entries in ARCH_DLINFO */
+-#define AT_VECTOR_SIZE_ARCH 9
++#define AT_VECTOR_SIZE_ARCH 10
+ #define AT_MINSIGSTKSZ 51
+
+ #endif /* _UAPI_ASM_RISCV_AUXVEC_H */
+diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c
+index 37e87fdcf6a00..30e12b310cab7 100644
+--- a/arch/riscv/kernel/patch.c
++++ b/arch/riscv/kernel/patch.c
+@@ -80,6 +80,8 @@ static int __patch_insn_set(void *addr, u8 c, size_t len)
+ */
+ lockdep_assert_held(&text_mutex);
+
++ preempt_disable();
++
+ if (across_pages)
+ patch_map(addr + PAGE_SIZE, FIX_TEXT_POKE1);
+
+@@ -92,6 +94,8 @@ static int __patch_insn_set(void *addr, u8 c, size_t len)
+ if (across_pages)
+ patch_unmap(FIX_TEXT_POKE1);
+
++ preempt_enable();
++
+ return 0;
+ }
+ NOKPROBE_SYMBOL(__patch_insn_set);
+@@ -122,6 +126,8 @@ static int __patch_insn_write(void *addr, const void *insn, size_t len)
+ if (!riscv_patch_in_stop_machine)
+ lockdep_assert_held(&text_mutex);
+
++ preempt_disable();
++
+ if (across_pages)
+ patch_map(addr + PAGE_SIZE, FIX_TEXT_POKE1);
+
+@@ -134,6 +140,8 @@ static int __patch_insn_write(void *addr, const void *insn, size_t len)
+ if (across_pages)
+ patch_unmap(FIX_TEXT_POKE1);
+
++ preempt_enable();
++
+ return ret;
+ }
+ NOKPROBE_SYMBOL(__patch_insn_write);
+diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
+index 92922dbd5b5c1..e4bc61c4e58af 100644
+--- a/arch/riscv/kernel/process.c
++++ b/arch/riscv/kernel/process.c
+@@ -27,8 +27,6 @@
+ #include <asm/vector.h>
+ #include <asm/cpufeature.h>
+
+-register unsigned long gp_in_global __asm__("gp");
+-
+ #if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_STACKPROTECTOR_PER_TASK)
+ #include <linux/stackprotector.h>
+ unsigned long __stack_chk_guard __read_mostly;
+@@ -37,7 +35,7 @@ EXPORT_SYMBOL(__stack_chk_guard);
+
+ extern asmlinkage void ret_from_fork(void);
+
+-void arch_cpu_idle(void)
++void noinstr arch_cpu_idle(void)
+ {
+ cpu_do_idle();
+ }
+@@ -207,7 +205,6 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
+ if (unlikely(args->fn)) {
+ /* Kernel thread */
+ memset(childregs, 0, sizeof(struct pt_regs));
+- childregs->gp = gp_in_global;
+ /* Supervisor/Machine, irqs on: */
+ childregs->status = SR_PP | SR_PIE;
+
+diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
+index 501e66debf697..5a2edd7f027e5 100644
+--- a/arch/riscv/kernel/signal.c
++++ b/arch/riscv/kernel/signal.c
+@@ -119,6 +119,13 @@ static long __restore_v_state(struct pt_regs *regs, void __user *sc_vec)
+ struct __sc_riscv_v_state __user *state = sc_vec;
+ void __user *datap;
+
++ /*
++ * Mark the vstate as clean prior performing the actual copy,
++ * to avoid getting the vstate incorrectly clobbered by the
++ * discarded vector state.
++ */
++ riscv_v_vstate_set_restore(current, regs);
++
+ /* Copy everything of __sc_riscv_v_state except datap. */
+ err = __copy_from_user(¤t->thread.vstate, &state->v_state,
+ offsetof(struct __riscv_v_ext_state, datap));
+@@ -133,13 +140,7 @@ static long __restore_v_state(struct pt_regs *regs, void __user *sc_vec)
+ * Copy the whole vector content from user space datap. Use
+ * copy_from_user to prevent information leak.
+ */
+- err = copy_from_user(current->thread.vstate.datap, datap, riscv_v_vsize);
+- if (unlikely(err))
+- return err;
+-
+- riscv_v_vstate_set_restore(current, regs);
+-
+- return err;
++ return copy_from_user(current->thread.vstate.datap, datap, riscv_v_vsize);
+ }
+ #else
+ #define save_v_state(task, regs) (0)
+diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
+index a1b9be3c4332d..142f5f5168fb1 100644
+--- a/arch/riscv/kernel/traps.c
++++ b/arch/riscv/kernel/traps.c
+@@ -121,7 +121,7 @@ void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr)
+ print_vma_addr(KERN_CONT " in ", instruction_pointer(regs));
+ pr_cont("\n");
+ __show_regs(regs);
+- dump_instr(KERN_EMERG, regs);
++ dump_instr(KERN_INFO, regs);
+ }
+
+ force_sig_fault(signo, code, (void __user *)addr);
+diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile
+index 9b517fe1b8a8e..272c431ac5b9f 100644
+--- a/arch/riscv/kernel/vdso/Makefile
++++ b/arch/riscv/kernel/vdso/Makefile
+@@ -37,6 +37,7 @@ endif
+
+ # Disable -pg to prevent insert call site
+ CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS)
++CFLAGS_REMOVE_hwprobe.o = $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS)
+
+ # Disable profiling and instrumentation for VDSO code
+ GCOV_PROFILE := n
+diff --git a/arch/riscv/kvm/aia_aplic.c b/arch/riscv/kvm/aia_aplic.c
+index 39e72aa016a4c..b467ba5ed9100 100644
+--- a/arch/riscv/kvm/aia_aplic.c
++++ b/arch/riscv/kvm/aia_aplic.c
+@@ -137,11 +137,21 @@ static void aplic_write_pending(struct aplic *aplic, u32 irq, bool pending)
+ raw_spin_lock_irqsave(&irqd->lock, flags);
+
+ sm = irqd->sourcecfg & APLIC_SOURCECFG_SM_MASK;
+- if (!pending &&
+- ((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) ||
+- (sm == APLIC_SOURCECFG_SM_LEVEL_LOW)))
++ if (sm == APLIC_SOURCECFG_SM_INACTIVE)
+ goto skip_write_pending;
+
++ if (sm == APLIC_SOURCECFG_SM_LEVEL_HIGH ||
++ sm == APLIC_SOURCECFG_SM_LEVEL_LOW) {
++ if (!pending)
++ goto skip_write_pending;
++ if ((irqd->state & APLIC_IRQ_STATE_INPUT) &&
++ sm == APLIC_SOURCECFG_SM_LEVEL_LOW)
++ goto skip_write_pending;
++ if (!(irqd->state & APLIC_IRQ_STATE_INPUT) &&
++ sm == APLIC_SOURCECFG_SM_LEVEL_HIGH)
++ goto skip_write_pending;
++ }
++
+ if (pending)
+ irqd->state |= APLIC_IRQ_STATE_PENDING;
+ else
+@@ -187,16 +197,31 @@ static void aplic_write_enabled(struct aplic *aplic, u32 irq, bool enabled)
+
+ static bool aplic_read_input(struct aplic *aplic, u32 irq)
+ {
+- bool ret;
+- unsigned long flags;
++ u32 sourcecfg, sm, raw_input, irq_inverted;
+ struct aplic_irq *irqd;
++ unsigned long flags;
++ bool ret = false;
+
+ if (!irq || aplic->nr_irqs <= irq)
+ return false;
+ irqd = &aplic->irqs[irq];
+
+ raw_spin_lock_irqsave(&irqd->lock, flags);
+- ret = (irqd->state & APLIC_IRQ_STATE_INPUT) ? true : false;
++
++ sourcecfg = irqd->sourcecfg;
++ if (sourcecfg & APLIC_SOURCECFG_D)
++ goto skip;
++
++ sm = sourcecfg & APLIC_SOURCECFG_SM_MASK;
++ if (sm == APLIC_SOURCECFG_SM_INACTIVE)
++ goto skip;
++
++ raw_input = (irqd->state & APLIC_IRQ_STATE_INPUT) ? 1 : 0;
++ irq_inverted = (sm == APLIC_SOURCECFG_SM_LEVEL_LOW ||
++ sm == APLIC_SOURCECFG_SM_EDGE_FALL) ? 1 : 0;
++ ret = !!(raw_input ^ irq_inverted);
++
++skip:
+ raw_spin_unlock_irqrestore(&irqd->lock, flags);
+
+ return ret;
+diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
+index 893566e004b73..07d743f87b3f6 100644
+--- a/arch/riscv/mm/tlbflush.c
++++ b/arch/riscv/mm/tlbflush.c
+@@ -99,7 +99,7 @@ static void __ipi_flush_tlb_range_asid(void *info)
+ local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid);
+ }
+
+-static void __flush_tlb_range(struct cpumask *cmask, unsigned long asid,
++static void __flush_tlb_range(const struct cpumask *cmask, unsigned long asid,
+ unsigned long start, unsigned long size,
+ unsigned long stride)
+ {
+@@ -200,7 +200,7 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+
+ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+ {
+- __flush_tlb_range((struct cpumask *)cpu_online_mask, FLUSH_TLB_NO_ASID,
++ __flush_tlb_range(cpu_online_mask, FLUSH_TLB_NO_ASID,
+ start, end - start, PAGE_SIZE);
+ }
+
+diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c
+index e3a4500a5a757..47e1f54c587ae 100644
+--- a/arch/s390/boot/vmem.c
++++ b/arch/s390/boot/vmem.c
+@@ -366,7 +366,7 @@ static void pgtable_pud_populate(p4d_t *p4d, unsigned long addr, unsigned long e
+ }
+ pmd = boot_crst_alloc(_SEGMENT_ENTRY_EMPTY);
+ pud_populate(&init_mm, pud, pmd);
+- } else if (pud_large(*pud)) {
++ } else if (pud_leaf(*pud)) {
+ continue;
+ }
+ pgtable_pmd_populate(pud, addr, next, mode);
+diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
+index 1299b56e43f6f..12a7b86789259 100644
+--- a/arch/s390/include/asm/pgtable.h
++++ b/arch/s390/include/asm/pgtable.h
+@@ -730,7 +730,7 @@ static inline int pud_bad(pud_t pud)
+ {
+ unsigned long type = pud_val(pud) & _REGION_ENTRY_TYPE_MASK;
+
+- if (type > _REGION_ENTRY_TYPE_R3 || pud_large(pud))
++ if (type > _REGION_ENTRY_TYPE_R3 || pud_leaf(pud))
+ return 1;
+ if (type < _REGION_ENTRY_TYPE_R3)
+ return 0;
+@@ -1398,7 +1398,7 @@ static inline unsigned long pud_deref(pud_t pud)
+ unsigned long origin_mask;
+
+ origin_mask = _REGION_ENTRY_ORIGIN;
+- if (pud_large(pud))
++ if (pud_leaf(pud))
+ origin_mask = _REGION3_ENTRY_ORIGIN_LARGE;
+ return (unsigned long)__va(pud_val(pud) & origin_mask);
+ }
+diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
+index 49a11f6dd7ae9..26c08ee877407 100644
+--- a/arch/s390/kernel/entry.S
++++ b/arch/s390/kernel/entry.S
+@@ -653,6 +653,7 @@ SYM_DATA_START_LOCAL(daton_psw)
+ SYM_DATA_END(daton_psw)
+
+ .section .rodata, "a"
++ .balign 8
+ #define SYSCALL(esame,emu) .quad __s390x_ ## esame
+ SYM_DATA_START(sys_call_table)
+ #include "asm/syscall_table.h"
+diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c
+index 522a5ea0a9f49..335e3f5d71f74 100644
+--- a/arch/s390/kernel/perf_pai_crypto.c
++++ b/arch/s390/kernel/perf_pai_crypto.c
+@@ -90,7 +90,6 @@ static void paicrypt_event_destroy(struct perf_event *event)
+ event->cpu);
+ struct paicrypt_map *cpump = mp->mapptr;
+
+- cpump->event = NULL;
+ static_branch_dec(&pai_key);
+ mutex_lock(&pai_reserve_mutex);
+ debug_sprintf_event(cfm_dbg, 5, "%s event %#llx cpu %d users %d"
+@@ -348,10 +347,15 @@ static int paicrypt_add(struct perf_event *event, int flags)
+
+ static void paicrypt_stop(struct perf_event *event, int flags)
+ {
+- if (!event->attr.sample_period) /* Counting */
++ struct paicrypt_mapptr *mp = this_cpu_ptr(paicrypt_root.mapptr);
++ struct paicrypt_map *cpump = mp->mapptr;
++
++ if (!event->attr.sample_period) { /* Counting */
+ paicrypt_read(event);
+- else /* Sampling */
++ } else { /* Sampling */
+ perf_sched_cb_dec(event->pmu);
++ cpump->event = NULL;
++ }
+ event->hw.state = PERF_HES_STOPPED;
+ }
+
+diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c
+index 95d1a890640a3..db37c38ddcee4 100644
+--- a/arch/s390/kernel/perf_pai_ext.c
++++ b/arch/s390/kernel/perf_pai_ext.c
+@@ -121,7 +121,6 @@ static void paiext_event_destroy(struct perf_event *event)
+ struct paiext_map *cpump = mp->mapptr;
+
+ mutex_lock(&paiext_reserve_mutex);
+- cpump->event = NULL;
+ if (refcount_dec_and_test(&cpump->refcnt)) /* Last reference gone */
+ paiext_free(mp);
+ paiext_root_free();
+@@ -355,10 +354,15 @@ static int paiext_add(struct perf_event *event, int flags)
+
+ static void paiext_stop(struct perf_event *event, int flags)
+ {
+- if (!event->attr.sample_period) /* Counting */
++ struct paiext_mapptr *mp = this_cpu_ptr(paiext_root.mapptr);
++ struct paiext_map *cpump = mp->mapptr;
++
++ if (!event->attr.sample_period) { /* Counting */
+ paiext_read(event);
+- else /* Sampling */
++ } else { /* Sampling */
+ perf_sched_cb_dec(event->pmu);
++ cpump->event = NULL;
++ }
+ event->hw.state = PERF_HES_STOPPED;
+ }
+
+diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
+index 8da39deb56ca4..08a7eca03daf7 100644
+--- a/arch/s390/mm/gmap.c
++++ b/arch/s390/mm/gmap.c
+@@ -596,7 +596,7 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr)
+ pud = pud_offset(p4d, vmaddr);
+ VM_BUG_ON(pud_none(*pud));
+ /* large puds cannot yet be handled */
+- if (pud_large(*pud))
++ if (pud_leaf(*pud))
+ return -EFAULT;
+ pmd = pmd_offset(pud, vmaddr);
+ VM_BUG_ON(pmd_none(*pmd));
+diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
+index 297a6d897d5a0..5f64f3d0fafbb 100644
+--- a/arch/s390/mm/hugetlbpage.c
++++ b/arch/s390/mm/hugetlbpage.c
+@@ -224,7 +224,7 @@ pte_t *huge_pte_offset(struct mm_struct *mm,
+ if (p4d_present(*p4dp)) {
+ pudp = pud_offset(p4dp, addr);
+ if (pud_present(*pudp)) {
+- if (pud_large(*pudp))
++ if (pud_leaf(*pudp))
+ return (pte_t *) pudp;
+ pmdp = pmd_offset(pudp, addr);
+ }
+@@ -240,7 +240,7 @@ int pmd_huge(pmd_t pmd)
+
+ int pud_huge(pud_t pud)
+ {
+- return pud_large(pud);
++ return pud_leaf(pud);
+ }
+
+ bool __init arch_hugetlb_valid_size(unsigned long size)
+diff --git a/arch/s390/mm/pageattr.c b/arch/s390/mm/pageattr.c
+index 631e3a4ee2de8..739185fc39ead 100644
+--- a/arch/s390/mm/pageattr.c
++++ b/arch/s390/mm/pageattr.c
+@@ -274,7 +274,7 @@ static int walk_pud_level(p4d_t *p4d, unsigned long addr, unsigned long end,
+ if (pud_none(*pudp))
+ return -EINVAL;
+ next = pud_addr_end(addr, end);
+- if (pud_large(*pudp)) {
++ if (pud_leaf(*pudp)) {
+ need_split = !!(flags & SET_MEMORY_4K);
+ need_split |= !!(addr & ~PUD_MASK);
+ need_split |= !!(addr + PUD_SIZE > next);
+diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
+index 99422926efe1b..3ff07b6bcd65a 100644
+--- a/arch/s390/mm/pgtable.c
++++ b/arch/s390/mm/pgtable.c
+@@ -470,7 +470,7 @@ static int pmd_lookup(struct mm_struct *mm, unsigned long addr, pmd_t **pmdp)
+ return -ENOENT;
+
+ /* Large PUDs are not supported yet. */
+- if (pud_large(*pud))
++ if (pud_leaf(*pud))
+ return -EFAULT;
+
+ *pmdp = pmd_offset(pud, addr);
+diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
+index 186a020857cf6..84e173c02ab91 100644
+--- a/arch/s390/mm/vmem.c
++++ b/arch/s390/mm/vmem.c
+@@ -323,7 +323,7 @@ static int modify_pud_table(p4d_t *p4d, unsigned long addr, unsigned long end,
+ if (!add) {
+ if (pud_none(*pud))
+ continue;
+- if (pud_large(*pud)) {
++ if (pud_leaf(*pud)) {
+ if (IS_ALIGNED(addr, PUD_SIZE) &&
+ IS_ALIGNED(next, PUD_SIZE)) {
+ pud_clear(pud);
+@@ -344,7 +344,7 @@ static int modify_pud_table(p4d_t *p4d, unsigned long addr, unsigned long end,
+ if (!pmd)
+ goto out;
+ pud_populate(&init_mm, pud, pmd);
+- } else if (pud_large(*pud)) {
++ } else if (pud_leaf(*pud)) {
+ continue;
+ }
+ ret = modify_pmd_table(pud, addr, next, add, direct);
+@@ -591,7 +591,7 @@ pte_t *vmem_get_alloc_pte(unsigned long addr, bool alloc)
+ if (!pmd)
+ goto out;
+ pud_populate(&init_mm, pud, pmd);
+- } else if (WARN_ON_ONCE(pud_large(*pud))) {
++ } else if (WARN_ON_ONCE(pud_leaf(*pud))) {
+ goto out;
+ }
+ pmd = pmd_offset(pud, addr);
+diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
+index b418333bb0863..5af0402e94b88 100644
+--- a/arch/s390/net/bpf_jit_comp.c
++++ b/arch/s390/net/bpf_jit_comp.c
+@@ -516,11 +516,12 @@ static void bpf_skip(struct bpf_jit *jit, int size)
+ * PLT for hotpatchable calls. The calling convention is the same as for the
+ * ftrace hotpatch trampolines: %r0 is return address, %r1 is clobbered.
+ */
+-extern const char bpf_plt[];
+-extern const char bpf_plt_ret[];
+-extern const char bpf_plt_target[];
+-extern const char bpf_plt_end[];
+-#define BPF_PLT_SIZE 32
++struct bpf_plt {
++ char code[16];
++ void *ret;
++ void *target;
++} __packed;
++extern const struct bpf_plt bpf_plt;
+ asm(
+ ".pushsection .rodata\n"
+ " .balign 8\n"
+@@ -531,15 +532,14 @@ asm(
+ " .balign 8\n"
+ "bpf_plt_ret: .quad 0\n"
+ "bpf_plt_target: .quad 0\n"
+- "bpf_plt_end:\n"
+ " .popsection\n"
+ );
+
+-static void bpf_jit_plt(void *plt, void *ret, void *target)
++static void bpf_jit_plt(struct bpf_plt *plt, void *ret, void *target)
+ {
+- memcpy(plt, bpf_plt, BPF_PLT_SIZE);
+- *(void **)((char *)plt + (bpf_plt_ret - bpf_plt)) = ret;
+- *(void **)((char *)plt + (bpf_plt_target - bpf_plt)) = target ?: ret;
++ memcpy(plt, &bpf_plt, sizeof(*plt));
++ plt->ret = ret;
++ plt->target = target;
+ }
+
+ /*
+@@ -662,9 +662,9 @@ static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth)
+ jit->prg = ALIGN(jit->prg, 8);
+ jit->prologue_plt = jit->prg;
+ if (jit->prg_buf)
+- bpf_jit_plt(jit->prg_buf + jit->prg,
++ bpf_jit_plt((struct bpf_plt *)(jit->prg_buf + jit->prg),
+ jit->prg_buf + jit->prologue_plt_ret, NULL);
+- jit->prg += BPF_PLT_SIZE;
++ jit->prg += sizeof(struct bpf_plt);
+ }
+
+ static int get_probe_mem_regno(const u8 *insn)
+@@ -2040,9 +2040,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
+ struct bpf_jit jit;
+ int pass;
+
+- if (WARN_ON_ONCE(bpf_plt_end - bpf_plt != BPF_PLT_SIZE))
+- return orig_fp;
+-
+ if (!fp->jit_requested)
+ return orig_fp;
+
+@@ -2148,14 +2145,11 @@ bool bpf_jit_supports_far_kfunc_call(void)
+ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
+ void *old_addr, void *new_addr)
+ {
++ struct bpf_plt expected_plt, current_plt, new_plt, *plt;
+ struct {
+ u16 opc;
+ s32 disp;
+ } __packed insn;
+- char expected_plt[BPF_PLT_SIZE];
+- char current_plt[BPF_PLT_SIZE];
+- char new_plt[BPF_PLT_SIZE];
+- char *plt;
+ char *ret;
+ int err;
+
+@@ -2174,18 +2168,18 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
+ */
+ } else {
+ /* Verify the PLT. */
+- plt = (char *)ip + (insn.disp << 1);
+- err = copy_from_kernel_nofault(current_plt, plt, BPF_PLT_SIZE);
++ plt = ip + (insn.disp << 1);
++ err = copy_from_kernel_nofault(¤t_plt, plt,
++ sizeof(current_plt));
+ if (err < 0)
+ return err;
+ ret = (char *)ip + 6;
+- bpf_jit_plt(expected_plt, ret, old_addr);
+- if (memcmp(current_plt, expected_plt, BPF_PLT_SIZE))
++ bpf_jit_plt(&expected_plt, ret, old_addr);
++ if (memcmp(¤t_plt, &expected_plt, sizeof(current_plt)))
+ return -EINVAL;
+ /* Adjust the call address. */
+- bpf_jit_plt(new_plt, ret, new_addr);
+- s390_kernel_write(plt + (bpf_plt_target - bpf_plt),
+- new_plt + (bpf_plt_target - bpf_plt),
++ bpf_jit_plt(&new_plt, ret, new_addr);
++ s390_kernel_write(&plt->target, &new_plt.target,
+ sizeof(void *));
+ }
+
+diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
+index f83017992eaae..d7db4e737218c 100644
+--- a/arch/sparc/mm/init_64.c
++++ b/arch/sparc/mm/init_64.c
+@@ -1665,7 +1665,7 @@ bool kern_addr_valid(unsigned long addr)
+ if (pud_none(*pud))
+ return false;
+
+- if (pud_large(*pud))
++ if (pud_leaf(*pud))
+ return pfn_valid(pud_pfn(*pud));
+
+ pmd = pmd_offset(pud, addr);
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 1847307056502..890ba8e48bc39 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -2612,6 +2612,31 @@ config MITIGATION_RFDS
+ stored in floating point, vector and integer registers.
+ See also <file:Documentation/admin-guide/hw-vuln/reg-file-data-sampling.rst>
+
++choice
++ prompt "Clear branch history"
++ depends on CPU_SUP_INTEL
++ default SPECTRE_BHI_ON
++ help
++ Enable BHI mitigations. BHI attacks are a form of Spectre V2 attacks
++ where the branch history buffer is poisoned to speculatively steer
++ indirect branches.
++ See <file:Documentation/admin-guide/hw-vuln/spectre.rst>
++
++config SPECTRE_BHI_ON
++ bool "on"
++ help
++ Equivalent to setting spectre_bhi=on command line parameter.
++config SPECTRE_BHI_OFF
++ bool "off"
++ help
++ Equivalent to setting spectre_bhi=off command line parameter.
++config SPECTRE_BHI_AUTO
++ bool "auto"
++ help
++ Equivalent to setting spectre_bhi=auto command line parameter.
++
++endchoice
++
+ endif
+
+ config ARCH_HAS_ADD_PAGES
+diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
+index f19c038409aa0..e9522c6893bee 100644
+--- a/arch/x86/boot/compressed/Makefile
++++ b/arch/x86/boot/compressed/Makefile
+@@ -84,7 +84,7 @@ LDFLAGS_vmlinux += -T
+ hostprogs := mkpiggy
+ HOST_EXTRACFLAGS += -I$(srctree)/tools/include
+
+-sed-voffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(_text\|__bss_start\|_end\)$$/\#define VO_\2 _AC(0x\1,UL)/p'
++sed-voffset := -e 's/^\([0-9a-fA-F]*\) [ABCDGRSTVW] \(_text\|__start_rodata\|__bss_start\|_end\)$$/\#define VO_\2 _AC(0x\1,UL)/p'
+
+ quiet_cmd_voffset = VOFFSET $@
+ cmd_voffset = $(NM) $< | sed -n $(sed-voffset) > $@
+diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
+index b99e08e6815b1..ee0fac468e7f7 100644
+--- a/arch/x86/boot/compressed/misc.c
++++ b/arch/x86/boot/compressed/misc.c
+@@ -330,6 +330,7 @@ static size_t parse_elf(void *output)
+ return ehdr.e_entry - LOAD_PHYSICAL_ADDR;
+ }
+
++const unsigned long kernel_text_size = VO___start_rodata - VO__text;
+ const unsigned long kernel_total_size = VO__end - VO__text;
+
+ static u8 boot_heap[BOOT_HEAP_SIZE] __aligned(4);
+@@ -357,6 +358,19 @@ unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr,
+ return entry;
+ }
+
++/*
++ * Set the memory encryption xloadflag based on the mem_encrypt= command line
++ * parameter, if provided.
++ */
++static void parse_mem_encrypt(struct setup_header *hdr)
++{
++ int on = cmdline_find_option_bool("mem_encrypt=on");
++ int off = cmdline_find_option_bool("mem_encrypt=off");
++
++ if (on > off)
++ hdr->xloadflags |= XLF_MEM_ENCRYPTION;
++}
++
+ /*
+ * The compressed kernel image (ZO), has been moved so that its position
+ * is against the end of the buffer used to hold the uncompressed kernel
+@@ -387,6 +401,8 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output)
+ /* Clear flags intended for solely in-kernel use. */
+ boot_params_ptr->hdr.loadflags &= ~KASLR_FLAG;
+
++ parse_mem_encrypt(&boot_params_ptr->hdr);
++
+ sanitize_boot_params(boot_params_ptr);
+
+ if (boot_params_ptr->screen_info.orig_video_mode == 7) {
+diff --git a/arch/x86/boot/compressed/sev.c b/arch/x86/boot/compressed/sev.c
+index 454acd7a2daff..4c9b752814177 100644
+--- a/arch/x86/boot/compressed/sev.c
++++ b/arch/x86/boot/compressed/sev.c
+@@ -116,6 +116,9 @@ static bool fault_in_kernel_space(unsigned long address)
+ #undef __init
+ #define __init
+
++#undef __head
++#define __head
++
+ #define __BOOT_COMPRESSED
+
+ /* Basic instruction decoding support needed */
+diff --git a/arch/x86/coco/core.c b/arch/x86/coco/core.c
+index d07be9d05cd03..ddd4efdc79d66 100644
+--- a/arch/x86/coco/core.c
++++ b/arch/x86/coco/core.c
+@@ -3,13 +3,17 @@
+ * Confidential Computing Platform Capability checks
+ *
+ * Copyright (C) 2021 Advanced Micro Devices, Inc.
++ * Copyright (C) 2024 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ *
+ * Author: Tom Lendacky <thomas.lendacky@amd.com>
+ */
+
+ #include <linux/export.h>
+ #include <linux/cc_platform.h>
++#include <linux/string.h>
++#include <linux/random.h>
+
++#include <asm/archrandom.h>
+ #include <asm/coco.h>
+ #include <asm/processor.h>
+
+@@ -148,3 +152,40 @@ u64 cc_mkdec(u64 val)
+ }
+ }
+ EXPORT_SYMBOL_GPL(cc_mkdec);
++
++__init void cc_random_init(void)
++{
++ /*
++ * The seed is 32 bytes (in units of longs), which is 256 bits, which
++ * is the security level that the RNG is targeting.
++ */
++ unsigned long rng_seed[32 / sizeof(long)];
++ size_t i, longs;
++
++ if (!cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
++ return;
++
++ /*
++ * Since the CoCo threat model includes the host, the only reliable
++ * source of entropy that can be neither observed nor manipulated is
++ * RDRAND. Usually, RDRAND failure is considered tolerable, but since
++ * CoCo guests have no other unobservable source of entropy, it's
++ * important to at least ensure the RNG gets some initial random seeds.
++ */
++ for (i = 0; i < ARRAY_SIZE(rng_seed); i += longs) {
++ longs = arch_get_random_longs(&rng_seed[i], ARRAY_SIZE(rng_seed) - i);
++
++ /*
++ * A zero return value means that the guest doesn't have RDRAND
++ * or the CPU is physically broken, and in both cases that
++ * means most crypto inside of the CoCo instance will be
++ * broken, defeating the purpose of CoCo in the first place. So
++ * just panic here because it's absolutely unsafe to continue
++ * executing.
++ */
++ if (longs == 0)
++ panic("RDRAND is defective.");
++ }
++ add_device_randomness(rng_seed, sizeof(rng_seed));
++ memzero_explicit(rng_seed, sizeof(rng_seed));
++}
+diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
+index 6356060caaf31..6de50b80702e6 100644
+--- a/arch/x86/entry/common.c
++++ b/arch/x86/entry/common.c
+@@ -49,7 +49,7 @@ static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr)
+
+ if (likely(unr < NR_syscalls)) {
+ unr = array_index_nospec(unr, NR_syscalls);
+- regs->ax = sys_call_table[unr](regs);
++ regs->ax = x64_sys_call(regs, unr);
+ return true;
+ }
+ return false;
+@@ -66,7 +66,7 @@ static __always_inline bool do_syscall_x32(struct pt_regs *regs, int nr)
+
+ if (IS_ENABLED(CONFIG_X86_X32_ABI) && likely(xnr < X32_NR_syscalls)) {
+ xnr = array_index_nospec(xnr, X32_NR_syscalls);
+- regs->ax = x32_sys_call_table[xnr](regs);
++ regs->ax = x32_sys_call(regs, xnr);
+ return true;
+ }
+ return false;
+@@ -162,7 +162,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, int nr)
+
+ if (likely(unr < IA32_NR_syscalls)) {
+ unr = array_index_nospec(unr, IA32_NR_syscalls);
+- regs->ax = ia32_sys_call_table[unr](regs);
++ regs->ax = ia32_sys_call(regs, unr);
+ } else if (nr != -1) {
+ regs->ax = __ia32_sys_ni_syscall(regs);
+ }
+@@ -189,7 +189,7 @@ static __always_inline bool int80_is_external(void)
+ }
+
+ /**
+- * int80_emulation - 32-bit legacy syscall entry
++ * do_int80_emulation - 32-bit legacy syscall C entry from asm
+ *
+ * This entry point can be used by 32-bit and 64-bit programs to perform
+ * 32-bit system calls. Instances of INT $0x80 can be found inline in
+@@ -207,7 +207,7 @@ static __always_inline bool int80_is_external(void)
+ * eax: system call number
+ * ebx, ecx, edx, esi, edi, ebp: arg1 - arg 6
+ */
+-DEFINE_IDTENTRY_RAW(int80_emulation)
++__visible noinstr void do_int80_emulation(struct pt_regs *regs)
+ {
+ int nr;
+
+diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
+index 9bb4859776291..e986331b14e1d 100644
+--- a/arch/x86/entry/entry_64.S
++++ b/arch/x86/entry/entry_64.S
+@@ -116,6 +116,7 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL)
+ /* clobbers %rax, make sure it is after saving the syscall nr */
+ IBRS_ENTER
+ UNTRAIN_RET
++ CLEAR_BRANCH_HISTORY
+
+ call do_syscall_64 /* returns with IRQs disabled */
+
+@@ -1494,3 +1495,63 @@ SYM_CODE_START_NOALIGN(rewind_stack_and_make_dead)
+ call make_task_dead
+ SYM_CODE_END(rewind_stack_and_make_dead)
+ .popsection
++
++/*
++ * This sequence executes branches in order to remove user branch information
++ * from the branch history tracker in the Branch Predictor, therefore removing
++ * user influence on subsequent BTB lookups.
++ *
++ * It should be used on parts prior to Alder Lake. Newer parts should use the
++ * BHI_DIS_S hardware control instead. If a pre-Alder Lake part is being
++ * virtualized on newer hardware the VMM should protect against BHI attacks by
++ * setting BHI_DIS_S for the guests.
++ *
++ * CALLs/RETs are necessary to prevent Loop Stream Detector(LSD) from engaging
++ * and not clearing the branch history. The call tree looks like:
++ *
++ * call 1
++ * call 2
++ * call 2
++ * call 2
++ * call 2
++ * call 2
++ * ret
++ * ret
++ * ret
++ * ret
++ * ret
++ * ret
++ *
++ * This means that the stack is non-constant and ORC can't unwind it with %rsp
++ * alone. Therefore we unconditionally set up the frame pointer, which allows
++ * ORC to unwind properly.
++ *
++ * The alignment is for performance and not for safety, and may be safely
++ * refactored in the future if needed.
++ */
++SYM_FUNC_START(clear_bhb_loop)
++ push %rbp
++ mov %rsp, %rbp
++ movl $5, %ecx
++ ANNOTATE_INTRA_FUNCTION_CALL
++ call 1f
++ jmp 5f
++ .align 64, 0xcc
++ ANNOTATE_INTRA_FUNCTION_CALL
++1: call 2f
++ RET
++ .align 64, 0xcc
++2: movl $5, %eax
++3: jmp 4f
++ nop
++4: sub $1, %eax
++ jnz 3b
++ sub $1, %ecx
++ jnz 1b
++ RET
++5: lfence
++ pop %rbp
++ RET
++SYM_FUNC_END(clear_bhb_loop)
++EXPORT_SYMBOL_GPL(clear_bhb_loop)
++STACK_FRAME_NON_STANDARD(clear_bhb_loop)
+diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
+index eabf48c4d4b4c..c779046cc3fe7 100644
+--- a/arch/x86/entry/entry_64_compat.S
++++ b/arch/x86/entry/entry_64_compat.S
+@@ -92,6 +92,7 @@ SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL)
+
+ IBRS_ENTER
+ UNTRAIN_RET
++ CLEAR_BRANCH_HISTORY
+
+ /*
+ * SYSENTER doesn't filter flags, so we need to clear NT and AC
+@@ -206,6 +207,7 @@ SYM_INNER_LABEL(entry_SYSCALL_compat_after_hwframe, SYM_L_GLOBAL)
+
+ IBRS_ENTER
+ UNTRAIN_RET
++ CLEAR_BRANCH_HISTORY
+
+ movq %rsp, %rdi
+ call do_fast_syscall_32
+@@ -276,3 +278,17 @@ SYM_INNER_LABEL(entry_SYSRETL_compat_end, SYM_L_GLOBAL)
+ ANNOTATE_NOENDBR
+ int3
+ SYM_CODE_END(entry_SYSCALL_compat)
++
++/*
++ * int 0x80 is used by 32 bit mode as a system call entry. Normally idt entries
++ * point to C routines, however since this is a system call interface the branch
++ * history needs to be scrubbed to protect against BHI attacks, and that
++ * scrubbing needs to take place in assembly code prior to entering any C
++ * routines.
++ */
++SYM_CODE_START(int80_emulation)
++ ANNOTATE_NOENDBR
++ UNWIND_HINT_FUNC
++ CLEAR_BRANCH_HISTORY
++ jmp do_int80_emulation
++SYM_CODE_END(int80_emulation)
+diff --git a/arch/x86/entry/syscall_32.c b/arch/x86/entry/syscall_32.c
+index 8cfc9bc73e7f8..c2235bae17ef6 100644
+--- a/arch/x86/entry/syscall_32.c
++++ b/arch/x86/entry/syscall_32.c
+@@ -18,8 +18,25 @@
+ #include <asm/syscalls_32.h>
+ #undef __SYSCALL
+
++/*
++ * The sys_call_table[] is no longer used for system calls, but
++ * kernel/trace/trace_syscalls.c still wants to know the system
++ * call address.
++ */
++#ifdef CONFIG_X86_32
+ #define __SYSCALL(nr, sym) __ia32_##sym,
+-
+-__visible const sys_call_ptr_t ia32_sys_call_table[] = {
++const sys_call_ptr_t sys_call_table[] = {
+ #include <asm/syscalls_32.h>
+ };
++#undef __SYSCALL
++#endif
++
++#define __SYSCALL(nr, sym) case nr: return __ia32_##sym(regs);
++
++long ia32_sys_call(const struct pt_regs *regs, unsigned int nr)
++{
++ switch (nr) {
++ #include <asm/syscalls_32.h>
++ default: return __ia32_sys_ni_syscall(regs);
++ }
++};
+diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c
+index be120eec1fc9f..33b3f09e6f151 100644
+--- a/arch/x86/entry/syscall_64.c
++++ b/arch/x86/entry/syscall_64.c
+@@ -11,8 +11,23 @@
+ #include <asm/syscalls_64.h>
+ #undef __SYSCALL
+
++/*
++ * The sys_call_table[] is no longer used for system calls, but
++ * kernel/trace/trace_syscalls.c still wants to know the system
++ * call address.
++ */
+ #define __SYSCALL(nr, sym) __x64_##sym,
+-
+-asmlinkage const sys_call_ptr_t sys_call_table[] = {
++const sys_call_ptr_t sys_call_table[] = {
+ #include <asm/syscalls_64.h>
+ };
++#undef __SYSCALL
++
++#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs);
++
++long x64_sys_call(const struct pt_regs *regs, unsigned int nr)
++{
++ switch (nr) {
++ #include <asm/syscalls_64.h>
++ default: return __x64_sys_ni_syscall(regs);
++ }
++};
+diff --git a/arch/x86/entry/syscall_x32.c b/arch/x86/entry/syscall_x32.c
+index bdd0e03a1265d..03de4a9321318 100644
+--- a/arch/x86/entry/syscall_x32.c
++++ b/arch/x86/entry/syscall_x32.c
+@@ -11,8 +11,12 @@
+ #include <asm/syscalls_x32.h>
+ #undef __SYSCALL
+
+-#define __SYSCALL(nr, sym) __x64_##sym,
++#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs);
+
+-asmlinkage const sys_call_ptr_t x32_sys_call_table[] = {
+-#include <asm/syscalls_x32.h>
++long x32_sys_call(const struct pt_regs *regs, unsigned int nr)
++{
++ switch (nr) {
++ #include <asm/syscalls_x32.h>
++ default: return __x64_sys_ni_syscall(regs);
++ }
+ };
+diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
+index d49d661ec0a7d..807de7b596ab7 100644
+--- a/arch/x86/events/intel/ds.c
++++ b/arch/x86/events/intel/ds.c
+@@ -1236,11 +1236,11 @@ pebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc,
+ struct pmu *pmu = event->pmu;
+
+ /*
+- * Make sure we get updated with the first PEBS
+- * event. It will trigger also during removal, but
+- * that does not hurt:
++ * Make sure we get updated with the first PEBS event.
++ * During removal, ->pebs_data_cfg is still valid for
++ * the last PEBS event. Don't clear it.
+ */
+- if (cpuc->n_pebs == 1)
++ if ((cpuc->n_pebs == 1) && add)
+ cpuc->pebs_data_cfg = PEBS_UPDATE_DS_SW;
+
+ if (needed_cb != pebs_needs_sched_cb(cpuc)) {
+diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h
+index a38cc0afc90a0..a3e0be0470a40 100644
+--- a/arch/x86/include/asm/boot.h
++++ b/arch/x86/include/asm/boot.h
+@@ -81,6 +81,7 @@
+
+ #ifndef __ASSEMBLY__
+ extern unsigned int output_len;
++extern const unsigned long kernel_text_size;
+ extern const unsigned long kernel_total_size;
+
+ unsigned long decompress_kernel(unsigned char *outbuf, unsigned long virt_addr,
+diff --git a/arch/x86/include/asm/coco.h b/arch/x86/include/asm/coco.h
+index 18bbdda053221..3dd052bfefc51 100644
+--- a/arch/x86/include/asm/coco.h
++++ b/arch/x86/include/asm/coco.h
+@@ -21,6 +21,7 @@ static inline void cc_set_mask(u64 mask)
+
+ u64 cc_mkenc(u64 val);
+ u64 cc_mkdec(u64 val);
++void cc_random_init(void);
+ #else
+ #define cc_vendor (CC_VENDOR_NONE)
+
+@@ -33,6 +34,7 @@ static inline u64 cc_mkdec(u64 val)
+ {
+ return val;
+ }
++static inline void cc_random_init(void) { }
+ #endif
+
+ #endif /* _ASM_X86_COCO_H */
+diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
+index a1273698fc430..686e92d2663ee 100644
+--- a/arch/x86/include/asm/cpufeature.h
++++ b/arch/x86/include/asm/cpufeature.h
+@@ -33,6 +33,8 @@ enum cpuid_leafs
+ CPUID_7_EDX,
+ CPUID_8000_001F_EAX,
+ CPUID_8000_0021_EAX,
++ CPUID_LNX_5,
++ NR_CPUID_WORDS,
+ };
+
+ #define X86_CAP_FMT_NUM "%d:%d"
+@@ -91,8 +93,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
+ CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 18, feature_bit) || \
+ CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 19, feature_bit) || \
+ CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 20, feature_bit) || \
++ CHECK_BIT_IN_MASK_WORD(REQUIRED_MASK, 21, feature_bit) || \
+ REQUIRED_MASK_CHECK || \
+- BUILD_BUG_ON_ZERO(NCAPINTS != 21))
++ BUILD_BUG_ON_ZERO(NCAPINTS != 22))
+
+ #define DISABLED_MASK_BIT_SET(feature_bit) \
+ ( CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 0, feature_bit) || \
+@@ -116,8 +119,9 @@ extern const char * const x86_bug_flags[NBUGINTS*32];
+ CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 18, feature_bit) || \
+ CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 19, feature_bit) || \
+ CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 20, feature_bit) || \
++ CHECK_BIT_IN_MASK_WORD(DISABLED_MASK, 21, feature_bit) || \
+ DISABLED_MASK_CHECK || \
+- BUILD_BUG_ON_ZERO(NCAPINTS != 21))
++ BUILD_BUG_ON_ZERO(NCAPINTS != 22))
+
+ #define cpu_has(c, bit) \
+ (__builtin_constant_p(bit) && REQUIRED_MASK_BIT_SET(bit) ? 1 : \
+diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
+index 8511aad595813..76b3b00ff1021 100644
+--- a/arch/x86/include/asm/cpufeatures.h
++++ b/arch/x86/include/asm/cpufeatures.h
+@@ -13,7 +13,7 @@
+ /*
+ * Defines x86 CPU feature bits
+ */
+-#define NCAPINTS 21 /* N 32-bit words worth of info */
++#define NCAPINTS 22 /* N 32-bit words worth of info */
+ #define NBUGINTS 2 /* N 32-bit bug flags */
+
+ /*
+@@ -456,6 +456,17 @@
+ #define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* "" MSR_PRED_CMD[IBPB] flushes all branch type predictions */
+ #define X86_FEATURE_SRSO_NO (20*32+29) /* "" CPU is not affected by SRSO */
+
++/*
++ * Extended auxiliary flags: Linux defined - for features scattered in various
++ * CPUID levels like 0x80000022, etc and Linux defined features.
++ *
++ * Reuse free bits when adding new feature flags!
++ */
++#define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* "" Clear branch history at syscall entry using SW loop */
++#define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */
++#define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */
++#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */
++
+ /*
+ * BUG word(s)
+ */
+@@ -504,4 +515,5 @@
+ #define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */
+ #define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */
+ #define X86_BUG_RFDS X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */
++#define X86_BUG_BHI X86_BUG(1*32 + 3) /* CPU is affected by Branch History Injection */
+ #endif /* _ASM_X86_CPUFEATURES_H */
+diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
+index 702d93fdd10e8..88fcf08458d9c 100644
+--- a/arch/x86/include/asm/disabled-features.h
++++ b/arch/x86/include/asm/disabled-features.h
+@@ -143,6 +143,7 @@
+ #define DISABLED_MASK18 (DISABLE_IBT)
+ #define DISABLED_MASK19 0
+ #define DISABLED_MASK20 0
+-#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 21)
++#define DISABLED_MASK21 0
++#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 22)
+
+ #endif /* _ASM_X86_DISABLED_FEATURES_H */
+diff --git a/arch/x86/include/asm/mem_encrypt.h b/arch/x86/include/asm/mem_encrypt.h
+index b31eb9fd59544..f922b682b9b4c 100644
+--- a/arch/x86/include/asm/mem_encrypt.h
++++ b/arch/x86/include/asm/mem_encrypt.h
+@@ -47,8 +47,8 @@ void __init sme_unmap_bootdata(char *real_mode_data);
+
+ void __init sme_early_init(void);
+
+-void __init sme_encrypt_kernel(struct boot_params *bp);
+-void __init sme_enable(struct boot_params *bp);
++void sme_encrypt_kernel(struct boot_params *bp);
++void sme_enable(struct boot_params *bp);
+
+ int __init early_set_memory_decrypted(unsigned long vaddr, unsigned long size);
+ int __init early_set_memory_encrypted(unsigned long vaddr, unsigned long size);
+@@ -81,8 +81,8 @@ static inline void __init sme_unmap_bootdata(char *real_mode_data) { }
+
+ static inline void __init sme_early_init(void) { }
+
+-static inline void __init sme_encrypt_kernel(struct boot_params *bp) { }
+-static inline void __init sme_enable(struct boot_params *bp) { }
++static inline void sme_encrypt_kernel(struct boot_params *bp) { }
++static inline void sme_enable(struct boot_params *bp) { }
+
+ static inline void sev_es_init_vc_handling(void) { }
+
+diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
+index d1b5edaf6c34b..d65f8ce6b7cf0 100644
+--- a/arch/x86/include/asm/msr-index.h
++++ b/arch/x86/include/asm/msr-index.h
+@@ -50,10 +50,13 @@
+ #define SPEC_CTRL_SSBD BIT(SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */
+ #define SPEC_CTRL_RRSBA_DIS_S_SHIFT 6 /* Disable RRSBA behavior */
+ #define SPEC_CTRL_RRSBA_DIS_S BIT(SPEC_CTRL_RRSBA_DIS_S_SHIFT)
++#define SPEC_CTRL_BHI_DIS_S_SHIFT 10 /* Disable Branch History Injection behavior */
++#define SPEC_CTRL_BHI_DIS_S BIT(SPEC_CTRL_BHI_DIS_S_SHIFT)
+
+ /* A mask for bits which the kernel toggles when controlling mitigations */
+ #define SPEC_CTRL_MITIGATIONS_MASK (SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD \
+- | SPEC_CTRL_RRSBA_DIS_S)
++ | SPEC_CTRL_RRSBA_DIS_S \
++ | SPEC_CTRL_BHI_DIS_S)
+
+ #define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */
+ #define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */
+@@ -152,6 +155,10 @@
+ * are restricted to targets in
+ * kernel.
+ */
++#define ARCH_CAP_BHI_NO BIT(20) /*
++ * CPU is not affected by Branch
++ * History Injection.
++ */
+ #define ARCH_CAP_PBRSB_NO BIT(24) /*
+ * Not susceptible to Post-Barrier
+ * Return Stack Buffer Predictions.
+diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
+index 93c3e28dd8e0e..3ff081a74ab2b 100644
+--- a/arch/x86/include/asm/nospec-branch.h
++++ b/arch/x86/include/asm/nospec-branch.h
+@@ -335,6 +335,19 @@
+ ALTERNATIVE "", __stringify(verw _ASM_RIP(mds_verw_sel)), X86_FEATURE_CLEAR_CPU_BUF
+ .endm
+
++#ifdef CONFIG_X86_64
++.macro CLEAR_BRANCH_HISTORY
++ ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP
++.endm
++
++.macro CLEAR_BRANCH_HISTORY_VMEXIT
++ ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT
++.endm
++#else
++#define CLEAR_BRANCH_HISTORY
++#define CLEAR_BRANCH_HISTORY_VMEXIT
++#endif
++
+ #else /* __ASSEMBLY__ */
+
+ #define ANNOTATE_RETPOLINE_SAFE \
+@@ -377,6 +390,10 @@ extern void srso_alias_return_thunk(void);
+ extern void entry_untrain_ret(void);
+ extern void entry_ibpb(void);
+
++#ifdef CONFIG_X86_64
++extern void clear_bhb_loop(void);
++#endif
++
+ extern void (*x86_return_thunk)(void);
+
+ #ifdef CONFIG_CALL_DEPTH_TRACKING
+diff --git a/arch/x86/include/asm/required-features.h b/arch/x86/include/asm/required-features.h
+index 7ba1726b71c7b..e9187ddd3d1fd 100644
+--- a/arch/x86/include/asm/required-features.h
++++ b/arch/x86/include/asm/required-features.h
+@@ -99,6 +99,7 @@
+ #define REQUIRED_MASK18 0
+ #define REQUIRED_MASK19 0
+ #define REQUIRED_MASK20 0
+-#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 21)
++#define REQUIRED_MASK21 0
++#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 22)
+
+ #endif /* _ASM_X86_REQUIRED_FEATURES_H */
+diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h
+index 36f905797075e..75a5388d40681 100644
+--- a/arch/x86/include/asm/sev.h
++++ b/arch/x86/include/asm/sev.h
+@@ -199,15 +199,15 @@ static inline int pvalidate(unsigned long vaddr, bool rmp_psize, bool validate)
+ struct snp_guest_request_ioctl;
+
+ void setup_ghcb(void);
+-void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
+- unsigned long npages);
+-void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
+- unsigned long npages);
++void early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
++ unsigned long npages);
++void early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
++ unsigned long npages);
+ void snp_set_memory_shared(unsigned long vaddr, unsigned long npages);
+ void snp_set_memory_private(unsigned long vaddr, unsigned long npages);
+ void snp_set_wakeup_secondary_cpu(void);
+ bool snp_init(struct boot_params *bp);
+-void __init __noreturn snp_abort(void);
++void __noreturn snp_abort(void);
+ void snp_dmi_setup(void);
+ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, struct snp_guest_request_ioctl *rio);
+ void snp_accept_memory(phys_addr_t start, phys_addr_t end);
+diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h
+index f44e2f9ab65d7..2fc7bc3863ff6 100644
+--- a/arch/x86/include/asm/syscall.h
++++ b/arch/x86/include/asm/syscall.h
+@@ -16,19 +16,17 @@
+ #include <asm/thread_info.h> /* for TS_COMPAT */
+ #include <asm/unistd.h>
+
++/* This is used purely for kernel/trace/trace_syscalls.c */
+ typedef long (*sys_call_ptr_t)(const struct pt_regs *);
+ extern const sys_call_ptr_t sys_call_table[];
+
+-#if defined(CONFIG_X86_32)
+-#define ia32_sys_call_table sys_call_table
+-#else
+ /*
+ * These may not exist, but still put the prototypes in so we
+ * can use IS_ENABLED().
+ */
+-extern const sys_call_ptr_t ia32_sys_call_table[];
+-extern const sys_call_ptr_t x32_sys_call_table[];
+-#endif
++extern long ia32_sys_call(const struct pt_regs *, unsigned int nr);
++extern long x32_sys_call(const struct pt_regs *, unsigned int nr);
++extern long x64_sys_call(const struct pt_regs *, unsigned int nr);
+
+ /*
+ * Only the low 32 bits of orig_ax are meaningful, so we return int.
+@@ -127,6 +125,7 @@ static inline int syscall_get_arch(struct task_struct *task)
+ }
+
+ bool do_syscall_64(struct pt_regs *regs, int nr);
++void do_int80_emulation(struct pt_regs *regs);
+
+ #endif /* CONFIG_X86_32 */
+
+diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
+index 01d19fc223463..eeea058cf6028 100644
+--- a/arch/x86/include/uapi/asm/bootparam.h
++++ b/arch/x86/include/uapi/asm/bootparam.h
+@@ -38,6 +38,7 @@
+ #define XLF_EFI_KEXEC (1<<4)
+ #define XLF_5LEVEL (1<<5)
+ #define XLF_5LEVEL_ENABLED (1<<6)
++#define XLF_MEM_ENCRYPTION (1<<7)
+
+ #ifndef __ASSEMBLY__
+
+diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
+index 01ac18f56147f..0d7238d88b38a 100644
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -1606,6 +1606,79 @@ static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_
+ dump_stack();
+ }
+
++/*
++ * Set BHI_DIS_S to prevent indirect branches in kernel to be influenced by
++ * branch history in userspace. Not needed if BHI_NO is set.
++ */
++static bool __init spec_ctrl_bhi_dis(void)
++{
++ if (!boot_cpu_has(X86_FEATURE_BHI_CTRL))
++ return false;
++
++ x86_spec_ctrl_base |= SPEC_CTRL_BHI_DIS_S;
++ update_spec_ctrl(x86_spec_ctrl_base);
++ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_HW);
++
++ return true;
++}
++
++enum bhi_mitigations {
++ BHI_MITIGATION_OFF,
++ BHI_MITIGATION_ON,
++ BHI_MITIGATION_AUTO,
++};
++
++static enum bhi_mitigations bhi_mitigation __ro_after_init =
++ IS_ENABLED(CONFIG_SPECTRE_BHI_ON) ? BHI_MITIGATION_ON :
++ IS_ENABLED(CONFIG_SPECTRE_BHI_OFF) ? BHI_MITIGATION_OFF :
++ BHI_MITIGATION_AUTO;
++
++static int __init spectre_bhi_parse_cmdline(char *str)
++{
++ if (!str)
++ return -EINVAL;
++
++ if (!strcmp(str, "off"))
++ bhi_mitigation = BHI_MITIGATION_OFF;
++ else if (!strcmp(str, "on"))
++ bhi_mitigation = BHI_MITIGATION_ON;
++ else if (!strcmp(str, "auto"))
++ bhi_mitigation = BHI_MITIGATION_AUTO;
++ else
++ pr_err("Ignoring unknown spectre_bhi option (%s)", str);
++
++ return 0;
++}
++early_param("spectre_bhi", spectre_bhi_parse_cmdline);
++
++static void __init bhi_select_mitigation(void)
++{
++ if (bhi_mitigation == BHI_MITIGATION_OFF)
++ return;
++
++ /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */
++ if (cpu_feature_enabled(X86_FEATURE_RETPOLINE) &&
++ !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA))
++ return;
++
++ if (spec_ctrl_bhi_dis())
++ return;
++
++ if (!IS_ENABLED(CONFIG_X86_64))
++ return;
++
++ /* Mitigate KVM by default */
++ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT);
++ pr_info("Spectre BHI mitigation: SW BHB clearing on vm exit\n");
++
++ if (bhi_mitigation == BHI_MITIGATION_AUTO)
++ return;
++
++ /* Mitigate syscalls when the mitigation is forced =on */
++ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP);
++ pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n");
++}
++
+ static void __init spectre_v2_select_mitigation(void)
+ {
+ enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
+@@ -1717,6 +1790,9 @@ static void __init spectre_v2_select_mitigation(void)
+ mode == SPECTRE_V2_RETPOLINE)
+ spec_ctrl_disable_kernel_rrsba();
+
++ if (boot_cpu_has(X86_BUG_BHI))
++ bhi_select_mitigation();
++
+ spectre_v2_enabled = mode;
+ pr_info("%s\n", spectre_v2_strings[mode]);
+
+@@ -2694,15 +2770,15 @@ static char *stibp_state(void)
+
+ switch (spectre_v2_user_stibp) {
+ case SPECTRE_V2_USER_NONE:
+- return ", STIBP: disabled";
++ return "; STIBP: disabled";
+ case SPECTRE_V2_USER_STRICT:
+- return ", STIBP: forced";
++ return "; STIBP: forced";
+ case SPECTRE_V2_USER_STRICT_PREFERRED:
+- return ", STIBP: always-on";
++ return "; STIBP: always-on";
+ case SPECTRE_V2_USER_PRCTL:
+ case SPECTRE_V2_USER_SECCOMP:
+ if (static_key_enabled(&switch_to_cond_stibp))
+- return ", STIBP: conditional";
++ return "; STIBP: conditional";
+ }
+ return "";
+ }
+@@ -2711,10 +2787,10 @@ static char *ibpb_state(void)
+ {
+ if (boot_cpu_has(X86_FEATURE_IBPB)) {
+ if (static_key_enabled(&switch_mm_always_ibpb))
+- return ", IBPB: always-on";
++ return "; IBPB: always-on";
+ if (static_key_enabled(&switch_mm_cond_ibpb))
+- return ", IBPB: conditional";
+- return ", IBPB: disabled";
++ return "; IBPB: conditional";
++ return "; IBPB: disabled";
+ }
+ return "";
+ }
+@@ -2724,14 +2800,31 @@ static char *pbrsb_eibrs_state(void)
+ if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) {
+ if (boot_cpu_has(X86_FEATURE_RSB_VMEXIT_LITE) ||
+ boot_cpu_has(X86_FEATURE_RSB_VMEXIT))
+- return ", PBRSB-eIBRS: SW sequence";
++ return "; PBRSB-eIBRS: SW sequence";
+ else
+- return ", PBRSB-eIBRS: Vulnerable";
++ return "; PBRSB-eIBRS: Vulnerable";
+ } else {
+- return ", PBRSB-eIBRS: Not affected";
++ return "; PBRSB-eIBRS: Not affected";
+ }
+ }
+
++static const char * const spectre_bhi_state(void)
++{
++ if (!boot_cpu_has_bug(X86_BUG_BHI))
++ return "; BHI: Not affected";
++ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW))
++ return "; BHI: BHI_DIS_S";
++ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
++ return "; BHI: SW loop, KVM: SW loop";
++ else if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
++ !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA))
++ return "; BHI: Retpoline";
++ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
++ return "; BHI: Syscall hardening, KVM: SW loop";
++
++ return "; BHI: Vulnerable (Syscall hardening enabled)";
++}
++
+ static ssize_t spectre_v2_show_state(char *buf)
+ {
+ if (spectre_v2_enabled == SPECTRE_V2_LFENCE)
+@@ -2744,13 +2837,15 @@ static ssize_t spectre_v2_show_state(char *buf)
+ spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE)
+ return sysfs_emit(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n");
+
+- return sysfs_emit(buf, "%s%s%s%s%s%s%s\n",
++ return sysfs_emit(buf, "%s%s%s%s%s%s%s%s\n",
+ spectre_v2_strings[spectre_v2_enabled],
+ ibpb_state(),
+- boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
++ boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? "; IBRS_FW" : "",
+ stibp_state(),
+- boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
++ boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? "; RSB filling" : "",
+ pbrsb_eibrs_state(),
++ spectre_bhi_state(),
++ /* this should always be at the end */
+ spectre_v2_module_string());
+ }
+
+diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
+index 40d8c110bb32e..785fedddb5f09 100644
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -1163,6 +1163,7 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
+ #define NO_SPECTRE_V2 BIT(8)
+ #define NO_MMIO BIT(9)
+ #define NO_EIBRS_PBRSB BIT(10)
++#define NO_BHI BIT(11)
+
+ #define VULNWL(vendor, family, model, whitelist) \
+ X86_MATCH_VENDOR_FAM_MODEL(vendor, family, model, whitelist)
+@@ -1225,18 +1226,18 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
+ VULNWL_INTEL(ATOM_TREMONT_D, NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB),
+
+ /* AMD Family 0xf - 0x12 */
+- VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+- VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+- VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+- VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
++ VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI),
++ VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI),
++ VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI),
++ VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI),
+
+ /* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
+- VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB),
+- VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB),
++ VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB | NO_BHI),
++ VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB | NO_BHI),
+
+ /* Zhaoxin Family 7 */
+- VULNWL(CENTAUR, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO),
+- VULNWL(ZHAOXIN, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO),
++ VULNWL(CENTAUR, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO | NO_BHI),
++ VULNWL(ZHAOXIN, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO | NO_BHI),
+ {}
+ };
+
+@@ -1473,6 +1474,13 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ if (vulnerable_to_rfds(ia32_cap))
+ setup_force_cpu_bug(X86_BUG_RFDS);
+
++ /* When virtualized, eIBRS could be hidden, assume vulnerable */
++ if (!(ia32_cap & ARCH_CAP_BHI_NO) &&
++ !cpu_matches(cpu_vuln_whitelist, NO_BHI) &&
++ (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED) ||
++ boot_cpu_has(X86_FEATURE_HYPERVISOR)))
++ setup_force_cpu_bug(X86_BUG_BHI);
++
+ if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN))
+ return;
+
+diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
+index bc39252bc54f2..c17f9403cf6c0 100644
+--- a/arch/x86/kernel/cpu/mce/core.c
++++ b/arch/x86/kernel/cpu/mce/core.c
+@@ -2474,12 +2474,14 @@ static ssize_t set_bank(struct device *s, struct device_attribute *attr,
+ return -EINVAL;
+
+ b = &per_cpu(mce_banks_array, s->id)[bank];
+-
+ if (!b->init)
+ return -ENODEV;
+
+ b->ctl = new;
++
++ mutex_lock(&mce_sysfs_mutex);
+ mce_restart();
++ mutex_unlock(&mce_sysfs_mutex);
+
+ return size;
+ }
+diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
+index 0dad49a09b7a9..0ebca40dfd74b 100644
+--- a/arch/x86/kernel/cpu/scattered.c
++++ b/arch/x86/kernel/cpu/scattered.c
+@@ -28,6 +28,7 @@ static const struct cpuid_bit cpuid_bits[] = {
+ { X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 },
+ { X86_FEATURE_INTEL_PPIN, CPUID_EBX, 0, 0x00000007, 1 },
+ { X86_FEATURE_RRSBA_CTRL, CPUID_EDX, 2, 0x00000007, 2 },
++ { X86_FEATURE_BHI_CTRL, CPUID_EDX, 4, 0x00000007, 2 },
+ { X86_FEATURE_CQM_LLC, CPUID_EDX, 1, 0x0000000f, 0 },
+ { X86_FEATURE_CQM_OCCUP_LLC, CPUID_EDX, 0, 0x0000000f, 1 },
+ { X86_FEATURE_CQM_MBM_TOTAL, CPUID_EDX, 1, 0x0000000f, 1 },
+diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
+index 15c700d358700..b223922248e9f 100644
+--- a/arch/x86/kernel/mpparse.c
++++ b/arch/x86/kernel/mpparse.c
+@@ -196,12 +196,12 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
+ if (!smp_check_mpc(mpc, oem, str))
+ return 0;
+
+- if (early) {
+- /* Initialize the lapic mapping */
+- if (!acpi_lapic)
+- register_lapic_address(mpc->lapic);
++ /* Initialize the lapic mapping */
++ if (!acpi_lapic)
++ register_lapic_address(mpc->lapic);
++
++ if (early)
+ return 1;
+- }
+
+ /* Now process the configuration blocks. */
+ while (count < mpc->length) {
+diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
+index 97dd702857413..3998109195dab 100644
+--- a/arch/x86/kernel/setup.c
++++ b/arch/x86/kernel/setup.c
+@@ -35,6 +35,7 @@
+ #include <asm/bios_ebda.h>
+ #include <asm/bugs.h>
+ #include <asm/cacheinfo.h>
++#include <asm/coco.h>
+ #include <asm/cpu.h>
+ #include <asm/efi.h>
+ #include <asm/gart.h>
+@@ -993,6 +994,7 @@ void __init setup_arch(char **cmdline_p)
+ * memory size.
+ */
+ mem_encrypt_setup_arch();
++ cc_random_init();
+
+ efi_fake_memmap();
+ efi_find_mirror();
+diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c
+index 0b04e3bfd72ae..be2fa2fc02f36 100644
+--- a/arch/x86/kernel/sev-shared.c
++++ b/arch/x86/kernel/sev-shared.c
+@@ -89,7 +89,8 @@ static bool __init sev_es_check_cpu_features(void)
+ return true;
+ }
+
+-static void __noreturn sev_es_terminate(unsigned int set, unsigned int reason)
++static void __head __noreturn
++sev_es_terminate(unsigned int set, unsigned int reason)
+ {
+ u64 val = GHCB_MSR_TERM_REQ;
+
+@@ -326,13 +327,7 @@ static int sev_cpuid_hv(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid
+ */
+ static const struct snp_cpuid_table *snp_cpuid_get_table(void)
+ {
+- void *ptr;
+-
+- asm ("lea cpuid_table_copy(%%rip), %0"
+- : "=r" (ptr)
+- : "p" (&cpuid_table_copy));
+-
+- return ptr;
++ return &RIP_REL_REF(cpuid_table_copy);
+ }
+
+ /*
+@@ -391,7 +386,7 @@ static u32 snp_cpuid_calc_xsave_size(u64 xfeatures_en, bool compacted)
+ return xsave_size;
+ }
+
+-static bool
++static bool __head
+ snp_cpuid_get_validated_func(struct cpuid_leaf *leaf)
+ {
+ const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
+@@ -528,7 +523,8 @@ static int snp_cpuid_postprocess(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
+ * Returns -EOPNOTSUPP if feature not enabled. Any other non-zero return value
+ * should be treated as fatal by caller.
+ */
+-static int snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
++static int __head
++snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_leaf *leaf)
+ {
+ const struct snp_cpuid_table *cpuid_table = snp_cpuid_get_table();
+
+@@ -570,7 +566,7 @@ static int snp_cpuid(struct ghcb *ghcb, struct es_em_ctxt *ctxt, struct cpuid_le
+ * page yet, so it only supports the MSR based communication with the
+ * hypervisor and only the CPUID exit-code.
+ */
+-void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)
++void __head do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)
+ {
+ unsigned int subfn = lower_bits(regs->cx, 32);
+ unsigned int fn = lower_bits(regs->ax, 32);
+@@ -1016,7 +1012,8 @@ struct cc_setup_data {
+ * Search for a Confidential Computing blob passed in as a setup_data entry
+ * via the Linux Boot Protocol.
+ */
+-static struct cc_blob_sev_info *find_cc_blob_setup_data(struct boot_params *bp)
++static __head
++struct cc_blob_sev_info *find_cc_blob_setup_data(struct boot_params *bp)
+ {
+ struct cc_setup_data *sd = NULL;
+ struct setup_data *hdr;
+@@ -1043,7 +1040,7 @@ static struct cc_blob_sev_info *find_cc_blob_setup_data(struct boot_params *bp)
+ * mapping needs to be updated in sync with all the changes to virtual memory
+ * layout and related mapping facilities throughout the boot process.
+ */
+-static void __init setup_cpuid_table(const struct cc_blob_sev_info *cc_info)
++static void __head setup_cpuid_table(const struct cc_blob_sev_info *cc_info)
+ {
+ const struct snp_cpuid_table *cpuid_table_fw, *cpuid_table;
+ int i;
+diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
+index 0f58242b54b86..eb2873b5eb1bb 100644
+--- a/arch/x86/kernel/sev.c
++++ b/arch/x86/kernel/sev.c
+@@ -26,6 +26,7 @@
+ #include <linux/dmi.h>
+ #include <uapi/linux/sev-guest.h>
+
++#include <asm/init.h>
+ #include <asm/cpu_entry_area.h>
+ #include <asm/stacktrace.h>
+ #include <asm/sev.h>
+@@ -683,8 +684,9 @@ static u64 __init get_jump_table_addr(void)
+ return ret;
+ }
+
+-static void early_set_pages_state(unsigned long vaddr, unsigned long paddr,
+- unsigned long npages, enum psc_op op)
++static void __head
++early_set_pages_state(unsigned long vaddr, unsigned long paddr,
++ unsigned long npages, enum psc_op op)
+ {
+ unsigned long paddr_end;
+ u64 val;
+@@ -740,7 +742,7 @@ static void early_set_pages_state(unsigned long vaddr, unsigned long paddr,
+ sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_PSC);
+ }
+
+-void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
++void __head early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
+ unsigned long npages)
+ {
+ /*
+@@ -2045,7 +2047,7 @@ bool __init handle_vc_boot_ghcb(struct pt_regs *regs)
+ *
+ * Scan for the blob in that order.
+ */
+-static __init struct cc_blob_sev_info *find_cc_blob(struct boot_params *bp)
++static __head struct cc_blob_sev_info *find_cc_blob(struct boot_params *bp)
+ {
+ struct cc_blob_sev_info *cc_info;
+
+@@ -2071,7 +2073,7 @@ static __init struct cc_blob_sev_info *find_cc_blob(struct boot_params *bp)
+ return cc_info;
+ }
+
+-bool __init snp_init(struct boot_params *bp)
++bool __head snp_init(struct boot_params *bp)
+ {
+ struct cc_blob_sev_info *cc_info;
+
+@@ -2093,7 +2095,7 @@ bool __init snp_init(struct boot_params *bp)
+ return true;
+ }
+
+-void __init __noreturn snp_abort(void)
++void __head __noreturn snp_abort(void)
+ {
+ sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
+ }
+diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
+index 0544700ca50b8..e2c3573f53e43 100644
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -3126,7 +3126,7 @@ static int host_pfn_mapping_level(struct kvm *kvm, gfn_t gfn,
+ if (pud_none(pud) || !pud_present(pud))
+ goto out;
+
+- if (pud_large(pud)) {
++ if (pud_leaf(pud)) {
+ level = PG_LEVEL_1G;
+ goto out;
+ }
+diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h
+index aadefcaa9561d..2f4e155080bad 100644
+--- a/arch/x86/kvm/reverse_cpuid.h
++++ b/arch/x86/kvm/reverse_cpuid.h
+@@ -52,7 +52,7 @@ enum kvm_only_cpuid_leafs {
+ #define X86_FEATURE_IPRED_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 1)
+ #define KVM_X86_FEATURE_RRSBA_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 2)
+ #define X86_FEATURE_DDPD_U KVM_X86_FEATURE(CPUID_7_2_EDX, 3)
+-#define X86_FEATURE_BHI_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 4)
++#define KVM_X86_FEATURE_BHI_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 4)
+ #define X86_FEATURE_MCDT_NO KVM_X86_FEATURE(CPUID_7_2_EDX, 5)
+
+ /* CPUID level 0x80000007 (EDX). */
+@@ -102,10 +102,12 @@ static const struct cpuid_reg reverse_cpuid[] = {
+ */
+ static __always_inline void reverse_cpuid_check(unsigned int x86_leaf)
+ {
++ BUILD_BUG_ON(NR_CPUID_WORDS != NCAPINTS);
+ BUILD_BUG_ON(x86_leaf == CPUID_LNX_1);
+ BUILD_BUG_ON(x86_leaf == CPUID_LNX_2);
+ BUILD_BUG_ON(x86_leaf == CPUID_LNX_3);
+ BUILD_BUG_ON(x86_leaf == CPUID_LNX_4);
++ BUILD_BUG_ON(x86_leaf == CPUID_LNX_5);
+ BUILD_BUG_ON(x86_leaf >= ARRAY_SIZE(reverse_cpuid));
+ BUILD_BUG_ON(reverse_cpuid[x86_leaf].function == 0);
+ }
+@@ -126,6 +128,7 @@ static __always_inline u32 __feature_translate(int x86_feature)
+ KVM_X86_TRANSLATE_FEATURE(CONSTANT_TSC);
+ KVM_X86_TRANSLATE_FEATURE(PERFMON_V2);
+ KVM_X86_TRANSLATE_FEATURE(RRSBA_CTRL);
++ KVM_X86_TRANSLATE_FEATURE(BHI_CTRL);
+ default:
+ return x86_feature;
+ }
+diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
+index a8ce5226b3b57..86088d1250b3d 100644
+--- a/arch/x86/kvm/svm/sev.c
++++ b/arch/x86/kvm/svm/sev.c
+@@ -84,9 +84,10 @@ struct enc_region {
+ };
+
+ /* Called with the sev_bitmap_lock held, or on shutdown */
+-static int sev_flush_asids(int min_asid, int max_asid)
++static int sev_flush_asids(unsigned int min_asid, unsigned int max_asid)
+ {
+- int ret, asid, error = 0;
++ int ret, error = 0;
++ unsigned int asid;
+
+ /* Check if there are any ASIDs to reclaim before performing a flush */
+ asid = find_next_bit(sev_reclaim_asid_bitmap, nr_asids, min_asid);
+@@ -116,7 +117,7 @@ static inline bool is_mirroring_enc_context(struct kvm *kvm)
+ }
+
+ /* Must be called with the sev_bitmap_lock held */
+-static bool __sev_recycle_asids(int min_asid, int max_asid)
++static bool __sev_recycle_asids(unsigned int min_asid, unsigned int max_asid)
+ {
+ if (sev_flush_asids(min_asid, max_asid))
+ return false;
+@@ -143,8 +144,20 @@ static void sev_misc_cg_uncharge(struct kvm_sev_info *sev)
+
+ static int sev_asid_new(struct kvm_sev_info *sev)
+ {
+- int asid, min_asid, max_asid, ret;
++ /*
++ * SEV-enabled guests must use asid from min_sev_asid to max_sev_asid.
++ * SEV-ES-enabled guest can use from 1 to min_sev_asid - 1.
++ * Note: min ASID can end up larger than the max if basic SEV support is
++ * effectively disabled by disallowing use of ASIDs for SEV guests.
++ */
++ unsigned int min_asid = sev->es_active ? 1 : min_sev_asid;
++ unsigned int max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid;
++ unsigned int asid;
+ bool retry = true;
++ int ret;
++
++ if (min_asid > max_asid)
++ return -ENOTTY;
+
+ WARN_ON(sev->misc_cg);
+ sev->misc_cg = get_current_misc_cg();
+@@ -157,12 +170,6 @@ static int sev_asid_new(struct kvm_sev_info *sev)
+
+ mutex_lock(&sev_bitmap_lock);
+
+- /*
+- * SEV-enabled guests must use asid from min_sev_asid to max_sev_asid.
+- * SEV-ES-enabled guest can use from 1 to min_sev_asid - 1.
+- */
+- min_asid = sev->es_active ? 1 : min_sev_asid;
+- max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid;
+ again:
+ asid = find_next_zero_bit(sev_asid_bitmap, max_asid + 1, min_asid);
+ if (asid > max_asid) {
+@@ -187,7 +194,7 @@ static int sev_asid_new(struct kvm_sev_info *sev)
+ return ret;
+ }
+
+-static int sev_get_asid(struct kvm *kvm)
++static unsigned int sev_get_asid(struct kvm *kvm)
+ {
+ struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
+
+@@ -284,8 +291,8 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
+
+ static int sev_bind_asid(struct kvm *kvm, unsigned int handle, int *error)
+ {
++ unsigned int asid = sev_get_asid(kvm);
+ struct sev_data_activate activate;
+- int asid = sev_get_asid(kvm);
+ int ret;
+
+ /* activate ASID on the given handle */
+@@ -2237,8 +2244,10 @@ void __init sev_hardware_setup(void)
+ goto out;
+ }
+
+- sev_asid_count = max_sev_asid - min_sev_asid + 1;
+- WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count));
++ if (min_sev_asid <= max_sev_asid) {
++ sev_asid_count = max_sev_asid - min_sev_asid + 1;
++ WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count));
++ }
+ sev_supported = true;
+
+ /* SEV-ES support requested? */
+@@ -2269,7 +2278,9 @@ void __init sev_hardware_setup(void)
+ out:
+ if (boot_cpu_has(X86_FEATURE_SEV))
+ pr_info("SEV %s (ASIDs %u - %u)\n",
+- sev_supported ? "enabled" : "disabled",
++ sev_supported ? min_sev_asid <= max_sev_asid ? "enabled" :
++ "unusable" :
++ "disabled",
+ min_sev_asid, max_sev_asid);
+ if (boot_cpu_has(X86_FEATURE_SEV_ES))
+ pr_info("SEV-ES %s (ASIDs %u - %u)\n",
+@@ -2317,7 +2328,7 @@ int sev_cpu_init(struct svm_cpu_data *sd)
+ */
+ static void sev_flush_encrypted_page(struct kvm_vcpu *vcpu, void *va)
+ {
+- int asid = to_kvm_svm(vcpu->kvm)->sev_info.asid;
++ unsigned int asid = sev_get_asid(vcpu->kvm);
+
+ /*
+ * Note! The address must be a kernel address, as regular page walk
+@@ -2635,7 +2646,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm)
+ void pre_sev_run(struct vcpu_svm *svm, int cpu)
+ {
+ struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
+- int asid = sev_get_asid(svm->vcpu.kvm);
++ unsigned int asid = sev_get_asid(svm->vcpu.kvm);
+
+ /* Assign the asid allocated with this SEV guest */
+ svm->asid = asid;
+diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
+index 83843379813ee..b82e6ed4f0241 100644
+--- a/arch/x86/kvm/trace.h
++++ b/arch/x86/kvm/trace.h
+@@ -732,13 +732,13 @@ TRACE_EVENT(kvm_nested_intr_vmexit,
+ * Tracepoint for nested #vmexit because of interrupt pending
+ */
+ TRACE_EVENT(kvm_invlpga,
+- TP_PROTO(__u64 rip, int asid, u64 address),
++ TP_PROTO(__u64 rip, unsigned int asid, u64 address),
+ TP_ARGS(rip, asid, address),
+
+ TP_STRUCT__entry(
+- __field( __u64, rip )
+- __field( int, asid )
+- __field( __u64, address )
++ __field( __u64, rip )
++ __field( unsigned int, asid )
++ __field( __u64, address )
+ ),
+
+ TP_fast_assign(
+@@ -747,7 +747,7 @@ TRACE_EVENT(kvm_invlpga,
+ __entry->address = address;
+ ),
+
+- TP_printk("rip: 0x%016llx asid: %d address: 0x%016llx",
++ TP_printk("rip: 0x%016llx asid: %u address: 0x%016llx",
+ __entry->rip, __entry->asid, __entry->address)
+ );
+
+diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S
+index 2bfbf758d0611..f6986dee6f8c7 100644
+--- a/arch/x86/kvm/vmx/vmenter.S
++++ b/arch/x86/kvm/vmx/vmenter.S
+@@ -275,6 +275,8 @@ SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL)
+
+ call vmx_spec_ctrl_restore_host
+
++ CLEAR_BRANCH_HISTORY_VMEXIT
++
+ /* Put return value in AX */
+ mov %_ASM_BX, %_ASM_AX
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index ffe580169c93f..8e4e48840290e 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -1624,7 +1624,7 @@ static bool kvm_is_immutable_feature_msr(u32 msr)
+ ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \
+ ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \
+ ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO | ARCH_CAP_GDS_NO | \
+- ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR)
++ ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR | ARCH_CAP_BHI_NO)
+
+ static u64 kvm_get_arch_capabilities(void)
+ {
+diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
+index ea3a28e7b613c..f0dae4fb6d071 100644
+--- a/arch/x86/lib/Makefile
++++ b/arch/x86/lib/Makefile
+@@ -14,19 +14,6 @@ ifdef CONFIG_KCSAN
+ CFLAGS_REMOVE_delay.o = $(CC_FLAGS_FTRACE)
+ endif
+
+-# Early boot use of cmdline; don't instrument it
+-ifdef CONFIG_AMD_MEM_ENCRYPT
+-KCOV_INSTRUMENT_cmdline.o := n
+-KASAN_SANITIZE_cmdline.o := n
+-KCSAN_SANITIZE_cmdline.o := n
+-
+-ifdef CONFIG_FUNCTION_TRACER
+-CFLAGS_REMOVE_cmdline.o = -pg
+-endif
+-
+-CFLAGS_cmdline.o := -fno-stack-protector -fno-jump-tables
+-endif
+-
+ inat_tables_script = $(srctree)/arch/x86/tools/gen-insn-attr-x86.awk
+ inat_tables_maps = $(srctree)/arch/x86/lib/x86-opcode-map.txt
+ quiet_cmd_inat_tables = GEN $@
+diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S
+index 1e59367b46813..5b26a952e2fa6 100644
+--- a/arch/x86/lib/retpoline.S
++++ b/arch/x86/lib/retpoline.S
+@@ -229,8 +229,12 @@ SYM_CODE_END(srso_return_thunk)
+ #define JMP_SRSO_UNTRAIN_RET "ud2"
+ /* Dummy for the alternative in CALL_UNTRAIN_RET. */
+ SYM_CODE_START(srso_alias_untrain_ret)
+- RET
++ ANNOTATE_UNRET_SAFE
++ ANNOTATE_NOENDBR
++ ret
++ int3
+ SYM_FUNC_END(srso_alias_untrain_ret)
++__EXPORT_THUNK(srso_alias_untrain_ret)
+ #endif /* CONFIG_CPU_SRSO */
+
+ #ifdef CONFIG_CPU_UNRET_ENTRY
+diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
+index d6375b3c633bc..b01df023de04c 100644
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -376,7 +376,7 @@ static void dump_pagetable(unsigned long address)
+ goto bad;
+
+ pr_cont("PUD %lx ", pud_val(*pud));
+- if (!pud_present(*pud) || pud_large(*pud))
++ if (!pud_present(*pud) || pud_leaf(*pud))
+ goto out;
+
+ pmd = pmd_offset(pud, address);
+@@ -1037,7 +1037,7 @@ spurious_kernel_fault(unsigned long error_code, unsigned long address)
+ if (!pud_present(*pud))
+ return 0;
+
+- if (pud_large(*pud))
++ if (pud_leaf(*pud))
+ return spurious_kernel_fault_check(error_code, (pte_t *) pud);
+
+ pmd = pmd_offset(pud, address);
+diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c
+index f50cc210a9818..968d7005f4a72 100644
+--- a/arch/x86/mm/ident_map.c
++++ b/arch/x86/mm/ident_map.c
+@@ -26,31 +26,18 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
+ for (; addr < end; addr = next) {
+ pud_t *pud = pud_page + pud_index(addr);
+ pmd_t *pmd;
+- bool use_gbpage;
+
+ next = (addr & PUD_MASK) + PUD_SIZE;
+ if (next > end)
+ next = end;
+
+- /* if this is already a gbpage, this portion is already mapped */
+- if (pud_large(*pud))
+- continue;
+-
+- /* Is using a gbpage allowed? */
+- use_gbpage = info->direct_gbpages;
+-
+- /* Don't use gbpage if it maps more than the requested region. */
+- /* at the begining: */
+- use_gbpage &= ((addr & ~PUD_MASK) == 0);
+- /* ... or at the end: */
+- use_gbpage &= ((next & ~PUD_MASK) == 0);
+-
+- /* Never overwrite existing mappings */
+- use_gbpage &= !pud_present(*pud);
+-
+- if (use_gbpage) {
++ if (info->direct_gbpages) {
+ pud_t pudval;
+
++ if (pud_present(*pud))
++ continue;
++
++ addr &= PUD_MASK;
+ pudval = __pud((addr - info->offset) | info->page_flag);
+ set_pud(pud, pudval);
+ continue;
+diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
+index a0dffaca6d2bf..534436c9d3997 100644
+--- a/arch/x86/mm/init_64.c
++++ b/arch/x86/mm/init_64.c
+@@ -617,7 +617,7 @@ phys_pud_init(pud_t *pud_page, unsigned long paddr, unsigned long paddr_end,
+ }
+
+ if (!pud_none(*pud)) {
+- if (!pud_large(*pud)) {
++ if (!pud_leaf(*pud)) {
+ pmd = pmd_offset(pud, 0);
+ paddr_last = phys_pmd_init(pmd, paddr,
+ paddr_end,
+@@ -1163,7 +1163,7 @@ remove_pud_table(pud_t *pud_start, unsigned long addr, unsigned long end,
+ if (!pud_present(*pud))
+ continue;
+
+- if (pud_large(*pud) &&
++ if (pud_leaf(*pud) &&
+ IS_ALIGNED(addr, PUD_SIZE) &&
+ IS_ALIGNED(next, PUD_SIZE)) {
+ spin_lock(&init_mm.page_table_lock);
+diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
+index 0302491d799d1..fcf508c52bdc5 100644
+--- a/arch/x86/mm/kasan_init_64.c
++++ b/arch/x86/mm/kasan_init_64.c
+@@ -115,7 +115,7 @@ static void __init kasan_populate_p4d(p4d_t *p4d, unsigned long addr,
+ pud = pud_offset(p4d, addr);
+ do {
+ next = pud_addr_end(addr, end);
+- if (!pud_large(*pud))
++ if (!pud_leaf(*pud))
+ kasan_populate_pud(pud, addr, next, nid);
+ } while (pud++, addr = next, addr != end);
+ }
+diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c
+index 0166ab1780ccb..cc47a818a640a 100644
+--- a/arch/x86/mm/mem_encrypt_identity.c
++++ b/arch/x86/mm/mem_encrypt_identity.c
+@@ -41,9 +41,9 @@
+ #include <linux/mem_encrypt.h>
+ #include <linux/cc_platform.h>
+
++#include <asm/init.h>
+ #include <asm/setup.h>
+ #include <asm/sections.h>
+-#include <asm/cmdline.h>
+ #include <asm/coco.h>
+ #include <asm/sev.h>
+
+@@ -95,10 +95,7 @@ struct sme_populate_pgd_data {
+ */
+ static char sme_workarea[2 * PMD_SIZE] __section(".init.scratch");
+
+-static char sme_cmdline_arg[] __initdata = "mem_encrypt";
+-static char sme_cmdline_on[] __initdata = "on";
+-
+-static void __init sme_clear_pgd(struct sme_populate_pgd_data *ppd)
++static void __head sme_clear_pgd(struct sme_populate_pgd_data *ppd)
+ {
+ unsigned long pgd_start, pgd_end, pgd_size;
+ pgd_t *pgd_p;
+@@ -113,7 +110,7 @@ static void __init sme_clear_pgd(struct sme_populate_pgd_data *ppd)
+ memset(pgd_p, 0, pgd_size);
+ }
+
+-static pud_t __init *sme_prepare_pgd(struct sme_populate_pgd_data *ppd)
++static pud_t __head *sme_prepare_pgd(struct sme_populate_pgd_data *ppd)
+ {
+ pgd_t *pgd;
+ p4d_t *p4d;
+@@ -144,13 +141,13 @@ static pud_t __init *sme_prepare_pgd(struct sme_populate_pgd_data *ppd)
+ set_pud(pud, __pud(PUD_FLAGS | __pa(pmd)));
+ }
+
+- if (pud_large(*pud))
++ if (pud_leaf(*pud))
+ return NULL;
+
+ return pud;
+ }
+
+-static void __init sme_populate_pgd_large(struct sme_populate_pgd_data *ppd)
++static void __head sme_populate_pgd_large(struct sme_populate_pgd_data *ppd)
+ {
+ pud_t *pud;
+ pmd_t *pmd;
+@@ -166,7 +163,7 @@ static void __init sme_populate_pgd_large(struct sme_populate_pgd_data *ppd)
+ set_pmd(pmd, __pmd(ppd->paddr | ppd->pmd_flags));
+ }
+
+-static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd)
++static void __head sme_populate_pgd(struct sme_populate_pgd_data *ppd)
+ {
+ pud_t *pud;
+ pmd_t *pmd;
+@@ -192,7 +189,7 @@ static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd)
+ set_pte(pte, __pte(ppd->paddr | ppd->pte_flags));
+ }
+
+-static void __init __sme_map_range_pmd(struct sme_populate_pgd_data *ppd)
++static void __head __sme_map_range_pmd(struct sme_populate_pgd_data *ppd)
+ {
+ while (ppd->vaddr < ppd->vaddr_end) {
+ sme_populate_pgd_large(ppd);
+@@ -202,7 +199,7 @@ static void __init __sme_map_range_pmd(struct sme_populate_pgd_data *ppd)
+ }
+ }
+
+-static void __init __sme_map_range_pte(struct sme_populate_pgd_data *ppd)
++static void __head __sme_map_range_pte(struct sme_populate_pgd_data *ppd)
+ {
+ while (ppd->vaddr < ppd->vaddr_end) {
+ sme_populate_pgd(ppd);
+@@ -212,7 +209,7 @@ static void __init __sme_map_range_pte(struct sme_populate_pgd_data *ppd)
+ }
+ }
+
+-static void __init __sme_map_range(struct sme_populate_pgd_data *ppd,
++static void __head __sme_map_range(struct sme_populate_pgd_data *ppd,
+ pmdval_t pmd_flags, pteval_t pte_flags)
+ {
+ unsigned long vaddr_end;
+@@ -236,22 +233,22 @@ static void __init __sme_map_range(struct sme_populate_pgd_data *ppd,
+ __sme_map_range_pte(ppd);
+ }
+
+-static void __init sme_map_range_encrypted(struct sme_populate_pgd_data *ppd)
++static void __head sme_map_range_encrypted(struct sme_populate_pgd_data *ppd)
+ {
+ __sme_map_range(ppd, PMD_FLAGS_ENC, PTE_FLAGS_ENC);
+ }
+
+-static void __init sme_map_range_decrypted(struct sme_populate_pgd_data *ppd)
++static void __head sme_map_range_decrypted(struct sme_populate_pgd_data *ppd)
+ {
+ __sme_map_range(ppd, PMD_FLAGS_DEC, PTE_FLAGS_DEC);
+ }
+
+-static void __init sme_map_range_decrypted_wp(struct sme_populate_pgd_data *ppd)
++static void __head sme_map_range_decrypted_wp(struct sme_populate_pgd_data *ppd)
+ {
+ __sme_map_range(ppd, PMD_FLAGS_DEC_WP, PTE_FLAGS_DEC_WP);
+ }
+
+-static unsigned long __init sme_pgtable_calc(unsigned long len)
++static unsigned long __head sme_pgtable_calc(unsigned long len)
+ {
+ unsigned long entries = 0, tables = 0;
+
+@@ -288,7 +285,7 @@ static unsigned long __init sme_pgtable_calc(unsigned long len)
+ return entries + tables;
+ }
+
+-void __init sme_encrypt_kernel(struct boot_params *bp)
++void __head sme_encrypt_kernel(struct boot_params *bp)
+ {
+ unsigned long workarea_start, workarea_end, workarea_len;
+ unsigned long execute_start, execute_end, execute_len;
+@@ -323,9 +320,8 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
+ * memory from being cached.
+ */
+
+- /* Physical addresses gives us the identity mapped virtual addresses */
+- kernel_start = __pa_symbol(_text);
+- kernel_end = ALIGN(__pa_symbol(_end), PMD_SIZE);
++ kernel_start = (unsigned long)RIP_REL_REF(_text);
++ kernel_end = ALIGN((unsigned long)RIP_REL_REF(_end), PMD_SIZE);
+ kernel_len = kernel_end - kernel_start;
+
+ initrd_start = 0;
+@@ -342,14 +338,6 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
+ }
+ #endif
+
+- /*
+- * We're running identity mapped, so we must obtain the address to the
+- * SME encryption workarea using rip-relative addressing.
+- */
+- asm ("lea sme_workarea(%%rip), %0"
+- : "=r" (workarea_start)
+- : "p" (sme_workarea));
+-
+ /*
+ * Calculate required number of workarea bytes needed:
+ * executable encryption area size:
+@@ -359,7 +347,7 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
+ * pagetable structures for the encryption of the kernel
+ * pagetable structures for workarea (in case not currently mapped)
+ */
+- execute_start = workarea_start;
++ execute_start = workarea_start = (unsigned long)RIP_REL_REF(sme_workarea);
+ execute_end = execute_start + (PAGE_SIZE * 2) + PMD_SIZE;
+ execute_len = execute_end - execute_start;
+
+@@ -502,13 +490,11 @@ void __init sme_encrypt_kernel(struct boot_params *bp)
+ native_write_cr3(__native_read_cr3());
+ }
+
+-void __init sme_enable(struct boot_params *bp)
++void __head sme_enable(struct boot_params *bp)
+ {
+- const char *cmdline_ptr, *cmdline_arg, *cmdline_on;
+ unsigned int eax, ebx, ecx, edx;
+ unsigned long feature_mask;
+ unsigned long me_mask;
+- char buffer[16];
+ bool snp;
+ u64 msr;
+
+@@ -551,6 +537,9 @@ void __init sme_enable(struct boot_params *bp)
+
+ /* Check if memory encryption is enabled */
+ if (feature_mask == AMD_SME_BIT) {
++ if (!(bp->hdr.xloadflags & XLF_MEM_ENCRYPTION))
++ return;
++
+ /*
+ * No SME if Hypervisor bit is set. This check is here to
+ * prevent a guest from trying to enable SME. For running as a
+@@ -570,31 +559,8 @@ void __init sme_enable(struct boot_params *bp)
+ msr = __rdmsr(MSR_AMD64_SYSCFG);
+ if (!(msr & MSR_AMD64_SYSCFG_MEM_ENCRYPT))
+ return;
+- } else {
+- /* SEV state cannot be controlled by a command line option */
+- goto out;
+ }
+
+- /*
+- * Fixups have not been applied to phys_base yet and we're running
+- * identity mapped, so we must obtain the address to the SME command
+- * line argument data using rip-relative addressing.
+- */
+- asm ("lea sme_cmdline_arg(%%rip), %0"
+- : "=r" (cmdline_arg)
+- : "p" (sme_cmdline_arg));
+- asm ("lea sme_cmdline_on(%%rip), %0"
+- : "=r" (cmdline_on)
+- : "p" (sme_cmdline_on));
+-
+- cmdline_ptr = (const char *)((u64)bp->hdr.cmd_line_ptr |
+- ((u64)bp->ext_cmd_line_ptr << 32));
+-
+- if (cmdline_find_option(cmdline_ptr, cmdline_arg, buffer, sizeof(buffer)) < 0 ||
+- strncmp(buffer, cmdline_on, sizeof(buffer)))
+- return;
+-
+-out:
+ RIP_REL_REF(sme_me_mask) = me_mask;
+ physical_mask &= ~me_mask;
+ cc_vendor = CC_VENDOR_AMD;
+diff --git a/arch/x86/mm/pat/memtype.c b/arch/x86/mm/pat/memtype.c
+index 0904d7e8e1260..37d51cfd77cb5 100644
+--- a/arch/x86/mm/pat/memtype.c
++++ b/arch/x86/mm/pat/memtype.c
+@@ -950,6 +950,38 @@ static void free_pfn_range(u64 paddr, unsigned long size)
+ memtype_free(paddr, paddr + size);
+ }
+
++static int get_pat_info(struct vm_area_struct *vma, resource_size_t *paddr,
++ pgprot_t *pgprot)
++{
++ unsigned long prot;
++
++ VM_WARN_ON_ONCE(!(vma->vm_flags & VM_PAT));
++
++ /*
++ * We need the starting PFN and cachemode used for track_pfn_remap()
++ * that covered the whole VMA. For most mappings, we can obtain that
++ * information from the page tables. For COW mappings, we might now
++ * suddenly have anon folios mapped and follow_phys() will fail.
++ *
++ * Fallback to using vma->vm_pgoff, see remap_pfn_range_notrack(), to
++ * detect the PFN. If we need the cachemode as well, we're out of luck
++ * for now and have to fail fork().
++ */
++ if (!follow_phys(vma, vma->vm_start, 0, &prot, paddr)) {
++ if (pgprot)
++ *pgprot = __pgprot(prot);
++ return 0;
++ }
++ if (is_cow_mapping(vma->vm_flags)) {
++ if (pgprot)
++ return -EINVAL;
++ *paddr = (resource_size_t)vma->vm_pgoff << PAGE_SHIFT;
++ return 0;
++ }
++ WARN_ON_ONCE(1);
++ return -EINVAL;
++}
++
+ /*
+ * track_pfn_copy is called when vma that is covering the pfnmap gets
+ * copied through copy_page_range().
+@@ -960,20 +992,13 @@ static void free_pfn_range(u64 paddr, unsigned long size)
+ int track_pfn_copy(struct vm_area_struct *vma)
+ {
+ resource_size_t paddr;
+- unsigned long prot;
+ unsigned long vma_size = vma->vm_end - vma->vm_start;
+ pgprot_t pgprot;
+
+ if (vma->vm_flags & VM_PAT) {
+- /*
+- * reserve the whole chunk covered by vma. We need the
+- * starting address and protection from pte.
+- */
+- if (follow_phys(vma, vma->vm_start, 0, &prot, &paddr)) {
+- WARN_ON_ONCE(1);
++ if (get_pat_info(vma, &paddr, &pgprot))
+ return -EINVAL;
+- }
+- pgprot = __pgprot(prot);
++ /* reserve the whole chunk covered by vma. */
+ return reserve_pfn_range(paddr, vma_size, &pgprot, 1);
+ }
+
+@@ -1048,7 +1073,6 @@ void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn,
+ unsigned long size, bool mm_wr_locked)
+ {
+ resource_size_t paddr;
+- unsigned long prot;
+
+ if (vma && !(vma->vm_flags & VM_PAT))
+ return;
+@@ -1056,11 +1080,8 @@ void untrack_pfn(struct vm_area_struct *vma, unsigned long pfn,
+ /* free the chunk starting from pfn or the whole chunk */
+ paddr = (resource_size_t)pfn << PAGE_SHIFT;
+ if (!paddr && !size) {
+- if (follow_phys(vma, vma->vm_start, 0, &prot, &paddr)) {
+- WARN_ON_ONCE(1);
++ if (get_pat_info(vma, &paddr, NULL))
+ return;
+- }
+-
+ size = vma->vm_end - vma->vm_start;
+ }
+ free_pfn_range(paddr, size);
+diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
+index 1028804040463..135bb594df8b7 100644
+--- a/arch/x86/mm/pat/set_memory.c
++++ b/arch/x86/mm/pat/set_memory.c
+@@ -684,7 +684,7 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
+ return NULL;
+
+ *level = PG_LEVEL_1G;
+- if (pud_large(*pud) || !pud_present(*pud))
++ if (pud_leaf(*pud) || !pud_present(*pud))
+ return (pte_t *)pud;
+
+ pmd = pmd_offset(pud, address);
+@@ -743,7 +743,7 @@ pmd_t *lookup_pmd_address(unsigned long address)
+ return NULL;
+
+ pud = pud_offset(p4d, address);
+- if (pud_none(*pud) || pud_large(*pud) || !pud_present(*pud))
++ if (pud_none(*pud) || pud_leaf(*pud) || !pud_present(*pud))
+ return NULL;
+
+ return pmd_offset(pud, address);
+@@ -1278,7 +1278,7 @@ static void unmap_pud_range(p4d_t *p4d, unsigned long start, unsigned long end)
+ */
+ while (end - start >= PUD_SIZE) {
+
+- if (pud_large(*pud))
++ if (pud_leaf(*pud))
+ pud_clear(pud);
+ else
+ unmap_pmd_range(pud, start, start + PUD_SIZE);
+diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
+index 0cbc1b8e8e3d1..a67bb8f982bd5 100644
+--- a/arch/x86/mm/pgtable.c
++++ b/arch/x86/mm/pgtable.c
+@@ -777,7 +777,7 @@ int pmd_set_huge(pmd_t *pmd, phys_addr_t addr, pgprot_t prot)
+ */
+ int pud_clear_huge(pud_t *pud)
+ {
+- if (pud_large(*pud)) {
++ if (pud_leaf(*pud)) {
+ pud_clear(pud);
+ return 1;
+ }
+diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
+index 669ba1c345b38..912b1da7ed80c 100644
+--- a/arch/x86/mm/pti.c
++++ b/arch/x86/mm/pti.c
+@@ -217,7 +217,7 @@ static pmd_t *pti_user_pagetable_walk_pmd(unsigned long address)
+
+ pud = pud_offset(p4d, address);
+ /* The user page tables do not use large mappings: */
+- if (pud_large(*pud)) {
++ if (pud_leaf(*pud)) {
+ WARN_ON(1);
+ return NULL;
+ }
+diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
+index 919f647c740fb..df484885ccd4a 100644
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -466,7 +466,7 @@ static int emit_call(u8 **pprog, void *func, void *ip)
+ static int emit_rsb_call(u8 **pprog, void *func, void *ip)
+ {
+ OPTIMIZER_HIDE_VAR(func);
+- x86_call_depth_emit_accounting(pprog, func);
++ ip += x86_call_depth_emit_accounting(pprog, func);
+ return emit_patch(pprog, func, ip, 0xE8);
+ }
+
+diff --git a/arch/x86/power/hibernate.c b/arch/x86/power/hibernate.c
+index 6f955eb1e1631..d8af46e677503 100644
+--- a/arch/x86/power/hibernate.c
++++ b/arch/x86/power/hibernate.c
+@@ -170,7 +170,7 @@ int relocate_restore_code(void)
+ goto out;
+ }
+ pud = pud_offset(p4d, relocated_restore_code);
+- if (pud_large(*pud)) {
++ if (pud_leaf(*pud)) {
+ set_pud(pud, __pud(pud_val(*pud) & ~_PAGE_NX));
+ goto out;
+ }
+diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c
+index 72af496a160c8..994aef4473a65 100644
+--- a/arch/x86/xen/mmu_pv.c
++++ b/arch/x86/xen/mmu_pv.c
+@@ -1082,7 +1082,7 @@ static void __init xen_cleanmfnmap_pud(pud_t *pud, bool unpin)
+ pmd_t *pmd_tbl;
+ int i;
+
+- if (pud_large(*pud)) {
++ if (pud_leaf(*pud)) {
+ pa = pud_val(*pud) & PHYSICAL_PAGE_MASK;
+ xen_free_ro_pages(pa, PUD_SIZE);
+ return;
+@@ -1863,7 +1863,7 @@ static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr)
+ if (!pud_present(pud))
+ return 0;
+ pa = pud_val(pud) & PTE_PFN_MASK;
+- if (pud_large(pud))
++ if (pud_leaf(pud))
+ return pa + (vaddr & ~PUD_MASK);
+
+ pmd = native_make_pmd(xen_read_phys_ulong(pa + pmd_index(vaddr) *
+diff --git a/block/bdev.c b/block/bdev.c
+index e9f1b12bd75c7..678807bcd0034 100644
+--- a/block/bdev.c
++++ b/block/bdev.c
+@@ -738,17 +738,17 @@ void blkdev_put_no_open(struct block_device *bdev)
+
+ static bool bdev_writes_blocked(struct block_device *bdev)
+ {
+- return bdev->bd_writers == -1;
++ return bdev->bd_writers < 0;
+ }
+
+ static void bdev_block_writes(struct block_device *bdev)
+ {
+- bdev->bd_writers = -1;
++ bdev->bd_writers--;
+ }
+
+ static void bdev_unblock_writes(struct block_device *bdev)
+ {
+- bdev->bd_writers = 0;
++ bdev->bd_writers++;
+ }
+
+ static bool bdev_may_open(struct block_device *bdev, blk_mode_t mode)
+diff --git a/drivers/acpi/acpica/dbnames.c b/drivers/acpi/acpica/dbnames.c
+index b91155ea9c343..c9131259f717b 100644
+--- a/drivers/acpi/acpica/dbnames.c
++++ b/drivers/acpi/acpica/dbnames.c
+@@ -550,8 +550,12 @@ acpi_db_walk_for_fields(acpi_handle obj_handle,
+ ACPI_FREE(buffer.pointer);
+
+ buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+- acpi_evaluate_object(obj_handle, NULL, NULL, &buffer);
+-
++ status = acpi_evaluate_object(obj_handle, NULL, NULL, &buffer);
++ if (ACPI_FAILURE(status)) {
++ acpi_os_printf("Could Not evaluate object %p\n",
++ obj_handle);
++ return (AE_OK);
++ }
+ /*
+ * Since this is a field unit, surround the output in braces
+ */
+diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
+index e82786c63fbd7..9bec0aee92e04 100644
+--- a/drivers/ata/sata_mv.c
++++ b/drivers/ata/sata_mv.c
+@@ -787,37 +787,6 @@ static const struct ata_port_info mv_port_info[] = {
+ },
+ };
+
+-static const struct pci_device_id mv_pci_tbl[] = {
+- { PCI_VDEVICE(MARVELL, 0x5040), chip_504x },
+- { PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
+- { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
+- { PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
+- /* RocketRAID 1720/174x have different identifiers */
+- { PCI_VDEVICE(TTI, 0x1720), chip_6042 },
+- { PCI_VDEVICE(TTI, 0x1740), chip_6042 },
+- { PCI_VDEVICE(TTI, 0x1742), chip_6042 },
+-
+- { PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
+- { PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
+- { PCI_VDEVICE(MARVELL, 0x6042), chip_6042 },
+- { PCI_VDEVICE(MARVELL, 0x6080), chip_608x },
+- { PCI_VDEVICE(MARVELL, 0x6081), chip_608x },
+-
+- { PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
+-
+- /* Adaptec 1430SA */
+- { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
+-
+- /* Marvell 7042 support */
+- { PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
+-
+- /* Highpoint RocketRAID PCIe series */
+- { PCI_VDEVICE(TTI, 0x2300), chip_7042 },
+- { PCI_VDEVICE(TTI, 0x2310), chip_7042 },
+-
+- { } /* terminate list */
+-};
+-
+ static const struct mv_hw_ops mv5xxx_ops = {
+ .phy_errata = mv5_phy_errata,
+ .enable_leds = mv5_enable_leds,
+@@ -4303,6 +4272,36 @@ static int mv_pci_init_one(struct pci_dev *pdev,
+ static int mv_pci_device_resume(struct pci_dev *pdev);
+ #endif
+
++static const struct pci_device_id mv_pci_tbl[] = {
++ { PCI_VDEVICE(MARVELL, 0x5040), chip_504x },
++ { PCI_VDEVICE(MARVELL, 0x5041), chip_504x },
++ { PCI_VDEVICE(MARVELL, 0x5080), chip_5080 },
++ { PCI_VDEVICE(MARVELL, 0x5081), chip_508x },
++ /* RocketRAID 1720/174x have different identifiers */
++ { PCI_VDEVICE(TTI, 0x1720), chip_6042 },
++ { PCI_VDEVICE(TTI, 0x1740), chip_6042 },
++ { PCI_VDEVICE(TTI, 0x1742), chip_6042 },
++
++ { PCI_VDEVICE(MARVELL, 0x6040), chip_604x },
++ { PCI_VDEVICE(MARVELL, 0x6041), chip_604x },
++ { PCI_VDEVICE(MARVELL, 0x6042), chip_6042 },
++ { PCI_VDEVICE(MARVELL, 0x6080), chip_608x },
++ { PCI_VDEVICE(MARVELL, 0x6081), chip_608x },
++
++ { PCI_VDEVICE(ADAPTEC2, 0x0241), chip_604x },
++
++ /* Adaptec 1430SA */
++ { PCI_VDEVICE(ADAPTEC2, 0x0243), chip_7042 },
++
++ /* Marvell 7042 support */
++ { PCI_VDEVICE(MARVELL, 0x7042), chip_7042 },
++
++ /* Highpoint RocketRAID PCIe series */
++ { PCI_VDEVICE(TTI, 0x2300), chip_7042 },
++ { PCI_VDEVICE(TTI, 0x2310), chip_7042 },
++
++ { } /* terminate list */
++};
+
+ static struct pci_driver mv_pci_driver = {
+ .name = DRV_NAME,
+@@ -4315,6 +4314,7 @@ static struct pci_driver mv_pci_driver = {
+ #endif
+
+ };
++MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
+
+ /**
+ * mv_print_info - Dump key info to kernel log for perusal.
+@@ -4487,7 +4487,6 @@ static void __exit mv_exit(void)
+ MODULE_AUTHOR("Brett Russ");
+ MODULE_DESCRIPTION("SCSI low-level driver for Marvell SATA controllers");
+ MODULE_LICENSE("GPL v2");
+-MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
+ MODULE_VERSION(DRV_VERSION);
+ MODULE_ALIAS("platform:" DRV_NAME);
+
+diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
+index b51d7a9d0d90c..a482741eb181f 100644
+--- a/drivers/ata/sata_sx4.c
++++ b/drivers/ata/sata_sx4.c
+@@ -957,8 +957,7 @@ static void pdc20621_get_from_dimm(struct ata_host *host, void *psource,
+
+ offset -= (idx * window_size);
+ idx++;
+- dist = ((long) (window_size - (offset + size))) >= 0 ? size :
+- (long) (window_size - offset);
++ dist = min(size, window_size - offset);
+ memcpy_fromio(psource, dimm_mmio + offset / 4, dist);
+
+ psource += dist;
+@@ -1005,8 +1004,7 @@ static void pdc20621_put_to_dimm(struct ata_host *host, void *psource,
+ readl(mmio + PDC_DIMM_WINDOW_CTLR);
+ offset -= (idx * window_size);
+ idx++;
+- dist = ((long)(s32)(window_size - (offset + size))) >= 0 ? size :
+- (long) (window_size - offset);
++ dist = min(size, window_size - offset);
+ memcpy_toio(dimm_mmio + offset / 4, psource, dist);
+ writel(0x01, mmio + PDC_GENERAL_CTLR);
+ readl(mmio + PDC_GENERAL_CTLR);
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 9828da9b933cb..7f39c813ce52c 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -44,6 +44,7 @@ static bool fw_devlink_is_permissive(void);
+ static void __fw_devlink_link_to_consumers(struct device *dev);
+ static bool fw_devlink_drv_reg_done;
+ static bool fw_devlink_best_effort;
++static struct workqueue_struct *device_link_wq;
+
+ /**
+ * __fwnode_link_add - Create a link between two fwnode_handles.
+@@ -532,12 +533,26 @@ static void devlink_dev_release(struct device *dev)
+ /*
+ * It may take a while to complete this work because of the SRCU
+ * synchronization in device_link_release_fn() and if the consumer or
+- * supplier devices get deleted when it runs, so put it into the "long"
+- * workqueue.
++ * supplier devices get deleted when it runs, so put it into the
++ * dedicated workqueue.
+ */
+- queue_work(system_long_wq, &link->rm_work);
++ queue_work(device_link_wq, &link->rm_work);
+ }
+
++/**
++ * device_link_wait_removal - Wait for ongoing devlink removal jobs to terminate
++ */
++void device_link_wait_removal(void)
++{
++ /*
++ * devlink removal jobs are queued in the dedicated work queue.
++ * To be sure that all removal jobs are terminated, ensure that any
++ * scheduled work has run to completion.
++ */
++ flush_workqueue(device_link_wq);
++}
++EXPORT_SYMBOL_GPL(device_link_wait_removal);
++
+ static struct class devlink_class = {
+ .name = "devlink",
+ .dev_groups = devlink_groups,
+@@ -4098,9 +4113,14 @@ int __init devices_init(void)
+ sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
+ if (!sysfs_dev_char_kobj)
+ goto char_kobj_err;
++ device_link_wq = alloc_workqueue("device_link_wq", 0, 0);
++ if (!device_link_wq)
++ goto wq_err;
+
+ return 0;
+
++ wq_err:
++ kobject_put(sysfs_dev_char_kobj);
+ char_kobj_err:
+ kobject_put(sysfs_dev_block_kobj);
+ block_kobj_err:
+diff --git a/drivers/base/regmap/regcache-maple.c b/drivers/base/regmap/regcache-maple.c
+index 41edd6a430eb4..55999a50ccc0b 100644
+--- a/drivers/base/regmap/regcache-maple.c
++++ b/drivers/base/regmap/regcache-maple.c
+@@ -112,7 +112,7 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min,
+ unsigned long *entry, *lower, *upper;
+ unsigned long lower_index, lower_last;
+ unsigned long upper_index, upper_last;
+- int ret;
++ int ret = 0;
+
+ lower = NULL;
+ upper = NULL;
+@@ -145,7 +145,7 @@ static int regcache_maple_drop(struct regmap *map, unsigned int min,
+ upper_index = max + 1;
+ upper_last = mas.last;
+
+- upper = kmemdup(&entry[max + 1],
++ upper = kmemdup(&entry[max - mas.index + 1],
+ ((mas.last - max) *
+ sizeof(unsigned long)),
+ map->alloc_flags);
+@@ -244,7 +244,7 @@ static int regcache_maple_sync(struct regmap *map, unsigned int min,
+ unsigned long lmin = min;
+ unsigned long lmax = max;
+ unsigned int r, v, sync_start;
+- int ret;
++ int ret = 0;
+ bool sync_needed = false;
+
+ map->cache_bypass = true;
+diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
+index b40b32fa7f1c3..19cfc342fc7bb 100644
+--- a/drivers/bluetooth/btqca.c
++++ b/drivers/bluetooth/btqca.c
+@@ -826,11 +826,15 @@ EXPORT_SYMBOL_GPL(qca_uart_setup);
+
+ int qca_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+ {
++ bdaddr_t bdaddr_swapped;
+ struct sk_buff *skb;
+ int err;
+
+- skb = __hci_cmd_sync_ev(hdev, EDL_WRITE_BD_ADDR_OPCODE, 6, bdaddr,
+- HCI_EV_VENDOR, HCI_INIT_TIMEOUT);
++ baswap(&bdaddr_swapped, bdaddr);
++
++ skb = __hci_cmd_sync_ev(hdev, EDL_WRITE_BD_ADDR_OPCODE, 6,
++ &bdaddr_swapped, HCI_EV_VENDOR,
++ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ bt_dev_err(hdev, "QCA Change address cmd failed (%d)", err);
+diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
+index 8a60ad7acd705..ecbc52eaf1010 100644
+--- a/drivers/bluetooth/hci_qca.c
++++ b/drivers/bluetooth/hci_qca.c
+@@ -7,7 +7,6 @@
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Copyright (c) 2010, 2012, 2018 The Linux Foundation. All rights reserved.
+- * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ * Acknowledgements:
+ * This file is based on hci_ll.c, which was...
+@@ -226,6 +225,7 @@ struct qca_serdev {
+ struct qca_power *bt_power;
+ u32 init_speed;
+ u32 oper_speed;
++ bool bdaddr_property_broken;
+ const char *firmware_name;
+ };
+
+@@ -1843,6 +1843,7 @@ static int qca_setup(struct hci_uart *hu)
+ const char *firmware_name = qca_get_firmware_name(hu);
+ int ret;
+ struct qca_btsoc_version ver;
++ struct qca_serdev *qcadev;
+ const char *soc_name;
+
+ ret = qca_check_speeds(hu);
+@@ -1904,16 +1905,11 @@ static int qca_setup(struct hci_uart *hu)
+ case QCA_WCN6750:
+ case QCA_WCN6855:
+ case QCA_WCN7850:
++ set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
+
+- /* Set BDA quirk bit for reading BDA value from fwnode property
+- * only if that property exist in DT.
+- */
+- if (fwnode_property_present(dev_fwnode(hdev->dev.parent), "local-bd-address")) {
+- set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
+- bt_dev_info(hdev, "setting quirk bit to read BDA from fwnode later");
+- } else {
+- bt_dev_dbg(hdev, "local-bd-address` is not present in the devicetree so not setting quirk bit for BDA");
+- }
++ qcadev = serdev_device_get_drvdata(hu->serdev);
++ if (qcadev->bdaddr_property_broken)
++ set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks);
+
+ hci_set_aosp_capable(hdev);
+
+@@ -2295,6 +2291,9 @@ static int qca_serdev_probe(struct serdev_device *serdev)
+ if (!qcadev->oper_speed)
+ BT_DBG("UART will pick default operating speed");
+
++ qcadev->bdaddr_property_broken = device_property_read_bool(&serdev->dev,
++ "qcom,local-bd-address-broken");
++
+ if (data)
+ qcadev->btsoc_type = data->soc_type;
+ else
+diff --git a/drivers/dma-buf/st-dma-fence-chain.c b/drivers/dma-buf/st-dma-fence-chain.c
+index 9c2a0c082a768..ed4b323886e43 100644
+--- a/drivers/dma-buf/st-dma-fence-chain.c
++++ b/drivers/dma-buf/st-dma-fence-chain.c
+@@ -84,11 +84,11 @@ static int sanitycheck(void *arg)
+ return -ENOMEM;
+
+ chain = mock_chain(NULL, f, 1);
+- if (!chain)
++ if (chain)
++ dma_fence_enable_sw_signaling(chain);
++ else
+ err = -ENOMEM;
+
+- dma_fence_enable_sw_signaling(chain);
+-
+ dma_fence_signal(f);
+ dma_fence_put(f);
+
+diff --git a/drivers/dpll/Kconfig b/drivers/dpll/Kconfig
+index a4cae73f20d3d..20607ed542435 100644
+--- a/drivers/dpll/Kconfig
++++ b/drivers/dpll/Kconfig
+@@ -4,4 +4,4 @@
+ #
+
+ config DPLL
+- bool
++ bool
+diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
+index bfa30625f5d03..3dc2f9aaf08db 100644
+--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
++++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
+@@ -24,6 +24,8 @@ static bool efi_noinitrd;
+ static bool efi_nosoftreserve;
+ static bool efi_disable_pci_dma = IS_ENABLED(CONFIG_EFI_DISABLE_PCI_DMA);
+
++int efi_mem_encrypt;
++
+ bool __pure __efi_soft_reserve_enabled(void)
+ {
+ return !efi_nosoftreserve;
+@@ -75,6 +77,12 @@ efi_status_t efi_parse_options(char const *cmdline)
+ efi_noinitrd = true;
+ } else if (IS_ENABLED(CONFIG_X86_64) && !strcmp(param, "no5lvl")) {
+ efi_no5lvl = true;
++ } else if (IS_ENABLED(CONFIG_ARCH_HAS_MEM_ENCRYPT) &&
++ !strcmp(param, "mem_encrypt") && val) {
++ if (parse_option_str(val, "on"))
++ efi_mem_encrypt = 1;
++ else if (parse_option_str(val, "off"))
++ efi_mem_encrypt = -1;
+ } else if (!strcmp(param, "efi") && val) {
+ efi_nochunk = parse_option_str(val, "nochunk");
+ efi_novamap |= parse_option_str(val, "novamap");
+diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
+index c04b82ea40f21..fc18fd649ed77 100644
+--- a/drivers/firmware/efi/libstub/efistub.h
++++ b/drivers/firmware/efi/libstub/efistub.h
+@@ -37,8 +37,8 @@ extern bool efi_no5lvl;
+ extern bool efi_nochunk;
+ extern bool efi_nokaslr;
+ extern int efi_loglevel;
++extern int efi_mem_encrypt;
+ extern bool efi_novamap;
+-
+ extern const efi_system_table_t *efi_system_table;
+
+ typedef union efi_dxe_services_table efi_dxe_services_table_t;
+diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
+index dd80082aac1ac..19b51dc34f670 100644
+--- a/drivers/firmware/efi/libstub/x86-stub.c
++++ b/drivers/firmware/efi/libstub/x86-stub.c
+@@ -238,6 +238,15 @@ efi_status_t efi_adjust_memory_range_protection(unsigned long start,
+ rounded_end = roundup(start + size, EFI_PAGE_SIZE);
+
+ if (memattr != NULL) {
++ status = efi_call_proto(memattr, set_memory_attributes,
++ rounded_start,
++ rounded_end - rounded_start,
++ EFI_MEMORY_RO);
++ if (status != EFI_SUCCESS) {
++ efi_warn("Failed to set EFI_MEMORY_RO attribute\n");
++ return status;
++ }
++
+ status = efi_call_proto(memattr, clear_memory_attributes,
+ rounded_start,
+ rounded_end - rounded_start,
+@@ -818,7 +827,7 @@ static efi_status_t efi_decompress_kernel(unsigned long *kernel_entry)
+
+ *kernel_entry = addr + entry;
+
+- return efi_adjust_memory_range_protection(addr, kernel_total_size);
++ return efi_adjust_memory_range_protection(addr, kernel_text_size);
+ }
+
+ static void __noreturn enter_kernel(unsigned long kernel_addr,
+@@ -890,6 +899,9 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
+ }
+ }
+
++ if (efi_mem_encrypt > 0)
++ hdr->xloadflags |= XLF_MEM_ENCRYPTION;
++
+ status = efi_decompress_kernel(&kernel_entry);
+ if (status != EFI_SUCCESS) {
+ efi_err("Failed to decompress kernel\n");
+diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
+index 2a88736629ef3..1438fdca0b748 100644
+--- a/drivers/gpio/gpiolib-cdev.c
++++ b/drivers/gpio/gpiolib-cdev.c
+@@ -734,6 +734,25 @@ static u32 line_event_id(int level)
+ GPIO_V2_LINE_EVENT_FALLING_EDGE;
+ }
+
++static inline char *make_irq_label(const char *orig)
++{
++ char *new;
++
++ if (!orig)
++ return NULL;
++
++ new = kstrdup_and_replace(orig, '/', ':', GFP_KERNEL);
++ if (!new)
++ return ERR_PTR(-ENOMEM);
++
++ return new;
++}
++
++static inline void free_irq_label(const char *label)
++{
++ kfree(label);
++}
++
+ #ifdef CONFIG_HTE
+
+ static enum hte_return process_hw_ts_thread(void *p)
+@@ -1021,6 +1040,7 @@ static int debounce_setup(struct line *line, unsigned int debounce_period_us)
+ {
+ unsigned long irqflags;
+ int ret, level, irq;
++ char *label;
+
+ /* try hardware */
+ ret = gpiod_set_debounce(line->desc, debounce_period_us);
+@@ -1043,11 +1063,17 @@ static int debounce_setup(struct line *line, unsigned int debounce_period_us)
+ if (irq < 0)
+ return -ENXIO;
+
++ label = make_irq_label(line->req->label);
++ if (IS_ERR(label))
++ return -ENOMEM;
++
+ irqflags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
+ ret = request_irq(irq, debounce_irq_handler, irqflags,
+- line->req->label, line);
+- if (ret)
++ label, line);
++ if (ret) {
++ free_irq_label(label);
+ return ret;
++ }
+ line->irq = irq;
+ } else {
+ ret = hte_edge_setup(line, GPIO_V2_LINE_FLAG_EDGE_BOTH);
+@@ -1092,7 +1118,7 @@ static u32 gpio_v2_line_config_debounce_period(struct gpio_v2_line_config *lc,
+ static void edge_detector_stop(struct line *line)
+ {
+ if (line->irq) {
+- free_irq(line->irq, line);
++ free_irq_label(free_irq(line->irq, line));
+ line->irq = 0;
+ }
+
+@@ -1116,6 +1142,7 @@ static int edge_detector_setup(struct line *line,
+ unsigned long irqflags = 0;
+ u64 eflags;
+ int irq, ret;
++ char *label;
+
+ eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS;
+ if (eflags && !kfifo_initialized(&line->req->events)) {
+@@ -1152,11 +1179,17 @@ static int edge_detector_setup(struct line *line,
+ IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
+ irqflags |= IRQF_ONESHOT;
+
++ label = make_irq_label(line->req->label);
++ if (IS_ERR(label))
++ return PTR_ERR(label);
++
+ /* Request a thread to read the events */
+ ret = request_threaded_irq(irq, edge_irq_handler, edge_irq_thread,
+- irqflags, line->req->label, line);
+- if (ret)
++ irqflags, label, line);
++ if (ret) {
++ free_irq_label(label);
+ return ret;
++ }
+
+ line->irq = irq;
+ return 0;
+@@ -1979,7 +2012,7 @@ static void lineevent_free(struct lineevent_state *le)
+ blocking_notifier_chain_unregister(&le->gdev->device_notifier,
+ &le->device_unregistered_nb);
+ if (le->irq)
+- free_irq(le->irq, le);
++ free_irq_label(free_irq(le->irq, le));
+ if (le->desc)
+ gpiod_free(le->desc);
+ kfree(le->label);
+@@ -2120,6 +2153,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
+ int fd;
+ int ret;
+ int irq, irqflags = 0;
++ char *label;
+
+ if (copy_from_user(&eventreq, ip, sizeof(eventreq)))
+ return -EFAULT;
+@@ -2204,15 +2238,23 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
+ if (ret)
+ goto out_free_le;
+
++ label = make_irq_label(le->label);
++ if (IS_ERR(label)) {
++ ret = PTR_ERR(label);
++ goto out_free_le;
++ }
++
+ /* Request a thread to read the events */
+ ret = request_threaded_irq(irq,
+ lineevent_irq_handler,
+ lineevent_irq_thread,
+ irqflags,
+- le->label,
++ label,
+ le);
+- if (ret)
++ if (ret) {
++ free_irq_label(label);
+ goto out_free_le;
++ }
+
+ le->irq = irq;
+
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index 3ad09d2193330..d9da0331e8340 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -2402,6 +2402,11 @@ char *gpiochip_dup_line_label(struct gpio_chip *gc, unsigned int offset)
+ }
+ EXPORT_SYMBOL_GPL(gpiochip_dup_line_label);
+
++static inline const char *function_name_or_default(const char *con_id)
++{
++ return con_id ?: "(default)";
++}
++
+ /**
+ * gpiochip_request_own_desc - Allow GPIO chip to request its own descriptor
+ * @gc: GPIO chip
+@@ -2430,10 +2435,11 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc,
+ enum gpiod_flags dflags)
+ {
+ struct gpio_desc *desc = gpiochip_get_desc(gc, hwnum);
++ const char *name = function_name_or_default(label);
+ int ret;
+
+ if (IS_ERR(desc)) {
+- chip_err(gc, "failed to get GPIO descriptor\n");
++ chip_err(gc, "failed to get GPIO %s descriptor\n", name);
+ return desc;
+ }
+
+@@ -2443,8 +2449,8 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc,
+
+ ret = gpiod_configure_flags(desc, label, lflags, dflags);
+ if (ret) {
+- chip_err(gc, "setup of own GPIO %s failed\n", label);
+ gpiod_free_commit(desc);
++ chip_err(gc, "setup of own GPIO %s failed\n", name);
+ return ERR_PTR(ret);
+ }
+
+@@ -4119,19 +4125,17 @@ static struct gpio_desc *gpiod_find_by_fwnode(struct fwnode_handle *fwnode,
+ enum gpiod_flags *flags,
+ unsigned long *lookupflags)
+ {
++ const char *name = function_name_or_default(con_id);
+ struct gpio_desc *desc = ERR_PTR(-ENOENT);
+
+ if (is_of_node(fwnode)) {
+- dev_dbg(consumer, "using DT '%pfw' for '%s' GPIO lookup\n",
+- fwnode, con_id);
++ dev_dbg(consumer, "using DT '%pfw' for '%s' GPIO lookup\n", fwnode, name);
+ desc = of_find_gpio(to_of_node(fwnode), con_id, idx, lookupflags);
+ } else if (is_acpi_node(fwnode)) {
+- dev_dbg(consumer, "using ACPI '%pfw' for '%s' GPIO lookup\n",
+- fwnode, con_id);
++ dev_dbg(consumer, "using ACPI '%pfw' for '%s' GPIO lookup\n", fwnode, name);
+ desc = acpi_find_gpio(fwnode, con_id, idx, flags, lookupflags);
+ } else if (is_software_node(fwnode)) {
+- dev_dbg(consumer, "using swnode '%pfw' for '%s' GPIO lookup\n",
+- fwnode, con_id);
++ dev_dbg(consumer, "using swnode '%pfw' for '%s' GPIO lookup\n", fwnode, name);
+ desc = swnode_find_gpio(fwnode, con_id, idx, lookupflags);
+ }
+
+@@ -4147,6 +4151,7 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
+ bool platform_lookup_allowed)
+ {
+ unsigned long lookupflags = GPIO_LOOKUP_FLAGS_DEFAULT;
++ const char *name = function_name_or_default(con_id);
+ struct gpio_desc *desc;
+ int ret;
+
+@@ -4162,7 +4167,7 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
+ }
+
+ if (IS_ERR(desc)) {
+- dev_dbg(consumer, "No GPIO consumer %s found\n", con_id);
++ dev_dbg(consumer, "No GPIO consumer %s found\n", name);
+ return desc;
+ }
+
+@@ -4183,15 +4188,14 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer,
+ *
+ * FIXME: Make this more sane and safe.
+ */
+- dev_info(consumer,
+- "nonexclusive access to GPIO for %s\n", con_id);
++ dev_info(consumer, "nonexclusive access to GPIO for %s\n", name);
+ return desc;
+ }
+
+ ret = gpiod_configure_flags(desc, con_id, lookupflags, flags);
+ if (ret < 0) {
+- dev_dbg(consumer, "setup of GPIO %s failed\n", con_id);
+ gpiod_put(desc);
++ dev_dbg(consumer, "setup of GPIO %s failed\n", name);
+ return ERR_PTR(ret);
+ }
+
+@@ -4307,6 +4311,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_optional);
+ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
+ unsigned long lflags, enum gpiod_flags dflags)
+ {
++ const char *name = function_name_or_default(con_id);
+ int ret;
+
+ if (lflags & GPIO_ACTIVE_LOW)
+@@ -4350,7 +4355,7 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
+
+ /* No particular flag request, return here... */
+ if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) {
+- gpiod_dbg(desc, "no flags found for %s\n", con_id);
++ gpiod_dbg(desc, "no flags found for GPIO %s\n", name);
+ return 0;
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index 94bdb5fa6ebc6..1fbaf7b81d69a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -4524,6 +4524,8 @@ int amdgpu_device_prepare(struct drm_device *dev)
+ if (r)
+ goto unprepare;
+
++ flush_delayed_work(&adev->gfx.gfx_off_delay_work);
++
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+ if (!adev->ip_blocks[i].status.valid)
+ continue;
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+index 3db46bdc71a35..9cbab880c6233 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+@@ -384,19 +384,6 @@ static void dcn35_enable_pme_wa(struct clk_mgr *clk_mgr_base)
+ dcn35_smu_enable_pme_wa(clk_mgr);
+ }
+
+-void dcn35_init_clocks(struct clk_mgr *clk_mgr)
+-{
+- uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz;
+-
+- memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
+-
+- // Assumption is that boot state always supports pstate
+- clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk; // restore ref_dtbclk
+- clk_mgr->clks.p_state_change_support = true;
+- clk_mgr->clks.prev_p_state_change_support = true;
+- clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN;
+- clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN;
+-}
+
+ bool dcn35_are_clock_states_equal(struct dc_clocks *a,
+ struct dc_clocks *b)
+@@ -421,7 +408,19 @@ static void dcn35_dump_clk_registers(struct clk_state_registers_and_bypass *regs
+ struct clk_mgr_dcn35 *clk_mgr)
+ {
+ }
++void dcn35_init_clocks(struct clk_mgr *clk_mgr)
++{
++ uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz;
+
++ memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks));
++
++ // Assumption is that boot state always supports pstate
++ clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk; // restore ref_dtbclk
++ clk_mgr->clks.p_state_change_support = true;
++ clk_mgr->clks.prev_p_state_change_support = true;
++ clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN;
++ clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN;
++}
+ static struct clk_bw_params dcn35_bw_params = {
+ .vram_type = Ddr4MemType,
+ .num_channels = 1,
+diff --git a/drivers/gpu/drm/amd/display/dc/dce110/Makefile b/drivers/gpu/drm/amd/display/dc/dce110/Makefile
+index f0777d61c2cbb..c307f040e48fc 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce110/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dce110/Makefile
+@@ -23,7 +23,7 @@
+ # Makefile for the 'controller' sub-component of DAL.
+ # It provides the control and status of HW CRTC block.
+
+-CFLAGS_$(AMDDALPATH)/dc/dce110/dce110_resource.o = $(call cc-disable-warning, override-init)
++CFLAGS_$(AMDDALPATH)/dc/dce110/dce110_resource.o = -Wno-override-init
+
+ DCE110 = dce110_timing_generator.o \
+ dce110_compressor.o dce110_opp_regamma_v.o \
+diff --git a/drivers/gpu/drm/amd/display/dc/dce112/Makefile b/drivers/gpu/drm/amd/display/dc/dce112/Makefile
+index 7e92effec8944..683866797709b 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce112/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dce112/Makefile
+@@ -23,7 +23,7 @@
+ # Makefile for the 'controller' sub-component of DAL.
+ # It provides the control and status of HW CRTC block.
+
+-CFLAGS_$(AMDDALPATH)/dc/dce112/dce112_resource.o = $(call cc-disable-warning, override-init)
++CFLAGS_$(AMDDALPATH)/dc/dce112/dce112_resource.o = -Wno-override-init
+
+ DCE112 = dce112_compressor.o
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dce120/Makefile b/drivers/gpu/drm/amd/display/dc/dce120/Makefile
+index 1e3ef68a452a5..8f508e6627480 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce120/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dce120/Makefile
+@@ -24,7 +24,7 @@
+ # It provides the control and status of HW CRTC block.
+
+
+-CFLAGS_$(AMDDALPATH)/dc/dce120/dce120_resource.o = $(call cc-disable-warning, override-init)
++CFLAGS_$(AMDDALPATH)/dc/dce120/dce120_resource.o = -Wno-override-init
+
+ DCE120 = dce120_timing_generator.o
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dce60/Makefile b/drivers/gpu/drm/amd/display/dc/dce60/Makefile
+index fee331accc0e7..eede83ad91fa0 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce60/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dce60/Makefile
+@@ -23,7 +23,7 @@
+ # Makefile for the 'controller' sub-component of DAL.
+ # It provides the control and status of HW CRTC block.
+
+-CFLAGS_$(AMDDALPATH)/dc/dce60/dce60_resource.o = $(call cc-disable-warning, override-init)
++CFLAGS_$(AMDDALPATH)/dc/dce60/dce60_resource.o = -Wno-override-init
+
+ DCE60 = dce60_timing_generator.o dce60_hw_sequencer.o \
+ dce60_resource.o
+diff --git a/drivers/gpu/drm/amd/display/dc/dce80/Makefile b/drivers/gpu/drm/amd/display/dc/dce80/Makefile
+index 7eefffbdc9253..fba189d26652d 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce80/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dce80/Makefile
+@@ -23,7 +23,7 @@
+ # Makefile for the 'controller' sub-component of DAL.
+ # It provides the control and status of HW CRTC block.
+
+-CFLAGS_$(AMDDALPATH)/dc/dce80/dce80_resource.o = $(call cc-disable-warning, override-init)
++CFLAGS_$(AMDDALPATH)/dc/dce80/dce80_resource.o = -Wno-override-init
+
+ DCE80 = dce80_timing_generator.o
+
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+index 5fdcda8f86026..04d230aa8861f 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+@@ -701,7 +701,7 @@ static const struct dc_plane_cap plane_cap = {
+
+ // 6:1 downscaling ratio: 1000/6 = 166.666
+ .max_downscale_factor = {
+- .argb8888 = 167,
++ .argb8888 = 250,
+ .nv12 = 167,
+ .fp16 = 167
+ },
+diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
+index 7352bde299d54..03bd3c7bd0dc2 100644
+--- a/drivers/gpu/drm/drm_prime.c
++++ b/drivers/gpu/drm/drm_prime.c
+@@ -582,7 +582,12 @@ int drm_gem_map_attach(struct dma_buf *dma_buf,
+ {
+ struct drm_gem_object *obj = dma_buf->priv;
+
+- if (!obj->funcs->get_sg_table)
++ /*
++ * drm_gem_map_dma_buf() requires obj->get_sg_table(), but drivers
++ * that implement their own ->map_dma_buf() do not.
++ */
++ if (dma_buf->ops->map_dma_buf == drm_gem_map_dma_buf &&
++ !obj->funcs->get_sg_table)
+ return -ENOSYS;
+
+ return drm_gem_pin(obj);
+diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
+index c13f14edb5088..2d08baa91da08 100644
+--- a/drivers/gpu/drm/i915/Makefile
++++ b/drivers/gpu/drm/i915/Makefile
+@@ -33,9 +33,9 @@ endif
+ subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror
+
+ # Fine grained warnings disable
+-CFLAGS_i915_pci.o = $(call cc-disable-warning, override-init)
+-CFLAGS_display/intel_display_device.o = $(call cc-disable-warning, override-init)
+-CFLAGS_display/intel_fbdev.o = $(call cc-disable-warning, override-init)
++CFLAGS_i915_pci.o = -Wno-override-init
++CFLAGS_display/intel_display_device.o = -Wno-override-init
++CFLAGS_display/intel_fbdev.o = -Wno-override-init
+
+ # Support compiling the display code separately for both i915 and xe
+ # drivers. Define I915 when building i915.
+@@ -118,6 +118,7 @@ gt-y += \
+ gt/intel_ggtt_fencing.o \
+ gt/intel_gt.o \
+ gt/intel_gt_buffer_pool.o \
++ gt/intel_gt_ccs_mode.o \
+ gt/intel_gt_clock_utils.o \
+ gt/intel_gt_debugfs.o \
+ gt/intel_gt_engines_debugfs.o \
+diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c
+index dfe0b07a122d1..06ec04e667e32 100644
+--- a/drivers/gpu/drm/i915/display/g4x_dp.c
++++ b/drivers/gpu/drm/i915/display/g4x_dp.c
+@@ -717,7 +717,6 @@ static void g4x_enable_dp(struct intel_atomic_state *state,
+ {
+ intel_enable_dp(state, encoder, pipe_config, conn_state);
+ intel_edp_backlight_on(pipe_config, conn_state);
+- encoder->audio_enable(encoder, pipe_config, conn_state);
+ }
+
+ static void vlv_enable_dp(struct intel_atomic_state *state,
+@@ -726,7 +725,6 @@ static void vlv_enable_dp(struct intel_atomic_state *state,
+ const struct drm_connector_state *conn_state)
+ {
+ intel_edp_backlight_on(pipe_config, conn_state);
+- encoder->audio_enable(encoder, pipe_config, conn_state);
+ }
+
+ static void g4x_pre_enable_dp(struct intel_atomic_state *state,
+diff --git a/drivers/gpu/drm/i915/display/intel_display_device.h b/drivers/gpu/drm/i915/display/intel_display_device.h
+index fe42688137863..9b1bce2624b9e 100644
+--- a/drivers/gpu/drm/i915/display/intel_display_device.h
++++ b/drivers/gpu/drm/i915/display/intel_display_device.h
+@@ -47,6 +47,7 @@ struct drm_printer;
+ #define HAS_DPT(i915) (DISPLAY_VER(i915) >= 13)
+ #define HAS_DSB(i915) (DISPLAY_INFO(i915)->has_dsb)
+ #define HAS_DSC(__i915) (DISPLAY_RUNTIME_INFO(__i915)->has_dsc)
++#define HAS_DSC_MST(__i915) (DISPLAY_VER(__i915) >= 12 && HAS_DSC(__i915))
+ #define HAS_FBC(i915) (DISPLAY_RUNTIME_INFO(i915)->fbc_mask != 0)
+ #define HAS_FPGA_DBG_UNCLAIMED(i915) (DISPLAY_INFO(i915)->has_fpga_dbg)
+ #define HAS_FW_BLC(i915) (DISPLAY_VER(i915) >= 3)
+diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
+index 94d2a15d8444a..360e90601ff93 100644
+--- a/drivers/gpu/drm/i915/display/intel_dp.c
++++ b/drivers/gpu/drm/i915/display/intel_dp.c
+@@ -1422,7 +1422,8 @@ static bool intel_dp_source_supports_fec(struct intel_dp *intel_dp,
+ if (DISPLAY_VER(dev_priv) >= 12)
+ return true;
+
+- if (DISPLAY_VER(dev_priv) == 11 && encoder->port != PORT_A)
++ if (DISPLAY_VER(dev_priv) == 11 && encoder->port != PORT_A &&
++ !intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST))
+ return true;
+
+ return false;
+@@ -1915,8 +1916,9 @@ icl_dsc_compute_link_config(struct intel_dp *intel_dp,
+ dsc_max_bpp = min(dsc_max_bpp, pipe_bpp - 1);
+
+ for (i = 0; i < ARRAY_SIZE(valid_dsc_bpp); i++) {
+- if (valid_dsc_bpp[i] < dsc_min_bpp ||
+- valid_dsc_bpp[i] > dsc_max_bpp)
++ if (valid_dsc_bpp[i] < dsc_min_bpp)
++ continue;
++ if (valid_dsc_bpp[i] > dsc_max_bpp)
+ break;
+
+ ret = dsc_compute_link_config(intel_dp,
+@@ -6523,6 +6525,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
+ intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;
+ else
+ intel_connector->get_hw_state = intel_connector_get_hw_state;
++ intel_connector->sync_state = intel_dp_connector_sync_state;
+
+ if (!intel_edp_init_connector(intel_dp, intel_connector)) {
+ intel_dp_aux_fini(intel_dp);
+diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
+index a01a59f57ae55..2151e916ccfa4 100644
+--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
++++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
+@@ -1338,7 +1338,7 @@ intel_dp_mst_mode_valid_ctx(struct drm_connector *connector,
+ return 0;
+ }
+
+- if (DISPLAY_VER(dev_priv) >= 10 &&
++ if (HAS_DSC_MST(dev_priv) &&
+ drm_dp_sink_supports_dsc(intel_connector->dp.dsc_dpcd)) {
+ /*
+ * TBD pass the connector BPC,
+diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
+index 2915d7afe5ccc..cc978ee6d1309 100644
+--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
++++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
+@@ -1830,8 +1830,6 @@ static void intel_disable_sdvo(struct intel_atomic_state *state,
+ struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
+ u32 temp;
+
+- encoder->audio_disable(encoder, old_crtc_state, conn_state);
+-
+ intel_sdvo_set_active_outputs(intel_sdvo, 0);
+ if (0)
+ intel_sdvo_set_encoder_power_state(intel_sdvo,
+@@ -1923,8 +1921,6 @@ static void intel_enable_sdvo(struct intel_atomic_state *state,
+ intel_sdvo_set_encoder_power_state(intel_sdvo,
+ DRM_MODE_DPMS_ON);
+ intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo_connector->output_flag);
+-
+- encoder->audio_enable(encoder, pipe_config, conn_state);
+ }
+
+ static enum drm_mode_status
+diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
+index 511dc1544854f..8bba6c2e50989 100644
+--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
++++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
+@@ -2290,6 +2290,9 @@ static u8 skl_get_plane_caps(struct drm_i915_private *i915,
+ if (HAS_4TILE(i915))
+ caps |= INTEL_PLANE_CAP_TILING_4;
+
++ if (!IS_ENABLED(I915) && !HAS_FLAT_CCS(i915))
++ return caps;
++
+ if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) {
+ caps |= INTEL_PLANE_CAP_CCS_RC;
+ if (DISPLAY_VER(i915) >= 12)
+diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
+index 86a04afff64b3..e1bf13e3d3070 100644
+--- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
++++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
+@@ -226,7 +226,7 @@ u32 *gen12_emit_aux_table_inv(struct intel_engine_cs *engine, u32 *cs)
+ static int mtl_dummy_pipe_control(struct i915_request *rq)
+ {
+ /* Wa_14016712196 */
+- if (IS_GFX_GT_IP_RANGE(rq->engine->gt, IP_VER(12, 70), IP_VER(12, 71)) ||
++ if (IS_GFX_GT_IP_RANGE(rq->engine->gt, IP_VER(12, 70), IP_VER(12, 74)) ||
+ IS_DG2(rq->i915)) {
+ u32 *cs;
+
+@@ -822,7 +822,7 @@ u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs)
+ flags |= PIPE_CONTROL_FLUSH_L3;
+
+ /* Wa_14016712196 */
+- if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)) || IS_DG2(i915))
++ if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74)) || IS_DG2(i915))
+ /* dummy PIPE_CONTROL + depth flush */
+ cs = gen12_emit_pipe_control(cs, 0,
+ PIPE_CONTROL_DEPTH_CACHE_FLUSH, 0);
+diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
+index fa46d2308b0ed..81bf2216371be 100644
+--- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
++++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
+@@ -961,6 +961,9 @@ static int gen8_init_rsvd(struct i915_address_space *vm)
+ struct i915_vma *vma;
+ int ret;
+
++ if (!intel_gt_needs_wa_16018031267(vm->gt))
++ return 0;
++
+ /* The memory will be used only by GPU. */
+ obj = i915_gem_object_create_lmem(i915, PAGE_SIZE,
+ I915_BO_ALLOC_VOLATILE |
+diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+index 40687806d22a6..84be97f959faa 100644
+--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
++++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+@@ -908,6 +908,23 @@ static intel_engine_mask_t init_engine_mask(struct intel_gt *gt)
+ info->engine_mask &= ~BIT(GSC0);
+ }
+
++ /*
++ * Do not create the command streamer for CCS slices beyond the first.
++ * All the workload submitted to the first engine will be shared among
++ * all the slices.
++ *
++ * Once the user will be allowed to customize the CCS mode, then this
++ * check needs to be removed.
++ */
++ if (IS_DG2(gt->i915)) {
++ u8 first_ccs = __ffs(CCS_MASK(gt));
++
++ /* Mask off all the CCS engine */
++ info->engine_mask &= ~GENMASK(CCS3, CCS0);
++ /* Put back in the first CCS engine */
++ info->engine_mask |= BIT(_CCS(first_ccs));
++ }
++
+ return info->engine_mask;
+ }
+
+diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
+index a425db5ed3a22..6a2c2718bcc38 100644
+--- a/drivers/gpu/drm/i915/gt/intel_gt.c
++++ b/drivers/gpu/drm/i915/gt/intel_gt.c
+@@ -1024,6 +1024,12 @@ enum i915_map_type intel_gt_coherent_map_type(struct intel_gt *gt,
+ return I915_MAP_WC;
+ }
+
++bool intel_gt_needs_wa_16018031267(struct intel_gt *gt)
++{
++ /* Wa_16018031267, Wa_16018063123 */
++ return IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 55), IP_VER(12, 71));
++}
++
+ bool intel_gt_needs_wa_22016122933(struct intel_gt *gt)
+ {
+ return MEDIA_VER_FULL(gt->i915) == IP_VER(13, 0) && gt->type == GT_MEDIA;
+diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h
+index 608f5c8729285..003eb93b826fd 100644
+--- a/drivers/gpu/drm/i915/gt/intel_gt.h
++++ b/drivers/gpu/drm/i915/gt/intel_gt.h
+@@ -82,17 +82,18 @@ struct drm_printer;
+ ##__VA_ARGS__); \
+ } while (0)
+
+-#define NEEDS_FASTCOLOR_BLT_WABB(engine) ( \
+- IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 55), IP_VER(12, 71)) && \
+- engine->class == COPY_ENGINE_CLASS && engine->instance == 0)
+-
+ static inline bool gt_is_root(struct intel_gt *gt)
+ {
+ return !gt->info.id;
+ }
+
++bool intel_gt_needs_wa_16018031267(struct intel_gt *gt);
+ bool intel_gt_needs_wa_22016122933(struct intel_gt *gt);
+
++#define NEEDS_FASTCOLOR_BLT_WABB(engine) ( \
++ intel_gt_needs_wa_16018031267(engine->gt) && \
++ engine->class == COPY_ENGINE_CLASS && engine->instance == 0)
++
+ static inline struct intel_gt *uc_to_gt(struct intel_uc *uc)
+ {
+ return container_of(uc, struct intel_gt, uc);
+diff --git a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c
+new file mode 100644
+index 0000000000000..044219c5960a5
+--- /dev/null
++++ b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c
+@@ -0,0 +1,39 @@
++// SPDX-License-Identifier: MIT
++/*
++ * Copyright © 2024 Intel Corporation
++ */
++
++#include "i915_drv.h"
++#include "intel_gt.h"
++#include "intel_gt_ccs_mode.h"
++#include "intel_gt_regs.h"
++
++void intel_gt_apply_ccs_mode(struct intel_gt *gt)
++{
++ int cslice;
++ u32 mode = 0;
++ int first_ccs = __ffs(CCS_MASK(gt));
++
++ if (!IS_DG2(gt->i915))
++ return;
++
++ /* Build the value for the fixed CCS load balancing */
++ for (cslice = 0; cslice < I915_MAX_CCS; cslice++) {
++ if (CCS_MASK(gt) & BIT(cslice))
++ /*
++ * If available, assign the cslice
++ * to the first available engine...
++ */
++ mode |= XEHP_CCS_MODE_CSLICE(cslice, first_ccs);
++
++ else
++ /*
++ * ... otherwise, mark the cslice as
++ * unavailable if no CCS dispatches here
++ */
++ mode |= XEHP_CCS_MODE_CSLICE(cslice,
++ XEHP_CCS_MODE_CSLICE_MASK);
++ }
++
++ intel_uncore_write(gt->uncore, XEHP_CCS_MODE, mode);
++}
+diff --git a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h
+new file mode 100644
+index 0000000000000..9e5549caeb269
+--- /dev/null
++++ b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h
+@@ -0,0 +1,13 @@
++/* SPDX-License-Identifier: MIT */
++/*
++ * Copyright © 2024 Intel Corporation
++ */
++
++#ifndef __INTEL_GT_CCS_MODE_H__
++#define __INTEL_GT_CCS_MODE_H__
++
++struct intel_gt;
++
++void intel_gt_apply_ccs_mode(struct intel_gt *gt);
++
++#endif /* __INTEL_GT_CCS_MODE_H__ */
+diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
+index 50962cfd1353a..743fe35667227 100644
+--- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h
++++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
+@@ -1477,8 +1477,14 @@
+ #define ECOBITS_PPGTT_CACHE4B (0 << 8)
+
+ #define GEN12_RCU_MODE _MMIO(0x14800)
++#define XEHP_RCU_MODE_FIXED_SLICE_CCS_MODE REG_BIT(1)
+ #define GEN12_RCU_MODE_CCS_ENABLE REG_BIT(0)
+
++#define XEHP_CCS_MODE _MMIO(0x14804)
++#define XEHP_CCS_MODE_CSLICE_MASK REG_GENMASK(2, 0) /* CCS0-3 + rsvd */
++#define XEHP_CCS_MODE_CSLICE_WIDTH ilog2(XEHP_CCS_MODE_CSLICE_MASK + 1)
++#define XEHP_CCS_MODE_CSLICE(cslice, ccs) (ccs << (cslice * XEHP_CCS_MODE_CSLICE_WIDTH))
++
+ #define CHV_FUSE_GT _MMIO(VLV_GUNIT_BASE + 0x2168)
+ #define CHV_FGT_DISABLE_SS0 (1 << 10)
+ #define CHV_FGT_DISABLE_SS1 (1 << 11)
+diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
+index 3eacbc50caf8d..59816dd6fbfef 100644
+--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
++++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
+@@ -10,6 +10,7 @@
+ #include "intel_engine_regs.h"
+ #include "intel_gpu_commands.h"
+ #include "intel_gt.h"
++#include "intel_gt_ccs_mode.h"
+ #include "intel_gt_mcr.h"
+ #include "intel_gt_print.h"
+ #include "intel_gt_regs.h"
+@@ -51,7 +52,8 @@
+ * registers belonging to BCS, VCS or VECS should be implemented in
+ * xcs_engine_wa_init(). Workarounds for registers not belonging to a specific
+ * engine's MMIO range but that are part of of the common RCS/CCS reset domain
+- * should be implemented in general_render_compute_wa_init().
++ * should be implemented in general_render_compute_wa_init(). The settings
++ * about the CCS load balancing should be added in ccs_engine_wa_mode().
+ *
+ * - GT workarounds: the list of these WAs is applied whenever these registers
+ * revert to their default values: on GPU reset, suspend/resume [1]_, etc.
+@@ -789,8 +791,13 @@ static void xelpg_ctx_gt_tuning_init(struct intel_engine_cs *engine,
+
+ dg2_ctx_gt_tuning_init(engine, wal);
+
+- if (IS_GFX_GT_IP_STEP(gt, IP_VER(12, 70), STEP_B0, STEP_FOREVER) ||
+- IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_B0, STEP_FOREVER))
++ /*
++ * Due to Wa_16014892111, the DRAW_WATERMARK tuning must be done in
++ * gen12_emit_indirect_ctx_rcs() rather than here on some early
++ * steppings.
++ */
++ if (!(IS_GFX_GT_IP_STEP(gt, IP_VER(12, 70), STEP_A0, STEP_B0) ||
++ IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_A0, STEP_B0)))
+ wa_add(wal, DRAW_WATERMARK, VERT_WM_VAL, 0x3FF, 0, false);
+ }
+
+@@ -908,7 +915,7 @@ __intel_engine_init_ctx_wa(struct intel_engine_cs *engine,
+ if (engine->class != RENDER_CLASS)
+ goto done;
+
+- if (IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 71)))
++ if (IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 74)))
+ xelpg_ctx_workarounds_init(engine, wal);
+ else if (IS_PONTEVECCHIO(i915))
+ ; /* noop; none at this time */
+@@ -1643,7 +1650,8 @@ pvc_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
+ static void
+ xelpg_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
+ {
+- /* Wa_14018778641 / Wa_18018781329 */
++ /* Wa_14018575942 / Wa_18018781329 */
++ wa_mcr_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB);
+ wa_mcr_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB);
+
+ /* Wa_22016670082 */
+@@ -1710,7 +1718,7 @@ xelpmp_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
+ */
+ static void gt_tuning_settings(struct intel_gt *gt, struct i915_wa_list *wal)
+ {
+- if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) {
++ if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74))) {
+ wa_mcr_write_or(wal, XEHP_L3SCQREG7, BLEND_FILL_CACHING_OPT_DIS);
+ wa_mcr_write_or(wal, XEHP_SQCM, EN_32B_ACCESS);
+ }
+@@ -1743,7 +1751,7 @@ gt_init_workarounds(struct intel_gt *gt, struct i915_wa_list *wal)
+ return;
+ }
+
+- if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)))
++ if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74)))
+ xelpg_gt_workarounds_init(gt, wal);
+ else if (IS_PONTEVECCHIO(i915))
+ pvc_gt_workarounds_init(gt, wal);
+@@ -2216,7 +2224,7 @@ void intel_engine_init_whitelist(struct intel_engine_cs *engine)
+
+ if (engine->gt->type == GT_MEDIA)
+ ; /* none yet */
+- else if (IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 71)))
++ else if (IS_GFX_GT_IP_RANGE(engine->gt, IP_VER(12, 70), IP_VER(12, 74)))
+ xelpg_whitelist_build(engine);
+ else if (IS_PONTEVECCHIO(i915))
+ pvc_whitelist_build(engine);
+@@ -2828,7 +2836,7 @@ add_render_compute_tuning_settings(struct intel_gt *gt,
+ {
+ struct drm_i915_private *i915 = gt->i915;
+
+- if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71)) || IS_DG2(i915))
++ if (IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74)) || IS_DG2(i915))
+ wa_mcr_write_clr_set(wal, RT_CTRL, STACKID_CTRL, STACKID_CTRL_512);
+
+ /*
+@@ -2844,6 +2852,28 @@ add_render_compute_tuning_settings(struct intel_gt *gt,
+ wa_write_clr(wal, GEN8_GARBCNTL, GEN12_BUS_HASH_CTL_BIT_EXC);
+ }
+
++static void ccs_engine_wa_mode(struct intel_engine_cs *engine, struct i915_wa_list *wal)
++{
++ struct intel_gt *gt = engine->gt;
++
++ if (!IS_DG2(gt->i915))
++ return;
++
++ /*
++ * Wa_14019159160: This workaround, along with others, leads to
++ * significant challenges in utilizing load balancing among the
++ * CCS slices. Consequently, an architectural decision has been
++ * made to completely disable automatic CCS load balancing.
++ */
++ wa_masked_en(wal, GEN12_RCU_MODE, XEHP_RCU_MODE_FIXED_SLICE_CCS_MODE);
++
++ /*
++ * After having disabled automatic load balancing we need to
++ * assign all slices to a single CCS. We will call it CCS mode 1
++ */
++ intel_gt_apply_ccs_mode(gt);
++}
++
+ /*
+ * The workarounds in this function apply to shared registers in
+ * the general render reset domain that aren't tied to a
+@@ -2881,7 +2911,8 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li
+ }
+
+ if (IS_GFX_GT_IP_STEP(gt, IP_VER(12, 70), STEP_B0, STEP_FOREVER) ||
+- IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_B0, STEP_FOREVER))
++ IS_GFX_GT_IP_STEP(gt, IP_VER(12, 71), STEP_B0, STEP_FOREVER) ||
++ IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 74), IP_VER(12, 74)))
+ /* Wa_14017856879 */
+ wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN3, MTL_DISABLE_FIX_FOR_EOT_FLUSH);
+
+@@ -2993,8 +3024,10 @@ engine_init_workarounds(struct intel_engine_cs *engine, struct i915_wa_list *wal
+ * to a single RCS/CCS engine's workaround list since
+ * they're reset as part of the general render domain reset.
+ */
+- if (engine->flags & I915_ENGINE_FIRST_RENDER_COMPUTE)
++ if (engine->flags & I915_ENGINE_FIRST_RENDER_COMPUTE) {
+ general_render_compute_wa_init(engine, wal);
++ ccs_engine_wa_mode(engine, wal);
++ }
+
+ if (engine->class == COMPUTE_CLASS)
+ ccs_engine_wa_init(engine, wal);
+diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c
+index c7d7c3b7ecc63..9967148aedf15 100644
+--- a/drivers/gpu/drm/i915/i915_driver.c
++++ b/drivers/gpu/drm/i915/i915_driver.c
+@@ -799,7 +799,7 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ goto out_cleanup_modeset2;
+
+ ret = intel_pxp_init(i915);
+- if (ret != -ENODEV)
++ if (ret && ret != -ENODEV)
+ drm_dbg(&i915->drm, "pxp init failed with %d\n", ret);
+
+ ret = intel_display_driver_probe(i915);
+diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
+index 2d695818f0062..bd9d812b1afa7 100644
+--- a/drivers/gpu/drm/i915/i915_perf.c
++++ b/drivers/gpu/drm/i915/i915_perf.c
+@@ -3225,7 +3225,7 @@ u32 i915_perf_oa_timestamp_frequency(struct drm_i915_private *i915)
+ struct intel_gt *gt = to_gt(i915);
+
+ /* Wa_18013179988 */
+- if (IS_DG2(i915) || IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 71))) {
++ if (IS_DG2(i915) || IS_GFX_GT_IP_RANGE(gt, IP_VER(12, 70), IP_VER(12, 74))) {
+ intel_wakeref_t wakeref;
+ u32 reg, shift;
+
+diff --git a/drivers/gpu/drm/nouveau/nouveau_uvmm.c b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
+index 0a0a11dc9ec03..ee02cd833c5e4 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c
++++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
+@@ -812,15 +812,15 @@ op_remap(struct drm_gpuva_op_remap *r,
+ struct drm_gpuva_op_unmap *u = r->unmap;
+ struct nouveau_uvma *uvma = uvma_from_va(u->va);
+ u64 addr = uvma->va.va.addr;
+- u64 range = uvma->va.va.range;
++ u64 end = uvma->va.va.addr + uvma->va.va.range;
+
+ if (r->prev)
+ addr = r->prev->va.addr + r->prev->va.range;
+
+ if (r->next)
+- range = r->next->va.addr - addr;
++ end = r->next->va.addr;
+
+- op_unmap_range(u, addr, range);
++ op_unmap_range(u, addr, end - addr);
+ }
+
+ static int
+diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c
+index 9063ce2546422..fd8e44992184f 100644
+--- a/drivers/gpu/drm/panfrost/panfrost_gpu.c
++++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c
+@@ -441,19 +441,19 @@ void panfrost_gpu_power_off(struct panfrost_device *pfdev)
+
+ gpu_write(pfdev, SHADER_PWROFF_LO, pfdev->features.shader_present);
+ ret = readl_relaxed_poll_timeout(pfdev->iomem + SHADER_PWRTRANS_LO,
+- val, !val, 1, 1000);
++ val, !val, 1, 2000);
+ if (ret)
+ dev_err(pfdev->dev, "shader power transition timeout");
+
+ gpu_write(pfdev, TILER_PWROFF_LO, pfdev->features.tiler_present);
+ ret = readl_relaxed_poll_timeout(pfdev->iomem + TILER_PWRTRANS_LO,
+- val, !val, 1, 1000);
++ val, !val, 1, 2000);
+ if (ret)
+ dev_err(pfdev->dev, "tiler power transition timeout");
+
+ gpu_write(pfdev, L2_PWROFF_LO, pfdev->features.l2_present);
+ ret = readl_poll_timeout(pfdev->iomem + L2_PWRTRANS_LO,
+- val, !val, 0, 1000);
++ val, !val, 0, 2000);
+ if (ret)
+ dev_err(pfdev->dev, "l2 power transition timeout");
+ }
+diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
+index 48170694ac6b8..18efb3fe1c000 100644
+--- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
++++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
+@@ -17,9 +17,7 @@
+
+ static const uint32_t formats_cluster[] = {
+ DRM_FORMAT_XRGB2101010,
+- DRM_FORMAT_ARGB2101010,
+ DRM_FORMAT_XBGR2101010,
+- DRM_FORMAT_ABGR2101010,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_XBGR8888,
+diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
+index 802c807c782cc..1c9e6906b06a2 100644
+--- a/drivers/gpu/drm/xe/Makefile
++++ b/drivers/gpu/drm/xe/Makefile
+@@ -162,8 +162,8 @@ subdir-ccflags-$(CONFIG_DRM_XE_DISPLAY) += \
+ -Ddrm_i915_gem_object=xe_bo \
+ -Ddrm_i915_private=xe_device
+
+-CFLAGS_i915-display/intel_fbdev.o = $(call cc-disable-warning, override-init)
+-CFLAGS_i915-display/intel_display_device.o = $(call cc-disable-warning, override-init)
++CFLAGS_i915-display/intel_fbdev.o = -Wno-override-init
++CFLAGS_i915-display/intel_display_device.o = -Wno-override-init
+
+ # Rule to build SOC code shared with i915
+ $(obj)/i915-soc/%.o: $(srctree)/drivers/gpu/drm/i915/soc/%.c FORCE
+diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
+index 4d3b80ec906d0..eb2c44a328278 100644
+--- a/drivers/gpu/drm/xe/xe_bo.c
++++ b/drivers/gpu/drm/xe/xe_bo.c
+@@ -140,9 +140,6 @@ static void try_add_system(struct xe_device *xe, struct xe_bo *bo,
+ .mem_type = XE_PL_TT,
+ };
+ *c += 1;
+-
+- if (bo->props.preferred_mem_type == XE_BO_PROPS_INVALID)
+- bo->props.preferred_mem_type = XE_PL_TT;
+ }
+ }
+
+@@ -177,25 +174,15 @@ static void add_vram(struct xe_device *xe, struct xe_bo *bo,
+ }
+ places[*c] = place;
+ *c += 1;
+-
+- if (bo->props.preferred_mem_type == XE_BO_PROPS_INVALID)
+- bo->props.preferred_mem_type = mem_type;
+ }
+
+ static void try_add_vram(struct xe_device *xe, struct xe_bo *bo,
+ u32 bo_flags, u32 *c)
+ {
+- if (bo->props.preferred_gt == XE_GT1) {
+- if (bo_flags & XE_BO_CREATE_VRAM1_BIT)
+- add_vram(xe, bo, bo->placements, bo_flags, XE_PL_VRAM1, c);
+- if (bo_flags & XE_BO_CREATE_VRAM0_BIT)
+- add_vram(xe, bo, bo->placements, bo_flags, XE_PL_VRAM0, c);
+- } else {
+- if (bo_flags & XE_BO_CREATE_VRAM0_BIT)
+- add_vram(xe, bo, bo->placements, bo_flags, XE_PL_VRAM0, c);
+- if (bo_flags & XE_BO_CREATE_VRAM1_BIT)
+- add_vram(xe, bo, bo->placements, bo_flags, XE_PL_VRAM1, c);
+- }
++ if (bo_flags & XE_BO_CREATE_VRAM0_BIT)
++ add_vram(xe, bo, bo->placements, bo_flags, XE_PL_VRAM0, c);
++ if (bo_flags & XE_BO_CREATE_VRAM1_BIT)
++ add_vram(xe, bo, bo->placements, bo_flags, XE_PL_VRAM1, c);
+ }
+
+ static void try_add_stolen(struct xe_device *xe, struct xe_bo *bo,
+@@ -219,17 +206,8 @@ static int __xe_bo_placement_for_flags(struct xe_device *xe, struct xe_bo *bo,
+ {
+ u32 c = 0;
+
+- bo->props.preferred_mem_type = XE_BO_PROPS_INVALID;
+-
+- /* The order of placements should indicate preferred location */
+-
+- if (bo->props.preferred_mem_class == DRM_XE_MEM_REGION_CLASS_SYSMEM) {
+- try_add_system(xe, bo, bo_flags, &c);
+- try_add_vram(xe, bo, bo_flags, &c);
+- } else {
+- try_add_vram(xe, bo, bo_flags, &c);
+- try_add_system(xe, bo, bo_flags, &c);
+- }
++ try_add_vram(xe, bo, bo_flags, &c);
++ try_add_system(xe, bo, bo_flags, &c);
+ try_add_stolen(xe, bo, bo_flags, &c);
+
+ if (!c)
+@@ -1106,19 +1084,12 @@ static void xe_gem_object_close(struct drm_gem_object *obj,
+ }
+ }
+
+-static bool should_migrate_to_system(struct xe_bo *bo)
+-{
+- struct xe_device *xe = xe_bo_device(bo);
+-
+- return xe_device_in_fault_mode(xe) && bo->props.cpu_atomic;
+-}
+-
+ static vm_fault_t xe_gem_fault(struct vm_fault *vmf)
+ {
+ struct ttm_buffer_object *tbo = vmf->vma->vm_private_data;
+ struct drm_device *ddev = tbo->base.dev;
+ vm_fault_t ret;
+- int idx, r = 0;
++ int idx;
+
+ ret = ttm_bo_vm_reserve(tbo, vmf);
+ if (ret)
+@@ -1129,17 +1100,8 @@ static vm_fault_t xe_gem_fault(struct vm_fault *vmf)
+
+ trace_xe_bo_cpu_fault(bo);
+
+- if (should_migrate_to_system(bo)) {
+- r = xe_bo_migrate(bo, XE_PL_TT);
+- if (r == -EBUSY || r == -ERESTARTSYS || r == -EINTR)
+- ret = VM_FAULT_NOPAGE;
+- else if (r)
+- ret = VM_FAULT_SIGBUS;
+- }
+- if (!ret)
+- ret = ttm_bo_vm_fault_reserved(vmf,
+- vmf->vma->vm_page_prot,
+- TTM_BO_VM_NUM_PREFAULT);
++ ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot,
++ TTM_BO_VM_NUM_PREFAULT);
+ drm_dev_exit(idx);
+ } else {
+ ret = ttm_bo_vm_dummy_page(vmf, vmf->vma->vm_page_prot);
+@@ -1253,9 +1215,6 @@ struct xe_bo *___xe_bo_create_locked(struct xe_device *xe, struct xe_bo *bo,
+ bo->flags = flags;
+ bo->cpu_caching = cpu_caching;
+ bo->ttm.base.funcs = &xe_gem_object_funcs;
+- bo->props.preferred_mem_class = XE_BO_PROPS_INVALID;
+- bo->props.preferred_gt = XE_BO_PROPS_INVALID;
+- bo->props.preferred_mem_type = XE_BO_PROPS_INVALID;
+ bo->ttm.priority = XE_BO_PRIORITY_NORMAL;
+ INIT_LIST_HEAD(&bo->pinned_link);
+ #ifdef CONFIG_PROC_FS
+diff --git a/drivers/gpu/drm/xe/xe_bo_types.h b/drivers/gpu/drm/xe/xe_bo_types.h
+index 64c2249a4e407..81dca15315d5c 100644
+--- a/drivers/gpu/drm/xe/xe_bo_types.h
++++ b/drivers/gpu/drm/xe/xe_bo_types.h
+@@ -56,25 +56,6 @@ struct xe_bo {
+ */
+ struct list_head client_link;
+ #endif
+- /** @props: BO user controlled properties */
+- struct {
+- /** @preferred_mem: preferred memory class for this BO */
+- s16 preferred_mem_class;
+- /** @prefered_gt: preferred GT for this BO */
+- s16 preferred_gt;
+- /** @preferred_mem_type: preferred memory type */
+- s32 preferred_mem_type;
+- /**
+- * @cpu_atomic: the CPU expects to do atomics operations to
+- * this BO
+- */
+- bool cpu_atomic;
+- /**
+- * @device_atomic: the device expects to do atomics operations
+- * to this BO
+- */
+- bool device_atomic;
+- } props;
+ /** @freed: List node for delayed put. */
+ struct llist_node freed;
+ /** @created: Whether the bo has passed initial creation */
+diff --git a/drivers/gpu/drm/xe/xe_device.h b/drivers/gpu/drm/xe/xe_device.h
+index 08d8b72c77319..bf8efb44edf60 100644
+--- a/drivers/gpu/drm/xe/xe_device.h
++++ b/drivers/gpu/drm/xe/xe_device.h
+@@ -58,7 +58,7 @@ static inline struct xe_tile *xe_device_get_root_tile(struct xe_device *xe)
+
+ static inline struct xe_gt *xe_tile_get_gt(struct xe_tile *tile, u8 gt_id)
+ {
+- if (drm_WARN_ON(&tile_to_xe(tile)->drm, gt_id > XE_MAX_GT_PER_TILE))
++ if (drm_WARN_ON(&tile_to_xe(tile)->drm, gt_id >= XE_MAX_GT_PER_TILE))
+ gt_id = 0;
+
+ return gt_id ? tile->media_gt : tile->primary_gt;
+@@ -79,7 +79,7 @@ static inline struct xe_gt *xe_device_get_gt(struct xe_device *xe, u8 gt_id)
+ if (MEDIA_VER(xe) >= 13) {
+ gt = xe_tile_get_gt(root_tile, gt_id);
+ } else {
+- if (drm_WARN_ON(&xe->drm, gt_id > XE_MAX_TILES_PER_DEVICE))
++ if (drm_WARN_ON(&xe->drm, gt_id >= XE_MAX_TILES_PER_DEVICE))
+ gt_id = 0;
+
+ gt = xe->tiles[gt_id].primary_gt;
+diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
+index 222209b0d6904..2cd4ad2fcffa1 100644
+--- a/drivers/gpu/drm/xe/xe_exec.c
++++ b/drivers/gpu/drm/xe/xe_exec.c
+@@ -113,7 +113,6 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+ struct drm_exec *exec = &vm_exec.exec;
+ u32 i, num_syncs = 0, num_ufence = 0;
+ struct xe_sched_job *job;
+- struct dma_fence *rebind_fence;
+ struct xe_vm *vm;
+ bool write_locked, skip_retry = false;
+ ktime_t end = 0;
+@@ -256,35 +255,11 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+ * Rebind any invalidated userptr or evicted BOs in the VM, non-compute
+ * VM mode only.
+ */
+- rebind_fence = xe_vm_rebind(vm, false);
+- if (IS_ERR(rebind_fence)) {
+- err = PTR_ERR(rebind_fence);
++ err = xe_vm_rebind(vm, false);
++ if (err)
+ goto err_put_job;
+- }
+-
+- /*
+- * We store the rebind_fence in the VM so subsequent execs don't get
+- * scheduled before the rebinds of userptrs / evicted BOs is complete.
+- */
+- if (rebind_fence) {
+- dma_fence_put(vm->rebind_fence);
+- vm->rebind_fence = rebind_fence;
+- }
+- if (vm->rebind_fence) {
+- if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
+- &vm->rebind_fence->flags)) {
+- dma_fence_put(vm->rebind_fence);
+- vm->rebind_fence = NULL;
+- } else {
+- dma_fence_get(vm->rebind_fence);
+- err = drm_sched_job_add_dependency(&job->drm,
+- vm->rebind_fence);
+- if (err)
+- goto err_put_job;
+- }
+- }
+
+- /* Wait behind munmap style rebinds */
++ /* Wait behind rebinds */
+ if (!xe_vm_in_lr_mode(vm)) {
+ err = drm_sched_job_add_resv_dependencies(&job->drm,
+ xe_vm_resv(vm),
+diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
+index 49223026c89fd..5093c56d60ab6 100644
+--- a/drivers/gpu/drm/xe/xe_exec_queue.c
++++ b/drivers/gpu/drm/xe/xe_exec_queue.c
+@@ -66,6 +66,8 @@ static struct xe_exec_queue *__xe_exec_queue_create(struct xe_device *xe,
+ q->sched_props.timeslice_us = hwe->eclass->sched_props.timeslice_us;
+ q->sched_props.preempt_timeout_us =
+ hwe->eclass->sched_props.preempt_timeout_us;
++ q->sched_props.job_timeout_ms =
++ hwe->eclass->sched_props.job_timeout_ms;
+ if (q->flags & EXEC_QUEUE_FLAG_KERNEL &&
+ q->flags & EXEC_QUEUE_FLAG_HIGH_PRIORITY)
+ q->sched_props.priority = XE_EXEC_QUEUE_PRIORITY_KERNEL;
+@@ -403,7 +405,7 @@ find_hw_engine(struct xe_device *xe,
+ {
+ u32 idx;
+
+- if (eci.engine_class > ARRAY_SIZE(user_to_xe_engine_class))
++ if (eci.engine_class >= ARRAY_SIZE(user_to_xe_engine_class))
+ return NULL;
+
+ if (eci.gt_id >= xe->info.gt_count)
+diff --git a/drivers/gpu/drm/xe/xe_exec_queue_types.h b/drivers/gpu/drm/xe/xe_exec_queue_types.h
+index 36f4901d8d7ee..22e1dffd0649f 100644
+--- a/drivers/gpu/drm/xe/xe_exec_queue_types.h
++++ b/drivers/gpu/drm/xe/xe_exec_queue_types.h
+@@ -132,6 +132,8 @@ struct xe_exec_queue {
+ u32 timeslice_us;
+ /** @preempt_timeout_us: preemption timeout in micro-seconds */
+ u32 preempt_timeout_us;
++ /** @job_timeout_ms: job timeout in milliseconds */
++ u32 job_timeout_ms;
+ /** @priority: priority of this exec queue */
+ enum xe_exec_queue_priority priority;
+ } sched_props;
+@@ -157,6 +159,11 @@ struct xe_exec_queue {
+ const struct xe_ring_ops *ring_ops;
+ /** @entity: DRM sched entity for this exec queue (1 to 1 relationship) */
+ struct drm_sched_entity *entity;
++ /**
++ * @tlb_flush_seqno: The seqno of the last rebind tlb flush performed
++ * Protected by @vm's resv. Unused if @vm == NULL.
++ */
++ u64 tlb_flush_seqno;
+ /** @lrc: logical ring context for this exec queue */
+ struct xe_lrc lrc[];
+ };
+diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
+index f22ae717b0b2d..bd1079aa88498 100644
+--- a/drivers/gpu/drm/xe/xe_guc_submit.c
++++ b/drivers/gpu/drm/xe/xe_guc_submit.c
+@@ -1216,7 +1216,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q)
+ init_waitqueue_head(&ge->suspend_wait);
+
+ timeout = (q->vm && xe_vm_in_lr_mode(q->vm)) ? MAX_SCHEDULE_TIMEOUT :
+- q->hwe->eclass->sched_props.job_timeout_ms;
++ msecs_to_jiffies(q->sched_props.job_timeout_ms);
+ err = xe_sched_init(&ge->sched, &drm_sched_ops, &xe_sched_ops,
+ get_submit_wq(guc),
+ q->lrc[0].ring.size / MAX_JOB_SIZE_BYTES, 64,
+diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
+index 6653c045f3c92..c1a833b1cb3d3 100644
+--- a/drivers/gpu/drm/xe/xe_pt.c
++++ b/drivers/gpu/drm/xe/xe_pt.c
+@@ -1255,11 +1255,13 @@ __xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue
+ * non-faulting LR, in particular on user-space batch buffer chaining,
+ * it needs to be done here.
+ */
+- if ((rebind && !xe_vm_in_lr_mode(vm) && !vm->batch_invalidate_tlb) ||
+- (!rebind && xe_vm_has_scratch(vm) && xe_vm_in_preempt_fence_mode(vm))) {
++ if ((!rebind && xe_vm_has_scratch(vm) && xe_vm_in_preempt_fence_mode(vm))) {
+ ifence = kzalloc(sizeof(*ifence), GFP_KERNEL);
+ if (!ifence)
+ return ERR_PTR(-ENOMEM);
++ } else if (rebind && !xe_vm_in_lr_mode(vm)) {
++ /* We bump also if batch_invalidate_tlb is true */
++ vm->tlb_flush_seqno++;
+ }
+
+ rfence = kzalloc(sizeof(*rfence), GFP_KERNEL);
+@@ -1298,7 +1300,7 @@ __xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue
+ }
+
+ /* add shared fence now for pagetable delayed destroy */
+- dma_resv_add_fence(xe_vm_resv(vm), fence, !rebind &&
++ dma_resv_add_fence(xe_vm_resv(vm), fence, rebind ||
+ last_munmap_rebind ?
+ DMA_RESV_USAGE_KERNEL :
+ DMA_RESV_USAGE_BOOKKEEP);
+diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c
+index 1e4c06eacd984..68495f8858794 100644
+--- a/drivers/gpu/drm/xe/xe_ring_ops.c
++++ b/drivers/gpu/drm/xe/xe_ring_ops.c
+@@ -227,10 +227,9 @@ static void __emit_job_gen12_simple(struct xe_sched_job *job, struct xe_lrc *lrc
+ {
+ u32 dw[MAX_JOB_SIZE_DW], i = 0;
+ u32 ppgtt_flag = get_ppgtt_flag(job);
+- struct xe_vm *vm = job->q->vm;
+ struct xe_gt *gt = job->q->gt;
+
+- if (vm && vm->batch_invalidate_tlb) {
++ if (job->ring_ops_flush_tlb) {
+ dw[i++] = preparser_disable(true);
+ i = emit_flush_imm_ggtt(xe_lrc_start_seqno_ggtt_addr(lrc),
+ seqno, true, dw, i);
+@@ -278,7 +277,6 @@ static void __emit_job_gen12_video(struct xe_sched_job *job, struct xe_lrc *lrc,
+ struct xe_gt *gt = job->q->gt;
+ struct xe_device *xe = gt_to_xe(gt);
+ bool decode = job->q->class == XE_ENGINE_CLASS_VIDEO_DECODE;
+- struct xe_vm *vm = job->q->vm;
+
+ dw[i++] = preparser_disable(true);
+
+@@ -290,13 +288,13 @@ static void __emit_job_gen12_video(struct xe_sched_job *job, struct xe_lrc *lrc,
+ i = emit_aux_table_inv(gt, VE0_AUX_INV, dw, i);
+ }
+
+- if (vm && vm->batch_invalidate_tlb)
++ if (job->ring_ops_flush_tlb)
+ i = emit_flush_imm_ggtt(xe_lrc_start_seqno_ggtt_addr(lrc),
+ seqno, true, dw, i);
+
+ dw[i++] = preparser_disable(false);
+
+- if (!vm || !vm->batch_invalidate_tlb)
++ if (!job->ring_ops_flush_tlb)
+ i = emit_store_imm_ggtt(xe_lrc_start_seqno_ggtt_addr(lrc),
+ seqno, dw, i);
+
+@@ -325,7 +323,6 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job,
+ struct xe_gt *gt = job->q->gt;
+ struct xe_device *xe = gt_to_xe(gt);
+ bool lacks_render = !(gt->info.engine_mask & XE_HW_ENGINE_RCS_MASK);
+- struct xe_vm *vm = job->q->vm;
+ u32 mask_flags = 0;
+
+ dw[i++] = preparser_disable(true);
+@@ -335,7 +332,7 @@ static void __emit_job_gen12_render_compute(struct xe_sched_job *job,
+ mask_flags = PIPE_CONTROL_3D_ENGINE_FLAGS;
+
+ /* See __xe_pt_bind_vma() for a discussion on TLB invalidations. */
+- i = emit_pipe_invalidate(mask_flags, vm && vm->batch_invalidate_tlb, dw, i);
++ i = emit_pipe_invalidate(mask_flags, job->ring_ops_flush_tlb, dw, i);
+
+ /* hsdes: 1809175790 */
+ if (has_aux_ccs(xe))
+diff --git a/drivers/gpu/drm/xe/xe_sched_job.c b/drivers/gpu/drm/xe/xe_sched_job.c
+index 4e2ccad0e52fa..d07b9ee0eaa55 100644
+--- a/drivers/gpu/drm/xe/xe_sched_job.c
++++ b/drivers/gpu/drm/xe/xe_sched_job.c
+@@ -250,6 +250,16 @@ bool xe_sched_job_completed(struct xe_sched_job *job)
+
+ void xe_sched_job_arm(struct xe_sched_job *job)
+ {
++ struct xe_exec_queue *q = job->q;
++ struct xe_vm *vm = q->vm;
++
++ if (vm && !xe_sched_job_is_migration(q) && !xe_vm_in_lr_mode(vm) &&
++ (vm->batch_invalidate_tlb || vm->tlb_flush_seqno != q->tlb_flush_seqno)) {
++ xe_vm_assert_held(vm);
++ q->tlb_flush_seqno = vm->tlb_flush_seqno;
++ job->ring_ops_flush_tlb = true;
++ }
++
+ drm_sched_job_arm(&job->drm);
+ }
+
+diff --git a/drivers/gpu/drm/xe/xe_sched_job_types.h b/drivers/gpu/drm/xe/xe_sched_job_types.h
+index 71213ba9735bc..46ead6345956b 100644
+--- a/drivers/gpu/drm/xe/xe_sched_job_types.h
++++ b/drivers/gpu/drm/xe/xe_sched_job_types.h
+@@ -39,6 +39,8 @@ struct xe_sched_job {
+ } user_fence;
+ /** @migrate_flush_flags: Additional flush flags for migration jobs */
+ u32 migrate_flush_flags;
++ /** @ring_ops_flush_tlb: The ring ops need to flush TLB before payload. */
++ bool ring_ops_flush_tlb;
+ /** @batch_addr: batch buffer address of job */
+ u64 batch_addr[];
+ };
+diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
+index a2397f232efc6..a2024247bec1a 100644
+--- a/drivers/gpu/drm/xe/xe_vm.c
++++ b/drivers/gpu/drm/xe/xe_vm.c
+@@ -520,7 +520,6 @@ static void preempt_rebind_work_func(struct work_struct *w)
+ {
+ struct xe_vm *vm = container_of(w, struct xe_vm, preempt.rebind_work);
+ struct drm_exec exec;
+- struct dma_fence *rebind_fence;
+ unsigned int fence_count = 0;
+ LIST_HEAD(preempt_fences);
+ ktime_t end = 0;
+@@ -566,18 +565,11 @@ static void preempt_rebind_work_func(struct work_struct *w)
+ if (err)
+ goto out_unlock;
+
+- rebind_fence = xe_vm_rebind(vm, true);
+- if (IS_ERR(rebind_fence)) {
+- err = PTR_ERR(rebind_fence);
++ err = xe_vm_rebind(vm, true);
++ if (err)
+ goto out_unlock;
+- }
+-
+- if (rebind_fence) {
+- dma_fence_wait(rebind_fence, false);
+- dma_fence_put(rebind_fence);
+- }
+
+- /* Wait on munmap style VM unbinds */
++ /* Wait on rebinds and munmap style VM unbinds */
+ wait = dma_resv_wait_timeout(xe_vm_resv(vm),
+ DMA_RESV_USAGE_KERNEL,
+ false, MAX_SCHEDULE_TIMEOUT);
+@@ -771,14 +763,14 @@ xe_vm_bind_vma(struct xe_vma *vma, struct xe_exec_queue *q,
+ struct xe_sync_entry *syncs, u32 num_syncs,
+ bool first_op, bool last_op);
+
+-struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
++int xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
+ {
+- struct dma_fence *fence = NULL;
++ struct dma_fence *fence;
+ struct xe_vma *vma, *next;
+
+ lockdep_assert_held(&vm->lock);
+ if (xe_vm_in_lr_mode(vm) && !rebind_worker)
+- return NULL;
++ return 0;
+
+ xe_vm_assert_held(vm);
+ list_for_each_entry_safe(vma, next, &vm->rebind_list,
+@@ -786,17 +778,17 @@ struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker)
+ xe_assert(vm->xe, vma->tile_present);
+
+ list_del_init(&vma->combined_links.rebind);
+- dma_fence_put(fence);
+ if (rebind_worker)
+ trace_xe_vma_rebind_worker(vma);
+ else
+ trace_xe_vma_rebind_exec(vma);
+ fence = xe_vm_bind_vma(vma, NULL, NULL, 0, false, false);
+ if (IS_ERR(fence))
+- return fence;
++ return PTR_ERR(fence);
++ dma_fence_put(fence);
+ }
+
+- return fence;
++ return 0;
+ }
+
+ static void xe_vma_free(struct xe_vma *vma)
+@@ -1575,7 +1567,6 @@ static void vm_destroy_work_func(struct work_struct *w)
+ XE_WARN_ON(vm->pt_root[id]);
+
+ trace_xe_vm_free(vm);
+- dma_fence_put(vm->rebind_fence);
+ kfree(vm);
+ }
+
+diff --git a/drivers/gpu/drm/xe/xe_vm.h b/drivers/gpu/drm/xe/xe_vm.h
+index 9654a0612fc25..40188a28c5471 100644
+--- a/drivers/gpu/drm/xe/xe_vm.h
++++ b/drivers/gpu/drm/xe/xe_vm.h
+@@ -207,7 +207,7 @@ int __xe_vm_userptr_needs_repin(struct xe_vm *vm);
+
+ int xe_vm_userptr_check_repin(struct xe_vm *vm);
+
+-struct dma_fence *xe_vm_rebind(struct xe_vm *vm, bool rebind_worker);
++int xe_vm_rebind(struct xe_vm *vm, bool rebind_worker);
+
+ int xe_vm_invalidate_vma(struct xe_vma *vma);
+
+diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
+index 5b96549479504..4027da3a10b3a 100644
+--- a/drivers/gpu/drm/xe/xe_vm_types.h
++++ b/drivers/gpu/drm/xe/xe_vm_types.h
+@@ -171,9 +171,6 @@ struct xe_vm {
+ */
+ struct list_head rebind_list;
+
+- /** @rebind_fence: rebind fence from execbuf */
+- struct dma_fence *rebind_fence;
+-
+ /**
+ * @destroy_work: worker to destroy VM, needed as a dma_fence signaling
+ * from an irq context can be last put and the destroy needs to be able
+@@ -282,6 +279,11 @@ struct xe_vm {
+ bool capture_once;
+ } error_capture;
+
++ /**
++ * @tlb_flush_seqno: Required TLB flush seqno for the next exec.
++ * protected by the vm resv.
++ */
++ u64 tlb_flush_seqno;
+ /** @batch_invalidate_tlb: Always invalidate TLB before batch start */
+ bool batch_invalidate_tlb;
+ /** @xef: XE file handle for tracking this VM's drm client */
+diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
+index cd1210026ac53..ad33161f2374b 100644
+--- a/drivers/iommu/iommu.c
++++ b/drivers/iommu/iommu.c
+@@ -3547,6 +3547,7 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
+ {
+ /* Caller must be a probed driver on dev */
+ struct iommu_group *group = dev->iommu_group;
++ struct group_device *device;
+ void *curr;
+ int ret;
+
+@@ -3556,10 +3557,18 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
+ if (!group)
+ return -ENODEV;
+
+- if (!dev_has_iommu(dev) || dev_iommu_ops(dev) != domain->owner)
++ if (!dev_has_iommu(dev) || dev_iommu_ops(dev) != domain->owner ||
++ pasid == IOMMU_NO_PASID)
+ return -EINVAL;
+
+ mutex_lock(&group->mutex);
++ for_each_group_device(group, device) {
++ if (pasid >= device->dev->iommu->max_pasids) {
++ ret = -EINVAL;
++ goto out_unlock;
++ }
++ }
++
+ curr = xa_cmpxchg(&group->pasid_array, pasid, NULL, domain, GFP_KERNEL);
+ if (curr) {
+ ret = xa_err(curr) ? : -EBUSY;
+diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
+index 47cf1ab34941f..3b4218a2e750d 100644
+--- a/drivers/md/dm-integrity.c
++++ b/drivers/md/dm-integrity.c
+@@ -4221,7 +4221,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned int argc, char **argv
+ } else if (sscanf(opt_string, "sectors_per_bit:%llu%c", &llval, &dummy) == 1) {
+ log2_sectors_per_bitmap_bit = !llval ? 0 : __ilog2_u64(llval);
+ } else if (sscanf(opt_string, "bitmap_flush_interval:%u%c", &val, &dummy) == 1) {
+- if (val >= (uint64_t)UINT_MAX * 1000 / HZ) {
++ if ((uint64_t)val >= (uint64_t)UINT_MAX * 1000 / HZ) {
+ r = -EINVAL;
+ ti->error = "Invalid bitmap_flush_interval argument";
+ goto bad;
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
+index 614cabb5c1b03..7de8a9c9e4576 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -5500,8 +5500,12 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
+ .family = MV88E6XXX_FAMILY_6250,
+ .name = "Marvell 88E6020",
+ .num_databases = 64,
+- .num_ports = 4,
++ /* Ports 2-4 are not routed to pins
++ * => usable ports 0, 1, 5, 6
++ */
++ .num_ports = 7,
+ .num_internal_phys = 2,
++ .invalid_port_mask = BIT(2) | BIT(3) | BIT(4),
+ .max_vid = 4095,
+ .port_base_addr = 0x8,
+ .phy_base_addr = 0x0,
+diff --git a/drivers/net/dsa/sja1105/sja1105_mdio.c b/drivers/net/dsa/sja1105/sja1105_mdio.c
+index 833e55e4b9612..52ddb4ef259e9 100644
+--- a/drivers/net/dsa/sja1105/sja1105_mdio.c
++++ b/drivers/net/dsa/sja1105/sja1105_mdio.c
+@@ -94,7 +94,7 @@ int sja1110_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg)
+ return tmp & 0xffff;
+ }
+
+-int sja1110_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int reg, int mmd,
++int sja1110_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd, int reg,
+ u16 val)
+ {
+ struct sja1105_mdio_private *mdio_priv = bus->priv;
+diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
+index 6ad1366270f79..78901e2e73032 100644
+--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
+@@ -391,7 +391,9 @@ static void umac_reset(struct bcmasp_intf *intf)
+ umac_wl(intf, 0x0, UMC_CMD);
+ umac_wl(intf, UMC_CMD_SW_RESET, UMC_CMD);
+ usleep_range(10, 100);
+- umac_wl(intf, 0x0, UMC_CMD);
++ /* We hold the umac in reset and bring it out of
++ * reset when phy link is up.
++ */
+ }
+
+ static void umac_set_hw_addr(struct bcmasp_intf *intf,
+@@ -411,6 +413,8 @@ static void umac_enable_set(struct bcmasp_intf *intf, u32 mask,
+ u32 reg;
+
+ reg = umac_rl(intf, UMC_CMD);
++ if (reg & UMC_CMD_SW_RESET)
++ return;
+ if (enable)
+ reg |= mask;
+ else
+@@ -429,7 +433,6 @@ static void umac_init(struct bcmasp_intf *intf)
+ umac_wl(intf, 0x800, UMC_FRM_LEN);
+ umac_wl(intf, 0xffff, UMC_PAUSE_CNTRL);
+ umac_wl(intf, 0x800, UMC_RX_MAX_PKT_SZ);
+- umac_enable_set(intf, UMC_CMD_PROMISC, 1);
+ }
+
+ static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
+@@ -656,6 +659,12 @@ static void bcmasp_adj_link(struct net_device *dev)
+ UMC_CMD_HD_EN | UMC_CMD_RX_PAUSE_IGNORE |
+ UMC_CMD_TX_PAUSE_IGNORE);
+ reg |= cmd_bits;
++ if (reg & UMC_CMD_SW_RESET) {
++ reg &= ~UMC_CMD_SW_RESET;
++ umac_wl(intf, reg, UMC_CMD);
++ udelay(2);
++ reg |= UMC_CMD_TX_EN | UMC_CMD_RX_EN | UMC_CMD_PROMISC;
++ }
+ umac_wl(intf, reg, UMC_CMD);
+
+ intf->eee.eee_active = phy_init_eee(phydev, 0) >= 0;
+@@ -1063,9 +1072,6 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect)
+
+ umac_init(intf);
+
+- /* Disable the UniMAC RX/TX */
+- umac_enable_set(intf, (UMC_CMD_RX_EN | UMC_CMD_TX_EN), 0);
+-
+ umac_set_hw_addr(intf, dev->dev_addr);
+
+ intf->old_duplex = -1;
+@@ -1085,9 +1091,6 @@ static int bcmasp_netif_init(struct net_device *dev, bool phy_connect)
+
+ bcmasp_enable_rx(intf, 1);
+
+- /* Turn on UniMAC TX/RX */
+- umac_enable_set(intf, (UMC_CMD_RX_EN | UMC_CMD_TX_EN), 1);
+-
+ intf->crc_fwd = !!(umac_rl(intf, UMC_CMD) & UMC_CMD_CRC_FWD);
+
+ bcmasp_netif_start(dev);
+@@ -1324,7 +1327,14 @@ static void bcmasp_suspend_to_wol(struct bcmasp_intf *intf)
+ if (intf->wolopts & WAKE_FILTER)
+ bcmasp_netfilt_suspend(intf);
+
+- /* UniMAC receive needs to be turned on */
++ /* Bring UniMAC out of reset if needed and enable RX */
++ reg = umac_rl(intf, UMC_CMD);
++ if (reg & UMC_CMD_SW_RESET)
++ reg &= ~UMC_CMD_SW_RESET;
++
++ reg |= UMC_CMD_RX_EN | UMC_CMD_PROMISC;
++ umac_wl(intf, reg, UMC_CMD);
++
+ umac_enable_set(intf, UMC_CMD_RX_EN, 1);
+
+ if (intf->parent->wol_irq > 0) {
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index 432523b2c7892..8decb1b072c5e 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -2406,8 +2406,6 @@ static int fec_enet_mii_probe(struct net_device *ndev)
+ fep->link = 0;
+ fep->full_duplex = 0;
+
+- phy_dev->mac_managed_pm = true;
+-
+ phy_attached_info(phy_dev);
+
+ return 0;
+@@ -2419,10 +2417,12 @@ static int fec_enet_mii_init(struct platform_device *pdev)
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct fec_enet_private *fep = netdev_priv(ndev);
+ bool suppress_preamble = false;
++ struct phy_device *phydev;
+ struct device_node *node;
+ int err = -ENXIO;
+ u32 mii_speed, holdtime;
+ u32 bus_freq;
++ int addr;
+
+ /*
+ * The i.MX28 dual fec interfaces are not equal.
+@@ -2536,6 +2536,13 @@ static int fec_enet_mii_init(struct platform_device *pdev)
+ goto err_out_free_mdiobus;
+ of_node_put(node);
+
++ /* find all the PHY devices on the bus and set mac_managed_pm to true */
++ for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
++ phydev = mdiobus_get_phy(fep->mii_bus, addr);
++ if (phydev)
++ phydev->mac_managed_pm = true;
++ }
++
+ mii_cnt++;
+
+ /* save fec0 mii_bus */
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.c b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.c
+index f3c9395d8351c..618f66d9586b3 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_tqp_stats.c
+@@ -85,7 +85,7 @@ int hclge_comm_tqps_update_stats(struct hnae3_handle *handle,
+ hclge_comm_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_TX_STATS,
+ true);
+
+- desc.data[0] = cpu_to_le32(tqp->index & 0x1ff);
++ desc.data[0] = cpu_to_le32(tqp->index);
+ ret = hclge_comm_cmd_send(hw, &desc, 1);
+ if (ret) {
+ dev_err(&hw->cmq.csq.pdev->dev,
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+index 999a0ee162a64..941cb529d671f 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+@@ -78,6 +78,9 @@ static const struct hns3_stats hns3_rxq_stats[] = {
+ #define HNS3_NIC_LB_TEST_NO_MEM_ERR 1
+ #define HNS3_NIC_LB_TEST_TX_CNT_ERR 2
+ #define HNS3_NIC_LB_TEST_RX_CNT_ERR 3
++#define HNS3_NIC_LB_TEST_UNEXECUTED 4
++
++static int hns3_get_sset_count(struct net_device *netdev, int stringset);
+
+ static int hns3_lp_setup(struct net_device *ndev, enum hnae3_loop loop, bool en)
+ {
+@@ -418,18 +421,26 @@ static void hns3_do_external_lb(struct net_device *ndev,
+ static void hns3_self_test(struct net_device *ndev,
+ struct ethtool_test *eth_test, u64 *data)
+ {
++ int cnt = hns3_get_sset_count(ndev, ETH_SS_TEST);
+ struct hns3_nic_priv *priv = netdev_priv(ndev);
+ struct hnae3_handle *h = priv->ae_handle;
+ int st_param[HNAE3_LOOP_NONE][2];
+ bool if_running = netif_running(ndev);
++ int i;
++
++ /* initialize the loopback test result, avoid marking an unexcuted
++ * loopback test as PASS.
++ */
++ for (i = 0; i < cnt; i++)
++ data[i] = HNS3_NIC_LB_TEST_UNEXECUTED;
+
+ if (hns3_nic_resetting(ndev)) {
+ netdev_err(ndev, "dev resetting!");
+- return;
++ goto failure;
+ }
+
+ if (!(eth_test->flags & ETH_TEST_FL_OFFLINE))
+- return;
++ goto failure;
+
+ if (netif_msg_ifdown(h))
+ netdev_info(ndev, "self test start\n");
+@@ -451,6 +462,10 @@ static void hns3_self_test(struct net_device *ndev,
+
+ if (netif_msg_ifdown(h))
+ netdev_info(ndev, "self test end\n");
++ return;
++
++failure:
++ eth_test->flags |= ETH_TEST_FL_FAILED;
+ }
+
+ static void hns3_update_limit_promisc_mode(struct net_device *netdev,
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index 609d3799d7738..a3b7723a97bb1 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -11613,6 +11613,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
+ if (ret)
+ goto err_pci_uninit;
+
++ devl_lock(hdev->devlink);
++
+ /* Firmware command queue initialize */
+ ret = hclge_comm_cmd_queue_init(hdev->pdev, &hdev->hw.hw);
+ if (ret)
+@@ -11792,6 +11794,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
+
+ hclge_task_schedule(hdev, round_jiffies_relative(HZ));
+
++ devl_unlock(hdev->devlink);
+ return 0;
+
+ err_mdiobus_unreg:
+@@ -11804,6 +11807,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
+ err_cmd_uninit:
+ hclge_comm_cmd_uninit(hdev->ae_dev, &hdev->hw.hw);
+ err_devlink_uninit:
++ devl_unlock(hdev->devlink);
+ hclge_devlink_uninit(hdev);
+ err_pci_uninit:
+ pcim_iounmap(pdev, hdev->hw.hw.io_base);
+diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h
+index 1fef6bb5a5fbc..4b6e7536170ab 100644
+--- a/drivers/net/ethernet/intel/e1000e/hw.h
++++ b/drivers/net/ethernet/intel/e1000e/hw.h
+@@ -628,6 +628,7 @@ struct e1000_phy_info {
+ u32 id;
+ u32 reset_delay_us; /* in usec */
+ u32 revision;
++ u32 retry_count;
+
+ enum e1000_media_type media_type;
+
+@@ -644,6 +645,7 @@ struct e1000_phy_info {
+ bool polarity_correction;
+ bool speed_downgraded;
+ bool autoneg_wait_to_complete;
++ bool retry_enabled;
+ };
+
+ struct e1000_nvm_info {
+diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c
+index 19e450a5bd314..f9e94be36e97f 100644
+--- a/drivers/net/ethernet/intel/e1000e/ich8lan.c
++++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c
+@@ -222,11 +222,18 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
+ if (hw->mac.type >= e1000_pch_lpt) {
+ /* Only unforce SMBus if ME is not active */
+ if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
++ /* Switching PHY interface always returns MDI error
++ * so disable retry mechanism to avoid wasting time
++ */
++ e1000e_disable_phy_retry(hw);
++
+ /* Unforce SMBus mode in PHY */
+ e1e_rphy_locked(hw, CV_SMB_CTRL, &phy_reg);
+ phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
+ e1e_wphy_locked(hw, CV_SMB_CTRL, phy_reg);
+
++ e1000e_enable_phy_retry(hw);
++
+ /* Unforce SMBus mode in MAC */
+ mac_reg = er32(CTRL_EXT);
+ mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
+@@ -310,6 +317,11 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
+ goto out;
+ }
+
++ /* There is no guarantee that the PHY is accessible at this time
++ * so disable retry mechanism to avoid wasting time
++ */
++ e1000e_disable_phy_retry(hw);
++
+ /* The MAC-PHY interconnect may be in SMBus mode. If the PHY is
+ * inaccessible and resetting the PHY is not blocked, toggle the
+ * LANPHYPC Value bit to force the interconnect to PCIe mode.
+@@ -380,6 +392,8 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
+ break;
+ }
+
++ e1000e_enable_phy_retry(hw);
++
+ hw->phy.ops.release(hw);
+ if (!ret_val) {
+
+@@ -449,6 +463,11 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
+
+ phy->id = e1000_phy_unknown;
+
++ if (hw->mac.type == e1000_pch_mtp) {
++ phy->retry_count = 2;
++ e1000e_enable_phy_retry(hw);
++ }
++
+ ret_val = e1000_init_phy_workarounds_pchlan(hw);
+ if (ret_val)
+ return ret_val;
+@@ -1146,18 +1165,6 @@ s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
+ if (ret_val)
+ goto out;
+
+- /* Force SMBus mode in PHY */
+- ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
+- if (ret_val)
+- goto release;
+- phy_reg |= CV_SMB_CTRL_FORCE_SMBUS;
+- e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg);
+-
+- /* Force SMBus mode in MAC */
+- mac_reg = er32(CTRL_EXT);
+- mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
+- ew32(CTRL_EXT, mac_reg);
+-
+ /* Si workaround for ULP entry flow on i127/rev6 h/w. Enable
+ * LPLU and disable Gig speed when entering ULP
+ */
+@@ -1313,6 +1320,11 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
+ /* Toggle LANPHYPC Value bit */
+ e1000_toggle_lanphypc_pch_lpt(hw);
+
++ /* Switching PHY interface always returns MDI error
++ * so disable retry mechanism to avoid wasting time
++ */
++ e1000e_disable_phy_retry(hw);
++
+ /* Unforce SMBus mode in PHY */
+ ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
+ if (ret_val) {
+@@ -1333,6 +1345,8 @@ static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
+ phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
+ e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg);
+
++ e1000e_enable_phy_retry(hw);
++
+ /* Unforce SMBus mode in MAC */
+ mac_reg = er32(CTRL_EXT);
+ mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
+diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
+index af5d9d97a0d6c..3692fce201959 100644
+--- a/drivers/net/ethernet/intel/e1000e/netdev.c
++++ b/drivers/net/ethernet/intel/e1000e/netdev.c
+@@ -6623,6 +6623,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
+ struct e1000_hw *hw = &adapter->hw;
+ u32 ctrl, ctrl_ext, rctl, status, wufc;
+ int retval = 0;
++ u16 smb_ctrl;
+
+ /* Runtime suspend should only enable wakeup for link changes */
+ if (runtime)
+@@ -6688,14 +6689,31 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
+ if (adapter->hw.phy.type == e1000_phy_igp_3) {
+ e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
+ } else if (hw->mac.type >= e1000_pch_lpt) {
+- if (wufc && !(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC)))
++ if (wufc && !(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC))) {
+ /* ULP does not support wake from unicast, multicast
+ * or broadcast.
+ */
+ retval = e1000_enable_ulp_lpt_lp(hw, !runtime);
++ if (retval)
++ return retval;
++ }
++
++ /* Force SMBUS to allow WOL */
++ /* Switching PHY interface always returns MDI error
++ * so disable retry mechanism to avoid wasting time
++ */
++ e1000e_disable_phy_retry(hw);
++
++ e1e_rphy(hw, CV_SMB_CTRL, &smb_ctrl);
++ smb_ctrl |= CV_SMB_CTRL_FORCE_SMBUS;
++ e1e_wphy(hw, CV_SMB_CTRL, smb_ctrl);
+
+- if (retval)
+- return retval;
++ e1000e_enable_phy_retry(hw);
++
++ /* Force SMBus mode in MAC */
++ ctrl_ext = er32(CTRL_EXT);
++ ctrl_ext |= E1000_CTRL_EXT_FORCE_SMBUS;
++ ew32(CTRL_EXT, ctrl_ext);
+ }
+
+ /* Ensure that the appropriate bits are set in LPI_CTRL
+diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c
+index 5e329156d1bae..93544f1cc2a51 100644
+--- a/drivers/net/ethernet/intel/e1000e/phy.c
++++ b/drivers/net/ethernet/intel/e1000e/phy.c
+@@ -107,6 +107,16 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
+ return e1e_wphy(hw, M88E1000_PHY_GEN_CONTROL, 0);
+ }
+
++void e1000e_disable_phy_retry(struct e1000_hw *hw)
++{
++ hw->phy.retry_enabled = false;
++}
++
++void e1000e_enable_phy_retry(struct e1000_hw *hw)
++{
++ hw->phy.retry_enabled = true;
++}
++
+ /**
+ * e1000e_read_phy_reg_mdic - Read MDI control register
+ * @hw: pointer to the HW structure
+@@ -118,55 +128,73 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw)
+ **/
+ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+ {
++ u32 i, mdic = 0, retry_counter, retry_max;
+ struct e1000_phy_info *phy = &hw->phy;
+- u32 i, mdic = 0;
++ bool success;
+
+ if (offset > MAX_PHY_REG_ADDRESS) {
+ e_dbg("PHY Address %d is out of range\n", offset);
+ return -E1000_ERR_PARAM;
+ }
+
++ retry_max = phy->retry_enabled ? phy->retry_count : 0;
++
+ /* Set up Op-code, Phy Address, and register offset in the MDI
+ * Control register. The MAC will take care of interfacing with the
+ * PHY to retrieve the desired data.
+ */
+- mdic = ((offset << E1000_MDIC_REG_SHIFT) |
+- (phy->addr << E1000_MDIC_PHY_SHIFT) |
+- (E1000_MDIC_OP_READ));
++ for (retry_counter = 0; retry_counter <= retry_max; retry_counter++) {
++ success = true;
+
+- ew32(MDIC, mdic);
++ mdic = ((offset << E1000_MDIC_REG_SHIFT) |
++ (phy->addr << E1000_MDIC_PHY_SHIFT) |
++ (E1000_MDIC_OP_READ));
+
+- /* Poll the ready bit to see if the MDI read completed
+- * Increasing the time out as testing showed failures with
+- * the lower time out
+- */
+- for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
+- udelay(50);
+- mdic = er32(MDIC);
+- if (mdic & E1000_MDIC_READY)
+- break;
+- }
+- if (!(mdic & E1000_MDIC_READY)) {
+- e_dbg("MDI Read PHY Reg Address %d did not complete\n", offset);
+- return -E1000_ERR_PHY;
+- }
+- if (mdic & E1000_MDIC_ERROR) {
+- e_dbg("MDI Read PHY Reg Address %d Error\n", offset);
+- return -E1000_ERR_PHY;
+- }
+- if (FIELD_GET(E1000_MDIC_REG_MASK, mdic) != offset) {
+- e_dbg("MDI Read offset error - requested %d, returned %d\n",
+- offset, FIELD_GET(E1000_MDIC_REG_MASK, mdic));
+- return -E1000_ERR_PHY;
++ ew32(MDIC, mdic);
++
++ /* Poll the ready bit to see if the MDI read completed
++ * Increasing the time out as testing showed failures with
++ * the lower time out
++ */
++ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
++ usleep_range(50, 60);
++ mdic = er32(MDIC);
++ if (mdic & E1000_MDIC_READY)
++ break;
++ }
++ if (!(mdic & E1000_MDIC_READY)) {
++ e_dbg("MDI Read PHY Reg Address %d did not complete\n",
++ offset);
++ success = false;
++ }
++ if (mdic & E1000_MDIC_ERROR) {
++ e_dbg("MDI Read PHY Reg Address %d Error\n", offset);
++ success = false;
++ }
++ if (FIELD_GET(E1000_MDIC_REG_MASK, mdic) != offset) {
++ e_dbg("MDI Read offset error - requested %d, returned %d\n",
++ offset, FIELD_GET(E1000_MDIC_REG_MASK, mdic));
++ success = false;
++ }
++
++ /* Allow some time after each MDIC transaction to avoid
++ * reading duplicate data in the next MDIC transaction.
++ */
++ if (hw->mac.type == e1000_pch2lan)
++ usleep_range(100, 150);
++
++ if (success) {
++ *data = (u16)mdic;
++ return 0;
++ }
++
++ if (retry_counter != retry_max) {
++ e_dbg("Perform retry on PHY transaction...\n");
++ mdelay(10);
++ }
+ }
+- *data = (u16)mdic;
+
+- /* Allow some time after each MDIC transaction to avoid
+- * reading duplicate data in the next MDIC transaction.
+- */
+- if (hw->mac.type == e1000_pch2lan)
+- udelay(100);
+- return 0;
++ return -E1000_ERR_PHY;
+ }
+
+ /**
+@@ -179,56 +207,72 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+ **/
+ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+ {
++ u32 i, mdic = 0, retry_counter, retry_max;
+ struct e1000_phy_info *phy = &hw->phy;
+- u32 i, mdic = 0;
++ bool success;
+
+ if (offset > MAX_PHY_REG_ADDRESS) {
+ e_dbg("PHY Address %d is out of range\n", offset);
+ return -E1000_ERR_PARAM;
+ }
+
++ retry_max = phy->retry_enabled ? phy->retry_count : 0;
++
+ /* Set up Op-code, Phy Address, and register offset in the MDI
+ * Control register. The MAC will take care of interfacing with the
+ * PHY to retrieve the desired data.
+ */
+- mdic = (((u32)data) |
+- (offset << E1000_MDIC_REG_SHIFT) |
+- (phy->addr << E1000_MDIC_PHY_SHIFT) |
+- (E1000_MDIC_OP_WRITE));
++ for (retry_counter = 0; retry_counter <= retry_max; retry_counter++) {
++ success = true;
+
+- ew32(MDIC, mdic);
++ mdic = (((u32)data) |
++ (offset << E1000_MDIC_REG_SHIFT) |
++ (phy->addr << E1000_MDIC_PHY_SHIFT) |
++ (E1000_MDIC_OP_WRITE));
+
+- /* Poll the ready bit to see if the MDI read completed
+- * Increasing the time out as testing showed failures with
+- * the lower time out
+- */
+- for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
+- udelay(50);
+- mdic = er32(MDIC);
+- if (mdic & E1000_MDIC_READY)
+- break;
+- }
+- if (!(mdic & E1000_MDIC_READY)) {
+- e_dbg("MDI Write PHY Reg Address %d did not complete\n", offset);
+- return -E1000_ERR_PHY;
+- }
+- if (mdic & E1000_MDIC_ERROR) {
+- e_dbg("MDI Write PHY Red Address %d Error\n", offset);
+- return -E1000_ERR_PHY;
+- }
+- if (FIELD_GET(E1000_MDIC_REG_MASK, mdic) != offset) {
+- e_dbg("MDI Write offset error - requested %d, returned %d\n",
+- offset, FIELD_GET(E1000_MDIC_REG_MASK, mdic));
+- return -E1000_ERR_PHY;
+- }
++ ew32(MDIC, mdic);
+
+- /* Allow some time after each MDIC transaction to avoid
+- * reading duplicate data in the next MDIC transaction.
+- */
+- if (hw->mac.type == e1000_pch2lan)
+- udelay(100);
++ /* Poll the ready bit to see if the MDI read completed
++ * Increasing the time out as testing showed failures with
++ * the lower time out
++ */
++ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
++ usleep_range(50, 60);
++ mdic = er32(MDIC);
++ if (mdic & E1000_MDIC_READY)
++ break;
++ }
++ if (!(mdic & E1000_MDIC_READY)) {
++ e_dbg("MDI Write PHY Reg Address %d did not complete\n",
++ offset);
++ success = false;
++ }
++ if (mdic & E1000_MDIC_ERROR) {
++ e_dbg("MDI Write PHY Reg Address %d Error\n", offset);
++ success = false;
++ }
++ if (FIELD_GET(E1000_MDIC_REG_MASK, mdic) != offset) {
++ e_dbg("MDI Write offset error - requested %d, returned %d\n",
++ offset, FIELD_GET(E1000_MDIC_REG_MASK, mdic));
++ success = false;
++ }
+
+- return 0;
++ /* Allow some time after each MDIC transaction to avoid
++ * reading duplicate data in the next MDIC transaction.
++ */
++ if (hw->mac.type == e1000_pch2lan)
++ usleep_range(100, 150);
++
++ if (success)
++ return 0;
++
++ if (retry_counter != retry_max) {
++ e_dbg("Perform retry on PHY transaction...\n");
++ mdelay(10);
++ }
++ }
++
++ return -E1000_ERR_PHY;
+ }
+
+ /**
+diff --git a/drivers/net/ethernet/intel/e1000e/phy.h b/drivers/net/ethernet/intel/e1000e/phy.h
+index c48777d095235..049bb325b4b14 100644
+--- a/drivers/net/ethernet/intel/e1000e/phy.h
++++ b/drivers/net/ethernet/intel/e1000e/phy.h
+@@ -51,6 +51,8 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
+ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
+ void e1000_power_up_phy_copper(struct e1000_hw *hw);
+ void e1000_power_down_phy_copper(struct e1000_hw *hw);
++void e1000e_disable_phy_retry(struct e1000_hw *hw);
++void e1000e_enable_phy_retry(struct e1000_hw *hw);
+ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
+ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
+ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
+diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
+index 9b701615c7c62..4d2b05de6c634 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e.h
++++ b/drivers/net/ethernet/intel/i40e/i40e.h
+@@ -908,6 +908,7 @@ struct i40e_q_vector {
+ struct rcu_head rcu; /* to avoid race with update stats on free */
+ char name[I40E_INT_NAME_STR_LEN];
+ bool arm_wb_state;
++ bool in_busy_poll;
+ int irq_num; /* IRQ assigned to this q_vector */
+ } ____cacheline_internodealigned_in_smp;
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index 89a3401d20ab4..bb4ab3a9576b9 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -1257,8 +1257,11 @@ int i40e_count_filters(struct i40e_vsi *vsi)
+ int bkt;
+ int cnt = 0;
+
+- hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist)
+- ++cnt;
++ hash_for_each_safe(vsi->mac_filter_hash, bkt, h, f, hlist) {
++ if (f->state == I40E_FILTER_NEW ||
++ f->state == I40E_FILTER_ACTIVE)
++ ++cnt;
++ }
+
+ return cnt;
+ }
+@@ -3915,6 +3918,12 @@ static void i40e_vsi_configure_msix(struct i40e_vsi *vsi)
+ q_vector->tx.target_itr >> 1);
+ q_vector->tx.current_itr = q_vector->tx.target_itr;
+
++ /* Set ITR for software interrupts triggered after exiting
++ * busy-loop polling.
++ */
++ wr32(hw, I40E_PFINT_ITRN(I40E_SW_ITR, vector - 1),
++ I40E_ITR_20K);
++
+ wr32(hw, I40E_PFINT_RATEN(vector - 1),
+ i40e_intrl_usec_to_reg(vsi->int_rate_limit));
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/ethernet/intel/i40e/i40e_register.h
+index 14ab642cafdb2..432afbb642013 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_register.h
++++ b/drivers/net/ethernet/intel/i40e/i40e_register.h
+@@ -333,8 +333,11 @@
+ #define I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT 3
+ #define I40E_PFINT_DYN_CTLN_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)
+ #define I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT 5
++#define I40E_PFINT_DYN_CTLN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT)
+ #define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24
+ #define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
++#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25
++#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
+ #define I40E_PFINT_ICR0 0x00038780 /* Reset: CORER */
+ #define I40E_PFINT_ICR0_INTEVENT_SHIFT 0
+ #define I40E_PFINT_ICR0_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_INTEVENT_SHIFT)
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+index 0d7177083708f..1a12b732818ee 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+@@ -2630,7 +2630,22 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget,
+ return failure ? budget : (int)total_rx_packets;
+ }
+
+-static inline u32 i40e_buildreg_itr(const int type, u16 itr)
++/**
++ * i40e_buildreg_itr - build a value for writing to I40E_PFINT_DYN_CTLN register
++ * @itr_idx: interrupt throttling index
++ * @interval: interrupt throttling interval value in usecs
++ * @force_swint: force software interrupt
++ *
++ * The function builds a value for I40E_PFINT_DYN_CTLN register that
++ * is used to update interrupt throttling interval for specified ITR index
++ * and optionally enforces a software interrupt. If the @itr_idx is equal
++ * to I40E_ITR_NONE then no interval change is applied and only @force_swint
++ * parameter is taken into account. If the interval change and enforced
++ * software interrupt are not requested then the built value just enables
++ * appropriate vector interrupt.
++ **/
++static u32 i40e_buildreg_itr(enum i40e_dyn_idx itr_idx, u16 interval,
++ bool force_swint)
+ {
+ u32 val;
+
+@@ -2644,23 +2659,33 @@ static inline u32 i40e_buildreg_itr(const int type, u16 itr)
+ * an event in the PBA anyway so we need to rely on the automask
+ * to hold pending events for us until the interrupt is re-enabled
+ *
+- * The itr value is reported in microseconds, and the register
+- * value is recorded in 2 microsecond units. For this reason we
+- * only need to shift by the interval shift - 1 instead of the
+- * full value.
++ * We have to shift the given value as it is reported in microseconds
++ * and the register value is recorded in 2 microsecond units.
+ */
+- itr &= I40E_ITR_MASK;
++ interval >>= 1;
+
++ /* 1. Enable vector interrupt
++ * 2. Update the interval for the specified ITR index
++ * (I40E_ITR_NONE in the register is used to indicate that
++ * no interval update is requested)
++ */
+ val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
+- (type << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
+- (itr << (I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT - 1));
++ FIELD_PREP(I40E_PFINT_DYN_CTLN_ITR_INDX_MASK, itr_idx) |
++ FIELD_PREP(I40E_PFINT_DYN_CTLN_INTERVAL_MASK, interval);
++
++ /* 3. Enforce software interrupt trigger if requested
++ * (These software interrupts rate is limited by ITR2 that is
++ * set to 20K interrupts per second)
++ */
++ if (force_swint)
++ val |= I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK |
++ I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK |
++ FIELD_PREP(I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK,
++ I40E_SW_ITR);
+
+ return val;
+ }
+
+-/* a small macro to shorten up some long lines */
+-#define INTREG I40E_PFINT_DYN_CTLN
+-
+ /* The act of updating the ITR will cause it to immediately trigger. In order
+ * to prevent this from throwing off adaptive update statistics we defer the
+ * update so that it can only happen so often. So after either Tx or Rx are
+@@ -2679,8 +2704,10 @@ static inline u32 i40e_buildreg_itr(const int type, u16 itr)
+ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
+ struct i40e_q_vector *q_vector)
+ {
++ enum i40e_dyn_idx itr_idx = I40E_ITR_NONE;
+ struct i40e_hw *hw = &vsi->back->hw;
+- u32 intval;
++ u16 interval = 0;
++ u32 itr_val;
+
+ /* If we don't have MSIX, then we only need to re-enable icr0 */
+ if (!test_bit(I40E_FLAG_MSIX_ENA, vsi->back->flags)) {
+@@ -2702,8 +2729,8 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
+ */
+ if (q_vector->rx.target_itr < q_vector->rx.current_itr) {
+ /* Rx ITR needs to be reduced, this is highest priority */
+- intval = i40e_buildreg_itr(I40E_RX_ITR,
+- q_vector->rx.target_itr);
++ itr_idx = I40E_RX_ITR;
++ interval = q_vector->rx.target_itr;
+ q_vector->rx.current_itr = q_vector->rx.target_itr;
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
+ } else if ((q_vector->tx.target_itr < q_vector->tx.current_itr) ||
+@@ -2712,25 +2739,36 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
+ /* Tx ITR needs to be reduced, this is second priority
+ * Tx ITR needs to be increased more than Rx, fourth priority
+ */
+- intval = i40e_buildreg_itr(I40E_TX_ITR,
+- q_vector->tx.target_itr);
++ itr_idx = I40E_TX_ITR;
++ interval = q_vector->tx.target_itr;
+ q_vector->tx.current_itr = q_vector->tx.target_itr;
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
+ } else if (q_vector->rx.current_itr != q_vector->rx.target_itr) {
+ /* Rx ITR needs to be increased, third priority */
+- intval = i40e_buildreg_itr(I40E_RX_ITR,
+- q_vector->rx.target_itr);
++ itr_idx = I40E_RX_ITR;
++ interval = q_vector->rx.target_itr;
+ q_vector->rx.current_itr = q_vector->rx.target_itr;
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
+ } else {
+ /* No ITR update, lowest priority */
+- intval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
+ if (q_vector->itr_countdown)
+ q_vector->itr_countdown--;
+ }
+
+- if (!test_bit(__I40E_VSI_DOWN, vsi->state))
+- wr32(hw, INTREG(q_vector->reg_idx), intval);
++ /* Do not update interrupt control register if VSI is down */
++ if (test_bit(__I40E_VSI_DOWN, vsi->state))
++ return;
++
++ /* Update ITR interval if necessary and enforce software interrupt
++ * if we are exiting busy poll.
++ */
++ if (q_vector->in_busy_poll) {
++ itr_val = i40e_buildreg_itr(itr_idx, interval, true);
++ q_vector->in_busy_poll = false;
++ } else {
++ itr_val = i40e_buildreg_itr(itr_idx, interval, false);
++ }
++ wr32(hw, I40E_PFINT_DYN_CTLN(q_vector->reg_idx), itr_val);
+ }
+
+ /**
+@@ -2845,6 +2883,8 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
+ */
+ if (likely(napi_complete_done(napi, work_done)))
+ i40e_update_enable_itr(vsi, q_vector);
++ else
++ q_vector->in_busy_poll = true;
+
+ return min(work_done, budget - 1);
+ }
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+index abf15067eb5de..2cdc7de6301c1 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
++++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+@@ -68,6 +68,7 @@ enum i40e_dyn_idx {
+ /* these are indexes into ITRN registers */
+ #define I40E_RX_ITR I40E_IDX_ITR0
+ #define I40E_TX_ITR I40E_IDX_ITR1
++#define I40E_SW_ITR I40E_IDX_ITR2
+
+ /* Supported RSS offloads */
+ #define I40E_DEFAULT_RSS_HENA ( \
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+index b34c717708874..37e77163da4cd 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+@@ -1628,8 +1628,8 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
+ {
+ struct i40e_hw *hw = &pf->hw;
+ struct i40e_vf *vf;
+- int i, v;
+ u32 reg;
++ int i;
+
+ /* If we don't have any VFs, then there is nothing to reset */
+ if (!pf->num_alloc_vfs)
+@@ -1640,11 +1640,10 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
+ return false;
+
+ /* Begin reset on all VFs at once */
+- for (v = 0; v < pf->num_alloc_vfs; v++) {
+- vf = &pf->vf[v];
++ for (vf = &pf->vf[0]; vf < &pf->vf[pf->num_alloc_vfs]; ++vf) {
+ /* If VF is being reset no need to trigger reset again */
+ if (!test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
+- i40e_trigger_vf_reset(&pf->vf[v], flr);
++ i40e_trigger_vf_reset(vf, flr);
+ }
+
+ /* HW requires some time to make sure it can flush the FIFO for a VF
+@@ -1653,14 +1652,13 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
+ * the VFs using a simple iterator that increments once that VF has
+ * finished resetting.
+ */
+- for (i = 0, v = 0; i < 10 && v < pf->num_alloc_vfs; i++) {
++ for (i = 0, vf = &pf->vf[0]; i < 10 && vf < &pf->vf[pf->num_alloc_vfs]; ++i) {
+ usleep_range(10000, 20000);
+
+ /* Check each VF in sequence, beginning with the VF to fail
+ * the previous check.
+ */
+- while (v < pf->num_alloc_vfs) {
+- vf = &pf->vf[v];
++ while (vf < &pf->vf[pf->num_alloc_vfs]) {
+ if (!test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states)) {
+ reg = rd32(hw, I40E_VPGEN_VFRSTAT(vf->vf_id));
+ if (!(reg & I40E_VPGEN_VFRSTAT_VFRD_MASK))
+@@ -1670,7 +1668,7 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
+ /* If the current VF has finished resetting, move on
+ * to the next VF in sequence.
+ */
+- v++;
++ ++vf;
+ }
+ }
+
+@@ -1680,39 +1678,39 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
+ /* Display a warning if at least one VF didn't manage to reset in
+ * time, but continue on with the operation.
+ */
+- if (v < pf->num_alloc_vfs)
++ if (vf < &pf->vf[pf->num_alloc_vfs])
+ dev_err(&pf->pdev->dev, "VF reset check timeout on VF %d\n",
+- pf->vf[v].vf_id);
++ vf->vf_id);
+ usleep_range(10000, 20000);
+
+ /* Begin disabling all the rings associated with VFs, but do not wait
+ * between each VF.
+ */
+- for (v = 0; v < pf->num_alloc_vfs; v++) {
++ for (vf = &pf->vf[0]; vf < &pf->vf[pf->num_alloc_vfs]; ++vf) {
+ /* On initial reset, we don't have any queues to disable */
+- if (pf->vf[v].lan_vsi_idx == 0)
++ if (vf->lan_vsi_idx == 0)
+ continue;
+
+ /* If VF is reset in another thread just continue */
+ if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
+ continue;
+
+- i40e_vsi_stop_rings_no_wait(pf->vsi[pf->vf[v].lan_vsi_idx]);
++ i40e_vsi_stop_rings_no_wait(pf->vsi[vf->lan_vsi_idx]);
+ }
+
+ /* Now that we've notified HW to disable all of the VF rings, wait
+ * until they finish.
+ */
+- for (v = 0; v < pf->num_alloc_vfs; v++) {
++ for (vf = &pf->vf[0]; vf < &pf->vf[pf->num_alloc_vfs]; ++vf) {
+ /* On initial reset, we don't have any queues to disable */
+- if (pf->vf[v].lan_vsi_idx == 0)
++ if (vf->lan_vsi_idx == 0)
+ continue;
+
+ /* If VF is reset in another thread just continue */
+ if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
+ continue;
+
+- i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[v].lan_vsi_idx]);
++ i40e_vsi_wait_queues_disabled(pf->vsi[vf->lan_vsi_idx]);
+ }
+
+ /* Hw may need up to 50ms to finish disabling the RX queues. We
+@@ -1721,12 +1719,12 @@ bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr)
+ mdelay(50);
+
+ /* Finish the reset on each VF */
+- for (v = 0; v < pf->num_alloc_vfs; v++) {
++ for (vf = &pf->vf[0]; vf < &pf->vf[pf->num_alloc_vfs]; ++vf) {
+ /* If VF is reset in another thread just continue */
+ if (test_bit(I40E_VF_STATE_RESETTING, &vf->vf_states))
+ continue;
+
+- i40e_cleanup_reset_vf(&pf->vf[v]);
++ i40e_cleanup_reset_vf(vf);
+ }
+
+ i40e_flush(hw);
+@@ -3143,11 +3141,12 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg)
+ /* Allow to delete VF primary MAC only if it was not set
+ * administratively by PF or if VF is trusted.
+ */
+- if (ether_addr_equal(addr, vf->default_lan_addr.addr) &&
+- i40e_can_vf_change_mac(vf))
+- was_unimac_deleted = true;
+- else
+- continue;
++ if (ether_addr_equal(addr, vf->default_lan_addr.addr)) {
++ if (i40e_can_vf_change_mac(vf))
++ was_unimac_deleted = true;
++ else
++ continue;
++ }
+
+ if (i40e_del_mac_filter(vsi, al->list[i].addr)) {
+ ret = -EINVAL;
+diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+index 8040317c95617..1f3e7a6903e56 100644
+--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
++++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+@@ -593,8 +593,9 @@ struct ice_aqc_recipe_data_elem {
+ struct ice_aqc_recipe_to_profile {
+ __le16 profile_id;
+ u8 rsvd[6];
+- DECLARE_BITMAP(recipe_assoc, ICE_MAX_NUM_RECIPES);
++ __le64 recipe_assoc;
+ };
++static_assert(sizeof(struct ice_aqc_recipe_to_profile) == 16);
+
+ /* Add/Update/Remove/Get switch rules (indirect 0x02A0, 0x02A1, 0x02A2, 0x02A3)
+ */
+diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c
+index 467372d541d21..a7a342809935f 100644
+--- a/drivers/net/ethernet/intel/ice/ice_lag.c
++++ b/drivers/net/ethernet/intel/ice/ice_lag.c
+@@ -2041,7 +2041,7 @@ int ice_init_lag(struct ice_pf *pf)
+ /* associate recipes to profiles */
+ for (n = 0; n < ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER; n++) {
+ err = ice_aq_get_recipe_to_profile(&pf->hw, n,
+- (u8 *)&recipe_bits, NULL);
++ &recipe_bits, NULL);
+ if (err)
+ continue;
+
+@@ -2049,7 +2049,7 @@ int ice_init_lag(struct ice_pf *pf)
+ recipe_bits |= BIT(lag->pf_recipe) |
+ BIT(lag->lport_recipe);
+ ice_aq_map_recipe_to_profile(&pf->hw, n,
+- (u8 *)&recipe_bits, NULL);
++ recipe_bits, NULL);
+ }
+ }
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
+index fc23dbe302b46..cfc20684f25ab 100644
+--- a/drivers/net/ethernet/intel/ice/ice_lib.c
++++ b/drivers/net/ethernet/intel/ice/ice_lib.c
+@@ -3238,7 +3238,7 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags)
+ {
+ struct ice_vsi_cfg_params params = {};
+ struct ice_coalesce_stored *coalesce;
+- int prev_num_q_vectors = 0;
++ int prev_num_q_vectors;
+ struct ice_pf *pf;
+ int ret;
+
+@@ -3252,13 +3252,6 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags)
+ if (WARN_ON(vsi->type == ICE_VSI_VF && !vsi->vf))
+ return -EINVAL;
+
+- coalesce = kcalloc(vsi->num_q_vectors,
+- sizeof(struct ice_coalesce_stored), GFP_KERNEL);
+- if (!coalesce)
+- return -ENOMEM;
+-
+- prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, coalesce);
+-
+ ret = ice_vsi_realloc_stat_arrays(vsi);
+ if (ret)
+ goto err_vsi_cfg;
+@@ -3268,6 +3261,13 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags)
+ if (ret)
+ goto err_vsi_cfg;
+
++ coalesce = kcalloc(vsi->num_q_vectors,
++ sizeof(struct ice_coalesce_stored), GFP_KERNEL);
++ if (!coalesce)
++ return -ENOMEM;
++
++ prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, coalesce);
++
+ ret = ice_vsi_cfg_tc_lan(pf, vsi);
+ if (ret) {
+ if (vsi_flags & ICE_VSI_FLAG_INIT) {
+@@ -3286,8 +3286,8 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags)
+
+ err_vsi_cfg_tc_lan:
+ ice_vsi_decfg(vsi);
+-err_vsi_cfg:
+ kfree(coalesce);
++err_vsi_cfg:
+ return ret;
+ }
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
+index f84bab80ca423..ba0ef91e4c19c 100644
+--- a/drivers/net/ethernet/intel/ice/ice_switch.c
++++ b/drivers/net/ethernet/intel/ice/ice_switch.c
+@@ -2025,12 +2025,12 @@ ice_update_recipe_lkup_idx(struct ice_hw *hw,
+ * ice_aq_map_recipe_to_profile - Map recipe to packet profile
+ * @hw: pointer to the HW struct
+ * @profile_id: package profile ID to associate the recipe with
+- * @r_bitmap: Recipe bitmap filled in and need to be returned as response
++ * @r_assoc: Recipe bitmap filled in and need to be returned as response
+ * @cd: pointer to command details structure or NULL
+ * Recipe to profile association (0x0291)
+ */
+ int
+-ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
++ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u64 r_assoc,
+ struct ice_sq_cd *cd)
+ {
+ struct ice_aqc_recipe_to_profile *cmd;
+@@ -2042,7 +2042,7 @@ ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
+ /* Set the recipe ID bit in the bitmask to let the device know which
+ * profile we are associating the recipe to
+ */
+- memcpy(cmd->recipe_assoc, r_bitmap, sizeof(cmd->recipe_assoc));
++ cmd->recipe_assoc = cpu_to_le64(r_assoc);
+
+ return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+ }
+@@ -2051,12 +2051,12 @@ ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
+ * ice_aq_get_recipe_to_profile - Map recipe to packet profile
+ * @hw: pointer to the HW struct
+ * @profile_id: package profile ID to associate the recipe with
+- * @r_bitmap: Recipe bitmap filled in and need to be returned as response
++ * @r_assoc: Recipe bitmap filled in and need to be returned as response
+ * @cd: pointer to command details structure or NULL
+ * Associate profile ID with given recipe (0x0293)
+ */
+ int
+-ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
++ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u64 *r_assoc,
+ struct ice_sq_cd *cd)
+ {
+ struct ice_aqc_recipe_to_profile *cmd;
+@@ -2069,7 +2069,7 @@ ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
+
+ status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
+ if (!status)
+- memcpy(r_bitmap, cmd->recipe_assoc, sizeof(cmd->recipe_assoc));
++ *r_assoc = le64_to_cpu(cmd->recipe_assoc);
+
+ return status;
+ }
+@@ -2108,6 +2108,7 @@ int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
+ static void ice_get_recp_to_prof_map(struct ice_hw *hw)
+ {
+ DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
++ u64 recp_assoc;
+ u16 i;
+
+ for (i = 0; i < hw->switch_info->max_used_prof_index + 1; i++) {
+@@ -2115,8 +2116,9 @@ static void ice_get_recp_to_prof_map(struct ice_hw *hw)
+
+ bitmap_zero(profile_to_recipe[i], ICE_MAX_NUM_RECIPES);
+ bitmap_zero(r_bitmap, ICE_MAX_NUM_RECIPES);
+- if (ice_aq_get_recipe_to_profile(hw, i, (u8 *)r_bitmap, NULL))
++ if (ice_aq_get_recipe_to_profile(hw, i, &recp_assoc, NULL))
+ continue;
++ bitmap_from_arr64(r_bitmap, &recp_assoc, ICE_MAX_NUM_RECIPES);
+ bitmap_copy(profile_to_recipe[i], r_bitmap,
+ ICE_MAX_NUM_RECIPES);
+ for_each_set_bit(j, r_bitmap, ICE_MAX_NUM_RECIPES)
+@@ -5390,22 +5392,24 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
+ */
+ list_for_each_entry(fvit, &rm->fv_list, list_entry) {
+ DECLARE_BITMAP(r_bitmap, ICE_MAX_NUM_RECIPES);
++ u64 recp_assoc;
+ u16 j;
+
+ status = ice_aq_get_recipe_to_profile(hw, fvit->profile_id,
+- (u8 *)r_bitmap, NULL);
++ &recp_assoc, NULL);
+ if (status)
+ goto err_unroll;
+
++ bitmap_from_arr64(r_bitmap, &recp_assoc, ICE_MAX_NUM_RECIPES);
+ bitmap_or(r_bitmap, r_bitmap, rm->r_bitmap,
+ ICE_MAX_NUM_RECIPES);
+ status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
+ if (status)
+ goto err_unroll;
+
++ bitmap_to_arr64(&recp_assoc, r_bitmap, ICE_MAX_NUM_RECIPES);
+ status = ice_aq_map_recipe_to_profile(hw, fvit->profile_id,
+- (u8 *)r_bitmap,
+- NULL);
++ recp_assoc, NULL);
+ ice_release_change_lock(hw);
+
+ if (status)
+diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h
+index db7e501b7e0a4..89ffa1b51b5ad 100644
+--- a/drivers/net/ethernet/intel/ice/ice_switch.h
++++ b/drivers/net/ethernet/intel/ice/ice_switch.h
+@@ -424,10 +424,10 @@ int ice_aq_add_recipe(struct ice_hw *hw,
+ struct ice_aqc_recipe_data_elem *s_recipe_list,
+ u16 num_recipes, struct ice_sq_cd *cd);
+ int
+-ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
++ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u64 *r_assoc,
+ struct ice_sq_cd *cd);
+ int
+-ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
++ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u64 r_assoc,
+ struct ice_sq_cd *cd);
+
+ #endif /* _ICE_SWITCH_H_ */
+diff --git a/drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.c b/drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.c
+index 80dc4bcdd3a41..b3e1bdcb80f84 100644
+--- a/drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.c
++++ b/drivers/net/ethernet/intel/ice/ice_vf_vsi_vlan_ops.c
+@@ -26,24 +26,22 @@ static void ice_port_vlan_on(struct ice_vsi *vsi)
+ struct ice_vsi_vlan_ops *vlan_ops;
+ struct ice_pf *pf = vsi->back;
+
+- if (ice_is_dvm_ena(&pf->hw)) {
+- vlan_ops = &vsi->outer_vlan_ops;
+-
+- /* setup outer VLAN ops */
+- vlan_ops->set_port_vlan = ice_vsi_set_outer_port_vlan;
+- vlan_ops->clear_port_vlan = ice_vsi_clear_outer_port_vlan;
++ /* setup inner VLAN ops */
++ vlan_ops = &vsi->inner_vlan_ops;
+
+- /* setup inner VLAN ops */
+- vlan_ops = &vsi->inner_vlan_ops;
++ if (ice_is_dvm_ena(&pf->hw)) {
+ vlan_ops->add_vlan = noop_vlan_arg;
+ vlan_ops->del_vlan = noop_vlan_arg;
+ vlan_ops->ena_stripping = ice_vsi_ena_inner_stripping;
+ vlan_ops->dis_stripping = ice_vsi_dis_inner_stripping;
+ vlan_ops->ena_insertion = ice_vsi_ena_inner_insertion;
+ vlan_ops->dis_insertion = ice_vsi_dis_inner_insertion;
+- } else {
+- vlan_ops = &vsi->inner_vlan_ops;
+
++ /* setup outer VLAN ops */
++ vlan_ops = &vsi->outer_vlan_ops;
++ vlan_ops->set_port_vlan = ice_vsi_set_outer_port_vlan;
++ vlan_ops->clear_port_vlan = ice_vsi_clear_outer_port_vlan;
++ } else {
+ vlan_ops->set_port_vlan = ice_vsi_set_inner_port_vlan;
+ vlan_ops->clear_port_vlan = ice_vsi_clear_inner_port_vlan;
+ }
+diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+index 2f8ad79ae3f04..017a081d85802 100644
+--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
++++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+@@ -2940,6 +2940,8 @@ static int idpf_rx_process_skb_fields(struct idpf_queue *rxq,
+ rx_ptype = le16_get_bits(rx_desc->ptype_err_fflags0,
+ VIRTCHNL2_RX_FLEX_DESC_ADV_PTYPE_M);
+
++ skb->protocol = eth_type_trans(skb, rxq->vport->netdev);
++
+ decoded = rxq->vport->rx_ptype_lkup[rx_ptype];
+ /* If we don't know the ptype we can't do anything else with it. Just
+ * pass it up the stack as-is.
+@@ -2950,8 +2952,6 @@ static int idpf_rx_process_skb_fields(struct idpf_queue *rxq,
+ /* process RSS/hash */
+ idpf_rx_hash(rxq, skb, rx_desc, &decoded);
+
+- skb->protocol = eth_type_trans(skb, rxq->vport->netdev);
+-
+ if (le16_get_bits(rx_desc->hdrlen_flags,
+ VIRTCHNL2_RX_FLEX_DESC_ADV_RSC_M))
+ return idpf_rx_rsc(rxq, skb, rx_desc, &decoded);
+diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
+index e447ba0370568..23bed58a9d825 100644
+--- a/drivers/net/ethernet/intel/igc/igc_main.c
++++ b/drivers/net/ethernet/intel/igc/igc_main.c
+@@ -1642,10 +1642,6 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb,
+
+ if (unlikely(test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) &&
+ skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
+- /* FIXME: add support for retrieving timestamps from
+- * the other timer registers before skipping the
+- * timestamping request.
+- */
+ unsigned long flags;
+ u32 tstamp_flags;
+
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+index 13a6fca31004a..866024f2b9eeb 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+@@ -914,7 +914,13 @@ int ixgbe_ipsec_vf_add_sa(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
+ goto err_out;
+ }
+
+- xs = kzalloc(sizeof(*xs), GFP_KERNEL);
++ algo = xfrm_aead_get_byname(aes_gcm_name, IXGBE_IPSEC_AUTH_BITS, 1);
++ if (unlikely(!algo)) {
++ err = -ENOENT;
++ goto err_out;
++ }
++
++ xs = kzalloc(sizeof(*xs), GFP_ATOMIC);
+ if (unlikely(!xs)) {
+ err = -ENOMEM;
+ goto err_out;
+@@ -930,14 +936,8 @@ int ixgbe_ipsec_vf_add_sa(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
+ memcpy(&xs->id.daddr.a4, sam->addr, sizeof(xs->id.daddr.a4));
+ xs->xso.dev = adapter->netdev;
+
+- algo = xfrm_aead_get_byname(aes_gcm_name, IXGBE_IPSEC_AUTH_BITS, 1);
+- if (unlikely(!algo)) {
+- err = -ENOENT;
+- goto err_xs;
+- }
+-
+ aead_len = sizeof(*xs->aead) + IXGBE_IPSEC_KEY_BITS / 8;
+- xs->aead = kzalloc(aead_len, GFP_KERNEL);
++ xs->aead = kzalloc(aead_len, GFP_ATOMIC);
+ if (unlikely(!xs->aead)) {
+ err = -ENOMEM;
+ goto err_xs;
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+index 3c0f55b3e48ea..b86f3224f0b78 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+@@ -808,6 +808,11 @@ static int cgx_lmac_enadis_pause_frm(void *cgxd, int lmac_id,
+ if (!is_lmac_valid(cgx, lmac_id))
+ return -ENODEV;
+
++ cfg = cgx_read(cgx, lmac_id, CGXX_GMP_GMI_RXX_FRM_CTL);
++ cfg &= ~CGX_GMP_GMI_RXX_FRM_CTL_CTL_BCK;
++ cfg |= rx_pause ? CGX_GMP_GMI_RXX_FRM_CTL_CTL_BCK : 0x0;
++ cgx_write(cgx, lmac_id, CGXX_GMP_GMI_RXX_FRM_CTL, cfg);
++
+ cfg = cgx_read(cgx, lmac_id, CGXX_SMUX_RX_FRM_CTL);
+ cfg &= ~CGX_SMUX_RX_FRM_CTL_CTL_BCK;
+ cfg |= rx_pause ? CGX_SMUX_RX_FRM_CTL_CTL_BCK : 0x0;
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+index 72e060cf6b618..e9bf9231b0185 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
+@@ -160,6 +160,8 @@ static int rvu_map_cgx_lmac_pf(struct rvu *rvu)
+ continue;
+ lmac_bmap = cgx_get_lmac_bmap(rvu_cgx_pdata(cgx, rvu));
+ for_each_set_bit(iter, &lmac_bmap, rvu->hw->lmac_per_cgx) {
++ if (iter >= MAX_LMAC_COUNT)
++ continue;
+ lmac = cgx_get_lmacid(rvu_cgx_pdata(cgx, rvu),
+ iter);
+ rvu->pf2cgxlmac_map[pf] = cgxlmac_id_to_bmap(cgx, lmac);
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index 516adb50f9f6b..42b5ed02bc87f 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -1657,7 +1657,7 @@ static int npc_fwdb_detect_load_prfl_img(struct rvu *rvu, uint64_t prfl_sz,
+ struct npc_coalesced_kpu_prfl *img_data = NULL;
+ int i = 0, rc = -EINVAL;
+ void __iomem *kpu_prfl_addr;
+- u16 offset;
++ u32 offset;
+
+ img_data = (struct npc_coalesced_kpu_prfl __force *)rvu->kpu_prfl_addr;
+ if (le64_to_cpu(img_data->signature) == KPU_SIGN &&
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+index b40bd0e467514..3f46d5e0fb2ec 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+@@ -1933,7 +1933,7 @@ int otx2_open(struct net_device *netdev)
+ * mcam entries are enabled to receive the packets. Hence disable the
+ * packet I/O.
+ */
+- if (err == EIO)
++ if (err == -EIO)
+ goto err_disable_rxtx;
+ else if (err)
+ goto err_tx_stop_queues;
+diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
+index 3d09fa54598f1..ba303868686a7 100644
+--- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
++++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c
+@@ -14,6 +14,7 @@
+ #include <linux/module.h>
+ #include <linux/phy.h>
+ #include <linux/platform_device.h>
++#include <linux/rtnetlink.h>
+ #include <linux/skbuff.h>
+
+ #include "mlxbf_gige.h"
+@@ -139,13 +140,10 @@ static int mlxbf_gige_open(struct net_device *netdev)
+ control |= MLXBF_GIGE_CONTROL_PORT_EN;
+ writeq(control, priv->base + MLXBF_GIGE_CONTROL);
+
+- err = mlxbf_gige_request_irqs(priv);
+- if (err)
+- return err;
+ mlxbf_gige_cache_stats(priv);
+ err = mlxbf_gige_clean_port(priv);
+ if (err)
+- goto free_irqs;
++ return err;
+
+ /* Clear driver's valid_polarity to match hardware,
+ * since the above call to clean_port() resets the
+@@ -157,7 +155,7 @@ static int mlxbf_gige_open(struct net_device *netdev)
+
+ err = mlxbf_gige_tx_init(priv);
+ if (err)
+- goto free_irqs;
++ goto phy_deinit;
+ err = mlxbf_gige_rx_init(priv);
+ if (err)
+ goto tx_deinit;
+@@ -166,6 +164,10 @@ static int mlxbf_gige_open(struct net_device *netdev)
+ napi_enable(&priv->napi);
+ netif_start_queue(netdev);
+
++ err = mlxbf_gige_request_irqs(priv);
++ if (err)
++ goto napi_deinit;
++
+ /* Set bits in INT_EN that we care about */
+ int_en = MLXBF_GIGE_INT_EN_HW_ACCESS_ERROR |
+ MLXBF_GIGE_INT_EN_TX_CHECKSUM_INPUTS |
+@@ -182,11 +184,17 @@ static int mlxbf_gige_open(struct net_device *netdev)
+
+ return 0;
+
++napi_deinit:
++ netif_stop_queue(netdev);
++ napi_disable(&priv->napi);
++ netif_napi_del(&priv->napi);
++ mlxbf_gige_rx_deinit(priv);
++
+ tx_deinit:
+ mlxbf_gige_tx_deinit(priv);
+
+-free_irqs:
+- mlxbf_gige_free_irqs(priv);
++phy_deinit:
++ phy_stop(phydev);
+ return err;
+ }
+
+@@ -485,8 +493,13 @@ static void mlxbf_gige_shutdown(struct platform_device *pdev)
+ {
+ struct mlxbf_gige *priv = platform_get_drvdata(pdev);
+
+- writeq(0, priv->base + MLXBF_GIGE_INT_EN);
+- mlxbf_gige_clean_port(priv);
++ rtnl_lock();
++ netif_device_detach(priv->netdev);
++
++ if (netif_running(priv->netdev))
++ dev_close(priv->netdev);
++
++ rtnl_unlock();
+ }
+
+ static const struct acpi_device_id __maybe_unused mlxbf_gige_acpi_match[] = {
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c
+index 45e209a7d0831..6bf3367404eba 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.c
++++ b/drivers/net/ethernet/microchip/lan743x_main.c
+@@ -25,6 +25,8 @@
+ #define PCS_POWER_STATE_DOWN 0x6
+ #define PCS_POWER_STATE_UP 0x4
+
++#define RFE_RD_FIFO_TH_3_DWORDS 0x3
++
+ static void pci11x1x_strap_get_status(struct lan743x_adapter *adapter)
+ {
+ u32 chip_rev;
+@@ -3272,6 +3274,21 @@ static void lan743x_full_cleanup(struct lan743x_adapter *adapter)
+ lan743x_pci_cleanup(adapter);
+ }
+
++static void pci11x1x_set_rfe_rd_fifo_threshold(struct lan743x_adapter *adapter)
++{
++ u16 rev = adapter->csr.id_rev & ID_REV_CHIP_REV_MASK_;
++
++ if (rev == ID_REV_CHIP_REV_PCI11X1X_B0_) {
++ u32 misc_ctl;
++
++ misc_ctl = lan743x_csr_read(adapter, MISC_CTL_0);
++ misc_ctl &= ~MISC_CTL_0_RFE_READ_FIFO_MASK_;
++ misc_ctl |= FIELD_PREP(MISC_CTL_0_RFE_READ_FIFO_MASK_,
++ RFE_RD_FIFO_TH_3_DWORDS);
++ lan743x_csr_write(adapter, MISC_CTL_0, misc_ctl);
++ }
++}
++
+ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
+ struct pci_dev *pdev)
+ {
+@@ -3287,6 +3304,7 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter,
+ pci11x1x_strap_get_status(adapter);
+ spin_lock_init(&adapter->eth_syslock_spinlock);
+ mutex_init(&adapter->sgmii_rw_lock);
++ pci11x1x_set_rfe_rd_fifo_threshold(adapter);
+ } else {
+ adapter->max_tx_channels = LAN743X_MAX_TX_CHANNELS;
+ adapter->used_tx_channels = LAN743X_USED_TX_CHANNELS;
+diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h
+index be79cb0ae5af3..645bc048e52ef 100644
+--- a/drivers/net/ethernet/microchip/lan743x_main.h
++++ b/drivers/net/ethernet/microchip/lan743x_main.h
+@@ -26,6 +26,7 @@
+ #define ID_REV_CHIP_REV_MASK_ (0x0000FFFF)
+ #define ID_REV_CHIP_REV_A0_ (0x00000000)
+ #define ID_REV_CHIP_REV_B0_ (0x00000010)
++#define ID_REV_CHIP_REV_PCI11X1X_B0_ (0x000000B0)
+
+ #define FPGA_REV (0x04)
+ #define FPGA_REV_GET_MINOR_(fpga_rev) (((fpga_rev) >> 8) & 0x000000FF)
+@@ -311,6 +312,9 @@
+ #define SGMII_CTL_LINK_STATUS_SOURCE_ BIT(8)
+ #define SGMII_CTL_SGMII_POWER_DN_ BIT(1)
+
++#define MISC_CTL_0 (0x920)
++#define MISC_CTL_0_RFE_READ_FIFO_MASK_ GENMASK(6, 4)
++
+ /* Vendor Specific SGMII MMD details */
+ #define SR_VSMMD_PCS_ID1 0x0004
+ #define SR_VSMMD_PCS_ID2 0x0005
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 59287c6e6cee6..d8af5e7e15b4d 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -601,7 +601,7 @@ static void mana_get_rxbuf_cfg(int mtu, u32 *datasize, u32 *alloc_size,
+
+ *alloc_size = mtu + MANA_RXBUF_PAD + *headroom;
+
+- *datasize = ALIGN(mtu + ETH_HLEN, MANA_RX_DATA_ALIGN);
++ *datasize = mtu + ETH_HLEN;
+ }
+
+ static int mana_pre_alloc_rxbufs(struct mana_port_context *mpc, int new_mtu)
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index dd73df6b17b06..4b6c28576a518 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -1255,17 +1255,40 @@ static void rtl8168ep_stop_cmac(struct rtl8169_private *tp)
+ RTL_W8(tp, IBCR0, RTL_R8(tp, IBCR0) & ~0x01);
+ }
+
++static void rtl_dash_loop_wait(struct rtl8169_private *tp,
++ const struct rtl_cond *c,
++ unsigned long usecs, int n, bool high)
++{
++ if (!tp->dash_enabled)
++ return;
++ rtl_loop_wait(tp, c, usecs, n, high);
++}
++
++static void rtl_dash_loop_wait_high(struct rtl8169_private *tp,
++ const struct rtl_cond *c,
++ unsigned long d, int n)
++{
++ rtl_dash_loop_wait(tp, c, d, n, true);
++}
++
++static void rtl_dash_loop_wait_low(struct rtl8169_private *tp,
++ const struct rtl_cond *c,
++ unsigned long d, int n)
++{
++ rtl_dash_loop_wait(tp, c, d, n, false);
++}
++
+ static void rtl8168dp_driver_start(struct rtl8169_private *tp)
+ {
+ r8168dp_oob_notify(tp, OOB_CMD_DRIVER_START);
+- rtl_loop_wait_high(tp, &rtl_dp_ocp_read_cond, 10000, 10);
++ rtl_dash_loop_wait_high(tp, &rtl_dp_ocp_read_cond, 10000, 10);
+ }
+
+ static void rtl8168ep_driver_start(struct rtl8169_private *tp)
+ {
+ r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_START);
+ r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01);
+- rtl_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10000, 30);
++ rtl_dash_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10000, 30);
+ }
+
+ static void rtl8168_driver_start(struct rtl8169_private *tp)
+@@ -1279,7 +1302,7 @@ static void rtl8168_driver_start(struct rtl8169_private *tp)
+ static void rtl8168dp_driver_stop(struct rtl8169_private *tp)
+ {
+ r8168dp_oob_notify(tp, OOB_CMD_DRIVER_STOP);
+- rtl_loop_wait_low(tp, &rtl_dp_ocp_read_cond, 10000, 10);
++ rtl_dash_loop_wait_low(tp, &rtl_dp_ocp_read_cond, 10000, 10);
+ }
+
+ static void rtl8168ep_driver_stop(struct rtl8169_private *tp)
+@@ -1287,7 +1310,7 @@ static void rtl8168ep_driver_stop(struct rtl8169_private *tp)
+ rtl8168ep_stop_cmac(tp);
+ r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_STOP);
+ r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01);
+- rtl_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10000, 10);
++ rtl_dash_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10000, 10);
+ }
+
+ static void rtl8168_driver_stop(struct rtl8169_private *tp)
+@@ -5027,6 +5050,15 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
+ struct mii_bus *new_bus;
+ int ret;
+
++ /* On some boards with this chip version the BIOS is buggy and misses
++ * to reset the PHY page selector. This results in the PHY ID read
++ * accessing registers on a different page, returning a more or
++ * less random value. Fix this by resetting the page selector first.
++ */
++ if (tp->mac_version == RTL_GIGA_MAC_VER_25 ||
++ tp->mac_version == RTL_GIGA_MAC_VER_26)
++ r8169_mdio_write(tp, 0x1f, 0);
++
+ new_bus = devm_mdiobus_alloc(&pdev->dev);
+ if (!new_bus)
+ return -ENOMEM;
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index f7566cfa45ca3..1bdf0abb256cf 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -1284,25 +1284,16 @@ static int ravb_poll(struct napi_struct *napi, int budget)
+ struct net_device *ndev = napi->dev;
+ struct ravb_private *priv = netdev_priv(ndev);
+ const struct ravb_hw_info *info = priv->info;
+- bool gptp = info->gptp || info->ccc_gac;
+- struct ravb_rx_desc *desc;
+ unsigned long flags;
+ int q = napi - priv->napi;
+ int mask = BIT(q);
+ int quota = budget;
+- unsigned int entry;
++ bool unmask;
+
+- if (!gptp) {
+- entry = priv->cur_rx[q] % priv->num_rx_ring[q];
+- desc = &priv->gbeth_rx_ring[entry];
+- }
+ /* Processing RX Descriptor Ring */
+ /* Clear RX interrupt */
+ ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0);
+- if (gptp || desc->die_dt != DT_FEMPTY) {
+- if (ravb_rx(ndev, "a, q))
+- goto out;
+- }
++ unmask = !ravb_rx(ndev, "a, q);
+
+ /* Processing TX Descriptor Ring */
+ spin_lock_irqsave(&priv->lock, flags);
+@@ -1312,6 +1303,18 @@ static int ravb_poll(struct napi_struct *napi, int budget)
+ netif_wake_subqueue(ndev, q);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
++ /* Receive error message handling */
++ priv->rx_over_errors = priv->stats[RAVB_BE].rx_over_errors;
++ if (info->nc_queues)
++ priv->rx_over_errors += priv->stats[RAVB_NC].rx_over_errors;
++ if (priv->rx_over_errors != ndev->stats.rx_over_errors)
++ ndev->stats.rx_over_errors = priv->rx_over_errors;
++ if (priv->rx_fifo_errors != ndev->stats.rx_fifo_errors)
++ ndev->stats.rx_fifo_errors = priv->rx_fifo_errors;
++
++ if (!unmask)
++ goto out;
++
+ napi_complete(napi);
+
+ /* Re-enable RX/TX interrupts */
+@@ -1325,14 +1328,6 @@ static int ravb_poll(struct napi_struct *napi, int budget)
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- /* Receive error message handling */
+- priv->rx_over_errors = priv->stats[RAVB_BE].rx_over_errors;
+- if (info->nc_queues)
+- priv->rx_over_errors += priv->stats[RAVB_NC].rx_over_errors;
+- if (priv->rx_over_errors != ndev->stats.rx_over_errors)
+- ndev->stats.rx_over_errors = priv->rx_over_errors;
+- if (priv->rx_fifo_errors != ndev->stats.rx_fifo_errors)
+- ndev->stats.rx_fifo_errors = priv->rx_fifo_errors;
+ out:
+ return budget - quota;
+ }
+diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
+index 475e1e8c1d35f..0786eb0da3914 100644
+--- a/drivers/net/ethernet/renesas/sh_eth.c
++++ b/drivers/net/ethernet/renesas/sh_eth.c
+@@ -50,7 +50,7 @@
+ * the macros available to do this only define GCC 8.
+ */
+ __diag_push();
+-__diag_ignore(GCC, 8, "-Woverride-init",
++__diag_ignore_all("-Woverride-init",
+ "logic to initialize all and then override some is OK");
+ static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
+ SH_ETH_OFFSET_DEFAULTS,
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+index 6b6d0de096197..cef25efbdff99 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+@@ -92,19 +92,41 @@ static void dwmac4_rx_queue_priority(struct mac_device_info *hw,
+ u32 prio, u32 queue)
+ {
+ void __iomem *ioaddr = hw->pcsr;
+- u32 base_register;
+- u32 value;
++ u32 clear_mask = 0;
++ u32 ctrl2, ctrl3;
++ int i;
+
+- base_register = (queue < 4) ? GMAC_RXQ_CTRL2 : GMAC_RXQ_CTRL3;
+- if (queue >= 4)
+- queue -= 4;
++ ctrl2 = readl(ioaddr + GMAC_RXQ_CTRL2);
++ ctrl3 = readl(ioaddr + GMAC_RXQ_CTRL3);
+
+- value = readl(ioaddr + base_register);
++ /* The software must ensure that the same priority
++ * is not mapped to multiple Rx queues
++ */
++ for (i = 0; i < 4; i++)
++ clear_mask |= ((prio << GMAC_RXQCTRL_PSRQX_SHIFT(i)) &
++ GMAC_RXQCTRL_PSRQX_MASK(i));
++
++ ctrl2 &= ~clear_mask;
++ ctrl3 &= ~clear_mask;
++
++ /* First assign new priorities to a queue, then
++ * clear them from others queues
++ */
++ if (queue < 4) {
++ ctrl2 |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) &
++ GMAC_RXQCTRL_PSRQX_MASK(queue);
+
+- value &= ~GMAC_RXQCTRL_PSRQX_MASK(queue);
+- value |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) &
++ writel(ctrl2, ioaddr + GMAC_RXQ_CTRL2);
++ writel(ctrl3, ioaddr + GMAC_RXQ_CTRL3);
++ } else {
++ queue -= 4;
++
++ ctrl3 |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) &
+ GMAC_RXQCTRL_PSRQX_MASK(queue);
+- writel(value, ioaddr + base_register);
++
++ writel(ctrl3, ioaddr + GMAC_RXQ_CTRL3);
++ writel(ctrl2, ioaddr + GMAC_RXQ_CTRL2);
++ }
+ }
+
+ static void dwmac4_tx_queue_priority(struct mac_device_info *hw,
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+index 1af2f89a0504a..e841e312077ef 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+@@ -105,17 +105,41 @@ static void dwxgmac2_rx_queue_prio(struct mac_device_info *hw, u32 prio,
+ u32 queue)
+ {
+ void __iomem *ioaddr = hw->pcsr;
+- u32 value, reg;
++ u32 clear_mask = 0;
++ u32 ctrl2, ctrl3;
++ int i;
+
+- reg = (queue < 4) ? XGMAC_RXQ_CTRL2 : XGMAC_RXQ_CTRL3;
+- if (queue >= 4)
++ ctrl2 = readl(ioaddr + XGMAC_RXQ_CTRL2);
++ ctrl3 = readl(ioaddr + XGMAC_RXQ_CTRL3);
++
++ /* The software must ensure that the same priority
++ * is not mapped to multiple Rx queues
++ */
++ for (i = 0; i < 4; i++)
++ clear_mask |= ((prio << XGMAC_PSRQ_SHIFT(i)) &
++ XGMAC_PSRQ(i));
++
++ ctrl2 &= ~clear_mask;
++ ctrl3 &= ~clear_mask;
++
++ /* First assign new priorities to a queue, then
++ * clear them from others queues
++ */
++ if (queue < 4) {
++ ctrl2 |= (prio << XGMAC_PSRQ_SHIFT(queue)) &
++ XGMAC_PSRQ(queue);
++
++ writel(ctrl2, ioaddr + XGMAC_RXQ_CTRL2);
++ writel(ctrl3, ioaddr + XGMAC_RXQ_CTRL3);
++ } else {
+ queue -= 4;
+
+- value = readl(ioaddr + reg);
+- value &= ~XGMAC_PSRQ(queue);
+- value |= (prio << XGMAC_PSRQ_SHIFT(queue)) & XGMAC_PSRQ(queue);
++ ctrl3 |= (prio << XGMAC_PSRQ_SHIFT(queue)) &
++ XGMAC_PSRQ(queue);
+
+- writel(value, ioaddr + reg);
++ writel(ctrl3, ioaddr + XGMAC_RXQ_CTRL3);
++ writel(ctrl2, ioaddr + XGMAC_RXQ_CTRL2);
++ }
+ }
+
+ static void dwxgmac2_tx_queue_prio(struct mac_device_info *hw, u32 prio,
+diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
+index 29997e4b2d6ca..8cddc9ddb3392 100644
+--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
+@@ -20,6 +20,8 @@
+ #include "txgbe_phy.h"
+ #include "txgbe_hw.h"
+
++#define TXGBE_I2C_CLK_DEV_NAME "i2c_dw"
++
+ static int txgbe_swnodes_register(struct txgbe *txgbe)
+ {
+ struct txgbe_nodes *nodes = &txgbe->nodes;
+@@ -556,8 +558,8 @@ static int txgbe_clock_register(struct txgbe *txgbe)
+ char clk_name[32];
+ struct clk *clk;
+
+- snprintf(clk_name, sizeof(clk_name), "i2c_dw.%d",
+- pci_dev_id(pdev));
++ snprintf(clk_name, sizeof(clk_name), "%s.%d",
++ TXGBE_I2C_CLK_DEV_NAME, pci_dev_id(pdev));
+
+ clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000);
+ if (IS_ERR(clk))
+@@ -619,7 +621,7 @@ static int txgbe_i2c_register(struct txgbe *txgbe)
+
+ info.parent = &pdev->dev;
+ info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]);
+- info.name = "i2c_designware";
++ info.name = TXGBE_I2C_CLK_DEV_NAME;
+ info.id = pci_dev_id(pdev);
+
+ info.res = &DEFINE_RES_IRQ(pdev->irq);
+diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
+index dad720138baaf..1f950c824418f 100644
+--- a/drivers/net/phy/micrel.c
++++ b/drivers/net/phy/micrel.c
+@@ -2416,6 +2416,7 @@ static int lan8814_hwtstamp(struct mii_timestamper *mii_ts,
+ struct lan8814_ptp_rx_ts *rx_ts, *tmp;
+ int txcfg = 0, rxcfg = 0;
+ int pkt_ts_enable;
++ int tx_mod;
+
+ ptp_priv->hwts_tx_type = config->tx_type;
+ ptp_priv->rx_filter = config->rx_filter;
+@@ -2462,9 +2463,14 @@ static int lan8814_hwtstamp(struct mii_timestamper *mii_ts,
+ lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_RX_TIMESTAMP_EN, pkt_ts_enable);
+ lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_TIMESTAMP_EN, pkt_ts_enable);
+
+- if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ONESTEP_SYNC)
++ tx_mod = lanphy_read_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD);
++ if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ONESTEP_SYNC) {
+ lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD,
+- PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_);
++ tx_mod | PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_);
++ } else if (ptp_priv->hwts_tx_type == HWTSTAMP_TX_ON) {
++ lanphy_write_page_reg(ptp_priv->phydev, 5, PTP_TX_MOD,
++ tx_mod & ~PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_);
++ }
+
+ if (config->rx_filter != HWTSTAMP_FILTER_NONE)
+ lan8814_config_ts_intr(ptp_priv->phydev, true);
+@@ -2522,7 +2528,7 @@ static void lan8814_txtstamp(struct mii_timestamper *mii_ts,
+ }
+ }
+
+-static void lan8814_get_sig_rx(struct sk_buff *skb, u16 *sig)
++static bool lan8814_get_sig_rx(struct sk_buff *skb, u16 *sig)
+ {
+ struct ptp_header *ptp_header;
+ u32 type;
+@@ -2532,7 +2538,11 @@ static void lan8814_get_sig_rx(struct sk_buff *skb, u16 *sig)
+ ptp_header = ptp_parse_header(skb, type);
+ skb_pull_inline(skb, ETH_HLEN);
+
++ if (!ptp_header)
++ return false;
++
+ *sig = (__force u16)(ntohs(ptp_header->sequence_id));
++ return true;
+ }
+
+ static bool lan8814_match_rx_skb(struct kszphy_ptp_priv *ptp_priv,
+@@ -2544,7 +2554,8 @@ static bool lan8814_match_rx_skb(struct kszphy_ptp_priv *ptp_priv,
+ bool ret = false;
+ u16 skb_sig;
+
+- lan8814_get_sig_rx(skb, &skb_sig);
++ if (!lan8814_get_sig_rx(skb, &skb_sig))
++ return ret;
+
+ /* Iterate over all RX timestamps and match it with the received skbs */
+ spin_lock_irqsave(&ptp_priv->rx_ts_lock, flags);
+@@ -2824,7 +2835,7 @@ static int lan8814_ptpci_adjfine(struct ptp_clock_info *ptpci, long scaled_ppm)
+ return 0;
+ }
+
+-static void lan8814_get_sig_tx(struct sk_buff *skb, u16 *sig)
++static bool lan8814_get_sig_tx(struct sk_buff *skb, u16 *sig)
+ {
+ struct ptp_header *ptp_header;
+ u32 type;
+@@ -2832,7 +2843,11 @@ static void lan8814_get_sig_tx(struct sk_buff *skb, u16 *sig)
+ type = ptp_classify_raw(skb);
+ ptp_header = ptp_parse_header(skb, type);
+
++ if (!ptp_header)
++ return false;
++
+ *sig = (__force u16)(ntohs(ptp_header->sequence_id));
++ return true;
+ }
+
+ static void lan8814_match_tx_skb(struct kszphy_ptp_priv *ptp_priv,
+@@ -2846,7 +2861,8 @@ static void lan8814_match_tx_skb(struct kszphy_ptp_priv *ptp_priv,
+
+ spin_lock_irqsave(&ptp_priv->tx_queue.lock, flags);
+ skb_queue_walk_safe(&ptp_priv->tx_queue, skb, skb_tmp) {
+- lan8814_get_sig_tx(skb, &skb_sig);
++ if (!lan8814_get_sig_tx(skb, &skb_sig))
++ continue;
+
+ if (memcmp(&skb_sig, &seq_id, sizeof(seq_id)))
+ continue;
+@@ -2900,7 +2916,8 @@ static bool lan8814_match_skb(struct kszphy_ptp_priv *ptp_priv,
+
+ spin_lock_irqsave(&ptp_priv->rx_queue.lock, flags);
+ skb_queue_walk_safe(&ptp_priv->rx_queue, skb, skb_tmp) {
+- lan8814_get_sig_rx(skb, &skb_sig);
++ if (!lan8814_get_sig_rx(skb, &skb_sig))
++ continue;
+
+ if (memcmp(&skb_sig, &rx_ts->seq_id, sizeof(rx_ts->seq_id)))
+ continue;
+diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
+index d837c18874161..e0e9b4c53cb02 100644
+--- a/drivers/net/usb/ax88179_178a.c
++++ b/drivers/net/usb/ax88179_178a.c
+@@ -1273,6 +1273,8 @@ static void ax88179_get_mac_addr(struct usbnet *dev)
+
+ if (is_valid_ether_addr(mac)) {
+ eth_hw_addr_set(dev->net, mac);
++ if (!is_local_ether_addr(mac))
++ dev->net->addr_assign_type = NET_ADDR_PERM;
+ } else {
+ netdev_info(dev->net, "invalid MAC address, using random\n");
+ eth_hw_addr_random(dev->net);
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rfi.c b/drivers/net/wireless/intel/iwlwifi/mvm/rfi.c
+index 2ecd32bed752f..045c862a8fc4f 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/rfi.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rfi.c
+@@ -132,14 +132,18 @@ struct iwl_rfi_freq_table_resp_cmd *iwl_rfi_get_freq_table(struct iwl_mvm *mvm)
+ if (ret)
+ return ERR_PTR(ret);
+
+- if (WARN_ON_ONCE(iwl_rx_packet_payload_len(cmd.resp_pkt) != resp_size))
++ if (WARN_ON_ONCE(iwl_rx_packet_payload_len(cmd.resp_pkt) !=
++ resp_size)) {
++ iwl_free_resp(&cmd);
+ return ERR_PTR(-EIO);
++ }
+
+ resp = kmemdup(cmd.resp_pkt->data, resp_size, GFP_KERNEL);
++ iwl_free_resp(&cmd);
++
+ if (!resp)
+ return ERR_PTR(-ENOMEM);
+
+- iwl_free_resp(&cmd);
+ return resp;
+ }
+
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+index 7bf2a5947e5e9..481dfbbe46162 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c
+@@ -236,21 +236,13 @@ static void iwl_mvm_add_rtap_sniffer_config(struct iwl_mvm *mvm,
+ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
+ struct napi_struct *napi,
+ struct sk_buff *skb, int queue,
+- struct ieee80211_sta *sta,
+- struct ieee80211_link_sta *link_sta)
++ struct ieee80211_sta *sta)
+ {
+ if (unlikely(iwl_mvm_check_pn(mvm, skb, queue, sta))) {
+ kfree_skb(skb);
+ return;
+ }
+
+- if (sta && sta->valid_links && link_sta) {
+- struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
+-
+- rx_status->link_valid = 1;
+- rx_status->link_id = link_sta->link_id;
+- }
+-
+ ieee80211_rx_napi(mvm->hw, sta, skb, napi);
+ }
+
+@@ -587,7 +579,7 @@ static void iwl_mvm_release_frames(struct iwl_mvm *mvm,
+ while ((skb = __skb_dequeue(skb_list))) {
+ iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb,
+ reorder_buf->queue,
+- sta, NULL /* FIXME */);
++ sta);
+ reorder_buf->num_stored--;
+ }
+ }
+@@ -2214,6 +2206,11 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
+ if (IS_ERR(sta))
+ sta = NULL;
+ link_sta = rcu_dereference(mvm->fw_id_to_link_sta[id]);
++
++ if (sta && sta->valid_links && link_sta) {
++ rx_status->link_valid = 1;
++ rx_status->link_id = link_sta->link_id;
++ }
+ }
+ } else if (!is_multicast_ether_addr(hdr->addr2)) {
+ /*
+@@ -2357,8 +2354,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
+ !(desc->amsdu_info & IWL_RX_MPDU_AMSDU_LAST_SUBFRAME))
+ rx_status->flag |= RX_FLAG_AMSDU_MORE;
+
+- iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta,
+- link_sta);
++ iwl_mvm_pass_packet_to_mac80211(mvm, napi, skb, queue, sta);
+ }
+ out:
+ rcu_read_unlock();
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+index da00ef6e4fbcf..3d96a824dbd65 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c
+@@ -898,9 +898,8 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm,
+ struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ struct iwl_mvm_session_prot_notif *notif = (void *)pkt->data;
+ unsigned int ver =
+- iwl_fw_lookup_cmd_ver(mvm->fw,
+- WIDE_ID(MAC_CONF_GROUP,
+- SESSION_PROTECTION_CMD), 2);
++ iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP,
++ SESSION_PROTECTION_NOTIF, 2);
+ int id = le32_to_cpu(notif->mac_link_id);
+ struct ieee80211_vif *vif;
+ struct iwl_mvm_vif *mvmvif;
+diff --git a/drivers/net/wwan/t7xx/t7xx_cldma.c b/drivers/net/wwan/t7xx/t7xx_cldma.c
+index 9f43f256db1d0..f0a4783baf1f3 100644
+--- a/drivers/net/wwan/t7xx/t7xx_cldma.c
++++ b/drivers/net/wwan/t7xx/t7xx_cldma.c
+@@ -106,7 +106,7 @@ bool t7xx_cldma_tx_addr_is_set(struct t7xx_cldma_hw *hw_info, unsigned int qno)
+ {
+ u32 offset = REG_CLDMA_UL_START_ADDRL_0 + qno * ADDR_SIZE;
+
+- return ioread64(hw_info->ap_pdn_base + offset);
++ return ioread64_lo_hi(hw_info->ap_pdn_base + offset);
+ }
+
+ void t7xx_cldma_hw_set_start_addr(struct t7xx_cldma_hw *hw_info, unsigned int qno, u64 address,
+@@ -117,7 +117,7 @@ void t7xx_cldma_hw_set_start_addr(struct t7xx_cldma_hw *hw_info, unsigned int qn
+
+ reg = tx_rx == MTK_RX ? hw_info->ap_ao_base + REG_CLDMA_DL_START_ADDRL_0 :
+ hw_info->ap_pdn_base + REG_CLDMA_UL_START_ADDRL_0;
+- iowrite64(address, reg + offset);
++ iowrite64_lo_hi(address, reg + offset);
+ }
+
+ void t7xx_cldma_hw_resume_queue(struct t7xx_cldma_hw *hw_info, unsigned int qno,
+diff --git a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c
+index cc70360364b7d..554ba4669cc8d 100644
+--- a/drivers/net/wwan/t7xx/t7xx_hif_cldma.c
++++ b/drivers/net/wwan/t7xx/t7xx_hif_cldma.c
+@@ -139,8 +139,9 @@ static int t7xx_cldma_gpd_rx_from_q(struct cldma_queue *queue, int budget, bool
+ return -ENODEV;
+ }
+
+- gpd_addr = ioread64(hw_info->ap_pdn_base + REG_CLDMA_DL_CURRENT_ADDRL_0 +
+- queue->index * sizeof(u64));
++ gpd_addr = ioread64_lo_hi(hw_info->ap_pdn_base +
++ REG_CLDMA_DL_CURRENT_ADDRL_0 +
++ queue->index * sizeof(u64));
+ if (req->gpd_addr == gpd_addr || hwo_polling_count++ >= 100)
+ return 0;
+
+@@ -318,8 +319,8 @@ static void t7xx_cldma_txq_empty_hndl(struct cldma_queue *queue)
+ struct t7xx_cldma_hw *hw_info = &md_ctrl->hw_info;
+
+ /* Check current processing TGPD, 64-bit address is in a table by Q index */
+- ul_curr_addr = ioread64(hw_info->ap_pdn_base + REG_CLDMA_UL_CURRENT_ADDRL_0 +
+- queue->index * sizeof(u64));
++ ul_curr_addr = ioread64_lo_hi(hw_info->ap_pdn_base + REG_CLDMA_UL_CURRENT_ADDRL_0 +
++ queue->index * sizeof(u64));
+ if (req->gpd_addr != ul_curr_addr) {
+ spin_unlock_irqrestore(&md_ctrl->cldma_lock, flags);
+ dev_err(md_ctrl->dev, "CLDMA%d queue %d is not empty\n",
+diff --git a/drivers/net/wwan/t7xx/t7xx_pcie_mac.c b/drivers/net/wwan/t7xx/t7xx_pcie_mac.c
+index 76da4c15e3de1..f071ec7ff23d5 100644
+--- a/drivers/net/wwan/t7xx/t7xx_pcie_mac.c
++++ b/drivers/net/wwan/t7xx/t7xx_pcie_mac.c
+@@ -75,7 +75,7 @@ static void t7xx_pcie_mac_atr_tables_dis(void __iomem *pbase, enum t7xx_atr_src_
+ for (i = 0; i < ATR_TABLE_NUM_PER_ATR; i++) {
+ offset = ATR_PORT_OFFSET * port + ATR_TABLE_OFFSET * i;
+ reg = pbase + ATR_PCIE_WIN0_T0_ATR_PARAM_SRC_ADDR + offset;
+- iowrite64(0, reg);
++ iowrite64_lo_hi(0, reg);
+ }
+ }
+
+@@ -112,17 +112,17 @@ static int t7xx_pcie_mac_atr_cfg(struct t7xx_pci_dev *t7xx_dev, struct t7xx_atr_
+
+ reg = pbase + ATR_PCIE_WIN0_T0_TRSL_ADDR + offset;
+ value = cfg->trsl_addr & ATR_PCIE_WIN0_ADDR_ALGMT;
+- iowrite64(value, reg);
++ iowrite64_lo_hi(value, reg);
+
+ reg = pbase + ATR_PCIE_WIN0_T0_TRSL_PARAM + offset;
+ iowrite32(cfg->trsl_id, reg);
+
+ reg = pbase + ATR_PCIE_WIN0_T0_ATR_PARAM_SRC_ADDR + offset;
+ value = (cfg->src_addr & ATR_PCIE_WIN0_ADDR_ALGMT) | (atr_size << 1) | BIT(0);
+- iowrite64(value, reg);
++ iowrite64_lo_hi(value, reg);
+
+ /* Ensure ATR is set */
+- ioread64(reg);
++ ioread64_lo_hi(reg);
+ return 0;
+ }
+
+diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
+index ad29f370034e4..8d2aee88526c6 100644
+--- a/drivers/net/xen-netfront.c
++++ b/drivers/net/xen-netfront.c
+@@ -285,6 +285,7 @@ static struct sk_buff *xennet_alloc_one_rx_buffer(struct netfront_queue *queue)
+ return NULL;
+ }
+ skb_add_rx_frag(skb, 0, page, 0, 0, PAGE_SIZE);
++ skb_mark_for_recycle(skb);
+
+ /* Align ip header to a 16 bytes boundary */
+ skb_reserve(skb, NET_IP_ALIGN);
+diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
+index 3bf27052832f3..4d57a4e341054 100644
+--- a/drivers/of/dynamic.c
++++ b/drivers/of/dynamic.c
+@@ -9,6 +9,7 @@
+
+ #define pr_fmt(fmt) "OF: " fmt
+
++#include <linux/device.h>
+ #include <linux/of.h>
+ #include <linux/spinlock.h>
+ #include <linux/slab.h>
+@@ -667,6 +668,17 @@ void of_changeset_destroy(struct of_changeset *ocs)
+ {
+ struct of_changeset_entry *ce, *cen;
+
++ /*
++ * When a device is deleted, the device links to/from it are also queued
++ * for deletion. Until these device links are freed, the devices
++ * themselves aren't freed. If the device being deleted is due to an
++ * overlay change, this device might be holding a reference to a device
++ * node that will be freed. So, wait until all already pending device
++ * links are deleted before freeing a device node. This ensures we don't
++ * free any device node that has a non-zero reference count.
++ */
++ device_link_wait_removal();
++
+ list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node)
+ __of_changeset_entry_destroy(ce);
+ }
+diff --git a/drivers/of/module.c b/drivers/of/module.c
+index 0e8aa974f0f2b..f58e624953a20 100644
+--- a/drivers/of/module.c
++++ b/drivers/of/module.c
+@@ -16,6 +16,14 @@ ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
+ ssize_t csize;
+ ssize_t tsize;
+
++ /*
++ * Prevent a kernel oops in vsnprintf() -- it only allows passing a
++ * NULL ptr when the length is also 0. Also filter out the negative
++ * lengths...
++ */
++ if ((len > 0 && !str) || len < 0)
++ return -EINVAL;
++
+ /* Name & Type */
+ /* %p eats all alphanum characters, so %c must be used here */
+ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
+diff --git a/drivers/perf/riscv_pmu.c b/drivers/perf/riscv_pmu.c
+index c78a6fd6c57f6..b4efdddb2ad91 100644
+--- a/drivers/perf/riscv_pmu.c
++++ b/drivers/perf/riscv_pmu.c
+@@ -313,6 +313,10 @@ static int riscv_pmu_event_init(struct perf_event *event)
+ u64 event_config = 0;
+ uint64_t cmask;
+
++ /* driver does not support branch stack sampling */
++ if (has_branch_stack(event))
++ return -EOPNOTSUPP;
++
+ hwc->flags = 0;
+ mapped_event = rvpmu->event_map(event, &event_config);
+ if (mapped_event < 0) {
+diff --git a/drivers/pinctrl/aspeed/Makefile b/drivers/pinctrl/aspeed/Makefile
+index 489ea1778353f..db2a7600ae2bd 100644
+--- a/drivers/pinctrl/aspeed/Makefile
++++ b/drivers/pinctrl/aspeed/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ # Aspeed pinctrl support
+
+-ccflags-y += $(call cc-option,-Woverride-init)
++ccflags-y += -Woverride-init
+ obj-$(CONFIG_PINCTRL_ASPEED) += pinctrl-aspeed.o pinmux-aspeed.o
+ obj-$(CONFIG_PINCTRL_ASPEED_G4) += pinctrl-aspeed-g4.o
+ obj-$(CONFIG_PINCTRL_ASPEED_G5) += pinctrl-aspeed-g5.o
+diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
+index cf8506d0f185c..601d00e09de4a 100644
+--- a/drivers/s390/net/qeth_core_main.c
++++ b/drivers/s390/net/qeth_core_main.c
+@@ -1179,6 +1179,20 @@ static int qeth_check_irb_error(struct qeth_card *card, struct ccw_device *cdev,
+ }
+ }
+
++/**
++ * qeth_irq() - qeth interrupt handler
++ * @cdev: ccw device
++ * @intparm: expect pointer to iob
++ * @irb: Interruption Response Block
++ *
++ * In the good path:
++ * corresponding qeth channel is locked with last used iob as active_cmd.
++ * But this function is also called for error interrupts.
++ *
++ * Caller ensures that:
++ * Interrupts are disabled; ccw device lock is held;
++ *
++ */
+ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
+ struct irb *irb)
+ {
+@@ -1220,11 +1234,10 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
+ iob = (struct qeth_cmd_buffer *) (addr_t)intparm;
+ }
+
+- qeth_unlock_channel(card, channel);
+-
+ rc = qeth_check_irb_error(card, cdev, irb);
+ if (rc) {
+ /* IO was terminated, free its resources. */
++ qeth_unlock_channel(card, channel);
+ if (iob)
+ qeth_cancel_cmd(iob, rc);
+ return;
+@@ -1268,6 +1281,7 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
+ rc = qeth_get_problem(card, cdev, irb);
+ if (rc) {
+ card->read_or_write_problem = 1;
++ qeth_unlock_channel(card, channel);
+ if (iob)
+ qeth_cancel_cmd(iob, rc);
+ qeth_clear_ipacmd_list(card);
+@@ -1276,6 +1290,26 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
+ }
+ }
+
++ if (scsw_cmd_is_valid_cc(&irb->scsw) && irb->scsw.cmd.cc == 1 && iob) {
++ /* channel command hasn't started: retry.
++ * active_cmd is still set to last iob
++ */
++ QETH_CARD_TEXT(card, 2, "irqcc1");
++ rc = ccw_device_start_timeout(cdev, __ccw_from_cmd(iob),
++ (addr_t)iob, 0, 0, iob->timeout);
++ if (rc) {
++ QETH_DBF_MESSAGE(2,
++ "ccw retry on %x failed, rc = %i\n",
++ CARD_DEVID(card), rc);
++ QETH_CARD_TEXT_(card, 2, " err%d", rc);
++ qeth_unlock_channel(card, channel);
++ qeth_cancel_cmd(iob, rc);
++ }
++ return;
++ }
++
++ qeth_unlock_channel(card, channel);
++
+ if (iob) {
+ /* sanity check: */
+ if (irb->scsw.cmd.count > iob->length) {
+diff --git a/drivers/scsi/myrb.c b/drivers/scsi/myrb.c
+index ca2e932dd9b70..f684eb5e04898 100644
+--- a/drivers/scsi/myrb.c
++++ b/drivers/scsi/myrb.c
+@@ -1775,9 +1775,9 @@ static ssize_t raid_state_show(struct device *dev,
+
+ name = myrb_devstate_name(ldev_info->state);
+ if (name)
+- ret = snprintf(buf, 32, "%s\n", name);
++ ret = snprintf(buf, 64, "%s\n", name);
+ else
+- ret = snprintf(buf, 32, "Invalid (%02X)\n",
++ ret = snprintf(buf, 64, "Invalid (%02X)\n",
+ ldev_info->state);
+ } else {
+ struct myrb_pdev_state *pdev_info = sdev->hostdata;
+@@ -1796,9 +1796,9 @@ static ssize_t raid_state_show(struct device *dev,
+ else
+ name = myrb_devstate_name(pdev_info->state);
+ if (name)
+- ret = snprintf(buf, 32, "%s\n", name);
++ ret = snprintf(buf, 64, "%s\n", name);
+ else
+- ret = snprintf(buf, 32, "Invalid (%02X)\n",
++ ret = snprintf(buf, 64, "Invalid (%02X)\n",
+ pdev_info->state);
+ }
+ return ret;
+@@ -1886,11 +1886,11 @@ static ssize_t raid_level_show(struct device *dev,
+
+ name = myrb_raidlevel_name(ldev_info->raid_level);
+ if (!name)
+- return snprintf(buf, 32, "Invalid (%02X)\n",
++ return snprintf(buf, 64, "Invalid (%02X)\n",
+ ldev_info->state);
+- return snprintf(buf, 32, "%s\n", name);
++ return snprintf(buf, 64, "%s\n", name);
+ }
+- return snprintf(buf, 32, "Physical Drive\n");
++ return snprintf(buf, 64, "Physical Drive\n");
+ }
+ static DEVICE_ATTR_RO(raid_level);
+
+@@ -1903,15 +1903,15 @@ static ssize_t rebuild_show(struct device *dev,
+ unsigned char status;
+
+ if (sdev->channel < myrb_logical_channel(sdev->host))
+- return snprintf(buf, 32, "physical device - not rebuilding\n");
++ return snprintf(buf, 64, "physical device - not rebuilding\n");
+
+ status = myrb_get_rbld_progress(cb, &rbld_buf);
+
+ if (rbld_buf.ldev_num != sdev->id ||
+ status != MYRB_STATUS_SUCCESS)
+- return snprintf(buf, 32, "not rebuilding\n");
++ return snprintf(buf, 64, "not rebuilding\n");
+
+- return snprintf(buf, 32, "rebuilding block %u of %u\n",
++ return snprintf(buf, 64, "rebuilding block %u of %u\n",
+ rbld_buf.ldev_size - rbld_buf.blocks_left,
+ rbld_buf.ldev_size);
+ }
+diff --git a/drivers/scsi/myrs.c b/drivers/scsi/myrs.c
+index a1eec65a9713f..e824be9d9bbb9 100644
+--- a/drivers/scsi/myrs.c
++++ b/drivers/scsi/myrs.c
+@@ -947,9 +947,9 @@ static ssize_t raid_state_show(struct device *dev,
+
+ name = myrs_devstate_name(ldev_info->dev_state);
+ if (name)
+- ret = snprintf(buf, 32, "%s\n", name);
++ ret = snprintf(buf, 64, "%s\n", name);
+ else
+- ret = snprintf(buf, 32, "Invalid (%02X)\n",
++ ret = snprintf(buf, 64, "Invalid (%02X)\n",
+ ldev_info->dev_state);
+ } else {
+ struct myrs_pdev_info *pdev_info;
+@@ -958,9 +958,9 @@ static ssize_t raid_state_show(struct device *dev,
+ pdev_info = sdev->hostdata;
+ name = myrs_devstate_name(pdev_info->dev_state);
+ if (name)
+- ret = snprintf(buf, 32, "%s\n", name);
++ ret = snprintf(buf, 64, "%s\n", name);
+ else
+- ret = snprintf(buf, 32, "Invalid (%02X)\n",
++ ret = snprintf(buf, 64, "Invalid (%02X)\n",
+ pdev_info->dev_state);
+ }
+ return ret;
+@@ -1066,13 +1066,13 @@ static ssize_t raid_level_show(struct device *dev,
+ ldev_info = sdev->hostdata;
+ name = myrs_raid_level_name(ldev_info->raid_level);
+ if (!name)
+- return snprintf(buf, 32, "Invalid (%02X)\n",
++ return snprintf(buf, 64, "Invalid (%02X)\n",
+ ldev_info->dev_state);
+
+ } else
+ name = myrs_raid_level_name(MYRS_RAID_PHYSICAL);
+
+- return snprintf(buf, 32, "%s\n", name);
++ return snprintf(buf, 64, "%s\n", name);
+ }
+ static DEVICE_ATTR_RO(raid_level);
+
+@@ -1086,7 +1086,7 @@ static ssize_t rebuild_show(struct device *dev,
+ unsigned char status;
+
+ if (sdev->channel < cs->ctlr_info->physchan_present)
+- return snprintf(buf, 32, "physical device - not rebuilding\n");
++ return snprintf(buf, 64, "physical device - not rebuilding\n");
+
+ ldev_info = sdev->hostdata;
+ ldev_num = ldev_info->ldev_num;
+@@ -1098,11 +1098,11 @@ static ssize_t rebuild_show(struct device *dev,
+ return -EIO;
+ }
+ if (ldev_info->rbld_active) {
+- return snprintf(buf, 32, "rebuilding block %zu of %zu\n",
++ return snprintf(buf, 64, "rebuilding block %zu of %zu\n",
+ (size_t)ldev_info->rbld_lba,
+ (size_t)ldev_info->cfg_devsize);
+ } else
+- return snprintf(buf, 32, "not rebuilding\n");
++ return snprintf(buf, 64, "not rebuilding\n");
+ }
+
+ static ssize_t rebuild_store(struct device *dev,
+@@ -1190,7 +1190,7 @@ static ssize_t consistency_check_show(struct device *dev,
+ unsigned short ldev_num;
+
+ if (sdev->channel < cs->ctlr_info->physchan_present)
+- return snprintf(buf, 32, "physical device - not checking\n");
++ return snprintf(buf, 64, "physical device - not checking\n");
+
+ ldev_info = sdev->hostdata;
+ if (!ldev_info)
+@@ -1198,11 +1198,11 @@ static ssize_t consistency_check_show(struct device *dev,
+ ldev_num = ldev_info->ldev_num;
+ myrs_get_ldev_info(cs, ldev_num, ldev_info);
+ if (ldev_info->cc_active)
+- return snprintf(buf, 32, "checking block %zu of %zu\n",
++ return snprintf(buf, 64, "checking block %zu of %zu\n",
+ (size_t)ldev_info->cc_lba,
+ (size_t)ldev_info->cfg_devsize);
+ else
+- return snprintf(buf, 32, "not checking\n");
++ return snprintf(buf, 64, "not checking\n");
+ }
+
+ static ssize_t consistency_check_store(struct device *dev,
+diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
+index d5d3eea006c13..35200a7a73553 100644
+--- a/drivers/scsi/sd.c
++++ b/drivers/scsi/sd.c
+@@ -3757,7 +3757,7 @@ static int sd_probe(struct device *dev)
+
+ error = device_add_disk(dev, gd, NULL);
+ if (error) {
+- put_device(&sdkp->disk_dev);
++ device_unregister(&sdkp->disk_dev);
+ put_disk(gd);
+ goto out;
+ }
+diff --git a/drivers/spi/spi-pci1xxxx.c b/drivers/spi/spi-pci1xxxx.c
+index 5b2d3e4e21b7a..5a42266820522 100644
+--- a/drivers/spi/spi-pci1xxxx.c
++++ b/drivers/spi/spi-pci1xxxx.c
+@@ -275,6 +275,8 @@ static int pci1xxxx_spi_probe(struct pci_dev *pdev, const struct pci_device_id *
+ spi_bus->spi_int[iter] = devm_kzalloc(&pdev->dev,
+ sizeof(struct pci1xxxx_spi_internal),
+ GFP_KERNEL);
++ if (!spi_bus->spi_int[iter])
++ return -ENOMEM;
+ spi_sub_ptr = spi_bus->spi_int[iter];
+ spi_sub_ptr->spi_host = devm_spi_alloc_host(dev, sizeof(struct spi_controller));
+ if (!spi_sub_ptr->spi_host)
+diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c
+index 0e48ffd499b9f..652eadbefe24c 100644
+--- a/drivers/spi/spi-s3c64xx.c
++++ b/drivers/spi/spi-s3c64xx.c
+@@ -3,19 +3,20 @@
+ // Copyright (c) 2009 Samsung Electronics Co., Ltd.
+ // Jaswinder Singh <jassi.brar@samsung.com>
+
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/interrupt.h>
+-#include <linux/delay.h>
++#include <linux/bitops.h>
++#include <linux/bits.h>
+ #include <linux/clk.h>
++#include <linux/delay.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/dmaengine.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/platform_data/spi-s3c64xx.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/spi/spi.h>
+-#include <linux/of.h>
+-
+-#include <linux/platform_data/spi-s3c64xx.h>
+
+ #define MAX_SPI_PORTS 12
+ #define S3C64XX_SPI_QUIRK_CS_AUTO (1 << 1)
+@@ -76,6 +77,7 @@
+ #define S3C64XX_SPI_INT_RX_FIFORDY_EN (1<<1)
+ #define S3C64XX_SPI_INT_TX_FIFORDY_EN (1<<0)
+
++#define S3C64XX_SPI_ST_TX_FIFO_LVL_SHIFT 6
+ #define S3C64XX_SPI_ST_RX_OVERRUN_ERR (1<<5)
+ #define S3C64XX_SPI_ST_RX_UNDERRUN_ERR (1<<4)
+ #define S3C64XX_SPI_ST_TX_OVERRUN_ERR (1<<3)
+@@ -106,9 +108,11 @@
+ #define FIFO_LVL_MASK(i) ((i)->port_conf->fifo_lvl_mask[i->port_id])
+ #define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & \
+ (1 << (i)->port_conf->tx_st_done)) ? 1 : 0)
+-#define TX_FIFO_LVL(v, i) (((v) >> 6) & FIFO_LVL_MASK(i))
+-#define RX_FIFO_LVL(v, i) (((v) >> (i)->port_conf->rx_lvl_offset) & \
+- FIFO_LVL_MASK(i))
++#define TX_FIFO_LVL(v, sdd) (((v) & (sdd)->tx_fifomask) >> \
++ __ffs((sdd)->tx_fifomask))
++#define RX_FIFO_LVL(v, sdd) (((v) & (sdd)->rx_fifomask) >> \
++ __ffs((sdd)->rx_fifomask))
++#define FIFO_DEPTH(i) ((FIFO_LVL_MASK(i) >> 1) + 1)
+
+ #define S3C64XX_SPI_MAX_TRAILCNT 0x3ff
+ #define S3C64XX_SPI_TRAILCNT_OFF 19
+@@ -133,6 +137,10 @@ struct s3c64xx_spi_dma_data {
+ * struct s3c64xx_spi_port_config - SPI Controller hardware info
+ * @fifo_lvl_mask: Bit-mask for {TX|RX}_FIFO_LVL bits in SPI_STATUS register.
+ * @rx_lvl_offset: Bit offset of RX_FIFO_LVL bits in SPI_STATUS regiter.
++ * @rx_fifomask: SPI_STATUS.RX_FIFO_LVL mask. Shifted mask defining the field's
++ * length and position.
++ * @tx_fifomask: SPI_STATUS.TX_FIFO_LVL mask. Shifted mask defining the field's
++ * length and position.
+ * @tx_st_done: Bit offset of TX_DONE bit in SPI_STATUS regiter.
+ * @clk_div: Internal clock divider
+ * @quirks: Bitmask of known quirks
+@@ -150,6 +158,8 @@ struct s3c64xx_spi_dma_data {
+ struct s3c64xx_spi_port_config {
+ int fifo_lvl_mask[MAX_SPI_PORTS];
+ int rx_lvl_offset;
++ u32 rx_fifomask;
++ u32 tx_fifomask;
+ int tx_st_done;
+ int quirks;
+ int clk_div;
+@@ -179,6 +189,11 @@ struct s3c64xx_spi_port_config {
+ * @tx_dma: Local transmit DMA data (e.g. chan and direction)
+ * @port_conf: Local SPI port configuartion data
+ * @port_id: Port identification number
++ * @fifo_depth: depth of the FIFO.
++ * @rx_fifomask: SPI_STATUS.RX_FIFO_LVL mask. Shifted mask defining the field's
++ * length and position.
++ * @tx_fifomask: SPI_STATUS.TX_FIFO_LVL mask. Shifted mask defining the field's
++ * length and position.
+ */
+ struct s3c64xx_spi_driver_data {
+ void __iomem *regs;
+@@ -198,6 +213,9 @@ struct s3c64xx_spi_driver_data {
+ struct s3c64xx_spi_dma_data tx_dma;
+ const struct s3c64xx_spi_port_config *port_conf;
+ unsigned int port_id;
++ unsigned int fifo_depth;
++ u32 rx_fifomask;
++ u32 tx_fifomask;
+ };
+
+ static void s3c64xx_flush_fifo(struct s3c64xx_spi_driver_data *sdd)
+@@ -405,12 +423,10 @@ static bool s3c64xx_spi_can_dma(struct spi_controller *host,
+ {
+ struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host);
+
+- if (sdd->rx_dma.ch && sdd->tx_dma.ch) {
+- return xfer->len > (FIFO_LVL_MASK(sdd) >> 1) + 1;
+- } else {
+- return false;
+- }
++ if (sdd->rx_dma.ch && sdd->tx_dma.ch)
++ return xfer->len >= sdd->fifo_depth;
+
++ return false;
+ }
+
+ static int s3c64xx_enable_datapath(struct s3c64xx_spi_driver_data *sdd,
+@@ -495,9 +511,7 @@ static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd,
+ void __iomem *regs = sdd->regs;
+ unsigned long val = 1;
+ u32 status;
+-
+- /* max fifo depth available */
+- u32 max_fifo = (FIFO_LVL_MASK(sdd) >> 1) + 1;
++ u32 max_fifo = sdd->fifo_depth;
+
+ if (timeout_ms)
+ val = msecs_to_loops(timeout_ms);
+@@ -604,7 +618,7 @@ static int s3c64xx_wait_for_pio(struct s3c64xx_spi_driver_data *sdd,
+ * For any size less than the fifo size the below code is
+ * executed atleast once.
+ */
+- loops = xfer->len / ((FIFO_LVL_MASK(sdd) >> 1) + 1);
++ loops = xfer->len / sdd->fifo_depth;
+ buf = xfer->rx_buf;
+ do {
+ /* wait for data to be received in the fifo */
+@@ -741,7 +755,7 @@ static int s3c64xx_spi_transfer_one(struct spi_controller *host,
+ struct spi_transfer *xfer)
+ {
+ struct s3c64xx_spi_driver_data *sdd = spi_controller_get_devdata(host);
+- const unsigned int fifo_len = (FIFO_LVL_MASK(sdd) >> 1) + 1;
++ const unsigned int fifo_len = sdd->fifo_depth;
+ const void *tx_buf = NULL;
+ void *rx_buf = NULL;
+ int target_len = 0, origin_len = 0;
+@@ -769,10 +783,9 @@ static int s3c64xx_spi_transfer_one(struct spi_controller *host,
+ return status;
+ }
+
+- if (!is_polling(sdd) && (xfer->len > fifo_len) &&
++ if (!is_polling(sdd) && xfer->len >= fifo_len &&
+ sdd->rx_dma.ch && sdd->tx_dma.ch) {
+ use_dma = 1;
+-
+ } else if (xfer->len >= fifo_len) {
+ tx_buf = xfer->tx_buf;
+ rx_buf = xfer->rx_buf;
+@@ -1146,6 +1159,23 @@ static inline const struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config(
+ return (const struct s3c64xx_spi_port_config *)platform_get_device_id(pdev)->driver_data;
+ }
+
++static void s3c64xx_spi_set_fifomask(struct s3c64xx_spi_driver_data *sdd)
++{
++ const struct s3c64xx_spi_port_config *port_conf = sdd->port_conf;
++
++ if (port_conf->rx_fifomask)
++ sdd->rx_fifomask = port_conf->rx_fifomask;
++ else
++ sdd->rx_fifomask = FIFO_LVL_MASK(sdd) <<
++ port_conf->rx_lvl_offset;
++
++ if (port_conf->tx_fifomask)
++ sdd->tx_fifomask = port_conf->tx_fifomask;
++ else
++ sdd->tx_fifomask = FIFO_LVL_MASK(sdd) <<
++ S3C64XX_SPI_ST_TX_FIFO_LVL_SHIFT;
++}
++
+ static int s3c64xx_spi_probe(struct platform_device *pdev)
+ {
+ struct resource *mem_res;
+@@ -1191,6 +1221,10 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
+ sdd->port_id = pdev->id;
+ }
+
++ sdd->fifo_depth = FIFO_DEPTH(sdd);
++
++ s3c64xx_spi_set_fifomask(sdd);
++
+ sdd->cur_bpw = 8;
+
+ sdd->tx_dma.direction = DMA_MEM_TO_DEV;
+@@ -1280,7 +1314,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev)
+ dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d with %d Targets attached\n",
+ sdd->port_id, host->num_chipselect);
+ dev_dbg(&pdev->dev, "\tIOmem=[%pR]\tFIFO %dbytes\n",
+- mem_res, (FIFO_LVL_MASK(sdd) >> 1) + 1);
++ mem_res, sdd->fifo_depth);
+
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
+diff --git a/drivers/thermal/gov_power_allocator.c b/drivers/thermal/gov_power_allocator.c
+index 81e061f183ad1..38581583ad289 100644
+--- a/drivers/thermal/gov_power_allocator.c
++++ b/drivers/thermal/gov_power_allocator.c
+@@ -606,7 +606,7 @@ static int allocate_actors_buffer(struct power_allocator_params *params,
+
+ /* There might be no cooling devices yet. */
+ if (!num_actors) {
+- ret = -EINVAL;
++ ret = 0;
+ goto clean_state;
+ }
+
+@@ -679,11 +679,6 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
+ return -ENOMEM;
+
+ get_governor_trips(tz, params);
+- if (!params->trip_max) {
+- dev_warn(&tz->device, "power_allocator: missing trip_max\n");
+- kfree(params);
+- return -EINVAL;
+- }
+
+ ret = check_power_actors(tz, params);
+ if (ret < 0) {
+@@ -712,9 +707,10 @@ static int power_allocator_bind(struct thermal_zone_device *tz)
+ if (!tz->tzp->sustainable_power)
+ dev_warn(&tz->device, "power_allocator: sustainable_power will be estimated\n");
+
+- estimate_pid_constants(tz, tz->tzp->sustainable_power,
+- params->trip_switch_on,
+- params->trip_max->temperature);
++ if (params->trip_max)
++ estimate_pid_constants(tz, tz->tzp->sustainable_power,
++ params->trip_switch_on,
++ params->trip_max->temperature);
+
+ reset_pid_controller(params);
+
+diff --git a/fs/aio.c b/fs/aio.c
+index 9cdaa2faa5363..0f4f531c97800 100644
+--- a/fs/aio.c
++++ b/fs/aio.c
+@@ -1202,8 +1202,8 @@ static void aio_complete(struct aio_kiocb *iocb)
+ spin_lock_irqsave(&ctx->wait.lock, flags);
+ list_for_each_entry_safe(curr, next, &ctx->wait.head, w.entry)
+ if (avail >= curr->min_nr) {
+- list_del_init_careful(&curr->w.entry);
+ wake_up_process(curr->w.private);
++ list_del_init_careful(&curr->w.entry);
+ }
+ spin_unlock_irqrestore(&ctx->wait.lock, flags);
+ }
+diff --git a/fs/bcachefs/mean_and_variance_test.c b/fs/bcachefs/mean_and_variance_test.c
+index 019583c3ca0ea..51093fa848202 100644
+--- a/fs/bcachefs/mean_and_variance_test.c
++++ b/fs/bcachefs/mean_and_variance_test.c
+@@ -130,20 +130,8 @@ static void mean_and_variance_test_1(struct kunit *test)
+ d, mean, stddev, weighted_mean, weighted_stddev);
+ }
+
+-static void mean_and_variance_test_2(struct kunit *test)
+-{
+- s64 d[] = { 100, 10, 10, 10, 10, 10, 10 };
+- s64 mean[] = { 10, 10, 10, 10, 10, 10, 10 };
+- s64 stddev[] = { 9, 9, 9, 9, 9, 9, 9 };
+- s64 weighted_mean[] = { 32, 27, 22, 19, 17, 15, 14 };
+- s64 weighted_stddev[] = { 38, 35, 31, 27, 24, 21, 18 };
+-
+- do_mean_and_variance_test(test, 10, 6, ARRAY_SIZE(d), 2,
+- d, mean, stddev, weighted_mean, weighted_stddev);
+-}
+-
+ /* Test behaviour where we switch from one steady state to another: */
+-static void mean_and_variance_test_3(struct kunit *test)
++static void mean_and_variance_test_2(struct kunit *test)
+ {
+ s64 d[] = { 100, 100, 100, 100, 100 };
+ s64 mean[] = { 22, 32, 40, 46, 50 };
+@@ -155,18 +143,6 @@ static void mean_and_variance_test_3(struct kunit *test)
+ d, mean, stddev, weighted_mean, weighted_stddev);
+ }
+
+-static void mean_and_variance_test_4(struct kunit *test)
+-{
+- s64 d[] = { 100, 100, 100, 100, 100 };
+- s64 mean[] = { 10, 11, 12, 13, 14 };
+- s64 stddev[] = { 9, 13, 15, 17, 19 };
+- s64 weighted_mean[] = { 32, 49, 61, 71, 78 };
+- s64 weighted_stddev[] = { 38, 44, 44, 41, 38 };
+-
+- do_mean_and_variance_test(test, 10, 6, ARRAY_SIZE(d), 2,
+- d, mean, stddev, weighted_mean, weighted_stddev);
+-}
+-
+ static void mean_and_variance_fast_divpow2(struct kunit *test)
+ {
+ s64 i;
+@@ -224,8 +200,6 @@ static struct kunit_case mean_and_variance_test_cases[] = {
+ KUNIT_CASE(mean_and_variance_weighted_advanced_test),
+ KUNIT_CASE(mean_and_variance_test_1),
+ KUNIT_CASE(mean_and_variance_test_2),
+- KUNIT_CASE(mean_and_variance_test_3),
+- KUNIT_CASE(mean_and_variance_test_4),
+ {}
+ };
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 7d6c657e0409d..692ede488254a 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -2888,12 +2888,9 @@ static void
+ nfsd4_cb_recall_any_release(struct nfsd4_callback *cb)
+ {
+ struct nfs4_client *clp = cb->cb_clp;
+- struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+
+- spin_lock(&nn->client_lock);
+ clear_bit(NFSD4_CLIENT_CB_RECALL_ANY, &clp->cl_flags);
+- put_client_renew_locked(clp);
+- spin_unlock(&nn->client_lock);
++ drop_client(clp);
+ }
+
+ static const struct nfsd4_callback_ops nfsd4_cb_recall_any_ops = {
+@@ -6274,7 +6271,7 @@ deleg_reaper(struct nfsd_net *nn)
+ list_add(&clp->cl_ra_cblist, &cblist);
+
+ /* release in nfsd4_cb_recall_any_release */
+- atomic_inc(&clp->cl_rpc_users);
++ kref_get(&clp->cl_nfsdfs.cl_ref);
+ set_bit(NFSD4_CLIENT_CB_RECALL_ANY, &clp->cl_flags);
+ clp->cl_ra_time = ktime_get_boottime_seconds();
+ }
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index b7c7a9273ea01..4ed1e83defa23 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1833,7 +1833,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
+ trap = lock_rename(tdentry, fdentry);
+ if (IS_ERR(trap)) {
+ err = (rqstp->rq_vers == 2) ? nfserr_acces : nfserr_xdev;
+- goto out;
++ goto out_want_write;
+ }
+ err = fh_fill_pre_attrs(ffhp);
+ if (err != nfs_ok)
+@@ -1903,6 +1903,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
+ }
+ out_unlock:
+ unlock_rename(tdentry, fdentry);
++out_want_write:
+ fh_drop_write(ffhp);
+
+ /*
+diff --git a/fs/proc/Makefile b/fs/proc/Makefile
+index bd08616ed8bad..7b4db9c56e6a7 100644
+--- a/fs/proc/Makefile
++++ b/fs/proc/Makefile
+@@ -5,7 +5,7 @@
+
+ obj-y += proc.o
+
+-CFLAGS_task_mmu.o += $(call cc-option,-Wno-override-init,)
++CFLAGS_task_mmu.o += -Wno-override-init
+ proc-y := nommu.o task_nommu.o
+ proc-$(CONFIG_MMU) := task_mmu.o
+
+diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
+index a0017724d5239..13a9d7acf8f8e 100644
+--- a/fs/smb/client/cached_dir.c
++++ b/fs/smb/client/cached_dir.c
+@@ -417,6 +417,7 @@ smb2_close_cached_fid(struct kref *ref)
+ {
+ struct cached_fid *cfid = container_of(ref, struct cached_fid,
+ refcount);
++ int rc;
+
+ spin_lock(&cfid->cfids->cfid_list_lock);
+ if (cfid->on_list) {
+@@ -430,9 +431,10 @@ smb2_close_cached_fid(struct kref *ref)
+ cfid->dentry = NULL;
+
+ if (cfid->is_open) {
+- SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid,
++ rc = SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid,
+ cfid->fid.volatile_fid);
+- atomic_dec(&cfid->tcon->num_remote_opens);
++ if (rc != -EBUSY && rc != -EAGAIN)
++ atomic_dec(&cfid->tcon->num_remote_opens);
+ }
+
+ free_cached_dir(cfid);
+diff --git a/fs/smb/client/cifs_debug.c b/fs/smb/client/cifs_debug.c
+index 23d2622b969f0..aa95fa95ca112 100644
+--- a/fs/smb/client/cifs_debug.c
++++ b/fs/smb/client/cifs_debug.c
+@@ -250,6 +250,8 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
+ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
++ if (cifs_ses_exiting(ses))
++ continue;
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ spin_lock(&tcon->open_file_lock);
+ list_for_each_entry(cfile, &tcon->openFileList, tlist) {
+@@ -656,6 +658,8 @@ static ssize_t cifs_stats_proc_write(struct file *file,
+ }
+ #endif /* CONFIG_CIFS_STATS2 */
+ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
++ if (cifs_ses_exiting(ses))
++ continue;
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ atomic_set(&tcon->num_smbs_sent, 0);
+ spin_lock(&tcon->stat_lock);
+@@ -735,6 +739,8 @@ static int cifs_stats_proc_show(struct seq_file *m, void *v)
+ }
+ #endif /* STATS2 */
+ list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
++ if (cifs_ses_exiting(ses))
++ continue;
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ i++;
+ seq_printf(m, "\n%d) %s", i, tcon->tree_name);
+diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
+index 0c269396ae151..501bfd3afdc64 100644
+--- a/fs/smb/client/cifsfs.c
++++ b/fs/smb/client/cifsfs.c
+@@ -160,6 +160,7 @@ struct workqueue_struct *decrypt_wq;
+ struct workqueue_struct *fileinfo_put_wq;
+ struct workqueue_struct *cifsoplockd_wq;
+ struct workqueue_struct *deferredclose_wq;
++struct workqueue_struct *serverclose_wq;
+ __u32 cifs_lock_secret;
+
+ /*
+@@ -1893,6 +1894,13 @@ init_cifs(void)
+ goto out_destroy_cifsoplockd_wq;
+ }
+
++ serverclose_wq = alloc_workqueue("serverclose",
++ WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
++ if (!serverclose_wq) {
++ rc = -ENOMEM;
++ goto out_destroy_serverclose_wq;
++ }
++
+ rc = cifs_init_inodecache();
+ if (rc)
+ goto out_destroy_deferredclose_wq;
+@@ -1967,6 +1975,8 @@ init_cifs(void)
+ destroy_workqueue(decrypt_wq);
+ out_destroy_cifsiod_wq:
+ destroy_workqueue(cifsiod_wq);
++out_destroy_serverclose_wq:
++ destroy_workqueue(serverclose_wq);
+ out_clean_proc:
+ cifs_proc_clean();
+ return rc;
+@@ -1996,6 +2006,7 @@ exit_cifs(void)
+ destroy_workqueue(cifsoplockd_wq);
+ destroy_workqueue(decrypt_wq);
+ destroy_workqueue(fileinfo_put_wq);
++ destroy_workqueue(serverclose_wq);
+ destroy_workqueue(cifsiod_wq);
+ cifs_proc_clean();
+ }
+diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
+index 06e81afe31c14..844afda090d05 100644
+--- a/fs/smb/client/cifsglob.h
++++ b/fs/smb/client/cifsglob.h
+@@ -432,10 +432,10 @@ struct smb_version_operations {
+ /* set fid protocol-specific info */
+ void (*set_fid)(struct cifsFileInfo *, struct cifs_fid *, __u32);
+ /* close a file */
+- void (*close)(const unsigned int, struct cifs_tcon *,
++ int (*close)(const unsigned int, struct cifs_tcon *,
+ struct cifs_fid *);
+ /* close a file, returning file attributes and timestamps */
+- void (*close_getattr)(const unsigned int xid, struct cifs_tcon *tcon,
++ int (*close_getattr)(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *pfile_info);
+ /* send a flush request to the server */
+ int (*flush)(const unsigned int, struct cifs_tcon *, struct cifs_fid *);
+@@ -1267,7 +1267,6 @@ struct cifs_tcon {
+ struct cached_fids *cfids;
+ /* BB add field for back pointer to sb struct(s)? */
+ #ifdef CONFIG_CIFS_DFS_UPCALL
+- struct list_head dfs_ses_list;
+ struct delayed_work dfs_cache_work;
+ #endif
+ struct delayed_work query_interfaces; /* query interfaces workqueue job */
+@@ -1424,6 +1423,7 @@ struct cifsFileInfo {
+ bool invalidHandle:1; /* file closed via session abend */
+ bool swapfile:1;
+ bool oplock_break_cancelled:1;
++ bool offload:1; /* offload final part of _put to a wq */
+ unsigned int oplock_epoch; /* epoch from the lease break */
+ __u32 oplock_level; /* oplock/lease level from the lease break */
+ int count;
+@@ -1432,6 +1432,7 @@ struct cifsFileInfo {
+ struct cifs_search_info srch_inf;
+ struct work_struct oplock_break; /* work for oplock breaks */
+ struct work_struct put; /* work for the final part of _put */
++ struct work_struct serverclose; /* work for serverclose */
+ struct delayed_work deferred;
+ bool deferred_close_scheduled; /* Flag to indicate close is scheduled */
+ char *symlink_target;
+@@ -1788,7 +1789,6 @@ struct cifs_mount_ctx {
+ struct TCP_Server_Info *server;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+- struct list_head dfs_ses_list;
+ };
+
+ static inline void __free_dfs_info_param(struct dfs_info3_param *param)
+@@ -2089,6 +2089,7 @@ extern struct workqueue_struct *decrypt_wq;
+ extern struct workqueue_struct *fileinfo_put_wq;
+ extern struct workqueue_struct *cifsoplockd_wq;
+ extern struct workqueue_struct *deferredclose_wq;
++extern struct workqueue_struct *serverclose_wq;
+ extern __u32 cifs_lock_secret;
+
+ extern mempool_t *cifs_mid_poolp;
+@@ -2294,4 +2295,14 @@ struct smb2_compound_vars {
+ struct smb2_file_link_info link_info;
+ };
+
++static inline bool cifs_ses_exiting(struct cifs_ses *ses)
++{
++ bool ret;
++
++ spin_lock(&ses->ses_lock);
++ ret = ses->ses_status == SES_EXITING;
++ spin_unlock(&ses->ses_lock);
++ return ret;
++}
++
+ #endif /* _CIFS_GLOB_H */
+diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
+index 58cfbd450a55e..996ca413dd8bd 100644
+--- a/fs/smb/client/cifsproto.h
++++ b/fs/smb/client/cifsproto.h
+@@ -723,31 +723,31 @@ struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon);
+ void cifs_put_tcon_super(struct super_block *sb);
+ int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry);
+
+-/* Put references of @ses and @ses->dfs_root_ses */
++/* Put references of @ses and its children */
+ static inline void cifs_put_smb_ses(struct cifs_ses *ses)
+ {
+- struct cifs_ses *rses = ses->dfs_root_ses;
++ struct cifs_ses *next;
+
+- __cifs_put_smb_ses(ses);
+- if (rses)
+- __cifs_put_smb_ses(rses);
++ do {
++ next = ses->dfs_root_ses;
++ __cifs_put_smb_ses(ses);
++ } while ((ses = next));
+ }
+
+-/* Get an active reference of @ses and @ses->dfs_root_ses.
++/* Get an active reference of @ses and its children.
+ *
+ * NOTE: make sure to call this function when incrementing reference count of
+ * @ses to ensure that any DFS root session attached to it (@ses->dfs_root_ses)
+ * will also get its reference count incremented.
+ *
+- * cifs_put_smb_ses() will put both references, so call it when you're done.
++ * cifs_put_smb_ses() will put all references, so call it when you're done.
+ */
+ static inline void cifs_smb_ses_inc_refcount(struct cifs_ses *ses)
+ {
+ lockdep_assert_held(&cifs_tcp_ses_lock);
+
+- ses->ses_count++;
+- if (ses->dfs_root_ses)
+- ses->dfs_root_ses->ses_count++;
++ for (; ses; ses = ses->dfs_root_ses)
++ ses->ses_count++;
+ }
+
+ static inline bool dfs_src_pathname_equal(const char *s1, const char *s2)
+diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
+index 2341604606157..7516c7d4558d8 100644
+--- a/fs/smb/client/connect.c
++++ b/fs/smb/client/connect.c
+@@ -178,6 +178,8 @@ cifs_signal_cifsd_for_reconnect(struct TCP_Server_Info *server,
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
++ if (cifs_ses_exiting(ses))
++ continue;
+ spin_lock(&ses->chan_lock);
+ for (i = 0; i < ses->chan_count; i++) {
+ if (!ses->chans[i].server)
+@@ -235,7 +237,13 @@ cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server,
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry_safe(ses, nses, &pserver->smb_ses_list, smb_ses_list) {
+- /* check if iface is still active */
++ spin_lock(&ses->ses_lock);
++ if (ses->ses_status == SES_EXITING) {
++ spin_unlock(&ses->ses_lock);
++ continue;
++ }
++ spin_unlock(&ses->ses_lock);
++
+ spin_lock(&ses->chan_lock);
+ if (cifs_ses_get_chan_index(ses, server) ==
+ CIFS_INVAL_CHAN_INDEX) {
+@@ -1863,6 +1871,9 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
+ ctx->sectype != ses->sectype)
+ return 0;
+
++ if (ctx->dfs_root_ses != ses->dfs_root_ses)
++ return 0;
++
+ /*
+ * If an existing session is limited to less channels than
+ * requested, it should not be reused
+@@ -1966,31 +1977,6 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx)
+ return rc;
+ }
+
+-/**
+- * cifs_free_ipc - helper to release the session IPC tcon
+- * @ses: smb session to unmount the IPC from
+- *
+- * Needs to be called everytime a session is destroyed.
+- *
+- * On session close, the IPC is closed and the server must release all tcons of the session.
+- * No need to send a tree disconnect here.
+- *
+- * Besides, it will make the server to not close durable and resilient files on session close, as
+- * specified in MS-SMB2 3.3.5.6 Receiving an SMB2 LOGOFF Request.
+- */
+-static int
+-cifs_free_ipc(struct cifs_ses *ses)
+-{
+- struct cifs_tcon *tcon = ses->tcon_ipc;
+-
+- if (tcon == NULL)
+- return 0;
+-
+- tconInfoFree(tcon);
+- ses->tcon_ipc = NULL;
+- return 0;
+-}
+-
+ static struct cifs_ses *
+ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
+ {
+@@ -2022,48 +2008,52 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
+ void __cifs_put_smb_ses(struct cifs_ses *ses)
+ {
+ struct TCP_Server_Info *server = ses->server;
++ struct cifs_tcon *tcon;
+ unsigned int xid;
+ size_t i;
++ bool do_logoff;
+ int rc;
+
++ spin_lock(&cifs_tcp_ses_lock);
+ spin_lock(&ses->ses_lock);
+- if (ses->ses_status == SES_EXITING) {
++ cifs_dbg(FYI, "%s: id=0x%llx ses_count=%d ses_status=%u ipc=%s\n",
++ __func__, ses->Suid, ses->ses_count, ses->ses_status,
++ ses->tcon_ipc ? ses->tcon_ipc->tree_name : "none");
++ if (ses->ses_status == SES_EXITING || --ses->ses_count > 0) {
+ spin_unlock(&ses->ses_lock);
++ spin_unlock(&cifs_tcp_ses_lock);
+ return;
+ }
+- spin_unlock(&ses->ses_lock);
++ /* ses_count can never go negative */
++ WARN_ON(ses->ses_count < 0);
+
+- cifs_dbg(FYI, "%s: ses_count=%d\n", __func__, ses->ses_count);
+- cifs_dbg(FYI,
+- "%s: ses ipc: %s\n", __func__, ses->tcon_ipc ? ses->tcon_ipc->tree_name : "NONE");
++ spin_lock(&ses->chan_lock);
++ cifs_chan_clear_need_reconnect(ses, server);
++ spin_unlock(&ses->chan_lock);
+
+- spin_lock(&cifs_tcp_ses_lock);
+- if (--ses->ses_count > 0) {
+- spin_unlock(&cifs_tcp_ses_lock);
+- return;
+- }
+- spin_lock(&ses->ses_lock);
+- if (ses->ses_status == SES_GOOD)
+- ses->ses_status = SES_EXITING;
++ do_logoff = ses->ses_status == SES_GOOD && server->ops->logoff;
++ ses->ses_status = SES_EXITING;
++ tcon = ses->tcon_ipc;
++ ses->tcon_ipc = NULL;
+ spin_unlock(&ses->ses_lock);
+ spin_unlock(&cifs_tcp_ses_lock);
+
+- /* ses_count can never go negative */
+- WARN_ON(ses->ses_count < 0);
+-
+- spin_lock(&ses->ses_lock);
+- if (ses->ses_status == SES_EXITING && server->ops->logoff) {
+- spin_unlock(&ses->ses_lock);
+- cifs_free_ipc(ses);
++ /*
++ * On session close, the IPC is closed and the server must release all
++ * tcons of the session. No need to send a tree disconnect here.
++ *
++ * Besides, it will make the server to not close durable and resilient
++ * files on session close, as specified in MS-SMB2 3.3.5.6 Receiving an
++ * SMB2 LOGOFF Request.
++ */
++ tconInfoFree(tcon);
++ if (do_logoff) {
+ xid = get_xid();
+ rc = server->ops->logoff(xid, ses);
+ if (rc)
+ cifs_server_dbg(VFS, "%s: Session Logoff failure rc=%d\n",
+ __func__, rc);
+ _free_xid(xid);
+- } else {
+- spin_unlock(&ses->ses_lock);
+- cifs_free_ipc(ses);
+ }
+
+ spin_lock(&cifs_tcp_ses_lock);
+@@ -2376,9 +2366,9 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
+ * need to lock before changing something in the session.
+ */
+ spin_lock(&cifs_tcp_ses_lock);
++ if (ctx->dfs_root_ses)
++ cifs_smb_ses_inc_refcount(ctx->dfs_root_ses);
+ ses->dfs_root_ses = ctx->dfs_root_ses;
+- if (ses->dfs_root_ses)
+- ses->dfs_root_ses->ses_count++;
+ list_add(&ses->smb_ses_list, &server->smb_ses_list);
+ spin_unlock(&cifs_tcp_ses_lock);
+
+@@ -3327,6 +3317,9 @@ void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx)
+ cifs_put_smb_ses(mnt_ctx->ses);
+ else if (mnt_ctx->server)
+ cifs_put_tcp_session(mnt_ctx->server, 0);
++ mnt_ctx->ses = NULL;
++ mnt_ctx->tcon = NULL;
++ mnt_ctx->server = NULL;
+ mnt_ctx->cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_POSIX_PATHS;
+ free_xid(mnt_ctx->xid);
+ }
+@@ -3605,8 +3598,6 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
+ bool isdfs;
+ int rc;
+
+- INIT_LIST_HEAD(&mnt_ctx.dfs_ses_list);
+-
+ rc = dfs_mount_share(&mnt_ctx, &isdfs);
+ if (rc)
+ goto error;
+@@ -3637,7 +3628,6 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
+ return rc;
+
+ error:
+- dfs_put_root_smb_sessions(&mnt_ctx.dfs_ses_list);
+ cifs_mount_put_conns(&mnt_ctx);
+ return rc;
+ }
+@@ -3652,6 +3642,18 @@ int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb3_fs_context *ctx)
+ goto error;
+
+ rc = cifs_mount_get_tcon(&mnt_ctx);
++ if (!rc) {
++ /*
++ * Prevent superblock from being created with any missing
++ * connections.
++ */
++ if (WARN_ON(!mnt_ctx.server))
++ rc = -EHOSTDOWN;
++ else if (WARN_ON(!mnt_ctx.ses))
++ rc = -EACCES;
++ else if (WARN_ON(!mnt_ctx.tcon))
++ rc = -ENOENT;
++ }
+ if (rc)
+ goto error;
+
+@@ -3989,13 +3991,14 @@ cifs_set_vol_auth(struct smb3_fs_context *ctx, struct cifs_ses *ses)
+ }
+
+ static struct cifs_tcon *
+-cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
++__cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
+ {
+ int rc;
+ struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb);
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon = NULL;
+ struct smb3_fs_context *ctx;
++ char *origin_fullpath = NULL;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (ctx == NULL)
+@@ -4019,6 +4022,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
+ ctx->sign = master_tcon->ses->sign;
+ ctx->seal = master_tcon->seal;
+ ctx->witness = master_tcon->use_witness;
++ ctx->dfs_root_ses = master_tcon->ses->dfs_root_ses;
+
+ rc = cifs_set_vol_auth(ctx, master_tcon->ses);
+ if (rc) {
+@@ -4038,12 +4042,39 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
+ goto out;
+ }
+
++#ifdef CONFIG_CIFS_DFS_UPCALL
++ spin_lock(&master_tcon->tc_lock);
++ if (master_tcon->origin_fullpath) {
++ spin_unlock(&master_tcon->tc_lock);
++ origin_fullpath = dfs_get_path(cifs_sb, cifs_sb->ctx->source);
++ if (IS_ERR(origin_fullpath)) {
++ tcon = ERR_CAST(origin_fullpath);
++ origin_fullpath = NULL;
++ cifs_put_smb_ses(ses);
++ goto out;
++ }
++ } else {
++ spin_unlock(&master_tcon->tc_lock);
++ }
++#endif
++
+ tcon = cifs_get_tcon(ses, ctx);
+ if (IS_ERR(tcon)) {
+ cifs_put_smb_ses(ses);
+ goto out;
+ }
+
++#ifdef CONFIG_CIFS_DFS_UPCALL
++ if (origin_fullpath) {
++ spin_lock(&tcon->tc_lock);
++ tcon->origin_fullpath = origin_fullpath;
++ spin_unlock(&tcon->tc_lock);
++ origin_fullpath = NULL;
++ queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work,
++ dfs_cache_get_ttl() * HZ);
++ }
++#endif
++
+ #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (cap_unix(ses))
+ reset_cifs_unix_caps(0, tcon, NULL, ctx);
+@@ -4052,11 +4083,23 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
+ out:
+ kfree(ctx->username);
+ kfree_sensitive(ctx->password);
++ kfree(origin_fullpath);
+ kfree(ctx);
+
+ return tcon;
+ }
+
++static struct cifs_tcon *
++cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
++{
++ struct cifs_tcon *ret;
++
++ cifs_mount_lock();
++ ret = __cifs_construct_tcon(cifs_sb, fsuid);
++ cifs_mount_unlock();
++ return ret;
++}
++
+ struct cifs_tcon *
+ cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
+ {
+diff --git a/fs/smb/client/dfs.c b/fs/smb/client/dfs.c
+index 449c59830039b..3ec965547e3d4 100644
+--- a/fs/smb/client/dfs.c
++++ b/fs/smb/client/dfs.c
+@@ -66,33 +66,20 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path)
+ }
+
+ /*
+- * Track individual DFS referral servers used by new DFS mount.
+- *
+- * On success, their lifetime will be shared by final tcon (dfs_ses_list).
+- * Otherwise, they will be put by dfs_put_root_smb_sessions() in cifs_mount().
++ * Get an active reference of @ses so that next call to cifs_put_tcon() won't
++ * release it as any new DFS referrals must go through its IPC tcon.
+ */
+-static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
++static void add_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
+ {
+ struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
+- struct dfs_root_ses *root_ses;
+ struct cifs_ses *ses = mnt_ctx->ses;
+
+ if (ses) {
+- root_ses = kmalloc(sizeof(*root_ses), GFP_KERNEL);
+- if (!root_ses)
+- return -ENOMEM;
+-
+- INIT_LIST_HEAD(&root_ses->list);
+-
+ spin_lock(&cifs_tcp_ses_lock);
+ cifs_smb_ses_inc_refcount(ses);
+ spin_unlock(&cifs_tcp_ses_lock);
+- root_ses->ses = ses;
+- list_add_tail(&root_ses->list, &mnt_ctx->dfs_ses_list);
+ }
+- /* Select new DFS referral server so that new referrals go through it */
+ ctx->dfs_root_ses = ses;
+- return 0;
+ }
+
+ static inline int parse_dfs_target(struct smb3_fs_context *ctx,
+@@ -185,11 +172,8 @@ static int __dfs_referral_walk(struct cifs_mount_ctx *mnt_ctx,
+ continue;
+ }
+
+- if (is_refsrv) {
+- rc = add_root_smb_session(mnt_ctx);
+- if (rc)
+- goto out;
+- }
++ if (is_refsrv)
++ add_root_smb_session(mnt_ctx);
+
+ rc = ref_walk_advance(rw);
+ if (!rc) {
+@@ -232,6 +216,7 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
+ struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
+ struct cifs_tcon *tcon;
+ char *origin_fullpath;
++ bool new_tcon = true;
+ int rc;
+
+ origin_fullpath = dfs_get_path(cifs_sb, ctx->source);
+@@ -239,6 +224,18 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
+ return PTR_ERR(origin_fullpath);
+
+ rc = dfs_referral_walk(mnt_ctx);
++ if (!rc) {
++ /*
++ * Prevent superblock from being created with any missing
++ * connections.
++ */
++ if (WARN_ON(!mnt_ctx->server))
++ rc = -EHOSTDOWN;
++ else if (WARN_ON(!mnt_ctx->ses))
++ rc = -EACCES;
++ else if (WARN_ON(!mnt_ctx->tcon))
++ rc = -ENOENT;
++ }
+ if (rc)
+ goto out;
+
+@@ -247,15 +244,14 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
+ if (!tcon->origin_fullpath) {
+ tcon->origin_fullpath = origin_fullpath;
+ origin_fullpath = NULL;
++ } else {
++ new_tcon = false;
+ }
+ spin_unlock(&tcon->tc_lock);
+
+- if (list_empty(&tcon->dfs_ses_list)) {
+- list_replace_init(&mnt_ctx->dfs_ses_list, &tcon->dfs_ses_list);
++ if (new_tcon) {
+ queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work,
+ dfs_cache_get_ttl() * HZ);
+- } else {
+- dfs_put_root_smb_sessions(&mnt_ctx->dfs_ses_list);
+ }
+
+ out:
+@@ -298,7 +294,6 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
+ if (rc)
+ return rc;
+
+- ctx->dfs_root_ses = mnt_ctx->ses;
+ /*
+ * If called with 'nodfs' mount option, then skip DFS resolving. Otherwise unconditionally
+ * try to get an DFS referral (even cached) to determine whether it is an DFS mount.
+@@ -324,7 +319,9 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
+
+ *isdfs = true;
+ add_root_smb_session(mnt_ctx);
+- return __dfs_mount_share(mnt_ctx);
++ rc = __dfs_mount_share(mnt_ctx);
++ dfs_put_root_smb_sessions(mnt_ctx);
++ return rc;
+ }
+
+ /* Update dfs referral path of superblock */
+diff --git a/fs/smb/client/dfs.h b/fs/smb/client/dfs.h
+index 875ab7ae57fcd..e5c4dcf837503 100644
+--- a/fs/smb/client/dfs.h
++++ b/fs/smb/client/dfs.h
+@@ -7,7 +7,9 @@
+ #define _CIFS_DFS_H
+
+ #include "cifsglob.h"
++#include "cifsproto.h"
+ #include "fs_context.h"
++#include "dfs_cache.h"
+ #include "cifs_unicode.h"
+ #include <linux/namei.h>
+
+@@ -114,11 +116,6 @@ static inline void ref_walk_set_tgt_hint(struct dfs_ref_walk *rw)
+ ref_walk_tit(rw));
+ }
+
+-struct dfs_root_ses {
+- struct list_head list;
+- struct cifs_ses *ses;
+-};
+-
+ int dfs_parse_target_referral(const char *full_path, const struct dfs_info3_param *ref,
+ struct smb3_fs_context *ctx);
+ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs);
+@@ -133,20 +130,32 @@ static inline int dfs_get_referral(struct cifs_mount_ctx *mnt_ctx, const char *p
+ {
+ struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
+ struct cifs_sb_info *cifs_sb = mnt_ctx->cifs_sb;
++ struct cifs_ses *rses = ctx->dfs_root_ses ?: mnt_ctx->ses;
+
+- return dfs_cache_find(mnt_ctx->xid, ctx->dfs_root_ses, cifs_sb->local_nls,
++ return dfs_cache_find(mnt_ctx->xid, rses, cifs_sb->local_nls,
+ cifs_remap(cifs_sb), path, ref, tl);
+ }
+
+-static inline void dfs_put_root_smb_sessions(struct list_head *head)
++/*
++ * cifs_get_smb_ses() already guarantees an active reference of
++ * @ses->dfs_root_ses when a new session is created, so we need to put extra
++ * references of all DFS root sessions that were used across the mount process
++ * in dfs_mount_share().
++ */
++static inline void dfs_put_root_smb_sessions(struct cifs_mount_ctx *mnt_ctx)
+ {
+- struct dfs_root_ses *root, *tmp;
++ const struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
++ struct cifs_ses *ses = ctx->dfs_root_ses;
++ struct cifs_ses *cur;
++
++ if (!ses)
++ return;
+
+- list_for_each_entry_safe(root, tmp, head, list) {
+- list_del_init(&root->list);
+- cifs_put_smb_ses(root->ses);
+- kfree(root);
++ for (cur = ses; cur; cur = cur->dfs_root_ses) {
++ if (cur->dfs_root_ses)
++ cifs_put_smb_ses(cur->dfs_root_ses);
+ }
++ cifs_put_smb_ses(ses);
+ }
+
+ #endif /* _CIFS_DFS_H */
+diff --git a/fs/smb/client/dfs_cache.c b/fs/smb/client/dfs_cache.c
+index 508d831fabe37..11c8efecf7aa1 100644
+--- a/fs/smb/client/dfs_cache.c
++++ b/fs/smb/client/dfs_cache.c
+@@ -1172,8 +1172,8 @@ static bool is_ses_good(struct cifs_ses *ses)
+ return ret;
+ }
+
+-/* Refresh dfs referral of tcon and mark it for reconnect if needed */
+-static int __refresh_tcon(const char *path, struct cifs_ses *ses, bool force_refresh)
++/* Refresh dfs referral of @ses and mark it for reconnect if needed */
++static void __refresh_ses_referral(struct cifs_ses *ses, bool force_refresh)
+ {
+ struct TCP_Server_Info *server = ses->server;
+ DFS_CACHE_TGT_LIST(old_tl);
+@@ -1181,10 +1181,21 @@ static int __refresh_tcon(const char *path, struct cifs_ses *ses, bool force_ref
+ bool needs_refresh = false;
+ struct cache_entry *ce;
+ unsigned int xid;
++ char *path = NULL;
+ int rc = 0;
+
+ xid = get_xid();
+
++ mutex_lock(&server->refpath_lock);
++ if (server->leaf_fullpath) {
++ path = kstrdup(server->leaf_fullpath + 1, GFP_ATOMIC);
++ if (!path)
++ rc = -ENOMEM;
++ }
++ mutex_unlock(&server->refpath_lock);
++ if (!path)
++ goto out;
++
+ down_read(&htable_rw_lock);
+ ce = lookup_cache_entry(path);
+ needs_refresh = force_refresh || IS_ERR(ce) || cache_entry_expired(ce);
+@@ -1218,19 +1229,17 @@ static int __refresh_tcon(const char *path, struct cifs_ses *ses, bool force_ref
+ free_xid(xid);
+ dfs_cache_free_tgts(&old_tl);
+ dfs_cache_free_tgts(&new_tl);
+- return rc;
++ kfree(path);
+ }
+
+-static int refresh_tcon(struct cifs_tcon *tcon, bool force_refresh)
++static inline void refresh_ses_referral(struct cifs_ses *ses)
+ {
+- struct TCP_Server_Info *server = tcon->ses->server;
+- struct cifs_ses *ses = tcon->ses;
++ __refresh_ses_referral(ses, false);
++}
+
+- mutex_lock(&server->refpath_lock);
+- if (server->leaf_fullpath)
+- __refresh_tcon(server->leaf_fullpath + 1, ses, force_refresh);
+- mutex_unlock(&server->refpath_lock);
+- return 0;
++static inline void force_refresh_ses_referral(struct cifs_ses *ses)
++{
++ __refresh_ses_referral(ses, true);
+ }
+
+ /**
+@@ -1271,34 +1280,20 @@ int dfs_cache_remount_fs(struct cifs_sb_info *cifs_sb)
+ */
+ cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH;
+
+- return refresh_tcon(tcon, true);
++ force_refresh_ses_referral(tcon->ses);
++ return 0;
+ }
+
+ /* Refresh all DFS referrals related to DFS tcon */
+ void dfs_cache_refresh(struct work_struct *work)
+ {
+- struct TCP_Server_Info *server;
+- struct dfs_root_ses *rses;
+ struct cifs_tcon *tcon;
+ struct cifs_ses *ses;
+
+ tcon = container_of(work, struct cifs_tcon, dfs_cache_work.work);
+- ses = tcon->ses;
+- server = ses->server;
+
+- mutex_lock(&server->refpath_lock);
+- if (server->leaf_fullpath)
+- __refresh_tcon(server->leaf_fullpath + 1, ses, false);
+- mutex_unlock(&server->refpath_lock);
+-
+- list_for_each_entry(rses, &tcon->dfs_ses_list, list) {
+- ses = rses->ses;
+- server = ses->server;
+- mutex_lock(&server->refpath_lock);
+- if (server->leaf_fullpath)
+- __refresh_tcon(server->leaf_fullpath + 1, ses, false);
+- mutex_unlock(&server->refpath_lock);
+- }
++ for (ses = tcon->ses; ses; ses = ses->dfs_root_ses)
++ refresh_ses_referral(ses);
+
+ queue_delayed_work(dfscache_wq, &tcon->dfs_cache_work,
+ atomic_read(&dfs_cache_ttl) * HZ);
+diff --git a/fs/smb/client/dir.c b/fs/smb/client/dir.c
+index 89333d9bce36e..37897b919dd5a 100644
+--- a/fs/smb/client/dir.c
++++ b/fs/smb/client/dir.c
+@@ -189,6 +189,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
+ int disposition;
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct cifs_open_parms oparms;
++ int rdwr_for_fscache = 0;
+
+ *oplock = 0;
+ if (tcon->ses->server->oplocks)
+@@ -200,6 +201,10 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
+ return PTR_ERR(full_path);
+ }
+
++ /* If we're caching, we need to be able to fill in around partial writes. */
++ if (cifs_fscache_enabled(inode) && (oflags & O_ACCMODE) == O_WRONLY)
++ rdwr_for_fscache = 1;
++
+ #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ if (tcon->unix_ext && cap_unix(tcon->ses) && !tcon->broken_posix_open &&
+ (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+@@ -276,6 +281,8 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
+ desired_access |= GENERIC_READ; /* is this too little? */
+ if (OPEN_FMODE(oflags) & FMODE_WRITE)
+ desired_access |= GENERIC_WRITE;
++ if (rdwr_for_fscache == 1)
++ desired_access |= GENERIC_READ;
+
+ disposition = FILE_OVERWRITE_IF;
+ if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+@@ -304,6 +311,7 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
+ if (!tcon->unix_ext && (mode & S_IWUGO) == 0)
+ create_options |= CREATE_OPTION_READONLY;
+
++retry_open:
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+@@ -317,8 +325,15 @@ static int cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned
+ rc = server->ops->open(xid, &oparms, oplock, buf);
+ if (rc) {
+ cifs_dbg(FYI, "cifs_create returned 0x%x\n", rc);
++ if (rc == -EACCES && rdwr_for_fscache == 1) {
++ desired_access &= ~GENERIC_READ;
++ rdwr_for_fscache = 2;
++ goto retry_open;
++ }
+ goto out;
+ }
++ if (rdwr_for_fscache == 2)
++ cifs_invalidate_cache(inode, FSCACHE_INVAL_DIO_WRITE);
+
+ #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ /*
+diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
+index 9d42a39009076..af5c476db6e66 100644
+--- a/fs/smb/client/file.c
++++ b/fs/smb/client/file.c
+@@ -206,12 +206,12 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
+ */
+ }
+
+-static inline int cifs_convert_flags(unsigned int flags)
++static inline int cifs_convert_flags(unsigned int flags, int rdwr_for_fscache)
+ {
+ if ((flags & O_ACCMODE) == O_RDONLY)
+ return GENERIC_READ;
+ else if ((flags & O_ACCMODE) == O_WRONLY)
+- return GENERIC_WRITE;
++ return rdwr_for_fscache == 1 ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE;
+ else if ((flags & O_ACCMODE) == O_RDWR) {
+ /* GENERIC_ALL is too much permission to request
+ can cause unnecessary access denied on create */
+@@ -348,11 +348,16 @@ static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_
+ int create_options = CREATE_NOT_DIR;
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct cifs_open_parms oparms;
++ int rdwr_for_fscache = 0;
+
+ if (!server->ops->open)
+ return -ENOSYS;
+
+- desired_access = cifs_convert_flags(f_flags);
++ /* If we're caching, we need to be able to fill in around partial writes. */
++ if (cifs_fscache_enabled(inode) && (f_flags & O_ACCMODE) == O_WRONLY)
++ rdwr_for_fscache = 1;
++
++ desired_access = cifs_convert_flags(f_flags, rdwr_for_fscache);
+
+ /*********************************************************************
+ * open flag mapping table:
+@@ -389,6 +394,7 @@ static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_
+ if (f_flags & O_DIRECT)
+ create_options |= CREATE_NO_BUFFER;
+
++retry_open:
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+@@ -400,8 +406,16 @@ static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_
+ };
+
+ rc = server->ops->open(xid, &oparms, oplock, buf);
+- if (rc)
++ if (rc) {
++ if (rc == -EACCES && rdwr_for_fscache == 1) {
++ desired_access = cifs_convert_flags(f_flags, 0);
++ rdwr_for_fscache = 2;
++ goto retry_open;
++ }
+ return rc;
++ }
++ if (rdwr_for_fscache == 2)
++ cifs_invalidate_cache(inode, FSCACHE_INVAL_DIO_WRITE);
+
+ /* TODO: Add support for calling posix query info but with passing in fid */
+ if (tcon->unix_ext)
+@@ -445,6 +459,7 @@ cifs_down_write(struct rw_semaphore *sem)
+ }
+
+ static void cifsFileInfo_put_work(struct work_struct *work);
++void serverclose_work(struct work_struct *work);
+
+ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
+ struct tcon_link *tlink, __u32 oplock,
+@@ -491,6 +506,7 @@ struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
+ cfile->tlink = cifs_get_tlink(tlink);
+ INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
+ INIT_WORK(&cfile->put, cifsFileInfo_put_work);
++ INIT_WORK(&cfile->serverclose, serverclose_work);
+ INIT_DELAYED_WORK(&cfile->deferred, smb2_deferred_work_close);
+ mutex_init(&cfile->fh_mutex);
+ spin_lock_init(&cfile->file_info_lock);
+@@ -582,6 +598,40 @@ static void cifsFileInfo_put_work(struct work_struct *work)
+ cifsFileInfo_put_final(cifs_file);
+ }
+
++void serverclose_work(struct work_struct *work)
++{
++ struct cifsFileInfo *cifs_file = container_of(work,
++ struct cifsFileInfo, serverclose);
++
++ struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
++
++ struct TCP_Server_Info *server = tcon->ses->server;
++ int rc = 0;
++ int retries = 0;
++ int MAX_RETRIES = 4;
++
++ do {
++ if (server->ops->close_getattr)
++ rc = server->ops->close_getattr(0, tcon, cifs_file);
++ else if (server->ops->close)
++ rc = server->ops->close(0, tcon, &cifs_file->fid);
++
++ if (rc == -EBUSY || rc == -EAGAIN) {
++ retries++;
++ msleep(250);
++ }
++ } while ((rc == -EBUSY || rc == -EAGAIN) && (retries < MAX_RETRIES)
++ );
++
++ if (retries == MAX_RETRIES)
++ pr_warn("Serverclose failed %d times, giving up\n", MAX_RETRIES);
++
++ if (cifs_file->offload)
++ queue_work(fileinfo_put_wq, &cifs_file->put);
++ else
++ cifsFileInfo_put_final(cifs_file);
++}
++
+ /**
+ * cifsFileInfo_put - release a reference of file priv data
+ *
+@@ -622,10 +672,13 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file,
+ struct cifs_fid fid = {};
+ struct cifs_pending_open open;
+ bool oplock_break_cancelled;
++ bool serverclose_offloaded = false;
+
+ spin_lock(&tcon->open_file_lock);
+ spin_lock(&cifsi->open_file_lock);
+ spin_lock(&cifs_file->file_info_lock);
++
++ cifs_file->offload = offload;
+ if (--cifs_file->count > 0) {
+ spin_unlock(&cifs_file->file_info_lock);
+ spin_unlock(&cifsi->open_file_lock);
+@@ -667,13 +720,20 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file,
+ if (!tcon->need_reconnect && !cifs_file->invalidHandle) {
+ struct TCP_Server_Info *server = tcon->ses->server;
+ unsigned int xid;
++ int rc = 0;
+
+ xid = get_xid();
+ if (server->ops->close_getattr)
+- server->ops->close_getattr(xid, tcon, cifs_file);
++ rc = server->ops->close_getattr(xid, tcon, cifs_file);
+ else if (server->ops->close)
+- server->ops->close(xid, tcon, &cifs_file->fid);
++ rc = server->ops->close(xid, tcon, &cifs_file->fid);
+ _free_xid(xid);
++
++ if (rc == -EBUSY || rc == -EAGAIN) {
++ // Server close failed, hence offloading it as an async op
++ queue_work(serverclose_wq, &cifs_file->serverclose);
++ serverclose_offloaded = true;
++ }
+ }
+
+ if (oplock_break_cancelled)
+@@ -681,10 +741,15 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file,
+
+ cifs_del_pending_open(&open);
+
+- if (offload)
+- queue_work(fileinfo_put_wq, &cifs_file->put);
+- else
+- cifsFileInfo_put_final(cifs_file);
++ // if serverclose has been offloaded to wq (on failure), it will
++ // handle offloading put as well. If serverclose not offloaded,
++ // we need to handle offloading put here.
++ if (!serverclose_offloaded) {
++ if (offload)
++ queue_work(fileinfo_put_wq, &cifs_file->put);
++ else
++ cifsFileInfo_put_final(cifs_file);
++ }
+ }
+
+ int cifs_open(struct inode *inode, struct file *file)
+@@ -834,11 +899,11 @@ int cifs_open(struct inode *inode, struct file *file)
+ use_cache:
+ fscache_use_cookie(cifs_inode_cookie(file_inode(file)),
+ file->f_mode & FMODE_WRITE);
+- if (file->f_flags & O_DIRECT &&
+- (!((file->f_flags & O_ACCMODE) != O_RDONLY) ||
+- file->f_flags & O_APPEND))
+- cifs_invalidate_cache(file_inode(file),
+- FSCACHE_INVAL_DIO_WRITE);
++ if (!(file->f_flags & O_DIRECT))
++ goto out;
++ if ((file->f_flags & (O_ACCMODE | O_APPEND)) == O_RDONLY)
++ goto out;
++ cifs_invalidate_cache(file_inode(file), FSCACHE_INVAL_DIO_WRITE);
+
+ out:
+ free_dentry_path(page);
+@@ -903,6 +968,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
+ int disposition = FILE_OPEN;
+ int create_options = CREATE_NOT_DIR;
+ struct cifs_open_parms oparms;
++ int rdwr_for_fscache = 0;
+
+ xid = get_xid();
+ mutex_lock(&cfile->fh_mutex);
+@@ -966,7 +1032,11 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
+ }
+ #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+
+- desired_access = cifs_convert_flags(cfile->f_flags);
++ /* If we're caching, we need to be able to fill in around partial writes. */
++ if (cifs_fscache_enabled(inode) && (cfile->f_flags & O_ACCMODE) == O_WRONLY)
++ rdwr_for_fscache = 1;
++
++ desired_access = cifs_convert_flags(cfile->f_flags, rdwr_for_fscache);
+
+ /* O_SYNC also has bit for O_DSYNC so following check picks up either */
+ if (cfile->f_flags & O_SYNC)
+@@ -978,6 +1048,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
+ if (server->ops->get_lease_key)
+ server->ops->get_lease_key(inode, &cfile->fid);
+
++retry_open:
+ oparms = (struct cifs_open_parms) {
+ .tcon = tcon,
+ .cifs_sb = cifs_sb,
+@@ -1003,6 +1074,11 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
+ /* indicate that we need to relock the file */
+ oparms.reconnect = true;
+ }
++ if (rc == -EACCES && rdwr_for_fscache == 1) {
++ desired_access = cifs_convert_flags(cfile->f_flags, 0);
++ rdwr_for_fscache = 2;
++ goto retry_open;
++ }
+
+ if (rc) {
+ mutex_unlock(&cfile->fh_mutex);
+@@ -1011,6 +1087,9 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
+ goto reopen_error_exit;
+ }
+
++ if (rdwr_for_fscache == 2)
++ cifs_invalidate_cache(inode, FSCACHE_INVAL_DIO_WRITE);
++
+ #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
+ reopen_success:
+ #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */
+diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
+index 415e87635d5aa..d9fe17b2ba375 100644
+--- a/fs/smb/client/fs_context.c
++++ b/fs/smb/client/fs_context.c
+@@ -37,7 +37,7 @@
+ #include "rfc1002pdu.h"
+ #include "fs_context.h"
+
+-static DEFINE_MUTEX(cifs_mount_mutex);
++DEFINE_MUTEX(cifs_mount_mutex);
+
+ static const match_table_t cifs_smb_version_tokens = {
+ { Smb_1, SMB1_VERSION_STRING },
+@@ -753,9 +753,9 @@ static int smb3_get_tree(struct fs_context *fc)
+
+ if (err)
+ return err;
+- mutex_lock(&cifs_mount_mutex);
++ cifs_mount_lock();
+ ret = smb3_get_tree_common(fc);
+- mutex_unlock(&cifs_mount_mutex);
++ cifs_mount_unlock();
+ return ret;
+ }
+
+diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h
+index 182ce11cbe936..b3d51b345eaef 100644
+--- a/fs/smb/client/fs_context.h
++++ b/fs/smb/client/fs_context.h
+@@ -295,4 +295,16 @@ extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
+ #define MAX_CACHED_FIDS 16
+ extern char *cifs_sanitize_prepath(char *prepath, gfp_t gfp);
+
++extern struct mutex cifs_mount_mutex;
++
++static inline void cifs_mount_lock(void)
++{
++ mutex_lock(&cifs_mount_mutex);
++}
++
++static inline void cifs_mount_unlock(void)
++{
++ mutex_unlock(&cifs_mount_mutex);
++}
++
+ #endif
+diff --git a/fs/smb/client/fscache.c b/fs/smb/client/fscache.c
+index c4a3cb736881a..340efce8f0529 100644
+--- a/fs/smb/client/fscache.c
++++ b/fs/smb/client/fscache.c
+@@ -12,6 +12,16 @@
+ #include "cifs_fs_sb.h"
+ #include "cifsproto.h"
+
++/*
++ * Key for fscache inode. [!] Contents must match comparisons in cifs_find_inode().
++ */
++struct cifs_fscache_inode_key {
++
++ __le64 uniqueid; /* server inode number */
++ __le64 createtime; /* creation time on server */
++ u8 type; /* S_IFMT file type */
++} __packed;
++
+ static void cifs_fscache_fill_volume_coherency(
+ struct cifs_tcon *tcon,
+ struct cifs_fscache_volume_coherency_data *cd)
+@@ -97,15 +107,19 @@ void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
+ void cifs_fscache_get_inode_cookie(struct inode *inode)
+ {
+ struct cifs_fscache_inode_coherency_data cd;
++ struct cifs_fscache_inode_key key;
+ struct cifsInodeInfo *cifsi = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+
++ key.uniqueid = cpu_to_le64(cifsi->uniqueid);
++ key.createtime = cpu_to_le64(cifsi->createtime);
++ key.type = (inode->i_mode & S_IFMT) >> 12;
+ cifs_fscache_fill_coherency(&cifsi->netfs.inode, &cd);
+
+ cifsi->netfs.cache =
+ fscache_acquire_cookie(tcon->fscache, 0,
+- &cifsi->uniqueid, sizeof(cifsi->uniqueid),
++ &key, sizeof(key),
+ &cd, sizeof(cd),
+ i_size_read(&cifsi->netfs.inode));
+ if (cifsi->netfs.cache)
+diff --git a/fs/smb/client/fscache.h b/fs/smb/client/fscache.h
+index a3d73720914f8..1f2ea9f5cc9a8 100644
+--- a/fs/smb/client/fscache.h
++++ b/fs/smb/client/fscache.h
+@@ -109,6 +109,11 @@ static inline void cifs_readahead_to_fscache(struct inode *inode,
+ __cifs_readahead_to_fscache(inode, pos, len);
+ }
+
++static inline bool cifs_fscache_enabled(struct inode *inode)
++{
++ return fscache_cookie_enabled(cifs_inode_cookie(inode));
++}
++
+ #else /* CONFIG_CIFS_FSCACHE */
+ static inline
+ void cifs_fscache_fill_coherency(struct inode *inode,
+@@ -124,6 +129,7 @@ static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
+ static inline void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update) {}
+ static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) { return NULL; }
+ static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) {}
++static inline bool cifs_fscache_enabled(struct inode *inode) { return false; }
+
+ static inline int cifs_fscache_query_occupancy(struct inode *inode,
+ pgoff_t first, unsigned int nr_pages,
+diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
+index 7f28edf4b20f3..4c3dec384f922 100644
+--- a/fs/smb/client/inode.c
++++ b/fs/smb/client/inode.c
+@@ -1414,6 +1414,8 @@ cifs_find_inode(struct inode *inode, void *opaque)
+ {
+ struct cifs_fattr *fattr = opaque;
+
++ /* [!] The compared values must be the same in struct cifs_fscache_inode_key. */
++
+ /* don't match inode with different uniqueid */
+ if (CIFS_I(inode)->uniqueid != fattr->cf_uniqueid)
+ return 0;
+diff --git a/fs/smb/client/ioctl.c b/fs/smb/client/ioctl.c
+index e2f92c21fff50..682eabdd1d6cc 100644
+--- a/fs/smb/client/ioctl.c
++++ b/fs/smb/client/ioctl.c
+@@ -247,7 +247,9 @@ static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(server_it, &cifs_tcp_ses_list, tcp_ses_list) {
+ list_for_each_entry(ses_it, &server_it->smb_ses_list, smb_ses_list) {
+- if (ses_it->Suid == out.session_id) {
++ spin_lock(&ses_it->ses_lock);
++ if (ses_it->ses_status != SES_EXITING &&
++ ses_it->Suid == out.session_id) {
+ ses = ses_it;
+ /*
+ * since we are using the session outside the crit
+@@ -255,9 +257,11 @@ static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug
+ * so increment its refcount
+ */
+ cifs_smb_ses_inc_refcount(ses);
++ spin_unlock(&ses_it->ses_lock);
+ found = true;
+ goto search_end;
+ }
++ spin_unlock(&ses_it->ses_lock);
+ }
+ }
+ search_end:
+diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c
+index 0748d7b757b95..74627d647818a 100644
+--- a/fs/smb/client/misc.c
++++ b/fs/smb/client/misc.c
+@@ -141,9 +141,6 @@ tcon_info_alloc(bool dir_leases_enabled)
+ atomic_set(&ret_buf->num_local_opens, 0);
+ atomic_set(&ret_buf->num_remote_opens, 0);
+ ret_buf->stats_from_time = ktime_get_real_seconds();
+-#ifdef CONFIG_CIFS_DFS_UPCALL
+- INIT_LIST_HEAD(&ret_buf->dfs_ses_list);
+-#endif
+
+ return ret_buf;
+ }
+@@ -159,9 +156,6 @@ tconInfoFree(struct cifs_tcon *tcon)
+ atomic_dec(&tconInfoAllocCount);
+ kfree(tcon->nativeFileSystem);
+ kfree_sensitive(tcon->password);
+-#ifdef CONFIG_CIFS_DFS_UPCALL
+- dfs_put_root_smb_sessions(&tcon->dfs_ses_list);
+-#endif
+ kfree(tcon->origin_fullpath);
+ kfree(tcon);
+ }
+@@ -490,6 +484,8 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv)
+ /* look up tcon based on tid & uid */
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
++ if (cifs_ses_exiting(ses))
++ continue;
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ if (tcon->tid != buf->Tid)
+ continue;
+diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
+index a9eaba8083b0d..212ec6f66ec65 100644
+--- a/fs/smb/client/smb1ops.c
++++ b/fs/smb/client/smb1ops.c
+@@ -753,11 +753,11 @@ cifs_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
+ cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode);
+ }
+
+-static void
++static int
+ cifs_close_file(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_fid *fid)
+ {
+- CIFSSMBClose(xid, tcon, fid->netfid);
++ return CIFSSMBClose(xid, tcon, fid->netfid);
+ }
+
+ static int
+diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c
+index 82b84a4941dd2..cc72be5a93a93 100644
+--- a/fs/smb/client/smb2misc.c
++++ b/fs/smb/client/smb2misc.c
+@@ -622,6 +622,8 @@ smb2_is_valid_lease_break(char *buffer, struct TCP_Server_Info *server)
+ /* look up tcon based on tid & uid */
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
++ if (cifs_ses_exiting(ses))
++ continue;
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ spin_lock(&tcon->open_file_lock);
+ cifs_stats_inc(
+@@ -697,6 +699,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
+ /* look up tcon based on tid & uid */
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
++ if (cifs_ses_exiting(ses))
++ continue;
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+
+ spin_lock(&tcon->open_file_lock);
+diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
+index 3b8896987197e..ab77ecb2d4f02 100644
+--- a/fs/smb/client/smb2ops.c
++++ b/fs/smb/client/smb2ops.c
+@@ -1411,14 +1411,14 @@ smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock)
+ memcpy(cfile->fid.create_guid, fid->create_guid, 16);
+ }
+
+-static void
++static int
+ smb2_close_file(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_fid *fid)
+ {
+- SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
++ return SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
+ }
+
+-static void
++static int
+ smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile)
+ {
+@@ -1429,7 +1429,7 @@ smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon,
+ rc = __SMB2_close(xid, tcon, cfile->fid.persistent_fid,
+ cfile->fid.volatile_fid, &file_inf);
+ if (rc)
+- return;
++ return rc;
+
+ inode = d_inode(cfile->dentry);
+
+@@ -1458,6 +1458,7 @@ smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon,
+
+ /* End of file and Attributes should not have to be updated on close */
+ spin_unlock(&inode->i_lock);
++ return rc;
+ }
+
+ static int
+@@ -2479,6 +2480,8 @@ smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
+
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) {
++ if (cifs_ses_exiting(ses))
++ continue;
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ if (tcon->tid == le32_to_cpu(shdr->Id.SyncId.TreeId)) {
+ spin_lock(&tcon->tc_lock);
+diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
+index 92c3710df6159..b71e32d66eba7 100644
+--- a/fs/smb/client/smb2pdu.c
++++ b/fs/smb/client/smb2pdu.c
+@@ -3606,9 +3606,9 @@ __SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
+ memcpy(&pbuf->network_open_info,
+ &rsp->network_open_info,
+ sizeof(pbuf->network_open_info));
++ atomic_dec(&tcon->num_remote_opens);
+ }
+
+- atomic_dec(&tcon->num_remote_opens);
+ close_exit:
+ SMB2_close_free(&rqst);
+ free_rsp_buf(resp_buftype, rsp);
+diff --git a/fs/smb/server/ksmbd_netlink.h b/fs/smb/server/ksmbd_netlink.h
+index 0ebf91ffa2361..4464a62228cf3 100644
+--- a/fs/smb/server/ksmbd_netlink.h
++++ b/fs/smb/server/ksmbd_netlink.h
+@@ -166,7 +166,8 @@ struct ksmbd_share_config_response {
+ __u16 force_uid;
+ __u16 force_gid;
+ __s8 share_name[KSMBD_REQ_MAX_SHARE_NAME];
+- __u32 reserved[112]; /* Reserved room */
++ __u32 reserved[111]; /* Reserved room */
++ __u32 payload_sz;
+ __u32 veto_list_sz;
+ __s8 ____payload[];
+ };
+diff --git a/fs/smb/server/mgmt/share_config.c b/fs/smb/server/mgmt/share_config.c
+index 328a412259dc1..a2f0a2edceb8a 100644
+--- a/fs/smb/server/mgmt/share_config.c
++++ b/fs/smb/server/mgmt/share_config.c
+@@ -158,7 +158,12 @@ static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
+ share->name = kstrdup(name, GFP_KERNEL);
+
+ if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
+- share->path = kstrdup(ksmbd_share_config_path(resp),
++ int path_len = PATH_MAX;
++
++ if (resp->payload_sz)
++ path_len = resp->payload_sz - resp->veto_list_sz;
++
++ share->path = kstrndup(ksmbd_share_config_path(resp), path_len,
+ GFP_KERNEL);
+ if (share->path)
+ share->path_sz = strlen(share->path);
+diff --git a/fs/smb/server/smb2ops.c b/fs/smb/server/smb2ops.c
+index 27a9dce3e03ab..8600f32c981a1 100644
+--- a/fs/smb/server/smb2ops.c
++++ b/fs/smb/server/smb2ops.c
+@@ -228,6 +228,11 @@ void init_smb3_0_server(struct ksmbd_conn *conn)
+ conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
+
++ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION ||
++ (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) &&
++ conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION))
++ conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
++
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
+ }
+@@ -275,11 +280,6 @@ int init_smb3_11_server(struct ksmbd_conn *conn)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING |
+ SMB2_GLOBAL_CAP_DIRECTORY_LEASING;
+
+- if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION ||
+- (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) &&
+- conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION))
+- conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
+-
+ if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
+ conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
+
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index 88db6e207e0ee..cd2ed345c3d39 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -5632,8 +5632,9 @@ static int smb2_rename(struct ksmbd_work *work,
+ if (!file_info->ReplaceIfExists)
+ flags = RENAME_NOREPLACE;
+
+- smb_break_all_levII_oplock(work, fp, 0);
+ rc = ksmbd_vfs_rename(work, &fp->filp->f_path, new_name, flags);
++ if (!rc)
++ smb_break_all_levII_oplock(work, fp, 0);
+ out:
+ kfree(new_name);
+ return rc;
+diff --git a/fs/smb/server/transport_ipc.c b/fs/smb/server/transport_ipc.c
+index f29bb03f0dc47..8752ac82c557b 100644
+--- a/fs/smb/server/transport_ipc.c
++++ b/fs/smb/server/transport_ipc.c
+@@ -65,6 +65,7 @@ struct ipc_msg_table_entry {
+ struct hlist_node ipc_table_hlist;
+
+ void *response;
++ unsigned int msg_sz;
+ };
+
+ static struct delayed_work ipc_timer_work;
+@@ -275,6 +276,7 @@ static int handle_response(int type, void *payload, size_t sz)
+ }
+
+ memcpy(entry->response, payload, sz);
++ entry->msg_sz = sz;
+ wake_up_interruptible(&entry->wait);
+ ret = 0;
+ break;
+@@ -453,6 +455,34 @@ static int ipc_msg_send(struct ksmbd_ipc_msg *msg)
+ return ret;
+ }
+
++static int ipc_validate_msg(struct ipc_msg_table_entry *entry)
++{
++ unsigned int msg_sz = entry->msg_sz;
++
++ if (entry->type == KSMBD_EVENT_RPC_REQUEST) {
++ struct ksmbd_rpc_command *resp = entry->response;
++
++ msg_sz = sizeof(struct ksmbd_rpc_command) + resp->payload_sz;
++ } else if (entry->type == KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST) {
++ struct ksmbd_spnego_authen_response *resp = entry->response;
++
++ msg_sz = sizeof(struct ksmbd_spnego_authen_response) +
++ resp->session_key_len + resp->spnego_blob_len;
++ } else if (entry->type == KSMBD_EVENT_SHARE_CONFIG_REQUEST) {
++ struct ksmbd_share_config_response *resp = entry->response;
++
++ if (resp->payload_sz) {
++ if (resp->payload_sz < resp->veto_list_sz)
++ return -EINVAL;
++
++ msg_sz = sizeof(struct ksmbd_share_config_response) +
++ resp->payload_sz;
++ }
++ }
++
++ return entry->msg_sz != msg_sz ? -EINVAL : 0;
++}
++
+ static void *ipc_msg_send_request(struct ksmbd_ipc_msg *msg, unsigned int handle)
+ {
+ struct ipc_msg_table_entry entry;
+@@ -477,6 +507,13 @@ static void *ipc_msg_send_request(struct ksmbd_ipc_msg *msg, unsigned int handle
+ ret = wait_event_interruptible_timeout(entry.wait,
+ entry.response != NULL,
+ IPC_WAIT_TIMEOUT);
++ if (entry.response) {
++ ret = ipc_validate_msg(&entry);
++ if (ret) {
++ kvfree(entry.response);
++ entry.response = NULL;
++ }
++ }
+ out:
+ down_write(&ipc_msg_table_lock);
+ hash_del(&entry.ipc_table_hlist);
+diff --git a/fs/vboxsf/super.c b/fs/vboxsf/super.c
+index 1fb8f4df60cbb..9848af78215bf 100644
+--- a/fs/vboxsf/super.c
++++ b/fs/vboxsf/super.c
+@@ -151,7 +151,7 @@ static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc)
+ if (!sbi->nls) {
+ vbg_err("vboxsf: Count not load '%s' nls\n", nls_name);
+ err = -EINVAL;
+- goto fail_free;
++ goto fail_destroy_idr;
+ }
+ }
+
+@@ -224,6 +224,7 @@ static int vboxsf_fill_super(struct super_block *sb, struct fs_context *fc)
+ ida_simple_remove(&vboxsf_bdi_ida, sbi->bdi_id);
+ if (sbi->nls)
+ unload_nls(sbi->nls);
++fail_destroy_idr:
+ idr_destroy(&sbi->ino_idr);
+ kfree(sbi);
+ return err;
+diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
+index 4b9d8fb393a84..df32355e3e38f 100644
+--- a/include/kvm/arm_pmu.h
++++ b/include/kvm/arm_pmu.h
+@@ -86,7 +86,7 @@ void kvm_vcpu_pmu_resync_el0(void);
+ */
+ #define kvm_pmu_update_vcpu_events(vcpu) \
+ do { \
+- if (!has_vhe() && kvm_vcpu_has_pmu(vcpu)) \
++ if (!has_vhe() && kvm_arm_support_pmu_v3()) \
+ vcpu->arch.pmu.events = *kvm_get_pmu_events(); \
+ } while (0)
+
+diff --git a/include/linux/bpf.h b/include/linux/bpf.h
+index e30100597d0a9..7d719976b5641 100644
+--- a/include/linux/bpf.h
++++ b/include/linux/bpf.h
+@@ -1568,12 +1568,26 @@ struct bpf_link {
+ enum bpf_link_type type;
+ const struct bpf_link_ops *ops;
+ struct bpf_prog *prog;
+- struct work_struct work;
++ /* rcu is used before freeing, work can be used to schedule that
++ * RCU-based freeing before that, so they never overlap
++ */
++ union {
++ struct rcu_head rcu;
++ struct work_struct work;
++ };
+ };
+
+ struct bpf_link_ops {
+ void (*release)(struct bpf_link *link);
++ /* deallocate link resources callback, called without RCU grace period
++ * waiting
++ */
+ void (*dealloc)(struct bpf_link *link);
++ /* deallocate link resources callback, called after RCU grace period;
++ * if underlying BPF program is sleepable we go through tasks trace
++ * RCU GP and then "classic" RCU GP
++ */
++ void (*dealloc_deferred)(struct bpf_link *link);
+ int (*detach)(struct bpf_link *link);
+ int (*update_prog)(struct bpf_link *link, struct bpf_prog *new_prog,
+ struct bpf_prog *old_prog);
+diff --git a/include/linux/device.h b/include/linux/device.h
+index 97c4b046c09d9..b9f5464f44ed8 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -1247,6 +1247,7 @@ void device_link_del(struct device_link *link);
+ void device_link_remove(void *consumer, struct device *supplier);
+ void device_links_supplier_sync_state_pause(void);
+ void device_links_supplier_sync_state_resume(void);
++void device_link_wait_removal(void);
+
+ /* Create alias, so I can be autoloaded. */
+ #define MODULE_ALIAS_CHARDEV(major,minor) \
+diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h
+index 854ad67a5f70e..73de1f6f0ab11 100644
+--- a/include/linux/io_uring_types.h
++++ b/include/linux/io_uring_types.h
+@@ -281,7 +281,6 @@ struct io_ring_ctx {
+
+ struct io_submit_state submit_state;
+
+- struct io_buffer_list *io_bl;
+ struct xarray io_bl_xa;
+
+ struct io_hash_table cancel_table_locked;
+diff --git a/include/linux/secretmem.h b/include/linux/secretmem.h
+index 35f3a4a8ceb1e..acf7e1a3f3def 100644
+--- a/include/linux/secretmem.h
++++ b/include/linux/secretmem.h
+@@ -13,10 +13,10 @@ static inline bool folio_is_secretmem(struct folio *folio)
+ /*
+ * Using folio_mapping() is quite slow because of the actual call
+ * instruction.
+- * We know that secretmem pages are not compound and LRU so we can
++ * We know that secretmem pages are not compound, so we can
+ * save a couple of cycles here.
+ */
+- if (folio_test_large(folio) || !folio_test_lru(folio))
++ if (folio_test_large(folio))
+ return false;
+
+ mapping = (struct address_space *)
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index d9a1ccfb57080..227f4514476b1 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -748,8 +748,6 @@ typedef unsigned char *sk_buff_data_t;
+ * @list: queue head
+ * @ll_node: anchor in an llist (eg socket defer_list)
+ * @sk: Socket we are owned by
+- * @ip_defrag_offset: (aka @sk) alternate use of @sk, used in
+- * fragmentation management
+ * @dev: Device we arrived on/are leaving by
+ * @dev_scratch: (aka @dev) alternate use of @dev when @dev would be %NULL
+ * @cb: Control buffer. Free for use by every layer. Put private vars here
+@@ -870,10 +868,7 @@ struct sk_buff {
+ struct llist_node ll_node;
+ };
+
+- union {
+- struct sock *sk;
+- int ip_defrag_offset;
+- };
++ struct sock *sk;
+
+ union {
+ ktime_t tstamp;
+diff --git a/include/linux/stackdepot.h b/include/linux/stackdepot.h
+index adcbb8f236000..bf0136891a0f2 100644
+--- a/include/linux/stackdepot.h
++++ b/include/linux/stackdepot.h
+@@ -30,6 +30,52 @@ typedef u32 depot_stack_handle_t;
+ */
+ #define STACK_DEPOT_EXTRA_BITS 5
+
++#define DEPOT_HANDLE_BITS (sizeof(depot_stack_handle_t) * 8)
++
++#define DEPOT_POOL_ORDER 2 /* Pool size order, 4 pages */
++#define DEPOT_POOL_SIZE (1LL << (PAGE_SHIFT + DEPOT_POOL_ORDER))
++#define DEPOT_STACK_ALIGN 4
++#define DEPOT_OFFSET_BITS (DEPOT_POOL_ORDER + PAGE_SHIFT - DEPOT_STACK_ALIGN)
++#define DEPOT_POOL_INDEX_BITS (DEPOT_HANDLE_BITS - DEPOT_OFFSET_BITS - \
++ STACK_DEPOT_EXTRA_BITS)
++
++#ifdef CONFIG_STACKDEPOT
++/* Compact structure that stores a reference to a stack. */
++union handle_parts {
++ depot_stack_handle_t handle;
++ struct {
++ u32 pool_index_plus_1 : DEPOT_POOL_INDEX_BITS;
++ u32 offset : DEPOT_OFFSET_BITS;
++ u32 extra : STACK_DEPOT_EXTRA_BITS;
++ };
++};
++
++struct stack_record {
++ struct list_head hash_list; /* Links in the hash table */
++ u32 hash; /* Hash in hash table */
++ u32 size; /* Number of stored frames */
++ union handle_parts handle; /* Constant after initialization */
++ refcount_t count;
++ union {
++ unsigned long entries[CONFIG_STACKDEPOT_MAX_FRAMES]; /* Frames */
++ struct {
++ /*
++ * An important invariant of the implementation is to
++ * only place a stack record onto the freelist iff its
++ * refcount is zero. Because stack records with a zero
++ * refcount are never considered as valid, it is safe to
++ * union @entries and freelist management state below.
++ * Conversely, as soon as an entry is off the freelist
++ * and its refcount becomes non-zero, the below must not
++ * be accessed until being placed back on the freelist.
++ */
++ struct list_head free_list; /* Links in the freelist */
++ unsigned long rcu_state; /* RCU cookie */
++ };
++ };
++};
++#endif
++
+ typedef u32 depot_flags_t;
+
+ /*
+diff --git a/include/linux/udp.h b/include/linux/udp.h
+index d04188714dca1..94e63b2695406 100644
+--- a/include/linux/udp.h
++++ b/include/linux/udp.h
+@@ -140,6 +140,24 @@ static inline void udp_cmsg_recv(struct msghdr *msg, struct sock *sk,
+ }
+ }
+
++DECLARE_STATIC_KEY_FALSE(udp_encap_needed_key);
++#if IS_ENABLED(CONFIG_IPV6)
++DECLARE_STATIC_KEY_FALSE(udpv6_encap_needed_key);
++#endif
++
++static inline bool udp_encap_needed(void)
++{
++ if (static_branch_unlikely(&udp_encap_needed_key))
++ return true;
++
++#if IS_ENABLED(CONFIG_IPV6)
++ if (static_branch_unlikely(&udpv6_encap_needed_key))
++ return true;
++#endif
++
++ return false;
++}
++
+ static inline bool udp_unexpected_gso(struct sock *sk, struct sk_buff *skb)
+ {
+ if (!skb_is_gso(skb))
+@@ -153,6 +171,16 @@ static inline bool udp_unexpected_gso(struct sock *sk, struct sk_buff *skb)
+ !udp_test_bit(ACCEPT_FRAGLIST, sk))
+ return true;
+
++ /* GSO packets lacking the SKB_GSO_UDP_TUNNEL/_CSUM bits might still
++ * land in a tunnel as the socket check in udp_gro_receive cannot be
++ * foolproof.
++ */
++ if (udp_encap_needed() &&
++ READ_ONCE(udp_sk(sk)->encap_rcv) &&
++ !(skb_shinfo(skb)->gso_type &
++ (SKB_GSO_UDP_TUNNEL | SKB_GSO_UDP_TUNNEL_CSUM)))
++ return true;
++
+ return false;
+ }
+
+diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
+index 0d231024570a3..03e68a8e229f5 100644
+--- a/include/net/bluetooth/hci.h
++++ b/include/net/bluetooth/hci.h
+@@ -176,6 +176,15 @@ enum {
+ */
+ HCI_QUIRK_USE_BDADDR_PROPERTY,
+
++ /* When this quirk is set, the Bluetooth Device Address provided by
++ * the 'local-bd-address' fwnode property is incorrectly specified in
++ * big-endian order.
++ *
++ * This quirk can be set before hci_register_dev is called or
++ * during the hdev->setup vendor callback.
++ */
++ HCI_QUIRK_BDADDR_PROPERTY_BROKEN,
++
+ /* When this quirk is set, the duplicate filtering during
+ * scanning is based on Bluetooth devices addresses. To allow
+ * RSSI based updates, restart scanning if needed.
+diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
+index 9ab4bf704e864..ccf171f7eb60d 100644
+--- a/include/net/inet_connection_sock.h
++++ b/include/net/inet_connection_sock.h
+@@ -175,6 +175,7 @@ void inet_csk_init_xmit_timers(struct sock *sk,
+ void (*delack_handler)(struct timer_list *),
+ void (*keepalive_handler)(struct timer_list *));
+ void inet_csk_clear_xmit_timers(struct sock *sk);
++void inet_csk_clear_xmit_timers_sync(struct sock *sk);
+
+ static inline void inet_csk_schedule_ack(struct sock *sk)
+ {
+diff --git a/include/net/mana/mana.h b/include/net/mana/mana.h
+index 76147feb0d10a..4eeedf14711b3 100644
+--- a/include/net/mana/mana.h
++++ b/include/net/mana/mana.h
+@@ -39,7 +39,6 @@ enum TRI_STATE {
+ #define COMP_ENTRY_SIZE 64
+
+ #define RX_BUFFERS_PER_QUEUE 512
+-#define MANA_RX_DATA_ALIGN 64
+
+ #define MAX_SEND_BUFFERS_PER_QUEUE 256
+
+diff --git a/include/net/sock.h b/include/net/sock.h
+index 54ca8dcbfb433..4afb4376c97e8 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -1779,6 +1779,13 @@ static inline void sock_owned_by_me(const struct sock *sk)
+ #endif
+ }
+
++static inline void sock_not_owned_by_me(const struct sock *sk)
++{
++#ifdef CONFIG_LOCKDEP
++ WARN_ON_ONCE(lockdep_sock_is_held(sk) && debug_locks);
++#endif
++}
++
+ static inline bool sock_owned_by_user(const struct sock *sk)
+ {
+ sock_owned_by_me(sk);
+diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h
+index 3cb4dc9bd70e4..3d54de168a6d9 100644
+--- a/include/net/xdp_sock.h
++++ b/include/net/xdp_sock.h
+@@ -188,6 +188,8 @@ static inline void xsk_tx_metadata_complete(struct xsk_tx_metadata_compl *compl,
+ {
+ if (!compl)
+ return;
++ if (!compl->tx_timestamp)
++ return;
+
+ *compl->tx_timestamp = ops->tmo_fill_timestamp(priv);
+ }
+diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h
+index a8bebac1e4b28..957295364a5e3 100644
+--- a/include/sound/hdaudio_ext.h
++++ b/include/sound/hdaudio_ext.h
+@@ -56,6 +56,9 @@ struct hdac_ext_stream {
+ u32 pphcldpl;
+ u32 pphcldpu;
+
++ u32 pplcllpl;
++ u32 pplcllpu;
++
+ bool decoupled:1;
+ bool link_locked:1;
+ bool link_prepared;
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index adf944bb5a2fe..572effd0af532 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -152,6 +152,7 @@ static bool io_uring_try_cancel_requests(struct io_ring_ctx *ctx,
+ static void io_queue_sqe(struct io_kiocb *req);
+
+ struct kmem_cache *req_cachep;
++static struct workqueue_struct *iou_wq __ro_after_init;
+
+ static int __read_mostly sysctl_io_uring_disabled;
+ static int __read_mostly sysctl_io_uring_group = -1;
+@@ -353,7 +354,6 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
+ err:
+ kfree(ctx->cancel_table.hbs);
+ kfree(ctx->cancel_table_locked.hbs);
+- kfree(ctx->io_bl);
+ xa_destroy(&ctx->io_bl_xa);
+ kfree(ctx);
+ return NULL;
+@@ -2906,7 +2906,6 @@ static __cold void io_ring_ctx_free(struct io_ring_ctx *ctx)
+ io_wq_put_hash(ctx->hash_map);
+ kfree(ctx->cancel_table.hbs);
+ kfree(ctx->cancel_table_locked.hbs);
+- kfree(ctx->io_bl);
+ xa_destroy(&ctx->io_bl_xa);
+ kfree(ctx);
+ }
+@@ -3141,7 +3140,7 @@ static __cold void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
+ * noise and overhead, there's no discernable change in runtime
+ * over using system_wq.
+ */
+- queue_work(system_unbound_wq, &ctx->exit_work);
++ queue_work(iou_wq, &ctx->exit_work);
+ }
+
+ static int io_uring_release(struct inode *inode, struct file *file)
+@@ -3423,14 +3422,15 @@ static void *io_uring_validate_mmap_request(struct file *file,
+ ptr = ctx->sq_sqes;
+ break;
+ case IORING_OFF_PBUF_RING: {
++ struct io_buffer_list *bl;
+ unsigned int bgid;
+
+ bgid = (offset & ~IORING_OFF_MMAP_MASK) >> IORING_OFF_PBUF_SHIFT;
+- rcu_read_lock();
+- ptr = io_pbuf_get_address(ctx, bgid);
+- rcu_read_unlock();
+- if (!ptr)
+- return ERR_PTR(-EINVAL);
++ bl = io_pbuf_get_bl(ctx, bgid);
++ if (IS_ERR(bl))
++ return bl;
++ ptr = bl->buf_ring;
++ io_put_bl(ctx, bl);
+ break;
+ }
+ default:
+@@ -4166,6 +4166,8 @@ static int __init io_uring_init(void)
+ SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT,
+ NULL);
+
++ iou_wq = alloc_workqueue("iou_exit", WQ_UNBOUND, 64);
++
+ #ifdef CONFIG_SYSCTL
+ register_sysctl_init("kernel", kernel_io_uring_disabled_table);
+ #endif
+diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
+index 18df5a9d2f5e7..b2c4f829376e3 100644
+--- a/io_uring/kbuf.c
++++ b/io_uring/kbuf.c
+@@ -17,8 +17,6 @@
+
+ #define IO_BUFFER_LIST_BUF_PER_PAGE (PAGE_SIZE / sizeof(struct io_uring_buf))
+
+-#define BGID_ARRAY 64
+-
+ /* BIDs are addressed by a 16-bit field in a CQE */
+ #define MAX_BIDS_PER_BGID (1 << 16)
+
+@@ -40,13 +38,9 @@ struct io_buf_free {
+ int inuse;
+ };
+
+-static struct io_buffer_list *__io_buffer_get_list(struct io_ring_ctx *ctx,
+- struct io_buffer_list *bl,
+- unsigned int bgid)
++static inline struct io_buffer_list *__io_buffer_get_list(struct io_ring_ctx *ctx,
++ unsigned int bgid)
+ {
+- if (bl && bgid < BGID_ARRAY)
+- return &bl[bgid];
+-
+ return xa_load(&ctx->io_bl_xa, bgid);
+ }
+
+@@ -55,7 +49,7 @@ static inline struct io_buffer_list *io_buffer_get_list(struct io_ring_ctx *ctx,
+ {
+ lockdep_assert_held(&ctx->uring_lock);
+
+- return __io_buffer_get_list(ctx, ctx->io_bl, bgid);
++ return __io_buffer_get_list(ctx, bgid);
+ }
+
+ static int io_buffer_add_list(struct io_ring_ctx *ctx,
+@@ -67,11 +61,7 @@ static int io_buffer_add_list(struct io_ring_ctx *ctx,
+ * always under the ->uring_lock, but the RCU lookup from mmap does.
+ */
+ bl->bgid = bgid;
+- smp_store_release(&bl->is_ready, 1);
+-
+- if (bgid < BGID_ARRAY)
+- return 0;
+-
++ atomic_set(&bl->refs, 1);
+ return xa_err(xa_store(&ctx->io_bl_xa, bgid, bl, GFP_KERNEL));
+ }
+
+@@ -217,24 +207,6 @@ void __user *io_buffer_select(struct io_kiocb *req, size_t *len,
+ return ret;
+ }
+
+-static __cold int io_init_bl_list(struct io_ring_ctx *ctx)
+-{
+- struct io_buffer_list *bl;
+- int i;
+-
+- bl = kcalloc(BGID_ARRAY, sizeof(struct io_buffer_list), GFP_KERNEL);
+- if (!bl)
+- return -ENOMEM;
+-
+- for (i = 0; i < BGID_ARRAY; i++) {
+- INIT_LIST_HEAD(&bl[i].buf_list);
+- bl[i].bgid = i;
+- }
+-
+- smp_store_release(&ctx->io_bl, bl);
+- return 0;
+-}
+-
+ /*
+ * Mark the given mapped range as free for reuse
+ */
+@@ -303,24 +275,24 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx,
+ return i;
+ }
+
++void io_put_bl(struct io_ring_ctx *ctx, struct io_buffer_list *bl)
++{
++ if (atomic_dec_and_test(&bl->refs)) {
++ __io_remove_buffers(ctx, bl, -1U);
++ kfree_rcu(bl, rcu);
++ }
++}
++
+ void io_destroy_buffers(struct io_ring_ctx *ctx)
+ {
+ struct io_buffer_list *bl;
+ struct list_head *item, *tmp;
+ struct io_buffer *buf;
+ unsigned long index;
+- int i;
+-
+- for (i = 0; i < BGID_ARRAY; i++) {
+- if (!ctx->io_bl)
+- break;
+- __io_remove_buffers(ctx, &ctx->io_bl[i], -1U);
+- }
+
+ xa_for_each(&ctx->io_bl_xa, index, bl) {
+ xa_erase(&ctx->io_bl_xa, bl->bgid);
+- __io_remove_buffers(ctx, bl, -1U);
+- kfree_rcu(bl, rcu);
++ io_put_bl(ctx, bl);
+ }
+
+ /*
+@@ -498,12 +470,6 @@ int io_provide_buffers(struct io_kiocb *req, unsigned int issue_flags)
+
+ io_ring_submit_lock(ctx, issue_flags);
+
+- if (unlikely(p->bgid < BGID_ARRAY && !ctx->io_bl)) {
+- ret = io_init_bl_list(ctx);
+- if (ret)
+- goto err;
+- }
+-
+ bl = io_buffer_get_list(ctx, p->bgid);
+ if (unlikely(!bl)) {
+ bl = kzalloc(sizeof(*bl), GFP_KERNEL_ACCOUNT);
+@@ -516,14 +482,9 @@ int io_provide_buffers(struct io_kiocb *req, unsigned int issue_flags)
+ if (ret) {
+ /*
+ * Doesn't need rcu free as it was never visible, but
+- * let's keep it consistent throughout. Also can't
+- * be a lower indexed array group, as adding one
+- * where lookup failed cannot happen.
++ * let's keep it consistent throughout.
+ */
+- if (p->bgid >= BGID_ARRAY)
+- kfree_rcu(bl, rcu);
+- else
+- WARN_ON_ONCE(1);
++ kfree_rcu(bl, rcu);
+ goto err;
+ }
+ }
+@@ -688,12 +649,6 @@ int io_register_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg)
+ if (reg.ring_entries >= 65536)
+ return -EINVAL;
+
+- if (unlikely(reg.bgid < BGID_ARRAY && !ctx->io_bl)) {
+- int ret = io_init_bl_list(ctx);
+- if (ret)
+- return ret;
+- }
+-
+ bl = io_buffer_get_list(ctx, reg.bgid);
+ if (bl) {
+ /* if mapped buffer ring OR classic exists, don't allow */
+@@ -742,11 +697,8 @@ int io_unregister_pbuf_ring(struct io_ring_ctx *ctx, void __user *arg)
+ if (!bl->is_mapped)
+ return -EINVAL;
+
+- __io_remove_buffers(ctx, bl, -1U);
+- if (bl->bgid >= BGID_ARRAY) {
+- xa_erase(&ctx->io_bl_xa, bl->bgid);
+- kfree_rcu(bl, rcu);
+- }
++ xa_erase(&ctx->io_bl_xa, bl->bgid);
++ io_put_bl(ctx, bl);
+ return 0;
+ }
+
+@@ -776,23 +728,35 @@ int io_register_pbuf_status(struct io_ring_ctx *ctx, void __user *arg)
+ return 0;
+ }
+
+-void *io_pbuf_get_address(struct io_ring_ctx *ctx, unsigned long bgid)
++struct io_buffer_list *io_pbuf_get_bl(struct io_ring_ctx *ctx,
++ unsigned long bgid)
+ {
+ struct io_buffer_list *bl;
++ bool ret;
+
+- bl = __io_buffer_get_list(ctx, smp_load_acquire(&ctx->io_bl), bgid);
+-
+- if (!bl || !bl->is_mmap)
+- return NULL;
+ /*
+- * Ensure the list is fully setup. Only strictly needed for RCU lookup
+- * via mmap, and in that case only for the array indexed groups. For
+- * the xarray lookups, it's either visible and ready, or not at all.
++ * We have to be a bit careful here - we're inside mmap and cannot grab
++ * the uring_lock. This means the buffer_list could be simultaneously
++ * going away, if someone is trying to be sneaky. Look it up under rcu
++ * so we know it's not going away, and attempt to grab a reference to
++ * it. If the ref is already zero, then fail the mapping. If successful,
++ * the caller will call io_put_bl() to drop the the reference at at the
++ * end. This may then safely free the buffer_list (and drop the pages)
++ * at that point, vm_insert_pages() would've already grabbed the
++ * necessary vma references.
+ */
+- if (!smp_load_acquire(&bl->is_ready))
+- return NULL;
+-
+- return bl->buf_ring;
++ rcu_read_lock();
++ bl = xa_load(&ctx->io_bl_xa, bgid);
++ /* must be a mmap'able buffer ring and have pages */
++ ret = false;
++ if (bl && bl->is_mmap)
++ ret = atomic_inc_not_zero(&bl->refs);
++ rcu_read_unlock();
++
++ if (ret)
++ return bl;
++
++ return ERR_PTR(-EINVAL);
+ }
+
+ /*
+diff --git a/io_uring/kbuf.h b/io_uring/kbuf.h
+index 53dfaa71a397c..038091a0047d4 100644
+--- a/io_uring/kbuf.h
++++ b/io_uring/kbuf.h
+@@ -25,12 +25,12 @@ struct io_buffer_list {
+ __u16 head;
+ __u16 mask;
+
++ atomic_t refs;
++
+ /* ring mapped provided buffers */
+ __u8 is_mapped;
+ /* ring mapped provided buffers, but mmap'ed by application */
+ __u8 is_mmap;
+- /* bl is visible from an RCU point of view for lookup */
+- __u8 is_ready;
+ };
+
+ struct io_buffer {
+@@ -61,7 +61,9 @@ unsigned int __io_put_kbuf(struct io_kiocb *req, unsigned issue_flags);
+
+ bool io_kbuf_recycle_legacy(struct io_kiocb *req, unsigned issue_flags);
+
+-void *io_pbuf_get_address(struct io_ring_ctx *ctx, unsigned long bgid);
++void io_put_bl(struct io_ring_ctx *ctx, struct io_buffer_list *bl);
++struct io_buffer_list *io_pbuf_get_bl(struct io_ring_ctx *ctx,
++ unsigned long bgid);
+
+ static inline bool io_kbuf_recycle_ring(struct io_kiocb *req)
+ {
+diff --git a/io_uring/rw.c b/io_uring/rw.c
+index 2b84ce8a8a677..dd6fe3b328f40 100644
+--- a/io_uring/rw.c
++++ b/io_uring/rw.c
+@@ -937,6 +937,13 @@ int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags)
+
+ ret = __io_read(req, issue_flags);
+
++ /*
++ * If the file doesn't support proper NOWAIT, then disable multishot
++ * and stay in single shot mode.
++ */
++ if (!io_file_supports_nowait(req))
++ req->flags &= ~REQ_F_APOLL_MULTISHOT;
++
+ /*
+ * If we get -EAGAIN, recycle our buffer and just let normal poll
+ * handling arm it.
+@@ -956,7 +963,7 @@ int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags)
+ /*
+ * Any successful return value will keep the multishot read armed.
+ */
+- if (ret > 0) {
++ if (ret > 0 && req->flags & REQ_F_APOLL_MULTISHOT) {
+ /*
+ * Put our buffer and post a CQE. If we fail to post a CQE, then
+ * jump to the termination path. This request is then done.
+diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
+index f526b7573e97c..418a8188a8e84 100644
+--- a/kernel/bpf/Makefile
++++ b/kernel/bpf/Makefile
+@@ -4,7 +4,7 @@ ifneq ($(CONFIG_BPF_JIT_ALWAYS_ON),y)
+ # ___bpf_prog_run() needs GCSE disabled on x86; see 3193c0836f203 for details
+ cflags-nogcse-$(CONFIG_X86)$(CONFIG_CC_IS_GCC) := -fno-gcse
+ endif
+-CFLAGS_core.o += $(call cc-disable-warning, override-init) $(cflags-nogcse-yy)
++CFLAGS_core.o += -Wno-override-init $(cflags-nogcse-yy)
+
+ obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o log.o
+ obj-$(CONFIG_BPF_SYSCALL) += bpf_iter.o map_iter.o task_iter.o prog_iter.o link_iter.o
+diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
+index a1f18681721c7..0f90b6b27430d 100644
+--- a/kernel/bpf/syscall.c
++++ b/kernel/bpf/syscall.c
+@@ -2895,17 +2895,46 @@ void bpf_link_inc(struct bpf_link *link)
+ atomic64_inc(&link->refcnt);
+ }
+
++static void bpf_link_defer_dealloc_rcu_gp(struct rcu_head *rcu)
++{
++ struct bpf_link *link = container_of(rcu, struct bpf_link, rcu);
++
++ /* free bpf_link and its containing memory */
++ link->ops->dealloc_deferred(link);
++}
++
++static void bpf_link_defer_dealloc_mult_rcu_gp(struct rcu_head *rcu)
++{
++ if (rcu_trace_implies_rcu_gp())
++ bpf_link_defer_dealloc_rcu_gp(rcu);
++ else
++ call_rcu(rcu, bpf_link_defer_dealloc_rcu_gp);
++}
++
+ /* bpf_link_free is guaranteed to be called from process context */
+ static void bpf_link_free(struct bpf_link *link)
+ {
++ bool sleepable = false;
++
+ bpf_link_free_id(link->id);
+ if (link->prog) {
++ sleepable = link->prog->aux->sleepable;
+ /* detach BPF program, clean up used resources */
+ link->ops->release(link);
+ bpf_prog_put(link->prog);
+ }
+- /* free bpf_link and its containing memory */
+- link->ops->dealloc(link);
++ if (link->ops->dealloc_deferred) {
++ /* schedule BPF link deallocation; if underlying BPF program
++ * is sleepable, we need to first wait for RCU tasks trace
++ * sync, then go through "classic" RCU grace period
++ */
++ if (sleepable)
++ call_rcu_tasks_trace(&link->rcu, bpf_link_defer_dealloc_mult_rcu_gp);
++ else
++ call_rcu(&link->rcu, bpf_link_defer_dealloc_rcu_gp);
++ }
++ if (link->ops->dealloc)
++ link->ops->dealloc(link);
+ }
+
+ static void bpf_link_put_deferred(struct work_struct *work)
+@@ -3415,7 +3444,7 @@ static int bpf_raw_tp_link_fill_link_info(const struct bpf_link *link,
+
+ static const struct bpf_link_ops bpf_raw_tp_link_lops = {
+ .release = bpf_raw_tp_link_release,
+- .dealloc = bpf_raw_tp_link_dealloc,
++ .dealloc_deferred = bpf_raw_tp_link_dealloc,
+ .show_fdinfo = bpf_raw_tp_link_show_fdinfo,
+ .fill_link_info = bpf_raw_tp_link_fill_link_info,
+ };
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index ddea9567f7559..19e575e6b7fe0 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -6618,6 +6618,11 @@ static int check_stack_access_within_bounds(
+ err = check_stack_slot_within_bounds(env, min_off, state, type);
+ if (!err && max_off > 0)
+ err = -EINVAL; /* out of stack access into non-negative offsets */
++ if (!err && access_size < 0)
++ /* access_size should not be negative (or overflow an int); others checks
++ * along the way should have prevented such an access.
++ */
++ err = -EFAULT; /* invalid negative access size; integer overflow? */
+
+ if (err) {
+ if (tnum_is_const(reg->var_off)) {
+diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
+index 7ac6c52b25ebc..c8d1ebc438380 100644
+--- a/kernel/trace/bpf_trace.c
++++ b/kernel/trace/bpf_trace.c
+@@ -2713,7 +2713,7 @@ static int bpf_kprobe_multi_link_fill_link_info(const struct bpf_link *link,
+
+ static const struct bpf_link_ops bpf_kprobe_multi_link_lops = {
+ .release = bpf_kprobe_multi_link_release,
+- .dealloc = bpf_kprobe_multi_link_dealloc,
++ .dealloc_deferred = bpf_kprobe_multi_link_dealloc,
+ .fill_link_info = bpf_kprobe_multi_link_fill_link_info,
+ };
+
+@@ -3142,6 +3142,9 @@ static void bpf_uprobe_multi_link_release(struct bpf_link *link)
+
+ umulti_link = container_of(link, struct bpf_uprobe_multi_link, link);
+ bpf_uprobe_unregister(&umulti_link->path, umulti_link->uprobes, umulti_link->cnt);
++ if (umulti_link->task)
++ put_task_struct(umulti_link->task);
++ path_put(&umulti_link->path);
+ }
+
+ static void bpf_uprobe_multi_link_dealloc(struct bpf_link *link)
+@@ -3149,9 +3152,6 @@ static void bpf_uprobe_multi_link_dealloc(struct bpf_link *link)
+ struct bpf_uprobe_multi_link *umulti_link;
+
+ umulti_link = container_of(link, struct bpf_uprobe_multi_link, link);
+- if (umulti_link->task)
+- put_task_struct(umulti_link->task);
+- path_put(&umulti_link->path);
+ kvfree(umulti_link->uprobes);
+ kfree(umulti_link);
+ }
+@@ -3227,7 +3227,7 @@ static int bpf_uprobe_multi_link_fill_link_info(const struct bpf_link *link,
+
+ static const struct bpf_link_ops bpf_uprobe_multi_link_lops = {
+ .release = bpf_uprobe_multi_link_release,
+- .dealloc = bpf_uprobe_multi_link_dealloc,
++ .dealloc_deferred = bpf_uprobe_multi_link_dealloc,
+ .fill_link_info = bpf_uprobe_multi_link_fill_link_info,
+ };
+
+diff --git a/lib/stackdepot.c b/lib/stackdepot.c
+index c1ec2b4b6dabf..ee830f14afb78 100644
+--- a/lib/stackdepot.c
++++ b/lib/stackdepot.c
+@@ -36,55 +36,12 @@
+ #include <linux/memblock.h>
+ #include <linux/kasan-enabled.h>
+
+-#define DEPOT_HANDLE_BITS (sizeof(depot_stack_handle_t) * 8)
+-
+-#define DEPOT_POOL_ORDER 2 /* Pool size order, 4 pages */
+-#define DEPOT_POOL_SIZE (1LL << (PAGE_SHIFT + DEPOT_POOL_ORDER))
+-#define DEPOT_STACK_ALIGN 4
+-#define DEPOT_OFFSET_BITS (DEPOT_POOL_ORDER + PAGE_SHIFT - DEPOT_STACK_ALIGN)
+-#define DEPOT_POOL_INDEX_BITS (DEPOT_HANDLE_BITS - DEPOT_OFFSET_BITS - \
+- STACK_DEPOT_EXTRA_BITS)
+ #define DEPOT_POOLS_CAP 8192
+ /* The pool_index is offset by 1 so the first record does not have a 0 handle. */
+ #define DEPOT_MAX_POOLS \
+ (((1LL << (DEPOT_POOL_INDEX_BITS)) - 1 < DEPOT_POOLS_CAP) ? \
+ (1LL << (DEPOT_POOL_INDEX_BITS)) - 1 : DEPOT_POOLS_CAP)
+
+-/* Compact structure that stores a reference to a stack. */
+-union handle_parts {
+- depot_stack_handle_t handle;
+- struct {
+- u32 pool_index : DEPOT_POOL_INDEX_BITS; /* pool_index is offset by 1 */
+- u32 offset : DEPOT_OFFSET_BITS;
+- u32 extra : STACK_DEPOT_EXTRA_BITS;
+- };
+-};
+-
+-struct stack_record {
+- struct list_head hash_list; /* Links in the hash table */
+- u32 hash; /* Hash in hash table */
+- u32 size; /* Number of stored frames */
+- union handle_parts handle; /* Constant after initialization */
+- refcount_t count;
+- union {
+- unsigned long entries[CONFIG_STACKDEPOT_MAX_FRAMES]; /* Frames */
+- struct {
+- /*
+- * An important invariant of the implementation is to
+- * only place a stack record onto the freelist iff its
+- * refcount is zero. Because stack records with a zero
+- * refcount are never considered as valid, it is safe to
+- * union @entries and freelist management state below.
+- * Conversely, as soon as an entry is off the freelist
+- * and its refcount becomes non-zero, the below must not
+- * be accessed until being placed back on the freelist.
+- */
+- struct list_head free_list; /* Links in the freelist */
+- unsigned long rcu_state; /* RCU cookie */
+- };
+- };
+-};
+-
+ static bool stack_depot_disabled;
+ static bool __stack_depot_early_init_requested __initdata = IS_ENABLED(CONFIG_STACKDEPOT_ALWAYS_INIT);
+ static bool __stack_depot_early_init_passed __initdata;
+@@ -373,7 +330,7 @@ static struct stack_record *depot_pop_free_pool(void **prealloc, size_t size)
+ stack = current_pool + pool_offset;
+
+ /* Pre-initialize handle once. */
+- stack->handle.pool_index = pool_index + 1;
++ stack->handle.pool_index_plus_1 = pool_index + 1;
+ stack->handle.offset = pool_offset >> DEPOT_STACK_ALIGN;
+ stack->handle.extra = 0;
+ INIT_LIST_HEAD(&stack->hash_list);
+@@ -484,7 +441,7 @@ static struct stack_record *depot_fetch_stack(depot_stack_handle_t handle)
+ const int pools_num_cached = READ_ONCE(pools_num);
+ union handle_parts parts = { .handle = handle };
+ void *pool;
+- u32 pool_index = parts.pool_index - 1;
++ u32 pool_index = parts.pool_index_plus_1 - 1;
+ size_t offset = parts.offset << DEPOT_STACK_ALIGN;
+ struct stack_record *stack;
+
+diff --git a/mm/Makefile b/mm/Makefile
+index e4b5b75aaec9c..4abb40b911ec4 100644
+--- a/mm/Makefile
++++ b/mm/Makefile
+@@ -29,8 +29,7 @@ KCOV_INSTRUMENT_mmzone.o := n
+ KCOV_INSTRUMENT_vmstat.o := n
+ KCOV_INSTRUMENT_failslab.o := n
+
+-CFLAGS_init-mm.o += $(call cc-disable-warning, override-init)
+-CFLAGS_init-mm.o += $(call cc-disable-warning, initializer-overrides)
++CFLAGS_init-mm.o += -Wno-override-init
+
+ mmu-y := nommu.o
+ mmu-$(CONFIG_MMU) := highmem.o memory.o mincore.o \
+diff --git a/mm/memory.c b/mm/memory.c
+index 0bfc8b007c01a..296e4f05e8778 100644
+--- a/mm/memory.c
++++ b/mm/memory.c
+@@ -5837,6 +5837,10 @@ int follow_phys(struct vm_area_struct *vma,
+ goto out;
+ pte = ptep_get(ptep);
+
++ /* Never return PFNs of anon folios in COW mappings. */
++ if (vm_normal_folio(vma, address, pte))
++ goto unlock;
++
+ if ((flags & FOLL_WRITE) && !pte_write(pte))
+ goto unlock;
+
+diff --git a/net/9p/client.c b/net/9p/client.c
+index e265a0ca6bddd..f7e90b4769bba 100644
+--- a/net/9p/client.c
++++ b/net/9p/client.c
+@@ -1583,7 +1583,7 @@ p9_client_read_once(struct p9_fid *fid, u64 offset, struct iov_iter *to,
+ received = rsize;
+ }
+
+- p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count);
++ p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", received);
+
+ if (non_zc) {
+ int n = copy_to_iter(dataptr, received, to);
+@@ -1609,9 +1609,6 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
+ int total = 0;
+ *err = 0;
+
+- p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %zd\n",
+- fid->fid, offset, iov_iter_count(from));
+-
+ while (iov_iter_count(from)) {
+ int count = iov_iter_count(from);
+ int rsize = fid->iounit;
+@@ -1623,6 +1620,9 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
+ if (count < rsize)
+ rsize = count;
+
++ p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d (/%d)\n",
++ fid->fid, offset, rsize, count);
++
+ /* Don't bother zerocopy for small IO (< 1024) */
+ if (clnt->trans_mod->zc_request && rsize > 1024) {
+ req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, from, 0,
+@@ -1650,7 +1650,7 @@ p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err)
+ written = rsize;
+ }
+
+- p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);
++ p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", written);
+
+ p9_req_put(clnt, req);
+ iov_iter_revert(from, count - written - iov_iter_count(from));
+diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
+index c5462486dbca1..282ec581c0720 100644
+--- a/net/ax25/ax25_dev.c
++++ b/net/ax25/ax25_dev.c
+@@ -105,7 +105,7 @@ void ax25_dev_device_down(struct net_device *dev)
+ spin_lock_bh(&ax25_dev_lock);
+
+ #ifdef CONFIG_AX25_DAMA_SLAVE
+- ax25_ds_del_timer(ax25_dev);
++ timer_shutdown_sync(&ax25_dev->dama.slave_timer);
+ #endif
+
+ /*
+diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c
+index 233453807b509..ce3ff2fa72e58 100644
+--- a/net/bluetooth/hci_debugfs.c
++++ b/net/bluetooth/hci_debugfs.c
+@@ -218,10 +218,12 @@ static int conn_info_min_age_set(void *data, u64 val)
+ {
+ struct hci_dev *hdev = data;
+
+- if (val == 0 || val > hdev->conn_info_max_age)
++ hci_dev_lock(hdev);
++ if (val == 0 || val > hdev->conn_info_max_age) {
++ hci_dev_unlock(hdev);
+ return -EINVAL;
++ }
+
+- hci_dev_lock(hdev);
+ hdev->conn_info_min_age = val;
+ hci_dev_unlock(hdev);
+
+@@ -246,10 +248,12 @@ static int conn_info_max_age_set(void *data, u64 val)
+ {
+ struct hci_dev *hdev = data;
+
+- if (val == 0 || val < hdev->conn_info_min_age)
++ hci_dev_lock(hdev);
++ if (val == 0 || val < hdev->conn_info_min_age) {
++ hci_dev_unlock(hdev);
+ return -EINVAL;
++ }
+
+- hci_dev_lock(hdev);
+ hdev->conn_info_max_age = val;
+ hci_dev_unlock(hdev);
+
+@@ -567,10 +571,12 @@ static int sniff_min_interval_set(void *data, u64 val)
+ {
+ struct hci_dev *hdev = data;
+
+- if (val == 0 || val % 2 || val > hdev->sniff_max_interval)
++ hci_dev_lock(hdev);
++ if (val == 0 || val % 2 || val > hdev->sniff_max_interval) {
++ hci_dev_unlock(hdev);
+ return -EINVAL;
++ }
+
+- hci_dev_lock(hdev);
+ hdev->sniff_min_interval = val;
+ hci_dev_unlock(hdev);
+
+@@ -595,10 +601,12 @@ static int sniff_max_interval_set(void *data, u64 val)
+ {
+ struct hci_dev *hdev = data;
+
+- if (val == 0 || val % 2 || val < hdev->sniff_min_interval)
++ hci_dev_lock(hdev);
++ if (val == 0 || val % 2 || val < hdev->sniff_min_interval) {
++ hci_dev_unlock(hdev);
+ return -EINVAL;
++ }
+
+- hci_dev_lock(hdev);
+ hdev->sniff_max_interval = val;
+ hci_dev_unlock(hdev);
+
+@@ -850,10 +858,12 @@ static int conn_min_interval_set(void *data, u64 val)
+ {
+ struct hci_dev *hdev = data;
+
+- if (val < 0x0006 || val > 0x0c80 || val > hdev->le_conn_max_interval)
++ hci_dev_lock(hdev);
++ if (val < 0x0006 || val > 0x0c80 || val > hdev->le_conn_max_interval) {
++ hci_dev_unlock(hdev);
+ return -EINVAL;
++ }
+
+- hci_dev_lock(hdev);
+ hdev->le_conn_min_interval = val;
+ hci_dev_unlock(hdev);
+
+@@ -878,10 +888,12 @@ static int conn_max_interval_set(void *data, u64 val)
+ {
+ struct hci_dev *hdev = data;
+
+- if (val < 0x0006 || val > 0x0c80 || val < hdev->le_conn_min_interval)
++ hci_dev_lock(hdev);
++ if (val < 0x0006 || val > 0x0c80 || val < hdev->le_conn_min_interval) {
++ hci_dev_unlock(hdev);
+ return -EINVAL;
++ }
+
+- hci_dev_lock(hdev);
+ hdev->le_conn_max_interval = val;
+ hci_dev_unlock(hdev);
+
+@@ -990,10 +1002,12 @@ static int adv_min_interval_set(void *data, u64 val)
+ {
+ struct hci_dev *hdev = data;
+
+- if (val < 0x0020 || val > 0x4000 || val > hdev->le_adv_max_interval)
++ hci_dev_lock(hdev);
++ if (val < 0x0020 || val > 0x4000 || val > hdev->le_adv_max_interval) {
++ hci_dev_unlock(hdev);
+ return -EINVAL;
++ }
+
+- hci_dev_lock(hdev);
+ hdev->le_adv_min_interval = val;
+ hci_dev_unlock(hdev);
+
+@@ -1018,10 +1032,12 @@ static int adv_max_interval_set(void *data, u64 val)
+ {
+ struct hci_dev *hdev = data;
+
+- if (val < 0x0020 || val > 0x4000 || val < hdev->le_adv_min_interval)
++ hci_dev_lock(hdev);
++ if (val < 0x0020 || val > 0x4000 || val < hdev->le_adv_min_interval) {
++ hci_dev_unlock(hdev);
+ return -EINVAL;
++ }
+
+- hci_dev_lock(hdev);
+ hdev->le_adv_max_interval = val;
+ hci_dev_unlock(hdev);
+
+diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
+index 6275b14b56927..3b63513f57ba8 100644
+--- a/net/bluetooth/hci_event.c
++++ b/net/bluetooth/hci_event.c
+@@ -3219,6 +3219,31 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
+ if (test_bit(HCI_ENCRYPT, &hdev->flags))
+ set_bit(HCI_CONN_ENCRYPT, &conn->flags);
+
++ /* "Link key request" completed ahead of "connect request" completes */
++ if (ev->encr_mode == 1 && !test_bit(HCI_CONN_ENCRYPT, &conn->flags) &&
++ ev->link_type == ACL_LINK) {
++ struct link_key *key;
++ struct hci_cp_read_enc_key_size cp;
++
++ key = hci_find_link_key(hdev, &ev->bdaddr);
++ if (key) {
++ set_bit(HCI_CONN_ENCRYPT, &conn->flags);
++
++ if (!(hdev->commands[20] & 0x10)) {
++ conn->enc_key_size = HCI_LINK_KEY_SIZE;
++ } else {
++ cp.handle = cpu_to_le16(conn->handle);
++ if (hci_send_cmd(hdev, HCI_OP_READ_ENC_KEY_SIZE,
++ sizeof(cp), &cp)) {
++ bt_dev_err(hdev, "sending read key size failed");
++ conn->enc_key_size = HCI_LINK_KEY_SIZE;
++ }
++ }
++
++ hci_encrypt_cfm(conn, ev->status);
++ }
++ }
++
+ /* Get remote features */
+ if (conn->type == ACL_LINK) {
+ struct hci_cp_read_remote_features cp;
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 44ca5ea223e3f..824ce03bb361b 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -3224,7 +3224,10 @@ static void hci_dev_get_bd_addr_from_property(struct hci_dev *hdev)
+ if (ret < 0 || !bacmp(&ba, BDADDR_ANY))
+ return;
+
+- bacpy(&hdev->public_addr, &ba);
++ if (test_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks))
++ baswap(&hdev->public_addr, &ba);
++ else
++ bacpy(&hdev->public_addr, &ba);
+ }
+
+ struct hci_init_stage {
+diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
+index 99d82676f780a..cbd0e3586c3f6 100644
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -1111,6 +1111,8 @@ static int do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ struct ebt_table_info *newinfo;
+ struct ebt_replace tmp;
+
++ if (len < sizeof(tmp))
++ return -EINVAL;
+ if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
+ return -EFAULT;
+
+@@ -1423,6 +1425,8 @@ static int update_counters(struct net *net, sockptr_t arg, unsigned int len)
+ {
+ struct ebt_replace hlp;
+
++ if (len < sizeof(hlp))
++ return -EINVAL;
+ if (copy_from_sockptr(&hlp, arg, sizeof(hlp)))
+ return -EFAULT;
+
+@@ -2352,6 +2356,8 @@ static int compat_update_counters(struct net *net, sockptr_t arg,
+ {
+ struct compat_ebt_replace hlp;
+
++ if (len < sizeof(hlp))
++ return -EINVAL;
+ if (copy_from_sockptr(&hlp, arg, sizeof(hlp)))
+ return -EFAULT;
+
+diff --git a/net/core/gro.c b/net/core/gro.c
+index 0759277dc14ee..cefddf65f7db0 100644
+--- a/net/core/gro.c
++++ b/net/core/gro.c
+@@ -195,8 +195,9 @@ int skb_gro_receive(struct sk_buff *p, struct sk_buff *skb)
+ }
+
+ merge:
+- /* sk owenrship - if any - completely transferred to the aggregated packet */
++ /* sk ownership - if any - completely transferred to the aggregated packet */
+ skb->destructor = NULL;
++ skb->sk = NULL;
+ delta_truesize = skb->truesize;
+ if (offset > headlen) {
+ unsigned int eat = offset - headlen;
+diff --git a/net/core/sock_map.c b/net/core/sock_map.c
+index 27d733c0f65e1..8598466a38057 100644
+--- a/net/core/sock_map.c
++++ b/net/core/sock_map.c
+@@ -411,6 +411,9 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,
+ struct sock *sk;
+ int err = 0;
+
++ if (irqs_disabled())
++ return -EOPNOTSUPP; /* locks here are hardirq-unsafe */
++
+ spin_lock_bh(&stab->lock);
+ sk = *psk;
+ if (!sk_test || sk_test == sk)
+@@ -933,6 +936,9 @@ static long sock_hash_delete_elem(struct bpf_map *map, void *key)
+ struct bpf_shtab_elem *elem;
+ int ret = -ENOENT;
+
++ if (irqs_disabled())
++ return -EOPNOTSUPP; /* locks here are hardirq-unsafe */
++
+ hash = sock_hash_bucket_hash(key, key_size);
+ bucket = sock_hash_select_bucket(htab, hash);
+
+diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c
+index e5742f2a2d522..1b6457f357bdb 100644
+--- a/net/hsr/hsr_slave.c
++++ b/net/hsr/hsr_slave.c
+@@ -220,7 +220,8 @@ void hsr_del_port(struct hsr_port *port)
+ netdev_update_features(master->dev);
+ dev_set_mtu(master->dev, hsr_get_max_mtu(hsr));
+ netdev_rx_handler_unregister(port->dev);
+- dev_set_promiscuity(port->dev, -1);
++ if (!port->hsr->fwd_offloaded)
++ dev_set_promiscuity(port->dev, -1);
+ netdev_upper_dev_unlink(port->dev, master->dev);
+ }
+
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index 459af1f897395..d1492c649aea0 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -203,8 +203,15 @@ static bool __inet_bhash2_conflict(const struct sock *sk, struct sock *sk2,
+ kuid_t sk_uid, bool relax,
+ bool reuseport_cb_ok, bool reuseport_ok)
+ {
+- if (sk->sk_family == AF_INET && ipv6_only_sock(sk2))
+- return false;
++ if (ipv6_only_sock(sk2)) {
++ if (sk->sk_family == AF_INET)
++ return false;
++
++#if IS_ENABLED(CONFIG_IPV6)
++ if (ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr))
++ return false;
++#endif
++ }
+
+ return inet_bind_conflict(sk, sk2, sk_uid, relax,
+ reuseport_cb_ok, reuseport_ok);
+@@ -287,6 +294,7 @@ static bool inet_bhash2_addr_any_conflict(const struct sock *sk, int port, int l
+ struct sock_reuseport *reuseport_cb;
+ struct inet_bind_hashbucket *head2;
+ struct inet_bind2_bucket *tb2;
++ bool conflict = false;
+ bool reuseport_cb_ok;
+
+ rcu_read_lock();
+@@ -299,18 +307,20 @@ static bool inet_bhash2_addr_any_conflict(const struct sock *sk, int port, int l
+
+ spin_lock(&head2->lock);
+
+- inet_bind_bucket_for_each(tb2, &head2->chain)
+- if (inet_bind2_bucket_match_addr_any(tb2, net, port, l3mdev, sk))
+- break;
++ inet_bind_bucket_for_each(tb2, &head2->chain) {
++ if (!inet_bind2_bucket_match_addr_any(tb2, net, port, l3mdev, sk))
++ continue;
+
+- if (tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, reuseport_cb_ok,
+- reuseport_ok)) {
+- spin_unlock(&head2->lock);
+- return true;
++ if (!inet_bhash2_conflict(sk, tb2, uid, relax, reuseport_cb_ok, reuseport_ok))
++ continue;
++
++ conflict = true;
++ break;
+ }
+
+ spin_unlock(&head2->lock);
+- return false;
++
++ return conflict;
+ }
+
+ /*
+@@ -771,6 +781,20 @@ void inet_csk_clear_xmit_timers(struct sock *sk)
+ }
+ EXPORT_SYMBOL(inet_csk_clear_xmit_timers);
+
++void inet_csk_clear_xmit_timers_sync(struct sock *sk)
++{
++ struct inet_connection_sock *icsk = inet_csk(sk);
++
++ /* ongoing timer handlers need to acquire socket lock. */
++ sock_not_owned_by_me(sk);
++
++ icsk->icsk_pending = icsk->icsk_ack.pending = 0;
++
++ sk_stop_timer_sync(sk, &icsk->icsk_retransmit_timer);
++ sk_stop_timer_sync(sk, &icsk->icsk_delack_timer);
++ sk_stop_timer_sync(sk, &sk->sk_timer);
++}
++
+ void inet_csk_delete_keepalive_timer(struct sock *sk)
+ {
+ sk_stop_timer(sk, &sk->sk_timer);
+diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
+index 7072fc0783ef5..c88c9034d6300 100644
+--- a/net/ipv4/inet_fragment.c
++++ b/net/ipv4/inet_fragment.c
+@@ -24,6 +24,8 @@
+ #include <net/ip.h>
+ #include <net/ipv6.h>
+
++#include "../core/sock_destructor.h"
++
+ /* Use skb->cb to track consecutive/adjacent fragments coming at
+ * the end of the queue. Nodes in the rb-tree queue will
+ * contain "runs" of one or more adjacent fragments.
+@@ -39,6 +41,7 @@ struct ipfrag_skb_cb {
+ };
+ struct sk_buff *next_frag;
+ int frag_run_len;
++ int ip_defrag_offset;
+ };
+
+ #define FRAG_CB(skb) ((struct ipfrag_skb_cb *)((skb)->cb))
+@@ -396,12 +399,12 @@ int inet_frag_queue_insert(struct inet_frag_queue *q, struct sk_buff *skb,
+ */
+ if (!last)
+ fragrun_create(q, skb); /* First fragment. */
+- else if (last->ip_defrag_offset + last->len < end) {
++ else if (FRAG_CB(last)->ip_defrag_offset + last->len < end) {
+ /* This is the common case: skb goes to the end. */
+ /* Detect and discard overlaps. */
+- if (offset < last->ip_defrag_offset + last->len)
++ if (offset < FRAG_CB(last)->ip_defrag_offset + last->len)
+ return IPFRAG_OVERLAP;
+- if (offset == last->ip_defrag_offset + last->len)
++ if (offset == FRAG_CB(last)->ip_defrag_offset + last->len)
+ fragrun_append_to_last(q, skb);
+ else
+ fragrun_create(q, skb);
+@@ -418,13 +421,13 @@ int inet_frag_queue_insert(struct inet_frag_queue *q, struct sk_buff *skb,
+
+ parent = *rbn;
+ curr = rb_to_skb(parent);
+- curr_run_end = curr->ip_defrag_offset +
++ curr_run_end = FRAG_CB(curr)->ip_defrag_offset +
+ FRAG_CB(curr)->frag_run_len;
+- if (end <= curr->ip_defrag_offset)
++ if (end <= FRAG_CB(curr)->ip_defrag_offset)
+ rbn = &parent->rb_left;
+ else if (offset >= curr_run_end)
+ rbn = &parent->rb_right;
+- else if (offset >= curr->ip_defrag_offset &&
++ else if (offset >= FRAG_CB(curr)->ip_defrag_offset &&
+ end <= curr_run_end)
+ return IPFRAG_DUP;
+ else
+@@ -438,7 +441,7 @@ int inet_frag_queue_insert(struct inet_frag_queue *q, struct sk_buff *skb,
+ rb_insert_color(&skb->rbnode, &q->rb_fragments);
+ }
+
+- skb->ip_defrag_offset = offset;
++ FRAG_CB(skb)->ip_defrag_offset = offset;
+
+ return IPFRAG_OK;
+ }
+@@ -448,13 +451,28 @@ void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
+ struct sk_buff *parent)
+ {
+ struct sk_buff *fp, *head = skb_rb_first(&q->rb_fragments);
+- struct sk_buff **nextp;
++ void (*destructor)(struct sk_buff *);
++ unsigned int orig_truesize = 0;
++ struct sk_buff **nextp = NULL;
++ struct sock *sk = skb->sk;
+ int delta;
+
++ if (sk && is_skb_wmem(skb)) {
++ /* TX: skb->sk might have been passed as argument to
++ * dst->output and must remain valid until tx completes.
++ *
++ * Move sk to reassembled skb and fix up wmem accounting.
++ */
++ orig_truesize = skb->truesize;
++ destructor = skb->destructor;
++ }
++
+ if (head != skb) {
+ fp = skb_clone(skb, GFP_ATOMIC);
+- if (!fp)
+- return NULL;
++ if (!fp) {
++ head = skb;
++ goto out_restore_sk;
++ }
+ FRAG_CB(fp)->next_frag = FRAG_CB(skb)->next_frag;
+ if (RB_EMPTY_NODE(&skb->rbnode))
+ FRAG_CB(parent)->next_frag = fp;
+@@ -463,6 +481,12 @@ void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
+ &q->rb_fragments);
+ if (q->fragments_tail == skb)
+ q->fragments_tail = fp;
++
++ if (orig_truesize) {
++ /* prevent skb_morph from releasing sk */
++ skb->sk = NULL;
++ skb->destructor = NULL;
++ }
+ skb_morph(skb, head);
+ FRAG_CB(skb)->next_frag = FRAG_CB(head)->next_frag;
+ rb_replace_node(&head->rbnode, &skb->rbnode,
+@@ -470,13 +494,13 @@ void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
+ consume_skb(head);
+ head = skb;
+ }
+- WARN_ON(head->ip_defrag_offset != 0);
++ WARN_ON(FRAG_CB(head)->ip_defrag_offset != 0);
+
+ delta = -head->truesize;
+
+ /* Head of list must not be cloned. */
+ if (skb_unclone(head, GFP_ATOMIC))
+- return NULL;
++ goto out_restore_sk;
+
+ delta += head->truesize;
+ if (delta)
+@@ -492,7 +516,7 @@ void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
+
+ clone = alloc_skb(0, GFP_ATOMIC);
+ if (!clone)
+- return NULL;
++ goto out_restore_sk;
+ skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list;
+ skb_frag_list_init(head);
+ for (i = 0; i < skb_shinfo(head)->nr_frags; i++)
+@@ -509,6 +533,21 @@ void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb,
+ nextp = &skb_shinfo(head)->frag_list;
+ }
+
++out_restore_sk:
++ if (orig_truesize) {
++ int ts_delta = head->truesize - orig_truesize;
++
++ /* if this reassembled skb is fragmented later,
++ * fraglist skbs will get skb->sk assigned from head->sk,
++ * and each frag skb will be released via sock_wfree.
++ *
++ * Update sk_wmem_alloc.
++ */
++ head->sk = sk;
++ head->destructor = destructor;
++ refcount_add(ts_delta, &sk->sk_wmem_alloc);
++ }
++
+ return nextp;
+ }
+ EXPORT_SYMBOL(inet_frag_reasm_prepare);
+@@ -516,6 +555,8 @@ EXPORT_SYMBOL(inet_frag_reasm_prepare);
+ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
+ void *reasm_data, bool try_coalesce)
+ {
++ struct sock *sk = is_skb_wmem(head) ? head->sk : NULL;
++ const unsigned int head_truesize = head->truesize;
+ struct sk_buff **nextp = reasm_data;
+ struct rb_node *rbn;
+ struct sk_buff *fp;
+@@ -579,6 +620,9 @@ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head,
+ head->prev = NULL;
+ head->tstamp = q->stamp;
+ head->mono_delivery_time = q->mono_delivery_time;
++
++ if (sk)
++ refcount_add(sum_truesize - head_truesize, &sk->sk_wmem_alloc);
+ }
+ EXPORT_SYMBOL(inet_frag_reasm_finish);
+
+diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
+index a4941f53b5237..fb947d1613fe2 100644
+--- a/net/ipv4/ip_fragment.c
++++ b/net/ipv4/ip_fragment.c
+@@ -384,6 +384,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb)
+ }
+
+ skb_dst_drop(skb);
++ skb_orphan(skb);
+ return -EINPROGRESS;
+
+ insert_error:
+@@ -487,7 +488,6 @@ int ip_defrag(struct net *net, struct sk_buff *skb, u32 user)
+ struct ipq *qp;
+
+ __IP_INC_STATS(net, IPSTATS_MIB_REASMREQDS);
+- skb_orphan(skb);
+
+ /* Lookup (or create) queue header */
+ qp = ip_find(net, ip_hdr(skb), user, vif);
+diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
+index 6b9cf5a24c19f..1954a56fec6ba 100644
+--- a/net/ipv4/ip_gre.c
++++ b/net/ipv4/ip_gre.c
+@@ -280,8 +280,13 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
+ tpi->flags | TUNNEL_NO_KEY,
+ iph->saddr, iph->daddr, 0);
+ } else {
++ if (unlikely(!pskb_may_pull(skb,
++ gre_hdr_len + sizeof(*ershdr))))
++ return PACKET_REJECT;
++
+ ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
+ ver = ershdr->ver;
++ iph = ip_hdr(skb);
+ tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
+ tpi->flags | TUNNEL_KEY,
+ iph->saddr, iph->daddr, tpi->key);
+diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
+index 2407066b0fec1..b150c9929b12e 100644
+--- a/net/ipv4/netfilter/arp_tables.c
++++ b/net/ipv4/netfilter/arp_tables.c
+@@ -956,6 +956,8 @@ static int do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ void *loc_cpu_entry;
+ struct arpt_entry *iter;
+
++ if (len < sizeof(tmp))
++ return -EINVAL;
+ if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
+ return -EFAULT;
+
+@@ -1254,6 +1256,8 @@ static int compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ void *loc_cpu_entry;
+ struct arpt_entry *iter;
+
++ if (len < sizeof(tmp))
++ return -EINVAL;
+ if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
+ return -EFAULT;
+
+diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
+index 7da1df4997d05..4876707595781 100644
+--- a/net/ipv4/netfilter/ip_tables.c
++++ b/net/ipv4/netfilter/ip_tables.c
+@@ -1108,6 +1108,8 @@ do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ void *loc_cpu_entry;
+ struct ipt_entry *iter;
+
++ if (len < sizeof(tmp))
++ return -EINVAL;
+ if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
+ return -EFAULT;
+
+@@ -1492,6 +1494,8 @@ compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ void *loc_cpu_entry;
+ struct ipt_entry *iter;
+
++ if (len < sizeof(tmp))
++ return -EINVAL;
+ if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
+ return -EFAULT;
+
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index a4f4185923144..5887eac87bd28 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -2930,6 +2930,8 @@ void tcp_close(struct sock *sk, long timeout)
+ lock_sock(sk);
+ __tcp_close(sk, timeout);
+ release_sock(sk);
++ if (!sk->sk_net_refcnt)
++ inet_csk_clear_xmit_timers_sync(sk);
+ sock_put(sk);
+ }
+ EXPORT_SYMBOL(tcp_close);
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 17231c0f88302..a505ba383863c 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -584,6 +584,13 @@ static inline bool __udp_is_mcast_sock(struct net *net, const struct sock *sk,
+ }
+
+ DEFINE_STATIC_KEY_FALSE(udp_encap_needed_key);
++EXPORT_SYMBOL(udp_encap_needed_key);
++
++#if IS_ENABLED(CONFIG_IPV6)
++DEFINE_STATIC_KEY_FALSE(udpv6_encap_needed_key);
++EXPORT_SYMBOL(udpv6_encap_needed_key);
++#endif
++
+ void udp_encap_enable(void)
+ {
+ static_branch_inc(&udp_encap_needed_key);
+diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
+index 6c95d28d0c4a7..c3d67423ae189 100644
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -449,8 +449,9 @@ static int skb_gro_receive_list(struct sk_buff *p, struct sk_buff *skb)
+ NAPI_GRO_CB(p)->count++;
+ p->data_len += skb->len;
+
+- /* sk owenrship - if any - completely transferred to the aggregated packet */
++ /* sk ownership - if any - completely transferred to the aggregated packet */
+ skb->destructor = NULL;
++ skb->sk = NULL;
+ p->truesize += skb->truesize;
+ p->len += skb->len;
+
+@@ -551,11 +552,19 @@ struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb,
+ unsigned int off = skb_gro_offset(skb);
+ int flush = 1;
+
+- /* we can do L4 aggregation only if the packet can't land in a tunnel
+- * otherwise we could corrupt the inner stream
++ /* We can do L4 aggregation only if the packet can't land in a tunnel
++ * otherwise we could corrupt the inner stream. Detecting such packets
++ * cannot be foolproof and the aggregation might still happen in some
++ * cases. Such packets should be caught in udp_unexpected_gso later.
+ */
+ NAPI_GRO_CB(skb)->is_flist = 0;
+ if (!sk || !udp_sk(sk)->gro_receive) {
++ /* If the packet was locally encapsulated in a UDP tunnel that
++ * wasn't detected above, do not GRO.
++ */
++ if (skb->encapsulation)
++ goto out;
++
+ if (skb->dev->features & NETIF_F_GRO_FRAGLIST)
+ NAPI_GRO_CB(skb)->is_flist = sk ? !udp_test_bit(GRO_ENABLED, sk) : 1;
+
+@@ -719,13 +728,7 @@ INDIRECT_CALLABLE_SCOPE int udp4_gro_complete(struct sk_buff *skb, int nhoff)
+ skb_shinfo(skb)->gso_type |= (SKB_GSO_FRAGLIST|SKB_GSO_UDP_L4);
+ skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count;
+
+- if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+- if (skb->csum_level < SKB_MAX_CSUM_LEVEL)
+- skb->csum_level++;
+- } else {
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
+- skb->csum_level = 0;
+- }
++ __skb_incr_checksum_unnecessary(skb);
+
+ return 0;
+ }
+diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
+index 4fc2cae0d116c..54294f6a8ec51 100644
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -645,19 +645,19 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
+ if (!w) {
+ /* New dump:
+ *
+- * 1. hook callback destructor.
+- */
+- cb->args[3] = (long)cb->done;
+- cb->done = fib6_dump_done;
+-
+- /*
+- * 2. allocate and initialize walker.
++ * 1. allocate and initialize walker.
+ */
+ w = kzalloc(sizeof(*w), GFP_ATOMIC);
+ if (!w)
+ return -ENOMEM;
+ w->func = fib6_dump_node;
+ cb->args[2] = (long)w;
++
++ /* 2. hook callback destructor.
++ */
++ cb->args[3] = (long)cb->done;
++ cb->done = fib6_dump_done;
++
+ }
+
+ arg.skb = skb;
+diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
+index 070d87abf7c02..26c3287beb29c 100644
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -528,6 +528,9 @@ static int ip6erspan_rcv(struct sk_buff *skb,
+ struct ip6_tnl *tunnel;
+ u8 ver;
+
++ if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))
++ return PACKET_REJECT;
++
+ ipv6h = ipv6_hdr(skb);
+ ershdr = (struct erspan_base_hdr *)skb->data;
+ ver = ershdr->ver;
+diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
+index fd9f049d6d41e..636b360311c53 100644
+--- a/net/ipv6/netfilter/ip6_tables.c
++++ b/net/ipv6/netfilter/ip6_tables.c
+@@ -1125,6 +1125,8 @@ do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ void *loc_cpu_entry;
+ struct ip6t_entry *iter;
+
++ if (len < sizeof(tmp))
++ return -EINVAL;
+ if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
+ return -EFAULT;
+
+@@ -1501,6 +1503,8 @@ compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ void *loc_cpu_entry;
+ struct ip6t_entry *iter;
+
++ if (len < sizeof(tmp))
++ return -EINVAL;
+ if (copy_from_sockptr(&tmp, arg, sizeof(tmp)) != 0)
+ return -EFAULT;
+
+diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
+index b2dd48911c8d6..efbec7ee27d0a 100644
+--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
+@@ -294,6 +294,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb,
+ }
+
+ skb_dst_drop(skb);
++ skb_orphan(skb);
+ return -EINPROGRESS;
+
+ insert_error:
+@@ -469,7 +470,6 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
+ hdr = ipv6_hdr(skb);
+ fhdr = (struct frag_hdr *)skb_transport_header(skb);
+
+- skb_orphan(skb);
+ fq = fq_find(net, fhdr->identification, user, hdr,
+ skb->dev ? skb->dev->ifindex : 0);
+ if (fq == NULL) {
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index 3f2249b4cd5f6..26d9bd287b234 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -450,7 +450,7 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
+ goto try_again;
+ }
+
+-DEFINE_STATIC_KEY_FALSE(udpv6_encap_needed_key);
++DECLARE_STATIC_KEY_FALSE(udpv6_encap_needed_key);
+ void udpv6_encap_enable(void)
+ {
+ static_branch_inc(&udpv6_encap_needed_key);
+diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
+index 6b95ba241ebe2..626d7b362dc7b 100644
+--- a/net/ipv6/udp_offload.c
++++ b/net/ipv6/udp_offload.c
+@@ -174,13 +174,7 @@ INDIRECT_CALLABLE_SCOPE int udp6_gro_complete(struct sk_buff *skb, int nhoff)
+ skb_shinfo(skb)->gso_type |= (SKB_GSO_FRAGLIST|SKB_GSO_UDP_L4);
+ skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count;
+
+- if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
+- if (skb->csum_level < SKB_MAX_CSUM_LEVEL)
+- skb->csum_level++;
+- } else {
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
+- skb->csum_level = 0;
+- }
++ __skb_incr_checksum_unnecessary(skb);
+
+ return 0;
+ }
+diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
+index 7833a49f6214a..2b921af2718d9 100644
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -3916,8 +3916,6 @@ static int mptcp_stream_accept(struct socket *sock, struct socket *newsock,
+ mptcp_set_state(newsk, TCP_CLOSE);
+ }
+ } else {
+- MPTCP_INC_STATS(sock_net(ssk),
+- MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK);
+ tcpfallback:
+ newsk->sk_kern_sock = kern;
+ lock_sock(newsk);
+diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
+index c40f1428e6020..ef3edba754a32 100644
+--- a/net/mptcp/sockopt.c
++++ b/net/mptcp/sockopt.c
+@@ -1500,6 +1500,10 @@ int mptcp_set_rcvlowat(struct sock *sk, int val)
+ struct mptcp_subflow_context *subflow;
+ int space, cap;
+
++ /* bpf can land here with a wrong sk type */
++ if (sk->sk_protocol == IPPROTO_TCP)
++ return -EINVAL;
++
+ if (sk->sk_userlocks & SOCK_RCVBUF_LOCK)
+ cap = sk->sk_rcvbuf >> 1;
+ else
+diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
+index 71ba86246ff89..13f66d11b7a0b 100644
+--- a/net/mptcp/subflow.c
++++ b/net/mptcp/subflow.c
+@@ -905,6 +905,8 @@ static struct sock *subflow_syn_recv_sock(const struct sock *sk,
+ return child;
+
+ fallback:
++ if (fallback)
++ SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK);
+ mptcp_subflow_drop_ctx(child);
+ return child;
+ }
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index ec6266c1972c0..21581bae700c4 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -1198,6 +1198,26 @@ static void nf_tables_table_disable(struct net *net, struct nft_table *table)
+ #define __NFT_TABLE_F_UPDATE (__NFT_TABLE_F_WAS_DORMANT | \
+ __NFT_TABLE_F_WAS_AWAKEN)
+
++static bool nft_table_pending_update(const struct nft_ctx *ctx)
++{
++ struct nftables_pernet *nft_net = nft_pernet(ctx->net);
++ struct nft_trans *trans;
++
++ if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
++ return true;
++
++ list_for_each_entry(trans, &nft_net->commit_list, list) {
++ if (trans->ctx.table == ctx->table &&
++ ((trans->msg_type == NFT_MSG_NEWCHAIN &&
++ nft_trans_chain_update(trans)) ||
++ (trans->msg_type == NFT_MSG_DELCHAIN &&
++ nft_is_base_chain(trans->ctx.chain))))
++ return true;
++ }
++
++ return false;
++}
++
+ static int nf_tables_updtable(struct nft_ctx *ctx)
+ {
+ struct nft_trans *trans;
+@@ -1221,7 +1241,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
+ return -EOPNOTSUPP;
+
+ /* No dormant off/on/off/on games in single transaction */
+- if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
++ if (nft_table_pending_update(ctx))
+ return -EINVAL;
+
+ trans = nft_trans_alloc(ctx, NFT_MSG_NEWTABLE,
+@@ -2418,6 +2438,9 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
+ struct nft_stats __percpu *stats = NULL;
+ struct nft_chain_hook hook = {};
+
++ if (table->flags & __NFT_TABLE_F_UPDATE)
++ return -EINVAL;
++
+ if (flags & NFT_CHAIN_BINDING)
+ return -EOPNOTSUPP;
+
+@@ -2619,6 +2642,13 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
+ }
+ }
+
++ if (table->flags & __NFT_TABLE_F_UPDATE &&
++ !list_empty(&hook.list)) {
++ NL_SET_BAD_ATTR(extack, attr);
++ err = -EOPNOTSUPP;
++ goto err_hooks;
++ }
++
+ if (!(table->flags & NFT_TABLE_F_DORMANT) &&
+ nft_is_base_chain(chain) &&
+ !list_empty(&hook.list)) {
+@@ -2848,6 +2878,9 @@ static int nft_delchain_hook(struct nft_ctx *ctx,
+ struct nft_trans *trans;
+ int err;
+
++ if (ctx->table->flags & __NFT_TABLE_F_UPDATE)
++ return -EOPNOTSUPP;
++
+ err = nft_chain_parse_hook(ctx->net, basechain, nla, &chain_hook,
+ ctx->family, chain->flags, extack);
+ if (err < 0)
+@@ -2932,7 +2965,8 @@ static int nf_tables_delchain(struct sk_buff *skb, const struct nfnl_info *info,
+ nft_ctx_init(&ctx, net, skb, info->nlh, family, table, chain, nla);
+
+ if (nla[NFTA_CHAIN_HOOK]) {
+- if (chain->flags & NFT_CHAIN_HW_OFFLOAD)
++ if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYCHAIN ||
++ chain->flags & NFT_CHAIN_HW_OFFLOAD)
+ return -EOPNOTSUPP;
+
+ if (nft_is_base_chain(chain)) {
+@@ -8259,11 +8293,12 @@ static int nft_flowtable_parse_hook(const struct nft_ctx *ctx,
+ return err;
+ }
+
++/* call under rcu_read_lock */
+ static const struct nf_flowtable_type *__nft_flowtable_type_get(u8 family)
+ {
+ const struct nf_flowtable_type *type;
+
+- list_for_each_entry(type, &nf_tables_flowtables, list) {
++ list_for_each_entry_rcu(type, &nf_tables_flowtables, list) {
+ if (family == type->family)
+ return type;
+ }
+@@ -8275,9 +8310,13 @@ nft_flowtable_type_get(struct net *net, u8 family)
+ {
+ const struct nf_flowtable_type *type;
+
++ rcu_read_lock();
+ type = __nft_flowtable_type_get(family);
+- if (type != NULL && try_module_get(type->owner))
++ if (type != NULL && try_module_get(type->owner)) {
++ rcu_read_unlock();
+ return type;
++ }
++ rcu_read_unlock();
+
+ lockdep_nfnl_nft_mutex_not_held();
+ #ifdef CONFIG_MODULES
+@@ -10178,9 +10217,11 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+ if (nft_trans_chain_update(trans)) {
+ nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN,
+ &nft_trans_chain_hooks(trans));
+- nft_netdev_unregister_hooks(net,
+- &nft_trans_chain_hooks(trans),
+- true);
++ if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT)) {
++ nft_netdev_unregister_hooks(net,
++ &nft_trans_chain_hooks(trans),
++ true);
++ }
+ } else {
+ nft_chain_del(trans->ctx.chain);
+ nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN,
+@@ -10419,10 +10460,11 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
+ struct nft_trans *trans, *next;
+ LIST_HEAD(set_update_list);
+ struct nft_trans_elem *te;
++ int err = 0;
+
+ if (action == NFNL_ABORT_VALIDATE &&
+ nf_tables_validate(net) < 0)
+- return -EAGAIN;
++ err = -EAGAIN;
+
+ list_for_each_entry_safe_reverse(trans, next, &nft_net->commit_list,
+ list) {
+@@ -10452,9 +10494,11 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
+ break;
+ case NFT_MSG_NEWCHAIN:
+ if (nft_trans_chain_update(trans)) {
+- nft_netdev_unregister_hooks(net,
+- &nft_trans_chain_hooks(trans),
+- true);
++ if (!(trans->ctx.table->flags & NFT_TABLE_F_DORMANT)) {
++ nft_netdev_unregister_hooks(net,
++ &nft_trans_chain_hooks(trans),
++ true);
++ }
+ free_percpu(nft_trans_chain_stats(trans));
+ kfree(nft_trans_chain_name(trans));
+ nft_trans_destroy(trans);
+@@ -10608,12 +10652,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
+ nf_tables_abort_release(trans);
+ }
+
+- if (action == NFNL_ABORT_AUTOLOAD)
+- nf_tables_module_autoload(net);
+- else
+- nf_tables_module_autoload_cleanup(net);
+-
+- return 0;
++ return err;
+ }
+
+ static int nf_tables_abort(struct net *net, struct sk_buff *skb,
+@@ -10626,6 +10665,17 @@ static int nf_tables_abort(struct net *net, struct sk_buff *skb,
+ gc_seq = nft_gc_seq_begin(nft_net);
+ ret = __nf_tables_abort(net, action);
+ nft_gc_seq_end(nft_net, gc_seq);
++
++ WARN_ON_ONCE(!list_empty(&nft_net->commit_list));
++
++ /* module autoload needs to happen after GC sequence update because it
++ * temporarily releases and grabs mutex again.
++ */
++ if (action == NFNL_ABORT_AUTOLOAD)
++ nf_tables_module_autoload(net);
++ else
++ nf_tables_module_autoload_cleanup(net);
++
+ mutex_unlock(&nft_net->commit_mutex);
+
+ return ret;
+@@ -11427,9 +11477,10 @@ static void __net_exit nf_tables_exit_net(struct net *net)
+
+ gc_seq = nft_gc_seq_begin(nft_net);
+
+- if (!list_empty(&nft_net->commit_list) ||
+- !list_empty(&nft_net->module_list))
+- __nf_tables_abort(net, NFNL_ABORT_NONE);
++ WARN_ON_ONCE(!list_empty(&nft_net->commit_list));
++
++ if (!list_empty(&nft_net->module_list))
++ nf_tables_module_autoload_cleanup(net);
+
+ __nft_release_tables(net);
+
+@@ -11521,6 +11572,7 @@ static void __exit nf_tables_module_exit(void)
+ unregister_netdevice_notifier(&nf_tables_flowtable_notifier);
+ nft_chain_filter_fini();
+ nft_chain_route_fini();
++ nf_tables_trans_destroy_flush_work();
+ unregister_pernet_subsys(&nf_tables_net_ops);
+ cancel_work_sync(&trans_gc_work);
+ cancel_work_sync(&trans_destroy_work);
+diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
+index cdad47b140fa4..0d26c8ec9993e 100644
+--- a/net/nfc/nci/core.c
++++ b/net/nfc/nci/core.c
+@@ -1516,6 +1516,11 @@ static void nci_rx_work(struct work_struct *work)
+ nfc_send_to_raw_sock(ndev->nfc_dev, skb,
+ RAW_PAYLOAD_NCI, NFC_DIRECTION_RX);
+
++ if (!nci_plen(skb->data)) {
++ kfree_skb(skb);
++ break;
++ }
++
+ /* Process frame */
+ switch (nci_mt(skb->data)) {
+ case NCI_MT_RSP_PKT:
+diff --git a/net/rds/rdma.c b/net/rds/rdma.c
+index a4e3c5de998be..00dbcd4d28e68 100644
+--- a/net/rds/rdma.c
++++ b/net/rds/rdma.c
+@@ -302,7 +302,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
+ }
+ ret = PTR_ERR(trans_private);
+ /* Trigger connection so that its ready for the next retry */
+- if (ret == -ENODEV)
++ if (ret == -ENODEV && cp)
+ rds_conn_connect_if_down(cp->cp_conn);
+ goto out;
+ }
+diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
+index bcb673ab0008d..0015393910823 100644
+--- a/net/sched/act_skbmod.c
++++ b/net/sched/act_skbmod.c
+@@ -241,13 +241,13 @@ static int tcf_skbmod_dump(struct sk_buff *skb, struct tc_action *a,
+ struct tcf_skbmod *d = to_skbmod(a);
+ unsigned char *b = skb_tail_pointer(skb);
+ struct tcf_skbmod_params *p;
+- struct tc_skbmod opt = {
+- .index = d->tcf_index,
+- .refcnt = refcount_read(&d->tcf_refcnt) - ref,
+- .bindcnt = atomic_read(&d->tcf_bindcnt) - bind,
+- };
++ struct tc_skbmod opt;
+ struct tcf_t t;
+
++ memset(&opt, 0, sizeof(opt));
++ opt.index = d->tcf_index;
++ opt.refcnt = refcount_read(&d->tcf_refcnt) - ref,
++ opt.bindcnt = atomic_read(&d->tcf_bindcnt) - bind;
+ spin_lock_bh(&d->tcf_lock);
+ opt.action = d->tcf_action;
+ p = rcu_dereference_protected(d->skbmod_p,
+diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
+index 36b025cc4fd26..31e38a614f33a 100644
+--- a/net/sched/sch_api.c
++++ b/net/sched/sch_api.c
+@@ -809,7 +809,7 @@ void qdisc_tree_reduce_backlog(struct Qdisc *sch, int n, int len)
+ notify = !sch->q.qlen && !WARN_ON_ONCE(!n &&
+ !qdisc_is_offloaded);
+ /* TODO: perform the search on a per txq basis */
+- sch = qdisc_lookup(qdisc_dev(sch), TC_H_MAJ(parentid));
++ sch = qdisc_lookup_rcu(qdisc_dev(sch), TC_H_MAJ(parentid));
+ if (sch == NULL) {
+ WARN_ON_ONCE(parentid != TC_H_ROOT);
+ break;
+diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
+index 545017a3daa4d..6b3f01beb294b 100644
+--- a/net/sunrpc/svcsock.c
++++ b/net/sunrpc/svcsock.c
+@@ -1206,15 +1206,6 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
+ * MSG_SPLICE_PAGES is used exclusively to reduce the number of
+ * copy operations in this path. Therefore the caller must ensure
+ * that the pages backing @xdr are unchanging.
+- *
+- * Note that the send is non-blocking. The caller has incremented
+- * the reference count on each page backing the RPC message, and
+- * the network layer will "put" these pages when transmission is
+- * complete.
+- *
+- * This is safe for our RPC services because the memory backing
+- * the head and tail components is never kmalloc'd. These always
+- * come from pages in the svc_rqst::rq_pages array.
+ */
+ static int svc_tcp_sendmsg(struct svc_sock *svsk, struct svc_rqst *rqstp,
+ rpc_fraghdr marker, unsigned int *sentp)
+@@ -1244,6 +1235,7 @@ static int svc_tcp_sendmsg(struct svc_sock *svsk, struct svc_rqst *rqstp,
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, rqstp->rq_bvec,
+ 1 + count, sizeof(marker) + rqstp->rq_res.len);
+ ret = sock_sendmsg(svsk->sk_sock, &msg);
++ page_frag_free(buf);
+ if (ret < 0)
+ return ret;
+ *sentp += ret;
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index 211f57164cb61..b783231668c65 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -1976,10 +1976,10 @@ int tls_sw_recvmsg(struct sock *sk,
+ if (unlikely(flags & MSG_ERRQUEUE))
+ return sock_recv_errqueue(sk, msg, len, SOL_IP, IP_RECVERR);
+
+- psock = sk_psock_get(sk);
+ err = tls_rx_reader_lock(sk, ctx, flags & MSG_DONTWAIT);
+ if (err < 0)
+ return err;
++ psock = sk_psock_get(sk);
+ bpf_strp_enabled = sk_psock_strp_enabled(psock);
+
+ /* If crypto failed the connection is broken */
+@@ -2152,12 +2152,15 @@ int tls_sw_recvmsg(struct sock *sk,
+ }
+
+ /* Drain records from the rx_list & copy if required */
+- if (is_peek || is_kvec)
++ if (is_peek)
+ err = process_rx_list(ctx, msg, &control, copied + peeked,
+ decrypted - peeked, is_peek, NULL);
+ else
+ err = process_rx_list(ctx, msg, &control, 0,
+ async_copy_bytes, is_peek, NULL);
++
++ /* we could have copied less than we wanted, and possibly nothing */
++ decrypted += max(err, 0) - async_copy_bytes;
+ }
+
+ copied += decrypted;
+diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c
+index 1748268e0694f..ee5d306a96d0f 100644
+--- a/net/vmw_vsock/virtio_transport.c
++++ b/net/vmw_vsock/virtio_transport.c
+@@ -120,7 +120,6 @@ virtio_transport_send_pkt_work(struct work_struct *work)
+ if (!skb)
+ break;
+
+- virtio_transport_deliver_tap_pkt(skb);
+ reply = virtio_vsock_skb_reply(skb);
+ sgs = vsock->out_sgs;
+ sg_init_one(sgs[out_sg], virtio_vsock_hdr(skb),
+@@ -170,6 +169,8 @@ virtio_transport_send_pkt_work(struct work_struct *work)
+ break;
+ }
+
++ virtio_transport_deliver_tap_pkt(skb);
++
+ if (reply) {
+ struct virtqueue *rx_vq = vsock->vqs[VSOCK_VQ_RX];
+ int val;
+diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
+index 2f25a1de129d1..5660b96213e4b 100644
+--- a/scripts/Makefile.extrawarn
++++ b/scripts/Makefile.extrawarn
+@@ -114,6 +114,8 @@ KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow)
+ KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation)
+ KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation)
+
++KBUILD_CFLAGS += -Wno-override-init # alias for -Wno-initializer-overrides in clang
++
+ ifdef CONFIG_CC_IS_CLANG
+ # Clang before clang-16 would warn on default argument promotions.
+ ifneq ($(call clang-min-version, 160000),y)
+@@ -151,10 +153,6 @@ KBUILD_CFLAGS += -Wtype-limits
+ KBUILD_CFLAGS += $(call cc-option, -Wmaybe-uninitialized)
+ KBUILD_CFLAGS += $(call cc-option, -Wunused-macros)
+
+-ifdef CONFIG_CC_IS_CLANG
+-KBUILD_CFLAGS += -Winitializer-overrides
+-endif
+-
+ KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN2
+
+ else
+@@ -164,9 +162,7 @@ KBUILD_CFLAGS += -Wno-missing-field-initializers
+ KBUILD_CFLAGS += -Wno-type-limits
+ KBUILD_CFLAGS += -Wno-shift-negative-value
+
+-ifdef CONFIG_CC_IS_CLANG
+-KBUILD_CFLAGS += -Wno-initializer-overrides
+-else
++ifdef CONFIG_CC_IS_GCC
+ KBUILD_CFLAGS += -Wno-maybe-uninitialized
+ endif
+
+diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py
+index 0669bac5e900e..3f899cc7e99a9 100755
+--- a/scripts/bpf_doc.py
++++ b/scripts/bpf_doc.py
+@@ -414,8 +414,8 @@ class PrinterRST(Printer):
+ version = version.stdout.decode().rstrip()
+ except:
+ try:
+- version = subprocess.run(['make', 'kernelversion'], cwd=linuxRoot,
+- capture_output=True, check=True)
++ version = subprocess.run(['make', '-s', '--no-print-directory', 'kernelversion'],
++ cwd=linuxRoot, capture_output=True, check=True)
+ version = version.stdout.decode().rstrip()
+ except:
+ return 'Linux'
+diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
+index 267b9a0a3abcd..6568f8177e392 100644
+--- a/scripts/mod/modpost.c
++++ b/scripts/mod/modpost.c
+@@ -1007,6 +1007,8 @@ static Elf_Sym *find_fromsym(struct elf_info *elf, Elf_Addr addr,
+
+ static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym)
+ {
++ Elf_Sym *new_sym;
++
+ /* If the supplied symbol has a valid name, return it */
+ if (is_valid_name(elf, sym))
+ return sym;
+@@ -1015,8 +1017,9 @@ static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym)
+ * Strive to find a better symbol name, but the resulting name may not
+ * match the symbol referenced in the original code.
+ */
+- return symsearch_find_nearest(elf, addr, get_secindex(elf, sym),
+- true, 20);
++ new_sym = symsearch_find_nearest(elf, addr, get_secindex(elf, sym),
++ true, 20);
++ return new_sym ? new_sym : sym;
+ }
+
+ static bool is_executable_section(struct elf_info *elf, unsigned int secndx)
+diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
+index 0619a1cbbfbe4..074d6c2714eb5 100644
+--- a/security/selinux/selinuxfs.c
++++ b/security/selinux/selinuxfs.c
+@@ -2123,7 +2123,6 @@ static struct file_system_type sel_fs_type = {
+ .kill_sb = sel_kill_sb,
+ };
+
+-static struct vfsmount *selinuxfs_mount __ro_after_init;
+ struct path selinux_null __ro_after_init;
+
+ static int __init init_sel_fs(void)
+@@ -2145,18 +2144,21 @@ static int __init init_sel_fs(void)
+ return err;
+ }
+
+- selinux_null.mnt = selinuxfs_mount = kern_mount(&sel_fs_type);
+- if (IS_ERR(selinuxfs_mount)) {
++ selinux_null.mnt = kern_mount(&sel_fs_type);
++ if (IS_ERR(selinux_null.mnt)) {
+ pr_err("selinuxfs: could not mount!\n");
+- err = PTR_ERR(selinuxfs_mount);
+- selinuxfs_mount = NULL;
++ err = PTR_ERR(selinux_null.mnt);
++ selinux_null.mnt = NULL;
++ return err;
+ }
++
+ selinux_null.dentry = d_hash_and_lookup(selinux_null.mnt->mnt_root,
+ &null_name);
+ if (IS_ERR(selinux_null.dentry)) {
+ pr_err("selinuxfs: could not lookup null!\n");
+ err = PTR_ERR(selinux_null.dentry);
+ selinux_null.dentry = NULL;
++ return err;
+ }
+
+ return err;
+diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c
+index d36234b88fb42..941bfbf812ed3 100644
+--- a/sound/pci/emu10k1/emu10k1_callback.c
++++ b/sound/pci/emu10k1/emu10k1_callback.c
+@@ -255,7 +255,7 @@ lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw,
+ /* check if sample is finished playing (non-looping only) */
+ if (bp != best + V_OFF && bp != best + V_FREE &&
+ (vp->reg.sample_mode & SNDRV_SFNT_SAMPLE_SINGLESHOT)) {
+- val = snd_emu10k1_ptr_read(hw, CCCA_CURRADDR, vp->ch) - 64;
++ val = snd_emu10k1_ptr_read(hw, CCCA_CURRADDR, vp->ch);
+ if (val >= vp->reg.loopstart)
+ bp = best + V_OFF;
+ }
+@@ -362,7 +362,7 @@ start_voice(struct snd_emux_voice *vp)
+
+ map = (hw->silent_page.addr << hw->address_mode) | (hw->address_mode ? MAP_PTI_MASK1 : MAP_PTI_MASK0);
+
+- addr = vp->reg.start + 64;
++ addr = vp->reg.start;
+ temp = vp->reg.parm.filterQ;
+ ccca = (temp << 28) | addr;
+ if (vp->apitch < 0xe400)
+@@ -430,9 +430,6 @@ start_voice(struct snd_emux_voice *vp)
+ /* Q & current address (Q 4bit value, MSB) */
+ CCCA, ccca,
+
+- /* cache */
+- CCR, REG_VAL_PUT(CCR_CACHEINVALIDSIZE, 64),
+-
+ /* reset volume */
+ VTFT, vtarget | vp->ftarget,
+ CVCF, vtarget | CVCF_CURRENTFILTER_MASK,
+diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c
+index 86ddaff915de1..4d1f8734d13f3 100644
+--- a/sound/pci/hda/cs35l41_hda_property.c
++++ b/sound/pci/hda/cs35l41_hda_property.c
+@@ -97,7 +97,10 @@ static const struct cs35l41_config cs35l41_config_table[] = {
+ { "10431F12", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 1000, 4500, 24 },
+ { "10431F1F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 },
+ { "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
++ { "10433A60", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
+ { "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
++ { "17AA3877", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
++ { "17AA3878", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
+ { "17AA38A9", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
+ { "17AA38AB", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
+ { "17AA38B4", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
+@@ -434,7 +437,10 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
+ { "CSC3551", "10431F12", generic_dsd_config },
+ { "CSC3551", "10431F1F", generic_dsd_config },
+ { "CSC3551", "10431F62", generic_dsd_config },
++ { "CSC3551", "10433A60", generic_dsd_config },
+ { "CSC3551", "17AA386F", generic_dsd_config },
++ { "CSC3551", "17AA3877", generic_dsd_config },
++ { "CSC3551", "17AA3878", generic_dsd_config },
+ { "CSC3551", "17AA38A9", generic_dsd_config },
+ { "CSC3551", "17AA38AB", generic_dsd_config },
+ { "CSC3551", "17AA38B4", generic_dsd_config },
+diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c
+index 75a14ba54fcd1..43a445bd961fb 100644
+--- a/sound/pci/hda/cs35l56_hda.c
++++ b/sound/pci/hda/cs35l56_hda.c
+@@ -1017,14 +1017,14 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int id)
+ pm_runtime_mark_last_busy(cs35l56->base.dev);
+ pm_runtime_enable(cs35l56->base.dev);
+
++ cs35l56->base.init_done = true;
++
+ ret = component_add(cs35l56->base.dev, &cs35l56_hda_comp_ops);
+ if (ret) {
+ dev_err(cs35l56->base.dev, "Register component failed: %d\n", ret);
+ goto pm_err;
+ }
+
+- cs35l56->base.init_done = true;
+-
+ return 0;
+
+ pm_err:
+diff --git a/sound/pci/hda/cs35l56_hda_i2c.c b/sound/pci/hda/cs35l56_hda_i2c.c
+index a9ef6d86de839..09a810a50a12b 100644
+--- a/sound/pci/hda/cs35l56_hda_i2c.c
++++ b/sound/pci/hda/cs35l56_hda_i2c.c
+@@ -53,10 +53,19 @@ static const struct i2c_device_id cs35l56_hda_i2c_id[] = {
+ {}
+ };
+
++static const struct acpi_device_id cs35l56_acpi_hda_match[] = {
++ { "CSC3554", 0 },
++ { "CSC3556", 0 },
++ { "CSC3557", 0 },
++ {}
++};
++MODULE_DEVICE_TABLE(acpi, cs35l56_acpi_hda_match);
++
+ static struct i2c_driver cs35l56_hda_i2c_driver = {
+ .driver = {
+- .name = "cs35l56-hda",
+- .pm = &cs35l56_hda_pm_ops,
++ .name = "cs35l56-hda",
++ .acpi_match_table = cs35l56_acpi_hda_match,
++ .pm = &cs35l56_hda_pm_ops,
+ },
+ .id_table = cs35l56_hda_i2c_id,
+ .probe = cs35l56_hda_i2c_probe,
+diff --git a/sound/pci/hda/cs35l56_hda_spi.c b/sound/pci/hda/cs35l56_hda_spi.c
+index 080426de90830..04f9fe6197dc5 100644
+--- a/sound/pci/hda/cs35l56_hda_spi.c
++++ b/sound/pci/hda/cs35l56_hda_spi.c
+@@ -53,10 +53,19 @@ static const struct spi_device_id cs35l56_hda_spi_id[] = {
+ {}
+ };
+
++static const struct acpi_device_id cs35l56_acpi_hda_match[] = {
++ { "CSC3554", 0 },
++ { "CSC3556", 0 },
++ { "CSC3557", 0 },
++ {}
++};
++MODULE_DEVICE_TABLE(acpi, cs35l56_acpi_hda_match);
++
+ static struct spi_driver cs35l56_hda_spi_driver = {
+ .driver = {
+- .name = "cs35l56-hda",
+- .pm = &cs35l56_hda_pm_ops,
++ .name = "cs35l56-hda",
++ .acpi_match_table = cs35l56_acpi_hda_match,
++ .pm = &cs35l56_hda_pm_ops,
+ },
+ .id_table = cs35l56_hda_spi_id,
+ .probe = cs35l56_hda_spi_probe,
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 1dc5eb92ddcad..f4a02bf1abb11 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -10164,7 +10164,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1043, 0x3a30, "ASUS G814JVR/JIR", ALC245_FIXUP_CS35L41_SPI_2),
+ SND_PCI_QUIRK(0x1043, 0x3a40, "ASUS G814JZR", ALC245_FIXUP_CS35L41_SPI_2),
+ SND_PCI_QUIRK(0x1043, 0x3a50, "ASUS G834JYR/JZR", ALC245_FIXUP_CS35L41_SPI_2),
+- SND_PCI_QUIRK(0x1043, 0x3a60, "ASUS G634JYR/JZR", ALC245_FIXUP_CS35L41_SPI_2),
++ SND_PCI_QUIRK(0x1043, 0x3a60, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
+ SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
+ SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC),
+ SND_PCI_QUIRK(0x1043, 0x8398, "ASUS P1005", ALC269_FIXUP_STEREO_DMIC),
+@@ -10189,7 +10189,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
+ SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
+ SND_PCI_QUIRK(0x10ec, 0x12cc, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
+- SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE),
++ SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_ASPIRE_HEADSET_MIC),
+ SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
+ SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
+ SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_AMP),
+@@ -10361,6 +10361,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
++ SND_PCI_QUIRK(0x17aa, 0x3878, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x387e, "Yoga S780-16 pro Quad YC", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x3881, "YB9 dual power mode2 YC", ALC287_FIXUP_TAS2781_I2C),
+@@ -10427,6 +10429,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1d05, 0x1147, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
+ SND_PCI_QUIRK(0x1d05, 0x115c, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
+ SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP),
++ SND_PCI_QUIRK(0x1d05, 0x1387, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
+diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
+index 8c8b1dcac6281..5f35b90eab8d3 100644
+--- a/sound/soc/amd/acp/acp-pci.c
++++ b/sound/soc/amd/acp/acp-pci.c
+@@ -115,7 +115,10 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
+ goto unregister_dmic_dev;
+ }
+
+- acp_init(chip);
++ ret = acp_init(chip);
++ if (ret)
++ goto unregister_dmic_dev;
++
+ res = devm_kcalloc(&pci->dev, num_res, sizeof(struct resource), GFP_KERNEL);
+ if (!res) {
+ ret = -ENOMEM;
+@@ -133,11 +136,9 @@ static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
+ }
+ }
+
+- if (flag == FLAG_AMD_LEGACY_ONLY_DMIC) {
+- ret = check_acp_pdm(pci, chip);
+- if (ret < 0)
+- goto skip_pdev_creation;
+- }
++ ret = check_acp_pdm(pci, chip);
++ if (ret < 0)
++ goto skip_pdev_creation;
+
+ chip->flag = flag;
+ memset(&pdevinfo, 0, sizeof(pdevinfo));
+diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c
+index a97ccb512deba..a24b52c9dda6b 100644
+--- a/sound/soc/codecs/cs42l43.c
++++ b/sound/soc/codecs/cs42l43.c
+@@ -2338,7 +2338,8 @@ static int cs42l43_codec_runtime_resume(struct device *dev)
+
+ static int cs42l43_codec_suspend(struct device *dev)
+ {
+- struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
++ struct cs42l43_codec *priv = dev_get_drvdata(dev);
++ struct cs42l43 *cs42l43 = priv->core;
+
+ disable_irq(cs42l43->irq);
+
+@@ -2347,7 +2348,8 @@ static int cs42l43_codec_suspend(struct device *dev)
+
+ static int cs42l43_codec_suspend_noirq(struct device *dev)
+ {
+- struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
++ struct cs42l43_codec *priv = dev_get_drvdata(dev);
++ struct cs42l43 *cs42l43 = priv->core;
+
+ enable_irq(cs42l43->irq);
+
+@@ -2356,7 +2358,8 @@ static int cs42l43_codec_suspend_noirq(struct device *dev)
+
+ static int cs42l43_codec_resume(struct device *dev)
+ {
+- struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
++ struct cs42l43_codec *priv = dev_get_drvdata(dev);
++ struct cs42l43 *cs42l43 = priv->core;
+
+ enable_irq(cs42l43->irq);
+
+@@ -2365,7 +2368,8 @@ static int cs42l43_codec_resume(struct device *dev)
+
+ static int cs42l43_codec_resume_noirq(struct device *dev)
+ {
+- struct cs42l43 *cs42l43 = dev_get_drvdata(dev);
++ struct cs42l43_codec *priv = dev_get_drvdata(dev);
++ struct cs42l43 *cs42l43 = priv->core;
+
+ disable_irq(cs42l43->irq);
+
+diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c
+index e67c2e19cb1a7..1fdbef5fd6cba 100644
+--- a/sound/soc/codecs/rt5682-sdw.c
++++ b/sound/soc/codecs/rt5682-sdw.c
+@@ -763,12 +763,12 @@ static int __maybe_unused rt5682_dev_resume(struct device *dev)
+ return 0;
+
+ if (!slave->unattach_request) {
++ mutex_lock(&rt5682->disable_irq_lock);
+ if (rt5682->disable_irq == true) {
+- mutex_lock(&rt5682->disable_irq_lock);
+ sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
+ rt5682->disable_irq = false;
+- mutex_unlock(&rt5682->disable_irq_lock);
+ }
++ mutex_unlock(&rt5682->disable_irq_lock);
+ goto regmap_sync;
+ }
+
+diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c
+index 935e597022d32..b8471b2d8f4f1 100644
+--- a/sound/soc/codecs/rt711-sdca-sdw.c
++++ b/sound/soc/codecs/rt711-sdca-sdw.c
+@@ -438,13 +438,13 @@ static int __maybe_unused rt711_sdca_dev_resume(struct device *dev)
+ return 0;
+
+ if (!slave->unattach_request) {
++ mutex_lock(&rt711->disable_irq_lock);
+ if (rt711->disable_irq == true) {
+- mutex_lock(&rt711->disable_irq_lock);
+ sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
+ sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
+ rt711->disable_irq = false;
+- mutex_unlock(&rt711->disable_irq_lock);
+ }
++ mutex_unlock(&rt711->disable_irq_lock);
+ goto regmap_sync;
+ }
+
+diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c
+index 3f5773310ae8c..988451f24a756 100644
+--- a/sound/soc/codecs/rt711-sdw.c
++++ b/sound/soc/codecs/rt711-sdw.c
+@@ -536,12 +536,12 @@ static int __maybe_unused rt711_dev_resume(struct device *dev)
+ return 0;
+
+ if (!slave->unattach_request) {
++ mutex_lock(&rt711->disable_irq_lock);
+ if (rt711->disable_irq == true) {
+- mutex_lock(&rt711->disable_irq_lock);
+ sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
+ rt711->disable_irq = false;
+- mutex_unlock(&rt711->disable_irq_lock);
+ }
++ mutex_unlock(&rt711->disable_irq_lock);
+ goto regmap_sync;
+ }
+
+diff --git a/sound/soc/codecs/rt712-sdca-sdw.c b/sound/soc/codecs/rt712-sdca-sdw.c
+index 6b644a89c5890..ba877432cea61 100644
+--- a/sound/soc/codecs/rt712-sdca-sdw.c
++++ b/sound/soc/codecs/rt712-sdca-sdw.c
+@@ -438,13 +438,14 @@ static int __maybe_unused rt712_sdca_dev_resume(struct device *dev)
+ return 0;
+
+ if (!slave->unattach_request) {
++ mutex_lock(&rt712->disable_irq_lock);
+ if (rt712->disable_irq == true) {
+- mutex_lock(&rt712->disable_irq_lock);
++
+ sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
+ sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
+ rt712->disable_irq = false;
+- mutex_unlock(&rt712->disable_irq_lock);
+ }
++ mutex_unlock(&rt712->disable_irq_lock);
+ goto regmap_sync;
+ }
+
+diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c
+index e24b9cbdc10c9..e33836fffd5f2 100644
+--- a/sound/soc/codecs/rt722-sdca-sdw.c
++++ b/sound/soc/codecs/rt722-sdca-sdw.c
+@@ -467,13 +467,13 @@ static int __maybe_unused rt722_sdca_dev_resume(struct device *dev)
+ return 0;
+
+ if (!slave->unattach_request) {
++ mutex_lock(&rt722->disable_irq_lock);
+ if (rt722->disable_irq == true) {
+- mutex_lock(&rt722->disable_irq_lock);
+ sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_6);
+ sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
+ rt722->disable_irq = false;
+- mutex_unlock(&rt722->disable_irq_lock);
+ }
++ mutex_unlock(&rt722->disable_irq_lock);
+ goto regmap_sync;
+ }
+
+diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
+index 36ea0dcdc7ab0..9cb9068c0462a 100644
+--- a/sound/soc/codecs/wm_adsp.c
++++ b/sound/soc/codecs/wm_adsp.c
+@@ -683,11 +683,12 @@ static void wm_adsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
+ int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
+ unsigned int alg, void *buf, size_t len)
+ {
+- struct cs_dsp_coeff_ctl *cs_ctl = cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg);
++ struct cs_dsp_coeff_ctl *cs_ctl;
+ struct wm_coeff_ctl *ctl;
+ int ret;
+
+ mutex_lock(&dsp->cs_dsp.pwr_lock);
++ cs_ctl = cs_dsp_get_ctl(&dsp->cs_dsp, name, type, alg);
+ ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len);
+ mutex_unlock(&dsp->cs_dsp.pwr_lock);
+
+diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
+index 2d25748ca7066..b27e89ff6a167 100644
+--- a/sound/soc/soc-ops.c
++++ b/sound/soc/soc-ops.c
+@@ -263,7 +263,7 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
+ int max = mc->max;
+ int min = mc->min;
+ int sign_bit = mc->sign_bit;
+- unsigned int mask = (1 << fls(max)) - 1;
++ unsigned int mask = (1ULL << fls(max)) - 1;
+ unsigned int invert = mc->invert;
+ int val;
+ int ret;
+diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c
+index 4db8cdc91daae..2c242ef9f23c1 100644
+--- a/sound/soc/sof/amd/acp.c
++++ b/sound/soc/sof/amd/acp.c
+@@ -537,6 +537,10 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev)
+ goto unregister_dev;
+ }
+
++ ret = acp_init(sdev);
++ if (ret < 0)
++ goto free_smn_dev;
++
+ sdev->ipc_irq = pci->irq;
+ ret = request_threaded_irq(sdev->ipc_irq, acp_irq_handler, acp_irq_thread,
+ IRQF_SHARED, "AudioDSP", sdev);
+@@ -546,10 +550,6 @@ int amd_sof_acp_probe(struct snd_sof_dev *sdev)
+ goto free_smn_dev;
+ }
+
+- ret = acp_init(sdev);
+- if (ret < 0)
+- goto free_ipc_irq;
+-
+ sdev->dsp_box.offset = 0;
+ sdev->dsp_box.size = BOX_SIZE_512;
+
+diff --git a/sound/soc/sof/intel/hda-common-ops.c b/sound/soc/sof/intel/hda-common-ops.c
+index 26105d8f1bdc7..88c236b9a0453 100644
+--- a/sound/soc/sof/intel/hda-common-ops.c
++++ b/sound/soc/sof/intel/hda-common-ops.c
+@@ -57,6 +57,9 @@ struct snd_sof_dsp_ops sof_hda_common_ops = {
+ .pcm_pointer = hda_dsp_pcm_pointer,
+ .pcm_ack = hda_dsp_pcm_ack,
+
++ .get_dai_frame_counter = hda_dsp_get_stream_llp,
++ .get_host_byte_counter = hda_dsp_get_stream_ldp,
++
+ /* firmware loading */
+ .load_firmware = snd_sof_load_firmware_raw,
+
+diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c
+index 55ce75db23e52..92ec5db4677df 100644
+--- a/sound/soc/sof/intel/hda-dai-ops.c
++++ b/sound/soc/sof/intel/hda-dai-ops.c
+@@ -7,6 +7,7 @@
+
+ #include <sound/pcm_params.h>
+ #include <sound/hdaudio_ext.h>
++#include <sound/hda_register.h>
+ #include <sound/hda-mlink.h>
+ #include <sound/sof/ipc4/header.h>
+ #include <uapi/sound/sof/header.h>
+@@ -362,6 +363,16 @@ static int hda_trigger(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai,
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ snd_hdac_ext_stream_clear(hext_stream);
++
++ /*
++ * Save the LLP registers in case the stream is
++ * restarting due PAUSE_RELEASE, or START without a pcm
++ * close/open since in this case the LLP register is not reset
++ * to 0 and the delay calculation will return with invalid
++ * results.
++ */
++ hext_stream->pplcllpl = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL);
++ hext_stream->pplcllpu = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU);
+ break;
+ default:
+ dev_err(sdev->dev, "unknown trigger command %d\n", cmd);
+diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c
+index 18f07364d2198..d7b446f3f973e 100644
+--- a/sound/soc/sof/intel/hda-pcm.c
++++ b/sound/soc/sof/intel/hda-pcm.c
+@@ -259,8 +259,37 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
+ snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_FORMAT,
+ SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S32);
+
++ /*
++ * The dsp_max_burst_size_in_ms is the length of the maximum burst size
++ * of the host DMA in the ALSA buffer.
++ *
++ * On playback start the DMA will transfer dsp_max_burst_size_in_ms
++ * amount of data in one initial burst to fill up the host DMA buffer.
++ * Consequent DMA burst sizes are shorter and their length can vary.
++ * To make sure that userspace allocate large enough ALSA buffer we need
++ * to place a constraint on the buffer time.
++ *
++ * On capture the DMA will transfer 1ms chunks.
++ *
++ * Exact dsp_max_burst_size_in_ms constraint is racy, so set the
++ * constraint to a minimum of 2x dsp_max_burst_size_in_ms.
++ */
++ if (spcm->stream[direction].dsp_max_burst_size_in_ms)
++ snd_pcm_hw_constraint_minmax(substream->runtime,
++ SNDRV_PCM_HW_PARAM_BUFFER_TIME,
++ spcm->stream[direction].dsp_max_burst_size_in_ms * USEC_PER_MSEC * 2,
++ UINT_MAX);
++
+ /* binding pcm substream to hda stream */
+ substream->runtime->private_data = &dsp_stream->hstream;
++
++ /*
++ * Reset the llp cache values (they are used for LLP compensation in
++ * case the counter is not reset)
++ */
++ dsp_stream->pplcllpl = 0;
++ dsp_stream->pplcllpu = 0;
++
+ return 0;
+ }
+
+diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
+index f2ebadbbcc10e..c603aaf0ca773 100644
+--- a/sound/soc/sof/intel/hda-stream.c
++++ b/sound/soc/sof/intel/hda-stream.c
+@@ -1054,3 +1054,73 @@ snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream,
+
+ return pos;
+ }
++
++#define merge_u64(u32_u, u32_l) (((u64)(u32_u) << 32) | (u32_l))
++
++/**
++ * hda_dsp_get_stream_llp - Retrieve the LLP (Linear Link Position) of the stream
++ * @sdev: SOF device
++ * @component: ASoC component
++ * @substream: PCM substream
++ *
++ * Returns the raw Linear Link Position value
++ */
++u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
++ struct snd_soc_component *component,
++ struct snd_pcm_substream *substream)
++{
++ struct hdac_stream *hstream = substream->runtime->private_data;
++ struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
++ u32 llp_l, llp_u;
++
++ /*
++ * The pplc_addr have been calculated during probe in
++ * hda_dsp_stream_init():
++ * pplc_addr = sdev->bar[HDA_DSP_PP_BAR] +
++ * SOF_HDA_PPLC_BASE +
++ * SOF_HDA_PPLC_MULTI * total_stream +
++ * SOF_HDA_PPLC_INTERVAL * stream_index
++ *
++ * Use this pre-calculated address to avoid repeated re-calculation.
++ */
++ llp_l = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPL);
++ llp_u = readl(hext_stream->pplc_addr + AZX_REG_PPLCLLPU);
++
++ /* Compensate the LLP counter with the saved offset */
++ if (hext_stream->pplcllpl || hext_stream->pplcllpu)
++ return merge_u64(llp_u, llp_l) -
++ merge_u64(hext_stream->pplcllpu, hext_stream->pplcllpl);
++
++ return merge_u64(llp_u, llp_l);
++}
++
++/**
++ * hda_dsp_get_stream_ldp - Retrieve the LDP (Linear DMA Position) of the stream
++ * @sdev: SOF device
++ * @component: ASoC component
++ * @substream: PCM substream
++ *
++ * Returns the raw Linear Link Position value
++ */
++u64 hda_dsp_get_stream_ldp(struct snd_sof_dev *sdev,
++ struct snd_soc_component *component,
++ struct snd_pcm_substream *substream)
++{
++ struct hdac_stream *hstream = substream->runtime->private_data;
++ struct hdac_ext_stream *hext_stream = stream_to_hdac_ext_stream(hstream);
++ u32 ldp_l, ldp_u;
++
++ /*
++ * The pphc_addr have been calculated during probe in
++ * hda_dsp_stream_init():
++ * pphc_addr = sdev->bar[HDA_DSP_PP_BAR] +
++ * SOF_HDA_PPHC_BASE +
++ * SOF_HDA_PPHC_INTERVAL * stream_index
++ *
++ * Use this pre-calculated address to avoid repeated re-calculation.
++ */
++ ldp_l = readl(hext_stream->pphc_addr + AZX_REG_PPHCLDPL);
++ ldp_u = readl(hext_stream->pphc_addr + AZX_REG_PPHCLDPU);
++
++ return ((u64)ldp_u << 32) | ldp_l;
++}
+diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
+index 1592e27bc14da..efb42117df793 100644
+--- a/sound/soc/sof/intel/hda.h
++++ b/sound/soc/sof/intel/hda.h
+@@ -657,6 +657,12 @@ bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev);
+
+ snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream,
+ int direction, bool can_sleep);
++u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
++ struct snd_soc_component *component,
++ struct snd_pcm_substream *substream);
++u64 hda_dsp_get_stream_ldp(struct snd_sof_dev *sdev,
++ struct snd_soc_component *component,
++ struct snd_pcm_substream *substream);
+
+ struct hdac_ext_stream *
+ hda_dsp_stream_get(struct snd_sof_dev *sdev, int direction, u32 flags);
+diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c
+index 30712ea05a7a5..555a51c688dc6 100644
+--- a/sound/soc/sof/intel/lnl.c
++++ b/sound/soc/sof/intel/lnl.c
+@@ -118,8 +118,6 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev)
+ sof_lnl_ops.resume = lnl_hda_dsp_resume;
+ sof_lnl_ops.runtime_resume = lnl_hda_dsp_runtime_resume;
+
+- sof_lnl_ops.get_stream_position = mtl_dsp_get_stream_hda_link_position;
+-
+ /* dsp core get/put */
+ sof_lnl_ops.core_get = mtl_dsp_core_get;
+ sof_lnl_ops.core_put = mtl_dsp_core_put;
+diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c
+index df05dc77b8d5e..060c34988e90d 100644
+--- a/sound/soc/sof/intel/mtl.c
++++ b/sound/soc/sof/intel/mtl.c
+@@ -626,18 +626,6 @@ static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev)
+ return mtl_enable_interrupts(sdev, false);
+ }
+
+-u64 mtl_dsp_get_stream_hda_link_position(struct snd_sof_dev *sdev,
+- struct snd_soc_component *component,
+- struct snd_pcm_substream *substream)
+-{
+- struct hdac_stream *hstream = substream->runtime->private_data;
+- u32 llp_l, llp_u;
+-
+- llp_l = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, MTL_PPLCLLPL(hstream->index));
+- llp_u = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, MTL_PPLCLLPU(hstream->index));
+- return ((u64)llp_u << 32) | llp_l;
+-}
+-
+ int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core)
+ {
+ const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm;
+@@ -707,8 +695,6 @@ int sof_mtl_ops_init(struct snd_sof_dev *sdev)
+ sof_mtl_ops.core_get = mtl_dsp_core_get;
+ sof_mtl_ops.core_put = mtl_dsp_core_put;
+
+- sof_mtl_ops.get_stream_position = mtl_dsp_get_stream_hda_link_position;
+-
+ sdev->private = kzalloc(sizeof(struct sof_ipc4_fw_data), GFP_KERNEL);
+ if (!sdev->private)
+ return -ENOMEM;
+diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h
+index cc5a1f46fd095..ea8c1b83f7127 100644
+--- a/sound/soc/sof/intel/mtl.h
++++ b/sound/soc/sof/intel/mtl.h
+@@ -6,12 +6,6 @@
+ * Copyright(c) 2020-2022 Intel Corporation. All rights reserved.
+ */
+
+-/* HDA Registers */
+-#define MTL_PPLCLLPL_BASE 0x948
+-#define MTL_PPLCLLPU_STRIDE 0x10
+-#define MTL_PPLCLLPL(x) (MTL_PPLCLLPL_BASE + (x) * MTL_PPLCLLPU_STRIDE)
+-#define MTL_PPLCLLPU(x) (MTL_PPLCLLPL_BASE + 0x4 + (x) * MTL_PPLCLLPU_STRIDE)
+-
+ /* DSP Registers */
+ #define MTL_HFDSSCS 0x1000
+ #define MTL_HFDSSCS_SPA_MASK BIT(16)
+@@ -103,9 +97,5 @@ int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id);
+
+ void mtl_ipc_dump(struct snd_sof_dev *sdev);
+
+-u64 mtl_dsp_get_stream_hda_link_position(struct snd_sof_dev *sdev,
+- struct snd_soc_component *component,
+- struct snd_pcm_substream *substream);
+-
+ int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core);
+ int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core);
+diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c
+index 07eb5c6d4adf3..a99fced908251 100644
+--- a/sound/soc/sof/ipc4-pcm.c
++++ b/sound/soc/sof/ipc4-pcm.c
+@@ -15,6 +15,28 @@
+ #include "ipc4-topology.h"
+ #include "ipc4-fw-reg.h"
+
++/**
++ * struct sof_ipc4_timestamp_info - IPC4 timestamp info
++ * @host_copier: the host copier of the pcm stream
++ * @dai_copier: the dai copier of the pcm stream
++ * @stream_start_offset: reported by fw in memory window (converted to frames)
++ * @stream_end_offset: reported by fw in memory window (converted to frames)
++ * @llp_offset: llp offset in memory window
++ * @boundary: wrap boundary should be used for the LLP frame counter
++ * @delay: Calculated and stored in pointer callback. The stored value is
++ * returned in the delay callback.
++ */
++struct sof_ipc4_timestamp_info {
++ struct sof_ipc4_copier *host_copier;
++ struct sof_ipc4_copier *dai_copier;
++ u64 stream_start_offset;
++ u64 stream_end_offset;
++ u32 llp_offset;
++
++ u64 boundary;
++ snd_pcm_sframes_t delay;
++};
++
+ static int sof_ipc4_set_multi_pipeline_state(struct snd_sof_dev *sdev, u32 state,
+ struct ipc4_pipeline_set_state_data *trigger_list)
+ {
+@@ -406,8 +428,19 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
+ }
+
+ /* return if this is the final state */
+- if (state == SOF_IPC4_PIPE_PAUSED)
++ if (state == SOF_IPC4_PIPE_PAUSED) {
++ struct sof_ipc4_timestamp_info *time_info;
++
++ /*
++ * Invalidate the stream_start_offset to make sure that it is
++ * going to be updated if the stream resumes
++ */
++ time_info = spcm->stream[substream->stream].private;
++ if (time_info)
++ time_info->stream_start_offset = SOF_IPC4_INVALID_STREAM_POSITION;
++
+ goto free;
++ }
+ skip_pause_transition:
+ /* else set the RUNNING/RESET state in the DSP */
+ ret = sof_ipc4_set_multi_pipeline_state(sdev, state, trigger_list);
+@@ -447,14 +480,12 @@ static int sof_ipc4_pcm_trigger(struct snd_soc_component *component,
+
+ /* determine the pipeline state */
+ switch (cmd) {
+- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+- state = SOF_IPC4_PIPE_PAUSED;
+- break;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_START:
+ state = SOF_IPC4_PIPE_RUNNING;
+ break;
++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_STOP:
+ state = SOF_IPC4_PIPE_PAUSED;
+@@ -686,6 +717,10 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
+ if (abi_version < SOF_IPC4_FW_REGS_ABI_VER)
+ support_info = false;
+
++ /* For delay reporting the get_host_byte_counter callback is needed */
++ if (!sof_ops(sdev) || !sof_ops(sdev)->get_host_byte_counter)
++ support_info = false;
++
+ for_each_pcm_streams(stream) {
+ pipeline_list = &spcm->stream[stream].pipeline_list;
+
+@@ -818,7 +853,6 @@ static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
+ struct sof_ipc4_copier *host_copier = time_info->host_copier;
+ struct sof_ipc4_copier *dai_copier = time_info->dai_copier;
+ struct sof_ipc4_pipeline_registers ppl_reg;
+- u64 stream_start_position;
+ u32 dai_sample_size;
+ u32 ch, node_index;
+ u32 offset;
+@@ -835,38 +869,51 @@ static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
+ if (ppl_reg.stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION)
+ return -EINVAL;
+
+- stream_start_position = ppl_reg.stream_start_offset;
+ ch = dai_copier->data.out_format.fmt_cfg;
+ ch = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(ch);
+ dai_sample_size = (dai_copier->data.out_format.bit_depth >> 3) * ch;
+- /* convert offset to sample count */
+- do_div(stream_start_position, dai_sample_size);
+- time_info->stream_start_offset = stream_start_position;
++
++ /* convert offsets to frame count */
++ time_info->stream_start_offset = ppl_reg.stream_start_offset;
++ do_div(time_info->stream_start_offset, dai_sample_size);
++ time_info->stream_end_offset = ppl_reg.stream_end_offset;
++ do_div(time_info->stream_end_offset, dai_sample_size);
++
++ /*
++ * Calculate the wrap boundary need to be used for delay calculation
++ * The host counter is in bytes, it will wrap earlier than the frames
++ * based link counter.
++ */
++ time_info->boundary = div64_u64(~((u64)0),
++ frames_to_bytes(substream->runtime, 1));
++ /* Initialize the delay value to 0 (no delay) */
++ time_info->delay = 0;
+
+ return 0;
+ }
+
+-static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
+- struct snd_pcm_substream *substream)
++static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
++ struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t *pointer)
+ {
+ struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct sof_ipc4_timestamp_info *time_info;
+ struct sof_ipc4_llp_reading_slot llp;
+- snd_pcm_uframes_t head_ptr, tail_ptr;
++ snd_pcm_uframes_t head_cnt, tail_cnt;
+ struct snd_sof_pcm_stream *stream;
++ u64 dai_cnt, host_cnt, host_ptr;
+ struct snd_sof_pcm *spcm;
+- u64 tmp_ptr;
+ int ret;
+
+ spcm = snd_sof_find_spcm_dai(component, rtd);
+ if (!spcm)
+- return 0;
++ return -EOPNOTSUPP;
+
+ stream = &spcm->stream[substream->stream];
+ time_info = stream->private;
+ if (!time_info)
+- return 0;
++ return -EOPNOTSUPP;
+
+ /*
+ * stream_start_offset is updated to memory window by FW based on
+@@ -876,45 +923,116 @@ static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
+ if (time_info->stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION) {
+ ret = sof_ipc4_get_stream_start_offset(sdev, substream, stream, time_info);
+ if (ret < 0)
+- return 0;
++ return -EOPNOTSUPP;
+ }
+
++ /* For delay calculation we need the host counter */
++ host_cnt = snd_sof_pcm_get_host_byte_counter(sdev, component, substream);
++ host_ptr = host_cnt;
++
++ /* convert the host_cnt to frames */
++ host_cnt = div64_u64(host_cnt, frames_to_bytes(substream->runtime, 1));
++
+ /*
+- * HDaudio links don't support the LLP counter reported by firmware
+- * the link position is read directly from hardware registers.
++ * If the LLP counter is not reported by firmware in the SRAM window
++ * then read the dai (link) counter via host accessible means if
++ * available.
+ */
+ if (!time_info->llp_offset) {
+- tmp_ptr = snd_sof_pcm_get_stream_position(sdev, component, substream);
+- if (!tmp_ptr)
+- return 0;
++ dai_cnt = snd_sof_pcm_get_dai_frame_counter(sdev, component, substream);
++ if (!dai_cnt)
++ return -EOPNOTSUPP;
+ } else {
+ sof_mailbox_read(sdev, time_info->llp_offset, &llp, sizeof(llp));
+- tmp_ptr = ((u64)llp.reading.llp_u << 32) | llp.reading.llp_l;
++ dai_cnt = ((u64)llp.reading.llp_u << 32) | llp.reading.llp_l;
+ }
++ dai_cnt += time_info->stream_end_offset;
+
+- /* In two cases dai dma position is not accurate
++ /* In two cases dai dma counter is not accurate
+ * (1) dai pipeline is started before host pipeline
+- * (2) multiple streams mixed into one. Each stream has the same dai dma position
++ * (2) multiple streams mixed into one. Each stream has the same dai dma
++ * counter
+ *
+- * Firmware calculates correct stream_start_offset for all cases including above two.
+- * Driver subtracts stream_start_offset from dai dma position to get accurate one
++ * Firmware calculates correct stream_start_offset for all cases
++ * including above two.
++ * Driver subtracts stream_start_offset from dai dma counter to get
++ * accurate one
+ */
+- tmp_ptr -= time_info->stream_start_offset;
+
+- /* Calculate the delay taking into account that both pointer can wrap */
+- div64_u64_rem(tmp_ptr, substream->runtime->boundary, &tmp_ptr);
++ /*
++ * On stream start the dai counter might not yet have reached the
++ * stream_start_offset value which means that no frames have left the
++ * DSP yet from the audio stream (on playback, capture streams have
++ * offset of 0 as we start capturing right away).
++ * In this case we need to adjust the distance between the counters by
++ * increasing the host counter by (offset - dai_counter).
++ * Otherwise the dai_counter needs to be adjusted to reflect the number
++ * of valid frames passed on the DAI side.
++ *
++ * The delay is the difference between the counters on the two
++ * sides of the DSP.
++ */
++ if (dai_cnt < time_info->stream_start_offset) {
++ host_cnt += time_info->stream_start_offset - dai_cnt;
++ dai_cnt = 0;
++ } else {
++ dai_cnt -= time_info->stream_start_offset;
++ }
++
++ /* Wrap the dai counter at the boundary where the host counter wraps */
++ div64_u64_rem(dai_cnt, time_info->boundary, &dai_cnt);
++
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+- head_ptr = substream->runtime->status->hw_ptr;
+- tail_ptr = tmp_ptr;
++ head_cnt = host_cnt;
++ tail_cnt = dai_cnt;
+ } else {
+- head_ptr = tmp_ptr;
+- tail_ptr = substream->runtime->status->hw_ptr;
++ head_cnt = dai_cnt;
++ tail_cnt = host_cnt;
++ }
++
++ if (head_cnt < tail_cnt) {
++ time_info->delay = time_info->boundary - tail_cnt + head_cnt;
++ goto out;
+ }
+
+- if (head_ptr < tail_ptr)
+- return substream->runtime->boundary - tail_ptr + head_ptr;
++ time_info->delay = head_cnt - tail_cnt;
++
++out:
++ /*
++ * Convert the host byte counter to PCM pointer which wraps in buffer
++ * and it is in frames
++ */
++ div64_u64_rem(host_ptr, snd_pcm_lib_buffer_bytes(substream), &host_ptr);
++ *pointer = bytes_to_frames(substream->runtime, host_ptr);
++
++ return 0;
++}
++
++static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
++ struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
++ struct sof_ipc4_timestamp_info *time_info;
++ struct snd_sof_pcm_stream *stream;
++ struct snd_sof_pcm *spcm;
++
++ spcm = snd_sof_find_spcm_dai(component, rtd);
++ if (!spcm)
++ return 0;
++
++ stream = &spcm->stream[substream->stream];
++ time_info = stream->private;
++ /*
++ * Report the stored delay value calculated in the pointer callback.
++ * In the unlikely event that the calculation was skipped/aborted, the
++ * default 0 delay returned.
++ */
++ if (time_info)
++ return time_info->delay;
++
++ /* No delay information available, report 0 as delay */
++ return 0;
+
+- return head_ptr - tail_ptr;
+ }
+
+ const struct sof_ipc_pcm_ops ipc4_pcm_ops = {
+@@ -924,6 +1042,7 @@ const struct sof_ipc_pcm_ops ipc4_pcm_ops = {
+ .dai_link_fixup = sof_ipc4_pcm_dai_link_fixup,
+ .pcm_setup = sof_ipc4_pcm_setup,
+ .pcm_free = sof_ipc4_pcm_free,
++ .pointer = sof_ipc4_pcm_pointer,
+ .delay = sof_ipc4_pcm_delay,
+ .ipc_first_on_start = true,
+ .platform_stop_during_hw_free = true,
+diff --git a/sound/soc/sof/ipc4-priv.h b/sound/soc/sof/ipc4-priv.h
+index 1d39836d5efac..9db9002b44d68 100644
+--- a/sound/soc/sof/ipc4-priv.h
++++ b/sound/soc/sof/ipc4-priv.h
+@@ -88,20 +88,6 @@ struct sof_ipc4_fw_data {
+ struct mutex pipeline_state_mutex; /* protect pipeline triggers, ref counts and states */
+ };
+
+-/**
+- * struct sof_ipc4_timestamp_info - IPC4 timestamp info
+- * @host_copier: the host copier of the pcm stream
+- * @dai_copier: the dai copier of the pcm stream
+- * @stream_start_offset: reported by fw in memory window
+- * @llp_offset: llp offset in memory window
+- */
+-struct sof_ipc4_timestamp_info {
+- struct sof_ipc4_copier *host_copier;
+- struct sof_ipc4_copier *dai_copier;
+- u64 stream_start_offset;
+- u32 llp_offset;
+-};
+-
+ extern const struct sof_ipc_fw_loader_ops ipc4_loader_ops;
+ extern const struct sof_ipc_tplg_ops ipc4_tplg_ops;
+ extern const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops;
+diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
+index f779156fe0e60..4d3d415179c07 100644
+--- a/sound/soc/sof/ipc4-topology.c
++++ b/sound/soc/sof/ipc4-topology.c
+@@ -412,8 +412,9 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
+ struct sof_ipc4_available_audio_format *available_fmt;
+ struct snd_soc_component *scomp = swidget->scomp;
+ struct sof_ipc4_copier *ipc4_copier;
++ struct snd_sof_pcm *spcm;
+ int node_type = 0;
+- int ret;
++ int ret, dir;
+
+ ipc4_copier = kzalloc(sizeof(*ipc4_copier), GFP_KERNEL);
+ if (!ipc4_copier)
+@@ -447,6 +448,25 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
+ }
+ dev_dbg(scomp->dev, "host copier '%s' node_type %u\n", swidget->widget->name, node_type);
+
++ spcm = snd_sof_find_spcm_comp(scomp, swidget->comp_id, &dir);
++ if (!spcm)
++ goto skip_gtw_cfg;
++
++ if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
++ struct snd_sof_pcm_stream *sps = &spcm->stream[dir];
++
++ sof_update_ipc_object(scomp, &sps->dsp_max_burst_size_in_ms,
++ SOF_COPIER_DEEP_BUFFER_TOKENS,
++ swidget->tuples,
++ swidget->num_tuples, sizeof(u32), 1);
++ /* Set default DMA buffer size if it is not specified in topology */
++ if (!sps->dsp_max_burst_size_in_ms)
++ sps->dsp_max_burst_size_in_ms = SOF_IPC4_MIN_DMA_BUFFER_SIZE;
++ } else {
++ /* Capture data is copied from DSP to host in 1ms bursts */
++ spcm->stream[dir].dsp_max_burst_size_in_ms = 1;
++ }
++
+ skip_gtw_cfg:
+ ipc4_copier->gtw_attr = kzalloc(sizeof(*ipc4_copier->gtw_attr), GFP_KERNEL);
+ if (!ipc4_copier->gtw_attr) {
+diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
+index 6538d9f4fe96e..2505a1e1ce340 100644
+--- a/sound/soc/sof/ops.h
++++ b/sound/soc/sof/ops.h
+@@ -523,12 +523,26 @@ static inline int snd_sof_pcm_platform_ack(struct snd_sof_dev *sdev,
+ return 0;
+ }
+
+-static inline u64 snd_sof_pcm_get_stream_position(struct snd_sof_dev *sdev,
+- struct snd_soc_component *component,
+- struct snd_pcm_substream *substream)
++static inline u64
++snd_sof_pcm_get_dai_frame_counter(struct snd_sof_dev *sdev,
++ struct snd_soc_component *component,
++ struct snd_pcm_substream *substream)
+ {
+- if (sof_ops(sdev) && sof_ops(sdev)->get_stream_position)
+- return sof_ops(sdev)->get_stream_position(sdev, component, substream);
++ if (sof_ops(sdev) && sof_ops(sdev)->get_dai_frame_counter)
++ return sof_ops(sdev)->get_dai_frame_counter(sdev, component,
++ substream);
++
++ return 0;
++}
++
++static inline u64
++snd_sof_pcm_get_host_byte_counter(struct snd_sof_dev *sdev,
++ struct snd_soc_component *component,
++ struct snd_pcm_substream *substream)
++{
++ if (sof_ops(sdev) && sof_ops(sdev)->get_host_byte_counter)
++ return sof_ops(sdev)->get_host_byte_counter(sdev, component,
++ substream);
+
+ return 0;
+ }
+diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
+index 33d576b176478..f03cee94bce62 100644
+--- a/sound/soc/sof/pcm.c
++++ b/sound/soc/sof/pcm.c
+@@ -388,13 +388,21 @@ static snd_pcm_uframes_t sof_pcm_pointer(struct snd_soc_component *component,
+ {
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
++ const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm);
+ struct snd_sof_pcm *spcm;
+ snd_pcm_uframes_t host, dai;
++ int ret = -EOPNOTSUPP;
+
+ /* nothing to do for BE */
+ if (rtd->dai_link->no_pcm)
+ return 0;
+
++ if (pcm_ops && pcm_ops->pointer)
++ ret = pcm_ops->pointer(component, substream, &host);
++
++ if (ret != -EOPNOTSUPP)
++ return ret ? ret : host;
++
+ /* use dsp ops pointer callback directly if set */
+ if (sof_ops(sdev)->pcm_pointer)
+ return sof_ops(sdev)->pcm_pointer(sdev, substream);
+diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
+index 8874ee5f557fb..85b26e3fefa8f 100644
+--- a/sound/soc/sof/sof-audio.h
++++ b/sound/soc/sof/sof-audio.h
+@@ -103,7 +103,10 @@ struct snd_sof_dai_config_data {
+ * additional memory in the SOF PCM stream structure
+ * @pcm_free: Function pointer for PCM free that can be used for freeing any
+ * additional memory in the SOF PCM stream structure
+- * @delay: Function pointer for pcm delay calculation
++ * @pointer: Function pointer for pcm pointer
++ * Note: the @pointer callback may return -EOPNOTSUPP which should be
++ * handled in a same way as if the callback is not provided
++ * @delay: Function pointer for pcm delay reporting
+ * @reset_hw_params_during_stop: Flag indicating whether the hw_params should be reset during the
+ * STOP pcm trigger
+ * @ipc_first_on_start: Send IPC before invoking platform trigger during
+@@ -124,6 +127,9 @@ struct sof_ipc_pcm_ops {
+ int (*dai_link_fixup)(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params);
+ int (*pcm_setup)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm);
+ void (*pcm_free)(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm);
++ int (*pointer)(struct snd_soc_component *component,
++ struct snd_pcm_substream *substream,
++ snd_pcm_uframes_t *pointer);
+ snd_pcm_sframes_t (*delay)(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream);
+ bool reset_hw_params_during_stop;
+@@ -321,6 +327,7 @@ struct snd_sof_pcm_stream {
+ struct work_struct period_elapsed_work;
+ struct snd_soc_dapm_widget_list *list; /* list of connected DAPM widgets */
+ bool d0i3_compatible; /* DSP can be in D0I3 when this pcm is opened */
++ unsigned int dsp_max_burst_size_in_ms; /* The maximum size of the host DMA burst in ms */
+ /*
+ * flag to indicate that the DSP pipelines should be kept
+ * active or not while suspending the stream
+diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h
+index 6d7897bf96075..09eb2de445fee 100644
+--- a/sound/soc/sof/sof-priv.h
++++ b/sound/soc/sof/sof-priv.h
+@@ -255,13 +255,25 @@ struct snd_sof_dsp_ops {
+ int (*pcm_ack)(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream); /* optional */
+
+ /*
+- * optional callback to retrieve the link DMA position for the substream
+- * when the position is not reported in the shared SRAM windows but
+- * instead from a host-accessible hardware counter.
++ * optional callback to retrieve the number of frames left/arrived from/to
++ * the DSP on the DAI side (link/codec/DMIC/etc).
++ *
++ * The callback is used when the firmware does not provide this information
++ * via the shared SRAM window and it can be retrieved by host.
+ */
+- u64 (*get_stream_position)(struct snd_sof_dev *sdev,
+- struct snd_soc_component *component,
+- struct snd_pcm_substream *substream); /* optional */
++ u64 (*get_dai_frame_counter)(struct snd_sof_dev *sdev,
++ struct snd_soc_component *component,
++ struct snd_pcm_substream *substream); /* optional */
++
++ /*
++ * Optional callback to retrieve the number of bytes left/arrived from/to
++ * the DSP on the host side (bytes between host ALSA buffer and DSP).
++ *
++ * The callback is needed for ALSA delay reporting.
++ */
++ u64 (*get_host_byte_counter)(struct snd_sof_dev *sdev,
++ struct snd_soc_component *component,
++ struct snd_pcm_substream *substream); /* optional */
+
+ /* host read DSP stream data */
+ int (*ipc_msg_data)(struct snd_sof_dev *sdev,
+diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py
+index 7fc1aa788f6f5..c19dec2394915 100755
+--- a/tools/net/ynl/ynl-gen-c.py
++++ b/tools/net/ynl/ynl-gen-c.py
+@@ -243,8 +243,11 @@ class Type(SpecAttr):
+ presence = ''
+ for i in range(0, len(ref)):
+ presence = f"{var}->{'.'.join(ref[:i] + [''])}_present.{ref[i]}"
+- if self.presence_type() == 'bit':
+- code.append(presence + ' = 1;')
++ # Every layer below last is a nest, so we know it uses bit presence
++ # last layer is "self" and may be a complex type
++ if i == len(ref) - 1 and self.presence_type() != 'bit':
++ continue
++ code.append(presence + ' = 1;')
+ code += self._setter_lines(ri, member, presence)
+
+ func_name = f"{op_prefix(ri, direction, deref=deref)}_set_{'_'.join(ref)}"
+diff --git a/tools/testing/selftests/mm/vm_util.h b/tools/testing/selftests/mm/vm_util.h
+index c02990bbd56f4..9007c420d52c5 100644
+--- a/tools/testing/selftests/mm/vm_util.h
++++ b/tools/testing/selftests/mm/vm_util.h
+@@ -3,7 +3,7 @@
+ #include <stdbool.h>
+ #include <sys/mman.h>
+ #include <err.h>
+-#include <string.h> /* ffsl() */
++#include <strings.h> /* ffsl() */
+ #include <unistd.h> /* _SC_PAGESIZE */
+
+ #define BIT_ULL(nr) (1ULL << (nr))
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_connect.sh b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
+index 7898d62fce0b5..713de81822227 100755
+--- a/tools/testing/selftests/net/mptcp/mptcp_connect.sh
++++ b/tools/testing/selftests/net/mptcp/mptcp_connect.sh
+@@ -1,6 +1,11 @@
+ #!/bin/bash
+ # SPDX-License-Identifier: GPL-2.0
+
++# Double quotes to prevent globbing and word splitting is recommended in new
++# code but we accept it, especially because there were too many before having
++# address all other issues detected by shellcheck.
++#shellcheck disable=SC2086
++
+ . "$(dirname "${0}")/mptcp_lib.sh"
+
+ time_start=$(date +%s)
+@@ -13,7 +18,6 @@ sout=""
+ cin_disconnect=""
+ cin=""
+ cout=""
+-ksft_skip=4
+ capture=false
+ timeout_poll=30
+ timeout_test=$((timeout_poll * 2 + 1))
+@@ -131,6 +135,8 @@ ns4="ns4-$rndh"
+ TEST_COUNT=0
+ TEST_GROUP=""
+
++# This function is used in the cleanup trap
++#shellcheck disable=SC2317
+ cleanup()
+ {
+ rm -f "$cin_disconnect" "$cout_disconnect"
+@@ -225,8 +231,9 @@ set_ethtool_flags() {
+ local dev="$2"
+ local flags="$3"
+
+- ip netns exec $ns ethtool -K $dev $flags 2>/dev/null
+- [ $? -eq 0 ] && echo "INFO: set $ns dev $dev: ethtool -K $flags"
++ if ip netns exec $ns ethtool -K $dev $flags 2>/dev/null; then
++ echo "INFO: set $ns dev $dev: ethtool -K $flags"
++ fi
+ }
+
+ set_random_ethtool_flags() {
+@@ -321,19 +328,19 @@ do_transfer()
+ local extra_args="$7"
+
+ local port
+- port=$((10000+$TEST_COUNT))
++ port=$((10000+TEST_COUNT))
+ TEST_COUNT=$((TEST_COUNT+1))
+
+ if [ "$rcvbuf" -gt 0 ]; then
+- extra_args="$extra_args -R $rcvbuf"
++ extra_args+=" -R $rcvbuf"
+ fi
+
+ if [ "$sndbuf" -gt 0 ]; then
+- extra_args="$extra_args -S $sndbuf"
++ extra_args+=" -S $sndbuf"
+ fi
+
+ if [ -n "$testmode" ]; then
+- extra_args="$extra_args -m $testmode"
++ extra_args+=" -m $testmode"
+ fi
+
+ if [ -n "$extra_args" ] && $options_log; then
+@@ -378,12 +385,20 @@ do_transfer()
+ nstat -n
+ fi
+
+- local stat_synrx_last_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX")
+- local stat_ackrx_last_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableACKRX")
+- local stat_cookietx_last=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesSent")
+- local stat_cookierx_last=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesRecv")
+- local stat_csum_err_s=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtDataCsumErr")
+- local stat_csum_err_c=$(mptcp_lib_get_counter "${connector_ns}" "MPTcpExtDataCsumErr")
++ local stat_synrx_last_l
++ local stat_ackrx_last_l
++ local stat_cookietx_last
++ local stat_cookierx_last
++ local stat_csum_err_s
++ local stat_csum_err_c
++ local stat_tcpfb_last_l
++ stat_synrx_last_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX")
++ stat_ackrx_last_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableACKRX")
++ stat_cookietx_last=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesSent")
++ stat_cookierx_last=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesRecv")
++ stat_csum_err_s=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtDataCsumErr")
++ stat_csum_err_c=$(mptcp_lib_get_counter "${connector_ns}" "MPTcpExtDataCsumErr")
++ stat_tcpfb_last_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableFallbackACK")
+
+ timeout ${timeout_test} \
+ ip netns exec ${listener_ns} \
+@@ -446,11 +461,19 @@ do_transfer()
+ mptcp_lib_check_transfer $cin $sout "file received by server"
+ rets=$?
+
+- local stat_synrx_now_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX")
+- local stat_ackrx_now_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableACKRX")
+- local stat_cookietx_now=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesSent")
+- local stat_cookierx_now=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesRecv")
+- local stat_ooo_now=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtTCPOFOQueue")
++ local extra=""
++ local stat_synrx_now_l
++ local stat_ackrx_now_l
++ local stat_cookietx_now
++ local stat_cookierx_now
++ local stat_ooo_now
++ local stat_tcpfb_now_l
++ stat_synrx_now_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableSYNRX")
++ stat_ackrx_now_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableACKRX")
++ stat_cookietx_now=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesSent")
++ stat_cookierx_now=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtSyncookiesRecv")
++ stat_ooo_now=$(mptcp_lib_get_counter "${listener_ns}" "TcpExtTCPOFOQueue")
++ stat_tcpfb_now_l=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtMPCapableFallbackACK")
+
+ expect_synrx=$((stat_synrx_last_l))
+ expect_ackrx=$((stat_ackrx_last_l))
+@@ -459,8 +482,8 @@ do_transfer()
+ cookies=${cookies##*=}
+
+ if [ ${cl_proto} = "MPTCP" ] && [ ${srv_proto} = "MPTCP" ]; then
+- expect_synrx=$((stat_synrx_last_l+$connect_per_transfer))
+- expect_ackrx=$((stat_ackrx_last_l+$connect_per_transfer))
++ expect_synrx=$((stat_synrx_last_l+connect_per_transfer))
++ expect_ackrx=$((stat_ackrx_last_l+connect_per_transfer))
+ fi
+
+ if [ ${stat_synrx_now_l} -lt ${expect_synrx} ]; then
+@@ -468,66 +491,75 @@ do_transfer()
+ "${stat_synrx_now_l}" "${expect_synrx}" 1>&2
+ retc=1
+ fi
+- if [ ${stat_ackrx_now_l} -lt ${expect_ackrx} -a ${stat_ooo_now} -eq 0 ]; then
++ if [ ${stat_ackrx_now_l} -lt ${expect_ackrx} ] && [ ${stat_ooo_now} -eq 0 ]; then
+ if [ ${stat_ooo_now} -eq 0 ]; then
+ printf "[ FAIL ] lower MPC ACK rx (%d) than expected (%d)\n" \
+ "${stat_ackrx_now_l}" "${expect_ackrx}" 1>&2
+ rets=1
+ else
+- printf "[ Note ] fallback due to TCP OoO"
++ extra+=" [ Note ] fallback due to TCP OoO"
+ fi
+ fi
+
+ if $checksum; then
+- local csum_err_s=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtDataCsumErr")
+- local csum_err_c=$(mptcp_lib_get_counter "${connector_ns}" "MPTcpExtDataCsumErr")
++ local csum_err_s
++ local csum_err_c
++ csum_err_s=$(mptcp_lib_get_counter "${listener_ns}" "MPTcpExtDataCsumErr")
++ csum_err_c=$(mptcp_lib_get_counter "${connector_ns}" "MPTcpExtDataCsumErr")
+
+ local csum_err_s_nr=$((csum_err_s - stat_csum_err_s))
+ if [ $csum_err_s_nr -gt 0 ]; then
+- printf "[ FAIL ]\nserver got $csum_err_s_nr data checksum error[s]"
++ printf "[ FAIL ]\nserver got %d data checksum error[s]" ${csum_err_s_nr}
+ rets=1
+ fi
+
+ local csum_err_c_nr=$((csum_err_c - stat_csum_err_c))
+ if [ $csum_err_c_nr -gt 0 ]; then
+- printf "[ FAIL ]\nclient got $csum_err_c_nr data checksum error[s]"
++ printf "[ FAIL ]\nclient got %d data checksum error[s]" ${csum_err_c_nr}
+ retc=1
+ fi
+ fi
+
+- if [ $retc -eq 0 ] && [ $rets -eq 0 ]; then
+- printf "[ OK ]"
+- mptcp_lib_result_pass "${TEST_GROUP}: ${result_msg}"
+- else
+- mptcp_lib_result_fail "${TEST_GROUP}: ${result_msg}"
++ if [ ${stat_ooo_now} -eq 0 ] && [ ${stat_tcpfb_last_l} -ne ${stat_tcpfb_now_l} ]; then
++ mptcp_lib_pr_fail "unexpected fallback to TCP"
++ rets=1
+ fi
+
+ if [ $cookies -eq 2 ];then
+ if [ $stat_cookietx_last -ge $stat_cookietx_now ] ;then
+- printf " WARN: CookieSent: did not advance"
++ extra+=" WARN: CookieSent: did not advance"
+ fi
+ if [ $stat_cookierx_last -ge $stat_cookierx_now ] ;then
+- printf " WARN: CookieRecv: did not advance"
++ extra+=" WARN: CookieRecv: did not advance"
+ fi
+ else
+ if [ $stat_cookietx_last -ne $stat_cookietx_now ] ;then
+- printf " WARN: CookieSent: changed"
++ extra+=" WARN: CookieSent: changed"
+ fi
+ if [ $stat_cookierx_last -ne $stat_cookierx_now ] ;then
+- printf " WARN: CookieRecv: changed"
++ extra+=" WARN: CookieRecv: changed"
+ fi
+ fi
+
+ if [ ${stat_synrx_now_l} -gt ${expect_synrx} ]; then
+- printf " WARN: SYNRX: expect %d, got %d (probably retransmissions)" \
+- "${expect_synrx}" "${stat_synrx_now_l}"
++ extra+=" WARN: SYNRX: expect ${expect_synrx},"
++ extra+=" got ${stat_synrx_now_l} (probably retransmissions)"
+ fi
+ if [ ${stat_ackrx_now_l} -gt ${expect_ackrx} ]; then
+- printf " WARN: ACKRX: expect %d, got %d (probably retransmissions)" \
+- "${expect_ackrx}" "${stat_ackrx_now_l}"
++ extra+=" WARN: ACKRX: expect ${expect_ackrx},"
++ extra+=" got ${stat_ackrx_now_l} (probably retransmissions)"
++ fi
++
++ if [ $retc -eq 0 ] && [ $rets -eq 0 ]; then
++ printf "[ OK ]%s\n" "${extra:1}"
++ mptcp_lib_result_pass "${TEST_GROUP}: ${result_msg}"
++ else
++ if [ -n "${extra}" ]; then
++ printf "%s\n" "${extra:1}"
++ fi
++ mptcp_lib_result_fail "${TEST_GROUP}: ${result_msg}"
+ fi
+
+- echo
+ cat "$capout"
+ [ $retc -eq 0 ] && [ $rets -eq 0 ]
+ }
+@@ -658,7 +690,7 @@ run_test_transparent()
+ return
+ fi
+
+-ip netns exec "$listener_ns" nft -f /dev/stdin <<"EOF"
++ if ! ip netns exec "$listener_ns" nft -f /dev/stdin <<"EOF"
+ flush ruleset
+ table inet mangle {
+ chain divert {
+@@ -669,7 +701,7 @@ table inet mangle {
+ }
+ }
+ EOF
+- if [ $? -ne 0 ]; then
++ then
+ echo "SKIP: $msg, could not load nft ruleset"
+ mptcp_lib_fail_if_expected_feature "nft rules"
+ mptcp_lib_result_skip "${TEST_GROUP}"
+@@ -684,8 +716,7 @@ EOF
+ local_addr="0.0.0.0"
+ fi
+
+- ip -net "$listener_ns" $r6flag rule add fwmark 1 lookup 100
+- if [ $? -ne 0 ]; then
++ if ! ip -net "$listener_ns" $r6flag rule add fwmark 1 lookup 100; then
+ ip netns exec "$listener_ns" nft flush ruleset
+ echo "SKIP: $msg, ip $r6flag rule failed"
+ mptcp_lib_fail_if_expected_feature "ip rule"
+@@ -693,8 +724,7 @@ EOF
+ return
+ fi
+
+- ip -net "$listener_ns" route add local $local_addr/0 dev lo table 100
+- if [ $? -ne 0 ]; then
++ if ! ip -net "$listener_ns" route add local $local_addr/0 dev lo table 100; then
+ ip netns exec "$listener_ns" nft flush ruleset
+ ip -net "$listener_ns" $r6flag rule del fwmark 1 lookup 100
+ echo "SKIP: $msg, ip route add local $local_addr failed"
+@@ -854,10 +884,10 @@ mptcp_lib_result_code "${ret}" "ping tests"
+ stop_if_error "Could not even run ping tests"
+
+ [ -n "$tc_loss" ] && tc -net "$ns2" qdisc add dev ns2eth3 root netem loss random $tc_loss delay ${tc_delay}ms
+-echo -n "INFO: Using loss of $tc_loss "
+-test "$tc_delay" -gt 0 && echo -n "delay $tc_delay ms "
++tc_info="loss of $tc_loss "
++test "$tc_delay" -gt 0 && tc_info+="delay $tc_delay ms "
+
+-reorder_delay=$(($tc_delay / 4))
++reorder_delay=$((tc_delay / 4))
+
+ if [ -z "${tc_reorder}" ]; then
+ reorder1=$((RANDOM%10))
+@@ -866,17 +896,17 @@ if [ -z "${tc_reorder}" ]; then
+
+ if [ $reorder_delay -gt 0 ] && [ $reorder1 -lt 100 ] && [ $reorder2 -gt 0 ]; then
+ tc_reorder="reorder ${reorder1}% ${reorder2}%"
+- echo -n "$tc_reorder with delay ${reorder_delay}ms "
++ tc_info+="$tc_reorder with delay ${reorder_delay}ms "
+ fi
+ elif [ "$tc_reorder" = "0" ];then
+ tc_reorder=""
+ elif [ "$reorder_delay" -gt 0 ];then
+ # reordering requires some delay
+ tc_reorder="reorder $tc_reorder"
+- echo -n "$tc_reorder with delay ${reorder_delay}ms "
++ tc_info+="$tc_reorder with delay ${reorder_delay}ms "
+ fi
+
+-echo "on ns3eth4"
++echo "INFO: Using ${tc_info}on ns3eth4"
+
+ tc -net "$ns3" qdisc add dev ns3eth4 root netem delay ${reorder_delay}ms $tc_reorder
+
+diff --git a/tools/testing/selftests/net/mptcp/mptcp_join.sh b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+index e4581b0dfb967..24be952b4d4a1 100755
+--- a/tools/testing/selftests/net/mptcp/mptcp_join.sh
++++ b/tools/testing/selftests/net/mptcp/mptcp_join.sh
+@@ -773,7 +773,7 @@ pm_nl_check_endpoint()
+ [ -n "$_flags" ]; flags="flags $_flags"
+ shift
+ elif [ $1 = "dev" ]; then
+- [ -n "$2" ]; dev="dev $1"
++ [ -n "$2" ]; dev="dev $2"
+ shift
+ elif [ $1 = "id" ]; then
+ _id=$2
+@@ -799,18 +799,18 @@ pm_nl_check_endpoint()
+ line="${line% }"
+ # the dump order is: address id flags port dev
+ [ -n "$addr" ] && expected_line="$addr"
+- expected_line="$expected_line $id"
+- [ -n "$_flags" ] && expected_line="$expected_line ${_flags//","/" "}"
+- [ -n "$dev" ] && expected_line="$expected_line $dev"
+- [ -n "$port" ] && expected_line="$expected_line $port"
++ expected_line+=" $id"
++ [ -n "$_flags" ] && expected_line+=" ${_flags//","/" "}"
++ [ -n "$dev" ] && expected_line+=" $dev"
++ [ -n "$port" ] && expected_line+=" $port"
+ else
+ line=$(ip netns exec $ns ./pm_nl_ctl get $_id)
+ # the dump order is: id flags dev address port
+ expected_line="$id"
+- [ -n "$flags" ] && expected_line="$expected_line $flags"
+- [ -n "$dev" ] && expected_line="$expected_line $dev"
+- [ -n "$addr" ] && expected_line="$expected_line $addr"
+- [ -n "$_port" ] && expected_line="$expected_line $_port"
++ [ -n "$flags" ] && expected_line+=" $flags"
++ [ -n "$dev" ] && expected_line+=" $dev"
++ [ -n "$addr" ] && expected_line+=" $addr"
++ [ -n "$_port" ] && expected_line+=" $_port"
+ fi
+ if [ "$line" = "$expected_line" ]; then
+ print_ok
+@@ -1261,7 +1261,7 @@ chk_csum_nr()
+ print_check "sum"
+ count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtDataCsumErr")
+ if [ "$count" != "$csum_ns1" ]; then
+- extra_msg="$extra_msg ns1=$count"
++ extra_msg+=" ns1=$count"
+ fi
+ if [ -z "$count" ]; then
+ print_skip
+@@ -1274,7 +1274,7 @@ chk_csum_nr()
+ print_check "csum"
+ count=$(mptcp_lib_get_counter ${ns2} "MPTcpExtDataCsumErr")
+ if [ "$count" != "$csum_ns2" ]; then
+- extra_msg="$extra_msg ns2=$count"
++ extra_msg+=" ns2=$count"
+ fi
+ if [ -z "$count" ]; then
+ print_skip
+@@ -1318,7 +1318,7 @@ chk_fail_nr()
+ print_check "ftx"
+ count=$(mptcp_lib_get_counter ${ns_tx} "MPTcpExtMPFailTx")
+ if [ "$count" != "$fail_tx" ]; then
+- extra_msg="$extra_msg,tx=$count"
++ extra_msg+=",tx=$count"
+ fi
+ if [ -z "$count" ]; then
+ print_skip
+@@ -1332,7 +1332,7 @@ chk_fail_nr()
+ print_check "failrx"
+ count=$(mptcp_lib_get_counter ${ns_rx} "MPTcpExtMPFailRx")
+ if [ "$count" != "$fail_rx" ]; then
+- extra_msg="$extra_msg,rx=$count"
++ extra_msg+=",rx=$count"
+ fi
+ if [ -z "$count" ]; then
+ print_skip
+@@ -1367,7 +1367,7 @@ chk_fclose_nr()
+ if [ -z "$count" ]; then
+ print_skip
+ elif [ "$count" != "$fclose_tx" ]; then
+- extra_msg="$extra_msg,tx=$count"
++ extra_msg+=",tx=$count"
+ fail_test "got $count MP_FASTCLOSE[s] TX expected $fclose_tx"
+ else
+ print_ok
+@@ -1378,7 +1378,7 @@ chk_fclose_nr()
+ if [ -z "$count" ]; then
+ print_skip
+ elif [ "$count" != "$fclose_rx" ]; then
+- extra_msg="$extra_msg,rx=$count"
++ extra_msg+=",rx=$count"
+ fail_test "got $count MP_FASTCLOSE[s] RX expected $fclose_rx"
+ else
+ print_ok
+@@ -1747,7 +1747,7 @@ chk_rm_nr()
+ count=$((count + cnt))
+ if [ "$count" != "$rm_subflow_nr" ]; then
+ suffix="$count in [$rm_subflow_nr:$((rm_subflow_nr*2))]"
+- extra_msg="$extra_msg simult"
++ extra_msg+=" simult"
+ fi
+ if [ $count -ge "$rm_subflow_nr" ] && \
+ [ "$count" -le "$((rm_subflow_nr *2 ))" ]; then
+@@ -3589,6 +3589,8 @@ endpoint_tests()
+ local tests_pid=$!
+
+ wait_mpj $ns2
++ pm_nl_check_endpoint "creation" \
++ $ns2 10.0.2.2 id 2 flags subflow dev ns2eth2
+ chk_subflow_nr "before delete" 2
+ chk_mptcp_info subflows 1 subflows 1
+
+diff --git a/tools/testing/selftests/net/reuseaddr_conflict.c b/tools/testing/selftests/net/reuseaddr_conflict.c
+index 7c5b12664b03b..bfb07dc495186 100644
+--- a/tools/testing/selftests/net/reuseaddr_conflict.c
++++ b/tools/testing/selftests/net/reuseaddr_conflict.c
+@@ -109,6 +109,6 @@ int main(void)
+ fd1 = open_port(0, 1);
+ if (fd1 >= 0)
+ error(1, 0, "Was allowed to create an ipv4 reuseport on an already bound non-reuseport socket with no ipv6");
+- fprintf(stderr, "Success");
++ fprintf(stderr, "Success\n");
+ return 0;
+ }
+diff --git a/tools/testing/selftests/net/test_vxlan_mdb.sh b/tools/testing/selftests/net/test_vxlan_mdb.sh
+index 84a05a9e46d86..04fb17a92e993 100755
+--- a/tools/testing/selftests/net/test_vxlan_mdb.sh
++++ b/tools/testing/selftests/net/test_vxlan_mdb.sh
+@@ -1177,6 +1177,7 @@ encap_params_common()
+ local plen=$1; shift
+ local enc_ethtype=$1; shift
+ local grp=$1; shift
++ local grp_dmac=$1; shift
+ local src=$1; shift
+ local mz=$1; shift
+
+@@ -1195,11 +1196,11 @@ encap_params_common()
+ run_cmd "bridge -n $ns1 mdb replace dev vx0 port vx0 grp $grp permanent dst $vtep2_ip src_vni 10020"
+
+ run_cmd "tc -n $ns2 filter replace dev vx0 ingress pref 1 handle 101 proto all flower enc_dst_ip $vtep1_ip action pass"
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Destination IP - match"
+
+- run_cmd "ip netns exec $ns1 $mz br0.20 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.20 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Destination IP - no match"
+
+@@ -1212,20 +1213,20 @@ encap_params_common()
+ run_cmd "bridge -n $ns1 mdb replace dev vx0 port vx0 grp $grp permanent dst $vtep1_ip dst_port 1111 src_vni 10020"
+
+ run_cmd "tc -n $ns2 filter replace dev veth0 ingress pref 1 handle 101 proto $enc_ethtype flower ip_proto udp dst_port 4789 action pass"
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev veth0 ingress" 101 1
+ log_test $? 0 "Default destination port - match"
+
+- run_cmd "ip netns exec $ns1 $mz br0.20 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.20 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev veth0 ingress" 101 1
+ log_test $? 0 "Default destination port - no match"
+
+ run_cmd "tc -n $ns2 filter replace dev veth0 ingress pref 1 handle 101 proto $enc_ethtype flower ip_proto udp dst_port 1111 action pass"
+- run_cmd "ip netns exec $ns1 $mz br0.20 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.20 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev veth0 ingress" 101 1
+ log_test $? 0 "Non-default destination port - match"
+
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev veth0 ingress" 101 1
+ log_test $? 0 "Non-default destination port - no match"
+
+@@ -1238,11 +1239,11 @@ encap_params_common()
+ run_cmd "bridge -n $ns1 mdb replace dev vx0 port vx0 grp $grp permanent dst $vtep1_ip src_vni 10020"
+
+ run_cmd "tc -n $ns2 filter replace dev vx0 ingress pref 1 handle 101 proto all flower enc_key_id 10010 action pass"
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Default destination VNI - match"
+
+- run_cmd "ip netns exec $ns1 $mz br0.20 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.20 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Default destination VNI - no match"
+
+@@ -1250,11 +1251,11 @@ encap_params_common()
+ run_cmd "bridge -n $ns1 mdb replace dev vx0 port vx0 grp $grp permanent dst $vtep1_ip vni 10010 src_vni 10020"
+
+ run_cmd "tc -n $ns2 filter replace dev vx0 ingress pref 1 handle 101 proto all flower enc_key_id 10020 action pass"
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Non-default destination VNI - match"
+
+- run_cmd "ip netns exec $ns1 $mz br0.20 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.20 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Non-default destination VNI - no match"
+
+@@ -1272,6 +1273,7 @@ encap_params_ipv4_ipv4()
+ local plen=32
+ local enc_ethtype="ip"
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local src=192.0.2.129
+
+ echo
+@@ -1279,7 +1281,7 @@ encap_params_ipv4_ipv4()
+ echo "------------------------------------------------------------------"
+
+ encap_params_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $enc_ethtype \
+- $grp $src "mausezahn"
++ $grp $grp_dmac $src "mausezahn"
+ }
+
+ encap_params_ipv6_ipv4()
+@@ -1291,6 +1293,7 @@ encap_params_ipv6_ipv4()
+ local plen=32
+ local enc_ethtype="ip"
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local src=2001:db8:100::1
+
+ echo
+@@ -1298,7 +1301,7 @@ encap_params_ipv6_ipv4()
+ echo "------------------------------------------------------------------"
+
+ encap_params_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $enc_ethtype \
+- $grp $src "mausezahn -6"
++ $grp $grp_dmac $src "mausezahn -6"
+ }
+
+ encap_params_ipv4_ipv6()
+@@ -1310,6 +1313,7 @@ encap_params_ipv4_ipv6()
+ local plen=128
+ local enc_ethtype="ipv6"
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local src=192.0.2.129
+
+ echo
+@@ -1317,7 +1321,7 @@ encap_params_ipv4_ipv6()
+ echo "------------------------------------------------------------------"
+
+ encap_params_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $enc_ethtype \
+- $grp $src "mausezahn"
++ $grp $grp_dmac $src "mausezahn"
+ }
+
+ encap_params_ipv6_ipv6()
+@@ -1329,6 +1333,7 @@ encap_params_ipv6_ipv6()
+ local plen=128
+ local enc_ethtype="ipv6"
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local src=2001:db8:100::1
+
+ echo
+@@ -1336,7 +1341,7 @@ encap_params_ipv6_ipv6()
+ echo "------------------------------------------------------------------"
+
+ encap_params_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $enc_ethtype \
+- $grp $src "mausezahn -6"
++ $grp $grp_dmac $src "mausezahn -6"
+ }
+
+ starg_exclude_ir_common()
+@@ -1347,6 +1352,7 @@ starg_exclude_ir_common()
+ local vtep2_ip=$1; shift
+ local plen=$1; shift
+ local grp=$1; shift
++ local grp_dmac=$1; shift
+ local valid_src=$1; shift
+ local invalid_src=$1; shift
+ local mz=$1; shift
+@@ -1368,14 +1374,14 @@ starg_exclude_ir_common()
+ run_cmd "bridge -n $ns1 mdb replace dev vx0 port vx0 grp $grp permanent filter_mode exclude source_list $invalid_src dst $vtep2_ip src_vni 10010"
+
+ # Check that invalid source is not forwarded to any VTEP.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $invalid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $invalid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 0
+ log_test $? 0 "Block excluded source - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 0
+ log_test $? 0 "Block excluded source - second VTEP"
+
+ # Check that valid source is forwarded to both VTEPs.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Forward valid source - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 1
+@@ -1385,14 +1391,14 @@ starg_exclude_ir_common()
+ run_cmd "bridge -n $ns1 mdb del dev vx0 port vx0 grp $grp dst $vtep2_ip src_vni 10010"
+
+ # Check that invalid source is not forwarded to any VTEP.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $invalid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $invalid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Block excluded source after removal - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 1
+ log_test $? 0 "Block excluded source after removal - second VTEP"
+
+ # Check that valid source is forwarded to the remaining VTEP.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 2
+ log_test $? 0 "Forward valid source after removal - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 1
+@@ -1407,6 +1413,7 @@ starg_exclude_ir_ipv4_ipv4()
+ local vtep2_ip=198.51.100.200
+ local plen=32
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local valid_src=192.0.2.129
+ local invalid_src=192.0.2.145
+
+@@ -1415,7 +1422,7 @@ starg_exclude_ir_ipv4_ipv4()
+ echo "-------------------------------------------------------------"
+
+ starg_exclude_ir_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $grp \
+- $valid_src $invalid_src "mausezahn"
++ $grp_dmac $valid_src $invalid_src "mausezahn"
+ }
+
+ starg_exclude_ir_ipv6_ipv4()
+@@ -1426,6 +1433,7 @@ starg_exclude_ir_ipv6_ipv4()
+ local vtep2_ip=198.51.100.200
+ local plen=32
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local valid_src=2001:db8:100::1
+ local invalid_src=2001:db8:200::1
+
+@@ -1434,7 +1442,7 @@ starg_exclude_ir_ipv6_ipv4()
+ echo "-------------------------------------------------------------"
+
+ starg_exclude_ir_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $grp \
+- $valid_src $invalid_src "mausezahn -6"
++ $grp_dmac $valid_src $invalid_src "mausezahn -6"
+ }
+
+ starg_exclude_ir_ipv4_ipv6()
+@@ -1445,6 +1453,7 @@ starg_exclude_ir_ipv4_ipv6()
+ local vtep2_ip=2001:db8:2000::1
+ local plen=128
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local valid_src=192.0.2.129
+ local invalid_src=192.0.2.145
+
+@@ -1453,7 +1462,7 @@ starg_exclude_ir_ipv4_ipv6()
+ echo "-------------------------------------------------------------"
+
+ starg_exclude_ir_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $grp \
+- $valid_src $invalid_src "mausezahn"
++ $grp_dmac $valid_src $invalid_src "mausezahn"
+ }
+
+ starg_exclude_ir_ipv6_ipv6()
+@@ -1464,6 +1473,7 @@ starg_exclude_ir_ipv6_ipv6()
+ local vtep2_ip=2001:db8:2000::1
+ local plen=128
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local valid_src=2001:db8:100::1
+ local invalid_src=2001:db8:200::1
+
+@@ -1472,7 +1482,7 @@ starg_exclude_ir_ipv6_ipv6()
+ echo "-------------------------------------------------------------"
+
+ starg_exclude_ir_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $grp \
+- $valid_src $invalid_src "mausezahn -6"
++ $grp_dmac $valid_src $invalid_src "mausezahn -6"
+ }
+
+ starg_include_ir_common()
+@@ -1483,6 +1493,7 @@ starg_include_ir_common()
+ local vtep2_ip=$1; shift
+ local plen=$1; shift
+ local grp=$1; shift
++ local grp_dmac=$1; shift
+ local valid_src=$1; shift
+ local invalid_src=$1; shift
+ local mz=$1; shift
+@@ -1504,14 +1515,14 @@ starg_include_ir_common()
+ run_cmd "bridge -n $ns1 mdb replace dev vx0 port vx0 grp $grp permanent filter_mode include source_list $valid_src dst $vtep2_ip src_vni 10010"
+
+ # Check that invalid source is not forwarded to any VTEP.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $invalid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $invalid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 0
+ log_test $? 0 "Block excluded source - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 0
+ log_test $? 0 "Block excluded source - second VTEP"
+
+ # Check that valid source is forwarded to both VTEPs.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Forward valid source - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 1
+@@ -1521,14 +1532,14 @@ starg_include_ir_common()
+ run_cmd "bridge -n $ns1 mdb del dev vx0 port vx0 grp $grp dst $vtep2_ip src_vni 10010"
+
+ # Check that invalid source is not forwarded to any VTEP.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $invalid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $invalid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Block excluded source after removal - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 1
+ log_test $? 0 "Block excluded source after removal - second VTEP"
+
+ # Check that valid source is forwarded to the remaining VTEP.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 2
+ log_test $? 0 "Forward valid source after removal - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 1
+@@ -1543,6 +1554,7 @@ starg_include_ir_ipv4_ipv4()
+ local vtep2_ip=198.51.100.200
+ local plen=32
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local valid_src=192.0.2.129
+ local invalid_src=192.0.2.145
+
+@@ -1551,7 +1563,7 @@ starg_include_ir_ipv4_ipv4()
+ echo "-------------------------------------------------------------"
+
+ starg_include_ir_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $grp \
+- $valid_src $invalid_src "mausezahn"
++ $grp_dmac $valid_src $invalid_src "mausezahn"
+ }
+
+ starg_include_ir_ipv6_ipv4()
+@@ -1562,6 +1574,7 @@ starg_include_ir_ipv6_ipv4()
+ local vtep2_ip=198.51.100.200
+ local plen=32
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local valid_src=2001:db8:100::1
+ local invalid_src=2001:db8:200::1
+
+@@ -1570,7 +1583,7 @@ starg_include_ir_ipv6_ipv4()
+ echo "-------------------------------------------------------------"
+
+ starg_include_ir_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $grp \
+- $valid_src $invalid_src "mausezahn -6"
++ $grp_dmac $valid_src $invalid_src "mausezahn -6"
+ }
+
+ starg_include_ir_ipv4_ipv6()
+@@ -1581,6 +1594,7 @@ starg_include_ir_ipv4_ipv6()
+ local vtep2_ip=2001:db8:2000::1
+ local plen=128
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local valid_src=192.0.2.129
+ local invalid_src=192.0.2.145
+
+@@ -1589,7 +1603,7 @@ starg_include_ir_ipv4_ipv6()
+ echo "-------------------------------------------------------------"
+
+ starg_include_ir_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $grp \
+- $valid_src $invalid_src "mausezahn"
++ $grp_dmac $valid_src $invalid_src "mausezahn"
+ }
+
+ starg_include_ir_ipv6_ipv6()
+@@ -1600,6 +1614,7 @@ starg_include_ir_ipv6_ipv6()
+ local vtep2_ip=2001:db8:2000::1
+ local plen=128
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local valid_src=2001:db8:100::1
+ local invalid_src=2001:db8:200::1
+
+@@ -1608,7 +1623,7 @@ starg_include_ir_ipv6_ipv6()
+ echo "-------------------------------------------------------------"
+
+ starg_include_ir_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $grp \
+- $valid_src $invalid_src "mausezahn -6"
++ $grp_dmac $valid_src $invalid_src "mausezahn -6"
+ }
+
+ starg_exclude_p2mp_common()
+@@ -1618,6 +1633,7 @@ starg_exclude_p2mp_common()
+ local mcast_grp=$1; shift
+ local plen=$1; shift
+ local grp=$1; shift
++ local grp_dmac=$1; shift
+ local valid_src=$1; shift
+ local invalid_src=$1; shift
+ local mz=$1; shift
+@@ -1635,12 +1651,12 @@ starg_exclude_p2mp_common()
+ run_cmd "bridge -n $ns1 mdb replace dev vx0 port vx0 grp $grp permanent filter_mode exclude source_list $invalid_src dst $mcast_grp src_vni 10010 via veth0"
+
+ # Check that invalid source is not forwarded.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $invalid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $invalid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 0
+ log_test $? 0 "Block excluded source"
+
+ # Check that valid source is forwarded.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Forward valid source"
+
+@@ -1648,7 +1664,7 @@ starg_exclude_p2mp_common()
+ run_cmd "ip -n $ns2 address del $mcast_grp/$plen dev veth0"
+
+ # Check that valid source is not received anymore.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Receive of valid source after removal from group"
+ }
+@@ -1660,6 +1676,7 @@ starg_exclude_p2mp_ipv4_ipv4()
+ local mcast_grp=238.1.1.1
+ local plen=32
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local valid_src=192.0.2.129
+ local invalid_src=192.0.2.145
+
+@@ -1667,7 +1684,7 @@ starg_exclude_p2mp_ipv4_ipv4()
+ echo "Data path: (*, G) EXCLUDE - P2MP - IPv4 overlay / IPv4 underlay"
+ echo "---------------------------------------------------------------"
+
+- starg_exclude_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp \
++ starg_exclude_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp $grp_dmac \
+ $valid_src $invalid_src "mausezahn"
+ }
+
+@@ -1678,6 +1695,7 @@ starg_exclude_p2mp_ipv6_ipv4()
+ local mcast_grp=238.1.1.1
+ local plen=32
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local valid_src=2001:db8:100::1
+ local invalid_src=2001:db8:200::1
+
+@@ -1685,7 +1703,7 @@ starg_exclude_p2mp_ipv6_ipv4()
+ echo "Data path: (*, G) EXCLUDE - P2MP - IPv6 overlay / IPv4 underlay"
+ echo "---------------------------------------------------------------"
+
+- starg_exclude_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp \
++ starg_exclude_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp $grp_dmac \
+ $valid_src $invalid_src "mausezahn -6"
+ }
+
+@@ -1696,6 +1714,7 @@ starg_exclude_p2mp_ipv4_ipv6()
+ local mcast_grp=ff0e::2
+ local plen=128
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local valid_src=192.0.2.129
+ local invalid_src=192.0.2.145
+
+@@ -1703,7 +1722,7 @@ starg_exclude_p2mp_ipv4_ipv6()
+ echo "Data path: (*, G) EXCLUDE - P2MP - IPv4 overlay / IPv6 underlay"
+ echo "---------------------------------------------------------------"
+
+- starg_exclude_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp \
++ starg_exclude_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp $grp_dmac \
+ $valid_src $invalid_src "mausezahn"
+ }
+
+@@ -1714,6 +1733,7 @@ starg_exclude_p2mp_ipv6_ipv6()
+ local mcast_grp=ff0e::2
+ local plen=128
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local valid_src=2001:db8:100::1
+ local invalid_src=2001:db8:200::1
+
+@@ -1721,7 +1741,7 @@ starg_exclude_p2mp_ipv6_ipv6()
+ echo "Data path: (*, G) EXCLUDE - P2MP - IPv6 overlay / IPv6 underlay"
+ echo "---------------------------------------------------------------"
+
+- starg_exclude_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp \
++ starg_exclude_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp $grp_dmac \
+ $valid_src $invalid_src "mausezahn -6"
+ }
+
+@@ -1732,6 +1752,7 @@ starg_include_p2mp_common()
+ local mcast_grp=$1; shift
+ local plen=$1; shift
+ local grp=$1; shift
++ local grp_dmac=$1; shift
+ local valid_src=$1; shift
+ local invalid_src=$1; shift
+ local mz=$1; shift
+@@ -1749,12 +1770,12 @@ starg_include_p2mp_common()
+ run_cmd "bridge -n $ns1 mdb replace dev vx0 port vx0 grp $grp permanent filter_mode include source_list $valid_src dst $mcast_grp src_vni 10010 via veth0"
+
+ # Check that invalid source is not forwarded.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $invalid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $invalid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 0
+ log_test $? 0 "Block excluded source"
+
+ # Check that valid source is forwarded.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Forward valid source"
+
+@@ -1762,7 +1783,7 @@ starg_include_p2mp_common()
+ run_cmd "ip -n $ns2 address del $mcast_grp/$plen dev veth0"
+
+ # Check that valid source is not received anymore.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $valid_src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Receive of valid source after removal from group"
+ }
+@@ -1774,6 +1795,7 @@ starg_include_p2mp_ipv4_ipv4()
+ local mcast_grp=238.1.1.1
+ local plen=32
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local valid_src=192.0.2.129
+ local invalid_src=192.0.2.145
+
+@@ -1781,7 +1803,7 @@ starg_include_p2mp_ipv4_ipv4()
+ echo "Data path: (*, G) INCLUDE - P2MP - IPv4 overlay / IPv4 underlay"
+ echo "---------------------------------------------------------------"
+
+- starg_include_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp \
++ starg_include_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp $grp_dmac \
+ $valid_src $invalid_src "mausezahn"
+ }
+
+@@ -1792,6 +1814,7 @@ starg_include_p2mp_ipv6_ipv4()
+ local mcast_grp=238.1.1.1
+ local plen=32
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local valid_src=2001:db8:100::1
+ local invalid_src=2001:db8:200::1
+
+@@ -1799,7 +1822,7 @@ starg_include_p2mp_ipv6_ipv4()
+ echo "Data path: (*, G) INCLUDE - P2MP - IPv6 overlay / IPv4 underlay"
+ echo "---------------------------------------------------------------"
+
+- starg_include_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp \
++ starg_include_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp $grp_dmac \
+ $valid_src $invalid_src "mausezahn -6"
+ }
+
+@@ -1810,6 +1833,7 @@ starg_include_p2mp_ipv4_ipv6()
+ local mcast_grp=ff0e::2
+ local plen=128
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local valid_src=192.0.2.129
+ local invalid_src=192.0.2.145
+
+@@ -1817,7 +1841,7 @@ starg_include_p2mp_ipv4_ipv6()
+ echo "Data path: (*, G) INCLUDE - P2MP - IPv4 overlay / IPv6 underlay"
+ echo "---------------------------------------------------------------"
+
+- starg_include_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp \
++ starg_include_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp $grp_dmac \
+ $valid_src $invalid_src "mausezahn"
+ }
+
+@@ -1828,6 +1852,7 @@ starg_include_p2mp_ipv6_ipv6()
+ local mcast_grp=ff0e::2
+ local plen=128
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local valid_src=2001:db8:100::1
+ local invalid_src=2001:db8:200::1
+
+@@ -1835,7 +1860,7 @@ starg_include_p2mp_ipv6_ipv6()
+ echo "Data path: (*, G) INCLUDE - P2MP - IPv6 overlay / IPv6 underlay"
+ echo "---------------------------------------------------------------"
+
+- starg_include_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp \
++ starg_include_p2mp_common $ns1 $ns2 $mcast_grp $plen $grp $grp_dmac \
+ $valid_src $invalid_src "mausezahn -6"
+ }
+
+@@ -1847,6 +1872,7 @@ egress_vni_translation_common()
+ local plen=$1; shift
+ local proto=$1; shift
+ local grp=$1; shift
++ local grp_dmac=$1; shift
+ local src=$1; shift
+ local mz=$1; shift
+
+@@ -1882,20 +1908,20 @@ egress_vni_translation_common()
+ # Make sure that packets sent from the first VTEP over VLAN 10 are
+ # received by the SVI corresponding to the L3VNI (14000 / VLAN 4000) on
+ # the second VTEP, since it is configured as PVID.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev br0.4000 ingress" 101 1
+ log_test $? 0 "Egress VNI translation - PVID configured"
+
+ # Remove PVID flag from VLAN 4000 on the second VTEP and make sure
+ # packets are no longer received by the SVI interface.
+ run_cmd "bridge -n $ns2 vlan add vid 4000 dev vx0"
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev br0.4000 ingress" 101 1
+ log_test $? 0 "Egress VNI translation - no PVID configured"
+
+ # Reconfigure the PVID and make sure packets are received again.
+ run_cmd "bridge -n $ns2 vlan add vid 4000 dev vx0 pvid"
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev br0.4000 ingress" 101 2
+ log_test $? 0 "Egress VNI translation - PVID reconfigured"
+ }
+@@ -1908,6 +1934,7 @@ egress_vni_translation_ipv4_ipv4()
+ local plen=32
+ local proto="ipv4"
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local src=192.0.2.129
+
+ echo
+@@ -1915,7 +1942,7 @@ egress_vni_translation_ipv4_ipv4()
+ echo "----------------------------------------------------------------"
+
+ egress_vni_translation_common $ns1 $ns2 $mcast_grp $plen $proto $grp \
+- $src "mausezahn"
++ $grp_dmac $src "mausezahn"
+ }
+
+ egress_vni_translation_ipv6_ipv4()
+@@ -1926,6 +1953,7 @@ egress_vni_translation_ipv6_ipv4()
+ local plen=32
+ local proto="ipv6"
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local src=2001:db8:100::1
+
+ echo
+@@ -1933,7 +1961,7 @@ egress_vni_translation_ipv6_ipv4()
+ echo "----------------------------------------------------------------"
+
+ egress_vni_translation_common $ns1 $ns2 $mcast_grp $plen $proto $grp \
+- $src "mausezahn -6"
++ $grp_dmac $src "mausezahn -6"
+ }
+
+ egress_vni_translation_ipv4_ipv6()
+@@ -1944,6 +1972,7 @@ egress_vni_translation_ipv4_ipv6()
+ local plen=128
+ local proto="ipv4"
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local src=192.0.2.129
+
+ echo
+@@ -1951,7 +1980,7 @@ egress_vni_translation_ipv4_ipv6()
+ echo "----------------------------------------------------------------"
+
+ egress_vni_translation_common $ns1 $ns2 $mcast_grp $plen $proto $grp \
+- $src "mausezahn"
++ $grp_dmac $src "mausezahn"
+ }
+
+ egress_vni_translation_ipv6_ipv6()
+@@ -1962,6 +1991,7 @@ egress_vni_translation_ipv6_ipv6()
+ local plen=128
+ local proto="ipv6"
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local src=2001:db8:100::1
+
+ echo
+@@ -1969,7 +1999,7 @@ egress_vni_translation_ipv6_ipv6()
+ echo "----------------------------------------------------------------"
+
+ egress_vni_translation_common $ns1 $ns2 $mcast_grp $plen $proto $grp \
+- $src "mausezahn -6"
++ $grp_dmac $src "mausezahn -6"
+ }
+
+ all_zeros_mdb_common()
+@@ -1982,12 +2012,18 @@ all_zeros_mdb_common()
+ local vtep4_ip=$1; shift
+ local plen=$1; shift
+ local ipv4_grp=239.1.1.1
++ local ipv4_grp_dmac=01:00:5e:01:01:01
+ local ipv4_unreg_grp=239.2.2.2
++ local ipv4_unreg_grp_dmac=01:00:5e:02:02:02
+ local ipv4_ll_grp=224.0.0.100
++ local ipv4_ll_grp_dmac=01:00:5e:00:00:64
+ local ipv4_src=192.0.2.129
+ local ipv6_grp=ff0e::1
++ local ipv6_grp_dmac=33:33:00:00:00:01
+ local ipv6_unreg_grp=ff0e::2
++ local ipv6_unreg_grp_dmac=33:33:00:00:00:02
+ local ipv6_ll_grp=ff02::1
++ local ipv6_ll_grp_dmac=33:33:00:00:00:01
+ local ipv6_src=2001:db8:100::1
+
+ # Install all-zeros (catchall) MDB entries for IPv4 and IPv6 traffic
+@@ -2023,7 +2059,7 @@ all_zeros_mdb_common()
+
+ # Send registered IPv4 multicast and make sure it only arrives to the
+ # first VTEP.
+- run_cmd "ip netns exec $ns1 mausezahn br0.10 -A $ipv4_src -B $ipv4_grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 mausezahn br0.10 -a own -b $ipv4_grp_dmac -A $ipv4_src -B $ipv4_grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "Registered IPv4 multicast - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 0
+@@ -2031,7 +2067,7 @@ all_zeros_mdb_common()
+
+ # Send unregistered IPv4 multicast that is not link-local and make sure
+ # it arrives to the first and second VTEPs.
+- run_cmd "ip netns exec $ns1 mausezahn br0.10 -A $ipv4_src -B $ipv4_unreg_grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 mausezahn br0.10 -a own -b $ipv4_unreg_grp_dmac -A $ipv4_src -B $ipv4_unreg_grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 2
+ log_test $? 0 "Unregistered IPv4 multicast - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 1
+@@ -2039,7 +2075,7 @@ all_zeros_mdb_common()
+
+ # Send IPv4 link-local multicast traffic and make sure it does not
+ # arrive to any VTEP.
+- run_cmd "ip netns exec $ns1 mausezahn br0.10 -A $ipv4_src -B $ipv4_ll_grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 mausezahn br0.10 -a own -b $ipv4_ll_grp_dmac -A $ipv4_src -B $ipv4_ll_grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 2
+ log_test $? 0 "Link-local IPv4 multicast - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 1
+@@ -2074,7 +2110,7 @@ all_zeros_mdb_common()
+
+ # Send registered IPv6 multicast and make sure it only arrives to the
+ # third VTEP.
+- run_cmd "ip netns exec $ns1 mausezahn -6 br0.10 -A $ipv6_src -B $ipv6_grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 mausezahn -6 br0.10 -a own -b $ipv6_grp_dmac -A $ipv6_src -B $ipv6_grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 103 1
+ log_test $? 0 "Registered IPv6 multicast - third VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 104 0
+@@ -2082,7 +2118,7 @@ all_zeros_mdb_common()
+
+ # Send unregistered IPv6 multicast that is not link-local and make sure
+ # it arrives to the third and fourth VTEPs.
+- run_cmd "ip netns exec $ns1 mausezahn -6 br0.10 -A $ipv6_src -B $ipv6_unreg_grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 mausezahn -6 br0.10 -a own -b $ipv6_unreg_grp_dmac -A $ipv6_src -B $ipv6_unreg_grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 103 2
+ log_test $? 0 "Unregistered IPv6 multicast - third VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 104 1
+@@ -2090,7 +2126,7 @@ all_zeros_mdb_common()
+
+ # Send IPv6 link-local multicast traffic and make sure it does not
+ # arrive to any VTEP.
+- run_cmd "ip netns exec $ns1 mausezahn -6 br0.10 -A $ipv6_src -B $ipv6_ll_grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 mausezahn -6 br0.10 -a own -b $ipv6_ll_grp_dmac -A $ipv6_src -B $ipv6_ll_grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 103 2
+ log_test $? 0 "Link-local IPv6 multicast - third VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 104 1
+@@ -2165,6 +2201,7 @@ mdb_fdb_common()
+ local plen=$1; shift
+ local proto=$1; shift
+ local grp=$1; shift
++ local grp_dmac=$1; shift
+ local src=$1; shift
+ local mz=$1; shift
+
+@@ -2188,7 +2225,7 @@ mdb_fdb_common()
+
+ # Send IP multicast traffic and make sure it is forwarded by the MDB
+ # and only arrives to the first VTEP.
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "IP multicast - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 0
+@@ -2205,7 +2242,7 @@ mdb_fdb_common()
+ # Remove the MDB entry and make sure that IP multicast is now forwarded
+ # by the FDB to the second VTEP.
+ run_cmd "bridge -n $ns1 mdb del dev vx0 port vx0 grp $grp dst $vtep1_ip src_vni 10010"
+- run_cmd "ip netns exec $ns1 $mz br0.10 -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
++ run_cmd "ip netns exec $ns1 $mz br0.10 -a own -b $grp_dmac -A $src -B $grp -t udp sp=12345,dp=54321 -p 100 -c 1 -q"
+ tc_check_packets "$ns2" "dev vx0 ingress" 101 1
+ log_test $? 0 "IP multicast after removal - first VTEP"
+ tc_check_packets "$ns2" "dev vx0 ingress" 102 2
+@@ -2221,14 +2258,15 @@ mdb_fdb_ipv4_ipv4()
+ local plen=32
+ local proto="ipv4"
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local src=192.0.2.129
+
+ echo
+ echo "Data path: MDB with FDB - IPv4 overlay / IPv4 underlay"
+ echo "------------------------------------------------------"
+
+- mdb_fdb_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $proto $grp $src \
+- "mausezahn"
++ mdb_fdb_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $proto $grp \
++ $grp_dmac $src "mausezahn"
+ }
+
+ mdb_fdb_ipv6_ipv4()
+@@ -2240,14 +2278,15 @@ mdb_fdb_ipv6_ipv4()
+ local plen=32
+ local proto="ipv6"
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local src=2001:db8:100::1
+
+ echo
+ echo "Data path: MDB with FDB - IPv6 overlay / IPv4 underlay"
+ echo "------------------------------------------------------"
+
+- mdb_fdb_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $proto $grp $src \
+- "mausezahn -6"
++ mdb_fdb_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $proto $grp \
++ $grp_dmac $src "mausezahn -6"
+ }
+
+ mdb_fdb_ipv4_ipv6()
+@@ -2259,14 +2298,15 @@ mdb_fdb_ipv4_ipv6()
+ local plen=128
+ local proto="ipv4"
+ local grp=239.1.1.1
++ local grp_dmac=01:00:5e:01:01:01
+ local src=192.0.2.129
+
+ echo
+ echo "Data path: MDB with FDB - IPv4 overlay / IPv6 underlay"
+ echo "------------------------------------------------------"
+
+- mdb_fdb_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $proto $grp $src \
+- "mausezahn"
++ mdb_fdb_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $proto $grp \
++ $grp_dmac $src "mausezahn"
+ }
+
+ mdb_fdb_ipv6_ipv6()
+@@ -2278,14 +2318,15 @@ mdb_fdb_ipv6_ipv6()
+ local plen=128
+ local proto="ipv6"
+ local grp=ff0e::1
++ local grp_dmac=33:33:00:00:00:01
+ local src=2001:db8:100::1
+
+ echo
+ echo "Data path: MDB with FDB - IPv6 overlay / IPv6 underlay"
+ echo "------------------------------------------------------"
+
+- mdb_fdb_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $proto $grp $src \
+- "mausezahn -6"
++ mdb_fdb_common $ns1 $ns2 $vtep1_ip $vtep2_ip $plen $proto $grp \
++ $grp_dmac $src "mausezahn -6"
+ }
+
+ mdb_grp1_loop()
+@@ -2320,7 +2361,9 @@ mdb_torture_common()
+ local vtep1_ip=$1; shift
+ local vtep2_ip=$1; shift
+ local grp1=$1; shift
++ local grp1_dmac=$1; shift
+ local grp2=$1; shift
++ local grp2_dmac=$1; shift
+ local src=$1; shift
+ local mz=$1; shift
+ local pid1
+@@ -2345,9 +2388,9 @@ mdb_torture_common()
+ pid1=$!
+ mdb_grp2_loop $ns1 $vtep1_ip $vtep2_ip $grp2 &
+ pid2=$!
+- ip netns exec $ns1 $mz br0.10 -A $src -B $grp1 -t udp sp=12345,dp=54321 -p 100 -c 0 -q &
++ ip netns exec $ns1 $mz br0.10 -a own -b $grp1_dmac -A $src -B $grp1 -t udp sp=12345,dp=54321 -p 100 -c 0 -q &
+ pid3=$!
+- ip netns exec $ns1 $mz br0.10 -A $src -B $grp2 -t udp sp=12345,dp=54321 -p 100 -c 0 -q &
++ ip netns exec $ns1 $mz br0.10 -a own -b $grp2_dmac -A $src -B $grp2 -t udp sp=12345,dp=54321 -p 100 -c 0 -q &
+ pid4=$!
+
+ sleep 30
+@@ -2363,15 +2406,17 @@ mdb_torture_ipv4_ipv4()
+ local vtep1_ip=198.51.100.100
+ local vtep2_ip=198.51.100.200
+ local grp1=239.1.1.1
++ local grp1_dmac=01:00:5e:01:01:01
+ local grp2=239.2.2.2
++ local grp2_dmac=01:00:5e:02:02:02
+ local src=192.0.2.129
+
+ echo
+ echo "Data path: MDB torture test - IPv4 overlay / IPv4 underlay"
+ echo "----------------------------------------------------------"
+
+- mdb_torture_common $ns1 $vtep1_ip $vtep2_ip $grp1 $grp2 $src \
+- "mausezahn"
++ mdb_torture_common $ns1 $vtep1_ip $vtep2_ip $grp1 $grp1_dmac $grp2 \
++ $grp2_dmac $src "mausezahn"
+ }
+
+ mdb_torture_ipv6_ipv4()
+@@ -2380,15 +2425,17 @@ mdb_torture_ipv6_ipv4()
+ local vtep1_ip=198.51.100.100
+ local vtep2_ip=198.51.100.200
+ local grp1=ff0e::1
++ local grp1_dmac=33:33:00:00:00:01
+ local grp2=ff0e::2
++ local grp2_dmac=33:33:00:00:00:02
+ local src=2001:db8:100::1
+
+ echo
+ echo "Data path: MDB torture test - IPv6 overlay / IPv4 underlay"
+ echo "----------------------------------------------------------"
+
+- mdb_torture_common $ns1 $vtep1_ip $vtep2_ip $grp1 $grp2 $src \
+- "mausezahn -6"
++ mdb_torture_common $ns1 $vtep1_ip $vtep2_ip $grp1 $grp1_dmac $grp2 \
++ $grp2_dmac $src "mausezahn -6"
+ }
+
+ mdb_torture_ipv4_ipv6()
+@@ -2397,15 +2444,17 @@ mdb_torture_ipv4_ipv6()
+ local vtep1_ip=2001:db8:1000::1
+ local vtep2_ip=2001:db8:2000::1
+ local grp1=239.1.1.1
++ local grp1_dmac=01:00:5e:01:01:01
+ local grp2=239.2.2.2
++ local grp2_dmac=01:00:5e:02:02:02
+ local src=192.0.2.129
+
+ echo
+ echo "Data path: MDB torture test - IPv4 overlay / IPv6 underlay"
+ echo "----------------------------------------------------------"
+
+- mdb_torture_common $ns1 $vtep1_ip $vtep2_ip $grp1 $grp2 $src \
+- "mausezahn"
++ mdb_torture_common $ns1 $vtep1_ip $vtep2_ip $grp1 $grp1_dmac $grp2 \
++ $grp2_dmac $src "mausezahn"
+ }
+
+ mdb_torture_ipv6_ipv6()
+@@ -2414,15 +2463,17 @@ mdb_torture_ipv6_ipv6()
+ local vtep1_ip=2001:db8:1000::1
+ local vtep2_ip=2001:db8:2000::1
+ local grp1=ff0e::1
++ local grp1_dmac=33:33:00:00:00:01
+ local grp2=ff0e::2
++ local grp2_dmac=33:33:00:00:00:02
+ local src=2001:db8:100::1
+
+ echo
+ echo "Data path: MDB torture test - IPv6 overlay / IPv6 underlay"
+ echo "----------------------------------------------------------"
+
+- mdb_torture_common $ns1 $vtep1_ip $vtep2_ip $grp1 $grp2 $src \
+- "mausezahn -6"
++ mdb_torture_common $ns1 $vtep1_ip $vtep2_ip $grp1 $grp1_dmac $grp2 \
++ $grp2_dmac $src "mausezahn -6"
+ }
+
+ ################################################################################
+diff --git a/tools/testing/selftests/net/udpgro_fwd.sh b/tools/testing/selftests/net/udpgro_fwd.sh
+index 9cd5e885e91f7..f4549e6894dd9 100755
+--- a/tools/testing/selftests/net/udpgro_fwd.sh
++++ b/tools/testing/selftests/net/udpgro_fwd.sh
+@@ -241,7 +241,7 @@ for family in 4 6; do
+
+ create_vxlan_pair
+ ip netns exec $NS_DST ethtool -K veth$DST rx-gro-list on
+- run_test "GRO frag list over UDP tunnel" $OL_NET$DST 1 1
++ run_test "GRO frag list over UDP tunnel" $OL_NET$DST 10 10
+ cleanup
+
+ # use NAT to circumvent GRO FWD check
+@@ -254,13 +254,7 @@ for family in 4 6; do
+ # load arp cache before running the test to reduce the amount of
+ # stray traffic on top of the UDP tunnel
+ ip netns exec $NS_SRC $PING -q -c 1 $OL_NET$DST_NAT >/dev/null
+- run_test "GRO fwd over UDP tunnel" $OL_NET$DST_NAT 1 1 $OL_NET$DST
+- cleanup
+-
+- create_vxlan_pair
+- run_bench "UDP tunnel fwd perf" $OL_NET$DST
+- ip netns exec $NS_DST ethtool -K veth$DST rx-udp-gro-forwarding on
+- run_bench "UDP tunnel GRO fwd perf" $OL_NET$DST
++ run_test "GRO fwd over UDP tunnel" $OL_NET$DST_NAT 10 10 $OL_NET$DST
+ cleanup
+ done
+
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-11 14:47 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-04-11 14:47 UTC (permalink / raw
To: gentoo-commits
commit: e9ca04d0b0f60f591603f76063130b0f82920234
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Thu Apr 11 14:46:47 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Thu Apr 11 14:46:47 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=e9ca04d0
gcc-plugins/stackleak: Avoid .head.text section
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +++
...plugins-stackleak-Avoid-head-text-section.patch | 36 ++++++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/0000_README b/0000_README
index d556a3be..a7081596 100644
--- a/0000_README
+++ b/0000_README
@@ -75,6 +75,10 @@ Patch: 1730_parisc-Disable-prctl.patch
From: https://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git
Desc: prctl: Temporarily disable prctl(PR_SET_MDWE) on parisc
+Patch: 1800_gcc-plugins-stackleak-Avoid-head-text-section.patch
+From: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+Desc: gcc-plugins/stackleak: Avoid .head.text section
+
Patch: 2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch
From: https://lore.kernel.org/linux-bluetooth/20190522070540.48895-1-marcel@holtmann.org/raw
Desc: Bluetooth: Check key sizes only when Secure Simple Pairing is enabled. See bug #686758
diff --git a/1800_gcc-plugins-stackleak-Avoid-head-text-section.patch b/1800_gcc-plugins-stackleak-Avoid-head-text-section.patch
new file mode 100644
index 00000000..28964f01
--- /dev/null
+++ b/1800_gcc-plugins-stackleak-Avoid-head-text-section.patch
@@ -0,0 +1,36 @@
+From e7d24c0aa8e678f41457d1304e2091cac6fd1a2e Mon Sep 17 00:00:00 2001
+From: Ard Biesheuvel <ardb@kernel.org>
+Date: Thu, 28 Mar 2024 07:42:57 +0100
+Subject: gcc-plugins/stackleak: Avoid .head.text section
+
+The .head.text section carries the startup code that runs with the MMU
+off or with a translation of memory that deviates from the ordinary one.
+So avoid instrumentation with the stackleak plugin, which already avoids
+.init.text and .noinstr.text entirely.
+
+Fixes: 48204aba801f1b51 ("x86/sme: Move early SME kernel encryption handling into .head.text")
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Closes: https://lore.kernel.org/oe-lkp/202403221630.2692c998-oliver.sang@intel.com
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Link: https://lore.kernel.org/r/20240328064256.2358634-2-ardb+git@google.com
+Signed-off-by: Kees Cook <keescook@chromium.org>
+---
+ scripts/gcc-plugins/stackleak_plugin.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c
+index c5c2ce113c9232..d20c47d21ad835 100644
+--- a/scripts/gcc-plugins/stackleak_plugin.c
++++ b/scripts/gcc-plugins/stackleak_plugin.c
+@@ -467,6 +467,8 @@ static bool stackleak_gate(void)
+ return false;
+ if (STRING_EQUAL(section, ".entry.text"))
+ return false;
++ if (STRING_EQUAL(section, ".head.text"))
++ return false;
+ }
+
+ return track_frame_size >= 0;
+--
+cgit 1.2.3-korg
+
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-13 13:05 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-04-13 13:05 UTC (permalink / raw
To: gentoo-commits
commit: 6bda36616382a968aef5fa2696c513e2017f2294
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sat Apr 13 13:05:20 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sat Apr 13 13:05:20 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=6bda3661
Linux patch 6.8.6
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1005_linux-6.8.6.patch | 5431 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 5435 insertions(+)
diff --git a/0000_README b/0000_README
index a7081596..98a6896a 100644
--- a/0000_README
+++ b/0000_README
@@ -63,6 +63,10 @@ Patch: 1004_linux-6.8.5.patch
From: https://www.kernel.org
Desc: Linux 6.8.5
+Patch: 1005_linux-6.8.6.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.6
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1005_linux-6.8.6.patch b/1005_linux-6.8.6.patch
new file mode 100644
index 00000000..35581ea1
--- /dev/null
+++ b/1005_linux-6.8.6.patch
@@ -0,0 +1,5431 @@
+diff --git a/Makefile b/Makefile
+index f29a75b75861a..c426d47f4b7bf 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 5
++SUBLEVEL = 6
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/arch/arm/boot/dts/rockchip/rk322x.dtsi b/arch/arm/boot/dts/rockchip/rk322x.dtsi
+index 831561fc18146..96421355c2746 100644
+--- a/arch/arm/boot/dts/rockchip/rk322x.dtsi
++++ b/arch/arm/boot/dts/rockchip/rk322x.dtsi
+@@ -736,14 +736,20 @@ hdmi: hdmi@200a0000 {
+ status = "disabled";
+
+ ports {
+- hdmi_in: port {
+- #address-cells = <1>;
+- #size-cells = <0>;
+- hdmi_in_vop: endpoint@0 {
+- reg = <0>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ hdmi_in: port@0 {
++ reg = <0>;
++
++ hdmi_in_vop: endpoint {
+ remote-endpoint = <&vop_out_hdmi>;
+ };
+ };
++
++ hdmi_out: port@1 {
++ reg = <1>;
++ };
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/rockchip/rk3288.dtsi b/arch/arm/boot/dts/rockchip/rk3288.dtsi
+index ead343dc3df10..3f1d640afafae 100644
+--- a/arch/arm/boot/dts/rockchip/rk3288.dtsi
++++ b/arch/arm/boot/dts/rockchip/rk3288.dtsi
+@@ -1240,27 +1240,37 @@ hdmi: hdmi@ff980000 {
+ compatible = "rockchip,rk3288-dw-hdmi";
+ reg = <0x0 0xff980000 0x0 0x20000>;
+ reg-io-width = <4>;
+- #sound-dai-cells = <0>;
+- rockchip,grf = <&grf>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>, <&cru SCLK_HDMI_CEC>;
+ clock-names = "iahb", "isfr", "cec";
+ power-domains = <&power RK3288_PD_VIO>;
++ rockchip,grf = <&grf>;
++ #sound-dai-cells = <0>;
+ status = "disabled";
+
+ ports {
+- hdmi_in: port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ hdmi_in: port@0 {
++ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
++
+ hdmi_in_vopb: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vopb_out_hdmi>;
+ };
++
+ hdmi_in_vopl: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&vopl_out_hdmi>;
+ };
+ };
++
++ hdmi_out: port@1 {
++ reg = <1>;
++ };
+ };
+ };
+
+diff --git a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
+index 74f5a43d53db9..d58d4f5dc3173 100644
+--- a/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
++++ b/arch/arm64/boot/dts/qcom/qcm6490-idp.dts
+@@ -5,6 +5,7 @@
+
+ /dts-v1/;
+
++#include <dt-bindings/leds/common.h>
+ #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+ #include "sc7280.dtsi"
+ #include "pm7325.dtsi"
+@@ -415,6 +416,33 @@ vreg_bob_3p296: bob {
+ };
+ };
+
++&pm8350c_pwm {
++ status = "okay";
++
++ multi-led {
++ color = <LED_COLOR_ID_RGB>;
++ function = LED_FUNCTION_STATUS;
++
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ led@1 {
++ reg = <1>;
++ color = <LED_COLOR_ID_RED>;
++ };
++
++ led@2 {
++ reg = <2>;
++ color = <LED_COLOR_ID_GREEN>;
++ };
++
++ led@3 {
++ reg = <3>;
++ color = <LED_COLOR_ID_BLUE>;
++ };
++ };
++};
++
+ &qupv3_id_0 {
+ status = "okay";
+ };
+diff --git a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
+index ae1632182d7c1..ac4579119d3ba 100644
+--- a/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
++++ b/arch/arm64/boot/dts/qcom/qcs6490-rb3gen2.dts
+@@ -413,6 +413,23 @@ vreg_bob_3p296: bob {
+ };
+ };
+
++&gcc {
++ protected-clocks = <GCC_CFG_NOC_LPASS_CLK>,
++ <GCC_MSS_CFG_AHB_CLK>,
++ <GCC_MSS_GPLL0_MAIN_DIV_CLK_SRC>,
++ <GCC_MSS_OFFLINE_AXI_CLK>,
++ <GCC_MSS_Q6SS_BOOT_CLK_SRC>,
++ <GCC_MSS_Q6_MEMNOC_AXI_CLK>,
++ <GCC_MSS_SNOC_AXI_CLK>,
++ <GCC_QSPI_CNOC_PERIPH_AHB_CLK>,
++ <GCC_QSPI_CORE_CLK>,
++ <GCC_QSPI_CORE_CLK_SRC>,
++ <GCC_SEC_CTRL_CLK_SRC>,
++ <GCC_WPSS_AHB_BDG_MST_CLK>,
++ <GCC_WPSS_AHB_CLK>,
++ <GCC_WPSS_RSCP_CLK>;
++};
++
+ &qupv3_id_0 {
+ status = "okay";
+ };
+diff --git a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
+index 64b2ab2862793..6e9dd0312adc5 100644
+--- a/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
++++ b/arch/arm64/boot/dts/qcom/qrb2210-rb1.dts
+@@ -177,6 +177,24 @@ vph_pwr: regulator-vph-pwr {
+ };
+ };
+
++&CPU_PD0 {
++ /delete-property/ power-domains;
++};
++
++&CPU_PD1 {
++ /delete-property/ power-domains;
++};
++
++&CPU_PD2 {
++ /delete-property/ power-domains;
++};
++
++&CPU_PD3 {
++ /delete-property/ power-domains;
++};
++
++/delete-node/ &CLUSTER_PD;
++
+ &gpi_dma0 {
+ status = "okay";
+ };
+diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+index 7b4c15c4a9c31..b6f045069ee2f 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+@@ -744,11 +744,20 @@ hdmi: hdmi@ff3c0000 {
+ status = "disabled";
+
+ ports {
+- hdmi_in: port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ hdmi_in: port@0 {
++ reg = <0>;
++
+ hdmi_in_vop: endpoint {
+ remote-endpoint = <&vop_out_hdmi>;
+ };
+ };
++
++ hdmi_out: port@1 {
++ reg = <1>;
++ };
+ };
+ };
+
+diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+index 6e12c5a920cab..fe818a2700aa7 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+@@ -1956,6 +1956,7 @@ simple-audio-card,codec {
+ hdmi: hdmi@ff940000 {
+ compatible = "rockchip,rk3399-dw-hdmi";
+ reg = <0x0 0xff940000 0x0 0x20000>;
++ reg-io-width = <4>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru PCLK_HDMI_CTRL>,
+ <&cru SCLK_HDMI_SFR>,
+@@ -1964,13 +1965,16 @@ hdmi: hdmi@ff940000 {
+ <&cru PLL_VPLL>;
+ clock-names = "iahb", "isfr", "cec", "grf", "ref";
+ power-domains = <&power RK3399_PD_HDCP>;
+- reg-io-width = <4>;
+ rockchip,grf = <&grf>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+
+ ports {
+- hdmi_in: port {
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ hdmi_in: port@0 {
++ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+@@ -1983,6 +1987,10 @@ hdmi_in_vopl: endpoint@1 {
+ remote-endpoint = <&vopl_out_hdmi>;
+ };
+ };
++
++ hdmi_out: port@1 {
++ reg = <1>;
++ };
+ };
+ };
+
+diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
+index b1b8dd1608f7e..73ac5adb0b4c9 100644
+--- a/arch/x86/entry/vdso/Makefile
++++ b/arch/x86/entry/vdso/Makefile
+@@ -34,8 +34,13 @@ obj-y += vma.o extable.o
+ KASAN_SANITIZE_vma.o := y
+ UBSAN_SANITIZE_vma.o := y
+ KCSAN_SANITIZE_vma.o := y
+-OBJECT_FILES_NON_STANDARD_vma.o := n
+-OBJECT_FILES_NON_STANDARD_extable.o := n
++
++OBJECT_FILES_NON_STANDARD_extable.o := n
++OBJECT_FILES_NON_STANDARD_vdso-image-32.o := n
++OBJECT_FILES_NON_STANDARD_vdso-image-x32.o := n
++OBJECT_FILES_NON_STANDARD_vdso-image-64.o := n
++OBJECT_FILES_NON_STANDARD_vdso32-setup.o := n
++OBJECT_FILES_NON_STANDARD_vma.o := n
+
+ # vDSO images to build
+ vdso_img-$(VDSO64-y) += 64
+@@ -43,7 +48,6 @@ vdso_img-$(VDSOX32-y) += x32
+ vdso_img-$(VDSO32-y) += 32
+
+ obj-$(VDSO32-y) += vdso32-setup.o
+-OBJECT_FILES_NON_STANDARD_vdso32-setup.o := n
+
+ vobjs := $(foreach F,$(vobjs-y),$(obj)/$F)
+ vobjs32 := $(foreach F,$(vobjs32-y),$(obj)/$F)
+diff --git a/arch/x86/events/amd/lbr.c b/arch/x86/events/amd/lbr.c
+index eb31f850841a8..4a1e600314d5d 100644
+--- a/arch/x86/events/amd/lbr.c
++++ b/arch/x86/events/amd/lbr.c
+@@ -173,9 +173,11 @@ void amd_pmu_lbr_read(void)
+
+ /*
+ * Check if a branch has been logged; if valid = 0, spec = 0
+- * then no branch was recorded
++ * then no branch was recorded; if reserved = 1 then an
++ * erroneous branch was recorded (see Erratum 1452)
+ */
+- if (!entry.to.split.valid && !entry.to.split.spec)
++ if ((!entry.to.split.valid && !entry.to.split.spec) ||
++ entry.to.split.reserved)
+ continue;
+
+ perf_clear_branch_entry_bitfields(br + out);
+diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h
+index a9088250770f2..64fbd2dbc5b76 100644
+--- a/arch/x86/include/asm/xen/hypervisor.h
++++ b/arch/x86/include/asm/xen/hypervisor.h
+@@ -62,6 +62,11 @@ void xen_arch_unregister_cpu(int num);
+ #ifdef CONFIG_PVH
+ void __init xen_pvh_init(struct boot_params *boot_params);
+ void __init mem_map_via_hcall(struct boot_params *boot_params_p);
++#ifdef CONFIG_XEN_PVH
++void __init xen_reserve_extra_memory(struct boot_params *bootp);
++#else
++static inline void xen_reserve_extra_memory(struct boot_params *bootp) { }
++#endif
+ #endif
+
+ /* Lazy mode for batching updates / context switch */
+diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
+index f347c20247d30..b33afb240601b 100644
+--- a/arch/x86/pci/fixup.c
++++ b/arch/x86/pci/fixup.c
+@@ -907,6 +907,54 @@ static void chromeos_fixup_apl_pci_l1ss_capability(struct pci_dev *dev)
+ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x5ad6, chromeos_save_apl_pci_l1ss_capability);
+ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, 0x5ad6, chromeos_fixup_apl_pci_l1ss_capability);
+
++/*
++ * Disable D3cold on Asus B1400 PCI-NVMe bridge
++ *
++ * On this platform with VMD off, the NVMe device cannot successfully power
++ * back on from D3cold. This appears to be an untested transition by the
++ * vendor: Windows leaves the NVMe and parent bridge in D0 during suspend.
++ *
++ * We disable D3cold on the parent bridge for simplicity, and the fact that
++ * both parent bridge and NVMe device share the same power resource.
++ *
++ * This is only needed on BIOS versions before 308; the newer versions flip
++ * StorageD3Enable from 1 to 0.
++ */
++static const struct dmi_system_id asus_nvme_broken_d3cold_table[] = {
++ {
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++ DMI_MATCH(DMI_BIOS_VERSION, "B1400CEAE.304"),
++ },
++ },
++ {
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++ DMI_MATCH(DMI_BIOS_VERSION, "B1400CEAE.305"),
++ },
++ },
++ {
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++ DMI_MATCH(DMI_BIOS_VERSION, "B1400CEAE.306"),
++ },
++ },
++ {
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++ DMI_MATCH(DMI_BIOS_VERSION, "B1400CEAE.307"),
++ },
++ },
++ {}
++};
++
++static void asus_disable_nvme_d3cold(struct pci_dev *pdev)
++{
++ if (dmi_check_system(asus_nvme_broken_d3cold_table) > 0)
++ pci_d3cold_disable(pdev);
++}
++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x9a09, asus_disable_nvme_d3cold);
++
+ #ifdef CONFIG_SUSPEND
+ /*
+ * Root Ports on some AMD SoCs advertise PME_Support for D3hot and D3cold, but
+diff --git a/arch/x86/platform/pvh/enlighten.c b/arch/x86/platform/pvh/enlighten.c
+index 00a92cb2c8147..a12117f3d4de7 100644
+--- a/arch/x86/platform/pvh/enlighten.c
++++ b/arch/x86/platform/pvh/enlighten.c
+@@ -74,6 +74,9 @@ static void __init init_pvh_bootparams(bool xen_guest)
+ } else
+ xen_raw_printk("Warning: Can fit ISA range into e820\n");
+
++ if (xen_guest)
++ xen_reserve_extra_memory(&pvh_bootparams);
++
+ pvh_bootparams.hdr.cmd_line_ptr =
+ pvh_start_info.cmdline_paddr;
+
+diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
+index 3c61bb98c10e2..a01ca255b0c64 100644
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -6,6 +6,7 @@
+ #include <linux/console.h>
+ #include <linux/cpu.h>
+ #include <linux/kexec.h>
++#include <linux/memblock.h>
+ #include <linux/slab.h>
+ #include <linux/panic_notifier.h>
+
+@@ -350,3 +351,34 @@ void xen_arch_unregister_cpu(int num)
+ }
+ EXPORT_SYMBOL(xen_arch_unregister_cpu);
+ #endif
++
++/* Amount of extra memory space we add to the e820 ranges */
++struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
++
++void __init xen_add_extra_mem(unsigned long start_pfn, unsigned long n_pfns)
++{
++ unsigned int i;
++
++ /*
++ * No need to check for zero size, should happen rarely and will only
++ * write a new entry regarded to be unused due to zero size.
++ */
++ for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) {
++ /* Add new region. */
++ if (xen_extra_mem[i].n_pfns == 0) {
++ xen_extra_mem[i].start_pfn = start_pfn;
++ xen_extra_mem[i].n_pfns = n_pfns;
++ break;
++ }
++ /* Append to existing region. */
++ if (xen_extra_mem[i].start_pfn + xen_extra_mem[i].n_pfns ==
++ start_pfn) {
++ xen_extra_mem[i].n_pfns += n_pfns;
++ break;
++ }
++ }
++ if (i == XEN_EXTRA_MEM_MAX_REGIONS)
++ printk(KERN_WARNING "Warning: not enough extra memory regions\n");
++
++ memblock_reserve(PFN_PHYS(start_pfn), PFN_PHYS(n_pfns));
++}
+diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c
+index ada3868c02c23..c28f073c1df52 100644
+--- a/arch/x86/xen/enlighten_pvh.c
++++ b/arch/x86/xen/enlighten_pvh.c
+@@ -1,6 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0
+ #include <linux/acpi.h>
+ #include <linux/export.h>
++#include <linux/mm.h>
+
+ #include <xen/hvc-console.h>
+
+@@ -72,3 +73,70 @@ void __init mem_map_via_hcall(struct boot_params *boot_params_p)
+ }
+ boot_params_p->e820_entries = memmap.nr_entries;
+ }
++
++/*
++ * Reserve e820 UNUSABLE regions to inflate the memory balloon.
++ *
++ * On PVH dom0 the host memory map is used, RAM regions available to dom0 are
++ * located as the same place as in the native memory map, but since dom0 gets
++ * less memory than the total amount of host RAM the ranges that can't be
++ * populated are converted from RAM -> UNUSABLE. Use such regions (up to the
++ * ratio signaled in EXTRA_MEM_RATIO) in order to inflate the balloon driver at
++ * boot. Doing so prevents the guest (even if just temporary) from using holes
++ * in the memory map in order to map grants or foreign addresses, and
++ * hopefully limits the risk of a clash with a device MMIO region. Ideally the
++ * hypervisor should notify us which memory ranges are suitable for creating
++ * foreign mappings, but that's not yet implemented.
++ */
++void __init xen_reserve_extra_memory(struct boot_params *bootp)
++{
++ unsigned int i, ram_pages = 0, extra_pages;
++
++ for (i = 0; i < bootp->e820_entries; i++) {
++ struct boot_e820_entry *e = &bootp->e820_table[i];
++
++ if (e->type != E820_TYPE_RAM)
++ continue;
++ ram_pages += PFN_DOWN(e->addr + e->size) - PFN_UP(e->addr);
++ }
++
++ /* Max amount of extra memory. */
++ extra_pages = EXTRA_MEM_RATIO * ram_pages;
++
++ /*
++ * Convert UNUSABLE ranges to RAM and reserve them for foreign mapping
++ * purposes.
++ */
++ for (i = 0; i < bootp->e820_entries && extra_pages; i++) {
++ struct boot_e820_entry *e = &bootp->e820_table[i];
++ unsigned long pages;
++
++ if (e->type != E820_TYPE_UNUSABLE)
++ continue;
++
++ pages = min(extra_pages,
++ PFN_DOWN(e->addr + e->size) - PFN_UP(e->addr));
++
++ if (pages != (PFN_DOWN(e->addr + e->size) - PFN_UP(e->addr))) {
++ struct boot_e820_entry *next;
++
++ if (bootp->e820_entries ==
++ ARRAY_SIZE(bootp->e820_table))
++ /* No space left to split - skip region. */
++ continue;
++
++ /* Split entry. */
++ next = e + 1;
++ memmove(next, e,
++ (bootp->e820_entries - i) * sizeof(*e));
++ bootp->e820_entries++;
++ next->addr = PAGE_ALIGN(e->addr) + PFN_PHYS(pages);
++ e->size = next->addr - e->addr;
++ next->size -= e->size;
++ }
++ e->type = E820_TYPE_RAM;
++ extra_pages -= pages;
++
++ xen_add_extra_mem(PFN_UP(e->addr), pages);
++ }
++}
+diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
+index b3e37961065a2..380591028cb8f 100644
+--- a/arch/x86/xen/setup.c
++++ b/arch/x86/xen/setup.c
+@@ -38,9 +38,6 @@
+
+ #define GB(x) ((uint64_t)(x) * 1024 * 1024 * 1024)
+
+-/* Amount of extra memory space we add to the e820 ranges */
+-struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
+-
+ /* Number of pages released from the initial allocation. */
+ unsigned long xen_released_pages;
+
+@@ -64,18 +61,6 @@ static struct {
+ } xen_remap_buf __initdata __aligned(PAGE_SIZE);
+ static unsigned long xen_remap_mfn __initdata = INVALID_P2M_ENTRY;
+
+-/*
+- * The maximum amount of extra memory compared to the base size. The
+- * main scaling factor is the size of struct page. At extreme ratios
+- * of base:extra, all the base memory can be filled with page
+- * structures for the extra memory, leaving no space for anything
+- * else.
+- *
+- * 10x seems like a reasonable balance between scaling flexibility and
+- * leaving a practically usable system.
+- */
+-#define EXTRA_MEM_RATIO (10)
+-
+ static bool xen_512gb_limit __initdata = IS_ENABLED(CONFIG_XEN_512GB);
+
+ static void __init xen_parse_512gb(void)
+@@ -96,35 +81,6 @@ static void __init xen_parse_512gb(void)
+ xen_512gb_limit = val;
+ }
+
+-static void __init xen_add_extra_mem(unsigned long start_pfn,
+- unsigned long n_pfns)
+-{
+- int i;
+-
+- /*
+- * No need to check for zero size, should happen rarely and will only
+- * write a new entry regarded to be unused due to zero size.
+- */
+- for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) {
+- /* Add new region. */
+- if (xen_extra_mem[i].n_pfns == 0) {
+- xen_extra_mem[i].start_pfn = start_pfn;
+- xen_extra_mem[i].n_pfns = n_pfns;
+- break;
+- }
+- /* Append to existing region. */
+- if (xen_extra_mem[i].start_pfn + xen_extra_mem[i].n_pfns ==
+- start_pfn) {
+- xen_extra_mem[i].n_pfns += n_pfns;
+- break;
+- }
+- }
+- if (i == XEN_EXTRA_MEM_MAX_REGIONS)
+- printk(KERN_WARNING "Warning: not enough extra memory regions\n");
+-
+- memblock_reserve(PFN_PHYS(start_pfn), PFN_PHYS(n_pfns));
+-}
+-
+ static void __init xen_del_extra_mem(unsigned long start_pfn,
+ unsigned long n_pfns)
+ {
+diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
+index a87ab36889e76..79cf93f2c92f1 100644
+--- a/arch/x86/xen/xen-ops.h
++++ b/arch/x86/xen/xen-ops.h
+@@ -163,4 +163,18 @@ void xen_hvm_post_suspend(int suspend_cancelled);
+ static inline void xen_hvm_post_suspend(int suspend_cancelled) {}
+ #endif
+
++/*
++ * The maximum amount of extra memory compared to the base size. The
++ * main scaling factor is the size of struct page. At extreme ratios
++ * of base:extra, all the base memory can be filled with page
++ * structures for the extra memory, leaving no space for anything
++ * else.
++ *
++ * 10x seems like a reasonable balance between scaling flexibility and
++ * leaving a practically usable system.
++ */
++#define EXTRA_MEM_RATIO (10)
++
++void xen_add_extra_mem(unsigned long start_pfn, unsigned long n_pfns);
++
+ #endif /* XEN_OPS_H */
+diff --git a/block/blk-stat.c b/block/blk-stat.c
+index 7ff76ae6c76a9..e42c263e53fb9 100644
+--- a/block/blk-stat.c
++++ b/block/blk-stat.c
+@@ -27,7 +27,7 @@ void blk_rq_stat_init(struct blk_rq_stat *stat)
+ /* src is a per-cpu stat, mean isn't initialized */
+ void blk_rq_stat_sum(struct blk_rq_stat *dst, struct blk_rq_stat *src)
+ {
+- if (!src->nr_samples)
++ if (dst->nr_samples + src->nr_samples <= dst->nr_samples)
+ return;
+
+ dst->min = min(dst->min, src->min);
+diff --git a/drivers/accel/habanalabs/common/habanalabs.h b/drivers/accel/habanalabs/common/habanalabs.h
+index 2a900c9941fee..41c7aac2ffcf9 100644
+--- a/drivers/accel/habanalabs/common/habanalabs.h
++++ b/drivers/accel/habanalabs/common/habanalabs.h
+@@ -2547,7 +2547,7 @@ struct hl_state_dump_specs {
+ * DEVICES
+ */
+
+-#define HL_STR_MAX 32
++#define HL_STR_MAX 64
+
+ #define HL_DEV_STS_MAX (HL_DEVICE_STATUS_LAST + 1)
+
+diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
+index c843feb02e980..b5193049d7b1b 100644
+--- a/drivers/acpi/resource.c
++++ b/drivers/acpi/resource.c
+@@ -489,6 +489,13 @@ static const struct dmi_system_id irq1_level_low_skip_override[] = {
+ DMI_MATCH(DMI_BOARD_NAME, "B2502CBA"),
+ },
+ },
++ {
++ /* Asus ExpertBook B2502FBA */
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++ DMI_MATCH(DMI_BOARD_NAME, "B2502FBA"),
++ },
++ },
+ {
+ /* Asus Vivobook E1504GA */
+ .matches = {
+diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
+index 808484d112097..728acfeb774d8 100644
+--- a/drivers/acpi/sleep.c
++++ b/drivers/acpi/sleep.c
+@@ -385,18 +385,6 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "20GGA00L00"),
+ },
+ },
+- /*
+- * ASUS B1400CEAE hangs on resume from suspend (see
+- * https://bugzilla.kernel.org/show_bug.cgi?id=215742).
+- */
+- {
+- .callback = init_default_s3,
+- .ident = "ASUS B1400CEAE",
+- .matches = {
+- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+- DMI_MATCH(DMI_PRODUCT_NAME, "ASUS EXPERTBOOK B1400CEAE"),
+- },
+- },
+ {},
+ };
+
+diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
+index bc65ebfcdf767..90c3d2eab9e99 100644
+--- a/drivers/acpi/x86/utils.c
++++ b/drivers/acpi/x86/utils.c
+@@ -428,7 +428,7 @@ bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev)
+ }
+ EXPORT_SYMBOL_GPL(acpi_quirk_skip_i2c_client_enumeration);
+
+-int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
++static int acpi_dmi_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
+ {
+ struct acpi_device *adev = ACPI_COMPANION(controller_parent);
+ const struct dmi_system_id *dmi_id;
+@@ -436,8 +436,6 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s
+ u64 uid;
+ int ret;
+
+- *skip = false;
+-
+ ret = acpi_dev_uid_to_integer(adev, &uid);
+ if (ret)
+ return 0;
+@@ -463,7 +461,6 @@ int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *s
+
+ return 0;
+ }
+-EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration);
+
+ bool acpi_quirk_skip_gpio_event_handlers(void)
+ {
+@@ -478,8 +475,41 @@ bool acpi_quirk_skip_gpio_event_handlers(void)
+ return (quirks & ACPI_QUIRK_SKIP_GPIO_EVENT_HANDLERS);
+ }
+ EXPORT_SYMBOL_GPL(acpi_quirk_skip_gpio_event_handlers);
++#else
++static int acpi_dmi_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
++{
++ return 0;
++}
+ #endif
+
++int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
++{
++ struct acpi_device *adev = ACPI_COMPANION(controller_parent);
++
++ *skip = false;
++
++ /*
++ * The DELL0501 ACPI HID represents an UART (CID is set to PNP0501) with
++ * a backlight-controller attached. There is no separate ACPI device with
++ * an UartSerialBusV2() resource to model the backlight-controller.
++ * Set skip to true so that the tty core creates a serdev ctrl device.
++ * The backlight driver will manually create the serdev client device.
++ */
++ if (acpi_dev_hid_match(adev, "DELL0501")) {
++ *skip = true;
++ /*
++ * Create a platform dev for dell-uart-backlight to bind to.
++ * This is a static device, so no need to store the result.
++ */
++ platform_device_register_simple("dell-uart-backlight", PLATFORM_DEVID_NONE,
++ NULL, 0);
++ return 0;
++ }
++
++ return acpi_dmi_skip_serdev_enumeration(controller_parent, skip);
++}
++EXPORT_SYMBOL_GPL(acpi_quirk_skip_serdev_enumeration);
++
+ /* Lists of PMIC ACPI HIDs with an (often better) native charger driver */
+ static const struct {
+ const char *hid;
+diff --git a/drivers/bluetooth/btintel.c b/drivers/bluetooth/btintel.c
+index cdc5c08824a0a..e532e2be1715d 100644
+--- a/drivers/bluetooth/btintel.c
++++ b/drivers/bluetooth/btintel.c
+@@ -441,7 +441,7 @@ int btintel_read_version(struct hci_dev *hdev, struct intel_version *ver)
+ return PTR_ERR(skb);
+ }
+
+- if (skb->len != sizeof(*ver)) {
++ if (!skb || skb->len != sizeof(*ver)) {
+ bt_dev_err(hdev, "Intel version event size mismatch");
+ kfree_skb(skb);
+ return -EILSEQ;
+diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
+index 285418dbb43f5..ac8ebccd35075 100644
+--- a/drivers/bluetooth/btmtk.c
++++ b/drivers/bluetooth/btmtk.c
+@@ -422,5 +422,6 @@ MODULE_LICENSE("GPL");
+ MODULE_FIRMWARE(FIRMWARE_MT7622);
+ MODULE_FIRMWARE(FIRMWARE_MT7663);
+ MODULE_FIRMWARE(FIRMWARE_MT7668);
++MODULE_FIRMWARE(FIRMWARE_MT7922);
+ MODULE_FIRMWARE(FIRMWARE_MT7961);
+ MODULE_FIRMWARE(FIRMWARE_MT7925);
+diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
+index 56f5502baadf9..cbcdb99a22e6d 100644
+--- a/drivers/bluetooth/btmtk.h
++++ b/drivers/bluetooth/btmtk.h
+@@ -4,6 +4,7 @@
+ #define FIRMWARE_MT7622 "mediatek/mt7622pr2h.bin"
+ #define FIRMWARE_MT7663 "mediatek/mt7663pr2h.bin"
+ #define FIRMWARE_MT7668 "mediatek/mt7668pr2h.bin"
++#define FIRMWARE_MT7922 "mediatek/BT_RAM_CODE_MT7922_1_1_hdr.bin"
+ #define FIRMWARE_MT7961 "mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin"
+ #define FIRMWARE_MT7925 "mediatek/mt7925/BT_RAM_CODE_MT7925_1_1_hdr.bin"
+
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index 6cb87d47ad7d5..f684108dc2f1c 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -4483,6 +4483,7 @@ static int btusb_probe(struct usb_interface *intf,
+ set_bit(HCI_QUIRK_BROKEN_READ_TRANSMIT_POWER, &hdev->quirks);
+ set_bit(HCI_QUIRK_BROKEN_SET_RPA_TIMEOUT, &hdev->quirks);
+ set_bit(HCI_QUIRK_BROKEN_EXT_SCAN, &hdev->quirks);
++ set_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks);
+ }
+
+ if (!reset)
+diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c
+index 65ceac1837f9a..8e5ec1a409b80 100644
+--- a/drivers/bus/mhi/host/init.c
++++ b/drivers/bus/mhi/host/init.c
+@@ -62,6 +62,7 @@ static const char * const mhi_pm_state_str[] = {
+ [MHI_PM_STATE_FW_DL_ERR] = "Firmware Download Error",
+ [MHI_PM_STATE_SYS_ERR_DETECT] = "SYS ERROR Detect",
+ [MHI_PM_STATE_SYS_ERR_PROCESS] = "SYS ERROR Process",
++ [MHI_PM_STATE_SYS_ERR_FAIL] = "SYS ERROR Failure",
+ [MHI_PM_STATE_SHUTDOWN_PROCESS] = "SHUTDOWN Process",
+ [MHI_PM_STATE_LD_ERR_FATAL_DETECT] = "Linkdown or Error Fatal Detect",
+ };
+diff --git a/drivers/bus/mhi/host/internal.h b/drivers/bus/mhi/host/internal.h
+index 30ac415a3000f..4b6deea17bcd2 100644
+--- a/drivers/bus/mhi/host/internal.h
++++ b/drivers/bus/mhi/host/internal.h
+@@ -88,6 +88,7 @@ enum mhi_pm_state {
+ MHI_PM_STATE_FW_DL_ERR,
+ MHI_PM_STATE_SYS_ERR_DETECT,
+ MHI_PM_STATE_SYS_ERR_PROCESS,
++ MHI_PM_STATE_SYS_ERR_FAIL,
+ MHI_PM_STATE_SHUTDOWN_PROCESS,
+ MHI_PM_STATE_LD_ERR_FATAL_DETECT,
+ MHI_PM_STATE_MAX
+@@ -104,14 +105,16 @@ enum mhi_pm_state {
+ #define MHI_PM_FW_DL_ERR BIT(7)
+ #define MHI_PM_SYS_ERR_DETECT BIT(8)
+ #define MHI_PM_SYS_ERR_PROCESS BIT(9)
+-#define MHI_PM_SHUTDOWN_PROCESS BIT(10)
++#define MHI_PM_SYS_ERR_FAIL BIT(10)
++#define MHI_PM_SHUTDOWN_PROCESS BIT(11)
+ /* link not accessible */
+-#define MHI_PM_LD_ERR_FATAL_DETECT BIT(11)
++#define MHI_PM_LD_ERR_FATAL_DETECT BIT(12)
+
+ #define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \
+ MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \
+ MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \
+- MHI_PM_SHUTDOWN_PROCESS | MHI_PM_FW_DL_ERR)))
++ MHI_PM_SYS_ERR_FAIL | MHI_PM_SHUTDOWN_PROCESS | \
++ MHI_PM_FW_DL_ERR)))
+ #define MHI_PM_IN_ERROR_STATE(pm_state) (pm_state >= MHI_PM_FW_DL_ERR)
+ #define MHI_PM_IN_FATAL_STATE(pm_state) (pm_state == MHI_PM_LD_ERR_FATAL_DETECT)
+ #define MHI_DB_ACCESS_VALID(mhi_cntrl) (mhi_cntrl->pm_state & mhi_cntrl->db_access)
+diff --git a/drivers/bus/mhi/host/pm.c b/drivers/bus/mhi/host/pm.c
+index a2f2feef14768..d0d033ce9984b 100644
+--- a/drivers/bus/mhi/host/pm.c
++++ b/drivers/bus/mhi/host/pm.c
+@@ -36,7 +36,10 @@
+ * M0 <--> M0
+ * M0 -> FW_DL_ERR
+ * M0 -> M3_ENTER -> M3 -> M3_EXIT --> M0
+- * L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS --> POR
++ * L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS
++ * SYS_ERR_PROCESS -> SYS_ERR_FAIL
++ * SYS_ERR_FAIL -> SYS_ERR_DETECT
++ * SYS_ERR_PROCESS --> POR
+ * L2: SHUTDOWN_PROCESS -> LD_ERR_FATAL_DETECT
+ * SHUTDOWN_PROCESS -> DISABLE
+ * L3: LD_ERR_FATAL_DETECT <--> LD_ERR_FATAL_DETECT
+@@ -93,7 +96,12 @@ static const struct mhi_pm_transitions dev_state_transitions[] = {
+ },
+ {
+ MHI_PM_SYS_ERR_PROCESS,
+- MHI_PM_POR | MHI_PM_SHUTDOWN_PROCESS |
++ MHI_PM_POR | MHI_PM_SYS_ERR_FAIL | MHI_PM_SHUTDOWN_PROCESS |
++ MHI_PM_LD_ERR_FATAL_DETECT
++ },
++ {
++ MHI_PM_SYS_ERR_FAIL,
++ MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS |
+ MHI_PM_LD_ERR_FATAL_DETECT
+ },
+ /* L2 States */
+@@ -629,7 +637,13 @@ static void mhi_pm_sys_error_transition(struct mhi_controller *mhi_cntrl)
+ !in_reset, timeout);
+ if (!ret || in_reset) {
+ dev_err(dev, "Device failed to exit MHI Reset state\n");
+- goto exit_sys_error_transition;
++ write_lock_irq(&mhi_cntrl->pm_lock);
++ cur_state = mhi_tryset_pm_state(mhi_cntrl,
++ MHI_PM_SYS_ERR_FAIL);
++ write_unlock_irq(&mhi_cntrl->pm_lock);
++ /* Shutdown may have occurred, otherwise cleanup now */
++ if (cur_state != MHI_PM_SYS_ERR_FAIL)
++ goto exit_sys_error_transition;
+ }
+
+ /*
+diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
+index 7d570b44777ac..3c2c955fbbbd6 100644
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -1576,7 +1576,8 @@ static int cpufreq_online(unsigned int cpu)
+ if (cpufreq_driver->ready)
+ cpufreq_driver->ready(policy);
+
+- if (cpufreq_thermal_control_enabled(cpufreq_driver))
++ /* Register cpufreq cooling only for a new policy */
++ if (new_policy && cpufreq_thermal_control_enabled(cpufreq_driver))
+ policy->cdev = of_cpufreq_cooling_register(policy);
+
+ pr_debug("initialization complete\n");
+@@ -1660,11 +1661,6 @@ static void __cpufreq_offline(unsigned int cpu, struct cpufreq_policy *policy)
+ else
+ policy->last_policy = policy->policy;
+
+- if (cpufreq_thermal_control_enabled(cpufreq_driver)) {
+- cpufreq_cooling_unregister(policy->cdev);
+- policy->cdev = NULL;
+- }
+-
+ if (has_target())
+ cpufreq_exit_governor(policy);
+
+@@ -1725,6 +1721,15 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
+ return;
+ }
+
++ /*
++ * Unregister cpufreq cooling once all the CPUs of the policy are
++ * removed.
++ */
++ if (cpufreq_thermal_control_enabled(cpufreq_driver)) {
++ cpufreq_cooling_unregister(policy->cdev);
++ policy->cdev = NULL;
++ }
++
+ /* We did light-weight exit earlier, do full tear down now */
+ if (cpufreq_driver->offline)
+ cpufreq_driver->exit(policy);
+diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
+index d9cda7f6ccb98..cf5873cc45dc8 100644
+--- a/drivers/cpuidle/driver.c
++++ b/drivers/cpuidle/driver.c
+@@ -16,6 +16,7 @@
+ #include <linux/cpumask.h>
+ #include <linux/tick.h>
+ #include <linux/cpu.h>
++#include <linux/math64.h>
+
+ #include "cpuidle.h"
+
+@@ -187,7 +188,7 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv)
+ s->target_residency = div_u64(s->target_residency_ns, NSEC_PER_USEC);
+
+ if (s->exit_latency > 0)
+- s->exit_latency_ns = s->exit_latency * NSEC_PER_USEC;
++ s->exit_latency_ns = mul_u32_u32(s->exit_latency, NSEC_PER_USEC);
+ else if (s->exit_latency_ns < 0)
+ s->exit_latency_ns = 0;
+ else
+diff --git a/drivers/crypto/intel/iaa/iaa_crypto_main.c b/drivers/crypto/intel/iaa/iaa_crypto_main.c
+index aa65c1791ce76..64a2e87a55b3c 100644
+--- a/drivers/crypto/intel/iaa/iaa_crypto_main.c
++++ b/drivers/crypto/intel/iaa/iaa_crypto_main.c
+@@ -1328,7 +1328,7 @@ static int iaa_compress(struct crypto_tfm *tfm, struct acomp_req *req,
+
+ *compression_crc = idxd_desc->iax_completion->crc;
+
+- if (!ctx->async_mode)
++ if (!ctx->async_mode || disable_async)
+ idxd_free_desc(wq, idxd_desc);
+ out:
+ return ret;
+@@ -1574,7 +1574,7 @@ static int iaa_decompress(struct crypto_tfm *tfm, struct acomp_req *req,
+
+ *dlen = req->dlen;
+
+- if (!ctx->async_mode)
++ if (!ctx->async_mode || disable_async)
+ idxd_free_desc(wq, idxd_desc);
+
+ /* Update stats */
+diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c
+index bbcdd9fed3fb6..4221fed70ad48 100644
+--- a/drivers/firmware/tegra/bpmp-debugfs.c
++++ b/drivers/firmware/tegra/bpmp-debugfs.c
+@@ -77,7 +77,7 @@ static const char *get_filename(struct tegra_bpmp *bpmp,
+
+ root_path_buf = kzalloc(root_path_buf_len, GFP_KERNEL);
+ if (!root_path_buf)
+- goto out;
++ return NULL;
+
+ root_path = dentry_path(bpmp->debugfs_mirror, root_path_buf,
+ root_path_buf_len);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+index 41db030ddc4ee..131983ed43465 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+@@ -146,7 +146,7 @@ int amdgpu_amdkfd_drm_client_create(struct amdgpu_device *adev)
+ {
+ int ret;
+
+- if (!adev->kfd.init_complete)
++ if (!adev->kfd.init_complete || adev->kfd.client.dev)
+ return 0;
+
+ ret = drm_client_init(&adev->ddev, &adev->kfd.client, "kfd",
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index 1fbaf7b81d69a..d0afb9ba3789c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -6109,6 +6109,20 @@ pci_ers_result_t amdgpu_pci_slot_reset(struct pci_dev *pdev)
+ struct amdgpu_reset_context reset_context;
+ u32 memsize;
+ struct list_head device_list;
++ struct amdgpu_hive_info *hive;
++ int hive_ras_recovery = 0;
++ struct amdgpu_ras *ras;
++
++ /* PCI error slot reset should be skipped During RAS recovery */
++ hive = amdgpu_get_xgmi_hive(adev);
++ if (hive) {
++ hive_ras_recovery = atomic_read(&hive->ras_recovery);
++ amdgpu_put_xgmi_hive(hive);
++ }
++ ras = amdgpu_ras_get_context(adev);
++ if ((amdgpu_ip_version(adev, GC_HWIP, 0) == IP_VERSION(9, 4, 3)) &&
++ ras && (atomic_read(&ras->in_recovery) || hive_ras_recovery))
++ return PCI_ERS_RESULT_RECOVERED;
+
+ DRM_INFO("PCI error: slot reset callback!!\n");
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+index 586f4d03039df..64b1bb2404242 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -2451,8 +2451,11 @@ static void amdgpu_drv_delayed_reset_work_handler(struct work_struct *work)
+ }
+ for (i = 0; i < mgpu_info.num_dgpu; i++) {
+ adev = mgpu_info.gpu_ins[i].adev;
+- if (!adev->kfd.init_complete)
++ if (!adev->kfd.init_complete) {
++ kgd2kfd_init_zone_device(adev);
+ amdgpu_amdkfd_device_init(adev);
++ amdgpu_amdkfd_drm_client_create(adev);
++ }
+ amdgpu_ttm_set_buffer_funcs_status(adev, true);
+ }
+ }
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+index 80e90fdef291d..08da993df1480 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+@@ -778,8 +778,8 @@ static int kfd_ioctl_get_process_apertures_new(struct file *filp,
+ * nodes, but not more than args->num_of_nodes as that is
+ * the amount of memory allocated by user
+ */
+- pa = kzalloc((sizeof(struct kfd_process_device_apertures) *
+- args->num_of_nodes), GFP_KERNEL);
++ pa = kcalloc(args->num_of_nodes, sizeof(struct kfd_process_device_apertures),
++ GFP_KERNEL);
+ if (!pa)
+ return -ENOMEM;
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
+index f1342314f7f43..fc60fa5814fbe 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc.h
++++ b/drivers/gpu/drm/amd/display/dc/dc.h
+@@ -987,6 +987,7 @@ struct dc_debug_options {
+ bool psp_disabled_wa;
+ unsigned int ips2_eval_delay_us;
+ unsigned int ips2_entry_delay_us;
++ bool disable_dmub_reallow_idle;
+ bool disable_timeout;
+ bool disable_extblankadj;
+ unsigned int static_screen_wait_frames;
+diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+index 363d522603a21..9084b320849a6 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
++++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+@@ -1364,7 +1364,7 @@ bool dc_wake_and_execute_dmub_cmd_list(const struct dc_context *ctx, unsigned in
+ else
+ result = dm_execute_dmub_cmd(ctx, cmd, wait_type);
+
+- if (result && reallow_idle)
++ if (result && reallow_idle && !ctx->dc->debug.disable_dmub_reallow_idle)
+ dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, true);
+
+ return result;
+@@ -1413,7 +1413,7 @@ bool dc_wake_and_execute_gpint(const struct dc_context *ctx, enum dmub_gpint_com
+
+ result = dc_dmub_execute_gpint(ctx, command_code, param, response, wait_type);
+
+- if (result && reallow_idle)
++ if (result && reallow_idle && !ctx->dc->debug.disable_dmub_reallow_idle)
+ dc_dmub_srv_apply_idle_power_optimizations(ctx->dc, true);
+
+ return result;
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+index a0a65e0991041..ba76dd4a2ce29 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+@@ -2760,7 +2760,7 @@ static int build_synthetic_soc_states(bool disable_dc_mode_overwrite, struct clk
+ struct _vcs_dpi_voltage_scaling_st entry = {0};
+ struct clk_limit_table_entry max_clk_data = {0};
+
+- unsigned int min_dcfclk_mhz = 199, min_fclk_mhz = 299;
++ unsigned int min_dcfclk_mhz = 399, min_fclk_mhz = 599;
+
+ static const unsigned int num_dcfclk_stas = 5;
+ unsigned int dcfclk_sta_targets[DC__VOLTAGE_STATES] = {199, 615, 906, 1324, 1564};
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+index 04d230aa8861f..78c315541f031 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+@@ -782,6 +782,7 @@ static const struct dc_debug_options debug_defaults_drv = {
+ .psp_disabled_wa = true,
+ .ips2_eval_delay_us = 2000,
+ .ips2_entry_delay_us = 800,
++ .disable_dmub_reallow_idle = true,
+ .static_screen_wait_frames = 2,
+ };
+
+diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h b/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h
+index 5960dd760e91c..8ce6c22e5d041 100644
+--- a/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h
++++ b/drivers/gpu/drm/amd/display/modules/inc/mod_stats.h
+@@ -57,10 +57,10 @@ void mod_stats_update_event(struct mod_stats *mod_stats,
+ unsigned int length);
+
+ void mod_stats_update_flip(struct mod_stats *mod_stats,
+- unsigned long timestamp_in_ns);
++ unsigned long long timestamp_in_ns);
+
+ void mod_stats_update_vupdate(struct mod_stats *mod_stats,
+- unsigned long timestamp_in_ns);
++ unsigned long long timestamp_in_ns);
+
+ void mod_stats_update_freesync(struct mod_stats *mod_stats,
+ unsigned int v_total_min,
+diff --git a/drivers/gpu/drm/ci/gitlab-ci.yml b/drivers/gpu/drm/ci/gitlab-ci.yml
+index dac92cc2777cc..084e3ff8e3f42 100644
+--- a/drivers/gpu/drm/ci/gitlab-ci.yml
++++ b/drivers/gpu/drm/ci/gitlab-ci.yml
+@@ -1,6 +1,6 @@
+ variables:
+ DRM_CI_PROJECT_PATH: &drm-ci-project-path mesa/mesa
+- DRM_CI_COMMIT_SHA: &drm-ci-commit-sha edfbf74df1d4d6ce54ffe24566108be0e1a98c3d
++ DRM_CI_COMMIT_SHA: &drm-ci-commit-sha 9d162de9a05155e1c4041857a5848842749164cf
+
+ UPSTREAM_REPO: git://anongit.freedesktop.org/drm/drm
+ TARGET_BRANCH: drm-next
+@@ -25,7 +25,9 @@ variables:
+ # per-job artifact storage on MinIO
+ JOB_ARTIFACTS_BASE: ${PIPELINE_ARTIFACTS_BASE}/${CI_JOB_ID}
+ # default kernel for rootfs before injecting the current kernel tree
+- KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/gfx-ci/linux/v6.4.12-for-mesa-ci-f6b4ad45f48d
++ KERNEL_REPO: "gfx-ci/linux"
++ KERNEL_TAG: "v6.6.4-for-mesa-ci-e4f4c500f7fb"
++ KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/${KERNEL_REPO}/${KERNEL_TAG}
+ LAVA_TAGS: subset-1-gfx
+ LAVA_JOB_PRIORITY: 30
+
+@@ -133,6 +135,11 @@ stages:
+ - if: &is-pre-merge-for-marge '$GITLAB_USER_LOGIN == "marge-bot" && $CI_PIPELINE_SOURCE == "merge_request_event"'
+ when: on_success
+
++.never-post-merge-rules:
++ rules:
++ - if: *is-post-merge
++ when: never
++
+ # Rule to filter for only scheduled pipelines.
+ .scheduled_pipeline-rules:
+ rules:
+@@ -150,6 +157,7 @@ stages:
+ .build-rules:
+ rules:
+ - !reference [.no_scheduled_pipelines-rules, rules]
++ - !reference [.never-post-merge-rules, rules]
+ # Run automatically once all dependency jobs have passed
+ - when: on_success
+
+@@ -157,6 +165,7 @@ stages:
+ .container+build-rules:
+ rules:
+ - !reference [.no_scheduled_pipelines-rules, rules]
++ - !reference [.never-post-merge-rules, rules]
+ - when: manual
+
+ .ci-deqp-artifacts:
+@@ -175,6 +184,7 @@ stages:
+ .container-rules:
+ rules:
+ - !reference [.no_scheduled_pipelines-rules, rules]
++ - !reference [.never-post-merge-rules, rules]
+ # Run pipeline by default in the main project if any CI pipeline
+ # configuration files were changed, to ensure docker images are up to date
+ - if: *is-post-merge
+diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml
+index 5e1c727640c40..9faf76e55a56a 100644
+--- a/drivers/gpu/drm/ci/test.yml
++++ b/drivers/gpu/drm/ci/test.yml
+@@ -327,6 +327,7 @@ virtio_gpu:none:
+ GPU_VERSION: none
+ extends:
+ - .test-gl
++ - .test-rules
+ tags:
+ - kvm
+ script:
+diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c
+index f858dfedf2cfc..2c582020cb423 100644
+--- a/drivers/gpu/drm/drm_modeset_helper.c
++++ b/drivers/gpu/drm/drm_modeset_helper.c
+@@ -193,13 +193,22 @@ int drm_mode_config_helper_suspend(struct drm_device *dev)
+
+ if (!dev)
+ return 0;
++ /*
++ * Don't disable polling if it was never initialized
++ */
++ if (dev->mode_config.poll_enabled)
++ drm_kms_helper_poll_disable(dev);
+
+- drm_kms_helper_poll_disable(dev);
+ drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 1);
+ state = drm_atomic_helper_suspend(dev);
+ if (IS_ERR(state)) {
+ drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
+- drm_kms_helper_poll_enable(dev);
++ /*
++ * Don't enable polling if it was never initialized
++ */
++ if (dev->mode_config.poll_enabled)
++ drm_kms_helper_poll_enable(dev);
++
+ return PTR_ERR(state);
+ }
+
+@@ -239,7 +248,11 @@ int drm_mode_config_helper_resume(struct drm_device *dev)
+ dev->mode_config.suspend_state = NULL;
+
+ drm_fb_helper_set_suspend_unlocked(dev->fb_helper, 0);
+- drm_kms_helper_poll_enable(dev);
++ /*
++ * Don't enable polling if it is not initialized
++ */
++ if (dev->mode_config.poll_enabled)
++ drm_kms_helper_poll_enable(dev);
+
+ return ret;
+ }
+diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+index 3d92f66e550c3..aa93129c3397e 100644
+--- a/drivers/gpu/drm/drm_panel_orientation_quirks.c
++++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c
+@@ -117,6 +117,12 @@ static const struct drm_dmi_panel_orientation_data lcd1080x1920_leftside_up = {
+ .orientation = DRM_MODE_PANEL_ORIENTATION_LEFT_UP,
+ };
+
++static const struct drm_dmi_panel_orientation_data lcd1080x1920_rightside_up = {
++ .width = 1080,
++ .height = 1920,
++ .orientation = DRM_MODE_PANEL_ORIENTATION_RIGHT_UP,
++};
++
+ static const struct drm_dmi_panel_orientation_data lcd1200x1920_rightside_up = {
+ .width = 1200,
+ .height = 1920,
+@@ -279,6 +285,12 @@ static const struct dmi_system_id orientation_data[] = {
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1618-03")
+ },
+ .driver_data = (void *)&lcd720x1280_rightside_up,
++ }, { /* GPD Win Mini */
++ .matches = {
++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "GPD"),
++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "G1617-01")
++ },
++ .driver_data = (void *)&lcd1080x1920_rightside_up,
+ }, { /* I.T.Works TW891 */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "To be filled by O.E.M."),
+diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
+index 744cde9db246b..36433fa681f32 100644
+--- a/drivers/gpu/drm/drm_probe_helper.c
++++ b/drivers/gpu/drm/drm_probe_helper.c
+@@ -293,14 +293,17 @@ static void reschedule_output_poll_work(struct drm_device *dev)
+ * Drivers can call this helper from their device resume implementation. It is
+ * not an error to call this even when output polling isn't enabled.
+ *
++ * If device polling was never initialized before, this call will trigger a
++ * warning and return.
++ *
+ * Note that calls to enable and disable polling must be strictly ordered, which
+ * is automatically the case when they're only call from suspend/resume
+ * callbacks.
+ */
+ void drm_kms_helper_poll_enable(struct drm_device *dev)
+ {
+- if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll ||
+- dev->mode_config.poll_running)
++ if (drm_WARN_ON_ONCE(dev, !dev->mode_config.poll_enabled) ||
++ !drm_kms_helper_poll || dev->mode_config.poll_running)
+ return;
+
+ if (drm_kms_helper_enable_hpd(dev) ||
+@@ -626,8 +629,12 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
+ 0);
+ }
+
+- /* Re-enable polling in case the global poll config changed. */
+- drm_kms_helper_poll_enable(dev);
++ /*
++ * Re-enable polling in case the global poll config changed but polling
++ * is still initialized.
++ */
++ if (dev->mode_config.poll_enabled)
++ drm_kms_helper_poll_enable(dev);
+
+ if (connector->status == connector_status_disconnected) {
+ DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
+@@ -880,12 +887,18 @@ EXPORT_SYMBOL(drm_kms_helper_is_poll_worker);
+ * not an error to call this even when output polling isn't enabled or already
+ * disabled. Polling is re-enabled by calling drm_kms_helper_poll_enable().
+ *
++ * If however, the polling was never initialized, this call will trigger a
++ * warning and return
++ *
+ * Note that calls to enable and disable polling must be strictly ordered, which
+ * is automatically the case when they're only call from suspend/resume
+ * callbacks.
+ */
+ void drm_kms_helper_poll_disable(struct drm_device *dev)
+ {
++ if (drm_WARN_ON(dev, !dev->mode_config.poll_enabled))
++ return;
++
+ if (dev->mode_config.poll_running)
+ drm_kms_helper_disable_hpd(dev);
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c
+index 7bcbc4895ec22..271bfa038f5bc 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c
+@@ -25,6 +25,7 @@
+
+ #include <subdev/bios.h>
+ #include <subdev/bios/init.h>
++#include <subdev/gsp.h>
+
+ void
+ gm107_devinit_disable(struct nvkm_devinit *init)
+@@ -33,10 +34,13 @@ gm107_devinit_disable(struct nvkm_devinit *init)
+ u32 r021c00 = nvkm_rd32(device, 0x021c00);
+ u32 r021c04 = nvkm_rd32(device, 0x021c04);
+
+- if (r021c00 & 0x00000001)
+- nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0);
+- if (r021c00 & 0x00000004)
+- nvkm_subdev_disable(device, NVKM_ENGINE_CE, 2);
++ /* gsp only wants to enable/disable display */
++ if (!nvkm_gsp_rm(device->gsp)) {
++ if (r021c00 & 0x00000001)
++ nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0);
++ if (r021c00 & 0x00000004)
++ nvkm_subdev_disable(device, NVKM_ENGINE_CE, 2);
++ }
+ if (r021c04 & 0x00000001)
+ nvkm_subdev_disable(device, NVKM_ENGINE_DISP, 0);
+ }
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c
+index 11b4c9c274a1a..666eb93b1742c 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c
+@@ -41,6 +41,7 @@ r535_devinit_new(const struct nvkm_devinit_func *hw,
+
+ rm->dtor = r535_devinit_dtor;
+ rm->post = hw->post;
++ rm->disable = hw->disable;
+
+ ret = nv50_devinit_new_(rm, device, type, inst, pdevinit);
+ if (ret)
+diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
+index d493ee735c734..72fdab8adb088 100644
+--- a/drivers/gpu/drm/panel/panel-simple.c
++++ b/drivers/gpu/drm/panel/panel-simple.c
+@@ -1367,6 +1367,23 @@ static const struct drm_display_mode boe_bp101wx1_100_mode = {
+ .vtotal = 800 + 6 + 8 + 2,
+ };
+
++static const struct panel_desc boe_bp082wx1_100 = {
++ .modes = &boe_bp101wx1_100_mode,
++ .num_modes = 1,
++ .bpc = 8,
++ .size = {
++ .width = 177,
++ .height = 110,
++ },
++ .delay = {
++ .enable = 50,
++ .disable = 50,
++ },
++ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA,
++ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
++ .connector_type = DRM_MODE_CONNECTOR_LVDS,
++};
++
+ static const struct panel_desc boe_bp101wx1_100 = {
+ .modes = &boe_bp101wx1_100_mode,
+ .num_modes = 1,
+@@ -4345,6 +4362,9 @@ static const struct of_device_id platform_of_match[] = {
+ }, {
+ .compatible = "bananapi,s070wv20-ct16",
+ .data = &bananapi_s070wv20_ct16,
++ }, {
++ .compatible = "boe,bp082wx1-100",
++ .data = &boe_bp082wx1_100,
+ }, {
+ .compatible = "boe,bp101wx1-100",
+ .data = &boe_bp101wx1_100,
+diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
+index edf10618fe2b2..f95b0406ca995 100644
+--- a/drivers/gpu/drm/ttm/ttm_bo.c
++++ b/drivers/gpu/drm/ttm/ttm_bo.c
+@@ -770,7 +770,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
+ * This function may sleep while waiting for space to become available.
+ * Returns:
+ * -EBUSY: No space available (only if no_wait == 1).
+- * -ENOMEM: Could not allocate memory for the buffer object, either due to
++ * -ENOSPC: Could not allocate space for the buffer object, either due to
+ * fragmentation or concurrent allocators.
+ * -ERESTARTSYS: An interruptible sleep was interrupted by a signal.
+ */
+@@ -830,7 +830,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo,
+ goto error;
+ }
+
+- ret = -ENOMEM;
++ ret = -ENOSPC;
+ if (!type_found) {
+ pr_err(TTM_PFX "No compatible memory type found\n");
+ ret = -EINVAL;
+@@ -916,6 +916,9 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
+ return -EINVAL;
+
+ ret = ttm_bo_move_buffer(bo, placement, ctx);
++ /* For backward compatibility with userspace */
++ if (ret == -ENOSPC)
++ return -ENOMEM;
+ if (ret)
+ return ret;
+
+diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
+index 00e713faecd5a..5948e34f7f813 100644
+--- a/drivers/gpu/drm/vc4/vc4_plane.c
++++ b/drivers/gpu/drm/vc4/vc4_plane.c
+@@ -1505,9 +1505,6 @@ static int vc4_prepare_fb(struct drm_plane *plane,
+
+ drm_gem_plane_helper_prepare_fb(plane, state);
+
+- if (plane->state->fb == state->fb)
+- return 0;
+-
+ return vc4_bo_inc_usecnt(bo);
+ }
+
+@@ -1516,7 +1513,7 @@ static void vc4_cleanup_fb(struct drm_plane *plane,
+ {
+ struct vc4_bo *bo;
+
+- if (plane->state->fb == state->fb || !state->fb)
++ if (!state->fb)
+ return;
+
+ bo = to_vc4_bo(&drm_fb_dma_get_gem_obj(state->fb, 0)->base);
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index 828a5c022c640..175b6680087e0 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -430,6 +430,7 @@
+ #define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1 0x2BED
+ #define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2 0x2BEE
+ #define I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG 0x2D02
++#define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM 0x2F81
+
+ #define USB_VENDOR_ID_ELECOM 0x056e
+ #define USB_DEVICE_ID_ELECOM_BM084 0x0061
+diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
+index c8b20d44b1472..e03d300d2bac4 100644
+--- a/drivers/hid/hid-input.c
++++ b/drivers/hid/hid-input.c
+@@ -411,6 +411,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
+ HID_BATTERY_QUIRK_IGNORE },
+ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG),
+ HID_BATTERY_QUIRK_IGNORE },
++ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM),
++ HID_BATTERY_QUIRK_AVOID_QUERY },
+ {}
+ };
+
+diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
+index a7f6f3eafad7d..ae835000fd32a 100644
+--- a/drivers/i2c/busses/i2c-designware-core.h
++++ b/drivers/i2c/busses/i2c-designware-core.h
+@@ -318,7 +318,7 @@ struct dw_i2c_dev {
+ #define AMD_UCSI_INTR_EN 0xd
+
+ #define TXGBE_TX_FIFO_DEPTH 4
+-#define TXGBE_RX_FIFO_DEPTH 0
++#define TXGBE_RX_FIFO_DEPTH 1
+
+ struct i2c_dw_semaphore_callbacks {
+ int (*probe)(struct dw_i2c_dev *dev);
+diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
+index ff58058aeadca..bf0df6ee4f785 100644
+--- a/drivers/infiniband/core/cm.c
++++ b/drivers/infiniband/core/cm.c
+@@ -34,6 +34,7 @@ MODULE_AUTHOR("Sean Hefty");
+ MODULE_DESCRIPTION("InfiniBand CM");
+ MODULE_LICENSE("Dual BSD/GPL");
+
++#define CM_DESTROY_ID_WAIT_TIMEOUT 10000 /* msecs */
+ static const char * const ibcm_rej_reason_strs[] = {
+ [IB_CM_REJ_NO_QP] = "no QP",
+ [IB_CM_REJ_NO_EEC] = "no EEC",
+@@ -1025,10 +1026,20 @@ static void cm_reset_to_idle(struct cm_id_private *cm_id_priv)
+ }
+ }
+
++static noinline void cm_destroy_id_wait_timeout(struct ib_cm_id *cm_id)
++{
++ struct cm_id_private *cm_id_priv;
++
++ cm_id_priv = container_of(cm_id, struct cm_id_private, id);
++ pr_err("%s: cm_id=%p timed out. state=%d refcnt=%d\n", __func__,
++ cm_id, cm_id->state, refcount_read(&cm_id_priv->refcount));
++}
++
+ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
+ {
+ struct cm_id_private *cm_id_priv;
+ struct cm_work *work;
++ int ret;
+
+ cm_id_priv = container_of(cm_id, struct cm_id_private, id);
+ spin_lock_irq(&cm_id_priv->lock);
+@@ -1135,7 +1146,14 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
+
+ xa_erase(&cm.local_id_table, cm_local_id(cm_id->local_id));
+ cm_deref_id(cm_id_priv);
+- wait_for_completion(&cm_id_priv->comp);
++ do {
++ ret = wait_for_completion_timeout(&cm_id_priv->comp,
++ msecs_to_jiffies(
++ CM_DESTROY_ID_WAIT_TIMEOUT));
++ if (!ret) /* timeout happened */
++ cm_destroy_id_wait_timeout(cm_id);
++ } while (!ret);
++
+ while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
+ cm_free_work(work);
+
+diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
+index 14c828adebf78..1fad51b51b0e1 100644
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -366,6 +366,8 @@ static const struct xpad_device {
+ { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 },
+ { 0x24c6, 0xfafe, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
+ { 0x2563, 0x058d, "OneXPlayer Gamepad", 0, XTYPE_XBOX360 },
++ { 0x294b, 0x3303, "Snakebyte GAMEPAD BASE X", 0, XTYPE_XBOXONE },
++ { 0x294b, 0x3404, "Snakebyte GAMEPAD RGB X", 0, XTYPE_XBOXONE },
+ { 0x2dc8, 0x2000, "8BitDo Pro 2 Wired Controller fox Xbox", 0, XTYPE_XBOXONE },
+ { 0x2dc8, 0x3106, "8BitDo Pro 2 Wired Controller", 0, XTYPE_XBOX360 },
+ { 0x31e3, 0x1100, "Wooting One", 0, XTYPE_XBOX360 },
+@@ -507,6 +509,7 @@ static const struct usb_device_id xpad_table[] = {
+ XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA controllers */
+ XPAD_XBOX360_VENDOR(0x2563), /* OneXPlayer Gamepad */
+ XPAD_XBOX360_VENDOR(0x260d), /* Dareu H101 */
++ XPAD_XBOXONE_VENDOR(0x294b), /* Snakebyte */
+ XPAD_XBOX360_VENDOR(0x2c22), /* Qanba Controllers */
+ XPAD_XBOX360_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller */
+ XPAD_XBOXONE_VENDOR(0x2dc8), /* 8BitDo Pro 2 Wired Controller for Xbox */
+diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
+index 42eaebb3bf5cc..ef9ea295f9e03 100644
+--- a/drivers/input/rmi4/rmi_driver.c
++++ b/drivers/input/rmi4/rmi_driver.c
+@@ -1196,7 +1196,11 @@ static int rmi_driver_probe(struct device *dev)
+ }
+ rmi_driver_set_input_params(rmi_dev, data->input);
+ data->input->phys = devm_kasprintf(dev, GFP_KERNEL,
+- "%s/input0", dev_name(dev));
++ "%s/input0", dev_name(dev));
++ if (!data->input->phys) {
++ retval = -ENOMEM;
++ goto err;
++ }
+ }
+
+ retval = rmi_init_functions(data);
+diff --git a/drivers/input/touchscreen/imagis.c b/drivers/input/touchscreen/imagis.c
+index 07111ca244556..55ecebe981445 100644
+--- a/drivers/input/touchscreen/imagis.c
++++ b/drivers/input/touchscreen/imagis.c
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+
++#include <linux/bitfield.h>
+ #include <linux/bits.h>
+ #include <linux/delay.h>
+ #include <linux/i2c.h>
+@@ -23,12 +24,9 @@
+ #define IST3038C_I2C_RETRY_COUNT 3
+ #define IST3038C_MAX_FINGER_NUM 10
+ #define IST3038C_X_MASK GENMASK(23, 12)
+-#define IST3038C_X_SHIFT 12
+ #define IST3038C_Y_MASK GENMASK(11, 0)
+ #define IST3038C_AREA_MASK GENMASK(27, 24)
+-#define IST3038C_AREA_SHIFT 24
+ #define IST3038C_FINGER_COUNT_MASK GENMASK(15, 12)
+-#define IST3038C_FINGER_COUNT_SHIFT 12
+ #define IST3038C_FINGER_STATUS_MASK GENMASK(9, 0)
+
+ struct imagis_ts {
+@@ -92,8 +90,7 @@ static irqreturn_t imagis_interrupt(int irq, void *dev_id)
+ goto out;
+ }
+
+- finger_count = (intr_message & IST3038C_FINGER_COUNT_MASK) >>
+- IST3038C_FINGER_COUNT_SHIFT;
++ finger_count = FIELD_GET(IST3038C_FINGER_COUNT_MASK, intr_message);
+ if (finger_count > IST3038C_MAX_FINGER_NUM) {
+ dev_err(&ts->client->dev,
+ "finger count %d is more than maximum supported\n",
+@@ -101,7 +98,7 @@ static irqreturn_t imagis_interrupt(int irq, void *dev_id)
+ goto out;
+ }
+
+- finger_pressed = intr_message & IST3038C_FINGER_STATUS_MASK;
++ finger_pressed = FIELD_GET(IST3038C_FINGER_STATUS_MASK, intr_message);
+
+ for (i = 0; i < finger_count; i++) {
+ error = imagis_i2c_read_reg(ts,
+@@ -118,12 +115,11 @@ static irqreturn_t imagis_interrupt(int irq, void *dev_id)
+ input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
+ finger_pressed & BIT(i));
+ touchscreen_report_pos(ts->input_dev, &ts->prop,
+- (finger_status & IST3038C_X_MASK) >>
+- IST3038C_X_SHIFT,
+- finger_status & IST3038C_Y_MASK, 1);
++ FIELD_GET(IST3038C_X_MASK, finger_status),
++ FIELD_GET(IST3038C_Y_MASK, finger_status),
++ true);
+ input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+- (finger_status & IST3038C_AREA_MASK) >>
+- IST3038C_AREA_SHIFT);
++ FIELD_GET(IST3038C_AREA_MASK, finger_status));
+ }
+
+ input_mt_sync_frame(ts->input_dev);
+@@ -210,7 +206,7 @@ static int imagis_init_input_dev(struct imagis_ts *ts)
+
+ input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_X);
+ input_set_capability(input_dev, EV_ABS, ABS_MT_POSITION_Y);
+- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
++ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 16, 0, 0);
+
+ touchscreen_parse_properties(input_dev, true, &ts->prop);
+ if (!ts->prop.max_x || !ts->prop.max_y) {
+diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+index 0ffb1cf17e0b2..f3f2e47b6d488 100644
+--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
++++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+@@ -2398,8 +2398,6 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
+ return -EBUSY;
+ }
+
+- arm_smmu_detach_dev(master);
+-
+ mutex_lock(&smmu_domain->init_mutex);
+
+ if (!smmu_domain->smmu) {
+@@ -2414,6 +2412,16 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
+ if (ret)
+ return ret;
+
++ /*
++ * Prevent arm_smmu_share_asid() from trying to change the ASID
++ * of either the old or new domain while we are working on it.
++ * This allows the STE and the smmu_domain->devices list to
++ * be inconsistent during this routine.
++ */
++ mutex_lock(&arm_smmu_asid_lock);
++
++ arm_smmu_detach_dev(master);
++
+ master->domain = smmu_domain;
+
+ /*
+@@ -2439,13 +2447,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
+ }
+ }
+
+- /*
+- * Prevent SVA from concurrently modifying the CD or writing to
+- * the CD entry
+- */
+- mutex_lock(&arm_smmu_asid_lock);
+ ret = arm_smmu_write_ctx_desc(master, IOMMU_NO_PASID, &smmu_domain->cd);
+- mutex_unlock(&arm_smmu_asid_lock);
+ if (ret) {
+ master->domain = NULL;
+ goto out_list_del;
+@@ -2455,13 +2457,15 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
+ arm_smmu_install_ste_for_dev(master);
+
+ arm_smmu_enable_ats(master);
+- return 0;
++ goto out_unlock;
+
+ out_list_del:
+ spin_lock_irqsave(&smmu_domain->devices_lock, flags);
+ list_del(&master->domain_head);
+ spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
+
++out_unlock:
++ mutex_unlock(&arm_smmu_asid_lock);
+ return ret;
+ }
+
+diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
+index e4cf9d63e926d..364ce9e570182 100644
+--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
++++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
+@@ -757,7 +757,7 @@ static const struct video_device video_dev_template = {
+ /**
+ * vip_irq - interrupt routine
+ * @irq: Number of interrupt ( not used, correct number is assumed )
+- * @vip: local data structure containing all information
++ * @data: local data structure containing all information
+ *
+ * check for both frame interrupts set ( top and bottom ).
+ * check FIFO overflow, but limit number of log messages after open.
+@@ -767,8 +767,9 @@ static const struct video_device video_dev_template = {
+ *
+ * IRQ_HANDLED, interrupt done.
+ */
+-static irqreturn_t vip_irq(int irq, struct sta2x11_vip *vip)
++static irqreturn_t vip_irq(int irq, void *data)
+ {
++ struct sta2x11_vip *vip = data;
+ unsigned int status;
+
+ status = reg_read(vip, DVP_ITS);
+@@ -1053,9 +1054,7 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev,
+
+ spin_lock_init(&vip->slock);
+
+- ret = request_irq(pdev->irq,
+- (irq_handler_t) vip_irq,
+- IRQF_SHARED, KBUILD_MODNAME, vip);
++ ret = request_irq(pdev->irq, vip_irq, IRQF_SHARED, KBUILD_MODNAME, vip);
+ if (ret) {
+ dev_err(&pdev->dev, "request_irq failed\n");
+ ret = -ENODEV;
+diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c
+index 4c34344dc7dcb..d7027d600208f 100644
+--- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c
++++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c
+@@ -50,12 +50,12 @@ static void mtk_vcodec_vpu_reset_dec_handler(void *priv)
+
+ dev_err(&dev->plat_dev->dev, "Watchdog timeout!!");
+
+- mutex_lock(&dev->dev_mutex);
++ mutex_lock(&dev->dev_ctx_lock);
+ list_for_each_entry(ctx, &dev->ctx_list, list) {
+ ctx->state = MTK_STATE_ABORT;
+ mtk_v4l2_vdec_dbg(0, ctx, "[%d] Change to state MTK_STATE_ABORT", ctx->id);
+ }
+- mutex_unlock(&dev->dev_mutex);
++ mutex_unlock(&dev->dev_ctx_lock);
+ }
+
+ static void mtk_vcodec_vpu_reset_enc_handler(void *priv)
+@@ -65,12 +65,12 @@ static void mtk_vcodec_vpu_reset_enc_handler(void *priv)
+
+ dev_err(&dev->plat_dev->dev, "Watchdog timeout!!");
+
+- mutex_lock(&dev->dev_mutex);
++ mutex_lock(&dev->dev_ctx_lock);
+ list_for_each_entry(ctx, &dev->ctx_list, list) {
+ ctx->state = MTK_STATE_ABORT;
+ mtk_v4l2_vdec_dbg(0, ctx, "[%d] Change to state MTK_STATE_ABORT", ctx->id);
+ }
+- mutex_unlock(&dev->dev_mutex);
++ mutex_unlock(&dev->dev_ctx_lock);
+ }
+
+ static const struct mtk_vcodec_fw_ops mtk_vcodec_vpu_msg = {
+diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
+index f47c98faf068b..2073781ccadb1 100644
+--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
++++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
+@@ -268,7 +268,9 @@ static int fops_vcodec_open(struct file *file)
+
+ ctx->dev->vdec_pdata->init_vdec_params(ctx);
+
++ mutex_lock(&dev->dev_ctx_lock);
+ list_add(&ctx->list, &dev->ctx_list);
++ mutex_unlock(&dev->dev_ctx_lock);
+ mtk_vcodec_dbgfs_create(ctx);
+
+ mutex_unlock(&dev->dev_mutex);
+@@ -311,7 +313,9 @@ static int fops_vcodec_release(struct file *file)
+ v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+
+ mtk_vcodec_dbgfs_remove(dev, ctx->id);
++ mutex_lock(&dev->dev_ctx_lock);
+ list_del_init(&ctx->list);
++ mutex_unlock(&dev->dev_ctx_lock);
+ kfree(ctx);
+ mutex_unlock(&dev->dev_mutex);
+ return 0;
+@@ -404,6 +408,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
+ for (i = 0; i < MTK_VDEC_HW_MAX; i++)
+ mutex_init(&dev->dec_mutex[i]);
+ mutex_init(&dev->dev_mutex);
++ mutex_init(&dev->dev_ctx_lock);
+ spin_lock_init(&dev->irqlock);
+
+ snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
+diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
+index 849b89dd205c2..85b2c0d3d8bcd 100644
+--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
++++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
+@@ -241,6 +241,7 @@ struct mtk_vcodec_dec_ctx {
+ *
+ * @dec_mutex: decoder hardware lock
+ * @dev_mutex: video_device lock
++ * @dev_ctx_lock: the lock of context list
+ * @decode_workqueue: decode work queue
+ *
+ * @irqlock: protect data access by irq handler and work thread
+@@ -282,6 +283,7 @@ struct mtk_vcodec_dec_dev {
+ /* decoder hardware mutex lock */
+ struct mutex dec_mutex[MTK_VDEC_HW_MAX];
+ struct mutex dev_mutex;
++ struct mutex dev_ctx_lock;
+ struct workqueue_struct *decode_workqueue;
+
+ spinlock_t irqlock;
+diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
+index 06ed47df693bf..21836dd6ef85a 100644
+--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
++++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c
+@@ -869,7 +869,6 @@ static int vdec_hevc_slice_init(struct mtk_vcodec_dec_ctx *ctx)
+ inst->vpu.codec_type = ctx->current_codec;
+ inst->vpu.capture_type = ctx->capture_fourcc;
+
+- ctx->drv_handle = inst;
+ err = vpu_dec_init(&inst->vpu);
+ if (err) {
+ mtk_vdec_err(ctx, "vdec_hevc init err=%d", err);
+@@ -898,6 +897,7 @@ static int vdec_hevc_slice_init(struct mtk_vcodec_dec_ctx *ctx)
+ mtk_vdec_debug(ctx, "lat hevc instance >> %p, codec_type = 0x%x",
+ inst, inst->vpu.codec_type);
+
++ ctx->drv_handle = inst;
+ return 0;
+ error_free_inst:
+ kfree(inst);
+diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
+index 82e57ae983d55..da6be556727bb 100644
+--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
++++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c
+@@ -77,12 +77,14 @@ static bool vpu_dec_check_ap_inst(struct mtk_vcodec_dec_dev *dec_dev, struct vde
+ struct mtk_vcodec_dec_ctx *ctx;
+ int ret = false;
+
++ mutex_lock(&dec_dev->dev_ctx_lock);
+ list_for_each_entry(ctx, &dec_dev->ctx_list, list) {
+ if (!IS_ERR_OR_NULL(ctx) && ctx->vpu_inst == vpu) {
+ ret = true;
+ break;
+ }
+ }
++ mutex_unlock(&dec_dev->dev_ctx_lock);
+
+ return ret;
+ }
+diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c
+index 6319f24bc714b..3cb8a16222220 100644
+--- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c
++++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c
+@@ -177,7 +177,9 @@ static int fops_vcodec_open(struct file *file)
+ mtk_v4l2_venc_dbg(2, ctx, "Create instance [%d]@%p m2m_ctx=%p ",
+ ctx->id, ctx, ctx->m2m_ctx);
+
++ mutex_lock(&dev->dev_ctx_lock);
+ list_add(&ctx->list, &dev->ctx_list);
++ mutex_unlock(&dev->dev_ctx_lock);
+
+ mutex_unlock(&dev->dev_mutex);
+ mtk_v4l2_venc_dbg(0, ctx, "%s encoder [%d]", dev_name(&dev->plat_dev->dev),
+@@ -212,7 +214,9 @@ static int fops_vcodec_release(struct file *file)
+ v4l2_fh_exit(&ctx->fh);
+ v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
+
++ mutex_lock(&dev->dev_ctx_lock);
+ list_del_init(&ctx->list);
++ mutex_unlock(&dev->dev_ctx_lock);
+ kfree(ctx);
+ mutex_unlock(&dev->dev_mutex);
+ return 0;
+@@ -294,6 +298,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
+
+ mutex_init(&dev->enc_mutex);
+ mutex_init(&dev->dev_mutex);
++ mutex_init(&dev->dev_ctx_lock);
+ spin_lock_init(&dev->irqlock);
+
+ snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
+diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h
+index a042f607ed8d1..0bd85d0fb379a 100644
+--- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h
++++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h
+@@ -178,6 +178,7 @@ struct mtk_vcodec_enc_ctx {
+ *
+ * @enc_mutex: encoder hardware lock.
+ * @dev_mutex: video_device lock
++ * @dev_ctx_lock: the lock of context list
+ * @encode_workqueue: encode work queue
+ *
+ * @enc_irq: h264 encoder irq resource
+@@ -205,6 +206,7 @@ struct mtk_vcodec_enc_dev {
+ /* encoder hardware mutex lock */
+ struct mutex enc_mutex;
+ struct mutex dev_mutex;
++ struct mutex dev_ctx_lock;
+ struct workqueue_struct *encode_workqueue;
+
+ int enc_irq;
+diff --git a/drivers/media/platform/mediatek/vcodec/encoder/venc_vpu_if.c b/drivers/media/platform/mediatek/vcodec/encoder/venc_vpu_if.c
+index 84ad1cc6ad171..51bb7ee141b9e 100644
+--- a/drivers/media/platform/mediatek/vcodec/encoder/venc_vpu_if.c
++++ b/drivers/media/platform/mediatek/vcodec/encoder/venc_vpu_if.c
+@@ -47,12 +47,14 @@ static bool vpu_enc_check_ap_inst(struct mtk_vcodec_enc_dev *enc_dev, struct ven
+ struct mtk_vcodec_enc_ctx *ctx;
+ int ret = false;
+
++ mutex_lock(&enc_dev->dev_ctx_lock);
+ list_for_each_entry(ctx, &enc_dev->ctx_list, list) {
+ if (!IS_ERR_OR_NULL(ctx) && ctx->vpu_inst == vpu) {
+ ret = true;
+ break;
+ }
+ }
++ mutex_unlock(&enc_dev->dev_ctx_lock);
+
+ return ret;
+ }
+diff --git a/drivers/misc/vmw_vmci/vmci_datagram.c b/drivers/misc/vmw_vmci/vmci_datagram.c
+index f50d22882476f..a0ad1f3a69f7e 100644
+--- a/drivers/misc/vmw_vmci/vmci_datagram.c
++++ b/drivers/misc/vmw_vmci/vmci_datagram.c
+@@ -234,7 +234,8 @@ static int dg_dispatch_as_host(u32 context_id, struct vmci_datagram *dg)
+
+ dg_info->in_dg_host_queue = true;
+ dg_info->entry = dst_entry;
+- memcpy(&dg_info->msg, dg, dg_size);
++ dg_info->msg = *dg;
++ memcpy(&dg_info->msg_payload, dg + 1, dg->payload_size);
+
+ INIT_WORK(&dg_info->work, dg_delayed_dispatch);
+ schedule_work(&dg_info->work);
+@@ -377,7 +378,8 @@ int vmci_datagram_invoke_guest_handler(struct vmci_datagram *dg)
+
+ dg_info->in_dg_host_queue = false;
+ dg_info->entry = dst_entry;
+- memcpy(&dg_info->msg, dg, VMCI_DG_SIZE(dg));
++ dg_info->msg = *dg;
++ memcpy(&dg_info->msg_payload, dg + 1, dg->payload_size);
+
+ INIT_WORK(&dg_info->work, dg_delayed_dispatch);
+ schedule_work(&dg_info->work);
+diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
+index 7a864329cb726..95d78b3181d1c 100644
+--- a/drivers/net/dsa/qca/qca8k-8xxx.c
++++ b/drivers/net/dsa/qca/qca8k-8xxx.c
+@@ -954,7 +954,7 @@ qca8k_mdio_register(struct qca8k_priv *priv)
+
+ mdio = of_get_child_by_name(dev->of_node, "mdio");
+ if (mdio && !of_device_is_available(mdio))
+- goto out;
++ goto out_put_node;
+
+ bus = devm_mdiobus_alloc(dev);
+ if (!bus) {
+@@ -988,7 +988,6 @@ qca8k_mdio_register(struct qca8k_priv *priv)
+
+ out_put_node:
+ of_node_put(mdio);
+-out:
+ return err;
+ }
+
+diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
+index 768454aa36d6c..946bba0701a4f 100644
+--- a/drivers/net/dummy.c
++++ b/drivers/net/dummy.c
+@@ -71,6 +71,7 @@ static int dummy_dev_init(struct net_device *dev)
+ if (!dev->lstats)
+ return -ENOMEM;
+
++ netdev_lockdep_set_classes(dev);
+ return 0;
+ }
+
+diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+index e9c1e1bb55806..528441b28c4ef 100644
+--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+@@ -147,10 +147,11 @@ void bnx2x_fill_fw_str(struct bnx2x *bp, char *buf, size_t buf_len)
+
+ phy_fw_ver[0] = '\0';
+ bnx2x_get_ext_phy_fw_version(&bp->link_params,
+- phy_fw_ver, PHY_FW_VER_LEN);
+- strscpy(buf, bp->fw_ver, buf_len);
+- snprintf(buf + strlen(bp->fw_ver), 32 - strlen(bp->fw_ver),
+- "bc %d.%d.%d%s%s",
++ phy_fw_ver, sizeof(phy_fw_ver));
++ /* This may become truncated. */
++ scnprintf(buf, buf_len,
++ "%sbc %d.%d.%d%s%s",
++ bp->fw_ver,
+ (bp->common.bc_ver & 0xff0000) >> 16,
+ (bp->common.bc_ver & 0xff00) >> 8,
+ (bp->common.bc_ver & 0xff),
+diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+index 81d232e6d05fe..0bc7690cdee16 100644
+--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+@@ -1132,7 +1132,7 @@ static void bnx2x_get_drvinfo(struct net_device *dev,
+ }
+
+ memset(version, 0, sizeof(version));
+- bnx2x_fill_fw_str(bp, version, ETHTOOL_FWVERS_LEN);
++ bnx2x_fill_fw_str(bp, version, sizeof(version));
+ strlcat(info->fw_version, version, sizeof(info->fw_version));
+
+ strscpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
+diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+index 02808513ffe45..ea310057fe3af 100644
+--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+@@ -6163,8 +6163,8 @@ static void bnx2x_link_int_ack(struct link_params *params,
+
+ static int bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+ {
+- str[0] = '\0';
+- (*len)--;
++ if (*len)
++ str[0] = '\0';
+ return 0;
+ }
+
+@@ -6173,7 +6173,7 @@ static int bnx2x_format_ver(u32 num, u8 *str, u16 *len)
+ u16 ret;
+
+ if (*len < 10) {
+- /* Need more than 10chars for this format */
++ /* Need more than 10 chars for this format */
+ bnx2x_null_format_ver(num, str, len);
+ return -EINVAL;
+ }
+@@ -6188,8 +6188,8 @@ static int bnx2x_3_seq_format_ver(u32 num, u8 *str, u16 *len)
+ {
+ u16 ret;
+
+- if (*len < 10) {
+- /* Need more than 10chars for this format */
++ if (*len < 9) {
++ /* Need more than 9 chars for this format */
+ bnx2x_null_format_ver(num, str, len);
+ return -EINVAL;
+ }
+@@ -6208,7 +6208,7 @@ int bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 *version,
+ int status = 0;
+ u8 *ver_p = version;
+ u16 remain_len = len;
+- if (version == NULL || params == NULL)
++ if (version == NULL || params == NULL || len == 0)
+ return -EINVAL;
+ bp = params->bp;
+
+@@ -11546,7 +11546,7 @@ static int bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len)
+ str[2] = (spirom_ver & 0xFF0000) >> 16;
+ str[3] = (spirom_ver & 0xFF000000) >> 24;
+ str[4] = '\0';
+- *len -= 5;
++ *len -= 4;
+ return 0;
+ }
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
+index 6f2328a049bf1..7b550d7d96b68 100644
+--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c
++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
+@@ -499,7 +499,7 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)
+ vfres->rss_lut_size = ICE_LUT_VSI_SIZE;
+ vfres->max_mtu = ice_vc_get_max_frame_size(vf);
+
+- vfres->vsi_res[0].vsi_id = vf->lan_vsi_num;
++ vfres->vsi_res[0].vsi_id = ICE_VF_VSI_ID;
+ vfres->vsi_res[0].vsi_type = VIRTCHNL_VSI_SRIOV;
+ vfres->vsi_res[0].num_queue_pairs = vsi->num_txq;
+ ether_addr_copy(vfres->vsi_res[0].default_mac_addr,
+@@ -545,12 +545,7 @@ static void ice_vc_reset_vf_msg(struct ice_vf *vf)
+ */
+ bool ice_vc_isvalid_vsi_id(struct ice_vf *vf, u16 vsi_id)
+ {
+- struct ice_pf *pf = vf->pf;
+- struct ice_vsi *vsi;
+-
+- vsi = ice_find_vsi(pf, vsi_id);
+-
+- return (vsi && (vsi->vf == vf));
++ return vsi_id == ICE_VF_VSI_ID;
+ }
+
+ /**
+diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.h b/drivers/net/ethernet/intel/ice/ice_virtchnl.h
+index 60dfbe05980aa..3a41158691532 100644
+--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.h
++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.h
+@@ -19,6 +19,15 @@
+ #define ICE_MAX_MACADDR_PER_VF 18
+ #define ICE_FLEX_DESC_RXDID_MAX_NUM 64
+
++/* VFs only get a single VSI. For ice hardware, the VF does not need to know
++ * its VSI index. However, the virtchnl interface requires a VSI number,
++ * mainly due to legacy hardware.
++ *
++ * Since the VF doesn't need this information, report a static value to the VF
++ * instead of leaking any information about the PF or hardware setup.
++ */
++#define ICE_VF_VSI_ID 1
++
+ struct ice_virtchnl_ops {
+ int (*get_ver_msg)(struct ice_vf *vf, u8 *msg);
+ int (*get_vf_res_msg)(struct ice_vf *vf, u8 *msg);
+diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+index fcb44ceeb6aa5..44d30115ded13 100644
+--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
++++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+@@ -3391,9 +3391,12 @@ static int ionic_lif_adminq_init(struct ionic_lif *lif)
+
+ napi_enable(&qcq->napi);
+
+- if (qcq->flags & IONIC_QCQ_F_INTR)
++ if (qcq->flags & IONIC_QCQ_F_INTR) {
++ irq_set_affinity_hint(qcq->intr.vector,
++ &qcq->intr.affinity_mask);
+ ionic_intr_mask(idev->intr_ctrl, qcq->intr.index,
+ IONIC_INTR_MASK_CLEAR);
++ }
+
+ qcq->flags |= IONIC_QCQ_F_INITED;
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+index 85dcda51df052..4ec61f1ee71a2 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+@@ -165,9 +165,9 @@ config DWMAC_STARFIVE
+ help
+ Support for ethernet controllers on StarFive RISC-V SoCs
+
+- This selects the StarFive platform specific glue layer support for
+- the stmmac device driver. This driver is used for StarFive JH7110
+- ethernet controller.
++ This selects the StarFive platform specific glue layer support
++ for the stmmac device driver. This driver is used for the
++ StarFive JH7100 and JH7110 ethernet controllers.
+
+ config DWMAC_STI
+ tristate "STi GMAC support"
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+index 5d630affb4d15..4e1076faee0cd 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+@@ -15,13 +15,20 @@
+
+ #include "stmmac_platform.h"
+
+-#define STARFIVE_DWMAC_PHY_INFT_RGMII 0x1
+-#define STARFIVE_DWMAC_PHY_INFT_RMII 0x4
+-#define STARFIVE_DWMAC_PHY_INFT_FIELD 0x7U
++#define STARFIVE_DWMAC_PHY_INFT_RGMII 0x1
++#define STARFIVE_DWMAC_PHY_INFT_RMII 0x4
++#define STARFIVE_DWMAC_PHY_INFT_FIELD 0x7U
++
++#define JH7100_SYSMAIN_REGISTER49_DLYCHAIN 0xc8
++
++struct starfive_dwmac_data {
++ unsigned int gtxclk_dlychain;
++};
+
+ struct starfive_dwmac {
+ struct device *dev;
+ struct clk *clk_tx;
++ const struct starfive_dwmac_data *data;
+ };
+
+ static void starfive_dwmac_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode)
+@@ -67,6 +74,8 @@ static int starfive_dwmac_set_mode(struct plat_stmmacenet_data *plat_dat)
+
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
++ case PHY_INTERFACE_MODE_RGMII_RXID:
++ case PHY_INTERFACE_MODE_RGMII_TXID:
+ mode = STARFIVE_DWMAC_PHY_INFT_RGMII;
+ break;
+
+@@ -89,6 +98,14 @@ static int starfive_dwmac_set_mode(struct plat_stmmacenet_data *plat_dat)
+ if (err)
+ return dev_err_probe(dwmac->dev, err, "error setting phy mode\n");
+
++ if (dwmac->data) {
++ err = regmap_write(regmap, JH7100_SYSMAIN_REGISTER49_DLYCHAIN,
++ dwmac->data->gtxclk_dlychain);
++ if (err)
++ return dev_err_probe(dwmac->dev, err,
++ "error selecting gtxclk delay chain\n");
++ }
++
+ return 0;
+ }
+
+@@ -114,6 +131,8 @@ static int starfive_dwmac_probe(struct platform_device *pdev)
+ if (!dwmac)
+ return -ENOMEM;
+
++ dwmac->data = device_get_match_data(&pdev->dev);
++
+ dwmac->clk_tx = devm_clk_get_enabled(&pdev->dev, "tx");
+ if (IS_ERR(dwmac->clk_tx))
+ return dev_err_probe(&pdev->dev, PTR_ERR(dwmac->clk_tx),
+@@ -144,8 +163,13 @@ static int starfive_dwmac_probe(struct platform_device *pdev)
+ return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+ }
+
++static const struct starfive_dwmac_data jh7100_data = {
++ .gtxclk_dlychain = 4,
++};
++
+ static const struct of_device_id starfive_dwmac_match[] = {
+- { .compatible = "starfive,jh7110-dwmac" },
++ { .compatible = "starfive,jh7100-dwmac", .data = &jh7100_data },
++ { .compatible = "starfive,jh7110-dwmac" },
+ { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, starfive_dwmac_match);
+diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
+index c4ed36c718974..097a8db0d1d99 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -349,6 +349,7 @@ static int geneve_init(struct net_device *dev)
+ gro_cells_destroy(&geneve->gro_cells);
+ return err;
+ }
++ netdev_lockdep_set_classes(dev);
+ return 0;
+ }
+
+diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
+index f6d53e63ef4ec..f6eab66c26608 100644
+--- a/drivers/net/loopback.c
++++ b/drivers/net/loopback.c
+@@ -144,6 +144,7 @@ static int loopback_dev_init(struct net_device *dev)
+ dev->lstats = netdev_alloc_pcpu_stats(struct pcpu_lstats);
+ if (!dev->lstats)
+ return -ENOMEM;
++ netdev_lockdep_set_classes(dev);
+ return 0;
+ }
+
+diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
+index 31f0beba638a2..03d6a6aef77cd 100644
+--- a/drivers/net/pcs/pcs-xpcs.c
++++ b/drivers/net/pcs/pcs-xpcs.c
+@@ -293,7 +293,7 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs,
+ dev = MDIO_MMD_VEND2;
+ break;
+ default:
+- return -1;
++ return -EINVAL;
+ }
+
+ ret = xpcs_write(xpcs, dev, MDIO_CTRL1, MDIO_CTRL1_RESET);
+@@ -891,7 +891,7 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface,
+ return ret;
+ break;
+ default:
+- return -1;
++ return -EINVAL;
+ }
+
+ if (compat->pma_config) {
+diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
+index 6125418ca93f3..8efa2a136faa9 100644
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -1413,6 +1413,11 @@ int phy_sfp_probe(struct phy_device *phydev,
+ }
+ EXPORT_SYMBOL(phy_sfp_probe);
+
++static bool phy_drv_supports_irq(struct phy_driver *phydrv)
++{
++ return phydrv->config_intr && phydrv->handle_interrupt;
++}
++
+ /**
+ * phy_attach_direct - attach a network device to a given PHY device pointer
+ * @dev: network device to attach
+@@ -1527,6 +1532,9 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
+ if (phydev->dev_flags & PHY_F_NO_IRQ)
+ phydev->irq = PHY_POLL;
+
++ if (!phy_drv_supports_irq(phydev->drv) && phy_interrupt_is_valid(phydev))
++ phydev->irq = PHY_POLL;
++
+ /* Port is set to PORT_TP by default and the actual PHY driver will set
+ * it to different value depending on the PHY configuration. If we have
+ * the generic PHY driver we can't figure it out, thus set the old
+@@ -2992,11 +3000,6 @@ s32 phy_get_internal_delay(struct phy_device *phydev, struct device *dev,
+ }
+ EXPORT_SYMBOL(phy_get_internal_delay);
+
+-static bool phy_drv_supports_irq(struct phy_driver *phydrv)
+-{
+- return phydrv->config_intr && phydrv->handle_interrupt;
+-}
+-
+ static int phy_led_set_brightness(struct led_classdev *led_cdev,
+ enum led_brightness value)
+ {
+diff --git a/drivers/net/veth.c b/drivers/net/veth.c
+index f0b2c4d5fe43a..5146aa6989acc 100644
+--- a/drivers/net/veth.c
++++ b/drivers/net/veth.c
+@@ -1483,6 +1483,7 @@ static void veth_free_queues(struct net_device *dev)
+
+ static int veth_dev_init(struct net_device *dev)
+ {
++ netdev_lockdep_set_classes(dev);
+ return veth_alloc_queues(dev);
+ }
+
+diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
+index 16106e088c630..0bedb804824ba 100644
+--- a/drivers/net/vxlan/vxlan_core.c
++++ b/drivers/net/vxlan/vxlan_core.c
+@@ -2855,6 +2855,7 @@ static int vxlan_init(struct net_device *dev)
+ if (err)
+ goto err_gro_cells_destroy;
+
++ netdev_lockdep_set_classes(dev);
+ return 0;
+
+ err_gro_cells_destroy:
+diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
+index 6835c14b82cc9..337590236485f 100644
+--- a/drivers/net/wireless/ath/ath11k/mhi.c
++++ b/drivers/net/wireless/ath/ath11k/mhi.c
+@@ -106,7 +106,7 @@ static struct mhi_controller_config ath11k_mhi_config_qca6390 = {
+ .max_channels = 128,
+ .timeout_ms = 2000,
+ .use_bounce_buf = false,
+- .buf_len = 0,
++ .buf_len = 8192,
+ .num_channels = ARRAY_SIZE(ath11k_mhi_channels_qca6390),
+ .ch_cfg = ath11k_mhi_channels_qca6390,
+ .num_events = ARRAY_SIZE(ath11k_mhi_events_qca6390),
+diff --git a/drivers/net/wireless/ath/ath9k/antenna.c b/drivers/net/wireless/ath/ath9k/antenna.c
+index 988222cea9dfe..acc84e6711b0e 100644
+--- a/drivers/net/wireless/ath/ath9k/antenna.c
++++ b/drivers/net/wireless/ath/ath9k/antenna.c
+@@ -643,7 +643,7 @@ static void ath_ant_try_scan(struct ath_ant_comb *antcomb,
+ conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+ conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_PLUS_LNA2;
+ } else if (antcomb->rssi_sub >
+- antcomb->rssi_lna1) {
++ antcomb->rssi_lna2) {
+ /* set to A-B */
+ conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
+ conf->alt_lna_conf = ATH_ANT_DIV_COMB_LNA1_MINUS_LNA2;
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c
+index 86ff174936a9a..c3a602197662b 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/dmi.c
+@@ -82,6 +82,15 @@ static const struct dmi_system_id dmi_platform_data[] = {
+ },
+ .driver_data = (void *)&acepc_t8_data,
+ },
++ {
++ /* ACEPC W5 Pro Cherry Trail Z8350 HDMI stick, same wifi as the T8 */
++ .matches = {
++ DMI_MATCH(DMI_BOARD_NAME, "T3 MRD"),
++ DMI_MATCH(DMI_CHASSIS_TYPE, "3"),
++ DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
++ },
++ .driver_data = (void *)&acepc_t8_data,
++ },
+ {
+ /* Chuwi Hi8 Pro with D2D3_Hi8Pro.233 BIOS */
+ .matches = {
+diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c
+index 134635c70ce85..73cbb120a49b4 100644
+--- a/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c
++++ b/drivers/net/wireless/intel/iwlwifi/cfg/ax210.c
+@@ -299,3 +299,9 @@ MODULE_FIRMWARE(IWL_MA_B_HR_B_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+ MODULE_FIRMWARE(IWL_MA_B_GF_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+ MODULE_FIRMWARE(IWL_MA_B_GF4_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
+ MODULE_FIRMWARE(IWL_MA_B_MR_A_FW_MODULE_FIRMWARE(IWL_AX210_UCODE_API_MAX));
++
++MODULE_FIRMWARE("iwlwifi-so-a0-gf-a0.pnvm");
++MODULE_FIRMWARE("iwlwifi-so-a0-gf4-a0.pnvm");
++MODULE_FIRMWARE("iwlwifi-ty-a0-gf-a0.pnvm");
++MODULE_FIRMWARE("iwlwifi-ma-b0-gf-a0.pnvm");
++MODULE_FIRMWARE("iwlwifi-ma-b0-gf4-a0.pnvm");
+diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
+index 82da957adcf6e..1b6249561cd58 100644
+--- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
++++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
+@@ -179,3 +179,5 @@ MODULE_FIRMWARE(IWL_BZ_A_FM_C_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+ MODULE_FIRMWARE(IWL_BZ_A_FM4_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+ MODULE_FIRMWARE(IWL_GL_B_FM_B_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
+ MODULE_FIRMWARE(IWL_GL_C_FM_C_MODULE_FIRMWARE(IWL_BZ_UCODE_API_MAX));
++
++MODULE_FIRMWARE("iwlwifi-gl-c0-fm-c0.pnvm");
+diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
+index 80eb9b4995389..156c428547497 100644
+--- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
++++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ /*
+ * Copyright (C) 2015-2017 Intel Deutschland GmbH
+- * Copyright (C) 2018-2023 Intel Corporation
++ * Copyright (C) 2018-2024 Intel Corporation
+ */
+ #include <linux/module.h>
+ #include <linux/stringify.h>
+@@ -33,6 +33,10 @@
+ #define IWL_SC_A_GF_A_FW_PRE "iwlwifi-sc-a0-gf-a0"
+ #define IWL_SC_A_GF4_A_FW_PRE "iwlwifi-sc-a0-gf4-a0"
+ #define IWL_SC_A_WH_A_FW_PRE "iwlwifi-sc-a0-wh-a0"
++#define IWL_SC2_A_FM_C_FW_PRE "iwlwifi-sc2-a0-fm-c0"
++#define IWL_SC2_A_WH_A_FW_PRE "iwlwifi-sc2-a0-wh-a0"
++#define IWL_SC2F_A_FM_C_FW_PRE "iwlwifi-sc2f-a0-fm-c0"
++#define IWL_SC2F_A_WH_A_FW_PRE "iwlwifi-sc2f-a0-wh-a0"
+
+ #define IWL_SC_A_FM_B_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_FM_B_FW_PRE "-" __stringify(api) ".ucode"
+@@ -48,6 +52,14 @@
+ IWL_SC_A_GF4_A_FW_PRE "-" __stringify(api) ".ucode"
+ #define IWL_SC_A_WH_A_FW_MODULE_FIRMWARE(api) \
+ IWL_SC_A_WH_A_FW_PRE "-" __stringify(api) ".ucode"
++#define IWL_SC2_A_FM_C_FW_MODULE_FIRMWARE(api) \
++ IWL_SC2_A_FM_C_FW_PRE "-" __stringify(api) ".ucode"
++#define IWL_SC2_A_WH_A_FW_MODULE_FIRMWARE(api) \
++ IWL_SC2_A_WH_A_FW_PRE "-" __stringify(api) ".ucode"
++#define IWL_SC2F_A_FM_C_FW_MODULE_FIRMWARE(api) \
++ IWL_SC2F_A_FM_C_FW_PRE "-" __stringify(api) ".ucode"
++#define IWL_SC2F_A_WH_A_FW_MODULE_FIRMWARE(api) \
++ IWL_SC2F_A_WH_A_FW_PRE "-" __stringify(api) ".ucode"
+
+ static const struct iwl_base_params iwl_sc_base_params = {
+ .eeprom_size = OTP_LOW_IMAGE_SIZE_32K,
+@@ -124,6 +136,9 @@ static const struct iwl_base_params iwl_sc_base_params = {
+
+ #define IWL_DEVICE_SC \
+ IWL_DEVICE_BZ_COMMON, \
++ .uhb_supported = true, \
++ .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM, \
++ .num_rbds = IWL_NUM_RBDS_SC_EHT, \
+ .ht_params = &iwl_22000_ht_params
+
+ /*
+@@ -149,10 +164,21 @@ const char iwl_sc_name[] = "Intel(R) TBD Sc device";
+
+ const struct iwl_cfg iwl_cfg_sc = {
+ .fw_name_mac = "sc",
+- .uhb_supported = true,
+ IWL_DEVICE_SC,
+- .features = IWL_TX_CSUM_NETIF_FLAGS | NETIF_F_RXCSUM,
+- .num_rbds = IWL_NUM_RBDS_SC_EHT,
++};
++
++const char iwl_sc2_name[] = "Intel(R) TBD Sc2 device";
++
++const struct iwl_cfg iwl_cfg_sc2 = {
++ .fw_name_mac = "sc2",
++ IWL_DEVICE_SC,
++};
++
++const char iwl_sc2f_name[] = "Intel(R) TBD Sc2f device";
++
++const struct iwl_cfg iwl_cfg_sc2f = {
++ .fw_name_mac = "sc2f",
++ IWL_DEVICE_SC,
+ };
+
+ MODULE_FIRMWARE(IWL_SC_A_FM_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+@@ -162,3 +188,7 @@ MODULE_FIRMWARE(IWL_SC_A_HR_B_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+ MODULE_FIRMWARE(IWL_SC_A_GF_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+ MODULE_FIRMWARE(IWL_SC_A_GF4_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+ MODULE_FIRMWARE(IWL_SC_A_WH_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
++MODULE_FIRMWARE(IWL_SC2_A_FM_C_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
++MODULE_FIRMWARE(IWL_SC2_A_WH_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
++MODULE_FIRMWARE(IWL_SC2F_A_FM_C_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
++MODULE_FIRMWARE(IWL_SC2F_A_WH_A_FW_MODULE_FIRMWARE(IWL_SC_UCODE_API_MAX));
+diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+index ae6f1cd4d6605..e99d691362a86 100644
+--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
++++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+@@ -2,7 +2,7 @@
+ /*
+ * Copyright (C) 2005-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2016-2017 Intel Deutschland GmbH
+- * Copyright (C) 2018-2023 Intel Corporation
++ * Copyright (C) 2018-2024 Intel Corporation
+ */
+ #ifndef __IWL_CONFIG_H__
+ #define __IWL_CONFIG_H__
+@@ -418,6 +418,8 @@ struct iwl_cfg {
+ #define IWL_CFG_MAC_TYPE_BZ 0x46
+ #define IWL_CFG_MAC_TYPE_GL 0x47
+ #define IWL_CFG_MAC_TYPE_SC 0x48
++#define IWL_CFG_MAC_TYPE_SC2 0x49
++#define IWL_CFG_MAC_TYPE_SC2F 0x4A
+
+ #define IWL_CFG_RF_TYPE_TH 0x105
+ #define IWL_CFG_RF_TYPE_TH1 0x108
+@@ -527,6 +529,8 @@ extern const char iwl_ax231_name[];
+ extern const char iwl_ax411_name[];
+ extern const char iwl_bz_name[];
+ extern const char iwl_sc_name[];
++extern const char iwl_sc2_name[];
++extern const char iwl_sc2f_name[];
+ #if IS_ENABLED(CONFIG_IWLDVM)
+ extern const struct iwl_cfg iwl5300_agn_cfg;
+ extern const struct iwl_cfg iwl5100_agn_cfg;
+@@ -632,6 +636,8 @@ extern const struct iwl_cfg iwl_cfg_bz;
+ extern const struct iwl_cfg iwl_cfg_gl;
+
+ extern const struct iwl_cfg iwl_cfg_sc;
++extern const struct iwl_cfg iwl_cfg_sc2;
++extern const struct iwl_cfg iwl_cfg_sc2f;
+ #endif /* CONFIG_IWLMVM */
+
+ #endif /* __IWL_CONFIG_H__ */
+diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+index 2c9b98c8184b5..ba3db601ab878 100644
+--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
++++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ /*
+- * Copyright (C) 2005-2014, 2018-2023 Intel Corporation
++ * Copyright (C) 2005-2014, 2018-2024 Intel Corporation
+ * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016-2017 Intel Deutschland GmbH
+ */
+@@ -502,12 +502,16 @@ static const struct pci_device_id iwl_hw_card_ids[] = {
+
+ /* Bz devices */
+ {IWL_PCI_DEVICE(0x2727, PCI_ANY_ID, iwl_bz_trans_cfg)},
++ {IWL_PCI_DEVICE(0x272D, PCI_ANY_ID, iwl_bz_trans_cfg)},
+ {IWL_PCI_DEVICE(0x272b, PCI_ANY_ID, iwl_bz_trans_cfg)},
+ {IWL_PCI_DEVICE(0xA840, PCI_ANY_ID, iwl_bz_trans_cfg)},
+ {IWL_PCI_DEVICE(0x7740, PCI_ANY_ID, iwl_bz_trans_cfg)},
+
+ /* Sc devices */
+ {IWL_PCI_DEVICE(0xE440, PCI_ANY_ID, iwl_sc_trans_cfg)},
++ {IWL_PCI_DEVICE(0xE340, PCI_ANY_ID, iwl_sc_trans_cfg)},
++ {IWL_PCI_DEVICE(0xD340, PCI_ANY_ID, iwl_sc_trans_cfg)},
++ {IWL_PCI_DEVICE(0x6E70, PCI_ANY_ID, iwl_sc_trans_cfg)},
+ #endif /* CONFIG_IWLMVM */
+
+ {0}
+@@ -1115,6 +1119,16 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_sc, iwl_sc_name),
++ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
++ IWL_CFG_MAC_TYPE_SC2, IWL_CFG_ANY,
++ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
++ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
++ iwl_cfg_sc2, iwl_sc2_name),
++ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
++ IWL_CFG_MAC_TYPE_SC2F, IWL_CFG_ANY,
++ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
++ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
++ iwl_cfg_sc2f, iwl_sc2f_name),
+ #endif /* CONFIG_IWLMVM */
+ };
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
+index 3039f53e22454..dceb505987b19 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mmio.c
+@@ -490,6 +490,11 @@ static u32 __mt7915_reg_addr(struct mt7915_dev *dev, u32 addr)
+ return dev->reg.map[i].maps + ofs;
+ }
+
++ return 0;
++}
++
++static u32 __mt7915_reg_remap_addr(struct mt7915_dev *dev, u32 addr)
++{
+ if ((addr >= MT_INFRA_BASE && addr < MT_WFSYS0_PHY_START) ||
+ (addr >= MT_WFSYS0_PHY_START && addr < MT_WFSYS1_PHY_START) ||
+ (addr >= MT_WFSYS1_PHY_START && addr <= MT_WFSYS1_PHY_END))
+@@ -514,15 +519,30 @@ void mt7915_memcpy_fromio(struct mt7915_dev *dev, void *buf, u32 offset,
+ {
+ u32 addr = __mt7915_reg_addr(dev, offset);
+
+- memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len);
++ if (addr) {
++ memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len);
++ return;
++ }
++
++ spin_lock_bh(&dev->reg_lock);
++ memcpy_fromio(buf, dev->mt76.mmio.regs +
++ __mt7915_reg_remap_addr(dev, offset), len);
++ spin_unlock_bh(&dev->reg_lock);
+ }
+
+ static u32 mt7915_rr(struct mt76_dev *mdev, u32 offset)
+ {
+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
+- u32 addr = __mt7915_reg_addr(dev, offset);
++ u32 addr = __mt7915_reg_addr(dev, offset), val;
+
+- return dev->bus_ops->rr(mdev, addr);
++ if (addr)
++ return dev->bus_ops->rr(mdev, addr);
++
++ spin_lock_bh(&dev->reg_lock);
++ val = dev->bus_ops->rr(mdev, __mt7915_reg_remap_addr(dev, offset));
++ spin_unlock_bh(&dev->reg_lock);
++
++ return val;
+ }
+
+ static void mt7915_wr(struct mt76_dev *mdev, u32 offset, u32 val)
+@@ -530,7 +550,14 @@ static void mt7915_wr(struct mt76_dev *mdev, u32 offset, u32 val)
+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
+ u32 addr = __mt7915_reg_addr(dev, offset);
+
+- dev->bus_ops->wr(mdev, addr, val);
++ if (addr) {
++ dev->bus_ops->wr(mdev, addr, val);
++ return;
++ }
++
++ spin_lock_bh(&dev->reg_lock);
++ dev->bus_ops->wr(mdev, __mt7915_reg_remap_addr(dev, offset), val);
++ spin_unlock_bh(&dev->reg_lock);
+ }
+
+ static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
+@@ -538,7 +565,14 @@ static u32 mt7915_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
+ struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
+ u32 addr = __mt7915_reg_addr(dev, offset);
+
+- return dev->bus_ops->rmw(mdev, addr, mask, val);
++ if (addr)
++ return dev->bus_ops->rmw(mdev, addr, mask, val);
++
++ spin_lock_bh(&dev->reg_lock);
++ val = dev->bus_ops->rmw(mdev, __mt7915_reg_remap_addr(dev, offset), mask, val);
++ spin_unlock_bh(&dev->reg_lock);
++
++ return val;
+ }
+
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+@@ -707,6 +741,7 @@ static int mt7915_mmio_init(struct mt76_dev *mdev,
+
+ dev = container_of(mdev, struct mt7915_dev, mt76);
+ mt76_mmio_init(&dev->mt76, mem_base);
++ spin_lock_init(&dev->reg_lock);
+
+ switch (device_id) {
+ case 0x7915:
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+index 4727d9c7b11de..6e79bc65f5a51 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+@@ -287,6 +287,7 @@ struct mt7915_dev {
+
+ struct list_head sta_rc_list;
+ struct list_head twt_list;
++ spinlock_t reg_lock;
+
+ u32 hw_pattern;
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+index 63d34844c1223..0384fb059ddfc 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+@@ -732,6 +732,9 @@ mt7996_mac_write_txwi_8023(struct mt7996_dev *dev, __le32 *txwi,
+ FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype);
+
+ txwi[2] |= cpu_to_le32(val);
++
++ if (wcid->amsdu)
++ txwi[3] |= cpu_to_le32(MT_TXD3_HW_AMSDU);
+ }
+
+ static void
+@@ -862,8 +865,6 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
+ val |= MT_TXD3_PROTECT_FRAME;
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+ val |= MT_TXD3_NO_ACK;
+- if (wcid->amsdu)
+- val |= MT_TXD3_HW_AMSDU;
+
+ txwi[3] = cpu_to_le32(val);
+ txwi[4] = 0;
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
+index 9f2abfa273c9b..efd4a767eb37d 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
+@@ -140,7 +140,6 @@ static u32 mt7996_reg_map_l1(struct mt7996_dev *dev, u32 addr)
+ u32 offset = FIELD_GET(MT_HIF_REMAP_L1_OFFSET, addr);
+ u32 base = FIELD_GET(MT_HIF_REMAP_L1_BASE, addr);
+
+- dev->reg_l1_backup = dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L1);
+ dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L1,
+ MT_HIF_REMAP_L1_MASK,
+ FIELD_PREP(MT_HIF_REMAP_L1_MASK, base));
+@@ -155,7 +154,6 @@ static u32 mt7996_reg_map_l2(struct mt7996_dev *dev, u32 addr)
+ u32 offset = FIELD_GET(MT_HIF_REMAP_L2_OFFSET, addr);
+ u32 base = FIELD_GET(MT_HIF_REMAP_L2_BASE, addr);
+
+- dev->reg_l2_backup = dev->bus_ops->rr(&dev->mt76, MT_HIF_REMAP_L2);
+ dev->bus_ops->rmw(&dev->mt76, MT_HIF_REMAP_L2,
+ MT_HIF_REMAP_L2_MASK,
+ FIELD_PREP(MT_HIF_REMAP_L2_MASK, base));
+@@ -165,26 +163,10 @@ static u32 mt7996_reg_map_l2(struct mt7996_dev *dev, u32 addr)
+ return MT_HIF_REMAP_BASE_L2 + offset;
+ }
+
+-static void mt7996_reg_remap_restore(struct mt7996_dev *dev)
+-{
+- /* remap to ori status */
+- if (unlikely(dev->reg_l1_backup)) {
+- dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L1, dev->reg_l1_backup);
+- dev->reg_l1_backup = 0;
+- }
+-
+- if (dev->reg_l2_backup) {
+- dev->bus_ops->wr(&dev->mt76, MT_HIF_REMAP_L2, dev->reg_l2_backup);
+- dev->reg_l2_backup = 0;
+- }
+-}
+-
+ static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr)
+ {
+ int i;
+
+- mt7996_reg_remap_restore(dev);
+-
+ if (addr < 0x100000)
+ return addr;
+
+@@ -201,6 +183,11 @@ static u32 __mt7996_reg_addr(struct mt7996_dev *dev, u32 addr)
+ return dev->reg.map[i].mapped + ofs;
+ }
+
++ return 0;
++}
++
++static u32 __mt7996_reg_remap_addr(struct mt7996_dev *dev, u32 addr)
++{
+ if ((addr >= MT_INFRA_BASE && addr < MT_WFSYS0_PHY_START) ||
+ (addr >= MT_WFSYS0_PHY_START && addr < MT_WFSYS1_PHY_START) ||
+ (addr >= MT_WFSYS1_PHY_START && addr <= MT_WFSYS1_PHY_END))
+@@ -225,28 +212,60 @@ void mt7996_memcpy_fromio(struct mt7996_dev *dev, void *buf, u32 offset,
+ {
+ u32 addr = __mt7996_reg_addr(dev, offset);
+
+- memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len);
++ if (addr) {
++ memcpy_fromio(buf, dev->mt76.mmio.regs + addr, len);
++ return;
++ }
++
++ spin_lock_bh(&dev->reg_lock);
++ memcpy_fromio(buf, dev->mt76.mmio.regs +
++ __mt7996_reg_remap_addr(dev, offset), len);
++ spin_unlock_bh(&dev->reg_lock);
+ }
+
+ static u32 mt7996_rr(struct mt76_dev *mdev, u32 offset)
+ {
+ struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
++ u32 addr = __mt7996_reg_addr(dev, offset), val;
++
++ if (addr)
++ return dev->bus_ops->rr(mdev, addr);
+
+- return dev->bus_ops->rr(mdev, __mt7996_reg_addr(dev, offset));
++ spin_lock_bh(&dev->reg_lock);
++ val = dev->bus_ops->rr(mdev, __mt7996_reg_remap_addr(dev, offset));
++ spin_unlock_bh(&dev->reg_lock);
++
++ return val;
+ }
+
+ static void mt7996_wr(struct mt76_dev *mdev, u32 offset, u32 val)
+ {
+ struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
++ u32 addr = __mt7996_reg_addr(dev, offset);
+
+- dev->bus_ops->wr(mdev, __mt7996_reg_addr(dev, offset), val);
++ if (addr) {
++ dev->bus_ops->wr(mdev, addr, val);
++ return;
++ }
++
++ spin_lock_bh(&dev->reg_lock);
++ dev->bus_ops->wr(mdev, __mt7996_reg_remap_addr(dev, offset), val);
++ spin_unlock_bh(&dev->reg_lock);
+ }
+
+ static u32 mt7996_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
+ {
+ struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76);
++ u32 addr = __mt7996_reg_addr(dev, offset);
++
++ if (addr)
++ return dev->bus_ops->rmw(mdev, addr, mask, val);
++
++ spin_lock_bh(&dev->reg_lock);
++ val = dev->bus_ops->rmw(mdev, __mt7996_reg_remap_addr(dev, offset), mask, val);
++ spin_unlock_bh(&dev->reg_lock);
+
+- return dev->bus_ops->rmw(mdev, __mt7996_reg_addr(dev, offset), mask, val);
++ return val;
+ }
+
+ #ifdef CONFIG_NET_MEDIATEK_SOC_WED
+@@ -421,6 +440,7 @@ static int mt7996_mmio_init(struct mt76_dev *mdev,
+
+ dev = container_of(mdev, struct mt7996_dev, mt76);
+ mt76_mmio_init(&dev->mt76, mem_base);
++ spin_lock_init(&dev->reg_lock);
+
+ switch (device_id) {
+ case 0x7990:
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+index 8154ad37827f0..36d1f247d55aa 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+@@ -325,8 +325,7 @@ struct mt7996_dev {
+ u8 n_agrt;
+ } twt;
+
+- u32 reg_l1_backup;
+- u32 reg_l2_backup;
++ spinlock_t reg_lock;
+
+ u8 wtbl_size_group;
+ };
+diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
+index 93889d2fface1..956a06c8cdaab 100644
+--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
++++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
+@@ -441,7 +441,7 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw,
+ * when disconnected by peer
+ */
+ if (rtwdev->scanning)
+- rtw89_hw_scan_abort(rtwdev, vif);
++ rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
+ }
+ }
+
+@@ -990,7 +990,7 @@ static int rtw89_ops_remain_on_channel(struct ieee80211_hw *hw,
+ }
+
+ if (rtwdev->scanning)
+- rtw89_hw_scan_abort(rtwdev, vif);
++ rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
+
+ if (type == IEEE80211_ROC_TYPE_MGMT_TX)
+ roc->state = RTW89_ROC_MGMT;
+diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
+index 769f1ce62ebcc..cb03474f81552 100644
+--- a/drivers/net/wireless/realtek/rtw89/pci.c
++++ b/drivers/net/wireless/realtek/rtw89/pci.c
+@@ -155,8 +155,8 @@ static void rtw89_pci_sync_skb_for_device(struct rtw89_dev *rtwdev,
+ DMA_FROM_DEVICE);
+ }
+
+-static int rtw89_pci_rxbd_info_update(struct rtw89_dev *rtwdev,
+- struct sk_buff *skb)
++static void rtw89_pci_rxbd_info_update(struct rtw89_dev *rtwdev,
++ struct sk_buff *skb)
+ {
+ struct rtw89_pci_rxbd_info *rxbd_info;
+ struct rtw89_pci_rx_info *rx_info = RTW89_PCI_RX_SKB_CB(skb);
+@@ -166,10 +166,58 @@ static int rtw89_pci_rxbd_info_update(struct rtw89_dev *rtwdev,
+ rx_info->ls = le32_get_bits(rxbd_info->dword, RTW89_PCI_RXBD_LS);
+ rx_info->len = le32_get_bits(rxbd_info->dword, RTW89_PCI_RXBD_WRITE_SIZE);
+ rx_info->tag = le32_get_bits(rxbd_info->dword, RTW89_PCI_RXBD_TAG);
++}
++
++static int rtw89_pci_validate_rx_tag(struct rtw89_dev *rtwdev,
++ struct rtw89_pci_rx_ring *rx_ring,
++ struct sk_buff *skb)
++{
++ struct rtw89_pci_rx_info *rx_info = RTW89_PCI_RX_SKB_CB(skb);
++ const struct rtw89_pci_info *info = rtwdev->pci_info;
++ u32 target_rx_tag;
++
++ if (!info->check_rx_tag)
++ return 0;
++
++ /* valid range is 1 ~ 0x1FFF */
++ if (rx_ring->target_rx_tag == 0)
++ target_rx_tag = 1;
++ else
++ target_rx_tag = rx_ring->target_rx_tag;
++
++ if (rx_info->tag != target_rx_tag) {
++ rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "mismatch RX tag 0x%x 0x%x\n",
++ rx_info->tag, target_rx_tag);
++ return -EAGAIN;
++ }
+
+ return 0;
+ }
+
++static
++int rtw89_pci_sync_skb_for_device_and_validate_rx_info(struct rtw89_dev *rtwdev,
++ struct rtw89_pci_rx_ring *rx_ring,
++ struct sk_buff *skb)
++{
++ struct rtw89_pci_rx_info *rx_info = RTW89_PCI_RX_SKB_CB(skb);
++ int rx_tag_retry = 100;
++ int ret;
++
++ do {
++ rtw89_pci_sync_skb_for_cpu(rtwdev, skb);
++ rtw89_pci_rxbd_info_update(rtwdev, skb);
++
++ ret = rtw89_pci_validate_rx_tag(rtwdev, rx_ring, skb);
++ if (ret != -EAGAIN)
++ break;
++ } while (rx_tag_retry--);
++
++ /* update target rx_tag for next RX */
++ rx_ring->target_rx_tag = rx_info->tag + 1;
++
++ return ret;
++}
++
+ static void rtw89_pci_ctrl_txdma_ch_pcie(struct rtw89_dev *rtwdev, bool enable)
+ {
+ const struct rtw89_pci_info *info = rtwdev->pci_info;
+@@ -259,9 +307,8 @@ static u32 rtw89_pci_rxbd_deliver_skbs(struct rtw89_dev *rtwdev,
+
+ skb_idx = rtw89_pci_get_rx_skb_idx(rtwdev, bd_ring);
+ skb = rx_ring->buf[skb_idx];
+- rtw89_pci_sync_skb_for_cpu(rtwdev, skb);
+
+- ret = rtw89_pci_rxbd_info_update(rtwdev, skb);
++ ret = rtw89_pci_sync_skb_for_device_and_validate_rx_info(rtwdev, rx_ring, skb);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to update %d RXBD info: %d\n",
+ bd_ring->wp, ret);
+@@ -549,9 +596,8 @@ static u32 rtw89_pci_release_tx_skbs(struct rtw89_dev *rtwdev,
+
+ skb_idx = rtw89_pci_get_rx_skb_idx(rtwdev, bd_ring);
+ skb = rx_ring->buf[skb_idx];
+- rtw89_pci_sync_skb_for_cpu(rtwdev, skb);
+
+- ret = rtw89_pci_rxbd_info_update(rtwdev, skb);
++ ret = rtw89_pci_sync_skb_for_device_and_validate_rx_info(rtwdev, rx_ring, skb);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to update %d RXBD info: %d\n",
+ bd_ring->wp, ret);
+@@ -1550,6 +1596,7 @@ static void rtw89_pci_reset_trx_rings(struct rtw89_dev *rtwdev)
+ bd_ring->rp = 0;
+ rx_ring->diliver_skb = NULL;
+ rx_ring->diliver_desc.ready = false;
++ rx_ring->target_rx_tag = 0;
+
+ rtw89_write16(rtwdev, addr_num, bd_ring->len);
+ rtw89_write32(rtwdev, addr_desa_l, bd_ring->dma);
+@@ -3148,6 +3195,7 @@ static int rtw89_pci_alloc_rx_ring(struct rtw89_dev *rtwdev,
+ rx_ring->buf_sz = buf_sz;
+ rx_ring->diliver_skb = NULL;
+ rx_ring->diliver_desc.ready = false;
++ rx_ring->target_rx_tag = 0;
+
+ for (i = 0; i < len; i++) {
+ skb = dev_alloc_skb(buf_sz);
+diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h
+index ca5de77fee90a..772a84bd8db6b 100644
+--- a/drivers/net/wireless/realtek/rtw89/pci.h
++++ b/drivers/net/wireless/realtek/rtw89/pci.h
+@@ -996,7 +996,7 @@
+ #define RTW89_PCI_TXWD_NUM_MAX 512
+ #define RTW89_PCI_TXWD_PAGE_SIZE 128
+ #define RTW89_PCI_ADDRINFO_MAX 4
+-#define RTW89_PCI_RX_BUF_SIZE 11460
++#define RTW89_PCI_RX_BUF_SIZE (11454 + 40) /* +40 for rtw89_rxdesc_long_v2 */
+
+ #define RTW89_PCI_POLL_BDRAM_RST_CNT 100
+ #define RTW89_PCI_MULTITAG 8
+@@ -1234,6 +1234,7 @@ struct rtw89_pci_info {
+ enum mac_ax_pcie_func_ctrl io_rcy_en;
+ enum mac_ax_io_rcy_tmr io_rcy_tmr;
+ bool rx_ring_eq_is_full;
++ bool check_rx_tag;
+
+ u32 init_cfg_reg;
+ u32 txhci_en_bit;
+@@ -1276,7 +1277,7 @@ struct rtw89_pci_tx_data {
+
+ struct rtw89_pci_rx_info {
+ dma_addr_t dma;
+- u32 fs:1, ls:1, tag:11, len:14;
++ u32 fs:1, ls:1, tag:13, len:14;
+ };
+
+ #define RTW89_PCI_TXBD_OPTION_LS BIT(14)
+@@ -1405,6 +1406,7 @@ struct rtw89_pci_rx_ring {
+ u32 buf_sz;
+ struct sk_buff *diliver_skb;
+ struct rtw89_rx_desc_info diliver_desc;
++ u32 target_rx_tag:13;
+ };
+
+ struct rtw89_pci_isrs {
+diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851be.c b/drivers/net/wireless/realtek/rtw89/rtw8851be.c
+index ade69bd30fc86..ca1374a717272 100644
+--- a/drivers/net/wireless/realtek/rtw89/rtw8851be.c
++++ b/drivers/net/wireless/realtek/rtw89/rtw8851be.c
+@@ -25,6 +25,8 @@ static const struct rtw89_pci_info rtw8851b_pci_info = {
+ .autok_en = MAC_AX_PCIE_DISABLE,
+ .io_rcy_en = MAC_AX_PCIE_DISABLE,
+ .io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_6MS,
++ .rx_ring_eq_is_full = false,
++ .check_rx_tag = false,
+
+ .init_cfg_reg = R_AX_PCIE_INIT_CFG1,
+ .txhci_en_bit = B_AX_TXHCI_EN,
+diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852ae.c b/drivers/net/wireless/realtek/rtw89/rtw8852ae.c
+index f1e890bde0499..7c6ffedb77e27 100644
+--- a/drivers/net/wireless/realtek/rtw89/rtw8852ae.c
++++ b/drivers/net/wireless/realtek/rtw89/rtw8852ae.c
+@@ -26,6 +26,7 @@ static const struct rtw89_pci_info rtw8852a_pci_info = {
+ .io_rcy_en = MAC_AX_PCIE_DISABLE,
+ .io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_6MS,
+ .rx_ring_eq_is_full = false,
++ .check_rx_tag = false,
+
+ .init_cfg_reg = R_AX_PCIE_INIT_CFG1,
+ .txhci_en_bit = B_AX_TXHCI_EN,
+diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852be.c b/drivers/net/wireless/realtek/rtw89/rtw8852be.c
+index 920b20bbcfb73..ed71364e6437b 100644
+--- a/drivers/net/wireless/realtek/rtw89/rtw8852be.c
++++ b/drivers/net/wireless/realtek/rtw89/rtw8852be.c
+@@ -26,6 +26,7 @@ static const struct rtw89_pci_info rtw8852b_pci_info = {
+ .io_rcy_en = MAC_AX_PCIE_DISABLE,
+ .io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_6MS,
+ .rx_ring_eq_is_full = false,
++ .check_rx_tag = false,
+
+ .init_cfg_reg = R_AX_PCIE_INIT_CFG1,
+ .txhci_en_bit = B_AX_TXHCI_EN,
+diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852ce.c b/drivers/net/wireless/realtek/rtw89/rtw8852ce.c
+index 4592de3dbd942..583ea673a4f54 100644
+--- a/drivers/net/wireless/realtek/rtw89/rtw8852ce.c
++++ b/drivers/net/wireless/realtek/rtw89/rtw8852ce.c
+@@ -35,6 +35,7 @@ static const struct rtw89_pci_info rtw8852c_pci_info = {
+ .io_rcy_en = MAC_AX_PCIE_ENABLE,
+ .io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_6MS,
+ .rx_ring_eq_is_full = false,
++ .check_rx_tag = false,
+
+ .init_cfg_reg = R_AX_HAXI_INIT_CFG1,
+ .txhci_en_bit = B_AX_TXHCI_EN_V1,
+diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922ae.c b/drivers/net/wireless/realtek/rtw89/rtw8922ae.c
+index 7b3d98d2c402c..9f46fb1661055 100644
+--- a/drivers/net/wireless/realtek/rtw89/rtw8922ae.c
++++ b/drivers/net/wireless/realtek/rtw89/rtw8922ae.c
+@@ -26,6 +26,7 @@ static const struct rtw89_pci_info rtw8922a_pci_info = {
+ .io_rcy_en = MAC_AX_PCIE_ENABLE,
+ .io_rcy_tmr = MAC_AX_IO_RCY_ANA_TMR_DEF,
+ .rx_ring_eq_is_full = true,
++ .check_rx_tag = true,
+
+ .init_cfg_reg = R_BE_HAXI_INIT_CFG1,
+ .txhci_en_bit = B_BE_TXDMA_EN,
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index e6267a6aa3801..8e0bb9692685d 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -3363,6 +3363,9 @@ static const struct pci_device_id nvme_id_table[] = {
+ NVME_QUIRK_BOGUS_NID, },
+ { PCI_VDEVICE(REDHAT, 0x0010), /* Qemu emulated controller */
+ .driver_data = NVME_QUIRK_BOGUS_NID, },
++ { PCI_DEVICE(0x126f, 0x2262), /* Silicon Motion generic */
++ .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
++ NVME_QUIRK_BOGUS_NID, },
+ { PCI_DEVICE(0x126f, 0x2263), /* Silicon Motion unidentified */
+ .driver_data = NVME_QUIRK_NO_NS_DESC_LIST |
+ NVME_QUIRK_BOGUS_NID, },
+diff --git a/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
+index 636fb79647c8c..481dcc9e8fbf8 100644
+--- a/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
++++ b/drivers/perf/hisilicon/hisi_uncore_uc_pmu.c
+@@ -287,12 +287,52 @@ static u64 hisi_uc_pmu_read_counter(struct hisi_pmu *uc_pmu,
+ return readq(uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx));
+ }
+
+-static void hisi_uc_pmu_write_counter(struct hisi_pmu *uc_pmu,
++static bool hisi_uc_pmu_get_glb_en_state(struct hisi_pmu *uc_pmu)
++{
++ u32 val;
++
++ val = readl(uc_pmu->base + HISI_UC_EVENT_CTRL_REG);
++ return !!FIELD_GET(HISI_UC_EVENT_GLB_EN, val);
++}
++
++static void hisi_uc_pmu_write_counter_normal(struct hisi_pmu *uc_pmu,
+ struct hw_perf_event *hwc, u64 val)
+ {
+ writeq(val, uc_pmu->base + HISI_UC_CNTR_REGn(hwc->idx));
+ }
+
++static void hisi_uc_pmu_write_counter_quirk_v2(struct hisi_pmu *uc_pmu,
++ struct hw_perf_event *hwc, u64 val)
++{
++ hisi_uc_pmu_start_counters(uc_pmu);
++ hisi_uc_pmu_write_counter_normal(uc_pmu, hwc, val);
++ hisi_uc_pmu_stop_counters(uc_pmu);
++}
++
++static void hisi_uc_pmu_write_counter(struct hisi_pmu *uc_pmu,
++ struct hw_perf_event *hwc, u64 val)
++{
++ bool enable = hisi_uc_pmu_get_glb_en_state(uc_pmu);
++ bool erratum = uc_pmu->identifier == HISI_PMU_V2;
++
++ /*
++ * HiSilicon UC PMU v2 suffers the erratum 162700402 that the
++ * PMU counter cannot be set due to the lack of clock under power
++ * saving mode. This will lead to error or inaccurate counts.
++ * The clock can be enabled by the PMU global enabling control.
++ * The irq handler and pmu_start() will call the function to set
++ * period. If the function under irq context, the PMU has been
++ * enabled therefore we set counter directly. Other situations
++ * the PMU is disabled, we need to enable it to turn on the
++ * counter clock to set period, and then restore PMU enable
++ * status, the counter can hold its value without a clock.
++ */
++ if (enable || !erratum)
++ hisi_uc_pmu_write_counter_normal(uc_pmu, hwc, val);
++ else
++ hisi_uc_pmu_write_counter_quirk_v2(uc_pmu, hwc, val);
++}
++
+ static void hisi_uc_pmu_enable_counter_int(struct hisi_pmu *uc_pmu,
+ struct hw_perf_event *hwc)
+ {
+diff --git a/drivers/pinctrl/renesas/core.c b/drivers/pinctrl/renesas/core.c
+index d1e92bbed33ad..757bbc549b0e2 100644
+--- a/drivers/pinctrl/renesas/core.c
++++ b/drivers/pinctrl/renesas/core.c
+@@ -909,9 +909,11 @@ static void __init sh_pfc_check_cfg_reg(const char *drvname,
+ sh_pfc_err("reg 0x%x: var_field_width declares %u instead of %u bits\n",
+ cfg_reg->reg, rw, cfg_reg->reg_width);
+
+- if (n != cfg_reg->nr_enum_ids)
++ if (n != cfg_reg->nr_enum_ids) {
+ sh_pfc_err("reg 0x%x: enum_ids[] has %u instead of %u values\n",
+ cfg_reg->reg, cfg_reg->nr_enum_ids, n);
++ n = cfg_reg->nr_enum_ids;
++ }
+
+ check_enum_ids:
+ sh_pfc_check_reg_enums(drvname, cfg_reg->reg, cfg_reg->enum_ids, n);
+diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
+index 88b826e88ebd7..ee2e164f86b9c 100644
+--- a/drivers/platform/x86/acer-wmi.c
++++ b/drivers/platform/x86/acer-wmi.c
+@@ -276,6 +276,7 @@ static bool has_type_aa;
+ static u16 commun_func_bitmap;
+ static u8 commun_fn_key_number;
+ static bool cycle_gaming_thermal_profile = true;
++static bool predator_v4;
+
+ module_param(mailled, int, 0444);
+ module_param(brightness, int, 0444);
+@@ -284,6 +285,7 @@ module_param(force_series, int, 0444);
+ module_param(force_caps, int, 0444);
+ module_param(ec_raw_mode, bool, 0444);
+ module_param(cycle_gaming_thermal_profile, bool, 0644);
++module_param(predator_v4, bool, 0444);
+ MODULE_PARM_DESC(mailled, "Set initial state of Mail LED");
+ MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness");
+ MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware");
+@@ -292,6 +294,8 @@ MODULE_PARM_DESC(force_caps, "Force the capability bitmask to this value");
+ MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode");
+ MODULE_PARM_DESC(cycle_gaming_thermal_profile,
+ "Set thermal mode key in cycle mode. Disabling it sets the mode key in turbo toggle mode");
++MODULE_PARM_DESC(predator_v4,
++ "Enable features for predator laptops that use predator sense v4");
+
+ struct acer_data {
+ int mailled;
+@@ -584,6 +588,15 @@ static const struct dmi_system_id acer_quirks[] __initconst = {
+ },
+ .driver_data = &quirk_acer_predator_v4,
+ },
++ {
++ .callback = dmi_matched,
++ .ident = "Acer Predator PH16-71",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH16-71"),
++ },
++ .driver_data = &quirk_acer_predator_v4,
++ },
+ {
+ .callback = set_force_caps,
+ .ident = "Acer Aspire Switch 10E SW3-016",
+@@ -725,7 +738,9 @@ enum acer_predator_v4_thermal_profile_wmi {
+ /* Find which quirks are needed for a particular vendor/ model pair */
+ static void __init find_quirks(void)
+ {
+- if (!force_series) {
++ if (predator_v4) {
++ quirks = &quirk_acer_predator_v4;
++ } else if (!force_series) {
+ dmi_check_system(acer_quirks);
+ dmi_check_system(non_acer_quirks);
+ } else if (force_series == 2490) {
+diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c
+index 7457ca2b27a60..9ffbdc988fe50 100644
+--- a/drivers/platform/x86/intel/hid.c
++++ b/drivers/platform/x86/intel/hid.c
+@@ -504,6 +504,7 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
+ struct platform_device *device = context;
+ struct intel_hid_priv *priv = dev_get_drvdata(&device->dev);
+ unsigned long long ev_index;
++ struct key_entry *ke;
+ int err;
+
+ /*
+@@ -545,11 +546,15 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
+ if (event == 0xc0 || !priv->array)
+ return;
+
+- if (!sparse_keymap_entry_from_scancode(priv->array, event)) {
++ ke = sparse_keymap_entry_from_scancode(priv->array, event);
++ if (!ke) {
+ dev_info(&device->dev, "unknown event 0x%x\n", event);
+ return;
+ }
+
++ if (ke->type == KE_IGNORE)
++ return;
++
+ wakeup:
+ pm_wakeup_hard_event(&device->dev);
+
+diff --git a/drivers/platform/x86/intel/vbtn.c b/drivers/platform/x86/intel/vbtn.c
+index 084c355c86f5f..5d13452bb947a 100644
+--- a/drivers/platform/x86/intel/vbtn.c
++++ b/drivers/platform/x86/intel/vbtn.c
+@@ -136,8 +136,6 @@ static int intel_vbtn_input_setup(struct platform_device *device)
+ priv->switches_dev->id.bustype = BUS_HOST;
+
+ if (priv->has_switches) {
+- detect_tablet_mode(&device->dev);
+-
+ ret = input_register_device(priv->switches_dev);
+ if (ret)
+ return ret;
+@@ -316,6 +314,9 @@ static int intel_vbtn_probe(struct platform_device *device)
+ if (ACPI_FAILURE(status))
+ dev_err(&device->dev, "Error VBDL failed with ACPI status %d\n", status);
+ }
++ // Check switches after buttons since VBDL may have side effects.
++ if (has_switches)
++ detect_tablet_mode(&device->dev);
+
+ device_init_wakeup(&device->dev, true);
+ /*
+diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c
+index 975cf24ae359a..c6a10ec2c83f6 100644
+--- a/drivers/platform/x86/touchscreen_dmi.c
++++ b/drivers/platform/x86/touchscreen_dmi.c
+@@ -1217,6 +1217,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
+ DMI_MATCH(DMI_BIOS_VERSION, "CHUWI.D86JLBNR"),
+ },
+ },
++ {
++ /* Chuwi Vi8 dual-boot (CWI506) */
++ .driver_data = (void *)&chuwi_vi8_data,
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "i86"),
++ DMI_MATCH(DMI_BIOS_VERSION, "CHUWI2.D86JHBNR02"),
++ },
++ },
+ {
+ /* Chuwi Vi8 Plus (CWI519) */
+ .driver_data = (void *)&chuwi_vi8_plus_data,
+diff --git a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
+index e3203eb6a0229..a56f7f92d0915 100644
+--- a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
++++ b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
+@@ -55,7 +55,7 @@ struct imx8mp_blk_ctrl_domain_data {
+ const char *gpc_name;
+ };
+
+-#define DOMAIN_MAX_CLKS 2
++#define DOMAIN_MAX_CLKS 3
+ #define DOMAIN_MAX_PATHS 3
+
+ struct imx8mp_blk_ctrl_domain {
+@@ -457,8 +457,8 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
+ },
+ [IMX8MP_HDMIBLK_PD_LCDIF] = {
+ .name = "hdmiblk-lcdif",
+- .clk_names = (const char *[]){ "axi", "apb" },
+- .num_clks = 2,
++ .clk_names = (const char *[]){ "axi", "apb", "fdcc" },
++ .num_clks = 3,
+ .gpc_name = "lcdif",
+ .path_names = (const char *[]){"lcdif-hdmi"},
+ .num_paths = 1,
+@@ -483,8 +483,8 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
+ },
+ [IMX8MP_HDMIBLK_PD_HDMI_TX] = {
+ .name = "hdmiblk-hdmi-tx",
+- .clk_names = (const char *[]){ "apb", "ref_266m" },
+- .num_clks = 2,
++ .clk_names = (const char *[]){ "apb", "ref_266m", "fdcc" },
++ .num_clks = 3,
+ .gpc_name = "hdmi-tx",
+ },
+ [IMX8MP_HDMIBLK_PD_HDMI_TX_PHY] = {
+diff --git a/drivers/pmdomain/ti/omap_prm.c b/drivers/pmdomain/ti/omap_prm.c
+index c2feae3a634ca..b8ceb3c2b81c2 100644
+--- a/drivers/pmdomain/ti/omap_prm.c
++++ b/drivers/pmdomain/ti/omap_prm.c
+@@ -695,6 +695,8 @@ static int omap_prm_domain_init(struct device *dev, struct omap_prm *prm)
+ data = prm->data;
+ name = devm_kasprintf(dev, GFP_KERNEL, "prm_%s",
+ data->name);
++ if (!name)
++ return -ENOMEM;
+
+ prmd->dev = dev;
+ prmd->prm = prm;
+diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
+index d9074929fbab8..b147304b01fa1 100644
+--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
+@@ -748,8 +748,10 @@ lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ /* Save the ELS cmd */
+ elsiocb->drvrTimeout = cmd;
+
+- lpfc_sli4_resume_rpi(ndlp,
+- lpfc_mbx_cmpl_resume_rpi, elsiocb);
++ if (lpfc_sli4_resume_rpi(ndlp,
++ lpfc_mbx_cmpl_resume_rpi,
++ elsiocb))
++ kfree(elsiocb);
+ goto out;
+ }
+ }
+diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c
+index 9ebdd0cd0b1cf..91ab97a456fa9 100644
+--- a/drivers/soundwire/dmi-quirks.c
++++ b/drivers/soundwire/dmi-quirks.c
+@@ -130,6 +130,14 @@ static const struct dmi_system_id adr_remap_quirk_table[] = {
+ },
+ .driver_data = (void *)intel_rooks_county,
+ },
++ {
++ /* quirk used for NUC15 LAPRC710 skew */
++ .matches = {
++ DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
++ DMI_MATCH(DMI_BOARD_NAME, "LAPRC710"),
++ },
++ .driver_data = (void *)intel_rooks_county,
++ },
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
+diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c
+index 4d6c22e0ed85b..61bbd42aa2cb4 100644
+--- a/drivers/thermal/thermal_of.c
++++ b/drivers/thermal/thermal_of.c
+@@ -225,14 +225,18 @@ static int thermal_of_monitor_init(struct device_node *np, int *delay, int *pdel
+ int ret;
+
+ ret = of_property_read_u32(np, "polling-delay-passive", pdelay);
+- if (ret < 0) {
+- pr_err("%pOFn: missing polling-delay-passive property\n", np);
++ if (ret == -EINVAL) {
++ *pdelay = 0;
++ } else if (ret < 0) {
++ pr_err("%pOFn: Couldn't get polling-delay-passive: %d\n", np, ret);
+ return ret;
+ }
+
+ ret = of_property_read_u32(np, "polling-delay", delay);
+- if (ret < 0) {
+- pr_err("%pOFn: missing polling-delay property\n", np);
++ if (ret == -EINVAL) {
++ *delay = 0;
++ } else if (ret < 0) {
++ pr_err("%pOFn: Couldn't get polling-delay: %d\n", np, ret);
+ return ret;
+ }
+
+diff --git a/drivers/thunderbolt/quirks.c b/drivers/thunderbolt/quirks.c
+index e6bfa63b40aee..e81de9c30eac9 100644
+--- a/drivers/thunderbolt/quirks.c
++++ b/drivers/thunderbolt/quirks.c
+@@ -43,6 +43,12 @@ static void quirk_usb3_maximum_bandwidth(struct tb_switch *sw)
+ }
+ }
+
++static void quirk_block_rpm_in_redrive(struct tb_switch *sw)
++{
++ sw->quirks |= QUIRK_KEEP_POWER_IN_DP_REDRIVE;
++ tb_sw_dbg(sw, "preventing runtime PM in DP redrive mode\n");
++}
++
+ struct tb_quirk {
+ u16 hw_vendor_id;
+ u16 hw_device_id;
+@@ -86,6 +92,14 @@ static const struct tb_quirk tb_quirks[] = {
+ quirk_usb3_maximum_bandwidth },
+ { 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HUB_40G_BRIDGE, 0x0000, 0x0000,
+ quirk_usb3_maximum_bandwidth },
++ /*
++ * Block Runtime PM in DP redrive mode for Intel Barlow Ridge host
++ * controllers.
++ */
++ { 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI, 0x0000, 0x0000,
++ quirk_block_rpm_in_redrive },
++ { 0x8087, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI, 0x0000, 0x0000,
++ quirk_block_rpm_in_redrive },
+ /*
+ * CLx is not supported on AMD USB4 Yellow Carp and Pink Sardine platforms.
+ */
+diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
+index 846d2813bb1a5..e6681f153c69d 100644
+--- a/drivers/thunderbolt/tb.c
++++ b/drivers/thunderbolt/tb.c
+@@ -1887,6 +1887,49 @@ static void tb_tunnel_dp(struct tb *tb)
+ ;
+ }
+
++static void tb_enter_redrive(struct tb_port *port)
++{
++ struct tb_switch *sw = port->sw;
++
++ if (!(sw->quirks & QUIRK_KEEP_POWER_IN_DP_REDRIVE))
++ return;
++
++ /*
++ * If we get hot-unplug for the DP IN port of the host router
++ * and the DP resource is not available anymore it means there
++ * is a monitor connected directly to the Type-C port and we are
++ * in "redrive" mode. For this to work we cannot enter RTD3 so
++ * we bump up the runtime PM reference count here.
++ */
++ if (!tb_port_is_dpin(port))
++ return;
++ if (tb_route(sw))
++ return;
++ if (!tb_switch_query_dp_resource(sw, port)) {
++ port->redrive = true;
++ pm_runtime_get(&sw->dev);
++ tb_port_dbg(port, "enter redrive mode, keeping powered\n");
++ }
++}
++
++static void tb_exit_redrive(struct tb_port *port)
++{
++ struct tb_switch *sw = port->sw;
++
++ if (!(sw->quirks & QUIRK_KEEP_POWER_IN_DP_REDRIVE))
++ return;
++
++ if (!tb_port_is_dpin(port))
++ return;
++ if (tb_route(sw))
++ return;
++ if (port->redrive && tb_switch_query_dp_resource(sw, port)) {
++ port->redrive = false;
++ pm_runtime_put(&sw->dev);
++ tb_port_dbg(port, "exit redrive mode\n");
++ }
++}
++
+ static void tb_dp_resource_unavailable(struct tb *tb, struct tb_port *port)
+ {
+ struct tb_port *in, *out;
+@@ -1903,7 +1946,10 @@ static void tb_dp_resource_unavailable(struct tb *tb, struct tb_port *port)
+ }
+
+ tunnel = tb_find_tunnel(tb, TB_TUNNEL_DP, in, out);
+- tb_deactivate_and_free_tunnel(tunnel);
++ if (tunnel)
++ tb_deactivate_and_free_tunnel(tunnel);
++ else
++ tb_enter_redrive(port);
+ list_del_init(&port->list);
+
+ /*
+@@ -1930,6 +1976,7 @@ static void tb_dp_resource_available(struct tb *tb, struct tb_port *port)
+ tb_port_dbg(port, "DP %s resource available after hotplug\n",
+ tb_port_is_dpin(port) ? "IN" : "OUT");
+ list_add_tail(&port->list, &tcm->dp_resources);
++ tb_exit_redrive(port);
+
+ /* Look for suitable DP IN <-> DP OUT pairs now */
+ tb_tunnel_dp(tb);
+diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
+index 997c5a5369052..e4d4effb94447 100644
+--- a/drivers/thunderbolt/tb.h
++++ b/drivers/thunderbolt/tb.h
+@@ -23,6 +23,8 @@
+ #define QUIRK_FORCE_POWER_LINK_CONTROLLER BIT(0)
+ /* Disable CLx if not supported */
+ #define QUIRK_NO_CLX BIT(1)
++/* Need to keep power on while USB4 port is in redrive mode */
++#define QUIRK_KEEP_POWER_IN_DP_REDRIVE BIT(2)
+
+ /**
+ * struct tb_nvm - Structure holding NVM information
+@@ -258,6 +260,7 @@ struct tb_bandwidth_group {
+ * @group_list: The adapter is linked to the group's list of ports through this
+ * @max_bw: Maximum possible bandwidth through this adapter if set to
+ * non-zero.
++ * @redrive: For DP IN, if true the adapter is in redrive mode.
+ *
+ * In USB4 terminology this structure represents an adapter (protocol or
+ * lane adapter).
+@@ -286,6 +289,7 @@ struct tb_port {
+ struct tb_bandwidth_group *group;
+ struct list_head group_list;
+ unsigned int max_bw;
++ bool redrive;
+ };
+
+ /**
+diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c
+index 6fffb2c82d3d1..4f09216b70f90 100644
+--- a/drivers/thunderbolt/tunnel.c
++++ b/drivers/thunderbolt/tunnel.c
+@@ -1196,17 +1196,13 @@ static int tb_dp_consumed_bandwidth(struct tb_tunnel *tunnel, int *consumed_up,
+ /*
+ * Then see if the DPRX negotiation is ready and if yes
+ * return that bandwidth (it may be smaller than the
+- * reduced one). Otherwise return the remote (possibly
+- * reduced) caps.
++ * reduced one). According to VESA spec, the DPRX
++ * negotiation shall compete in 5 seconds after tunnel
++ * established. We give it 100ms extra just in case.
+ */
+- ret = tb_dp_wait_dprx(tunnel, 150);
+- if (ret) {
+- if (ret == -ETIMEDOUT)
+- ret = tb_dp_read_cap(tunnel, DP_REMOTE_CAP,
+- &rate, &lanes);
+- if (ret)
+- return ret;
+- }
++ ret = tb_dp_wait_dprx(tunnel, 5100);
++ if (ret)
++ return ret;
+ ret = tb_dp_read_cap(tunnel, DP_COMMON_CAP, &rate, &lanes);
+ if (ret)
+ return ret;
+diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
+index 34f17a9785e79..9dcc17e332690 100644
+--- a/drivers/tty/serial/8250/8250_of.c
++++ b/drivers/tty/serial/8250/8250_of.c
+@@ -4,7 +4,10 @@
+ *
+ * Copyright (C) 2006 Arnd Bergmann <arnd@arndb.de>, IBM Corp.
+ */
++
++#include <linux/bits.h>
+ #include <linux/console.h>
++#include <linux/math.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/serial_core.h>
+@@ -25,6 +28,36 @@ struct of_serial_info {
+ int line;
+ };
+
++/* Nuvoton NPCM timeout register */
++#define UART_NPCM_TOR 7
++#define UART_NPCM_TOIE BIT(7) /* Timeout Interrupt Enable */
++
++static int npcm_startup(struct uart_port *port)
++{
++ /*
++ * Nuvoton calls the scratch register 'UART_TOR' (timeout
++ * register). Enable it, and set TIOC (timeout interrupt
++ * comparator) to be 0x20 for correct operation.
++ */
++ serial_port_out(port, UART_NPCM_TOR, UART_NPCM_TOIE | 0x20);
++
++ return serial8250_do_startup(port);
++}
++
++/* Nuvoton NPCM UARTs have a custom divisor calculation */
++static unsigned int npcm_get_divisor(struct uart_port *port, unsigned int baud,
++ unsigned int *frac)
++{
++ return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2;
++}
++
++static int npcm_setup(struct uart_port *port)
++{
++ port->get_divisor = npcm_get_divisor;
++ port->startup = npcm_startup;
++ return 0;
++}
++
+ /*
+ * Fill a struct uart_port for a given device node
+ */
+@@ -164,10 +197,17 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
+ switch (type) {
+ case PORT_RT2880:
+ ret = rt288x_setup(port);
+- if (ret)
+- goto err_pmruntime;
++ break;
++ case PORT_NPCM:
++ ret = npcm_setup(port);
++ break;
++ default:
++ /* Nothing to do */
++ ret = 0;
+ break;
+ }
++ if (ret)
++ goto err_pmruntime;
+
+ if (IS_REACHABLE(CONFIG_SERIAL_8250_FSL) &&
+ (of_device_is_compatible(np, "fsl,ns16550") ||
+diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
+index 1d65055dde276..c0c34e410c581 100644
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -38,10 +38,6 @@
+
+ #include "8250.h"
+
+-/* Nuvoton NPCM timeout register */
+-#define UART_NPCM_TOR 7
+-#define UART_NPCM_TOIE BIT(7) /* Timeout Interrupt Enable */
+-
+ /*
+ * Debugging.
+ */
+@@ -2229,15 +2225,6 @@ int serial8250_do_startup(struct uart_port *port)
+ UART_DA830_PWREMU_MGMT_FREE);
+ }
+
+- if (port->type == PORT_NPCM) {
+- /*
+- * Nuvoton calls the scratch register 'UART_TOR' (timeout
+- * register). Enable it, and set TIOC (timeout interrupt
+- * comparator) to be 0x20 for correct operation.
+- */
+- serial_port_out(port, UART_NPCM_TOR, UART_NPCM_TOIE | 0x20);
+- }
+-
+ #ifdef CONFIG_SERIAL_8250_RSA
+ /*
+ * If this is an RSA port, see if we can kick it up to the
+@@ -2539,15 +2526,6 @@ static void serial8250_shutdown(struct uart_port *port)
+ serial8250_do_shutdown(port);
+ }
+
+-/* Nuvoton NPCM UARTs have a custom divisor calculation */
+-static unsigned int npcm_get_divisor(struct uart_8250_port *up,
+- unsigned int baud)
+-{
+- struct uart_port *port = &up->port;
+-
+- return DIV_ROUND_CLOSEST(port->uartclk, 16 * baud + 2) - 2;
+-}
+-
+ static unsigned int serial8250_do_get_divisor(struct uart_port *port,
+ unsigned int baud,
+ unsigned int *frac)
+@@ -2592,8 +2570,6 @@ static unsigned int serial8250_do_get_divisor(struct uart_port *port,
+ quot = 0x8001;
+ else if (magic_multiplier && baud >= port->uartclk / 12)
+ quot = 0x8002;
+- else if (up->port.type == PORT_NPCM)
+- quot = npcm_get_divisor(up, baud);
+ else
+ quot = uart_get_divisor(port, baud);
+
+diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
+index 3d43c7ac7a3f8..f532e2c004a25 100644
+--- a/drivers/ufs/host/ufs-qcom.c
++++ b/drivers/ufs/host/ufs-qcom.c
+@@ -738,8 +738,17 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
+ * the second init can program the optimal PHY settings. This allows one to start
+ * the first init with either the minimum or the maximum support gear.
+ */
+- if (hba->ufshcd_state == UFSHCD_STATE_RESET)
+- host->phy_gear = dev_req_params->gear_tx;
++ if (hba->ufshcd_state == UFSHCD_STATE_RESET) {
++ /*
++ * Skip REINIT if the negotiated gear matches with the
++ * initial phy_gear. Otherwise, update the phy_gear to
++ * program the optimal gear setting during REINIT.
++ */
++ if (host->phy_gear == dev_req_params->gear_tx)
++ hba->quirks &= ~UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH;
++ else
++ host->phy_gear = dev_req_params->gear_tx;
++ }
+
+ /* enable the device ref clock before changing to HS mode */
+ if (!ufshcd_is_hs_mode(&hba->pwr_info) &&
+diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c
+index dd3241fc6939d..53e4cd81ea446 100644
+--- a/drivers/usb/gadget/function/uvc_video.c
++++ b/drivers/usb/gadget/function/uvc_video.c
+@@ -35,6 +35,9 @@ uvc_video_encode_header(struct uvc_video *video, struct uvc_buffer *buf,
+
+ data[1] = UVC_STREAM_EOH | video->fid;
+
++ if (video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE)
++ data[1] |= UVC_STREAM_ERR;
++
+ if (video->queue.buf_used == 0 && ts.tv_sec) {
+ /* dwClockFrequency is 48 MHz */
+ u32 pts = ((u64)ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC) * 48;
+@@ -594,10 +597,7 @@ static void uvcg_video_pump(struct work_struct *work)
+ */
+ spin_lock_irqsave(&queue->irqlock, flags);
+ buf = uvcg_queue_head(queue);
+-
+- if (buf != NULL) {
+- video->encode(req, video, buf);
+- } else {
++ if (!buf) {
+ /*
+ * Either the queue has been disconnected or no video buffer
+ * available for bulk transfer. Either way, stop processing
+@@ -607,6 +607,8 @@ static void uvcg_video_pump(struct work_struct *work)
+ break;
+ }
+
++ video->encode(req, video, buf);
++
+ spin_unlock_irqrestore(&queue->irqlock, flags);
+
+ spin_lock_irqsave(&video->req_lock, flags);
+diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
+index 0956495bba575..2b871540bb500 100644
+--- a/drivers/usb/host/sl811-hcd.c
++++ b/drivers/usb/host/sl811-hcd.c
+@@ -585,6 +585,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank)
+ finish_request(sl811, ep, urb, urbstat);
+ }
+
++#ifdef QUIRK2
+ static inline u8 checkdone(struct sl811 *sl811)
+ {
+ u8 ctl;
+@@ -616,6 +617,7 @@ static inline u8 checkdone(struct sl811 *sl811)
+ #endif
+ return irqstat;
+ }
++#endif
+
+ static irqreturn_t sl811h_irq(struct usb_hcd *hcd)
+ {
+diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
+index 0ee3e6e29bb17..7118551827f6a 100644
+--- a/drivers/usb/typec/tcpm/tcpci.c
++++ b/drivers/usb/typec/tcpm/tcpci.c
+@@ -889,6 +889,7 @@ MODULE_DEVICE_TABLE(i2c, tcpci_id);
+ #ifdef CONFIG_OF
+ static const struct of_device_id tcpci_of_match[] = {
+ { .compatible = "nxp,ptn5110", },
++ { .compatible = "tcpci", },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, tcpci_of_match);
+diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
+index 0bfe5e906e543..cd415565b60a1 100644
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -36,6 +36,19 @@
+ */
+ #define UCSI_SWAP_TIMEOUT_MS 5000
+
++static int ucsi_read_message_in(struct ucsi *ucsi, void *buf,
++ size_t buf_size)
++{
++ /*
++ * Below UCSI 2.0, MESSAGE_IN was limited to 16 bytes. Truncate the
++ * reads here.
++ */
++ if (ucsi->version <= UCSI_VERSION_1_2)
++ buf_size = clamp(buf_size, 0, 16);
++
++ return ucsi->ops->read(ucsi, UCSI_MESSAGE_IN, buf, buf_size);
++}
++
+ static int ucsi_acknowledge_command(struct ucsi *ucsi)
+ {
+ u64 ctrl;
+@@ -72,7 +85,7 @@ static int ucsi_read_error(struct ucsi *ucsi)
+ if (ret < 0)
+ return ret;
+
+- ret = ucsi->ops->read(ucsi, UCSI_MESSAGE_IN, &error, sizeof(error));
++ ret = ucsi_read_message_in(ucsi, &error, sizeof(error));
+ if (ret)
+ return ret;
+
+@@ -174,7 +187,7 @@ int ucsi_send_command(struct ucsi *ucsi, u64 command,
+ length = ret;
+
+ if (data) {
+- ret = ucsi->ops->read(ucsi, UCSI_MESSAGE_IN, data, size);
++ ret = ucsi_read_message_in(ucsi, data, size);
+ if (ret)
+ goto out;
+ }
+@@ -1596,6 +1609,15 @@ int ucsi_register(struct ucsi *ucsi)
+ if (!ucsi->version)
+ return -ENODEV;
+
++ /*
++ * Version format is JJ.M.N (JJ = Major version, M = Minor version,
++ * N = sub-minor version).
++ */
++ dev_dbg(ucsi->dev, "Registered UCSI interface with version %x.%x.%x",
++ UCSI_BCD_GET_MAJOR(ucsi->version),
++ UCSI_BCD_GET_MINOR(ucsi->version),
++ UCSI_BCD_GET_SUBMINOR(ucsi->version));
++
+ queue_delayed_work(system_long_wq, &ucsi->work, 0);
+
+ ucsi_debugfs_register(ucsi);
+diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
+index 4550f3e8cfe9c..ede9876488564 100644
+--- a/drivers/usb/typec/ucsi/ucsi.h
++++ b/drivers/usb/typec/ucsi/ucsi.h
+@@ -23,6 +23,17 @@ struct dentry;
+ #define UCSI_CONTROL 8
+ #define UCSI_MESSAGE_IN 16
+ #define UCSI_MESSAGE_OUT 32
++#define UCSIv2_MESSAGE_OUT 272
++
++/* UCSI versions */
++#define UCSI_VERSION_1_2 0x0120
++#define UCSI_VERSION_2_0 0x0200
++#define UCSI_VERSION_2_1 0x0210
++#define UCSI_VERSION_3_0 0x0300
++
++#define UCSI_BCD_GET_MAJOR(_v_) (((_v_) >> 8) & 0xFF)
++#define UCSI_BCD_GET_MINOR(_v_) (((_v_) >> 4) & 0x0F)
++#define UCSI_BCD_GET_SUBMINOR(_v_) ((_v_) & 0x0F)
+
+ /* Command Status and Connector Change Indication (CCI) bits */
+ #define UCSI_CCI_CONNECTOR(_c_) (((_c_) & GENMASK(7, 1)) >> 1)
+diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c
+index 5d098e71f1bb7..ce08eb33e5bec 100644
+--- a/drivers/usb/typec/ucsi/ucsi_glink.c
++++ b/drivers/usb/typec/ucsi/ucsi_glink.c
+@@ -312,6 +312,7 @@ static void pmic_glink_ucsi_destroy(void *data)
+ }
+
+ static const struct of_device_id pmic_glink_ucsi_of_quirks[] = {
++ { .compatible = "qcom,qcm6490-pmic-glink", .data = (void *)UCSI_NO_PARTNER_PDOS, },
+ { .compatible = "qcom,sc8180x-pmic-glink", .data = (void *)UCSI_NO_PARTNER_PDOS, },
+ { .compatible = "qcom,sc8280xp-pmic-glink", .data = (void *)UCSI_NO_PARTNER_PDOS, },
+ { .compatible = "qcom,sm8350-pmic-glink", .data = (void *)UCSI_NO_PARTNER_PDOS, },
+diff --git a/drivers/video/fbdev/core/fbmon.c b/drivers/video/fbdev/core/fbmon.c
+index 79e5bfbdd34c2..0a26399dbc899 100644
+--- a/drivers/video/fbdev/core/fbmon.c
++++ b/drivers/video/fbdev/core/fbmon.c
+@@ -1311,7 +1311,7 @@ int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, struct fb_inf
+ int fb_videomode_from_videomode(const struct videomode *vm,
+ struct fb_videomode *fbmode)
+ {
+- unsigned int htotal, vtotal;
++ unsigned int htotal, vtotal, total;
+
+ fbmode->xres = vm->hactive;
+ fbmode->left_margin = vm->hback_porch;
+@@ -1344,8 +1344,9 @@ int fb_videomode_from_videomode(const struct videomode *vm,
+ vtotal = vm->vactive + vm->vfront_porch + vm->vback_porch +
+ vm->vsync_len;
+ /* prevent division by zero */
+- if (htotal && vtotal) {
+- fbmode->refresh = vm->pixelclock / (htotal * vtotal);
++ total = htotal * vtotal;
++ if (total) {
++ fbmode->refresh = vm->pixelclock / total;
+ /* a mode must have htotal and vtotal != 0 or it is invalid */
+ } else {
+ fbmode->refresh = 0;
+diff --git a/drivers/video/fbdev/via/accel.c b/drivers/video/fbdev/via/accel.c
+index 0a1bc7a4d7853..1e04026f08091 100644
+--- a/drivers/video/fbdev/via/accel.c
++++ b/drivers/video/fbdev/via/accel.c
+@@ -115,7 +115,7 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height,
+
+ if (op != VIA_BITBLT_FILL) {
+ tmp = src_mem ? 0 : src_addr;
+- if (dst_addr & 0xE0000007) {
++ if (tmp & 0xE0000007) {
+ printk(KERN_WARNING "hw_bitblt_1: Unsupported source "
+ "address %X\n", tmp);
+ return -EINVAL;
+@@ -260,7 +260,7 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height,
+ writel(tmp, engine + 0x18);
+
+ tmp = src_mem ? 0 : src_addr;
+- if (dst_addr & 0xE0000007) {
++ if (tmp & 0xE0000007) {
+ printk(KERN_WARNING "hw_bitblt_2: Unsupported source "
+ "address %X\n", tmp);
+ return -EINVAL;
+diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
+index 976c6cdf9ee67..aaf2514fcfa46 100644
+--- a/drivers/xen/balloon.c
++++ b/drivers/xen/balloon.c
+@@ -672,7 +672,6 @@ EXPORT_SYMBOL(xen_free_ballooned_pages);
+
+ static void __init balloon_add_regions(void)
+ {
+-#if defined(CONFIG_XEN_PV)
+ unsigned long start_pfn, pages;
+ unsigned long pfn, extra_pfn_end;
+ unsigned int i;
+@@ -696,7 +695,6 @@ static void __init balloon_add_regions(void)
+
+ balloon_stats.total_pages += extra_pfn_end - start_pfn;
+ }
+-#endif
+ }
+
+ static int __init balloon_init(void)
+diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
+index 63d4cc338b81a..1ac00ee7959b7 100644
+--- a/fs/btrfs/export.c
++++ b/fs/btrfs/export.c
+@@ -174,8 +174,15 @@ struct dentry *btrfs_get_parent(struct dentry *child)
+ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+ if (ret < 0)
+ goto fail;
++ if (ret == 0) {
++ /*
++ * Key with offset of -1 found, there would have to exist an
++ * inode with such number or a root with such id.
++ */
++ ret = -EUCLEAN;
++ goto fail;
++ }
+
+- BUG_ON(ret == 0); /* Key with offset of -1 found */
+ if (path->slots[0] == 0) {
+ ret = -ENOENT;
+ goto fail;
+diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
+index e9516509b2761..e8187669153dd 100644
+--- a/fs/btrfs/send.c
++++ b/fs/btrfs/send.c
+@@ -1070,7 +1070,15 @@ static int iterate_inode_ref(struct btrfs_root *root, struct btrfs_path *path,
+ ret = PTR_ERR(start);
+ goto out;
+ }
+- BUG_ON(start < p->buf);
++ if (unlikely(start < p->buf)) {
++ btrfs_err(root->fs_info,
++ "send: path ref buffer underflow for key (%llu %u %llu)",
++ found_key->objectid,
++ found_key->type,
++ found_key->offset);
++ ret = -EINVAL;
++ goto out;
++ }
+ }
+ p->start = start;
+ } else {
+diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
+index 5ccbb5f998175..f3890f7c78076 100644
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -3440,7 +3440,17 @@ static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info)
+ mutex_unlock(&fs_info->reclaim_bgs_lock);
+ goto error;
+ }
+- BUG_ON(ret == 0); /* Corruption */
++ if (ret == 0) {
++ /*
++ * On the first search we would find chunk tree with
++ * offset -1, which is not possible. On subsequent
++ * loops this would find an existing item on an invalid
++ * offset (one less than the previous one, wrong
++ * alignment and size).
++ */
++ ret = -EUCLEAN;
++ goto error;
++ }
+
+ ret = btrfs_previous_item(chunk_root, path, key.objectid,
+ key.type);
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index 70836e25418ab..cf407425d0f30 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -3059,7 +3059,10 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v)
+ for (i = 0; i <= 13; i++)
+ seq_printf(seq, " %-5u", i <= blocksize_bits + 1 ?
+ sg.info.bb_counters[i] : 0);
+- seq_puts(seq, " ]\n");
++ seq_puts(seq, " ]");
++ if (EXT4_MB_GRP_BBITMAP_CORRUPT(&sg.info))
++ seq_puts(seq, " Block bitmap corrupted!");
++ seq_puts(seq, "\n");
+
+ return 0;
+ }
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 32bd83adf0bb8..4866657c6d41f 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -6864,6 +6864,10 @@ static int ext4_write_dquot(struct dquot *dquot)
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ ret = dquot_commit(dquot);
++ if (ret < 0)
++ ext4_error_err(dquot->dq_sb, -ret,
++ "Failed to commit dquot type %d",
++ dquot->dq_id.type);
+ err = ext4_journal_stop(handle);
+ if (!ret)
+ ret = err;
+@@ -6880,6 +6884,10 @@ static int ext4_acquire_dquot(struct dquot *dquot)
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ ret = dquot_acquire(dquot);
++ if (ret < 0)
++ ext4_error_err(dquot->dq_sb, -ret,
++ "Failed to acquire dquot type %d",
++ dquot->dq_id.type);
+ err = ext4_journal_stop(handle);
+ if (!ret)
+ ret = err;
+@@ -6899,6 +6907,10 @@ static int ext4_release_dquot(struct dquot *dquot)
+ return PTR_ERR(handle);
+ }
+ ret = dquot_release(dquot);
++ if (ret < 0)
++ ext4_error_err(dquot->dq_sb, -ret,
++ "Failed to release dquot type %d",
++ dquot->dq_id.type);
+ err = ext4_journal_stop(handle);
+ if (!ret)
+ ret = err;
+diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
+index 3e4d53e26f947..379c9edc907cf 100644
+--- a/fs/isofs/inode.c
++++ b/fs/isofs/inode.c
+@@ -908,8 +908,22 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
+ * we then decide whether to use the Joliet descriptor.
+ */
+ inode = isofs_iget(s, sbi->s_firstdatazone, 0);
+- if (IS_ERR(inode))
+- goto out_no_root;
++
++ /*
++ * Fix for broken CDs with a corrupt root inode but a correct Joliet
++ * root directory.
++ */
++ if (IS_ERR(inode)) {
++ if (joliet_level && sbi->s_firstdatazone != first_data_zone) {
++ printk(KERN_NOTICE
++ "ISOFS: root inode is unusable. "
++ "Disabling Rock Ridge and switching to Joliet.");
++ sbi->s_rock = 0;
++ inode = NULL;
++ } else {
++ goto out_no_root;
++ }
++ }
+
+ /*
+ * Fix for broken CDs with Rock Ridge and empty ISO root directory but
+diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
+index bce1d7ac95caa..458519e416fe7 100644
+--- a/fs/kernfs/dir.c
++++ b/fs/kernfs/dir.c
+@@ -529,6 +529,20 @@ void kernfs_get(struct kernfs_node *kn)
+ }
+ EXPORT_SYMBOL_GPL(kernfs_get);
+
++static void kernfs_free_rcu(struct rcu_head *rcu)
++{
++ struct kernfs_node *kn = container_of(rcu, struct kernfs_node, rcu);
++
++ kfree_const(kn->name);
++
++ if (kn->iattr) {
++ simple_xattrs_free(&kn->iattr->xattrs, NULL);
++ kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
++ }
++
++ kmem_cache_free(kernfs_node_cache, kn);
++}
++
+ /**
+ * kernfs_put - put a reference count on a kernfs_node
+ * @kn: the target kernfs_node
+@@ -557,16 +571,11 @@ void kernfs_put(struct kernfs_node *kn)
+ if (kernfs_type(kn) == KERNFS_LINK)
+ kernfs_put(kn->symlink.target_kn);
+
+- kfree_const(kn->name);
+-
+- if (kn->iattr) {
+- simple_xattrs_free(&kn->iattr->xattrs, NULL);
+- kmem_cache_free(kernfs_iattrs_cache, kn->iattr);
+- }
+ spin_lock(&kernfs_idr_lock);
+ idr_remove(&root->ino_idr, (u32)kernfs_ino(kn));
+ spin_unlock(&kernfs_idr_lock);
+- kmem_cache_free(kernfs_node_cache, kn);
++
++ call_rcu(&kn->rcu, kernfs_free_rcu);
+
+ kn = parent;
+ if (kn) {
+@@ -575,7 +584,7 @@ void kernfs_put(struct kernfs_node *kn)
+ } else {
+ /* just released the root kn, free @root too */
+ idr_destroy(&root->ino_idr);
+- kfree(root);
++ kfree_rcu(root, rcu);
+ }
+ }
+ EXPORT_SYMBOL_GPL(kernfs_put);
+@@ -715,7 +724,7 @@ struct kernfs_node *kernfs_find_and_get_node_by_id(struct kernfs_root *root,
+ ino_t ino = kernfs_id_ino(id);
+ u32 gen = kernfs_id_gen(id);
+
+- spin_lock(&kernfs_idr_lock);
++ rcu_read_lock();
+
+ kn = idr_find(&root->ino_idr, (u32)ino);
+ if (!kn)
+@@ -739,10 +748,10 @@ struct kernfs_node *kernfs_find_and_get_node_by_id(struct kernfs_root *root,
+ if (unlikely(!__kernfs_active(kn) || !atomic_inc_not_zero(&kn->count)))
+ goto err_unlock;
+
+- spin_unlock(&kernfs_idr_lock);
++ rcu_read_unlock();
+ return kn;
+ err_unlock:
+- spin_unlock(&kernfs_idr_lock);
++ rcu_read_unlock();
+ return NULL;
+ }
+
+diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h
+index 237f2764b9412..b42ee6547cdc1 100644
+--- a/fs/kernfs/kernfs-internal.h
++++ b/fs/kernfs/kernfs-internal.h
+@@ -49,6 +49,8 @@ struct kernfs_root {
+ struct rw_semaphore kernfs_rwsem;
+ struct rw_semaphore kernfs_iattr_rwsem;
+ struct rw_semaphore kernfs_supers_rwsem;
++
++ struct rcu_head rcu;
+ };
+
+ /* +1 to avoid triggering overflow warning when negating it */
+diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c
+index 5254256a224d7..4ca8ed410c3cf 100644
+--- a/fs/orangefs/super.c
++++ b/fs/orangefs/super.c
+@@ -527,7 +527,7 @@ struct dentry *orangefs_mount(struct file_system_type *fst,
+ sb->s_fs_info = kzalloc(sizeof(struct orangefs_sb_info_s), GFP_KERNEL);
+ if (!ORANGEFS_SB(sb)) {
+ d = ERR_PTR(-ENOMEM);
+- goto free_sb_and_op;
++ goto free_op;
+ }
+
+ ret = orangefs_fill_sb(sb,
+diff --git a/fs/pstore/zone.c b/fs/pstore/zone.c
+index 2770746bb7aa1..abca117725c81 100644
+--- a/fs/pstore/zone.c
++++ b/fs/pstore/zone.c
+@@ -973,6 +973,8 @@ static ssize_t psz_kmsg_read(struct pstore_zone *zone,
+ char *buf = kasprintf(GFP_KERNEL, "%s: Total %d times\n",
+ kmsg_dump_reason_str(record->reason),
+ record->count);
++ if (!buf)
++ return -ENOMEM;
+ hlen = strlen(buf);
+ record->buf = krealloc(buf, hlen + size, GFP_KERNEL);
+ if (!record->buf) {
+diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c
+index 410ab2a44d2f6..19bcb51a22036 100644
+--- a/fs/sysv/itree.c
++++ b/fs/sysv/itree.c
+@@ -83,9 +83,6 @@ static inline sysv_zone_t *block_end(struct buffer_head *bh)
+ return (sysv_zone_t*)((char*)bh->b_data + bh->b_size);
+ }
+
+-/*
+- * Requires read_lock(&pointers_lock) or write_lock(&pointers_lock)
+- */
+ static Indirect *get_branch(struct inode *inode,
+ int depth,
+ int offsets[],
+@@ -105,15 +102,18 @@ static Indirect *get_branch(struct inode *inode,
+ bh = sb_bread(sb, block);
+ if (!bh)
+ goto failure;
++ read_lock(&pointers_lock);
+ if (!verify_chain(chain, p))
+ goto changed;
+ add_chain(++p, bh, (sysv_zone_t*)bh->b_data + *++offsets);
++ read_unlock(&pointers_lock);
+ if (!p->key)
+ goto no_block;
+ }
+ return NULL;
+
+ changed:
++ read_unlock(&pointers_lock);
+ brelse(bh);
+ *err = -EAGAIN;
+ goto no_block;
+@@ -219,9 +219,7 @@ static int get_block(struct inode *inode, sector_t iblock, struct buffer_head *b
+ goto out;
+
+ reread:
+- read_lock(&pointers_lock);
+ partial = get_branch(inode, depth, offsets, chain, &err);
+- read_unlock(&pointers_lock);
+
+ /* Simplest case - block found, no allocation needed */
+ if (!partial) {
+@@ -291,9 +289,9 @@ static Indirect *find_shared(struct inode *inode,
+ *top = 0;
+ for (k = depth; k > 1 && !offsets[k-1]; k--)
+ ;
++ partial = get_branch(inode, k, offsets, chain, &err);
+
+ write_lock(&pointers_lock);
+- partial = get_branch(inode, k, offsets, chain, &err);
+ if (!partial)
+ partial = chain + k-1;
+ /*
+diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
+index e4d24d3f9abb5..446225aada50d 100644
+--- a/include/acpi/acpi_bus.h
++++ b/include/acpi/acpi_bus.h
+@@ -749,6 +749,7 @@ bool acpi_device_override_status(struct acpi_device *adev, unsigned long long *s
+ bool acpi_quirk_skip_acpi_ac_and_battery(void);
+ int acpi_install_cmos_rtc_space_handler(acpi_handle handle);
+ void acpi_remove_cmos_rtc_space_handler(acpi_handle handle);
++int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip);
+ #else
+ static inline bool acpi_device_override_status(struct acpi_device *adev,
+ unsigned long long *status)
+@@ -766,23 +767,22 @@ static inline int acpi_install_cmos_rtc_space_handler(acpi_handle handle)
+ static inline void acpi_remove_cmos_rtc_space_handler(acpi_handle handle)
+ {
+ }
++static inline int
++acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
++{
++ *skip = false;
++ return 0;
++}
+ #endif
+
+ #if IS_ENABLED(CONFIG_X86_ANDROID_TABLETS)
+ bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev);
+-int acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip);
+ bool acpi_quirk_skip_gpio_event_handlers(void);
+ #else
+ static inline bool acpi_quirk_skip_i2c_client_enumeration(struct acpi_device *adev)
+ {
+ return false;
+ }
+-static inline int
+-acpi_quirk_skip_serdev_enumeration(struct device *controller_parent, bool *skip)
+-{
+- *skip = false;
+- return 0;
+-}
+ static inline bool acpi_quirk_skip_gpio_event_handlers(void)
+ {
+ return false;
+diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h
+index 99aaa050ccb76..e857a150babc6 100644
+--- a/include/linux/kernfs.h
++++ b/include/linux/kernfs.h
+@@ -223,6 +223,8 @@ struct kernfs_node {
+ unsigned short flags;
+ umode_t mode;
+ struct kernfs_iattrs *iattr;
++
++ struct rcu_head rcu;
+ };
+
+ /*
+diff --git a/include/linux/overflow.h b/include/linux/overflow.h
+index 7b5cf4a5cd191..51af56522915e 100644
+--- a/include/linux/overflow.h
++++ b/include/linux/overflow.h
+@@ -31,8 +31,10 @@
+ * credit to Christian Biere.
+ */
+ #define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
+-#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
+-#define type_min(T) ((T)((T)-type_max(T)-(T)1))
++#define __type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
++#define type_max(t) __type_max(typeof(t))
++#define __type_min(T) ((T)((T)-type_max(T)-(T)1))
++#define type_min(t) __type_min(typeof(t))
+
+ /*
+ * Avoids triggering -Wtype-limits compilation warning,
+@@ -130,10 +132,10 @@ static inline bool __must_check __must_check_overflow(bool overflow)
+
+ #define __overflows_type_constexpr(x, T) ( \
+ is_unsigned_type(typeof(x)) ? \
+- (x) > type_max(typeof(T)) : \
++ (x) > type_max(T) : \
+ is_unsigned_type(typeof(T)) ? \
+- (x) < 0 || (x) > type_max(typeof(T)) : \
+- (x) < type_min(typeof(T)) || (x) > type_max(typeof(T)))
++ (x) < 0 || (x) > type_max(T) : \
++ (x) < type_min(T) || (x) > type_max(T))
+
+ #define __overflows_type(x, T) ({ \
+ typeof(T) v = 0; \
+diff --git a/include/linux/printk.h b/include/linux/printk.h
+index 8ef499ab3c1ed..955e31860095e 100644
+--- a/include/linux/printk.h
++++ b/include/linux/printk.h
+@@ -273,6 +273,8 @@ static inline void printk_trigger_flush(void)
+ }
+ #endif
+
++bool this_cpu_in_panic(void);
++
+ #ifdef CONFIG_SMP
+ extern int __printk_cpu_sync_try_get(void);
+ extern void __printk_cpu_sync_wait(void);
+diff --git a/include/linux/randomize_kstack.h b/include/linux/randomize_kstack.h
+index 5d868505a94e4..6d92b68efbf6c 100644
+--- a/include/linux/randomize_kstack.h
++++ b/include/linux/randomize_kstack.h
+@@ -80,7 +80,7 @@ DECLARE_PER_CPU(u32, kstack_offset);
+ if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \
+ &randomize_kstack_offset)) { \
+ u32 offset = raw_cpu_read(kstack_offset); \
+- offset ^= (rand); \
++ offset = ror32(offset, 5) ^ (rand); \
+ raw_cpu_write(kstack_offset, offset); \
+ } \
+ } while (0)
+diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
+index 9d69e4bd6f0a8..17d7ed5f3ae6e 100644
+--- a/include/linux/rcupdate.h
++++ b/include/linux/rcupdate.h
+@@ -184,9 +184,9 @@ void rcu_tasks_trace_qs_blkd(struct task_struct *t);
+ do { \
+ int ___rttq_nesting = READ_ONCE((t)->trc_reader_nesting); \
+ \
+- if (likely(!READ_ONCE((t)->trc_reader_special.b.need_qs)) && \
++ if (unlikely(READ_ONCE((t)->trc_reader_special.b.need_qs) == TRC_NEED_QS) && \
+ likely(!___rttq_nesting)) { \
+- rcu_trc_cmpxchg_need_qs((t), 0, TRC_NEED_QS_CHECKED); \
++ rcu_trc_cmpxchg_need_qs((t), TRC_NEED_QS, TRC_NEED_QS_CHECKED); \
+ } else if (___rttq_nesting && ___rttq_nesting != INT_MIN && \
+ !READ_ONCE((t)->trc_reader_special.b.blocked)) { \
+ rcu_tasks_trace_qs_blkd(t); \
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index 227f4514476b1..5bafcfe18be61 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -2637,6 +2637,8 @@ static inline void skb_put_u8(struct sk_buff *skb, u8 val)
+ void *skb_push(struct sk_buff *skb, unsigned int len);
+ static inline void *__skb_push(struct sk_buff *skb, unsigned int len)
+ {
++ DEBUG_NET_WARN_ON_ONCE(len > INT_MAX);
++
+ skb->data -= len;
+ skb->len += len;
+ return skb->data;
+@@ -2645,6 +2647,8 @@ static inline void *__skb_push(struct sk_buff *skb, unsigned int len)
+ void *skb_pull(struct sk_buff *skb, unsigned int len);
+ static inline void *__skb_pull(struct sk_buff *skb, unsigned int len)
+ {
++ DEBUG_NET_WARN_ON_ONCE(len > INT_MAX);
++
+ skb->len -= len;
+ if (unlikely(skb->len < skb->data_len)) {
+ #if defined(CONFIG_DEBUG_NET)
+@@ -2669,6 +2673,8 @@ void *__pskb_pull_tail(struct sk_buff *skb, int delta);
+ static inline enum skb_drop_reason
+ pskb_may_pull_reason(struct sk_buff *skb, unsigned int len)
+ {
++ DEBUG_NET_WARN_ON_ONCE(len > INT_MAX);
++
+ if (likely(len <= skb_headlen(skb)))
+ return SKB_NOT_DROPPED_YET;
+
+@@ -2841,6 +2847,11 @@ static inline void skb_set_inner_network_header(struct sk_buff *skb,
+ skb->inner_network_header += offset;
+ }
+
++static inline bool skb_inner_network_header_was_set(const struct sk_buff *skb)
++{
++ return skb->inner_network_header > 0;
++}
++
+ static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb)
+ {
+ return skb->head + skb->inner_mac_header;
+diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
+index 2d61987b35456..0c77ba488bbae 100644
+--- a/include/linux/sunrpc/sched.h
++++ b/include/linux/sunrpc/sched.h
+@@ -197,7 +197,7 @@ struct rpc_wait_queue {
+ unsigned char maxpriority; /* maximum priority (0 if queue is not a priority queue) */
+ unsigned char priority; /* current priority */
+ unsigned char nr; /* # tasks remaining for cookie */
+- unsigned short qlen; /* total # tasks waiting in queue */
++ unsigned int qlen; /* total # tasks waiting in queue */
+ struct rpc_timer timer_list;
+ #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) || IS_ENABLED(CONFIG_TRACEPOINTS)
+ const char * name;
+diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
+index 03e68a8e229f5..35c5f75a3a5ee 100644
+--- a/include/net/bluetooth/hci.h
++++ b/include/net/bluetooth/hci.h
+@@ -339,6 +339,14 @@ enum {
+ * during the hdev->setup vendor callback.
+ */
+ HCI_QUIRK_BROKEN_LE_CODED,
++
++ /*
++ * When this quirk is set, the HCI_OP_READ_ENC_KEY_SIZE command is
++ * skipped during an HCI_EV_ENCRYPT_CHANGE event. This is required
++ * for Actions Semiconductor ATS2851 based controllers, which erroneously
++ * claim to support it.
++ */
++ HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE,
+ };
+
+ /* HCI device flags */
+diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h
+index 022a520e31fc2..03edf2ccdf6c8 100644
+--- a/include/uapi/linux/input-event-codes.h
++++ b/include/uapi/linux/input-event-codes.h
+@@ -602,6 +602,7 @@
+
+ #define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */
+ #define KEY_ROTATE_LOCK_TOGGLE 0x231 /* Display rotation lock */
++#define KEY_REFRESH_RATE_TOGGLE 0x232 /* Display refresh rate toggle */
+
+ #define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */
+ #define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index 572effd0af532..0f52ea80103ef 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -2143,6 +2143,13 @@ static void io_init_req_drain(struct io_kiocb *req)
+ }
+ }
+
++static __cold int io_init_fail_req(struct io_kiocb *req, int err)
++{
++ /* ensure per-opcode data is cleared if we fail before prep */
++ memset(&req->cmd.data, 0, sizeof(req->cmd.data));
++ return err;
++}
++
+ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
+ const struct io_uring_sqe *sqe)
+ __must_hold(&ctx->uring_lock)
+@@ -2163,29 +2170,29 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
+
+ if (unlikely(opcode >= IORING_OP_LAST)) {
+ req->opcode = 0;
+- return -EINVAL;
++ return io_init_fail_req(req, -EINVAL);
+ }
+ def = &io_issue_defs[opcode];
+ if (unlikely(sqe_flags & ~SQE_COMMON_FLAGS)) {
+ /* enforce forwards compatibility on users */
+ if (sqe_flags & ~SQE_VALID_FLAGS)
+- return -EINVAL;
++ return io_init_fail_req(req, -EINVAL);
+ if (sqe_flags & IOSQE_BUFFER_SELECT) {
+ if (!def->buffer_select)
+- return -EOPNOTSUPP;
++ return io_init_fail_req(req, -EOPNOTSUPP);
+ req->buf_index = READ_ONCE(sqe->buf_group);
+ }
+ if (sqe_flags & IOSQE_CQE_SKIP_SUCCESS)
+ ctx->drain_disabled = true;
+ if (sqe_flags & IOSQE_IO_DRAIN) {
+ if (ctx->drain_disabled)
+- return -EOPNOTSUPP;
++ return io_init_fail_req(req, -EOPNOTSUPP);
+ io_init_req_drain(req);
+ }
+ }
+ if (unlikely(ctx->restricted || ctx->drain_active || ctx->drain_next)) {
+ if (ctx->restricted && !io_check_restriction(ctx, req, sqe_flags))
+- return -EACCES;
++ return io_init_fail_req(req, -EACCES);
+ /* knock it to the slow queue path, will be drained there */
+ if (ctx->drain_active)
+ req->flags |= REQ_F_FORCE_ASYNC;
+@@ -2198,9 +2205,9 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
+ }
+
+ if (!def->ioprio && sqe->ioprio)
+- return -EINVAL;
++ return io_init_fail_req(req, -EINVAL);
+ if (!def->iopoll && (ctx->flags & IORING_SETUP_IOPOLL))
+- return -EINVAL;
++ return io_init_fail_req(req, -EINVAL);
+
+ if (def->needs_file) {
+ struct io_submit_state *state = &ctx->submit_state;
+@@ -2224,12 +2231,12 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
+
+ req->creds = xa_load(&ctx->personalities, personality);
+ if (!req->creds)
+- return -EINVAL;
++ return io_init_fail_req(req, -EINVAL);
+ get_cred(req->creds);
+ ret = security_uring_override_creds(req->creds);
+ if (ret) {
+ put_cred(req->creds);
+- return ret;
++ return io_init_fail_req(req, ret);
+ }
+ req->flags |= REQ_F_CREDS;
+ }
+diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
+index 98b2e192fd696..4d543b1e9d577 100644
+--- a/kernel/dma/direct.c
++++ b/kernel/dma/direct.c
+@@ -286,7 +286,7 @@ void *dma_direct_alloc(struct device *dev, size_t size,
+ } else {
+ ret = page_address(page);
+ if (dma_set_decrypted(dev, ret, size))
+- goto out_free_pages;
++ goto out_leak_pages;
+ }
+
+ memset(ret, 0, size);
+@@ -307,6 +307,8 @@ void *dma_direct_alloc(struct device *dev, size_t size,
+ out_free_pages:
+ __dma_direct_free_pages(dev, page, size);
+ return NULL;
++out_leak_pages:
++ return NULL;
+ }
+
+ void dma_direct_free(struct device *dev, size_t size,
+@@ -367,12 +369,11 @@ struct page *dma_direct_alloc_pages(struct device *dev, size_t size,
+
+ ret = page_address(page);
+ if (dma_set_decrypted(dev, ret, size))
+- goto out_free_pages;
++ goto out_leak_pages;
+ memset(ret, 0, size);
+ *dma_handle = phys_to_dma_direct(dev, page_to_phys(page));
+ return page;
+-out_free_pages:
+- __dma_direct_free_pages(dev, page, size);
++out_leak_pages:
+ return NULL;
+ }
+
+diff --git a/kernel/panic.c b/kernel/panic.c
+index 2807639aab51d..f22d8f33ea147 100644
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -446,6 +446,14 @@ void panic(const char *fmt, ...)
+
+ /* Do not scroll important messages printed above */
+ suppress_printk = 1;
++
++ /*
++ * The final messages may not have been printed if in a context that
++ * defers printing (such as NMI) and irq_work is not available.
++ * Explicitly flush the kernel log buffer one last time.
++ */
++ console_flush_on_panic(CONSOLE_FLUSH_PENDING);
++
+ local_irq_enable();
+ for (i = 0; ; i += PANIC_TIMER_STEP) {
+ touch_softlockup_watchdog();
+diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h
+index ac2d9750e5f81..6c2afee5ef620 100644
+--- a/kernel/printk/internal.h
++++ b/kernel/printk/internal.h
+@@ -130,7 +130,6 @@ struct printk_message {
+ };
+
+ bool other_cpu_in_panic(void);
+-bool this_cpu_in_panic(void);
+ bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
+ bool is_extended, bool may_supress);
+
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index 7a835b277e98d..e1b992652ab25 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2328,8 +2328,7 @@ asmlinkage int vprintk_emit(int facility, int level,
+ if (unlikely(suppress_printk))
+ return 0;
+
+- if (unlikely(suppress_panic_printk) &&
+- atomic_read(&panic_cpu) != raw_smp_processor_id())
++ if (unlikely(suppress_panic_printk) && other_cpu_in_panic())
+ return 0;
+
+ if (level == LOGLEVEL_SCHED) {
+diff --git a/kernel/rcu/tree_nocb.h b/kernel/rcu/tree_nocb.h
+index 4efbf7333d4e1..d430b4656f59e 100644
+--- a/kernel/rcu/tree_nocb.h
++++ b/kernel/rcu/tree_nocb.h
+@@ -1383,7 +1383,7 @@ lazy_rcu_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
+ rcu_nocb_unlock_irqrestore(rdp, flags);
+ continue;
+ }
+- WARN_ON_ONCE(!rcu_nocb_flush_bypass(rdp, NULL, jiffies, false));
++ rcu_nocb_try_flush_bypass(rdp, jiffies);
+ rcu_nocb_unlock_irqrestore(rdp, flags);
+ wake_nocb_gp(rdp, false);
+ sc->nr_to_scan -= _count;
+diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
+index 43060a7ae15e7..2ad234366d21c 100644
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -4395,7 +4395,7 @@ int ring_buffer_iter_empty(struct ring_buffer_iter *iter)
+ cpu_buffer = iter->cpu_buffer;
+ reader = cpu_buffer->reader_page;
+ head_page = cpu_buffer->head_page;
+- commit_page = cpu_buffer->commit_page;
++ commit_page = READ_ONCE(cpu_buffer->commit_page);
+ commit_ts = commit_page->page->time_stamp;
+
+ /*
+diff --git a/lib/dump_stack.c b/lib/dump_stack.c
+index 83471e81501a7..222c6d6c8281a 100644
+--- a/lib/dump_stack.c
++++ b/lib/dump_stack.c
+@@ -96,15 +96,25 @@ static void __dump_stack(const char *log_lvl)
+ */
+ asmlinkage __visible void dump_stack_lvl(const char *log_lvl)
+ {
++ bool in_panic = this_cpu_in_panic();
+ unsigned long flags;
+
+ /*
+ * Permit this cpu to perform nested stack dumps while serialising
+- * against other CPUs
++ * against other CPUs, unless this CPU is in panic.
++ *
++ * When in panic, non-panic CPUs are not permitted to store new
++ * printk messages so there is no need to synchronize the output.
++ * This avoids potential deadlock in panic() if another CPU is
++ * holding and unable to release the printk_cpu_sync.
+ */
+- printk_cpu_sync_get_irqsave(flags);
++ if (!in_panic)
++ printk_cpu_sync_get_irqsave(flags);
++
+ __dump_stack(log_lvl);
+- printk_cpu_sync_put_irqrestore(flags);
++
++ if (!in_panic)
++ printk_cpu_sync_put_irqrestore(flags);
+ }
+ EXPORT_SYMBOL(dump_stack_lvl);
+
+diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
+index 3b63513f57ba8..3992e18f0babb 100644
+--- a/net/bluetooth/hci_event.c
++++ b/net/bluetooth/hci_event.c
+@@ -3679,7 +3679,8 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
+ * controller really supports it. If it doesn't, assume
+ * the default size (16).
+ */
+- if (!(hdev->commands[20] & 0x10)) {
++ if (!(hdev->commands[20] & 0x10) ||
++ test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks)) {
+ conn->enc_key_size = HCI_LINK_KEY_SIZE;
+ goto notify;
+ }
+diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
+index fd98936da3aec..918b109e0cf40 100644
+--- a/net/core/netdev-genl.c
++++ b/net/core/netdev-genl.c
+@@ -152,10 +152,7 @@ int netdev_nl_dev_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+ }
+ rtnl_unlock();
+
+- if (err != -EMSGSIZE)
+- return err;
+-
+- return skb->len;
++ return err;
+ }
+
+ static int
+@@ -287,10 +284,7 @@ int netdev_nl_napi_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+ }
+ rtnl_unlock();
+
+- if (err != -EMSGSIZE)
+- return err;
+-
+- return skb->len;
++ return err;
+ }
+
+ static int
+@@ -463,10 +457,7 @@ int netdev_nl_queue_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+ }
+ rtnl_unlock();
+
+- if (err != -EMSGSIZE)
+- return err;
+-
+- return skb->len;
++ return err;
+ }
+
+ static int netdev_genl_netdevice_event(struct notifier_block *nb,
+diff --git a/net/core/page_pool_user.c b/net/core/page_pool_user.c
+index 278294aca66ab..3a3277ba167b1 100644
+--- a/net/core/page_pool_user.c
++++ b/net/core/page_pool_user.c
+@@ -103,8 +103,6 @@ netdev_nl_page_pool_get_dump(struct sk_buff *skb, struct netlink_callback *cb,
+ mutex_unlock(&page_pools_lock);
+ rtnl_unlock();
+
+- if (skb->len && err == -EMSGSIZE)
+- return skb->len;
+ return err;
+ }
+
+diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
+index 7af36e4f1647d..55039191b8d2b 100644
+--- a/net/ipv4/ip_tunnel.c
++++ b/net/ipv4/ip_tunnel.c
+@@ -1298,6 +1298,7 @@ int ip_tunnel_init(struct net_device *dev)
+
+ if (tunnel->collect_md)
+ netif_keep_dst(dev);
++ netdev_lockdep_set_classes(dev);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(ip_tunnel_init);
+diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
+index 26c3287beb29c..289b83347d9d5 100644
+--- a/net/ipv6/ip6_gre.c
++++ b/net/ipv6/ip6_gre.c
+@@ -1514,6 +1514,7 @@ static int ip6gre_tunnel_init_common(struct net_device *dev)
+ ip6gre_tnl_init_features(dev);
+
+ netdev_hold(dev, &tunnel->dev_tracker, GFP_KERNEL);
++ netdev_lockdep_set_classes(dev);
+ return 0;
+
+ cleanup_dst_cache_init:
+@@ -1906,6 +1907,7 @@ static int ip6erspan_tap_init(struct net_device *dev)
+ ip6erspan_tnl_link_config(tunnel, 1);
+
+ netdev_hold(dev, &tunnel->dev_tracker, GFP_KERNEL);
++ netdev_lockdep_set_classes(dev);
+ return 0;
+
+ cleanup_dst_cache_init:
+diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
+index 9bbabf750a21e..70478027a7af7 100644
+--- a/net/ipv6/ip6_tunnel.c
++++ b/net/ipv6/ip6_tunnel.c
+@@ -1898,6 +1898,7 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
+ dev->max_mtu = IP6_MAX_MTU - dev->hard_header_len;
+
+ netdev_hold(dev, &t->dev_tracker, GFP_KERNEL);
++ netdev_lockdep_set_classes(dev);
+ return 0;
+
+ destroy_dst:
+diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
+index e550240c85e1c..1163ca6ea4af1 100644
+--- a/net/ipv6/ip6_vti.c
++++ b/net/ipv6/ip6_vti.c
+@@ -935,6 +935,7 @@ static inline int vti6_dev_init_gen(struct net_device *dev)
+ if (!dev->tstats)
+ return -ENOMEM;
+ netdev_hold(dev, &t->dev_tracker, GFP_KERNEL);
++ netdev_lockdep_set_classes(dev);
+ return 0;
+ }
+
+diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
+index 5e9f625b76e36..fbad6e1c970e4 100644
+--- a/net/ipv6/sit.c
++++ b/net/ipv6/sit.c
+@@ -1460,6 +1460,7 @@ static int ipip6_tunnel_init(struct net_device *dev)
+ return err;
+ }
+ netdev_hold(dev, &tunnel->dev_tracker, GFP_KERNEL);
++ netdev_lockdep_set_classes(dev);
+ return 0;
+ }
+
+diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c
+index 533d082f0701e..45d1e6a157fc7 100644
+--- a/net/mpls/mpls_gso.c
++++ b/net/mpls/mpls_gso.c
+@@ -27,6 +27,9 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
+ __be16 mpls_protocol;
+ unsigned int mpls_hlen;
+
++ if (!skb_inner_network_header_was_set(skb))
++ goto out;
++
+ skb_reset_network_header(skb);
+ mpls_hlen = skb_inner_network_header(skb) - skb_network_header(skb);
+ if (unlikely(!mpls_hlen || mpls_hlen % MPLS_HLEN))
+diff --git a/net/smc/smc_pnet.c b/net/smc/smc_pnet.c
+index 9f2c58c5a86b7..2adb92b8c4699 100644
+--- a/net/smc/smc_pnet.c
++++ b/net/smc/smc_pnet.c
+@@ -806,6 +806,16 @@ static void smc_pnet_create_pnetids_list(struct net *net)
+ u8 ndev_pnetid[SMC_MAX_PNETID_LEN];
+ struct net_device *dev;
+
++ /* Newly created netns do not have devices.
++ * Do not even acquire rtnl.
++ */
++ if (list_empty(&net->dev_base_head))
++ return;
++
++ /* Note: This might not be needed, because smc_pnet_netdev_event()
++ * is also calling smc_pnet_add_base_pnetid() when handling
++ * NETDEV_UP event.
++ */
+ rtnl_lock();
+ for_each_netdev(net, dev)
+ smc_pnet_add_base_pnetid(net, dev, ndev_pnetid);
+diff --git a/net/wireless/util.c b/net/wireless/util.c
+index d1ce3bee27973..b9d15f369378b 100644
+--- a/net/wireless/util.c
++++ b/net/wireless/util.c
+@@ -791,15 +791,19 @@ ieee80211_amsdu_subframe_length(void *field, u8 mesh_flags, u8 hdr_type)
+
+ bool ieee80211_is_valid_amsdu(struct sk_buff *skb, u8 mesh_hdr)
+ {
+- int offset = 0, remaining, subframe_len, padding;
++ int offset = 0, subframe_len, padding;
+
+ for (offset = 0; offset < skb->len; offset += subframe_len + padding) {
++ int remaining = skb->len - offset;
+ struct {
+ __be16 len;
+ u8 mesh_flags;
+ } hdr;
+ u16 len;
+
++ if (sizeof(hdr) > remaining)
++ return false;
++
+ if (skb_copy_bits(skb, offset + 2 * ETH_ALEN, &hdr, sizeof(hdr)) < 0)
+ return false;
+
+@@ -807,7 +811,6 @@ bool ieee80211_is_valid_amsdu(struct sk_buff *skb, u8 mesh_hdr)
+ mesh_hdr);
+ subframe_len = sizeof(struct ethhdr) + len;
+ padding = (4 - subframe_len) & 0x3;
+- remaining = skb->len - offset;
+
+ if (subframe_len > remaining)
+ return false;
+@@ -825,7 +828,7 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
+ {
+ unsigned int hlen = ALIGN(extra_headroom, 4);
+ struct sk_buff *frame = NULL;
+- int offset = 0, remaining;
++ int offset = 0;
+ struct {
+ struct ethhdr eth;
+ uint8_t flags;
+@@ -839,10 +842,14 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
+ copy_len = sizeof(hdr);
+
+ while (!last) {
++ int remaining = skb->len - offset;
+ unsigned int subframe_len;
+ int len, mesh_len = 0;
+ u8 padding;
+
++ if (copy_len > remaining)
++ goto purge;
++
+ skb_copy_bits(skb, offset, &hdr, copy_len);
+ if (iftype == NL80211_IFTYPE_MESH_POINT)
+ mesh_len = __ieee80211_get_mesh_hdrlen(hdr.flags);
+@@ -852,7 +859,6 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
+ padding = (4 - subframe_len) & 0x3;
+
+ /* the last MSDU has no padding */
+- remaining = skb->len - offset;
+ if (subframe_len > remaining)
+ goto purge;
+ /* mitigate A-MSDU aggregation injection attacks */
+diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c
+index c5c2ce113c923..d20c47d21ad83 100644
+--- a/scripts/gcc-plugins/stackleak_plugin.c
++++ b/scripts/gcc-plugins/stackleak_plugin.c
+@@ -467,6 +467,8 @@ static bool stackleak_gate(void)
+ return false;
+ if (STRING_EQUAL(section, ".entry.text"))
+ return false;
++ if (STRING_EQUAL(section, ".head.text"))
++ return false;
+ }
+
+ return track_frame_size >= 0;
+diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
+index 6568f8177e392..ce686ebf5591f 100644
+--- a/scripts/mod/modpost.c
++++ b/scripts/mod/modpost.c
+@@ -1053,7 +1053,9 @@ static void default_mismatch_handler(const char *modname, struct elf_info *elf,
+ sec_mismatch_count++;
+
+ warn("%s: section mismatch in reference: %s+0x%x (section: %s) -> %s (section: %s)\n",
+- modname, fromsym, (unsigned int)(faddr - from->st_value), fromsec, tosym, tosec);
++ modname, fromsym,
++ (unsigned int)(faddr - (from ? from->st_value : 0)),
++ fromsec, tosym, tosec);
+
+ if (mismatch->mismatch == EXTABLE_TO_NON_TEXT) {
+ if (match(tosec, mismatch->bad_tosec))
+diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
+index 7be17bca257f0..c9f153f85ae6b 100644
+--- a/sound/firewire/amdtp-stream.c
++++ b/sound/firewire/amdtp-stream.c
+@@ -773,10 +773,14 @@ static int check_cip_header(struct amdtp_stream *s, const __be32 *buf,
+ } else {
+ unsigned int dbc_interval;
+
+- if (*data_blocks > 0 && s->ctx_data.tx.dbc_interval > 0)
+- dbc_interval = s->ctx_data.tx.dbc_interval;
+- else
+- dbc_interval = *data_blocks;
++ if (!(s->flags & CIP_DBC_IS_PAYLOAD_QUADLETS)) {
++ if (*data_blocks > 0 && s->ctx_data.tx.dbc_interval > 0)
++ dbc_interval = s->ctx_data.tx.dbc_interval;
++ else
++ dbc_interval = *data_blocks;
++ } else {
++ dbc_interval = payload_length / sizeof(__be32);
++ }
+
+ lost = dbc != ((*data_block_counter + dbc_interval) & 0xff);
+ }
+diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h
+index b7ff44751ab93..a1ed2e80f91a7 100644
+--- a/sound/firewire/amdtp-stream.h
++++ b/sound/firewire/amdtp-stream.h
+@@ -37,6 +37,9 @@
+ * the value of current SYT_INTERVAL; e.g. initial value is not zero.
+ * @CIP_UNAWARE_SYT: For outgoing packet, the value in SYT field of CIP is 0xffff.
+ * For incoming packet, the value in SYT field of CIP is not handled.
++ * @CIP_DBC_IS_PAYLOAD_QUADLETS: Available for incoming packet, and only effective with
++ * CIP_DBC_IS_END_EVENT flag. The value of dbc field is the number of accumulated quadlets
++ * in CIP payload, instead of the number of accumulated data blocks.
+ */
+ enum cip_flags {
+ CIP_NONBLOCKING = 0x00,
+@@ -51,6 +54,7 @@ enum cip_flags {
+ CIP_NO_HEADER = 0x100,
+ CIP_UNALIGHED_DBC = 0x200,
+ CIP_UNAWARE_SYT = 0x400,
++ CIP_DBC_IS_PAYLOAD_QUADLETS = 0x800,
+ };
+
+ /**
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index f4a02bf1abb11..8c2467ed127ee 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -2646,6 +2646,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1558, 0x65f1, "Clevo PC50HS", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x65f5, "Clevo PD50PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x66a2, "Clevo PE60RNE", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
++ SND_PCI_QUIRK(0x1558, 0x66a6, "Clevo PE60SN[CDE]-[GS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x67e5, "Clevo PC70D[PRS](?:-D|-G)?", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+@@ -7521,6 +7522,7 @@ enum {
+ ALC287_FIXUP_LEGION_16ITHG6,
+ ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK,
+ ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN,
++ ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN,
+ ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS,
+ ALC236_FIXUP_DELL_DUAL_CODECS,
+ ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI,
+@@ -9650,6 +9652,12 @@ static const struct hda_fixup alc269_fixups[] = {
+ .chained = true,
+ .chain_id = ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK,
+ },
++ [ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc287_fixup_yoga9_14iap7_bass_spk_pin,
++ .chained = true,
++ .chain_id = ALC287_FIXUP_CS35L41_I2C_2,
++ },
+ [ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc295_fixup_dell_inspiron_top_speakers,
+@@ -10207,12 +10215,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x152d, 0x1082, "Quanta NL3", ALC269_FIXUP_LIFEBOOK),
++ SND_PCI_QUIRK(0x1558, 0x0353, "Clevo V35[05]SN[CDE]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x1325, "Clevo N15[01][CW]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x1401, "Clevo L140[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x1403, "Clevo N140CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x1404, "Clevo N150CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x14a1, "Clevo L141MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
++ SND_PCI_QUIRK(0x1558, 0x2624, "Clevo L240TU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x4018, "Clevo NV40M[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x4019, "Clevo NV40MZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x4020, "Clevo NV40MB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+@@ -10384,6 +10394,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x17aa, 0x38c3, "Y980 DUAL", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x38cb, "Y790 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x38cd, "Y790 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x38d2, "Lenovo Yoga 9 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN),
++ SND_PCI_QUIRK(0x17aa, 0x38d7, "Lenovo Yoga 9 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
+ SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
+ SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
+diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
+index 1d1452c29ed02..69c68d8e7a6b5 100644
+--- a/sound/soc/amd/yc/acp6x-mach.c
++++ b/sound/soc/amd/yc/acp6x-mach.c
+@@ -311,6 +311,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "E1504FA"),
+ }
+ },
++ {
++ .driver_data = &acp6x_card,
++ .matches = {
++ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
++ DMI_MATCH(DMI_PRODUCT_NAME, "M7600RE"),
++ }
++ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c
+index 8e91eece992db..8360ce557401c 100644
+--- a/sound/soc/intel/avs/board_selection.c
++++ b/sound/soc/intel/avs/board_selection.c
+@@ -236,6 +236,82 @@ static struct snd_soc_acpi_mach avs_gml_i2s_machines[] = {
+ {},
+ };
+
++static struct snd_soc_acpi_mach avs_cnl_i2s_machines[] = {
++ {
++ .id = "INT34C2",
++ .drv_name = "avs_rt274",
++ .mach_params = {
++ .i2s_link_mask = AVS_SSP(0),
++ },
++ .tplg_filename = "rt274-tplg.bin",
++ },
++ {
++ .id = "10EC5682",
++ .drv_name = "avs_rt5682",
++ .mach_params = {
++ .i2s_link_mask = AVS_SSP(1),
++ },
++ .tplg_filename = "rt5682-tplg.bin",
++ },
++ {},
++};
++
++static struct snd_soc_acpi_mach avs_icl_i2s_machines[] = {
++ {
++ .id = "INT343A",
++ .drv_name = "avs_rt298",
++ .mach_params = {
++ .i2s_link_mask = AVS_SSP(0),
++ },
++ .tplg_filename = "rt298-tplg.bin",
++ },
++ {
++ .id = "INT34C2",
++ .drv_name = "avs_rt274",
++ .mach_params = {
++ .i2s_link_mask = AVS_SSP(0),
++ },
++ .tplg_filename = "rt274-tplg.bin",
++ },
++ {},
++};
++
++static struct snd_soc_acpi_mach avs_tgl_i2s_machines[] = {
++ {
++ .id = "INT34C2",
++ .drv_name = "avs_rt274",
++ .mach_params = {
++ .i2s_link_mask = AVS_SSP(0),
++ },
++ .tplg_filename = "rt274-tplg.bin",
++ },
++ {
++ .id = "10EC0298",
++ .drv_name = "avs_rt298",
++ .mach_params = {
++ .i2s_link_mask = AVS_SSP(0),
++ },
++ .tplg_filename = "rt298-tplg.bin",
++ },
++ {
++ .id = "10EC1308",
++ .drv_name = "avs_rt1308",
++ .mach_params = {
++ .i2s_link_mask = AVS_SSP(1),
++ },
++ .tplg_filename = "rt1308-tplg.bin",
++ },
++ {
++ .id = "ESSX8336",
++ .drv_name = "avs_es8336",
++ .mach_params = {
++ .i2s_link_mask = AVS_SSP(0),
++ },
++ .tplg_filename = "es8336-tplg.bin",
++ },
++ {},
++};
++
+ static struct snd_soc_acpi_mach avs_test_i2s_machines[] = {
+ {
+ .drv_name = "avs_i2s_test",
+@@ -296,6 +372,15 @@ static const struct avs_acpi_boards i2s_boards[] = {
+ AVS_MACH_ENTRY(HDA_KBL_LP, avs_kbl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_APL, avs_apl_i2s_machines),
+ AVS_MACH_ENTRY(HDA_GML, avs_gml_i2s_machines),
++ AVS_MACH_ENTRY(HDA_CNL_LP, avs_cnl_i2s_machines),
++ AVS_MACH_ENTRY(HDA_CNL_H, avs_cnl_i2s_machines),
++ AVS_MACH_ENTRY(HDA_CML_LP, avs_cnl_i2s_machines),
++ AVS_MACH_ENTRY(HDA_ICL_LP, avs_icl_i2s_machines),
++ AVS_MACH_ENTRY(HDA_TGL_LP, avs_tgl_i2s_machines),
++ AVS_MACH_ENTRY(HDA_EHL_0, avs_tgl_i2s_machines),
++ AVS_MACH_ENTRY(HDA_ADL_P, avs_tgl_i2s_machines),
++ AVS_MACH_ENTRY(HDA_RPL_P_0, avs_tgl_i2s_machines),
++ AVS_MACH_ENTRY(HDA_RPL_M, avs_tgl_i2s_machines),
+ {},
+ };
+
+diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
+index cd50f26d1edbe..02705034e5713 100644
+--- a/sound/soc/intel/boards/sof_rt5682.c
++++ b/sound/soc/intel/boards/sof_rt5682.c
+@@ -154,46 +154,6 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = {
+ SOF_RT5682_SSP_AMP(2) |
+ SOF_RT5682_NUM_HDMIDEV(4)),
+ },
+- {
+- .callback = sof_rt5682_quirk_cb,
+- .matches = {
+- DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
+- DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S"),
+- },
+- .driver_data = (void *)(SOF_RT5682_MCLK_EN |
+- SOF_RT5682_SSP_CODEC(2) |
+- SOF_RT5682_SSP_AMP(0) |
+- SOF_RT5682_NUM_HDMIDEV(3) |
+- SOF_BT_OFFLOAD_SSP(1) |
+- SOF_SSP_BT_OFFLOAD_PRESENT
+- ),
+- },
+- {
+- .callback = sof_rt5682_quirk_cb,
+- .matches = {
+- DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
+- DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_DISCRETE_I2S_BT"),
+- },
+- .driver_data = (void *)(SOF_RT5682_MCLK_EN |
+- SOF_RT5682_SSP_CODEC(2) |
+- SOF_RT5682_SSP_AMP(0) |
+- SOF_RT5682_NUM_HDMIDEV(3) |
+- SOF_BT_OFFLOAD_SSP(1) |
+- SOF_SSP_BT_OFFLOAD_PRESENT
+- ),
+- },
+- {
+- .callback = sof_rt5682_quirk_cb,
+- .matches = {
+- DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"),
+- DMI_MATCH(DMI_OEM_STRING, "AUDIO-ALC1019_ALC5682I_I2S"),
+- },
+- .driver_data = (void *)(SOF_RT5682_MCLK_EN |
+- SOF_RT5682_SSP_CODEC(2) |
+- SOF_RT5682_SSP_AMP(0) |
+- SOF_RT5682_NUM_HDMIDEV(3)
+- ),
+- },
+ {
+ .callback = sof_rt5682_quirk_cb,
+ .matches = {
+diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
+index 300391fbc2fc2..cf14bd3053fc9 100644
+--- a/sound/soc/intel/boards/sof_sdw.c
++++ b/sound/soc/intel/boards/sof_sdw.c
+@@ -236,6 +236,17 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
+ SOF_SDW_PCH_DMIC |
+ RT711_JD2_100K),
+ },
++ {
++ /* NUC15 LAPRC710 skews */
++ .callback = sof_sdw_quirk_cb,
++ .matches = {
++ DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
++ DMI_MATCH(DMI_BOARD_NAME, "LAPRC710"),
++ },
++ .driver_data = (void *)(SOF_SDW_TGL_HDMI |
++ SOF_SDW_PCH_DMIC |
++ RT711_JD2_100K),
++ },
+ /* TigerLake-SDCA devices */
+ {
+ .callback = sof_sdw_quirk_cb,
+diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
+index 516350533e73f..8b5b583a2bad0 100644
+--- a/sound/soc/soc-core.c
++++ b/sound/soc/soc-core.c
+@@ -1218,6 +1218,9 @@ static int snd_soc_add_pcm_runtime(struct snd_soc_card *card,
+ if (!snd_soc_is_matching_component(platform, component))
+ continue;
+
++ if (snd_soc_component_is_dummy(component) && component->num_dai)
++ continue;
++
+ snd_soc_rtd_add_component(rtd, component);
+ }
+ }
+diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c
+index 2c242ef9f23c1..1b6f5724c82b0 100644
+--- a/sound/soc/sof/amd/acp.c
++++ b/sound/soc/sof/amd/acp.c
+@@ -31,11 +31,10 @@ static struct acp_quirk_entry quirk_valve_galileo = {
+
+ const struct dmi_system_id acp_sof_quirk_table[] = {
+ {
+- /* Valve Jupiter device */
++ /* Steam Deck OLED device */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Valve"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Galileo"),
+- DMI_MATCH(DMI_PRODUCT_FAMILY, "Sephiroth"),
+ },
+ .driver_data = &quirk_valve_galileo,
+ },
+diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c
+index 6a00a6eecaef0..c5c5082cb24e5 100644
+--- a/tools/iio/iio_utils.c
++++ b/tools/iio/iio_utils.c
+@@ -376,7 +376,7 @@ int build_channel_array(const char *device_dir, int buffer_idx,
+ goto error_close_dir;
+ }
+
+- seekdir(dp, 0);
++ rewinddir(dp);
+ while (ent = readdir(dp), ent) {
+ if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
+ "_en") == 0) {
+diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c
+index 058e3ff10f9b2..c6d67fc9e57ef 100644
+--- a/tools/lib/perf/evlist.c
++++ b/tools/lib/perf/evlist.c
+@@ -248,10 +248,10 @@ u64 perf_evlist__read_format(struct perf_evlist *evlist)
+
+ static void perf_evlist__id_hash(struct perf_evlist *evlist,
+ struct perf_evsel *evsel,
+- int cpu, int thread, u64 id)
++ int cpu_map_idx, int thread, u64 id)
+ {
+ int hash;
+- struct perf_sample_id *sid = SID(evsel, cpu, thread);
++ struct perf_sample_id *sid = SID(evsel, cpu_map_idx, thread);
+
+ sid->id = id;
+ sid->evsel = evsel;
+@@ -269,21 +269,27 @@ void perf_evlist__reset_id_hash(struct perf_evlist *evlist)
+
+ void perf_evlist__id_add(struct perf_evlist *evlist,
+ struct perf_evsel *evsel,
+- int cpu, int thread, u64 id)
++ int cpu_map_idx, int thread, u64 id)
+ {
+- perf_evlist__id_hash(evlist, evsel, cpu, thread, id);
++ if (!SID(evsel, cpu_map_idx, thread))
++ return;
++
++ perf_evlist__id_hash(evlist, evsel, cpu_map_idx, thread, id);
+ evsel->id[evsel->ids++] = id;
+ }
+
+ int perf_evlist__id_add_fd(struct perf_evlist *evlist,
+ struct perf_evsel *evsel,
+- int cpu, int thread, int fd)
++ int cpu_map_idx, int thread, int fd)
+ {
+ u64 read_data[4] = { 0, };
+ int id_idx = 1; /* The first entry is the counter value */
+ u64 id;
+ int ret;
+
++ if (!SID(evsel, cpu_map_idx, thread))
++ return -1;
++
+ ret = ioctl(fd, PERF_EVENT_IOC_ID, &id);
+ if (!ret)
+ goto add;
+@@ -312,7 +318,7 @@ int perf_evlist__id_add_fd(struct perf_evlist *evlist,
+ id = read_data[id_idx];
+
+ add:
+- perf_evlist__id_add(evlist, evsel, cpu, thread, id);
++ perf_evlist__id_add(evlist, evsel, cpu_map_idx, thread, id);
+ return 0;
+ }
+
+diff --git a/tools/lib/perf/include/internal/evlist.h b/tools/lib/perf/include/internal/evlist.h
+index d86ffe8ed483e..f43bdb9b6227c 100644
+--- a/tools/lib/perf/include/internal/evlist.h
++++ b/tools/lib/perf/include/internal/evlist.h
+@@ -126,11 +126,11 @@ u64 perf_evlist__read_format(struct perf_evlist *evlist);
+
+ void perf_evlist__id_add(struct perf_evlist *evlist,
+ struct perf_evsel *evsel,
+- int cpu, int thread, u64 id);
++ int cpu_map_idx, int thread, u64 id);
+
+ int perf_evlist__id_add_fd(struct perf_evlist *evlist,
+ struct perf_evsel *evsel,
+- int cpu, int thread, int fd);
++ int cpu_map_idx, int thread, int fd);
+
+ void perf_evlist__reset_id_hash(struct perf_evlist *evlist);
+
+diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
+index 5fd9e594079cf..ebda9c366b2ba 100644
+--- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
++++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
+@@ -1241,6 +1241,7 @@ unsigned int get_pkg_num(int cpu)
+ retval = fscanf(fp, "%d\n", &pkg);
+ if (retval != 1)
+ errx(1, "%s: failed to parse", pathname);
++ fclose(fp);
+ return pkg;
+ }
+
+diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl
+index 829f5bdfd2e43..24451f8f42910 100755
+--- a/tools/testing/ktest/ktest.pl
++++ b/tools/testing/ktest/ktest.pl
+@@ -843,6 +843,7 @@ sub set_value {
+ if ($lvalue =~ /^(TEST|BISECT|CONFIG_BISECT)_TYPE(\[.*\])?$/ &&
+ $prvalue !~ /^(config_|)bisect$/ &&
+ $prvalue !~ /^build$/ &&
++ $prvalue !~ /^make_warnings_file$/ &&
+ $buildonly) {
+
+ # Note if a test is something other than build, then we
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-18 3:04 Alice Ferrazzi
0 siblings, 0 replies; 25+ messages in thread
From: Alice Ferrazzi @ 2024-04-18 3:04 UTC (permalink / raw
To: gentoo-commits
commit: 47a523687dc6f6122c7e0503a5060ca53a794c7a
Author: Alice Ferrazzi <alicef <AT> gentoo <DOT> org>
AuthorDate: Thu Apr 18 03:04:18 2024 +0000
Commit: Alice Ferrazzi <alicef <AT> gentoo <DOT> org>
CommitDate: Thu Apr 18 03:04:18 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=47a52368
Linux patch 6.8.7
Signed-off-by: Alice Ferrazzi <alicef <AT> gentoo.org>
0000_README | 50 +-
1006_linux-6.8.7.patch | 6318 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 6322 insertions(+), 46 deletions(-)
diff --git a/0000_README b/0000_README
index 98a6896a..277bd38e 100644
--- a/0000_README
+++ b/0000_README
@@ -43,7 +43,7 @@ EXPERIMENTAL
Individual Patch Descriptions:
--------------------------------------------------------------------------
-Patch: 1000_linux-6.8.1.patch
+Patch: 1001_linux-6.8.1.patch
From: https://www.kernel.org
Desc: Linux 6.8.1
@@ -67,50 +67,8 @@ Patch: 1005_linux-6.8.6.patch
From: https://www.kernel.org
Desc: Linux 6.8.6
-Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
-From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
-Desc: Enable link security restrictions by default.
-
-Patch: 1700_sparc-address-warray-bound-warnings.patch
-From: https://github.com/KSPP/linux/issues/109
-Desc: Address -Warray-bounds warnings
-
-Patch: 1730_parisc-Disable-prctl.patch
-From: https://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git
-Desc: prctl: Temporarily disable prctl(PR_SET_MDWE) on parisc
-
-Patch: 1800_gcc-plugins-stackleak-Avoid-head-text-section.patch
-From: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
-Desc: gcc-plugins/stackleak: Avoid .head.text section
-
-Patch: 2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch
-From: https://lore.kernel.org/linux-bluetooth/20190522070540.48895-1-marcel@holtmann.org/raw
-Desc: Bluetooth: Check key sizes only when Secure Simple Pairing is enabled. See bug #686758
-
-Patch: 2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch
-From: https://bugs.gentoo.org/710790
-Desc: tmp513 requies REGMAP_I2C to build. Select it by default in Kconfig. See bug #710790. Thanks to Phil Stracchino
-
-Patch: 2910_bfp-mark-get-entry-ip-as--maybe-unused.patch
-From: https://www.spinics.net/lists/stable/msg604665.html
-Desc: bpf: mark get_entry_ip as __maybe_unused
-
-Patch: 2920_sign-file-patch-for-libressl.patch
-From: https://bugs.gentoo.org/717166
-Desc: sign-file: full functionality with modern LibreSSL
-
-Patch: 3000_Support-printing-firmware-info.patch
-From: https://bugs.gentoo.org/732852
-Desc: Print firmware info (Reqs CONFIG_GENTOO_PRINT_FIRMWARE_INFO). Thanks to Georgy Yakovlev
-
-Patch: 4567_distro-Gentoo-Kconfig.patch
-From: Tom Wijsman <TomWij@gentoo.org>
-Desc: Add Gentoo Linux support config settings and defaults.
-
-Patch: 5010_enable-cpu-optimizations-universal.patch
-From: https://github.com/graysky2/kernel_compiler_patch
-Desc: Kernel >= 5.15 patch enables gcc = v11.1+ optimizations for additional CPUs.
+Patch: 1006_linux-6.8.7.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.7
-Patch: 5020_BMQ-and-PDS-io-scheduler-v6.8-r4.patch
-From: https://gitlab.com/alfredchen/projectc
Desc: BMQ(BitMap Queue) Scheduler. A new CPU scheduler developed from PDS(incld). Inspired by the scheduler in zircon.
diff --git a/1006_linux-6.8.7.patch b/1006_linux-6.8.7.patch
new file mode 100644
index 00000000..09ffaa63
--- /dev/null
+++ b/1006_linux-6.8.7.patch
@@ -0,0 +1,6318 @@
+diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst
+index 9edb2860a3e19..e0a1be97fa759 100644
+--- a/Documentation/admin-guide/hw-vuln/spectre.rst
++++ b/Documentation/admin-guide/hw-vuln/spectre.rst
+@@ -439,12 +439,12 @@ The possible values in this file are:
+ - System is protected by retpoline
+ * - BHI: BHI_DIS_S
+ - System is protected by BHI_DIS_S
+- * - BHI: SW loop; KVM SW loop
++ * - BHI: SW loop, KVM SW loop
+ - System is protected by software clearing sequence
+- * - BHI: Syscall hardening
+- - Syscalls are hardened against BHI
+- * - BHI: Syscall hardening; KVM: SW loop
+- - System is protected from userspace attacks by syscall hardening; KVM is protected by software clearing sequence
++ * - BHI: Vulnerable
++ - System is vulnerable to BHI
++ * - BHI: Vulnerable, KVM: SW loop
++ - System is vulnerable; KVM is protected by software clearing sequence
+
+ Full mitigation might require a microcode update from the CPU
+ vendor. When the necessary microcode is not available, the kernel will
+@@ -661,18 +661,14 @@ kernel command line.
+ spectre_bhi=
+
+ [X86] Control mitigation of Branch History Injection
+- (BHI) vulnerability. Syscalls are hardened against BHI
+- regardless of this setting. This setting affects the deployment
++ (BHI) vulnerability. This setting affects the deployment
+ of the HW BHI control and the SW BHB clearing sequence.
+
+ on
+- unconditionally enable.
++ (default) Enable the HW or SW mitigation as
++ needed.
+ off
+- unconditionally disable.
+- auto
+- enable if hardware mitigation
+- control(BHI_DIS_S) is available, otherwise
+- enable alternate mitigation in KVM.
++ Disable the mitigation.
+
+ For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index 95efaccca4539..31fdaf4fe9dd8 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -3419,6 +3419,7 @@
+ reg_file_data_sampling=off [X86]
+ retbleed=off [X86]
+ spec_store_bypass_disable=off [X86,PPC]
++ spectre_bhi=off [X86]
+ spectre_v2_user=off [X86]
+ srbds=off [X86,INTEL]
+ ssbd=force-off [ARM64]
+@@ -6032,16 +6033,13 @@
+ See Documentation/admin-guide/laptops/sonypi.rst
+
+ spectre_bhi= [X86] Control mitigation of Branch History Injection
+- (BHI) vulnerability. Syscalls are hardened against BHI
+- reglardless of this setting. This setting affects the
++ (BHI) vulnerability. This setting affects the
+ deployment of the HW BHI control and the SW BHB
+ clearing sequence.
+
+- on - unconditionally enable.
+- off - unconditionally disable.
+- auto - (default) enable hardware mitigation
+- (BHI_DIS_S) if available, otherwise enable
+- alternate mitigation in KVM.
++ on - (default) Enable the HW or SW mitigation
++ as needed.
++ off - Disable the mitigation.
+
+ spectre_v2= [X86] Control mitigation of Spectre variant 2
+ (indirect branch speculation) vulnerability.
+diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml
+index c0d6a4fdff97e..e6dc5494baee2 100644
+--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml
++++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml
+@@ -53,6 +53,15 @@ patternProperties:
+ compatible:
+ const: qcom,sm8150-dpu
+
++ "^displayport-controller@[0-9a-f]+$":
++ type: object
++ additionalProperties: true
++
++ properties:
++ compatible:
++ contains:
++ const: qcom,sm8150-dp
++
+ "^dsi@[0-9a-f]+$":
+ type: object
+ additionalProperties: true
+diff --git a/Makefile b/Makefile
+index c426d47f4b7bf..e6c0a00722eae 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 6
++SUBLEVEL = 7
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts
+index ba7231b364bb8..7bab113ca6da7 100644
+--- a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts
++++ b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts
+@@ -210,6 +210,7 @@ ov2680_to_mipi: endpoint {
+ remote-endpoint = <&mipi_from_sensor>;
+ clock-lanes = <0>;
+ data-lanes = <1>;
++ link-frequencies = /bits/ 64 <330000000>;
+ };
+ };
+ };
+diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
+index 31755a378c736..ff2a4a4d82204 100644
+--- a/arch/arm/mach-omap2/board-n8x0.c
++++ b/arch/arm/mach-omap2/board-n8x0.c
+@@ -79,10 +79,8 @@ static struct musb_hdrc_platform_data tusb_data = {
+ static struct gpiod_lookup_table tusb_gpio_table = {
+ .dev_id = "musb-tusb",
+ .table = {
+- GPIO_LOOKUP("gpio-0-15", 0, "enable",
+- GPIO_ACTIVE_HIGH),
+- GPIO_LOOKUP("gpio-48-63", 10, "int",
+- GPIO_ACTIVE_HIGH),
++ GPIO_LOOKUP("gpio-0-31", 0, "enable", GPIO_ACTIVE_HIGH),
++ GPIO_LOOKUP("gpio-32-63", 26, "int", GPIO_ACTIVE_HIGH),
+ { }
+ },
+ };
+@@ -140,12 +138,11 @@ static int slot1_cover_open;
+ static int slot2_cover_open;
+ static struct device *mmc_device;
+
+-static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = {
++static struct gpiod_lookup_table nokia800_mmc_gpio_table = {
+ .dev_id = "mmci-omap.0",
+ .table = {
+ /* Slot switch, GPIO 96 */
+- GPIO_LOOKUP("gpio-80-111", 16,
+- "switch", GPIO_ACTIVE_HIGH),
++ GPIO_LOOKUP("gpio-96-127", 0, "switch", GPIO_ACTIVE_HIGH),
+ { }
+ },
+ };
+@@ -153,12 +150,12 @@ static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = {
+ static struct gpiod_lookup_table nokia810_mmc_gpio_table = {
+ .dev_id = "mmci-omap.0",
+ .table = {
++ /* Slot switch, GPIO 96 */
++ GPIO_LOOKUP("gpio-96-127", 0, "switch", GPIO_ACTIVE_HIGH),
+ /* Slot index 1, VSD power, GPIO 23 */
+- GPIO_LOOKUP_IDX("gpio-16-31", 7,
+- "vsd", 1, GPIO_ACTIVE_HIGH),
++ GPIO_LOOKUP_IDX("gpio-0-31", 23, "vsd", 1, GPIO_ACTIVE_HIGH),
+ /* Slot index 1, VIO power, GPIO 9 */
+- GPIO_LOOKUP_IDX("gpio-0-15", 9,
+- "vio", 1, GPIO_ACTIVE_HIGH),
++ GPIO_LOOKUP_IDX("gpio-0-31", 9, "vio", 1, GPIO_ACTIVE_HIGH),
+ { }
+ },
+ };
+@@ -415,8 +412,6 @@ static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC];
+
+ static void __init n8x0_mmc_init(void)
+ {
+- gpiod_add_lookup_table(&nokia8xx_mmc_gpio_table);
+-
+ if (board_is_n810()) {
+ mmc1_data.slots[0].name = "external";
+
+@@ -429,6 +424,8 @@ static void __init n8x0_mmc_init(void)
+ mmc1_data.slots[1].name = "internal";
+ mmc1_data.slots[1].ban_openended = 1;
+ gpiod_add_lookup_table(&nokia810_mmc_gpio_table);
++ } else {
++ gpiod_add_lookup_table(&nokia800_mmc_gpio_table);
+ }
+
+ mmc1_data.nr_slots = 2;
+diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
+index 3c42240e78e24..4aaf5a0c1ed8a 100644
+--- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
+@@ -41,7 +41,7 @@ usbotg1: usb@5b0d0000 {
+ interrupts = <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,usbphy = <&usbphy1>;
+ fsl,usbmisc = <&usbmisc1 0>;
+- clocks = <&usb2_lpcg 0>;
++ clocks = <&usb2_lpcg IMX_LPCG_CLK_6>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>;
+ rx-burst-size-dword = <0x10>;
+@@ -58,7 +58,7 @@ usbmisc1: usbmisc@5b0d0200 {
+ usbphy1: usbphy@5b100000 {
+ compatible = "fsl,imx7ulp-usbphy";
+ reg = <0x5b100000 0x1000>;
+- clocks = <&usb2_lpcg 1>;
++ clocks = <&usb2_lpcg IMX_LPCG_CLK_7>;
+ power-domains = <&pd IMX_SC_R_USB_0_PHY>;
+ status = "disabled";
+ };
+@@ -67,8 +67,8 @@ usdhc1: mmc@5b010000 {
+ interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x5b010000 0x10000>;
+ clocks = <&sdhc0_lpcg IMX_LPCG_CLK_4>,
+- <&sdhc0_lpcg IMX_LPCG_CLK_0>,
+- <&sdhc0_lpcg IMX_LPCG_CLK_5>;
++ <&sdhc0_lpcg IMX_LPCG_CLK_5>,
++ <&sdhc0_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "ahb", "per";
+ power-domains = <&pd IMX_SC_R_SDHC_0>;
+ status = "disabled";
+@@ -78,8 +78,8 @@ usdhc2: mmc@5b020000 {
+ interrupts = <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x5b020000 0x10000>;
+ clocks = <&sdhc1_lpcg IMX_LPCG_CLK_4>,
+- <&sdhc1_lpcg IMX_LPCG_CLK_0>,
+- <&sdhc1_lpcg IMX_LPCG_CLK_5>;
++ <&sdhc1_lpcg IMX_LPCG_CLK_5>,
++ <&sdhc1_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "ahb", "per";
+ power-domains = <&pd IMX_SC_R_SDHC_1>;
+ fsl,tuning-start-tap = <20>;
+@@ -91,8 +91,8 @@ usdhc3: mmc@5b030000 {
+ interrupts = <GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x5b030000 0x10000>;
+ clocks = <&sdhc2_lpcg IMX_LPCG_CLK_4>,
+- <&sdhc2_lpcg IMX_LPCG_CLK_0>,
+- <&sdhc2_lpcg IMX_LPCG_CLK_5>;
++ <&sdhc2_lpcg IMX_LPCG_CLK_5>,
++ <&sdhc2_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "ahb", "per";
+ power-domains = <&pd IMX_SC_R_SDHC_2>;
+ status = "disabled";
+diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
+index b0bb77150adcc..67b3c7573233a 100644
+--- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
+@@ -27,8 +27,8 @@ lpspi0: spi@5a000000 {
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&spi0_lpcg 0>,
+- <&spi0_lpcg 1>;
++ clocks = <&spi0_lpcg IMX_LPCG_CLK_0>,
++ <&spi0_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_SPI_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <60000000>;
+@@ -43,8 +43,8 @@ lpspi1: spi@5a010000 {
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&spi1_lpcg 0>,
+- <&spi1_lpcg 1>;
++ clocks = <&spi1_lpcg IMX_LPCG_CLK_0>,
++ <&spi1_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_SPI_1 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <60000000>;
+@@ -59,8 +59,8 @@ lpspi2: spi@5a020000 {
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&spi2_lpcg 0>,
+- <&spi2_lpcg 1>;
++ clocks = <&spi2_lpcg IMX_LPCG_CLK_0>,
++ <&spi2_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_SPI_2 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <60000000>;
+@@ -75,8 +75,8 @@ lpspi3: spi@5a030000 {
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&spi3_lpcg 0>,
+- <&spi3_lpcg 1>;
++ clocks = <&spi3_lpcg IMX_LPCG_CLK_0>,
++ <&spi3_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_SPI_3 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <60000000>;
+@@ -144,8 +144,8 @@ adma_pwm: pwm@5a190000 {
+ compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm";
+ reg = <0x5a190000 0x1000>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+- clocks = <&adma_pwm_lpcg 1>,
+- <&adma_pwm_lpcg 0>;
++ clocks = <&adma_pwm_lpcg IMX_LPCG_CLK_4>,
++ <&adma_pwm_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "per";
+ assigned-clocks = <&clk IMX_SC_R_LCD_0_PWM_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+@@ -377,8 +377,8 @@ adc0: adc@5a880000 {
+ reg = <0x5a880000 0x10000>;
+ interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&adc0_lpcg 0>,
+- <&adc0_lpcg 1>;
++ clocks = <&adc0_lpcg IMX_LPCG_CLK_0>,
++ <&adc0_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_ADC_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+@@ -392,8 +392,8 @@ adc1: adc@5a890000 {
+ reg = <0x5a890000 0x10000>;
+ interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&adc1_lpcg 0>,
+- <&adc1_lpcg 1>;
++ clocks = <&adc1_lpcg IMX_LPCG_CLK_0>,
++ <&adc1_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_ADC_1 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+@@ -406,8 +406,8 @@ flexcan1: can@5a8d0000 {
+ reg = <0x5a8d0000 0x10000>;
+ interrupts = <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&can0_lpcg 1>,
+- <&can0_lpcg 0>;
++ clocks = <&can0_lpcg IMX_LPCG_CLK_4>,
++ <&can0_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "per";
+ assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <40000000>;
+@@ -427,8 +427,8 @@ flexcan2: can@5a8e0000 {
+ * CAN1 shares CAN0's clock and to enable CAN0's clock it
+ * has to be powered on.
+ */
+- clocks = <&can0_lpcg 1>,
+- <&can0_lpcg 0>;
++ clocks = <&can0_lpcg IMX_LPCG_CLK_4>,
++ <&can0_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "per";
+ assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <40000000>;
+@@ -448,8 +448,8 @@ flexcan3: can@5a8f0000 {
+ * CAN2 shares CAN0's clock and to enable CAN0's clock it
+ * has to be powered on.
+ */
+- clocks = <&can0_lpcg 1>,
+- <&can0_lpcg 0>;
++ clocks = <&can0_lpcg IMX_LPCG_CLK_4>,
++ <&can0_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "per";
+ assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <40000000>;
+diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
+index 7e510b21bbac5..764c1a08e3b11 100644
+--- a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
+@@ -25,8 +25,8 @@ lsio_pwm0: pwm@5d000000 {
+ compatible = "fsl,imx27-pwm";
+ reg = <0x5d000000 0x10000>;
+ clock-names = "ipg", "per";
+- clocks = <&pwm0_lpcg 4>,
+- <&pwm0_lpcg 1>;
++ clocks = <&pwm0_lpcg IMX_LPCG_CLK_6>,
++ <&pwm0_lpcg IMX_LPCG_CLK_1>;
+ assigned-clocks = <&clk IMX_SC_R_PWM_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <3>;
+@@ -38,8 +38,8 @@ lsio_pwm1: pwm@5d010000 {
+ compatible = "fsl,imx27-pwm";
+ reg = <0x5d010000 0x10000>;
+ clock-names = "ipg", "per";
+- clocks = <&pwm1_lpcg 4>,
+- <&pwm1_lpcg 1>;
++ clocks = <&pwm1_lpcg IMX_LPCG_CLK_6>,
++ <&pwm1_lpcg IMX_LPCG_CLK_1>;
+ assigned-clocks = <&clk IMX_SC_R_PWM_1 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <3>;
+@@ -51,8 +51,8 @@ lsio_pwm2: pwm@5d020000 {
+ compatible = "fsl,imx27-pwm";
+ reg = <0x5d020000 0x10000>;
+ clock-names = "ipg", "per";
+- clocks = <&pwm2_lpcg 4>,
+- <&pwm2_lpcg 1>;
++ clocks = <&pwm2_lpcg IMX_LPCG_CLK_6>,
++ <&pwm2_lpcg IMX_LPCG_CLK_1>;
+ assigned-clocks = <&clk IMX_SC_R_PWM_2 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <3>;
+@@ -64,8 +64,8 @@ lsio_pwm3: pwm@5d030000 {
+ compatible = "fsl,imx27-pwm";
+ reg = <0x5d030000 0x10000>;
+ clock-names = "ipg", "per";
+- clocks = <&pwm3_lpcg 4>,
+- <&pwm3_lpcg 1>;
++ clocks = <&pwm3_lpcg IMX_LPCG_CLK_6>,
++ <&pwm3_lpcg IMX_LPCG_CLK_1>;
+ assigned-clocks = <&clk IMX_SC_R_PWM_3 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <3>;
+diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi
+index 41c79d2ebdd62..f24b14744799e 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi
+@@ -14,6 +14,7 @@ connector {
+ pinctrl-0 = <&pinctrl_usbcon1>;
+ type = "micro";
+ label = "otg";
++ vbus-supply = <®_usb1_vbus>;
+ id-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+
+ port {
+@@ -183,7 +184,6 @@ &usb3_0 {
+ };
+
+ &usb3_phy0 {
+- vbus-supply = <®_usb1_vbus>;
+ status = "okay";
+ };
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi
+index d5c400b355af5..f5491a608b2f3 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi
+@@ -14,6 +14,7 @@ connector {
+ pinctrl-0 = <&pinctrl_usbcon1>;
+ type = "micro";
+ label = "otg";
++ vbus-supply = <®_usb1_vbus>;
+ id-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+
+ port {
+@@ -202,7 +203,6 @@ &usb3_0 {
+ };
+
+ &usb3_phy0 {
+- vbus-supply = <®_usb1_vbus>;
+ status = "okay";
+ };
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
+index cafc1383115ab..cd96f9f75da16 100644
+--- a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
+@@ -127,15 +127,15 @@ &flexcan1 {
+ };
+
+ &flexcan2 {
+- clocks = <&can1_lpcg 1>,
+- <&can1_lpcg 0>;
++ clocks = <&can1_lpcg IMX_LPCG_CLK_4>,
++ <&can1_lpcg IMX_LPCG_CLK_0>;
+ assigned-clocks = <&clk IMX_SC_R_CAN_1 IMX_SC_PM_CLK_PER>;
+ fsl,clk-source = /bits/ 8 <1>;
+ };
+
+ &flexcan3 {
+- clocks = <&can2_lpcg 1>,
+- <&can2_lpcg 0>;
++ clocks = <&can2_lpcg IMX_LPCG_CLK_4>,
++ <&can2_lpcg IMX_LPCG_CLK_0>;
+ assigned-clocks = <&clk IMX_SC_R_CAN_2 IMX_SC_PM_CLK_PER>;
+ fsl,clk-source = /bits/ 8 <1>;
+ };
+diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
+index 1deb5d789c2e2..bfeb54f3a971f 100644
+--- a/arch/arm64/include/asm/tlbflush.h
++++ b/arch/arm64/include/asm/tlbflush.h
+@@ -161,12 +161,18 @@ static inline unsigned long get_trans_granule(void)
+ #define MAX_TLBI_RANGE_PAGES __TLBI_RANGE_PAGES(31, 3)
+
+ /*
+- * Generate 'num' values from -1 to 30 with -1 rejected by the
+- * __flush_tlb_range() loop below.
++ * Generate 'num' values from -1 to 31 with -1 rejected by the
++ * __flush_tlb_range() loop below. Its return value is only
++ * significant for a maximum of MAX_TLBI_RANGE_PAGES pages. If
++ * 'pages' is more than that, you must iterate over the overall
++ * range.
+ */
+-#define TLBI_RANGE_MASK GENMASK_ULL(4, 0)
+-#define __TLBI_RANGE_NUM(pages, scale) \
+- ((((pages) >> (5 * (scale) + 1)) & TLBI_RANGE_MASK) - 1)
++#define __TLBI_RANGE_NUM(pages, scale) \
++ ({ \
++ int __pages = min((pages), \
++ __TLBI_RANGE_PAGES(31, (scale))); \
++ (__pages >> (5 * (scale) + 1)) - 1; \
++ })
+
+ /*
+ * TLB Invalidation
+@@ -379,10 +385,6 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
+ * 3. If there is 1 page remaining, flush it through non-range operations. Range
+ * operations can only span an even number of pages. We save this for last to
+ * ensure 64KB start alignment is maintained for the LPA2 case.
+- *
+- * Note that certain ranges can be represented by either num = 31 and
+- * scale or num = 0 and scale + 1. The loop below favours the latter
+- * since num is limited to 30 by the __TLBI_RANGE_NUM() macro.
+ */
+ #define __flush_tlb_range_op(op, start, pages, stride, \
+ asid, tlb_level, tlbi_user, lpa2) \
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 890ba8e48bc39..b07f8b007ed9b 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -2612,31 +2612,16 @@ config MITIGATION_RFDS
+ stored in floating point, vector and integer registers.
+ See also <file:Documentation/admin-guide/hw-vuln/reg-file-data-sampling.rst>
+
+-choice
+- prompt "Clear branch history"
++config MITIGATION_SPECTRE_BHI
++ bool "Mitigate Spectre-BHB (Branch History Injection)"
+ depends on CPU_SUP_INTEL
+- default SPECTRE_BHI_ON
++ default y
+ help
+ Enable BHI mitigations. BHI attacks are a form of Spectre V2 attacks
+ where the branch history buffer is poisoned to speculatively steer
+ indirect branches.
+ See <file:Documentation/admin-guide/hw-vuln/spectre.rst>
+
+-config SPECTRE_BHI_ON
+- bool "on"
+- help
+- Equivalent to setting spectre_bhi=on command line parameter.
+-config SPECTRE_BHI_OFF
+- bool "off"
+- help
+- Equivalent to setting spectre_bhi=off command line parameter.
+-config SPECTRE_BHI_AUTO
+- bool "auto"
+- help
+- Equivalent to setting spectre_bhi=auto command line parameter.
+-
+-endchoice
+-
+ endif
+
+ config ARCH_HAS_ADD_PAGES
+diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
+index 09050641ce5d3..5b0dd07b1ef19 100644
+--- a/arch/x86/events/core.c
++++ b/arch/x86/events/core.c
+@@ -1644,6 +1644,7 @@ static void x86_pmu_del(struct perf_event *event, int flags)
+ while (++i < cpuc->n_events) {
+ cpuc->event_list[i-1] = cpuc->event_list[i];
+ cpuc->event_constraint[i-1] = cpuc->event_constraint[i];
++ cpuc->assign[i-1] = cpuc->assign[i];
+ }
+ cpuc->event_constraint[i-1] = NULL;
+ --cpuc->n_events;
+diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
+index 9d159b771dc81..dddd3fc195efa 100644
+--- a/arch/x86/include/asm/apic.h
++++ b/arch/x86/include/asm/apic.h
+@@ -13,6 +13,7 @@
+ #include <asm/mpspec.h>
+ #include <asm/msr.h>
+ #include <asm/hardirq.h>
++#include <asm/io.h>
+
+ #define ARCH_APICTIMER_STOPS_ON_C3 1
+
+@@ -96,7 +97,7 @@ static inline void native_apic_mem_write(u32 reg, u32 v)
+
+ static inline u32 native_apic_mem_read(u32 reg)
+ {
+- return *((volatile u32 *)(APIC_BASE + reg));
++ return readl((void __iomem *)(APIC_BASE + reg));
+ }
+
+ static inline void native_apic_mem_eoi(void)
+diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
+index 4667bc4b00ab8..75bd5ac7ac6a9 100644
+--- a/arch/x86/kernel/apic/apic.c
++++ b/arch/x86/kernel/apic/apic.c
+@@ -1724,11 +1724,11 @@ static int x2apic_state;
+
+ static bool x2apic_hw_locked(void)
+ {
+- u64 ia32_cap;
++ u64 x86_arch_cap_msr;
+ u64 msr;
+
+- ia32_cap = x86_read_arch_cap_msr();
+- if (ia32_cap & ARCH_CAP_XAPIC_DISABLE) {
++ x86_arch_cap_msr = x86_read_arch_cap_msr();
++ if (x86_arch_cap_msr & ARCH_CAP_XAPIC_DISABLE) {
+ rdmsrl(MSR_IA32_XAPIC_DISABLE_STATUS, msr);
+ return (msr & LEGACY_XAPIC_DISABLED);
+ }
+diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
+index 0d7238d88b38a..cbc8c88144e47 100644
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -61,6 +61,8 @@ EXPORT_SYMBOL_GPL(x86_spec_ctrl_current);
+ u64 x86_pred_cmd __ro_after_init = PRED_CMD_IBPB;
+ EXPORT_SYMBOL_GPL(x86_pred_cmd);
+
++static u64 __ro_after_init x86_arch_cap_msr;
++
+ static DEFINE_MUTEX(spec_ctrl_mutex);
+
+ void (*x86_return_thunk)(void) __ro_after_init = __x86_return_thunk;
+@@ -144,6 +146,8 @@ void __init cpu_select_mitigations(void)
+ x86_spec_ctrl_base &= ~SPEC_CTRL_MITIGATIONS_MASK;
+ }
+
++ x86_arch_cap_msr = x86_read_arch_cap_msr();
++
+ /* Select the proper CPU mitigations before patching alternatives: */
+ spectre_v1_select_mitigation();
+ spectre_v2_select_mitigation();
+@@ -301,8 +305,6 @@ static const char * const taa_strings[] = {
+
+ static void __init taa_select_mitigation(void)
+ {
+- u64 ia32_cap;
+-
+ if (!boot_cpu_has_bug(X86_BUG_TAA)) {
+ taa_mitigation = TAA_MITIGATION_OFF;
+ return;
+@@ -341,9 +343,8 @@ static void __init taa_select_mitigation(void)
+ * On MDS_NO=1 CPUs if ARCH_CAP_TSX_CTRL_MSR is not set, microcode
+ * update is required.
+ */
+- ia32_cap = x86_read_arch_cap_msr();
+- if ( (ia32_cap & ARCH_CAP_MDS_NO) &&
+- !(ia32_cap & ARCH_CAP_TSX_CTRL_MSR))
++ if ( (x86_arch_cap_msr & ARCH_CAP_MDS_NO) &&
++ !(x86_arch_cap_msr & ARCH_CAP_TSX_CTRL_MSR))
+ taa_mitigation = TAA_MITIGATION_UCODE_NEEDED;
+
+ /*
+@@ -401,8 +402,6 @@ static const char * const mmio_strings[] = {
+
+ static void __init mmio_select_mitigation(void)
+ {
+- u64 ia32_cap;
+-
+ if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) ||
+ boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN) ||
+ cpu_mitigations_off()) {
+@@ -413,8 +412,6 @@ static void __init mmio_select_mitigation(void)
+ if (mmio_mitigation == MMIO_MITIGATION_OFF)
+ return;
+
+- ia32_cap = x86_read_arch_cap_msr();
+-
+ /*
+ * Enable CPU buffer clear mitigation for host and VMM, if also affected
+ * by MDS or TAA. Otherwise, enable mitigation for VMM only.
+@@ -437,7 +434,7 @@ static void __init mmio_select_mitigation(void)
+ * be propagated to uncore buffers, clearing the Fill buffers on idle
+ * is required irrespective of SMT state.
+ */
+- if (!(ia32_cap & ARCH_CAP_FBSDP_NO))
++ if (!(x86_arch_cap_msr & ARCH_CAP_FBSDP_NO))
+ static_branch_enable(&mds_idle_clear);
+
+ /*
+@@ -447,10 +444,10 @@ static void __init mmio_select_mitigation(void)
+ * FB_CLEAR or by the presence of both MD_CLEAR and L1D_FLUSH on MDS
+ * affected systems.
+ */
+- if ((ia32_cap & ARCH_CAP_FB_CLEAR) ||
++ if ((x86_arch_cap_msr & ARCH_CAP_FB_CLEAR) ||
+ (boot_cpu_has(X86_FEATURE_MD_CLEAR) &&
+ boot_cpu_has(X86_FEATURE_FLUSH_L1D) &&
+- !(ia32_cap & ARCH_CAP_MDS_NO)))
++ !(x86_arch_cap_msr & ARCH_CAP_MDS_NO)))
+ mmio_mitigation = MMIO_MITIGATION_VERW;
+ else
+ mmio_mitigation = MMIO_MITIGATION_UCODE_NEEDED;
+@@ -508,7 +505,7 @@ static void __init rfds_select_mitigation(void)
+ if (rfds_mitigation == RFDS_MITIGATION_OFF)
+ return;
+
+- if (x86_read_arch_cap_msr() & ARCH_CAP_RFDS_CLEAR)
++ if (x86_arch_cap_msr & ARCH_CAP_RFDS_CLEAR)
+ setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF);
+ else
+ rfds_mitigation = RFDS_MITIGATION_UCODE_NEEDED;
+@@ -659,8 +656,6 @@ void update_srbds_msr(void)
+
+ static void __init srbds_select_mitigation(void)
+ {
+- u64 ia32_cap;
+-
+ if (!boot_cpu_has_bug(X86_BUG_SRBDS))
+ return;
+
+@@ -669,8 +664,7 @@ static void __init srbds_select_mitigation(void)
+ * are only exposed to SRBDS when TSX is enabled or when CPU is affected
+ * by Processor MMIO Stale Data vulnerability.
+ */
+- ia32_cap = x86_read_arch_cap_msr();
+- if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) &&
++ if ((x86_arch_cap_msr & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) &&
+ !boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA))
+ srbds_mitigation = SRBDS_MITIGATION_TSX_OFF;
+ else if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+@@ -813,7 +807,7 @@ static void __init gds_select_mitigation(void)
+ /* Will verify below that mitigation _can_ be disabled */
+
+ /* No microcode */
+- if (!(x86_read_arch_cap_msr() & ARCH_CAP_GDS_CTRL)) {
++ if (!(x86_arch_cap_msr & ARCH_CAP_GDS_CTRL)) {
+ if (gds_mitigation == GDS_MITIGATION_FORCE) {
+ /*
+ * This only needs to be done on the boot CPU so do it
+@@ -1543,20 +1537,25 @@ static enum spectre_v2_mitigation __init spectre_v2_select_retpoline(void)
+ return SPECTRE_V2_RETPOLINE;
+ }
+
++static bool __ro_after_init rrsba_disabled;
++
+ /* Disable in-kernel use of non-RSB RET predictors */
+ static void __init spec_ctrl_disable_kernel_rrsba(void)
+ {
+- u64 ia32_cap;
++ if (rrsba_disabled)
++ return;
+
+- if (!boot_cpu_has(X86_FEATURE_RRSBA_CTRL))
++ if (!(x86_arch_cap_msr & ARCH_CAP_RRSBA)) {
++ rrsba_disabled = true;
+ return;
++ }
+
+- ia32_cap = x86_read_arch_cap_msr();
++ if (!boot_cpu_has(X86_FEATURE_RRSBA_CTRL))
++ return;
+
+- if (ia32_cap & ARCH_CAP_RRSBA) {
+- x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S;
+- update_spec_ctrl(x86_spec_ctrl_base);
+- }
++ x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S;
++ update_spec_ctrl(x86_spec_ctrl_base);
++ rrsba_disabled = true;
+ }
+
+ static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_mitigation mode)
+@@ -1625,13 +1624,10 @@ static bool __init spec_ctrl_bhi_dis(void)
+ enum bhi_mitigations {
+ BHI_MITIGATION_OFF,
+ BHI_MITIGATION_ON,
+- BHI_MITIGATION_AUTO,
+ };
+
+ static enum bhi_mitigations bhi_mitigation __ro_after_init =
+- IS_ENABLED(CONFIG_SPECTRE_BHI_ON) ? BHI_MITIGATION_ON :
+- IS_ENABLED(CONFIG_SPECTRE_BHI_OFF) ? BHI_MITIGATION_OFF :
+- BHI_MITIGATION_AUTO;
++ IS_ENABLED(CONFIG_MITIGATION_SPECTRE_BHI) ? BHI_MITIGATION_ON : BHI_MITIGATION_OFF;
+
+ static int __init spectre_bhi_parse_cmdline(char *str)
+ {
+@@ -1642,8 +1638,6 @@ static int __init spectre_bhi_parse_cmdline(char *str)
+ bhi_mitigation = BHI_MITIGATION_OFF;
+ else if (!strcmp(str, "on"))
+ bhi_mitigation = BHI_MITIGATION_ON;
+- else if (!strcmp(str, "auto"))
+- bhi_mitigation = BHI_MITIGATION_AUTO;
+ else
+ pr_err("Ignoring unknown spectre_bhi option (%s)", str);
+
+@@ -1657,9 +1651,11 @@ static void __init bhi_select_mitigation(void)
+ return;
+
+ /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */
+- if (cpu_feature_enabled(X86_FEATURE_RETPOLINE) &&
+- !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA))
+- return;
++ if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) {
++ spec_ctrl_disable_kernel_rrsba();
++ if (rrsba_disabled)
++ return;
++ }
+
+ if (spec_ctrl_bhi_dis())
+ return;
+@@ -1671,9 +1667,6 @@ static void __init bhi_select_mitigation(void)
+ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT);
+ pr_info("Spectre BHI mitigation: SW BHB clearing on vm exit\n");
+
+- if (bhi_mitigation == BHI_MITIGATION_AUTO)
+- return;
+-
+ /* Mitigate syscalls when the mitigation is forced =on */
+ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP);
+ pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n");
+@@ -1907,8 +1900,6 @@ static void update_indir_branch_cond(void)
+ /* Update the static key controlling the MDS CPU buffer clear in idle */
+ static void update_mds_branch_idle(void)
+ {
+- u64 ia32_cap = x86_read_arch_cap_msr();
+-
+ /*
+ * Enable the idle clearing if SMT is active on CPUs which are
+ * affected only by MSBDS and not any other MDS variant.
+@@ -1923,7 +1914,7 @@ static void update_mds_branch_idle(void)
+ if (sched_smt_active()) {
+ static_branch_enable(&mds_idle_clear);
+ } else if (mmio_mitigation == MMIO_MITIGATION_OFF ||
+- (ia32_cap & ARCH_CAP_FBSDP_NO)) {
++ (x86_arch_cap_msr & ARCH_CAP_FBSDP_NO)) {
+ static_branch_disable(&mds_idle_clear);
+ }
+ }
+@@ -2808,7 +2799,7 @@ static char *pbrsb_eibrs_state(void)
+ }
+ }
+
+-static const char * const spectre_bhi_state(void)
++static const char *spectre_bhi_state(void)
+ {
+ if (!boot_cpu_has_bug(X86_BUG_BHI))
+ return "; BHI: Not affected";
+@@ -2816,13 +2807,12 @@ static const char * const spectre_bhi_state(void)
+ return "; BHI: BHI_DIS_S";
+ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
+ return "; BHI: SW loop, KVM: SW loop";
+- else if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
+- !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA))
++ else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && rrsba_disabled)
+ return "; BHI: Retpoline";
+- else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
+- return "; BHI: Syscall hardening, KVM: SW loop";
++ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
++ return "; BHI: Vulnerable, KVM: SW loop";
+
+- return "; BHI: Vulnerable (Syscall hardening enabled)";
++ return "; BHI: Vulnerable";
+ }
+
+ static ssize_t spectre_v2_show_state(char *buf)
+diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
+index 785fedddb5f09..46603c6e400aa 100644
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -1327,25 +1327,25 @@ static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long whi
+
+ u64 x86_read_arch_cap_msr(void)
+ {
+- u64 ia32_cap = 0;
++ u64 x86_arch_cap_msr = 0;
+
+ if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES))
+- rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap);
++ rdmsrl(MSR_IA32_ARCH_CAPABILITIES, x86_arch_cap_msr);
+
+- return ia32_cap;
++ return x86_arch_cap_msr;
+ }
+
+-static bool arch_cap_mmio_immune(u64 ia32_cap)
++static bool arch_cap_mmio_immune(u64 x86_arch_cap_msr)
+ {
+- return (ia32_cap & ARCH_CAP_FBSDP_NO &&
+- ia32_cap & ARCH_CAP_PSDP_NO &&
+- ia32_cap & ARCH_CAP_SBDR_SSDP_NO);
++ return (x86_arch_cap_msr & ARCH_CAP_FBSDP_NO &&
++ x86_arch_cap_msr & ARCH_CAP_PSDP_NO &&
++ x86_arch_cap_msr & ARCH_CAP_SBDR_SSDP_NO);
+ }
+
+-static bool __init vulnerable_to_rfds(u64 ia32_cap)
++static bool __init vulnerable_to_rfds(u64 x86_arch_cap_msr)
+ {
+ /* The "immunity" bit trumps everything else: */
+- if (ia32_cap & ARCH_CAP_RFDS_NO)
++ if (x86_arch_cap_msr & ARCH_CAP_RFDS_NO)
+ return false;
+
+ /*
+@@ -1353,7 +1353,7 @@ static bool __init vulnerable_to_rfds(u64 ia32_cap)
+ * indicate that mitigation is needed because guest is running on a
+ * vulnerable hardware or may migrate to such hardware:
+ */
+- if (ia32_cap & ARCH_CAP_RFDS_CLEAR)
++ if (x86_arch_cap_msr & ARCH_CAP_RFDS_CLEAR)
+ return true;
+
+ /* Only consult the blacklist when there is no enumeration: */
+@@ -1362,11 +1362,11 @@ static bool __init vulnerable_to_rfds(u64 ia32_cap)
+
+ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ {
+- u64 ia32_cap = x86_read_arch_cap_msr();
++ u64 x86_arch_cap_msr = x86_read_arch_cap_msr();
+
+ /* Set ITLB_MULTIHIT bug if cpu is not in the whitelist and not mitigated */
+ if (!cpu_matches(cpu_vuln_whitelist, NO_ITLB_MULTIHIT) &&
+- !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO))
++ !(x86_arch_cap_msr & ARCH_CAP_PSCHANGE_MC_NO))
+ setup_force_cpu_bug(X86_BUG_ITLB_MULTIHIT);
+
+ if (cpu_matches(cpu_vuln_whitelist, NO_SPECULATION))
+@@ -1378,7 +1378,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
+
+ if (!cpu_matches(cpu_vuln_whitelist, NO_SSB) &&
+- !(ia32_cap & ARCH_CAP_SSB_NO) &&
++ !(x86_arch_cap_msr & ARCH_CAP_SSB_NO) &&
+ !cpu_has(c, X86_FEATURE_AMD_SSB_NO))
+ setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
+
+@@ -1386,15 +1386,15 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ * AMD's AutoIBRS is equivalent to Intel's eIBRS - use the Intel feature
+ * flag and protect from vendor-specific bugs via the whitelist.
+ */
+- if ((ia32_cap & ARCH_CAP_IBRS_ALL) || cpu_has(c, X86_FEATURE_AUTOIBRS)) {
++ if ((x86_arch_cap_msr & ARCH_CAP_IBRS_ALL) || cpu_has(c, X86_FEATURE_AUTOIBRS)) {
+ setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED);
+ if (!cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) &&
+- !(ia32_cap & ARCH_CAP_PBRSB_NO))
++ !(x86_arch_cap_msr & ARCH_CAP_PBRSB_NO))
+ setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB);
+ }
+
+ if (!cpu_matches(cpu_vuln_whitelist, NO_MDS) &&
+- !(ia32_cap & ARCH_CAP_MDS_NO)) {
++ !(x86_arch_cap_msr & ARCH_CAP_MDS_NO)) {
+ setup_force_cpu_bug(X86_BUG_MDS);
+ if (cpu_matches(cpu_vuln_whitelist, MSBDS_ONLY))
+ setup_force_cpu_bug(X86_BUG_MSBDS_ONLY);
+@@ -1413,9 +1413,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ * TSX_CTRL check alone is not sufficient for cases when the microcode
+ * update is not present or running as guest that don't get TSX_CTRL.
+ */
+- if (!(ia32_cap & ARCH_CAP_TAA_NO) &&
++ if (!(x86_arch_cap_msr & ARCH_CAP_TAA_NO) &&
+ (cpu_has(c, X86_FEATURE_RTM) ||
+- (ia32_cap & ARCH_CAP_TSX_CTRL_MSR)))
++ (x86_arch_cap_msr & ARCH_CAP_TSX_CTRL_MSR)))
+ setup_force_cpu_bug(X86_BUG_TAA);
+
+ /*
+@@ -1441,7 +1441,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ * Set X86_BUG_MMIO_UNKNOWN for CPUs that are neither in the blacklist,
+ * nor in the whitelist and also don't enumerate MSR ARCH_CAP MMIO bits.
+ */
+- if (!arch_cap_mmio_immune(ia32_cap)) {
++ if (!arch_cap_mmio_immune(x86_arch_cap_msr)) {
+ if (cpu_matches(cpu_vuln_blacklist, MMIO))
+ setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
+ else if (!cpu_matches(cpu_vuln_whitelist, NO_MMIO))
+@@ -1449,7 +1449,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ }
+
+ if (!cpu_has(c, X86_FEATURE_BTC_NO)) {
+- if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA))
++ if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (x86_arch_cap_msr & ARCH_CAP_RSBA))
+ setup_force_cpu_bug(X86_BUG_RETBLEED);
+ }
+
+@@ -1467,15 +1467,15 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ * disabling AVX2. The only way to do this in HW is to clear XCR0[2],
+ * which means that AVX will be disabled.
+ */
+- if (cpu_matches(cpu_vuln_blacklist, GDS) && !(ia32_cap & ARCH_CAP_GDS_NO) &&
++ if (cpu_matches(cpu_vuln_blacklist, GDS) && !(x86_arch_cap_msr & ARCH_CAP_GDS_NO) &&
+ boot_cpu_has(X86_FEATURE_AVX))
+ setup_force_cpu_bug(X86_BUG_GDS);
+
+- if (vulnerable_to_rfds(ia32_cap))
++ if (vulnerable_to_rfds(x86_arch_cap_msr))
+ setup_force_cpu_bug(X86_BUG_RFDS);
+
+ /* When virtualized, eIBRS could be hidden, assume vulnerable */
+- if (!(ia32_cap & ARCH_CAP_BHI_NO) &&
++ if (!(x86_arch_cap_msr & ARCH_CAP_BHI_NO) &&
+ !cpu_matches(cpu_vuln_whitelist, NO_BHI) &&
+ (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED) ||
+ boot_cpu_has(X86_FEATURE_HYPERVISOR)))
+@@ -1485,7 +1485,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ return;
+
+ /* Rogue Data Cache Load? No! */
+- if (ia32_cap & ARCH_CAP_RDCL_NO)
++ if (x86_arch_cap_msr & ARCH_CAP_RDCL_NO)
+ return;
+
+ setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
+diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
+index ff93c385ba5af..4529122e0cbdb 100644
+--- a/block/blk-cgroup.c
++++ b/block/blk-cgroup.c
+@@ -1409,6 +1409,12 @@ static int blkcg_css_online(struct cgroup_subsys_state *css)
+ return 0;
+ }
+
++void blkg_init_queue(struct request_queue *q)
++{
++ INIT_LIST_HEAD(&q->blkg_list);
++ mutex_init(&q->blkcg_mutex);
++}
++
+ int blkcg_init_disk(struct gendisk *disk)
+ {
+ struct request_queue *q = disk->queue;
+@@ -1416,9 +1422,6 @@ int blkcg_init_disk(struct gendisk *disk)
+ bool preloaded;
+ int ret;
+
+- INIT_LIST_HEAD(&q->blkg_list);
+- mutex_init(&q->blkcg_mutex);
+-
+ new_blkg = blkg_alloc(&blkcg_root, disk, GFP_KERNEL);
+ if (!new_blkg)
+ return -ENOMEM;
+diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
+index b927a4a0ad030..5b0bdc268ade9 100644
+--- a/block/blk-cgroup.h
++++ b/block/blk-cgroup.h
+@@ -188,6 +188,7 @@ struct blkcg_policy {
+ extern struct blkcg blkcg_root;
+ extern bool blkcg_debug_stats;
+
++void blkg_init_queue(struct request_queue *q);
+ int blkcg_init_disk(struct gendisk *disk);
+ void blkcg_exit_disk(struct gendisk *disk);
+
+@@ -481,6 +482,7 @@ struct blkcg {
+ };
+
+ static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, void *key) { return NULL; }
++static inline void blkg_init_queue(struct request_queue *q) { }
+ static inline int blkcg_init_disk(struct gendisk *disk) { return 0; }
+ static inline void blkcg_exit_disk(struct gendisk *disk) { }
+ static inline int blkcg_policy_register(struct blkcg_policy *pol) { return 0; }
+diff --git a/block/blk-core.c b/block/blk-core.c
+index de771093b5268..99d684085719d 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -431,6 +431,8 @@ struct request_queue *blk_alloc_queue(int node_id)
+ init_waitqueue_head(&q->mq_freeze_wq);
+ mutex_init(&q->mq_freeze_lock);
+
++ blkg_init_queue(q);
++
+ /*
+ * Init percpu_ref in atomic mode so that it's faster to shutdown.
+ * See blk_register_queue() for details.
+diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c
+index 4b06402269869..b35c7aedca03e 100644
+--- a/drivers/accel/ivpu/ivpu_drv.c
++++ b/drivers/accel/ivpu/ivpu_drv.c
+@@ -131,22 +131,6 @@ static int ivpu_get_capabilities(struct ivpu_device *vdev, struct drm_ivpu_param
+ return 0;
+ }
+
+-static int ivpu_get_core_clock_rate(struct ivpu_device *vdev, u64 *clk_rate)
+-{
+- int ret;
+-
+- ret = ivpu_rpm_get_if_active(vdev);
+- if (ret < 0)
+- return ret;
+-
+- *clk_rate = ret ? ivpu_hw_reg_pll_freq_get(vdev) : 0;
+-
+- if (ret)
+- ivpu_rpm_put(vdev);
+-
+- return 0;
+-}
+-
+ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+ {
+ struct ivpu_file_priv *file_priv = file->driver_priv;
+@@ -170,7 +154,7 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f
+ args->value = vdev->platform;
+ break;
+ case DRM_IVPU_PARAM_CORE_CLOCK_RATE:
+- ret = ivpu_get_core_clock_rate(vdev, &args->value);
++ args->value = ivpu_hw_ratio_to_freq(vdev, vdev->hw->pll.max_ratio);
+ break;
+ case DRM_IVPU_PARAM_NUM_CONTEXTS:
+ args->value = ivpu_get_context_count(vdev);
+@@ -530,7 +514,7 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
+ vdev->context_xa_limit.min = IVPU_USER_CONTEXT_MIN_SSID;
+ vdev->context_xa_limit.max = IVPU_USER_CONTEXT_MAX_SSID;
+ atomic64_set(&vdev->unique_id_counter, 0);
+- xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC);
++ xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
+ xa_init_flags(&vdev->submitted_jobs_xa, XA_FLAGS_ALLOC1);
+ lockdep_set_class(&vdev->submitted_jobs_xa.xa_lock, &submitted_jobs_xa_lock_class_key);
+ INIT_LIST_HEAD(&vdev->bo_list);
+diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h
+index b2909168a0a69..094c659d2800b 100644
+--- a/drivers/accel/ivpu/ivpu_hw.h
++++ b/drivers/accel/ivpu/ivpu_hw.h
+@@ -21,6 +21,7 @@ struct ivpu_hw_ops {
+ u32 (*profiling_freq_get)(struct ivpu_device *vdev);
+ void (*profiling_freq_drive)(struct ivpu_device *vdev, bool enable);
+ u32 (*reg_pll_freq_get)(struct ivpu_device *vdev);
++ u32 (*ratio_to_freq)(struct ivpu_device *vdev, u32 ratio);
+ u32 (*reg_telemetry_offset_get)(struct ivpu_device *vdev);
+ u32 (*reg_telemetry_size_get)(struct ivpu_device *vdev);
+ u32 (*reg_telemetry_enable_get)(struct ivpu_device *vdev);
+@@ -130,6 +131,11 @@ static inline u32 ivpu_hw_reg_pll_freq_get(struct ivpu_device *vdev)
+ return vdev->hw->ops->reg_pll_freq_get(vdev);
+ };
+
++static inline u32 ivpu_hw_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
++{
++ return vdev->hw->ops->ratio_to_freq(vdev, ratio);
++}
++
+ static inline u32 ivpu_hw_reg_telemetry_offset_get(struct ivpu_device *vdev)
+ {
+ return vdev->hw->ops->reg_telemetry_offset_get(vdev);
+diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c
+index 89af1006df558..32bb772e03cf9 100644
+--- a/drivers/accel/ivpu/ivpu_hw_37xx.c
++++ b/drivers/accel/ivpu/ivpu_hw_37xx.c
+@@ -805,12 +805,12 @@ static void ivpu_hw_37xx_profiling_freq_drive(struct ivpu_device *vdev, bool ena
+ /* Profiling freq - is a debug feature. Unavailable on VPU 37XX. */
+ }
+
+-static u32 ivpu_hw_37xx_pll_to_freq(u32 ratio, u32 config)
++static u32 ivpu_hw_37xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
+ {
+ u32 pll_clock = PLL_REF_CLK_FREQ * ratio;
+ u32 cpu_clock;
+
+- if ((config & 0xff) == PLL_RATIO_4_3)
++ if ((vdev->hw->config & 0xff) == PLL_RATIO_4_3)
+ cpu_clock = pll_clock * 2 / 4;
+ else
+ cpu_clock = pll_clock * 2 / 5;
+@@ -829,7 +829,7 @@ static u32 ivpu_hw_37xx_reg_pll_freq_get(struct ivpu_device *vdev)
+ if (!ivpu_is_silicon(vdev))
+ return PLL_SIMULATION_FREQ;
+
+- return ivpu_hw_37xx_pll_to_freq(pll_curr_ratio, vdev->hw->config);
++ return ivpu_hw_37xx_ratio_to_freq(vdev, pll_curr_ratio);
+ }
+
+ static u32 ivpu_hw_37xx_reg_telemetry_offset_get(struct ivpu_device *vdev)
+@@ -1052,6 +1052,7 @@ const struct ivpu_hw_ops ivpu_hw_37xx_ops = {
+ .profiling_freq_get = ivpu_hw_37xx_profiling_freq_get,
+ .profiling_freq_drive = ivpu_hw_37xx_profiling_freq_drive,
+ .reg_pll_freq_get = ivpu_hw_37xx_reg_pll_freq_get,
++ .ratio_to_freq = ivpu_hw_37xx_ratio_to_freq,
+ .reg_telemetry_offset_get = ivpu_hw_37xx_reg_telemetry_offset_get,
+ .reg_telemetry_size_get = ivpu_hw_37xx_reg_telemetry_size_get,
+ .reg_telemetry_enable_get = ivpu_hw_37xx_reg_telemetry_enable_get,
+diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c
+index a1523d0b1ef36..0be353ad872d0 100644
+--- a/drivers/accel/ivpu/ivpu_hw_40xx.c
++++ b/drivers/accel/ivpu/ivpu_hw_40xx.c
+@@ -980,6 +980,11 @@ static u32 ivpu_hw_40xx_reg_pll_freq_get(struct ivpu_device *vdev)
+ return PLL_RATIO_TO_FREQ(pll_curr_ratio);
+ }
+
++static u32 ivpu_hw_40xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
++{
++ return PLL_RATIO_TO_FREQ(ratio);
++}
++
+ static u32 ivpu_hw_40xx_reg_telemetry_offset_get(struct ivpu_device *vdev)
+ {
+ return REGB_RD32(VPU_40XX_BUTTRESS_VPU_TELEMETRY_OFFSET);
+@@ -1230,6 +1235,7 @@ const struct ivpu_hw_ops ivpu_hw_40xx_ops = {
+ .profiling_freq_get = ivpu_hw_40xx_profiling_freq_get,
+ .profiling_freq_drive = ivpu_hw_40xx_profiling_freq_drive,
+ .reg_pll_freq_get = ivpu_hw_40xx_reg_pll_freq_get,
++ .ratio_to_freq = ivpu_hw_40xx_ratio_to_freq,
+ .reg_telemetry_offset_get = ivpu_hw_40xx_reg_telemetry_offset_get,
+ .reg_telemetry_size_get = ivpu_hw_40xx_reg_telemetry_size_get,
+ .reg_telemetry_enable_get = ivpu_hw_40xx_reg_telemetry_enable_get,
+diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c
+index fa66c39b57eca..f4c5392483656 100644
+--- a/drivers/accel/ivpu/ivpu_ipc.c
++++ b/drivers/accel/ivpu/ivpu_ipc.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Copyright (C) 2020-2023 Intel Corporation
++ * Copyright (C) 2020-2024 Intel Corporation
+ */
+
+ #include <linux/genalloc.h>
+@@ -501,7 +501,11 @@ int ivpu_ipc_init(struct ivpu_device *vdev)
+ spin_lock_init(&ipc->cons_lock);
+ INIT_LIST_HEAD(&ipc->cons_list);
+ INIT_LIST_HEAD(&ipc->cb_msg_list);
+- drmm_mutex_init(&vdev->drm, &ipc->lock);
++ ret = drmm_mutex_init(&vdev->drm, &ipc->lock);
++ if (ret) {
++ ivpu_err(vdev, "Failed to initialize ipc->lock, ret %d\n", ret);
++ goto err_free_rx;
++ }
+ ivpu_ipc_reset(vdev);
+ return 0;
+
+diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c
+index 5f73854234ba9..a15d30d0943af 100644
+--- a/drivers/accel/ivpu/ivpu_pm.c
++++ b/drivers/accel/ivpu/ivpu_pm.c
+@@ -74,10 +74,10 @@ static int ivpu_resume(struct ivpu_device *vdev)
+ {
+ int ret;
+
+- pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D0);
++retry:
+ pci_restore_state(to_pci_dev(vdev->drm.dev));
++ pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D0);
+
+-retry:
+ ret = ivpu_hw_power_up(vdev);
+ if (ret) {
+ ivpu_err(vdev, "Failed to power up HW: %d\n", ret);
+@@ -100,6 +100,7 @@ static int ivpu_resume(struct ivpu_device *vdev)
+ ivpu_mmu_disable(vdev);
+ err_power_down:
+ ivpu_hw_power_down(vdev);
++ pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
+
+ if (!ivpu_fw_is_cold_boot(vdev)) {
+ ivpu_pm_prepare_cold_boot(vdev);
+diff --git a/drivers/acpi/numa/hmat.c b/drivers/acpi/numa/hmat.c
+index a26e7793ec4ef..75e9aac43228a 100644
+--- a/drivers/acpi/numa/hmat.c
++++ b/drivers/acpi/numa/hmat.c
+@@ -59,9 +59,8 @@ struct target_cache {
+ };
+
+ enum {
+- NODE_ACCESS_CLASS_0 = 0,
+- NODE_ACCESS_CLASS_1,
+- NODE_ACCESS_CLASS_GENPORT_SINK,
++ NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL = ACCESS_COORDINATE_MAX,
++ NODE_ACCESS_CLASS_GENPORT_SINK_CPU,
+ NODE_ACCESS_CLASS_MAX,
+ };
+
+@@ -127,7 +126,8 @@ static struct memory_target *acpi_find_genport_target(u32 uid)
+ /**
+ * acpi_get_genport_coordinates - Retrieve the access coordinates for a generic port
+ * @uid: ACPI unique id
+- * @coord: The access coordinates written back out for the generic port
++ * @coord: The access coordinates written back out for the generic port.
++ * Expect 2 levels array.
+ *
+ * Return: 0 on success. Errno on failure.
+ *
+@@ -143,7 +143,10 @@ int acpi_get_genport_coordinates(u32 uid,
+ if (!target)
+ return -ENOENT;
+
+- *coord = target->coord[NODE_ACCESS_CLASS_GENPORT_SINK];
++ coord[ACCESS_COORDINATE_LOCAL] =
++ target->coord[NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL];
++ coord[ACCESS_COORDINATE_CPU] =
++ target->coord[NODE_ACCESS_CLASS_GENPORT_SINK_CPU];
+
+ return 0;
+ }
+@@ -374,11 +377,11 @@ static __init void hmat_update_target(unsigned int tgt_pxm, unsigned int init_px
+
+ if (target && target->processor_pxm == init_pxm) {
+ hmat_update_target_access(target, type, value,
+- NODE_ACCESS_CLASS_0);
++ ACCESS_COORDINATE_LOCAL);
+ /* If the node has a CPU, update access 1 */
+ if (node_state(pxm_to_node(init_pxm), N_CPU))
+ hmat_update_target_access(target, type, value,
+- NODE_ACCESS_CLASS_1);
++ ACCESS_COORDINATE_CPU);
+ }
+ }
+
+@@ -697,7 +700,8 @@ static void hmat_update_target_attrs(struct memory_target *target,
+ int i;
+
+ /* Don't update for generic port if there's no device handle */
+- if (access == NODE_ACCESS_CLASS_GENPORT_SINK &&
++ if ((access == NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL ||
++ access == NODE_ACCESS_CLASS_GENPORT_SINK_CPU) &&
+ !(*(u16 *)target->gen_port_device_handle))
+ return;
+
+@@ -709,7 +713,8 @@ static void hmat_update_target_attrs(struct memory_target *target,
+ */
+ if (target->processor_pxm != PXM_INVAL) {
+ cpu_nid = pxm_to_node(target->processor_pxm);
+- if (access == 0 || node_state(cpu_nid, N_CPU)) {
++ if (access == ACCESS_COORDINATE_LOCAL ||
++ node_state(cpu_nid, N_CPU)) {
+ set_bit(target->processor_pxm, p_nodes);
+ return;
+ }
+@@ -737,7 +742,9 @@ static void hmat_update_target_attrs(struct memory_target *target,
+ list_for_each_entry(initiator, &initiators, node) {
+ u32 value;
+
+- if (access == 1 && !initiator->has_cpu) {
++ if ((access == ACCESS_COORDINATE_CPU ||
++ access == NODE_ACCESS_CLASS_GENPORT_SINK_CPU) &&
++ !initiator->has_cpu) {
+ clear_bit(initiator->processor_pxm, p_nodes);
+ continue;
+ }
+@@ -775,15 +782,19 @@ static void hmat_update_generic_target(struct memory_target *target)
+ static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
+
+ hmat_update_target_attrs(target, p_nodes,
+- NODE_ACCESS_CLASS_GENPORT_SINK);
++ NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL);
++ hmat_update_target_attrs(target, p_nodes,
++ NODE_ACCESS_CLASS_GENPORT_SINK_CPU);
+ }
+
+ static void hmat_register_target_initiators(struct memory_target *target)
+ {
+ static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
+
+- __hmat_register_target_initiators(target, p_nodes, 0);
+- __hmat_register_target_initiators(target, p_nodes, 1);
++ __hmat_register_target_initiators(target, p_nodes,
++ ACCESS_COORDINATE_LOCAL);
++ __hmat_register_target_initiators(target, p_nodes,
++ ACCESS_COORDINATE_CPU);
+ }
+
+ static void hmat_register_target_cache(struct memory_target *target)
+@@ -854,8 +865,8 @@ static void hmat_register_target(struct memory_target *target)
+ if (!target->registered) {
+ hmat_register_target_initiators(target);
+ hmat_register_target_cache(target);
+- hmat_register_target_perf(target, NODE_ACCESS_CLASS_0);
+- hmat_register_target_perf(target, NODE_ACCESS_CLASS_1);
++ hmat_register_target_perf(target, ACCESS_COORDINATE_LOCAL);
++ hmat_register_target_perf(target, ACCESS_COORDINATE_CPU);
+ target->registered = true;
+ }
+ mutex_unlock(&target_lock);
+@@ -927,7 +938,7 @@ static int hmat_calculate_adistance(struct notifier_block *self,
+ return NOTIFY_OK;
+
+ mutex_lock(&target_lock);
+- hmat_update_target_attrs(target, p_nodes, 1);
++ hmat_update_target_attrs(target, p_nodes, ACCESS_COORDINATE_CPU);
+ mutex_unlock(&target_lock);
+
+ perf = &target->coord[1];
+diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
+index 617f3e0e963d5..eb4ca85d16ffb 100644
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -1802,7 +1802,8 @@ static void acpi_scan_dep_init(struct acpi_device *adev)
+ if (dep->honor_dep)
+ adev->flags.honor_deps = 1;
+
+- adev->dep_unmet++;
++ if (!dep->met)
++ adev->dep_unmet++;
+ }
+ }
+ }
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index be3412cdb22e7..c449d60d9bb96 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -2539,7 +2539,7 @@ static void ata_dev_config_cdl(struct ata_device *dev)
+ bool cdl_enabled;
+ u64 val;
+
+- if (ata_id_major_version(dev->id) < 12)
++ if (ata_id_major_version(dev->id) < 11)
+ goto not_supported;
+
+ if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE) ||
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 2f4c588376410..e954976891a9f 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -4745,7 +4745,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+ * bail out.
+ */
+ if (ap->pflags & ATA_PFLAG_SUSPENDED)
+- goto unlock;
++ goto unlock_ap;
+
+ if (!sdev)
+ continue;
+@@ -4758,7 +4758,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+ if (do_resume) {
+ ret = scsi_resume_device(sdev);
+ if (ret == -EWOULDBLOCK)
+- goto unlock;
++ goto unlock_scan;
+ dev->flags &= ~ATA_DFLAG_RESUMING;
+ }
+ ret = scsi_rescan_device(sdev);
+@@ -4766,12 +4766,13 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+ spin_lock_irqsave(ap->lock, flags);
+
+ if (ret)
+- goto unlock;
++ goto unlock_ap;
+ }
+ }
+
+-unlock:
++unlock_ap:
+ spin_unlock_irqrestore(ap->lock, flags);
++unlock_scan:
+ mutex_unlock(&ap->scsi_scan_mutex);
+
+ /* Reschedule with a delay if scsi_rescan_device() returned an error */
+diff --git a/drivers/base/node.c b/drivers/base/node.c
+index 1c05640461dd1..a73b0c9a401ad 100644
+--- a/drivers/base/node.c
++++ b/drivers/base/node.c
+@@ -126,7 +126,7 @@ static void node_access_release(struct device *dev)
+ }
+
+ static struct node_access_nodes *node_init_node_access(struct node *node,
+- unsigned int access)
++ enum access_coordinate_class access)
+ {
+ struct node_access_nodes *access_node;
+ struct device *dev;
+@@ -191,7 +191,7 @@ static struct attribute *access_attrs[] = {
+ * @access: The access class the for the given attributes
+ */
+ void node_set_perf_attrs(unsigned int nid, struct access_coordinate *coord,
+- unsigned int access)
++ enum access_coordinate_class access)
+ {
+ struct node_access_nodes *c;
+ struct node *node;
+@@ -689,7 +689,7 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid)
+ */
+ int register_memory_node_under_compute_node(unsigned int mem_nid,
+ unsigned int cpu_nid,
+- unsigned int access)
++ enum access_coordinate_class access)
+ {
+ struct node *init_node, *targ_node;
+ struct node_access_nodes *initiator, *target;
+diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
+index 1a3e6aafbdcc3..af5cb818f84d6 100644
+--- a/drivers/cxl/acpi.c
++++ b/drivers/cxl/acpi.c
+@@ -530,13 +530,15 @@ static int get_genport_coordinates(struct device *dev, struct cxl_dport *dport)
+ if (kstrtou32(acpi_device_uid(hb), 0, &uid))
+ return -EINVAL;
+
+- rc = acpi_get_genport_coordinates(uid, &dport->hb_coord);
++ rc = acpi_get_genport_coordinates(uid, dport->hb_coord);
+ if (rc < 0)
+ return rc;
+
+ /* Adjust back to picoseconds from nanoseconds */
+- dport->hb_coord.read_latency *= 1000;
+- dport->hb_coord.write_latency *= 1000;
++ for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
++ dport->hb_coord[i].read_latency *= 1000;
++ dport->hb_coord[i].write_latency *= 1000;
++ }
+
+ return 0;
+ }
+diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c
+index 0363ca434ef45..fbf167f9d59d4 100644
+--- a/drivers/cxl/core/cdat.c
++++ b/drivers/cxl/core/cdat.c
+@@ -162,15 +162,22 @@ static int cxl_cdat_endpoint_process(struct cxl_port *port,
+ static int cxl_port_perf_data_calculate(struct cxl_port *port,
+ struct xarray *dsmas_xa)
+ {
+- struct access_coordinate c;
++ struct access_coordinate ep_c;
++ struct access_coordinate coord[ACCESS_COORDINATE_MAX];
+ struct dsmas_entry *dent;
+ int valid_entries = 0;
+ unsigned long index;
+ int rc;
+
+- rc = cxl_endpoint_get_perf_coordinates(port, &c);
++ rc = cxl_endpoint_get_perf_coordinates(port, &ep_c);
+ if (rc) {
+- dev_dbg(&port->dev, "Failed to retrieve perf coordinates.\n");
++ dev_dbg(&port->dev, "Failed to retrieve ep perf coordinates.\n");
++ return rc;
++ }
++
++ rc = cxl_hb_get_perf_coordinates(port, coord);
++ if (rc) {
++ dev_dbg(&port->dev, "Failed to retrieve hb perf coordinates.\n");
+ return rc;
+ }
+
+@@ -185,18 +192,19 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
+ xa_for_each(dsmas_xa, index, dent) {
+ int qos_class;
+
+- dent->coord.read_latency = dent->coord.read_latency +
+- c.read_latency;
+- dent->coord.write_latency = dent->coord.write_latency +
+- c.write_latency;
+- dent->coord.read_bandwidth = min_t(int, c.read_bandwidth,
+- dent->coord.read_bandwidth);
+- dent->coord.write_bandwidth = min_t(int, c.write_bandwidth,
+- dent->coord.write_bandwidth);
+-
++ cxl_coordinates_combine(&dent->coord, &dent->coord, &ep_c);
++ /*
++ * Keeping the host bridge coordinates separate from the dsmas
++ * coordinates in order to allow calculation of access class
++ * 0 and 1 for region later.
++ */
++ cxl_coordinates_combine(&coord[ACCESS_COORDINATE_LOCAL],
++ &coord[ACCESS_COORDINATE_LOCAL],
++ &dent->coord);
+ dent->entries = 1;
+- rc = cxl_root->ops->qos_class(cxl_root, &dent->coord, 1,
+- &qos_class);
++ rc = cxl_root->ops->qos_class(cxl_root,
++ &coord[ACCESS_COORDINATE_LOCAL],
++ 1, &qos_class);
+ if (rc != 1)
+ continue;
+
+@@ -484,4 +492,26 @@ void cxl_switch_parse_cdat(struct cxl_port *port)
+ }
+ EXPORT_SYMBOL_NS_GPL(cxl_switch_parse_cdat, CXL);
+
++/**
++ * cxl_coordinates_combine - Combine the two input coordinates
++ *
++ * @out: Output coordinate of c1 and c2 combined
++ * @c1: input coordinates
++ * @c2: input coordinates
++ */
++void cxl_coordinates_combine(struct access_coordinate *out,
++ struct access_coordinate *c1,
++ struct access_coordinate *c2)
++{
++ if (c1->write_bandwidth && c2->write_bandwidth)
++ out->write_bandwidth = min(c1->write_bandwidth,
++ c2->write_bandwidth);
++ out->write_latency = c1->write_latency + c2->write_latency;
++
++ if (c1->read_bandwidth && c2->read_bandwidth)
++ out->read_bandwidth = min(c1->read_bandwidth,
++ c2->read_bandwidth);
++ out->read_latency = c1->read_latency + c2->read_latency;
++}
++
+ MODULE_IMPORT_NS(CXL);
+diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
+index 9adda4795eb78..f0f54aeccc872 100644
+--- a/drivers/cxl/core/mbox.c
++++ b/drivers/cxl/core/mbox.c
+@@ -915,7 +915,7 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds,
+
+ payload->handles[i++] = gen->hdr.handle;
+ dev_dbg(mds->cxlds.dev, "Event log '%d': Clearing %u\n", log,
+- le16_to_cpu(payload->handles[i]));
++ le16_to_cpu(payload->handles[i - 1]));
+
+ if (i == max_handles) {
+ payload->nr_recs = i;
+@@ -958,13 +958,14 @@ static void cxl_mem_get_records_log(struct cxl_memdev_state *mds,
+ .payload_in = &log_type,
+ .size_in = sizeof(log_type),
+ .payload_out = payload,
+- .size_out = mds->payload_size,
+ .min_out = struct_size(payload, records, 0),
+ };
+
+ do {
+ int rc, i;
+
++ mbox_cmd.size_out = mds->payload_size;
++
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
+ if (rc) {
+ dev_err_ratelimited(dev,
+diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
+index e59d9d37aa650..4ae441ef32174 100644
+--- a/drivers/cxl/core/port.c
++++ b/drivers/cxl/core/port.c
+@@ -2096,18 +2096,41 @@ bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd)
+ }
+ EXPORT_SYMBOL_NS_GPL(schedule_cxl_memdev_detach, CXL);
+
+-static void combine_coordinates(struct access_coordinate *c1,
+- struct access_coordinate *c2)
++/**
++ * cxl_hb_get_perf_coordinates - Retrieve performance numbers between initiator
++ * and host bridge
++ *
++ * @port: endpoint cxl_port
++ * @coord: output access coordinates
++ *
++ * Return: errno on failure, 0 on success.
++ */
++int cxl_hb_get_perf_coordinates(struct cxl_port *port,
++ struct access_coordinate *coord)
+ {
+- if (c2->write_bandwidth)
+- c1->write_bandwidth = min(c1->write_bandwidth,
+- c2->write_bandwidth);
+- c1->write_latency += c2->write_latency;
++ struct cxl_port *iter = port;
++ struct cxl_dport *dport;
++
++ if (!is_cxl_endpoint(port))
++ return -EINVAL;
++
++ dport = iter->parent_dport;
++ while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) {
++ iter = to_cxl_port(iter->dev.parent);
++ dport = iter->parent_dport;
++ }
++
++ coord[ACCESS_COORDINATE_LOCAL] =
++ dport->hb_coord[ACCESS_COORDINATE_LOCAL];
++ coord[ACCESS_COORDINATE_CPU] =
++ dport->hb_coord[ACCESS_COORDINATE_CPU];
+
+- if (c2->read_bandwidth)
+- c1->read_bandwidth = min(c1->read_bandwidth,
+- c2->read_bandwidth);
+- c1->read_latency += c2->read_latency;
++ return 0;
++}
++
++static bool parent_port_is_cxl_root(struct cxl_port *port)
++{
++ return is_cxl_root(to_cxl_port(port->dev.parent));
+ }
+
+ /**
+@@ -2129,30 +2152,31 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
+ struct cxl_dport *dport;
+ struct pci_dev *pdev;
+ unsigned int bw;
++ bool is_cxl_root;
+
+ if (!is_cxl_endpoint(port))
+ return -EINVAL;
+
+- dport = iter->parent_dport;
+-
+ /*
+- * Exit the loop when the parent port of the current port is cxl root.
+- * The iterative loop starts at the endpoint and gathers the
+- * latency of the CXL link from the current iter to the next downstream
+- * port each iteration. If the parent is cxl root then there is
+- * nothing to gather.
++ * Exit the loop when the parent port of the current iter port is cxl
++ * root. The iterative loop starts at the endpoint and gathers the
++ * latency of the CXL link from the current device/port to the connected
++ * downstream port each iteration.
+ */
+- while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) {
+- combine_coordinates(&c, &dport->sw_coord);
+- c.write_latency += dport->link_latency;
+- c.read_latency += dport->link_latency;
+-
+- iter = to_cxl_port(iter->dev.parent);
++ do {
+ dport = iter->parent_dport;
+- }
++ iter = to_cxl_port(iter->dev.parent);
++ is_cxl_root = parent_port_is_cxl_root(iter);
+
+- /* Augment with the generic port (host bridge) perf data */
+- combine_coordinates(&c, &dport->hb_coord);
++ /*
++ * There's no valid access_coordinate for a root port since RPs do not
++ * have CDAT and therefore needs to be skipped.
++ */
++ if (!is_cxl_root)
++ cxl_coordinates_combine(&c, &c, &dport->sw_coord);
++ c.write_latency += dport->link_latency;
++ c.read_latency += dport->link_latency;
++ } while (!is_cxl_root);
+
+ /* Get the calculated PCI paths bandwidth */
+ pdev = to_pci_dev(port->uport_dev->parent);
+diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
+index 372786f809555..3c42f984eeafa 100644
+--- a/drivers/cxl/core/regs.c
++++ b/drivers/cxl/core/regs.c
+@@ -271,6 +271,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_map_device_regs, CXL);
+ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi,
+ struct cxl_register_map *map)
+ {
++ u8 reg_type = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BLOCK_ID_MASK, reg_lo);
+ int bar = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BIR_MASK, reg_lo);
+ u64 offset = ((u64)reg_hi << 32) |
+ (reg_lo & CXL_DVSEC_REG_LOCATOR_BLOCK_OFF_LOW_MASK);
+@@ -278,11 +279,11 @@ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi,
+ if (offset > pci_resource_len(pdev, bar)) {
+ dev_warn(&pdev->dev,
+ "BAR%d: %pr: too small (offset: %pa, type: %d)\n", bar,
+- &pdev->resource[bar], &offset, map->reg_type);
++ &pdev->resource[bar], &offset, reg_type);
+ return false;
+ }
+
+- map->reg_type = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BLOCK_ID_MASK, reg_lo);
++ map->reg_type = reg_type;
+ map->resource = pci_resource_start(pdev, bar) + offset;
+ map->max_size = pci_resource_len(pdev, bar) - offset;
+ return true;
+diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
+index 003feebab79b5..de477eb7f5d54 100644
+--- a/drivers/cxl/cxl.h
++++ b/drivers/cxl/cxl.h
+@@ -671,7 +671,7 @@ struct cxl_dport {
+ struct cxl_port *port;
+ struct cxl_regs regs;
+ struct access_coordinate sw_coord;
+- struct access_coordinate hb_coord;
++ struct access_coordinate hb_coord[ACCESS_COORDINATE_MAX];
+ long link_latency;
+ };
+
+@@ -879,9 +879,15 @@ void cxl_switch_parse_cdat(struct cxl_port *port);
+
+ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
+ struct access_coordinate *coord);
++int cxl_hb_get_perf_coordinates(struct cxl_port *port,
++ struct access_coordinate *coord);
+
+ void cxl_memdev_update_perf(struct cxl_memdev *cxlmd);
+
++void cxl_coordinates_combine(struct access_coordinate *out,
++ struct access_coordinate *c1,
++ struct access_coordinate *c2);
++
+ /*
+ * Unit test builds overrides this to __weak, find the 'strong' version
+ * of these symbols in tools/testing/cxl/.
+diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
+index f2556a8e94015..9bc2e10381afd 100644
+--- a/drivers/firmware/arm_ffa/driver.c
++++ b/drivers/firmware/arm_ffa/driver.c
+@@ -790,7 +790,7 @@ static void ffa_notification_info_get(void)
+
+ part_id = packed_id_list[ids_processed++];
+
+- if (!ids_count[list]) { /* Global Notification */
++ if (ids_count[list] == 1) { /* Global Notification */
+ __do_sched_recv_cb(part_id, 0, false);
+ continue;
+ }
+diff --git a/drivers/firmware/arm_scmi/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c
+index 3505735185033..130d13e9cd6be 100644
+--- a/drivers/firmware/arm_scmi/raw_mode.c
++++ b/drivers/firmware/arm_scmi/raw_mode.c
+@@ -921,7 +921,7 @@ static int scmi_dbg_raw_mode_open(struct inode *inode, struct file *filp)
+ rd->raw = raw;
+ filp->private_data = rd;
+
+- return 0;
++ return nonseekable_open(inode, filp);
+ }
+
+ static int scmi_dbg_raw_mode_release(struct inode *inode, struct file *filp)
+@@ -950,6 +950,7 @@ static const struct file_operations scmi_dbg_raw_mode_reset_fops = {
+ .open = scmi_dbg_raw_mode_open,
+ .release = scmi_dbg_raw_mode_release,
+ .write = scmi_dbg_raw_mode_reset_write,
++ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+ };
+
+@@ -959,6 +960,7 @@ static const struct file_operations scmi_dbg_raw_mode_message_fops = {
+ .read = scmi_dbg_raw_mode_message_read,
+ .write = scmi_dbg_raw_mode_message_write,
+ .poll = scmi_dbg_raw_mode_message_poll,
++ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+ };
+
+@@ -975,6 +977,7 @@ static const struct file_operations scmi_dbg_raw_mode_message_async_fops = {
+ .read = scmi_dbg_raw_mode_message_read,
+ .write = scmi_dbg_raw_mode_message_async_write,
+ .poll = scmi_dbg_raw_mode_message_poll,
++ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+ };
+
+@@ -998,6 +1001,7 @@ static const struct file_operations scmi_dbg_raw_mode_notification_fops = {
+ .release = scmi_dbg_raw_mode_release,
+ .read = scmi_test_dbg_raw_mode_notif_read,
+ .poll = scmi_test_dbg_raw_mode_notif_poll,
++ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+ };
+
+@@ -1021,6 +1025,7 @@ static const struct file_operations scmi_dbg_raw_mode_errors_fops = {
+ .release = scmi_dbg_raw_mode_release,
+ .read = scmi_test_dbg_raw_mode_errors_read,
+ .poll = scmi_test_dbg_raw_mode_errors_poll,
++ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+ };
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
+index b9a15d51eb5c3..ad44012cc01e2 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
+@@ -390,6 +390,12 @@ static int vpe_hw_init(void *handle)
+ struct amdgpu_vpe *vpe = &adev->vpe;
+ int ret;
+
++ /* Power on VPE */
++ ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VPE,
++ AMD_PG_STATE_UNGATE);
++ if (ret)
++ return ret;
++
+ ret = vpe_load_microcode(vpe);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+index 4f3bfdc75b37d..0afe86bcc932b 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+@@ -1630,7 +1630,7 @@ static void gfx_v11_0_setup_rb(struct amdgpu_device *adev)
+ active_rb_bitmap |= (0x3 << (i * rb_bitmap_width_per_sa));
+ }
+
+- active_rb_bitmap |= global_active_rb_bitmap;
++ active_rb_bitmap &= global_active_rb_bitmap;
+ adev->gfx.config.backend_enable_mask = active_rb_bitmap;
+ adev->gfx.config.num_rbs = hweight32(active_rb_bitmap);
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c
+index 4d7188912edfe..fd4505fa4f670 100644
+--- a/drivers/gpu/drm/amd/amdgpu/soc21.c
++++ b/drivers/gpu/drm/amd/amdgpu/soc21.c
+@@ -450,10 +450,8 @@ static bool soc21_need_full_reset(struct amdgpu_device *adev)
+ {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
+ case IP_VERSION(11, 0, 0):
+- return amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC);
+ case IP_VERSION(11, 0, 2):
+ case IP_VERSION(11, 0, 3):
+- return false;
+ default:
+ return true;
+ }
+@@ -714,7 +712,10 @@ static int soc21_common_early_init(void *handle)
+ AMD_PG_SUPPORT_VCN |
+ AMD_PG_SUPPORT_JPEG |
+ AMD_PG_SUPPORT_GFX_PG;
+- adev->external_rev_id = adev->rev_id + 0x1;
++ if (adev->rev_id == 0)
++ adev->external_rev_id = 0x1;
++ else
++ adev->external_rev_id = adev->rev_id + 0x10;
+ break;
+ default:
+ /* FIXME: not supported yet */
+@@ -832,10 +833,35 @@ static int soc21_common_suspend(void *handle)
+ return soc21_common_hw_fini(adev);
+ }
+
++static bool soc21_need_reset_on_resume(struct amdgpu_device *adev)
++{
++ u32 sol_reg1, sol_reg2;
++
++ /* Will reset for the following suspend abort cases.
++ * 1) Only reset dGPU side.
++ * 2) S3 suspend got aborted and TOS is active.
++ */
++ if (!(adev->flags & AMD_IS_APU) && adev->in_s3 &&
++ !adev->suspend_complete) {
++ sol_reg1 = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81);
++ msleep(100);
++ sol_reg2 = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81);
++
++ return (sol_reg1 != sol_reg2);
++ }
++
++ return false;
++}
++
+ static int soc21_common_resume(void *handle)
+ {
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
++ if (soc21_need_reset_on_resume(adev)) {
++ dev_info(adev->dev, "S3 suspend aborted, resetting...");
++ soc21_asic_reset(adev);
++ }
++
+ return soc21_common_hw_init(adev);
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
+index 8e7b763cfdb7e..fd23cd348552b 100644
+--- a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
+@@ -225,6 +225,8 @@ static int umsch_mm_v4_0_ring_start(struct amdgpu_umsch_mm *umsch)
+
+ WREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_SIZE, ring->ring_size);
+
++ ring->wptr = 0;
++
+ data = RREG32_SOC15(VCN, 0, regVCN_RB_ENABLE);
+ data &= ~(VCN_RB_ENABLE__AUDIO_RB_EN_MASK);
+ WREG32_SOC15(VCN, 0, regVCN_RB_ENABLE, data);
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+index c0e71543389a9..c0ae1a97498b5 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+@@ -1997,6 +1997,7 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
+ dev_err(dev, "HIQ MQD's queue_doorbell_id0 is not 0, Queue preemption time out\n");
+ while (halt_if_hws_hang)
+ schedule();
++ kfd_hws_hang(dqm);
+ return -ETIME;
+ }
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 1eb0f82e9dfae..718e533ab46dd 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -6257,19 +6257,16 @@ create_stream_for_sink(struct drm_connector *connector,
+ if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+ mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket);
+
+- if (stream->link->psr_settings.psr_feature_enabled || stream->link->replay_settings.replay_feature_enabled) {
++ if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
++ stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
++ stream->signal == SIGNAL_TYPE_EDP) {
+ //
+ // should decide stream support vsc sdp colorimetry capability
+ // before building vsc info packet
+ //
+- stream->use_vsc_sdp_for_colorimetry = false;
+- if (aconnector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+- stream->use_vsc_sdp_for_colorimetry =
+- aconnector->dc_sink->is_vsc_sdp_colorimetry_supported;
+- } else {
+- if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED)
+- stream->use_vsc_sdp_for_colorimetry = true;
+- }
++ stream->use_vsc_sdp_for_colorimetry = stream->link->dpcd_caps.dpcd_rev.raw >= 0x14 &&
++ stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED;
++
+ if (stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22)
+ tf = TRANSFER_FUNC_GAMMA_22;
+ mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space, tf);
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
+index 16e72d623630c..08c494a7a21ba 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
+@@ -76,10 +76,8 @@ static int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder,
+
+ static int amdgpu_dm_wb_connector_get_modes(struct drm_connector *connector)
+ {
+- struct drm_device *dev = connector->dev;
+-
+- return drm_add_modes_noedid(connector, dev->mode_config.max_width,
+- dev->mode_config.max_height);
++ /* Maximum resolution supported by DWB */
++ return drm_add_modes_noedid(connector, 3840, 2160);
+ }
+
+ static int amdgpu_dm_wb_prepare_job(struct drm_writeback_connector *wb_connector,
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
+index 12f3e8aa46d8d..6ad4f4efec5dd 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
+@@ -99,20 +99,25 @@ static int dcn316_get_active_display_cnt_wa(
+ return display_count;
+ }
+
+-static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable)
++static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context,
++ bool safe_to_lower, bool disable)
+ {
+ struct dc *dc = clk_mgr_base->ctx->dc;
+ int i;
+
+ for (i = 0; i < dc->res_pool->pipe_count; ++i) {
+- struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
++ struct pipe_ctx *pipe = safe_to_lower
++ ? &context->res_ctx.pipe_ctx[i]
++ : &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (pipe->top_pipe || pipe->prev_odm_pipe)
+ continue;
+- if (pipe->stream && (pipe->stream->dpms_off || pipe->plane_state == NULL ||
+- dc_is_virtual_signal(pipe->stream->signal))) {
++ if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) ||
++ !pipe->stream->link_enc)) {
+ if (disable) {
+- pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
++ if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->immediate_disable_crtc)
++ pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
++
+ reset_sync_context_for_pipe(dc, context, i);
+ } else
+ pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
+@@ -207,11 +212,11 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base,
+ }
+
+ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
+- dcn316_disable_otg_wa(clk_mgr_base, context, true);
++ dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true);
+
+ clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
+ dcn316_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz);
+- dcn316_disable_otg_wa(clk_mgr_base, context, false);
++ dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false);
+
+ update_dispclk = true;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+index 5cc7f8da209c5..61986e5cb4919 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+@@ -436,6 +436,15 @@ bool dc_state_add_plane(
+ goto out;
+ }
+
++ if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm)
++ /* ODM combine could prevent us from supporting more planes
++ * we will reset ODM slice count back to 1 when all planes have
++ * been removed to maximize the amount of planes supported when
++ * new planes are added.
++ */
++ resource_update_pipes_for_stream_with_slice_count(
++ state, dc->current_state, dc->res_pool, stream, 1);
++
+ otg_master_pipe = resource_get_otg_master_for_stream(
+ &state->res_ctx, stream);
+ if (otg_master_pipe)
+diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
+index f07a4c7e48bc2..52eab8fccb7f1 100644
+--- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
++++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
+@@ -267,9 +267,6 @@ static void optc32_setup_manual_trigger(struct timing_generator *optc)
+ OTG_V_TOTAL_MAX_SEL, 1,
+ OTG_FORCE_LOCK_ON_EVENT, 0,
+ OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */
+-
+- // Setup manual flow control for EOF via TRIG_A
+- optc->funcs->setup_manual_trigger(optc);
+ }
+ }
+
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
+index bb98156b2fa1d..949131bd1ecb2 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
+@@ -226,8 +226,18 @@ static int smu_v13_0_4_system_features_control(struct smu_context *smu, bool en)
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+
+- if (!en && !adev->in_s0ix)
++ if (!en && !adev->in_s0ix) {
++ /* Adds a GFX reset as workaround just before sending the
++ * MP1_UNLOAD message to prevent GC/RLC/PMFW from entering
++ * an invalid state.
++ */
++ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset,
++ SMU_RESET_MODE_2, NULL);
++ if (ret)
++ return ret;
++
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
++ }
+
+ return ret;
+ }
+diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
+index ebb6d8ebd44eb..1e9259416980e 100644
+--- a/drivers/gpu/drm/ast/ast_dp.c
++++ b/drivers/gpu/drm/ast/ast_dp.c
+@@ -180,6 +180,7 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on)
+ {
+ struct ast_device *ast = to_ast_device(dev);
+ u8 video_on_off = on;
++ u32 i = 0;
+
+ // Video On/Off
+ ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on);
+@@ -192,6 +193,8 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on)
+ ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
+ // wait 1 ms
+ mdelay(1);
++ if (++i > 200)
++ break;
+ }
+ }
+ }
+diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
+index 871e4e2129d6d..0683a129b3628 100644
+--- a/drivers/gpu/drm/drm_client_modeset.c
++++ b/drivers/gpu/drm/drm_client_modeset.c
+@@ -777,6 +777,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
+ unsigned int total_modes_count = 0;
+ struct drm_client_offset *offsets;
+ unsigned int connector_count = 0;
++ /* points to modes protected by mode_config.mutex */
+ struct drm_display_mode **modes;
+ struct drm_crtc **crtcs;
+ int i, ret = 0;
+@@ -845,7 +846,6 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
+ drm_client_pick_crtcs(client, connectors, connector_count,
+ crtcs, modes, 0, width, height);
+ }
+- mutex_unlock(&dev->mode_config.mutex);
+
+ drm_client_modeset_release(client);
+
+@@ -875,6 +875,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
+ modeset->y = offset->y;
+ }
+ }
++ mutex_unlock(&dev->mode_config.mutex);
+
+ mutex_unlock(&client->modeset_mutex);
+ out:
+diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
+index c985ebb6831a3..6e36a15284537 100644
+--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
++++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
+@@ -2521,7 +2521,7 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
+ if (IS_DG2(i915))
+ intel_cdclk_pcode_pre_notify(state);
+
+- if (pipe == INVALID_PIPE ||
++ if (new_cdclk_state->disable_pipes ||
+ old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) {
+ drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
+
+@@ -2553,7 +2553,7 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
+ if (IS_DG2(i915))
+ intel_cdclk_pcode_post_notify(state);
+
+- if (pipe != INVALID_PIPE &&
++ if (!new_cdclk_state->disable_pipes &&
+ old_cdclk_state->actual.cdclk > new_cdclk_state->actual.cdclk) {
+ drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
+
+@@ -3036,6 +3036,7 @@ static struct intel_global_state *intel_cdclk_duplicate_state(struct intel_globa
+ return NULL;
+
+ cdclk_state->pipe = INVALID_PIPE;
++ cdclk_state->disable_pipes = false;
+
+ return &cdclk_state->base;
+ }
+@@ -3214,6 +3215,8 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
+ if (ret)
+ return ret;
+
++ new_cdclk_state->disable_pipes = true;
++
+ drm_dbg_kms(&dev_priv->drm,
+ "Modeset required for cdclk change\n");
+ }
+diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h
+index 48fd7d39e0cd9..71bc032bfef16 100644
+--- a/drivers/gpu/drm/i915/display/intel_cdclk.h
++++ b/drivers/gpu/drm/i915/display/intel_cdclk.h
+@@ -51,6 +51,9 @@ struct intel_cdclk_state {
+
+ /* bitmask of active pipes */
+ u8 active_pipes;
++
++ /* update cdclk with pipes disabled */
++ bool disable_pipes;
+ };
+
+ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state);
+diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
+index 12a29363e5dfe..31aa5d54fdf07 100644
+--- a/drivers/gpu/drm/i915/display/intel_ddi.c
++++ b/drivers/gpu/drm/i915/display/intel_ddi.c
+@@ -4229,7 +4229,12 @@ static bool m_n_equal(const struct intel_link_m_n *m_n_1,
+ static bool crtcs_port_sync_compatible(const struct intel_crtc_state *crtc_state1,
+ const struct intel_crtc_state *crtc_state2)
+ {
++ /*
++ * FIXME the modeset sequence is currently wrong and
++ * can't deal with bigjoiner + port sync at the same time.
++ */
+ return crtc_state1->hw.active && crtc_state2->hw.active &&
++ !crtc_state1->bigjoiner_pipes && !crtc_state2->bigjoiner_pipes &&
+ crtc_state1->output_types == crtc_state2->output_types &&
+ crtc_state1->output_format == crtc_state2->output_format &&
+ crtc_state1->lane_count == crtc_state2->lane_count &&
+diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
+index 360e90601ff93..4e8545126e246 100644
+--- a/drivers/gpu/drm/i915/display/intel_dp.c
++++ b/drivers/gpu/drm/i915/display/intel_dp.c
+@@ -2756,7 +2756,11 @@ intel_dp_drrs_compute_config(struct intel_connector *connector,
+ intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode);
+ int pixel_clock;
+
+- if (has_seamless_m_n(connector))
++ /*
++ * FIXME all joined pipes share the same transcoder.
++ * Need to account for that when updating M/N live.
++ */
++ if (has_seamless_m_n(connector) && !pipe_config->bigjoiner_pipes)
+ pipe_config->update_m_n = true;
+
+ if (!can_enable_drrs(connector, pipe_config, downclock_mode)) {
+diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
+index 4faaf4b3fc53b..925776ba1392e 100644
+--- a/drivers/gpu/drm/i915/display/intel_psr.c
++++ b/drivers/gpu/drm/i915/display/intel_psr.c
+@@ -1368,6 +1368,17 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
+ return;
+ }
+
++ /*
++ * FIXME figure out what is wrong with PSR+bigjoiner and
++ * fix it. Presumably something related to the fact that
++ * PSR is a transcoder level feature.
++ */
++ if (crtc_state->bigjoiner_pipes) {
++ drm_dbg_kms(&dev_priv->drm,
++ "PSR disabled due to bigjoiner\n");
++ return;
++ }
++
+ if (CAN_PANEL_REPLAY(intel_dp))
+ crtc_state->has_panel_replay = true;
+ else
+diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
+index eb5bd07439020..f542ee1db1d97 100644
+--- a/drivers/gpu/drm/i915/display/intel_vrr.c
++++ b/drivers/gpu/drm/i915/display/intel_vrr.c
+@@ -117,6 +117,13 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
+ const struct drm_display_info *info = &connector->base.display_info;
+ int vmin, vmax;
+
++ /*
++ * FIXME all joined pipes share the same transcoder.
++ * Need to account for that during VRR toggle/push/etc.
++ */
++ if (crtc_state->bigjoiner_pipes)
++ return;
++
+ if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+ return;
+
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+index fd60e49b8ec4d..792a4c60a20c2 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+@@ -1295,6 +1295,10 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
+ if (adreno_is_a618(gpu))
+ gpu->ubwc_config.highest_bank_bit = 14;
+
++ if (adreno_is_a619(gpu))
++ /* TODO: Should be 14 but causes corruption at e.g. 1920x1200 on DP */
++ gpu->ubwc_config.highest_bank_bit = 13;
++
+ if (adreno_is_a619_holi(gpu))
+ gpu->ubwc_config.highest_bank_bit = 13;
+
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+index ef871239adb2a..68fae048a9a83 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+@@ -459,15 +459,15 @@ int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent)
+ &perf->core_clk_rate);
+ debugfs_create_u32("enable_bw_release", 0600, entry,
+ (u32 *)&perf->enable_bw_release);
+- debugfs_create_u32("threshold_low", 0600, entry,
++ debugfs_create_u32("threshold_low", 0400, entry,
+ (u32 *)&perf->perf_cfg->max_bw_low);
+- debugfs_create_u32("threshold_high", 0600, entry,
++ debugfs_create_u32("threshold_high", 0400, entry,
+ (u32 *)&perf->perf_cfg->max_bw_high);
+- debugfs_create_u32("min_core_ib", 0600, entry,
++ debugfs_create_u32("min_core_ib", 0400, entry,
+ (u32 *)&perf->perf_cfg->min_core_ib);
+- debugfs_create_u32("min_llcc_ib", 0600, entry,
++ debugfs_create_u32("min_llcc_ib", 0400, entry,
+ (u32 *)&perf->perf_cfg->min_llcc_ib);
+- debugfs_create_u32("min_dram_ib", 0600, entry,
++ debugfs_create_u32("min_dram_ib", 0400, entry,
+ (u32 *)&perf->perf_cfg->min_dram_ib);
+ debugfs_create_file("perf_mode", 0600, entry,
+ (u32 *)perf, &dpu_core_perf_mode_fops);
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+index 946dd0135dffc..6a0a74832fb64 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+@@ -525,14 +525,14 @@ int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms,
+ int ret;
+
+ if (!irq_cb) {
+- DPU_ERROR("invalid IRQ=[%d, %d] irq_cb:%ps\n",
+- DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb);
++ DPU_ERROR("IRQ=[%d, %d] NULL callback\n",
++ DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
+ return -EINVAL;
+ }
+
+ if (!dpu_core_irq_is_valid(irq_idx)) {
+- DPU_ERROR("invalid IRQ=[%d, %d]\n",
+- DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
++ DPU_ERROR("invalid IRQ=[%d, %d] irq_cb:%ps\n",
++ DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb);
+ return -EINVAL;
+ }
+
+diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
+index 4c72124ffb5d4..78464c395c3d9 100644
+--- a/drivers/gpu/drm/msm/dp/dp_display.c
++++ b/drivers/gpu/drm/msm/dp/dp_display.c
+@@ -598,6 +598,7 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
+ ret = dp_display_usbpd_configure_cb(&pdev->dev);
+ if (ret) { /* link train failed */
+ dp->hpd_state = ST_DISCONNECTED;
++ pm_runtime_put_sync(&pdev->dev);
+ } else {
+ dp->hpd_state = ST_MAINLINK_READY;
+ }
+@@ -655,6 +656,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
+ dp_display_host_phy_exit(dp);
+ dp->hpd_state = ST_DISCONNECTED;
+ dp_display_notify_disconnect(&dp->dp_display.pdev->dev);
++ pm_runtime_put_sync(&pdev->dev);
+ mutex_unlock(&dp->event_mutex);
+ return 0;
+ }
+diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
+index e3f61c39df69b..80166f702a0db 100644
+--- a/drivers/gpu/drm/msm/msm_fb.c
++++ b/drivers/gpu/drm/msm/msm_fb.c
+@@ -89,7 +89,7 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb,
+
+ for (i = 0; i < n; i++) {
+ ret = msm_gem_get_and_pin_iova(fb->obj[i], aspace, &msm_fb->iova[i]);
+- drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)",
++ drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)\n",
+ fb->base.id, i, msm_fb->iova[i], ret);
+ if (ret)
+ return ret;
+@@ -176,7 +176,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
+ const struct msm_format *format;
+ int ret, i, n;
+
+- drm_dbg_state(dev, "create framebuffer: mode_cmd=%p (%dx%d@%4.4s)",
++ drm_dbg_state(dev, "create framebuffer: mode_cmd=%p (%dx%d@%4.4s)\n",
+ mode_cmd, mode_cmd->width, mode_cmd->height,
+ (char *)&mode_cmd->pixel_format);
+
+@@ -232,7 +232,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
+
+ refcount_set(&msm_fb->dirtyfb, 1);
+
+- drm_dbg_state(dev, "create: FB ID: %d (%p)", fb->base.id, fb);
++ drm_dbg_state(dev, "create: FB ID: %d (%p)\n", fb->base.id, fb);
+
+ return fb;
+
+diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c
+index 84c21ec2ceeae..af6a6fcb11736 100644
+--- a/drivers/gpu/drm/msm/msm_kms.c
++++ b/drivers/gpu/drm/msm/msm_kms.c
+@@ -149,7 +149,7 @@ int msm_crtc_enable_vblank(struct drm_crtc *crtc)
+ struct msm_kms *kms = priv->kms;
+ if (!kms)
+ return -ENXIO;
+- drm_dbg_vbl(dev, "crtc=%u", crtc->base.id);
++ drm_dbg_vbl(dev, "crtc=%u\n", crtc->base.id);
+ return vblank_ctrl_queue_work(priv, crtc, true);
+ }
+
+@@ -160,7 +160,7 @@ void msm_crtc_disable_vblank(struct drm_crtc *crtc)
+ struct msm_kms *kms = priv->kms;
+ if (!kms)
+ return;
+- drm_dbg_vbl(dev, "crtc=%u", crtc->base.id);
++ drm_dbg_vbl(dev, "crtc=%u\n", crtc->base.id);
+ vblank_ctrl_queue_work(priv, crtc, false);
+ }
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
+index 4bf486b571013..cb05f7f48a98b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
+@@ -66,11 +66,16 @@ of_init(struct nvkm_bios *bios, const char *name)
+ return ERR_PTR(-EINVAL);
+ }
+
++static void of_fini(void *p)
++{
++ kfree(p);
++}
++
+ const struct nvbios_source
+ nvbios_of = {
+ .name = "OpenFirmware",
+ .init = of_init,
+- .fini = (void(*)(void *))kfree,
++ .fini = of_fini,
+ .read = of_read,
+ .size = of_size,
+ .rw = false,
+diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
+index f38385fe76bbb..b91019cd5acb1 100644
+--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
++++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
+@@ -502,11 +502,18 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
+ mapping_set_unevictable(mapping);
+
+ for (i = page_offset; i < page_offset + NUM_FAULT_PAGES; i++) {
++ /* Can happen if the last fault only partially filled this
++ * section of the pages array before failing. In that case
++ * we skip already filled pages.
++ */
++ if (pages[i])
++ continue;
++
+ pages[i] = shmem_read_mapping_page(mapping, i);
+ if (IS_ERR(pages[i])) {
+ ret = PTR_ERR(pages[i]);
+ pages[i] = NULL;
+- goto err_pages;
++ goto err_unlock;
+ }
+ }
+
+@@ -514,7 +521,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
+ ret = sg_alloc_table_from_pages(sgt, pages + page_offset,
+ NUM_FAULT_PAGES, 0, SZ_2M, GFP_KERNEL);
+ if (ret)
+- goto err_pages;
++ goto err_unlock;
+
+ ret = dma_map_sgtable(pfdev->dev, sgt, DMA_BIDIRECTIONAL, 0);
+ if (ret)
+@@ -537,8 +544,6 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
+
+ err_map:
+ sg_free_table(sgt);
+-err_pages:
+- drm_gem_shmem_put_pages(&bo->base);
+ err_unlock:
+ dma_resv_unlock(obj->resv);
+ err_bo:
+diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
+index 368d26da0d6a2..9febc8b73f09e 100644
+--- a/drivers/gpu/drm/qxl/qxl_release.c
++++ b/drivers/gpu/drm/qxl/qxl_release.c
+@@ -58,16 +58,56 @@ static long qxl_fence_wait(struct dma_fence *fence, bool intr,
+ signed long timeout)
+ {
+ struct qxl_device *qdev;
++ struct qxl_release *release;
++ int count = 0, sc = 0;
++ bool have_drawable_releases;
+ unsigned long cur, end = jiffies + timeout;
+
+ qdev = container_of(fence->lock, struct qxl_device, release_lock);
++ release = container_of(fence, struct qxl_release, base);
++ have_drawable_releases = release->type == QXL_RELEASE_DRAWABLE;
+
+- if (!wait_event_timeout(qdev->release_event,
+- (dma_fence_is_signaled(fence) ||
+- (qxl_io_notify_oom(qdev), 0)),
+- timeout))
+- return 0;
++retry:
++ sc++;
++
++ if (dma_fence_is_signaled(fence))
++ goto signaled;
++
++ qxl_io_notify_oom(qdev);
++
++ for (count = 0; count < 11; count++) {
++ if (!qxl_queue_garbage_collect(qdev, true))
++ break;
++
++ if (dma_fence_is_signaled(fence))
++ goto signaled;
++ }
++
++ if (dma_fence_is_signaled(fence))
++ goto signaled;
++
++ if (have_drawable_releases || sc < 4) {
++ if (sc > 2)
++ /* back off */
++ usleep_range(500, 1000);
++
++ if (time_after(jiffies, end))
++ return 0;
++
++ if (have_drawable_releases && sc > 300) {
++ DMA_FENCE_WARN(fence,
++ "failed to wait on release %llu after spincount %d\n",
++ fence->context & ~0xf0000000, sc);
++ goto signaled;
++ }
++ goto retry;
++ }
++ /*
++ * yeah, original sync_obj_wait gave up after 3 spins when
++ * have_drawable_releases is not set.
++ */
+
++signaled:
+ cur = jiffies;
+ if (time_after(cur, end))
+ return 0;
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+index c7d90f96d16a6..0a304706e0132 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+@@ -666,11 +666,12 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv)
+ [vmw_dma_map_populate] = "Caching DMA mappings.",
+ [vmw_dma_map_bind] = "Giving up DMA mappings early."};
+
+- /* TTM currently doesn't fully support SEV encryption. */
+- if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
+- return -EINVAL;
+-
+- if (vmw_force_coherent)
++ /*
++ * When running with SEV we always want dma mappings, because
++ * otherwise ttm tt pool pages will bounce through swiotlb running
++ * out of available space.
++ */
++ if (vmw_force_coherent || cc_platform_has(CC_ATTR_MEM_ENCRYPT))
+ dev_priv->map_mode = vmw_dma_alloc_coherent;
+ else if (vmw_restrict_iommu)
+ dev_priv->map_mode = vmw_dma_map_bind;
+diff --git a/drivers/gpu/drm/xe/xe_display.c b/drivers/gpu/drm/xe/xe_display.c
+index e4db069f0db3f..6ec375c1c4b6c 100644
+--- a/drivers/gpu/drm/xe/xe_display.c
++++ b/drivers/gpu/drm/xe/xe_display.c
+@@ -108,11 +108,6 @@ int xe_display_create(struct xe_device *xe)
+ xe->display.hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0);
+
+ drmm_mutex_init(&xe->drm, &xe->sb_lock);
+- drmm_mutex_init(&xe->drm, &xe->display.backlight.lock);
+- drmm_mutex_init(&xe->drm, &xe->display.audio.mutex);
+- drmm_mutex_init(&xe->drm, &xe->display.wm.wm_mutex);
+- drmm_mutex_init(&xe->drm, &xe->display.pps.mutex);
+- drmm_mutex_init(&xe->drm, &xe->display.hdcp.hdcp_mutex);
+ xe->enabled_irq_mask = ~0;
+
+ err = drmm_add_action_or_reset(&xe->drm, display_destroy, NULL);
+diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c
+index 174ed2185481e..a6f43446c779a 100644
+--- a/drivers/gpu/drm/xe/xe_hwmon.c
++++ b/drivers/gpu/drm/xe/xe_hwmon.c
+@@ -288,7 +288,7 @@ xe_hwmon_power1_max_interval_show(struct device *dev, struct device_attribute *a
+ * As y can be < 2, we compute tau4 = (4 | x) << y
+ * and then add 2 when doing the final right shift to account for units
+ */
+- tau4 = ((1 << x_w) | x) << y;
++ tau4 = (u64)((1 << x_w) | x) << y;
+
+ /* val in hwmon interface units (millisec) */
+ out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+@@ -328,7 +328,7 @@ xe_hwmon_power1_max_interval_store(struct device *dev, struct device_attribute *
+ r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
+ x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
+ y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
+- tau4 = ((1 << x_w) | x) << y;
++ tau4 = (u64)((1 << x_w) | x) << y;
+ max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+ if (val > max_win)
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index 5dba58f322f03..d7e10f1311aaf 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -4381,9 +4381,11 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev)
+ }
+
+ dev_iommu_priv_set(dev, info);
+- ret = device_rbtree_insert(iommu, info);
+- if (ret)
+- goto free;
++ if (pdev && pci_ats_supported(pdev)) {
++ ret = device_rbtree_insert(iommu, info);
++ if (ret)
++ goto free;
++ }
+
+ if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) {
+ ret = intel_pasid_alloc_table(dev);
+@@ -4410,7 +4412,8 @@ static void intel_iommu_release_device(struct device *dev)
+ struct intel_iommu *iommu = info->iommu;
+
+ mutex_lock(&iommu->iopf_lock);
+- device_rbtree_remove(info);
++ if (dev_is_pci(dev) && pci_ats_supported(to_pci_dev(dev)))
++ device_rbtree_remove(info);
+ mutex_unlock(&iommu->iopf_lock);
+
+ if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev) &&
+diff --git a/drivers/iommu/intel/perfmon.c b/drivers/iommu/intel/perfmon.c
+index cf43e798eca49..44083d01852db 100644
+--- a/drivers/iommu/intel/perfmon.c
++++ b/drivers/iommu/intel/perfmon.c
+@@ -438,7 +438,7 @@ static int iommu_pmu_assign_event(struct iommu_pmu *iommu_pmu,
+ iommu_pmu_set_filter(domain, event->attr.config1,
+ IOMMU_PMU_FILTER_DOMAIN, idx,
+ event->attr.config1);
+- iommu_pmu_set_filter(pasid, event->attr.config1,
++ iommu_pmu_set_filter(pasid, event->attr.config2,
+ IOMMU_PMU_FILTER_PASID, idx,
+ event->attr.config1);
+ iommu_pmu_set_filter(ats, event->attr.config2,
+diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
+index ec47ec81f0ecd..4d269df0082fb 100644
+--- a/drivers/iommu/intel/svm.c
++++ b/drivers/iommu/intel/svm.c
+@@ -67,7 +67,7 @@ int intel_svm_enable_prq(struct intel_iommu *iommu)
+ struct page *pages;
+ int irq, ret;
+
+- pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, PRQ_ORDER);
++ pages = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO, PRQ_ORDER);
+ if (!pages) {
+ pr_warn("IOMMU: %s: Failed to allocate page request queue\n",
+ iommu->name);
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 82c9bb404ccca..4f3c35f1320d4 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1474,7 +1474,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
+ for (j = 0; j < i; j++)
+ if (r1_bio->bios[j])
+ rdev_dec_pending(conf->mirrors[j].rdev, mddev);
+- free_r1bio(r1_bio);
++ mempool_free(r1_bio, &conf->r1bio_pool);
+ allow_barrier(conf, bio->bi_iter.bi_sector);
+
+ if (bio->bi_opf & REQ_NOWAIT) {
+diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
+index 5741adf09a2ef..559a172ebc6cb 100644
+--- a/drivers/media/cec/core/cec-adap.c
++++ b/drivers/media/cec/core/cec-adap.c
+@@ -1151,20 +1151,6 @@ void cec_received_msg_ts(struct cec_adapter *adap,
+ if (valid_la && min_len) {
+ /* These messages have special length requirements */
+ switch (cmd) {
+- case CEC_MSG_TIMER_STATUS:
+- if (msg->msg[2] & 0x10) {
+- switch (msg->msg[2] & 0xf) {
+- case CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE:
+- case CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE:
+- if (msg->len < 5)
+- valid_la = false;
+- break;
+- }
+- } else if ((msg->msg[2] & 0xf) == CEC_OP_PROG_ERROR_DUPLICATE) {
+- if (msg->len < 5)
+- valid_la = false;
+- }
+- break;
+ case CEC_MSG_RECORD_ON:
+ switch (msg->msg[2]) {
+ case CEC_OP_RECORD_SRC_OWN:
+diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
+index 9fb8995b43a1c..13fa8588e38c1 100644
+--- a/drivers/mmc/host/omap.c
++++ b/drivers/mmc/host/omap.c
+@@ -1119,10 +1119,25 @@ static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on,
+
+ host = slot->host;
+
+- if (slot->vsd)
+- gpiod_set_value(slot->vsd, power_on);
+- if (slot->vio)
+- gpiod_set_value(slot->vio, power_on);
++ if (power_on) {
++ if (slot->vsd) {
++ gpiod_set_value(slot->vsd, power_on);
++ msleep(1);
++ }
++ if (slot->vio) {
++ gpiod_set_value(slot->vio, power_on);
++ msleep(1);
++ }
++ } else {
++ if (slot->vio) {
++ gpiod_set_value(slot->vio, power_on);
++ msleep(50);
++ }
++ if (slot->vsd) {
++ gpiod_set_value(slot->vsd, power_on);
++ msleep(50);
++ }
++ }
+
+ if (slot->pdata->set_power != NULL)
+ slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on,
+@@ -1259,18 +1274,18 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
+ slot->pdata = &host->pdata->slots[id];
+
+ /* Check for some optional GPIO controls */
+- slot->vsd = gpiod_get_index_optional(host->dev, "vsd",
+- id, GPIOD_OUT_LOW);
++ slot->vsd = devm_gpiod_get_index_optional(host->dev, "vsd",
++ id, GPIOD_OUT_LOW);
+ if (IS_ERR(slot->vsd))
+ return dev_err_probe(host->dev, PTR_ERR(slot->vsd),
+ "error looking up VSD GPIO\n");
+- slot->vio = gpiod_get_index_optional(host->dev, "vio",
+- id, GPIOD_OUT_LOW);
++ slot->vio = devm_gpiod_get_index_optional(host->dev, "vio",
++ id, GPIOD_OUT_LOW);
+ if (IS_ERR(slot->vio))
+ return dev_err_probe(host->dev, PTR_ERR(slot->vio),
+ "error looking up VIO GPIO\n");
+- slot->cover = gpiod_get_index_optional(host->dev, "cover",
+- id, GPIOD_IN);
++ slot->cover = devm_gpiod_get_index_optional(host->dev, "cover",
++ id, GPIOD_IN);
+ if (IS_ERR(slot->cover))
+ return dev_err_probe(host->dev, PTR_ERR(slot->cover),
+ "error looking up cover switch GPIO\n");
+@@ -1384,13 +1399,6 @@ static int mmc_omap_probe(struct platform_device *pdev)
+ if (IS_ERR(host->virt_base))
+ return PTR_ERR(host->virt_base);
+
+- host->slot_switch = gpiod_get_optional(host->dev, "switch",
+- GPIOD_OUT_LOW);
+- if (IS_ERR(host->slot_switch))
+- return dev_err_probe(host->dev, PTR_ERR(host->slot_switch),
+- "error looking up slot switch GPIO\n");
+-
+-
+ INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work);
+ INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work);
+
+@@ -1409,6 +1417,12 @@ static int mmc_omap_probe(struct platform_device *pdev)
+ host->dev = &pdev->dev;
+ platform_set_drvdata(pdev, host);
+
++ host->slot_switch = devm_gpiod_get_optional(host->dev, "switch",
++ GPIOD_OUT_LOW);
++ if (IS_ERR(host->slot_switch))
++ return dev_err_probe(host->dev, PTR_ERR(host->slot_switch),
++ "error looking up slot switch GPIO\n");
++
+ host->id = pdev->id;
+ host->irq = irq;
+ host->phys_base = res->start;
+diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
+index 40ae44c9945b1..22b97505fa536 100644
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -998,20 +998,173 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)
+ mutex_unlock(&priv->reg_mutex);
+ }
+
+-/* On page 205, section "8.6.3 Frame filtering" of the active standard, IEEE Std
+- * 802.1Q™-2022, it is stated that frames with 01:80:C2:00:00:00-0F as MAC DA
+- * must only be propagated to C-VLAN and MAC Bridge components. That means
+- * VLAN-aware and VLAN-unaware bridges. On the switch designs with CPU ports,
+- * these frames are supposed to be processed by the CPU (software). So we make
+- * the switch only forward them to the CPU port. And if received from a CPU
+- * port, forward to a single port. The software is responsible of making the
+- * switch conform to the latter by setting a single port as destination port on
+- * the special tag.
++/* In Clause 5 of IEEE Std 802-2014, two sublayers of the data link layer (DLL)
++ * of the Open Systems Interconnection basic reference model (OSI/RM) are
++ * described; the medium access control (MAC) and logical link control (LLC)
++ * sublayers. The MAC sublayer is the one facing the physical layer.
+ *
+- * This switch intellectual property cannot conform to this part of the standard
+- * fully. Whilst the REV_UN frame tag covers the remaining :04-0D and :0F MAC
+- * DAs, it also includes :22-FF which the scope of propagation is not supposed
+- * to be restricted for these MAC DAs.
++ * In 8.2 of IEEE Std 802.1Q-2022, the Bridge architecture is described. A
++ * Bridge component comprises a MAC Relay Entity for interconnecting the Ports
++ * of the Bridge, at least two Ports, and higher layer entities with at least a
++ * Spanning Tree Protocol Entity included.
++ *
++ * Each Bridge Port also functions as an end station and shall provide the MAC
++ * Service to an LLC Entity. Each instance of the MAC Service is provided to a
++ * distinct LLC Entity that supports protocol identification, multiplexing, and
++ * demultiplexing, for protocol data unit (PDU) transmission and reception by
++ * one or more higher layer entities.
++ *
++ * It is described in 8.13.9 of IEEE Std 802.1Q-2022 that in a Bridge, the LLC
++ * Entity associated with each Bridge Port is modeled as being directly
++ * connected to the attached Local Area Network (LAN).
++ *
++ * On the switch with CPU port architecture, CPU port functions as Management
++ * Port, and the Management Port functionality is provided by software which
++ * functions as an end station. Software is connected to an IEEE 802 LAN that is
++ * wholly contained within the system that incorporates the Bridge. Software
++ * provides access to the LLC Entity associated with each Bridge Port by the
++ * value of the source port field on the special tag on the frame received by
++ * software.
++ *
++ * We call frames that carry control information to determine the active
++ * topology and current extent of each Virtual Local Area Network (VLAN), i.e.,
++ * spanning tree or Shortest Path Bridging (SPB) and Multiple VLAN Registration
++ * Protocol Data Units (MVRPDUs), and frames from other link constrained
++ * protocols, such as Extensible Authentication Protocol over LAN (EAPOL) and
++ * Link Layer Discovery Protocol (LLDP), link-local frames. They are not
++ * forwarded by a Bridge. Permanently configured entries in the filtering
++ * database (FDB) ensure that such frames are discarded by the Forwarding
++ * Process. In 8.6.3 of IEEE Std 802.1Q-2022, this is described in detail:
++ *
++ * Each of the reserved MAC addresses specified in Table 8-1
++ * (01-80-C2-00-00-[00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F]) shall be
++ * permanently configured in the FDB in C-VLAN components and ERs.
++ *
++ * Each of the reserved MAC addresses specified in Table 8-2
++ * (01-80-C2-00-00-[01,02,03,04,05,06,07,08,09,0A,0E]) shall be permanently
++ * configured in the FDB in S-VLAN components.
++ *
++ * Each of the reserved MAC addresses specified in Table 8-3
++ * (01-80-C2-00-00-[01,02,04,0E]) shall be permanently configured in the FDB in
++ * TPMR components.
++ *
++ * The FDB entries for reserved MAC addresses shall specify filtering for all
++ * Bridge Ports and all VIDs. Management shall not provide the capability to
++ * modify or remove entries for reserved MAC addresses.
++ *
++ * The addresses in Table 8-1, Table 8-2, and Table 8-3 determine the scope of
++ * propagation of PDUs within a Bridged Network, as follows:
++ *
++ * The Nearest Bridge group address (01-80-C2-00-00-0E) is an address that no
++ * conformant Two-Port MAC Relay (TPMR) component, Service VLAN (S-VLAN)
++ * component, Customer VLAN (C-VLAN) component, or MAC Bridge can forward.
++ * PDUs transmitted using this destination address, or any other addresses
++ * that appear in Table 8-1, Table 8-2, and Table 8-3
++ * (01-80-C2-00-00-[00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F]), can
++ * therefore travel no further than those stations that can be reached via a
++ * single individual LAN from the originating station.
++ *
++ * The Nearest non-TPMR Bridge group address (01-80-C2-00-00-03), is an
++ * address that no conformant S-VLAN component, C-VLAN component, or MAC
++ * Bridge can forward; however, this address is relayed by a TPMR component.
++ * PDUs using this destination address, or any of the other addresses that
++ * appear in both Table 8-1 and Table 8-2 but not in Table 8-3
++ * (01-80-C2-00-00-[00,03,05,06,07,08,09,0A,0B,0C,0D,0F]), will be relayed by
++ * any TPMRs but will propagate no further than the nearest S-VLAN component,
++ * C-VLAN component, or MAC Bridge.
++ *
++ * The Nearest Customer Bridge group address (01-80-C2-00-00-00) is an address
++ * that no conformant C-VLAN component, MAC Bridge can forward; however, it is
++ * relayed by TPMR components and S-VLAN components. PDUs using this
++ * destination address, or any of the other addresses that appear in Table 8-1
++ * but not in either Table 8-2 or Table 8-3 (01-80-C2-00-00-[00,0B,0C,0D,0F]),
++ * will be relayed by TPMR components and S-VLAN components but will propagate
++ * no further than the nearest C-VLAN component or MAC Bridge.
++ *
++ * Because the LLC Entity associated with each Bridge Port is provided via CPU
++ * port, we must not filter these frames but forward them to CPU port.
++ *
++ * In a Bridge, the transmission Port is majorly decided by ingress and egress
++ * rules, FDB, and spanning tree Port State functions of the Forwarding Process.
++ * For link-local frames, only CPU port should be designated as destination port
++ * in the FDB, and the other functions of the Forwarding Process must not
++ * interfere with the decision of the transmission Port. We call this process
++ * trapping frames to CPU port.
++ *
++ * Therefore, on the switch with CPU port architecture, link-local frames must
++ * be trapped to CPU port, and certain link-local frames received by a Port of a
++ * Bridge comprising a TPMR component or an S-VLAN component must be excluded
++ * from it.
++ *
++ * A Bridge of the switch with CPU port architecture cannot comprise a Two-Port
++ * MAC Relay (TPMR) component as a TPMR component supports only a subset of the
++ * functionality of a MAC Bridge. A Bridge comprising two Ports (Management Port
++ * doesn't count) of this architecture will either function as a standard MAC
++ * Bridge or a standard VLAN Bridge.
++ *
++ * Therefore, a Bridge of this architecture can only comprise S-VLAN components,
++ * C-VLAN components, or MAC Bridge components. Since there's no TPMR component,
++ * we don't need to relay PDUs using the destination addresses specified on the
++ * Nearest non-TPMR section, and the proportion of the Nearest Customer Bridge
++ * section where they must be relayed by TPMR components.
++ *
++ * One option to trap link-local frames to CPU port is to add static FDB entries
++ * with CPU port designated as destination port. However, because that
++ * Independent VLAN Learning (IVL) is being used on every VID, each entry only
++ * applies to a single VLAN Identifier (VID). For a Bridge comprising a MAC
++ * Bridge component or a C-VLAN component, there would have to be 16 times 4096
++ * entries. This switch intellectual property can only hold a maximum of 2048
++ * entries. Using this option, there also isn't a mechanism to prevent
++ * link-local frames from being discarded when the spanning tree Port State of
++ * the reception Port is discarding.
++ *
++ * The remaining option is to utilise the BPC, RGAC1, RGAC2, RGAC3, and RGAC4
++ * registers. Whilst this applies to every VID, it doesn't contain all of the
++ * reserved MAC addresses without affecting the remaining Standard Group MAC
++ * Addresses. The REV_UN frame tag utilised using the RGAC4 register covers the
++ * remaining 01-80-C2-00-00-[04,05,06,07,08,09,0A,0B,0C,0D,0F] destination
++ * addresses. It also includes the 01-80-C2-00-00-22 to 01-80-C2-00-00-FF
++ * destination addresses which may be relayed by MAC Bridges or VLAN Bridges.
++ * The latter option provides better but not complete conformance.
++ *
++ * This switch intellectual property also does not provide a mechanism to trap
++ * link-local frames with specific destination addresses to CPU port by Bridge,
++ * to conform to the filtering rules for the distinct Bridge components.
++ *
++ * Therefore, regardless of the type of the Bridge component, link-local frames
++ * with these destination addresses will be trapped to CPU port:
++ *
++ * 01-80-C2-00-00-[00,01,02,03,0E]
++ *
++ * In a Bridge comprising a MAC Bridge component or a C-VLAN component:
++ *
++ * Link-local frames with these destination addresses won't be trapped to CPU
++ * port which won't conform to IEEE Std 802.1Q-2022:
++ *
++ * 01-80-C2-00-00-[04,05,06,07,08,09,0A,0B,0C,0D,0F]
++ *
++ * In a Bridge comprising an S-VLAN component:
++ *
++ * Link-local frames with these destination addresses will be trapped to CPU
++ * port which won't conform to IEEE Std 802.1Q-2022:
++ *
++ * 01-80-C2-00-00-00
++ *
++ * Link-local frames with these destination addresses won't be trapped to CPU
++ * port which won't conform to IEEE Std 802.1Q-2022:
++ *
++ * 01-80-C2-00-00-[04,05,06,07,08,09,0A]
++ *
++ * To trap link-local frames to CPU port as conformant as this switch
++ * intellectual property can allow, link-local frames are made to be regarded as
++ * Bridge Protocol Data Units (BPDUs). This is because this switch intellectual
++ * property only lets the frames regarded as BPDUs bypass the spanning tree Port
++ * State function of the Forwarding Process.
++ *
++ * The only remaining interference is the ingress rules. When the reception Port
++ * has no PVID assigned on software, VLAN-untagged frames won't be allowed in.
++ * There doesn't seem to be a mechanism on the switch intellectual property to
++ * have link-local frames bypass this function of the Forwarding Process.
+ */
+ static void
+ mt753x_trap_frames(struct mt7530_priv *priv)
+@@ -1019,35 +1172,43 @@ mt753x_trap_frames(struct mt7530_priv *priv)
+ /* Trap 802.1X PAE frames and BPDUs to the CPU port(s) and egress them
+ * VLAN-untagged.
+ */
+- mt7530_rmw(priv, MT753X_BPC, MT753X_PAE_EG_TAG_MASK |
+- MT753X_PAE_PORT_FW_MASK | MT753X_BPDU_EG_TAG_MASK |
+- MT753X_BPDU_PORT_FW_MASK,
+- MT753X_PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+- MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY) |
+- MT753X_BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+- MT753X_BPDU_CPU_ONLY);
++ mt7530_rmw(priv, MT753X_BPC,
++ MT753X_PAE_BPDU_FR | MT753X_PAE_EG_TAG_MASK |
++ MT753X_PAE_PORT_FW_MASK | MT753X_BPDU_EG_TAG_MASK |
++ MT753X_BPDU_PORT_FW_MASK,
++ MT753X_PAE_BPDU_FR |
++ MT753X_PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY) |
++ MT753X_BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_BPDU_CPU_ONLY);
+
+ /* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and egress
+ * them VLAN-untagged.
+ */
+- mt7530_rmw(priv, MT753X_RGAC1, MT753X_R02_EG_TAG_MASK |
+- MT753X_R02_PORT_FW_MASK | MT753X_R01_EG_TAG_MASK |
+- MT753X_R01_PORT_FW_MASK,
+- MT753X_R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+- MT753X_R02_PORT_FW(MT753X_BPDU_CPU_ONLY) |
+- MT753X_R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+- MT753X_BPDU_CPU_ONLY);
++ mt7530_rmw(priv, MT753X_RGAC1,
++ MT753X_R02_BPDU_FR | MT753X_R02_EG_TAG_MASK |
++ MT753X_R02_PORT_FW_MASK | MT753X_R01_BPDU_FR |
++ MT753X_R01_EG_TAG_MASK | MT753X_R01_PORT_FW_MASK,
++ MT753X_R02_BPDU_FR |
++ MT753X_R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_R02_PORT_FW(MT753X_BPDU_CPU_ONLY) |
++ MT753X_R01_BPDU_FR |
++ MT753X_R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_BPDU_CPU_ONLY);
+
+ /* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and egress
+ * them VLAN-untagged.
+ */
+- mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_EG_TAG_MASK |
+- MT753X_R0E_PORT_FW_MASK | MT753X_R03_EG_TAG_MASK |
+- MT753X_R03_PORT_FW_MASK,
+- MT753X_R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+- MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY) |
+- MT753X_R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+- MT753X_BPDU_CPU_ONLY);
++ mt7530_rmw(priv, MT753X_RGAC2,
++ MT753X_R0E_BPDU_FR | MT753X_R0E_EG_TAG_MASK |
++ MT753X_R0E_PORT_FW_MASK | MT753X_R03_BPDU_FR |
++ MT753X_R03_EG_TAG_MASK | MT753X_R03_PORT_FW_MASK,
++ MT753X_R0E_BPDU_FR |
++ MT753X_R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY) |
++ MT753X_R03_BPDU_FR |
++ MT753X_R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_BPDU_CPU_ONLY);
+ }
+
+ static int
+diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
+index 75bc9043c8c0a..ddefeb69afda1 100644
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -65,6 +65,7 @@ enum mt753x_id {
+
+ /* Registers for BPDU and PAE frame control*/
+ #define MT753X_BPC 0x24
++#define MT753X_PAE_BPDU_FR BIT(25)
+ #define MT753X_PAE_EG_TAG_MASK GENMASK(24, 22)
+ #define MT753X_PAE_EG_TAG(x) FIELD_PREP(MT753X_PAE_EG_TAG_MASK, x)
+ #define MT753X_PAE_PORT_FW_MASK GENMASK(18, 16)
+@@ -75,20 +76,24 @@ enum mt753x_id {
+
+ /* Register for :01 and :02 MAC DA frame control */
+ #define MT753X_RGAC1 0x28
++#define MT753X_R02_BPDU_FR BIT(25)
+ #define MT753X_R02_EG_TAG_MASK GENMASK(24, 22)
+ #define MT753X_R02_EG_TAG(x) FIELD_PREP(MT753X_R02_EG_TAG_MASK, x)
+ #define MT753X_R02_PORT_FW_MASK GENMASK(18, 16)
+ #define MT753X_R02_PORT_FW(x) FIELD_PREP(MT753X_R02_PORT_FW_MASK, x)
++#define MT753X_R01_BPDU_FR BIT(9)
+ #define MT753X_R01_EG_TAG_MASK GENMASK(8, 6)
+ #define MT753X_R01_EG_TAG(x) FIELD_PREP(MT753X_R01_EG_TAG_MASK, x)
+ #define MT753X_R01_PORT_FW_MASK GENMASK(2, 0)
+
+ /* Register for :03 and :0E MAC DA frame control */
+ #define MT753X_RGAC2 0x2c
++#define MT753X_R0E_BPDU_FR BIT(25)
+ #define MT753X_R0E_EG_TAG_MASK GENMASK(24, 22)
+ #define MT753X_R0E_EG_TAG(x) FIELD_PREP(MT753X_R0E_EG_TAG_MASK, x)
+ #define MT753X_R0E_PORT_FW_MASK GENMASK(18, 16)
+ #define MT753X_R0E_PORT_FW(x) FIELD_PREP(MT753X_R0E_PORT_FW_MASK, x)
++#define MT753X_R03_BPDU_FR BIT(9)
+ #define MT753X_R03_EG_TAG_MASK GENMASK(8, 6)
+ #define MT753X_R03_EG_TAG(x) FIELD_PREP(MT753X_R03_EG_TAG_MASK, x)
+ #define MT753X_R03_PORT_FW_MASK GENMASK(2, 0)
+diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c
+index 633b321d7fdd9..4db689372980e 100644
+--- a/drivers/net/ethernet/amazon/ena/ena_com.c
++++ b/drivers/net/ethernet/amazon/ena/ena_com.c
+@@ -362,7 +362,7 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev,
+ ENA_COM_BOUNCE_BUFFER_CNTRL_CNT;
+ io_sq->bounce_buf_ctrl.next_to_use = 0;
+
+- size = io_sq->bounce_buf_ctrl.buffer_size *
++ size = (size_t)io_sq->bounce_buf_ctrl.buffer_size *
+ io_sq->bounce_buf_ctrl.buffers_num;
+
+ dev_node = dev_to_node(ena_dev->dmadev);
+diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
+index 5482015411f2f..95ed32542edfe 100644
+--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
++++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
+@@ -696,8 +696,11 @@ void ena_unmap_tx_buff(struct ena_ring *tx_ring,
+ static void ena_free_tx_bufs(struct ena_ring *tx_ring)
+ {
+ bool print_once = true;
++ bool is_xdp_ring;
+ u32 i;
+
++ is_xdp_ring = ENA_IS_XDP_INDEX(tx_ring->adapter, tx_ring->qid);
++
+ for (i = 0; i < tx_ring->ring_size; i++) {
+ struct ena_tx_buffer *tx_info = &tx_ring->tx_buffer_info[i];
+
+@@ -717,10 +720,15 @@ static void ena_free_tx_bufs(struct ena_ring *tx_ring)
+
+ ena_unmap_tx_buff(tx_ring, tx_info);
+
+- dev_kfree_skb_any(tx_info->skb);
++ if (is_xdp_ring)
++ xdp_return_frame(tx_info->xdpf);
++ else
++ dev_kfree_skb_any(tx_info->skb);
+ }
+- netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev,
+- tx_ring->qid));
++
++ if (!is_xdp_ring)
++ netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev,
++ tx_ring->qid));
+ }
+
+ static void ena_free_all_tx_bufs(struct ena_adapter *adapter)
+@@ -3421,10 +3429,11 @@ static void check_for_missing_completions(struct ena_adapter *adapter)
+ {
+ struct ena_ring *tx_ring;
+ struct ena_ring *rx_ring;
+- int i, budget, rc;
++ int qid, budget, rc;
+ int io_queue_count;
+
+ io_queue_count = adapter->xdp_num_queues + adapter->num_io_queues;
++
+ /* Make sure the driver doesn't turn the device in other process */
+ smp_rmb();
+
+@@ -3437,27 +3446,29 @@ static void check_for_missing_completions(struct ena_adapter *adapter)
+ if (adapter->missing_tx_completion_to == ENA_HW_HINTS_NO_TIMEOUT)
+ return;
+
+- budget = ENA_MONITORED_TX_QUEUES;
++ budget = min_t(u32, io_queue_count, ENA_MONITORED_TX_QUEUES);
+
+- for (i = adapter->last_monitored_tx_qid; i < io_queue_count; i++) {
+- tx_ring = &adapter->tx_ring[i];
+- rx_ring = &adapter->rx_ring[i];
++ qid = adapter->last_monitored_tx_qid;
++
++ while (budget) {
++ qid = (qid + 1) % io_queue_count;
++
++ tx_ring = &adapter->tx_ring[qid];
++ rx_ring = &adapter->rx_ring[qid];
+
+ rc = check_missing_comp_in_tx_queue(adapter, tx_ring);
+ if (unlikely(rc))
+ return;
+
+- rc = !ENA_IS_XDP_INDEX(adapter, i) ?
++ rc = !ENA_IS_XDP_INDEX(adapter, qid) ?
+ check_for_rx_interrupt_queue(adapter, rx_ring) : 0;
+ if (unlikely(rc))
+ return;
+
+ budget--;
+- if (!budget)
+- break;
+ }
+
+- adapter->last_monitored_tx_qid = i % io_queue_count;
++ adapter->last_monitored_tx_qid = qid;
+ }
+
+ /* trigger napi schedule after 2 consecutive detections */
+diff --git a/drivers/net/ethernet/amazon/ena/ena_xdp.c b/drivers/net/ethernet/amazon/ena/ena_xdp.c
+index fc1c4ef73ba32..34d73c72f7803 100644
+--- a/drivers/net/ethernet/amazon/ena/ena_xdp.c
++++ b/drivers/net/ethernet/amazon/ena/ena_xdp.c
+@@ -89,7 +89,7 @@ int ena_xdp_xmit_frame(struct ena_ring *tx_ring,
+
+ rc = ena_xdp_tx_map_frame(tx_ring, tx_info, xdpf, &ena_tx_ctx);
+ if (unlikely(rc))
+- return rc;
++ goto err;
+
+ ena_tx_ctx.req_id = req_id;
+
+@@ -112,7 +112,9 @@ int ena_xdp_xmit_frame(struct ena_ring *tx_ring,
+
+ error_unmap_dma:
+ ena_unmap_tx_buff(tx_ring, tx_info);
++err:
+ tx_info->xdpf = NULL;
++
+ return rc;
+ }
+
+diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c
+index 7658a72867675..dd4f0965bbe64 100644
+--- a/drivers/net/ethernet/amd/pds_core/core.c
++++ b/drivers/net/ethernet/amd/pds_core/core.c
+@@ -595,6 +595,16 @@ void pdsc_fw_up(struct pdsc *pdsc)
+ pdsc_teardown(pdsc, PDSC_TEARDOWN_RECOVERY);
+ }
+
++void pdsc_pci_reset_thread(struct work_struct *work)
++{
++ struct pdsc *pdsc = container_of(work, struct pdsc, pci_reset_work);
++ struct pci_dev *pdev = pdsc->pdev;
++
++ pci_dev_get(pdev);
++ pci_reset_function(pdev);
++ pci_dev_put(pdev);
++}
++
+ static void pdsc_check_pci_health(struct pdsc *pdsc)
+ {
+ u8 fw_status;
+@@ -609,8 +619,8 @@ static void pdsc_check_pci_health(struct pdsc *pdsc)
+ if (fw_status != PDS_RC_BAD_PCI)
+ return;
+
+- pdsc_reset_prepare(pdsc->pdev);
+- pdsc_reset_done(pdsc->pdev);
++ /* prevent deadlock between pdsc_reset_prepare and pdsc_health_thread */
++ queue_work(pdsc->wq, &pdsc->pci_reset_work);
+ }
+
+ void pdsc_health_thread(struct work_struct *work)
+diff --git a/drivers/net/ethernet/amd/pds_core/core.h b/drivers/net/ethernet/amd/pds_core/core.h
+index 110c4b826b22d..401ff56eba0dc 100644
+--- a/drivers/net/ethernet/amd/pds_core/core.h
++++ b/drivers/net/ethernet/amd/pds_core/core.h
+@@ -197,6 +197,7 @@ struct pdsc {
+ struct pdsc_qcq notifyqcq;
+ u64 last_eid;
+ struct pdsc_viftype *viftype_status;
++ struct work_struct pci_reset_work;
+ };
+
+ /** enum pds_core_dbell_bits - bitwise composition of dbell values.
+@@ -283,9 +284,6 @@ int pdsc_devcmd_init(struct pdsc *pdsc);
+ int pdsc_devcmd_reset(struct pdsc *pdsc);
+ int pdsc_dev_init(struct pdsc *pdsc);
+
+-void pdsc_reset_prepare(struct pci_dev *pdev);
+-void pdsc_reset_done(struct pci_dev *pdev);
+-
+ int pdsc_intr_alloc(struct pdsc *pdsc, char *name,
+ irq_handler_t handler, void *data);
+ void pdsc_intr_free(struct pdsc *pdsc, int index);
+@@ -315,5 +313,6 @@ int pdsc_firmware_update(struct pdsc *pdsc, const struct firmware *fw,
+
+ void pdsc_fw_down(struct pdsc *pdsc);
+ void pdsc_fw_up(struct pdsc *pdsc);
++void pdsc_pci_reset_thread(struct work_struct *work);
+
+ #endif /* _PDSC_H_ */
+diff --git a/drivers/net/ethernet/amd/pds_core/dev.c b/drivers/net/ethernet/amd/pds_core/dev.c
+index e65a1632df505..bfb79c5aac391 100644
+--- a/drivers/net/ethernet/amd/pds_core/dev.c
++++ b/drivers/net/ethernet/amd/pds_core/dev.c
+@@ -229,6 +229,9 @@ int pdsc_devcmd_reset(struct pdsc *pdsc)
+ .reset.opcode = PDS_CORE_CMD_RESET,
+ };
+
++ if (!pdsc_is_fw_running(pdsc))
++ return 0;
++
+ return pdsc_devcmd(pdsc, &cmd, &comp, pdsc->devcmd_timeout);
+ }
+
+diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c
+index 0050c5894563b..a375d612d2875 100644
+--- a/drivers/net/ethernet/amd/pds_core/main.c
++++ b/drivers/net/ethernet/amd/pds_core/main.c
+@@ -238,6 +238,7 @@ static int pdsc_init_pf(struct pdsc *pdsc)
+ snprintf(wq_name, sizeof(wq_name), "%s.%d", PDS_CORE_DRV_NAME, pdsc->uid);
+ pdsc->wq = create_singlethread_workqueue(wq_name);
+ INIT_WORK(&pdsc->health_work, pdsc_health_thread);
++ INIT_WORK(&pdsc->pci_reset_work, pdsc_pci_reset_thread);
+ timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0);
+ pdsc->wdtimer_period = PDSC_WATCHDOG_SECS * HZ;
+
+@@ -468,7 +469,7 @@ static void pdsc_restart_health_thread(struct pdsc *pdsc)
+ mod_timer(&pdsc->wdtimer, jiffies + 1);
+ }
+
+-void pdsc_reset_prepare(struct pci_dev *pdev)
++static void pdsc_reset_prepare(struct pci_dev *pdev)
+ {
+ struct pdsc *pdsc = pci_get_drvdata(pdev);
+
+@@ -477,10 +478,11 @@ void pdsc_reset_prepare(struct pci_dev *pdev)
+
+ pdsc_unmap_bars(pdsc);
+ pci_release_regions(pdev);
+- pci_disable_device(pdev);
++ if (pci_is_enabled(pdev))
++ pci_disable_device(pdev);
+ }
+
+-void pdsc_reset_done(struct pci_dev *pdev)
++static void pdsc_reset_done(struct pci_dev *pdev)
+ {
+ struct pdsc *pdsc = pci_get_drvdata(pdev);
+ struct device *dev = pdsc->dev;
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 39845d556bafc..5e6e32d708e24 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -11526,6 +11526,8 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
+ /* VF-reps may need to be re-opened after the PF is re-opened */
+ if (BNXT_PF(bp))
+ bnxt_vf_reps_open(bp);
++ if (bp->ptp_cfg)
++ atomic_set(&bp->ptp_cfg->tx_avail, BNXT_MAX_TX_TS);
+ bnxt_ptp_init_rtc(bp, true);
+ bnxt_ptp_cfg_tstamp_filters(bp);
+ return 0;
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+index 93f9bd55020f2..195c02dc06830 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+@@ -210,6 +210,9 @@ void bnxt_ulp_start(struct bnxt *bp, int err)
+ if (err)
+ return;
+
++ if (edev->ulp_tbl->msix_requested)
++ bnxt_fill_msix_vecs(bp, edev->msix_entries);
++
+ if (aux_priv) {
+ struct auxiliary_device *adev;
+
+@@ -392,12 +395,13 @@ void bnxt_rdma_aux_device_init(struct bnxt *bp)
+ if (!edev)
+ goto aux_dev_uninit;
+
++ aux_priv->edev = edev;
++
+ ulp = kzalloc(sizeof(*ulp), GFP_KERNEL);
+ if (!ulp)
+ goto aux_dev_uninit;
+
+ edev->ulp_tbl = ulp;
+- aux_priv->edev = edev;
+ bp->edev = edev;
+ bnxt_set_edev_info(edev, bp);
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+index 66203a90f052b..42db213fb69a6 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+@@ -4721,18 +4721,18 @@ static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw)
+ */
+ rvu_write64(rvu, blkaddr, NIX_AF_CFG,
+ rvu_read64(rvu, blkaddr, NIX_AF_CFG) | 0x40ULL);
++ }
+
+- /* Set chan/link to backpressure TL3 instead of TL2 */
+- rvu_write64(rvu, blkaddr, NIX_AF_PSE_CHANNEL_LEVEL, 0x01);
++ /* Set chan/link to backpressure TL3 instead of TL2 */
++ rvu_write64(rvu, blkaddr, NIX_AF_PSE_CHANNEL_LEVEL, 0x01);
+
+- /* Disable SQ manager's sticky mode operation (set TM6 = 0)
+- * This sticky mode is known to cause SQ stalls when multiple
+- * SQs are mapped to same SMQ and transmitting pkts at a time.
+- */
+- cfg = rvu_read64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS);
+- cfg &= ~BIT_ULL(15);
+- rvu_write64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS, cfg);
+- }
++ /* Disable SQ manager's sticky mode operation (set TM6 = 0)
++ * This sticky mode is known to cause SQ stalls when multiple
++ * SQs are mapped to same SMQ and transmitting pkts at a time.
++ */
++ cfg = rvu_read64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS);
++ cfg &= ~BIT_ULL(15);
++ rvu_write64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS, cfg);
+
+ ltdefs = rvu->kpu.lt_def;
+ /* Calibrate X2P bus to check if CGX/LBK links are fine */
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
+index 1e77bbf5d22a1..1723e9912ae07 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
+@@ -382,6 +382,7 @@ static void otx2_qos_read_txschq_cfg_tl(struct otx2_qos_node *parent,
+ otx2_qos_read_txschq_cfg_tl(node, cfg);
+ cnt = cfg->static_node_pos[node->level];
+ cfg->schq_contig_list[node->level][cnt] = node->schq;
++ cfg->schq_index_used[node->level][cnt] = true;
+ cfg->schq_contig[node->level]++;
+ cfg->static_node_pos[node->level]++;
+ otx2_qos_read_txschq_cfg_schq(node, cfg);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h
+index 86f1854698b4e..883c044852f1d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h
+@@ -95,9 +95,15 @@ static inline void mlx5e_ptp_metadata_fifo_push(struct mlx5e_ptp_metadata_fifo *
+ }
+
+ static inline u8
++mlx5e_ptp_metadata_fifo_peek(struct mlx5e_ptp_metadata_fifo *fifo)
++{
++ return fifo->data[fifo->mask & fifo->cc];
++}
++
++static inline void
+ mlx5e_ptp_metadata_fifo_pop(struct mlx5e_ptp_metadata_fifo *fifo)
+ {
+- return fifo->data[fifo->mask & fifo->cc++];
++ fifo->cc++;
+ }
+
+ static inline void
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
+index 34adf8c3f81a0..922bc5b7c10e3 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
+@@ -83,24 +83,25 @@ int mlx5e_open_qos_sq(struct mlx5e_priv *priv, struct mlx5e_channels *chs,
+
+ txq_ix = mlx5e_qid_from_qos(chs, node_qid);
+
+- WARN_ON(node_qid > priv->htb_max_qos_sqs);
+- if (node_qid == priv->htb_max_qos_sqs) {
+- struct mlx5e_sq_stats *stats, **stats_list = NULL;
+-
+- if (priv->htb_max_qos_sqs == 0) {
+- stats_list = kvcalloc(mlx5e_qos_max_leaf_nodes(priv->mdev),
+- sizeof(*stats_list),
+- GFP_KERNEL);
+- if (!stats_list)
+- return -ENOMEM;
+- }
++ WARN_ON(node_qid >= mlx5e_htb_cur_leaf_nodes(priv->htb));
++ if (!priv->htb_qos_sq_stats) {
++ struct mlx5e_sq_stats **stats_list;
++
++ stats_list = kvcalloc(mlx5e_qos_max_leaf_nodes(priv->mdev),
++ sizeof(*stats_list), GFP_KERNEL);
++ if (!stats_list)
++ return -ENOMEM;
++
++ WRITE_ONCE(priv->htb_qos_sq_stats, stats_list);
++ }
++
++ if (!priv->htb_qos_sq_stats[node_qid]) {
++ struct mlx5e_sq_stats *stats;
++
+ stats = kzalloc(sizeof(*stats), GFP_KERNEL);
+- if (!stats) {
+- kvfree(stats_list);
++ if (!stats)
+ return -ENOMEM;
+- }
+- if (stats_list)
+- WRITE_ONCE(priv->htb_qos_sq_stats, stats_list);
++
+ WRITE_ONCE(priv->htb_qos_sq_stats[node_qid], stats);
+ /* Order htb_max_qos_sqs increment after writing the array pointer.
+ * Pairs with smp_load_acquire in en_stats.c.
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c b/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c
+index f675b1926340f..f66bbc8464645 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c
+@@ -57,6 +57,7 @@ int mlx5e_selq_init(struct mlx5e_selq *selq, struct mutex *state_lock)
+
+ void mlx5e_selq_cleanup(struct mlx5e_selq *selq)
+ {
++ mutex_lock(selq->state_lock);
+ WARN_ON_ONCE(selq->is_prepared);
+
+ kvfree(selq->standby);
+@@ -67,6 +68,7 @@ void mlx5e_selq_cleanup(struct mlx5e_selq *selq)
+
+ kvfree(selq->standby);
+ selq->standby = NULL;
++ mutex_unlock(selq->state_lock);
+ }
+
+ void mlx5e_selq_prepare_params(struct mlx5e_selq *selq, struct mlx5e_params *params)
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+index cc51ce16df14a..93461b0c5703b 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+@@ -451,6 +451,23 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
+
+ mutex_lock(&priv->state_lock);
+
++ /* If RXFH is configured, changing the channels number is allowed only if
++ * it does not require resizing the RSS table. This is because the previous
++ * configuration may no longer be compatible with the new RSS table.
++ */
++ if (netif_is_rxfh_configured(priv->netdev)) {
++ int cur_rqt_size = mlx5e_rqt_size(priv->mdev, cur_params->num_channels);
++ int new_rqt_size = mlx5e_rqt_size(priv->mdev, count);
++
++ if (new_rqt_size != cur_rqt_size) {
++ err = -EINVAL;
++ netdev_err(priv->netdev,
++ "%s: RXFH is configured, block changing channels number that affects RSS table size (new: %d, current: %d)\n",
++ __func__, new_rqt_size, cur_rqt_size);
++ goto out;
++ }
++ }
++
+ /* Don't allow changing the number of channels if HTB offload is active,
+ * because the numeration of the QoS SQs will change, while per-queue
+ * qdiscs are attached.
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index c8e8f512803ef..952f1f98138cc 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -5695,9 +5695,7 @@ void mlx5e_priv_cleanup(struct mlx5e_priv *priv)
+ kfree(priv->tx_rates);
+ kfree(priv->txq2sq);
+ destroy_workqueue(priv->wq);
+- mutex_lock(&priv->state_lock);
+ mlx5e_selq_cleanup(&priv->selq);
+- mutex_unlock(&priv->state_lock);
+ free_cpumask_var(priv->scratchpad.cpumask);
+
+ for (i = 0; i < priv->htb_max_qos_sqs; i++)
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+index 2fa076b23fbea..e21a3b4128ce8 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+@@ -398,6 +398,8 @@ mlx5e_txwqe_complete(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+ (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) {
+ u8 metadata_index = be32_to_cpu(eseg->flow_table_metadata);
+
++ mlx5e_ptp_metadata_fifo_pop(&sq->ptpsq->metadata_freelist);
++
+ mlx5e_skb_cb_hwtstamp_init(skb);
+ mlx5e_ptp_metadata_map_put(&sq->ptpsq->metadata_map, skb,
+ metadata_index);
+@@ -496,9 +498,6 @@ mlx5e_sq_xmit_wqe(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+
+ err_drop:
+ stats->dropped++;
+- if (unlikely(sq->ptpsq && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)))
+- mlx5e_ptp_metadata_fifo_push(&sq->ptpsq->metadata_freelist,
+- be32_to_cpu(eseg->flow_table_metadata));
+ dev_kfree_skb_any(skb);
+ mlx5e_tx_flush(sq);
+ }
+@@ -657,7 +656,7 @@ static void mlx5e_cqe_ts_id_eseg(struct mlx5e_ptpsq *ptpsq, struct sk_buff *skb,
+ {
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
+ eseg->flow_table_metadata =
+- cpu_to_be32(mlx5e_ptp_metadata_fifo_pop(&ptpsq->metadata_freelist));
++ cpu_to_be32(mlx5e_ptp_metadata_fifo_peek(&ptpsq->metadata_freelist));
+ }
+
+ static void mlx5e_txwqe_build_eseg(struct mlx5e_priv *priv, struct mlx5e_txqsq *sq,
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+index e6bfa7e4f146c..cf085a478e3e4 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+@@ -1664,6 +1664,16 @@ static int create_auto_flow_group(struct mlx5_flow_table *ft,
+ return err;
+ }
+
++static bool mlx5_pkt_reformat_cmp(struct mlx5_pkt_reformat *p1,
++ struct mlx5_pkt_reformat *p2)
++{
++ return p1->owner == p2->owner &&
++ (p1->owner == MLX5_FLOW_RESOURCE_OWNER_FW ?
++ p1->id == p2->id :
++ mlx5_fs_dr_action_get_pkt_reformat_id(p1) ==
++ mlx5_fs_dr_action_get_pkt_reformat_id(p2));
++}
++
+ static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
+ struct mlx5_flow_destination *d2)
+ {
+@@ -1675,8 +1685,8 @@ static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
+ ((d1->vport.flags & MLX5_FLOW_DEST_VPORT_VHCA_ID) ?
+ (d1->vport.vhca_id == d2->vport.vhca_id) : true) &&
+ ((d1->vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID) ?
+- (d1->vport.pkt_reformat->id ==
+- d2->vport.pkt_reformat->id) : true)) ||
++ mlx5_pkt_reformat_cmp(d1->vport.pkt_reformat,
++ d2->vport.pkt_reformat) : true)) ||
+ (d1->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE &&
+ d1->ft == d2->ft) ||
+ (d1->type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
+@@ -1808,8 +1818,9 @@ static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
+ }
+ trace_mlx5_fs_set_fte(fte, false);
+
++ /* Link newly added rules into the tree. */
+ for (i = 0; i < handle->num_rules; i++) {
+- if (refcount_read(&handle->rule[i]->node.refcount) == 1) {
++ if (!handle->rule[i]->node.parent) {
+ tree_add_node(&handle->rule[i]->node, &fte->node);
+ trace_mlx5_fs_add_rule(handle->rule[i]);
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
+index bccf6e53556c6..131a836c127e3 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
+@@ -1480,6 +1480,14 @@ int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev)
+ if (err)
+ goto err_register;
+
++ err = mlx5_crdump_enable(dev);
++ if (err)
++ mlx5_core_err(dev, "mlx5_crdump_enable failed with error code %d\n", err);
++
++ err = mlx5_hwmon_dev_register(dev);
++ if (err)
++ mlx5_core_err(dev, "mlx5_hwmon_dev_register failed with error code %d\n", err);
++
+ mutex_unlock(&dev->intf_state_mutex);
+ return 0;
+
+@@ -1505,7 +1513,10 @@ int mlx5_init_one(struct mlx5_core_dev *dev)
+ int err;
+
+ devl_lock(devlink);
++ devl_register(devlink);
+ err = mlx5_init_one_devl_locked(dev);
++ if (err)
++ devl_unregister(devlink);
+ devl_unlock(devlink);
+ return err;
+ }
+@@ -1517,6 +1528,8 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev)
+ devl_lock(devlink);
+ mutex_lock(&dev->intf_state_mutex);
+
++ mlx5_hwmon_dev_unregister(dev);
++ mlx5_crdump_disable(dev);
+ mlx5_unregister_device(dev);
+
+ if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
+@@ -1534,6 +1547,7 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev)
+ mlx5_function_teardown(dev, true);
+ out:
+ mutex_unlock(&dev->intf_state_mutex);
++ devl_unregister(devlink);
+ devl_unlock(devlink);
+ }
+
+@@ -1680,16 +1694,20 @@ int mlx5_init_one_light(struct mlx5_core_dev *dev)
+ }
+
+ devl_lock(devlink);
++ devl_register(devlink);
++
+ err = mlx5_devlink_params_register(priv_to_devlink(dev));
+- devl_unlock(devlink);
+ if (err) {
+ mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err);
+ goto query_hca_caps_err;
+ }
+
++ devl_unlock(devlink);
+ return 0;
+
+ query_hca_caps_err:
++ devl_unregister(devlink);
++ devl_unlock(devlink);
+ mlx5_function_disable(dev, true);
+ out:
+ dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
+@@ -1702,6 +1720,7 @@ void mlx5_uninit_one_light(struct mlx5_core_dev *dev)
+
+ devl_lock(devlink);
+ mlx5_devlink_params_unregister(priv_to_devlink(dev));
++ devl_unregister(devlink);
+ devl_unlock(devlink);
+ if (dev->state != MLX5_DEVICE_STATE_UP)
+ return;
+@@ -1943,16 +1962,7 @@ static int probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ goto err_init_one;
+ }
+
+- err = mlx5_crdump_enable(dev);
+- if (err)
+- dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err);
+-
+- err = mlx5_hwmon_dev_register(dev);
+- if (err)
+- mlx5_core_err(dev, "mlx5_hwmon_dev_register failed with error code %d\n", err);
+-
+ pci_save_state(pdev);
+- devlink_register(devlink);
+ return 0;
+
+ err_init_one:
+@@ -1973,16 +1983,9 @@ static void remove_one(struct pci_dev *pdev)
+ struct devlink *devlink = priv_to_devlink(dev);
+
+ set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
+- /* mlx5_drain_fw_reset() and mlx5_drain_health_wq() are using
+- * devlink notify APIs.
+- * Hence, we must drain them before unregistering the devlink.
+- */
+ mlx5_drain_fw_reset(dev);
+ mlx5_drain_health_wq(dev);
+- devlink_unregister(devlink);
+ mlx5_sriov_disable(pdev, false);
+- mlx5_hwmon_dev_unregister(dev);
+- mlx5_crdump_disable(dev);
+ mlx5_uninit_one(dev);
+ mlx5_pci_close(dev);
+ mlx5_mdev_uninit(dev);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+index 4dcf995cb1a20..6bac8ad70ba60 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+@@ -19,6 +19,7 @@
+ #define MLX5_IRQ_CTRL_SF_MAX 8
+ /* min num of vectors for SFs to be enabled */
+ #define MLX5_IRQ_VEC_COMP_BASE_SF 2
++#define MLX5_IRQ_VEC_COMP_BASE 1
+
+ #define MLX5_EQ_SHARE_IRQ_MAX_COMP (8)
+ #define MLX5_EQ_SHARE_IRQ_MAX_CTRL (UINT_MAX)
+@@ -246,6 +247,7 @@ static void irq_set_name(struct mlx5_irq_pool *pool, char *name, int vecidx)
+ return;
+ }
+
++ vecidx -= MLX5_IRQ_VEC_COMP_BASE;
+ snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", vecidx);
+ }
+
+@@ -585,7 +587,7 @@ struct mlx5_irq *mlx5_irq_request_vector(struct mlx5_core_dev *dev, u16 cpu,
+ struct mlx5_irq_table *table = mlx5_irq_table_get(dev);
+ struct mlx5_irq_pool *pool = table->pcif_pool;
+ struct irq_affinity_desc af_desc;
+- int offset = 1;
++ int offset = MLX5_IRQ_VEC_COMP_BASE;
+
+ if (!pool->xa_num_irqs.max)
+ offset = 0;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
+index 169c2c68ed5c2..e3bf8c7e4baa6 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
+@@ -95,24 +95,28 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
+ static void mlx5_sf_dev_remove(struct auxiliary_device *adev)
+ {
+ struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev);
+- struct devlink *devlink = priv_to_devlink(sf_dev->mdev);
++ struct mlx5_core_dev *mdev = sf_dev->mdev;
++ struct devlink *devlink;
+
+- mlx5_drain_health_wq(sf_dev->mdev);
+- devlink_unregister(devlink);
+- if (mlx5_dev_is_lightweight(sf_dev->mdev))
+- mlx5_uninit_one_light(sf_dev->mdev);
++ devlink = priv_to_devlink(mdev);
++ set_bit(MLX5_BREAK_FW_WAIT, &mdev->intf_state);
++ mlx5_drain_health_wq(mdev);
++ if (mlx5_dev_is_lightweight(mdev))
++ mlx5_uninit_one_light(mdev);
+ else
+- mlx5_uninit_one(sf_dev->mdev);
+- iounmap(sf_dev->mdev->iseg);
+- mlx5_mdev_uninit(sf_dev->mdev);
++ mlx5_uninit_one(mdev);
++ iounmap(mdev->iseg);
++ mlx5_mdev_uninit(mdev);
+ mlx5_devlink_free(devlink);
+ }
+
+ static void mlx5_sf_dev_shutdown(struct auxiliary_device *adev)
+ {
+ struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev);
++ struct mlx5_core_dev *mdev = sf_dev->mdev;
+
+- mlx5_unload_one(sf_dev->mdev, false);
++ set_bit(MLX5_BREAK_FW_WAIT, &mdev->intf_state);
++ mlx5_unload_one(mdev, false);
+ }
+
+ static const struct auxiliary_device_id mlx5_sf_dev_id_table[] = {
+diff --git a/drivers/net/ethernet/micrel/ks8851.h b/drivers/net/ethernet/micrel/ks8851.h
+index e5ec0a363aff8..31f75b4a67fd7 100644
+--- a/drivers/net/ethernet/micrel/ks8851.h
++++ b/drivers/net/ethernet/micrel/ks8851.h
+@@ -368,7 +368,6 @@ union ks8851_tx_hdr {
+ * @rdfifo: FIFO read callback
+ * @wrfifo: FIFO write callback
+ * @start_xmit: start_xmit() implementation callback
+- * @rx_skb: rx_skb() implementation callback
+ * @flush_tx_work: flush_tx_work() implementation callback
+ *
+ * The @statelock is used to protect information in the structure which may
+@@ -423,8 +422,6 @@ struct ks8851_net {
+ struct sk_buff *txp, bool irq);
+ netdev_tx_t (*start_xmit)(struct sk_buff *skb,
+ struct net_device *dev);
+- void (*rx_skb)(struct ks8851_net *ks,
+- struct sk_buff *skb);
+ void (*flush_tx_work)(struct ks8851_net *ks);
+ };
+
+diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c
+index 0bf13b38b8f5b..d4cdf3d4f5525 100644
+--- a/drivers/net/ethernet/micrel/ks8851_common.c
++++ b/drivers/net/ethernet/micrel/ks8851_common.c
+@@ -231,16 +231,6 @@ static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt)
+ rxpkt[12], rxpkt[13], rxpkt[14], rxpkt[15]);
+ }
+
+-/**
+- * ks8851_rx_skb - receive skbuff
+- * @ks: The device state.
+- * @skb: The skbuff
+- */
+-static void ks8851_rx_skb(struct ks8851_net *ks, struct sk_buff *skb)
+-{
+- ks->rx_skb(ks, skb);
+-}
+-
+ /**
+ * ks8851_rx_pkts - receive packets from the host
+ * @ks: The device information.
+@@ -309,7 +299,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
+ ks8851_dbg_dumpkkt(ks, rxpkt);
+
+ skb->protocol = eth_type_trans(skb, ks->netdev);
+- ks8851_rx_skb(ks, skb);
++ __netif_rx(skb);
+
+ ks->netdev->stats.rx_packets++;
+ ks->netdev->stats.rx_bytes += rxlen;
+@@ -340,6 +330,8 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
+ unsigned long flags;
+ unsigned int status;
+
++ local_bh_disable();
++
+ ks8851_lock(ks, &flags);
+
+ status = ks8851_rdreg16(ks, KS_ISR);
+@@ -416,6 +408,8 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
+ if (status & IRQ_LCI)
+ mii_check_link(&ks->mii);
+
++ local_bh_enable();
++
+ return IRQ_HANDLED;
+ }
+
+diff --git a/drivers/net/ethernet/micrel/ks8851_par.c b/drivers/net/ethernet/micrel/ks8851_par.c
+index 2a7f298542670..381b9cd285ebd 100644
+--- a/drivers/net/ethernet/micrel/ks8851_par.c
++++ b/drivers/net/ethernet/micrel/ks8851_par.c
+@@ -210,16 +210,6 @@ static void ks8851_wrfifo_par(struct ks8851_net *ks, struct sk_buff *txp,
+ iowrite16_rep(ksp->hw_addr, txp->data, len / 2);
+ }
+
+-/**
+- * ks8851_rx_skb_par - receive skbuff
+- * @ks: The device state.
+- * @skb: The skbuff
+- */
+-static void ks8851_rx_skb_par(struct ks8851_net *ks, struct sk_buff *skb)
+-{
+- netif_rx(skb);
+-}
+-
+ static unsigned int ks8851_rdreg16_par_txqcr(struct ks8851_net *ks)
+ {
+ return ks8851_rdreg16_par(ks, KS_TXQCR);
+@@ -298,7 +288,6 @@ static int ks8851_probe_par(struct platform_device *pdev)
+ ks->rdfifo = ks8851_rdfifo_par;
+ ks->wrfifo = ks8851_wrfifo_par;
+ ks->start_xmit = ks8851_start_xmit_par;
+- ks->rx_skb = ks8851_rx_skb_par;
+
+ #define STD_IRQ (IRQ_LCI | /* Link Change */ \
+ IRQ_RXI | /* RX done */ \
+diff --git a/drivers/net/ethernet/micrel/ks8851_spi.c b/drivers/net/ethernet/micrel/ks8851_spi.c
+index 54f2eac11a631..55f6f9f6d030e 100644
+--- a/drivers/net/ethernet/micrel/ks8851_spi.c
++++ b/drivers/net/ethernet/micrel/ks8851_spi.c
+@@ -298,16 +298,6 @@ static unsigned int calc_txlen(unsigned int len)
+ return ALIGN(len + 4, 4);
+ }
+
+-/**
+- * ks8851_rx_skb_spi - receive skbuff
+- * @ks: The device state
+- * @skb: The skbuff
+- */
+-static void ks8851_rx_skb_spi(struct ks8851_net *ks, struct sk_buff *skb)
+-{
+- netif_rx(skb);
+-}
+-
+ /**
+ * ks8851_tx_work - process tx packet(s)
+ * @work: The work strucutre what was scheduled.
+@@ -435,7 +425,6 @@ static int ks8851_probe_spi(struct spi_device *spi)
+ ks->rdfifo = ks8851_rdfifo_spi;
+ ks->wrfifo = ks8851_wrfifo_spi;
+ ks->start_xmit = ks8851_start_xmit_spi;
+- ks->rx_skb = ks8851_rx_skb_spi;
+ ks->flush_tx_work = ks8851_flush_tx_work_spi;
+
+ #define STD_IRQ (IRQ_LCI | /* Link Change */ \
+diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
+index 3a1b1a1f5a195..60dd2fd603a85 100644
+--- a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
+@@ -731,7 +731,7 @@ static int sparx5_port_pcs_low_set(struct sparx5 *sparx5,
+ bool sgmii = false, inband_aneg = false;
+ int err;
+
+- if (port->conf.inband) {
++ if (conf->inband) {
+ if (conf->portmode == PHY_INTERFACE_MODE_SGMII ||
+ conf->portmode == PHY_INTERFACE_MODE_QSGMII)
+ inband_aneg = true; /* Cisco-SGMII in-band-aneg */
+@@ -948,7 +948,7 @@ int sparx5_port_pcs_set(struct sparx5 *sparx5,
+ if (err)
+ return -EINVAL;
+
+- if (port->conf.inband) {
++ if (conf->inband) {
+ /* Enable/disable 1G counters in ASM */
+ spx5_rmw(ASM_PORT_CFG_CSC_STAT_DIS_SET(high_speed_dev),
+ ASM_PORT_CFG_CSC_STAT_DIS,
+diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
+index 097a8db0d1d99..7f00fca0c538c 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -830,7 +830,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
+ __be16 sport;
+ int err;
+
+- if (!pskb_inet_may_pull(skb))
++ if (!skb_vlan_inet_prepare(skb))
+ return -EINVAL;
+
+ if (!gs4)
+@@ -937,7 +937,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
+ __be16 sport;
+ int err;
+
+- if (!pskb_inet_may_pull(skb))
++ if (!skb_vlan_inet_prepare(skb))
+ return -EINVAL;
+
+ if (!gs6)
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index d7ce4a1011ea2..ec14bf2a9af05 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -3768,6 +3768,7 @@ static int virtnet_set_rxfh(struct net_device *dev,
+ struct netlink_ext_ack *extack)
+ {
+ struct virtnet_info *vi = netdev_priv(dev);
++ bool update = false;
+ int i;
+
+ if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
+@@ -3775,13 +3776,28 @@ static int virtnet_set_rxfh(struct net_device *dev,
+ return -EOPNOTSUPP;
+
+ if (rxfh->indir) {
++ if (!vi->has_rss)
++ return -EOPNOTSUPP;
++
+ for (i = 0; i < vi->rss_indir_table_size; ++i)
+ vi->ctrl->rss.indirection_table[i] = rxfh->indir[i];
++ update = true;
+ }
+- if (rxfh->key)
++
++ if (rxfh->key) {
++ /* If either _F_HASH_REPORT or _F_RSS are negotiated, the
++ * device provides hash calculation capabilities, that is,
++ * hash_key is configured.
++ */
++ if (!vi->has_rss && !vi->has_rss_hash_report)
++ return -EOPNOTSUPP;
++
+ memcpy(vi->ctrl->rss.key, rxfh->key, vi->rss_key_size);
++ update = true;
++ }
+
+- virtnet_commit_rss_command(vi);
++ if (update)
++ virtnet_commit_rss_command(vi);
+
+ return 0;
+ }
+@@ -4686,13 +4702,15 @@ static int virtnet_probe(struct virtio_device *vdev)
+ if (virtio_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT))
+ vi->has_rss_hash_report = true;
+
+- if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS))
++ if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) {
+ vi->has_rss = true;
+
+- if (vi->has_rss || vi->has_rss_hash_report) {
+ vi->rss_indir_table_size =
+ virtio_cread16(vdev, offsetof(struct virtio_net_config,
+ rss_max_indirection_table_length));
++ }
++
++ if (vi->has_rss || vi->has_rss_hash_report) {
+ vi->rss_key_size =
+ virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size));
+
+diff --git a/drivers/platform/chrome/cros_ec_uart.c b/drivers/platform/chrome/cros_ec_uart.c
+index 68d80559fddc2..eb5eddeb73f72 100644
+--- a/drivers/platform/chrome/cros_ec_uart.c
++++ b/drivers/platform/chrome/cros_ec_uart.c
+@@ -263,12 +263,6 @@ static int cros_ec_uart_probe(struct serdev_device *serdev)
+ if (!ec_dev)
+ return -ENOMEM;
+
+- ret = devm_serdev_device_open(dev, serdev);
+- if (ret) {
+- dev_err(dev, "Unable to open UART device");
+- return ret;
+- }
+-
+ serdev_device_set_drvdata(serdev, ec_dev);
+ init_waitqueue_head(&ec_uart->response.wait_queue);
+
+@@ -280,14 +274,6 @@ static int cros_ec_uart_probe(struct serdev_device *serdev)
+ return ret;
+ }
+
+- ret = serdev_device_set_baudrate(serdev, ec_uart->baudrate);
+- if (ret < 0) {
+- dev_err(dev, "Failed to set up host baud rate (%d)", ret);
+- return ret;
+- }
+-
+- serdev_device_set_flow_control(serdev, ec_uart->flowcontrol);
+-
+ /* Initialize ec_dev for cros_ec */
+ ec_dev->phys_name = dev_name(dev);
+ ec_dev->dev = dev;
+@@ -301,6 +287,20 @@ static int cros_ec_uart_probe(struct serdev_device *serdev)
+
+ serdev_device_set_client_ops(serdev, &cros_ec_uart_client_ops);
+
++ ret = devm_serdev_device_open(dev, serdev);
++ if (ret) {
++ dev_err(dev, "Unable to open UART device");
++ return ret;
++ }
++
++ ret = serdev_device_set_baudrate(serdev, ec_uart->baudrate);
++ if (ret < 0) {
++ dev_err(dev, "Failed to set up host baud rate (%d)", ret);
++ return ret;
++ }
++
++ serdev_device_set_flow_control(serdev, ec_uart->flowcontrol);
++
+ return cros_ec_register(ec_dev);
+ }
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 1abc62b07d24c..05c38e43f140a 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1792,7 +1792,7 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
+ if (dev_is_sata(device)) {
+ struct ata_link *link = &device->sata_dev.ap->link;
+
+- rc = ata_wait_after_reset(link, HISI_SAS_WAIT_PHYUP_TIMEOUT,
++ rc = ata_wait_after_reset(link, jiffies + HISI_SAS_WAIT_PHYUP_TIMEOUT,
+ smp_ata_check_ready_type);
+ } else {
+ msleep(2000);
+diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
+index 26e6b3e3af431..dcde55c8ee5de 100644
+--- a/drivers/scsi/qla2xxx/qla_edif.c
++++ b/drivers/scsi/qla2xxx/qla_edif.c
+@@ -1100,7 +1100,7 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+
+ list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
+ if (fcport->edif.enable) {
+- if (pcnt > app_req.num_ports)
++ if (pcnt >= app_req.num_ports)
+ break;
+
+ app_reply->elem[pcnt].rekey_count =
+diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
+index 86210e4dd0d35..b2d02dacaebd9 100644
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -285,6 +285,7 @@ sg_open(struct inode *inode, struct file *filp)
+ int dev = iminor(inode);
+ int flags = filp->f_flags;
+ struct request_queue *q;
++ struct scsi_device *device;
+ Sg_device *sdp;
+ Sg_fd *sfp;
+ int retval;
+@@ -301,11 +302,12 @@ sg_open(struct inode *inode, struct file *filp)
+
+ /* This driver's module count bumped by fops_get in <linux/fs.h> */
+ /* Prevent the device driver from vanishing while we sleep */
+- retval = scsi_device_get(sdp->device);
++ device = sdp->device;
++ retval = scsi_device_get(device);
+ if (retval)
+ goto sg_put;
+
+- retval = scsi_autopm_get_device(sdp->device);
++ retval = scsi_autopm_get_device(device);
+ if (retval)
+ goto sdp_put;
+
+@@ -313,7 +315,7 @@ sg_open(struct inode *inode, struct file *filp)
+ * check if O_NONBLOCK. Permits SCSI commands to be issued
+ * during error recovery. Tread carefully. */
+ if (!((flags & O_NONBLOCK) ||
+- scsi_block_when_processing_errors(sdp->device))) {
++ scsi_block_when_processing_errors(device))) {
+ retval = -ENXIO;
+ /* we are in error recovery for this device */
+ goto error_out;
+@@ -344,7 +346,7 @@ sg_open(struct inode *inode, struct file *filp)
+
+ if (sdp->open_cnt < 1) { /* no existing opens */
+ sdp->sgdebug = 0;
+- q = sdp->device->request_queue;
++ q = device->request_queue;
+ sdp->sg_tablesize = queue_max_segments(q);
+ }
+ sfp = sg_add_sfp(sdp);
+@@ -370,10 +372,11 @@ sg_open(struct inode *inode, struct file *filp)
+ error_mutex_locked:
+ mutex_unlock(&sdp->open_rel_lock);
+ error_out:
+- scsi_autopm_put_device(sdp->device);
++ scsi_autopm_put_device(device);
+ sdp_put:
+- scsi_device_put(sdp->device);
+- goto sg_put;
++ kref_put(&sdp->d_ref, sg_device_destroy);
++ scsi_device_put(device);
++ return retval;
+ }
+
+ /* Release resources associated with a successful sg_open()
+@@ -2207,6 +2210,7 @@ sg_remove_sfp_usercontext(struct work_struct *work)
+ {
+ struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
+ struct sg_device *sdp = sfp->parentdp;
++ struct scsi_device *device = sdp->device;
+ Sg_request *srp;
+ unsigned long iflags;
+
+@@ -2232,8 +2236,8 @@ sg_remove_sfp_usercontext(struct work_struct *work)
+ "sg_remove_sfp: sfp=0x%p\n", sfp));
+ kfree(sfp);
+
+- scsi_device_put(sdp->device);
+ kref_put(&sdp->d_ref, sg_device_destroy);
++ scsi_device_put(device);
+ module_put(THIS_MODULE);
+ }
+
+diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
+index 045f666b4f12a..32686c79c41d6 100644
+--- a/drivers/vhost/vhost.c
++++ b/drivers/vhost/vhost.c
+@@ -2799,9 +2799,19 @@ bool vhost_vq_avail_empty(struct vhost_dev *dev, struct vhost_virtqueue *vq)
+ r = vhost_get_avail_idx(vq, &avail_idx);
+ if (unlikely(r))
+ return false;
++
+ vq->avail_idx = vhost16_to_cpu(vq, avail_idx);
++ if (vq->avail_idx != vq->last_avail_idx) {
++ /* Since we have updated avail_idx, the following
++ * call to vhost_get_vq_desc() will read available
++ * ring entries. Make sure that read happens after
++ * the avail_idx read.
++ */
++ smp_rmb();
++ return false;
++ }
+
+- return vq->avail_idx == vq->last_avail_idx;
++ return true;
+ }
+ EXPORT_SYMBOL_GPL(vhost_vq_avail_empty);
+
+@@ -2838,9 +2848,19 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
+ &vq->avail->idx, r);
+ return false;
+ }
++
+ vq->avail_idx = vhost16_to_cpu(vq, avail_idx);
++ if (vq->avail_idx != vq->last_avail_idx) {
++ /* Since we have updated avail_idx, the following
++ * call to vhost_get_vq_desc() will read available
++ * ring entries. Make sure that read happens after
++ * the avail_idx read.
++ */
++ smp_rmb();
++ return true;
++ }
+
+- return vq->avail_idx != vq->last_avail_idx;
++ return false;
+ }
+ EXPORT_SYMBOL_GPL(vhost_enable_notify);
+
+diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
+index 08102883f560a..ab5a833e7d6ad 100644
+--- a/fs/btrfs/delayed-inode.c
++++ b/fs/btrfs/delayed-inode.c
+@@ -1128,6 +1128,9 @@ __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans,
+ if (ret)
+ return ret;
+
++ ret = btrfs_record_root_in_trans(trans, node->root);
++ if (ret)
++ return ret;
+ ret = btrfs_update_delayed_inode(trans, node->root, path, node);
+ return ret;
+ }
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 5ceb995709b56..6e2715e3f3aa0 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -4476,6 +4476,7 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
+ struct btrfs_trans_handle *trans;
+ struct btrfs_block_rsv block_rsv;
+ u64 root_flags;
++ u64 qgroup_reserved = 0;
+ int ret;
+
+ down_write(&fs_info->subvol_sem);
+@@ -4520,12 +4521,20 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
+ ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, 5, true);
+ if (ret)
+ goto out_undead;
++ qgroup_reserved = block_rsv.qgroup_rsv_reserved;
+
+ trans = btrfs_start_transaction(root, 0);
+ if (IS_ERR(trans)) {
+ ret = PTR_ERR(trans);
+ goto out_release;
+ }
++ ret = btrfs_record_root_in_trans(trans, root);
++ if (ret) {
++ btrfs_abort_transaction(trans, ret);
++ goto out_end_trans;
++ }
++ btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
++ qgroup_reserved = 0;
+ trans->block_rsv = &block_rsv;
+ trans->bytes_reserved = block_rsv.size;
+
+@@ -4584,7 +4593,9 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
+ ret = btrfs_end_transaction(trans);
+ inode->i_flags |= S_DEAD;
+ out_release:
+- btrfs_subvolume_release_metadata(root, &block_rsv);
++ btrfs_block_rsv_release(fs_info, &block_rsv, (u64)-1, NULL);
++ if (qgroup_reserved)
++ btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved);
+ out_undead:
+ if (ret) {
+ spin_lock(&dest->root_item_lock);
+diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
+index bd19aed66605a..6b93fae74403d 100644
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -603,6 +603,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
+ int ret;
+ dev_t anon_dev;
+ u64 objectid;
++ u64 qgroup_reserved = 0;
+
+ root_item = kzalloc(sizeof(*root_item), GFP_KERNEL);
+ if (!root_item)
+@@ -640,13 +641,18 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
+ trans_num_items, false);
+ if (ret)
+ goto out_new_inode_args;
++ qgroup_reserved = block_rsv.qgroup_rsv_reserved;
+
+ trans = btrfs_start_transaction(root, 0);
+ if (IS_ERR(trans)) {
+ ret = PTR_ERR(trans);
+- btrfs_subvolume_release_metadata(root, &block_rsv);
+- goto out_new_inode_args;
++ goto out_release_rsv;
+ }
++ ret = btrfs_record_root_in_trans(trans, BTRFS_I(dir)->root);
++ if (ret)
++ goto out;
++ btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
++ qgroup_reserved = 0;
+ trans->block_rsv = &block_rsv;
+ trans->bytes_reserved = block_rsv.size;
+ /* Tree log can't currently deal with an inode which is a new root. */
+@@ -757,9 +763,11 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
+ out:
+ trans->block_rsv = NULL;
+ trans->bytes_reserved = 0;
+- btrfs_subvolume_release_metadata(root, &block_rsv);
+-
+ btrfs_end_transaction(trans);
++out_release_rsv:
++ btrfs_block_rsv_release(fs_info, &block_rsv, (u64)-1, NULL);
++ if (qgroup_reserved)
++ btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved);
+ out_new_inode_args:
+ btrfs_new_inode_args_destroy(&new_inode_args);
+ out_inode:
+@@ -781,6 +789,8 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
+ struct btrfs_pending_snapshot *pending_snapshot;
+ unsigned int trans_num_items;
+ struct btrfs_trans_handle *trans;
++ struct btrfs_block_rsv *block_rsv;
++ u64 qgroup_reserved = 0;
+ int ret;
+
+ /* We do not support snapshotting right now. */
+@@ -817,19 +827,19 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
+ goto free_pending;
+ }
+
+- btrfs_init_block_rsv(&pending_snapshot->block_rsv,
+- BTRFS_BLOCK_RSV_TEMP);
++ block_rsv = &pending_snapshot->block_rsv;
++ btrfs_init_block_rsv(block_rsv, BTRFS_BLOCK_RSV_TEMP);
+ /*
+ * 1 to add dir item
+ * 1 to add dir index
+ * 1 to update parent inode item
+ */
+ trans_num_items = create_subvol_num_items(inherit) + 3;
+- ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root,
+- &pending_snapshot->block_rsv,
++ ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root, block_rsv,
+ trans_num_items, false);
+ if (ret)
+ goto free_pending;
++ qgroup_reserved = block_rsv->qgroup_rsv_reserved;
+
+ pending_snapshot->dentry = dentry;
+ pending_snapshot->root = root;
+@@ -842,6 +852,13 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
+ ret = PTR_ERR(trans);
+ goto fail;
+ }
++ ret = btrfs_record_root_in_trans(trans, BTRFS_I(dir)->root);
++ if (ret) {
++ btrfs_end_transaction(trans);
++ goto fail;
++ }
++ btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
++ qgroup_reserved = 0;
+
+ trans->pending_snapshot = pending_snapshot;
+
+@@ -871,7 +888,9 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
+ if (ret && pending_snapshot->snap)
+ pending_snapshot->snap->anon_dev = 0;
+ btrfs_put_root(pending_snapshot->snap);
+- btrfs_subvolume_release_metadata(root, &pending_snapshot->block_rsv);
++ btrfs_block_rsv_release(fs_info, block_rsv, (u64)-1, NULL);
++ if (qgroup_reserved)
++ btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved);
+ free_pending:
+ if (pending_snapshot->anon_dev)
+ free_anon_bdev(pending_snapshot->anon_dev);
+diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
+index a78c6694959aa..132802bd80999 100644
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -4432,6 +4432,8 @@ void btrfs_qgroup_convert_reserved_meta(struct btrfs_root *root, int num_bytes)
+ BTRFS_QGROUP_RSV_META_PREALLOC);
+ trace_qgroup_meta_convert(root, num_bytes);
+ qgroup_convert_meta(fs_info, root->root_key.objectid, num_bytes);
++ if (!sb_rdonly(fs_info->sb))
++ add_root_meta_rsv(root, num_bytes, BTRFS_QGROUP_RSV_META_PERTRANS);
+ }
+
+ /*
+diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
+index 603ad1459368c..5260677ad51e2 100644
+--- a/fs/btrfs/root-tree.c
++++ b/fs/btrfs/root-tree.c
+@@ -539,13 +539,3 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
+ }
+ return ret;
+ }
+-
+-void btrfs_subvolume_release_metadata(struct btrfs_root *root,
+- struct btrfs_block_rsv *rsv)
+-{
+- struct btrfs_fs_info *fs_info = root->fs_info;
+- u64 qgroup_to_release;
+-
+- btrfs_block_rsv_release(fs_info, rsv, (u64)-1, &qgroup_to_release);
+- btrfs_qgroup_convert_reserved_meta(root, qgroup_to_release);
+-}
+diff --git a/fs/btrfs/root-tree.h b/fs/btrfs/root-tree.h
+index 8b2c3859e4647..de0175cbdb1e5 100644
+--- a/fs/btrfs/root-tree.h
++++ b/fs/btrfs/root-tree.h
+@@ -8,8 +8,6 @@ struct fscrypt_str;
+ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
+ struct btrfs_block_rsv *rsv,
+ int nitems, bool use_global_rsv);
+-void btrfs_subvolume_release_metadata(struct btrfs_root *root,
+- struct btrfs_block_rsv *rsv);
+ int btrfs_add_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
+ u64 ref_id, u64 dirid, u64 sequence,
+ const struct fscrypt_str *name);
+diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c
+index 25b3349595e00..865d4af4b3035 100644
+--- a/fs/btrfs/tests/extent-io-tests.c
++++ b/fs/btrfs/tests/extent-io-tests.c
+@@ -11,6 +11,7 @@
+ #include "btrfs-tests.h"
+ #include "../ctree.h"
+ #include "../extent_io.h"
++#include "../disk-io.h"
+ #include "../btrfs_inode.h"
+
+ #define PROCESS_UNLOCK (1 << 0)
+@@ -105,9 +106,11 @@ static void dump_extent_io_tree(const struct extent_io_tree *tree)
+ }
+ }
+
+-static int test_find_delalloc(u32 sectorsize)
++static int test_find_delalloc(u32 sectorsize, u32 nodesize)
+ {
+- struct inode *inode;
++ struct btrfs_fs_info *fs_info;
++ struct btrfs_root *root = NULL;
++ struct inode *inode = NULL;
+ struct extent_io_tree *tmp;
+ struct page *page;
+ struct page *locked_page = NULL;
+@@ -121,12 +124,27 @@ static int test_find_delalloc(u32 sectorsize)
+
+ test_msg("running find delalloc tests");
+
++ fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
++ if (!fs_info) {
++ test_std_err(TEST_ALLOC_FS_INFO);
++ return -ENOMEM;
++ }
++
++ root = btrfs_alloc_dummy_root(fs_info);
++ if (IS_ERR(root)) {
++ test_std_err(TEST_ALLOC_ROOT);
++ ret = PTR_ERR(root);
++ goto out;
++ }
++
+ inode = btrfs_new_test_inode();
+ if (!inode) {
+ test_std_err(TEST_ALLOC_INODE);
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto out;
+ }
+ tmp = &BTRFS_I(inode)->io_tree;
++ BTRFS_I(inode)->root = root;
+
+ /*
+ * Passing NULL as we don't have fs_info but tracepoints are not used
+@@ -316,6 +334,8 @@ static int test_find_delalloc(u32 sectorsize)
+ process_page_range(inode, 0, total_dirty - 1,
+ PROCESS_UNLOCK | PROCESS_RELEASE);
+ iput(inode);
++ btrfs_free_dummy_root(root);
++ btrfs_free_dummy_fs_info(fs_info);
+ return ret;
+ }
+
+@@ -794,7 +814,7 @@ int btrfs_test_extent_io(u32 sectorsize, u32 nodesize)
+
+ test_msg("running extent I/O tests");
+
+- ret = test_find_delalloc(sectorsize);
++ ret = test_find_delalloc(sectorsize, nodesize);
+ if (ret)
+ goto out;
+
+diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
+index bf8e64c766b63..f1705ae59e4a9 100644
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -747,14 +747,6 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
+ h->reloc_reserved = reloc_reserved;
+ }
+
+- /*
+- * Now that we have found a transaction to be a part of, convert the
+- * qgroup reservation from prealloc to pertrans. A different transaction
+- * can't race in and free our pertrans out from under us.
+- */
+- if (qgroup_reserved)
+- btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
+-
+ got_it:
+ if (!current->journal_info)
+ current->journal_info = h;
+@@ -788,8 +780,15 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
+ * not just freed.
+ */
+ btrfs_end_transaction(h);
+- return ERR_PTR(ret);
++ goto reserve_fail;
+ }
++ /*
++ * Now that we have found a transaction to be a part of, convert the
++ * qgroup reservation from prealloc to pertrans. A different transaction
++ * can't race in and free our pertrans out from under us.
++ */
++ if (qgroup_reserved)
++ btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
+
+ return h;
+
+diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
+index 1340d77124ae4..ee9caf7916fb9 100644
+--- a/fs/ceph/addr.c
++++ b/fs/ceph/addr.c
+@@ -795,8 +795,10 @@ static int ceph_writepage(struct page *page, struct writeback_control *wbc)
+ ihold(inode);
+
+ if (wbc->sync_mode == WB_SYNC_NONE &&
+- ceph_inode_to_fs_client(inode)->write_congested)
++ ceph_inode_to_fs_client(inode)->write_congested) {
++ redirty_page_for_writepage(wbc, page);
+ return AOP_WRITEPAGE_ACTIVATE;
++ }
+
+ wait_on_page_fscache(page);
+
+diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
+index 7fb4aae974124..e8d8e3e633cdb 100644
+--- a/fs/ceph/caps.c
++++ b/fs/ceph/caps.c
+@@ -4775,13 +4775,13 @@ int ceph_drop_caps_for_unlink(struct inode *inode)
+
+ doutc(mdsc->fsc->client, "%p %llx.%llx\n", inode,
+ ceph_vinop(inode));
+- spin_lock(&mdsc->cap_unlink_delay_lock);
++ spin_lock(&mdsc->cap_delay_lock);
+ ci->i_ceph_flags |= CEPH_I_FLUSH;
+ if (!list_empty(&ci->i_cap_delay_list))
+ list_del_init(&ci->i_cap_delay_list);
+ list_add_tail(&ci->i_cap_delay_list,
+ &mdsc->cap_unlink_delay_list);
+- spin_unlock(&mdsc->cap_unlink_delay_lock);
++ spin_unlock(&mdsc->cap_delay_lock);
+
+ /*
+ * Fire the work immediately, because the MDS maybe
+diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
+index 3ab9c268a8bb3..360b686c3c67c 100644
+--- a/fs/ceph/mds_client.c
++++ b/fs/ceph/mds_client.c
+@@ -2504,7 +2504,7 @@ static void ceph_cap_unlink_work(struct work_struct *work)
+ struct ceph_client *cl = mdsc->fsc->client;
+
+ doutc(cl, "begin\n");
+- spin_lock(&mdsc->cap_unlink_delay_lock);
++ spin_lock(&mdsc->cap_delay_lock);
+ while (!list_empty(&mdsc->cap_unlink_delay_list)) {
+ struct ceph_inode_info *ci;
+ struct inode *inode;
+@@ -2516,15 +2516,15 @@ static void ceph_cap_unlink_work(struct work_struct *work)
+
+ inode = igrab(&ci->netfs.inode);
+ if (inode) {
+- spin_unlock(&mdsc->cap_unlink_delay_lock);
++ spin_unlock(&mdsc->cap_delay_lock);
+ doutc(cl, "on %p %llx.%llx\n", inode,
+ ceph_vinop(inode));
+ ceph_check_caps(ci, CHECK_CAPS_FLUSH);
+ iput(inode);
+- spin_lock(&mdsc->cap_unlink_delay_lock);
++ spin_lock(&mdsc->cap_delay_lock);
+ }
+ }
+- spin_unlock(&mdsc->cap_unlink_delay_lock);
++ spin_unlock(&mdsc->cap_delay_lock);
+ doutc(cl, "done\n");
+ }
+
+@@ -5404,7 +5404,6 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
+ INIT_LIST_HEAD(&mdsc->cap_wait_list);
+ spin_lock_init(&mdsc->cap_delay_lock);
+ INIT_LIST_HEAD(&mdsc->cap_unlink_delay_list);
+- spin_lock_init(&mdsc->cap_unlink_delay_lock);
+ INIT_LIST_HEAD(&mdsc->snap_flush_list);
+ spin_lock_init(&mdsc->snap_flush_lock);
+ mdsc->last_cap_flush_tid = 1;
+diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
+index 03f8ff00874f7..b88e804152241 100644
+--- a/fs/ceph/mds_client.h
++++ b/fs/ceph/mds_client.h
+@@ -461,9 +461,8 @@ struct ceph_mds_client {
+ struct delayed_work delayed_work; /* delayed work */
+ unsigned long last_renew_caps; /* last time we renewed our caps */
+ struct list_head cap_delay_list; /* caps with delayed release */
+- spinlock_t cap_delay_lock; /* protects cap_delay_list */
+ struct list_head cap_unlink_delay_list; /* caps with delayed release for unlink */
+- spinlock_t cap_unlink_delay_lock; /* protects cap_unlink_delay_list */
++ spinlock_t cap_delay_lock; /* protects cap_delay_list and cap_unlink_delay_list */
+ struct list_head snap_flush_list; /* cap_snaps ready to flush */
+ spinlock_t snap_flush_lock;
+
+diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
+index ffa4565c275a7..b7f943f33366d 100644
+--- a/fs/kernfs/file.c
++++ b/fs/kernfs/file.c
+@@ -634,11 +634,18 @@ static int kernfs_fop_open(struct inode *inode, struct file *file)
+ * each file a separate locking class. Let's differentiate on
+ * whether the file has mmap or not for now.
+ *
+- * Both paths of the branch look the same. They're supposed to
++ * For similar reasons, writable and readonly files are given different
++ * lockdep key, because the writable file /sys/power/resume may call vfs
++ * lookup helpers for arbitrary paths and readonly files can be read by
++ * overlayfs from vfs helpers when sysfs is a lower layer of overalyfs.
++ *
++ * All three cases look the same. They're supposed to
+ * look that way and give @of->mutex different static lockdep keys.
+ */
+ if (has_mmap)
+ mutex_init(&of->mutex);
++ else if (file->f_mode & FMODE_WRITE)
++ mutex_init(&of->mutex);
+ else
+ mutex_init(&of->mutex);
+
+diff --git a/fs/proc/bootconfig.c b/fs/proc/bootconfig.c
+index 902b326e1e560..87dcaae32ff87 100644
+--- a/fs/proc/bootconfig.c
++++ b/fs/proc/bootconfig.c
+@@ -62,12 +62,12 @@ static int __init copy_xbc_key_value_list(char *dst, size_t size)
+ break;
+ dst += ret;
+ }
+- if (ret >= 0 && boot_command_line[0]) {
+- ret = snprintf(dst, rest(dst, end), "# Parameters from bootloader:\n# %s\n",
+- boot_command_line);
+- if (ret > 0)
+- dst += ret;
+- }
++ }
++ if (cmdline_has_extra_options() && ret >= 0 && boot_command_line[0]) {
++ ret = snprintf(dst, rest(dst, end), "# Parameters from bootloader:\n# %s\n",
++ boot_command_line);
++ if (ret > 0)
++ dst += ret;
+ }
+ out:
+ kfree(key);
+diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
+index 13a9d7acf8f8e..0ff2491c311d8 100644
+--- a/fs/smb/client/cached_dir.c
++++ b/fs/smb/client/cached_dir.c
+@@ -433,8 +433,8 @@ smb2_close_cached_fid(struct kref *ref)
+ if (cfid->is_open) {
+ rc = SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid,
+ cfid->fid.volatile_fid);
+- if (rc != -EBUSY && rc != -EAGAIN)
+- atomic_dec(&cfid->tcon->num_remote_opens);
++ if (rc) /* should we retry on -EBUSY or -EAGAIN? */
++ cifs_dbg(VFS, "close cached dir rc %d\n", rc);
+ }
+
+ free_cached_dir(cfid);
+diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
+index 446225aada50d..8b45b82cd5edc 100644
+--- a/include/acpi/acpi_bus.h
++++ b/include/acpi/acpi_bus.h
+@@ -911,17 +911,19 @@ static inline bool acpi_int_uid_match(struct acpi_device *adev, u64 uid2)
+ * acpi_dev_hid_uid_match - Match device by supplied HID and UID
+ * @adev: ACPI device to match.
+ * @hid2: Hardware ID of the device.
+- * @uid2: Unique ID of the device, pass 0 or NULL to not check _UID.
++ * @uid2: Unique ID of the device, pass NULL to not check _UID.
+ *
+ * Matches HID and UID in @adev with given @hid2 and @uid2. Absence of @uid2
+ * will be treated as a match. If user wants to validate @uid2, it should be
+ * done before calling this function.
+ *
+- * Returns: %true if matches or @uid2 is 0 or NULL, %false otherwise.
++ * Returns: %true if matches or @uid2 is NULL, %false otherwise.
+ */
+ #define acpi_dev_hid_uid_match(adev, hid2, uid2) \
+ (acpi_dev_hid_match(adev, hid2) && \
+- (!(uid2) || acpi_dev_uid_match(adev, uid2)))
++ /* Distinguish integer 0 from NULL @uid2 */ \
++ (_Generic(uid2, ACPI_STR_TYPES(!(uid2)), default: 0) || \
++ acpi_dev_uid_match(adev, uid2)))
+
+ void acpi_dev_clear_dependencies(struct acpi_device *supplier);
+ bool acpi_dev_ready_for_enumeration(const struct acpi_device *device);
+diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h
+index ca73940e26df8..e5ee2c694401e 100644
+--- a/include/linux/bootconfig.h
++++ b/include/linux/bootconfig.h
+@@ -10,6 +10,7 @@
+ #ifdef __KERNEL__
+ #include <linux/kernel.h>
+ #include <linux/types.h>
++bool __init cmdline_has_extra_options(void);
+ #else /* !__KERNEL__ */
+ /*
+ * NOTE: This is only for tools/bootconfig, because tools/bootconfig will
+diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
+index e06bad467f55e..c3f9bb6602ba2 100644
+--- a/include/linux/dma-fence.h
++++ b/include/linux/dma-fence.h
+@@ -682,4 +682,11 @@ static inline bool dma_fence_is_container(struct dma_fence *fence)
+ return dma_fence_is_array(fence) || dma_fence_is_chain(fence);
+ }
+
++#define DMA_FENCE_WARN(f, fmt, args...) \
++ do { \
++ struct dma_fence *__ff = (f); \
++ pr_warn("f %llu#%llu: " fmt, __ff->context, __ff->seqno,\
++ ##args); \
++ } while (0)
++
+ #endif /* __LINUX_DMA_FENCE_H */
+diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h
+index 147feebd508ca..3f003d5fde534 100644
+--- a/include/linux/irqflags.h
++++ b/include/linux/irqflags.h
+@@ -114,7 +114,7 @@ do { \
+ # define lockdep_softirq_enter() do { } while (0)
+ # define lockdep_softirq_exit() do { } while (0)
+ # define lockdep_hrtimer_enter(__hrtimer) false
+-# define lockdep_hrtimer_exit(__context) do { } while (0)
++# define lockdep_hrtimer_exit(__context) do { (void)(__context); } while (0)
+ # define lockdep_posixtimer_enter() do { } while (0)
+ # define lockdep_posixtimer_exit() do { } while (0)
+ # define lockdep_irq_work_enter(__work) do { } while (0)
+diff --git a/include/linux/node.h b/include/linux/node.h
+index 25b66d705ee2e..dfc004e4bee74 100644
+--- a/include/linux/node.h
++++ b/include/linux/node.h
+@@ -34,6 +34,18 @@ struct access_coordinate {
+ unsigned int write_latency;
+ };
+
++/*
++ * ACCESS_COORDINATE_LOCAL correlates to ACCESS CLASS 0
++ * - access_coordinate between target node and nearest initiator node
++ * ACCESS_COORDINATE_CPU correlates to ACCESS CLASS 1
++ * - access_coordinate between target node and nearest CPU node
++ */
++enum access_coordinate_class {
++ ACCESS_COORDINATE_LOCAL,
++ ACCESS_COORDINATE_CPU,
++ ACCESS_COORDINATE_MAX
++};
++
+ enum cache_indexing {
+ NODE_CACHE_DIRECT_MAP,
+ NODE_CACHE_INDEXED,
+@@ -66,7 +78,7 @@ struct node_cache_attrs {
+ #ifdef CONFIG_HMEM_REPORTING
+ void node_add_cache(unsigned int nid, struct node_cache_attrs *cache_attrs);
+ void node_set_perf_attrs(unsigned int nid, struct access_coordinate *coord,
+- unsigned access);
++ enum access_coordinate_class access);
+ #else
+ static inline void node_add_cache(unsigned int nid,
+ struct node_cache_attrs *cache_attrs)
+@@ -75,7 +87,7 @@ static inline void node_add_cache(unsigned int nid,
+
+ static inline void node_set_perf_attrs(unsigned int nid,
+ struct access_coordinate *coord,
+- unsigned access)
++ enum access_coordinate_class access)
+ {
+ }
+ #endif
+@@ -137,7 +149,7 @@ extern void unregister_memory_block_under_nodes(struct memory_block *mem_blk);
+
+ extern int register_memory_node_under_compute_node(unsigned int mem_nid,
+ unsigned int cpu_nid,
+- unsigned access);
++ enum access_coordinate_class access);
+ #else
+ static inline void node_dev_init(void)
+ {
+diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h
+index ffe48e69b3f3a..457879938fc19 100644
+--- a/include/linux/u64_stats_sync.h
++++ b/include/linux/u64_stats_sync.h
+@@ -135,10 +135,11 @@ static inline void u64_stats_inc(u64_stats_t *p)
+ p->v++;
+ }
+
+-static inline void u64_stats_init(struct u64_stats_sync *syncp)
+-{
+- seqcount_init(&syncp->seq);
+-}
++#define u64_stats_init(syncp) \
++ do { \
++ struct u64_stats_sync *__s = (syncp); \
++ seqcount_init(&__s->seq); \
++ } while (0)
+
+ static inline void __u64_stats_update_begin(struct u64_stats_sync *syncp)
+ {
+diff --git a/include/net/addrconf.h b/include/net/addrconf.h
+index 61ebe723ee4d5..facb7a469efad 100644
+--- a/include/net/addrconf.h
++++ b/include/net/addrconf.h
+@@ -437,6 +437,10 @@ static inline void in6_ifa_hold(struct inet6_ifaddr *ifp)
+ refcount_inc(&ifp->refcnt);
+ }
+
++static inline bool in6_ifa_hold_safe(struct inet6_ifaddr *ifp)
++{
++ return refcount_inc_not_zero(&ifp->refcnt);
++}
+
+ /*
+ * compute link-local solicited-node multicast address
+diff --git a/include/net/af_unix.h b/include/net/af_unix.h
+index afd40dce40f3d..d1b07ddbe677e 100644
+--- a/include/net/af_unix.h
++++ b/include/net/af_unix.h
+@@ -55,7 +55,7 @@ struct unix_sock {
+ struct mutex iolock, bindlock;
+ struct sock *peer;
+ struct list_head link;
+- atomic_long_t inflight;
++ unsigned long inflight;
+ spinlock_t lock;
+ unsigned long gc_flags;
+ #define UNIX_GC_CANDIDATE 0
+diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
+index 7ffa8c192c3f2..eaec5d6caa29d 100644
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -164,6 +164,8 @@ struct bt_voice {
+ #define BT_ISO_QOS_BIG_UNSET 0xff
+ #define BT_ISO_QOS_BIS_UNSET 0xff
+
++#define BT_ISO_SYNC_TIMEOUT 0x07d0 /* 20 secs */
++
+ struct bt_iso_io_qos {
+ __u32 interval;
+ __u16 latency;
+@@ -583,6 +585,15 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
+ return skb;
+ }
+
++static inline int bt_copy_from_sockptr(void *dst, size_t dst_size,
++ sockptr_t src, size_t src_size)
++{
++ if (dst_size > src_size)
++ return -EINVAL;
++
++ return copy_from_sockptr(dst, src, dst_size);
++}
++
+ int bt_to_errno(u16 code);
+ __u8 bt_status(int err);
+
+diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
+index 2d746f4c9a0a4..6690939f241a4 100644
+--- a/include/net/ip_tunnels.h
++++ b/include/net/ip_tunnels.h
+@@ -360,6 +360,39 @@ static inline bool pskb_inet_may_pull(struct sk_buff *skb)
+ return pskb_network_may_pull(skb, nhlen);
+ }
+
++/* Variant of pskb_inet_may_pull().
++ */
++static inline bool skb_vlan_inet_prepare(struct sk_buff *skb)
++{
++ int nhlen = 0, maclen = ETH_HLEN;
++ __be16 type = skb->protocol;
++
++ /* Essentially this is skb_protocol(skb, true)
++ * And we get MAC len.
++ */
++ if (eth_type_vlan(type))
++ type = __vlan_get_protocol(skb, type, &maclen);
++
++ switch (type) {
++#if IS_ENABLED(CONFIG_IPV6)
++ case htons(ETH_P_IPV6):
++ nhlen = sizeof(struct ipv6hdr);
++ break;
++#endif
++ case htons(ETH_P_IP):
++ nhlen = sizeof(struct iphdr);
++ break;
++ }
++ /* For ETH_P_IPV6/ETH_P_IP we make sure to pull
++ * a base network header in skb->head.
++ */
++ if (!pskb_may_pull(skb, maclen + nhlen))
++ return false;
++
++ skb_set_network_header(skb, maclen);
++ return true;
++}
++
+ static inline int ip_encap_hlen(struct ip_tunnel_encap *e)
+ {
+ const struct ip_tunnel_encap_ops *ops;
+diff --git a/init/main.c b/init/main.c
+index 9e6ab6d593bd8..98fdd93d79a5c 100644
+--- a/init/main.c
++++ b/init/main.c
+@@ -485,6 +485,11 @@ static int __init warn_bootconfig(char *str)
+
+ early_param("bootconfig", warn_bootconfig);
+
++bool __init cmdline_has_extra_options(void)
++{
++ return extra_command_line || extra_init_args;
++}
++
+ /* Change NUL term back to "=", to make "param" the whole string. */
+ static void __init repair_env_string(char *param, char *val)
+ {
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index 0f52ea80103ef..3fc792dfc6ae7 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -949,6 +949,8 @@ bool io_fill_cqe_req_aux(struct io_kiocb *req, bool defer, s32 res, u32 cflags)
+ u64 user_data = req->cqe.user_data;
+ struct io_uring_cqe *cqe;
+
++ lockdep_assert(!io_wq_current_is_worker());
++
+ if (!defer)
+ return __io_post_aux_cqe(ctx, user_data, res, cflags, false);
+
+@@ -1950,6 +1952,29 @@ void io_wq_submit_work(struct io_wq_work *work)
+ goto fail;
+ }
+
++ /*
++ * If DEFER_TASKRUN is set, it's only allowed to post CQEs from the
++ * submitter task context. Final request completions are handed to the
++ * right context, however this is not the case of auxiliary CQEs,
++ * which is the main mean of operation for multishot requests.
++ * Don't allow any multishot execution from io-wq. It's more restrictive
++ * than necessary and also cleaner.
++ */
++ if (req->flags & REQ_F_APOLL_MULTISHOT) {
++ err = -EBADFD;
++ if (!file_can_poll(req->file))
++ goto fail;
++ if (req->file->f_flags & O_NONBLOCK ||
++ req->file->f_mode & FMODE_NOWAIT) {
++ err = -ECANCELED;
++ if (io_arm_poll_handler(req, issue_flags) != IO_APOLL_OK)
++ goto fail;
++ return;
++ } else {
++ req->flags &= ~REQ_F_APOLL_MULTISHOT;
++ }
++ }
++
+ if (req->flags & REQ_F_FORCE_ASYNC) {
+ bool opcode_poll = def->pollin || def->pollout;
+
+diff --git a/io_uring/net.c b/io_uring/net.c
+index 5a4001139e288..46ea09e1e3829 100644
+--- a/io_uring/net.c
++++ b/io_uring/net.c
+@@ -78,19 +78,6 @@ struct io_sr_msg {
+ */
+ #define MULTISHOT_MAX_RETRY 32
+
+-static inline bool io_check_multishot(struct io_kiocb *req,
+- unsigned int issue_flags)
+-{
+- /*
+- * When ->locked_cq is set we only allow to post CQEs from the original
+- * task context. Usual request completions will be handled in other
+- * generic paths but multipoll may decide to post extra cqes.
+- */
+- return !(issue_flags & IO_URING_F_IOWQ) ||
+- !(req->flags & REQ_F_APOLL_MULTISHOT) ||
+- !req->ctx->task_complete;
+-}
+-
+ int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+ {
+ struct io_shutdown *shutdown = io_kiocb_to_cmd(req, struct io_shutdown);
+@@ -837,9 +824,6 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
+ (sr->flags & IORING_RECVSEND_POLL_FIRST))
+ return io_setup_async_msg(req, kmsg, issue_flags);
+
+- if (!io_check_multishot(req, issue_flags))
+- return io_setup_async_msg(req, kmsg, issue_flags);
+-
+ retry_multishot:
+ if (io_do_buffer_select(req)) {
+ void __user *buf;
+@@ -935,9 +919,6 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
+ (sr->flags & IORING_RECVSEND_POLL_FIRST))
+ return -EAGAIN;
+
+- if (!io_check_multishot(req, issue_flags))
+- return -EAGAIN;
+-
+ sock = sock_from_file(req->file);
+ if (unlikely(!sock))
+ return -ENOTSOCK;
+@@ -1274,6 +1255,7 @@ int io_sendmsg_zc(struct io_kiocb *req, unsigned int issue_flags)
+
+ if (req_has_async_data(req)) {
+ kmsg = req->async_data;
++ kmsg->msg.msg_control_user = sr->msg_control;
+ } else {
+ ret = io_sendmsg_copy_hdr(req, &iomsg);
+ if (ret)
+@@ -1386,8 +1368,6 @@ int io_accept(struct io_kiocb *req, unsigned int issue_flags)
+ struct file *file;
+ int ret, fd;
+
+- if (!io_check_multishot(req, issue_flags))
+- return -EAGAIN;
+ retry:
+ if (!fixed) {
+ fd = __get_unused_fd_flags(accept->flags, accept->nofile);
+diff --git a/io_uring/rw.c b/io_uring/rw.c
+index dd6fe3b328f40..c3c154790e452 100644
+--- a/io_uring/rw.c
++++ b/io_uring/rw.c
+@@ -932,8 +932,6 @@ int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags)
+ */
+ if (!file_can_poll(req->file))
+ return -EBADFD;
+- if (issue_flags & IO_URING_F_IOWQ)
+- return -EAGAIN;
+
+ ret = __io_read(req, issue_flags);
+
+diff --git a/kernel/cpu.c b/kernel/cpu.c
+index e6ec3ba4950b4..980908ef958c1 100644
+--- a/kernel/cpu.c
++++ b/kernel/cpu.c
+@@ -3207,7 +3207,8 @@ enum cpu_mitigations {
+ };
+
+ static enum cpu_mitigations cpu_mitigations __ro_after_init =
+- CPU_MITIGATIONS_AUTO;
++ IS_ENABLED(CONFIG_SPECULATION_MITIGATIONS) ? CPU_MITIGATIONS_AUTO :
++ CPU_MITIGATIONS_OFF;
+
+ static int __init mitigations_parse_cmdline(char *arg)
+ {
+diff --git a/kernel/kprobes.c b/kernel/kprobes.c
+index 9d9095e817928..65adc815fc6e6 100644
+--- a/kernel/kprobes.c
++++ b/kernel/kprobes.c
+@@ -1567,10 +1567,17 @@ static int check_kprobe_address_safe(struct kprobe *p,
+ jump_label_lock();
+ preempt_disable();
+
+- /* Ensure it is not in reserved area nor out of text */
+- if (!(core_kernel_text((unsigned long) p->addr) ||
+- is_module_text_address((unsigned long) p->addr)) ||
+- in_gate_area_no_mm((unsigned long) p->addr) ||
++ /* Ensure the address is in a text area, and find a module if exists. */
++ *probed_mod = NULL;
++ if (!core_kernel_text((unsigned long) p->addr)) {
++ *probed_mod = __module_text_address((unsigned long) p->addr);
++ if (!(*probed_mod)) {
++ ret = -EINVAL;
++ goto out;
++ }
++ }
++ /* Ensure it is not in reserved area. */
++ if (in_gate_area_no_mm((unsigned long) p->addr) ||
+ within_kprobe_blacklist((unsigned long) p->addr) ||
+ jump_label_text_reserved(p->addr, p->addr) ||
+ static_call_text_reserved(p->addr, p->addr) ||
+@@ -1580,8 +1587,7 @@ static int check_kprobe_address_safe(struct kprobe *p,
+ goto out;
+ }
+
+- /* Check if 'p' is probing a module. */
+- *probed_mod = __module_text_address((unsigned long) p->addr);
++ /* Get module refcount and reject __init functions for loaded modules. */
+ if (*probed_mod) {
+ /*
+ * We must hold a refcount of the probed module while updating
+diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
+index a718067deecee..3aae526cc4aac 100644
+--- a/kernel/power/suspend.c
++++ b/kernel/power/suspend.c
+@@ -106,6 +106,12 @@ static void s2idle_enter(void)
+ swait_event_exclusive(s2idle_wait_head,
+ s2idle_state == S2IDLE_STATE_WAKE);
+
++ /*
++ * Kick all CPUs to ensure that they resume their timers and restore
++ * consistent system state.
++ */
++ wake_up_all_idle_cpus();
++
+ cpus_read_unlock();
+
+ raw_spin_lock_irq(&s2idle_lock);
+diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
+index 2ad234366d21c..faf56d9a9e88e 100644
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -1400,7 +1400,6 @@ static void rb_tail_page_update(struct ring_buffer_per_cpu *cpu_buffer,
+ old_write = local_add_return(RB_WRITE_INTCNT, &next_page->write);
+ old_entries = local_add_return(RB_WRITE_INTCNT, &next_page->entries);
+
+- local_inc(&cpu_buffer->pages_touched);
+ /*
+ * Just make sure we have seen our old_write and synchronize
+ * with any interrupts that come in.
+@@ -1437,8 +1436,9 @@ static void rb_tail_page_update(struct ring_buffer_per_cpu *cpu_buffer,
+ */
+ local_set(&next_page->page->commit, 0);
+
+- /* Again, either we update tail_page or an interrupt does */
+- (void)cmpxchg(&cpu_buffer->tail_page, tail_page, next_page);
++ /* Either we update tail_page or an interrupt does */
++ if (try_cmpxchg(&cpu_buffer->tail_page, &tail_page, next_page))
++ local_inc(&cpu_buffer->pages_touched);
+ }
+ }
+
+diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
+index 7c364b87352ee..52f75c36bbca4 100644
+--- a/kernel/trace/trace_events.c
++++ b/kernel/trace/trace_events.c
+@@ -1670,6 +1670,7 @@ static int trace_format_open(struct inode *inode, struct file *file)
+ return 0;
+ }
+
++#ifdef CONFIG_PERF_EVENTS
+ static ssize_t
+ event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+ {
+@@ -1684,6 +1685,7 @@ event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+
+ return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
+ }
++#endif
+
+ static ssize_t
+ event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
+@@ -2152,10 +2154,12 @@ static const struct file_operations ftrace_event_format_fops = {
+ .release = seq_release,
+ };
+
++#ifdef CONFIG_PERF_EVENTS
+ static const struct file_operations ftrace_event_id_fops = {
+ .read = event_id_read,
+ .llseek = default_llseek,
+ };
++#endif
+
+ static const struct file_operations ftrace_event_filter_fops = {
+ .open = tracing_open_file_tr,
+diff --git a/lib/checksum_kunit.c b/lib/checksum_kunit.c
+index bf70850035c76..404dba36bae38 100644
+--- a/lib/checksum_kunit.c
++++ b/lib/checksum_kunit.c
+@@ -594,13 +594,15 @@ static void test_ip_fast_csum(struct kunit *test)
+
+ static void test_csum_ipv6_magic(struct kunit *test)
+ {
+-#if defined(CONFIG_NET)
+ const struct in6_addr *saddr;
+ const struct in6_addr *daddr;
+ unsigned int len;
+ unsigned char proto;
+ __wsum csum;
+
++ if (!IS_ENABLED(CONFIG_NET))
++ return;
++
+ const int daddr_offset = sizeof(struct in6_addr);
+ const int len_offset = sizeof(struct in6_addr) + sizeof(struct in6_addr);
+ const int proto_offset = sizeof(struct in6_addr) + sizeof(struct in6_addr) +
+@@ -618,7 +620,6 @@ static void test_csum_ipv6_magic(struct kunit *test)
+ CHECK_EQ(to_sum16(expected_csum_ipv6_magic[i]),
+ csum_ipv6_magic(saddr, daddr, len, proto, csum));
+ }
+-#endif /* !CONFIG_NET */
+ }
+
+ static struct kunit_case __refdata checksum_test_cases[] = {
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index b95c36765d045..2243cec18ecc8 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -3948,7 +3948,7 @@ void batadv_tt_local_resize_to_mtu(struct net_device *soft_iface)
+
+ spin_lock_bh(&bat_priv->tt.commit_lock);
+
+- while (true) {
++ while (timeout) {
+ table_size = batadv_tt_local_table_transmit_size(bat_priv);
+ if (packet_size_max >= table_size)
+ break;
+diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
+index 00e02138003ec..efea25eb56ce0 100644
+--- a/net/bluetooth/hci_request.c
++++ b/net/bluetooth/hci_request.c
+@@ -105,8 +105,10 @@ void hci_req_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode,
+ if (hdev->req_status == HCI_REQ_PEND) {
+ hdev->req_result = result;
+ hdev->req_status = HCI_REQ_DONE;
+- if (skb)
++ if (skb) {
++ kfree_skb(hdev->req_skb);
+ hdev->req_skb = skb_get(skb);
++ }
+ wake_up_interruptible(&hdev->req_wait_q);
+ }
+ }
+diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
+index 3e7cd330d731a..3f5f0932330d2 100644
+--- a/net/bluetooth/hci_sock.c
++++ b/net/bluetooth/hci_sock.c
+@@ -1946,10 +1946,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
+
+ switch (optname) {
+ case HCI_DATA_DIR:
+- if (copy_from_sockptr(&opt, optval, sizeof(opt))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
+@@ -1958,10 +1957,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
+ break;
+
+ case HCI_TIME_STAMP:
+- if (copy_from_sockptr(&opt, optval, sizeof(opt))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
+@@ -1979,11 +1977,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
+ uf.event_mask[1] = *((u32 *) f->event_mask + 1);
+ }
+
+- len = min_t(unsigned int, len, sizeof(uf));
+- if (copy_from_sockptr(&uf, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&uf, sizeof(uf), optval, len);
++ if (err)
+ break;
+- }
+
+ if (!capable(CAP_NET_RAW)) {
+ uf.type_mask &= hci_sec_filter.type_mask;
+@@ -2042,10 +2038,9 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
+ goto done;
+ }
+
+- if (copy_from_sockptr(&opt, optval, sizeof(opt))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
++ if (err)
+ break;
+- }
+
+ hci_pi(sk)->mtu = opt;
+ break;
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 824ce03bb361b..e1050d7d21a59 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -2611,6 +2611,14 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
+ return filter_policy;
+ }
+
++static void hci_le_scan_phy_params(struct hci_cp_le_scan_phy_params *cp,
++ u8 type, u16 interval, u16 window)
++{
++ cp->type = type;
++ cp->interval = cpu_to_le16(interval);
++ cp->window = cpu_to_le16(window);
++}
++
+ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
+ u16 interval, u16 window,
+ u8 own_addr_type, u8 filter_policy)
+@@ -2618,7 +2626,7 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
+ struct hci_cp_le_set_ext_scan_params *cp;
+ struct hci_cp_le_scan_phy_params *phy;
+ u8 data[sizeof(*cp) + sizeof(*phy) * 2];
+- u8 num_phy = 0;
++ u8 num_phy = 0x00;
+
+ cp = (void *)data;
+ phy = (void *)cp->data;
+@@ -2628,28 +2636,64 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
+ cp->own_addr_type = own_addr_type;
+ cp->filter_policy = filter_policy;
+
++ /* Check if PA Sync is in progress then select the PHY based on the
++ * hci_conn.iso_qos.
++ */
++ if (hci_dev_test_flag(hdev, HCI_PA_SYNC)) {
++ struct hci_cp_le_add_to_accept_list *sent;
++
++ sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_ACCEPT_LIST);
++ if (sent) {
++ struct hci_conn *conn;
++
++ conn = hci_conn_hash_lookup_ba(hdev, ISO_LINK,
++ &sent->bdaddr);
++ if (conn) {
++ struct bt_iso_qos *qos = &conn->iso_qos;
++
++ if (qos->bcast.in.phy & BT_ISO_PHY_1M ||
++ qos->bcast.in.phy & BT_ISO_PHY_2M) {
++ cp->scanning_phys |= LE_SCAN_PHY_1M;
++ hci_le_scan_phy_params(phy, type,
++ interval,
++ window);
++ num_phy++;
++ phy++;
++ }
++
++ if (qos->bcast.in.phy & BT_ISO_PHY_CODED) {
++ cp->scanning_phys |= LE_SCAN_PHY_CODED;
++ hci_le_scan_phy_params(phy, type,
++ interval * 3,
++ window * 3);
++ num_phy++;
++ phy++;
++ }
++
++ if (num_phy)
++ goto done;
++ }
++ }
++ }
++
+ if (scan_1m(hdev) || scan_2m(hdev)) {
+ cp->scanning_phys |= LE_SCAN_PHY_1M;
+-
+- phy->type = type;
+- phy->interval = cpu_to_le16(interval);
+- phy->window = cpu_to_le16(window);
+-
++ hci_le_scan_phy_params(phy, type, interval, window);
+ num_phy++;
+ phy++;
+ }
+
+ if (scan_coded(hdev)) {
+ cp->scanning_phys |= LE_SCAN_PHY_CODED;
+-
+- phy->type = type;
+- phy->interval = cpu_to_le16(interval);
+- phy->window = cpu_to_le16(window);
+-
++ hci_le_scan_phy_params(phy, type, interval * 3, window * 3);
+ num_phy++;
+ phy++;
+ }
+
++done:
++ if (!num_phy)
++ return -EINVAL;
++
+ return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS,
+ sizeof(*cp) + sizeof(*phy) * num_phy,
+ data, HCI_CMD_TIMEOUT);
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index 04f6572d35f17..a8b05baa8e5a9 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -837,10 +837,10 @@ static struct bt_iso_qos default_qos = {
+ .bcode = {0x00},
+ .options = 0x00,
+ .skip = 0x0000,
+- .sync_timeout = 0x4000,
++ .sync_timeout = BT_ISO_SYNC_TIMEOUT,
+ .sync_cte_type = 0x00,
+ .mse = 0x00,
+- .timeout = 0x4000,
++ .timeout = BT_ISO_SYNC_TIMEOUT,
+ },
+ };
+
+@@ -1430,8 +1430,8 @@ static bool check_ucast_qos(struct bt_iso_qos *qos)
+
+ static bool check_bcast_qos(struct bt_iso_qos *qos)
+ {
+- if (qos->bcast.sync_factor == 0x00)
+- return false;
++ if (!qos->bcast.sync_factor)
++ qos->bcast.sync_factor = 0x01;
+
+ if (qos->bcast.packing > 0x01)
+ return false;
+@@ -1454,6 +1454,9 @@ static bool check_bcast_qos(struct bt_iso_qos *qos)
+ if (qos->bcast.skip > 0x01f3)
+ return false;
+
++ if (!qos->bcast.sync_timeout)
++ qos->bcast.sync_timeout = BT_ISO_SYNC_TIMEOUT;
++
+ if (qos->bcast.sync_timeout < 0x000a || qos->bcast.sync_timeout > 0x4000)
+ return false;
+
+@@ -1463,6 +1466,9 @@ static bool check_bcast_qos(struct bt_iso_qos *qos)
+ if (qos->bcast.mse > 0x1f)
+ return false;
+
++ if (!qos->bcast.timeout)
++ qos->bcast.sync_timeout = BT_ISO_SYNC_TIMEOUT;
++
+ if (qos->bcast.timeout < 0x000a || qos->bcast.timeout > 0x4000)
+ return false;
+
+@@ -1473,7 +1479,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ sockptr_t optval, unsigned int optlen)
+ {
+ struct sock *sk = sock->sk;
+- int len, err = 0;
++ int err = 0;
+ struct bt_iso_qos qos = default_qos;
+ u32 opt;
+
+@@ -1488,10 +1494,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+@@ -1500,10 +1505,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+
+ case BT_PKT_STATUS:
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags);
+@@ -1518,17 +1522,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- len = min_t(unsigned int, sizeof(qos), optlen);
+-
+- if (copy_from_sockptr(&qos, optval, len)) {
+- err = -EFAULT;
+- break;
+- }
+-
+- if (len == sizeof(qos.ucast) && !check_ucast_qos(&qos)) {
+- err = -EINVAL;
++ err = bt_copy_from_sockptr(&qos, sizeof(qos), optval, optlen);
++ if (err)
+ break;
+- }
+
+ iso_pi(sk)->qos = qos;
+ iso_pi(sk)->qos_user_set = true;
+@@ -1543,18 +1539,16 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ }
+
+ if (optlen > sizeof(iso_pi(sk)->base)) {
+- err = -EOVERFLOW;
++ err = -EINVAL;
+ break;
+ }
+
+- len = min_t(unsigned int, sizeof(iso_pi(sk)->base), optlen);
+-
+- if (copy_from_sockptr(iso_pi(sk)->base, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(iso_pi(sk)->base, optlen, optval,
++ optlen);
++ if (err)
+ break;
+- }
+
+- iso_pi(sk)->base_len = len;
++ iso_pi(sk)->base_len = optlen;
+
+ break;
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index ab5a9d42fae71..706d2478ddb33 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -4054,8 +4054,7 @@ static int l2cap_connect_req(struct l2cap_conn *conn,
+ return -EPROTO;
+
+ hci_dev_lock(hdev);
+- if (hci_dev_test_flag(hdev, HCI_MGMT) &&
+- !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
++ if (hci_dev_test_flag(hdev, HCI_MGMT))
+ mgmt_device_connected(hdev, hcon, NULL, 0);
+ hci_dev_unlock(hdev);
+
+diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
+index ee7a41d6994fc..1eeea5d1306c2 100644
+--- a/net/bluetooth/l2cap_sock.c
++++ b/net/bluetooth/l2cap_sock.c
+@@ -726,7 +726,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
+ struct sock *sk = sock->sk;
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+ struct l2cap_options opts;
+- int len, err = 0;
++ int err = 0;
+ u32 opt;
+
+ BT_DBG("sk %p", sk);
+@@ -753,11 +753,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
+ opts.max_tx = chan->max_tx;
+ opts.txwin_size = chan->tx_win;
+
+- len = min_t(unsigned int, sizeof(opts), optlen);
+- if (copy_from_sockptr(&opts, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opts, sizeof(opts), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) {
+ err = -EINVAL;
+@@ -800,10 +798,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
+ break;
+
+ case L2CAP_LM:
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt & L2CAP_LM_FIPS) {
+ err = -EINVAL;
+@@ -884,7 +881,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ struct bt_security sec;
+ struct bt_power pwr;
+ struct l2cap_conn *conn;
+- int len, err = 0;
++ int err = 0;
+ u32 opt;
+ u16 mtu;
+ u8 mode;
+@@ -910,11 +907,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ sec.level = BT_SECURITY_LOW;
+
+- len = min_t(unsigned int, sizeof(sec), optlen);
+- if (copy_from_sockptr(&sec, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (sec.level < BT_SECURITY_LOW ||
+ sec.level > BT_SECURITY_FIPS) {
+@@ -959,10 +954,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt) {
+ set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+@@ -974,10 +968,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+
+ case BT_FLUSHABLE:
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt > BT_FLUSHABLE_ON) {
+ err = -EINVAL;
+@@ -1009,11 +1002,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
+
+- len = min_t(unsigned int, sizeof(pwr), optlen);
+- if (copy_from_sockptr(&pwr, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&pwr, sizeof(pwr), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (pwr.force_active)
+ set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
+@@ -1022,10 +1013,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+
+ case BT_CHANNEL_POLICY:
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ err = -EOPNOTSUPP;
+ break;
+@@ -1054,10 +1044,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&mtu, optval, sizeof(u16))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&mtu, sizeof(mtu), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (chan->mode == L2CAP_MODE_EXT_FLOWCTL &&
+ sk->sk_state == BT_CONNECTED)
+@@ -1085,10 +1074,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&mode, optval, sizeof(u8))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&mode, sizeof(mode), optval, optlen);
++ if (err)
+ break;
+- }
+
+ BT_DBG("mode %u", mode);
+
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index b54e8a530f55a..29aa07e9db9d7 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -629,7 +629,7 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname,
+
+ switch (optname) {
+ case RFCOMM_LM:
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
++ if (bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen)) {
+ err = -EFAULT;
+ break;
+ }
+@@ -664,7 +664,6 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
+ struct sock *sk = sock->sk;
+ struct bt_security sec;
+ int err = 0;
+- size_t len;
+ u32 opt;
+
+ BT_DBG("sk %p", sk);
+@@ -686,11 +685,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ sec.level = BT_SECURITY_LOW;
+
+- len = min_t(unsigned int, sizeof(sec), optlen);
+- if (copy_from_sockptr(&sec, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (sec.level > BT_SECURITY_HIGH) {
+ err = -EINVAL;
+@@ -706,10 +703,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index c736186aba26b..8e4f39b8601cb 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -823,7 +823,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+ sockptr_t optval, unsigned int optlen)
+ {
+ struct sock *sk = sock->sk;
+- int len, err = 0;
++ int err = 0;
+ struct bt_voice voice;
+ u32 opt;
+ struct bt_codecs *codecs;
+@@ -842,10 +842,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+@@ -862,11 +861,10 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ voice.setting = sco_pi(sk)->setting;
+
+- len = min_t(unsigned int, sizeof(voice), optlen);
+- if (copy_from_sockptr(&voice, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&voice, sizeof(voice), optval,
++ optlen);
++ if (err)
+ break;
+- }
+
+ /* Explicitly check for these values */
+ if (voice.setting != BT_VOICE_TRANSPARENT &&
+@@ -889,10 +887,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+
+ case BT_PKT_STATUS:
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags);
+@@ -933,9 +930,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(buffer, optval, optlen)) {
++ err = bt_copy_from_sockptr(buffer, optlen, optval, optlen);
++ if (err) {
+ hci_dev_put(hdev);
+- err = -EFAULT;
+ break;
+ }
+
+diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
+index b150c9929b12e..14365b20f1c5c 100644
+--- a/net/ipv4/netfilter/arp_tables.c
++++ b/net/ipv4/netfilter/arp_tables.c
+@@ -966,6 +966,8 @@ static int do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ return -ENOMEM;
+ if (tmp.num_counters == 0)
+ return -EINVAL;
++ if ((u64)len < (u64)tmp.size + sizeof(tmp))
++ return -EINVAL;
+
+ tmp.name[sizeof(tmp.name)-1] = 0;
+
+@@ -1266,6 +1268,8 @@ static int compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ return -ENOMEM;
+ if (tmp.num_counters == 0)
+ return -EINVAL;
++ if ((u64)len < (u64)tmp.size + sizeof(tmp))
++ return -EINVAL;
+
+ tmp.name[sizeof(tmp.name)-1] = 0;
+
+diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
+index 4876707595781..fe89a056eb06c 100644
+--- a/net/ipv4/netfilter/ip_tables.c
++++ b/net/ipv4/netfilter/ip_tables.c
+@@ -1118,6 +1118,8 @@ do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ return -ENOMEM;
+ if (tmp.num_counters == 0)
+ return -EINVAL;
++ if ((u64)len < (u64)tmp.size + sizeof(tmp))
++ return -EINVAL;
+
+ tmp.name[sizeof(tmp.name)-1] = 0;
+
+@@ -1504,6 +1506,8 @@ compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ return -ENOMEM;
+ if (tmp.num_counters == 0)
+ return -EINVAL;
++ if ((u64)len < (u64)tmp.size + sizeof(tmp))
++ return -EINVAL;
+
+ tmp.name[sizeof(tmp.name)-1] = 0;
+
+diff --git a/net/ipv4/route.c b/net/ipv4/route.c
+index 16615d107cf06..15c37c8113fc8 100644
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -926,13 +926,11 @@ void ip_rt_send_redirect(struct sk_buff *skb)
+ icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw);
+ peer->rate_last = jiffies;
+ ++peer->n_redirects;
+-#ifdef CONFIG_IP_ROUTE_VERBOSE
+- if (log_martians &&
++ if (IS_ENABLED(CONFIG_IP_ROUTE_VERBOSE) && log_martians &&
+ peer->n_redirects == ip_rt_redirect_number)
+ net_warn_ratelimited("host %pI4/if%d ignores redirects for %pI4 to %pI4\n",
+ &ip_hdr(skb)->saddr, inet_iif(skb),
+ &ip_hdr(skb)->daddr, &gw);
+-#endif
+ }
+ out_put_peer:
+ inet_putpeer(peer);
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index 055230b669cf2..37d48aa073c3c 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -2061,9 +2061,10 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add
+ if (ipv6_addr_equal(&ifp->addr, addr)) {
+ if (!dev || ifp->idev->dev == dev ||
+ !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) {
+- result = ifp;
+- in6_ifa_hold(ifp);
+- break;
++ if (in6_ifa_hold_safe(ifp)) {
++ result = ifp;
++ break;
++ }
+ }
+ }
+ }
+diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
+index 54294f6a8ec51..8184076a3924e 100644
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -1375,7 +1375,10 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
+ struct nl_info *info, struct netlink_ext_ack *extack)
+ {
+ struct fib6_table *table = rt->fib6_table;
+- struct fib6_node *fn, *pn = NULL;
++ struct fib6_node *fn;
++#ifdef CONFIG_IPV6_SUBTREES
++ struct fib6_node *pn = NULL;
++#endif
+ int err = -ENOMEM;
+ int allow_create = 1;
+ int replace_required = 0;
+@@ -1399,9 +1402,9 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
+ goto out;
+ }
+
++#ifdef CONFIG_IPV6_SUBTREES
+ pn = fn;
+
+-#ifdef CONFIG_IPV6_SUBTREES
+ if (rt->fib6_src.plen) {
+ struct fib6_node *sn;
+
+diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
+index 636b360311c53..131f7bb2110d3 100644
+--- a/net/ipv6/netfilter/ip6_tables.c
++++ b/net/ipv6/netfilter/ip6_tables.c
+@@ -1135,6 +1135,8 @@ do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ return -ENOMEM;
+ if (tmp.num_counters == 0)
+ return -EINVAL;
++ if ((u64)len < (u64)tmp.size + sizeof(tmp))
++ return -EINVAL;
+
+ tmp.name[sizeof(tmp.name)-1] = 0;
+
+@@ -1513,6 +1515,8 @@ compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ return -ENOMEM;
+ if (tmp.num_counters == 0)
+ return -EINVAL;
++ if ((u64)len < (u64)tmp.size + sizeof(tmp))
++ return -EINVAL;
+
+ tmp.name[sizeof(tmp.name)-1] = 0;
+
+diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
+index 3019a4406ca4f..74b63cdb59923 100644
+--- a/net/openvswitch/conntrack.c
++++ b/net/openvswitch/conntrack.c
+@@ -1380,8 +1380,9 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
+ if (ct_info.timeout[0]) {
+ if (nf_ct_set_timeout(net, ct_info.ct, family, key->ip.proto,
+ ct_info.timeout))
+- pr_info_ratelimited("Failed to associated timeout "
+- "policy `%s'\n", ct_info.timeout);
++ OVS_NLERR(log,
++ "Failed to associated timeout policy '%s'",
++ ct_info.timeout);
+ else
+ ct_info.nf_ct_timeout = rcu_dereference(
+ nf_ct_timeout_find(ct_info.ct)->timeout);
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index 0748e7ea5210e..e37cf913818a1 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -980,11 +980,11 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern,
+ sk->sk_write_space = unix_write_space;
+ sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen;
+ sk->sk_destruct = unix_sock_destructor;
+- u = unix_sk(sk);
++ u = unix_sk(sk);
++ u->inflight = 0;
+ u->path.dentry = NULL;
+ u->path.mnt = NULL;
+ spin_lock_init(&u->lock);
+- atomic_long_set(&u->inflight, 0);
+ INIT_LIST_HEAD(&u->link);
+ mutex_init(&u->iolock); /* single task reading lock */
+ mutex_init(&u->bindlock); /* single task binding lock */
+@@ -2604,7 +2604,9 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
+ }
+ } else if (!(flags & MSG_PEEK)) {
+ skb_unlink(skb, &sk->sk_receive_queue);
+- consume_skb(skb);
++ WRITE_ONCE(u->oob_skb, NULL);
++ if (!WARN_ON_ONCE(skb_unref(skb)))
++ kfree_skb(skb);
+ skb = skb_peek(&sk->sk_receive_queue);
+ }
+ }
+diff --git a/net/unix/garbage.c b/net/unix/garbage.c
+index 027c86e804f8a..8734c0c1fc197 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -166,17 +166,18 @@ static void scan_children(struct sock *x, void (*func)(struct unix_sock *),
+
+ static void dec_inflight(struct unix_sock *usk)
+ {
+- atomic_long_dec(&usk->inflight);
++ usk->inflight--;
+ }
+
+ static void inc_inflight(struct unix_sock *usk)
+ {
+- atomic_long_inc(&usk->inflight);
++ usk->inflight++;
+ }
+
+ static void inc_inflight_move_tail(struct unix_sock *u)
+ {
+- atomic_long_inc(&u->inflight);
++ u->inflight++;
++
+ /* If this still might be part of a cycle, move it to the end
+ * of the list, so that it's checked even if it was already
+ * passed over
+@@ -234,20 +235,34 @@ void unix_gc(void)
+ * receive queues. Other, non candidate sockets _can_ be
+ * added to queue, so we must make sure only to touch
+ * candidates.
++ *
++ * Embryos, though never candidates themselves, affect which
++ * candidates are reachable by the garbage collector. Before
++ * being added to a listener's queue, an embryo may already
++ * receive data carrying SCM_RIGHTS, potentially making the
++ * passed socket a candidate that is not yet reachable by the
++ * collector. It becomes reachable once the embryo is
++ * enqueued. Therefore, we must ensure that no SCM-laden
++ * embryo appears in a (candidate) listener's queue between
++ * consecutive scan_children() calls.
+ */
+ list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
++ struct sock *sk = &u->sk;
+ long total_refs;
+- long inflight_refs;
+
+- total_refs = file_count(u->sk.sk_socket->file);
+- inflight_refs = atomic_long_read(&u->inflight);
++ total_refs = file_count(sk->sk_socket->file);
+
+- BUG_ON(inflight_refs < 1);
+- BUG_ON(total_refs < inflight_refs);
+- if (total_refs == inflight_refs) {
++ BUG_ON(!u->inflight);
++ BUG_ON(total_refs < u->inflight);
++ if (total_refs == u->inflight) {
+ list_move_tail(&u->link, &gc_candidates);
+ __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags);
+ __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
++
++ if (sk->sk_state == TCP_LISTEN) {
++ unix_state_lock(sk);
++ unix_state_unlock(sk);
++ }
+ }
+ }
+
+@@ -271,7 +286,7 @@ void unix_gc(void)
+ /* Move cursor to after the current position. */
+ list_move(&cursor, &u->link);
+
+- if (atomic_long_read(&u->inflight) > 0) {
++ if (u->inflight) {
+ list_move_tail(&u->link, ¬_cycle_list);
+ __clear_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
+ scan_children(&u->sk, inc_inflight_move_tail, NULL);
+diff --git a/net/unix/scm.c b/net/unix/scm.c
+index 822ce0d0d7915..e92f2fad64105 100644
+--- a/net/unix/scm.c
++++ b/net/unix/scm.c
+@@ -53,12 +53,13 @@ void unix_inflight(struct user_struct *user, struct file *fp)
+ if (s) {
+ struct unix_sock *u = unix_sk(s);
+
+- if (atomic_long_inc_return(&u->inflight) == 1) {
++ if (!u->inflight) {
+ BUG_ON(!list_empty(&u->link));
+ list_add_tail(&u->link, &gc_inflight_list);
+ } else {
+ BUG_ON(list_empty(&u->link));
+ }
++ u->inflight++;
+ /* Paired with READ_ONCE() in wait_for_unix_gc() */
+ WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + 1);
+ }
+@@ -75,10 +76,11 @@ void unix_notinflight(struct user_struct *user, struct file *fp)
+ if (s) {
+ struct unix_sock *u = unix_sk(s);
+
+- BUG_ON(!atomic_long_read(&u->inflight));
++ BUG_ON(!u->inflight);
+ BUG_ON(list_empty(&u->link));
+
+- if (atomic_long_dec_and_test(&u->inflight))
++ u->inflight--;
++ if (!u->inflight)
+ list_del_init(&u->link);
+ /* Paired with READ_ONCE() in wait_for_unix_gc() */
+ WRITE_ONCE(unix_tot_inflight, unix_tot_inflight - 1);
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index b78c0e095e221..7d1c0986f9bb3 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -1414,6 +1414,8 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname,
+ struct xsk_queue **q;
+ int entries;
+
++ if (optlen < sizeof(entries))
++ return -EINVAL;
+ if (copy_from_sockptr(&entries, optval, sizeof(entries)))
+ return -EFAULT;
+
+diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
+index a781e6311810b..e3e260fe002f7 100644
+--- a/tools/testing/selftests/kselftest.h
++++ b/tools/testing/selftests/kselftest.h
+@@ -50,6 +50,7 @@
+ #include <stdarg.h>
+ #include <string.h>
+ #include <stdio.h>
++#include <sys/utsname.h>
+ #endif
+
+ #ifndef ARRAY_SIZE
+@@ -78,6 +79,9 @@
+ #define KSFT_XPASS 3
+ #define KSFT_SKIP 4
+
++#ifndef __noreturn
++#define __noreturn __attribute__((__noreturn__))
++#endif
+ #define __printf(a, b) __attribute__((format(printf, a, b)))
+
+ /* counters */
+@@ -254,13 +258,13 @@ static inline __printf(1, 2) void ksft_test_result_error(const char *msg, ...)
+ va_end(args);
+ }
+
+-static inline int ksft_exit_pass(void)
++static inline __noreturn int ksft_exit_pass(void)
+ {
+ ksft_print_cnts();
+ exit(KSFT_PASS);
+ }
+
+-static inline int ksft_exit_fail(void)
++static inline __noreturn int ksft_exit_fail(void)
+ {
+ ksft_print_cnts();
+ exit(KSFT_FAIL);
+@@ -287,7 +291,7 @@ static inline int ksft_exit_fail(void)
+ ksft_cnt.ksft_xfail + \
+ ksft_cnt.ksft_xskip)
+
+-static inline __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...)
++static inline __noreturn __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...)
+ {
+ int saved_errno = errno;
+ va_list args;
+@@ -302,19 +306,19 @@ static inline __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...)
+ exit(KSFT_FAIL);
+ }
+
+-static inline int ksft_exit_xfail(void)
++static inline __noreturn int ksft_exit_xfail(void)
+ {
+ ksft_print_cnts();
+ exit(KSFT_XFAIL);
+ }
+
+-static inline int ksft_exit_xpass(void)
++static inline __noreturn int ksft_exit_xpass(void)
+ {
+ ksft_print_cnts();
+ exit(KSFT_XPASS);
+ }
+
+-static inline __printf(1, 2) int ksft_exit_skip(const char *msg, ...)
++static inline __noreturn __printf(1, 2) int ksft_exit_skip(const char *msg, ...)
+ {
+ int saved_errno = errno;
+ va_list args;
+@@ -343,4 +347,21 @@ static inline __printf(1, 2) int ksft_exit_skip(const char *msg, ...)
+ exit(KSFT_SKIP);
+ }
+
++static inline int ksft_min_kernel_version(unsigned int min_major,
++ unsigned int min_minor)
++{
++#ifdef NOLIBC
++ ksft_print_msg("NOLIBC: Can't check kernel version: Function not implemented\n");
++ return 0;
++#else
++ unsigned int major, minor;
++ struct utsname info;
++
++ if (uname(&info) || sscanf(info.release, "%u.%u.", &major, &minor) != 2)
++ ksft_exit_fail_msg("Can't parse kernel version\n");
++
++ return major > min_major || (major == min_major && minor >= min_minor);
++#endif
++}
++
+ #endif /* __KSELFTEST_H */
+diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c
+index d49dd3ffd0d96..c001dd79179d5 100644
+--- a/tools/testing/selftests/timers/posix_timers.c
++++ b/tools/testing/selftests/timers/posix_timers.c
+@@ -66,7 +66,7 @@ static int check_diff(struct timeval start, struct timeval end)
+ diff = end.tv_usec - start.tv_usec;
+ diff += (end.tv_sec - start.tv_sec) * USECS_PER_SEC;
+
+- if (abs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) {
++ if (llabs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) {
+ printf("Diff too high: %lld..", diff);
+ return -1;
+ }
+@@ -184,80 +184,71 @@ static int check_timer_create(int which)
+ return 0;
+ }
+
+-int remain;
+-__thread int got_signal;
++static pthread_t ctd_thread;
++static volatile int ctd_count, ctd_failed;
+
+-static void *distribution_thread(void *arg)
++static void ctd_sighandler(int sig)
+ {
+- while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
+- return NULL;
++ if (pthread_self() != ctd_thread)
++ ctd_failed = 1;
++ ctd_count--;
+ }
+
+-static void distribution_handler(int nr)
++static void *ctd_thread_func(void *arg)
+ {
+- if (!__atomic_exchange_n(&got_signal, 1, __ATOMIC_RELAXED))
+- __atomic_fetch_sub(&remain, 1, __ATOMIC_RELAXED);
+-}
+-
+-/*
+- * Test that all running threads _eventually_ receive CLOCK_PROCESS_CPUTIME_ID
+- * timer signals. This primarily tests that the kernel does not favour any one.
+- */
+-static int check_timer_distribution(void)
+-{
+- int err, i;
+- timer_t id;
+- const int nthreads = 10;
+- pthread_t threads[nthreads];
+ struct itimerspec val = {
+ .it_value.tv_sec = 0,
+ .it_value.tv_nsec = 1000 * 1000,
+ .it_interval.tv_sec = 0,
+ .it_interval.tv_nsec = 1000 * 1000,
+ };
++ timer_t id;
+
+- remain = nthreads + 1; /* worker threads + this thread */
+- signal(SIGALRM, distribution_handler);
+- err = timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id);
+- if (err < 0) {
+- ksft_perror("Can't create timer");
+- return -1;
+- }
+- err = timer_settime(id, 0, &val, NULL);
+- if (err < 0) {
+- ksft_perror("Can't set timer");
+- return -1;
+- }
++ /* 1/10 seconds to ensure the leader sleeps */
++ usleep(10000);
+
+- for (i = 0; i < nthreads; i++) {
+- err = pthread_create(&threads[i], NULL, distribution_thread,
+- NULL);
+- if (err) {
+- ksft_print_msg("Can't create thread: %s (%d)\n",
+- strerror(errno), errno);
+- return -1;
+- }
+- }
++ ctd_count = 100;
++ if (timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id))
++ return "Can't create timer\n";
++ if (timer_settime(id, 0, &val, NULL))
++ return "Can't set timer\n";
+
+- /* Wait for all threads to receive the signal. */
+- while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
++ while (ctd_count > 0 && !ctd_failed)
++ ;
+
+- for (i = 0; i < nthreads; i++) {
+- err = pthread_join(threads[i], NULL);
+- if (err) {
+- ksft_print_msg("Can't join thread: %s (%d)\n",
+- strerror(errno), errno);
+- return -1;
+- }
+- }
++ if (timer_delete(id))
++ return "Can't delete timer\n";
+
+- if (timer_delete(id)) {
+- ksft_perror("Can't delete timer");
+- return -1;
+- }
++ return NULL;
++}
++
++/*
++ * Test that only the running thread receives the timer signal.
++ */
++static int check_timer_distribution(void)
++{
++ const char *errmsg;
+
+- ksft_test_result_pass("check_timer_distribution\n");
++ signal(SIGALRM, ctd_sighandler);
++
++ errmsg = "Can't create thread\n";
++ if (pthread_create(&ctd_thread, NULL, ctd_thread_func, NULL))
++ goto err;
++
++ errmsg = "Can't join thread\n";
++ if (pthread_join(ctd_thread, (void **)&errmsg) || errmsg)
++ goto err;
++
++ if (!ctd_failed)
++ ksft_test_result_pass("check signal distribution\n");
++ else if (ksft_min_kernel_version(6, 3))
++ ksft_test_result_fail("check signal distribution\n");
++ else
++ ksft_test_result_skip("check signal distribution (old kernel)\n");
+ return 0;
++err:
++ ksft_print_msg("%s", errmsg);
++ return -1;
+ }
+
+ int main(int argc, char **argv)
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-18 5:31 Alice Ferrazzi
0 siblings, 0 replies; 25+ messages in thread
From: Alice Ferrazzi @ 2024-04-18 5:31 UTC (permalink / raw
To: gentoo-commits
commit: d3215cc0cf839cfd06cd6f2e3f6b02da939e86ab
Author: Alice Ferrazzi <alicef <AT> gentoo <DOT> org>
AuthorDate: Thu Apr 18 05:29:34 2024 +0000
Commit: Alice Ferrazzi <alicef <AT> gentoo <DOT> org>
CommitDate: Thu Apr 18 05:29:34 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=d3215cc0
Linux patch 6.8.1: fix patch filename
Signed-off-by: Alice Ferrazzi <alicef <AT> gentoo.org>
1001_linux-6.8.1.patch => 1000_linux-6.8.1.patch | 0
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/1001_linux-6.8.1.patch b/1000_linux-6.8.1.patch
similarity index 100%
rename from 1001_linux-6.8.1.patch
rename to 1000_linux-6.8.1.patch
^ permalink raw reply [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-18 6:31 Alice Ferrazzi
0 siblings, 0 replies; 25+ messages in thread
From: Alice Ferrazzi @ 2024-04-18 6:31 UTC (permalink / raw
To: gentoo-commits
commit: b3f5d49128d1354118e104aacca7c92658e5de94
Author: Alice Ferrazzi <alicef <AT> gentoo <DOT> org>
AuthorDate: Thu Apr 18 05:35:23 2024 +0000
Commit: Alice Ferrazzi <alicef <AT> gentoo <DOT> org>
CommitDate: Thu Apr 18 05:35:23 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=b3f5d491
Linux patch 6.8.7
Signed-off-by: Alice Ferrazzi <alicef <AT> gentoo.org>
0000_README | 4 +
1006_linux-6.8.7.patch | 6318 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 6322 insertions(+)
diff --git a/0000_README b/0000_README
index 98a6896a..1380bd5c 100644
--- a/0000_README
+++ b/0000_README
@@ -67,6 +67,10 @@ Patch: 1005_linux-6.8.6.patch
From: https://www.kernel.org
Desc: Linux 6.8.6
+Patch: 1006_linux-6.8.7.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.7
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1006_linux-6.8.7.patch b/1006_linux-6.8.7.patch
new file mode 100644
index 00000000..09ffaa63
--- /dev/null
+++ b/1006_linux-6.8.7.patch
@@ -0,0 +1,6318 @@
+diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst
+index 9edb2860a3e19..e0a1be97fa759 100644
+--- a/Documentation/admin-guide/hw-vuln/spectre.rst
++++ b/Documentation/admin-guide/hw-vuln/spectre.rst
+@@ -439,12 +439,12 @@ The possible values in this file are:
+ - System is protected by retpoline
+ * - BHI: BHI_DIS_S
+ - System is protected by BHI_DIS_S
+- * - BHI: SW loop; KVM SW loop
++ * - BHI: SW loop, KVM SW loop
+ - System is protected by software clearing sequence
+- * - BHI: Syscall hardening
+- - Syscalls are hardened against BHI
+- * - BHI: Syscall hardening; KVM: SW loop
+- - System is protected from userspace attacks by syscall hardening; KVM is protected by software clearing sequence
++ * - BHI: Vulnerable
++ - System is vulnerable to BHI
++ * - BHI: Vulnerable, KVM: SW loop
++ - System is vulnerable; KVM is protected by software clearing sequence
+
+ Full mitigation might require a microcode update from the CPU
+ vendor. When the necessary microcode is not available, the kernel will
+@@ -661,18 +661,14 @@ kernel command line.
+ spectre_bhi=
+
+ [X86] Control mitigation of Branch History Injection
+- (BHI) vulnerability. Syscalls are hardened against BHI
+- regardless of this setting. This setting affects the deployment
++ (BHI) vulnerability. This setting affects the deployment
+ of the HW BHI control and the SW BHB clearing sequence.
+
+ on
+- unconditionally enable.
++ (default) Enable the HW or SW mitigation as
++ needed.
+ off
+- unconditionally disable.
+- auto
+- enable if hardware mitigation
+- control(BHI_DIS_S) is available, otherwise
+- enable alternate mitigation in KVM.
++ Disable the mitigation.
+
+ For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index 95efaccca4539..31fdaf4fe9dd8 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -3419,6 +3419,7 @@
+ reg_file_data_sampling=off [X86]
+ retbleed=off [X86]
+ spec_store_bypass_disable=off [X86,PPC]
++ spectre_bhi=off [X86]
+ spectre_v2_user=off [X86]
+ srbds=off [X86,INTEL]
+ ssbd=force-off [ARM64]
+@@ -6032,16 +6033,13 @@
+ See Documentation/admin-guide/laptops/sonypi.rst
+
+ spectre_bhi= [X86] Control mitigation of Branch History Injection
+- (BHI) vulnerability. Syscalls are hardened against BHI
+- reglardless of this setting. This setting affects the
++ (BHI) vulnerability. This setting affects the
+ deployment of the HW BHI control and the SW BHB
+ clearing sequence.
+
+- on - unconditionally enable.
+- off - unconditionally disable.
+- auto - (default) enable hardware mitigation
+- (BHI_DIS_S) if available, otherwise enable
+- alternate mitigation in KVM.
++ on - (default) Enable the HW or SW mitigation
++ as needed.
++ off - Disable the mitigation.
+
+ spectre_v2= [X86] Control mitigation of Spectre variant 2
+ (indirect branch speculation) vulnerability.
+diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml
+index c0d6a4fdff97e..e6dc5494baee2 100644
+--- a/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml
++++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml
+@@ -53,6 +53,15 @@ patternProperties:
+ compatible:
+ const: qcom,sm8150-dpu
+
++ "^displayport-controller@[0-9a-f]+$":
++ type: object
++ additionalProperties: true
++
++ properties:
++ compatible:
++ contains:
++ const: qcom,sm8150-dp
++
+ "^dsi@[0-9a-f]+$":
+ type: object
+ additionalProperties: true
+diff --git a/Makefile b/Makefile
+index c426d47f4b7bf..e6c0a00722eae 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 6
++SUBLEVEL = 7
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts
+index ba7231b364bb8..7bab113ca6da7 100644
+--- a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts
++++ b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts
+@@ -210,6 +210,7 @@ ov2680_to_mipi: endpoint {
+ remote-endpoint = <&mipi_from_sensor>;
+ clock-lanes = <0>;
+ data-lanes = <1>;
++ link-frequencies = /bits/ 64 <330000000>;
+ };
+ };
+ };
+diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
+index 31755a378c736..ff2a4a4d82204 100644
+--- a/arch/arm/mach-omap2/board-n8x0.c
++++ b/arch/arm/mach-omap2/board-n8x0.c
+@@ -79,10 +79,8 @@ static struct musb_hdrc_platform_data tusb_data = {
+ static struct gpiod_lookup_table tusb_gpio_table = {
+ .dev_id = "musb-tusb",
+ .table = {
+- GPIO_LOOKUP("gpio-0-15", 0, "enable",
+- GPIO_ACTIVE_HIGH),
+- GPIO_LOOKUP("gpio-48-63", 10, "int",
+- GPIO_ACTIVE_HIGH),
++ GPIO_LOOKUP("gpio-0-31", 0, "enable", GPIO_ACTIVE_HIGH),
++ GPIO_LOOKUP("gpio-32-63", 26, "int", GPIO_ACTIVE_HIGH),
+ { }
+ },
+ };
+@@ -140,12 +138,11 @@ static int slot1_cover_open;
+ static int slot2_cover_open;
+ static struct device *mmc_device;
+
+-static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = {
++static struct gpiod_lookup_table nokia800_mmc_gpio_table = {
+ .dev_id = "mmci-omap.0",
+ .table = {
+ /* Slot switch, GPIO 96 */
+- GPIO_LOOKUP("gpio-80-111", 16,
+- "switch", GPIO_ACTIVE_HIGH),
++ GPIO_LOOKUP("gpio-96-127", 0, "switch", GPIO_ACTIVE_HIGH),
+ { }
+ },
+ };
+@@ -153,12 +150,12 @@ static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = {
+ static struct gpiod_lookup_table nokia810_mmc_gpio_table = {
+ .dev_id = "mmci-omap.0",
+ .table = {
++ /* Slot switch, GPIO 96 */
++ GPIO_LOOKUP("gpio-96-127", 0, "switch", GPIO_ACTIVE_HIGH),
+ /* Slot index 1, VSD power, GPIO 23 */
+- GPIO_LOOKUP_IDX("gpio-16-31", 7,
+- "vsd", 1, GPIO_ACTIVE_HIGH),
++ GPIO_LOOKUP_IDX("gpio-0-31", 23, "vsd", 1, GPIO_ACTIVE_HIGH),
+ /* Slot index 1, VIO power, GPIO 9 */
+- GPIO_LOOKUP_IDX("gpio-0-15", 9,
+- "vio", 1, GPIO_ACTIVE_HIGH),
++ GPIO_LOOKUP_IDX("gpio-0-31", 9, "vio", 1, GPIO_ACTIVE_HIGH),
+ { }
+ },
+ };
+@@ -415,8 +412,6 @@ static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC];
+
+ static void __init n8x0_mmc_init(void)
+ {
+- gpiod_add_lookup_table(&nokia8xx_mmc_gpio_table);
+-
+ if (board_is_n810()) {
+ mmc1_data.slots[0].name = "external";
+
+@@ -429,6 +424,8 @@ static void __init n8x0_mmc_init(void)
+ mmc1_data.slots[1].name = "internal";
+ mmc1_data.slots[1].ban_openended = 1;
+ gpiod_add_lookup_table(&nokia810_mmc_gpio_table);
++ } else {
++ gpiod_add_lookup_table(&nokia800_mmc_gpio_table);
+ }
+
+ mmc1_data.nr_slots = 2;
+diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
+index 3c42240e78e24..4aaf5a0c1ed8a 100644
+--- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
+@@ -41,7 +41,7 @@ usbotg1: usb@5b0d0000 {
+ interrupts = <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,usbphy = <&usbphy1>;
+ fsl,usbmisc = <&usbmisc1 0>;
+- clocks = <&usb2_lpcg 0>;
++ clocks = <&usb2_lpcg IMX_LPCG_CLK_6>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>;
+ rx-burst-size-dword = <0x10>;
+@@ -58,7 +58,7 @@ usbmisc1: usbmisc@5b0d0200 {
+ usbphy1: usbphy@5b100000 {
+ compatible = "fsl,imx7ulp-usbphy";
+ reg = <0x5b100000 0x1000>;
+- clocks = <&usb2_lpcg 1>;
++ clocks = <&usb2_lpcg IMX_LPCG_CLK_7>;
+ power-domains = <&pd IMX_SC_R_USB_0_PHY>;
+ status = "disabled";
+ };
+@@ -67,8 +67,8 @@ usdhc1: mmc@5b010000 {
+ interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x5b010000 0x10000>;
+ clocks = <&sdhc0_lpcg IMX_LPCG_CLK_4>,
+- <&sdhc0_lpcg IMX_LPCG_CLK_0>,
+- <&sdhc0_lpcg IMX_LPCG_CLK_5>;
++ <&sdhc0_lpcg IMX_LPCG_CLK_5>,
++ <&sdhc0_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "ahb", "per";
+ power-domains = <&pd IMX_SC_R_SDHC_0>;
+ status = "disabled";
+@@ -78,8 +78,8 @@ usdhc2: mmc@5b020000 {
+ interrupts = <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x5b020000 0x10000>;
+ clocks = <&sdhc1_lpcg IMX_LPCG_CLK_4>,
+- <&sdhc1_lpcg IMX_LPCG_CLK_0>,
+- <&sdhc1_lpcg IMX_LPCG_CLK_5>;
++ <&sdhc1_lpcg IMX_LPCG_CLK_5>,
++ <&sdhc1_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "ahb", "per";
+ power-domains = <&pd IMX_SC_R_SDHC_1>;
+ fsl,tuning-start-tap = <20>;
+@@ -91,8 +91,8 @@ usdhc3: mmc@5b030000 {
+ interrupts = <GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x5b030000 0x10000>;
+ clocks = <&sdhc2_lpcg IMX_LPCG_CLK_4>,
+- <&sdhc2_lpcg IMX_LPCG_CLK_0>,
+- <&sdhc2_lpcg IMX_LPCG_CLK_5>;
++ <&sdhc2_lpcg IMX_LPCG_CLK_5>,
++ <&sdhc2_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "ahb", "per";
+ power-domains = <&pd IMX_SC_R_SDHC_2>;
+ status = "disabled";
+diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
+index b0bb77150adcc..67b3c7573233a 100644
+--- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
+@@ -27,8 +27,8 @@ lpspi0: spi@5a000000 {
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&spi0_lpcg 0>,
+- <&spi0_lpcg 1>;
++ clocks = <&spi0_lpcg IMX_LPCG_CLK_0>,
++ <&spi0_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_SPI_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <60000000>;
+@@ -43,8 +43,8 @@ lpspi1: spi@5a010000 {
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&spi1_lpcg 0>,
+- <&spi1_lpcg 1>;
++ clocks = <&spi1_lpcg IMX_LPCG_CLK_0>,
++ <&spi1_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_SPI_1 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <60000000>;
+@@ -59,8 +59,8 @@ lpspi2: spi@5a020000 {
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&spi2_lpcg 0>,
+- <&spi2_lpcg 1>;
++ clocks = <&spi2_lpcg IMX_LPCG_CLK_0>,
++ <&spi2_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_SPI_2 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <60000000>;
+@@ -75,8 +75,8 @@ lpspi3: spi@5a030000 {
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&spi3_lpcg 0>,
+- <&spi3_lpcg 1>;
++ clocks = <&spi3_lpcg IMX_LPCG_CLK_0>,
++ <&spi3_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_SPI_3 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <60000000>;
+@@ -144,8 +144,8 @@ adma_pwm: pwm@5a190000 {
+ compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm";
+ reg = <0x5a190000 0x1000>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+- clocks = <&adma_pwm_lpcg 1>,
+- <&adma_pwm_lpcg 0>;
++ clocks = <&adma_pwm_lpcg IMX_LPCG_CLK_4>,
++ <&adma_pwm_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "per";
+ assigned-clocks = <&clk IMX_SC_R_LCD_0_PWM_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+@@ -377,8 +377,8 @@ adc0: adc@5a880000 {
+ reg = <0x5a880000 0x10000>;
+ interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&adc0_lpcg 0>,
+- <&adc0_lpcg 1>;
++ clocks = <&adc0_lpcg IMX_LPCG_CLK_0>,
++ <&adc0_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_ADC_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+@@ -392,8 +392,8 @@ adc1: adc@5a890000 {
+ reg = <0x5a890000 0x10000>;
+ interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&adc1_lpcg 0>,
+- <&adc1_lpcg 1>;
++ clocks = <&adc1_lpcg IMX_LPCG_CLK_0>,
++ <&adc1_lpcg IMX_LPCG_CLK_4>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_ADC_1 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+@@ -406,8 +406,8 @@ flexcan1: can@5a8d0000 {
+ reg = <0x5a8d0000 0x10000>;
+ interrupts = <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+- clocks = <&can0_lpcg 1>,
+- <&can0_lpcg 0>;
++ clocks = <&can0_lpcg IMX_LPCG_CLK_4>,
++ <&can0_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "per";
+ assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <40000000>;
+@@ -427,8 +427,8 @@ flexcan2: can@5a8e0000 {
+ * CAN1 shares CAN0's clock and to enable CAN0's clock it
+ * has to be powered on.
+ */
+- clocks = <&can0_lpcg 1>,
+- <&can0_lpcg 0>;
++ clocks = <&can0_lpcg IMX_LPCG_CLK_4>,
++ <&can0_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "per";
+ assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <40000000>;
+@@ -448,8 +448,8 @@ flexcan3: can@5a8f0000 {
+ * CAN2 shares CAN0's clock and to enable CAN0's clock it
+ * has to be powered on.
+ */
+- clocks = <&can0_lpcg 1>,
+- <&can0_lpcg 0>;
++ clocks = <&can0_lpcg IMX_LPCG_CLK_4>,
++ <&can0_lpcg IMX_LPCG_CLK_0>;
+ clock-names = "ipg", "per";
+ assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <40000000>;
+diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
+index 7e510b21bbac5..764c1a08e3b11 100644
+--- a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
+@@ -25,8 +25,8 @@ lsio_pwm0: pwm@5d000000 {
+ compatible = "fsl,imx27-pwm";
+ reg = <0x5d000000 0x10000>;
+ clock-names = "ipg", "per";
+- clocks = <&pwm0_lpcg 4>,
+- <&pwm0_lpcg 1>;
++ clocks = <&pwm0_lpcg IMX_LPCG_CLK_6>,
++ <&pwm0_lpcg IMX_LPCG_CLK_1>;
+ assigned-clocks = <&clk IMX_SC_R_PWM_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <3>;
+@@ -38,8 +38,8 @@ lsio_pwm1: pwm@5d010000 {
+ compatible = "fsl,imx27-pwm";
+ reg = <0x5d010000 0x10000>;
+ clock-names = "ipg", "per";
+- clocks = <&pwm1_lpcg 4>,
+- <&pwm1_lpcg 1>;
++ clocks = <&pwm1_lpcg IMX_LPCG_CLK_6>,
++ <&pwm1_lpcg IMX_LPCG_CLK_1>;
+ assigned-clocks = <&clk IMX_SC_R_PWM_1 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <3>;
+@@ -51,8 +51,8 @@ lsio_pwm2: pwm@5d020000 {
+ compatible = "fsl,imx27-pwm";
+ reg = <0x5d020000 0x10000>;
+ clock-names = "ipg", "per";
+- clocks = <&pwm2_lpcg 4>,
+- <&pwm2_lpcg 1>;
++ clocks = <&pwm2_lpcg IMX_LPCG_CLK_6>,
++ <&pwm2_lpcg IMX_LPCG_CLK_1>;
+ assigned-clocks = <&clk IMX_SC_R_PWM_2 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <3>;
+@@ -64,8 +64,8 @@ lsio_pwm3: pwm@5d030000 {
+ compatible = "fsl,imx27-pwm";
+ reg = <0x5d030000 0x10000>;
+ clock-names = "ipg", "per";
+- clocks = <&pwm3_lpcg 4>,
+- <&pwm3_lpcg 1>;
++ clocks = <&pwm3_lpcg IMX_LPCG_CLK_6>,
++ <&pwm3_lpcg IMX_LPCG_CLK_1>;
+ assigned-clocks = <&clk IMX_SC_R_PWM_3 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ #pwm-cells = <3>;
+diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi
+index 41c79d2ebdd62..f24b14744799e 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi
+@@ -14,6 +14,7 @@ connector {
+ pinctrl-0 = <&pinctrl_usbcon1>;
+ type = "micro";
+ label = "otg";
++ vbus-supply = <®_usb1_vbus>;
+ id-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+
+ port {
+@@ -183,7 +184,6 @@ &usb3_0 {
+ };
+
+ &usb3_phy0 {
+- vbus-supply = <®_usb1_vbus>;
+ status = "okay";
+ };
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi
+index d5c400b355af5..f5491a608b2f3 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi
+@@ -14,6 +14,7 @@ connector {
+ pinctrl-0 = <&pinctrl_usbcon1>;
+ type = "micro";
+ label = "otg";
++ vbus-supply = <®_usb1_vbus>;
+ id-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+
+ port {
+@@ -202,7 +203,6 @@ &usb3_0 {
+ };
+
+ &usb3_phy0 {
+- vbus-supply = <®_usb1_vbus>;
+ status = "okay";
+ };
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
+index cafc1383115ab..cd96f9f75da16 100644
+--- a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi
+@@ -127,15 +127,15 @@ &flexcan1 {
+ };
+
+ &flexcan2 {
+- clocks = <&can1_lpcg 1>,
+- <&can1_lpcg 0>;
++ clocks = <&can1_lpcg IMX_LPCG_CLK_4>,
++ <&can1_lpcg IMX_LPCG_CLK_0>;
+ assigned-clocks = <&clk IMX_SC_R_CAN_1 IMX_SC_PM_CLK_PER>;
+ fsl,clk-source = /bits/ 8 <1>;
+ };
+
+ &flexcan3 {
+- clocks = <&can2_lpcg 1>,
+- <&can2_lpcg 0>;
++ clocks = <&can2_lpcg IMX_LPCG_CLK_4>,
++ <&can2_lpcg IMX_LPCG_CLK_0>;
+ assigned-clocks = <&clk IMX_SC_R_CAN_2 IMX_SC_PM_CLK_PER>;
+ fsl,clk-source = /bits/ 8 <1>;
+ };
+diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
+index 1deb5d789c2e2..bfeb54f3a971f 100644
+--- a/arch/arm64/include/asm/tlbflush.h
++++ b/arch/arm64/include/asm/tlbflush.h
+@@ -161,12 +161,18 @@ static inline unsigned long get_trans_granule(void)
+ #define MAX_TLBI_RANGE_PAGES __TLBI_RANGE_PAGES(31, 3)
+
+ /*
+- * Generate 'num' values from -1 to 30 with -1 rejected by the
+- * __flush_tlb_range() loop below.
++ * Generate 'num' values from -1 to 31 with -1 rejected by the
++ * __flush_tlb_range() loop below. Its return value is only
++ * significant for a maximum of MAX_TLBI_RANGE_PAGES pages. If
++ * 'pages' is more than that, you must iterate over the overall
++ * range.
+ */
+-#define TLBI_RANGE_MASK GENMASK_ULL(4, 0)
+-#define __TLBI_RANGE_NUM(pages, scale) \
+- ((((pages) >> (5 * (scale) + 1)) & TLBI_RANGE_MASK) - 1)
++#define __TLBI_RANGE_NUM(pages, scale) \
++ ({ \
++ int __pages = min((pages), \
++ __TLBI_RANGE_PAGES(31, (scale))); \
++ (__pages >> (5 * (scale) + 1)) - 1; \
++ })
+
+ /*
+ * TLB Invalidation
+@@ -379,10 +385,6 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
+ * 3. If there is 1 page remaining, flush it through non-range operations. Range
+ * operations can only span an even number of pages. We save this for last to
+ * ensure 64KB start alignment is maintained for the LPA2 case.
+- *
+- * Note that certain ranges can be represented by either num = 31 and
+- * scale or num = 0 and scale + 1. The loop below favours the latter
+- * since num is limited to 30 by the __TLBI_RANGE_NUM() macro.
+ */
+ #define __flush_tlb_range_op(op, start, pages, stride, \
+ asid, tlb_level, tlbi_user, lpa2) \
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 890ba8e48bc39..b07f8b007ed9b 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -2612,31 +2612,16 @@ config MITIGATION_RFDS
+ stored in floating point, vector and integer registers.
+ See also <file:Documentation/admin-guide/hw-vuln/reg-file-data-sampling.rst>
+
+-choice
+- prompt "Clear branch history"
++config MITIGATION_SPECTRE_BHI
++ bool "Mitigate Spectre-BHB (Branch History Injection)"
+ depends on CPU_SUP_INTEL
+- default SPECTRE_BHI_ON
++ default y
+ help
+ Enable BHI mitigations. BHI attacks are a form of Spectre V2 attacks
+ where the branch history buffer is poisoned to speculatively steer
+ indirect branches.
+ See <file:Documentation/admin-guide/hw-vuln/spectre.rst>
+
+-config SPECTRE_BHI_ON
+- bool "on"
+- help
+- Equivalent to setting spectre_bhi=on command line parameter.
+-config SPECTRE_BHI_OFF
+- bool "off"
+- help
+- Equivalent to setting spectre_bhi=off command line parameter.
+-config SPECTRE_BHI_AUTO
+- bool "auto"
+- help
+- Equivalent to setting spectre_bhi=auto command line parameter.
+-
+-endchoice
+-
+ endif
+
+ config ARCH_HAS_ADD_PAGES
+diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
+index 09050641ce5d3..5b0dd07b1ef19 100644
+--- a/arch/x86/events/core.c
++++ b/arch/x86/events/core.c
+@@ -1644,6 +1644,7 @@ static void x86_pmu_del(struct perf_event *event, int flags)
+ while (++i < cpuc->n_events) {
+ cpuc->event_list[i-1] = cpuc->event_list[i];
+ cpuc->event_constraint[i-1] = cpuc->event_constraint[i];
++ cpuc->assign[i-1] = cpuc->assign[i];
+ }
+ cpuc->event_constraint[i-1] = NULL;
+ --cpuc->n_events;
+diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
+index 9d159b771dc81..dddd3fc195efa 100644
+--- a/arch/x86/include/asm/apic.h
++++ b/arch/x86/include/asm/apic.h
+@@ -13,6 +13,7 @@
+ #include <asm/mpspec.h>
+ #include <asm/msr.h>
+ #include <asm/hardirq.h>
++#include <asm/io.h>
+
+ #define ARCH_APICTIMER_STOPS_ON_C3 1
+
+@@ -96,7 +97,7 @@ static inline void native_apic_mem_write(u32 reg, u32 v)
+
+ static inline u32 native_apic_mem_read(u32 reg)
+ {
+- return *((volatile u32 *)(APIC_BASE + reg));
++ return readl((void __iomem *)(APIC_BASE + reg));
+ }
+
+ static inline void native_apic_mem_eoi(void)
+diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
+index 4667bc4b00ab8..75bd5ac7ac6a9 100644
+--- a/arch/x86/kernel/apic/apic.c
++++ b/arch/x86/kernel/apic/apic.c
+@@ -1724,11 +1724,11 @@ static int x2apic_state;
+
+ static bool x2apic_hw_locked(void)
+ {
+- u64 ia32_cap;
++ u64 x86_arch_cap_msr;
+ u64 msr;
+
+- ia32_cap = x86_read_arch_cap_msr();
+- if (ia32_cap & ARCH_CAP_XAPIC_DISABLE) {
++ x86_arch_cap_msr = x86_read_arch_cap_msr();
++ if (x86_arch_cap_msr & ARCH_CAP_XAPIC_DISABLE) {
+ rdmsrl(MSR_IA32_XAPIC_DISABLE_STATUS, msr);
+ return (msr & LEGACY_XAPIC_DISABLED);
+ }
+diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
+index 0d7238d88b38a..cbc8c88144e47 100644
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -61,6 +61,8 @@ EXPORT_SYMBOL_GPL(x86_spec_ctrl_current);
+ u64 x86_pred_cmd __ro_after_init = PRED_CMD_IBPB;
+ EXPORT_SYMBOL_GPL(x86_pred_cmd);
+
++static u64 __ro_after_init x86_arch_cap_msr;
++
+ static DEFINE_MUTEX(spec_ctrl_mutex);
+
+ void (*x86_return_thunk)(void) __ro_after_init = __x86_return_thunk;
+@@ -144,6 +146,8 @@ void __init cpu_select_mitigations(void)
+ x86_spec_ctrl_base &= ~SPEC_CTRL_MITIGATIONS_MASK;
+ }
+
++ x86_arch_cap_msr = x86_read_arch_cap_msr();
++
+ /* Select the proper CPU mitigations before patching alternatives: */
+ spectre_v1_select_mitigation();
+ spectre_v2_select_mitigation();
+@@ -301,8 +305,6 @@ static const char * const taa_strings[] = {
+
+ static void __init taa_select_mitigation(void)
+ {
+- u64 ia32_cap;
+-
+ if (!boot_cpu_has_bug(X86_BUG_TAA)) {
+ taa_mitigation = TAA_MITIGATION_OFF;
+ return;
+@@ -341,9 +343,8 @@ static void __init taa_select_mitigation(void)
+ * On MDS_NO=1 CPUs if ARCH_CAP_TSX_CTRL_MSR is not set, microcode
+ * update is required.
+ */
+- ia32_cap = x86_read_arch_cap_msr();
+- if ( (ia32_cap & ARCH_CAP_MDS_NO) &&
+- !(ia32_cap & ARCH_CAP_TSX_CTRL_MSR))
++ if ( (x86_arch_cap_msr & ARCH_CAP_MDS_NO) &&
++ !(x86_arch_cap_msr & ARCH_CAP_TSX_CTRL_MSR))
+ taa_mitigation = TAA_MITIGATION_UCODE_NEEDED;
+
+ /*
+@@ -401,8 +402,6 @@ static const char * const mmio_strings[] = {
+
+ static void __init mmio_select_mitigation(void)
+ {
+- u64 ia32_cap;
+-
+ if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) ||
+ boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN) ||
+ cpu_mitigations_off()) {
+@@ -413,8 +412,6 @@ static void __init mmio_select_mitigation(void)
+ if (mmio_mitigation == MMIO_MITIGATION_OFF)
+ return;
+
+- ia32_cap = x86_read_arch_cap_msr();
+-
+ /*
+ * Enable CPU buffer clear mitigation for host and VMM, if also affected
+ * by MDS or TAA. Otherwise, enable mitigation for VMM only.
+@@ -437,7 +434,7 @@ static void __init mmio_select_mitigation(void)
+ * be propagated to uncore buffers, clearing the Fill buffers on idle
+ * is required irrespective of SMT state.
+ */
+- if (!(ia32_cap & ARCH_CAP_FBSDP_NO))
++ if (!(x86_arch_cap_msr & ARCH_CAP_FBSDP_NO))
+ static_branch_enable(&mds_idle_clear);
+
+ /*
+@@ -447,10 +444,10 @@ static void __init mmio_select_mitigation(void)
+ * FB_CLEAR or by the presence of both MD_CLEAR and L1D_FLUSH on MDS
+ * affected systems.
+ */
+- if ((ia32_cap & ARCH_CAP_FB_CLEAR) ||
++ if ((x86_arch_cap_msr & ARCH_CAP_FB_CLEAR) ||
+ (boot_cpu_has(X86_FEATURE_MD_CLEAR) &&
+ boot_cpu_has(X86_FEATURE_FLUSH_L1D) &&
+- !(ia32_cap & ARCH_CAP_MDS_NO)))
++ !(x86_arch_cap_msr & ARCH_CAP_MDS_NO)))
+ mmio_mitigation = MMIO_MITIGATION_VERW;
+ else
+ mmio_mitigation = MMIO_MITIGATION_UCODE_NEEDED;
+@@ -508,7 +505,7 @@ static void __init rfds_select_mitigation(void)
+ if (rfds_mitigation == RFDS_MITIGATION_OFF)
+ return;
+
+- if (x86_read_arch_cap_msr() & ARCH_CAP_RFDS_CLEAR)
++ if (x86_arch_cap_msr & ARCH_CAP_RFDS_CLEAR)
+ setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF);
+ else
+ rfds_mitigation = RFDS_MITIGATION_UCODE_NEEDED;
+@@ -659,8 +656,6 @@ void update_srbds_msr(void)
+
+ static void __init srbds_select_mitigation(void)
+ {
+- u64 ia32_cap;
+-
+ if (!boot_cpu_has_bug(X86_BUG_SRBDS))
+ return;
+
+@@ -669,8 +664,7 @@ static void __init srbds_select_mitigation(void)
+ * are only exposed to SRBDS when TSX is enabled or when CPU is affected
+ * by Processor MMIO Stale Data vulnerability.
+ */
+- ia32_cap = x86_read_arch_cap_msr();
+- if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) &&
++ if ((x86_arch_cap_msr & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) &&
+ !boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA))
+ srbds_mitigation = SRBDS_MITIGATION_TSX_OFF;
+ else if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
+@@ -813,7 +807,7 @@ static void __init gds_select_mitigation(void)
+ /* Will verify below that mitigation _can_ be disabled */
+
+ /* No microcode */
+- if (!(x86_read_arch_cap_msr() & ARCH_CAP_GDS_CTRL)) {
++ if (!(x86_arch_cap_msr & ARCH_CAP_GDS_CTRL)) {
+ if (gds_mitigation == GDS_MITIGATION_FORCE) {
+ /*
+ * This only needs to be done on the boot CPU so do it
+@@ -1543,20 +1537,25 @@ static enum spectre_v2_mitigation __init spectre_v2_select_retpoline(void)
+ return SPECTRE_V2_RETPOLINE;
+ }
+
++static bool __ro_after_init rrsba_disabled;
++
+ /* Disable in-kernel use of non-RSB RET predictors */
+ static void __init spec_ctrl_disable_kernel_rrsba(void)
+ {
+- u64 ia32_cap;
++ if (rrsba_disabled)
++ return;
+
+- if (!boot_cpu_has(X86_FEATURE_RRSBA_CTRL))
++ if (!(x86_arch_cap_msr & ARCH_CAP_RRSBA)) {
++ rrsba_disabled = true;
+ return;
++ }
+
+- ia32_cap = x86_read_arch_cap_msr();
++ if (!boot_cpu_has(X86_FEATURE_RRSBA_CTRL))
++ return;
+
+- if (ia32_cap & ARCH_CAP_RRSBA) {
+- x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S;
+- update_spec_ctrl(x86_spec_ctrl_base);
+- }
++ x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S;
++ update_spec_ctrl(x86_spec_ctrl_base);
++ rrsba_disabled = true;
+ }
+
+ static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_mitigation mode)
+@@ -1625,13 +1624,10 @@ static bool __init spec_ctrl_bhi_dis(void)
+ enum bhi_mitigations {
+ BHI_MITIGATION_OFF,
+ BHI_MITIGATION_ON,
+- BHI_MITIGATION_AUTO,
+ };
+
+ static enum bhi_mitigations bhi_mitigation __ro_after_init =
+- IS_ENABLED(CONFIG_SPECTRE_BHI_ON) ? BHI_MITIGATION_ON :
+- IS_ENABLED(CONFIG_SPECTRE_BHI_OFF) ? BHI_MITIGATION_OFF :
+- BHI_MITIGATION_AUTO;
++ IS_ENABLED(CONFIG_MITIGATION_SPECTRE_BHI) ? BHI_MITIGATION_ON : BHI_MITIGATION_OFF;
+
+ static int __init spectre_bhi_parse_cmdline(char *str)
+ {
+@@ -1642,8 +1638,6 @@ static int __init spectre_bhi_parse_cmdline(char *str)
+ bhi_mitigation = BHI_MITIGATION_OFF;
+ else if (!strcmp(str, "on"))
+ bhi_mitigation = BHI_MITIGATION_ON;
+- else if (!strcmp(str, "auto"))
+- bhi_mitigation = BHI_MITIGATION_AUTO;
+ else
+ pr_err("Ignoring unknown spectre_bhi option (%s)", str);
+
+@@ -1657,9 +1651,11 @@ static void __init bhi_select_mitigation(void)
+ return;
+
+ /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */
+- if (cpu_feature_enabled(X86_FEATURE_RETPOLINE) &&
+- !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA))
+- return;
++ if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) {
++ spec_ctrl_disable_kernel_rrsba();
++ if (rrsba_disabled)
++ return;
++ }
+
+ if (spec_ctrl_bhi_dis())
+ return;
+@@ -1671,9 +1667,6 @@ static void __init bhi_select_mitigation(void)
+ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT);
+ pr_info("Spectre BHI mitigation: SW BHB clearing on vm exit\n");
+
+- if (bhi_mitigation == BHI_MITIGATION_AUTO)
+- return;
+-
+ /* Mitigate syscalls when the mitigation is forced =on */
+ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP);
+ pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n");
+@@ -1907,8 +1900,6 @@ static void update_indir_branch_cond(void)
+ /* Update the static key controlling the MDS CPU buffer clear in idle */
+ static void update_mds_branch_idle(void)
+ {
+- u64 ia32_cap = x86_read_arch_cap_msr();
+-
+ /*
+ * Enable the idle clearing if SMT is active on CPUs which are
+ * affected only by MSBDS and not any other MDS variant.
+@@ -1923,7 +1914,7 @@ static void update_mds_branch_idle(void)
+ if (sched_smt_active()) {
+ static_branch_enable(&mds_idle_clear);
+ } else if (mmio_mitigation == MMIO_MITIGATION_OFF ||
+- (ia32_cap & ARCH_CAP_FBSDP_NO)) {
++ (x86_arch_cap_msr & ARCH_CAP_FBSDP_NO)) {
+ static_branch_disable(&mds_idle_clear);
+ }
+ }
+@@ -2808,7 +2799,7 @@ static char *pbrsb_eibrs_state(void)
+ }
+ }
+
+-static const char * const spectre_bhi_state(void)
++static const char *spectre_bhi_state(void)
+ {
+ if (!boot_cpu_has_bug(X86_BUG_BHI))
+ return "; BHI: Not affected";
+@@ -2816,13 +2807,12 @@ static const char * const spectre_bhi_state(void)
+ return "; BHI: BHI_DIS_S";
+ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
+ return "; BHI: SW loop, KVM: SW loop";
+- else if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
+- !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA))
++ else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && rrsba_disabled)
+ return "; BHI: Retpoline";
+- else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
+- return "; BHI: Syscall hardening, KVM: SW loop";
++ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
++ return "; BHI: Vulnerable, KVM: SW loop";
+
+- return "; BHI: Vulnerable (Syscall hardening enabled)";
++ return "; BHI: Vulnerable";
+ }
+
+ static ssize_t spectre_v2_show_state(char *buf)
+diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
+index 785fedddb5f09..46603c6e400aa 100644
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -1327,25 +1327,25 @@ static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long whi
+
+ u64 x86_read_arch_cap_msr(void)
+ {
+- u64 ia32_cap = 0;
++ u64 x86_arch_cap_msr = 0;
+
+ if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES))
+- rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap);
++ rdmsrl(MSR_IA32_ARCH_CAPABILITIES, x86_arch_cap_msr);
+
+- return ia32_cap;
++ return x86_arch_cap_msr;
+ }
+
+-static bool arch_cap_mmio_immune(u64 ia32_cap)
++static bool arch_cap_mmio_immune(u64 x86_arch_cap_msr)
+ {
+- return (ia32_cap & ARCH_CAP_FBSDP_NO &&
+- ia32_cap & ARCH_CAP_PSDP_NO &&
+- ia32_cap & ARCH_CAP_SBDR_SSDP_NO);
++ return (x86_arch_cap_msr & ARCH_CAP_FBSDP_NO &&
++ x86_arch_cap_msr & ARCH_CAP_PSDP_NO &&
++ x86_arch_cap_msr & ARCH_CAP_SBDR_SSDP_NO);
+ }
+
+-static bool __init vulnerable_to_rfds(u64 ia32_cap)
++static bool __init vulnerable_to_rfds(u64 x86_arch_cap_msr)
+ {
+ /* The "immunity" bit trumps everything else: */
+- if (ia32_cap & ARCH_CAP_RFDS_NO)
++ if (x86_arch_cap_msr & ARCH_CAP_RFDS_NO)
+ return false;
+
+ /*
+@@ -1353,7 +1353,7 @@ static bool __init vulnerable_to_rfds(u64 ia32_cap)
+ * indicate that mitigation is needed because guest is running on a
+ * vulnerable hardware or may migrate to such hardware:
+ */
+- if (ia32_cap & ARCH_CAP_RFDS_CLEAR)
++ if (x86_arch_cap_msr & ARCH_CAP_RFDS_CLEAR)
+ return true;
+
+ /* Only consult the blacklist when there is no enumeration: */
+@@ -1362,11 +1362,11 @@ static bool __init vulnerable_to_rfds(u64 ia32_cap)
+
+ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ {
+- u64 ia32_cap = x86_read_arch_cap_msr();
++ u64 x86_arch_cap_msr = x86_read_arch_cap_msr();
+
+ /* Set ITLB_MULTIHIT bug if cpu is not in the whitelist and not mitigated */
+ if (!cpu_matches(cpu_vuln_whitelist, NO_ITLB_MULTIHIT) &&
+- !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO))
++ !(x86_arch_cap_msr & ARCH_CAP_PSCHANGE_MC_NO))
+ setup_force_cpu_bug(X86_BUG_ITLB_MULTIHIT);
+
+ if (cpu_matches(cpu_vuln_whitelist, NO_SPECULATION))
+@@ -1378,7 +1378,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
+
+ if (!cpu_matches(cpu_vuln_whitelist, NO_SSB) &&
+- !(ia32_cap & ARCH_CAP_SSB_NO) &&
++ !(x86_arch_cap_msr & ARCH_CAP_SSB_NO) &&
+ !cpu_has(c, X86_FEATURE_AMD_SSB_NO))
+ setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
+
+@@ -1386,15 +1386,15 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ * AMD's AutoIBRS is equivalent to Intel's eIBRS - use the Intel feature
+ * flag and protect from vendor-specific bugs via the whitelist.
+ */
+- if ((ia32_cap & ARCH_CAP_IBRS_ALL) || cpu_has(c, X86_FEATURE_AUTOIBRS)) {
++ if ((x86_arch_cap_msr & ARCH_CAP_IBRS_ALL) || cpu_has(c, X86_FEATURE_AUTOIBRS)) {
+ setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED);
+ if (!cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) &&
+- !(ia32_cap & ARCH_CAP_PBRSB_NO))
++ !(x86_arch_cap_msr & ARCH_CAP_PBRSB_NO))
+ setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB);
+ }
+
+ if (!cpu_matches(cpu_vuln_whitelist, NO_MDS) &&
+- !(ia32_cap & ARCH_CAP_MDS_NO)) {
++ !(x86_arch_cap_msr & ARCH_CAP_MDS_NO)) {
+ setup_force_cpu_bug(X86_BUG_MDS);
+ if (cpu_matches(cpu_vuln_whitelist, MSBDS_ONLY))
+ setup_force_cpu_bug(X86_BUG_MSBDS_ONLY);
+@@ -1413,9 +1413,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ * TSX_CTRL check alone is not sufficient for cases when the microcode
+ * update is not present or running as guest that don't get TSX_CTRL.
+ */
+- if (!(ia32_cap & ARCH_CAP_TAA_NO) &&
++ if (!(x86_arch_cap_msr & ARCH_CAP_TAA_NO) &&
+ (cpu_has(c, X86_FEATURE_RTM) ||
+- (ia32_cap & ARCH_CAP_TSX_CTRL_MSR)))
++ (x86_arch_cap_msr & ARCH_CAP_TSX_CTRL_MSR)))
+ setup_force_cpu_bug(X86_BUG_TAA);
+
+ /*
+@@ -1441,7 +1441,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ * Set X86_BUG_MMIO_UNKNOWN for CPUs that are neither in the blacklist,
+ * nor in the whitelist and also don't enumerate MSR ARCH_CAP MMIO bits.
+ */
+- if (!arch_cap_mmio_immune(ia32_cap)) {
++ if (!arch_cap_mmio_immune(x86_arch_cap_msr)) {
+ if (cpu_matches(cpu_vuln_blacklist, MMIO))
+ setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
+ else if (!cpu_matches(cpu_vuln_whitelist, NO_MMIO))
+@@ -1449,7 +1449,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ }
+
+ if (!cpu_has(c, X86_FEATURE_BTC_NO)) {
+- if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA))
++ if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (x86_arch_cap_msr & ARCH_CAP_RSBA))
+ setup_force_cpu_bug(X86_BUG_RETBLEED);
+ }
+
+@@ -1467,15 +1467,15 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ * disabling AVX2. The only way to do this in HW is to clear XCR0[2],
+ * which means that AVX will be disabled.
+ */
+- if (cpu_matches(cpu_vuln_blacklist, GDS) && !(ia32_cap & ARCH_CAP_GDS_NO) &&
++ if (cpu_matches(cpu_vuln_blacklist, GDS) && !(x86_arch_cap_msr & ARCH_CAP_GDS_NO) &&
+ boot_cpu_has(X86_FEATURE_AVX))
+ setup_force_cpu_bug(X86_BUG_GDS);
+
+- if (vulnerable_to_rfds(ia32_cap))
++ if (vulnerable_to_rfds(x86_arch_cap_msr))
+ setup_force_cpu_bug(X86_BUG_RFDS);
+
+ /* When virtualized, eIBRS could be hidden, assume vulnerable */
+- if (!(ia32_cap & ARCH_CAP_BHI_NO) &&
++ if (!(x86_arch_cap_msr & ARCH_CAP_BHI_NO) &&
+ !cpu_matches(cpu_vuln_whitelist, NO_BHI) &&
+ (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED) ||
+ boot_cpu_has(X86_FEATURE_HYPERVISOR)))
+@@ -1485,7 +1485,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
+ return;
+
+ /* Rogue Data Cache Load? No! */
+- if (ia32_cap & ARCH_CAP_RDCL_NO)
++ if (x86_arch_cap_msr & ARCH_CAP_RDCL_NO)
+ return;
+
+ setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
+diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
+index ff93c385ba5af..4529122e0cbdb 100644
+--- a/block/blk-cgroup.c
++++ b/block/blk-cgroup.c
+@@ -1409,6 +1409,12 @@ static int blkcg_css_online(struct cgroup_subsys_state *css)
+ return 0;
+ }
+
++void blkg_init_queue(struct request_queue *q)
++{
++ INIT_LIST_HEAD(&q->blkg_list);
++ mutex_init(&q->blkcg_mutex);
++}
++
+ int blkcg_init_disk(struct gendisk *disk)
+ {
+ struct request_queue *q = disk->queue;
+@@ -1416,9 +1422,6 @@ int blkcg_init_disk(struct gendisk *disk)
+ bool preloaded;
+ int ret;
+
+- INIT_LIST_HEAD(&q->blkg_list);
+- mutex_init(&q->blkcg_mutex);
+-
+ new_blkg = blkg_alloc(&blkcg_root, disk, GFP_KERNEL);
+ if (!new_blkg)
+ return -ENOMEM;
+diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
+index b927a4a0ad030..5b0bdc268ade9 100644
+--- a/block/blk-cgroup.h
++++ b/block/blk-cgroup.h
+@@ -188,6 +188,7 @@ struct blkcg_policy {
+ extern struct blkcg blkcg_root;
+ extern bool blkcg_debug_stats;
+
++void blkg_init_queue(struct request_queue *q);
+ int blkcg_init_disk(struct gendisk *disk);
+ void blkcg_exit_disk(struct gendisk *disk);
+
+@@ -481,6 +482,7 @@ struct blkcg {
+ };
+
+ static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, void *key) { return NULL; }
++static inline void blkg_init_queue(struct request_queue *q) { }
+ static inline int blkcg_init_disk(struct gendisk *disk) { return 0; }
+ static inline void blkcg_exit_disk(struct gendisk *disk) { }
+ static inline int blkcg_policy_register(struct blkcg_policy *pol) { return 0; }
+diff --git a/block/blk-core.c b/block/blk-core.c
+index de771093b5268..99d684085719d 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -431,6 +431,8 @@ struct request_queue *blk_alloc_queue(int node_id)
+ init_waitqueue_head(&q->mq_freeze_wq);
+ mutex_init(&q->mq_freeze_lock);
+
++ blkg_init_queue(q);
++
+ /*
+ * Init percpu_ref in atomic mode so that it's faster to shutdown.
+ * See blk_register_queue() for details.
+diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c
+index 4b06402269869..b35c7aedca03e 100644
+--- a/drivers/accel/ivpu/ivpu_drv.c
++++ b/drivers/accel/ivpu/ivpu_drv.c
+@@ -131,22 +131,6 @@ static int ivpu_get_capabilities(struct ivpu_device *vdev, struct drm_ivpu_param
+ return 0;
+ }
+
+-static int ivpu_get_core_clock_rate(struct ivpu_device *vdev, u64 *clk_rate)
+-{
+- int ret;
+-
+- ret = ivpu_rpm_get_if_active(vdev);
+- if (ret < 0)
+- return ret;
+-
+- *clk_rate = ret ? ivpu_hw_reg_pll_freq_get(vdev) : 0;
+-
+- if (ret)
+- ivpu_rpm_put(vdev);
+-
+- return 0;
+-}
+-
+ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+ {
+ struct ivpu_file_priv *file_priv = file->driver_priv;
+@@ -170,7 +154,7 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f
+ args->value = vdev->platform;
+ break;
+ case DRM_IVPU_PARAM_CORE_CLOCK_RATE:
+- ret = ivpu_get_core_clock_rate(vdev, &args->value);
++ args->value = ivpu_hw_ratio_to_freq(vdev, vdev->hw->pll.max_ratio);
+ break;
+ case DRM_IVPU_PARAM_NUM_CONTEXTS:
+ args->value = ivpu_get_context_count(vdev);
+@@ -530,7 +514,7 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
+ vdev->context_xa_limit.min = IVPU_USER_CONTEXT_MIN_SSID;
+ vdev->context_xa_limit.max = IVPU_USER_CONTEXT_MAX_SSID;
+ atomic64_set(&vdev->unique_id_counter, 0);
+- xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC);
++ xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
+ xa_init_flags(&vdev->submitted_jobs_xa, XA_FLAGS_ALLOC1);
+ lockdep_set_class(&vdev->submitted_jobs_xa.xa_lock, &submitted_jobs_xa_lock_class_key);
+ INIT_LIST_HEAD(&vdev->bo_list);
+diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h
+index b2909168a0a69..094c659d2800b 100644
+--- a/drivers/accel/ivpu/ivpu_hw.h
++++ b/drivers/accel/ivpu/ivpu_hw.h
+@@ -21,6 +21,7 @@ struct ivpu_hw_ops {
+ u32 (*profiling_freq_get)(struct ivpu_device *vdev);
+ void (*profiling_freq_drive)(struct ivpu_device *vdev, bool enable);
+ u32 (*reg_pll_freq_get)(struct ivpu_device *vdev);
++ u32 (*ratio_to_freq)(struct ivpu_device *vdev, u32 ratio);
+ u32 (*reg_telemetry_offset_get)(struct ivpu_device *vdev);
+ u32 (*reg_telemetry_size_get)(struct ivpu_device *vdev);
+ u32 (*reg_telemetry_enable_get)(struct ivpu_device *vdev);
+@@ -130,6 +131,11 @@ static inline u32 ivpu_hw_reg_pll_freq_get(struct ivpu_device *vdev)
+ return vdev->hw->ops->reg_pll_freq_get(vdev);
+ };
+
++static inline u32 ivpu_hw_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
++{
++ return vdev->hw->ops->ratio_to_freq(vdev, ratio);
++}
++
+ static inline u32 ivpu_hw_reg_telemetry_offset_get(struct ivpu_device *vdev)
+ {
+ return vdev->hw->ops->reg_telemetry_offset_get(vdev);
+diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c
+index 89af1006df558..32bb772e03cf9 100644
+--- a/drivers/accel/ivpu/ivpu_hw_37xx.c
++++ b/drivers/accel/ivpu/ivpu_hw_37xx.c
+@@ -805,12 +805,12 @@ static void ivpu_hw_37xx_profiling_freq_drive(struct ivpu_device *vdev, bool ena
+ /* Profiling freq - is a debug feature. Unavailable on VPU 37XX. */
+ }
+
+-static u32 ivpu_hw_37xx_pll_to_freq(u32 ratio, u32 config)
++static u32 ivpu_hw_37xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
+ {
+ u32 pll_clock = PLL_REF_CLK_FREQ * ratio;
+ u32 cpu_clock;
+
+- if ((config & 0xff) == PLL_RATIO_4_3)
++ if ((vdev->hw->config & 0xff) == PLL_RATIO_4_3)
+ cpu_clock = pll_clock * 2 / 4;
+ else
+ cpu_clock = pll_clock * 2 / 5;
+@@ -829,7 +829,7 @@ static u32 ivpu_hw_37xx_reg_pll_freq_get(struct ivpu_device *vdev)
+ if (!ivpu_is_silicon(vdev))
+ return PLL_SIMULATION_FREQ;
+
+- return ivpu_hw_37xx_pll_to_freq(pll_curr_ratio, vdev->hw->config);
++ return ivpu_hw_37xx_ratio_to_freq(vdev, pll_curr_ratio);
+ }
+
+ static u32 ivpu_hw_37xx_reg_telemetry_offset_get(struct ivpu_device *vdev)
+@@ -1052,6 +1052,7 @@ const struct ivpu_hw_ops ivpu_hw_37xx_ops = {
+ .profiling_freq_get = ivpu_hw_37xx_profiling_freq_get,
+ .profiling_freq_drive = ivpu_hw_37xx_profiling_freq_drive,
+ .reg_pll_freq_get = ivpu_hw_37xx_reg_pll_freq_get,
++ .ratio_to_freq = ivpu_hw_37xx_ratio_to_freq,
+ .reg_telemetry_offset_get = ivpu_hw_37xx_reg_telemetry_offset_get,
+ .reg_telemetry_size_get = ivpu_hw_37xx_reg_telemetry_size_get,
+ .reg_telemetry_enable_get = ivpu_hw_37xx_reg_telemetry_enable_get,
+diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c
+index a1523d0b1ef36..0be353ad872d0 100644
+--- a/drivers/accel/ivpu/ivpu_hw_40xx.c
++++ b/drivers/accel/ivpu/ivpu_hw_40xx.c
+@@ -980,6 +980,11 @@ static u32 ivpu_hw_40xx_reg_pll_freq_get(struct ivpu_device *vdev)
+ return PLL_RATIO_TO_FREQ(pll_curr_ratio);
+ }
+
++static u32 ivpu_hw_40xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio)
++{
++ return PLL_RATIO_TO_FREQ(ratio);
++}
++
+ static u32 ivpu_hw_40xx_reg_telemetry_offset_get(struct ivpu_device *vdev)
+ {
+ return REGB_RD32(VPU_40XX_BUTTRESS_VPU_TELEMETRY_OFFSET);
+@@ -1230,6 +1235,7 @@ const struct ivpu_hw_ops ivpu_hw_40xx_ops = {
+ .profiling_freq_get = ivpu_hw_40xx_profiling_freq_get,
+ .profiling_freq_drive = ivpu_hw_40xx_profiling_freq_drive,
+ .reg_pll_freq_get = ivpu_hw_40xx_reg_pll_freq_get,
++ .ratio_to_freq = ivpu_hw_40xx_ratio_to_freq,
+ .reg_telemetry_offset_get = ivpu_hw_40xx_reg_telemetry_offset_get,
+ .reg_telemetry_size_get = ivpu_hw_40xx_reg_telemetry_size_get,
+ .reg_telemetry_enable_get = ivpu_hw_40xx_reg_telemetry_enable_get,
+diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c
+index fa66c39b57eca..f4c5392483656 100644
+--- a/drivers/accel/ivpu/ivpu_ipc.c
++++ b/drivers/accel/ivpu/ivpu_ipc.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Copyright (C) 2020-2023 Intel Corporation
++ * Copyright (C) 2020-2024 Intel Corporation
+ */
+
+ #include <linux/genalloc.h>
+@@ -501,7 +501,11 @@ int ivpu_ipc_init(struct ivpu_device *vdev)
+ spin_lock_init(&ipc->cons_lock);
+ INIT_LIST_HEAD(&ipc->cons_list);
+ INIT_LIST_HEAD(&ipc->cb_msg_list);
+- drmm_mutex_init(&vdev->drm, &ipc->lock);
++ ret = drmm_mutex_init(&vdev->drm, &ipc->lock);
++ if (ret) {
++ ivpu_err(vdev, "Failed to initialize ipc->lock, ret %d\n", ret);
++ goto err_free_rx;
++ }
+ ivpu_ipc_reset(vdev);
+ return 0;
+
+diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c
+index 5f73854234ba9..a15d30d0943af 100644
+--- a/drivers/accel/ivpu/ivpu_pm.c
++++ b/drivers/accel/ivpu/ivpu_pm.c
+@@ -74,10 +74,10 @@ static int ivpu_resume(struct ivpu_device *vdev)
+ {
+ int ret;
+
+- pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D0);
++retry:
+ pci_restore_state(to_pci_dev(vdev->drm.dev));
++ pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D0);
+
+-retry:
+ ret = ivpu_hw_power_up(vdev);
+ if (ret) {
+ ivpu_err(vdev, "Failed to power up HW: %d\n", ret);
+@@ -100,6 +100,7 @@ static int ivpu_resume(struct ivpu_device *vdev)
+ ivpu_mmu_disable(vdev);
+ err_power_down:
+ ivpu_hw_power_down(vdev);
++ pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
+
+ if (!ivpu_fw_is_cold_boot(vdev)) {
+ ivpu_pm_prepare_cold_boot(vdev);
+diff --git a/drivers/acpi/numa/hmat.c b/drivers/acpi/numa/hmat.c
+index a26e7793ec4ef..75e9aac43228a 100644
+--- a/drivers/acpi/numa/hmat.c
++++ b/drivers/acpi/numa/hmat.c
+@@ -59,9 +59,8 @@ struct target_cache {
+ };
+
+ enum {
+- NODE_ACCESS_CLASS_0 = 0,
+- NODE_ACCESS_CLASS_1,
+- NODE_ACCESS_CLASS_GENPORT_SINK,
++ NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL = ACCESS_COORDINATE_MAX,
++ NODE_ACCESS_CLASS_GENPORT_SINK_CPU,
+ NODE_ACCESS_CLASS_MAX,
+ };
+
+@@ -127,7 +126,8 @@ static struct memory_target *acpi_find_genport_target(u32 uid)
+ /**
+ * acpi_get_genport_coordinates - Retrieve the access coordinates for a generic port
+ * @uid: ACPI unique id
+- * @coord: The access coordinates written back out for the generic port
++ * @coord: The access coordinates written back out for the generic port.
++ * Expect 2 levels array.
+ *
+ * Return: 0 on success. Errno on failure.
+ *
+@@ -143,7 +143,10 @@ int acpi_get_genport_coordinates(u32 uid,
+ if (!target)
+ return -ENOENT;
+
+- *coord = target->coord[NODE_ACCESS_CLASS_GENPORT_SINK];
++ coord[ACCESS_COORDINATE_LOCAL] =
++ target->coord[NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL];
++ coord[ACCESS_COORDINATE_CPU] =
++ target->coord[NODE_ACCESS_CLASS_GENPORT_SINK_CPU];
+
+ return 0;
+ }
+@@ -374,11 +377,11 @@ static __init void hmat_update_target(unsigned int tgt_pxm, unsigned int init_px
+
+ if (target && target->processor_pxm == init_pxm) {
+ hmat_update_target_access(target, type, value,
+- NODE_ACCESS_CLASS_0);
++ ACCESS_COORDINATE_LOCAL);
+ /* If the node has a CPU, update access 1 */
+ if (node_state(pxm_to_node(init_pxm), N_CPU))
+ hmat_update_target_access(target, type, value,
+- NODE_ACCESS_CLASS_1);
++ ACCESS_COORDINATE_CPU);
+ }
+ }
+
+@@ -697,7 +700,8 @@ static void hmat_update_target_attrs(struct memory_target *target,
+ int i;
+
+ /* Don't update for generic port if there's no device handle */
+- if (access == NODE_ACCESS_CLASS_GENPORT_SINK &&
++ if ((access == NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL ||
++ access == NODE_ACCESS_CLASS_GENPORT_SINK_CPU) &&
+ !(*(u16 *)target->gen_port_device_handle))
+ return;
+
+@@ -709,7 +713,8 @@ static void hmat_update_target_attrs(struct memory_target *target,
+ */
+ if (target->processor_pxm != PXM_INVAL) {
+ cpu_nid = pxm_to_node(target->processor_pxm);
+- if (access == 0 || node_state(cpu_nid, N_CPU)) {
++ if (access == ACCESS_COORDINATE_LOCAL ||
++ node_state(cpu_nid, N_CPU)) {
+ set_bit(target->processor_pxm, p_nodes);
+ return;
+ }
+@@ -737,7 +742,9 @@ static void hmat_update_target_attrs(struct memory_target *target,
+ list_for_each_entry(initiator, &initiators, node) {
+ u32 value;
+
+- if (access == 1 && !initiator->has_cpu) {
++ if ((access == ACCESS_COORDINATE_CPU ||
++ access == NODE_ACCESS_CLASS_GENPORT_SINK_CPU) &&
++ !initiator->has_cpu) {
+ clear_bit(initiator->processor_pxm, p_nodes);
+ continue;
+ }
+@@ -775,15 +782,19 @@ static void hmat_update_generic_target(struct memory_target *target)
+ static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
+
+ hmat_update_target_attrs(target, p_nodes,
+- NODE_ACCESS_CLASS_GENPORT_SINK);
++ NODE_ACCESS_CLASS_GENPORT_SINK_LOCAL);
++ hmat_update_target_attrs(target, p_nodes,
++ NODE_ACCESS_CLASS_GENPORT_SINK_CPU);
+ }
+
+ static void hmat_register_target_initiators(struct memory_target *target)
+ {
+ static DECLARE_BITMAP(p_nodes, MAX_NUMNODES);
+
+- __hmat_register_target_initiators(target, p_nodes, 0);
+- __hmat_register_target_initiators(target, p_nodes, 1);
++ __hmat_register_target_initiators(target, p_nodes,
++ ACCESS_COORDINATE_LOCAL);
++ __hmat_register_target_initiators(target, p_nodes,
++ ACCESS_COORDINATE_CPU);
+ }
+
+ static void hmat_register_target_cache(struct memory_target *target)
+@@ -854,8 +865,8 @@ static void hmat_register_target(struct memory_target *target)
+ if (!target->registered) {
+ hmat_register_target_initiators(target);
+ hmat_register_target_cache(target);
+- hmat_register_target_perf(target, NODE_ACCESS_CLASS_0);
+- hmat_register_target_perf(target, NODE_ACCESS_CLASS_1);
++ hmat_register_target_perf(target, ACCESS_COORDINATE_LOCAL);
++ hmat_register_target_perf(target, ACCESS_COORDINATE_CPU);
+ target->registered = true;
+ }
+ mutex_unlock(&target_lock);
+@@ -927,7 +938,7 @@ static int hmat_calculate_adistance(struct notifier_block *self,
+ return NOTIFY_OK;
+
+ mutex_lock(&target_lock);
+- hmat_update_target_attrs(target, p_nodes, 1);
++ hmat_update_target_attrs(target, p_nodes, ACCESS_COORDINATE_CPU);
+ mutex_unlock(&target_lock);
+
+ perf = &target->coord[1];
+diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
+index 617f3e0e963d5..eb4ca85d16ffb 100644
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -1802,7 +1802,8 @@ static void acpi_scan_dep_init(struct acpi_device *adev)
+ if (dep->honor_dep)
+ adev->flags.honor_deps = 1;
+
+- adev->dep_unmet++;
++ if (!dep->met)
++ adev->dep_unmet++;
+ }
+ }
+ }
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index be3412cdb22e7..c449d60d9bb96 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -2539,7 +2539,7 @@ static void ata_dev_config_cdl(struct ata_device *dev)
+ bool cdl_enabled;
+ u64 val;
+
+- if (ata_id_major_version(dev->id) < 12)
++ if (ata_id_major_version(dev->id) < 11)
+ goto not_supported;
+
+ if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE) ||
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 2f4c588376410..e954976891a9f 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -4745,7 +4745,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+ * bail out.
+ */
+ if (ap->pflags & ATA_PFLAG_SUSPENDED)
+- goto unlock;
++ goto unlock_ap;
+
+ if (!sdev)
+ continue;
+@@ -4758,7 +4758,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+ if (do_resume) {
+ ret = scsi_resume_device(sdev);
+ if (ret == -EWOULDBLOCK)
+- goto unlock;
++ goto unlock_scan;
+ dev->flags &= ~ATA_DFLAG_RESUMING;
+ }
+ ret = scsi_rescan_device(sdev);
+@@ -4766,12 +4766,13 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+ spin_lock_irqsave(ap->lock, flags);
+
+ if (ret)
+- goto unlock;
++ goto unlock_ap;
+ }
+ }
+
+-unlock:
++unlock_ap:
+ spin_unlock_irqrestore(ap->lock, flags);
++unlock_scan:
+ mutex_unlock(&ap->scsi_scan_mutex);
+
+ /* Reschedule with a delay if scsi_rescan_device() returned an error */
+diff --git a/drivers/base/node.c b/drivers/base/node.c
+index 1c05640461dd1..a73b0c9a401ad 100644
+--- a/drivers/base/node.c
++++ b/drivers/base/node.c
+@@ -126,7 +126,7 @@ static void node_access_release(struct device *dev)
+ }
+
+ static struct node_access_nodes *node_init_node_access(struct node *node,
+- unsigned int access)
++ enum access_coordinate_class access)
+ {
+ struct node_access_nodes *access_node;
+ struct device *dev;
+@@ -191,7 +191,7 @@ static struct attribute *access_attrs[] = {
+ * @access: The access class the for the given attributes
+ */
+ void node_set_perf_attrs(unsigned int nid, struct access_coordinate *coord,
+- unsigned int access)
++ enum access_coordinate_class access)
+ {
+ struct node_access_nodes *c;
+ struct node *node;
+@@ -689,7 +689,7 @@ int register_cpu_under_node(unsigned int cpu, unsigned int nid)
+ */
+ int register_memory_node_under_compute_node(unsigned int mem_nid,
+ unsigned int cpu_nid,
+- unsigned int access)
++ enum access_coordinate_class access)
+ {
+ struct node *init_node, *targ_node;
+ struct node_access_nodes *initiator, *target;
+diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
+index 1a3e6aafbdcc3..af5cb818f84d6 100644
+--- a/drivers/cxl/acpi.c
++++ b/drivers/cxl/acpi.c
+@@ -530,13 +530,15 @@ static int get_genport_coordinates(struct device *dev, struct cxl_dport *dport)
+ if (kstrtou32(acpi_device_uid(hb), 0, &uid))
+ return -EINVAL;
+
+- rc = acpi_get_genport_coordinates(uid, &dport->hb_coord);
++ rc = acpi_get_genport_coordinates(uid, dport->hb_coord);
+ if (rc < 0)
+ return rc;
+
+ /* Adjust back to picoseconds from nanoseconds */
+- dport->hb_coord.read_latency *= 1000;
+- dport->hb_coord.write_latency *= 1000;
++ for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) {
++ dport->hb_coord[i].read_latency *= 1000;
++ dport->hb_coord[i].write_latency *= 1000;
++ }
+
+ return 0;
+ }
+diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c
+index 0363ca434ef45..fbf167f9d59d4 100644
+--- a/drivers/cxl/core/cdat.c
++++ b/drivers/cxl/core/cdat.c
+@@ -162,15 +162,22 @@ static int cxl_cdat_endpoint_process(struct cxl_port *port,
+ static int cxl_port_perf_data_calculate(struct cxl_port *port,
+ struct xarray *dsmas_xa)
+ {
+- struct access_coordinate c;
++ struct access_coordinate ep_c;
++ struct access_coordinate coord[ACCESS_COORDINATE_MAX];
+ struct dsmas_entry *dent;
+ int valid_entries = 0;
+ unsigned long index;
+ int rc;
+
+- rc = cxl_endpoint_get_perf_coordinates(port, &c);
++ rc = cxl_endpoint_get_perf_coordinates(port, &ep_c);
+ if (rc) {
+- dev_dbg(&port->dev, "Failed to retrieve perf coordinates.\n");
++ dev_dbg(&port->dev, "Failed to retrieve ep perf coordinates.\n");
++ return rc;
++ }
++
++ rc = cxl_hb_get_perf_coordinates(port, coord);
++ if (rc) {
++ dev_dbg(&port->dev, "Failed to retrieve hb perf coordinates.\n");
+ return rc;
+ }
+
+@@ -185,18 +192,19 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
+ xa_for_each(dsmas_xa, index, dent) {
+ int qos_class;
+
+- dent->coord.read_latency = dent->coord.read_latency +
+- c.read_latency;
+- dent->coord.write_latency = dent->coord.write_latency +
+- c.write_latency;
+- dent->coord.read_bandwidth = min_t(int, c.read_bandwidth,
+- dent->coord.read_bandwidth);
+- dent->coord.write_bandwidth = min_t(int, c.write_bandwidth,
+- dent->coord.write_bandwidth);
+-
++ cxl_coordinates_combine(&dent->coord, &dent->coord, &ep_c);
++ /*
++ * Keeping the host bridge coordinates separate from the dsmas
++ * coordinates in order to allow calculation of access class
++ * 0 and 1 for region later.
++ */
++ cxl_coordinates_combine(&coord[ACCESS_COORDINATE_LOCAL],
++ &coord[ACCESS_COORDINATE_LOCAL],
++ &dent->coord);
+ dent->entries = 1;
+- rc = cxl_root->ops->qos_class(cxl_root, &dent->coord, 1,
+- &qos_class);
++ rc = cxl_root->ops->qos_class(cxl_root,
++ &coord[ACCESS_COORDINATE_LOCAL],
++ 1, &qos_class);
+ if (rc != 1)
+ continue;
+
+@@ -484,4 +492,26 @@ void cxl_switch_parse_cdat(struct cxl_port *port)
+ }
+ EXPORT_SYMBOL_NS_GPL(cxl_switch_parse_cdat, CXL);
+
++/**
++ * cxl_coordinates_combine - Combine the two input coordinates
++ *
++ * @out: Output coordinate of c1 and c2 combined
++ * @c1: input coordinates
++ * @c2: input coordinates
++ */
++void cxl_coordinates_combine(struct access_coordinate *out,
++ struct access_coordinate *c1,
++ struct access_coordinate *c2)
++{
++ if (c1->write_bandwidth && c2->write_bandwidth)
++ out->write_bandwidth = min(c1->write_bandwidth,
++ c2->write_bandwidth);
++ out->write_latency = c1->write_latency + c2->write_latency;
++
++ if (c1->read_bandwidth && c2->read_bandwidth)
++ out->read_bandwidth = min(c1->read_bandwidth,
++ c2->read_bandwidth);
++ out->read_latency = c1->read_latency + c2->read_latency;
++}
++
+ MODULE_IMPORT_NS(CXL);
+diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
+index 9adda4795eb78..f0f54aeccc872 100644
+--- a/drivers/cxl/core/mbox.c
++++ b/drivers/cxl/core/mbox.c
+@@ -915,7 +915,7 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds,
+
+ payload->handles[i++] = gen->hdr.handle;
+ dev_dbg(mds->cxlds.dev, "Event log '%d': Clearing %u\n", log,
+- le16_to_cpu(payload->handles[i]));
++ le16_to_cpu(payload->handles[i - 1]));
+
+ if (i == max_handles) {
+ payload->nr_recs = i;
+@@ -958,13 +958,14 @@ static void cxl_mem_get_records_log(struct cxl_memdev_state *mds,
+ .payload_in = &log_type,
+ .size_in = sizeof(log_type),
+ .payload_out = payload,
+- .size_out = mds->payload_size,
+ .min_out = struct_size(payload, records, 0),
+ };
+
+ do {
+ int rc, i;
+
++ mbox_cmd.size_out = mds->payload_size;
++
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
+ if (rc) {
+ dev_err_ratelimited(dev,
+diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
+index e59d9d37aa650..4ae441ef32174 100644
+--- a/drivers/cxl/core/port.c
++++ b/drivers/cxl/core/port.c
+@@ -2096,18 +2096,41 @@ bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd)
+ }
+ EXPORT_SYMBOL_NS_GPL(schedule_cxl_memdev_detach, CXL);
+
+-static void combine_coordinates(struct access_coordinate *c1,
+- struct access_coordinate *c2)
++/**
++ * cxl_hb_get_perf_coordinates - Retrieve performance numbers between initiator
++ * and host bridge
++ *
++ * @port: endpoint cxl_port
++ * @coord: output access coordinates
++ *
++ * Return: errno on failure, 0 on success.
++ */
++int cxl_hb_get_perf_coordinates(struct cxl_port *port,
++ struct access_coordinate *coord)
+ {
+- if (c2->write_bandwidth)
+- c1->write_bandwidth = min(c1->write_bandwidth,
+- c2->write_bandwidth);
+- c1->write_latency += c2->write_latency;
++ struct cxl_port *iter = port;
++ struct cxl_dport *dport;
++
++ if (!is_cxl_endpoint(port))
++ return -EINVAL;
++
++ dport = iter->parent_dport;
++ while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) {
++ iter = to_cxl_port(iter->dev.parent);
++ dport = iter->parent_dport;
++ }
++
++ coord[ACCESS_COORDINATE_LOCAL] =
++ dport->hb_coord[ACCESS_COORDINATE_LOCAL];
++ coord[ACCESS_COORDINATE_CPU] =
++ dport->hb_coord[ACCESS_COORDINATE_CPU];
+
+- if (c2->read_bandwidth)
+- c1->read_bandwidth = min(c1->read_bandwidth,
+- c2->read_bandwidth);
+- c1->read_latency += c2->read_latency;
++ return 0;
++}
++
++static bool parent_port_is_cxl_root(struct cxl_port *port)
++{
++ return is_cxl_root(to_cxl_port(port->dev.parent));
+ }
+
+ /**
+@@ -2129,30 +2152,31 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
+ struct cxl_dport *dport;
+ struct pci_dev *pdev;
+ unsigned int bw;
++ bool is_cxl_root;
+
+ if (!is_cxl_endpoint(port))
+ return -EINVAL;
+
+- dport = iter->parent_dport;
+-
+ /*
+- * Exit the loop when the parent port of the current port is cxl root.
+- * The iterative loop starts at the endpoint and gathers the
+- * latency of the CXL link from the current iter to the next downstream
+- * port each iteration. If the parent is cxl root then there is
+- * nothing to gather.
++ * Exit the loop when the parent port of the current iter port is cxl
++ * root. The iterative loop starts at the endpoint and gathers the
++ * latency of the CXL link from the current device/port to the connected
++ * downstream port each iteration.
+ */
+- while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) {
+- combine_coordinates(&c, &dport->sw_coord);
+- c.write_latency += dport->link_latency;
+- c.read_latency += dport->link_latency;
+-
+- iter = to_cxl_port(iter->dev.parent);
++ do {
+ dport = iter->parent_dport;
+- }
++ iter = to_cxl_port(iter->dev.parent);
++ is_cxl_root = parent_port_is_cxl_root(iter);
+
+- /* Augment with the generic port (host bridge) perf data */
+- combine_coordinates(&c, &dport->hb_coord);
++ /*
++ * There's no valid access_coordinate for a root port since RPs do not
++ * have CDAT and therefore needs to be skipped.
++ */
++ if (!is_cxl_root)
++ cxl_coordinates_combine(&c, &c, &dport->sw_coord);
++ c.write_latency += dport->link_latency;
++ c.read_latency += dport->link_latency;
++ } while (!is_cxl_root);
+
+ /* Get the calculated PCI paths bandwidth */
+ pdev = to_pci_dev(port->uport_dev->parent);
+diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
+index 372786f809555..3c42f984eeafa 100644
+--- a/drivers/cxl/core/regs.c
++++ b/drivers/cxl/core/regs.c
+@@ -271,6 +271,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_map_device_regs, CXL);
+ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi,
+ struct cxl_register_map *map)
+ {
++ u8 reg_type = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BLOCK_ID_MASK, reg_lo);
+ int bar = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BIR_MASK, reg_lo);
+ u64 offset = ((u64)reg_hi << 32) |
+ (reg_lo & CXL_DVSEC_REG_LOCATOR_BLOCK_OFF_LOW_MASK);
+@@ -278,11 +279,11 @@ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi,
+ if (offset > pci_resource_len(pdev, bar)) {
+ dev_warn(&pdev->dev,
+ "BAR%d: %pr: too small (offset: %pa, type: %d)\n", bar,
+- &pdev->resource[bar], &offset, map->reg_type);
++ &pdev->resource[bar], &offset, reg_type);
+ return false;
+ }
+
+- map->reg_type = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BLOCK_ID_MASK, reg_lo);
++ map->reg_type = reg_type;
+ map->resource = pci_resource_start(pdev, bar) + offset;
+ map->max_size = pci_resource_len(pdev, bar) - offset;
+ return true;
+diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
+index 003feebab79b5..de477eb7f5d54 100644
+--- a/drivers/cxl/cxl.h
++++ b/drivers/cxl/cxl.h
+@@ -671,7 +671,7 @@ struct cxl_dport {
+ struct cxl_port *port;
+ struct cxl_regs regs;
+ struct access_coordinate sw_coord;
+- struct access_coordinate hb_coord;
++ struct access_coordinate hb_coord[ACCESS_COORDINATE_MAX];
+ long link_latency;
+ };
+
+@@ -879,9 +879,15 @@ void cxl_switch_parse_cdat(struct cxl_port *port);
+
+ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
+ struct access_coordinate *coord);
++int cxl_hb_get_perf_coordinates(struct cxl_port *port,
++ struct access_coordinate *coord);
+
+ void cxl_memdev_update_perf(struct cxl_memdev *cxlmd);
+
++void cxl_coordinates_combine(struct access_coordinate *out,
++ struct access_coordinate *c1,
++ struct access_coordinate *c2);
++
+ /*
+ * Unit test builds overrides this to __weak, find the 'strong' version
+ * of these symbols in tools/testing/cxl/.
+diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
+index f2556a8e94015..9bc2e10381afd 100644
+--- a/drivers/firmware/arm_ffa/driver.c
++++ b/drivers/firmware/arm_ffa/driver.c
+@@ -790,7 +790,7 @@ static void ffa_notification_info_get(void)
+
+ part_id = packed_id_list[ids_processed++];
+
+- if (!ids_count[list]) { /* Global Notification */
++ if (ids_count[list] == 1) { /* Global Notification */
+ __do_sched_recv_cb(part_id, 0, false);
+ continue;
+ }
+diff --git a/drivers/firmware/arm_scmi/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c
+index 3505735185033..130d13e9cd6be 100644
+--- a/drivers/firmware/arm_scmi/raw_mode.c
++++ b/drivers/firmware/arm_scmi/raw_mode.c
+@@ -921,7 +921,7 @@ static int scmi_dbg_raw_mode_open(struct inode *inode, struct file *filp)
+ rd->raw = raw;
+ filp->private_data = rd;
+
+- return 0;
++ return nonseekable_open(inode, filp);
+ }
+
+ static int scmi_dbg_raw_mode_release(struct inode *inode, struct file *filp)
+@@ -950,6 +950,7 @@ static const struct file_operations scmi_dbg_raw_mode_reset_fops = {
+ .open = scmi_dbg_raw_mode_open,
+ .release = scmi_dbg_raw_mode_release,
+ .write = scmi_dbg_raw_mode_reset_write,
++ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+ };
+
+@@ -959,6 +960,7 @@ static const struct file_operations scmi_dbg_raw_mode_message_fops = {
+ .read = scmi_dbg_raw_mode_message_read,
+ .write = scmi_dbg_raw_mode_message_write,
+ .poll = scmi_dbg_raw_mode_message_poll,
++ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+ };
+
+@@ -975,6 +977,7 @@ static const struct file_operations scmi_dbg_raw_mode_message_async_fops = {
+ .read = scmi_dbg_raw_mode_message_read,
+ .write = scmi_dbg_raw_mode_message_async_write,
+ .poll = scmi_dbg_raw_mode_message_poll,
++ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+ };
+
+@@ -998,6 +1001,7 @@ static const struct file_operations scmi_dbg_raw_mode_notification_fops = {
+ .release = scmi_dbg_raw_mode_release,
+ .read = scmi_test_dbg_raw_mode_notif_read,
+ .poll = scmi_test_dbg_raw_mode_notif_poll,
++ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+ };
+
+@@ -1021,6 +1025,7 @@ static const struct file_operations scmi_dbg_raw_mode_errors_fops = {
+ .release = scmi_dbg_raw_mode_release,
+ .read = scmi_test_dbg_raw_mode_errors_read,
+ .poll = scmi_test_dbg_raw_mode_errors_poll,
++ .llseek = no_llseek,
+ .owner = THIS_MODULE,
+ };
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
+index b9a15d51eb5c3..ad44012cc01e2 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
+@@ -390,6 +390,12 @@ static int vpe_hw_init(void *handle)
+ struct amdgpu_vpe *vpe = &adev->vpe;
+ int ret;
+
++ /* Power on VPE */
++ ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VPE,
++ AMD_PG_STATE_UNGATE);
++ if (ret)
++ return ret;
++
+ ret = vpe_load_microcode(vpe);
+ if (ret)
+ return ret;
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+index 4f3bfdc75b37d..0afe86bcc932b 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+@@ -1630,7 +1630,7 @@ static void gfx_v11_0_setup_rb(struct amdgpu_device *adev)
+ active_rb_bitmap |= (0x3 << (i * rb_bitmap_width_per_sa));
+ }
+
+- active_rb_bitmap |= global_active_rb_bitmap;
++ active_rb_bitmap &= global_active_rb_bitmap;
+ adev->gfx.config.backend_enable_mask = active_rb_bitmap;
+ adev->gfx.config.num_rbs = hweight32(active_rb_bitmap);
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c
+index 4d7188912edfe..fd4505fa4f670 100644
+--- a/drivers/gpu/drm/amd/amdgpu/soc21.c
++++ b/drivers/gpu/drm/amd/amdgpu/soc21.c
+@@ -450,10 +450,8 @@ static bool soc21_need_full_reset(struct amdgpu_device *adev)
+ {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
+ case IP_VERSION(11, 0, 0):
+- return amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC);
+ case IP_VERSION(11, 0, 2):
+ case IP_VERSION(11, 0, 3):
+- return false;
+ default:
+ return true;
+ }
+@@ -714,7 +712,10 @@ static int soc21_common_early_init(void *handle)
+ AMD_PG_SUPPORT_VCN |
+ AMD_PG_SUPPORT_JPEG |
+ AMD_PG_SUPPORT_GFX_PG;
+- adev->external_rev_id = adev->rev_id + 0x1;
++ if (adev->rev_id == 0)
++ adev->external_rev_id = 0x1;
++ else
++ adev->external_rev_id = adev->rev_id + 0x10;
+ break;
+ default:
+ /* FIXME: not supported yet */
+@@ -832,10 +833,35 @@ static int soc21_common_suspend(void *handle)
+ return soc21_common_hw_fini(adev);
+ }
+
++static bool soc21_need_reset_on_resume(struct amdgpu_device *adev)
++{
++ u32 sol_reg1, sol_reg2;
++
++ /* Will reset for the following suspend abort cases.
++ * 1) Only reset dGPU side.
++ * 2) S3 suspend got aborted and TOS is active.
++ */
++ if (!(adev->flags & AMD_IS_APU) && adev->in_s3 &&
++ !adev->suspend_complete) {
++ sol_reg1 = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81);
++ msleep(100);
++ sol_reg2 = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81);
++
++ return (sol_reg1 != sol_reg2);
++ }
++
++ return false;
++}
++
+ static int soc21_common_resume(void *handle)
+ {
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
++ if (soc21_need_reset_on_resume(adev)) {
++ dev_info(adev->dev, "S3 suspend aborted, resetting...");
++ soc21_asic_reset(adev);
++ }
++
+ return soc21_common_hw_init(adev);
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
+index 8e7b763cfdb7e..fd23cd348552b 100644
+--- a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c
+@@ -225,6 +225,8 @@ static int umsch_mm_v4_0_ring_start(struct amdgpu_umsch_mm *umsch)
+
+ WREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_SIZE, ring->ring_size);
+
++ ring->wptr = 0;
++
+ data = RREG32_SOC15(VCN, 0, regVCN_RB_ENABLE);
+ data &= ~(VCN_RB_ENABLE__AUDIO_RB_EN_MASK);
+ WREG32_SOC15(VCN, 0, regVCN_RB_ENABLE, data);
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+index c0e71543389a9..c0ae1a97498b5 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+@@ -1997,6 +1997,7 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm,
+ dev_err(dev, "HIQ MQD's queue_doorbell_id0 is not 0, Queue preemption time out\n");
+ while (halt_if_hws_hang)
+ schedule();
++ kfd_hws_hang(dqm);
+ return -ETIME;
+ }
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 1eb0f82e9dfae..718e533ab46dd 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -6257,19 +6257,16 @@ create_stream_for_sink(struct drm_connector *connector,
+ if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
+ mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket);
+
+- if (stream->link->psr_settings.psr_feature_enabled || stream->link->replay_settings.replay_feature_enabled) {
++ if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT ||
++ stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
++ stream->signal == SIGNAL_TYPE_EDP) {
+ //
+ // should decide stream support vsc sdp colorimetry capability
+ // before building vsc info packet
+ //
+- stream->use_vsc_sdp_for_colorimetry = false;
+- if (aconnector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+- stream->use_vsc_sdp_for_colorimetry =
+- aconnector->dc_sink->is_vsc_sdp_colorimetry_supported;
+- } else {
+- if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED)
+- stream->use_vsc_sdp_for_colorimetry = true;
+- }
++ stream->use_vsc_sdp_for_colorimetry = stream->link->dpcd_caps.dpcd_rev.raw >= 0x14 &&
++ stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED;
++
+ if (stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22)
+ tf = TRANSFER_FUNC_GAMMA_22;
+ mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space, tf);
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
+index 16e72d623630c..08c494a7a21ba 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c
+@@ -76,10 +76,8 @@ static int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder,
+
+ static int amdgpu_dm_wb_connector_get_modes(struct drm_connector *connector)
+ {
+- struct drm_device *dev = connector->dev;
+-
+- return drm_add_modes_noedid(connector, dev->mode_config.max_width,
+- dev->mode_config.max_height);
++ /* Maximum resolution supported by DWB */
++ return drm_add_modes_noedid(connector, 3840, 2160);
+ }
+
+ static int amdgpu_dm_wb_prepare_job(struct drm_writeback_connector *wb_connector,
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
+index 12f3e8aa46d8d..6ad4f4efec5dd 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c
+@@ -99,20 +99,25 @@ static int dcn316_get_active_display_cnt_wa(
+ return display_count;
+ }
+
+-static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable)
++static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context,
++ bool safe_to_lower, bool disable)
+ {
+ struct dc *dc = clk_mgr_base->ctx->dc;
+ int i;
+
+ for (i = 0; i < dc->res_pool->pipe_count; ++i) {
+- struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
++ struct pipe_ctx *pipe = safe_to_lower
++ ? &context->res_ctx.pipe_ctx[i]
++ : &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (pipe->top_pipe || pipe->prev_odm_pipe)
+ continue;
+- if (pipe->stream && (pipe->stream->dpms_off || pipe->plane_state == NULL ||
+- dc_is_virtual_signal(pipe->stream->signal))) {
++ if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) ||
++ !pipe->stream->link_enc)) {
+ if (disable) {
+- pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
++ if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->immediate_disable_crtc)
++ pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg);
++
+ reset_sync_context_for_pipe(dc, context, i);
+ } else
+ pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg);
+@@ -207,11 +212,11 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base,
+ }
+
+ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) {
+- dcn316_disable_otg_wa(clk_mgr_base, context, true);
++ dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true);
+
+ clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz;
+ dcn316_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz);
+- dcn316_disable_otg_wa(clk_mgr_base, context, false);
++ dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false);
+
+ update_dispclk = true;
+ }
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+index 5cc7f8da209c5..61986e5cb4919 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c
+@@ -436,6 +436,15 @@ bool dc_state_add_plane(
+ goto out;
+ }
+
++ if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm)
++ /* ODM combine could prevent us from supporting more planes
++ * we will reset ODM slice count back to 1 when all planes have
++ * been removed to maximize the amount of planes supported when
++ * new planes are added.
++ */
++ resource_update_pipes_for_stream_with_slice_count(
++ state, dc->current_state, dc->res_pool, stream, 1);
++
+ otg_master_pipe = resource_get_otg_master_for_stream(
+ &state->res_ctx, stream);
+ if (otg_master_pipe)
+diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
+index f07a4c7e48bc2..52eab8fccb7f1 100644
+--- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
++++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c
+@@ -267,9 +267,6 @@ static void optc32_setup_manual_trigger(struct timing_generator *optc)
+ OTG_V_TOTAL_MAX_SEL, 1,
+ OTG_FORCE_LOCK_ON_EVENT, 0,
+ OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */
+-
+- // Setup manual flow control for EOF via TRIG_A
+- optc->funcs->setup_manual_trigger(optc);
+ }
+ }
+
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
+index bb98156b2fa1d..949131bd1ecb2 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
+@@ -226,8 +226,18 @@ static int smu_v13_0_4_system_features_control(struct smu_context *smu, bool en)
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+
+- if (!en && !adev->in_s0ix)
++ if (!en && !adev->in_s0ix) {
++ /* Adds a GFX reset as workaround just before sending the
++ * MP1_UNLOAD message to prevent GC/RLC/PMFW from entering
++ * an invalid state.
++ */
++ ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset,
++ SMU_RESET_MODE_2, NULL);
++ if (ret)
++ return ret;
++
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL);
++ }
+
+ return ret;
+ }
+diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c
+index ebb6d8ebd44eb..1e9259416980e 100644
+--- a/drivers/gpu/drm/ast/ast_dp.c
++++ b/drivers/gpu/drm/ast/ast_dp.c
+@@ -180,6 +180,7 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on)
+ {
+ struct ast_device *ast = to_ast_device(dev);
+ u8 video_on_off = on;
++ u32 i = 0;
+
+ // Video On/Off
+ ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on);
+@@ -192,6 +193,8 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on)
+ ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) {
+ // wait 1 ms
+ mdelay(1);
++ if (++i > 200)
++ break;
+ }
+ }
+ }
+diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
+index 871e4e2129d6d..0683a129b3628 100644
+--- a/drivers/gpu/drm/drm_client_modeset.c
++++ b/drivers/gpu/drm/drm_client_modeset.c
+@@ -777,6 +777,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
+ unsigned int total_modes_count = 0;
+ struct drm_client_offset *offsets;
+ unsigned int connector_count = 0;
++ /* points to modes protected by mode_config.mutex */
+ struct drm_display_mode **modes;
+ struct drm_crtc **crtcs;
+ int i, ret = 0;
+@@ -845,7 +846,6 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
+ drm_client_pick_crtcs(client, connectors, connector_count,
+ crtcs, modes, 0, width, height);
+ }
+- mutex_unlock(&dev->mode_config.mutex);
+
+ drm_client_modeset_release(client);
+
+@@ -875,6 +875,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
+ modeset->y = offset->y;
+ }
+ }
++ mutex_unlock(&dev->mode_config.mutex);
+
+ mutex_unlock(&client->modeset_mutex);
+ out:
+diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
+index c985ebb6831a3..6e36a15284537 100644
+--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
++++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
+@@ -2521,7 +2521,7 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
+ if (IS_DG2(i915))
+ intel_cdclk_pcode_pre_notify(state);
+
+- if (pipe == INVALID_PIPE ||
++ if (new_cdclk_state->disable_pipes ||
+ old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) {
+ drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
+
+@@ -2553,7 +2553,7 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
+ if (IS_DG2(i915))
+ intel_cdclk_pcode_post_notify(state);
+
+- if (pipe != INVALID_PIPE &&
++ if (!new_cdclk_state->disable_pipes &&
+ old_cdclk_state->actual.cdclk > new_cdclk_state->actual.cdclk) {
+ drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
+
+@@ -3036,6 +3036,7 @@ static struct intel_global_state *intel_cdclk_duplicate_state(struct intel_globa
+ return NULL;
+
+ cdclk_state->pipe = INVALID_PIPE;
++ cdclk_state->disable_pipes = false;
+
+ return &cdclk_state->base;
+ }
+@@ -3214,6 +3215,8 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
+ if (ret)
+ return ret;
+
++ new_cdclk_state->disable_pipes = true;
++
+ drm_dbg_kms(&dev_priv->drm,
+ "Modeset required for cdclk change\n");
+ }
+diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h
+index 48fd7d39e0cd9..71bc032bfef16 100644
+--- a/drivers/gpu/drm/i915/display/intel_cdclk.h
++++ b/drivers/gpu/drm/i915/display/intel_cdclk.h
+@@ -51,6 +51,9 @@ struct intel_cdclk_state {
+
+ /* bitmask of active pipes */
+ u8 active_pipes;
++
++ /* update cdclk with pipes disabled */
++ bool disable_pipes;
+ };
+
+ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state);
+diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
+index 12a29363e5dfe..31aa5d54fdf07 100644
+--- a/drivers/gpu/drm/i915/display/intel_ddi.c
++++ b/drivers/gpu/drm/i915/display/intel_ddi.c
+@@ -4229,7 +4229,12 @@ static bool m_n_equal(const struct intel_link_m_n *m_n_1,
+ static bool crtcs_port_sync_compatible(const struct intel_crtc_state *crtc_state1,
+ const struct intel_crtc_state *crtc_state2)
+ {
++ /*
++ * FIXME the modeset sequence is currently wrong and
++ * can't deal with bigjoiner + port sync at the same time.
++ */
+ return crtc_state1->hw.active && crtc_state2->hw.active &&
++ !crtc_state1->bigjoiner_pipes && !crtc_state2->bigjoiner_pipes &&
+ crtc_state1->output_types == crtc_state2->output_types &&
+ crtc_state1->output_format == crtc_state2->output_format &&
+ crtc_state1->lane_count == crtc_state2->lane_count &&
+diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
+index 360e90601ff93..4e8545126e246 100644
+--- a/drivers/gpu/drm/i915/display/intel_dp.c
++++ b/drivers/gpu/drm/i915/display/intel_dp.c
+@@ -2756,7 +2756,11 @@ intel_dp_drrs_compute_config(struct intel_connector *connector,
+ intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode);
+ int pixel_clock;
+
+- if (has_seamless_m_n(connector))
++ /*
++ * FIXME all joined pipes share the same transcoder.
++ * Need to account for that when updating M/N live.
++ */
++ if (has_seamless_m_n(connector) && !pipe_config->bigjoiner_pipes)
+ pipe_config->update_m_n = true;
+
+ if (!can_enable_drrs(connector, pipe_config, downclock_mode)) {
+diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
+index 4faaf4b3fc53b..925776ba1392e 100644
+--- a/drivers/gpu/drm/i915/display/intel_psr.c
++++ b/drivers/gpu/drm/i915/display/intel_psr.c
+@@ -1368,6 +1368,17 @@ void intel_psr_compute_config(struct intel_dp *intel_dp,
+ return;
+ }
+
++ /*
++ * FIXME figure out what is wrong with PSR+bigjoiner and
++ * fix it. Presumably something related to the fact that
++ * PSR is a transcoder level feature.
++ */
++ if (crtc_state->bigjoiner_pipes) {
++ drm_dbg_kms(&dev_priv->drm,
++ "PSR disabled due to bigjoiner\n");
++ return;
++ }
++
+ if (CAN_PANEL_REPLAY(intel_dp))
+ crtc_state->has_panel_replay = true;
+ else
+diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
+index eb5bd07439020..f542ee1db1d97 100644
+--- a/drivers/gpu/drm/i915/display/intel_vrr.c
++++ b/drivers/gpu/drm/i915/display/intel_vrr.c
+@@ -117,6 +117,13 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state,
+ const struct drm_display_info *info = &connector->base.display_info;
+ int vmin, vmax;
+
++ /*
++ * FIXME all joined pipes share the same transcoder.
++ * Need to account for that during VRR toggle/push/etc.
++ */
++ if (crtc_state->bigjoiner_pipes)
++ return;
++
+ if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
+ return;
+
+diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+index fd60e49b8ec4d..792a4c60a20c2 100644
+--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
++++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+@@ -1295,6 +1295,10 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu)
+ if (adreno_is_a618(gpu))
+ gpu->ubwc_config.highest_bank_bit = 14;
+
++ if (adreno_is_a619(gpu))
++ /* TODO: Should be 14 but causes corruption at e.g. 1920x1200 on DP */
++ gpu->ubwc_config.highest_bank_bit = 13;
++
+ if (adreno_is_a619_holi(gpu))
+ gpu->ubwc_config.highest_bank_bit = 13;
+
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+index ef871239adb2a..68fae048a9a83 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+@@ -459,15 +459,15 @@ int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent)
+ &perf->core_clk_rate);
+ debugfs_create_u32("enable_bw_release", 0600, entry,
+ (u32 *)&perf->enable_bw_release);
+- debugfs_create_u32("threshold_low", 0600, entry,
++ debugfs_create_u32("threshold_low", 0400, entry,
+ (u32 *)&perf->perf_cfg->max_bw_low);
+- debugfs_create_u32("threshold_high", 0600, entry,
++ debugfs_create_u32("threshold_high", 0400, entry,
+ (u32 *)&perf->perf_cfg->max_bw_high);
+- debugfs_create_u32("min_core_ib", 0600, entry,
++ debugfs_create_u32("min_core_ib", 0400, entry,
+ (u32 *)&perf->perf_cfg->min_core_ib);
+- debugfs_create_u32("min_llcc_ib", 0600, entry,
++ debugfs_create_u32("min_llcc_ib", 0400, entry,
+ (u32 *)&perf->perf_cfg->min_llcc_ib);
+- debugfs_create_u32("min_dram_ib", 0600, entry,
++ debugfs_create_u32("min_dram_ib", 0400, entry,
+ (u32 *)&perf->perf_cfg->min_dram_ib);
+ debugfs_create_file("perf_mode", 0600, entry,
+ (u32 *)perf, &dpu_core_perf_mode_fops);
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+index 946dd0135dffc..6a0a74832fb64 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+@@ -525,14 +525,14 @@ int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms,
+ int ret;
+
+ if (!irq_cb) {
+- DPU_ERROR("invalid IRQ=[%d, %d] irq_cb:%ps\n",
+- DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb);
++ DPU_ERROR("IRQ=[%d, %d] NULL callback\n",
++ DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
+ return -EINVAL;
+ }
+
+ if (!dpu_core_irq_is_valid(irq_idx)) {
+- DPU_ERROR("invalid IRQ=[%d, %d]\n",
+- DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx));
++ DPU_ERROR("invalid IRQ=[%d, %d] irq_cb:%ps\n",
++ DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb);
+ return -EINVAL;
+ }
+
+diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
+index 4c72124ffb5d4..78464c395c3d9 100644
+--- a/drivers/gpu/drm/msm/dp/dp_display.c
++++ b/drivers/gpu/drm/msm/dp/dp_display.c
+@@ -598,6 +598,7 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
+ ret = dp_display_usbpd_configure_cb(&pdev->dev);
+ if (ret) { /* link train failed */
+ dp->hpd_state = ST_DISCONNECTED;
++ pm_runtime_put_sync(&pdev->dev);
+ } else {
+ dp->hpd_state = ST_MAINLINK_READY;
+ }
+@@ -655,6 +656,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
+ dp_display_host_phy_exit(dp);
+ dp->hpd_state = ST_DISCONNECTED;
+ dp_display_notify_disconnect(&dp->dp_display.pdev->dev);
++ pm_runtime_put_sync(&pdev->dev);
+ mutex_unlock(&dp->event_mutex);
+ return 0;
+ }
+diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
+index e3f61c39df69b..80166f702a0db 100644
+--- a/drivers/gpu/drm/msm/msm_fb.c
++++ b/drivers/gpu/drm/msm/msm_fb.c
+@@ -89,7 +89,7 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb,
+
+ for (i = 0; i < n; i++) {
+ ret = msm_gem_get_and_pin_iova(fb->obj[i], aspace, &msm_fb->iova[i]);
+- drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)",
++ drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)\n",
+ fb->base.id, i, msm_fb->iova[i], ret);
+ if (ret)
+ return ret;
+@@ -176,7 +176,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
+ const struct msm_format *format;
+ int ret, i, n;
+
+- drm_dbg_state(dev, "create framebuffer: mode_cmd=%p (%dx%d@%4.4s)",
++ drm_dbg_state(dev, "create framebuffer: mode_cmd=%p (%dx%d@%4.4s)\n",
+ mode_cmd, mode_cmd->width, mode_cmd->height,
+ (char *)&mode_cmd->pixel_format);
+
+@@ -232,7 +232,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev,
+
+ refcount_set(&msm_fb->dirtyfb, 1);
+
+- drm_dbg_state(dev, "create: FB ID: %d (%p)", fb->base.id, fb);
++ drm_dbg_state(dev, "create: FB ID: %d (%p)\n", fb->base.id, fb);
+
+ return fb;
+
+diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c
+index 84c21ec2ceeae..af6a6fcb11736 100644
+--- a/drivers/gpu/drm/msm/msm_kms.c
++++ b/drivers/gpu/drm/msm/msm_kms.c
+@@ -149,7 +149,7 @@ int msm_crtc_enable_vblank(struct drm_crtc *crtc)
+ struct msm_kms *kms = priv->kms;
+ if (!kms)
+ return -ENXIO;
+- drm_dbg_vbl(dev, "crtc=%u", crtc->base.id);
++ drm_dbg_vbl(dev, "crtc=%u\n", crtc->base.id);
+ return vblank_ctrl_queue_work(priv, crtc, true);
+ }
+
+@@ -160,7 +160,7 @@ void msm_crtc_disable_vblank(struct drm_crtc *crtc)
+ struct msm_kms *kms = priv->kms;
+ if (!kms)
+ return;
+- drm_dbg_vbl(dev, "crtc=%u", crtc->base.id);
++ drm_dbg_vbl(dev, "crtc=%u\n", crtc->base.id);
+ vblank_ctrl_queue_work(priv, crtc, false);
+ }
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
+index 4bf486b571013..cb05f7f48a98b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
+@@ -66,11 +66,16 @@ of_init(struct nvkm_bios *bios, const char *name)
+ return ERR_PTR(-EINVAL);
+ }
+
++static void of_fini(void *p)
++{
++ kfree(p);
++}
++
+ const struct nvbios_source
+ nvbios_of = {
+ .name = "OpenFirmware",
+ .init = of_init,
+- .fini = (void(*)(void *))kfree,
++ .fini = of_fini,
+ .read = of_read,
+ .size = of_size,
+ .rw = false,
+diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c
+index f38385fe76bbb..b91019cd5acb1 100644
+--- a/drivers/gpu/drm/panfrost/panfrost_mmu.c
++++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c
+@@ -502,11 +502,18 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
+ mapping_set_unevictable(mapping);
+
+ for (i = page_offset; i < page_offset + NUM_FAULT_PAGES; i++) {
++ /* Can happen if the last fault only partially filled this
++ * section of the pages array before failing. In that case
++ * we skip already filled pages.
++ */
++ if (pages[i])
++ continue;
++
+ pages[i] = shmem_read_mapping_page(mapping, i);
+ if (IS_ERR(pages[i])) {
+ ret = PTR_ERR(pages[i]);
+ pages[i] = NULL;
+- goto err_pages;
++ goto err_unlock;
+ }
+ }
+
+@@ -514,7 +521,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
+ ret = sg_alloc_table_from_pages(sgt, pages + page_offset,
+ NUM_FAULT_PAGES, 0, SZ_2M, GFP_KERNEL);
+ if (ret)
+- goto err_pages;
++ goto err_unlock;
+
+ ret = dma_map_sgtable(pfdev->dev, sgt, DMA_BIDIRECTIONAL, 0);
+ if (ret)
+@@ -537,8 +544,6 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
+
+ err_map:
+ sg_free_table(sgt);
+-err_pages:
+- drm_gem_shmem_put_pages(&bo->base);
+ err_unlock:
+ dma_resv_unlock(obj->resv);
+ err_bo:
+diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
+index 368d26da0d6a2..9febc8b73f09e 100644
+--- a/drivers/gpu/drm/qxl/qxl_release.c
++++ b/drivers/gpu/drm/qxl/qxl_release.c
+@@ -58,16 +58,56 @@ static long qxl_fence_wait(struct dma_fence *fence, bool intr,
+ signed long timeout)
+ {
+ struct qxl_device *qdev;
++ struct qxl_release *release;
++ int count = 0, sc = 0;
++ bool have_drawable_releases;
+ unsigned long cur, end = jiffies + timeout;
+
+ qdev = container_of(fence->lock, struct qxl_device, release_lock);
++ release = container_of(fence, struct qxl_release, base);
++ have_drawable_releases = release->type == QXL_RELEASE_DRAWABLE;
+
+- if (!wait_event_timeout(qdev->release_event,
+- (dma_fence_is_signaled(fence) ||
+- (qxl_io_notify_oom(qdev), 0)),
+- timeout))
+- return 0;
++retry:
++ sc++;
++
++ if (dma_fence_is_signaled(fence))
++ goto signaled;
++
++ qxl_io_notify_oom(qdev);
++
++ for (count = 0; count < 11; count++) {
++ if (!qxl_queue_garbage_collect(qdev, true))
++ break;
++
++ if (dma_fence_is_signaled(fence))
++ goto signaled;
++ }
++
++ if (dma_fence_is_signaled(fence))
++ goto signaled;
++
++ if (have_drawable_releases || sc < 4) {
++ if (sc > 2)
++ /* back off */
++ usleep_range(500, 1000);
++
++ if (time_after(jiffies, end))
++ return 0;
++
++ if (have_drawable_releases && sc > 300) {
++ DMA_FENCE_WARN(fence,
++ "failed to wait on release %llu after spincount %d\n",
++ fence->context & ~0xf0000000, sc);
++ goto signaled;
++ }
++ goto retry;
++ }
++ /*
++ * yeah, original sync_obj_wait gave up after 3 spins when
++ * have_drawable_releases is not set.
++ */
+
++signaled:
+ cur = jiffies;
+ if (time_after(cur, end))
+ return 0;
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+index c7d90f96d16a6..0a304706e0132 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+@@ -666,11 +666,12 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv)
+ [vmw_dma_map_populate] = "Caching DMA mappings.",
+ [vmw_dma_map_bind] = "Giving up DMA mappings early."};
+
+- /* TTM currently doesn't fully support SEV encryption. */
+- if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
+- return -EINVAL;
+-
+- if (vmw_force_coherent)
++ /*
++ * When running with SEV we always want dma mappings, because
++ * otherwise ttm tt pool pages will bounce through swiotlb running
++ * out of available space.
++ */
++ if (vmw_force_coherent || cc_platform_has(CC_ATTR_MEM_ENCRYPT))
+ dev_priv->map_mode = vmw_dma_alloc_coherent;
+ else if (vmw_restrict_iommu)
+ dev_priv->map_mode = vmw_dma_map_bind;
+diff --git a/drivers/gpu/drm/xe/xe_display.c b/drivers/gpu/drm/xe/xe_display.c
+index e4db069f0db3f..6ec375c1c4b6c 100644
+--- a/drivers/gpu/drm/xe/xe_display.c
++++ b/drivers/gpu/drm/xe/xe_display.c
+@@ -108,11 +108,6 @@ int xe_display_create(struct xe_device *xe)
+ xe->display.hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0);
+
+ drmm_mutex_init(&xe->drm, &xe->sb_lock);
+- drmm_mutex_init(&xe->drm, &xe->display.backlight.lock);
+- drmm_mutex_init(&xe->drm, &xe->display.audio.mutex);
+- drmm_mutex_init(&xe->drm, &xe->display.wm.wm_mutex);
+- drmm_mutex_init(&xe->drm, &xe->display.pps.mutex);
+- drmm_mutex_init(&xe->drm, &xe->display.hdcp.hdcp_mutex);
+ xe->enabled_irq_mask = ~0;
+
+ err = drmm_add_action_or_reset(&xe->drm, display_destroy, NULL);
+diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c
+index 174ed2185481e..a6f43446c779a 100644
+--- a/drivers/gpu/drm/xe/xe_hwmon.c
++++ b/drivers/gpu/drm/xe/xe_hwmon.c
+@@ -288,7 +288,7 @@ xe_hwmon_power1_max_interval_show(struct device *dev, struct device_attribute *a
+ * As y can be < 2, we compute tau4 = (4 | x) << y
+ * and then add 2 when doing the final right shift to account for units
+ */
+- tau4 = ((1 << x_w) | x) << y;
++ tau4 = (u64)((1 << x_w) | x) << y;
+
+ /* val in hwmon interface units (millisec) */
+ out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+@@ -328,7 +328,7 @@ xe_hwmon_power1_max_interval_store(struct device *dev, struct device_attribute *
+ r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
+ x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
+ y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
+- tau4 = ((1 << x_w) | x) << y;
++ tau4 = (u64)((1 << x_w) | x) << y;
+ max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+ if (val > max_win)
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index 5dba58f322f03..d7e10f1311aaf 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -4381,9 +4381,11 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev)
+ }
+
+ dev_iommu_priv_set(dev, info);
+- ret = device_rbtree_insert(iommu, info);
+- if (ret)
+- goto free;
++ if (pdev && pci_ats_supported(pdev)) {
++ ret = device_rbtree_insert(iommu, info);
++ if (ret)
++ goto free;
++ }
+
+ if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) {
+ ret = intel_pasid_alloc_table(dev);
+@@ -4410,7 +4412,8 @@ static void intel_iommu_release_device(struct device *dev)
+ struct intel_iommu *iommu = info->iommu;
+
+ mutex_lock(&iommu->iopf_lock);
+- device_rbtree_remove(info);
++ if (dev_is_pci(dev) && pci_ats_supported(to_pci_dev(dev)))
++ device_rbtree_remove(info);
+ mutex_unlock(&iommu->iopf_lock);
+
+ if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev) &&
+diff --git a/drivers/iommu/intel/perfmon.c b/drivers/iommu/intel/perfmon.c
+index cf43e798eca49..44083d01852db 100644
+--- a/drivers/iommu/intel/perfmon.c
++++ b/drivers/iommu/intel/perfmon.c
+@@ -438,7 +438,7 @@ static int iommu_pmu_assign_event(struct iommu_pmu *iommu_pmu,
+ iommu_pmu_set_filter(domain, event->attr.config1,
+ IOMMU_PMU_FILTER_DOMAIN, idx,
+ event->attr.config1);
+- iommu_pmu_set_filter(pasid, event->attr.config1,
++ iommu_pmu_set_filter(pasid, event->attr.config2,
+ IOMMU_PMU_FILTER_PASID, idx,
+ event->attr.config1);
+ iommu_pmu_set_filter(ats, event->attr.config2,
+diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
+index ec47ec81f0ecd..4d269df0082fb 100644
+--- a/drivers/iommu/intel/svm.c
++++ b/drivers/iommu/intel/svm.c
+@@ -67,7 +67,7 @@ int intel_svm_enable_prq(struct intel_iommu *iommu)
+ struct page *pages;
+ int irq, ret;
+
+- pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, PRQ_ORDER);
++ pages = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO, PRQ_ORDER);
+ if (!pages) {
+ pr_warn("IOMMU: %s: Failed to allocate page request queue\n",
+ iommu->name);
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 82c9bb404ccca..4f3c35f1320d4 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1474,7 +1474,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
+ for (j = 0; j < i; j++)
+ if (r1_bio->bios[j])
+ rdev_dec_pending(conf->mirrors[j].rdev, mddev);
+- free_r1bio(r1_bio);
++ mempool_free(r1_bio, &conf->r1bio_pool);
+ allow_barrier(conf, bio->bi_iter.bi_sector);
+
+ if (bio->bi_opf & REQ_NOWAIT) {
+diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c
+index 5741adf09a2ef..559a172ebc6cb 100644
+--- a/drivers/media/cec/core/cec-adap.c
++++ b/drivers/media/cec/core/cec-adap.c
+@@ -1151,20 +1151,6 @@ void cec_received_msg_ts(struct cec_adapter *adap,
+ if (valid_la && min_len) {
+ /* These messages have special length requirements */
+ switch (cmd) {
+- case CEC_MSG_TIMER_STATUS:
+- if (msg->msg[2] & 0x10) {
+- switch (msg->msg[2] & 0xf) {
+- case CEC_OP_PROG_INFO_NOT_ENOUGH_SPACE:
+- case CEC_OP_PROG_INFO_MIGHT_NOT_BE_ENOUGH_SPACE:
+- if (msg->len < 5)
+- valid_la = false;
+- break;
+- }
+- } else if ((msg->msg[2] & 0xf) == CEC_OP_PROG_ERROR_DUPLICATE) {
+- if (msg->len < 5)
+- valid_la = false;
+- }
+- break;
+ case CEC_MSG_RECORD_ON:
+ switch (msg->msg[2]) {
+ case CEC_OP_RECORD_SRC_OWN:
+diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
+index 9fb8995b43a1c..13fa8588e38c1 100644
+--- a/drivers/mmc/host/omap.c
++++ b/drivers/mmc/host/omap.c
+@@ -1119,10 +1119,25 @@ static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on,
+
+ host = slot->host;
+
+- if (slot->vsd)
+- gpiod_set_value(slot->vsd, power_on);
+- if (slot->vio)
+- gpiod_set_value(slot->vio, power_on);
++ if (power_on) {
++ if (slot->vsd) {
++ gpiod_set_value(slot->vsd, power_on);
++ msleep(1);
++ }
++ if (slot->vio) {
++ gpiod_set_value(slot->vio, power_on);
++ msleep(1);
++ }
++ } else {
++ if (slot->vio) {
++ gpiod_set_value(slot->vio, power_on);
++ msleep(50);
++ }
++ if (slot->vsd) {
++ gpiod_set_value(slot->vsd, power_on);
++ msleep(50);
++ }
++ }
+
+ if (slot->pdata->set_power != NULL)
+ slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on,
+@@ -1259,18 +1274,18 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id)
+ slot->pdata = &host->pdata->slots[id];
+
+ /* Check for some optional GPIO controls */
+- slot->vsd = gpiod_get_index_optional(host->dev, "vsd",
+- id, GPIOD_OUT_LOW);
++ slot->vsd = devm_gpiod_get_index_optional(host->dev, "vsd",
++ id, GPIOD_OUT_LOW);
+ if (IS_ERR(slot->vsd))
+ return dev_err_probe(host->dev, PTR_ERR(slot->vsd),
+ "error looking up VSD GPIO\n");
+- slot->vio = gpiod_get_index_optional(host->dev, "vio",
+- id, GPIOD_OUT_LOW);
++ slot->vio = devm_gpiod_get_index_optional(host->dev, "vio",
++ id, GPIOD_OUT_LOW);
+ if (IS_ERR(slot->vio))
+ return dev_err_probe(host->dev, PTR_ERR(slot->vio),
+ "error looking up VIO GPIO\n");
+- slot->cover = gpiod_get_index_optional(host->dev, "cover",
+- id, GPIOD_IN);
++ slot->cover = devm_gpiod_get_index_optional(host->dev, "cover",
++ id, GPIOD_IN);
+ if (IS_ERR(slot->cover))
+ return dev_err_probe(host->dev, PTR_ERR(slot->cover),
+ "error looking up cover switch GPIO\n");
+@@ -1384,13 +1399,6 @@ static int mmc_omap_probe(struct platform_device *pdev)
+ if (IS_ERR(host->virt_base))
+ return PTR_ERR(host->virt_base);
+
+- host->slot_switch = gpiod_get_optional(host->dev, "switch",
+- GPIOD_OUT_LOW);
+- if (IS_ERR(host->slot_switch))
+- return dev_err_probe(host->dev, PTR_ERR(host->slot_switch),
+- "error looking up slot switch GPIO\n");
+-
+-
+ INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work);
+ INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work);
+
+@@ -1409,6 +1417,12 @@ static int mmc_omap_probe(struct platform_device *pdev)
+ host->dev = &pdev->dev;
+ platform_set_drvdata(pdev, host);
+
++ host->slot_switch = devm_gpiod_get_optional(host->dev, "switch",
++ GPIOD_OUT_LOW);
++ if (IS_ERR(host->slot_switch))
++ return dev_err_probe(host->dev, PTR_ERR(host->slot_switch),
++ "error looking up slot switch GPIO\n");
++
+ host->id = pdev->id;
+ host->irq = irq;
+ host->phys_base = res->start;
+diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
+index 40ae44c9945b1..22b97505fa536 100644
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -998,20 +998,173 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)
+ mutex_unlock(&priv->reg_mutex);
+ }
+
+-/* On page 205, section "8.6.3 Frame filtering" of the active standard, IEEE Std
+- * 802.1Q™-2022, it is stated that frames with 01:80:C2:00:00:00-0F as MAC DA
+- * must only be propagated to C-VLAN and MAC Bridge components. That means
+- * VLAN-aware and VLAN-unaware bridges. On the switch designs with CPU ports,
+- * these frames are supposed to be processed by the CPU (software). So we make
+- * the switch only forward them to the CPU port. And if received from a CPU
+- * port, forward to a single port. The software is responsible of making the
+- * switch conform to the latter by setting a single port as destination port on
+- * the special tag.
++/* In Clause 5 of IEEE Std 802-2014, two sublayers of the data link layer (DLL)
++ * of the Open Systems Interconnection basic reference model (OSI/RM) are
++ * described; the medium access control (MAC) and logical link control (LLC)
++ * sublayers. The MAC sublayer is the one facing the physical layer.
+ *
+- * This switch intellectual property cannot conform to this part of the standard
+- * fully. Whilst the REV_UN frame tag covers the remaining :04-0D and :0F MAC
+- * DAs, it also includes :22-FF which the scope of propagation is not supposed
+- * to be restricted for these MAC DAs.
++ * In 8.2 of IEEE Std 802.1Q-2022, the Bridge architecture is described. A
++ * Bridge component comprises a MAC Relay Entity for interconnecting the Ports
++ * of the Bridge, at least two Ports, and higher layer entities with at least a
++ * Spanning Tree Protocol Entity included.
++ *
++ * Each Bridge Port also functions as an end station and shall provide the MAC
++ * Service to an LLC Entity. Each instance of the MAC Service is provided to a
++ * distinct LLC Entity that supports protocol identification, multiplexing, and
++ * demultiplexing, for protocol data unit (PDU) transmission and reception by
++ * one or more higher layer entities.
++ *
++ * It is described in 8.13.9 of IEEE Std 802.1Q-2022 that in a Bridge, the LLC
++ * Entity associated with each Bridge Port is modeled as being directly
++ * connected to the attached Local Area Network (LAN).
++ *
++ * On the switch with CPU port architecture, CPU port functions as Management
++ * Port, and the Management Port functionality is provided by software which
++ * functions as an end station. Software is connected to an IEEE 802 LAN that is
++ * wholly contained within the system that incorporates the Bridge. Software
++ * provides access to the LLC Entity associated with each Bridge Port by the
++ * value of the source port field on the special tag on the frame received by
++ * software.
++ *
++ * We call frames that carry control information to determine the active
++ * topology and current extent of each Virtual Local Area Network (VLAN), i.e.,
++ * spanning tree or Shortest Path Bridging (SPB) and Multiple VLAN Registration
++ * Protocol Data Units (MVRPDUs), and frames from other link constrained
++ * protocols, such as Extensible Authentication Protocol over LAN (EAPOL) and
++ * Link Layer Discovery Protocol (LLDP), link-local frames. They are not
++ * forwarded by a Bridge. Permanently configured entries in the filtering
++ * database (FDB) ensure that such frames are discarded by the Forwarding
++ * Process. In 8.6.3 of IEEE Std 802.1Q-2022, this is described in detail:
++ *
++ * Each of the reserved MAC addresses specified in Table 8-1
++ * (01-80-C2-00-00-[00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F]) shall be
++ * permanently configured in the FDB in C-VLAN components and ERs.
++ *
++ * Each of the reserved MAC addresses specified in Table 8-2
++ * (01-80-C2-00-00-[01,02,03,04,05,06,07,08,09,0A,0E]) shall be permanently
++ * configured in the FDB in S-VLAN components.
++ *
++ * Each of the reserved MAC addresses specified in Table 8-3
++ * (01-80-C2-00-00-[01,02,04,0E]) shall be permanently configured in the FDB in
++ * TPMR components.
++ *
++ * The FDB entries for reserved MAC addresses shall specify filtering for all
++ * Bridge Ports and all VIDs. Management shall not provide the capability to
++ * modify or remove entries for reserved MAC addresses.
++ *
++ * The addresses in Table 8-1, Table 8-2, and Table 8-3 determine the scope of
++ * propagation of PDUs within a Bridged Network, as follows:
++ *
++ * The Nearest Bridge group address (01-80-C2-00-00-0E) is an address that no
++ * conformant Two-Port MAC Relay (TPMR) component, Service VLAN (S-VLAN)
++ * component, Customer VLAN (C-VLAN) component, or MAC Bridge can forward.
++ * PDUs transmitted using this destination address, or any other addresses
++ * that appear in Table 8-1, Table 8-2, and Table 8-3
++ * (01-80-C2-00-00-[00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F]), can
++ * therefore travel no further than those stations that can be reached via a
++ * single individual LAN from the originating station.
++ *
++ * The Nearest non-TPMR Bridge group address (01-80-C2-00-00-03), is an
++ * address that no conformant S-VLAN component, C-VLAN component, or MAC
++ * Bridge can forward; however, this address is relayed by a TPMR component.
++ * PDUs using this destination address, or any of the other addresses that
++ * appear in both Table 8-1 and Table 8-2 but not in Table 8-3
++ * (01-80-C2-00-00-[00,03,05,06,07,08,09,0A,0B,0C,0D,0F]), will be relayed by
++ * any TPMRs but will propagate no further than the nearest S-VLAN component,
++ * C-VLAN component, or MAC Bridge.
++ *
++ * The Nearest Customer Bridge group address (01-80-C2-00-00-00) is an address
++ * that no conformant C-VLAN component, MAC Bridge can forward; however, it is
++ * relayed by TPMR components and S-VLAN components. PDUs using this
++ * destination address, or any of the other addresses that appear in Table 8-1
++ * but not in either Table 8-2 or Table 8-3 (01-80-C2-00-00-[00,0B,0C,0D,0F]),
++ * will be relayed by TPMR components and S-VLAN components but will propagate
++ * no further than the nearest C-VLAN component or MAC Bridge.
++ *
++ * Because the LLC Entity associated with each Bridge Port is provided via CPU
++ * port, we must not filter these frames but forward them to CPU port.
++ *
++ * In a Bridge, the transmission Port is majorly decided by ingress and egress
++ * rules, FDB, and spanning tree Port State functions of the Forwarding Process.
++ * For link-local frames, only CPU port should be designated as destination port
++ * in the FDB, and the other functions of the Forwarding Process must not
++ * interfere with the decision of the transmission Port. We call this process
++ * trapping frames to CPU port.
++ *
++ * Therefore, on the switch with CPU port architecture, link-local frames must
++ * be trapped to CPU port, and certain link-local frames received by a Port of a
++ * Bridge comprising a TPMR component or an S-VLAN component must be excluded
++ * from it.
++ *
++ * A Bridge of the switch with CPU port architecture cannot comprise a Two-Port
++ * MAC Relay (TPMR) component as a TPMR component supports only a subset of the
++ * functionality of a MAC Bridge. A Bridge comprising two Ports (Management Port
++ * doesn't count) of this architecture will either function as a standard MAC
++ * Bridge or a standard VLAN Bridge.
++ *
++ * Therefore, a Bridge of this architecture can only comprise S-VLAN components,
++ * C-VLAN components, or MAC Bridge components. Since there's no TPMR component,
++ * we don't need to relay PDUs using the destination addresses specified on the
++ * Nearest non-TPMR section, and the proportion of the Nearest Customer Bridge
++ * section where they must be relayed by TPMR components.
++ *
++ * One option to trap link-local frames to CPU port is to add static FDB entries
++ * with CPU port designated as destination port. However, because that
++ * Independent VLAN Learning (IVL) is being used on every VID, each entry only
++ * applies to a single VLAN Identifier (VID). For a Bridge comprising a MAC
++ * Bridge component or a C-VLAN component, there would have to be 16 times 4096
++ * entries. This switch intellectual property can only hold a maximum of 2048
++ * entries. Using this option, there also isn't a mechanism to prevent
++ * link-local frames from being discarded when the spanning tree Port State of
++ * the reception Port is discarding.
++ *
++ * The remaining option is to utilise the BPC, RGAC1, RGAC2, RGAC3, and RGAC4
++ * registers. Whilst this applies to every VID, it doesn't contain all of the
++ * reserved MAC addresses without affecting the remaining Standard Group MAC
++ * Addresses. The REV_UN frame tag utilised using the RGAC4 register covers the
++ * remaining 01-80-C2-00-00-[04,05,06,07,08,09,0A,0B,0C,0D,0F] destination
++ * addresses. It also includes the 01-80-C2-00-00-22 to 01-80-C2-00-00-FF
++ * destination addresses which may be relayed by MAC Bridges or VLAN Bridges.
++ * The latter option provides better but not complete conformance.
++ *
++ * This switch intellectual property also does not provide a mechanism to trap
++ * link-local frames with specific destination addresses to CPU port by Bridge,
++ * to conform to the filtering rules for the distinct Bridge components.
++ *
++ * Therefore, regardless of the type of the Bridge component, link-local frames
++ * with these destination addresses will be trapped to CPU port:
++ *
++ * 01-80-C2-00-00-[00,01,02,03,0E]
++ *
++ * In a Bridge comprising a MAC Bridge component or a C-VLAN component:
++ *
++ * Link-local frames with these destination addresses won't be trapped to CPU
++ * port which won't conform to IEEE Std 802.1Q-2022:
++ *
++ * 01-80-C2-00-00-[04,05,06,07,08,09,0A,0B,0C,0D,0F]
++ *
++ * In a Bridge comprising an S-VLAN component:
++ *
++ * Link-local frames with these destination addresses will be trapped to CPU
++ * port which won't conform to IEEE Std 802.1Q-2022:
++ *
++ * 01-80-C2-00-00-00
++ *
++ * Link-local frames with these destination addresses won't be trapped to CPU
++ * port which won't conform to IEEE Std 802.1Q-2022:
++ *
++ * 01-80-C2-00-00-[04,05,06,07,08,09,0A]
++ *
++ * To trap link-local frames to CPU port as conformant as this switch
++ * intellectual property can allow, link-local frames are made to be regarded as
++ * Bridge Protocol Data Units (BPDUs). This is because this switch intellectual
++ * property only lets the frames regarded as BPDUs bypass the spanning tree Port
++ * State function of the Forwarding Process.
++ *
++ * The only remaining interference is the ingress rules. When the reception Port
++ * has no PVID assigned on software, VLAN-untagged frames won't be allowed in.
++ * There doesn't seem to be a mechanism on the switch intellectual property to
++ * have link-local frames bypass this function of the Forwarding Process.
+ */
+ static void
+ mt753x_trap_frames(struct mt7530_priv *priv)
+@@ -1019,35 +1172,43 @@ mt753x_trap_frames(struct mt7530_priv *priv)
+ /* Trap 802.1X PAE frames and BPDUs to the CPU port(s) and egress them
+ * VLAN-untagged.
+ */
+- mt7530_rmw(priv, MT753X_BPC, MT753X_PAE_EG_TAG_MASK |
+- MT753X_PAE_PORT_FW_MASK | MT753X_BPDU_EG_TAG_MASK |
+- MT753X_BPDU_PORT_FW_MASK,
+- MT753X_PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+- MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY) |
+- MT753X_BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+- MT753X_BPDU_CPU_ONLY);
++ mt7530_rmw(priv, MT753X_BPC,
++ MT753X_PAE_BPDU_FR | MT753X_PAE_EG_TAG_MASK |
++ MT753X_PAE_PORT_FW_MASK | MT753X_BPDU_EG_TAG_MASK |
++ MT753X_BPDU_PORT_FW_MASK,
++ MT753X_PAE_BPDU_FR |
++ MT753X_PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY) |
++ MT753X_BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_BPDU_CPU_ONLY);
+
+ /* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and egress
+ * them VLAN-untagged.
+ */
+- mt7530_rmw(priv, MT753X_RGAC1, MT753X_R02_EG_TAG_MASK |
+- MT753X_R02_PORT_FW_MASK | MT753X_R01_EG_TAG_MASK |
+- MT753X_R01_PORT_FW_MASK,
+- MT753X_R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+- MT753X_R02_PORT_FW(MT753X_BPDU_CPU_ONLY) |
+- MT753X_R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+- MT753X_BPDU_CPU_ONLY);
++ mt7530_rmw(priv, MT753X_RGAC1,
++ MT753X_R02_BPDU_FR | MT753X_R02_EG_TAG_MASK |
++ MT753X_R02_PORT_FW_MASK | MT753X_R01_BPDU_FR |
++ MT753X_R01_EG_TAG_MASK | MT753X_R01_PORT_FW_MASK,
++ MT753X_R02_BPDU_FR |
++ MT753X_R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_R02_PORT_FW(MT753X_BPDU_CPU_ONLY) |
++ MT753X_R01_BPDU_FR |
++ MT753X_R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_BPDU_CPU_ONLY);
+
+ /* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and egress
+ * them VLAN-untagged.
+ */
+- mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_EG_TAG_MASK |
+- MT753X_R0E_PORT_FW_MASK | MT753X_R03_EG_TAG_MASK |
+- MT753X_R03_PORT_FW_MASK,
+- MT753X_R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+- MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY) |
+- MT753X_R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+- MT753X_BPDU_CPU_ONLY);
++ mt7530_rmw(priv, MT753X_RGAC2,
++ MT753X_R0E_BPDU_FR | MT753X_R0E_EG_TAG_MASK |
++ MT753X_R0E_PORT_FW_MASK | MT753X_R03_BPDU_FR |
++ MT753X_R03_EG_TAG_MASK | MT753X_R03_PORT_FW_MASK,
++ MT753X_R0E_BPDU_FR |
++ MT753X_R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY) |
++ MT753X_R03_BPDU_FR |
++ MT753X_R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
++ MT753X_BPDU_CPU_ONLY);
+ }
+
+ static int
+diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
+index 75bc9043c8c0a..ddefeb69afda1 100644
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -65,6 +65,7 @@ enum mt753x_id {
+
+ /* Registers for BPDU and PAE frame control*/
+ #define MT753X_BPC 0x24
++#define MT753X_PAE_BPDU_FR BIT(25)
+ #define MT753X_PAE_EG_TAG_MASK GENMASK(24, 22)
+ #define MT753X_PAE_EG_TAG(x) FIELD_PREP(MT753X_PAE_EG_TAG_MASK, x)
+ #define MT753X_PAE_PORT_FW_MASK GENMASK(18, 16)
+@@ -75,20 +76,24 @@ enum mt753x_id {
+
+ /* Register for :01 and :02 MAC DA frame control */
+ #define MT753X_RGAC1 0x28
++#define MT753X_R02_BPDU_FR BIT(25)
+ #define MT753X_R02_EG_TAG_MASK GENMASK(24, 22)
+ #define MT753X_R02_EG_TAG(x) FIELD_PREP(MT753X_R02_EG_TAG_MASK, x)
+ #define MT753X_R02_PORT_FW_MASK GENMASK(18, 16)
+ #define MT753X_R02_PORT_FW(x) FIELD_PREP(MT753X_R02_PORT_FW_MASK, x)
++#define MT753X_R01_BPDU_FR BIT(9)
+ #define MT753X_R01_EG_TAG_MASK GENMASK(8, 6)
+ #define MT753X_R01_EG_TAG(x) FIELD_PREP(MT753X_R01_EG_TAG_MASK, x)
+ #define MT753X_R01_PORT_FW_MASK GENMASK(2, 0)
+
+ /* Register for :03 and :0E MAC DA frame control */
+ #define MT753X_RGAC2 0x2c
++#define MT753X_R0E_BPDU_FR BIT(25)
+ #define MT753X_R0E_EG_TAG_MASK GENMASK(24, 22)
+ #define MT753X_R0E_EG_TAG(x) FIELD_PREP(MT753X_R0E_EG_TAG_MASK, x)
+ #define MT753X_R0E_PORT_FW_MASK GENMASK(18, 16)
+ #define MT753X_R0E_PORT_FW(x) FIELD_PREP(MT753X_R0E_PORT_FW_MASK, x)
++#define MT753X_R03_BPDU_FR BIT(9)
+ #define MT753X_R03_EG_TAG_MASK GENMASK(8, 6)
+ #define MT753X_R03_EG_TAG(x) FIELD_PREP(MT753X_R03_EG_TAG_MASK, x)
+ #define MT753X_R03_PORT_FW_MASK GENMASK(2, 0)
+diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c
+index 633b321d7fdd9..4db689372980e 100644
+--- a/drivers/net/ethernet/amazon/ena/ena_com.c
++++ b/drivers/net/ethernet/amazon/ena/ena_com.c
+@@ -362,7 +362,7 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev,
+ ENA_COM_BOUNCE_BUFFER_CNTRL_CNT;
+ io_sq->bounce_buf_ctrl.next_to_use = 0;
+
+- size = io_sq->bounce_buf_ctrl.buffer_size *
++ size = (size_t)io_sq->bounce_buf_ctrl.buffer_size *
+ io_sq->bounce_buf_ctrl.buffers_num;
+
+ dev_node = dev_to_node(ena_dev->dmadev);
+diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
+index 5482015411f2f..95ed32542edfe 100644
+--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
++++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
+@@ -696,8 +696,11 @@ void ena_unmap_tx_buff(struct ena_ring *tx_ring,
+ static void ena_free_tx_bufs(struct ena_ring *tx_ring)
+ {
+ bool print_once = true;
++ bool is_xdp_ring;
+ u32 i;
+
++ is_xdp_ring = ENA_IS_XDP_INDEX(tx_ring->adapter, tx_ring->qid);
++
+ for (i = 0; i < tx_ring->ring_size; i++) {
+ struct ena_tx_buffer *tx_info = &tx_ring->tx_buffer_info[i];
+
+@@ -717,10 +720,15 @@ static void ena_free_tx_bufs(struct ena_ring *tx_ring)
+
+ ena_unmap_tx_buff(tx_ring, tx_info);
+
+- dev_kfree_skb_any(tx_info->skb);
++ if (is_xdp_ring)
++ xdp_return_frame(tx_info->xdpf);
++ else
++ dev_kfree_skb_any(tx_info->skb);
+ }
+- netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev,
+- tx_ring->qid));
++
++ if (!is_xdp_ring)
++ netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev,
++ tx_ring->qid));
+ }
+
+ static void ena_free_all_tx_bufs(struct ena_adapter *adapter)
+@@ -3421,10 +3429,11 @@ static void check_for_missing_completions(struct ena_adapter *adapter)
+ {
+ struct ena_ring *tx_ring;
+ struct ena_ring *rx_ring;
+- int i, budget, rc;
++ int qid, budget, rc;
+ int io_queue_count;
+
+ io_queue_count = adapter->xdp_num_queues + adapter->num_io_queues;
++
+ /* Make sure the driver doesn't turn the device in other process */
+ smp_rmb();
+
+@@ -3437,27 +3446,29 @@ static void check_for_missing_completions(struct ena_adapter *adapter)
+ if (adapter->missing_tx_completion_to == ENA_HW_HINTS_NO_TIMEOUT)
+ return;
+
+- budget = ENA_MONITORED_TX_QUEUES;
++ budget = min_t(u32, io_queue_count, ENA_MONITORED_TX_QUEUES);
+
+- for (i = adapter->last_monitored_tx_qid; i < io_queue_count; i++) {
+- tx_ring = &adapter->tx_ring[i];
+- rx_ring = &adapter->rx_ring[i];
++ qid = adapter->last_monitored_tx_qid;
++
++ while (budget) {
++ qid = (qid + 1) % io_queue_count;
++
++ tx_ring = &adapter->tx_ring[qid];
++ rx_ring = &adapter->rx_ring[qid];
+
+ rc = check_missing_comp_in_tx_queue(adapter, tx_ring);
+ if (unlikely(rc))
+ return;
+
+- rc = !ENA_IS_XDP_INDEX(adapter, i) ?
++ rc = !ENA_IS_XDP_INDEX(adapter, qid) ?
+ check_for_rx_interrupt_queue(adapter, rx_ring) : 0;
+ if (unlikely(rc))
+ return;
+
+ budget--;
+- if (!budget)
+- break;
+ }
+
+- adapter->last_monitored_tx_qid = i % io_queue_count;
++ adapter->last_monitored_tx_qid = qid;
+ }
+
+ /* trigger napi schedule after 2 consecutive detections */
+diff --git a/drivers/net/ethernet/amazon/ena/ena_xdp.c b/drivers/net/ethernet/amazon/ena/ena_xdp.c
+index fc1c4ef73ba32..34d73c72f7803 100644
+--- a/drivers/net/ethernet/amazon/ena/ena_xdp.c
++++ b/drivers/net/ethernet/amazon/ena/ena_xdp.c
+@@ -89,7 +89,7 @@ int ena_xdp_xmit_frame(struct ena_ring *tx_ring,
+
+ rc = ena_xdp_tx_map_frame(tx_ring, tx_info, xdpf, &ena_tx_ctx);
+ if (unlikely(rc))
+- return rc;
++ goto err;
+
+ ena_tx_ctx.req_id = req_id;
+
+@@ -112,7 +112,9 @@ int ena_xdp_xmit_frame(struct ena_ring *tx_ring,
+
+ error_unmap_dma:
+ ena_unmap_tx_buff(tx_ring, tx_info);
++err:
+ tx_info->xdpf = NULL;
++
+ return rc;
+ }
+
+diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c
+index 7658a72867675..dd4f0965bbe64 100644
+--- a/drivers/net/ethernet/amd/pds_core/core.c
++++ b/drivers/net/ethernet/amd/pds_core/core.c
+@@ -595,6 +595,16 @@ void pdsc_fw_up(struct pdsc *pdsc)
+ pdsc_teardown(pdsc, PDSC_TEARDOWN_RECOVERY);
+ }
+
++void pdsc_pci_reset_thread(struct work_struct *work)
++{
++ struct pdsc *pdsc = container_of(work, struct pdsc, pci_reset_work);
++ struct pci_dev *pdev = pdsc->pdev;
++
++ pci_dev_get(pdev);
++ pci_reset_function(pdev);
++ pci_dev_put(pdev);
++}
++
+ static void pdsc_check_pci_health(struct pdsc *pdsc)
+ {
+ u8 fw_status;
+@@ -609,8 +619,8 @@ static void pdsc_check_pci_health(struct pdsc *pdsc)
+ if (fw_status != PDS_RC_BAD_PCI)
+ return;
+
+- pdsc_reset_prepare(pdsc->pdev);
+- pdsc_reset_done(pdsc->pdev);
++ /* prevent deadlock between pdsc_reset_prepare and pdsc_health_thread */
++ queue_work(pdsc->wq, &pdsc->pci_reset_work);
+ }
+
+ void pdsc_health_thread(struct work_struct *work)
+diff --git a/drivers/net/ethernet/amd/pds_core/core.h b/drivers/net/ethernet/amd/pds_core/core.h
+index 110c4b826b22d..401ff56eba0dc 100644
+--- a/drivers/net/ethernet/amd/pds_core/core.h
++++ b/drivers/net/ethernet/amd/pds_core/core.h
+@@ -197,6 +197,7 @@ struct pdsc {
+ struct pdsc_qcq notifyqcq;
+ u64 last_eid;
+ struct pdsc_viftype *viftype_status;
++ struct work_struct pci_reset_work;
+ };
+
+ /** enum pds_core_dbell_bits - bitwise composition of dbell values.
+@@ -283,9 +284,6 @@ int pdsc_devcmd_init(struct pdsc *pdsc);
+ int pdsc_devcmd_reset(struct pdsc *pdsc);
+ int pdsc_dev_init(struct pdsc *pdsc);
+
+-void pdsc_reset_prepare(struct pci_dev *pdev);
+-void pdsc_reset_done(struct pci_dev *pdev);
+-
+ int pdsc_intr_alloc(struct pdsc *pdsc, char *name,
+ irq_handler_t handler, void *data);
+ void pdsc_intr_free(struct pdsc *pdsc, int index);
+@@ -315,5 +313,6 @@ int pdsc_firmware_update(struct pdsc *pdsc, const struct firmware *fw,
+
+ void pdsc_fw_down(struct pdsc *pdsc);
+ void pdsc_fw_up(struct pdsc *pdsc);
++void pdsc_pci_reset_thread(struct work_struct *work);
+
+ #endif /* _PDSC_H_ */
+diff --git a/drivers/net/ethernet/amd/pds_core/dev.c b/drivers/net/ethernet/amd/pds_core/dev.c
+index e65a1632df505..bfb79c5aac391 100644
+--- a/drivers/net/ethernet/amd/pds_core/dev.c
++++ b/drivers/net/ethernet/amd/pds_core/dev.c
+@@ -229,6 +229,9 @@ int pdsc_devcmd_reset(struct pdsc *pdsc)
+ .reset.opcode = PDS_CORE_CMD_RESET,
+ };
+
++ if (!pdsc_is_fw_running(pdsc))
++ return 0;
++
+ return pdsc_devcmd(pdsc, &cmd, &comp, pdsc->devcmd_timeout);
+ }
+
+diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c
+index 0050c5894563b..a375d612d2875 100644
+--- a/drivers/net/ethernet/amd/pds_core/main.c
++++ b/drivers/net/ethernet/amd/pds_core/main.c
+@@ -238,6 +238,7 @@ static int pdsc_init_pf(struct pdsc *pdsc)
+ snprintf(wq_name, sizeof(wq_name), "%s.%d", PDS_CORE_DRV_NAME, pdsc->uid);
+ pdsc->wq = create_singlethread_workqueue(wq_name);
+ INIT_WORK(&pdsc->health_work, pdsc_health_thread);
++ INIT_WORK(&pdsc->pci_reset_work, pdsc_pci_reset_thread);
+ timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0);
+ pdsc->wdtimer_period = PDSC_WATCHDOG_SECS * HZ;
+
+@@ -468,7 +469,7 @@ static void pdsc_restart_health_thread(struct pdsc *pdsc)
+ mod_timer(&pdsc->wdtimer, jiffies + 1);
+ }
+
+-void pdsc_reset_prepare(struct pci_dev *pdev)
++static void pdsc_reset_prepare(struct pci_dev *pdev)
+ {
+ struct pdsc *pdsc = pci_get_drvdata(pdev);
+
+@@ -477,10 +478,11 @@ void pdsc_reset_prepare(struct pci_dev *pdev)
+
+ pdsc_unmap_bars(pdsc);
+ pci_release_regions(pdev);
+- pci_disable_device(pdev);
++ if (pci_is_enabled(pdev))
++ pci_disable_device(pdev);
+ }
+
+-void pdsc_reset_done(struct pci_dev *pdev)
++static void pdsc_reset_done(struct pci_dev *pdev)
+ {
+ struct pdsc *pdsc = pci_get_drvdata(pdev);
+ struct device *dev = pdsc->dev;
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 39845d556bafc..5e6e32d708e24 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -11526,6 +11526,8 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
+ /* VF-reps may need to be re-opened after the PF is re-opened */
+ if (BNXT_PF(bp))
+ bnxt_vf_reps_open(bp);
++ if (bp->ptp_cfg)
++ atomic_set(&bp->ptp_cfg->tx_avail, BNXT_MAX_TX_TS);
+ bnxt_ptp_init_rtc(bp, true);
+ bnxt_ptp_cfg_tstamp_filters(bp);
+ return 0;
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+index 93f9bd55020f2..195c02dc06830 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+@@ -210,6 +210,9 @@ void bnxt_ulp_start(struct bnxt *bp, int err)
+ if (err)
+ return;
+
++ if (edev->ulp_tbl->msix_requested)
++ bnxt_fill_msix_vecs(bp, edev->msix_entries);
++
+ if (aux_priv) {
+ struct auxiliary_device *adev;
+
+@@ -392,12 +395,13 @@ void bnxt_rdma_aux_device_init(struct bnxt *bp)
+ if (!edev)
+ goto aux_dev_uninit;
+
++ aux_priv->edev = edev;
++
+ ulp = kzalloc(sizeof(*ulp), GFP_KERNEL);
+ if (!ulp)
+ goto aux_dev_uninit;
+
+ edev->ulp_tbl = ulp;
+- aux_priv->edev = edev;
+ bp->edev = edev;
+ bnxt_set_edev_info(edev, bp);
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+index 66203a90f052b..42db213fb69a6 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+@@ -4721,18 +4721,18 @@ static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw)
+ */
+ rvu_write64(rvu, blkaddr, NIX_AF_CFG,
+ rvu_read64(rvu, blkaddr, NIX_AF_CFG) | 0x40ULL);
++ }
+
+- /* Set chan/link to backpressure TL3 instead of TL2 */
+- rvu_write64(rvu, blkaddr, NIX_AF_PSE_CHANNEL_LEVEL, 0x01);
++ /* Set chan/link to backpressure TL3 instead of TL2 */
++ rvu_write64(rvu, blkaddr, NIX_AF_PSE_CHANNEL_LEVEL, 0x01);
+
+- /* Disable SQ manager's sticky mode operation (set TM6 = 0)
+- * This sticky mode is known to cause SQ stalls when multiple
+- * SQs are mapped to same SMQ and transmitting pkts at a time.
+- */
+- cfg = rvu_read64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS);
+- cfg &= ~BIT_ULL(15);
+- rvu_write64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS, cfg);
+- }
++ /* Disable SQ manager's sticky mode operation (set TM6 = 0)
++ * This sticky mode is known to cause SQ stalls when multiple
++ * SQs are mapped to same SMQ and transmitting pkts at a time.
++ */
++ cfg = rvu_read64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS);
++ cfg &= ~BIT_ULL(15);
++ rvu_write64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS, cfg);
+
+ ltdefs = rvu->kpu.lt_def;
+ /* Calibrate X2P bus to check if CGX/LBK links are fine */
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
+index 1e77bbf5d22a1..1723e9912ae07 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c
+@@ -382,6 +382,7 @@ static void otx2_qos_read_txschq_cfg_tl(struct otx2_qos_node *parent,
+ otx2_qos_read_txschq_cfg_tl(node, cfg);
+ cnt = cfg->static_node_pos[node->level];
+ cfg->schq_contig_list[node->level][cnt] = node->schq;
++ cfg->schq_index_used[node->level][cnt] = true;
+ cfg->schq_contig[node->level]++;
+ cfg->static_node_pos[node->level]++;
+ otx2_qos_read_txschq_cfg_schq(node, cfg);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h
+index 86f1854698b4e..883c044852f1d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h
+@@ -95,9 +95,15 @@ static inline void mlx5e_ptp_metadata_fifo_push(struct mlx5e_ptp_metadata_fifo *
+ }
+
+ static inline u8
++mlx5e_ptp_metadata_fifo_peek(struct mlx5e_ptp_metadata_fifo *fifo)
++{
++ return fifo->data[fifo->mask & fifo->cc];
++}
++
++static inline void
+ mlx5e_ptp_metadata_fifo_pop(struct mlx5e_ptp_metadata_fifo *fifo)
+ {
+- return fifo->data[fifo->mask & fifo->cc++];
++ fifo->cc++;
+ }
+
+ static inline void
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
+index 34adf8c3f81a0..922bc5b7c10e3 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
+@@ -83,24 +83,25 @@ int mlx5e_open_qos_sq(struct mlx5e_priv *priv, struct mlx5e_channels *chs,
+
+ txq_ix = mlx5e_qid_from_qos(chs, node_qid);
+
+- WARN_ON(node_qid > priv->htb_max_qos_sqs);
+- if (node_qid == priv->htb_max_qos_sqs) {
+- struct mlx5e_sq_stats *stats, **stats_list = NULL;
+-
+- if (priv->htb_max_qos_sqs == 0) {
+- stats_list = kvcalloc(mlx5e_qos_max_leaf_nodes(priv->mdev),
+- sizeof(*stats_list),
+- GFP_KERNEL);
+- if (!stats_list)
+- return -ENOMEM;
+- }
++ WARN_ON(node_qid >= mlx5e_htb_cur_leaf_nodes(priv->htb));
++ if (!priv->htb_qos_sq_stats) {
++ struct mlx5e_sq_stats **stats_list;
++
++ stats_list = kvcalloc(mlx5e_qos_max_leaf_nodes(priv->mdev),
++ sizeof(*stats_list), GFP_KERNEL);
++ if (!stats_list)
++ return -ENOMEM;
++
++ WRITE_ONCE(priv->htb_qos_sq_stats, stats_list);
++ }
++
++ if (!priv->htb_qos_sq_stats[node_qid]) {
++ struct mlx5e_sq_stats *stats;
++
+ stats = kzalloc(sizeof(*stats), GFP_KERNEL);
+- if (!stats) {
+- kvfree(stats_list);
++ if (!stats)
+ return -ENOMEM;
+- }
+- if (stats_list)
+- WRITE_ONCE(priv->htb_qos_sq_stats, stats_list);
++
+ WRITE_ONCE(priv->htb_qos_sq_stats[node_qid], stats);
+ /* Order htb_max_qos_sqs increment after writing the array pointer.
+ * Pairs with smp_load_acquire in en_stats.c.
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c b/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c
+index f675b1926340f..f66bbc8464645 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c
+@@ -57,6 +57,7 @@ int mlx5e_selq_init(struct mlx5e_selq *selq, struct mutex *state_lock)
+
+ void mlx5e_selq_cleanup(struct mlx5e_selq *selq)
+ {
++ mutex_lock(selq->state_lock);
+ WARN_ON_ONCE(selq->is_prepared);
+
+ kvfree(selq->standby);
+@@ -67,6 +68,7 @@ void mlx5e_selq_cleanup(struct mlx5e_selq *selq)
+
+ kvfree(selq->standby);
+ selq->standby = NULL;
++ mutex_unlock(selq->state_lock);
+ }
+
+ void mlx5e_selq_prepare_params(struct mlx5e_selq *selq, struct mlx5e_params *params)
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+index cc51ce16df14a..93461b0c5703b 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+@@ -451,6 +451,23 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
+
+ mutex_lock(&priv->state_lock);
+
++ /* If RXFH is configured, changing the channels number is allowed only if
++ * it does not require resizing the RSS table. This is because the previous
++ * configuration may no longer be compatible with the new RSS table.
++ */
++ if (netif_is_rxfh_configured(priv->netdev)) {
++ int cur_rqt_size = mlx5e_rqt_size(priv->mdev, cur_params->num_channels);
++ int new_rqt_size = mlx5e_rqt_size(priv->mdev, count);
++
++ if (new_rqt_size != cur_rqt_size) {
++ err = -EINVAL;
++ netdev_err(priv->netdev,
++ "%s: RXFH is configured, block changing channels number that affects RSS table size (new: %d, current: %d)\n",
++ __func__, new_rqt_size, cur_rqt_size);
++ goto out;
++ }
++ }
++
+ /* Don't allow changing the number of channels if HTB offload is active,
+ * because the numeration of the QoS SQs will change, while per-queue
+ * qdiscs are attached.
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index c8e8f512803ef..952f1f98138cc 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -5695,9 +5695,7 @@ void mlx5e_priv_cleanup(struct mlx5e_priv *priv)
+ kfree(priv->tx_rates);
+ kfree(priv->txq2sq);
+ destroy_workqueue(priv->wq);
+- mutex_lock(&priv->state_lock);
+ mlx5e_selq_cleanup(&priv->selq);
+- mutex_unlock(&priv->state_lock);
+ free_cpumask_var(priv->scratchpad.cpumask);
+
+ for (i = 0; i < priv->htb_max_qos_sqs; i++)
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+index 2fa076b23fbea..e21a3b4128ce8 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
+@@ -398,6 +398,8 @@ mlx5e_txwqe_complete(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+ (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) {
+ u8 metadata_index = be32_to_cpu(eseg->flow_table_metadata);
+
++ mlx5e_ptp_metadata_fifo_pop(&sq->ptpsq->metadata_freelist);
++
+ mlx5e_skb_cb_hwtstamp_init(skb);
+ mlx5e_ptp_metadata_map_put(&sq->ptpsq->metadata_map, skb,
+ metadata_index);
+@@ -496,9 +498,6 @@ mlx5e_sq_xmit_wqe(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+
+ err_drop:
+ stats->dropped++;
+- if (unlikely(sq->ptpsq && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)))
+- mlx5e_ptp_metadata_fifo_push(&sq->ptpsq->metadata_freelist,
+- be32_to_cpu(eseg->flow_table_metadata));
+ dev_kfree_skb_any(skb);
+ mlx5e_tx_flush(sq);
+ }
+@@ -657,7 +656,7 @@ static void mlx5e_cqe_ts_id_eseg(struct mlx5e_ptpsq *ptpsq, struct sk_buff *skb,
+ {
+ if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
+ eseg->flow_table_metadata =
+- cpu_to_be32(mlx5e_ptp_metadata_fifo_pop(&ptpsq->metadata_freelist));
++ cpu_to_be32(mlx5e_ptp_metadata_fifo_peek(&ptpsq->metadata_freelist));
+ }
+
+ static void mlx5e_txwqe_build_eseg(struct mlx5e_priv *priv, struct mlx5e_txqsq *sq,
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+index e6bfa7e4f146c..cf085a478e3e4 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+@@ -1664,6 +1664,16 @@ static int create_auto_flow_group(struct mlx5_flow_table *ft,
+ return err;
+ }
+
++static bool mlx5_pkt_reformat_cmp(struct mlx5_pkt_reformat *p1,
++ struct mlx5_pkt_reformat *p2)
++{
++ return p1->owner == p2->owner &&
++ (p1->owner == MLX5_FLOW_RESOURCE_OWNER_FW ?
++ p1->id == p2->id :
++ mlx5_fs_dr_action_get_pkt_reformat_id(p1) ==
++ mlx5_fs_dr_action_get_pkt_reformat_id(p2));
++}
++
+ static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
+ struct mlx5_flow_destination *d2)
+ {
+@@ -1675,8 +1685,8 @@ static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1,
+ ((d1->vport.flags & MLX5_FLOW_DEST_VPORT_VHCA_ID) ?
+ (d1->vport.vhca_id == d2->vport.vhca_id) : true) &&
+ ((d1->vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID) ?
+- (d1->vport.pkt_reformat->id ==
+- d2->vport.pkt_reformat->id) : true)) ||
++ mlx5_pkt_reformat_cmp(d1->vport.pkt_reformat,
++ d2->vport.pkt_reformat) : true)) ||
+ (d1->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE &&
+ d1->ft == d2->ft) ||
+ (d1->type == MLX5_FLOW_DESTINATION_TYPE_TIR &&
+@@ -1808,8 +1818,9 @@ static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
+ }
+ trace_mlx5_fs_set_fte(fte, false);
+
++ /* Link newly added rules into the tree. */
+ for (i = 0; i < handle->num_rules; i++) {
+- if (refcount_read(&handle->rule[i]->node.refcount) == 1) {
++ if (!handle->rule[i]->node.parent) {
+ tree_add_node(&handle->rule[i]->node, &fte->node);
+ trace_mlx5_fs_add_rule(handle->rule[i]);
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
+index bccf6e53556c6..131a836c127e3 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
+@@ -1480,6 +1480,14 @@ int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev)
+ if (err)
+ goto err_register;
+
++ err = mlx5_crdump_enable(dev);
++ if (err)
++ mlx5_core_err(dev, "mlx5_crdump_enable failed with error code %d\n", err);
++
++ err = mlx5_hwmon_dev_register(dev);
++ if (err)
++ mlx5_core_err(dev, "mlx5_hwmon_dev_register failed with error code %d\n", err);
++
+ mutex_unlock(&dev->intf_state_mutex);
+ return 0;
+
+@@ -1505,7 +1513,10 @@ int mlx5_init_one(struct mlx5_core_dev *dev)
+ int err;
+
+ devl_lock(devlink);
++ devl_register(devlink);
+ err = mlx5_init_one_devl_locked(dev);
++ if (err)
++ devl_unregister(devlink);
+ devl_unlock(devlink);
+ return err;
+ }
+@@ -1517,6 +1528,8 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev)
+ devl_lock(devlink);
+ mutex_lock(&dev->intf_state_mutex);
+
++ mlx5_hwmon_dev_unregister(dev);
++ mlx5_crdump_disable(dev);
+ mlx5_unregister_device(dev);
+
+ if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
+@@ -1534,6 +1547,7 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev)
+ mlx5_function_teardown(dev, true);
+ out:
+ mutex_unlock(&dev->intf_state_mutex);
++ devl_unregister(devlink);
+ devl_unlock(devlink);
+ }
+
+@@ -1680,16 +1694,20 @@ int mlx5_init_one_light(struct mlx5_core_dev *dev)
+ }
+
+ devl_lock(devlink);
++ devl_register(devlink);
++
+ err = mlx5_devlink_params_register(priv_to_devlink(dev));
+- devl_unlock(devlink);
+ if (err) {
+ mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err);
+ goto query_hca_caps_err;
+ }
+
++ devl_unlock(devlink);
+ return 0;
+
+ query_hca_caps_err:
++ devl_unregister(devlink);
++ devl_unlock(devlink);
+ mlx5_function_disable(dev, true);
+ out:
+ dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
+@@ -1702,6 +1720,7 @@ void mlx5_uninit_one_light(struct mlx5_core_dev *dev)
+
+ devl_lock(devlink);
+ mlx5_devlink_params_unregister(priv_to_devlink(dev));
++ devl_unregister(devlink);
+ devl_unlock(devlink);
+ if (dev->state != MLX5_DEVICE_STATE_UP)
+ return;
+@@ -1943,16 +1962,7 @@ static int probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ goto err_init_one;
+ }
+
+- err = mlx5_crdump_enable(dev);
+- if (err)
+- dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err);
+-
+- err = mlx5_hwmon_dev_register(dev);
+- if (err)
+- mlx5_core_err(dev, "mlx5_hwmon_dev_register failed with error code %d\n", err);
+-
+ pci_save_state(pdev);
+- devlink_register(devlink);
+ return 0;
+
+ err_init_one:
+@@ -1973,16 +1983,9 @@ static void remove_one(struct pci_dev *pdev)
+ struct devlink *devlink = priv_to_devlink(dev);
+
+ set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state);
+- /* mlx5_drain_fw_reset() and mlx5_drain_health_wq() are using
+- * devlink notify APIs.
+- * Hence, we must drain them before unregistering the devlink.
+- */
+ mlx5_drain_fw_reset(dev);
+ mlx5_drain_health_wq(dev);
+- devlink_unregister(devlink);
+ mlx5_sriov_disable(pdev, false);
+- mlx5_hwmon_dev_unregister(dev);
+- mlx5_crdump_disable(dev);
+ mlx5_uninit_one(dev);
+ mlx5_pci_close(dev);
+ mlx5_mdev_uninit(dev);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+index 4dcf995cb1a20..6bac8ad70ba60 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+@@ -19,6 +19,7 @@
+ #define MLX5_IRQ_CTRL_SF_MAX 8
+ /* min num of vectors for SFs to be enabled */
+ #define MLX5_IRQ_VEC_COMP_BASE_SF 2
++#define MLX5_IRQ_VEC_COMP_BASE 1
+
+ #define MLX5_EQ_SHARE_IRQ_MAX_COMP (8)
+ #define MLX5_EQ_SHARE_IRQ_MAX_CTRL (UINT_MAX)
+@@ -246,6 +247,7 @@ static void irq_set_name(struct mlx5_irq_pool *pool, char *name, int vecidx)
+ return;
+ }
+
++ vecidx -= MLX5_IRQ_VEC_COMP_BASE;
+ snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", vecidx);
+ }
+
+@@ -585,7 +587,7 @@ struct mlx5_irq *mlx5_irq_request_vector(struct mlx5_core_dev *dev, u16 cpu,
+ struct mlx5_irq_table *table = mlx5_irq_table_get(dev);
+ struct mlx5_irq_pool *pool = table->pcif_pool;
+ struct irq_affinity_desc af_desc;
+- int offset = 1;
++ int offset = MLX5_IRQ_VEC_COMP_BASE;
+
+ if (!pool->xa_num_irqs.max)
+ offset = 0;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
+index 169c2c68ed5c2..e3bf8c7e4baa6 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
+@@ -95,24 +95,28 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
+ static void mlx5_sf_dev_remove(struct auxiliary_device *adev)
+ {
+ struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev);
+- struct devlink *devlink = priv_to_devlink(sf_dev->mdev);
++ struct mlx5_core_dev *mdev = sf_dev->mdev;
++ struct devlink *devlink;
+
+- mlx5_drain_health_wq(sf_dev->mdev);
+- devlink_unregister(devlink);
+- if (mlx5_dev_is_lightweight(sf_dev->mdev))
+- mlx5_uninit_one_light(sf_dev->mdev);
++ devlink = priv_to_devlink(mdev);
++ set_bit(MLX5_BREAK_FW_WAIT, &mdev->intf_state);
++ mlx5_drain_health_wq(mdev);
++ if (mlx5_dev_is_lightweight(mdev))
++ mlx5_uninit_one_light(mdev);
+ else
+- mlx5_uninit_one(sf_dev->mdev);
+- iounmap(sf_dev->mdev->iseg);
+- mlx5_mdev_uninit(sf_dev->mdev);
++ mlx5_uninit_one(mdev);
++ iounmap(mdev->iseg);
++ mlx5_mdev_uninit(mdev);
+ mlx5_devlink_free(devlink);
+ }
+
+ static void mlx5_sf_dev_shutdown(struct auxiliary_device *adev)
+ {
+ struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev);
++ struct mlx5_core_dev *mdev = sf_dev->mdev;
+
+- mlx5_unload_one(sf_dev->mdev, false);
++ set_bit(MLX5_BREAK_FW_WAIT, &mdev->intf_state);
++ mlx5_unload_one(mdev, false);
+ }
+
+ static const struct auxiliary_device_id mlx5_sf_dev_id_table[] = {
+diff --git a/drivers/net/ethernet/micrel/ks8851.h b/drivers/net/ethernet/micrel/ks8851.h
+index e5ec0a363aff8..31f75b4a67fd7 100644
+--- a/drivers/net/ethernet/micrel/ks8851.h
++++ b/drivers/net/ethernet/micrel/ks8851.h
+@@ -368,7 +368,6 @@ union ks8851_tx_hdr {
+ * @rdfifo: FIFO read callback
+ * @wrfifo: FIFO write callback
+ * @start_xmit: start_xmit() implementation callback
+- * @rx_skb: rx_skb() implementation callback
+ * @flush_tx_work: flush_tx_work() implementation callback
+ *
+ * The @statelock is used to protect information in the structure which may
+@@ -423,8 +422,6 @@ struct ks8851_net {
+ struct sk_buff *txp, bool irq);
+ netdev_tx_t (*start_xmit)(struct sk_buff *skb,
+ struct net_device *dev);
+- void (*rx_skb)(struct ks8851_net *ks,
+- struct sk_buff *skb);
+ void (*flush_tx_work)(struct ks8851_net *ks);
+ };
+
+diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c
+index 0bf13b38b8f5b..d4cdf3d4f5525 100644
+--- a/drivers/net/ethernet/micrel/ks8851_common.c
++++ b/drivers/net/ethernet/micrel/ks8851_common.c
+@@ -231,16 +231,6 @@ static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt)
+ rxpkt[12], rxpkt[13], rxpkt[14], rxpkt[15]);
+ }
+
+-/**
+- * ks8851_rx_skb - receive skbuff
+- * @ks: The device state.
+- * @skb: The skbuff
+- */
+-static void ks8851_rx_skb(struct ks8851_net *ks, struct sk_buff *skb)
+-{
+- ks->rx_skb(ks, skb);
+-}
+-
+ /**
+ * ks8851_rx_pkts - receive packets from the host
+ * @ks: The device information.
+@@ -309,7 +299,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
+ ks8851_dbg_dumpkkt(ks, rxpkt);
+
+ skb->protocol = eth_type_trans(skb, ks->netdev);
+- ks8851_rx_skb(ks, skb);
++ __netif_rx(skb);
+
+ ks->netdev->stats.rx_packets++;
+ ks->netdev->stats.rx_bytes += rxlen;
+@@ -340,6 +330,8 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
+ unsigned long flags;
+ unsigned int status;
+
++ local_bh_disable();
++
+ ks8851_lock(ks, &flags);
+
+ status = ks8851_rdreg16(ks, KS_ISR);
+@@ -416,6 +408,8 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
+ if (status & IRQ_LCI)
+ mii_check_link(&ks->mii);
+
++ local_bh_enable();
++
+ return IRQ_HANDLED;
+ }
+
+diff --git a/drivers/net/ethernet/micrel/ks8851_par.c b/drivers/net/ethernet/micrel/ks8851_par.c
+index 2a7f298542670..381b9cd285ebd 100644
+--- a/drivers/net/ethernet/micrel/ks8851_par.c
++++ b/drivers/net/ethernet/micrel/ks8851_par.c
+@@ -210,16 +210,6 @@ static void ks8851_wrfifo_par(struct ks8851_net *ks, struct sk_buff *txp,
+ iowrite16_rep(ksp->hw_addr, txp->data, len / 2);
+ }
+
+-/**
+- * ks8851_rx_skb_par - receive skbuff
+- * @ks: The device state.
+- * @skb: The skbuff
+- */
+-static void ks8851_rx_skb_par(struct ks8851_net *ks, struct sk_buff *skb)
+-{
+- netif_rx(skb);
+-}
+-
+ static unsigned int ks8851_rdreg16_par_txqcr(struct ks8851_net *ks)
+ {
+ return ks8851_rdreg16_par(ks, KS_TXQCR);
+@@ -298,7 +288,6 @@ static int ks8851_probe_par(struct platform_device *pdev)
+ ks->rdfifo = ks8851_rdfifo_par;
+ ks->wrfifo = ks8851_wrfifo_par;
+ ks->start_xmit = ks8851_start_xmit_par;
+- ks->rx_skb = ks8851_rx_skb_par;
+
+ #define STD_IRQ (IRQ_LCI | /* Link Change */ \
+ IRQ_RXI | /* RX done */ \
+diff --git a/drivers/net/ethernet/micrel/ks8851_spi.c b/drivers/net/ethernet/micrel/ks8851_spi.c
+index 54f2eac11a631..55f6f9f6d030e 100644
+--- a/drivers/net/ethernet/micrel/ks8851_spi.c
++++ b/drivers/net/ethernet/micrel/ks8851_spi.c
+@@ -298,16 +298,6 @@ static unsigned int calc_txlen(unsigned int len)
+ return ALIGN(len + 4, 4);
+ }
+
+-/**
+- * ks8851_rx_skb_spi - receive skbuff
+- * @ks: The device state
+- * @skb: The skbuff
+- */
+-static void ks8851_rx_skb_spi(struct ks8851_net *ks, struct sk_buff *skb)
+-{
+- netif_rx(skb);
+-}
+-
+ /**
+ * ks8851_tx_work - process tx packet(s)
+ * @work: The work strucutre what was scheduled.
+@@ -435,7 +425,6 @@ static int ks8851_probe_spi(struct spi_device *spi)
+ ks->rdfifo = ks8851_rdfifo_spi;
+ ks->wrfifo = ks8851_wrfifo_spi;
+ ks->start_xmit = ks8851_start_xmit_spi;
+- ks->rx_skb = ks8851_rx_skb_spi;
+ ks->flush_tx_work = ks8851_flush_tx_work_spi;
+
+ #define STD_IRQ (IRQ_LCI | /* Link Change */ \
+diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
+index 3a1b1a1f5a195..60dd2fd603a85 100644
+--- a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
+@@ -731,7 +731,7 @@ static int sparx5_port_pcs_low_set(struct sparx5 *sparx5,
+ bool sgmii = false, inband_aneg = false;
+ int err;
+
+- if (port->conf.inband) {
++ if (conf->inband) {
+ if (conf->portmode == PHY_INTERFACE_MODE_SGMII ||
+ conf->portmode == PHY_INTERFACE_MODE_QSGMII)
+ inband_aneg = true; /* Cisco-SGMII in-band-aneg */
+@@ -948,7 +948,7 @@ int sparx5_port_pcs_set(struct sparx5 *sparx5,
+ if (err)
+ return -EINVAL;
+
+- if (port->conf.inband) {
++ if (conf->inband) {
+ /* Enable/disable 1G counters in ASM */
+ spx5_rmw(ASM_PORT_CFG_CSC_STAT_DIS_SET(high_speed_dev),
+ ASM_PORT_CFG_CSC_STAT_DIS,
+diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
+index 097a8db0d1d99..7f00fca0c538c 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -830,7 +830,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
+ __be16 sport;
+ int err;
+
+- if (!pskb_inet_may_pull(skb))
++ if (!skb_vlan_inet_prepare(skb))
+ return -EINVAL;
+
+ if (!gs4)
+@@ -937,7 +937,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
+ __be16 sport;
+ int err;
+
+- if (!pskb_inet_may_pull(skb))
++ if (!skb_vlan_inet_prepare(skb))
+ return -EINVAL;
+
+ if (!gs6)
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index d7ce4a1011ea2..ec14bf2a9af05 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -3768,6 +3768,7 @@ static int virtnet_set_rxfh(struct net_device *dev,
+ struct netlink_ext_ack *extack)
+ {
+ struct virtnet_info *vi = netdev_priv(dev);
++ bool update = false;
+ int i;
+
+ if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
+@@ -3775,13 +3776,28 @@ static int virtnet_set_rxfh(struct net_device *dev,
+ return -EOPNOTSUPP;
+
+ if (rxfh->indir) {
++ if (!vi->has_rss)
++ return -EOPNOTSUPP;
++
+ for (i = 0; i < vi->rss_indir_table_size; ++i)
+ vi->ctrl->rss.indirection_table[i] = rxfh->indir[i];
++ update = true;
+ }
+- if (rxfh->key)
++
++ if (rxfh->key) {
++ /* If either _F_HASH_REPORT or _F_RSS are negotiated, the
++ * device provides hash calculation capabilities, that is,
++ * hash_key is configured.
++ */
++ if (!vi->has_rss && !vi->has_rss_hash_report)
++ return -EOPNOTSUPP;
++
+ memcpy(vi->ctrl->rss.key, rxfh->key, vi->rss_key_size);
++ update = true;
++ }
+
+- virtnet_commit_rss_command(vi);
++ if (update)
++ virtnet_commit_rss_command(vi);
+
+ return 0;
+ }
+@@ -4686,13 +4702,15 @@ static int virtnet_probe(struct virtio_device *vdev)
+ if (virtio_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT))
+ vi->has_rss_hash_report = true;
+
+- if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS))
++ if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) {
+ vi->has_rss = true;
+
+- if (vi->has_rss || vi->has_rss_hash_report) {
+ vi->rss_indir_table_size =
+ virtio_cread16(vdev, offsetof(struct virtio_net_config,
+ rss_max_indirection_table_length));
++ }
++
++ if (vi->has_rss || vi->has_rss_hash_report) {
+ vi->rss_key_size =
+ virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size));
+
+diff --git a/drivers/platform/chrome/cros_ec_uart.c b/drivers/platform/chrome/cros_ec_uart.c
+index 68d80559fddc2..eb5eddeb73f72 100644
+--- a/drivers/platform/chrome/cros_ec_uart.c
++++ b/drivers/platform/chrome/cros_ec_uart.c
+@@ -263,12 +263,6 @@ static int cros_ec_uart_probe(struct serdev_device *serdev)
+ if (!ec_dev)
+ return -ENOMEM;
+
+- ret = devm_serdev_device_open(dev, serdev);
+- if (ret) {
+- dev_err(dev, "Unable to open UART device");
+- return ret;
+- }
+-
+ serdev_device_set_drvdata(serdev, ec_dev);
+ init_waitqueue_head(&ec_uart->response.wait_queue);
+
+@@ -280,14 +274,6 @@ static int cros_ec_uart_probe(struct serdev_device *serdev)
+ return ret;
+ }
+
+- ret = serdev_device_set_baudrate(serdev, ec_uart->baudrate);
+- if (ret < 0) {
+- dev_err(dev, "Failed to set up host baud rate (%d)", ret);
+- return ret;
+- }
+-
+- serdev_device_set_flow_control(serdev, ec_uart->flowcontrol);
+-
+ /* Initialize ec_dev for cros_ec */
+ ec_dev->phys_name = dev_name(dev);
+ ec_dev->dev = dev;
+@@ -301,6 +287,20 @@ static int cros_ec_uart_probe(struct serdev_device *serdev)
+
+ serdev_device_set_client_ops(serdev, &cros_ec_uart_client_ops);
+
++ ret = devm_serdev_device_open(dev, serdev);
++ if (ret) {
++ dev_err(dev, "Unable to open UART device");
++ return ret;
++ }
++
++ ret = serdev_device_set_baudrate(serdev, ec_uart->baudrate);
++ if (ret < 0) {
++ dev_err(dev, "Failed to set up host baud rate (%d)", ret);
++ return ret;
++ }
++
++ serdev_device_set_flow_control(serdev, ec_uart->flowcontrol);
++
+ return cros_ec_register(ec_dev);
+ }
+
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
+index 1abc62b07d24c..05c38e43f140a 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
+@@ -1792,7 +1792,7 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
+ if (dev_is_sata(device)) {
+ struct ata_link *link = &device->sata_dev.ap->link;
+
+- rc = ata_wait_after_reset(link, HISI_SAS_WAIT_PHYUP_TIMEOUT,
++ rc = ata_wait_after_reset(link, jiffies + HISI_SAS_WAIT_PHYUP_TIMEOUT,
+ smp_ata_check_ready_type);
+ } else {
+ msleep(2000);
+diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c
+index 26e6b3e3af431..dcde55c8ee5de 100644
+--- a/drivers/scsi/qla2xxx/qla_edif.c
++++ b/drivers/scsi/qla2xxx/qla_edif.c
+@@ -1100,7 +1100,7 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job)
+
+ list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) {
+ if (fcport->edif.enable) {
+- if (pcnt > app_req.num_ports)
++ if (pcnt >= app_req.num_ports)
+ break;
+
+ app_reply->elem[pcnt].rekey_count =
+diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
+index 86210e4dd0d35..b2d02dacaebd9 100644
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -285,6 +285,7 @@ sg_open(struct inode *inode, struct file *filp)
+ int dev = iminor(inode);
+ int flags = filp->f_flags;
+ struct request_queue *q;
++ struct scsi_device *device;
+ Sg_device *sdp;
+ Sg_fd *sfp;
+ int retval;
+@@ -301,11 +302,12 @@ sg_open(struct inode *inode, struct file *filp)
+
+ /* This driver's module count bumped by fops_get in <linux/fs.h> */
+ /* Prevent the device driver from vanishing while we sleep */
+- retval = scsi_device_get(sdp->device);
++ device = sdp->device;
++ retval = scsi_device_get(device);
+ if (retval)
+ goto sg_put;
+
+- retval = scsi_autopm_get_device(sdp->device);
++ retval = scsi_autopm_get_device(device);
+ if (retval)
+ goto sdp_put;
+
+@@ -313,7 +315,7 @@ sg_open(struct inode *inode, struct file *filp)
+ * check if O_NONBLOCK. Permits SCSI commands to be issued
+ * during error recovery. Tread carefully. */
+ if (!((flags & O_NONBLOCK) ||
+- scsi_block_when_processing_errors(sdp->device))) {
++ scsi_block_when_processing_errors(device))) {
+ retval = -ENXIO;
+ /* we are in error recovery for this device */
+ goto error_out;
+@@ -344,7 +346,7 @@ sg_open(struct inode *inode, struct file *filp)
+
+ if (sdp->open_cnt < 1) { /* no existing opens */
+ sdp->sgdebug = 0;
+- q = sdp->device->request_queue;
++ q = device->request_queue;
+ sdp->sg_tablesize = queue_max_segments(q);
+ }
+ sfp = sg_add_sfp(sdp);
+@@ -370,10 +372,11 @@ sg_open(struct inode *inode, struct file *filp)
+ error_mutex_locked:
+ mutex_unlock(&sdp->open_rel_lock);
+ error_out:
+- scsi_autopm_put_device(sdp->device);
++ scsi_autopm_put_device(device);
+ sdp_put:
+- scsi_device_put(sdp->device);
+- goto sg_put;
++ kref_put(&sdp->d_ref, sg_device_destroy);
++ scsi_device_put(device);
++ return retval;
+ }
+
+ /* Release resources associated with a successful sg_open()
+@@ -2207,6 +2210,7 @@ sg_remove_sfp_usercontext(struct work_struct *work)
+ {
+ struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
+ struct sg_device *sdp = sfp->parentdp;
++ struct scsi_device *device = sdp->device;
+ Sg_request *srp;
+ unsigned long iflags;
+
+@@ -2232,8 +2236,8 @@ sg_remove_sfp_usercontext(struct work_struct *work)
+ "sg_remove_sfp: sfp=0x%p\n", sfp));
+ kfree(sfp);
+
+- scsi_device_put(sdp->device);
+ kref_put(&sdp->d_ref, sg_device_destroy);
++ scsi_device_put(device);
+ module_put(THIS_MODULE);
+ }
+
+diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
+index 045f666b4f12a..32686c79c41d6 100644
+--- a/drivers/vhost/vhost.c
++++ b/drivers/vhost/vhost.c
+@@ -2799,9 +2799,19 @@ bool vhost_vq_avail_empty(struct vhost_dev *dev, struct vhost_virtqueue *vq)
+ r = vhost_get_avail_idx(vq, &avail_idx);
+ if (unlikely(r))
+ return false;
++
+ vq->avail_idx = vhost16_to_cpu(vq, avail_idx);
++ if (vq->avail_idx != vq->last_avail_idx) {
++ /* Since we have updated avail_idx, the following
++ * call to vhost_get_vq_desc() will read available
++ * ring entries. Make sure that read happens after
++ * the avail_idx read.
++ */
++ smp_rmb();
++ return false;
++ }
+
+- return vq->avail_idx == vq->last_avail_idx;
++ return true;
+ }
+ EXPORT_SYMBOL_GPL(vhost_vq_avail_empty);
+
+@@ -2838,9 +2848,19 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
+ &vq->avail->idx, r);
+ return false;
+ }
++
+ vq->avail_idx = vhost16_to_cpu(vq, avail_idx);
++ if (vq->avail_idx != vq->last_avail_idx) {
++ /* Since we have updated avail_idx, the following
++ * call to vhost_get_vq_desc() will read available
++ * ring entries. Make sure that read happens after
++ * the avail_idx read.
++ */
++ smp_rmb();
++ return true;
++ }
+
+- return vq->avail_idx != vq->last_avail_idx;
++ return false;
+ }
+ EXPORT_SYMBOL_GPL(vhost_enable_notify);
+
+diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
+index 08102883f560a..ab5a833e7d6ad 100644
+--- a/fs/btrfs/delayed-inode.c
++++ b/fs/btrfs/delayed-inode.c
+@@ -1128,6 +1128,9 @@ __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans,
+ if (ret)
+ return ret;
+
++ ret = btrfs_record_root_in_trans(trans, node->root);
++ if (ret)
++ return ret;
+ ret = btrfs_update_delayed_inode(trans, node->root, path, node);
+ return ret;
+ }
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 5ceb995709b56..6e2715e3f3aa0 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -4476,6 +4476,7 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
+ struct btrfs_trans_handle *trans;
+ struct btrfs_block_rsv block_rsv;
+ u64 root_flags;
++ u64 qgroup_reserved = 0;
+ int ret;
+
+ down_write(&fs_info->subvol_sem);
+@@ -4520,12 +4521,20 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
+ ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, 5, true);
+ if (ret)
+ goto out_undead;
++ qgroup_reserved = block_rsv.qgroup_rsv_reserved;
+
+ trans = btrfs_start_transaction(root, 0);
+ if (IS_ERR(trans)) {
+ ret = PTR_ERR(trans);
+ goto out_release;
+ }
++ ret = btrfs_record_root_in_trans(trans, root);
++ if (ret) {
++ btrfs_abort_transaction(trans, ret);
++ goto out_end_trans;
++ }
++ btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
++ qgroup_reserved = 0;
+ trans->block_rsv = &block_rsv;
+ trans->bytes_reserved = block_rsv.size;
+
+@@ -4584,7 +4593,9 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry)
+ ret = btrfs_end_transaction(trans);
+ inode->i_flags |= S_DEAD;
+ out_release:
+- btrfs_subvolume_release_metadata(root, &block_rsv);
++ btrfs_block_rsv_release(fs_info, &block_rsv, (u64)-1, NULL);
++ if (qgroup_reserved)
++ btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved);
+ out_undead:
+ if (ret) {
+ spin_lock(&dest->root_item_lock);
+diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
+index bd19aed66605a..6b93fae74403d 100644
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -603,6 +603,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
+ int ret;
+ dev_t anon_dev;
+ u64 objectid;
++ u64 qgroup_reserved = 0;
+
+ root_item = kzalloc(sizeof(*root_item), GFP_KERNEL);
+ if (!root_item)
+@@ -640,13 +641,18 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
+ trans_num_items, false);
+ if (ret)
+ goto out_new_inode_args;
++ qgroup_reserved = block_rsv.qgroup_rsv_reserved;
+
+ trans = btrfs_start_transaction(root, 0);
+ if (IS_ERR(trans)) {
+ ret = PTR_ERR(trans);
+- btrfs_subvolume_release_metadata(root, &block_rsv);
+- goto out_new_inode_args;
++ goto out_release_rsv;
+ }
++ ret = btrfs_record_root_in_trans(trans, BTRFS_I(dir)->root);
++ if (ret)
++ goto out;
++ btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
++ qgroup_reserved = 0;
+ trans->block_rsv = &block_rsv;
+ trans->bytes_reserved = block_rsv.size;
+ /* Tree log can't currently deal with an inode which is a new root. */
+@@ -757,9 +763,11 @@ static noinline int create_subvol(struct mnt_idmap *idmap,
+ out:
+ trans->block_rsv = NULL;
+ trans->bytes_reserved = 0;
+- btrfs_subvolume_release_metadata(root, &block_rsv);
+-
+ btrfs_end_transaction(trans);
++out_release_rsv:
++ btrfs_block_rsv_release(fs_info, &block_rsv, (u64)-1, NULL);
++ if (qgroup_reserved)
++ btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved);
+ out_new_inode_args:
+ btrfs_new_inode_args_destroy(&new_inode_args);
+ out_inode:
+@@ -781,6 +789,8 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
+ struct btrfs_pending_snapshot *pending_snapshot;
+ unsigned int trans_num_items;
+ struct btrfs_trans_handle *trans;
++ struct btrfs_block_rsv *block_rsv;
++ u64 qgroup_reserved = 0;
+ int ret;
+
+ /* We do not support snapshotting right now. */
+@@ -817,19 +827,19 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
+ goto free_pending;
+ }
+
+- btrfs_init_block_rsv(&pending_snapshot->block_rsv,
+- BTRFS_BLOCK_RSV_TEMP);
++ block_rsv = &pending_snapshot->block_rsv;
++ btrfs_init_block_rsv(block_rsv, BTRFS_BLOCK_RSV_TEMP);
+ /*
+ * 1 to add dir item
+ * 1 to add dir index
+ * 1 to update parent inode item
+ */
+ trans_num_items = create_subvol_num_items(inherit) + 3;
+- ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root,
+- &pending_snapshot->block_rsv,
++ ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root, block_rsv,
+ trans_num_items, false);
+ if (ret)
+ goto free_pending;
++ qgroup_reserved = block_rsv->qgroup_rsv_reserved;
+
+ pending_snapshot->dentry = dentry;
+ pending_snapshot->root = root;
+@@ -842,6 +852,13 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
+ ret = PTR_ERR(trans);
+ goto fail;
+ }
++ ret = btrfs_record_root_in_trans(trans, BTRFS_I(dir)->root);
++ if (ret) {
++ btrfs_end_transaction(trans);
++ goto fail;
++ }
++ btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
++ qgroup_reserved = 0;
+
+ trans->pending_snapshot = pending_snapshot;
+
+@@ -871,7 +888,9 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
+ if (ret && pending_snapshot->snap)
+ pending_snapshot->snap->anon_dev = 0;
+ btrfs_put_root(pending_snapshot->snap);
+- btrfs_subvolume_release_metadata(root, &pending_snapshot->block_rsv);
++ btrfs_block_rsv_release(fs_info, block_rsv, (u64)-1, NULL);
++ if (qgroup_reserved)
++ btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved);
+ free_pending:
+ if (pending_snapshot->anon_dev)
+ free_anon_bdev(pending_snapshot->anon_dev);
+diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
+index a78c6694959aa..132802bd80999 100644
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -4432,6 +4432,8 @@ void btrfs_qgroup_convert_reserved_meta(struct btrfs_root *root, int num_bytes)
+ BTRFS_QGROUP_RSV_META_PREALLOC);
+ trace_qgroup_meta_convert(root, num_bytes);
+ qgroup_convert_meta(fs_info, root->root_key.objectid, num_bytes);
++ if (!sb_rdonly(fs_info->sb))
++ add_root_meta_rsv(root, num_bytes, BTRFS_QGROUP_RSV_META_PERTRANS);
+ }
+
+ /*
+diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
+index 603ad1459368c..5260677ad51e2 100644
+--- a/fs/btrfs/root-tree.c
++++ b/fs/btrfs/root-tree.c
+@@ -539,13 +539,3 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
+ }
+ return ret;
+ }
+-
+-void btrfs_subvolume_release_metadata(struct btrfs_root *root,
+- struct btrfs_block_rsv *rsv)
+-{
+- struct btrfs_fs_info *fs_info = root->fs_info;
+- u64 qgroup_to_release;
+-
+- btrfs_block_rsv_release(fs_info, rsv, (u64)-1, &qgroup_to_release);
+- btrfs_qgroup_convert_reserved_meta(root, qgroup_to_release);
+-}
+diff --git a/fs/btrfs/root-tree.h b/fs/btrfs/root-tree.h
+index 8b2c3859e4647..de0175cbdb1e5 100644
+--- a/fs/btrfs/root-tree.h
++++ b/fs/btrfs/root-tree.h
+@@ -8,8 +8,6 @@ struct fscrypt_str;
+ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root,
+ struct btrfs_block_rsv *rsv,
+ int nitems, bool use_global_rsv);
+-void btrfs_subvolume_release_metadata(struct btrfs_root *root,
+- struct btrfs_block_rsv *rsv);
+ int btrfs_add_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
+ u64 ref_id, u64 dirid, u64 sequence,
+ const struct fscrypt_str *name);
+diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c
+index 25b3349595e00..865d4af4b3035 100644
+--- a/fs/btrfs/tests/extent-io-tests.c
++++ b/fs/btrfs/tests/extent-io-tests.c
+@@ -11,6 +11,7 @@
+ #include "btrfs-tests.h"
+ #include "../ctree.h"
+ #include "../extent_io.h"
++#include "../disk-io.h"
+ #include "../btrfs_inode.h"
+
+ #define PROCESS_UNLOCK (1 << 0)
+@@ -105,9 +106,11 @@ static void dump_extent_io_tree(const struct extent_io_tree *tree)
+ }
+ }
+
+-static int test_find_delalloc(u32 sectorsize)
++static int test_find_delalloc(u32 sectorsize, u32 nodesize)
+ {
+- struct inode *inode;
++ struct btrfs_fs_info *fs_info;
++ struct btrfs_root *root = NULL;
++ struct inode *inode = NULL;
+ struct extent_io_tree *tmp;
+ struct page *page;
+ struct page *locked_page = NULL;
+@@ -121,12 +124,27 @@ static int test_find_delalloc(u32 sectorsize)
+
+ test_msg("running find delalloc tests");
+
++ fs_info = btrfs_alloc_dummy_fs_info(nodesize, sectorsize);
++ if (!fs_info) {
++ test_std_err(TEST_ALLOC_FS_INFO);
++ return -ENOMEM;
++ }
++
++ root = btrfs_alloc_dummy_root(fs_info);
++ if (IS_ERR(root)) {
++ test_std_err(TEST_ALLOC_ROOT);
++ ret = PTR_ERR(root);
++ goto out;
++ }
++
+ inode = btrfs_new_test_inode();
+ if (!inode) {
+ test_std_err(TEST_ALLOC_INODE);
+- return -ENOMEM;
++ ret = -ENOMEM;
++ goto out;
+ }
+ tmp = &BTRFS_I(inode)->io_tree;
++ BTRFS_I(inode)->root = root;
+
+ /*
+ * Passing NULL as we don't have fs_info but tracepoints are not used
+@@ -316,6 +334,8 @@ static int test_find_delalloc(u32 sectorsize)
+ process_page_range(inode, 0, total_dirty - 1,
+ PROCESS_UNLOCK | PROCESS_RELEASE);
+ iput(inode);
++ btrfs_free_dummy_root(root);
++ btrfs_free_dummy_fs_info(fs_info);
+ return ret;
+ }
+
+@@ -794,7 +814,7 @@ int btrfs_test_extent_io(u32 sectorsize, u32 nodesize)
+
+ test_msg("running extent I/O tests");
+
+- ret = test_find_delalloc(sectorsize);
++ ret = test_find_delalloc(sectorsize, nodesize);
+ if (ret)
+ goto out;
+
+diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
+index bf8e64c766b63..f1705ae59e4a9 100644
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -747,14 +747,6 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
+ h->reloc_reserved = reloc_reserved;
+ }
+
+- /*
+- * Now that we have found a transaction to be a part of, convert the
+- * qgroup reservation from prealloc to pertrans. A different transaction
+- * can't race in and free our pertrans out from under us.
+- */
+- if (qgroup_reserved)
+- btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
+-
+ got_it:
+ if (!current->journal_info)
+ current->journal_info = h;
+@@ -788,8 +780,15 @@ start_transaction(struct btrfs_root *root, unsigned int num_items,
+ * not just freed.
+ */
+ btrfs_end_transaction(h);
+- return ERR_PTR(ret);
++ goto reserve_fail;
+ }
++ /*
++ * Now that we have found a transaction to be a part of, convert the
++ * qgroup reservation from prealloc to pertrans. A different transaction
++ * can't race in and free our pertrans out from under us.
++ */
++ if (qgroup_reserved)
++ btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved);
+
+ return h;
+
+diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
+index 1340d77124ae4..ee9caf7916fb9 100644
+--- a/fs/ceph/addr.c
++++ b/fs/ceph/addr.c
+@@ -795,8 +795,10 @@ static int ceph_writepage(struct page *page, struct writeback_control *wbc)
+ ihold(inode);
+
+ if (wbc->sync_mode == WB_SYNC_NONE &&
+- ceph_inode_to_fs_client(inode)->write_congested)
++ ceph_inode_to_fs_client(inode)->write_congested) {
++ redirty_page_for_writepage(wbc, page);
+ return AOP_WRITEPAGE_ACTIVATE;
++ }
+
+ wait_on_page_fscache(page);
+
+diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
+index 7fb4aae974124..e8d8e3e633cdb 100644
+--- a/fs/ceph/caps.c
++++ b/fs/ceph/caps.c
+@@ -4775,13 +4775,13 @@ int ceph_drop_caps_for_unlink(struct inode *inode)
+
+ doutc(mdsc->fsc->client, "%p %llx.%llx\n", inode,
+ ceph_vinop(inode));
+- spin_lock(&mdsc->cap_unlink_delay_lock);
++ spin_lock(&mdsc->cap_delay_lock);
+ ci->i_ceph_flags |= CEPH_I_FLUSH;
+ if (!list_empty(&ci->i_cap_delay_list))
+ list_del_init(&ci->i_cap_delay_list);
+ list_add_tail(&ci->i_cap_delay_list,
+ &mdsc->cap_unlink_delay_list);
+- spin_unlock(&mdsc->cap_unlink_delay_lock);
++ spin_unlock(&mdsc->cap_delay_lock);
+
+ /*
+ * Fire the work immediately, because the MDS maybe
+diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
+index 3ab9c268a8bb3..360b686c3c67c 100644
+--- a/fs/ceph/mds_client.c
++++ b/fs/ceph/mds_client.c
+@@ -2504,7 +2504,7 @@ static void ceph_cap_unlink_work(struct work_struct *work)
+ struct ceph_client *cl = mdsc->fsc->client;
+
+ doutc(cl, "begin\n");
+- spin_lock(&mdsc->cap_unlink_delay_lock);
++ spin_lock(&mdsc->cap_delay_lock);
+ while (!list_empty(&mdsc->cap_unlink_delay_list)) {
+ struct ceph_inode_info *ci;
+ struct inode *inode;
+@@ -2516,15 +2516,15 @@ static void ceph_cap_unlink_work(struct work_struct *work)
+
+ inode = igrab(&ci->netfs.inode);
+ if (inode) {
+- spin_unlock(&mdsc->cap_unlink_delay_lock);
++ spin_unlock(&mdsc->cap_delay_lock);
+ doutc(cl, "on %p %llx.%llx\n", inode,
+ ceph_vinop(inode));
+ ceph_check_caps(ci, CHECK_CAPS_FLUSH);
+ iput(inode);
+- spin_lock(&mdsc->cap_unlink_delay_lock);
++ spin_lock(&mdsc->cap_delay_lock);
+ }
+ }
+- spin_unlock(&mdsc->cap_unlink_delay_lock);
++ spin_unlock(&mdsc->cap_delay_lock);
+ doutc(cl, "done\n");
+ }
+
+@@ -5404,7 +5404,6 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
+ INIT_LIST_HEAD(&mdsc->cap_wait_list);
+ spin_lock_init(&mdsc->cap_delay_lock);
+ INIT_LIST_HEAD(&mdsc->cap_unlink_delay_list);
+- spin_lock_init(&mdsc->cap_unlink_delay_lock);
+ INIT_LIST_HEAD(&mdsc->snap_flush_list);
+ spin_lock_init(&mdsc->snap_flush_lock);
+ mdsc->last_cap_flush_tid = 1;
+diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
+index 03f8ff00874f7..b88e804152241 100644
+--- a/fs/ceph/mds_client.h
++++ b/fs/ceph/mds_client.h
+@@ -461,9 +461,8 @@ struct ceph_mds_client {
+ struct delayed_work delayed_work; /* delayed work */
+ unsigned long last_renew_caps; /* last time we renewed our caps */
+ struct list_head cap_delay_list; /* caps with delayed release */
+- spinlock_t cap_delay_lock; /* protects cap_delay_list */
+ struct list_head cap_unlink_delay_list; /* caps with delayed release for unlink */
+- spinlock_t cap_unlink_delay_lock; /* protects cap_unlink_delay_list */
++ spinlock_t cap_delay_lock; /* protects cap_delay_list and cap_unlink_delay_list */
+ struct list_head snap_flush_list; /* cap_snaps ready to flush */
+ spinlock_t snap_flush_lock;
+
+diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
+index ffa4565c275a7..b7f943f33366d 100644
+--- a/fs/kernfs/file.c
++++ b/fs/kernfs/file.c
+@@ -634,11 +634,18 @@ static int kernfs_fop_open(struct inode *inode, struct file *file)
+ * each file a separate locking class. Let's differentiate on
+ * whether the file has mmap or not for now.
+ *
+- * Both paths of the branch look the same. They're supposed to
++ * For similar reasons, writable and readonly files are given different
++ * lockdep key, because the writable file /sys/power/resume may call vfs
++ * lookup helpers for arbitrary paths and readonly files can be read by
++ * overlayfs from vfs helpers when sysfs is a lower layer of overalyfs.
++ *
++ * All three cases look the same. They're supposed to
+ * look that way and give @of->mutex different static lockdep keys.
+ */
+ if (has_mmap)
+ mutex_init(&of->mutex);
++ else if (file->f_mode & FMODE_WRITE)
++ mutex_init(&of->mutex);
+ else
+ mutex_init(&of->mutex);
+
+diff --git a/fs/proc/bootconfig.c b/fs/proc/bootconfig.c
+index 902b326e1e560..87dcaae32ff87 100644
+--- a/fs/proc/bootconfig.c
++++ b/fs/proc/bootconfig.c
+@@ -62,12 +62,12 @@ static int __init copy_xbc_key_value_list(char *dst, size_t size)
+ break;
+ dst += ret;
+ }
+- if (ret >= 0 && boot_command_line[0]) {
+- ret = snprintf(dst, rest(dst, end), "# Parameters from bootloader:\n# %s\n",
+- boot_command_line);
+- if (ret > 0)
+- dst += ret;
+- }
++ }
++ if (cmdline_has_extra_options() && ret >= 0 && boot_command_line[0]) {
++ ret = snprintf(dst, rest(dst, end), "# Parameters from bootloader:\n# %s\n",
++ boot_command_line);
++ if (ret > 0)
++ dst += ret;
+ }
+ out:
+ kfree(key);
+diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
+index 13a9d7acf8f8e..0ff2491c311d8 100644
+--- a/fs/smb/client/cached_dir.c
++++ b/fs/smb/client/cached_dir.c
+@@ -433,8 +433,8 @@ smb2_close_cached_fid(struct kref *ref)
+ if (cfid->is_open) {
+ rc = SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid,
+ cfid->fid.volatile_fid);
+- if (rc != -EBUSY && rc != -EAGAIN)
+- atomic_dec(&cfid->tcon->num_remote_opens);
++ if (rc) /* should we retry on -EBUSY or -EAGAIN? */
++ cifs_dbg(VFS, "close cached dir rc %d\n", rc);
+ }
+
+ free_cached_dir(cfid);
+diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
+index 446225aada50d..8b45b82cd5edc 100644
+--- a/include/acpi/acpi_bus.h
++++ b/include/acpi/acpi_bus.h
+@@ -911,17 +911,19 @@ static inline bool acpi_int_uid_match(struct acpi_device *adev, u64 uid2)
+ * acpi_dev_hid_uid_match - Match device by supplied HID and UID
+ * @adev: ACPI device to match.
+ * @hid2: Hardware ID of the device.
+- * @uid2: Unique ID of the device, pass 0 or NULL to not check _UID.
++ * @uid2: Unique ID of the device, pass NULL to not check _UID.
+ *
+ * Matches HID and UID in @adev with given @hid2 and @uid2. Absence of @uid2
+ * will be treated as a match. If user wants to validate @uid2, it should be
+ * done before calling this function.
+ *
+- * Returns: %true if matches or @uid2 is 0 or NULL, %false otherwise.
++ * Returns: %true if matches or @uid2 is NULL, %false otherwise.
+ */
+ #define acpi_dev_hid_uid_match(adev, hid2, uid2) \
+ (acpi_dev_hid_match(adev, hid2) && \
+- (!(uid2) || acpi_dev_uid_match(adev, uid2)))
++ /* Distinguish integer 0 from NULL @uid2 */ \
++ (_Generic(uid2, ACPI_STR_TYPES(!(uid2)), default: 0) || \
++ acpi_dev_uid_match(adev, uid2)))
+
+ void acpi_dev_clear_dependencies(struct acpi_device *supplier);
+ bool acpi_dev_ready_for_enumeration(const struct acpi_device *device);
+diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h
+index ca73940e26df8..e5ee2c694401e 100644
+--- a/include/linux/bootconfig.h
++++ b/include/linux/bootconfig.h
+@@ -10,6 +10,7 @@
+ #ifdef __KERNEL__
+ #include <linux/kernel.h>
+ #include <linux/types.h>
++bool __init cmdline_has_extra_options(void);
+ #else /* !__KERNEL__ */
+ /*
+ * NOTE: This is only for tools/bootconfig, because tools/bootconfig will
+diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
+index e06bad467f55e..c3f9bb6602ba2 100644
+--- a/include/linux/dma-fence.h
++++ b/include/linux/dma-fence.h
+@@ -682,4 +682,11 @@ static inline bool dma_fence_is_container(struct dma_fence *fence)
+ return dma_fence_is_array(fence) || dma_fence_is_chain(fence);
+ }
+
++#define DMA_FENCE_WARN(f, fmt, args...) \
++ do { \
++ struct dma_fence *__ff = (f); \
++ pr_warn("f %llu#%llu: " fmt, __ff->context, __ff->seqno,\
++ ##args); \
++ } while (0)
++
+ #endif /* __LINUX_DMA_FENCE_H */
+diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h
+index 147feebd508ca..3f003d5fde534 100644
+--- a/include/linux/irqflags.h
++++ b/include/linux/irqflags.h
+@@ -114,7 +114,7 @@ do { \
+ # define lockdep_softirq_enter() do { } while (0)
+ # define lockdep_softirq_exit() do { } while (0)
+ # define lockdep_hrtimer_enter(__hrtimer) false
+-# define lockdep_hrtimer_exit(__context) do { } while (0)
++# define lockdep_hrtimer_exit(__context) do { (void)(__context); } while (0)
+ # define lockdep_posixtimer_enter() do { } while (0)
+ # define lockdep_posixtimer_exit() do { } while (0)
+ # define lockdep_irq_work_enter(__work) do { } while (0)
+diff --git a/include/linux/node.h b/include/linux/node.h
+index 25b66d705ee2e..dfc004e4bee74 100644
+--- a/include/linux/node.h
++++ b/include/linux/node.h
+@@ -34,6 +34,18 @@ struct access_coordinate {
+ unsigned int write_latency;
+ };
+
++/*
++ * ACCESS_COORDINATE_LOCAL correlates to ACCESS CLASS 0
++ * - access_coordinate between target node and nearest initiator node
++ * ACCESS_COORDINATE_CPU correlates to ACCESS CLASS 1
++ * - access_coordinate between target node and nearest CPU node
++ */
++enum access_coordinate_class {
++ ACCESS_COORDINATE_LOCAL,
++ ACCESS_COORDINATE_CPU,
++ ACCESS_COORDINATE_MAX
++};
++
+ enum cache_indexing {
+ NODE_CACHE_DIRECT_MAP,
+ NODE_CACHE_INDEXED,
+@@ -66,7 +78,7 @@ struct node_cache_attrs {
+ #ifdef CONFIG_HMEM_REPORTING
+ void node_add_cache(unsigned int nid, struct node_cache_attrs *cache_attrs);
+ void node_set_perf_attrs(unsigned int nid, struct access_coordinate *coord,
+- unsigned access);
++ enum access_coordinate_class access);
+ #else
+ static inline void node_add_cache(unsigned int nid,
+ struct node_cache_attrs *cache_attrs)
+@@ -75,7 +87,7 @@ static inline void node_add_cache(unsigned int nid,
+
+ static inline void node_set_perf_attrs(unsigned int nid,
+ struct access_coordinate *coord,
+- unsigned access)
++ enum access_coordinate_class access)
+ {
+ }
+ #endif
+@@ -137,7 +149,7 @@ extern void unregister_memory_block_under_nodes(struct memory_block *mem_blk);
+
+ extern int register_memory_node_under_compute_node(unsigned int mem_nid,
+ unsigned int cpu_nid,
+- unsigned access);
++ enum access_coordinate_class access);
+ #else
+ static inline void node_dev_init(void)
+ {
+diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h
+index ffe48e69b3f3a..457879938fc19 100644
+--- a/include/linux/u64_stats_sync.h
++++ b/include/linux/u64_stats_sync.h
+@@ -135,10 +135,11 @@ static inline void u64_stats_inc(u64_stats_t *p)
+ p->v++;
+ }
+
+-static inline void u64_stats_init(struct u64_stats_sync *syncp)
+-{
+- seqcount_init(&syncp->seq);
+-}
++#define u64_stats_init(syncp) \
++ do { \
++ struct u64_stats_sync *__s = (syncp); \
++ seqcount_init(&__s->seq); \
++ } while (0)
+
+ static inline void __u64_stats_update_begin(struct u64_stats_sync *syncp)
+ {
+diff --git a/include/net/addrconf.h b/include/net/addrconf.h
+index 61ebe723ee4d5..facb7a469efad 100644
+--- a/include/net/addrconf.h
++++ b/include/net/addrconf.h
+@@ -437,6 +437,10 @@ static inline void in6_ifa_hold(struct inet6_ifaddr *ifp)
+ refcount_inc(&ifp->refcnt);
+ }
+
++static inline bool in6_ifa_hold_safe(struct inet6_ifaddr *ifp)
++{
++ return refcount_inc_not_zero(&ifp->refcnt);
++}
+
+ /*
+ * compute link-local solicited-node multicast address
+diff --git a/include/net/af_unix.h b/include/net/af_unix.h
+index afd40dce40f3d..d1b07ddbe677e 100644
+--- a/include/net/af_unix.h
++++ b/include/net/af_unix.h
+@@ -55,7 +55,7 @@ struct unix_sock {
+ struct mutex iolock, bindlock;
+ struct sock *peer;
+ struct list_head link;
+- atomic_long_t inflight;
++ unsigned long inflight;
+ spinlock_t lock;
+ unsigned long gc_flags;
+ #define UNIX_GC_CANDIDATE 0
+diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
+index 7ffa8c192c3f2..eaec5d6caa29d 100644
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -164,6 +164,8 @@ struct bt_voice {
+ #define BT_ISO_QOS_BIG_UNSET 0xff
+ #define BT_ISO_QOS_BIS_UNSET 0xff
+
++#define BT_ISO_SYNC_TIMEOUT 0x07d0 /* 20 secs */
++
+ struct bt_iso_io_qos {
+ __u32 interval;
+ __u16 latency;
+@@ -583,6 +585,15 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
+ return skb;
+ }
+
++static inline int bt_copy_from_sockptr(void *dst, size_t dst_size,
++ sockptr_t src, size_t src_size)
++{
++ if (dst_size > src_size)
++ return -EINVAL;
++
++ return copy_from_sockptr(dst, src, dst_size);
++}
++
+ int bt_to_errno(u16 code);
+ __u8 bt_status(int err);
+
+diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
+index 2d746f4c9a0a4..6690939f241a4 100644
+--- a/include/net/ip_tunnels.h
++++ b/include/net/ip_tunnels.h
+@@ -360,6 +360,39 @@ static inline bool pskb_inet_may_pull(struct sk_buff *skb)
+ return pskb_network_may_pull(skb, nhlen);
+ }
+
++/* Variant of pskb_inet_may_pull().
++ */
++static inline bool skb_vlan_inet_prepare(struct sk_buff *skb)
++{
++ int nhlen = 0, maclen = ETH_HLEN;
++ __be16 type = skb->protocol;
++
++ /* Essentially this is skb_protocol(skb, true)
++ * And we get MAC len.
++ */
++ if (eth_type_vlan(type))
++ type = __vlan_get_protocol(skb, type, &maclen);
++
++ switch (type) {
++#if IS_ENABLED(CONFIG_IPV6)
++ case htons(ETH_P_IPV6):
++ nhlen = sizeof(struct ipv6hdr);
++ break;
++#endif
++ case htons(ETH_P_IP):
++ nhlen = sizeof(struct iphdr);
++ break;
++ }
++ /* For ETH_P_IPV6/ETH_P_IP we make sure to pull
++ * a base network header in skb->head.
++ */
++ if (!pskb_may_pull(skb, maclen + nhlen))
++ return false;
++
++ skb_set_network_header(skb, maclen);
++ return true;
++}
++
+ static inline int ip_encap_hlen(struct ip_tunnel_encap *e)
+ {
+ const struct ip_tunnel_encap_ops *ops;
+diff --git a/init/main.c b/init/main.c
+index 9e6ab6d593bd8..98fdd93d79a5c 100644
+--- a/init/main.c
++++ b/init/main.c
+@@ -485,6 +485,11 @@ static int __init warn_bootconfig(char *str)
+
+ early_param("bootconfig", warn_bootconfig);
+
++bool __init cmdline_has_extra_options(void)
++{
++ return extra_command_line || extra_init_args;
++}
++
+ /* Change NUL term back to "=", to make "param" the whole string. */
+ static void __init repair_env_string(char *param, char *val)
+ {
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index 0f52ea80103ef..3fc792dfc6ae7 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -949,6 +949,8 @@ bool io_fill_cqe_req_aux(struct io_kiocb *req, bool defer, s32 res, u32 cflags)
+ u64 user_data = req->cqe.user_data;
+ struct io_uring_cqe *cqe;
+
++ lockdep_assert(!io_wq_current_is_worker());
++
+ if (!defer)
+ return __io_post_aux_cqe(ctx, user_data, res, cflags, false);
+
+@@ -1950,6 +1952,29 @@ void io_wq_submit_work(struct io_wq_work *work)
+ goto fail;
+ }
+
++ /*
++ * If DEFER_TASKRUN is set, it's only allowed to post CQEs from the
++ * submitter task context. Final request completions are handed to the
++ * right context, however this is not the case of auxiliary CQEs,
++ * which is the main mean of operation for multishot requests.
++ * Don't allow any multishot execution from io-wq. It's more restrictive
++ * than necessary and also cleaner.
++ */
++ if (req->flags & REQ_F_APOLL_MULTISHOT) {
++ err = -EBADFD;
++ if (!file_can_poll(req->file))
++ goto fail;
++ if (req->file->f_flags & O_NONBLOCK ||
++ req->file->f_mode & FMODE_NOWAIT) {
++ err = -ECANCELED;
++ if (io_arm_poll_handler(req, issue_flags) != IO_APOLL_OK)
++ goto fail;
++ return;
++ } else {
++ req->flags &= ~REQ_F_APOLL_MULTISHOT;
++ }
++ }
++
+ if (req->flags & REQ_F_FORCE_ASYNC) {
+ bool opcode_poll = def->pollin || def->pollout;
+
+diff --git a/io_uring/net.c b/io_uring/net.c
+index 5a4001139e288..46ea09e1e3829 100644
+--- a/io_uring/net.c
++++ b/io_uring/net.c
+@@ -78,19 +78,6 @@ struct io_sr_msg {
+ */
+ #define MULTISHOT_MAX_RETRY 32
+
+-static inline bool io_check_multishot(struct io_kiocb *req,
+- unsigned int issue_flags)
+-{
+- /*
+- * When ->locked_cq is set we only allow to post CQEs from the original
+- * task context. Usual request completions will be handled in other
+- * generic paths but multipoll may decide to post extra cqes.
+- */
+- return !(issue_flags & IO_URING_F_IOWQ) ||
+- !(req->flags & REQ_F_APOLL_MULTISHOT) ||
+- !req->ctx->task_complete;
+-}
+-
+ int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+ {
+ struct io_shutdown *shutdown = io_kiocb_to_cmd(req, struct io_shutdown);
+@@ -837,9 +824,6 @@ int io_recvmsg(struct io_kiocb *req, unsigned int issue_flags)
+ (sr->flags & IORING_RECVSEND_POLL_FIRST))
+ return io_setup_async_msg(req, kmsg, issue_flags);
+
+- if (!io_check_multishot(req, issue_flags))
+- return io_setup_async_msg(req, kmsg, issue_flags);
+-
+ retry_multishot:
+ if (io_do_buffer_select(req)) {
+ void __user *buf;
+@@ -935,9 +919,6 @@ int io_recv(struct io_kiocb *req, unsigned int issue_flags)
+ (sr->flags & IORING_RECVSEND_POLL_FIRST))
+ return -EAGAIN;
+
+- if (!io_check_multishot(req, issue_flags))
+- return -EAGAIN;
+-
+ sock = sock_from_file(req->file);
+ if (unlikely(!sock))
+ return -ENOTSOCK;
+@@ -1274,6 +1255,7 @@ int io_sendmsg_zc(struct io_kiocb *req, unsigned int issue_flags)
+
+ if (req_has_async_data(req)) {
+ kmsg = req->async_data;
++ kmsg->msg.msg_control_user = sr->msg_control;
+ } else {
+ ret = io_sendmsg_copy_hdr(req, &iomsg);
+ if (ret)
+@@ -1386,8 +1368,6 @@ int io_accept(struct io_kiocb *req, unsigned int issue_flags)
+ struct file *file;
+ int ret, fd;
+
+- if (!io_check_multishot(req, issue_flags))
+- return -EAGAIN;
+ retry:
+ if (!fixed) {
+ fd = __get_unused_fd_flags(accept->flags, accept->nofile);
+diff --git a/io_uring/rw.c b/io_uring/rw.c
+index dd6fe3b328f40..c3c154790e452 100644
+--- a/io_uring/rw.c
++++ b/io_uring/rw.c
+@@ -932,8 +932,6 @@ int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags)
+ */
+ if (!file_can_poll(req->file))
+ return -EBADFD;
+- if (issue_flags & IO_URING_F_IOWQ)
+- return -EAGAIN;
+
+ ret = __io_read(req, issue_flags);
+
+diff --git a/kernel/cpu.c b/kernel/cpu.c
+index e6ec3ba4950b4..980908ef958c1 100644
+--- a/kernel/cpu.c
++++ b/kernel/cpu.c
+@@ -3207,7 +3207,8 @@ enum cpu_mitigations {
+ };
+
+ static enum cpu_mitigations cpu_mitigations __ro_after_init =
+- CPU_MITIGATIONS_AUTO;
++ IS_ENABLED(CONFIG_SPECULATION_MITIGATIONS) ? CPU_MITIGATIONS_AUTO :
++ CPU_MITIGATIONS_OFF;
+
+ static int __init mitigations_parse_cmdline(char *arg)
+ {
+diff --git a/kernel/kprobes.c b/kernel/kprobes.c
+index 9d9095e817928..65adc815fc6e6 100644
+--- a/kernel/kprobes.c
++++ b/kernel/kprobes.c
+@@ -1567,10 +1567,17 @@ static int check_kprobe_address_safe(struct kprobe *p,
+ jump_label_lock();
+ preempt_disable();
+
+- /* Ensure it is not in reserved area nor out of text */
+- if (!(core_kernel_text((unsigned long) p->addr) ||
+- is_module_text_address((unsigned long) p->addr)) ||
+- in_gate_area_no_mm((unsigned long) p->addr) ||
++ /* Ensure the address is in a text area, and find a module if exists. */
++ *probed_mod = NULL;
++ if (!core_kernel_text((unsigned long) p->addr)) {
++ *probed_mod = __module_text_address((unsigned long) p->addr);
++ if (!(*probed_mod)) {
++ ret = -EINVAL;
++ goto out;
++ }
++ }
++ /* Ensure it is not in reserved area. */
++ if (in_gate_area_no_mm((unsigned long) p->addr) ||
+ within_kprobe_blacklist((unsigned long) p->addr) ||
+ jump_label_text_reserved(p->addr, p->addr) ||
+ static_call_text_reserved(p->addr, p->addr) ||
+@@ -1580,8 +1587,7 @@ static int check_kprobe_address_safe(struct kprobe *p,
+ goto out;
+ }
+
+- /* Check if 'p' is probing a module. */
+- *probed_mod = __module_text_address((unsigned long) p->addr);
++ /* Get module refcount and reject __init functions for loaded modules. */
+ if (*probed_mod) {
+ /*
+ * We must hold a refcount of the probed module while updating
+diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
+index a718067deecee..3aae526cc4aac 100644
+--- a/kernel/power/suspend.c
++++ b/kernel/power/suspend.c
+@@ -106,6 +106,12 @@ static void s2idle_enter(void)
+ swait_event_exclusive(s2idle_wait_head,
+ s2idle_state == S2IDLE_STATE_WAKE);
+
++ /*
++ * Kick all CPUs to ensure that they resume their timers and restore
++ * consistent system state.
++ */
++ wake_up_all_idle_cpus();
++
+ cpus_read_unlock();
+
+ raw_spin_lock_irq(&s2idle_lock);
+diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
+index 2ad234366d21c..faf56d9a9e88e 100644
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -1400,7 +1400,6 @@ static void rb_tail_page_update(struct ring_buffer_per_cpu *cpu_buffer,
+ old_write = local_add_return(RB_WRITE_INTCNT, &next_page->write);
+ old_entries = local_add_return(RB_WRITE_INTCNT, &next_page->entries);
+
+- local_inc(&cpu_buffer->pages_touched);
+ /*
+ * Just make sure we have seen our old_write and synchronize
+ * with any interrupts that come in.
+@@ -1437,8 +1436,9 @@ static void rb_tail_page_update(struct ring_buffer_per_cpu *cpu_buffer,
+ */
+ local_set(&next_page->page->commit, 0);
+
+- /* Again, either we update tail_page or an interrupt does */
+- (void)cmpxchg(&cpu_buffer->tail_page, tail_page, next_page);
++ /* Either we update tail_page or an interrupt does */
++ if (try_cmpxchg(&cpu_buffer->tail_page, &tail_page, next_page))
++ local_inc(&cpu_buffer->pages_touched);
+ }
+ }
+
+diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
+index 7c364b87352ee..52f75c36bbca4 100644
+--- a/kernel/trace/trace_events.c
++++ b/kernel/trace/trace_events.c
+@@ -1670,6 +1670,7 @@ static int trace_format_open(struct inode *inode, struct file *file)
+ return 0;
+ }
+
++#ifdef CONFIG_PERF_EVENTS
+ static ssize_t
+ event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+ {
+@@ -1684,6 +1685,7 @@ event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
+
+ return simple_read_from_buffer(ubuf, cnt, ppos, buf, len);
+ }
++#endif
+
+ static ssize_t
+ event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
+@@ -2152,10 +2154,12 @@ static const struct file_operations ftrace_event_format_fops = {
+ .release = seq_release,
+ };
+
++#ifdef CONFIG_PERF_EVENTS
+ static const struct file_operations ftrace_event_id_fops = {
+ .read = event_id_read,
+ .llseek = default_llseek,
+ };
++#endif
+
+ static const struct file_operations ftrace_event_filter_fops = {
+ .open = tracing_open_file_tr,
+diff --git a/lib/checksum_kunit.c b/lib/checksum_kunit.c
+index bf70850035c76..404dba36bae38 100644
+--- a/lib/checksum_kunit.c
++++ b/lib/checksum_kunit.c
+@@ -594,13 +594,15 @@ static void test_ip_fast_csum(struct kunit *test)
+
+ static void test_csum_ipv6_magic(struct kunit *test)
+ {
+-#if defined(CONFIG_NET)
+ const struct in6_addr *saddr;
+ const struct in6_addr *daddr;
+ unsigned int len;
+ unsigned char proto;
+ __wsum csum;
+
++ if (!IS_ENABLED(CONFIG_NET))
++ return;
++
+ const int daddr_offset = sizeof(struct in6_addr);
+ const int len_offset = sizeof(struct in6_addr) + sizeof(struct in6_addr);
+ const int proto_offset = sizeof(struct in6_addr) + sizeof(struct in6_addr) +
+@@ -618,7 +620,6 @@ static void test_csum_ipv6_magic(struct kunit *test)
+ CHECK_EQ(to_sum16(expected_csum_ipv6_magic[i]),
+ csum_ipv6_magic(saddr, daddr, len, proto, csum));
+ }
+-#endif /* !CONFIG_NET */
+ }
+
+ static struct kunit_case __refdata checksum_test_cases[] = {
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index b95c36765d045..2243cec18ecc8 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -3948,7 +3948,7 @@ void batadv_tt_local_resize_to_mtu(struct net_device *soft_iface)
+
+ spin_lock_bh(&bat_priv->tt.commit_lock);
+
+- while (true) {
++ while (timeout) {
+ table_size = batadv_tt_local_table_transmit_size(bat_priv);
+ if (packet_size_max >= table_size)
+ break;
+diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
+index 00e02138003ec..efea25eb56ce0 100644
+--- a/net/bluetooth/hci_request.c
++++ b/net/bluetooth/hci_request.c
+@@ -105,8 +105,10 @@ void hci_req_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode,
+ if (hdev->req_status == HCI_REQ_PEND) {
+ hdev->req_result = result;
+ hdev->req_status = HCI_REQ_DONE;
+- if (skb)
++ if (skb) {
++ kfree_skb(hdev->req_skb);
+ hdev->req_skb = skb_get(skb);
++ }
+ wake_up_interruptible(&hdev->req_wait_q);
+ }
+ }
+diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
+index 3e7cd330d731a..3f5f0932330d2 100644
+--- a/net/bluetooth/hci_sock.c
++++ b/net/bluetooth/hci_sock.c
+@@ -1946,10 +1946,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
+
+ switch (optname) {
+ case HCI_DATA_DIR:
+- if (copy_from_sockptr(&opt, optval, sizeof(opt))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR;
+@@ -1958,10 +1957,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
+ break;
+
+ case HCI_TIME_STAMP:
+- if (copy_from_sockptr(&opt, optval, sizeof(opt))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP;
+@@ -1979,11 +1977,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
+ uf.event_mask[1] = *((u32 *) f->event_mask + 1);
+ }
+
+- len = min_t(unsigned int, len, sizeof(uf));
+- if (copy_from_sockptr(&uf, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&uf, sizeof(uf), optval, len);
++ if (err)
+ break;
+- }
+
+ if (!capable(CAP_NET_RAW)) {
+ uf.type_mask &= hci_sec_filter.type_mask;
+@@ -2042,10 +2038,9 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
+ goto done;
+ }
+
+- if (copy_from_sockptr(&opt, optval, sizeof(opt))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
++ if (err)
+ break;
+- }
+
+ hci_pi(sk)->mtu = opt;
+ break;
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 824ce03bb361b..e1050d7d21a59 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -2611,6 +2611,14 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
+ return filter_policy;
+ }
+
++static void hci_le_scan_phy_params(struct hci_cp_le_scan_phy_params *cp,
++ u8 type, u16 interval, u16 window)
++{
++ cp->type = type;
++ cp->interval = cpu_to_le16(interval);
++ cp->window = cpu_to_le16(window);
++}
++
+ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
+ u16 interval, u16 window,
+ u8 own_addr_type, u8 filter_policy)
+@@ -2618,7 +2626,7 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
+ struct hci_cp_le_set_ext_scan_params *cp;
+ struct hci_cp_le_scan_phy_params *phy;
+ u8 data[sizeof(*cp) + sizeof(*phy) * 2];
+- u8 num_phy = 0;
++ u8 num_phy = 0x00;
+
+ cp = (void *)data;
+ phy = (void *)cp->data;
+@@ -2628,28 +2636,64 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type,
+ cp->own_addr_type = own_addr_type;
+ cp->filter_policy = filter_policy;
+
++ /* Check if PA Sync is in progress then select the PHY based on the
++ * hci_conn.iso_qos.
++ */
++ if (hci_dev_test_flag(hdev, HCI_PA_SYNC)) {
++ struct hci_cp_le_add_to_accept_list *sent;
++
++ sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_ACCEPT_LIST);
++ if (sent) {
++ struct hci_conn *conn;
++
++ conn = hci_conn_hash_lookup_ba(hdev, ISO_LINK,
++ &sent->bdaddr);
++ if (conn) {
++ struct bt_iso_qos *qos = &conn->iso_qos;
++
++ if (qos->bcast.in.phy & BT_ISO_PHY_1M ||
++ qos->bcast.in.phy & BT_ISO_PHY_2M) {
++ cp->scanning_phys |= LE_SCAN_PHY_1M;
++ hci_le_scan_phy_params(phy, type,
++ interval,
++ window);
++ num_phy++;
++ phy++;
++ }
++
++ if (qos->bcast.in.phy & BT_ISO_PHY_CODED) {
++ cp->scanning_phys |= LE_SCAN_PHY_CODED;
++ hci_le_scan_phy_params(phy, type,
++ interval * 3,
++ window * 3);
++ num_phy++;
++ phy++;
++ }
++
++ if (num_phy)
++ goto done;
++ }
++ }
++ }
++
+ if (scan_1m(hdev) || scan_2m(hdev)) {
+ cp->scanning_phys |= LE_SCAN_PHY_1M;
+-
+- phy->type = type;
+- phy->interval = cpu_to_le16(interval);
+- phy->window = cpu_to_le16(window);
+-
++ hci_le_scan_phy_params(phy, type, interval, window);
+ num_phy++;
+ phy++;
+ }
+
+ if (scan_coded(hdev)) {
+ cp->scanning_phys |= LE_SCAN_PHY_CODED;
+-
+- phy->type = type;
+- phy->interval = cpu_to_le16(interval);
+- phy->window = cpu_to_le16(window);
+-
++ hci_le_scan_phy_params(phy, type, interval * 3, window * 3);
+ num_phy++;
+ phy++;
+ }
+
++done:
++ if (!num_phy)
++ return -EINVAL;
++
+ return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS,
+ sizeof(*cp) + sizeof(*phy) * num_phy,
+ data, HCI_CMD_TIMEOUT);
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index 04f6572d35f17..a8b05baa8e5a9 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -837,10 +837,10 @@ static struct bt_iso_qos default_qos = {
+ .bcode = {0x00},
+ .options = 0x00,
+ .skip = 0x0000,
+- .sync_timeout = 0x4000,
++ .sync_timeout = BT_ISO_SYNC_TIMEOUT,
+ .sync_cte_type = 0x00,
+ .mse = 0x00,
+- .timeout = 0x4000,
++ .timeout = BT_ISO_SYNC_TIMEOUT,
+ },
+ };
+
+@@ -1430,8 +1430,8 @@ static bool check_ucast_qos(struct bt_iso_qos *qos)
+
+ static bool check_bcast_qos(struct bt_iso_qos *qos)
+ {
+- if (qos->bcast.sync_factor == 0x00)
+- return false;
++ if (!qos->bcast.sync_factor)
++ qos->bcast.sync_factor = 0x01;
+
+ if (qos->bcast.packing > 0x01)
+ return false;
+@@ -1454,6 +1454,9 @@ static bool check_bcast_qos(struct bt_iso_qos *qos)
+ if (qos->bcast.skip > 0x01f3)
+ return false;
+
++ if (!qos->bcast.sync_timeout)
++ qos->bcast.sync_timeout = BT_ISO_SYNC_TIMEOUT;
++
+ if (qos->bcast.sync_timeout < 0x000a || qos->bcast.sync_timeout > 0x4000)
+ return false;
+
+@@ -1463,6 +1466,9 @@ static bool check_bcast_qos(struct bt_iso_qos *qos)
+ if (qos->bcast.mse > 0x1f)
+ return false;
+
++ if (!qos->bcast.timeout)
++ qos->bcast.sync_timeout = BT_ISO_SYNC_TIMEOUT;
++
+ if (qos->bcast.timeout < 0x000a || qos->bcast.timeout > 0x4000)
+ return false;
+
+@@ -1473,7 +1479,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ sockptr_t optval, unsigned int optlen)
+ {
+ struct sock *sk = sock->sk;
+- int len, err = 0;
++ int err = 0;
+ struct bt_iso_qos qos = default_qos;
+ u32 opt;
+
+@@ -1488,10 +1494,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+@@ -1500,10 +1505,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+
+ case BT_PKT_STATUS:
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags);
+@@ -1518,17 +1522,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- len = min_t(unsigned int, sizeof(qos), optlen);
+-
+- if (copy_from_sockptr(&qos, optval, len)) {
+- err = -EFAULT;
+- break;
+- }
+-
+- if (len == sizeof(qos.ucast) && !check_ucast_qos(&qos)) {
+- err = -EINVAL;
++ err = bt_copy_from_sockptr(&qos, sizeof(qos), optval, optlen);
++ if (err)
+ break;
+- }
+
+ iso_pi(sk)->qos = qos;
+ iso_pi(sk)->qos_user_set = true;
+@@ -1543,18 +1539,16 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
+ }
+
+ if (optlen > sizeof(iso_pi(sk)->base)) {
+- err = -EOVERFLOW;
++ err = -EINVAL;
+ break;
+ }
+
+- len = min_t(unsigned int, sizeof(iso_pi(sk)->base), optlen);
+-
+- if (copy_from_sockptr(iso_pi(sk)->base, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(iso_pi(sk)->base, optlen, optval,
++ optlen);
++ if (err)
+ break;
+- }
+
+- iso_pi(sk)->base_len = len;
++ iso_pi(sk)->base_len = optlen;
+
+ break;
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index ab5a9d42fae71..706d2478ddb33 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -4054,8 +4054,7 @@ static int l2cap_connect_req(struct l2cap_conn *conn,
+ return -EPROTO;
+
+ hci_dev_lock(hdev);
+- if (hci_dev_test_flag(hdev, HCI_MGMT) &&
+- !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
++ if (hci_dev_test_flag(hdev, HCI_MGMT))
+ mgmt_device_connected(hdev, hcon, NULL, 0);
+ hci_dev_unlock(hdev);
+
+diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
+index ee7a41d6994fc..1eeea5d1306c2 100644
+--- a/net/bluetooth/l2cap_sock.c
++++ b/net/bluetooth/l2cap_sock.c
+@@ -726,7 +726,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
+ struct sock *sk = sock->sk;
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+ struct l2cap_options opts;
+- int len, err = 0;
++ int err = 0;
+ u32 opt;
+
+ BT_DBG("sk %p", sk);
+@@ -753,11 +753,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
+ opts.max_tx = chan->max_tx;
+ opts.txwin_size = chan->tx_win;
+
+- len = min_t(unsigned int, sizeof(opts), optlen);
+- if (copy_from_sockptr(&opts, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opts, sizeof(opts), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) {
+ err = -EINVAL;
+@@ -800,10 +798,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
+ break;
+
+ case L2CAP_LM:
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt & L2CAP_LM_FIPS) {
+ err = -EINVAL;
+@@ -884,7 +881,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ struct bt_security sec;
+ struct bt_power pwr;
+ struct l2cap_conn *conn;
+- int len, err = 0;
++ int err = 0;
+ u32 opt;
+ u16 mtu;
+ u8 mode;
+@@ -910,11 +907,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ sec.level = BT_SECURITY_LOW;
+
+- len = min_t(unsigned int, sizeof(sec), optlen);
+- if (copy_from_sockptr(&sec, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (sec.level < BT_SECURITY_LOW ||
+ sec.level > BT_SECURITY_FIPS) {
+@@ -959,10 +954,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt) {
+ set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+@@ -974,10 +968,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+
+ case BT_FLUSHABLE:
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt > BT_FLUSHABLE_ON) {
+ err = -EINVAL;
+@@ -1009,11 +1002,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
+
+- len = min_t(unsigned int, sizeof(pwr), optlen);
+- if (copy_from_sockptr(&pwr, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&pwr, sizeof(pwr), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (pwr.force_active)
+ set_bit(FLAG_FORCE_ACTIVE, &chan->flags);
+@@ -1022,10 +1013,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+
+ case BT_CHANNEL_POLICY:
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ err = -EOPNOTSUPP;
+ break;
+@@ -1054,10 +1044,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&mtu, optval, sizeof(u16))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&mtu, sizeof(mtu), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (chan->mode == L2CAP_MODE_EXT_FLOWCTL &&
+ sk->sk_state == BT_CONNECTED)
+@@ -1085,10 +1074,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&mode, optval, sizeof(u8))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&mode, sizeof(mode), optval, optlen);
++ if (err)
+ break;
+- }
+
+ BT_DBG("mode %u", mode);
+
+diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
+index b54e8a530f55a..29aa07e9db9d7 100644
+--- a/net/bluetooth/rfcomm/sock.c
++++ b/net/bluetooth/rfcomm/sock.c
+@@ -629,7 +629,7 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname,
+
+ switch (optname) {
+ case RFCOMM_LM:
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
++ if (bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen)) {
+ err = -EFAULT;
+ break;
+ }
+@@ -664,7 +664,6 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
+ struct sock *sk = sock->sk;
+ struct bt_security sec;
+ int err = 0;
+- size_t len;
+ u32 opt;
+
+ BT_DBG("sk %p", sk);
+@@ -686,11 +685,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ sec.level = BT_SECURITY_LOW;
+
+- len = min_t(unsigned int, sizeof(sec), optlen);
+- if (copy_from_sockptr(&sec, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (sec.level > BT_SECURITY_HIGH) {
+ err = -EINVAL;
+@@ -706,10 +703,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index c736186aba26b..8e4f39b8601cb 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -823,7 +823,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+ sockptr_t optval, unsigned int optlen)
+ {
+ struct sock *sk = sock->sk;
+- int len, err = 0;
++ int err = 0;
+ struct bt_voice voice;
+ u32 opt;
+ struct bt_codecs *codecs;
+@@ -842,10 +842,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+@@ -862,11 +861,10 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+
+ voice.setting = sco_pi(sk)->setting;
+
+- len = min_t(unsigned int, sizeof(voice), optlen);
+- if (copy_from_sockptr(&voice, optval, len)) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&voice, sizeof(voice), optval,
++ optlen);
++ if (err)
+ break;
+- }
+
+ /* Explicitly check for these values */
+ if (voice.setting != BT_VOICE_TRANSPARENT &&
+@@ -889,10 +887,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+
+ case BT_PKT_STATUS:
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt)
+ set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags);
+@@ -933,9 +930,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(buffer, optval, optlen)) {
++ err = bt_copy_from_sockptr(buffer, optlen, optval, optlen);
++ if (err) {
+ hci_dev_put(hdev);
+- err = -EFAULT;
+ break;
+ }
+
+diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
+index b150c9929b12e..14365b20f1c5c 100644
+--- a/net/ipv4/netfilter/arp_tables.c
++++ b/net/ipv4/netfilter/arp_tables.c
+@@ -966,6 +966,8 @@ static int do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ return -ENOMEM;
+ if (tmp.num_counters == 0)
+ return -EINVAL;
++ if ((u64)len < (u64)tmp.size + sizeof(tmp))
++ return -EINVAL;
+
+ tmp.name[sizeof(tmp.name)-1] = 0;
+
+@@ -1266,6 +1268,8 @@ static int compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ return -ENOMEM;
+ if (tmp.num_counters == 0)
+ return -EINVAL;
++ if ((u64)len < (u64)tmp.size + sizeof(tmp))
++ return -EINVAL;
+
+ tmp.name[sizeof(tmp.name)-1] = 0;
+
+diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
+index 4876707595781..fe89a056eb06c 100644
+--- a/net/ipv4/netfilter/ip_tables.c
++++ b/net/ipv4/netfilter/ip_tables.c
+@@ -1118,6 +1118,8 @@ do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ return -ENOMEM;
+ if (tmp.num_counters == 0)
+ return -EINVAL;
++ if ((u64)len < (u64)tmp.size + sizeof(tmp))
++ return -EINVAL;
+
+ tmp.name[sizeof(tmp.name)-1] = 0;
+
+@@ -1504,6 +1506,8 @@ compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ return -ENOMEM;
+ if (tmp.num_counters == 0)
+ return -EINVAL;
++ if ((u64)len < (u64)tmp.size + sizeof(tmp))
++ return -EINVAL;
+
+ tmp.name[sizeof(tmp.name)-1] = 0;
+
+diff --git a/net/ipv4/route.c b/net/ipv4/route.c
+index 16615d107cf06..15c37c8113fc8 100644
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -926,13 +926,11 @@ void ip_rt_send_redirect(struct sk_buff *skb)
+ icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw);
+ peer->rate_last = jiffies;
+ ++peer->n_redirects;
+-#ifdef CONFIG_IP_ROUTE_VERBOSE
+- if (log_martians &&
++ if (IS_ENABLED(CONFIG_IP_ROUTE_VERBOSE) && log_martians &&
+ peer->n_redirects == ip_rt_redirect_number)
+ net_warn_ratelimited("host %pI4/if%d ignores redirects for %pI4 to %pI4\n",
+ &ip_hdr(skb)->saddr, inet_iif(skb),
+ &ip_hdr(skb)->daddr, &gw);
+-#endif
+ }
+ out_put_peer:
+ inet_putpeer(peer);
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index 055230b669cf2..37d48aa073c3c 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -2061,9 +2061,10 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add
+ if (ipv6_addr_equal(&ifp->addr, addr)) {
+ if (!dev || ifp->idev->dev == dev ||
+ !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) {
+- result = ifp;
+- in6_ifa_hold(ifp);
+- break;
++ if (in6_ifa_hold_safe(ifp)) {
++ result = ifp;
++ break;
++ }
+ }
+ }
+ }
+diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
+index 54294f6a8ec51..8184076a3924e 100644
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -1375,7 +1375,10 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
+ struct nl_info *info, struct netlink_ext_ack *extack)
+ {
+ struct fib6_table *table = rt->fib6_table;
+- struct fib6_node *fn, *pn = NULL;
++ struct fib6_node *fn;
++#ifdef CONFIG_IPV6_SUBTREES
++ struct fib6_node *pn = NULL;
++#endif
+ int err = -ENOMEM;
+ int allow_create = 1;
+ int replace_required = 0;
+@@ -1399,9 +1402,9 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
+ goto out;
+ }
+
++#ifdef CONFIG_IPV6_SUBTREES
+ pn = fn;
+
+-#ifdef CONFIG_IPV6_SUBTREES
+ if (rt->fib6_src.plen) {
+ struct fib6_node *sn;
+
+diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
+index 636b360311c53..131f7bb2110d3 100644
+--- a/net/ipv6/netfilter/ip6_tables.c
++++ b/net/ipv6/netfilter/ip6_tables.c
+@@ -1135,6 +1135,8 @@ do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ return -ENOMEM;
+ if (tmp.num_counters == 0)
+ return -EINVAL;
++ if ((u64)len < (u64)tmp.size + sizeof(tmp))
++ return -EINVAL;
+
+ tmp.name[sizeof(tmp.name)-1] = 0;
+
+@@ -1513,6 +1515,8 @@ compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
+ return -ENOMEM;
+ if (tmp.num_counters == 0)
+ return -EINVAL;
++ if ((u64)len < (u64)tmp.size + sizeof(tmp))
++ return -EINVAL;
+
+ tmp.name[sizeof(tmp.name)-1] = 0;
+
+diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
+index 3019a4406ca4f..74b63cdb59923 100644
+--- a/net/openvswitch/conntrack.c
++++ b/net/openvswitch/conntrack.c
+@@ -1380,8 +1380,9 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
+ if (ct_info.timeout[0]) {
+ if (nf_ct_set_timeout(net, ct_info.ct, family, key->ip.proto,
+ ct_info.timeout))
+- pr_info_ratelimited("Failed to associated timeout "
+- "policy `%s'\n", ct_info.timeout);
++ OVS_NLERR(log,
++ "Failed to associated timeout policy '%s'",
++ ct_info.timeout);
+ else
+ ct_info.nf_ct_timeout = rcu_dereference(
+ nf_ct_timeout_find(ct_info.ct)->timeout);
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index 0748e7ea5210e..e37cf913818a1 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -980,11 +980,11 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern,
+ sk->sk_write_space = unix_write_space;
+ sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen;
+ sk->sk_destruct = unix_sock_destructor;
+- u = unix_sk(sk);
++ u = unix_sk(sk);
++ u->inflight = 0;
+ u->path.dentry = NULL;
+ u->path.mnt = NULL;
+ spin_lock_init(&u->lock);
+- atomic_long_set(&u->inflight, 0);
+ INIT_LIST_HEAD(&u->link);
+ mutex_init(&u->iolock); /* single task reading lock */
+ mutex_init(&u->bindlock); /* single task binding lock */
+@@ -2604,7 +2604,9 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
+ }
+ } else if (!(flags & MSG_PEEK)) {
+ skb_unlink(skb, &sk->sk_receive_queue);
+- consume_skb(skb);
++ WRITE_ONCE(u->oob_skb, NULL);
++ if (!WARN_ON_ONCE(skb_unref(skb)))
++ kfree_skb(skb);
+ skb = skb_peek(&sk->sk_receive_queue);
+ }
+ }
+diff --git a/net/unix/garbage.c b/net/unix/garbage.c
+index 027c86e804f8a..8734c0c1fc197 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -166,17 +166,18 @@ static void scan_children(struct sock *x, void (*func)(struct unix_sock *),
+
+ static void dec_inflight(struct unix_sock *usk)
+ {
+- atomic_long_dec(&usk->inflight);
++ usk->inflight--;
+ }
+
+ static void inc_inflight(struct unix_sock *usk)
+ {
+- atomic_long_inc(&usk->inflight);
++ usk->inflight++;
+ }
+
+ static void inc_inflight_move_tail(struct unix_sock *u)
+ {
+- atomic_long_inc(&u->inflight);
++ u->inflight++;
++
+ /* If this still might be part of a cycle, move it to the end
+ * of the list, so that it's checked even if it was already
+ * passed over
+@@ -234,20 +235,34 @@ void unix_gc(void)
+ * receive queues. Other, non candidate sockets _can_ be
+ * added to queue, so we must make sure only to touch
+ * candidates.
++ *
++ * Embryos, though never candidates themselves, affect which
++ * candidates are reachable by the garbage collector. Before
++ * being added to a listener's queue, an embryo may already
++ * receive data carrying SCM_RIGHTS, potentially making the
++ * passed socket a candidate that is not yet reachable by the
++ * collector. It becomes reachable once the embryo is
++ * enqueued. Therefore, we must ensure that no SCM-laden
++ * embryo appears in a (candidate) listener's queue between
++ * consecutive scan_children() calls.
+ */
+ list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
++ struct sock *sk = &u->sk;
+ long total_refs;
+- long inflight_refs;
+
+- total_refs = file_count(u->sk.sk_socket->file);
+- inflight_refs = atomic_long_read(&u->inflight);
++ total_refs = file_count(sk->sk_socket->file);
+
+- BUG_ON(inflight_refs < 1);
+- BUG_ON(total_refs < inflight_refs);
+- if (total_refs == inflight_refs) {
++ BUG_ON(!u->inflight);
++ BUG_ON(total_refs < u->inflight);
++ if (total_refs == u->inflight) {
+ list_move_tail(&u->link, &gc_candidates);
+ __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags);
+ __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
++
++ if (sk->sk_state == TCP_LISTEN) {
++ unix_state_lock(sk);
++ unix_state_unlock(sk);
++ }
+ }
+ }
+
+@@ -271,7 +286,7 @@ void unix_gc(void)
+ /* Move cursor to after the current position. */
+ list_move(&cursor, &u->link);
+
+- if (atomic_long_read(&u->inflight) > 0) {
++ if (u->inflight) {
+ list_move_tail(&u->link, ¬_cycle_list);
+ __clear_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
+ scan_children(&u->sk, inc_inflight_move_tail, NULL);
+diff --git a/net/unix/scm.c b/net/unix/scm.c
+index 822ce0d0d7915..e92f2fad64105 100644
+--- a/net/unix/scm.c
++++ b/net/unix/scm.c
+@@ -53,12 +53,13 @@ void unix_inflight(struct user_struct *user, struct file *fp)
+ if (s) {
+ struct unix_sock *u = unix_sk(s);
+
+- if (atomic_long_inc_return(&u->inflight) == 1) {
++ if (!u->inflight) {
+ BUG_ON(!list_empty(&u->link));
+ list_add_tail(&u->link, &gc_inflight_list);
+ } else {
+ BUG_ON(list_empty(&u->link));
+ }
++ u->inflight++;
+ /* Paired with READ_ONCE() in wait_for_unix_gc() */
+ WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + 1);
+ }
+@@ -75,10 +76,11 @@ void unix_notinflight(struct user_struct *user, struct file *fp)
+ if (s) {
+ struct unix_sock *u = unix_sk(s);
+
+- BUG_ON(!atomic_long_read(&u->inflight));
++ BUG_ON(!u->inflight);
+ BUG_ON(list_empty(&u->link));
+
+- if (atomic_long_dec_and_test(&u->inflight))
++ u->inflight--;
++ if (!u->inflight)
+ list_del_init(&u->link);
+ /* Paired with READ_ONCE() in wait_for_unix_gc() */
+ WRITE_ONCE(unix_tot_inflight, unix_tot_inflight - 1);
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index b78c0e095e221..7d1c0986f9bb3 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -1414,6 +1414,8 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname,
+ struct xsk_queue **q;
+ int entries;
+
++ if (optlen < sizeof(entries))
++ return -EINVAL;
+ if (copy_from_sockptr(&entries, optval, sizeof(entries)))
+ return -EFAULT;
+
+diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h
+index a781e6311810b..e3e260fe002f7 100644
+--- a/tools/testing/selftests/kselftest.h
++++ b/tools/testing/selftests/kselftest.h
+@@ -50,6 +50,7 @@
+ #include <stdarg.h>
+ #include <string.h>
+ #include <stdio.h>
++#include <sys/utsname.h>
+ #endif
+
+ #ifndef ARRAY_SIZE
+@@ -78,6 +79,9 @@
+ #define KSFT_XPASS 3
+ #define KSFT_SKIP 4
+
++#ifndef __noreturn
++#define __noreturn __attribute__((__noreturn__))
++#endif
+ #define __printf(a, b) __attribute__((format(printf, a, b)))
+
+ /* counters */
+@@ -254,13 +258,13 @@ static inline __printf(1, 2) void ksft_test_result_error(const char *msg, ...)
+ va_end(args);
+ }
+
+-static inline int ksft_exit_pass(void)
++static inline __noreturn int ksft_exit_pass(void)
+ {
+ ksft_print_cnts();
+ exit(KSFT_PASS);
+ }
+
+-static inline int ksft_exit_fail(void)
++static inline __noreturn int ksft_exit_fail(void)
+ {
+ ksft_print_cnts();
+ exit(KSFT_FAIL);
+@@ -287,7 +291,7 @@ static inline int ksft_exit_fail(void)
+ ksft_cnt.ksft_xfail + \
+ ksft_cnt.ksft_xskip)
+
+-static inline __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...)
++static inline __noreturn __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...)
+ {
+ int saved_errno = errno;
+ va_list args;
+@@ -302,19 +306,19 @@ static inline __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...)
+ exit(KSFT_FAIL);
+ }
+
+-static inline int ksft_exit_xfail(void)
++static inline __noreturn int ksft_exit_xfail(void)
+ {
+ ksft_print_cnts();
+ exit(KSFT_XFAIL);
+ }
+
+-static inline int ksft_exit_xpass(void)
++static inline __noreturn int ksft_exit_xpass(void)
+ {
+ ksft_print_cnts();
+ exit(KSFT_XPASS);
+ }
+
+-static inline __printf(1, 2) int ksft_exit_skip(const char *msg, ...)
++static inline __noreturn __printf(1, 2) int ksft_exit_skip(const char *msg, ...)
+ {
+ int saved_errno = errno;
+ va_list args;
+@@ -343,4 +347,21 @@ static inline __printf(1, 2) int ksft_exit_skip(const char *msg, ...)
+ exit(KSFT_SKIP);
+ }
+
++static inline int ksft_min_kernel_version(unsigned int min_major,
++ unsigned int min_minor)
++{
++#ifdef NOLIBC
++ ksft_print_msg("NOLIBC: Can't check kernel version: Function not implemented\n");
++ return 0;
++#else
++ unsigned int major, minor;
++ struct utsname info;
++
++ if (uname(&info) || sscanf(info.release, "%u.%u.", &major, &minor) != 2)
++ ksft_exit_fail_msg("Can't parse kernel version\n");
++
++ return major > min_major || (major == min_major && minor >= min_minor);
++#endif
++}
++
+ #endif /* __KSELFTEST_H */
+diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c
+index d49dd3ffd0d96..c001dd79179d5 100644
+--- a/tools/testing/selftests/timers/posix_timers.c
++++ b/tools/testing/selftests/timers/posix_timers.c
+@@ -66,7 +66,7 @@ static int check_diff(struct timeval start, struct timeval end)
+ diff = end.tv_usec - start.tv_usec;
+ diff += (end.tv_sec - start.tv_sec) * USECS_PER_SEC;
+
+- if (abs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) {
++ if (llabs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) {
+ printf("Diff too high: %lld..", diff);
+ return -1;
+ }
+@@ -184,80 +184,71 @@ static int check_timer_create(int which)
+ return 0;
+ }
+
+-int remain;
+-__thread int got_signal;
++static pthread_t ctd_thread;
++static volatile int ctd_count, ctd_failed;
+
+-static void *distribution_thread(void *arg)
++static void ctd_sighandler(int sig)
+ {
+- while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
+- return NULL;
++ if (pthread_self() != ctd_thread)
++ ctd_failed = 1;
++ ctd_count--;
+ }
+
+-static void distribution_handler(int nr)
++static void *ctd_thread_func(void *arg)
+ {
+- if (!__atomic_exchange_n(&got_signal, 1, __ATOMIC_RELAXED))
+- __atomic_fetch_sub(&remain, 1, __ATOMIC_RELAXED);
+-}
+-
+-/*
+- * Test that all running threads _eventually_ receive CLOCK_PROCESS_CPUTIME_ID
+- * timer signals. This primarily tests that the kernel does not favour any one.
+- */
+-static int check_timer_distribution(void)
+-{
+- int err, i;
+- timer_t id;
+- const int nthreads = 10;
+- pthread_t threads[nthreads];
+ struct itimerspec val = {
+ .it_value.tv_sec = 0,
+ .it_value.tv_nsec = 1000 * 1000,
+ .it_interval.tv_sec = 0,
+ .it_interval.tv_nsec = 1000 * 1000,
+ };
++ timer_t id;
+
+- remain = nthreads + 1; /* worker threads + this thread */
+- signal(SIGALRM, distribution_handler);
+- err = timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id);
+- if (err < 0) {
+- ksft_perror("Can't create timer");
+- return -1;
+- }
+- err = timer_settime(id, 0, &val, NULL);
+- if (err < 0) {
+- ksft_perror("Can't set timer");
+- return -1;
+- }
++ /* 1/10 seconds to ensure the leader sleeps */
++ usleep(10000);
+
+- for (i = 0; i < nthreads; i++) {
+- err = pthread_create(&threads[i], NULL, distribution_thread,
+- NULL);
+- if (err) {
+- ksft_print_msg("Can't create thread: %s (%d)\n",
+- strerror(errno), errno);
+- return -1;
+- }
+- }
++ ctd_count = 100;
++ if (timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id))
++ return "Can't create timer\n";
++ if (timer_settime(id, 0, &val, NULL))
++ return "Can't set timer\n";
+
+- /* Wait for all threads to receive the signal. */
+- while (__atomic_load_n(&remain, __ATOMIC_RELAXED));
++ while (ctd_count > 0 && !ctd_failed)
++ ;
+
+- for (i = 0; i < nthreads; i++) {
+- err = pthread_join(threads[i], NULL);
+- if (err) {
+- ksft_print_msg("Can't join thread: %s (%d)\n",
+- strerror(errno), errno);
+- return -1;
+- }
+- }
++ if (timer_delete(id))
++ return "Can't delete timer\n";
+
+- if (timer_delete(id)) {
+- ksft_perror("Can't delete timer");
+- return -1;
+- }
++ return NULL;
++}
++
++/*
++ * Test that only the running thread receives the timer signal.
++ */
++static int check_timer_distribution(void)
++{
++ const char *errmsg;
+
+- ksft_test_result_pass("check_timer_distribution\n");
++ signal(SIGALRM, ctd_sighandler);
++
++ errmsg = "Can't create thread\n";
++ if (pthread_create(&ctd_thread, NULL, ctd_thread_func, NULL))
++ goto err;
++
++ errmsg = "Can't join thread\n";
++ if (pthread_join(ctd_thread, (void **)&errmsg) || errmsg)
++ goto err;
++
++ if (!ctd_failed)
++ ksft_test_result_pass("check signal distribution\n");
++ else if (ksft_min_kernel_version(6, 3))
++ ksft_test_result_fail("check signal distribution\n");
++ else
++ ksft_test_result_skip("check signal distribution (old kernel)\n");
+ return 0;
++err:
++ ksft_print_msg("%s", errmsg);
++ return -1;
+ }
+
+ int main(int argc, char **argv)
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-21 22:25 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-04-21 22:25 UTC (permalink / raw
To: gentoo-commits
commit: 3584cee31ed8f353980cc8b10137fc86a44d0669
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sun Apr 21 22:24:38 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sun Apr 21 22:24:38 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=3584cee3
Remove redundant patch
Removed:
1800_gcc-plugins-stackleak-Avoid-head-text-section.patch
Bug: https://bugs.gentoo.org/930389
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 ---
...plugins-stackleak-Avoid-head-text-section.patch | 36 ----------------------
2 files changed, 40 deletions(-)
diff --git a/0000_README b/0000_README
index 1380bd5c..ba3f48c8 100644
--- a/0000_README
+++ b/0000_README
@@ -83,10 +83,6 @@ Patch: 1730_parisc-Disable-prctl.patch
From: https://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git
Desc: prctl: Temporarily disable prctl(PR_SET_MDWE) on parisc
-Patch: 1800_gcc-plugins-stackleak-Avoid-head-text-section.patch
-From: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
-Desc: gcc-plugins/stackleak: Avoid .head.text section
-
Patch: 2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch
From: https://lore.kernel.org/linux-bluetooth/20190522070540.48895-1-marcel@holtmann.org/raw
Desc: Bluetooth: Check key sizes only when Secure Simple Pairing is enabled. See bug #686758
diff --git a/1800_gcc-plugins-stackleak-Avoid-head-text-section.patch b/1800_gcc-plugins-stackleak-Avoid-head-text-section.patch
deleted file mode 100644
index 28964f01..00000000
--- a/1800_gcc-plugins-stackleak-Avoid-head-text-section.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-From e7d24c0aa8e678f41457d1304e2091cac6fd1a2e Mon Sep 17 00:00:00 2001
-From: Ard Biesheuvel <ardb@kernel.org>
-Date: Thu, 28 Mar 2024 07:42:57 +0100
-Subject: gcc-plugins/stackleak: Avoid .head.text section
-
-The .head.text section carries the startup code that runs with the MMU
-off or with a translation of memory that deviates from the ordinary one.
-So avoid instrumentation with the stackleak plugin, which already avoids
-.init.text and .noinstr.text entirely.
-
-Fixes: 48204aba801f1b51 ("x86/sme: Move early SME kernel encryption handling into .head.text")
-Reported-by: kernel test robot <oliver.sang@intel.com>
-Closes: https://lore.kernel.org/oe-lkp/202403221630.2692c998-oliver.sang@intel.com
-Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
-Link: https://lore.kernel.org/r/20240328064256.2358634-2-ardb+git@google.com
-Signed-off-by: Kees Cook <keescook@chromium.org>
----
- scripts/gcc-plugins/stackleak_plugin.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c
-index c5c2ce113c9232..d20c47d21ad835 100644
---- a/scripts/gcc-plugins/stackleak_plugin.c
-+++ b/scripts/gcc-plugins/stackleak_plugin.c
-@@ -467,6 +467,8 @@ static bool stackleak_gate(void)
- return false;
- if (STRING_EQUAL(section, ".entry.text"))
- return false;
-+ if (STRING_EQUAL(section, ".head.text"))
-+ return false;
- }
-
- return track_frame_size >= 0;
---
-cgit 1.2.3-korg
-
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-27 17:04 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-04-27 17:04 UTC (permalink / raw
To: gentoo-commits
commit: b652b323fdea33739084afcbd7f056e1c910bc4c
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sat Apr 27 17:04:24 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sat Apr 27 17:04:24 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=b652b323
Linux patch 6.8.8
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1007_linux-6.8.8.patch | 7100 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 7104 insertions(+)
diff --git a/0000_README b/0000_README
index ba3f48c8..03fbc840 100644
--- a/0000_README
+++ b/0000_README
@@ -71,6 +71,10 @@ Patch: 1006_linux-6.8.7.patch
From: https://www.kernel.org
Desc: Linux 6.8.7
+Patch: 1007_linux-6.8.8.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.8
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1007_linux-6.8.8.patch b/1007_linux-6.8.8.patch
new file mode 100644
index 00000000..481ef1a6
--- /dev/null
+++ b/1007_linux-6.8.8.patch
@@ -0,0 +1,7100 @@
+diff --git a/Makefile b/Makefile
+index e6c0a00722eae..ffa43a6d04241 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 7
++SUBLEVEL = 8
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
+index cab7f91949d8f..a92905e6d43ad 100644
+--- a/arch/arm64/kernel/head.S
++++ b/arch/arm64/kernel/head.S
+@@ -569,6 +569,11 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL)
+ adr_l x1, __hyp_text_end
+ adr_l x2, dcache_clean_poc
+ blr x2
++
++ mov_q x0, INIT_SCTLR_EL2_MMU_OFF
++ pre_disable_mmu_workaround
++ msr sctlr_el2, x0
++ isb
+ 0:
+ mov_q x0, HCR_HOST_NVHE_FLAGS
+ msr hcr_el2, x0
+diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
+index 924843f1f661b..0a62f458c5cb0 100644
+--- a/arch/arm64/mm/pageattr.c
++++ b/arch/arm64/mm/pageattr.c
+@@ -219,9 +219,6 @@ bool kernel_page_present(struct page *page)
+ pte_t *ptep;
+ unsigned long addr = (unsigned long)page_address(page);
+
+- if (!can_set_direct_map())
+- return true;
+-
+ pgdp = pgd_offset_k(addr);
+ if (pgd_none(READ_ONCE(*pgdp)))
+ return false;
+diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h
+index 0216f63a366b5..d0795b5fab46a 100644
+--- a/arch/x86/include/asm/barrier.h
++++ b/arch/x86/include/asm/barrier.h
+@@ -79,6 +79,9 @@ do { \
+ #define __smp_mb__before_atomic() do { } while (0)
+ #define __smp_mb__after_atomic() do { } while (0)
+
++/* Writing to CR3 provides a full memory barrier in switch_mm(). */
++#define smp_mb__after_switch_mm() do { } while (0)
++
+ #include <asm-generic/barrier.h>
+
+ #endif /* _ASM_X86_BARRIER_H */
+diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
+index d271ba20a0b21..b7a539ea2986f 100644
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -854,6 +854,7 @@ struct kvm_vcpu_arch {
+ int cpuid_nent;
+ struct kvm_cpuid_entry2 *cpuid_entries;
+ struct kvm_hypervisor_cpuid kvm_cpuid;
++ bool is_amd_compatible;
+
+ /*
+ * FIXME: Drop this macro and use KVM_NR_GOVERNED_FEATURES directly
+diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
+index cbc8c88144e47..e7ceee008bd09 100644
+--- a/arch/x86/kernel/cpu/bugs.c
++++ b/arch/x86/kernel/cpu/bugs.c
+@@ -1651,7 +1651,8 @@ static void __init bhi_select_mitigation(void)
+ return;
+
+ /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */
+- if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) {
++ if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
++ !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE)) {
+ spec_ctrl_disable_kernel_rrsba();
+ if (rrsba_disabled)
+ return;
+@@ -2803,11 +2804,13 @@ static const char *spectre_bhi_state(void)
+ {
+ if (!boot_cpu_has_bug(X86_BUG_BHI))
+ return "; BHI: Not affected";
+- else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW))
++ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW))
+ return "; BHI: BHI_DIS_S";
+- else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
++ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP))
+ return "; BHI: SW loop, KVM: SW loop";
+- else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && rrsba_disabled)
++ else if (boot_cpu_has(X86_FEATURE_RETPOLINE) &&
++ !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE) &&
++ rrsba_disabled)
+ return "; BHI: Retpoline";
+ else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT))
+ return "; BHI: Vulnerable, KVM: SW loop";
+diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
+index e462c1d3800a6..6fb6d8a57ceca 100644
+--- a/arch/x86/kernel/cpu/cpuid-deps.c
++++ b/arch/x86/kernel/cpu/cpuid-deps.c
+@@ -44,7 +44,10 @@ static const struct cpuid_dep cpuid_deps[] = {
+ { X86_FEATURE_F16C, X86_FEATURE_XMM2, },
+ { X86_FEATURE_AES, X86_FEATURE_XMM2 },
+ { X86_FEATURE_SHA_NI, X86_FEATURE_XMM2 },
++ { X86_FEATURE_GFNI, X86_FEATURE_XMM2 },
+ { X86_FEATURE_FMA, X86_FEATURE_AVX },
++ { X86_FEATURE_VAES, X86_FEATURE_AVX },
++ { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX },
+ { X86_FEATURE_AVX2, X86_FEATURE_AVX, },
+ { X86_FEATURE_AVX512F, X86_FEATURE_AVX, },
+ { X86_FEATURE_AVX512IFMA, X86_FEATURE_AVX512F },
+@@ -56,9 +59,6 @@ static const struct cpuid_dep cpuid_deps[] = {
+ { X86_FEATURE_AVX512VL, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512VBMI, X86_FEATURE_AVX512F },
+ { X86_FEATURE_AVX512_VBMI2, X86_FEATURE_AVX512VL },
+- { X86_FEATURE_GFNI, X86_FEATURE_AVX512VL },
+- { X86_FEATURE_VAES, X86_FEATURE_AVX512VL },
+- { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_AVX512_VNNI, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_AVX512_BITALG, X86_FEATURE_AVX512VL },
+ { X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F },
+diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
+index adba49afb5fe6..3a02276899db8 100644
+--- a/arch/x86/kvm/cpuid.c
++++ b/arch/x86/kvm/cpuid.c
+@@ -366,6 +366,7 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
+
+ kvm_update_pv_runtime(vcpu);
+
++ vcpu->arch.is_amd_compatible = guest_cpuid_is_amd_or_hygon(vcpu);
+ vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu);
+ vcpu->arch.reserved_gpa_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu);
+
+diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
+index 856e3037e74f3..23dbb9eb277c7 100644
+--- a/arch/x86/kvm/cpuid.h
++++ b/arch/x86/kvm/cpuid.h
+@@ -120,6 +120,16 @@ static inline bool guest_cpuid_is_intel(struct kvm_vcpu *vcpu)
+ return best && is_guest_vendor_intel(best->ebx, best->ecx, best->edx);
+ }
+
++static inline bool guest_cpuid_is_amd_compatible(struct kvm_vcpu *vcpu)
++{
++ return vcpu->arch.is_amd_compatible;
++}
++
++static inline bool guest_cpuid_is_intel_compatible(struct kvm_vcpu *vcpu)
++{
++ return !guest_cpuid_is_amd_compatible(vcpu);
++}
++
+ static inline int guest_cpuid_family(struct kvm_vcpu *vcpu)
+ {
+ struct kvm_cpuid_entry2 *best;
+diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
+index 75bc7d3f0022d..76fcee92b0706 100644
+--- a/arch/x86/kvm/lapic.c
++++ b/arch/x86/kvm/lapic.c
+@@ -2771,7 +2771,8 @@ int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type)
+ trig_mode = reg & APIC_LVT_LEVEL_TRIGGER;
+
+ r = __apic_accept_irq(apic, mode, vector, 1, trig_mode, NULL);
+- if (r && lvt_type == APIC_LVTPC)
++ if (r && lvt_type == APIC_LVTPC &&
++ guest_cpuid_is_intel_compatible(apic->vcpu))
+ kvm_lapic_set_reg(apic, APIC_LVTPC, reg | APIC_LVT_MASKED);
+ return r;
+ }
+diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
+index e2c3573f53e43..982cf41e14924 100644
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -4922,7 +4922,7 @@ static void reset_guest_rsvds_bits_mask(struct kvm_vcpu *vcpu,
+ context->cpu_role.base.level, is_efer_nx(context),
+ guest_can_use(vcpu, X86_FEATURE_GBPAGES),
+ is_cr4_pse(context),
+- guest_cpuid_is_amd_or_hygon(vcpu));
++ guest_cpuid_is_amd_compatible(vcpu));
+ }
+
+ static void __reset_rsvds_bits_mask_ept(struct rsvd_bits_validate *rsvd_check,
+@@ -7388,7 +7388,8 @@ bool kvm_arch_post_set_memory_attributes(struct kvm *kvm,
+ * by the memslot, KVM can't use a hugepage due to the
+ * misaligned address regardless of memory attributes.
+ */
+- if (gfn >= slot->base_gfn) {
++ if (gfn >= slot->base_gfn &&
++ gfn + nr_pages <= slot->base_gfn + slot->npages) {
+ if (hugepage_has_attrs(kvm, slot, gfn, level, attrs))
+ hugepage_clear_mixed(slot, gfn, level);
+ else
+diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
+index 6ae19b4ee5b1c..953082bf96e27 100644
+--- a/arch/x86/kvm/mmu/tdp_mmu.c
++++ b/arch/x86/kvm/mmu/tdp_mmu.c
+@@ -1498,6 +1498,16 @@ void kvm_tdp_mmu_try_split_huge_pages(struct kvm *kvm,
+ }
+ }
+
++static bool tdp_mmu_need_write_protect(struct kvm_mmu_page *sp)
++{
++ /*
++ * All TDP MMU shadow pages share the same role as their root, aside
++ * from level, so it is valid to key off any shadow page to determine if
++ * write protection is needed for an entire tree.
++ */
++ return kvm_mmu_page_ad_need_write_protect(sp) || !kvm_ad_enabled();
++}
++
+ /*
+ * Clear the dirty status of all the SPTEs mapping GFNs in the memslot. If
+ * AD bits are enabled, this will involve clearing the dirty bit on each SPTE.
+@@ -1508,7 +1518,8 @@ void kvm_tdp_mmu_try_split_huge_pages(struct kvm *kvm,
+ static bool clear_dirty_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
+ gfn_t start, gfn_t end)
+ {
+- u64 dbit = kvm_ad_enabled() ? shadow_dirty_mask : PT_WRITABLE_MASK;
++ const u64 dbit = tdp_mmu_need_write_protect(root) ? PT_WRITABLE_MASK :
++ shadow_dirty_mask;
+ struct tdp_iter iter;
+ bool spte_set = false;
+
+@@ -1523,7 +1534,7 @@ static bool clear_dirty_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
+ if (tdp_mmu_iter_cond_resched(kvm, &iter, false, true))
+ continue;
+
+- KVM_MMU_WARN_ON(kvm_ad_enabled() &&
++ KVM_MMU_WARN_ON(dbit == shadow_dirty_mask &&
+ spte_ad_need_write_protect(iter.old_spte));
+
+ if (!(iter.old_spte & dbit))
+@@ -1570,8 +1581,8 @@ bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm,
+ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root,
+ gfn_t gfn, unsigned long mask, bool wrprot)
+ {
+- u64 dbit = (wrprot || !kvm_ad_enabled()) ? PT_WRITABLE_MASK :
+- shadow_dirty_mask;
++ const u64 dbit = (wrprot || tdp_mmu_need_write_protect(root)) ? PT_WRITABLE_MASK :
++ shadow_dirty_mask;
+ struct tdp_iter iter;
+
+ lockdep_assert_held_write(&kvm->mmu_lock);
+@@ -1583,7 +1594,7 @@ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root,
+ if (!mask)
+ break;
+
+- KVM_MMU_WARN_ON(kvm_ad_enabled() &&
++ KVM_MMU_WARN_ON(dbit == shadow_dirty_mask &&
+ spte_ad_need_write_protect(iter.old_spte));
+
+ if (iter.level > PG_LEVEL_4K ||
+diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
+index 88a4ff200d04b..784f2ecca5d2c 100644
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -7857,8 +7857,28 @@ static u64 vmx_get_perf_capabilities(void)
+
+ if (vmx_pebs_supported()) {
+ perf_cap |= host_perf_cap & PERF_CAP_PEBS_MASK;
+- if ((perf_cap & PERF_CAP_PEBS_FORMAT) < 4)
+- perf_cap &= ~PERF_CAP_PEBS_BASELINE;
++
++ /*
++ * Disallow adaptive PEBS as it is functionally broken, can be
++ * used by the guest to read *host* LBRs, and can be used to
++ * bypass userspace event filters. To correctly and safely
++ * support adaptive PEBS, KVM needs to:
++ *
++ * 1. Account for the ADAPTIVE flag when (re)programming fixed
++ * counters.
++ *
++ * 2. Gain support from perf (or take direct control of counter
++ * programming) to support events without adaptive PEBS
++ * enabled for the hardware counter.
++ *
++ * 3. Ensure LBR MSRs cannot hold host data on VM-Entry with
++ * adaptive PEBS enabled and MSR_PEBS_DATA_CFG.LBRS=1.
++ *
++ * 4. Document which PMU events are effectively exposed to the
++ * guest via adaptive PEBS, and make adaptive PEBS mutually
++ * exclusive with KVM_SET_PMU_EVENT_FILTER if necessary.
++ */
++ perf_cap &= ~PERF_CAP_PEBS_BASELINE;
+ }
+
+ return perf_cap;
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 8e4e48840290e..c84927216fad4 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -3422,7 +3422,7 @@ static bool is_mci_status_msr(u32 msr)
+ static bool can_set_mci_status(struct kvm_vcpu *vcpu)
+ {
+ /* McStatusWrEn enabled? */
+- if (guest_cpuid_is_amd_or_hygon(vcpu))
++ if (guest_cpuid_is_amd_compatible(vcpu))
+ return !!(vcpu->arch.msr_hwcr & BIT_ULL(18));
+
+ return false;
+diff --git a/block/bdev.c b/block/bdev.c
+index 678807bcd0034..2b0f97651a0a7 100644
+--- a/block/bdev.c
++++ b/block/bdev.c
+@@ -639,6 +639,14 @@ static void blkdev_flush_mapping(struct block_device *bdev)
+ bdev_write_inode(bdev);
+ }
+
++static void blkdev_put_whole(struct block_device *bdev)
++{
++ if (atomic_dec_and_test(&bdev->bd_openers))
++ blkdev_flush_mapping(bdev);
++ if (bdev->bd_disk->fops->release)
++ bdev->bd_disk->fops->release(bdev->bd_disk);
++}
++
+ static int blkdev_get_whole(struct block_device *bdev, blk_mode_t mode)
+ {
+ struct gendisk *disk = bdev->bd_disk;
+@@ -657,20 +665,21 @@ static int blkdev_get_whole(struct block_device *bdev, blk_mode_t mode)
+
+ if (!atomic_read(&bdev->bd_openers))
+ set_init_blocksize(bdev);
+- if (test_bit(GD_NEED_PART_SCAN, &disk->state))
+- bdev_disk_changed(disk, false);
+ atomic_inc(&bdev->bd_openers);
++ if (test_bit(GD_NEED_PART_SCAN, &disk->state)) {
++ /*
++ * Only return scanning errors if we are called from contexts
++ * that explicitly want them, e.g. the BLKRRPART ioctl.
++ */
++ ret = bdev_disk_changed(disk, false);
++ if (ret && (mode & BLK_OPEN_STRICT_SCAN)) {
++ blkdev_put_whole(bdev);
++ return ret;
++ }
++ }
+ return 0;
+ }
+
+-static void blkdev_put_whole(struct block_device *bdev)
+-{
+- if (atomic_dec_and_test(&bdev->bd_openers))
+- blkdev_flush_mapping(bdev);
+- if (bdev->bd_disk->fops->release)
+- bdev->bd_disk->fops->release(bdev->bd_disk);
+-}
+-
+ static int blkdev_get_part(struct block_device *part, blk_mode_t mode)
+ {
+ struct gendisk *disk = part->bd_disk;
+diff --git a/block/ioctl.c b/block/ioctl.c
+index 438f79c564cfc..5f8c988239c68 100644
+--- a/block/ioctl.c
++++ b/block/ioctl.c
+@@ -556,7 +556,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode,
+ return -EACCES;
+ if (bdev_is_partition(bdev))
+ return -EINVAL;
+- return disk_scan_partitions(bdev->bd_disk, mode);
++ return disk_scan_partitions(bdev->bd_disk,
++ mode | BLK_OPEN_STRICT_SCAN);
+ case BLKTRACESTART:
+ case BLKTRACESTOP:
+ case BLKTRACETEARDOWN:
+diff --git a/drivers/accessibility/speakup/main.c b/drivers/accessibility/speakup/main.c
+index 1fbc9b921c4fc..736c2eb8c0f37 100644
+--- a/drivers/accessibility/speakup/main.c
++++ b/drivers/accessibility/speakup/main.c
+@@ -574,7 +574,7 @@ static u_long get_word(struct vc_data *vc)
+ }
+ attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr);
+ buf[cnt++] = attr_ch;
+- while (tmpx < vc->vc_cols - 1) {
++ while (tmpx < vc->vc_cols - 1 && cnt < sizeof(buf) - 1) {
+ tmp_pos += 2;
+ tmpx++;
+ ch = get_char(vc, (u_short *)tmp_pos, &temp);
+diff --git a/drivers/android/binder.c b/drivers/android/binder.c
+index eca24f41556df..d6f14c8e20be3 100644
+--- a/drivers/android/binder.c
++++ b/drivers/android/binder.c
+@@ -1708,8 +1708,10 @@ static size_t binder_get_object(struct binder_proc *proc,
+ size_t object_size = 0;
+
+ read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset);
+- if (offset > buffer->data_size || read_size < sizeof(*hdr))
++ if (offset > buffer->data_size || read_size < sizeof(*hdr) ||
++ !IS_ALIGNED(offset, sizeof(u32)))
+ return 0;
++
+ if (u) {
+ if (copy_from_user(object, u + offset, read_size))
+ return 0;
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 456be28ba67cb..2597cb43f4387 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -702,7 +702,7 @@ static void extract_entropy(void *buf, size_t len)
+
+ static void __cold _credit_init_bits(size_t bits)
+ {
+- static struct execute_work set_ready;
++ static DECLARE_WORK(set_ready, crng_set_ready);
+ unsigned int new, orig, add;
+ unsigned long flags;
+
+@@ -718,8 +718,8 @@ static void __cold _credit_init_bits(size_t bits)
+
+ if (orig < POOL_READY_BITS && new >= POOL_READY_BITS) {
+ crng_reseed(NULL); /* Sets crng_init to CRNG_READY under base_crng.lock. */
+- if (static_key_initialized)
+- execute_in_process_context(crng_set_ready, &set_ready);
++ if (static_key_initialized && system_unbound_wq)
++ queue_work(system_unbound_wq, &set_ready);
+ atomic_notifier_call_chain(&random_ready_notifier, 0, NULL);
+ wake_up_interruptible(&crng_init_wait);
+ kill_fasync(&fasync, SIGIO, POLL_IN);
+@@ -890,8 +890,8 @@ void __init random_init(void)
+
+ /*
+ * If we were initialized by the cpu or bootloader before jump labels
+- * are initialized, then we should enable the static branch here, where
+- * it's guaranteed that jump labels have been initialized.
++ * or workqueues are initialized, then we should enable the static
++ * branch here, where it's guaranteed that these have been initialized.
+ */
+ if (!static_branch_likely(&crng_is_ready) && crng_init >= CRNG_READY)
+ crng_set_ready(NULL);
+diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
+index 20c4b28fed061..cf1fc0edfdbca 100644
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -37,6 +37,10 @@ static HLIST_HEAD(clk_root_list);
+ static HLIST_HEAD(clk_orphan_list);
+ static LIST_HEAD(clk_notifier_list);
+
++/* List of registered clks that use runtime PM */
++static HLIST_HEAD(clk_rpm_list);
++static DEFINE_MUTEX(clk_rpm_list_lock);
++
+ static const struct hlist_head *all_lists[] = {
+ &clk_root_list,
+ &clk_orphan_list,
+@@ -59,6 +63,7 @@ struct clk_core {
+ struct clk_hw *hw;
+ struct module *owner;
+ struct device *dev;
++ struct hlist_node rpm_node;
+ struct device_node *of_node;
+ struct clk_core *parent;
+ struct clk_parent_map *parents;
+@@ -122,6 +127,89 @@ static void clk_pm_runtime_put(struct clk_core *core)
+ pm_runtime_put_sync(core->dev);
+ }
+
++/**
++ * clk_pm_runtime_get_all() - Runtime "get" all clk provider devices
++ *
++ * Call clk_pm_runtime_get() on all runtime PM enabled clks in the clk tree so
++ * that disabling unused clks avoids a deadlock where a device is runtime PM
++ * resuming/suspending and the runtime PM callback is trying to grab the
++ * prepare_lock for something like clk_prepare_enable() while
++ * clk_disable_unused_subtree() holds the prepare_lock and is trying to runtime
++ * PM resume/suspend the device as well.
++ *
++ * Context: Acquires the 'clk_rpm_list_lock' and returns with the lock held on
++ * success. Otherwise the lock is released on failure.
++ *
++ * Return: 0 on success, negative errno otherwise.
++ */
++static int clk_pm_runtime_get_all(void)
++{
++ int ret;
++ struct clk_core *core, *failed;
++
++ /*
++ * Grab the list lock to prevent any new clks from being registered
++ * or unregistered until clk_pm_runtime_put_all().
++ */
++ mutex_lock(&clk_rpm_list_lock);
++
++ /*
++ * Runtime PM "get" all the devices that are needed for the clks
++ * currently registered. Do this without holding the prepare_lock, to
++ * avoid the deadlock.
++ */
++ hlist_for_each_entry(core, &clk_rpm_list, rpm_node) {
++ ret = clk_pm_runtime_get(core);
++ if (ret) {
++ failed = core;
++ pr_err("clk: Failed to runtime PM get '%s' for clk '%s'\n",
++ dev_name(failed->dev), failed->name);
++ goto err;
++ }
++ }
++
++ return 0;
++
++err:
++ hlist_for_each_entry(core, &clk_rpm_list, rpm_node) {
++ if (core == failed)
++ break;
++
++ clk_pm_runtime_put(core);
++ }
++ mutex_unlock(&clk_rpm_list_lock);
++
++ return ret;
++}
++
++/**
++ * clk_pm_runtime_put_all() - Runtime "put" all clk provider devices
++ *
++ * Put the runtime PM references taken in clk_pm_runtime_get_all() and release
++ * the 'clk_rpm_list_lock'.
++ */
++static void clk_pm_runtime_put_all(void)
++{
++ struct clk_core *core;
++
++ hlist_for_each_entry(core, &clk_rpm_list, rpm_node)
++ clk_pm_runtime_put(core);
++ mutex_unlock(&clk_rpm_list_lock);
++}
++
++static void clk_pm_runtime_init(struct clk_core *core)
++{
++ struct device *dev = core->dev;
++
++ if (dev && pm_runtime_enabled(dev)) {
++ core->rpm_enabled = true;
++
++ mutex_lock(&clk_rpm_list_lock);
++ hlist_add_head(&core->rpm_node, &clk_rpm_list);
++ mutex_unlock(&clk_rpm_list_lock);
++ }
++}
++
+ /*** locking ***/
+ static void clk_prepare_lock(void)
+ {
+@@ -1362,9 +1450,6 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core)
+ if (core->flags & CLK_IGNORE_UNUSED)
+ return;
+
+- if (clk_pm_runtime_get(core))
+- return;
+-
+ if (clk_core_is_prepared(core)) {
+ trace_clk_unprepare(core);
+ if (core->ops->unprepare_unused)
+@@ -1373,8 +1458,6 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core)
+ core->ops->unprepare(core->hw);
+ trace_clk_unprepare_complete(core);
+ }
+-
+- clk_pm_runtime_put(core);
+ }
+
+ static void __init clk_disable_unused_subtree(struct clk_core *core)
+@@ -1390,9 +1473,6 @@ static void __init clk_disable_unused_subtree(struct clk_core *core)
+ if (core->flags & CLK_OPS_PARENT_ENABLE)
+ clk_core_prepare_enable(core->parent);
+
+- if (clk_pm_runtime_get(core))
+- goto unprepare_out;
+-
+ flags = clk_enable_lock();
+
+ if (core->enable_count)
+@@ -1417,8 +1497,6 @@ static void __init clk_disable_unused_subtree(struct clk_core *core)
+
+ unlock_out:
+ clk_enable_unlock(flags);
+- clk_pm_runtime_put(core);
+-unprepare_out:
+ if (core->flags & CLK_OPS_PARENT_ENABLE)
+ clk_core_disable_unprepare(core->parent);
+ }
+@@ -1434,6 +1512,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
+ static int __init clk_disable_unused(void)
+ {
+ struct clk_core *core;
++ int ret;
+
+ if (clk_ignore_unused) {
+ pr_warn("clk: Not disabling unused clocks\n");
+@@ -1442,6 +1521,13 @@ static int __init clk_disable_unused(void)
+
+ pr_info("clk: Disabling unused clocks\n");
+
++ ret = clk_pm_runtime_get_all();
++ if (ret)
++ return ret;
++ /*
++ * Grab the prepare lock to keep the clk topology stable while iterating
++ * over clks.
++ */
+ clk_prepare_lock();
+
+ hlist_for_each_entry(core, &clk_root_list, child_node)
+@@ -1458,6 +1544,8 @@ static int __init clk_disable_unused(void)
+
+ clk_prepare_unlock();
+
++ clk_pm_runtime_put_all();
++
+ return 0;
+ }
+ late_initcall_sync(clk_disable_unused);
+@@ -3233,9 +3321,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
+ {
+ struct clk_core *child;
+
+- clk_pm_runtime_get(c);
+ clk_summary_show_one(s, c, level);
+- clk_pm_runtime_put(c);
+
+ hlist_for_each_entry(child, &c->children, child_node)
+ clk_summary_show_subtree(s, child, level + 1);
+@@ -3245,11 +3331,15 @@ static int clk_summary_show(struct seq_file *s, void *data)
+ {
+ struct clk_core *c;
+ struct hlist_head **lists = s->private;
++ int ret;
+
+ seq_puts(s, " enable prepare protect duty hardware connection\n");
+ seq_puts(s, " clock count count count rate accuracy phase cycle enable consumer id\n");
+ seq_puts(s, "---------------------------------------------------------------------------------------------------------------------------------------------\n");
+
++ ret = clk_pm_runtime_get_all();
++ if (ret)
++ return ret;
+
+ clk_prepare_lock();
+
+@@ -3258,6 +3348,7 @@ static int clk_summary_show(struct seq_file *s, void *data)
+ clk_summary_show_subtree(s, c, 0);
+
+ clk_prepare_unlock();
++ clk_pm_runtime_put_all();
+
+ return 0;
+ }
+@@ -3305,8 +3396,14 @@ static int clk_dump_show(struct seq_file *s, void *data)
+ struct clk_core *c;
+ bool first_node = true;
+ struct hlist_head **lists = s->private;
++ int ret;
++
++ ret = clk_pm_runtime_get_all();
++ if (ret)
++ return ret;
+
+ seq_putc(s, '{');
++
+ clk_prepare_lock();
+
+ for (; *lists; lists++) {
+@@ -3319,6 +3416,7 @@ static int clk_dump_show(struct seq_file *s, void *data)
+ }
+
+ clk_prepare_unlock();
++ clk_pm_runtime_put_all();
+
+ seq_puts(s, "}\n");
+ return 0;
+@@ -3962,8 +4060,6 @@ static int __clk_core_init(struct clk_core *core)
+ }
+
+ clk_core_reparent_orphans_nolock();
+-
+- kref_init(&core->ref);
+ out:
+ clk_pm_runtime_put(core);
+ unlock:
+@@ -4192,6 +4288,22 @@ static void clk_core_free_parent_map(struct clk_core *core)
+ kfree(core->parents);
+ }
+
++/* Free memory allocated for a struct clk_core */
++static void __clk_release(struct kref *ref)
++{
++ struct clk_core *core = container_of(ref, struct clk_core, ref);
++
++ if (core->rpm_enabled) {
++ mutex_lock(&clk_rpm_list_lock);
++ hlist_del(&core->rpm_node);
++ mutex_unlock(&clk_rpm_list_lock);
++ }
++
++ clk_core_free_parent_map(core);
++ kfree_const(core->name);
++ kfree(core);
++}
++
+ static struct clk *
+ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
+ {
+@@ -4212,6 +4324,8 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
+ goto fail_out;
+ }
+
++ kref_init(&core->ref);
++
+ core->name = kstrdup_const(init->name, GFP_KERNEL);
+ if (!core->name) {
+ ret = -ENOMEM;
+@@ -4224,9 +4338,8 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
+ }
+ core->ops = init->ops;
+
+- if (dev && pm_runtime_enabled(dev))
+- core->rpm_enabled = true;
+ core->dev = dev;
++ clk_pm_runtime_init(core);
+ core->of_node = np;
+ if (dev && dev->driver)
+ core->owner = dev->driver->owner;
+@@ -4266,12 +4379,10 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
+ hw->clk = NULL;
+
+ fail_create_clk:
+- clk_core_free_parent_map(core);
+ fail_parents:
+ fail_ops:
+- kfree_const(core->name);
+ fail_name:
+- kfree(core);
++ kref_put(&core->ref, __clk_release);
+ fail_out:
+ return ERR_PTR(ret);
+ }
+@@ -4351,18 +4462,6 @@ int of_clk_hw_register(struct device_node *node, struct clk_hw *hw)
+ }
+ EXPORT_SYMBOL_GPL(of_clk_hw_register);
+
+-/* Free memory allocated for a clock. */
+-static void __clk_release(struct kref *ref)
+-{
+- struct clk_core *core = container_of(ref, struct clk_core, ref);
+-
+- lockdep_assert_held(&prepare_lock);
+-
+- clk_core_free_parent_map(core);
+- kfree_const(core->name);
+- kfree(core);
+-}
+-
+ /*
+ * Empty clk_ops for unregistered clocks. These are used temporarily
+ * after clk_unregister() was called on a clock and until last clock
+diff --git a/drivers/clk/mediatek/clk-mt7988-infracfg.c b/drivers/clk/mediatek/clk-mt7988-infracfg.c
+index 8011ef278bea3..df02997c6b7c9 100644
+--- a/drivers/clk/mediatek/clk-mt7988-infracfg.c
++++ b/drivers/clk/mediatek/clk-mt7988-infracfg.c
+@@ -152,7 +152,7 @@ static const struct mtk_gate infra_clks[] = {
+ GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P1, "infra_pcie_peri_ck_26m_ck_p1",
+ "csw_infra_f26m_sel", 8),
+ GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P2, "infra_pcie_peri_ck_26m_ck_p2",
+- "csw_infra_f26m_sel", 9),
++ "infra_pcie_peri_ck_26m_ck_p3", 9),
+ GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P3, "infra_pcie_peri_ck_26m_ck_p3",
+ "csw_infra_f26m_sel", 10),
+ /* INFRA1 */
+diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
+index 2e55368dc4d82..bd37ab4d1a9bb 100644
+--- a/drivers/clk/mediatek/clk-mtk.c
++++ b/drivers/clk/mediatek/clk-mtk.c
+@@ -13,6 +13,7 @@
+ #include <linux/of.h>
+ #include <linux/of_address.h>
+ #include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
+ #include <linux/slab.h>
+
+ #include "clk-mtk.h"
+@@ -494,6 +495,16 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
+ return IS_ERR(base) ? PTR_ERR(base) : -ENOMEM;
+ }
+
++
++ devm_pm_runtime_enable(&pdev->dev);
++ /*
++ * Do a pm_runtime_resume_and_get() to workaround a possible
++ * deadlock between clk_register() and the genpd framework.
++ */
++ r = pm_runtime_resume_and_get(&pdev->dev);
++ if (r)
++ return r;
++
+ /* Calculate how many clk_hw_onecell_data entries to allocate */
+ num_clks = mcd->num_clks + mcd->num_composite_clks;
+ num_clks += mcd->num_fixed_clks + mcd->num_factor_clks;
+@@ -574,6 +585,8 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
+ goto unregister_clks;
+ }
+
++ pm_runtime_put(&pdev->dev);
++
+ return r;
+
+ unregister_clks:
+@@ -604,6 +617,8 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev,
+ free_base:
+ if (mcd->shared_io && base)
+ iounmap(base);
++
++ pm_runtime_put(&pdev->dev);
+ return r;
+ }
+
+diff --git a/drivers/comedi/drivers/vmk80xx.c b/drivers/comedi/drivers/vmk80xx.c
+index 4536ed43f65b2..84dce5184a77a 100644
+--- a/drivers/comedi/drivers/vmk80xx.c
++++ b/drivers/comedi/drivers/vmk80xx.c
+@@ -641,33 +641,22 @@ static int vmk80xx_find_usb_endpoints(struct comedi_device *dev)
+ struct vmk80xx_private *devpriv = dev->private;
+ struct usb_interface *intf = comedi_to_usb_interface(dev);
+ struct usb_host_interface *iface_desc = intf->cur_altsetting;
+- struct usb_endpoint_descriptor *ep_desc;
+- int i;
+-
+- if (iface_desc->desc.bNumEndpoints != 2)
+- return -ENODEV;
+-
+- for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
+- ep_desc = &iface_desc->endpoint[i].desc;
+-
+- if (usb_endpoint_is_int_in(ep_desc) ||
+- usb_endpoint_is_bulk_in(ep_desc)) {
+- if (!devpriv->ep_rx)
+- devpriv->ep_rx = ep_desc;
+- continue;
+- }
++ struct usb_endpoint_descriptor *ep_rx_desc, *ep_tx_desc;
++ int ret;
+
+- if (usb_endpoint_is_int_out(ep_desc) ||
+- usb_endpoint_is_bulk_out(ep_desc)) {
+- if (!devpriv->ep_tx)
+- devpriv->ep_tx = ep_desc;
+- continue;
+- }
+- }
++ if (devpriv->model == VMK8061_MODEL)
++ ret = usb_find_common_endpoints(iface_desc, &ep_rx_desc,
++ &ep_tx_desc, NULL, NULL);
++ else
++ ret = usb_find_common_endpoints(iface_desc, NULL, NULL,
++ &ep_rx_desc, &ep_tx_desc);
+
+- if (!devpriv->ep_rx || !devpriv->ep_tx)
++ if (ret)
+ return -ENODEV;
+
++ devpriv->ep_rx = ep_rx_desc;
++ devpriv->ep_tx = ep_tx_desc;
++
+ if (!usb_endpoint_maxp(devpriv->ep_rx) || !usb_endpoint_maxp(devpriv->ep_tx))
+ return -EINVAL;
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+index b0ed10f4de609..a5ceec7820cfa 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+@@ -562,7 +562,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev,
+ struct ttm_resource *mem)
+ {
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
+- size_t bus_size = (size_t)mem->size;
+
+ switch (mem->mem_type) {
+ case TTM_PL_SYSTEM:
+@@ -573,9 +572,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev,
+ break;
+ case TTM_PL_VRAM:
+ mem->bus.offset = mem->start << PAGE_SHIFT;
+- /* check if it's visible */
+- if ((mem->bus.offset + bus_size) > adev->gmc.visible_vram_size)
+- return -EINVAL;
+
+ if (adev->mman.aper_base_kaddr &&
+ mem->placement & TTM_PL_FLAG_CONTIGUOUS)
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+index b8fcb6c556989..5b50f7359199d 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+@@ -1559,6 +1559,37 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev,
+ trace_amdgpu_vm_bo_map(bo_va, mapping);
+ }
+
++/* Validate operation parameters to prevent potential abuse */
++static int amdgpu_vm_verify_parameters(struct amdgpu_device *adev,
++ struct amdgpu_bo *bo,
++ uint64_t saddr,
++ uint64_t offset,
++ uint64_t size)
++{
++ uint64_t tmp, lpfn;
++
++ if (saddr & AMDGPU_GPU_PAGE_MASK
++ || offset & AMDGPU_GPU_PAGE_MASK
++ || size & AMDGPU_GPU_PAGE_MASK)
++ return -EINVAL;
++
++ if (check_add_overflow(saddr, size, &tmp)
++ || check_add_overflow(offset, size, &tmp)
++ || size == 0 /* which also leads to end < begin */)
++ return -EINVAL;
++
++ /* make sure object fit at this offset */
++ if (bo && offset + size > amdgpu_bo_size(bo))
++ return -EINVAL;
++
++ /* Ensure last pfn not exceed max_pfn */
++ lpfn = (saddr + size - 1) >> AMDGPU_GPU_PAGE_SHIFT;
++ if (lpfn >= adev->vm_manager.max_pfn)
++ return -EINVAL;
++
++ return 0;
++}
++
+ /**
+ * amdgpu_vm_bo_map - map bo inside a vm
+ *
+@@ -1585,21 +1616,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev,
+ struct amdgpu_bo *bo = bo_va->base.bo;
+ struct amdgpu_vm *vm = bo_va->base.vm;
+ uint64_t eaddr;
++ int r;
+
+- /* validate the parameters */
+- if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
+- return -EINVAL;
+- if (saddr + size <= saddr || offset + size <= offset)
+- return -EINVAL;
+-
+- /* make sure object fit at this offset */
+- eaddr = saddr + size - 1;
+- if ((bo && offset + size > amdgpu_bo_size(bo)) ||
+- (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT))
+- return -EINVAL;
++ r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
++ if (r)
++ return r;
+
+ saddr /= AMDGPU_GPU_PAGE_SIZE;
+- eaddr /= AMDGPU_GPU_PAGE_SIZE;
++ eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
+
+ tmp = amdgpu_vm_it_iter_first(&vm->va, saddr, eaddr);
+ if (tmp) {
+@@ -1652,17 +1676,9 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
+ uint64_t eaddr;
+ int r;
+
+- /* validate the parameters */
+- if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK)
+- return -EINVAL;
+- if (saddr + size <= saddr || offset + size <= offset)
+- return -EINVAL;
+-
+- /* make sure object fit at this offset */
+- eaddr = saddr + size - 1;
+- if ((bo && offset + size > amdgpu_bo_size(bo)) ||
+- (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT))
+- return -EINVAL;
++ r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size);
++ if (r)
++ return r;
+
+ /* Allocate all the needed memory */
+ mapping = kmalloc(sizeof(*mapping), GFP_KERNEL);
+@@ -1676,7 +1692,7 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev,
+ }
+
+ saddr /= AMDGPU_GPU_PAGE_SIZE;
+- eaddr /= AMDGPU_GPU_PAGE_SIZE;
++ eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
+
+ mapping->start = saddr;
+ mapping->last = eaddr;
+@@ -1763,10 +1779,14 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
+ struct amdgpu_bo_va_mapping *before, *after, *tmp, *next;
+ LIST_HEAD(removed);
+ uint64_t eaddr;
++ int r;
++
++ r = amdgpu_vm_verify_parameters(adev, NULL, saddr, 0, size);
++ if (r)
++ return r;
+
+- eaddr = saddr + size - 1;
+ saddr /= AMDGPU_GPU_PAGE_SIZE;
+- eaddr /= AMDGPU_GPU_PAGE_SIZE;
++ eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE;
+
+ /* Allocate all the needed memory */
+ before = kzalloc(sizeof(*before), GFP_KERNEL);
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+index 717a60d7a4ea9..b79986412cd83 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+@@ -819,9 +819,9 @@ struct kfd_process *kfd_create_process(struct task_struct *thread)
+ mutex_lock(&kfd_processes_mutex);
+
+ if (kfd_is_locked()) {
+- mutex_unlock(&kfd_processes_mutex);
+ pr_debug("KFD is locked! Cannot create process");
+- return ERR_PTR(-EINVAL);
++ process = ERR_PTR(-EINVAL);
++ goto out;
+ }
+
+ /* A prior open of /dev/kfd could have already created the process. */
+diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
+index 6e36a15284537..7ba30d26f620c 100644
+--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
++++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
+@@ -2512,7 +2512,8 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
+ intel_atomic_get_old_cdclk_state(state);
+ const struct intel_cdclk_state *new_cdclk_state =
+ intel_atomic_get_new_cdclk_state(state);
+- enum pipe pipe = new_cdclk_state->pipe;
++ struct intel_cdclk_config cdclk_config;
++ enum pipe pipe;
+
+ if (!intel_cdclk_changed(&old_cdclk_state->actual,
+ &new_cdclk_state->actual))
+@@ -2521,12 +2522,25 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
+ if (IS_DG2(i915))
+ intel_cdclk_pcode_pre_notify(state);
+
+- if (new_cdclk_state->disable_pipes ||
+- old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) {
+- drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
++ if (new_cdclk_state->disable_pipes) {
++ cdclk_config = new_cdclk_state->actual;
++ pipe = INVALID_PIPE;
++ } else {
++ if (new_cdclk_state->actual.cdclk >= old_cdclk_state->actual.cdclk) {
++ cdclk_config = new_cdclk_state->actual;
++ pipe = new_cdclk_state->pipe;
++ } else {
++ cdclk_config = old_cdclk_state->actual;
++ pipe = INVALID_PIPE;
++ }
+
+- intel_set_cdclk(i915, &new_cdclk_state->actual, pipe);
++ cdclk_config.voltage_level = max(new_cdclk_state->actual.voltage_level,
++ old_cdclk_state->actual.voltage_level);
+ }
++
++ drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
++
++ intel_set_cdclk(i915, &cdclk_config, pipe);
+ }
+
+ /**
+@@ -2544,7 +2558,7 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
+ intel_atomic_get_old_cdclk_state(state);
+ const struct intel_cdclk_state *new_cdclk_state =
+ intel_atomic_get_new_cdclk_state(state);
+- enum pipe pipe = new_cdclk_state->pipe;
++ enum pipe pipe;
+
+ if (!intel_cdclk_changed(&old_cdclk_state->actual,
+ &new_cdclk_state->actual))
+@@ -2554,11 +2568,14 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
+ intel_cdclk_pcode_post_notify(state);
+
+ if (!new_cdclk_state->disable_pipes &&
+- old_cdclk_state->actual.cdclk > new_cdclk_state->actual.cdclk) {
+- drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
++ new_cdclk_state->actual.cdclk < old_cdclk_state->actual.cdclk)
++ pipe = new_cdclk_state->pipe;
++ else
++ pipe = INVALID_PIPE;
+
+- intel_set_cdclk(i915, &new_cdclk_state->actual, pipe);
+- }
++ drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed);
++
++ intel_set_cdclk(i915, &new_cdclk_state->actual, pipe);
+ }
+
+ static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state)
+diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
+index 479effcf607e2..79cfab53f80e2 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
++++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
+@@ -23,6 +23,7 @@
+ */
+
+ #include "nouveau_drv.h"
++#include "nouveau_bios.h"
+ #include "nouveau_reg.h"
+ #include "dispnv04/hw.h"
+ #include "nouveau_encoder.h"
+@@ -1677,7 +1678,7 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf)
+ */
+ if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) {
+ if (*conn == 0xf2005014 && *conf == 0xffffffff) {
+- fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, 1);
++ fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, DCB_OUTPUT_B);
+ return false;
+ }
+ }
+@@ -1763,26 +1764,26 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios)
+ #ifdef __powerpc__
+ /* Apple iMac G4 NV17 */
+ if (of_machine_is_compatible("PowerMac4,5")) {
+- fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, 1);
+- fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, 2);
++ fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, DCB_OUTPUT_B);
++ fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, DCB_OUTPUT_C);
+ return;
+ }
+ #endif
+
+ /* Make up some sane defaults */
+ fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG,
+- bios->legacy.i2c_indices.crt, 1, 1);
++ bios->legacy.i2c_indices.crt, 1, DCB_OUTPUT_B);
+
+ if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
+ fabricate_dcb_output(dcb, DCB_OUTPUT_TV,
+ bios->legacy.i2c_indices.tv,
+- all_heads, 0);
++ all_heads, DCB_OUTPUT_A);
+
+ else if (bios->tmds.output0_script_ptr ||
+ bios->tmds.output1_script_ptr)
+ fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS,
+ bios->legacy.i2c_indices.panel,
+- all_heads, 1);
++ all_heads, DCB_OUTPUT_B);
+ }
+
+ static int
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
+index a7f3fc342d87e..dd5b5a17ece0b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
+@@ -222,8 +222,11 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
+ void __iomem *map = NULL;
+
+ /* Already mapped? */
+- if (refcount_inc_not_zero(&iobj->maps))
++ if (refcount_inc_not_zero(&iobj->maps)) {
++ /* read barrier match the wmb on refcount set */
++ smp_rmb();
+ return iobj->map;
++ }
+
+ /* Take the lock, and re-check that another thread hasn't
+ * already mapped the object in the meantime.
+@@ -250,6 +253,8 @@ nv50_instobj_acquire(struct nvkm_memory *memory)
+ iobj->base.memory.ptrs = &nv50_instobj_fast;
+ else
+ iobj->base.memory.ptrs = &nv50_instobj_slow;
++ /* barrier to ensure the ptrs are written before refcount is set */
++ smp_wmb();
+ refcount_set(&iobj->maps, 1);
+ }
+
+diff --git a/drivers/gpu/drm/panel/panel-visionox-rm69299.c b/drivers/gpu/drm/panel/panel-visionox-rm69299.c
+index 775144695283f..b15ca56a09a74 100644
+--- a/drivers/gpu/drm/panel/panel-visionox-rm69299.c
++++ b/drivers/gpu/drm/panel/panel-visionox-rm69299.c
+@@ -253,8 +253,6 @@ static void visionox_rm69299_remove(struct mipi_dsi_device *dsi)
+ struct visionox_rm69299 *ctx = mipi_dsi_get_drvdata(dsi);
+
+ mipi_dsi_detach(ctx->dsi);
+- mipi_dsi_device_unregister(ctx->dsi);
+-
+ drm_panel_remove(&ctx->panel);
+ }
+
+diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
+index 3596ea4a8b60f..fc7b0e8f1ca15 100644
+--- a/drivers/gpu/drm/radeon/radeon_atombios.c
++++ b/drivers/gpu/drm/radeon/radeon_atombios.c
+@@ -923,8 +923,12 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
+ max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO;
+
+ for (i = 0; i < max_device; i++) {
+- ATOM_CONNECTOR_INFO_I2C ci =
+- supported_devices->info.asConnInfo[i];
++ ATOM_CONNECTOR_INFO_I2C ci;
++
++ if (frev > 1)
++ ci = supported_devices->info_2d1.asConnInfo[i];
++ else
++ ci = supported_devices->info.asConnInfo[i];
+
+ bios_connectors[i].valid = false;
+
+diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
+index 112438d965ffb..6e1fd6985ffcb 100644
+--- a/drivers/gpu/drm/ttm/ttm_pool.c
++++ b/drivers/gpu/drm/ttm/ttm_pool.c
+@@ -288,17 +288,23 @@ static struct ttm_pool_type *ttm_pool_select_type(struct ttm_pool *pool,
+ enum ttm_caching caching,
+ unsigned int order)
+ {
+- if (pool->use_dma_alloc || pool->nid != NUMA_NO_NODE)
++ if (pool->use_dma_alloc)
+ return &pool->caching[caching].orders[order];
+
+ #ifdef CONFIG_X86
+ switch (caching) {
+ case ttm_write_combined:
++ if (pool->nid != NUMA_NO_NODE)
++ return &pool->caching[caching].orders[order];
++
+ if (pool->use_dma32)
+ return &global_dma32_write_combined[order];
+
+ return &global_write_combined[order];
+ case ttm_uncached:
++ if (pool->nid != NUMA_NO_NODE)
++ return &pool->caching[caching].orders[order];
++
+ if (pool->use_dma32)
+ return &global_dma32_uncached[order];
+
+@@ -566,11 +572,17 @@ void ttm_pool_init(struct ttm_pool *pool, struct device *dev,
+ pool->use_dma_alloc = use_dma_alloc;
+ pool->use_dma32 = use_dma32;
+
+- if (use_dma_alloc || nid != NUMA_NO_NODE) {
+- for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i)
+- for (j = 0; j < NR_PAGE_ORDERS; ++j)
+- ttm_pool_type_init(&pool->caching[i].orders[j],
+- pool, i, j);
++ for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) {
++ for (j = 0; j < NR_PAGE_ORDERS; ++j) {
++ struct ttm_pool_type *pt;
++
++ /* Initialize only pool types which are actually used */
++ pt = ttm_pool_select_type(pool, i, j);
++ if (pt != &pool->caching[i].orders[j])
++ continue;
++
++ ttm_pool_type_init(pt, pool, i, j);
++ }
+ }
+ }
+ EXPORT_SYMBOL(ttm_pool_init);
+@@ -599,10 +611,16 @@ void ttm_pool_fini(struct ttm_pool *pool)
+ {
+ unsigned int i, j;
+
+- if (pool->use_dma_alloc || pool->nid != NUMA_NO_NODE) {
+- for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i)
+- for (j = 0; j < NR_PAGE_ORDERS; ++j)
+- ttm_pool_type_fini(&pool->caching[i].orders[j]);
++ for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) {
++ for (j = 0; j < NR_PAGE_ORDERS; ++j) {
++ struct ttm_pool_type *pt;
++
++ pt = ttm_pool_select_type(pool, i, j);
++ if (pt != &pool->caching[i].orders[j])
++ continue;
++
++ ttm_pool_type_fini(pt);
++ }
+ }
+
+ /* We removed the pool types from the LRU, but we need to also make sure
+diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c
+index afc76390a197a..b8f9f2a3d2fb3 100644
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -105,7 +105,6 @@ v3d_irq(int irq, void *arg)
+ struct v3d_file_priv *file = v3d->bin_job->base.file->driver_priv;
+ u64 runtime = local_clock() - file->start_ns[V3D_BIN];
+
+- file->enabled_ns[V3D_BIN] += local_clock() - file->start_ns[V3D_BIN];
+ file->jobs_sent[V3D_BIN]++;
+ v3d->queue[V3D_BIN].jobs_sent++;
+
+@@ -126,7 +125,6 @@ v3d_irq(int irq, void *arg)
+ struct v3d_file_priv *file = v3d->render_job->base.file->driver_priv;
+ u64 runtime = local_clock() - file->start_ns[V3D_RENDER];
+
+- file->enabled_ns[V3D_RENDER] += local_clock() - file->start_ns[V3D_RENDER];
+ file->jobs_sent[V3D_RENDER]++;
+ v3d->queue[V3D_RENDER].jobs_sent++;
+
+@@ -147,7 +145,6 @@ v3d_irq(int irq, void *arg)
+ struct v3d_file_priv *file = v3d->csd_job->base.file->driver_priv;
+ u64 runtime = local_clock() - file->start_ns[V3D_CSD];
+
+- file->enabled_ns[V3D_CSD] += local_clock() - file->start_ns[V3D_CSD];
+ file->jobs_sent[V3D_CSD]++;
+ v3d->queue[V3D_CSD].jobs_sent++;
+
+@@ -195,7 +192,6 @@ v3d_hub_irq(int irq, void *arg)
+ struct v3d_file_priv *file = v3d->tfu_job->base.file->driver_priv;
+ u64 runtime = local_clock() - file->start_ns[V3D_TFU];
+
+- file->enabled_ns[V3D_TFU] += local_clock() - file->start_ns[V3D_TFU];
+ file->jobs_sent[V3D_TFU]++;
+ v3d->queue[V3D_TFU].jobs_sent++;
+
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
+index c52c7bf1485b1..717d624e9a052 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
+@@ -456,8 +456,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
+ .no_wait_gpu = false
+ };
+ u32 j, initial_line = dst_offset / dst_stride;
+- struct vmw_bo_blit_line_data d;
++ struct vmw_bo_blit_line_data d = {0};
+ int ret = 0;
++ struct page **dst_pages = NULL;
++ struct page **src_pages = NULL;
+
+ /* Buffer objects need to be either pinned or reserved: */
+ if (!(dst->pin_count))
+@@ -477,12 +479,35 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
+ return ret;
+ }
+
++ if (!src->ttm->pages && src->ttm->sg) {
++ src_pages = kvmalloc_array(src->ttm->num_pages,
++ sizeof(struct page *), GFP_KERNEL);
++ if (!src_pages)
++ return -ENOMEM;
++ ret = drm_prime_sg_to_page_array(src->ttm->sg, src_pages,
++ src->ttm->num_pages);
++ if (ret)
++ goto out;
++ }
++ if (!dst->ttm->pages && dst->ttm->sg) {
++ dst_pages = kvmalloc_array(dst->ttm->num_pages,
++ sizeof(struct page *), GFP_KERNEL);
++ if (!dst_pages) {
++ ret = -ENOMEM;
++ goto out;
++ }
++ ret = drm_prime_sg_to_page_array(dst->ttm->sg, dst_pages,
++ dst->ttm->num_pages);
++ if (ret)
++ goto out;
++ }
++
+ d.mapped_dst = 0;
+ d.mapped_src = 0;
+ d.dst_addr = NULL;
+ d.src_addr = NULL;
+- d.dst_pages = dst->ttm->pages;
+- d.src_pages = src->ttm->pages;
++ d.dst_pages = dst->ttm->pages ? dst->ttm->pages : dst_pages;
++ d.src_pages = src->ttm->pages ? src->ttm->pages : src_pages;
+ d.dst_num_pages = PFN_UP(dst->resource->size);
+ d.src_num_pages = PFN_UP(src->resource->size);
+ d.dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL);
+@@ -504,6 +529,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
+ kunmap_atomic(d.src_addr);
+ if (d.dst_addr)
+ kunmap_atomic(d.dst_addr);
++ if (src_pages)
++ kvfree(src_pages);
++ if (dst_pages)
++ kvfree(dst_pages);
+
+ return ret;
+ }
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+index 2bfac3aad7b7d..4aac88cc5f913 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+@@ -377,7 +377,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,
+ {
+ struct ttm_operation_ctx ctx = {
+ .interruptible = params->bo_type != ttm_bo_type_kernel,
+- .no_wait_gpu = false
++ .no_wait_gpu = false,
++ .resv = params->resv,
+ };
+ struct ttm_device *bdev = &dev_priv->bdev;
+ struct drm_device *vdev = &dev_priv->drm;
+@@ -394,8 +395,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,
+
+ vmw_bo_placement_set(vmw_bo, params->domain, params->busy_domain);
+ ret = ttm_bo_init_reserved(bdev, &vmw_bo->tbo, params->bo_type,
+- &vmw_bo->placement, 0, &ctx, NULL,
+- NULL, destroy);
++ &vmw_bo->placement, 0, &ctx,
++ params->sg, params->resv, destroy);
+ if (unlikely(ret))
+ return ret;
+
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
+index 0d496dc9c6af7..f349642e6190d 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
+@@ -55,6 +55,8 @@ struct vmw_bo_params {
+ enum ttm_bo_type bo_type;
+ size_t size;
+ bool pin;
++ struct dma_resv *resv;
++ struct sg_table *sg;
+ };
+
+ /**
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+index 0a304706e0132..58fb40c93100a 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+@@ -1628,6 +1628,7 @@ static const struct drm_driver driver = {
+
+ .prime_fd_to_handle = vmw_prime_fd_to_handle,
+ .prime_handle_to_fd = vmw_prime_handle_to_fd,
++ .gem_prime_import_sg_table = vmw_prime_import_sg_table,
+
+ .fops = &vmwgfx_driver_fops,
+ .name = VMWGFX_DRIVER_NAME,
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+index 3cd5090dedfc5..6acc7ad0e9eb8 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+@@ -1131,6 +1131,9 @@ extern int vmw_prime_handle_to_fd(struct drm_device *dev,
+ struct drm_file *file_priv,
+ uint32_t handle, uint32_t flags,
+ int *prime_fd);
++struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev,
++ struct dma_buf_attachment *attach,
++ struct sg_table *table);
+
+ /*
+ * MemoryOBject management - vmwgfx_mob.c
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
+index 12787bb9c111d..d6bcaf078b1f4 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
+@@ -149,6 +149,38 @@ int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv,
+ return ret;
+ }
+
++struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev,
++ struct dma_buf_attachment *attach,
++ struct sg_table *table)
++{
++ int ret;
++ struct vmw_private *dev_priv = vmw_priv(dev);
++ struct drm_gem_object *gem = NULL;
++ struct vmw_bo *vbo;
++ struct vmw_bo_params params = {
++ .domain = (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM,
++ .busy_domain = VMW_BO_DOMAIN_SYS,
++ .bo_type = ttm_bo_type_sg,
++ .size = attach->dmabuf->size,
++ .pin = false,
++ .resv = attach->dmabuf->resv,
++ .sg = table,
++
++ };
++
++ dma_resv_lock(params.resv, NULL);
++
++ ret = vmw_bo_create(dev_priv, ¶ms, &vbo);
++ if (ret != 0)
++ goto out_no_bo;
++
++ vbo->tbo.base.funcs = &vmw_gem_object_funcs;
++
++ gem = &vbo->tbo.base;
++out_no_bo:
++ dma_resv_unlock(params.resv);
++ return gem;
++}
+
+ int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data,
+ struct drm_file *filp)
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+index 65be9e4a8992a..f27afc6e39ee2 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+@@ -932,6 +932,7 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
+ int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+ {
++ struct vmw_private *vmw = vmw_priv(crtc->dev);
+ struct drm_crtc_state *new_state = drm_atomic_get_new_crtc_state(state,
+ crtc);
+ struct vmw_display_unit *du = vmw_crtc_to_du(new_state->crtc);
+@@ -939,9 +940,13 @@ int vmw_du_crtc_atomic_check(struct drm_crtc *crtc,
+ bool has_primary = new_state->plane_mask &
+ drm_plane_mask(crtc->primary);
+
+- /* We always want to have an active plane with an active CRTC */
+- if (has_primary != new_state->enable)
+- return -EINVAL;
++ /*
++ * This is fine in general, but broken userspace might expect
++ * some actual rendering so give a clue as why it's blank.
++ */
++ if (new_state->enable && !has_primary)
++ drm_dbg_driver(&vmw->drm,
++ "CRTC without a primary plane will be blank.\n");
+
+
+ if (new_state->connector_mask != connector_mask &&
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+index db81e635dc061..9fda4f4ec7a97 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+@@ -243,10 +243,10 @@ struct vmw_framebuffer_bo {
+
+
+ static const uint32_t __maybe_unused vmw_primary_plane_formats[] = {
+- DRM_FORMAT_XRGB1555,
+- DRM_FORMAT_RGB565,
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_ARGB8888,
++ DRM_FORMAT_RGB565,
++ DRM_FORMAT_XRGB1555,
+ };
+
+ static const uint32_t __maybe_unused vmw_cursor_plane_formats[] = {
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
+index 2d72a5ee7c0c7..c99cad4449915 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
+@@ -75,8 +75,12 @@ int vmw_prime_fd_to_handle(struct drm_device *dev,
+ int fd, u32 *handle)
+ {
+ struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
++ int ret = ttm_prime_fd_to_handle(tfile, fd, handle);
+
+- return ttm_prime_fd_to_handle(tfile, fd, handle);
++ if (ret)
++ ret = drm_gem_prime_fd_to_handle(dev, file_priv, fd, handle);
++
++ return ret;
+ }
+
+ int vmw_prime_handle_to_fd(struct drm_device *dev,
+@@ -85,5 +89,12 @@ int vmw_prime_handle_to_fd(struct drm_device *dev,
+ int *prime_fd)
+ {
+ struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+- return ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd);
++ int ret;
++
++ if (handle > VMWGFX_NUM_MOB)
++ ret = ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd);
++ else
++ ret = drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, prime_fd);
++
++ return ret;
+ }
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
+index af8562c95cc35..fcb87d83760ef 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
+@@ -220,13 +220,18 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
+ switch (dev_priv->map_mode) {
+ case vmw_dma_map_bind:
+ case vmw_dma_map_populate:
+- vsgt->sgt = &vmw_tt->sgt;
+- ret = sg_alloc_table_from_pages_segment(
+- &vmw_tt->sgt, vsgt->pages, vsgt->num_pages, 0,
+- (unsigned long)vsgt->num_pages << PAGE_SHIFT,
+- dma_get_max_seg_size(dev_priv->drm.dev), GFP_KERNEL);
+- if (ret)
+- goto out_sg_alloc_fail;
++ if (vmw_tt->dma_ttm.page_flags & TTM_TT_FLAG_EXTERNAL) {
++ vsgt->sgt = vmw_tt->dma_ttm.sg;
++ } else {
++ vsgt->sgt = &vmw_tt->sgt;
++ ret = sg_alloc_table_from_pages_segment(&vmw_tt->sgt,
++ vsgt->pages, vsgt->num_pages, 0,
++ (unsigned long)vsgt->num_pages << PAGE_SHIFT,
++ dma_get_max_seg_size(dev_priv->drm.dev),
++ GFP_KERNEL);
++ if (ret)
++ goto out_sg_alloc_fail;
++ }
+
+ ret = vmw_ttm_map_for_dma(vmw_tt);
+ if (unlikely(ret != 0))
+@@ -241,8 +246,9 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt)
+ return 0;
+
+ out_map_fail:
+- sg_free_table(vmw_tt->vsgt.sgt);
+- vmw_tt->vsgt.sgt = NULL;
++ drm_warn(&dev_priv->drm, "VSG table map failed!");
++ sg_free_table(vsgt->sgt);
++ vsgt->sgt = NULL;
+ out_sg_alloc_fail:
+ return ret;
+ }
+@@ -388,15 +394,17 @@ static void vmw_ttm_destroy(struct ttm_device *bdev, struct ttm_tt *ttm)
+ static int vmw_ttm_populate(struct ttm_device *bdev,
+ struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
+ {
+- int ret;
++ bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0;
+
+- /* TODO: maybe completely drop this ? */
+ if (ttm_tt_is_populated(ttm))
+ return 0;
+
+- ret = ttm_pool_alloc(&bdev->pool, ttm, ctx);
++ if (external && ttm->sg)
++ return drm_prime_sg_to_dma_addr_array(ttm->sg,
++ ttm->dma_address,
++ ttm->num_pages);
+
+- return ret;
++ return ttm_pool_alloc(&bdev->pool, ttm, ctx);
+ }
+
+ static void vmw_ttm_unpopulate(struct ttm_device *bdev,
+@@ -404,6 +412,10 @@ static void vmw_ttm_unpopulate(struct ttm_device *bdev,
+ {
+ struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt,
+ dma_ttm);
++ bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0;
++
++ if (external)
++ return;
+
+ vmw_ttm_unbind(bdev, ttm);
+
+@@ -422,6 +434,7 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,
+ {
+ struct vmw_ttm_tt *vmw_be;
+ int ret;
++ bool external = bo->type == ttm_bo_type_sg;
+
+ vmw_be = kzalloc(sizeof(*vmw_be), GFP_KERNEL);
+ if (!vmw_be)
+@@ -430,7 +443,10 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo,
+ vmw_be->dev_priv = vmw_priv_from_ttm(bo->bdev);
+ vmw_be->mob = NULL;
+
+- if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent)
++ if (external)
++ page_flags |= TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_EXTERNAL_MAPPABLE;
++
++ if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent || external)
+ ret = ttm_sg_tt_init(&vmw_be->dma_ttm, bo, page_flags,
+ ttm_cached);
+ else
+diff --git a/drivers/gpu/drm/xe/display/intel_fb_bo.c b/drivers/gpu/drm/xe/display/intel_fb_bo.c
+index b21da7b745a5e..a9c1f9885c6bb 100644
+--- a/drivers/gpu/drm/xe/display/intel_fb_bo.c
++++ b/drivers/gpu/drm/xe/display/intel_fb_bo.c
+@@ -31,7 +31,7 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
+
+ ret = ttm_bo_reserve(&bo->ttm, true, false, NULL);
+ if (ret)
+- return ret;
++ goto err;
+
+ if (!(bo->flags & XE_BO_SCANOUT_BIT)) {
+ /*
+@@ -42,12 +42,16 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb,
+ */
+ if (XE_IOCTL_DBG(i915, !list_empty(&bo->ttm.base.gpuva.list))) {
+ ttm_bo_unreserve(&bo->ttm);
+- return -EINVAL;
++ ret = -EINVAL;
++ goto err;
+ }
+ bo->flags |= XE_BO_SCANOUT_BIT;
+ }
+ ttm_bo_unreserve(&bo->ttm);
++ return 0;
+
++err:
++ xe_bo_put(bo);
+ return ret;
+ }
+
+diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
+index bf0df6ee4f785..07fb8d3c037f0 100644
+--- a/drivers/infiniband/core/cm.c
++++ b/drivers/infiniband/core/cm.c
+@@ -1026,23 +1026,26 @@ static void cm_reset_to_idle(struct cm_id_private *cm_id_priv)
+ }
+ }
+
+-static noinline void cm_destroy_id_wait_timeout(struct ib_cm_id *cm_id)
++static noinline void cm_destroy_id_wait_timeout(struct ib_cm_id *cm_id,
++ enum ib_cm_state old_state)
+ {
+ struct cm_id_private *cm_id_priv;
+
+ cm_id_priv = container_of(cm_id, struct cm_id_private, id);
+- pr_err("%s: cm_id=%p timed out. state=%d refcnt=%d\n", __func__,
+- cm_id, cm_id->state, refcount_read(&cm_id_priv->refcount));
++ pr_err("%s: cm_id=%p timed out. state %d -> %d, refcnt=%d\n", __func__,
++ cm_id, old_state, cm_id->state, refcount_read(&cm_id_priv->refcount));
+ }
+
+ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
+ {
+ struct cm_id_private *cm_id_priv;
++ enum ib_cm_state old_state;
+ struct cm_work *work;
+ int ret;
+
+ cm_id_priv = container_of(cm_id, struct cm_id_private, id);
+ spin_lock_irq(&cm_id_priv->lock);
++ old_state = cm_id->state;
+ retest:
+ switch (cm_id->state) {
+ case IB_CM_LISTEN:
+@@ -1151,7 +1154,7 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
+ msecs_to_jiffies(
+ CM_DESTROY_ID_WAIT_TIMEOUT));
+ if (!ret) /* timeout happened */
+- cm_destroy_id_wait_timeout(cm_id);
++ cm_destroy_id_wait_timeout(cm_id, old_state);
+ } while (!ret);
+
+ while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
+diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c
+index 0c3c4e64812c5..3e43687a7f6f7 100644
+--- a/drivers/infiniband/hw/mlx5/mad.c
++++ b/drivers/infiniband/hw/mlx5/mad.c
+@@ -188,7 +188,8 @@ static int process_pma_cmd(struct mlx5_ib_dev *dev, u32 port_num,
+ mdev = dev->mdev;
+ mdev_port_num = 1;
+ }
+- if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1) {
++ if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1 &&
++ !mlx5_core_mp_enabled(mdev)) {
+ /* set local port to one for Function-Per-Port HCA. */
+ mdev = dev->mdev;
+ mdev_port_num = 1;
+diff --git a/drivers/infiniband/sw/rxe/rxe.c b/drivers/infiniband/sw/rxe/rxe.c
+index 54c723a6eddac..6f9ec8db014c7 100644
+--- a/drivers/infiniband/sw/rxe/rxe.c
++++ b/drivers/infiniband/sw/rxe/rxe.c
+@@ -33,6 +33,8 @@ void rxe_dealloc(struct ib_device *ib_dev)
+
+ if (rxe->tfm)
+ crypto_free_shash(rxe->tfm);
++
++ mutex_destroy(&rxe->usdev_lock);
+ }
+
+ /* initialize rxe device parameters */
+diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
+index 50bac2d79d9b5..68edb07d4443e 100644
+--- a/drivers/interconnect/core.c
++++ b/drivers/interconnect/core.c
+@@ -176,6 +176,8 @@ static struct icc_path *path_init(struct device *dev, struct icc_node *dst,
+
+ path->num_nodes = num_nodes;
+
++ mutex_lock(&icc_bw_lock);
++
+ for (i = num_nodes - 1; i >= 0; i--) {
+ node->provider->users++;
+ hlist_add_head(&path->reqs[i].req_node, &node->req_list);
+@@ -186,6 +188,8 @@ static struct icc_path *path_init(struct device *dev, struct icc_node *dst,
+ node = node->reverse;
+ }
+
++ mutex_unlock(&icc_bw_lock);
++
+ return path;
+ }
+
+@@ -792,12 +796,16 @@ void icc_put(struct icc_path *path)
+ pr_err("%s: error (%d)\n", __func__, ret);
+
+ mutex_lock(&icc_lock);
++ mutex_lock(&icc_bw_lock);
++
+ for (i = 0; i < path->num_nodes; i++) {
+ node = path->reqs[i].node;
+ hlist_del(&path->reqs[i].req_node);
+ if (!WARN_ON(!node->provider->users))
+ node->provider->users--;
+ }
++
++ mutex_unlock(&icc_bw_lock);
+ mutex_unlock(&icc_lock);
+
+ kfree_const(path->name);
+diff --git a/drivers/interconnect/qcom/x1e80100.c b/drivers/interconnect/qcom/x1e80100.c
+index cbaf4f9c41be6..06f0a6d6cbbc0 100644
+--- a/drivers/interconnect/qcom/x1e80100.c
++++ b/drivers/interconnect/qcom/x1e80100.c
+@@ -116,15 +116,6 @@ static struct qcom_icc_node xm_sdc2 = {
+ .links = { X1E80100_SLAVE_A2NOC_SNOC },
+ };
+
+-static struct qcom_icc_node ddr_perf_mode_master = {
+- .name = "ddr_perf_mode_master",
+- .id = X1E80100_MASTER_DDR_PERF_MODE,
+- .channels = 1,
+- .buswidth = 4,
+- .num_links = 1,
+- .links = { X1E80100_SLAVE_DDR_PERF_MODE },
+-};
+-
+ static struct qcom_icc_node qup0_core_master = {
+ .name = "qup0_core_master",
+ .id = X1E80100_MASTER_QUP_CORE_0,
+@@ -832,14 +823,6 @@ static struct qcom_icc_node qns_a2noc_snoc = {
+ .links = { X1E80100_MASTER_A2NOC_SNOC },
+ };
+
+-static struct qcom_icc_node ddr_perf_mode_slave = {
+- .name = "ddr_perf_mode_slave",
+- .id = X1E80100_SLAVE_DDR_PERF_MODE,
+- .channels = 1,
+- .buswidth = 4,
+- .num_links = 0,
+-};
+-
+ static struct qcom_icc_node qup0_core_slave = {
+ .name = "qup0_core_slave",
+ .id = X1E80100_SLAVE_QUP_CORE_0,
+@@ -1591,12 +1574,6 @@ static struct qcom_icc_bcm bcm_acv = {
+ .nodes = { &ebi },
+ };
+
+-static struct qcom_icc_bcm bcm_acv_perf = {
+- .name = "ACV_PERF",
+- .num_nodes = 1,
+- .nodes = { &ddr_perf_mode_slave },
+-};
+-
+ static struct qcom_icc_bcm bcm_ce0 = {
+ .name = "CE0",
+ .num_nodes = 1,
+@@ -1863,18 +1840,15 @@ static const struct qcom_icc_desc x1e80100_aggre2_noc = {
+ };
+
+ static struct qcom_icc_bcm * const clk_virt_bcms[] = {
+- &bcm_acv_perf,
+ &bcm_qup0,
+ &bcm_qup1,
+ &bcm_qup2,
+ };
+
+ static struct qcom_icc_node * const clk_virt_nodes[] = {
+- [MASTER_DDR_PERF_MODE] = &ddr_perf_mode_master,
+ [MASTER_QUP_CORE_0] = &qup0_core_master,
+ [MASTER_QUP_CORE_1] = &qup1_core_master,
+ [MASTER_QUP_CORE_2] = &qup2_core_master,
+- [SLAVE_DDR_PERF_MODE] = &ddr_perf_mode_slave,
+ [SLAVE_QUP_CORE_0] = &qup0_core_slave,
+ [SLAVE_QUP_CORE_1] = &qup1_core_slave,
+ [SLAVE_QUP_CORE_2] = &qup2_core_slave,
+diff --git a/drivers/iommu/iommufd/Kconfig b/drivers/iommu/iommufd/Kconfig
+index 99d4b075df49e..76656fe0470d7 100644
+--- a/drivers/iommu/iommufd/Kconfig
++++ b/drivers/iommu/iommufd/Kconfig
+@@ -37,6 +37,7 @@ config IOMMUFD_TEST
+ depends on DEBUG_KERNEL
+ depends on FAULT_INJECTION
+ depends on RUNTIME_TESTING_MENU
++ select IOMMUFD_DRIVER
+ default n
+ help
+ This is dangerous, do not enable unless running
+diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c
+index 1a64364700eb0..0ad2ff9065aad 100644
+--- a/drivers/misc/cardreader/rtsx_pcr.c
++++ b/drivers/misc/cardreader/rtsx_pcr.c
+@@ -1002,7 +1002,7 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
+ } else {
+ pcr->card_removed |= SD_EXIST;
+ pcr->card_inserted &= ~SD_EXIST;
+- if (PCI_PID(pcr) == PID_5261) {
++ if ((PCI_PID(pcr) == PID_5261) || (PCI_PID(pcr) == PID_5264)) {
+ rtsx_pci_write_register(pcr, RTS5261_FW_STATUS,
+ RTS5261_EXPRESS_LINK_FAIL_MASK, 0);
+ pcr->extra_caps |= EXTRA_CAPS_SD_EXPRESS;
+diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
+index 8cf636c540322..bd4e3df44865e 100644
+--- a/drivers/misc/mei/pci-me.c
++++ b/drivers/misc/mei/pci-me.c
+@@ -116,7 +116,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
+ {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_P, MEI_ME_PCH15_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_N, MEI_ME_PCH15_CFG)},
+
+- {MEI_PCI_DEVICE(MEI_DEV_ID_RPL_S, MEI_ME_PCH15_CFG)},
++ {MEI_PCI_DEVICE(MEI_DEV_ID_RPL_S, MEI_ME_PCH15_SPS_CFG)},
+
+ {MEI_PCI_DEVICE(MEI_DEV_ID_MTL_M, MEI_ME_PCH15_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_ARL_S, MEI_ME_PCH15_CFG)},
+diff --git a/drivers/misc/mei/platform-vsc.c b/drivers/misc/mei/platform-vsc.c
+index 8d303c6c00006..8db0fcf24e709 100644
+--- a/drivers/misc/mei/platform-vsc.c
++++ b/drivers/misc/mei/platform-vsc.c
+@@ -402,25 +402,40 @@ static int mei_vsc_remove(struct platform_device *pdev)
+ static int mei_vsc_suspend(struct device *dev)
+ {
+ struct mei_device *mei_dev = dev_get_drvdata(dev);
++ struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
+
+ mei_stop(mei_dev);
+
++ mei_disable_interrupts(mei_dev);
++
++ vsc_tp_free_irq(hw->tp);
++
+ return 0;
+ }
+
+ static int mei_vsc_resume(struct device *dev)
+ {
+ struct mei_device *mei_dev = dev_get_drvdata(dev);
++ struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev);
+ int ret;
+
+- ret = mei_restart(mei_dev);
++ ret = vsc_tp_request_irq(hw->tp);
+ if (ret)
+ return ret;
+
++ ret = mei_restart(mei_dev);
++ if (ret)
++ goto err_free;
++
+ /* start timer if stopped in suspend */
+ schedule_delayed_work(&mei_dev->timer_work, HZ);
+
+ return 0;
++
++err_free:
++ vsc_tp_free_irq(hw->tp);
++
++ return ret;
+ }
+
+ static DEFINE_SIMPLE_DEV_PM_OPS(mei_vsc_pm_ops, mei_vsc_suspend, mei_vsc_resume);
+diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c
+index 682c62c635b63..870c70ef3bb8b 100644
+--- a/drivers/misc/mei/vsc-tp.c
++++ b/drivers/misc/mei/vsc-tp.c
+@@ -94,6 +94,27 @@ static const struct acpi_gpio_mapping vsc_tp_acpi_gpios[] = {
+ {}
+ };
+
++static irqreturn_t vsc_tp_isr(int irq, void *data)
++{
++ struct vsc_tp *tp = data;
++
++ atomic_inc(&tp->assert_cnt);
++
++ wake_up(&tp->xfer_wait);
++
++ return IRQ_WAKE_THREAD;
++}
++
++static irqreturn_t vsc_tp_thread_isr(int irq, void *data)
++{
++ struct vsc_tp *tp = data;
++
++ if (tp->event_notify)
++ tp->event_notify(tp->event_notify_context);
++
++ return IRQ_HANDLED;
++}
++
+ /* wakeup firmware and wait for response */
+ static int vsc_tp_wakeup_request(struct vsc_tp *tp)
+ {
+@@ -383,6 +404,37 @@ int vsc_tp_register_event_cb(struct vsc_tp *tp, vsc_tp_event_cb_t event_cb,
+ }
+ EXPORT_SYMBOL_NS_GPL(vsc_tp_register_event_cb, VSC_TP);
+
++/**
++ * vsc_tp_request_irq - request irq for vsc_tp device
++ * @tp: vsc_tp device handle
++ */
++int vsc_tp_request_irq(struct vsc_tp *tp)
++{
++ struct spi_device *spi = tp->spi;
++ struct device *dev = &spi->dev;
++ int ret;
++
++ irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY);
++ ret = request_threaded_irq(spi->irq, vsc_tp_isr, vsc_tp_thread_isr,
++ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
++ dev_name(dev), tp);
++ if (ret)
++ return ret;
++
++ return 0;
++}
++EXPORT_SYMBOL_NS_GPL(vsc_tp_request_irq, VSC_TP);
++
++/**
++ * vsc_tp_free_irq - free irq for vsc_tp device
++ * @tp: vsc_tp device handle
++ */
++void vsc_tp_free_irq(struct vsc_tp *tp)
++{
++ free_irq(tp->spi->irq, tp);
++}
++EXPORT_SYMBOL_NS_GPL(vsc_tp_free_irq, VSC_TP);
++
+ /**
+ * vsc_tp_intr_synchronize - synchronize vsc_tp interrupt
+ * @tp: vsc_tp device handle
+@@ -413,27 +465,6 @@ void vsc_tp_intr_disable(struct vsc_tp *tp)
+ }
+ EXPORT_SYMBOL_NS_GPL(vsc_tp_intr_disable, VSC_TP);
+
+-static irqreturn_t vsc_tp_isr(int irq, void *data)
+-{
+- struct vsc_tp *tp = data;
+-
+- atomic_inc(&tp->assert_cnt);
+-
+- return IRQ_WAKE_THREAD;
+-}
+-
+-static irqreturn_t vsc_tp_thread_isr(int irq, void *data)
+-{
+- struct vsc_tp *tp = data;
+-
+- wake_up(&tp->xfer_wait);
+-
+- if (tp->event_notify)
+- tp->event_notify(tp->event_notify_context);
+-
+- return IRQ_HANDLED;
+-}
+-
+ static int vsc_tp_match_any(struct acpi_device *adev, void *data)
+ {
+ struct acpi_device **__adev = data;
+@@ -485,10 +516,9 @@ static int vsc_tp_probe(struct spi_device *spi)
+ tp->spi = spi;
+
+ irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY);
+- ret = devm_request_threaded_irq(dev, spi->irq, vsc_tp_isr,
+- vsc_tp_thread_isr,
+- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+- dev_name(dev), tp);
++ ret = request_threaded_irq(spi->irq, vsc_tp_isr, vsc_tp_thread_isr,
++ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
++ dev_name(dev), tp);
+ if (ret)
+ return ret;
+
+@@ -522,6 +552,8 @@ static int vsc_tp_probe(struct spi_device *spi)
+ err_destroy_lock:
+ mutex_destroy(&tp->mutex);
+
++ free_irq(spi->irq, tp);
++
+ return ret;
+ }
+
+@@ -532,6 +564,8 @@ static void vsc_tp_remove(struct spi_device *spi)
+ platform_device_unregister(tp->pdev);
+
+ mutex_destroy(&tp->mutex);
++
++ free_irq(spi->irq, tp);
+ }
+
+ static const struct acpi_device_id vsc_tp_acpi_ids[] = {
+diff --git a/drivers/misc/mei/vsc-tp.h b/drivers/misc/mei/vsc-tp.h
+index f9513ddc3e409..14ca195cbddcc 100644
+--- a/drivers/misc/mei/vsc-tp.h
++++ b/drivers/misc/mei/vsc-tp.h
+@@ -37,6 +37,9 @@ int vsc_tp_xfer(struct vsc_tp *tp, u8 cmd, const void *obuf, size_t olen,
+ int vsc_tp_register_event_cb(struct vsc_tp *tp, vsc_tp_event_cb_t event_cb,
+ void *context);
+
++int vsc_tp_request_irq(struct vsc_tp *tp);
++void vsc_tp_free_irq(struct vsc_tp *tp);
++
+ void vsc_tp_intr_enable(struct vsc_tp *tp);
+ void vsc_tp_intr_disable(struct vsc_tp *tp);
+ void vsc_tp_intr_synchronize(struct vsc_tp *tp);
+diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
+index 22b97505fa536..e48ef9823c8ea 100644
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1947,14 +1947,16 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port,
+
+ static int mt753x_mirror_port_get(unsigned int id, u32 val)
+ {
+- return (id == ID_MT7531) ? MT7531_MIRROR_PORT_GET(val) :
+- MIRROR_PORT(val);
++ return (id == ID_MT7531 || id == ID_MT7988) ?
++ MT7531_MIRROR_PORT_GET(val) :
++ MIRROR_PORT(val);
+ }
+
+ static int mt753x_mirror_port_set(unsigned int id, u32 val)
+ {
+- return (id == ID_MT7531) ? MT7531_MIRROR_PORT_SET(val) :
+- MIRROR_PORT(val);
++ return (id == ID_MT7531 || id == ID_MT7988) ?
++ MT7531_MIRROR_PORT_SET(val) :
++ MIRROR_PORT(val);
+ }
+
+ static int mt753x_port_mirror_add(struct dsa_switch *ds, int port,
+@@ -2469,8 +2471,6 @@ mt7530_setup(struct dsa_switch *ds)
+ SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST |
+ SYS_CTRL_REG_RST);
+
+- mt7530_pll_setup(priv);
+-
+ /* Lower Tx driving for TRGMII path */
+ for (i = 0; i < NUM_TRGMII_CTRL; i++)
+ mt7530_write(priv, MT7530_TRGMII_TD_ODT(i),
+@@ -2488,6 +2488,9 @@ mt7530_setup(struct dsa_switch *ds)
+
+ priv->p6_interface = PHY_INTERFACE_MODE_NA;
+
++ if ((val & HWTRAP_XTAL_MASK) == HWTRAP_XTAL_40MHZ)
++ mt7530_pll_setup(priv);
++
+ mt753x_trap_frames(priv);
+
+ /* Enable and reset MIB counters */
+@@ -2517,6 +2520,9 @@ mt7530_setup(struct dsa_switch *ds)
+ PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
+ }
+
++ /* Allow mirroring frames received on the local port (monitor port). */
++ mt7530_set(priv, MT753X_AGC, LOCAL_EN);
++
+ /* Setup VLAN ID 0 for VLAN-unaware bridges */
+ ret = mt7530_setup_vlan0(priv);
+ if (ret)
+@@ -2625,6 +2631,9 @@ mt7531_setup_common(struct dsa_switch *ds)
+ PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
+ }
+
++ /* Allow mirroring frames received on the local port (monitor port). */
++ mt7530_set(priv, MT753X_AGC, LOCAL_EN);
++
+ /* Flush the FDB table */
+ ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);
+ if (ret < 0)
+@@ -2703,18 +2712,25 @@ mt7531_setup(struct dsa_switch *ds)
+ priv->p5_interface = PHY_INTERFACE_MODE_NA;
+ priv->p6_interface = PHY_INTERFACE_MODE_NA;
+
+- /* Enable PHY core PLL, since phy_device has not yet been created
+- * provided for phy_[read,write]_mmd_indirect is called, we provide
+- * our own mt7531_ind_mmd_phy_[read,write] to complete this
+- * function.
++ /* Enable Energy-Efficient Ethernet (EEE) and PHY core PLL, since
++ * phy_device has not yet been created provided for
++ * phy_[read,write]_mmd_indirect is called, we provide our own
++ * mt7531_ind_mmd_phy_[read,write] to complete this function.
+ */
+ val = mt7531_ind_c45_phy_read(priv, MT753X_CTRL_PHY_ADDR,
+ MDIO_MMD_VEND2, CORE_PLL_GROUP4);
+- val |= MT7531_PHY_PLL_BYPASS_MODE;
++ val |= MT7531_RG_SYSPLL_DMY2 | MT7531_PHY_PLL_BYPASS_MODE;
+ val &= ~MT7531_PHY_PLL_OFF;
+ mt7531_ind_c45_phy_write(priv, MT753X_CTRL_PHY_ADDR, MDIO_MMD_VEND2,
+ CORE_PLL_GROUP4, val);
+
++ /* Disable EEE advertisement on the switch PHYs. */
++ for (i = MT753X_CTRL_PHY_ADDR;
++ i < MT753X_CTRL_PHY_ADDR + MT7530_NUM_PHYS; i++) {
++ mt7531_ind_c45_phy_write(priv, i, MDIO_MMD_AN, MDIO_AN_EEE_ADV,
++ 0);
++ }
++
+ mt7531_setup_common(ds);
+
+ /* Setup VLAN ID 0 for VLAN-unaware bridges */
+diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
+index ddefeb69afda1..0ad52d3cbfebb 100644
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -32,6 +32,10 @@ enum mt753x_id {
+ #define SYSC_REG_RSTCTRL 0x34
+ #define RESET_MCM BIT(2)
+
++/* Register for ARL global control */
++#define MT753X_AGC 0xc
++#define LOCAL_EN BIT(7)
++
+ /* Registers to mac forward control for unknown frames */
+ #define MT7530_MFC 0x10
+ #define BC_FFP(x) (((x) & 0xff) << 24)
+@@ -630,6 +634,7 @@ enum mt7531_clk_skew {
+ #define RG_SYSPLL_DDSFBK_EN BIT(12)
+ #define RG_SYSPLL_BIAS_EN BIT(11)
+ #define RG_SYSPLL_BIAS_LPF_EN BIT(10)
++#define MT7531_RG_SYSPLL_DMY2 BIT(6)
+ #define MT7531_PHY_PLL_OFF BIT(5)
+ #define MT7531_PHY_PLL_BYPASS_MODE BIT(4)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
+index b890410a2bc0b..688ccb0615ab9 100644
+--- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c
++++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c
+@@ -28,6 +28,8 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
+ * - ICE_TC_FLWR_FIELD_VLAN_TPID (present if specified)
+ * - Tunnel flag (present if tunnel)
+ */
++ if (fltr->direction == ICE_ESWITCH_FLTR_EGRESS)
++ lkups_cnt++;
+
+ if (flags & ICE_TC_FLWR_FIELD_TENANT_ID)
+ lkups_cnt++;
+@@ -363,6 +365,11 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
+ /* Always add direction metadata */
+ ice_rule_add_direction_metadata(&list[ICE_TC_METADATA_LKUP_IDX]);
+
++ if (tc_fltr->direction == ICE_ESWITCH_FLTR_EGRESS) {
++ ice_rule_add_src_vsi_metadata(&list[i]);
++ i++;
++ }
++
+ rule_info->tun_type = ice_sw_type_from_tunnel(tc_fltr->tunnel_type);
+ if (tc_fltr->tunnel_type != TNL_LAST) {
+ i = ice_tc_fill_tunnel_outer(flags, tc_fltr, list, i);
+@@ -772,7 +779,7 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr)
+ int ret;
+ int i;
+
+- if (!flags || (flags & ICE_TC_FLWR_FIELD_ENC_SRC_L4_PORT)) {
++ if (flags & ICE_TC_FLWR_FIELD_ENC_SRC_L4_PORT) {
+ NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported encap field(s)");
+ return -EOPNOTSUPP;
+ }
+@@ -820,6 +827,7 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr)
+
+ /* specify the cookie as filter_rule_id */
+ rule_info.fltr_rule_id = fltr->cookie;
++ rule_info.src_vsi = vsi->idx;
+
+ ret = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, &rule_added);
+ if (ret == -EEXIST) {
+@@ -1481,7 +1489,10 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
+ (BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
+ BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
+ BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) |
+- BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS))) {
++ BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS) |
++ BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP) |
++ BIT_ULL(FLOW_DISSECTOR_KEY_ENC_OPTS) |
++ BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL))) {
+ NL_SET_ERR_MSG_MOD(fltr->extack, "Tunnel key used, but device isn't a tunnel");
+ return -EOPNOTSUPP;
+ } else {
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
+index 4fd44b6eecea6..60ee7ae2c4097 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
+@@ -688,6 +688,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
+
+ if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
+ struct flow_match_control match;
++ u32 val;
+
+ flow_rule_match_control(rule, &match);
+ if (match.mask->flags & FLOW_DIS_FIRST_FRAG) {
+@@ -696,12 +697,14 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
+ }
+
+ if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) {
++ val = match.key->flags & FLOW_DIS_IS_FRAGMENT;
+ if (ntohs(flow_spec->etype) == ETH_P_IP) {
+- flow_spec->ip_flag = IPV4_FLAG_MORE;
++ flow_spec->ip_flag = val ? IPV4_FLAG_MORE : 0;
+ flow_mask->ip_flag = IPV4_FLAG_MORE;
+ req->features |= BIT_ULL(NPC_IPFRAG_IPV4);
+ } else if (ntohs(flow_spec->etype) == ETH_P_IPV6) {
+- flow_spec->next_header = IPPROTO_FRAGMENT;
++ flow_spec->next_header = val ?
++ IPPROTO_FRAGMENT : 0;
+ flow_mask->next_header = 0xff;
+ req->features |= BIT_ULL(NPC_IPFRAG_IPV6);
+ } else {
+diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c
+index c895e265ae0eb..61334a71058c7 100644
+--- a/drivers/net/ethernet/mediatek/mtk_wed.c
++++ b/drivers/net/ethernet/mediatek/mtk_wed.c
+@@ -1074,13 +1074,13 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
+ static void
+ mtk_wed_stop(struct mtk_wed_device *dev)
+ {
++ mtk_wed_dma_disable(dev);
+ mtk_wed_set_ext_int(dev, false);
+
+ wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
+ wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
+ wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
+ wdma_w32(dev, MTK_WDMA_INT_GRP2, 0);
+- wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0);
+
+ if (!mtk_wed_get_rx_capa(dev))
+ return;
+@@ -1093,7 +1093,6 @@ static void
+ mtk_wed_deinit(struct mtk_wed_device *dev)
+ {
+ mtk_wed_stop(dev);
+- mtk_wed_dma_disable(dev);
+
+ wed_clr(dev, MTK_WED_CTRL,
+ MTK_WED_CTRL_WDMA_INT_AGENT_EN |
+@@ -2605,9 +2604,6 @@ mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask)
+ static void
+ mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask)
+ {
+- if (!dev->running)
+- return;
+-
+ mtk_wed_set_ext_int(dev, !!mask);
+ wed_w32(dev, MTK_WED_INT_MASK, mask);
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
+index e66f486faafe1..415fec7763bd2 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
+@@ -45,6 +45,10 @@ struct arfs_table {
+ struct hlist_head rules_hash[ARFS_HASH_SIZE];
+ };
+
++enum {
++ MLX5E_ARFS_STATE_ENABLED,
++};
++
+ enum arfs_type {
+ ARFS_IPV4_TCP,
+ ARFS_IPV6_TCP,
+@@ -59,6 +63,7 @@ struct mlx5e_arfs_tables {
+ spinlock_t arfs_lock;
+ int last_filter_id;
+ struct workqueue_struct *wq;
++ unsigned long state;
+ };
+
+ struct arfs_tuple {
+@@ -169,6 +174,8 @@ int mlx5e_arfs_enable(struct mlx5e_flow_steering *fs)
+ return err;
+ }
+ }
++ set_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state);
++
+ return 0;
+ }
+
+@@ -454,6 +461,8 @@ static void arfs_del_rules(struct mlx5e_flow_steering *fs)
+ int i;
+ int j;
+
++ clear_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state);
++
+ spin_lock_bh(&arfs->arfs_lock);
+ mlx5e_for_each_arfs_rule(rule, htmp, arfs->arfs_tables, i, j) {
+ hlist_del_init(&rule->hlist);
+@@ -626,17 +635,8 @@ static void arfs_handle_work(struct work_struct *work)
+ struct mlx5_flow_handle *rule;
+
+ arfs = mlx5e_fs_get_arfs(priv->fs);
+- mutex_lock(&priv->state_lock);
+- if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
+- spin_lock_bh(&arfs->arfs_lock);
+- hlist_del(&arfs_rule->hlist);
+- spin_unlock_bh(&arfs->arfs_lock);
+-
+- mutex_unlock(&priv->state_lock);
+- kfree(arfs_rule);
+- goto out;
+- }
+- mutex_unlock(&priv->state_lock);
++ if (!test_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state))
++ return;
+
+ if (!arfs_rule->rule) {
+ rule = arfs_add_rule(priv, arfs_rule);
+@@ -752,6 +752,11 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
+ return -EPROTONOSUPPORT;
+
+ spin_lock_bh(&arfs->arfs_lock);
++ if (!test_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state)) {
++ spin_unlock_bh(&arfs->arfs_lock);
++ return -EPERM;
++ }
++
+ arfs_rule = arfs_find_rule(arfs_t, &fk);
+ if (arfs_rule) {
+ if (arfs_rule->rxq == rxq_index || work_busy(&arfs_rule->arfs_work)) {
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+index 3047d7015c525..1789800faaeb6 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+@@ -1868,6 +1868,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
+ if (err)
+ goto abort;
+
++ dev->priv.eswitch = esw;
+ err = esw_offloads_init(esw);
+ if (err)
+ goto reps_err;
+@@ -1892,11 +1893,6 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
+ esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC;
+ else
+ esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
+- if (MLX5_ESWITCH_MANAGER(dev) &&
+- mlx5_esw_vport_match_metadata_supported(esw))
+- esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
+-
+- dev->priv.eswitch = esw;
+ BLOCKING_INIT_NOTIFIER_HEAD(&esw->n_head);
+
+ esw_info(dev,
+@@ -1908,6 +1904,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
+
+ reps_err:
+ mlx5_esw_vports_cleanup(esw);
++ dev->priv.eswitch = NULL;
+ abort:
+ if (esw->work_queue)
+ destroy_workqueue(esw->work_queue);
+@@ -1926,7 +1923,6 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
+
+ esw_info(esw->dev, "cleanup\n");
+
+- esw->dev->priv.eswitch = NULL;
+ destroy_workqueue(esw->work_queue);
+ WARN_ON(refcount_read(&esw->qos.refcnt));
+ mutex_destroy(&esw->state_lock);
+@@ -1937,6 +1933,7 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
+ mutex_destroy(&esw->offloads.encap_tbl_lock);
+ mutex_destroy(&esw->offloads.decap_tbl_lock);
+ esw_offloads_cleanup(esw);
++ esw->dev->priv.eswitch = NULL;
+ mlx5_esw_vports_cleanup(esw);
+ debugfs_remove_recursive(esw->debugfs_root);
+ devl_params_unregister(priv_to_devlink(esw->dev), mlx5_eswitch_params,
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+index baaae628b0a0f..e3cce110e52fd 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+@@ -2476,6 +2476,10 @@ int esw_offloads_init(struct mlx5_eswitch *esw)
+ if (err)
+ return err;
+
++ if (MLX5_ESWITCH_MANAGER(esw->dev) &&
++ mlx5_esw_vport_match_metadata_supported(esw))
++ esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
++
+ err = devl_params_register(priv_to_devlink(esw->dev),
+ esw_devlink_params,
+ ARRAY_SIZE(esw_devlink_params));
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+index d14459e5c04fc..69d482f7c5a29 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+@@ -703,8 +703,10 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev)
+ return err;
+ }
+
+- if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags))
++ if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) {
+ mlx5_lag_port_sel_destroy(ldev);
++ ldev->buckets = 1;
++ }
+ if (mlx5_lag_has_drop_rule(ldev))
+ mlx5_lag_drop_rule_cleanup(ldev);
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
+index 131a836c127e3..e285823bd08f0 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
+@@ -1699,12 +1699,15 @@ int mlx5_init_one_light(struct mlx5_core_dev *dev)
+ err = mlx5_devlink_params_register(priv_to_devlink(dev));
+ if (err) {
+ mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err);
+- goto query_hca_caps_err;
++ goto params_reg_err;
+ }
+
+ devl_unlock(devlink);
+ return 0;
+
++params_reg_err:
++ devl_unregister(devlink);
++ devl_unlock(devlink);
+ query_hca_caps_err:
+ devl_unregister(devlink);
+ devl_unlock(devlink);
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
+index e3bf8c7e4baa6..7ebe712808275 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
+@@ -75,7 +75,6 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
+ goto peer_devlink_set_err;
+ }
+
+- devlink_register(devlink);
+ return 0;
+
+ peer_devlink_set_err:
+diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
+index 523e0c470894f..55f255a3c9db6 100644
+--- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c
+@@ -36,6 +36,27 @@ struct sparx5_tc_flower_template {
+ u16 l3_proto; /* protocol specified in the template */
+ };
+
++/* SparX-5 VCAP fragment types:
++ * 0 = no fragment, 1 = initial fragment,
++ * 2 = suspicious fragment, 3 = valid follow-up fragment
++ */
++enum { /* key / mask */
++ FRAG_NOT = 0x03, /* 0 / 3 */
++ FRAG_SOME = 0x11, /* 1 / 1 */
++ FRAG_FIRST = 0x13, /* 1 / 3 */
++ FRAG_LATER = 0x33, /* 3 / 3 */
++ FRAG_INVAL = 0xff, /* invalid */
++};
++
++/* Flower fragment flag to VCAP fragment type mapping */
++static const u8 sparx5_vcap_frag_map[4][4] = { /* is_frag */
++ { FRAG_INVAL, FRAG_INVAL, FRAG_INVAL, FRAG_FIRST }, /* 0/0 */
++ { FRAG_NOT, FRAG_NOT, FRAG_INVAL, FRAG_INVAL }, /* 0/1 */
++ { FRAG_INVAL, FRAG_INVAL, FRAG_INVAL, FRAG_INVAL }, /* 1/0 */
++ { FRAG_SOME, FRAG_LATER, FRAG_INVAL, FRAG_FIRST } /* 1/1 */
++ /* 0/0 0/1 1/0 1/1 <-- first_frag */
++};
++
+ static int
+ sparx5_tc_flower_es0_tpid(struct vcap_tc_flower_parse_usage *st)
+ {
+@@ -145,29 +166,27 @@ sparx5_tc_flower_handler_control_usage(struct vcap_tc_flower_parse_usage *st)
+ flow_rule_match_control(st->frule, &mt);
+
+ if (mt.mask->flags) {
+- if (mt.mask->flags & FLOW_DIS_FIRST_FRAG) {
+- if (mt.key->flags & FLOW_DIS_FIRST_FRAG) {
+- value = 1; /* initial fragment */
+- mask = 0x3;
+- } else {
+- if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) {
+- value = 3; /* follow up fragment */
+- mask = 0x3;
+- } else {
+- value = 0; /* no fragment */
+- mask = 0x3;
+- }
+- }
+- } else {
+- if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) {
+- value = 3; /* follow up fragment */
+- mask = 0x3;
+- } else {
+- value = 0; /* no fragment */
+- mask = 0x3;
+- }
++ u8 is_frag_key = !!(mt.key->flags & FLOW_DIS_IS_FRAGMENT);
++ u8 is_frag_mask = !!(mt.mask->flags & FLOW_DIS_IS_FRAGMENT);
++ u8 is_frag_idx = (is_frag_key << 1) | is_frag_mask;
++
++ u8 first_frag_key = !!(mt.key->flags & FLOW_DIS_FIRST_FRAG);
++ u8 first_frag_mask = !!(mt.mask->flags & FLOW_DIS_FIRST_FRAG);
++ u8 first_frag_idx = (first_frag_key << 1) | first_frag_mask;
++
++ /* Lookup verdict based on the 2 + 2 input bits */
++ u8 vdt = sparx5_vcap_frag_map[is_frag_idx][first_frag_idx];
++
++ if (vdt == FRAG_INVAL) {
++ NL_SET_ERR_MSG_MOD(st->fco->common.extack,
++ "Match on invalid fragment flag combination");
++ return -EINVAL;
+ }
+
++ /* Extract VCAP fragment key and mask from verdict */
++ value = (vdt >> 4) & 0x3;
++ mask = vdt & 0x3;
++
+ err = vcap_rule_add_key_u32(st->vrule,
+ VCAP_KF_L3_FRAGMENT_TYPE,
+ value, mask);
+diff --git a/drivers/net/ethernet/realtek/r8169.h b/drivers/net/ethernet/realtek/r8169.h
+index 81567fcf39579..1ef39928757bd 100644
+--- a/drivers/net/ethernet/realtek/r8169.h
++++ b/drivers/net/ethernet/realtek/r8169.h
+@@ -72,6 +72,7 @@ enum mac_version {
+ };
+
+ struct rtl8169_private;
++struct r8169_led_classdev;
+
+ void r8169_apply_firmware(struct rtl8169_private *tp);
+ u16 rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private *tp);
+@@ -83,4 +84,5 @@ void r8169_get_led_name(struct rtl8169_private *tp, int idx,
+ char *buf, int buf_len);
+ int rtl8168_get_led_mode(struct rtl8169_private *tp);
+ int rtl8168_led_mod_ctrl(struct rtl8169_private *tp, u16 mask, u16 val);
+-void rtl8168_init_leds(struct net_device *ndev);
++struct r8169_led_classdev *rtl8168_init_leds(struct net_device *ndev);
++void r8169_remove_leds(struct r8169_led_classdev *leds);
+diff --git a/drivers/net/ethernet/realtek/r8169_leds.c b/drivers/net/ethernet/realtek/r8169_leds.c
+index 007d077edcad7..1c97f3cca22a1 100644
+--- a/drivers/net/ethernet/realtek/r8169_leds.c
++++ b/drivers/net/ethernet/realtek/r8169_leds.c
+@@ -138,20 +138,31 @@ static void rtl8168_setup_ldev(struct r8169_led_classdev *ldev,
+ led_cdev->hw_control_get_device = r8169_led_hw_control_get_device;
+
+ /* ignore errors */
+- devm_led_classdev_register(&ndev->dev, led_cdev);
++ led_classdev_register(&ndev->dev, led_cdev);
+ }
+
+-void rtl8168_init_leds(struct net_device *ndev)
++struct r8169_led_classdev *rtl8168_init_leds(struct net_device *ndev)
+ {
+- /* bind resource mgmt to netdev */
+- struct device *dev = &ndev->dev;
+ struct r8169_led_classdev *leds;
+ int i;
+
+- leds = devm_kcalloc(dev, RTL8168_NUM_LEDS, sizeof(*leds), GFP_KERNEL);
++ leds = kcalloc(RTL8168_NUM_LEDS + 1, sizeof(*leds), GFP_KERNEL);
+ if (!leds)
+- return;
++ return NULL;
+
+ for (i = 0; i < RTL8168_NUM_LEDS; i++)
+ rtl8168_setup_ldev(leds + i, ndev, i);
++
++ return leds;
++}
++
++void r8169_remove_leds(struct r8169_led_classdev *leds)
++{
++ if (!leds)
++ return;
++
++ for (struct r8169_led_classdev *l = leds; l->ndev; l++)
++ led_classdev_unregister(&l->led);
++
++ kfree(leds);
+ }
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index 4b6c28576a518..32b73f3988e8c 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -634,6 +634,8 @@ struct rtl8169_private {
+ const char *fw_name;
+ struct rtl_fw *rtl_fw;
+
++ struct r8169_led_classdev *leds;
++
+ u32 ocp_base;
+ };
+
+@@ -4930,6 +4932,9 @@ static void rtl_remove_one(struct pci_dev *pdev)
+
+ cancel_work_sync(&tp->wk.work);
+
++ if (IS_ENABLED(CONFIG_R8169_LEDS))
++ r8169_remove_leds(tp->leds);
++
+ unregister_netdev(tp->dev);
+
+ if (tp->dash_type != RTL_DASH_NONE)
+@@ -5391,7 +5396,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ if (IS_ENABLED(CONFIG_R8169_LEDS) &&
+ tp->mac_version > RTL_GIGA_MAC_VER_06 &&
+ tp->mac_version < RTL_GIGA_MAC_VER_61)
+- rtl8168_init_leds(dev);
++ tp->leds = rtl8168_init_leds(dev);
+
+ netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n",
+ rtl_chip_infos[chipset].name, dev->dev_addr, xid, tp->irq);
+diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
+index e0f8276cffedd..fd59155a70e1f 100644
+--- a/drivers/net/ethernet/renesas/ravb.h
++++ b/drivers/net/ethernet/renesas/ravb.h
+@@ -1060,8 +1060,10 @@ struct ravb_private {
+ struct ravb_desc *desc_bat;
+ dma_addr_t rx_desc_dma[NUM_RX_QUEUE];
+ dma_addr_t tx_desc_dma[NUM_TX_QUEUE];
+- struct ravb_rx_desc *gbeth_rx_ring;
+- struct ravb_ex_rx_desc *rx_ring[NUM_RX_QUEUE];
++ union {
++ struct ravb_rx_desc *desc;
++ struct ravb_ex_rx_desc *ex_desc;
++ } rx_ring[NUM_RX_QUEUE];
+ struct ravb_tx_desc *tx_ring[NUM_TX_QUEUE];
+ void *tx_align[NUM_TX_QUEUE];
+ struct sk_buff *rx_1st_skb;
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index 1bdf0abb256cf..853c2a0d4e259 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -250,11 +250,11 @@ static void ravb_rx_ring_free_gbeth(struct net_device *ndev, int q)
+ unsigned int ring_size;
+ unsigned int i;
+
+- if (!priv->gbeth_rx_ring)
++ if (!priv->rx_ring[q].desc)
+ return;
+
+ for (i = 0; i < priv->num_rx_ring[q]; i++) {
+- struct ravb_rx_desc *desc = &priv->gbeth_rx_ring[i];
++ struct ravb_rx_desc *desc = &priv->rx_ring[q].desc[i];
+
+ if (!dma_mapping_error(ndev->dev.parent,
+ le32_to_cpu(desc->dptr)))
+@@ -264,9 +264,9 @@ static void ravb_rx_ring_free_gbeth(struct net_device *ndev, int q)
+ DMA_FROM_DEVICE);
+ }
+ ring_size = sizeof(struct ravb_rx_desc) * (priv->num_rx_ring[q] + 1);
+- dma_free_coherent(ndev->dev.parent, ring_size, priv->gbeth_rx_ring,
++ dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q].desc,
+ priv->rx_desc_dma[q]);
+- priv->gbeth_rx_ring = NULL;
++ priv->rx_ring[q].desc = NULL;
+ }
+
+ static void ravb_rx_ring_free_rcar(struct net_device *ndev, int q)
+@@ -275,11 +275,11 @@ static void ravb_rx_ring_free_rcar(struct net_device *ndev, int q)
+ unsigned int ring_size;
+ unsigned int i;
+
+- if (!priv->rx_ring[q])
++ if (!priv->rx_ring[q].ex_desc)
+ return;
+
+ for (i = 0; i < priv->num_rx_ring[q]; i++) {
+- struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i];
++ struct ravb_ex_rx_desc *desc = &priv->rx_ring[q].ex_desc[i];
+
+ if (!dma_mapping_error(ndev->dev.parent,
+ le32_to_cpu(desc->dptr)))
+@@ -290,9 +290,9 @@ static void ravb_rx_ring_free_rcar(struct net_device *ndev, int q)
+ }
+ ring_size = sizeof(struct ravb_ex_rx_desc) *
+ (priv->num_rx_ring[q] + 1);
+- dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q],
++ dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q].ex_desc,
+ priv->rx_desc_dma[q]);
+- priv->rx_ring[q] = NULL;
++ priv->rx_ring[q].ex_desc = NULL;
+ }
+
+ /* Free skb's and DMA buffers for Ethernet AVB */
+@@ -344,11 +344,11 @@ static void ravb_rx_ring_format_gbeth(struct net_device *ndev, int q)
+ unsigned int i;
+
+ rx_ring_size = sizeof(*rx_desc) * priv->num_rx_ring[q];
+- memset(priv->gbeth_rx_ring, 0, rx_ring_size);
++ memset(priv->rx_ring[q].desc, 0, rx_ring_size);
+ /* Build RX ring buffer */
+ for (i = 0; i < priv->num_rx_ring[q]; i++) {
+ /* RX descriptor */
+- rx_desc = &priv->gbeth_rx_ring[i];
++ rx_desc = &priv->rx_ring[q].desc[i];
+ rx_desc->ds_cc = cpu_to_le16(GBETH_RX_DESC_DATA_SIZE);
+ dma_addr = dma_map_single(ndev->dev.parent, priv->rx_skb[q][i]->data,
+ GBETH_RX_BUFF_MAX,
+@@ -361,7 +361,7 @@ static void ravb_rx_ring_format_gbeth(struct net_device *ndev, int q)
+ rx_desc->dptr = cpu_to_le32(dma_addr);
+ rx_desc->die_dt = DT_FEMPTY;
+ }
+- rx_desc = &priv->gbeth_rx_ring[i];
++ rx_desc = &priv->rx_ring[q].desc[i];
+ rx_desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]);
+ rx_desc->die_dt = DT_LINKFIX; /* type */
+ }
+@@ -374,11 +374,11 @@ static void ravb_rx_ring_format_rcar(struct net_device *ndev, int q)
+ dma_addr_t dma_addr;
+ unsigned int i;
+
+- memset(priv->rx_ring[q], 0, rx_ring_size);
++ memset(priv->rx_ring[q].ex_desc, 0, rx_ring_size);
+ /* Build RX ring buffer */
+ for (i = 0; i < priv->num_rx_ring[q]; i++) {
+ /* RX descriptor */
+- rx_desc = &priv->rx_ring[q][i];
++ rx_desc = &priv->rx_ring[q].ex_desc[i];
+ rx_desc->ds_cc = cpu_to_le16(RX_BUF_SZ);
+ dma_addr = dma_map_single(ndev->dev.parent, priv->rx_skb[q][i]->data,
+ RX_BUF_SZ,
+@@ -391,7 +391,7 @@ static void ravb_rx_ring_format_rcar(struct net_device *ndev, int q)
+ rx_desc->dptr = cpu_to_le32(dma_addr);
+ rx_desc->die_dt = DT_FEMPTY;
+ }
+- rx_desc = &priv->rx_ring[q][i];
++ rx_desc = &priv->rx_ring[q].ex_desc[i];
+ rx_desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]);
+ rx_desc->die_dt = DT_LINKFIX; /* type */
+ }
+@@ -446,10 +446,10 @@ static void *ravb_alloc_rx_desc_gbeth(struct net_device *ndev, int q)
+
+ ring_size = sizeof(struct ravb_rx_desc) * (priv->num_rx_ring[q] + 1);
+
+- priv->gbeth_rx_ring = dma_alloc_coherent(ndev->dev.parent, ring_size,
+- &priv->rx_desc_dma[q],
+- GFP_KERNEL);
+- return priv->gbeth_rx_ring;
++ priv->rx_ring[q].desc = dma_alloc_coherent(ndev->dev.parent, ring_size,
++ &priv->rx_desc_dma[q],
++ GFP_KERNEL);
++ return priv->rx_ring[q].desc;
+ }
+
+ static void *ravb_alloc_rx_desc_rcar(struct net_device *ndev, int q)
+@@ -459,10 +459,11 @@ static void *ravb_alloc_rx_desc_rcar(struct net_device *ndev, int q)
+
+ ring_size = sizeof(struct ravb_ex_rx_desc) * (priv->num_rx_ring[q] + 1);
+
+- priv->rx_ring[q] = dma_alloc_coherent(ndev->dev.parent, ring_size,
+- &priv->rx_desc_dma[q],
+- GFP_KERNEL);
+- return priv->rx_ring[q];
++ priv->rx_ring[q].ex_desc = dma_alloc_coherent(ndev->dev.parent,
++ ring_size,
++ &priv->rx_desc_dma[q],
++ GFP_KERNEL);
++ return priv->rx_ring[q].ex_desc;
+ }
+
+ /* Init skb and descriptor buffer for Ethernet AVB */
+@@ -780,12 +781,15 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
+ int limit;
+ int i;
+
+- entry = priv->cur_rx[q] % priv->num_rx_ring[q];
+ limit = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q];
+ stats = &priv->stats[q];
+
+- desc = &priv->gbeth_rx_ring[entry];
+- for (i = 0; i < limit && rx_packets < *quota && desc->die_dt != DT_FEMPTY; i++) {
++ for (i = 0; i < limit; i++, priv->cur_rx[q]++) {
++ entry = priv->cur_rx[q] % priv->num_rx_ring[q];
++ desc = &priv->rx_ring[q].desc[entry];
++ if (rx_packets == *quota || desc->die_dt == DT_FEMPTY)
++ break;
++
+ /* Descriptor type must be checked before all other reads */
+ dma_rmb();
+ desc_status = desc->msc;
+@@ -849,15 +853,12 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
+ break;
+ }
+ }
+-
+- entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q];
+- desc = &priv->gbeth_rx_ring[entry];
+ }
+
+ /* Refill the RX ring buffers. */
+ for (; priv->cur_rx[q] - priv->dirty_rx[q] > 0; priv->dirty_rx[q]++) {
+ entry = priv->dirty_rx[q] % priv->num_rx_ring[q];
+- desc = &priv->gbeth_rx_ring[entry];
++ desc = &priv->rx_ring[q].desc[entry];
+ desc->ds_cc = cpu_to_le16(GBETH_RX_DESC_DATA_SIZE);
+
+ if (!priv->rx_skb[q][entry]) {
+@@ -893,30 +894,29 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q)
+ {
+ struct ravb_private *priv = netdev_priv(ndev);
+ const struct ravb_hw_info *info = priv->info;
+- int entry = priv->cur_rx[q] % priv->num_rx_ring[q];
+- int boguscnt = (priv->dirty_rx[q] + priv->num_rx_ring[q]) -
+- priv->cur_rx[q];
+ struct net_device_stats *stats = &priv->stats[q];
+ struct ravb_ex_rx_desc *desc;
++ unsigned int limit, i;
+ struct sk_buff *skb;
+ dma_addr_t dma_addr;
+ struct timespec64 ts;
++ int rx_packets = 0;
+ u8 desc_status;
+ u16 pkt_len;
+- int limit;
++ int entry;
++
++ limit = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q];
++ for (i = 0; i < limit; i++, priv->cur_rx[q]++) {
++ entry = priv->cur_rx[q] % priv->num_rx_ring[q];
++ desc = &priv->rx_ring[q].ex_desc[entry];
++ if (rx_packets == *quota || desc->die_dt == DT_FEMPTY)
++ break;
+
+- boguscnt = min(boguscnt, *quota);
+- limit = boguscnt;
+- desc = &priv->rx_ring[q][entry];
+- while (desc->die_dt != DT_FEMPTY) {
+ /* Descriptor type must be checked before all other reads */
+ dma_rmb();
+ desc_status = desc->msc;
+ pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS;
+
+- if (--boguscnt < 0)
+- break;
+-
+ /* We use 0-byte descriptors to mark the DMA mapping errors */
+ if (!pkt_len)
+ continue;
+@@ -962,18 +962,15 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q)
+ if (ndev->features & NETIF_F_RXCSUM)
+ ravb_rx_csum(skb);
+ napi_gro_receive(&priv->napi[q], skb);
+- stats->rx_packets++;
++ rx_packets++;
+ stats->rx_bytes += pkt_len;
+ }
+-
+- entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q];
+- desc = &priv->rx_ring[q][entry];
+ }
+
+ /* Refill the RX ring buffers. */
+ for (; priv->cur_rx[q] - priv->dirty_rx[q] > 0; priv->dirty_rx[q]++) {
+ entry = priv->dirty_rx[q] % priv->num_rx_ring[q];
+- desc = &priv->rx_ring[q][entry];
++ desc = &priv->rx_ring[q].ex_desc[entry];
+ desc->ds_cc = cpu_to_le16(RX_BUF_SZ);
+
+ if (!priv->rx_skb[q][entry]) {
+@@ -998,9 +995,9 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q)
+ desc->die_dt = DT_FEMPTY;
+ }
+
+- *quota -= limit - (++boguscnt);
+-
+- return boguscnt <= 0;
++ stats->rx_packets += rx_packets;
++ *quota -= rx_packets;
++ return *quota == 0;
+ }
+
+ /* Packet receive function for Ethernet AVB */
+diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
+index 5ba606a596e77..5a1d46dcd5de0 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/common.h
++++ b/drivers/net/ethernet/stmicro/stmmac/common.h
+@@ -550,6 +550,7 @@ extern const struct stmmac_hwtimestamp stmmac_ptp;
+ extern const struct stmmac_mode_ops dwmac4_ring_mode_ops;
+
+ struct mac_link {
++ u32 caps;
+ u32 speed_mask;
+ u32 speed10;
+ u32 speed100;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+index b21d99faa2d04..e1b761dcfa1dd 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
+@@ -1096,6 +1096,8 @@ static struct mac_device_info *sun8i_dwmac_setup(void *ppriv)
+
+ priv->dev->priv_flags |= IFF_UNICAST_FLT;
+
++ mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
++ MAC_10 | MAC_100 | MAC_1000;
+ /* The loopback bit seems to be re-set when link change
+ * Simply mask it each time
+ * Speed 10/100/1000 are set in BIT(2)/BIT(3)
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+index 3927609abc441..8555299443f4e 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
+@@ -539,6 +539,8 @@ int dwmac1000_setup(struct stmmac_priv *priv)
+ if (mac->multicast_filter_bins)
+ mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
+
++ mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
++ MAC_10 | MAC_100 | MAC_1000;
+ mac->link.duplex = GMAC_CONTROL_DM;
+ mac->link.speed10 = GMAC_CONTROL_PS;
+ mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+index a6e8d7bd95886..7667d103cd0eb 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c
+@@ -175,6 +175,8 @@ int dwmac100_setup(struct stmmac_priv *priv)
+ dev_info(priv->device, "\tDWMAC100\n");
+
+ mac->pcsr = priv->ioaddr;
++ mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
++ MAC_10 | MAC_100;
+ mac->link.duplex = MAC_CONTROL_F;
+ mac->link.speed10 = 0;
+ mac->link.speed100 = 0;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+index cef25efbdff99..a38226d7cc6a9 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+@@ -70,7 +70,10 @@ static void dwmac4_core_init(struct mac_device_info *hw,
+
+ static void dwmac4_phylink_get_caps(struct stmmac_priv *priv)
+ {
+- priv->phylink_config.mac_capabilities |= MAC_2500FD;
++ if (priv->plat->tx_queues_to_use > 1)
++ priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD | MAC_1000HD);
++ else
++ priv->hw->link.caps |= (MAC_10HD | MAC_100HD | MAC_1000HD);
+ }
+
+ static void dwmac4_rx_queue_enable(struct mac_device_info *hw,
+@@ -1378,6 +1381,8 @@ int dwmac4_setup(struct stmmac_priv *priv)
+ if (mac->multicast_filter_bins)
+ mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
+
++ mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
++ MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
+ mac->link.duplex = GMAC_CONFIG_DM;
+ mac->link.speed10 = GMAC_CONFIG_PS;
+ mac->link.speed100 = GMAC_CONFIG_FES | GMAC_CONFIG_PS;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+index e841e312077ef..f8e7775bb6336 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+@@ -47,14 +47,6 @@ static void dwxgmac2_core_init(struct mac_device_info *hw,
+ writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN);
+ }
+
+-static void xgmac_phylink_get_caps(struct stmmac_priv *priv)
+-{
+- priv->phylink_config.mac_capabilities |= MAC_2500FD | MAC_5000FD |
+- MAC_10000FD | MAC_25000FD |
+- MAC_40000FD | MAC_50000FD |
+- MAC_100000FD;
+-}
+-
+ static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable)
+ {
+ u32 tx = readl(ioaddr + XGMAC_TX_CONFIG);
+@@ -1540,7 +1532,6 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *
+
+ const struct stmmac_ops dwxgmac210_ops = {
+ .core_init = dwxgmac2_core_init,
+- .phylink_get_caps = xgmac_phylink_get_caps,
+ .set_mac = dwxgmac2_set_mac,
+ .rx_ipc = dwxgmac2_rx_ipc,
+ .rx_queue_enable = dwxgmac2_rx_queue_enable,
+@@ -1601,7 +1592,6 @@ static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
+
+ const struct stmmac_ops dwxlgmac2_ops = {
+ .core_init = dwxgmac2_core_init,
+- .phylink_get_caps = xgmac_phylink_get_caps,
+ .set_mac = dwxgmac2_set_mac,
+ .rx_ipc = dwxgmac2_rx_ipc,
+ .rx_queue_enable = dwxlgmac2_rx_queue_enable,
+@@ -1661,6 +1651,9 @@ int dwxgmac2_setup(struct stmmac_priv *priv)
+ if (mac->multicast_filter_bins)
+ mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
+
++ mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
++ MAC_1000FD | MAC_2500FD | MAC_5000FD |
++ MAC_10000FD;
+ mac->link.duplex = 0;
+ mac->link.speed10 = XGMAC_CONFIG_SS_10_MII;
+ mac->link.speed100 = XGMAC_CONFIG_SS_100_MII;
+@@ -1698,6 +1691,11 @@ int dwxlgmac2_setup(struct stmmac_priv *priv)
+ if (mac->multicast_filter_bins)
+ mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
+
++ mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
++ MAC_1000FD | MAC_2500FD | MAC_5000FD |
++ MAC_10000FD | MAC_25000FD |
++ MAC_40000FD | MAC_50000FD |
++ MAC_100000FD;
+ mac->link.duplex = 0;
+ mac->link.speed1000 = XLGMAC_CONFIG_SS_1000;
+ mac->link.speed2500 = XLGMAC_CONFIG_SS_2500;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 7c6aef033a456..83b732c30c1bb 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -1198,17 +1198,6 @@ static int stmmac_init_phy(struct net_device *dev)
+ return ret;
+ }
+
+-static void stmmac_set_half_duplex(struct stmmac_priv *priv)
+-{
+- /* Half-Duplex can only work with single tx queue */
+- if (priv->plat->tx_queues_to_use > 1)
+- priv->phylink_config.mac_capabilities &=
+- ~(MAC_10HD | MAC_100HD | MAC_1000HD);
+- else
+- priv->phylink_config.mac_capabilities |=
+- (MAC_10HD | MAC_100HD | MAC_1000HD);
+-}
+-
+ static int stmmac_phy_setup(struct stmmac_priv *priv)
+ {
+ struct stmmac_mdio_bus_data *mdio_bus_data;
+@@ -1236,15 +1225,11 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
+ xpcs_get_interfaces(priv->hw->xpcs,
+ priv->phylink_config.supported_interfaces);
+
+- priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+- MAC_10FD | MAC_100FD |
+- MAC_1000FD;
+-
+- stmmac_set_half_duplex(priv);
+-
+ /* Get the MAC specific capabilities */
+ stmmac_mac_phylink_get_caps(priv);
+
++ priv->phylink_config.mac_capabilities = priv->hw->link.caps;
++
+ max_speed = priv->plat->max_speed;
+ if (max_speed)
+ phylink_limit_mac_speed(&priv->phylink_config, max_speed);
+@@ -7286,6 +7271,7 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
+ {
+ struct stmmac_priv *priv = netdev_priv(dev);
+ int ret = 0, i;
++ int max_speed;
+
+ if (netif_running(dev))
+ stmmac_release(dev);
+@@ -7299,7 +7285,14 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt)
+ priv->rss.table[i] = ethtool_rxfh_indir_default(i,
+ rx_cnt);
+
+- stmmac_set_half_duplex(priv);
++ stmmac_mac_phylink_get_caps(priv);
++
++ priv->phylink_config.mac_capabilities = priv->hw->link.caps;
++
++ max_speed = priv->plat->max_speed;
++ if (max_speed)
++ phylink_limit_mac_speed(&priv->phylink_config, max_speed);
++
+ stmmac_napi_add(dev);
+
+ if (netif_running(dev))
+diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+index 2939a21ca74f3..1d00e21808c1c 100644
+--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
++++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+@@ -2793,6 +2793,8 @@ static void am65_cpsw_unregister_devlink(struct am65_cpsw_common *common)
+
+ static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common)
+ {
++ struct am65_cpsw_rx_chn *rx_chan = &common->rx_chns;
++ struct am65_cpsw_tx_chn *tx_chan = common->tx_chns;
+ struct device *dev = common->dev;
+ struct am65_cpsw_port *port;
+ int ret = 0, i;
+@@ -2805,6 +2807,22 @@ static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common)
+ if (ret)
+ return ret;
+
++ /* The DMA Channels are not guaranteed to be in a clean state.
++ * Reset and disable them to ensure that they are back to the
++ * clean state and ready to be used.
++ */
++ for (i = 0; i < common->tx_ch_num; i++) {
++ k3_udma_glue_reset_tx_chn(tx_chan[i].tx_chn, &tx_chan[i],
++ am65_cpsw_nuss_tx_cleanup);
++ k3_udma_glue_disable_tx_chn(tx_chan[i].tx_chn);
++ }
++
++ for (i = 0; i < AM65_CPSW_MAX_RX_FLOWS; i++)
++ k3_udma_glue_reset_rx_chn(rx_chan->rx_chn, i, rx_chan,
++ am65_cpsw_nuss_rx_cleanup, !!i);
++
++ k3_udma_glue_disable_rx_chn(rx_chan->rx_chn);
++
+ ret = am65_cpsw_nuss_register_devlink(common);
+ if (ret)
+ return ret;
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 8f95a562b8d0c..86515f0c2b6c1 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2132,14 +2132,16 @@ static ssize_t tun_put_user(struct tun_struct *tun,
+ tun_is_little_endian(tun), true,
+ vlan_hlen)) {
+ struct skb_shared_info *sinfo = skb_shinfo(skb);
+- pr_err("unexpected GSO type: "
+- "0x%x, gso_size %d, hdr_len %d\n",
+- sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size),
+- tun16_to_cpu(tun, gso.hdr_len));
+- print_hex_dump(KERN_ERR, "tun: ",
+- DUMP_PREFIX_NONE,
+- 16, 1, skb->head,
+- min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true);
++
++ if (net_ratelimit()) {
++ netdev_err(tun->dev, "unexpected GSO type: 0x%x, gso_size %d, hdr_len %d\n",
++ sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size),
++ tun16_to_cpu(tun, gso.hdr_len));
++ print_hex_dump(KERN_ERR, "tun: ",
++ DUMP_PREFIX_NONE,
++ 16, 1, skb->head,
++ min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true);
++ }
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
+diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
+index e0e9b4c53cb02..3078511f76083 100644
+--- a/drivers/net/usb/ax88179_178a.c
++++ b/drivers/net/usb/ax88179_178a.c
+@@ -1317,6 +1317,8 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf)
+
+ netif_set_tso_max_size(dev->net, 16384);
+
++ ax88179_reset(dev);
++
+ return 0;
+ }
+
+@@ -1695,7 +1697,6 @@ static const struct driver_info ax88179_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1708,7 +1709,6 @@ static const struct driver_info ax88178a_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+diff --git a/drivers/platform/x86/amd/pmc/pmc-quirks.c b/drivers/platform/x86/amd/pmc/pmc-quirks.c
+index b456370166b6b..b4f49720c87f6 100644
+--- a/drivers/platform/x86/amd/pmc/pmc-quirks.c
++++ b/drivers/platform/x86/amd/pmc/pmc-quirks.c
+@@ -208,6 +208,15 @@ static const struct dmi_system_id fwbug_list[] = {
+ DMI_MATCH(DMI_BIOS_VERSION, "03.03"),
+ }
+ },
++ {
++ .ident = "Framework Laptop 13 (Phoenix)",
++ .driver_data = &quirk_spurious_8042,
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"),
++ DMI_MATCH(DMI_BIOS_VERSION, "03.05"),
++ }
++ },
+ {}
+ };
+
+diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
+index 0cfb179e1bcb6..34b2567b8df49 100644
+--- a/drivers/s390/cio/device.c
++++ b/drivers/s390/cio/device.c
+@@ -363,10 +363,8 @@ int ccw_device_set_online(struct ccw_device *cdev)
+
+ spin_lock_irq(cdev->ccwlock);
+ ret = ccw_device_online(cdev);
+- spin_unlock_irq(cdev->ccwlock);
+- if (ret == 0)
+- wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
+- else {
++ if (ret) {
++ spin_unlock_irq(cdev->ccwlock);
+ CIO_MSG_EVENT(0, "ccw_device_online returned %d, "
+ "device 0.%x.%04x\n",
+ ret, cdev->private->dev_id.ssid,
+@@ -375,7 +373,12 @@ int ccw_device_set_online(struct ccw_device *cdev)
+ put_device(&cdev->dev);
+ return ret;
+ }
+- spin_lock_irq(cdev->ccwlock);
++ /* Wait until a final state is reached */
++ while (!dev_fsm_final_state(cdev)) {
++ spin_unlock_irq(cdev->ccwlock);
++ wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
++ spin_lock_irq(cdev->ccwlock);
++ }
+ /* Check if online processing was successful */
+ if ((cdev->private->state != DEV_STATE_ONLINE) &&
+ (cdev->private->state != DEV_STATE_W4SENSE)) {
+diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
+index 9cde55730b65a..ebcb535809882 100644
+--- a/drivers/s390/cio/qdio_main.c
++++ b/drivers/s390/cio/qdio_main.c
+@@ -722,8 +722,8 @@ static void qdio_handle_activate_check(struct qdio_irq *irq_ptr,
+ lgr_info_log();
+ }
+
+-static void qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat,
+- int dstat)
++static int qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat,
++ int dstat, int dcc)
+ {
+ DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq");
+
+@@ -731,15 +731,18 @@ static void qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat,
+ goto error;
+ if (dstat & ~(DEV_STAT_DEV_END | DEV_STAT_CHN_END))
+ goto error;
++ if (dcc == 1)
++ return -EAGAIN;
+ if (!(dstat & DEV_STAT_DEV_END))
+ goto error;
+ qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ESTABLISHED);
+- return;
++ return 0;
+
+ error:
+ DBF_ERROR("%4x EQ:error", irq_ptr->schid.sch_no);
+ DBF_ERROR("ds: %2x cs:%2x", dstat, cstat);
+ qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
++ return -EIO;
+ }
+
+ /* qdio interrupt handler */
+@@ -748,7 +751,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
+ {
+ struct qdio_irq *irq_ptr = cdev->private->qdio_data;
+ struct subchannel_id schid;
+- int cstat, dstat;
++ int cstat, dstat, rc, dcc;
+
+ if (!intparm || !irq_ptr) {
+ ccw_device_get_schid(cdev, &schid);
+@@ -768,10 +771,12 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
+ qdio_irq_check_sense(irq_ptr, irb);
+ cstat = irb->scsw.cmd.cstat;
+ dstat = irb->scsw.cmd.dstat;
++ dcc = scsw_cmd_is_valid_cc(&irb->scsw) ? irb->scsw.cmd.cc : 0;
++ rc = 0;
+
+ switch (irq_ptr->state) {
+ case QDIO_IRQ_STATE_INACTIVE:
+- qdio_establish_handle_irq(irq_ptr, cstat, dstat);
++ rc = qdio_establish_handle_irq(irq_ptr, cstat, dstat, dcc);
+ break;
+ case QDIO_IRQ_STATE_CLEANUP:
+ qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE);
+@@ -785,12 +790,25 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
+ if (cstat || dstat)
+ qdio_handle_activate_check(irq_ptr, intparm, cstat,
+ dstat);
++ else if (dcc == 1)
++ rc = -EAGAIN;
+ break;
+ case QDIO_IRQ_STATE_STOPPED:
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ }
++
++ if (rc == -EAGAIN) {
++ DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qint retry");
++ rc = ccw_device_start(cdev, irq_ptr->ccw, intparm, 0, 0);
++ if (!rc)
++ return;
++ DBF_ERROR("%4x RETRY ERR", irq_ptr->schid.sch_no);
++ DBF_ERROR("rc:%4x", rc);
++ qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR);
++ }
++
+ wake_up(&cdev->private->wait_q);
+ }
+
+diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
+index 2c8e964425dc3..43778b088ffac 100644
+--- a/drivers/s390/net/ism_drv.c
++++ b/drivers/s390/net/ism_drv.c
+@@ -292,13 +292,16 @@ static int ism_read_local_gid(struct ism_dev *ism)
+ static void ism_free_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
+ {
+ clear_bit(dmb->sba_idx, ism->sba_bitmap);
+- dma_free_coherent(&ism->pdev->dev, dmb->dmb_len,
+- dmb->cpu_addr, dmb->dma_addr);
++ dma_unmap_page(&ism->pdev->dev, dmb->dma_addr, dmb->dmb_len,
++ DMA_FROM_DEVICE);
++ folio_put(virt_to_folio(dmb->cpu_addr));
+ }
+
+ static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
+ {
++ struct folio *folio;
+ unsigned long bit;
++ int rc;
+
+ if (PAGE_ALIGN(dmb->dmb_len) > dma_get_max_seg_size(&ism->pdev->dev))
+ return -EINVAL;
+@@ -315,14 +318,30 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
+ test_and_set_bit(dmb->sba_idx, ism->sba_bitmap))
+ return -EINVAL;
+
+- dmb->cpu_addr = dma_alloc_coherent(&ism->pdev->dev, dmb->dmb_len,
+- &dmb->dma_addr,
+- GFP_KERNEL | __GFP_NOWARN |
+- __GFP_NOMEMALLOC | __GFP_NORETRY);
+- if (!dmb->cpu_addr)
+- clear_bit(dmb->sba_idx, ism->sba_bitmap);
++ folio = folio_alloc(GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC |
++ __GFP_NORETRY, get_order(dmb->dmb_len));
+
+- return dmb->cpu_addr ? 0 : -ENOMEM;
++ if (!folio) {
++ rc = -ENOMEM;
++ goto out_bit;
++ }
++
++ dmb->cpu_addr = folio_address(folio);
++ dmb->dma_addr = dma_map_page(&ism->pdev->dev,
++ virt_to_page(dmb->cpu_addr), 0,
++ dmb->dmb_len, DMA_FROM_DEVICE);
++ if (dma_mapping_error(&ism->pdev->dev, dmb->dma_addr)) {
++ rc = -ENOMEM;
++ goto out_free;
++ }
++
++ return 0;
++
++out_free:
++ kfree(dmb->cpu_addr);
++out_bit:
++ clear_bit(dmb->sba_idx, ism->sba_bitmap);
++ return rc;
+ }
+
+ int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb,
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index df5ac03d5d6c2..189dfeb378202 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -543,10 +543,9 @@ static bool scsi_end_request(struct request *req, blk_status_t error,
+ if (blk_queue_add_random(q))
+ add_disk_randomness(req->q->disk);
+
+- if (!blk_rq_is_passthrough(req)) {
+- WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED));
+- cmd->flags &= ~SCMD_INITIALIZED;
+- }
++ WARN_ON_ONCE(!blk_rq_is_passthrough(req) &&
++ !(cmd->flags & SCMD_INITIALIZED));
++ cmd->flags = 0;
+
+ /*
+ * Calling rcu_barrier() is not necessary here because the
+diff --git a/drivers/thermal/thermal_debugfs.c b/drivers/thermal/thermal_debugfs.c
+index c617e8b9f0ddf..d78d54ae2605e 100644
+--- a/drivers/thermal/thermal_debugfs.c
++++ b/drivers/thermal/thermal_debugfs.c
+@@ -616,6 +616,7 @@ void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
+ tze->trip_stats[trip_id].timestamp = now;
+ tze->trip_stats[trip_id].max = max(tze->trip_stats[trip_id].max, temperature);
+ tze->trip_stats[trip_id].min = min(tze->trip_stats[trip_id].min, temperature);
++ tze->trip_stats[trip_id].count++;
+ tze->trip_stats[trip_id].avg = tze->trip_stats[trip_id].avg +
+ (temperature - tze->trip_stats[trip_id].avg) /
+ tze->trip_stats[trip_id].count;
+diff --git a/drivers/thunderbolt/domain.c b/drivers/thunderbolt/domain.c
+index 9fb1a64f3300b..df0d845e069ac 100644
+--- a/drivers/thunderbolt/domain.c
++++ b/drivers/thunderbolt/domain.c
+@@ -423,6 +423,7 @@ struct tb *tb_domain_alloc(struct tb_nhi *nhi, int timeout_msec, size_t privsize
+ /**
+ * tb_domain_add() - Add domain to the system
+ * @tb: Domain to add
++ * @reset: Issue reset to the host router
+ *
+ * Starts the domain and adds it to the system. Hotplugging devices will
+ * work after this has been returned successfully. In order to remove
+@@ -431,7 +432,7 @@ struct tb *tb_domain_alloc(struct tb_nhi *nhi, int timeout_msec, size_t privsize
+ *
+ * Return: %0 in case of success and negative errno in case of error
+ */
+-int tb_domain_add(struct tb *tb)
++int tb_domain_add(struct tb *tb, bool reset)
+ {
+ int ret;
+
+@@ -460,7 +461,7 @@ int tb_domain_add(struct tb *tb)
+
+ /* Start the domain */
+ if (tb->cm_ops->start) {
+- ret = tb->cm_ops->start(tb);
++ ret = tb->cm_ops->start(tb, reset);
+ if (ret)
+ goto err_domain_del;
+ }
+diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c
+index 56790d50f9e32..baf10d099c778 100644
+--- a/drivers/thunderbolt/icm.c
++++ b/drivers/thunderbolt/icm.c
+@@ -2144,7 +2144,7 @@ static int icm_runtime_resume(struct tb *tb)
+ return 0;
+ }
+
+-static int icm_start(struct tb *tb)
++static int icm_start(struct tb *tb, bool not_used)
+ {
+ struct icm *icm = tb_priv(tb);
+ int ret;
+diff --git a/drivers/thunderbolt/lc.c b/drivers/thunderbolt/lc.c
+index 633970fbe9b05..63cb4b6afb718 100644
+--- a/drivers/thunderbolt/lc.c
++++ b/drivers/thunderbolt/lc.c
+@@ -6,6 +6,8 @@
+ * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
+ */
+
++#include <linux/delay.h>
++
+ #include "tb.h"
+
+ /**
+@@ -45,6 +47,49 @@ static int find_port_lc_cap(struct tb_port *port)
+ return sw->cap_lc + start + phys * size;
+ }
+
++/**
++ * tb_lc_reset_port() - Trigger downstream port reset through LC
++ * @port: Port that is reset
++ *
++ * Triggers downstream port reset through link controller registers.
++ * Returns %0 in case of success negative errno otherwise. Only supports
++ * non-USB4 routers with link controller (that's Thunderbolt 2 and
++ * Thunderbolt 3).
++ */
++int tb_lc_reset_port(struct tb_port *port)
++{
++ struct tb_switch *sw = port->sw;
++ int cap, ret;
++ u32 mode;
++
++ if (sw->generation < 2)
++ return -EINVAL;
++
++ cap = find_port_lc_cap(port);
++ if (cap < 0)
++ return cap;
++
++ ret = tb_sw_read(sw, &mode, TB_CFG_SWITCH, cap + TB_LC_PORT_MODE, 1);
++ if (ret)
++ return ret;
++
++ mode |= TB_LC_PORT_MODE_DPR;
++
++ ret = tb_sw_write(sw, &mode, TB_CFG_SWITCH, cap + TB_LC_PORT_MODE, 1);
++ if (ret)
++ return ret;
++
++ fsleep(10000);
++
++ ret = tb_sw_read(sw, &mode, TB_CFG_SWITCH, cap + TB_LC_PORT_MODE, 1);
++ if (ret)
++ return ret;
++
++ mode &= ~TB_LC_PORT_MODE_DPR;
++
++ return tb_sw_write(sw, &mode, TB_CFG_SWITCH, cap + TB_LC_PORT_MODE, 1);
++}
++
+ static int tb_lc_set_port_configured(struct tb_port *port, bool configured)
+ {
+ bool upstream = tb_is_upstream_port(port);
+diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
+index fb4f46e51753a..b22023fae60de 100644
+--- a/drivers/thunderbolt/nhi.c
++++ b/drivers/thunderbolt/nhi.c
+@@ -1221,7 +1221,7 @@ static void nhi_check_iommu(struct tb_nhi *nhi)
+ str_enabled_disabled(port_ok));
+ }
+
+-static void nhi_reset(struct tb_nhi *nhi)
++static bool nhi_reset(struct tb_nhi *nhi)
+ {
+ ktime_t timeout;
+ u32 val;
+@@ -1229,11 +1229,11 @@ static void nhi_reset(struct tb_nhi *nhi)
+ val = ioread32(nhi->iobase + REG_CAPS);
+ /* Reset only v2 and later routers */
+ if (FIELD_GET(REG_CAPS_VERSION_MASK, val) < REG_CAPS_VERSION_2)
+- return;
++ return false;
+
+ if (!host_reset) {
+ dev_dbg(&nhi->pdev->dev, "skipping host router reset\n");
+- return;
++ return false;
+ }
+
+ iowrite32(REG_RESET_HRR, nhi->iobase + REG_RESET);
+@@ -1244,12 +1244,14 @@ static void nhi_reset(struct tb_nhi *nhi)
+ val = ioread32(nhi->iobase + REG_RESET);
+ if (!(val & REG_RESET_HRR)) {
+ dev_warn(&nhi->pdev->dev, "host router reset successful\n");
+- return;
++ return true;
+ }
+ usleep_range(10, 20);
+ } while (ktime_before(ktime_get(), timeout));
+
+ dev_warn(&nhi->pdev->dev, "timeout resetting host router\n");
++
++ return false;
+ }
+
+ static int nhi_init_msi(struct tb_nhi *nhi)
+@@ -1331,6 +1333,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ struct device *dev = &pdev->dev;
+ struct tb_nhi *nhi;
+ struct tb *tb;
++ bool reset;
+ int res;
+
+ if (!nhi_imr_valid(pdev))
+@@ -1365,7 +1368,11 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ nhi_check_quirks(nhi);
+ nhi_check_iommu(nhi);
+
+- nhi_reset(nhi);
++ /*
++ * Only USB4 v2 hosts support host reset so if we already did
++ * that then don't do it again when the domain is initialized.
++ */
++ reset = nhi_reset(nhi) ? false : host_reset;
+
+ res = nhi_init_msi(nhi);
+ if (res)
+@@ -1392,7 +1399,7 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+
+ dev_dbg(dev, "NHI initialized, starting thunderbolt\n");
+
+- res = tb_domain_add(tb);
++ res = tb_domain_add(tb, reset);
+ if (res) {
+ /*
+ * At this point the RX/TX rings might already have been
+diff --git a/drivers/thunderbolt/path.c b/drivers/thunderbolt/path.c
+index 091a81bbdbdc9..f760e54cd9bd1 100644
+--- a/drivers/thunderbolt/path.c
++++ b/drivers/thunderbolt/path.c
+@@ -446,6 +446,19 @@ static int __tb_path_deactivate_hop(struct tb_port *port, int hop_index,
+ return -ETIMEDOUT;
+ }
+
++/**
++ * tb_path_deactivate_hop() - Deactivate one path in path config space
++ * @port: Lane or protocol adapter
++ * @hop_index: HopID of the path to be cleared
++ *
++ * This deactivates or clears a single path config space entry at
++ * @hop_index. Returns %0 in success and negative errno otherwise.
++ */
++int tb_path_deactivate_hop(struct tb_port *port, int hop_index)
++{
++ return __tb_path_deactivate_hop(port, hop_index, true);
++}
++
+ static void __tb_path_deactivate_hops(struct tb_path *path, int first_hop)
+ {
+ int i, res;
+diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
+index fad40c4bc7103..7b086923cec6b 100644
+--- a/drivers/thunderbolt/switch.c
++++ b/drivers/thunderbolt/switch.c
+@@ -676,6 +676,13 @@ int tb_port_disable(struct tb_port *port)
+ return __tb_port_enable(port, false);
+ }
+
++static int tb_port_reset(struct tb_port *port)
++{
++ if (tb_switch_is_usb4(port->sw))
++ return port->cap_usb4 ? usb4_port_reset(port) : 0;
++ return tb_lc_reset_port(port);
++}
++
+ /*
+ * tb_init_port() - initialize a port
+ *
+@@ -1534,29 +1541,124 @@ static void tb_dump_switch(const struct tb *tb, const struct tb_switch *sw)
+ regs->__unknown1, regs->__unknown4);
+ }
+
++static int tb_switch_reset_host(struct tb_switch *sw)
++{
++ if (sw->generation > 1) {
++ struct tb_port *port;
++
++ tb_switch_for_each_port(sw, port) {
++ int i, ret;
++
++ /*
++ * For lane adapters we issue downstream port
++ * reset and clear up path config spaces.
++ *
++ * For protocol adapters we disable the path and
++ * clear path config space one by one (from 8 to
++ * Max Input HopID of the adapter).
++ */
++ if (tb_port_is_null(port) && !tb_is_upstream_port(port)) {
++ ret = tb_port_reset(port);
++ if (ret)
++ return ret;
++ } else if (tb_port_is_usb3_down(port) ||
++ tb_port_is_usb3_up(port)) {
++ tb_usb3_port_enable(port, false);
++ } else if (tb_port_is_dpin(port) ||
++ tb_port_is_dpout(port)) {
++ tb_dp_port_enable(port, false);
++ } else if (tb_port_is_pcie_down(port) ||
++ tb_port_is_pcie_up(port)) {
++ tb_pci_port_enable(port, false);
++ } else {
++ continue;
++ }
++
++ /* Cleanup path config space of protocol adapter */
++ for (i = TB_PATH_MIN_HOPID;
++ i <= port->config.max_in_hop_id; i++) {
++ ret = tb_path_deactivate_hop(port, i);
++ if (ret)
++ return ret;
++ }
++ }
++ } else {
++ struct tb_cfg_result res;
++
++ /* Thunderbolt 1 uses the "reset" config space packet */
++ res.err = tb_sw_write(sw, ((u32 *) &sw->config) + 2,
++ TB_CFG_SWITCH, 2, 2);
++ if (res.err)
++ return res.err;
++ res = tb_cfg_reset(sw->tb->ctl, tb_route(sw));
++ if (res.err > 0)
++ return -EIO;
++ else if (res.err < 0)
++ return res.err;
++ }
++
++ return 0;
++}
++
++static int tb_switch_reset_device(struct tb_switch *sw)
++{
++ return tb_port_reset(tb_switch_downstream_port(sw));
++}
++
++static bool tb_switch_enumerated(struct tb_switch *sw)
++{
++ u32 val;
++ int ret;
++
++ /*
++ * Read directly from the hardware because we use this also
++ * during system sleep where sw->config.enabled is already set
++ * by us.
++ */
++ ret = tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_3, 1);
++ if (ret)
++ return false;
++
++ return !!(val & ROUTER_CS_3_V);
++}
++
+ /**
+- * tb_switch_reset() - reconfigure route, enable and send TB_CFG_PKG_RESET
+- * @sw: Switch to reset
++ * tb_switch_reset() - Perform reset to the router
++ * @sw: Router to reset
+ *
+- * Return: Returns 0 on success or an error code on failure.
++ * Issues reset to the router @sw. Can be used for any router. For host
++ * routers, resets all the downstream ports and cleans up path config
++ * spaces accordingly. For device routers issues downstream port reset
++ * through the parent router, so as side effect there will be unplug
++ * soon after this is finished.
++ *
++ * If the router is not enumerated does nothing.
++ *
++ * Returns %0 on success or negative errno in case of failure.
+ */
+ int tb_switch_reset(struct tb_switch *sw)
+ {
+- struct tb_cfg_result res;
++ int ret;
+
+- if (sw->generation > 1)
++ /*
++ * We cannot access the port config spaces unless the router is
++ * already enumerated. If the router is not enumerated it is
++ * equal to being reset so we can skip that here.
++ */
++ if (!tb_switch_enumerated(sw))
+ return 0;
+
+- tb_sw_dbg(sw, "resetting switch\n");
++ tb_sw_dbg(sw, "resetting\n");
++
++ if (tb_route(sw))
++ ret = tb_switch_reset_device(sw);
++ else
++ ret = tb_switch_reset_host(sw);
+
+- res.err = tb_sw_write(sw, ((u32 *) &sw->config) + 2,
+- TB_CFG_SWITCH, 2, 2);
+- if (res.err)
+- return res.err;
+- res = tb_cfg_reset(sw->tb->ctl, tb_route(sw));
+- if (res.err > 0)
+- return -EIO;
+- return res.err;
++ if (ret)
++ tb_sw_warn(sw, "failed to reset\n");
++
++ return ret;
+ }
+
+ /**
+@@ -3078,22 +3180,29 @@ void tb_switch_unconfigure_link(struct tb_switch *sw)
+ {
+ struct tb_port *up, *down;
+
+- if (sw->is_unplugged)
+- return;
+ if (!tb_route(sw) || tb_switch_is_icm(sw))
+ return;
+
++ /*
++ * Unconfigure downstream port so that wake-on-connect can be
++ * configured after router unplug. No need to unconfigure upstream port
++ * since its router is unplugged.
++ */
+ up = tb_upstream_port(sw);
+- if (tb_switch_is_usb4(up->sw))
+- usb4_port_unconfigure(up);
+- else
+- tb_lc_unconfigure_port(up);
+-
+ down = up->remote;
+ if (tb_switch_is_usb4(down->sw))
+ usb4_port_unconfigure(down);
+ else
+ tb_lc_unconfigure_port(down);
++
++ if (sw->is_unplugged)
++ return;
++
++ up = tb_upstream_port(sw);
++ if (tb_switch_is_usb4(up->sw))
++ usb4_port_unconfigure(up);
++ else
++ tb_lc_unconfigure_port(up);
+ }
+
+ static void tb_switch_credits_init(struct tb_switch *sw)
+@@ -3339,7 +3448,26 @@ static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags)
+ return tb_lc_set_wake(sw, flags);
+ }
+
+-int tb_switch_resume(struct tb_switch *sw)
++static void tb_switch_check_wakes(struct tb_switch *sw)
++{
++ if (device_may_wakeup(&sw->dev)) {
++ if (tb_switch_is_usb4(sw))
++ usb4_switch_check_wakes(sw);
++ }
++}
++
++/**
++ * tb_switch_resume() - Resume a switch after sleep
++ * @sw: Switch to resume
++ * @runtime: Is this resume from runtime suspend or system sleep
++ *
++ * Resumes and re-enumerates router (and all its children), if still plugged
++ * after suspend. Don't enumerate device router whose UID was changed during
++ * suspend. If this is resume from system sleep, notifies PM core about the
++ * wakes occurred during suspend. Disables all wakes, except USB4 wake of
++ * upstream port for USB4 routers that shall be always enabled.
++ */
++int tb_switch_resume(struct tb_switch *sw, bool runtime)
+ {
+ struct tb_port *port;
+ int err;
+@@ -3388,6 +3516,9 @@ int tb_switch_resume(struct tb_switch *sw)
+ if (err)
+ return err;
+
++ if (!runtime)
++ tb_switch_check_wakes(sw);
++
+ /* Disable wakes */
+ tb_switch_set_wake(sw, 0);
+
+@@ -3417,7 +3548,8 @@ int tb_switch_resume(struct tb_switch *sw)
+ */
+ if (tb_port_unlock(port))
+ tb_port_warn(port, "failed to unlock port\n");
+- if (port->remote && tb_switch_resume(port->remote->sw)) {
++ if (port->remote &&
++ tb_switch_resume(port->remote->sw, runtime)) {
+ tb_port_warn(port,
+ "lost during suspend, disconnecting\n");
+ tb_sw_set_unplugged(port->remote->sw);
+diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
+index e6681f153c69d..525f515e8b48b 100644
+--- a/drivers/thunderbolt/tb.c
++++ b/drivers/thunderbolt/tb.c
+@@ -1717,6 +1717,12 @@ static struct tb_port *tb_find_dp_out(struct tb *tb, struct tb_port *in)
+ continue;
+ }
+
++ /* Needs to be on different routers */
++ if (in->sw == port->sw) {
++ tb_port_dbg(port, "skipping DP OUT on same router\n");
++ continue;
++ }
++
+ tb_port_dbg(port, "DP OUT available\n");
+
+ /*
+@@ -2628,7 +2634,7 @@ static int tb_scan_finalize_switch(struct device *dev, void *data)
+ return 0;
+ }
+
+-static int tb_start(struct tb *tb)
++static int tb_start(struct tb *tb, bool reset)
+ {
+ struct tb_cm *tcm = tb_priv(tb);
+ int ret;
+@@ -2669,12 +2675,24 @@ static int tb_start(struct tb *tb)
+ tb_switch_tmu_configure(tb->root_switch, TB_SWITCH_TMU_MODE_LOWRES);
+ /* Enable TMU if it is off */
+ tb_switch_tmu_enable(tb->root_switch);
+- /* Full scan to discover devices added before the driver was loaded. */
+- tb_scan_switch(tb->root_switch);
+- /* Find out tunnels created by the boot firmware */
+- tb_discover_tunnels(tb);
+- /* Add DP resources from the DP tunnels created by the boot firmware */
+- tb_discover_dp_resources(tb);
++
++ /*
++ * Boot firmware might have created tunnels of its own. Since we
++ * cannot be sure they are usable for us, tear them down and
++ * reset the ports to handle it as new hotplug for USB4 v1
++ * routers (for USB4 v2 and beyond we already do host reset).
++ */
++ if (reset && usb4_switch_version(tb->root_switch) == 1) {
++ tb_switch_reset(tb->root_switch);
++ } else {
++ /* Full scan to discover devices added before the driver was loaded. */
++ tb_scan_switch(tb->root_switch);
++ /* Find out tunnels created by the boot firmware */
++ tb_discover_tunnels(tb);
++ /* Add DP resources from the DP tunnels created by the boot firmware */
++ tb_discover_dp_resources(tb);
++ }
++
+ /*
+ * If the boot firmware did not create USB 3.x tunnels create them
+ * now for the whole topology.
+@@ -2745,10 +2763,14 @@ static int tb_resume_noirq(struct tb *tb)
+
+ tb_dbg(tb, "resuming...\n");
+
+- /* remove any pci devices the firmware might have setup */
+- tb_switch_reset(tb->root_switch);
++ /*
++ * For non-USB4 hosts (Apple systems) remove any PCIe devices
++ * the firmware might have setup.
++ */
++ if (!tb_switch_is_usb4(tb->root_switch))
++ tb_switch_reset(tb->root_switch);
+
+- tb_switch_resume(tb->root_switch);
++ tb_switch_resume(tb->root_switch, false);
+ tb_free_invalid_tunnels(tb);
+ tb_free_unplugged_children(tb->root_switch);
+ tb_restore_children(tb->root_switch);
+@@ -2874,7 +2896,7 @@ static int tb_runtime_resume(struct tb *tb)
+ struct tb_tunnel *tunnel, *n;
+
+ mutex_lock(&tb->lock);
+- tb_switch_resume(tb->root_switch);
++ tb_switch_resume(tb->root_switch, true);
+ tb_free_invalid_tunnels(tb);
+ tb_restore_children(tb->root_switch);
+ list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list)
+diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
+index e4d4effb94447..7706f8e08c8d6 100644
+--- a/drivers/thunderbolt/tb.h
++++ b/drivers/thunderbolt/tb.h
+@@ -487,7 +487,7 @@ struct tb_path {
+ */
+ struct tb_cm_ops {
+ int (*driver_ready)(struct tb *tb);
+- int (*start)(struct tb *tb);
++ int (*start)(struct tb *tb, bool reset);
+ void (*stop)(struct tb *tb);
+ int (*suspend_noirq)(struct tb *tb);
+ int (*resume_noirq)(struct tb *tb);
+@@ -750,7 +750,7 @@ int tb_xdomain_init(void);
+ void tb_xdomain_exit(void);
+
+ struct tb *tb_domain_alloc(struct tb_nhi *nhi, int timeout_msec, size_t privsize);
+-int tb_domain_add(struct tb *tb);
++int tb_domain_add(struct tb *tb, bool reset);
+ void tb_domain_remove(struct tb *tb);
+ int tb_domain_suspend_noirq(struct tb *tb);
+ int tb_domain_resume_noirq(struct tb *tb);
+@@ -817,7 +817,7 @@ int tb_switch_configuration_valid(struct tb_switch *sw);
+ int tb_switch_add(struct tb_switch *sw);
+ void tb_switch_remove(struct tb_switch *sw);
+ void tb_switch_suspend(struct tb_switch *sw, bool runtime);
+-int tb_switch_resume(struct tb_switch *sw);
++int tb_switch_resume(struct tb_switch *sw, bool runtime);
+ int tb_switch_reset(struct tb_switch *sw);
+ int tb_switch_wait_for_bit(struct tb_switch *sw, u32 offset, u32 bit,
+ u32 value, int timeout_msec);
+@@ -1154,6 +1154,7 @@ struct tb_path *tb_path_alloc(struct tb *tb, struct tb_port *src, int src_hopid,
+ void tb_path_free(struct tb_path *path);
+ int tb_path_activate(struct tb_path *path);
+ void tb_path_deactivate(struct tb_path *path);
++int tb_path_deactivate_hop(struct tb_port *port, int hop_index);
+ bool tb_path_is_invalid(struct tb_path *path);
+ bool tb_path_port_on_path(const struct tb_path *path,
+ const struct tb_port *port);
+@@ -1173,6 +1174,7 @@ int tb_drom_read(struct tb_switch *sw);
+ int tb_drom_read_uid_only(struct tb_switch *sw, u64 *uid);
+
+ int tb_lc_read_uuid(struct tb_switch *sw, u32 *uuid);
++int tb_lc_reset_port(struct tb_port *port);
+ int tb_lc_configure_port(struct tb_port *port);
+ void tb_lc_unconfigure_port(struct tb_port *port);
+ int tb_lc_configure_xdomain(struct tb_port *port);
+@@ -1276,6 +1278,7 @@ static inline bool tb_switch_is_usb4(const struct tb_switch *sw)
+ return usb4_switch_version(sw) > 0;
+ }
+
++void usb4_switch_check_wakes(struct tb_switch *sw);
+ int usb4_switch_setup(struct tb_switch *sw);
+ int usb4_switch_configuration_valid(struct tb_switch *sw);
+ int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid);
+@@ -1305,6 +1308,7 @@ void usb4_switch_remove_ports(struct tb_switch *sw);
+
+ int usb4_port_unlock(struct tb_port *port);
+ int usb4_port_hotplug_enable(struct tb_port *port);
++int usb4_port_reset(struct tb_port *port);
+ int usb4_port_configure(struct tb_port *port);
+ void usb4_port_unconfigure(struct tb_port *port);
+ int usb4_port_configure_xdomain(struct tb_port *port, struct tb_xdomain *xd);
+diff --git a/drivers/thunderbolt/tb_regs.h b/drivers/thunderbolt/tb_regs.h
+index 6f798f6a2b848..4e43b47f9f119 100644
+--- a/drivers/thunderbolt/tb_regs.h
++++ b/drivers/thunderbolt/tb_regs.h
+@@ -194,6 +194,8 @@ struct tb_regs_switch_header {
+ #define USB4_VERSION_MAJOR_MASK GENMASK(7, 5)
+
+ #define ROUTER_CS_1 0x01
++#define ROUTER_CS_3 0x03
++#define ROUTER_CS_3_V BIT(31)
+ #define ROUTER_CS_4 0x04
+ /* Used with the router cmuv field */
+ #define ROUTER_CS_4_CMUV_V1 0x10
+@@ -389,6 +391,7 @@ struct tb_regs_port_header {
+ #define PORT_CS_18_CSA BIT(22)
+ #define PORT_CS_18_TIP BIT(24)
+ #define PORT_CS_19 0x13
++#define PORT_CS_19_DPR BIT(0)
+ #define PORT_CS_19_PC BIT(3)
+ #define PORT_CS_19_PID BIT(4)
+ #define PORT_CS_19_WOC BIT(16)
+@@ -584,6 +587,9 @@ struct tb_regs_hop {
+ #define TB_LC_POWER 0x740
+
+ /* Link controller registers */
++#define TB_LC_PORT_MODE 0x26
++#define TB_LC_PORT_MODE_DPR BIT(0)
++
+ #define TB_LC_CS_42 0x2a
+ #define TB_LC_CS_42_USB_PLUGGED BIT(31)
+
+diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c
+index 1515eff8cc3e2..a74c9ea67bf54 100644
+--- a/drivers/thunderbolt/usb4.c
++++ b/drivers/thunderbolt/usb4.c
+@@ -155,7 +155,13 @@ static inline int usb4_switch_op_data(struct tb_switch *sw, u16 opcode,
+ tx_dwords, rx_data, rx_dwords);
+ }
+
+-static void usb4_switch_check_wakes(struct tb_switch *sw)
++/**
++ * usb4_switch_check_wakes() - Check for wakes and notify PM core about them
++ * @sw: Router whose wakes to check
++ *
++ * Checks wakes occurred during suspend and notify the PM core about them.
++ */
++void usb4_switch_check_wakes(struct tb_switch *sw)
+ {
+ bool wakeup_usb4 = false;
+ struct usb4_port *usb4;
+@@ -163,9 +169,6 @@ static void usb4_switch_check_wakes(struct tb_switch *sw)
+ bool wakeup = false;
+ u32 val;
+
+- if (!device_may_wakeup(&sw->dev))
+- return;
+-
+ if (tb_route(sw)) {
+ if (tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_6, 1))
+ return;
+@@ -244,8 +247,6 @@ int usb4_switch_setup(struct tb_switch *sw)
+ u32 val = 0;
+ int ret;
+
+- usb4_switch_check_wakes(sw);
+-
+ if (!tb_route(sw))
+ return 0;
+
+@@ -1113,6 +1114,45 @@ int usb4_port_hotplug_enable(struct tb_port *port)
+ return tb_port_write(port, &val, TB_CFG_PORT, ADP_CS_5, 1);
+ }
+
++/**
++ * usb4_port_reset() - Issue downstream port reset
++ * @port: USB4 port to reset
++ *
++ * Issues downstream port reset to @port.
++ */
++int usb4_port_reset(struct tb_port *port)
++{
++ int ret;
++ u32 val;
++
++ if (!port->cap_usb4)
++ return -EINVAL;
++
++ ret = tb_port_read(port, &val, TB_CFG_PORT,
++ port->cap_usb4 + PORT_CS_19, 1);
++ if (ret)
++ return ret;
++
++ val |= PORT_CS_19_DPR;
++
++ ret = tb_port_write(port, &val, TB_CFG_PORT,
++ port->cap_usb4 + PORT_CS_19, 1);
++ if (ret)
++ return ret;
++
++ fsleep(10000);
++
++ ret = tb_port_read(port, &val, TB_CFG_PORT,
++ port->cap_usb4 + PORT_CS_19, 1);
++ if (ret)
++ return ret;
++
++ val &= ~PORT_CS_19_DPR;
++
++ return tb_port_write(port, &val, TB_CFG_PORT,
++ port->cap_usb4 + PORT_CS_19, 1);
++}
++
+ static int usb4_port_set_configured(struct tb_port *port, bool configured)
+ {
+ int ret;
+diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
+index c1d43f040c43a..2d1f350a4bea2 100644
+--- a/drivers/tty/serial/8250/8250_dw.c
++++ b/drivers/tty/serial/8250/8250_dw.c
+@@ -357,9 +357,9 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
+ long rate;
+ int ret;
+
++ clk_disable_unprepare(d->clk);
+ rate = clk_round_rate(d->clk, newrate);
+- if (rate > 0 && p->uartclk != rate) {
+- clk_disable_unprepare(d->clk);
++ if (rate > 0) {
+ /*
+ * Note that any clock-notifer worker will block in
+ * serial8250_update_uartclk() until we are done.
+@@ -367,8 +367,8 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
+ ret = clk_set_rate(d->clk, newrate);
+ if (!ret)
+ p->uartclk = rate;
+- clk_prepare_enable(d->clk);
+ }
++ clk_prepare_enable(d->clk);
+
+ dw8250_do_set_termios(p, termios, old);
+ }
+diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
+index 4749331fe618c..1e8853eae5042 100644
+--- a/drivers/tty/serial/mxs-auart.c
++++ b/drivers/tty/serial/mxs-auart.c
+@@ -1086,11 +1086,13 @@ static void mxs_auart_set_ldisc(struct uart_port *port,
+
+ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
+ {
+- u32 istat;
++ u32 istat, stat;
+ struct mxs_auart_port *s = context;
+ u32 mctrl_temp = s->mctrl_prev;
+- u32 stat = mxs_read(s, REG_STAT);
+
++ uart_port_lock(&s->port);
++
++ stat = mxs_read(s, REG_STAT);
+ istat = mxs_read(s, REG_INTR);
+
+ /* ack irq */
+@@ -1126,6 +1128,8 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
+ istat &= ~AUART_INTR_TXIS;
+ }
+
++ uart_port_unlock(&s->port);
++
+ return IRQ_HANDLED;
+ }
+
+diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
+index c8bf08c19c647..77691fbbf779a 100644
+--- a/drivers/tty/serial/pmac_zilog.c
++++ b/drivers/tty/serial/pmac_zilog.c
+@@ -210,7 +210,6 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap)
+ {
+ struct tty_port *port;
+ unsigned char ch, r1, drop, flag;
+- int loops = 0;
+
+ /* Sanity check, make sure the old bug is no longer happening */
+ if (uap->port.state == NULL) {
+@@ -291,24 +290,11 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap)
+ if (r1 & Rx_OVR)
+ tty_insert_flip_char(port, 0, TTY_OVERRUN);
+ next_char:
+- /* We can get stuck in an infinite loop getting char 0 when the
+- * line is in a wrong HW state, we break that here.
+- * When that happens, I disable the receive side of the driver.
+- * Note that what I've been experiencing is a real irq loop where
+- * I'm getting flooded regardless of the actual port speed.
+- * Something strange is going on with the HW
+- */
+- if ((++loops) > 1000)
+- goto flood;
+ ch = read_zsreg(uap, R0);
+ if (!(ch & Rx_CH_AV))
+ break;
+ }
+
+- return true;
+- flood:
+- pmz_interrupt_control(uap, 0);
+- pmz_error("pmz: rx irq flood !\n");
+ return true;
+ }
+
+diff --git a/drivers/tty/serial/serial_base.h b/drivers/tty/serial/serial_base.h
+index c74c548f0db62..b6c38d2edfd40 100644
+--- a/drivers/tty/serial/serial_base.h
++++ b/drivers/tty/serial/serial_base.h
+@@ -22,6 +22,7 @@ struct serial_ctrl_device {
+ struct serial_port_device {
+ struct device dev;
+ struct uart_port *port;
++ unsigned int tx_enabled:1;
+ };
+
+ int serial_base_ctrl_init(void);
+@@ -30,6 +31,9 @@ void serial_base_ctrl_exit(void);
+ int serial_base_port_init(void);
+ void serial_base_port_exit(void);
+
++void serial_base_port_startup(struct uart_port *port);
++void serial_base_port_shutdown(struct uart_port *port);
++
+ int serial_base_driver_register(struct device_driver *driver);
+ void serial_base_driver_unregister(struct device_driver *driver);
+
+diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
+index ff85ebd3a007d..c476d884356db 100644
+--- a/drivers/tty/serial/serial_core.c
++++ b/drivers/tty/serial/serial_core.c
+@@ -156,7 +156,7 @@ static void __uart_start(struct uart_state *state)
+ * enabled, serial_port_runtime_resume() calls start_tx() again
+ * after enabling the device.
+ */
+- if (pm_runtime_active(&port_dev->dev))
++ if (!pm_runtime_enabled(port->dev) || pm_runtime_active(&port_dev->dev))
+ port->ops->start_tx(port);
+ pm_runtime_mark_last_busy(&port_dev->dev);
+ pm_runtime_put_autosuspend(&port_dev->dev);
+@@ -323,16 +323,26 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state,
+ bool init_hw)
+ {
+ struct tty_port *port = &state->port;
++ struct uart_port *uport;
+ int retval;
+
+ if (tty_port_initialized(port))
+- return 0;
++ goto out_base_port_startup;
+
+ retval = uart_port_startup(tty, state, init_hw);
+- if (retval)
++ if (retval) {
+ set_bit(TTY_IO_ERROR, &tty->flags);
++ return retval;
++ }
+
+- return retval;
++out_base_port_startup:
++ uport = uart_port_check(state);
++ if (!uport)
++ return -EIO;
++
++ serial_base_port_startup(uport);
++
++ return 0;
+ }
+
+ /*
+@@ -355,6 +365,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state)
+ if (tty)
+ set_bit(TTY_IO_ERROR, &tty->flags);
+
++ if (uport)
++ serial_base_port_shutdown(uport);
++
+ if (tty_port_initialized(port)) {
+ tty_port_set_initialized(port, false);
+
+@@ -1775,6 +1788,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
+ uport->ops->stop_rx(uport);
+ uart_port_unlock_irq(uport);
+
++ serial_base_port_shutdown(uport);
+ uart_port_shutdown(port);
+
+ /*
+@@ -1788,6 +1802,7 @@ static void uart_tty_port_shutdown(struct tty_port *port)
+ * Free the transmit buffer.
+ */
+ uart_port_lock_irq(uport);
++ uart_circ_clear(&state->xmit);
+ buf = state->xmit.buf;
+ state->xmit.buf = NULL;
+ uart_port_unlock_irq(uport);
+diff --git a/drivers/tty/serial/serial_port.c b/drivers/tty/serial/serial_port.c
+index 72b6f4f326e2b..7d51e66ec88b9 100644
+--- a/drivers/tty/serial/serial_port.c
++++ b/drivers/tty/serial/serial_port.c
+@@ -36,8 +36,12 @@ static int serial_port_runtime_resume(struct device *dev)
+
+ /* Flush any pending TX for the port */
+ uart_port_lock_irqsave(port, &flags);
++ if (!port_dev->tx_enabled)
++ goto unlock;
+ if (__serial_port_busy(port))
+ port->ops->start_tx(port);
++
++unlock:
+ uart_port_unlock_irqrestore(port, flags);
+
+ out:
+@@ -57,6 +61,11 @@ static int serial_port_runtime_suspend(struct device *dev)
+ return 0;
+
+ uart_port_lock_irqsave(port, &flags);
++ if (!port_dev->tx_enabled) {
++ uart_port_unlock_irqrestore(port, flags);
++ return 0;
++ }
++
+ busy = __serial_port_busy(port);
+ if (busy)
+ port->ops->start_tx(port);
+@@ -68,6 +77,31 @@ static int serial_port_runtime_suspend(struct device *dev)
+ return busy ? -EBUSY : 0;
+ }
+
++static void serial_base_port_set_tx(struct uart_port *port,
++ struct serial_port_device *port_dev,
++ bool enabled)
++{
++ unsigned long flags;
++
++ uart_port_lock_irqsave(port, &flags);
++ port_dev->tx_enabled = enabled;
++ uart_port_unlock_irqrestore(port, flags);
++}
++
++void serial_base_port_startup(struct uart_port *port)
++{
++ struct serial_port_device *port_dev = port->port_dev;
++
++ serial_base_port_set_tx(port, port_dev, true);
++}
++
++void serial_base_port_shutdown(struct uart_port *port)
++{
++ struct serial_port_device *port_dev = port->port_dev;
++
++ serial_base_port_set_tx(port, port_dev, false);
++}
++
+ static DEFINE_RUNTIME_DEV_PM_OPS(serial_port_pm,
+ serial_port_runtime_suspend,
+ serial_port_runtime_resume, NULL);
+diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
+index 693e932d6feb5..d103b07d10ee5 100644
+--- a/drivers/tty/serial/stm32-usart.c
++++ b/drivers/tty/serial/stm32-usart.c
+@@ -857,6 +857,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
+ const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs;
+ u32 sr;
+ unsigned int size;
++ irqreturn_t ret = IRQ_NONE;
+
+ sr = readl_relaxed(port->membase + ofs->isr);
+
+@@ -865,11 +866,14 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
+ (sr & USART_SR_TC)) {
+ stm32_usart_tc_interrupt_disable(port);
+ stm32_usart_rs485_rts_disable(port);
++ ret = IRQ_HANDLED;
+ }
+
+- if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG)
++ if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG) {
+ writel_relaxed(USART_ICR_RTOCF,
+ port->membase + ofs->icr);
++ ret = IRQ_HANDLED;
++ }
+
+ if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG) {
+ /* Clear wake up flag and disable wake up interrupt */
+@@ -878,6 +882,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
+ stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE);
+ if (irqd_is_wakeup_set(irq_get_irq_data(port->irq)))
+ pm_wakeup_event(tport->tty->dev, 0);
++ ret = IRQ_HANDLED;
+ }
+
+ /*
+@@ -892,6 +897,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
+ uart_unlock_and_check_sysrq(port);
+ if (size)
+ tty_flip_buffer_push(tport);
++ ret = IRQ_HANDLED;
+ }
+ }
+
+@@ -899,6 +905,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
+ uart_port_lock(port);
+ stm32_usart_transmit_chars(port);
+ uart_port_unlock(port);
++ ret = IRQ_HANDLED;
+ }
+
+ /* Receiver timeout irq for DMA RX */
+@@ -908,9 +915,10 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr)
+ uart_unlock_and_check_sysrq(port);
+ if (size)
+ tty_flip_buffer_push(tport);
++ ret = IRQ_HANDLED;
+ }
+
+- return IRQ_HANDLED;
++ return ret;
+ }
+
+ static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+@@ -1080,6 +1088,7 @@ static int stm32_usart_startup(struct uart_port *port)
+ val |= USART_CR2_SWAP;
+ writel_relaxed(val, port->membase + ofs->cr2);
+ }
++ stm32_port->throttled = false;
+
+ /* RX FIFO Flush */
+ if (ofs->rqr != UNDEF_REG)
+diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
+index f532e2c004a25..bcbcf758925be 100644
+--- a/drivers/ufs/host/ufs-qcom.c
++++ b/drivers/ufs/host/ufs-qcom.c
+@@ -47,7 +47,7 @@ enum {
+ TSTBUS_MAX,
+ };
+
+-#define QCOM_UFS_MAX_GEAR 4
++#define QCOM_UFS_MAX_GEAR 5
+ #define QCOM_UFS_MAX_LANE 2
+
+ enum {
+@@ -67,26 +67,32 @@ static const struct __ufs_qcom_bw_table {
+ [MODE_PWM][UFS_PWM_G2][UFS_LANE_1] = { 1844, 1000 },
+ [MODE_PWM][UFS_PWM_G3][UFS_LANE_1] = { 3688, 1000 },
+ [MODE_PWM][UFS_PWM_G4][UFS_LANE_1] = { 7376, 1000 },
++ [MODE_PWM][UFS_PWM_G5][UFS_LANE_1] = { 14752, 1000 },
+ [MODE_PWM][UFS_PWM_G1][UFS_LANE_2] = { 1844, 1000 },
+ [MODE_PWM][UFS_PWM_G2][UFS_LANE_2] = { 3688, 1000 },
+ [MODE_PWM][UFS_PWM_G3][UFS_LANE_2] = { 7376, 1000 },
+ [MODE_PWM][UFS_PWM_G4][UFS_LANE_2] = { 14752, 1000 },
++ [MODE_PWM][UFS_PWM_G5][UFS_LANE_2] = { 29504, 1000 },
+ [MODE_HS_RA][UFS_HS_G1][UFS_LANE_1] = { 127796, 1000 },
+ [MODE_HS_RA][UFS_HS_G2][UFS_LANE_1] = { 255591, 1000 },
+ [MODE_HS_RA][UFS_HS_G3][UFS_LANE_1] = { 1492582, 102400 },
+ [MODE_HS_RA][UFS_HS_G4][UFS_LANE_1] = { 2915200, 204800 },
++ [MODE_HS_RA][UFS_HS_G5][UFS_LANE_1] = { 5836800, 409600 },
+ [MODE_HS_RA][UFS_HS_G1][UFS_LANE_2] = { 255591, 1000 },
+ [MODE_HS_RA][UFS_HS_G2][UFS_LANE_2] = { 511181, 1000 },
+ [MODE_HS_RA][UFS_HS_G3][UFS_LANE_2] = { 1492582, 204800 },
+ [MODE_HS_RA][UFS_HS_G4][UFS_LANE_2] = { 2915200, 409600 },
++ [MODE_HS_RA][UFS_HS_G5][UFS_LANE_2] = { 5836800, 819200 },
+ [MODE_HS_RB][UFS_HS_G1][UFS_LANE_1] = { 149422, 1000 },
+ [MODE_HS_RB][UFS_HS_G2][UFS_LANE_1] = { 298189, 1000 },
+ [MODE_HS_RB][UFS_HS_G3][UFS_LANE_1] = { 1492582, 102400 },
+ [MODE_HS_RB][UFS_HS_G4][UFS_LANE_1] = { 2915200, 204800 },
++ [MODE_HS_RB][UFS_HS_G5][UFS_LANE_1] = { 5836800, 409600 },
+ [MODE_HS_RB][UFS_HS_G1][UFS_LANE_2] = { 298189, 1000 },
+ [MODE_HS_RB][UFS_HS_G2][UFS_LANE_2] = { 596378, 1000 },
+ [MODE_HS_RB][UFS_HS_G3][UFS_LANE_2] = { 1492582, 204800 },
+ [MODE_HS_RB][UFS_HS_G4][UFS_LANE_2] = { 2915200, 409600 },
++ [MODE_HS_RB][UFS_HS_G5][UFS_LANE_2] = { 5836800, 819200 },
+ [MODE_MAX][0][0] = { 7643136, 307200 },
+ };
+
+diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
+index c8262e2f29177..c553decb54610 100644
+--- a/drivers/usb/class/cdc-wdm.c
++++ b/drivers/usb/class/cdc-wdm.c
+@@ -485,7 +485,6 @@ static ssize_t wdm_write
+ static int service_outstanding_interrupt(struct wdm_device *desc)
+ {
+ int rv = 0;
+- int used;
+
+ /* submit read urb only if the device is waiting for it */
+ if (!desc->resp_count || !--desc->resp_count)
+@@ -500,10 +499,7 @@ static int service_outstanding_interrupt(struct wdm_device *desc)
+ goto out;
+ }
+
+- used = test_and_set_bit(WDM_RESPONDING, &desc->flags);
+- if (used)
+- goto out;
+-
++ set_bit(WDM_RESPONDING, &desc->flags);
+ spin_unlock_irq(&desc->iuspin);
+ rv = usb_submit_urb(desc->response, GFP_KERNEL);
+ spin_lock_irq(&desc->iuspin);
+diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
+index a5776531ba4d3..97ff2073cf1e2 100644
+--- a/drivers/usb/core/port.c
++++ b/drivers/usb/core/port.c
+@@ -448,8 +448,10 @@ static void usb_port_shutdown(struct device *dev)
+ {
+ struct usb_port *port_dev = to_usb_port(dev);
+
+- if (port_dev->child)
++ if (port_dev->child) {
+ usb_disable_usb2_hardware_lpm(port_dev->child);
++ usb_unlocked_disable_lpm(port_dev->child);
++ }
+ }
+
+ static const struct dev_pm_ops usb_port_pm_ops = {
+diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c
+index 79582b102c7ed..994a78ad084b1 100644
+--- a/drivers/usb/dwc2/hcd_ddma.c
++++ b/drivers/usb/dwc2/hcd_ddma.c
+@@ -867,13 +867,15 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
+ struct dwc2_dma_desc *dma_desc;
+ struct dwc2_hcd_iso_packet_desc *frame_desc;
+ u16 frame_desc_idx;
+- struct urb *usb_urb = qtd->urb->priv;
++ struct urb *usb_urb;
+ u16 remain = 0;
+ int rc = 0;
+
+ if (!qtd->urb)
+ return -EINVAL;
+
++ usb_urb = qtd->urb->priv;
++
+ dma_sync_single_for_cpu(hsotg->dev, qh->desc_list_dma + (idx *
+ sizeof(struct dwc2_dma_desc)),
+ sizeof(struct dwc2_dma_desc),
+diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
+index 28f4e6552e845..0acc32ed99609 100644
+--- a/drivers/usb/gadget/function/f_ncm.c
++++ b/drivers/usb/gadget/function/f_ncm.c
+@@ -878,7 +878,7 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+ if (alt > 1)
+ goto fail;
+
+- if (ncm->port.in_ep->enabled) {
++ if (ncm->netdev) {
+ DBG(cdev, "reset ncm\n");
+ ncm->netdev = NULL;
+ gether_disconnect(&ncm->port);
+@@ -1367,7 +1367,7 @@ static void ncm_disable(struct usb_function *f)
+
+ DBG(cdev, "ncm deactivated\n");
+
+- if (ncm->port.in_ep->enabled) {
++ if (ncm->netdev) {
+ ncm->netdev = NULL;
+ gether_disconnect(&ncm->port);
+ }
+diff --git a/drivers/usb/misc/onboard_usb_hub.c b/drivers/usb/misc/onboard_usb_hub.c
+index 0dd2b032c90b9..e162838bec3d9 100644
+--- a/drivers/usb/misc/onboard_usb_hub.c
++++ b/drivers/usb/misc/onboard_usb_hub.c
+@@ -78,7 +78,7 @@ static int onboard_hub_power_on(struct onboard_hub *hub)
+ err = regulator_bulk_enable(hub->pdata->num_supplies, hub->supplies);
+ if (err) {
+ dev_err(hub->dev, "failed to enable supplies: %pe\n", ERR_PTR(err));
+- return err;
++ goto disable_clk;
+ }
+
+ fsleep(hub->pdata->reset_us);
+@@ -87,6 +87,10 @@ static int onboard_hub_power_on(struct onboard_hub *hub)
+ hub->is_powered_on = true;
+
+ return 0;
++
++disable_clk:
++ clk_disable_unprepare(hub->clk);
++ return err;
+ }
+
+ static int onboard_hub_power_off(struct onboard_hub *hub)
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index 55a65d941ccbf..8a5846d4adf67 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -255,6 +255,10 @@ static void option_instat_callback(struct urb *urb);
+ #define QUECTEL_PRODUCT_EM061K_LMS 0x0124
+ #define QUECTEL_PRODUCT_EC25 0x0125
+ #define QUECTEL_PRODUCT_EM060K_128 0x0128
++#define QUECTEL_PRODUCT_EM060K_129 0x0129
++#define QUECTEL_PRODUCT_EM060K_12a 0x012a
++#define QUECTEL_PRODUCT_EM060K_12b 0x012b
++#define QUECTEL_PRODUCT_EM060K_12c 0x012c
+ #define QUECTEL_PRODUCT_EG91 0x0191
+ #define QUECTEL_PRODUCT_EG95 0x0195
+ #define QUECTEL_PRODUCT_BG96 0x0296
+@@ -1218,6 +1222,18 @@ static const struct usb_device_id option_ids[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x30) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x40) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_129, 0xff, 0xff, 0x30) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_129, 0xff, 0x00, 0x40) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_129, 0xff, 0xff, 0x40) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12a, 0xff, 0xff, 0x30) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12a, 0xff, 0x00, 0x40) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12a, 0xff, 0xff, 0x40) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12b, 0xff, 0xff, 0x30) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12b, 0xff, 0x00, 0x40) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12b, 0xff, 0xff, 0x40) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12c, 0xff, 0xff, 0x30) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12c, 0xff, 0x00, 0x40) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12c, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x30) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x40) },
+@@ -1360,6 +1376,12 @@ static const struct usb_device_id option_ids[] = {
+ .driver_info = NCTRL(2) | RSVD(3) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff), /* Telit FE990 (ECM) */
+ .driver_info = NCTRL(0) | RSVD(1) },
++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a0, 0xff), /* Telit FN20C04 (rmnet) */
++ .driver_info = RSVD(0) | NCTRL(3) },
++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a4, 0xff), /* Telit FN20C04 (rmnet) */
++ .driver_info = RSVD(0) | NCTRL(3) },
++ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a9, 0xff), /* Telit FN20C04 (rmnet) */
++ .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
+ .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
+@@ -2052,6 +2074,10 @@ static const struct usb_device_id option_ids[] = {
+ .driver_info = RSVD(3) },
+ { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9803, 0xff),
+ .driver_info = RSVD(4) },
++ { USB_DEVICE(LONGCHEER_VENDOR_ID, 0x9b05), /* Longsung U8300 */
++ .driver_info = RSVD(4) | RSVD(5) },
++ { USB_DEVICE(LONGCHEER_VENDOR_ID, 0x9b3c), /* Longsung U9300 */
++ .driver_info = RSVD(0) | RSVD(4) },
+ { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
+ { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) },
+ { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
+@@ -2272,15 +2298,29 @@ static const struct usb_device_id option_ids[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */
+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0111, 0xff) }, /* Fibocom FM160 (MBIM mode) */
++ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0115, 0xff), /* Fibocom FM135 (laptop MBIM) */
++ .driver_info = RSVD(5) },
+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */
+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a3, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */
+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff), /* Fibocom FM101-GL (laptop MBIM) */
+ .driver_info = RSVD(4) },
++ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a04, 0xff) }, /* Fibocom FM650-CN (ECM mode) */
++ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a05, 0xff) }, /* Fibocom FM650-CN (NCM mode) */
++ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a06, 0xff) }, /* Fibocom FM650-CN (RNDIS mode) */
++ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a07, 0xff) }, /* Fibocom FM650-CN (MBIM mode) */
+ { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */
+ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */
+ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */
+ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */
++ { USB_DEVICE(0x33f8, 0x0104), /* Rolling RW101-GL (laptop RMNET) */
++ .driver_info = RSVD(4) | RSVD(5) },
++ { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a2, 0xff) }, /* Rolling RW101-GL (laptop MBIM) */
++ { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a3, 0xff) }, /* Rolling RW101-GL (laptop MBIM) */
++ { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a4, 0xff), /* Rolling RW101-GL (laptop MBIM) */
++ .driver_info = RSVD(4) },
++ { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0115, 0xff), /* Rolling RW135-GL (laptop MBIM) */
++ .driver_info = RSVD(5) },
+ { USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) },
+ { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) },
+ { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
+diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
+index f81699537312a..df9a5d6760b45 100644
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -6111,14 +6111,14 @@ static int tcpm_pd_set(struct typec_port *p, struct usb_power_delivery *pd)
+ if (data->sink_desc.pdo[0]) {
+ for (i = 0; i < PDO_MAX_OBJECTS && data->sink_desc.pdo[i]; i++)
+ port->snk_pdo[i] = data->sink_desc.pdo[i];
+- port->nr_snk_pdo = i + 1;
++ port->nr_snk_pdo = i;
+ port->operating_snk_mw = data->operating_snk_mw;
+ }
+
+ if (data->source_desc.pdo[0]) {
+ for (i = 0; i < PDO_MAX_OBJECTS && data->source_desc.pdo[i]; i++)
+ port->src_pdo[i] = data->source_desc.pdo[i];
+- port->nr_src_pdo = i + 1;
++ port->nr_src_pdo = i;
+ }
+
+ switch (port->state) {
+diff --git a/drivers/virt/vmgenid.c b/drivers/virt/vmgenid.c
+index b67a28da47026..a1c467a0e9f71 100644
+--- a/drivers/virt/vmgenid.c
++++ b/drivers/virt/vmgenid.c
+@@ -68,7 +68,6 @@ static int vmgenid_add(struct acpi_device *device)
+ static void vmgenid_notify(struct acpi_device *device, u32 event)
+ {
+ struct vmgenid_state *state = acpi_driver_data(device);
+- char *envp[] = { "NEW_VMGENID=1", NULL };
+ u8 old_id[VMGENID_SIZE];
+
+ memcpy(old_id, state->this_id, sizeof(old_id));
+@@ -76,7 +75,6 @@ static void vmgenid_notify(struct acpi_device *device, u32 event)
+ if (!memcmp(old_id, state->this_id, sizeof(old_id)))
+ return;
+ add_vmfork_randomness(state->this_id, sizeof(state->this_id));
+- kobject_uevent_env(&device->dev.kobj, KOBJ_CHANGE, envp);
+ }
+
+ static const struct acpi_device_id vmgenid_ids[] = {
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index 77260cb9d0b2b..b5175b9929f87 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -692,31 +692,21 @@ static void end_bbio_data_read(struct btrfs_bio *bbio)
+ int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array,
+ gfp_t extra_gfp)
+ {
++ const gfp_t gfp = GFP_NOFS | extra_gfp;
+ unsigned int allocated;
+
+ for (allocated = 0; allocated < nr_pages;) {
+ unsigned int last = allocated;
+
+- allocated = alloc_pages_bulk_array(GFP_NOFS | extra_gfp,
+- nr_pages, page_array);
+-
+- if (allocated == nr_pages)
+- return 0;
+-
+- /*
+- * During this iteration, no page could be allocated, even
+- * though alloc_pages_bulk_array() falls back to alloc_page()
+- * if it could not bulk-allocate. So we must be out of memory.
+- */
+- if (allocated == last) {
++ allocated = alloc_pages_bulk_array(gfp, nr_pages, page_array);
++ if (unlikely(allocated == last)) {
++ /* No progress, fail and do cleanup. */
+ for (int i = 0; i < allocated; i++) {
+ __free_page(page_array[i]);
+ page_array[i] = NULL;
+ }
+ return -ENOMEM;
+ }
+-
+- memalloc_retry_wait(GFP_NOFS);
+ }
+ return 0;
+ }
+@@ -4140,7 +4130,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans,
+ * The actual zeroout of the buffer will happen later in
+ * btree_csum_one_bio.
+ */
+- if (btrfs_is_zoned(fs_info)) {
++ if (btrfs_is_zoned(fs_info) && test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) {
+ set_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags);
+ return;
+ }
+diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
+index 9307bb4393b8f..bd3b21d4850af 100644
+--- a/fs/fuse/dir.c
++++ b/fs/fuse/dir.c
+@@ -1317,6 +1317,7 @@ static int fuse_update_get_attr(struct inode *inode, struct file *file,
+ err = fuse_do_statx(inode, file, stat);
+ if (err == -ENOSYS) {
+ fc->no_statx = 1;
++ err = 0;
+ goto retry;
+ }
+ } else {
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index c719c475a068e..c17bdf973c18d 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -3490,11 +3490,13 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+ struct dentry *dentry, const u32 *bmval,
+ int ignore_crossmnt)
+ {
++ DECLARE_BITMAP(attr_bitmap, ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops));
+ struct nfsd4_fattr_args args;
+ struct svc_fh *tempfh = NULL;
+ int starting_len = xdr->buf->len;
+ __be32 *attrlen_p, status;
+ int attrlen_offset;
++ u32 attrmask[3];
+ int err;
+ struct nfsd4_compoundres *resp = rqstp->rq_resp;
+ u32 minorversion = resp->cstate.minorversion;
+@@ -3502,10 +3504,6 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+ .mnt = exp->ex_path.mnt,
+ .dentry = dentry,
+ };
+- union {
+- u32 attrmask[3];
+- unsigned long mask[2];
+- } u;
+ unsigned long bit;
+
+ WARN_ON_ONCE(bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1);
+@@ -3519,20 +3517,19 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+ /*
+ * Make a local copy of the attribute bitmap that can be modified.
+ */
+- memset(&u, 0, sizeof(u));
+- u.attrmask[0] = bmval[0];
+- u.attrmask[1] = bmval[1];
+- u.attrmask[2] = bmval[2];
++ attrmask[0] = bmval[0];
++ attrmask[1] = bmval[1];
++ attrmask[2] = bmval[2];
+
+ args.rdattr_err = 0;
+ if (exp->ex_fslocs.migrated) {
+- status = fattr_handle_absent_fs(&u.attrmask[0], &u.attrmask[1],
+- &u.attrmask[2], &args.rdattr_err);
++ status = fattr_handle_absent_fs(&attrmask[0], &attrmask[1],
++ &attrmask[2], &args.rdattr_err);
+ if (status)
+ goto out;
+ }
+ args.size = 0;
+- if (u.attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) {
++ if (attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) {
+ status = nfsd4_deleg_getattr_conflict(rqstp, d_inode(dentry));
+ if (status)
+ goto out;
+@@ -3547,16 +3544,16 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+
+ if (!(args.stat.result_mask & STATX_BTIME))
+ /* underlying FS does not offer btime so we can't share it */
+- u.attrmask[1] &= ~FATTR4_WORD1_TIME_CREATE;
+- if ((u.attrmask[0] & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE |
++ attrmask[1] &= ~FATTR4_WORD1_TIME_CREATE;
++ if ((attrmask[0] & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE |
+ FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_MAXNAME)) ||
+- (u.attrmask[1] & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
++ (attrmask[1] & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
+ FATTR4_WORD1_SPACE_TOTAL))) {
+ err = vfs_statfs(&path, &args.statfs);
+ if (err)
+ goto out_nfserr;
+ }
+- if ((u.attrmask[0] & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) &&
++ if ((attrmask[0] & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) &&
+ !fhp) {
+ tempfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
+ status = nfserr_jukebox;
+@@ -3571,10 +3568,10 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+ args.fhp = fhp;
+
+ args.acl = NULL;
+- if (u.attrmask[0] & FATTR4_WORD0_ACL) {
++ if (attrmask[0] & FATTR4_WORD0_ACL) {
+ err = nfsd4_get_nfs4_acl(rqstp, dentry, &args.acl);
+ if (err == -EOPNOTSUPP)
+- u.attrmask[0] &= ~FATTR4_WORD0_ACL;
++ attrmask[0] &= ~FATTR4_WORD0_ACL;
+ else if (err == -EINVAL) {
+ status = nfserr_attrnotsupp;
+ goto out;
+@@ -3586,17 +3583,17 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+
+ #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
+ args.context = NULL;
+- if ((u.attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) ||
+- u.attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
++ if ((attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) ||
++ attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
+ if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
+ err = security_inode_getsecctx(d_inode(dentry),
+ &args.context, &args.contextlen);
+ else
+ err = -EOPNOTSUPP;
+ args.contextsupport = (err == 0);
+- if (u.attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) {
++ if (attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) {
+ if (err == -EOPNOTSUPP)
+- u.attrmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
++ attrmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
+ else if (err)
+ goto out_nfserr;
+ }
+@@ -3604,8 +3601,8 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+ #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
+
+ /* attrmask */
+- status = nfsd4_encode_bitmap4(xdr, u.attrmask[0],
+- u.attrmask[1], u.attrmask[2]);
++ status = nfsd4_encode_bitmap4(xdr, attrmask[0], attrmask[1],
++ attrmask[2]);
+ if (status)
+ goto out;
+
+@@ -3614,7 +3611,9 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+ attrlen_p = xdr_reserve_space(xdr, XDR_UNIT);
+ if (!attrlen_p)
+ goto out_resource;
+- for_each_set_bit(bit, (const unsigned long *)&u.mask,
++ bitmap_from_arr32(attr_bitmap, attrmask,
++ ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops));
++ for_each_set_bit(bit, attr_bitmap,
+ ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops)) {
+ status = nfsd4_enc_fattr4_encode_ops[bit](xdr, &args);
+ if (status != nfs_ok)
+diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
+index bc846b904b68d..aee40db7a036f 100644
+--- a/fs/nilfs2/dir.c
++++ b/fs/nilfs2/dir.c
+@@ -240,7 +240,7 @@ nilfs_filetype_table[NILFS_FT_MAX] = {
+
+ #define S_SHIFT 12
+ static unsigned char
+-nilfs_type_by_mode[S_IFMT >> S_SHIFT] = {
++nilfs_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
+ [S_IFREG >> S_SHIFT] = NILFS_FT_REG_FILE,
+ [S_IFDIR >> S_SHIFT] = NILFS_FT_DIR,
+ [S_IFCHR >> S_SHIFT] = NILFS_FT_CHRDEV,
+diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h
+index 57f2343164a34..a233a24352b1f 100644
+--- a/fs/smb/common/smb2pdu.h
++++ b/fs/smb/common/smb2pdu.h
+@@ -702,7 +702,7 @@ struct smb2_close_rsp {
+ __le16 StructureSize; /* 60 */
+ __le16 Flags;
+ __le32 Reserved;
+- struct_group(network_open_info,
++ struct_group_attr(network_open_info, __packed,
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c
+index 3079e607c5fe6..2bbc3c3316f0f 100644
+--- a/fs/smb/server/server.c
++++ b/fs/smb/server/server.c
+@@ -167,20 +167,17 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
+ int rc;
+ bool is_chained = false;
+
+- if (conn->ops->allocate_rsp_buf(work))
+- return;
+-
+ if (conn->ops->is_transform_hdr &&
+ conn->ops->is_transform_hdr(work->request_buf)) {
+ rc = conn->ops->decrypt_req(work);
+- if (rc < 0) {
+- conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
+- goto send;
+- }
+-
++ if (rc < 0)
++ return;
+ work->encrypted = true;
+ }
+
++ if (conn->ops->allocate_rsp_buf(work))
++ return;
++
+ rc = conn->ops->init_rsp_hdr(work);
+ if (rc) {
+ /* either uid or tid is not correct */
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index cd2ed345c3d39..8ae0c4d5ab96c 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -535,6 +535,10 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
+ if (cmd == SMB2_QUERY_INFO_HE) {
+ struct smb2_query_info_req *req;
+
++ if (get_rfc1002_len(work->request_buf) <
++ offsetof(struct smb2_query_info_req, OutputBufferLength))
++ return -EINVAL;
++
+ req = smb2_get_msg(work->request_buf);
+ if ((req->InfoType == SMB2_O_INFO_FILE &&
+ (req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
+diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c
+index 2e992fadeaa7d..d7906efaa96b1 100644
+--- a/fs/smb/server/vfs.c
++++ b/fs/smb/server/vfs.c
+@@ -754,10 +754,15 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
+ goto out4;
+ }
+
++ /*
++ * explicitly handle file overwrite case, for compatibility with
++ * filesystems that may not support rename flags (e.g: fuse)
++ */
+ if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) {
+ err = -EEXIST;
+ goto out4;
+ }
++ flags &= ~(RENAME_NOREPLACE);
+
+ if (old_child == trap) {
+ err = -EINVAL;
+diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c
+index aa3411354e66d..16bd693d0b3aa 100644
+--- a/fs/squashfs/inode.c
++++ b/fs/squashfs/inode.c
+@@ -48,6 +48,10 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
+ gid_t i_gid;
+ int err;
+
++ inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
++ if (inode->i_ino == 0)
++ return -EINVAL;
++
+ err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->uid), &i_uid);
+ if (err)
+ return err;
+@@ -58,7 +62,6 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode,
+
+ i_uid_write(inode, i_uid);
+ i_gid_write(inode, i_gid);
+- inode->i_ino = le32_to_cpu(sqsh_ino->inode_number);
+ inode_set_mtime(inode, le32_to_cpu(sqsh_ino->mtime), 0);
+ inode_set_atime(inode, inode_get_mtime_sec(inode), 0);
+ inode_set_ctime(inode, inode_get_mtime_sec(inode), 0);
+diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
+index 6b7652fb80505..7cd64021d453d 100644
+--- a/fs/sysfs/file.c
++++ b/fs/sysfs/file.c
+@@ -463,6 +463,8 @@ struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj,
+ kn = kernfs_find_and_get(kobj->sd, attr->name);
+ if (kn)
+ kernfs_break_active_protection(kn);
++ else
++ kobject_put(kobj);
+ return kn;
+ }
+ EXPORT_SYMBOL_GPL(sysfs_break_active_protection);
+diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h
+index 961f4d88f9ef7..1985c22d90ca4 100644
+--- a/include/asm-generic/barrier.h
++++ b/include/asm-generic/barrier.h
+@@ -296,5 +296,13 @@ do { \
+ #define io_stop_wc() do { } while (0)
+ #endif
+
++/*
++ * Architectures that guarantee an implicit smp_mb() in switch_mm()
++ * can override smp_mb__after_switch_mm.
++ */
++#ifndef smp_mb__after_switch_mm
++# define smp_mb__after_switch_mm() smp_mb()
++#endif
++
+ #endif /* !__ASSEMBLY__ */
+ #endif /* __ASM_GENERIC_BARRIER_H */
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 99e4f5e722132..b43ca3b9d2a26 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -126,6 +126,8 @@ typedef unsigned int __bitwise blk_mode_t;
+ #define BLK_OPEN_WRITE_IOCTL ((__force blk_mode_t)(1 << 4))
+ /* open is exclusive wrt all other BLK_OPEN_WRITE opens to the device */
+ #define BLK_OPEN_RESTRICT_WRITES ((__force blk_mode_t)(1 << 5))
++/* return partition scanning errors */
++#define BLK_OPEN_STRICT_SCAN ((__force blk_mode_t)(1 << 6))
+
+ struct gendisk {
+ /*
+diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h
+index e5ee2c694401e..3f4b4ac527ca2 100644
+--- a/include/linux/bootconfig.h
++++ b/include/linux/bootconfig.h
+@@ -288,7 +288,12 @@ int __init xbc_init(const char *buf, size_t size, const char **emsg, int *epos);
+ int __init xbc_get_info(int *node_size, size_t *data_size);
+
+ /* XBC cleanup data structures */
+-void __init xbc_exit(void);
++void __init _xbc_exit(bool early);
++
++static inline void xbc_exit(void)
++{
++ _xbc_exit(false);
++}
+
+ /* XBC embedded bootconfig data in kernel */
+ #ifdef CONFIG_BOOT_CONFIG_EMBED
+diff --git a/include/linux/gpio/property.h b/include/linux/gpio/property.h
+index 6c75c8bd44a0b..1a14e239221f7 100644
+--- a/include/linux/gpio/property.h
++++ b/include/linux/gpio/property.h
+@@ -2,7 +2,6 @@
+ #ifndef __LINUX_GPIO_PROPERTY_H
+ #define __LINUX_GPIO_PROPERTY_H
+
+-#include <dt-bindings/gpio/gpio.h> /* for GPIO_* flags */
+ #include <linux/property.h>
+
+ #define PROPERTY_ENTRY_GPIO(_name_, _chip_node_, _idx_, _flags_) \
+diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
+index 66828dfc6e74e..f0c6bf9828327 100644
+--- a/include/linux/shmem_fs.h
++++ b/include/linux/shmem_fs.h
+@@ -114,8 +114,17 @@ extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
+ extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end);
+ int shmem_unuse(unsigned int type);
+
++#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ extern bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force,
+ struct mm_struct *mm, unsigned long vm_flags);
++#else
++static __always_inline bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force,
++ struct mm_struct *mm, unsigned long vm_flags)
++{
++ return false;
++}
++#endif
++
+ #ifdef CONFIG_SHMEM
+ extern unsigned long shmem_swap_usage(struct vm_area_struct *vma);
+ #else
+diff --git a/include/linux/swapops.h b/include/linux/swapops.h
+index bff1e8d97de0e..925c84653af5e 100644
+--- a/include/linux/swapops.h
++++ b/include/linux/swapops.h
+@@ -390,6 +390,35 @@ static inline bool is_migration_entry_dirty(swp_entry_t entry)
+ }
+ #endif /* CONFIG_MIGRATION */
+
++#ifdef CONFIG_MEMORY_FAILURE
++
++/*
++ * Support for hardware poisoned pages
++ */
++static inline swp_entry_t make_hwpoison_entry(struct page *page)
++{
++ BUG_ON(!PageLocked(page));
++ return swp_entry(SWP_HWPOISON, page_to_pfn(page));
++}
++
++static inline int is_hwpoison_entry(swp_entry_t entry)
++{
++ return swp_type(entry) == SWP_HWPOISON;
++}
++
++#else
++
++static inline swp_entry_t make_hwpoison_entry(struct page *page)
++{
++ return swp_entry(0, 0);
++}
++
++static inline int is_hwpoison_entry(swp_entry_t swp)
++{
++ return 0;
++}
++#endif
++
+ typedef unsigned long pte_marker;
+
+ #define PTE_MARKER_UFFD_WP BIT(0)
+@@ -470,8 +499,9 @@ static inline struct page *pfn_swap_entry_to_page(swp_entry_t entry)
+
+ /*
+ * A pfn swap entry is a special type of swap entry that always has a pfn stored
+- * in the swap offset. They are used to represent unaddressable device memory
+- * and to restrict access to a page undergoing migration.
++ * in the swap offset. They can either be used to represent unaddressable device
++ * memory, to restrict access to a page undergoing migration or to represent a
++ * pfn which has been hwpoisoned and unmapped.
+ */
+ static inline bool is_pfn_swap_entry(swp_entry_t entry)
+ {
+@@ -479,7 +509,7 @@ static inline bool is_pfn_swap_entry(swp_entry_t entry)
+ BUILD_BUG_ON(SWP_TYPE_SHIFT < SWP_PFN_BITS);
+
+ return is_migration_entry(entry) || is_device_private_entry(entry) ||
+- is_device_exclusive_entry(entry);
++ is_device_exclusive_entry(entry) || is_hwpoison_entry(entry);
+ }
+
+ struct page_vma_mapped_walk;
+@@ -548,35 +578,6 @@ static inline int is_pmd_migration_entry(pmd_t pmd)
+ }
+ #endif /* CONFIG_ARCH_ENABLE_THP_MIGRATION */
+
+-#ifdef CONFIG_MEMORY_FAILURE
+-
+-/*
+- * Support for hardware poisoned pages
+- */
+-static inline swp_entry_t make_hwpoison_entry(struct page *page)
+-{
+- BUG_ON(!PageLocked(page));
+- return swp_entry(SWP_HWPOISON, page_to_pfn(page));
+-}
+-
+-static inline int is_hwpoison_entry(swp_entry_t entry)
+-{
+- return swp_type(entry) == SWP_HWPOISON;
+-}
+-
+-#else
+-
+-static inline swp_entry_t make_hwpoison_entry(struct page *page)
+-{
+- return swp_entry(0, 0);
+-}
+-
+-static inline int is_hwpoison_entry(swp_entry_t swp)
+-{
+- return 0;
+-}
+-#endif
+-
+ static inline int non_swap_entry(swp_entry_t entry)
+ {
+ return swp_type(entry) >= MAX_SWAPFILES;
+diff --git a/include/linux/udp.h b/include/linux/udp.h
+index 94e63b2695406..00790bb5cbde6 100644
+--- a/include/linux/udp.h
++++ b/include/linux/udp.h
+@@ -105,7 +105,7 @@ struct udp_sock {
+ #define udp_assign_bit(nr, sk, val) \
+ assign_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags, val)
+
+-#define UDP_MAX_SEGMENTS (1 << 6UL)
++#define UDP_MAX_SEGMENTS (1 << 7UL)
+
+ #define udp_sk(ptr) container_of_const(ptr, struct udp_sock, inet.sk)
+
+diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
+index a763dd327c6ea..9abb7ee40d72f 100644
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -336,7 +336,7 @@ int nf_flow_rule_route_ipv6(struct net *net, struct flow_offload *flow,
+ int nf_flow_table_offload_init(void);
+ void nf_flow_table_offload_exit(void);
+
+-static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
++static inline __be16 __nf_flow_pppoe_proto(const struct sk_buff *skb)
+ {
+ __be16 proto;
+
+@@ -352,6 +352,16 @@ static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb)
+ return 0;
+ }
+
++static inline bool nf_flow_pppoe_proto(struct sk_buff *skb, __be16 *inner_proto)
++{
++ if (!pskb_may_pull(skb, PPPOE_SES_HLEN))
++ return false;
++
++ *inner_proto = __nf_flow_pppoe_proto(skb);
++
++ return true;
++}
++
+ #define NF_FLOW_TABLE_STAT_INC(net, count) __this_cpu_inc((net)->ft.stat->count)
+ #define NF_FLOW_TABLE_STAT_DEC(net, count) __this_cpu_dec((net)->ft.stat->count)
+ #define NF_FLOW_TABLE_STAT_INC_ATOMIC(net, count) \
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index 510244cc0f8f0..1cf9cb0f0a975 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -307,9 +307,23 @@ static inline void *nft_elem_priv_cast(const struct nft_elem_priv *priv)
+ return (void *)priv;
+ }
+
++
++/**
++ * enum nft_iter_type - nftables set iterator type
++ *
++ * @NFT_ITER_READ: read-only iteration over set elements
++ * @NFT_ITER_UPDATE: iteration under mutex to update set element state
++ */
++enum nft_iter_type {
++ NFT_ITER_UNSPEC,
++ NFT_ITER_READ,
++ NFT_ITER_UPDATE,
++};
++
+ struct nft_set;
+ struct nft_set_iter {
+ u8 genmask;
++ enum nft_iter_type type:8;
+ unsigned int count;
+ unsigned int skip;
+ int err;
+diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
+index cefe0c4bdae34..41ca14e81d55f 100644
+--- a/include/net/sch_generic.h
++++ b/include/net/sch_generic.h
+@@ -117,6 +117,7 @@ struct Qdisc {
+ struct qdisc_skb_head q;
+ struct gnet_stats_basic_sync bstats;
+ struct gnet_stats_queue qstats;
++ int owner;
+ unsigned long state;
+ unsigned long state2; /* must be written under qdisc spinlock */
+ struct Qdisc *next_sched;
+diff --git a/include/trace/events/rpcgss.h b/include/trace/events/rpcgss.h
+index ba2d96a1bc2f9..f50fcafc69de2 100644
+--- a/include/trace/events/rpcgss.h
++++ b/include/trace/events/rpcgss.h
+@@ -609,7 +609,7 @@ TRACE_EVENT(rpcgss_context,
+ __field(unsigned int, timeout)
+ __field(u32, window_size)
+ __field(int, len)
+- __string(acceptor, data)
++ __string_len(acceptor, data, len)
+ ),
+
+ TP_fast_assign(
+@@ -618,7 +618,7 @@ TRACE_EVENT(rpcgss_context,
+ __entry->timeout = timeout;
+ __entry->window_size = window_size;
+ __entry->len = len;
+- strncpy(__get_str(acceptor), data, len);
++ __assign_str(acceptor, data);
+ ),
+
+ TP_printk("win_size=%u expiry=%lu now=%lu timeout=%u acceptor=%.*s",
+diff --git a/init/main.c b/init/main.c
+index 98fdd93d79a5c..b06bb72a288a9 100644
+--- a/init/main.c
++++ b/init/main.c
+@@ -635,6 +635,8 @@ static void __init setup_command_line(char *command_line)
+ if (!saved_command_line)
+ panic("%s: Failed to allocate %zu bytes\n", __func__, len + ilen);
+
++ len = xlen + strlen(command_line) + 1;
++
+ static_command_line = memblock_alloc(len, SMP_CACHE_BYTES);
+ if (!static_command_line)
+ panic("%s: Failed to allocate %zu bytes\n", __func__, len);
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index 3fc792dfc6ae7..dc0235ff472d3 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -2610,19 +2610,6 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
+ if (__io_cqring_events_user(ctx) >= min_events)
+ return 0;
+
+- if (sig) {
+-#ifdef CONFIG_COMPAT
+- if (in_compat_syscall())
+- ret = set_compat_user_sigmask((const compat_sigset_t __user *)sig,
+- sigsz);
+- else
+-#endif
+- ret = set_user_sigmask(sig, sigsz);
+-
+- if (ret)
+- return ret;
+- }
+-
+ init_waitqueue_func_entry(&iowq.wq, io_wake_function);
+ iowq.wq.private = current;
+ INIT_LIST_HEAD(&iowq.wq.entry);
+@@ -2639,6 +2626,19 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events,
+ iowq.timeout = ktime_add_ns(timespec64_to_ktime(ts), ktime_get_ns());
+ }
+
++ if (sig) {
++#ifdef CONFIG_COMPAT
++ if (in_compat_syscall())
++ ret = set_compat_user_sigmask((const compat_sigset_t __user *)sig,
++ sigsz);
++ else
++#endif
++ ret = set_user_sigmask(sig, sigsz);
++
++ if (ret)
++ return ret;
++ }
++
+ trace_io_uring_cqring_wait(ctx, min_events);
+ do {
+ int nr_wait = (int) iowq.cq_tail - READ_ONCE(ctx->rings->cq.tail);
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 0d944e92a43ff..3b9cdb42e757c 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -712,6 +712,23 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
+ } else if (anon_vma_fork(tmp, mpnt))
+ goto fail_nomem_anon_vma_fork;
+ vm_flags_clear(tmp, VM_LOCKED_MASK);
++ /*
++ * Copy/update hugetlb private vma information.
++ */
++ if (is_vm_hugetlb_page(tmp))
++ hugetlb_dup_vma_private(tmp);
++
++ /*
++ * Link the vma into the MT. After using __mt_dup(), memory
++ * allocation is not necessary here, so it cannot fail.
++ */
++ vma_iter_bulk_store(&vmi, tmp);
++
++ mm->map_count++;
++
++ if (tmp->vm_ops && tmp->vm_ops->open)
++ tmp->vm_ops->open(tmp);
++
+ file = tmp->vm_file;
+ if (file) {
+ struct address_space *mapping = file->f_mapping;
+@@ -728,25 +745,9 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
+ i_mmap_unlock_write(mapping);
+ }
+
+- /*
+- * Copy/update hugetlb private vma information.
+- */
+- if (is_vm_hugetlb_page(tmp))
+- hugetlb_dup_vma_private(tmp);
+-
+- /*
+- * Link the vma into the MT. After using __mt_dup(), memory
+- * allocation is not necessary here, so it cannot fail.
+- */
+- vma_iter_bulk_store(&vmi, tmp);
+-
+- mm->map_count++;
+ if (!(tmp->vm_flags & VM_WIPEONFORK))
+ retval = copy_page_range(tmp, mpnt);
+
+- if (tmp->vm_ops && tmp->vm_ops->open)
+- tmp->vm_ops->open(tmp);
+-
+ if (retval) {
+ mpnt = vma_next(&vmi);
+ goto loop_out;
+diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
+index 001fe047bd5d8..8c817d0a92f3e 100644
+--- a/kernel/sched/sched.h
++++ b/kernel/sched/sched.h
+@@ -79,6 +79,8 @@
+ # include <asm/paravirt_api_clock.h>
+ #endif
+
++#include <asm/barrier.h>
++
+ #include "cpupri.h"
+ #include "cpudeadline.h"
+
+@@ -3445,13 +3447,19 @@ static inline void switch_mm_cid(struct rq *rq,
+ * between rq->curr store and load of {prev,next}->mm->pcpu_cid[cpu].
+ * Provide it here.
+ */
+- if (!prev->mm) // from kernel
++ if (!prev->mm) { // from kernel
+ smp_mb();
+- /*
+- * user -> user transition guarantees a memory barrier through
+- * switch_mm() when current->mm changes. If current->mm is
+- * unchanged, no barrier is needed.
+- */
++ } else { // from user
++ /*
++ * user->user transition relies on an implicit
++ * memory barrier in switch_mm() when
++ * current->mm changes. If the architecture
++ * switch_mm() does not have an implicit memory
++ * barrier, it is emitted here. If current->mm
++ * is unchanged, no barrier is needed.
++ */
++ smp_mb__after_switch_mm();
++ }
+ }
+ if (prev->mm_cid_active) {
+ mm_cid_snapshot_time(rq, prev->mm);
+diff --git a/lib/bootconfig.c b/lib/bootconfig.c
+index c59d26068a640..8841554432d5b 100644
+--- a/lib/bootconfig.c
++++ b/lib/bootconfig.c
+@@ -61,9 +61,12 @@ static inline void * __init xbc_alloc_mem(size_t size)
+ return memblock_alloc(size, SMP_CACHE_BYTES);
+ }
+
+-static inline void __init xbc_free_mem(void *addr, size_t size)
++static inline void __init xbc_free_mem(void *addr, size_t size, bool early)
+ {
+- memblock_free(addr, size);
++ if (early)
++ memblock_free(addr, size);
++ else if (addr)
++ memblock_free_late(__pa(addr), size);
+ }
+
+ #else /* !__KERNEL__ */
+@@ -73,7 +76,7 @@ static inline void *xbc_alloc_mem(size_t size)
+ return malloc(size);
+ }
+
+-static inline void xbc_free_mem(void *addr, size_t size)
++static inline void xbc_free_mem(void *addr, size_t size, bool early)
+ {
+ free(addr);
+ }
+@@ -904,13 +907,13 @@ static int __init xbc_parse_tree(void)
+ * If you need to reuse xbc_init() with new boot config, you can
+ * use this.
+ */
+-void __init xbc_exit(void)
++void __init _xbc_exit(bool early)
+ {
+- xbc_free_mem(xbc_data, xbc_data_size);
++ xbc_free_mem(xbc_data, xbc_data_size, early);
+ xbc_data = NULL;
+ xbc_data_size = 0;
+ xbc_node_num = 0;
+- xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX);
++ xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX, early);
+ xbc_nodes = NULL;
+ brace_index = 0;
+ }
+@@ -963,7 +966,7 @@ int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos)
+ if (!xbc_nodes) {
+ if (emsg)
+ *emsg = "Failed to allocate bootconfig nodes";
+- xbc_exit();
++ _xbc_exit(true);
+ return -ENOMEM;
+ }
+ memset(xbc_nodes, 0, sizeof(struct xbc_node) * XBC_NODE_MAX);
+@@ -977,7 +980,7 @@ int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos)
+ *epos = xbc_err_pos;
+ if (emsg)
+ *emsg = xbc_err_msg;
+- xbc_exit();
++ _xbc_exit(true);
+ } else
+ ret = xbc_node_num;
+
+diff --git a/mm/gup.c b/mm/gup.c
+index df83182ec72d5..f6d55635742f5 100644
+--- a/mm/gup.c
++++ b/mm/gup.c
+@@ -1206,6 +1206,22 @@ static long __get_user_pages(struct mm_struct *mm,
+
+ /* first iteration or cross vma bound */
+ if (!vma || start >= vma->vm_end) {
++ /*
++ * MADV_POPULATE_(READ|WRITE) wants to handle VMA
++ * lookups+error reporting differently.
++ */
++ if (gup_flags & FOLL_MADV_POPULATE) {
++ vma = vma_lookup(mm, start);
++ if (!vma) {
++ ret = -ENOMEM;
++ goto out;
++ }
++ if (check_vma_flags(vma, gup_flags)) {
++ ret = -EINVAL;
++ goto out;
++ }
++ goto retry;
++ }
+ vma = gup_vma_lookup(mm, start);
+ if (!vma && in_gate_area(mm, start)) {
+ ret = get_gate_page(mm, start & PAGE_MASK,
+@@ -1683,35 +1699,35 @@ long populate_vma_page_range(struct vm_area_struct *vma,
+ }
+
+ /*
+- * faultin_vma_page_range() - populate (prefault) page tables inside the
+- * given VMA range readable/writable
++ * faultin_page_range() - populate (prefault) page tables inside the
++ * given range readable/writable
+ *
+ * This takes care of mlocking the pages, too, if VM_LOCKED is set.
+ *
+- * @vma: target vma
++ * @mm: the mm to populate page tables in
+ * @start: start address
+ * @end: end address
+ * @write: whether to prefault readable or writable
+ * @locked: whether the mmap_lock is still held
+ *
+- * Returns either number of processed pages in the vma, or a negative error
+- * code on error (see __get_user_pages()).
++ * Returns either number of processed pages in the MM, or a negative error
++ * code on error (see __get_user_pages()). Note that this function reports
++ * errors related to VMAs, such as incompatible mappings, as expected by
++ * MADV_POPULATE_(READ|WRITE).
+ *
+- * vma->vm_mm->mmap_lock must be held. The range must be page-aligned and
+- * covered by the VMA. If it's released, *@locked will be set to 0.
++ * The range must be page-aligned.
++ *
++ * mm->mmap_lock must be held. If it's released, *@locked will be set to 0.
+ */
+-long faultin_vma_page_range(struct vm_area_struct *vma, unsigned long start,
+- unsigned long end, bool write, int *locked)
++long faultin_page_range(struct mm_struct *mm, unsigned long start,
++ unsigned long end, bool write, int *locked)
+ {
+- struct mm_struct *mm = vma->vm_mm;
+ unsigned long nr_pages = (end - start) / PAGE_SIZE;
+ int gup_flags;
+ long ret;
+
+ VM_BUG_ON(!PAGE_ALIGNED(start));
+ VM_BUG_ON(!PAGE_ALIGNED(end));
+- VM_BUG_ON_VMA(start < vma->vm_start, vma);
+- VM_BUG_ON_VMA(end > vma->vm_end, vma);
+ mmap_assert_locked(mm);
+
+ /*
+@@ -1723,19 +1739,13 @@ long faultin_vma_page_range(struct vm_area_struct *vma, unsigned long start,
+ * a poisoned page.
+ * !FOLL_FORCE: Require proper access permissions.
+ */
+- gup_flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_UNLOCKABLE;
++ gup_flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_UNLOCKABLE |
++ FOLL_MADV_POPULATE;
+ if (write)
+ gup_flags |= FOLL_WRITE;
+
+- /*
+- * We want to report -EINVAL instead of -EFAULT for any permission
+- * problems or incompatible mappings.
+- */
+- if (check_vma_flags(vma, gup_flags))
+- return -EINVAL;
+-
+- ret = __get_user_pages(mm, start, nr_pages, gup_flags,
+- NULL, locked);
++ ret = __get_user_pages_locked(mm, start, nr_pages, NULL, locked,
++ gup_flags);
+ lru_add_drain();
+ return ret;
+ }
+diff --git a/mm/huge_memory.c b/mm/huge_memory.c
+index 94c958f7ebb50..6790f93fda45b 100644
+--- a/mm/huge_memory.c
++++ b/mm/huge_memory.c
+@@ -2244,9 +2244,6 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm
+ goto unlock_ptls;
+ }
+
+- folio_move_anon_rmap(src_folio, dst_vma);
+- WRITE_ONCE(src_folio->index, linear_page_index(dst_vma, dst_addr));
+-
+ src_pmdval = pmdp_huge_clear_flush(src_vma, src_addr, src_pmd);
+ /* Folio got pinned from under us. Put it back and fail the move. */
+ if (folio_maybe_dma_pinned(src_folio)) {
+@@ -2255,6 +2252,9 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm
+ goto unlock_ptls;
+ }
+
++ folio_move_anon_rmap(src_folio, dst_vma);
++ WRITE_ONCE(src_folio->index, linear_page_index(dst_vma, dst_addr));
++
+ _dst_pmd = mk_huge_pmd(&src_folio->page, dst_vma->vm_page_prot);
+ /* Follow mremap() behavior and treat the entry dirty after the move */
+ _dst_pmd = pmd_mkwrite(pmd_mkdirty(_dst_pmd), dst_vma);
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index ed1581b670d42..e5e3df1d3b874 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -6943,9 +6943,13 @@ long hugetlb_change_protection(struct vm_area_struct *vma,
+ if (!pte_same(pte, newpte))
+ set_huge_pte_at(mm, address, ptep, newpte, psize);
+ } else if (unlikely(is_pte_marker(pte))) {
+- /* No other markers apply for now. */
+- WARN_ON_ONCE(!pte_marker_uffd_wp(pte));
+- if (uffd_wp_resolve)
++ /*
++ * Do nothing on a poison marker; page is
++ * corrupted, permissons do not apply. Here
++ * pte_marker_uffd_wp()==true implies !poison
++ * because they're mutual exclusive.
++ */
++ if (pte_marker_uffd_wp(pte) && uffd_wp_resolve)
+ /* Safe to modify directly (non-present->none). */
+ huge_pte_clear(mm, address, ptep, psize);
+ } else if (!huge_pte_none(pte)) {
+diff --git a/mm/internal.h b/mm/internal.h
+index f309a010d50fb..c3f3e0f191151 100644
+--- a/mm/internal.h
++++ b/mm/internal.h
+@@ -590,9 +590,8 @@ struct anon_vma *folio_anon_vma(struct folio *folio);
+ void unmap_mapping_folio(struct folio *folio);
+ extern long populate_vma_page_range(struct vm_area_struct *vma,
+ unsigned long start, unsigned long end, int *locked);
+-extern long faultin_vma_page_range(struct vm_area_struct *vma,
+- unsigned long start, unsigned long end,
+- bool write, int *locked);
++extern long faultin_page_range(struct mm_struct *mm, unsigned long start,
++ unsigned long end, bool write, int *locked);
+ extern bool mlock_future_ok(struct mm_struct *mm, unsigned long flags,
+ unsigned long bytes);
+
+@@ -1031,10 +1030,13 @@ enum {
+ FOLL_FAST_ONLY = 1 << 20,
+ /* allow unlocking the mmap lock */
+ FOLL_UNLOCKABLE = 1 << 21,
++ /* VMA lookup+checks compatible with MADV_POPULATE_(READ|WRITE) */
++ FOLL_MADV_POPULATE = 1 << 22,
+ };
+
+ #define INTERNAL_GUP_FLAGS (FOLL_TOUCH | FOLL_TRIED | FOLL_REMOTE | FOLL_PIN | \
+- FOLL_FAST_ONLY | FOLL_UNLOCKABLE)
++ FOLL_FAST_ONLY | FOLL_UNLOCKABLE | \
++ FOLL_MADV_POPULATE)
+
+ /*
+ * Indicates for which pages that are write-protected in the page table,
+diff --git a/mm/madvise.c b/mm/madvise.c
+index cfa5e72882611..f2c818af0b66e 100644
+--- a/mm/madvise.c
++++ b/mm/madvise.c
+@@ -908,27 +908,14 @@ static long madvise_populate(struct vm_area_struct *vma,
+ {
+ const bool write = behavior == MADV_POPULATE_WRITE;
+ struct mm_struct *mm = vma->vm_mm;
+- unsigned long tmp_end;
+ int locked = 1;
+ long pages;
+
+ *prev = vma;
+
+ while (start < end) {
+- /*
+- * We might have temporarily dropped the lock. For example,
+- * our VMA might have been split.
+- */
+- if (!vma || start >= vma->vm_end) {
+- vma = vma_lookup(mm, start);
+- if (!vma)
+- return -ENOMEM;
+- }
+-
+- tmp_end = min_t(unsigned long, end, vma->vm_end);
+ /* Populate (prefault) page tables readable/writable. */
+- pages = faultin_vma_page_range(vma, start, tmp_end, write,
+- &locked);
++ pages = faultin_page_range(mm, start, end, write, &locked);
+ if (!locked) {
+ mmap_read_lock(mm);
+ locked = 1;
+@@ -949,7 +936,7 @@ static long madvise_populate(struct vm_area_struct *vma,
+ pr_warn_once("%s: unhandled return value: %ld\n",
+ __func__, pages);
+ fallthrough;
+- case -ENOMEM:
++ case -ENOMEM: /* No VMA or out of memory. */
+ return -ENOMEM;
+ }
+ }
+diff --git a/mm/memory-failure.c b/mm/memory-failure.c
+index 9349948f1abfd..9e62a00b46dde 100644
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -154,11 +154,23 @@ static int __page_handle_poison(struct page *page)
+ {
+ int ret;
+
+- zone_pcp_disable(page_zone(page));
++ /*
++ * zone_pcp_disable() can't be used here. It will
++ * hold pcp_batch_high_lock and dissolve_free_huge_page() might hold
++ * cpu_hotplug_lock via static_key_slow_dec() when hugetlb vmemmap
++ * optimization is enabled. This will break current lock dependency
++ * chain and leads to deadlock.
++ * Disabling pcp before dissolving the page was a deterministic
++ * approach because we made sure that those pages cannot end up in any
++ * PCP list. Draining PCP lists expels those pages to the buddy system,
++ * but nothing guarantees that those pages do not get back to a PCP
++ * queue if we need to refill those.
++ */
+ ret = dissolve_free_huge_page(page);
+- if (!ret)
++ if (!ret) {
++ drain_all_pages(page_zone(page));
+ ret = take_page_off_buddy(page);
+- zone_pcp_enable(page_zone(page));
++ }
+
+ return ret;
+ }
+diff --git a/mm/shmem.c b/mm/shmem.c
+index 791a6dc163244..5853f3ae36e53 100644
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -742,12 +742,6 @@ static long shmem_unused_huge_count(struct super_block *sb,
+
+ #define shmem_huge SHMEM_HUGE_DENY
+
+-bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force,
+- struct mm_struct *mm, unsigned long vm_flags)
+-{
+- return false;
+-}
+-
+ static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo,
+ struct shrink_control *sc, unsigned long nr_to_split)
+ {
+diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
+index f21097e734827..ceaa5a89b947f 100644
+--- a/net/bridge/br_input.c
++++ b/net/bridge/br_input.c
+@@ -30,7 +30,7 @@ br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb)
+ return netif_receive_skb(skb);
+ }
+
+-static int br_pass_frame_up(struct sk_buff *skb)
++static int br_pass_frame_up(struct sk_buff *skb, bool promisc)
+ {
+ struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev;
+ struct net_bridge *br = netdev_priv(brdev);
+@@ -65,6 +65,8 @@ static int br_pass_frame_up(struct sk_buff *skb)
+ br_multicast_count(br, NULL, skb, br_multicast_igmp_type(skb),
+ BR_MCAST_DIR_TX);
+
++ BR_INPUT_SKB_CB(skb)->promisc = promisc;
++
+ return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN,
+ dev_net(indev), NULL, skb, indev, NULL,
+ br_netif_receive_skb);
+@@ -82,6 +84,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
+ struct net_bridge_mcast *brmctx;
+ struct net_bridge_vlan *vlan;
+ struct net_bridge *br;
++ bool promisc;
+ u16 vid = 0;
+ u8 state;
+
+@@ -137,7 +140,9 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
+ if (p->flags & BR_LEARNING)
+ br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, 0);
+
+- local_rcv = !!(br->dev->flags & IFF_PROMISC);
++ promisc = !!(br->dev->flags & IFF_PROMISC);
++ local_rcv = promisc;
++
+ if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) {
+ /* by definition the broadcast is also a multicast address */
+ if (is_broadcast_ether_addr(eth_hdr(skb)->h_dest)) {
+@@ -200,7 +205,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
+ unsigned long now = jiffies;
+
+ if (test_bit(BR_FDB_LOCAL, &dst->flags))
+- return br_pass_frame_up(skb);
++ return br_pass_frame_up(skb, false);
+
+ if (now != dst->used)
+ dst->used = now;
+@@ -213,7 +218,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
+ }
+
+ if (local_rcv)
+- return br_pass_frame_up(skb);
++ return br_pass_frame_up(skb, promisc);
+
+ out:
+ return 0;
+@@ -386,6 +391,8 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
+ goto forward;
+ }
+
++ BR_INPUT_SKB_CB(skb)->promisc = false;
++
+ /* The else clause should be hit when nf_hook():
+ * - returns < 0 (drop/error)
+ * - returns = 0 (stolen/nf_queue)
+diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
+index 35e10c5a766d5..22e35623c148a 100644
+--- a/net/bridge/br_netfilter_hooks.c
++++ b/net/bridge/br_netfilter_hooks.c
+@@ -600,11 +600,17 @@ static unsigned int br_nf_local_in(void *priv,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state)
+ {
++ bool promisc = BR_INPUT_SKB_CB(skb)->promisc;
+ struct nf_conntrack *nfct = skb_nfct(skb);
+ const struct nf_ct_hook *ct_hook;
+ struct nf_conn *ct;
+ int ret;
+
++ if (promisc) {
++ nf_reset_ct(skb);
++ return NF_ACCEPT;
++ }
++
+ if (!nfct || skb->pkt_type == PACKET_HOST)
+ return NF_ACCEPT;
+
+diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
+index 86ea5e6689b5c..d4bedc87b1d8f 100644
+--- a/net/bridge/br_private.h
++++ b/net/bridge/br_private.h
+@@ -589,6 +589,7 @@ struct br_input_skb_cb {
+ #endif
+ u8 proxyarp_replied:1;
+ u8 src_port_isolated:1;
++ u8 promisc:1;
+ #ifdef CONFIG_BRIDGE_VLAN_FILTERING
+ u8 vlan_filtered:1;
+ #endif
+diff --git a/net/bridge/netfilter/nf_conntrack_bridge.c b/net/bridge/netfilter/nf_conntrack_bridge.c
+index 6f877e31709ba..c3c51b9a68265 100644
+--- a/net/bridge/netfilter/nf_conntrack_bridge.c
++++ b/net/bridge/netfilter/nf_conntrack_bridge.c
+@@ -294,18 +294,24 @@ static unsigned int nf_ct_bridge_pre(void *priv, struct sk_buff *skb,
+ static unsigned int nf_ct_bridge_in(void *priv, struct sk_buff *skb,
+ const struct nf_hook_state *state)
+ {
+- enum ip_conntrack_info ctinfo;
++ bool promisc = BR_INPUT_SKB_CB(skb)->promisc;
++ struct nf_conntrack *nfct = skb_nfct(skb);
+ struct nf_conn *ct;
+
+- if (skb->pkt_type == PACKET_HOST)
++ if (promisc) {
++ nf_reset_ct(skb);
++ return NF_ACCEPT;
++ }
++
++ if (!nfct || skb->pkt_type == PACKET_HOST)
+ return NF_ACCEPT;
+
+ /* nf_conntrack_confirm() cannot handle concurrent clones,
+ * this happens for broad/multicast frames with e.g. macvlan on top
+ * of the bridge device.
+ */
+- ct = nf_ct_get(skb, &ctinfo);
+- if (!ct || nf_ct_is_confirmed(ct) || nf_ct_is_template(ct))
++ ct = container_of(nfct, struct nf_conn, ct_general);
++ if (nf_ct_is_confirmed(ct) || nf_ct_is_template(ct))
+ return NF_ACCEPT;
+
+ /* let inet prerouting call conntrack again */
+diff --git a/net/core/dev.c b/net/core/dev.c
+index c9b8412f1c9d3..c365aa06f886f 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -3791,6 +3791,10 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
+ return rc;
+ }
+
++ if (unlikely(READ_ONCE(q->owner) == smp_processor_id())) {
++ kfree_skb_reason(skb, SKB_DROP_REASON_TC_RECLASSIFY_LOOP);
++ return NET_XMIT_DROP;
++ }
+ /*
+ * Heuristic to force contended enqueues to serialize on a
+ * separate lock before trying to get qdisc main lock.
+@@ -3830,7 +3834,9 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
+ qdisc_run_end(q);
+ rc = NET_XMIT_SUCCESS;
+ } else {
++ WRITE_ONCE(q->owner, smp_processor_id());
+ rc = dev_qdisc_enqueue(skb, q, &to_free, txq);
++ WRITE_ONCE(q->owner, -1);
+ if (qdisc_run_begin(q)) {
+ if (unlikely(contended)) {
+ spin_unlock(&q->busylock);
+diff --git a/net/netfilter/nf_flow_table_inet.c b/net/netfilter/nf_flow_table_inet.c
+index 9505f9d188ff2..6eef15648b7b0 100644
+--- a/net/netfilter/nf_flow_table_inet.c
++++ b/net/netfilter/nf_flow_table_inet.c
+@@ -21,7 +21,8 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb,
+ proto = veth->h_vlan_encapsulated_proto;
+ break;
+ case htons(ETH_P_PPP_SES):
+- proto = nf_flow_pppoe_proto(skb);
++ if (!nf_flow_pppoe_proto(skb, &proto))
++ return NF_ACCEPT;
+ break;
+ default:
+ proto = skb->protocol;
+diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c
+index e45fade764096..5383bed3d3e00 100644
+--- a/net/netfilter/nf_flow_table_ip.c
++++ b/net/netfilter/nf_flow_table_ip.c
+@@ -157,7 +157,7 @@ static void nf_flow_tuple_encap(struct sk_buff *skb,
+ tuple->encap[i].proto = skb->protocol;
+ break;
+ case htons(ETH_P_PPP_SES):
+- phdr = (struct pppoe_hdr *)skb_mac_header(skb);
++ phdr = (struct pppoe_hdr *)skb_network_header(skb);
+ tuple->encap[i].id = ntohs(phdr->sid);
+ tuple->encap[i].proto = skb->protocol;
+ break;
+@@ -273,10 +273,11 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
+ return NF_STOLEN;
+ }
+
+-static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
++static bool nf_flow_skb_encap_protocol(struct sk_buff *skb, __be16 proto,
+ u32 *offset)
+ {
+ struct vlan_ethhdr *veth;
++ __be16 inner_proto;
+
+ switch (skb->protocol) {
+ case htons(ETH_P_8021Q):
+@@ -287,7 +288,8 @@ static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto,
+ }
+ break;
+ case htons(ETH_P_PPP_SES):
+- if (nf_flow_pppoe_proto(skb) == proto) {
++ if (nf_flow_pppoe_proto(skb, &inner_proto) &&
++ inner_proto == proto) {
+ *offset += PPPOE_SES_HLEN;
+ return true;
+ }
+@@ -316,7 +318,7 @@ static void nf_flow_encap_pop(struct sk_buff *skb,
+ skb_reset_network_header(skb);
+ break;
+ case htons(ETH_P_PPP_SES):
+- skb->protocol = nf_flow_pppoe_proto(skb);
++ skb->protocol = __nf_flow_pppoe_proto(skb);
+ skb_pull(skb, PPPOE_SES_HLEN);
+ skb_reset_network_header(skb);
+ break;
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 21581bae700c4..0e697e53a7902 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -594,6 +594,12 @@ static int nft_mapelem_deactivate(const struct nft_ctx *ctx,
+ const struct nft_set_iter *iter,
+ struct nft_elem_priv *elem_priv)
+ {
++ struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
++
++ if (!nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
++ nft_set_elem_change_active(ctx->net, set, ext);
+ nft_setelem_data_deactivate(ctx->net, set, elem_priv);
+
+ return 0;
+@@ -617,6 +623,7 @@ static void nft_map_catchall_deactivate(const struct nft_ctx *ctx,
+ if (!nft_set_elem_active(ext, genmask))
+ continue;
+
++ nft_set_elem_change_active(ctx->net, set, ext);
+ nft_setelem_data_deactivate(ctx->net, set, catchall->elem);
+ break;
+ }
+@@ -626,6 +633,7 @@ static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set)
+ {
+ struct nft_set_iter iter = {
+ .genmask = nft_genmask_next(ctx->net),
++ .type = NFT_ITER_UPDATE,
+ .fn = nft_mapelem_deactivate,
+ };
+
+@@ -3048,7 +3056,7 @@ static const struct nft_expr_type *__nft_expr_type_get(u8 family,
+ {
+ const struct nft_expr_type *type, *candidate = NULL;
+
+- list_for_each_entry(type, &nf_tables_expressions, list) {
++ list_for_each_entry_rcu(type, &nf_tables_expressions, list) {
+ if (!nla_strcmp(nla, type->name)) {
+ if (!type->family && !candidate)
+ candidate = type;
+@@ -3080,9 +3088,13 @@ static const struct nft_expr_type *nft_expr_type_get(struct net *net,
+ if (nla == NULL)
+ return ERR_PTR(-EINVAL);
+
++ rcu_read_lock();
+ type = __nft_expr_type_get(family, nla);
+- if (type != NULL && try_module_get(type->owner))
++ if (type != NULL && try_module_get(type->owner)) {
++ rcu_read_unlock();
+ return type;
++ }
++ rcu_read_unlock();
+
+ lockdep_nfnl_nft_mutex_not_held();
+ #ifdef CONFIG_MODULES
+@@ -3863,6 +3875,9 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
+ const struct nft_data *data;
+ int err;
+
++ if (!nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
+ if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
+ *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
+ return 0;
+@@ -3886,17 +3901,20 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set,
+
+ int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set)
+ {
+- u8 genmask = nft_genmask_next(ctx->net);
++ struct nft_set_iter dummy_iter = {
++ .genmask = nft_genmask_next(ctx->net),
++ };
+ struct nft_set_elem_catchall *catchall;
++
+ struct nft_set_ext *ext;
+ int ret = 0;
+
+ list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
+ ext = nft_set_elem_ext(set, catchall->elem);
+- if (!nft_set_elem_active(ext, genmask))
++ if (!nft_set_elem_active(ext, dummy_iter.genmask))
+ continue;
+
+- ret = nft_setelem_validate(ctx, set, NULL, catchall->elem);
++ ret = nft_setelem_validate(ctx, set, &dummy_iter, catchall->elem);
+ if (ret < 0)
+ return ret;
+ }
+@@ -5393,6 +5411,11 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
+ const struct nft_set_iter *iter,
+ struct nft_elem_priv *elem_priv)
+ {
++ const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
++
++ if (!nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
+ return nft_setelem_data_validate(ctx, set, elem_priv);
+ }
+
+@@ -5437,6 +5460,7 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
+ }
+
+ iter.genmask = nft_genmask_next(ctx->net);
++ iter.type = NFT_ITER_UPDATE;
+ iter.skip = 0;
+ iter.count = 0;
+ iter.err = 0;
+@@ -5484,6 +5508,13 @@ static int nft_mapelem_activate(const struct nft_ctx *ctx,
+ const struct nft_set_iter *iter,
+ struct nft_elem_priv *elem_priv)
+ {
++ struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
++
++ /* called from abort path, reverse check to undo changes. */
++ if (nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
++ nft_clear(ctx->net, ext);
+ nft_setelem_data_activate(ctx->net, set, elem_priv);
+
+ return 0;
+@@ -5501,6 +5532,7 @@ static void nft_map_catchall_activate(const struct nft_ctx *ctx,
+ if (!nft_set_elem_active(ext, genmask))
+ continue;
+
++ nft_clear(ctx->net, ext);
+ nft_setelem_data_activate(ctx->net, set, catchall->elem);
+ break;
+ }
+@@ -5510,6 +5542,7 @@ static void nft_map_activate(const struct nft_ctx *ctx, struct nft_set *set)
+ {
+ struct nft_set_iter iter = {
+ .genmask = nft_genmask_next(ctx->net),
++ .type = NFT_ITER_UPDATE,
+ .fn = nft_mapelem_activate,
+ };
+
+@@ -5774,6 +5807,9 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
+ const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
+ struct nft_set_dump_args *args;
+
++ if (!nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
+ if (nft_set_elem_expired(ext) || nft_set_elem_is_dead(ext))
+ return 0;
+
+@@ -5884,6 +5920,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
+ args.skb = skb;
+ args.reset = dump_ctx->reset;
+ args.iter.genmask = nft_genmask_cur(net);
++ args.iter.type = NFT_ITER_READ;
+ args.iter.skip = cb->args[0];
+ args.iter.count = 0;
+ args.iter.err = 0;
+@@ -6623,7 +6660,7 @@ static void nft_setelem_activate(struct net *net, struct nft_set *set,
+ struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
+
+ if (nft_setelem_is_catchall(set, elem_priv)) {
+- nft_set_elem_change_active(net, set, ext);
++ nft_clear(net, ext);
+ } else {
+ set->ops->activate(net, set, elem_priv);
+ }
+@@ -7182,6 +7219,16 @@ void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
+ }
+ }
+
++static int nft_setelem_active_next(const struct net *net,
++ const struct nft_set *set,
++ struct nft_elem_priv *elem_priv)
++{
++ const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
++ u8 genmask = nft_genmask_next(net);
++
++ return nft_set_elem_active(ext, genmask);
++}
++
+ static void nft_setelem_data_activate(const struct net *net,
+ const struct nft_set *set,
+ struct nft_elem_priv *elem_priv)
+@@ -7305,8 +7352,12 @@ static int nft_setelem_flush(const struct nft_ctx *ctx,
+ const struct nft_set_iter *iter,
+ struct nft_elem_priv *elem_priv)
+ {
++ const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
+ struct nft_trans *trans;
+
++ if (!nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
+ trans = nft_trans_alloc_gfp(ctx, NFT_MSG_DELSETELEM,
+ sizeof(struct nft_trans_elem), GFP_ATOMIC);
+ if (!trans)
+@@ -7368,6 +7419,7 @@ static int nft_set_flush(struct nft_ctx *ctx, struct nft_set *set, u8 genmask)
+ {
+ struct nft_set_iter iter = {
+ .genmask = genmask,
++ .type = NFT_ITER_UPDATE,
+ .fn = nft_setelem_flush,
+ };
+
+@@ -7603,7 +7655,7 @@ static const struct nft_object_type *__nft_obj_type_get(u32 objtype, u8 family)
+ {
+ const struct nft_object_type *type;
+
+- list_for_each_entry(type, &nf_tables_objects, list) {
++ list_for_each_entry_rcu(type, &nf_tables_objects, list) {
+ if (type->family != NFPROTO_UNSPEC &&
+ type->family != family)
+ continue;
+@@ -7619,9 +7671,13 @@ nft_obj_type_get(struct net *net, u32 objtype, u8 family)
+ {
+ const struct nft_object_type *type;
+
++ rcu_read_lock();
+ type = __nft_obj_type_get(objtype, family);
+- if (type != NULL && try_module_get(type->owner))
++ if (type != NULL && try_module_get(type->owner)) {
++ rcu_read_unlock();
+ return type;
++ }
++ rcu_read_unlock();
+
+ lockdep_nfnl_nft_mutex_not_held();
+ #ifdef CONFIG_MODULES
+@@ -10590,8 +10646,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
+ case NFT_MSG_DESTROYSETELEM:
+ te = (struct nft_trans_elem *)trans->data;
+
+- nft_setelem_data_activate(net, te->set, te->elem_priv);
+- nft_setelem_activate(net, te->set, te->elem_priv);
++ if (!nft_setelem_active_next(net, te->set, te->elem_priv)) {
++ nft_setelem_data_activate(net, te->set, te->elem_priv);
++ nft_setelem_activate(net, te->set, te->elem_priv);
++ }
+ if (!nft_setelem_is_catchall(te->set, te->elem_priv))
+ te->set->ndeact--;
+
+@@ -10779,6 +10837,9 @@ static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx,
+ {
+ const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv);
+
++ if (!nft_set_elem_active(ext, iter->genmask))
++ return 0;
++
+ if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
+ *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END)
+ return 0;
+@@ -10863,6 +10924,7 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
+ continue;
+
+ iter.genmask = nft_genmask_next(ctx->net);
++ iter.type = NFT_ITER_UPDATE;
+ iter.skip = 0;
+ iter.count = 0;
+ iter.err = 0;
+diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c
+index 870e5b113d13e..87c18eddb0689 100644
+--- a/net/netfilter/nft_lookup.c
++++ b/net/netfilter/nft_lookup.c
+@@ -216,6 +216,7 @@ static int nft_lookup_validate(const struct nft_ctx *ctx,
+ return 0;
+
+ iter.genmask = nft_genmask_next(ctx->net);
++ iter.type = NFT_ITER_UPDATE;
+ iter.skip = 0;
+ iter.count = 0;
+ iter.err = 0;
+diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c
+index 32df7a16835da..1caa04619dc6d 100644
+--- a/net/netfilter/nft_set_bitmap.c
++++ b/net/netfilter/nft_set_bitmap.c
+@@ -172,7 +172,7 @@ static void nft_bitmap_activate(const struct net *net,
+ nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off);
+ /* Enter 11 state. */
+ priv->bitmap[idx] |= (genmask << off);
+- nft_set_elem_change_active(net, set, &be->ext);
++ nft_clear(net, &be->ext);
+ }
+
+ static void nft_bitmap_flush(const struct net *net,
+@@ -222,8 +222,6 @@ static void nft_bitmap_walk(const struct nft_ctx *ctx,
+ list_for_each_entry_rcu(be, &priv->list, head) {
+ if (iter->count < iter->skip)
+ goto cont;
+- if (!nft_set_elem_active(&be->ext, iter->genmask))
+- goto cont;
+
+ iter->err = iter->fn(ctx, set, iter, &be->priv);
+
+diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
+index 6968a3b342367..daa56dda737ae 100644
+--- a/net/netfilter/nft_set_hash.c
++++ b/net/netfilter/nft_set_hash.c
+@@ -199,7 +199,7 @@ static void nft_rhash_activate(const struct net *net, const struct nft_set *set,
+ {
+ struct nft_rhash_elem *he = nft_elem_priv_cast(elem_priv);
+
+- nft_set_elem_change_active(net, set, &he->ext);
++ nft_clear(net, &he->ext);
+ }
+
+ static void nft_rhash_flush(const struct net *net,
+@@ -286,8 +286,6 @@ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set,
+
+ if (iter->count < iter->skip)
+ goto cont;
+- if (!nft_set_elem_active(&he->ext, iter->genmask))
+- goto cont;
+
+ iter->err = iter->fn(ctx, set, iter, &he->priv);
+ if (iter->err < 0)
+@@ -599,7 +597,7 @@ static void nft_hash_activate(const struct net *net, const struct nft_set *set,
+ {
+ struct nft_hash_elem *he = nft_elem_priv_cast(elem_priv);
+
+- nft_set_elem_change_active(net, set, &he->ext);
++ nft_clear(net, &he->ext);
+ }
+
+ static void nft_hash_flush(const struct net *net,
+@@ -652,8 +650,6 @@ static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set,
+ hlist_for_each_entry_rcu(he, &priv->table[i], node) {
+ if (iter->count < iter->skip)
+ goto cont;
+- if (!nft_set_elem_active(&he->ext, iter->genmask))
+- goto cont;
+
+ iter->err = iter->fn(ctx, set, iter, &he->priv);
+ if (iter->err < 0)
+diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
+index b3b282de802de..b42a34087e807 100644
+--- a/net/netfilter/nft_set_pipapo.c
++++ b/net/netfilter/nft_set_pipapo.c
+@@ -360,7 +360,7 @@
+ * Return: -1 on no match, bit position on 'match_only', 0 otherwise.
+ */
+ int pipapo_refill(unsigned long *map, int len, int rules, unsigned long *dst,
+- union nft_pipapo_map_bucket *mt, bool match_only)
++ const union nft_pipapo_map_bucket *mt, bool match_only)
+ {
+ unsigned long bitset;
+ int k, ret = -1;
+@@ -412,9 +412,9 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
+ struct nft_pipapo_scratch *scratch;
+ unsigned long *res_map, *fill_map;
+ u8 genmask = nft_genmask_cur(net);
++ const struct nft_pipapo_match *m;
++ const struct nft_pipapo_field *f;
+ const u8 *rp = (const u8 *)key;
+- struct nft_pipapo_match *m;
+- struct nft_pipapo_field *f;
+ bool map_index;
+ int i;
+
+@@ -519,11 +519,13 @@ static struct nft_pipapo_elem *pipapo_get(const struct net *net,
+ {
+ struct nft_pipapo_elem *ret = ERR_PTR(-ENOENT);
+ struct nft_pipapo *priv = nft_set_priv(set);
+- struct nft_pipapo_match *m = priv->clone;
+ unsigned long *res_map, *fill_map = NULL;
+- struct nft_pipapo_field *f;
++ const struct nft_pipapo_match *m;
++ const struct nft_pipapo_field *f;
+ int i;
+
++ m = priv->clone;
++
+ res_map = kmalloc_array(m->bsize_max, sizeof(*res_map), GFP_ATOMIC);
+ if (!res_map) {
+ ret = ERR_PTR(-ENOMEM);
+@@ -1597,7 +1599,7 @@ static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m)
+
+ while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) {
+ union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS];
+- struct nft_pipapo_field *f;
++ const struct nft_pipapo_field *f;
+ int i, start, rules_fx;
+
+ start = first_rule;
+@@ -1771,7 +1773,7 @@ static void nft_pipapo_activate(const struct net *net,
+ {
+ struct nft_pipapo_elem *e = nft_elem_priv_cast(elem_priv);
+
+- nft_set_elem_change_active(net, set, &e->ext);
++ nft_clear(net, &e->ext);
+ }
+
+ /**
+@@ -2000,6 +2002,8 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
+ rules_fx = rules_f0;
+
+ nft_pipapo_for_each_field(f, i, m) {
++ bool last = i == m->field_count - 1;
++
+ if (!pipapo_match_field(f, start, rules_fx,
+ match_start, match_end))
+ break;
+@@ -2012,16 +2016,18 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
+
+ match_start += NFT_PIPAPO_GROUPS_PADDED_SIZE(f);
+ match_end += NFT_PIPAPO_GROUPS_PADDED_SIZE(f);
+- }
+
+- if (i == m->field_count) {
+- priv->dirty = true;
+- pipapo_drop(m, rulemap);
+- return;
++ if (last && f->mt[rulemap[i].to].e == e) {
++ priv->dirty = true;
++ pipapo_drop(m, rulemap);
++ return;
++ }
+ }
+
+ first_rule += rules_f0;
+ }
++
++ WARN_ON_ONCE(1); /* elem_priv not found */
+ }
+
+ /**
+@@ -2038,13 +2044,15 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
+ struct nft_set_iter *iter)
+ {
+ struct nft_pipapo *priv = nft_set_priv(set);
+- struct net *net = read_pnet(&set->net);
+- struct nft_pipapo_match *m;
+- struct nft_pipapo_field *f;
++ const struct nft_pipapo_match *m;
++ const struct nft_pipapo_field *f;
+ int i, r;
+
++ WARN_ON_ONCE(iter->type != NFT_ITER_READ &&
++ iter->type != NFT_ITER_UPDATE);
++
+ rcu_read_lock();
+- if (iter->genmask == nft_genmask_cur(net))
++ if (iter->type == NFT_ITER_READ)
+ m = rcu_dereference(priv->match);
+ else
+ m = priv->clone;
+@@ -2066,9 +2074,6 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
+
+ e = f->mt[r].e;
+
+- if (!nft_set_elem_active(&e->ext, iter->genmask))
+- goto cont;
+-
+ iter->err = iter->fn(ctx, set, iter, &e->priv);
+ if (iter->err < 0)
+ goto out;
+diff --git a/net/netfilter/nft_set_pipapo.h b/net/netfilter/nft_set_pipapo.h
+index 3842c7341a9f4..42464e7c24ac0 100644
+--- a/net/netfilter/nft_set_pipapo.h
++++ b/net/netfilter/nft_set_pipapo.h
+@@ -187,7 +187,7 @@ struct nft_pipapo_elem {
+ };
+
+ int pipapo_refill(unsigned long *map, int len, int rules, unsigned long *dst,
+- union nft_pipapo_map_bucket *mt, bool match_only);
++ const union nft_pipapo_map_bucket *mt, bool match_only);
+
+ /**
+ * pipapo_and_field_buckets_4bit() - Intersect 4-bit buckets
+@@ -195,7 +195,7 @@ int pipapo_refill(unsigned long *map, int len, int rules, unsigned long *dst,
+ * @dst: Area to store result
+ * @data: Input data selecting table buckets
+ */
+-static inline void pipapo_and_field_buckets_4bit(struct nft_pipapo_field *f,
++static inline void pipapo_and_field_buckets_4bit(const struct nft_pipapo_field *f,
+ unsigned long *dst,
+ const u8 *data)
+ {
+@@ -223,7 +223,7 @@ static inline void pipapo_and_field_buckets_4bit(struct nft_pipapo_field *f,
+ * @dst: Area to store result
+ * @data: Input data selecting table buckets
+ */
+-static inline void pipapo_and_field_buckets_8bit(struct nft_pipapo_field *f,
++static inline void pipapo_and_field_buckets_8bit(const struct nft_pipapo_field *f,
+ unsigned long *dst,
+ const u8 *data)
+ {
+diff --git a/net/netfilter/nft_set_pipapo_avx2.c b/net/netfilter/nft_set_pipapo_avx2.c
+index a3a8ddca99189..d08407d589eac 100644
+--- a/net/netfilter/nft_set_pipapo_avx2.c
++++ b/net/netfilter/nft_set_pipapo_avx2.c
+@@ -212,8 +212,9 @@ static int nft_pipapo_avx2_refill(int offset, unsigned long *map,
+ * word index to be checked next (i.e. first filled word).
+ */
+ static int nft_pipapo_avx2_lookup_4b_2(unsigned long *map, unsigned long *fill,
+- struct nft_pipapo_field *f, int offset,
+- const u8 *pkt, bool first, bool last)
++ const struct nft_pipapo_field *f,
++ int offset, const u8 *pkt,
++ bool first, bool last)
+ {
+ int i, ret = -1, m256_size = f->bsize / NFT_PIPAPO_LONGS_PER_M256, b;
+ u8 pg[2] = { pkt[0] >> 4, pkt[0] & 0xf };
+@@ -274,8 +275,9 @@ static int nft_pipapo_avx2_lookup_4b_2(unsigned long *map, unsigned long *fill,
+ * word index to be checked next (i.e. first filled word).
+ */
+ static int nft_pipapo_avx2_lookup_4b_4(unsigned long *map, unsigned long *fill,
+- struct nft_pipapo_field *f, int offset,
+- const u8 *pkt, bool first, bool last)
++ const struct nft_pipapo_field *f,
++ int offset, const u8 *pkt,
++ bool first, bool last)
+ {
+ int i, ret = -1, m256_size = f->bsize / NFT_PIPAPO_LONGS_PER_M256, b;
+ u8 pg[4] = { pkt[0] >> 4, pkt[0] & 0xf, pkt[1] >> 4, pkt[1] & 0xf };
+@@ -350,8 +352,9 @@ static int nft_pipapo_avx2_lookup_4b_4(unsigned long *map, unsigned long *fill,
+ * word index to be checked next (i.e. first filled word).
+ */
+ static int nft_pipapo_avx2_lookup_4b_8(unsigned long *map, unsigned long *fill,
+- struct nft_pipapo_field *f, int offset,
+- const u8 *pkt, bool first, bool last)
++ const struct nft_pipapo_field *f,
++ int offset, const u8 *pkt,
++ bool first, bool last)
+ {
+ u8 pg[8] = { pkt[0] >> 4, pkt[0] & 0xf, pkt[1] >> 4, pkt[1] & 0xf,
+ pkt[2] >> 4, pkt[2] & 0xf, pkt[3] >> 4, pkt[3] & 0xf,
+@@ -445,8 +448,9 @@ static int nft_pipapo_avx2_lookup_4b_8(unsigned long *map, unsigned long *fill,
+ * word index to be checked next (i.e. first filled word).
+ */
+ static int nft_pipapo_avx2_lookup_4b_12(unsigned long *map, unsigned long *fill,
+- struct nft_pipapo_field *f, int offset,
+- const u8 *pkt, bool first, bool last)
++ const struct nft_pipapo_field *f,
++ int offset, const u8 *pkt,
++ bool first, bool last)
+ {
+ u8 pg[12] = { pkt[0] >> 4, pkt[0] & 0xf, pkt[1] >> 4, pkt[1] & 0xf,
+ pkt[2] >> 4, pkt[2] & 0xf, pkt[3] >> 4, pkt[3] & 0xf,
+@@ -534,8 +538,9 @@ static int nft_pipapo_avx2_lookup_4b_12(unsigned long *map, unsigned long *fill,
+ * word index to be checked next (i.e. first filled word).
+ */
+ static int nft_pipapo_avx2_lookup_4b_32(unsigned long *map, unsigned long *fill,
+- struct nft_pipapo_field *f, int offset,
+- const u8 *pkt, bool first, bool last)
++ const struct nft_pipapo_field *f,
++ int offset, const u8 *pkt,
++ bool first, bool last)
+ {
+ u8 pg[32] = { pkt[0] >> 4, pkt[0] & 0xf, pkt[1] >> 4, pkt[1] & 0xf,
+ pkt[2] >> 4, pkt[2] & 0xf, pkt[3] >> 4, pkt[3] & 0xf,
+@@ -669,8 +674,9 @@ static int nft_pipapo_avx2_lookup_4b_32(unsigned long *map, unsigned long *fill,
+ * word index to be checked next (i.e. first filled word).
+ */
+ static int nft_pipapo_avx2_lookup_8b_1(unsigned long *map, unsigned long *fill,
+- struct nft_pipapo_field *f, int offset,
+- const u8 *pkt, bool first, bool last)
++ const struct nft_pipapo_field *f,
++ int offset, const u8 *pkt,
++ bool first, bool last)
+ {
+ int i, ret = -1, m256_size = f->bsize / NFT_PIPAPO_LONGS_PER_M256, b;
+ unsigned long *lt = f->lt, bsize = f->bsize;
+@@ -726,8 +732,9 @@ static int nft_pipapo_avx2_lookup_8b_1(unsigned long *map, unsigned long *fill,
+ * word index to be checked next (i.e. first filled word).
+ */
+ static int nft_pipapo_avx2_lookup_8b_2(unsigned long *map, unsigned long *fill,
+- struct nft_pipapo_field *f, int offset,
+- const u8 *pkt, bool first, bool last)
++ const struct nft_pipapo_field *f,
++ int offset, const u8 *pkt,
++ bool first, bool last)
+ {
+ int i, ret = -1, m256_size = f->bsize / NFT_PIPAPO_LONGS_PER_M256, b;
+ unsigned long *lt = f->lt, bsize = f->bsize;
+@@ -790,8 +797,9 @@ static int nft_pipapo_avx2_lookup_8b_2(unsigned long *map, unsigned long *fill,
+ * word index to be checked next (i.e. first filled word).
+ */
+ static int nft_pipapo_avx2_lookup_8b_4(unsigned long *map, unsigned long *fill,
+- struct nft_pipapo_field *f, int offset,
+- const u8 *pkt, bool first, bool last)
++ const struct nft_pipapo_field *f,
++ int offset, const u8 *pkt,
++ bool first, bool last)
+ {
+ int i, ret = -1, m256_size = f->bsize / NFT_PIPAPO_LONGS_PER_M256, b;
+ unsigned long *lt = f->lt, bsize = f->bsize;
+@@ -865,8 +873,9 @@ static int nft_pipapo_avx2_lookup_8b_4(unsigned long *map, unsigned long *fill,
+ * word index to be checked next (i.e. first filled word).
+ */
+ static int nft_pipapo_avx2_lookup_8b_6(unsigned long *map, unsigned long *fill,
+- struct nft_pipapo_field *f, int offset,
+- const u8 *pkt, bool first, bool last)
++ const struct nft_pipapo_field *f,
++ int offset, const u8 *pkt,
++ bool first, bool last)
+ {
+ int i, ret = -1, m256_size = f->bsize / NFT_PIPAPO_LONGS_PER_M256, b;
+ unsigned long *lt = f->lt, bsize = f->bsize;
+@@ -950,8 +959,9 @@ static int nft_pipapo_avx2_lookup_8b_6(unsigned long *map, unsigned long *fill,
+ * word index to be checked next (i.e. first filled word).
+ */
+ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill,
+- struct nft_pipapo_field *f, int offset,
+- const u8 *pkt, bool first, bool last)
++ const struct nft_pipapo_field *f,
++ int offset, const u8 *pkt,
++ bool first, bool last)
+ {
+ int i, ret = -1, m256_size = f->bsize / NFT_PIPAPO_LONGS_PER_M256, b;
+ unsigned long *lt = f->lt, bsize = f->bsize;
+@@ -1042,8 +1052,9 @@ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill,
+ * word index to be checked next (i.e. first filled word).
+ */
+ static int nft_pipapo_avx2_lookup_slow(unsigned long *map, unsigned long *fill,
+- struct nft_pipapo_field *f, int offset,
+- const u8 *pkt, bool first, bool last)
++ const struct nft_pipapo_field *f,
++ int offset, const u8 *pkt,
++ bool first, bool last)
+ {
+ unsigned long bsize = f->bsize;
+ int i, ret = -1, b;
+@@ -1119,9 +1130,9 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
+ struct nft_pipapo *priv = nft_set_priv(set);
+ struct nft_pipapo_scratch *scratch;
+ u8 genmask = nft_genmask_cur(net);
++ const struct nft_pipapo_match *m;
++ const struct nft_pipapo_field *f;
+ const u8 *rp = (const u8 *)key;
+- struct nft_pipapo_match *m;
+- struct nft_pipapo_field *f;
+ unsigned long *res, *fill;
+ bool map_index;
+ int i, ret = 0;
+diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
+index 9944fe479e536..b7ea21327549b 100644
+--- a/net/netfilter/nft_set_rbtree.c
++++ b/net/netfilter/nft_set_rbtree.c
+@@ -532,7 +532,7 @@ static void nft_rbtree_activate(const struct net *net,
+ {
+ struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem_priv);
+
+- nft_set_elem_change_active(net, set, &rbe->ext);
++ nft_clear(net, &rbe->ext);
+ }
+
+ static void nft_rbtree_flush(const struct net *net,
+@@ -600,8 +600,6 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
+
+ if (iter->count < iter->skip)
+ goto cont;
+- if (!nft_set_elem_active(&rbe->ext, iter->genmask))
+- goto cont;
+
+ iter->err = iter->fn(ctx, set, iter, &rbe->priv);
+ if (iter->err < 0) {
+diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
+index 9b3e9262040b6..a498b5d7c5d60 100644
+--- a/net/sched/sch_generic.c
++++ b/net/sched/sch_generic.c
+@@ -973,6 +973,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
+ sch->enqueue = ops->enqueue;
+ sch->dequeue = ops->dequeue;
+ sch->dev_queue = dev_queue;
++ sch->owner = -1;
+ netdev_hold(dev, &sch->dev_tracker, GFP_KERNEL);
+ refcount_set(&sch->refcnt, 1);
+
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index e37cf913818a1..9df15a7bc2569 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -2602,7 +2602,9 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
+ WRITE_ONCE(u->oob_skb, NULL);
+ consume_skb(skb);
+ }
+- } else if (!(flags & MSG_PEEK)) {
++ } else if (flags & MSG_PEEK) {
++ skb = NULL;
++ } else {
+ skb_unlink(skb, &sk->sk_receive_queue);
+ WRITE_ONCE(u->oob_skb, NULL);
+ if (!WARN_ON_ONCE(skb_unref(skb)))
+@@ -2680,18 +2682,16 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
+ last = skb = skb_peek(&sk->sk_receive_queue);
+ last_len = last ? last->len : 0;
+
++again:
+ #if IS_ENABLED(CONFIG_AF_UNIX_OOB)
+ if (skb) {
+ skb = manage_oob(skb, sk, flags, copied);
+- if (!skb) {
++ if (!skb && copied) {
+ unix_state_unlock(sk);
+- if (copied)
+- break;
+- goto redo;
++ break;
+ }
+ }
+ #endif
+-again:
+ if (skb == NULL) {
+ if (copied >= target)
+ goto unlock;
+diff --git a/sound/core/seq/seq_ump_convert.c b/sound/core/seq/seq_ump_convert.c
+index b141024830ecc..ee6ac649df836 100644
+--- a/sound/core/seq/seq_ump_convert.c
++++ b/sound/core/seq/seq_ump_convert.c
+@@ -428,7 +428,7 @@ static int cvt_ump_midi2_to_midi1(struct snd_seq_client *dest,
+ midi1->note.group = midi2->note.group;
+ midi1->note.status = midi2->note.status;
+ midi1->note.channel = midi2->note.channel;
+- switch (midi2->note.status << 4) {
++ switch (midi2->note.status) {
+ case UMP_MSG_STATUS_NOTE_ON:
+ case UMP_MSG_STATUS_NOTE_OFF:
+ midi1->note.note = midi2->note.note;
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 8c2467ed127ee..bf0618ab4fda0 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -10215,6 +10215,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x152d, 0x1082, "Quanta NL3", ALC269_FIXUP_LIFEBOOK),
++ SND_PCI_QUIRK(0x152d, 0x1262, "Huawei NBLB-WAX9N", ALC2XX_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1558, 0x0353, "Clevo V35[05]SN[CDE]Q", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x1325, "Clevo N15[01][CW]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+@@ -10320,6 +10321,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x17aa, 0x222e, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
+ SND_PCI_QUIRK(0x17aa, 0x2231, "Thinkpad T560", ALC292_FIXUP_TPT460),
+ SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460),
++ SND_PCI_QUIRK(0x17aa, 0x2234, "Thinkpad ICE-1", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x2245, "Thinkpad T470", ALC298_FIXUP_TPT470_DOCK),
+ SND_PCI_QUIRK(0x17aa, 0x2246, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
+ SND_PCI_QUIRK(0x17aa, 0x2247, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
+@@ -10381,8 +10383,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x17aa, 0x3886, "Y780 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x38a7, "Y780P AMD YG dual", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x38a8, "Y780P AMD VECO dual", ALC287_FIXUP_TAS2781_I2C),
+- SND_PCI_QUIRK(0x17aa, 0x38a9, "Thinkbook 16P", ALC287_FIXUP_CS35L41_I2C_2),
+- SND_PCI_QUIRK(0x17aa, 0x38ab, "Thinkbook 16P", ALC287_FIXUP_CS35L41_I2C_2),
++ SND_PCI_QUIRK(0x17aa, 0x38a9, "Thinkbook 16P", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
++ SND_PCI_QUIRK(0x17aa, 0x38ab, "Thinkbook 16P", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
+ SND_PCI_QUIRK(0x17aa, 0x38b4, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x17aa, 0x38b5, "Legion Slim 7 16IRH8", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x17aa, 0x38b6, "Legion Slim 7 16APH8", ALC287_FIXUP_CS35L41_I2C_2),
+@@ -10442,6 +10444,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1d05, 0x115c, "TongFang GMxTGxx", ALC269_FIXUP_NO_SHUTUP),
+ SND_PCI_QUIRK(0x1d05, 0x121b, "TongFang GMxAGxx", ALC269_FIXUP_NO_SHUTUP),
+ SND_PCI_QUIRK(0x1d05, 0x1387, "TongFang GMxIXxx", ALC2XX_FIXUP_HEADSET_MIC),
++ SND_PCI_QUIRK(0x1d17, 0x3288, "Haier Boyue G42", ALC269VC_FIXUP_ACER_VCOPPERBOX_PINS),
+ SND_PCI_QUIRK(0x1d72, 0x1602, "RedmiBook", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1d72, 0x1701, "XiaomiNotebook Pro", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC),
+diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c
+index 693c1b81a23c2..e19f2fa1a528f 100644
+--- a/sound/pci/hda/tas2781_hda_i2c.c
++++ b/sound/pci/hda/tas2781_hda_i2c.c
+@@ -501,10 +501,10 @@ static int tas2563_save_calibration(struct tasdevice_priv *tas_priv)
+ static void tas2781_apply_calib(struct tasdevice_priv *tas_priv)
+ {
+ static const unsigned char page_array[CALIB_MAX] = {
+- 0x17, 0x18, 0x18, 0x0d, 0x18
++ 0x17, 0x18, 0x18, 0x13, 0x18,
+ };
+ static const unsigned char rgno_array[CALIB_MAX] = {
+- 0x74, 0x0c, 0x14, 0x3c, 0x7c
++ 0x74, 0x0c, 0x14, 0x70, 0x7c,
+ };
+ unsigned char *data;
+ int i, j, rc;
+diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
+index ec5e219328760..4790c735599bd 100644
+--- a/tools/perf/ui/browsers/annotate.c
++++ b/tools/perf/ui/browsers/annotate.c
+@@ -970,7 +970,7 @@ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel,
+ if (dso->annotate_warned)
+ return -1;
+
+- if (not_annotated) {
++ if (not_annotated || !sym->annotate2) {
+ err = symbol__annotate2(ms, evsel, &browser.arch);
+ if (err) {
+ char msg[BUFSIZ];
+diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
+index 9b70ab110ce79..86a996290e9ab 100644
+--- a/tools/perf/util/annotate.c
++++ b/tools/perf/util/annotate.c
+@@ -2435,6 +2435,9 @@ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel,
+ if (parch)
+ *parch = arch;
+
++ if (!list_empty(¬es->src->source))
++ return 0;
++
+ args.arch = arch;
+ args.ms = *ms;
+ if (annotate_opts.full_addr)
+diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c
+index 95cd8414f6ef8..e5d78565f479f 100644
+--- a/tools/perf/util/bpf_skel/lock_contention.bpf.c
++++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c
+@@ -289,6 +289,7 @@ static inline __u32 check_lock_type(__u64 lock, __u32 flags)
+ struct task_struct *curr;
+ struct mm_struct___old *mm_old;
+ struct mm_struct___new *mm_new;
++ struct sighand_struct *sighand;
+
+ switch (flags) {
+ case LCB_F_READ: /* rwsem */
+@@ -310,7 +311,9 @@ static inline __u32 check_lock_type(__u64 lock, __u32 flags)
+ break;
+ case LCB_F_SPIN: /* spinlock */
+ curr = bpf_get_current_task_btf();
+- if (&curr->sighand->siglock == (void *)lock)
++ sighand = curr->sighand;
++
++ if (sighand && &sighand->siglock == (void *)lock)
+ return LCD_F_SIGHAND_LOCK;
+ break;
+ default:
+diff --git a/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
+index b1ede62498667..b7c8f29c09a97 100644
+--- a/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
++++ b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
+@@ -18,7 +18,7 @@ echo 'sched:*' > set_event
+
+ yield
+
+-count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
++count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
+ if [ $count -lt 3 ]; then
+ fail "at least fork, exec and exit events should be recorded"
+ fi
+@@ -29,7 +29,7 @@ echo 1 > events/sched/enable
+
+ yield
+
+-count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
++count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
+ if [ $count -lt 3 ]; then
+ fail "at least fork, exec and exit events should be recorded"
+ fi
+@@ -40,7 +40,7 @@ echo 0 > events/sched/enable
+
+ yield
+
+-count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
++count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l`
+ if [ $count -ne 0 ]; then
+ fail "any of scheduler events should not be recorded"
+ fi
+diff --git a/tools/testing/selftests/iommu/config b/tools/testing/selftests/iommu/config
+index 110d73917615d..02a2a1b267c1e 100644
+--- a/tools/testing/selftests/iommu/config
++++ b/tools/testing/selftests/iommu/config
+@@ -1,3 +1,5 @@
+ CONFIG_IOMMUFD=y
++CONFIG_FAULT_INJECTION_DEBUG_FS=y
+ CONFIG_FAULT_INJECTION=y
+ CONFIG_IOMMUFD_TEST=y
++CONFIG_FAILSLAB=y
+diff --git a/tools/testing/selftests/net/tcp_ao/lib/proc.c b/tools/testing/selftests/net/tcp_ao/lib/proc.c
+index 2fb6dd8adba69..8b984fa042869 100644
+--- a/tools/testing/selftests/net/tcp_ao/lib/proc.c
++++ b/tools/testing/selftests/net/tcp_ao/lib/proc.c
+@@ -86,7 +86,7 @@ static void netstat_read_type(FILE *fnetstat, struct netstat **dest, char *line)
+
+ pos = strchr(line, ' ') + 1;
+
+- if (fscanf(fnetstat, type->header_name) == EOF)
++ if (fscanf(fnetstat, "%[^ :]", type->header_name) == EOF)
+ test_error("fscanf(%s)", type->header_name);
+ if (fread(&tmp, 1, 1, fnetstat) != 1 || tmp != ':')
+ test_error("Unexpected netstat format (%c)", tmp);
+diff --git a/tools/testing/selftests/net/tcp_ao/lib/setup.c b/tools/testing/selftests/net/tcp_ao/lib/setup.c
+index 92276f916f2f3..e408b9243b2c5 100644
+--- a/tools/testing/selftests/net/tcp_ao/lib/setup.c
++++ b/tools/testing/selftests/net/tcp_ao/lib/setup.c
+@@ -17,37 +17,37 @@ static pthread_mutex_t ksft_print_lock = PTHREAD_MUTEX_INITIALIZER;
+ void __test_msg(const char *buf)
+ {
+ pthread_mutex_lock(&ksft_print_lock);
+- ksft_print_msg(buf);
++ ksft_print_msg("%s", buf);
+ pthread_mutex_unlock(&ksft_print_lock);
+ }
+ void __test_ok(const char *buf)
+ {
+ pthread_mutex_lock(&ksft_print_lock);
+- ksft_test_result_pass(buf);
++ ksft_test_result_pass("%s", buf);
+ pthread_mutex_unlock(&ksft_print_lock);
+ }
+ void __test_fail(const char *buf)
+ {
+ pthread_mutex_lock(&ksft_print_lock);
+- ksft_test_result_fail(buf);
++ ksft_test_result_fail("%s", buf);
+ pthread_mutex_unlock(&ksft_print_lock);
+ }
+ void __test_xfail(const char *buf)
+ {
+ pthread_mutex_lock(&ksft_print_lock);
+- ksft_test_result_xfail(buf);
++ ksft_test_result_xfail("%s", buf);
+ pthread_mutex_unlock(&ksft_print_lock);
+ }
+ void __test_error(const char *buf)
+ {
+ pthread_mutex_lock(&ksft_print_lock);
+- ksft_test_result_error(buf);
++ ksft_test_result_error("%s", buf);
+ pthread_mutex_unlock(&ksft_print_lock);
+ }
+ void __test_skip(const char *buf)
+ {
+ pthread_mutex_lock(&ksft_print_lock);
+- ksft_test_result_skip(buf);
++ ksft_test_result_skip("%s", buf);
+ pthread_mutex_unlock(&ksft_print_lock);
+ }
+
+diff --git a/tools/testing/selftests/net/tcp_ao/rst.c b/tools/testing/selftests/net/tcp_ao/rst.c
+index 7df8b8700e39e..a2fe88d35ac06 100644
+--- a/tools/testing/selftests/net/tcp_ao/rst.c
++++ b/tools/testing/selftests/net/tcp_ao/rst.c
+@@ -256,8 +256,6 @@ static int test_wait_fds(int sk[], size_t nr, bool is_writable[],
+
+ static void test_client_active_rst(unsigned int port)
+ {
+- /* one in queue, another accept()ed */
+- unsigned int wait_for = backlog + 2;
+ int i, sk[3], err;
+ bool is_writable[ARRAY_SIZE(sk)] = {false};
+ unsigned int last = ARRAY_SIZE(sk) - 1;
+@@ -275,16 +273,20 @@ static void test_client_active_rst(unsigned int port)
+ for (i = 0; i < last; i++) {
+ err = _test_connect_socket(sk[i], this_ip_dest, port,
+ (i == 0) ? TEST_TIMEOUT_SEC : -1);
+-
+ if (err < 0)
+ test_error("failed to connect()");
+ }
+
+- synchronize_threads(); /* 2: connection accept()ed, another queued */
+- err = test_wait_fds(sk, last, is_writable, wait_for, TEST_TIMEOUT_SEC);
++ synchronize_threads(); /* 2: two connections: one accept()ed, another queued */
++ err = test_wait_fds(sk, last, is_writable, last, TEST_TIMEOUT_SEC);
+ if (err < 0)
+ test_error("test_wait_fds(): %d", err);
+
++ /* async connect() with third sk to get into request_sock_queue */
++ err = _test_connect_socket(sk[last], this_ip_dest, port, -1);
++ if (err < 0)
++ test_error("failed to connect()");
++
+ synchronize_threads(); /* 3: close listen socket */
+ if (test_client_verify(sk[0], packet_sz, quota / packet_sz, TEST_TIMEOUT_SEC))
+ test_fail("Failed to send data on connected socket");
+@@ -292,13 +294,14 @@ static void test_client_active_rst(unsigned int port)
+ test_ok("Verified established tcp connection");
+
+ synchronize_threads(); /* 4: finishing up */
+- err = _test_connect_socket(sk[last], this_ip_dest, port, -1);
+- if (err < 0)
+- test_error("failed to connect()");
+
+ synchronize_threads(); /* 5: closed active sk */
+- err = test_wait_fds(sk, ARRAY_SIZE(sk), NULL,
+- wait_for, TEST_TIMEOUT_SEC);
++ /*
++ * Wait for 2 connections: one accepted, another in the accept queue,
++ * the one in request_sock_queue won't get fully established, so
++ * doesn't receive an active RST, see inet_csk_listen_stop().
++ */
++ err = test_wait_fds(sk, last, NULL, last, TEST_TIMEOUT_SEC);
+ if (err < 0)
+ test_error("select(): %d", err);
+
+diff --git a/tools/testing/selftests/net/tcp_ao/setsockopt-closed.c b/tools/testing/selftests/net/tcp_ao/setsockopt-closed.c
+index 452de131fa3a9..517930f9721bd 100644
+--- a/tools/testing/selftests/net/tcp_ao/setsockopt-closed.c
++++ b/tools/testing/selftests/net/tcp_ao/setsockopt-closed.c
+@@ -21,7 +21,7 @@ static void make_listen(int sk)
+ static void test_vefify_ao_info(int sk, struct tcp_ao_info_opt *info,
+ const char *tst)
+ {
+- struct tcp_ao_info_opt tmp;
++ struct tcp_ao_info_opt tmp = {};
+ socklen_t len = sizeof(tmp);
+
+ if (getsockopt(sk, IPPROTO_TCP, TCP_AO_INFO, &tmp, &len))
+diff --git a/tools/testing/selftests/net/udpgso.c b/tools/testing/selftests/net/udpgso.c
+index 7badaf215de28..b02080d09fbc0 100644
+--- a/tools/testing/selftests/net/udpgso.c
++++ b/tools/testing/selftests/net/udpgso.c
+@@ -34,7 +34,7 @@
+ #endif
+
+ #ifndef UDP_MAX_SEGMENTS
+-#define UDP_MAX_SEGMENTS (1 << 6UL)
++#define UDP_MAX_SEGMENTS (1 << 7UL)
+ #endif
+
+ #define CONST_MTU_TEST 1500
+diff --git a/tools/testing/selftests/powerpc/papr_vpd/papr_vpd.c b/tools/testing/selftests/powerpc/papr_vpd/papr_vpd.c
+index 505294da1b9fb..d6f99eb9be659 100644
+--- a/tools/testing/selftests/powerpc/papr_vpd/papr_vpd.c
++++ b/tools/testing/selftests/powerpc/papr_vpd/papr_vpd.c
+@@ -154,7 +154,7 @@ static int dev_papr_vpd_null_handle(void)
+ static int papr_vpd_close_handle_without_reading(void)
+ {
+ const int devfd = open(DEVPATH, O_RDONLY);
+- struct papr_location_code lc;
++ struct papr_location_code lc = { .str = "", };
+ int fd;
+
+ SKIP_IF_MSG(devfd < 0 && errno == ENOENT,
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-27 22:03 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-04-27 22:03 UTC (permalink / raw
To: gentoo-commits
commit: 910c52a332d5bc4800f6d510cc7427a5af1d7a28
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sat Apr 27 22:01:28 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sat Apr 27 22:03:10 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=910c52a3
Add UBSAN_BOUNDS and UBSAN_SHIFT and dependencies
Bug: https://bugs.gentoo.org/930733
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
4567_distro-Gentoo-Kconfig.patch | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/4567_distro-Gentoo-Kconfig.patch b/4567_distro-Gentoo-Kconfig.patch
index d215166c..6134393f 100644
--- a/4567_distro-Gentoo-Kconfig.patch
+++ b/4567_distro-Gentoo-Kconfig.patch
@@ -6,9 +6,9 @@
source "Documentation/Kconfig"
+
+source "distro/Kconfig"
---- /dev/null 2022-08-25 07:13:06.694086407 -0400
-+++ b/distro/Kconfig 2022-08-25 13:21:55.150660724 -0400
-@@ -0,0 +1,291 @@
+--- /dev/null 2024-04-27 13:10:54.188000027 -0400
++++ b/distro/Kconfig 2024-04-27 17:56:56.723132353 -0400
+@@ -0,0 +1,295 @@
+menu "Gentoo Linux"
+
+config GENTOO_LINUX
@@ -213,6 +213,10 @@
+ select SLAB_FREELIST_HARDENED
+ select SHUFFLE_PAGE_ALLOCATOR
+ select SLUB_DEBUG
++ select UBSAN
++ select CC_HAS_UBSAN_BOUNDS_STRICT if !CC_HAS_UBSAN_ARRAY_BOUNDS
++ select UBSAN_BOUNDS
++ select UBSAN_SHIFT
+ select PAGE_POISONING
+ select PAGE_POISONING_NO_SANITY
+ select PAGE_POISONING_ZERO
@@ -300,9 +304,6 @@
+ See the settings that become available for more details and fine-tuning.
+
+endmenu
---
-2.31.1
-
From bd3ff0b16792c18c0614c2b95e148943209f460a Mon Sep 17 00:00:00 2001
From: Georgy Yakovlev <gyakovlev@gentoo.org>
Date: Tue, 8 Jun 2021 13:59:57 -0700
@@ -327,4 +328,3 @@ index 24c045b24..e13fc740c 100644
This is the portion of low virtual memory which should be protected
--
2.31.1
-```
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-04-28 22:04 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-04-28 22:04 UTC (permalink / raw
To: gentoo-commits
commit: 315003951b6f0bc2014da65ad339d8a961f388e3
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sun Apr 28 22:04:16 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sun Apr 28 22:04:16 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=31500395
BMQ Patch v6.8-r6
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 2 +-
... => 5020_BMQ-and-PDS-io-scheduler-v6.8-r6.patch | 227 ++++++++++-----------
2 files changed, 106 insertions(+), 123 deletions(-)
diff --git a/0000_README b/0000_README
index 03fbc840..7f4b52bc 100644
--- a/0000_README
+++ b/0000_README
@@ -115,6 +115,6 @@ Patch: 5010_enable-cpu-optimizations-universal.patch
From: https://github.com/graysky2/kernel_compiler_patch
Desc: Kernel >= 5.15 patch enables gcc = v11.1+ optimizations for additional CPUs.
-Patch: 5020_BMQ-and-PDS-io-scheduler-v6.8-r4.patch
+Patch: 5020_BMQ-and-PDS-io-scheduler-v6.8-r6.patch
From: https://gitlab.com/alfredchen/projectc
Desc: BMQ(BitMap Queue) Scheduler. A new CPU scheduler developed from PDS(incld). Inspired by the scheduler in zircon.
diff --git a/5020_BMQ-and-PDS-io-scheduler-v6.8-r4.patch b/5020_BMQ-and-PDS-io-scheduler-v6.8-r6.patch
similarity index 98%
rename from 5020_BMQ-and-PDS-io-scheduler-v6.8-r4.patch
rename to 5020_BMQ-and-PDS-io-scheduler-v6.8-r6.patch
index 6ade9048..6fd79852 100644
--- a/5020_BMQ-and-PDS-io-scheduler-v6.8-r4.patch
+++ b/5020_BMQ-and-PDS-io-scheduler-v6.8-r6.patch
@@ -268,10 +268,10 @@ index df3aca89d4f5..1df1f7635188 100644
static inline bool dl_time_before(u64 a, u64 b)
{
diff --git a/include/linux/sched/prio.h b/include/linux/sched/prio.h
-index ab83d85e1183..a9a1dfa99140 100644
+index ab83d85e1183..e66dfb553bc5 100644
--- a/include/linux/sched/prio.h
+++ b/include/linux/sched/prio.h
-@@ -18,6 +18,32 @@
+@@ -18,6 +18,28 @@
#define MAX_PRIO (MAX_RT_PRIO + NICE_WIDTH)
#define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2)
@@ -284,20 +284,16 @@ index ab83d85e1183..a9a1dfa99140 100644
+/* +/- priority levels from the base priority */
+#ifdef CONFIG_SCHED_BMQ
+#define MAX_PRIORITY_ADJ (12)
-+
-+#define MIN_NORMAL_PRIO (MAX_RT_PRIO)
-+#define MAX_PRIO (MIN_NORMAL_PRIO + NICE_WIDTH)
-+#define DEFAULT_PRIO (MIN_NORMAL_PRIO + NICE_WIDTH / 2)
+#endif
+
+#ifdef CONFIG_SCHED_PDS
+#define MAX_PRIORITY_ADJ (0)
++#endif
+
+#define MIN_NORMAL_PRIO (128)
+#define NORMAL_PRIO_NUM (64)
+#define MAX_PRIO (MIN_NORMAL_PRIO + NORMAL_PRIO_NUM)
-+#define DEFAULT_PRIO (MAX_PRIO - NICE_WIDTH / 2)
-+#endif
++#define DEFAULT_PRIO (MAX_PRIO - MAX_PRIORITY_ADJ - NICE_WIDTH / 2)
+
+#endif /* CONFIG_SCHED_ALT */
+
@@ -422,7 +418,7 @@ index bee58f7468c3..81f568107a6b 100644
select CGROUP_SCHED
select FAIR_GROUP_SCHED
diff --git a/init/init_task.c b/init/init_task.c
-index 7ecb458eb3da..40d2e86da6f9 100644
+index 7ecb458eb3da..e8f8be4f23ba 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -70,9 +70,15 @@ struct task_struct init_task __aligned(L1_CACHE_BYTES) = {
@@ -430,9 +426,9 @@ index 7ecb458eb3da..40d2e86da6f9 100644
.usage = REFCOUNT_INIT(2),
.flags = PF_KTHREAD,
+#ifdef CONFIG_SCHED_ALT
-+ .prio = DEFAULT_PRIO + MAX_PRIORITY_ADJ,
++ .prio = DEFAULT_PRIO,
+ .static_prio = DEFAULT_PRIO,
-+ .normal_prio = DEFAULT_PRIO + MAX_PRIORITY_ADJ,
++ .normal_prio = DEFAULT_PRIO,
+#else
.prio = MAX_PRIO - 20,
.static_prio = MAX_PRIO - 20,
@@ -663,10 +659,10 @@ index 976092b7bd45..31d587c16ec1 100644
obj-y += build_utility.o
diff --git a/kernel/sched/alt_core.c b/kernel/sched/alt_core.c
new file mode 100644
-index 000000000000..1044207ba0ad
+index 000000000000..c566583fe838
--- /dev/null
+++ b/kernel/sched/alt_core.c
-@@ -0,0 +1,8945 @@
+@@ -0,0 +1,8934 @@
+/*
+ * kernel/sched/alt_core.c
+ *
@@ -745,7 +741,7 @@ index 000000000000..1044207ba0ad
+#define sched_feat(x) (0)
+#endif /* CONFIG_SCHED_DEBUG */
+
-+#define ALT_SCHED_VERSION "v6.8-r4"
++#define ALT_SCHED_VERSION "v6.8-r6"
+
+/*
+ * Compile time debug macro
@@ -856,27 +852,21 @@ index 000000000000..1044207ba0ad
+ idle->on_rq = TASK_ON_RQ_QUEUED;
+}
+
-+static inline void
-+clear_recorded_preempt_mask(int pr, int low, int high, int cpu)
-+{
-+ if (low < pr && pr <= high)
++#define CLEAR_CACHED_PREEMPT_MASK(pr, low, high, cpu) \
++ if (low < pr && pr <= high) \
+ cpumask_clear_cpu(cpu, sched_preempt_mask + pr);
-+}
+
-+static inline void
-+set_recorded_preempt_mask(int pr, int low, int high, int cpu)
-+{
-+ if (low < pr && pr <= high)
++#define SET_CACHED_PREEMPT_MASK(pr, low, high, cpu) \
++ if (low < pr && pr <= high) \
+ cpumask_set_cpu(cpu, sched_preempt_mask + pr);
-+}
+
+static atomic_t sched_prio_record = ATOMIC_INIT(0);
+
+/* water mark related functions */
+static inline void update_sched_preempt_mask(struct rq *rq)
+{
-+ unsigned long prio = find_first_bit(rq->queue.bitmap, SCHED_QUEUE_BITS);
-+ unsigned long last_prio = rq->prio;
++ int prio = find_first_bit(rq->queue.bitmap, SCHED_QUEUE_BITS);
++ int last_prio = rq->prio;
+ int cpu, pr;
+
+ if (prio == last_prio)
@@ -899,7 +889,7 @@ index 000000000000..1044207ba0ad
+ cpumask_clear_cpu(cpu, sched_idle_mask);
+ last_prio -= 2;
+ }
-+ clear_recorded_preempt_mask(pr, prio, last_prio, cpu);
++ CLEAR_CACHED_PREEMPT_MASK(pr, prio, last_prio, cpu);
+
+ return;
+ }
@@ -908,13 +898,12 @@ index 000000000000..1044207ba0ad
+#ifdef CONFIG_SCHED_SMT
+ if (static_branch_likely(&sched_smt_present) &&
+ cpumask_intersects(cpu_smt_mask(cpu), sched_idle_mask))
-+ cpumask_or(sched_sg_idle_mask,
-+ sched_sg_idle_mask, cpu_smt_mask(cpu));
++ cpumask_or(sched_sg_idle_mask, sched_sg_idle_mask, cpu_smt_mask(cpu));
+#endif
+ cpumask_set_cpu(cpu, sched_idle_mask);
+ prio -= 2;
+ }
-+ set_recorded_preempt_mask(pr, last_prio, prio, cpu);
++ SET_CACHED_PREEMPT_MASK(pr, last_prio, prio, cpu);
+}
+
+/*
@@ -927,8 +916,7 @@ index 000000000000..1044207ba0ad
+ return list_first_entry(head, struct task_struct, sq_node);
+}
+
-+static inline struct task_struct *
-+sched_rq_next_task(struct task_struct *p, struct rq *rq)
++static inline struct task_struct * sched_rq_next_task(struct task_struct *p, struct rq *rq)
+{
+ struct list_head *next = p->sq_node.next;
+
@@ -936,7 +924,8 @@ index 000000000000..1044207ba0ad
+ struct list_head *head;
+ unsigned long idx = next - &rq->queue.heads[0];
+
-+ idx = find_next_bit(rq->queue.bitmap, SCHED_QUEUE_BITS, sched_idx2prio(idx, rq) + 1);
++ idx = find_next_bit(rq->queue.bitmap, SCHED_QUEUE_BITS,
++ sched_idx2prio(idx, rq) + 1);
+ head = &rq->queue.heads[sched_prio2idx(idx, rq)];
+
+ return list_first_entry(head, struct task_struct, sq_node);
@@ -1040,16 +1029,14 @@ index 000000000000..1044207ba0ad
+/*
+ * Context: p->pi_lock
+ */
-+static inline struct rq
-+*__task_access_lock(struct task_struct *p, raw_spinlock_t **plock)
++static inline struct rq *__task_access_lock(struct task_struct *p, raw_spinlock_t **plock)
+{
+ struct rq *rq;
+ for (;;) {
+ rq = task_rq(p);
+ if (p->on_cpu || task_on_rq_queued(p)) {
+ raw_spin_lock(&rq->lock);
-+ if (likely((p->on_cpu || task_on_rq_queued(p))
-+ && rq == task_rq(p))) {
++ if (likely((p->on_cpu || task_on_rq_queued(p)) && rq == task_rq(p))) {
+ *plock = &rq->lock;
+ return rq;
+ }
@@ -1065,24 +1052,21 @@ index 000000000000..1044207ba0ad
+ }
+}
+
-+static inline void
-+__task_access_unlock(struct task_struct *p, raw_spinlock_t *lock)
++static inline void __task_access_unlock(struct task_struct *p, raw_spinlock_t *lock)
+{
+ if (NULL != lock)
+ raw_spin_unlock(lock);
+}
+
-+static inline struct rq
-+*task_access_lock_irqsave(struct task_struct *p, raw_spinlock_t **plock,
-+ unsigned long *flags)
++static inline struct rq *
++task_access_lock_irqsave(struct task_struct *p, raw_spinlock_t **plock, unsigned long *flags)
+{
+ struct rq *rq;
+ for (;;) {
+ rq = task_rq(p);
+ if (p->on_cpu || task_on_rq_queued(p)) {
+ raw_spin_lock_irqsave(&rq->lock, *flags);
-+ if (likely((p->on_cpu || task_on_rq_queued(p))
-+ && rq == task_rq(p))) {
++ if (likely((p->on_cpu || task_on_rq_queued(p)) && rq == task_rq(p))) {
+ *plock = &rq->lock;
+ return rq;
+ }
@@ -1093,8 +1077,7 @@ index 000000000000..1044207ba0ad
+ } while (unlikely(task_on_rq_migrating(p)));
+ } else {
+ raw_spin_lock_irqsave(&p->pi_lock, *flags);
-+ if (likely(!p->on_cpu && !p->on_rq &&
-+ rq == task_rq(p))) {
++ if (likely(!p->on_cpu && !p->on_rq && rq == task_rq(p))) {
+ *plock = &p->pi_lock;
+ return rq;
+ }
@@ -1104,8 +1087,7 @@ index 000000000000..1044207ba0ad
+}
+
+static inline void
-+task_access_unlock_irqrestore(struct task_struct *p, raw_spinlock_t *lock,
-+ unsigned long *flags)
++task_access_unlock_irqrestore(struct task_struct *p, raw_spinlock_t *lock, unsigned long *flags)
+{
+ raw_spin_unlock_irqrestore(lock, *flags);
+}
@@ -1173,15 +1155,13 @@ index 000000000000..1044207ba0ad
+ }
+}
+
-+static inline void
-+rq_lock_irqsave(struct rq *rq, struct rq_flags *rf)
++static inline void rq_lock_irqsave(struct rq *rq, struct rq_flags *rf)
+ __acquires(rq->lock)
+{
+ raw_spin_lock_irqsave(&rq->lock, rf->flags);
+}
+
-+static inline void
-+rq_unlock_irqrestore(struct rq *rq, struct rq_flags *rf)
++static inline void rq_unlock_irqrestore(struct rq *rq, struct rq_flags *rf)
+ __releases(rq->lock)
+{
+ raw_spin_unlock_irqrestore(&rq->lock, rf->flags);
@@ -1301,8 +1281,7 @@ index 000000000000..1044207ba0ad
+static inline void rq_load_update(struct rq *rq)
+{
+ u64 time = rq->clock;
-+ u64 delta = min(LOAD_BLOCK(time) - LOAD_BLOCK(rq->load_stamp),
-+ RQ_LOAD_HISTORY_BITS - 1);
++ u64 delta = min(LOAD_BLOCK(time) - LOAD_BLOCK(rq->load_stamp), RQ_LOAD_HISTORY_BITS - 1);
+ u64 prev = !!(rq->load_history & CURRENT_LOAD_BIT);
+ u64 curr = !!rq->nr_running;
+
@@ -1366,8 +1345,7 @@ index 000000000000..1044207ba0ad
+#ifdef CONFIG_SMP
+ rq_load_update(rq);
+#endif
-+ data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data,
-+ cpu_of(rq)));
++ data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data, cpu_of(rq)));
+ if (data)
+ data->func(data, rq_clock(rq), flags);
+}
@@ -2117,8 +2095,7 @@ index 000000000000..1044207ba0ad
+
+static inline int __normal_prio(int policy, int rt_prio, int static_prio)
+{
-+ return rt_policy(policy) ? (MAX_RT_PRIO - 1 - rt_prio) :
-+ static_prio + MAX_PRIORITY_ADJ;
++ return rt_policy(policy) ? (MAX_RT_PRIO - 1 - rt_prio) : static_prio;
+}
+
+/*
@@ -2393,8 +2370,7 @@ index 000000000000..1044207ba0ad
+ *
+ * Returns (locked) new rq. Old rq's lock is released.
+ */
-+static struct rq *move_queued_task(struct rq *rq, struct task_struct *p, int
-+ new_cpu)
++static struct rq *move_queued_task(struct rq *rq, struct task_struct *p, int new_cpu)
+{
+ int src_cpu;
+
@@ -2435,8 +2411,7 @@ index 000000000000..1044207ba0ad
+ * So we race with normal scheduler movements, but that's OK, as long
+ * as the task is no longer on this CPU.
+ */
-+static struct rq *__migrate_task(struct rq *rq, struct task_struct *p, int
-+ dest_cpu)
++static struct rq *__migrate_task(struct rq *rq, struct task_struct *p, int dest_cpu)
+{
+ /* Affinity changed (again). */
+ if (!is_cpu_allowed(p, dest_cpu))
@@ -4862,41 +4837,40 @@ index 000000000000..1044207ba0ad
+ wq_worker_tick(curr);
+}
+
-+#ifdef CONFIG_SCHED_SMT
-+static inline int sg_balance_cpu_stop(void *data)
++#ifdef CONFIG_SMP
++
++static int active_balance_cpu_stop(void *data)
+{
++ struct balance_arg *arg = data;
++ struct task_struct *p = arg->task;
+ struct rq *rq = this_rq();
-+ struct task_struct *p = data;
-+ cpumask_t tmp;
+ unsigned long flags;
++ cpumask_t tmp;
+
+ local_irq_save(flags);
+
+ raw_spin_lock(&p->pi_lock);
+ raw_spin_lock(&rq->lock);
+
-+ rq->active_balance = 0;
-+ /* _something_ may have changed the task, double check again */
++ arg->active = 0;
++
+ if (task_on_rq_queued(p) && task_rq(p) == rq &&
-+ cpumask_and(&tmp, p->cpus_ptr, sched_sg_idle_mask) &&
++ cpumask_and(&tmp, p->cpus_ptr, arg->cpumask) &&
+ !is_migration_disabled(p)) {
-+ int cpu = cpu_of(rq);
-+ int dcpu = __best_mask_cpu(&tmp, per_cpu(sched_cpu_llc_mask, cpu));
++ int dcpu = __best_mask_cpu(&tmp, per_cpu(sched_cpu_llc_mask, cpu_of(rq)));
+ rq = move_queued_task(rq, p, dcpu);
+ }
+
+ raw_spin_unlock(&rq->lock);
-+ raw_spin_unlock(&p->pi_lock);
-+
-+ local_irq_restore(flags);
++ raw_spin_unlock_irqrestore(&p->pi_lock, flags);
+
+ return 0;
+}
+
-+/* sg_balance_trigger - trigger slibing group balance for @cpu */
-+static inline int sg_balance_trigger(struct rq *src_rq, const int cpu)
++/* trigger_active_balance - for @rq */
++static inline int
++trigger_active_balance(struct rq *src_rq, struct rq *rq, struct balance_arg *arg)
+{
-+ struct rq *rq= cpu_rq(cpu);
+ unsigned long flags;
+ struct task_struct *p;
+ int res;
@@ -4906,10 +4880,13 @@ index 000000000000..1044207ba0ad
+
+ res = (1 == rq->nr_running) && \
+ !is_migration_disabled((p = sched_rq_first_task(rq))) && \
-+ cpumask_intersects(p->cpus_ptr, sched_sg_idle_mask) && \
-+ !rq->active_balance;
-+ if (res)
-+ rq->active_balance = 1;
++ cpumask_intersects(p->cpus_ptr, arg->cpumask) && \
++ !arg->active;
++ if (res) {
++ arg->task = p;
++
++ arg->active = 1;
++ }
+
+ raw_spin_unlock_irqrestore(&rq->lock, flags);
+
@@ -4917,8 +4894,8 @@ index 000000000000..1044207ba0ad
+ preempt_disable();
+ raw_spin_unlock(&src_rq->lock);
+
-+ stop_one_cpu_nowait(cpu, sg_balance_cpu_stop, p,
-+ &rq->active_balance_work);
++ stop_one_cpu_nowait(cpu_of(rq), active_balance_cpu_stop,
++ arg, &rq->active_balance_work);
+
+ preempt_enable();
+ raw_spin_lock(&src_rq->lock);
@@ -4927,6 +4904,7 @@ index 000000000000..1044207ba0ad
+ return res;
+}
+
++#ifdef CONFIG_SCHED_SMT
+/*
+ * sg_balance - slibing group balance check for run queue @rq
+ */
@@ -4939,9 +4917,11 @@ index 000000000000..1044207ba0ad
+ int i, cpu = cpu_of(rq);
+
+ for_each_cpu_wrap(i, &chk, cpu) {
-+ if (cpumask_subset(cpu_smt_mask(i), &chk) &&\
-+ sg_balance_trigger(rq, i))
-+ return;
++ if (cpumask_subset(cpu_smt_mask(i), &chk)) {
++ struct rq *target_rq = cpu_rq(i);
++ if (trigger_active_balance(rq, target_rq, &target_rq->sg_balance_arg))
++ return;
++ }
+ }
+ }
+}
@@ -4951,6 +4931,8 @@ index 000000000000..1044207ba0ad
+};
+#endif /* CONFIG_SCHED_SMT */
+
++#endif /* CONFIG_SMP */
++
+#ifdef CONFIG_NO_HZ_FULL
+
+struct tick_work {
@@ -5378,8 +5360,9 @@ index 000000000000..1044207ba0ad
+#endif
+
+#ifdef CONFIG_SCHED_SMT
-+ if (likely(rq->online) &&
-+ cpumask_test_cpu(cpu, sched_sg_idle_mask))
++ if (static_key_count(&sched_smt_present.key) > 1 &&
++ cpumask_test_cpu(cpu, sched_sg_idle_mask) &&
++ rq->online)
+ __queue_balance_callback(rq, &per_cpu(sg_balance_head, cpu));
+#endif
+ schedstat_inc(rq->sched_goidle);
@@ -5544,9 +5527,6 @@ index 000000000000..1044207ba0ad
+#endif
+
+ if (likely(prev != next)) {
-+#ifdef CONFIG_SCHED_BMQ
-+ rq->last_ts_switch = rq->clock;
-+#endif
+ next->last_ran = rq->clock_task;
+
+ /*printk(KERN_INFO "sched: %px -> %px\n", prev, next);*/
@@ -8288,6 +8268,8 @@ index 000000000000..1044207ba0ad
+#ifdef CONFIG_SCHED_SMT
+ TOPOLOGY_CPUMASK(smt, topology_sibling_cpumask(cpu), false);
+#endif
++ TOPOLOGY_CPUMASK(cluster, topology_cluster_cpumask(cpu), false);
++
+ per_cpu(sd_llc_id, cpu) = cpumask_first(cpu_coregroup_mask(cpu));
+ per_cpu(sched_cpu_llc_mask, cpu) = topo;
+ TOPOLOGY_CPUMASK(coregroup, cpu_coregroup_mask(cpu), false);
@@ -8354,6 +8336,9 @@ index 000000000000..1044207ba0ad
+{
+ int i;
+ struct rq *rq;
++#ifdef CONFIG_SCHED_SMT
++ struct balance_arg balance_arg = {.cpumask = sched_sg_idle_mask, .active = 0};
++#endif
+
+ printk(KERN_INFO "sched/alt: "ALT_SCHED_NAME" CPU Scheduler "ALT_SCHED_VERSION\
+ " by Alfred Chen.\n");
@@ -8390,7 +8375,7 @@ index 000000000000..1044207ba0ad
+ rq->cpu = i;
+
+#ifdef CONFIG_SCHED_SMT
-+ rq->active_balance = 0;
++ rq->sg_balance_arg = balance_arg;
+#endif
+
+#ifdef CONFIG_NO_HZ_COMMON
@@ -9652,10 +9637,10 @@ index 000000000000..1dbd7eb6a434
+{}
diff --git a/kernel/sched/alt_sched.h b/kernel/sched/alt_sched.h
new file mode 100644
-index 000000000000..ba1b7b805f1a
+index 000000000000..5da166931ee9
--- /dev/null
+++ b/kernel/sched/alt_sched.h
-@@ -0,0 +1,975 @@
+@@ -0,0 +1,976 @@
+#ifndef ALT_SCHED_H
+#define ALT_SCHED_H
+
@@ -9814,6 +9799,12 @@ index 000000000000..ba1b7b805f1a
+ void (*func)(struct rq *rq);
+};
+
++struct balance_arg {
++ struct task_struct *task;
++ int active;
++ cpumask_t *cpumask;
++};
++
+/*
+ * This is the main, per-CPU runqueue data structure.
+ * This data should only be modified by the local cpu.
@@ -9828,11 +9819,12 @@ index 000000000000..ba1b7b805f1a
+ struct mm_struct *prev_mm;
+
+ struct sched_queue queue ____cacheline_aligned;
++
++ int prio;
+#ifdef CONFIG_SCHED_PDS
-+ u64 time_edge;
-+ unsigned long prio_idx;
++ int prio_idx;
++ u64 time_edge;
+#endif
-+ unsigned long prio;
+
+ /* switch count */
+ u64 nr_switches;
@@ -9861,9 +9853,10 @@ index 000000000000..ba1b7b805f1a
+#endif
+
+#ifdef CONFIG_SCHED_SMT
-+ int active_balance;
-+ struct cpu_stop_work active_balance_work;
++ struct balance_arg sg_balance_arg ____cacheline_aligned;
+#endif
++ struct cpu_stop_work active_balance_work;
++
+ struct balance_callback *balance_callback;
+#ifdef CONFIG_HOTPLUG_CPU
+ struct rcuwait hotplug_wait;
@@ -9893,9 +9886,6 @@ index 000000000000..ba1b7b805f1a
+ /* Ensure that all clocks are in the same cache line */
+ u64 clock ____cacheline_aligned;
+ u64 clock_task;
-+#ifdef CONFIG_SCHED_BMQ
-+ u64 last_ts_switch;
-+#endif
+
+ unsigned int nr_running;
+ unsigned long nr_uninterruptible;
@@ -10004,10 +9994,6 @@ index 000000000000..ba1b7b805f1a
+ return __best_mask_cpu(mask, per_cpu(sched_cpu_topo_masks, cpu));
+}
+
-+extern void flush_smp_call_function_queue(void);
-+
-+#else /* !CONFIG_SMP */
-+static inline void flush_smp_call_function_queue(void) { }
+#endif
+
+#ifndef arch_scale_freq_tick
@@ -10633,19 +10619,16 @@ index 000000000000..ba1b7b805f1a
+#endif /* ALT_SCHED_H */
diff --git a/kernel/sched/bmq.h b/kernel/sched/bmq.h
new file mode 100644
-index 000000000000..b7c9813f6fa7
+index 000000000000..bdc34ad3cc8c
--- /dev/null
+++ b/kernel/sched/bmq.h
-@@ -0,0 +1,101 @@
+@@ -0,0 +1,98 @@
+#define ALT_SCHED_NAME "BMQ"
+
+/*
+ * BMQ only routines
+ */
-+#define rq_switch_time(rq) ((rq)->clock - (rq)->last_ts_switch)
-+#define boost_threshold(p) (sysctl_sched_base_slice >> ((20 - (p)->boost_prio) / 2))
-+
-+static inline void boost_task(struct task_struct *p)
++static inline void boost_task(struct task_struct *p, int n)
+{
+ int limit;
+
@@ -10660,8 +10643,7 @@ index 000000000000..b7c9813f6fa7
+ return;
+ }
+
-+ if (p->boost_prio > limit)
-+ p->boost_prio--;
++ p->boost_prio = max(limit, p->boost_prio - n);
+}
+
+static inline void deboost_task(struct task_struct *p)
@@ -10679,13 +10661,13 @@ index 000000000000..b7c9813f6fa7
+static inline int
+task_sched_prio_normal(const struct task_struct *p, const struct rq *rq)
+{
-+ return p->prio + p->boost_prio - MAX_RT_PRIO;
++ return p->prio + p->boost_prio - MIN_NORMAL_PRIO;
+}
+
+static inline int task_sched_prio(const struct task_struct *p)
+{
-+ return (p->prio < MAX_RT_PRIO)? (p->prio >> 2) :
-+ MIN_SCHED_NORMAL_PRIO + (p->prio + p->boost_prio - MAX_RT_PRIO) / 2;
++ return (p->prio < MIN_NORMAL_PRIO)? (p->prio >> 2) :
++ MIN_SCHED_NORMAL_PRIO + (p->prio + p->boost_prio - MIN_NORMAL_PRIO) / 2;
+}
+
+#define TASK_SCHED_PRIO_IDX(p, rq, idx, prio) \
@@ -10709,7 +10691,7 @@ index 000000000000..b7c9813f6fa7
+
+inline int task_running_nice(struct task_struct *p)
+{
-+ return (p->prio + p->boost_prio > DEFAULT_PRIO + MAX_PRIORITY_ADJ);
++ return (p->prio + p->boost_prio > DEFAULT_PRIO);
+}
+
+static inline void sched_update_rq_clock(struct rq *rq) {}
@@ -10729,14 +10711,15 @@ index 000000000000..b7c9813f6fa7
+
+static inline void sched_task_ttwu(struct task_struct *p)
+{
-+ if(this_rq()->clock_task - p->last_ran > sysctl_sched_base_slice)
-+ boost_task(p);
++ s64 delta = this_rq()->clock_task > p->last_ran;
++
++ if (likely(delta > 0))
++ boost_task(p, delta >> 22);
+}
+
+static inline void sched_task_deactivate(struct task_struct *p, struct rq *rq)
+{
-+ if (rq_switch_time(rq) < boost_threshold(p))
-+ boost_task(p);
++ boost_task(p, 1);
+}
diff --git a/kernel/sched/build_policy.c b/kernel/sched/build_policy.c
index d9dc9ab3773f..71a25540d65e 100644
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-05-02 15:14 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-05-02 15:14 UTC (permalink / raw
To: gentoo-commits
commit: 7c06ce549b999cd746462a6a688eb5a71ebafc6e
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Thu May 2 15:14:08 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Thu May 2 15:14:08 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=7c06ce54
Linux patch 6.8.9
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1008_linux-6.8.9.patch | 9798 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 9802 insertions(+)
diff --git a/0000_README b/0000_README
index 7f4b52bc..f9626b92 100644
--- a/0000_README
+++ b/0000_README
@@ -75,6 +75,10 @@ Patch: 1007_linux-6.8.8.patch
From: https://www.kernel.org
Desc: Linux 6.8.8
+Patch: 1008_linux-6.8.9.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.9
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1008_linux-6.8.9.patch b/1008_linux-6.8.9.patch
new file mode 100644
index 00000000..97f04a2c
--- /dev/null
+++ b/1008_linux-6.8.9.patch
@@ -0,0 +1,9798 @@
+diff --git a/Documentation/admin-guide/sysctl/net.rst b/Documentation/admin-guide/sysctl/net.rst
+index 3960916519557..7250c0542828b 100644
+--- a/Documentation/admin-guide/sysctl/net.rst
++++ b/Documentation/admin-guide/sysctl/net.rst
+@@ -206,6 +206,11 @@ Will increase power usage.
+
+ Default: 0 (off)
+
++mem_pcpu_rsv
++------------
++
++Per-cpu reserved forward alloc cache size in page units. Default 1MB per CPU.
++
+ rmem_default
+ ------------
+
+diff --git a/Documentation/devicetree/bindings/eeprom/at24.yaml b/Documentation/devicetree/bindings/eeprom/at24.yaml
+index 1812ef31d5f1e..3c36cd0510de8 100644
+--- a/Documentation/devicetree/bindings/eeprom/at24.yaml
++++ b/Documentation/devicetree/bindings/eeprom/at24.yaml
+@@ -68,14 +68,10 @@ properties:
+ pattern: cs16$
+ - items:
+ pattern: c32$
+- - items:
+- pattern: c32d-wl$
+ - items:
+ pattern: cs32$
+ - items:
+ pattern: c64$
+- - items:
+- pattern: c64d-wl$
+ - items:
+ pattern: cs64$
+ - items:
+@@ -136,6 +132,7 @@ properties:
+ - renesas,r1ex24128
+ - samsung,s524ad0xd1
+ - const: atmel,24c128
++ - pattern: '^atmel,24c(32|64)d-wl$' # Actual vendor is st
+
+ label:
+ description: Descriptive name of the EEPROM.
+diff --git a/Makefile b/Makefile
+index ffa43a6d04241..2917a6914c03c 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 8
++SUBLEVEL = 9
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/arch/Kconfig b/arch/Kconfig
+index a5af0edd3eb8f..03cd763ed40c1 100644
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -9,6 +9,14 @@
+ #
+ source "arch/$(SRCARCH)/Kconfig"
+
++config ARCH_CONFIGURES_CPU_MITIGATIONS
++ bool
++
++if !ARCH_CONFIGURES_CPU_MITIGATIONS
++config CPU_MITIGATIONS
++ def_bool y
++endif
++
+ menu "General architecture-dependent options"
+
+ config ARCH_HAS_SUBPAGE_FAULTS
+diff --git a/arch/arc/boot/dts/hsdk.dts b/arch/arc/boot/dts/hsdk.dts
+index 6691f42550778..41b980df862b1 100644
+--- a/arch/arc/boot/dts/hsdk.dts
++++ b/arch/arc/boot/dts/hsdk.dts
+@@ -205,7 +205,6 @@ dmac_cfg_clk: dmac-gpu-cfg-clk {
+ };
+
+ gmac: ethernet@8000 {
+- #interrupt-cells = <1>;
+ compatible = "snps,dwmac";
+ reg = <0x8000 0x2000>;
+ interrupts = <10>;
+diff --git a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
+index 217e9b96c61e5..20b2497657ae4 100644
+--- a/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
++++ b/arch/arm/boot/dts/microchip/at91-sama7g5ek.dts
+@@ -293,7 +293,7 @@ vddcore: VDD_CORE {
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+- regulator-suspend-voltage = <1150000>;
++ regulator-suspend-microvolt = <1150000>;
+ regulator-mode = <4>;
+ };
+
+@@ -314,7 +314,7 @@ vddcpu: VDD_OTHER {
+
+ regulator-state-standby {
+ regulator-on-in-suspend;
+- regulator-suspend-voltage = <1050000>;
++ regulator-suspend-microvolt = <1050000>;
+ regulator-mode = <4>;
+ };
+
+@@ -331,7 +331,7 @@ vldo1: LDO1 {
+ regulator-always-on;
+
+ regulator-state-standby {
+- regulator-suspend-voltage = <1800000>;
++ regulator-suspend-microvolt = <1800000>;
+ regulator-on-in-suspend;
+ };
+
+@@ -346,7 +346,7 @@ vldo2: LDO2 {
+ regulator-max-microvolt = <3700000>;
+
+ regulator-state-standby {
+- regulator-suspend-voltage = <1800000>;
++ regulator-suspend-microvolt = <1800000>;
+ regulator-on-in-suspend;
+ };
+
+diff --git a/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-common.dtsi b/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-common.dtsi
+index 3fdece5bd31f9..5248a058230c8 100644
+--- a/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-common.dtsi
++++ b/arch/arm/boot/dts/nxp/imx/imx6ull-tarragon-common.dtsi
+@@ -805,6 +805,7 @@ &usbotg1 {
+ &pinctrl_usb_pwr>;
+ dr_mode = "host";
+ power-active-high;
++ over-current-active-low;
+ disable-over-current;
+ status = "okay";
+ };
+diff --git a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts
+index fffdb7bbf889e..2d0ef6f23b3a9 100644
+--- a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts
++++ b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts
+@@ -129,7 +129,7 @@ ethernet_phy0: ethernet-phy@5 {
+ };
+
+ &pio {
+- eth_default: eth_default {
++ eth_default: eth-default-pins {
+ tx_pins {
+ pinmux = <MT2712_PIN_71_GBE_TXD3__FUNC_GBE_TXD3>,
+ <MT2712_PIN_72_GBE_TXD2__FUNC_GBE_TXD2>,
+@@ -156,7 +156,7 @@ mdio_pins {
+ };
+ };
+
+- eth_sleep: eth_sleep {
++ eth_sleep: eth-sleep-pins {
+ tx_pins {
+ pinmux = <MT2712_PIN_71_GBE_TXD3__FUNC_GPIO71>,
+ <MT2712_PIN_72_GBE_TXD2__FUNC_GPIO72>,
+@@ -182,14 +182,14 @@ mdio_pins {
+ };
+ };
+
+- usb0_id_pins_float: usb0_iddig {
++ usb0_id_pins_float: usb0-iddig-pins {
+ pins_iddig {
+ pinmux = <MT2712_PIN_12_IDDIG_P0__FUNC_IDDIG_A>;
+ bias-pull-up;
+ };
+ };
+
+- usb1_id_pins_float: usb1_iddig {
++ usb1_id_pins_float: usb1-iddig-pins {
+ pins_iddig {
+ pinmux = <MT2712_PIN_14_IDDIG_P1__FUNC_IDDIG_B>;
+ bias-pull-up;
+diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
+index ed1a9d3194153..f767f921bdee1 100644
+--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
+@@ -249,10 +249,11 @@ topckgen: syscon@10000000 {
+ #clock-cells = <1>;
+ };
+
+- infracfg: syscon@10001000 {
++ infracfg: clock-controller@10001000 {
+ compatible = "mediatek,mt2712-infracfg", "syscon";
+ reg = <0 0x10001000 0 0x1000>;
+ #clock-cells = <1>;
++ #reset-cells = <1>;
+ };
+
+ pericfg: syscon@10003000 {
+diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+index 3ee9266fa8e98..917fa39a74f8d 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+@@ -252,7 +252,7 @@ scpsys: power-controller@10006000 {
+ clock-names = "hif_sel";
+ };
+
+- cir: cir@10009000 {
++ cir: ir-receiver@10009000 {
+ compatible = "mediatek,mt7622-cir";
+ reg = <0 0x10009000 0 0x1000>;
+ interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_LOW>;
+@@ -283,16 +283,14 @@ thermal_calibration: calib@198 {
+ };
+ };
+
+- apmixedsys: apmixedsys@10209000 {
+- compatible = "mediatek,mt7622-apmixedsys",
+- "syscon";
++ apmixedsys: clock-controller@10209000 {
++ compatible = "mediatek,mt7622-apmixedsys";
+ reg = <0 0x10209000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+- topckgen: topckgen@10210000 {
+- compatible = "mediatek,mt7622-topckgen",
+- "syscon";
++ topckgen: clock-controller@10210000 {
++ compatible = "mediatek,mt7622-topckgen";
+ reg = <0 0x10210000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+@@ -515,7 +513,6 @@ thermal: thermal@1100b000 {
+ <&pericfg CLK_PERI_AUXADC_PD>;
+ clock-names = "therm", "auxadc";
+ resets = <&pericfg MT7622_PERI_THERM_SW_RST>;
+- reset-names = "therm";
+ mediatek,auxadc = <&auxadc>;
+ mediatek,apmixedsys = <&apmixedsys>;
+ nvmem-cells = <&thermal_calibration>;
+@@ -734,9 +731,8 @@ wmac: wmac@18000000 {
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_WB>;
+ };
+
+- ssusbsys: ssusbsys@1a000000 {
+- compatible = "mediatek,mt7622-ssusbsys",
+- "syscon";
++ ssusbsys: clock-controller@1a000000 {
++ compatible = "mediatek,mt7622-ssusbsys";
+ reg = <0 0x1a000000 0 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+@@ -793,9 +789,8 @@ u2port1: usb-phy@1a0c5000 {
+ };
+ };
+
+- pciesys: pciesys@1a100800 {
+- compatible = "mediatek,mt7622-pciesys",
+- "syscon";
++ pciesys: clock-controller@1a100800 {
++ compatible = "mediatek,mt7622-pciesys";
+ reg = <0 0x1a100800 0 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+@@ -921,12 +916,13 @@ sata_port: sata-phy@1a243000 {
+ };
+ };
+
+- hifsys: syscon@1af00000 {
+- compatible = "mediatek,mt7622-hifsys", "syscon";
++ hifsys: clock-controller@1af00000 {
++ compatible = "mediatek,mt7622-hifsys";
+ reg = <0 0x1af00000 0 0x70>;
++ #clock-cells = <1>;
+ };
+
+- ethsys: syscon@1b000000 {
++ ethsys: clock-controller@1b000000 {
+ compatible = "mediatek,mt7622-ethsys",
+ "syscon";
+ reg = <0 0x1b000000 0 0x1000>;
+@@ -966,9 +962,7 @@ wed1: wed@1020b000 {
+ };
+
+ eth: ethernet@1b100000 {
+- compatible = "mediatek,mt7622-eth",
+- "mediatek,mt2701-eth",
+- "syscon";
++ compatible = "mediatek,mt7622-eth";
+ reg = <0 0x1b100000 0 0x20000>;
+ interrupts = <GIC_SPI 223 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 224 IRQ_TYPE_LEVEL_LOW>,
+diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
+index e04b1c0c0ebbf..ed79ad1ae8716 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
++++ b/arch/arm64/boot/dts/mediatek/mt7986a-bananapi-bpi-r3.dts
+@@ -146,19 +146,19 @@ sfp2: sfp-2 {
+
+ &cpu_thermal {
+ cooling-maps {
+- cpu-active-high {
++ map-cpu-active-high {
+ /* active: set fan to cooling level 2 */
+ cooling-device = <&fan 2 2>;
+ trip = <&cpu_trip_active_high>;
+ };
+
+- cpu-active-med {
++ map-cpu-active-med {
+ /* active: set fan to cooling level 1 */
+ cooling-device = <&fan 1 1>;
+ trip = <&cpu_trip_active_med>;
+ };
+
+- cpu-active-low {
++ map-cpu-active-low {
+ /* active: set fan to cooling level 0 */
+ cooling-device = <&fan 0 0>;
+ trip = <&cpu_trip_active_low>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+index d974739eae1c9..559990dcd1d17 100644
+--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+@@ -16,49 +16,49 @@ / {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+- clk40m: oscillator-40m {
+- compatible = "fixed-clock";
+- clock-frequency = <40000000>;
+- #clock-cells = <0>;
+- clock-output-names = "clkxtal";
+- };
+-
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ cpu0: cpu@0 {
+- device_type = "cpu";
+ compatible = "arm,cortex-a53";
+- enable-method = "psci";
+ reg = <0x0>;
++ device_type = "cpu";
++ enable-method = "psci";
+ #cooling-cells = <2>;
+ };
+
+ cpu1: cpu@1 {
+- device_type = "cpu";
+ compatible = "arm,cortex-a53";
+- enable-method = "psci";
+ reg = <0x1>;
++ device_type = "cpu";
++ enable-method = "psci";
+ #cooling-cells = <2>;
+ };
+
+ cpu2: cpu@2 {
+- device_type = "cpu";
+ compatible = "arm,cortex-a53";
+- enable-method = "psci";
+ reg = <0x2>;
++ device_type = "cpu";
++ enable-method = "psci";
+ #cooling-cells = <2>;
+ };
+
+ cpu3: cpu@3 {
+- device_type = "cpu";
+- enable-method = "psci";
+ compatible = "arm,cortex-a53";
+ reg = <0x3>;
++ device_type = "cpu";
++ enable-method = "psci";
+ #cooling-cells = <2>;
+ };
+ };
+
++ clk40m: oscillator-40m {
++ compatible = "fixed-clock";
++ clock-frequency = <40000000>;
++ #clock-cells = <0>;
++ clock-output-names = "clkxtal";
++ };
++
+ psci {
+ compatible = "arm,psci-0.2";
+ method = "smc";
+@@ -121,32 +121,23 @@ wo_boot: wo-boot@15194000 {
+
+ };
+
+- timer {
+- compatible = "arm,armv8-timer";
+- interrupt-parent = <&gic>;
+- interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+- <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+- <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+- <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+- };
+-
+ soc {
+- #address-cells = <2>;
+- #size-cells = <2>;
+ compatible = "simple-bus";
+ ranges;
++ #address-cells = <2>;
++ #size-cells = <2>;
+
+ gic: interrupt-controller@c000000 {
+ compatible = "arm,gic-v3";
+- #interrupt-cells = <3>;
+- interrupt-parent = <&gic>;
+- interrupt-controller;
+ reg = <0 0x0c000000 0 0x10000>, /* GICD */
+ <0 0x0c080000 0 0x80000>, /* GICR */
+ <0 0x0c400000 0 0x2000>, /* GICC */
+ <0 0x0c410000 0 0x1000>, /* GICH */
+ <0 0x0c420000 0 0x2000>; /* GICV */
++ interrupt-parent = <&gic>;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
++ interrupt-controller;
++ #interrupt-cells = <3>;
+ };
+
+ infracfg: infracfg@10001000 {
+@@ -203,6 +194,19 @@ pio: pinctrl@1001f000 {
+ #interrupt-cells = <2>;
+ };
+
++ pwm: pwm@10048000 {
++ compatible = "mediatek,mt7986-pwm";
++ reg = <0 0x10048000 0 0x1000>;
++ #pwm-cells = <2>;
++ interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&topckgen CLK_TOP_PWM_SEL>,
++ <&infracfg CLK_INFRA_PWM_STA>,
++ <&infracfg CLK_INFRA_PWM1_CK>,
++ <&infracfg CLK_INFRA_PWM2_CK>;
++ clock-names = "top", "main", "pwm1", "pwm2";
++ status = "disabled";
++ };
++
+ sgmiisys0: syscon@10060000 {
+ compatible = "mediatek,mt7986-sgmiisys_0",
+ "syscon";
+@@ -240,19 +244,6 @@ crypto: crypto@10320000 {
+ status = "disabled";
+ };
+
+- pwm: pwm@10048000 {
+- compatible = "mediatek,mt7986-pwm";
+- reg = <0 0x10048000 0 0x1000>;
+- #pwm-cells = <2>;
+- interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+- clocks = <&topckgen CLK_TOP_PWM_SEL>,
+- <&infracfg CLK_INFRA_PWM_STA>,
+- <&infracfg CLK_INFRA_PWM1_CK>,
+- <&infracfg CLK_INFRA_PWM2_CK>;
+- clock-names = "top", "main", "pwm1", "pwm2";
+- status = "disabled";
+- };
+-
+ uart0: serial@11002000 {
+ compatible = "mediatek,mt7986-uart",
+ "mediatek,mt6577-uart";
+@@ -310,9 +301,9 @@ i2c0: i2c@11008000 {
+
+ spi0: spi@1100a000 {
+ compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm";
++ reg = <0 0x1100a000 0 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+- reg = <0 0x1100a000 0 0x100>;
+ interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&topckgen CLK_TOP_MPLL_D2>,
+ <&topckgen CLK_TOP_SPI_SEL>,
+@@ -324,9 +315,9 @@ spi0: spi@1100a000 {
+
+ spi1: spi@1100b000 {
+ compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm";
++ reg = <0 0x1100b000 0 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+- reg = <0 0x1100b000 0 0x100>;
+ interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&topckgen CLK_TOP_MPLL_D2>,
+ <&topckgen CLK_TOP_SPIM_MST_SEL>,
+@@ -336,6 +327,20 @@ spi1: spi@1100b000 {
+ status = "disabled";
+ };
+
++ thermal: thermal@1100c800 {
++ compatible = "mediatek,mt7986-thermal";
++ reg = <0 0x1100c800 0 0x800>;
++ interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
++ clocks = <&infracfg CLK_INFRA_THERM_CK>,
++ <&infracfg CLK_INFRA_ADC_26M_CK>;
++ clock-names = "therm", "auxadc";
++ nvmem-cells = <&thermal_calibration>;
++ nvmem-cell-names = "calibration-data";
++ #thermal-sensor-cells = <1>;
++ mediatek,auxadc = <&auxadc>;
++ mediatek,apmixedsys = <&apmixedsys>;
++ };
++
+ auxadc: adc@1100d000 {
+ compatible = "mediatek,mt7986-auxadc";
+ reg = <0 0x1100d000 0 0x1000>;
+@@ -387,39 +392,23 @@ mmc0: mmc@11230000 {
+ status = "disabled";
+ };
+
+- thermal: thermal@1100c800 {
+- #thermal-sensor-cells = <1>;
+- compatible = "mediatek,mt7986-thermal";
+- reg = <0 0x1100c800 0 0x800>;
+- interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
+- clocks = <&infracfg CLK_INFRA_THERM_CK>,
+- <&infracfg CLK_INFRA_ADC_26M_CK>,
+- <&infracfg CLK_INFRA_ADC_FRC_CK>;
+- clock-names = "therm", "auxadc", "adc_32k";
+- mediatek,auxadc = <&auxadc>;
+- mediatek,apmixedsys = <&apmixedsys>;
+- nvmem-cells = <&thermal_calibration>;
+- nvmem-cell-names = "calibration-data";
+- };
+-
+ pcie: pcie@11280000 {
+ compatible = "mediatek,mt7986-pcie",
+ "mediatek,mt8192-pcie";
++ reg = <0x00 0x11280000 0x00 0x4000>;
++ reg-names = "pcie-mac";
++ ranges = <0x82000000 0x00 0x20000000 0x00
++ 0x20000000 0x00 0x10000000>;
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+- reg = <0x00 0x11280000 0x00 0x4000>;
+- reg-names = "pcie-mac";
+ interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+ bus-range = <0x00 0xff>;
+- ranges = <0x82000000 0x00 0x20000000 0x00
+- 0x20000000 0x00 0x10000000>;
+ clocks = <&infracfg CLK_INFRA_IPCIE_PIPE_CK>,
+ <&infracfg CLK_INFRA_IPCIE_CK>,
+ <&infracfg CLK_INFRA_IPCIER_CK>,
+ <&infracfg CLK_INFRA_IPCIEB_CK>;
+ clock-names = "pl_250m", "tl_26m", "peri_26m", "top_133m";
+- status = "disabled";
+
+ phys = <&pcie_port PHY_TYPE_PCIE>;
+ phy-names = "pcie-phy";
+@@ -430,6 +419,8 @@ pcie: pcie@11280000 {
+ <0 0 0 2 &pcie_intc 1>,
+ <0 0 0 3 &pcie_intc 2>,
+ <0 0 0 4 &pcie_intc 3>;
++ status = "disabled";
++
+ pcie_intc: interrupt-controller {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+@@ -440,9 +431,9 @@ pcie_intc: interrupt-controller {
+ pcie_phy: t-phy {
+ compatible = "mediatek,mt7986-tphy",
+ "mediatek,generic-tphy-v2";
++ ranges;
+ #address-cells = <2>;
+ #size-cells = <2>;
+- ranges;
+ status = "disabled";
+
+ pcie_port: pcie-phy@11c00000 {
+@@ -467,9 +458,9 @@ thermal_calibration: calib@274 {
+ usb_phy: t-phy@11e10000 {
+ compatible = "mediatek,mt7986-tphy",
+ "mediatek,generic-tphy-v2";
++ ranges = <0 0 0x11e10000 0x1700>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+- ranges = <0 0 0x11e10000 0x1700>;
+ status = "disabled";
+
+ u2port0: usb-phy@0 {
+@@ -497,8 +488,6 @@ u2port1: usb-phy@1000 {
+ };
+
+ ethsys: syscon@15000000 {
+- #address-cells = <1>;
+- #size-cells = <1>;
+ compatible = "mediatek,mt7986-ethsys",
+ "syscon";
+ reg = <0 0x15000000 0 0x1000>;
+@@ -532,20 +521,6 @@ wed1: wed@15011000 {
+ mediatek,wo-ccif = <&wo_ccif1>;
+ };
+
+- wo_ccif0: syscon@151a5000 {
+- compatible = "mediatek,mt7986-wo-ccif", "syscon";
+- reg = <0 0x151a5000 0 0x1000>;
+- interrupt-parent = <&gic>;
+- interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
+- };
+-
+- wo_ccif1: syscon@151ad000 {
+- compatible = "mediatek,mt7986-wo-ccif", "syscon";
+- reg = <0 0x151ad000 0 0x1000>;
+- interrupt-parent = <&gic>;
+- interrupts = <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
+- };
+-
+ eth: ethernet@15100000 {
+ compatible = "mediatek,mt7986-eth";
+ reg = <0 0x15100000 0 0x80000>;
+@@ -578,26 +553,39 @@ eth: ethernet@15100000 {
+ <&topckgen CLK_TOP_SGM_325M_SEL>;
+ assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>,
+ <&apmixedsys CLK_APMIXED_SGMPLL>;
++ #address-cells = <1>;
++ #size-cells = <0>;
+ mediatek,ethsys = <ðsys>;
+ mediatek,sgmiisys = <&sgmiisys0>, <&sgmiisys1>;
+ mediatek,wed-pcie = <&wed_pcie>;
+ mediatek,wed = <&wed0>, <&wed1>;
+- #reset-cells = <1>;
+- #address-cells = <1>;
+- #size-cells = <0>;
+ status = "disabled";
+ };
+
++ wo_ccif0: syscon@151a5000 {
++ compatible = "mediatek,mt7986-wo-ccif", "syscon";
++ reg = <0 0x151a5000 0 0x1000>;
++ interrupt-parent = <&gic>;
++ interrupts = <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
++ wo_ccif1: syscon@151ad000 {
++ compatible = "mediatek,mt7986-wo-ccif", "syscon";
++ reg = <0 0x151ad000 0 0x1000>;
++ interrupt-parent = <&gic>;
++ interrupts = <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
++ };
++
+ wifi: wifi@18000000 {
+ compatible = "mediatek,mt7986-wmac";
++ reg = <0 0x18000000 0 0x1000000>,
++ <0 0x10003000 0 0x1000>,
++ <0 0x11d10000 0 0x1000>;
+ resets = <&watchdog MT7986_TOPRGU_CONSYS_SW_RST>;
+ reset-names = "consys";
+ clocks = <&topckgen CLK_TOP_CONN_MCUSYS_SEL>,
+ <&topckgen CLK_TOP_AP2CNN_HOST_SEL>;
+ clock-names = "mcu", "ap2conn";
+- reg = <0 0x18000000 0 0x1000000>,
+- <0 0x10003000 0 0x1000>,
+- <0 0x11d10000 0 0x1000>;
+ interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>,
+@@ -645,4 +633,13 @@ cpu_trip_active_low: active-low {
+ };
+ };
+ };
++
++ timer {
++ compatible = "arm,armv8-timer";
++ interrupt-parent = <&gic>;
++ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
++ <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
++ <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
++ <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
++ };
+ };
+diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
+index 90c5ad917a9ba..41aef6c3edfc5 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
+@@ -433,7 +433,6 @@ &mt6358regulator {
+ };
+
+ &mt6358_vgpu_reg {
+- regulator-min-microvolt = <625000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-coupled-with = <&mt6358_vsram_gpu_reg>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt8183.dtsi b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+index 920ee415ef5fb..e1767a4e38f3a 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8183.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8183.dtsi
+@@ -1628,6 +1628,7 @@ mfgcfg: syscon@13000000 {
+ compatible = "mediatek,mt8183-mfgcfg", "syscon";
+ reg = <0 0x13000000 0 0x1000>;
+ #clock-cells = <1>;
++ power-domains = <&spm MT8183_POWER_DOMAIN_MFG_ASYNC>;
+ };
+
+ gpu: gpu@13040000 {
+diff --git a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
+index d4dd5e8b2e1d3..f62b2498eb1c7 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi
+@@ -1420,7 +1420,7 @@ regulators {
+ mt6315_6_vbuck1: vbuck1 {
+ regulator-compatible = "vbuck1";
+ regulator-name = "Vbcpu";
+- regulator-min-microvolt = <300000>;
++ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1193750>;
+ regulator-enable-ramp-delay = <256>;
+ regulator-allowed-modes = <0 1 2>;
+@@ -1430,7 +1430,7 @@ mt6315_6_vbuck1: vbuck1 {
+ mt6315_6_vbuck3: vbuck3 {
+ regulator-compatible = "vbuck3";
+ regulator-name = "Vlcpu";
+- regulator-min-microvolt = <300000>;
++ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1193750>;
+ regulator-enable-ramp-delay = <256>;
+ regulator-allowed-modes = <0 1 2>;
+@@ -1447,7 +1447,7 @@ regulators {
+ mt6315_7_vbuck1: vbuck1 {
+ regulator-compatible = "vbuck1";
+ regulator-name = "Vgpu";
+- regulator-min-microvolt = <606250>;
++ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <800000>;
+ regulator-enable-ramp-delay = <256>;
+ regulator-allowed-modes = <0 1 2>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt8192.dtsi b/arch/arm64/boot/dts/mediatek/mt8192.dtsi
+index 0e432636b8c23..eea8d141f93cf 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8192.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8192.dtsi
+@@ -1456,6 +1456,7 @@ mutex: mutex@14001000 {
+ reg = <0 0x14001000 0 0x1000>;
+ interrupts = <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&mmsys CLK_MM_DISP_MUTEX0>;
++ mediatek,gce-client-reg = <&gce SUBSYS_1400XXXX 0x1000 0x1000>;
+ mediatek,gce-events = <CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_0>,
+ <CMDQ_EVENT_DISP_STREAM_DONE_ENG_EVENT_1>;
+ power-domains = <&spm MT8192_POWER_DOMAIN_DISP>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
+index 3c6079edda190..121dfd91da07b 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
+@@ -264,6 +264,38 @@ &auxadc {
+ status = "okay";
+ };
+
++&cpu0 {
++ cpu-supply = <&mt6359_vcore_buck_reg>;
++};
++
++&cpu1 {
++ cpu-supply = <&mt6359_vcore_buck_reg>;
++};
++
++&cpu2 {
++ cpu-supply = <&mt6359_vcore_buck_reg>;
++};
++
++&cpu3 {
++ cpu-supply = <&mt6359_vcore_buck_reg>;
++};
++
++&cpu4 {
++ cpu-supply = <&mt6315_6_vbuck1>;
++};
++
++&cpu5 {
++ cpu-supply = <&mt6315_6_vbuck1>;
++};
++
++&cpu6 {
++ cpu-supply = <&mt6315_6_vbuck1>;
++};
++
++&cpu7 {
++ cpu-supply = <&mt6315_6_vbuck1>;
++};
++
+ &dp_intf0 {
+ status = "okay";
+
+@@ -1213,7 +1245,7 @@ regulators {
+ mt6315_6_vbuck1: vbuck1 {
+ regulator-compatible = "vbuck1";
+ regulator-name = "Vbcpu";
+- regulator-min-microvolt = <300000>;
++ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1193750>;
+ regulator-enable-ramp-delay = <256>;
+ regulator-ramp-delay = <6250>;
+@@ -1231,7 +1263,7 @@ regulators {
+ mt6315_7_vbuck1: vbuck1 {
+ regulator-compatible = "vbuck1";
+ regulator-name = "Vgpu";
+- regulator-min-microvolt = <625000>;
++ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1193750>;
+ regulator-enable-ramp-delay = <256>;
+ regulator-ramp-delay = <6250>;
+diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
+index b9101662ce40d..4dd7f755630ea 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
++++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
+@@ -1998,6 +1998,7 @@ vppsys0: syscon@14000000 {
+ compatible = "mediatek,mt8195-vppsys0", "syscon";
+ reg = <0 0x14000000 0 0x1000>;
+ #clock-cells = <1>;
++ mediatek,gce-client-reg = <&gce1 SUBSYS_1400XXXX 0 0x1000>;
+ };
+
+ dma-controller@14001000 {
+@@ -2221,6 +2222,7 @@ vppsys1: syscon@14f00000 {
+ compatible = "mediatek,mt8195-vppsys1", "syscon";
+ reg = <0 0x14f00000 0 0x1000>;
+ #clock-cells = <1>;
++ mediatek,gce-client-reg = <&gce1 SUBSYS_14f0XXXX 0 0x1000>;
+ };
+
+ mutex@14f01000 {
+@@ -3050,6 +3052,7 @@ vdosys0: syscon@1c01a000 {
+ reg = <0 0x1c01a000 0 0x1000>;
+ mboxes = <&gce0 0 CMDQ_THR_PRIO_4>;
+ #clock-cells = <1>;
++ mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0xa000 0x1000>;
+ };
+
+
+@@ -3231,6 +3234,7 @@ mutex: mutex@1c016000 {
+ interrupts = <GIC_SPI 658 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS0>;
+ clocks = <&vdosys0 CLK_VDO0_DISP_MUTEX0>;
++ mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0x6000 0x1000>;
+ mediatek,gce-events = <CMDQ_EVENT_VDO0_DISP_STREAM_DONE_0>;
+ };
+
+@@ -3301,6 +3305,7 @@ mutex1: mutex@1c101000 {
+ power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
+ clocks = <&vdosys1 CLK_VDO1_DISP_MUTEX>;
+ clock-names = "vdo1_mutex";
++ mediatek,gce-client-reg = <&gce0 SUBSYS_1c10XXXX 0x1000 0x1000>;
+ mediatek,gce-events = <CMDQ_EVENT_VDO1_STREAM_DONE_ENG_0>;
+ };
+
+diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
+index 7dc2c37716e84..46545cd6964a9 100644
+--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
++++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
+@@ -3650,7 +3650,7 @@ remoteproc_adsp: remoteproc@3700000 {
+ compatible = "qcom,sc7280-adsp-pas";
+ reg = <0 0x03700000 0 0x100>;
+
+- interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
+ <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&adsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&adsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
+@@ -3887,7 +3887,7 @@ remoteproc_cdsp: remoteproc@a300000 {
+ compatible = "qcom,sc7280-cdsp-pas";
+ reg = <0 0x0a300000 0 0x10000>;
+
+- interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
+ <&cdsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&cdsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&cdsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
+diff --git a/arch/arm64/boot/dts/qcom/sc8180x.dtsi b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
+index c0dd44f146748..b481c15b255ce 100644
+--- a/arch/arm64/boot/dts/qcom/sc8180x.dtsi
++++ b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
+@@ -2641,7 +2641,7 @@ usb_sec: usb@a8f8800 {
+ resets = <&gcc GCC_USB30_SEC_BCR>;
+ power-domains = <&gcc USB30_SEC_GDSC>;
+ interrupts-extended = <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+- <&pdc 7 IRQ_TYPE_LEVEL_HIGH>,
++ <&pdc 40 IRQ_TYPE_LEVEL_HIGH>,
+ <&pdc 10 IRQ_TYPE_EDGE_BOTH>,
+ <&pdc 11 IRQ_TYPE_EDGE_BOTH>;
+ interrupt-names = "hs_phy_irq", "ss_phy_irq",
+diff --git a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
+index febf28356ff8b..2e2126c1627a4 100644
+--- a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
++++ b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
+@@ -1774,6 +1774,7 @@ pcie4: pcie@1c00000 {
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_4_GDSC>;
++ required-opps = <&rpmhpd_opp_nom>;
+
+ phys = <&pcie4_phy>;
+ phy-names = "pciephy";
+@@ -1872,6 +1873,7 @@ pcie3b: pcie@1c08000 {
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_3B_GDSC>;
++ required-opps = <&rpmhpd_opp_nom>;
+
+ phys = <&pcie3b_phy>;
+ phy-names = "pciephy";
+@@ -1970,6 +1972,7 @@ pcie3a: pcie@1c10000 {
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_3A_GDSC>;
++ required-opps = <&rpmhpd_opp_nom>;
+
+ phys = <&pcie3a_phy>;
+ phy-names = "pciephy";
+@@ -2071,6 +2074,7 @@ pcie2b: pcie@1c18000 {
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_2B_GDSC>;
++ required-opps = <&rpmhpd_opp_nom>;
+
+ phys = <&pcie2b_phy>;
+ phy-names = "pciephy";
+@@ -2169,6 +2173,7 @@ pcie2a: pcie@1c20000 {
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_2A_GDSC>;
++ required-opps = <&rpmhpd_opp_nom>;
+
+ phys = <&pcie2a_phy>;
+ phy-names = "pciephy";
+@@ -2635,7 +2640,7 @@ remoteproc_adsp: remoteproc@3000000 {
+ compatible = "qcom,sc8280xp-adsp-pas";
+ reg = <0 0x03000000 0 0x100>;
+
+- interrupts-extended = <&intc GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts-extended = <&intc GIC_SPI 162 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
+@@ -4407,7 +4412,7 @@ remoteproc_nsp0: remoteproc@1b300000 {
+ compatible = "qcom,sc8280xp-nsp0-pas";
+ reg = <0 0x1b300000 0 0x100>;
+
+- interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_nsp0_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_nsp0_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_nsp0_in 2 IRQ_TYPE_EDGE_RISING>,
+@@ -4538,7 +4543,7 @@ remoteproc_nsp1: remoteproc@21300000 {
+ compatible = "qcom,sc8280xp-nsp1-pas";
+ reg = <0 0x21300000 0 0x100>;
+
+- interrupts-extended = <&intc GIC_SPI 887 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts-extended = <&intc GIC_SPI 887 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_nsp1_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_nsp1_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_nsp1_in 2 IRQ_TYPE_EDGE_RISING>,
+diff --git a/arch/arm64/boot/dts/qcom/sm6350.dtsi b/arch/arm64/boot/dts/qcom/sm6350.dtsi
+index 43cffe8e1247e..7532107580aee 100644
+--- a/arch/arm64/boot/dts/qcom/sm6350.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm6350.dtsi
+@@ -1249,7 +1249,7 @@ adsp: remoteproc@3000000 {
+ compatible = "qcom,sm6350-adsp-pas";
+ reg = <0 0x03000000 0 0x100>;
+
+- interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
+@@ -1509,7 +1509,7 @@ cdsp: remoteproc@8300000 {
+ compatible = "qcom,sm6350-cdsp-pas";
+ reg = <0 0x08300000 0 0x10000>;
+
+- interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>,
+diff --git a/arch/arm64/boot/dts/qcom/sm6375.dtsi b/arch/arm64/boot/dts/qcom/sm6375.dtsi
+index 7ac8bf26dda3a..a74472ac6186d 100644
+--- a/arch/arm64/boot/dts/qcom/sm6375.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm6375.dtsi
+@@ -1559,7 +1559,7 @@ remoteproc_adsp: remoteproc@a400000 {
+ compatible = "qcom,sm6375-adsp-pas";
+ reg = <0 0x0a400000 0 0x100>;
+
+- interrupts-extended = <&intc GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts-extended = <&intc GIC_SPI 282 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
+diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
+index 760501c1301a6..b07a3bad6eb96 100644
+--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
+@@ -3025,7 +3025,7 @@ slpi: remoteproc@5c00000 {
+ compatible = "qcom,sm8250-slpi-pas";
+ reg = <0 0x05c00000 0 0x4000>;
+
+- interrupts-extended = <&pdc 9 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts-extended = <&pdc 9 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_slpi_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_slpi_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_slpi_in 2 IRQ_TYPE_EDGE_RISING>,
+@@ -3729,7 +3729,7 @@ cdsp: remoteproc@8300000 {
+ compatible = "qcom,sm8250-cdsp-pas";
+ reg = <0 0x08300000 0 0x10000>;
+
+- interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>,
+@@ -5887,7 +5887,7 @@ adsp: remoteproc@17300000 {
+ compatible = "qcom,sm8250-adsp-pas";
+ reg = <0 0x17300000 0 0x100>;
+
+- interrupts-extended = <&pdc 6 IRQ_TYPE_LEVEL_HIGH>,
++ interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
+diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
+index 06f183ef8c78f..b72a48c1d3ba4 100644
+--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
+@@ -1777,12 +1777,8 @@ pcie0: pcie@1c00000 {
+ ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>,
+ <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>;
+
+- /*
+- * MSIs for BDF (1:0.0) only works with Device ID 0x5980.
+- * Hence, the IDs are swapped.
+- */
+- msi-map = <0x0 &gic_its 0x5981 0x1>,
+- <0x100 &gic_its 0x5980 0x1>;
++ msi-map = <0x0 &gic_its 0x5980 0x1>,
++ <0x100 &gic_its 0x5981 0x1>;
+ msi-map-mask = <0xff00>;
+ interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+@@ -1886,12 +1882,8 @@ pcie1: pcie@1c08000 {
+ ranges = <0x01000000 0x0 0x00000000 0x0 0x40200000 0x0 0x100000>,
+ <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>;
+
+- /*
+- * MSIs for BDF (1:0.0) only works with Device ID 0x5a00.
+- * Hence, the IDs are swapped.
+- */
+- msi-map = <0x0 &gic_its 0x5a01 0x1>,
+- <0x100 &gic_its 0x5a00 0x1>;
++ msi-map = <0x0 &gic_its 0x5a00 0x1>,
++ <0x100 &gic_its 0x5a01 0x1>;
+ msi-map-mask = <0xff00>;
+ interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+diff --git a/arch/arm64/boot/dts/qcom/x1e80100.dtsi b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
+index be1285d9919e0..5ba7924aa4355 100644
+--- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi
++++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
+@@ -278,7 +278,7 @@ CLUSTER_C4: cpu-sleep-0 {
+
+ domain-idle-states {
+ CLUSTER_CL4: cluster-sleep-0 {
+- compatible = "arm,idle-state";
++ compatible = "domain-idle-state";
+ idle-state-name = "l2-ret";
+ arm,psci-suspend-param = <0x01000044>;
+ entry-latency-us = <350>;
+@@ -287,7 +287,7 @@ CLUSTER_CL4: cluster-sleep-0 {
+ };
+
+ CLUSTER_CL5: cluster-sleep-1 {
+- compatible = "arm,idle-state";
++ compatible = "domain-idle-state";
+ idle-state-name = "ret-pll-off";
+ arm,psci-suspend-param = <0x01000054>;
+ entry-latency-us = <2200>;
+diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
+index 054c6a4d1a45f..294eb2de263de 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
+@@ -779,7 +779,6 @@ &pcie_phy {
+ };
+
+ &pcie0 {
+- bus-scan-delay-ms = <1000>;
+ ep-gpios = <&gpio2 RK_PD4 GPIO_ACTIVE_HIGH>;
+ num-lanes = <4>;
+ pinctrl-names = "default";
+diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
+index c08e69391c015..2484ad2bd86fc 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
+@@ -416,16 +416,22 @@ &io_domains {
+ gpio1830-supply = <&vcc_1v8>;
+ };
+
+-&pmu_io_domains {
+- status = "okay";
+- pmu1830-supply = <&vcc_1v8>;
+-};
+-
+-&pwm2 {
+- status = "okay";
++&pcie_clkreqn_cpm {
++ rockchip,pins =
++ <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ &pinctrl {
++ pinctrl-names = "default";
++ pinctrl-0 = <&q7_thermal_pin>;
++
++ gpios {
++ q7_thermal_pin: q7-thermal-pin {
++ rockchip,pins =
++ <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
++ };
++ };
++
+ i2c8 {
+ i2c8_xfer_a: i2c8-xfer {
+ rockchip,pins =
+@@ -458,11 +464,20 @@ vcc5v0_host_en: vcc5v0-host-en {
+ usb3 {
+ usb3_id: usb3-id {
+ rockchip,pins =
+- <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
++ <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+ };
+
++&pmu_io_domains {
++ status = "okay";
++ pmu1830-supply = <&vcc_1v8>;
++};
++
++&pwm2 {
++ status = "okay";
++};
++
+ &sdhci {
+ /*
+ * Signal integrity isn't great at 200MHz but 100MHz has proven stable
+diff --git a/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts b/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
+index f9127ddfbb7df..dc5892d25c100 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3568-bpi-r2-pro.dts
+@@ -416,6 +416,8 @@ regulator-state-mem {
+
+ vccio_sd: LDO_REG5 {
+ regulator-name = "vccio_sd";
++ regulator-always-on;
++ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+
+@@ -525,9 +527,9 @@ &mdio0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+- switch@0 {
++ switch@1f {
+ compatible = "mediatek,mt7531";
+- reg = <0>;
++ reg = <0x1f>;
+
+ ports {
+ #address-cells = <1>;
+diff --git a/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi
+index cce1c8e835877..94ecb9b4f98f8 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi
++++ b/arch/arm64/boot/dts/rockchip/rk3588-coolpi-cm5.dtsi
+@@ -216,9 +216,9 @@ &i2c7 {
+ pinctrl-0 = <&i2c7m0_xfer>;
+ status = "okay";
+
+- es8316: audio-codec@11 {
++ es8316: audio-codec@10 {
+ compatible = "everest,es8316";
+- reg = <0x11>;
++ reg = <0x10>;
+ assigned-clocks = <&cru I2S0_8CH_MCLKOUT>;
+ assigned-clock-rates = <12288000>;
+ clocks = <&cru I2S0_8CH_MCLKOUT>;
+diff --git a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
+index 3e660ff6cd5ff..e74871491ef56 100644
+--- a/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
++++ b/arch/arm64/boot/dts/rockchip/rk3588-orangepi-5-plus.dts
+@@ -486,6 +486,7 @@ pmic@0 {
+ pinctrl-0 = <&pmic_pins>, <&rk806_dvs1_null>,
+ <&rk806_dvs2_null>, <&rk806_dvs3_null>;
+ spi-max-frequency = <1000000>;
++ system-power-controller;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+@@ -507,7 +508,7 @@ pmic@0 {
+ #gpio-cells = <2>;
+
+ rk806_dvs1_null: dvs1-null-pins {
+- pins = "gpio_pwrctrl2";
++ pins = "gpio_pwrctrl1";
+ function = "pin_fun0";
+ };
+
+diff --git a/arch/loongarch/include/asm/perf_event.h b/arch/loongarch/include/asm/perf_event.h
+index 2a35a0bc2aaab..52b638059e40b 100644
+--- a/arch/loongarch/include/asm/perf_event.h
++++ b/arch/loongarch/include/asm/perf_event.h
+@@ -7,6 +7,14 @@
+ #ifndef __LOONGARCH_PERF_EVENT_H__
+ #define __LOONGARCH_PERF_EVENT_H__
+
++#include <asm/ptrace.h>
++
+ #define perf_arch_bpf_user_pt_regs(regs) (struct user_pt_regs *)regs
+
++#define perf_arch_fetch_caller_regs(regs, __ip) { \
++ (regs)->csr_era = (__ip); \
++ (regs)->regs[3] = current_stack_pointer; \
++ (regs)->regs[22] = (unsigned long) __builtin_frame_address(0); \
++}
++
+ #endif /* __LOONGARCH_PERF_EVENT_H__ */
+diff --git a/arch/loongarch/mm/fault.c b/arch/loongarch/mm/fault.c
+index 1fc2f6813ea02..97b40defde060 100644
+--- a/arch/loongarch/mm/fault.c
++++ b/arch/loongarch/mm/fault.c
+@@ -202,10 +202,10 @@ static void __kprobes __do_page_fault(struct pt_regs *regs,
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ } else {
+- if (!(vma->vm_flags & VM_READ) && address != exception_era(regs))
+- goto bad_area;
+ if (!(vma->vm_flags & VM_EXEC) && address == exception_era(regs))
+ goto bad_area;
++ if (!(vma->vm_flags & (VM_READ | VM_WRITE)) && address != exception_era(regs))
++ goto bad_area;
+ }
+
+ /*
+diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h
+index 57e887bfa34cb..94b3d6930fc37 100644
+--- a/arch/riscv/include/asm/page.h
++++ b/arch/riscv/include/asm/page.h
+@@ -89,7 +89,7 @@ typedef struct page *pgtable_t;
+ #define PTE_FMT "%08lx"
+ #endif
+
+-#ifdef CONFIG_64BIT
++#if defined(CONFIG_64BIT) && defined(CONFIG_MMU)
+ /*
+ * We override this value as its generic definition uses __pa too early in
+ * the boot process (before kernel_map.va_pa_offset is set).
+diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
+index 3422ced8a07fd..39c6bb8254683 100644
+--- a/arch/riscv/include/asm/pgtable.h
++++ b/arch/riscv/include/asm/pgtable.h
+@@ -888,7 +888,7 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
+ #define PAGE_SHARED __pgprot(0)
+ #define PAGE_KERNEL __pgprot(0)
+ #define swapper_pg_dir NULL
+-#define TASK_SIZE 0xffffffffUL
++#define TASK_SIZE _AC(-1, UL)
+ #define VMALLOC_START _AC(0, UL)
+ #define VMALLOC_END TASK_SIZE
+
+diff --git a/arch/riscv/include/uapi/asm/hwprobe.h b/arch/riscv/include/uapi/asm/hwprobe.h
+index 9f2a8e3ff2048..2902f68dc913a 100644
+--- a/arch/riscv/include/uapi/asm/hwprobe.h
++++ b/arch/riscv/include/uapi/asm/hwprobe.h
+@@ -54,7 +54,7 @@ struct riscv_hwprobe {
+ #define RISCV_HWPROBE_EXT_ZFHMIN (1 << 28)
+ #define RISCV_HWPROBE_EXT_ZIHINTNTL (1 << 29)
+ #define RISCV_HWPROBE_EXT_ZVFH (1 << 30)
+-#define RISCV_HWPROBE_EXT_ZVFHMIN (1 << 31)
++#define RISCV_HWPROBE_EXT_ZVFHMIN (1ULL << 31)
+ #define RISCV_HWPROBE_EXT_ZFA (1ULL << 32)
+ #define RISCV_HWPROBE_EXT_ZTSO (1ULL << 33)
+ #define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34)
+diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
+index fa34cf55037bd..0c00efc75643a 100644
+--- a/arch/riscv/mm/init.c
++++ b/arch/riscv/mm/init.c
+@@ -232,7 +232,7 @@ static void __init setup_bootmem(void)
+ * In 64-bit, any use of __va/__pa before this point is wrong as we
+ * did not know the start of DRAM before.
+ */
+- if (IS_ENABLED(CONFIG_64BIT))
++ if (IS_ENABLED(CONFIG_64BIT) && IS_ENABLED(CONFIG_MMU))
+ kernel_map.va_pa_offset = PAGE_OFFSET - phys_ram_base;
+
+ /*
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index b07f8b007ed9b..6f49999a6b838 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -62,6 +62,7 @@ config X86
+ select ACPI_HOTPLUG_CPU if ACPI_PROCESSOR && HOTPLUG_CPU
+ select ARCH_32BIT_OFF_T if X86_32
+ select ARCH_CLOCKSOURCE_INIT
++ select ARCH_CONFIGURES_CPU_MITIGATIONS
+ select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
+ select ARCH_ENABLE_HUGEPAGE_MIGRATION if X86_64 && HUGETLB_PAGE && MIGRATION
+ select ARCH_ENABLE_MEMORY_HOTPLUG if X86_64
+@@ -2467,17 +2468,17 @@ config PREFIX_SYMBOLS
+ def_bool y
+ depends on CALL_PADDING && !CFI_CLANG
+
+-menuconfig SPECULATION_MITIGATIONS
+- bool "Mitigations for speculative execution vulnerabilities"
++menuconfig CPU_MITIGATIONS
++ bool "Mitigations for CPU vulnerabilities"
+ default y
+ help
+- Say Y here to enable options which enable mitigations for
+- speculative execution hardware vulnerabilities.
++ Say Y here to enable options which enable mitigations for hardware
++ vulnerabilities (usually related to speculative execution).
+
+ If you say N, all mitigations will be disabled. You really
+ should know what you are doing to say so.
+
+-if SPECULATION_MITIGATIONS
++if CPU_MITIGATIONS
+
+ config PAGE_TABLE_ISOLATION
+ bool "Remove the kernel mapping in user mode"
+diff --git a/arch/x86/include/asm/coco.h b/arch/x86/include/asm/coco.h
+index 3dd052bfefc51..a368afce372b9 100644
+--- a/arch/x86/include/asm/coco.h
++++ b/arch/x86/include/asm/coco.h
+@@ -24,6 +24,7 @@ u64 cc_mkdec(u64 val);
+ void cc_random_init(void);
+ #else
+ #define cc_vendor (CC_VENDOR_NONE)
++static const u64 cc_mask = 0;
+
+ static inline u64 cc_mkenc(u64 val)
+ {
+diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
+index 0b748ee16b3d9..9abb8cc4cd474 100644
+--- a/arch/x86/include/asm/pgtable_types.h
++++ b/arch/x86/include/asm/pgtable_types.h
+@@ -148,7 +148,7 @@
+ #define _COMMON_PAGE_CHG_MASK (PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT | \
+ _PAGE_SPECIAL | _PAGE_ACCESSED | \
+ _PAGE_DIRTY_BITS | _PAGE_SOFT_DIRTY | \
+- _PAGE_DEVMAP | _PAGE_ENC | _PAGE_UFFD_WP)
++ _PAGE_DEVMAP | _PAGE_CC | _PAGE_UFFD_WP)
+ #define _PAGE_CHG_MASK (_COMMON_PAGE_CHG_MASK | _PAGE_PAT)
+ #define _HPAGE_CHG_MASK (_COMMON_PAGE_CHG_MASK | _PAGE_PSE | _PAGE_PAT_LARGE)
+
+@@ -173,6 +173,7 @@ enum page_cache_mode {
+ };
+ #endif
+
++#define _PAGE_CC (_AT(pteval_t, cc_mask))
+ #define _PAGE_ENC (_AT(pteval_t, sme_me_mask))
+
+ #define _PAGE_CACHE_MASK (_PAGE_PWT | _PAGE_PCD | _PAGE_PAT)
+diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
+index dfa8d0cf5e185..0838ea579eb0f 100644
+--- a/arch/x86/kernel/cpu/amd.c
++++ b/arch/x86/kernel/cpu/amd.c
+@@ -572,8 +572,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
+
+ case 0x1a:
+ switch (c->x86_model) {
+- case 0x00 ... 0x0f:
+- case 0x20 ... 0x2f:
++ case 0x00 ... 0x2f:
+ case 0x40 ... 0x4f:
+ case 0x70 ... 0x7f:
+ setup_force_cpu_cap(X86_FEATURE_ZEN5);
+diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
+index 33b268747bb7b..4989095ab7696 100644
+--- a/arch/x86/kernel/process_64.c
++++ b/arch/x86/kernel/process_64.c
+@@ -138,7 +138,7 @@ void __show_regs(struct pt_regs *regs, enum show_regs_mode mode,
+ log_lvl, d3, d6, d7);
+ }
+
+- if (cpu_feature_enabled(X86_FEATURE_OSPKE))
++ if (cr4 & X86_CR4_PKE)
+ printk("%sPKRU: %08x\n", log_lvl, read_pkru());
+ }
+
+diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
+index 87cc6c8809ad8..2ab2d5213f52f 100644
+--- a/arch/x86/kvm/pmu.c
++++ b/arch/x86/kvm/pmu.c
+@@ -741,6 +741,8 @@ static void kvm_pmu_reset(struct kvm_vcpu *vcpu)
+ */
+ void kvm_pmu_refresh(struct kvm_vcpu *vcpu)
+ {
++ struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
++
+ if (KVM_BUG_ON(kvm_vcpu_has_run(vcpu), vcpu->kvm))
+ return;
+
+@@ -750,8 +752,34 @@ void kvm_pmu_refresh(struct kvm_vcpu *vcpu)
+ */
+ kvm_pmu_reset(vcpu);
+
+- bitmap_zero(vcpu_to_pmu(vcpu)->all_valid_pmc_idx, X86_PMC_IDX_MAX);
++ pmu->version = 0;
++ pmu->nr_arch_gp_counters = 0;
++ pmu->nr_arch_fixed_counters = 0;
++ pmu->counter_bitmask[KVM_PMC_GP] = 0;
++ pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
++ pmu->reserved_bits = 0xffffffff00200000ull;
++ pmu->raw_event_mask = X86_RAW_EVENT_MASK;
++ pmu->global_ctrl_mask = ~0ull;
++ pmu->global_status_mask = ~0ull;
++ pmu->fixed_ctr_ctrl_mask = ~0ull;
++ pmu->pebs_enable_mask = ~0ull;
++ pmu->pebs_data_cfg_mask = ~0ull;
++ bitmap_zero(pmu->all_valid_pmc_idx, X86_PMC_IDX_MAX);
++
++ if (!vcpu->kvm->arch.enable_pmu)
++ return;
++
+ static_call(kvm_x86_pmu_refresh)(vcpu);
++
++ /*
++ * At RESET, both Intel and AMD CPUs set all enable bits for general
++ * purpose counters in IA32_PERF_GLOBAL_CTRL (so that software that
++ * was written for v1 PMUs don't unknowingly leave GP counters disabled
++ * in the global controls). Emulate that behavior when refreshing the
++ * PMU so that userspace doesn't need to manually set PERF_GLOBAL_CTRL.
++ */
++ if (kvm_pmu_has_perf_global_ctrl(pmu) && pmu->nr_arch_gp_counters)
++ pmu->global_ctrl = GENMASK_ULL(pmu->nr_arch_gp_counters - 1, 0);
+ }
+
+ void kvm_pmu_init(struct kvm_vcpu *vcpu)
+diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
+index 315c7c2ba89b1..600a021ae958b 100644
+--- a/arch/x86/kvm/vmx/pmu_intel.c
++++ b/arch/x86/kvm/vmx/pmu_intel.c
+@@ -491,19 +491,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ u64 counter_mask;
+ int i;
+
+- pmu->nr_arch_gp_counters = 0;
+- pmu->nr_arch_fixed_counters = 0;
+- pmu->counter_bitmask[KVM_PMC_GP] = 0;
+- pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
+- pmu->version = 0;
+- pmu->reserved_bits = 0xffffffff00200000ull;
+- pmu->raw_event_mask = X86_RAW_EVENT_MASK;
+- pmu->global_ctrl_mask = ~0ull;
+- pmu->global_status_mask = ~0ull;
+- pmu->fixed_ctr_ctrl_mask = ~0ull;
+- pmu->pebs_enable_mask = ~0ull;
+- pmu->pebs_data_cfg_mask = ~0ull;
+-
+ memset(&lbr_desc->records, 0, sizeof(lbr_desc->records));
+
+ /*
+@@ -515,8 +502,9 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ return;
+
+ entry = kvm_find_cpuid_entry(vcpu, 0xa);
+- if (!entry || !vcpu->kvm->arch.enable_pmu)
++ if (!entry)
+ return;
++
+ eax.full = entry->eax;
+ edx.full = entry->edx;
+
+diff --git a/block/bdev.c b/block/bdev.c
+index 2b0f97651a0a7..812872cdc0bef 100644
+--- a/block/bdev.c
++++ b/block/bdev.c
+@@ -873,7 +873,7 @@ struct bdev_handle *bdev_open_by_dev(dev_t dev, blk_mode_t mode, void *holder,
+ goto abort_claiming;
+ ret = -EBUSY;
+ if (!bdev_may_open(bdev, mode))
+- goto abort_claiming;
++ goto put_module;
+ if (bdev_is_partition(bdev))
+ ret = blkdev_get_part(bdev, mode);
+ else
+diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
+index d155a86a86148..1b27ebc6d01d0 100644
+--- a/drivers/acpi/cppc_acpi.c
++++ b/drivers/acpi/cppc_acpi.c
+@@ -166,6 +166,13 @@ show_cppc_data(cppc_get_perf_caps, cppc_perf_caps, nominal_freq);
+ show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, reference_perf);
+ show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, wraparound_time);
+
++/* Check for valid access_width, otherwise, fallback to using bit_width */
++#define GET_BIT_WIDTH(reg) ((reg)->access_width ? (8 << ((reg)->access_width - 1)) : (reg)->bit_width)
++
++/* Shift and apply the mask for CPC reads/writes */
++#define MASK_VAL(reg, val) (((val) >> (reg)->bit_offset) & \
++ GENMASK(((reg)->bit_width) - 1, 0))
++
+ static ssize_t show_feedback_ctrs(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+ {
+@@ -780,6 +787,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
+ } else if (gas_t->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+ if (gas_t->address) {
+ void __iomem *addr;
++ size_t access_width;
+
+ if (!osc_cpc_flexible_adr_space_confirmed) {
+ pr_debug("Flexible address space capability not supported\n");
+@@ -787,7 +795,8 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
+ goto out_free;
+ }
+
+- addr = ioremap(gas_t->address, gas_t->bit_width/8);
++ access_width = GET_BIT_WIDTH(gas_t) / 8;
++ addr = ioremap(gas_t->address, access_width);
+ if (!addr)
+ goto out_free;
+ cpc_ptr->cpc_regs[i-2].sys_mem_vaddr = addr;
+@@ -983,6 +992,7 @@ int __weak cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val)
+ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
+ {
+ void __iomem *vaddr = NULL;
++ int size;
+ int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
+ struct cpc_reg *reg = ®_res->cpc_entry.reg;
+
+@@ -992,14 +1002,14 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
+ }
+
+ *val = 0;
++ size = GET_BIT_WIDTH(reg);
+
+ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
+- u32 width = 8 << (reg->access_width - 1);
+ u32 val_u32;
+ acpi_status status;
+
+ status = acpi_os_read_port((acpi_io_address)reg->address,
+- &val_u32, width);
++ &val_u32, size);
+ if (ACPI_FAILURE(status)) {
+ pr_debug("Error: Failed to read SystemIO port %llx\n",
+ reg->address);
+@@ -1008,17 +1018,24 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
+
+ *val = val_u32;
+ return 0;
+- } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
++ } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) {
++ /*
++ * For registers in PCC space, the register size is determined
++ * by the bit width field; the access size is used to indicate
++ * the PCC subspace id.
++ */
++ size = reg->bit_width;
+ vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
++ }
+ else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ vaddr = reg_res->sys_mem_vaddr;
+ else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE)
+ return cpc_read_ffh(cpu, reg, val);
+ else
+ return acpi_os_read_memory((acpi_physical_address)reg->address,
+- val, reg->bit_width);
++ val, size);
+
+- switch (reg->bit_width) {
++ switch (size) {
+ case 8:
+ *val = readb_relaxed(vaddr);
+ break;
+@@ -1032,27 +1049,37 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val)
+ *val = readq_relaxed(vaddr);
+ break;
+ default:
+- pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n",
+- reg->bit_width, pcc_ss_id);
++ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
++ pr_debug("Error: Cannot read %u bit width from system memory: 0x%llx\n",
++ size, reg->address);
++ } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
++ pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n",
++ size, pcc_ss_id);
++ }
+ return -EFAULT;
+ }
+
++ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
++ *val = MASK_VAL(reg, *val);
++
+ return 0;
+ }
+
+ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
+ {
+ int ret_val = 0;
++ int size;
+ void __iomem *vaddr = NULL;
+ int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu);
+ struct cpc_reg *reg = ®_res->cpc_entry.reg;
+
++ size = GET_BIT_WIDTH(reg);
++
+ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
+- u32 width = 8 << (reg->access_width - 1);
+ acpi_status status;
+
+ status = acpi_os_write_port((acpi_io_address)reg->address,
+- (u32)val, width);
++ (u32)val, size);
+ if (ACPI_FAILURE(status)) {
+ pr_debug("Error: Failed to write SystemIO port %llx\n",
+ reg->address);
+@@ -1060,17 +1087,27 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
+ }
+
+ return 0;
+- } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0)
++ } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) {
++ /*
++ * For registers in PCC space, the register size is determined
++ * by the bit width field; the access size is used to indicate
++ * the PCC subspace id.
++ */
++ size = reg->bit_width;
+ vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id);
++ }
+ else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
+ vaddr = reg_res->sys_mem_vaddr;
+ else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE)
+ return cpc_write_ffh(cpu, reg, val);
+ else
+ return acpi_os_write_memory((acpi_physical_address)reg->address,
+- val, reg->bit_width);
++ val, size);
++
++ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY)
++ val = MASK_VAL(reg, val);
+
+- switch (reg->bit_width) {
++ switch (size) {
+ case 8:
+ writeb_relaxed(val, vaddr);
+ break;
+@@ -1084,8 +1121,13 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val)
+ writeq_relaxed(val, vaddr);
+ break;
+ default:
+- pr_debug("Error: Cannot write %u bit width to PCC for ss: %d\n",
+- reg->bit_width, pcc_ss_id);
++ if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
++ pr_debug("Error: Cannot write %u bit width to system memory: 0x%llx\n",
++ size, reg->address);
++ } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {
++ pr_debug("Error: Cannot write %u bit width to PCC for ss: %d\n",
++ size, pcc_ss_id);
++ }
+ ret_val = -EFAULT;
+ break;
+ }
+diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
+index ac8ebccd35075..812fd2a8f853e 100644
+--- a/drivers/bluetooth/btmtk.c
++++ b/drivers/bluetooth/btmtk.c
+@@ -380,8 +380,10 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
+ switch (data->cd_info.state) {
+ case HCI_DEVCOREDUMP_IDLE:
+ err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE);
+- if (err < 0)
++ if (err < 0) {
++ kfree_skb(skb);
+ break;
++ }
+ data->cd_info.cnt = 0;
+
+ /* It is supposed coredump can be done within 5 seconds */
+@@ -407,9 +409,6 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
+ break;
+ }
+
+- if (err < 0)
+- kfree_skb(skb);
+-
+ return err;
+ }
+ EXPORT_SYMBOL_GPL(btmtk_process_coredump);
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index f684108dc2f1c..effa546296486 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -542,6 +542,8 @@ static const struct usb_device_id quirks_table[] = {
+ /* Realtek 8852BE Bluetooth devices */
+ { USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK |
+ BTUSB_WIDEBAND_SPEECH },
++ { USB_DEVICE(0x0bda, 0x4853), .driver_info = BTUSB_REALTEK |
++ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK |
+ BTUSB_WIDEBAND_SPEECH },
+ { USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK |
+@@ -3463,13 +3465,12 @@ static void btusb_dump_hdr_qca(struct hci_dev *hdev, struct sk_buff *skb)
+
+ static void btusb_coredump_qca(struct hci_dev *hdev)
+ {
++ int err;
+ static const u8 param[] = { 0x26 };
+- struct sk_buff *skb;
+
+- skb = __hci_cmd_sync(hdev, 0xfc0c, 1, param, HCI_CMD_TIMEOUT);
+- if (IS_ERR(skb))
+- bt_dev_err(hdev, "%s: triggle crash failed (%ld)", __func__, PTR_ERR(skb));
+- kfree_skb(skb);
++ err = __hci_cmd_send(hdev, 0xfc0c, 1, param);
++ if (err < 0)
++ bt_dev_err(hdev, "%s: triggle crash failed (%d)", __func__, err);
+ }
+
+ /*
+diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
+index ecbc52eaf1010..ce5c2aa743b08 100644
+--- a/drivers/bluetooth/hci_qca.c
++++ b/drivers/bluetooth/hci_qca.c
+@@ -1672,6 +1672,9 @@ static bool qca_wakeup(struct hci_dev *hdev)
+ struct hci_uart *hu = hci_get_drvdata(hdev);
+ bool wakeup;
+
++ if (!hu->serdev)
++ return true;
++
+ /* BT SoC attached through the serial bus is handled by the serdev driver.
+ * So we need to use the device handle of the serdev driver to get the
+ * status of device may wakeup.
+@@ -1957,8 +1960,10 @@ static int qca_setup(struct hci_uart *hu)
+ qca_debugfs_init(hdev);
+ hu->hdev->hw_error = qca_hw_error;
+ hu->hdev->cmd_timeout = qca_cmd_timeout;
+- if (device_can_wakeup(hu->serdev->ctrl->dev.parent))
+- hu->hdev->wakeup = qca_wakeup;
++ if (hu->serdev) {
++ if (device_can_wakeup(hu->serdev->ctrl->dev.parent))
++ hu->hdev->wakeup = qca_wakeup;
++ }
+ } else if (ret == -ENOENT) {
+ /* No patch/nvm-config found, run with original fw/config */
+ set_bit(QCA_ROM_FW, &qca->flags);
+@@ -2329,16 +2334,21 @@ static int qca_serdev_probe(struct serdev_device *serdev)
+ (data->soc_type == QCA_WCN6750 ||
+ data->soc_type == QCA_WCN6855)) {
+ dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n");
+- power_ctrl_enabled = false;
++ return PTR_ERR(qcadev->bt_en);
+ }
+
++ if (!qcadev->bt_en)
++ power_ctrl_enabled = false;
++
+ qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl",
+ GPIOD_IN);
+ if (IS_ERR(qcadev->sw_ctrl) &&
+ (data->soc_type == QCA_WCN6750 ||
+ data->soc_type == QCA_WCN6855 ||
+- data->soc_type == QCA_WCN7850))
+- dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n");
++ data->soc_type == QCA_WCN7850)) {
++ dev_err(&serdev->dev, "failed to acquire SW_CTRL gpio\n");
++ return PTR_ERR(qcadev->sw_ctrl);
++ }
+
+ qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
+ if (IS_ERR(qcadev->susclk)) {
+@@ -2357,10 +2367,13 @@ static int qca_serdev_probe(struct serdev_device *serdev)
+ qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(qcadev->bt_en)) {
+- dev_warn(&serdev->dev, "failed to acquire enable gpio\n");
+- power_ctrl_enabled = false;
++ dev_err(&serdev->dev, "failed to acquire enable gpio\n");
++ return PTR_ERR(qcadev->bt_en);
+ }
+
++ if (!qcadev->bt_en)
++ power_ctrl_enabled = false;
++
+ qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL);
+ if (IS_ERR(qcadev->susclk)) {
+ dev_warn(&serdev->dev, "failed to acquire clk\n");
+diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
+index f0f54aeccc872..65185c9fa0013 100644
+--- a/drivers/cxl/core/mbox.c
++++ b/drivers/cxl/core/mbox.c
+@@ -946,25 +946,22 @@ static void cxl_mem_get_records_log(struct cxl_memdev_state *mds,
+ struct cxl_memdev *cxlmd = mds->cxlds.cxlmd;
+ struct device *dev = mds->cxlds.dev;
+ struct cxl_get_event_payload *payload;
+- struct cxl_mbox_cmd mbox_cmd;
+ u8 log_type = type;
+ u16 nr_rec;
+
+ mutex_lock(&mds->event.log_lock);
+ payload = mds->event.buf;
+
+- mbox_cmd = (struct cxl_mbox_cmd) {
+- .opcode = CXL_MBOX_OP_GET_EVENT_RECORD,
+- .payload_in = &log_type,
+- .size_in = sizeof(log_type),
+- .payload_out = payload,
+- .min_out = struct_size(payload, records, 0),
+- };
+-
+ do {
+ int rc, i;
+-
+- mbox_cmd.size_out = mds->payload_size;
++ struct cxl_mbox_cmd mbox_cmd = (struct cxl_mbox_cmd) {
++ .opcode = CXL_MBOX_OP_GET_EVENT_RECORD,
++ .payload_in = &log_type,
++ .size_in = sizeof(log_type),
++ .payload_out = payload,
++ .size_out = mds->payload_size,
++ .min_out = struct_size(payload, records, 0),
++ };
+
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
+ if (rc) {
+@@ -1297,7 +1294,6 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
+ struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
+ struct cxl_mbox_poison_out *po;
+ struct cxl_mbox_poison_in pi;
+- struct cxl_mbox_cmd mbox_cmd;
+ int nr_records = 0;
+ int rc;
+
+@@ -1309,16 +1305,16 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
+ pi.offset = cpu_to_le64(offset);
+ pi.length = cpu_to_le64(len / CXL_POISON_LEN_MULT);
+
+- mbox_cmd = (struct cxl_mbox_cmd) {
+- .opcode = CXL_MBOX_OP_GET_POISON,
+- .size_in = sizeof(pi),
+- .payload_in = &pi,
+- .size_out = mds->payload_size,
+- .payload_out = po,
+- .min_out = struct_size(po, record, 0),
+- };
+-
+ do {
++ struct cxl_mbox_cmd mbox_cmd = (struct cxl_mbox_cmd){
++ .opcode = CXL_MBOX_OP_GET_POISON,
++ .size_in = sizeof(pi),
++ .payload_in = &pi,
++ .size_out = mds->payload_size,
++ .payload_out = po,
++ .min_out = struct_size(po, record, 0),
++ };
++
+ rc = cxl_internal_send_cmd(mds, &mbox_cmd);
+ if (rc)
+ break;
+diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c
+index 78a938969d7d7..1398814d8fbb6 100644
+--- a/drivers/dma/idma64.c
++++ b/drivers/dma/idma64.c
+@@ -171,6 +171,10 @@ static irqreturn_t idma64_irq(int irq, void *dev)
+ u32 status_err;
+ unsigned short i;
+
++ /* Since IRQ may be shared, check if DMA controller is powered on */
++ if (status == GENMASK(31, 0))
++ return IRQ_NONE;
++
+ dev_vdbg(idma64->dma.dev, "%s: status=%#x\n", __func__, status);
+
+ /* Check if we have any interrupt from the DMA controller */
+diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c
+index e5a94a93a3cc4..59456f21778b4 100644
+--- a/drivers/dma/idxd/cdev.c
++++ b/drivers/dma/idxd/cdev.c
+@@ -342,7 +342,7 @@ static void idxd_cdev_evl_drain_pasid(struct idxd_wq *wq, u32 pasid)
+ if (!evl)
+ return;
+
+- spin_lock(&evl->lock);
++ mutex_lock(&evl->lock);
+ status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
+ t = status.tail;
+ h = status.head;
+@@ -354,9 +354,8 @@ static void idxd_cdev_evl_drain_pasid(struct idxd_wq *wq, u32 pasid)
+ set_bit(h, evl->bmap);
+ h = (h + 1) % size;
+ }
+- spin_unlock(&evl->lock);
+-
+ drain_workqueue(wq->wq);
++ mutex_unlock(&evl->lock);
+ }
+
+ static int idxd_cdev_release(struct inode *node, struct file *filep)
+diff --git a/drivers/dma/idxd/debugfs.c b/drivers/dma/idxd/debugfs.c
+index f3f25ee676f30..ad4245cb301d5 100644
+--- a/drivers/dma/idxd/debugfs.c
++++ b/drivers/dma/idxd/debugfs.c
+@@ -66,7 +66,7 @@ static int debugfs_evl_show(struct seq_file *s, void *d)
+ if (!evl || !evl->log)
+ return 0;
+
+- spin_lock(&evl->lock);
++ mutex_lock(&evl->lock);
+
+ evl_status.bits = ioread64(idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
+ t = evl_status.tail;
+@@ -87,7 +87,7 @@ static int debugfs_evl_show(struct seq_file *s, void *d)
+ dump_event_entry(idxd, s, i, &count, processed);
+ }
+
+- spin_unlock(&evl->lock);
++ mutex_unlock(&evl->lock);
+ return 0;
+ }
+
+diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
+index ecfdf4a8f1f83..c41ef195eeb9f 100644
+--- a/drivers/dma/idxd/device.c
++++ b/drivers/dma/idxd/device.c
+@@ -775,7 +775,7 @@ static int idxd_device_evl_setup(struct idxd_device *idxd)
+ goto err_alloc;
+ }
+
+- spin_lock(&evl->lock);
++ mutex_lock(&evl->lock);
+ evl->log = addr;
+ evl->dma = dma_addr;
+ evl->log_size = size;
+@@ -796,7 +796,7 @@ static int idxd_device_evl_setup(struct idxd_device *idxd)
+ gencfg.evl_en = 1;
+ iowrite32(gencfg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET);
+
+- spin_unlock(&evl->lock);
++ mutex_unlock(&evl->lock);
+ return 0;
+
+ err_alloc:
+@@ -819,7 +819,7 @@ static void idxd_device_evl_free(struct idxd_device *idxd)
+ if (!gencfg.evl_en)
+ return;
+
+- spin_lock(&evl->lock);
++ mutex_lock(&evl->lock);
+ gencfg.evl_en = 0;
+ iowrite32(gencfg.bits, idxd->reg_base + IDXD_GENCFG_OFFSET);
+
+@@ -836,7 +836,7 @@ static void idxd_device_evl_free(struct idxd_device *idxd)
+ evl_dma = evl->dma;
+ evl->log = NULL;
+ evl->size = IDXD_EVL_SIZE_MIN;
+- spin_unlock(&evl->lock);
++ mutex_unlock(&evl->lock);
+
+ dma_free_coherent(dev, evl_log_size, evl_log, evl_dma);
+ }
+diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h
+index d0f5db6cf1eda..df91472f0f5b1 100644
+--- a/drivers/dma/idxd/idxd.h
++++ b/drivers/dma/idxd/idxd.h
+@@ -293,7 +293,7 @@ struct idxd_driver_data {
+
+ struct idxd_evl {
+ /* Lock to protect event log access. */
+- spinlock_t lock;
++ struct mutex lock;
+ void *log;
+ dma_addr_t dma;
+ /* Total size of event log = number of entries * entry size. */
+diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
+index 4954adc6bb609..264c4e47d7cca 100644
+--- a/drivers/dma/idxd/init.c
++++ b/drivers/dma/idxd/init.c
+@@ -354,7 +354,7 @@ static int idxd_init_evl(struct idxd_device *idxd)
+ if (!evl)
+ return -ENOMEM;
+
+- spin_lock_init(&evl->lock);
++ mutex_init(&evl->lock);
+ evl->size = IDXD_EVL_SIZE_MIN;
+
+ idxd_name = dev_name(idxd_confdev(idxd));
+diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c
+index 348aa21389a9f..8dc029c865515 100644
+--- a/drivers/dma/idxd/irq.c
++++ b/drivers/dma/idxd/irq.c
+@@ -363,7 +363,7 @@ static void process_evl_entries(struct idxd_device *idxd)
+ evl_status.bits = 0;
+ evl_status.int_pending = 1;
+
+- spin_lock(&evl->lock);
++ mutex_lock(&evl->lock);
+ /* Clear interrupt pending bit */
+ iowrite32(evl_status.bits_upper32,
+ idxd->reg_base + IDXD_EVLSTATUS_OFFSET + sizeof(u32));
+@@ -380,7 +380,7 @@ static void process_evl_entries(struct idxd_device *idxd)
+
+ evl_status.head = h;
+ iowrite32(evl_status.bits_lower32, idxd->reg_base + IDXD_EVLSTATUS_OFFSET);
+- spin_unlock(&evl->lock);
++ mutex_unlock(&evl->lock);
+ }
+
+ irqreturn_t idxd_misc_thread(int vec, void *data)
+diff --git a/drivers/dma/idxd/perfmon.c b/drivers/dma/idxd/perfmon.c
+index fdda6d6042629..5e94247e1ea70 100644
+--- a/drivers/dma/idxd/perfmon.c
++++ b/drivers/dma/idxd/perfmon.c
+@@ -528,14 +528,11 @@ static int perf_event_cpu_offline(unsigned int cpu, struct hlist_node *node)
+ return 0;
+
+ target = cpumask_any_but(cpu_online_mask, cpu);
+-
+ /* migrate events if there is a valid target */
+- if (target < nr_cpu_ids)
++ if (target < nr_cpu_ids) {
+ cpumask_set_cpu(target, &perfmon_dsa_cpu_mask);
+- else
+- target = -1;
+-
+- perf_pmu_migrate_context(&idxd_pmu->pmu, cpu, target);
++ perf_pmu_migrate_context(&idxd_pmu->pmu, cpu, target);
++ }
+
+ return 0;
+ }
+diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c
+index 4e76c4ec2d396..e001f4f7aa640 100644
+--- a/drivers/dma/owl-dma.c
++++ b/drivers/dma/owl-dma.c
+@@ -250,7 +250,7 @@ static void pchan_update(struct owl_dma_pchan *pchan, u32 reg,
+ else
+ regval &= ~val;
+
+- writel(val, pchan->base + reg);
++ writel(regval, pchan->base + reg);
+ }
+
+ static void pchan_writel(struct owl_dma_pchan *pchan, u32 reg, u32 data)
+@@ -274,7 +274,7 @@ static void dma_update(struct owl_dma *od, u32 reg, u32 val, bool state)
+ else
+ regval &= ~val;
+
+- writel(val, od->base + reg);
++ writel(regval, od->base + reg);
+ }
+
+ static void dma_writel(struct owl_dma *od, u32 reg, u32 data)
+diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
+index c29744bfdf2c2..3cf0b38387ae5 100644
+--- a/drivers/dma/pl330.c
++++ b/drivers/dma/pl330.c
+@@ -1053,9 +1053,6 @@ static bool _trigger(struct pl330_thread *thrd)
+
+ thrd->req_running = idx;
+
+- if (desc->rqtype == DMA_MEM_TO_DEV || desc->rqtype == DMA_DEV_TO_MEM)
+- UNTIL(thrd, PL330_STATE_WFP);
+-
+ return true;
+ }
+
+diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
+index 88547a23825b1..3642508e88bb2 100644
+--- a/drivers/dma/tegra186-gpc-dma.c
++++ b/drivers/dma/tegra186-gpc-dma.c
+@@ -746,6 +746,9 @@ static int tegra_dma_get_residual(struct tegra_dma_channel *tdc)
+ bytes_xfer = dma_desc->bytes_xfer +
+ sg_req[dma_desc->sg_idx].len - (wcount * 4);
+
++ if (dma_desc->bytes_req == bytes_xfer)
++ return 0;
++
+ residual = dma_desc->bytes_req - (bytes_xfer % dma_desc->bytes_req);
+
+ return residual;
+diff --git a/drivers/dma/xilinx/xdma-regs.h b/drivers/dma/xilinx/xdma-regs.h
+index 98f5f6fb9ff9c..6ad08878e9386 100644
+--- a/drivers/dma/xilinx/xdma-regs.h
++++ b/drivers/dma/xilinx/xdma-regs.h
+@@ -117,6 +117,9 @@ struct xdma_hw_desc {
+ CHAN_CTRL_IE_WRITE_ERROR | \
+ CHAN_CTRL_IE_DESC_ERROR)
+
++/* bits of the channel status register */
++#define XDMA_CHAN_STATUS_BUSY BIT(0)
++
+ #define XDMA_CHAN_STATUS_MASK CHAN_CTRL_START
+
+ #define XDMA_CHAN_ERROR_MASK (CHAN_CTRL_IE_DESC_ALIGN_MISMATCH | \
+diff --git a/drivers/dma/xilinx/xdma.c b/drivers/dma/xilinx/xdma.c
+index 170017ff2aad6..5a3a3293b21b5 100644
+--- a/drivers/dma/xilinx/xdma.c
++++ b/drivers/dma/xilinx/xdma.c
+@@ -71,6 +71,8 @@ struct xdma_chan {
+ enum dma_transfer_direction dir;
+ struct dma_slave_config cfg;
+ u32 irq;
++ struct completion last_interrupt;
++ bool stop_requested;
+ };
+
+ /**
+@@ -376,6 +378,8 @@ static int xdma_xfer_start(struct xdma_chan *xchan)
+ return ret;
+
+ xchan->busy = true;
++ xchan->stop_requested = false;
++ reinit_completion(&xchan->last_interrupt);
+
+ return 0;
+ }
+@@ -387,7 +391,6 @@ static int xdma_xfer_start(struct xdma_chan *xchan)
+ static int xdma_xfer_stop(struct xdma_chan *xchan)
+ {
+ int ret;
+- u32 val;
+ struct xdma_device *xdev = xchan->xdev_hdl;
+
+ /* clear run stop bit to prevent any further auto-triggering */
+@@ -395,13 +398,7 @@ static int xdma_xfer_stop(struct xdma_chan *xchan)
+ CHAN_CTRL_RUN_STOP);
+ if (ret)
+ return ret;
+-
+- /* Clear the channel status register */
+- ret = regmap_read(xdev->rmap, xchan->base + XDMA_CHAN_STATUS_RC, &val);
+- if (ret)
+- return ret;
+-
+- return 0;
++ return ret;
+ }
+
+ /**
+@@ -474,6 +471,8 @@ static int xdma_alloc_channels(struct xdma_device *xdev,
+ xchan->xdev_hdl = xdev;
+ xchan->base = base + i * XDMA_CHAN_STRIDE;
+ xchan->dir = dir;
++ xchan->stop_requested = false;
++ init_completion(&xchan->last_interrupt);
+
+ ret = xdma_channel_init(xchan);
+ if (ret)
+@@ -521,6 +520,7 @@ static int xdma_terminate_all(struct dma_chan *chan)
+ spin_lock_irqsave(&xdma_chan->vchan.lock, flags);
+
+ xdma_chan->busy = false;
++ xdma_chan->stop_requested = true;
+ vd = vchan_next_desc(&xdma_chan->vchan);
+ if (vd) {
+ list_del(&vd->node);
+@@ -542,6 +542,13 @@ static int xdma_terminate_all(struct dma_chan *chan)
+ static void xdma_synchronize(struct dma_chan *chan)
+ {
+ struct xdma_chan *xdma_chan = to_xdma_chan(chan);
++ struct xdma_device *xdev = xdma_chan->xdev_hdl;
++ int st = 0;
++
++ /* If the engine continues running, wait for the last interrupt */
++ regmap_read(xdev->rmap, xdma_chan->base + XDMA_CHAN_STATUS, &st);
++ if (st & XDMA_CHAN_STATUS_BUSY)
++ wait_for_completion_timeout(&xdma_chan->last_interrupt, msecs_to_jiffies(1000));
+
+ vchan_synchronize(&xdma_chan->vchan);
+ }
+@@ -704,7 +711,7 @@ xdma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t address,
+ desc_num = 0;
+ for (i = 0; i < periods; i++) {
+ desc_num += xdma_fill_descs(sw_desc, *src, *dst, period_size, desc_num);
+- addr += i * period_size;
++ addr += period_size;
+ }
+
+ tx_desc = vchan_tx_prep(&xdma_chan->vchan, &sw_desc->vdesc, flags);
+@@ -876,6 +883,9 @@ static irqreturn_t xdma_channel_isr(int irq, void *dev_id)
+ u32 st;
+ bool repeat_tx;
+
++ if (xchan->stop_requested)
++ complete(&xchan->last_interrupt);
++
+ spin_lock(&xchan->vchan.lock);
+
+ /* get submitted request */
+diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c
+index b82815e64d24e..eb0637d90342a 100644
+--- a/drivers/dma/xilinx/xilinx_dpdma.c
++++ b/drivers/dma/xilinx/xilinx_dpdma.c
+@@ -214,7 +214,8 @@ struct xilinx_dpdma_tx_desc {
+ * @running: true if the channel is running
+ * @first_frame: flag for the first frame of stream
+ * @video_group: flag if multi-channel operation is needed for video channels
+- * @lock: lock to access struct xilinx_dpdma_chan
++ * @lock: lock to access struct xilinx_dpdma_chan. Must be taken before
++ * @vchan.lock, if both are to be held.
+ * @desc_pool: descriptor allocation pool
+ * @err_task: error IRQ bottom half handler
+ * @desc: References to descriptors being processed
+@@ -1097,12 +1098,14 @@ static void xilinx_dpdma_chan_vsync_irq(struct xilinx_dpdma_chan *chan)
+ * Complete the active descriptor, if any, promote the pending
+ * descriptor to active, and queue the next transfer, if any.
+ */
++ spin_lock(&chan->vchan.lock);
+ if (chan->desc.active)
+ vchan_cookie_complete(&chan->desc.active->vdesc);
+ chan->desc.active = pending;
+ chan->desc.pending = NULL;
+
+ xilinx_dpdma_chan_queue_transfer(chan);
++ spin_unlock(&chan->vchan.lock);
+
+ out:
+ spin_unlock_irqrestore(&chan->lock, flags);
+@@ -1264,10 +1267,12 @@ static void xilinx_dpdma_issue_pending(struct dma_chan *dchan)
+ struct xilinx_dpdma_chan *chan = to_xilinx_chan(dchan);
+ unsigned long flags;
+
+- spin_lock_irqsave(&chan->vchan.lock, flags);
++ spin_lock_irqsave(&chan->lock, flags);
++ spin_lock(&chan->vchan.lock);
+ if (vchan_issue_pending(&chan->vchan))
+ xilinx_dpdma_chan_queue_transfer(chan);
+- spin_unlock_irqrestore(&chan->vchan.lock, flags);
++ spin_unlock(&chan->vchan.lock);
++ spin_unlock_irqrestore(&chan->lock, flags);
+ }
+
+ static int xilinx_dpdma_config(struct dma_chan *dchan,
+@@ -1495,7 +1500,9 @@ static void xilinx_dpdma_chan_err_task(struct tasklet_struct *t)
+ XILINX_DPDMA_EINTR_CHAN_ERR_MASK << chan->id);
+
+ spin_lock_irqsave(&chan->lock, flags);
++ spin_lock(&chan->vchan.lock);
+ xilinx_dpdma_chan_queue_transfer(chan);
++ spin_unlock(&chan->vchan.lock);
+ spin_unlock_irqrestore(&chan->lock, flags);
+ }
+
+diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
+index c751a87c7a8e6..a6856730ca90f 100644
+--- a/drivers/dpll/dpll_core.c
++++ b/drivers/dpll/dpll_core.c
+@@ -29,6 +29,8 @@ static u32 dpll_pin_xa_id;
+ WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
+ #define ASSERT_DPLL_NOT_REGISTERED(d) \
+ WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
++#define ASSERT_DPLL_PIN_REGISTERED(p) \
++ WARN_ON_ONCE(!xa_get_mark(&dpll_pin_xa, (p)->id, DPLL_REGISTERED))
+
+ struct dpll_device_registration {
+ struct list_head list;
+@@ -40,6 +42,7 @@ struct dpll_pin_registration {
+ struct list_head list;
+ const struct dpll_pin_ops *ops;
+ void *priv;
++ void *cookie;
+ };
+
+ struct dpll_device *dpll_device_get_by_id(int id)
+@@ -52,12 +55,14 @@ struct dpll_device *dpll_device_get_by_id(int id)
+
+ static struct dpll_pin_registration *
+ dpll_pin_registration_find(struct dpll_pin_ref *ref,
+- const struct dpll_pin_ops *ops, void *priv)
++ const struct dpll_pin_ops *ops, void *priv,
++ void *cookie)
+ {
+ struct dpll_pin_registration *reg;
+
+ list_for_each_entry(reg, &ref->registration_list, list) {
+- if (reg->ops == ops && reg->priv == priv)
++ if (reg->ops == ops && reg->priv == priv &&
++ reg->cookie == cookie)
+ return reg;
+ }
+ return NULL;
+@@ -65,7 +70,8 @@ dpll_pin_registration_find(struct dpll_pin_ref *ref,
+
+ static int
+ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
+- const struct dpll_pin_ops *ops, void *priv)
++ const struct dpll_pin_ops *ops, void *priv,
++ void *cookie)
+ {
+ struct dpll_pin_registration *reg;
+ struct dpll_pin_ref *ref;
+@@ -76,7 +82,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
+ xa_for_each(xa_pins, i, ref) {
+ if (ref->pin != pin)
+ continue;
+- reg = dpll_pin_registration_find(ref, ops, priv);
++ reg = dpll_pin_registration_find(ref, ops, priv, cookie);
+ if (reg) {
+ refcount_inc(&ref->refcount);
+ return 0;
+@@ -109,6 +115,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
+ }
+ reg->ops = ops;
+ reg->priv = priv;
++ reg->cookie = cookie;
+ if (ref_exists)
+ refcount_inc(&ref->refcount);
+ list_add_tail(®->list, &ref->registration_list);
+@@ -117,7 +124,8 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin,
+ }
+
+ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
+- const struct dpll_pin_ops *ops, void *priv)
++ const struct dpll_pin_ops *ops, void *priv,
++ void *cookie)
+ {
+ struct dpll_pin_registration *reg;
+ struct dpll_pin_ref *ref;
+@@ -126,7 +134,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
+ xa_for_each(xa_pins, i, ref) {
+ if (ref->pin != pin)
+ continue;
+- reg = dpll_pin_registration_find(ref, ops, priv);
++ reg = dpll_pin_registration_find(ref, ops, priv, cookie);
+ if (WARN_ON(!reg))
+ return -EINVAL;
+ list_del(®->list);
+@@ -144,7 +152,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin,
+
+ static int
+ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
+- const struct dpll_pin_ops *ops, void *priv)
++ const struct dpll_pin_ops *ops, void *priv, void *cookie)
+ {
+ struct dpll_pin_registration *reg;
+ struct dpll_pin_ref *ref;
+@@ -155,7 +163,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
+ xa_for_each(xa_dplls, i, ref) {
+ if (ref->dpll != dpll)
+ continue;
+- reg = dpll_pin_registration_find(ref, ops, priv);
++ reg = dpll_pin_registration_find(ref, ops, priv, cookie);
+ if (reg) {
+ refcount_inc(&ref->refcount);
+ return 0;
+@@ -188,6 +196,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
+ }
+ reg->ops = ops;
+ reg->priv = priv;
++ reg->cookie = cookie;
+ if (ref_exists)
+ refcount_inc(&ref->refcount);
+ list_add_tail(®->list, &ref->registration_list);
+@@ -197,7 +206,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll,
+
+ static void
+ dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll,
+- const struct dpll_pin_ops *ops, void *priv)
++ const struct dpll_pin_ops *ops, void *priv, void *cookie)
+ {
+ struct dpll_pin_registration *reg;
+ struct dpll_pin_ref *ref;
+@@ -206,7 +215,7 @@ dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll,
+ xa_for_each(xa_dplls, i, ref) {
+ if (ref->dpll != dpll)
+ continue;
+- reg = dpll_pin_registration_find(ref, ops, priv);
++ reg = dpll_pin_registration_find(ref, ops, priv, cookie);
+ if (WARN_ON(!reg))
+ return;
+ list_del(®->list);
+@@ -592,14 +601,14 @@ EXPORT_SYMBOL_GPL(dpll_pin_put);
+
+ static int
+ __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
+- const struct dpll_pin_ops *ops, void *priv)
++ const struct dpll_pin_ops *ops, void *priv, void *cookie)
+ {
+ int ret;
+
+- ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv);
++ ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv, cookie);
+ if (ret)
+ return ret;
+- ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv);
++ ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv, cookie);
+ if (ret)
+ goto ref_pin_del;
+ xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
+@@ -608,7 +617,7 @@ __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
+ return ret;
+
+ ref_pin_del:
+- dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv);
++ dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie);
+ return ret;
+ }
+
+@@ -640,7 +649,7 @@ dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
+ dpll->clock_id == pin->clock_id)))
+ ret = -EINVAL;
+ else
+- ret = __dpll_pin_register(dpll, pin, ops, priv);
++ ret = __dpll_pin_register(dpll, pin, ops, priv, NULL);
+ mutex_unlock(&dpll_lock);
+
+ return ret;
+@@ -649,10 +658,11 @@ EXPORT_SYMBOL_GPL(dpll_pin_register);
+
+ static void
+ __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
+- const struct dpll_pin_ops *ops, void *priv)
++ const struct dpll_pin_ops *ops, void *priv, void *cookie)
+ {
+- dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv);
+- dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv);
++ ASSERT_DPLL_PIN_REGISTERED(pin);
++ dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie);
++ dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie);
+ if (xa_empty(&pin->dpll_refs))
+ xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED);
+ }
+@@ -677,7 +687,7 @@ void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
+
+ mutex_lock(&dpll_lock);
+ dpll_pin_delete_ntf(pin);
+- __dpll_pin_unregister(dpll, pin, ops, priv);
++ __dpll_pin_unregister(dpll, pin, ops, priv, NULL);
+ mutex_unlock(&dpll_lock);
+ }
+ EXPORT_SYMBOL_GPL(dpll_pin_unregister);
+@@ -713,12 +723,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
+ return -EINVAL;
+
+ mutex_lock(&dpll_lock);
+- ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv);
++ ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin);
+ if (ret)
+ goto unlock;
+ refcount_inc(&pin->refcount);
+ xa_for_each(&parent->dpll_refs, i, ref) {
+- ret = __dpll_pin_register(ref->dpll, pin, ops, priv);
++ ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent);
+ if (ret) {
+ stop = i;
+ goto dpll_unregister;
+@@ -732,11 +742,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
+ dpll_unregister:
+ xa_for_each(&parent->dpll_refs, i, ref)
+ if (i < stop) {
+- __dpll_pin_unregister(ref->dpll, pin, ops, priv);
++ __dpll_pin_unregister(ref->dpll, pin, ops, priv,
++ parent);
+ dpll_pin_delete_ntf(pin);
+ }
+ refcount_dec(&pin->refcount);
+- dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv);
++ dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
+ unlock:
+ mutex_unlock(&dpll_lock);
+ return ret;
+@@ -761,10 +772,10 @@ void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin,
+
+ mutex_lock(&dpll_lock);
+ dpll_pin_delete_ntf(pin);
+- dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv);
++ dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin);
+ refcount_dec(&pin->refcount);
+ xa_for_each(&pin->dpll_refs, i, ref)
+- __dpll_pin_unregister(ref->dpll, pin, ops, priv);
++ __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent);
+ mutex_unlock(&dpll_lock);
+ }
+ EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister);
+diff --git a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
+index 32188f098ef34..bc550ad0dbe0c 100644
+--- a/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
++++ b/drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
+@@ -221,6 +221,19 @@ struct qsee_rsp_uefi_query_variable_info {
+ * alignment of 8 bytes (64 bits) for GUIDs. Our definition of efi_guid_t,
+ * however, has an alignment of 4 byte (32 bits). So far, this seems to work
+ * fine here. See also the comment on the typedef of efi_guid_t.
++ *
++ * Note: It looks like uefisecapp is quite picky about how the memory passed to
++ * it is structured and aligned. In particular the request/response setup used
++ * for QSEE_CMD_UEFI_GET_VARIABLE. While qcom_qseecom_app_send(), in theory,
++ * accepts separate buffers/addresses for the request and response parts, in
++ * practice, however, it seems to expect them to be both part of a larger
++ * contiguous block. We initially allocated separate buffers for the request
++ * and response but this caused the QSEE_CMD_UEFI_GET_VARIABLE command to
++ * either not write any response to the response buffer or outright crash the
++ * device. Therefore, we now allocate a single contiguous block of DMA memory
++ * for both and properly align the data using the macros below. In particular,
++ * request and response structs are aligned at 8 byte (via __reqdata_offs()),
++ * following the driver that this has been reverse-engineered from.
+ */
+ #define qcuefi_buf_align_fields(fields...) \
+ ({ \
+@@ -244,6 +257,12 @@ struct qsee_rsp_uefi_query_variable_info {
+ #define __array_offs(type, count, offset) \
+ __field_impl(sizeof(type) * (count), __alignof__(type), offset)
+
++#define __array_offs_aligned(type, count, align, offset) \
++ __field_impl(sizeof(type) * (count), align, offset)
++
++#define __reqdata_offs(size, offset) \
++ __array_offs_aligned(u8, size, 8, offset)
++
+ #define __array(type, count) __array_offs(type, count, NULL)
+ #define __field_offs(type, offset) __array_offs(type, 1, offset)
+ #define __field(type) __array_offs(type, 1, NULL)
+@@ -277,10 +296,15 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
+ unsigned long buffer_size = *data_size;
+ efi_status_t efi_status = EFI_SUCCESS;
+ unsigned long name_length;
++ dma_addr_t cmd_buf_dma;
++ size_t cmd_buf_size;
++ void *cmd_buf;
+ size_t guid_offs;
+ size_t name_offs;
+ size_t req_size;
+ size_t rsp_size;
++ size_t req_offs;
++ size_t rsp_offs;
+ ssize_t status;
+
+ if (!name || !guid)
+@@ -304,17 +328,19 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
+ __array(u8, buffer_size)
+ );
+
+- req_data = kzalloc(req_size, GFP_KERNEL);
+- if (!req_data) {
++ cmd_buf_size = qcuefi_buf_align_fields(
++ __reqdata_offs(req_size, &req_offs)
++ __reqdata_offs(rsp_size, &rsp_offs)
++ );
++
++ cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
++ if (!cmd_buf) {
+ efi_status = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+- rsp_data = kzalloc(rsp_size, GFP_KERNEL);
+- if (!rsp_data) {
+- efi_status = EFI_OUT_OF_RESOURCES;
+- goto out_free_req;
+- }
++ req_data = cmd_buf + req_offs;
++ rsp_data = cmd_buf + rsp_offs;
+
+ req_data->command_id = QSEE_CMD_UEFI_GET_VARIABLE;
+ req_data->data_size = buffer_size;
+@@ -332,7 +358,9 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
+
+ memcpy(((void *)req_data) + req_data->guid_offset, guid, req_data->guid_size);
+
+- status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size);
++ status = qcom_qseecom_app_send(qcuefi->client,
++ cmd_buf_dma + req_offs, req_size,
++ cmd_buf_dma + rsp_offs, rsp_size);
+ if (status) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+@@ -407,9 +435,7 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
+ memcpy(data, ((void *)rsp_data) + rsp_data->data_offset, rsp_data->data_size);
+
+ out_free:
+- kfree(rsp_data);
+-out_free_req:
+- kfree(req_data);
++ qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
+ out:
+ return efi_status;
+ }
+@@ -422,10 +448,15 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
+ struct qsee_rsp_uefi_set_variable *rsp_data;
+ efi_status_t efi_status = EFI_SUCCESS;
+ unsigned long name_length;
++ dma_addr_t cmd_buf_dma;
++ size_t cmd_buf_size;
++ void *cmd_buf;
+ size_t name_offs;
+ size_t guid_offs;
+ size_t data_offs;
+ size_t req_size;
++ size_t req_offs;
++ size_t rsp_offs;
+ ssize_t status;
+
+ if (!name || !guid)
+@@ -450,17 +481,19 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
+ __array_offs(u8, data_size, &data_offs)
+ );
+
+- req_data = kzalloc(req_size, GFP_KERNEL);
+- if (!req_data) {
++ cmd_buf_size = qcuefi_buf_align_fields(
++ __reqdata_offs(req_size, &req_offs)
++ __reqdata_offs(sizeof(*rsp_data), &rsp_offs)
++ );
++
++ cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
++ if (!cmd_buf) {
+ efi_status = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+- rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL);
+- if (!rsp_data) {
+- efi_status = EFI_OUT_OF_RESOURCES;
+- goto out_free_req;
+- }
++ req_data = cmd_buf + req_offs;
++ rsp_data = cmd_buf + rsp_offs;
+
+ req_data->command_id = QSEE_CMD_UEFI_SET_VARIABLE;
+ req_data->attributes = attributes;
+@@ -483,8 +516,9 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
+ if (data_size)
+ memcpy(((void *)req_data) + req_data->data_offset, data, req_data->data_size);
+
+- status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data,
+- sizeof(*rsp_data));
++ status = qcom_qseecom_app_send(qcuefi->client,
++ cmd_buf_dma + req_offs, req_size,
++ cmd_buf_dma + rsp_offs, sizeof(*rsp_data));
+ if (status) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+@@ -507,9 +541,7 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
+ }
+
+ out_free:
+- kfree(rsp_data);
+-out_free_req:
+- kfree(req_data);
++ qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
+ out:
+ return efi_status;
+ }
+@@ -521,10 +553,15 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
+ struct qsee_req_uefi_get_next_variable *req_data;
+ struct qsee_rsp_uefi_get_next_variable *rsp_data;
+ efi_status_t efi_status = EFI_SUCCESS;
++ dma_addr_t cmd_buf_dma;
++ size_t cmd_buf_size;
++ void *cmd_buf;
+ size_t guid_offs;
+ size_t name_offs;
+ size_t req_size;
+ size_t rsp_size;
++ size_t req_offs;
++ size_t rsp_offs;
+ ssize_t status;
+
+ if (!name_size || !name || !guid)
+@@ -545,17 +582,19 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
+ __array(*name, *name_size / sizeof(*name))
+ );
+
+- req_data = kzalloc(req_size, GFP_KERNEL);
+- if (!req_data) {
++ cmd_buf_size = qcuefi_buf_align_fields(
++ __reqdata_offs(req_size, &req_offs)
++ __reqdata_offs(rsp_size, &rsp_offs)
++ );
++
++ cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
++ if (!cmd_buf) {
+ efi_status = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+- rsp_data = kzalloc(rsp_size, GFP_KERNEL);
+- if (!rsp_data) {
+- efi_status = EFI_OUT_OF_RESOURCES;
+- goto out_free_req;
+- }
++ req_data = cmd_buf + req_offs;
++ rsp_data = cmd_buf + rsp_offs;
+
+ req_data->command_id = QSEE_CMD_UEFI_GET_NEXT_VARIABLE;
+ req_data->guid_offset = guid_offs;
+@@ -572,7 +611,9 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
+ goto out_free;
+ }
+
+- status = qcom_qseecom_app_send(qcuefi->client, req_data, req_size, rsp_data, rsp_size);
++ status = qcom_qseecom_app_send(qcuefi->client,
++ cmd_buf_dma + req_offs, req_size,
++ cmd_buf_dma + rsp_offs, rsp_size);
+ if (status) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+@@ -645,9 +686,7 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
+ }
+
+ out_free:
+- kfree(rsp_data);
+-out_free_req:
+- kfree(req_data);
++ qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
+ out:
+ return efi_status;
+ }
+@@ -659,26 +698,34 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
+ struct qsee_req_uefi_query_variable_info *req_data;
+ struct qsee_rsp_uefi_query_variable_info *rsp_data;
+ efi_status_t efi_status = EFI_SUCCESS;
++ dma_addr_t cmd_buf_dma;
++ size_t cmd_buf_size;
++ void *cmd_buf;
++ size_t req_offs;
++ size_t rsp_offs;
+ int status;
+
+- req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
+- if (!req_data) {
++ cmd_buf_size = qcuefi_buf_align_fields(
++ __reqdata_offs(sizeof(*req_data), &req_offs)
++ __reqdata_offs(sizeof(*rsp_data), &rsp_offs)
++ );
++
++ cmd_buf = qseecom_dma_alloc(qcuefi->client, cmd_buf_size, &cmd_buf_dma, GFP_KERNEL);
++ if (!cmd_buf) {
+ efi_status = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+- rsp_data = kzalloc(sizeof(*rsp_data), GFP_KERNEL);
+- if (!rsp_data) {
+- efi_status = EFI_OUT_OF_RESOURCES;
+- goto out_free_req;
+- }
++ req_data = cmd_buf + req_offs;
++ rsp_data = cmd_buf + rsp_offs;
+
+ req_data->command_id = QSEE_CMD_UEFI_QUERY_VARIABLE_INFO;
+ req_data->attributes = attr;
+ req_data->length = sizeof(*req_data);
+
+- status = qcom_qseecom_app_send(qcuefi->client, req_data, sizeof(*req_data), rsp_data,
+- sizeof(*rsp_data));
++ status = qcom_qseecom_app_send(qcuefi->client,
++ cmd_buf_dma + req_offs, sizeof(*req_data),
++ cmd_buf_dma + rsp_offs, sizeof(*rsp_data));
+ if (status) {
+ efi_status = EFI_DEVICE_ERROR;
+ goto out_free;
+@@ -711,9 +758,7 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
+ *max_variable_size = rsp_data->max_variable_size;
+
+ out_free:
+- kfree(rsp_data);
+-out_free_req:
+- kfree(req_data);
++ qseecom_dma_free(qcuefi->client, cmd_buf_size, cmd_buf, cmd_buf_dma);
+ out:
+ return efi_status;
+ }
+diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
+index 520de9b5633ab..90283f160a228 100644
+--- a/drivers/firmware/qcom/qcom_scm.c
++++ b/drivers/firmware/qcom/qcom_scm.c
+@@ -1576,9 +1576,9 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_get_id);
+ /**
+ * qcom_scm_qseecom_app_send() - Send to and receive data from a given QSEE app.
+ * @app_id: The ID of the target app.
+- * @req: Request buffer sent to the app (must be DMA-mappable).
++ * @req: DMA address of the request buffer sent to the app.
+ * @req_size: Size of the request buffer.
+- * @rsp: Response buffer, written to by the app (must be DMA-mappable).
++ * @rsp: DMA address of the response buffer, written to by the app.
+ * @rsp_size: Size of the response buffer.
+ *
+ * Sends a request to the QSEE app associated with the given ID and read back
+@@ -1589,33 +1589,13 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_get_id);
+ *
+ * Return: Zero on success, nonzero on failure.
+ */
+-int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp,
+- size_t rsp_size)
++int qcom_scm_qseecom_app_send(u32 app_id, dma_addr_t req, size_t req_size,
++ dma_addr_t rsp, size_t rsp_size)
+ {
+ struct qcom_scm_qseecom_resp res = {};
+ struct qcom_scm_desc desc = {};
+- dma_addr_t req_phys;
+- dma_addr_t rsp_phys;
+ int status;
+
+- /* Map request buffer */
+- req_phys = dma_map_single(__scm->dev, req, req_size, DMA_TO_DEVICE);
+- status = dma_mapping_error(__scm->dev, req_phys);
+- if (status) {
+- dev_err(__scm->dev, "qseecom: failed to map request buffer\n");
+- return status;
+- }
+-
+- /* Map response buffer */
+- rsp_phys = dma_map_single(__scm->dev, rsp, rsp_size, DMA_FROM_DEVICE);
+- status = dma_mapping_error(__scm->dev, rsp_phys);
+- if (status) {
+- dma_unmap_single(__scm->dev, req_phys, req_size, DMA_TO_DEVICE);
+- dev_err(__scm->dev, "qseecom: failed to map response buffer\n");
+- return status;
+- }
+-
+- /* Set up SCM call data */
+ desc.owner = QSEECOM_TZ_OWNER_TZ_APPS;
+ desc.svc = QSEECOM_TZ_SVC_APP_ID_PLACEHOLDER;
+ desc.cmd = QSEECOM_TZ_CMD_APP_SEND;
+@@ -1623,18 +1603,13 @@ int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp,
+ QCOM_SCM_RW, QCOM_SCM_VAL,
+ QCOM_SCM_RW, QCOM_SCM_VAL);
+ desc.args[0] = app_id;
+- desc.args[1] = req_phys;
++ desc.args[1] = req;
+ desc.args[2] = req_size;
+- desc.args[3] = rsp_phys;
++ desc.args[3] = rsp;
+ desc.args[4] = rsp_size;
+
+- /* Perform call */
+ status = qcom_scm_qseecom_call(&desc, &res);
+
+- /* Unmap buffers */
+- dma_unmap_single(__scm->dev, rsp_phys, rsp_size, DMA_FROM_DEVICE);
+- dma_unmap_single(__scm->dev, req_phys, req_size, DMA_TO_DEVICE);
+-
+ if (status)
+ return status;
+
+diff --git a/drivers/gpio/gpio-tangier.c b/drivers/gpio/gpio-tangier.c
+index b75e0b12087ac..4b29abafecf6a 100644
+--- a/drivers/gpio/gpio-tangier.c
++++ b/drivers/gpio/gpio-tangier.c
+@@ -195,7 +195,8 @@ static int tng_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+
+ static void tng_irq_ack(struct irq_data *d)
+ {
+- struct tng_gpio *priv = irq_data_get_irq_chip_data(d);
++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
++ struct tng_gpio *priv = gpiochip_get_data(gc);
+ irq_hw_number_t gpio = irqd_to_hwirq(d);
+ void __iomem *gisr;
+ u8 shift;
+@@ -227,7 +228,8 @@ static void tng_irq_unmask_mask(struct tng_gpio *priv, u32 gpio, bool unmask)
+
+ static void tng_irq_mask(struct irq_data *d)
+ {
+- struct tng_gpio *priv = irq_data_get_irq_chip_data(d);
++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
++ struct tng_gpio *priv = gpiochip_get_data(gc);
+ irq_hw_number_t gpio = irqd_to_hwirq(d);
+
+ tng_irq_unmask_mask(priv, gpio, false);
+@@ -236,7 +238,8 @@ static void tng_irq_mask(struct irq_data *d)
+
+ static void tng_irq_unmask(struct irq_data *d)
+ {
+- struct tng_gpio *priv = irq_data_get_irq_chip_data(d);
++ struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
++ struct tng_gpio *priv = gpiochip_get_data(gc);
+ irq_hw_number_t gpio = irqd_to_hwirq(d);
+
+ gpiochip_enable_irq(&priv->chip, gpio);
+diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
+index d87dd06db40d0..9130c691a2dd3 100644
+--- a/drivers/gpio/gpio-tegra186.c
++++ b/drivers/gpio/gpio-tegra186.c
+@@ -36,12 +36,6 @@
+ #define TEGRA186_GPIO_SCR_SEC_REN BIT(27)
+ #define TEGRA186_GPIO_SCR_SEC_G1W BIT(9)
+ #define TEGRA186_GPIO_SCR_SEC_G1R BIT(1)
+-#define TEGRA186_GPIO_FULL_ACCESS (TEGRA186_GPIO_SCR_SEC_WEN | \
+- TEGRA186_GPIO_SCR_SEC_REN | \
+- TEGRA186_GPIO_SCR_SEC_G1R | \
+- TEGRA186_GPIO_SCR_SEC_G1W)
+-#define TEGRA186_GPIO_SCR_SEC_ENABLE (TEGRA186_GPIO_SCR_SEC_WEN | \
+- TEGRA186_GPIO_SCR_SEC_REN)
+
+ /* control registers */
+ #define TEGRA186_GPIO_ENABLE_CONFIG 0x00
+@@ -177,10 +171,18 @@ static inline bool tegra186_gpio_is_accessible(struct tegra_gpio *gpio, unsigned
+
+ value = __raw_readl(secure + TEGRA186_GPIO_SCR);
+
+- if ((value & TEGRA186_GPIO_SCR_SEC_ENABLE) == 0)
+- return true;
++ /*
++ * When SCR_SEC_[R|W]EN is unset, then we have full read/write access to all the
++ * registers for given GPIO pin.
++ * When SCR_SEC[R|W]EN is set, then there is need to further check the accompanying
++ * SCR_SEC_G1[R|W] bit to determine read/write access to all the registers for given
++ * GPIO pin.
++ */
+
+- if ((value & TEGRA186_GPIO_FULL_ACCESS) == TEGRA186_GPIO_FULL_ACCESS)
++ if (((value & TEGRA186_GPIO_SCR_SEC_REN) == 0 ||
++ ((value & TEGRA186_GPIO_SCR_SEC_REN) && (value & TEGRA186_GPIO_SCR_SEC_G1R))) &&
++ ((value & TEGRA186_GPIO_SCR_SEC_WEN) == 0 ||
++ ((value & TEGRA186_GPIO_SCR_SEC_WEN) && (value & TEGRA186_GPIO_SCR_SEC_G1W))))
+ return true;
+
+ return false;
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+index 231fd927dcfbe..daa66eb4f722b 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+@@ -1851,6 +1851,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
+ err_bo_create:
+ amdgpu_amdkfd_unreserve_mem_limit(adev, aligned_size, flags, xcp_id);
+ err_reserve_limit:
++ amdgpu_sync_free(&(*mem)->sync);
+ mutex_destroy(&(*mem)->lock);
+ if (gobj)
+ drm_gem_object_put(gobj);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+index 6adeddfb3d564..116d3756c9c35 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+@@ -819,7 +819,7 @@ static int amdgpu_cs_bo_validate(void *param, struct amdgpu_bo *bo)
+
+ p->bytes_moved += ctx.bytes_moved;
+ if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
+- amdgpu_bo_in_cpu_visible_vram(bo))
++ amdgpu_res_cpu_visible(adev, bo->tbo.resource))
+ p->bytes_moved_vis += ctx.bytes_moved;
+
+ if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) {
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c
+index 5706b282a0c7e..c7df7fa3459f1 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.c
+@@ -97,6 +97,10 @@ void amdgpu_show_fdinfo(struct drm_printer *p, struct drm_file *file)
+ stats.requested_visible_vram/1024UL);
+ drm_printf(p, "amd-requested-gtt:\t%llu KiB\n",
+ stats.requested_gtt/1024UL);
++ drm_printf(p, "drm-shared-vram:\t%llu KiB\n", stats.vram_shared/1024UL);
++ drm_printf(p, "drm-shared-gtt:\t%llu KiB\n", stats.gtt_shared/1024UL);
++ drm_printf(p, "drm-shared-cpu:\t%llu KiB\n", stats.cpu_shared/1024UL);
++
+ for (hw_ip = 0; hw_ip < AMDGPU_HW_IP_NUM; ++hw_ip) {
+ if (!usage[hw_ip])
+ continue;
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+index 425cebcc5cbff..866bfde1ca6f9 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+@@ -620,8 +620,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
+ return r;
+
+ if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
+- bo->tbo.resource->mem_type == TTM_PL_VRAM &&
+- amdgpu_bo_in_cpu_visible_vram(bo))
++ amdgpu_res_cpu_visible(adev, bo->tbo.resource))
+ amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved,
+ ctx.bytes_moved);
+ else
+@@ -1275,26 +1274,39 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict)
+ void amdgpu_bo_get_memory(struct amdgpu_bo *bo,
+ struct amdgpu_mem_stats *stats)
+ {
++ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
++ struct ttm_resource *res = bo->tbo.resource;
+ uint64_t size = amdgpu_bo_size(bo);
++ struct drm_gem_object *obj;
+ unsigned int domain;
++ bool shared;
+
+ /* Abort if the BO doesn't currently have a backing store */
+- if (!bo->tbo.resource)
++ if (!res)
+ return;
+
+- domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type);
++ obj = &bo->tbo.base;
++ shared = drm_gem_object_is_shared_for_memory_stats(obj);
++
++ domain = amdgpu_mem_type_to_domain(res->mem_type);
+ switch (domain) {
+ case AMDGPU_GEM_DOMAIN_VRAM:
+ stats->vram += size;
+- if (amdgpu_bo_in_cpu_visible_vram(bo))
++ if (amdgpu_res_cpu_visible(adev, bo->tbo.resource))
+ stats->visible_vram += size;
++ if (shared)
++ stats->vram_shared += size;
+ break;
+ case AMDGPU_GEM_DOMAIN_GTT:
+ stats->gtt += size;
++ if (shared)
++ stats->gtt_shared += size;
+ break;
+ case AMDGPU_GEM_DOMAIN_CPU:
+ default:
+ stats->cpu += size;
++ if (shared)
++ stats->cpu_shared += size;
+ break;
+ }
+
+@@ -1381,10 +1393,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
+ /* Remember that this BO was accessed by the CPU */
+ abo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
+
+- if (bo->resource->mem_type != TTM_PL_VRAM)
+- return 0;
+-
+- if (amdgpu_bo_in_cpu_visible_vram(abo))
++ if (amdgpu_res_cpu_visible(adev, bo->resource))
+ return 0;
+
+ /* Can't move a pinned BO to visible VRAM */
+@@ -1408,7 +1417,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
+
+ /* this should never happen */
+ if (bo->resource->mem_type == TTM_PL_VRAM &&
+- !amdgpu_bo_in_cpu_visible_vram(abo))
++ !amdgpu_res_cpu_visible(adev, bo->resource))
+ return VM_FAULT_SIGBUS;
+
+ ttm_bo_move_to_lru_tail_unlocked(bo);
+@@ -1572,6 +1581,7 @@ uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev,
+ */
+ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)
+ {
++ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+ struct dma_buf_attachment *attachment;
+ struct dma_buf *dma_buf;
+ const char *placement;
+@@ -1580,10 +1590,11 @@ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m)
+
+ if (dma_resv_trylock(bo->tbo.base.resv)) {
+ unsigned int domain;
++
+ domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type);
+ switch (domain) {
+ case AMDGPU_GEM_DOMAIN_VRAM:
+- if (amdgpu_bo_in_cpu_visible_vram(bo))
++ if (amdgpu_res_cpu_visible(adev, bo->tbo.resource))
+ placement = "VRAM VISIBLE";
+ else
+ placement = "VRAM";
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+index a3ea8a82db23a..fa03d9e4874cc 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+@@ -138,12 +138,18 @@ struct amdgpu_bo_vm {
+ struct amdgpu_mem_stats {
+ /* current VRAM usage, includes visible VRAM */
+ uint64_t vram;
++ /* current shared VRAM usage, includes visible VRAM */
++ uint64_t vram_shared;
+ /* current visible VRAM usage */
+ uint64_t visible_vram;
+ /* current GTT usage */
+ uint64_t gtt;
++ /* current shared GTT usage */
++ uint64_t gtt_shared;
+ /* current system memory usage */
+ uint64_t cpu;
++ /* current shared system memory usage */
++ uint64_t cpu_shared;
+ /* sum of evicted buffers, includes visible VRAM */
+ uint64_t evicted_vram;
+ /* sum of evicted buffers due to CPU access */
+@@ -244,28 +250,6 @@ static inline u64 amdgpu_bo_mmap_offset(struct amdgpu_bo *bo)
+ return drm_vma_node_offset_addr(&bo->tbo.base.vma_node);
+ }
+
+-/**
+- * amdgpu_bo_in_cpu_visible_vram - check if BO is (partly) in visible VRAM
+- */
+-static inline bool amdgpu_bo_in_cpu_visible_vram(struct amdgpu_bo *bo)
+-{
+- struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+- struct amdgpu_res_cursor cursor;
+-
+- if (!bo->tbo.resource || bo->tbo.resource->mem_type != TTM_PL_VRAM)
+- return false;
+-
+- amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor);
+- while (cursor.remaining) {
+- if (cursor.start < adev->gmc.visible_vram_size)
+- return true;
+-
+- amdgpu_res_next(&cursor, cursor.size);
+- }
+-
+- return false;
+-}
+-
+ /**
+ * amdgpu_bo_explicit_sync - return whether the bo is explicitly synced
+ */
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+index a5ceec7820cfa..851509c6e90eb 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+@@ -137,7 +137,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
+ amdgpu_bo_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU);
+ } else if (!amdgpu_gmc_vram_full_visible(&adev->gmc) &&
+ !(abo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) &&
+- amdgpu_bo_in_cpu_visible_vram(abo)) {
++ amdgpu_res_cpu_visible(adev, bo->resource)) {
+
+ /* Try evicting to the CPU inaccessible part of VRAM
+ * first, but only set GTT as busy placement, so this
+@@ -408,40 +408,55 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
+ return r;
+ }
+
+-/*
+- * amdgpu_mem_visible - Check that memory can be accessed by ttm_bo_move_memcpy
++/**
++ * amdgpu_res_cpu_visible - Check that resource can be accessed by CPU
++ * @adev: amdgpu device
++ * @res: the resource to check
+ *
+- * Called by amdgpu_bo_move()
++ * Returns: true if the full resource is CPU visible, false otherwise.
+ */
+-static bool amdgpu_mem_visible(struct amdgpu_device *adev,
+- struct ttm_resource *mem)
++bool amdgpu_res_cpu_visible(struct amdgpu_device *adev,
++ struct ttm_resource *res)
+ {
+- u64 mem_size = (u64)mem->size;
+ struct amdgpu_res_cursor cursor;
+- u64 end;
+
+- if (mem->mem_type == TTM_PL_SYSTEM ||
+- mem->mem_type == TTM_PL_TT)
++ if (!res)
++ return false;
++
++ if (res->mem_type == TTM_PL_SYSTEM || res->mem_type == TTM_PL_TT ||
++ res->mem_type == AMDGPU_PL_PREEMPT)
+ return true;
+- if (mem->mem_type != TTM_PL_VRAM)
++
++ if (res->mem_type != TTM_PL_VRAM)
+ return false;
+
+- amdgpu_res_first(mem, 0, mem_size, &cursor);
+- end = cursor.start + cursor.size;
++ amdgpu_res_first(res, 0, res->size, &cursor);
+ while (cursor.remaining) {
++ if ((cursor.start + cursor.size) >= adev->gmc.visible_vram_size)
++ return false;
+ amdgpu_res_next(&cursor, cursor.size);
++ }
+
+- if (!cursor.remaining)
+- break;
++ return true;
++}
+
+- /* ttm_resource_ioremap only supports contiguous memory */
+- if (end != cursor.start)
+- return false;
++/*
++ * amdgpu_res_copyable - Check that memory can be accessed by ttm_bo_move_memcpy
++ *
++ * Called by amdgpu_bo_move()
++ */
++static bool amdgpu_res_copyable(struct amdgpu_device *adev,
++ struct ttm_resource *mem)
++{
++ if (!amdgpu_res_cpu_visible(adev, mem))
++ return false;
+
+- end = cursor.start + cursor.size;
+- }
++ /* ttm_resource_ioremap only supports contiguous memory */
++ if (mem->mem_type == TTM_PL_VRAM &&
++ !(mem->placement & TTM_PL_FLAG_CONTIGUOUS))
++ return false;
+
+- return end <= adev->gmc.visible_vram_size;
++ return true;
+ }
+
+ /*
+@@ -534,8 +549,8 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
+
+ if (r) {
+ /* Check that all memory is CPU accessible */
+- if (!amdgpu_mem_visible(adev, old_mem) ||
+- !amdgpu_mem_visible(adev, new_mem)) {
++ if (!amdgpu_res_copyable(adev, old_mem) ||
++ !amdgpu_res_copyable(adev, new_mem)) {
+ pr_err("Move buffer fallback to memcpy unavailable\n");
+ return r;
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+index 65ec82141a8e0..32cf6b6f6efd9 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+@@ -139,6 +139,9 @@ int amdgpu_vram_mgr_reserve_range(struct amdgpu_vram_mgr *mgr,
+ int amdgpu_vram_mgr_query_page_status(struct amdgpu_vram_mgr *mgr,
+ uint64_t start);
+
++bool amdgpu_res_cpu_visible(struct amdgpu_device *adev,
++ struct ttm_resource *res);
++
+ int amdgpu_ttm_init(struct amdgpu_device *adev);
+ void amdgpu_ttm_fini(struct amdgpu_device *adev);
+ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev,
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c
+index bfbf59326ee12..1b5ef32108e14 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c
+@@ -766,6 +766,9 @@ static int umsch_mm_late_init(void *handle)
+ {
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
++ if (amdgpu_in_reset(adev) || adev->in_s0ix || adev->in_suspend)
++ return 0;
++
+ return umsch_mm_test(adev);
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+index 45a67a77455ee..1caed0163b53d 100644
+--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
++++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+@@ -366,7 +366,8 @@ static void sdma_v4_4_2_ring_emit_hdp_flush(struct amdgpu_ring *ring)
+ u32 ref_and_mask = 0;
+ const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
+
+- ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
++ ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0
++ << (ring->me % adev->sdma.num_inst_per_aid);
+
+ sdma_v4_4_2_wait_reg_mem(ring, 0, 1,
+ adev->nbio.funcs->get_hdp_flush_done_offset(adev),
+diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
+index 0058f3f7cf6e4..46f9f58d845f8 100644
+--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
++++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
+@@ -292,17 +292,21 @@ static void sdma_v5_2_ring_emit_hdp_flush(struct amdgpu_ring *ring)
+ u32 ref_and_mask = 0;
+ const struct nbio_hdp_flush_reg *nbio_hf_reg = adev->nbio.hdp_flush_reg;
+
+- ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
+-
+- amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
+- SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) |
+- SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */
+- amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_done_offset(adev)) << 2);
+- amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_req_offset(adev)) << 2);
+- amdgpu_ring_write(ring, ref_and_mask); /* reference */
+- amdgpu_ring_write(ring, ref_and_mask); /* mask */
+- amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
+- SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */
++ if (ring->me > 1) {
++ amdgpu_asic_flush_hdp(adev, ring);
++ } else {
++ ref_and_mask = nbio_hf_reg->ref_and_mask_sdma0 << ring->me;
++
++ amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
++ SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) |
++ SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */
++ amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_done_offset(adev)) << 2);
++ amdgpu_ring_write(ring, (adev->nbio.funcs->get_hdp_flush_req_offset(adev)) << 2);
++ amdgpu_ring_write(ring, ref_and_mask); /* reference */
++ amdgpu_ring_write(ring, ref_and_mask); /* mask */
++ amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
++ SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10)); /* retry count, poll interval */
++ }
+ }
+
+ /**
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+index b79986412cd83..58c1fe5421934 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+@@ -1922,6 +1922,8 @@ static int signal_eviction_fence(struct kfd_process *p)
+ rcu_read_lock();
+ ef = dma_fence_get_rcu_safe(&p->ef);
+ rcu_read_unlock();
++ if (!ef)
++ return -EINVAL;
+
+ ret = dma_fence_signal(ef);
+ dma_fence_put(ef);
+@@ -1949,10 +1951,9 @@ static void evict_process_worker(struct work_struct *work)
+ * they are responsible stopping the queues and scheduling
+ * the restore work.
+ */
+- if (!signal_eviction_fence(p))
+- queue_delayed_work(kfd_restore_wq, &p->restore_work,
+- msecs_to_jiffies(PROCESS_RESTORE_TIME_MS));
+- else
++ if (signal_eviction_fence(p) ||
++ mod_delayed_work(kfd_restore_wq, &p->restore_work,
++ msecs_to_jiffies(PROCESS_RESTORE_TIME_MS)))
+ kfd_process_restore_queues(p);
+
+ pr_debug("Finished evicting pasid 0x%x\n", p->pasid);
+@@ -2011,9 +2012,9 @@ static void restore_process_worker(struct work_struct *work)
+ if (ret) {
+ pr_debug("Failed to restore BOs of pasid 0x%x, retry after %d ms\n",
+ p->pasid, PROCESS_BACK_OFF_TIME_MS);
+- ret = queue_delayed_work(kfd_restore_wq, &p->restore_work,
+- msecs_to_jiffies(PROCESS_BACK_OFF_TIME_MS));
+- WARN(!ret, "reschedule restore work failed\n");
++ if (mod_delayed_work(kfd_restore_wq, &p->restore_work,
++ msecs_to_jiffies(PROCESS_RESTORE_TIME_MS)))
++ kfd_process_restore_queues(p);
+ }
+ }
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c
+index d761b0df28784..8a0460e863097 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c
+@@ -34,6 +34,7 @@
+ #include "dc_bios_types.h"
+ #include "link_enc_cfg.h"
+
++#include "dc_dmub_srv.h"
+ #include "gpio_service_interface.h"
+
+ #ifndef MIN
+@@ -61,6 +62,38 @@
+ #define AUX_REG_WRITE(reg_name, val) \
+ dm_write_reg(CTX, AUX_REG(reg_name), val)
+
++static uint8_t phy_id_from_transmitter(enum transmitter t)
++{
++ uint8_t phy_id;
++
++ switch (t) {
++ case TRANSMITTER_UNIPHY_A:
++ phy_id = 0;
++ break;
++ case TRANSMITTER_UNIPHY_B:
++ phy_id = 1;
++ break;
++ case TRANSMITTER_UNIPHY_C:
++ phy_id = 2;
++ break;
++ case TRANSMITTER_UNIPHY_D:
++ phy_id = 3;
++ break;
++ case TRANSMITTER_UNIPHY_E:
++ phy_id = 4;
++ break;
++ case TRANSMITTER_UNIPHY_F:
++ phy_id = 5;
++ break;
++ case TRANSMITTER_UNIPHY_G:
++ phy_id = 6;
++ break;
++ default:
++ phy_id = 0;
++ break;
++ }
++ return phy_id;
++}
+
+ void enc32_hw_init(struct link_encoder *enc)
+ {
+@@ -117,38 +150,50 @@ void dcn32_link_encoder_enable_dp_output(
+ }
+ }
+
+-static bool dcn32_link_encoder_is_in_alt_mode(struct link_encoder *enc)
++static bool query_dp_alt_from_dmub(struct link_encoder *enc,
++ union dmub_rb_cmd *cmd)
+ {
+ struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+- uint32_t dp_alt_mode_disable = 0;
+- bool is_usb_c_alt_mode = false;
+
+- if (enc->features.flags.bits.DP_IS_USB_C) {
+- /* if value == 1 alt mode is disabled, otherwise it is enabled */
+- REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, &dp_alt_mode_disable);
+- is_usb_c_alt_mode = (dp_alt_mode_disable == 0);
+- }
++ memset(cmd, 0, sizeof(*cmd));
++ cmd->query_dp_alt.header.type = DMUB_CMD__VBIOS;
++ cmd->query_dp_alt.header.sub_type =
++ DMUB_CMD__VBIOS_TRANSMITTER_QUERY_DP_ALT;
++ cmd->query_dp_alt.header.payload_bytes = sizeof(cmd->query_dp_alt.data);
++ cmd->query_dp_alt.data.phy_id = phy_id_from_transmitter(enc10->base.transmitter);
++
++ if (!dc_wake_and_execute_dmub_cmd(enc->ctx, cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
++ return false;
+
+- return is_usb_c_alt_mode;
++ return true;
+ }
+
+-static void dcn32_link_encoder_get_max_link_cap(struct link_encoder *enc,
++bool dcn32_link_encoder_is_in_alt_mode(struct link_encoder *enc)
++{
++ union dmub_rb_cmd cmd;
++
++ if (!query_dp_alt_from_dmub(enc, &cmd))
++ return false;
++
++ return (cmd.query_dp_alt.data.is_dp_alt_disable == 0);
++}
++
++void dcn32_link_encoder_get_max_link_cap(struct link_encoder *enc,
+ struct dc_link_settings *link_settings)
+ {
+- struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc);
+- uint32_t is_in_usb_c_dp4_mode = 0;
++ union dmub_rb_cmd cmd;
+
+ dcn10_link_encoder_get_max_link_cap(enc, link_settings);
+
+- /* in usb c dp2 mode, max lane count is 2 */
+- if (enc->funcs->is_in_alt_mode && enc->funcs->is_in_alt_mode(enc)) {
+- REG_GET(RDPCSPIPE_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, &is_in_usb_c_dp4_mode);
+- if (!is_in_usb_c_dp4_mode)
+- link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count);
+- }
++ if (!query_dp_alt_from_dmub(enc, &cmd))
++ return;
+
++ if (cmd.query_dp_alt.data.is_usb &&
++ cmd.query_dp_alt.data.is_dp4 == 0)
++ link_settings->lane_count = MIN(LANE_COUNT_TWO, link_settings->lane_count);
+ }
+
++
+ static const struct link_encoder_funcs dcn32_link_enc_funcs = {
+ .read_state = link_enc2_read_state,
+ .validate_output_with_stream =
+@@ -203,12 +248,12 @@ void dcn32_link_encoder_construct(
+ enc10->base.hpd_source = init_data->hpd_source;
+ enc10->base.connector = init_data->connector;
+
++ if (enc10->base.connector.id == CONNECTOR_ID_USBC)
++ enc10->base.features.flags.bits.DP_IS_USB_C = 1;
+
+ enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
+
+ enc10->base.features = *enc_features;
+- if (enc10->base.connector.id == CONNECTOR_ID_USBC)
+- enc10->base.features.flags.bits.DP_IS_USB_C = 1;
+
+ enc10->base.transmitter = init_data->transmitter;
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.h
+index bbcfce06bec01..2d5f25290ed14 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.h
++++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.h
+@@ -53,4 +53,9 @@ void dcn32_link_encoder_enable_dp_output(
+ const struct dc_link_settings *link_settings,
+ enum clock_source_id clock_source);
+
++bool dcn32_link_encoder_is_in_alt_mode(struct link_encoder *enc);
++
++void dcn32_link_encoder_get_max_link_cap(struct link_encoder *enc,
++ struct dc_link_settings *link_settings);
++
+ #endif /* __DC_LINK_ENCODER__DCN32_H__ */
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c
+index 81e349d5835bb..da94e5309fbaf 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c
+@@ -184,6 +184,8 @@ void dcn35_link_encoder_construct(
+ enc10->base.hpd_source = init_data->hpd_source;
+ enc10->base.connector = init_data->connector;
+
++ if (enc10->base.connector.id == CONNECTOR_ID_USBC)
++ enc10->base.features.flags.bits.DP_IS_USB_C = 1;
+
+ enc10->base.preferred_engine = ENGINE_ID_UNKNOWN;
+
+@@ -238,8 +240,6 @@ void dcn35_link_encoder_construct(
+ }
+
+ enc10->base.features.flags.bits.HDMI_6GB_EN = 1;
+- if (enc10->base.connector.id == CONNECTOR_ID_USBC)
+- enc10->base.features.flags.bits.DP_IS_USB_C = 1;
+
+ if (bp_funcs->get_connector_speed_cap_info)
+ result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios,
+diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+index 39c5e1dfa275a..b4698f9856006 100644
+--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
++++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+@@ -4217,6 +4217,13 @@ static int amdgpu_od_set_init(struct amdgpu_device *adev)
+ }
+ }
+
++ /*
++ * If gpu_od is the only member in the list, that means gpu_od is an
++ * empty directory, so remove it.
++ */
++ if (list_is_singular(&adev->pm.od_kobj_list))
++ goto err_out;
++
+ return 0;
+
+ err_out:
+diff --git a/drivers/gpu/drm/drm_gem_atomic_helper.c b/drivers/gpu/drm/drm_gem_atomic_helper.c
+index e440f458b6633..93337543aac32 100644
+--- a/drivers/gpu/drm/drm_gem_atomic_helper.c
++++ b/drivers/gpu/drm/drm_gem_atomic_helper.c
+@@ -224,8 +224,8 @@ __drm_gem_duplicate_shadow_plane_state(struct drm_plane *plane,
+
+ __drm_atomic_helper_plane_duplicate_state(plane, &new_shadow_plane_state->base);
+
+- drm_format_conv_state_copy(&shadow_plane_state->fmtcnv_state,
+- &new_shadow_plane_state->fmtcnv_state);
++ drm_format_conv_state_copy(&new_shadow_plane_state->fmtcnv_state,
++ &shadow_plane_state->fmtcnv_state);
+ }
+ EXPORT_SYMBOL(__drm_gem_duplicate_shadow_plane_state);
+
+diff --git a/drivers/gpu/drm/gma500/Makefile b/drivers/gpu/drm/gma500/Makefile
+index 4f302cd5e1a6c..58fed80c7392a 100644
+--- a/drivers/gpu/drm/gma500/Makefile
++++ b/drivers/gpu/drm/gma500/Makefile
+@@ -34,7 +34,6 @@ gma500_gfx-y += \
+ psb_intel_lvds.o \
+ psb_intel_modes.o \
+ psb_intel_sdvo.o \
+- psb_lid.o \
+ psb_irq.o
+
+ gma500_gfx-$(CONFIG_ACPI) += opregion.o
+diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c
+index dcfcd7b89d4a1..6dece8f0e380f 100644
+--- a/drivers/gpu/drm/gma500/psb_device.c
++++ b/drivers/gpu/drm/gma500/psb_device.c
+@@ -73,8 +73,7 @@ static int psb_backlight_setup(struct drm_device *dev)
+ }
+
+ psb_intel_lvds_set_brightness(dev, PSB_MAX_BRIGHTNESS);
+- /* This must occur after the backlight is properly initialised */
+- psb_lid_timer_init(dev_priv);
++
+ return 0;
+ }
+
+@@ -259,8 +258,6 @@ static int psb_chip_setup(struct drm_device *dev)
+
+ static void psb_chip_teardown(struct drm_device *dev)
+ {
+- struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
+- psb_lid_timer_takedown(dev_priv);
+ gma_intel_teardown_gmbus(dev);
+ }
+
+diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
+index c5edfa4aa4ccd..83c17689c454f 100644
+--- a/drivers/gpu/drm/gma500/psb_drv.h
++++ b/drivers/gpu/drm/gma500/psb_drv.h
+@@ -162,7 +162,6 @@
+ #define PSB_NUM_VBLANKS 2
+
+ #define PSB_WATCHDOG_DELAY (HZ * 2)
+-#define PSB_LID_DELAY (HZ / 10)
+
+ #define PSB_MAX_BRIGHTNESS 100
+
+@@ -491,11 +490,7 @@ struct drm_psb_private {
+ /* Hotplug handling */
+ struct work_struct hotplug_work;
+
+- /* LID-Switch */
+- spinlock_t lid_lock;
+- struct timer_list lid_timer;
+ struct psb_intel_opregion opregion;
+- u32 lid_last_state;
+
+ /* Watchdog */
+ uint32_t apm_reg;
+@@ -591,10 +586,6 @@ struct psb_ops {
+ int i2c_bus; /* I2C bus identifier for Moorestown */
+ };
+
+-/* psb_lid.c */
+-extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
+-extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv);
+-
+ /* modesetting */
+ extern void psb_modeset_init(struct drm_device *dev);
+ extern void psb_modeset_cleanup(struct drm_device *dev);
+diff --git a/drivers/gpu/drm/gma500/psb_lid.c b/drivers/gpu/drm/gma500/psb_lid.c
+deleted file mode 100644
+index 58a7fe3926360..0000000000000
+--- a/drivers/gpu/drm/gma500/psb_lid.c
++++ /dev/null
+@@ -1,80 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-only
+-/**************************************************************************
+- * Copyright (c) 2007, Intel Corporation.
+- *
+- * Authors: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
+- **************************************************************************/
+-
+-#include <linux/spinlock.h>
+-
+-#include "psb_drv.h"
+-#include "psb_intel_reg.h"
+-#include "psb_reg.h"
+-
+-static void psb_lid_timer_func(struct timer_list *t)
+-{
+- struct drm_psb_private *dev_priv = from_timer(dev_priv, t, lid_timer);
+- struct drm_device *dev = (struct drm_device *)&dev_priv->dev;
+- struct timer_list *lid_timer = &dev_priv->lid_timer;
+- unsigned long irq_flags;
+- u32 __iomem *lid_state = dev_priv->opregion.lid_state;
+- u32 pp_status;
+-
+- if (readl(lid_state) == dev_priv->lid_last_state)
+- goto lid_timer_schedule;
+-
+- if ((readl(lid_state)) & 0x01) {
+- /*lid state is open*/
+- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON);
+- do {
+- pp_status = REG_READ(PP_STATUS);
+- } while ((pp_status & PP_ON) == 0 &&
+- (pp_status & PP_SEQUENCE_MASK) != 0);
+-
+- if (REG_READ(PP_STATUS) & PP_ON) {
+- /*FIXME: should be backlight level before*/
+- psb_intel_lvds_set_brightness(dev, 100);
+- } else {
+- DRM_DEBUG("LVDS panel never powered up");
+- return;
+- }
+- } else {
+- psb_intel_lvds_set_brightness(dev, 0);
+-
+- REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON);
+- do {
+- pp_status = REG_READ(PP_STATUS);
+- } while ((pp_status & PP_ON) == 0);
+- }
+- dev_priv->lid_last_state = readl(lid_state);
+-
+-lid_timer_schedule:
+- spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
+- if (!timer_pending(lid_timer)) {
+- lid_timer->expires = jiffies + PSB_LID_DELAY;
+- add_timer(lid_timer);
+- }
+- spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
+-}
+-
+-void psb_lid_timer_init(struct drm_psb_private *dev_priv)
+-{
+- struct timer_list *lid_timer = &dev_priv->lid_timer;
+- unsigned long irq_flags;
+-
+- spin_lock_init(&dev_priv->lid_lock);
+- spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
+-
+- timer_setup(lid_timer, psb_lid_timer_func, 0);
+-
+- lid_timer->expires = jiffies + PSB_LID_DELAY;
+-
+- add_timer(lid_timer);
+- spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
+-}
+-
+-void psb_lid_timer_takedown(struct drm_psb_private *dev_priv)
+-{
+- del_timer_sync(&dev_priv->lid_timer);
+-}
+-
+diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
+index 35474ddbaf97e..d23ee1397cf07 100644
+--- a/drivers/gpu/drm/xe/xe_gt.c
++++ b/drivers/gpu/drm/xe/xe_gt.c
+@@ -384,7 +384,9 @@ static int gt_fw_domain_init(struct xe_gt *gt)
+ err);
+
+ /* Initialize CCS mode sysfs after early initialization of HW engines */
+- xe_gt_ccs_mode_sysfs_init(gt);
++ err = xe_gt_ccs_mode_sysfs_init(gt);
++ if (err)
++ goto err_force_wake;
+
+ err = xe_force_wake_put(gt_to_fw(gt), XE_FW_GT);
+ XE_WARN_ON(err);
+diff --git a/drivers/gpu/drm/xe/xe_gt_ccs_mode.c b/drivers/gpu/drm/xe/xe_gt_ccs_mode.c
+index 529fc286cd06c..396aeb5b99242 100644
+--- a/drivers/gpu/drm/xe/xe_gt_ccs_mode.c
++++ b/drivers/gpu/drm/xe/xe_gt_ccs_mode.c
+@@ -167,25 +167,20 @@ static void xe_gt_ccs_mode_sysfs_fini(struct drm_device *drm, void *arg)
+ * and it is expected that there are no open drm clients while doing so.
+ * The number of available compute slices is exposed to user through a per-gt
+ * 'num_cslices' sysfs interface.
++ *
++ * Returns: Returns error value for failure and 0 for success.
+ */
+-void xe_gt_ccs_mode_sysfs_init(struct xe_gt *gt)
++int xe_gt_ccs_mode_sysfs_init(struct xe_gt *gt)
+ {
+ struct xe_device *xe = gt_to_xe(gt);
+ int err;
+
+ if (!xe_gt_ccs_mode_enabled(gt))
+- return;
++ return 0;
+
+ err = sysfs_create_files(gt->sysfs, gt_ccs_mode_attrs);
+- if (err) {
+- drm_warn(&xe->drm, "Sysfs creation for ccs_mode failed err: %d\n", err);
+- return;
+- }
++ if (err)
++ return err;
+
+- err = drmm_add_action_or_reset(&xe->drm, xe_gt_ccs_mode_sysfs_fini, gt);
+- if (err) {
+- sysfs_remove_files(gt->sysfs, gt_ccs_mode_attrs);
+- drm_warn(&xe->drm, "%s: drmm_add_action_or_reset failed, err: %d\n",
+- __func__, err);
+- }
++ return drmm_add_action_or_reset(&xe->drm, xe_gt_ccs_mode_sysfs_fini, gt);
+ }
+diff --git a/drivers/gpu/drm/xe/xe_gt_ccs_mode.h b/drivers/gpu/drm/xe/xe_gt_ccs_mode.h
+index f39975aaaab0d..f8779852cf0d2 100644
+--- a/drivers/gpu/drm/xe/xe_gt_ccs_mode.h
++++ b/drivers/gpu/drm/xe/xe_gt_ccs_mode.h
+@@ -12,7 +12,7 @@
+ #include "xe_platform_types.h"
+
+ void xe_gt_apply_ccs_mode(struct xe_gt *gt);
+-void xe_gt_ccs_mode_sysfs_init(struct xe_gt *gt);
++int xe_gt_ccs_mode_sysfs_init(struct xe_gt *gt);
+
+ static inline bool xe_gt_ccs_mode_enabled(const struct xe_gt *gt)
+ {
+diff --git a/drivers/gpu/drm/xe/xe_huc.c b/drivers/gpu/drm/xe/xe_huc.c
+index eca109791c6ae..01b2d0bd26a30 100644
+--- a/drivers/gpu/drm/xe/xe_huc.c
++++ b/drivers/gpu/drm/xe/xe_huc.c
+@@ -53,7 +53,6 @@ static int huc_alloc_gsc_pkt(struct xe_huc *huc)
+ struct xe_gt *gt = huc_to_gt(huc);
+ struct xe_device *xe = gt_to_xe(gt);
+ struct xe_bo *bo;
+- int err;
+
+ /* we use a single object for both input and output */
+ bo = xe_bo_create_pin_map(xe, gt_to_tile(gt), NULL,
+@@ -66,13 +65,7 @@ static int huc_alloc_gsc_pkt(struct xe_huc *huc)
+
+ huc->gsc_pkt = bo;
+
+- err = drmm_add_action_or_reset(&xe->drm, free_gsc_pkt, huc);
+- if (err) {
+- free_gsc_pkt(&xe->drm, huc);
+- return err;
+- }
+-
+- return 0;
++ return drmm_add_action_or_reset(&xe->drm, free_gsc_pkt, huc);
+ }
+
+ int xe_huc_init(struct xe_huc *huc)
+diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c
+index e6a8b6d8eab70..3c3c497b6b911 100644
+--- a/drivers/hid/hid-logitech-dj.c
++++ b/drivers/hid/hid-logitech-dj.c
+@@ -965,9 +965,7 @@ static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev,
+ }
+ break;
+ case REPORT_TYPE_MOUSE:
+- workitem->reports_supported |= STD_MOUSE | HIDPP;
+- if (djrcv_dev->type == recvr_type_mouse_only)
+- workitem->reports_supported |= MULTIMEDIA;
++ workitem->reports_supported |= STD_MOUSE | HIDPP | MULTIMEDIA;
+ break;
+ }
+ }
+diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
+index 2df1ab3c31cc5..d965382196c69 100644
+--- a/drivers/hid/i2c-hid/i2c-hid-core.c
++++ b/drivers/hid/i2c-hid/i2c-hid-core.c
+@@ -64,7 +64,6 @@
+ /* flags */
+ #define I2C_HID_STARTED 0
+ #define I2C_HID_RESET_PENDING 1
+-#define I2C_HID_READ_PENDING 2
+
+ #define I2C_HID_PWR_ON 0x00
+ #define I2C_HID_PWR_SLEEP 0x01
+@@ -190,15 +189,10 @@ static int i2c_hid_xfer(struct i2c_hid *ihid,
+ msgs[n].len = recv_len;
+ msgs[n].buf = recv_buf;
+ n++;
+-
+- set_bit(I2C_HID_READ_PENDING, &ihid->flags);
+ }
+
+ ret = i2c_transfer(client->adapter, msgs, n);
+
+- if (recv_len)
+- clear_bit(I2C_HID_READ_PENDING, &ihid->flags);
+-
+ if (ret != n)
+ return ret < 0 ? ret : -EIO;
+
+@@ -556,9 +550,6 @@ static irqreturn_t i2c_hid_irq(int irq, void *dev_id)
+ {
+ struct i2c_hid *ihid = dev_id;
+
+- if (test_bit(I2C_HID_READ_PENDING, &ihid->flags))
+- return IRQ_HANDLED;
+-
+ i2c_hid_get_input(ihid);
+
+ return IRQ_HANDLED;
+@@ -735,12 +726,15 @@ static int i2c_hid_parse(struct hid_device *hid)
+ mutex_lock(&ihid->reset_lock);
+ do {
+ ret = i2c_hid_start_hwreset(ihid);
+- if (ret)
++ if (ret == 0)
++ ret = i2c_hid_finish_hwreset(ihid);
++ else
+ msleep(1000);
+ } while (tries-- > 0 && ret);
++ mutex_unlock(&ihid->reset_lock);
+
+ if (ret)
+- goto abort_reset;
++ return ret;
+
+ use_override = i2c_hid_get_dmi_hid_report_desc_override(client->name,
+ &rsize);
+@@ -750,11 +744,8 @@ static int i2c_hid_parse(struct hid_device *hid)
+ i2c_hid_dbg(ihid, "Using a HID report descriptor override\n");
+ } else {
+ rdesc = kzalloc(rsize, GFP_KERNEL);
+-
+- if (!rdesc) {
+- ret = -ENOMEM;
+- goto abort_reset;
+- }
++ if (!rdesc)
++ return -ENOMEM;
+
+ i2c_hid_dbg(ihid, "asking HID report descriptor\n");
+
+@@ -763,23 +754,10 @@ static int i2c_hid_parse(struct hid_device *hid)
+ rdesc, rsize);
+ if (ret) {
+ hid_err(hid, "reading report descriptor failed\n");
+- goto abort_reset;
++ goto out;
+ }
+ }
+
+- /*
+- * Windows directly reads the report-descriptor after sending reset
+- * and then waits for resets completion afterwards. Some touchpads
+- * actually wait for the report-descriptor to be read before signalling
+- * reset completion.
+- */
+- ret = i2c_hid_finish_hwreset(ihid);
+-abort_reset:
+- clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
+- mutex_unlock(&ihid->reset_lock);
+- if (ret)
+- goto out;
+-
+ i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
+
+ ret = hid_parse_report(hid, rdesc, rsize);
+diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c
+index a49c6affd7c4c..dd5fc60874ba1 100644
+--- a/drivers/hid/intel-ish-hid/ipc/ipc.c
++++ b/drivers/hid/intel-ish-hid/ipc/ipc.c
+@@ -948,6 +948,7 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
+ if (!dev)
+ return NULL;
+
++ dev->devc = &pdev->dev;
+ ishtp_device_init(dev);
+
+ init_waitqueue_head(&dev->wait_hw_ready);
+@@ -983,7 +984,6 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev)
+ }
+
+ dev->ops = &ish_hw_ops;
+- dev->devc = &pdev->dev;
+ dev->mtu = IPC_PAYLOAD_SIZE - sizeof(struct ishtp_msg_hdr);
+ return dev;
+ }
+diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
+index 3bd48d4b6318f..5e2cefb37e1a4 100644
+--- a/drivers/i2c/i2c-core-base.c
++++ b/drivers/i2c/i2c-core-base.c
+@@ -2200,13 +2200,18 @@ static int i2c_check_for_quirks(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ * Returns negative errno, else the number of messages executed.
+ *
+ * Adapter lock must be held when calling this function. No debug logging
+- * takes place. adap->algo->master_xfer existence isn't checked.
++ * takes place.
+ */
+ int __i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ {
+ unsigned long orig_jiffies;
+ int ret, try;
+
++ if (!adap->algo->master_xfer) {
++ dev_dbg(&adap->dev, "I2C level transfers not supported\n");
++ return -EOPNOTSUPP;
++ }
++
+ if (WARN_ON(!msgs || num < 1))
+ return -EINVAL;
+
+@@ -2273,11 +2278,6 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ {
+ int ret;
+
+- if (!adap->algo->master_xfer) {
+- dev_dbg(&adap->dev, "I2C level transfers not supported\n");
+- return -EOPNOTSUPP;
+- }
+-
+ /* REVISIT the fault reporting model here is weak:
+ *
+ * - When we get an error after receiving N bytes from a slave,
+diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
+index b822752c42617..6b386511cd1f4 100644
+--- a/drivers/irqchip/irq-gic-v3-its.c
++++ b/drivers/irqchip/irq-gic-v3-its.c
+@@ -4561,13 +4561,8 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
+ irqd_set_resend_when_in_progress(irq_get_irq_data(virq + i));
+ }
+
+- if (err) {
+- if (i > 0)
+- its_vpe_irq_domain_free(domain, virq, i);
+-
+- its_lpi_free(bitmap, base, nr_ids);
+- its_free_prop_table(vprop_page);
+- }
++ if (err)
++ its_vpe_irq_domain_free(domain, virq, i);
+
+ return err;
+ }
+diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
+index 572333ead5fb8..4bd4f32bcdabb 100644
+--- a/drivers/misc/eeprom/at24.c
++++ b/drivers/misc/eeprom/at24.c
+@@ -758,15 +758,6 @@ static int at24_probe(struct i2c_client *client)
+ }
+ pm_runtime_enable(dev);
+
+- at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
+- if (IS_ERR(at24->nvmem)) {
+- pm_runtime_disable(dev);
+- if (!pm_runtime_status_suspended(dev))
+- regulator_disable(at24->vcc_reg);
+- return dev_err_probe(dev, PTR_ERR(at24->nvmem),
+- "failed to register nvmem\n");
+- }
+-
+ /*
+ * Perform a one-byte test read to verify that the chip is functional,
+ * unless powering on the device is to be avoided during probe (i.e.
+@@ -782,6 +773,15 @@ static int at24_probe(struct i2c_client *client)
+ }
+ }
+
++ at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
++ if (IS_ERR(at24->nvmem)) {
++ pm_runtime_disable(dev);
++ if (!pm_runtime_status_suspended(dev))
++ regulator_disable(at24->vcc_reg);
++ return dev_err_probe(dev, PTR_ERR(at24->nvmem),
++ "failed to register nvmem\n");
++ }
++
+ /* If this a SPD EEPROM, probe for DDR3 thermal sensor */
+ if (cdata == &at24_data_spd)
+ at24_probe_temp_sensor(client);
+diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
+index 668e0aceeebac..e113b99a3eab5 100644
+--- a/drivers/mmc/host/sdhci-msm.c
++++ b/drivers/mmc/host/sdhci-msm.c
+@@ -2694,6 +2694,11 @@ static __maybe_unused int sdhci_msm_runtime_suspend(struct device *dev)
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
++ unsigned long flags;
++
++ spin_lock_irqsave(&host->lock, flags);
++ host->runtime_suspended = true;
++ spin_unlock_irqrestore(&host->lock, flags);
+
+ /* Drop the performance vote */
+ dev_pm_opp_set_rate(dev, 0);
+@@ -2708,6 +2713,7 @@ static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev)
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
++ unsigned long flags;
+ int ret;
+
+ ret = clk_bulk_prepare_enable(ARRAY_SIZE(msm_host->bulk_clks),
+@@ -2726,7 +2732,15 @@ static __maybe_unused int sdhci_msm_runtime_resume(struct device *dev)
+
+ dev_pm_opp_set_rate(dev, msm_host->clk_rate);
+
+- return sdhci_msm_ice_resume(msm_host);
++ ret = sdhci_msm_ice_resume(msm_host);
++ if (ret)
++ return ret;
++
++ spin_lock_irqsave(&host->lock, flags);
++ host->runtime_suspended = false;
++ spin_unlock_irqrestore(&host->lock, flags);
++
++ return ret;
+ }
+
+ static const struct dev_pm_ops sdhci_msm_pm_ops = {
+diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c
+index fa29460fd2903..60b42126a4edb 100644
+--- a/drivers/mmc/host/sdhci-of-dwcmshc.c
++++ b/drivers/mmc/host/sdhci-of-dwcmshc.c
+@@ -612,6 +612,7 @@ static int th1520_execute_tuning(struct sdhci_host *host, u32 opcode)
+
+ /* perform tuning */
+ sdhci_start_tuning(host);
++ host->tuning_loop_count = 128;
+ host->tuning_err = __sdhci_execute_tuning(host, opcode);
+ if (host->tuning_err) {
+ /* disable auto-tuning upon tuning error */
+diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
+index 5887feb347a4e..0de87bc638405 100644
+--- a/drivers/mtd/mtdcore.c
++++ b/drivers/mtd/mtdcore.c
+@@ -900,7 +900,7 @@ static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd,
+ config.name = compatible;
+ config.id = NVMEM_DEVID_AUTO;
+ config.owner = THIS_MODULE;
+- config.add_legacy_fixed_of_cells = true;
++ config.add_legacy_fixed_of_cells = !mtd_type_is_nand(mtd);
+ config.type = NVMEM_TYPE_OTP;
+ config.root_only = true;
+ config.ignore_wp = true;
+diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c
+index 5243fab9face0..8db7fc4245711 100644
+--- a/drivers/mtd/nand/raw/diskonchip.c
++++ b/drivers/mtd/nand/raw/diskonchip.c
+@@ -53,7 +53,7 @@ static unsigned long doc_locations[] __initdata = {
+ 0xe8000, 0xea000, 0xec000, 0xee000,
+ #endif
+ #endif
+- 0xffffffff };
++};
+
+ static struct mtd_info *doclist = NULL;
+
+@@ -1554,7 +1554,7 @@ static int __init init_nanddoc(void)
+ if (ret < 0)
+ return ret;
+ } else {
+- for (i = 0; (doc_locations[i] != 0xffffffff); i++) {
++ for (i = 0; i < ARRAY_SIZE(doc_locations); i++) {
+ doc_probe(doc_locations[i]);
+ }
+ }
+diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
+index b079605c84d38..b8cff9240b286 100644
+--- a/drivers/mtd/nand/raw/qcom_nandc.c
++++ b/drivers/mtd/nand/raw/qcom_nandc.c
+@@ -2815,7 +2815,7 @@ static int qcom_misc_cmd_type_exec(struct nand_chip *chip, const struct nand_sub
+ host->cfg0_raw & ~(7 << CW_PER_PAGE));
+ nandc_set_reg(chip, NAND_DEV0_CFG1, host->cfg1_raw);
+ instrs = 3;
+- } else {
++ } else if (q_op.cmd_reg != OP_RESET_DEVICE) {
+ return 0;
+ }
+
+@@ -2830,9 +2830,8 @@ static int qcom_misc_cmd_type_exec(struct nand_chip *chip, const struct nand_sub
+ nandc_set_reg(chip, NAND_EXEC_CMD, 1);
+
+ write_reg_dma(nandc, NAND_FLASH_CMD, instrs, NAND_BAM_NEXT_SGL);
+- (q_op.cmd_reg == OP_BLOCK_ERASE) ? write_reg_dma(nandc, NAND_DEV0_CFG0,
+- 2, NAND_BAM_NEXT_SGL) : read_reg_dma(nandc,
+- NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
++ if (q_op.cmd_reg == OP_BLOCK_ERASE)
++ write_reg_dma(nandc, NAND_DEV0_CFG0, 2, NAND_BAM_NEXT_SGL);
+
+ write_reg_dma(nandc, NAND_EXEC_CMD, 1, NAND_BAM_NEXT_SGL);
+ read_reg_dma(nandc, NAND_FLASH_STATUS, 1, NAND_BAM_NEXT_SGL);
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
+index 7de8a9c9e4576..32416d8802ca4 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -566,13 +566,61 @@ static void mv88e6xxx_translate_cmode(u8 cmode, unsigned long *supported)
+ phy_interface_set_rgmii(supported);
+ }
+
+-static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
+- struct phylink_config *config)
++static void
++mv88e6250_setup_supported_interfaces(struct mv88e6xxx_chip *chip, int port,
++ struct phylink_config *config)
+ {
+ unsigned long *supported = config->supported_interfaces;
++ int err;
++ u16 reg;
+
+- /* Translate the default cmode */
+- mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
++ err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®);
++ if (err) {
++ dev_err(chip->dev, "p%d: failed to read port status\n", port);
++ return;
++ }
++
++ switch (reg & MV88E6250_PORT_STS_PORTMODE_MASK) {
++ case MV88E6250_PORT_STS_PORTMODE_MII_10_HALF_PHY:
++ case MV88E6250_PORT_STS_PORTMODE_MII_100_HALF_PHY:
++ case MV88E6250_PORT_STS_PORTMODE_MII_10_FULL_PHY:
++ case MV88E6250_PORT_STS_PORTMODE_MII_100_FULL_PHY:
++ __set_bit(PHY_INTERFACE_MODE_REVMII, supported);
++ break;
++
++ case MV88E6250_PORT_STS_PORTMODE_MII_HALF:
++ case MV88E6250_PORT_STS_PORTMODE_MII_FULL:
++ __set_bit(PHY_INTERFACE_MODE_MII, supported);
++ break;
++
++ case MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL_PHY:
++ case MV88E6250_PORT_STS_PORTMODE_MII_200_RMII_FULL_PHY:
++ case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_HALF_PHY:
++ case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL_PHY:
++ __set_bit(PHY_INTERFACE_MODE_REVRMII, supported);
++ break;
++
++ case MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL:
++ case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL:
++ __set_bit(PHY_INTERFACE_MODE_RMII, supported);
++ break;
++
++ case MV88E6250_PORT_STS_PORTMODE_MII_100_RGMII:
++ __set_bit(PHY_INTERFACE_MODE_RGMII, supported);
++ break;
++
++ default:
++ dev_err(chip->dev,
++ "p%d: invalid port mode in status register: %04x\n",
++ port, reg);
++ }
++}
++
++static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
++ struct phylink_config *config)
++{
++ if (!mv88e6xxx_phy_is_internal(chip, port))
++ mv88e6250_setup_supported_interfaces(chip, port, config);
+
+ config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100;
+ }
+diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
+index 86deeb347cbc1..ddadeb9bfdaee 100644
+--- a/drivers/net/dsa/mv88e6xxx/port.h
++++ b/drivers/net/dsa/mv88e6xxx/port.h
+@@ -25,10 +25,25 @@
+ #define MV88E6250_PORT_STS_PORTMODE_PHY_100_HALF 0x0900
+ #define MV88E6250_PORT_STS_PORTMODE_PHY_10_FULL 0x0a00
+ #define MV88E6250_PORT_STS_PORTMODE_PHY_100_FULL 0x0b00
+-#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF 0x0c00
+-#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF 0x0d00
+-#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL 0x0e00
+-#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL 0x0f00
++/* - Modes with PHY suffix use output instead of input clock
++ * - Modes without RMII or RGMII use MII
++ * - Modes without speed do not have a fixed speed specified in the manual
++ * ("DC to x MHz" - variable clock support?)
++ */
++#define MV88E6250_PORT_STS_PORTMODE_MII_DISABLED 0x0000
++#define MV88E6250_PORT_STS_PORTMODE_MII_100_RGMII 0x0100
++#define MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL_PHY 0x0200
++#define MV88E6250_PORT_STS_PORTMODE_MII_200_RMII_FULL_PHY 0x0400
++#define MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL 0x0600
++#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL 0x0700
++#define MV88E6250_PORT_STS_PORTMODE_MII_HALF 0x0800
++#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_HALF_PHY 0x0900
++#define MV88E6250_PORT_STS_PORTMODE_MII_FULL 0x0a00
++#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL_PHY 0x0b00
++#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF_PHY 0x0c00
++#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF_PHY 0x0d00
++#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL_PHY 0x0e00
++#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL_PHY 0x0f00
+ #define MV88E6XXX_PORT_STS_LINK 0x0800
+ #define MV88E6XXX_PORT_STS_DUPLEX 0x0400
+ #define MV88E6XXX_PORT_STS_SPEED_MASK 0x0300
+diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
+index 78901e2e73032..529172a87ae50 100644
+--- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
++++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c
+@@ -435,10 +435,8 @@ static void umac_init(struct bcmasp_intf *intf)
+ umac_wl(intf, 0x800, UMC_RX_MAX_PKT_SZ);
+ }
+
+-static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
++static int bcmasp_tx_reclaim(struct bcmasp_intf *intf)
+ {
+- struct bcmasp_intf *intf =
+- container_of(napi, struct bcmasp_intf, tx_napi);
+ struct bcmasp_intf_stats64 *stats = &intf->stats64;
+ struct device *kdev = &intf->parent->pdev->dev;
+ unsigned long read, released = 0;
+@@ -481,10 +479,16 @@ static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
+ DESC_RING_COUNT);
+ }
+
+- /* Ensure all descriptors have been written to DRAM for the hardware
+- * to see updated contents.
+- */
+- wmb();
++ return released;
++}
++
++static int bcmasp_tx_poll(struct napi_struct *napi, int budget)
++{
++ struct bcmasp_intf *intf =
++ container_of(napi, struct bcmasp_intf, tx_napi);
++ int released = 0;
++
++ released = bcmasp_tx_reclaim(intf);
+
+ napi_complete(&intf->tx_napi);
+
+@@ -796,6 +800,7 @@ static int bcmasp_init_tx(struct bcmasp_intf *intf)
+
+ intf->tx_spb_index = 0;
+ intf->tx_spb_clean_index = 0;
++ memset(intf->tx_cbs, 0, sizeof(struct bcmasp_tx_cb) * DESC_RING_COUNT);
+
+ netif_napi_add_tx(intf->ndev, &intf->tx_napi, bcmasp_tx_poll);
+
+@@ -906,6 +911,8 @@ static void bcmasp_netif_deinit(struct net_device *dev)
+ } while (timeout-- > 0);
+ tx_spb_dma_wl(intf, 0x0, TX_SPB_DMA_FIFO_CTRL);
+
++ bcmasp_tx_reclaim(intf);
++
+ umac_enable_set(intf, UMC_CMD_TX_EN, 0);
+
+ phy_stop(dev->phydev);
+diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
+index 3e4fb3c3e8342..1be6d14030bcf 100644
+--- a/drivers/net/ethernet/broadcom/b44.c
++++ b/drivers/net/ethernet/broadcom/b44.c
+@@ -2009,12 +2009,14 @@ static int b44_set_pauseparam(struct net_device *dev,
+ bp->flags |= B44_FLAG_TX_PAUSE;
+ else
+ bp->flags &= ~B44_FLAG_TX_PAUSE;
+- if (bp->flags & B44_FLAG_PAUSE_AUTO) {
+- b44_halt(bp);
+- b44_init_rings(bp);
+- b44_init_hw(bp, B44_FULL_RESET);
+- } else {
+- __b44_set_flow_ctrl(bp, bp->flags);
++ if (netif_running(dev)) {
++ if (bp->flags & B44_FLAG_PAUSE_AUTO) {
++ b44_halt(bp);
++ b44_init_rings(bp);
++ b44_init_hw(bp, B44_FULL_RESET);
++ } else {
++ __b44_set_flow_ctrl(bp, bp->flags);
++ }
+ }
+ spin_unlock_irq(&bp->lock);
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index 5e6e32d708e24..e133a412a13fc 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -1735,7 +1735,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
+ skb = bnxt_copy_skb(bnapi, data_ptr, len, mapping);
+ if (!skb) {
+ bnxt_abort_tpa(cpr, idx, agg_bufs);
+- cpr->sw_stats.rx.rx_oom_discards += 1;
++ cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
+ return NULL;
+ }
+ } else {
+@@ -1745,7 +1745,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
+ new_data = __bnxt_alloc_rx_frag(bp, &new_mapping, GFP_ATOMIC);
+ if (!new_data) {
+ bnxt_abort_tpa(cpr, idx, agg_bufs);
+- cpr->sw_stats.rx.rx_oom_discards += 1;
++ cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
+ return NULL;
+ }
+
+@@ -1761,7 +1761,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
+ if (!skb) {
+ skb_free_frag(data);
+ bnxt_abort_tpa(cpr, idx, agg_bufs);
+- cpr->sw_stats.rx.rx_oom_discards += 1;
++ cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
+ return NULL;
+ }
+ skb_reserve(skb, bp->rx_offset);
+@@ -1772,7 +1772,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp,
+ skb = bnxt_rx_agg_pages_skb(bp, cpr, skb, idx, agg_bufs, true);
+ if (!skb) {
+ /* Page reuse already handled by bnxt_rx_pages(). */
+- cpr->sw_stats.rx.rx_oom_discards += 1;
++ cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
+ return NULL;
+ }
+ }
+@@ -2051,11 +2051,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
+ u32 frag_len = bnxt_rx_agg_pages_xdp(bp, cpr, &xdp,
+ cp_cons, agg_bufs,
+ false);
+- if (!frag_len) {
+- cpr->sw_stats.rx.rx_oom_discards += 1;
+- rc = -ENOMEM;
+- goto next_rx;
+- }
++ if (!frag_len)
++ goto oom_next_rx;
+ }
+ xdp_active = true;
+ }
+@@ -2078,9 +2075,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
+ else
+ bnxt_xdp_buff_frags_free(rxr, &xdp);
+ }
+- cpr->sw_stats.rx.rx_oom_discards += 1;
+- rc = -ENOMEM;
+- goto next_rx;
++ goto oom_next_rx;
+ }
+ } else {
+ u32 payload;
+@@ -2091,29 +2086,21 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
+ payload = 0;
+ skb = bp->rx_skb_func(bp, rxr, cons, data, data_ptr, dma_addr,
+ payload | len);
+- if (!skb) {
+- cpr->sw_stats.rx.rx_oom_discards += 1;
+- rc = -ENOMEM;
+- goto next_rx;
+- }
++ if (!skb)
++ goto oom_next_rx;
+ }
+
+ if (agg_bufs) {
+ if (!xdp_active) {
+ skb = bnxt_rx_agg_pages_skb(bp, cpr, skb, cp_cons, agg_bufs, false);
+- if (!skb) {
+- cpr->sw_stats.rx.rx_oom_discards += 1;
+- rc = -ENOMEM;
+- goto next_rx;
+- }
++ if (!skb)
++ goto oom_next_rx;
+ } else {
+ skb = bnxt_xdp_build_skb(bp, skb, agg_bufs, rxr->page_pool, &xdp, rxcmp1);
+ if (!skb) {
+ /* we should be able to free the old skb here */
+ bnxt_xdp_buff_frags_free(rxr, &xdp);
+- cpr->sw_stats.rx.rx_oom_discards += 1;
+- rc = -ENOMEM;
+- goto next_rx;
++ goto oom_next_rx;
+ }
+ }
+ }
+@@ -2191,6 +2178,11 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
+ *raw_cons = tmp_raw_cons;
+
+ return rc;
++
++oom_next_rx:
++ cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1;
++ rc = -ENOMEM;
++ goto next_rx;
+ }
+
+ /* In netpoll mode, if we are using a combined completion ring, we need to
+@@ -2237,7 +2229,7 @@ static int bnxt_force_rx_discard(struct bnxt *bp,
+ }
+ rc = bnxt_rx_pkt(bp, cpr, raw_cons, event);
+ if (rc && rc != -EBUSY)
+- cpr->sw_stats.rx.rx_netpoll_discards += 1;
++ cpr->bnapi->cp_ring.sw_stats.rx.rx_netpoll_discards += 1;
+ return rc;
+ }
+
+@@ -8906,7 +8898,7 @@ static void bnxt_try_map_fw_health_reg(struct bnxt *bp)
+ BNXT_FW_HEALTH_WIN_BASE +
+ BNXT_GRC_REG_CHIP_NUM);
+ }
+- if (!BNXT_CHIP_P5(bp))
++ if (!BNXT_CHIP_P5_PLUS(bp))
+ return;
+
+ status_loc = BNXT_GRC_REG_STATUS_P5 |
+@@ -12776,6 +12768,16 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
+ bnxt_rtnl_unlock_sp(bp);
+ }
+
++static void bnxt_fw_fatal_close(struct bnxt *bp)
++{
++ bnxt_tx_disable(bp);
++ bnxt_disable_napi(bp);
++ bnxt_disable_int_sync(bp);
++ bnxt_free_irq(bp);
++ bnxt_clear_int_mode(bp);
++ pci_disable_device(bp->pdev);
++}
++
+ static void bnxt_fw_reset_close(struct bnxt *bp)
+ {
+ bnxt_ulp_stop(bp);
+@@ -12789,12 +12791,7 @@ static void bnxt_fw_reset_close(struct bnxt *bp)
+ pci_read_config_word(bp->pdev, PCI_SUBSYSTEM_ID, &val);
+ if (val == 0xffff)
+ bp->fw_reset_min_dsecs = 0;
+- bnxt_tx_disable(bp);
+- bnxt_disable_napi(bp);
+- bnxt_disable_int_sync(bp);
+- bnxt_free_irq(bp);
+- bnxt_clear_int_mode(bp);
+- pci_disable_device(bp->pdev);
++ bnxt_fw_fatal_close(bp);
+ }
+ __bnxt_close_nic(bp, true, false);
+ bnxt_vf_reps_free(bp);
+@@ -15040,6 +15037,7 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
+ {
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct bnxt *bp = netdev_priv(netdev);
++ bool abort = false;
+
+ netdev_info(netdev, "PCI I/O error detected\n");
+
+@@ -15048,16 +15046,27 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev,
+
+ bnxt_ulp_stop(bp);
+
+- if (state == pci_channel_io_perm_failure) {
++ if (test_and_set_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
++ netdev_err(bp->dev, "Firmware reset already in progress\n");
++ abort = true;
++ }
++
++ if (abort || state == pci_channel_io_perm_failure) {
+ rtnl_unlock();
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+- if (state == pci_channel_io_frozen)
++ /* Link is not reliable anymore if state is pci_channel_io_frozen
++ * so we disable bus master to prevent any potential bad DMAs before
++ * freeing kernel memory.
++ */
++ if (state == pci_channel_io_frozen) {
+ set_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state);
++ bnxt_fw_fatal_close(bp);
++ }
+
+ if (netif_running(netdev))
+- bnxt_close(netdev);
++ __bnxt_close_nic(bp, true, true);
+
+ if (pci_is_enabled(pdev))
+ pci_disable_device(pdev);
+@@ -15141,6 +15150,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev)
+ }
+
+ reset_exit:
++ clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
+ bnxt_clear_reservations(bp, true);
+ rtnl_unlock();
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index bb4ab3a9576b9..f3c1df46f699c 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -16186,8 +16186,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ val = FIELD_GET(I40E_PRTGL_SAH_MFS_MASK,
+ rd32(&pf->hw, I40E_PRTGL_SAH));
+ if (val < MAX_FRAME_SIZE_DEFAULT)
+- dev_warn(&pdev->dev, "MFS for port %x has been set below the default: %x\n",
+- pf->hw.port, val);
++ dev_warn(&pdev->dev, "MFS for port %x (%d) has been set below the default (%d)\n",
++ pf->hw.port, val, MAX_FRAME_SIZE_DEFAULT);
+
+ /* Add a filter to drop all Flow control frames from any VSI from being
+ * transmitted. By doing so we stop a malicious VF from sending out
+@@ -16733,7 +16733,7 @@ static int __init i40e_init_module(void)
+ * since we need to be able to guarantee forward progress even under
+ * memory pressure.
+ */
+- i40e_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, i40e_driver_name);
++ i40e_wq = alloc_workqueue("%s", 0, 0, i40e_driver_name);
+ if (!i40e_wq) {
+ pr_err("%s: Failed to create workqueue\n", i40e_driver_name);
+ return -ENOMEM;
+diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
+index 335fd13e86f71..1ff381361c29d 100644
+--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
++++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
+@@ -3511,6 +3511,34 @@ static void iavf_del_all_cloud_filters(struct iavf_adapter *adapter)
+ spin_unlock_bh(&adapter->cloud_filter_list_lock);
+ }
+
++/**
++ * iavf_is_tc_config_same - Compare the mqprio TC config with the
++ * TC config already configured on this adapter.
++ * @adapter: board private structure
++ * @mqprio_qopt: TC config received from kernel.
++ *
++ * This function compares the TC config received from the kernel
++ * with the config already configured on the adapter.
++ *
++ * Return: True if configuration is same, false otherwise.
++ **/
++static bool iavf_is_tc_config_same(struct iavf_adapter *adapter,
++ struct tc_mqprio_qopt *mqprio_qopt)
++{
++ struct virtchnl_channel_info *ch = &adapter->ch_config.ch_info[0];
++ int i;
++
++ if (adapter->num_tc != mqprio_qopt->num_tc)
++ return false;
++
++ for (i = 0; i < adapter->num_tc; i++) {
++ if (ch[i].count != mqprio_qopt->count[i] ||
++ ch[i].offset != mqprio_qopt->offset[i])
++ return false;
++ }
++ return true;
++}
++
+ /**
+ * __iavf_setup_tc - configure multiple traffic classes
+ * @netdev: network interface device structure
+@@ -3568,7 +3596,7 @@ static int __iavf_setup_tc(struct net_device *netdev, void *type_data)
+ if (ret)
+ return ret;
+ /* Return if same TC config is requested */
+- if (adapter->num_tc == num_tc)
++ if (iavf_is_tc_config_same(adapter, &mqprio_qopt->qopt))
+ return 0;
+ adapter->num_tc = num_tc;
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
+index 2ffdae9a82dfb..15ade19de55a2 100644
+--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c
++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
+@@ -863,6 +863,11 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
+ return 0;
+ }
+
++ if (flags & ICE_VF_RESET_LOCK)
++ mutex_lock(&vf->cfg_lock);
++ else
++ lockdep_assert_held(&vf->cfg_lock);
++
+ lag = pf->lag;
+ mutex_lock(&pf->lag_mutex);
+ if (lag && lag->bonded && lag->primary) {
+@@ -874,11 +879,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
+ act_prt = ICE_LAG_INVALID_PORT;
+ }
+
+- if (flags & ICE_VF_RESET_LOCK)
+- mutex_lock(&vf->cfg_lock);
+- else
+- lockdep_assert_held(&vf->cfg_lock);
+-
+ if (ice_is_vf_disabled(vf)) {
+ vsi = ice_get_vf_vsi(vf);
+ if (!vsi) {
+@@ -963,14 +963,14 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags)
+ ice_mbx_clear_malvf(&vf->mbx_info);
+
+ out_unlock:
+- if (flags & ICE_VF_RESET_LOCK)
+- mutex_unlock(&vf->cfg_lock);
+-
+ if (lag && lag->bonded && lag->primary &&
+ act_prt != ICE_LAG_INVALID_PORT)
+ ice_lag_move_vf_nodes_cfg(lag, pri_prt, act_prt);
+ mutex_unlock(&pf->lag_mutex);
+
++ if (flags & ICE_VF_RESET_LOCK)
++ mutex_unlock(&vf->cfg_lock);
++
+ return err;
+ }
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index 42b5ed02bc87f..d94b7b88e14ca 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -2181,7 +2181,6 @@ void rvu_npc_freemem(struct rvu *rvu)
+
+ kfree(pkind->rsrc.bmap);
+ npc_mcam_rsrcs_deinit(rvu);
+- kfree(mcam->counters.bmap);
+ if (rvu->kpu_prfl_addr)
+ iounmap(rvu->kpu_prfl_addr);
+ else
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
+index b2cabd6ab86cb..cc9bcc4200324 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
+@@ -1640,6 +1640,7 @@ static const struct macsec_ops macsec_offload_ops = {
+ .mdo_add_secy = mlx5e_macsec_add_secy,
+ .mdo_upd_secy = mlx5e_macsec_upd_secy,
+ .mdo_del_secy = mlx5e_macsec_del_secy,
++ .rx_uses_md_dst = true,
+ };
+
+ bool mlx5e_macsec_handle_tx_skb(struct mlx5e_macsec *macsec, struct sk_buff *skb)
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
+index e4d7739bd7c88..4a79c0d7e7ad8 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
+@@ -849,7 +849,7 @@ static void mlxsw_emad_rx_listener_func(struct sk_buff *skb, u16 local_port,
+
+ static const struct mlxsw_listener mlxsw_emad_rx_listener =
+ MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false,
+- EMAD, DISCARD);
++ EMAD, FORWARD);
+
+ static int mlxsw_emad_tlv_enable(struct mlxsw_core *mlxsw_core)
+ {
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
+index faa63ea9b83e1..1915fa41c6224 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
+@@ -95,7 +95,7 @@ struct mlxsw_afa_set {
+ */
+ has_trap:1,
+ has_police:1;
+- unsigned int ref_count;
++ refcount_t ref_count;
+ struct mlxsw_afa_set *next; /* Pointer to the next set. */
+ struct mlxsw_afa_set *prev; /* Pointer to the previous set,
+ * note that set may have multiple
+@@ -120,7 +120,7 @@ struct mlxsw_afa_fwd_entry {
+ struct rhash_head ht_node;
+ struct mlxsw_afa_fwd_entry_ht_key ht_key;
+ u32 kvdl_index;
+- unsigned int ref_count;
++ refcount_t ref_count;
+ };
+
+ static const struct rhashtable_params mlxsw_afa_fwd_entry_ht_params = {
+@@ -282,7 +282,7 @@ static struct mlxsw_afa_set *mlxsw_afa_set_create(bool is_first)
+ /* Need to initialize the set to pass by default */
+ mlxsw_afa_set_goto_set(set, MLXSW_AFA_SET_GOTO_BINDING_CMD_TERM, 0);
+ set->ht_key.is_first = is_first;
+- set->ref_count = 1;
++ refcount_set(&set->ref_count, 1);
+ return set;
+ }
+
+@@ -330,7 +330,7 @@ static void mlxsw_afa_set_unshare(struct mlxsw_afa *mlxsw_afa,
+ static void mlxsw_afa_set_put(struct mlxsw_afa *mlxsw_afa,
+ struct mlxsw_afa_set *set)
+ {
+- if (--set->ref_count)
++ if (!refcount_dec_and_test(&set->ref_count))
+ return;
+ if (set->shared)
+ mlxsw_afa_set_unshare(mlxsw_afa, set);
+@@ -350,7 +350,7 @@ static struct mlxsw_afa_set *mlxsw_afa_set_get(struct mlxsw_afa *mlxsw_afa,
+ set = rhashtable_lookup_fast(&mlxsw_afa->set_ht, &orig_set->ht_key,
+ mlxsw_afa_set_ht_params);
+ if (set) {
+- set->ref_count++;
++ refcount_inc(&set->ref_count);
+ mlxsw_afa_set_put(mlxsw_afa, orig_set);
+ } else {
+ set = orig_set;
+@@ -564,7 +564,7 @@ mlxsw_afa_fwd_entry_create(struct mlxsw_afa *mlxsw_afa, u16 local_port)
+ if (!fwd_entry)
+ return ERR_PTR(-ENOMEM);
+ fwd_entry->ht_key.local_port = local_port;
+- fwd_entry->ref_count = 1;
++ refcount_set(&fwd_entry->ref_count, 1);
+
+ err = rhashtable_insert_fast(&mlxsw_afa->fwd_entry_ht,
+ &fwd_entry->ht_node,
+@@ -607,7 +607,7 @@ mlxsw_afa_fwd_entry_get(struct mlxsw_afa *mlxsw_afa, u16 local_port)
+ fwd_entry = rhashtable_lookup_fast(&mlxsw_afa->fwd_entry_ht, &ht_key,
+ mlxsw_afa_fwd_entry_ht_params);
+ if (fwd_entry) {
+- fwd_entry->ref_count++;
++ refcount_inc(&fwd_entry->ref_count);
+ return fwd_entry;
+ }
+ return mlxsw_afa_fwd_entry_create(mlxsw_afa, local_port);
+@@ -616,7 +616,7 @@ mlxsw_afa_fwd_entry_get(struct mlxsw_afa *mlxsw_afa, u16 local_port)
+ static void mlxsw_afa_fwd_entry_put(struct mlxsw_afa *mlxsw_afa,
+ struct mlxsw_afa_fwd_entry *fwd_entry)
+ {
+- if (--fwd_entry->ref_count)
++ if (!refcount_dec_and_test(&fwd_entry->ref_count))
+ return;
+ mlxsw_afa_fwd_entry_destroy(mlxsw_afa, fwd_entry);
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
+index 0d5e6f9b466ec..947500f8ed714 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c
+@@ -5,6 +5,7 @@
+ #include <linux/slab.h>
+ #include <linux/list.h>
+ #include <linux/errno.h>
++#include <linux/refcount.h>
+
+ #include "item.h"
+ #include "core_acl_flex_keys.h"
+@@ -107,7 +108,7 @@ EXPORT_SYMBOL(mlxsw_afk_destroy);
+
+ struct mlxsw_afk_key_info {
+ struct list_head list;
+- unsigned int ref_count;
++ refcount_t ref_count;
+ unsigned int blocks_count;
+ int element_to_block[MLXSW_AFK_ELEMENT_MAX]; /* index is element, value
+ * is index inside "blocks"
+@@ -334,7 +335,7 @@ mlxsw_afk_key_info_create(struct mlxsw_afk *mlxsw_afk,
+ if (err)
+ goto err_picker;
+ list_add(&key_info->list, &mlxsw_afk->key_info_list);
+- key_info->ref_count = 1;
++ refcount_set(&key_info->ref_count, 1);
+ return key_info;
+
+ err_picker:
+@@ -356,7 +357,7 @@ mlxsw_afk_key_info_get(struct mlxsw_afk *mlxsw_afk,
+
+ key_info = mlxsw_afk_key_info_find(mlxsw_afk, elusage);
+ if (key_info) {
+- key_info->ref_count++;
++ refcount_inc(&key_info->ref_count);
+ return key_info;
+ }
+ return mlxsw_afk_key_info_create(mlxsw_afk, elusage);
+@@ -365,7 +366,7 @@ EXPORT_SYMBOL(mlxsw_afk_key_info_get);
+
+ void mlxsw_afk_key_info_put(struct mlxsw_afk_key_info *key_info)
+ {
+- if (--key_info->ref_count)
++ if (!refcount_dec_and_test(&key_info->ref_count))
+ return;
+ mlxsw_afk_key_info_destroy(key_info);
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
+index 53b150b7ae4e7..6c06b05927608 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c
+@@ -1357,24 +1357,20 @@ static struct mlxsw_linecards_event_ops mlxsw_env_event_ops = {
+ .got_inactive = mlxsw_env_got_inactive,
+ };
+
+-static int mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env)
++static void mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env)
+ {
+ char mcam_pl[MLXSW_REG_MCAM_LEN];
+- bool mcia_128b_supported;
++ bool mcia_128b_supported = false;
+ int err;
+
+ mlxsw_reg_mcam_pack(mcam_pl,
+ MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES);
+ err = mlxsw_reg_query(mlxsw_env->core, MLXSW_REG(mcam), mcam_pl);
+- if (err)
+- return err;
+-
+- mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B,
+- &mcia_128b_supported);
++ if (!err)
++ mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B,
++ &mcia_128b_supported);
+
+ mlxsw_env->max_eeprom_len = mcia_128b_supported ? 128 : 48;
+-
+- return 0;
+ }
+
+ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
+@@ -1445,15 +1441,11 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
+ if (err)
+ goto err_type_set;
+
+- err = mlxsw_env_max_module_eeprom_len_query(env);
+- if (err)
+- goto err_eeprom_len_query;
+-
++ mlxsw_env_max_module_eeprom_len_query(env);
+ env->line_cards[0]->active = true;
+
+ return 0;
+
+-err_eeprom_len_query:
+ err_type_set:
+ mlxsw_env_module_event_disable(env, 0);
+ err_mlxsw_env_module_event_enable:
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
+index af99bf17eb36d..f42a1b1c93687 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
+@@ -1530,7 +1530,7 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
+ {
+ struct pci_dev *pdev = mlxsw_pci->pdev;
+ char mcam_pl[MLXSW_REG_MCAM_LEN];
+- bool pci_reset_supported;
++ bool pci_reset_supported = false;
+ u32 sys_status;
+ int err;
+
+@@ -1548,11 +1548,9 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
+ mlxsw_reg_mcam_pack(mcam_pl,
+ MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES);
+ err = mlxsw_reg_query(mlxsw_pci->core, MLXSW_REG(mcam), mcam_pl);
+- if (err)
+- return err;
+-
+- mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET,
+- &pci_reset_supported);
++ if (!err)
++ mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET,
++ &pci_reset_supported);
+
+ if (pci_reset_supported) {
+ pci_dbg(pdev, "Starting PCI reset flow\n");
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+index 7c59c8a135840..b01b000bc71c1 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+@@ -9,6 +9,7 @@
+ #include <linux/rhashtable.h>
+ #include <linux/netdevice.h>
+ #include <linux/mutex.h>
++#include <linux/refcount.h>
+ #include <net/net_namespace.h>
+ #include <net/tc_act/tc_vlan.h>
+
+@@ -55,7 +56,7 @@ struct mlxsw_sp_acl_ruleset {
+ struct rhash_head ht_node; /* Member of acl HT */
+ struct mlxsw_sp_acl_ruleset_ht_key ht_key;
+ struct rhashtable rule_ht;
+- unsigned int ref_count;
++ refcount_t ref_count;
+ unsigned int min_prio;
+ unsigned int max_prio;
+ unsigned long priv[];
+@@ -99,7 +100,7 @@ static bool
+ mlxsw_sp_acl_ruleset_is_singular(const struct mlxsw_sp_acl_ruleset *ruleset)
+ {
+ /* We hold a reference on ruleset ourselves */
+- return ruleset->ref_count == 2;
++ return refcount_read(&ruleset->ref_count) == 2;
+ }
+
+ int mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp,
+@@ -176,7 +177,7 @@ mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp,
+ ruleset = kzalloc(alloc_size, GFP_KERNEL);
+ if (!ruleset)
+ return ERR_PTR(-ENOMEM);
+- ruleset->ref_count = 1;
++ refcount_set(&ruleset->ref_count, 1);
+ ruleset->ht_key.block = block;
+ ruleset->ht_key.chain_index = chain_index;
+ ruleset->ht_key.ops = ops;
+@@ -222,13 +223,13 @@ static void mlxsw_sp_acl_ruleset_destroy(struct mlxsw_sp *mlxsw_sp,
+
+ static void mlxsw_sp_acl_ruleset_ref_inc(struct mlxsw_sp_acl_ruleset *ruleset)
+ {
+- ruleset->ref_count++;
++ refcount_inc(&ruleset->ref_count);
+ }
+
+ static void mlxsw_sp_acl_ruleset_ref_dec(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_ruleset *ruleset)
+ {
+- if (--ruleset->ref_count)
++ if (!refcount_dec_and_test(&ruleset->ref_count))
+ return;
+ mlxsw_sp_acl_ruleset_destroy(mlxsw_sp, ruleset);
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+index 50ea1eff02b2f..92a406f02eae7 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c
+@@ -9,6 +9,8 @@
+ #include <linux/rhashtable.h>
+ #include <linux/netdevice.h>
+ #include <linux/mutex.h>
++#include <linux/refcount.h>
++#include <linux/idr.h>
+ #include <net/devlink.h>
+ #include <trace/events/mlxsw.h>
+
+@@ -57,41 +59,43 @@ int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp,
+ static int mlxsw_sp_acl_tcam_region_id_get(struct mlxsw_sp_acl_tcam *tcam,
+ u16 *p_id)
+ {
+- u16 id;
++ int id;
+
+- id = find_first_zero_bit(tcam->used_regions, tcam->max_regions);
+- if (id < tcam->max_regions) {
+- __set_bit(id, tcam->used_regions);
+- *p_id = id;
+- return 0;
+- }
+- return -ENOBUFS;
++ id = ida_alloc_max(&tcam->used_regions, tcam->max_regions - 1,
++ GFP_KERNEL);
++ if (id < 0)
++ return id;
++
++ *p_id = id;
++
++ return 0;
+ }
+
+ static void mlxsw_sp_acl_tcam_region_id_put(struct mlxsw_sp_acl_tcam *tcam,
+ u16 id)
+ {
+- __clear_bit(id, tcam->used_regions);
++ ida_free(&tcam->used_regions, id);
+ }
+
+ static int mlxsw_sp_acl_tcam_group_id_get(struct mlxsw_sp_acl_tcam *tcam,
+ u16 *p_id)
+ {
+- u16 id;
++ int id;
+
+- id = find_first_zero_bit(tcam->used_groups, tcam->max_groups);
+- if (id < tcam->max_groups) {
+- __set_bit(id, tcam->used_groups);
+- *p_id = id;
+- return 0;
+- }
+- return -ENOBUFS;
++ id = ida_alloc_max(&tcam->used_groups, tcam->max_groups - 1,
++ GFP_KERNEL);
++ if (id < 0)
++ return id;
++
++ *p_id = id;
++
++ return 0;
+ }
+
+ static void mlxsw_sp_acl_tcam_group_id_put(struct mlxsw_sp_acl_tcam *tcam,
+ u16 id)
+ {
+- __clear_bit(id, tcam->used_groups);
++ ida_free(&tcam->used_groups, id);
+ }
+
+ struct mlxsw_sp_acl_tcam_pattern {
+@@ -155,7 +159,7 @@ struct mlxsw_sp_acl_tcam_vregion {
+ struct mlxsw_sp_acl_tcam_rehash_ctx ctx;
+ } rehash;
+ struct mlxsw_sp *mlxsw_sp;
+- unsigned int ref_count;
++ refcount_t ref_count;
+ };
+
+ struct mlxsw_sp_acl_tcam_vchunk;
+@@ -176,7 +180,7 @@ struct mlxsw_sp_acl_tcam_vchunk {
+ unsigned int priority; /* Priority within the vregion and group */
+ struct mlxsw_sp_acl_tcam_vgroup *vgroup;
+ struct mlxsw_sp_acl_tcam_vregion *vregion;
+- unsigned int ref_count;
++ refcount_t ref_count;
+ };
+
+ struct mlxsw_sp_acl_tcam_entry {
+@@ -714,7 +718,9 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
+ rehash.dw.work);
+ int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS;
+
++ mutex_lock(&vregion->lock);
+ mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion, &credits);
++ mutex_unlock(&vregion->lock);
+ if (credits < 0)
+ /* Rehash gone out of credits so it was interrupted.
+ * Schedule the work as soon as possible to continue.
+@@ -724,6 +730,17 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work)
+ mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion);
+ }
+
++static void
++mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(struct mlxsw_sp_acl_tcam_rehash_ctx *ctx)
++{
++ /* The entry markers are relative to the current chunk and therefore
++ * needs to be reset together with the chunk marker.
++ */
++ ctx->current_vchunk = NULL;
++ ctx->start_ventry = NULL;
++ ctx->stop_ventry = NULL;
++}
++
+ static void
+ mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(struct mlxsw_sp_acl_tcam_vchunk *vchunk)
+ {
+@@ -746,7 +763,7 @@ mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(struct mlxsw_sp_acl_tcam_vregion *v
+ * the current chunk pointer to make sure all chunks
+ * are properly migrated.
+ */
+- vregion->rehash.ctx.current_vchunk = NULL;
++ mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(&vregion->rehash.ctx);
+ }
+
+ static struct mlxsw_sp_acl_tcam_vregion *
+@@ -769,7 +786,7 @@ mlxsw_sp_acl_tcam_vregion_create(struct mlxsw_sp *mlxsw_sp,
+ vregion->tcam = tcam;
+ vregion->mlxsw_sp = mlxsw_sp;
+ vregion->vgroup = vgroup;
+- vregion->ref_count = 1;
++ refcount_set(&vregion->ref_count, 1);
+
+ vregion->key_info = mlxsw_afk_key_info_get(afk, elusage);
+ if (IS_ERR(vregion->key_info)) {
+@@ -819,10 +836,14 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam *tcam = vregion->tcam;
+
+ if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) {
++ struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx;
++
+ mutex_lock(&tcam->lock);
+ list_del(&vregion->tlist);
+ mutex_unlock(&tcam->lock);
+- cancel_delayed_work_sync(&vregion->rehash.dw);
++ if (cancel_delayed_work_sync(&vregion->rehash.dw) &&
++ ctx->hints_priv)
++ ops->region_rehash_hints_put(ctx->hints_priv);
+ }
+ mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion);
+ if (vregion->region2)
+@@ -856,7 +877,7 @@ mlxsw_sp_acl_tcam_vregion_get(struct mlxsw_sp *mlxsw_sp,
+ */
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+- vregion->ref_count++;
++ refcount_inc(&vregion->ref_count);
+ return vregion;
+ }
+
+@@ -871,7 +892,7 @@ static void
+ mlxsw_sp_acl_tcam_vregion_put(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vregion *vregion)
+ {
+- if (--vregion->ref_count)
++ if (!refcount_dec_and_test(&vregion->ref_count))
+ return;
+ mlxsw_sp_acl_tcam_vregion_destroy(mlxsw_sp, vregion);
+ }
+@@ -924,7 +945,7 @@ mlxsw_sp_acl_tcam_vchunk_create(struct mlxsw_sp *mlxsw_sp,
+ INIT_LIST_HEAD(&vchunk->ventry_list);
+ vchunk->priority = priority;
+ vchunk->vgroup = vgroup;
+- vchunk->ref_count = 1;
++ refcount_set(&vchunk->ref_count, 1);
+
+ vregion = mlxsw_sp_acl_tcam_vregion_get(mlxsw_sp, vgroup,
+ priority, elusage);
+@@ -1008,7 +1029,7 @@ mlxsw_sp_acl_tcam_vchunk_get(struct mlxsw_sp *mlxsw_sp,
+ if (WARN_ON(!mlxsw_afk_key_info_subset(vchunk->vregion->key_info,
+ elusage)))
+ return ERR_PTR(-EINVAL);
+- vchunk->ref_count++;
++ refcount_inc(&vchunk->ref_count);
+ return vchunk;
+ }
+ return mlxsw_sp_acl_tcam_vchunk_create(mlxsw_sp, vgroup,
+@@ -1019,7 +1040,7 @@ static void
+ mlxsw_sp_acl_tcam_vchunk_put(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk)
+ {
+- if (--vchunk->ref_count)
++ if (!refcount_dec_and_test(&vchunk->ref_count))
+ return;
+ mlxsw_sp_acl_tcam_vchunk_destroy(mlxsw_sp, vchunk);
+ }
+@@ -1153,8 +1174,14 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_ventry *ventry,
+ bool *activity)
+ {
+- return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp,
+- ventry->entry, activity);
++ struct mlxsw_sp_acl_tcam_vregion *vregion = ventry->vchunk->vregion;
++ int err;
++
++ mutex_lock(&vregion->lock);
++ err = mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, ventry->entry,
++ activity);
++ mutex_unlock(&vregion->lock);
++ return err;
+ }
+
+ static int
+@@ -1188,6 +1215,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_start(struct mlxsw_sp *mlxsw_sp,
+ {
+ struct mlxsw_sp_acl_tcam_chunk *new_chunk;
+
++ WARN_ON(vchunk->chunk2);
++
+ new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region);
+ if (IS_ERR(new_chunk))
+ return PTR_ERR(new_chunk);
+@@ -1206,7 +1235,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_end(struct mlxsw_sp *mlxsw_sp,
+ {
+ mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2);
+ vchunk->chunk2 = NULL;
+- ctx->current_vchunk = NULL;
++ mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
+ }
+
+ static int
+@@ -1229,6 +1258,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
+ return 0;
+ }
+
++ if (list_empty(&vchunk->ventry_list))
++ goto out;
++
+ /* If the migration got interrupted, we have the ventry to start from
+ * stored in context.
+ */
+@@ -1238,6 +1270,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
+ ventry = list_first_entry(&vchunk->ventry_list,
+ typeof(*ventry), list);
+
++ WARN_ON(ventry->vchunk != vchunk);
++
+ list_for_each_entry_from(ventry, &vchunk->ventry_list, list) {
+ /* During rollback, once we reach the ventry that failed
+ * to migrate, we are done.
+@@ -1278,6 +1312,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp,
+ }
+ }
+
++out:
+ mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk, ctx);
+ return 0;
+ }
+@@ -1291,6 +1326,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_acl_tcam_vchunk *vchunk;
+ int err;
+
++ if (list_empty(&vregion->vchunk_list))
++ return 0;
++
+ /* If the migration got interrupted, we have the vchunk
+ * we are working on stored in context.
+ */
+@@ -1319,16 +1357,17 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
+ int err, err2;
+
+ trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion);
+- mutex_lock(&vregion->lock);
+ err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
+ ctx, credits);
+ if (err) {
++ if (ctx->this_is_rollback)
++ return err;
+ /* In case migration was not successful, we need to swap
+ * so the original region pointer is assigned again
+ * to vregion->region.
+ */
+ swap(vregion->region, vregion->region2);
+- ctx->current_vchunk = NULL;
++ mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
+ ctx->this_is_rollback = true;
+ err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion,
+ ctx, credits);
+@@ -1339,7 +1378,6 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp,
+ /* Let the rollback to be continued later on. */
+ }
+ }
+- mutex_unlock(&vregion->lock);
+ trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion);
+ return err;
+ }
+@@ -1388,6 +1426,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp,
+
+ ctx->hints_priv = hints_priv;
+ ctx->this_is_rollback = false;
++ mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx);
+
+ return 0;
+
+@@ -1440,7 +1479,8 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
+ err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion,
+ ctx, credits);
+ if (err) {
+- dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
++ dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n");
++ return;
+ }
+
+ if (*credits >= 0)
+@@ -1548,19 +1588,11 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
+ if (max_tcam_regions < max_regions)
+ max_regions = max_tcam_regions;
+
+- tcam->used_regions = bitmap_zalloc(max_regions, GFP_KERNEL);
+- if (!tcam->used_regions) {
+- err = -ENOMEM;
+- goto err_alloc_used_regions;
+- }
++ ida_init(&tcam->used_regions);
+ tcam->max_regions = max_regions;
+
+ max_groups = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_GROUPS);
+- tcam->used_groups = bitmap_zalloc(max_groups, GFP_KERNEL);
+- if (!tcam->used_groups) {
+- err = -ENOMEM;
+- goto err_alloc_used_groups;
+- }
++ ida_init(&tcam->used_groups);
+ tcam->max_groups = max_groups;
+ tcam->max_group_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+ ACL_MAX_GROUP_SIZE);
+@@ -1574,10 +1606,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp,
+ return 0;
+
+ err_tcam_init:
+- bitmap_free(tcam->used_groups);
+-err_alloc_used_groups:
+- bitmap_free(tcam->used_regions);
+-err_alloc_used_regions:
++ ida_destroy(&tcam->used_groups);
++ ida_destroy(&tcam->used_regions);
+ mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp);
+ err_rehash_params_register:
+ mutex_destroy(&tcam->lock);
+@@ -1590,8 +1620,8 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp,
+ const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops;
+
+ ops->fini(mlxsw_sp, tcam->priv);
+- bitmap_free(tcam->used_groups);
+- bitmap_free(tcam->used_regions);
++ ida_destroy(&tcam->used_groups);
++ ida_destroy(&tcam->used_regions);
+ mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp);
+ mutex_destroy(&tcam->lock);
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
+index 462bf448497d3..79a1d86065125 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h
+@@ -6,15 +6,16 @@
+
+ #include <linux/list.h>
+ #include <linux/parman.h>
++#include <linux/idr.h>
+
+ #include "reg.h"
+ #include "spectrum.h"
+ #include "core_acl_flex_keys.h"
+
+ struct mlxsw_sp_acl_tcam {
+- unsigned long *used_regions; /* bit array */
++ struct ida used_regions;
+ unsigned int max_regions;
+- unsigned long *used_groups; /* bit array */
++ struct ida used_groups;
+ unsigned int max_groups;
+ unsigned int max_group_size;
+ struct mutex lock; /* guards vregion list */
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+index 7164f9e6370fb..87617df694ab2 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+@@ -501,7 +501,7 @@ struct mlxsw_sp_rt6 {
+
+ struct mlxsw_sp_lpm_tree {
+ u8 id; /* tree ID */
+- unsigned int ref_count;
++ refcount_t ref_count;
+ enum mlxsw_sp_l3proto proto;
+ unsigned long prefix_ref_count[MLXSW_SP_PREFIX_COUNT];
+ struct mlxsw_sp_prefix_usage prefix_usage;
+@@ -578,7 +578,7 @@ mlxsw_sp_lpm_tree_find_unused(struct mlxsw_sp *mlxsw_sp)
+
+ for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
+ lpm_tree = &mlxsw_sp->router->lpm.trees[i];
+- if (lpm_tree->ref_count == 0)
++ if (refcount_read(&lpm_tree->ref_count) == 0)
+ return lpm_tree;
+ }
+ return NULL;
+@@ -654,7 +654,7 @@ mlxsw_sp_lpm_tree_create(struct mlxsw_sp *mlxsw_sp,
+ sizeof(lpm_tree->prefix_usage));
+ memset(&lpm_tree->prefix_ref_count, 0,
+ sizeof(lpm_tree->prefix_ref_count));
+- lpm_tree->ref_count = 1;
++ refcount_set(&lpm_tree->ref_count, 1);
+ return lpm_tree;
+
+ err_left_struct_set:
+@@ -678,7 +678,7 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp,
+
+ for (i = 0; i < mlxsw_sp->router->lpm.tree_count; i++) {
+ lpm_tree = &mlxsw_sp->router->lpm.trees[i];
+- if (lpm_tree->ref_count != 0 &&
++ if (refcount_read(&lpm_tree->ref_count) &&
+ lpm_tree->proto == proto &&
+ mlxsw_sp_prefix_usage_eq(&lpm_tree->prefix_usage,
+ prefix_usage)) {
+@@ -691,14 +691,15 @@ mlxsw_sp_lpm_tree_get(struct mlxsw_sp *mlxsw_sp,
+
+ static void mlxsw_sp_lpm_tree_hold(struct mlxsw_sp_lpm_tree *lpm_tree)
+ {
+- lpm_tree->ref_count++;
++ refcount_inc(&lpm_tree->ref_count);
+ }
+
+ static void mlxsw_sp_lpm_tree_put(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_lpm_tree *lpm_tree)
+ {
+- if (--lpm_tree->ref_count == 0)
+- mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree);
++ if (!refcount_dec_and_test(&lpm_tree->ref_count))
++ return;
++ mlxsw_sp_lpm_tree_destroy(mlxsw_sp, lpm_tree);
+ }
+
+ #define MLXSW_SP_LPM_TREE_MIN 1 /* tree 0 is reserved */
+diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+index 6c749c148148d..6397ff0dc951c 100644
+--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
++++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+@@ -61,7 +61,7 @@ struct mlxsw_sp_bridge_port {
+ struct mlxsw_sp_bridge_device *bridge_device;
+ struct list_head list;
+ struct list_head vlans_list;
+- unsigned int ref_count;
++ refcount_t ref_count;
+ u8 stp_state;
+ unsigned long flags;
+ bool mrouter;
+@@ -495,7 +495,7 @@ mlxsw_sp_bridge_port_create(struct mlxsw_sp_bridge_device *bridge_device,
+ BR_MCAST_FLOOD;
+ INIT_LIST_HEAD(&bridge_port->vlans_list);
+ list_add(&bridge_port->list, &bridge_device->ports_list);
+- bridge_port->ref_count = 1;
++ refcount_set(&bridge_port->ref_count, 1);
+
+ err = switchdev_bridge_port_offload(brport_dev, mlxsw_sp_port->dev,
+ NULL, NULL, NULL, false, extack);
+@@ -531,7 +531,7 @@ mlxsw_sp_bridge_port_get(struct mlxsw_sp_bridge *bridge,
+
+ bridge_port = mlxsw_sp_bridge_port_find(bridge, brport_dev);
+ if (bridge_port) {
+- bridge_port->ref_count++;
++ refcount_inc(&bridge_port->ref_count);
+ return bridge_port;
+ }
+
+@@ -558,7 +558,7 @@ static void mlxsw_sp_bridge_port_put(struct mlxsw_sp_bridge *bridge,
+ {
+ struct mlxsw_sp_bridge_device *bridge_device;
+
+- if (--bridge_port->ref_count != 0)
++ if (!refcount_dec_and_test(&bridge_port->ref_count))
+ return;
+ bridge_device = bridge_port->bridge_device;
+ mlxsw_sp_bridge_port_destroy(bridge_port);
+diff --git a/drivers/net/ethernet/ti/am65-cpts.c b/drivers/net/ethernet/ti/am65-cpts.c
+index c66618d91c28f..f89716b1cfb64 100644
+--- a/drivers/net/ethernet/ti/am65-cpts.c
++++ b/drivers/net/ethernet/ti/am65-cpts.c
+@@ -784,6 +784,11 @@ static bool am65_cpts_match_tx_ts(struct am65_cpts *cpts,
+ struct am65_cpts_skb_cb_data *skb_cb =
+ (struct am65_cpts_skb_cb_data *)skb->cb;
+
++ if ((ptp_classify_raw(skb) & PTP_CLASS_V1) &&
++ ((mtype_seqid & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK) ==
++ (skb_cb->skb_mtype_seqid & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK)))
++ mtype_seqid = skb_cb->skb_mtype_seqid;
++
+ if (mtype_seqid == skb_cb->skb_mtype_seqid) {
+ u64 ns = event->timestamp;
+
+diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+index 411898a4f38ca..4a78e8a1cabf4 100644
+--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
++++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+@@ -421,12 +421,14 @@ static int prueth_init_rx_chns(struct prueth_emac *emac,
+ if (!i)
+ fdqring_id = k3_udma_glue_rx_flow_get_fdq_id(rx_chn->rx_chn,
+ i);
+- rx_chn->irq[i] = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, i);
+- if (rx_chn->irq[i] <= 0) {
+- ret = rx_chn->irq[i];
++ ret = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, i);
++ if (ret <= 0) {
++ if (!ret)
++ ret = -ENXIO;
+ netdev_err(ndev, "Failed to get rx dma irq");
+ goto fail;
+ }
++ rx_chn->irq[i] = ret;
+ }
+
+ return 0;
+diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+index 8706223a6e5aa..08d3e4069c5fa 100644
+--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
++++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+@@ -1598,7 +1598,7 @@ static void wx_set_num_queues(struct wx *wx)
+ */
+ static int wx_acquire_msix_vectors(struct wx *wx)
+ {
+- struct irq_affinity affd = {0, };
++ struct irq_affinity affd = { .pre_vectors = 1 };
+ int nvecs, i;
+
+ /* We start by asking for one vector per queue pair */
+diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
+index 2b5357d94ff56..63f932256c9f5 100644
+--- a/drivers/net/gtp.c
++++ b/drivers/net/gtp.c
+@@ -1111,11 +1111,12 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
+ static void gtp_dellink(struct net_device *dev, struct list_head *head)
+ {
+ struct gtp_dev *gtp = netdev_priv(dev);
++ struct hlist_node *next;
+ struct pdp_ctx *pctx;
+ int i;
+
+ for (i = 0; i < gtp->hash_size; i++)
+- hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], hlist_tid)
++ hlist_for_each_entry_safe(pctx, next, >p->tid_hash[i], hlist_tid)
+ pdp_context_delete(pctx);
+
+ list_del_rcu(>p->list);
+diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
+index 7f5426285c61b..ac3f6801c940c 100644
+--- a/drivers/net/macsec.c
++++ b/drivers/net/macsec.c
+@@ -999,10 +999,12 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
+ struct metadata_dst *md_dst;
+ struct macsec_rxh_data *rxd;
+ struct macsec_dev *macsec;
++ bool is_macsec_md_dst;
+
+ rcu_read_lock();
+ rxd = macsec_data_rcu(skb->dev);
+ md_dst = skb_metadata_dst(skb);
++ is_macsec_md_dst = md_dst && md_dst->type == METADATA_MACSEC;
+
+ list_for_each_entry_rcu(macsec, &rxd->secys, secys) {
+ struct sk_buff *nskb;
+@@ -1013,14 +1015,42 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
+ * the SecTAG, so we have to deduce which port to deliver to.
+ */
+ if (macsec_is_offloaded(macsec) && netif_running(ndev)) {
+- struct macsec_rx_sc *rx_sc = NULL;
++ const struct macsec_ops *ops;
+
+- if (md_dst && md_dst->type == METADATA_MACSEC)
+- rx_sc = find_rx_sc(&macsec->secy, md_dst->u.macsec_info.sci);
++ ops = macsec_get_ops(macsec, NULL);
+
+- if (md_dst && md_dst->type == METADATA_MACSEC && !rx_sc)
++ if (ops->rx_uses_md_dst && !is_macsec_md_dst)
+ continue;
+
++ if (is_macsec_md_dst) {
++ struct macsec_rx_sc *rx_sc;
++
++ /* All drivers that implement MACsec offload
++ * support using skb metadata destinations must
++ * indicate that they do so.
++ */
++ DEBUG_NET_WARN_ON_ONCE(!ops->rx_uses_md_dst);
++ rx_sc = find_rx_sc(&macsec->secy,
++ md_dst->u.macsec_info.sci);
++ if (!rx_sc)
++ continue;
++ /* device indicated macsec offload occurred */
++ skb->dev = ndev;
++ skb->pkt_type = PACKET_HOST;
++ eth_skb_pkt_type(skb, ndev);
++ ret = RX_HANDLER_ANOTHER;
++ goto out;
++ }
++
++ /* This datapath is insecure because it is unable to
++ * enforce isolation of broadcast/multicast traffic and
++ * unicast traffic with promiscuous mode on the macsec
++ * netdev. Since the core stack has no mechanism to
++ * check that the hardware did indeed receive MACsec
++ * traffic, it is possible that the response handling
++ * done by the MACsec port was to a plaintext packet.
++ * This violates the MACsec protocol standard.
++ */
+ if (ether_addr_equal_64bits(hdr->h_dest,
+ ndev->dev_addr)) {
+ /* exact match, divert skb to this port */
+@@ -1036,14 +1066,10 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb)
+ break;
+
+ nskb->dev = ndev;
+- if (ether_addr_equal_64bits(hdr->h_dest,
+- ndev->broadcast))
+- nskb->pkt_type = PACKET_BROADCAST;
+- else
+- nskb->pkt_type = PACKET_MULTICAST;
++ eth_skb_pkt_type(nskb, ndev);
+
+ __netif_rx(nskb);
+- } else if (rx_sc || ndev->flags & IFF_PROMISC) {
++ } else if (ndev->flags & IFF_PROMISC) {
+ skb->dev = ndev;
+ skb->pkt_type = PACKET_HOST;
+ ret = RX_HANDLER_ANOTHER;
+diff --git a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c
+index fa8c6fdcf3018..d7aaefb5226b6 100644
+--- a/drivers/net/phy/dp83869.c
++++ b/drivers/net/phy/dp83869.c
+@@ -695,7 +695,8 @@ static int dp83869_configure_mode(struct phy_device *phydev,
+ phy_ctrl_val = dp83869->mode;
+ if (phydev->interface == PHY_INTERFACE_MODE_MII) {
+ if (dp83869->mode == DP83869_100M_MEDIA_CONVERT ||
+- dp83869->mode == DP83869_RGMII_100_BASE) {
++ dp83869->mode == DP83869_RGMII_100_BASE ||
++ dp83869->mode == DP83869_RGMII_COPPER_ETHERNET) {
+ phy_ctrl_val |= DP83869_OP_MODE_MII;
+ } else {
+ phydev_err(phydev, "selected op-mode is not valid with MII mode\n");
+diff --git a/drivers/net/phy/mediatek-ge-soc.c b/drivers/net/phy/mediatek-ge-soc.c
+index 0f3a1538a8b8e..f4f9412d0cd7e 100644
+--- a/drivers/net/phy/mediatek-ge-soc.c
++++ b/drivers/net/phy/mediatek-ge-soc.c
+@@ -216,6 +216,9 @@
+ #define MTK_PHY_LED_ON_LINK1000 BIT(0)
+ #define MTK_PHY_LED_ON_LINK100 BIT(1)
+ #define MTK_PHY_LED_ON_LINK10 BIT(2)
++#define MTK_PHY_LED_ON_LINK (MTK_PHY_LED_ON_LINK10 |\
++ MTK_PHY_LED_ON_LINK100 |\
++ MTK_PHY_LED_ON_LINK1000)
+ #define MTK_PHY_LED_ON_LINKDOWN BIT(3)
+ #define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */
+ #define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */
+@@ -231,6 +234,12 @@
+ #define MTK_PHY_LED_BLINK_100RX BIT(3)
+ #define MTK_PHY_LED_BLINK_10TX BIT(4)
+ #define MTK_PHY_LED_BLINK_10RX BIT(5)
++#define MTK_PHY_LED_BLINK_RX (MTK_PHY_LED_BLINK_10RX |\
++ MTK_PHY_LED_BLINK_100RX |\
++ MTK_PHY_LED_BLINK_1000RX)
++#define MTK_PHY_LED_BLINK_TX (MTK_PHY_LED_BLINK_10TX |\
++ MTK_PHY_LED_BLINK_100TX |\
++ MTK_PHY_LED_BLINK_1000TX)
+ #define MTK_PHY_LED_BLINK_COLLISION BIT(6)
+ #define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7)
+ #define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8)
+@@ -1247,11 +1256,9 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
+ if (blink < 0)
+ return -EIO;
+
+- if ((on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 |
+- MTK_PHY_LED_ON_LINK10)) ||
+- (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX |
+- MTK_PHY_LED_BLINK_10RX | MTK_PHY_LED_BLINK_1000TX |
+- MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX)))
++ if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX |
++ MTK_PHY_LED_ON_LINKDOWN)) ||
++ (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX)))
+ set_bit(bit_netdev, &priv->led_state);
+ else
+ clear_bit(bit_netdev, &priv->led_state);
+@@ -1269,7 +1276,7 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
+ if (!rules)
+ return 0;
+
+- if (on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 | MTK_PHY_LED_ON_LINK10))
++ if (on & MTK_PHY_LED_ON_LINK)
+ *rules |= BIT(TRIGGER_NETDEV_LINK);
+
+ if (on & MTK_PHY_LED_ON_LINK10)
+@@ -1287,10 +1294,10 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
+ if (on & MTK_PHY_LED_ON_HDX)
+ *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
+
+- if (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | MTK_PHY_LED_BLINK_10RX))
++ if (blink & MTK_PHY_LED_BLINK_RX)
+ *rules |= BIT(TRIGGER_NETDEV_RX);
+
+- if (blink & (MTK_PHY_LED_BLINK_1000TX | MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX))
++ if (blink & MTK_PHY_LED_BLINK_TX)
+ *rules |= BIT(TRIGGER_NETDEV_TX);
+
+ return 0;
+@@ -1323,15 +1330,19 @@ static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
+ on |= MTK_PHY_LED_ON_LINK1000;
+
+ if (rules & BIT(TRIGGER_NETDEV_RX)) {
+- blink |= MTK_PHY_LED_BLINK_10RX |
+- MTK_PHY_LED_BLINK_100RX |
+- MTK_PHY_LED_BLINK_1000RX;
++ blink |= (on & MTK_PHY_LED_ON_LINK) ?
++ (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10RX : 0) |
++ ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100RX : 0) |
++ ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000RX : 0)) :
++ MTK_PHY_LED_BLINK_RX;
+ }
+
+ if (rules & BIT(TRIGGER_NETDEV_TX)) {
+- blink |= MTK_PHY_LED_BLINK_10TX |
+- MTK_PHY_LED_BLINK_100TX |
+- MTK_PHY_LED_BLINK_1000TX;
++ blink |= (on & MTK_PHY_LED_ON_LINK) ?
++ (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10TX : 0) |
++ ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100TX : 0) |
++ ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000TX : 0)) :
++ MTK_PHY_LED_BLINK_TX;
+ }
+
+ if (blink || on)
+@@ -1344,9 +1355,7 @@ static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
+ MTK_PHY_LED0_ON_CTRL,
+ MTK_PHY_LED_ON_FDX |
+ MTK_PHY_LED_ON_HDX |
+- MTK_PHY_LED_ON_LINK10 |
+- MTK_PHY_LED_ON_LINK100 |
+- MTK_PHY_LED_ON_LINK1000,
++ MTK_PHY_LED_ON_LINK,
+ on);
+
+ if (ret)
+diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
+index 3078511f76083..21b6c4d94a632 100644
+--- a/drivers/net/usb/ax88179_178a.c
++++ b/drivers/net/usb/ax88179_178a.c
+@@ -1456,21 +1456,16 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+ /* Skip IP alignment pseudo header */
+ skb_pull(skb, 2);
+
+- skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd);
+ ax88179_rx_checksum(skb, pkt_hdr);
+ return 1;
+ }
+
+- ax_skb = skb_clone(skb, GFP_ATOMIC);
++ ax_skb = netdev_alloc_skb_ip_align(dev->net, pkt_len);
+ if (!ax_skb)
+ return 0;
+- skb_trim(ax_skb, pkt_len);
++ skb_put(ax_skb, pkt_len);
++ memcpy(ax_skb->data, skb->data + 2, pkt_len);
+
+- /* Skip IP alignment pseudo header */
+- skb_pull(ax_skb, 2);
+-
+- skb->truesize = pkt_len_plus_padd +
+- SKB_DATA_ALIGN(sizeof(struct sk_buff));
+ ax88179_rx_checksum(ax_skb, pkt_hdr);
+ usbnet_skb_return(dev, ax_skb);
+
+diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
+index 0bedb804824ba..9ec46048d361d 100644
+--- a/drivers/net/vxlan/vxlan_core.c
++++ b/drivers/net/vxlan/vxlan_core.c
+@@ -1615,6 +1615,10 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan,
+ if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
+ return false;
+
++ /* Ignore packets from invalid src-address */
++ if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
++ return false;
++
+ /* Get address from the outer IP header */
+ if (vxlan_get_sk_family(vs) == AF_INET) {
+ saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+index 233ae81884a0e..ae0eb585b61ee 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c
+@@ -53,6 +53,8 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ if (!pasn)
+ return -ENOBUFS;
+
++ iwl_mvm_ftm_remove_pasn_sta(mvm, addr);
++
+ pasn->cipher = iwl_mvm_cipher_to_location_cipher(cipher);
+
+ switch (pasn->cipher) {
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+index 7b6f1cdca067e..97d44354dbbb5 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+@@ -2815,7 +2815,8 @@ static int iwl_mvm_build_scan_cmd(struct iwl_mvm *mvm,
+ if (ver_handler->version != scan_ver)
+ continue;
+
+- return ver_handler->handler(mvm, vif, params, type, uid);
++ err = ver_handler->handler(mvm, vif, params, type, uid);
++ return err ? : uid;
+ }
+
+ err = iwl_mvm_scan_umac(mvm, vif, params, type, uid);
+diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
+index a84340c2075ff..a9c3fb2ccdcdb 100644
+--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
++++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
+@@ -3818,7 +3818,7 @@ static int hwsim_pmsr_report_nl(struct sk_buff *msg, struct genl_info *info)
+ }
+
+ nla_for_each_nested(peer, peers, rem) {
+- struct cfg80211_pmsr_result result;
++ struct cfg80211_pmsr_result result = {};
+
+ err = mac80211_hwsim_parse_pmsr_result(peer, &result, info);
+ if (err)
+diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c
+index 7eb17f46a8153..9e1a34e23af26 100644
+--- a/drivers/nfc/trf7970a.c
++++ b/drivers/nfc/trf7970a.c
+@@ -424,7 +424,8 @@ struct trf7970a {
+ enum trf7970a_state state;
+ struct device *dev;
+ struct spi_device *spi;
+- struct regulator *regulator;
++ struct regulator *vin_regulator;
++ struct regulator *vddio_regulator;
+ struct nfc_digital_dev *ddev;
+ u32 quirks;
+ bool is_initiator;
+@@ -1883,7 +1884,7 @@ static int trf7970a_power_up(struct trf7970a *trf)
+ if (trf->state != TRF7970A_ST_PWR_OFF)
+ return 0;
+
+- ret = regulator_enable(trf->regulator);
++ ret = regulator_enable(trf->vin_regulator);
+ if (ret) {
+ dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret);
+ return ret;
+@@ -1926,7 +1927,7 @@ static int trf7970a_power_down(struct trf7970a *trf)
+ if (trf->en2_gpiod && !(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW))
+ gpiod_set_value_cansleep(trf->en2_gpiod, 0);
+
+- ret = regulator_disable(trf->regulator);
++ ret = regulator_disable(trf->vin_regulator);
+ if (ret)
+ dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__,
+ ret);
+@@ -2065,37 +2066,37 @@ static int trf7970a_probe(struct spi_device *spi)
+ mutex_init(&trf->lock);
+ INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler);
+
+- trf->regulator = devm_regulator_get(&spi->dev, "vin");
+- if (IS_ERR(trf->regulator)) {
+- ret = PTR_ERR(trf->regulator);
++ trf->vin_regulator = devm_regulator_get(&spi->dev, "vin");
++ if (IS_ERR(trf->vin_regulator)) {
++ ret = PTR_ERR(trf->vin_regulator);
+ dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret);
+ goto err_destroy_lock;
+ }
+
+- ret = regulator_enable(trf->regulator);
++ ret = regulator_enable(trf->vin_regulator);
+ if (ret) {
+ dev_err(trf->dev, "Can't enable VIN: %d\n", ret);
+ goto err_destroy_lock;
+ }
+
+- uvolts = regulator_get_voltage(trf->regulator);
++ uvolts = regulator_get_voltage(trf->vin_regulator);
+ if (uvolts > 4000000)
+ trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3;
+
+- trf->regulator = devm_regulator_get(&spi->dev, "vdd-io");
+- if (IS_ERR(trf->regulator)) {
+- ret = PTR_ERR(trf->regulator);
++ trf->vddio_regulator = devm_regulator_get(&spi->dev, "vdd-io");
++ if (IS_ERR(trf->vddio_regulator)) {
++ ret = PTR_ERR(trf->vddio_regulator);
+ dev_err(trf->dev, "Can't get VDD_IO regulator: %d\n", ret);
+- goto err_destroy_lock;
++ goto err_disable_vin_regulator;
+ }
+
+- ret = regulator_enable(trf->regulator);
++ ret = regulator_enable(trf->vddio_regulator);
+ if (ret) {
+ dev_err(trf->dev, "Can't enable VDD_IO: %d\n", ret);
+- goto err_destroy_lock;
++ goto err_disable_vin_regulator;
+ }
+
+- if (regulator_get_voltage(trf->regulator) == 1800000) {
++ if (regulator_get_voltage(trf->vddio_regulator) == 1800000) {
+ trf->io_ctrl = TRF7970A_REG_IO_CTRL_IO_LOW;
+ dev_dbg(trf->dev, "trf7970a config vdd_io to 1.8V\n");
+ }
+@@ -2108,7 +2109,7 @@ static int trf7970a_probe(struct spi_device *spi)
+ if (!trf->ddev) {
+ dev_err(trf->dev, "Can't allocate NFC digital device\n");
+ ret = -ENOMEM;
+- goto err_disable_regulator;
++ goto err_disable_vddio_regulator;
+ }
+
+ nfc_digital_set_parent_dev(trf->ddev, trf->dev);
+@@ -2137,8 +2138,10 @@ static int trf7970a_probe(struct spi_device *spi)
+ trf7970a_shutdown(trf);
+ err_free_ddev:
+ nfc_digital_free_device(trf->ddev);
+-err_disable_regulator:
+- regulator_disable(trf->regulator);
++err_disable_vddio_regulator:
++ regulator_disable(trf->vddio_regulator);
++err_disable_vin_regulator:
++ regulator_disable(trf->vin_regulator);
+ err_destroy_lock:
+ mutex_destroy(&trf->lock);
+ return ret;
+@@ -2157,7 +2160,8 @@ static void trf7970a_remove(struct spi_device *spi)
+ nfc_digital_unregister_device(trf->ddev);
+ nfc_digital_free_device(trf->ddev);
+
+- regulator_disable(trf->regulator);
++ regulator_disable(trf->vddio_regulator);
++ regulator_disable(trf->vin_regulator);
+
+ mutex_destroy(&trf->lock);
+ }
+diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+index b700f52b7b679..11fcb1867118c 100644
+--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
++++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+@@ -110,8 +110,10 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
+ /* Source clock from SoC internal PLL */
+ writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL,
+ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062);
+- writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
+- imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
++ if (imx8_phy->drvdata->variant != IMX8MM) {
++ writel(AUX_PLL_REFCLK_SEL_SYS_PLL,
++ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063);
++ }
+ val = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM;
+ writel(val | ANA_AUX_RX_TERM_GND_EN,
+ imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064);
+diff --git a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c
+index 24c3371e2bb29..27f221a0f922d 100644
+--- a/drivers/phy/marvell/phy-mvebu-a3700-comphy.c
++++ b/drivers/phy/marvell/phy-mvebu-a3700-comphy.c
+@@ -603,7 +603,7 @@ static void comphy_gbe_phy_init(struct mvebu_a3700_comphy_lane *lane,
+ u16 val;
+
+ fix_idx = 0;
+- for (addr = 0; addr < 512; addr++) {
++ for (addr = 0; addr < ARRAY_SIZE(gbe_phy_init); addr++) {
+ /*
+ * All PHY register values are defined in full for 3.125Gbps
+ * SERDES speed. The values required for 1.25 Gbps are almost
+@@ -611,11 +611,12 @@ static void comphy_gbe_phy_init(struct mvebu_a3700_comphy_lane *lane,
+ * comparison to 3.125 Gbps values. These register values are
+ * stored in "gbe_phy_init_fix" array.
+ */
+- if (!is_1gbps && gbe_phy_init_fix[fix_idx].addr == addr) {
++ if (!is_1gbps &&
++ fix_idx < ARRAY_SIZE(gbe_phy_init_fix) &&
++ gbe_phy_init_fix[fix_idx].addr == addr) {
+ /* Use new value */
+ val = gbe_phy_init_fix[fix_idx].value;
+- if (fix_idx < ARRAY_SIZE(gbe_phy_init_fix))
+- fix_idx++;
++ fix_idx++;
+ } else {
+ val = gbe_phy_init[addr];
+ }
+diff --git a/drivers/phy/qualcomm/phy-qcom-m31.c b/drivers/phy/qualcomm/phy-qcom-m31.c
+index 03fb0d4b75d74..20d4c020a83c1 100644
+--- a/drivers/phy/qualcomm/phy-qcom-m31.c
++++ b/drivers/phy/qualcomm/phy-qcom-m31.c
+@@ -297,7 +297,7 @@ static int m31usb_phy_probe(struct platform_device *pdev)
+ return dev_err_probe(dev, PTR_ERR(qphy->phy),
+ "failed to create phy\n");
+
+- qphy->vreg = devm_regulator_get(dev, "vdda-phy");
++ qphy->vreg = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(qphy->vreg))
+ return dev_err_probe(dev, PTR_ERR(qphy->vreg),
+ "failed to get vreg\n");
+diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+index 17c4ad7553a5e..e74e1bf9ed60b 100644
+--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
++++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c
+@@ -112,6 +112,7 @@ enum qphy_reg_layout {
+ QPHY_COM_BIAS_EN_CLKBUFLR_EN,
+
+ QPHY_DP_PHY_STATUS,
++ QPHY_DP_PHY_VCO_DIV,
+
+ QPHY_TX_TX_POL_INV,
+ QPHY_TX_TX_DRV_LVL,
+@@ -137,6 +138,7 @@ static const unsigned int qmp_v3_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
+ [QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN,
+
+ [QPHY_DP_PHY_STATUS] = QSERDES_V3_DP_PHY_STATUS,
++ [QPHY_DP_PHY_VCO_DIV] = QSERDES_V3_DP_PHY_VCO_DIV,
+
+ [QPHY_TX_TX_POL_INV] = QSERDES_V3_TX_TX_POL_INV,
+ [QPHY_TX_TX_DRV_LVL] = QSERDES_V3_TX_TX_DRV_LVL,
+@@ -161,6 +163,7 @@ static const unsigned int qmp_v45_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
+ [QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V4_COM_BIAS_EN_CLKBUFLR_EN,
+
+ [QPHY_DP_PHY_STATUS] = QSERDES_V4_DP_PHY_STATUS,
++ [QPHY_DP_PHY_VCO_DIV] = QSERDES_V4_DP_PHY_VCO_DIV,
+
+ [QPHY_TX_TX_POL_INV] = QSERDES_V4_TX_TX_POL_INV,
+ [QPHY_TX_TX_DRV_LVL] = QSERDES_V4_TX_TX_DRV_LVL,
+@@ -185,6 +188,7 @@ static const unsigned int qmp_v5_5nm_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
+ [QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN,
+
+ [QPHY_DP_PHY_STATUS] = QSERDES_V5_DP_PHY_STATUS,
++ [QPHY_DP_PHY_VCO_DIV] = QSERDES_V5_DP_PHY_VCO_DIV,
+
+ [QPHY_TX_TX_POL_INV] = QSERDES_V5_5NM_TX_TX_POL_INV,
+ [QPHY_TX_TX_DRV_LVL] = QSERDES_V5_5NM_TX_TX_DRV_LVL,
+@@ -209,6 +213,7 @@ static const unsigned int qmp_v6_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = {
+ [QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN,
+
+ [QPHY_DP_PHY_STATUS] = QSERDES_V6_DP_PHY_STATUS,
++ [QPHY_DP_PHY_VCO_DIV] = QSERDES_V6_DP_PHY_VCO_DIV,
+
+ [QPHY_TX_TX_POL_INV] = QSERDES_V6_TX_TX_POL_INV,
+ [QPHY_TX_TX_DRV_LVL] = QSERDES_V6_TX_TX_DRV_LVL,
+@@ -2211,9 +2216,9 @@ static bool qmp_combo_configure_dp_mode(struct qmp_combo *qmp)
+ writel(val, qmp->dp_dp_phy + QSERDES_DP_PHY_PD_CTL);
+
+ if (reverse)
+- writel(0x4c, qmp->pcs + QSERDES_DP_PHY_MODE);
++ writel(0x4c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
+ else
+- writel(0x5c, qmp->pcs + QSERDES_DP_PHY_MODE);
++ writel(0x5c, qmp->dp_dp_phy + QSERDES_DP_PHY_MODE);
+
+ return reverse;
+ }
+@@ -2223,6 +2228,7 @@ static int qmp_combo_configure_dp_clocks(struct qmp_combo *qmp)
+ const struct phy_configure_opts_dp *dp_opts = &qmp->dp_opts;
+ u32 phy_vco_div;
+ unsigned long pixel_freq;
++ const struct qmp_phy_cfg *cfg = qmp->cfg;
+
+ switch (dp_opts->link_rate) {
+ case 1620:
+@@ -2245,7 +2251,7 @@ static int qmp_combo_configure_dp_clocks(struct qmp_combo *qmp)
+ /* Other link rates aren't supported */
+ return -EINVAL;
+ }
+- writel(phy_vco_div, qmp->dp_dp_phy + QSERDES_V4_DP_PHY_VCO_DIV);
++ writel(phy_vco_div, qmp->dp_dp_phy + cfg->regs[QPHY_DP_PHY_VCO_DIV]);
+
+ clk_set_rate(qmp->dp_link_hw.clk, dp_opts->link_rate * 100000);
+ clk_set_rate(qmp->dp_pixel_hw.clk, pixel_freq);
+diff --git a/drivers/phy/qualcomm/phy-qcom-qmp.h b/drivers/phy/qualcomm/phy-qcom-qmp.h
+index 6923496cbfee2..49ceded9b3cb6 100644
+--- a/drivers/phy/qualcomm/phy-qcom-qmp.h
++++ b/drivers/phy/qualcomm/phy-qcom-qmp.h
+@@ -132,9 +132,11 @@
+ #define QSERDES_V4_DP_PHY_AUX_INTERRUPT_STATUS 0x0d8
+ #define QSERDES_V4_DP_PHY_STATUS 0x0dc
+
++#define QSERDES_V5_DP_PHY_VCO_DIV 0x070
+ #define QSERDES_V5_DP_PHY_STATUS 0x0dc
+
+ /* Only for QMP V6 PHY - DP PHY registers */
++#define QSERDES_V6_DP_PHY_VCO_DIV 0x070
+ #define QSERDES_V6_DP_PHY_AUX_INTERRUPT_STATUS 0x0e0
+ #define QSERDES_V6_DP_PHY_STATUS 0x0e4
+
+diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
+index 5de5e2e97ffa0..26b157f53f3da 100644
+--- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
++++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
+@@ -125,12 +125,15 @@ struct rockchip_combphy_grfcfg {
+ };
+
+ struct rockchip_combphy_cfg {
++ unsigned int num_phys;
++ unsigned int phy_ids[3];
+ const struct rockchip_combphy_grfcfg *grfcfg;
+ int (*combphy_cfg)(struct rockchip_combphy_priv *priv);
+ };
+
+ struct rockchip_combphy_priv {
+ u8 type;
++ int id;
+ void __iomem *mmio;
+ int num_clks;
+ struct clk_bulk_data *clks;
+@@ -320,7 +323,7 @@ static int rockchip_combphy_probe(struct platform_device *pdev)
+ struct rockchip_combphy_priv *priv;
+ const struct rockchip_combphy_cfg *phy_cfg;
+ struct resource *res;
+- int ret;
++ int ret, id;
+
+ phy_cfg = of_device_get_match_data(dev);
+ if (!phy_cfg) {
+@@ -338,6 +341,15 @@ static int rockchip_combphy_probe(struct platform_device *pdev)
+ return ret;
+ }
+
++ /* find the phy-id from the io address */
++ priv->id = -ENODEV;
++ for (id = 0; id < phy_cfg->num_phys; id++) {
++ if (res->start == phy_cfg->phy_ids[id]) {
++ priv->id = id;
++ break;
++ }
++ }
++
+ priv->dev = dev;
+ priv->type = PHY_NONE;
+ priv->cfg = phy_cfg;
+@@ -562,6 +574,12 @@ static const struct rockchip_combphy_grfcfg rk3568_combphy_grfcfgs = {
+ };
+
+ static const struct rockchip_combphy_cfg rk3568_combphy_cfgs = {
++ .num_phys = 3,
++ .phy_ids = {
++ 0xfe820000,
++ 0xfe830000,
++ 0xfe840000,
++ },
+ .grfcfg = &rk3568_combphy_grfcfgs,
+ .combphy_cfg = rk3568_combphy_cfg,
+ };
+@@ -578,8 +596,14 @@ static int rk3588_combphy_cfg(struct rockchip_combphy_priv *priv)
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->con1_for_pcie, true);
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->con2_for_pcie, true);
+ rockchip_combphy_param_write(priv->phy_grf, &cfg->con3_for_pcie, true);
+- rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l0_sel, true);
+- rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l1_sel, true);
++ switch (priv->id) {
++ case 1:
++ rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l0_sel, true);
++ break;
++ case 2:
++ rockchip_combphy_param_write(priv->pipe_grf, &cfg->pipe_pcie1l1_sel, true);
++ break;
++ }
+ break;
+ case PHY_TYPE_USB3:
+ /* Set SSC downward spread spectrum */
+@@ -736,6 +760,12 @@ static const struct rockchip_combphy_grfcfg rk3588_combphy_grfcfgs = {
+ };
+
+ static const struct rockchip_combphy_cfg rk3588_combphy_cfgs = {
++ .num_phys = 3,
++ .phy_ids = {
++ 0xfee00000,
++ 0xfee10000,
++ 0xfee20000,
++ },
+ .grfcfg = &rk3588_combphy_grfcfgs,
+ .combphy_cfg = rk3588_combphy_cfg,
+ };
+diff --git a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
+index 121e5961ce114..9857ee45b89e0 100644
+--- a/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
++++ b/drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
+@@ -40,6 +40,8 @@
+ #define RK3588_BIFURCATION_LANE_0_1 BIT(0)
+ #define RK3588_BIFURCATION_LANE_2_3 BIT(1)
+ #define RK3588_LANE_AGGREGATION BIT(2)
++#define RK3588_PCIE1LN_SEL_EN (GENMASK(1, 0) << 16)
++#define RK3588_PCIE30_PHY_MODE_EN (GENMASK(2, 0) << 16)
+
+ struct rockchip_p3phy_ops;
+
+@@ -132,7 +134,7 @@ static const struct rockchip_p3phy_ops rk3568_ops = {
+ static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
+ {
+ u32 reg = 0;
+- u8 mode = 0;
++ u8 mode = RK3588_LANE_AGGREGATION; /* default */
+ int ret;
+
+ /* Deassert PCIe PMA output clamp mode */
+@@ -140,31 +142,24 @@ static int rockchip_p3phy_rk3588_init(struct rockchip_p3phy_priv *priv)
+
+ /* Set bifurcation if needed */
+ for (int i = 0; i < priv->num_lanes; i++) {
+- if (!priv->lanes[i])
+- mode |= (BIT(i) << 3);
+-
+ if (priv->lanes[i] > 1)
+- mode |= (BIT(i) >> 1);
+- }
+-
+- if (!mode)
+- reg = RK3588_LANE_AGGREGATION;
+- else {
+- if (mode & (BIT(0) | BIT(1)))
+- reg |= RK3588_BIFURCATION_LANE_0_1;
+-
+- if (mode & (BIT(2) | BIT(3)))
+- reg |= RK3588_BIFURCATION_LANE_2_3;
++ mode &= ~RK3588_LANE_AGGREGATION;
++ if (priv->lanes[i] == 3)
++ mode |= RK3588_BIFURCATION_LANE_0_1;
++ if (priv->lanes[i] == 4)
++ mode |= RK3588_BIFURCATION_LANE_2_3;
+ }
+
+- regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0, (0x7<<16) | reg);
++ reg = mode;
++ regmap_write(priv->phy_grf, RK3588_PCIE3PHY_GRF_CMN_CON0,
++ RK3588_PCIE30_PHY_MODE_EN | reg);
+
+ /* Set pcie1ln_sel in PHP_GRF_PCIESEL_CON */
+ if (!IS_ERR(priv->pipe_grf)) {
+- reg = (mode & (BIT(6) | BIT(7))) >> 6;
++ reg = mode & (RK3588_BIFURCATION_LANE_0_1 | RK3588_BIFURCATION_LANE_2_3);
+ if (reg)
+ regmap_write(priv->pipe_grf, PHP_GRF_PCIESEL_CON,
+- (reg << 16) | reg);
++ RK3588_PCIE1LN_SEL_EN | reg);
+ }
+
+ reset_control_deassert(priv->p30phy);
+diff --git a/drivers/phy/ti/phy-tusb1210.c b/drivers/phy/ti/phy-tusb1210.c
+index b4881cb344759..c23eecc7d1800 100644
+--- a/drivers/phy/ti/phy-tusb1210.c
++++ b/drivers/phy/ti/phy-tusb1210.c
+@@ -65,7 +65,6 @@ struct tusb1210 {
+ struct delayed_work chg_det_work;
+ struct notifier_block psy_nb;
+ struct power_supply *psy;
+- struct power_supply *charger;
+ #endif
+ };
+
+@@ -231,19 +230,24 @@ static const char * const tusb1210_chargers[] = {
+
+ static bool tusb1210_get_online(struct tusb1210 *tusb)
+ {
++ struct power_supply *charger = NULL;
+ union power_supply_propval val;
+- int i;
++ bool online = false;
++ int i, ret;
+
+- for (i = 0; i < ARRAY_SIZE(tusb1210_chargers) && !tusb->charger; i++)
+- tusb->charger = power_supply_get_by_name(tusb1210_chargers[i]);
++ for (i = 0; i < ARRAY_SIZE(tusb1210_chargers) && !charger; i++)
++ charger = power_supply_get_by_name(tusb1210_chargers[i]);
+
+- if (!tusb->charger)
++ if (!charger)
+ return false;
+
+- if (power_supply_get_property(tusb->charger, POWER_SUPPLY_PROP_ONLINE, &val))
+- return false;
++ ret = power_supply_get_property(charger, POWER_SUPPLY_PROP_ONLINE, &val);
++ if (ret == 0)
++ online = val.intval;
++
++ power_supply_put(charger);
+
+- return val.intval;
++ return online;
+ }
+
+ static void tusb1210_chg_det_work(struct work_struct *work)
+@@ -467,9 +471,6 @@ static void tusb1210_remove_charger_detect(struct tusb1210 *tusb)
+ cancel_delayed_work_sync(&tusb->chg_det_work);
+ power_supply_unregister(tusb->psy);
+ }
+-
+- if (tusb->charger)
+- power_supply_put(tusb->charger);
+ }
+ #else
+ static void tusb1210_probe_charger_detect(struct tusb1210 *tusb) { }
+diff --git a/drivers/soc/mediatek/mtk-svs.c b/drivers/soc/mediatek/mtk-svs.c
+index c832f5c670bcf..9a91298c12539 100644
+--- a/drivers/soc/mediatek/mtk-svs.c
++++ b/drivers/soc/mediatek/mtk-svs.c
+@@ -1768,6 +1768,7 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
+ const struct svs_bank_pdata *bdata;
+ struct svs_bank *svsb;
+ struct dev_pm_opp *opp;
++ char tz_name_buf[20];
+ unsigned long freq;
+ int count, ret;
+ u32 idx, i;
+@@ -1819,10 +1820,12 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
+ }
+
+ if (!IS_ERR_OR_NULL(bdata->tzone_name)) {
+- svsb->tzd = thermal_zone_get_zone_by_name(bdata->tzone_name);
++ snprintf(tz_name_buf, ARRAY_SIZE(tz_name_buf),
++ "%s-thermal", bdata->tzone_name);
++ svsb->tzd = thermal_zone_get_zone_by_name(tz_name_buf);
+ if (IS_ERR(svsb->tzd)) {
+ dev_err(svsb->dev, "cannot get \"%s\" thermal zone\n",
+- bdata->tzone_name);
++ tz_name_buf);
+ return PTR_ERR(svsb->tzd);
+ }
+ }
+diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c
+index f54bb4dd2d101..42028ace063a4 100644
+--- a/drivers/soundwire/amd_manager.c
++++ b/drivers/soundwire/amd_manager.c
+@@ -148,6 +148,19 @@ static void amd_sdw_set_frameshape(struct amd_sdw_manager *amd_manager)
+ writel(frame_size, amd_manager->mmio + ACP_SW_FRAMESIZE);
+ }
+
++static void amd_sdw_wake_enable(struct amd_sdw_manager *amd_manager, bool enable)
++{
++ u32 wake_ctrl;
++
++ wake_ctrl = readl(amd_manager->mmio + ACP_SW_STATE_CHANGE_STATUS_MASK_8TO11);
++ if (enable)
++ wake_ctrl |= AMD_SDW_WAKE_INTR_MASK;
++ else
++ wake_ctrl &= ~AMD_SDW_WAKE_INTR_MASK;
++
++ writel(wake_ctrl, amd_manager->mmio + ACP_SW_STATE_CHANGE_STATUS_MASK_8TO11);
++}
++
+ static void amd_sdw_ctl_word_prep(u32 *lower_word, u32 *upper_word, struct sdw_msg *msg,
+ int cmd_offset)
+ {
+@@ -1122,6 +1135,7 @@ static int __maybe_unused amd_suspend(struct device *dev)
+ }
+
+ if (amd_manager->power_mode_mask & AMD_SDW_CLK_STOP_MODE) {
++ amd_sdw_wake_enable(amd_manager, false);
+ return amd_sdw_clock_stop(amd_manager);
+ } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) {
+ /*
+@@ -1148,6 +1162,7 @@ static int __maybe_unused amd_suspend_runtime(struct device *dev)
+ return 0;
+ }
+ if (amd_manager->power_mode_mask & AMD_SDW_CLK_STOP_MODE) {
++ amd_sdw_wake_enable(amd_manager, true);
+ return amd_sdw_clock_stop(amd_manager);
+ } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) {
+ ret = amd_sdw_clock_stop(amd_manager);
+diff --git a/drivers/soundwire/amd_manager.h b/drivers/soundwire/amd_manager.h
+index 5f040151a259b..6dcc7a449346e 100644
+--- a/drivers/soundwire/amd_manager.h
++++ b/drivers/soundwire/amd_manager.h
+@@ -152,7 +152,7 @@
+ #define AMD_SDW0_EXT_INTR_MASK 0x200000
+ #define AMD_SDW1_EXT_INTR_MASK 4
+ #define AMD_SDW_IRQ_MASK_0TO7 0x77777777
+-#define AMD_SDW_IRQ_MASK_8TO11 0x000d7777
++#define AMD_SDW_IRQ_MASK_8TO11 0x000c7777
+ #define AMD_SDW_IRQ_ERROR_MASK 0xff
+ #define AMD_SDW_MAX_FREQ_NUM 1
+ #define AMD_SDW0_MAX_TX_PORTS 3
+@@ -190,6 +190,7 @@
+ #define AMD_SDW_CLK_RESUME_REQ 2
+ #define AMD_SDW_CLK_RESUME_DONE 3
+ #define AMD_SDW_WAKE_STAT_MASK BIT(16)
++#define AMD_SDW_WAKE_INTR_MASK BIT(16)
+
+ static u32 amd_sdw_freq_tbl[AMD_SDW_MAX_FREQ_NUM] = {
+ AMD_SDW_DEFAULT_CLK_FREQ,
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 61bd29dd71a2f..b2868217de941 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -3075,6 +3075,46 @@ static void xhci_clear_interrupt_pending(struct xhci_hcd *xhci,
+ }
+ }
+
++static int xhci_handle_events(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
++{
++ int event_loop = 0;
++ u64 temp;
++
++ xhci_clear_interrupt_pending(xhci, ir);
++
++ if (xhci->xhc_state & XHCI_STATE_DYING ||
++ xhci->xhc_state & XHCI_STATE_HALTED) {
++ xhci_dbg(xhci, "xHCI dying, ignoring interrupt. Shouldn't IRQs be disabled?\n");
++
++ /* Clear the event handler busy flag (RW1C) */
++ temp = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
++ xhci_write_64(xhci, temp | ERST_EHB, &ir->ir_set->erst_dequeue);
++ return -ENODEV;
++ }
++
++ while (xhci_handle_event(xhci, ir) > 0) {
++ /*
++ * If half a segment of events have been handled in one go then
++ * update ERDP, and force isoc trbs to interrupt more often
++ */
++ if (event_loop++ > TRBS_PER_SEGMENT / 2) {
++ xhci_update_erst_dequeue(xhci, ir, false);
++
++ if (ir->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN)
++ ir->isoc_bei_interval = ir->isoc_bei_interval / 2;
++
++ event_loop = 0;
++ }
++
++ /* Update SW event ring dequeue pointer */
++ inc_deq(xhci, ir->event_ring);
++ }
++
++ xhci_update_erst_dequeue(xhci, ir, true);
++
++ return 0;
++}
++
+ /*
+ * xHCI spec says we can get an interrupt, and if the HC has an error condition,
+ * we might get bad data out of the event ring. Section 4.10.2.7 has a list of
+@@ -3083,23 +3123,21 @@ static void xhci_clear_interrupt_pending(struct xhci_hcd *xhci,
+ irqreturn_t xhci_irq(struct usb_hcd *hcd)
+ {
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+- struct xhci_interrupter *ir;
+- irqreturn_t ret = IRQ_NONE;
+- u64 temp_64;
++ irqreturn_t ret = IRQ_HANDLED;
+ u32 status;
+- int event_loop = 0;
+
+ spin_lock(&xhci->lock);
+ /* Check if the xHC generated the interrupt, or the irq is shared */
+ status = readl(&xhci->op_regs->status);
+ if (status == ~(u32)0) {
+ xhci_hc_died(xhci);
+- ret = IRQ_HANDLED;
+ goto out;
+ }
+
+- if (!(status & STS_EINT))
++ if (!(status & STS_EINT)) {
++ ret = IRQ_NONE;
+ goto out;
++ }
+
+ if (status & STS_HCE) {
+ xhci_warn(xhci, "WARNING: Host Controller Error\n");
+@@ -3109,7 +3147,6 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
+ if (status & STS_FATAL) {
+ xhci_warn(xhci, "WARNING: Host System Error\n");
+ xhci_halt(xhci);
+- ret = IRQ_HANDLED;
+ goto out;
+ }
+
+@@ -3122,48 +3159,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
+ writel(status, &xhci->op_regs->status);
+
+ /* This is the handler of the primary interrupter */
+- ir = xhci->interrupters[0];
+-
+- xhci_clear_interrupt_pending(xhci, ir);
+-
+- if (xhci->xhc_state & XHCI_STATE_DYING ||
+- xhci->xhc_state & XHCI_STATE_HALTED) {
+- xhci_dbg(xhci, "xHCI dying, ignoring interrupt. "
+- "Shouldn't IRQs be disabled?\n");
+- /* Clear the event handler busy flag (RW1C);
+- * the event ring should be empty.
+- */
+- temp_64 = xhci_read_64(xhci, &ir->ir_set->erst_dequeue);
+- xhci_write_64(xhci, temp_64 | ERST_EHB,
+- &ir->ir_set->erst_dequeue);
+- ret = IRQ_HANDLED;
+- goto out;
+- }
+-
+- /* FIXME this should be a delayed service routine
+- * that clears the EHB.
+- */
+- while (xhci_handle_event(xhci, ir) > 0) {
+- /*
+- * If half a segment of events have been handled in one go then
+- * update ERDP, and force isoc trbs to interrupt more often
+- */
+- if (event_loop++ > TRBS_PER_SEGMENT / 2) {
+- xhci_update_erst_dequeue(xhci, ir, false);
+-
+- if (ir->isoc_bei_interval > AVOID_BEI_INTERVAL_MIN)
+- ir->isoc_bei_interval = ir->isoc_bei_interval / 2;
+-
+- event_loop = 0;
+- }
+-
+- /* Update SW event ring dequeue pointer */
+- inc_deq(xhci, ir->event_ring);
+- }
+-
+- xhci_update_erst_dequeue(xhci, ir, true);
+- ret = IRQ_HANDLED;
+-
++ xhci_handle_events(xhci, xhci->interrupters[0]);
+ out:
+ spin_unlock(&xhci->lock);
+
+diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c
+index dae96c9f61cf8..806ecd32219b6 100644
+--- a/drivers/video/fbdev/core/fb_defio.c
++++ b/drivers/video/fbdev/core/fb_defio.c
+@@ -196,7 +196,7 @@ static vm_fault_t fb_deferred_io_track_page(struct fb_info *info, unsigned long
+ */
+ static vm_fault_t fb_deferred_io_page_mkwrite(struct fb_info *info, struct vm_fault *vmf)
+ {
+- unsigned long offset = vmf->address - vmf->vma->vm_start;
++ unsigned long offset = vmf->pgoff << PAGE_SHIFT;
+ struct page *page = vmf->page;
+
+ file_update_time(vmf->vma->vm_file);
+diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
+index beed7e459dabd..fc0930dd922bc 100644
+--- a/fs/btrfs/backref.c
++++ b/fs/btrfs/backref.c
+@@ -2773,20 +2773,14 @@ struct btrfs_data_container *init_data_container(u32 total_bytes)
+ size_t alloc_bytes;
+
+ alloc_bytes = max_t(size_t, total_bytes, sizeof(*data));
+- data = kvmalloc(alloc_bytes, GFP_KERNEL);
++ data = kvzalloc(alloc_bytes, GFP_KERNEL);
+ if (!data)
+ return ERR_PTR(-ENOMEM);
+
+- if (total_bytes >= sizeof(*data)) {
++ if (total_bytes >= sizeof(*data))
+ data->bytes_left = total_bytes - sizeof(*data);
+- data->bytes_missing = 0;
+- } else {
++ else
+ data->bytes_missing = sizeof(*data) - total_bytes;
+- data->bytes_left = 0;
+- }
+-
+- data->elem_cnt = 0;
+- data->elem_missed = 0;
+
+ return data;
+ }
+diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
+index 76378382dd8c4..54e111b5faa75 100644
+--- a/fs/btrfs/extent_map.c
++++ b/fs/btrfs/extent_map.c
+@@ -818,7 +818,7 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end,
+ split->block_len = em->block_len;
+ split->orig_start = em->orig_start;
+ } else {
+- const u64 diff = start + len - em->start;
++ const u64 diff = end - em->start;
+
+ split->block_len = split->len;
+ split->block_start += diff;
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 6e2715e3f3aa0..b28bb1c93dcb5 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -1144,13 +1144,13 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
+ 0, *alloc_hint, &ins, 1, 1);
+ if (ret) {
+ /*
+- * Here we used to try again by going back to non-compressed
+- * path for ENOSPC. But we can't reserve space even for
+- * compressed size, how could it work for uncompressed size
+- * which requires larger size? So here we directly go error
+- * path.
++ * We can't reserve contiguous space for the compressed size.
++ * Unlikely, but it's possible that we could have enough
++ * non-contiguous space for the uncompressed size instead. So
++ * fall back to uncompressed.
+ */
+- goto out_free;
++ submit_uncompressed_range(inode, async_extent, locked_page);
++ goto done;
+ }
+
+ /* Here we're doing allocation and writeback of the compressed pages */
+@@ -1202,7 +1202,6 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
+ out_free_reserve:
+ btrfs_dec_block_group_reservations(fs_info, ins.objectid);
+ btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 1);
+-out_free:
+ mapping_set_error(inode->vfs_inode.i_mapping, -EIO);
+ extent_clear_unlock_delalloc(inode, start, end,
+ NULL, EXTENT_LOCKED | EXTENT_DELALLOC |
+diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
+index 9e87a6adc580b..d89d5c0a8cd2d 100644
+--- a/fs/btrfs/scrub.c
++++ b/fs/btrfs/scrub.c
+@@ -1012,6 +1012,7 @@ static void scrub_stripe_read_repair_worker(struct work_struct *work)
+ struct btrfs_fs_info *fs_info = sctx->fs_info;
+ int num_copies = btrfs_num_copies(fs_info, stripe->bg->start,
+ stripe->bg->length);
++ unsigned long repaired;
+ int mirror;
+ int i;
+
+@@ -1078,16 +1079,15 @@ static void scrub_stripe_read_repair_worker(struct work_struct *work)
+ * Submit the repaired sectors. For zoned case, we cannot do repair
+ * in-place, but queue the bg to be relocated.
+ */
+- if (btrfs_is_zoned(fs_info)) {
+- if (!bitmap_empty(&stripe->error_bitmap, stripe->nr_sectors))
++ bitmap_andnot(&repaired, &stripe->init_error_bitmap, &stripe->error_bitmap,
++ stripe->nr_sectors);
++ if (!sctx->readonly && !bitmap_empty(&repaired, stripe->nr_sectors)) {
++ if (btrfs_is_zoned(fs_info)) {
+ btrfs_repair_one_zone(fs_info, sctx->stripes[0].bg->start);
+- } else if (!sctx->readonly) {
+- unsigned long repaired;
+-
+- bitmap_andnot(&repaired, &stripe->init_error_bitmap,
+- &stripe->error_bitmap, stripe->nr_sectors);
+- scrub_write_sectors(sctx, stripe, repaired, false);
+- wait_scrub_stripe_io(stripe);
++ } else {
++ scrub_write_sectors(sctx, stripe, repaired, false);
++ wait_scrub_stripe_io(stripe);
++ }
+ }
+
+ scrub_stripe_report_errors(sctx, stripe);
+diff --git a/fs/btrfs/tests/extent-map-tests.c b/fs/btrfs/tests/extent-map-tests.c
+index 253cce7ffecfe..47b5d301038ee 100644
+--- a/fs/btrfs/tests/extent-map-tests.c
++++ b/fs/btrfs/tests/extent-map-tests.c
+@@ -847,6 +847,11 @@ static int test_case_7(struct btrfs_fs_info *fs_info)
+ goto out;
+ }
+
++ if (em->block_start != SZ_32K + SZ_4K) {
++ test_err("em->block_start is %llu, expected 36K", em->block_start);
++ goto out;
++ }
++
+ free_extent_map(em);
+
+ read_lock(&em_tree->lock);
+diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c
+index 9a0d32e4b422a..267b622d923b1 100644
+--- a/fs/netfs/buffered_write.c
++++ b/fs/netfs/buffered_write.c
+@@ -164,7 +164,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
+ enum netfs_how_to_modify howto;
+ enum netfs_folio_trace trace;
+ unsigned int bdp_flags = (iocb->ki_flags & IOCB_SYNC) ? 0: BDP_ASYNC;
+- ssize_t written = 0, ret;
++ ssize_t written = 0, ret, ret2;
+ loff_t i_size, pos = iocb->ki_pos, from, to;
+ size_t max_chunk = PAGE_SIZE << MAX_PAGECACHE_ORDER;
+ bool maybe_trouble = false;
+@@ -172,15 +172,14 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
+ if (unlikely(test_bit(NETFS_ICTX_WRITETHROUGH, &ctx->flags) ||
+ iocb->ki_flags & (IOCB_DSYNC | IOCB_SYNC))
+ ) {
+- if (pos < i_size_read(inode)) {
+- ret = filemap_write_and_wait_range(mapping, pos, pos + iter->count);
+- if (ret < 0) {
+- goto out;
+- }
+- }
+-
+ wbc_attach_fdatawrite_inode(&wbc, mapping->host);
+
++ ret = filemap_write_and_wait_range(mapping, pos, pos + iter->count);
++ if (ret < 0) {
++ wbc_detach_inode(&wbc);
++ goto out;
++ }
++
+ wreq = netfs_begin_writethrough(iocb, iter->count);
+ if (IS_ERR(wreq)) {
+ wbc_detach_inode(&wbc);
+@@ -395,10 +394,12 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct iov_iter *iter,
+
+ out:
+ if (unlikely(wreq)) {
+- ret = netfs_end_writethrough(wreq, iocb);
++ ret2 = netfs_end_writethrough(wreq, iocb);
+ wbc_detach_inode(&wbc);
+- if (ret == -EIOCBQUEUED)
+- return ret;
++ if (ret2 == -EIOCBQUEUED)
++ return ret2;
++ if (ret == 0)
++ ret = ret2;
+ }
+
+ iocb->ki_pos += written;
+diff --git a/fs/proc/page.c b/fs/proc/page.c
+index 195b077c0facb..9223856c934b4 100644
+--- a/fs/proc/page.c
++++ b/fs/proc/page.c
+@@ -67,7 +67,7 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf,
+ */
+ ppage = pfn_to_online_page(pfn);
+
+- if (!ppage || PageSlab(ppage) || page_has_type(ppage))
++ if (!ppage)
+ pcount = 0;
+ else
+ pcount = page_mapcount(ppage);
+@@ -124,11 +124,8 @@ u64 stable_page_flags(struct page *page)
+
+ /*
+ * pseudo flags for the well known (anonymous) memory mapped pages
+- *
+- * Note that page->_mapcount is overloaded in SLAB, so the
+- * simple test in page_mapped() is not enough.
+ */
+- if (!PageSlab(page) && page_mapped(page))
++ if (page_mapped(page))
+ u |= 1 << KPF_MMAP;
+ if (PageAnon(page))
+ u |= 1 << KPF_ANON;
+diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
+index 501bfd3afdc64..81fe60815885c 100644
+--- a/fs/smb/client/cifsfs.c
++++ b/fs/smb/client/cifsfs.c
+@@ -393,6 +393,7 @@ cifs_alloc_inode(struct super_block *sb)
+ * server, can not assume caching of file data or metadata.
+ */
+ cifs_set_oplock_level(cifs_inode, 0);
++ cifs_inode->lease_granted = false;
+ cifs_inode->flags = 0;
+ spin_lock_init(&cifs_inode->writers_lock);
+ cifs_inode->writers = 0;
+diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
+index 844afda090d05..0c3311de5dc0a 100644
+--- a/fs/smb/client/cifsglob.h
++++ b/fs/smb/client/cifsglob.h
+@@ -1261,7 +1261,9 @@ struct cifs_tcon {
+ __u32 max_cached_dirs;
+ #ifdef CONFIG_CIFS_FSCACHE
+ u64 resource_id; /* server resource id */
++ bool fscache_acquired; /* T if we've tried acquiring a cookie */
+ struct fscache_volume *fscache; /* cookie for share */
++ struct mutex fscache_lock; /* Prevent regetting a cookie */
+ #endif
+ struct list_head pending_opens; /* list of incomplete opens */
+ struct cached_fids *cfids;
+diff --git a/fs/smb/client/cifspdu.h b/fs/smb/client/cifspdu.h
+index c0513fbb8a59d..c46d418c1c0c3 100644
+--- a/fs/smb/client/cifspdu.h
++++ b/fs/smb/client/cifspdu.h
+@@ -882,7 +882,7 @@ typedef struct smb_com_open_rsp {
+ __u8 OplockLevel;
+ __u16 Fid;
+ __le32 CreateAction;
+- struct_group(common_attributes,
++ struct_group_attr(common_attributes, __packed,
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+@@ -2266,7 +2266,7 @@ typedef struct {
+ /* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */
+ /******************************************************************************/
+ typedef struct { /* data block encoding of response to level 263 QPathInfo */
+- struct_group(common_attributes,
++ struct_group_attr(common_attributes, __packed,
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
+index d9fe17b2ba375..775b0ca605892 100644
+--- a/fs/smb/client/fs_context.c
++++ b/fs/smb/client/fs_context.c
+@@ -715,6 +715,16 @@ static int smb3_fs_context_validate(struct fs_context *fc)
+ /* set the port that we got earlier */
+ cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port);
+
++ if (ctx->uid_specified && !ctx->forceuid_specified) {
++ ctx->override_uid = 1;
++ pr_notice("enabling forceuid mount option implicitly because uid= option is specified\n");
++ }
++
++ if (ctx->gid_specified && !ctx->forcegid_specified) {
++ ctx->override_gid = 1;
++ pr_notice("enabling forcegid mount option implicitly because gid= option is specified\n");
++ }
++
+ if (ctx->override_uid && !ctx->uid_specified) {
+ ctx->override_uid = 0;
+ pr_notice("ignoring forceuid mount option specified with no uid= option\n");
+@@ -984,12 +994,14 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
+ ctx->override_uid = 0;
+ else
+ ctx->override_uid = 1;
++ ctx->forceuid_specified = true;
+ break;
+ case Opt_forcegid:
+ if (result.negated)
+ ctx->override_gid = 0;
+ else
+ ctx->override_gid = 1;
++ ctx->forcegid_specified = true;
+ break;
+ case Opt_perm:
+ if (result.negated)
+diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h
+index b3d51b345eaef..61776572b8d2d 100644
+--- a/fs/smb/client/fs_context.h
++++ b/fs/smb/client/fs_context.h
+@@ -156,6 +156,8 @@ enum cifs_param {
+ };
+
+ struct smb3_fs_context {
++ bool forceuid_specified;
++ bool forcegid_specified;
+ bool uid_specified;
+ bool cruid_specified;
+ bool gid_specified;
+diff --git a/fs/smb/client/fscache.c b/fs/smb/client/fscache.c
+index 340efce8f0529..113bde8f1e613 100644
+--- a/fs/smb/client/fscache.c
++++ b/fs/smb/client/fscache.c
+@@ -43,12 +43,23 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
+ char *key;
+ int ret = -ENOMEM;
+
++ if (tcon->fscache_acquired)
++ return 0;
++
++ mutex_lock(&tcon->fscache_lock);
++ if (tcon->fscache_acquired) {
++ mutex_unlock(&tcon->fscache_lock);
++ return 0;
++ }
++ tcon->fscache_acquired = true;
++
+ tcon->fscache = NULL;
+ switch (sa->sa_family) {
+ case AF_INET:
+ case AF_INET6:
+ break;
+ default:
++ mutex_unlock(&tcon->fscache_lock);
+ cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family);
+ return -EINVAL;
+ }
+@@ -57,6 +68,7 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
+
+ sharename = extract_sharename(tcon->tree_name);
+ if (IS_ERR(sharename)) {
++ mutex_unlock(&tcon->fscache_lock);
+ cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__);
+ return PTR_ERR(sharename);
+ }
+@@ -90,6 +102,7 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
+ kfree(key);
+ out:
+ kfree(sharename);
++ mutex_unlock(&tcon->fscache_lock);
+ return ret;
+ }
+
+diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c
+index 74627d647818a..0d13db80e67c9 100644
+--- a/fs/smb/client/misc.c
++++ b/fs/smb/client/misc.c
+@@ -141,6 +141,9 @@ tcon_info_alloc(bool dir_leases_enabled)
+ atomic_set(&ret_buf->num_local_opens, 0);
+ atomic_set(&ret_buf->num_remote_opens, 0);
+ ret_buf->stats_from_time = ktime_get_real_seconds();
++#ifdef CONFIG_CIFS_FSCACHE
++ mutex_init(&ret_buf->fscache_lock);
++#endif
+
+ return ret_buf;
+ }
+diff --git a/fs/smb/client/smb2pdu.h b/fs/smb/client/smb2pdu.h
+index db08194484e06..b00f707bddfcc 100644
+--- a/fs/smb/client/smb2pdu.h
++++ b/fs/smb/client/smb2pdu.h
+@@ -319,7 +319,7 @@ struct smb2_file_reparse_point_info {
+ } __packed;
+
+ struct smb2_file_network_open_info {
+- struct_group(network_open_info,
++ struct_group_attr(network_open_info, __packed,
+ __le64 CreationTime;
+ __le64 LastAccessTime;
+ __le64 LastWriteTime;
+diff --git a/fs/smb/client/transport.c b/fs/smb/client/transport.c
+index 994d701934329..ddf1a3aafee5c 100644
+--- a/fs/smb/client/transport.c
++++ b/fs/smb/client/transport.c
+@@ -909,12 +909,15 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
+ list_del_init(&mid->qhead);
+ mid->mid_flags |= MID_DELETED;
+ }
++ spin_unlock(&server->mid_lock);
+ cifs_server_dbg(VFS, "%s: invalid mid state mid=%llu state=%d\n",
+ __func__, mid->mid, mid->mid_state);
+ rc = -EIO;
++ goto sync_mid_done;
+ }
+ spin_unlock(&server->mid_lock);
+
++sync_mid_done:
+ release_mid(mid);
+ return rc;
+ }
+@@ -1057,9 +1060,11 @@ struct TCP_Server_Info *cifs_pick_channel(struct cifs_ses *ses)
+ index = (uint)atomic_inc_return(&ses->chan_seq);
+ index %= ses->chan_count;
+ }
++
++ server = ses->chans[index].server;
+ spin_unlock(&ses->chan_lock);
+
+- return ses->chans[index].server;
++ return server;
+ }
+
+ int
+diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
+index 369505447acd8..2ebec3984cd44 100644
+--- a/include/drm/drm_gem.h
++++ b/include/drm/drm_gem.h
+@@ -553,6 +553,19 @@ unsigned long drm_gem_lru_scan(struct drm_gem_lru *lru,
+
+ int drm_gem_evict(struct drm_gem_object *obj);
+
++/**
++ * drm_gem_object_is_shared_for_memory_stats - helper for shared memory stats
++ *
++ * This helper should only be used for fdinfo shared memory stats to determine
++ * if a GEM object is shared.
++ *
++ * @obj: obj in question
++ */
++static inline bool drm_gem_object_is_shared_for_memory_stats(struct drm_gem_object *obj)
++{
++ return (obj->handle_count > 1) || obj->dma_buf;
++}
++
+ #ifdef CONFIG_LOCKDEP
+ /**
+ * drm_gem_gpuva_set_lock() - Set the lock protecting accesses to the gpuva list.
+diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
+index 224645f17c333..297231854ada5 100644
+--- a/include/linux/etherdevice.h
++++ b/include/linux/etherdevice.h
+@@ -607,6 +607,31 @@ static inline void eth_hw_addr_gen(struct net_device *dev, const u8 *base_addr,
+ eth_hw_addr_set(dev, addr);
+ }
+
++/**
++ * eth_skb_pkt_type - Assign packet type if destination address does not match
++ * @skb: Assigned a packet type if address does not match @dev address
++ * @dev: Network device used to compare packet address against
++ *
++ * If the destination MAC address of the packet does not match the network
++ * device address, assign an appropriate packet type.
++ */
++static inline void eth_skb_pkt_type(struct sk_buff *skb,
++ const struct net_device *dev)
++{
++ const struct ethhdr *eth = eth_hdr(skb);
++
++ if (unlikely(!ether_addr_equal_64bits(eth->h_dest, dev->dev_addr))) {
++ if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) {
++ if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
++ skb->pkt_type = PACKET_BROADCAST;
++ else
++ skb->pkt_type = PACKET_MULTICAST;
++ } else {
++ skb->pkt_type = PACKET_OTHERHOST;
++ }
++ }
++}
++
+ /**
+ * eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame
+ * @skb: Buffer to pad
+diff --git a/include/linux/firmware/qcom/qcom_qseecom.h b/include/linux/firmware/qcom/qcom_qseecom.h
+index 5c28298a98bec..366243ee96096 100644
+--- a/include/linux/firmware/qcom/qcom_qseecom.h
++++ b/include/linux/firmware/qcom/qcom_qseecom.h
+@@ -10,6 +10,7 @@
+ #define __QCOM_QSEECOM_H
+
+ #include <linux/auxiliary_bus.h>
++#include <linux/dma-mapping.h>
+ #include <linux/types.h>
+
+ #include <linux/firmware/qcom/qcom_scm.h>
+@@ -24,12 +25,57 @@ struct qseecom_client {
+ u32 app_id;
+ };
+
++/**
++ * qseecom_scm_dev() - Get the SCM device associated with the QSEECOM client.
++ * @client: The QSEECOM client device.
++ *
++ * Returns the SCM device under which the provided QSEECOM client device
++ * operates. This function is intended to be used for DMA allocations.
++ */
++static inline struct device *qseecom_scm_dev(struct qseecom_client *client)
++{
++ return client->aux_dev.dev.parent->parent;
++}
++
++/**
++ * qseecom_dma_alloc() - Allocate DMA memory for a QSEECOM client.
++ * @client: The QSEECOM client to allocate the memory for.
++ * @size: The number of bytes to allocate.
++ * @dma_handle: Pointer to where the DMA address should be stored.
++ * @gfp: Allocation flags.
++ *
++ * Wrapper function for dma_alloc_coherent(), allocating DMA memory usable for
++ * TZ/QSEECOM communication. Refer to dma_alloc_coherent() for details.
++ */
++static inline void *qseecom_dma_alloc(struct qseecom_client *client, size_t size,
++ dma_addr_t *dma_handle, gfp_t gfp)
++{
++ return dma_alloc_coherent(qseecom_scm_dev(client), size, dma_handle, gfp);
++}
++
++/**
++ * dma_free_coherent() - Free QSEECOM DMA memory.
++ * @client: The QSEECOM client for which the memory has been allocated.
++ * @size: The number of bytes allocated.
++ * @cpu_addr: Virtual memory address to free.
++ * @dma_handle: DMA memory address to free.
++ *
++ * Wrapper function for dma_free_coherent(), freeing memory previously
++ * allocated with qseecom_dma_alloc(). Refer to dma_free_coherent() for
++ * details.
++ */
++static inline void qseecom_dma_free(struct qseecom_client *client, size_t size,
++ void *cpu_addr, dma_addr_t dma_handle)
++{
++ return dma_free_coherent(qseecom_scm_dev(client), size, cpu_addr, dma_handle);
++}
++
+ /**
+ * qcom_qseecom_app_send() - Send to and receive data from a given QSEE app.
+ * @client: The QSEECOM client associated with the target app.
+- * @req: Request buffer sent to the app (must be DMA-mappable).
++ * @req: DMA address of the request buffer sent to the app.
+ * @req_size: Size of the request buffer.
+- * @rsp: Response buffer, written to by the app (must be DMA-mappable).
++ * @rsp: DMA address of the response buffer, written to by the app.
+ * @rsp_size: Size of the response buffer.
+ *
+ * Sends a request to the QSEE app associated with the given client and read
+@@ -43,8 +89,9 @@ struct qseecom_client {
+ *
+ * Return: Zero on success, nonzero on failure.
+ */
+-static inline int qcom_qseecom_app_send(struct qseecom_client *client, void *req, size_t req_size,
+- void *rsp, size_t rsp_size)
++static inline int qcom_qseecom_app_send(struct qseecom_client *client,
++ dma_addr_t req, size_t req_size,
++ dma_addr_t rsp, size_t rsp_size)
+ {
+ return qcom_scm_qseecom_app_send(client->app_id, req, req_size, rsp, rsp_size);
+ }
+diff --git a/include/linux/firmware/qcom/qcom_scm.h b/include/linux/firmware/qcom/qcom_scm.h
+index ccaf288460546..aaa19f93ac430 100644
+--- a/include/linux/firmware/qcom/qcom_scm.h
++++ b/include/linux/firmware/qcom/qcom_scm.h
+@@ -118,8 +118,8 @@ bool qcom_scm_lmh_dcvsh_available(void);
+ #ifdef CONFIG_QCOM_QSEECOM
+
+ int qcom_scm_qseecom_app_get_id(const char *app_name, u32 *app_id);
+-int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp,
+- size_t rsp_size);
++int qcom_scm_qseecom_app_send(u32 app_id, dma_addr_t req, size_t req_size,
++ dma_addr_t rsp, size_t rsp_size);
+
+ #else /* CONFIG_QCOM_QSEECOM */
+
+@@ -128,9 +128,9 @@ static inline int qcom_scm_qseecom_app_get_id(const char *app_name, u32 *app_id)
+ return -EINVAL;
+ }
+
+-static inline int qcom_scm_qseecom_app_send(u32 app_id, void *req,
+- size_t req_size, void *rsp,
+- size_t rsp_size)
++static inline int qcom_scm_qseecom_app_send(u32 app_id,
++ dma_addr_t req, size_t req_size,
++ dma_addr_t rsp, size_t rsp_size)
+ {
+ return -EINVAL;
+ }
+diff --git a/include/linux/mm.h b/include/linux/mm.h
+index f5a97dec51694..adbab01e2e90a 100644
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -1204,14 +1204,16 @@ static inline void page_mapcount_reset(struct page *page)
+ * a large folio, it includes the number of times this page is mapped
+ * as part of that folio.
+ *
+- * The result is undefined for pages which cannot be mapped into userspace.
+- * For example SLAB or special types of pages. See function page_has_type().
+- * They use this field in struct page differently.
++ * Will report 0 for pages which cannot be mapped into userspace, eg
++ * slab, page tables and similar.
+ */
+ static inline int page_mapcount(struct page *page)
+ {
+ int mapcount = atomic_read(&page->_mapcount) + 1;
+
++ /* Handle page_has_type() pages */
++ if (mapcount < 0)
++ mapcount = 0;
+ if (unlikely(PageCompound(page)))
+ mapcount += folio_entire_mapcount(page_folio(page));
+
+diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
+index 735cddc13d20e..68e9973cd62d9 100644
+--- a/include/linux/page-flags.h
++++ b/include/linux/page-flags.h
+@@ -190,7 +190,6 @@ enum pageflags {
+
+ /* At least one page in this folio has the hwpoison flag set */
+ PG_has_hwpoisoned = PG_error,
+- PG_hugetlb = PG_active,
+ PG_large_rmappable = PG_workingset, /* anon or file-backed */
+ };
+
+@@ -432,30 +431,51 @@ static __always_inline int TestClearPage##uname(struct page *page) \
+ TESTSETFLAG(uname, lname, policy) \
+ TESTCLEARFLAG(uname, lname, policy)
+
++#define FOLIO_TEST_FLAG_FALSE(name) \
++static inline bool folio_test_##name(const struct folio *folio) \
++{ return false; }
++#define FOLIO_SET_FLAG_NOOP(name) \
++static inline void folio_set_##name(struct folio *folio) { }
++#define FOLIO_CLEAR_FLAG_NOOP(name) \
++static inline void folio_clear_##name(struct folio *folio) { }
++#define __FOLIO_SET_FLAG_NOOP(name) \
++static inline void __folio_set_##name(struct folio *folio) { }
++#define __FOLIO_CLEAR_FLAG_NOOP(name) \
++static inline void __folio_clear_##name(struct folio *folio) { }
++#define FOLIO_TEST_SET_FLAG_FALSE(name) \
++static inline bool folio_test_set_##name(struct folio *folio) \
++{ return false; }
++#define FOLIO_TEST_CLEAR_FLAG_FALSE(name) \
++static inline bool folio_test_clear_##name(struct folio *folio) \
++{ return false; }
++
++#define FOLIO_FLAG_FALSE(name) \
++FOLIO_TEST_FLAG_FALSE(name) \
++FOLIO_SET_FLAG_NOOP(name) \
++FOLIO_CLEAR_FLAG_NOOP(name)
++
+ #define TESTPAGEFLAG_FALSE(uname, lname) \
+-static inline bool folio_test_##lname(const struct folio *folio) { return false; } \
++FOLIO_TEST_FLAG_FALSE(lname) \
+ static inline int Page##uname(const struct page *page) { return 0; }
+
+ #define SETPAGEFLAG_NOOP(uname, lname) \
+-static inline void folio_set_##lname(struct folio *folio) { } \
++FOLIO_SET_FLAG_NOOP(lname) \
+ static inline void SetPage##uname(struct page *page) { }
+
+ #define CLEARPAGEFLAG_NOOP(uname, lname) \
+-static inline void folio_clear_##lname(struct folio *folio) { } \
++FOLIO_CLEAR_FLAG_NOOP(lname) \
+ static inline void ClearPage##uname(struct page *page) { }
+
+ #define __CLEARPAGEFLAG_NOOP(uname, lname) \
+-static inline void __folio_clear_##lname(struct folio *folio) { } \
++__FOLIO_CLEAR_FLAG_NOOP(lname) \
+ static inline void __ClearPage##uname(struct page *page) { }
+
+ #define TESTSETFLAG_FALSE(uname, lname) \
+-static inline bool folio_test_set_##lname(struct folio *folio) \
+-{ return 0; } \
++FOLIO_TEST_SET_FLAG_FALSE(lname) \
+ static inline int TestSetPage##uname(struct page *page) { return 0; }
+
+ #define TESTCLEARFLAG_FALSE(uname, lname) \
+-static inline bool folio_test_clear_##lname(struct folio *folio) \
+-{ return 0; } \
++FOLIO_TEST_CLEAR_FLAG_FALSE(lname) \
+ static inline int TestClearPage##uname(struct page *page) { return 0; }
+
+ #define PAGEFLAG_FALSE(uname, lname) TESTPAGEFLAG_FALSE(uname, lname) \
+@@ -829,29 +849,6 @@ TESTPAGEFLAG_FALSE(LargeRmappable, large_rmappable)
+
+ #define PG_head_mask ((1UL << PG_head))
+
+-#ifdef CONFIG_HUGETLB_PAGE
+-int PageHuge(struct page *page);
+-SETPAGEFLAG(HugeTLB, hugetlb, PF_SECOND)
+-CLEARPAGEFLAG(HugeTLB, hugetlb, PF_SECOND)
+-
+-/**
+- * folio_test_hugetlb - Determine if the folio belongs to hugetlbfs
+- * @folio: The folio to test.
+- *
+- * Context: Any context. Caller should have a reference on the folio to
+- * prevent it from being turned into a tail page.
+- * Return: True for hugetlbfs folios, false for anon folios or folios
+- * belonging to other filesystems.
+- */
+-static inline bool folio_test_hugetlb(struct folio *folio)
+-{
+- return folio_test_large(folio) &&
+- test_bit(PG_hugetlb, folio_flags(folio, 1));
+-}
+-#else
+-TESTPAGEFLAG_FALSE(Huge, hugetlb)
+-#endif
+-
+ #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ /*
+ * PageHuge() only returns true for hugetlbfs pages, but not for
+@@ -907,34 +904,23 @@ PAGEFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)
+ TESTSCFLAG_FALSE(HasHWPoisoned, has_hwpoisoned)
+ #endif
+
+-/*
+- * Check if a page is currently marked HWPoisoned. Note that this check is
+- * best effort only and inherently racy: there is no way to synchronize with
+- * failing hardware.
+- */
+-static inline bool is_page_hwpoison(struct page *page)
+-{
+- if (PageHWPoison(page))
+- return true;
+- return PageHuge(page) && PageHWPoison(compound_head(page));
+-}
+-
+ /*
+ * For pages that are never mapped to userspace (and aren't PageSlab),
+ * page_type may be used. Because it is initialised to -1, we invert the
+ * sense of the bit, so __SetPageFoo *clears* the bit used for PageFoo, and
+ * __ClearPageFoo *sets* the bit used for PageFoo. We reserve a few high and
+- * low bits so that an underflow or overflow of page_mapcount() won't be
++ * low bits so that an underflow or overflow of _mapcount won't be
+ * mistaken for a page type value.
+ */
+
+ #define PAGE_TYPE_BASE 0xf0000000
+-/* Reserve 0x0000007f to catch underflows of page_mapcount */
++/* Reserve 0x0000007f to catch underflows of _mapcount */
+ #define PAGE_MAPCOUNT_RESERVE -128
+ #define PG_buddy 0x00000080
+ #define PG_offline 0x00000100
+ #define PG_table 0x00000200
+ #define PG_guard 0x00000400
++#define PG_hugetlb 0x00000800
+
+ #define PageType(page, flag) \
+ ((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE)
+@@ -951,35 +937,38 @@ static inline int page_has_type(struct page *page)
+ return page_type_has_type(page->page_type);
+ }
+
++#define FOLIO_TYPE_OPS(lname, fname) \
++static __always_inline bool folio_test_##fname(const struct folio *folio)\
++{ \
++ return folio_test_type(folio, PG_##lname); \
++} \
++static __always_inline void __folio_set_##fname(struct folio *folio) \
++{ \
++ VM_BUG_ON_FOLIO(!folio_test_type(folio, 0), folio); \
++ folio->page.page_type &= ~PG_##lname; \
++} \
++static __always_inline void __folio_clear_##fname(struct folio *folio) \
++{ \
++ VM_BUG_ON_FOLIO(!folio_test_##fname(folio), folio); \
++ folio->page.page_type |= PG_##lname; \
++}
++
+ #define PAGE_TYPE_OPS(uname, lname, fname) \
++FOLIO_TYPE_OPS(lname, fname) \
+ static __always_inline int Page##uname(const struct page *page) \
+ { \
+ return PageType(page, PG_##lname); \
+ } \
+-static __always_inline int folio_test_##fname(const struct folio *folio)\
+-{ \
+- return folio_test_type(folio, PG_##lname); \
+-} \
+ static __always_inline void __SetPage##uname(struct page *page) \
+ { \
+ VM_BUG_ON_PAGE(!PageType(page, 0), page); \
+ page->page_type &= ~PG_##lname; \
+ } \
+-static __always_inline void __folio_set_##fname(struct folio *folio) \
+-{ \
+- VM_BUG_ON_FOLIO(!folio_test_type(folio, 0), folio); \
+- folio->page.page_type &= ~PG_##lname; \
+-} \
+ static __always_inline void __ClearPage##uname(struct page *page) \
+ { \
+ VM_BUG_ON_PAGE(!Page##uname(page), page); \
+ page->page_type |= PG_##lname; \
+-} \
+-static __always_inline void __folio_clear_##fname(struct folio *folio) \
+-{ \
+- VM_BUG_ON_FOLIO(!folio_test_##fname(folio), folio); \
+- folio->page.page_type |= PG_##lname; \
+-} \
++}
+
+ /*
+ * PageBuddy() indicates that the page is free and in the buddy system
+@@ -1026,6 +1015,37 @@ PAGE_TYPE_OPS(Table, table, pgtable)
+ */
+ PAGE_TYPE_OPS(Guard, guard, guard)
+
++#ifdef CONFIG_HUGETLB_PAGE
++FOLIO_TYPE_OPS(hugetlb, hugetlb)
++#else
++FOLIO_TEST_FLAG_FALSE(hugetlb)
++#endif
++
++/**
++ * PageHuge - Determine if the page belongs to hugetlbfs
++ * @page: The page to test.
++ *
++ * Context: Any context.
++ * Return: True for hugetlbfs pages, false for anon pages or pages
++ * belonging to other filesystems.
++ */
++static inline bool PageHuge(const struct page *page)
++{
++ return folio_test_hugetlb(page_folio(page));
++}
++
++/*
++ * Check if a page is currently marked HWPoisoned. Note that this check is
++ * best effort only and inherently racy: there is no way to synchronize with
++ * failing hardware.
++ */
++static inline bool is_page_hwpoison(struct page *page)
++{
++ if (PageHWPoison(page))
++ return true;
++ return PageHuge(page) && PageHWPoison(compound_head(page));
++}
++
+ extern bool is_free_buddy_page(struct page *page);
+
+ PAGEFLAG(Isolated, isolated, PF_ANY);
+@@ -1092,7 +1112,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)
+ */
+ #define PAGE_FLAGS_SECOND \
+ (0xffUL /* order */ | 1UL << PG_has_hwpoisoned | \
+- 1UL << PG_hugetlb | 1UL << PG_large_rmappable)
++ 1UL << PG_large_rmappable)
+
+ #define PAGE_FLAGS_PRIVATE \
+ (1UL << PG_private | 1UL << PG_private_2)
+diff --git a/include/net/af_unix.h b/include/net/af_unix.h
+index d1b07ddbe677e..77bf30203d3cf 100644
+--- a/include/net/af_unix.h
++++ b/include/net/af_unix.h
+@@ -77,6 +77,9 @@ enum unix_socket_lock_class {
+ U_LOCK_NORMAL,
+ U_LOCK_SECOND, /* for double locking, see unix_state_double_lock(). */
+ U_LOCK_DIAG, /* used while dumping icons, see sk_diag_dump_icons(). */
++ U_LOCK_GC_LISTENER, /* used for listening socket while determining gc
++ * candidates to close a small race window.
++ */
+ };
+
+ static inline void unix_state_lock_nested(struct sock *sk,
+diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
+index 35c5f75a3a5ee..2cfd8d862639f 100644
+--- a/include/net/bluetooth/hci.h
++++ b/include/net/bluetooth/hci.h
+@@ -453,6 +453,7 @@ enum {
+ #define HCI_NCMD_TIMEOUT msecs_to_jiffies(4000) /* 4 seconds */
+ #define HCI_ACL_TX_TIMEOUT msecs_to_jiffies(45000) /* 45 seconds */
+ #define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
++#define HCI_ACL_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */
+ #define HCI_LE_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */
+ #define HCI_LE_AUTOCONN_TIMEOUT msecs_to_jiffies(4000) /* 4 seconds */
+
+@@ -668,6 +669,7 @@ enum {
+ #define HCI_ERROR_PIN_OR_KEY_MISSING 0x06
+ #define HCI_ERROR_MEMORY_EXCEEDED 0x07
+ #define HCI_ERROR_CONNECTION_TIMEOUT 0x08
++#define HCI_ERROR_COMMAND_DISALLOWED 0x0c
+ #define HCI_ERROR_REJ_LIMITED_RESOURCES 0x0d
+ #define HCI_ERROR_REJ_BAD_ADDR 0x0f
+ #define HCI_ERROR_INVALID_PARAMETERS 0x12
+@@ -676,6 +678,7 @@ enum {
+ #define HCI_ERROR_REMOTE_POWER_OFF 0x15
+ #define HCI_ERROR_LOCAL_HOST_TERM 0x16
+ #define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18
++#define HCI_ERROR_UNSUPPORTED_REMOTE_FEATURE 0x1e
+ #define HCI_ERROR_INVALID_LL_PARAMS 0x1e
+ #define HCI_ERROR_UNSPECIFIED 0x1f
+ #define HCI_ERROR_ADVERTISING_TIMEOUT 0x3c
+@@ -2050,6 +2053,7 @@ struct hci_cp_le_set_per_adv_params {
+ } __packed;
+
+ #define HCI_MAX_PER_AD_LENGTH 252
++#define HCI_MAX_PER_AD_TOT_LEN 1650
+
+ #define HCI_OP_LE_SET_PER_ADV_DATA 0x203f
+ struct hci_cp_le_set_per_adv_data {
+@@ -2810,6 +2814,10 @@ struct hci_ev_le_per_adv_report {
+ __u8 data[];
+ } __packed;
+
++#define LE_PA_DATA_COMPLETE 0x00
++#define LE_PA_DATA_MORE_TO_COME 0x01
++#define LE_PA_DATA_TRUNCATED 0x02
++
+ #define HCI_EV_LE_EXT_ADV_SET_TERM 0x12
+ struct hci_evt_le_ext_adv_set_term {
+ __u8 status;
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index d1228857b1d0f..fe9e1524d30ff 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -735,8 +735,11 @@ struct hci_conn {
+ __u16 le_supv_timeout;
+ __u8 le_adv_data[HCI_MAX_EXT_AD_LENGTH];
+ __u8 le_adv_data_len;
+- __u8 le_per_adv_data[HCI_MAX_PER_AD_LENGTH];
+- __u8 le_per_adv_data_len;
++ __u8 le_per_adv_data[HCI_MAX_PER_AD_TOT_LEN];
++ __u16 le_per_adv_data_len;
++ __u16 le_per_adv_data_offset;
++ __u8 le_adv_phy;
++ __u8 le_adv_sec_phy;
+ __u8 le_tx_phy;
+ __u8 le_rx_phy;
+ __s8 rssi;
+@@ -1084,6 +1087,24 @@ static inline unsigned int hci_conn_count(struct hci_dev *hdev)
+ return c->acl_num + c->amp_num + c->sco_num + c->le_num + c->iso_num;
+ }
+
++static inline bool hci_conn_valid(struct hci_dev *hdev, struct hci_conn *conn)
++{
++ struct hci_conn_hash *h = &hdev->conn_hash;
++ struct hci_conn *c;
++
++ rcu_read_lock();
++
++ list_for_each_entry_rcu(c, &h->list, list) {
++ if (c == conn) {
++ rcu_read_unlock();
++ return true;
++ }
++ }
++ rcu_read_unlock();
++
++ return false;
++}
++
+ static inline __u8 hci_conn_lookup_type(struct hci_dev *hdev, __u16 handle)
+ {
+ struct hci_conn_hash *h = &hdev->conn_hash;
+@@ -1481,7 +1502,6 @@ struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
+ bdaddr_t *dst, u8 role);
+ void hci_conn_del(struct hci_conn *conn);
+ void hci_conn_hash_flush(struct hci_dev *hdev);
+-void hci_conn_check_pending(struct hci_dev *hdev);
+
+ struct hci_chan *hci_chan_create(struct hci_conn *conn);
+ void hci_chan_del(struct hci_chan *chan);
+@@ -1494,12 +1514,14 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
+ enum conn_reasons conn_reason);
+ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
+ u8 dst_type, bool dst_resolved, u8 sec_level,
+- u16 conn_timeout, u8 role);
++ u16 conn_timeout, u8 role, u8 phy, u8 sec_phy);
++void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status);
+ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
+ u8 sec_level, u8 auth_type,
+- enum conn_reasons conn_reason);
++ enum conn_reasons conn_reason, u16 timeout);
+ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
+- __u16 setting, struct bt_codec *codec);
++ __u16 setting, struct bt_codec *codec,
++ u16 timeout);
+ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
+ __u8 dst_type, struct bt_iso_qos *qos);
+ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst,
+@@ -1885,6 +1907,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
+ #define privacy_mode_capable(dev) (use_ll_privacy(dev) && \
+ (hdev->commands[39] & 0x04))
+
++#define read_key_size_capable(dev) \
++ ((dev)->commands[20] & 0x10 && \
++ !test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks))
++
+ /* Use enhanced synchronous connection if command is supported and its quirk
+ * has not been set.
+ */
+diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h
+index e2582c2425449..6a9d063e9f472 100644
+--- a/include/net/bluetooth/hci_sync.h
++++ b/include/net/bluetooth/hci_sync.h
+@@ -48,6 +48,18 @@ int hci_cmd_sync_submit(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
+ void *data, hci_cmd_sync_work_destroy_t destroy);
+ int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
+ void *data, hci_cmd_sync_work_destroy_t destroy);
++int hci_cmd_sync_queue_once(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++ void *data, hci_cmd_sync_work_destroy_t destroy);
++struct hci_cmd_sync_work_entry *
++hci_cmd_sync_lookup_entry(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++ void *data, hci_cmd_sync_work_destroy_t destroy);
++void hci_cmd_sync_cancel_entry(struct hci_dev *hdev,
++ struct hci_cmd_sync_work_entry *entry);
++bool hci_cmd_sync_dequeue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++ void *data, hci_cmd_sync_work_destroy_t destroy);
++bool hci_cmd_sync_dequeue_once(struct hci_dev *hdev,
++ hci_cmd_sync_work_func_t func, void *data,
++ hci_cmd_sync_work_destroy_t destroy);
+
+ int hci_update_eir_sync(struct hci_dev *hdev);
+ int hci_update_class_sync(struct hci_dev *hdev);
+@@ -127,8 +139,6 @@ struct hci_conn;
+
+ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason);
+
+-int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn);
+-
+ int hci_le_create_cis_sync(struct hci_dev *hdev);
+
+ int hci_le_remove_cig_sync(struct hci_dev *hdev, u8 handle);
+@@ -138,3 +148,9 @@ int hci_le_terminate_big_sync(struct hci_dev *hdev, u8 handle, u8 reason);
+ int hci_le_big_terminate_sync(struct hci_dev *hdev, u8 handle);
+
+ int hci_le_pa_terminate_sync(struct hci_dev *hdev, u16 handle);
++
++int hci_connect_acl_sync(struct hci_dev *hdev, struct hci_conn *conn);
++
++int hci_connect_le_sync(struct hci_dev *hdev, struct hci_conn *conn);
++
++int hci_cancel_connect_sync(struct hci_dev *hdev, struct hci_conn *conn);
+diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
+index 92d7197f9a563..a4278aa618ab1 100644
+--- a/include/net/bluetooth/l2cap.h
++++ b/include/net/bluetooth/l2cap.h
+@@ -939,7 +939,7 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
+ struct l2cap_chan *l2cap_chan_create(void);
+ void l2cap_chan_close(struct l2cap_chan *chan, int reason);
+ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
+- bdaddr_t *dst, u8 dst_type);
++ bdaddr_t *dst, u8 dst_type, u16 timeout);
+ int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu);
+ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
+ void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
+diff --git a/include/net/macsec.h b/include/net/macsec.h
+index dbd22180cc5c3..de216cbc6b059 100644
+--- a/include/net/macsec.h
++++ b/include/net/macsec.h
+@@ -321,6 +321,7 @@ struct macsec_context {
+ * for the TX tag
+ * @needed_tailroom: number of bytes reserved at the end of the sk_buff for the
+ * TX tag
++ * @rx_uses_md_dst: whether MACsec device offload supports sk_buff md_dst
+ */
+ struct macsec_ops {
+ /* Device wide */
+@@ -352,6 +353,7 @@ struct macsec_ops {
+ struct sk_buff *skb);
+ unsigned int needed_headroom;
+ unsigned int needed_tailroom;
++ bool rx_uses_md_dst;
+ };
+
+ void macsec_pn_wrapped(struct macsec_secy *secy, struct macsec_tx_sa *tx_sa);
+diff --git a/include/net/sock.h b/include/net/sock.h
+index 4afb4376c97e8..54a7967613348 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -1429,33 +1429,36 @@ sk_memory_allocated(const struct sock *sk)
+
+ /* 1 MB per cpu, in page units */
+ #define SK_MEMORY_PCPU_RESERVE (1 << (20 - PAGE_SHIFT))
++extern int sysctl_mem_pcpu_rsv;
++
++static inline void proto_memory_pcpu_drain(struct proto *proto)
++{
++ int val = this_cpu_xchg(*proto->per_cpu_fw_alloc, 0);
++
++ if (val)
++ atomic_long_add(val, proto->memory_allocated);
++}
+
+ static inline void
+-sk_memory_allocated_add(struct sock *sk, int amt)
++sk_memory_allocated_add(const struct sock *sk, int val)
+ {
+- int local_reserve;
++ struct proto *proto = sk->sk_prot;
+
+- preempt_disable();
+- local_reserve = __this_cpu_add_return(*sk->sk_prot->per_cpu_fw_alloc, amt);
+- if (local_reserve >= SK_MEMORY_PCPU_RESERVE) {
+- __this_cpu_sub(*sk->sk_prot->per_cpu_fw_alloc, local_reserve);
+- atomic_long_add(local_reserve, sk->sk_prot->memory_allocated);
+- }
+- preempt_enable();
++ val = this_cpu_add_return(*proto->per_cpu_fw_alloc, val);
++
++ if (unlikely(val >= READ_ONCE(sysctl_mem_pcpu_rsv)))
++ proto_memory_pcpu_drain(proto);
+ }
+
+ static inline void
+-sk_memory_allocated_sub(struct sock *sk, int amt)
++sk_memory_allocated_sub(const struct sock *sk, int val)
+ {
+- int local_reserve;
++ struct proto *proto = sk->sk_prot;
+
+- preempt_disable();
+- local_reserve = __this_cpu_sub_return(*sk->sk_prot->per_cpu_fw_alloc, amt);
+- if (local_reserve <= -SK_MEMORY_PCPU_RESERVE) {
+- __this_cpu_sub(*sk->sk_prot->per_cpu_fw_alloc, local_reserve);
+- atomic_long_add(local_reserve, sk->sk_prot->memory_allocated);
+- }
+- preempt_enable();
++ val = this_cpu_sub_return(*proto->per_cpu_fw_alloc, val);
++
++ if (unlikely(val <= -READ_ONCE(sysctl_mem_pcpu_rsv)))
++ proto_memory_pcpu_drain(proto);
+ }
+
+ #define SK_ALLOC_PERCPU_COUNTER_BATCH 16
+diff --git a/include/net/tls.h b/include/net/tls.h
+index 340ad43971e47..33f657d3c0510 100644
+--- a/include/net/tls.h
++++ b/include/net/tls.h
+@@ -111,7 +111,8 @@ struct tls_strparser {
+ u32 stopped : 1;
+ u32 copy_mode : 1;
+ u32 mixed_decrypted : 1;
+- u32 msg_ready : 1;
++
++ bool msg_ready;
+
+ struct strp_msg stm;
+
+diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h
+index d801409b33cfe..d55e53ac91bd2 100644
+--- a/include/trace/events/mmflags.h
++++ b/include/trace/events/mmflags.h
+@@ -135,6 +135,7 @@ IF_HAVE_PG_ARCH_X(arch_3)
+ #define DEF_PAGETYPE_NAME(_name) { PG_##_name, __stringify(_name) }
+
+ #define __def_pagetype_names \
++ DEF_PAGETYPE_NAME(hugetlb), \
+ DEF_PAGETYPE_NAME(offline), \
+ DEF_PAGETYPE_NAME(guard), \
+ DEF_PAGETYPE_NAME(table), \
+diff --git a/init/Kconfig b/init/Kconfig
+index bee58f7468c36..c8a155cf7209b 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1904,11 +1904,11 @@ config RUST
+ bool "Rust support"
+ depends on HAVE_RUST
+ depends on RUST_IS_AVAILABLE
++ depends on !CFI_CLANG
+ depends on !MODVERSIONS
+ depends on !GCC_PLUGINS
+ depends on !RANDSTRUCT
+ depends on !DEBUG_INFO_BTF || PAHOLE_HAS_LANG_EXCLUDE
+- select CONSTRUCTORS
+ help
+ Enables Rust support in the kernel.
+
+diff --git a/kernel/bounds.c b/kernel/bounds.c
+index c5a9fcd2d6228..29b2cd00df2cc 100644
+--- a/kernel/bounds.c
++++ b/kernel/bounds.c
+@@ -19,7 +19,7 @@ int main(void)
+ DEFINE(NR_PAGEFLAGS, __NR_PAGEFLAGS);
+ DEFINE(MAX_NR_ZONES, __MAX_NR_ZONES);
+ #ifdef CONFIG_SMP
+- DEFINE(NR_CPUS_BITS, bits_per(CONFIG_NR_CPUS));
++ DEFINE(NR_CPUS_BITS, order_base_2(CONFIG_NR_CPUS));
+ #endif
+ DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t));
+ #ifdef CONFIG_LRU_GEN
+diff --git a/kernel/cpu.c b/kernel/cpu.c
+index 980908ef958c1..f8a0406ce8ba5 100644
+--- a/kernel/cpu.c
++++ b/kernel/cpu.c
+@@ -3207,8 +3207,8 @@ enum cpu_mitigations {
+ };
+
+ static enum cpu_mitigations cpu_mitigations __ro_after_init =
+- IS_ENABLED(CONFIG_SPECULATION_MITIGATIONS) ? CPU_MITIGATIONS_AUTO :
+- CPU_MITIGATIONS_OFF;
++ IS_ENABLED(CONFIG_CPU_MITIGATIONS) ? CPU_MITIGATIONS_AUTO :
++ CPU_MITIGATIONS_OFF;
+
+ static int __init mitigations_parse_cmdline(char *arg)
+ {
+diff --git a/kernel/crash_core.c b/kernel/crash_core.c
+index 40bd908e0a81b..ebde3063b5312 100644
+--- a/kernel/crash_core.c
++++ b/kernel/crash_core.c
+@@ -814,11 +814,10 @@ static int __init crash_save_vmcoreinfo_init(void)
+ VMCOREINFO_NUMBER(PG_head_mask);
+ #define PAGE_BUDDY_MAPCOUNT_VALUE (~PG_buddy)
+ VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE);
+-#ifdef CONFIG_HUGETLB_PAGE
+- VMCOREINFO_NUMBER(PG_hugetlb);
++#define PAGE_HUGETLB_MAPCOUNT_VALUE (~PG_hugetlb)
++ VMCOREINFO_NUMBER(PAGE_HUGETLB_MAPCOUNT_VALUE);
+ #define PAGE_OFFLINE_MAPCOUNT_VALUE (~PG_offline)
+ VMCOREINFO_NUMBER(PAGE_OFFLINE_MAPCOUNT_VALUE);
+-#endif
+
+ #ifdef CONFIG_KALLSYMS
+ VMCOREINFO_SYMBOL(kallsyms_names);
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index e2b4e0396af84..aee5e7a70170c 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -696,15 +696,21 @@ u64 avg_vruntime(struct cfs_rq *cfs_rq)
+ *
+ * XXX could add max_slice to the augmented data to track this.
+ */
+-static void update_entity_lag(struct cfs_rq *cfs_rq, struct sched_entity *se)
++static s64 entity_lag(u64 avruntime, struct sched_entity *se)
+ {
+- s64 lag, limit;
++ s64 vlag, limit;
++
++ vlag = avruntime - se->vruntime;
++ limit = calc_delta_fair(max_t(u64, 2*se->slice, TICK_NSEC), se);
+
++ return clamp(vlag, -limit, limit);
++}
++
++static void update_entity_lag(struct cfs_rq *cfs_rq, struct sched_entity *se)
++{
+ SCHED_WARN_ON(!se->on_rq);
+- lag = avg_vruntime(cfs_rq) - se->vruntime;
+
+- limit = calc_delta_fair(max_t(u64, 2*se->slice, TICK_NSEC), se);
+- se->vlag = clamp(lag, -limit, limit);
++ se->vlag = entity_lag(avg_vruntime(cfs_rq), se);
+ }
+
+ /*
+@@ -3670,11 +3676,10 @@ static inline void
+ dequeue_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se) { }
+ #endif
+
+-static void reweight_eevdf(struct cfs_rq *cfs_rq, struct sched_entity *se,
++static void reweight_eevdf(struct sched_entity *se, u64 avruntime,
+ unsigned long weight)
+ {
+ unsigned long old_weight = se->load.weight;
+- u64 avruntime = avg_vruntime(cfs_rq);
+ s64 vlag, vslice;
+
+ /*
+@@ -3755,7 +3760,7 @@ static void reweight_eevdf(struct cfs_rq *cfs_rq, struct sched_entity *se,
+ * = V - vl'
+ */
+ if (avruntime != se->vruntime) {
+- vlag = (s64)(avruntime - se->vruntime);
++ vlag = entity_lag(avruntime, se);
+ vlag = div_s64(vlag * old_weight, weight);
+ se->vruntime = avruntime - vlag;
+ }
+@@ -3781,25 +3786,26 @@ static void reweight_entity(struct cfs_rq *cfs_rq, struct sched_entity *se,
+ unsigned long weight)
+ {
+ bool curr = cfs_rq->curr == se;
++ u64 avruntime;
+
+ if (se->on_rq) {
+ /* commit outstanding execution time */
+- if (curr)
+- update_curr(cfs_rq);
+- else
++ update_curr(cfs_rq);
++ avruntime = avg_vruntime(cfs_rq);
++ if (!curr)
+ __dequeue_entity(cfs_rq, se);
+ update_load_sub(&cfs_rq->load, se->load.weight);
+ }
+ dequeue_load_avg(cfs_rq, se);
+
+- if (!se->on_rq) {
++ if (se->on_rq) {
++ reweight_eevdf(se, avruntime, weight);
++ } else {
+ /*
+ * Because we keep se->vlag = V - v_i, while: lag_i = w_i*(V - v_i),
+ * we need to scale se->vlag when w_i changes.
+ */
+ se->vlag = div_s64(se->vlag * se->load.weight, weight);
+- } else {
+- reweight_eevdf(cfs_rq, se, weight);
+ }
+
+ update_load_set(&se->load, weight);
+diff --git a/lib/stackdepot.c b/lib/stackdepot.c
+index ee830f14afb78..91d2301fdef79 100644
+--- a/lib/stackdepot.c
++++ b/lib/stackdepot.c
+@@ -627,10 +627,10 @@ depot_stack_handle_t stack_depot_save_flags(unsigned long *entries,
+ /*
+ * Zero out zone modifiers, as we don't have specific zone
+ * requirements. Keep the flags related to allocation in atomic
+- * contexts and I/O.
++ * contexts, I/O, nolockdep.
+ */
+ alloc_flags &= ~GFP_ZONEMASK;
+- alloc_flags &= (GFP_ATOMIC | GFP_KERNEL);
++ alloc_flags &= (GFP_ATOMIC | GFP_KERNEL | __GFP_NOLOCKDEP);
+ alloc_flags |= __GFP_NOWARN;
+ page = alloc_pages(alloc_flags, DEPOT_POOL_ORDER);
+ if (page)
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index e5e3df1d3b874..c2b9ba3a546e4 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -1623,7 +1623,7 @@ static inline void __clear_hugetlb_destructor(struct hstate *h,
+ {
+ lockdep_assert_held(&hugetlb_lock);
+
+- folio_clear_hugetlb(folio);
++ __folio_clear_hugetlb(folio);
+ }
+
+ /*
+@@ -1710,7 +1710,7 @@ static void add_hugetlb_folio(struct hstate *h, struct folio *folio,
+ h->surplus_huge_pages_node[nid]++;
+ }
+
+- folio_set_hugetlb(folio);
++ __folio_set_hugetlb(folio);
+ folio_change_private(folio, NULL);
+ /*
+ * We have to set hugetlb_vmemmap_optimized again as above
+@@ -1780,7 +1780,7 @@ static void __update_and_free_hugetlb_folio(struct hstate *h,
+ * If vmemmap pages were allocated above, then we need to clear the
+ * hugetlb destructor under the hugetlb lock.
+ */
+- if (clear_dtor) {
++ if (folio_test_hugetlb(folio)) {
+ spin_lock_irq(&hugetlb_lock);
+ __clear_hugetlb_destructor(h, folio);
+ spin_unlock_irq(&hugetlb_lock);
+@@ -2048,7 +2048,7 @@ static void __prep_account_new_huge_page(struct hstate *h, int nid)
+
+ static void init_new_hugetlb_folio(struct hstate *h, struct folio *folio)
+ {
+- folio_set_hugetlb(folio);
++ __folio_set_hugetlb(folio);
+ INIT_LIST_HEAD(&folio->lru);
+ hugetlb_set_folio_subpool(folio, NULL);
+ set_hugetlb_cgroup(folio, NULL);
+@@ -2158,22 +2158,6 @@ static bool prep_compound_gigantic_folio_for_demote(struct folio *folio,
+ return __prep_compound_gigantic_folio(folio, order, true);
+ }
+
+-/*
+- * PageHuge() only returns true for hugetlbfs pages, but not for normal or
+- * transparent huge pages. See the PageTransHuge() documentation for more
+- * details.
+- */
+-int PageHuge(struct page *page)
+-{
+- struct folio *folio;
+-
+- if (!PageCompound(page))
+- return 0;
+- folio = page_folio(page);
+- return folio_test_hugetlb(folio);
+-}
+-EXPORT_SYMBOL_GPL(PageHuge);
+-
+ /*
+ * Find and lock address space (mapping) in write mode.
+ *
+@@ -3266,9 +3250,12 @@ struct folio *alloc_hugetlb_folio(struct vm_area_struct *vma,
+
+ rsv_adjust = hugepage_subpool_put_pages(spool, 1);
+ hugetlb_acct_memory(h, -rsv_adjust);
+- if (deferred_reserve)
++ if (deferred_reserve) {
++ spin_lock_irq(&hugetlb_lock);
+ hugetlb_cgroup_uncharge_folio_rsvd(hstate_index(h),
+ pages_per_huge_page(h), folio);
++ spin_unlock_irq(&hugetlb_lock);
++ }
+ }
+
+ if (!memcg_charge_ret)
+diff --git a/mm/zswap.c b/mm/zswap.c
+index e9c04387195fa..69766f2c5a6c4 100644
+--- a/mm/zswap.c
++++ b/mm/zswap.c
+@@ -653,15 +653,22 @@ static unsigned long zswap_shrinker_count(struct shrinker *shrinker,
+ if (!gfp_has_io_fs(sc->gfp_mask))
+ return 0;
+
+-#ifdef CONFIG_MEMCG_KMEM
+- mem_cgroup_flush_stats(memcg);
+- nr_backing = memcg_page_state(memcg, MEMCG_ZSWAP_B) >> PAGE_SHIFT;
+- nr_stored = memcg_page_state(memcg, MEMCG_ZSWAPPED);
+-#else
+- /* use pool stats instead of memcg stats */
+- nr_backing = get_zswap_pool_size(pool) >> PAGE_SHIFT;
+- nr_stored = atomic_read(&pool->nr_stored);
+-#endif
++ /*
++ * For memcg, use the cgroup-wide ZSWAP stats since we don't
++ * have them per-node and thus per-lruvec. Careful if memcg is
++ * runtime-disabled: we can get sc->memcg == NULL, which is ok
++ * for the lruvec, but not for memcg_page_state().
++ *
++ * Without memcg, use the zswap pool-wide metrics.
++ */
++ if (!mem_cgroup_disabled()) {
++ mem_cgroup_flush_stats(memcg);
++ nr_backing = memcg_page_state(memcg, MEMCG_ZSWAP_B) >> PAGE_SHIFT;
++ nr_stored = memcg_page_state(memcg, MEMCG_ZSWAPPED);
++ } else {
++ nr_backing = get_zswap_pool_size(pool) >> PAGE_SHIFT;
++ nr_stored = atomic_read(&pool->nr_stored);
++ }
+
+ if (!nr_stored)
+ return 0;
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 558e158c98d01..9169efb2f43aa 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -103,7 +103,7 @@ static void ax25_kill_by_device(struct net_device *dev)
+ s->ax25_dev = NULL;
+ if (sk->sk_socket) {
+ netdev_put(ax25_dev->dev,
+- &ax25_dev->dev_tracker);
++ &s->dev_tracker);
+ ax25_dev_put(ax25_dev);
+ }
+ ax25_cb_del(s);
+diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
+index 4eb1b3ced0d27..715cbafbf6631 100644
+--- a/net/bluetooth/6lowpan.c
++++ b/net/bluetooth/6lowpan.c
+@@ -892,7 +892,7 @@ static int bt_6lowpan_connect(bdaddr_t *addr, u8 dst_type)
+ chan->ops = &bt_6lowpan_chan_ops;
+
+ err = l2cap_chan_connect(chan, cpu_to_le16(L2CAP_PSM_IPSP), 0,
+- addr, dst_type);
++ addr, dst_type, L2CAP_CONN_TIMEOUT);
+
+ BT_DBG("chan %p err %d", chan, err);
+ if (err < 0)
+diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
+index ba330114d38f7..18f97b2288699 100644
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -68,7 +68,7 @@ static const struct sco_param esco_param_msbc[] = {
+ };
+
+ /* This function requires the caller holds hdev->lock */
+-static void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
++void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
+ {
+ struct hci_conn_params *params;
+ struct hci_dev *hdev = conn->hdev;
+@@ -178,64 +178,6 @@ static void hci_conn_cleanup(struct hci_conn *conn)
+ hci_dev_put(hdev);
+ }
+
+-static void hci_acl_create_connection(struct hci_conn *conn)
+-{
+- struct hci_dev *hdev = conn->hdev;
+- struct inquiry_entry *ie;
+- struct hci_cp_create_conn cp;
+-
+- BT_DBG("hcon %p", conn);
+-
+- /* Many controllers disallow HCI Create Connection while it is doing
+- * HCI Inquiry. So we cancel the Inquiry first before issuing HCI Create
+- * Connection. This may cause the MGMT discovering state to become false
+- * without user space's request but it is okay since the MGMT Discovery
+- * APIs do not promise that discovery should be done forever. Instead,
+- * the user space monitors the status of MGMT discovering and it may
+- * request for discovery again when this flag becomes false.
+- */
+- if (test_bit(HCI_INQUIRY, &hdev->flags)) {
+- /* Put this connection to "pending" state so that it will be
+- * executed after the inquiry cancel command complete event.
+- */
+- conn->state = BT_CONNECT2;
+- hci_send_cmd(hdev, HCI_OP_INQUIRY_CANCEL, 0, NULL);
+- return;
+- }
+-
+- conn->state = BT_CONNECT;
+- conn->out = true;
+- conn->role = HCI_ROLE_MASTER;
+-
+- conn->attempt++;
+-
+- conn->link_policy = hdev->link_policy;
+-
+- memset(&cp, 0, sizeof(cp));
+- bacpy(&cp.bdaddr, &conn->dst);
+- cp.pscan_rep_mode = 0x02;
+-
+- ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
+- if (ie) {
+- if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
+- cp.pscan_rep_mode = ie->data.pscan_rep_mode;
+- cp.pscan_mode = ie->data.pscan_mode;
+- cp.clock_offset = ie->data.clock_offset |
+- cpu_to_le16(0x8000);
+- }
+-
+- memcpy(conn->dev_class, ie->data.dev_class, 3);
+- }
+-
+- cp.pkt_type = cpu_to_le16(conn->pkt_type);
+- if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
+- cp.role_switch = 0x01;
+- else
+- cp.role_switch = 0x00;
+-
+- hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp);
+-}
+-
+ int hci_disconnect(struct hci_conn *conn, __u8 reason)
+ {
+ BT_DBG("hcon %p", conn);
+@@ -1182,6 +1124,9 @@ void hci_conn_del(struct hci_conn *conn)
+ * rest of hci_conn_del.
+ */
+ hci_conn_cleanup(conn);
++
++ /* Dequeue callbacks using connection pointer as data */
++ hci_cmd_sync_dequeue(hdev, NULL, conn, NULL);
+ }
+
+ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, uint8_t src_type)
+@@ -1316,56 +1261,9 @@ u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle)
+ return 0;
+ }
+
+-static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
+-{
+- struct hci_conn *conn;
+- u16 handle = PTR_UINT(data);
+-
+- conn = hci_conn_hash_lookup_handle(hdev, handle);
+- if (!conn)
+- return;
+-
+- bt_dev_dbg(hdev, "err %d", err);
+-
+- hci_dev_lock(hdev);
+-
+- if (!err) {
+- hci_connect_le_scan_cleanup(conn, 0x00);
+- goto done;
+- }
+-
+- /* Check if connection is still pending */
+- if (conn != hci_lookup_le_connect(hdev))
+- goto done;
+-
+- /* Flush to make sure we send create conn cancel command if needed */
+- flush_delayed_work(&conn->le_conn_timeout);
+- hci_conn_failed(conn, bt_status(err));
+-
+-done:
+- hci_dev_unlock(hdev);
+-}
+-
+-static int hci_connect_le_sync(struct hci_dev *hdev, void *data)
+-{
+- struct hci_conn *conn;
+- u16 handle = PTR_UINT(data);
+-
+- conn = hci_conn_hash_lookup_handle(hdev, handle);
+- if (!conn)
+- return 0;
+-
+- bt_dev_dbg(hdev, "conn %p", conn);
+-
+- clear_bit(HCI_CONN_SCANNING, &conn->flags);
+- conn->state = BT_CONNECT;
+-
+- return hci_le_create_conn_sync(hdev, conn);
+-}
+-
+ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
+ u8 dst_type, bool dst_resolved, u8 sec_level,
+- u16 conn_timeout, u8 role)
++ u16 conn_timeout, u8 role, u8 phy, u8 sec_phy)
+ {
+ struct hci_conn *conn;
+ struct smp_irk *irk;
+@@ -1428,10 +1326,10 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
+ conn->dst_type = dst_type;
+ conn->sec_level = BT_SECURITY_LOW;
+ conn->conn_timeout = conn_timeout;
++ conn->le_adv_phy = phy;
++ conn->le_adv_sec_phy = sec_phy;
+
+- err = hci_cmd_sync_queue(hdev, hci_connect_le_sync,
+- UINT_PTR(conn->handle),
+- create_le_conn_complete);
++ err = hci_connect_le_sync(hdev, conn);
+ if (err) {
+ hci_conn_del(conn);
+ return ERR_PTR(err);
+@@ -1665,7 +1563,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
+
+ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
+ u8 sec_level, u8 auth_type,
+- enum conn_reasons conn_reason)
++ enum conn_reasons conn_reason, u16 timeout)
+ {
+ struct hci_conn *acl;
+
+@@ -1696,10 +1594,18 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
+
+ acl->conn_reason = conn_reason;
+ if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
++ int err;
++
+ acl->sec_level = BT_SECURITY_LOW;
+ acl->pending_sec_level = sec_level;
+ acl->auth_type = auth_type;
+- hci_acl_create_connection(acl);
++ acl->conn_timeout = timeout;
++
++ err = hci_connect_acl_sync(hdev, acl);
++ if (err) {
++ hci_conn_del(acl);
++ return ERR_PTR(err);
++ }
+ }
+
+ return acl;
+@@ -1734,14 +1640,15 @@ static struct hci_link *hci_conn_link(struct hci_conn *parent,
+ }
+
+ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
+- __u16 setting, struct bt_codec *codec)
++ __u16 setting, struct bt_codec *codec,
++ u16 timeout)
+ {
+ struct hci_conn *acl;
+ struct hci_conn *sco;
+ struct hci_link *link;
+
+ acl = hci_connect_acl(hdev, dst, BT_SECURITY_LOW, HCI_AT_NO_BONDING,
+- CONN_REASON_SCO_CONNECT);
++ CONN_REASON_SCO_CONNECT, timeout);
+ if (IS_ERR(acl))
+ return acl;
+
+@@ -2348,7 +2255,7 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
+ le = hci_connect_le(hdev, dst, dst_type, false,
+ BT_SECURITY_LOW,
+ HCI_LE_CONN_TIMEOUT,
+- HCI_ROLE_SLAVE);
++ HCI_ROLE_SLAVE, 0, 0);
+ else
+ le = hci_connect_le_scan(hdev, dst, dst_type,
+ BT_SECURITY_LOW,
+@@ -2643,22 +2550,6 @@ void hci_conn_hash_flush(struct hci_dev *hdev)
+ }
+ }
+
+-/* Check pending connect attempts */
+-void hci_conn_check_pending(struct hci_dev *hdev)
+-{
+- struct hci_conn *conn;
+-
+- BT_DBG("hdev %s", hdev->name);
+-
+- hci_dev_lock(hdev);
+-
+- conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2);
+- if (conn)
+- hci_acl_create_connection(conn);
+-
+- hci_dev_unlock(hdev);
+-}
+-
+ static u32 get_link_mode(struct hci_conn *conn)
+ {
+ u32 link_mode = 0;
+@@ -2974,12 +2865,10 @@ u32 hci_conn_get_phy(struct hci_conn *conn)
+
+ static int abort_conn_sync(struct hci_dev *hdev, void *data)
+ {
+- struct hci_conn *conn;
+- u16 handle = PTR_UINT(data);
++ struct hci_conn *conn = data;
+
+- conn = hci_conn_hash_lookup_handle(hdev, handle);
+- if (!conn)
+- return 0;
++ if (!hci_conn_valid(hdev, conn))
++ return -ECANCELED;
+
+ return hci_abort_conn_sync(hdev, conn, conn->abort_reason);
+ }
+@@ -3007,14 +2896,17 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
+ */
+ if (conn->state == BT_CONNECT && hdev->req_status == HCI_REQ_PEND) {
+ switch (hci_skb_event(hdev->sent_cmd)) {
++ case HCI_EV_CONN_COMPLETE:
+ case HCI_EV_LE_CONN_COMPLETE:
+ case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
+ case HCI_EVT_LE_CIS_ESTABLISHED:
+ hci_cmd_sync_cancel(hdev, ECANCELED);
+ break;
+ }
++ /* Cancel connect attempt if still queued/pending */
++ } else if (!hci_cancel_connect_sync(hdev, conn)) {
++ return 0;
+ }
+
+- return hci_cmd_sync_queue(hdev, abort_conn_sync, UINT_PTR(conn->handle),
+- NULL);
++ return hci_cmd_sync_queue_once(hdev, abort_conn_sync, conn, NULL);
+ }
+diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
+index 3992e18f0babb..9d1063c51ed29 100644
+--- a/net/bluetooth/hci_event.c
++++ b/net/bluetooth/hci_event.c
+@@ -93,11 +93,11 @@ static u8 hci_cc_inquiry_cancel(struct hci_dev *hdev, void *data,
+ /* It is possible that we receive Inquiry Complete event right
+ * before we receive Inquiry Cancel Command Complete event, in
+ * which case the latter event should have status of Command
+- * Disallowed (0x0c). This should not be treated as error, since
++ * Disallowed. This should not be treated as error, since
+ * we actually achieve what Inquiry Cancel wants to achieve,
+ * which is to end the last Inquiry session.
+ */
+- if (rp->status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) {
++ if (rp->status == HCI_ERROR_COMMAND_DISALLOWED && !test_bit(HCI_INQUIRY, &hdev->flags)) {
+ bt_dev_warn(hdev, "Ignoring error of Inquiry Cancel command");
+ rp->status = 0x00;
+ }
+@@ -118,8 +118,6 @@ static u8 hci_cc_inquiry_cancel(struct hci_dev *hdev, void *data,
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+ hci_dev_unlock(hdev);
+
+- hci_conn_check_pending(hdev);
+-
+ return rp->status;
+ }
+
+@@ -150,8 +148,6 @@ static u8 hci_cc_exit_periodic_inq(struct hci_dev *hdev, void *data,
+
+ hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ);
+
+- hci_conn_check_pending(hdev);
+-
+ return rp->status;
+ }
+
+@@ -2312,10 +2308,8 @@ static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
+ {
+ bt_dev_dbg(hdev, "status 0x%2.2x", status);
+
+- if (status) {
+- hci_conn_check_pending(hdev);
++ if (status)
+ return;
+- }
+
+ if (hci_sent_cmd_data(hdev, HCI_OP_INQUIRY))
+ set_bit(HCI_INQUIRY, &hdev->flags);
+@@ -2340,12 +2334,9 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
+
+ if (status) {
+ if (conn && conn->state == BT_CONNECT) {
+- if (status != 0x0c || conn->attempt > 2) {
+- conn->state = BT_CLOSED;
+- hci_connect_cfm(conn, status);
+- hci_conn_del(conn);
+- } else
+- conn->state = BT_CONNECT2;
++ conn->state = BT_CLOSED;
++ hci_connect_cfm(conn, status);
++ hci_conn_del(conn);
+ }
+ } else {
+ if (!conn) {
+@@ -3035,8 +3026,6 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, void *data,
+
+ bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
+
+- hci_conn_check_pending(hdev);
+-
+ if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
+ return;
+
+@@ -3229,7 +3218,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
+ if (key) {
+ set_bit(HCI_CONN_ENCRYPT, &conn->flags);
+
+- if (!(hdev->commands[20] & 0x10)) {
++ if (!read_key_size_capable(hdev)) {
+ conn->enc_key_size = HCI_LINK_KEY_SIZE;
+ } else {
+ cp.handle = cpu_to_le16(conn->handle);
+@@ -3283,8 +3272,6 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
+
+ unlock:
+ hci_dev_unlock(hdev);
+-
+- hci_conn_check_pending(hdev);
+ }
+
+ static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr)
+@@ -3679,8 +3666,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
+ * controller really supports it. If it doesn't, assume
+ * the default size (16).
+ */
+- if (!(hdev->commands[20] & 0x10) ||
+- test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks)) {
++ if (!read_key_size_capable(hdev)) {
+ conn->enc_key_size = HCI_LINK_KEY_SIZE;
+ goto notify;
+ }
+@@ -6195,7 +6181,7 @@ static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, void *data,
+ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
+ bdaddr_t *addr,
+ u8 addr_type, bool addr_resolved,
+- u8 adv_type)
++ u8 adv_type, u8 phy, u8 sec_phy)
+ {
+ struct hci_conn *conn;
+ struct hci_conn_params *params;
+@@ -6250,7 +6236,7 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
+
+ conn = hci_connect_le(hdev, addr, addr_type, addr_resolved,
+ BT_SECURITY_LOW, hdev->def_le_autoconnect_timeout,
+- HCI_ROLE_MASTER);
++ HCI_ROLE_MASTER, phy, sec_phy);
+ if (!IS_ERR(conn)) {
+ /* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned
+ * by higher layer that tried to connect, if no then
+@@ -6285,8 +6271,9 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
+
+ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
+ u8 bdaddr_type, bdaddr_t *direct_addr,
+- u8 direct_addr_type, s8 rssi, u8 *data, u8 len,
+- bool ext_adv, bool ctl_time, u64 instant)
++ u8 direct_addr_type, u8 phy, u8 sec_phy, s8 rssi,
++ u8 *data, u8 len, bool ext_adv, bool ctl_time,
++ u64 instant)
+ {
+ struct discovery_state *d = &hdev->discovery;
+ struct smp_irk *irk;
+@@ -6374,7 +6361,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
+ * for advertising reports) and is already verified to be RPA above.
+ */
+ conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, bdaddr_resolved,
+- type);
++ type, phy, sec_phy);
+ if (!ext_adv && conn && type == LE_ADV_IND &&
+ len <= max_adv_len(hdev)) {
+ /* Store report for later inclusion by
+@@ -6520,7 +6507,8 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, void *data,
+ if (info->length <= max_adv_len(hdev)) {
+ rssi = info->data[info->length];
+ process_adv_report(hdev, info->type, &info->bdaddr,
+- info->bdaddr_type, NULL, 0, rssi,
++ info->bdaddr_type, NULL, 0,
++ HCI_ADV_PHY_1M, 0, rssi,
+ info->data, info->length, false,
+ false, instant);
+ } else {
+@@ -6605,6 +6593,8 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data,
+ if (legacy_evt_type != LE_ADV_INVALID) {
+ process_adv_report(hdev, legacy_evt_type, &info->bdaddr,
+ info->bdaddr_type, NULL, 0,
++ info->primary_phy,
++ info->secondary_phy,
+ info->rssi, info->data, info->length,
+ !(evt_type & LE_EXT_ADV_LEGACY_PDU),
+ false, instant);
+@@ -6710,7 +6700,7 @@ static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, void *data,
+ * transition into connected state and mark it as
+ * successful.
+ */
+- if (!conn->out && ev->status == 0x1a &&
++ if (!conn->out && ev->status == HCI_ERROR_UNSUPPORTED_REMOTE_FEATURE &&
+ (hdev->le_features[0] & HCI_LE_PERIPHERAL_FEATURES))
+ status = 0x00;
+ else
+@@ -6887,8 +6877,8 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, void *data,
+
+ process_adv_report(hdev, info->type, &info->bdaddr,
+ info->bdaddr_type, &info->direct_addr,
+- info->direct_addr_type, info->rssi, NULL, 0,
+- false, false, instant);
++ info->direct_addr_type, HCI_ADV_PHY_1M, 0,
++ info->rssi, NULL, 0, false, false, instant);
+ }
+
+ hci_dev_unlock(hdev);
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index e1050d7d21a59..40b71bc505730 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -570,6 +570,17 @@ void hci_cmd_sync_init(struct hci_dev *hdev)
+ INIT_DELAYED_WORK(&hdev->adv_instance_expire, adv_timeout_expire);
+ }
+
++static void _hci_cmd_sync_cancel_entry(struct hci_dev *hdev,
++ struct hci_cmd_sync_work_entry *entry,
++ int err)
++{
++ if (entry->destroy)
++ entry->destroy(hdev, entry->data, err);
++
++ list_del(&entry->list);
++ kfree(entry);
++}
++
+ void hci_cmd_sync_clear(struct hci_dev *hdev)
+ {
+ struct hci_cmd_sync_work_entry *entry, *tmp;
+@@ -578,13 +589,8 @@ void hci_cmd_sync_clear(struct hci_dev *hdev)
+ cancel_work_sync(&hdev->reenable_adv_work);
+
+ mutex_lock(&hdev->cmd_sync_work_lock);
+- list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) {
+- if (entry->destroy)
+- entry->destroy(hdev, entry->data, -ECANCELED);
+-
+- list_del(&entry->list);
+- kfree(entry);
+- }
++ list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list)
++ _hci_cmd_sync_cancel_entry(hdev, entry, -ECANCELED);
+ mutex_unlock(&hdev->cmd_sync_work_lock);
+ }
+
+@@ -676,6 +682,115 @@ int hci_cmd_sync_queue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
+ }
+ EXPORT_SYMBOL(hci_cmd_sync_queue);
+
++static struct hci_cmd_sync_work_entry *
++_hci_cmd_sync_lookup_entry(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++ void *data, hci_cmd_sync_work_destroy_t destroy)
++{
++ struct hci_cmd_sync_work_entry *entry, *tmp;
++
++ list_for_each_entry_safe(entry, tmp, &hdev->cmd_sync_work_list, list) {
++ if (func && entry->func != func)
++ continue;
++
++ if (data && entry->data != data)
++ continue;
++
++ if (destroy && entry->destroy != destroy)
++ continue;
++
++ return entry;
++ }
++
++ return NULL;
++}
++
++/* Queue HCI command entry once:
++ *
++ * - Lookup if an entry already exist and only if it doesn't creates a new entry
++ * and queue it.
++ */
++int hci_cmd_sync_queue_once(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++ void *data, hci_cmd_sync_work_destroy_t destroy)
++{
++ if (hci_cmd_sync_lookup_entry(hdev, func, data, destroy))
++ return 0;
++
++ return hci_cmd_sync_queue(hdev, func, data, destroy);
++}
++EXPORT_SYMBOL(hci_cmd_sync_queue_once);
++
++/* Lookup HCI command entry:
++ *
++ * - Return first entry that matches by function callback or data or
++ * destroy callback.
++ */
++struct hci_cmd_sync_work_entry *
++hci_cmd_sync_lookup_entry(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++ void *data, hci_cmd_sync_work_destroy_t destroy)
++{
++ struct hci_cmd_sync_work_entry *entry;
++
++ mutex_lock(&hdev->cmd_sync_work_lock);
++ entry = _hci_cmd_sync_lookup_entry(hdev, func, data, destroy);
++ mutex_unlock(&hdev->cmd_sync_work_lock);
++
++ return entry;
++}
++EXPORT_SYMBOL(hci_cmd_sync_lookup_entry);
++
++/* Cancel HCI command entry */
++void hci_cmd_sync_cancel_entry(struct hci_dev *hdev,
++ struct hci_cmd_sync_work_entry *entry)
++{
++ mutex_lock(&hdev->cmd_sync_work_lock);
++ _hci_cmd_sync_cancel_entry(hdev, entry, -ECANCELED);
++ mutex_unlock(&hdev->cmd_sync_work_lock);
++}
++EXPORT_SYMBOL(hci_cmd_sync_cancel_entry);
++
++/* Dequeue one HCI command entry:
++ *
++ * - Lookup and cancel first entry that matches.
++ */
++bool hci_cmd_sync_dequeue_once(struct hci_dev *hdev,
++ hci_cmd_sync_work_func_t func,
++ void *data, hci_cmd_sync_work_destroy_t destroy)
++{
++ struct hci_cmd_sync_work_entry *entry;
++
++ entry = hci_cmd_sync_lookup_entry(hdev, func, data, destroy);
++ if (!entry)
++ return false;
++
++ hci_cmd_sync_cancel_entry(hdev, entry);
++
++ return true;
++}
++EXPORT_SYMBOL(hci_cmd_sync_dequeue_once);
++
++/* Dequeue HCI command entry:
++ *
++ * - Lookup and cancel any entry that matches by function callback or data or
++ * destroy callback.
++ */
++bool hci_cmd_sync_dequeue(struct hci_dev *hdev, hci_cmd_sync_work_func_t func,
++ void *data, hci_cmd_sync_work_destroy_t destroy)
++{
++ struct hci_cmd_sync_work_entry *entry;
++ bool ret = false;
++
++ mutex_lock(&hdev->cmd_sync_work_lock);
++ while ((entry = _hci_cmd_sync_lookup_entry(hdev, func, data,
++ destroy))) {
++ _hci_cmd_sync_cancel_entry(hdev, entry, -ECANCELED);
++ ret = true;
++ }
++ mutex_unlock(&hdev->cmd_sync_work_lock);
++
++ return ret;
++}
++EXPORT_SYMBOL(hci_cmd_sync_dequeue);
++
+ int hci_update_eir_sync(struct hci_dev *hdev)
+ {
+ struct hci_cp_write_eir cp;
+@@ -2932,7 +3047,8 @@ int hci_update_passive_scan(struct hci_dev *hdev)
+ hci_dev_test_flag(hdev, HCI_UNREGISTER))
+ return 0;
+
+- return hci_cmd_sync_queue(hdev, update_passive_scan_sync, NULL, NULL);
++ return hci_cmd_sync_queue_once(hdev, update_passive_scan_sync, NULL,
++ NULL);
+ }
+
+ int hci_write_sc_support_sync(struct hci_dev *hdev, u8 val)
+@@ -6199,7 +6315,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
+
+ plen = sizeof(*cp);
+
+- if (scan_1m(hdev)) {
++ if (scan_1m(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_1M ||
++ conn->le_adv_sec_phy == HCI_ADV_PHY_1M)) {
+ cp->phys |= LE_SCAN_PHY_1M;
+ set_ext_conn_params(conn, p);
+
+@@ -6207,7 +6324,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
+ plen += sizeof(*p);
+ }
+
+- if (scan_2m(hdev)) {
++ if (scan_2m(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_2M ||
++ conn->le_adv_sec_phy == HCI_ADV_PHY_2M)) {
+ cp->phys |= LE_SCAN_PHY_2M;
+ set_ext_conn_params(conn, p);
+
+@@ -6215,7 +6333,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
+ plen += sizeof(*p);
+ }
+
+- if (scan_coded(hdev)) {
++ if (scan_coded(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_CODED ||
++ conn->le_adv_sec_phy == HCI_ADV_PHY_CODED)) {
+ cp->phys |= LE_SCAN_PHY_CODED;
+ set_ext_conn_params(conn, p);
+
+@@ -6228,12 +6347,21 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev,
+ conn->conn_timeout, NULL);
+ }
+
+-int hci_le_create_conn_sync(struct hci_dev *hdev, struct hci_conn *conn)
++static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)
+ {
+ struct hci_cp_le_create_conn cp;
+ struct hci_conn_params *params;
+ u8 own_addr_type;
+ int err;
++ struct hci_conn *conn = data;
++
++ if (!hci_conn_valid(hdev, conn))
++ return -ECANCELED;
++
++ bt_dev_dbg(hdev, "conn %p", conn);
++
++ clear_bit(HCI_CONN_SCANNING, &conn->flags);
++ conn->state = BT_CONNECT;
+
+ /* If requested to connect as peripheral use directed advertising */
+ if (conn->role == HCI_ROLE_SLAVE) {
+@@ -6551,3 +6679,125 @@ int hci_update_adv_data(struct hci_dev *hdev, u8 instance)
+ return hci_cmd_sync_queue(hdev, _update_adv_data_sync,
+ UINT_PTR(instance), NULL);
+ }
++
++static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data)
++{
++ struct hci_conn *conn = data;
++ struct inquiry_entry *ie;
++ struct hci_cp_create_conn cp;
++ int err;
++
++ if (!hci_conn_valid(hdev, conn))
++ return -ECANCELED;
++
++ /* Many controllers disallow HCI Create Connection while it is doing
++ * HCI Inquiry. So we cancel the Inquiry first before issuing HCI Create
++ * Connection. This may cause the MGMT discovering state to become false
++ * without user space's request but it is okay since the MGMT Discovery
++ * APIs do not promise that discovery should be done forever. Instead,
++ * the user space monitors the status of MGMT discovering and it may
++ * request for discovery again when this flag becomes false.
++ */
++ if (test_bit(HCI_INQUIRY, &hdev->flags)) {
++ err = __hci_cmd_sync_status(hdev, HCI_OP_INQUIRY_CANCEL, 0,
++ NULL, HCI_CMD_TIMEOUT);
++ if (err)
++ bt_dev_warn(hdev, "Failed to cancel inquiry %d", err);
++ }
++
++ conn->state = BT_CONNECT;
++ conn->out = true;
++ conn->role = HCI_ROLE_MASTER;
++
++ conn->attempt++;
++
++ conn->link_policy = hdev->link_policy;
++
++ memset(&cp, 0, sizeof(cp));
++ bacpy(&cp.bdaddr, &conn->dst);
++ cp.pscan_rep_mode = 0x02;
++
++ ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
++ if (ie) {
++ if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
++ cp.pscan_rep_mode = ie->data.pscan_rep_mode;
++ cp.pscan_mode = ie->data.pscan_mode;
++ cp.clock_offset = ie->data.clock_offset |
++ cpu_to_le16(0x8000);
++ }
++
++ memcpy(conn->dev_class, ie->data.dev_class, 3);
++ }
++
++ cp.pkt_type = cpu_to_le16(conn->pkt_type);
++ if (lmp_rswitch_capable(hdev) && !(hdev->link_mode & HCI_LM_MASTER))
++ cp.role_switch = 0x01;
++ else
++ cp.role_switch = 0x00;
++
++ return __hci_cmd_sync_status_sk(hdev, HCI_OP_CREATE_CONN,
++ sizeof(cp), &cp,
++ HCI_EV_CONN_COMPLETE,
++ conn->conn_timeout, NULL);
++}
++
++int hci_connect_acl_sync(struct hci_dev *hdev, struct hci_conn *conn)
++{
++ return hci_cmd_sync_queue_once(hdev, hci_acl_create_conn_sync, conn,
++ NULL);
++}
++
++static void create_le_conn_complete(struct hci_dev *hdev, void *data, int err)
++{
++ struct hci_conn *conn = data;
++
++ bt_dev_dbg(hdev, "err %d", err);
++
++ if (err == -ECANCELED)
++ return;
++
++ hci_dev_lock(hdev);
++
++ if (!hci_conn_valid(hdev, conn))
++ goto done;
++
++ if (!err) {
++ hci_connect_le_scan_cleanup(conn, 0x00);
++ goto done;
++ }
++
++ /* Check if connection is still pending */
++ if (conn != hci_lookup_le_connect(hdev))
++ goto done;
++
++ /* Flush to make sure we send create conn cancel command if needed */
++ flush_delayed_work(&conn->le_conn_timeout);
++ hci_conn_failed(conn, bt_status(err));
++
++done:
++ hci_dev_unlock(hdev);
++}
++
++int hci_connect_le_sync(struct hci_dev *hdev, struct hci_conn *conn)
++{
++ return hci_cmd_sync_queue_once(hdev, hci_le_create_conn_sync, conn,
++ create_le_conn_complete);
++}
++
++int hci_cancel_connect_sync(struct hci_dev *hdev, struct hci_conn *conn)
++{
++ if (conn->state != BT_OPEN)
++ return -EINVAL;
++
++ switch (conn->type) {
++ case ACL_LINK:
++ return !hci_cmd_sync_dequeue_once(hdev,
++ hci_acl_create_conn_sync,
++ conn, NULL);
++ case LE_LINK:
++ return !hci_cmd_sync_dequeue_once(hdev, hci_le_create_conn_sync,
++ conn, create_le_conn_complete);
++ }
++
++ return -ENOENT;
++}
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index a8b05baa8e5a9..fa6c2e95d5542 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -1955,16 +1955,58 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
+
+ ev3 = hci_recv_event_data(hdev, HCI_EV_LE_PER_ADV_REPORT);
+ if (ev3) {
+- size_t base_len = ev3->length;
++ size_t base_len = 0;
+ u8 *base;
++ struct hci_conn *hcon;
+
+ sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
+ iso_match_sync_handle_pa_report, ev3);
+- base = eir_get_service_data(ev3->data, ev3->length,
+- EIR_BAA_SERVICE_UUID, &base_len);
+- if (base && sk && base_len <= sizeof(iso_pi(sk)->base)) {
++ if (!sk)
++ goto done;
++
++ hcon = iso_pi(sk)->conn->hcon;
++ if (!hcon)
++ goto done;
++
++ if (ev3->data_status == LE_PA_DATA_TRUNCATED) {
++ /* The controller was unable to retrieve PA data. */
++ memset(hcon->le_per_adv_data, 0,
++ HCI_MAX_PER_AD_TOT_LEN);
++ hcon->le_per_adv_data_len = 0;
++ hcon->le_per_adv_data_offset = 0;
++ goto done;
++ }
++
++ if (hcon->le_per_adv_data_offset + ev3->length >
++ HCI_MAX_PER_AD_TOT_LEN)
++ goto done;
++
++ memcpy(hcon->le_per_adv_data + hcon->le_per_adv_data_offset,
++ ev3->data, ev3->length);
++ hcon->le_per_adv_data_offset += ev3->length;
++
++ if (ev3->data_status == LE_PA_DATA_COMPLETE) {
++ /* All PA data has been received. */
++ hcon->le_per_adv_data_len =
++ hcon->le_per_adv_data_offset;
++ hcon->le_per_adv_data_offset = 0;
++
++ /* Extract BASE */
++ base = eir_get_service_data(hcon->le_per_adv_data,
++ hcon->le_per_adv_data_len,
++ EIR_BAA_SERVICE_UUID,
++ &base_len);
++
++ if (!base || base_len > BASE_MAX_LENGTH)
++ goto done;
++
+ memcpy(iso_pi(sk)->base, base, base_len);
+ iso_pi(sk)->base_len = base_len;
++ } else {
++ /* This is a PA data fragment. Keep pa_data_len set to 0
++ * until all data has been reassembled.
++ */
++ hcon->le_per_adv_data_len = 0;
+ }
+ } else {
+ sk = iso_get_sock_listen(&hdev->bdaddr, BDADDR_ANY, NULL, NULL);
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 706d2478ddb33..84fc70862d78a 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -6924,7 +6924,7 @@ static void l2cap_chan_by_pid(struct l2cap_chan *chan, void *data)
+ }
+
+ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
+- bdaddr_t *dst, u8 dst_type)
++ bdaddr_t *dst, u8 dst_type, u16 timeout)
+ {
+ struct l2cap_conn *conn;
+ struct hci_conn *hcon;
+@@ -7017,19 +7017,17 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
+
+ if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
+ hcon = hci_connect_le(hdev, dst, dst_type, false,
+- chan->sec_level,
+- HCI_LE_CONN_TIMEOUT,
+- HCI_ROLE_SLAVE);
++ chan->sec_level, timeout,
++ HCI_ROLE_SLAVE, 0, 0);
+ else
+ hcon = hci_connect_le_scan(hdev, dst, dst_type,
+- chan->sec_level,
+- HCI_LE_CONN_TIMEOUT,
++ chan->sec_level, timeout,
+ CONN_REASON_L2CAP_CHAN);
+
+ } else {
+ u8 auth_type = l2cap_get_auth_type(chan);
+ hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type,
+- CONN_REASON_L2CAP_CHAN);
++ CONN_REASON_L2CAP_CHAN, timeout);
+ }
+
+ if (IS_ERR(hcon)) {
+diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
+index 1eeea5d1306c2..5cc83f906c123 100644
+--- a/net/bluetooth/l2cap_sock.c
++++ b/net/bluetooth/l2cap_sock.c
+@@ -254,7 +254,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
+ chan->mode = L2CAP_MODE_LE_FLOWCTL;
+
+ err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid),
+- &la.l2_bdaddr, la.l2_bdaddr_type);
++ &la.l2_bdaddr, la.l2_bdaddr_type,
++ sk->sk_sndtimeo);
+ if (err)
+ return err;
+
+@@ -438,7 +439,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
+ struct l2cap_chan *chan = l2cap_pi(sk)->chan;
+ struct l2cap_options opts;
+ struct l2cap_conninfo cinfo;
+- int len, err = 0;
++ int err = 0;
++ size_t len;
+ u32 opt;
+
+ BT_DBG("sk %p", sk);
+@@ -485,7 +487,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
+
+ BT_DBG("mode 0x%2.2x", chan->mode);
+
+- len = min_t(unsigned int, len, sizeof(opts));
++ len = min(len, sizeof(opts));
+ if (copy_to_user(optval, (char *) &opts, len))
+ err = -EFAULT;
+
+@@ -535,7 +537,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
+ cinfo.hci_handle = chan->conn->hcon->handle;
+ memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
+
+- len = min_t(unsigned int, len, sizeof(cinfo));
++ len = min(len, sizeof(cinfo));
+ if (copy_to_user(optval, (char *) &cinfo, len))
+ err = -EFAULT;
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index 640d6d54ac6ba..b8e05ddeedba9 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -2616,7 +2616,11 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
+ goto failed;
+ }
+
+- err = hci_cmd_sync_queue(hdev, add_uuid_sync, cmd, mgmt_class_complete);
++ /* MGMT_OP_ADD_UUID don't require adapter the UP/Running so use
++ * hci_cmd_sync_submit instead of hci_cmd_sync_queue.
++ */
++ err = hci_cmd_sync_submit(hdev, add_uuid_sync, cmd,
++ mgmt_class_complete);
+ if (err < 0) {
+ mgmt_pending_free(cmd);
+ goto failed;
+@@ -2710,8 +2714,11 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
+ goto unlock;
+ }
+
+- err = hci_cmd_sync_queue(hdev, remove_uuid_sync, cmd,
+- mgmt_class_complete);
++ /* MGMT_OP_REMOVE_UUID don't require adapter the UP/Running so use
++ * hci_cmd_sync_submit instead of hci_cmd_sync_queue.
++ */
++ err = hci_cmd_sync_submit(hdev, remove_uuid_sync, cmd,
++ mgmt_class_complete);
+ if (err < 0)
+ mgmt_pending_free(cmd);
+
+@@ -2777,8 +2784,11 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
+ goto unlock;
+ }
+
+- err = hci_cmd_sync_queue(hdev, set_class_sync, cmd,
+- mgmt_class_complete);
++ /* MGMT_OP_SET_DEV_CLASS don't require adapter the UP/Running so use
++ * hci_cmd_sync_submit instead of hci_cmd_sync_queue.
++ */
++ err = hci_cmd_sync_submit(hdev, set_class_sync, cmd,
++ mgmt_class_complete);
+ if (err < 0)
+ mgmt_pending_free(cmd);
+
+@@ -3436,7 +3446,8 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
+
+ if (cp->addr.type == BDADDR_BREDR) {
+ conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
+- auth_type, CONN_REASON_PAIR_DEVICE);
++ auth_type, CONN_REASON_PAIR_DEVICE,
++ HCI_ACL_CONN_TIMEOUT);
+ } else {
+ u8 addr_type = le_addr_type(cp->addr.type);
+ struct hci_conn_params *p;
+@@ -5467,8 +5478,8 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
+ goto unlock;
+ }
+
+- err = hci_cmd_sync_queue(hdev, mgmt_remove_adv_monitor_sync, cmd,
+- mgmt_remove_adv_monitor_complete);
++ err = hci_cmd_sync_submit(hdev, mgmt_remove_adv_monitor_sync, cmd,
++ mgmt_remove_adv_monitor_complete);
+
+ if (err) {
+ mgmt_pending_remove(cmd);
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index 8e4f39b8601cb..5d03c5440b06f 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -264,7 +264,8 @@ static int sco_connect(struct sock *sk)
+ }
+
+ hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
+- sco_pi(sk)->setting, &sco_pi(sk)->codec);
++ sco_pi(sk)->setting, &sco_pi(sk)->codec,
++ sk->sk_sndtimeo);
+ if (IS_ERR(hcon)) {
+ err = PTR_ERR(hcon);
+ goto unlock;
+@@ -963,7 +964,8 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
+ struct sock *sk = sock->sk;
+ struct sco_options opts;
+ struct sco_conninfo cinfo;
+- int len, err = 0;
++ int err = 0;
++ size_t len;
+
+ BT_DBG("sk %p", sk);
+
+@@ -985,7 +987,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
+
+ BT_DBG("mtu %u", opts.mtu);
+
+- len = min_t(unsigned int, len, sizeof(opts));
++ len = min(len, sizeof(opts));
+ if (copy_to_user(optval, (char *)&opts, len))
+ err = -EFAULT;
+
+@@ -1003,7 +1005,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
+ cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
+ memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
+
+- len = min_t(unsigned int, len, sizeof(cinfo));
++ len = min(len, sizeof(cinfo));
+ if (copy_to_user(optval, (char *)&cinfo, len))
+ err = -EFAULT;
+
+diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
+index 5ad4abfcb7ba3..d415833fce91f 100644
+--- a/net/bridge/br_netlink.c
++++ b/net/bridge/br_netlink.c
+@@ -666,7 +666,7 @@ void br_ifinfo_notify(int event, const struct net_bridge *br,
+ {
+ u32 filter = RTEXT_FILTER_BRVLAN_COMPRESSED;
+
+- return br_info_notify(event, br, port, filter);
++ br_info_notify(event, br, port, filter);
+ }
+
+ /*
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 5e78798456fd8..9cf404e8038a4 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -283,6 +283,7 @@ __u32 sysctl_rmem_max __read_mostly = SK_RMEM_MAX;
+ EXPORT_SYMBOL(sysctl_rmem_max);
+ __u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX;
+ __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX;
++int sysctl_mem_pcpu_rsv __read_mostly = SK_MEMORY_PCPU_RESERVE;
+
+ int sysctl_tstamp_allow_data __read_mostly = 1;
+
+diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
+index 0f0cb1465e089..986f15e5d6c41 100644
+--- a/net/core/sysctl_net_core.c
++++ b/net/core/sysctl_net_core.c
+@@ -30,6 +30,7 @@ static int int_3600 = 3600;
+ static int min_sndbuf = SOCK_MIN_SNDBUF;
+ static int min_rcvbuf = SOCK_MIN_RCVBUF;
+ static int max_skb_frags = MAX_SKB_FRAGS;
++static int min_mem_pcpu_rsv = SK_MEMORY_PCPU_RESERVE;
+
+ static int net_msg_warn; /* Unused, but still a sysctl */
+
+@@ -407,6 +408,14 @@ static struct ctl_table net_core_table[] = {
+ .proc_handler = proc_dointvec_minmax,
+ .extra1 = &min_rcvbuf,
+ },
++ {
++ .procname = "mem_pcpu_rsv",
++ .data = &sysctl_mem_pcpu_rsv,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = proc_dointvec_minmax,
++ .extra1 = &min_mem_pcpu_rsv,
++ },
+ {
+ .procname = "dev_weight",
+ .data = &weight_p,
+diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
+index 2edc8b796a4e7..049c3adeb8504 100644
+--- a/net/ethernet/eth.c
++++ b/net/ethernet/eth.c
+@@ -164,17 +164,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
+ eth = (struct ethhdr *)skb->data;
+ skb_pull_inline(skb, ETH_HLEN);
+
+- if (unlikely(!ether_addr_equal_64bits(eth->h_dest,
+- dev->dev_addr))) {
+- if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) {
+- if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast))
+- skb->pkt_type = PACKET_BROADCAST;
+- else
+- skb->pkt_type = PACKET_MULTICAST;
+- } else {
+- skb->pkt_type = PACKET_OTHERHOST;
+- }
+- }
++ eth_skb_pkt_type(skb, dev);
+
+ /*
+ * Some variants of DSA tagging don't have an ethertype field
+diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
+index e63a3bf996176..437e782b9663b 100644
+--- a/net/ipv4/icmp.c
++++ b/net/ipv4/icmp.c
+@@ -92,6 +92,7 @@
+ #include <net/inet_common.h>
+ #include <net/ip_fib.h>
+ #include <net/l3mdev.h>
++#include <net/addrconf.h>
+
+ /*
+ * Build xmit assembly blocks
+@@ -1032,6 +1033,8 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
+ struct icmp_ext_hdr *ext_hdr, _ext_hdr;
+ struct icmp_ext_echo_iio *iio, _iio;
+ struct net *net = dev_net(skb->dev);
++ struct inet6_dev *in6_dev;
++ struct in_device *in_dev;
+ struct net_device *dev;
+ char buff[IFNAMSIZ];
+ u16 ident_len;
+@@ -1115,10 +1118,15 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
+ /* Fill bits in reply message */
+ if (dev->flags & IFF_UP)
+ status |= ICMP_EXT_ECHOREPLY_ACTIVE;
+- if (__in_dev_get_rcu(dev) && __in_dev_get_rcu(dev)->ifa_list)
++
++ in_dev = __in_dev_get_rcu(dev);
++ if (in_dev && rcu_access_pointer(in_dev->ifa_list))
+ status |= ICMP_EXT_ECHOREPLY_IPV4;
+- if (!list_empty(&rcu_dereference(dev->ip6_ptr)->addr_list))
++
++ in6_dev = __in6_dev_get(dev);
++ if (in6_dev && !list_empty(&in6_dev->addr_list))
+ status |= ICMP_EXT_ECHOREPLY_IPV6;
++
+ dev_put(dev);
+ icmphdr->un.echo.sequence |= htons(status);
+ return true;
+diff --git a/net/ipv4/route.c b/net/ipv4/route.c
+index 15c37c8113fc8..f67d3d6fe9345 100644
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -2166,6 +2166,9 @@ int ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+ int err = -EINVAL;
+ u32 tag = 0;
+
++ if (!in_dev)
++ return -EINVAL;
++
+ if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr))
+ goto martian_source;
+
+diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c
+index 87db432c6bb4a..254d6e3f93fa7 100644
+--- a/net/ipv4/tcp_ao.c
++++ b/net/ipv4/tcp_ao.c
+@@ -1068,6 +1068,7 @@ void tcp_ao_connect_init(struct sock *sk)
+ {
+ struct tcp_sock *tp = tcp_sk(sk);
+ struct tcp_ao_info *ao_info;
++ struct hlist_node *next;
+ union tcp_ao_addr *addr;
+ struct tcp_ao_key *key;
+ int family, l3index;
+@@ -1090,7 +1091,7 @@ void tcp_ao_connect_init(struct sock *sk)
+ l3index = l3mdev_master_ifindex_by_index(sock_net(sk),
+ sk->sk_bound_dev_if);
+
+- hlist_for_each_entry_rcu(key, &ao_info->head, node) {
++ hlist_for_each_entry_safe(key, next, &ao_info->head, node) {
+ if (!tcp_ao_key_cmp(key, l3index, addr, key->prefixlen, family, -1, -1))
+ continue;
+
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index a505ba383863c..40282a34180ca 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -1125,16 +1125,17 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+
+ if (msg->msg_controllen) {
+ err = udp_cmsg_send(sk, msg, &ipc.gso_size);
+- if (err > 0)
++ if (err > 0) {
+ err = ip_cmsg_send(sk, msg, &ipc,
+ sk->sk_family == AF_INET6);
++ connected = 0;
++ }
+ if (unlikely(err < 0)) {
+ kfree(ipc.opt);
+ return err;
+ }
+ if (ipc.opt)
+ free = 1;
+- connected = 0;
+ }
+ if (!ipc.opt) {
+ struct ip_options_rcu *inet_opt;
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index 26d9bd287b234..8c14c4cc82ff7 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -1476,9 +1476,11 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ ipc6.opt = opt;
+
+ err = udp_cmsg_send(sk, msg, &ipc6.gso_size);
+- if (err > 0)
++ if (err > 0) {
+ err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, fl6,
+ &ipc6);
++ connected = false;
++ }
+ if (err < 0) {
+ fl6_sock_release(flowlabel);
+ return err;
+@@ -1490,7 +1492,6 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ }
+ if (!(opt->opt_nflen|opt->opt_flen))
+ opt = NULL;
+- connected = false;
+ }
+ if (!opt) {
+ opt = txopt_get(np);
+diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
+index fccbcde3359af..3d4806b7ff6c4 100644
+--- a/net/mac80211/mesh.c
++++ b/net/mac80211/mesh.c
+@@ -769,6 +769,9 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, u32 ctrl_flags)
+ {
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
++ struct ieee80211_mesh_fast_tx_key key = {
++ .type = MESH_FAST_TX_TYPE_LOCAL
++ };
+ struct ieee80211_mesh_fast_tx *entry;
+ struct ieee80211s_hdr *meshhdr;
+ u8 sa[ETH_ALEN] __aligned(2);
+@@ -804,7 +807,10 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
+ return false;
+ }
+
+- entry = mesh_fast_tx_get(sdata, skb->data);
++ ether_addr_copy(key.addr, skb->data);
++ if (!ether_addr_equal(skb->data + ETH_ALEN, sdata->vif.addr))
++ key.type = MESH_FAST_TX_TYPE_PROXIED;
++ entry = mesh_fast_tx_get(sdata, &key);
+ if (!entry)
+ return false;
+
+diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
+index ad8469293d712..58c619874ca6a 100644
+--- a/net/mac80211/mesh.h
++++ b/net/mac80211/mesh.h
+@@ -133,10 +133,39 @@ struct mesh_path {
+ #define MESH_FAST_TX_CACHE_THRESHOLD_SIZE 384
+ #define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */
+
++/**
++ * enum ieee80211_mesh_fast_tx_type - cached mesh fast tx entry type
++ *
++ * @MESH_FAST_TX_TYPE_LOCAL: tx from the local vif address as SA
++ * @MESH_FAST_TX_TYPE_PROXIED: local tx with a different SA (e.g. bridged)
++ * @MESH_FAST_TX_TYPE_FORWARDED: forwarded from a different mesh point
++ * @NUM_MESH_FAST_TX_TYPE: number of entry types
++ */
++enum ieee80211_mesh_fast_tx_type {
++ MESH_FAST_TX_TYPE_LOCAL,
++ MESH_FAST_TX_TYPE_PROXIED,
++ MESH_FAST_TX_TYPE_FORWARDED,
++
++ /* must be last */
++ NUM_MESH_FAST_TX_TYPE
++};
++
++
++/**
++ * struct ieee80211_mesh_fast_tx_key - cached mesh fast tx entry key
++ *
++ * @addr: The Ethernet DA for this entry
++ * @type: cache entry type
++ */
++struct ieee80211_mesh_fast_tx_key {
++ u8 addr[ETH_ALEN] __aligned(2);
++ u16 type;
++};
++
+ /**
+ * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry
+ * @rhash: rhashtable pointer
+- * @addr_key: The Ethernet DA which is the key for this entry
++ * @key: the lookup key for this cache entry
+ * @fast_tx: base fast_tx data
+ * @hdr: cached mesh and rfc1042 headers
+ * @hdrlen: length of mesh + rfc1042
+@@ -147,7 +176,7 @@ struct mesh_path {
+ */
+ struct ieee80211_mesh_fast_tx {
+ struct rhash_head rhash;
+- u8 addr_key[ETH_ALEN] __aligned(2);
++ struct ieee80211_mesh_fast_tx_key key;
+
+ struct ieee80211_fast_tx fast_tx;
+ u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)];
+@@ -333,7 +362,8 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata);
+
+ bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
+ struct ieee80211_mesh_fast_tx *
+-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr);
++mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
++ struct ieee80211_mesh_fast_tx_key *key);
+ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, u32 ctrl_flags);
+ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
+diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
+index 735edde1bd819..a6b62169f0848 100644
+--- a/net/mac80211/mesh_pathtbl.c
++++ b/net/mac80211/mesh_pathtbl.c
+@@ -37,8 +37,8 @@ static const struct rhashtable_params mesh_rht_params = {
+ static const struct rhashtable_params fast_tx_rht_params = {
+ .nelem_hint = 10,
+ .automatic_shrinking = true,
+- .key_len = ETH_ALEN,
+- .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key),
++ .key_len = sizeof_field(struct ieee80211_mesh_fast_tx, key),
++ .key_offset = offsetof(struct ieee80211_mesh_fast_tx, key),
+ .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash),
+ .hashfn = mesh_table_hash,
+ };
+@@ -431,20 +431,21 @@ static void mesh_fast_tx_entry_free(struct mesh_tx_cache *cache,
+ }
+
+ struct ieee80211_mesh_fast_tx *
+-mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr)
++mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata,
++ struct ieee80211_mesh_fast_tx_key *key)
+ {
+ struct ieee80211_mesh_fast_tx *entry;
+ struct mesh_tx_cache *cache;
+
+ cache = &sdata->u.mesh.tx_cache;
+- entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
++ entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
+ if (!entry)
+ return NULL;
+
+ if (!(entry->mpath->flags & MESH_PATH_ACTIVE) ||
+ mpath_expired(entry->mpath)) {
+ spin_lock_bh(&cache->walk_lock);
+- entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params);
++ entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
+ if (entry)
+ mesh_fast_tx_entry_free(cache, entry);
+ spin_unlock_bh(&cache->walk_lock);
+@@ -489,18 +490,24 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
+ if (!sta)
+ return;
+
++ build.key.type = MESH_FAST_TX_TYPE_LOCAL;
+ if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
+ /* This is required to keep the mppath alive */
+ mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
+ if (!mppath)
+ return;
+ build.mppath = mppath;
++ if (!ether_addr_equal(meshhdr->eaddr2, sdata->vif.addr))
++ build.key.type = MESH_FAST_TX_TYPE_PROXIED;
+ } else if (ieee80211_has_a4(hdr->frame_control)) {
+ mppath = mpath;
+ } else {
+ return;
+ }
+
++ if (!ether_addr_equal(hdr->addr4, sdata->vif.addr))
++ build.key.type = MESH_FAST_TX_TYPE_FORWARDED;
++
+ /* rate limit, in case fast xmit can't be enabled */
+ if (mppath->fast_tx_check == jiffies)
+ return;
+@@ -547,7 +554,7 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
+ }
+ }
+
+- memcpy(build.addr_key, mppath->dst, ETH_ALEN);
++ memcpy(build.key.addr, mppath->dst, ETH_ALEN);
+ build.timestamp = jiffies;
+ build.fast_tx.band = info->band;
+ build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3);
+@@ -600,11 +607,10 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
+ void mesh_fast_tx_gc(struct ieee80211_sub_if_data *sdata)
+ {
+ unsigned long timeout = msecs_to_jiffies(MESH_FAST_TX_CACHE_TIMEOUT);
+- struct mesh_tx_cache *cache;
++ struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
+ struct ieee80211_mesh_fast_tx *entry;
+ struct hlist_node *n;
+
+- cache = &sdata->u.mesh.tx_cache;
+ if (atomic_read(&cache->rht.nelems) < MESH_FAST_TX_CACHE_THRESHOLD_SIZE)
+ return;
+
+@@ -622,7 +628,6 @@ void mesh_fast_tx_flush_mpath(struct mesh_path *mpath)
+ struct ieee80211_mesh_fast_tx *entry;
+ struct hlist_node *n;
+
+- cache = &sdata->u.mesh.tx_cache;
+ spin_lock_bh(&cache->walk_lock);
+ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
+ if (entry->mpath == mpath)
+@@ -637,7 +642,6 @@ void mesh_fast_tx_flush_sta(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mesh_fast_tx *entry;
+ struct hlist_node *n;
+
+- cache = &sdata->u.mesh.tx_cache;
+ spin_lock_bh(&cache->walk_lock);
+ hlist_for_each_entry_safe(entry, n, &cache->walk_head, walk_list)
+ if (rcu_access_pointer(entry->mpath->next_hop) == sta)
+@@ -649,13 +653,18 @@ void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata,
+ const u8 *addr)
+ {
+ struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache;
++ struct ieee80211_mesh_fast_tx_key key = {};
+ struct ieee80211_mesh_fast_tx *entry;
++ int i;
+
+- cache = &sdata->u.mesh.tx_cache;
++ ether_addr_copy(key.addr, addr);
+ spin_lock_bh(&cache->walk_lock);
+- entry = rhashtable_lookup_fast(&cache->rht, addr, fast_tx_rht_params);
+- if (entry)
+- mesh_fast_tx_entry_free(cache, entry);
++ for (i = 0; i < NUM_MESH_FAST_TX_TYPE; i++) {
++ key.type = i;
++ entry = rhashtable_lookup_fast(&cache->rht, &key, fast_tx_rht_params);
++ if (entry)
++ mesh_fast_tx_entry_free(cache, entry);
++ }
+ spin_unlock_bh(&cache->walk_lock);
+ }
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 20d863370796d..94028b541beba 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -5848,7 +5848,7 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata,
+ */
+ if (control &
+ IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT)
+- link_removal_timeout[link_id] = le16_to_cpu(*(__le16 *)pos);
++ link_removal_timeout[link_id] = get_unaligned_le16(pos);
+ }
+
+ removed_links &= sdata->vif.valid_links;
+@@ -5873,8 +5873,11 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata,
+ continue;
+ }
+
+- link_delay = link_conf->beacon_int *
+- link_removal_timeout[link_id];
++ if (link_removal_timeout[link_id] < 1)
++ link_delay = 0;
++ else
++ link_delay = link_conf->beacon_int *
++ (link_removal_timeout[link_id] - 1);
+
+ if (!delay)
+ delay = link_delay;
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index 0bf72928ccfca..541b0f53c6c35 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2746,7 +2746,10 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
+ struct sk_buff *skb, int hdrlen)
+ {
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+- struct ieee80211_mesh_fast_tx *entry = NULL;
++ struct ieee80211_mesh_fast_tx_key key = {
++ .type = MESH_FAST_TX_TYPE_FORWARDED
++ };
++ struct ieee80211_mesh_fast_tx *entry;
+ struct ieee80211s_hdr *mesh_hdr;
+ struct tid_ampdu_tx *tid_tx;
+ struct sta_info *sta;
+@@ -2755,9 +2758,13 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata,
+
+ mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth));
+ if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6)
+- entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1);
++ ether_addr_copy(key.addr, mesh_hdr->eaddr1);
+ else if (!(mesh_hdr->flags & MESH_FLAGS_AE))
+- entry = mesh_fast_tx_get(sdata, skb->data);
++ ether_addr_copy(key.addr, skb->data);
++ else
++ return false;
++
++ entry = mesh_fast_tx_get(sdata, &key);
+ if (!entry)
+ return false;
+
+diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
+index a0921adc31a9f..1e689c7141271 100644
+--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
++++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
+@@ -126,7 +126,8 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ if (sctph->source != cp->vport || payload_csum ||
+ skb->ip_summed == CHECKSUM_PARTIAL) {
+ sctph->source = cp->vport;
+- sctp_nat_csum(skb, sctph, sctphoff);
++ if (!skb_is_gso(skb) || !skb_is_gso_sctp(skb))
++ sctp_nat_csum(skb, sctph, sctphoff);
+ } else {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+@@ -174,7 +175,8 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ (skb->ip_summed == CHECKSUM_PARTIAL &&
+ !(skb_dst(skb)->dev->features & NETIF_F_SCTP_CRC))) {
+ sctph->dest = cp->dport;
+- sctp_nat_csum(skb, sctph, sctphoff);
++ if (!skb_is_gso(skb) || !skb_is_gso_sctp(skb))
++ sctp_nat_csum(skb, sctph, sctphoff);
+ } else if (skb->ip_summed != CHECKSUM_PARTIAL) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+diff --git a/net/netfilter/nft_chain_filter.c b/net/netfilter/nft_chain_filter.c
+index 274b6f7e6bb57..d170758a1eb5d 100644
+--- a/net/netfilter/nft_chain_filter.c
++++ b/net/netfilter/nft_chain_filter.c
+@@ -338,7 +338,9 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev,
+ return;
+
+ if (n > 1) {
+- nf_unregister_net_hook(ctx->net, &found->ops);
++ if (!(ctx->chain->table->flags & NFT_TABLE_F_DORMANT))
++ nf_unregister_net_hook(ctx->net, &found->ops);
++
+ list_del_rcu(&found->list);
+ kfree_rcu(found, rcu);
+ return;
+diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
+index 74b63cdb59923..2928c142a2ddb 100644
+--- a/net/openvswitch/conntrack.c
++++ b/net/openvswitch/conntrack.c
+@@ -1593,9 +1593,9 @@ static void ovs_ct_limit_exit(struct net *net, struct ovs_net *ovs_net)
+ for (i = 0; i < CT_LIMIT_HASH_BUCKETS; ++i) {
+ struct hlist_head *head = &info->limits[i];
+ struct ovs_ct_limit *ct_limit;
++ struct hlist_node *next;
+
+- hlist_for_each_entry_rcu(ct_limit, head, hlist_node,
+- lockdep_ovsl_is_held())
++ hlist_for_each_entry_safe(ct_limit, next, head, hlist_node)
+ kfree_rcu(ct_limit, rcu);
+ }
+ kfree(info->limits);
+diff --git a/net/tls/tls.h b/net/tls/tls.h
+index 762f424ff2d59..e5e47452308ab 100644
+--- a/net/tls/tls.h
++++ b/net/tls/tls.h
+@@ -215,7 +215,7 @@ static inline struct sk_buff *tls_strp_msg(struct tls_sw_context_rx *ctx)
+
+ static inline bool tls_strp_msg_ready(struct tls_sw_context_rx *ctx)
+ {
+- return ctx->strp.msg_ready;
++ return READ_ONCE(ctx->strp.msg_ready);
+ }
+
+ static inline bool tls_strp_msg_mixed_decrypted(struct tls_sw_context_rx *ctx)
+diff --git a/net/tls/tls_strp.c b/net/tls/tls_strp.c
+index ca1e0e198ceb4..5df08d848b5c9 100644
+--- a/net/tls/tls_strp.c
++++ b/net/tls/tls_strp.c
+@@ -360,7 +360,7 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb,
+ if (strp->stm.full_len && strp->stm.full_len == skb->len) {
+ desc->count = 0;
+
+- strp->msg_ready = 1;
++ WRITE_ONCE(strp->msg_ready, 1);
+ tls_rx_msg_ready(strp);
+ }
+
+@@ -528,7 +528,7 @@ static int tls_strp_read_sock(struct tls_strparser *strp)
+ if (!tls_strp_check_queue_ok(strp))
+ return tls_strp_read_copy(strp, false);
+
+- strp->msg_ready = 1;
++ WRITE_ONCE(strp->msg_ready, 1);
+ tls_rx_msg_ready(strp);
+
+ return 0;
+@@ -580,7 +580,7 @@ void tls_strp_msg_done(struct tls_strparser *strp)
+ else
+ tls_strp_flush_anchor_copy(strp);
+
+- strp->msg_ready = 0;
++ WRITE_ONCE(strp->msg_ready, 0);
+ memset(&strp->stm, 0, sizeof(strp->stm));
+
+ tls_strp_check_rcv(strp);
+diff --git a/net/unix/garbage.c b/net/unix/garbage.c
+index 8734c0c1fc197..2a758531e1027 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -260,7 +260,7 @@ void unix_gc(void)
+ __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
+
+ if (sk->sk_state == TCP_LISTEN) {
+- unix_state_lock(sk);
++ unix_state_lock_nested(sk, U_LOCK_GC_LISTENER);
+ unix_state_unlock(sk);
+ }
+ }
+diff --git a/rust/Makefile b/rust/Makefile
+index 9d2a16cc91cb4..cd9e5e3fcee86 100644
+--- a/rust/Makefile
++++ b/rust/Makefile
+@@ -175,7 +175,6 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
+ mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
+ OBJTREE=$(abspath $(objtree)) \
+ $(RUSTDOC) --test $(rust_flags) \
+- @$(objtree)/include/generated/rustc_cfg \
+ -L$(objtree)/$(obj) --extern alloc --extern kernel \
+ --extern build_error --extern macros \
+ --extern bindings --extern uapi \
+diff --git a/rust/kernel/init.rs b/rust/kernel/init.rs
+index 65be9ae57b80b..cf9575f156a63 100644
+--- a/rust/kernel/init.rs
++++ b/rust/kernel/init.rs
+@@ -1292,8 +1292,15 @@ macro_rules! impl_zeroable {
+ i8, i16, i32, i64, i128, isize,
+ f32, f64,
+
+- // SAFETY: These are ZSTs, there is nothing to zero.
+- {<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, Infallible, (),
++ // Note: do not add uninhabited types (such as `!` or `core::convert::Infallible`) to this list;
++ // creating an instance of an uninhabited type is immediate undefined behavior. For more on
++ // uninhabited/empty types, consult The Rustonomicon:
++ // <https://doc.rust-lang.org/stable/nomicon/exotic-sizes.html#empty-types>. The Rust Reference
++ // also has information on undefined behavior:
++ // <https://doc.rust-lang.org/stable/reference/behavior-considered-undefined.html>.
++ //
++ // SAFETY: These are inhabited ZSTs; there is nothing to zero and a valid value exists.
++ {<T: ?Sized>} PhantomData<T>, core::marker::PhantomPinned, (),
+
+ // SAFETY: Type is allowed to take any value, including all zeros.
+ {<T>} MaybeUninit<T>,
+diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
+index 7ac39874aeac3..75efe47522e4f 100644
+--- a/rust/kernel/lib.rs
++++ b/rust/kernel/lib.rs
+@@ -66,7 +66,7 @@
+ /// The top level entrypoint to implementing a kernel module.
+ ///
+ /// For any teardown or cleanup operations, your type may implement [`Drop`].
+-pub trait Module: Sized + Sync {
++pub trait Module: Sized + Sync + Send {
+ /// Called at module initialization time.
+ ///
+ /// Use this method to perform whatever setup or registration your module
+diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
+index e457b3c7cb2fc..869797745b82a 100644
+--- a/rust/kernel/net/phy.rs
++++ b/rust/kernel/net/phy.rs
+@@ -640,6 +640,10 @@ pub struct Registration {
+ drivers: Pin<&'static mut [DriverVTable]>,
+ }
+
++// SAFETY: The only action allowed in a `Registration` instance is dropping it, which is safe to do
++// from any thread because `phy_drivers_unregister` can be called from any thread context.
++unsafe impl Send for Registration {}
++
+ impl Registration {
+ /// Registers a PHY driver.
+ pub fn register(
+diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
+index f489f31573832..520eae5fd7928 100644
+--- a/rust/macros/lib.rs
++++ b/rust/macros/lib.rs
+@@ -35,18 +35,6 @@
+ /// author: "Rust for Linux Contributors",
+ /// description: "My very own kernel module!",
+ /// license: "GPL",
+-/// params: {
+-/// my_i32: i32 {
+-/// default: 42,
+-/// permissions: 0o000,
+-/// description: "Example of i32",
+-/// },
+-/// writeable_i32: i32 {
+-/// default: 42,
+-/// permissions: 0o644,
+-/// description: "Example of i32",
+-/// },
+-/// },
+ /// }
+ ///
+ /// struct MyModule;
+diff --git a/scripts/Makefile.build b/scripts/Makefile.build
+index dae447a1ad30c..1633175846dfc 100644
+--- a/scripts/Makefile.build
++++ b/scripts/Makefile.build
+@@ -272,7 +272,7 @@ rust_common_cmd = \
+ -Zallow-features=$(rust_allowed_features) \
+ -Zcrate-attr=no_std \
+ -Zcrate-attr='feature($(rust_allowed_features))' \
+- --extern alloc --extern kernel \
++ -Zunstable-options --extern force:alloc --extern kernel \
+ --crate-type rlib -L $(objtree)/rust/ \
+ --crate-name $(basename $(notdir $@)) \
+ --sysroot=/dev/null \
+diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py
+index 1e10512b2117c..571c2e218993f 100644
+--- a/tools/net/ynl/lib/ynl.py
++++ b/tools/net/ynl/lib/ynl.py
+@@ -208,6 +208,7 @@ class NlMsg:
+ self.done = 1
+ extack_off = 20
+ elif self.nl_type == Netlink.NLMSG_DONE:
++ self.error = struct.unpack("i", self.raw[0:4])[0]
+ self.done = 1
+ extack_off = 4
+
+diff --git a/tools/testing/selftests/riscv/hwprobe/cbo.c b/tools/testing/selftests/riscv/hwprobe/cbo.c
+index c537d52fafc58..a40541bb7c7de 100644
+--- a/tools/testing/selftests/riscv/hwprobe/cbo.c
++++ b/tools/testing/selftests/riscv/hwprobe/cbo.c
+@@ -19,7 +19,7 @@
+ #include "hwprobe.h"
+ #include "../../kselftest.h"
+
+-#define MK_CBO(fn) cpu_to_le32((fn) << 20 | 10 << 15 | 2 << 12 | 0 << 7 | 15)
++#define MK_CBO(fn) le32_bswap((uint32_t)(fn) << 20 | 10 << 15 | 2 << 12 | 0 << 7 | 15)
+
+ static char mem[4096] __aligned(4096) = { [0 ... 4095] = 0xa5 };
+
+diff --git a/tools/testing/selftests/riscv/hwprobe/hwprobe.h b/tools/testing/selftests/riscv/hwprobe/hwprobe.h
+index e3fccb390c4dc..f3de970c32227 100644
+--- a/tools/testing/selftests/riscv/hwprobe/hwprobe.h
++++ b/tools/testing/selftests/riscv/hwprobe/hwprobe.h
+@@ -4,6 +4,16 @@
+ #include <stddef.h>
+ #include <asm/hwprobe.h>
+
++#if __BYTE_ORDER == __BIG_ENDIAN
++# define le32_bswap(_x) \
++ ((((_x) & 0x000000ffU) << 24) | \
++ (((_x) & 0x0000ff00U) << 8) | \
++ (((_x) & 0x00ff0000U) >> 8) | \
++ (((_x) & 0xff000000U) >> 24))
++#else
++# define le32_bswap(_x) (_x)
++#endif
++
+ /*
+ * Rather than relying on having a new enough libc to define this, just do it
+ * ourselves. This way we don't need to be coupled to a new-enough libc to
+diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
+index 38f6514699682..cacf6507f6905 100644
+--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
++++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
+@@ -784,7 +784,7 @@ void *kill_thread(void *data)
+ bool die = (bool)data;
+
+ if (die) {
+- prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
++ syscall(__NR_getpid);
+ return (void *)SIBLING_EXIT_FAILURE;
+ }
+
+@@ -803,11 +803,11 @@ void kill_thread_or_group(struct __test_metadata *_metadata,
+ {
+ pthread_t thread;
+ void *status;
+- /* Kill only when calling __NR_prctl. */
++ /* Kill only when calling __NR_getpid. */
+ struct sock_filter filter_thread[] = {
+ BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+ offsetof(struct seccomp_data, nr)),
+- BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
++ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
+ BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD),
+ BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+ };
+@@ -819,7 +819,7 @@ void kill_thread_or_group(struct __test_metadata *_metadata,
+ struct sock_filter filter_process[] = {
+ BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
+ offsetof(struct seccomp_data, nr)),
+- BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_prctl, 0, 1),
++ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getpid, 0, 1),
+ BPF_STMT(BPF_RET|BPF_K, kill),
+ BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
+ };
+@@ -3709,7 +3709,12 @@ TEST(user_notification_sibling_pid_ns)
+ ASSERT_GE(pid, 0);
+
+ if (pid == 0) {
+- ASSERT_EQ(unshare(CLONE_NEWPID), 0);
++ ASSERT_EQ(unshare(CLONE_NEWPID), 0) {
++ if (errno == EPERM)
++ SKIP(return, "CLONE_NEWPID requires CAP_SYS_ADMIN");
++ else if (errno == EINVAL)
++ SKIP(return, "CLONE_NEWPID is invalid (missing CONFIG_PID_NS?)");
++ }
+
+ pid2 = fork();
+ ASSERT_GE(pid2, 0);
+@@ -3727,6 +3732,8 @@ TEST(user_notification_sibling_pid_ns)
+ ASSERT_EQ(unshare(CLONE_NEWPID), 0) {
+ if (errno == EPERM)
+ SKIP(return, "CLONE_NEWPID requires CAP_SYS_ADMIN");
++ else if (errno == EINVAL)
++ SKIP(return, "CLONE_NEWPID is invalid (missing CONFIG_PID_NS?)");
+ }
+ ASSERT_EQ(errno, 0);
+
+@@ -4037,6 +4044,16 @@ TEST(user_notification_filter_empty_threaded)
+ EXPECT_GT((pollfd.revents & POLLHUP) ?: 0, 0);
+ }
+
++
++int get_next_fd(int prev_fd)
++{
++ for (int i = prev_fd + 1; i < FD_SETSIZE; ++i) {
++ if (fcntl(i, F_GETFD) == -1)
++ return i;
++ }
++ _exit(EXIT_FAILURE);
++}
++
+ TEST(user_notification_addfd)
+ {
+ pid_t pid;
+@@ -4053,7 +4070,7 @@ TEST(user_notification_addfd)
+ /* There may be arbitrary already-open fds at test start. */
+ memfd = memfd_create("test", 0);
+ ASSERT_GE(memfd, 0);
+- nextfd = memfd + 1;
++ nextfd = get_next_fd(memfd);
+
+ ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+ ASSERT_EQ(0, ret) {
+@@ -4064,7 +4081,8 @@ TEST(user_notification_addfd)
+ /* Check that the basic notification machinery works */
+ listener = user_notif_syscall(__NR_getppid,
+ SECCOMP_FILTER_FLAG_NEW_LISTENER);
+- ASSERT_EQ(listener, nextfd++);
++ ASSERT_EQ(listener, nextfd);
++ nextfd = get_next_fd(nextfd);
+
+ pid = fork();
+ ASSERT_GE(pid, 0);
+@@ -4119,14 +4137,16 @@ TEST(user_notification_addfd)
+
+ /* Verify we can set an arbitrary remote fd */
+ fd = ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd);
+- EXPECT_EQ(fd, nextfd++);
++ EXPECT_EQ(fd, nextfd);
++ nextfd = get_next_fd(nextfd);
+ EXPECT_EQ(filecmp(getpid(), pid, memfd, fd), 0);
+
+ /* Verify we can set an arbitrary remote fd with large size */
+ memset(&big, 0x0, sizeof(big));
+ big.addfd = addfd;
+ fd = ioctl(listener, SECCOMP_IOCTL_NOTIF_ADDFD_BIG, &big);
+- EXPECT_EQ(fd, nextfd++);
++ EXPECT_EQ(fd, nextfd);
++ nextfd = get_next_fd(nextfd);
+
+ /* Verify we can set a specific remote fd */
+ addfd.newfd = 42;
+@@ -4164,7 +4184,8 @@ TEST(user_notification_addfd)
+ * Child has earlier "low" fds and now 42, so we expect the next
+ * lowest available fd to be assigned here.
+ */
+- EXPECT_EQ(fd, nextfd++);
++ EXPECT_EQ(fd, nextfd);
++ nextfd = get_next_fd(nextfd);
+ ASSERT_EQ(filecmp(getpid(), pid, memfd, fd), 0);
+
+ /*
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-05-05 18:01 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-05-05 18:01 UTC (permalink / raw
To: gentoo-commits
commit: 54d1b8f05b1a9bb154b528bda020c5c1b9143e51
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sun May 5 18:00:38 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sun May 5 18:00:38 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=54d1b8f0
Default alternate schedulars (ALT_SCHED=n)
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 ++++
5021_BMQ-and-PDS-gentoo-defaults.patch | 13 +++++++++++++
2 files changed, 17 insertions(+)
diff --git a/0000_README b/0000_README
index f9626b92..bb655415 100644
--- a/0000_README
+++ b/0000_README
@@ -122,3 +122,7 @@ Desc: Kernel >= 5.15 patch enables gcc = v11.1+ optimizations for additional C
Patch: 5020_BMQ-and-PDS-io-scheduler-v6.8-r6.patch
From: https://gitlab.com/alfredchen/projectc
Desc: BMQ(BitMap Queue) Scheduler. A new CPU scheduler developed from PDS(incld). Inspired by the scheduler in zircon.
+
+Patch: 5021_BMQ-and-PDS-gentoo-defaults.patch
+From: https://gitweb.gentoo.org/proj/linux-patches.git/
+Desc: Set defaults for BMQ. default to n
diff --git a/5021_BMQ-and-PDS-gentoo-defaults.patch b/5021_BMQ-and-PDS-gentoo-defaults.patch
new file mode 100644
index 00000000..6dc48eec
--- /dev/null
+++ b/5021_BMQ-and-PDS-gentoo-defaults.patch
@@ -0,0 +1,13 @@
+--- a/init/Kconfig 2023-02-13 08:16:09.534315265 -0500
++++ b/init/Kconfig 2023-02-13 08:17:24.130237204 -0500
+@@ -867,8 +867,9 @@ config UCLAMP_BUCKETS_COUNT
+ If in doubt, use the default value.
+
+ menuconfig SCHED_ALT
++ depends on X86_64
+ bool "Alternative CPU Schedulers"
+- default y
++ default n
+ help
+ This feature enable alternative CPU scheduler"
+
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-05-05 18:02 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-05-05 18:02 UTC (permalink / raw
To: gentoo-commits
commit: 9dcf8bea816a2e0a4ee33c00c855bd27a5253e7f
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sun May 5 17:54:13 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sun May 5 18:01:54 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=9dcf8bea
Update to KSPP patch
Bug: https://bugs.gentoo.org/930733
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
4567_distro-Gentoo-Kconfig.patch | 33 +++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/4567_distro-Gentoo-Kconfig.patch b/4567_distro-Gentoo-Kconfig.patch
index 6134393f..87b8fa95 100644
--- a/4567_distro-Gentoo-Kconfig.patch
+++ b/4567_distro-Gentoo-Kconfig.patch
@@ -6,9 +6,9 @@
source "Documentation/Kconfig"
+
+source "distro/Kconfig"
---- /dev/null 2024-04-27 13:10:54.188000027 -0400
-+++ b/distro/Kconfig 2024-04-27 17:56:56.723132353 -0400
-@@ -0,0 +1,295 @@
+--- /dev/null 2024-05-05 10:40:37.103999988 -0400
++++ b/distro/Kconfig 2024-05-05 13:37:37.699554927 -0400
+@@ -0,0 +1,310 @@
+menu "Gentoo Linux"
+
+config GENTOO_LINUX
@@ -178,7 +178,7 @@
+ to unmet dependencies. Search for GENTOO_KERNEL_SELF_PROTECTION_COMMON and search for
+ GENTOO_KERNEL_SELF_PROTECTION_{X86_64, ARM64, X86_32, ARM} for dependency information on your
+ specific architecture.
-+ Note 2: Please see the URL above for numeric settings, e.g. CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
++ Note 2: Please see the URL above for numeric settings, e.g. CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
+ for X86_64
+
+if GENTOO_KERNEL_SELF_PROTECTION
@@ -201,10 +201,13 @@
+ select DEBUG_SG
+ select HARDENED_USERCOPY if HAVE_HARDENED_USERCOPY_ALLOCATOR=y
+ select KFENCE if HAVE_ARCH_KFENCE && (!SLAB || SLUB)
++ select PAGE_TABLE_CHECK if ARCH_SUPPORTS_PAGE_TABLE_CHECK=y && EXCLUSIVE_SYSTEM_RAM=y
++ select PAGE_TABLE_CHECK_ENFORCED if PAGE_TABLE_CHECK=y
+ select RANDOMIZE_KSTACK_OFFSET_DEFAULT if HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET && (INIT_STACK_NONE || !CC_IS_CLANG || CLANG_VERSION>=140000)
+ select SECURITY_LANDLOCK
+ select SCHED_CORE if SCHED_SMT
+ select BUG_ON_DATA_CORRUPTION
++ select RANDOM_KMALLOC_CACHE if SLUB_TINY=n
+ select SCHED_STACK_END_CHECK
+ select SECCOMP if HAVE_ARCH_SECCOMP
+ select SECCOMP_FILTER if HAVE_ARCH_SECCOMP_FILTER
@@ -245,11 +248,13 @@
+ default n
+
+ select GCC_PLUGIN_STACKLEAK
++ select X86_KERNEL_IBT if CC_HAS_IBT=y && HAVE_OBJTOOL=y && (!LD_IS_LLD=n || LLD_VERSION>=140000)
+ select LEGACY_VSYSCALL_NONE
+ select PAGE_TABLE_ISOLATION
+ select RANDOMIZE_BASE
+ select RANDOMIZE_MEMORY
+ select RELOCATABLE
++ select X86_USER_SHADOW_STACK if AS_WRUSS=Y
+ select VMAP_STACK
+
+
@@ -259,11 +264,21 @@
+ depends on ARM64
+ default n
+
-+ select RANDOMIZE_BASE
-+ select RELOCATABLE
++ select ARM64_BTI
++ select ARM64_E0PD
++ select ARM64_EPAN if ARM64_PAN=y
++ select ARM64_MTE if (ARM64_AS_HAS_MTE=y && ARM64_TAGGED_ADDR_ABI=y ) && ( AS_HAS_ARMV8_5=y ) && ( AS_HAS_LSE_ATOMICS=y ) && ( ARM64_PAN=y )
++ select ARM64_PTR_AUTH
++ select ARM64_PTR_AUTH_KERNEL if ( ARM64_PTR_AUTH=y ) && (( CC_HAS_SIGN_RETURN_ADDRESS=y || CC_HAS_BRANCH_PROT_PAC_RET=y ) && AS_HAS_ARMV8_3=y ) && ( LD_IS_LLD=y || LD_VERSION >= 23301 || ( CC_IS_GCC=y && GCC_VERSION < 90100 )) && (CC_IS_CLANG=n || AS_HAS_CFI_NEGATE_RA_STATE=y ) && ((FUNCTION_GRAPH_TRACER=n || DYNAMIC_FTRACE_WITH_ARGS=y ))
++ select ARM64_BTI_KERNEL if ( ARM64_BTI=y ) && ( ARM64_PTR_AUTH_KERNEL=y ) && ( CC_HAS_BRANCH_PROT_PAC_RET_BTI=y ) && (CC_IS_GCC=n || GCC_VERSION >= 100100 ) && (CC_IS_GCC=n ) && ((FUNCTION_GRAPH_TRACE=n || DYNAMIC_FTRACE_WITH_ARG=y ))
+ select ARM64_SW_TTBR0_PAN
+ select CONFIG_UNMAP_KERNEL_AT_EL0
+ select GCC_PLUGIN_STACKLEAK
++ select KASAN_HW_TAGS if HAVE_ARCH_KASAN_HW_TAGS=y
++ select RANDOMIZE_BASE
++ select RELOCATABLE
++ select SHADOW_CALL_STACK if ARCH_SUPPORTS_SHADOW_CALL_STACK=y && (DYNAMIC_FTRACE_WITH_ARGS=y || DYNAMIC_FTRACE_WITH_REGS=y || FUNCTION_GRAPH_TRACER=n) && MMU=y
++ select UNWIND_PATCH_PAC_INTO_SCS if (CC_IS_CLANG=y && CLANG_VERSION >= CONFIG_150000 ) && ( ARM64_PTR_AUTH_KERNEL=y && CC_HAS_BRANCH_PROT_PAC_RET=y ) && ( SHADOW_CALL_STACK=y )
+ select VMAP_STACK
+
+config GENTOO_KERNEL_SELF_PROTECTION_X86_32
@@ -304,12 +319,6 @@
+ See the settings that become available for more details and fine-tuning.
+
+endmenu
-From bd3ff0b16792c18c0614c2b95e148943209f460a Mon Sep 17 00:00:00 2001
-From: Georgy Yakovlev <gyakovlev@gentoo.org>
-Date: Tue, 8 Jun 2021 13:59:57 -0700
-Subject: [PATCH 2/2] set DEFAULT_MMAP_MIN_ADDR by default
-
----
mm/Kconfig | 2 ++
1 file changed, 2 insertions(+)
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-05-17 11:34 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-05-17 11:34 UTC (permalink / raw
To: gentoo-commits
commit: 264afa5628b9c804e1a2f6eeb672729373f5ac04
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Fri May 17 11:33:51 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Fri May 17 11:33:51 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=264afa56
Linux patch 6.8.10
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1009_linux-6.8.10.patch | 13493 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 13497 insertions(+)
diff --git a/0000_README b/0000_README
index bb655415..a90ed274 100644
--- a/0000_README
+++ b/0000_README
@@ -79,6 +79,10 @@ Patch: 1008_linux-6.8.9.patch
From: https://www.kernel.org
Desc: Linux 6.8.9
+Patch: 1009_linux-6.8.10.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.10
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1009_linux-6.8.10.patch b/1009_linux-6.8.10.patch
new file mode 100644
index 00000000..c00d908c
--- /dev/null
+++ b/1009_linux-6.8.10.patch
@@ -0,0 +1,13493 @@
+diff --git a/Documentation/devicetree/bindings/iio/health/maxim,max30102.yaml b/Documentation/devicetree/bindings/iio/health/maxim,max30102.yaml
+index c13c10c8d65da..eed0df9d3a232 100644
+--- a/Documentation/devicetree/bindings/iio/health/maxim,max30102.yaml
++++ b/Documentation/devicetree/bindings/iio/health/maxim,max30102.yaml
+@@ -42,7 +42,7 @@ allOf:
+ properties:
+ compatible:
+ contains:
+- const: maxim,max30100
++ const: maxim,max30102
+ then:
+ properties:
+ maxim,green-led-current-microamp: false
+diff --git a/Documentation/devicetree/bindings/net/mediatek,net.yaml b/Documentation/devicetree/bindings/net/mediatek,net.yaml
+index e74502a0afe86..3202dc7967c5b 100644
+--- a/Documentation/devicetree/bindings/net/mediatek,net.yaml
++++ b/Documentation/devicetree/bindings/net/mediatek,net.yaml
+@@ -337,8 +337,8 @@ allOf:
+ minItems: 4
+
+ clocks:
+- minItems: 34
+- maxItems: 34
++ minItems: 24
++ maxItems: 24
+
+ clock-names:
+ items:
+@@ -351,18 +351,6 @@ allOf:
+ - const: ethwarp_wocpu1
+ - const: ethwarp_wocpu0
+ - const: esw
+- - const: netsys0
+- - const: netsys1
+- - const: sgmii_tx250m
+- - const: sgmii_rx250m
+- - const: sgmii2_tx250m
+- - const: sgmii2_rx250m
+- - const: top_usxgmii0_sel
+- - const: top_usxgmii1_sel
+- - const: top_sgm0_sel
+- - const: top_sgm1_sel
+- - const: top_xfi_phy0_xtal_sel
+- - const: top_xfi_phy1_xtal_sel
+ - const: top_eth_gmii_sel
+ - const: top_eth_refck_50m_sel
+ - const: top_eth_sys_200m_sel
+@@ -375,16 +363,10 @@ allOf:
+ - const: top_netsys_sync_250m_sel
+ - const: top_netsys_ppefb_250m_sel
+ - const: top_netsys_warp_sel
+- - const: wocpu1
+- - const: wocpu0
+ - const: xgp1
+ - const: xgp2
+ - const: xgp3
+
+- mediatek,sgmiisys:
+- minItems: 2
+- maxItems: 2
+-
+ patternProperties:
+ "^mac@[0-1]$":
+ type: object
+diff --git a/Documentation/netlink/specs/rt_link.yaml b/Documentation/netlink/specs/rt_link.yaml
+index 8e4d19adee8cd..4e702ac8bf66b 100644
+--- a/Documentation/netlink/specs/rt_link.yaml
++++ b/Documentation/netlink/specs/rt_link.yaml
+@@ -1144,6 +1144,12 @@ attribute-sets:
+ -
+ name: mcast-querier-state
+ type: binary
++ -
++ name: fdb-n-learned
++ type: u32
++ -
++ name: fdb-max-learned
++ type: u32
+ -
+ name: linkinfo-brport-attrs
+ name-prefix: ifla-brport-
+diff --git a/Makefile b/Makefile
+index 2917a6914c03c..01acaf667e789 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 9
++SUBLEVEL = 10
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
+index a86a1d4f34618..93afd1005b43c 100644
+--- a/arch/arm/kernel/sleep.S
++++ b/arch/arm/kernel/sleep.S
+@@ -127,6 +127,10 @@ cpu_resume_after_mmu:
+ instr_sync
+ #endif
+ bl cpu_init @ restore the und/abt/irq banked regs
++#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK)
++ mov r0, sp
++ bl kasan_unpoison_task_stack_below
++#endif
+ mov r0, #0 @ return zero on success
+ ldmfd sp!, {r4 - r11, pc}
+ ENDPROC(cpu_resume_after_mmu)
+diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
+index 1d672457d02ff..72b5cd697f5d9 100644
+--- a/arch/arm/net/bpf_jit_32.c
++++ b/arch/arm/net/bpf_jit_32.c
+@@ -871,16 +871,11 @@ static inline void emit_a32_alu_r64(const bool is64, const s8 dst[],
+ }
+
+ /* dst = src (4 bytes)*/
+-static inline void emit_a32_mov_r(const s8 dst, const s8 src, const u8 off,
+- struct jit_ctx *ctx) {
++static inline void emit_a32_mov_r(const s8 dst, const s8 src, struct jit_ctx *ctx) {
+ const s8 *tmp = bpf2a32[TMP_REG_1];
+ s8 rt;
+
+ rt = arm_bpf_get_reg32(src, tmp[0], ctx);
+- if (off && off != 32) {
+- emit(ARM_LSL_I(rt, rt, 32 - off), ctx);
+- emit(ARM_ASR_I(rt, rt, 32 - off), ctx);
+- }
+ arm_bpf_put_reg32(dst, rt, ctx);
+ }
+
+@@ -889,15 +884,15 @@ static inline void emit_a32_mov_r64(const bool is64, const s8 dst[],
+ const s8 src[],
+ struct jit_ctx *ctx) {
+ if (!is64) {
+- emit_a32_mov_r(dst_lo, src_lo, 0, ctx);
++ emit_a32_mov_r(dst_lo, src_lo, ctx);
+ if (!ctx->prog->aux->verifier_zext)
+ /* Zero out high 4 bytes */
+ emit_a32_mov_i(dst_hi, 0, ctx);
+ } else if (__LINUX_ARM_ARCH__ < 6 &&
+ ctx->cpu_architecture < CPU_ARCH_ARMv5TE) {
+ /* complete 8 byte move */
+- emit_a32_mov_r(dst_lo, src_lo, 0, ctx);
+- emit_a32_mov_r(dst_hi, src_hi, 0, ctx);
++ emit_a32_mov_r(dst_lo, src_lo, ctx);
++ emit_a32_mov_r(dst_hi, src_hi, ctx);
+ } else if (is_stacked(src_lo) && is_stacked(dst_lo)) {
+ const u8 *tmp = bpf2a32[TMP_REG_1];
+
+@@ -917,17 +912,52 @@ static inline void emit_a32_mov_r64(const bool is64, const s8 dst[],
+ static inline void emit_a32_movsx_r64(const bool is64, const u8 off, const s8 dst[], const s8 src[],
+ struct jit_ctx *ctx) {
+ const s8 *tmp = bpf2a32[TMP_REG_1];
+- const s8 *rt;
++ s8 rs;
++ s8 rd;
+
+- rt = arm_bpf_get_reg64(dst, tmp, ctx);
++ if (is_stacked(dst_lo))
++ rd = tmp[1];
++ else
++ rd = dst_lo;
++ rs = arm_bpf_get_reg32(src_lo, rd, ctx);
++ /* rs may be one of src[1], dst[1], or tmp[1] */
++
++ /* Sign extend rs if needed. If off == 32, lower 32-bits of src are moved to dst and sign
++ * extension only happens in the upper 64 bits.
++ */
++ if (off != 32) {
++ /* Sign extend rs into rd */
++ emit(ARM_LSL_I(rd, rs, 32 - off), ctx);
++ emit(ARM_ASR_I(rd, rd, 32 - off), ctx);
++ } else {
++ rd = rs;
++ }
++
++ /* Write rd to dst_lo
++ *
++ * Optimization:
++ * Assume:
++ * 1. dst == src and stacked.
++ * 2. off == 32
++ *
++ * In this case src_lo was loaded into rd(tmp[1]) but rd was not sign extended as off==32.
++ * So, we don't need to write rd back to dst_lo as they have the same value.
++ * This saves us one str instruction.
++ */
++ if (dst_lo != src_lo || off != 32)
++ arm_bpf_put_reg32(dst_lo, rd, ctx);
+
+- emit_a32_mov_r(dst_lo, src_lo, off, ctx);
+ if (!is64) {
+ if (!ctx->prog->aux->verifier_zext)
+ /* Zero out high 4 bytes */
+ emit_a32_mov_i(dst_hi, 0, ctx);
+ } else {
+- emit(ARM_ASR_I(rt[0], rt[1], 31), ctx);
++ if (is_stacked(dst_hi)) {
++ emit(ARM_ASR_I(tmp[0], rd, 31), ctx);
++ arm_bpf_put_reg32(dst_hi, tmp[0], ctx);
++ } else {
++ emit(ARM_ASR_I(dst_hi, rd, 31), ctx);
++ }
+ }
+ }
+
+diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-pico6.dts b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-pico6.dts
+index a2e74b8293206..6a7ae616512d6 100644
+--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-pico6.dts
++++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui-jacuzzi-pico6.dts
+@@ -82,7 +82,8 @@ pins-clk {
+ };
+
+ &mmc1 {
+- bt_reset: bt-reset {
++ bluetooth@2 {
++ reg = <2>;
+ compatible = "mediatek,mt7921s-bluetooth";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_pins_reset>;
+diff --git a/arch/arm64/boot/dts/qcom/sa8155p-adp.dts b/arch/arm64/boot/dts/qcom/sa8155p-adp.dts
+index 5e4287f8c8cd1..b2cf2c988336c 100644
+--- a/arch/arm64/boot/dts/qcom/sa8155p-adp.dts
++++ b/arch/arm64/boot/dts/qcom/sa8155p-adp.dts
+@@ -367,6 +367,16 @@ queue0 {
+ };
+ };
+
++&pmm8155au_1_gpios {
++ pmm8155au_1_sdc2_cd: sdc2-cd-default-state {
++ pins = "gpio4";
++ function = "normal";
++ input-enable;
++ bias-pull-up;
++ power-source = <0>;
++ };
++};
++
+ &qupv3_id_1 {
+ status = "okay";
+ };
+@@ -384,10 +394,10 @@ &remoteproc_cdsp {
+ &sdhc_2 {
+ status = "okay";
+
+- cd-gpios = <&tlmm 4 GPIO_ACTIVE_LOW>;
++ cd-gpios = <&pmm8155au_1_gpios 4 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default", "sleep";
+- pinctrl-0 = <&sdc2_on>;
+- pinctrl-1 = <&sdc2_off>;
++ pinctrl-0 = <&sdc2_on &pmm8155au_1_sdc2_cd>;
++ pinctrl-1 = <&sdc2_off &pmm8155au_1_sdc2_cd>;
+ vqmmc-supply = <&vreg_l13c_2p96>; /* IO line power */
+ vmmc-supply = <&vreg_l17a_2p96>; /* Card power line */
+ bus-width = <4>;
+@@ -505,13 +515,6 @@ data-pins {
+ bias-pull-up; /* pull up */
+ drive-strength = <16>; /* 16 MA */
+ };
+-
+- sd-cd-pins {
+- pins = "gpio96";
+- function = "gpio";
+- bias-pull-up; /* pull up */
+- drive-strength = <2>; /* 2 MA */
+- };
+ };
+
+ sdc2_off: sdc2-off-state {
+@@ -532,13 +535,6 @@ data-pins {
+ bias-pull-up; /* pull up */
+ drive-strength = <2>; /* 2 MA */
+ };
+-
+- sd-cd-pins {
+- pins = "gpio96";
+- function = "gpio";
+- bias-pull-up; /* pull up */
+- drive-strength = <2>; /* 2 MA */
+- };
+ };
+
+ usb2phy_ac_en1_default: usb2phy-ac-en1-default-state {
+diff --git a/arch/arm64/kvm/vgic/vgic-kvm-device.c b/arch/arm64/kvm/vgic/vgic-kvm-device.c
+index f48b8dab8b3d2..1d26bb5b02f4b 100644
+--- a/arch/arm64/kvm/vgic/vgic-kvm-device.c
++++ b/arch/arm64/kvm/vgic/vgic-kvm-device.c
+@@ -338,12 +338,12 @@ int kvm_register_vgic_device(unsigned long type)
+ int vgic_v2_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr,
+ struct vgic_reg_attr *reg_attr)
+ {
+- int cpuid;
++ int cpuid = FIELD_GET(KVM_DEV_ARM_VGIC_CPUID_MASK, attr->attr);
+
+- cpuid = FIELD_GET(KVM_DEV_ARM_VGIC_CPUID_MASK, attr->attr);
+-
+- reg_attr->vcpu = kvm_get_vcpu_by_id(dev->kvm, cpuid);
+ reg_attr->addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
++ reg_attr->vcpu = kvm_get_vcpu_by_id(dev->kvm, cpuid);
++ if (!reg_attr->vcpu)
++ return -EINVAL;
+
+ return 0;
+ }
+diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
+index 00217d8d034b7..ceed77c29fe6b 100644
+--- a/arch/arm64/net/bpf_jit_comp.c
++++ b/arch/arm64/net/bpf_jit_comp.c
+@@ -1738,15 +1738,15 @@ static void invoke_bpf_prog(struct jit_ctx *ctx, struct bpf_tramp_link *l,
+
+ emit_call(enter_prog, ctx);
+
++ /* save return value to callee saved register x20 */
++ emit(A64_MOV(1, A64_R(20), A64_R(0)), ctx);
++
+ /* if (__bpf_prog_enter(prog) == 0)
+ * goto skip_exec_of_prog;
+ */
+ branch = ctx->image + ctx->idx;
+ emit(A64_NOP, ctx);
+
+- /* save return value to callee saved register x20 */
+- emit(A64_MOV(1, A64_R(20), A64_R(0)), ctx);
+-
+ emit(A64_ADD_I(1, A64_R(0), A64_SP, args_off), ctx);
+ if (!p->jited)
+ emit_addr_mov_i64(A64_R(1), (const u64)p->insnsi, ctx);
+diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
+index d14d0e37ad02d..4a2b40ce39e09 100644
+--- a/arch/mips/include/asm/ptrace.h
++++ b/arch/mips/include/asm/ptrace.h
+@@ -159,7 +159,7 @@ extern unsigned long exception_ip(struct pt_regs *regs);
+ #define exception_ip(regs) exception_ip(regs)
+ #define profile_pc(regs) instruction_pointer(regs)
+
+-extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
++extern asmlinkage long syscall_trace_enter(struct pt_regs *regs);
+ extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
+
+ extern void die(const char *, struct pt_regs *) __noreturn;
+diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
+index d1b11f66f748f..cb1045ebab062 100644
+--- a/arch/mips/kernel/asm-offsets.c
++++ b/arch/mips/kernel/asm-offsets.c
+@@ -101,6 +101,7 @@ void output_thread_info_defines(void)
+ OFFSET(TI_CPU, thread_info, cpu);
+ OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
+ OFFSET(TI_REGS, thread_info, regs);
++ OFFSET(TI_SYSCALL, thread_info, syscall);
+ DEFINE(_THREAD_SIZE, THREAD_SIZE);
+ DEFINE(_THREAD_MASK, THREAD_MASK);
+ DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE);
+diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
+index 59288c13b581b..61503a36067e9 100644
+--- a/arch/mips/kernel/ptrace.c
++++ b/arch/mips/kernel/ptrace.c
+@@ -1317,16 +1317,13 @@ long arch_ptrace(struct task_struct *child, long request,
+ * Notification of system call entry/exit
+ * - triggered by current->work.syscall_trace
+ */
+-asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
++asmlinkage long syscall_trace_enter(struct pt_regs *regs)
+ {
+ user_exit();
+
+- current_thread_info()->syscall = syscall;
+-
+ if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+ if (ptrace_report_syscall_entry(regs))
+ return -1;
+- syscall = current_thread_info()->syscall;
+ }
+
+ #ifdef CONFIG_SECCOMP
+@@ -1335,7 +1332,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
+ struct seccomp_data sd;
+ unsigned long args[6];
+
+- sd.nr = syscall;
++ sd.nr = current_thread_info()->syscall;
+ sd.arch = syscall_get_arch(current);
+ syscall_get_arguments(current, regs, args);
+ for (i = 0; i < 6; i++)
+@@ -1345,23 +1342,23 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
+ ret = __secure_computing(&sd);
+ if (ret == -1)
+ return ret;
+- syscall = current_thread_info()->syscall;
+ }
+ #endif
+
+ if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
+ trace_sys_enter(regs, regs->regs[2]);
+
+- audit_syscall_entry(syscall, regs->regs[4], regs->regs[5],
++ audit_syscall_entry(current_thread_info()->syscall,
++ regs->regs[4], regs->regs[5],
+ regs->regs[6], regs->regs[7]);
+
+ /*
+ * Negative syscall numbers are mistaken for rejected syscalls, but
+ * won't have had the return value set appropriately, so we do so now.
+ */
+- if (syscall < 0)
++ if (current_thread_info()->syscall < 0)
+ syscall_set_return_value(current, regs, -ENOSYS, 0);
+- return syscall;
++ return current_thread_info()->syscall;
+ }
+
+ /*
+diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
+index 18dc9b3450561..2c604717e6308 100644
+--- a/arch/mips/kernel/scall32-o32.S
++++ b/arch/mips/kernel/scall32-o32.S
+@@ -77,6 +77,18 @@ loads_done:
+ PTR_WD load_a7, bad_stack_a7
+ .previous
+
++ /*
++ * syscall number is in v0 unless we called syscall(__NR_###)
++ * where the real syscall number is in a0
++ */
++ subu t2, v0, __NR_O32_Linux
++ bnez t2, 1f /* __NR_syscall at offset 0 */
++ LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number
++ b 2f
++1:
++ LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number
++2:
++
+ lw t0, TI_FLAGS($28) # syscall tracing enabled?
+ li t1, _TIF_WORK_SYSCALL_ENTRY
+ and t0, t1
+@@ -114,16 +126,7 @@ syscall_trace_entry:
+ SAVE_STATIC
+ move a0, sp
+
+- /*
+- * syscall number is in v0 unless we called syscall(__NR_###)
+- * where the real syscall number is in a0
+- */
+- move a1, v0
+- subu t2, v0, __NR_O32_Linux
+- bnez t2, 1f /* __NR_syscall at offset 0 */
+- lw a1, PT_R4(sp)
+-
+-1: jal syscall_trace_enter
++ jal syscall_trace_enter
+
+ bltz v0, 1f # seccomp failed? Skip syscall
+
+diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
+index 97456b2ca7dc3..97788859238c3 100644
+--- a/arch/mips/kernel/scall64-n32.S
++++ b/arch/mips/kernel/scall64-n32.S
+@@ -44,6 +44,8 @@ NESTED(handle_sysn32, PT_SIZE, sp)
+
+ sd a3, PT_R26(sp) # save a3 for syscall restarting
+
++ LONG_S v0, TI_SYSCALL($28) # Store syscall number
++
+ li t1, _TIF_WORK_SYSCALL_ENTRY
+ LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
+ and t0, t1, t0
+@@ -72,7 +74,6 @@ syscall_common:
+ n32_syscall_trace_entry:
+ SAVE_STATIC
+ move a0, sp
+- move a1, v0
+ jal syscall_trace_enter
+
+ bltz v0, 1f # seccomp failed? Skip syscall
+diff --git a/arch/mips/kernel/scall64-n64.S b/arch/mips/kernel/scall64-n64.S
+index e6264aa62e457..be11ea5cc67e0 100644
+--- a/arch/mips/kernel/scall64-n64.S
++++ b/arch/mips/kernel/scall64-n64.S
+@@ -46,6 +46,8 @@ NESTED(handle_sys64, PT_SIZE, sp)
+
+ sd a3, PT_R26(sp) # save a3 for syscall restarting
+
++ LONG_S v0, TI_SYSCALL($28) # Store syscall number
++
+ li t1, _TIF_WORK_SYSCALL_ENTRY
+ LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
+ and t0, t1, t0
+@@ -82,7 +84,6 @@ n64_syscall_exit:
+ syscall_trace_entry:
+ SAVE_STATIC
+ move a0, sp
+- move a1, v0
+ jal syscall_trace_enter
+
+ bltz v0, 1f # seccomp failed? Skip syscall
+diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
+index d3c2616cba226..7a5abb73e5312 100644
+--- a/arch/mips/kernel/scall64-o32.S
++++ b/arch/mips/kernel/scall64-o32.S
+@@ -79,6 +79,22 @@ loads_done:
+ PTR_WD load_a7, bad_stack_a7
+ .previous
+
++ /*
++ * absolute syscall number is in v0 unless we called syscall(__NR_###)
++ * where the real syscall number is in a0
++ * note: NR_syscall is the first O32 syscall but the macro is
++ * only defined when compiling with -mabi=32 (CONFIG_32BIT)
++ * therefore __NR_O32_Linux is used (4000)
++ */
++
++ subu t2, v0, __NR_O32_Linux
++ bnez t2, 1f /* __NR_syscall at offset 0 */
++ LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number
++ b 2f
++1:
++ LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number
++2:
++
+ li t1, _TIF_WORK_SYSCALL_ENTRY
+ LONG_L t0, TI_FLAGS($28) # syscall tracing enabled?
+ and t0, t1, t0
+@@ -113,22 +129,7 @@ trace_a_syscall:
+ sd a7, PT_R11(sp) # For indirect syscalls
+
+ move a0, sp
+- /*
+- * absolute syscall number is in v0 unless we called syscall(__NR_###)
+- * where the real syscall number is in a0
+- * note: NR_syscall is the first O32 syscall but the macro is
+- * only defined when compiling with -mabi=32 (CONFIG_32BIT)
+- * therefore __NR_O32_Linux is used (4000)
+- */
+- .set push
+- .set reorder
+- subu t1, v0, __NR_O32_Linux
+- move a1, v0
+- bnez t1, 1f /* __NR_syscall at offset 0 */
+- ld a1, PT_R4(sp) /* Arg1 for __NR_syscall case */
+- .set pop
+-
+-1: jal syscall_trace_enter
++ jal syscall_trace_enter
+
+ bltz v0, 1f # seccomp failed? Skip syscall
+
+diff --git a/arch/powerpc/crypto/chacha-p10-glue.c b/arch/powerpc/crypto/chacha-p10-glue.c
+index 74fb86b0d2097..7c728755852e1 100644
+--- a/arch/powerpc/crypto/chacha-p10-glue.c
++++ b/arch/powerpc/crypto/chacha-p10-glue.c
+@@ -197,6 +197,9 @@ static struct skcipher_alg algs[] = {
+
+ static int __init chacha_p10_init(void)
+ {
++ if (!cpu_has_feature(CPU_FTR_ARCH_31))
++ return 0;
++
+ static_branch_enable(&have_p10);
+
+ return crypto_register_skciphers(algs, ARRAY_SIZE(algs));
+@@ -204,10 +207,13 @@ static int __init chacha_p10_init(void)
+
+ static void __exit chacha_p10_exit(void)
+ {
++ if (!static_branch_likely(&have_p10))
++ return;
++
+ crypto_unregister_skciphers(algs, ARRAY_SIZE(algs));
+ }
+
+-module_cpu_feature_match(PPC_MODULE_FEATURE_P10, chacha_p10_init);
++module_init(chacha_p10_init);
+ module_exit(chacha_p10_exit);
+
+ MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (P10 accelerated)");
+diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
+index 23b77027c9163..7a84069759b03 100644
+--- a/arch/powerpc/include/asm/plpks.h
++++ b/arch/powerpc/include/asm/plpks.h
+@@ -44,9 +44,8 @@
+ #define PLPKS_MAX_DATA_SIZE 4000
+
+ // Timeouts for PLPKS operations
+-#define PLPKS_MAX_TIMEOUT 5000 // msec
+-#define PLPKS_FLUSH_SLEEP 10 // msec
+-#define PLPKS_FLUSH_SLEEP_RANGE 400
++#define PLPKS_MAX_TIMEOUT (5 * USEC_PER_SEC)
++#define PLPKS_FLUSH_SLEEP 10000 // usec
+
+ struct plpks_var {
+ char *component;
+diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
+index e8c4129697b14..b1e6d275cda9e 100644
+--- a/arch/powerpc/platforms/pseries/iommu.c
++++ b/arch/powerpc/platforms/pseries/iommu.c
+@@ -786,8 +786,16 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
+ * parent bus. During reboot, there will be ibm,dma-window property to
+ * define DMA window. For kdump, there will at least be default window or DDW
+ * or both.
++ * There is an exception to the above. In case the PE goes into frozen
++ * state, firmware may not provide ibm,dma-window property at the time
++ * of LPAR boot up.
+ */
+
++ if (!pdn) {
++ pr_debug(" no ibm,dma-window property !\n");
++ return;
++ }
++
+ ppci = PCI_DN(pdn);
+
+ pr_debug(" parent is %pOF, iommu_table: 0x%p\n",
+diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c
+index febe18f251d0c..4a595493d28ae 100644
+--- a/arch/powerpc/platforms/pseries/plpks.c
++++ b/arch/powerpc/platforms/pseries/plpks.c
+@@ -415,8 +415,7 @@ static int plpks_confirm_object_flushed(struct label *label,
+ break;
+ }
+
+- usleep_range(PLPKS_FLUSH_SLEEP,
+- PLPKS_FLUSH_SLEEP + PLPKS_FLUSH_SLEEP_RANGE);
++ fsleep(PLPKS_FLUSH_SLEEP);
+ timeout = timeout + PLPKS_FLUSH_SLEEP;
+ } while (timeout < PLPKS_MAX_TIMEOUT);
+
+@@ -464,9 +463,10 @@ int plpks_signed_update_var(struct plpks_var *var, u64 flags)
+
+ continuetoken = retbuf[0];
+ if (pseries_status_to_err(rc) == -EBUSY) {
+- int delay_ms = get_longbusy_msecs(rc);
+- mdelay(delay_ms);
+- timeout += delay_ms;
++ int delay_us = get_longbusy_msecs(rc) * 1000;
++
++ fsleep(delay_us);
++ timeout += delay_us;
+ }
+ rc = pseries_status_to_err(rc);
+ } while (rc == -EBUSY && timeout < PLPKS_MAX_TIMEOUT);
+diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
+index 719a97e7edb2c..0bd747d1d00fc 100644
+--- a/arch/riscv/net/bpf_jit_comp64.c
++++ b/arch/riscv/net/bpf_jit_comp64.c
+@@ -740,6 +740,9 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of
+ if (ret)
+ return ret;
+
++ /* store prog start time */
++ emit_mv(RV_REG_S1, RV_REG_A0, ctx);
++
+ /* if (__bpf_prog_enter(prog) == 0)
+ * goto skip_exec_of_prog;
+ */
+@@ -747,9 +750,6 @@ static int invoke_bpf_prog(struct bpf_tramp_link *l, int args_off, int retval_of
+ /* nop reserved for conditional jump */
+ emit(rv_nop(), ctx);
+
+- /* store prog start time */
+- emit_mv(RV_REG_S1, RV_REG_A0, ctx);
+-
+ /* arg1: &args_off */
+ emit_addi(RV_REG_A0, RV_REG_FP, -args_off, ctx);
+ if (!p->jited)
+diff --git a/arch/s390/include/asm/dwarf.h b/arch/s390/include/asm/dwarf.h
+index 4f21ae561e4dd..390906b8e386e 100644
+--- a/arch/s390/include/asm/dwarf.h
++++ b/arch/s390/include/asm/dwarf.h
+@@ -9,6 +9,7 @@
+ #define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset
+ #define CFI_ADJUST_CFA_OFFSET .cfi_adjust_cfa_offset
+ #define CFI_RESTORE .cfi_restore
++#define CFI_REL_OFFSET .cfi_rel_offset
+
+ #ifdef CONFIG_AS_CFI_VAL_OFFSET
+ #define CFI_VAL_OFFSET .cfi_val_offset
+diff --git a/arch/s390/kernel/vdso64/vdso_user_wrapper.S b/arch/s390/kernel/vdso64/vdso_user_wrapper.S
+index 57f62596e53b9..85247ef5a41b8 100644
+--- a/arch/s390/kernel/vdso64/vdso_user_wrapper.S
++++ b/arch/s390/kernel/vdso64/vdso_user_wrapper.S
+@@ -24,8 +24,10 @@ __kernel_\func:
+ CFI_DEF_CFA_OFFSET (STACK_FRAME_OVERHEAD + WRAPPER_FRAME_SIZE)
+ CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD
+ stg %r14,STACK_FRAME_OVERHEAD(%r15)
++ CFI_REL_OFFSET 14, STACK_FRAME_OVERHEAD
+ brasl %r14,__s390_vdso_\func
+ lg %r14,STACK_FRAME_OVERHEAD(%r15)
++ CFI_RESTORE 14
+ aghi %r15,WRAPPER_FRAME_SIZE
+ CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD
+ CFI_RESTORE 15
+diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
+index 08a7eca03daf7..41a4a60c5e651 100644
+--- a/arch/s390/mm/gmap.c
++++ b/arch/s390/mm/gmap.c
+@@ -2659,7 +2659,7 @@ static int __s390_enable_skey_hugetlb(pte_t *pte, unsigned long addr,
+ return 0;
+
+ start = pmd_val(*pmd) & HPAGE_MASK;
+- end = start + HPAGE_SIZE - 1;
++ end = start + HPAGE_SIZE;
+ __storage_key_init_range(start, end);
+ set_bit(PG_arch_1, &page->flags);
+ cond_resched();
+diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
+index 5f64f3d0fafbb..763469e518eec 100644
+--- a/arch/s390/mm/hugetlbpage.c
++++ b/arch/s390/mm/hugetlbpage.c
+@@ -139,7 +139,7 @@ static void clear_huge_pte_skeys(struct mm_struct *mm, unsigned long rste)
+ }
+
+ if (!test_and_set_bit(PG_arch_1, &page->flags))
+- __storage_key_init_range(paddr, paddr + size - 1);
++ __storage_key_init_range(paddr, paddr + size);
+ }
+
+ void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
+index 75bd5ac7ac6a9..a04a5163e56c3 100644
+--- a/arch/x86/kernel/apic/apic.c
++++ b/arch/x86/kernel/apic/apic.c
+@@ -1808,7 +1808,7 @@ void x2apic_setup(void)
+ __x2apic_enable();
+ }
+
+-static __init void apic_set_fixmap(void);
++static __init void apic_set_fixmap(bool read_apic);
+
+ static __init void x2apic_disable(void)
+ {
+@@ -1830,7 +1830,12 @@ static __init void x2apic_disable(void)
+ }
+
+ __x2apic_disable();
+- apic_set_fixmap();
++ /*
++ * Don't reread the APIC ID as it was already done from
++ * check_x2apic() and the APIC driver still is a x2APIC variant,
++ * which fails to do the read after x2APIC was disabled.
++ */
++ apic_set_fixmap(false);
+ }
+
+ static __init void x2apic_enable(void)
+@@ -2095,13 +2100,14 @@ void __init init_apic_mappings(void)
+ }
+ }
+
+-static __init void apic_set_fixmap(void)
++static __init void apic_set_fixmap(bool read_apic)
+ {
+ set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
+ apic_mmio_base = APIC_BASE;
+ apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
+ apic_mmio_base, mp_lapic_addr);
+- apic_read_boot_cpu_id(false);
++ if (read_apic)
++ apic_read_boot_cpu_id(false);
+ }
+
+ void __init register_lapic_address(unsigned long address)
+@@ -2111,7 +2117,7 @@ void __init register_lapic_address(unsigned long address)
+ mp_lapic_addr = address;
+
+ if (!x2apic_mode)
+- apic_set_fixmap();
++ apic_set_fixmap(true);
+ }
+
+ /*
+diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h
+index d008a153a2b9f..7ed1a2085bd72 100644
+--- a/arch/xtensa/include/asm/processor.h
++++ b/arch/xtensa/include/asm/processor.h
+@@ -115,9 +115,9 @@
+ #define MAKE_RA_FOR_CALL(ra,ws) (((ra) & 0x3fffffff) | (ws) << 30)
+
+ /* Convert return address to a valid pc
+- * Note: We assume that the stack pointer is in the same 1GB ranges as the ra
++ * Note: 'text' is the address within the same 1GB range as the ra
+ */
+-#define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000))
++#define MAKE_PC_FROM_RA(ra, text) (((ra) & 0x3fffffff) | ((unsigned long)(text) & 0xc0000000))
+
+ #elif defined(__XTENSA_CALL0_ABI__)
+
+@@ -127,9 +127,9 @@
+ #define MAKE_RA_FOR_CALL(ra, ws) (ra)
+
+ /* Convert return address to a valid pc
+- * Note: We assume that the stack pointer is in the same 1GB ranges as the ra
++ * Note: 'text' is not used as 'ra' is always the full address
+ */
+-#define MAKE_PC_FROM_RA(ra, sp) (ra)
++#define MAKE_PC_FROM_RA(ra, text) (ra)
+
+ #else
+ #error Unsupported Xtensa ABI
+diff --git a/arch/xtensa/include/asm/ptrace.h b/arch/xtensa/include/asm/ptrace.h
+index a270467556dc8..86c70117371bb 100644
+--- a/arch/xtensa/include/asm/ptrace.h
++++ b/arch/xtensa/include/asm/ptrace.h
+@@ -87,7 +87,7 @@ struct pt_regs {
+ # define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
+ # define instruction_pointer(regs) ((regs)->pc)
+ # define return_pointer(regs) (MAKE_PC_FROM_RA((regs)->areg[0], \
+- (regs)->areg[1]))
++ (regs)->pc))
+
+ # ifndef CONFIG_SMP
+ # define profile_pc(regs) instruction_pointer(regs)
+diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
+index a815577d25fd0..7bd66677f7b6d 100644
+--- a/arch/xtensa/kernel/process.c
++++ b/arch/xtensa/kernel/process.c
+@@ -47,6 +47,7 @@
+ #include <asm/asm-offsets.h>
+ #include <asm/regs.h>
+ #include <asm/hw_breakpoint.h>
++#include <asm/sections.h>
+ #include <asm/traps.h>
+
+ extern void ret_from_fork(void);
+@@ -380,7 +381,7 @@ unsigned long __get_wchan(struct task_struct *p)
+ int count = 0;
+
+ sp = p->thread.sp;
+- pc = MAKE_PC_FROM_RA(p->thread.ra, p->thread.sp);
++ pc = MAKE_PC_FROM_RA(p->thread.ra, _text);
+
+ do {
+ if (sp < stack_page + sizeof(struct task_struct) ||
+@@ -392,7 +393,7 @@ unsigned long __get_wchan(struct task_struct *p)
+
+ /* Stack layout: sp-4: ra, sp-3: sp' */
+
+- pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), sp);
++ pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), _text);
+ sp = SPILL_SLOT(sp, 1);
+ } while (count++ < 16);
+ return 0;
+diff --git a/arch/xtensa/kernel/stacktrace.c b/arch/xtensa/kernel/stacktrace.c
+index 831ffb648bda7..ed324fdf2a2f9 100644
+--- a/arch/xtensa/kernel/stacktrace.c
++++ b/arch/xtensa/kernel/stacktrace.c
+@@ -13,6 +13,7 @@
+ #include <linux/stacktrace.h>
+
+ #include <asm/ftrace.h>
++#include <asm/sections.h>
+ #include <asm/stacktrace.h>
+ #include <asm/traps.h>
+ #include <linux/uaccess.h>
+@@ -189,7 +190,7 @@ void walk_stackframe(unsigned long *sp,
+ if (a1 <= (unsigned long)sp)
+ break;
+
+- frame.pc = MAKE_PC_FROM_RA(a0, a1);
++ frame.pc = MAKE_PC_FROM_RA(a0, _text);
+ frame.sp = a1;
+
+ if (fn(&frame, data))
+diff --git a/block/blk-iocost.c b/block/blk-iocost.c
+index 04d44f0bcbc85..f3b68b7994391 100644
+--- a/block/blk-iocost.c
++++ b/block/blk-iocost.c
+@@ -1347,7 +1347,7 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now)
+ {
+ struct ioc *ioc = iocg->ioc;
+ struct blkcg_gq *blkg = iocg_to_blkg(iocg);
+- u64 tdelta, delay, new_delay;
++ u64 tdelta, delay, new_delay, shift;
+ s64 vover, vover_pct;
+ u32 hwa;
+
+@@ -1362,8 +1362,9 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now)
+
+ /* calculate the current delay in effect - 1/2 every second */
+ tdelta = now->now - iocg->delay_at;
+- if (iocg->delay)
+- delay = iocg->delay >> div64_u64(tdelta, USEC_PER_SEC);
++ shift = div64_u64(tdelta, USEC_PER_SEC);
++ if (iocg->delay && shift < BITS_PER_LONG)
++ delay = iocg->delay >> shift;
+ else
+ delay = 0;
+
+@@ -1438,8 +1439,11 @@ static void iocg_pay_debt(struct ioc_gq *iocg, u64 abs_vpay,
+ lockdep_assert_held(&iocg->ioc->lock);
+ lockdep_assert_held(&iocg->waitq.lock);
+
+- /* make sure that nobody messed with @iocg */
+- WARN_ON_ONCE(list_empty(&iocg->active_list));
++ /*
++ * make sure that nobody messed with @iocg. Check iocg->pd.online
++ * to avoid warn when removing blkcg or disk.
++ */
++ WARN_ON_ONCE(list_empty(&iocg->active_list) && iocg->pd.online);
+ WARN_ON_ONCE(iocg->inuse > 1);
+
+ iocg->abs_vdebt -= min(abs_vpay, iocg->abs_vdebt);
+diff --git a/block/ioctl.c b/block/ioctl.c
+index 5f8c988239c68..7dbed0c1155cf 100644
+--- a/block/ioctl.c
++++ b/block/ioctl.c
+@@ -89,7 +89,7 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
+ unsigned long arg)
+ {
+ uint64_t range[2];
+- uint64_t start, len;
++ uint64_t start, len, end;
+ struct inode *inode = bdev->bd_inode;
+ int err;
+
+@@ -110,7 +110,8 @@ static int blk_ioctl_discard(struct block_device *bdev, blk_mode_t mode,
+ if (len & 511)
+ return -EINVAL;
+
+- if (start + len > bdev_nr_bytes(bdev))
++ if (check_add_overflow(start, len, &end) ||
++ end > bdev_nr_bytes(bdev))
+ return -EINVAL;
+
+ filemap_invalidate_lock(inode->i_mapping);
+diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c
+index b35c7aedca03e..bad1ccc81ad73 100644
+--- a/drivers/accel/ivpu/ivpu_drv.c
++++ b/drivers/accel/ivpu/ivpu_drv.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Copyright (C) 2020-2023 Intel Corporation
++ * Copyright (C) 2020-2024 Intel Corporation
+ */
+
+ #include <linux/firmware.h>
+@@ -371,12 +371,15 @@ int ivpu_shutdown(struct ivpu_device *vdev)
+ {
+ int ret;
+
+- ivpu_prepare_for_reset(vdev);
++ /* Save PCI state before powering down as it sometimes gets corrupted if NPU hangs */
++ pci_save_state(to_pci_dev(vdev->drm.dev));
+
+ ret = ivpu_hw_power_down(vdev);
+ if (ret)
+ ivpu_warn(vdev, "Failed to power down HW: %d\n", ret);
+
++ pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
++
+ return ret;
+ }
+
+@@ -543,11 +546,11 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
+ /* Power up early so the rest of init code can access VPU registers */
+ ret = ivpu_hw_power_up(vdev);
+ if (ret)
+- goto err_power_down;
++ goto err_shutdown;
+
+ ret = ivpu_mmu_global_context_init(vdev);
+ if (ret)
+- goto err_power_down;
++ goto err_shutdown;
+
+ ret = ivpu_mmu_init(vdev);
+ if (ret)
+@@ -584,10 +587,8 @@ static int ivpu_dev_init(struct ivpu_device *vdev)
+ ivpu_mmu_reserved_context_fini(vdev);
+ err_mmu_gctx_fini:
+ ivpu_mmu_global_context_fini(vdev);
+-err_power_down:
+- ivpu_hw_power_down(vdev);
+- if (IVPU_WA(d3hot_after_power_off))
+- pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
++err_shutdown:
++ ivpu_shutdown(vdev);
+ err_xa_destroy:
+ xa_destroy(&vdev->submitted_jobs_xa);
+ xa_destroy(&vdev->context_xa);
+@@ -610,9 +611,8 @@ static void ivpu_bo_unbind_all_user_contexts(struct ivpu_device *vdev)
+ static void ivpu_dev_fini(struct ivpu_device *vdev)
+ {
+ ivpu_pm_disable(vdev);
++ ivpu_prepare_for_reset(vdev);
+ ivpu_shutdown(vdev);
+- if (IVPU_WA(d3hot_after_power_off))
+- pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
+
+ ivpu_jobs_abort_all(vdev);
+ ivpu_job_done_consumer_fini(vdev);
+diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h
+index 069ace4adb2d1..e7a9e849940ea 100644
+--- a/drivers/accel/ivpu/ivpu_drv.h
++++ b/drivers/accel/ivpu/ivpu_drv.h
+@@ -1,6 +1,6 @@
+ /* SPDX-License-Identifier: GPL-2.0-only */
+ /*
+- * Copyright (C) 2020-2023 Intel Corporation
++ * Copyright (C) 2020-2024 Intel Corporation
+ */
+
+ #ifndef __IVPU_DRV_H__
+@@ -87,7 +87,6 @@
+ struct ivpu_wa_table {
+ bool punit_disabled;
+ bool clear_runtime_mem;
+- bool d3hot_after_power_off;
+ bool interrupt_clear_with_0;
+ bool disable_clock_relinquish;
+ bool disable_d0i3_msg;
+diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c
+index 32bb772e03cf9..5e392b6823764 100644
+--- a/drivers/accel/ivpu/ivpu_hw_37xx.c
++++ b/drivers/accel/ivpu/ivpu_hw_37xx.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Copyright (C) 2020-2023 Intel Corporation
++ * Copyright (C) 2020-2024 Intel Corporation
+ */
+
+ #include "ivpu_drv.h"
+@@ -75,7 +75,6 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev)
+ {
+ vdev->wa.punit_disabled = false;
+ vdev->wa.clear_runtime_mem = false;
+- vdev->wa.d3hot_after_power_off = true;
+
+ REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, BUTTRESS_ALL_IRQ_MASK);
+ if (REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) == BUTTRESS_ALL_IRQ_MASK) {
+@@ -86,7 +85,6 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev)
+
+ IVPU_PRINT_WA(punit_disabled);
+ IVPU_PRINT_WA(clear_runtime_mem);
+- IVPU_PRINT_WA(d3hot_after_power_off);
+ IVPU_PRINT_WA(interrupt_clear_with_0);
+ }
+
+diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c
+index 91bd640655ab3..2e46b322c4505 100644
+--- a/drivers/accel/ivpu/ivpu_mmu.c
++++ b/drivers/accel/ivpu/ivpu_mmu.c
+@@ -278,7 +278,7 @@ static const char *ivpu_mmu_event_to_str(u32 cmd)
+ case IVPU_MMU_EVT_F_VMS_FETCH:
+ return "Fetch of VMS caused external abort";
+ default:
+- return "Unknown CMDQ command";
++ return "Unknown event";
+ }
+ }
+
+@@ -286,15 +286,15 @@ static const char *ivpu_mmu_cmdq_err_to_str(u32 err)
+ {
+ switch (err) {
+ case IVPU_MMU_CERROR_NONE:
+- return "No CMDQ Error";
++ return "No error";
+ case IVPU_MMU_CERROR_ILL:
+ return "Illegal command";
+ case IVPU_MMU_CERROR_ABT:
+- return "External abort on CMDQ read";
++ return "External abort on command queue read";
+ case IVPU_MMU_CERROR_ATC_INV_SYNC:
+ return "Sync failed to complete ATS invalidation";
+ default:
+- return "Unknown CMDQ Error";
++ return "Unknown error";
+ }
+ }
+
+diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c
+index a15d30d0943af..64618fc2cec40 100644
+--- a/drivers/accel/ivpu/ivpu_pm.c
++++ b/drivers/accel/ivpu/ivpu_pm.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
+ /*
+- * Copyright (C) 2020-2023 Intel Corporation
++ * Copyright (C) 2020-2024 Intel Corporation
+ */
+
+ #include <linux/highmem.h>
+@@ -58,14 +58,11 @@ static int ivpu_suspend(struct ivpu_device *vdev)
+ {
+ int ret;
+
+- /* Save PCI state before powering down as it sometimes gets corrupted if NPU hangs */
+- pci_save_state(to_pci_dev(vdev->drm.dev));
++ ivpu_prepare_for_reset(vdev);
+
+ ret = ivpu_shutdown(vdev);
+ if (ret)
+- ivpu_err(vdev, "Failed to shutdown VPU: %d\n", ret);
+-
+- pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot);
++ ivpu_err(vdev, "Failed to shutdown NPU: %d\n", ret);
+
+ return ret;
+ }
+diff --git a/drivers/ata/sata_gemini.c b/drivers/ata/sata_gemini.c
+index 400b22ee99c33..4c270999ba3cc 100644
+--- a/drivers/ata/sata_gemini.c
++++ b/drivers/ata/sata_gemini.c
+@@ -200,7 +200,10 @@ int gemini_sata_start_bridge(struct sata_gemini *sg, unsigned int bridge)
+ pclk = sg->sata0_pclk;
+ else
+ pclk = sg->sata1_pclk;
+- clk_enable(pclk);
++ ret = clk_enable(pclk);
++ if (ret)
++ return ret;
++
+ msleep(10);
+
+ /* Do not keep clocking a bridge that is not online */
+diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
+index 6db77d8e45f92..4ae399c30f0f2 100644
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -2836,6 +2836,43 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
+ }
+ EXPORT_SYMBOL_GPL(regmap_read);
+
++/**
++ * regmap_read_bypassed() - Read a value from a single register direct
++ * from the device, bypassing the cache
++ *
++ * @map: Register map to read from
++ * @reg: Register to be read from
++ * @val: Pointer to store read value
++ *
++ * A value of zero will be returned on success, a negative errno will
++ * be returned in error cases.
++ */
++int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val)
++{
++ int ret;
++ bool bypass, cache_only;
++
++ if (!IS_ALIGNED(reg, map->reg_stride))
++ return -EINVAL;
++
++ map->lock(map->lock_arg);
++
++ bypass = map->cache_bypass;
++ cache_only = map->cache_only;
++ map->cache_bypass = true;
++ map->cache_only = false;
++
++ ret = _regmap_read(map, reg, val);
++
++ map->cache_bypass = bypass;
++ map->cache_only = cache_only;
++
++ map->unlock(map->lock_arg);
++
++ return ret;
++}
++EXPORT_SYMBOL_GPL(regmap_read_bypassed);
++
+ /**
+ * regmap_raw_read() - Read raw data from the device
+ *
+diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
+index 19cfc342fc7bb..638074992c829 100644
+--- a/drivers/bluetooth/btqca.c
++++ b/drivers/bluetooth/btqca.c
+@@ -99,7 +99,8 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
+ {
+ struct sk_buff *skb;
+ struct edl_event_hdr *edl;
+- char cmd, build_label[QCA_FW_BUILD_VER_LEN];
++ char *build_label;
++ char cmd;
+ int build_lbl_len, err = 0;
+
+ bt_dev_dbg(hdev, "QCA read fw build info");
+@@ -114,6 +115,11 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
+ return err;
+ }
+
++ if (skb->len < sizeof(*edl)) {
++ err = -EILSEQ;
++ goto out;
++ }
++
+ edl = (struct edl_event_hdr *)(skb->data);
+ if (!edl) {
+ bt_dev_err(hdev, "QCA read fw build info with no header");
+@@ -129,14 +135,25 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
+ goto out;
+ }
+
++ if (skb->len < sizeof(*edl) + 1) {
++ err = -EILSEQ;
++ goto out;
++ }
++
+ build_lbl_len = edl->data[0];
+- if (build_lbl_len <= QCA_FW_BUILD_VER_LEN - 1) {
+- memcpy(build_label, edl->data + 1, build_lbl_len);
+- *(build_label + build_lbl_len) = '\0';
++
++ if (skb->len < sizeof(*edl) + 1 + build_lbl_len) {
++ err = -EILSEQ;
++ goto out;
+ }
+
++ build_label = kstrndup(&edl->data[1], build_lbl_len, GFP_KERNEL);
++ if (!build_label)
++ goto out;
++
+ hci_set_fw_info(hdev, "%s", build_label);
+
++ kfree(build_label);
+ out:
+ kfree_skb(skb);
+ return err;
+@@ -235,6 +252,11 @@ static int qca_read_fw_board_id(struct hci_dev *hdev, u16 *bid)
+ goto out;
+ }
+
++ if (skb->len < 3) {
++ err = -EILSEQ;
++ goto out;
++ }
++
+ *bid = (edl->data[1] << 8) + edl->data[2];
+ bt_dev_dbg(hdev, "%s: bid = %x", __func__, *bid);
+
+@@ -265,9 +287,10 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
+ }
+ EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
+
+-static void qca_tlv_check_data(struct hci_dev *hdev,
++static int qca_tlv_check_data(struct hci_dev *hdev,
+ struct qca_fw_config *config,
+- u8 *fw_data, enum qca_btsoc_type soc_type)
++ u8 *fw_data, size_t fw_size,
++ enum qca_btsoc_type soc_type)
+ {
+ const u8 *data;
+ u32 type_len;
+@@ -277,12 +300,16 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
+ struct tlv_type_patch *tlv_patch;
+ struct tlv_type_nvm *tlv_nvm;
+ uint8_t nvm_baud_rate = config->user_baud_rate;
++ u8 type;
+
+ config->dnld_mode = QCA_SKIP_EVT_NONE;
+ config->dnld_type = QCA_SKIP_EVT_NONE;
+
+ switch (config->type) {
+ case ELF_TYPE_PATCH:
++ if (fw_size < 7)
++ return -EINVAL;
++
+ config->dnld_mode = QCA_SKIP_EVT_VSE_CC;
+ config->dnld_type = QCA_SKIP_EVT_VSE_CC;
+
+@@ -291,6 +318,9 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
+ bt_dev_dbg(hdev, "File version : 0x%x", fw_data[6]);
+ break;
+ case TLV_TYPE_PATCH:
++ if (fw_size < sizeof(struct tlv_type_hdr) + sizeof(struct tlv_type_patch))
++ return -EINVAL;
++
+ tlv = (struct tlv_type_hdr *)fw_data;
+ type_len = le32_to_cpu(tlv->type_len);
+ tlv_patch = (struct tlv_type_patch *)tlv->data;
+@@ -330,25 +360,64 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
+ break;
+
+ case TLV_TYPE_NVM:
++ if (fw_size < sizeof(struct tlv_type_hdr))
++ return -EINVAL;
++
+ tlv = (struct tlv_type_hdr *)fw_data;
+
+ type_len = le32_to_cpu(tlv->type_len);
+- length = (type_len >> 8) & 0x00ffffff;
++ length = type_len >> 8;
++ type = type_len & 0xff;
+
+- BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x000000ff);
++ /* Some NVM files have more than one set of tags, only parse
++ * the first set when it has type 2 for now. When there is
++ * more than one set there is an enclosing header of type 4.
++ */
++ if (type == 4) {
++ if (fw_size < 2 * sizeof(struct tlv_type_hdr))
++ return -EINVAL;
++
++ tlv++;
++
++ type_len = le32_to_cpu(tlv->type_len);
++ length = type_len >> 8;
++ type = type_len & 0xff;
++ }
++
++ BT_DBG("TLV Type\t\t : 0x%x", type);
+ BT_DBG("Length\t\t : %d bytes", length);
+
++ if (type != 2)
++ break;
++
++ if (fw_size < length + (tlv->data - fw_data))
++ return -EINVAL;
++
+ idx = 0;
+ data = tlv->data;
+- while (idx < length) {
++ while (idx < length - sizeof(struct tlv_type_nvm)) {
+ tlv_nvm = (struct tlv_type_nvm *)(data + idx);
+
+ tag_id = le16_to_cpu(tlv_nvm->tag_id);
+ tag_len = le16_to_cpu(tlv_nvm->tag_len);
+
++ if (length < idx + sizeof(struct tlv_type_nvm) + tag_len)
++ return -EINVAL;
++
+ /* Update NVM tags as needed */
+ switch (tag_id) {
++ case EDL_TAG_ID_BD_ADDR:
++ if (tag_len != sizeof(bdaddr_t))
++ return -EINVAL;
++
++ memcpy(&config->bdaddr, tlv_nvm->data, sizeof(bdaddr_t));
++
++ break;
++
+ case EDL_TAG_ID_HCI:
++ if (tag_len < 3)
++ return -EINVAL;
++
+ /* HCI transport layer parameters
+ * enabling software inband sleep
+ * onto controller side.
+@@ -364,6 +433,9 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
+ break;
+
+ case EDL_TAG_ID_DEEP_SLEEP:
++ if (tag_len < 1)
++ return -EINVAL;
++
+ /* Sleep enable mask
+ * enabling deep sleep feature on controller.
+ */
+@@ -372,14 +444,16 @@ static void qca_tlv_check_data(struct hci_dev *hdev,
+ break;
+ }
+
+- idx += (sizeof(u16) + sizeof(u16) + 8 + tag_len);
++ idx += sizeof(struct tlv_type_nvm) + tag_len;
+ }
+ break;
+
+ default:
+ BT_ERR("Unknown TLV type %d", config->type);
+- break;
++ return -EINVAL;
+ }
++
++ return 0;
+ }
+
+ static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size,
+@@ -529,7 +603,9 @@ static int qca_download_firmware(struct hci_dev *hdev,
+ memcpy(data, fw->data, size);
+ release_firmware(fw);
+
+- qca_tlv_check_data(hdev, config, data, soc_type);
++ ret = qca_tlv_check_data(hdev, config, data, size, soc_type);
++ if (ret)
++ goto out;
+
+ segment = data;
+ remain = size;
+@@ -612,6 +688,38 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+ }
+ EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome);
+
++static int qca_check_bdaddr(struct hci_dev *hdev, const struct qca_fw_config *config)
++{
++ struct hci_rp_read_bd_addr *bda;
++ struct sk_buff *skb;
++ int err;
++
++ if (bacmp(&hdev->public_addr, BDADDR_ANY))
++ return 0;
++
++ skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
++ HCI_INIT_TIMEOUT);
++ if (IS_ERR(skb)) {
++ err = PTR_ERR(skb);
++ bt_dev_err(hdev, "Failed to read device address (%d)", err);
++ return err;
++ }
++
++ if (skb->len != sizeof(*bda)) {
++ bt_dev_err(hdev, "Device address length mismatch");
++ kfree_skb(skb);
++ return -EIO;
++ }
++
++ bda = (struct hci_rp_read_bd_addr *)skb->data;
++ if (!bacmp(&bda->bdaddr, &config->bdaddr))
++ set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
++
++ kfree_skb(skb);
++
++ return 0;
++}
++
+ static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size,
+ struct qca_btsoc_version ver, u8 rom_ver, u16 bid)
+ {
+@@ -633,7 +741,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
+ enum qca_btsoc_type soc_type, struct qca_btsoc_version ver,
+ const char *firmware_name)
+ {
+- struct qca_fw_config config;
++ struct qca_fw_config config = {};
+ int err;
+ u8 rom_ver = 0;
+ u32 soc_ver;
+@@ -818,6 +926,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
+ break;
+ }
+
++ err = qca_check_bdaddr(hdev, &config);
++ if (err)
++ return err;
++
+ bt_dev_info(hdev, "QCA setup on UART is completed");
+
+ return 0;
+diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
+index dc31984f71dc1..215433fd76a10 100644
+--- a/drivers/bluetooth/btqca.h
++++ b/drivers/bluetooth/btqca.h
+@@ -29,6 +29,7 @@
+ #define EDL_PATCH_CONFIG_RES_EVT (0x00)
+ #define QCA_DISABLE_LOGGING_SUB_OP (0x14)
+
++#define EDL_TAG_ID_BD_ADDR 2
+ #define EDL_TAG_ID_HCI (17)
+ #define EDL_TAG_ID_DEEP_SLEEP (27)
+
+@@ -47,7 +48,6 @@
+ #define get_soc_ver(soc_id, rom_ver) \
+ ((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver)))
+
+-#define QCA_FW_BUILD_VER_LEN 255
+ #define QCA_HSP_GF_SOC_ID 0x1200
+ #define QCA_HSP_GF_SOC_MASK 0x0000ff00
+
+@@ -94,6 +94,7 @@ struct qca_fw_config {
+ uint8_t user_baud_rate;
+ enum qca_tlv_dnld_mode dnld_mode;
+ enum qca_tlv_dnld_mode dnld_type;
++ bdaddr_t bdaddr;
+ };
+
+ struct edl_event_hdr {
+diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
+index ce5c2aa743b08..0c9c9ee56592d 100644
+--- a/drivers/bluetooth/hci_qca.c
++++ b/drivers/bluetooth/hci_qca.c
+@@ -1908,8 +1908,6 @@ static int qca_setup(struct hci_uart *hu)
+ case QCA_WCN6750:
+ case QCA_WCN6855:
+ case QCA_WCN7850:
+- set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks);
+-
+ qcadev = serdev_device_get_drvdata(hu->serdev);
+ if (qcadev->bdaddr_property_broken)
+ set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks);
+diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
+index cf1fc0edfdbca..260e901d0ba70 100644
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -4552,7 +4552,8 @@ void clk_unregister(struct clk *clk)
+ if (ops == &clk_nodrv_ops) {
+ pr_err("%s: unregistered clock: %s\n", __func__,
+ clk->core->name);
+- goto unlock;
++ clk_prepare_unlock();
++ return;
+ }
+ /*
+ * Assign empty clock ops for consumers that might still hold
+@@ -4586,11 +4587,10 @@ void clk_unregister(struct clk *clk)
+ if (clk->core->protect_count)
+ pr_warn("%s: unregistering protected clock: %s\n",
+ __func__, clk->core->name);
++ clk_prepare_unlock();
+
+ kref_put(&clk->core->ref, __clk_release);
+ free_clk(clk);
+-unlock:
+- clk_prepare_unlock();
+ }
+ EXPORT_SYMBOL_GPL(clk_unregister);
+
+@@ -4749,13 +4749,11 @@ void __clk_put(struct clk *clk)
+ if (clk->min_rate > 0 || clk->max_rate < ULONG_MAX)
+ clk_set_rate_range_nolock(clk, 0, ULONG_MAX);
+
+- owner = clk->core->owner;
+- kref_put(&clk->core->ref, __clk_release);
+-
+ clk_prepare_unlock();
+
++ owner = clk->core->owner;
++ kref_put(&clk->core->ref, __clk_release);
+ module_put(owner);
+-
+ free_clk(clk);
+ }
+
+diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c
+index 8602c02047d04..45c5255bcd11b 100644
+--- a/drivers/clk/qcom/clk-smd-rpm.c
++++ b/drivers/clk/qcom/clk-smd-rpm.c
+@@ -768,6 +768,7 @@ static struct clk_smd_rpm *msm8976_clks[] = {
+
+ static const struct rpm_smd_clk_desc rpm_clk_msm8976 = {
+ .clks = msm8976_clks,
++ .num_clks = ARRAY_SIZE(msm8976_clks),
+ .icc_clks = bimc_pcnoc_snoc_smmnoc_icc_clks,
+ .num_icc_clks = ARRAY_SIZE(bimc_pcnoc_snoc_smmnoc_icc_clks),
+ };
+diff --git a/drivers/clk/samsung/clk-exynos-clkout.c b/drivers/clk/samsung/clk-exynos-clkout.c
+index 3484e6cc80ad1..503c6f5b20d5c 100644
+--- a/drivers/clk/samsung/clk-exynos-clkout.c
++++ b/drivers/clk/samsung/clk-exynos-clkout.c
+@@ -13,9 +13,9 @@
+ #include <linux/io.h>
+ #include <linux/of.h>
+ #include <linux/of_address.h>
++#include <linux/of_device.h>
+ #include <linux/platform_device.h>
+ #include <linux/pm.h>
+-#include <linux/property.h>
+
+ #define EXYNOS_CLKOUT_NR_CLKS 1
+ #define EXYNOS_CLKOUT_PARENTS 32
+@@ -84,17 +84,24 @@ MODULE_DEVICE_TABLE(of, exynos_clkout_ids);
+ static int exynos_clkout_match_parent_dev(struct device *dev, u32 *mux_mask)
+ {
+ const struct exynos_clkout_variant *variant;
++ const struct of_device_id *match;
+
+ if (!dev->parent) {
+ dev_err(dev, "not instantiated from MFD\n");
+ return -EINVAL;
+ }
+
+- variant = device_get_match_data(dev->parent);
+- if (!variant) {
++ /*
++ * 'exynos_clkout_ids' arrays is not the ids array matched by
++ * the dev->parent driver, so of_device_get_match_data() or
++ * device_get_match_data() cannot be used here.
++ */
++ match = of_match_device(exynos_clkout_ids, dev->parent);
++ if (!match) {
+ dev_err(dev, "cannot match parent device\n");
+ return -EINVAL;
+ }
++ variant = match->data;
+
+ *mux_mask = variant->mux_mask;
+
+diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+index 8951ffc14ff52..6a4b2b9ef30a8 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
++++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+@@ -182,6 +182,8 @@ static struct ccu_nkm pll_mipi_clk = {
+ &ccu_nkm_ops,
+ CLK_SET_RATE_UNGATE | CLK_SET_RATE_PARENT),
+ .features = CCU_FEATURE_CLOSEST_RATE,
++ .min_rate = 500000000,
++ .max_rate = 1400000000,
+ },
+ };
+
+diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+index 42568c6161814..892df807275c8 100644
+--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
++++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+@@ -1181,11 +1181,18 @@ static const u32 usb2_clk_regs[] = {
+ SUN50I_H6_USB3_CLK_REG,
+ };
+
++static struct ccu_mux_nb sun50i_h6_cpu_nb = {
++ .common = &cpux_clk.common,
++ .cm = &cpux_clk.mux,
++ .delay_us = 1,
++ .bypass_index = 0, /* index of 24 MHz oscillator */
++};
++
+ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
+ {
+ void __iomem *reg;
++ int i, ret;
+ u32 val;
+- int i;
+
+ reg = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(reg))
+@@ -1252,7 +1259,15 @@ static int sun50i_h6_ccu_probe(struct platform_device *pdev)
+ val |= BIT(24);
+ writel(val, reg + SUN50I_H6_HDMI_CEC_CLK_REG);
+
+- return devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc);
++ ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun50i_h6_ccu_desc);
++ if (ret)
++ return ret;
++
++ /* Reparent CPU during PLL CPUX rate changes */
++ ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
++ &sun50i_h6_cpu_nb);
++
++ return 0;
+ }
+
+ static const struct of_device_id sun50i_h6_ccu_ids[] = {
+diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c
+index 8babce55302f5..ac0091b4ce242 100644
+--- a/drivers/clk/sunxi-ng/ccu_common.c
++++ b/drivers/clk/sunxi-ng/ccu_common.c
+@@ -44,6 +44,16 @@ bool ccu_is_better_rate(struct ccu_common *common,
+ unsigned long current_rate,
+ unsigned long best_rate)
+ {
++ unsigned long min_rate, max_rate;
++
++ clk_hw_get_rate_range(&common->hw, &min_rate, &max_rate);
++
++ if (current_rate > max_rate)
++ return false;
++
++ if (current_rate < min_rate)
++ return false;
++
+ if (common->features & CCU_FEATURE_CLOSEST_RATE)
+ return abs(current_rate - target_rate) < abs(best_rate - target_rate);
+
+@@ -122,6 +132,7 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
+
+ for (i = 0; i < desc->hw_clks->num ; i++) {
+ struct clk_hw *hw = desc->hw_clks->hws[i];
++ struct ccu_common *common = hw_to_ccu_common(hw);
+ const char *name;
+
+ if (!hw)
+@@ -136,6 +147,14 @@ static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
+ pr_err("Couldn't register clock %d - %s\n", i, name);
+ goto err_clk_unreg;
+ }
++
++ if (common->max_rate)
++ clk_hw_set_rate_range(hw, common->min_rate,
++ common->max_rate);
++ else
++ WARN(common->min_rate,
++ "No max_rate, ignoring min_rate of clock %d - %s\n",
++ i, name);
+ }
+
+ ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
+diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
+index 942a72c094374..329734f8cf42b 100644
+--- a/drivers/clk/sunxi-ng/ccu_common.h
++++ b/drivers/clk/sunxi-ng/ccu_common.h
+@@ -31,6 +31,9 @@ struct ccu_common {
+ u16 lock_reg;
+ u32 prediv;
+
++ unsigned long min_rate;
++ unsigned long max_rate;
++
+ unsigned long features;
+ spinlock_t *lock;
+ struct clk_hw hw;
+diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c
+index 59456f21778b4..dcefb838b8c0f 100644
+--- a/drivers/dma/idxd/cdev.c
++++ b/drivers/dma/idxd/cdev.c
+@@ -400,6 +400,18 @@ static int idxd_cdev_mmap(struct file *filp, struct vm_area_struct *vma)
+ int rc;
+
+ dev_dbg(&pdev->dev, "%s called\n", __func__);
++
++ /*
++ * Due to an erratum in some of the devices supported by the driver,
++ * direct user submission to the device can be unsafe.
++ * (See the INTEL-SA-01084 security advisory)
++ *
++ * For the devices that exhibit this behavior, require that the user
++ * has CAP_SYS_RAWIO capabilities.
++ */
++ if (!idxd->user_submission_safe && !capable(CAP_SYS_RAWIO))
++ return -EPERM;
++
+ rc = check_vma(wq, vma, __func__);
+ if (rc < 0)
+ return rc;
+@@ -414,6 +426,70 @@ static int idxd_cdev_mmap(struct file *filp, struct vm_area_struct *vma)
+ vma->vm_page_prot);
+ }
+
++static int idxd_submit_user_descriptor(struct idxd_user_context *ctx,
++ struct dsa_hw_desc __user *udesc)
++{
++ struct idxd_wq *wq = ctx->wq;
++ struct idxd_dev *idxd_dev = &wq->idxd->idxd_dev;
++ const uint64_t comp_addr_align = is_dsa_dev(idxd_dev) ? 0x20 : 0x40;
++ void __iomem *portal = idxd_wq_portal_addr(wq);
++ struct dsa_hw_desc descriptor __aligned(64);
++ int rc;
++
++ rc = copy_from_user(&descriptor, udesc, sizeof(descriptor));
++ if (rc)
++ return -EFAULT;
++
++ /*
++ * DSA devices are capable of indirect ("batch") command submission.
++ * On devices where direct user submissions are not safe, we cannot
++ * allow this since there is no good way for us to verify these
++ * indirect commands.
++ */
++ if (is_dsa_dev(idxd_dev) && descriptor.opcode == DSA_OPCODE_BATCH &&
++ !wq->idxd->user_submission_safe)
++ return -EINVAL;
++ /*
++ * As per the programming specification, the completion address must be
++ * aligned to 32 or 64 bytes. If this is violated the hardware
++ * engine can get very confused (security issue).
++ */
++ if (!IS_ALIGNED(descriptor.completion_addr, comp_addr_align))
++ return -EINVAL;
++
++ if (wq_dedicated(wq))
++ iosubmit_cmds512(portal, &descriptor, 1);
++ else {
++ descriptor.priv = 0;
++ descriptor.pasid = ctx->pasid;
++ rc = idxd_enqcmds(wq, portal, &descriptor);
++ if (rc < 0)
++ return rc;
++ }
++
++ return 0;
++}
++
++static ssize_t idxd_cdev_write(struct file *filp, const char __user *buf, size_t len,
++ loff_t *unused)
++{
++ struct dsa_hw_desc __user *udesc = (struct dsa_hw_desc __user *)buf;
++ struct idxd_user_context *ctx = filp->private_data;
++ ssize_t written = 0;
++ int i;
++
++ for (i = 0; i < len/sizeof(struct dsa_hw_desc); i++) {
++ int rc = idxd_submit_user_descriptor(ctx, udesc + i);
++
++ if (rc)
++ return written ? written : rc;
++
++ written += sizeof(struct dsa_hw_desc);
++ }
++
++ return written;
++}
++
+ static __poll_t idxd_cdev_poll(struct file *filp,
+ struct poll_table_struct *wait)
+ {
+@@ -436,6 +512,7 @@ static const struct file_operations idxd_cdev_fops = {
+ .open = idxd_cdev_open,
+ .release = idxd_cdev_release,
+ .mmap = idxd_cdev_mmap,
++ .write = idxd_cdev_write,
+ .poll = idxd_cdev_poll,
+ };
+
+diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h
+index df91472f0f5b1..eb73cabb4ad07 100644
+--- a/drivers/dma/idxd/idxd.h
++++ b/drivers/dma/idxd/idxd.h
+@@ -288,6 +288,7 @@ struct idxd_driver_data {
+ int evl_cr_off;
+ int cr_status_off;
+ int cr_result_off;
++ bool user_submission_safe;
+ load_device_defaults_fn_t load_device_defaults;
+ };
+
+@@ -374,6 +375,8 @@ struct idxd_device {
+
+ struct dentry *dbgfs_dir;
+ struct dentry *dbgfs_evl_file;
++
++ bool user_submission_safe;
+ };
+
+ static inline unsigned int evl_ent_size(struct idxd_device *idxd)
+diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
+index 264c4e47d7cca..a7295943fa223 100644
+--- a/drivers/dma/idxd/init.c
++++ b/drivers/dma/idxd/init.c
+@@ -47,6 +47,7 @@ static struct idxd_driver_data idxd_driver_data[] = {
+ .align = 32,
+ .dev_type = &dsa_device_type,
+ .evl_cr_off = offsetof(struct dsa_evl_entry, cr),
++ .user_submission_safe = false, /* See INTEL-SA-01084 security advisory */
+ .cr_status_off = offsetof(struct dsa_completion_record, status),
+ .cr_result_off = offsetof(struct dsa_completion_record, result),
+ },
+@@ -57,6 +58,7 @@ static struct idxd_driver_data idxd_driver_data[] = {
+ .align = 64,
+ .dev_type = &iax_device_type,
+ .evl_cr_off = offsetof(struct iax_evl_entry, cr),
++ .user_submission_safe = false, /* See INTEL-SA-01084 security advisory */
+ .cr_status_off = offsetof(struct iax_completion_record, status),
+ .cr_result_off = offsetof(struct iax_completion_record, error_code),
+ .load_device_defaults = idxd_load_iaa_device_defaults,
+@@ -774,6 +776,8 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ dev_info(&pdev->dev, "Intel(R) Accelerator Device (v%x)\n",
+ idxd->hw.version);
+
++ idxd->user_submission_safe = data->user_submission_safe;
++
+ return 0;
+
+ err_dev_register:
+diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h
+index 315c004f58e47..e16dbf9ab324c 100644
+--- a/drivers/dma/idxd/registers.h
++++ b/drivers/dma/idxd/registers.h
+@@ -6,9 +6,6 @@
+ #include <uapi/linux/idxd.h>
+
+ /* PCI Config */
+-#define PCI_DEVICE_ID_INTEL_DSA_SPR0 0x0b25
+-#define PCI_DEVICE_ID_INTEL_IAX_SPR0 0x0cfe
+-
+ #define DEVICE_VERSION_1 0x100
+ #define DEVICE_VERSION_2 0x200
+
+diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c
+index 523ae0dff7d4a..3a5ce477a81ad 100644
+--- a/drivers/dma/idxd/sysfs.c
++++ b/drivers/dma/idxd/sysfs.c
+@@ -1197,12 +1197,35 @@ static ssize_t wq_enqcmds_retries_store(struct device *dev, struct device_attrib
+ static struct device_attribute dev_attr_wq_enqcmds_retries =
+ __ATTR(enqcmds_retries, 0644, wq_enqcmds_retries_show, wq_enqcmds_retries_store);
+
++static ssize_t op_cap_show_common(struct device *dev, char *buf, unsigned long *opcap_bmap)
++{
++ ssize_t pos;
++ int i;
++
++ pos = 0;
++ for (i = IDXD_MAX_OPCAP_BITS/64 - 1; i >= 0; i--) {
++ unsigned long val = opcap_bmap[i];
++
++ /* On systems where direct user submissions are not safe, we need to clear out
++ * the BATCH capability from the capability mask in sysfs since we cannot support
++ * that command on such systems.
++ */
++ if (i == DSA_OPCODE_BATCH/64 && !confdev_to_idxd(dev)->user_submission_safe)
++ clear_bit(DSA_OPCODE_BATCH % 64, &val);
++
++ pos += sysfs_emit_at(buf, pos, "%*pb", 64, &val);
++ pos += sysfs_emit_at(buf, pos, "%c", i == 0 ? '\n' : ',');
++ }
++
++ return pos;
++}
++
+ static ssize_t wq_op_config_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+ struct idxd_wq *wq = confdev_to_wq(dev);
+
+- return sysfs_emit(buf, "%*pb\n", IDXD_MAX_OPCAP_BITS, wq->opcap_bmap);
++ return op_cap_show_common(dev, buf, wq->opcap_bmap);
+ }
+
+ static int idxd_verify_supported_opcap(struct idxd_device *idxd, unsigned long *opmask)
+@@ -1455,7 +1478,7 @@ static ssize_t op_cap_show(struct device *dev,
+ {
+ struct idxd_device *idxd = confdev_to_idxd(dev);
+
+- return sysfs_emit(buf, "%*pb\n", IDXD_MAX_OPCAP_BITS, idxd->opcap_bmap);
++ return op_cap_show_common(dev, buf, idxd->opcap_bmap);
+ }
+ static DEVICE_ATTR_RO(op_cap);
+
+diff --git a/drivers/edac/versal_edac.c b/drivers/edac/versal_edac.c
+index 62caf454b5670..a840c6922e5b9 100644
+--- a/drivers/edac/versal_edac.c
++++ b/drivers/edac/versal_edac.c
+@@ -423,7 +423,7 @@ static void handle_error(struct mem_ctl_info *mci, struct ecc_status *stat)
+ convert_to_physical(priv, pinf), pinf.burstpos);
+
+ edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci,
+- priv->ce_cnt, 0, 0, 0, 0, 0, -1,
++ 1, 0, 0, 0, 0, 0, -1,
+ priv->message, "");
+ }
+
+@@ -436,7 +436,7 @@ static void handle_error(struct mem_ctl_info *mci, struct ecc_status *stat)
+ convert_to_physical(priv, pinf), pinf.burstpos);
+
+ edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci,
+- priv->ue_cnt, 0, 0, 0, 0, 0, -1,
++ 1, 0, 0, 0, 0, 0, -1,
+ priv->message, "");
+ }
+
+diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c
+index b0d671db178a8..ea31ac7ac1ca9 100644
+--- a/drivers/firewire/nosy.c
++++ b/drivers/firewire/nosy.c
+@@ -148,10 +148,12 @@ packet_buffer_get(struct client *client, char __user *data, size_t user_length)
+ if (atomic_read(&buffer->size) == 0)
+ return -ENODEV;
+
+- /* FIXME: Check length <= user_length. */
++ length = buffer->head->length;
++
++ if (length > user_length)
++ return 0;
+
+ end = buffer->data + buffer->capacity;
+- length = buffer->head->length;
+
+ if (&buffer->head->data[length] < end) {
+ if (copy_to_user(data, buffer->head->data, length))
+diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
+index 7bc71f4be64a0..b9ae0340b8a70 100644
+--- a/drivers/firewire/ohci.c
++++ b/drivers/firewire/ohci.c
+@@ -1556,6 +1556,8 @@ static int handle_at_packet(struct context *context,
+ #define HEADER_GET_DATA_LENGTH(q) (((q) >> 16) & 0xffff)
+ #define HEADER_GET_EXTENDED_TCODE(q) (((q) >> 0) & 0xffff)
+
++static u32 get_cycle_time(struct fw_ohci *ohci);
++
+ static void handle_local_rom(struct fw_ohci *ohci,
+ struct fw_packet *packet, u32 csr)
+ {
+@@ -1580,6 +1582,8 @@ static void handle_local_rom(struct fw_ohci *ohci,
+ (void *) ohci->config_rom + i, length);
+ }
+
++ // Timestamping on behalf of the hardware.
++ response.timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci));
+ fw_core_handle_response(&ohci->card, &response);
+ }
+
+@@ -1628,6 +1632,8 @@ static void handle_local_lock(struct fw_ohci *ohci,
+ fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0);
+
+ out:
++ // Timestamping on behalf of the hardware.
++ response.timestamp = cycle_time_to_ohci_tstamp(get_cycle_time(ohci));
+ fw_core_handle_response(&ohci->card, &response);
+ }
+
+@@ -1670,8 +1676,6 @@ static void handle_local_request(struct context *ctx, struct fw_packet *packet)
+ }
+ }
+
+-static u32 get_cycle_time(struct fw_ohci *ohci);
+-
+ static void at_context_transmit(struct context *ctx, struct fw_packet *packet)
+ {
+ unsigned long flags;
+@@ -2060,6 +2064,8 @@ static void bus_reset_work(struct work_struct *work)
+
+ ohci->generation = generation;
+ reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
++ if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
++ reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
+
+ if (ohci->quirks & QUIRK_RESET_PACKET)
+ ohci->request_generation = generation;
+@@ -2125,12 +2131,14 @@ static irqreturn_t irq_handler(int irq, void *data)
+ return IRQ_NONE;
+
+ /*
+- * busReset and postedWriteErr must not be cleared yet
++ * busReset and postedWriteErr events must not be cleared yet
+ * (OHCI 1.1 clauses 7.2.3.2 and 13.2.8.1)
+ */
+ reg_write(ohci, OHCI1394_IntEventClear,
+ event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr));
+ log_irqs(ohci, event);
++ if (event & OHCI1394_busReset)
++ reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset);
+
+ if (event & OHCI1394_selfIDComplete)
+ queue_work(selfid_workqueue, &ohci->bus_reset_work);
+diff --git a/drivers/firmware/efi/unaccepted_memory.c b/drivers/firmware/efi/unaccepted_memory.c
+index 5b439d04079c8..50f6503fe49f5 100644
+--- a/drivers/firmware/efi/unaccepted_memory.c
++++ b/drivers/firmware/efi/unaccepted_memory.c
+@@ -4,6 +4,7 @@
+ #include <linux/memblock.h>
+ #include <linux/spinlock.h>
+ #include <linux/crash_dump.h>
++#include <linux/nmi.h>
+ #include <asm/unaccepted_memory.h>
+
+ /* Protects unaccepted memory bitmap and accepting_list */
+@@ -149,6 +150,9 @@ void accept_memory(phys_addr_t start, phys_addr_t end)
+ }
+
+ list_del(&range.list);
++
++ touch_softlockup_watchdog();
++
+ spin_unlock_irqrestore(&unaccepted_memory_lock, flags);
+ }
+
+diff --git a/drivers/firmware/microchip/mpfs-auto-update.c b/drivers/firmware/microchip/mpfs-auto-update.c
+index fbeeaee4ac856..23134ffc4dfc6 100644
+--- a/drivers/firmware/microchip/mpfs-auto-update.c
++++ b/drivers/firmware/microchip/mpfs-auto-update.c
+@@ -206,10 +206,12 @@ static int mpfs_auto_update_verify_image(struct fw_upload *fw_uploader)
+ if (ret | response->resp_status) {
+ dev_warn(priv->dev, "Verification of Upgrade Image failed!\n");
+ ret = ret ? ret : -EBADMSG;
++ goto free_message;
+ }
+
+ dev_info(priv->dev, "Verification of Upgrade Image passed!\n");
+
++free_message:
+ devm_kfree(priv->dev, message);
+ free_response:
+ devm_kfree(priv->dev, response);
+diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c
+index 1ee62cd58582b..25db014494a4d 100644
+--- a/drivers/gpio/gpio-crystalcove.c
++++ b/drivers/gpio/gpio-crystalcove.c
+@@ -92,7 +92,7 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type)
+ case 0x5e:
+ return GPIOPANELCTL;
+ default:
+- return -EOPNOTSUPP;
++ return -ENOTSUPP;
+ }
+ }
+
+diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c
+index 5ef8af8249806..c097e310c9e84 100644
+--- a/drivers/gpio/gpio-lpc32xx.c
++++ b/drivers/gpio/gpio-lpc32xx.c
+@@ -529,6 +529,7 @@ static const struct of_device_id lpc32xx_gpio_of_match[] = {
+ { .compatible = "nxp,lpc3220-gpio", },
+ { },
+ };
++MODULE_DEVICE_TABLE(of, lpc32xx_gpio_of_match);
+
+ static struct platform_driver lpc32xx_gpio_driver = {
+ .driver = {
+diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c
+index c18b6b47384f1..94ca9d03c0949 100644
+--- a/drivers/gpio/gpio-wcove.c
++++ b/drivers/gpio/gpio-wcove.c
+@@ -104,7 +104,7 @@ static inline int to_reg(int gpio, enum ctrl_register type)
+ unsigned int reg = type == CTRL_IN ? GPIO_IN_CTRL_BASE : GPIO_OUT_CTRL_BASE;
+
+ if (gpio >= WCOVE_GPIO_NUM)
+- return -EOPNOTSUPP;
++ return -ENOTSUPP;
+
+ return reg + gpio;
+ }
+diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
+index 1438fdca0b748..5cca9e8803495 100644
+--- a/drivers/gpio/gpiolib-cdev.c
++++ b/drivers/gpio/gpiolib-cdev.c
+@@ -1199,6 +1199,8 @@ static int edge_detector_update(struct line *line,
+ struct gpio_v2_line_config *lc,
+ unsigned int line_idx, u64 edflags)
+ {
++ u64 eflags;
++ int ret;
+ u64 active_edflags = READ_ONCE(line->edflags);
+ unsigned int debounce_period_us =
+ gpio_v2_line_config_debounce_period(lc, line_idx);
+@@ -1210,6 +1212,18 @@ static int edge_detector_update(struct line *line,
+ /* sw debounced and still will be...*/
+ if (debounce_period_us && READ_ONCE(line->sw_debounced)) {
+ line_set_debounce_period(line, debounce_period_us);
++ /*
++ * ensure event fifo is initialised if edge detection
++ * is now enabled.
++ */
++ eflags = edflags & GPIO_V2_LINE_EDGE_FLAGS;
++ if (eflags && !kfifo_initialized(&line->req->events)) {
++ ret = kfifo_alloc(&line->req->events,
++ line->req->event_buffer_size,
++ GFP_KERNEL);
++ if (ret)
++ return ret;
++ }
+ return 0;
+ }
+
+@@ -2800,11 +2814,11 @@ static int gpio_chrdev_release(struct inode *inode, struct file *file)
+ struct gpio_chardev_data *cdev = file->private_data;
+ struct gpio_device *gdev = cdev->gdev;
+
+- bitmap_free(cdev->watched_lines);
+ blocking_notifier_chain_unregister(&gdev->device_notifier,
+ &cdev->device_unregistered_nb);
+ blocking_notifier_chain_unregister(&gdev->line_state_notifier,
+ &cdev->lineinfo_changed_nb);
++ bitmap_free(cdev->watched_lines);
+ gpio_device_put(gdev);
+ kfree(cdev);
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index d0afb9ba3789c..14d878675586a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -4120,18 +4120,22 @@ int amdgpu_device_init(struct amdgpu_device *adev,
+ adev->ip_blocks[i].status.hw = true;
+ }
+ }
++ } else if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 10) &&
++ !amdgpu_device_has_display_hardware(adev)) {
++ r = psp_gpu_reset(adev);
+ } else {
+- tmp = amdgpu_reset_method;
+- /* It should do a default reset when loading or reloading the driver,
+- * regardless of the module parameter reset_method.
+- */
+- amdgpu_reset_method = AMD_RESET_METHOD_NONE;
+- r = amdgpu_asic_reset(adev);
+- amdgpu_reset_method = tmp;
+- if (r) {
+- dev_err(adev->dev, "asic reset on init failed\n");
+- goto failed;
+- }
++ tmp = amdgpu_reset_method;
++ /* It should do a default reset when loading or reloading the driver,
++ * regardless of the module parameter reset_method.
++ */
++ amdgpu_reset_method = AMD_RESET_METHOD_NONE;
++ r = amdgpu_asic_reset(adev);
++ amdgpu_reset_method = tmp;
++ }
++
++ if (r) {
++ dev_err(adev->dev, "asic reset on init failed\n");
++ goto failed;
+ }
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+index 4f9900779ef9e..ff28265838ec0 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+@@ -1867,6 +1867,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
+ amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
+ break;
+ case IP_VERSION(14, 0, 0):
++ case IP_VERSION(14, 0, 1):
+ amdgpu_device_ip_block_add(adev, &smu_v14_0_ip_block);
+ break;
+ default:
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+index 71a5cf37b472d..0b8c6581b62c0 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+@@ -300,12 +300,15 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job)
+ dma_fence_set_error(finished, -ECANCELED);
+
+ if (finished->error < 0) {
+- DRM_INFO("Skip scheduling IBs!\n");
++ dev_dbg(adev->dev, "Skip scheduling IBs in ring(%s)",
++ ring->name);
+ } else {
+ r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, job,
+ &fence);
+ if (r)
+- DRM_ERROR("Error scheduling IBs (%d)\n", r);
++ dev_err(adev->dev,
++ "Error scheduling IBs (%d) in ring(%s)", r,
++ ring->name);
+ }
+
+ job->job_run_counter++;
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+index 866bfde1ca6f9..9e5526046aa15 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+@@ -1244,14 +1244,18 @@ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
+ * amdgpu_bo_move_notify - notification about a memory move
+ * @bo: pointer to a buffer object
+ * @evict: if this move is evicting the buffer from the graphics address space
++ * @new_mem: new resource for backing the BO
+ *
+ * Marks the corresponding &amdgpu_bo buffer object as invalid, also performs
+ * bookkeeping.
+ * TTM driver callback which is called when ttm moves a buffer.
+ */
+-void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict)
++void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
++ bool evict,
++ struct ttm_resource *new_mem)
+ {
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev);
++ struct ttm_resource *old_mem = bo->resource;
+ struct amdgpu_bo *abo;
+
+ if (!amdgpu_bo_is_amdgpu_bo(bo))
+@@ -1263,12 +1267,12 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict)
+ amdgpu_bo_kunmap(abo);
+
+ if (abo->tbo.base.dma_buf && !abo->tbo.base.import_attach &&
+- bo->resource->mem_type != TTM_PL_SYSTEM)
++ old_mem && old_mem->mem_type != TTM_PL_SYSTEM)
+ dma_buf_move_notify(abo->tbo.base.dma_buf);
+
+- /* remember the eviction */
+- if (evict)
+- atomic64_inc(&adev->num_evictions);
++ /* move_notify is called before move happens */
++ trace_amdgpu_bo_move(abo, new_mem ? new_mem->mem_type : -1,
++ old_mem ? old_mem->mem_type : -1);
+ }
+
+ void amdgpu_bo_get_memory(struct amdgpu_bo *bo,
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+index fa03d9e4874cc..bc42ccbde659a 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+@@ -328,7 +328,9 @@ int amdgpu_bo_set_metadata (struct amdgpu_bo *bo, void *metadata,
+ int amdgpu_bo_get_metadata(struct amdgpu_bo *bo, void *buffer,
+ size_t buffer_size, uint32_t *metadata_size,
+ uint64_t *flags);
+-void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict);
++void amdgpu_bo_move_notify(struct ttm_buffer_object *bo,
++ bool evict,
++ struct ttm_resource *new_mem);
+ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo);
+ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
+ void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence,
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+index 851509c6e90eb..43ab165df4900 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+@@ -424,7 +424,7 @@ bool amdgpu_res_cpu_visible(struct amdgpu_device *adev,
+ return false;
+
+ if (res->mem_type == TTM_PL_SYSTEM || res->mem_type == TTM_PL_TT ||
+- res->mem_type == AMDGPU_PL_PREEMPT)
++ res->mem_type == AMDGPU_PL_PREEMPT || res->mem_type == AMDGPU_PL_DOORBELL)
+ return true;
+
+ if (res->mem_type != TTM_PL_VRAM)
+@@ -432,7 +432,7 @@ bool amdgpu_res_cpu_visible(struct amdgpu_device *adev,
+
+ amdgpu_res_first(res, 0, res->size, &cursor);
+ while (cursor.remaining) {
+- if ((cursor.start + cursor.size) >= adev->gmc.visible_vram_size)
++ if ((cursor.start + cursor.size) > adev->gmc.visible_vram_size)
+ return false;
+ amdgpu_res_next(&cursor, cursor.size);
+ }
+@@ -486,14 +486,16 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
+
+ if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM &&
+ bo->ttm == NULL)) {
++ amdgpu_bo_move_notify(bo, evict, new_mem);
+ ttm_bo_move_null(bo, new_mem);
+- goto out;
++ return 0;
+ }
+ if (old_mem->mem_type == TTM_PL_SYSTEM &&
+ (new_mem->mem_type == TTM_PL_TT ||
+ new_mem->mem_type == AMDGPU_PL_PREEMPT)) {
++ amdgpu_bo_move_notify(bo, evict, new_mem);
+ ttm_bo_move_null(bo, new_mem);
+- goto out;
++ return 0;
+ }
+ if ((old_mem->mem_type == TTM_PL_TT ||
+ old_mem->mem_type == AMDGPU_PL_PREEMPT) &&
+@@ -503,9 +505,10 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
+ return r;
+
+ amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm);
++ amdgpu_bo_move_notify(bo, evict, new_mem);
+ ttm_resource_free(bo, &bo->resource);
+ ttm_bo_assign_mem(bo, new_mem);
+- goto out;
++ return 0;
+ }
+
+ if (old_mem->mem_type == AMDGPU_PL_GDS ||
+@@ -517,8 +520,9 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
+ new_mem->mem_type == AMDGPU_PL_OA ||
+ new_mem->mem_type == AMDGPU_PL_DOORBELL) {
+ /* Nothing to save here */
++ amdgpu_bo_move_notify(bo, evict, new_mem);
+ ttm_bo_move_null(bo, new_mem);
+- goto out;
++ return 0;
+ }
+
+ if (bo->type == ttm_bo_type_device &&
+@@ -530,22 +534,23 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
+ abo->flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
+ }
+
+- if (adev->mman.buffer_funcs_enabled) {
+- if (((old_mem->mem_type == TTM_PL_SYSTEM &&
+- new_mem->mem_type == TTM_PL_VRAM) ||
+- (old_mem->mem_type == TTM_PL_VRAM &&
+- new_mem->mem_type == TTM_PL_SYSTEM))) {
+- hop->fpfn = 0;
+- hop->lpfn = 0;
+- hop->mem_type = TTM_PL_TT;
+- hop->flags = TTM_PL_FLAG_TEMPORARY;
+- return -EMULTIHOP;
+- }
++ if (adev->mman.buffer_funcs_enabled &&
++ ((old_mem->mem_type == TTM_PL_SYSTEM &&
++ new_mem->mem_type == TTM_PL_VRAM) ||
++ (old_mem->mem_type == TTM_PL_VRAM &&
++ new_mem->mem_type == TTM_PL_SYSTEM))) {
++ hop->fpfn = 0;
++ hop->lpfn = 0;
++ hop->mem_type = TTM_PL_TT;
++ hop->flags = TTM_PL_FLAG_TEMPORARY;
++ return -EMULTIHOP;
++ }
+
++ amdgpu_bo_move_notify(bo, evict, new_mem);
++ if (adev->mman.buffer_funcs_enabled)
+ r = amdgpu_move_blit(bo, evict, new_mem, old_mem);
+- } else {
++ else
+ r = -ENODEV;
+- }
+
+ if (r) {
+ /* Check that all memory is CPU accessible */
+@@ -560,11 +565,10 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
+ return r;
+ }
+
+- trace_amdgpu_bo_move(abo, new_mem->mem_type, old_mem->mem_type);
+-out:
+- /* update statistics */
++ /* update statistics after the move */
++ if (evict)
++ atomic64_inc(&adev->num_evictions);
+ atomic64_add(bo->base.size, &adev->num_bytes_moved);
+- amdgpu_bo_move_notify(bo, evict);
+ return 0;
+ }
+
+@@ -1566,7 +1570,7 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo,
+ static void
+ amdgpu_bo_delete_mem_notify(struct ttm_buffer_object *bo)
+ {
+- amdgpu_bo_move_notify(bo, false);
++ amdgpu_bo_move_notify(bo, false, NULL);
+ }
+
+ static struct ttm_device_funcs amdgpu_bo_driver = {
+diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
+index d6f808acfb17b..fbb43ae7624f4 100644
+--- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
++++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
+@@ -62,6 +62,11 @@ void aqua_vanjaram_doorbell_index_init(struct amdgpu_device *adev)
+ adev->doorbell_index.max_assignment = AMDGPU_DOORBELL_LAYOUT1_MAX_ASSIGNMENT << 1;
+ }
+
++static bool aqua_vanjaram_xcp_vcn_shared(struct amdgpu_device *adev)
++{
++ return (adev->xcp_mgr->num_xcps > adev->vcn.num_vcn_inst);
++}
++
+ static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev,
+ uint32_t inst_idx, struct amdgpu_ring *ring)
+ {
+@@ -87,7 +92,7 @@ static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev,
+ case AMDGPU_RING_TYPE_VCN_ENC:
+ case AMDGPU_RING_TYPE_VCN_JPEG:
+ ip_blk = AMDGPU_XCP_VCN;
+- if (adev->xcp_mgr->mode == AMDGPU_CPX_PARTITION_MODE)
++ if (aqua_vanjaram_xcp_vcn_shared(adev))
+ inst_mask = 1 << (inst_idx * 2);
+ break;
+ default:
+@@ -140,10 +145,12 @@ static int aqua_vanjaram_xcp_sched_list_update(
+
+ aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id);
+
+- /* VCN is shared by two partitions under CPX MODE */
++ /* VCN may be shared by two partitions under CPX MODE in certain
++ * configs.
++ */
+ if ((ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC ||
+- ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) &&
+- adev->xcp_mgr->mode == AMDGPU_CPX_PARTITION_MODE)
++ ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) &&
++ aqua_vanjaram_xcp_vcn_shared(adev))
+ aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id + 1);
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+index 1caed0163b53d..328682cbb7e22 100644
+--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
++++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+@@ -1601,19 +1601,9 @@ static int sdma_v4_4_2_set_ecc_irq_state(struct amdgpu_device *adev,
+ u32 sdma_cntl;
+
+ sdma_cntl = RREG32_SDMA(type, regSDMA_CNTL);
+- switch (state) {
+- case AMDGPU_IRQ_STATE_DISABLE:
+- sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL,
+- DRAM_ECC_INT_ENABLE, 0);
+- WREG32_SDMA(type, regSDMA_CNTL, sdma_cntl);
+- break;
+- /* sdma ecc interrupt is enabled by default
+- * driver doesn't need to do anything to
+- * enable the interrupt */
+- case AMDGPU_IRQ_STATE_ENABLE:
+- default:
+- break;
+- }
++ sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL, DRAM_ECC_INT_ENABLE,
++ state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0);
++ WREG32_SDMA(type, regSDMA_CNTL, sdma_cntl);
+
+ return 0;
+ }
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+index 08da993df1480..88ad54f88d599 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+@@ -1138,7 +1138,7 @@ static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep,
+ goto err_unlock;
+ }
+ offset = dev->adev->rmmio_remap.bus_addr;
+- if (!offset) {
++ if (!offset || (PAGE_SIZE > 4096)) {
+ err = -ENOMEM;
+ goto err_unlock;
+ }
+@@ -1522,7 +1522,7 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
+
+ /* Find a KFD GPU device that supports the get_dmabuf_info query */
+ for (i = 0; kfd_topology_enum_kfd_devices(i, &dev) == 0; i++)
+- if (dev)
++ if (dev && !kfd_devcgroup_check_permission(dev))
+ break;
+ if (!dev)
+ return -EINVAL;
+@@ -1544,7 +1544,7 @@ static int kfd_ioctl_get_dmabuf_info(struct file *filep,
+ if (xcp_id >= 0)
+ args->gpu_id = dmabuf_adev->kfd.dev->nodes[xcp_id]->id;
+ else
+- args->gpu_id = dmabuf_adev->kfd.dev->nodes[0]->id;
++ args->gpu_id = dev->id;
+ args->flags = flags;
+
+ /* Copy metadata buffer to user mode */
+@@ -2306,7 +2306,7 @@ static int criu_restore_memory_of_gpu(struct kfd_process_device *pdd,
+ return -EINVAL;
+ }
+ offset = pdd->dev->adev->rmmio_remap.bus_addr;
+- if (!offset) {
++ if (!offset || (PAGE_SIZE > 4096)) {
+ pr_err("amdgpu_amdkfd_get_mmio_remap_phys_addr failed\n");
+ return -ENOMEM;
+ }
+@@ -3347,6 +3347,9 @@ static int kfd_mmio_mmap(struct kfd_node *dev, struct kfd_process *process,
+ if (vma->vm_end - vma->vm_start != PAGE_SIZE)
+ return -EINVAL;
+
++ if (PAGE_SIZE > 4096)
++ return -EINVAL;
++
+ address = dev->adev->rmmio_remap.bus_addr;
+
+ vm_flags_set(vma, VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_NORESERVE |
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+index 0a9cf9dfc2243..fcf6558d019e5 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+@@ -944,7 +944,6 @@ void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm)
+ {
+ struct kfd_node *node;
+ int i;
+- int count;
+
+ if (!kfd->init_complete)
+ return;
+@@ -952,12 +951,10 @@ void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm)
+ /* for runtime suspend, skip locking kfd */
+ if (!run_pm) {
+ mutex_lock(&kfd_processes_mutex);
+- count = ++kfd_locked;
+- mutex_unlock(&kfd_processes_mutex);
+-
+ /* For first KFD device suspend all the KFD processes */
+- if (count == 1)
++ if (++kfd_locked == 1)
+ kfd_suspend_all_processes();
++ mutex_unlock(&kfd_processes_mutex);
+ }
+
+ for (i = 0; i < kfd->num_nodes; i++) {
+@@ -968,7 +965,7 @@ void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm)
+
+ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm)
+ {
+- int ret, count, i;
++ int ret, i;
+
+ if (!kfd->init_complete)
+ return 0;
+@@ -982,12 +979,10 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm)
+ /* for runtime resume, skip unlocking kfd */
+ if (!run_pm) {
+ mutex_lock(&kfd_processes_mutex);
+- count = --kfd_locked;
+- mutex_unlock(&kfd_processes_mutex);
+-
+- WARN_ONCE(count < 0, "KFD suspend / resume ref. error");
+- if (count == 0)
++ if (--kfd_locked == 0)
+ ret = kfd_resume_all_processes();
++ WARN_ONCE(kfd_locked < 0, "KFD suspend / resume ref. error");
++ mutex_unlock(&kfd_processes_mutex);
+ }
+
+ return ret;
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c
+index a7697ec8188e0..f85ca6cb90f56 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v10.c
+@@ -336,7 +336,8 @@ static void event_interrupt_wq_v10(struct kfd_node *dev,
+ break;
+ }
+ kfd_signal_event_interrupt(pasid, context_id0 & 0x7fffff, 23);
+- } else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE) {
++ } else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE &&
++ KFD_DBG_EC_TYPE_IS_PACKET(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0))) {
+ kfd_set_dbg_ev_from_interrupt(dev, pasid,
+ KFD_DEBUG_DOORBELL_ID(context_id0),
+ KFD_EC_MASK(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0)),
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
+index 2a65792fd1162..3ca9c160da7c2 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v11.c
+@@ -325,7 +325,8 @@ static void event_interrupt_wq_v11(struct kfd_node *dev,
+ /* CP */
+ if (source_id == SOC15_INTSRC_CP_END_OF_PIPE)
+ kfd_signal_event_interrupt(pasid, context_id0, 32);
+- else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE)
++ else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE &&
++ KFD_DBG_EC_TYPE_IS_PACKET(KFD_CTXID0_CP_BAD_OP_ECODE(context_id0)))
+ kfd_set_dbg_ev_from_interrupt(dev, pasid,
+ KFD_CTXID0_DOORBELL_ID(context_id0),
+ KFD_EC_MASK(KFD_CTXID0_CP_BAD_OP_ECODE(context_id0)),
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
+index 27cdaea405017..8a6729939ae55 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
+@@ -385,7 +385,8 @@ static void event_interrupt_wq_v9(struct kfd_node *dev,
+ break;
+ }
+ kfd_signal_event_interrupt(pasid, sq_int_data, 24);
+- } else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE) {
++ } else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE &&
++ KFD_DBG_EC_TYPE_IS_PACKET(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0))) {
+ kfd_set_dbg_ev_from_interrupt(dev, pasid,
+ KFD_DEBUG_DOORBELL_ID(context_id0),
+ KFD_EC_MASK(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0)),
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 718e533ab46dd..9044214dfdbdf 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -147,6 +147,9 @@ MODULE_FIRMWARE(FIRMWARE_NAVI12_DMCU);
+ #define FIRMWARE_DCN_35_DMUB "amdgpu/dcn_3_5_dmcub.bin"
+ MODULE_FIRMWARE(FIRMWARE_DCN_35_DMUB);
+
++#define FIRMWARE_DCN_351_DMUB "amdgpu/dcn_3_5_1_dmcub.bin"
++MODULE_FIRMWARE(FIRMWARE_DCN_351_DMUB);
++
+ /* Number of bytes in PSP header for firmware. */
+ #define PSP_HEADER_BYTES 0x100
+
+@@ -3025,6 +3028,10 @@ static int dm_resume(void *handle)
+ /* Do mst topology probing after resuming cached state*/
+ drm_connector_list_iter_begin(ddev, &iter);
+ drm_for_each_connector_iter(connector, &iter) {
++
++ if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
++ continue;
++
+ aconnector = to_amdgpu_dm_connector(connector);
+ if (aconnector->dc_link->type != dc_connection_mst_branch ||
+ aconnector->mst_root)
+@@ -4776,6 +4783,9 @@ static int dm_init_microcode(struct amdgpu_device *adev)
+ case IP_VERSION(3, 5, 0):
+ fw_name_dmub = FIRMWARE_DCN_35_DMUB;
+ break;
++ case IP_VERSION(3, 5, 1):
++ fw_name_dmub = FIRMWARE_DCN_351_DMUB;
++ break;
+ default:
+ /* ASIC doesn't support DMUB. */
+ return 0;
+@@ -5873,6 +5883,9 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector,
+ &aconnector->base.probed_modes :
+ &aconnector->base.modes;
+
++ if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
++ return NULL;
++
+ if (aconnector->freesync_vid_base.clock != 0)
+ return &aconnector->freesync_vid_base;
+
+@@ -8627,10 +8640,10 @@ static void amdgpu_dm_commit_audio(struct drm_device *dev,
+ if (!drm_atomic_crtc_needs_modeset(new_crtc_state))
+ continue;
+
++notify:
+ if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)
+ continue;
+
+-notify:
+ aconnector = to_amdgpu_dm_connector(connector);
+
+ mutex_lock(&adev->dm.audio_lock);
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+index 85fc6181303bb..5d499b99aba91 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c
+@@ -1495,7 +1495,9 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf,
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+- pipe_ctx->stream->link == aconnector->dc_link)
++ pipe_ctx->stream->link == aconnector->dc_link &&
++ pipe_ctx->stream->sink &&
++ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+@@ -1596,7 +1598,9 @@ static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf,
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+- pipe_ctx->stream->link == aconnector->dc_link)
++ pipe_ctx->stream->link == aconnector->dc_link &&
++ pipe_ctx->stream->sink &&
++ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+@@ -1681,7 +1685,9 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf,
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+- pipe_ctx->stream->link == aconnector->dc_link)
++ pipe_ctx->stream->link == aconnector->dc_link &&
++ pipe_ctx->stream->sink &&
++ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+@@ -1780,7 +1786,9 @@ static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf,
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+- pipe_ctx->stream->link == aconnector->dc_link)
++ pipe_ctx->stream->link == aconnector->dc_link &&
++ pipe_ctx->stream->sink &&
++ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+@@ -1865,7 +1873,9 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf,
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+- pipe_ctx->stream->link == aconnector->dc_link)
++ pipe_ctx->stream->link == aconnector->dc_link &&
++ pipe_ctx->stream->sink &&
++ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+@@ -1964,7 +1974,9 @@ static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf,
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+- pipe_ctx->stream->link == aconnector->dc_link)
++ pipe_ctx->stream->link == aconnector->dc_link &&
++ pipe_ctx->stream->sink &&
++ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+@@ -2045,7 +2057,9 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf,
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+- pipe_ctx->stream->link == aconnector->dc_link)
++ pipe_ctx->stream->link == aconnector->dc_link &&
++ pipe_ctx->stream->sink &&
++ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+@@ -2141,7 +2155,9 @@ static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *bu
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+- pipe_ctx->stream->link == aconnector->dc_link)
++ pipe_ctx->stream->link == aconnector->dc_link &&
++ pipe_ctx->stream->sink &&
++ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+@@ -2220,7 +2236,9 @@ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf,
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+- pipe_ctx->stream->link == aconnector->dc_link)
++ pipe_ctx->stream->link == aconnector->dc_link &&
++ pipe_ctx->stream->sink &&
++ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+@@ -2276,7 +2294,9 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf,
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+- pipe_ctx->stream->link == aconnector->dc_link)
++ pipe_ctx->stream->link == aconnector->dc_link &&
++ pipe_ctx->stream->sink &&
++ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+@@ -2347,7 +2367,9 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf,
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+- pipe_ctx->stream->link == aconnector->dc_link)
++ pipe_ctx->stream->link == aconnector->dc_link &&
++ pipe_ctx->stream->sink &&
++ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+@@ -2418,7 +2440,9 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf,
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe_ctx->stream &&
+- pipe_ctx->stream->link == aconnector->dc_link)
++ pipe_ctx->stream->link == aconnector->dc_link &&
++ pipe_ctx->stream->sink &&
++ pipe_ctx->stream->sink == aconnector->dc_sink)
+ break;
+ }
+
+diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+index 05f392501c0ae..ab31643b10969 100644
+--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
++++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+@@ -2948,6 +2948,7 @@ static enum bp_result construct_integrated_info(
+ result = get_integrated_info_v2_1(bp, info);
+ break;
+ case 2:
++ case 3:
+ result = get_integrated_info_v2_2(bp, info);
+ break;
+ default:
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c
+index 5b7ad38f85e08..65e45a0b4ff34 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_link_encoder.c
+@@ -395,6 +395,12 @@ void dcn31_hpo_dp_link_enc_set_throttled_vcp_size(
+ x),
+ 25));
+
++ // If y rounds up to integer, carry it over to x.
++ if (y >> 25) {
++ x += 1;
++ y = 0;
++ }
++
+ switch (stream_encoder_inst) {
+ case 0:
+ REG_SET_2(DP_DPHY_SYM32_VC_RATE_CNTL0, 0,
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+index 1e67374b89978..46cbb5a6c8e74 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+@@ -638,22 +638,43 @@ void dcn35_power_down_on_boot(struct dc *dc)
+
+ bool dcn35_apply_idle_power_optimizations(struct dc *dc, bool enable)
+ {
+- struct dc_link *edp_links[MAX_NUM_EDP];
+- int i, edp_num;
+ if (dc->debug.dmcub_emulation)
+ return true;
+
+ if (enable) {
+- dc_get_edp_links(dc, edp_links, &edp_num);
+- if (edp_num == 0 || edp_num > 1)
+- return false;
++ uint32_t num_active_edp = 0;
++ int i;
+
+ for (i = 0; i < dc->current_state->stream_count; ++i) {
+ struct dc_stream_state *stream = dc->current_state->streams[i];
++ struct dc_link *link = stream->link;
++ bool is_psr = link && !link->panel_config.psr.disable_psr &&
++ (link->psr_settings.psr_version == DC_PSR_VERSION_1 ||
++ link->psr_settings.psr_version == DC_PSR_VERSION_SU_1);
++ bool is_replay = link && link->replay_settings.replay_feature_enabled;
++
++ /* Ignore streams that disabled. */
++ if (stream->dpms_off)
++ continue;
++
++ /* Active external displays block idle optimizations. */
++ if (!dc_is_embedded_signal(stream->signal))
++ return false;
++
++ /* If not PWRSEQ0 can't enter idle optimizations */
++ if (link && link->link_index != 0)
++ return false;
+
+- if (!stream->dpms_off && !dc_is_embedded_signal(stream->signal))
++ /* Check for panel power features required for idle optimizations. */
++ if (!is_psr && !is_replay)
+ return false;
++
++ num_active_edp += 1;
+ }
++
++ /* If more than one active eDP then disallow. */
++ if (num_active_edp > 1)
++ return false;
+ }
+
+ // TODO: review other cases when idle optimization is allowed
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+index 0ad947df777ab..ba1597b01a970 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+@@ -734,7 +734,7 @@ static int smu_early_init(void *handle)
+ smu->adev = adev;
+ smu->pm_enabled = !!amdgpu_dpm;
+ smu->is_apu = false;
+- smu->smu_baco.state = SMU_BACO_STATE_EXIT;
++ smu->smu_baco.state = SMU_BACO_STATE_NONE;
+ smu->smu_baco.platform_support = false;
+ smu->user_dpm_profile.fan_mode = -1;
+
+@@ -1954,10 +1954,25 @@ static int smu_smc_hw_cleanup(struct smu_context *smu)
+ return 0;
+ }
+
++static int smu_reset_mp1_state(struct smu_context *smu)
++{
++ struct amdgpu_device *adev = smu->adev;
++ int ret = 0;
++
++ if ((!adev->in_runpm) && (!adev->in_suspend) &&
++ (!amdgpu_in_reset(adev)) && amdgpu_ip_version(adev, MP1_HWIP, 0) ==
++ IP_VERSION(13, 0, 10) &&
++ !amdgpu_device_has_display_hardware(adev))
++ ret = smu_set_mp1_state(smu, PP_MP1_STATE_UNLOAD);
++
++ return ret;
++}
++
+ static int smu_hw_fini(void *handle)
+ {
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct smu_context *smu = adev->powerplay.pp_handle;
++ int ret;
+
+ if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev))
+ return 0;
+@@ -1975,7 +1990,15 @@ static int smu_hw_fini(void *handle)
+
+ adev->pm.dpm_enabled = false;
+
+- return smu_smc_hw_cleanup(smu);
++ ret = smu_smc_hw_cleanup(smu);
++ if (ret)
++ return ret;
++
++ ret = smu_reset_mp1_state(smu);
++ if (ret)
++ return ret;
++
++ return 0;
+ }
+
+ static void smu_late_fini(void *handle)
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+index 66e84defd0b6e..2aa4fea873147 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
++++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+@@ -424,6 +424,7 @@ enum smu_reset_mode {
+ enum smu_baco_state {
+ SMU_BACO_STATE_ENTER = 0,
+ SMU_BACO_STATE_EXIT,
++ SMU_BACO_STATE_NONE,
+ };
+
+ struct smu_baco_context {
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+index 9c03296f92cdd..67117ced7c6ae 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+@@ -2751,7 +2751,13 @@ static int smu_v13_0_0_set_mp1_state(struct smu_context *smu,
+
+ switch (mp1_state) {
+ case PP_MP1_STATE_UNLOAD:
+- ret = smu_cmn_set_mp1_state(smu, mp1_state);
++ ret = smu_cmn_send_smc_msg_with_param(smu,
++ SMU_MSG_PrepareMp1ForUnload,
++ 0x55, NULL);
++
++ if (!ret && smu->smu_baco.state == SMU_BACO_STATE_EXIT)
++ ret = smu_v13_0_disable_pmfw_state(smu);
++
+ break;
+ default:
+ /* Ignore others */
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
+index 949131bd1ecb2..4abfcd32747d3 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c
+@@ -226,7 +226,7 @@ static int smu_v13_0_4_system_features_control(struct smu_context *smu, bool en)
+ struct amdgpu_device *adev = smu->adev;
+ int ret = 0;
+
+- if (!en && !adev->in_s0ix) {
++ if (!en && adev->in_s4) {
+ /* Adds a GFX reset as workaround just before sending the
+ * MP1_UNLOAD message to prevent GC/RLC/PMFW from entering
+ * an invalid state.
+diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
+index b0516505f7ae9..4d2df7f64dc51 100644
+--- a/drivers/gpu/drm/drm_connector.c
++++ b/drivers/gpu/drm/drm_connector.c
+@@ -2940,7 +2940,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
+ dev->mode_config.max_width,
+ dev->mode_config.max_height);
+ else
+- drm_dbg_kms(dev, "User-space requested a forced probe on [CONNECTOR:%d:%s] but is not the DRM master, demoting to read-only probe",
++ drm_dbg_kms(dev, "User-space requested a forced probe on [CONNECTOR:%d:%s] but is not the DRM master, demoting to read-only probe\n",
+ connector->base.id, connector->name);
+ }
+
+diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c
+index 07e0c73204f30..ed81e1466c4b5 100644
+--- a/drivers/gpu/drm/i915/display/intel_audio.c
++++ b/drivers/gpu/drm/i915/display/intel_audio.c
+@@ -76,19 +76,6 @@ struct intel_audio_funcs {
+ struct intel_crtc_state *crtc_state);
+ };
+
+-/* DP N/M table */
+-#define LC_810M 810000
+-#define LC_540M 540000
+-#define LC_270M 270000
+-#define LC_162M 162000
+-
+-struct dp_aud_n_m {
+- int sample_rate;
+- int clock;
+- u16 m;
+- u16 n;
+-};
+-
+ struct hdmi_aud_ncts {
+ int sample_rate;
+ int clock;
+@@ -96,60 +83,6 @@ struct hdmi_aud_ncts {
+ int cts;
+ };
+
+-/* Values according to DP 1.4 Table 2-104 */
+-static const struct dp_aud_n_m dp_aud_n_m[] = {
+- { 32000, LC_162M, 1024, 10125 },
+- { 44100, LC_162M, 784, 5625 },
+- { 48000, LC_162M, 512, 3375 },
+- { 64000, LC_162M, 2048, 10125 },
+- { 88200, LC_162M, 1568, 5625 },
+- { 96000, LC_162M, 1024, 3375 },
+- { 128000, LC_162M, 4096, 10125 },
+- { 176400, LC_162M, 3136, 5625 },
+- { 192000, LC_162M, 2048, 3375 },
+- { 32000, LC_270M, 1024, 16875 },
+- { 44100, LC_270M, 784, 9375 },
+- { 48000, LC_270M, 512, 5625 },
+- { 64000, LC_270M, 2048, 16875 },
+- { 88200, LC_270M, 1568, 9375 },
+- { 96000, LC_270M, 1024, 5625 },
+- { 128000, LC_270M, 4096, 16875 },
+- { 176400, LC_270M, 3136, 9375 },
+- { 192000, LC_270M, 2048, 5625 },
+- { 32000, LC_540M, 1024, 33750 },
+- { 44100, LC_540M, 784, 18750 },
+- { 48000, LC_540M, 512, 11250 },
+- { 64000, LC_540M, 2048, 33750 },
+- { 88200, LC_540M, 1568, 18750 },
+- { 96000, LC_540M, 1024, 11250 },
+- { 128000, LC_540M, 4096, 33750 },
+- { 176400, LC_540M, 3136, 18750 },
+- { 192000, LC_540M, 2048, 11250 },
+- { 32000, LC_810M, 1024, 50625 },
+- { 44100, LC_810M, 784, 28125 },
+- { 48000, LC_810M, 512, 16875 },
+- { 64000, LC_810M, 2048, 50625 },
+- { 88200, LC_810M, 1568, 28125 },
+- { 96000, LC_810M, 1024, 16875 },
+- { 128000, LC_810M, 4096, 50625 },
+- { 176400, LC_810M, 3136, 28125 },
+- { 192000, LC_810M, 2048, 16875 },
+-};
+-
+-static const struct dp_aud_n_m *
+-audio_config_dp_get_n_m(const struct intel_crtc_state *crtc_state, int rate)
+-{
+- int i;
+-
+- for (i = 0; i < ARRAY_SIZE(dp_aud_n_m); i++) {
+- if (rate == dp_aud_n_m[i].sample_rate &&
+- crtc_state->port_clock == dp_aud_n_m[i].clock)
+- return &dp_aud_n_m[i];
+- }
+-
+- return NULL;
+-}
+-
+ static const struct {
+ int clock;
+ u32 config;
+@@ -387,47 +320,17 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder,
+ const struct intel_crtc_state *crtc_state)
+ {
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+- struct i915_audio_component *acomp = i915->display.audio.component;
+ enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
+- enum port port = encoder->port;
+- const struct dp_aud_n_m *nm;
+- int rate;
+- u32 tmp;
+-
+- rate = acomp ? acomp->aud_sample_rate[port] : 0;
+- nm = audio_config_dp_get_n_m(crtc_state, rate);
+- if (nm)
+- drm_dbg_kms(&i915->drm, "using Maud %u, Naud %u\n", nm->m,
+- nm->n);
+- else
+- drm_dbg_kms(&i915->drm, "using automatic Maud, Naud\n");
+-
+- tmp = intel_de_read(i915, HSW_AUD_CFG(cpu_transcoder));
+- tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
+- tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
+- tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
+- tmp |= AUD_CONFIG_N_VALUE_INDEX;
+
+- if (nm) {
+- tmp &= ~AUD_CONFIG_N_MASK;
+- tmp |= AUD_CONFIG_N(nm->n);
+- tmp |= AUD_CONFIG_N_PROG_ENABLE;
+- }
+-
+- intel_de_write(i915, HSW_AUD_CFG(cpu_transcoder), tmp);
+-
+- tmp = intel_de_read(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder));
+- tmp &= ~AUD_CONFIG_M_MASK;
+- tmp &= ~AUD_M_CTS_M_VALUE_INDEX;
+- tmp &= ~AUD_M_CTS_M_PROG_ENABLE;
+-
+- if (nm) {
+- tmp |= nm->m;
+- tmp |= AUD_M_CTS_M_VALUE_INDEX;
+- tmp |= AUD_M_CTS_M_PROG_ENABLE;
+- }
++ /* Enable time stamps. Let HW calculate Maud/Naud values */
++ intel_de_rmw(i915, HSW_AUD_CFG(cpu_transcoder),
++ AUD_CONFIG_N_VALUE_INDEX |
++ AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK |
++ AUD_CONFIG_UPPER_N_MASK |
++ AUD_CONFIG_LOWER_N_MASK |
++ AUD_CONFIG_N_PROG_ENABLE,
++ AUD_CONFIG_N_VALUE_INDEX);
+
+- intel_de_write(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp);
+ }
+
+ static void
+diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
+index eb9835d48d019..c36633d7dda84 100644
+--- a/drivers/gpu/drm/i915/display/intel_bios.c
++++ b/drivers/gpu/drm/i915/display/intel_bios.c
+@@ -1042,22 +1042,11 @@ parse_lfp_backlight(struct drm_i915_private *i915,
+ panel->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI;
+ panel->vbt.backlight.controller = 0;
+ if (i915->display.vbt.version >= 191) {
+- size_t exp_size;
++ const struct lfp_backlight_control_method *method;
+
+- if (i915->display.vbt.version >= 236)
+- exp_size = sizeof(struct bdb_lfp_backlight_data);
+- else if (i915->display.vbt.version >= 234)
+- exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_234;
+- else
+- exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_191;
+-
+- if (get_blocksize(backlight_data) >= exp_size) {
+- const struct lfp_backlight_control_method *method;
+-
+- method = &backlight_data->backlight_control[panel_type];
+- panel->vbt.backlight.type = method->type;
+- panel->vbt.backlight.controller = method->controller;
+- }
++ method = &backlight_data->backlight_control[panel_type];
++ panel->vbt.backlight.type = method->type;
++ panel->vbt.backlight.controller = method->controller;
+ }
+
+ panel->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
+diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
+index a9f44abfc9fc2..b50cd0dcabda9 100644
+--- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
++++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
+@@ -897,11 +897,6 @@ struct lfp_brightness_level {
+ u16 reserved;
+ } __packed;
+
+-#define EXP_BDB_LFP_BL_DATA_SIZE_REV_191 \
+- offsetof(struct bdb_lfp_backlight_data, brightness_level)
+-#define EXP_BDB_LFP_BL_DATA_SIZE_REV_234 \
+- offsetof(struct bdb_lfp_backlight_data, brightness_precision_bits)
+-
+ struct bdb_lfp_backlight_data {
+ u8 entry_size;
+ struct lfp_backlight_data_entry data[16];
+diff --git a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c
+index 044219c5960a5..99b71bb7da0a6 100644
+--- a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c
++++ b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.c
+@@ -8,14 +8,14 @@
+ #include "intel_gt_ccs_mode.h"
+ #include "intel_gt_regs.h"
+
+-void intel_gt_apply_ccs_mode(struct intel_gt *gt)
++unsigned int intel_gt_apply_ccs_mode(struct intel_gt *gt)
+ {
+ int cslice;
+ u32 mode = 0;
+ int first_ccs = __ffs(CCS_MASK(gt));
+
+ if (!IS_DG2(gt->i915))
+- return;
++ return 0;
+
+ /* Build the value for the fixed CCS load balancing */
+ for (cslice = 0; cslice < I915_MAX_CCS; cslice++) {
+@@ -35,5 +35,5 @@ void intel_gt_apply_ccs_mode(struct intel_gt *gt)
+ XEHP_CCS_MODE_CSLICE_MASK);
+ }
+
+- intel_uncore_write(gt->uncore, XEHP_CCS_MODE, mode);
++ return mode;
+ }
+diff --git a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h
+index 9e5549caeb269..55547f2ff426a 100644
+--- a/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h
++++ b/drivers/gpu/drm/i915/gt/intel_gt_ccs_mode.h
+@@ -8,6 +8,6 @@
+
+ struct intel_gt;
+
+-void intel_gt_apply_ccs_mode(struct intel_gt *gt);
++unsigned int intel_gt_apply_ccs_mode(struct intel_gt *gt);
+
+ #endif /* __INTEL_GT_CCS_MODE_H__ */
+diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
+index 59816dd6fbfef..bc1b598d9a098 100644
+--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
++++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
+@@ -2855,6 +2855,7 @@ add_render_compute_tuning_settings(struct intel_gt *gt,
+ static void ccs_engine_wa_mode(struct intel_engine_cs *engine, struct i915_wa_list *wal)
+ {
+ struct intel_gt *gt = engine->gt;
++ u32 mode;
+
+ if (!IS_DG2(gt->i915))
+ return;
+@@ -2871,7 +2872,8 @@ static void ccs_engine_wa_mode(struct intel_engine_cs *engine, struct i915_wa_li
+ * After having disabled automatic load balancing we need to
+ * assign all slices to a single CCS. We will call it CCS mode 1
+ */
+- intel_gt_apply_ccs_mode(gt);
++ mode = intel_gt_apply_ccs_mode(gt);
++ wa_masked_en(wal, XEHP_CCS_MODE, mode);
+ }
+
+ /*
+diff --git a/drivers/gpu/drm/imagination/pvr_fw_mips.h b/drivers/gpu/drm/imagination/pvr_fw_mips.h
+index 408dbe63a90cf..a0c5c41c8aa24 100644
+--- a/drivers/gpu/drm/imagination/pvr_fw_mips.h
++++ b/drivers/gpu/drm/imagination/pvr_fw_mips.h
+@@ -7,13 +7,14 @@
+ #include "pvr_rogue_mips.h"
+
+ #include <asm/page.h>
++#include <linux/math.h>
+ #include <linux/types.h>
+
+ /* Forward declaration from pvr_gem.h. */
+ struct pvr_gem_object;
+
+-#define PVR_MIPS_PT_PAGE_COUNT ((ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * ROGUE_MIPSFW_PAGE_SIZE_4K) \
+- >> PAGE_SHIFT)
++#define PVR_MIPS_PT_PAGE_COUNT DIV_ROUND_UP(ROGUE_MIPSFW_MAX_NUM_PAGETABLE_PAGES * ROGUE_MIPSFW_PAGE_SIZE_4K, PAGE_SIZE)
++
+ /**
+ * struct pvr_fw_mips_data - MIPS-specific data
+ */
+diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
+index 5a9538bc0e26f..5565f7777529f 100644
+--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
++++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
+@@ -106,6 +106,8 @@
+ #define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 */
+ #define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 */
+ #define HHI_HDMI_PHY_CNTL1 0x3a4 /* 0xe9 */
++#define PHY_CNTL1_INIT 0x03900000
++#define PHY_INVERT BIT(17)
+ #define HHI_HDMI_PHY_CNTL2 0x3a8 /* 0xea */
+ #define HHI_HDMI_PHY_CNTL3 0x3ac /* 0xeb */
+ #define HHI_HDMI_PHY_CNTL4 0x3b0 /* 0xec */
+@@ -130,6 +132,8 @@ struct meson_dw_hdmi_data {
+ unsigned int addr);
+ void (*dwc_write)(struct meson_dw_hdmi *dw_hdmi,
+ unsigned int addr, unsigned int data);
++ u32 cntl0_init;
++ u32 cntl1_init;
+ };
+
+ struct meson_dw_hdmi {
+@@ -384,26 +388,6 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
+ dw_hdmi_bus_fmt_is_420(hdmi))
+ mode_is_420 = true;
+
+- /* Enable clocks */
+- regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
+-
+- /* Bring HDMITX MEM output of power down */
+- regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
+-
+- /* Bring out of reset */
+- dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_SW_RESET, 0);
+-
+- /* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */
+- dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
+- 0x3, 0x3);
+-
+- /* Enable cec_clk and hdcp22_tmdsclk_en */
+- dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
+- 0x3 << 4, 0x3 << 4);
+-
+- /* Enable normal output to PHY */
+- dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
+-
+ /* TMDS pattern setup */
+ if (mode->clock > 340000 && !mode_is_420) {
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
+@@ -425,20 +409,6 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
+ /* Setup PHY parameters */
+ meson_hdmi_phy_setup_mode(dw_hdmi, mode, mode_is_420);
+
+- /* Setup PHY */
+- regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
+- 0xffff << 16, 0x0390 << 16);
+-
+- /* BIT_INVERT */
+- if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
+- dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
+- dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
+- regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
+- BIT(17), 0);
+- else
+- regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
+- BIT(17), BIT(17));
+-
+ /* Disable clock, fifo, fifo_wr */
+ regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0);
+
+@@ -492,7 +462,9 @@ static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi,
+
+ DRM_DEBUG_DRIVER("\n");
+
+- regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
++ /* Fallback to init mode */
++ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL1, dw_hdmi->data->cntl1_init);
++ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, dw_hdmi->data->cntl0_init);
+ }
+
+ static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi,
+@@ -610,11 +582,22 @@ static const struct regmap_config meson_dw_hdmi_regmap_config = {
+ .fast_io = true,
+ };
+
+-static const struct meson_dw_hdmi_data meson_dw_hdmi_gx_data = {
++static const struct meson_dw_hdmi_data meson_dw_hdmi_gxbb_data = {
+ .top_read = dw_hdmi_top_read,
+ .top_write = dw_hdmi_top_write,
+ .dwc_read = dw_hdmi_dwc_read,
+ .dwc_write = dw_hdmi_dwc_write,
++ .cntl0_init = 0x0,
++ .cntl1_init = PHY_CNTL1_INIT | PHY_INVERT,
++};
++
++static const struct meson_dw_hdmi_data meson_dw_hdmi_gxl_data = {
++ .top_read = dw_hdmi_top_read,
++ .top_write = dw_hdmi_top_write,
++ .dwc_read = dw_hdmi_dwc_read,
++ .dwc_write = dw_hdmi_dwc_write,
++ .cntl0_init = 0x0,
++ .cntl1_init = PHY_CNTL1_INIT,
+ };
+
+ static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = {
+@@ -622,6 +605,8 @@ static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = {
+ .top_write = dw_hdmi_g12a_top_write,
+ .dwc_read = dw_hdmi_g12a_dwc_read,
+ .dwc_write = dw_hdmi_g12a_dwc_write,
++ .cntl0_init = 0x000b4242, /* Bandgap */
++ .cntl1_init = PHY_CNTL1_INIT,
+ };
+
+ static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi)
+@@ -656,6 +641,13 @@ static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi)
+ meson_dw_hdmi->data->top_write(meson_dw_hdmi,
+ HDMITX_TOP_CLK_CNTL, 0xff);
+
++ /* Enable normal output to PHY */
++ meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
++
++ /* Setup PHY */
++ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL1, meson_dw_hdmi->data->cntl1_init);
++ regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, meson_dw_hdmi->data->cntl0_init);
++
+ /* Enable HDMI-TX Interrupt */
+ meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
+ HDMITX_TOP_INTR_CORE);
+@@ -865,11 +857,11 @@ static const struct dev_pm_ops meson_dw_hdmi_pm_ops = {
+
+ static const struct of_device_id meson_dw_hdmi_of_table[] = {
+ { .compatible = "amlogic,meson-gxbb-dw-hdmi",
+- .data = &meson_dw_hdmi_gx_data },
++ .data = &meson_dw_hdmi_gxbb_data },
+ { .compatible = "amlogic,meson-gxl-dw-hdmi",
+- .data = &meson_dw_hdmi_gx_data },
++ .data = &meson_dw_hdmi_gxl_data },
+ { .compatible = "amlogic,meson-gxm-dw-hdmi",
+- .data = &meson_dw_hdmi_gx_data },
++ .data = &meson_dw_hdmi_gxl_data },
+ { .compatible = "amlogic,meson-g12a-dw-hdmi",
+ .data = &meson_dw_hdmi_g12a_data },
+ { }
+diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
+index 6f5d376d8fcc1..a11d16a16c3b2 100644
+--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
++++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
+@@ -15,7 +15,9 @@ struct nvkm_gsp_mem {
+ };
+
+ struct nvkm_gsp_radix3 {
+- struct nvkm_gsp_mem mem[3];
++ struct nvkm_gsp_mem lvl0;
++ struct nvkm_gsp_mem lvl1;
++ struct sg_table lvl2;
+ };
+
+ int nvkm_gsp_sg(struct nvkm_device *, u64 size, struct sg_table *);
+diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
+index 7de7707ec6a89..3f72bc38bd2c4 100644
+--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
++++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
+@@ -225,12 +225,15 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
+ u8 *dpcd = nv_encoder->dp.dpcd;
+ int ret = NOUVEAU_DP_NONE, hpd;
+
+- /* If we've already read the DPCD on an eDP device, we don't need to
+- * reread it as it won't change
++ /* eDP ports don't support hotplugging - so there's no point in probing eDP ports unless we
++ * haven't probed them once before.
+ */
+- if (connector->connector_type == DRM_MODE_CONNECTOR_eDP &&
+- dpcd[DP_DPCD_REV] != 0)
+- return NOUVEAU_DP_SST;
++ if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
++ if (connector->status == connector_status_connected)
++ return NOUVEAU_DP_SST;
++ else if (connector->status == connector_status_disconnected)
++ return NOUVEAU_DP_NONE;
++ }
+
+ mutex_lock(&nv_encoder->dp.hpd_irq_lock);
+ if (mstm) {
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
+index a73a5b5897904..49171d312f607 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c
+@@ -1112,7 +1112,7 @@ r535_gsp_rpc_set_registry(struct nvkm_gsp *gsp)
+ rpc->numEntries = NV_GSP_REG_NUM_ENTRIES;
+
+ str_offset = offsetof(typeof(*rpc), entries[NV_GSP_REG_NUM_ENTRIES]);
+- strings = (char *)&rpc->entries[NV_GSP_REG_NUM_ENTRIES];
++ strings = (char *)rpc + str_offset;
+ for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) {
+ int name_len = strlen(r535_registry_entries[i].name) + 1;
+
+@@ -1620,7 +1620,7 @@ r535_gsp_wpr_meta_init(struct nvkm_gsp *gsp)
+ meta->magic = GSP_FW_WPR_META_MAGIC;
+ meta->revision = GSP_FW_WPR_META_REVISION;
+
+- meta->sysmemAddrOfRadix3Elf = gsp->radix3.mem[0].addr;
++ meta->sysmemAddrOfRadix3Elf = gsp->radix3.lvl0.addr;
+ meta->sizeOfRadix3Elf = gsp->fb.wpr2.elf.size;
+
+ meta->sysmemAddrOfBootloader = gsp->boot.fw.addr;
+@@ -1914,8 +1914,9 @@ nvkm_gsp_sg(struct nvkm_device *device, u64 size, struct sg_table *sgt)
+ static void
+ nvkm_gsp_radix3_dtor(struct nvkm_gsp *gsp, struct nvkm_gsp_radix3 *rx3)
+ {
+- for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--)
+- nvkm_gsp_mem_dtor(gsp, &rx3->mem[i]);
++ nvkm_gsp_sg_free(gsp->subdev.device, &rx3->lvl2);
++ nvkm_gsp_mem_dtor(gsp, &rx3->lvl1);
++ nvkm_gsp_mem_dtor(gsp, &rx3->lvl0);
+ }
+
+ /**
+@@ -1951,36 +1952,60 @@ static int
+ nvkm_gsp_radix3_sg(struct nvkm_gsp *gsp, struct sg_table *sgt, u64 size,
+ struct nvkm_gsp_radix3 *rx3)
+ {
+- u64 addr;
++ struct sg_dma_page_iter sg_dma_iter;
++ struct scatterlist *sg;
++ size_t bufsize;
++ u64 *pte;
++ int ret, i, page_idx = 0;
+
+- for (int i = ARRAY_SIZE(rx3->mem) - 1; i >= 0; i--) {
+- u64 *ptes;
+- size_t bufsize;
+- int ret, idx;
++ ret = nvkm_gsp_mem_ctor(gsp, GSP_PAGE_SIZE, &rx3->lvl0);
++ if (ret)
++ return ret;
+
+- bufsize = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE);
+- ret = nvkm_gsp_mem_ctor(gsp, bufsize, &rx3->mem[i]);
+- if (ret)
+- return ret;
++ ret = nvkm_gsp_mem_ctor(gsp, GSP_PAGE_SIZE, &rx3->lvl1);
++ if (ret)
++ goto lvl1_fail;
+
+- ptes = rx3->mem[i].data;
+- if (i == 2) {
+- struct scatterlist *sgl;
++ // Allocate level 2
++ bufsize = ALIGN((size / GSP_PAGE_SIZE) * sizeof(u64), GSP_PAGE_SIZE);
++ ret = nvkm_gsp_sg(gsp->subdev.device, bufsize, &rx3->lvl2);
++ if (ret)
++ goto lvl2_fail;
+
+- for_each_sgtable_dma_sg(sgt, sgl, idx) {
+- for (int j = 0; j < sg_dma_len(sgl) / GSP_PAGE_SIZE; j++)
+- *ptes++ = sg_dma_address(sgl) + (GSP_PAGE_SIZE * j);
+- }
+- } else {
+- for (int j = 0; j < size / GSP_PAGE_SIZE; j++)
+- *ptes++ = addr + GSP_PAGE_SIZE * j;
++ // Write the bus address of level 1 to level 0
++ pte = rx3->lvl0.data;
++ *pte = rx3->lvl1.addr;
++
++ // Write the bus address of each page in level 2 to level 1
++ pte = rx3->lvl1.data;
++ for_each_sgtable_dma_page(&rx3->lvl2, &sg_dma_iter, 0)
++ *pte++ = sg_page_iter_dma_address(&sg_dma_iter);
++
++ // Finally, write the bus address of each page in sgt to level 2
++ for_each_sgtable_sg(&rx3->lvl2, sg, i) {
++ void *sgl_end;
++
++ pte = sg_virt(sg);
++ sgl_end = (void *)pte + sg->length;
++
++ for_each_sgtable_dma_page(sgt, &sg_dma_iter, page_idx) {
++ *pte++ = sg_page_iter_dma_address(&sg_dma_iter);
++ page_idx++;
++
++ // Go to the next scatterlist for level 2 if we've reached the end
++ if ((void *)pte >= sgl_end)
++ break;
+ }
++ }
+
+- size = rx3->mem[i].size;
+- addr = rx3->mem[i].addr;
++ if (ret) {
++lvl2_fail:
++ nvkm_gsp_mem_dtor(gsp, &rx3->lvl1);
++lvl1_fail:
++ nvkm_gsp_mem_dtor(gsp, &rx3->lvl0);
+ }
+
+- return 0;
++ return ret;
+ }
+
+ int
+@@ -2012,7 +2037,7 @@ r535_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
+ sr = gsp->sr.meta.data;
+ sr->magic = GSP_FW_SR_META_MAGIC;
+ sr->revision = GSP_FW_SR_META_REVISION;
+- sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.mem[0].addr;
++ sr->sysmemAddrOfSuspendResumeData = gsp->sr.radix3.lvl0.addr;
+ sr->sizeOfSuspendResumeData = len;
+
+ mbox0 = lower_32_bits(gsp->sr.meta.addr);
+diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
+index 8f3783742208b..888297d0d3955 100644
+--- a/drivers/gpu/drm/panel/Kconfig
++++ b/drivers/gpu/drm/panel/Kconfig
+@@ -184,7 +184,7 @@ config DRM_PANEL_ILITEK_IL9322
+
+ config DRM_PANEL_ILITEK_ILI9341
+ tristate "Ilitek ILI9341 240x320 QVGA panels"
+- depends on OF && SPI
++ depends on SPI
+ select DRM_KMS_HELPER
+ select DRM_GEM_DMA_HELPER
+ depends on BACKLIGHT_CLASS_DEVICE
+diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
+index 3574681891e81..b933380b7eb78 100644
+--- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
++++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
+@@ -22,8 +22,9 @@
+ #include <linux/bitops.h>
+ #include <linux/delay.h>
+ #include <linux/gpio/consumer.h>
++#include <linux/mod_devicetable.h>
+ #include <linux/module.h>
+-#include <linux/of.h>
++#include <linux/property.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/spi/spi.h>
+
+@@ -421,7 +422,7 @@ static int ili9341_dpi_prepare(struct drm_panel *panel)
+
+ ili9341_dpi_init(ili);
+
+- return ret;
++ return 0;
+ }
+
+ static int ili9341_dpi_enable(struct drm_panel *panel)
+@@ -691,7 +692,7 @@ static int ili9341_dpi_probe(struct spi_device *spi, struct gpio_desc *dc,
+ * Every new incarnation of this display must have a unique
+ * data entry for the system in this driver.
+ */
+- ili->conf = of_device_get_match_data(dev);
++ ili->conf = device_get_match_data(dev);
+ if (!ili->conf) {
+ dev_err(dev, "missing device configuration\n");
+ return -ENODEV;
+@@ -714,18 +715,18 @@ static int ili9341_probe(struct spi_device *spi)
+
+ reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(reset))
+- dev_err(dev, "Failed to get gpio 'reset'\n");
++ return dev_err_probe(dev, PTR_ERR(reset), "Failed to get gpio 'reset'\n");
+
+ dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW);
+ if (IS_ERR(dc))
+- dev_err(dev, "Failed to get gpio 'dc'\n");
++ return dev_err_probe(dev, PTR_ERR(dc), "Failed to get gpio 'dc'\n");
+
+ if (!strcmp(id->name, "sf-tc240t-9370-t"))
+ return ili9341_dpi_probe(spi, dc, reset);
+ else if (!strcmp(id->name, "yx240qv29"))
+ return ili9341_dbi_probe(spi, dc, reset);
+
+- return -1;
++ return -ENODEV;
+ }
+
+ static void ili9341_remove(struct spi_device *spi)
+diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c
+index 9febc8b73f09e..368d26da0d6a2 100644
+--- a/drivers/gpu/drm/qxl/qxl_release.c
++++ b/drivers/gpu/drm/qxl/qxl_release.c
+@@ -58,56 +58,16 @@ static long qxl_fence_wait(struct dma_fence *fence, bool intr,
+ signed long timeout)
+ {
+ struct qxl_device *qdev;
+- struct qxl_release *release;
+- int count = 0, sc = 0;
+- bool have_drawable_releases;
+ unsigned long cur, end = jiffies + timeout;
+
+ qdev = container_of(fence->lock, struct qxl_device, release_lock);
+- release = container_of(fence, struct qxl_release, base);
+- have_drawable_releases = release->type == QXL_RELEASE_DRAWABLE;
+-
+-retry:
+- sc++;
+-
+- if (dma_fence_is_signaled(fence))
+- goto signaled;
+-
+- qxl_io_notify_oom(qdev);
+-
+- for (count = 0; count < 11; count++) {
+- if (!qxl_queue_garbage_collect(qdev, true))
+- break;
+-
+- if (dma_fence_is_signaled(fence))
+- goto signaled;
+- }
+-
+- if (dma_fence_is_signaled(fence))
+- goto signaled;
+
+- if (have_drawable_releases || sc < 4) {
+- if (sc > 2)
+- /* back off */
+- usleep_range(500, 1000);
+-
+- if (time_after(jiffies, end))
+- return 0;
+-
+- if (have_drawable_releases && sc > 300) {
+- DMA_FENCE_WARN(fence,
+- "failed to wait on release %llu after spincount %d\n",
+- fence->context & ~0xf0000000, sc);
+- goto signaled;
+- }
+- goto retry;
+- }
+- /*
+- * yeah, original sync_obj_wait gave up after 3 spins when
+- * have_drawable_releases is not set.
+- */
++ if (!wait_event_timeout(qdev->release_event,
++ (dma_fence_is_signaled(fence) ||
++ (qxl_io_notify_oom(qdev), 0)),
++ timeout))
++ return 0;
+
+-signaled:
+ cur = jiffies;
+ if (time_after(cur, end))
+ return 0;
+diff --git a/drivers/gpu/drm/radeon/pptable.h b/drivers/gpu/drm/radeon/pptable.h
+index 94947229888ba..b7f22597ee95e 100644
+--- a/drivers/gpu/drm/radeon/pptable.h
++++ b/drivers/gpu/drm/radeon/pptable.h
+@@ -424,7 +424,7 @@ typedef struct _ATOM_PPLIB_SUMO_CLOCK_INFO{
+ typedef struct _ATOM_PPLIB_STATE_V2
+ {
+ //number of valid dpm levels in this state; Driver uses it to calculate the whole
+- //size of the state: sizeof(ATOM_PPLIB_STATE_V2) + (ucNumDPMLevels - 1) * sizeof(UCHAR)
++ //size of the state: struct_size(ATOM_PPLIB_STATE_V2, clockInfoIndex, ucNumDPMLevels)
+ UCHAR ucNumDPMLevels;
+
+ //a index to the array of nonClockInfos
+@@ -432,14 +432,14 @@ typedef struct _ATOM_PPLIB_STATE_V2
+ /**
+ * Driver will read the first ucNumDPMLevels in this array
+ */
+- UCHAR clockInfoIndex[1];
++ UCHAR clockInfoIndex[] __counted_by(ucNumDPMLevels);
+ } ATOM_PPLIB_STATE_V2;
+
+ typedef struct _StateArray{
+ //how many states we have
+ UCHAR ucNumEntries;
+
+- ATOM_PPLIB_STATE_V2 states[1];
++ ATOM_PPLIB_STATE_V2 states[] __counted_by(ucNumEntries);
+ }StateArray;
+
+
+@@ -450,7 +450,7 @@ typedef struct _ClockInfoArray{
+ //sizeof(ATOM_PPLIB_CLOCK_INFO)
+ UCHAR ucEntrySize;
+
+- UCHAR clockInfo[1];
++ UCHAR clockInfo[] __counted_by(ucNumEntries);
+ }ClockInfoArray;
+
+ typedef struct _NonClockInfoArray{
+@@ -460,7 +460,7 @@ typedef struct _NonClockInfoArray{
+ //sizeof(ATOM_PPLIB_NONCLOCK_INFO)
+ UCHAR ucEntrySize;
+
+- ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[1];
++ ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[] __counted_by(ucNumEntries);
+ }NonClockInfoArray;
+
+ typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Record
+diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c
+index 43eaffa7faae3..bf9601351fa35 100644
+--- a/drivers/gpu/drm/ttm/ttm_tt.c
++++ b/drivers/gpu/drm/ttm/ttm_tt.c
+@@ -92,7 +92,7 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc)
+ */
+ if (bdev->pool.use_dma_alloc && cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
+ page_flags |= TTM_TT_FLAG_DECRYPTED;
+- drm_info(ddev, "TT memory decryption enabled.");
++ drm_info_once(ddev, "TT memory decryption enabled.");
+ }
+
+ bo->ttm = bdev->funcs->ttm_tt_create(bo, page_flags);
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+index 4aac88cc5f913..ae796e0c64aa5 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+@@ -204,6 +204,7 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv,
+ VMW_BO_DOMAIN_VRAM,
+ VMW_BO_DOMAIN_VRAM);
+ buf->places[0].lpfn = PFN_UP(bo->resource->size);
++ buf->busy_places[0].lpfn = PFN_UP(bo->resource->size);
+ ret = ttm_bo_validate(bo, &buf->placement, &ctx);
+
+ /* For some reason we didn't end up at the start of vram */
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+index 2a0cda3247031..5efc6a766f64e 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+@@ -991,7 +991,7 @@ static int vmw_event_fence_action_create(struct drm_file *file_priv,
+ }
+
+ event->event.base.type = DRM_VMW_EVENT_FENCE_SIGNALED;
+- event->event.base.length = sizeof(*event);
++ event->event.base.length = sizeof(event->event);
+ event->event.user_data = user_data;
+
+ ret = drm_event_reserve_init(dev, file_priv, &event->base, &event->event.base);
+diff --git a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
+index 5d2a77b52db41..d9a81e6a4b85a 100644
+--- a/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
++++ b/drivers/gpu/drm/xe/compat-i915-headers/i915_drv.h
+@@ -84,7 +84,8 @@ static inline struct drm_i915_private *kdev_to_i915(struct device *kdev)
+ #define IS_ROCKETLAKE(dev_priv) IS_PLATFORM(dev_priv, XE_ROCKETLAKE)
+ #define IS_DG1(dev_priv) IS_PLATFORM(dev_priv, XE_DG1)
+ #define IS_ALDERLAKE_S(dev_priv) IS_PLATFORM(dev_priv, XE_ALDERLAKE_S)
+-#define IS_ALDERLAKE_P(dev_priv) IS_PLATFORM(dev_priv, XE_ALDERLAKE_P)
++#define IS_ALDERLAKE_P(dev_priv) (IS_PLATFORM(dev_priv, XE_ALDERLAKE_P) || \
++ IS_PLATFORM(dev_priv, XE_ALDERLAKE_N))
+ #define IS_XEHPSDV(dev_priv) (dev_priv && 0)
+ #define IS_DG2(dev_priv) IS_PLATFORM(dev_priv, XE_DG2)
+ #define IS_PONTEVECCHIO(dev_priv) IS_PLATFORM(dev_priv, XE_PVC)
+diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h
+index 5592774fc6903..81b8362e93406 100644
+--- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h
++++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h
+@@ -120,7 +120,7 @@
+ #define RING_EXECLIST_STATUS_LO(base) XE_REG((base) + 0x234)
+ #define RING_EXECLIST_STATUS_HI(base) XE_REG((base) + 0x234 + 4)
+
+-#define RING_CONTEXT_CONTROL(base) XE_REG((base) + 0x244)
++#define RING_CONTEXT_CONTROL(base) XE_REG((base) + 0x244, XE_REG_OPTION_MASKED)
+ #define CTX_CTRL_INHIBIT_SYN_CTX_SWITCH REG_BIT(3)
+ #define CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT REG_BIT(0)
+
+diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c
+index b38319d2801e0..72f04a656e8b1 100644
+--- a/drivers/gpu/drm/xe/xe_lrc.c
++++ b/drivers/gpu/drm/xe/xe_lrc.c
+@@ -95,7 +95,6 @@ static void set_offsets(u32 *regs,
+ #define REG16(x) \
+ (((x) >> 9) | BIT(7) | BUILD_BUG_ON_ZERO(x >= 0x10000)), \
+ (((x) >> 2) & 0x7f)
+-#define END 0
+ {
+ const u32 base = hwe->mmio_base;
+
+@@ -166,7 +165,7 @@ static const u8 gen12_xcs_offsets[] = {
+ REG16(0x274),
+ REG16(0x270),
+
+- END
++ 0
+ };
+
+ static const u8 dg2_xcs_offsets[] = {
+@@ -200,7 +199,7 @@ static const u8 dg2_xcs_offsets[] = {
+ REG16(0x274),
+ REG16(0x270),
+
+- END
++ 0
+ };
+
+ static const u8 gen12_rcs_offsets[] = {
+@@ -296,7 +295,7 @@ static const u8 gen12_rcs_offsets[] = {
+ REG(0x084),
+ NOP(1),
+
+- END
++ 0
+ };
+
+ static const u8 xehp_rcs_offsets[] = {
+@@ -337,7 +336,7 @@ static const u8 xehp_rcs_offsets[] = {
+ LRI(1, 0),
+ REG(0x0c8),
+
+- END
++ 0
+ };
+
+ static const u8 dg2_rcs_offsets[] = {
+@@ -380,7 +379,7 @@ static const u8 dg2_rcs_offsets[] = {
+ LRI(1, 0),
+ REG(0x0c8),
+
+- END
++ 0
+ };
+
+ static const u8 mtl_rcs_offsets[] = {
+@@ -423,7 +422,7 @@ static const u8 mtl_rcs_offsets[] = {
+ LRI(1, 0),
+ REG(0x0c8),
+
+- END
++ 0
+ };
+
+ #define XE2_CTX_COMMON \
+@@ -469,7 +468,7 @@ static const u8 xe2_rcs_offsets[] = {
+ LRI(1, 0), /* [0x47] */
+ REG(0x0c8), /* [0x48] R_PWR_CLK_STATE */
+
+- END
++ 0
+ };
+
+ static const u8 xe2_bcs_offsets[] = {
+@@ -480,16 +479,15 @@ static const u8 xe2_bcs_offsets[] = {
+ REG16(0x200), /* [0x42] BCS_SWCTRL */
+ REG16(0x204), /* [0x44] BLIT_CCTL */
+
+- END
++ 0
+ };
+
+ static const u8 xe2_xcs_offsets[] = {
+ XE2_CTX_COMMON,
+
+- END
++ 0
+ };
+
+-#undef END
+ #undef REG16
+ #undef REG
+ #undef LRI
+@@ -525,9 +523,8 @@ static const u8 *reg_offsets(struct xe_device *xe, enum xe_engine_class class)
+
+ static void set_context_control(u32 *regs, struct xe_hw_engine *hwe)
+ {
+- regs[CTX_CONTEXT_CONTROL] = _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH) |
+- _MASKED_BIT_DISABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT) |
+- CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT;
++ regs[CTX_CONTEXT_CONTROL] = _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH |
++ CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT);
+
+ /* TODO: Timestamp */
+ }
+diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
+index 70480c3056021..7a6ad3469d748 100644
+--- a/drivers/gpu/drm/xe/xe_migrate.c
++++ b/drivers/gpu/drm/xe/xe_migrate.c
+@@ -216,7 +216,7 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m,
+ if (vm->flags & XE_VM_FLAG_64K && level == 1)
+ flags = XE_PDE_64K;
+
+- entry = vm->pt_ops->pde_encode_bo(bo, map_ofs + (level - 1) *
++ entry = vm->pt_ops->pde_encode_bo(bo, map_ofs + (u64)(level - 1) *
+ XE_PAGE_SIZE, pat_index);
+ xe_map_wr(xe, &bo->vmap, map_ofs + XE_PAGE_SIZE * level, u64,
+ entry | flags);
+@@ -224,7 +224,7 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m,
+
+ /* Write PDE's that point to our BO. */
+ for (i = 0; i < num_entries - num_level; i++) {
+- entry = vm->pt_ops->pde_encode_bo(bo, i * XE_PAGE_SIZE,
++ entry = vm->pt_ops->pde_encode_bo(bo, (u64)i * XE_PAGE_SIZE,
+ pat_index);
+
+ xe_map_wr(xe, &bo->vmap, map_ofs + XE_PAGE_SIZE +
+@@ -280,7 +280,7 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m,
+ #define VM_SA_UPDATE_UNIT_SIZE (XE_PAGE_SIZE / NUM_VMUSA_UNIT_PER_PAGE)
+ #define NUM_VMUSA_WRITES_PER_UNIT (VM_SA_UPDATE_UNIT_SIZE / sizeof(u64))
+ drm_suballoc_manager_init(&m->vm_update_sa,
+- (map_ofs / XE_PAGE_SIZE - NUM_KERNEL_PDE) *
++ (size_t)(map_ofs / XE_PAGE_SIZE - NUM_KERNEL_PDE) *
+ NUM_VMUSA_UNIT_PER_PAGE, 0);
+
+ m->pt_bo = bo;
+@@ -479,7 +479,7 @@ static void emit_pte(struct xe_migrate *m,
+ struct xe_vm *vm = m->q->vm;
+ u16 pat_index;
+ u32 ptes;
+- u64 ofs = at_pt * XE_PAGE_SIZE;
++ u64 ofs = (u64)at_pt * XE_PAGE_SIZE;
+ u64 cur_ofs;
+
+ /* Indirect access needs compression enabled uncached PAT index */
+diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
+index 84d042796d2e6..3937889fa912d 100644
+--- a/drivers/gpu/host1x/bus.c
++++ b/drivers/gpu/host1x/bus.c
+@@ -351,11 +351,6 @@ static int host1x_device_uevent(const struct device *dev,
+ return 0;
+ }
+
+-static int host1x_dma_configure(struct device *dev)
+-{
+- return of_dma_configure(dev, dev->of_node, true);
+-}
+-
+ static const struct dev_pm_ops host1x_device_pm_ops = {
+ .suspend = pm_generic_suspend,
+ .resume = pm_generic_resume,
+@@ -369,7 +364,6 @@ struct bus_type host1x_bus_type = {
+ .name = "host1x",
+ .match = host1x_device_match,
+ .uevent = host1x_device_uevent,
+- .dma_configure = host1x_dma_configure,
+ .pm = &host1x_device_pm_ops,
+ };
+
+@@ -458,8 +452,6 @@ static int host1x_device_add(struct host1x *host1x,
+ device->dev.bus = &host1x_bus_type;
+ device->dev.parent = host1x->dev;
+
+- of_dma_configure(&device->dev, host1x->dev->of_node, true);
+-
+ device->dev.dma_parms = &device->dma_parms;
+ dma_set_max_seg_size(&device->dev, UINT_MAX);
+
+diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
+index adbf674355b2b..fb8cd8469328e 100644
+--- a/drivers/hv/channel.c
++++ b/drivers/hv/channel.c
+@@ -153,7 +153,9 @@ void vmbus_free_ring(struct vmbus_channel *channel)
+ hv_ringbuffer_cleanup(&channel->inbound);
+
+ if (channel->ringbuffer_page) {
+- __free_pages(channel->ringbuffer_page,
++ /* In a CoCo VM leak the memory if it didn't get re-encrypted */
++ if (!channel->ringbuffer_gpadlhandle.decrypted)
++ __free_pages(channel->ringbuffer_page,
+ get_order(channel->ringbuffer_pagecount
+ << PAGE_SHIFT));
+ channel->ringbuffer_page = NULL;
+@@ -436,9 +438,18 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
+ (atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1);
+
+ ret = create_gpadl_header(type, kbuffer, size, send_offset, &msginfo);
+- if (ret)
++ if (ret) {
++ gpadl->decrypted = false;
+ return ret;
++ }
+
++ /*
++ * Set the "decrypted" flag to true for the set_memory_decrypted()
++ * success case. In the failure case, the encryption state of the
++ * memory is unknown. Leave "decrypted" as true to ensure the
++ * memory will be leaked instead of going back on the free list.
++ */
++ gpadl->decrypted = true;
+ ret = set_memory_decrypted((unsigned long)kbuffer,
+ PFN_UP(size));
+ if (ret) {
+@@ -527,9 +538,15 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel,
+
+ kfree(msginfo);
+
+- if (ret)
+- set_memory_encrypted((unsigned long)kbuffer,
+- PFN_UP(size));
++ if (ret) {
++ /*
++ * If set_memory_encrypted() fails, the decrypted flag is
++ * left as true so the memory is leaked instead of being
++ * put back on the free list.
++ */
++ if (!set_memory_encrypted((unsigned long)kbuffer, PFN_UP(size)))
++ gpadl->decrypted = false;
++ }
+
+ return ret;
+ }
+@@ -850,6 +867,8 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, struct vmbus_gpadl *gpad
+ if (ret)
+ pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret);
+
++ gpadl->decrypted = ret;
++
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
+diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
+index 3cabeeabb1cac..f001ae880e1db 100644
+--- a/drivers/hv/connection.c
++++ b/drivers/hv/connection.c
+@@ -237,8 +237,17 @@ int vmbus_connect(void)
+ vmbus_connection.monitor_pages[0], 1);
+ ret |= set_memory_decrypted((unsigned long)
+ vmbus_connection.monitor_pages[1], 1);
+- if (ret)
++ if (ret) {
++ /*
++ * If set_memory_decrypted() fails, the encryption state
++ * of the memory is unknown. So leak the memory instead
++ * of risking returning decrypted memory to the free list.
++ * For simplicity, always handle both pages the same.
++ */
++ vmbus_connection.monitor_pages[0] = NULL;
++ vmbus_connection.monitor_pages[1] = NULL;
+ goto cleanup;
++ }
+
+ /*
+ * Set_memory_decrypted() will change the memory contents if
+@@ -337,13 +346,19 @@ void vmbus_disconnect(void)
+ vmbus_connection.int_page = NULL;
+ }
+
+- set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[0], 1);
+- set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[1], 1);
++ if (vmbus_connection.monitor_pages[0]) {
++ if (!set_memory_encrypted(
++ (unsigned long)vmbus_connection.monitor_pages[0], 1))
++ hv_free_hyperv_page(vmbus_connection.monitor_pages[0]);
++ vmbus_connection.monitor_pages[0] = NULL;
++ }
+
+- hv_free_hyperv_page(vmbus_connection.monitor_pages[0]);
+- hv_free_hyperv_page(vmbus_connection.monitor_pages[1]);
+- vmbus_connection.monitor_pages[0] = NULL;
+- vmbus_connection.monitor_pages[1] = NULL;
++ if (vmbus_connection.monitor_pages[1]) {
++ if (!set_memory_encrypted(
++ (unsigned long)vmbus_connection.monitor_pages[1], 1))
++ hv_free_hyperv_page(vmbus_connection.monitor_pages[1]);
++ vmbus_connection.monitor_pages[1] = NULL;
++ }
+ }
+
+ /*
+diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c
+index a284a02839fbb..3e63666a61bd6 100644
+--- a/drivers/hwmon/corsair-cpro.c
++++ b/drivers/hwmon/corsair-cpro.c
+@@ -16,6 +16,7 @@
+ #include <linux/module.h>
+ #include <linux/mutex.h>
+ #include <linux/slab.h>
++#include <linux/spinlock.h>
+ #include <linux/types.h>
+
+ #define USB_VENDOR_ID_CORSAIR 0x1b1c
+@@ -77,8 +78,11 @@
+ struct ccp_device {
+ struct hid_device *hdev;
+ struct device *hwmon_dev;
++ /* For reinitializing the completion below */
++ spinlock_t wait_input_report_lock;
+ struct completion wait_input_report;
+ struct mutex mutex; /* whenever buffer is used, lock before send_usb_cmd */
++ u8 *cmd_buffer;
+ u8 *buffer;
+ int target[6];
+ DECLARE_BITMAP(temp_cnct, NUM_TEMP_SENSORS);
+@@ -111,15 +115,23 @@ static int send_usb_cmd(struct ccp_device *ccp, u8 command, u8 byte1, u8 byte2,
+ unsigned long t;
+ int ret;
+
+- memset(ccp->buffer, 0x00, OUT_BUFFER_SIZE);
+- ccp->buffer[0] = command;
+- ccp->buffer[1] = byte1;
+- ccp->buffer[2] = byte2;
+- ccp->buffer[3] = byte3;
+-
++ memset(ccp->cmd_buffer, 0x00, OUT_BUFFER_SIZE);
++ ccp->cmd_buffer[0] = command;
++ ccp->cmd_buffer[1] = byte1;
++ ccp->cmd_buffer[2] = byte2;
++ ccp->cmd_buffer[3] = byte3;
++
++ /*
++ * Disable raw event parsing for a moment to safely reinitialize the
++ * completion. Reinit is done because hidraw could have triggered
++ * the raw event parsing and marked the ccp->wait_input_report
++ * completion as done.
++ */
++ spin_lock_bh(&ccp->wait_input_report_lock);
+ reinit_completion(&ccp->wait_input_report);
++ spin_unlock_bh(&ccp->wait_input_report_lock);
+
+- ret = hid_hw_output_report(ccp->hdev, ccp->buffer, OUT_BUFFER_SIZE);
++ ret = hid_hw_output_report(ccp->hdev, ccp->cmd_buffer, OUT_BUFFER_SIZE);
+ if (ret < 0)
+ return ret;
+
+@@ -135,11 +147,12 @@ static int ccp_raw_event(struct hid_device *hdev, struct hid_report *report, u8
+ struct ccp_device *ccp = hid_get_drvdata(hdev);
+
+ /* only copy buffer when requested */
+- if (completion_done(&ccp->wait_input_report))
+- return 0;
+-
+- memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size));
+- complete(&ccp->wait_input_report);
++ spin_lock(&ccp->wait_input_report_lock);
++ if (!completion_done(&ccp->wait_input_report)) {
++ memcpy(ccp->buffer, data, min(IN_BUFFER_SIZE, size));
++ complete_all(&ccp->wait_input_report);
++ }
++ spin_unlock(&ccp->wait_input_report_lock);
+
+ return 0;
+ }
+@@ -492,7 +505,11 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+ if (!ccp)
+ return -ENOMEM;
+
+- ccp->buffer = devm_kmalloc(&hdev->dev, OUT_BUFFER_SIZE, GFP_KERNEL);
++ ccp->cmd_buffer = devm_kmalloc(&hdev->dev, OUT_BUFFER_SIZE, GFP_KERNEL);
++ if (!ccp->cmd_buffer)
++ return -ENOMEM;
++
++ ccp->buffer = devm_kmalloc(&hdev->dev, IN_BUFFER_SIZE, GFP_KERNEL);
+ if (!ccp->buffer)
+ return -ENOMEM;
+
+@@ -510,7 +527,9 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
+
+ ccp->hdev = hdev;
+ hid_set_drvdata(hdev, ccp);
++
+ mutex_init(&ccp->mutex);
++ spin_lock_init(&ccp->wait_input_report_lock);
+ init_completion(&ccp->wait_input_report);
+
+ hid_device_io_start(hdev);
+diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c
+index 8d9d422450e5c..d817c719b90bd 100644
+--- a/drivers/hwmon/pmbus/ucd9000.c
++++ b/drivers/hwmon/pmbus/ucd9000.c
+@@ -80,11 +80,11 @@ struct ucd9000_debugfs_entry {
+ * It has been observed that the UCD90320 randomly fails register access when
+ * doing another access right on the back of a register write. To mitigate this
+ * make sure that there is a minimum delay between a write access and the
+- * following access. The 250us is based on experimental data. At a delay of
+- * 200us the issue seems to go away. Add a bit of extra margin to allow for
++ * following access. The 500 is based on experimental data. At a delay of
++ * 350us the issue seems to go away. Add a bit of extra margin to allow for
+ * system to system differences.
+ */
+-#define UCD90320_WAIT_DELAY_US 250
++#define UCD90320_WAIT_DELAY_US 500
+
+ static inline void ucd90320_wait(const struct ucd9000_data *data)
+ {
+diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c
+index 82e8d0b390495..49e30b87732f5 100644
+--- a/drivers/iio/accel/mxc4005.c
++++ b/drivers/iio/accel/mxc4005.c
+@@ -5,6 +5,7 @@
+ * Copyright (c) 2014, Intel Corporation.
+ */
+
++#include <linux/delay.h>
+ #include <linux/module.h>
+ #include <linux/i2c.h>
+ #include <linux/iio/iio.h>
+@@ -27,11 +28,16 @@
+ #define MXC4005_REG_ZOUT_UPPER 0x07
+ #define MXC4005_REG_ZOUT_LOWER 0x08
+
++#define MXC4005_REG_INT_MASK0 0x0A
++
+ #define MXC4005_REG_INT_MASK1 0x0B
+ #define MXC4005_REG_INT_MASK1_BIT_DRDYE 0x01
+
++#define MXC4005_REG_INT_CLR0 0x00
++
+ #define MXC4005_REG_INT_CLR1 0x01
+ #define MXC4005_REG_INT_CLR1_BIT_DRDYC 0x01
++#define MXC4005_REG_INT_CLR1_SW_RST 0x10
+
+ #define MXC4005_REG_CONTROL 0x0D
+ #define MXC4005_REG_CONTROL_MASK_FSR GENMASK(6, 5)
+@@ -39,6 +45,9 @@
+
+ #define MXC4005_REG_DEVICE_ID 0x0E
+
++/* Datasheet does not specify a reset time, this is a conservative guess */
++#define MXC4005_RESET_TIME_US 2000
++
+ enum mxc4005_axis {
+ AXIS_X,
+ AXIS_Y,
+@@ -62,6 +71,8 @@ struct mxc4005_data {
+ s64 timestamp __aligned(8);
+ } scan;
+ bool trigger_enabled;
++ unsigned int control;
++ unsigned int int_mask1;
+ };
+
+ /*
+@@ -113,7 +124,9 @@ static bool mxc4005_is_readable_reg(struct device *dev, unsigned int reg)
+ static bool mxc4005_is_writeable_reg(struct device *dev, unsigned int reg)
+ {
+ switch (reg) {
++ case MXC4005_REG_INT_CLR0:
+ case MXC4005_REG_INT_CLR1:
++ case MXC4005_REG_INT_MASK0:
+ case MXC4005_REG_INT_MASK1:
+ case MXC4005_REG_CONTROL:
+ return true;
+@@ -330,23 +343,20 @@ static int mxc4005_set_trigger_state(struct iio_trigger *trig,
+ {
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct mxc4005_data *data = iio_priv(indio_dev);
++ unsigned int val;
+ int ret;
+
+ mutex_lock(&data->mutex);
+- if (state) {
+- ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1,
+- MXC4005_REG_INT_MASK1_BIT_DRDYE);
+- } else {
+- ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1,
+- ~MXC4005_REG_INT_MASK1_BIT_DRDYE);
+- }
+
++ val = state ? MXC4005_REG_INT_MASK1_BIT_DRDYE : 0;
++ ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, val);
+ if (ret < 0) {
+ mutex_unlock(&data->mutex);
+ dev_err(data->dev, "failed to update reg_int_mask1");
+ return ret;
+ }
+
++ data->int_mask1 = val;
+ data->trigger_enabled = state;
+ mutex_unlock(&data->mutex);
+
+@@ -382,6 +392,21 @@ static int mxc4005_chip_init(struct mxc4005_data *data)
+
+ dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg);
+
++ ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
++ MXC4005_REG_INT_CLR1_SW_RST);
++ if (ret < 0)
++ return dev_err_probe(data->dev, ret, "resetting chip\n");
++
++ fsleep(MXC4005_RESET_TIME_US);
++
++ ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
++ if (ret < 0)
++ return dev_err_probe(data->dev, ret, "writing INT_MASK0\n");
++
++ ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, 0);
++ if (ret < 0)
++ return dev_err_probe(data->dev, ret, "writing INT_MASK1\n");
++
+ return 0;
+ }
+
+@@ -469,6 +494,58 @@ static int mxc4005_probe(struct i2c_client *client)
+ return devm_iio_device_register(&client->dev, indio_dev);
+ }
+
++static int mxc4005_suspend(struct device *dev)
++{
++ struct iio_dev *indio_dev = dev_get_drvdata(dev);
++ struct mxc4005_data *data = iio_priv(indio_dev);
++ int ret;
++
++ /* Save control to restore it on resume */
++ ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, &data->control);
++ if (ret < 0)
++ dev_err(data->dev, "failed to read reg_control\n");
++
++ return ret;
++}
++
++static int mxc4005_resume(struct device *dev)
++{
++ struct iio_dev *indio_dev = dev_get_drvdata(dev);
++ struct mxc4005_data *data = iio_priv(indio_dev);
++ int ret;
++
++ ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
++ MXC4005_REG_INT_CLR1_SW_RST);
++ if (ret) {
++ dev_err(data->dev, "failed to reset chip: %d\n", ret);
++ return ret;
++ }
++
++ fsleep(MXC4005_RESET_TIME_US);
++
++ ret = regmap_write(data->regmap, MXC4005_REG_CONTROL, data->control);
++ if (ret) {
++ dev_err(data->dev, "failed to restore control register\n");
++ return ret;
++ }
++
++ ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
++ if (ret) {
++ dev_err(data->dev, "failed to restore interrupt 0 mask\n");
++ return ret;
++ }
++
++ ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, data->int_mask1);
++ if (ret) {
++ dev_err(data->dev, "failed to restore interrupt 1 mask\n");
++ return ret;
++ }
++
++ return 0;
++}
++
++static DEFINE_SIMPLE_DEV_PM_OPS(mxc4005_pm_ops, mxc4005_suspend, mxc4005_resume);
++
+ static const struct acpi_device_id mxc4005_acpi_match[] = {
+ {"MXC4005", 0},
+ {"MXC6655", 0},
+@@ -495,6 +572,7 @@ static struct i2c_driver mxc4005_driver = {
+ .name = MXC4005_DRV_NAME,
+ .acpi_match_table = ACPI_PTR(mxc4005_acpi_match),
+ .of_match_table = mxc4005_of_match,
++ .pm = pm_sleep_ptr(&mxc4005_pm_ops),
+ },
+ .probe = mxc4005_probe,
+ .id_table = mxc4005_id,
+diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
+index 64be656f0b805..289b6c2bb2c28 100644
+--- a/drivers/iio/imu/adis16475.c
++++ b/drivers/iio/imu/adis16475.c
+@@ -1289,6 +1289,7 @@ static int adis16475_config_sync_mode(struct adis16475 *st)
+ struct device *dev = &st->adis.spi->dev;
+ const struct adis16475_sync *sync;
+ u32 sync_mode;
++ u16 val;
+
+ /* default to internal clk */
+ st->clk_freq = st->info->int_clk * 1000;
+@@ -1350,8 +1351,9 @@ static int adis16475_config_sync_mode(struct adis16475 *st)
+ * I'm keeping this for simplicity and avoiding extra variables
+ * in chip_info.
+ */
++ val = ADIS16475_SYNC_MODE(sync->sync_mode);
+ ret = __adis_update_bits(&st->adis, ADIS16475_REG_MSG_CTRL,
+- ADIS16475_SYNC_MODE_MASK, sync->sync_mode);
++ ADIS16475_SYNC_MODE_MASK, val);
+ if (ret)
+ return ret;
+
+diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
+index fe8734468ed35..62e9e93d915dc 100644
+--- a/drivers/iio/pressure/bmp280-core.c
++++ b/drivers/iio/pressure/bmp280-core.c
+@@ -1233,6 +1233,7 @@ const struct bmp280_chip_info bmp380_chip_info = {
+ .chip_id = bmp380_chip_ids,
+ .num_chip_id = ARRAY_SIZE(bmp380_chip_ids),
+ .regmap_config = &bmp380_regmap_config,
++ .spi_read_extra_byte = true,
+ .start_up_time = 2000,
+ .channels = bmp380_channels,
+ .num_channels = 2,
+diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c
+index a444d4b2978b5..4e19ea0b4d398 100644
+--- a/drivers/iio/pressure/bmp280-spi.c
++++ b/drivers/iio/pressure/bmp280-spi.c
+@@ -96,15 +96,10 @@ static int bmp280_spi_probe(struct spi_device *spi)
+
+ chip_info = spi_get_device_match_data(spi);
+
+- switch (chip_info->chip_id[0]) {
+- case BMP380_CHIP_ID:
+- case BMP390_CHIP_ID:
++ if (chip_info->spi_read_extra_byte)
+ bmp_regmap_bus = &bmp380_regmap_bus;
+- break;
+- default:
++ else
+ bmp_regmap_bus = &bmp280_regmap_bus;
+- break;
+- }
+
+ regmap = devm_regmap_init(&spi->dev,
+ bmp_regmap_bus,
+@@ -127,7 +122,7 @@ static const struct of_device_id bmp280_of_spi_match[] = {
+ { .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp181", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
+- { .compatible = "bosch,bme280", .data = &bmp280_chip_info },
++ { .compatible = "bosch,bme280", .data = &bme280_chip_info },
+ { .compatible = "bosch,bmp380", .data = &bmp380_chip_info },
+ { .compatible = "bosch,bmp580", .data = &bmp580_chip_info },
+ { },
+@@ -139,7 +134,7 @@ static const struct spi_device_id bmp280_spi_id[] = {
+ { "bmp180", (kernel_ulong_t)&bmp180_chip_info },
+ { "bmp181", (kernel_ulong_t)&bmp180_chip_info },
+ { "bmp280", (kernel_ulong_t)&bmp280_chip_info },
+- { "bme280", (kernel_ulong_t)&bmp280_chip_info },
++ { "bme280", (kernel_ulong_t)&bme280_chip_info },
+ { "bmp380", (kernel_ulong_t)&bmp380_chip_info },
+ { "bmp580", (kernel_ulong_t)&bmp580_chip_info },
+ { }
+diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
+index 4012387d79565..5812a344ed8e8 100644
+--- a/drivers/iio/pressure/bmp280.h
++++ b/drivers/iio/pressure/bmp280.h
+@@ -423,6 +423,7 @@ struct bmp280_chip_info {
+ int num_chip_id;
+
+ const struct regmap_config *regmap_config;
++ bool spi_read_extra_byte;
+
+ const struct iio_chan_spec *channels;
+ int num_channels;
+diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c
+index 455e966eeff39..b27791029fa93 100644
+--- a/drivers/infiniband/hw/qib/qib_fs.c
++++ b/drivers/infiniband/hw/qib/qib_fs.c
+@@ -439,6 +439,7 @@ static int remove_device_files(struct super_block *sb,
+ return PTR_ERR(dir);
+ }
+ simple_recursive_removal(dir, NULL);
++ dput(dir);
+ return 0;
+ }
+
+diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
+index 4283dd8191f05..f945bf3253ce0 100644
+--- a/drivers/iommu/amd/iommu.c
++++ b/drivers/iommu/amd/iommu.c
+@@ -2593,6 +2593,10 @@ static int amd_iommu_def_domain_type(struct device *dev)
+ if (!dev_data)
+ return 0;
+
++ /* Always use DMA domain for untrusted device */
++ if (dev_is_pci(dev) && to_pci_dev(dev)->untrusted)
++ return IOMMU_DOMAIN_DMA;
++
+ /*
+ * Do not identity map IOMMUv2 capable devices when:
+ * - memory encryption is active, because some of those devices
+diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c b/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
+index 87bf522b9d2ee..957d988b6d832 100644
+--- a/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
++++ b/drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
+@@ -221,11 +221,9 @@ static irqreturn_t nvidia_smmu_context_fault(int irq, void *dev)
+ unsigned int inst;
+ irqreturn_t ret = IRQ_NONE;
+ struct arm_smmu_device *smmu;
+- struct iommu_domain *domain = dev;
+- struct arm_smmu_domain *smmu_domain;
++ struct arm_smmu_domain *smmu_domain = dev;
+ struct nvidia_smmu *nvidia;
+
+- smmu_domain = container_of(domain, struct arm_smmu_domain, domain);
+ smmu = smmu_domain->smmu;
+ nvidia = to_nvidia_smmu(smmu);
+
+diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
+index 7abe9e85a5706..51d0eba8cbdf3 100644
+--- a/drivers/iommu/mtk_iommu.c
++++ b/drivers/iommu/mtk_iommu.c
+@@ -1789,6 +1789,7 @@ static const struct of_device_id mtk_iommu_of_ids[] = {
+ { .compatible = "mediatek,mt8365-m4u", .data = &mt8365_data},
+ {}
+ };
++MODULE_DEVICE_TABLE(of, mtk_iommu_of_ids);
+
+ static struct platform_driver mtk_iommu_driver = {
+ .probe = mtk_iommu_probe,
+diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
+index 25b41222abaec..32cc8341d3726 100644
+--- a/drivers/iommu/mtk_iommu_v1.c
++++ b/drivers/iommu/mtk_iommu_v1.c
+@@ -599,6 +599,7 @@ static const struct of_device_id mtk_iommu_v1_of_ids[] = {
+ { .compatible = "mediatek,mt2701-m4u", },
+ {}
+ };
++MODULE_DEVICE_TABLE(of, mtk_iommu_v1_of_ids);
+
+ static const struct component_master_ops mtk_iommu_v1_com_ops = {
+ .bind = mtk_iommu_v1_bind,
+diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
+index aac36750d2c54..c3a6657dcd4a2 100644
+--- a/drivers/misc/mei/hw-me-regs.h
++++ b/drivers/misc/mei/hw-me-regs.h
+@@ -115,6 +115,8 @@
+ #define MEI_DEV_ID_ARL_S 0x7F68 /* Arrow Lake Point S */
+ #define MEI_DEV_ID_ARL_H 0x7770 /* Arrow Lake Point H */
+
++#define MEI_DEV_ID_LNL_M 0xA870 /* Lunar Lake Point M */
++
+ /*
+ * MEI HW Section
+ */
+diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
+index bd4e3df44865e..3c2c28c8ba30a 100644
+--- a/drivers/misc/mei/pci-me.c
++++ b/drivers/misc/mei/pci-me.c
+@@ -122,6 +122,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
+ {MEI_PCI_DEVICE(MEI_DEV_ID_ARL_S, MEI_ME_PCH15_CFG)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_ARL_H, MEI_ME_PCH15_CFG)},
+
++ {MEI_PCI_DEVICE(MEI_DEV_ID_LNL_M, MEI_ME_PCH15_CFG)},
++
+ /* required last entry */
+ {0, }
+ };
+diff --git a/drivers/misc/pvpanic/pvpanic-pci.c b/drivers/misc/pvpanic/pvpanic-pci.c
+index 9ad20e82785bc..b21598a18f6da 100644
+--- a/drivers/misc/pvpanic/pvpanic-pci.c
++++ b/drivers/misc/pvpanic/pvpanic-pci.c
+@@ -44,8 +44,6 @@ static struct pci_driver pvpanic_pci_driver = {
+ .name = "pvpanic-pci",
+ .id_table = pvpanic_pci_id_tbl,
+ .probe = pvpanic_pci_probe,
+- .driver = {
+- .dev_groups = pvpanic_dev_groups,
+- },
++ .dev_groups = pvpanic_dev_groups,
+ };
+ module_pci_driver(pvpanic_pci_driver);
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
+index 32416d8802ca4..967d9136313f4 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -697,6 +697,18 @@ static void mv88e6352_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
+ }
+ }
+
++static void mv88e632x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
++ struct phylink_config *config)
++{
++ unsigned long *supported = config->supported_interfaces;
++
++ /* Translate the default cmode */
++ mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported);
++
++ config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 |
++ MAC_1000FD;
++}
++
+ static void mv88e6341_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
+ struct phylink_config *config)
+ {
+@@ -5090,7 +5102,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
+ .gpio_ops = &mv88e6352_gpio_ops,
+ .avb_ops = &mv88e6352_avb_ops,
+ .ptp_ops = &mv88e6352_ptp_ops,
+- .phylink_get_caps = mv88e6185_phylink_get_caps,
++ .phylink_get_caps = mv88e632x_phylink_get_caps,
+ };
+
+ static const struct mv88e6xxx_ops mv88e6321_ops = {
+@@ -5136,7 +5148,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
+ .gpio_ops = &mv88e6352_gpio_ops,
+ .avb_ops = &mv88e6352_avb_ops,
+ .ptp_ops = &mv88e6352_ptp_ops,
+- .phylink_get_caps = mv88e6185_phylink_get_caps,
++ .phylink_get_caps = mv88e632x_phylink_get_caps,
+ };
+
+ static const struct mv88e6xxx_ops mv88e6341_ops = {
+@@ -5702,7 +5714,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
+ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6141,
+ .family = MV88E6XXX_FAMILY_6341,
+ .name = "Marvell 88E6141",
+- .num_databases = 4096,
++ .num_databases = 256,
+ .num_macs = 2048,
+ .num_ports = 6,
+ .num_internal_phys = 5,
+@@ -6161,7 +6173,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
+ .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6341,
+ .family = MV88E6XXX_FAMILY_6341,
+ .name = "Marvell 88E6341",
+- .num_databases = 4096,
++ .num_databases = 256,
+ .num_macs = 2048,
+ .num_internal_phys = 5,
+ .num_ports = 6,
+diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+index 2d7ae71287b14..cefb9f34d57b0 100644
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+@@ -2,7 +2,7 @@
+ /*
+ * Broadcom GENET (Gigabit Ethernet) controller driver
+ *
+- * Copyright (c) 2014-2020 Broadcom
++ * Copyright (c) 2014-2024 Broadcom
+ */
+
+ #define pr_fmt(fmt) "bcmgenet: " fmt
+@@ -2469,14 +2469,18 @@ static void umac_enable_set(struct bcmgenet_priv *priv, u32 mask, bool enable)
+ {
+ u32 reg;
+
++ spin_lock_bh(&priv->reg_lock);
+ reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+- if (reg & CMD_SW_RESET)
++ if (reg & CMD_SW_RESET) {
++ spin_unlock_bh(&priv->reg_lock);
+ return;
++ }
+ if (enable)
+ reg |= mask;
+ else
+ reg &= ~mask;
+ bcmgenet_umac_writel(priv, reg, UMAC_CMD);
++ spin_unlock_bh(&priv->reg_lock);
+
+ /* UniMAC stops on a packet boundary, wait for a full-size packet
+ * to be processed
+@@ -2492,8 +2496,10 @@ static void reset_umac(struct bcmgenet_priv *priv)
+ udelay(10);
+
+ /* issue soft reset and disable MAC while updating its registers */
++ spin_lock_bh(&priv->reg_lock);
+ bcmgenet_umac_writel(priv, CMD_SW_RESET, UMAC_CMD);
+ udelay(2);
++ spin_unlock_bh(&priv->reg_lock);
+ }
+
+ static void bcmgenet_intr_disable(struct bcmgenet_priv *priv)
+@@ -3282,7 +3288,7 @@ static void bcmgenet_get_hw_addr(struct bcmgenet_priv *priv,
+ }
+
+ /* Returns a reusable dma control register value */
+-static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv)
++static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv, bool flush_rx)
+ {
+ unsigned int i;
+ u32 reg;
+@@ -3307,6 +3313,14 @@ static u32 bcmgenet_dma_disable(struct bcmgenet_priv *priv)
+ udelay(10);
+ bcmgenet_umac_writel(priv, 0, UMAC_TX_FLUSH);
+
++ if (flush_rx) {
++ reg = bcmgenet_rbuf_ctrl_get(priv);
++ bcmgenet_rbuf_ctrl_set(priv, reg | BIT(0));
++ udelay(10);
++ bcmgenet_rbuf_ctrl_set(priv, reg);
++ udelay(10);
++ }
++
+ return dma_ctrl;
+ }
+
+@@ -3328,7 +3342,9 @@ static void bcmgenet_netif_start(struct net_device *dev)
+ struct bcmgenet_priv *priv = netdev_priv(dev);
+
+ /* Start the network engine */
++ netif_addr_lock_bh(dev);
+ bcmgenet_set_rx_mode(dev);
++ netif_addr_unlock_bh(dev);
+ bcmgenet_enable_rx_napi(priv);
+
+ umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true);
+@@ -3370,8 +3386,8 @@ static int bcmgenet_open(struct net_device *dev)
+
+ bcmgenet_set_hw_addr(priv, dev->dev_addr);
+
+- /* Disable RX/TX DMA and flush TX queues */
+- dma_ctrl = bcmgenet_dma_disable(priv);
++ /* Disable RX/TX DMA and flush TX and RX queues */
++ dma_ctrl = bcmgenet_dma_disable(priv, true);
+
+ /* Reinitialize TDMA and RDMA and SW housekeeping */
+ ret = bcmgenet_init_dma(priv);
+@@ -3589,16 +3605,19 @@ static void bcmgenet_set_rx_mode(struct net_device *dev)
+ * 3. The number of filters needed exceeds the number filters
+ * supported by the hardware.
+ */
++ spin_lock(&priv->reg_lock);
+ reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+ if ((dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) ||
+ (nfilter > MAX_MDF_FILTER)) {
+ reg |= CMD_PROMISC;
+ bcmgenet_umac_writel(priv, reg, UMAC_CMD);
++ spin_unlock(&priv->reg_lock);
+ bcmgenet_umac_writel(priv, 0, UMAC_MDF_CTRL);
+ return;
+ } else {
+ reg &= ~CMD_PROMISC;
+ bcmgenet_umac_writel(priv, reg, UMAC_CMD);
++ spin_unlock(&priv->reg_lock);
+ }
+
+ /* update MDF filter */
+@@ -3997,6 +4016,7 @@ static int bcmgenet_probe(struct platform_device *pdev)
+ goto err;
+ }
+
++ spin_lock_init(&priv->reg_lock);
+ spin_lock_init(&priv->lock);
+
+ /* Set default pause parameters */
+@@ -4237,7 +4257,7 @@ static int bcmgenet_resume(struct device *d)
+ bcmgenet_hfb_create_rxnfc_filter(priv, rule);
+
+ /* Disable RX/TX DMA and flush TX queues */
+- dma_ctrl = bcmgenet_dma_disable(priv);
++ dma_ctrl = bcmgenet_dma_disable(priv, false);
+
+ /* Reinitialize TDMA and RDMA and SW housekeeping */
+ ret = bcmgenet_init_dma(priv);
+diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+index 1985c0ec4da2a..28e2c94ef835c 100644
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+@@ -1,6 +1,6 @@
+ /* SPDX-License-Identifier: GPL-2.0-only */
+ /*
+- * Copyright (c) 2014-2020 Broadcom
++ * Copyright (c) 2014-2024 Broadcom
+ */
+
+ #ifndef __BCMGENET_H__
+@@ -573,6 +573,8 @@ struct bcmgenet_rxnfc_rule {
+ /* device context */
+ struct bcmgenet_priv {
+ void __iomem *base;
++ /* reg_lock: lock to serialize access to shared registers */
++ spinlock_t reg_lock;
+ enum bcmgenet_version version;
+ struct net_device *dev;
+
+diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+index 7a41cad5788f4..1248792d7fd4d 100644
+--- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c
+@@ -2,7 +2,7 @@
+ /*
+ * Broadcom GENET (Gigabit Ethernet) Wake-on-LAN support
+ *
+- * Copyright (c) 2014-2020 Broadcom
++ * Copyright (c) 2014-2024 Broadcom
+ */
+
+ #define pr_fmt(fmt) "bcmgenet_wol: " fmt
+@@ -151,6 +151,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
+ }
+
+ /* Can't suspend with WoL if MAC is still in reset */
++ spin_lock_bh(&priv->reg_lock);
+ reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+ if (reg & CMD_SW_RESET)
+ reg &= ~CMD_SW_RESET;
+@@ -158,6 +159,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
+ /* disable RX */
+ reg &= ~CMD_RX_EN;
+ bcmgenet_umac_writel(priv, reg, UMAC_CMD);
++ spin_unlock_bh(&priv->reg_lock);
+ mdelay(10);
+
+ if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) {
+@@ -203,6 +205,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
+ }
+
+ /* Enable CRC forward */
++ spin_lock_bh(&priv->reg_lock);
+ reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+ priv->crc_fwd_en = 1;
+ reg |= CMD_CRC_FWD;
+@@ -210,6 +213,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv,
+ /* Receiver must be enabled for WOL MP detection */
+ reg |= CMD_RX_EN;
+ bcmgenet_umac_writel(priv, reg, UMAC_CMD);
++ spin_unlock_bh(&priv->reg_lock);
+
+ reg = UMAC_IRQ_MPD_R;
+ if (hfb_enable)
+@@ -256,7 +260,9 @@ void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv,
+ }
+
+ /* Disable CRC Forward */
++ spin_lock_bh(&priv->reg_lock);
+ reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+ reg &= ~CMD_CRC_FWD;
+ bcmgenet_umac_writel(priv, reg, UMAC_CMD);
++ spin_unlock_bh(&priv->reg_lock);
+ }
+diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
+index 97ea76d443abe..e7c659cd39746 100644
+--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
++++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
+@@ -2,7 +2,7 @@
+ /*
+ * Broadcom GENET MDIO routines
+ *
+- * Copyright (c) 2014-2017 Broadcom
++ * Copyright (c) 2014-2024 Broadcom
+ */
+
+ #include <linux/acpi.h>
+@@ -75,6 +75,7 @@ static void bcmgenet_mac_config(struct net_device *dev)
+ reg |= RGMII_LINK;
+ bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
+
++ spin_lock_bh(&priv->reg_lock);
+ reg = bcmgenet_umac_readl(priv, UMAC_CMD);
+ reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
+ CMD_HD_EN |
+@@ -87,6 +88,7 @@ static void bcmgenet_mac_config(struct net_device *dev)
+ reg |= CMD_TX_EN | CMD_RX_EN;
+ }
+ bcmgenet_umac_writel(priv, reg, UMAC_CMD);
++ spin_unlock_bh(&priv->reg_lock);
+
+ priv->eee.eee_active = phy_init_eee(phydev, 0) >= 0;
+ bcmgenet_eee_enable_set(dev,
+@@ -274,6 +276,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
+ * block for the interface to work, unconditionally clear the
+ * Out-of-band disable since we do not need it.
+ */
++ mutex_lock(&phydev->lock);
+ reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
+ reg &= ~OOB_DISABLE;
+ if (priv->ext_phy) {
+@@ -285,6 +288,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)
+ reg |= RGMII_MODE_EN;
+ }
+ bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
++ mutex_unlock(&phydev->lock);
+
+ if (init)
+ dev_info(kdev, "configuring instance for %s\n", phy_name);
+diff --git a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
+index 7246e13dd559f..97291bfbeea58 100644
+--- a/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
++++ b/drivers/net/ethernet/brocade/bna/bnad_debugfs.c
+@@ -312,7 +312,7 @@ bnad_debugfs_write_regrd(struct file *file, const char __user *buf,
+ void *kern_buf;
+
+ /* Copy the user space buf */
+- kern_buf = memdup_user(buf, nbytes);
++ kern_buf = memdup_user_nul(buf, nbytes);
+ if (IS_ERR(kern_buf))
+ return PTR_ERR(kern_buf);
+
+@@ -372,7 +372,7 @@ bnad_debugfs_write_regwr(struct file *file, const char __user *buf,
+ void *kern_buf;
+
+ /* Copy the user space buf */
+- kern_buf = memdup_user(buf, nbytes);
++ kern_buf = memdup_user_nul(buf, nbytes);
+ if (IS_ERR(kern_buf))
+ return PTR_ERR(kern_buf);
+
+diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
+index b5ff2e1a9975f..2285f2e87e689 100644
+--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
++++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
+@@ -2684,12 +2684,12 @@ int cxgb4_selftest_lb_pkt(struct net_device *netdev)
+ lb->loopback = 1;
+
+ q = &adap->sge.ethtxq[pi->first_qset];
+- __netif_tx_lock(q->txq, smp_processor_id());
++ __netif_tx_lock_bh(q->txq);
+
+ reclaim_completed_tx(adap, &q->q, -1, true);
+ credits = txq_avail(&q->q) - ndesc;
+ if (unlikely(credits < 0)) {
+- __netif_tx_unlock(q->txq);
++ __netif_tx_unlock_bh(q->txq);
+ return -ENOMEM;
+ }
+
+@@ -2724,7 +2724,7 @@ int cxgb4_selftest_lb_pkt(struct net_device *netdev)
+ init_completion(&lb->completion);
+ txq_advance(&q->q, ndesc);
+ cxgb4_ring_tx_db(adap, &q->q, ndesc);
+- __netif_tx_unlock(q->txq);
++ __netif_tx_unlock_bh(q->txq);
+
+ /* wait for the pkt to return */
+ ret = wait_for_completion_timeout(&lb->completion, 10 * HZ);
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+index d7e175a9cb49b..2f7195ba4902b 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
++++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+@@ -895,7 +895,7 @@ struct hnae3_handle {
+ struct hnae3_roce_private_info rinfo;
+ };
+
+- u32 numa_node_mask; /* for multi-chip support */
++ nodemask_t numa_node_mask; /* for multi-chip support */
+
+ enum hnae3_port_base_vlan_state port_base_vlan_state;
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+index a3b7723a97bb1..c55b5430b75a9 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+@@ -1524,6 +1524,9 @@ static int hclge_configure(struct hclge_dev *hdev)
+ cfg.default_speed, ret);
+ return ret;
+ }
++ hdev->hw.mac.req_speed = hdev->hw.mac.speed;
++ hdev->hw.mac.req_autoneg = AUTONEG_ENABLE;
++ hdev->hw.mac.req_duplex = DUPLEX_FULL;
+
+ hclge_parse_link_mode(hdev, cfg.speed_ability);
+
+@@ -1753,7 +1756,8 @@ static int hclge_vport_setup(struct hclge_vport *vport, u16 num_tqps)
+
+ nic->pdev = hdev->pdev;
+ nic->ae_algo = &ae_algo;
+- nic->numa_node_mask = hdev->numa_node_mask;
++ bitmap_copy(nic->numa_node_mask.bits, hdev->numa_node_mask.bits,
++ MAX_NUMNODES);
+ nic->kinfo.io_base = hdev->hw.hw.io_base;
+
+ ret = hclge_knic_setup(vport, num_tqps,
+@@ -2445,7 +2449,8 @@ static int hclge_init_roce_base_info(struct hclge_vport *vport)
+
+ roce->pdev = nic->pdev;
+ roce->ae_algo = nic->ae_algo;
+- roce->numa_node_mask = nic->numa_node_mask;
++ bitmap_copy(roce->numa_node_mask.bits, nic->numa_node_mask.bits,
++ MAX_NUMNODES);
+
+ return 0;
+ }
+@@ -3329,9 +3334,9 @@ hclge_set_phy_link_ksettings(struct hnae3_handle *handle,
+ return ret;
+ }
+
+- hdev->hw.mac.autoneg = cmd->base.autoneg;
+- hdev->hw.mac.speed = cmd->base.speed;
+- hdev->hw.mac.duplex = cmd->base.duplex;
++ hdev->hw.mac.req_autoneg = cmd->base.autoneg;
++ hdev->hw.mac.req_speed = cmd->base.speed;
++ hdev->hw.mac.req_duplex = cmd->base.duplex;
+ linkmode_copy(hdev->hw.mac.advertising, cmd->link_modes.advertising);
+
+ return 0;
+@@ -3364,9 +3369,9 @@ static int hclge_tp_port_init(struct hclge_dev *hdev)
+ if (!hnae3_dev_phy_imp_supported(hdev))
+ return 0;
+
+- cmd.base.autoneg = hdev->hw.mac.autoneg;
+- cmd.base.speed = hdev->hw.mac.speed;
+- cmd.base.duplex = hdev->hw.mac.duplex;
++ cmd.base.autoneg = hdev->hw.mac.req_autoneg;
++ cmd.base.speed = hdev->hw.mac.req_speed;
++ cmd.base.duplex = hdev->hw.mac.req_duplex;
+ linkmode_copy(cmd.link_modes.advertising, hdev->hw.mac.advertising);
+
+ return hclge_set_phy_link_ksettings(&hdev->vport->nic, &cmd);
+@@ -7939,8 +7944,7 @@ static void hclge_set_timer_task(struct hnae3_handle *handle, bool enable)
+ /* Set the DOWN flag here to disable link updating */
+ set_bit(HCLGE_STATE_DOWN, &hdev->state);
+
+- /* flush memory to make sure DOWN is seen by service task */
+- smp_mb__before_atomic();
++ smp_mb__after_atomic(); /* flush memory to make sure DOWN is seen by service task */
+ hclge_flush_link_update(hdev);
+ }
+ }
+@@ -9893,6 +9897,7 @@ static int hclge_set_vlan_protocol_type(struct hclge_dev *hdev)
+ static int hclge_init_vlan_filter(struct hclge_dev *hdev)
+ {
+ struct hclge_vport *vport;
++ bool enable = true;
+ int ret;
+ int i;
+
+@@ -9912,8 +9917,12 @@ static int hclge_init_vlan_filter(struct hclge_dev *hdev)
+ vport->cur_vlan_fltr_en = true;
+ }
+
++ if (test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, hdev->ae_dev->caps) &&
++ !test_bit(HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B, hdev->ae_dev->caps))
++ enable = false;
++
+ return hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_PORT,
+- HCLGE_FILTER_FE_INGRESS, true, 0);
++ HCLGE_FILTER_FE_INGRESS, enable, 0);
+ }
+
+ static int hclge_init_vlan_type(struct hclge_dev *hdev)
+@@ -11609,16 +11618,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
+ if (ret)
+ goto out;
+
+- ret = hclge_devlink_init(hdev);
+- if (ret)
+- goto err_pci_uninit;
+-
+- devl_lock(hdev->devlink);
+-
+ /* Firmware command queue initialize */
+ ret = hclge_comm_cmd_queue_init(hdev->pdev, &hdev->hw.hw);
+ if (ret)
+- goto err_devlink_uninit;
++ goto err_pci_uninit;
+
+ /* Firmware command initialize */
+ ret = hclge_comm_cmd_init(hdev->ae_dev, &hdev->hw.hw, &hdev->fw_version,
+@@ -11746,7 +11749,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
+
+ ret = hclge_update_port_info(hdev);
+ if (ret)
+- goto err_mdiobus_unreg;
++ goto err_ptp_uninit;
+
+ INIT_KFIFO(hdev->mac_tnl_log);
+
+@@ -11786,6 +11789,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
+ dev_warn(&pdev->dev,
+ "failed to wake on lan init, ret = %d\n", ret);
+
++ ret = hclge_devlink_init(hdev);
++ if (ret)
++ goto err_ptp_uninit;
++
+ hclge_state_init(hdev);
+ hdev->last_reset_time = jiffies;
+
+@@ -11793,10 +11800,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
+ HCLGE_DRIVER_NAME);
+
+ hclge_task_schedule(hdev, round_jiffies_relative(HZ));
+-
+- devl_unlock(hdev->devlink);
+ return 0;
+
++err_ptp_uninit:
++ hclge_ptp_uninit(hdev);
+ err_mdiobus_unreg:
+ if (hdev->hw.mac.phydev)
+ mdiobus_unregister(hdev->hw.mac.mdio_bus);
+@@ -11806,9 +11813,6 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
+ pci_free_irq_vectors(pdev);
+ err_cmd_uninit:
+ hclge_comm_cmd_uninit(hdev->ae_dev, &hdev->hw.hw);
+-err_devlink_uninit:
+- devl_unlock(hdev->devlink);
+- hclge_devlink_uninit(hdev);
+ err_pci_uninit:
+ pcim_iounmap(pdev, hdev->hw.hw.io_base);
+ pci_release_regions(pdev);
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+index 51979cf712623..d4a146c53c5e9 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+@@ -270,11 +270,14 @@ struct hclge_mac {
+ u8 media_type; /* port media type, e.g. fibre/copper/backplane */
+ u8 mac_addr[ETH_ALEN];
+ u8 autoneg;
++ u8 req_autoneg;
+ u8 duplex;
++ u8 req_duplex;
+ u8 support_autoneg;
+ u8 speed_type; /* 0: sfp speed, 1: active speed */
+ u8 lane_num;
+ u32 speed;
++ u32 req_speed;
+ u32 max_speed;
+ u32 speed_ability; /* speed ability supported by current media */
+ u32 module_type; /* sub media type, e.g. kr/cr/sr/lr */
+@@ -882,7 +885,7 @@ struct hclge_dev {
+
+ u16 fdir_pf_filter_count; /* Num of guaranteed filters for this PF */
+ u16 num_alloc_vport; /* Num vports this driver supports */
+- u32 numa_node_mask;
++ nodemask_t numa_node_mask;
+ u16 rx_buf_len;
+ u16 num_tx_desc; /* desc num of per tx queue */
+ u16 num_rx_desc; /* desc num of per rx queue */
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+index 4b0d07ca2505e..a44659906ca0e 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
+@@ -1077,12 +1077,13 @@ static void hclge_mbx_request_handling(struct hclge_mbx_ops_param *param)
+
+ hdev = param->vport->back;
+ cmd_func = hclge_mbx_ops_list[param->req->msg.code];
+- if (cmd_func)
+- ret = cmd_func(param);
+- else
++ if (!cmd_func) {
+ dev_err(&hdev->pdev->dev,
+ "un-supported mailbox message, code = %u\n",
+ param->req->msg.code);
++ return;
++ }
++ ret = cmd_func(param);
+
+ /* PF driver should not reply IMP */
+ if (hnae3_get_bit(param->req->mbx_need_resp, HCLGE_MBX_NEED_RESP_B) &&
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+index 0aa9beefd1c7e..43ee20eb03d1f 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+@@ -412,7 +412,8 @@ static int hclgevf_set_handle_info(struct hclgevf_dev *hdev)
+
+ nic->ae_algo = &ae_algovf;
+ nic->pdev = hdev->pdev;
+- nic->numa_node_mask = hdev->numa_node_mask;
++ bitmap_copy(nic->numa_node_mask.bits, hdev->numa_node_mask.bits,
++ MAX_NUMNODES);
+ nic->flags |= HNAE3_SUPPORT_VF;
+ nic->kinfo.io_base = hdev->hw.hw.io_base;
+
+@@ -2082,8 +2083,8 @@ static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev)
+
+ roce->pdev = nic->pdev;
+ roce->ae_algo = nic->ae_algo;
+- roce->numa_node_mask = nic->numa_node_mask;
+-
++ bitmap_copy(roce->numa_node_mask.bits, nic->numa_node_mask.bits,
++ MAX_NUMNODES);
+ return 0;
+ }
+
+@@ -2180,8 +2181,7 @@ static void hclgevf_set_timer_task(struct hnae3_handle *handle, bool enable)
+ } else {
+ set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
+
+- /* flush memory to make sure DOWN is seen by service task */
+- smp_mb__before_atomic();
++ smp_mb__after_atomic(); /* flush memory to make sure DOWN is seen by service task */
+ hclgevf_flush_link_update(hdev);
+ }
+ }
+@@ -2845,10 +2845,6 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
+ if (ret)
+ return ret;
+
+- ret = hclgevf_devlink_init(hdev);
+- if (ret)
+- goto err_devlink_init;
+-
+ ret = hclge_comm_cmd_queue_init(hdev->pdev, &hdev->hw.hw);
+ if (ret)
+ goto err_cmd_queue_init;
+@@ -2941,6 +2937,10 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
+
+ hclgevf_init_rxd_adv_layout(hdev);
+
++ ret = hclgevf_devlink_init(hdev);
++ if (ret)
++ goto err_config;
++
+ set_bit(HCLGEVF_STATE_SERVICE_INITED, &hdev->state);
+
+ hdev->last_reset_time = jiffies;
+@@ -2960,8 +2960,6 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
+ err_cmd_init:
+ hclge_comm_cmd_uninit(hdev->ae_dev, &hdev->hw.hw);
+ err_cmd_queue_init:
+- hclgevf_devlink_uninit(hdev);
+-err_devlink_init:
+ hclgevf_pci_uninit(hdev);
+ clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
+ return ret;
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
+index a73f2bf3a56a6..cccef32284616 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
+@@ -236,7 +236,7 @@ struct hclgevf_dev {
+ u16 rss_size_max; /* HW defined max RSS task queue */
+
+ u16 num_alloc_vport; /* num vports this driver supports */
+- u32 numa_node_mask;
++ nodemask_t numa_node_mask;
+ u16 rx_buf_len;
+ u16 num_tx_desc; /* desc num of per tx queue */
+ u16 num_rx_desc; /* desc num of per rx queue */
+diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c
+index 93544f1cc2a51..f7ae0e0aa4a4f 100644
+--- a/drivers/net/ethernet/intel/e1000e/phy.c
++++ b/drivers/net/ethernet/intel/e1000e/phy.c
+@@ -157,7 +157,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+ * the lower time out
+ */
+ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
+- usleep_range(50, 60);
++ udelay(50);
+ mdic = er32(MDIC);
+ if (mdic & E1000_MDIC_READY)
+ break;
+@@ -181,7 +181,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
+ * reading duplicate data in the next MDIC transaction.
+ */
+ if (hw->mac.type == e1000_pch2lan)
+- usleep_range(100, 150);
++ udelay(100);
+
+ if (success) {
+ *data = (u16)mdic;
+@@ -237,7 +237,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+ * the lower time out
+ */
+ for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
+- usleep_range(50, 60);
++ udelay(50);
+ mdic = er32(MDIC);
+ if (mdic & E1000_MDIC_READY)
+ break;
+@@ -261,7 +261,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
+ * reading duplicate data in the next MDIC transaction.
+ */
+ if (hw->mac.type == e1000_pch2lan)
+- usleep_range(100, 150);
++ udelay(100);
+
+ if (success)
+ return 0;
+diff --git a/drivers/net/ethernet/intel/ice/ice_debugfs.c b/drivers/net/ethernet/intel/ice/ice_debugfs.c
+index c2bfba6b9ead6..66aa9759c8e7e 100644
+--- a/drivers/net/ethernet/intel/ice/ice_debugfs.c
++++ b/drivers/net/ethernet/intel/ice/ice_debugfs.c
+@@ -174,7 +174,7 @@ ice_debugfs_module_write(struct file *filp, const char __user *buf,
+ if (*ppos != 0 || count > 8)
+ return -EINVAL;
+
+- cmd_buf = memdup_user(buf, count);
++ cmd_buf = memdup_user_nul(buf, count);
+ if (IS_ERR(cmd_buf))
+ return PTR_ERR(cmd_buf);
+
+@@ -260,7 +260,7 @@ ice_debugfs_nr_messages_write(struct file *filp, const char __user *buf,
+ if (*ppos != 0 || count > 4)
+ return -EINVAL;
+
+- cmd_buf = memdup_user(buf, count);
++ cmd_buf = memdup_user_nul(buf, count);
+ if (IS_ERR(cmd_buf))
+ return PTR_ERR(cmd_buf);
+
+@@ -335,7 +335,7 @@ ice_debugfs_enable_write(struct file *filp, const char __user *buf,
+ if (*ppos != 0 || count > 2)
+ return -EINVAL;
+
+- cmd_buf = memdup_user(buf, count);
++ cmd_buf = memdup_user_nul(buf, count);
+ if (IS_ERR(cmd_buf))
+ return PTR_ERR(cmd_buf);
+
+@@ -431,7 +431,7 @@ ice_debugfs_log_size_write(struct file *filp, const char __user *buf,
+ if (*ppos != 0 || count > 5)
+ return -EINVAL;
+
+- cmd_buf = memdup_user(buf, count);
++ cmd_buf = memdup_user_nul(buf, count);
+ if (IS_ERR(cmd_buf))
+ return PTR_ERR(cmd_buf);
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
+index e6d7914ce61c4..e7eca8141e8c7 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c
+@@ -999,12 +999,10 @@ static ssize_t rvu_dbg_qsize_write(struct file *filp,
+ u16 pcifunc;
+ int ret, lf;
+
+- cmd_buf = memdup_user(buffer, count + 1);
++ cmd_buf = memdup_user_nul(buffer, count);
+ if (IS_ERR(cmd_buf))
+ return -ENOMEM;
+
+- cmd_buf[count] = '\0';
+-
+ cmd_buf_tmp = strchr(cmd_buf, '\n');
+ if (cmd_buf_tmp) {
+ *cmd_buf_tmp = '\0';
+diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c
+index d4cdf3d4f5525..502518cdb4618 100644
+--- a/drivers/net/ethernet/micrel/ks8851_common.c
++++ b/drivers/net/ethernet/micrel/ks8851_common.c
+@@ -234,12 +234,13 @@ static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt)
+ /**
+ * ks8851_rx_pkts - receive packets from the host
+ * @ks: The device information.
++ * @rxq: Queue of packets received in this function.
+ *
+ * This is called from the IRQ work queue when the system detects that there
+ * are packets in the receive queue. Find out how many packets there are and
+ * read them from the FIFO.
+ */
+-static void ks8851_rx_pkts(struct ks8851_net *ks)
++static void ks8851_rx_pkts(struct ks8851_net *ks, struct sk_buff_head *rxq)
+ {
+ struct sk_buff *skb;
+ unsigned rxfc;
+@@ -299,7 +300,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
+ ks8851_dbg_dumpkkt(ks, rxpkt);
+
+ skb->protocol = eth_type_trans(skb, ks->netdev);
+- __netif_rx(skb);
++ __skb_queue_tail(rxq, skb);
+
+ ks->netdev->stats.rx_packets++;
+ ks->netdev->stats.rx_bytes += rxlen;
+@@ -326,11 +327,11 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
+ static irqreturn_t ks8851_irq(int irq, void *_ks)
+ {
+ struct ks8851_net *ks = _ks;
++ struct sk_buff_head rxq;
+ unsigned handled = 0;
+ unsigned long flags;
+ unsigned int status;
+-
+- local_bh_disable();
++ struct sk_buff *skb;
+
+ ks8851_lock(ks, &flags);
+
+@@ -384,7 +385,8 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
+ * from the device so do not bother masking just the RX
+ * from the device. */
+
+- ks8851_rx_pkts(ks);
++ __skb_queue_head_init(&rxq);
++ ks8851_rx_pkts(ks, &rxq);
+ }
+
+ /* if something stopped the rx process, probably due to wanting
+@@ -408,7 +410,9 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
+ if (status & IRQ_LCI)
+ mii_check_link(&ks->mii);
+
+- local_bh_enable();
++ if (status & IRQ_RXI)
++ while ((skb = __skb_dequeue(&rxq)))
++ netif_rx(skb);
+
+ return IRQ_HANDLED;
+ }
+diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
+index a5ac21a0ee33f..cb6b33a228ea2 100644
+--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
++++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
+@@ -1868,8 +1868,8 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
+ struct flow_cls_offload *f)
+ {
+ struct qede_arfs_fltr_node *n;
+- int min_hlen, rc = -EINVAL;
+ struct qede_arfs_tuple t;
++ int min_hlen, rc;
+
+ __qede_lock(edev);
+
+@@ -1879,7 +1879,8 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
+ }
+
+ /* parse flower attribute and prepare filter */
+- if (qede_parse_flow_attr(edev, proto, f->rule, &t))
++ rc = qede_parse_flow_attr(edev, proto, f->rule, &t);
++ if (rc)
+ goto unlock;
+
+ /* Validate profile mode and number of filters */
+@@ -1888,11 +1889,13 @@ int qede_add_tc_flower_fltr(struct qede_dev *edev, __be16 proto,
+ DP_NOTICE(edev,
+ "Filter configuration invalidated, filter mode=0x%x, configured mode=0x%x, filter count=0x%x\n",
+ t.mode, edev->arfs->mode, edev->arfs->filter_count);
++ rc = -EINVAL;
+ goto unlock;
+ }
+
+ /* parse tc actions and get the vf_id */
+- if (qede_parse_actions(edev, &f->rule->action, f->common.extack))
++ rc = qede_parse_actions(edev, &f->rule->action, f->common.extack);
++ if (rc)
+ goto unlock;
+
+ if (qede_flow_find_fltr(edev, &t)) {
+@@ -1998,10 +2001,9 @@ static int qede_flow_spec_to_rule(struct qede_dev *edev,
+ if (IS_ERR(flow))
+ return PTR_ERR(flow);
+
+- if (qede_parse_flow_attr(edev, proto, flow->rule, t)) {
+- err = -EINVAL;
++ err = qede_parse_flow_attr(edev, proto, flow->rule, t);
++ if (err)
+ goto err_out;
+- }
+
+ /* Make sure location is valid and filter isn't already set */
+ err = qede_flow_spec_validate(edev, &flow->rule->action, t,
+diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
+index a6fcbda64ecc6..2b6ec979a62f2 100644
+--- a/drivers/net/hyperv/netvsc.c
++++ b/drivers/net/hyperv/netvsc.c
+@@ -154,8 +154,11 @@ static void free_netvsc_device(struct rcu_head *head)
+ int i;
+
+ kfree(nvdev->extension);
+- vfree(nvdev->recv_buf);
+- vfree(nvdev->send_buf);
++
++ if (!nvdev->recv_buf_gpadl_handle.decrypted)
++ vfree(nvdev->recv_buf);
++ if (!nvdev->send_buf_gpadl_handle.decrypted)
++ vfree(nvdev->send_buf);
+ bitmap_free(nvdev->send_section_map);
+
+ for (i = 0; i < VRSS_CHANNEL_MAX; i++) {
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index e2e181378f412..edc34402e787f 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -1431,6 +1431,7 @@ static const struct usb_device_id products[] = {
+ {QMI_FIXED_INTF(0x2692, 0x9025, 4)}, /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */
+ {QMI_QUIRK_SET_DTR(0x1546, 0x1312, 4)}, /* u-blox LARA-R6 01B */
+ {QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */
++ {QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */
+
+ /* 4. Gobi 1000 devices */
+ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
+diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
+index 9ec46048d361d..0a0b4a9717cec 100644
+--- a/drivers/net/vxlan/vxlan_core.c
++++ b/drivers/net/vxlan/vxlan_core.c
+@@ -1674,6 +1674,7 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
+ bool raw_proto = false;
+ void *oiph;
+ __be32 vni = 0;
++ int nh;
+
+ /* Need UDP and VXLAN header to be present */
+ if (!pskb_may_pull(skb, VXLAN_HLEN))
+@@ -1762,12 +1763,28 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
+ skb->pkt_type = PACKET_HOST;
+ }
+
+- oiph = skb_network_header(skb);
++ /* Save offset of outer header relative to skb->head,
++ * because we are going to reset the network header to the inner header
++ * and might change skb->head.
++ */
++ nh = skb_network_header(skb) - skb->head;
++
+ skb_reset_network_header(skb);
+
++ if (!pskb_inet_may_pull(skb)) {
++ DEV_STATS_INC(vxlan->dev, rx_length_errors);
++ DEV_STATS_INC(vxlan->dev, rx_errors);
++ vxlan_vnifilter_count(vxlan, vni, vninode,
++ VXLAN_VNI_STATS_RX_ERRORS, 0);
++ goto drop;
++ }
++
++ /* Get the outer header. */
++ oiph = skb->head + nh;
++
+ if (!vxlan_ecn_decapsulate(vs, oiph, skb)) {
+- ++vxlan->dev->stats.rx_frame_errors;
+- ++vxlan->dev->stats.rx_errors;
++ DEV_STATS_INC(vxlan->dev, rx_frame_errors);
++ DEV_STATS_INC(vxlan->dev, rx_errors);
+ vxlan_vnifilter_count(vxlan, vni, vninode,
+ VXLAN_VNI_STATS_RX_ERRORS, 0);
+ goto drop;
+@@ -1837,7 +1854,9 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
+ goto out;
+
+ if (!pskb_may_pull(skb, arp_hdr_len(dev))) {
+- dev->stats.tx_dropped++;
++ dev_core_stats_tx_dropped_inc(dev);
++ vxlan_vnifilter_count(vxlan, vni, NULL,
++ VXLAN_VNI_STATS_TX_DROPS, 0);
+ goto out;
+ }
+ parp = arp_hdr(skb);
+@@ -1893,7 +1912,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
+ reply->pkt_type = PACKET_HOST;
+
+ if (netif_rx(reply) == NET_RX_DROP) {
+- dev->stats.rx_dropped++;
++ dev_core_stats_rx_dropped_inc(dev);
+ vxlan_vnifilter_count(vxlan, vni, NULL,
+ VXLAN_VNI_STATS_RX_DROPS, 0);
+ }
+@@ -2052,7 +2071,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
+ goto out;
+
+ if (netif_rx(reply) == NET_RX_DROP) {
+- dev->stats.rx_dropped++;
++ dev_core_stats_rx_dropped_inc(dev);
+ vxlan_vnifilter_count(vxlan, vni, NULL,
+ VXLAN_VNI_STATS_RX_DROPS, 0);
+ }
+@@ -2263,7 +2282,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
+ len);
+ } else {
+ drop:
+- dev->stats.rx_dropped++;
++ dev_core_stats_rx_dropped_inc(dev);
+ vxlan_vnifilter_count(dst_vxlan, vni, NULL,
+ VXLAN_VNI_STATS_RX_DROPS, 0);
+ }
+@@ -2295,7 +2314,7 @@ static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
+ addr_family, dst_port,
+ vxlan->cfg.flags);
+ if (!dst_vxlan) {
+- dev->stats.tx_errors++;
++ DEV_STATS_INC(dev, tx_errors);
+ vxlan_vnifilter_count(vxlan, vni, NULL,
+ VXLAN_VNI_STATS_TX_ERRORS, 0);
+ kfree_skb(skb);
+@@ -2559,7 +2578,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ return;
+
+ drop:
+- dev->stats.tx_dropped++;
++ dev_core_stats_tx_dropped_inc(dev);
+ vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_DROPS, 0);
+ dev_kfree_skb(skb);
+ return;
+@@ -2567,11 +2586,11 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ tx_error:
+ rcu_read_unlock();
+ if (err == -ELOOP)
+- dev->stats.collisions++;
++ DEV_STATS_INC(dev, collisions);
+ else if (err == -ENETUNREACH)
+- dev->stats.tx_carrier_errors++;
++ DEV_STATS_INC(dev, tx_carrier_errors);
+ dst_release(ndst);
+- dev->stats.tx_errors++;
++ DEV_STATS_INC(dev, tx_errors);
+ vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_ERRORS, 0);
+ kfree_skb(skb);
+ }
+@@ -2604,7 +2623,7 @@ static void vxlan_xmit_nh(struct sk_buff *skb, struct net_device *dev,
+ return;
+
+ drop:
+- dev->stats.tx_dropped++;
++ dev_core_stats_tx_dropped_inc(dev);
+ vxlan_vnifilter_count(netdev_priv(dev), vni, NULL,
+ VXLAN_VNI_STATS_TX_DROPS, 0);
+ dev_kfree_skb(skb);
+@@ -2642,7 +2661,7 @@ static netdev_tx_t vxlan_xmit_nhid(struct sk_buff *skb, struct net_device *dev,
+ return NETDEV_TX_OK;
+
+ drop:
+- dev->stats.tx_dropped++;
++ dev_core_stats_tx_dropped_inc(dev);
+ vxlan_vnifilter_count(netdev_priv(dev), vni, NULL,
+ VXLAN_VNI_STATS_TX_DROPS, 0);
+ dev_kfree_skb(skb);
+@@ -2739,7 +2758,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
+ !is_multicast_ether_addr(eth->h_dest))
+ vxlan_fdb_miss(vxlan, eth->h_dest);
+
+- dev->stats.tx_dropped++;
++ dev_core_stats_tx_dropped_inc(dev);
+ vxlan_vnifilter_count(vxlan, vni, NULL,
+ VXLAN_VNI_STATS_TX_DROPS, 0);
+ kfree_skb(skb);
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+index 1628bf55458fc..23e64a757cfe8 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+@@ -855,10 +855,15 @@ int iwl_mvm_mld_rm_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+
+ int iwl_mvm_mld_rm_sta_id(struct iwl_mvm *mvm, u8 sta_id)
+ {
+- int ret = iwl_mvm_mld_rm_sta_from_fw(mvm, sta_id);
++ int ret;
+
+ lockdep_assert_held(&mvm->mutex);
+
++ if (WARN_ON(sta_id == IWL_MVM_INVALID_STA))
++ return 0;
++
++ ret = iwl_mvm_mld_rm_sta_from_fw(mvm, sta_id);
++
+ RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id], NULL);
+ RCU_INIT_POINTER(mvm->fw_id_to_link_sta[sta_id], NULL);
+ return ret;
+diff --git a/drivers/net/wireless/intel/iwlwifi/queue/tx.c b/drivers/net/wireless/intel/iwlwifi/queue/tx.c
+index ca74b1b63cac1..0efa304904bd3 100644
+--- a/drivers/net/wireless/intel/iwlwifi/queue/tx.c
++++ b/drivers/net/wireless/intel/iwlwifi/queue/tx.c
+@@ -1588,9 +1588,9 @@ void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
+ return;
+
+ tfd_num = iwl_txq_get_cmd_index(txq, ssn);
+- read_ptr = iwl_txq_get_cmd_index(txq, txq->read_ptr);
+
+ spin_lock_bh(&txq->lock);
++ read_ptr = iwl_txq_get_cmd_index(txq, txq->read_ptr);
+
+ if (!test_bit(txq_id, trans->txqs.queue_used)) {
+ IWL_DEBUG_TX_QUEUES(trans, "Q %d inactive - ignoring idx %d\n",
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index fe3627c5bdc99..26153cb7647d7 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -3630,7 +3630,7 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
+ "Found shared namespace %d, but multipathing not supported.\n",
+ info->nsid);
+ dev_warn_once(ctrl->device,
+- "Support for shared namespaces without CONFIG_NVME_MULTIPATH is deprecated and will be removed in Linux 6.0\n.");
++ "Support for shared namespaces without CONFIG_NVME_MULTIPATH is deprecated and will be removed in Linux 6.0.\n");
+ }
+ }
+
+diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
+index 7b87763e2f8a6..738719085e054 100644
+--- a/drivers/nvme/host/nvme.h
++++ b/drivers/nvme/host/nvme.h
+@@ -162,6 +162,11 @@ enum nvme_quirks {
+ * Disables simple suspend/resume path.
+ */
+ NVME_QUIRK_FORCE_NO_SIMPLE_SUSPEND = (1 << 20),
++
++ /*
++ * MSI (but not MSI-X) interrupts are broken and never fire.
++ */
++ NVME_QUIRK_BROKEN_MSI = (1 << 21),
+ };
+
+ /*
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index 8e0bb9692685d..02565dc99ad85 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -2218,6 +2218,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
+ .priv = dev,
+ };
+ unsigned int irq_queues, poll_queues;
++ unsigned int flags = PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY;
+
+ /*
+ * Poll queues don't need interrupts, but we need at least one I/O queue
+@@ -2241,8 +2242,10 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
+ irq_queues = 1;
+ if (!(dev->ctrl.quirks & NVME_QUIRK_SINGLE_VECTOR))
+ irq_queues += (nr_io_queues - poll_queues);
+- return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues,
+- PCI_IRQ_ALL_TYPES | PCI_IRQ_AFFINITY, &affd);
++ if (dev->ctrl.quirks & NVME_QUIRK_BROKEN_MSI)
++ flags &= ~PCI_IRQ_MSI;
++ return pci_alloc_irq_vectors_affinity(pdev, 1, irq_queues, flags,
++ &affd);
+ }
+
+ static unsigned int nvme_max_io_queues(struct nvme_dev *dev)
+@@ -2471,6 +2474,7 @@ static int nvme_pci_enable(struct nvme_dev *dev)
+ {
+ int result = -ENOMEM;
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
++ unsigned int flags = PCI_IRQ_ALL_TYPES;
+
+ if (pci_enable_device_mem(pdev))
+ return result;
+@@ -2487,7 +2491,9 @@ static int nvme_pci_enable(struct nvme_dev *dev)
+ * interrupts. Pre-enable a single MSIX or MSI vec for setup. We'll
+ * adjust this later.
+ */
+- result = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
++ if (dev->ctrl.quirks & NVME_QUIRK_BROKEN_MSI)
++ flags &= ~PCI_IRQ_MSI;
++ result = pci_alloc_irq_vectors(pdev, 1, 1, flags);
+ if (result < 0)
+ goto disable;
+
+@@ -3384,6 +3390,8 @@ static const struct pci_device_id nvme_id_table[] = {
+ .driver_data = NVME_QUIRK_DELAY_BEFORE_CHK_RDY |
+ NVME_QUIRK_DISABLE_WRITE_ZEROES|
+ NVME_QUIRK_IGNORE_DEV_SUBNQN, },
++ { PCI_DEVICE(0x15b7, 0x5008), /* Sandisk SN530 */
++ .driver_data = NVME_QUIRK_BROKEN_MSI },
+ { PCI_DEVICE(0x1987, 0x5012), /* Phison E12 */
+ .driver_data = NVME_QUIRK_BOGUS_NID, },
+ { PCI_DEVICE(0x1987, 0x5016), /* Phison E16 */
+diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+index d376fa7114d1a..029efe16f8cc2 100644
+--- a/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
++++ b/drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
+@@ -43,7 +43,7 @@
+ #define SCU614 0x614 /* Disable GPIO Internal Pull-Down #1 */
+ #define SCU618 0x618 /* Disable GPIO Internal Pull-Down #2 */
+ #define SCU61C 0x61c /* Disable GPIO Internal Pull-Down #3 */
+-#define SCU620 0x620 /* Disable GPIO Internal Pull-Down #4 */
++#define SCU630 0x630 /* Disable GPIO Internal Pull-Down #4 */
+ #define SCU634 0x634 /* Disable GPIO Internal Pull-Down #5 */
+ #define SCU638 0x638 /* Disable GPIO Internal Pull-Down #6 */
+ #define SCU690 0x690 /* Multi-function Pin Control #24 */
+@@ -2495,38 +2495,38 @@ static struct aspeed_pin_config aspeed_g6_configs[] = {
+ ASPEED_PULL_DOWN_PINCONF(D14, SCU61C, 0),
+
+ /* GPIOS7 */
+- ASPEED_PULL_DOWN_PINCONF(T24, SCU620, 23),
++ ASPEED_PULL_DOWN_PINCONF(T24, SCU630, 23),
+ /* GPIOS6 */
+- ASPEED_PULL_DOWN_PINCONF(P23, SCU620, 22),
++ ASPEED_PULL_DOWN_PINCONF(P23, SCU630, 22),
+ /* GPIOS5 */
+- ASPEED_PULL_DOWN_PINCONF(P24, SCU620, 21),
++ ASPEED_PULL_DOWN_PINCONF(P24, SCU630, 21),
+ /* GPIOS4 */
+- ASPEED_PULL_DOWN_PINCONF(R26, SCU620, 20),
++ ASPEED_PULL_DOWN_PINCONF(R26, SCU630, 20),
+ /* GPIOS3*/
+- ASPEED_PULL_DOWN_PINCONF(R24, SCU620, 19),
++ ASPEED_PULL_DOWN_PINCONF(R24, SCU630, 19),
+ /* GPIOS2 */
+- ASPEED_PULL_DOWN_PINCONF(T26, SCU620, 18),
++ ASPEED_PULL_DOWN_PINCONF(T26, SCU630, 18),
+ /* GPIOS1 */
+- ASPEED_PULL_DOWN_PINCONF(T25, SCU620, 17),
++ ASPEED_PULL_DOWN_PINCONF(T25, SCU630, 17),
+ /* GPIOS0 */
+- ASPEED_PULL_DOWN_PINCONF(R23, SCU620, 16),
++ ASPEED_PULL_DOWN_PINCONF(R23, SCU630, 16),
+
+ /* GPIOR7 */
+- ASPEED_PULL_DOWN_PINCONF(U26, SCU620, 15),
++ ASPEED_PULL_DOWN_PINCONF(U26, SCU630, 15),
+ /* GPIOR6 */
+- ASPEED_PULL_DOWN_PINCONF(W26, SCU620, 14),
++ ASPEED_PULL_DOWN_PINCONF(W26, SCU630, 14),
+ /* GPIOR5 */
+- ASPEED_PULL_DOWN_PINCONF(T23, SCU620, 13),
++ ASPEED_PULL_DOWN_PINCONF(T23, SCU630, 13),
+ /* GPIOR4 */
+- ASPEED_PULL_DOWN_PINCONF(U25, SCU620, 12),
++ ASPEED_PULL_DOWN_PINCONF(U25, SCU630, 12),
+ /* GPIOR3*/
+- ASPEED_PULL_DOWN_PINCONF(V26, SCU620, 11),
++ ASPEED_PULL_DOWN_PINCONF(V26, SCU630, 11),
+ /* GPIOR2 */
+- ASPEED_PULL_DOWN_PINCONF(V24, SCU620, 10),
++ ASPEED_PULL_DOWN_PINCONF(V24, SCU630, 10),
+ /* GPIOR1 */
+- ASPEED_PULL_DOWN_PINCONF(U24, SCU620, 9),
++ ASPEED_PULL_DOWN_PINCONF(U24, SCU630, 9),
+ /* GPIOR0 */
+- ASPEED_PULL_DOWN_PINCONF(V25, SCU620, 8),
++ ASPEED_PULL_DOWN_PINCONF(V25, SCU630, 8),
+
+ /* GPIOX7 */
+ ASPEED_PULL_DOWN_PINCONF(AB10, SCU634, 31),
+diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
+index bbcdece83bf42..ae975e1365dfd 100644
+--- a/drivers/pinctrl/core.c
++++ b/drivers/pinctrl/core.c
+@@ -2120,13 +2120,7 @@ int pinctrl_enable(struct pinctrl_dev *pctldev)
+
+ error = pinctrl_claim_hogs(pctldev);
+ if (error) {
+- dev_err(pctldev->dev, "could not claim hogs: %i\n",
+- error);
+- pinctrl_free_pindescs(pctldev, pctldev->desc->pins,
+- pctldev->desc->npins);
+- mutex_destroy(&pctldev->mutex);
+- kfree(pctldev);
+-
++ dev_err(pctldev->dev, "could not claim hogs: %i\n", error);
+ return error;
+ }
+
+diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
+index df1efc2e52025..6a94ecd6a8dea 100644
+--- a/drivers/pinctrl/devicetree.c
++++ b/drivers/pinctrl/devicetree.c
+@@ -220,14 +220,16 @@ int pinctrl_dt_to_map(struct pinctrl *p, struct pinctrl_dev *pctldev)
+ for (state = 0; ; state++) {
+ /* Retrieve the pinctrl-* property */
+ propname = kasprintf(GFP_KERNEL, "pinctrl-%d", state);
+- if (!propname)
+- return -ENOMEM;
++ if (!propname) {
++ ret = -ENOMEM;
++ goto err;
++ }
+ prop = of_find_property(np, propname, &size);
+ kfree(propname);
+ if (!prop) {
+ if (state == 0) {
+- of_node_put(np);
+- return -ENODEV;
++ ret = -ENODEV;
++ goto err;
+ }
+ break;
+ }
+diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
+index ac97724c59bae..1edb6041fb424 100644
+--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
+@@ -278,33 +278,33 @@ static const unsigned int byt_score_plt_clk5_pins[] = { 101 };
+ static const unsigned int byt_score_smbus_pins[] = { 51, 52, 53 };
+
+ static const struct intel_pingroup byt_score_groups[] = {
+- PIN_GROUP("uart1_grp", byt_score_uart1_pins, 1),
+- PIN_GROUP("uart2_grp", byt_score_uart2_pins, 1),
+- PIN_GROUP("pwm0_grp", byt_score_pwm0_pins, 1),
+- PIN_GROUP("pwm1_grp", byt_score_pwm1_pins, 1),
+- PIN_GROUP("ssp2_grp", byt_score_ssp2_pins, 1),
+- PIN_GROUP("sio_spi_grp", byt_score_sio_spi_pins, 1),
+- PIN_GROUP("i2c5_grp", byt_score_i2c5_pins, 1),
+- PIN_GROUP("i2c6_grp", byt_score_i2c6_pins, 1),
+- PIN_GROUP("i2c4_grp", byt_score_i2c4_pins, 1),
+- PIN_GROUP("i2c3_grp", byt_score_i2c3_pins, 1),
+- PIN_GROUP("i2c2_grp", byt_score_i2c2_pins, 1),
+- PIN_GROUP("i2c1_grp", byt_score_i2c1_pins, 1),
+- PIN_GROUP("i2c0_grp", byt_score_i2c0_pins, 1),
+- PIN_GROUP("ssp0_grp", byt_score_ssp0_pins, 1),
+- PIN_GROUP("ssp1_grp", byt_score_ssp1_pins, 1),
+- PIN_GROUP("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values),
+- PIN_GROUP("sdio_grp", byt_score_sdio_pins, 1),
+- PIN_GROUP("emmc_grp", byt_score_emmc_pins, 1),
+- PIN_GROUP("lpc_grp", byt_score_ilb_lpc_pins, 1),
+- PIN_GROUP("sata_grp", byt_score_sata_pins, 1),
+- PIN_GROUP("plt_clk0_grp", byt_score_plt_clk0_pins, 1),
+- PIN_GROUP("plt_clk1_grp", byt_score_plt_clk1_pins, 1),
+- PIN_GROUP("plt_clk2_grp", byt_score_plt_clk2_pins, 1),
+- PIN_GROUP("plt_clk3_grp", byt_score_plt_clk3_pins, 1),
+- PIN_GROUP("plt_clk4_grp", byt_score_plt_clk4_pins, 1),
+- PIN_GROUP("plt_clk5_grp", byt_score_plt_clk5_pins, 1),
+- PIN_GROUP("smbus_grp", byt_score_smbus_pins, 1),
++ PIN_GROUP_GPIO("uart1_grp", byt_score_uart1_pins, 1),
++ PIN_GROUP_GPIO("uart2_grp", byt_score_uart2_pins, 1),
++ PIN_GROUP_GPIO("pwm0_grp", byt_score_pwm0_pins, 1),
++ PIN_GROUP_GPIO("pwm1_grp", byt_score_pwm1_pins, 1),
++ PIN_GROUP_GPIO("ssp2_grp", byt_score_ssp2_pins, 1),
++ PIN_GROUP_GPIO("sio_spi_grp", byt_score_sio_spi_pins, 1),
++ PIN_GROUP_GPIO("i2c5_grp", byt_score_i2c5_pins, 1),
++ PIN_GROUP_GPIO("i2c6_grp", byt_score_i2c6_pins, 1),
++ PIN_GROUP_GPIO("i2c4_grp", byt_score_i2c4_pins, 1),
++ PIN_GROUP_GPIO("i2c3_grp", byt_score_i2c3_pins, 1),
++ PIN_GROUP_GPIO("i2c2_grp", byt_score_i2c2_pins, 1),
++ PIN_GROUP_GPIO("i2c1_grp", byt_score_i2c1_pins, 1),
++ PIN_GROUP_GPIO("i2c0_grp", byt_score_i2c0_pins, 1),
++ PIN_GROUP_GPIO("ssp0_grp", byt_score_ssp0_pins, 1),
++ PIN_GROUP_GPIO("ssp1_grp", byt_score_ssp1_pins, 1),
++ PIN_GROUP_GPIO("sdcard_grp", byt_score_sdcard_pins, byt_score_sdcard_mux_values),
++ PIN_GROUP_GPIO("sdio_grp", byt_score_sdio_pins, 1),
++ PIN_GROUP_GPIO("emmc_grp", byt_score_emmc_pins, 1),
++ PIN_GROUP_GPIO("lpc_grp", byt_score_ilb_lpc_pins, 1),
++ PIN_GROUP_GPIO("sata_grp", byt_score_sata_pins, 1),
++ PIN_GROUP_GPIO("plt_clk0_grp", byt_score_plt_clk0_pins, 1),
++ PIN_GROUP_GPIO("plt_clk1_grp", byt_score_plt_clk1_pins, 1),
++ PIN_GROUP_GPIO("plt_clk2_grp", byt_score_plt_clk2_pins, 1),
++ PIN_GROUP_GPIO("plt_clk3_grp", byt_score_plt_clk3_pins, 1),
++ PIN_GROUP_GPIO("plt_clk4_grp", byt_score_plt_clk4_pins, 1),
++ PIN_GROUP_GPIO("plt_clk5_grp", byt_score_plt_clk5_pins, 1),
++ PIN_GROUP_GPIO("smbus_grp", byt_score_smbus_pins, 1),
+ };
+
+ static const char * const byt_score_uart_groups[] = {
+@@ -332,12 +332,14 @@ static const char * const byt_score_plt_clk_groups[] = {
+ };
+ static const char * const byt_score_smbus_groups[] = { "smbus_grp" };
+ static const char * const byt_score_gpio_groups[] = {
+- "uart1_grp", "uart2_grp", "pwm0_grp", "pwm1_grp", "ssp0_grp",
+- "ssp1_grp", "ssp2_grp", "sio_spi_grp", "i2c0_grp", "i2c1_grp",
+- "i2c2_grp", "i2c3_grp", "i2c4_grp", "i2c5_grp", "i2c6_grp",
+- "sdcard_grp", "sdio_grp", "emmc_grp", "lpc_grp", "sata_grp",
+- "plt_clk0_grp", "plt_clk1_grp", "plt_clk2_grp", "plt_clk3_grp",
+- "plt_clk4_grp", "plt_clk5_grp", "smbus_grp",
++ "uart1_grp_gpio", "uart2_grp_gpio", "pwm0_grp_gpio",
++ "pwm1_grp_gpio", "ssp0_grp_gpio", "ssp1_grp_gpio", "ssp2_grp_gpio",
++ "sio_spi_grp_gpio", "i2c0_grp_gpio", "i2c1_grp_gpio", "i2c2_grp_gpio",
++ "i2c3_grp_gpio", "i2c4_grp_gpio", "i2c5_grp_gpio", "i2c6_grp_gpio",
++ "sdcard_grp_gpio", "sdio_grp_gpio", "emmc_grp_gpio", "lpc_grp_gpio",
++ "sata_grp_gpio", "plt_clk0_grp_gpio", "plt_clk1_grp_gpio",
++ "plt_clk2_grp_gpio", "plt_clk3_grp_gpio", "plt_clk4_grp_gpio",
++ "plt_clk5_grp_gpio", "smbus_grp_gpio",
+ };
+
+ static const struct intel_function byt_score_functions[] = {
+@@ -456,8 +458,8 @@ static const struct intel_pingroup byt_sus_groups[] = {
+ PIN_GROUP("usb_oc_grp_gpio", byt_sus_usb_over_current_pins, byt_sus_usb_over_current_gpio_mode_values),
+ PIN_GROUP("usb_ulpi_grp_gpio", byt_sus_usb_ulpi_pins, byt_sus_usb_ulpi_gpio_mode_values),
+ PIN_GROUP("pcu_spi_grp_gpio", byt_sus_pcu_spi_pins, byt_sus_pcu_spi_gpio_mode_values),
+- PIN_GROUP("pmu_clk1_grp", byt_sus_pmu_clk1_pins, 1),
+- PIN_GROUP("pmu_clk2_grp", byt_sus_pmu_clk2_pins, 1),
++ PIN_GROUP_GPIO("pmu_clk1_grp", byt_sus_pmu_clk1_pins, 1),
++ PIN_GROUP_GPIO("pmu_clk2_grp", byt_sus_pmu_clk2_pins, 1),
+ };
+
+ static const char * const byt_sus_usb_groups[] = {
+@@ -469,7 +471,7 @@ static const char * const byt_sus_pmu_clk_groups[] = {
+ };
+ static const char * const byt_sus_gpio_groups[] = {
+ "usb_oc_grp_gpio", "usb_ulpi_grp_gpio", "pcu_spi_grp_gpio",
+- "pmu_clk1_grp", "pmu_clk2_grp",
++ "pmu_clk1_grp_gpio", "pmu_clk2_grp_gpio",
+ };
+
+ static const struct intel_function byt_sus_functions[] = {
+diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h
+index fde65e18cd145..6981e2fab93f3 100644
+--- a/drivers/pinctrl/intel/pinctrl-intel.h
++++ b/drivers/pinctrl/intel/pinctrl-intel.h
+@@ -179,6 +179,10 @@ struct intel_community {
+ .modes = __builtin_choose_expr(__builtin_constant_p((m)), NULL, (m)), \
+ }
+
++#define PIN_GROUP_GPIO(n, p, m) \
++ PIN_GROUP(n, p, m), \
++ PIN_GROUP(n "_gpio", p, 0)
++
+ #define FUNCTION(n, g) \
+ { \
+ .func = PINCTRL_PINFUNCTION((n), (g), ARRAY_SIZE(g)), \
+diff --git a/drivers/pinctrl/mediatek/pinctrl-paris.c b/drivers/pinctrl/mediatek/pinctrl-paris.c
+index b6bc31abd2b06..b19bc391705ee 100644
+--- a/drivers/pinctrl/mediatek/pinctrl-paris.c
++++ b/drivers/pinctrl/mediatek/pinctrl-paris.c
+@@ -165,20 +165,21 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SR, &ret);
+ break;
+ case PIN_CONFIG_INPUT_ENABLE:
+- case PIN_CONFIG_OUTPUT_ENABLE:
++ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_IES, &ret);
++ if (!ret)
++ err = -EINVAL;
++ break;
++ case PIN_CONFIG_OUTPUT:
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
+ if (err)
+ break;
+- /* CONFIG Current direction return value
+- * ------------- ----------------- ----------------------
+- * OUTPUT_ENABLE output 1 (= HW value)
+- * input 0 (= HW value)
+- * INPUT_ENABLE output 0 (= reverse HW value)
+- * input 1 (= reverse HW value)
+- */
+- if (param == PIN_CONFIG_INPUT_ENABLE)
+- ret = !ret;
+
++ if (!ret) {
++ err = -EINVAL;
++ break;
++ }
++
++ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DO, &ret);
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_DIR, &ret);
+@@ -193,6 +194,8 @@ static int mtk_pinconf_get(struct pinctrl_dev *pctldev,
+ }
+
+ err = mtk_hw_get_value(hw, desc, PINCTRL_PIN_REG_SMT, &ret);
++ if (!ret)
++ err = -EINVAL;
+ break;
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ if (!hw->soc->drive_get)
+@@ -281,26 +284,9 @@ static int mtk_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+ break;
+ err = hw->soc->bias_set_combo(hw, desc, 0, arg);
+ break;
+- case PIN_CONFIG_OUTPUT_ENABLE:
+- err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_SMT,
+- MTK_DISABLE);
+- /* Keep set direction to consider the case that a GPIO pin
+- * does not have SMT control
+- */
+- if (err != -ENOTSUPP)
+- break;
+-
+- err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
+- MTK_OUTPUT);
+- break;
+ case PIN_CONFIG_INPUT_ENABLE:
+ /* regard all non-zero value as enable */
+ err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_IES, !!arg);
+- if (err)
+- break;
+-
+- err = mtk_hw_set_value(hw, desc, PINCTRL_PIN_REG_DIR,
+- MTK_INPUT);
+ break;
+ case PIN_CONFIG_SLEW_RATE:
+ /* regard all non-zero value as enable */
+diff --git a/drivers/pinctrl/meson/pinctrl-meson-a1.c b/drivers/pinctrl/meson/pinctrl-meson-a1.c
+index 79f5d753d7e1a..50a87d9618a8e 100644
+--- a/drivers/pinctrl/meson/pinctrl-meson-a1.c
++++ b/drivers/pinctrl/meson/pinctrl-meson-a1.c
+@@ -250,7 +250,7 @@ static const unsigned int pdm_dclk_x_pins[] = { GPIOX_10 };
+ static const unsigned int pdm_din2_a_pins[] = { GPIOA_6 };
+ static const unsigned int pdm_din1_a_pins[] = { GPIOA_7 };
+ static const unsigned int pdm_din0_a_pins[] = { GPIOA_8 };
+-static const unsigned int pdm_dclk_pins[] = { GPIOA_9 };
++static const unsigned int pdm_dclk_a_pins[] = { GPIOA_9 };
+
+ /* gen_clk */
+ static const unsigned int gen_clk_x_pins[] = { GPIOX_7 };
+@@ -591,7 +591,7 @@ static struct meson_pmx_group meson_a1_periphs_groups[] = {
+ GROUP(pdm_din2_a, 3),
+ GROUP(pdm_din1_a, 3),
+ GROUP(pdm_din0_a, 3),
+- GROUP(pdm_dclk, 3),
++ GROUP(pdm_dclk_a, 3),
+ GROUP(pwm_c_a, 3),
+ GROUP(pwm_b_a, 3),
+
+@@ -755,7 +755,7 @@ static const char * const spi_a_groups[] = {
+
+ static const char * const pdm_groups[] = {
+ "pdm_din0_x", "pdm_din1_x", "pdm_din2_x", "pdm_dclk_x", "pdm_din2_a",
+- "pdm_din1_a", "pdm_din0_a", "pdm_dclk",
++ "pdm_din1_a", "pdm_din0_a", "pdm_dclk_a",
+ };
+
+ static const char * const gen_clk_groups[] = {
+diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
+index ee2e164f86b9c..38c932df6446a 100644
+--- a/drivers/platform/x86/acer-wmi.c
++++ b/drivers/platform/x86/acer-wmi.c
+@@ -597,6 +597,15 @@ static const struct dmi_system_id acer_quirks[] __initconst = {
+ },
+ .driver_data = &quirk_acer_predator_v4,
+ },
++ {
++ .callback = dmi_matched,
++ .ident = "Acer Predator PH18-71",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH18-71"),
++ },
++ .driver_data = &quirk_acer_predator_v4,
++ },
+ {
+ .callback = set_force_caps,
+ .ident = "Acer Aspire Switch 10E SW3-016",
+diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c
+index f2eb07ef855af..1c0d2bbc1f974 100644
+--- a/drivers/platform/x86/amd/pmf/acpi.c
++++ b/drivers/platform/x86/amd/pmf/acpi.c
+@@ -309,7 +309,7 @@ int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev)
+
+ status = acpi_walk_resources(ahandle, METHOD_NAME__CRS, apmf_walk_resources, pmf_dev);
+ if (ACPI_FAILURE(status)) {
+- dev_err(pmf_dev->dev, "acpi_walk_resources failed :%d\n", status);
++ dev_dbg(pmf_dev->dev, "acpi_walk_resources failed :%d\n", status);
+ return -EINVAL;
+ }
+
+diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
+index 08df9494603c5..30951f7131cd9 100644
+--- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
++++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
+@@ -719,6 +719,7 @@ static struct miscdevice isst_if_char_driver = {
+ };
+
+ static const struct x86_cpu_id hpm_cpu_ids[] = {
++ X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_D, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_X, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(ATOM_CRESTMONT_X, NULL),
+ {}
+diff --git a/drivers/power/supply/mt6360_charger.c b/drivers/power/supply/mt6360_charger.c
+index 1305cba61edd4..aca123783efcc 100644
+--- a/drivers/power/supply/mt6360_charger.c
++++ b/drivers/power/supply/mt6360_charger.c
+@@ -588,7 +588,7 @@ static const struct regulator_ops mt6360_chg_otg_ops = {
+ };
+
+ static const struct regulator_desc mt6360_otg_rdesc = {
+- .of_match = "usb-otg-vbus",
++ .of_match = "usb-otg-vbus-regulator",
+ .name = "usb-otg-vbus",
+ .ops = &mt6360_chg_otg_ops,
+ .owner = THIS_MODULE,
+diff --git a/drivers/power/supply/rt9455_charger.c b/drivers/power/supply/rt9455_charger.c
+index c345a77f9f78c..e4dbacd50a437 100644
+--- a/drivers/power/supply/rt9455_charger.c
++++ b/drivers/power/supply/rt9455_charger.c
+@@ -192,6 +192,7 @@ static const int rt9455_voreg_values[] = {
+ 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000, 4450000
+ };
+
++#if IS_ENABLED(CONFIG_USB_PHY)
+ /*
+ * When the charger is in boost mode, REG02[7:2] represent boost output
+ * voltage.
+@@ -207,6 +208,7 @@ static const int rt9455_boost_voltage_values[] = {
+ 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000,
+ 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000, 5600000,
+ };
++#endif
+
+ /* REG07[3:0] (VMREG) in uV */
+ static const int rt9455_vmreg_values[] = {
+diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
+index a968dabb48f55..1b897d0009c5b 100644
+--- a/drivers/regulator/core.c
++++ b/drivers/regulator/core.c
+@@ -1911,19 +1911,24 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
+ }
+ }
+
+- if (err != -EEXIST)
++ if (err != -EEXIST) {
+ regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs);
+- if (IS_ERR(regulator->debugfs))
+- rdev_dbg(rdev, "Failed to create debugfs directory\n");
++ if (IS_ERR(regulator->debugfs)) {
++ rdev_dbg(rdev, "Failed to create debugfs directory\n");
++ regulator->debugfs = NULL;
++ }
++ }
+
+- debugfs_create_u32("uA_load", 0444, regulator->debugfs,
+- ®ulator->uA_load);
+- debugfs_create_u32("min_uV", 0444, regulator->debugfs,
+- ®ulator->voltage[PM_SUSPEND_ON].min_uV);
+- debugfs_create_u32("max_uV", 0444, regulator->debugfs,
+- ®ulator->voltage[PM_SUSPEND_ON].max_uV);
+- debugfs_create_file("constraint_flags", 0444, regulator->debugfs,
+- regulator, &constraint_flags_fops);
++ if (regulator->debugfs) {
++ debugfs_create_u32("uA_load", 0444, regulator->debugfs,
++ ®ulator->uA_load);
++ debugfs_create_u32("min_uV", 0444, regulator->debugfs,
++ ®ulator->voltage[PM_SUSPEND_ON].min_uV);
++ debugfs_create_u32("max_uV", 0444, regulator->debugfs,
++ ®ulator->voltage[PM_SUSPEND_ON].max_uV);
++ debugfs_create_file("constraint_flags", 0444, regulator->debugfs,
++ regulator, &constraint_flags_fops);
++ }
+
+ /*
+ * Check now if the regulator is an always on regulator - if
+diff --git a/drivers/regulator/mt6360-regulator.c b/drivers/regulator/mt6360-regulator.c
+index ad6587a378d09..24cc9fc94e900 100644
+--- a/drivers/regulator/mt6360-regulator.c
++++ b/drivers/regulator/mt6360-regulator.c
+@@ -319,15 +319,15 @@ static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode)
+ }
+ }
+
+-#define MT6360_REGULATOR_DESC(_name, _sname, ereg, emask, vreg, vmask, \
+- mreg, mmask, streg, stmask, vranges, \
+- vcnts, offon_delay, irq_tbls) \
++#define MT6360_REGULATOR_DESC(match, _name, _sname, ereg, emask, vreg, \
++ vmask, mreg, mmask, streg, stmask, \
++ vranges, vcnts, offon_delay, irq_tbls) \
+ { \
+ .desc = { \
+ .name = #_name, \
+ .supply_name = #_sname, \
+ .id = MT6360_REGULATOR_##_name, \
+- .of_match = of_match_ptr(#_name), \
++ .of_match = of_match_ptr(match), \
+ .regulators_node = of_match_ptr("regulator"), \
+ .of_map_mode = mt6360_regulator_of_map_mode, \
+ .owner = THIS_MODULE, \
+@@ -351,21 +351,29 @@ static unsigned int mt6360_regulator_of_map_mode(unsigned int hw_mode)
+ }
+
+ static const struct mt6360_regulator_desc mt6360_regulator_descs[] = {
+- MT6360_REGULATOR_DESC(BUCK1, BUCK1_VIN, 0x117, 0x40, 0x110, 0xff, 0x117, 0x30, 0x117, 0x04,
++ MT6360_REGULATOR_DESC("buck1", BUCK1, BUCK1_VIN,
++ 0x117, 0x40, 0x110, 0xff, 0x117, 0x30, 0x117, 0x04,
+ buck_vout_ranges, 256, 0, buck1_irq_tbls),
+- MT6360_REGULATOR_DESC(BUCK2, BUCK2_VIN, 0x127, 0x40, 0x120, 0xff, 0x127, 0x30, 0x127, 0x04,
++ MT6360_REGULATOR_DESC("buck2", BUCK2, BUCK2_VIN,
++ 0x127, 0x40, 0x120, 0xff, 0x127, 0x30, 0x127, 0x04,
+ buck_vout_ranges, 256, 0, buck2_irq_tbls),
+- MT6360_REGULATOR_DESC(LDO6, LDO_VIN3, 0x137, 0x40, 0x13B, 0xff, 0x137, 0x30, 0x137, 0x04,
++ MT6360_REGULATOR_DESC("ldo6", LDO6, LDO_VIN3,
++ 0x137, 0x40, 0x13B, 0xff, 0x137, 0x30, 0x137, 0x04,
+ ldo_vout_ranges1, 256, 0, ldo6_irq_tbls),
+- MT6360_REGULATOR_DESC(LDO7, LDO_VIN3, 0x131, 0x40, 0x135, 0xff, 0x131, 0x30, 0x131, 0x04,
++ MT6360_REGULATOR_DESC("ldo7", LDO7, LDO_VIN3,
++ 0x131, 0x40, 0x135, 0xff, 0x131, 0x30, 0x131, 0x04,
+ ldo_vout_ranges1, 256, 0, ldo7_irq_tbls),
+- MT6360_REGULATOR_DESC(LDO1, LDO_VIN1, 0x217, 0x40, 0x21B, 0xff, 0x217, 0x30, 0x217, 0x04,
++ MT6360_REGULATOR_DESC("ldo1", LDO1, LDO_VIN1,
++ 0x217, 0x40, 0x21B, 0xff, 0x217, 0x30, 0x217, 0x04,
+ ldo_vout_ranges2, 256, 0, ldo1_irq_tbls),
+- MT6360_REGULATOR_DESC(LDO2, LDO_VIN1, 0x211, 0x40, 0x215, 0xff, 0x211, 0x30, 0x211, 0x04,
++ MT6360_REGULATOR_DESC("ldo2", LDO2, LDO_VIN1,
++ 0x211, 0x40, 0x215, 0xff, 0x211, 0x30, 0x211, 0x04,
+ ldo_vout_ranges2, 256, 0, ldo2_irq_tbls),
+- MT6360_REGULATOR_DESC(LDO3, LDO_VIN1, 0x205, 0x40, 0x209, 0xff, 0x205, 0x30, 0x205, 0x04,
++ MT6360_REGULATOR_DESC("ldo3", LDO3, LDO_VIN1,
++ 0x205, 0x40, 0x209, 0xff, 0x205, 0x30, 0x205, 0x04,
+ ldo_vout_ranges2, 256, 100, ldo3_irq_tbls),
+- MT6360_REGULATOR_DESC(LDO5, LDO_VIN2, 0x20B, 0x40, 0x20F, 0x7f, 0x20B, 0x30, 0x20B, 0x04,
++ MT6360_REGULATOR_DESC("ldo5", LDO5, LDO_VIN2,
++ 0x20B, 0x40, 0x20F, 0x7f, 0x20B, 0x30, 0x20B, 0x04,
+ ldo_vout_ranges3, 128, 100, ldo5_irq_tbls),
+ };
+
+diff --git a/drivers/regulator/tps65132-regulator.c b/drivers/regulator/tps65132-regulator.c
+index a06f5f2d79329..9c2f0dd42613d 100644
+--- a/drivers/regulator/tps65132-regulator.c
++++ b/drivers/regulator/tps65132-regulator.c
+@@ -267,10 +267,17 @@ static const struct i2c_device_id tps65132_id[] = {
+ };
+ MODULE_DEVICE_TABLE(i2c, tps65132_id);
+
++static const struct of_device_id __maybe_unused tps65132_of_match[] = {
++ { .compatible = "ti,tps65132" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, tps65132_of_match);
++
+ static struct i2c_driver tps65132_i2c_driver = {
+ .driver = {
+ .name = "tps65132",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
++ .of_match_table = of_match_ptr(tps65132_of_match),
+ },
+ .probe = tps65132_probe,
+ .id_table = tps65132_id,
+diff --git a/drivers/s390/cio/cio_inject.c b/drivers/s390/cio/cio_inject.c
+index 8613fa937237b..a2e771ebae8eb 100644
+--- a/drivers/s390/cio/cio_inject.c
++++ b/drivers/s390/cio/cio_inject.c
+@@ -95,7 +95,7 @@ static ssize_t crw_inject_write(struct file *file, const char __user *buf,
+ return -EINVAL;
+ }
+
+- buffer = vmemdup_user(buf, lbuf);
++ buffer = memdup_user_nul(buf, lbuf);
+ if (IS_ERR(buffer))
+ return -ENOMEM;
+
+diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
+index 601d00e09de4a..dc5ae75d462b9 100644
+--- a/drivers/s390/net/qeth_core_main.c
++++ b/drivers/s390/net/qeth_core_main.c
+@@ -364,30 +364,33 @@ static int qeth_cq_init(struct qeth_card *card)
+ return rc;
+ }
+
++static void qeth_free_cq(struct qeth_card *card)
++{
++ if (card->qdio.c_q) {
++ qeth_free_qdio_queue(card->qdio.c_q);
++ card->qdio.c_q = NULL;
++ }
++}
++
+ static int qeth_alloc_cq(struct qeth_card *card)
+ {
+ if (card->options.cq == QETH_CQ_ENABLED) {
+ QETH_CARD_TEXT(card, 2, "cqon");
+- card->qdio.c_q = qeth_alloc_qdio_queue();
+ if (!card->qdio.c_q) {
+- dev_err(&card->gdev->dev, "Failed to create completion queue\n");
+- return -ENOMEM;
++ card->qdio.c_q = qeth_alloc_qdio_queue();
++ if (!card->qdio.c_q) {
++ dev_err(&card->gdev->dev,
++ "Failed to create completion queue\n");
++ return -ENOMEM;
++ }
+ }
+ } else {
+ QETH_CARD_TEXT(card, 2, "nocq");
+- card->qdio.c_q = NULL;
++ qeth_free_cq(card);
+ }
+ return 0;
+ }
+
+-static void qeth_free_cq(struct qeth_card *card)
+-{
+- if (card->qdio.c_q) {
+- qeth_free_qdio_queue(card->qdio.c_q);
+- card->qdio.c_q = NULL;
+- }
+-}
+-
+ static enum iucv_tx_notify qeth_compute_cq_notification(int sbalf15,
+ int delayed)
+ {
+@@ -2628,6 +2631,10 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card)
+
+ QETH_CARD_TEXT(card, 2, "allcqdbf");
+
++ /* completion */
++ if (qeth_alloc_cq(card))
++ goto out_err;
++
+ if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED,
+ QETH_QDIO_ALLOCATED) != QETH_QDIO_UNINITIALIZED)
+ return 0;
+@@ -2663,10 +2670,6 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card)
+ queue->priority = QETH_QIB_PQUE_PRIO_DEFAULT;
+ }
+
+- /* completion */
+- if (qeth_alloc_cq(card))
+- goto out_freeoutq;
+-
+ return 0;
+
+ out_freeoutq:
+@@ -2677,6 +2680,8 @@ static int qeth_alloc_qdio_queues(struct qeth_card *card)
+ qeth_free_buffer_pool(card);
+ out_buffer_pool:
+ atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
++ qeth_free_cq(card);
++out_err:
+ return -ENOMEM;
+ }
+
+@@ -2684,11 +2689,12 @@ static void qeth_free_qdio_queues(struct qeth_card *card)
+ {
+ int i, j;
+
++ qeth_free_cq(card);
++
+ if (atomic_xchg(&card->qdio.state, QETH_QDIO_UNINITIALIZED) ==
+ QETH_QDIO_UNINITIALIZED)
+ return;
+
+- qeth_free_cq(card);
+ for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
+ if (card->qdio.in_q->bufs[j].rx_skb) {
+ consume_skb(card->qdio.in_q->bufs[j].rx_skb);
+@@ -3742,24 +3748,11 @@ static void qeth_qdio_poll(struct ccw_device *cdev, unsigned long card_ptr)
+
+ int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq)
+ {
+- int rc;
+-
+- if (card->options.cq == QETH_CQ_NOTAVAILABLE) {
+- rc = -1;
+- goto out;
+- } else {
+- if (card->options.cq == cq) {
+- rc = 0;
+- goto out;
+- }
+-
+- qeth_free_qdio_queues(card);
+- card->options.cq = cq;
+- rc = 0;
+- }
+-out:
+- return rc;
++ if (card->options.cq == QETH_CQ_NOTAVAILABLE)
++ return -1;
+
++ card->options.cq = cq;
++ return 0;
+ }
+ EXPORT_SYMBOL_GPL(qeth_configure_cq);
+
+diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+index 2c246e80c1c4d..d91659811eb3c 100644
+--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
++++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+@@ -833,7 +833,6 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
+
+ BNX2FC_TGT_DBG(tgt, "Freeing up session resources\n");
+
+- spin_lock_bh(&tgt->cq_lock);
+ ctx_base_ptr = tgt->ctx_base;
+ tgt->ctx_base = NULL;
+
+@@ -889,7 +888,6 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
+ tgt->sq, tgt->sq_dma);
+ tgt->sq = NULL;
+ }
+- spin_unlock_bh(&tgt->cq_lock);
+
+ if (ctx_base_ptr)
+ iounmap(ctx_base_ptr);
+diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+index b56fbc61a15ae..86112f234740d 100644
+--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
++++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+@@ -2244,7 +2244,15 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
+ case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+ if ((dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) &&
+ (sipc_rx_err_type & RX_FIS_STATUS_ERR_MSK)) {
+- ts->stat = SAS_PROTO_RESPONSE;
++ if (task->ata_task.use_ncq) {
++ struct domain_device *device = task->dev;
++ struct hisi_sas_device *sas_dev = device->lldd_dev;
++
++ sas_dev->dev_status = HISI_SAS_DEV_NCQ_ERR;
++ slot->abort = 1;
++ } else {
++ ts->stat = SAS_PROTO_RESPONSE;
++ }
+ } else if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) {
+ ts->residual = trans_tx_fail_type;
+ ts->stat = SAS_DATA_UNDERRUN;
+diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
+index 5c261005b74e4..f6e6db8b8aba9 100644
+--- a/drivers/scsi/libsas/sas_expander.c
++++ b/drivers/scsi/libsas/sas_expander.c
+@@ -135,7 +135,7 @@ static int smp_execute_task(struct domain_device *dev, void *req, int req_size,
+
+ static inline void *alloc_smp_req(int size)
+ {
+- u8 *p = kzalloc(size, GFP_KERNEL);
++ u8 *p = kzalloc(ALIGN(size, ARCH_DMA_MINALIGN), GFP_KERNEL);
+ if (p)
+ p[0] = SMP_REQUEST;
+ return p;
+diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
+index 04d608ea91060..9670cb2bf198e 100644
+--- a/drivers/scsi/lpfc/lpfc.h
++++ b/drivers/scsi/lpfc/lpfc.h
+@@ -1325,7 +1325,6 @@ struct lpfc_hba {
+ struct timer_list fabric_block_timer;
+ unsigned long bit_flags;
+ atomic_t num_rsrc_err;
+- atomic_t num_cmd_success;
+ unsigned long last_rsrc_error_time;
+ unsigned long last_ramp_down_time;
+ #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+@@ -1430,6 +1429,7 @@ struct lpfc_hba {
+ struct timer_list inactive_vmid_poll;
+
+ /* RAS Support */
++ spinlock_t ras_fwlog_lock; /* do not take while holding another lock */
+ struct lpfc_ras_fwlog ras_fwlog;
+
+ uint32_t iocb_cnt;
+diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
+index d3a5d6ecdf7d2..6f97a04171c44 100644
+--- a/drivers/scsi/lpfc/lpfc_attr.c
++++ b/drivers/scsi/lpfc/lpfc_attr.c
+@@ -5864,9 +5864,9 @@ lpfc_ras_fwlog_buffsize_set(struct lpfc_hba *phba, uint val)
+ if (phba->cfg_ras_fwlog_func != PCI_FUNC(phba->pcidev->devfn))
+ return -EINVAL;
+
+- spin_lock_irq(&phba->hbalock);
++ spin_lock_irq(&phba->ras_fwlog_lock);
+ state = phba->ras_fwlog.state;
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+
+ if (state == REG_INPROGRESS) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "6147 RAS Logging "
+diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
+index 2919579fa0846..c305d16cfae9a 100644
+--- a/drivers/scsi/lpfc/lpfc_bsg.c
++++ b/drivers/scsi/lpfc/lpfc_bsg.c
+@@ -5070,12 +5070,12 @@ lpfc_bsg_get_ras_config(struct bsg_job *job)
+ bsg_reply->reply_data.vendor_reply.vendor_rsp;
+
+ /* Current logging state */
+- spin_lock_irq(&phba->hbalock);
++ spin_lock_irq(&phba->ras_fwlog_lock);
+ if (ras_fwlog->state == ACTIVE)
+ ras_reply->state = LPFC_RASLOG_STATE_RUNNING;
+ else
+ ras_reply->state = LPFC_RASLOG_STATE_STOPPED;
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+
+ ras_reply->log_level = phba->ras_fwlog.fw_loglevel;
+ ras_reply->log_buff_sz = phba->cfg_ras_fwlog_buffsize;
+@@ -5132,13 +5132,13 @@ lpfc_bsg_set_ras_config(struct bsg_job *job)
+
+ if (action == LPFC_RASACTION_STOP_LOGGING) {
+ /* Check if already disabled */
+- spin_lock_irq(&phba->hbalock);
++ spin_lock_irq(&phba->ras_fwlog_lock);
+ if (ras_fwlog->state != ACTIVE) {
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+ rc = -ESRCH;
+ goto ras_job_error;
+ }
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+
+ /* Disable logging */
+ lpfc_ras_stop_fwlog(phba);
+@@ -5149,10 +5149,10 @@ lpfc_bsg_set_ras_config(struct bsg_job *job)
+ * FW-logging with new log-level. Return status
+ * "Logging already Running" to caller.
+ **/
+- spin_lock_irq(&phba->hbalock);
++ spin_lock_irq(&phba->ras_fwlog_lock);
+ if (ras_fwlog->state != INACTIVE)
+ action_status = -EINPROGRESS;
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+
+ /* Enable logging */
+ rc = lpfc_sli4_ras_fwlog_init(phba, log_level,
+@@ -5268,13 +5268,13 @@ lpfc_bsg_get_ras_fwlog(struct bsg_job *job)
+ goto ras_job_error;
+
+ /* Logging to be stopped before reading */
+- spin_lock_irq(&phba->hbalock);
++ spin_lock_irq(&phba->ras_fwlog_lock);
+ if (ras_fwlog->state == ACTIVE) {
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+ rc = -EINPROGRESS;
+ goto ras_job_error;
+ }
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+
+ if (job->request_len <
+ sizeof(struct fc_bsg_request) +
+diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
+index ea9b42225e629..20662b4f339eb 100644
+--- a/drivers/scsi/lpfc/lpfc_debugfs.c
++++ b/drivers/scsi/lpfc/lpfc_debugfs.c
+@@ -2196,12 +2196,12 @@ static int lpfc_debugfs_ras_log_data(struct lpfc_hba *phba,
+
+ memset(buffer, 0, size);
+
+- spin_lock_irq(&phba->hbalock);
++ spin_lock_irq(&phba->ras_fwlog_lock);
+ if (phba->ras_fwlog.state != ACTIVE) {
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+ return -EINVAL;
+ }
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+
+ list_for_each_entry_safe(dmabuf, next,
+ &phba->ras_fwlog.fwlog_buff_list, list) {
+@@ -2252,13 +2252,13 @@ lpfc_debugfs_ras_log_open(struct inode *inode, struct file *file)
+ int size;
+ int rc = -ENOMEM;
+
+- spin_lock_irq(&phba->hbalock);
++ spin_lock_irq(&phba->ras_fwlog_lock);
+ if (phba->ras_fwlog.state != ACTIVE) {
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+ rc = -EINVAL;
+ goto out;
+ }
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+
+ if (check_mul_overflow(LPFC_RAS_MIN_BUFF_POST_SIZE,
+ phba->cfg_ras_fwlog_buffsize, &size))
+diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
+index 4d723200690a4..26736122bda17 100644
+--- a/drivers/scsi/lpfc/lpfc_els.c
++++ b/drivers/scsi/lpfc/lpfc_els.c
+@@ -4462,23 +4462,23 @@ lpfc_els_retry_delay(struct timer_list *t)
+ unsigned long flags;
+ struct lpfc_work_evt *evtp = &ndlp->els_retry_evt;
+
++ /* Hold a node reference for outstanding queued work */
++ if (!lpfc_nlp_get(ndlp))
++ return;
++
+ spin_lock_irqsave(&phba->hbalock, flags);
+ if (!list_empty(&evtp->evt_listp)) {
+ spin_unlock_irqrestore(&phba->hbalock, flags);
++ lpfc_nlp_put(ndlp);
+ return;
+ }
+
+- /* We need to hold the node by incrementing the reference
+- * count until the queued work is done
+- */
+- evtp->evt_arg1 = lpfc_nlp_get(ndlp);
+- if (evtp->evt_arg1) {
+- evtp->evt = LPFC_EVT_ELS_RETRY;
+- list_add_tail(&evtp->evt_listp, &phba->work_list);
+- lpfc_worker_wake_up(phba);
+- }
++ evtp->evt_arg1 = ndlp;
++ evtp->evt = LPFC_EVT_ELS_RETRY;
++ list_add_tail(&evtp->evt_listp, &phba->work_list);
+ spin_unlock_irqrestore(&phba->hbalock, flags);
+- return;
++
++ lpfc_worker_wake_up(phba);
+ }
+
+ /**
+diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
+index f80bbc315f4ca..da3aee0f63237 100644
+--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
+@@ -257,7 +257,9 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
+ if (evtp->evt_arg1) {
+ evtp->evt = LPFC_EVT_DEV_LOSS;
+ list_add_tail(&evtp->evt_listp, &phba->work_list);
++ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ lpfc_worker_wake_up(phba);
++ return;
+ }
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ } else {
+@@ -275,10 +277,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
+ lpfc_disc_state_machine(vport, ndlp, NULL,
+ NLP_EVT_DEVICE_RM);
+ }
+-
+ }
+-
+- return;
+ }
+
+ /**
+diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
+index 70bcee64bc8c6..858ca395c0bf0 100644
+--- a/drivers/scsi/lpfc/lpfc_init.c
++++ b/drivers/scsi/lpfc/lpfc_init.c
+@@ -7698,6 +7698,9 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba)
+ "NVME" : " "),
+ (phba->nvmet_support ? "NVMET" : " "));
+
++ /* ras_fwlog state */
++ spin_lock_init(&phba->ras_fwlog_lock);
++
+ /* Initialize the IO buffer list used by driver for SLI3 SCSI */
+ spin_lock_init(&phba->scsi_buf_list_get_lock);
+ INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_get);
+@@ -13047,7 +13050,7 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
+ rc = request_threaded_irq(eqhdl->irq,
+ &lpfc_sli4_hba_intr_handler,
+ &lpfc_sli4_hba_intr_handler_th,
+- IRQF_ONESHOT, name, eqhdl);
++ 0, name, eqhdl);
+ if (rc) {
+ lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
+ "0486 MSI-X fast-path (%d) "
+diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
+index 128fc1bab5865..47218cf4d110d 100644
+--- a/drivers/scsi/lpfc/lpfc_nvme.c
++++ b/drivers/scsi/lpfc/lpfc_nvme.c
+@@ -2616,9 +2616,9 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
+ /* No concern about the role change on the nvme remoteport.
+ * The transport will update it.
+ */
+- spin_lock_irq(&vport->phba->hbalock);
++ spin_lock_irq(&ndlp->lock);
+ ndlp->fc4_xpt_flags |= NVME_XPT_UNREG_WAIT;
+- spin_unlock_irq(&vport->phba->hbalock);
++ spin_unlock_irq(&ndlp->lock);
+
+ /* Don't let the host nvme transport keep sending keep-alives
+ * on this remoteport. Vport is unloading, no recovery. The
+diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
+index bf879d81846b6..cf506556f3b0b 100644
+--- a/drivers/scsi/lpfc/lpfc_scsi.c
++++ b/drivers/scsi/lpfc/lpfc_scsi.c
+@@ -167,11 +167,10 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
+ struct Scsi_Host *shost;
+ struct scsi_device *sdev;
+ unsigned long new_queue_depth;
+- unsigned long num_rsrc_err, num_cmd_success;
++ unsigned long num_rsrc_err;
+ int i;
+
+ num_rsrc_err = atomic_read(&phba->num_rsrc_err);
+- num_cmd_success = atomic_read(&phba->num_cmd_success);
+
+ /*
+ * The error and success command counters are global per
+@@ -186,20 +185,16 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba)
+ for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) {
+ shost = lpfc_shost_from_vport(vports[i]);
+ shost_for_each_device(sdev, shost) {
+- new_queue_depth =
+- sdev->queue_depth * num_rsrc_err /
+- (num_rsrc_err + num_cmd_success);
+- if (!new_queue_depth)
+- new_queue_depth = sdev->queue_depth - 1;
++ if (num_rsrc_err >= sdev->queue_depth)
++ new_queue_depth = 1;
+ else
+ new_queue_depth = sdev->queue_depth -
+- new_queue_depth;
++ num_rsrc_err;
+ scsi_change_queue_depth(sdev, new_queue_depth);
+ }
+ }
+ lpfc_destroy_vport_work_array(phba, vports);
+ atomic_set(&phba->num_rsrc_err, 0);
+- atomic_set(&phba->num_cmd_success, 0);
+ }
+
+ /**
+diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
+index 706985358c6a0..e1821072552a5 100644
+--- a/drivers/scsi/lpfc/lpfc_sli.c
++++ b/drivers/scsi/lpfc/lpfc_sli.c
+@@ -1217,9 +1217,9 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+ empty = list_empty(&phba->active_rrq_list);
+ list_add_tail(&rrq->list, &phba->active_rrq_list);
+ phba->hba_flag |= HBA_RRQ_ACTIVE;
++ spin_unlock_irqrestore(&phba->hbalock, iflags);
+ if (empty)
+ lpfc_worker_wake_up(phba);
+- spin_unlock_irqrestore(&phba->hbalock, iflags);
+ return 0;
+ out:
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+@@ -6849,9 +6849,9 @@ lpfc_ras_stop_fwlog(struct lpfc_hba *phba)
+ {
+ struct lpfc_ras_fwlog *ras_fwlog = &phba->ras_fwlog;
+
+- spin_lock_irq(&phba->hbalock);
++ spin_lock_irq(&phba->ras_fwlog_lock);
+ ras_fwlog->state = INACTIVE;
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+
+ /* Disable FW logging to host memory */
+ writel(LPFC_CTL_PDEV_CTL_DDL_RAS,
+@@ -6894,9 +6894,9 @@ lpfc_sli4_ras_dma_free(struct lpfc_hba *phba)
+ ras_fwlog->lwpd.virt = NULL;
+ }
+
+- spin_lock_irq(&phba->hbalock);
++ spin_lock_irq(&phba->ras_fwlog_lock);
+ ras_fwlog->state = INACTIVE;
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+ }
+
+ /**
+@@ -6998,9 +6998,9 @@ lpfc_sli4_ras_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+ goto disable_ras;
+ }
+
+- spin_lock_irq(&phba->hbalock);
++ spin_lock_irq(&phba->ras_fwlog_lock);
+ ras_fwlog->state = ACTIVE;
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+ mempool_free(pmb, phba->mbox_mem_pool);
+
+ return;
+@@ -7032,9 +7032,9 @@ lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba,
+ uint32_t len = 0, fwlog_buffsize, fwlog_entry_count;
+ int rc = 0;
+
+- spin_lock_irq(&phba->hbalock);
++ spin_lock_irq(&phba->ras_fwlog_lock);
+ ras_fwlog->state = INACTIVE;
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+
+ fwlog_buffsize = (LPFC_RAS_MIN_BUFF_POST_SIZE *
+ phba->cfg_ras_fwlog_buffsize);
+@@ -7095,9 +7095,9 @@ lpfc_sli4_ras_fwlog_init(struct lpfc_hba *phba,
+ mbx_fwlog->u.request.lwpd.addr_lo = putPaddrLow(ras_fwlog->lwpd.phys);
+ mbx_fwlog->u.request.lwpd.addr_hi = putPaddrHigh(ras_fwlog->lwpd.phys);
+
+- spin_lock_irq(&phba->hbalock);
++ spin_lock_irq(&phba->ras_fwlog_lock);
+ ras_fwlog->state = REG_INPROGRESS;
+- spin_unlock_irq(&phba->hbalock);
++ spin_unlock_irq(&phba->ras_fwlog_lock);
+ mbox->vport = phba->pport;
+ mbox->mbox_cmpl = lpfc_sli4_ras_mbox_cmpl;
+
+@@ -11373,18 +11373,18 @@ lpfc_sli_post_recovery_event(struct lpfc_hba *phba,
+ unsigned long iflags;
+ struct lpfc_work_evt *evtp = &ndlp->recovery_evt;
+
++ /* Hold a node reference for outstanding queued work */
++ if (!lpfc_nlp_get(ndlp))
++ return;
++
+ spin_lock_irqsave(&phba->hbalock, iflags);
+ if (!list_empty(&evtp->evt_listp)) {
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
++ lpfc_nlp_put(ndlp);
+ return;
+ }
+
+- /* Incrementing the reference count until the queued work is done. */
+- evtp->evt_arg1 = lpfc_nlp_get(ndlp);
+- if (!evtp->evt_arg1) {
+- spin_unlock_irqrestore(&phba->hbalock, iflags);
+- return;
+- }
++ evtp->evt_arg1 = ndlp;
+ evtp->evt = LPFC_EVT_RECOVER_PORT;
+ list_add_tail(&evtp->evt_listp, &phba->work_list);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
+diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
+index 6c7559cf1a4b6..9e0e9e02d2c47 100644
+--- a/drivers/scsi/lpfc/lpfc_vport.c
++++ b/drivers/scsi/lpfc/lpfc_vport.c
+@@ -683,10 +683,6 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
+ lpfc_free_sysfs_attr(vport);
+ lpfc_debugfs_terminate(vport);
+
+- /* Remove FC host to break driver binding. */
+- fc_remove_host(shost);
+- scsi_remove_host(shost);
+-
+ /* Send the DA_ID and Fabric LOGO to cleanup Nameserver entries. */
+ ndlp = lpfc_findnode_did(vport, Fabric_DID);
+ if (!ndlp)
+@@ -730,6 +726,10 @@ lpfc_vport_delete(struct fc_vport *fc_vport)
+
+ skip_logo:
+
++ /* Remove FC host to break driver binding. */
++ fc_remove_host(shost);
++ scsi_remove_host(shost);
++
+ lpfc_cleanup(vport);
+
+ /* Remove scsi host now. The nodes are cleaned up. */
+diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c
+index 0380996b5ad27..55d590b919476 100644
+--- a/drivers/scsi/mpi3mr/mpi3mr_app.c
++++ b/drivers/scsi/mpi3mr/mpi3mr_app.c
+@@ -1644,7 +1644,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
+ if ((mpirep_offset != 0xFF) &&
+ drv_bufs[mpirep_offset].bsg_buf_len) {
+ drv_buf_iter = &drv_bufs[mpirep_offset];
+- drv_buf_iter->kern_buf_len = (sizeof(*bsg_reply_buf) - 1 +
++ drv_buf_iter->kern_buf_len = (sizeof(*bsg_reply_buf) +
+ mrioc->reply_sz);
+ bsg_reply_buf = kzalloc(drv_buf_iter->kern_buf_len, GFP_KERNEL);
+
+diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
+index 77aa6d26476cd..0da5d9d1af037 100644
+--- a/drivers/slimbus/qcom-ngd-ctrl.c
++++ b/drivers/slimbus/qcom-ngd-ctrl.c
+@@ -1451,7 +1451,11 @@ static void qcom_slim_ngd_up_worker(struct work_struct *work)
+ ctrl = container_of(work, struct qcom_slim_ngd_ctrl, ngd_up_work);
+
+ /* Make sure qmi service is up before continuing */
+- wait_for_completion_interruptible(&ctrl->qmi_up);
++ if (!wait_for_completion_interruptible_timeout(&ctrl->qmi_up,
++ msecs_to_jiffies(MSEC_PER_SEC))) {
++ dev_err(ctrl->dev, "QMI wait timeout\n");
++ return;
++ }
+
+ mutex_lock(&ctrl->ssr_lock);
+ qcom_slim_ngd_enable(ctrl, true);
+diff --git a/drivers/spi/spi-axi-spi-engine.c b/drivers/spi/spi-axi-spi-engine.c
+index 9ace259d2d29d..2b07b6dbf8a34 100644
+--- a/drivers/spi/spi-axi-spi-engine.c
++++ b/drivers/spi/spi-axi-spi-engine.c
+@@ -6,6 +6,7 @@
+ */
+
+ #include <linux/clk.h>
++#include <linux/fpga/adi-axi-common.h>
+ #include <linux/idr.h>
+ #include <linux/interrupt.h>
+ #include <linux/io.h>
+@@ -15,12 +16,6 @@
+ #include <linux/spi/spi.h>
+ #include <linux/timer.h>
+
+-#define SPI_ENGINE_VERSION_MAJOR(x) ((x >> 16) & 0xff)
+-#define SPI_ENGINE_VERSION_MINOR(x) ((x >> 8) & 0xff)
+-#define SPI_ENGINE_VERSION_PATCH(x) (x & 0xff)
+-
+-#define SPI_ENGINE_REG_VERSION 0x00
+-
+ #define SPI_ENGINE_REG_RESET 0x40
+
+ #define SPI_ENGINE_REG_INT_ENABLE 0x80
+@@ -661,12 +656,12 @@ static int spi_engine_probe(struct platform_device *pdev)
+ if (IS_ERR(spi_engine->base))
+ return PTR_ERR(spi_engine->base);
+
+- version = readl(spi_engine->base + SPI_ENGINE_REG_VERSION);
+- if (SPI_ENGINE_VERSION_MAJOR(version) != 1) {
+- dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%c\n",
+- SPI_ENGINE_VERSION_MAJOR(version),
+- SPI_ENGINE_VERSION_MINOR(version),
+- SPI_ENGINE_VERSION_PATCH(version));
++ version = readl(spi_engine->base + ADI_AXI_REG_VERSION);
++ if (ADI_AXI_PCORE_VER_MAJOR(version) != 1) {
++ dev_err(&pdev->dev, "Unsupported peripheral version %u.%u.%u\n",
++ ADI_AXI_PCORE_VER_MAJOR(version),
++ ADI_AXI_PCORE_VER_MINOR(version),
++ ADI_AXI_PCORE_VER_PATCH(version));
+ return -ENODEV;
+ }
+
+diff --git a/drivers/spi/spi-hisi-kunpeng.c b/drivers/spi/spi-hisi-kunpeng.c
+index 35ef5e8e2ffd2..77e9738e42f60 100644
+--- a/drivers/spi/spi-hisi-kunpeng.c
++++ b/drivers/spi/spi-hisi-kunpeng.c
+@@ -151,8 +151,6 @@ static const struct debugfs_reg32 hisi_spi_regs[] = {
+ HISI_SPI_DBGFS_REG("ENR", HISI_SPI_ENR),
+ HISI_SPI_DBGFS_REG("FIFOC", HISI_SPI_FIFOC),
+ HISI_SPI_DBGFS_REG("IMR", HISI_SPI_IMR),
+- HISI_SPI_DBGFS_REG("DIN", HISI_SPI_DIN),
+- HISI_SPI_DBGFS_REG("DOUT", HISI_SPI_DOUT),
+ HISI_SPI_DBGFS_REG("SR", HISI_SPI_SR),
+ HISI_SPI_DBGFS_REG("RISR", HISI_SPI_RISR),
+ HISI_SPI_DBGFS_REG("ISR", HISI_SPI_ISR),
+diff --git a/drivers/spi/spi-microchip-core-qspi.c b/drivers/spi/spi-microchip-core-qspi.c
+index 03d125a71fd99..09f16471c5375 100644
+--- a/drivers/spi/spi-microchip-core-qspi.c
++++ b/drivers/spi/spi-microchip-core-qspi.c
+@@ -283,6 +283,7 @@ static int mchp_coreqspi_setup_clock(struct mchp_coreqspi *qspi, struct spi_devi
+ }
+
+ control = readl_relaxed(qspi->regs + REG_CONTROL);
++ control &= ~CONTROL_CLKRATE_MASK;
+ control |= baud_rate_val << CONTROL_CLKRATE_SHIFT;
+ writel_relaxed(control, qspi->regs + REG_CONTROL);
+ control = readl_relaxed(qspi->regs + REG_CONTROL);
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index 46f1535487608..a7194f29c2007 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -4431,6 +4431,7 @@ static int __spi_sync(struct spi_device *spi, struct spi_message *message)
+ wait_for_completion(&done);
+ status = message->status;
+ }
++ message->complete = NULL;
+ message->context = NULL;
+
+ return status;
+diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
+index c1fbcdd161826..c40217f44b1bc 100644
+--- a/drivers/target/target_core_configfs.c
++++ b/drivers/target/target_core_configfs.c
+@@ -3672,6 +3672,8 @@ static int __init target_core_init_configfs(void)
+ {
+ struct configfs_subsystem *subsys = &target_core_fabrics;
+ struct t10_alua_lu_gp *lu_gp;
++ struct cred *kern_cred;
++ const struct cred *old_cred;
+ int ret;
+
+ pr_debug("TARGET_CORE[0]: Loading Generic Kernel Storage"
+@@ -3748,11 +3750,21 @@ static int __init target_core_init_configfs(void)
+ if (ret < 0)
+ goto out;
+
++ /* We use the kernel credentials to access the target directory */
++ kern_cred = prepare_kernel_cred(&init_task);
++ if (!kern_cred) {
++ ret = -ENOMEM;
++ goto out;
++ }
++ old_cred = override_creds(kern_cred);
+ target_init_dbroot();
++ revert_creds(old_cred);
++ put_cred(kern_cred);
+
+ return 0;
+
+ out:
++ target_xcopy_release_pt();
+ configfs_unregister_subsystem(subsys);
+ core_dev_release_virtual_lun0();
+ rd_module_exit();
+diff --git a/drivers/thermal/thermal_debugfs.c b/drivers/thermal/thermal_debugfs.c
+index d78d54ae2605e..5693cc8b231aa 100644
+--- a/drivers/thermal/thermal_debugfs.c
++++ b/drivers/thermal/thermal_debugfs.c
+@@ -139,11 +139,13 @@ struct tz_episode {
+ * we keep track of the current position in the history array.
+ *
+ * @tz_episodes: a list of thermal mitigation episodes
++ * @tz: thermal zone this object belongs to
+ * @trips_crossed: an array of trip points crossed by id
+ * @nr_trips: the number of trip points currently being crossed
+ */
+ struct tz_debugfs {
+ struct list_head tz_episodes;
++ struct thermal_zone_device *tz;
+ int *trips_crossed;
+ int nr_trips;
+ };
+@@ -503,15 +505,23 @@ void thermal_debug_cdev_add(struct thermal_cooling_device *cdev)
+ */
+ void thermal_debug_cdev_remove(struct thermal_cooling_device *cdev)
+ {
+- struct thermal_debugfs *thermal_dbg = cdev->debugfs;
++ struct thermal_debugfs *thermal_dbg;
+
+- if (!thermal_dbg)
++ mutex_lock(&cdev->lock);
++
++ thermal_dbg = cdev->debugfs;
++ if (!thermal_dbg) {
++ mutex_unlock(&cdev->lock);
+ return;
++ }
++
++ cdev->debugfs = NULL;
++
++ mutex_unlock(&cdev->lock);
+
+ mutex_lock(&thermal_dbg->lock);
+
+ thermal_debugfs_cdev_clear(&thermal_dbg->cdev_dbg);
+- cdev->debugfs = NULL;
+
+ mutex_unlock(&thermal_dbg->lock);
+
+@@ -716,8 +726,7 @@ void thermal_debug_update_temp(struct thermal_zone_device *tz)
+
+ static void *tze_seq_start(struct seq_file *s, loff_t *pos)
+ {
+- struct thermal_zone_device *tz = s->private;
+- struct thermal_debugfs *thermal_dbg = tz->debugfs;
++ struct thermal_debugfs *thermal_dbg = s->private;
+ struct tz_debugfs *tz_dbg = &thermal_dbg->tz_dbg;
+
+ mutex_lock(&thermal_dbg->lock);
+@@ -727,8 +736,7 @@ static void *tze_seq_start(struct seq_file *s, loff_t *pos)
+
+ static void *tze_seq_next(struct seq_file *s, void *v, loff_t *pos)
+ {
+- struct thermal_zone_device *tz = s->private;
+- struct thermal_debugfs *thermal_dbg = tz->debugfs;
++ struct thermal_debugfs *thermal_dbg = s->private;
+ struct tz_debugfs *tz_dbg = &thermal_dbg->tz_dbg;
+
+ return seq_list_next(v, &tz_dbg->tz_episodes, pos);
+@@ -736,15 +744,15 @@ static void *tze_seq_next(struct seq_file *s, void *v, loff_t *pos)
+
+ static void tze_seq_stop(struct seq_file *s, void *v)
+ {
+- struct thermal_zone_device *tz = s->private;
+- struct thermal_debugfs *thermal_dbg = tz->debugfs;
++ struct thermal_debugfs *thermal_dbg = s->private;
+
+ mutex_unlock(&thermal_dbg->lock);
+ }
+
+ static int tze_seq_show(struct seq_file *s, void *v)
+ {
+- struct thermal_zone_device *tz = s->private;
++ struct thermal_debugfs *thermal_dbg = s->private;
++ struct thermal_zone_device *tz = thermal_dbg->tz_dbg.tz;
+ struct thermal_trip *trip;
+ struct tz_episode *tze;
+ const char *type;
+@@ -810,6 +818,8 @@ void thermal_debug_tz_add(struct thermal_zone_device *tz)
+
+ tz_dbg = &thermal_dbg->tz_dbg;
+
++ tz_dbg->tz = tz;
++
+ tz_dbg->trips_crossed = kzalloc(sizeof(int) * tz->num_trips, GFP_KERNEL);
+ if (!tz_dbg->trips_crossed) {
+ thermal_debugfs_remove_id(thermal_dbg);
+@@ -818,23 +828,44 @@ void thermal_debug_tz_add(struct thermal_zone_device *tz)
+
+ INIT_LIST_HEAD(&tz_dbg->tz_episodes);
+
+- debugfs_create_file("mitigations", 0400, thermal_dbg->d_top, tz, &tze_fops);
++ debugfs_create_file("mitigations", 0400, thermal_dbg->d_top,
++ thermal_dbg, &tze_fops);
+
+ tz->debugfs = thermal_dbg;
+ }
+
+ void thermal_debug_tz_remove(struct thermal_zone_device *tz)
+ {
+- struct thermal_debugfs *thermal_dbg = tz->debugfs;
++ struct thermal_debugfs *thermal_dbg;
++ struct tz_episode *tze, *tmp;
++ struct tz_debugfs *tz_dbg;
++ int *trips_crossed;
+
+- if (!thermal_dbg)
++ mutex_lock(&tz->lock);
++
++ thermal_dbg = tz->debugfs;
++ if (!thermal_dbg) {
++ mutex_unlock(&tz->lock);
+ return;
++ }
++
++ tz->debugfs = NULL;
++
++ mutex_unlock(&tz->lock);
++
++ tz_dbg = &thermal_dbg->tz_dbg;
+
+ mutex_lock(&thermal_dbg->lock);
+
+- tz->debugfs = NULL;
++ trips_crossed = tz_dbg->trips_crossed;
++
++ list_for_each_entry_safe(tze, tmp, &tz_dbg->tz_episodes, node) {
++ list_del(&tze->node);
++ kfree(tze);
++ }
+
+ mutex_unlock(&thermal_dbg->lock);
+
+ thermal_debugfs_remove_id(thermal_dbg);
++ kfree(trips_crossed);
+ }
+diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
+index 0787456c2b892..c873fd8239427 100644
+--- a/drivers/ufs/core/ufs-mcq.c
++++ b/drivers/ufs/core/ufs-mcq.c
+@@ -94,7 +94,7 @@ void ufshcd_mcq_config_mac(struct ufs_hba *hba, u32 max_active_cmds)
+
+ val = ufshcd_readl(hba, REG_UFS_MCQ_CFG);
+ val &= ~MCQ_CFG_MAC_MASK;
+- val |= FIELD_PREP(MCQ_CFG_MAC_MASK, max_active_cmds);
++ val |= FIELD_PREP(MCQ_CFG_MAC_MASK, max_active_cmds - 1);
+ ufshcd_writel(hba, val, REG_UFS_MCQ_CFG);
+ }
+ EXPORT_SYMBOL_GPL(ufshcd_mcq_config_mac);
+diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
+index 3b89c9d4aa404..4a07a18cf835d 100644
+--- a/drivers/ufs/core/ufshcd.c
++++ b/drivers/ufs/core/ufshcd.c
+@@ -3172,7 +3172,9 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
+
+ /* MCQ mode */
+ if (is_mcq_enabled(hba)) {
+- err = ufshcd_clear_cmd(hba, lrbp->task_tag);
++ /* successfully cleared the command, retry if needed */
++ if (ufshcd_clear_cmd(hba, lrbp->task_tag) == 0)
++ err = -EAGAIN;
+ hba->dev_cmd.complete = NULL;
+ return err;
+ }
+@@ -9745,7 +9747,10 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+
+ /* UFS device & link must be active before we enter in this function */
+ if (!ufshcd_is_ufs_dev_active(hba) || !ufshcd_is_link_active(hba)) {
+- ret = -EINVAL;
++ /* Wait err handler finish or trigger err recovery */
++ if (!ufshcd_eh_in_progress(hba))
++ ufshcd_force_error_recovery(hba);
++ ret = -EBUSY;
+ goto enable_scaling;
+ }
+
+diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
+index 20d9762331bd7..6be3462b109ff 100644
+--- a/drivers/uio/uio_hv_generic.c
++++ b/drivers/uio/uio_hv_generic.c
+@@ -181,12 +181,14 @@ hv_uio_cleanup(struct hv_device *dev, struct hv_uio_private_data *pdata)
+ {
+ if (pdata->send_gpadl.gpadl_handle) {
+ vmbus_teardown_gpadl(dev->channel, &pdata->send_gpadl);
+- vfree(pdata->send_buf);
++ if (!pdata->send_gpadl.decrypted)
++ vfree(pdata->send_buf);
+ }
+
+ if (pdata->recv_gpadl.gpadl_handle) {
+ vmbus_teardown_gpadl(dev->channel, &pdata->recv_gpadl);
+- vfree(pdata->recv_buf);
++ if (!pdata->recv_gpadl.decrypted)
++ vfree(pdata->recv_buf);
+ }
+ }
+
+@@ -295,7 +297,8 @@ hv_uio_probe(struct hv_device *dev,
+ ret = vmbus_establish_gpadl(channel, pdata->recv_buf,
+ RECV_BUFFER_SIZE, &pdata->recv_gpadl);
+ if (ret) {
+- vfree(pdata->recv_buf);
++ if (!pdata->recv_gpadl.decrypted)
++ vfree(pdata->recv_buf);
+ goto fail_close;
+ }
+
+@@ -317,7 +320,8 @@ hv_uio_probe(struct hv_device *dev,
+ ret = vmbus_establish_gpadl(channel, pdata->send_buf,
+ SEND_BUFFER_SIZE, &pdata->send_gpadl);
+ if (ret) {
+- vfree(pdata->send_buf);
++ if (!pdata->send_gpadl.decrypted)
++ vfree(pdata->send_buf);
+ goto fail_close;
+ }
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 64e54163f05e6..48e1e43780eb8 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -5081,9 +5081,10 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
+ }
+ if (usb_endpoint_maxp(&udev->ep0.desc) == i) {
+ ; /* Initial ep0 maxpacket guess is right */
+- } else if ((udev->speed == USB_SPEED_FULL ||
++ } else if (((udev->speed == USB_SPEED_FULL ||
+ udev->speed == USB_SPEED_HIGH) &&
+- (i == 8 || i == 16 || i == 32 || i == 64)) {
++ (i == 8 || i == 16 || i == 32 || i == 64)) ||
++ (udev->speed >= USB_SPEED_SUPER && i > 0)) {
+ /* Initial guess is wrong; use the descriptor's value */
+ if (udev->speed == USB_SPEED_FULL)
+ dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
+diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
+index 97ff2073cf1e2..d34d67fcb47b2 100644
+--- a/drivers/usb/core/port.c
++++ b/drivers/usb/core/port.c
+@@ -50,13 +50,15 @@ static ssize_t disable_show(struct device *dev,
+ struct usb_port *port_dev = to_usb_port(dev);
+ struct usb_device *hdev = to_usb_device(dev->parent->parent);
+ struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
+- struct usb_interface *intf = to_usb_interface(hub->intfdev);
++ struct usb_interface *intf = to_usb_interface(dev->parent);
+ int port1 = port_dev->portnum;
+ u16 portstatus, unused;
+ bool disabled;
+ int rc;
+ struct kernfs_node *kn;
+
++ if (!hub)
++ return -ENODEV;
+ hub_get(hub);
+ rc = usb_autopm_get_interface(intf);
+ if (rc < 0)
+@@ -100,12 +102,14 @@ static ssize_t disable_store(struct device *dev, struct device_attribute *attr,
+ struct usb_port *port_dev = to_usb_port(dev);
+ struct usb_device *hdev = to_usb_device(dev->parent->parent);
+ struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
+- struct usb_interface *intf = to_usb_interface(hub->intfdev);
++ struct usb_interface *intf = to_usb_interface(dev->parent);
+ int port1 = port_dev->portnum;
+ bool disabled;
+ int rc;
+ struct kernfs_node *kn;
+
++ if (!hub)
++ return -ENODEV;
+ rc = kstrtobool(buf, &disabled);
+ if (rc)
+ return rc;
+diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
+index 31684cdaaae30..100041320e8dd 100644
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -104,6 +104,27 @@ static int dwc3_get_dr_mode(struct dwc3 *dwc)
+ return 0;
+ }
+
++void dwc3_enable_susphy(struct dwc3 *dwc, bool enable)
++{
++ u32 reg;
++
++ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
++ if (enable && !dwc->dis_u3_susphy_quirk)
++ reg |= DWC3_GUSB3PIPECTL_SUSPHY;
++ else
++ reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
++
++ dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
++
++ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
++ if (enable && !dwc->dis_u2_susphy_quirk)
++ reg |= DWC3_GUSB2PHYCFG_SUSPHY;
++ else
++ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
++
++ dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
++}
++
+ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode)
+ {
+ u32 reg;
+@@ -585,11 +606,8 @@ static int dwc3_core_ulpi_init(struct dwc3 *dwc)
+ */
+ static int dwc3_phy_setup(struct dwc3 *dwc)
+ {
+- unsigned int hw_mode;
+ u32 reg;
+
+- hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
+-
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
+
+ /*
+@@ -599,21 +617,16 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
+ reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX;
+
+ /*
+- * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY
+- * to '0' during coreConsultant configuration. So default value
+- * will be '0' when the core is reset. Application needs to set it
+- * to '1' after the core initialization is completed.
+- */
+- if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A))
+- reg |= DWC3_GUSB3PIPECTL_SUSPHY;
+-
+- /*
+- * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be cleared after
+- * power-on reset, and it can be set after core initialization, which is
+- * after device soft-reset during initialization.
++ * Above DWC_usb3.0 1.94a, it is recommended to set
++ * DWC3_GUSB3PIPECTL_SUSPHY to '0' during coreConsultant configuration.
++ * So default value will be '0' when the core is reset. Application
++ * needs to set it to '1' after the core initialization is completed.
++ *
++ * Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be
++ * cleared after power-on reset, and it can be set after core
++ * initialization.
+ */
+- if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
+- reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
++ reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
+
+ if (dwc->u2ss_inp3_quirk)
+ reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK;
+@@ -639,9 +652,6 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
+ if (dwc->tx_de_emphasis_quirk)
+ reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis);
+
+- if (dwc->dis_u3_susphy_quirk)
+- reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
+-
+ if (dwc->dis_del_phy_power_chg_quirk)
+ reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
+
+@@ -689,24 +699,15 @@ static int dwc3_phy_setup(struct dwc3 *dwc)
+ }
+
+ /*
+- * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to
+- * '0' during coreConsultant configuration. So default value will
+- * be '0' when the core is reset. Application needs to set it to
+- * '1' after the core initialization is completed.
+- */
+- if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A))
+- reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+-
+- /*
+- * For DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared after
+- * power-on reset, and it can be set after core initialization, which is
+- * after device soft-reset during initialization.
++ * Above DWC_usb3.0 1.94a, it is recommended to set
++ * DWC3_GUSB2PHYCFG_SUSPHY to '0' during coreConsultant configuration.
++ * So default value will be '0' when the core is reset. Application
++ * needs to set it to '1' after the core initialization is completed.
++ *
++ * Similarly for DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared
++ * after power-on reset, and it can be set after core initialization.
+ */
+- if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD)
+- reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+-
+- if (dwc->dis_u2_susphy_quirk)
+- reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
++ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+
+ if (dwc->dis_enblslpm_quirk)
+ reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
+@@ -1227,21 +1228,6 @@ static int dwc3_core_init(struct dwc3 *dwc)
+ if (ret)
+ goto err_exit_phy;
+
+- if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD &&
+- !DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) {
+- if (!dwc->dis_u3_susphy_quirk) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0));
+- reg |= DWC3_GUSB3PIPECTL_SUSPHY;
+- dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
+- }
+-
+- if (!dwc->dis_u2_susphy_quirk) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+- reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+- }
+- }
+-
+ dwc3_core_setup_global_control(dwc);
+ dwc3_core_num_eps(dwc);
+
+diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
+index 893b1e694efe1..d96a28eecbcc3 100644
+--- a/drivers/usb/dwc3/core.h
++++ b/drivers/usb/dwc3/core.h
+@@ -1578,6 +1578,7 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc);
+ void dwc3_event_buffers_cleanup(struct dwc3 *dwc);
+
+ int dwc3_core_soft_reset(struct dwc3 *dwc);
++void dwc3_enable_susphy(struct dwc3 *dwc, bool enable);
+
+ #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
+ int dwc3_host_init(struct dwc3 *dwc);
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 07820b1a88a24..4062a486b9e63 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -2937,6 +2937,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
+ dwc3_ep0_out_start(dwc);
+
+ dwc3_gadget_enable_irq(dwc);
++ dwc3_enable_susphy(dwc, true);
+
+ return 0;
+
+@@ -4703,6 +4704,7 @@ void dwc3_gadget_exit(struct dwc3 *dwc)
+ if (!dwc->gadget)
+ return;
+
++ dwc3_enable_susphy(dwc, false);
+ usb_del_gadget(dwc->gadget);
+ dwc3_gadget_free_endpoints(dwc);
+ usb_put_gadget(dwc->gadget);
+diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
+index f6a020d77fa18..6c143f7d24103 100644
+--- a/drivers/usb/dwc3/host.c
++++ b/drivers/usb/dwc3/host.c
+@@ -10,9 +10,30 @@
+ #include <linux/irq.h>
+ #include <linux/of.h>
+ #include <linux/platform_device.h>
++#include <linux/usb.h>
++#include <linux/usb/hcd.h>
+
++#include "../host/xhci-plat.h"
+ #include "core.h"
+
++static void dwc3_xhci_plat_start(struct usb_hcd *hcd)
++{
++ struct platform_device *pdev;
++ struct dwc3 *dwc;
++
++ if (!usb_hcd_is_primary_hcd(hcd))
++ return;
++
++ pdev = to_platform_device(hcd->self.controller);
++ dwc = dev_get_drvdata(pdev->dev.parent);
++
++ dwc3_enable_susphy(dwc, true);
++}
++
++static const struct xhci_plat_priv dwc3_xhci_plat_quirk = {
++ .plat_start = dwc3_xhci_plat_start,
++};
++
+ static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc,
+ int irq, char *name)
+ {
+@@ -117,6 +138,11 @@ int dwc3_host_init(struct dwc3 *dwc)
+ }
+ }
+
++ ret = platform_device_add_data(xhci, &dwc3_xhci_plat_quirk,
++ sizeof(struct xhci_plat_priv));
++ if (ret)
++ goto err;
++
+ ret = platform_device_add(xhci);
+ if (ret) {
+ dev_err(dwc->dev, "failed to register xHCI device\n");
+@@ -142,6 +168,7 @@ void dwc3_host_exit(struct dwc3 *dwc)
+ if (dwc->sys_wakeup)
+ device_init_wakeup(&dwc->xhci->dev, false);
+
++ dwc3_enable_susphy(dwc, false);
+ platform_device_unregister(dwc->xhci);
+ dwc->xhci = NULL;
+ }
+diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
+index 0ace45b66a31c..0e151b54aae82 100644
+--- a/drivers/usb/gadget/composite.c
++++ b/drivers/usb/gadget/composite.c
+@@ -2112,7 +2112,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+ buf[5] = 0x01;
+ switch (ctrl->bRequestType & USB_RECIP_MASK) {
+ case USB_RECIP_DEVICE:
+- if (w_index != 0x4 || (w_value >> 8))
++ if (w_index != 0x4 || (w_value & 0xff))
+ break;
+ buf[6] = w_index;
+ /* Number of ext compat interfaces */
+@@ -2128,9 +2128,9 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
+ }
+ break;
+ case USB_RECIP_INTERFACE:
+- if (w_index != 0x5 || (w_value >> 8))
++ if (w_index != 0x5 || (w_value & 0xff))
+ break;
+- interface = w_value & 0xFF;
++ interface = w_value >> 8;
+ if (interface >= MAX_CONFIG_INTERFACES ||
+ !os_desc_cfg->interface[interface])
+ break;
+diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
+index 6bff6cb937891..839426d92b995 100644
+--- a/drivers/usb/gadget/function/f_fs.c
++++ b/drivers/usb/gadget/function/f_fs.c
+@@ -821,6 +821,7 @@ static void ffs_user_copy_worker(struct work_struct *work)
+ work);
+ int ret = io_data->status;
+ bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
++ unsigned long flags;
+
+ if (io_data->read && ret > 0) {
+ kthread_use_mm(io_data->mm);
+@@ -833,6 +834,11 @@ static void ffs_user_copy_worker(struct work_struct *work)
+ if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd)
+ eventfd_signal(io_data->ffs->ffs_eventfd);
+
++ spin_lock_irqsave(&io_data->ffs->eps_lock, flags);
++ usb_ep_free_request(io_data->ep, io_data->req);
++ io_data->req = NULL;
++ spin_unlock_irqrestore(&io_data->ffs->eps_lock, flags);
++
+ if (io_data->read)
+ kfree(io_data->to_free);
+ ffs_free_buffer(io_data);
+@@ -846,7 +852,6 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep,
+ struct ffs_data *ffs = io_data->ffs;
+
+ io_data->status = req->status ? req->status : req->actual;
+- usb_ep_free_request(_ep, req);
+
+ INIT_WORK(&io_data->work, ffs_user_copy_worker);
+ queue_work(ffs->io_completion_wq, &io_data->work);
+@@ -3330,7 +3335,7 @@ static int ffs_func_setup(struct usb_function *f,
+ __ffs_event_add(ffs, FUNCTIONFS_SETUP);
+ spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
+
+- return creq->wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
++ return ffs->ev.setup.wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0;
+ }
+
+ static bool ffs_func_req_match(struct usb_function *f,
+diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
+index 7e704b2bcfd1c..a4377df612f51 100644
+--- a/drivers/usb/gadget/function/uvc_configfs.c
++++ b/drivers/usb/gadget/function/uvc_configfs.c
+@@ -92,10 +92,10 @@ static int __uvcg_iter_item_entries(const char *page, size_t len,
+
+ while (pg - page < len) {
+ i = 0;
+- while (i < sizeof(buf) && (pg - page < len) &&
++ while (i < bufsize && (pg - page < len) &&
+ *pg != '\0' && *pg != '\n')
+ buf[i++] = *pg++;
+- if (i == sizeof(buf)) {
++ if (i == bufsize) {
+ ret = -EINVAL;
+ goto out_free_buf;
+ }
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index 4f9982ecfb583..5cec7640e913c 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -888,6 +888,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ /* Check for an all 1's result which is a typical consequence
+ * of dead, unclocked, or unplugged (CardBus...) devices
+ */
++again:
+ if (ints == ~(u32)0) {
+ ohci->rh_state = OHCI_RH_HALTED;
+ ohci_dbg (ohci, "device removed!\n");
+@@ -982,6 +983,13 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ }
+ spin_unlock(&ohci->lock);
+
++ /* repeat until all enabled interrupts are handled */
++ if (ohci->rh_state != OHCI_RH_HALTED) {
++ ints = ohci_readl(ohci, ®s->intrstatus);
++ if (ints && (ints & ohci_readl(ohci, ®s->intrenable)))
++ goto again;
++ }
++
+ return IRQ_HANDLED;
+ }
+
+diff --git a/drivers/usb/host/xhci-plat.h b/drivers/usb/host/xhci-plat.h
+index 2d15386f2c504..6475130eac4b3 100644
+--- a/drivers/usb/host/xhci-plat.h
++++ b/drivers/usb/host/xhci-plat.h
+@@ -8,7 +8,9 @@
+ #ifndef _XHCI_PLAT_H
+ #define _XHCI_PLAT_H
+
+-#include "xhci.h" /* for hcd_to_xhci() */
++struct device;
++struct platform_device;
++struct usb_hcd;
+
+ struct xhci_plat_priv {
+ const char *firmware_name;
+diff --git a/drivers/usb/host/xhci-rzv2m.c b/drivers/usb/host/xhci-rzv2m.c
+index ec65b24eafa86..4f59867d7117c 100644
+--- a/drivers/usb/host/xhci-rzv2m.c
++++ b/drivers/usb/host/xhci-rzv2m.c
+@@ -6,6 +6,7 @@
+ */
+
+ #include <linux/usb/rzv2m_usb3drd.h>
++#include "xhci.h"
+ #include "xhci-plat.h"
+ #include "xhci-rzv2m.h"
+
+diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
+index df9a5d6760b45..3f7200a2272f2 100644
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -1501,7 +1501,8 @@ static void svdm_consume_identity(struct tcpm_port *port, const u32 *p, int cnt)
+ port->partner_ident.cert_stat = p[VDO_INDEX_CSTAT];
+ port->partner_ident.product = product;
+
+- typec_partner_set_identity(port->partner);
++ if (port->partner)
++ typec_partner_set_identity(port->partner);
+
+ tcpm_log(port, "Identity: %04x:%04x.%04x",
+ PD_IDH_VID(vdo),
+@@ -1589,6 +1590,9 @@ static void tcpm_register_partner_altmodes(struct tcpm_port *port)
+ struct typec_altmode *altmode;
+ int i;
+
++ if (!port->partner)
++ return;
++
+ for (i = 0; i < modep->altmodes; i++) {
+ altmode = typec_partner_register_altmode(port->partner,
+ &modep->altmode_desc[i]);
+@@ -2435,7 +2439,7 @@ static int tcpm_register_sink_caps(struct tcpm_port *port)
+ {
+ struct usb_power_delivery_desc desc = { port->negotiated_rev };
+ struct usb_power_delivery_capabilities_desc caps = { };
+- struct usb_power_delivery_capabilities *cap;
++ struct usb_power_delivery_capabilities *cap = port->partner_source_caps;
+
+ if (!port->partner_pd)
+ port->partner_pd = usb_power_delivery_register(NULL, &desc);
+@@ -2445,6 +2449,9 @@ static int tcpm_register_sink_caps(struct tcpm_port *port)
+ memcpy(caps.pdo, port->sink_caps, sizeof(u32) * port->nr_sink_caps);
+ caps.role = TYPEC_SINK;
+
++ if (cap)
++ usb_power_delivery_unregister_capabilities(cap);
++
+ cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps);
+ if (IS_ERR(cap))
+ return PTR_ERR(cap);
+@@ -3584,7 +3591,10 @@ static int tcpm_init_vconn(struct tcpm_port *port)
+
+ static void tcpm_typec_connect(struct tcpm_port *port)
+ {
++ struct typec_partner *partner;
++
+ if (!port->connected) {
++ port->connected = true;
+ /* Make sure we don't report stale identity information */
+ memset(&port->partner_ident, 0, sizeof(port->partner_ident));
+ port->partner_desc.usb_pd = port->pd_capable;
+@@ -3594,9 +3604,13 @@ static void tcpm_typec_connect(struct tcpm_port *port)
+ port->partner_desc.accessory = TYPEC_ACCESSORY_AUDIO;
+ else
+ port->partner_desc.accessory = TYPEC_ACCESSORY_NONE;
+- port->partner = typec_register_partner(port->typec_port,
+- &port->partner_desc);
+- port->connected = true;
++ partner = typec_register_partner(port->typec_port, &port->partner_desc);
++ if (IS_ERR(partner)) {
++ dev_err(port->dev, "Failed to register partner (%ld)\n", PTR_ERR(partner));
++ return;
++ }
++
++ port->partner = partner;
+ typec_partner_set_usb_power_delivery(port->partner, port->partner_pd);
+ }
+ }
+@@ -3666,9 +3680,11 @@ static int tcpm_src_attach(struct tcpm_port *port)
+ static void tcpm_typec_disconnect(struct tcpm_port *port)
+ {
+ if (port->connected) {
+- typec_partner_set_usb_power_delivery(port->partner, NULL);
+- typec_unregister_partner(port->partner);
+- port->partner = NULL;
++ if (port->partner) {
++ typec_partner_set_usb_power_delivery(port->partner, NULL);
++ typec_unregister_partner(port->partner);
++ port->partner = NULL;
++ }
+ port->connected = false;
+ }
+ }
+@@ -3884,6 +3900,9 @@ static enum typec_cc_status tcpm_pwr_opmode_to_rp(enum typec_pwr_opmode opmode)
+
+ static void tcpm_set_initial_svdm_version(struct tcpm_port *port)
+ {
++ if (!port->partner)
++ return;
++
+ switch (port->negotiated_rev) {
+ case PD_REV30:
+ break;
+@@ -4873,6 +4892,7 @@ static void run_state_machine(struct tcpm_port *port)
+ break;
+ case PORT_RESET:
+ tcpm_reset_port(port);
++ port->pd_events = 0;
+ if (port->self_powered)
+ tcpm_set_cc(port, TYPEC_CC_OPEN);
+ else
+diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
+index cd415565b60a1..b501760012c4f 100644
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -975,7 +975,7 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num)
+ struct ucsi_connector *con = &ucsi->connector[num - 1];
+
+ if (!(ucsi->ntfy & UCSI_ENABLE_NTFY_CONNECTOR_CHANGE)) {
+- dev_dbg(ucsi->dev, "Bogus connector change event\n");
++ dev_dbg(ucsi->dev, "Early connector change event\n");
+ return;
+ }
+
+@@ -1406,6 +1406,7 @@ static int ucsi_init(struct ucsi *ucsi)
+ {
+ struct ucsi_connector *con, *connector;
+ u64 command, ntfy;
++ u32 cci;
+ int ret;
+ int i;
+
+@@ -1458,6 +1459,15 @@ static int ucsi_init(struct ucsi *ucsi)
+
+ ucsi->connector = connector;
+ ucsi->ntfy = ntfy;
++
++ mutex_lock(&ucsi->ppm_lock);
++ ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci));
++ mutex_unlock(&ucsi->ppm_lock);
++ if (ret)
++ return ret;
++ if (UCSI_CCI_CONNECTOR(cci))
++ ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci));
++
+ return 0;
+
+ err_unregister:
+diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
+index cb5b7f865d585..e727941f589de 100644
+--- a/drivers/vfio/pci/vfio_pci.c
++++ b/drivers/vfio/pci/vfio_pci.c
+@@ -71,6 +71,8 @@ static bool vfio_pci_dev_in_denylist(struct pci_dev *pdev)
+ case PCI_DEVICE_ID_INTEL_QAT_C62X_VF:
+ case PCI_DEVICE_ID_INTEL_QAT_DH895XCC:
+ case PCI_DEVICE_ID_INTEL_QAT_DH895XCC_VF:
++ case PCI_DEVICE_ID_INTEL_DSA_SPR0:
++ case PCI_DEVICE_ID_INTEL_IAX_SPR0:
+ return true;
+ default:
+ return false;
+diff --git a/fs/9p/fid.h b/fs/9p/fid.h
+index 29281b7c38870..0d6138bee2a3d 100644
+--- a/fs/9p/fid.h
++++ b/fs/9p/fid.h
+@@ -49,9 +49,6 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
+ static inline void v9fs_fid_add_modes(struct p9_fid *fid, unsigned int s_flags,
+ unsigned int s_cache, unsigned int f_flags)
+ {
+- if (fid->qid.type != P9_QTFILE)
+- return;
+-
+ if ((!s_cache) ||
+ ((fid->qid.version == 0) && !(s_flags & V9FS_IGNORE_QV)) ||
+ (s_flags & V9FS_DIRECT_IO) || (f_flags & O_DIRECT)) {
+diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c
+index bae330c2f0cf0..a504240c818c8 100644
+--- a/fs/9p/vfs_file.c
++++ b/fs/9p/vfs_file.c
+@@ -520,6 +520,7 @@ const struct file_operations v9fs_file_operations = {
+ .splice_read = v9fs_file_splice_read,
+ .splice_write = iter_file_splice_write,
+ .fsync = v9fs_file_fsync,
++ .setlease = simple_nosetlease,
+ };
+
+ const struct file_operations v9fs_file_operations_dotl = {
+@@ -534,4 +535,5 @@ const struct file_operations v9fs_file_operations_dotl = {
+ .splice_read = v9fs_file_splice_read,
+ .splice_write = iter_file_splice_write,
+ .fsync = v9fs_file_fsync_dotl,
++ .setlease = simple_nosetlease,
+ };
+diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
+index 32572982f72e6..0fde0ab77eff6 100644
+--- a/fs/9p/vfs_inode.c
++++ b/fs/9p/vfs_inode.c
+@@ -83,7 +83,7 @@ static int p9mode2perm(struct v9fs_session_info *v9ses,
+ int res;
+ int mode = stat->mode;
+
+- res = mode & S_IALLUGO;
++ res = mode & 0777; /* S_IRWXUGO */
+ if (v9fs_proto_dotu(v9ses)) {
+ if ((mode & P9_DMSETUID) == P9_DMSETUID)
+ res |= S_ISUID;
+@@ -178,6 +178,9 @@ int v9fs_uflags2omode(int uflags, int extended)
+ break;
+ }
+
++ if (uflags & O_TRUNC)
++ ret |= P9_OTRUNC;
++
+ if (extended) {
+ if (uflags & O_EXCL)
+ ret |= P9_OEXCL;
+@@ -371,17 +374,21 @@ void v9fs_evict_inode(struct inode *inode)
+ struct v9fs_inode __maybe_unused *v9inode = V9FS_I(inode);
+ __le32 __maybe_unused version;
+
+- truncate_inode_pages_final(&inode->i_data);
++ if (!is_bad_inode(inode)) {
++ truncate_inode_pages_final(&inode->i_data);
+
+- version = cpu_to_le32(v9inode->qid.version);
+- netfs_clear_inode_writeback(inode, &version);
++ version = cpu_to_le32(v9inode->qid.version);
++ netfs_clear_inode_writeback(inode, &version);
+
+- clear_inode(inode);
+- filemap_fdatawrite(&inode->i_data);
++ clear_inode(inode);
++ filemap_fdatawrite(&inode->i_data);
+
+ #ifdef CONFIG_9P_FSCACHE
+- fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
++ if (v9fs_inode_cookie(v9inode))
++ fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false);
+ #endif
++ } else
++ clear_inode(inode);
+ }
+
+ static int v9fs_test_inode(struct inode *inode, void *data)
+@@ -1145,8 +1152,6 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode,
+ struct v9fs_session_info *v9ses = sb->s_fs_info;
+ struct v9fs_inode *v9inode = V9FS_I(inode);
+
+- set_nlink(inode, 1);
+-
+ inode_set_atime(inode, stat->atime, 0);
+ inode_set_mtime(inode, stat->mtime, 0);
+ inode_set_ctime(inode, stat->mtime, 0);
+diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c
+index 941f7d0e0bfa2..23cc67f29af20 100644
+--- a/fs/9p/vfs_super.c
++++ b/fs/9p/vfs_super.c
+@@ -310,6 +310,7 @@ static const struct super_operations v9fs_super_ops = {
+ .alloc_inode = v9fs_alloc_inode,
+ .free_inode = v9fs_free_inode,
+ .statfs = simple_statfs,
++ .drop_inode = v9fs_drop_inode,
+ .evict_inode = v9fs_evict_inode,
+ .show_options = v9fs_show_options,
+ .umount_begin = v9fs_umount_begin,
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index b28bb1c93dcb5..d3c534c1bfb59 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -2522,7 +2522,7 @@ void btrfs_clear_delalloc_extent(struct btrfs_inode *inode,
+ */
+ if (bits & EXTENT_CLEAR_META_RESV &&
+ root != fs_info->tree_root)
+- btrfs_delalloc_release_metadata(inode, len, false);
++ btrfs_delalloc_release_metadata(inode, len, true);
+
+ /* For sanity tests. */
+ if (btrfs_is_testing(fs_info))
+diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
+index 59850dc17b22f..81f67ebf7426e 100644
+--- a/fs/btrfs/ordered-data.c
++++ b/fs/btrfs/ordered-data.c
+@@ -1189,6 +1189,7 @@ struct btrfs_ordered_extent *btrfs_split_ordered_extent(
+ ordered->disk_bytenr += len;
+ ordered->num_bytes -= len;
+ ordered->disk_num_bytes -= len;
++ ordered->ram_bytes -= len;
+
+ if (test_bit(BTRFS_ORDERED_IO_DONE, &ordered->flags)) {
+ ASSERT(ordered->bytes_left == 0);
+diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
+index 132802bd80999..82d4559eb4b1e 100644
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -3052,6 +3052,8 @@ int btrfs_qgroup_check_inherit(struct btrfs_fs_info *fs_info,
+ struct btrfs_qgroup_inherit *inherit,
+ size_t size)
+ {
++ if (!btrfs_qgroup_enabled(fs_info))
++ return 0;
+ if (inherit->flags & ~BTRFS_QGROUP_INHERIT_FLAGS_SUPP)
+ return -EOPNOTSUPP;
+ if (size < sizeof(*inherit) || size > PAGE_SIZE)
+diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
+index f1705ae59e4a9..b93cdf5f179cf 100644
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -1496,6 +1496,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)
+ radix_tree_tag_clear(&fs_info->fs_roots_radix,
+ (unsigned long)root->root_key.objectid,
+ BTRFS_ROOT_TRANS_TAG);
++ btrfs_qgroup_free_meta_all_pertrans(root);
+ spin_unlock(&fs_info->fs_roots_radix_lock);
+
+ btrfs_free_log(trans, root);
+@@ -1520,7 +1521,6 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans)
+ if (ret2)
+ return ret2;
+ spin_lock(&fs_info->fs_roots_radix_lock);
+- btrfs_qgroup_free_meta_all_pertrans(root);
+ }
+ }
+ spin_unlock(&fs_info->fs_roots_radix_lock);
+diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
+index 6eccf8496486c..75c78a5556c5b 100644
+--- a/fs/btrfs/tree-checker.c
++++ b/fs/btrfs/tree-checker.c
+@@ -1793,6 +1793,11 @@ enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf)
+ return BTRFS_TREE_BLOCK_INVALID_LEVEL;
+ }
+
++ if (unlikely(!btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_WRITTEN))) {
++ generic_err(leaf, 0, "invalid flag for leaf, WRITTEN not set");
++ return BTRFS_TREE_BLOCK_WRITTEN_NOT_SET;
++ }
++
+ /*
+ * Extent buffers from a relocation tree have a owner field that
+ * corresponds to the subvolume tree they are based on. So just from an
+@@ -1854,6 +1859,7 @@ enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf)
+ for (slot = 0; slot < nritems; slot++) {
+ u32 item_end_expected;
+ u64 item_data_end;
++ enum btrfs_tree_block_status ret;
+
+ btrfs_item_key_to_cpu(leaf, &key, slot);
+
+@@ -1909,21 +1915,10 @@ enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf)
+ return BTRFS_TREE_BLOCK_INVALID_OFFSETS;
+ }
+
+- /*
+- * We only want to do this if WRITTEN is set, otherwise the leaf
+- * may be in some intermediate state and won't appear valid.
+- */
+- if (btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_WRITTEN)) {
+- enum btrfs_tree_block_status ret;
+-
+- /*
+- * Check if the item size and content meet other
+- * criteria
+- */
+- ret = check_leaf_item(leaf, &key, slot, &prev_key);
+- if (unlikely(ret != BTRFS_TREE_BLOCK_CLEAN))
+- return ret;
+- }
++ /* Check if the item size and content meet other criteria. */
++ ret = check_leaf_item(leaf, &key, slot, &prev_key);
++ if (unlikely(ret != BTRFS_TREE_BLOCK_CLEAN))
++ return ret;
+
+ prev_key.objectid = key.objectid;
+ prev_key.type = key.type;
+@@ -1953,6 +1948,11 @@ enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node)
+ int level = btrfs_header_level(node);
+ u64 bytenr;
+
++ if (unlikely(!btrfs_header_flag(node, BTRFS_HEADER_FLAG_WRITTEN))) {
++ generic_err(node, 0, "invalid flag for node, WRITTEN not set");
++ return BTRFS_TREE_BLOCK_WRITTEN_NOT_SET;
++ }
++
+ if (unlikely(level <= 0 || level >= BTRFS_MAX_LEVEL)) {
+ generic_err(node, 0,
+ "invalid level for node, have %d expect [1, %d]",
+diff --git a/fs/btrfs/tree-checker.h b/fs/btrfs/tree-checker.h
+index 14b9fbe82da47..580ec4fde01a3 100644
+--- a/fs/btrfs/tree-checker.h
++++ b/fs/btrfs/tree-checker.h
+@@ -51,6 +51,7 @@ enum btrfs_tree_block_status {
+ BTRFS_TREE_BLOCK_INVALID_BLOCKPTR,
+ BTRFS_TREE_BLOCK_INVALID_ITEM,
+ BTRFS_TREE_BLOCK_INVALID_OWNER,
++ BTRFS_TREE_BLOCK_WRITTEN_NOT_SET,
+ };
+
+ /*
+diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
+index f3890f7c78076..3ebadc5ec8aeb 100644
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -1182,23 +1182,30 @@ static int open_fs_devices(struct btrfs_fs_devices *fs_devices,
+ struct btrfs_device *device;
+ struct btrfs_device *latest_dev = NULL;
+ struct btrfs_device *tmp_device;
++ int ret = 0;
+
+ list_for_each_entry_safe(device, tmp_device, &fs_devices->devices,
+ dev_list) {
+- int ret;
++ int ret2;
+
+- ret = btrfs_open_one_device(fs_devices, device, flags, holder);
+- if (ret == 0 &&
++ ret2 = btrfs_open_one_device(fs_devices, device, flags, holder);
++ if (ret2 == 0 &&
+ (!latest_dev || device->generation > latest_dev->generation)) {
+ latest_dev = device;
+- } else if (ret == -ENODATA) {
++ } else if (ret2 == -ENODATA) {
+ fs_devices->num_devices--;
+ list_del(&device->dev_list);
+ btrfs_free_device(device);
+ }
++ if (ret == 0 && ret2 != 0)
++ ret = ret2;
+ }
+- if (fs_devices->open_devices == 0)
++
++ if (fs_devices->open_devices == 0) {
++ if (ret)
++ return ret;
+ return -EINVAL;
++ }
+
+ fs_devices->opened = 1;
+ fs_devices->latest_dev = latest_dev;
+@@ -3449,6 +3456,7 @@ static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info)
+ * alignment and size).
+ */
+ ret = -EUCLEAN;
++ mutex_unlock(&fs_info->reclaim_bgs_lock);
+ goto error;
+ }
+
+diff --git a/fs/exfat/file.c b/fs/exfat/file.c
+index cc00f1a7a1e18..9adfc38ca7dac 100644
+--- a/fs/exfat/file.c
++++ b/fs/exfat/file.c
+@@ -51,7 +51,7 @@ static int exfat_cont_expand(struct inode *inode, loff_t size)
+ clu.flags = ei->flags;
+
+ ret = exfat_alloc_cluster(inode, new_num_clusters - num_clusters,
+- &clu, IS_DIRSYNC(inode));
++ &clu, inode_needs_sync(inode));
+ if (ret)
+ return ret;
+
+@@ -77,12 +77,11 @@ static int exfat_cont_expand(struct inode *inode, loff_t size)
+ ei->i_size_aligned = round_up(size, sb->s_blocksize);
+ ei->i_size_ondisk = ei->i_size_aligned;
+ inode->i_blocks = round_up(size, sbi->cluster_size) >> 9;
++ mark_inode_dirty(inode);
+
+- if (IS_DIRSYNC(inode))
++ if (IS_SYNC(inode))
+ return write_inode_now(inode, 1);
+
+- mark_inode_dirty(inode);
+-
+ return 0;
+
+ free_clu:
+diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
+index d9ccfd27e4f11..643175498d1c3 100644
+--- a/fs/gfs2/bmap.c
++++ b/fs/gfs2/bmap.c
+@@ -1718,7 +1718,8 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
+ struct buffer_head *dibh, *bh;
+ struct gfs2_holder rd_gh;
+ unsigned int bsize_shift = sdp->sd_sb.sb_bsize_shift;
+- u64 lblock = (offset + (1 << bsize_shift) - 1) >> bsize_shift;
++ unsigned int bsize = 1 << bsize_shift;
++ u64 lblock = (offset + bsize - 1) >> bsize_shift;
+ __u16 start_list[GFS2_MAX_META_HEIGHT];
+ __u16 __end_list[GFS2_MAX_META_HEIGHT], *end_list = NULL;
+ unsigned int start_aligned, end_aligned;
+@@ -1729,7 +1730,7 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length)
+ u64 prev_bnr = 0;
+ __be64 *start, *end;
+
+- if (offset >= maxsize) {
++ if (offset + bsize - 1 >= maxsize) {
+ /*
+ * The starting point lies beyond the allocated metadata;
+ * there are no blocks to deallocate.
+diff --git a/fs/nfs/client.c b/fs/nfs/client.c
+index fbdc9ca80f714..a8fad331dff6b 100644
+--- a/fs/nfs/client.c
++++ b/fs/nfs/client.c
+@@ -73,7 +73,6 @@ const struct rpc_program nfs_program = {
+ .number = NFS_PROGRAM,
+ .nrvers = ARRAY_SIZE(nfs_version),
+ .version = nfs_version,
+- .stats = &nfs_rpcstat,
+ .pipe_dir_name = NFS_PIPE_DIRNAME,
+ };
+
+@@ -502,6 +501,7 @@ int nfs_create_rpc_client(struct nfs_client *clp,
+ const struct nfs_client_initdata *cl_init,
+ rpc_authflavor_t flavor)
+ {
++ struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
+ struct rpc_clnt *clnt = NULL;
+ struct rpc_create_args args = {
+ .net = clp->cl_net,
+@@ -513,6 +513,7 @@ int nfs_create_rpc_client(struct nfs_client *clp,
+ .servername = clp->cl_hostname,
+ .nodename = cl_init->nodename,
+ .program = &nfs_program,
++ .stats = &nn->rpcstats,
+ .version = clp->rpc_ops->version,
+ .authflavor = flavor,
+ .cred = cl_init->cred,
+@@ -1182,6 +1183,8 @@ void nfs_clients_init(struct net *net)
+ #endif
+ spin_lock_init(&nn->nfs_client_lock);
+ nn->boot_time = ktime_get_real();
++ memset(&nn->rpcstats, 0, sizeof(nn->rpcstats));
++ nn->rpcstats.program = &nfs_program;
+
+ nfs_netns_sysfs_setup(nn, net);
+ }
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index ebb8d60e11526..6fe4b47c39287 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -2426,12 +2426,21 @@ EXPORT_SYMBOL_GPL(nfs_net_id);
+
+ static int nfs_net_init(struct net *net)
+ {
++ struct nfs_net *nn = net_generic(net, nfs_net_id);
++
+ nfs_clients_init(net);
++
++ if (!rpc_proc_register(net, &nn->rpcstats)) {
++ nfs_clients_exit(net);
++ return -ENOMEM;
++ }
++
+ return nfs_fs_proc_net_init(net);
+ }
+
+ static void nfs_net_exit(struct net *net)
+ {
++ rpc_proc_unregister(net, "nfs");
+ nfs_fs_proc_net_exit(net);
+ nfs_clients_exit(net);
+ }
+@@ -2486,15 +2495,12 @@ static int __init init_nfs_fs(void)
+ if (err)
+ goto out1;
+
+- rpc_proc_register(&init_net, &nfs_rpcstat);
+-
+ err = register_nfs_fs();
+ if (err)
+ goto out0;
+
+ return 0;
+ out0:
+- rpc_proc_unregister(&init_net, "nfs");
+ nfs_destroy_directcache();
+ out1:
+ nfs_destroy_writepagecache();
+@@ -2524,7 +2530,6 @@ static void __exit exit_nfs_fs(void)
+ nfs_destroy_inodecache();
+ nfs_destroy_nfspagecache();
+ unregister_pernet_subsys(&nfs_net_ops);
+- rpc_proc_unregister(&init_net, "nfs");
+ unregister_nfs_fs();
+ nfs_fs_proc_exit();
+ nfsiod_stop();
+diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
+index e3722ce6722e2..06253695fe53f 100644
+--- a/fs/nfs/internal.h
++++ b/fs/nfs/internal.h
+@@ -449,8 +449,6 @@ int nfs_try_get_tree(struct fs_context *);
+ int nfs_get_tree_common(struct fs_context *);
+ void nfs_kill_super(struct super_block *);
+
+-extern struct rpc_stat nfs_rpcstat;
+-
+ extern int __init register_nfs_fs(void);
+ extern void __exit unregister_nfs_fs(void);
+ extern bool nfs_sb_active(struct super_block *sb);
+diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h
+index c8374f74dce11..a68b21603ea9a 100644
+--- a/fs/nfs/netns.h
++++ b/fs/nfs/netns.h
+@@ -9,6 +9,7 @@
+ #include <linux/nfs4.h>
+ #include <net/net_namespace.h>
+ #include <net/netns/generic.h>
++#include <linux/sunrpc/stats.h>
+
+ struct bl_dev_msg {
+ int32_t status;
+@@ -34,6 +35,7 @@ struct nfs_net {
+ struct nfs_netns_client *nfs_client;
+ spinlock_t nfs_client_lock;
+ ktime_t boot_time;
++ struct rpc_stat rpcstats;
+ #ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *proc_nfsfs;
+ #endif
+diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h
+index 4cbe0434cbb8c..66a05fefae98e 100644
+--- a/fs/nfsd/cache.h
++++ b/fs/nfsd/cache.h
+@@ -80,8 +80,6 @@ enum {
+
+ int nfsd_drc_slab_create(void);
+ void nfsd_drc_slab_free(void);
+-int nfsd_net_reply_cache_init(struct nfsd_net *nn);
+-void nfsd_net_reply_cache_destroy(struct nfsd_net *nn);
+ int nfsd_reply_cache_init(struct nfsd_net *);
+ void nfsd_reply_cache_shutdown(struct nfsd_net *);
+ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start,
+diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
+index 74b4360779a11..0cef4bb407a9c 100644
+--- a/fs/nfsd/netns.h
++++ b/fs/nfsd/netns.h
+@@ -11,6 +11,7 @@
+ #include <net/net_namespace.h>
+ #include <net/netns/generic.h>
+ #include <linux/filelock.h>
++#include <linux/nfs4.h>
+ #include <linux/percpu_counter.h>
+ #include <linux/siphash.h>
+
+@@ -26,10 +27,22 @@ struct nfsd4_client_tracking_ops;
+
+ enum {
+ /* cache misses due only to checksum comparison failures */
+- NFSD_NET_PAYLOAD_MISSES,
++ NFSD_STATS_PAYLOAD_MISSES,
+ /* amount of memory (in bytes) currently consumed by the DRC */
+- NFSD_NET_DRC_MEM_USAGE,
+- NFSD_NET_COUNTERS_NUM
++ NFSD_STATS_DRC_MEM_USAGE,
++ NFSD_STATS_RC_HITS, /* repcache hits */
++ NFSD_STATS_RC_MISSES, /* repcache misses */
++ NFSD_STATS_RC_NOCACHE, /* uncached reqs */
++ NFSD_STATS_FH_STALE, /* FH stale error */
++ NFSD_STATS_IO_READ, /* bytes returned to read requests */
++ NFSD_STATS_IO_WRITE, /* bytes passed in write requests */
++#ifdef CONFIG_NFSD_V4
++ NFSD_STATS_FIRST_NFS4_OP, /* count of individual nfsv4 operations */
++ NFSD_STATS_LAST_NFS4_OP = NFSD_STATS_FIRST_NFS4_OP + LAST_NFS4_OP,
++#define NFSD_STATS_NFS4_OP(op) (NFSD_STATS_FIRST_NFS4_OP + (op))
++ NFSD_STATS_WDELEG_GETATTR, /* count of getattr conflict with wdeleg */
++#endif
++ NFSD_STATS_COUNTERS_NUM
+ };
+
+ /*
+@@ -164,7 +177,7 @@ struct nfsd_net {
+ atomic_t num_drc_entries;
+
+ /* Per-netns stats counters */
+- struct percpu_counter counter[NFSD_NET_COUNTERS_NUM];
++ struct percpu_counter counter[NFSD_STATS_COUNTERS_NUM];
+
+ /* longest hash chain seen */
+ unsigned int longest_chain;
+diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
+index 926c29879c6ab..30aa241038eb4 100644
+--- a/fs/nfsd/nfs4callback.c
++++ b/fs/nfsd/nfs4callback.c
+@@ -85,7 +85,21 @@ static void encode_uint32(struct xdr_stream *xdr, u32 n)
+ static void encode_bitmap4(struct xdr_stream *xdr, const __u32 *bitmap,
+ size_t len)
+ {
+- WARN_ON_ONCE(xdr_stream_encode_uint32_array(xdr, bitmap, len) < 0);
++ xdr_stream_encode_uint32_array(xdr, bitmap, len);
++}
++
++static int decode_cb_fattr4(struct xdr_stream *xdr, uint32_t *bitmap,
++ struct nfs4_cb_fattr *fattr)
++{
++ fattr->ncf_cb_change = 0;
++ fattr->ncf_cb_fsize = 0;
++ if (bitmap[0] & FATTR4_WORD0_CHANGE)
++ if (xdr_stream_decode_u64(xdr, &fattr->ncf_cb_change) < 0)
++ return -NFSERR_BAD_XDR;
++ if (bitmap[0] & FATTR4_WORD0_SIZE)
++ if (xdr_stream_decode_u64(xdr, &fattr->ncf_cb_fsize) < 0)
++ return -NFSERR_BAD_XDR;
++ return 0;
+ }
+
+ static void encode_nfs_cb_opnum4(struct xdr_stream *xdr, enum nfs_cb_opnum4 op)
+@@ -333,6 +347,30 @@ encode_cb_recallany4args(struct xdr_stream *xdr,
+ hdr->nops++;
+ }
+
++/*
++ * CB_GETATTR4args
++ * struct CB_GETATTR4args {
++ * nfs_fh4 fh;
++ * bitmap4 attr_request;
++ * };
++ *
++ * The size and change attributes are the only one
++ * guaranteed to be serviced by the client.
++ */
++static void
++encode_cb_getattr4args(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr,
++ struct nfs4_cb_fattr *fattr)
++{
++ struct nfs4_delegation *dp =
++ container_of(fattr, struct nfs4_delegation, dl_cb_fattr);
++ struct knfsd_fh *fh = &dp->dl_stid.sc_file->fi_fhandle;
++
++ encode_nfs_cb_opnum4(xdr, OP_CB_GETATTR);
++ encode_nfs_fh4(xdr, fh);
++ encode_bitmap4(xdr, fattr->ncf_cb_bmap, ARRAY_SIZE(fattr->ncf_cb_bmap));
++ hdr->nops++;
++}
++
+ /*
+ * CB_SEQUENCE4args
+ *
+@@ -468,6 +506,26 @@ static void nfs4_xdr_enc_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr,
+ xdr_reserve_space(xdr, 0);
+ }
+
++/*
++ * 20.1. Operation 3: CB_GETATTR - Get Attributes
++ */
++static void nfs4_xdr_enc_cb_getattr(struct rpc_rqst *req,
++ struct xdr_stream *xdr, const void *data)
++{
++ const struct nfsd4_callback *cb = data;
++ struct nfs4_cb_fattr *ncf =
++ container_of(cb, struct nfs4_cb_fattr, ncf_getattr);
++ struct nfs4_cb_compound_hdr hdr = {
++ .ident = cb->cb_clp->cl_cb_ident,
++ .minorversion = cb->cb_clp->cl_minorversion,
++ };
++
++ encode_cb_compound4args(xdr, &hdr);
++ encode_cb_sequence4args(xdr, cb, &hdr);
++ encode_cb_getattr4args(xdr, &hdr, ncf);
++ encode_cb_nops(&hdr);
++}
++
+ /*
+ * 20.2. Operation 4: CB_RECALL - Recall a Delegation
+ */
+@@ -523,6 +581,42 @@ static int nfs4_xdr_dec_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr,
+ return 0;
+ }
+
++/*
++ * 20.1. Operation 3: CB_GETATTR - Get Attributes
++ */
++static int nfs4_xdr_dec_cb_getattr(struct rpc_rqst *rqstp,
++ struct xdr_stream *xdr,
++ void *data)
++{
++ struct nfsd4_callback *cb = data;
++ struct nfs4_cb_compound_hdr hdr;
++ int status;
++ u32 bitmap[3] = {0};
++ u32 attrlen;
++ struct nfs4_cb_fattr *ncf =
++ container_of(cb, struct nfs4_cb_fattr, ncf_getattr);
++
++ status = decode_cb_compound4res(xdr, &hdr);
++ if (unlikely(status))
++ return status;
++
++ status = decode_cb_sequence4res(xdr, cb);
++ if (unlikely(status || cb->cb_seq_status))
++ return status;
++
++ status = decode_cb_op_status(xdr, OP_CB_GETATTR, &cb->cb_status);
++ if (status)
++ return status;
++ if (xdr_stream_decode_uint32_array(xdr, bitmap, 3) < 0)
++ return -NFSERR_BAD_XDR;
++ if (xdr_stream_decode_u32(xdr, &attrlen) < 0)
++ return -NFSERR_BAD_XDR;
++ if (attrlen > (sizeof(ncf->ncf_cb_change) + sizeof(ncf->ncf_cb_fsize)))
++ return -NFSERR_BAD_XDR;
++ status = decode_cb_fattr4(xdr, bitmap, ncf);
++ return status;
++}
++
+ /*
+ * 20.2. Operation 4: CB_RECALL - Recall a Delegation
+ */
+@@ -831,6 +925,7 @@ static const struct rpc_procinfo nfs4_cb_procedures[] = {
+ PROC(CB_NOTIFY_LOCK, COMPOUND, cb_notify_lock, cb_notify_lock),
+ PROC(CB_OFFLOAD, COMPOUND, cb_offload, cb_offload),
+ PROC(CB_RECALL_ANY, COMPOUND, cb_recall_any, cb_recall_any),
++ PROC(CB_GETATTR, COMPOUND, cb_getattr, cb_getattr),
+ };
+
+ static unsigned int nfs4_cb_counts[ARRAY_SIZE(nfs4_cb_procedures)];
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index 14712fa08f769..648ff427005e6 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -2490,10 +2490,10 @@ nfsd4_proc_null(struct svc_rqst *rqstp)
+ return rpc_success;
+ }
+
+-static inline void nfsd4_increment_op_stats(u32 opnum)
++static inline void nfsd4_increment_op_stats(struct nfsd_net *nn, u32 opnum)
+ {
+ if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP)
+- percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_NFS4_OP(opnum)]);
++ percpu_counter_inc(&nn->counter[NFSD_STATS_NFS4_OP(opnum)]);
+ }
+
+ static const struct nfsd4_operation nfsd4_ops[];
+@@ -2768,7 +2768,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
+ status, nfsd4_op_name(op->opnum));
+
+ nfsd4_cstate_clear_replay(cstate);
+- nfsd4_increment_op_stats(op->opnum);
++ nfsd4_increment_op_stats(nn, op->opnum);
+ }
+
+ fh_put(current_fh);
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 692ede488254a..71f9442c5c9fc 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -8447,6 +8447,7 @@ __be32
+ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode)
+ {
+ __be32 status;
++ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+ struct file_lock_context *ctx;
+ struct file_lock *fl;
+ struct nfs4_delegation *dp;
+@@ -8476,7 +8477,7 @@ nfsd4_deleg_getattr_conflict(struct svc_rqst *rqstp, struct inode *inode)
+ }
+ break_lease:
+ spin_unlock(&ctx->flc_lock);
+- nfsd_stats_wdeleg_getattr_inc();
++ nfsd_stats_wdeleg_getattr_inc(nn);
+ status = nfserrno(nfsd_open_break_lease(inode, NFSD_MAY_READ));
+ if (status != nfserr_jukebox ||
+ !nfsd_wait_for_delegreturn(rqstp, inode))
+diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
+index c17bdf973c18d..24db9f9ea86a2 100644
+--- a/fs/nfsd/nfs4xdr.c
++++ b/fs/nfsd/nfs4xdr.c
+@@ -3513,6 +3513,7 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+ args.exp = exp;
+ args.dentry = dentry;
+ args.ignore_crossmnt = (ignore_crossmnt != 0);
++ args.acl = NULL;
+
+ /*
+ * Make a local copy of the attribute bitmap that can be modified.
+@@ -3567,7 +3568,6 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr,
+ } else
+ args.fhp = fhp;
+
+- args.acl = NULL;
+ if (attrmask[0] & FATTR4_WORD0_ACL) {
+ err = nfsd4_get_nfs4_acl(rqstp, dentry, &args.acl);
+ if (err == -EOPNOTSUPP)
+diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
+index 5c1a4a0aa6056..cfcc6ac8f255a 100644
+--- a/fs/nfsd/nfscache.c
++++ b/fs/nfsd/nfscache.c
+@@ -176,27 +176,6 @@ void nfsd_drc_slab_free(void)
+ kmem_cache_destroy(drc_slab);
+ }
+
+-/**
+- * nfsd_net_reply_cache_init - per net namespace reply cache set-up
+- * @nn: nfsd_net being initialized
+- *
+- * Returns zero on succes; otherwise a negative errno is returned.
+- */
+-int nfsd_net_reply_cache_init(struct nfsd_net *nn)
+-{
+- return nfsd_percpu_counters_init(nn->counter, NFSD_NET_COUNTERS_NUM);
+-}
+-
+-/**
+- * nfsd_net_reply_cache_destroy - per net namespace reply cache tear-down
+- * @nn: nfsd_net being freed
+- *
+- */
+-void nfsd_net_reply_cache_destroy(struct nfsd_net *nn)
+-{
+- nfsd_percpu_counters_destroy(nn->counter, NFSD_NET_COUNTERS_NUM);
+-}
+-
+ int nfsd_reply_cache_init(struct nfsd_net *nn)
+ {
+ unsigned int hashsize;
+@@ -501,7 +480,7 @@ nfsd_cache_insert(struct nfsd_drc_bucket *b, struct nfsd_cacherep *key,
+ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start,
+ unsigned int len, struct nfsd_cacherep **cacherep)
+ {
+- struct nfsd_net *nn;
++ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+ struct nfsd_cacherep *rp, *found;
+ __wsum csum;
+ struct nfsd_drc_bucket *b;
+@@ -510,7 +489,7 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start,
+ int rtn = RC_DOIT;
+
+ if (type == RC_NOCACHE) {
+- nfsd_stats_rc_nocache_inc();
++ nfsd_stats_rc_nocache_inc(nn);
+ goto out;
+ }
+
+@@ -520,7 +499,6 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start,
+ * Since the common case is a cache miss followed by an insert,
+ * preallocate an entry.
+ */
+- nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+ rp = nfsd_cacherep_alloc(rqstp, csum, nn);
+ if (!rp)
+ goto out;
+@@ -537,7 +515,7 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start,
+
+ nfsd_cacherep_dispose(&dispose);
+
+- nfsd_stats_rc_misses_inc();
++ nfsd_stats_rc_misses_inc(nn);
+ atomic_inc(&nn->num_drc_entries);
+ nfsd_stats_drc_mem_usage_add(nn, sizeof(*rp));
+ goto out;
+@@ -545,7 +523,7 @@ int nfsd_cache_lookup(struct svc_rqst *rqstp, unsigned int start,
+ found_entry:
+ /* We found a matching entry which is either in progress or done. */
+ nfsd_reply_cache_free_locked(NULL, rp, nn);
+- nfsd_stats_rc_hits_inc();
++ nfsd_stats_rc_hits_inc(nn);
+ rtn = RC_DROPIT;
+ rp = found;
+
+@@ -687,15 +665,15 @@ int nfsd_reply_cache_stats_show(struct seq_file *m, void *v)
+ atomic_read(&nn->num_drc_entries));
+ seq_printf(m, "hash buckets: %u\n", 1 << nn->maskbits);
+ seq_printf(m, "mem usage: %lld\n",
+- percpu_counter_sum_positive(&nn->counter[NFSD_NET_DRC_MEM_USAGE]));
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_DRC_MEM_USAGE]));
+ seq_printf(m, "cache hits: %lld\n",
+- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_HITS]));
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_HITS]));
+ seq_printf(m, "cache misses: %lld\n",
+- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_MISSES]));
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_MISSES]));
+ seq_printf(m, "not cached: %lld\n",
+- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_NOCACHE]));
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_NOCACHE]));
+ seq_printf(m, "payload misses: %lld\n",
+- percpu_counter_sum_positive(&nn->counter[NFSD_NET_PAYLOAD_MISSES]));
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_PAYLOAD_MISSES]));
+ seq_printf(m, "longest chain len: %u\n", nn->longest_chain);
+ seq_printf(m, "cachesize at longest: %u\n", nn->longest_chain_cachesize);
+ return 0;
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index f206ca32e7f53..ea3c8114245c2 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -1671,7 +1671,7 @@ static __net_init int nfsd_net_init(struct net *net)
+ retval = nfsd_idmap_init(net);
+ if (retval)
+ goto out_idmap_error;
+- retval = nfsd_net_reply_cache_init(nn);
++ retval = nfsd_stat_counters_init(nn);
+ if (retval)
+ goto out_repcache_error;
+ nn->nfsd_versions = NULL;
+@@ -1679,6 +1679,7 @@ static __net_init int nfsd_net_init(struct net *net)
+ nfsd4_init_leases_net(nn);
+ get_random_bytes(&nn->siphash_key, sizeof(nn->siphash_key));
+ seqlock_init(&nn->writeverf_lock);
++ nfsd_proc_stat_init(net);
+
+ return 0;
+
+@@ -1699,7 +1700,8 @@ static __net_exit void nfsd_net_exit(struct net *net)
+ {
+ struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+
+- nfsd_net_reply_cache_destroy(nn);
++ nfsd_proc_stat_shutdown(net);
++ nfsd_stat_counters_destroy(nn);
+ nfsd_idmap_shutdown(net);
+ nfsd_export_shutdown(net);
+ nfsd_netns_free_versions(nn);
+@@ -1722,12 +1724,9 @@ static int __init init_nfsd(void)
+ retval = nfsd4_init_pnfs();
+ if (retval)
+ goto out_free_slabs;
+- retval = nfsd_stat_init(); /* Statistics */
+- if (retval)
+- goto out_free_pnfs;
+ retval = nfsd_drc_slab_create();
+ if (retval)
+- goto out_free_stat;
++ goto out_free_pnfs;
+ nfsd_lockd_init(); /* lockd->nfsd callbacks */
+ retval = create_proc_exports_entry();
+ if (retval)
+@@ -1761,8 +1760,6 @@ static int __init init_nfsd(void)
+ out_free_lockd:
+ nfsd_lockd_shutdown();
+ nfsd_drc_slab_free();
+-out_free_stat:
+- nfsd_stat_shutdown();
+ out_free_pnfs:
+ nfsd4_exit_pnfs();
+ out_free_slabs:
+@@ -1780,7 +1777,6 @@ static void __exit exit_nfsd(void)
+ nfsd_drc_slab_free();
+ remove_proc_entry("fs/nfs/exports", NULL);
+ remove_proc_entry("fs/nfs", NULL);
+- nfsd_stat_shutdown();
+ nfsd_lockd_shutdown();
+ nfsd4_free_slabs();
+ nfsd4_exit_pnfs();
+diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
+index dbfa0ac13564a..40fecf7b224f2 100644
+--- a/fs/nfsd/nfsfh.c
++++ b/fs/nfsd/nfsfh.c
+@@ -327,6 +327,7 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
+ __be32
+ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
+ {
++ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+ struct svc_export *exp = NULL;
+ struct dentry *dentry;
+ __be32 error;
+@@ -395,7 +396,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)
+ out:
+ trace_nfsd_fh_verify_err(rqstp, fhp, type, access, error);
+ if (error == nfserr_stale)
+- nfsd_stats_fh_stale_inc(exp);
++ nfsd_stats_fh_stale_inc(nn, exp);
+ return error;
+ }
+
+diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
+index 41bdc913fa715..0bbbe57e027d3 100644
+--- a/fs/nfsd/state.h
++++ b/fs/nfsd/state.h
+@@ -117,6 +117,16 @@ struct nfs4_cpntf_state {
+ time64_t cpntf_time; /* last time stateid used */
+ };
+
++struct nfs4_cb_fattr {
++ struct nfsd4_callback ncf_getattr;
++ u32 ncf_cb_status;
++ u32 ncf_cb_bmap[1];
++
++ /* from CB_GETATTR reply */
++ u64 ncf_cb_change;
++ u64 ncf_cb_fsize;
++};
++
+ /*
+ * Represents a delegation stateid. The nfs4_client holds references to these
+ * and they are put when it is being destroyed or when the delegation is
+@@ -150,6 +160,9 @@ struct nfs4_delegation {
+ int dl_retries;
+ struct nfsd4_callback dl_recall;
+ bool dl_recalled;
++
++ /* for CB_GETATTR */
++ struct nfs4_cb_fattr dl_cb_fattr;
+ };
+
+ #define cb_to_delegation(cb) \
+@@ -640,6 +653,7 @@ enum nfsd4_cb_op {
+ NFSPROC4_CLNT_CB_SEQUENCE,
+ NFSPROC4_CLNT_CB_NOTIFY_LOCK,
+ NFSPROC4_CLNT_CB_RECALL_ANY,
++ NFSPROC4_CLNT_CB_GETATTR,
+ };
+
+ /* Returns true iff a is later than b: */
+diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
+index 12d79f5d4eb1a..44e275324b06e 100644
+--- a/fs/nfsd/stats.c
++++ b/fs/nfsd/stats.c
+@@ -34,15 +34,17 @@ struct svc_stat nfsd_svcstats = {
+
+ static int nfsd_show(struct seq_file *seq, void *v)
+ {
++ struct net *net = pde_data(file_inode(seq->file));
++ struct nfsd_net *nn = net_generic(net, nfsd_net_id);
+ int i;
+
+ seq_printf(seq, "rc %lld %lld %lld\nfh %lld 0 0 0 0\nio %lld %lld\n",
+- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_HITS]),
+- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_MISSES]),
+- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_RC_NOCACHE]),
+- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_FH_STALE]),
+- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_IO_READ]),
+- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_IO_WRITE]));
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_HITS]),
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_MISSES]),
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_RC_NOCACHE]),
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_FH_STALE]),
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_IO_READ]),
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_IO_WRITE]));
+
+ /* thread usage: */
+ seq_printf(seq, "th %u 0", atomic_read(&nfsdstats.th_cnt));
+@@ -63,10 +65,10 @@ static int nfsd_show(struct seq_file *seq, void *v)
+ seq_printf(seq, "proc4ops %u", LAST_NFS4_OP + 1);
+ for (i = 0; i <= LAST_NFS4_OP; i++) {
+ seq_printf(seq, " %lld",
+- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_NFS4_OP(i)]));
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_NFS4_OP(i)]));
+ }
+ seq_printf(seq, "\nwdeleg_getattr %lld",
+- percpu_counter_sum_positive(&nfsdstats.counter[NFSD_STATS_WDELEG_GETATTR]));
++ percpu_counter_sum_positive(&nn->counter[NFSD_STATS_WDELEG_GETATTR]));
+
+ seq_putc(seq, '\n');
+ #endif
+@@ -108,31 +110,22 @@ void nfsd_percpu_counters_destroy(struct percpu_counter counters[], int num)
+ percpu_counter_destroy(&counters[i]);
+ }
+
+-static int nfsd_stat_counters_init(void)
++int nfsd_stat_counters_init(struct nfsd_net *nn)
+ {
+- return nfsd_percpu_counters_init(nfsdstats.counter, NFSD_STATS_COUNTERS_NUM);
++ return nfsd_percpu_counters_init(nn->counter, NFSD_STATS_COUNTERS_NUM);
+ }
+
+-static void nfsd_stat_counters_destroy(void)
++void nfsd_stat_counters_destroy(struct nfsd_net *nn)
+ {
+- nfsd_percpu_counters_destroy(nfsdstats.counter, NFSD_STATS_COUNTERS_NUM);
++ nfsd_percpu_counters_destroy(nn->counter, NFSD_STATS_COUNTERS_NUM);
+ }
+
+-int nfsd_stat_init(void)
++void nfsd_proc_stat_init(struct net *net)
+ {
+- int err;
+-
+- err = nfsd_stat_counters_init();
+- if (err)
+- return err;
+-
+- svc_proc_register(&init_net, &nfsd_svcstats, &nfsd_proc_ops);
+-
+- return 0;
++ svc_proc_register(net, &nfsd_svcstats, &nfsd_proc_ops);
+ }
+
+-void nfsd_stat_shutdown(void)
++void nfsd_proc_stat_shutdown(struct net *net)
+ {
+- nfsd_stat_counters_destroy();
+- svc_proc_unregister(&init_net, "nfsd");
++ svc_proc_unregister(net, "nfsd");
+ }
+diff --git a/fs/nfsd/stats.h b/fs/nfsd/stats.h
+index 14f50c660b619..c24be4ddbe7d7 100644
+--- a/fs/nfsd/stats.h
++++ b/fs/nfsd/stats.h
+@@ -10,26 +10,7 @@
+ #include <uapi/linux/nfsd/stats.h>
+ #include <linux/percpu_counter.h>
+
+-
+-enum {
+- NFSD_STATS_RC_HITS, /* repcache hits */
+- NFSD_STATS_RC_MISSES, /* repcache misses */
+- NFSD_STATS_RC_NOCACHE, /* uncached reqs */
+- NFSD_STATS_FH_STALE, /* FH stale error */
+- NFSD_STATS_IO_READ, /* bytes returned to read requests */
+- NFSD_STATS_IO_WRITE, /* bytes passed in write requests */
+-#ifdef CONFIG_NFSD_V4
+- NFSD_STATS_FIRST_NFS4_OP, /* count of individual nfsv4 operations */
+- NFSD_STATS_LAST_NFS4_OP = NFSD_STATS_FIRST_NFS4_OP + LAST_NFS4_OP,
+-#define NFSD_STATS_NFS4_OP(op) (NFSD_STATS_FIRST_NFS4_OP + (op))
+- NFSD_STATS_WDELEG_GETATTR, /* count of getattr conflict with wdeleg */
+-#endif
+- NFSD_STATS_COUNTERS_NUM
+-};
+-
+ struct nfsd_stats {
+- struct percpu_counter counter[NFSD_STATS_COUNTERS_NUM];
+-
+ atomic_t th_cnt; /* number of available threads */
+ };
+
+@@ -40,64 +21,69 @@ extern struct svc_stat nfsd_svcstats;
+ int nfsd_percpu_counters_init(struct percpu_counter *counters, int num);
+ void nfsd_percpu_counters_reset(struct percpu_counter *counters, int num);
+ void nfsd_percpu_counters_destroy(struct percpu_counter *counters, int num);
+-int nfsd_stat_init(void);
+-void nfsd_stat_shutdown(void);
++int nfsd_stat_counters_init(struct nfsd_net *nn);
++void nfsd_stat_counters_destroy(struct nfsd_net *nn);
++void nfsd_proc_stat_init(struct net *net);
++void nfsd_proc_stat_shutdown(struct net *net);
+
+-static inline void nfsd_stats_rc_hits_inc(void)
++static inline void nfsd_stats_rc_hits_inc(struct nfsd_net *nn)
+ {
+- percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_RC_HITS]);
++ percpu_counter_inc(&nn->counter[NFSD_STATS_RC_HITS]);
+ }
+
+-static inline void nfsd_stats_rc_misses_inc(void)
++static inline void nfsd_stats_rc_misses_inc(struct nfsd_net *nn)
+ {
+- percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_RC_MISSES]);
++ percpu_counter_inc(&nn->counter[NFSD_STATS_RC_MISSES]);
+ }
+
+-static inline void nfsd_stats_rc_nocache_inc(void)
++static inline void nfsd_stats_rc_nocache_inc(struct nfsd_net *nn)
+ {
+- percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_RC_NOCACHE]);
++ percpu_counter_inc(&nn->counter[NFSD_STATS_RC_NOCACHE]);
+ }
+
+-static inline void nfsd_stats_fh_stale_inc(struct svc_export *exp)
++static inline void nfsd_stats_fh_stale_inc(struct nfsd_net *nn,
++ struct svc_export *exp)
+ {
+- percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_FH_STALE]);
++ percpu_counter_inc(&nn->counter[NFSD_STATS_FH_STALE]);
+ if (exp && exp->ex_stats)
+ percpu_counter_inc(&exp->ex_stats->counter[EXP_STATS_FH_STALE]);
+ }
+
+-static inline void nfsd_stats_io_read_add(struct svc_export *exp, s64 amount)
++static inline void nfsd_stats_io_read_add(struct nfsd_net *nn,
++ struct svc_export *exp, s64 amount)
+ {
+- percpu_counter_add(&nfsdstats.counter[NFSD_STATS_IO_READ], amount);
++ percpu_counter_add(&nn->counter[NFSD_STATS_IO_READ], amount);
+ if (exp && exp->ex_stats)
+ percpu_counter_add(&exp->ex_stats->counter[EXP_STATS_IO_READ], amount);
+ }
+
+-static inline void nfsd_stats_io_write_add(struct svc_export *exp, s64 amount)
++static inline void nfsd_stats_io_write_add(struct nfsd_net *nn,
++ struct svc_export *exp, s64 amount)
+ {
+- percpu_counter_add(&nfsdstats.counter[NFSD_STATS_IO_WRITE], amount);
++ percpu_counter_add(&nn->counter[NFSD_STATS_IO_WRITE], amount);
+ if (exp && exp->ex_stats)
+ percpu_counter_add(&exp->ex_stats->counter[EXP_STATS_IO_WRITE], amount);
+ }
+
+ static inline void nfsd_stats_payload_misses_inc(struct nfsd_net *nn)
+ {
+- percpu_counter_inc(&nn->counter[NFSD_NET_PAYLOAD_MISSES]);
++ percpu_counter_inc(&nn->counter[NFSD_STATS_PAYLOAD_MISSES]);
+ }
+
+ static inline void nfsd_stats_drc_mem_usage_add(struct nfsd_net *nn, s64 amount)
+ {
+- percpu_counter_add(&nn->counter[NFSD_NET_DRC_MEM_USAGE], amount);
++ percpu_counter_add(&nn->counter[NFSD_STATS_DRC_MEM_USAGE], amount);
+ }
+
+ static inline void nfsd_stats_drc_mem_usage_sub(struct nfsd_net *nn, s64 amount)
+ {
+- percpu_counter_sub(&nn->counter[NFSD_NET_DRC_MEM_USAGE], amount);
++ percpu_counter_sub(&nn->counter[NFSD_STATS_DRC_MEM_USAGE], amount);
+ }
+
+ #ifdef CONFIG_NFSD_V4
+-static inline void nfsd_stats_wdeleg_getattr_inc(void)
++static inline void nfsd_stats_wdeleg_getattr_inc(struct nfsd_net *nn)
+ {
+- percpu_counter_inc(&nfsdstats.counter[NFSD_STATS_WDELEG_GETATTR]);
++ percpu_counter_inc(&nn->counter[NFSD_STATS_WDELEG_GETATTR]);
+ }
+ #endif
+ #endif /* _NFSD_STATS_H */
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 4ed1e83defa23..9b5e20b2d0387 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1002,7 +1002,9 @@ static __be32 nfsd_finish_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ unsigned long *count, u32 *eof, ssize_t host_err)
+ {
+ if (host_err >= 0) {
+- nfsd_stats_io_read_add(fhp->fh_export, host_err);
++ struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
++
++ nfsd_stats_io_read_add(nn, fhp->fh_export, host_err);
+ *eof = nfsd_eof_on_read(file, offset, host_err, *count);
+ *count = host_err;
+ fsnotify_access(file);
+@@ -1185,7 +1187,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
+ goto out_nfserr;
+ }
+ *cnt = host_err;
+- nfsd_stats_io_write_add(exp, *cnt);
++ nfsd_stats_io_write_add(nn, exp, *cnt);
+ fsnotify_modify(file);
+ host_err = filemap_check_wb_err(file->f_mapping, since);
+ if (host_err < 0)
+diff --git a/fs/nfsd/xdr4cb.h b/fs/nfsd/xdr4cb.h
+index 0d39af1b00a0f..e8b00309c449f 100644
+--- a/fs/nfsd/xdr4cb.h
++++ b/fs/nfsd/xdr4cb.h
+@@ -54,3 +54,21 @@
+ #define NFS4_dec_cb_recall_any_sz (cb_compound_dec_hdr_sz + \
+ cb_sequence_dec_sz + \
+ op_dec_sz)
++
++/*
++ * 1: CB_GETATTR opcode (32-bit)
++ * N: file_handle
++ * 1: number of entry in attribute array (32-bit)
++ * 1: entry 0 in attribute array (32-bit)
++ */
++#define NFS4_enc_cb_getattr_sz (cb_compound_enc_hdr_sz + \
++ cb_sequence_enc_sz + \
++ 1 + enc_nfs4_fh_sz + 1 + 1)
++/*
++ * 4: fattr_bitmap_maxsz
++ * 1: attribute array len
++ * 2: change attr (64-bit)
++ * 2: size (64-bit)
++ */
++#define NFS4_dec_cb_getattr_sz (cb_compound_dec_hdr_sz + \
++ cb_sequence_dec_sz + 4 + 1 + 2 + 2 + op_dec_sz)
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 3f78ebbb795fe..8433f076e9872 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -1818,15 +1818,13 @@ static unsigned long pagemap_page_category(struct pagemap_scan_private *p,
+ }
+
+ static void make_uffd_wp_pte(struct vm_area_struct *vma,
+- unsigned long addr, pte_t *pte)
++ unsigned long addr, pte_t *pte, pte_t ptent)
+ {
+- pte_t ptent = ptep_get(pte);
+-
+ if (pte_present(ptent)) {
+ pte_t old_pte;
+
+ old_pte = ptep_modify_prot_start(vma, addr, pte);
+- ptent = pte_mkuffd_wp(ptent);
++ ptent = pte_mkuffd_wp(old_pte);
+ ptep_modify_prot_commit(vma, addr, pte, old_pte, ptent);
+ } else if (is_swap_pte(ptent)) {
+ ptent = pte_swp_mkuffd_wp(ptent);
+@@ -2176,9 +2174,12 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start,
+ if ((p->arg.flags & PM_SCAN_WP_MATCHING) && !p->vec_out) {
+ /* Fast path for performing exclusive WP */
+ for (addr = start; addr != end; pte++, addr += PAGE_SIZE) {
+- if (pte_uffd_wp(ptep_get(pte)))
++ pte_t ptent = ptep_get(pte);
++
++ if ((pte_present(ptent) && pte_uffd_wp(ptent)) ||
++ pte_swp_uffd_wp_any(ptent))
+ continue;
+- make_uffd_wp_pte(vma, addr, pte);
++ make_uffd_wp_pte(vma, addr, pte, ptent);
+ if (!flush_end)
+ start = addr;
+ flush_end = addr + PAGE_SIZE;
+@@ -2191,8 +2192,10 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start,
+ p->arg.return_mask == PAGE_IS_WRITTEN) {
+ for (addr = start; addr < end; pte++, addr += PAGE_SIZE) {
+ unsigned long next = addr + PAGE_SIZE;
++ pte_t ptent = ptep_get(pte);
+
+- if (pte_uffd_wp(ptep_get(pte)))
++ if ((pte_present(ptent) && pte_uffd_wp(ptent)) ||
++ pte_swp_uffd_wp_any(ptent))
+ continue;
+ ret = pagemap_scan_output(p->cur_vma_category | PAGE_IS_WRITTEN,
+ p, addr, &next);
+@@ -2200,7 +2203,7 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start,
+ break;
+ if (~p->arg.flags & PM_SCAN_WP_MATCHING)
+ continue;
+- make_uffd_wp_pte(vma, addr, pte);
++ make_uffd_wp_pte(vma, addr, pte, ptent);
+ if (!flush_end)
+ start = addr;
+ flush_end = next;
+@@ -2209,8 +2212,9 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start,
+ }
+
+ for (addr = start; addr != end; pte++, addr += PAGE_SIZE) {
++ pte_t ptent = ptep_get(pte);
+ unsigned long categories = p->cur_vma_category |
+- pagemap_page_category(p, vma, addr, ptep_get(pte));
++ pagemap_page_category(p, vma, addr, ptent);
+ unsigned long next = addr + PAGE_SIZE;
+
+ if (!pagemap_scan_is_interesting_page(categories, p))
+@@ -2225,7 +2229,7 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start,
+ if (~categories & PAGE_IS_WRITTEN)
+ continue;
+
+- make_uffd_wp_pte(vma, addr, pte);
++ make_uffd_wp_pte(vma, addr, pte, ptent);
+ if (!flush_end)
+ start = addr;
+ flush_end = next;
+diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
+index 0c3311de5dc0a..a393d505e847a 100644
+--- a/fs/smb/client/cifsglob.h
++++ b/fs/smb/client/cifsglob.h
+@@ -1063,6 +1063,7 @@ struct cifs_ses {
+ and after mount option parsing we fill it */
+ char *domainName;
+ char *password;
++ char *password2; /* When key rotation used, new password may be set before it expires */
+ char workstation_name[CIFS_MAX_WORKSTATION_LEN];
+ struct session_key auth_key;
+ struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
+diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
+index 7516c7d4558d8..e28f011f11d6c 100644
+--- a/fs/smb/client/connect.c
++++ b/fs/smb/client/connect.c
+@@ -2186,6 +2186,7 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses)
+ }
+
+ ++delim;
++ /* BB consider adding support for password2 (Key Rotation) for multiuser in future */
+ ctx->password = kstrndup(delim, len, GFP_KERNEL);
+ if (!ctx->password) {
+ cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n",
+@@ -2209,6 +2210,7 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses)
+ kfree(ctx->username);
+ ctx->username = NULL;
+ kfree_sensitive(ctx->password);
++ /* no need to free ctx->password2 since not allocated in this path */
+ ctx->password = NULL;
+ goto out_key_put;
+ }
+@@ -2320,6 +2322,12 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
+ if (!ses->password)
+ goto get_ses_fail;
+ }
++ /* ctx->password freed at unmount */
++ if (ctx->password2) {
++ ses->password2 = kstrdup(ctx->password2, GFP_KERNEL);
++ if (!ses->password2)
++ goto get_ses_fail;
++ }
+ if (ctx->domainname) {
+ ses->domainName = kstrdup(ctx->domainname, GFP_KERNEL);
+ if (!ses->domainName)
+diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
+index 775b0ca605892..f119035a82725 100644
+--- a/fs/smb/client/fs_context.c
++++ b/fs/smb/client/fs_context.c
+@@ -162,6 +162,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = {
+ fsparam_string("username", Opt_user),
+ fsparam_string("pass", Opt_pass),
+ fsparam_string("password", Opt_pass),
++ fsparam_string("password2", Opt_pass2),
+ fsparam_string("ip", Opt_ip),
+ fsparam_string("addr", Opt_ip),
+ fsparam_string("domain", Opt_domain),
+@@ -315,6 +316,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx
+ new_ctx->nodename = NULL;
+ new_ctx->username = NULL;
+ new_ctx->password = NULL;
++ new_ctx->password2 = NULL;
+ new_ctx->server_hostname = NULL;
+ new_ctx->domainname = NULL;
+ new_ctx->UNC = NULL;
+@@ -327,6 +329,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx
+ DUP_CTX_STR(prepath);
+ DUP_CTX_STR(username);
+ DUP_CTX_STR(password);
++ DUP_CTX_STR(password2);
+ DUP_CTX_STR(server_hostname);
+ DUP_CTX_STR(UNC);
+ DUP_CTX_STR(source);
+@@ -885,6 +888,8 @@ static int smb3_reconfigure(struct fs_context *fc)
+ else {
+ kfree_sensitive(ses->password);
+ ses->password = kstrdup(ctx->password, GFP_KERNEL);
++ kfree_sensitive(ses->password2);
++ ses->password2 = kstrdup(ctx->password2, GFP_KERNEL);
+ }
+ STEAL_STRING(cifs_sb, ctx, domainname);
+ STEAL_STRING(cifs_sb, ctx, nodename);
+@@ -1287,6 +1292,18 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
+ goto cifs_parse_mount_err;
+ }
+ break;
++ case Opt_pass2:
++ kfree_sensitive(ctx->password2);
++ ctx->password2 = NULL;
++ if (strlen(param->string) == 0)
++ break;
++
++ ctx->password2 = kstrdup(param->string, GFP_KERNEL);
++ if (ctx->password2 == NULL) {
++ cifs_errorf(fc, "OOM when copying password2 string\n");
++ goto cifs_parse_mount_err;
++ }
++ break;
+ case Opt_ip:
+ if (strlen(param->string) == 0) {
+ ctx->got_ip = false;
+@@ -1586,6 +1603,8 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
+ cifs_parse_mount_err:
+ kfree_sensitive(ctx->password);
+ ctx->password = NULL;
++ kfree_sensitive(ctx->password2);
++ ctx->password2 = NULL;
+ return -EINVAL;
+ }
+
+@@ -1690,6 +1709,8 @@ smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx)
+ ctx->username = NULL;
+ kfree_sensitive(ctx->password);
+ ctx->password = NULL;
++ kfree_sensitive(ctx->password2);
++ ctx->password2 = NULL;
+ kfree(ctx->server_hostname);
+ ctx->server_hostname = NULL;
+ kfree(ctx->UNC);
+diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h
+index 61776572b8d2d..369a3fea1dfe0 100644
+--- a/fs/smb/client/fs_context.h
++++ b/fs/smb/client/fs_context.h
+@@ -138,6 +138,7 @@ enum cifs_param {
+ Opt_source,
+ Opt_user,
+ Opt_pass,
++ Opt_pass2,
+ Opt_ip,
+ Opt_domain,
+ Opt_srcaddr,
+@@ -171,6 +172,7 @@ struct smb3_fs_context {
+
+ char *username;
+ char *password;
++ char *password2;
+ char *domainname;
+ char *source;
+ char *server_hostname;
+diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c
+index 0d13db80e67c9..d56959d02e36d 100644
+--- a/fs/smb/client/misc.c
++++ b/fs/smb/client/misc.c
+@@ -101,6 +101,7 @@ sesInfoFree(struct cifs_ses *buf_to_free)
+ kfree(buf_to_free->serverDomain);
+ kfree(buf_to_free->serverNOS);
+ kfree_sensitive(buf_to_free->password);
++ kfree_sensitive(buf_to_free->password2);
+ kfree(buf_to_free->user_name);
+ kfree(buf_to_free->domainName);
+ kfree_sensitive(buf_to_free->auth_key.response);
+diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
+index b71e32d66eba7..60793143e24c6 100644
+--- a/fs/smb/client/smb2pdu.c
++++ b/fs/smb/client/smb2pdu.c
+@@ -367,6 +367,17 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
+ }
+
+ rc = cifs_setup_session(0, ses, server, nls_codepage);
++ if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED)) {
++ /*
++ * Try alternate password for next reconnect (key rotation
++ * could be enabled on the server e.g.) if an alternate
++ * password is available and the current password is expired,
++ * but do not swap on non pwd related errors like host down
++ */
++ if (ses->password2)
++ swap(ses->password2, ses->password);
++ }
++
+ if ((rc == -EACCES) && !tcon->retry) {
+ mutex_unlock(&ses->session_mutex);
+ rc = -EHOSTDOWN;
+diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
+index 53dfaac425c68..dc729ab980dc0 100644
+--- a/fs/smb/server/oplock.c
++++ b/fs/smb/server/oplock.c
+@@ -612,13 +612,23 @@ static int oplock_break_pending(struct oplock_info *opinfo, int req_op_level)
+
+ if (opinfo->op_state == OPLOCK_CLOSING)
+ return -ENOENT;
+- else if (!opinfo->is_lease && opinfo->level <= req_op_level)
+- return 1;
++ else if (opinfo->level <= req_op_level) {
++ if (opinfo->is_lease &&
++ opinfo->o_lease->state !=
++ (SMB2_LEASE_HANDLE_CACHING_LE |
++ SMB2_LEASE_READ_CACHING_LE))
++ return 1;
++ }
+ }
+
+- if (!opinfo->is_lease && opinfo->level <= req_op_level) {
+- wake_up_oplock_break(opinfo);
+- return 1;
++ if (opinfo->level <= req_op_level) {
++ if (opinfo->is_lease &&
++ opinfo->o_lease->state !=
++ (SMB2_LEASE_HANDLE_CACHING_LE |
++ SMB2_LEASE_READ_CACHING_LE)) {
++ wake_up_oplock_break(opinfo);
++ return 1;
++ }
+ }
+ return 0;
+ }
+@@ -886,7 +896,6 @@ static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level)
+ struct lease *lease = brk_opinfo->o_lease;
+
+ atomic_inc(&brk_opinfo->breaking_cnt);
+-
+ err = oplock_break_pending(brk_opinfo, req_op_level);
+ if (err)
+ return err < 0 ? err : 0;
+@@ -1199,7 +1208,9 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
+
+ /* Only v2 leases handle the directory */
+ if (S_ISDIR(file_inode(fp->filp)->i_mode)) {
+- if (!lctx || lctx->version != 2)
++ if (!lctx || lctx->version != 2 ||
++ (lctx->flags != SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE &&
++ !lctx->epoch))
+ return 0;
+ }
+
+@@ -1461,8 +1472,9 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
+ buf->lcontext.LeaseFlags = lease->flags;
+ buf->lcontext.Epoch = cpu_to_le16(lease->epoch);
+ buf->lcontext.LeaseState = lease->state;
+- memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
+- SMB2_LEASE_KEY_SIZE);
++ if (lease->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE)
++ memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
++ SMB2_LEASE_KEY_SIZE);
+ buf->ccontext.DataOffset = cpu_to_le16(offsetof
+ (struct create_lease_v2, lcontext));
+ buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
+@@ -1527,8 +1539,9 @@ struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir)
+ lreq->flags = lc->lcontext.LeaseFlags;
+ lreq->epoch = lc->lcontext.Epoch;
+ lreq->duration = lc->lcontext.LeaseDuration;
+- memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
+- SMB2_LEASE_KEY_SIZE);
++ if (lreq->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE)
++ memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
++ SMB2_LEASE_KEY_SIZE);
+ lreq->version = 2;
+ } else {
+ struct create_lease *lc = (struct create_lease *)cc;
+diff --git a/fs/smb/server/transport_tcp.c b/fs/smb/server/transport_tcp.c
+index 002a3f0dc7c58..6633fa78e9b96 100644
+--- a/fs/smb/server/transport_tcp.c
++++ b/fs/smb/server/transport_tcp.c
+@@ -448,6 +448,10 @@ static int create_socket(struct interface *iface)
+ sin6.sin6_family = PF_INET6;
+ sin6.sin6_addr = in6addr_any;
+ sin6.sin6_port = htons(server_conf.tcp_port);
++
++ lock_sock(ksmbd_socket->sk);
++ ksmbd_socket->sk->sk_ipv6only = false;
++ release_sock(ksmbd_socket->sk);
+ }
+
+ ksmbd_tcp_nodelay(ksmbd_socket);
+diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c
+index 110e8a2721890..56d1741fe0413 100644
+--- a/fs/tracefs/event_inode.c
++++ b/fs/tracefs/event_inode.c
+@@ -164,21 +164,7 @@ static int eventfs_set_attr(struct mnt_idmap *idmap, struct dentry *dentry,
+ * determined by the parent directory.
+ */
+ if (dentry->d_inode->i_mode & S_IFDIR) {
+- /*
+- * The events directory dentry is never freed, unless its
+- * part of an instance that is deleted. It's attr is the
+- * default for its child files and directories.
+- * Do not update it. It's not used for its own mode or ownership.
+- */
+- if (ei->is_events) {
+- /* But it still needs to know if it was modified */
+- if (iattr->ia_valid & ATTR_UID)
+- ei->attr.mode |= EVENTFS_SAVE_UID;
+- if (iattr->ia_valid & ATTR_GID)
+- ei->attr.mode |= EVENTFS_SAVE_GID;
+- } else {
+- update_attr(&ei->attr, iattr);
+- }
++ update_attr(&ei->attr, iattr);
+
+ } else {
+ name = dentry->d_name.name;
+@@ -265,6 +251,35 @@ static const struct file_operations eventfs_file_operations = {
+ .llseek = generic_file_llseek,
+ };
+
++/*
++ * On a remount of tracefs, if UID or GID options are set, then
++ * the mount point inode permissions should be used.
++ * Reset the saved permission flags appropriately.
++ */
++void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid)
++{
++ struct eventfs_inode *ei = ti->private;
++
++ if (!ei)
++ return;
++
++ if (update_uid)
++ ei->attr.mode &= ~EVENTFS_SAVE_UID;
++
++ if (update_gid)
++ ei->attr.mode &= ~EVENTFS_SAVE_GID;
++
++ if (!ei->entry_attrs)
++ return;
++
++ for (int i = 0; i < ei->nr_entries; i++) {
++ if (update_uid)
++ ei->entry_attrs[i].mode &= ~EVENTFS_SAVE_UID;
++ if (update_gid)
++ ei->entry_attrs[i].mode &= ~EVENTFS_SAVE_GID;
++ }
++}
++
+ /* Return the evenfs_inode of the "events" directory */
+ static struct eventfs_inode *eventfs_find_events(struct dentry *dentry)
+ {
+diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
+index d65ffad4c327c..e30b74228ef7e 100644
+--- a/fs/tracefs/inode.c
++++ b/fs/tracefs/inode.c
+@@ -30,20 +30,47 @@ static struct vfsmount *tracefs_mount;
+ static int tracefs_mount_count;
+ static bool tracefs_registered;
+
++/*
++ * Keep track of all tracefs_inodes in order to update their
++ * flags if necessary on a remount.
++ */
++static DEFINE_SPINLOCK(tracefs_inode_lock);
++static LIST_HEAD(tracefs_inodes);
++
+ static struct inode *tracefs_alloc_inode(struct super_block *sb)
+ {
+ struct tracefs_inode *ti;
++ unsigned long flags;
+
+ ti = kmem_cache_alloc(tracefs_inode_cachep, GFP_KERNEL);
+ if (!ti)
+ return NULL;
+
++ spin_lock_irqsave(&tracefs_inode_lock, flags);
++ list_add_rcu(&ti->list, &tracefs_inodes);
++ spin_unlock_irqrestore(&tracefs_inode_lock, flags);
++
+ return &ti->vfs_inode;
+ }
+
++static void tracefs_free_inode_rcu(struct rcu_head *rcu)
++{
++ struct tracefs_inode *ti;
++
++ ti = container_of(rcu, struct tracefs_inode, rcu);
++ kmem_cache_free(tracefs_inode_cachep, ti);
++}
++
+ static void tracefs_free_inode(struct inode *inode)
+ {
+- kmem_cache_free(tracefs_inode_cachep, get_tracefs(inode));
++ struct tracefs_inode *ti = get_tracefs(inode);
++ unsigned long flags;
++
++ spin_lock_irqsave(&tracefs_inode_lock, flags);
++ list_del_rcu(&ti->list);
++ spin_unlock_irqrestore(&tracefs_inode_lock, flags);
++
++ call_rcu(&ti->rcu, tracefs_free_inode_rcu);
+ }
+
+ static ssize_t default_read_file(struct file *file, char __user *buf,
+@@ -153,16 +180,39 @@ static void set_tracefs_inode_owner(struct inode *inode)
+ {
+ struct tracefs_inode *ti = get_tracefs(inode);
+ struct inode *root_inode = ti->private;
++ kuid_t uid;
++ kgid_t gid;
++
++ uid = root_inode->i_uid;
++ gid = root_inode->i_gid;
++
++ /*
++ * If the root is not the mount point, then check the root's
++ * permissions. If it was never set, then default to the
++ * mount point.
++ */
++ if (root_inode != d_inode(root_inode->i_sb->s_root)) {
++ struct tracefs_inode *rti;
++
++ rti = get_tracefs(root_inode);
++ root_inode = d_inode(root_inode->i_sb->s_root);
++
++ if (!(rti->flags & TRACEFS_UID_PERM_SET))
++ uid = root_inode->i_uid;
++
++ if (!(rti->flags & TRACEFS_GID_PERM_SET))
++ gid = root_inode->i_gid;
++ }
+
+ /*
+ * If this inode has never been referenced, then update
+ * the permissions to the superblock.
+ */
+ if (!(ti->flags & TRACEFS_UID_PERM_SET))
+- inode->i_uid = root_inode->i_uid;
++ inode->i_uid = uid;
+
+ if (!(ti->flags & TRACEFS_GID_PERM_SET))
+- inode->i_gid = root_inode->i_gid;
++ inode->i_gid = gid;
+ }
+
+ static int tracefs_permission(struct mnt_idmap *idmap,
+@@ -313,6 +363,8 @@ static int tracefs_apply_options(struct super_block *sb, bool remount)
+ struct tracefs_fs_info *fsi = sb->s_fs_info;
+ struct inode *inode = d_inode(sb->s_root);
+ struct tracefs_mount_opts *opts = &fsi->mount_opts;
++ struct tracefs_inode *ti;
++ bool update_uid, update_gid;
+ umode_t tmp_mode;
+
+ /*
+@@ -332,6 +384,25 @@ static int tracefs_apply_options(struct super_block *sb, bool remount)
+ if (!remount || opts->opts & BIT(Opt_gid))
+ inode->i_gid = opts->gid;
+
++ if (remount && (opts->opts & BIT(Opt_uid) || opts->opts & BIT(Opt_gid))) {
++
++ update_uid = opts->opts & BIT(Opt_uid);
++ update_gid = opts->opts & BIT(Opt_gid);
++
++ rcu_read_lock();
++ list_for_each_entry_rcu(ti, &tracefs_inodes, list) {
++ if (update_uid)
++ ti->flags &= ~TRACEFS_UID_PERM_SET;
++
++ if (update_gid)
++ ti->flags &= ~TRACEFS_GID_PERM_SET;
++
++ if (ti->flags & TRACEFS_EVENT_INODE)
++ eventfs_remount(ti, update_uid, update_gid);
++ }
++ rcu_read_unlock();
++ }
++
+ return 0;
+ }
+
+@@ -398,7 +469,22 @@ static int tracefs_d_revalidate(struct dentry *dentry, unsigned int flags)
+ return !(ei && ei->is_freed);
+ }
+
++static void tracefs_d_iput(struct dentry *dentry, struct inode *inode)
++{
++ struct tracefs_inode *ti = get_tracefs(inode);
++
++ /*
++ * This inode is being freed and cannot be used for
++ * eventfs. Clear the flag so that it doesn't call into
++ * eventfs during the remount flag updates. The eventfs_inode
++ * gets freed after an RCU cycle, so the content will still
++ * be safe if the iteration is going on now.
++ */
++ ti->flags &= ~TRACEFS_EVENT_INODE;
++}
++
+ static const struct dentry_operations tracefs_dentry_operations = {
++ .d_iput = tracefs_d_iput,
+ .d_revalidate = tracefs_d_revalidate,
+ .d_release = tracefs_d_release,
+ };
+diff --git a/fs/tracefs/internal.h b/fs/tracefs/internal.h
+index beb3dcd0e4342..824cbe83679cc 100644
+--- a/fs/tracefs/internal.h
++++ b/fs/tracefs/internal.h
+@@ -11,8 +11,12 @@ enum {
+ };
+
+ struct tracefs_inode {
+- struct inode vfs_inode;
++ union {
++ struct inode vfs_inode;
++ struct rcu_head rcu;
++ };
+ /* The below gets initialized with memset_after(ti, 0, vfs_inode) */
++ struct list_head list;
+ unsigned long flags;
+ void *private;
+ };
+@@ -75,6 +79,7 @@ struct dentry *tracefs_end_creating(struct dentry *dentry);
+ struct dentry *tracefs_failed_creating(struct dentry *dentry);
+ struct inode *tracefs_get_inode(struct super_block *sb);
+
++void eventfs_remount(struct tracefs_inode *ti, bool update_uid, bool update_gid);
+ void eventfs_d_release(struct dentry *dentry);
+
+ #endif /* _TRACEFS_INTERNAL_H */
+diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
+index 959551ff9a951..13ef4e1fc1237 100644
+--- a/fs/userfaultfd.c
++++ b/fs/userfaultfd.c
+@@ -925,6 +925,10 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
+ prev = vma;
+ continue;
+ }
++ /* Reset ptes for the whole vma range if wr-protected */
++ if (userfaultfd_wp(vma))
++ uffd_wp_range(vma, vma->vm_start,
++ vma->vm_end - vma->vm_start, false);
+ new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS;
+ vma = vma_modify_flags_uffd(&vmi, prev, vma, vma->vm_start,
+ vma->vm_end, new_flags,
+diff --git a/fs/vboxsf/file.c b/fs/vboxsf/file.c
+index 2307f8037efc3..118dedef8ebe8 100644
+--- a/fs/vboxsf/file.c
++++ b/fs/vboxsf/file.c
+@@ -218,6 +218,7 @@ const struct file_operations vboxsf_reg_fops = {
+ .release = vboxsf_file_release,
+ .fsync = noop_fsync,
+ .splice_read = filemap_splice_read,
++ .setlease = simple_nosetlease,
+ };
+
+ const struct inode_operations vboxsf_reg_iops = {
+diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
+index 0caf354cb94b5..a6a28952836cb 100644
+--- a/include/linux/compiler_types.h
++++ b/include/linux/compiler_types.h
+@@ -278,6 +278,17 @@ struct ftrace_likely_data {
+ # define __no_kcsan
+ #endif
+
++#ifdef __SANITIZE_MEMORY__
++/*
++ * Similarly to KASAN and KCSAN, KMSAN loses function attributes of inlined
++ * functions, therefore disabling KMSAN checks also requires disabling inlining.
++ *
++ * __no_sanitize_or_inline effectively prevents KMSAN from reporting errors
++ * within the function and marks all its outputs as initialized.
++ */
++# define __no_sanitize_or_inline __no_kmsan_checks notrace __maybe_unused
++#endif
++
+ #ifndef __no_sanitize_or_inline
+ #define __no_sanitize_or_inline __always_inline
+ #endif
+diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h
+index c3f9bb6602ba2..e06bad467f55e 100644
+--- a/include/linux/dma-fence.h
++++ b/include/linux/dma-fence.h
+@@ -682,11 +682,4 @@ static inline bool dma_fence_is_container(struct dma_fence *fence)
+ return dma_fence_is_array(fence) || dma_fence_is_chain(fence);
+ }
+
+-#define DMA_FENCE_WARN(f, fmt, args...) \
+- do { \
+- struct dma_fence *__ff = (f); \
+- pr_warn("f %llu#%llu: " fmt, __ff->context, __ff->seqno,\
+- ##args); \
+- } while (0)
+-
+ #endif /* __LINUX_DMA_FENCE_H */
+diff --git a/include/linux/gfp_types.h b/include/linux/gfp_types.h
+index 1b6053da8754e..495ebf5f2cb6d 100644
+--- a/include/linux/gfp_types.h
++++ b/include/linux/gfp_types.h
+@@ -2,6 +2,8 @@
+ #ifndef __LINUX_GFP_TYPES_H
+ #define __LINUX_GFP_TYPES_H
+
++#include <linux/bits.h>
++
+ /* The typedef is in types.h but we want the documentation here */
+ #if 0
+ /**
+diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
+index 6ef0557b4bff8..96ceb4095425e 100644
+--- a/include/linux/hyperv.h
++++ b/include/linux/hyperv.h
+@@ -832,6 +832,7 @@ struct vmbus_gpadl {
+ u32 gpadl_handle;
+ u32 size;
+ void *buffer;
++ bool decrypted;
+ };
+
+ struct vmbus_channel {
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index a0c75e467df36..5bfa57a5f7340 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -2686,8 +2686,10 @@
+ #define PCI_DEVICE_ID_INTEL_I960 0x0960
+ #define PCI_DEVICE_ID_INTEL_I960RM 0x0962
+ #define PCI_DEVICE_ID_INTEL_HDA_HSW_0 0x0a0c
++#define PCI_DEVICE_ID_INTEL_DSA_SPR0 0x0b25
+ #define PCI_DEVICE_ID_INTEL_HDA_HSW_2 0x0c0c
+ #define PCI_DEVICE_ID_INTEL_CENTERTON_ILB 0x0c60
++#define PCI_DEVICE_ID_INTEL_IAX_SPR0 0x0cfe
+ #define PCI_DEVICE_ID_INTEL_HDA_HSW_3 0x0d0c
+ #define PCI_DEVICE_ID_INTEL_HDA_BYT 0x0f04
+ #define PCI_DEVICE_ID_INTEL_SST_BYT 0x0f28
+diff --git a/include/linux/regmap.h b/include/linux/regmap.h
+index c9182a47736ef..113261287af28 100644
+--- a/include/linux/regmap.h
++++ b/include/linux/regmap.h
+@@ -1225,6 +1225,7 @@ int regmap_multi_reg_write_bypassed(struct regmap *map,
+ int regmap_raw_write_async(struct regmap *map, unsigned int reg,
+ const void *val, size_t val_len);
+ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val);
++int regmap_read_bypassed(struct regmap *map, unsigned int reg, unsigned int *val);
+ int regmap_raw_read(struct regmap *map, unsigned int reg,
+ void *val, size_t val_len);
+ int regmap_noinc_read(struct regmap *map, unsigned int reg,
+@@ -1734,6 +1735,13 @@ static inline int regmap_read(struct regmap *map, unsigned int reg,
+ return -EINVAL;
+ }
+
++static inline int regmap_read_bypassed(struct regmap *map, unsigned int reg,
++ unsigned int *val)
++{
++ WARN_ONCE(1, "regmap API is disabled");
++ return -EINVAL;
++}
++
+ static inline int regmap_raw_read(struct regmap *map, unsigned int reg,
+ void *val, size_t val_len)
+ {
+diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
+index 4660582a33022..ed180ca419dad 100644
+--- a/include/linux/regulator/consumer.h
++++ b/include/linux/regulator/consumer.h
+@@ -320,13 +320,13 @@ devm_regulator_get_exclusive(struct device *dev, const char *id)
+
+ static inline int devm_regulator_get_enable(struct device *dev, const char *id)
+ {
+- return -ENODEV;
++ return 0;
+ }
+
+ static inline int devm_regulator_get_enable_optional(struct device *dev,
+ const char *id)
+ {
+- return -ENODEV;
++ return 0;
+ }
+
+ static inline struct regulator *__must_check
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index 5bafcfe18be61..f86f9396f727b 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -2972,6 +2972,21 @@ static inline void skb_mac_header_rebuild(struct sk_buff *skb)
+ }
+ }
+
++/* Move the full mac header up to current network_header.
++ * Leaves skb->data pointing at offset skb->mac_len into the mac_header.
++ * Must be provided the complete mac header length.
++ */
++static inline void skb_mac_header_rebuild_full(struct sk_buff *skb, u32 full_mac_len)
++{
++ if (skb_mac_header_was_set(skb)) {
++ const unsigned char *old_mac = skb_mac_header(skb);
++
++ skb_set_mac_header(skb, -full_mac_len);
++ memmove(skb_mac_header(skb), old_mac, full_mac_len);
++ __skb_push(skb, full_mac_len - skb->mac_len);
++ }
++}
++
+ static inline int skb_checksum_start_offset(const struct sk_buff *skb)
+ {
+ return skb->csum_start - skb_headroom(skb);
+diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h
+index e65ec3fd27998..a509caf823d61 100644
+--- a/include/linux/skmsg.h
++++ b/include/linux/skmsg.h
+@@ -461,10 +461,12 @@ static inline void sk_psock_put(struct sock *sk, struct sk_psock *psock)
+
+ static inline void sk_psock_data_ready(struct sock *sk, struct sk_psock *psock)
+ {
++ read_lock_bh(&sk->sk_callback_lock);
+ if (psock->saved_data_ready)
+ psock->saved_data_ready(sk);
+ else
+ sk->sk_data_ready(sk);
++ read_unlock_bh(&sk->sk_callback_lock);
+ }
+
+ static inline void psock_set_prog(struct bpf_prog **pprog,
+diff --git a/include/linux/slab.h b/include/linux/slab.h
+index b5f5ee8308d0f..34b32c59ce790 100644
+--- a/include/linux/slab.h
++++ b/include/linux/slab.h
+@@ -228,7 +228,7 @@ void kfree(const void *objp);
+ void kfree_sensitive(const void *objp);
+ size_t __ksize(const void *objp);
+
+-DEFINE_FREE(kfree, void *, if (_T) kfree(_T))
++DEFINE_FREE(kfree, void *, if (!IS_ERR_OR_NULL(_T)) kfree(_T))
+
+ /**
+ * ksize - Report actual allocation size of associated object
+@@ -754,7 +754,7 @@ static inline __alloc_size(1, 2) void *kvcalloc(size_t n, size_t size, gfp_t fla
+ extern void *kvrealloc(const void *p, size_t oldsize, size_t newsize, gfp_t flags)
+ __realloc_size(3);
+ extern void kvfree(const void *addr);
+-DEFINE_FREE(kvfree, void *, if (_T) kvfree(_T))
++DEFINE_FREE(kvfree, void *, if (!IS_ERR_OR_NULL(_T)) kvfree(_T))
+
+ extern void kvfree_sensitive(const void *addr, size_t len);
+
+diff --git a/include/linux/sockptr.h b/include/linux/sockptr.h
+index 307961b41541a..317200cd3a603 100644
+--- a/include/linux/sockptr.h
++++ b/include/linux/sockptr.h
+@@ -50,11 +50,36 @@ static inline int copy_from_sockptr_offset(void *dst, sockptr_t src,
+ return 0;
+ }
+
++/* Deprecated.
++ * This is unsafe, unless caller checked user provided optlen.
++ * Prefer copy_safe_from_sockptr() instead.
++ */
+ static inline int copy_from_sockptr(void *dst, sockptr_t src, size_t size)
+ {
+ return copy_from_sockptr_offset(dst, src, 0, size);
+ }
+
++/**
++ * copy_safe_from_sockptr: copy a struct from sockptr
++ * @dst: Destination address, in kernel space. This buffer must be @ksize
++ * bytes long.
++ * @ksize: Size of @dst struct.
++ * @optval: Source address. (in user or kernel space)
++ * @optlen: Size of @optval data.
++ *
++ * Returns:
++ * * -EINVAL: @optlen < @ksize
++ * * -EFAULT: access to userspace failed.
++ * * 0 : @ksize bytes were copied
++ */
++static inline int copy_safe_from_sockptr(void *dst, size_t ksize,
++ sockptr_t optval, unsigned int optlen)
++{
++ if (optlen < ksize)
++ return -EINVAL;
++ return copy_from_sockptr(dst, optval, ksize);
++}
++
+ static inline int copy_struct_from_sockptr(void *dst, size_t ksize,
+ sockptr_t src, size_t usize)
+ {
+diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
+index 5e9d1469c6fae..5321585c778fc 100644
+--- a/include/linux/sunrpc/clnt.h
++++ b/include/linux/sunrpc/clnt.h
+@@ -139,6 +139,7 @@ struct rpc_create_args {
+ const char *servername;
+ const char *nodename;
+ const struct rpc_program *program;
++ struct rpc_stat *stats;
+ u32 prognumber; /* overrides program->number */
+ u32 version;
+ rpc_authflavor_t authflavor;
+diff --git a/include/net/gro.h b/include/net/gro.h
+index b435f0ddbf64f..62b006f3ed184 100644
+--- a/include/net/gro.h
++++ b/include/net/gro.h
+@@ -86,6 +86,15 @@ struct napi_gro_cb {
+
+ /* used to support CHECKSUM_COMPLETE for tunneling protocols */
+ __wsum csum;
++
++ /* L3 offsets */
++ union {
++ struct {
++ u16 network_offset;
++ u16 inner_network_offset;
++ };
++ u16 network_offsets[2];
++ };
+ };
+
+ #define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
+diff --git a/include/net/xfrm.h b/include/net/xfrm.h
+index 1d107241b9018..5d0f8f40b8d16 100644
+--- a/include/net/xfrm.h
++++ b/include/net/xfrm.h
+@@ -1047,6 +1047,9 @@ struct xfrm_offload {
+ #define CRYPTO_INVALID_PACKET_SYNTAX 64
+ #define CRYPTO_INVALID_PROTOCOL 128
+
++ /* Used to keep whole l2 header for transport mode GRO */
++ __u32 orig_mac_len;
++
+ __u8 proto;
+ __u8 inner_ipproto;
+ };
+diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
+index 1af9e68193920..9cc10fab01a8c 100644
+--- a/include/sound/emu10k1.h
++++ b/include/sound/emu10k1.h
+@@ -1684,8 +1684,7 @@ struct snd_emu1010 {
+ unsigned int clock_fallback;
+ unsigned int optical_in; /* 0:SPDIF, 1:ADAT */
+ unsigned int optical_out; /* 0:SPDIF, 1:ADAT */
+- struct work_struct firmware_work;
+- struct work_struct clock_work;
++ struct work_struct work;
+ };
+
+ struct snd_emu10k1 {
+diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
+index 87b8de9b6c1c4..ecf9da5462359 100644
+--- a/include/trace/events/rxrpc.h
++++ b/include/trace/events/rxrpc.h
+@@ -83,7 +83,7 @@
+ EM(rxrpc_badmsg_bad_abort, "bad-abort") \
+ EM(rxrpc_badmsg_bad_jumbo, "bad-jumbo") \
+ EM(rxrpc_badmsg_short_ack, "short-ack") \
+- EM(rxrpc_badmsg_short_ack_info, "short-ack-info") \
++ EM(rxrpc_badmsg_short_ack_trailer, "short-ack-trailer") \
+ EM(rxrpc_badmsg_short_hdr, "short-hdr") \
+ EM(rxrpc_badmsg_unsupported_packet, "unsup-pkt") \
+ EM(rxrpc_badmsg_zero_call, "zero-call") \
+diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h
+index f0ed68974c543..5fdaf0ab460da 100644
+--- a/include/uapi/linux/kfd_ioctl.h
++++ b/include/uapi/linux/kfd_ioctl.h
+@@ -912,14 +912,25 @@ enum kfd_dbg_trap_exception_code {
+ KFD_EC_MASK(EC_DEVICE_NEW))
+ #define KFD_EC_MASK_PROCESS (KFD_EC_MASK(EC_PROCESS_RUNTIME) | \
+ KFD_EC_MASK(EC_PROCESS_DEVICE_REMOVE))
++#define KFD_EC_MASK_PACKET (KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_DIM_INVALID) | \
++ KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_GROUP_SEGMENT_SIZE_INVALID) | \
++ KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_CODE_INVALID) | \
++ KFD_EC_MASK(EC_QUEUE_PACKET_RESERVED) | \
++ KFD_EC_MASK(EC_QUEUE_PACKET_UNSUPPORTED) | \
++ KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_WORK_GROUP_SIZE_INVALID) | \
++ KFD_EC_MASK(EC_QUEUE_PACKET_DISPATCH_REGISTER_INVALID) | \
++ KFD_EC_MASK(EC_QUEUE_PACKET_VENDOR_UNSUPPORTED))
+
+ /* Checks for exception code types for KFD search */
++#define KFD_DBG_EC_IS_VALID(ecode) (ecode > EC_NONE && ecode < EC_MAX)
+ #define KFD_DBG_EC_TYPE_IS_QUEUE(ecode) \
+- (!!(KFD_EC_MASK(ecode) & KFD_EC_MASK_QUEUE))
++ (KFD_DBG_EC_IS_VALID(ecode) && !!(KFD_EC_MASK(ecode) & KFD_EC_MASK_QUEUE))
+ #define KFD_DBG_EC_TYPE_IS_DEVICE(ecode) \
+- (!!(KFD_EC_MASK(ecode) & KFD_EC_MASK_DEVICE))
++ (KFD_DBG_EC_IS_VALID(ecode) && !!(KFD_EC_MASK(ecode) & KFD_EC_MASK_DEVICE))
+ #define KFD_DBG_EC_TYPE_IS_PROCESS(ecode) \
+- (!!(KFD_EC_MASK(ecode) & KFD_EC_MASK_PROCESS))
++ (KFD_DBG_EC_IS_VALID(ecode) && !!(KFD_EC_MASK(ecode) & KFD_EC_MASK_PROCESS))
++#define KFD_DBG_EC_TYPE_IS_PACKET(ecode) \
++ (KFD_DBG_EC_IS_VALID(ecode) && !!(KFD_EC_MASK(ecode) & KFD_EC_MASK_PACKET))
+
+
+ /* Runtime enable states */
+diff --git a/include/uapi/scsi/scsi_bsg_mpi3mr.h b/include/uapi/scsi/scsi_bsg_mpi3mr.h
+index c72ce387286ad..30a5c1a593764 100644
+--- a/include/uapi/scsi/scsi_bsg_mpi3mr.h
++++ b/include/uapi/scsi/scsi_bsg_mpi3mr.h
+@@ -382,7 +382,7 @@ struct mpi3mr_bsg_in_reply_buf {
+ __u8 mpi_reply_type;
+ __u8 rsvd1;
+ __u16 rsvd2;
+- __u8 reply_buf[1];
++ __u8 reply_buf[];
+ };
+
+ /**
+diff --git a/kernel/bpf/bloom_filter.c b/kernel/bpf/bloom_filter.c
+index addf3dd57b59b..35e1ddca74d21 100644
+--- a/kernel/bpf/bloom_filter.c
++++ b/kernel/bpf/bloom_filter.c
+@@ -80,6 +80,18 @@ static int bloom_map_get_next_key(struct bpf_map *map, void *key, void *next_key
+ return -EOPNOTSUPP;
+ }
+
++/* Called from syscall */
++static int bloom_map_alloc_check(union bpf_attr *attr)
++{
++ if (attr->value_size > KMALLOC_MAX_SIZE)
++ /* if value_size is bigger, the user space won't be able to
++ * access the elements.
++ */
++ return -E2BIG;
++
++ return 0;
++}
++
+ static struct bpf_map *bloom_map_alloc(union bpf_attr *attr)
+ {
+ u32 bitset_bytes, bitset_mask, nr_hash_funcs, nr_bits;
+@@ -191,6 +203,7 @@ static u64 bloom_map_mem_usage(const struct bpf_map *map)
+ BTF_ID_LIST_SINGLE(bpf_bloom_map_btf_ids, struct, bpf_bloom_filter)
+ const struct bpf_map_ops bloom_filter_map_ops = {
+ .map_meta_equal = bpf_map_meta_equal,
++ .map_alloc_check = bloom_map_alloc_check,
+ .map_alloc = bloom_map_alloc,
+ .map_free = bloom_map_free,
+ .map_get_next_key = bloom_map_get_next_key,
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 19e575e6b7fe0..11bc3af33f34f 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -18040,8 +18040,7 @@ static int resolve_pseudo_ldimm64(struct bpf_verifier_env *env)
+ f = fdget(fd);
+ map = __bpf_map_get(f);
+ if (IS_ERR(map)) {
+- verbose(env, "fd %d is not pointing to valid bpf_map\n",
+- insn[0].imm);
++ verbose(env, "fd %d is not pointing to valid bpf_map\n", fd);
+ return PTR_ERR(map);
+ }
+
+diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
+index 877c4b8fad195..1955b42f42fc9 100644
+--- a/kernel/dma/swiotlb.c
++++ b/kernel/dma/swiotlb.c
+@@ -1717,6 +1717,7 @@ static int rmem_swiotlb_device_init(struct reserved_mem *rmem,
+ mem->for_alloc = true;
+ #ifdef CONFIG_SWIOTLB_DYNAMIC
+ spin_lock_init(&mem->lock);
++ INIT_LIST_HEAD_RCU(&mem->pools);
+ #endif
+ add_mem_pool(mem, pool);
+
+diff --git a/kernel/workqueue.c b/kernel/workqueue.c
+index 7b482a26d7419..223aa99bb71c1 100644
+--- a/kernel/workqueue.c
++++ b/kernel/workqueue.c
+@@ -1141,8 +1141,12 @@ static bool kick_pool(struct worker_pool *pool)
+ !cpumask_test_cpu(p->wake_cpu, pool->attrs->__pod_cpumask)) {
+ struct work_struct *work = list_first_entry(&pool->worklist,
+ struct work_struct, entry);
+- p->wake_cpu = cpumask_any_distribute(pool->attrs->__pod_cpumask);
+- get_work_pwq(work)->stats[PWQ_STAT_REPATRIATED]++;
++ int wake_cpu = cpumask_any_and_distribute(pool->attrs->__pod_cpumask,
++ cpu_online_mask);
++ if (wake_cpu < nr_cpu_ids) {
++ p->wake_cpu = wake_cpu;
++ get_work_pwq(work)->stats[PWQ_STAT_REPATRIATED]++;
++ }
+ }
+ #endif
+ wake_up_process(p);
+diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
+index ef36b829ae1f5..6352d59c57461 100644
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -375,7 +375,7 @@ config DEBUG_INFO_SPLIT
+ Incompatible with older versions of ccache.
+
+ config DEBUG_INFO_BTF
+- bool "Generate BTF typeinfo"
++ bool "Generate BTF type information"
+ depends on !DEBUG_INFO_SPLIT && !DEBUG_INFO_REDUCED
+ depends on !GCC_PLUGIN_RANDSTRUCT || COMPILE_TEST
+ depends on BPF_SYSCALL
+@@ -408,7 +408,8 @@ config PAHOLE_HAS_LANG_EXCLUDE
+ using DEBUG_INFO_BTF_MODULES.
+
+ config DEBUG_INFO_BTF_MODULES
+- def_bool y
++ bool "Generate BTF type information for kernel modules"
++ default y
+ depends on DEBUG_INFO_BTF && MODULES && PAHOLE_HAS_SPLIT_BTF
+ help
+ Generate compact split BTF type information for kernel modules.
+diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
+index 6fba6423cc10b..a5a687e1c9192 100644
+--- a/lib/dynamic_debug.c
++++ b/lib/dynamic_debug.c
+@@ -302,7 +302,11 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords)
+ } else {
+ for (end = buf; *end && !isspace(*end); end++)
+ ;
+- BUG_ON(end == buf);
++ if (end == buf) {
++ pr_err("parse err after word:%d=%s\n", nwords,
++ nwords ? words[nwords - 1] : "<none>");
++ return -EINVAL;
++ }
+ }
+
+ /* `buf' is start of word, `end' is one past its end */
+diff --git a/lib/maple_tree.c b/lib/maple_tree.c
+index 6f241bb387992..d70db05757091 100644
+--- a/lib/maple_tree.c
++++ b/lib/maple_tree.c
+@@ -5061,18 +5061,18 @@ int mas_empty_area_rev(struct ma_state *mas, unsigned long min,
+ if (size == 0 || max - min < size - 1)
+ return -EINVAL;
+
+- if (mas_is_start(mas)) {
++ if (mas_is_start(mas))
+ mas_start(mas);
+- mas->offset = mas_data_end(mas);
+- } else if (mas->offset >= 2) {
+- mas->offset -= 2;
+- } else if (!mas_rewind_node(mas)) {
++ else if ((mas->offset < 2) && (!mas_rewind_node(mas)))
+ return -EBUSY;
+- }
+
+- /* Empty set. */
+- if (mas_is_none(mas) || mas_is_ptr(mas))
++ if (unlikely(mas_is_none(mas) || mas_is_ptr(mas)))
+ return mas_sparse_area(mas, min, max, size, false);
++ else if (mas->offset >= 2)
++ mas->offset -= 2;
++ else
++ mas->offset = mas_data_end(mas);
++
+
+ /* The start of the window can only be within these values. */
+ mas->index = min;
+diff --git a/lib/scatterlist.c b/lib/scatterlist.c
+index 68b45c82c37a6..7bc2220fea805 100644
+--- a/lib/scatterlist.c
++++ b/lib/scatterlist.c
+@@ -1124,7 +1124,7 @@ static ssize_t extract_user_to_sg(struct iov_iter *iter,
+ do {
+ res = iov_iter_extract_pages(iter, &pages, maxsize, sg_max,
+ extraction_flags, &off);
+- if (res < 0)
++ if (res <= 0)
+ goto failed;
+
+ len = res;
+diff --git a/mm/readahead.c b/mm/readahead.c
+index 2648ec4f04947..89139a8721941 100644
+--- a/mm/readahead.c
++++ b/mm/readahead.c
+@@ -490,6 +490,7 @@ void page_cache_ra_order(struct readahead_control *ractl,
+ pgoff_t index = readahead_index(ractl);
+ pgoff_t limit = (i_size_read(mapping->host) - 1) >> PAGE_SHIFT;
+ pgoff_t mark = index + ra->size - ra->async_size;
++ unsigned int nofs;
+ int err = 0;
+ gfp_t gfp = readahead_gfp_mask(mapping);
+
+@@ -506,6 +507,8 @@ void page_cache_ra_order(struct readahead_control *ractl,
+ new_order--;
+ }
+
++ /* See comment in page_cache_ra_unbounded() */
++ nofs = memalloc_nofs_save();
+ filemap_invalidate_lock_shared(mapping);
+ while (index <= limit) {
+ unsigned int order = new_order;
+@@ -532,6 +535,7 @@ void page_cache_ra_order(struct readahead_control *ractl,
+
+ read_pages(ractl);
+ filemap_invalidate_unlock_shared(mapping);
++ memalloc_nofs_restore(nofs);
+
+ /*
+ * If there were already pages in the page cache, then we may have
+diff --git a/mm/slub.c b/mm/slub.c
+index 2ef88bbf56a37..914c35a7d4ef0 100644
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -557,6 +557,26 @@ static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
+ *(freeptr_t *)freeptr_addr = freelist_ptr_encode(s, fp, freeptr_addr);
+ }
+
++/*
++ * See comment in calculate_sizes().
++ */
++static inline bool freeptr_outside_object(struct kmem_cache *s)
++{
++ return s->offset >= s->inuse;
++}
++
++/*
++ * Return offset of the end of info block which is inuse + free pointer if
++ * not overlapping with object.
++ */
++static inline unsigned int get_info_end(struct kmem_cache *s)
++{
++ if (freeptr_outside_object(s))
++ return s->inuse + sizeof(void *);
++ else
++ return s->inuse;
++}
++
+ /* Loop over all objects in a slab */
+ #define for_each_object(__p, __s, __addr, __objects) \
+ for (__p = fixup_red_left(__s, __addr); \
+@@ -845,26 +865,6 @@ static void print_section(char *level, char *text, u8 *addr,
+ metadata_access_disable();
+ }
+
+-/*
+- * See comment in calculate_sizes().
+- */
+-static inline bool freeptr_outside_object(struct kmem_cache *s)
+-{
+- return s->offset >= s->inuse;
+-}
+-
+-/*
+- * Return offset of the end of info block which is inuse + free pointer if
+- * not overlapping with object.
+- */
+-static inline unsigned int get_info_end(struct kmem_cache *s)
+-{
+- if (freeptr_outside_object(s))
+- return s->inuse + sizeof(void *);
+- else
+- return s->inuse;
+-}
+-
+ static struct track *get_track(struct kmem_cache *s, void *object,
+ enum track_item alloc)
+ {
+@@ -2107,15 +2107,20 @@ bool slab_free_hook(struct kmem_cache *s, void *x, bool init)
+ *
+ * The initialization memset's clear the object and the metadata,
+ * but don't touch the SLAB redzone.
++ *
++ * The object's freepointer is also avoided if stored outside the
++ * object.
+ */
+ if (unlikely(init)) {
+ int rsize;
++ unsigned int inuse;
+
++ inuse = get_info_end(s);
+ if (!kasan_has_integrated_init())
+ memset(kasan_reset_tag(x), 0, s->object_size);
+ rsize = (s->flags & SLAB_RED_ZONE) ? s->red_left_pad : 0;
+- memset((char *)kasan_reset_tag(x) + s->inuse, 0,
+- s->size - s->inuse - rsize);
++ memset((char *)kasan_reset_tag(x) + inuse, 0,
++ s->size - inuse - rsize);
+ }
+ /* KASAN might put x into memory quarantine, delaying its reuse. */
+ return !kasan_slab_free(s, x, init);
+@@ -3737,7 +3742,8 @@ static void *__slab_alloc_node(struct kmem_cache *s,
+ static __always_inline void maybe_wipe_obj_freeptr(struct kmem_cache *s,
+ void *obj)
+ {
+- if (unlikely(slab_want_init_on_free(s)) && obj)
++ if (unlikely(slab_want_init_on_free(s)) && obj &&
++ !freeptr_outside_object(s))
+ memset((void *)((char *)kasan_reset_tag(obj) + s->offset),
+ 0, sizeof(void *));
+ }
+diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
+index f001582345052..9404dd551dfd2 100644
+--- a/net/8021q/vlan_core.c
++++ b/net/8021q/vlan_core.c
+@@ -478,6 +478,8 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,
+ if (unlikely(!vhdr))
+ goto out;
+
++ NAPI_GRO_CB(skb)->network_offsets[NAPI_GRO_CB(skb)->encap_mark] = hlen;
++
+ type = vhdr->h_vlan_encapsulated_proto;
+
+ ptype = gro_find_receive_by_type(type);
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index 0592369579ab2..befe645d3f9bf 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -2736,8 +2736,6 @@ void hci_unregister_dev(struct hci_dev *hdev)
+
+ hci_unregister_suspend_notifier(hdev);
+
+- msft_unregister(hdev);
+-
+ hci_dev_do_close(hdev);
+
+ if (!test_bit(HCI_INIT, &hdev->flags) &&
+@@ -2791,6 +2789,7 @@ void hci_release_dev(struct hci_dev *hdev)
+ hci_discovery_filter_clear(hdev);
+ hci_blocked_keys_clear(hdev);
+ hci_codec_list_clear(&hdev->local_codecs);
++ msft_release(hdev);
+ hci_dev_unlock(hdev);
+
+ ida_destroy(&hdev->unset_handle_ida);
+diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
+index 9d1063c51ed29..0f56ad33801e3 100644
+--- a/net/bluetooth/hci_event.c
++++ b/net/bluetooth/hci_event.c
+@@ -7181,6 +7181,8 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
+ u16 handle = le16_to_cpu(ev->bis[i]);
+
+ bis = hci_conn_hash_lookup_handle(hdev, handle);
++ if (!bis)
++ continue;
+
+ set_bit(HCI_CONN_BIG_SYNC_FAILED, &bis->flags);
+ hci_connect_cfm(bis, ev->status);
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 84fc70862d78a..5761d37c55376 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -415,6 +415,9 @@ static void l2cap_chan_timeout(struct work_struct *work)
+
+ BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
+
++ if (!conn)
++ return;
++
+ mutex_lock(&conn->chan_lock);
+ /* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
+ * this work. No need to call l2cap_chan_hold(chan) here again.
+diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c
+index 9612c5d1b13f6..d039683d3bdd4 100644
+--- a/net/bluetooth/msft.c
++++ b/net/bluetooth/msft.c
+@@ -769,7 +769,7 @@ void msft_register(struct hci_dev *hdev)
+ mutex_init(&msft->filter_lock);
+ }
+
+-void msft_unregister(struct hci_dev *hdev)
++void msft_release(struct hci_dev *hdev)
+ {
+ struct msft_data *msft = hdev->msft_data;
+
+diff --git a/net/bluetooth/msft.h b/net/bluetooth/msft.h
+index 2a63205b377b7..fe538e9c91c01 100644
+--- a/net/bluetooth/msft.h
++++ b/net/bluetooth/msft.h
+@@ -14,7 +14,7 @@
+
+ bool msft_monitor_supported(struct hci_dev *hdev);
+ void msft_register(struct hci_dev *hdev);
+-void msft_unregister(struct hci_dev *hdev);
++void msft_release(struct hci_dev *hdev);
+ void msft_do_open(struct hci_dev *hdev);
+ void msft_do_close(struct hci_dev *hdev);
+ void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb);
+@@ -35,7 +35,7 @@ static inline bool msft_monitor_supported(struct hci_dev *hdev)
+ }
+
+ static inline void msft_register(struct hci_dev *hdev) {}
+-static inline void msft_unregister(struct hci_dev *hdev) {}
++static inline void msft_release(struct hci_dev *hdev) {}
+ static inline void msft_do_open(struct hci_dev *hdev) {}
+ static inline void msft_do_close(struct hci_dev *hdev) {}
+ static inline void msft_vendor_evt(struct hci_dev *hdev, void *data,
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index 5d03c5440b06f..e0ad30862ee41 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -83,6 +83,10 @@ static void sco_sock_timeout(struct work_struct *work)
+ struct sock *sk;
+
+ sco_conn_lock(conn);
++ if (!conn->hcon) {
++ sco_conn_unlock(conn);
++ return;
++ }
+ sk = conn->sk;
+ if (sk)
+ sock_hold(sk);
+diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
+index 7431f89e897b9..d97064d460dc7 100644
+--- a/net/bridge/br_forward.c
++++ b/net/bridge/br_forward.c
+@@ -258,6 +258,7 @@ static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb,
+ {
+ struct net_device *dev = BR_INPUT_SKB_CB(skb)->brdev;
+ const unsigned char *src = eth_hdr(skb)->h_source;
++ struct sk_buff *nskb;
+
+ if (!should_deliver(p, skb))
+ return;
+@@ -266,12 +267,16 @@ static void maybe_deliver_addr(struct net_bridge_port *p, struct sk_buff *skb,
+ if (skb->dev == p->dev && ether_addr_equal(src, addr))
+ return;
+
+- skb = skb_copy(skb, GFP_ATOMIC);
+- if (!skb) {
++ __skb_push(skb, ETH_HLEN);
++ nskb = pskb_copy(skb, GFP_ATOMIC);
++ __skb_pull(skb, ETH_HLEN);
++ if (!nskb) {
+ DEV_STATS_INC(dev, tx_dropped);
+ return;
+ }
+
++ skb = nskb;
++ __skb_pull(skb, ETH_HLEN);
+ if (!is_broadcast_ether_addr(addr))
+ memcpy(eth_hdr(skb)->h_dest, addr, ETH_ALEN);
+
+diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
+index d415833fce91f..f17dbac7d8284 100644
+--- a/net/bridge/br_netlink.c
++++ b/net/bridge/br_netlink.c
+@@ -455,7 +455,8 @@ static int br_fill_ifinfo(struct sk_buff *skb,
+ u32 filter_mask, const struct net_device *dev,
+ bool getlink)
+ {
+- u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
++ u8 operstate = netif_running(dev) ? READ_ONCE(dev->operstate) :
++ IF_OPER_DOWN;
+ struct nlattr *af = NULL;
+ struct net_bridge *br;
+ struct ifinfomsg *hdr;
+diff --git a/net/core/filter.c b/net/core/filter.c
+index ef3e78b6a39c4..75cdaa16046bb 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -4360,10 +4360,12 @@ static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri,
+ enum bpf_map_type map_type = ri->map_type;
+ void *fwd = ri->tgt_value;
+ u32 map_id = ri->map_id;
++ u32 flags = ri->flags;
+ struct bpf_map *map;
+ int err;
+
+ ri->map_id = 0; /* Valid map id idr range: [1,INT_MAX[ */
++ ri->flags = 0;
+ ri->map_type = BPF_MAP_TYPE_UNSPEC;
+
+ if (unlikely(!xdpf)) {
+@@ -4375,11 +4377,20 @@ static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri,
+ case BPF_MAP_TYPE_DEVMAP:
+ fallthrough;
+ case BPF_MAP_TYPE_DEVMAP_HASH:
+- map = READ_ONCE(ri->map);
+- if (unlikely(map)) {
++ if (unlikely(flags & BPF_F_BROADCAST)) {
++ map = READ_ONCE(ri->map);
++
++ /* The map pointer is cleared when the map is being torn
++ * down by bpf_clear_redirect_map()
++ */
++ if (unlikely(!map)) {
++ err = -ENOENT;
++ break;
++ }
++
+ WRITE_ONCE(ri->map, NULL);
+ err = dev_map_enqueue_multi(xdpf, dev, map,
+- ri->flags & BPF_F_EXCLUDE_INGRESS);
++ flags & BPF_F_EXCLUDE_INGRESS);
+ } else {
+ err = dev_map_enqueue(fwd, xdpf, dev);
+ }
+@@ -4442,9 +4453,9 @@ EXPORT_SYMBOL_GPL(xdp_do_redirect_frame);
+ static int xdp_do_generic_redirect_map(struct net_device *dev,
+ struct sk_buff *skb,
+ struct xdp_buff *xdp,
+- struct bpf_prog *xdp_prog,
+- void *fwd,
+- enum bpf_map_type map_type, u32 map_id)
++ struct bpf_prog *xdp_prog, void *fwd,
++ enum bpf_map_type map_type, u32 map_id,
++ u32 flags)
+ {
+ struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
+ struct bpf_map *map;
+@@ -4454,11 +4465,20 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
+ case BPF_MAP_TYPE_DEVMAP:
+ fallthrough;
+ case BPF_MAP_TYPE_DEVMAP_HASH:
+- map = READ_ONCE(ri->map);
+- if (unlikely(map)) {
++ if (unlikely(flags & BPF_F_BROADCAST)) {
++ map = READ_ONCE(ri->map);
++
++ /* The map pointer is cleared when the map is being torn
++ * down by bpf_clear_redirect_map()
++ */
++ if (unlikely(!map)) {
++ err = -ENOENT;
++ break;
++ }
++
+ WRITE_ONCE(ri->map, NULL);
+ err = dev_map_redirect_multi(dev, skb, xdp_prog, map,
+- ri->flags & BPF_F_EXCLUDE_INGRESS);
++ flags & BPF_F_EXCLUDE_INGRESS);
+ } else {
+ err = dev_map_generic_redirect(fwd, skb, xdp_prog);
+ }
+@@ -4495,9 +4515,11 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
+ enum bpf_map_type map_type = ri->map_type;
+ void *fwd = ri->tgt_value;
+ u32 map_id = ri->map_id;
++ u32 flags = ri->flags;
+ int err;
+
+ ri->map_id = 0; /* Valid map id idr range: [1,INT_MAX[ */
++ ri->flags = 0;
+ ri->map_type = BPF_MAP_TYPE_UNSPEC;
+
+ if (map_type == BPF_MAP_TYPE_UNSPEC && map_id == INT_MAX) {
+@@ -4517,7 +4539,7 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
+ return 0;
+ }
+
+- return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog, fwd, map_type, map_id);
++ return xdp_do_generic_redirect_map(dev, skb, xdp, xdp_prog, fwd, map_type, map_id, flags);
+ err:
+ _trace_xdp_redirect_err(dev, xdp_prog, ri->tgt_index, err);
+ return err;
+diff --git a/net/core/gro.c b/net/core/gro.c
+index cefddf65f7db0..31e40f25fdf10 100644
+--- a/net/core/gro.c
++++ b/net/core/gro.c
+@@ -373,6 +373,7 @@ static inline void skb_gro_reset_offset(struct sk_buff *skb, u32 nhoff)
+ const struct skb_shared_info *pinfo = skb_shinfo(skb);
+ const skb_frag_t *frag0 = &pinfo->frags[0];
+
++ NAPI_GRO_CB(skb)->network_offset = 0;
+ NAPI_GRO_CB(skb)->data_offset = 0;
+ NAPI_GRO_CB(skb)->frag0 = NULL;
+ NAPI_GRO_CB(skb)->frag0_len = 0;
+diff --git a/net/core/link_watch.c b/net/core/link_watch.c
+index 429571c258da7..1b93e054c9a3c 100644
+--- a/net/core/link_watch.c
++++ b/net/core/link_watch.c
+@@ -67,7 +67,7 @@ static void rfc2863_policy(struct net_device *dev)
+ {
+ unsigned char operstate = default_operstate(dev);
+
+- if (operstate == dev->operstate)
++ if (operstate == READ_ONCE(dev->operstate))
+ return;
+
+ write_lock(&dev_base_lock);
+@@ -87,7 +87,7 @@ static void rfc2863_policy(struct net_device *dev)
+ break;
+ }
+
+- dev->operstate = operstate;
++ WRITE_ONCE(dev->operstate, operstate);
+
+ write_unlock(&dev_base_lock);
+ }
+diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
+index a09d507c5b03d..676048ae11831 100644
+--- a/net/core/net-sysfs.c
++++ b/net/core/net-sysfs.c
+@@ -318,11 +318,9 @@ static ssize_t operstate_show(struct device *dev,
+ const struct net_device *netdev = to_net_dev(dev);
+ unsigned char operstate;
+
+- read_lock(&dev_base_lock);
+- operstate = netdev->operstate;
++ operstate = READ_ONCE(netdev->operstate);
+ if (!netif_running(netdev))
+ operstate = IF_OPER_DOWN;
+- read_unlock(&dev_base_lock);
+
+ if (operstate >= ARRAY_SIZE(operstates))
+ return -EINVAL; /* should not happen */
+diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
+index 72799533426b6..b36444e3810c2 100644
+--- a/net/core/net_namespace.c
++++ b/net/core/net_namespace.c
+@@ -69,12 +69,15 @@ DEFINE_COOKIE(net_cookie);
+
+ static struct net_generic *net_alloc_generic(void)
+ {
++ unsigned int gen_ptrs = READ_ONCE(max_gen_ptrs);
++ unsigned int generic_size;
+ struct net_generic *ng;
+- unsigned int generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]);
++
++ generic_size = offsetof(struct net_generic, ptr[gen_ptrs]);
+
+ ng = kzalloc(generic_size, GFP_KERNEL);
+ if (ng)
+- ng->s.len = max_gen_ptrs;
++ ng->s.len = gen_ptrs;
+
+ return ng;
+ }
+@@ -1278,7 +1281,11 @@ static int register_pernet_operations(struct list_head *list,
+ if (error < 0)
+ return error;
+ *ops->id = error;
+- max_gen_ptrs = max(max_gen_ptrs, *ops->id + 1);
++ /* This does not require READ_ONCE as writers already hold
++ * pernet_ops_rwsem. But WRITE_ONCE is needed to protect
++ * net_alloc_generic.
++ */
++ WRITE_ONCE(max_gen_ptrs, max(max_gen_ptrs, *ops->id + 1));
+ }
+ error = __register_pernet_operations(list, ops);
+ if (error) {
+diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
+index bd50e9fe3234b..95e62235b5410 100644
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -875,9 +875,9 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
+ break;
+ }
+
+- if (dev->operstate != operstate) {
++ if (READ_ONCE(dev->operstate) != operstate) {
+ write_lock(&dev_base_lock);
+- dev->operstate = operstate;
++ WRITE_ONCE(dev->operstate, operstate);
+ write_unlock(&dev_base_lock);
+ netdev_state_change(dev);
+ }
+@@ -2552,7 +2552,7 @@ static int do_setvfinfo(struct net_device *dev, struct nlattr **tb)
+
+ nla_for_each_nested(attr, tb[IFLA_VF_VLAN_LIST], rem) {
+ if (nla_type(attr) != IFLA_VF_VLAN_INFO ||
+- nla_len(attr) < NLA_HDRLEN) {
++ nla_len(attr) < sizeof(struct ifla_vf_vlan_info)) {
+ return -EINVAL;
+ }
+ if (len >= MAX_VLAN_LIST_LEN)
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 71dee435d549d..570269c477549 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -2014,11 +2014,17 @@ static inline int skb_alloc_rx_flag(const struct sk_buff *skb)
+
+ struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
+ {
+- int headerlen = skb_headroom(skb);
+- unsigned int size = skb_end_offset(skb) + skb->data_len;
+- struct sk_buff *n = __alloc_skb(size, gfp_mask,
+- skb_alloc_rx_flag(skb), NUMA_NO_NODE);
++ struct sk_buff *n;
++ unsigned int size;
++ int headerlen;
++
++ if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
++ return NULL;
+
++ headerlen = skb_headroom(skb);
++ size = skb_end_offset(skb) + skb->data_len;
++ n = __alloc_skb(size, gfp_mask,
++ skb_alloc_rx_flag(skb), NUMA_NO_NODE);
+ if (!n)
+ return NULL;
+
+@@ -2346,12 +2352,17 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
+ /*
+ * Allocate the copy buffer
+ */
+- struct sk_buff *n = __alloc_skb(newheadroom + skb->len + newtailroom,
+- gfp_mask, skb_alloc_rx_flag(skb),
+- NUMA_NO_NODE);
+- int oldheadroom = skb_headroom(skb);
+ int head_copy_len, head_copy_off;
++ struct sk_buff *n;
++ int oldheadroom;
++
++ if (WARN_ON_ONCE(skb_shinfo(skb)->gso_type & SKB_GSO_FRAGLIST))
++ return NULL;
+
++ oldheadroom = skb_headroom(skb);
++ n = __alloc_skb(newheadroom + skb->len + newtailroom,
++ gfp_mask, skb_alloc_rx_flag(skb),
++ NUMA_NO_NODE);
+ if (!n)
+ return NULL;
+
+diff --git a/net/core/skmsg.c b/net/core/skmsg.c
+index 4d75ef9d24bfa..fd20aae30be23 100644
+--- a/net/core/skmsg.c
++++ b/net/core/skmsg.c
+@@ -1226,11 +1226,8 @@ static void sk_psock_verdict_data_ready(struct sock *sk)
+
+ rcu_read_lock();
+ psock = sk_psock(sk);
+- if (psock) {
+- read_lock_bh(&sk->sk_callback_lock);
++ if (psock)
+ sk_psock_data_ready(sk, psock);
+- read_unlock_bh(&sk->sk_callback_lock);
+- }
+ rcu_read_unlock();
+ }
+ }
+diff --git a/net/core/sock.c b/net/core/sock.c
+index 9cf404e8038a4..599f186fe3d3a 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -482,7 +482,7 @@ int __sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+ unsigned long flags;
+ struct sk_buff_head *list = &sk->sk_receive_queue;
+
+- if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) {
++ if (atomic_read(&sk->sk_rmem_alloc) >= READ_ONCE(sk->sk_rcvbuf)) {
+ atomic_inc(&sk->sk_drops);
+ trace_sock_rcvqueue_full(sk, skb);
+ return -ENOMEM;
+@@ -552,7 +552,7 @@ int __sk_receive_skb(struct sock *sk, struct sk_buff *skb,
+
+ skb->dev = NULL;
+
+- if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) {
++ if (sk_rcvqueues_full(sk, READ_ONCE(sk->sk_rcvbuf))) {
+ atomic_inc(&sk->sk_drops);
+ goto discard_and_relse;
+ }
+diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
+index 9d71b66183daf..03a42de7511e8 100644
+--- a/net/hsr/hsr_device.c
++++ b/net/hsr/hsr_device.c
+@@ -31,8 +31,8 @@ static bool is_slave_up(struct net_device *dev)
+ static void __hsr_set_operstate(struct net_device *dev, int transition)
+ {
+ write_lock(&dev_base_lock);
+- if (dev->operstate != transition) {
+- dev->operstate = transition;
++ if (READ_ONCE(dev->operstate) != transition) {
++ WRITE_ONCE(dev->operstate, transition);
+ write_unlock(&dev_base_lock);
+ netdev_state_change(dev);
+ } else {
+@@ -71,39 +71,36 @@ static bool hsr_check_carrier(struct hsr_port *master)
+ return false;
+ }
+
+-static void hsr_check_announce(struct net_device *hsr_dev,
+- unsigned char old_operstate)
++static void hsr_check_announce(struct net_device *hsr_dev)
+ {
+ struct hsr_priv *hsr;
+
+ hsr = netdev_priv(hsr_dev);
+-
+- if (hsr_dev->operstate == IF_OPER_UP && old_operstate != IF_OPER_UP) {
+- /* Went up */
+- hsr->announce_count = 0;
+- mod_timer(&hsr->announce_timer,
+- jiffies + msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL));
++ if (netif_running(hsr_dev) && netif_oper_up(hsr_dev)) {
++ /* Enable announce timer and start sending supervisory frames */
++ if (!timer_pending(&hsr->announce_timer)) {
++ hsr->announce_count = 0;
++ mod_timer(&hsr->announce_timer, jiffies +
++ msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL));
++ }
++ } else {
++ /* Deactivate the announce timer */
++ timer_delete(&hsr->announce_timer);
+ }
+-
+- if (hsr_dev->operstate != IF_OPER_UP && old_operstate == IF_OPER_UP)
+- /* Went down */
+- del_timer(&hsr->announce_timer);
+ }
+
+ void hsr_check_carrier_and_operstate(struct hsr_priv *hsr)
+ {
+ struct hsr_port *master;
+- unsigned char old_operstate;
+ bool has_carrier;
+
+ master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
+ /* netif_stacked_transfer_operstate() cannot be used here since
+ * it doesn't set IF_OPER_LOWERLAYERDOWN (?)
+ */
+- old_operstate = master->dev->operstate;
+ has_carrier = hsr_check_carrier(master);
+ hsr_set_operstate(master, has_carrier);
+- hsr_check_announce(master->dev, old_operstate);
++ hsr_check_announce(master->dev);
+ }
+
+ int hsr_get_max_mtu(struct hsr_priv *hsr)
+diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
+index a5a820ee20266..ce5c26cf1e2e8 100644
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -1571,6 +1571,7 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)
+ /* The above will be needed by the transport layer if there is one
+ * immediately following this IP hdr.
+ */
++ NAPI_GRO_CB(skb)->inner_network_offset = off;
+
+ /* Note : No need to call skb_gro_postpull_rcsum() here,
+ * as we already checked checksum over ipv4 header was 0
+diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
+index 67d846622365e..a38e63669c54a 100644
+--- a/net/ipv4/ip_output.c
++++ b/net/ipv4/ip_output.c
+@@ -1473,7 +1473,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
+ * by icmp_hdr(skb)->type.
+ */
+ if (sk->sk_type == SOCK_RAW &&
+- !inet_test_bit(HDRINCL, sk))
++ !(fl4->flowi4_flags & FLOWI_FLAG_KNOWN_NH))
+ icmp_type = fl4->fl4_icmp_type;
+ else
+ icmp_type = icmp_hdr(skb)->type;
+diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
+index 288f1846b3518..a1d8218fa1a2d 100644
+--- a/net/ipv4/raw.c
++++ b/net/ipv4/raw.c
+@@ -605,6 +605,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
+ daddr, saddr, 0, 0, sk->sk_uid);
+
++ fl4.fl4_icmp_type = 0;
++ fl4.fl4_icmp_code = 0;
++
+ if (!hdrincl) {
+ rfv.msg = msg;
+ rfv.hlen = 0;
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 5887eac87bd28..94b129301d38a 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -2709,7 +2709,7 @@ void tcp_shutdown(struct sock *sk, int how)
+ /* If we've already sent a FIN, or it's a closed state, skip this. */
+ if ((1 << sk->sk_state) &
+ (TCPF_ESTABLISHED | TCPF_SYN_SENT |
+- TCPF_SYN_RECV | TCPF_CLOSE_WAIT)) {
++ TCPF_CLOSE_WAIT)) {
+ /* Clear out any half completed packets. FIN if needed. */
+ if (tcp_close_state(sk))
+ tcp_send_fin(sk);
+@@ -2818,7 +2818,7 @@ void __tcp_close(struct sock *sk, long timeout)
+ * machine. State transitions:
+ *
+ * TCP_ESTABLISHED -> TCP_FIN_WAIT1
+- * TCP_SYN_RECV -> TCP_FIN_WAIT1 (forget it, it's impossible)
++ * TCP_SYN_RECV -> TCP_FIN_WAIT1 (it is difficult)
+ * TCP_CLOSE_WAIT -> TCP_LAST_ACK
+ *
+ * are legal only when FIN has been sent (i.e. in window),
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index df7b13f0e5e0d..ff10be8c76cf0 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -6752,6 +6752,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
+
+ tcp_initialize_rcv_mss(sk);
+ tcp_fast_path_on(tp);
++ if (sk->sk_shutdown & SEND_SHUTDOWN)
++ tcp_shutdown(sk, SEND_SHUTDOWN);
+ break;
+
+ case TCP_FIN_WAIT1: {
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 0c50c5a32b84a..68a065c0e5081 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -154,6 +154,12 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
+ if (tcptw->tw_ts_recent_stamp &&
+ (!twp || (reuse && time_after32(ktime_get_seconds(),
+ tcptw->tw_ts_recent_stamp)))) {
++ /* inet_twsk_hashdance() sets sk_refcnt after putting twsk
++ * and releasing the bucket lock.
++ */
++ if (unlikely(!refcount_inc_not_zero(&sktw->sk_refcnt)))
++ return 0;
++
+ /* In case of repair and re-using TIME-WAIT sockets we still
+ * want to be sure that it is safe as above but honor the
+ * sequence numbers and time stamps set as part of the repair
+@@ -174,7 +180,7 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
+ tp->rx_opt.ts_recent = tcptw->tw_ts_recent;
+ tp->rx_opt.ts_recent_stamp = tcptw->tw_ts_recent_stamp;
+ }
+- sock_hold(sktw);
++
+ return 1;
+ }
+
+diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
+index e3167ad965676..02caeb7bcf634 100644
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -3563,7 +3563,9 @@ void tcp_send_fin(struct sock *sk)
+ return;
+ }
+ } else {
+- skb = alloc_skb_fclone(MAX_TCP_HEADER, sk->sk_allocation);
++ skb = alloc_skb_fclone(MAX_TCP_HEADER,
++ sk_gfp_mask(sk, GFP_ATOMIC |
++ __GFP_NOWARN));
+ if (unlikely(!skb))
+ return;
+
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 40282a34180ca..9120694359af4 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -534,7 +534,8 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
+ struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
+ __be16 sport, __be16 dport)
+ {
+- const struct iphdr *iph = ip_hdr(skb);
++ const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
++ const struct iphdr *iph = (struct iphdr *)(skb->data + offset);
+ struct net *net = dev_net(skb->dev);
+ int iif, sdif;
+
+diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
+index c3d67423ae189..e5971890d637d 100644
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -471,6 +471,7 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head,
+ struct sk_buff *p;
+ unsigned int ulen;
+ int ret = 0;
++ int flush;
+
+ /* requires non zero csum, for symmetry with GSO */
+ if (!uh->check) {
+@@ -504,13 +505,22 @@ static struct sk_buff *udp_gro_receive_segment(struct list_head *head,
+ return p;
+ }
+
++ flush = NAPI_GRO_CB(p)->flush;
++
++ if (NAPI_GRO_CB(p)->flush_id != 1 ||
++ NAPI_GRO_CB(p)->count != 1 ||
++ !NAPI_GRO_CB(p)->is_atomic)
++ flush |= NAPI_GRO_CB(p)->flush_id;
++ else
++ NAPI_GRO_CB(p)->is_atomic = false;
++
+ /* Terminate the flow on len mismatch or if it grow "too much".
+ * Under small packet flood GRO count could elsewhere grow a lot
+ * leading to excessive truesize values.
+ * On len mismatch merge the first packet shorter than gso_size,
+ * otherwise complete the GRO packet.
+ */
+- if (ulen > ntohs(uh2->len)) {
++ if (ulen > ntohs(uh2->len) || flush) {
+ pp = p;
+ } else {
+ if (NAPI_GRO_CB(skb)->is_flist) {
+@@ -718,7 +728,8 @@ EXPORT_SYMBOL(udp_gro_complete);
+
+ INDIRECT_CALLABLE_SCOPE int udp4_gro_complete(struct sk_buff *skb, int nhoff)
+ {
+- const struct iphdr *iph = ip_hdr(skb);
++ const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
++ const struct iphdr *iph = (struct iphdr *)(skb->data + offset);
+ struct udphdr *uh = (struct udphdr *)(skb->data + nhoff);
+
+ /* do fraglist only if there is no outer UDP encap (or we already processed it) */
+diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c
+index c54676998eb60..801404f7d6574 100644
+--- a/net/ipv4/xfrm4_input.c
++++ b/net/ipv4/xfrm4_input.c
+@@ -63,7 +63,11 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async)
+ ip_send_check(iph);
+
+ if (xo && (xo->flags & XFRM_GRO)) {
+- skb_mac_header_rebuild(skb);
++ /* The full l2 header needs to be preserved so that re-injecting the packet at l2
++ * works correctly in the presence of vlan tags.
++ */
++ skb_mac_header_rebuild_full(skb, xo->orig_mac_len);
++ skb_reset_network_header(skb);
+ skb_reset_transport_header(skb);
+ return 0;
+ }
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index 37d48aa073c3c..c4e2f9d35e687 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -4164,7 +4164,7 @@ static void addrconf_dad_work(struct work_struct *w)
+ if (!ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) &&
+ ipv6_addr_equal(&ifp->addr, &addr)) {
+ /* DAD failed for link-local based on MAC */
+- idev->cnf.disable_ipv6 = 1;
++ WRITE_ONCE(idev->cnf.disable_ipv6, 1);
+
+ pr_info("%s: IPv6 being disabled!\n",
+ ifp->idev->dev->name);
+@@ -6015,7 +6015,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
+ (dev->ifindex != dev_get_iflink(dev) &&
+ nla_put_u32(skb, IFLA_LINK, dev_get_iflink(dev))) ||
+ nla_put_u8(skb, IFLA_OPERSTATE,
+- netif_running(dev) ? dev->operstate : IF_OPER_DOWN))
++ netif_running(dev) ? READ_ONCE(dev->operstate) : IF_OPER_DOWN))
+ goto nla_put_failure;
+ protoinfo = nla_nest_start_noflag(skb, IFLA_PROTINFO);
+ if (!protoinfo)
+@@ -6325,7 +6325,8 @@ static void addrconf_disable_change(struct net *net, __s32 newf)
+ idev = __in6_dev_get(dev);
+ if (idev) {
+ int changed = (!idev->cnf.disable_ipv6) ^ (!newf);
+- idev->cnf.disable_ipv6 = newf;
++
++ WRITE_ONCE(idev->cnf.disable_ipv6, newf);
+ if (changed)
+ dev_disable_change(idev);
+ }
+@@ -6342,7 +6343,7 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
+
+ net = (struct net *)table->extra2;
+ old = *p;
+- *p = newf;
++ WRITE_ONCE(*p, newf);
+
+ if (p == &net->ipv6.devconf_dflt->disable_ipv6) {
+ rtnl_unlock();
+@@ -6350,7 +6351,7 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
+ }
+
+ if (p == &net->ipv6.devconf_all->disable_ipv6) {
+- net->ipv6.devconf_dflt->disable_ipv6 = newf;
++ WRITE_ONCE(net->ipv6.devconf_dflt->disable_ipv6, newf);
+ addrconf_disable_change(net, newf);
+ } else if ((!newf) ^ (!old))
+ dev_disable_change((struct inet6_dev *)table->extra1);
+diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
+index 52c04f0ac4981..9e254de7462fb 100644
+--- a/net/ipv6/fib6_rules.c
++++ b/net/ipv6/fib6_rules.c
+@@ -233,8 +233,12 @@ static int __fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
+ rt = pol_lookup_func(lookup,
+ net, table, flp6, arg->lookup_data, flags);
+ if (rt != net->ipv6.ip6_null_entry) {
++ struct inet6_dev *idev = ip6_dst_idev(&rt->dst);
++
++ if (!idev)
++ goto again;
+ err = fib6_rule_saddr(net, rule, flags, flp6,
+- ip6_dst_idev(&rt->dst)->dev);
++ idev->dev);
+
+ if (err == -EAGAIN)
+ goto again;
+diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
+index b8378814532ce..1ba97933c74fb 100644
+--- a/net/ipv6/ip6_input.c
++++ b/net/ipv6/ip6_input.c
+@@ -168,9 +168,9 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev,
+
+ SKB_DR_SET(reason, NOT_SPECIFIED);
+ if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
+- !idev || unlikely(idev->cnf.disable_ipv6)) {
++ !idev || unlikely(READ_ONCE(idev->cnf.disable_ipv6))) {
+ __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
+- if (idev && unlikely(idev->cnf.disable_ipv6))
++ if (idev && unlikely(READ_ONCE(idev->cnf.disable_ipv6)))
+ SKB_DR_SET(reason, IPV6DISABLED);
+ goto drop;
+ }
+diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
+index cca64c7809bee..19ae2d4cd2021 100644
+--- a/net/ipv6/ip6_offload.c
++++ b/net/ipv6/ip6_offload.c
+@@ -237,6 +237,7 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head,
+ goto out;
+
+ skb_set_network_header(skb, off);
++ NAPI_GRO_CB(skb)->inner_network_offset = off;
+
+ flush += ntohs(iph->payload_len) != skb->len - hlen;
+
+diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
+index 31b86fe661aa6..51b358f6c3918 100644
+--- a/net/ipv6/ip6_output.c
++++ b/net/ipv6/ip6_output.c
+@@ -234,7 +234,7 @@ int ip6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
+ skb->protocol = htons(ETH_P_IPV6);
+ skb->dev = dev;
+
+- if (unlikely(idev->cnf.disable_ipv6)) {
++ if (unlikely(!idev || READ_ONCE(idev->cnf.disable_ipv6))) {
+ IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS);
+ kfree_skb_reason(skb, SKB_DROP_REASON_IPV6DISABLED);
+ return 0;
+@@ -1933,7 +1933,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
+ u8 icmp6_type;
+
+ if (sk->sk_socket->type == SOCK_RAW &&
+- !inet_test_bit(HDRINCL, sk))
++ !(fl6->flowi6_flags & FLOWI_FLAG_KNOWN_NH))
+ icmp6_type = fl6->fl6_icmp_type;
+ else
+ icmp6_type = icmp6_hdr(skb)->icmp6_type;
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index 8c14c4cc82ff7..785b2d076a6b3 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -275,7 +275,8 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb,
+ struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
+ __be16 sport, __be16 dport)
+ {
+- const struct ipv6hdr *iph = ipv6_hdr(skb);
++ const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
++ const struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + offset);
+ struct net *net = dev_net(skb->dev);
+ int iif, sdif;
+
+diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
+index 626d7b362dc7b..639a4b506f9b5 100644
+--- a/net/ipv6/udp_offload.c
++++ b/net/ipv6/udp_offload.c
+@@ -164,7 +164,8 @@ struct sk_buff *udp6_gro_receive(struct list_head *head, struct sk_buff *skb)
+
+ INDIRECT_CALLABLE_SCOPE int udp6_gro_complete(struct sk_buff *skb, int nhoff)
+ {
+- const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
++ const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
++ const struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + offset);
+ struct udphdr *uh = (struct udphdr *)(skb->data + nhoff);
+
+ /* do fraglist only if there is no outer UDP encap (or we already processed it) */
+diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
+index 6e36e5047fbab..4e6dcefd635c8 100644
+--- a/net/ipv6/xfrm6_input.c
++++ b/net/ipv6/xfrm6_input.c
+@@ -58,7 +58,11 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
+ skb_postpush_rcsum(skb, skb_network_header(skb), nhlen);
+
+ if (xo && (xo->flags & XFRM_GRO)) {
+- skb_mac_header_rebuild(skb);
++ /* The full l2 header needs to be preserved so that re-injecting the packet at l2
++ * works correctly in the presence of vlan tags.
++ */
++ skb_mac_header_rebuild_full(skb, xo->orig_mac_len);
++ skb_reset_network_header(skb);
+ skb_reset_transport_header(skb);
+ return 0;
+ }
+diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
+index 25ca89f804145..9dacfa91acc78 100644
+--- a/net/l2tp/l2tp_eth.c
++++ b/net/l2tp/l2tp_eth.c
+@@ -127,6 +127,9 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb,
+ /* checksums verified by L2TP */
+ skb->ip_summed = CHECKSUM_NONE;
+
++ /* drop outer flow-hash */
++ skb_clear_hash(skb);
++
+ skb_dst_drop(skb);
+ nf_reset_ct(skb);
+
+diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
+index a18361afea249..399fcb66658da 100644
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -131,7 +131,7 @@ struct ieee80211_bss {
+ };
+
+ /**
+- * enum ieee80211_corrupt_data_flags - BSS data corruption flags
++ * enum ieee80211_bss_corrupt_data_flags - BSS data corruption flags
+ * @IEEE80211_BSS_CORRUPT_BEACON: last beacon frame received was corrupted
+ * @IEEE80211_BSS_CORRUPT_PROBE_RESP: last probe response received was corrupted
+ *
+@@ -144,7 +144,7 @@ enum ieee80211_bss_corrupt_data_flags {
+ };
+
+ /**
+- * enum ieee80211_valid_data_flags - BSS valid data flags
++ * enum ieee80211_bss_valid_data_flags - BSS valid data flags
+ * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE
+ * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE
+ * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 94028b541beba..ac0073c8f96f4 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -7294,7 +7294,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
+ sdata_info(sdata,
+ "failed to insert STA entry for the AP (error %d)\n",
+ err);
+- goto out_err;
++ goto out_release_chan;
+ }
+ } else
+ WARN_ON_ONCE(!ether_addr_equal(link->u.mgd.bssid, cbss->bssid));
+@@ -7305,8 +7305,9 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
+
+ return 0;
+
++out_release_chan:
++ ieee80211_link_release_channel(link);
+ out_err:
+- ieee80211_link_release_channel(&sdata->deflink);
+ ieee80211_vif_set_links(sdata, 0, 0);
+ return err;
+ }
+diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c
+index 13fe0748dde83..2963ba84e2ee4 100644
+--- a/net/mptcp/ctrl.c
++++ b/net/mptcp/ctrl.c
+@@ -96,6 +96,43 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
+ }
+
+ #ifdef CONFIG_SYSCTL
++static int mptcp_set_scheduler(const struct net *net, const char *name)
++{
++ struct mptcp_pernet *pernet = mptcp_get_pernet(net);
++ struct mptcp_sched_ops *sched;
++ int ret = 0;
++
++ rcu_read_lock();
++ sched = mptcp_sched_find(name);
++ if (sched)
++ strscpy(pernet->scheduler, name, MPTCP_SCHED_NAME_MAX);
++ else
++ ret = -ENOENT;
++ rcu_read_unlock();
++
++ return ret;
++}
++
++static int proc_scheduler(struct ctl_table *ctl, int write,
++ void *buffer, size_t *lenp, loff_t *ppos)
++{
++ const struct net *net = current->nsproxy->net_ns;
++ char val[MPTCP_SCHED_NAME_MAX];
++ struct ctl_table tbl = {
++ .data = val,
++ .maxlen = MPTCP_SCHED_NAME_MAX,
++ };
++ int ret;
++
++ strscpy(val, mptcp_get_scheduler(net), MPTCP_SCHED_NAME_MAX);
++
++ ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
++ if (write && ret == 0)
++ ret = mptcp_set_scheduler(net, val);
++
++ return ret;
++}
++
+ static struct ctl_table mptcp_sysctl_table[] = {
+ {
+ .procname = "enabled",
+@@ -148,7 +185,7 @@ static struct ctl_table mptcp_sysctl_table[] = {
+ .procname = "scheduler",
+ .maxlen = MPTCP_SCHED_NAME_MAX,
+ .mode = 0644,
+- .proc_handler = proc_dostring,
++ .proc_handler = proc_scheduler,
+ },
+ {
+ .procname = "close_timeout",
+diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
+index 2b921af2718d9..74c1faec271d1 100644
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -3703,6 +3703,9 @@ static int mptcp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+ MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_TOKENFALLBACKINIT);
+ mptcp_subflow_early_fallback(msk, subflow);
+ }
++
++ WRITE_ONCE(msk->write_seq, subflow->idsn);
++ WRITE_ONCE(msk->snd_nxt, subflow->idsn);
+ if (likely(!__mptcp_check_fallback(msk)))
+ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVE);
+
+diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
+index 819157bbb5a2c..d5344563e525c 100644
+--- a/net/nfc/llcp_sock.c
++++ b/net/nfc/llcp_sock.c
+@@ -252,10 +252,10 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = copy_safe_from_sockptr(&opt, sizeof(opt),
++ optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt > LLCP_MAX_RW) {
+ err = -EINVAL;
+@@ -274,10 +274,10 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname,
+ break;
+ }
+
+- if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+- err = -EFAULT;
++ err = copy_safe_from_sockptr(&opt, sizeof(opt),
++ optval, optlen);
++ if (err)
+ break;
+- }
+
+ if (opt > LLCP_MAX_MIUX) {
+ err = -EINVAL;
+diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
+index 0d26c8ec9993e..b133dc55304ce 100644
+--- a/net/nfc/nci/core.c
++++ b/net/nfc/nci/core.c
+@@ -1518,6 +1518,7 @@ static void nci_rx_work(struct work_struct *work)
+
+ if (!nci_plen(skb->data)) {
+ kfree_skb(skb);
++ kcov_remote_stop();
+ break;
+ }
+
+diff --git a/net/nsh/nsh.c b/net/nsh/nsh.c
+index f4a38bd6a7e04..bfb7758063f31 100644
+--- a/net/nsh/nsh.c
++++ b/net/nsh/nsh.c
+@@ -77,13 +77,15 @@ EXPORT_SYMBOL_GPL(nsh_pop);
+ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
+ netdev_features_t features)
+ {
++ unsigned int outer_hlen, mac_len, nsh_len;
+ struct sk_buff *segs = ERR_PTR(-EINVAL);
+ u16 mac_offset = skb->mac_header;
+- unsigned int nsh_len, mac_len;
+- __be16 proto;
++ __be16 outer_proto, proto;
+
+ skb_reset_network_header(skb);
+
++ outer_proto = skb->protocol;
++ outer_hlen = skb_mac_header_len(skb);
+ mac_len = skb->mac_len;
+
+ if (unlikely(!pskb_may_pull(skb, NSH_BASE_HDR_LEN)))
+@@ -113,10 +115,10 @@ static struct sk_buff *nsh_gso_segment(struct sk_buff *skb,
+ }
+
+ for (skb = segs; skb; skb = skb->next) {
+- skb->protocol = htons(ETH_P_NSH);
+- __skb_push(skb, nsh_len);
+- skb->mac_header = mac_offset;
+- skb->network_header = skb->mac_header + mac_len;
++ skb->protocol = outer_proto;
++ __skb_push(skb, nsh_len + outer_hlen);
++ skb_reset_mac_header(skb);
++ skb_set_network_header(skb, outer_hlen);
+ skb->mac_len = mac_len;
+ }
+
+diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
+index 59aebe2968907..dd4c7e9a634fb 100644
+--- a/net/phonet/pn_netlink.c
++++ b/net/phonet/pn_netlink.c
+@@ -193,7 +193,7 @@ void rtm_phonet_notify(int event, struct net_device *dev, u8 dst)
+ struct sk_buff *skb;
+ int err = -ENOBUFS;
+
+- skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
++ skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct rtmsg)) +
+ nla_total_size(1) + nla_total_size(4), GFP_KERNEL);
+ if (skb == NULL)
+ goto errout;
+diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
+index 7818aae1be8e0..4301dd20b4eaa 100644
+--- a/net/rxrpc/ar-internal.h
++++ b/net/rxrpc/ar-internal.h
+@@ -692,7 +692,7 @@ struct rxrpc_call {
+ * packets) rather than bytes.
+ */
+ #define RXRPC_TX_SMSS RXRPC_JUMBO_DATALEN
+-#define RXRPC_MIN_CWND (RXRPC_TX_SMSS > 2190 ? 2 : RXRPC_TX_SMSS > 1095 ? 3 : 4)
++#define RXRPC_MIN_CWND 4
+ u8 cong_cwnd; /* Congestion window size */
+ u8 cong_extra; /* Extra to send for congestion management */
+ u8 cong_ssthresh; /* Slow-start threshold */
+diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
+index 9fc9a6c3f6858..3847b14af7f3c 100644
+--- a/net/rxrpc/call_object.c
++++ b/net/rxrpc/call_object.c
+@@ -175,12 +175,7 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp,
+ call->rx_winsize = rxrpc_rx_window_size;
+ call->tx_winsize = 16;
+
+- if (RXRPC_TX_SMSS > 2190)
+- call->cong_cwnd = 2;
+- else if (RXRPC_TX_SMSS > 1095)
+- call->cong_cwnd = 3;
+- else
+- call->cong_cwnd = 4;
++ call->cong_cwnd = RXRPC_MIN_CWND;
+ call->cong_ssthresh = RXRPC_TX_MAX_WINDOW;
+
+ call->rxnet = rxnet;
+diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
+index 1f251d758cb9d..598b4ee389fc1 100644
+--- a/net/rxrpc/conn_event.c
++++ b/net/rxrpc/conn_event.c
+@@ -88,7 +88,7 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
+ struct rxrpc_ackpacket ack;
+ };
+ } __attribute__((packed)) pkt;
+- struct rxrpc_ackinfo ack_info;
++ struct rxrpc_acktrailer trailer;
+ size_t len;
+ int ret, ioc;
+ u32 serial, mtu, call_id, padding;
+@@ -122,8 +122,8 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
+ iov[0].iov_len = sizeof(pkt.whdr);
+ iov[1].iov_base = &padding;
+ iov[1].iov_len = 3;
+- iov[2].iov_base = &ack_info;
+- iov[2].iov_len = sizeof(ack_info);
++ iov[2].iov_base = &trailer;
++ iov[2].iov_len = sizeof(trailer);
+
+ serial = rxrpc_get_next_serial(conn);
+
+@@ -158,14 +158,14 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
+ pkt.ack.serial = htonl(skb ? sp->hdr.serial : 0);
+ pkt.ack.reason = skb ? RXRPC_ACK_DUPLICATE : RXRPC_ACK_IDLE;
+ pkt.ack.nAcks = 0;
+- ack_info.rxMTU = htonl(rxrpc_rx_mtu);
+- ack_info.maxMTU = htonl(mtu);
+- ack_info.rwind = htonl(rxrpc_rx_window_size);
+- ack_info.jumbo_max = htonl(rxrpc_rx_jumbo_max);
++ trailer.maxMTU = htonl(rxrpc_rx_mtu);
++ trailer.ifMTU = htonl(mtu);
++ trailer.rwind = htonl(rxrpc_rx_window_size);
++ trailer.jumbo_max = htonl(rxrpc_rx_jumbo_max);
+ pkt.whdr.flags |= RXRPC_SLOW_START_OK;
+ padding = 0;
+ iov[0].iov_len += sizeof(pkt.ack);
+- len += sizeof(pkt.ack) + 3 + sizeof(ack_info);
++ len += sizeof(pkt.ack) + 3 + sizeof(trailer);
+ ioc = 3;
+
+ trace_rxrpc_tx_ack(chan->call_debug_id, serial,
+diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
+index df8a271948a1c..7aa58129ae455 100644
+--- a/net/rxrpc/conn_object.c
++++ b/net/rxrpc/conn_object.c
+@@ -118,18 +118,13 @@ struct rxrpc_connection *rxrpc_find_client_connection_rcu(struct rxrpc_local *lo
+ switch (srx->transport.family) {
+ case AF_INET:
+ if (peer->srx.transport.sin.sin_port !=
+- srx->transport.sin.sin_port ||
+- peer->srx.transport.sin.sin_addr.s_addr !=
+- srx->transport.sin.sin_addr.s_addr)
++ srx->transport.sin.sin_port)
+ goto not_found;
+ break;
+ #ifdef CONFIG_AF_RXRPC_IPV6
+ case AF_INET6:
+ if (peer->srx.transport.sin6.sin6_port !=
+- srx->transport.sin6.sin6_port ||
+- memcmp(&peer->srx.transport.sin6.sin6_addr,
+- &srx->transport.sin6.sin6_addr,
+- sizeof(struct in6_addr)) != 0)
++ srx->transport.sin6.sin6_port)
+ goto not_found;
+ break;
+ #endif
+diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
+index 9691de00ade75..5dfda1ac51dda 100644
+--- a/net/rxrpc/input.c
++++ b/net/rxrpc/input.c
+@@ -9,6 +9,17 @@
+
+ #include "ar-internal.h"
+
++/* Override priority when generating ACKs for received DATA */
++static const u8 rxrpc_ack_priority[RXRPC_ACK__INVALID] = {
++ [RXRPC_ACK_IDLE] = 1,
++ [RXRPC_ACK_DELAY] = 2,
++ [RXRPC_ACK_REQUESTED] = 3,
++ [RXRPC_ACK_DUPLICATE] = 4,
++ [RXRPC_ACK_EXCEEDS_WINDOW] = 5,
++ [RXRPC_ACK_NOSPACE] = 6,
++ [RXRPC_ACK_OUT_OF_SEQUENCE] = 7,
++};
++
+ static void rxrpc_proto_abort(struct rxrpc_call *call, rxrpc_seq_t seq,
+ enum rxrpc_abort_reason why)
+ {
+@@ -366,7 +377,7 @@ static void rxrpc_input_queue_data(struct rxrpc_call *call, struct sk_buff *skb,
+ * Process a DATA packet.
+ */
+ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
+- bool *_notify)
++ bool *_notify, rxrpc_serial_t *_ack_serial, int *_ack_reason)
+ {
+ struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+ struct sk_buff *oos;
+@@ -419,8 +430,6 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
+ /* Send an immediate ACK if we fill in a hole */
+ else if (!skb_queue_empty(&call->rx_oos_queue))
+ ack_reason = RXRPC_ACK_DELAY;
+- else
+- call->ackr_nr_unacked++;
+
+ window++;
+ if (after(window, wtop)) {
+@@ -498,12 +507,16 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
+ }
+
+ send_ack:
+- if (ack_reason >= 0)
+- rxrpc_send_ACK(call, ack_reason, serial,
+- rxrpc_propose_ack_input_data);
+- else
+- rxrpc_propose_delay_ACK(call, serial,
+- rxrpc_propose_ack_input_data);
++ if (ack_reason >= 0) {
++ if (rxrpc_ack_priority[ack_reason] > rxrpc_ack_priority[*_ack_reason]) {
++ *_ack_serial = serial;
++ *_ack_reason = ack_reason;
++ } else if (rxrpc_ack_priority[ack_reason] == rxrpc_ack_priority[*_ack_reason] &&
++ ack_reason == RXRPC_ACK_REQUESTED) {
++ *_ack_serial = serial;
++ *_ack_reason = ack_reason;
++ }
++ }
+ }
+
+ /*
+@@ -514,9 +527,11 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb
+ struct rxrpc_jumbo_header jhdr;
+ struct rxrpc_skb_priv *sp = rxrpc_skb(skb), *jsp;
+ struct sk_buff *jskb;
++ rxrpc_serial_t ack_serial = 0;
+ unsigned int offset = sizeof(struct rxrpc_wire_header);
+ unsigned int len = skb->len - offset;
+ bool notify = false;
++ int ack_reason = 0;
+
+ while (sp->hdr.flags & RXRPC_JUMBO_PACKET) {
+ if (len < RXRPC_JUMBO_SUBPKTLEN)
+@@ -536,7 +551,7 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb
+ jsp = rxrpc_skb(jskb);
+ jsp->offset = offset;
+ jsp->len = RXRPC_JUMBO_DATALEN;
+- rxrpc_input_data_one(call, jskb, ¬ify);
++ rxrpc_input_data_one(call, jskb, ¬ify, &ack_serial, &ack_reason);
+ rxrpc_free_skb(jskb, rxrpc_skb_put_jumbo_subpacket);
+
+ sp->hdr.flags = jhdr.flags;
+@@ -549,7 +564,16 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb
+
+ sp->offset = offset;
+ sp->len = len;
+- rxrpc_input_data_one(call, skb, ¬ify);
++ rxrpc_input_data_one(call, skb, ¬ify, &ack_serial, &ack_reason);
++
++ if (ack_reason > 0) {
++ rxrpc_send_ACK(call, ack_reason, ack_serial,
++ rxrpc_propose_ack_input_data);
++ } else {
++ call->ackr_nr_unacked++;
++ rxrpc_propose_delay_ACK(call, sp->hdr.serial,
++ rxrpc_propose_ack_input_data);
++ }
+ if (notify) {
+ trace_rxrpc_notify_socket(call->debug_id, sp->hdr.serial);
+ rxrpc_notify_socket(call);
+@@ -670,14 +694,14 @@ static void rxrpc_complete_rtt_probe(struct rxrpc_call *call,
+ /*
+ * Process the extra information that may be appended to an ACK packet
+ */
+-static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
+- struct rxrpc_ackinfo *ackinfo)
++static void rxrpc_input_ack_trailer(struct rxrpc_call *call, struct sk_buff *skb,
++ struct rxrpc_acktrailer *trailer)
+ {
+ struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+ struct rxrpc_peer *peer;
+ unsigned int mtu;
+ bool wake = false;
+- u32 rwind = ntohl(ackinfo->rwind);
++ u32 rwind = ntohl(trailer->rwind);
+
+ if (rwind > RXRPC_TX_MAX_WINDOW)
+ rwind = RXRPC_TX_MAX_WINDOW;
+@@ -688,10 +712,7 @@ static void rxrpc_input_ackinfo(struct rxrpc_call *call, struct sk_buff *skb,
+ call->tx_winsize = rwind;
+ }
+
+- if (call->cong_ssthresh > rwind)
+- call->cong_ssthresh = rwind;
+-
+- mtu = min(ntohl(ackinfo->rxMTU), ntohl(ackinfo->maxMTU));
++ mtu = min(ntohl(trailer->maxMTU), ntohl(trailer->ifMTU));
+
+ peer = call->peer;
+ if (mtu < peer->maxdata) {
+@@ -837,7 +858,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
+ struct rxrpc_ack_summary summary = { 0 };
+ struct rxrpc_ackpacket ack;
+ struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+- struct rxrpc_ackinfo info;
++ struct rxrpc_acktrailer trailer;
+ rxrpc_serial_t ack_serial, acked_serial;
+ rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt, since;
+ int nr_acks, offset, ioffset;
+@@ -917,11 +938,11 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
+ goto send_response;
+ }
+
+- info.rxMTU = 0;
++ trailer.maxMTU = 0;
+ ioffset = offset + nr_acks + 3;
+- if (skb->len >= ioffset + sizeof(info) &&
+- skb_copy_bits(skb, ioffset, &info, sizeof(info)) < 0)
+- return rxrpc_proto_abort(call, 0, rxrpc_badmsg_short_ack_info);
++ if (skb->len >= ioffset + sizeof(trailer) &&
++ skb_copy_bits(skb, ioffset, &trailer, sizeof(trailer)) < 0)
++ return rxrpc_proto_abort(call, 0, rxrpc_badmsg_short_ack_trailer);
+
+ if (nr_acks > 0)
+ skb_condense(skb);
+@@ -950,8 +971,8 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
+ }
+
+ /* Parse rwind and mtu sizes if provided. */
+- if (info.rxMTU)
+- rxrpc_input_ackinfo(call, skb, &info);
++ if (trailer.maxMTU)
++ rxrpc_input_ack_trailer(call, skb, &trailer);
+
+ if (first_soft_ack == 0)
+ return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_zero);
+diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
+index 4a292f860ae37..cad6a7d18e040 100644
+--- a/net/rxrpc/output.c
++++ b/net/rxrpc/output.c
+@@ -83,7 +83,7 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn,
+ struct rxrpc_txbuf *txb,
+ u16 *_rwind)
+ {
+- struct rxrpc_ackinfo ackinfo;
++ struct rxrpc_acktrailer trailer;
+ unsigned int qsize, sack, wrap, to;
+ rxrpc_seq_t window, wtop;
+ int rsize;
+@@ -126,16 +126,16 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn,
+ qsize = (window - 1) - call->rx_consumed;
+ rsize = max_t(int, call->rx_winsize - qsize, 0);
+ *_rwind = rsize;
+- ackinfo.rxMTU = htonl(rxrpc_rx_mtu);
+- ackinfo.maxMTU = htonl(mtu);
+- ackinfo.rwind = htonl(rsize);
+- ackinfo.jumbo_max = htonl(jmax);
++ trailer.maxMTU = htonl(rxrpc_rx_mtu);
++ trailer.ifMTU = htonl(mtu);
++ trailer.rwind = htonl(rsize);
++ trailer.jumbo_max = htonl(jmax);
+
+ *ackp++ = 0;
+ *ackp++ = 0;
+ *ackp++ = 0;
+- memcpy(ackp, &ackinfo, sizeof(ackinfo));
+- return txb->ack.nAcks + 3 + sizeof(ackinfo);
++ memcpy(ackp, &trailer, sizeof(trailer));
++ return txb->ack.nAcks + 3 + sizeof(trailer);
+ }
+
+ /*
+diff --git a/net/rxrpc/protocol.h b/net/rxrpc/protocol.h
+index e8ee4af43ca89..4fe6b4d20ada9 100644
+--- a/net/rxrpc/protocol.h
++++ b/net/rxrpc/protocol.h
+@@ -135,9 +135,9 @@ struct rxrpc_ackpacket {
+ /*
+ * ACK packets can have a further piece of information tagged on the end
+ */
+-struct rxrpc_ackinfo {
+- __be32 rxMTU; /* maximum Rx MTU size (bytes) [AFS 3.3] */
+- __be32 maxMTU; /* maximum interface MTU size (bytes) [AFS 3.3] */
++struct rxrpc_acktrailer {
++ __be32 maxMTU; /* maximum Rx MTU size (bytes) [AFS 3.3] */
++ __be32 ifMTU; /* maximum interface MTU size (bytes) [AFS 3.3] */
+ __be32 rwind; /* Rx window size (packets) [AFS 3.4] */
+ __be32 jumbo_max; /* max packets to stick into a jumbo packet [AFS 3.5] */
+ };
+diff --git a/net/smc/smc_ib.c b/net/smc/smc_ib.c
+index 97704a9e84c70..9297dc20bfe23 100644
+--- a/net/smc/smc_ib.c
++++ b/net/smc/smc_ib.c
+@@ -209,13 +209,18 @@ int smc_ib_find_route(struct net *net, __be32 saddr, __be32 daddr,
+ if (IS_ERR(rt))
+ goto out;
+ if (rt->rt_uses_gateway && rt->rt_gw_family != AF_INET)
+- goto out;
+- neigh = rt->dst.ops->neigh_lookup(&rt->dst, NULL, &fl4.daddr);
+- if (neigh) {
+- memcpy(nexthop_mac, neigh->ha, ETH_ALEN);
+- *uses_gateway = rt->rt_uses_gateway;
+- return 0;
+- }
++ goto out_rt;
++ neigh = dst_neigh_lookup(&rt->dst, &fl4.daddr);
++ if (!neigh)
++ goto out_rt;
++ memcpy(nexthop_mac, neigh->ha, ETH_ALEN);
++ *uses_gateway = rt->rt_uses_gateway;
++ neigh_release(neigh);
++ ip_rt_put(rt);
++ return 0;
++
++out_rt:
++ ip_rt_put(rt);
+ out:
+ return -ENOENT;
+ }
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index cda0935a68c9d..28f3749f6dc6c 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -405,7 +405,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
+ clnt->cl_maxproc = version->nrprocs;
+ clnt->cl_prog = args->prognumber ? : program->number;
+ clnt->cl_vers = version->number;
+- clnt->cl_stats = program->stats;
++ clnt->cl_stats = args->stats ? : program->stats;
+ clnt->cl_metrics = rpc_alloc_iostats(clnt);
+ rpc_init_pipe_dir_head(&clnt->cl_pipedir_objects);
+ err = -ENOMEM;
+@@ -691,6 +691,7 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *clnt)
+ .version = clnt->cl_vers,
+ .authflavor = clnt->cl_auth->au_flavor,
+ .cred = clnt->cl_cred,
++ .stats = clnt->cl_stats,
+ };
+ return __rpc_clone_client(&args, clnt);
+ }
+@@ -713,6 +714,7 @@ rpc_clone_client_set_auth(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
+ .version = clnt->cl_vers,
+ .authflavor = flavor,
+ .cred = clnt->cl_cred,
++ .stats = clnt->cl_stats,
+ };
+ return __rpc_clone_client(&args, clnt);
+ }
+@@ -1068,6 +1070,7 @@ struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
+ .version = vers,
+ .authflavor = old->cl_auth->au_flavor,
+ .cred = old->cl_cred,
++ .stats = old->cl_stats,
+ };
+ struct rpc_clnt *clnt;
+ int err;
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index 58f3dc8d0d71c..004d2bd8b49ec 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -2645,6 +2645,7 @@ static void xs_tcp_tls_setup_socket(struct work_struct *work)
+ .xprtsec = {
+ .policy = RPC_XPRTSEC_NONE,
+ },
++ .stats = upper_clnt->cl_stats,
+ };
+ unsigned int pflags = current->flags;
+ struct rpc_clnt *lower_clnt;
+diff --git a/net/tipc/msg.c b/net/tipc/msg.c
+index 5c9fd4791c4ba..76284fc538ebd 100644
+--- a/net/tipc/msg.c
++++ b/net/tipc/msg.c
+@@ -142,9 +142,9 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
+ if (fragid == FIRST_FRAGMENT) {
+ if (unlikely(head))
+ goto err;
+- *buf = NULL;
+ if (skb_has_frag_list(frag) && __skb_linearize(frag))
+ goto err;
++ *buf = NULL;
+ frag = skb_unshare(frag, GFP_ATOMIC);
+ if (unlikely(!frag))
+ goto err;
+@@ -156,6 +156,11 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
+ if (!head)
+ goto err;
+
++ /* Either the input skb ownership is transferred to headskb
++ * or the input skb is freed, clear the reference to avoid
++ * bad access on error path.
++ */
++ *buf = NULL;
+ if (skb_try_coalesce(head, frag, &headstolen, &delta)) {
+ kfree_skb_partial(frag, headstolen);
+ } else {
+@@ -179,7 +184,6 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
+ *headbuf = NULL;
+ return 1;
+ }
+- *buf = NULL;
+ return 0;
+ err:
+ kfree_skb(*buf);
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index bd54a928bab41..daac83aa8988e 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -14092,6 +14092,8 @@ static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
+ error:
+ for (i = 0; i < new_coalesce.n_rules; i++) {
+ tmp_rule = &new_coalesce.rules[i];
++ if (!tmp_rule)
++ continue;
+ for (j = 0; j < tmp_rule->n_patterns; j++)
+ kfree(tmp_rule->patterns[j].mask);
+ kfree(tmp_rule->patterns);
+diff --git a/net/wireless/trace.h b/net/wireless/trace.h
+index 1f374c8a17a50..cc3fd4177bcee 100644
+--- a/net/wireless/trace.h
++++ b/net/wireless/trace.h
+@@ -1013,7 +1013,7 @@ TRACE_EVENT(rdev_get_mpp,
+ TRACE_EVENT(rdev_dump_mpp,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int _idx,
+ u8 *dst, u8 *mpp),
+- TP_ARGS(wiphy, netdev, _idx, mpp, dst),
++ TP_ARGS(wiphy, netdev, _idx, dst, mpp),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ NETDEV_ENTRY
+diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
+index bd4ce21d76d75..b2f7af63b7dae 100644
+--- a/net/xfrm/xfrm_input.c
++++ b/net/xfrm/xfrm_input.c
+@@ -388,11 +388,15 @@ static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
+ */
+ static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+ {
++ struct xfrm_offload *xo = xfrm_offload(skb);
+ int ihl = skb->data - skb_transport_header(skb);
+
+ if (skb->transport_header != skb->network_header) {
+ memmove(skb_transport_header(skb),
+ skb_network_header(skb), ihl);
++ if (xo)
++ xo->orig_mac_len =
++ skb_mac_header_was_set(skb) ? skb_mac_header_len(skb) : 0;
+ skb->network_header = skb->transport_header;
+ }
+ ip_hdr(skb)->tot_len = htons(skb->len + ihl);
+@@ -403,11 +407,15 @@ static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+ static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
+ {
+ #if IS_ENABLED(CONFIG_IPV6)
++ struct xfrm_offload *xo = xfrm_offload(skb);
+ int ihl = skb->data - skb_transport_header(skb);
+
+ if (skb->transport_header != skb->network_header) {
+ memmove(skb_transport_header(skb),
+ skb_network_header(skb), ihl);
++ if (xo)
++ xo->orig_mac_len =
++ skb_mac_header_was_set(skb) ? skb_mac_header_len(skb) : 0;
+ skb->network_header = skb->transport_header;
+ }
+ ipv6_hdr(skb)->payload_len = htons(skb->len + ihl -
+diff --git a/rust/macros/module.rs b/rust/macros/module.rs
+index d62d8710d77ab..acd0393b50957 100644
+--- a/rust/macros/module.rs
++++ b/rust/macros/module.rs
+@@ -199,17 +199,6 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
+ /// Used by the printing macros, e.g. [`info!`].
+ const __LOG_PREFIX: &[u8] = b\"{name}\\0\";
+
+- /// The \"Rust loadable module\" mark.
+- //
+- // This may be best done another way later on, e.g. as a new modinfo
+- // key or a new section. For the moment, keep it simple.
+- #[cfg(MODULE)]
+- #[doc(hidden)]
+- #[used]
+- static __IS_RUST_MODULE: () = ();
+-
+- static mut __MOD: Option<{type_}> = None;
+-
+ // SAFETY: `__this_module` is constructed by the kernel at load time and will not be
+ // freed until the module is unloaded.
+ #[cfg(MODULE)]
+@@ -221,76 +210,132 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
+ kernel::ThisModule::from_ptr(core::ptr::null_mut())
+ }};
+
+- // Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
+- #[cfg(MODULE)]
+- #[doc(hidden)]
+- #[no_mangle]
+- pub extern \"C\" fn init_module() -> core::ffi::c_int {{
+- __init()
+- }}
+-
+- #[cfg(MODULE)]
+- #[doc(hidden)]
+- #[no_mangle]
+- pub extern \"C\" fn cleanup_module() {{
+- __exit()
+- }}
++ // Double nested modules, since then nobody can access the public items inside.
++ mod __module_init {{
++ mod __module_init {{
++ use super::super::{type_};
++
++ /// The \"Rust loadable module\" mark.
++ //
++ // This may be best done another way later on, e.g. as a new modinfo
++ // key or a new section. For the moment, keep it simple.
++ #[cfg(MODULE)]
++ #[doc(hidden)]
++ #[used]
++ static __IS_RUST_MODULE: () = ();
++
++ static mut __MOD: Option<{type_}> = None;
++
++ // Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
++ /// # Safety
++ ///
++ /// This function must not be called after module initialization, because it may be
++ /// freed after that completes.
++ #[cfg(MODULE)]
++ #[doc(hidden)]
++ #[no_mangle]
++ #[link_section = \".init.text\"]
++ pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{
++ // SAFETY: This function is inaccessible to the outside due to the double
++ // module wrapping it. It is called exactly once by the C side via its
++ // unique name.
++ unsafe {{ __init() }}
++ }}
+
+- // Built-in modules are initialized through an initcall pointer
+- // and the identifiers need to be unique.
+- #[cfg(not(MODULE))]
+- #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
+- #[doc(hidden)]
+- #[link_section = \"{initcall_section}\"]
+- #[used]
+- pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init;
++ #[cfg(MODULE)]
++ #[doc(hidden)]
++ #[no_mangle]
++ pub extern \"C\" fn cleanup_module() {{
++ // SAFETY:
++ // - This function is inaccessible to the outside due to the double
++ // module wrapping it. It is called exactly once by the C side via its
++ // unique name,
++ // - furthermore it is only called after `init_module` has returned `0`
++ // (which delegates to `__init`).
++ unsafe {{ __exit() }}
++ }}
+
+- #[cfg(not(MODULE))]
+- #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
+- core::arch::global_asm!(
+- r#\".section \"{initcall_section}\", \"a\"
+- __{name}_initcall:
+- .long __{name}_init - .
+- .previous
+- \"#
+- );
++ // Built-in modules are initialized through an initcall pointer
++ // and the identifiers need to be unique.
++ #[cfg(not(MODULE))]
++ #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
++ #[doc(hidden)]
++ #[link_section = \"{initcall_section}\"]
++ #[used]
++ pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init;
++
++ #[cfg(not(MODULE))]
++ #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
++ core::arch::global_asm!(
++ r#\".section \"{initcall_section}\", \"a\"
++ __{name}_initcall:
++ .long __{name}_init - .
++ .previous
++ \"#
++ );
++
++ #[cfg(not(MODULE))]
++ #[doc(hidden)]
++ #[no_mangle]
++ pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{
++ // SAFETY: This function is inaccessible to the outside due to the double
++ // module wrapping it. It is called exactly once by the C side via its
++ // placement above in the initcall section.
++ unsafe {{ __init() }}
++ }}
+
+- #[cfg(not(MODULE))]
+- #[doc(hidden)]
+- #[no_mangle]
+- pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{
+- __init()
+- }}
++ #[cfg(not(MODULE))]
++ #[doc(hidden)]
++ #[no_mangle]
++ pub extern \"C\" fn __{name}_exit() {{
++ // SAFETY:
++ // - This function is inaccessible to the outside due to the double
++ // module wrapping it. It is called exactly once by the C side via its
++ // unique name,
++ // - furthermore it is only called after `__{name}_init` has returned `0`
++ // (which delegates to `__init`).
++ unsafe {{ __exit() }}
++ }}
+
+- #[cfg(not(MODULE))]
+- #[doc(hidden)]
+- #[no_mangle]
+- pub extern \"C\" fn __{name}_exit() {{
+- __exit()
+- }}
++ /// # Safety
++ ///
++ /// This function must only be called once.
++ unsafe fn __init() -> core::ffi::c_int {{
++ match <{type_} as kernel::Module>::init(&super::super::THIS_MODULE) {{
++ Ok(m) => {{
++ // SAFETY: No data race, since `__MOD` can only be accessed by this
++ // module and there only `__init` and `__exit` access it. These
++ // functions are only called once and `__exit` cannot be called
++ // before or during `__init`.
++ unsafe {{
++ __MOD = Some(m);
++ }}
++ return 0;
++ }}
++ Err(e) => {{
++ return e.to_errno();
++ }}
++ }}
++ }}
+
+- fn __init() -> core::ffi::c_int {{
+- match <{type_} as kernel::Module>::init(&THIS_MODULE) {{
+- Ok(m) => {{
++ /// # Safety
++ ///
++ /// This function must
++ /// - only be called once,
++ /// - be called after `__init` has been called and returned `0`.
++ unsafe fn __exit() {{
++ // SAFETY: No data race, since `__MOD` can only be accessed by this module
++ // and there only `__init` and `__exit` access it. These functions are only
++ // called once and `__init` was already called.
+ unsafe {{
+- __MOD = Some(m);
++ // Invokes `drop()` on `__MOD`, which should be used for cleanup.
++ __MOD = None;
+ }}
+- return 0;
+- }}
+- Err(e) => {{
+- return e.to_errno();
+ }}
+- }}
+- }}
+
+- fn __exit() {{
+- unsafe {{
+- // Invokes `drop()` on `__MOD`, which should be used for cleanup.
+- __MOD = None;
++ {modinfo}
+ }}
+ }}
+-
+- {modinfo}
+ ",
+ type_ = info.type_,
+ name = info.name,
+diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
+index 8568d256d6fbf..79fcf27316864 100644
+--- a/scripts/Makefile.modfinal
++++ b/scripts/Makefile.modfinal
+@@ -23,7 +23,7 @@ modname = $(notdir $(@:.mod.o=))
+ part-of-module = y
+
+ quiet_cmd_cc_o_c = CC [M] $@
+- cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI) $(CFLAGS_GCOV), $(c_flags)) -c -o $@ $<
++ cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI) $(CFLAGS_GCOV) $(CFLAGS_KCSAN), $(c_flags)) -c -o $@ $<
+
+ %.mod.o: %.mod.c FORCE
+ $(call if_changed_dep,cc_o_c)
+diff --git a/security/keys/key.c b/security/keys/key.c
+index 5b10641debd54..74dfd961af96a 100644
+--- a/security/keys/key.c
++++ b/security/keys/key.c
+@@ -464,7 +464,8 @@ static int __key_instantiate_and_link(struct key *key,
+ if (authkey)
+ key_invalidate(authkey);
+
+- key_set_expiry(key, prep->expiry);
++ if (prep->expiry != TIME64_MAX)
++ key_set_expiry(key, prep->expiry);
+ }
+ }
+
+diff --git a/sound/hda/intel-sdw-acpi.c b/sound/hda/intel-sdw-acpi.c
+index b57d72ea4503f..4e376994bf78b 100644
+--- a/sound/hda/intel-sdw-acpi.c
++++ b/sound/hda/intel-sdw-acpi.c
+@@ -41,6 +41,8 @@ static bool is_link_enabled(struct fwnode_handle *fw_node, u8 idx)
+ "intel-quirk-mask",
+ &quirk_mask);
+
++ fwnode_handle_put(link);
++
+ if (quirk_mask & SDW_INTEL_QUIRK_MASK_BUS_DISABLE)
+ return false;
+
+diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c
+index 0ba8f0c4cd99a..3a593da09280d 100644
+--- a/sound/oss/dmasound/dmasound_paula.c
++++ b/sound/oss/dmasound/dmasound_paula.c
+@@ -725,7 +725,13 @@ static void __exit amiga_audio_remove(struct platform_device *pdev)
+ dmasound_deinit();
+ }
+
+-static struct platform_driver amiga_audio_driver = {
++/*
++ * amiga_audio_remove() lives in .exit.text. For drivers registered via
++ * module_platform_driver_probe() this is ok because they cannot get unbound at
++ * runtime. So mark the driver struct with __refdata to prevent modpost
++ * triggering a section mismatch warning.
++ */
++static struct platform_driver amiga_audio_driver __refdata = {
+ .remove_new = __exit_p(amiga_audio_remove),
+ .driver = {
+ .name = "amiga-audio",
+diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
+index fe72e7d772412..dadeda7758cee 100644
+--- a/sound/pci/emu10k1/emu10k1.c
++++ b/sound/pci/emu10k1/emu10k1.c
+@@ -189,8 +189,7 @@ static int snd_emu10k1_suspend(struct device *dev)
+
+ emu->suspend = 1;
+
+- cancel_work_sync(&emu->emu1010.firmware_work);
+- cancel_work_sync(&emu->emu1010.clock_work);
++ cancel_work_sync(&emu->emu1010.work);
+
+ snd_ac97_suspend(emu->ac97);
+
+diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
+index de5c41e578e1f..ade90c7ecd922 100644
+--- a/sound/pci/emu10k1/emu10k1_main.c
++++ b/sound/pci/emu10k1/emu10k1_main.c
+@@ -732,69 +732,67 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, int dock,
+ return snd_emu1010_load_firmware_entry(emu, *fw);
+ }
+
+-static void emu1010_firmware_work(struct work_struct *work)
++static void snd_emu1010_load_dock_firmware(struct snd_emu10k1 *emu)
+ {
+- struct snd_emu10k1 *emu;
+- u32 tmp, tmp2, reg;
++ u32 tmp, tmp2;
+ int err;
+
+- emu = container_of(work, struct snd_emu10k1,
+- emu1010.firmware_work);
+- if (emu->card->shutdown)
++ // The docking events clearly arrive prematurely - while the
++ // Dock's FPGA seems to be successfully programmed, the Dock
++ // fails to initialize subsequently if we don't give it some
++ // time to "warm up" here.
++ msleep(200);
++
++ dev_info(emu->card->dev, "emu1010: Loading Audio Dock Firmware\n");
++ /* Return to Audio Dock programming mode */
++ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
++ EMU_HANA_FPGA_CONFIG_AUDIODOCK);
++ err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
++ if (err < 0)
+ return;
+-#ifdef CONFIG_PM_SLEEP
+- if (emu->suspend)
++ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
++
++ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
++ dev_dbg(emu->card->dev, "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
++ if ((tmp & 0x1f) != 0x15) {
++ /* FPGA failed to be programmed */
++ dev_err(emu->card->dev,
++ "emu1010: Loading Audio Dock Firmware failed, reg = 0x%x\n",
++ tmp);
+ return;
+-#endif
++ }
++ dev_info(emu->card->dev, "emu1010: Audio Dock Firmware loaded\n");
++
++ snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
++ snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
++ dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
++
++ /* Allow DLL to settle, to sync clocking between 1010 and Dock */
++ msleep(10);
++}
++
++static void emu1010_dock_event(struct snd_emu10k1 *emu)
++{
++ u32 reg;
++
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */
+ if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) {
+ /* Audio Dock attached */
+- /* Return to Audio Dock programming mode */
+- dev_info(emu->card->dev,
+- "emu1010: Loading Audio Dock Firmware\n");
+- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG,
+- EMU_HANA_FPGA_CONFIG_AUDIODOCK);
+- err = snd_emu1010_load_firmware(emu, 1, &emu->dock_fw);
+- if (err < 0)
+- return;
+- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
+- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &tmp);
+- dev_info(emu->card->dev,
+- "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", tmp);
+- if ((tmp & 0x1f) != 0x15) {
+- /* FPGA failed to be programmed */
+- dev_info(emu->card->dev,
+- "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n",
+- tmp);
+- return;
+- }
+- dev_info(emu->card->dev,
+- "emu1010: Audio Dock Firmware loaded\n");
+- snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
+- snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
+- dev_info(emu->card->dev, "Audio Dock ver: %u.%u\n", tmp, tmp2);
+- /* Sync clocking between 1010 and Dock */
+- /* Allow DLL to settle */
+- msleep(10);
++ snd_emu1010_load_dock_firmware(emu);
+ /* Unmute all. Default is muted after a firmware load */
+ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
++ } else if (!(reg & EMU_HANA_OPTION_DOCK_ONLINE)) {
++ /* Audio Dock removed */
++ dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
++ /* The hardware auto-mutes all, so we unmute again */
++ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
+ }
+ }
+
+-static void emu1010_clock_work(struct work_struct *work)
++static void emu1010_clock_event(struct snd_emu10k1 *emu)
+ {
+- struct snd_emu10k1 *emu;
+ struct snd_ctl_elem_id id;
+
+- emu = container_of(work, struct snd_emu10k1,
+- emu1010.clock_work);
+- if (emu->card->shutdown)
+- return;
+-#ifdef CONFIG_PM_SLEEP
+- if (emu->suspend)
+- return;
+-#endif
+-
+ spin_lock_irq(&emu->reg_lock);
+ // This is the only thing that can actually happen.
+ emu->emu1010.clock_source = emu->emu1010.clock_fallback;
+@@ -805,21 +803,40 @@ static void emu1010_clock_work(struct work_struct *work)
+ snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
+ }
+
+-static void emu1010_interrupt(struct snd_emu10k1 *emu)
++static void emu1010_work(struct work_struct *work)
+ {
++ struct snd_emu10k1 *emu;
+ u32 sts;
+
++ emu = container_of(work, struct snd_emu10k1, emu1010.work);
++ if (emu->card->shutdown)
++ return;
++#ifdef CONFIG_PM_SLEEP
++ if (emu->suspend)
++ return;
++#endif
++
+ snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &sts);
+- if (sts & EMU_HANA_IRQ_DOCK_LOST) {
+- /* Audio Dock removed */
+- dev_info(emu->card->dev, "emu1010: Audio Dock detached\n");
+- /* The hardware auto-mutes all, so we unmute again */
+- snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
+- } else if (sts & EMU_HANA_IRQ_DOCK) {
+- schedule_work(&emu->emu1010.firmware_work);
+- }
++
++ // The distinction of the IRQ status bits is unreliable,
++ // so we dispatch later based on option card status.
++ if (sts & (EMU_HANA_IRQ_DOCK | EMU_HANA_IRQ_DOCK_LOST))
++ emu1010_dock_event(emu);
++
+ if (sts & EMU_HANA_IRQ_WCLK_CHANGED)
+- schedule_work(&emu->emu1010.clock_work);
++ emu1010_clock_event(emu);
++}
++
++static void emu1010_interrupt(struct snd_emu10k1 *emu)
++{
++ // We get an interrupt on each GPIO input pin change, but we
++ // care only about the ones triggered by the dedicated pin.
++ u16 sts = inw(emu->port + A_GPIO);
++ u16 bit = emu->card_capabilities->ca0108_chip ? 0x2000 : 0x8000;
++ if (!(sts & bit))
++ return;
++
++ schedule_work(&emu->emu1010.work);
+ }
+
+ /*
+@@ -889,7 +906,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®);
+ dev_info(emu->card->dev, "emu1010: Card options = 0x%x\n", reg);
+ if (reg & EMU_HANA_OPTION_DOCK_OFFLINE)
+- schedule_work(&emu->emu1010.firmware_work);
++ snd_emu1010_load_dock_firmware(emu);
+ if (emu->card_capabilities->no_adat) {
+ emu->emu1010.optical_in = 0; /* IN_SPDIF */
+ emu->emu1010.optical_out = 0; /* OUT_SPDIF */
+@@ -960,8 +977,7 @@ static void snd_emu10k1_free(struct snd_card *card)
+ /* Disable 48Volt power to Audio Dock */
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
+ }
+- cancel_work_sync(&emu->emu1010.firmware_work);
+- cancel_work_sync(&emu->emu1010.clock_work);
++ cancel_work_sync(&emu->emu1010.work);
+ release_firmware(emu->firmware);
+ release_firmware(emu->dock_fw);
+ snd_util_memhdr_free(emu->memhdr);
+@@ -1540,8 +1556,7 @@ int snd_emu10k1_create(struct snd_card *card,
+ emu->irq = -1;
+ emu->synth = NULL;
+ emu->get_synth_voice = NULL;
+- INIT_WORK(&emu->emu1010.firmware_work, emu1010_firmware_work);
+- INIT_WORK(&emu->emu1010.clock_work, emu1010_clock_work);
++ INIT_WORK(&emu->emu1010.work, emu1010_work);
+ /* read revision & serial */
+ emu->revision = pci->revision;
+ pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index bf0618ab4fda0..7c82f93ba9197 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -7502,6 +7502,7 @@ enum {
+ ALC287_FIXUP_YOGA7_14ITL_SPEAKERS,
+ ALC298_FIXUP_LENOVO_C940_DUET7,
+ ALC287_FIXUP_LENOVO_14IRP8_DUETITL,
++ ALC287_FIXUP_LENOVO_LEGION_7,
+ ALC287_FIXUP_13S_GEN2_SPEAKERS,
+ ALC256_FIXUP_SET_COEF_DEFAULTS,
+ ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
+@@ -7574,6 +7575,23 @@ static void alc287_fixup_lenovo_14irp8_duetitl(struct hda_codec *codec,
+ __snd_hda_apply_fixup(codec, id, action, 0);
+ }
+
++/* Another hilarious PCI SSID conflict with Lenovo Legion Pro 7 16ARX8H (with
++ * TAS2781 codec) and Legion 7i 16IAX7 (with CS35L41 codec);
++ * we apply a corresponding fixup depending on the codec SSID instead
++ */
++static void alc287_fixup_lenovo_legion_7(struct hda_codec *codec,
++ const struct hda_fixup *fix,
++ int action)
++{
++ int id;
++
++ if (codec->core.subsystem_id == 0x17aa38a8)
++ id = ALC287_FIXUP_TAS2781_I2C; /* Legion Pro 7 16ARX8H */
++ else
++ id = ALC287_FIXUP_CS35L41_I2C_2; /* Legion 7i 16IAX7 */
++ __snd_hda_apply_fixup(codec, id, action, 0);
++}
++
+ static const struct hda_fixup alc269_fixups[] = {
+ [ALC269_FIXUP_GPIO2] = {
+ .type = HDA_FIXUP_FUNC,
+@@ -9468,6 +9486,10 @@ static const struct hda_fixup alc269_fixups[] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc287_fixup_lenovo_14irp8_duetitl,
+ },
++ [ALC287_FIXUP_LENOVO_LEGION_7] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc287_fixup_lenovo_legion_7,
++ },
+ [ALC287_FIXUP_13S_GEN2_SPEAKERS] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+@@ -9934,6 +9956,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x860f, "HP ZBook 15 G6", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+ SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+ SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
++ SND_PCI_QUIRK(0x103c, 0x86c1, "HP Laptop 15-da3001TU", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
+ SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO),
+ SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
+ SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
+@@ -10371,7 +10394,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
+ SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
+ SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
+- SND_PCI_QUIRK(0x17aa, 0x386f, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
++ SND_PCI_QUIRK(0x17aa, 0x386f, "Legion Pro 7/7i", ALC287_FIXUP_LENOVO_LEGION_7),
+ SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x17aa, 0x3878, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
+diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c
+index cbcd02ec6ba42..a3dbeebaeb0c9 100644
+--- a/sound/soc/codecs/es8326.c
++++ b/sound/soc/codecs/es8326.c
+@@ -326,9 +326,9 @@ static const struct _coeff_div coeff_div_v3[] = {
+ {125, 48000, 6000000, 0x04, 0x04, 0x1F, 0x2D, 0x8A, 0x0A, 0x27, 0x27},
+
+ {128, 8000, 1024000, 0x60, 0x00, 0x05, 0x75, 0x8A, 0x1B, 0x1F, 0x7F},
+- {128, 16000, 2048000, 0x20, 0x00, 0x31, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
+- {128, 44100, 5644800, 0xE0, 0x00, 0x01, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
+- {128, 48000, 6144000, 0xE0, 0x00, 0x01, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
++ {128, 16000, 2048000, 0x20, 0x00, 0x31, 0x35, 0x08, 0x19, 0x1F, 0x3F},
++ {128, 44100, 5644800, 0xE0, 0x00, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
++ {128, 48000, 6144000, 0xE0, 0x00, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
+ {144, 8000, 1152000, 0x20, 0x00, 0x03, 0x35, 0x8A, 0x1B, 0x23, 0x47},
+ {144, 16000, 2304000, 0x20, 0x00, 0x11, 0x35, 0x8A, 0x1B, 0x23, 0x47},
+ {192, 8000, 1536000, 0x60, 0x02, 0x0D, 0x75, 0x8A, 0x1B, 0x1F, 0x7F},
+@@ -337,10 +337,10 @@ static const struct _coeff_div coeff_div_v3[] = {
+
+ {200, 48000, 9600000, 0x04, 0x04, 0x0F, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
+ {250, 48000, 12000000, 0x04, 0x04, 0x0F, 0x2D, 0xCA, 0x0A, 0x27, 0x27},
+- {256, 8000, 2048000, 0x60, 0x00, 0x31, 0x35, 0x8A, 0x1B, 0x1F, 0x7F},
+- {256, 16000, 4096000, 0x20, 0x00, 0x01, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
+- {256, 44100, 11289600, 0xE0, 0x00, 0x30, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
+- {256, 48000, 12288000, 0xE0, 0x00, 0x30, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
++ {256, 8000, 2048000, 0x60, 0x00, 0x31, 0x35, 0x08, 0x19, 0x1F, 0x7F},
++ {256, 16000, 4096000, 0x20, 0x00, 0x01, 0x35, 0x08, 0x19, 0x1F, 0x3F},
++ {256, 44100, 11289600, 0xE0, 0x01, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
++ {256, 48000, 12288000, 0xE0, 0x01, 0x01, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
+ {288, 8000, 2304000, 0x20, 0x00, 0x01, 0x35, 0x8A, 0x1B, 0x23, 0x47},
+ {384, 8000, 3072000, 0x60, 0x02, 0x05, 0x75, 0x8A, 0x1B, 0x1F, 0x7F},
+ {384, 16000, 6144000, 0x20, 0x02, 0x03, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
+@@ -349,10 +349,10 @@ static const struct _coeff_div coeff_div_v3[] = {
+
+ {400, 48000, 19200000, 0xE4, 0x04, 0x35, 0x6d, 0xCA, 0x0A, 0x1F, 0x1F},
+ {500, 48000, 24000000, 0xF8, 0x04, 0x3F, 0x6D, 0xCA, 0x0A, 0x1F, 0x1F},
+- {512, 8000, 4096000, 0x60, 0x00, 0x01, 0x35, 0x8A, 0x1B, 0x1F, 0x7F},
+- {512, 16000, 8192000, 0x20, 0x00, 0x30, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
+- {512, 44100, 22579200, 0xE0, 0x00, 0x00, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
+- {512, 48000, 24576000, 0xE0, 0x00, 0x00, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
++ {512, 8000, 4096000, 0x60, 0x00, 0x01, 0x08, 0x19, 0x1B, 0x1F, 0x7F},
++ {512, 16000, 8192000, 0x20, 0x00, 0x30, 0x35, 0x08, 0x19, 0x1F, 0x3F},
++ {512, 44100, 22579200, 0xE0, 0x00, 0x00, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
++ {512, 48000, 24576000, 0xE0, 0x00, 0x00, 0x2D, 0x48, 0x08, 0x1F, 0x1F},
+ {768, 8000, 6144000, 0x60, 0x02, 0x11, 0x35, 0x8A, 0x1B, 0x1F, 0x7F},
+ {768, 16000, 12288000, 0x20, 0x02, 0x01, 0x35, 0x8A, 0x1B, 0x1F, 0x3F},
+ {768, 32000, 24576000, 0xE0, 0x02, 0x30, 0x2D, 0xCA, 0x0A, 0x1F, 0x1F},
+@@ -757,6 +757,7 @@ static void es8326_jack_detect_handler(struct work_struct *work)
+ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01);
+ regmap_write(es8326->regmap, ES8326_SYS_BIAS, 0x0a);
+ regmap_update_bits(es8326->regmap, ES8326_HP_DRIVER_REF, 0x0f, 0x03);
++ regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9);
+ /*
+ * Inverted HPJACK_POL bit to trigger one IRQ to double check HP Removal event
+ */
+@@ -779,6 +780,8 @@ static void es8326_jack_detect_handler(struct work_struct *work)
+ * set auto-check mode, then restart jack_detect_work after 400ms.
+ * Don't report jack status.
+ */
++ regmap_write(es8326->regmap, ES8326_INT_SOURCE,
++ (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON));
+ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x01);
+ es8326_enable_micbias(es8326->component);
+ usleep_range(50000, 70000);
+@@ -901,7 +904,7 @@ static int es8326_resume(struct snd_soc_component *component)
+ regmap_write(es8326->regmap, ES8326_VMIDSEL, 0x0E);
+ regmap_write(es8326->regmap, ES8326_ANA_LP, 0xf0);
+ usleep_range(10000, 15000);
+- regmap_write(es8326->regmap, ES8326_HPJACK_TIMER, 0xe9);
++ regmap_write(es8326->regmap, ES8326_HPJACK_TIMER, 0xd9);
+ regmap_write(es8326->regmap, ES8326_ANA_MICBIAS, 0xcb);
+ /* set headphone default type and detect pin */
+ regmap_write(es8326->regmap, ES8326_HPDET_TYPE, 0x83);
+@@ -952,8 +955,7 @@ static int es8326_resume(struct snd_soc_component *component)
+ es8326_enable_micbias(es8326->component);
+ usleep_range(50000, 70000);
+ regmap_update_bits(es8326->regmap, ES8326_HPDET_TYPE, 0x03, 0x00);
+- regmap_write(es8326->regmap, ES8326_INT_SOURCE,
+- (ES8326_INT_SRC_PIN9 | ES8326_INT_SRC_BUTTON));
++ regmap_write(es8326->regmap, ES8326_INT_SOURCE, ES8326_INT_SRC_PIN9);
+ regmap_write(es8326->regmap, ES8326_INTOUT_IO,
+ es8326->interrupt_clk);
+ regmap_write(es8326->regmap, ES8326_SDINOUT1_IO,
+diff --git a/sound/soc/codecs/es8326.h b/sound/soc/codecs/es8326.h
+index 4234bbb900c45..dfef808673f4a 100644
+--- a/sound/soc/codecs/es8326.h
++++ b/sound/soc/codecs/es8326.h
+@@ -101,7 +101,7 @@
+ #define ES8326_MUTE (3 << 0)
+
+ /* ES8326_CLK_CTL */
+-#define ES8326_CLK_ON (0x7e << 0)
++#define ES8326_CLK_ON (0x7f << 0)
+ #define ES8326_CLK_OFF (0 << 0)
+
+ /* ES8326_CLK_INV */
+diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c
+index 3c025dabaf7a4..1253695bebd86 100644
+--- a/sound/soc/codecs/wsa881x.c
++++ b/sound/soc/codecs/wsa881x.c
+@@ -1155,6 +1155,7 @@ static int wsa881x_probe(struct sdw_slave *pdev,
+ pdev->prop.sink_ports = GENMASK(WSA881X_MAX_SWR_PORTS, 0);
+ pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop;
+ pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
++ pdev->prop.clk_stop_mode1 = true;
+ gpiod_direction_output(wsa881x->sd_n, !wsa881x->sd_n_val);
+
+ wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config);
+diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c
+index 48b3c67c91032..d8223e2b4cfe2 100644
+--- a/sound/soc/intel/avs/topology.c
++++ b/sound/soc/intel/avs/topology.c
+@@ -1458,6 +1458,8 @@ static int avs_widget_load(struct snd_soc_component *comp, int index,
+ if (!le32_to_cpu(dw->priv.size))
+ return 0;
+
++ w->no_wname_in_kcontrol_name = true;
++
+ if (w->ignore_suspend && !AVS_S0IX_SUPPORTED) {
+ dev_info_once(comp->dev, "Device does not support S0IX, check BIOS settings\n");
+ w->ignore_suspend = false;
+diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig
+index b93ea33739f29..6458d5dc4902f 100644
+--- a/sound/soc/meson/Kconfig
++++ b/sound/soc/meson/Kconfig
+@@ -99,6 +99,7 @@ config SND_MESON_AXG_PDM
+
+ config SND_MESON_CARD_UTILS
+ tristate
++ select SND_DYNAMIC_MINORS
+
+ config SND_MESON_CODEC_GLUE
+ tristate
+diff --git a/sound/soc/meson/axg-card.c b/sound/soc/meson/axg-card.c
+index 3180aa4d3a157..8c5605c1e34e8 100644
+--- a/sound/soc/meson/axg-card.c
++++ b/sound/soc/meson/axg-card.c
+@@ -318,6 +318,7 @@ static int axg_card_add_link(struct snd_soc_card *card, struct device_node *np,
+
+ dai_link->cpus = cpu;
+ dai_link->num_cpus = 1;
++ dai_link->nonatomic = true;
+
+ ret = meson_card_parse_dai(card, np, dai_link->cpus);
+ if (ret)
+diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c
+index 65541fdb0038a..ecb3eb7a9723d 100644
+--- a/sound/soc/meson/axg-fifo.c
++++ b/sound/soc/meson/axg-fifo.c
+@@ -3,6 +3,7 @@
+ // Copyright (c) 2018 BayLibre, SAS.
+ // Author: Jerome Brunet <jbrunet@baylibre.com>
+
++#include <linux/bitfield.h>
+ #include <linux/clk.h>
+ #include <linux/of_irq.h>
+ #include <linux/of_platform.h>
+@@ -145,8 +146,8 @@ int axg_fifo_pcm_hw_params(struct snd_soc_component *component,
+ /* Enable irq if necessary */
+ irq_en = runtime->no_period_wakeup ? 0 : FIFO_INT_COUNT_REPEAT;
+ regmap_update_bits(fifo->map, FIFO_CTRL0,
+- CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT),
+- CTRL0_INT_EN(irq_en));
++ CTRL0_INT_EN,
++ FIELD_PREP(CTRL0_INT_EN, irq_en));
+
+ return 0;
+ }
+@@ -176,9 +177,9 @@ int axg_fifo_pcm_hw_free(struct snd_soc_component *component,
+ {
+ struct axg_fifo *fifo = axg_fifo_data(ss);
+
+- /* Disable the block count irq */
++ /* Disable irqs */
+ regmap_update_bits(fifo->map, FIFO_CTRL0,
+- CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), 0);
++ CTRL0_INT_EN, 0);
+
+ return 0;
+ }
+@@ -187,13 +188,13 @@ EXPORT_SYMBOL_GPL(axg_fifo_pcm_hw_free);
+ static void axg_fifo_ack_irq(struct axg_fifo *fifo, u8 mask)
+ {
+ regmap_update_bits(fifo->map, FIFO_CTRL1,
+- CTRL1_INT_CLR(FIFO_INT_MASK),
+- CTRL1_INT_CLR(mask));
++ CTRL1_INT_CLR,
++ FIELD_PREP(CTRL1_INT_CLR, mask));
+
+ /* Clear must also be cleared */
+ regmap_update_bits(fifo->map, FIFO_CTRL1,
+- CTRL1_INT_CLR(FIFO_INT_MASK),
+- 0);
++ CTRL1_INT_CLR,
++ FIELD_PREP(CTRL1_INT_CLR, 0));
+ }
+
+ static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id)
+@@ -203,18 +204,26 @@ static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id)
+ unsigned int status;
+
+ regmap_read(fifo->map, FIFO_STATUS1, &status);
++ status = FIELD_GET(STATUS1_INT_STS, status);
++ axg_fifo_ack_irq(fifo, status);
+
+- status = STATUS1_INT_STS(status) & FIFO_INT_MASK;
++ /* Use the thread to call period elapsed on nonatomic links */
+ if (status & FIFO_INT_COUNT_REPEAT)
+- snd_pcm_period_elapsed(ss);
+- else
+- dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n",
+- status);
++ return IRQ_WAKE_THREAD;
+
+- /* Ack irqs */
+- axg_fifo_ack_irq(fifo, status);
++ dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n",
++ status);
++
++ return IRQ_NONE;
++}
++
++static irqreturn_t axg_fifo_pcm_irq_block_thread(int irq, void *dev_id)
++{
++ struct snd_pcm_substream *ss = dev_id;
++
++ snd_pcm_period_elapsed(ss);
+
+- return IRQ_RETVAL(status);
++ return IRQ_HANDLED;
+ }
+
+ int axg_fifo_pcm_open(struct snd_soc_component *component,
+@@ -242,8 +251,9 @@ int axg_fifo_pcm_open(struct snd_soc_component *component,
+ if (ret)
+ return ret;
+
+- ret = request_irq(fifo->irq, axg_fifo_pcm_irq_block, 0,
+- dev_name(dev), ss);
++ ret = request_threaded_irq(fifo->irq, axg_fifo_pcm_irq_block,
++ axg_fifo_pcm_irq_block_thread,
++ IRQF_ONESHOT, dev_name(dev), ss);
+ if (ret)
+ return ret;
+
+@@ -254,15 +264,15 @@ int axg_fifo_pcm_open(struct snd_soc_component *component,
+
+ /* Setup status2 so it reports the memory pointer */
+ regmap_update_bits(fifo->map, FIFO_CTRL1,
+- CTRL1_STATUS2_SEL_MASK,
+- CTRL1_STATUS2_SEL(STATUS2_SEL_DDR_READ));
++ CTRL1_STATUS2_SEL,
++ FIELD_PREP(CTRL1_STATUS2_SEL, STATUS2_SEL_DDR_READ));
+
+ /* Make sure the dma is initially disabled */
+ __dma_enable(fifo, false);
+
+ /* Disable irqs until params are ready */
+ regmap_update_bits(fifo->map, FIFO_CTRL0,
+- CTRL0_INT_EN(FIFO_INT_MASK), 0);
++ CTRL0_INT_EN, 0);
+
+ /* Clear any pending interrupt */
+ axg_fifo_ack_irq(fifo, FIFO_INT_MASK);
+diff --git a/sound/soc/meson/axg-fifo.h b/sound/soc/meson/axg-fifo.h
+index df528e8cb7c91..84a2664139905 100644
+--- a/sound/soc/meson/axg-fifo.h
++++ b/sound/soc/meson/axg-fifo.h
+@@ -42,21 +42,19 @@ struct snd_soc_pcm_runtime;
+
+ #define FIFO_CTRL0 0x00
+ #define CTRL0_DMA_EN BIT(31)
+-#define CTRL0_INT_EN(x) ((x) << 16)
++#define CTRL0_INT_EN GENMASK(23, 16)
+ #define CTRL0_SEL_MASK GENMASK(2, 0)
+ #define CTRL0_SEL_SHIFT 0
+ #define FIFO_CTRL1 0x04
+-#define CTRL1_INT_CLR(x) ((x) << 0)
+-#define CTRL1_STATUS2_SEL_MASK GENMASK(11, 8)
+-#define CTRL1_STATUS2_SEL(x) ((x) << 8)
++#define CTRL1_INT_CLR GENMASK(7, 0)
++#define CTRL1_STATUS2_SEL GENMASK(11, 8)
+ #define STATUS2_SEL_DDR_READ 0
+-#define CTRL1_FRDDR_DEPTH_MASK GENMASK(31, 24)
+-#define CTRL1_FRDDR_DEPTH(x) ((x) << 24)
++#define CTRL1_FRDDR_DEPTH GENMASK(31, 24)
+ #define FIFO_START_ADDR 0x08
+ #define FIFO_FINISH_ADDR 0x0c
+ #define FIFO_INT_ADDR 0x10
+ #define FIFO_STATUS1 0x14
+-#define STATUS1_INT_STS(x) ((x) << 0)
++#define STATUS1_INT_STS GENMASK(7, 0)
+ #define FIFO_STATUS2 0x18
+ #define FIFO_INIT_ADDR 0x24
+ #define FIFO_CTRL2 0x28
+diff --git a/sound/soc/meson/axg-frddr.c b/sound/soc/meson/axg-frddr.c
+index 8c166a5f338ce..747a900c0bb22 100644
+--- a/sound/soc/meson/axg-frddr.c
++++ b/sound/soc/meson/axg-frddr.c
+@@ -7,6 +7,7 @@
+ * This driver implements the frontend playback DAI of AXG and G12A based SoCs
+ */
+
++#include <linux/bitfield.h>
+ #include <linux/clk.h>
+ #include <linux/regmap.h>
+ #include <linux/module.h>
+@@ -59,8 +60,8 @@ static int axg_frddr_dai_hw_params(struct snd_pcm_substream *substream,
+ /* Trim the FIFO depth if the period is small to improve latency */
+ depth = min(period, fifo->depth);
+ val = (depth / AXG_FIFO_BURST) - 1;
+- regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_FRDDR_DEPTH_MASK,
+- CTRL1_FRDDR_DEPTH(val));
++ regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_FRDDR_DEPTH,
++ FIELD_PREP(CTRL1_FRDDR_DEPTH, val));
+
+ return 0;
+ }
+diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c
+index 2cedbce738373..a71790908e178 100644
+--- a/sound/soc/meson/axg-tdm-interface.c
++++ b/sound/soc/meson/axg-tdm-interface.c
+@@ -349,26 +349,31 @@ static int axg_tdm_iface_hw_params(struct snd_pcm_substream *substream,
+ return 0;
+ }
+
+-static int axg_tdm_iface_hw_free(struct snd_pcm_substream *substream,
++static int axg_tdm_iface_trigger(struct snd_pcm_substream *substream,
++ int cmd,
+ struct snd_soc_dai *dai)
+ {
+- struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
++ struct axg_tdm_stream *ts =
++ snd_soc_dai_get_dma_data(dai, substream);
+
+- /* Stop all attached formatters */
+- axg_tdm_stream_stop(ts);
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ case SNDRV_PCM_TRIGGER_RESUME:
++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++ axg_tdm_stream_start(ts);
++ break;
++ case SNDRV_PCM_TRIGGER_SUSPEND:
++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++ case SNDRV_PCM_TRIGGER_STOP:
++ axg_tdm_stream_stop(ts);
++ break;
++ default:
++ return -EINVAL;
++ }
+
+ return 0;
+ }
+
+-static int axg_tdm_iface_prepare(struct snd_pcm_substream *substream,
+- struct snd_soc_dai *dai)
+-{
+- struct axg_tdm_stream *ts = snd_soc_dai_get_dma_data(dai, substream);
+-
+- /* Force all attached formatters to update */
+- return axg_tdm_stream_reset(ts);
+-}
+-
+ static int axg_tdm_iface_remove_dai(struct snd_soc_dai *dai)
+ {
+ int stream;
+@@ -412,8 +417,7 @@ static const struct snd_soc_dai_ops axg_tdm_iface_ops = {
+ .set_fmt = axg_tdm_iface_set_fmt,
+ .startup = axg_tdm_iface_startup,
+ .hw_params = axg_tdm_iface_hw_params,
+- .prepare = axg_tdm_iface_prepare,
+- .hw_free = axg_tdm_iface_hw_free,
++ .trigger = axg_tdm_iface_trigger,
+ };
+
+ /* TDM Backend DAIs */
+diff --git a/sound/soc/meson/axg-toddr.c b/sound/soc/meson/axg-toddr.c
+index 1a0be177b8fe7..972ad99f31be2 100644
+--- a/sound/soc/meson/axg-toddr.c
++++ b/sound/soc/meson/axg-toddr.c
+@@ -5,6 +5,7 @@
+
+ /* This driver implements the frontend capture DAI of AXG based SoCs */
+
++#include <linux/bitfield.h>
+ #include <linux/clk.h>
+ #include <linux/regmap.h>
+ #include <linux/module.h>
+@@ -19,12 +20,9 @@
+ #define CTRL0_TODDR_EXT_SIGNED BIT(29)
+ #define CTRL0_TODDR_PP_MODE BIT(28)
+ #define CTRL0_TODDR_SYNC_CH BIT(27)
+-#define CTRL0_TODDR_TYPE_MASK GENMASK(15, 13)
+-#define CTRL0_TODDR_TYPE(x) ((x) << 13)
+-#define CTRL0_TODDR_MSB_POS_MASK GENMASK(12, 8)
+-#define CTRL0_TODDR_MSB_POS(x) ((x) << 8)
+-#define CTRL0_TODDR_LSB_POS_MASK GENMASK(7, 3)
+-#define CTRL0_TODDR_LSB_POS(x) ((x) << 3)
++#define CTRL0_TODDR_TYPE GENMASK(15, 13)
++#define CTRL0_TODDR_MSB_POS GENMASK(12, 8)
++#define CTRL0_TODDR_LSB_POS GENMASK(7, 3)
+ #define CTRL1_TODDR_FORCE_FINISH BIT(25)
+ #define CTRL1_SEL_SHIFT 28
+
+@@ -76,12 +74,12 @@ static int axg_toddr_dai_hw_params(struct snd_pcm_substream *substream,
+ width = params_width(params);
+
+ regmap_update_bits(fifo->map, FIFO_CTRL0,
+- CTRL0_TODDR_TYPE_MASK |
+- CTRL0_TODDR_MSB_POS_MASK |
+- CTRL0_TODDR_LSB_POS_MASK,
+- CTRL0_TODDR_TYPE(type) |
+- CTRL0_TODDR_MSB_POS(TODDR_MSB_POS) |
+- CTRL0_TODDR_LSB_POS(TODDR_MSB_POS - (width - 1)));
++ CTRL0_TODDR_TYPE |
++ CTRL0_TODDR_MSB_POS |
++ CTRL0_TODDR_LSB_POS,
++ FIELD_PREP(CTRL0_TODDR_TYPE, type) |
++ FIELD_PREP(CTRL0_TODDR_MSB_POS, TODDR_MSB_POS) |
++ FIELD_PREP(CTRL0_TODDR_LSB_POS, TODDR_MSB_POS - (width - 1)));
+
+ return 0;
+ }
+diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
+index 2445ae7f6b2e9..1506982a56c30 100644
+--- a/sound/soc/sof/intel/hda-dsp.c
++++ b/sound/soc/sof/intel/hda-dsp.c
+@@ -681,17 +681,27 @@ static int hda_suspend(struct snd_sof_dev *sdev, bool runtime_suspend)
+ struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
+ const struct sof_intel_dsp_desc *chip = hda->desc;
+ struct hdac_bus *bus = sof_to_bus(sdev);
++ bool imr_lost = false;
+ int ret, j;
+
+ /*
+- * The memory used for IMR boot loses its content in deeper than S3 state
+- * We must not try IMR boot on next power up (as it will fail).
+- *
++ * The memory used for IMR boot loses its content in deeper than S3
++ * state on CAVS platforms.
++ * On ACE platforms due to the system architecture the IMR content is
++ * lost at S3 state already, they are tailored for s2idle use.
++ * We must not try IMR boot on next power up in these cases as it will
++ * fail.
++ */
++ if (sdev->system_suspend_target > SOF_SUSPEND_S3 ||
++ (chip->hw_ip_version >= SOF_INTEL_ACE_1_0 &&
++ sdev->system_suspend_target == SOF_SUSPEND_S3))
++ imr_lost = true;
++
++ /*
+ * In case of firmware crash or boot failure set the skip_imr_boot to true
+ * as well in order to try to re-load the firmware to do a 'cold' boot.
+ */
+- if (sdev->system_suspend_target > SOF_SUSPEND_S3 ||
+- sdev->fw_state == SOF_FW_CRASHED ||
++ if (imr_lost || sdev->fw_state == SOF_FW_CRASHED ||
+ sdev->fw_state == SOF_FW_BOOT_FAILED)
+ hda->skip_imr_boot = true;
+
+diff --git a/sound/soc/sof/intel/pci-lnl.c b/sound/soc/sof/intel/pci-lnl.c
+index b26ffe767fab5..b14e508f1f315 100644
+--- a/sound/soc/sof/intel/pci-lnl.c
++++ b/sound/soc/sof/intel/pci-lnl.c
+@@ -35,6 +35,9 @@ static const struct sof_dev_desc lnl_desc = {
+ .default_fw_path = {
+ [SOF_IPC_TYPE_4] = "intel/sof-ipc4/lnl",
+ },
++ .default_lib_path = {
++ [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/lnl",
++ },
+ .default_tplg_path = {
+ [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
+ },
+diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c
+index aa37c4ab0adbd..21cd41fec7a9c 100644
+--- a/sound/soc/tegra/tegra186_dspk.c
++++ b/sound/soc/tegra/tegra186_dspk.c
+@@ -1,8 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0-only
++// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ //
+ // tegra186_dspk.c - Tegra186 DSPK driver
+-//
+-// Copyright (c) 2020 NVIDIA CORPORATION. All rights reserved.
+
+ #include <linux/clk.h>
+ #include <linux/device.h>
+@@ -241,14 +240,14 @@ static int tegra186_dspk_hw_params(struct snd_pcm_substream *substream,
+ return -EINVAL;
+ }
+
+- cif_conf.client_bits = TEGRA_ACIF_BITS_24;
+-
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
++ cif_conf.client_bits = TEGRA_ACIF_BITS_16;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
++ cif_conf.client_bits = TEGRA_ACIF_BITS_24;
+ break;
+ default:
+ dev_err(dev, "unsupported format!\n");
+diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
+index b892d66f78470..1e760c3155213 100644
+--- a/sound/soc/ti/davinci-mcasp.c
++++ b/sound/soc/ti/davinci-mcasp.c
+@@ -2417,12 +2417,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+
+ mcasp_reparent_fck(pdev);
+
+- ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
+- &davinci_mcasp_dai[mcasp->op_mode], 1);
+-
+- if (ret != 0)
+- goto err;
+-
+ ret = davinci_mcasp_get_dma_type(mcasp);
+ switch (ret) {
+ case PCM_EDMA:
+@@ -2449,6 +2443,12 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
+ goto err;
+ }
+
++ ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
++ &davinci_mcasp_dai[mcasp->op_mode], 1);
++
++ if (ret != 0)
++ goto err;
++
+ no_audio:
+ ret = davinci_mcasp_init_gpiochip(mcasp);
+ if (ret) {
+diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c
+index b67617b68e509..f4437015d43a7 100644
+--- a/sound/usb/line6/driver.c
++++ b/sound/usb/line6/driver.c
+@@ -202,7 +202,7 @@ int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer,
+ struct urb *urb;
+
+ /* create message: */
+- msg = kmalloc(sizeof(struct message), GFP_ATOMIC);
++ msg = kzalloc(sizeof(struct message), GFP_ATOMIC);
+ if (msg == NULL)
+ return -ENOMEM;
+
+@@ -688,7 +688,7 @@ static int line6_init_cap_control(struct usb_line6 *line6)
+ int ret;
+
+ /* initialize USB buffers: */
+- line6->buffer_listen = kmalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL);
++ line6->buffer_listen = kzalloc(LINE6_BUFSIZE_LISTEN, GFP_KERNEL);
+ if (!line6->buffer_listen)
+ return -ENOMEM;
+
+@@ -697,7 +697,7 @@ static int line6_init_cap_control(struct usb_line6 *line6)
+ return -ENOMEM;
+
+ if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) {
+- line6->buffer_message = kmalloc(LINE6_MIDI_MESSAGE_MAXLEN, GFP_KERNEL);
++ line6->buffer_message = kzalloc(LINE6_MIDI_MESSAGE_MAXLEN, GFP_KERNEL);
+ if (!line6->buffer_message)
+ return -ENOMEM;
+
+diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
+index 4b0673bf52c2e..07cfad817d539 100644
+--- a/tools/include/linux/kernel.h
++++ b/tools/include/linux/kernel.h
+@@ -8,6 +8,7 @@
+ #include <linux/build_bug.h>
+ #include <linux/compiler.h>
+ #include <linux/math.h>
++#include <linux/panic.h>
+ #include <endian.h>
+ #include <byteswap.h>
+
+diff --git a/tools/include/linux/mm.h b/tools/include/linux/mm.h
+index f3c82ab5b14cd..7d73da0980473 100644
+--- a/tools/include/linux/mm.h
++++ b/tools/include/linux/mm.h
+@@ -37,4 +37,9 @@ static inline void totalram_pages_add(long count)
+ {
+ }
+
++static inline int early_pfn_to_nid(unsigned long pfn)
++{
++ return 0;
++}
++
+ #endif
+diff --git a/tools/include/linux/panic.h b/tools/include/linux/panic.h
+new file mode 100644
+index 0000000000000..9c8f17a41ce8e
+--- /dev/null
++++ b/tools/include/linux/panic.h
+@@ -0,0 +1,19 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _TOOLS_LINUX_PANIC_H
++#define _TOOLS_LINUX_PANIC_H
++
++#include <stdarg.h>
++#include <stdio.h>
++#include <stdlib.h>
++
++static inline void panic(const char *fmt, ...)
++{
++ va_list argp;
++
++ va_start(argp, fmt);
++ vfprintf(stderr, fmt, argp);
++ va_end(argp);
++ exit(-1);
++}
++
++#endif
+diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
+index 8f08c3fd498d5..1ba6340d3b3da 100644
+--- a/tools/power/x86/turbostat/turbostat.8
++++ b/tools/power/x86/turbostat/turbostat.8
+@@ -370,7 +370,7 @@ below the processor's base frequency.
+
+ Busy% = MPERF_delta/TSC_delta
+
+-Bzy_MHz = TSC_delta/APERF_delta/MPERF_delta/measurement_interval
++Bzy_MHz = TSC_delta*APERF_delta/MPERF_delta/measurement_interval
+
+ Note that these calculations depend on TSC_delta, so they
+ are not reliable during intervals when TSC_MHz is not running at the base frequency.
+diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
+index 7a334377f92b9..53b764422e804 100644
+--- a/tools/power/x86/turbostat/turbostat.c
++++ b/tools/power/x86/turbostat/turbostat.c
+@@ -53,6 +53,8 @@
+ #define NAME_BYTES 20
+ #define PATH_BYTES 128
+
++#define MAX_NOFILE 0x8000
++
+ enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE };
+ enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC };
+ enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT };
+@@ -989,8 +991,8 @@ struct pkg_data {
+ unsigned long long pc8;
+ unsigned long long pc9;
+ unsigned long long pc10;
+- unsigned long long cpu_lpi;
+- unsigned long long sys_lpi;
++ long long cpu_lpi;
++ long long sys_lpi;
+ unsigned long long pkg_wtd_core_c0;
+ unsigned long long pkg_any_core_c0;
+ unsigned long long pkg_any_gfxe_c0;
+@@ -1976,12 +1978,22 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data
+ if (DO_BIC(BIC_Pkgpc10))
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc10 / tsc);
+
+- if (DO_BIC(BIC_CPU_LPI))
+- outp +=
+- sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->cpu_lpi / 1000000.0 / interval_float);
+- if (DO_BIC(BIC_SYS_LPI))
+- outp +=
+- sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->sys_lpi / 1000000.0 / interval_float);
++ if (DO_BIC(BIC_CPU_LPI)) {
++ if (p->cpu_lpi >= 0)
++ outp +=
++ sprintf(outp, "%s%.2f", (printed++ ? delim : ""),
++ 100.0 * p->cpu_lpi / 1000000.0 / interval_float);
++ else
++ outp += sprintf(outp, "%s(neg)", (printed++ ? delim : ""));
++ }
++ if (DO_BIC(BIC_SYS_LPI)) {
++ if (p->sys_lpi >= 0)
++ outp +=
++ sprintf(outp, "%s%.2f", (printed++ ? delim : ""),
++ 100.0 * p->sys_lpi / 1000000.0 / interval_float);
++ else
++ outp += sprintf(outp, "%s(neg)", (printed++ ? delim : ""));
++ }
+
+ if (DO_BIC(BIC_PkgWatt))
+ outp +=
+@@ -2444,9 +2456,10 @@ int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
+ average.packages.rapl_dram_perf_status += p->rapl_dram_perf_status;
+
+ for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
+- if (mp->format == FORMAT_RAW)
+- continue;
+- average.packages.counter[i] += p->counter[i];
++ if ((mp->format == FORMAT_RAW) && (topo.num_packages == 0))
++ average.packages.counter[i] = p->counter[i];
++ else
++ average.packages.counter[i] += p->counter[i];
+ }
+ return 0;
+ }
+@@ -2599,7 +2612,7 @@ unsigned long long get_uncore_mhz(int package, int die)
+ {
+ char path[128];
+
+- sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/current_freq_khz", package,
++ sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/current_freq_khz", package,
+ die);
+
+ return (snapshot_sysfs_counter(path) / 1000);
+@@ -3829,7 +3842,8 @@ void re_initialize(void)
+ {
+ free_all_buffers();
+ setup_all_buffers(false);
+- fprintf(outf, "turbostat: re-initialized with num_cpus %d, allowed_cpus %d\n", topo.num_cpus, topo.allowed_cpus);
++ fprintf(outf, "turbostat: re-initialized with num_cpus %d, allowed_cpus %d\n", topo.num_cpus,
++ topo.allowed_cpus);
+ }
+
+ void set_max_cpu_num(void)
+@@ -4567,20 +4581,15 @@ static void dump_sysfs_file(char *path)
+ static void probe_intel_uncore_frequency(void)
+ {
+ int i, j;
+- char path[128];
++ char path[256];
+
+ if (!genuine_intel)
+ return;
+
+- if (access("/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00", R_OK))
+- return;
+-
+- /* Cluster level sysfs not supported yet. */
+- if (!access("/sys/devices/system/cpu/intel_uncore_frequency/uncore00", R_OK))
+- return;
++ if (access("/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/current_freq_khz", R_OK))
++ goto probe_cluster;
+
+- if (!access("/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/current_freq_khz", R_OK))
+- BIC_PRESENT(BIC_UNCORE_MHZ);
++ BIC_PRESENT(BIC_UNCORE_MHZ);
+
+ if (quiet)
+ return;
+@@ -4588,26 +4597,73 @@ static void probe_intel_uncore_frequency(void)
+ for (i = 0; i < topo.num_packages; ++i) {
+ for (j = 0; j < topo.num_die; ++j) {
+ int k, l;
++ char path_base[128];
++
++ sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d", i,
++ j);
+
+- sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/min_freq_khz",
+- i, j);
++ sprintf(path, "%s/min_freq_khz", path_base);
+ k = read_sysfs_int(path);
+- sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/max_freq_khz",
+- i, j);
++ sprintf(path, "%s/max_freq_khz", path_base);
+ l = read_sysfs_int(path);
+- fprintf(outf, "Uncore Frequency pkg%d die%d: %d - %d MHz ", i, j, k / 1000, l / 1000);
++ fprintf(outf, "Uncore Frequency package%d die%d: %d - %d MHz ", i, j, k / 1000, l / 1000);
+
+- sprintf(path,
+- "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/initial_min_freq_khz",
+- i, j);
++ sprintf(path, "%s/initial_min_freq_khz", path_base);
+ k = read_sysfs_int(path);
+- sprintf(path,
+- "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/initial_max_freq_khz",
+- i, j);
++ sprintf(path, "%s/initial_max_freq_khz", path_base);
+ l = read_sysfs_int(path);
+- fprintf(outf, "(%d - %d MHz)\n", k / 1000, l / 1000);
++ fprintf(outf, "(%d - %d MHz)", k / 1000, l / 1000);
++
++ sprintf(path, "%s/current_freq_khz", path_base);
++ k = read_sysfs_int(path);
++ fprintf(outf, " %d MHz\n", k / 1000);
+ }
+ }
++ return;
++
++probe_cluster:
++ if (access("/sys/devices/system/cpu/intel_uncore_frequency/uncore00/current_freq_khz", R_OK))
++ return;
++
++ if (quiet)
++ return;
++
++ for (i = 0;; ++i) {
++ int k, l;
++ char path_base[128];
++ int package_id, domain_id, cluster_id;
++
++ sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/uncore%02d", i);
++
++ if (access(path_base, R_OK))
++ break;
++
++ sprintf(path, "%s/package_id", path_base);
++ package_id = read_sysfs_int(path);
++
++ sprintf(path, "%s/domain_id", path_base);
++ domain_id = read_sysfs_int(path);
++
++ sprintf(path, "%s/fabric_cluster_id", path_base);
++ cluster_id = read_sysfs_int(path);
++
++ sprintf(path, "%s/min_freq_khz", path_base);
++ k = read_sysfs_int(path);
++ sprintf(path, "%s/max_freq_khz", path_base);
++ l = read_sysfs_int(path);
++ fprintf(outf, "Uncore Frequency package%d domain%d cluster%d: %d - %d MHz ", package_id, domain_id,
++ cluster_id, k / 1000, l / 1000);
++
++ sprintf(path, "%s/initial_min_freq_khz", path_base);
++ k = read_sysfs_int(path);
++ sprintf(path, "%s/initial_max_freq_khz", path_base);
++ l = read_sysfs_int(path);
++ fprintf(outf, "(%d - %d MHz)", k / 1000, l / 1000);
++
++ sprintf(path, "%s/current_freq_khz", path_base);
++ k = read_sysfs_int(path);
++ fprintf(outf, " %d MHz\n", k / 1000);
++ }
+ }
+
+ static void probe_graphics(void)
+@@ -5489,7 +5545,8 @@ void print_dev_latency(void)
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+- warnx("capget(CAP_SYS_ADMIN) failed, try \"# setcap cap_sys_admin=ep %s\"", progname);
++ if (debug)
++ warnx("Read %s failed", path);
+ return;
+ }
+
+@@ -5623,6 +5680,7 @@ void process_cpuid()
+ unsigned int eax, ebx, ecx, edx;
+ unsigned int fms, family, model, stepping, ecx_flags, edx_flags;
+ unsigned long long ucode_patch = 0;
++ bool ucode_patch_valid = false;
+
+ eax = ebx = ecx = edx = 0;
+
+@@ -5652,6 +5710,8 @@ void process_cpuid()
+
+ if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch))
+ warnx("get_msr(UCODE)");
++ else
++ ucode_patch_valid = true;
+
+ /*
+ * check max extended function levels of CPUID.
+@@ -5662,9 +5722,12 @@ void process_cpuid()
+ __cpuid(0x80000000, max_extended_level, ebx, ecx, edx);
+
+ if (!quiet) {
+- fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d) microcode 0x%x\n",
+- family, model, stepping, family, model, stepping,
+- (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF));
++ fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d)",
++ family, model, stepping, family, model, stepping);
++ if (ucode_patch_valid)
++ fprintf(outf, " microcode 0x%x", (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF));
++ fputc('\n', outf);
++
+ fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level);
+ fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s %s\n",
+ ecx_flags & (1 << 0) ? "SSE3" : "-",
+@@ -6142,6 +6205,7 @@ void topology_update(void)
+ topo.allowed_packages = 0;
+ for_all_cpus(update_topo, ODD_COUNTERS);
+ }
++
+ void setup_all_buffers(bool startup)
+ {
+ topology_probe(startup);
+@@ -6704,6 +6768,22 @@ void cmdline(int argc, char **argv)
+ }
+ }
+
++void set_rlimit(void)
++{
++ struct rlimit limit;
++
++ if (getrlimit(RLIMIT_NOFILE, &limit) < 0)
++ err(1, "Failed to get rlimit");
++
++ if (limit.rlim_max < MAX_NOFILE)
++ limit.rlim_max = MAX_NOFILE;
++ if (limit.rlim_cur < MAX_NOFILE)
++ limit.rlim_cur = MAX_NOFILE;
++
++ if (setrlimit(RLIMIT_NOFILE, &limit) < 0)
++ err(1, "Failed to set rlimit");
++}
++
+ int main(int argc, char **argv)
+ {
+ int fd, ret;
+@@ -6729,6 +6809,9 @@ int main(int argc, char **argv)
+
+ probe_sysfs();
+
++ if (!getuid())
++ set_rlimit();
++
+ turbostat_init();
+
+ msr_sum_record();
+diff --git a/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c b/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c
+index 053f4d6da77a4..cc184e4420f6e 100644
+--- a/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c
++++ b/tools/testing/selftests/bpf/prog_tests/bloom_filter_map.c
+@@ -2,6 +2,7 @@
+ /* Copyright (c) 2021 Facebook */
+
+ #include <sys/syscall.h>
++#include <limits.h>
+ #include <test_progs.h>
+ #include "bloom_filter_map.skel.h"
+
+@@ -21,6 +22,11 @@ static void test_fail_cases(void)
+ if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid value size 0"))
+ close(fd);
+
++ /* Invalid value size: too big */
++ fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, INT32_MAX, 100, NULL);
++ if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid value too large"))
++ close(fd);
++
+ /* Invalid max entries size */
+ fd = bpf_map_create(BPF_MAP_TYPE_BLOOM_FILTER, NULL, 0, sizeof(value), 0, NULL);
+ if (!ASSERT_LT(fd, 0, "bpf_map_create bloom filter invalid max entries size"))
+diff --git a/tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc b/tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc
+index 2de7c61d1ae30..3f74c09c56b62 100644
+--- a/tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc
++++ b/tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc
+@@ -24,7 +24,7 @@ echo 0 > events/enable
+ echo "Get the most frequently calling function"
+ sample_events
+
+-target_func=`cut -d: -f3 trace | sed 's/call_site=\([^+]*\)+0x.*/\1/' | sort | uniq -c | sort | tail -n 1 | sed 's/^[ 0-9]*//'`
++target_func=`cat trace | grep -o 'call_site=\([^+]*\)' | sed 's/call_site=//' | sort | uniq -c | sort | tail -n 1 | sed 's/^[ 0-9]*//'`
+ if [ -z "$target_func" ]; then
+ exit_fail
+ fi
+diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile
+index 2453add65d12f..c04a81535ed41 100644
+--- a/tools/testing/selftests/mm/Makefile
++++ b/tools/testing/selftests/mm/Makefile
+@@ -12,7 +12,7 @@ uname_M := $(shell uname -m 2>/dev/null || echo not)
+ else
+ uname_M := $(shell echo $(CROSS_COMPILE) | grep -o '^[a-z0-9]\+')
+ endif
+-ARCH ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/' -e 's/ppc64.*/ppc64/')
++ARCH ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/' -e 's/ppc64.*/powerpc/')
+ endif
+
+ # Without this, failed build products remain, with up-to-date timestamps,
+@@ -97,13 +97,13 @@ TEST_GEN_FILES += $(BINARIES_64)
+ endif
+ else
+
+-ifneq (,$(findstring $(ARCH),ppc64))
++ifneq (,$(findstring $(ARCH),powerpc))
+ TEST_GEN_FILES += protection_keys
+ endif
+
+ endif
+
+-ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 ppc64 riscv64 s390x sparc64 x86_64))
++ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 powerpc riscv64 s390x sparc64 x86_64))
+ TEST_GEN_FILES += va_high_addr_switch
+ TEST_GEN_FILES += virtual_address_range
+ TEST_GEN_FILES += write_to_hugetlbfs
+diff --git a/tools/testing/selftests/net/test_bridge_neigh_suppress.sh b/tools/testing/selftests/net/test_bridge_neigh_suppress.sh
+index 8533393a4f186..02b986c9c247d 100755
+--- a/tools/testing/selftests/net/test_bridge_neigh_suppress.sh
++++ b/tools/testing/selftests/net/test_bridge_neigh_suppress.sh
+@@ -154,17 +154,9 @@ setup_topo()
+ setup_topo_ns $ns
+ done
+
+- ip link add name veth0 type veth peer name veth1
+- ip link set dev veth0 netns $h1 name eth0
+- ip link set dev veth1 netns $sw1 name swp1
+-
+- ip link add name veth0 type veth peer name veth1
+- ip link set dev veth0 netns $sw1 name veth0
+- ip link set dev veth1 netns $sw2 name veth0
+-
+- ip link add name veth0 type veth peer name veth1
+- ip link set dev veth0 netns $h2 name eth0
+- ip link set dev veth1 netns $sw2 name swp1
++ ip -n $h1 link add name eth0 type veth peer name swp1 netns $sw1
++ ip -n $sw1 link add name veth0 type veth peer name veth0 netns $sw2
++ ip -n $h2 link add name eth0 type veth peer name swp1 netns $sw2
+ }
+
+ setup_host_common()
+diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c
+index 48b9a803235a8..d13ebde203221 100644
+--- a/tools/testing/selftests/timers/valid-adjtimex.c
++++ b/tools/testing/selftests/timers/valid-adjtimex.c
+@@ -21,9 +21,6 @@
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+-
+-
+-
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <time.h>
+@@ -62,45 +59,47 @@ int clear_time_state(void)
+ #define NUM_FREQ_OUTOFRANGE 4
+ #define NUM_FREQ_INVALID 2
+
++#define SHIFTED_PPM (1 << 16)
++
+ long valid_freq[NUM_FREQ_VALID] = {
+- -499<<16,
+- -450<<16,
+- -400<<16,
+- -350<<16,
+- -300<<16,
+- -250<<16,
+- -200<<16,
+- -150<<16,
+- -100<<16,
+- -75<<16,
+- -50<<16,
+- -25<<16,
+- -10<<16,
+- -5<<16,
+- -1<<16,
++ -499 * SHIFTED_PPM,
++ -450 * SHIFTED_PPM,
++ -400 * SHIFTED_PPM,
++ -350 * SHIFTED_PPM,
++ -300 * SHIFTED_PPM,
++ -250 * SHIFTED_PPM,
++ -200 * SHIFTED_PPM,
++ -150 * SHIFTED_PPM,
++ -100 * SHIFTED_PPM,
++ -75 * SHIFTED_PPM,
++ -50 * SHIFTED_PPM,
++ -25 * SHIFTED_PPM,
++ -10 * SHIFTED_PPM,
++ -5 * SHIFTED_PPM,
++ -1 * SHIFTED_PPM,
+ -1000,
+- 1<<16,
+- 5<<16,
+- 10<<16,
+- 25<<16,
+- 50<<16,
+- 75<<16,
+- 100<<16,
+- 150<<16,
+- 200<<16,
+- 250<<16,
+- 300<<16,
+- 350<<16,
+- 400<<16,
+- 450<<16,
+- 499<<16,
++ 1 * SHIFTED_PPM,
++ 5 * SHIFTED_PPM,
++ 10 * SHIFTED_PPM,
++ 25 * SHIFTED_PPM,
++ 50 * SHIFTED_PPM,
++ 75 * SHIFTED_PPM,
++ 100 * SHIFTED_PPM,
++ 150 * SHIFTED_PPM,
++ 200 * SHIFTED_PPM,
++ 250 * SHIFTED_PPM,
++ 300 * SHIFTED_PPM,
++ 350 * SHIFTED_PPM,
++ 400 * SHIFTED_PPM,
++ 450 * SHIFTED_PPM,
++ 499 * SHIFTED_PPM,
+ };
+
+ long outofrange_freq[NUM_FREQ_OUTOFRANGE] = {
+- -1000<<16,
+- -550<<16,
+- 550<<16,
+- 1000<<16,
++ -1000 * SHIFTED_PPM,
++ -550 * SHIFTED_PPM,
++ 550 * SHIFTED_PPM,
++ 1000 * SHIFTED_PPM,
+ };
+
+ #define LONG_MAX (~0UL>>1)
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-05-25 15:18 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-05-25 15:18 UTC (permalink / raw
To: gentoo-commits
commit: 4c9513c83791150732d91fe7bccec0cdd207e493
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Sat May 25 15:17:57 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Sat May 25 15:17:57 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=4c9513c8
Linux patch 6.8.11
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1010_linux-6.8.11.patch | 1585 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1589 insertions(+)
diff --git a/0000_README b/0000_README
index a90ed274..7fa03211 100644
--- a/0000_README
+++ b/0000_README
@@ -83,6 +83,10 @@ Patch: 1009_linux-6.8.10.patch
From: https://www.kernel.org
Desc: Linux 6.8.10
+Patch: 1010_linux-6.8.11.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.11
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1010_linux-6.8.11.patch b/1010_linux-6.8.11.patch
new file mode 100644
index 00000000..e6516e5a
--- /dev/null
+++ b/1010_linux-6.8.11.patch
@@ -0,0 +1,1585 @@
+diff --git a/Documentation/ABI/stable/sysfs-block b/Documentation/ABI/stable/sysfs-block
+index 1fe9a553c37b7..f0025d1c3d5ac 100644
+--- a/Documentation/ABI/stable/sysfs-block
++++ b/Documentation/ABI/stable/sysfs-block
+@@ -101,6 +101,16 @@ Description:
+ devices that support receiving integrity metadata.
+
+
++What: /sys/block/<disk>/partscan
++Date: May 2024
++Contact: Christoph Hellwig <hch@lst.de>
++Description:
++ The /sys/block/<disk>/partscan files reports if partition
++ scanning is enabled for the disk. It returns "1" if partition
++ scanning is enabled, or "0" if not. The value type is a 32-bit
++ unsigned integer, but only "0" and "1" are valid values.
++
++
+ What: /sys/block/<disk>/<partition>/alignment_offset
+ Date: April 2009
+ Contact: Martin K. Petersen <martin.petersen@oracle.com>
+diff --git a/Documentation/admin-guide/hw-vuln/core-scheduling.rst b/Documentation/admin-guide/hw-vuln/core-scheduling.rst
+index cf1eeefdfc32f..a92e10ec402e7 100644
+--- a/Documentation/admin-guide/hw-vuln/core-scheduling.rst
++++ b/Documentation/admin-guide/hw-vuln/core-scheduling.rst
+@@ -67,8 +67,8 @@ arg4:
+ will be performed for all tasks in the task group of ``pid``.
+
+ arg5:
+- userspace pointer to an unsigned long for storing the cookie returned by
+- ``PR_SCHED_CORE_GET`` command. Should be 0 for all other commands.
++ userspace pointer to an unsigned long long for storing the cookie returned
++ by ``PR_SCHED_CORE_GET`` command. Should be 0 for all other commands.
+
+ In order for a process to push a cookie to, or pull a cookie from a process, it
+ is required to have the ptrace access mode: `PTRACE_MODE_READ_REALCREDS` to the
+diff --git a/Documentation/admin-guide/mm/damon/usage.rst b/Documentation/admin-guide/mm/damon/usage.rst
+index 9d23144bf9850..87fdc258d1027 100644
+--- a/Documentation/admin-guide/mm/damon/usage.rst
++++ b/Documentation/admin-guide/mm/damon/usage.rst
+@@ -450,7 +450,7 @@ pages of all memory cgroups except ``/having_care_already``.::
+ # # further filter out all cgroups except one at '/having_care_already'
+ echo memcg > 1/type
+ echo /having_care_already > 1/memcg_path
+- echo N > 1/matching
++ echo Y > 1/matching
+
+ Note that ``anon`` and ``memcg`` filters are currently supported only when
+ ``paddr`` :ref:`implementation <sysfs_context>` is being used.
+diff --git a/Documentation/sphinx/kernel_include.py b/Documentation/sphinx/kernel_include.py
+index abe7680883771..6387624423363 100755
+--- a/Documentation/sphinx/kernel_include.py
++++ b/Documentation/sphinx/kernel_include.py
+@@ -97,7 +97,6 @@ class KernelInclude(Include):
+ # HINT: this is the only line I had to change / commented out:
+ #path = utils.relative_path(None, path)
+
+- path = nodes.reprunicode(path)
+ encoding = self.options.get(
+ 'encoding', self.state.document.settings.input_encoding)
+ e_handler=self.state.document.settings.input_encoding_error_handler
+diff --git a/Makefile b/Makefile
+index 01acaf667e789..ce6b03cce386d 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 10
++SUBLEVEL = 11
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/block/genhd.c b/block/genhd.c
+index d74fb5b4ae681..d0471f469f7d0 100644
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -345,9 +345,7 @@ int disk_scan_partitions(struct gendisk *disk, blk_mode_t mode)
+ struct bdev_handle *handle;
+ int ret = 0;
+
+- if (disk->flags & (GENHD_FL_NO_PART | GENHD_FL_HIDDEN))
+- return -EINVAL;
+- if (test_bit(GD_SUPPRESS_PART_SCAN, &disk->state))
++ if (!disk_has_partscan(disk))
+ return -EINVAL;
+ if (disk->open_partitions)
+ return -EBUSY;
+@@ -503,8 +501,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
+ goto out_unregister_bdi;
+
+ /* Make sure the first partition scan will be proceed */
+- if (get_capacity(disk) && !(disk->flags & GENHD_FL_NO_PART) &&
+- !test_bit(GD_SUPPRESS_PART_SCAN, &disk->state))
++ if (get_capacity(disk) && disk_has_partscan(disk))
+ set_bit(GD_NEED_PART_SCAN, &disk->state);
+
+ bdev_add(disk->part0, ddev->devt);
+@@ -1047,6 +1044,12 @@ static ssize_t diskseq_show(struct device *dev,
+ return sprintf(buf, "%llu\n", disk->diskseq);
+ }
+
++static ssize_t partscan_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "%u\n", disk_has_partscan(dev_to_disk(dev)));
++}
++
+ static DEVICE_ATTR(range, 0444, disk_range_show, NULL);
+ static DEVICE_ATTR(ext_range, 0444, disk_ext_range_show, NULL);
+ static DEVICE_ATTR(removable, 0444, disk_removable_show, NULL);
+@@ -1060,6 +1063,7 @@ static DEVICE_ATTR(stat, 0444, part_stat_show, NULL);
+ static DEVICE_ATTR(inflight, 0444, part_inflight_show, NULL);
+ static DEVICE_ATTR(badblocks, 0644, disk_badblocks_show, disk_badblocks_store);
+ static DEVICE_ATTR(diskseq, 0444, diskseq_show, NULL);
++static DEVICE_ATTR(partscan, 0444, partscan_show, NULL);
+
+ #ifdef CONFIG_FAIL_MAKE_REQUEST
+ ssize_t part_fail_show(struct device *dev,
+@@ -1106,6 +1110,7 @@ static struct attribute *disk_attrs[] = {
+ &dev_attr_events_async.attr,
+ &dev_attr_events_poll_msecs.attr,
+ &dev_attr_diskseq.attr,
++ &dev_attr_partscan.attr,
+ #ifdef CONFIG_FAIL_MAKE_REQUEST
+ &dev_attr_fail.attr,
+ #endif
+diff --git a/block/partitions/core.c b/block/partitions/core.c
+index 5f5ed5c75f04d..eac887755f4f0 100644
+--- a/block/partitions/core.c
++++ b/block/partitions/core.c
+@@ -584,10 +584,7 @@ static int blk_add_partitions(struct gendisk *disk)
+ struct parsed_partitions *state;
+ int ret = -EAGAIN, p;
+
+- if (disk->flags & GENHD_FL_NO_PART)
+- return 0;
+-
+- if (test_bit(GD_SUPPRESS_PART_SCAN, &disk->state))
++ if (!disk_has_partscan(disk))
+ return 0;
+
+ state = check_partition(disk);
+diff --git a/drivers/android/binder.c b/drivers/android/binder.c
+index d6f14c8e20be3..e029687e57322 100644
+--- a/drivers/android/binder.c
++++ b/drivers/android/binder.c
+@@ -5367,7 +5367,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+ goto err;
+ break;
+ case BINDER_SET_MAX_THREADS: {
+- int max_threads;
++ u32 max_threads;
+
+ if (copy_from_user(&max_threads, ubuf,
+ sizeof(max_threads))) {
+diff --git a/drivers/android/binder_internal.h b/drivers/android/binder_internal.h
+index 7270d4d222070..5b7c80b99ae86 100644
+--- a/drivers/android/binder_internal.h
++++ b/drivers/android/binder_internal.h
+@@ -421,7 +421,7 @@ struct binder_proc {
+ struct list_head todo;
+ struct binder_stats stats;
+ struct list_head delivered_death;
+- int max_threads;
++ u32 max_threads;
+ int requested_threads;
+ int requested_threads_started;
+ int tmp_ref;
+diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+index 0df6c55eb3260..6b10124e21b72 100644
+--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
++++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+@@ -1050,7 +1050,12 @@ static bool setup_dsc_config(
+ if (!is_dsc_possible)
+ goto done;
+
+- dsc_cfg->num_slices_v = pic_height/slice_height;
++ if (slice_height > 0) {
++ dsc_cfg->num_slices_v = pic_height / slice_height;
++ } else {
++ is_dsc_possible = false;
++ goto done;
++ }
+
+ if (target_bandwidth_kbps > 0) {
+ is_dsc_possible = decide_dsc_target_bpp_x16(
+diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
+index 7b550d7d96b68..1ff9818b4c84f 100644
+--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c
++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
+@@ -550,17 +550,15 @@ bool ice_vc_isvalid_vsi_id(struct ice_vf *vf, u16 vsi_id)
+
+ /**
+ * ice_vc_isvalid_q_id
+- * @vf: pointer to the VF info
+- * @vsi_id: VSI ID
++ * @vsi: VSI to check queue ID against
+ * @qid: VSI relative queue ID
+ *
+ * check for the valid queue ID
+ */
+-static bool ice_vc_isvalid_q_id(struct ice_vf *vf, u16 vsi_id, u8 qid)
++static bool ice_vc_isvalid_q_id(struct ice_vsi *vsi, u8 qid)
+ {
+- struct ice_vsi *vsi = ice_find_vsi(vf->pf, vsi_id);
+ /* allocated Tx and Rx queues should be always equal for VF VSI */
+- return (vsi && (qid < vsi->alloc_txq));
++ return qid < vsi->alloc_txq;
+ }
+
+ /**
+@@ -1318,7 +1316,7 @@ static int ice_vc_ena_qs_msg(struct ice_vf *vf, u8 *msg)
+ */
+ q_map = vqs->rx_queues;
+ for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) {
+- if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) {
++ if (!ice_vc_isvalid_q_id(vsi, vf_q_id)) {
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto error_param;
+ }
+@@ -1340,7 +1338,7 @@ static int ice_vc_ena_qs_msg(struct ice_vf *vf, u8 *msg)
+
+ q_map = vqs->tx_queues;
+ for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) {
+- if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) {
++ if (!ice_vc_isvalid_q_id(vsi, vf_q_id)) {
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto error_param;
+ }
+@@ -1445,7 +1443,7 @@ static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg)
+ q_map = vqs->tx_queues;
+
+ for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) {
+- if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) {
++ if (!ice_vc_isvalid_q_id(vsi, vf_q_id)) {
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto error_param;
+ }
+@@ -1471,7 +1469,7 @@ static int ice_vc_dis_qs_msg(struct ice_vf *vf, u8 *msg)
+ bitmap_zero(vf->rxq_ena, ICE_MAX_RSS_QS_PER_VF);
+ } else if (q_map) {
+ for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) {
+- if (!ice_vc_isvalid_q_id(vf, vqs->vsi_id, vf_q_id)) {
++ if (!ice_vc_isvalid_q_id(vsi, vf_q_id)) {
+ v_ret = VIRTCHNL_STATUS_ERR_PARAM;
+ goto error_param;
+ }
+@@ -1527,7 +1525,7 @@ ice_cfg_interrupt(struct ice_vf *vf, struct ice_vsi *vsi, u16 vector_id,
+ for_each_set_bit(vsi_q_id_idx, &qmap, ICE_MAX_RSS_QS_PER_VF) {
+ vsi_q_id = vsi_q_id_idx;
+
+- if (!ice_vc_isvalid_q_id(vf, vsi->vsi_num, vsi_q_id))
++ if (!ice_vc_isvalid_q_id(vsi, vsi_q_id))
+ return VIRTCHNL_STATUS_ERR_PARAM;
+
+ q_vector->num_ring_rx++;
+@@ -1541,7 +1539,7 @@ ice_cfg_interrupt(struct ice_vf *vf, struct ice_vsi *vsi, u16 vector_id,
+ for_each_set_bit(vsi_q_id_idx, &qmap, ICE_MAX_RSS_QS_PER_VF) {
+ vsi_q_id = vsi_q_id_idx;
+
+- if (!ice_vc_isvalid_q_id(vf, vsi->vsi_num, vsi_q_id))
++ if (!ice_vc_isvalid_q_id(vsi, vsi_q_id))
+ return VIRTCHNL_STATUS_ERR_PARAM;
+
+ q_vector->num_ring_tx++;
+@@ -1698,7 +1696,7 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
+ qpi->txq.headwb_enabled ||
+ !ice_vc_isvalid_ring_len(qpi->txq.ring_len) ||
+ !ice_vc_isvalid_ring_len(qpi->rxq.ring_len) ||
+- !ice_vc_isvalid_q_id(vf, qci->vsi_id, qpi->txq.queue_id)) {
++ !ice_vc_isvalid_q_id(vsi, qpi->txq.queue_id)) {
+ goto error_param;
+ }
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c
+index f001553e1a1a0..8e4ff3af86c68 100644
+--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c
++++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_fdir.c
+@@ -94,9 +94,6 @@ ice_vc_fdir_param_check(struct ice_vf *vf, u16 vsi_id)
+ if (!(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_FDIR_PF))
+ return -EINVAL;
+
+- if (vsi_id != vf->lan_vsi_num)
+- return -EINVAL;
+-
+ if (!ice_vc_isvalid_vsi_id(vf, vsi_id))
+ return -EINVAL;
+
+diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c
+index 502518cdb4618..6453c92f0fa7c 100644
+--- a/drivers/net/ethernet/micrel/ks8851_common.c
++++ b/drivers/net/ethernet/micrel/ks8851_common.c
+@@ -328,7 +328,6 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
+ {
+ struct ks8851_net *ks = _ks;
+ struct sk_buff_head rxq;
+- unsigned handled = 0;
+ unsigned long flags;
+ unsigned int status;
+ struct sk_buff *skb;
+@@ -336,24 +335,17 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
+ ks8851_lock(ks, &flags);
+
+ status = ks8851_rdreg16(ks, KS_ISR);
++ ks8851_wrreg16(ks, KS_ISR, status);
+
+ netif_dbg(ks, intr, ks->netdev,
+ "%s: status 0x%04x\n", __func__, status);
+
+- if (status & IRQ_LCI)
+- handled |= IRQ_LCI;
+-
+ if (status & IRQ_LDI) {
+ u16 pmecr = ks8851_rdreg16(ks, KS_PMECR);
+ pmecr &= ~PMECR_WKEVT_MASK;
+ ks8851_wrreg16(ks, KS_PMECR, pmecr | PMECR_WKEVT_LINK);
+-
+- handled |= IRQ_LDI;
+ }
+
+- if (status & IRQ_RXPSI)
+- handled |= IRQ_RXPSI;
+-
+ if (status & IRQ_TXI) {
+ unsigned short tx_space = ks8851_rdreg16(ks, KS_TXMIR);
+
+@@ -365,20 +357,12 @@ static irqreturn_t ks8851_irq(int irq, void *_ks)
+ if (netif_queue_stopped(ks->netdev))
+ netif_wake_queue(ks->netdev);
+ spin_unlock(&ks->statelock);
+-
+- handled |= IRQ_TXI;
+ }
+
+- if (status & IRQ_RXI)
+- handled |= IRQ_RXI;
+-
+ if (status & IRQ_SPIBEI) {
+ netdev_err(ks->netdev, "%s: spi bus error\n", __func__);
+- handled |= IRQ_SPIBEI;
+ }
+
+- ks8851_wrreg16(ks, KS_ISR, handled);
+-
+ if (status & IRQ_RXI) {
+ /* the datasheet says to disable the rx interrupt during
+ * packet read-out, however we're masking the interrupt
+diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
+index 21b6c4d94a632..6d31061818e93 100644
+--- a/drivers/net/usb/ax88179_178a.c
++++ b/drivers/net/usb/ax88179_178a.c
+@@ -174,6 +174,7 @@ struct ax88179_data {
+ u32 wol_supported;
+ u32 wolopts;
+ u8 disconnecting;
++ u8 initialized;
+ };
+
+ struct ax88179_int_data {
+@@ -1673,6 +1674,18 @@ static int ax88179_reset(struct usbnet *dev)
+ return 0;
+ }
+
++static int ax88179_net_reset(struct usbnet *dev)
++{
++ struct ax88179_data *ax179_data = dev->driver_priv;
++
++ if (ax179_data->initialized)
++ ax88179_reset(dev);
++ else
++ ax179_data->initialized = 1;
++
++ return 0;
++}
++
+ static int ax88179_stop(struct usbnet *dev)
+ {
+ u16 tmp16;
+@@ -1692,6 +1705,7 @@ static const struct driver_info ax88179_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1704,6 +1718,7 @@ static const struct driver_info ax88178a_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1716,7 +1731,7 @@ static const struct driver_info cypress_GX3_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1729,7 +1744,7 @@ static const struct driver_info dlink_dub1312_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1742,7 +1757,7 @@ static const struct driver_info sitecom_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1755,7 +1770,7 @@ static const struct driver_info samsung_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1768,7 +1783,7 @@ static const struct driver_info lenovo_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1781,7 +1796,7 @@ static const struct driver_info belkin_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1794,7 +1809,7 @@ static const struct driver_info toshiba_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1807,7 +1822,7 @@ static const struct driver_info mct_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1820,7 +1835,7 @@ static const struct driver_info at_umc2000_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1833,7 +1848,7 @@ static const struct driver_info at_umc200_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+@@ -1846,7 +1861,7 @@ static const struct driver_info at_umc2000sp_info = {
+ .unbind = ax88179_unbind,
+ .status = ax88179_status,
+ .link_reset = ax88179_link_reset,
+- .reset = ax88179_reset,
++ .reset = ax88179_net_reset,
+ .stop = ax88179_stop,
+ .flags = FLAG_ETHER | FLAG_FRAMING_AX,
+ .rx_fixup = ax88179_rx_fixup,
+diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
+index a35409eda0cf2..67518291a8ad6 100644
+--- a/drivers/remoteproc/mtk_scp.c
++++ b/drivers/remoteproc/mtk_scp.c
+@@ -132,7 +132,7 @@ static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
+ static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw)
+ {
+ int ret;
+- size_t offset;
++ size_t buf_sz, offset;
+
+ /* read the ipi buf addr from FW itself first */
+ ret = scp_elf_read_ipi_buf_addr(scp, fw, &offset);
+@@ -144,6 +144,14 @@ static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw)
+ }
+ dev_info(scp->dev, "IPI buf addr %#010zx\n", offset);
+
++ /* Make sure IPI buffer fits in the L2TCM range assigned to this core */
++ buf_sz = sizeof(*scp->recv_buf) + sizeof(*scp->send_buf);
++
++ if (scp->sram_size < buf_sz + offset) {
++ dev_err(scp->dev, "IPI buffer does not fit in SRAM.\n");
++ return -EOVERFLOW;
++ }
++
+ scp->recv_buf = (struct mtk_share_obj __iomem *)
+ (scp->sram_base + offset);
+ scp->send_buf = (struct mtk_share_obj __iomem *)
+diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c
+index 7ce7bb1640054..58ea1e1391cee 100644
+--- a/drivers/tty/serial/kgdboc.c
++++ b/drivers/tty/serial/kgdboc.c
+@@ -19,6 +19,7 @@
+ #include <linux/console.h>
+ #include <linux/vt_kern.h>
+ #include <linux/input.h>
++#include <linux/irq_work.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/serial_core.h>
+@@ -48,6 +49,25 @@ static struct kgdb_io kgdboc_earlycon_io_ops;
+ static int (*earlycon_orig_exit)(struct console *con);
+ #endif /* IS_BUILTIN(CONFIG_KGDB_SERIAL_CONSOLE) */
+
++/*
++ * When we leave the debug trap handler we need to reset the keyboard status
++ * (since the original keyboard state gets partially clobbered by kdb use of
++ * the keyboard).
++ *
++ * The path to deliver the reset is somewhat circuitous.
++ *
++ * To deliver the reset we register an input handler, reset the keyboard and
++ * then deregister the input handler. However, to get this done right, we do
++ * have to carefully manage the calling context because we can only register
++ * input handlers from task context.
++ *
++ * In particular we need to trigger the action from the debug trap handler with
++ * all its NMI and/or NMI-like oddities. To solve this the kgdboc trap exit code
++ * (the "post_exception" callback) uses irq_work_queue(), which is NMI-safe, to
++ * schedule a callback from a hardirq context. From there we have to defer the
++ * work again, this time using schedule_work(), to get a callback using the
++ * system workqueue, which runs in task context.
++ */
+ #ifdef CONFIG_KDB_KEYBOARD
+ static int kgdboc_reset_connect(struct input_handler *handler,
+ struct input_dev *dev,
+@@ -99,10 +119,17 @@ static void kgdboc_restore_input_helper(struct work_struct *dummy)
+
+ static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper);
+
++static void kgdboc_queue_restore_input_helper(struct irq_work *unused)
++{
++ schedule_work(&kgdboc_restore_input_work);
++}
++
++static DEFINE_IRQ_WORK(kgdboc_restore_input_irq_work, kgdboc_queue_restore_input_helper);
++
+ static void kgdboc_restore_input(void)
+ {
+ if (likely(system_state == SYSTEM_RUNNING))
+- schedule_work(&kgdboc_restore_input_work);
++ irq_work_queue(&kgdboc_restore_input_irq_work);
+ }
+
+ static int kgdboc_register_kbd(char **cptr)
+@@ -133,6 +160,7 @@ static void kgdboc_unregister_kbd(void)
+ i--;
+ }
+ }
++ irq_work_sync(&kgdboc_restore_input_irq_work);
+ flush_work(&kgdboc_restore_input_work);
+ }
+ #else /* ! CONFIG_KDB_KEYBOARD */
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 4062a486b9e63..579d90efc281a 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1718,7 +1718,6 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
+ */
+ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
+ {
+- struct dwc3 *dwc = dep->dwc;
+ struct dwc3_gadget_ep_cmd_params params;
+ u32 cmd;
+ int ret;
+@@ -1743,8 +1742,7 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int
+ dep->resource_index = 0;
+
+ if (!interrupt) {
+- if (!DWC3_IP_IS(DWC3) || DWC3_VER_IS_PRIOR(DWC3, 310A))
+- mdelay(1);
++ mdelay(1);
+ dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
+ } else if (!ret) {
+ dep->flags |= DWC3_EP_END_TRANSFER_PENDING;
+diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c
+index 0717cfcd9f8ca..191f86da283d0 100644
+--- a/drivers/usb/typec/tipd/core.c
++++ b/drivers/usb/typec/tipd/core.c
+@@ -28,6 +28,7 @@
+ #define TPS_REG_MODE 0x03
+ #define TPS_REG_CMD1 0x08
+ #define TPS_REG_DATA1 0x09
++#define TPS_REG_VERSION 0x0F
+ #define TPS_REG_INT_EVENT1 0x14
+ #define TPS_REG_INT_EVENT2 0x15
+ #define TPS_REG_INT_MASK1 0x16
+@@ -604,11 +605,11 @@ static irqreturn_t tps25750_interrupt(int irq, void *data)
+ if (!tps6598x_read_status(tps, &status))
+ goto err_clear_ints;
+
+- if ((event[0] | event[1]) & TPS_REG_INT_POWER_STATUS_UPDATE)
++ if (event[0] & TPS_REG_INT_POWER_STATUS_UPDATE)
+ if (!tps6598x_read_power_status(tps))
+ goto err_clear_ints;
+
+- if ((event[0] | event[1]) & TPS_REG_INT_DATA_STATUS_UPDATE)
++ if (event[0] & TPS_REG_INT_DATA_STATUS_UPDATE)
+ if (!tps6598x_read_data_status(tps))
+ goto err_clear_ints;
+
+@@ -617,7 +618,7 @@ static irqreturn_t tps25750_interrupt(int irq, void *data)
+ * a plug event. Therefore, we need to check
+ * for pr/dr status change to set TypeC dr/pr accordingly.
+ */
+- if ((event[0] | event[1]) & TPS_REG_INT_PLUG_EVENT ||
++ if (event[0] & TPS_REG_INT_PLUG_EVENT ||
+ tps6598x_has_role_changed(tps, status))
+ tps6598x_handle_plug_event(tps, status);
+
+@@ -636,49 +637,67 @@ static irqreturn_t tps25750_interrupt(int irq, void *data)
+
+ static irqreturn_t tps6598x_interrupt(int irq, void *data)
+ {
++ int intev_len = TPS_65981_2_6_INTEVENT_LEN;
+ struct tps6598x *tps = data;
+- u64 event1 = 0;
+- u64 event2 = 0;
++ u64 event1[2] = { };
++ u64 event2[2] = { };
++ u32 version;
+ u32 status;
+ int ret;
+
+ mutex_lock(&tps->lock);
+
+- ret = tps6598x_read64(tps, TPS_REG_INT_EVENT1, &event1);
+- ret |= tps6598x_read64(tps, TPS_REG_INT_EVENT2, &event2);
++ ret = tps6598x_read32(tps, TPS_REG_VERSION, &version);
++ if (ret)
++ dev_warn(tps->dev, "%s: failed to read version (%d)\n",
++ __func__, ret);
++
++ if (TPS_VERSION_HW_VERSION(version) == TPS_VERSION_HW_65987_8_DH ||
++ TPS_VERSION_HW_VERSION(version) == TPS_VERSION_HW_65987_8_DK)
++ intev_len = TPS_65987_8_INTEVENT_LEN;
++
++ ret = tps6598x_block_read(tps, TPS_REG_INT_EVENT1, event1, intev_len);
++
++ ret = tps6598x_block_read(tps, TPS_REG_INT_EVENT1, event1, intev_len);
+ if (ret) {
+- dev_err(tps->dev, "%s: failed to read events\n", __func__);
++ dev_err(tps->dev, "%s: failed to read event1\n", __func__);
+ goto err_unlock;
+ }
+- trace_tps6598x_irq(event1, event2);
++ ret = tps6598x_block_read(tps, TPS_REG_INT_EVENT2, event2, intev_len);
++ if (ret) {
++ dev_err(tps->dev, "%s: failed to read event2\n", __func__);
++ goto err_unlock;
++ }
++ trace_tps6598x_irq(event1[0], event2[0]);
+
+- if (!(event1 | event2))
++ if (!(event1[0] | event1[1] | event2[0] | event2[1]))
+ goto err_unlock;
+
+ if (!tps6598x_read_status(tps, &status))
+ goto err_clear_ints;
+
+- if ((event1 | event2) & TPS_REG_INT_POWER_STATUS_UPDATE)
++ if ((event1[0] | event2[0]) & TPS_REG_INT_POWER_STATUS_UPDATE)
+ if (!tps6598x_read_power_status(tps))
+ goto err_clear_ints;
+
+- if ((event1 | event2) & TPS_REG_INT_DATA_STATUS_UPDATE)
++ if ((event1[0] | event2[0]) & TPS_REG_INT_DATA_STATUS_UPDATE)
+ if (!tps6598x_read_data_status(tps))
+ goto err_clear_ints;
+
+ /* Handle plug insert or removal */
+- if ((event1 | event2) & TPS_REG_INT_PLUG_EVENT)
++ if ((event1[0] | event2[0]) & TPS_REG_INT_PLUG_EVENT)
+ tps6598x_handle_plug_event(tps, status);
+
+ err_clear_ints:
+- tps6598x_write64(tps, TPS_REG_INT_CLEAR1, event1);
+- tps6598x_write64(tps, TPS_REG_INT_CLEAR2, event2);
++ tps6598x_block_write(tps, TPS_REG_INT_CLEAR1, event1, intev_len);
++ tps6598x_block_write(tps, TPS_REG_INT_CLEAR2, event2, intev_len);
+
+ err_unlock:
+ mutex_unlock(&tps->lock);
+
+- if (event1 | event2)
++ if (event1[0] | event1[1] | event2[0] | event2[1])
+ return IRQ_HANDLED;
++
+ return IRQ_NONE;
+ }
+
+diff --git a/drivers/usb/typec/tipd/tps6598x.h b/drivers/usb/typec/tipd/tps6598x.h
+index 89b24519463a1..9b23e90174521 100644
+--- a/drivers/usb/typec/tipd/tps6598x.h
++++ b/drivers/usb/typec/tipd/tps6598x.h
+@@ -253,4 +253,15 @@
+ #define TPS_PTCC_DEV 2
+ #define TPS_PTCC_APP 3
+
++/* Version Register */
++#define TPS_VERSION_HW_VERSION_MASK GENMASK(31, 24)
++#define TPS_VERSION_HW_VERSION(x) TPS_FIELD_GET(TPS_VERSION_HW_VERSION_MASK, (x))
++#define TPS_VERSION_HW_65981_2_6 0x00
++#define TPS_VERSION_HW_65987_8_DH 0xF7
++#define TPS_VERSION_HW_65987_8_DK 0xF9
++
++/* Int Event Register length */
++#define TPS_65981_2_6_INTEVENT_LEN 8
++#define TPS_65987_8_INTEVENT_LEN 11
++
+ #endif /* __TPS6598X_H__ */
+diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c
+index d9d3c91125ca8..8be92fc1d12c9 100644
+--- a/drivers/usb/typec/ucsi/displayport.c
++++ b/drivers/usb/typec/ucsi/displayport.c
+@@ -275,8 +275,6 @@ static void ucsi_displayport_work(struct work_struct *work)
+ struct ucsi_dp *dp = container_of(work, struct ucsi_dp, work);
+ int ret;
+
+- mutex_lock(&dp->con->lock);
+-
+ ret = typec_altmode_vdm(dp->alt, dp->header,
+ dp->vdo_data, dp->vdo_size);
+ if (ret)
+@@ -285,8 +283,6 @@ static void ucsi_displayport_work(struct work_struct *work)
+ dp->vdo_data = NULL;
+ dp->vdo_size = 0;
+ dp->header = 0;
+-
+- mutex_unlock(&dp->con->lock);
+ }
+
+ void ucsi_displayport_remove_partner(struct typec_altmode *alt)
+diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
+index 410f5af623540..c69174675caf7 100644
+--- a/fs/erofs/internal.h
++++ b/fs/erofs/internal.h
+@@ -84,13 +84,6 @@ struct erofs_dev_context {
+ bool flatdev;
+ };
+
+-struct erofs_fs_context {
+- struct erofs_mount_opts opt;
+- struct erofs_dev_context *devs;
+- char *fsid;
+- char *domain_id;
+-};
+-
+ /* all filesystem-wide lz4 configurations */
+ struct erofs_sb_lz4_info {
+ /* # of pages needed for EROFS lz4 rolling decompression */
+diff --git a/fs/erofs/super.c b/fs/erofs/super.c
+index 24788c230b494..a2fa745585704 100644
+--- a/fs/erofs/super.c
++++ b/fs/erofs/super.c
+@@ -370,18 +370,18 @@ static int erofs_read_superblock(struct super_block *sb)
+ return ret;
+ }
+
+-static void erofs_default_options(struct erofs_fs_context *ctx)
++static void erofs_default_options(struct erofs_sb_info *sbi)
+ {
+ #ifdef CONFIG_EROFS_FS_ZIP
+- ctx->opt.cache_strategy = EROFS_ZIP_CACHE_READAROUND;
+- ctx->opt.max_sync_decompress_pages = 3;
+- ctx->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO;
++ sbi->opt.cache_strategy = EROFS_ZIP_CACHE_READAROUND;
++ sbi->opt.max_sync_decompress_pages = 3;
++ sbi->opt.sync_decompress = EROFS_SYNC_DECOMPRESS_AUTO;
+ #endif
+ #ifdef CONFIG_EROFS_FS_XATTR
+- set_opt(&ctx->opt, XATTR_USER);
++ set_opt(&sbi->opt, XATTR_USER);
+ #endif
+ #ifdef CONFIG_EROFS_FS_POSIX_ACL
+- set_opt(&ctx->opt, POSIX_ACL);
++ set_opt(&sbi->opt, POSIX_ACL);
+ #endif
+ }
+
+@@ -426,17 +426,17 @@ static const struct fs_parameter_spec erofs_fs_parameters[] = {
+ static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode)
+ {
+ #ifdef CONFIG_FS_DAX
+- struct erofs_fs_context *ctx = fc->fs_private;
++ struct erofs_sb_info *sbi = fc->s_fs_info;
+
+ switch (mode) {
+ case EROFS_MOUNT_DAX_ALWAYS:
+ warnfc(fc, "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
+- set_opt(&ctx->opt, DAX_ALWAYS);
+- clear_opt(&ctx->opt, DAX_NEVER);
++ set_opt(&sbi->opt, DAX_ALWAYS);
++ clear_opt(&sbi->opt, DAX_NEVER);
+ return true;
+ case EROFS_MOUNT_DAX_NEVER:
+- set_opt(&ctx->opt, DAX_NEVER);
+- clear_opt(&ctx->opt, DAX_ALWAYS);
++ set_opt(&sbi->opt, DAX_NEVER);
++ clear_opt(&sbi->opt, DAX_ALWAYS);
+ return true;
+ default:
+ DBG_BUGON(1);
+@@ -451,7 +451,7 @@ static bool erofs_fc_set_dax_mode(struct fs_context *fc, unsigned int mode)
+ static int erofs_fc_parse_param(struct fs_context *fc,
+ struct fs_parameter *param)
+ {
+- struct erofs_fs_context *ctx = fc->fs_private;
++ struct erofs_sb_info *sbi = fc->s_fs_info;
+ struct fs_parse_result result;
+ struct erofs_device_info *dif;
+ int opt, ret;
+@@ -464,9 +464,9 @@ static int erofs_fc_parse_param(struct fs_context *fc,
+ case Opt_user_xattr:
+ #ifdef CONFIG_EROFS_FS_XATTR
+ if (result.boolean)
+- set_opt(&ctx->opt, XATTR_USER);
++ set_opt(&sbi->opt, XATTR_USER);
+ else
+- clear_opt(&ctx->opt, XATTR_USER);
++ clear_opt(&sbi->opt, XATTR_USER);
+ #else
+ errorfc(fc, "{,no}user_xattr options not supported");
+ #endif
+@@ -474,16 +474,16 @@ static int erofs_fc_parse_param(struct fs_context *fc,
+ case Opt_acl:
+ #ifdef CONFIG_EROFS_FS_POSIX_ACL
+ if (result.boolean)
+- set_opt(&ctx->opt, POSIX_ACL);
++ set_opt(&sbi->opt, POSIX_ACL);
+ else
+- clear_opt(&ctx->opt, POSIX_ACL);
++ clear_opt(&sbi->opt, POSIX_ACL);
+ #else
+ errorfc(fc, "{,no}acl options not supported");
+ #endif
+ break;
+ case Opt_cache_strategy:
+ #ifdef CONFIG_EROFS_FS_ZIP
+- ctx->opt.cache_strategy = result.uint_32;
++ sbi->opt.cache_strategy = result.uint_32;
+ #else
+ errorfc(fc, "compression not supported, cache_strategy ignored");
+ #endif
+@@ -505,27 +505,27 @@ static int erofs_fc_parse_param(struct fs_context *fc,
+ kfree(dif);
+ return -ENOMEM;
+ }
+- down_write(&ctx->devs->rwsem);
+- ret = idr_alloc(&ctx->devs->tree, dif, 0, 0, GFP_KERNEL);
+- up_write(&ctx->devs->rwsem);
++ down_write(&sbi->devs->rwsem);
++ ret = idr_alloc(&sbi->devs->tree, dif, 0, 0, GFP_KERNEL);
++ up_write(&sbi->devs->rwsem);
+ if (ret < 0) {
+ kfree(dif->path);
+ kfree(dif);
+ return ret;
+ }
+- ++ctx->devs->extra_devices;
++ ++sbi->devs->extra_devices;
+ break;
+ #ifdef CONFIG_EROFS_FS_ONDEMAND
+ case Opt_fsid:
+- kfree(ctx->fsid);
+- ctx->fsid = kstrdup(param->string, GFP_KERNEL);
+- if (!ctx->fsid)
++ kfree(sbi->fsid);
++ sbi->fsid = kstrdup(param->string, GFP_KERNEL);
++ if (!sbi->fsid)
+ return -ENOMEM;
+ break;
+ case Opt_domain_id:
+- kfree(ctx->domain_id);
+- ctx->domain_id = kstrdup(param->string, GFP_KERNEL);
+- if (!ctx->domain_id)
++ kfree(sbi->domain_id);
++ sbi->domain_id = kstrdup(param->string, GFP_KERNEL);
++ if (!sbi->domain_id)
+ return -ENOMEM;
+ break;
+ #else
+@@ -582,8 +582,7 @@ static const struct export_operations erofs_export_ops = {
+ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
+ {
+ struct inode *inode;
+- struct erofs_sb_info *sbi;
+- struct erofs_fs_context *ctx = fc->fs_private;
++ struct erofs_sb_info *sbi = EROFS_SB(sb);
+ int err;
+
+ sb->s_magic = EROFS_SUPER_MAGIC;
+@@ -591,19 +590,6 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
+ sb->s_maxbytes = MAX_LFS_FILESIZE;
+ sb->s_op = &erofs_sops;
+
+- sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
+- if (!sbi)
+- return -ENOMEM;
+-
+- sb->s_fs_info = sbi;
+- sbi->opt = ctx->opt;
+- sbi->devs = ctx->devs;
+- ctx->devs = NULL;
+- sbi->fsid = ctx->fsid;
+- ctx->fsid = NULL;
+- sbi->domain_id = ctx->domain_id;
+- ctx->domain_id = NULL;
+-
+ sbi->blkszbits = PAGE_SHIFT;
+ if (erofs_is_fscache_mode(sb)) {
+ sb->s_blocksize = PAGE_SIZE;
+@@ -707,9 +693,9 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
+
+ static int erofs_fc_get_tree(struct fs_context *fc)
+ {
+- struct erofs_fs_context *ctx = fc->fs_private;
++ struct erofs_sb_info *sbi = fc->s_fs_info;
+
+- if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && ctx->fsid)
++ if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid)
+ return get_tree_nodev(fc, erofs_fc_fill_super);
+
+ return get_tree_bdev(fc, erofs_fc_fill_super);
+@@ -719,19 +705,19 @@ static int erofs_fc_reconfigure(struct fs_context *fc)
+ {
+ struct super_block *sb = fc->root->d_sb;
+ struct erofs_sb_info *sbi = EROFS_SB(sb);
+- struct erofs_fs_context *ctx = fc->fs_private;
++ struct erofs_sb_info *new_sbi = fc->s_fs_info;
+
+ DBG_BUGON(!sb_rdonly(sb));
+
+- if (ctx->fsid || ctx->domain_id)
++ if (new_sbi->fsid || new_sbi->domain_id)
+ erofs_info(sb, "ignoring reconfiguration for fsid|domain_id.");
+
+- if (test_opt(&ctx->opt, POSIX_ACL))
++ if (test_opt(&new_sbi->opt, POSIX_ACL))
+ fc->sb_flags |= SB_POSIXACL;
+ else
+ fc->sb_flags &= ~SB_POSIXACL;
+
+- sbi->opt = ctx->opt;
++ sbi->opt = new_sbi->opt;
+
+ fc->sb_flags |= SB_RDONLY;
+ return 0;
+@@ -762,12 +748,15 @@ static void erofs_free_dev_context(struct erofs_dev_context *devs)
+
+ static void erofs_fc_free(struct fs_context *fc)
+ {
+- struct erofs_fs_context *ctx = fc->fs_private;
++ struct erofs_sb_info *sbi = fc->s_fs_info;
+
+- erofs_free_dev_context(ctx->devs);
+- kfree(ctx->fsid);
+- kfree(ctx->domain_id);
+- kfree(ctx);
++ if (!sbi)
++ return;
++
++ erofs_free_dev_context(sbi->devs);
++ kfree(sbi->fsid);
++ kfree(sbi->domain_id);
++ kfree(sbi);
+ }
+
+ static const struct fs_context_operations erofs_context_ops = {
+@@ -779,38 +768,35 @@ static const struct fs_context_operations erofs_context_ops = {
+
+ static int erofs_init_fs_context(struct fs_context *fc)
+ {
+- struct erofs_fs_context *ctx;
++ struct erofs_sb_info *sbi;
+
+- ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+- if (!ctx)
++ sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
++ if (!sbi)
+ return -ENOMEM;
+- ctx->devs = kzalloc(sizeof(struct erofs_dev_context), GFP_KERNEL);
+- if (!ctx->devs) {
+- kfree(ctx);
++
++ sbi->devs = kzalloc(sizeof(struct erofs_dev_context), GFP_KERNEL);
++ if (!sbi->devs) {
++ kfree(sbi);
+ return -ENOMEM;
+ }
+- fc->fs_private = ctx;
++ fc->s_fs_info = sbi;
+
+- idr_init(&ctx->devs->tree);
+- init_rwsem(&ctx->devs->rwsem);
+- erofs_default_options(ctx);
++ idr_init(&sbi->devs->tree);
++ init_rwsem(&sbi->devs->rwsem);
++ erofs_default_options(sbi);
+ fc->ops = &erofs_context_ops;
+ return 0;
+ }
+
+ static void erofs_kill_sb(struct super_block *sb)
+ {
+- struct erofs_sb_info *sbi;
++ struct erofs_sb_info *sbi = EROFS_SB(sb);
+
+- if (erofs_is_fscache_mode(sb))
++ if (IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid)
+ kill_anon_super(sb);
+ else
+ kill_block_super(sb);
+
+- sbi = EROFS_SB(sb);
+- if (!sbi)
+- return;
+-
+ erofs_free_dev_context(sbi->devs);
+ fs_put_dax(sbi->dax_dev, NULL);
+ erofs_fscache_unregister_fs(sb);
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index b43ca3b9d2a26..6ee8e7d7383ca 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -233,6 +233,19 @@ static inline unsigned int disk_openers(struct gendisk *disk)
+ return atomic_read(&disk->part0->bd_openers);
+ }
+
++/**
++ * disk_has_partscan - return %true if partition scanning is enabled on a disk
++ * @disk: disk to check
++ *
++ * Returns %true if partitions scanning is enabled for @disk, or %false if
++ * partition scanning is disabled either permanently or temporarily.
++ */
++static inline bool disk_has_partscan(struct gendisk *disk)
++{
++ return !(disk->flags & (GENHD_FL_NO_PART | GENHD_FL_HIDDEN)) &&
++ !test_bit(GD_SUPPRESS_PART_SCAN, &disk->state);
++}
++
+ /*
+ * The gendisk is refcounted by the part0 block_device, and the bd_device
+ * therein is also used for device model presentation in sysfs.
+diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
+index 2cfd8d862639f..f9db2d1ca5d37 100644
+--- a/include/net/bluetooth/hci.h
++++ b/include/net/bluetooth/hci.h
+@@ -1665,6 +1665,15 @@ struct hci_cp_le_set_event_mask {
+ __u8 mask[8];
+ } __packed;
+
++/* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E
++ * 7.8.2 LE Read Buffer Size command
++ * MAX_LE_MTU is 0xffff.
++ * 0 is also valid. It means that no dedicated LE Buffer exists.
++ * It should use the HCI_Read_Buffer_Size command and mtu is shared
++ * between BR/EDR and LE.
++ */
++#define HCI_MIN_LE_MTU 0x001b
++
+ #define HCI_OP_LE_READ_BUFFER_SIZE 0x2002
+ struct hci_rp_le_read_buffer_size {
+ __u8 status;
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index fe9e1524d30ff..8504e10f51700 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -706,6 +706,7 @@ struct hci_conn {
+ __u16 handle;
+ __u16 sync_handle;
+ __u16 state;
++ __u16 mtu;
+ __u8 mode;
+ __u8 type;
+ __u8 role;
+diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
+index 18f97b2288699..9a369bc14fd57 100644
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -909,11 +909,37 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ {
+ struct hci_conn *conn;
+
++ switch (type) {
++ case ACL_LINK:
++ if (!hdev->acl_mtu)
++ return ERR_PTR(-ECONNREFUSED);
++ break;
++ case ISO_LINK:
++ if (hdev->iso_mtu)
++ /* Dedicated ISO Buffer exists */
++ break;
++ fallthrough;
++ case LE_LINK:
++ if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
++ return ERR_PTR(-ECONNREFUSED);
++ if (!hdev->le_mtu && hdev->acl_mtu < HCI_MIN_LE_MTU)
++ return ERR_PTR(-ECONNREFUSED);
++ break;
++ case SCO_LINK:
++ case ESCO_LINK:
++ if (!hdev->sco_pkts)
++ /* Controller does not support SCO or eSCO over HCI */
++ return ERR_PTR(-ECONNREFUSED);
++ break;
++ default:
++ return ERR_PTR(-ECONNREFUSED);
++ }
++
+ bt_dev_dbg(hdev, "dst %pMR handle 0x%4.4x", dst, handle);
+
+ conn = kzalloc(sizeof(*conn), GFP_KERNEL);
+ if (!conn)
+- return NULL;
++ return ERR_PTR(-ENOMEM);
+
+ bacpy(&conn->dst, dst);
+ bacpy(&conn->src, &hdev->bdaddr);
+@@ -944,10 +970,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ switch (type) {
+ case ACL_LINK:
+ conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
++ conn->mtu = hdev->acl_mtu;
+ break;
+ case LE_LINK:
+ /* conn->src should reflect the local identity address */
+ hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
++ conn->mtu = hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu;
+ break;
+ case ISO_LINK:
+ /* conn->src should reflect the local identity address */
+@@ -959,6 +987,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ else if (conn->role == HCI_ROLE_MASTER)
+ conn->cleanup = cis_cleanup;
+
++ conn->mtu = hdev->iso_mtu ? hdev->iso_mtu :
++ hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu;
+ break;
+ case SCO_LINK:
+ if (lmp_esco_capable(hdev))
+@@ -966,9 +996,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ (hdev->esco_type & EDR_ESCO_MASK);
+ else
+ conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
++
++ conn->mtu = hdev->sco_mtu;
+ break;
+ case ESCO_LINK:
+ conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
++ conn->mtu = hdev->sco_mtu;
+ break;
+ }
+
+@@ -1011,7 +1044,7 @@ struct hci_conn *hci_conn_add_unset(struct hci_dev *hdev, int type,
+
+ handle = hci_conn_hash_alloc_unset(hdev);
+ if (unlikely(handle < 0))
+- return NULL;
++ return ERR_PTR(-ECONNREFUSED);
+
+ return hci_conn_add(hdev, type, dst, role, handle);
+ }
+@@ -1317,8 +1350,8 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
+ bacpy(&conn->dst, dst);
+ } else {
+ conn = hci_conn_add_unset(hdev, LE_LINK, dst, role);
+- if (!conn)
+- return ERR_PTR(-ENOMEM);
++ if (IS_ERR(conn))
++ return conn;
+ hci_conn_hold(conn);
+ conn->pending_sec_level = sec_level;
+ }
+@@ -1494,8 +1527,8 @@ static struct hci_conn *hci_add_bis(struct hci_dev *hdev, bdaddr_t *dst,
+ return ERR_PTR(-EADDRINUSE);
+
+ conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
+- if (!conn)
+- return ERR_PTR(-ENOMEM);
++ if (IS_ERR(conn))
++ return conn;
+
+ conn->state = BT_CONNECT;
+
+@@ -1538,8 +1571,8 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst,
+ BT_DBG("requesting refresh of dst_addr");
+
+ conn = hci_conn_add_unset(hdev, LE_LINK, dst, HCI_ROLE_MASTER);
+- if (!conn)
+- return ERR_PTR(-ENOMEM);
++ if (IS_ERR(conn))
++ return conn;
+
+ if (hci_explicit_conn_params_set(hdev, dst, dst_type) < 0) {
+ hci_conn_del(conn);
+@@ -1586,8 +1619,8 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst,
+ acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
+ if (!acl) {
+ acl = hci_conn_add_unset(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
+- if (!acl)
+- return ERR_PTR(-ENOMEM);
++ if (IS_ERR(acl))
++ return acl;
+ }
+
+ hci_conn_hold(acl);
+@@ -1655,9 +1688,9 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
+ sco = hci_conn_hash_lookup_ba(hdev, type, dst);
+ if (!sco) {
+ sco = hci_conn_add_unset(hdev, type, dst, HCI_ROLE_MASTER);
+- if (!sco) {
++ if (IS_ERR(sco)) {
+ hci_conn_drop(acl);
+- return ERR_PTR(-ENOMEM);
++ return sco;
+ }
+ }
+
+@@ -1847,8 +1880,8 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
+ qos->ucast.cis);
+ if (!cis) {
+ cis = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
+- if (!cis)
+- return ERR_PTR(-ENOMEM);
++ if (IS_ERR(cis))
++ return cis;
+ cis->cleanup = cis_cleanup;
+ cis->dst_type = dst_type;
+ cis->iso_qos.ucast.cig = BT_ISO_QOS_CIG_UNSET;
+@@ -1983,14 +2016,8 @@ static void hci_iso_qos_setup(struct hci_dev *hdev, struct hci_conn *conn,
+ struct bt_iso_io_qos *qos, __u8 phy)
+ {
+ /* Only set MTU if PHY is enabled */
+- if (!qos->sdu && qos->phy) {
+- if (hdev->iso_mtu > 0)
+- qos->sdu = hdev->iso_mtu;
+- else if (hdev->le_mtu > 0)
+- qos->sdu = hdev->le_mtu;
+- else
+- qos->sdu = hdev->acl_mtu;
+- }
++ if (!qos->sdu && qos->phy)
++ qos->sdu = conn->mtu;
+
+ /* Use the same PHY as ACL if set to any */
+ if (qos->phy == BT_ISO_PHY_ANY)
+diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
+index 0f56ad33801e3..c19d78e5d2053 100644
+--- a/net/bluetooth/hci_event.c
++++ b/net/bluetooth/hci_event.c
+@@ -954,6 +954,9 @@ static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data,
+ BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
+ hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
+
++ if (!hdev->acl_mtu || !hdev->acl_pkts)
++ return HCI_ERROR_INVALID_PARAMETERS;
++
+ return rp->status;
+ }
+
+@@ -1263,6 +1266,9 @@ static u8 hci_cc_le_read_buffer_size(struct hci_dev *hdev, void *data,
+
+ BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
+
++ if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
++ return HCI_ERROR_INVALID_PARAMETERS;
++
+ return rp->status;
+ }
+
+@@ -2342,8 +2348,8 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
+ if (!conn) {
+ conn = hci_conn_add_unset(hdev, ACL_LINK, &cp->bdaddr,
+ HCI_ROLE_MASTER);
+- if (!conn)
+- bt_dev_err(hdev, "no memory for new connection");
++ if (IS_ERR(conn))
++ bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
+ }
+ }
+
+@@ -3154,8 +3160,8 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
+ BDADDR_BREDR)) {
+ conn = hci_conn_add_unset(hdev, ev->link_type,
+ &ev->bdaddr, HCI_ROLE_SLAVE);
+- if (!conn) {
+- bt_dev_err(hdev, "no memory for new conn");
++ if (IS_ERR(conn)) {
++ bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
+ goto unlock;
+ }
+ } else {
+@@ -3343,8 +3349,8 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
+ if (!conn) {
+ conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr,
+ HCI_ROLE_SLAVE);
+- if (!conn) {
+- bt_dev_err(hdev, "no memory for new connection");
++ if (IS_ERR(conn)) {
++ bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
+ goto unlock;
+ }
+ }
+@@ -3821,6 +3827,9 @@ static u8 hci_cc_le_read_buffer_size_v2(struct hci_dev *hdev, void *data,
+ BT_DBG("%s acl mtu %d:%d iso mtu %d:%d", hdev->name, hdev->acl_mtu,
+ hdev->acl_pkts, hdev->iso_mtu, hdev->iso_pkts);
+
++ if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
++ return HCI_ERROR_INVALID_PARAMETERS;
++
+ return rp->status;
+ }
+
+@@ -5912,8 +5921,8 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
+ goto unlock;
+
+ conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, role);
+- if (!conn) {
+- bt_dev_err(hdev, "no memory for new connection");
++ if (IS_ERR(conn)) {
++ bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
+ goto unlock;
+ }
+
+@@ -7042,7 +7051,7 @@ static void hci_le_cis_req_evt(struct hci_dev *hdev, void *data,
+ if (!cis) {
+ cis = hci_conn_add(hdev, ISO_LINK, &acl->dst, HCI_ROLE_SLAVE,
+ cis_handle);
+- if (!cis) {
++ if (IS_ERR(cis)) {
+ hci_le_reject_cis(hdev, ev->cis_handle);
+ goto unlock;
+ }
+@@ -7151,7 +7160,7 @@ static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
+ if (!bis) {
+ bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
+ HCI_ROLE_SLAVE, handle);
+- if (!bis)
++ if (IS_ERR(bis))
+ continue;
+ }
+
+@@ -7223,7 +7232,7 @@ static void hci_le_big_info_adv_report_evt(struct hci_dev *hdev, void *data,
+ pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
+ HCI_ROLE_SLAVE);
+
+- if (!pa_sync)
++ if (IS_ERR(pa_sync))
+ goto unlock;
+
+ pa_sync->sync_handle = le16_to_cpu(ev->sync_handle);
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index fa6c2e95d5542..6d217df75c62c 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -1264,7 +1264,7 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg,
+ return -ENOTCONN;
+ }
+
+- mtu = iso_pi(sk)->conn->hcon->hdev->iso_mtu;
++ mtu = iso_pi(sk)->conn->hcon->mtu;
+
+ release_sock(sk);
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 5761d37c55376..3f7a82f10fe98 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -3905,13 +3905,12 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn,
+ return 0;
+ }
+
+-static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
+- struct l2cap_cmd_hdr *cmd,
+- u8 *data, u8 rsp_code, u8 amp_id)
++static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
++ u8 *data, u8 rsp_code, u8 amp_id)
+ {
+ struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
+ struct l2cap_conn_rsp rsp;
+- struct l2cap_chan *chan = NULL, *pchan;
++ struct l2cap_chan *chan = NULL, *pchan = NULL;
+ int result, status = L2CAP_CS_NO_INFO;
+
+ u16 dcid = 0, scid = __le16_to_cpu(req->scid);
+@@ -3924,7 +3923,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
+ &conn->hcon->dst, ACL_LINK);
+ if (!pchan) {
+ result = L2CAP_CR_BAD_PSM;
+- goto sendresp;
++ goto response;
+ }
+
+ mutex_lock(&conn->chan_lock);
+@@ -4011,17 +4010,15 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
+ }
+
+ response:
+- l2cap_chan_unlock(pchan);
+- mutex_unlock(&conn->chan_lock);
+- l2cap_chan_put(pchan);
+-
+-sendresp:
+ rsp.scid = cpu_to_le16(scid);
+ rsp.dcid = cpu_to_le16(dcid);
+ rsp.result = cpu_to_le16(result);
+ rsp.status = cpu_to_le16(status);
+ l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
+
++ if (!pchan)
++ return;
++
+ if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
+ struct l2cap_info_req info;
+ info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
+@@ -4044,7 +4041,9 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
+ chan->num_conf_req++;
+ }
+
+- return chan;
++ l2cap_chan_unlock(pchan);
++ mutex_unlock(&conn->chan_lock);
++ l2cap_chan_put(pchan);
+ }
+
+ static int l2cap_connect_req(struct l2cap_conn *conn,
+@@ -6242,7 +6241,7 @@ static int l2cap_finish_move(struct l2cap_chan *chan)
+ BT_DBG("chan %p", chan);
+
+ chan->rx_state = L2CAP_RX_STATE_RECV;
+- chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
++ chan->conn->mtu = chan->conn->hcon->mtu;
+
+ return l2cap_resegment(chan);
+ }
+@@ -6309,7 +6308,7 @@ static int l2cap_rx_state_wait_f(struct l2cap_chan *chan,
+ */
+ chan->next_tx_seq = control->reqseq;
+ chan->unacked_frames = 0;
+- chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
++ chan->conn->mtu = chan->conn->hcon->mtu;
+
+ err = l2cap_resegment(chan);
+
+@@ -6849,18 +6848,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
+
+ BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
+
+- switch (hcon->type) {
+- case LE_LINK:
+- if (hcon->hdev->le_mtu) {
+- conn->mtu = hcon->hdev->le_mtu;
+- break;
+- }
+- fallthrough;
+- default:
+- conn->mtu = hcon->hdev->acl_mtu;
+- break;
+- }
+-
++ conn->mtu = hcon->mtu;
+ conn->feat_mask = 0;
+
+ conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index e0ad30862ee41..71d36582d4efa 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -126,7 +126,6 @@ static void sco_sock_clear_timer(struct sock *sk)
+ /* ---- SCO connections ---- */
+ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
+ {
+- struct hci_dev *hdev = hcon->hdev;
+ struct sco_conn *conn = hcon->sco_data;
+
+ if (conn) {
+@@ -144,9 +143,10 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
+
+ hcon->sco_data = conn;
+ conn->hcon = hcon;
++ conn->mtu = hcon->mtu;
+
+- if (hdev->sco_mtu > 0)
+- conn->mtu = hdev->sco_mtu;
++ if (hcon->mtu > 0)
++ conn->mtu = hcon->mtu;
+ else
+ conn->mtu = 60;
+
+diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
+index bc700f85f80be..ea277c55a38db 100644
+--- a/security/keys/trusted-keys/trusted_tpm2.c
++++ b/security/keys/trusted-keys/trusted_tpm2.c
+@@ -38,6 +38,7 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
+ u8 *end_work = scratch + SCRATCH_SIZE;
+ u8 *priv, *pub;
+ u16 priv_len, pub_len;
++ int ret;
+
+ priv_len = get_unaligned_be16(src) + 2;
+ priv = src;
+@@ -57,8 +58,10 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
+ unsigned char bool[3], *w = bool;
+ /* tag 0 is emptyAuth */
+ w = asn1_encode_boolean(w, w + sizeof(bool), true);
+- if (WARN(IS_ERR(w), "BUG: Boolean failed to encode"))
+- return PTR_ERR(w);
++ if (WARN(IS_ERR(w), "BUG: Boolean failed to encode")) {
++ ret = PTR_ERR(w);
++ goto err;
++ }
+ work = asn1_encode_tag(work, end_work, 0, bool, w - bool);
+ }
+
+@@ -69,8 +72,10 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
+ * trigger, so if it does there's something nefarious going on
+ */
+ if (WARN(work - scratch + pub_len + priv_len + 14 > SCRATCH_SIZE,
+- "BUG: scratch buffer is too small"))
+- return -EINVAL;
++ "BUG: scratch buffer is too small")) {
++ ret = -EINVAL;
++ goto err;
++ }
+
+ work = asn1_encode_integer(work, end_work, options->keyhandle);
+ work = asn1_encode_octet_string(work, end_work, pub, pub_len);
+@@ -79,10 +84,18 @@ static int tpm2_key_encode(struct trusted_key_payload *payload,
+ work1 = payload->blob;
+ work1 = asn1_encode_sequence(work1, work1 + sizeof(payload->blob),
+ scratch, work - scratch);
+- if (WARN(IS_ERR(work1), "BUG: ASN.1 encoder failed"))
+- return PTR_ERR(work1);
++ if (IS_ERR(work1)) {
++ ret = PTR_ERR(work1);
++ pr_err("BUG: ASN.1 encoder failed with %d\n", ret);
++ goto err;
++ }
+
++ kfree(scratch);
+ return work1 - payload->blob;
++
++err:
++ kfree(scratch);
++ return ret;
+ }
+
+ struct tpm2_key_context {
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [gentoo-commits] proj/linux-patches:6.8 commit in: /
@ 2024-05-30 11:58 Mike Pagano
0 siblings, 0 replies; 25+ messages in thread
From: Mike Pagano @ 2024-05-30 11:58 UTC (permalink / raw
To: gentoo-commits
commit: 389252d9943e973121719e1d54ea6b0b424a18f8
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Thu May 30 11:57:56 2024 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Thu May 30 11:57:56 2024 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=389252d9
Linux patch 6.8.12
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1011_linux-6.8.12.patch | 23201 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 23205 insertions(+)
diff --git a/0000_README b/0000_README
index 7fa03211..cb1f818b 100644
--- a/0000_README
+++ b/0000_README
@@ -87,6 +87,10 @@ Patch: 1010_linux-6.8.11.patch
From: https://www.kernel.org
Desc: Linux 6.8.11
+Patch: 1011_linux-6.8.12.patch
+From: https://www.kernel.org
+Desc: Linux 6.8.12
+
Patch: 1510_fs-enable-link-security-restrictions-by-default.patch
From: http://sources.debian.net/src/linux/3.16.7-ckt4-3/debian/patches/debian/fs-enable-link-security-restrictions-by-default.patch/
Desc: Enable link security restrictions by default.
diff --git a/1011_linux-6.8.12.patch b/1011_linux-6.8.12.patch
new file mode 100644
index 00000000..7a4b0795
--- /dev/null
+++ b/1011_linux-6.8.12.patch
@@ -0,0 +1,23201 @@
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index 31fdaf4fe9dd8..9bfc972af2403 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -3399,6 +3399,9 @@
+ arch-independent options, each of which is an
+ aggregation of existing arch-specific options.
+
++ Note, "mitigations" is supported if and only if the
++ kernel was built with CPU_MITIGATIONS=y.
++
+ off
+ Disable all optional CPU mitigations. This
+ improves system performance, but it may also
+diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml
+index cf456f8d9ddcb..c87677f5e2a25 100644
+--- a/Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml
++++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov2680.yaml
+@@ -37,15 +37,15 @@ properties:
+ active low.
+ maxItems: 1
+
+- dovdd-supply:
++ DOVDD-supply:
+ description:
+ Definition of the regulator used as interface power supply.
+
+- avdd-supply:
++ AVDD-supply:
+ description:
+ Definition of the regulator used as analog power supply.
+
+- dvdd-supply:
++ DVDD-supply:
+ description:
+ Definition of the regulator used as digital power supply.
+
+@@ -59,9 +59,9 @@ required:
+ - reg
+ - clocks
+ - clock-names
+- - dovdd-supply
+- - avdd-supply
+- - dvdd-supply
++ - DOVDD-supply
++ - AVDD-supply
++ - DVDD-supply
+ - reset-gpios
+ - port
+
+@@ -82,9 +82,9 @@ examples:
+ clock-names = "xvclk";
+ reset-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>;
+
+- dovdd-supply = <&sw2_reg>;
+- dvdd-supply = <&sw2_reg>;
+- avdd-supply = <®_peri_3p15v>;
++ DOVDD-supply = <&sw2_reg>;
++ DVDD-supply = <&sw2_reg>;
++ AVDD-supply = <®_peri_3p15v>;
+
+ port {
+ ov2680_to_mipi: endpoint {
+diff --git a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
+index 9793ea6f0fe65..575555810c2c2 100644
+--- a/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
++++ b/Documentation/devicetree/bindings/soc/rockchip/grf.yaml
+@@ -165,6 +165,7 @@ allOf:
+ unevaluatedProperties: false
+
+ pcie-phy:
++ type: object
+ description:
+ Documentation/devicetree/bindings/phy/rockchip-pcie-phy.txt
+
+diff --git a/Documentation/devicetree/bindings/sound/rt5645.txt b/Documentation/devicetree/bindings/sound/rt5645.txt
+index 41a62fd2ae1ff..c1fa379f5f3ea 100644
+--- a/Documentation/devicetree/bindings/sound/rt5645.txt
++++ b/Documentation/devicetree/bindings/sound/rt5645.txt
+@@ -20,6 +20,11 @@ Optional properties:
+ a GPIO spec for the external headphone detect pin. If jd-mode = 0,
+ we will get the JD status by getting the value of hp-detect-gpios.
+
++- cbj-sleeve-gpios:
++ a GPIO spec to control the external combo jack circuit to tie the sleeve/ring2
++ contacts to the ground or floating. It could avoid some electric noise from the
++ active speaker jacks.
++
+ - realtek,in2-differential
+ Boolean. Indicate MIC2 input are differential, rather than single-ended.
+
+@@ -68,6 +73,7 @@ codec: rt5650@1a {
+ compatible = "realtek,rt5650";
+ reg = <0x1a>;
+ hp-detect-gpios = <&gpio 19 0>;
++ cbj-sleeve-gpios = <&gpio 20 0>;
+ interrupt-parent = <&gpio>;
+ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+ realtek,dmic-en = "true";
+diff --git a/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml b/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml
+index b634f57cd011d..ca81c8afba79c 100644
+--- a/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml
++++ b/Documentation/devicetree/bindings/thermal/loongson,ls2k-thermal.yaml
+@@ -18,13 +18,15 @@ properties:
+ oneOf:
+ - enum:
+ - loongson,ls2k1000-thermal
++ - loongson,ls2k2000-thermal
+ - items:
+ - enum:
+- - loongson,ls2k2000-thermal
++ - loongson,ls2k0500-thermal
+ - const: loongson,ls2k1000-thermal
+
+ reg:
+- maxItems: 1
++ minItems: 1
++ maxItems: 2
+
+ interrupts:
+ maxItems: 1
+@@ -38,6 +40,24 @@ required:
+ - interrupts
+ - '#thermal-sensor-cells'
+
++if:
++ properties:
++ compatible:
++ contains:
++ enum:
++ - loongson,ls2k2000-thermal
++
++then:
++ properties:
++ reg:
++ minItems: 2
++ maxItems: 2
++
++else:
++ properties:
++ reg:
++ maxItems: 1
++
+ unevaluatedProperties: false
+
+ examples:
+diff --git a/Makefile b/Makefile
+index ce6b03cce386d..5447d5041e42d 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 8
+-SUBLEVEL = 11
++SUBLEVEL = 12
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
+index bddc82f789421..a83d29fed1756 100644
+--- a/arch/arm/configs/sunxi_defconfig
++++ b/arch/arm/configs/sunxi_defconfig
+@@ -110,6 +110,7 @@ CONFIG_DRM_PANEL_LVDS=y
+ CONFIG_DRM_PANEL_SIMPLE=y
+ CONFIG_DRM_PANEL_EDP=y
+ CONFIG_DRM_SIMPLE_BRIDGE=y
++CONFIG_DRM_DW_HDMI=y
+ CONFIG_DRM_LIMA=y
+ CONFIG_FB_SIMPLE=y
+ CONFIG_BACKLIGHT_CLASS_DEVICE=y
+diff --git a/arch/arm64/include/asm/irqflags.h b/arch/arm64/include/asm/irqflags.h
+index 0a7186a93882d..d4d7451c2c129 100644
+--- a/arch/arm64/include/asm/irqflags.h
++++ b/arch/arm64/include/asm/irqflags.h
+@@ -5,7 +5,6 @@
+ #ifndef __ASM_IRQFLAGS_H
+ #define __ASM_IRQFLAGS_H
+
+-#include <asm/alternative.h>
+ #include <asm/barrier.h>
+ #include <asm/ptrace.h>
+ #include <asm/sysreg.h>
+diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
+index f27acca550d55..5e7b0eb4687e1 100644
+--- a/arch/arm64/kernel/fpsimd.c
++++ b/arch/arm64/kernel/fpsimd.c
+@@ -1518,6 +1518,27 @@ static void fpsimd_save_kernel_state(struct task_struct *task)
+ task->thread.kernel_fpsimd_cpu = smp_processor_id();
+ }
+
++/*
++ * Invalidate any task's FPSIMD state that is present on this cpu.
++ * The FPSIMD context should be acquired with get_cpu_fpsimd_context()
++ * before calling this function.
++ */
++static void fpsimd_flush_cpu_state(void)
++{
++ WARN_ON(!system_supports_fpsimd());
++ __this_cpu_write(fpsimd_last_state.st, NULL);
++
++ /*
++ * Leaving streaming mode enabled will cause issues for any kernel
++ * NEON and leaving streaming mode or ZA enabled may increase power
++ * consumption.
++ */
++ if (system_supports_sme())
++ sme_smstop();
++
++ set_thread_flag(TIF_FOREIGN_FPSTATE);
++}
++
+ void fpsimd_thread_switch(struct task_struct *next)
+ {
+ bool wrong_task, wrong_cpu;
+@@ -1535,7 +1556,7 @@ void fpsimd_thread_switch(struct task_struct *next)
+
+ if (test_tsk_thread_flag(next, TIF_KERNEL_FPSTATE)) {
+ fpsimd_load_kernel_state(next);
+- set_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE);
++ fpsimd_flush_cpu_state();
+ } else {
+ /*
+ * Fix up TIF_FOREIGN_FPSTATE to correctly describe next's
+@@ -1824,27 +1845,6 @@ void fpsimd_flush_task_state(struct task_struct *t)
+ barrier();
+ }
+
+-/*
+- * Invalidate any task's FPSIMD state that is present on this cpu.
+- * The FPSIMD context should be acquired with get_cpu_fpsimd_context()
+- * before calling this function.
+- */
+-static void fpsimd_flush_cpu_state(void)
+-{
+- WARN_ON(!system_supports_fpsimd());
+- __this_cpu_write(fpsimd_last_state.st, NULL);
+-
+- /*
+- * Leaving streaming mode enabled will cause issues for any kernel
+- * NEON and leaving streaming mode or ZA enabled may increase power
+- * consumption.
+- */
+- if (system_supports_sme())
+- sme_smstop();
+-
+- set_thread_flag(TIF_FOREIGN_FPSTATE);
+-}
+-
+ /*
+ * Save the FPSIMD state to memory and invalidate cpu view.
+ * This function must be called with preemption disabled.
+diff --git a/arch/loongarch/kernel/perf_event.c b/arch/loongarch/kernel/perf_event.c
+index 0491bf453cd49..cac7cba81b65f 100644
+--- a/arch/loongarch/kernel/perf_event.c
++++ b/arch/loongarch/kernel/perf_event.c
+@@ -884,4 +884,4 @@ static int __init init_hw_perf_events(void)
+
+ return 0;
+ }
+-early_initcall(init_hw_perf_events);
++pure_initcall(init_hw_perf_events);
+diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
+index 3bcdd32a6b366..338b474910f74 100644
+--- a/arch/m68k/kernel/entry.S
++++ b/arch/m68k/kernel/entry.S
+@@ -430,7 +430,9 @@ resume:
+ movec %a0,%dfc
+
+ /* restore status register */
+- movew %a1@(TASK_THREAD+THREAD_SR),%sr
++ movew %a1@(TASK_THREAD+THREAD_SR),%d0
++ oriw #0x0700,%d0
++ movew %d0,%sr
+
+ rts
+
+diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c
+index 4c8f8cbfa05f3..e7f0f72c1b36e 100644
+--- a/arch/m68k/mac/misc.c
++++ b/arch/m68k/mac/misc.c
+@@ -453,30 +453,18 @@ void mac_poweroff(void)
+
+ void mac_reset(void)
+ {
+- if (macintosh_config->adb_type == MAC_ADB_II &&
+- macintosh_config->ident != MAC_MODEL_SE30) {
+- /* need ROMBASE in booter */
+- /* indeed, plus need to MAP THE ROM !! */
+-
+- if (mac_bi_data.rombase == 0)
+- mac_bi_data.rombase = 0x40800000;
+-
+- /* works on some */
+- rom_reset = (void *) (mac_bi_data.rombase + 0xa);
+-
+- local_irq_disable();
+- rom_reset();
+ #ifdef CONFIG_ADB_CUDA
+- } else if (macintosh_config->adb_type == MAC_ADB_EGRET ||
+- macintosh_config->adb_type == MAC_ADB_CUDA) {
++ if (macintosh_config->adb_type == MAC_ADB_EGRET ||
++ macintosh_config->adb_type == MAC_ADB_CUDA) {
+ cuda_restart();
++ } else
+ #endif
+ #ifdef CONFIG_ADB_PMU
+- } else if (macintosh_config->adb_type == MAC_ADB_PB2) {
++ if (macintosh_config->adb_type == MAC_ADB_PB2) {
+ pmu_restart();
++ } else
+ #endif
+- } else if (CPU_IS_030) {
+-
++ if (CPU_IS_030) {
+ /* 030-specific reset routine. The idea is general, but the
+ * specific registers to reset are '030-specific. Until I
+ * have a non-030 machine, I can't test anything else.
+@@ -524,6 +512,18 @@ void mac_reset(void)
+ "jmp %/a0@\n\t" /* jump to the reset vector */
+ ".chip 68k"
+ : : "r" (offset), "a" (rombase) : "a0");
++ } else {
++ /* need ROMBASE in booter */
++ /* indeed, plus need to MAP THE ROM !! */
++
++ if (mac_bi_data.rombase == 0)
++ mac_bi_data.rombase = 0x40800000;
++
++ /* works on some */
++ rom_reset = (void *)(mac_bi_data.rombase + 0xa);
++
++ local_irq_disable();
++ rom_reset();
+ }
+
+ /* should never get here */
+diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c
+index 9370888c9a7e3..90554a5558fbc 100644
+--- a/arch/openrisc/kernel/traps.c
++++ b/arch/openrisc/kernel/traps.c
+@@ -180,29 +180,39 @@ asmlinkage void unhandled_exception(struct pt_regs *regs, int ea, int vector)
+
+ asmlinkage void do_fpe_trap(struct pt_regs *regs, unsigned long address)
+ {
+- int code = FPE_FLTUNK;
+- unsigned long fpcsr = regs->fpcsr;
+-
+- if (fpcsr & SPR_FPCSR_IVF)
+- code = FPE_FLTINV;
+- else if (fpcsr & SPR_FPCSR_OVF)
+- code = FPE_FLTOVF;
+- else if (fpcsr & SPR_FPCSR_UNF)
+- code = FPE_FLTUND;
+- else if (fpcsr & SPR_FPCSR_DZF)
+- code = FPE_FLTDIV;
+- else if (fpcsr & SPR_FPCSR_IXF)
+- code = FPE_FLTRES;
+-
+- /* Clear all flags */
+- regs->fpcsr &= ~SPR_FPCSR_ALLF;
+-
+- force_sig_fault(SIGFPE, code, (void __user *)regs->pc);
++ if (user_mode(regs)) {
++ int code = FPE_FLTUNK;
++ unsigned long fpcsr = regs->fpcsr;
++
++ if (fpcsr & SPR_FPCSR_IVF)
++ code = FPE_FLTINV;
++ else if (fpcsr & SPR_FPCSR_OVF)
++ code = FPE_FLTOVF;
++ else if (fpcsr & SPR_FPCSR_UNF)
++ code = FPE_FLTUND;
++ else if (fpcsr & SPR_FPCSR_DZF)
++ code = FPE_FLTDIV;
++ else if (fpcsr & SPR_FPCSR_IXF)
++ code = FPE_FLTRES;
++
++ /* Clear all flags */
++ regs->fpcsr &= ~SPR_FPCSR_ALLF;
++
++ force_sig_fault(SIGFPE, code, (void __user *)regs->pc);
++ } else {
++ pr_emerg("KERNEL: Illegal fpe exception 0x%.8lx\n", regs->pc);
++ die("Die:", regs, SIGFPE);
++ }
+ }
+
+ asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)
+ {
+- force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc);
++ if (user_mode(regs)) {
++ force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc);
++ } else {
++ pr_emerg("KERNEL: Illegal trap exception 0x%.8lx\n", regs->pc);
++ die("Die:", regs, SIGILL);
++ }
+ }
+
+ asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address)
+diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
+index 6f0c92e8149d8..dcf61cbd31470 100644
+--- a/arch/parisc/kernel/parisc_ksyms.c
++++ b/arch/parisc/kernel/parisc_ksyms.c
+@@ -22,6 +22,7 @@ EXPORT_SYMBOL(memset);
+ #include <linux/atomic.h>
+ EXPORT_SYMBOL(__xchg8);
+ EXPORT_SYMBOL(__xchg32);
++EXPORT_SYMBOL(__cmpxchg_u8);
+ EXPORT_SYMBOL(__cmpxchg_u32);
+ EXPORT_SYMBOL(__cmpxchg_u64);
+ #ifdef CONFIG_SMP
+diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
+index 558ec68d768e6..60a2c5925161a 100644
+--- a/arch/powerpc/sysdev/fsl_msi.c
++++ b/arch/powerpc/sysdev/fsl_msi.c
+@@ -566,10 +566,12 @@ static const struct fsl_msi_feature ipic_msi_feature = {
+ .msiir_offset = 0x38,
+ };
+
++#ifdef CONFIG_EPAPR_PARAVIRT
+ static const struct fsl_msi_feature vmpic_msi_feature = {
+ .fsl_pic_ip = FSL_PIC_IP_VMPIC,
+ .msiir_offset = 0,
+ };
++#endif
+
+ static const struct of_device_id fsl_of_msi_ids[] = {
+ {
+diff --git a/arch/riscv/Kconfig.errata b/arch/riscv/Kconfig.errata
+index 910ba8837add8..2acc7d876e1fb 100644
+--- a/arch/riscv/Kconfig.errata
++++ b/arch/riscv/Kconfig.errata
+@@ -82,14 +82,14 @@ config ERRATA_THEAD
+
+ Otherwise, please say "N" here to avoid unnecessary overhead.
+
+-config ERRATA_THEAD_PBMT
+- bool "Apply T-Head memory type errata"
++config ERRATA_THEAD_MAE
++ bool "Apply T-Head's memory attribute extension (XTheadMae) errata"
+ depends on ERRATA_THEAD && 64BIT && MMU
+ select RISCV_ALTERNATIVE_EARLY
+ default y
+ help
+- This will apply the memory type errata to handle the non-standard
+- memory type bits in page-table-entries on T-Head SoCs.
++ This will apply the memory attribute extension errata to handle the
++ non-standard PTE utilization on T-Head SoCs (XTheadMae).
+
+ If you don't know what to do here, say "Y".
+
+diff --git a/arch/riscv/errata/thead/errata.c b/arch/riscv/errata/thead/errata.c
+index b1c410bbc1aec..bf6a0a6318ee3 100644
+--- a/arch/riscv/errata/thead/errata.c
++++ b/arch/riscv/errata/thead/errata.c
+@@ -19,20 +19,26 @@
+ #include <asm/patch.h>
+ #include <asm/vendorid_list.h>
+
+-static bool errata_probe_pbmt(unsigned int stage,
+- unsigned long arch_id, unsigned long impid)
++#define CSR_TH_SXSTATUS 0x5c0
++#define SXSTATUS_MAEE _AC(0x200000, UL)
++
++static bool errata_probe_mae(unsigned int stage,
++ unsigned long arch_id, unsigned long impid)
+ {
+- if (!IS_ENABLED(CONFIG_ERRATA_THEAD_PBMT))
++ if (!IS_ENABLED(CONFIG_ERRATA_THEAD_MAE))
+ return false;
+
+ if (arch_id != 0 || impid != 0)
+ return false;
+
+- if (stage == RISCV_ALTERNATIVES_EARLY_BOOT ||
+- stage == RISCV_ALTERNATIVES_MODULE)
+- return true;
++ if (stage != RISCV_ALTERNATIVES_EARLY_BOOT &&
++ stage != RISCV_ALTERNATIVES_MODULE)
++ return false;
++
++ if (!(csr_read(CSR_TH_SXSTATUS) & SXSTATUS_MAEE))
++ return false;
+
+- return false;
++ return true;
+ }
+
+ /*
+@@ -140,8 +146,8 @@ static u32 thead_errata_probe(unsigned int stage,
+ {
+ u32 cpu_req_errata = 0;
+
+- if (errata_probe_pbmt(stage, archid, impid))
+- cpu_req_errata |= BIT(ERRATA_THEAD_PBMT);
++ if (errata_probe_mae(stage, archid, impid))
++ cpu_req_errata |= BIT(ERRATA_THEAD_MAE);
+
+ errata_probe_cmo(stage, archid, impid);
+
+diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
+index ea33288f8a25b..9bad9dfa2f7a1 100644
+--- a/arch/riscv/include/asm/errata_list.h
++++ b/arch/riscv/include/asm/errata_list.h
+@@ -23,7 +23,7 @@
+ #endif
+
+ #ifdef CONFIG_ERRATA_THEAD
+-#define ERRATA_THEAD_PBMT 0
++#define ERRATA_THEAD_MAE 0
+ #define ERRATA_THEAD_PMU 1
+ #define ERRATA_THEAD_NUMBER 2
+ #endif
+@@ -53,20 +53,20 @@ asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID, \
+ * in the default case.
+ */
+ #define ALT_SVPBMT_SHIFT 61
+-#define ALT_THEAD_PBMT_SHIFT 59
++#define ALT_THEAD_MAE_SHIFT 59
+ #define ALT_SVPBMT(_val, prot) \
+ asm(ALTERNATIVE_2("li %0, 0\t\nnop", \
+ "li %0, %1\t\nslli %0,%0,%3", 0, \
+ RISCV_ISA_EXT_SVPBMT, CONFIG_RISCV_ISA_SVPBMT, \
+ "li %0, %2\t\nslli %0,%0,%4", THEAD_VENDOR_ID, \
+- ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT) \
++ ERRATA_THEAD_MAE, CONFIG_ERRATA_THEAD_MAE) \
+ : "=r"(_val) \
+ : "I"(prot##_SVPBMT >> ALT_SVPBMT_SHIFT), \
+- "I"(prot##_THEAD >> ALT_THEAD_PBMT_SHIFT), \
++ "I"(prot##_THEAD >> ALT_THEAD_MAE_SHIFT), \
+ "I"(ALT_SVPBMT_SHIFT), \
+- "I"(ALT_THEAD_PBMT_SHIFT))
++ "I"(ALT_THEAD_MAE_SHIFT))
+
+-#ifdef CONFIG_ERRATA_THEAD_PBMT
++#ifdef CONFIG_ERRATA_THEAD_MAE
+ /*
+ * IO/NOCACHE memory types are handled together with svpbmt,
+ * so on T-Head chips, check if no other memory type is set,
+@@ -83,11 +83,11 @@ asm volatile(ALTERNATIVE( \
+ "slli t3, t3, %3\n\t" \
+ "or %0, %0, t3\n\t" \
+ "2:", THEAD_VENDOR_ID, \
+- ERRATA_THEAD_PBMT, CONFIG_ERRATA_THEAD_PBMT) \
++ ERRATA_THEAD_MAE, CONFIG_ERRATA_THEAD_MAE) \
+ : "+r"(_val) \
+- : "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_PBMT_SHIFT), \
+- "I"(_PAGE_PMA_THEAD >> ALT_THEAD_PBMT_SHIFT), \
+- "I"(ALT_THEAD_PBMT_SHIFT) \
++ : "I"(_PAGE_MTMASK_THEAD >> ALT_THEAD_MAE_SHIFT), \
++ "I"(_PAGE_PMA_THEAD >> ALT_THEAD_MAE_SHIFT), \
++ "I"(ALT_THEAD_MAE_SHIFT) \
+ : "t3")
+ #else
+ #define ALT_THEAD_PMA(_val)
+diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
+index 0bd747d1d00fc..29f031f68f480 100644
+--- a/arch/riscv/net/bpf_jit_comp64.c
++++ b/arch/riscv/net/bpf_jit_comp64.c
+@@ -516,33 +516,33 @@ static void emit_atomic(u8 rd, u8 rs, s16 off, s32 imm, bool is64,
+ break;
+ /* src_reg = atomic_fetch_<op>(dst_reg + off16, src_reg) */
+ case BPF_ADD | BPF_FETCH:
+- emit(is64 ? rv_amoadd_d(rs, rs, rd, 0, 0) :
+- rv_amoadd_w(rs, rs, rd, 0, 0), ctx);
++ emit(is64 ? rv_amoadd_d(rs, rs, rd, 1, 1) :
++ rv_amoadd_w(rs, rs, rd, 1, 1), ctx);
+ if (!is64)
+ emit_zext_32(rs, ctx);
+ break;
+ case BPF_AND | BPF_FETCH:
+- emit(is64 ? rv_amoand_d(rs, rs, rd, 0, 0) :
+- rv_amoand_w(rs, rs, rd, 0, 0), ctx);
++ emit(is64 ? rv_amoand_d(rs, rs, rd, 1, 1) :
++ rv_amoand_w(rs, rs, rd, 1, 1), ctx);
+ if (!is64)
+ emit_zext_32(rs, ctx);
+ break;
+ case BPF_OR | BPF_FETCH:
+- emit(is64 ? rv_amoor_d(rs, rs, rd, 0, 0) :
+- rv_amoor_w(rs, rs, rd, 0, 0), ctx);
++ emit(is64 ? rv_amoor_d(rs, rs, rd, 1, 1) :
++ rv_amoor_w(rs, rs, rd, 1, 1), ctx);
+ if (!is64)
+ emit_zext_32(rs, ctx);
+ break;
+ case BPF_XOR | BPF_FETCH:
+- emit(is64 ? rv_amoxor_d(rs, rs, rd, 0, 0) :
+- rv_amoxor_w(rs, rs, rd, 0, 0), ctx);
++ emit(is64 ? rv_amoxor_d(rs, rs, rd, 1, 1) :
++ rv_amoxor_w(rs, rs, rd, 1, 1), ctx);
+ if (!is64)
+ emit_zext_32(rs, ctx);
+ break;
+ /* src_reg = atomic_xchg(dst_reg + off16, src_reg); */
+ case BPF_XCHG:
+- emit(is64 ? rv_amoswap_d(rs, rs, rd, 0, 0) :
+- rv_amoswap_w(rs, rs, rd, 0, 0), ctx);
++ emit(is64 ? rv_amoswap_d(rs, rs, rd, 1, 1) :
++ rv_amoswap_w(rs, rs, rd, 1, 1), ctx);
+ if (!is64)
+ emit_zext_32(rs, ctx);
+ break;
+diff --git a/arch/s390/include/asm/gmap.h b/arch/s390/include/asm/gmap.h
+index 5cc46e0dde620..9725586f42597 100644
+--- a/arch/s390/include/asm/gmap.h
++++ b/arch/s390/include/asm/gmap.h
+@@ -146,7 +146,7 @@ int gmap_mprotect_notify(struct gmap *, unsigned long start,
+
+ void gmap_sync_dirty_log_pmd(struct gmap *gmap, unsigned long dirty_bitmap[4],
+ unsigned long gaddr, unsigned long vmaddr);
+-int gmap_mark_unmergeable(void);
++int s390_disable_cow_sharing(void);
+ void s390_unlist_old_asce(struct gmap *gmap);
+ int s390_replace_asce(struct gmap *gmap);
+ void s390_uv_destroy_pfns(unsigned long count, unsigned long *pfns);
+diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h
+index bb1b4bef1878b..4c2dc7abc2858 100644
+--- a/arch/s390/include/asm/mmu.h
++++ b/arch/s390/include/asm/mmu.h
+@@ -32,6 +32,11 @@ typedef struct {
+ unsigned int uses_skeys:1;
+ /* The mmu context uses CMM. */
+ unsigned int uses_cmm:1;
++ /*
++ * The mmu context allows COW-sharing of memory pages (KSM, zeropage).
++ * Note that COW-sharing during fork() is currently always allowed.
++ */
++ unsigned int allow_cow_sharing:1;
+ /* The gmaps associated with this context are allowed to use huge pages. */
+ unsigned int allow_gmap_hpage_1m:1;
+ } mm_context_t;
+diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
+index 929af18b09081..a7789a9f62186 100644
+--- a/arch/s390/include/asm/mmu_context.h
++++ b/arch/s390/include/asm/mmu_context.h
+@@ -35,6 +35,7 @@ static inline int init_new_context(struct task_struct *tsk,
+ mm->context.has_pgste = 0;
+ mm->context.uses_skeys = 0;
+ mm->context.uses_cmm = 0;
++ mm->context.allow_cow_sharing = 1;
+ mm->context.allow_gmap_hpage_1m = 0;
+ #endif
+ switch (mm->context.asce_limit) {
+diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
+index 12a7b86789259..0a7055518ba20 100644
+--- a/arch/s390/include/asm/pgtable.h
++++ b/arch/s390/include/asm/pgtable.h
+@@ -566,10 +566,20 @@ static inline pud_t set_pud_bit(pud_t pud, pgprot_t prot)
+ }
+
+ /*
+- * In the case that a guest uses storage keys
+- * faults should no longer be backed by zero pages
++ * As soon as the guest uses storage keys or enables PV, we deduplicate all
++ * mapped shared zeropages and prevent new shared zeropages from getting
++ * mapped.
+ */
+-#define mm_forbids_zeropage mm_has_pgste
++#define mm_forbids_zeropage mm_forbids_zeropage
++static inline int mm_forbids_zeropage(struct mm_struct *mm)
++{
++#ifdef CONFIG_PGSTE
++ if (!mm->context.allow_cow_sharing)
++ return 1;
++#endif
++ return 0;
++}
++
+ static inline int mm_uses_skeys(struct mm_struct *mm)
+ {
+ #ifdef CONFIG_PGSTE
+diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
+index ea63ac7698891..7c17be6ad4802 100644
+--- a/arch/s390/kvm/kvm-s390.c
++++ b/arch/s390/kvm/kvm-s390.c
+@@ -2631,9 +2631,7 @@ static int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)
+ if (r)
+ break;
+
+- mmap_write_lock(current->mm);
+- r = gmap_mark_unmergeable();
+- mmap_write_unlock(current->mm);
++ r = s390_disable_cow_sharing();
+ if (r)
+ break;
+
+diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
+index 41a4a60c5e651..3b57837f3e914 100644
+--- a/arch/s390/mm/gmap.c
++++ b/arch/s390/mm/gmap.c
+@@ -2547,41 +2547,6 @@ static inline void thp_split_mm(struct mm_struct *mm)
+ }
+ #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
+-/*
+- * Remove all empty zero pages from the mapping for lazy refaulting
+- * - This must be called after mm->context.has_pgste is set, to avoid
+- * future creation of zero pages
+- * - This must be called after THP was disabled.
+- *
+- * mm contracts with s390, that even if mm were to remove a page table,
+- * racing with the loop below and so causing pte_offset_map_lock() to fail,
+- * it will never insert a page table containing empty zero pages once
+- * mm_forbids_zeropage(mm) i.e. mm->context.has_pgste is set.
+- */
+-static int __zap_zero_pages(pmd_t *pmd, unsigned long start,
+- unsigned long end, struct mm_walk *walk)
+-{
+- unsigned long addr;
+-
+- for (addr = start; addr != end; addr += PAGE_SIZE) {
+- pte_t *ptep;
+- spinlock_t *ptl;
+-
+- ptep = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
+- if (!ptep)
+- break;
+- if (is_zero_pfn(pte_pfn(*ptep)))
+- ptep_xchg_direct(walk->mm, addr, ptep, __pte(_PAGE_INVALID));
+- pte_unmap_unlock(ptep, ptl);
+- }
+- return 0;
+-}
+-
+-static const struct mm_walk_ops zap_zero_walk_ops = {
+- .pmd_entry = __zap_zero_pages,
+- .walk_lock = PGWALK_WRLOCK,
+-};
+-
+ /*
+ * switch on pgstes for its userspace process (for kvm)
+ */
+@@ -2599,22 +2564,142 @@ int s390_enable_sie(void)
+ mm->context.has_pgste = 1;
+ /* split thp mappings and disable thp for future mappings */
+ thp_split_mm(mm);
+- walk_page_range(mm, 0, TASK_SIZE, &zap_zero_walk_ops, NULL);
+ mmap_write_unlock(mm);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(s390_enable_sie);
+
+-int gmap_mark_unmergeable(void)
++static int find_zeropage_pte_entry(pte_t *pte, unsigned long addr,
++ unsigned long end, struct mm_walk *walk)
++{
++ unsigned long *found_addr = walk->private;
++
++ /* Return 1 of the page is a zeropage. */
++ if (is_zero_pfn(pte_pfn(*pte))) {
++ /*
++ * Shared zeropage in e.g., a FS DAX mapping? We cannot do the
++ * right thing and likely don't care: FAULT_FLAG_UNSHARE
++ * currently only works in COW mappings, which is also where
++ * mm_forbids_zeropage() is checked.
++ */
++ if (!is_cow_mapping(walk->vma->vm_flags))
++ return -EFAULT;
++
++ *found_addr = addr;
++ return 1;
++ }
++ return 0;
++}
++
++static const struct mm_walk_ops find_zeropage_ops = {
++ .pte_entry = find_zeropage_pte_entry,
++ .walk_lock = PGWALK_WRLOCK,
++};
++
++/*
++ * Unshare all shared zeropages, replacing them by anonymous pages. Note that
++ * we cannot simply zap all shared zeropages, because this could later
++ * trigger unexpected userfaultfd missing events.
++ *
++ * This must be called after mm->context.allow_cow_sharing was
++ * set to 0, to avoid future mappings of shared zeropages.
++ *
++ * mm contracts with s390, that even if mm were to remove a page table,
++ * and racing with walk_page_range_vma() calling pte_offset_map_lock()
++ * would fail, it will never insert a page table containing empty zero
++ * pages once mm_forbids_zeropage(mm) i.e.
++ * mm->context.allow_cow_sharing is set to 0.
++ */
++static int __s390_unshare_zeropages(struct mm_struct *mm)
++{
++ struct vm_area_struct *vma;
++ VMA_ITERATOR(vmi, mm, 0);
++ unsigned long addr;
++ vm_fault_t fault;
++ int rc;
++
++ for_each_vma(vmi, vma) {
++ /*
++ * We could only look at COW mappings, but it's more future
++ * proof to catch unexpected zeropages in other mappings and
++ * fail.
++ */
++ if ((vma->vm_flags & VM_PFNMAP) || is_vm_hugetlb_page(vma))
++ continue;
++ addr = vma->vm_start;
++
++retry:
++ rc = walk_page_range_vma(vma, addr, vma->vm_end,
++ &find_zeropage_ops, &addr);
++ if (rc < 0)
++ return rc;
++ else if (!rc)
++ continue;
++
++ /* addr was updated by find_zeropage_pte_entry() */
++ fault = handle_mm_fault(vma, addr,
++ FAULT_FLAG_UNSHARE | FAULT_FLAG_REMOTE,
++ NULL);
++ if (fault & VM_FAULT_OOM)
++ return -ENOMEM;
++ /*
++ * See break_ksm(): even after handle_mm_fault() returned 0, we
++ * must start the lookup from the current address, because
++ * handle_mm_fault() may back out if there's any difficulty.
++ *
++ * VM_FAULT_SIGBUS and VM_FAULT_SIGSEGV are unexpected but
++ * maybe they could trigger in the future on concurrent
++ * truncation. In that case, the shared zeropage would be gone
++ * and we can simply retry and make progress.
++ */
++ cond_resched();
++ goto retry;
++ }
++
++ return 0;
++}
++
++static int __s390_disable_cow_sharing(struct mm_struct *mm)
+ {
++ int rc;
++
++ if (!mm->context.allow_cow_sharing)
++ return 0;
++
++ mm->context.allow_cow_sharing = 0;
++
++ /* Replace all shared zeropages by anonymous pages. */
++ rc = __s390_unshare_zeropages(mm);
+ /*
+ * Make sure to disable KSM (if enabled for the whole process or
+ * individual VMAs). Note that nothing currently hinders user space
+ * from re-enabling it.
+ */
+- return ksm_disable(current->mm);
++ if (!rc)
++ rc = ksm_disable(mm);
++ if (rc)
++ mm->context.allow_cow_sharing = 1;
++ return rc;
++}
++
++/*
++ * Disable most COW-sharing of memory pages for the whole process:
++ * (1) Disable KSM and unmerge/unshare any KSM pages.
++ * (2) Disallow shared zeropages and unshare any zerpages that are mapped.
++ *
++ * Not that we currently don't bother with COW-shared pages that are shared
++ * with parent/child processes due to fork().
++ */
++int s390_disable_cow_sharing(void)
++{
++ int rc;
++
++ mmap_write_lock(current->mm);
++ rc = __s390_disable_cow_sharing(current->mm);
++ mmap_write_unlock(current->mm);
++ return rc;
+ }
+-EXPORT_SYMBOL_GPL(gmap_mark_unmergeable);
++EXPORT_SYMBOL_GPL(s390_disable_cow_sharing);
+
+ /*
+ * Enable storage key handling from now on and initialize the storage
+@@ -2683,7 +2768,7 @@ int s390_enable_skey(void)
+ goto out_up;
+
+ mm->context.uses_skeys = 1;
+- rc = gmap_mark_unmergeable();
++ rc = __s390_disable_cow_sharing(mm);
+ if (rc) {
+ mm->context.uses_skeys = 0;
+ goto out_up;
+diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
+index 5af0402e94b88..1d168a98ae21b 100644
+--- a/arch/s390/net/bpf_jit_comp.c
++++ b/arch/s390/net/bpf_jit_comp.c
+@@ -1427,8 +1427,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
+ EMIT6_DISP_LH(0xeb000000, is32 ? (op32) : (op64), \
+ (insn->imm & BPF_FETCH) ? src_reg : REG_W0, \
+ src_reg, dst_reg, off); \
+- if (is32 && (insn->imm & BPF_FETCH)) \
+- EMIT_ZERO(src_reg); \
++ if (insn->imm & BPF_FETCH) { \
++ /* bcr 14,0 - see atomic_fetch_{add,and,or,xor}() */ \
++ _EMIT2(0x07e0); \
++ if (is32) \
++ EMIT_ZERO(src_reg); \
++ } \
+ } while (0)
+ case BPF_ADD:
+ case BPF_ADD | BPF_FETCH:
+diff --git a/arch/sh/kernel/kprobes.c b/arch/sh/kernel/kprobes.c
+index aed1ea8e2c2f0..74051b8ddf3e7 100644
+--- a/arch/sh/kernel/kprobes.c
++++ b/arch/sh/kernel/kprobes.c
+@@ -44,17 +44,12 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
+ if (OPCODE_RTE(opcode))
+ return -EFAULT; /* Bad breakpoint */
+
++ memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+ p->opcode = opcode;
+
+ return 0;
+ }
+
+-void __kprobes arch_copy_kprobe(struct kprobe *p)
+-{
+- memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+- p->opcode = *p->addr;
+-}
+-
+ void __kprobes arch_arm_kprobe(struct kprobe *p)
+ {
+ *p->addr = BREAKPOINT_INSTRUCTION;
+diff --git a/arch/sh/lib/checksum.S b/arch/sh/lib/checksum.S
+index 3e07074e00981..06fed5a21e8ba 100644
+--- a/arch/sh/lib/checksum.S
++++ b/arch/sh/lib/checksum.S
+@@ -33,7 +33,8 @@
+ */
+
+ /*
+- * asmlinkage __wsum csum_partial(const void *buf, int len, __wsum sum);
++ * unsigned int csum_partial(const unsigned char *buf, int len,
++ * unsigned int sum);
+ */
+
+ .text
+@@ -45,31 +46,11 @@ ENTRY(csum_partial)
+ * Fortunately, it is easy to convert 2-byte alignment to 4-byte
+ * alignment for the unrolled loop.
+ */
++ mov r5, r1
+ mov r4, r0
+- tst #3, r0 ! Check alignment.
+- bt/s 2f ! Jump if alignment is ok.
+- mov r4, r7 ! Keep a copy to check for alignment
++ tst #2, r0 ! Check alignment.
++ bt 2f ! Jump if alignment is ok.
+ !
+- tst #1, r0 ! Check alignment.
+- bt 21f ! Jump if alignment is boundary of 2bytes.
+-
+- ! buf is odd
+- tst r5, r5
+- add #-1, r5
+- bt 9f
+- mov.b @r4+, r0
+- extu.b r0, r0
+- addc r0, r6 ! t=0 from previous tst
+- mov r6, r0
+- shll8 r6
+- shlr16 r0
+- shlr8 r0
+- or r0, r6
+- mov r4, r0
+- tst #2, r0
+- bt 2f
+-21:
+- ! buf is 2 byte aligned (len could be 0)
+ add #-2, r5 ! Alignment uses up two bytes.
+ cmp/pz r5 !
+ bt/s 1f ! Jump if we had at least two bytes.
+@@ -77,17 +58,16 @@ ENTRY(csum_partial)
+ bra 6f
+ add #2, r5 ! r5 was < 2. Deal with it.
+ 1:
++ mov r5, r1 ! Save new len for later use.
+ mov.w @r4+, r0
+ extu.w r0, r0
+ addc r0, r6
+ bf 2f
+ add #1, r6
+ 2:
+- ! buf is 4 byte aligned (len could be 0)
+- mov r5, r1
+ mov #-5, r0
+- shld r0, r1
+- tst r1, r1
++ shld r0, r5
++ tst r5, r5
+ bt/s 4f ! if it's =0, go to 4f
+ clrt
+ .align 2
+@@ -109,31 +89,30 @@ ENTRY(csum_partial)
+ addc r0, r6
+ addc r2, r6
+ movt r0
+- dt r1
++ dt r5
+ bf/s 3b
+ cmp/eq #1, r0
+- ! here, we know r1==0
+- addc r1, r6 ! add carry to r6
++ ! here, we know r5==0
++ addc r5, r6 ! add carry to r6
+ 4:
+- mov r5, r0
++ mov r1, r0
+ and #0x1c, r0
+ tst r0, r0
+- bt 6f
+- ! 4 bytes or more remaining
+- mov r0, r1
+- shlr2 r1
++ bt/s 6f
++ mov r0, r5
++ shlr2 r5
+ mov #0, r2
+ 5:
+ addc r2, r6
+ mov.l @r4+, r2
+ movt r0
+- dt r1
++ dt r5
+ bf/s 5b
+ cmp/eq #1, r0
+ addc r2, r6
+- addc r1, r6 ! r1==0 here, so it means add carry-bit
++ addc r5, r6 ! r5==0 here, so it means add carry-bit
+ 6:
+- ! 3 bytes or less remaining
++ mov r1, r5
+ mov #3, r0
+ and r0, r5
+ tst r5, r5
+@@ -159,16 +138,6 @@ ENTRY(csum_partial)
+ mov #0, r0
+ addc r0, r6
+ 9:
+- ! Check if the buffer was misaligned, if so realign sum
+- mov r7, r0
+- tst #1, r0
+- bt 10f
+- mov r6, r0
+- shll8 r6
+- shlr16 r0
+- shlr8 r0
+- or r0, r6
+-10:
+ rts
+ mov r6, r0
+
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 6f49999a6b838..bfccf1213871b 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -2474,9 +2474,13 @@ menuconfig CPU_MITIGATIONS
+ help
+ Say Y here to enable options which enable mitigations for hardware
+ vulnerabilities (usually related to speculative execution).
++ Mitigations can be disabled or restricted to SMT systems at runtime
++ via the "mitigations" kernel parameter.
+
+- If you say N, all mitigations will be disabled. You really
+- should know what you are doing to say so.
++ If you say N, all mitigations will be disabled. This CANNOT be
++ overridden at runtime.
++
++ Say 'Y', unless you really know what you are doing.
+
+ if CPU_MITIGATIONS
+
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index bf4a10a5794f1..1dcb794c5479e 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -398,6 +398,11 @@ SYM_CODE_START(startup_64)
+ call sev_enable
+ #endif
+
++ /* Preserve only the CR4 bits that must be preserved, and clear the rest */
++ movq %cr4, %rax
++ andl $(X86_CR4_PAE | X86_CR4_MCE | X86_CR4_LA57), %eax
++ movq %rax, %cr4
++
+ /*
+ * configure_5level_paging() updates the number of paging levels using
+ * a trampoline in 32-bit addressable memory if the current number does
+diff --git a/arch/x86/crypto/nh-avx2-x86_64.S b/arch/x86/crypto/nh-avx2-x86_64.S
+index ef73a3ab87263..791386d9a83aa 100644
+--- a/arch/x86/crypto/nh-avx2-x86_64.S
++++ b/arch/x86/crypto/nh-avx2-x86_64.S
+@@ -154,5 +154,6 @@ SYM_TYPED_FUNC_START(nh_avx2)
+ vpaddq T1, T0, T0
+ vpaddq T4, T0, T0
+ vmovdqu T0, (HASH)
++ vzeroupper
+ RET
+ SYM_FUNC_END(nh_avx2)
+diff --git a/arch/x86/crypto/sha256-avx2-asm.S b/arch/x86/crypto/sha256-avx2-asm.S
+index 9918212faf914..0ffb072be9561 100644
+--- a/arch/x86/crypto/sha256-avx2-asm.S
++++ b/arch/x86/crypto/sha256-avx2-asm.S
+@@ -716,6 +716,7 @@ SYM_TYPED_FUNC_START(sha256_transform_rorx)
+ popq %r13
+ popq %r12
+ popq %rbx
++ vzeroupper
+ RET
+ SYM_FUNC_END(sha256_transform_rorx)
+
+diff --git a/arch/x86/crypto/sha512-avx2-asm.S b/arch/x86/crypto/sha512-avx2-asm.S
+index f08496cd68708..24973f42c43ff 100644
+--- a/arch/x86/crypto/sha512-avx2-asm.S
++++ b/arch/x86/crypto/sha512-avx2-asm.S
+@@ -680,6 +680,7 @@ SYM_TYPED_FUNC_START(sha512_transform_rorx)
+ pop %r12
+ pop %rbx
+
++ vzeroupper
+ RET
+ SYM_FUNC_END(sha512_transform_rorx)
+
+diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
+index e0ca8120aea87..1245000a8792f 100644
+--- a/arch/x86/entry/vsyscall/vsyscall_64.c
++++ b/arch/x86/entry/vsyscall/vsyscall_64.c
+@@ -98,11 +98,6 @@ static int addr_to_vsyscall_nr(unsigned long addr)
+
+ static bool write_ok_or_segv(unsigned long ptr, size_t size)
+ {
+- /*
+- * XXX: if access_ok, get_user, and put_user handled
+- * sig_on_uaccess_err, this could go away.
+- */
+-
+ if (!access_ok((void __user *)ptr, size)) {
+ struct thread_struct *thread = ¤t->thread;
+
+@@ -120,10 +115,8 @@ static bool write_ok_or_segv(unsigned long ptr, size_t size)
+ bool emulate_vsyscall(unsigned long error_code,
+ struct pt_regs *regs, unsigned long address)
+ {
+- struct task_struct *tsk;
+ unsigned long caller;
+ int vsyscall_nr, syscall_nr, tmp;
+- int prev_sig_on_uaccess_err;
+ long ret;
+ unsigned long orig_dx;
+
+@@ -172,8 +165,6 @@ bool emulate_vsyscall(unsigned long error_code,
+ goto sigsegv;
+ }
+
+- tsk = current;
+-
+ /*
+ * Check for access_ok violations and find the syscall nr.
+ *
+@@ -234,12 +225,8 @@ bool emulate_vsyscall(unsigned long error_code,
+ goto do_ret; /* skip requested */
+
+ /*
+- * With a real vsyscall, page faults cause SIGSEGV. We want to
+- * preserve that behavior to make writing exploits harder.
++ * With a real vsyscall, page faults cause SIGSEGV.
+ */
+- prev_sig_on_uaccess_err = current->thread.sig_on_uaccess_err;
+- current->thread.sig_on_uaccess_err = 1;
+-
+ ret = -EFAULT;
+ switch (vsyscall_nr) {
+ case 0:
+@@ -262,23 +249,12 @@ bool emulate_vsyscall(unsigned long error_code,
+ break;
+ }
+
+- current->thread.sig_on_uaccess_err = prev_sig_on_uaccess_err;
+-
+ check_fault:
+ if (ret == -EFAULT) {
+ /* Bad news -- userspace fed a bad pointer to a vsyscall. */
+ warn_bad_vsyscall(KERN_INFO, regs,
+ "vsyscall fault (exploit attempt?)");
+-
+- /*
+- * If we failed to generate a signal for any reason,
+- * generate one here. (This should be impossible.)
+- */
+- if (WARN_ON_ONCE(!sigismember(&tsk->pending.signal, SIGBUS) &&
+- !sigismember(&tsk->pending.signal, SIGSEGV)))
+- goto sigsegv;
+-
+- return true; /* Don't emulate the ret. */
++ goto sigsegv;
+ }
+
+ regs->ax = ret;
+diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h
+index 44b08b53ab32f..c1d6cd58f8094 100644
+--- a/arch/x86/include/asm/cmpxchg_64.h
++++ b/arch/x86/include/asm/cmpxchg_64.h
+@@ -62,7 +62,7 @@ static __always_inline u128 arch_cmpxchg128_local(volatile u128 *ptr, u128 old,
+ asm volatile(_lock "cmpxchg16b %[ptr]" \
+ CC_SET(e) \
+ : CC_OUT(e) (ret), \
+- [ptr] "+m" (*ptr), \
++ [ptr] "+m" (*(_ptr)), \
+ "+a" (o.low), "+d" (o.high) \
+ : "b" (n.low), "c" (n.high) \
+ : "memory"); \
+diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
+index 9abb8cc4cd474..b786449626267 100644
+--- a/arch/x86/include/asm/pgtable_types.h
++++ b/arch/x86/include/asm/pgtable_types.h
+@@ -567,6 +567,8 @@ static inline void update_page_count(int level, unsigned long pages) { }
+ extern pte_t *lookup_address(unsigned long address, unsigned int *level);
+ extern pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
+ unsigned int *level);
++pte_t *lookup_address_in_pgd_attr(pgd_t *pgd, unsigned long address,
++ unsigned int *level, bool *nx, bool *rw);
+ extern pmd_t *lookup_pmd_address(unsigned long address);
+ extern phys_addr_t slow_virt_to_phys(void *__address);
+ extern int __init kernel_map_pages_in_pgd(pgd_t *pgd, u64 pfn,
+diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
+index 26620d7642a9f..5636ad697394d 100644
+--- a/arch/x86/include/asm/processor.h
++++ b/arch/x86/include/asm/processor.h
+@@ -479,7 +479,6 @@ struct thread_struct {
+ unsigned long iopl_emul;
+
+ unsigned int iopl_warn:1;
+- unsigned int sig_on_uaccess_err:1;
+
+ /*
+ * Protection Keys Register for Userspace. Loaded immediately on
+diff --git a/arch/x86/include/asm/sparsemem.h b/arch/x86/include/asm/sparsemem.h
+index 1be13b2dfe8bf..64df897c0ee30 100644
+--- a/arch/x86/include/asm/sparsemem.h
++++ b/arch/x86/include/asm/sparsemem.h
+@@ -37,8 +37,6 @@ extern int phys_to_target_node(phys_addr_t start);
+ #define phys_to_target_node phys_to_target_node
+ extern int memory_add_physaddr_to_nid(u64 start);
+ #define memory_add_physaddr_to_nid memory_add_physaddr_to_nid
+-extern int numa_fill_memblks(u64 start, u64 end);
+-#define numa_fill_memblks numa_fill_memblks
+ #endif
+ #endif /* __ASSEMBLY__ */
+
+diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
+index 13b45b9c806da..620f0af713ca2 100644
+--- a/arch/x86/kernel/cpu/microcode/amd.c
++++ b/arch/x86/kernel/cpu/microcode/amd.c
+@@ -465,7 +465,7 @@ static bool early_apply_microcode(u32 cpuid_1_eax, u32 old_rev, void *ucode, siz
+ return !__apply_microcode_amd(mc);
+ }
+
+-static bool get_builtin_microcode(struct cpio_data *cp, unsigned int family)
++static bool get_builtin_microcode(struct cpio_data *cp, u8 family)
+ {
+ char fw_name[36] = "amd-ucode/microcode_amd.bin";
+ struct firmware fw;
+diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c
+index 1123ef3ccf901..4334033658edf 100644
+--- a/arch/x86/kernel/tsc_sync.c
++++ b/arch/x86/kernel/tsc_sync.c
+@@ -193,11 +193,9 @@ bool tsc_store_and_check_tsc_adjust(bool bootcpu)
+ cur->warned = false;
+
+ /*
+- * If a non-zero TSC value for socket 0 may be valid then the default
+- * adjusted value cannot assumed to be zero either.
++ * The default adjust value cannot be assumed to be zero on any socket.
+ */
+- if (tsc_async_resets)
+- cur->adjusted = bootval;
++ cur->adjusted = bootval;
+
+ /*
+ * Check whether this CPU is the first in a package to come up. In
+diff --git a/arch/x86/lib/x86-opcode-map.txt b/arch/x86/lib/x86-opcode-map.txt
+index 5168ee0360b24..d1ccd06c53127 100644
+--- a/arch/x86/lib/x86-opcode-map.txt
++++ b/arch/x86/lib/x86-opcode-map.txt
+@@ -148,7 +148,7 @@ AVXcode:
+ 65: SEG=GS (Prefix)
+ 66: Operand-Size (Prefix)
+ 67: Address-Size (Prefix)
+-68: PUSH Iz (d64)
++68: PUSH Iz
+ 69: IMUL Gv,Ev,Iz
+ 6a: PUSH Ib (d64)
+ 6b: IMUL Gv,Ev,Ib
+@@ -698,10 +698,10 @@ AVXcode: 2
+ 4d: vrcp14ss/d Vsd,Hpd,Wsd (66),(ev)
+ 4e: vrsqrt14ps/d Vpd,Wpd (66),(ev)
+ 4f: vrsqrt14ss/d Vsd,Hsd,Wsd (66),(ev)
+-50: vpdpbusd Vx,Hx,Wx (66),(ev)
+-51: vpdpbusds Vx,Hx,Wx (66),(ev)
+-52: vdpbf16ps Vx,Hx,Wx (F3),(ev) | vpdpwssd Vx,Hx,Wx (66),(ev) | vp4dpwssd Vdqq,Hdqq,Wdq (F2),(ev)
+-53: vpdpwssds Vx,Hx,Wx (66),(ev) | vp4dpwssds Vdqq,Hdqq,Wdq (F2),(ev)
++50: vpdpbusd Vx,Hx,Wx (66)
++51: vpdpbusds Vx,Hx,Wx (66)
++52: vdpbf16ps Vx,Hx,Wx (F3),(ev) | vpdpwssd Vx,Hx,Wx (66) | vp4dpwssd Vdqq,Hdqq,Wdq (F2),(ev)
++53: vpdpwssds Vx,Hx,Wx (66) | vp4dpwssds Vdqq,Hdqq,Wdq (F2),(ev)
+ 54: vpopcntb/w Vx,Wx (66),(ev)
+ 55: vpopcntd/q Vx,Wx (66),(ev)
+ 58: vpbroadcastd Vx,Wx (66),(v)
+diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
+index b01df023de04c..e604d2d6cc8f9 100644
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -717,39 +717,8 @@ kernelmode_fixup_or_oops(struct pt_regs *regs, unsigned long error_code,
+ WARN_ON_ONCE(user_mode(regs));
+
+ /* Are we prepared to handle this kernel fault? */
+- if (fixup_exception(regs, X86_TRAP_PF, error_code, address)) {
+- /*
+- * Any interrupt that takes a fault gets the fixup. This makes
+- * the below recursive fault logic only apply to a faults from
+- * task context.
+- */
+- if (in_interrupt())
+- return;
+-
+- /*
+- * Per the above we're !in_interrupt(), aka. task context.
+- *
+- * In this case we need to make sure we're not recursively
+- * faulting through the emulate_vsyscall() logic.
+- */
+- if (current->thread.sig_on_uaccess_err && signal) {
+- sanitize_error_code(address, &error_code);
+-
+- set_signal_archinfo(address, error_code);
+-
+- if (si_code == SEGV_PKUERR) {
+- force_sig_pkuerr((void __user *)address, pkey);
+- } else {
+- /* XXX: hwpoison faults will set the wrong code. */
+- force_sig_fault(signal, si_code, (void __user *)address);
+- }
+- }
+-
+- /*
+- * Barring that, we can do the fixup and be happy.
+- */
++ if (fixup_exception(regs, X86_TRAP_PF, error_code, address))
+ return;
+- }
+
+ /*
+ * AMD erratum #91 manifests as a spurious page fault on a PREFETCH
+diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
+index 65e9a6e391c04..ce84ba86e69e9 100644
+--- a/arch/x86/mm/numa.c
++++ b/arch/x86/mm/numa.c
+@@ -929,6 +929,8 @@ int memory_add_physaddr_to_nid(u64 start)
+ }
+ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+
++#endif
++
+ static int __init cmp_memblk(const void *a, const void *b)
+ {
+ const struct numa_memblk *ma = *(const struct numa_memblk **)a;
+@@ -1001,5 +1003,3 @@ int __init numa_fill_memblks(u64 start, u64 end)
+ }
+ return 0;
+ }
+-
+-#endif
+diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
+index 135bb594df8b7..b4073fb452b6a 100644
+--- a/arch/x86/mm/pat/set_memory.c
++++ b/arch/x86/mm/pat/set_memory.c
+@@ -619,7 +619,8 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long start,
+ * Validate strict W^X semantics.
+ */
+ static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long start,
+- unsigned long pfn, unsigned long npg)
++ unsigned long pfn, unsigned long npg,
++ bool nx, bool rw)
+ {
+ unsigned long end;
+
+@@ -641,6 +642,10 @@ static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long star
+ if ((pgprot_val(new) & (_PAGE_RW | _PAGE_NX)) != _PAGE_RW)
+ return new;
+
++ /* Non-leaf translation entries can disable writing or execution. */
++ if (!rw || nx)
++ return new;
++
+ end = start + npg * PAGE_SIZE - 1;
+ WARN_ONCE(1, "CPA detected W^X violation: %016llx -> %016llx range: 0x%016lx - 0x%016lx PFN %lx\n",
+ (unsigned long long)pgprot_val(old),
+@@ -657,20 +662,26 @@ static inline pgprot_t verify_rwx(pgprot_t old, pgprot_t new, unsigned long star
+
+ /*
+ * Lookup the page table entry for a virtual address in a specific pgd.
+- * Return a pointer to the entry and the level of the mapping.
++ * Return a pointer to the entry, the level of the mapping, and the effective
++ * NX and RW bits of all page table levels.
+ */
+-pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
+- unsigned int *level)
++pte_t *lookup_address_in_pgd_attr(pgd_t *pgd, unsigned long address,
++ unsigned int *level, bool *nx, bool *rw)
+ {
+ p4d_t *p4d;
+ pud_t *pud;
+ pmd_t *pmd;
+
+ *level = PG_LEVEL_NONE;
++ *nx = false;
++ *rw = true;
+
+ if (pgd_none(*pgd))
+ return NULL;
+
++ *nx |= pgd_flags(*pgd) & _PAGE_NX;
++ *rw &= pgd_flags(*pgd) & _PAGE_RW;
++
+ p4d = p4d_offset(pgd, address);
+ if (p4d_none(*p4d))
+ return NULL;
+@@ -679,6 +690,9 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
+ if (p4d_large(*p4d) || !p4d_present(*p4d))
+ return (pte_t *)p4d;
+
++ *nx |= p4d_flags(*p4d) & _PAGE_NX;
++ *rw &= p4d_flags(*p4d) & _PAGE_RW;
++
+ pud = pud_offset(p4d, address);
+ if (pud_none(*pud))
+ return NULL;
+@@ -687,6 +701,9 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
+ if (pud_leaf(*pud) || !pud_present(*pud))
+ return (pte_t *)pud;
+
++ *nx |= pud_flags(*pud) & _PAGE_NX;
++ *rw &= pud_flags(*pud) & _PAGE_RW;
++
+ pmd = pmd_offset(pud, address);
+ if (pmd_none(*pmd))
+ return NULL;
+@@ -695,11 +712,26 @@ pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
+ if (pmd_large(*pmd) || !pmd_present(*pmd))
+ return (pte_t *)pmd;
+
++ *nx |= pmd_flags(*pmd) & _PAGE_NX;
++ *rw &= pmd_flags(*pmd) & _PAGE_RW;
++
+ *level = PG_LEVEL_4K;
+
+ return pte_offset_kernel(pmd, address);
+ }
+
++/*
++ * Lookup the page table entry for a virtual address in a specific pgd.
++ * Return a pointer to the entry and the level of the mapping.
++ */
++pte_t *lookup_address_in_pgd(pgd_t *pgd, unsigned long address,
++ unsigned int *level)
++{
++ bool nx, rw;
++
++ return lookup_address_in_pgd_attr(pgd, address, level, &nx, &rw);
++}
++
+ /*
+ * Lookup the page table entry for a virtual address. Return a pointer
+ * to the entry and the level of the mapping.
+@@ -715,13 +747,16 @@ pte_t *lookup_address(unsigned long address, unsigned int *level)
+ EXPORT_SYMBOL_GPL(lookup_address);
+
+ static pte_t *_lookup_address_cpa(struct cpa_data *cpa, unsigned long address,
+- unsigned int *level)
++ unsigned int *level, bool *nx, bool *rw)
+ {
+- if (cpa->pgd)
+- return lookup_address_in_pgd(cpa->pgd + pgd_index(address),
+- address, level);
++ pgd_t *pgd;
++
++ if (!cpa->pgd)
++ pgd = pgd_offset_k(address);
++ else
++ pgd = cpa->pgd + pgd_index(address);
+
+- return lookup_address(address, level);
++ return lookup_address_in_pgd_attr(pgd, address, level, nx, rw);
+ }
+
+ /*
+@@ -849,12 +884,13 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
+ pgprot_t old_prot, new_prot, req_prot, chk_prot;
+ pte_t new_pte, *tmp;
+ enum pg_level level;
++ bool nx, rw;
+
+ /*
+ * Check for races, another CPU might have split this page
+ * up already:
+ */
+- tmp = _lookup_address_cpa(cpa, address, &level);
++ tmp = _lookup_address_cpa(cpa, address, &level, &nx, &rw);
+ if (tmp != kpte)
+ return 1;
+
+@@ -965,7 +1001,8 @@ static int __should_split_large_page(pte_t *kpte, unsigned long address,
+ new_prot = static_protections(req_prot, lpaddr, old_pfn, numpages,
+ psize, CPA_DETECT);
+
+- new_prot = verify_rwx(old_prot, new_prot, lpaddr, old_pfn, numpages);
++ new_prot = verify_rwx(old_prot, new_prot, lpaddr, old_pfn, numpages,
++ nx, rw);
+
+ /*
+ * If there is a conflict, split the large page.
+@@ -1046,6 +1083,7 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
+ pte_t *pbase = (pte_t *)page_address(base);
+ unsigned int i, level;
+ pgprot_t ref_prot;
++ bool nx, rw;
+ pte_t *tmp;
+
+ spin_lock(&pgd_lock);
+@@ -1053,7 +1091,7 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
+ * Check for races, another CPU might have split this page
+ * up for us already:
+ */
+- tmp = _lookup_address_cpa(cpa, address, &level);
++ tmp = _lookup_address_cpa(cpa, address, &level, &nx, &rw);
+ if (tmp != kpte) {
+ spin_unlock(&pgd_lock);
+ return 1;
+@@ -1594,10 +1632,11 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
+ int do_split, err;
+ unsigned int level;
+ pte_t *kpte, old_pte;
++ bool nx, rw;
+
+ address = __cpa_addr(cpa, cpa->curpage);
+ repeat:
+- kpte = _lookup_address_cpa(cpa, address, &level);
++ kpte = _lookup_address_cpa(cpa, address, &level, &nx, &rw);
+ if (!kpte)
+ return __cpa_process_fault(cpa, address, primary);
+
+@@ -1619,7 +1658,8 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)
+ new_prot = static_protections(new_prot, address, pfn, 1, 0,
+ CPA_PROTECT);
+
+- new_prot = verify_rwx(old_prot, new_prot, address, pfn, 1);
++ new_prot = verify_rwx(old_prot, new_prot, address, pfn, 1,
++ nx, rw);
+
+ new_prot = pgprot_clear_protnone_bits(new_prot);
+
+diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
+index df484885ccd4a..f415c2cf53582 100644
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -1585,36 +1585,41 @@ st: if (is_imm8(insn->off))
+ if (BPF_MODE(insn->code) == BPF_PROBE_MEM ||
+ BPF_MODE(insn->code) == BPF_PROBE_MEMSX) {
+ /* Conservatively check that src_reg + insn->off is a kernel address:
+- * src_reg + insn->off >= TASK_SIZE_MAX + PAGE_SIZE
+- * src_reg is used as scratch for src_reg += insn->off and restored
+- * after emit_ldx if necessary
++ * src_reg + insn->off > TASK_SIZE_MAX + PAGE_SIZE
++ * and
++ * src_reg + insn->off < VSYSCALL_ADDR
+ */
+
+- u64 limit = TASK_SIZE_MAX + PAGE_SIZE;
++ u64 limit = TASK_SIZE_MAX + PAGE_SIZE - VSYSCALL_ADDR;
+ u8 *end_of_jmp;
+
+- /* At end of these emitted checks, insn->off will have been added
+- * to src_reg, so no need to do relative load with insn->off offset
+- */
+- insn_off = 0;
++ /* movabsq r10, VSYSCALL_ADDR */
++ emit_mov_imm64(&prog, BPF_REG_AX, (long)VSYSCALL_ADDR >> 32,
++ (u32)(long)VSYSCALL_ADDR);
+
+- /* movabsq r11, limit */
+- EMIT2(add_1mod(0x48, AUX_REG), add_1reg(0xB8, AUX_REG));
+- EMIT((u32)limit, 4);
+- EMIT(limit >> 32, 4);
++ /* mov src_reg, r11 */
++ EMIT_mov(AUX_REG, src_reg);
+
+ if (insn->off) {
+- /* add src_reg, insn->off */
+- maybe_emit_1mod(&prog, src_reg, true);
+- EMIT2_off32(0x81, add_1reg(0xC0, src_reg), insn->off);
++ /* add r11, insn->off */
++ maybe_emit_1mod(&prog, AUX_REG, true);
++ EMIT2_off32(0x81, add_1reg(0xC0, AUX_REG), insn->off);
+ }
+
+- /* cmp src_reg, r11 */
+- maybe_emit_mod(&prog, src_reg, AUX_REG, true);
+- EMIT2(0x39, add_2reg(0xC0, src_reg, AUX_REG));
++ /* sub r11, r10 */
++ maybe_emit_mod(&prog, AUX_REG, BPF_REG_AX, true);
++ EMIT2(0x29, add_2reg(0xC0, AUX_REG, BPF_REG_AX));
++
++ /* movabsq r10, limit */
++ emit_mov_imm64(&prog, BPF_REG_AX, (long)limit >> 32,
++ (u32)(long)limit);
++
++ /* cmp r10, r11 */
++ maybe_emit_mod(&prog, AUX_REG, BPF_REG_AX, true);
++ EMIT2(0x39, add_2reg(0xC0, AUX_REG, BPF_REG_AX));
+
+- /* if unsigned '>=', goto load */
+- EMIT2(X86_JAE, 0);
++ /* if unsigned '>', goto load */
++ EMIT2(X86_JA, 0);
+ end_of_jmp = prog;
+
+ /* xor dst_reg, dst_reg */
+@@ -1640,18 +1645,6 @@ st: if (is_imm8(insn->off))
+ /* populate jmp_offset for JMP above */
+ start_of_ldx[-1] = prog - start_of_ldx;
+
+- if (insn->off && src_reg != dst_reg) {
+- /* sub src_reg, insn->off
+- * Restore src_reg after "add src_reg, insn->off" in prev
+- * if statement. But if src_reg == dst_reg, emit_ldx
+- * above already clobbered src_reg, so no need to restore.
+- * If add src_reg, insn->off was unnecessary, no need to
+- * restore either.
+- */
+- maybe_emit_1mod(&prog, src_reg, true);
+- EMIT2_off32(0x81, add_1reg(0xE8, src_reg), insn->off);
+- }
+-
+ if (!bpf_prog->aux->extable)
+ break;
+
+diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
+index 08aa0f25f12a0..8d1c82795ea1d 100644
+--- a/arch/x86/purgatory/Makefile
++++ b/arch/x86/purgatory/Makefile
+@@ -42,7 +42,8 @@ KCOV_INSTRUMENT := n
+ # make up the standalone purgatory.ro
+
+ PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel
+-PURGATORY_CFLAGS := -mcmodel=large -ffreestanding -fno-zero-initialized-in-bss -g0
++PURGATORY_CFLAGS := -mcmodel=small -ffreestanding -fno-zero-initialized-in-bss -g0
++PURGATORY_CFLAGS += -fpic -fvisibility=hidden
+ PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN) -DDISABLE_BRANCH_PROFILING
+ PURGATORY_CFLAGS += -fno-stack-protector
+
+diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
+index b029fb81ebeee..e7a44a7f617fb 100644
+--- a/arch/x86/tools/relocs.c
++++ b/arch/x86/tools/relocs.c
+@@ -746,6 +746,15 @@ static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel,
+ if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
+ continue;
+ }
++
++ /*
++ * Do not perform relocations in .notes sections; any
++ * values there are meant for pre-boot consumption (e.g.
++ * startup_xen).
++ */
++ if (sec_applies->shdr.sh_type == SHT_NOTE)
++ continue;
++
+ sh_symtab = sec_symtab->symtab;
+ sym_strtab = sec_symtab->link->strtab;
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
+diff --git a/block/blk-core.c b/block/blk-core.c
+index 99d684085719d..923b7d91e6dc5 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -976,10 +976,11 @@ void update_io_ticks(struct block_device *part, unsigned long now, bool end)
+ unsigned long stamp;
+ again:
+ stamp = READ_ONCE(part->bd_stamp);
+- if (unlikely(time_after(now, stamp))) {
+- if (likely(try_cmpxchg(&part->bd_stamp, &stamp, now)))
+- __part_stat_add(part, io_ticks, end ? now - stamp : 1);
+- }
++ if (unlikely(time_after(now, stamp)) &&
++ likely(try_cmpxchg(&part->bd_stamp, &stamp, now)) &&
++ (end || part_in_flight(part)))
++ __part_stat_add(part, io_ticks, now - stamp);
++
+ if (part->bd_partno) {
+ part = bdev_whole(part);
+ goto again;
+diff --git a/block/blk-merge.c b/block/blk-merge.c
+index 2d470cf2173e2..925c5eaac5815 100644
+--- a/block/blk-merge.c
++++ b/block/blk-merge.c
+@@ -779,6 +779,8 @@ static void blk_account_io_merge_request(struct request *req)
+ if (blk_do_io_stat(req)) {
+ part_stat_lock();
+ part_stat_inc(req->part, merges[op_stat_group(req_op(req))]);
++ part_stat_local_dec(req->part,
++ in_flight[op_is_write(req_op(req))]);
+ part_stat_unlock();
+ }
+ }
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index 25d2f3239eb65..f1d071810893e 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -998,6 +998,8 @@ static inline void blk_account_io_done(struct request *req, u64 now)
+ update_io_ticks(req->part, jiffies, true);
+ part_stat_inc(req->part, ios[sgrp]);
+ part_stat_add(req->part, nsecs[sgrp], now - req->start_time_ns);
++ part_stat_local_dec(req->part,
++ in_flight[op_is_write(req_op(req))]);
+ part_stat_unlock();
+ }
+ }
+@@ -1020,6 +1022,8 @@ static inline void blk_account_io_start(struct request *req)
+
+ part_stat_lock();
+ update_io_ticks(req->part, jiffies, false);
++ part_stat_local_inc(req->part,
++ in_flight[op_is_write(req_op(req))]);
+ part_stat_unlock();
+ }
+ }
+diff --git a/block/blk.h b/block/blk.h
+index 1ef920f72e0f8..1154e87a4022d 100644
+--- a/block/blk.h
++++ b/block/blk.h
+@@ -344,6 +344,7 @@ static inline bool blk_do_io_stat(struct request *rq)
+ }
+
+ void update_io_ticks(struct block_device *part, unsigned long now, bool end);
++unsigned int part_in_flight(struct block_device *part);
+
+ static inline void req_set_nomerge(struct request_queue *q, struct request *req)
+ {
+diff --git a/block/fops.c b/block/fops.c
+index 0cf8cf72cdfa1..799821040601a 100644
+--- a/block/fops.c
++++ b/block/fops.c
+@@ -387,7 +387,7 @@ static int blkdev_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
+
+ iomap->bdev = bdev;
+ iomap->offset = ALIGN_DOWN(offset, bdev_logical_block_size(bdev));
+- if (iomap->offset >= isize)
++ if (offset >= isize)
+ return -EIO;
+ iomap->type = IOMAP_MAPPED;
+ iomap->addr = iomap->offset;
+diff --git a/block/genhd.c b/block/genhd.c
+index d0471f469f7d0..2e4c2521584a1 100644
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -118,7 +118,7 @@ static void part_stat_read_all(struct block_device *part,
+ }
+ }
+
+-static unsigned int part_in_flight(struct block_device *part)
++unsigned int part_in_flight(struct block_device *part)
+ {
+ unsigned int inflight = 0;
+ int cpu;
+diff --git a/block/partitions/cmdline.c b/block/partitions/cmdline.c
+index c03bc105e5753..152c85df92b20 100644
+--- a/block/partitions/cmdline.c
++++ b/block/partitions/cmdline.c
+@@ -70,8 +70,8 @@ static int parse_subpart(struct cmdline_subpart **subpart, char *partdef)
+ }
+
+ if (*partdef == '(') {
+- int length;
+- char *next = strchr(++partdef, ')');
++ partdef++;
++ char *next = strsep(&partdef, ")");
+
+ if (!next) {
+ pr_warn("cmdline partition format is invalid.");
+@@ -79,11 +79,7 @@ static int parse_subpart(struct cmdline_subpart **subpart, char *partdef)
+ goto fail;
+ }
+
+- length = min_t(int, next - partdef,
+- sizeof(new_subpart->name) - 1);
+- strscpy(new_subpart->name, partdef, length);
+-
+- partdef = ++next;
++ strscpy(new_subpart->name, next, sizeof(new_subpart->name));
+ } else
+ new_subpart->name[0] = '\0';
+
+@@ -117,14 +113,12 @@ static void free_subpart(struct cmdline_parts *parts)
+ }
+ }
+
+-static int parse_parts(struct cmdline_parts **parts, const char *bdevdef)
++static int parse_parts(struct cmdline_parts **parts, char *bdevdef)
+ {
+ int ret = -EINVAL;
+ char *next;
+- int length;
+ struct cmdline_subpart **next_subpart;
+ struct cmdline_parts *newparts;
+- char buf[BDEVNAME_SIZE + 32 + 4];
+
+ *parts = NULL;
+
+@@ -132,28 +126,19 @@ static int parse_parts(struct cmdline_parts **parts, const char *bdevdef)
+ if (!newparts)
+ return -ENOMEM;
+
+- next = strchr(bdevdef, ':');
++ next = strsep(&bdevdef, ":");
+ if (!next) {
+ pr_warn("cmdline partition has no block device.");
+ goto fail;
+ }
+
+- length = min_t(int, next - bdevdef, sizeof(newparts->name) - 1);
+- strscpy(newparts->name, bdevdef, length);
++ strscpy(newparts->name, next, sizeof(newparts->name));
+ newparts->nr_subparts = 0;
+
+ next_subpart = &newparts->subpart;
+
+- while (next && *(++next)) {
+- bdevdef = next;
+- next = strchr(bdevdef, ',');
+-
+- length = (!next) ? (sizeof(buf) - 1) :
+- min_t(int, next - bdevdef, sizeof(buf) - 1);
+-
+- strscpy(buf, bdevdef, length);
+-
+- ret = parse_subpart(next_subpart, buf);
++ while ((next = strsep(&bdevdef, ","))) {
++ ret = parse_subpart(next_subpart, next);
+ if (ret)
+ goto fail;
+
+@@ -199,24 +184,17 @@ static int cmdline_parts_parse(struct cmdline_parts **parts,
+
+ *parts = NULL;
+
+- next = pbuf = buf = kstrdup(cmdline, GFP_KERNEL);
++ pbuf = buf = kstrdup(cmdline, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ next_parts = parts;
+
+- while (next && *pbuf) {
+- next = strchr(pbuf, ';');
+- if (next)
+- *next = '\0';
+-
+- ret = parse_parts(next_parts, pbuf);
++ while ((next = strsep(&pbuf, ";"))) {
++ ret = parse_parts(next_parts, next);
+ if (ret)
+ goto fail;
+
+- if (next)
+- pbuf = ++next;
+-
+ next_parts = &(*next_parts)->next_parts;
+ }
+
+@@ -250,7 +228,6 @@ static struct cmdline_parts *bdev_parts;
+ static int add_part(int slot, struct cmdline_subpart *subpart,
+ struct parsed_partitions *state)
+ {
+- int label_min;
+ struct partition_meta_info *info;
+ char tmp[sizeof(info->volname) + 4];
+
+@@ -262,9 +239,7 @@ static int add_part(int slot, struct cmdline_subpart *subpart,
+
+ info = &state->parts[slot].info;
+
+- label_min = min_t(int, sizeof(info->volname) - 1,
+- sizeof(subpart->name));
+- strscpy(info->volname, subpart->name, label_min);
++ strscpy(info->volname, subpart->name, sizeof(info->volname));
+
+ snprintf(tmp, sizeof(tmp), "(%s)", info->volname);
+ strlcat(state->pp_buf, tmp, PAGE_SIZE);
+diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
+index 59ec726b7c770..684767ab23e24 100644
+--- a/crypto/asymmetric_keys/Kconfig
++++ b/crypto/asymmetric_keys/Kconfig
+@@ -15,6 +15,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
+ select MPILIB
+ select CRYPTO_HASH_INFO
+ select CRYPTO_AKCIPHER
++ select CRYPTO_SIG
+ select CRYPTO_HASH
+ help
+ This option provides support for asymmetric public key type handling.
+@@ -85,5 +86,7 @@ config FIPS_SIGNATURE_SELFTEST
+ depends on ASYMMETRIC_KEY_TYPE
+ depends on PKCS7_MESSAGE_PARSER=X509_CERTIFICATE_PARSER
+ depends on X509_CERTIFICATE_PARSER
++ depends on CRYPTO_RSA
++ depends on CRYPTO_SHA256
+
+ endif # ASYMMETRIC_KEY_TYPE
+diff --git a/drivers/accessibility/speakup/main.c b/drivers/accessibility/speakup/main.c
+index 736c2eb8c0f37..f677ad2177c2f 100644
+--- a/drivers/accessibility/speakup/main.c
++++ b/drivers/accessibility/speakup/main.c
+@@ -574,7 +574,7 @@ static u_long get_word(struct vc_data *vc)
+ }
+ attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr);
+ buf[cnt++] = attr_ch;
+- while (tmpx < vc->vc_cols - 1 && cnt < sizeof(buf) - 1) {
++ while (tmpx < vc->vc_cols - 1 && cnt < ARRAY_SIZE(buf) - 1) {
+ tmp_pos += 2;
+ tmpx++;
+ ch = get_char(vc, (u_short *)tmp_pos, &temp);
+diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
+index 04e273167e92a..8e01792228d1e 100644
+--- a/drivers/acpi/acpi_lpss.c
++++ b/drivers/acpi/acpi_lpss.c
+@@ -325,6 +325,7 @@ static const struct lpss_device_desc bsw_i2c_dev_desc = {
+
+ static const struct property_entry bsw_spi_properties[] = {
+ PROPERTY_ENTRY_U32("intel,spi-pxa2xx-type", LPSS_BSW_SSP),
++ PROPERTY_ENTRY_U32("num-cs", 2),
+ { }
+ };
+
+diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
+index 30f3fc13c29d1..8d18af396de92 100644
+--- a/drivers/acpi/acpica/Makefile
++++ b/drivers/acpi/acpica/Makefile
+@@ -5,6 +5,7 @@
+
+ ccflags-y := -D_LINUX -DBUILDING_ACPICA
+ ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT
++CFLAGS_tbfind.o += $(call cc-disable-warning, stringop-truncation)
+
+ # use acpi.o to put all files here into acpi.o modparam namespace
+ obj-y += acpi.o
+diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
+index 569bd15f211be..3f84d8ed9d299 100644
+--- a/drivers/acpi/bus.c
++++ b/drivers/acpi/bus.c
+@@ -316,9 +316,14 @@ static void acpi_bus_osc_negotiate_platform_control(void)
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PAD_SUPPORT;
+ if (IS_ENABLED(CONFIG_ACPI_PROCESSOR))
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PPC_OST_SUPPORT;
++ if (IS_ENABLED(CONFIG_ACPI_THERMAL))
++ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_FAST_THERMAL_SAMPLING_SUPPORT;
+
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_HOTPLUG_OST_SUPPORT;
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT;
++ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_OVER_16_PSTATES_SUPPORT;
++ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_GED_SUPPORT;
++ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_IRQ_RESOURCE_SOURCE_SUPPORT;
+ if (IS_ENABLED(CONFIG_ACPI_PRMT))
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT;
+ if (IS_ENABLED(CONFIG_ACPI_FFH))
+diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c
+index 0214518fc582f..3ca22db3ed5db 100644
+--- a/drivers/acpi/numa/srat.c
++++ b/drivers/acpi/numa/srat.c
+@@ -206,6 +206,11 @@ int __init srat_disabled(void)
+ return acpi_numa < 0;
+ }
+
++__weak int __init numa_fill_memblks(u64 start, u64 end)
++{
++ return NUMA_NO_MEMBLK;
++}
++
+ #if defined(CONFIG_X86) || defined(CONFIG_ARM64) || defined(CONFIG_LOONGARCH)
+ /*
+ * Callback for SLIT parsing. pxm_to_node() returns NUMA_NO_NODE for
+diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
+index 36755f263e8ec..3584f389b92ce 100644
+--- a/drivers/block/null_blk/main.c
++++ b/drivers/block/null_blk/main.c
+@@ -2372,6 +2372,8 @@ static void __exit null_exit(void)
+
+ if (g_queue_mode == NULL_Q_MQ && shared_tags)
+ blk_mq_free_tag_set(&tag_set);
++
++ mutex_destroy(&lock);
+ }
+
+ module_init(null_init);
+diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
+index 9658b33c824a7..18f34998a1204 100644
+--- a/drivers/bluetooth/btmrvl_main.c
++++ b/drivers/bluetooth/btmrvl_main.c
+@@ -121,13 +121,6 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
+ ((event->data[2] == MODULE_BROUGHT_UP) ||
+ (event->data[2] == MODULE_ALREADY_UP)) ?
+ "Bring-up succeed" : "Bring-up failed");
+-
+- if (event->length > 3 && event->data[3])
+- priv->btmrvl_dev.dev_type = HCI_AMP;
+- else
+- priv->btmrvl_dev.dev_type = HCI_PRIMARY;
+-
+- BT_DBG("dev_type: %d", priv->btmrvl_dev.dev_type);
+ } else if (priv->btmrvl_dev.sendcmdflag &&
+ event->data[1] == MODULE_SHUTDOWN_REQ) {
+ BT_DBG("EVENT:%s", (event->data[2]) ?
+@@ -686,8 +679,6 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)
+ hdev->wakeup = btmrvl_wakeup;
+ SET_HCIDEV_DEV(hdev, &card->func->dev);
+
+- hdev->dev_type = priv->btmrvl_dev.dev_type;
+-
+ ret = hci_register_dev(hdev);
+ if (ret < 0) {
+ BT_ERR("Can not register HCI device");
+diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
+index 638074992c829..35fb26cbf2294 100644
+--- a/drivers/bluetooth/btqca.c
++++ b/drivers/bluetooth/btqca.c
+@@ -148,8 +148,10 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
+ }
+
+ build_label = kstrndup(&edl->data[1], build_lbl_len, GFP_KERNEL);
+- if (!build_label)
++ if (!build_label) {
++ err = -ENOMEM;
+ goto out;
++ }
+
+ hci_set_fw_info(hdev, "%s", build_label);
+
+diff --git a/drivers/bluetooth/btrsi.c b/drivers/bluetooth/btrsi.c
+index 634cf8f5ed2db..0c91d7635ac39 100644
+--- a/drivers/bluetooth/btrsi.c
++++ b/drivers/bluetooth/btrsi.c
+@@ -134,7 +134,6 @@ static int rsi_hci_attach(void *priv, struct rsi_proto_ops *ops)
+ hdev->bus = HCI_USB;
+
+ hci_set_drvdata(hdev, h_adapter);
+- hdev->dev_type = HCI_PRIMARY;
+ hdev->open = rsi_hci_open;
+ hdev->close = rsi_hci_close;
+ hdev->flush = rsi_hci_flush;
+diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
+index f19d31ee37ea8..fdcfe9c50313e 100644
+--- a/drivers/bluetooth/btsdio.c
++++ b/drivers/bluetooth/btsdio.c
+@@ -32,9 +32,6 @@ static const struct sdio_device_id btsdio_table[] = {
+ /* Generic Bluetooth Type-B SDIO device */
+ { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_B) },
+
+- /* Generic Bluetooth AMP controller */
+- { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_AMP) },
+-
+ { } /* Terminating entry */
+ };
+
+@@ -319,11 +316,6 @@ static int btsdio_probe(struct sdio_func *func,
+ hdev->bus = HCI_SDIO;
+ hci_set_drvdata(hdev, data);
+
+- if (id->class == SDIO_CLASS_BT_AMP)
+- hdev->dev_type = HCI_AMP;
+- else
+- hdev->dev_type = HCI_PRIMARY;
+-
+ data->hdev = hdev;
+
+ SET_HCIDEV_DEV(hdev, &func->dev);
+diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
+index effa546296486..a1b82abe06c5f 100644
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -4314,11 +4314,6 @@ static int btusb_probe(struct usb_interface *intf,
+ hdev->bus = HCI_USB;
+ hci_set_drvdata(hdev, data);
+
+- if (id->driver_info & BTUSB_AMP)
+- hdev->dev_type = HCI_AMP;
+- else
+- hdev->dev_type = HCI_PRIMARY;
+-
+ data->hdev = hdev;
+
+ SET_HCIDEV_DEV(hdev, &intf->dev);
+diff --git a/drivers/bluetooth/hci_bcm4377.c b/drivers/bluetooth/hci_bcm4377.c
+index 9a7243d5db71f..0c2f15235b4cd 100644
+--- a/drivers/bluetooth/hci_bcm4377.c
++++ b/drivers/bluetooth/hci_bcm4377.c
+@@ -2361,7 +2361,6 @@ static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+ bcm4377->hdev = hdev;
+
+ hdev->bus = HCI_PCI;
+- hdev->dev_type = HCI_PRIMARY;
+ hdev->open = bcm4377_hci_open;
+ hdev->close = bcm4377_hci_close;
+ hdev->send = bcm4377_hci_send_frame;
+diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
+index a26367e9fb197..17a2f158a0dfa 100644
+--- a/drivers/bluetooth/hci_ldisc.c
++++ b/drivers/bluetooth/hci_ldisc.c
+@@ -667,11 +667,6 @@ static int hci_uart_register_dev(struct hci_uart *hu)
+ if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags))
+ set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
+
+- if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags))
+- hdev->dev_type = HCI_AMP;
+- else
+- hdev->dev_type = HCI_PRIMARY;
+-
+ /* Only call open() for the protocol after hdev is fully initialized as
+ * open() (or a timer/workqueue it starts) may attempt to reference it.
+ */
+@@ -722,7 +717,6 @@ static int hci_uart_set_flags(struct hci_uart *hu, unsigned long flags)
+ {
+ unsigned long valid_flags = BIT(HCI_UART_RAW_DEVICE) |
+ BIT(HCI_UART_RESET_ON_INIT) |
+- BIT(HCI_UART_CREATE_AMP) |
+ BIT(HCI_UART_INIT_PENDING) |
+ BIT(HCI_UART_EXT_CONFIG) |
+ BIT(HCI_UART_VND_DETECT);
+diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c
+index 214fff876eae5..0eaec878fa1d8 100644
+--- a/drivers/bluetooth/hci_serdev.c
++++ b/drivers/bluetooth/hci_serdev.c
+@@ -366,11 +366,6 @@ int hci_uart_register_device_priv(struct hci_uart *hu,
+ if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags))
+ set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);
+
+- if (test_bit(HCI_UART_CREATE_AMP, &hu->hdev_flags))
+- hdev->dev_type = HCI_AMP;
+- else
+- hdev->dev_type = HCI_PRIMARY;
+-
+ if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
+ return 0;
+
+diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
+index 68c8c7e95d64d..00bf7ae82c5b7 100644
+--- a/drivers/bluetooth/hci_uart.h
++++ b/drivers/bluetooth/hci_uart.h
+@@ -37,7 +37,6 @@
+
+ #define HCI_UART_RAW_DEVICE 0
+ #define HCI_UART_RESET_ON_INIT 1
+-#define HCI_UART_CREATE_AMP 2
+ #define HCI_UART_INIT_PENDING 3
+ #define HCI_UART_EXT_CONFIG 4
+ #define HCI_UART_VND_DETECT 5
+diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
+index 572d68d52965f..28750a40f0ed5 100644
+--- a/drivers/bluetooth/hci_vhci.c
++++ b/drivers/bluetooth/hci_vhci.c
+@@ -384,17 +384,10 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
+ {
+ struct hci_dev *hdev;
+ struct sk_buff *skb;
+- __u8 dev_type;
+
+ if (data->hdev)
+ return -EBADFD;
+
+- /* bits 0-1 are dev_type (Primary or AMP) */
+- dev_type = opcode & 0x03;
+-
+- if (dev_type != HCI_PRIMARY && dev_type != HCI_AMP)
+- return -EINVAL;
+-
+ /* bits 2-5 are reserved (must be zero) */
+ if (opcode & 0x3c)
+ return -EINVAL;
+@@ -412,7 +405,6 @@ static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
+ data->hdev = hdev;
+
+ hdev->bus = HCI_VIRTUAL;
+- hdev->dev_type = dev_type;
+ hci_set_drvdata(hdev, data);
+
+ hdev->open = vhci_open_dev;
+@@ -634,7 +626,7 @@ static void vhci_open_timeout(struct work_struct *work)
+ struct vhci_data *data = container_of(work, struct vhci_data,
+ open_timeout.work);
+
+- vhci_create_device(data, amp ? HCI_AMP : HCI_PRIMARY);
++ vhci_create_device(data, 0x00);
+ }
+
+ static int vhci_open(struct inode *inode, struct file *file)
+diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c
+index 2ac70b560c46d..18208e152a367 100644
+--- a/drivers/bluetooth/virtio_bt.c
++++ b/drivers/bluetooth/virtio_bt.c
+@@ -274,7 +274,6 @@ static int virtbt_probe(struct virtio_device *vdev)
+
+ switch (type) {
+ case VIRTIO_BT_CONFIG_TYPE_PRIMARY:
+- case VIRTIO_BT_CONFIG_TYPE_AMP:
+ break;
+ default:
+ return -EINVAL;
+@@ -303,7 +302,6 @@ static int virtbt_probe(struct virtio_device *vdev)
+ vbt->hdev = hdev;
+
+ hdev->bus = HCI_VIRTIO;
+- hdev->dev_type = type;
+ hci_set_drvdata(hdev, vbt);
+
+ hdev->open = virtbt_open;
+diff --git a/drivers/char/hw_random/stm32-rng.c b/drivers/char/hw_random/stm32-rng.c
+index 379bc245c5202..0e903d6e22e30 100644
+--- a/drivers/char/hw_random/stm32-rng.c
++++ b/drivers/char/hw_random/stm32-rng.c
+@@ -220,7 +220,8 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+ if (err && i > RNG_NB_RECOVER_TRIES) {
+ dev_err((struct device *)priv->rng.priv,
+ "Couldn't recover from seed error\n");
+- return -ENOTRECOVERABLE;
++ retval = -ENOTRECOVERABLE;
++ goto exit_rpm;
+ }
+
+ continue;
+@@ -238,7 +239,8 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+ if (err && i > RNG_NB_RECOVER_TRIES) {
+ dev_err((struct device *)priv->rng.priv,
+ "Couldn't recover from seed error");
+- return -ENOTRECOVERABLE;
++ retval = -ENOTRECOVERABLE;
++ goto exit_rpm;
+ }
+
+ continue;
+@@ -250,6 +252,7 @@ static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+ max -= sizeof(u32);
+ }
+
++exit_rpm:
+ pm_runtime_mark_last_busy((struct device *) priv->rng.priv);
+ pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv);
+
+@@ -353,13 +356,15 @@ static int stm32_rng_init(struct hwrng *rng)
+ err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_SR, reg,
+ reg & RNG_SR_DRDY,
+ 10, 100000);
+- if (err | (reg & ~RNG_SR_DRDY)) {
++ if (err || (reg & ~RNG_SR_DRDY)) {
+ clk_disable_unprepare(priv->clk);
+ dev_err((struct device *)priv->rng.priv,
+ "%s: timeout:%x SR: %x!\n", __func__, err, reg);
+ return -EINVAL;
+ }
+
++ clk_disable_unprepare(priv->clk);
++
+ return 0;
+ }
+
+@@ -384,6 +389,11 @@ static int __maybe_unused stm32_rng_runtime_suspend(struct device *dev)
+ static int __maybe_unused stm32_rng_suspend(struct device *dev)
+ {
+ struct stm32_rng_private *priv = dev_get_drvdata(dev);
++ int err;
++
++ err = clk_prepare_enable(priv->clk);
++ if (err)
++ return err;
+
+ if (priv->data->has_cond_reset) {
+ priv->pm_conf.nscr = readl_relaxed(priv->base + RNG_NSCR);
+@@ -465,6 +475,8 @@ static int __maybe_unused stm32_rng_resume(struct device *dev)
+ writel_relaxed(reg, priv->base + RNG_CR);
+ }
+
++ clk_disable_unprepare(priv->clk);
++
+ return 0;
+ }
+
+diff --git a/drivers/clk/clk-renesas-pcie.c b/drivers/clk/clk-renesas-pcie.c
+index 53e21ac302e6d..4c3a5e4eb77ac 100644
+--- a/drivers/clk/clk-renesas-pcie.c
++++ b/drivers/clk/clk-renesas-pcie.c
+@@ -25,10 +25,12 @@
+ #define RS9_REG_SS_AMP_0V7 0x1
+ #define RS9_REG_SS_AMP_0V8 0x2
+ #define RS9_REG_SS_AMP_0V9 0x3
++#define RS9_REG_SS_AMP_DEFAULT RS9_REG_SS_AMP_0V8
+ #define RS9_REG_SS_AMP_MASK 0x3
+ #define RS9_REG_SS_SSC_100 0
+ #define RS9_REG_SS_SSC_M025 (1 << 3)
+ #define RS9_REG_SS_SSC_M050 (3 << 3)
++#define RS9_REG_SS_SSC_DEFAULT RS9_REG_SS_SSC_100
+ #define RS9_REG_SS_SSC_MASK (3 << 3)
+ #define RS9_REG_SS_SSC_LOCK BIT(5)
+ #define RS9_REG_SR 0x2
+@@ -205,8 +207,8 @@ static int rs9_get_common_config(struct rs9_driver_data *rs9)
+ int ret;
+
+ /* Set defaults */
+- rs9->pll_amplitude = RS9_REG_SS_AMP_0V7;
+- rs9->pll_ssc = RS9_REG_SS_SSC_100;
++ rs9->pll_amplitude = RS9_REG_SS_AMP_DEFAULT;
++ rs9->pll_ssc = RS9_REG_SS_SSC_DEFAULT;
+
+ /* Output clock amplitude */
+ ret = of_property_read_u32(np, "renesas,out-amplitude-microvolt",
+@@ -247,13 +249,13 @@ static void rs9_update_config(struct rs9_driver_data *rs9)
+ int i;
+
+ /* If amplitude is non-default, update it. */
+- if (rs9->pll_amplitude != RS9_REG_SS_AMP_0V7) {
++ if (rs9->pll_amplitude != RS9_REG_SS_AMP_DEFAULT) {
+ regmap_update_bits(rs9->regmap, RS9_REG_SS, RS9_REG_SS_AMP_MASK,
+ rs9->pll_amplitude);
+ }
+
+ /* If SSC is non-default, update it. */
+- if (rs9->pll_ssc != RS9_REG_SS_SSC_100) {
++ if (rs9->pll_ssc != RS9_REG_SS_SSC_DEFAULT) {
+ regmap_update_bits(rs9->regmap, RS9_REG_SS, RS9_REG_SS_SSC_MASK,
+ rs9->pll_ssc);
+ }
+diff --git a/drivers/clk/mediatek/clk-mt8365-mm.c b/drivers/clk/mediatek/clk-mt8365-mm.c
+index 01a2ef8f594ef..3f62ec7507336 100644
+--- a/drivers/clk/mediatek/clk-mt8365-mm.c
++++ b/drivers/clk/mediatek/clk-mt8365-mm.c
+@@ -53,7 +53,7 @@ static const struct mtk_gate mm_clks[] = {
+ GATE_MM0(CLK_MM_MM_DSI0, "mm_dsi0", "mm_sel", 17),
+ GATE_MM0(CLK_MM_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 18),
+ GATE_MM0(CLK_MM_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 19),
+- GATE_MM0(CLK_MM_DPI0_DPI0, "mm_dpi0_dpi0", "vpll_dpix", 20),
++ GATE_MM0(CLK_MM_DPI0_DPI0, "mm_dpi0_dpi0", "dpi0_sel", 20),
+ GATE_MM0(CLK_MM_MM_FAKE, "mm_fake", "mm_sel", 21),
+ GATE_MM0(CLK_MM_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 22),
+ GATE_MM0(CLK_MM_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 23),
+diff --git a/drivers/clk/mediatek/clk-pllfh.c b/drivers/clk/mediatek/clk-pllfh.c
+index 3a2b3f90be25d..094ec8a26d668 100644
+--- a/drivers/clk/mediatek/clk-pllfh.c
++++ b/drivers/clk/mediatek/clk-pllfh.c
+@@ -68,7 +68,7 @@ void fhctl_parse_dt(const u8 *compatible_node, struct mtk_pllfh_data *pllfhs,
+
+ node = of_find_compatible_node(NULL, NULL, compatible_node);
+ if (!node) {
+- pr_err("cannot find \"%s\"\n", compatible_node);
++ pr_warn("cannot find \"%s\"\n", compatible_node);
+ return;
+ }
+
+diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
+index 2a9da0939377a..be35803c7a4bf 100644
+--- a/drivers/clk/qcom/Kconfig
++++ b/drivers/clk/qcom/Kconfig
+@@ -439,6 +439,7 @@ config SC_CAMCC_7280
+
+ config SC_CAMCC_8280XP
+ tristate "SC8280XP Camera Clock Controller"
++ depends on ARM64 || COMPILE_TEST
+ select SC_GCC_8280XP
+ help
+ Support for the camera clock controller on Qualcomm Technologies, Inc
+@@ -1069,6 +1070,7 @@ config SM_GPUCC_8550
+
+ config SM_GPUCC_8650
+ tristate "SM8650 Graphics Clock Controller"
++ depends on ARM64 || COMPILE_TEST
+ select SM_GCC_8650
+ help
+ Support for the graphics clock controller on SM8650 devices.
+diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c
+index 678b805f13d45..5e3da5558f4e0 100644
+--- a/drivers/clk/qcom/apss-ipq-pll.c
++++ b/drivers/clk/qcom/apss-ipq-pll.c
+@@ -73,8 +73,9 @@ static struct clk_alpha_pll ipq_pll_stromer_plus = {
+ },
+ };
+
++/* 1.008 GHz configuration */
+ static const struct alpha_pll_config ipq5018_pll_config = {
+- .l = 0x32,
++ .l = 0x2a,
+ .config_ctl_val = 0x4001075b,
+ .config_ctl_hi_val = 0x304,
+ .main_output_mask = BIT(0),
+diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
+index 05898d2a8b22c..58ae732959803 100644
+--- a/drivers/clk/qcom/clk-alpha-pll.c
++++ b/drivers/clk/qcom/clk-alpha-pll.c
+@@ -212,7 +212,6 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
+ [PLL_OFF_USER_CTL] = 0x18,
+ [PLL_OFF_USER_CTL_U] = 0x1c,
+ [PLL_OFF_CONFIG_CTL] = 0x20,
+- [PLL_OFF_CONFIG_CTL_U] = 0xff,
+ [PLL_OFF_TEST_CTL] = 0x30,
+ [PLL_OFF_TEST_CTL_U] = 0x34,
+ [PLL_OFF_STATUS] = 0x28,
+diff --git a/drivers/clk/qcom/dispcc-sm6350.c b/drivers/clk/qcom/dispcc-sm6350.c
+index ea6f54ed846ec..441f042f5ea45 100644
+--- a/drivers/clk/qcom/dispcc-sm6350.c
++++ b/drivers/clk/qcom/dispcc-sm6350.c
+@@ -221,26 +221,17 @@ static struct clk_rcg2 disp_cc_mdss_dp_crypto_clk_src = {
+ },
+ };
+
+-static const struct freq_tbl ftbl_disp_cc_mdss_dp_link_clk_src[] = {
+- F(162000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0),
+- F(270000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0),
+- F(540000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0),
+- F(810000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0),
+- { }
+-};
+-
+ static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = {
+ .cmd_rcgr = 0x10f8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+- .freq_tbl = ftbl_disp_cc_mdss_dp_link_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_dp_link_clk_src",
+ .parent_data = disp_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+diff --git a/drivers/clk/qcom/dispcc-sm8450.c b/drivers/clk/qcom/dispcc-sm8450.c
+index 2c4aecd75186b..239cc726c7e29 100644
+--- a/drivers/clk/qcom/dispcc-sm8450.c
++++ b/drivers/clk/qcom/dispcc-sm8450.c
+@@ -309,26 +309,17 @@ static struct clk_rcg2 disp_cc_mdss_dptx0_aux_clk_src = {
+ },
+ };
+
+-static const struct freq_tbl ftbl_disp_cc_mdss_dptx0_link_clk_src[] = {
+- F(162000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0),
+- F(270000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0),
+- F(540000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0),
+- F(810000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0),
+- { }
+-};
+-
+ static struct clk_rcg2 disp_cc_mdss_dptx0_link_clk_src = {
+ .cmd_rcgr = 0x819c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_dptx0_link_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+@@ -382,13 +373,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx1_link_clk_src = {
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_dptx1_link_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+@@ -442,13 +432,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx2_link_clk_src = {
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_dptx2_link_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+@@ -502,13 +491,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx3_link_clk_src = {
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_dptx3_link_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+diff --git a/drivers/clk/qcom/dispcc-sm8550.c b/drivers/clk/qcom/dispcc-sm8550.c
+index f96d8b81fd9ad..c9b8c2eb5c64a 100644
+--- a/drivers/clk/qcom/dispcc-sm8550.c
++++ b/drivers/clk/qcom/dispcc-sm8550.c
+@@ -345,26 +345,17 @@ static struct clk_rcg2 disp_cc_mdss_dptx0_aux_clk_src = {
+ },
+ };
+
+-static const struct freq_tbl ftbl_disp_cc_mdss_dptx0_link_clk_src[] = {
+- F(162000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0),
+- F(270000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0),
+- F(540000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0),
+- F(810000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0),
+- { }
+-};
+-
+ static struct clk_rcg2 disp_cc_mdss_dptx0_link_clk_src = {
+ .cmd_rcgr = 0x8170,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_7,
+- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_dptx0_link_clk_src",
+ .parent_data = disp_cc_parent_data_7,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_7),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+@@ -418,13 +409,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx1_link_clk_src = {
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_dptx1_link_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+@@ -478,13 +468,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx2_link_clk_src = {
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_dptx2_link_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+@@ -538,13 +527,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx3_link_clk_src = {
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_dptx3_link_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+diff --git a/drivers/clk/qcom/dispcc-sm8650.c b/drivers/clk/qcom/dispcc-sm8650.c
+index f3b1d9d16baea..c9b139faf1a8f 100644
+--- a/drivers/clk/qcom/dispcc-sm8650.c
++++ b/drivers/clk/qcom/dispcc-sm8650.c
+@@ -343,26 +343,17 @@ static struct clk_rcg2 disp_cc_mdss_dptx0_aux_clk_src = {
+ },
+ };
+
+-static const struct freq_tbl ftbl_disp_cc_mdss_dptx0_link_clk_src[] = {
+- F(162000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0),
+- F(270000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0),
+- F(540000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0),
+- F(810000, P_DP0_PHY_PLL_LINK_CLK, 1, 0, 0),
+- { }
+-};
+-
+ static struct clk_rcg2 disp_cc_mdss_dptx0_link_clk_src = {
+ .cmd_rcgr = 0x8170,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_7,
+- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp_cc_mdss_dptx0_link_clk_src",
+ .parent_data = disp_cc_parent_data_7,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_7),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+@@ -416,13 +407,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx1_link_clk_src = {
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp_cc_mdss_dptx1_link_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+@@ -476,13 +466,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx2_link_clk_src = {
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp_cc_mdss_dptx2_link_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+@@ -536,13 +525,12 @@ static struct clk_rcg2 disp_cc_mdss_dptx3_link_clk_src = {
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+- .freq_tbl = ftbl_disp_cc_mdss_dptx0_link_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp_cc_mdss_dptx3_link_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+- .ops = &clk_rcg2_ops,
++ .ops = &clk_byte2_ops,
+ },
+ };
+
+diff --git a/drivers/clk/qcom/mmcc-msm8998.c b/drivers/clk/qcom/mmcc-msm8998.c
+index 1180e48c687ac..275fb3b71ede4 100644
+--- a/drivers/clk/qcom/mmcc-msm8998.c
++++ b/drivers/clk/qcom/mmcc-msm8998.c
+@@ -2535,6 +2535,8 @@ static struct clk_branch vmem_ahb_clk = {
+
+ static struct gdsc video_top_gdsc = {
+ .gdscr = 0x1024,
++ .cxcs = (unsigned int []){ 0x1028, 0x1034, 0x1038 },
++ .cxc_count = 3,
+ .pd = {
+ .name = "video_top",
+ },
+@@ -2543,20 +2545,26 @@ static struct gdsc video_top_gdsc = {
+
+ static struct gdsc video_subcore0_gdsc = {
+ .gdscr = 0x1040,
++ .cxcs = (unsigned int []){ 0x1048 },
++ .cxc_count = 1,
+ .pd = {
+ .name = "video_subcore0",
+ },
+ .parent = &video_top_gdsc.pd,
+ .pwrsts = PWRSTS_OFF_ON,
++ .flags = HW_CTRL,
+ };
+
+ static struct gdsc video_subcore1_gdsc = {
+ .gdscr = 0x1044,
++ .cxcs = (unsigned int []){ 0x104c },
++ .cxc_count = 1,
+ .pd = {
+ .name = "video_subcore1",
+ },
+ .parent = &video_top_gdsc.pd,
+ .pwrsts = PWRSTS_OFF_ON,
++ .flags = HW_CTRL,
+ };
+
+ static struct gdsc mdss_gdsc = {
+diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
+index 4c2872f45387f..ff3f85e906fe1 100644
+--- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c
++++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
+@@ -139,7 +139,7 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = {
+ DEF_MOD("avb3", 214, R8A779A0_CLK_S3D2),
+ DEF_MOD("avb4", 215, R8A779A0_CLK_S3D2),
+ DEF_MOD("avb5", 216, R8A779A0_CLK_S3D2),
+- DEF_MOD("canfd0", 328, R8A779A0_CLK_CANFD),
++ DEF_MOD("canfd0", 328, R8A779A0_CLK_S3D2),
+ DEF_MOD("csi40", 331, R8A779A0_CLK_CSI0),
+ DEF_MOD("csi41", 400, R8A779A0_CLK_CSI0),
+ DEF_MOD("csi42", 401, R8A779A0_CLK_CSI0),
+diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c
+index 075ade0925d45..9ad7ceb3ab1ba 100644
+--- a/drivers/clk/renesas/r9a07g043-cpg.c
++++ b/drivers/clk/renesas/r9a07g043-cpg.c
+@@ -265,6 +265,10 @@ static struct rzg2l_mod_clk r9a07g043_mod_clks[] = {
+ 0x5a8, 1),
+ DEF_MOD("tsu_pclk", R9A07G043_TSU_PCLK, R9A07G043_CLK_TSU,
+ 0x5ac, 0),
++#ifdef CONFIG_RISCV
++ DEF_MOD("nceplic_aclk", R9A07G043_NCEPLIC_ACLK, R9A07G043_CLK_P1,
++ 0x608, 0),
++#endif
+ };
+
+ static struct rzg2l_reset r9a07g043_resets[] = {
+@@ -318,6 +322,10 @@ static struct rzg2l_reset r9a07g043_resets[] = {
+ DEF_RST(R9A07G043_ADC_PRESETN, 0x8a8, 0),
+ DEF_RST(R9A07G043_ADC_ADRST_N, 0x8a8, 1),
+ DEF_RST(R9A07G043_TSU_PRESETN, 0x8ac, 0),
++#ifdef CONFIG_RISCV
++ DEF_RST(R9A07G043_NCEPLIC_ARESETN, 0x908, 0),
++#endif
++
+ };
+
+ static const unsigned int r9a07g043_crit_mod_clks[] __initconst = {
+@@ -327,6 +335,7 @@ static const unsigned int r9a07g043_crit_mod_clks[] __initconst = {
+ #endif
+ #ifdef CONFIG_RISCV
+ MOD_CLK_BASE + R9A07G043_IAX45_CLK,
++ MOD_CLK_BASE + R9A07G043_NCEPLIC_ACLK,
+ #endif
+ MOD_CLK_BASE + R9A07G043_DMAC_ACLK,
+ };
+diff --git a/drivers/clk/samsung/clk-exynosautov9.c b/drivers/clk/samsung/clk-exynosautov9.c
+index e9c06eb93e666..f04bacacab2cb 100644
+--- a/drivers/clk/samsung/clk-exynosautov9.c
++++ b/drivers/clk/samsung/clk-exynosautov9.c
+@@ -352,13 +352,13 @@ static const struct samsung_pll_clock top_pll_clks[] __initconst = {
+ /* CMU_TOP_PURECLKCOMP */
+ PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared0_pll", "oscclk",
+ PLL_LOCKTIME_PLL_SHARED0, PLL_CON3_PLL_SHARED0, NULL),
+- PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared1_pll", "oscclk",
++ PLL(pll_0822x, FOUT_SHARED1_PLL, "fout_shared1_pll", "oscclk",
+ PLL_LOCKTIME_PLL_SHARED1, PLL_CON3_PLL_SHARED1, NULL),
+- PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared2_pll", "oscclk",
++ PLL(pll_0822x, FOUT_SHARED2_PLL, "fout_shared2_pll", "oscclk",
+ PLL_LOCKTIME_PLL_SHARED2, PLL_CON3_PLL_SHARED2, NULL),
+- PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared3_pll", "oscclk",
++ PLL(pll_0822x, FOUT_SHARED3_PLL, "fout_shared3_pll", "oscclk",
+ PLL_LOCKTIME_PLL_SHARED3, PLL_CON3_PLL_SHARED3, NULL),
+- PLL(pll_0822x, FOUT_SHARED0_PLL, "fout_shared4_pll", "oscclk",
++ PLL(pll_0822x, FOUT_SHARED4_PLL, "fout_shared4_pll", "oscclk",
+ PLL_LOCKTIME_PLL_SHARED4, PLL_CON3_PLL_SHARED4, NULL),
+ };
+
+diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c
+index 1a1857b0a6f48..ea8438550b490 100644
+--- a/drivers/cpufreq/brcmstb-avs-cpufreq.c
++++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c
+@@ -481,9 +481,12 @@ static bool brcm_avs_is_firmware_loaded(struct private_data *priv)
+ static unsigned int brcm_avs_cpufreq_get(unsigned int cpu)
+ {
+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
++ struct private_data *priv;
++
+ if (!policy)
+ return 0;
+- struct private_data *priv = policy->driver_data;
++
++ priv = policy->driver_data;
+
+ cpufreq_cpu_put(policy);
+
+diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
+index 64420d9cfd1ed..15f1d41920a33 100644
+--- a/drivers/cpufreq/cppc_cpufreq.c
++++ b/drivers/cpufreq/cppc_cpufreq.c
+@@ -741,10 +741,15 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpu)
+ {
+ struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0};
+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+- struct cppc_cpudata *cpu_data = policy->driver_data;
++ struct cppc_cpudata *cpu_data;
+ u64 delivered_perf;
+ int ret;
+
++ if (!policy)
++ return -ENODEV;
++
++ cpu_data = policy->driver_data;
++
+ cpufreq_cpu_put(policy);
+
+ ret = cppc_get_perf_ctrs(cpu, &fb_ctrs_t0);
+@@ -822,10 +827,15 @@ static struct cpufreq_driver cppc_cpufreq_driver = {
+ static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu)
+ {
+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+- struct cppc_cpudata *cpu_data = policy->driver_data;
++ struct cppc_cpudata *cpu_data;
+ u64 desired_perf;
+ int ret;
+
++ if (!policy)
++ return -ENODEV;
++
++ cpu_data = policy->driver_data;
++
+ cpufreq_cpu_put(policy);
+
+ ret = cppc_get_desired_perf(cpu, &desired_perf);
+diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
+index 3c2c955fbbbd6..86f1bc7754ea6 100644
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -1670,10 +1670,13 @@ static void __cpufreq_offline(unsigned int cpu, struct cpufreq_policy *policy)
+ */
+ if (cpufreq_driver->offline) {
+ cpufreq_driver->offline(policy);
+- } else if (cpufreq_driver->exit) {
+- cpufreq_driver->exit(policy);
+- policy->freq_table = NULL;
++ return;
+ }
++
++ if (cpufreq_driver->exit)
++ cpufreq_driver->exit(policy);
++
++ policy->freq_table = NULL;
+ }
+
+ static int cpufreq_offline(unsigned int cpu)
+@@ -1731,7 +1734,7 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
+ }
+
+ /* We did light-weight exit earlier, do full tear down now */
+- if (cpufreq_driver->offline)
++ if (cpufreq_driver->offline && cpufreq_driver->exit)
+ cpufreq_driver->exit(policy);
+
+ up_write(&policy->rwsem);
+diff --git a/drivers/crypto/bcm/spu2.c b/drivers/crypto/bcm/spu2.c
+index 07989bb8c220a..3fdc64b5a65e7 100644
+--- a/drivers/crypto/bcm/spu2.c
++++ b/drivers/crypto/bcm/spu2.c
+@@ -495,7 +495,7 @@ static void spu2_dump_omd(u8 *omd, u16 hash_key_len, u16 ciph_key_len,
+ if (hash_iv_len) {
+ packet_log(" Hash IV Length %u bytes\n", hash_iv_len);
+ packet_dump(" hash IV: ", ptr, hash_iv_len);
+- ptr += ciph_key_len;
++ ptr += hash_iv_len;
+ }
+
+ if (ciph_iv_len) {
+diff --git a/drivers/crypto/ccp/sp-platform.c b/drivers/crypto/ccp/sp-platform.c
+index 4733012377601..ff6ceb4feee04 100644
+--- a/drivers/crypto/ccp/sp-platform.c
++++ b/drivers/crypto/ccp/sp-platform.c
+@@ -39,44 +39,38 @@ static const struct sp_dev_vdata dev_vdata[] = {
+ },
+ };
+
+-#ifdef CONFIG_ACPI
+ static const struct acpi_device_id sp_acpi_match[] = {
+ { "AMDI0C00", (kernel_ulong_t)&dev_vdata[0] },
+ { },
+ };
+ MODULE_DEVICE_TABLE(acpi, sp_acpi_match);
+-#endif
+
+-#ifdef CONFIG_OF
+ static const struct of_device_id sp_of_match[] = {
+ { .compatible = "amd,ccp-seattle-v1a",
+ .data = (const void *)&dev_vdata[0] },
+ { },
+ };
+ MODULE_DEVICE_TABLE(of, sp_of_match);
+-#endif
+
+ static struct sp_dev_vdata *sp_get_of_version(struct platform_device *pdev)
+ {
+-#ifdef CONFIG_OF
+ const struct of_device_id *match;
+
+ match = of_match_node(sp_of_match, pdev->dev.of_node);
+ if (match && match->data)
+ return (struct sp_dev_vdata *)match->data;
+-#endif
++
+ return NULL;
+ }
+
+ static struct sp_dev_vdata *sp_get_acpi_version(struct platform_device *pdev)
+ {
+-#ifdef CONFIG_ACPI
+ const struct acpi_device_id *match;
+
+ match = acpi_match_device(sp_acpi_match, &pdev->dev);
+ if (match && match->driver_data)
+ return (struct sp_dev_vdata *)match->driver_data;
+-#endif
++
+ return NULL;
+ }
+
+@@ -212,12 +206,8 @@ static int sp_platform_resume(struct platform_device *pdev)
+ static struct platform_driver sp_platform_driver = {
+ .driver = {
+ .name = "ccp",
+-#ifdef CONFIG_ACPI
+ .acpi_match_table = sp_acpi_match,
+-#endif
+-#ifdef CONFIG_OF
+ .of_match_table = sp_of_match,
+-#endif
+ },
+ .probe = sp_platform_probe,
+ .remove_new = sp_platform_remove,
+diff --git a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c
+index 7909b51e97c30..7b8abfb797fff 100644
+--- a/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c
++++ b/drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c
+@@ -296,7 +296,7 @@ static const u32 *adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev)
+ {
+ if (adf_gen4_init_thd2arb_map(accel_dev))
+ dev_warn(&GET_DEV(accel_dev),
+- "Generate of the thread to arbiter map failed");
++ "Failed to generate thread to arbiter mapping");
+
+ return GET_HW_DATA(accel_dev)->thd_to_arb_map;
+ }
+diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
+index e171cddf6f025..7a5c5f9711c8b 100644
+--- a/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
++++ b/drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
+@@ -208,7 +208,7 @@ static const u32 *adf_get_arbiter_mapping(struct adf_accel_dev *accel_dev)
+ {
+ if (adf_gen4_init_thd2arb_map(accel_dev))
+ dev_warn(&GET_DEV(accel_dev),
+- "Generate of the thread to arbiter map failed");
++ "Failed to generate thread to arbiter mapping");
+
+ return GET_HW_DATA(accel_dev)->thd_to_arb_map;
+ }
+diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
+index 9762f2bf7727f..d26564cebdec4 100644
+--- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
++++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
+@@ -197,7 +197,9 @@ module_pci_driver(adf_driver);
+ MODULE_LICENSE("Dual BSD/GPL");
+ MODULE_AUTHOR("Intel");
+ MODULE_FIRMWARE(ADF_4XXX_FW);
++MODULE_FIRMWARE(ADF_402XX_FW);
+ MODULE_FIRMWARE(ADF_4XXX_MMP);
++MODULE_FIRMWARE(ADF_402XX_MMP);
+ MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
+ MODULE_VERSION(ADF_DRV_VERSION);
+ MODULE_SOFTDEP("pre: crypto-intel_qat");
+diff --git a/drivers/crypto/intel/qat/qat_common/adf_gen4_tl.c b/drivers/crypto/intel/qat/qat_common/adf_gen4_tl.c
+index 7fc7a77f6aed9..c7ad8cf07863b 100644
+--- a/drivers/crypto/intel/qat/qat_common/adf_gen4_tl.c
++++ b/drivers/crypto/intel/qat/qat_common/adf_gen4_tl.c
+@@ -149,5 +149,6 @@ void adf_gen4_init_tl_data(struct adf_tl_hw_data *tl_data)
+ tl_data->sl_exec_counters = sl_exec_counters;
+ tl_data->rp_counters = rp_counters;
+ tl_data->num_rp_counters = ARRAY_SIZE(rp_counters);
++ tl_data->max_sl_cnt = ADF_GEN4_TL_MAX_SLICES_PER_TYPE;
+ }
+ EXPORT_SYMBOL_GPL(adf_gen4_init_tl_data);
+diff --git a/drivers/crypto/intel/qat/qat_common/adf_rl.c b/drivers/crypto/intel/qat/qat_common/adf_rl.c
+index d4f2db3c53d8c..e10f0024f4b85 100644
+--- a/drivers/crypto/intel/qat/qat_common/adf_rl.c
++++ b/drivers/crypto/intel/qat/qat_common/adf_rl.c
+@@ -1125,7 +1125,7 @@ int adf_rl_start(struct adf_accel_dev *accel_dev)
+ }
+
+ if ((fw_caps & RL_CAPABILITY_MASK) != RL_CAPABILITY_VALUE) {
+- dev_info(&GET_DEV(accel_dev), "not supported\n");
++ dev_info(&GET_DEV(accel_dev), "feature not supported by FW\n");
+ ret = -EOPNOTSUPP;
+ goto ret_free;
+ }
+diff --git a/drivers/crypto/intel/qat/qat_common/adf_telemetry.c b/drivers/crypto/intel/qat/qat_common/adf_telemetry.c
+index 2ff714d11bd2f..74fb0c2ed2412 100644
+--- a/drivers/crypto/intel/qat/qat_common/adf_telemetry.c
++++ b/drivers/crypto/intel/qat/qat_common/adf_telemetry.c
+@@ -41,6 +41,20 @@ static int validate_tl_data(struct adf_tl_hw_data *tl_data)
+ return 0;
+ }
+
++static int validate_tl_slice_counters(struct icp_qat_fw_init_admin_slice_cnt *slice_count,
++ u8 max_slices_per_type)
++{
++ u8 *sl_counter = (u8 *)slice_count;
++ int i;
++
++ for (i = 0; i < ADF_TL_SL_CNT_COUNT; i++) {
++ if (sl_counter[i] > max_slices_per_type)
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
+ static int adf_tl_alloc_mem(struct adf_accel_dev *accel_dev)
+ {
+ struct adf_tl_hw_data *tl_data = &GET_TL_DATA(accel_dev);
+@@ -214,6 +228,13 @@ int adf_tl_run(struct adf_accel_dev *accel_dev, int state)
+ return ret;
+ }
+
++ ret = validate_tl_slice_counters(&telemetry->slice_cnt, tl_data->max_sl_cnt);
++ if (ret) {
++ dev_err(dev, "invalid value returned by FW\n");
++ adf_send_admin_tl_stop(accel_dev);
++ return ret;
++ }
++
+ telemetry->hbuffs = state;
+ atomic_set(&telemetry->state, state);
+
+diff --git a/drivers/crypto/intel/qat/qat_common/adf_telemetry.h b/drivers/crypto/intel/qat/qat_common/adf_telemetry.h
+index 9be81cd3b8860..e54a406cc1b4a 100644
+--- a/drivers/crypto/intel/qat/qat_common/adf_telemetry.h
++++ b/drivers/crypto/intel/qat/qat_common/adf_telemetry.h
+@@ -40,6 +40,7 @@ struct adf_tl_hw_data {
+ u8 num_dev_counters;
+ u8 num_rp_counters;
+ u8 max_rp;
++ u8 max_sl_cnt;
+ };
+
+ struct adf_telemetry {
+diff --git a/drivers/crypto/marvell/octeontx2/cn10k_cpt.c b/drivers/crypto/marvell/octeontx2/cn10k_cpt.c
+index 79b4e74804f6d..6bfc59e677478 100644
+--- a/drivers/crypto/marvell/octeontx2/cn10k_cpt.c
++++ b/drivers/crypto/marvell/octeontx2/cn10k_cpt.c
+@@ -138,6 +138,10 @@ int cn10k_cpt_hw_ctx_init(struct pci_dev *pdev,
+ return -ENOMEM;
+ cptr_dma = dma_map_single(&pdev->dev, hctx, CN10K_CPT_HW_CTX_SIZE,
+ DMA_BIDIRECTIONAL);
++ if (dma_mapping_error(&pdev->dev, cptr_dma)) {
++ kfree(hctx);
++ return -ENOMEM;
++ }
+
+ cn10k_cpt_hw_ctx_set(hctx, 1);
+ er_ctx->hw_ctx = hctx;
+diff --git a/drivers/dma/xilinx/xdma.c b/drivers/dma/xilinx/xdma.c
+index 5a3a3293b21b5..313b217388fe9 100644
+--- a/drivers/dma/xilinx/xdma.c
++++ b/drivers/dma/xilinx/xdma.c
+@@ -554,12 +554,14 @@ static void xdma_synchronize(struct dma_chan *chan)
+ }
+
+ /**
+- * xdma_fill_descs - Fill hardware descriptors with contiguous memory block addresses
+- * @sw_desc: tx descriptor state container
+- * @src_addr: Value for a ->src_addr field of a first descriptor
+- * @dst_addr: Value for a ->dst_addr field of a first descriptor
+- * @size: Total size of a contiguous memory block
+- * @filled_descs_num: Number of filled hardware descriptors for corresponding sw_desc
++ * xdma_fill_descs() - Fill hardware descriptors for one contiguous memory chunk.
++ * More than one descriptor will be used if the size is bigger
++ * than XDMA_DESC_BLEN_MAX.
++ * @sw_desc: Descriptor container
++ * @src_addr: First value for the ->src_addr field
++ * @dst_addr: First value for the ->dst_addr field
++ * @size: Size of the contiguous memory block
++ * @filled_descs_num: Index of the first descriptor to take care of in @sw_desc
+ */
+ static inline u32 xdma_fill_descs(struct xdma_desc *sw_desc, u64 src_addr,
+ u64 dst_addr, u32 size, u32 filled_descs_num)
+diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c
+index a6856730ca90f..22c2f1375e867 100644
+--- a/drivers/dpll/dpll_core.c
++++ b/drivers/dpll/dpll_core.c
+@@ -449,7 +449,7 @@ static int dpll_pin_prop_dup(const struct dpll_pin_properties *src,
+ sizeof(*src->freq_supported);
+ dst->freq_supported = kmemdup(src->freq_supported,
+ freq_size, GFP_KERNEL);
+- if (!src->freq_supported)
++ if (!dst->freq_supported)
+ return -ENOMEM;
+ }
+ if (src->board_label) {
+diff --git a/drivers/edac/skx_common.c b/drivers/edac/skx_common.c
+index 9c5b6f8bd8bd5..27996b7924c82 100644
+--- a/drivers/edac/skx_common.c
++++ b/drivers/edac/skx_common.c
+@@ -648,7 +648,7 @@ int skx_mce_check_error(struct notifier_block *nb, unsigned long val,
+ memset(&res, 0, sizeof(res));
+ res.mce = mce;
+ res.addr = mce->addr & MCI_ADDR_PHYSADDR;
+- if (!pfn_to_online_page(res.addr >> PAGE_SHIFT)) {
++ if (!pfn_to_online_page(res.addr >> PAGE_SHIFT) && !arch_is_platform_page(res.addr)) {
+ pr_err("Invalid address 0x%llx in IA32_MC%d_ADDR\n", mce->addr, mce->bank);
+ return NOTIFY_DONE;
+ }
+diff --git a/drivers/edac/versal_edac.c b/drivers/edac/versal_edac.c
+index a840c6922e5b9..4d5b68b6be673 100644
+--- a/drivers/edac/versal_edac.c
++++ b/drivers/edac/versal_edac.c
+@@ -1006,8 +1006,7 @@ static int mc_probe(struct platform_device *pdev)
+ }
+
+ rc = xlnx_register_event(PM_NOTIFY_CB, VERSAL_EVENT_ERROR_PMC_ERR1,
+- XPM_EVENT_ERROR_MASK_DDRMC_CR | XPM_EVENT_ERROR_MASK_DDRMC_NCR |
+- XPM_EVENT_ERROR_MASK_NOC_CR | XPM_EVENT_ERROR_MASK_NOC_NCR,
++ XPM_EVENT_ERROR_MASK_DDRMC_CR | XPM_EVENT_ERROR_MASK_DDRMC_NCR,
+ false, err_callback, mci);
+ if (rc) {
+ if (rc == -EACCES)
+@@ -1044,8 +1043,6 @@ static int mc_remove(struct platform_device *pdev)
+
+ xlnx_unregister_event(PM_NOTIFY_CB, VERSAL_EVENT_ERROR_PMC_ERR1,
+ XPM_EVENT_ERROR_MASK_DDRMC_CR |
+- XPM_EVENT_ERROR_MASK_NOC_CR |
+- XPM_EVENT_ERROR_MASK_NOC_NCR |
+ XPM_EVENT_ERROR_MASK_DDRMC_NCR, err_callback, mci);
+ edac_mc_del_mc(&pdev->dev);
+ edac_mc_free(mci);
+diff --git a/drivers/firmware/qcom/qcom_scm.c b/drivers/firmware/qcom/qcom_scm.c
+index 90283f160a228..29c24578ad2bf 100644
+--- a/drivers/firmware/qcom/qcom_scm.c
++++ b/drivers/firmware/qcom/qcom_scm.c
+@@ -1624,7 +1624,7 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_send);
+ * We do not yet support re-entrant calls via the qseecom interface. To prevent
+ + any potential issues with this, only allow validated machines for now.
+ */
+-static const struct of_device_id qcom_scm_qseecom_allowlist[] = {
++static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = {
+ { .compatible = "lenovo,thinkpad-x13s", },
+ { }
+ };
+@@ -1713,7 +1713,7 @@ static int qcom_scm_qseecom_init(struct qcom_scm *scm)
+ */
+ bool qcom_scm_is_available(void)
+ {
+- return !!__scm;
++ return !!READ_ONCE(__scm);
+ }
+ EXPORT_SYMBOL_GPL(qcom_scm_is_available);
+
+@@ -1794,10 +1794,12 @@ static int qcom_scm_probe(struct platform_device *pdev)
+ if (!scm)
+ return -ENOMEM;
+
++ scm->dev = &pdev->dev;
+ ret = qcom_scm_find_dload_address(&pdev->dev, &scm->dload_mode_addr);
+ if (ret < 0)
+ return ret;
+
++ init_completion(&scm->waitq_comp);
+ mutex_init(&scm->scm_bw_lock);
+
+ scm->path = devm_of_icc_get(&pdev->dev, NULL);
+@@ -1829,10 +1831,8 @@ static int qcom_scm_probe(struct platform_device *pdev)
+ if (ret)
+ return ret;
+
+- __scm = scm;
+- __scm->dev = &pdev->dev;
+-
+- init_completion(&__scm->waitq_comp);
++ /* Let all above stores be available after this */
++ smp_store_release(&__scm, scm);
+
+ irq = platform_get_irq_optional(pdev, 0);
+ if (irq < 0) {
+diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
+index 322aada20f742..ac34876a97f8b 100644
+--- a/drivers/firmware/raspberrypi.c
++++ b/drivers/firmware/raspberrypi.c
+@@ -9,6 +9,7 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/kref.h>
+ #include <linux/mailbox_client.h>
++#include <linux/mailbox_controller.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
+ #include <linux/of_platform.h>
+@@ -97,8 +98,8 @@ int rpi_firmware_property_list(struct rpi_firmware *fw,
+ if (size & 3)
+ return -EINVAL;
+
+- buf = dma_alloc_coherent(fw->cl.dev, PAGE_ALIGN(size), &bus_addr,
+- GFP_ATOMIC);
++ buf = dma_alloc_coherent(fw->chan->mbox->dev, PAGE_ALIGN(size),
++ &bus_addr, GFP_ATOMIC);
+ if (!buf)
+ return -ENOMEM;
+
+@@ -126,7 +127,7 @@ int rpi_firmware_property_list(struct rpi_firmware *fw,
+ ret = -EINVAL;
+ }
+
+- dma_free_coherent(fw->cl.dev, PAGE_ALIGN(size), buf, bus_addr);
++ dma_free_coherent(fw->chan->mbox->dev, PAGE_ALIGN(size), buf, bus_addr);
+
+ return ret;
+ }
+diff --git a/drivers/fpga/dfl-pci.c b/drivers/fpga/dfl-pci.c
+index 98b8fd16183e4..80cac3a5f9767 100644
+--- a/drivers/fpga/dfl-pci.c
++++ b/drivers/fpga/dfl-pci.c
+@@ -78,6 +78,7 @@ static void cci_pci_free_irq(struct pci_dev *pcidev)
+ #define PCIE_DEVICE_ID_SILICOM_PAC_N5011 0x1001
+ #define PCIE_DEVICE_ID_INTEL_DFL 0xbcce
+ /* PCI Subdevice ID for PCIE_DEVICE_ID_INTEL_DFL */
++#define PCIE_SUBDEVICE_ID_INTEL_D5005 0x138d
+ #define PCIE_SUBDEVICE_ID_INTEL_N6000 0x1770
+ #define PCIE_SUBDEVICE_ID_INTEL_N6001 0x1771
+ #define PCIE_SUBDEVICE_ID_INTEL_C6100 0x17d4
+@@ -101,6 +102,8 @@ static struct pci_device_id cci_pcie_id_tbl[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_PAC_D5005_VF),},
+ {PCI_DEVICE(PCI_VENDOR_ID_SILICOM_DENMARK, PCIE_DEVICE_ID_SILICOM_PAC_N5010),},
+ {PCI_DEVICE(PCI_VENDOR_ID_SILICOM_DENMARK, PCIE_DEVICE_ID_SILICOM_PAC_N5011),},
++ {PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_DFL,
++ PCI_VENDOR_ID_INTEL, PCIE_SUBDEVICE_ID_INTEL_D5005),},
+ {PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_DFL,
+ PCI_VENDOR_ID_INTEL, PCIE_SUBDEVICE_ID_INTEL_N6000),},
+ {PCI_DEVICE_SUB(PCI_VENDOR_ID_INTEL, PCIE_DEVICE_ID_INTEL_DFL_VF,
+diff --git a/drivers/gpio/gpio-npcm-sgpio.c b/drivers/gpio/gpio-npcm-sgpio.c
+index d31788b43abcc..2605706145434 100644
+--- a/drivers/gpio/gpio-npcm-sgpio.c
++++ b/drivers/gpio/gpio-npcm-sgpio.c
+@@ -434,7 +434,7 @@ static void npcm_sgpio_irq_handler(struct irq_desc *desc)
+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+ struct irq_chip *ic = irq_desc_get_chip(desc);
+ struct npcm_sgpio *gpio = gpiochip_get_data(gc);
+- unsigned int i, j, girq;
++ unsigned int i, j;
+ unsigned long reg;
+
+ chained_irq_enter(ic, desc);
+@@ -443,11 +443,9 @@ static void npcm_sgpio_irq_handler(struct irq_desc *desc)
+ const struct npcm_sgpio_bank *bank = &npcm_sgpio_banks[i];
+
+ reg = ioread8(bank_reg(gpio, bank, EVENT_STS));
+- for_each_set_bit(j, ®, 8) {
+- girq = irq_find_mapping(gc->irq.domain,
+- i * 8 + gpio->nout_sgpio + j);
+- generic_handle_domain_irq(gc->irq.domain, girq);
+- }
++ for_each_set_bit(j, ®, 8)
++ generic_handle_domain_irq(gc->irq.domain,
++ i * 8 + gpio->nout_sgpio + j);
+ }
+
+ chained_irq_exit(ic, desc);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+index daa66eb4f722b..b1e2dd52e643d 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+@@ -220,7 +220,7 @@ int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev,
+ (kfd_mem_limit.ttm_mem_used + ttm_mem_needed >
+ kfd_mem_limit.max_ttm_mem_limit) ||
+ (adev && xcp_id >= 0 && adev->kfd.vram_used[xcp_id] + vram_needed >
+- vram_size - reserved_for_pt)) {
++ vram_size - reserved_for_pt - atomic64_read(&adev->vram_pin_size))) {
+ ret = -ENOMEM;
+ goto release;
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
+index da48b6da01072..420e5bc44e306 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
+@@ -1129,6 +1129,7 @@ void amdgpu_mes_remove_ring(struct amdgpu_device *adev,
+ return;
+
+ amdgpu_mes_remove_hw_queue(adev, ring->hw_queue_id);
++ del_timer_sync(&ring->fence_drv.fallback_timer);
+ amdgpu_ring_fini(ring);
+ kfree(ring);
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+index 9e5526046aa15..3af505e8cbbc3 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+@@ -608,6 +608,8 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
+ else
+ amdgpu_bo_placement_from_domain(bo, bp->domain);
+ if (bp->type == ttm_bo_type_kernel)
++ bo->tbo.priority = 2;
++ else if (!(bp->flags & AMDGPU_GEM_CREATE_DISCARDABLE))
+ bo->tbo.priority = 1;
+
+ if (!bp->destroy)
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+index dcdecb18b2306..42392a97daff2 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+@@ -9194,7 +9194,7 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = {
+ 7 + /* PIPELINE_SYNC */
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
+- 2 + /* VM_FLUSH */
++ 4 + /* VM_FLUSH */
+ 8 + /* FENCE for VM_FLUSH */
+ 20 + /* GDS switch */
+ 4 + /* double SWITCH_BUFFER,
+@@ -9285,7 +9285,6 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_kiq = {
+ 7 + /* gfx_v10_0_ring_emit_pipeline_sync */
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
+- 2 + /* gfx_v10_0_ring_emit_vm_flush */
+ 8 + 8 + 8, /* gfx_v10_0_ring_emit_fence_kiq x3 for user fence, vm fence */
+ .emit_ib_size = 7, /* gfx_v10_0_ring_emit_ib_compute */
+ .emit_ib = gfx_v10_0_ring_emit_ib_compute,
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+index 0afe86bcc932b..6a6fc422e44da 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+@@ -6110,7 +6110,7 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = {
+ 7 + /* PIPELINE_SYNC */
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
+- 2 + /* VM_FLUSH */
++ 4 + /* VM_FLUSH */
+ 8 + /* FENCE for VM_FLUSH */
+ 20 + /* GDS switch */
+ 5 + /* COND_EXEC */
+@@ -6195,7 +6195,6 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_kiq = {
+ 7 + /* gfx_v11_0_ring_emit_pipeline_sync */
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
+- 2 + /* gfx_v11_0_ring_emit_vm_flush */
+ 8 + 8 + 8, /* gfx_v11_0_ring_emit_fence_kiq x3 for user fence, vm fence */
+ .emit_ib_size = 7, /* gfx_v11_0_ring_emit_ib_compute */
+ .emit_ib = gfx_v11_0_ring_emit_ib_compute,
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+index 3bc6943365a4f..153932c1f64f3 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+@@ -6991,7 +6991,6 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = {
+ 7 + /* gfx_v9_0_ring_emit_pipeline_sync */
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
+- 2 + /* gfx_v9_0_ring_emit_vm_flush */
+ 8 + 8 + 8 + /* gfx_v9_0_ring_emit_fence x3 for user fence, vm fence */
+ 7 + /* gfx_v9_0_emit_mem_sync */
+ 5 + /* gfx_v9_0_emit_wave_limit for updating mmSPI_WCL_PIPE_PERCENT_GFX register */
+@@ -7029,7 +7028,6 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = {
+ 7 + /* gfx_v9_0_ring_emit_pipeline_sync */
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
+- 2 + /* gfx_v9_0_ring_emit_vm_flush */
+ 8 + 8 + 8, /* gfx_v9_0_ring_emit_fence_kiq x3 for user fence, vm fence */
+ .emit_ib_size = 7, /* gfx_v9_0_ring_emit_ib_compute */
+ .emit_fence = gfx_v9_0_ring_emit_fence_kiq,
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+index bdc01ca9609a7..5c8d81bfce7ab 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+@@ -509,10 +509,19 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
+ start = start_mgr << PAGE_SHIFT;
+ end = (last_mgr + 1) << PAGE_SHIFT;
+
++ r = amdgpu_amdkfd_reserve_mem_limit(node->adev,
++ prange->npages * PAGE_SIZE,
++ KFD_IOC_ALLOC_MEM_FLAGS_VRAM,
++ node->xcp ? node->xcp->id : 0);
++ if (r) {
++ dev_dbg(node->adev->dev, "failed to reserve VRAM, r: %ld\n", r);
++ return -ENOSPC;
++ }
++
+ r = svm_range_vram_node_new(node, prange, true);
+ if (r) {
+ dev_dbg(node->adev->dev, "fail %ld to alloc vram\n", r);
+- return r;
++ goto out;
+ }
+ ttm_res_offset = (start_mgr - prange->start + prange->offset) << PAGE_SHIFT;
+
+@@ -545,6 +554,11 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
+ svm_range_vram_node_free(prange);
+ }
+
++out:
++ amdgpu_amdkfd_unreserve_mem_limit(node->adev,
++ prange->npages * PAGE_SIZE,
++ KFD_IOC_ALLOC_MEM_FLAGS_VRAM,
++ node->xcp ? node->xcp->id : 0);
+ return r < 0 ? r : 0;
+ }
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+index 58c1fe5421934..451bb058cc620 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+@@ -829,6 +829,14 @@ struct kfd_process *kfd_create_process(struct task_struct *thread)
+ if (process) {
+ pr_debug("Process already found\n");
+ } else {
++ /* If the process just called exec(3), it is possible that the
++ * cleanup of the kfd_process (following the release of the mm
++ * of the old process image) is still in the cleanup work queue.
++ * Make sure to drain any job before trying to recreate any
++ * resource for this process.
++ */
++ flush_workqueue(kfd_process_wq);
++
+ process = create_process(thread);
+ if (IS_ERR(process))
+ goto out;
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+index c50a0dc9c9c07..33205078202b5 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+@@ -3424,7 +3424,7 @@ svm_range_trigger_migration(struct mm_struct *mm, struct svm_range *prange,
+ mm, KFD_MIGRATE_TRIGGER_PREFETCH);
+ *migrated = !r;
+
+- return r;
++ return 0;
+ }
+
+ int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence)
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 9044214dfdbdf..c4ba397f8cef5 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -3010,6 +3010,7 @@ static int dm_resume(void *handle)
+ dc_stream_release(dm_new_crtc_state->stream);
+ dm_new_crtc_state->stream = NULL;
+ }
++ dm_new_crtc_state->base.color_mgmt_changed = true;
+ }
+
+ for_each_new_plane_in_state(dm->cached_state, plane, new_plane_state, i) {
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
+index 644da46373209..5506cf9b3672f 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
+@@ -145,6 +145,10 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
+ */
+ clk_mgr_base->clks.zstate_support = new_clocks->zstate_support;
+ if (safe_to_lower) {
++ if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) {
++ dcn315_smu_set_dtbclk(clk_mgr, false);
++ clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
++ }
+ /* check that we're not already in lower */
+ if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_LOW_POWER) {
+ display_count = dcn315_get_active_display_cnt_wa(dc, context);
+@@ -160,6 +164,10 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base,
+ }
+ }
+ } else {
++ if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
++ dcn315_smu_set_dtbclk(clk_mgr, true);
++ clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
++ }
+ /* check that we're not already in D0 */
+ if (clk_mgr_base->clks.pwr_state != DCN_PWR_STATE_MISSION_MODE) {
+ union display_idle_optimization_u idle_info = { 0 };
+diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+index bbdbc78161a00..39c63565baa9a 100644
+--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
++++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+@@ -696,8 +696,12 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
+ * since we calculate mode support based on softmax being the max UCLK
+ * frequency.
+ */
+- dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
+- dc->clk_mgr->bw_params->dc_mode_softmax_memclk);
++ if (dc->debug.disable_dc_mode_overwrite) {
++ dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz);
++ dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz);
++ } else
++ dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
++ dc->clk_mgr->bw_params->dc_mode_softmax_memclk);
+ } else {
+ dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, dc->clk_mgr->bw_params->max_memclk_mhz);
+ }
+@@ -730,8 +734,13 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
+ /* set UCLK to requested value if P-State switching is supported, or to re-enable P-State switching */
+ if (clk_mgr_base->clks.p_state_change_support &&
+ (update_uclk || !clk_mgr_base->clks.prev_p_state_change_support) &&
+- !dc->work_arounds.clock_update_disable_mask.uclk)
++ !dc->work_arounds.clock_update_disable_mask.uclk) {
++ if (dc->clk_mgr->dc_mode_softmax_enabled && dc->debug.disable_dc_mode_overwrite)
++ dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK,
++ max((int)dc->clk_mgr->bw_params->dc_mode_softmax_memclk, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz)));
++
+ dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
++ }
+
+ if (clk_mgr_base->clks.num_ways != new_clocks->num_ways &&
+ clk_mgr_base->clks.num_ways > new_clocks->num_ways) {
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index 3c3d613c5f00e..040b5c2a57586 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -1804,6 +1804,9 @@ bool dc_validate_boot_timing(const struct dc *dc,
+ return false;
+ }
+
++ if (link->dpcd_caps.channel_coding_cap.bits.DP_128b_132b_SUPPORTED)
++ return false;
++
+ if (dc->link_srv->edp_is_ilr_optimization_required(link, crtc_timing)) {
+ DC_LOG_EVENT_LINK_TRAINING("Seamless boot disabled to optimize eDP link rate\n");
+ return false;
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
+index 3538973bd0c6c..c0372aa4ec838 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_cm_common.c
+@@ -382,6 +382,11 @@ bool cm_helper_translate_curve_to_hw_format(struct dc_context *ctx,
+ i += increment) {
+ if (j == hw_points - 1)
+ break;
++ if (i >= TRANSFER_FUNC_POINTS) {
++ DC_LOG_ERROR("Index out of bounds: i=%d, TRANSFER_FUNC_POINTS=%d\n",
++ i, TRANSFER_FUNC_POINTS);
++ return false;
++ }
+ rgb_resulted[j].red = output_tf->tf_pts.red[i];
+ rgb_resulted[j].green = output_tf->tf_pts.green[i];
+ rgb_resulted[j].blue = output_tf->tf_pts.blue[i];
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
+index deb6d162a2d5c..7307b7b8d8ad7 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c
+@@ -291,6 +291,7 @@ static struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = {
+ .do_urgent_latency_adjustment = false,
+ .urgent_latency_adjustment_fabric_clock_component_us = 0,
+ .urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
++ .dispclk_dppclk_vco_speed_mhz = 2400.0,
+ .num_chans = 4,
+ .dummy_pstate_latency_us = 10.0
+ };
+@@ -438,6 +439,7 @@ static struct _vcs_dpi_soc_bounding_box_st dcn3_16_soc = {
+ .do_urgent_latency_adjustment = false,
+ .urgent_latency_adjustment_fabric_clock_component_us = 0,
+ .urgent_latency_adjustment_fabric_clock_reference_mhz = 0,
++ .dispclk_dppclk_vco_speed_mhz = 2500.0,
+ };
+
+ void dcn31_zero_pipe_dcc_fraction(display_e2e_pipe_params_st *pipes,
+diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+index 46cbb5a6c8e74..1a3c212ae63c8 100644
+--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
++++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c
+@@ -999,8 +999,7 @@ void dcn35_calc_blocks_to_gate(struct dc *dc, struct dc_state *context,
+ if (pipe_ctx->plane_res.dpp)
+ update_state->pg_pipe_res_update[PG_DPP][pipe_ctx->plane_res.hubp->inst] = false;
+
+- if ((pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp) &&
+- pipe_ctx->plane_res.mpcc_inst >= 0)
++ if (pipe_ctx->plane_res.dpp || pipe_ctx->stream_res.opp)
+ update_state->pg_pipe_res_update[PG_MPCC][pipe_ctx->plane_res.mpcc_inst] = false;
+
+ if (pipe_ctx->stream_res.dsc)
+diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c
+index 5491b707cec88..5a965c26bf209 100644
+--- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c
++++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_dpia_bw.c
+@@ -270,7 +270,7 @@ static void set_usb4_req_bw_req(struct dc_link *link, int req_bw)
+
+ /* Error check whether requested and allocated are equal */
+ req_bw = requested_bw * (Kbps_TO_Gbps / link->dpia_bw_alloc_config.bw_granularity);
+- if (req_bw == link->dpia_bw_alloc_config.allocated_bw) {
++ if (req_bw && (req_bw == link->dpia_bw_alloc_config.allocated_bw)) {
+ DC_LOG_ERROR("%s: Request bw equals to allocated bw for link(%d)\n",
+ __func__, link->link_index);
+ }
+@@ -341,6 +341,14 @@ bool link_dp_dpia_set_dptx_usb4_bw_alloc_support(struct dc_link *link)
+ ret = true;
+ init_usb4_bw_struct(link);
+ link->dpia_bw_alloc_config.bw_alloc_enabled = true;
++
++ /*
++ * During DP tunnel creation, CM preallocates BW and reduces estimated BW of other
++ * DPIA. CM release preallocation only when allocation is complete. Do zero alloc
++ * to make the CM to release preallocation and update estimated BW correctly for
++ * all DPIAs per host router
++ */
++ link_dp_dpia_allocate_usb4_bandwidth_for_stream(link, 0);
+ }
+ }
+
+diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+index f9c5bc624be30..f81f6110913d3 100644
+--- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+@@ -2451,6 +2451,7 @@ static bool dcn20_resource_construct(
+ dc->caps.post_blend_color_processing = true;
+ dc->caps.force_dp_tps4_for_cp2520 = true;
+ dc->caps.extended_aux_timeout_support = true;
++ dc->caps.dmcub_support = true;
+
+ /* Color pipeline capabilities */
+ dc->caps.color.dpp.dcn_arch = 1;
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+index 78491b04df108..ddb11eb8c3f53 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+@@ -2205,6 +2205,17 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
+ return sizeof(*gpu_metrics);
+ }
+
++static void smu_v13_0_6_restore_pci_config(struct smu_context *smu)
++{
++ struct amdgpu_device *adev = smu->adev;
++ int i;
++
++ for (i = 0; i < 16; i++)
++ pci_write_config_dword(adev->pdev, i * 4,
++ adev->pdev->saved_config_space[i]);
++ pci_restore_msi_state(adev->pdev);
++}
++
+ static int smu_v13_0_6_mode2_reset(struct smu_context *smu)
+ {
+ int ret = 0, index;
+@@ -2226,6 +2237,20 @@ static int smu_v13_0_6_mode2_reset(struct smu_context *smu)
+ /* Restore the config space saved during init */
+ amdgpu_device_load_pci_state(adev->pdev);
+
++ /* Certain platforms have switches which assign virtual BAR values to
++ * devices. OS uses the virtual BAR values and device behind the switch
++ * is assgined another BAR value. When device's config space registers
++ * are queried, switch returns the virtual BAR values. When mode-2 reset
++ * is performed, switch is unaware of it, and will continue to return
++ * the same virtual values to the OS.This affects
++ * pci_restore_config_space() API as it doesn't write the value saved if
++ * the current value read from config space is the same as what is
++ * saved. As a workaround, make sure the config space is restored
++ * always.
++ */
++ if (!(adev->flags & AMD_IS_APU))
++ smu_v13_0_6_restore_pci_config(smu);
++
+ dev_dbg(smu->adev->dev, "wait for reset ack\n");
+ do {
+ ret = smu_cmn_wait_for_response(smu);
+diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
+index 626709bec6f5f..2577f0cef8fcd 100644
+--- a/drivers/gpu/drm/arm/malidp_mw.c
++++ b/drivers/gpu/drm/arm/malidp_mw.c
+@@ -72,7 +72,10 @@ static void malidp_mw_connector_reset(struct drm_connector *connector)
+ __drm_atomic_helper_connector_destroy_state(connector->state);
+
+ kfree(connector->state);
+- __drm_atomic_helper_connector_reset(connector, &mw_state->base);
++ connector->state = NULL;
++
++ if (mw_state)
++ __drm_atomic_helper_connector_reset(connector, &mw_state->base);
+ }
+
+ static enum drm_connector_status
+diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c
+index 29d91493b101a..c1191ef5e8e67 100644
+--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
++++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
+@@ -2076,10 +2076,8 @@ static int anx7625_setup_dsi_device(struct anx7625_data *ctx)
+ };
+
+ host = of_find_mipi_dsi_host_by_node(ctx->pdata.mipi_host_node);
+- if (!host) {
+- DRM_DEV_ERROR(dev, "fail to find dsi host.\n");
+- return -EPROBE_DEFER;
+- }
++ if (!host)
++ return dev_err_probe(dev, -EPROBE_DEFER, "fail to find dsi host.\n");
+
+ dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
+ if (IS_ERR(dsi)) {
+@@ -2481,15 +2479,22 @@ static void anx7625_bridge_atomic_disable(struct drm_bridge *bridge,
+ mutex_unlock(&ctx->aux_lock);
+ }
+
++static void
++anx7625_audio_update_connector_status(struct anx7625_data *ctx,
++ enum drm_connector_status status);
++
+ static enum drm_connector_status
+ anx7625_bridge_detect(struct drm_bridge *bridge)
+ {
+ struct anx7625_data *ctx = bridge_to_anx7625(bridge);
+ struct device *dev = ctx->dev;
++ enum drm_connector_status status;
+
+ DRM_DEV_DEBUG_DRIVER(dev, "drm bridge detect\n");
+
+- return anx7625_sink_detect(ctx);
++ status = anx7625_sink_detect(ctx);
++ anx7625_audio_update_connector_status(ctx, status);
++ return status;
+ }
+
+ static struct edid *anx7625_bridge_get_edid(struct drm_bridge *bridge,
+diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+index 7d470527455b1..bab8844c6fefb 100644
+--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
++++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+@@ -2057,6 +2057,9 @@ static void cdns_mhdp_atomic_enable(struct drm_bridge *bridge,
+ mhdp_state = to_cdns_mhdp_bridge_state(new_state);
+
+ mhdp_state->current_mode = drm_mode_duplicate(bridge->dev, mode);
++ if (!mhdp_state->current_mode)
++ return;
++
+ drm_mode_set_name(mhdp_state->current_mode);
+
+ dev_dbg(mhdp->dev, "%s: Enabling mode %s\n", __func__, mode->name);
+diff --git a/drivers/gpu/drm/bridge/chipone-icn6211.c b/drivers/gpu/drm/bridge/chipone-icn6211.c
+index 82d23e4df09eb..ff3284b6b1a37 100644
+--- a/drivers/gpu/drm/bridge/chipone-icn6211.c
++++ b/drivers/gpu/drm/bridge/chipone-icn6211.c
+@@ -563,10 +563,8 @@ static int chipone_dsi_host_attach(struct chipone *icn)
+
+ host = of_find_mipi_dsi_host_by_node(host_node);
+ of_node_put(host_node);
+- if (!host) {
+- dev_err(dev, "failed to find dsi host\n");
+- return -EPROBE_DEFER;
+- }
++ if (!host)
++ return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n");
+
+ dsi = mipi_dsi_device_register_full(host, &info);
+ if (IS_ERR(dsi)) {
+diff --git a/drivers/gpu/drm/bridge/lontium-lt8912b.c b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+index 97d4af3d13653..0b5b98d3e5f6f 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt8912b.c
++++ b/drivers/gpu/drm/bridge/lontium-lt8912b.c
+@@ -494,10 +494,8 @@ static int lt8912_attach_dsi(struct lt8912 *lt)
+ };
+
+ host = of_find_mipi_dsi_host_by_node(lt->host_node);
+- if (!host) {
+- dev_err(dev, "failed to find dsi host\n");
+- return -EPROBE_DEFER;
+- }
++ if (!host)
++ return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n");
+
+ dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
+ if (IS_ERR(dsi)) {
+diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c
+index 9663601ce0981..89bdd938757e1 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt9611.c
++++ b/drivers/gpu/drm/bridge/lontium-lt9611.c
+@@ -760,10 +760,8 @@ static struct mipi_dsi_device *lt9611_attach_dsi(struct lt9611 *lt9611,
+ int ret;
+
+ host = of_find_mipi_dsi_host_by_node(dsi_node);
+- if (!host) {
+- dev_err(lt9611->dev, "failed to find dsi host\n");
+- return ERR_PTR(-EPROBE_DEFER);
+- }
++ if (!host)
++ return ERR_PTR(dev_err_probe(lt9611->dev, -EPROBE_DEFER, "failed to find dsi host\n"));
+
+ dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
+ if (IS_ERR(dsi)) {
+diff --git a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+index e971b75e90ad0..b803899126d54 100644
+--- a/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
++++ b/drivers/gpu/drm/bridge/lontium-lt9611uxc.c
+@@ -265,10 +265,8 @@ static struct mipi_dsi_device *lt9611uxc_attach_dsi(struct lt9611uxc *lt9611uxc,
+ int ret;
+
+ host = of_find_mipi_dsi_host_by_node(dsi_node);
+- if (!host) {
+- dev_err(dev, "failed to find dsi host\n");
+- return ERR_PTR(-EPROBE_DEFER);
+- }
++ if (!host)
++ return ERR_PTR(dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n"));
+
+ dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
+ if (IS_ERR(dsi)) {
+diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c
+index 90a89d70d8328..fea4f00a20f83 100644
+--- a/drivers/gpu/drm/bridge/tc358775.c
++++ b/drivers/gpu/drm/bridge/tc358775.c
+@@ -610,10 +610,8 @@ static int tc_attach_host(struct tc_data *tc)
+ };
+
+ host = of_find_mipi_dsi_host_by_node(tc->host_node);
+- if (!host) {
+- dev_err(dev, "failed to find dsi host\n");
+- return -EPROBE_DEFER;
+- }
++ if (!host)
++ return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n");
+
+ dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
+ if (IS_ERR(dsi)) {
+diff --git a/drivers/gpu/drm/bridge/ti-dlpc3433.c b/drivers/gpu/drm/bridge/ti-dlpc3433.c
+index ca3348109bcd2..6b559e0713012 100644
+--- a/drivers/gpu/drm/bridge/ti-dlpc3433.c
++++ b/drivers/gpu/drm/bridge/ti-dlpc3433.c
+@@ -319,12 +319,11 @@ static int dlpc_host_attach(struct dlpc *dlpc)
+ .channel = 0,
+ .node = NULL,
+ };
++ int ret;
+
+ host = of_find_mipi_dsi_host_by_node(dlpc->host_node);
+- if (!host) {
+- DRM_DEV_ERROR(dev, "failed to find dsi host\n");
+- return -EPROBE_DEFER;
+- }
++ if (!host)
++ return dev_err_probe(dev, -EPROBE_DEFER, "failed to find dsi host\n");
+
+ dlpc->dsi = mipi_dsi_device_register_full(host, &info);
+ if (IS_ERR(dlpc->dsi)) {
+@@ -336,7 +335,11 @@ static int dlpc_host_attach(struct dlpc *dlpc)
+ dlpc->dsi->format = MIPI_DSI_FMT_RGB565;
+ dlpc->dsi->lanes = dlpc->dsi_lanes;
+
+- return devm_mipi_dsi_attach(dev, dlpc->dsi);
++ ret = devm_mipi_dsi_attach(dev, dlpc->dsi);
++ if (ret)
++ DRM_DEV_ERROR(dev, "failed to attach dsi host\n");
++
++ return ret;
+ }
+
+ static int dlpc3433_probe(struct i2c_client *client)
+@@ -367,10 +370,8 @@ static int dlpc3433_probe(struct i2c_client *client)
+ drm_bridge_add(&dlpc->bridge);
+
+ ret = dlpc_host_attach(dlpc);
+- if (ret) {
+- DRM_DEV_ERROR(dev, "failed to attach dsi host\n");
++ if (ret)
+ goto err_remove_bridge;
+- }
+
+ return 0;
+
+diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+index 62cc3893dca5d..1f6e929c2f6a3 100644
+--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
++++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+@@ -1591,7 +1591,6 @@ static int ti_sn_pwm_probe(struct auxiliary_device *adev,
+ pdata->pchip.ops = &ti_sn_pwm_ops;
+ pdata->pchip.npwm = 1;
+ pdata->pchip.of_xlate = of_pwm_single_xlate;
+- pdata->pchip.of_pwm_n_cells = 1;
+
+ devm_pm_runtime_enable(&adev->dev);
+
+diff --git a/drivers/gpu/drm/ci/test.yml b/drivers/gpu/drm/ci/test.yml
+index 9faf76e55a56a..da381257e7e54 100644
+--- a/drivers/gpu/drm/ci/test.yml
++++ b/drivers/gpu/drm/ci/test.yml
+@@ -237,11 +237,11 @@ i915:cml:
+ i915:tgl:
+ extends:
+ - .i915
+- parallel: 8
++ parallel: 5
+ variables:
+- DEVICE_TYPE: asus-cx9400-volteer
++ DEVICE_TYPE: acer-cp514-2h-1130g7-volteer
+ GPU_VERSION: tgl
+- RUNNER_TAG: mesa-ci-x86-64-lava-asus-cx9400-volteer
++ RUNNER_TAG: mesa-ci-x86-64-lava-acer-cp514-2h-1130g7-volteer
+
+ .amdgpu:
+ extends:
+diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c
+index 26c188ce5f1c3..fb80843e7f2df 100644
+--- a/drivers/gpu/drm/display/drm_dp_helper.c
++++ b/drivers/gpu/drm/display/drm_dp_helper.c
+@@ -532,6 +532,15 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request,
+
+ mutex_lock(&aux->hw_mutex);
+
++ /*
++ * If the device attached to the aux bus is powered down then there's
++ * no reason to attempt a transfer. Error out immediately.
++ */
++ if (aux->powered_down) {
++ ret = -EBUSY;
++ goto unlock;
++ }
++
+ /*
+ * The specification doesn't give any recommendation on how often to
+ * retry native transactions. We used to retry 7 times like for
+@@ -599,6 +608,29 @@ int drm_dp_dpcd_probe(struct drm_dp_aux *aux, unsigned int offset)
+ }
+ EXPORT_SYMBOL(drm_dp_dpcd_probe);
+
++/**
++ * drm_dp_dpcd_set_powered() - Set whether the DP device is powered
++ * @aux: DisplayPort AUX channel; for convenience it's OK to pass NULL here
++ * and the function will be a no-op.
++ * @powered: true if powered; false if not
++ *
++ * If the endpoint device on the DP AUX bus is known to be powered down
++ * then this function can be called to make future transfers fail immediately
++ * instead of needing to time out.
++ *
++ * If this function is never called then a device defaults to being powered.
++ */
++void drm_dp_dpcd_set_powered(struct drm_dp_aux *aux, bool powered)
++{
++ if (!aux)
++ return;
++
++ mutex_lock(&aux->hw_mutex);
++ aux->powered_down = !powered;
++ mutex_unlock(&aux->hw_mutex);
++}
++EXPORT_SYMBOL(drm_dp_dpcd_set_powered);
++
+ /**
+ * drm_dp_dpcd_read() - read a series of bytes from the DPCD
+ * @aux: DisplayPort AUX channel (SST or MST)
+@@ -1858,6 +1890,9 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
+ struct drm_dp_aux_msg msg;
+ int err = 0;
+
++ if (aux->powered_down)
++ return -EBUSY;
++
+ dp_aux_i2c_transfer_size = clamp(dp_aux_i2c_transfer_size, 1, DP_AUX_MAX_PAYLOAD_BYTES);
+
+ memset(&msg, 0, sizeof(msg));
+diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
+index 4f6f8c662d3fe..ac502ea20089b 100644
+--- a/drivers/gpu/drm/drm_bridge.c
++++ b/drivers/gpu/drm/drm_bridge.c
+@@ -687,11 +687,17 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
+ */
+ list_for_each_entry_from(next, &encoder->bridge_chain,
+ chain_node) {
+- if (next->pre_enable_prev_first) {
++ if (!next->pre_enable_prev_first) {
+ next = list_prev_entry(next, chain_node);
+ limit = next;
+ break;
+ }
++
++ if (list_is_last(&next->chain_node,
++ &encoder->bridge_chain)) {
++ limit = next;
++ break;
++ }
+ }
+
+ /* Call these bridges in reverse order */
+@@ -774,7 +780,7 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
+ /* Found first bridge that does NOT
+ * request prev to be enabled first
+ */
+- limit = list_prev_entry(next, chain_node);
++ limit = next;
+ break;
+ }
+ }
+diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
+index 69c68804023ff..9ef9a70a836c7 100644
+--- a/drivers/gpu/drm/drm_edid.c
++++ b/drivers/gpu/drm/drm_edid.c
+@@ -7345,7 +7345,7 @@ static void drm_parse_tiled_block(struct drm_connector *connector,
+ static bool displayid_is_tiled_block(const struct displayid_iter *iter,
+ const struct displayid_block *block)
+ {
+- return (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_12 &&
++ return (displayid_version(iter) < DISPLAY_ID_STRUCTURE_VER_20 &&
+ block->tag == DATA_BLOCK_TILED_DISPLAY) ||
+ (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_20 &&
+ block->tag == DATA_BLOCK_2_TILED_DISPLAY_TOPOLOGY);
+diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
+index 843a6dbda93a0..52a93149363b4 100644
+--- a/drivers/gpu/drm/drm_mipi_dsi.c
++++ b/drivers/gpu/drm/drm_mipi_dsi.c
+@@ -654,7 +654,7 @@ EXPORT_SYMBOL(mipi_dsi_set_maximum_return_packet_size);
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+-ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
++int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable)
+ {
+ /* Note: Needs updating for non-default PPS or algorithm */
+ u8 tx[2] = { enable << 0, 0 };
+@@ -679,8 +679,8 @@ EXPORT_SYMBOL(mipi_dsi_compression_mode);
+ *
+ * Return: 0 on success or a negative error code on failure.
+ */
+-ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
+- const struct drm_dsc_picture_parameter_set *pps)
++int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
++ const struct drm_dsc_picture_parameter_set *pps)
+ {
+ struct mipi_dsi_msg msg = {
+ .channel = dsi->channel,
+diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+index 9b8445d2a128f..89cb6799b547f 100644
+--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
++++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+@@ -632,8 +632,8 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu)
+ /* Disable TX clock gating on affected core revisions. */
+ if (etnaviv_is_model_rev(gpu, GC4000, 0x5222) ||
+ etnaviv_is_model_rev(gpu, GC2000, 0x5108) ||
+- etnaviv_is_model_rev(gpu, GC2000, 0x6202) ||
+- etnaviv_is_model_rev(gpu, GC2000, 0x6203))
++ etnaviv_is_model_rev(gpu, GC7000, 0x6202) ||
++ etnaviv_is_model_rev(gpu, GC7000, 0x6203))
+ pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX;
+
+ /* Disable SE and RA clock gating on affected core revisions. */
+diff --git a/drivers/gpu/drm/imagination/pvr_vm_mips.c b/drivers/gpu/drm/imagination/pvr_vm_mips.c
+index b7fef3c797e6c..4f99b4af871c0 100644
+--- a/drivers/gpu/drm/imagination/pvr_vm_mips.c
++++ b/drivers/gpu/drm/imagination/pvr_vm_mips.c
+@@ -46,7 +46,7 @@ pvr_vm_mips_init(struct pvr_device *pvr_dev)
+ if (!mips_data)
+ return -ENOMEM;
+
+- for (page_nr = 0; page_nr < ARRAY_SIZE(mips_data->pt_pages); page_nr++) {
++ for (page_nr = 0; page_nr < PVR_MIPS_PT_PAGE_COUNT; page_nr++) {
+ mips_data->pt_pages[page_nr] = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (!mips_data->pt_pages[page_nr]) {
+ err = -ENOMEM;
+@@ -102,7 +102,7 @@ pvr_vm_mips_fini(struct pvr_device *pvr_dev)
+ int page_nr;
+
+ vunmap(mips_data->pt);
+- for (page_nr = ARRAY_SIZE(mips_data->pt_pages) - 1; page_nr >= 0; page_nr--) {
++ for (page_nr = PVR_MIPS_PT_PAGE_COUNT - 1; page_nr >= 0; page_nr--) {
+ dma_unmap_page(from_pvr_device(pvr_dev)->dev,
+ mips_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE);
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+index 3d17de34d72bd..d398fa1871165 100644
+--- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
++++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c
+@@ -992,10 +992,10 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
+
+ mtk_crtc->mmsys_dev = priv->mmsys_dev;
+ mtk_crtc->ddp_comp_nr = path_len;
+- mtk_crtc->ddp_comp = devm_kmalloc_array(dev,
+- mtk_crtc->ddp_comp_nr + (conn_routes ? 1 : 0),
+- sizeof(*mtk_crtc->ddp_comp),
+- GFP_KERNEL);
++ mtk_crtc->ddp_comp = devm_kcalloc(dev,
++ mtk_crtc->ddp_comp_nr + (conn_routes ? 1 : 0),
++ sizeof(*mtk_crtc->ddp_comp),
++ GFP_KERNEL);
+ if (!mtk_crtc->ddp_comp)
+ return -ENOMEM;
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
+index 4f2e3feabc0f8..1bf229615b018 100644
+--- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c
++++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c
+@@ -38,6 +38,9 @@ static struct mtk_drm_gem_obj *mtk_drm_gem_init(struct drm_device *dev,
+
+ size = round_up(size, PAGE_SIZE);
+
++ if (size == 0)
++ return ERR_PTR(-EINVAL);
++
+ mtk_gem_obj = kzalloc(sizeof(*mtk_gem_obj), GFP_KERNEL);
+ if (!mtk_gem_obj)
+ return ERR_PTR(-ENOMEM);
+diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c
+index 2a82119eb58ed..2a942dc6a6dc2 100644
+--- a/drivers/gpu/drm/meson/meson_vclk.c
++++ b/drivers/gpu/drm/meson/meson_vclk.c
+@@ -790,13 +790,13 @@ meson_vclk_vic_supported_freq(struct meson_drm *priv, unsigned int phy_freq,
+ FREQ_1000_1001(params[i].pixel_freq));
+ DRM_DEBUG_DRIVER("i = %d phy_freq = %d alt = %d\n",
+ i, params[i].phy_freq,
+- FREQ_1000_1001(params[i].phy_freq/10)*10);
++ FREQ_1000_1001(params[i].phy_freq/1000)*1000);
+ /* Match strict frequency */
+ if (phy_freq == params[i].phy_freq &&
+ vclk_freq == params[i].vclk_freq)
+ return MODE_OK;
+ /* Match 1000/1001 variant */
+- if (phy_freq == (FREQ_1000_1001(params[i].phy_freq/10)*10) &&
++ if (phy_freq == (FREQ_1000_1001(params[i].phy_freq/1000)*1000) &&
+ vclk_freq == FREQ_1000_1001(params[i].vclk_freq))
+ return MODE_OK;
+ }
+@@ -1070,7 +1070,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
+
+ for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
+ if ((phy_freq == params[freq].phy_freq ||
+- phy_freq == FREQ_1000_1001(params[freq].phy_freq/10)*10) &&
++ phy_freq == FREQ_1000_1001(params[freq].phy_freq/1000)*1000) &&
+ (vclk_freq == params[freq].vclk_freq ||
+ vclk_freq == FREQ_1000_1001(params[freq].vclk_freq))) {
+ if (vclk_freq != params[freq].vclk_freq)
+diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
+index 03f4951c49f42..e67a80d56948c 100644
+--- a/drivers/gpu/drm/msm/dp/dp_aux.c
++++ b/drivers/gpu/drm/msm/dp/dp_aux.c
+@@ -35,6 +35,7 @@ struct dp_aux_private {
+ bool no_send_stop;
+ bool initted;
+ bool is_edp;
++ bool enable_xfers;
+ u32 offset;
+ u32 segment;
+
+@@ -301,6 +302,17 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
+ goto exit;
+ }
+
++ /*
++ * If we're using DP and an external display isn't connected then the
++ * transfer won't succeed. Return right away. If we don't do this we
++ * can end up with long timeouts if someone tries to access the DP AUX
++ * character device when no DP device is connected.
++ */
++ if (!aux->is_edp && !aux->enable_xfers) {
++ ret = -ENXIO;
++ goto exit;
++ }
++
+ /*
+ * For eDP it's important to give a reasonably long wait here for HPD
+ * to be asserted. This is because the panel driver may have _just_
+@@ -433,6 +445,14 @@ irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux)
+ return IRQ_HANDLED;
+ }
+
++void dp_aux_enable_xfers(struct drm_dp_aux *dp_aux, bool enabled)
++{
++ struct dp_aux_private *aux;
++
++ aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
++ aux->enable_xfers = enabled;
++}
++
+ void dp_aux_reconfig(struct drm_dp_aux *dp_aux)
+ {
+ struct dp_aux_private *aux;
+diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h
+index 511305da4f66d..f3052cb43306b 100644
+--- a/drivers/gpu/drm/msm/dp/dp_aux.h
++++ b/drivers/gpu/drm/msm/dp/dp_aux.h
+@@ -12,6 +12,7 @@
+ int dp_aux_register(struct drm_dp_aux *dp_aux);
+ void dp_aux_unregister(struct drm_dp_aux *dp_aux);
+ irqreturn_t dp_aux_isr(struct drm_dp_aux *dp_aux);
++void dp_aux_enable_xfers(struct drm_dp_aux *dp_aux, bool enabled);
+ void dp_aux_init(struct drm_dp_aux *dp_aux);
+ void dp_aux_deinit(struct drm_dp_aux *dp_aux);
+ void dp_aux_reconfig(struct drm_dp_aux *dp_aux);
+diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
+index fb588fde298a2..780e9747be1fb 100644
+--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
++++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
+@@ -1019,14 +1019,14 @@ static int dp_ctrl_update_vx_px(struct dp_ctrl_private *ctrl)
+ if (ret)
+ return ret;
+
+- if (voltage_swing_level >= DP_TRAIN_VOLTAGE_SWING_MAX) {
++ if (voltage_swing_level >= DP_TRAIN_LEVEL_MAX) {
+ drm_dbg_dp(ctrl->drm_dev,
+ "max. voltage swing level reached %d\n",
+ voltage_swing_level);
+ max_level_reached |= DP_TRAIN_MAX_SWING_REACHED;
+ }
+
+- if (pre_emphasis_level >= DP_TRAIN_PRE_EMPHASIS_MAX) {
++ if (pre_emphasis_level >= DP_TRAIN_LEVEL_MAX) {
+ drm_dbg_dp(ctrl->drm_dev,
+ "max. pre-emphasis level reached %d\n",
+ pre_emphasis_level);
+@@ -1117,7 +1117,7 @@ static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl,
+ }
+
+ if (ctrl->link->phy_params.v_level >=
+- DP_TRAIN_VOLTAGE_SWING_MAX) {
++ DP_TRAIN_LEVEL_MAX) {
+ DRM_ERROR_RATELIMITED("max v_level reached\n");
+ return -EAGAIN;
+ }
+diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
+index 78464c395c3d9..0840860336790 100644
+--- a/drivers/gpu/drm/msm/dp/dp_display.c
++++ b/drivers/gpu/drm/msm/dp/dp_display.c
+@@ -565,6 +565,8 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data)
+ int ret;
+ struct platform_device *pdev = dp->dp_display.pdev;
+
++ dp_aux_enable_xfers(dp->aux, true);
++
+ mutex_lock(&dp->event_mutex);
+
+ state = dp->hpd_state;
+@@ -630,6 +632,8 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data)
+ u32 state;
+ struct platform_device *pdev = dp->dp_display.pdev;
+
++ dp_aux_enable_xfers(dp->aux, false);
++
+ mutex_lock(&dp->event_mutex);
+
+ state = dp->hpd_state;
+diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c
+index 49dfac1fd1ef2..ea911d9244be7 100644
+--- a/drivers/gpu/drm/msm/dp/dp_link.c
++++ b/drivers/gpu/drm/msm/dp/dp_link.c
+@@ -1109,6 +1109,7 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link)
+ int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status)
+ {
+ int i;
++ u8 max_p_level;
+ int v_max = 0, p_max = 0;
+ struct dp_link_private *link;
+
+@@ -1140,30 +1141,29 @@ int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status)
+ * Adjust the voltage swing and pre-emphasis level combination to within
+ * the allowable range.
+ */
+- if (dp_link->phy_params.v_level > DP_TRAIN_VOLTAGE_SWING_MAX) {
++ if (dp_link->phy_params.v_level > DP_TRAIN_LEVEL_MAX) {
+ drm_dbg_dp(link->drm_dev,
+ "Requested vSwingLevel=%d, change to %d\n",
+ dp_link->phy_params.v_level,
+- DP_TRAIN_VOLTAGE_SWING_MAX);
+- dp_link->phy_params.v_level = DP_TRAIN_VOLTAGE_SWING_MAX;
++ DP_TRAIN_LEVEL_MAX);
++ dp_link->phy_params.v_level = DP_TRAIN_LEVEL_MAX;
+ }
+
+- if (dp_link->phy_params.p_level > DP_TRAIN_PRE_EMPHASIS_MAX) {
++ if (dp_link->phy_params.p_level > DP_TRAIN_LEVEL_MAX) {
+ drm_dbg_dp(link->drm_dev,
+ "Requested preEmphasisLevel=%d, change to %d\n",
+ dp_link->phy_params.p_level,
+- DP_TRAIN_PRE_EMPHASIS_MAX);
+- dp_link->phy_params.p_level = DP_TRAIN_PRE_EMPHASIS_MAX;
++ DP_TRAIN_LEVEL_MAX);
++ dp_link->phy_params.p_level = DP_TRAIN_LEVEL_MAX;
+ }
+
+- if ((dp_link->phy_params.p_level > DP_TRAIN_PRE_EMPHASIS_LVL_1)
+- && (dp_link->phy_params.v_level ==
+- DP_TRAIN_VOLTAGE_SWING_LVL_2)) {
++ max_p_level = DP_TRAIN_LEVEL_MAX - dp_link->phy_params.v_level;
++ if (dp_link->phy_params.p_level > max_p_level) {
+ drm_dbg_dp(link->drm_dev,
+ "Requested preEmphasisLevel=%d, change to %d\n",
+ dp_link->phy_params.p_level,
+- DP_TRAIN_PRE_EMPHASIS_LVL_1);
+- dp_link->phy_params.p_level = DP_TRAIN_PRE_EMPHASIS_LVL_1;
++ max_p_level);
++ dp_link->phy_params.p_level = max_p_level;
+ }
+
+ drm_dbg_dp(link->drm_dev, "adjusted: v_level=%d, p_level=%d\n",
+diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h
+index 9dd4dd9265304..79c3a02b8dacd 100644
+--- a/drivers/gpu/drm/msm/dp/dp_link.h
++++ b/drivers/gpu/drm/msm/dp/dp_link.h
+@@ -19,19 +19,7 @@ struct dp_link_info {
+ unsigned long capabilities;
+ };
+
+-enum dp_link_voltage_level {
+- DP_TRAIN_VOLTAGE_SWING_LVL_0 = 0,
+- DP_TRAIN_VOLTAGE_SWING_LVL_1 = 1,
+- DP_TRAIN_VOLTAGE_SWING_LVL_2 = 2,
+- DP_TRAIN_VOLTAGE_SWING_MAX = DP_TRAIN_VOLTAGE_SWING_LVL_2,
+-};
+-
+-enum dp_link_preemaphasis_level {
+- DP_TRAIN_PRE_EMPHASIS_LVL_0 = 0,
+- DP_TRAIN_PRE_EMPHASIS_LVL_1 = 1,
+- DP_TRAIN_PRE_EMPHASIS_LVL_2 = 2,
+- DP_TRAIN_PRE_EMPHASIS_MAX = DP_TRAIN_PRE_EMPHASIS_LVL_2,
+-};
++#define DP_TRAIN_LEVEL_MAX 3
+
+ struct dp_link_test_video {
+ u32 test_video_pattern;
+diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c b/drivers/gpu/drm/mxsfb/lcdif_drv.c
+index 18de2f17e2491..6494e82707569 100644
+--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
++++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
+@@ -340,6 +340,9 @@ static int __maybe_unused lcdif_suspend(struct device *dev)
+ if (ret)
+ return ret;
+
++ if (pm_runtime_suspended(dev))
++ return 0;
++
+ return lcdif_rpm_suspend(dev);
+ }
+
+@@ -347,7 +350,8 @@ static int __maybe_unused lcdif_resume(struct device *dev)
+ {
+ struct drm_device *drm = dev_get_drvdata(dev);
+
+- lcdif_rpm_resume(dev);
++ if (!pm_runtime_suspended(dev))
++ lcdif_rpm_resume(dev);
+
+ return drm_mode_config_helper_resume(drm);
+ }
+diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c
+index 6a0a4d3b8902d..027867c2a8c5b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c
++++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/r535.c
+@@ -1080,7 +1080,7 @@ r535_dp_aux_xfer(struct nvkm_outp *outp, u8 type, u32 addr, u8 *data, u8 *psize)
+ ret = nvkm_gsp_rm_ctrl_push(&disp->rm.objcom, &ctrl, sizeof(*ctrl));
+ if (ret) {
+ nvkm_gsp_rm_ctrl_done(&disp->rm.objcom, ctrl);
+- return PTR_ERR(ctrl);
++ return ret;
+ }
+
+ memcpy(data, ctrl->data, size);
+diff --git a/drivers/gpu/drm/omapdrm/Kconfig b/drivers/gpu/drm/omapdrm/Kconfig
+index b715301ec79f6..6c49270cb290a 100644
+--- a/drivers/gpu/drm/omapdrm/Kconfig
++++ b/drivers/gpu/drm/omapdrm/Kconfig
+@@ -4,7 +4,7 @@ config DRM_OMAP
+ depends on DRM && OF
+ depends on ARCH_OMAP2PLUS
+ select DRM_KMS_HELPER
+- select FB_DMAMEM_HELPERS if DRM_FBDEV_EMULATION
++ select FB_DMAMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION
+ select VIDEOMODE_HELPERS
+ select HDMI
+ default n
+diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
+index 6b08b137af1ad..523be34682caf 100644
+--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
++++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
+@@ -51,6 +51,10 @@ static void pan_worker(struct work_struct *work)
+ omap_gem_roll(bo, fbi->var.yoffset * npages);
+ }
+
++FB_GEN_DEFAULT_DEFERRED_DMAMEM_OPS(omap_fbdev,
++ drm_fb_helper_damage_range,
++ drm_fb_helper_damage_area)
++
+ static int omap_fbdev_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *fbi)
+ {
+@@ -78,11 +82,9 @@ static int omap_fbdev_pan_display(struct fb_var_screeninfo *var,
+
+ static int omap_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+ {
+- struct drm_fb_helper *helper = info->par;
+- struct drm_framebuffer *fb = helper->fb;
+- struct drm_gem_object *bo = drm_gem_fb_get_obj(fb, 0);
++ vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
+
+- return drm_gem_mmap_obj(bo, omap_gem_mmap_size(bo), vma);
++ return fb_deferred_io_mmap(info, vma);
+ }
+
+ static void omap_fbdev_fb_destroy(struct fb_info *info)
+@@ -94,6 +96,7 @@ static void omap_fbdev_fb_destroy(struct fb_info *info)
+
+ DBG();
+
++ fb_deferred_io_cleanup(info);
+ drm_fb_helper_fini(helper);
+
+ omap_gem_unpin(bo);
+@@ -104,15 +107,19 @@ static void omap_fbdev_fb_destroy(struct fb_info *info)
+ kfree(fbdev);
+ }
+
++/*
++ * For now, we cannot use FB_DEFAULT_DEFERRED_OPS and fb_deferred_io_mmap()
++ * because we use write-combine.
++ */
+ static const struct fb_ops omap_fb_ops = {
+ .owner = THIS_MODULE,
+- __FB_DEFAULT_DMAMEM_OPS_RDWR,
++ __FB_DEFAULT_DEFERRED_OPS_RDWR(omap_fbdev),
+ .fb_check_var = drm_fb_helper_check_var,
+ .fb_set_par = drm_fb_helper_set_par,
+ .fb_setcmap = drm_fb_helper_setcmap,
+ .fb_blank = drm_fb_helper_blank,
+ .fb_pan_display = omap_fbdev_pan_display,
+- __FB_DEFAULT_DMAMEM_OPS_DRAW,
++ __FB_DEFAULT_DEFERRED_OPS_DRAW(omap_fbdev),
+ .fb_ioctl = drm_fb_helper_ioctl,
+ .fb_mmap = omap_fbdev_fb_mmap,
+ .fb_destroy = omap_fbdev_fb_destroy,
+@@ -213,6 +220,15 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
+ fbi->fix.smem_start = dma_addr;
+ fbi->fix.smem_len = bo->size;
+
++ /* deferred I/O */
++ helper->fbdefio.delay = HZ / 20;
++ helper->fbdefio.deferred_io = drm_fb_helper_deferred_io;
++
++ fbi->fbdefio = &helper->fbdefio;
++ ret = fb_deferred_io_init(fbi);
++ if (ret)
++ goto fail;
++
+ /* if we have DMM, then we can use it for scrolling by just
+ * shuffling pages around in DMM rather than doing sw blit.
+ */
+@@ -238,8 +254,20 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
+ return ret;
+ }
+
++static int omap_fbdev_dirty(struct drm_fb_helper *helper, struct drm_clip_rect *clip)
++{
++ if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2))
++ return 0;
++
++ if (helper->fb->funcs->dirty)
++ return helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, clip, 1);
++
++ return 0;
++}
++
+ static const struct drm_fb_helper_funcs omap_fb_helper_funcs = {
+ .fb_probe = omap_fbdev_create,
++ .fb_dirty = omap_fbdev_dirty,
+ };
+
+ static struct drm_fb_helper *get_fb(struct fb_info *fbi)
+diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
+index e5e3f0b9ca61d..49b8a2484d92b 100644
+--- a/drivers/gpu/drm/panel/panel-edp.c
++++ b/drivers/gpu/drm/panel/panel-edp.c
+@@ -397,6 +397,7 @@ static int panel_edp_suspend(struct device *dev)
+ {
+ struct panel_edp *p = dev_get_drvdata(dev);
+
++ drm_dp_dpcd_set_powered(p->aux, false);
+ gpiod_set_value_cansleep(p->enable_gpio, 0);
+ regulator_disable(p->supply);
+ p->unprepared_time = ktime_get_boottime();
+@@ -453,6 +454,7 @@ static int panel_edp_prepare_once(struct panel_edp *p)
+ }
+
+ gpiod_set_value_cansleep(p->enable_gpio, 1);
++ drm_dp_dpcd_set_powered(p->aux, true);
+
+ delay = p->desc->delay.hpd_reliable;
+ if (p->no_hpd)
+@@ -489,6 +491,7 @@ static int panel_edp_prepare_once(struct panel_edp *p)
+ return 0;
+
+ error:
++ drm_dp_dpcd_set_powered(p->aux, false);
+ gpiod_set_value_cansleep(p->enable_gpio, 0);
+ regulator_disable(p->supply);
+ p->unprepared_time = ktime_get_boottime();
+diff --git a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
+index 30919c872ac8d..8e0f5c3e3b98e 100644
+--- a/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
++++ b/drivers/gpu/drm/panel/panel-leadtek-ltk050h3146w.c
+@@ -295,8 +295,6 @@ static int ltk050h3148w_init_sequence(struct ltk050h3146w *ctx)
+ mipi_dsi_dcs_write_seq(dsi, 0xbd, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xc6, 0xef);
+ mipi_dsi_dcs_write_seq(dsi, 0xd4, 0x02);
+- mipi_dsi_dcs_write_seq(dsi, 0x11);
+- mipi_dsi_dcs_write_seq(dsi, 0x29);
+
+ ret = mipi_dsi_dcs_set_tear_on(dsi, 1);
+ if (ret < 0) {
+@@ -326,7 +324,8 @@ static const struct drm_display_mode ltk050h3148w_mode = {
+ static const struct ltk050h3146w_desc ltk050h3148w_data = {
+ .mode = <k050h3148w_mode,
+ .init = ltk050h3148w_init_sequence,
+- .mode_flags = MIPI_DSI_MODE_VIDEO_SYNC_PULSE | MIPI_DSI_MODE_VIDEO_BURST,
++ .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
++ MIPI_DSI_MODE_VIDEO_BURST,
+ };
+
+ static int ltk050h3146w_init_sequence(struct ltk050h3146w *ctx)
+diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35950.c b/drivers/gpu/drm/panel/panel-novatek-nt35950.c
+index 648ce92014265..028fdac293f77 100644
+--- a/drivers/gpu/drm/panel/panel-novatek-nt35950.c
++++ b/drivers/gpu/drm/panel/panel-novatek-nt35950.c
+@@ -556,10 +556,8 @@ static int nt35950_probe(struct mipi_dsi_device *dsi)
+ }
+ dsi_r_host = of_find_mipi_dsi_host_by_node(dsi_r);
+ of_node_put(dsi_r);
+- if (!dsi_r_host) {
+- dev_err(dev, "Cannot get secondary DSI host\n");
+- return -EPROBE_DEFER;
+- }
++ if (!dsi_r_host)
++ return dev_err_probe(dev, -EPROBE_DEFER, "Cannot get secondary DSI host\n");
+
+ nt->dsi[1] = mipi_dsi_device_register_full(dsi_r_host, info);
+ if (!nt->dsi[1]) {
+diff --git a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c
+index 5703f4712d96e..9c336c71562b9 100644
+--- a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c
++++ b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c
+@@ -72,6 +72,7 @@ static int atana33xc20_suspend(struct device *dev)
+ if (p->el3_was_on)
+ atana33xc20_wait(p->el_on3_off_time, 150);
+
++ drm_dp_dpcd_set_powered(p->aux, false);
+ ret = regulator_disable(p->supply);
+ if (ret)
+ return ret;
+@@ -93,6 +94,7 @@ static int atana33xc20_resume(struct device *dev)
+ ret = regulator_enable(p->supply);
+ if (ret)
+ return ret;
++ drm_dp_dpcd_set_powered(p->aux, true);
+ p->powered_on_time = ktime_get_boottime();
+
+ if (p->no_hpd) {
+@@ -107,19 +109,17 @@ static int atana33xc20_resume(struct device *dev)
+ if (hpd_asserted < 0)
+ ret = hpd_asserted;
+
+- if (ret)
++ if (ret) {
+ dev_warn(dev, "Error waiting for HPD GPIO: %d\n", ret);
+-
+- return ret;
+- }
+-
+- if (p->aux->wait_hpd_asserted) {
++ goto error;
++ }
++ } else if (p->aux->wait_hpd_asserted) {
+ ret = p->aux->wait_hpd_asserted(p->aux, HPD_MAX_US);
+
+- if (ret)
++ if (ret) {
+ dev_warn(dev, "Controller error waiting for HPD: %d\n", ret);
+-
+- return ret;
++ goto error;
++ }
+ }
+
+ /*
+@@ -131,6 +131,12 @@ static int atana33xc20_resume(struct device *dev)
+ * right times.
+ */
+ return 0;
++
++error:
++ drm_dp_dpcd_set_powered(p->aux, false);
++ regulator_disable(p->supply);
++
++ return ret;
+ }
+
+ static int atana33xc20_disable(struct drm_panel *panel)
+diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
+index 72fdab8adb088..228c5c48e1588 100644
+--- a/drivers/gpu/drm/panel/panel-simple.c
++++ b/drivers/gpu/drm/panel/panel-simple.c
+@@ -2564,6 +2564,9 @@ static const struct panel_desc innolux_g121x1_l03 = {
+ .unprepare = 200,
+ .disable = 400,
+ },
++ .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
++ .bus_flags = DRM_BUS_FLAG_DE_HIGH,
++ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+ };
+
+ static const struct display_timing innolux_g156hce_l01_timings = {
+diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+index fdd768bbd487c..62ebbdb16253d 100644
+--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
++++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+@@ -706,6 +706,8 @@ static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win,
+ const struct drm_format_info *info;
+ u16 hor_scl_mode, ver_scl_mode;
+ u16 hscl_filter_mode, vscl_filter_mode;
++ uint16_t cbcr_src_w = src_w;
++ uint16_t cbcr_src_h = src_h;
+ u8 gt2 = 0;
+ u8 gt4 = 0;
+ u32 val;
+@@ -763,27 +765,27 @@ static void vop2_setup_scale(struct vop2 *vop2, const struct vop2_win *win,
+ vop2_win_write(win, VOP2_WIN_YRGB_VSCL_FILTER_MODE, vscl_filter_mode);
+
+ if (info->is_yuv) {
+- src_w /= info->hsub;
+- src_h /= info->vsub;
++ cbcr_src_w /= info->hsub;
++ cbcr_src_h /= info->vsub;
+
+ gt4 = 0;
+ gt2 = 0;
+
+- if (src_h >= (4 * dst_h)) {
++ if (cbcr_src_h >= (4 * dst_h)) {
+ gt4 = 1;
+- src_h >>= 2;
+- } else if (src_h >= (2 * dst_h)) {
++ cbcr_src_h >>= 2;
++ } else if (cbcr_src_h >= (2 * dst_h)) {
+ gt2 = 1;
+- src_h >>= 1;
++ cbcr_src_h >>= 1;
+ }
+
+- hor_scl_mode = scl_get_scl_mode(src_w, dst_w);
+- ver_scl_mode = scl_get_scl_mode(src_h, dst_h);
++ hor_scl_mode = scl_get_scl_mode(cbcr_src_w, dst_w);
++ ver_scl_mode = scl_get_scl_mode(cbcr_src_h, dst_h);
+
+- val = vop2_scale_factor(src_w, dst_w);
++ val = vop2_scale_factor(cbcr_src_w, dst_w);
+ vop2_win_write(win, VOP2_WIN_SCALE_CBCR_X, val);
+
+- val = vop2_scale_factor(src_h, dst_h);
++ val = vop2_scale_factor(cbcr_src_h, dst_h);
+ vop2_win_write(win, VOP2_WIN_SCALE_CBCR_Y, val);
+
+ vop2_win_write(win, VOP2_WIN_VSD_CBCR_GT4, gt4);
+diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
+index f827f26543641..eff47465707be 100644
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -2739,6 +2739,8 @@ static int vc4_hdmi_audio_init(struct vc4_hdmi *vc4_hdmi)
+ index = 1;
+
+ addr = of_get_address(dev->of_node, index, NULL, NULL);
++ if (!addr)
++ return -EINVAL;
+
+ vc4_hdmi->audio.dma_data.addr = be32_to_cpup(addr) + mai_data->offset;
+ vc4_hdmi->audio.dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
+index 9dbe6f4cb2942..c89e6a2a58736 100644
+--- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
++++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
+@@ -227,6 +227,11 @@ static void amd_sfh_resume(struct amd_mp2_dev *mp2)
+ struct amd_mp2_sensor_info info;
+ int i, status;
+
++ if (!cl_data->is_any_sensor_enabled) {
++ amd_sfh_clear_intr(mp2);
++ return;
++ }
++
+ for (i = 0; i < cl_data->num_hid_devices; i++) {
+ if (cl_data->sensor_sts[i] == SENSOR_DISABLED) {
+ info.sensor_idx = cl_data->sensor_idx[i];
+@@ -252,6 +257,11 @@ static void amd_sfh_suspend(struct amd_mp2_dev *mp2)
+ struct amdtp_cl_data *cl_data = mp2->cl_data;
+ int i, status;
+
++ if (!cl_data->is_any_sensor_enabled) {
++ amd_sfh_clear_intr(mp2);
++ return;
++ }
++
+ for (i = 0; i < cl_data->num_hid_devices; i++) {
+ if (cl_data->sensor_idx[i] != HPD_IDX &&
+ cl_data->sensor_sts[i] == SENSOR_ENABLED) {
+diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c
+index f9cceaeffd081..da5ea5a23b087 100644
+--- a/drivers/hid/hid-mcp2221.c
++++ b/drivers/hid/hid-mcp2221.c
+@@ -944,9 +944,11 @@ static void mcp2221_hid_unregister(void *ptr)
+ /* This is needed to be sure hid_hw_stop() isn't called twice by the subsystem */
+ static void mcp2221_remove(struct hid_device *hdev)
+ {
++#if IS_REACHABLE(CONFIG_IIO)
+ struct mcp2221 *mcp = hid_get_drvdata(hdev);
+
+ cancel_delayed_work_sync(&mcp->init_work);
++#endif
+ }
+
+ #if IS_REACHABLE(CONFIG_IIO)
+diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c
+index ccc4032fb2b03..4b2c81b49b80e 100644
+--- a/drivers/hid/hid-nintendo.c
++++ b/drivers/hid/hid-nintendo.c
+@@ -481,10 +481,10 @@ static const struct joycon_ctlr_button_mapping n64con_button_mappings[] = {
+ { BTN_TR, JC_BTN_R, },
+ { BTN_TR2, JC_BTN_LSTICK, }, /* ZR */
+ { BTN_START, JC_BTN_PLUS, },
+- { BTN_FORWARD, JC_BTN_Y, }, /* C UP */
+- { BTN_BACK, JC_BTN_ZR, }, /* C DOWN */
+- { BTN_LEFT, JC_BTN_X, }, /* C LEFT */
+- { BTN_RIGHT, JC_BTN_MINUS, }, /* C RIGHT */
++ { BTN_SELECT, JC_BTN_Y, }, /* C UP */
++ { BTN_X, JC_BTN_ZR, }, /* C DOWN */
++ { BTN_Y, JC_BTN_X, }, /* C LEFT */
++ { BTN_C, JC_BTN_MINUS, }, /* C RIGHT */
+ { BTN_MODE, JC_BTN_HOME, },
+ { BTN_Z, JC_BTN_CAP, },
+ { /* sentinel */ },
+diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+index 65e7eeb2fa64e..ce5576ef3c861 100644
+--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
++++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+@@ -172,6 +172,11 @@ static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+
+ /* request and enable interrupt */
+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
++ if (ret < 0) {
++ dev_err(dev, "ISH: Failed to allocate IRQ vectors\n");
++ return ret;
++ }
++
+ if (!pdev->msi_enabled && !pdev->msix_enabled)
+ irq_flag = IRQF_SHARED;
+
+diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
+index 1e2cd7c8716e8..64ace0b968f07 100644
+--- a/drivers/infiniband/core/cma.c
++++ b/drivers/infiniband/core/cma.c
+@@ -715,8 +715,10 @@ cma_validate_port(struct ib_device *device, u32 port,
+ rcu_read_lock();
+ ndev = rcu_dereference(sgid_attr->ndev);
+ if (!net_eq(dev_net(ndev), dev_addr->net) ||
+- ndev->ifindex != bound_if_index)
++ ndev->ifindex != bound_if_index) {
++ rdma_put_gid_attr(sgid_attr);
+ sgid_attr = ERR_PTR(-ENODEV);
++ }
+ rcu_read_unlock();
+ goto out;
+ }
+diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+index 439d0c7c5d0ca..04258676d0726 100644
+--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
++++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+@@ -1013,7 +1013,8 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
+ hwq_attr.stride = sizeof(struct sq_sge);
+ hwq_attr.depth = bnxt_qplib_get_depth(sq);
+ hwq_attr.aux_stride = psn_sz;
+- hwq_attr.aux_depth = bnxt_qplib_set_sq_size(sq, qp->wqe_mode);
++ hwq_attr.aux_depth = psn_sz ? bnxt_qplib_set_sq_size(sq, qp->wqe_mode)
++ : 0;
+ /* Update msn tbl size */
+ if (BNXT_RE_HW_RETX(qp->dev_cap_flags) && psn_sz) {
+ hwq_attr.aux_depth = roundup_pow_of_two(bnxt_qplib_set_sq_size(sq, qp->wqe_mode));
+diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c
+index 1b6d16af8c12b..2517c972c651a 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_cq.c
++++ b/drivers/infiniband/hw/hns/hns_roce_cq.c
+@@ -151,7 +151,7 @@ static int alloc_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
+ return ret;
+ }
+
+- ret = xa_err(xa_store(&cq_table->array, hr_cq->cqn, hr_cq, GFP_KERNEL));
++ ret = xa_err(xa_store_irq(&cq_table->array, hr_cq->cqn, hr_cq, GFP_KERNEL));
+ if (ret) {
+ ibdev_err(ibdev, "failed to xa_store CQ, ret = %d.\n", ret);
+ goto err_put;
+@@ -164,7 +164,7 @@ static int alloc_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
+ return 0;
+
+ err_xa:
+- xa_erase(&cq_table->array, hr_cq->cqn);
++ xa_erase_irq(&cq_table->array, hr_cq->cqn);
+ err_put:
+ hns_roce_table_put(hr_dev, &cq_table->table, hr_cq->cqn);
+
+@@ -183,7 +183,7 @@ static void free_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
+ dev_err(dev, "DESTROY_CQ failed (%d) for CQN %06lx\n", ret,
+ hr_cq->cqn);
+
+- xa_erase(&cq_table->array, hr_cq->cqn);
++ xa_erase_irq(&cq_table->array, hr_cq->cqn);
+
+ /* Waiting interrupt process procedure carried out */
+ synchronize_irq(hr_dev->eq_table.eq[hr_cq->vector].irq);
+@@ -477,13 +477,6 @@ void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type)
+ struct ib_event event;
+ struct ib_cq *ibcq;
+
+- hr_cq = xa_load(&hr_dev->cq_table.array,
+- cqn & (hr_dev->caps.num_cqs - 1));
+- if (!hr_cq) {
+- dev_warn(dev, "async event for bogus CQ 0x%06x\n", cqn);
+- return;
+- }
+-
+ if (event_type != HNS_ROCE_EVENT_TYPE_CQ_ID_INVALID &&
+ event_type != HNS_ROCE_EVENT_TYPE_CQ_ACCESS_ERROR &&
+ event_type != HNS_ROCE_EVENT_TYPE_CQ_OVERFLOW) {
+@@ -492,7 +485,16 @@ void hns_roce_cq_event(struct hns_roce_dev *hr_dev, u32 cqn, int event_type)
+ return;
+ }
+
+- refcount_inc(&hr_cq->refcount);
++ xa_lock(&hr_dev->cq_table.array);
++ hr_cq = xa_load(&hr_dev->cq_table.array,
++ cqn & (hr_dev->caps.num_cqs - 1));
++ if (hr_cq)
++ refcount_inc(&hr_cq->refcount);
++ xa_unlock(&hr_dev->cq_table.array);
++ if (!hr_cq) {
++ dev_warn(dev, "async event for bogus CQ 0x%06x\n", cqn);
++ return;
++ }
+
+ ibcq = &hr_cq->ib_cq;
+ if (ibcq->event_handler) {
+diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.h b/drivers/infiniband/hw/hns/hns_roce_hem.h
+index 7d23d3c51da46..fea6d7d508b60 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_hem.h
++++ b/drivers/infiniband/hw/hns/hns_roce_hem.h
+@@ -61,16 +61,16 @@ enum {
+ (sizeof(struct scatterlist) + sizeof(void *)))
+
+ #define check_whether_bt_num_3(type, hop_num) \
+- (type < HEM_TYPE_MTT && hop_num == 2)
++ ((type) < HEM_TYPE_MTT && (hop_num) == 2)
+
+ #define check_whether_bt_num_2(type, hop_num) \
+- ((type < HEM_TYPE_MTT && hop_num == 1) || \
+- (type >= HEM_TYPE_MTT && hop_num == 2))
++ (((type) < HEM_TYPE_MTT && (hop_num) == 1) || \
++ ((type) >= HEM_TYPE_MTT && (hop_num) == 2))
+
+ #define check_whether_bt_num_1(type, hop_num) \
+- ((type < HEM_TYPE_MTT && hop_num == HNS_ROCE_HOP_NUM_0) || \
+- (type >= HEM_TYPE_MTT && hop_num == 1) || \
+- (type >= HEM_TYPE_MTT && hop_num == HNS_ROCE_HOP_NUM_0))
++ (((type) < HEM_TYPE_MTT && (hop_num) == HNS_ROCE_HOP_NUM_0) || \
++ ((type) >= HEM_TYPE_MTT && (hop_num) == 1) || \
++ ((type) >= HEM_TYPE_MTT && (hop_num) == HNS_ROCE_HOP_NUM_0))
+
+ struct hns_roce_hem_chunk {
+ struct list_head list;
+diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+index 34e58e09b15d8..f95ec4618fbed 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+@@ -2105,7 +2105,7 @@ static void apply_func_caps(struct hns_roce_dev *hr_dev)
+ caps->gmv_bt_num *
+ (HNS_HW_PAGE_SIZE / caps->gmv_entry_sz));
+
+- caps->gmv_entry_num = caps->gmv_bt_num * (PAGE_SIZE /
++ caps->gmv_entry_num = caps->gmv_bt_num * (HNS_HW_PAGE_SIZE /
+ caps->gmv_entry_sz);
+ } else {
+ u32 func_num = max_t(u32, 1, hr_dev->func_num);
+@@ -3715,8 +3715,9 @@ static void get_cqe_status(struct hns_roce_dev *hr_dev, struct hns_roce_qp *qp,
+ wc->status == IB_WC_WR_FLUSH_ERR))
+ return;
+
+- ibdev_err(&hr_dev->ib_dev, "error cqe status 0x%x:\n", cqe_status);
+- print_hex_dump(KERN_ERR, "", DUMP_PREFIX_NONE, 16, 4, cqe,
++ ibdev_err_ratelimited(&hr_dev->ib_dev, "error cqe status 0x%x:\n",
++ cqe_status);
++ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, 16, 4, cqe,
+ cq->cqe_size, false);
+ wc->vendor_err = hr_reg_read(cqe, CQE_SUB_STATUS);
+
+diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c
+index b55fe6911f9f1..a33d3cedbc944 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_main.c
++++ b/drivers/infiniband/hw/hns/hns_roce_main.c
+@@ -37,6 +37,7 @@
+ #include <rdma/ib_smi.h>
+ #include <rdma/ib_user_verbs.h>
+ #include <rdma/ib_cache.h>
++#include "hnae3.h"
+ #include "hns_roce_common.h"
+ #include "hns_roce_device.h"
+ #include "hns_roce_hem.h"
+diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c
+index 91cd580480fe2..0d42fd197c11e 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_mr.c
++++ b/drivers/infiniband/hw/hns/hns_roce_mr.c
+@@ -433,18 +433,18 @@ int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
+ struct ib_device *ibdev = &hr_dev->ib_dev;
+ struct hns_roce_mr *mr = to_hr_mr(ibmr);
+ struct hns_roce_mtr *mtr = &mr->pbl_mtr;
+- int ret = 0;
++ int ret, sg_num = 0;
+
+ mr->npages = 0;
+ mr->page_list = kvcalloc(mr->pbl_mtr.hem_cfg.buf_pg_count,
+ sizeof(dma_addr_t), GFP_KERNEL);
+ if (!mr->page_list)
+- return ret;
++ return sg_num;
+
+- ret = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, hns_roce_set_page);
+- if (ret < 1) {
++ sg_num = ib_sg_to_pages(ibmr, sg, sg_nents, sg_offset, hns_roce_set_page);
++ if (sg_num < 1) {
+ ibdev_err(ibdev, "failed to store sg pages %u %u, cnt = %d.\n",
+- mr->npages, mr->pbl_mtr.hem_cfg.buf_pg_count, ret);
++ mr->npages, mr->pbl_mtr.hem_cfg.buf_pg_count, sg_num);
+ goto err_page_list;
+ }
+
+@@ -455,17 +455,16 @@ int hns_roce_map_mr_sg(struct ib_mr *ibmr, struct scatterlist *sg, int sg_nents,
+ ret = hns_roce_mtr_map(hr_dev, mtr, mr->page_list, mr->npages);
+ if (ret) {
+ ibdev_err(ibdev, "failed to map sg mtr, ret = %d.\n", ret);
+- ret = 0;
++ sg_num = 0;
+ } else {
+ mr->pbl_mtr.hem_cfg.buf_pg_shift = (u32)ilog2(ibmr->page_size);
+- ret = mr->npages;
+ }
+
+ err_page_list:
+ kvfree(mr->page_list);
+ mr->page_list = NULL;
+
+- return ret;
++ return sg_num;
+ }
+
+ static void hns_roce_mw_free(struct hns_roce_dev *hr_dev,
+diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c
+index 4abae94778544..8f48c6723e07e 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_srq.c
++++ b/drivers/infiniband/hw/hns/hns_roce_srq.c
+@@ -123,7 +123,7 @@ static int alloc_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq)
+ return ret;
+ }
+
+- ret = xa_err(xa_store(&srq_table->xa, srq->srqn, srq, GFP_KERNEL));
++ ret = xa_err(xa_store_irq(&srq_table->xa, srq->srqn, srq, GFP_KERNEL));
+ if (ret) {
+ ibdev_err(ibdev, "failed to store SRQC, ret = %d.\n", ret);
+ goto err_put;
+@@ -136,7 +136,7 @@ static int alloc_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq)
+ return 0;
+
+ err_xa:
+- xa_erase(&srq_table->xa, srq->srqn);
++ xa_erase_irq(&srq_table->xa, srq->srqn);
+ err_put:
+ hns_roce_table_put(hr_dev, &srq_table->table, srq->srqn);
+
+@@ -154,7 +154,7 @@ static void free_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq)
+ dev_err(hr_dev->dev, "DESTROY_SRQ failed (%d) for SRQN %06lx\n",
+ ret, srq->srqn);
+
+- xa_erase(&srq_table->xa, srq->srqn);
++ xa_erase_irq(&srq_table->xa, srq->srqn);
+
+ if (refcount_dec_and_test(&srq->refcount))
+ complete(&srq->free);
+diff --git a/drivers/infiniband/hw/mana/cq.c b/drivers/infiniband/hw/mana/cq.c
+index 4a71e678d09c1..89fcc09ded8a4 100644
+--- a/drivers/infiniband/hw/mana/cq.c
++++ b/drivers/infiniband/hw/mana/cq.c
+@@ -39,37 +39,13 @@ int mana_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
+ }
+
+ cq->cqe = attr->cqe;
+- cq->umem = ib_umem_get(ibdev, ucmd.buf_addr, cq->cqe * COMP_ENTRY_SIZE,
+- IB_ACCESS_LOCAL_WRITE);
+- if (IS_ERR(cq->umem)) {
+- err = PTR_ERR(cq->umem);
+- ibdev_dbg(ibdev, "Failed to get umem for create cq, err %d\n",
+- err);
+- return err;
+- }
+-
+- err = mana_ib_create_zero_offset_dma_region(mdev, cq->umem, &cq->gdma_region);
++ err = mana_ib_create_queue(mdev, ucmd.buf_addr, cq->cqe * COMP_ENTRY_SIZE, &cq->queue);
+ if (err) {
+- ibdev_dbg(ibdev,
+- "Failed to create dma region for create cq, %d\n",
+- err);
+- goto err_release_umem;
++ ibdev_dbg(ibdev, "Failed to create queue for create cq, %d\n", err);
++ return err;
+ }
+
+- ibdev_dbg(ibdev,
+- "create_dma_region ret %d gdma_region 0x%llx\n",
+- err, cq->gdma_region);
+-
+- /*
+- * The CQ ID is not known at this time. The ID is generated at create_qp
+- */
+- cq->id = INVALID_QUEUE_ID;
+-
+ return 0;
+-
+-err_release_umem:
+- ib_umem_release(cq->umem);
+- return err;
+ }
+
+ int mana_ib_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
+@@ -78,24 +54,16 @@ int mana_ib_destroy_cq(struct ib_cq *ibcq, struct ib_udata *udata)
+ struct ib_device *ibdev = ibcq->device;
+ struct mana_ib_dev *mdev;
+ struct gdma_context *gc;
+- int err;
+
+ mdev = container_of(ibdev, struct mana_ib_dev, ib_dev);
+ gc = mdev_to_gc(mdev);
+
+- err = mana_ib_gd_destroy_dma_region(mdev, cq->gdma_region);
+- if (err) {
+- ibdev_dbg(ibdev,
+- "Failed to destroy dma region, %d\n", err);
+- return err;
++ if (cq->queue.id != INVALID_QUEUE_ID) {
++ kfree(gc->cq_table[cq->queue.id]);
++ gc->cq_table[cq->queue.id] = NULL;
+ }
+
+- if (cq->id != INVALID_QUEUE_ID) {
+- kfree(gc->cq_table[cq->id]);
+- gc->cq_table[cq->id] = NULL;
+- }
+-
+- ib_umem_release(cq->umem);
++ mana_ib_destroy_queue(mdev, &cq->queue);
+
+ return 0;
+ }
+@@ -113,8 +81,10 @@ int mana_ib_install_cq_cb(struct mana_ib_dev *mdev, struct mana_ib_cq *cq)
+ struct gdma_context *gc = mdev_to_gc(mdev);
+ struct gdma_queue *gdma_cq;
+
++ if (cq->queue.id >= gc->max_num_cqs)
++ return -EINVAL;
+ /* Create CQ table entry */
+- WARN_ON(gc->cq_table[cq->id]);
++ WARN_ON(gc->cq_table[cq->queue.id]);
+ gdma_cq = kzalloc(sizeof(*gdma_cq), GFP_KERNEL);
+ if (!gdma_cq)
+ return -ENOMEM;
+@@ -122,7 +92,7 @@ int mana_ib_install_cq_cb(struct mana_ib_dev *mdev, struct mana_ib_cq *cq)
+ gdma_cq->cq.context = cq;
+ gdma_cq->type = GDMA_CQ;
+ gdma_cq->cq.callback = mana_ib_cq_handler;
+- gdma_cq->id = cq->id;
+- gc->cq_table[cq->id] = gdma_cq;
++ gdma_cq->id = cq->queue.id;
++ gc->cq_table[cq->queue.id] = gdma_cq;
+ return 0;
+ }
+diff --git a/drivers/infiniband/hw/mana/main.c b/drivers/infiniband/hw/mana/main.c
+index 71e33feee61bb..4524c6b807487 100644
+--- a/drivers/infiniband/hw/mana/main.c
++++ b/drivers/infiniband/hw/mana/main.c
+@@ -237,6 +237,49 @@ void mana_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
+ ibdev_dbg(ibdev, "Failed to destroy doorbell page %d\n", ret);
+ }
+
++int mana_ib_create_queue(struct mana_ib_dev *mdev, u64 addr, u32 size,
++ struct mana_ib_queue *queue)
++{
++ struct ib_umem *umem;
++ int err;
++
++ queue->umem = NULL;
++ queue->id = INVALID_QUEUE_ID;
++ queue->gdma_region = GDMA_INVALID_DMA_REGION;
++
++ umem = ib_umem_get(&mdev->ib_dev, addr, size, IB_ACCESS_LOCAL_WRITE);
++ if (IS_ERR(umem)) {
++ err = PTR_ERR(umem);
++ ibdev_dbg(&mdev->ib_dev, "Failed to get umem, %d\n", err);
++ return err;
++ }
++
++ err = mana_ib_create_zero_offset_dma_region(mdev, umem, &queue->gdma_region);
++ if (err) {
++ ibdev_dbg(&mdev->ib_dev, "Failed to create dma region, %d\n", err);
++ goto free_umem;
++ }
++ queue->umem = umem;
++
++ ibdev_dbg(&mdev->ib_dev,
++ "create_dma_region ret %d gdma_region 0x%llx\n",
++ err, queue->gdma_region);
++
++ return 0;
++free_umem:
++ ib_umem_release(umem);
++ return err;
++}
++
++void mana_ib_destroy_queue(struct mana_ib_dev *mdev, struct mana_ib_queue *queue)
++{
++ /* Ignore return code as there is not much we can do about it.
++ * The error message is printed inside.
++ */
++ mana_ib_gd_destroy_dma_region(mdev, queue->gdma_region);
++ ib_umem_release(queue->umem);
++}
++
+ static int
+ mana_ib_gd_first_dma_region(struct mana_ib_dev *dev,
+ struct gdma_context *gc,
+diff --git a/drivers/infiniband/hw/mana/mana_ib.h b/drivers/infiniband/hw/mana/mana_ib.h
+index f83390eebb7d7..6acb5c281c368 100644
+--- a/drivers/infiniband/hw/mana/mana_ib.h
++++ b/drivers/infiniband/hw/mana/mana_ib.h
+@@ -45,6 +45,12 @@ struct mana_ib_adapter_caps {
+ u32 max_inline_data_size;
+ };
+
++struct mana_ib_queue {
++ struct ib_umem *umem;
++ u64 gdma_region;
++ u64 id;
++};
++
+ struct mana_ib_dev {
+ struct ib_device ib_dev;
+ struct gdma_dev *gdma_dev;
+@@ -82,10 +88,8 @@ struct mana_ib_mr {
+
+ struct mana_ib_cq {
+ struct ib_cq ibcq;
+- struct ib_umem *umem;
++ struct mana_ib_queue queue;
+ int cqe;
+- u64 gdma_region;
+- u64 id;
+ u32 comp_vector;
+ };
+
+@@ -169,6 +173,10 @@ int mana_ib_create_dma_region(struct mana_ib_dev *dev, struct ib_umem *umem,
+ int mana_ib_gd_destroy_dma_region(struct mana_ib_dev *dev,
+ mana_handle_t gdma_region);
+
++int mana_ib_create_queue(struct mana_ib_dev *mdev, u64 addr, u32 size,
++ struct mana_ib_queue *queue);
++void mana_ib_destroy_queue(struct mana_ib_dev *mdev, struct mana_ib_queue *queue);
++
+ struct ib_wq *mana_ib_create_wq(struct ib_pd *pd,
+ struct ib_wq_init_attr *init_attr,
+ struct ib_udata *udata);
+diff --git a/drivers/infiniband/hw/mana/qp.c b/drivers/infiniband/hw/mana/qp.c
+index 6e7627745c957..d7485ee6a6854 100644
+--- a/drivers/infiniband/hw/mana/qp.c
++++ b/drivers/infiniband/hw/mana/qp.c
+@@ -197,7 +197,7 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd,
+ wq_spec.gdma_region = wq->gdma_region;
+ wq_spec.queue_size = wq->wq_buf_size;
+
+- cq_spec.gdma_region = cq->gdma_region;
++ cq_spec.gdma_region = cq->queue.gdma_region;
+ cq_spec.queue_size = cq->cqe * COMP_ENTRY_SIZE;
+ cq_spec.modr_ctx_id = 0;
+ eq = &mpc->ac->eqs[cq->comp_vector % gc->max_num_queues];
+@@ -213,16 +213,16 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd,
+
+ /* The GDMA regions are now owned by the WQ object */
+ wq->gdma_region = GDMA_INVALID_DMA_REGION;
+- cq->gdma_region = GDMA_INVALID_DMA_REGION;
++ cq->queue.gdma_region = GDMA_INVALID_DMA_REGION;
+
+ wq->id = wq_spec.queue_index;
+- cq->id = cq_spec.queue_index;
++ cq->queue.id = cq_spec.queue_index;
+
+ ibdev_dbg(&mdev->ib_dev,
+ "ret %d rx_object 0x%llx wq id %llu cq id %llu\n",
+- ret, wq->rx_object, wq->id, cq->id);
++ ret, wq->rx_object, wq->id, cq->queue.id);
+
+- resp.entries[i].cqid = cq->id;
++ resp.entries[i].cqid = cq->queue.id;
+ resp.entries[i].wqid = wq->id;
+
+ mana_ind_table[i] = wq->rx_object;
+@@ -232,7 +232,7 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd,
+ if (ret)
+ goto fail;
+
+- gdma_cq_allocated[i] = gc->cq_table[cq->id];
++ gdma_cq_allocated[i] = gc->cq_table[cq->queue.id];
+ }
+ resp.num_entries = i;
+
+@@ -264,7 +264,7 @@ static int mana_ib_create_qp_rss(struct ib_qp *ibqp, struct ib_pd *pd,
+ wq = container_of(ibwq, struct mana_ib_wq, ibwq);
+ cq = container_of(ibcq, struct mana_ib_cq, ibcq);
+
+- gc->cq_table[cq->id] = NULL;
++ gc->cq_table[cq->queue.id] = NULL;
+ kfree(gdma_cq_allocated[i]);
+
+ mana_destroy_wq_obj(mpc, GDMA_RQ, wq->rx_object);
+@@ -374,7 +374,7 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+ wq_spec.gdma_region = qp->sq_gdma_region;
+ wq_spec.queue_size = ucmd.sq_buf_size;
+
+- cq_spec.gdma_region = send_cq->gdma_region;
++ cq_spec.gdma_region = send_cq->queue.gdma_region;
+ cq_spec.queue_size = send_cq->cqe * COMP_ENTRY_SIZE;
+ cq_spec.modr_ctx_id = 0;
+ eq_vec = send_cq->comp_vector % gc->max_num_queues;
+@@ -392,10 +392,10 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+
+ /* The GDMA regions are now owned by the WQ object */
+ qp->sq_gdma_region = GDMA_INVALID_DMA_REGION;
+- send_cq->gdma_region = GDMA_INVALID_DMA_REGION;
++ send_cq->queue.gdma_region = GDMA_INVALID_DMA_REGION;
+
+ qp->sq_id = wq_spec.queue_index;
+- send_cq->id = cq_spec.queue_index;
++ send_cq->queue.id = cq_spec.queue_index;
+
+ /* Create CQ table entry */
+ err = mana_ib_install_cq_cb(mdev, send_cq);
+@@ -404,10 +404,10 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+
+ ibdev_dbg(&mdev->ib_dev,
+ "ret %d qp->tx_object 0x%llx sq id %llu cq id %llu\n", err,
+- qp->tx_object, qp->sq_id, send_cq->id);
++ qp->tx_object, qp->sq_id, send_cq->queue.id);
+
+ resp.sqid = qp->sq_id;
+- resp.cqid = send_cq->id;
++ resp.cqid = send_cq->queue.id;
+ resp.tx_vp_offset = pd->tx_vp_offset;
+
+ err = ib_copy_to_udata(udata, &resp, sizeof(resp));
+@@ -422,7 +422,7 @@ static int mana_ib_create_qp_raw(struct ib_qp *ibqp, struct ib_pd *ibpd,
+
+ err_release_gdma_cq:
+ kfree(gdma_cq);
+- gc->cq_table[send_cq->id] = NULL;
++ gc->cq_table[send_cq->queue.id] = NULL;
+
+ err_destroy_wq_obj:
+ mana_destroy_wq_obj(mpc, GDMA_SQ, qp->tx_object);
+diff --git a/drivers/infiniband/hw/mlx5/mem.c b/drivers/infiniband/hw/mlx5/mem.c
+index 96ffbbaf0a73d..5a22be14d958f 100644
+--- a/drivers/infiniband/hw/mlx5/mem.c
++++ b/drivers/infiniband/hw/mlx5/mem.c
+@@ -30,6 +30,7 @@
+ * SOFTWARE.
+ */
+
++#include <linux/io.h>
+ #include <rdma/ib_umem_odp.h>
+ #include "mlx5_ib.h"
+ #include <linux/jiffies.h>
+@@ -108,7 +109,6 @@ static int post_send_nop(struct mlx5_ib_dev *dev, struct ib_qp *ibqp, u64 wr_id,
+ __be32 mmio_wqe[16] = {};
+ unsigned long flags;
+ unsigned int idx;
+- int i;
+
+ if (unlikely(dev->mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR))
+ return -EIO;
+@@ -148,10 +148,8 @@ static int post_send_nop(struct mlx5_ib_dev *dev, struct ib_qp *ibqp, u64 wr_id,
+ * we hit doorbell
+ */
+ wmb();
+- for (i = 0; i < 8; i++)
+- mlx5_write64(&mmio_wqe[i * 2],
+- bf->bfreg->map + bf->offset + i * 8);
+- io_stop_wc();
++ __iowrite64_copy(bf->bfreg->map + bf->offset, mmio_wqe,
++ sizeof(mmio_wqe) / 8);
+
+ bf->offset ^= bf->buf_size;
+
+diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
+index bbe79b86c7178..79ebafecca22a 100644
+--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
++++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
+@@ -643,9 +643,10 @@ struct mlx5_ib_mkey {
+ unsigned int ndescs;
+ struct wait_queue_head wait;
+ refcount_t usecount;
+- /* User Mkey must hold either a rb_key or a cache_ent. */
++ /* Cacheable user Mkey must hold either a rb_key or a cache_ent. */
+ struct mlx5r_cache_rb_key rb_key;
+ struct mlx5_cache_ent *cache_ent;
++ u8 cacheable : 1;
+ };
+
+ #define MLX5_IB_MTT_PRESENT (MLX5_IB_MTT_READ | MLX5_IB_MTT_WRITE)
+diff --git a/drivers/infiniband/hw/mlx5/mr.c b/drivers/infiniband/hw/mlx5/mr.c
+index a8ee2ca1f4a17..ecc111ed5d86e 100644
+--- a/drivers/infiniband/hw/mlx5/mr.c
++++ b/drivers/infiniband/hw/mlx5/mr.c
+@@ -1158,6 +1158,7 @@ static struct mlx5_ib_mr *alloc_cacheable_mr(struct ib_pd *pd,
+ if (IS_ERR(mr))
+ return mr;
+ mr->mmkey.rb_key = rb_key;
++ mr->mmkey.cacheable = true;
+ return mr;
+ }
+
+@@ -1168,6 +1169,7 @@ static struct mlx5_ib_mr *alloc_cacheable_mr(struct ib_pd *pd,
+ mr->ibmr.pd = pd;
+ mr->umem = umem;
+ mr->page_shift = order_base_2(page_size);
++ mr->mmkey.cacheable = true;
+ set_mr_fields(dev, mr, umem->length, access_flags, iova);
+
+ return mr;
+@@ -1570,7 +1572,8 @@ static bool can_use_umr_rereg_access(struct mlx5_ib_dev *dev,
+ unsigned int diffs = current_access_flags ^ target_access_flags;
+
+ if (diffs & ~(IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE |
+- IB_ACCESS_REMOTE_READ | IB_ACCESS_RELAXED_ORDERING))
++ IB_ACCESS_REMOTE_READ | IB_ACCESS_RELAXED_ORDERING |
++ IB_ACCESS_REMOTE_ATOMIC))
+ return false;
+ return mlx5r_umr_can_reconfig(dev, current_access_flags,
+ target_access_flags);
+@@ -1835,6 +1838,23 @@ static int cache_ent_find_and_store(struct mlx5_ib_dev *dev,
+ return ret;
+ }
+
++static int mlx5_revoke_mr(struct mlx5_ib_mr *mr)
++{
++ struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device);
++ struct mlx5_cache_ent *ent = mr->mmkey.cache_ent;
++
++ if (mr->mmkey.cacheable && !mlx5r_umr_revoke_mr(mr) && !cache_ent_find_and_store(dev, mr))
++ return 0;
++
++ if (ent) {
++ spin_lock_irq(&ent->mkeys_queue.lock);
++ ent->in_use--;
++ mr->mmkey.cache_ent = NULL;
++ spin_unlock_irq(&ent->mkeys_queue.lock);
++ }
++ return destroy_mkey(dev, mr);
++}
++
+ int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
+ {
+ struct mlx5_ib_mr *mr = to_mmr(ibmr);
+@@ -1880,16 +1900,9 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
+ }
+
+ /* Stop DMA */
+- if (mr->umem && mlx5r_umr_can_load_pas(dev, mr->umem->length))
+- if (mlx5r_umr_revoke_mr(mr) ||
+- cache_ent_find_and_store(dev, mr))
+- mr->mmkey.cache_ent = NULL;
+-
+- if (!mr->mmkey.cache_ent) {
+- rc = destroy_mkey(to_mdev(mr->ibmr.device), mr);
+- if (rc)
+- return rc;
+- }
++ rc = mlx5_revoke_mr(mr);
++ if (rc)
++ return rc;
+
+ if (mr->umem) {
+ bool is_odp = is_odp_mr(mr);
+diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c
+index d0bdc2d8adc82..acd2172bf092b 100644
+--- a/drivers/infiniband/sw/rxe/rxe_comp.c
++++ b/drivers/infiniband/sw/rxe/rxe_comp.c
+@@ -131,12 +131,12 @@ void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb)
+ {
+ int must_sched;
+
+- skb_queue_tail(&qp->resp_pkts, skb);
+-
+- must_sched = skb_queue_len(&qp->resp_pkts) > 1;
++ must_sched = skb_queue_len(&qp->resp_pkts) > 0;
+ if (must_sched != 0)
+ rxe_counter_inc(SKB_TO_PKT(skb)->rxe, RXE_CNT_COMPLETER_SCHED);
+
++ skb_queue_tail(&qp->resp_pkts, skb);
++
+ if (must_sched)
+ rxe_sched_task(&qp->comp.task);
+ else
+diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
+index cd59666158b18..e5827064ab1e2 100644
+--- a/drivers/infiniband/sw/rxe/rxe_net.c
++++ b/drivers/infiniband/sw/rxe/rxe_net.c
+@@ -366,18 +366,10 @@ static int rxe_send(struct sk_buff *skb, struct rxe_pkt_info *pkt)
+ rxe_get(pkt->qp);
+ atomic_inc(&pkt->qp->skb_out);
+
+- if (skb->protocol == htons(ETH_P_IP)) {
++ if (skb->protocol == htons(ETH_P_IP))
+ err = ip_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb);
+- } else if (skb->protocol == htons(ETH_P_IPV6)) {
++ else
+ err = ip6_local_out(dev_net(skb_dst(skb)->dev), skb->sk, skb);
+- } else {
+- rxe_dbg_qp(pkt->qp, "Unknown layer 3 protocol: %d\n",
+- skb->protocol);
+- atomic_dec(&pkt->qp->skb_out);
+- rxe_put(pkt->qp);
+- kfree_skb(skb);
+- return -EINVAL;
+- }
+
+ if (unlikely(net_xmit_eval(err))) {
+ rxe_dbg_qp(pkt->qp, "error sending packet: %d\n", err);
+diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
+index 48f86839d36a8..0930350522e38 100644
+--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
++++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
+@@ -888,6 +888,7 @@ static int rxe_post_send_kernel(struct rxe_qp *qp,
+ {
+ int err = 0;
+ unsigned long flags;
++ int good = 0;
+
+ spin_lock_irqsave(&qp->sq.sq_lock, flags);
+ while (ibwr) {
+@@ -895,12 +896,15 @@ static int rxe_post_send_kernel(struct rxe_qp *qp,
+ if (err) {
+ *bad_wr = ibwr;
+ break;
++ } else {
++ good++;
+ }
+ ibwr = ibwr->next;
+ }
+ spin_unlock_irqrestore(&qp->sq.sq_lock, flags);
+
+- if (!err)
++ /* kickoff processing of any posted wqes */
++ if (good)
+ rxe_sched_task(&qp->req.task);
+
+ spin_lock_irqsave(&qp->state_lock, flags);
+diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+index 4bd161e86f8dd..562df2b3ef187 100644
+--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
++++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+@@ -184,8 +184,12 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
+
+ ppriv = ipoib_priv(pdev);
+
+- snprintf(intf_name, sizeof(intf_name), "%s.%04x",
+- ppriv->dev->name, pkey);
++ /* If you increase IFNAMSIZ, update snprintf below
++ * to allow longer names.
++ */
++ BUILD_BUG_ON(IFNAMSIZ != 16);
++ snprintf(intf_name, sizeof(intf_name), "%.10s.%04x", ppriv->dev->name,
++ pkey);
+
+ ndev = ipoib_intf_alloc(ppriv->ca, ppriv->port, intf_name);
+ if (IS_ERR(ndev)) {
+diff --git a/drivers/input/input.c b/drivers/input/input.c
+index f71ea4fb173fd..3212c63dcf5ba 100644
+--- a/drivers/input/input.c
++++ b/drivers/input/input.c
+@@ -1378,19 +1378,19 @@ static int input_print_modalias_bits(char *buf, int size,
+ char name, const unsigned long *bm,
+ unsigned int min_bit, unsigned int max_bit)
+ {
+- int len = 0, i;
++ int bit = min_bit;
++ int len = 0;
+
+ len += snprintf(buf, max(size, 0), "%c", name);
+- for (i = min_bit; i < max_bit; i++)
+- if (bm[BIT_WORD(i)] & BIT_MASK(i))
+- len += snprintf(buf + len, max(size - len, 0), "%X,", i);
++ for_each_set_bit_from(bit, bm, max_bit)
++ len += snprintf(buf + len, max(size - len, 0), "%X,", bit);
+ return len;
+ }
+
+-static int input_print_modalias(char *buf, int size, const struct input_dev *id,
+- int add_cr)
++static int input_print_modalias_parts(char *buf, int size, int full_len,
++ const struct input_dev *id)
+ {
+- int len;
++ int len, klen, remainder, space;
+
+ len = snprintf(buf, max(size, 0),
+ "input:b%04Xv%04Xp%04Xe%04X-",
+@@ -1399,8 +1399,48 @@ static int input_print_modalias(char *buf, int size, const struct input_dev *id,
+
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'e', id->evbit, 0, EV_MAX);
+- len += input_print_modalias_bits(buf + len, size - len,
++
++ /*
++ * Calculate the remaining space in the buffer making sure we
++ * have place for the terminating 0.
++ */
++ space = max(size - (len + 1), 0);
++
++ klen = input_print_modalias_bits(buf + len, size - len,
+ 'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
++ len += klen;
++
++ /*
++ * If we have more data than we can fit in the buffer, check
++ * if we can trim key data to fit in the rest. We will indicate
++ * that key data is incomplete by adding "+" sign at the end, like
++ * this: * "k1,2,3,45,+,".
++ *
++ * Note that we shortest key info (if present) is "k+," so we
++ * can only try to trim if key data is longer than that.
++ */
++ if (full_len && size < full_len + 1 && klen > 3) {
++ remainder = full_len - len;
++ /*
++ * We can only trim if we have space for the remainder
++ * and also for at least "k+," which is 3 more characters.
++ */
++ if (remainder <= space - 3) {
++ /*
++ * We are guaranteed to have 'k' in the buffer, so
++ * we need at least 3 additional bytes for storing
++ * "+," in addition to the remainder.
++ */
++ for (int i = size - 1 - remainder - 3; i >= 0; i--) {
++ if (buf[i] == 'k' || buf[i] == ',') {
++ strcpy(buf + i + 1, "+,");
++ len = i + 3; /* Not counting '\0' */
++ break;
++ }
++ }
++ }
++ }
++
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'r', id->relbit, 0, REL_MAX);
+ len += input_print_modalias_bits(buf + len, size - len,
+@@ -1416,12 +1456,25 @@ static int input_print_modalias(char *buf, int size, const struct input_dev *id,
+ len += input_print_modalias_bits(buf + len, size - len,
+ 'w', id->swbit, 0, SW_MAX);
+
+- if (add_cr)
+- len += snprintf(buf + len, max(size - len, 0), "\n");
+-
+ return len;
+ }
+
++static int input_print_modalias(char *buf, int size, const struct input_dev *id)
++{
++ int full_len;
++
++ /*
++ * Printing is done in 2 passes: first one figures out total length
++ * needed for the modalias string, second one will try to trim key
++ * data in case when buffer is too small for the entire modalias.
++ * If the buffer is too small regardless, it will fill as much as it
++ * can (without trimming key data) into the buffer and leave it to
++ * the caller to figure out what to do with the result.
++ */
++ full_len = input_print_modalias_parts(NULL, 0, 0, id);
++ return input_print_modalias_parts(buf, size, full_len, id);
++}
++
+ static ssize_t input_dev_show_modalias(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+@@ -1429,7 +1482,9 @@ static ssize_t input_dev_show_modalias(struct device *dev,
+ struct input_dev *id = to_input_dev(dev);
+ ssize_t len;
+
+- len = input_print_modalias(buf, PAGE_SIZE, id, 1);
++ len = input_print_modalias(buf, PAGE_SIZE, id);
++ if (len < PAGE_SIZE - 2)
++ len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+
+ return min_t(int, len, PAGE_SIZE);
+ }
+@@ -1641,6 +1696,23 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
+ return 0;
+ }
+
++/*
++ * This is a pretty gross hack. When building uevent data the driver core
++ * may try adding more environment variables to kobj_uevent_env without
++ * telling us, so we have no idea how much of the buffer we can use to
++ * avoid overflows/-ENOMEM elsewhere. To work around this let's artificially
++ * reduce amount of memory we will use for the modalias environment variable.
++ *
++ * The potential additions are:
++ *
++ * SEQNUM=18446744073709551615 - (%llu - 28 bytes)
++ * HOME=/ (6 bytes)
++ * PATH=/sbin:/bin:/usr/sbin:/usr/bin (34 bytes)
++ *
++ * 68 bytes total. Allow extra buffer - 96 bytes
++ */
++#define UEVENT_ENV_EXTRA_LEN 96
++
+ static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
+ const struct input_dev *dev)
+ {
+@@ -1650,9 +1722,11 @@ static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
+ return -ENOMEM;
+
+ len = input_print_modalias(&env->buf[env->buflen - 1],
+- sizeof(env->buf) - env->buflen,
+- dev, 0);
+- if (len >= (sizeof(env->buf) - env->buflen))
++ (int)sizeof(env->buf) - env->buflen -
++ UEVENT_ENV_EXTRA_LEN,
++ dev);
++ if (len >= ((int)sizeof(env->buf) - env->buflen -
++ UEVENT_ENV_EXTRA_LEN))
+ return -ENOMEM;
+
+ env->buflen += len;
+diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c
+index 1fad51b51b0e1..c2de2f063cb8d 100644
+--- a/drivers/input/joystick/xpad.c
++++ b/drivers/input/joystick/xpad.c
+@@ -207,6 +207,7 @@ static const struct xpad_device {
+ { 0x0738, 0xcb29, "Saitek Aviator Stick AV8R02", 0, XTYPE_XBOX360 },
+ { 0x0738, 0xf738, "Super SFIV FightStick TE S", 0, XTYPE_XBOX360 },
+ { 0x07ff, 0xffff, "Mad Catz GamePad", 0, XTYPE_XBOX360 },
++ { 0x0b05, 0x1a38, "ASUS ROG RAIKIRI", 0, XTYPE_XBOXONE },
+ { 0x0c12, 0x0005, "Intec wireless", 0, XTYPE_XBOX },
+ { 0x0c12, 0x8801, "Nyko Xbox Controller", 0, XTYPE_XBOX },
+ { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX },
+@@ -482,6 +483,7 @@ static const struct usb_device_id xpad_table[] = {
+ { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */
+ XPAD_XBOXONE_VENDOR(0x0738), /* Mad Catz FightStick TE 2 */
+ XPAD_XBOX360_VENDOR(0x07ff), /* Mad Catz Gamepad */
++ XPAD_XBOXONE_VENDOR(0x0b05), /* ASUS controllers */
+ XPAD_XBOX360_VENDOR(0x0c12), /* Zeroplus X-Box 360 controllers */
+ XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f Xbox 360 controllers */
+ XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f Xbox One controllers */
+diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c
+index cda0c3ff5a288..2fbbaeb76d708 100644
+--- a/drivers/input/mouse/amimouse.c
++++ b/drivers/input/mouse/amimouse.c
+@@ -132,7 +132,13 @@ static void __exit amimouse_remove(struct platform_device *pdev)
+ input_unregister_device(dev);
+ }
+
+-static struct platform_driver amimouse_driver = {
++/*
++ * amimouse_remove() lives in .exit.text. For drivers registered via
++ * module_platform_driver_probe() this is ok because they cannot get unbound at
++ * runtime. So mark the driver struct with __refdata to prevent modpost
++ * triggering a section mismatch warning.
++ */
++static struct platform_driver amimouse_driver __refdata = {
+ .remove_new = __exit_p(amimouse_remove),
+ .driver = {
+ .name = "amiga-mouse",
+diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
+index ad33161f2374b..e606d250d1d55 100644
+--- a/drivers/iommu/iommu.c
++++ b/drivers/iommu/iommu.c
+@@ -3510,15 +3510,26 @@ EXPORT_SYMBOL_GPL(iommu_group_dma_owner_claimed);
+ static int __iommu_set_group_pasid(struct iommu_domain *domain,
+ struct iommu_group *group, ioasid_t pasid)
+ {
+- struct group_device *device;
+- int ret = 0;
++ struct group_device *device, *last_gdev;
++ int ret;
+
+ for_each_group_device(group, device) {
+ ret = domain->ops->set_dev_pasid(domain, device->dev, pasid);
+ if (ret)
+- break;
++ goto err_revert;
+ }
+
++ return 0;
++
++err_revert:
++ last_gdev = device;
++ for_each_group_device(group, device) {
++ const struct iommu_ops *ops = dev_iommu_ops(device->dev);
++
++ if (device == last_gdev)
++ break;
++ ops->remove_dev_pasid(device->dev, pasid);
++ }
+ return ret;
+ }
+
+@@ -3576,10 +3587,8 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
+ }
+
+ ret = __iommu_set_group_pasid(domain, group, pasid);
+- if (ret) {
+- __iommu_remove_group_pasid(group, pasid);
++ if (ret)
+ xa_erase(&group->pasid_array, pasid);
+- }
+ out_unlock:
+ mutex_unlock(&group->mutex);
+ return ret;
+diff --git a/drivers/irqchip/irq-alpine-msi.c b/drivers/irqchip/irq-alpine-msi.c
+index 9c8b1349ee17b..a1430ab60a8a3 100644
+--- a/drivers/irqchip/irq-alpine-msi.c
++++ b/drivers/irqchip/irq-alpine-msi.c
+@@ -165,7 +165,7 @@ static int alpine_msix_middle_domain_alloc(struct irq_domain *domain,
+ return 0;
+
+ err_sgi:
+- irq_domain_free_irqs_parent(domain, virq, i - 1);
++ irq_domain_free_irqs_parent(domain, virq, i);
+ alpine_msix_free_sgi(priv, sgi, nr_irqs);
+ return err;
+ }
+diff --git a/drivers/irqchip/irq-loongson-pch-msi.c b/drivers/irqchip/irq-loongson-pch-msi.c
+index 6e1e1f011bb29..dd4d699170f4e 100644
+--- a/drivers/irqchip/irq-loongson-pch-msi.c
++++ b/drivers/irqchip/irq-loongson-pch-msi.c
+@@ -136,7 +136,7 @@ static int pch_msi_middle_domain_alloc(struct irq_domain *domain,
+
+ err_hwirq:
+ pch_msi_free_hwirq(priv, hwirq, nr_irqs);
+- irq_domain_free_irqs_parent(domain, virq, i - 1);
++ irq_domain_free_irqs_parent(domain, virq, i);
+
+ return err;
+ }
+diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
+index db9270da5b8e9..b6ddf1d47cb4e 100644
+--- a/drivers/macintosh/via-macii.c
++++ b/drivers/macintosh/via-macii.c
+@@ -140,24 +140,19 @@ static int macii_probe(void)
+ /* Initialize the driver */
+ static int macii_init(void)
+ {
+- unsigned long flags;
+ int err;
+
+- local_irq_save(flags);
+-
+ err = macii_init_via();
+ if (err)
+- goto out;
++ return err;
+
+ err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB",
+ macii_interrupt);
+ if (err)
+- goto out;
++ return err;
+
+ macii_state = idle;
+-out:
+- local_irq_restore(flags);
+- return err;
++ return 0;
+ }
+
+ /* initialize the hardware */
+diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
+index 5eabdb06c6498..2ac43d1f1b92c 100644
+--- a/drivers/md/dm-delay.c
++++ b/drivers/md/dm-delay.c
+@@ -154,8 +154,10 @@ static void delay_dtr(struct dm_target *ti)
+ {
+ struct delay_c *dc = ti->private;
+
+- if (dc->kdelayd_wq)
++ if (dc->kdelayd_wq) {
++ timer_shutdown_sync(&dc->delay_timer);
+ destroy_workqueue(dc->kdelayd_wq);
++ }
+
+ if (dc->read.dev)
+ dm_put_device(ti, dc->read.dev);
+@@ -240,19 +242,18 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ ret = delay_class_ctr(ti, &dc->flush, argv);
+ if (ret)
+ goto bad;
+- max_delay = max(max_delay, dc->write.delay);
+- max_delay = max(max_delay, dc->flush.delay);
+ goto out;
+ }
+
+ ret = delay_class_ctr(ti, &dc->write, argv + 3);
+ if (ret)
+ goto bad;
++ max_delay = max(max_delay, dc->write.delay);
++
+ if (argc == 6) {
+ ret = delay_class_ctr(ti, &dc->flush, argv + 3);
+ if (ret)
+ goto bad;
+- max_delay = max(max_delay, dc->flush.delay);
+ goto out;
+ }
+
+@@ -267,8 +268,7 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+ * In case of small requested delays, use kthread instead of
+ * timers and workqueue to achieve better latency.
+ */
+- dc->worker = kthread_create(&flush_worker_fn, dc,
+- "dm-delay-flush-worker");
++ dc->worker = kthread_run(&flush_worker_fn, dc, "dm-delay-flush-worker");
+ if (IS_ERR(dc->worker)) {
+ ret = PTR_ERR(dc->worker);
+ dc->worker = NULL;
+@@ -335,7 +335,7 @@ static void delay_presuspend(struct dm_target *ti)
+ mutex_unlock(&delayed_bios_lock);
+
+ if (!delay_is_fast(dc))
+- del_timer_sync(&dc->delay_timer);
++ timer_delete(&dc->delay_timer);
+ flush_delayed_bios(dc, true);
+ }
+
+diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
+index a4976ceae8688..ee67da44641b5 100644
+--- a/drivers/md/md-bitmap.c
++++ b/drivers/md/md-bitmap.c
+@@ -1427,7 +1427,7 @@ __acquires(bitmap->lock)
+ sector_t chunk = offset >> bitmap->chunkshift;
+ unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
+ unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT;
+- sector_t csize;
++ sector_t csize = ((sector_t)1) << bitmap->chunkshift;
+ int err;
+
+ if (page >= bitmap->pages) {
+@@ -1436,6 +1436,7 @@ __acquires(bitmap->lock)
+ * End-of-device while looking for a whole page or
+ * user set a huge number to sysfs bitmap_set_bits.
+ */
++ *blocks = csize - (offset & (csize - 1));
+ return NULL;
+ }
+ err = md_bitmap_checkpage(bitmap, page, create, 0);
+@@ -1444,8 +1445,7 @@ __acquires(bitmap->lock)
+ bitmap->bp[page].map == NULL)
+ csize = ((sector_t)1) << (bitmap->chunkshift +
+ PAGE_COUNTER_SHIFT);
+- else
+- csize = ((sector_t)1) << bitmap->chunkshift;
++
+ *blocks = csize - (offset & (csize - 1));
+
+ if (err < 0)
+diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c
+index f548b1bb75fb9..e932d25ca7b3a 100644
+--- a/drivers/media/i2c/et8ek8/et8ek8_driver.c
++++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c
+@@ -1475,7 +1475,7 @@ static int et8ek8_probe(struct i2c_client *client)
+ return ret;
+ }
+
+-static void __exit et8ek8_remove(struct i2c_client *client)
++static void et8ek8_remove(struct i2c_client *client)
+ {
+ struct v4l2_subdev *subdev = i2c_get_clientdata(client);
+ struct et8ek8_sensor *sensor = to_et8ek8_sensor(subdev);
+@@ -1517,7 +1517,7 @@ static struct i2c_driver et8ek8_i2c_driver = {
+ .of_match_table = et8ek8_of_table,
+ },
+ .probe = et8ek8_probe,
+- .remove = __exit_p(et8ek8_remove),
++ .remove = et8ek8_remove,
+ .id_table = et8ek8_id_table,
+ };
+
+diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
+index ed08bf4178f08..d5478779b3103 100644
+--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
++++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
+@@ -1789,11 +1789,6 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
+
+ v4l2_async_nf_init(&cio2->notifier, &cio2->v4l2_dev);
+
+- /* Register notifier for subdevices we care */
+- r = cio2_parse_firmware(cio2);
+- if (r)
+- goto fail_clean_notifier;
+-
+ r = devm_request_irq(dev, pci_dev->irq, cio2_irq, IRQF_SHARED,
+ CIO2_NAME, cio2);
+ if (r) {
+@@ -1801,6 +1796,11 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
+ goto fail_clean_notifier;
+ }
+
++ /* Register notifier for subdevices we care */
++ r = cio2_parse_firmware(cio2);
++ if (r)
++ goto fail_clean_notifier;
++
+ pm_runtime_put_noidle(dev);
+ pm_runtime_allow(dev);
+
+diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c
+index 7481f553f9595..24ec576dc3bff 100644
+--- a/drivers/media/pci/ngene/ngene-core.c
++++ b/drivers/media/pci/ngene/ngene-core.c
+@@ -1488,7 +1488,9 @@ static int init_channel(struct ngene_channel *chan)
+ }
+
+ if (dev->ci.en && (io & NGENE_IO_TSOUT)) {
+- dvb_ca_en50221_init(adapter, dev->ci.en, 0, 1);
++ ret = dvb_ca_en50221_init(adapter, dev->ci.en, 0, 1);
++ if (ret != 0)
++ goto err;
+ set_transfer(chan, 1);
+ chan->dev->channel[2].DataFormatFlags = DF_SWAP32;
+ set_transfer(&chan->dev->channel[2], 1);
+diff --git a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
+index 0ea5fa956fe9a..5be75bd4add39 100644
+--- a/drivers/media/platform/cadence/cdns-csi2rx.c
++++ b/drivers/media/platform/cadence/cdns-csi2rx.c
+@@ -235,10 +235,6 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
+
+ writel(reg, csi2rx->base + CSI2RX_STATIC_CFG_REG);
+
+- ret = v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, true);
+- if (ret)
+- goto err_disable_pclk;
+-
+ /* Enable DPHY clk and data lanes. */
+ if (csi2rx->dphy) {
+ reg = CSI2RX_DPHY_CL_EN | CSI2RX_DPHY_CL_RST;
+@@ -248,6 +244,13 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
+ }
+
+ writel(reg, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG);
++
++ ret = csi2rx_configure_ext_dphy(csi2rx);
++ if (ret) {
++ dev_err(csi2rx->dev,
++ "Failed to configure external DPHY: %d\n", ret);
++ goto err_disable_pclk;
++ }
+ }
+
+ /*
+@@ -287,14 +290,9 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
+
+ reset_control_deassert(csi2rx->sys_rst);
+
+- if (csi2rx->dphy) {
+- ret = csi2rx_configure_ext_dphy(csi2rx);
+- if (ret) {
+- dev_err(csi2rx->dev,
+- "Failed to configure external DPHY: %d\n", ret);
+- goto err_disable_sysclk;
+- }
+- }
++ ret = v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, true);
++ if (ret)
++ goto err_disable_sysclk;
+
+ clk_disable_unprepare(csi2rx->p_clk);
+
+@@ -308,6 +306,10 @@ static int csi2rx_start(struct csi2rx_priv *csi2rx)
+ clk_disable_unprepare(csi2rx->pixel_clk[i - 1]);
+ }
+
++ if (csi2rx->dphy) {
++ writel(0, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG);
++ phy_power_off(csi2rx->dphy);
++ }
+ err_disable_pclk:
+ clk_disable_unprepare(csi2rx->p_clk);
+
+diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
+index 792336dada447..997a66318a293 100644
+--- a/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
++++ b/drivers/media/platform/renesas/rcar-vin/rcar-vin.h
+@@ -59,7 +59,7 @@ enum rvin_isp_id {
+
+ #define RVIN_REMOTES_MAX \
+ (((unsigned int)RVIN_CSI_MAX) > ((unsigned int)RVIN_ISP_MAX) ? \
+- RVIN_CSI_MAX : RVIN_ISP_MAX)
++ (unsigned int)RVIN_CSI_MAX : (unsigned int)RVIN_ISP_MAX)
+
+ /**
+ * enum rvin_dma_state - DMA states
+diff --git a/drivers/media/radio/radio-shark2.c b/drivers/media/radio/radio-shark2.c
+index f1c5c0a6a335c..e3e6aa87fe081 100644
+--- a/drivers/media/radio/radio-shark2.c
++++ b/drivers/media/radio/radio-shark2.c
+@@ -62,7 +62,7 @@ struct shark_device {
+ #ifdef SHARK_USE_LEDS
+ struct work_struct led_work;
+ struct led_classdev leds[NO_LEDS];
+- char led_names[NO_LEDS][32];
++ char led_names[NO_LEDS][64];
+ atomic_t brightness[NO_LEDS];
+ unsigned long brightness_new;
+ #endif
+diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
+index bbd90123a4e76..91a41aa3ced24 100644
+--- a/drivers/media/usb/uvc/uvc_driver.c
++++ b/drivers/media/usb/uvc/uvc_driver.c
+@@ -14,6 +14,7 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/usb.h>
++#include <linux/usb/quirks.h>
+ #include <linux/usb/uvc.h>
+ #include <linux/videodev2.h>
+ #include <linux/vmalloc.h>
+@@ -2232,6 +2233,9 @@ static int uvc_probe(struct usb_interface *intf,
+ goto error;
+ }
+
++ if (dev->quirks & UVC_QUIRK_NO_RESET_RESUME)
++ udev->quirks &= ~USB_QUIRK_RESET_RESUME;
++
+ uvc_dbg(dev, PROBE, "UVC device initialized\n");
+ usb_enable_autosuspend(udev);
+ return 0;
+@@ -2574,6 +2578,33 @@ static const struct usb_device_id uvc_ids[] = {
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 0,
+ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_RESTORE_CTRLS_ON_INIT) },
++ /* Logitech Rally Bar Huddle */
++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
++ | USB_DEVICE_ID_MATCH_INT_INFO,
++ .idVendor = 0x046d,
++ .idProduct = 0x087c,
++ .bInterfaceClass = USB_CLASS_VIDEO,
++ .bInterfaceSubClass = 1,
++ .bInterfaceProtocol = 0,
++ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_NO_RESET_RESUME) },
++ /* Logitech Rally Bar */
++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
++ | USB_DEVICE_ID_MATCH_INT_INFO,
++ .idVendor = 0x046d,
++ .idProduct = 0x089b,
++ .bInterfaceClass = USB_CLASS_VIDEO,
++ .bInterfaceSubClass = 1,
++ .bInterfaceProtocol = 0,
++ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_NO_RESET_RESUME) },
++ /* Logitech Rally Bar Mini */
++ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
++ | USB_DEVICE_ID_MATCH_INT_INFO,
++ .idVendor = 0x046d,
++ .idProduct = 0x08d3,
++ .bInterfaceClass = USB_CLASS_VIDEO,
++ .bInterfaceSubClass = 1,
++ .bInterfaceProtocol = 0,
++ .driver_info = UVC_INFO_QUIRK(UVC_QUIRK_NO_RESET_RESUME) },
+ /* Chicony CNF7129 (Asus EEE 100HE) */
+ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
+index 6fb0a78b1b009..88218693f6f0b 100644
+--- a/drivers/media/usb/uvc/uvcvideo.h
++++ b/drivers/media/usb/uvc/uvcvideo.h
+@@ -73,6 +73,7 @@
+ #define UVC_QUIRK_FORCE_Y8 0x00000800
+ #define UVC_QUIRK_FORCE_BPP 0x00001000
+ #define UVC_QUIRK_WAKE_AUTOSUSPEND 0x00002000
++#define UVC_QUIRK_NO_RESET_RESUME 0x00004000
+
+ /* Format flags */
+ #define UVC_FMT_FLAG_COMPRESSED 0x00000001
+diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
+index 4c6198c48dd61..45836f0a2b0a7 100644
+--- a/drivers/media/v4l2-core/v4l2-subdev.c
++++ b/drivers/media/v4l2-core/v4l2-subdev.c
+@@ -732,6 +732,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
+ memset(&sel, 0, sizeof(sel));
+ sel.which = crop->which;
+ sel.pad = crop->pad;
++ sel.stream = crop->stream;
+ sel.target = V4L2_SEL_TGT_CROP;
+
+ rval = v4l2_subdev_call(
+@@ -756,6 +757,7 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg,
+ memset(&sel, 0, sizeof(sel));
+ sel.which = crop->which;
+ sel.pad = crop->pad;
++ sel.stream = crop->stream;
+ sel.target = V4L2_SEL_TGT_CROP;
+ sel.r = crop->rect;
+
+diff --git a/drivers/misc/lkdtm/Makefile b/drivers/misc/lkdtm/Makefile
+index 95ef971b5e1cb..b28701138b4bc 100644
+--- a/drivers/misc/lkdtm/Makefile
++++ b/drivers/misc/lkdtm/Makefile
+@@ -19,7 +19,7 @@ KASAN_SANITIZE_rodata.o := n
+ KCSAN_SANITIZE_rodata.o := n
+ KCOV_INSTRUMENT_rodata.o := n
+ OBJECT_FILES_NON_STANDARD_rodata.o := y
+-CFLAGS_REMOVE_rodata.o += $(CC_FLAGS_LTO) $(RETHUNK_CFLAGS)
++CFLAGS_REMOVE_rodata.o += $(CC_FLAGS_LTO) $(RETHUNK_CFLAGS) $(CC_FLAGS_CFI)
+
+ OBJCOPYFLAGS :=
+ OBJCOPYFLAGS_rodata_objcopy.o := \
+diff --git a/drivers/misc/lkdtm/perms.c b/drivers/misc/lkdtm/perms.c
+index b93404d656509..5b861dbff27e9 100644
+--- a/drivers/misc/lkdtm/perms.c
++++ b/drivers/misc/lkdtm/perms.c
+@@ -61,7 +61,7 @@ static void *setup_function_descriptor(func_desc_t *fdesc, void *dst)
+ return fdesc;
+ }
+
+-static noinline void execute_location(void *dst, bool write)
++static noinline __nocfi void execute_location(void *dst, bool write)
+ {
+ void (*func)(void);
+ func_desc_t fdesc;
+diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
+index 0de87bc638405..6d5c755411de0 100644
+--- a/drivers/mtd/mtdcore.c
++++ b/drivers/mtd/mtdcore.c
+@@ -956,8 +956,10 @@ static int mtd_otp_nvmem_add(struct mtd_info *mtd)
+
+ if (mtd->_get_user_prot_info && mtd->_read_user_prot_reg) {
+ size = mtd_otp_size(mtd, true);
+- if (size < 0)
+- return size;
++ if (size < 0) {
++ err = size;
++ goto err;
++ }
+
+ if (size > 0) {
+ nvmem = mtd_otp_nvmem_register(mtd, "user-otp", size,
+diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
+index 39076735a3fbb..9695f07b5eb26 100644
+--- a/drivers/mtd/nand/raw/nand_hynix.c
++++ b/drivers/mtd/nand/raw/nand_hynix.c
+@@ -402,7 +402,7 @@ static int hynix_nand_rr_init(struct nand_chip *chip)
+ if (ret)
+ pr_warn("failed to initialize read-retry infrastructure");
+
+- return 0;
++ return ret;
+ }
+
+ static void hynix_nand_extract_oobsize(struct nand_chip *chip,
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
+index 967d9136313f4..2ad9e4cd7b304 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -3135,6 +3135,7 @@ static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip)
+ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
+ {
+ struct gpio_desc *gpiod = chip->reset;
++ int err;
+
+ /* If there is a GPIO connected to the reset pin, toggle it */
+ if (gpiod) {
+@@ -3143,17 +3144,26 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip)
+ * mid-byte, causing the first EEPROM read after the reset
+ * from the wrong location resulting in the switch booting
+ * to wrong mode and inoperable.
++ * For this reason, switch families with EEPROM support
++ * generally wait for EEPROM loads to complete as their pre-
++ * and post-reset handlers.
+ */
+- if (chip->info->ops->get_eeprom)
+- mv88e6xxx_g2_eeprom_wait(chip);
++ if (chip->info->ops->hardware_reset_pre) {
++ err = chip->info->ops->hardware_reset_pre(chip);
++ if (err)
++ dev_err(chip->dev, "pre-reset error: %d\n", err);
++ }
+
+ gpiod_set_value_cansleep(gpiod, 1);
+ usleep_range(10000, 20000);
+ gpiod_set_value_cansleep(gpiod, 0);
+ usleep_range(10000, 20000);
+
+- if (chip->info->ops->get_eeprom)
+- mv88e6xxx_g2_eeprom_wait(chip);
++ if (chip->info->ops->hardware_reset_post) {
++ err = chip->info->ops->hardware_reset_post(chip);
++ if (err)
++ dev_err(chip->dev, "post-reset error: %d\n", err);
++ }
+ }
+ }
+
+@@ -4380,6 +4390,8 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
+ .watchdog_ops = &mv88e6390_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6390_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+@@ -4570,6 +4582,8 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
+ .watchdog_ops = &mv88e6097_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6352_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+@@ -4670,6 +4684,8 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
+ .watchdog_ops = &mv88e6097_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6352_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+@@ -4764,6 +4780,8 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
+ .watchdog_ops = &mv88e6390_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6390_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+@@ -4822,6 +4840,8 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
+ .watchdog_ops = &mv88e6390_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6390_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+@@ -4878,6 +4898,8 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
+ .watchdog_ops = &mv88e6390_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6390_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+@@ -4937,6 +4959,8 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
+ .watchdog_ops = &mv88e6097_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6352_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+@@ -4990,6 +5014,8 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
+ .watchdog_ops = &mv88e6250_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6250_g1_wait_eeprom_done_prereset,
++ .hardware_reset_post = mv88e6xxx_g1_wait_eeprom_done,
+ .reset = mv88e6250_g1_reset,
+ .vtu_getnext = mv88e6185_g1_vtu_getnext,
+ .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
+@@ -5037,6 +5063,8 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
+ .watchdog_ops = &mv88e6390_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6390_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+@@ -5096,6 +5124,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
+ .watchdog_ops = &mv88e6390_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .vtu_getnext = mv88e6185_g1_vtu_getnext,
+ .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
+@@ -5142,6 +5172,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
+ .set_egress_port = mv88e6095_g1_set_egress_port,
+ .watchdog_ops = &mv88e6390_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .vtu_getnext = mv88e6185_g1_vtu_getnext,
+ .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
+@@ -5192,6 +5224,8 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
+ .watchdog_ops = &mv88e6390_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6390_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+@@ -5347,6 +5381,8 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
+ .watchdog_ops = &mv88e6097_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6352_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+@@ -5409,6 +5445,8 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
+ .watchdog_ops = &mv88e6390_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6390_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+@@ -5471,6 +5509,8 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
+ .watchdog_ops = &mv88e6390_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6390_g1_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6390_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+@@ -5536,6 +5576,8 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
+ .watchdog_ops = &mv88e6393x_watchdog_ops,
+ .mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu,
+ .pot_clear = mv88e6xxx_g2_pot_clear,
++ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
++ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+ .rmu_disable = mv88e6390_g1_rmu_disable,
+ .atu_get_hash = mv88e6165_g1_atu_get_hash,
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
+index 85eb293381a7e..c34caf9815c5c 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.h
++++ b/drivers/net/dsa/mv88e6xxx/chip.h
+@@ -487,6 +487,12 @@ struct mv88e6xxx_ops {
+ int (*ppu_enable)(struct mv88e6xxx_chip *chip);
+ int (*ppu_disable)(struct mv88e6xxx_chip *chip);
+
++ /* Additional handlers to run before and after hard reset, to make sure
++ * that the switch and EEPROM are in a good state.
++ */
++ int (*hardware_reset_pre)(struct mv88e6xxx_chip *chip);
++ int (*hardware_reset_post)(struct mv88e6xxx_chip *chip);
++
+ /* Switch Software Reset */
+ int (*reset)(struct mv88e6xxx_chip *chip);
+
+diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c
+index 49444a72ff095..9820cd5967574 100644
+--- a/drivers/net/dsa/mv88e6xxx/global1.c
++++ b/drivers/net/dsa/mv88e6xxx/global1.c
+@@ -75,6 +75,95 @@ static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
+ return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1);
+ }
+
++static int mv88e6250_g1_eeprom_reload(struct mv88e6xxx_chip *chip)
++{
++ /* MV88E6185_G1_CTL1_RELOAD_EEPROM is also valid for 88E6250 */
++ int bit = __bf_shf(MV88E6185_G1_CTL1_RELOAD_EEPROM);
++ u16 val;
++ int err;
++
++ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val);
++ if (err)
++ return err;
++
++ val |= MV88E6185_G1_CTL1_RELOAD_EEPROM;
++
++ err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val);
++ if (err)
++ return err;
++
++ return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_CTL1, bit, 0);
++}
++
++/* Returns 0 when done, -EBUSY when waiting, other negative codes on error */
++static int mv88e6xxx_g1_is_eeprom_done(struct mv88e6xxx_chip *chip)
++{
++ u16 val;
++ int err;
++
++ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val);
++ if (err < 0) {
++ dev_err(chip->dev, "Error reading status");
++ return err;
++ }
++
++ /* If the switch is still resetting, it may not
++ * respond on the bus, and so MDIO read returns
++ * 0xffff. Differentiate between that, and waiting for
++ * the EEPROM to be done by bit 0 being set.
++ */
++ if (val == 0xffff || !(val & BIT(MV88E6XXX_G1_STS_IRQ_EEPROM_DONE)))
++ return -EBUSY;
++
++ return 0;
++}
++
++/* As the EEInt (EEPROM done) flag clears on read if the status register, this
++ * function must be called directly after a hard reset or EEPROM ReLoad request,
++ * or the done condition may have been missed
++ */
++int mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip)
++{
++ const unsigned long timeout = jiffies + 1 * HZ;
++ int ret;
++
++ /* Wait up to 1 second for the switch to finish reading the
++ * EEPROM.
++ */
++ while (time_before(jiffies, timeout)) {
++ ret = mv88e6xxx_g1_is_eeprom_done(chip);
++ if (ret != -EBUSY)
++ return ret;
++ }
++
++ dev_err(chip->dev, "Timeout waiting for EEPROM done");
++ return -ETIMEDOUT;
++}
++
++int mv88e6250_g1_wait_eeprom_done_prereset(struct mv88e6xxx_chip *chip)
++{
++ int ret;
++
++ ret = mv88e6xxx_g1_is_eeprom_done(chip);
++ if (ret != -EBUSY)
++ return ret;
++
++ /* Pre-reset, we don't know the state of the switch - when
++ * mv88e6xxx_g1_is_eeprom_done() returns -EBUSY, that may be because
++ * the switch is actually busy reading the EEPROM, or because
++ * MV88E6XXX_G1_STS_IRQ_EEPROM_DONE has been cleared by an unrelated
++ * status register read already.
++ *
++ * To account for the latter case, trigger another EEPROM reload for
++ * another chance at seeing the done flag.
++ */
++ ret = mv88e6250_g1_eeprom_reload(chip);
++ if (ret)
++ return ret;
++
++ return mv88e6xxx_g1_wait_eeprom_done(chip);
++}
++
+ /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1
+ * Offset 0x02: Switch MAC Address Register Bytes 2 & 3
+ * Offset 0x03: Switch MAC Address Register Bytes 4 & 5
+diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h
+index 1095261f5b490..3dbb7a1b8fe11 100644
+--- a/drivers/net/dsa/mv88e6xxx/global1.h
++++ b/drivers/net/dsa/mv88e6xxx/global1.h
+@@ -282,6 +282,8 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr);
+ int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip);
+ int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip);
+ int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip);
++int mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip);
++int mv88e6250_g1_wait_eeprom_done_prereset(struct mv88e6xxx_chip *chip);
+
+ int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip);
+ int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip);
+diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
+index 705c3eb19cd3f..d1fbadbf86d4a 100644
+--- a/drivers/net/ethernet/cortina/gemini.c
++++ b/drivers/net/ethernet/cortina/gemini.c
+@@ -1107,10 +1107,13 @@ static void gmac_tx_irq_enable(struct net_device *netdev,
+ {
+ struct gemini_ethernet_port *port = netdev_priv(netdev);
+ struct gemini_ethernet *geth = port->geth;
++ unsigned long flags;
+ u32 val, mask;
+
+ netdev_dbg(netdev, "%s device %d\n", __func__, netdev->dev_id);
+
++ spin_lock_irqsave(&geth->irq_lock, flags);
++
+ mask = GMAC0_IRQ0_TXQ0_INTS << (6 * netdev->dev_id + txq);
+
+ if (en)
+@@ -1119,6 +1122,8 @@ static void gmac_tx_irq_enable(struct net_device *netdev,
+ val = readl(geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG);
+ val = en ? val | mask : val & ~mask;
+ writel(val, geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG);
++
++ spin_unlock_irqrestore(&geth->irq_lock, flags);
+ }
+
+ static void gmac_tx_irq(struct net_device *netdev, unsigned int txq_num)
+@@ -1415,15 +1420,19 @@ static unsigned int gmac_rx(struct net_device *netdev, unsigned int budget)
+ union gmac_rxdesc_3 word3;
+ struct page *page = NULL;
+ unsigned int page_offs;
++ unsigned long flags;
+ unsigned short r, w;
+ union dma_rwptr rw;
+ dma_addr_t mapping;
+ int frag_nr = 0;
+
++ spin_lock_irqsave(&geth->irq_lock, flags);
+ rw.bits32 = readl(ptr_reg);
+ /* Reset interrupt as all packages until here are taken into account */
+ writel(DEFAULT_Q0_INT_BIT << netdev->dev_id,
+ geth->base + GLOBAL_INTERRUPT_STATUS_1_REG);
++ spin_unlock_irqrestore(&geth->irq_lock, flags);
++
+ r = rw.bits.rptr;
+ w = rw.bits.wptr;
+
+@@ -1726,10 +1735,9 @@ static irqreturn_t gmac_irq(int irq, void *data)
+ gmac_update_hw_stats(netdev);
+
+ if (val & (GMAC0_RX_OVERRUN_INT_BIT << (netdev->dev_id * 8))) {
++ spin_lock(&geth->irq_lock);
+ writel(GMAC0_RXDERR_INT_BIT << (netdev->dev_id * 8),
+ geth->base + GLOBAL_INTERRUPT_STATUS_4_REG);
+-
+- spin_lock(&geth->irq_lock);
+ u64_stats_update_begin(&port->ir_stats_syncp);
+ ++port->stats.rx_fifo_errors;
+ u64_stats_update_end(&port->ir_stats_syncp);
+diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
+index bfdbdab443ae0..5e6e1f7196f87 100644
+--- a/drivers/net/ethernet/freescale/enetc/enetc.c
++++ b/drivers/net/ethernet/freescale/enetc/enetc.c
+@@ -2769,7 +2769,7 @@ static int enetc_setup_xdp_prog(struct net_device *ndev, struct bpf_prog *prog,
+ if (priv->min_num_stack_tx_queues + num_xdp_tx_queues >
+ priv->num_tx_rings) {
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+- "Reserving %d XDP TXQs does not leave a minimum of %d for stack (total %d)",
++ "Reserving %d XDP TXQs leaves under %d for stack (total %d)",
+ num_xdp_tx_queues,
+ priv->min_num_stack_tx_queues,
+ priv->num_tx_rings);
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index 8decb1b072c5e..e92a830330590 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -3678,29 +3678,6 @@ fec_set_mac_address(struct net_device *ndev, void *p)
+ return 0;
+ }
+
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-/**
+- * fec_poll_controller - FEC Poll controller function
+- * @dev: The FEC network adapter
+- *
+- * Polled functionality used by netconsole and others in non interrupt mode
+- *
+- */
+-static void fec_poll_controller(struct net_device *dev)
+-{
+- int i;
+- struct fec_enet_private *fep = netdev_priv(dev);
+-
+- for (i = 0; i < FEC_IRQ_NUM; i++) {
+- if (fep->irq[i] > 0) {
+- disable_irq(fep->irq[i]);
+- fec_enet_interrupt(fep->irq[i], dev);
+- enable_irq(fep->irq[i]);
+- }
+- }
+-}
+-#endif
+-
+ static inline void fec_enet_set_netdev_features(struct net_device *netdev,
+ netdev_features_t features)
+ {
+@@ -4007,9 +3984,6 @@ static const struct net_device_ops fec_netdev_ops = {
+ .ndo_tx_timeout = fec_timeout,
+ .ndo_set_mac_address = fec_set_mac_address,
+ .ndo_eth_ioctl = phy_do_ioctl_running,
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+- .ndo_poll_controller = fec_poll_controller,
+-#endif
+ .ndo_set_features = fec_set_features,
+ .ndo_bpf = fec_enet_bpf,
+ .ndo_xdp_xmit = fec_enet_xdp_xmit,
+diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c
+index c979192e44d10..a545a7917e4fc 100644
+--- a/drivers/net/ethernet/intel/ice/ice_base.c
++++ b/drivers/net/ethernet/intel/ice/ice_base.c
+@@ -536,7 +536,7 @@ static void ice_xsk_pool_fill_cb(struct ice_rx_ring *ring)
+ *
+ * Return 0 on success and a negative value on error.
+ */
+-int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
++static int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
+ {
+ struct device *dev = ice_pf_to_dev(ring->vsi->back);
+ u32 num_bufs = ICE_RX_DESC_UNUSED(ring);
+@@ -631,6 +631,62 @@ int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
+ return 0;
+ }
+
++int ice_vsi_cfg_single_rxq(struct ice_vsi *vsi, u16 q_idx)
++{
++ if (q_idx >= vsi->num_rxq)
++ return -EINVAL;
++
++ return ice_vsi_cfg_rxq(vsi->rx_rings[q_idx]);
++}
++
++/**
++ * ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length
++ * @vsi: VSI
++ */
++static void ice_vsi_cfg_frame_size(struct ice_vsi *vsi)
++{
++ if (!vsi->netdev || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags)) {
++ vsi->max_frame = ICE_MAX_FRAME_LEGACY_RX;
++ vsi->rx_buf_len = ICE_RXBUF_1664;
++#if (PAGE_SIZE < 8192)
++ } else if (!ICE_2K_TOO_SMALL_WITH_PADDING &&
++ (vsi->netdev->mtu <= ETH_DATA_LEN)) {
++ vsi->max_frame = ICE_RXBUF_1536 - NET_IP_ALIGN;
++ vsi->rx_buf_len = ICE_RXBUF_1536 - NET_IP_ALIGN;
++#endif
++ } else {
++ vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
++ vsi->rx_buf_len = ICE_RXBUF_3072;
++ }
++}
++
++/**
++ * ice_vsi_cfg_rxqs - Configure the VSI for Rx
++ * @vsi: the VSI being configured
++ *
++ * Return 0 on success and a negative value on error
++ * Configure the Rx VSI for operation.
++ */
++int ice_vsi_cfg_rxqs(struct ice_vsi *vsi)
++{
++ u16 i;
++
++ if (vsi->type == ICE_VSI_VF)
++ goto setup_rings;
++
++ ice_vsi_cfg_frame_size(vsi);
++setup_rings:
++ /* set up individual rings */
++ ice_for_each_rxq(vsi, i) {
++ int err = ice_vsi_cfg_rxq(vsi->rx_rings[i]);
++
++ if (err)
++ return err;
++ }
++
++ return 0;
++}
++
+ /**
+ * __ice_vsi_get_qs - helper function for assigning queues from PF to VSI
+ * @qs_cfg: gathered variables needed for pf->vsi queues assignment
+@@ -826,7 +882,7 @@ void ice_vsi_free_q_vectors(struct ice_vsi *vsi)
+ * @ring: Tx ring to be configured
+ * @qg_buf: queue group buffer
+ */
+-int
++static int
+ ice_vsi_cfg_txq(struct ice_vsi *vsi, struct ice_tx_ring *ring,
+ struct ice_aqc_add_tx_qgrp *qg_buf)
+ {
+@@ -897,6 +953,80 @@ ice_vsi_cfg_txq(struct ice_vsi *vsi, struct ice_tx_ring *ring,
+ return 0;
+ }
+
++int ice_vsi_cfg_single_txq(struct ice_vsi *vsi, struct ice_tx_ring **tx_rings,
++ u16 q_idx)
++{
++ DEFINE_RAW_FLEX(struct ice_aqc_add_tx_qgrp, qg_buf, txqs, 1);
++
++ if (q_idx >= vsi->alloc_txq || !tx_rings || !tx_rings[q_idx])
++ return -EINVAL;
++
++ qg_buf->num_txqs = 1;
++
++ return ice_vsi_cfg_txq(vsi, tx_rings[q_idx], qg_buf);
++}
++
++/**
++ * ice_vsi_cfg_txqs - Configure the VSI for Tx
++ * @vsi: the VSI being configured
++ * @rings: Tx ring array to be configured
++ * @count: number of Tx ring array elements
++ *
++ * Return 0 on success and a negative value on error
++ * Configure the Tx VSI for operation.
++ */
++static int
++ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_tx_ring **rings, u16 count)
++{
++ DEFINE_RAW_FLEX(struct ice_aqc_add_tx_qgrp, qg_buf, txqs, 1);
++ int err = 0;
++ u16 q_idx;
++
++ qg_buf->num_txqs = 1;
++
++ for (q_idx = 0; q_idx < count; q_idx++) {
++ err = ice_vsi_cfg_txq(vsi, rings[q_idx], qg_buf);
++ if (err)
++ break;
++ }
++
++ return err;
++}
++
++/**
++ * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx
++ * @vsi: the VSI being configured
++ *
++ * Return 0 on success and a negative value on error
++ * Configure the Tx VSI for operation.
++ */
++int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi)
++{
++ return ice_vsi_cfg_txqs(vsi, vsi->tx_rings, vsi->num_txq);
++}
++
++/**
++ * ice_vsi_cfg_xdp_txqs - Configure Tx queues dedicated for XDP in given VSI
++ * @vsi: the VSI being configured
++ *
++ * Return 0 on success and a negative value on error
++ * Configure the Tx queues dedicated for XDP in given VSI for operation.
++ */
++int ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi)
++{
++ int ret;
++ int i;
++
++ ret = ice_vsi_cfg_txqs(vsi, vsi->xdp_rings, vsi->num_xdp_txq);
++ if (ret)
++ return ret;
++
++ ice_for_each_rxq(vsi, i)
++ ice_tx_xsk_pool(vsi, i);
++
++ return 0;
++}
++
+ /**
+ * ice_cfg_itr - configure the initial interrupt throttle values
+ * @hw: pointer to the HW structure
+diff --git a/drivers/net/ethernet/intel/ice/ice_base.h b/drivers/net/ethernet/intel/ice/ice_base.h
+index 17321ba75602d..b711bc921928d 100644
+--- a/drivers/net/ethernet/intel/ice/ice_base.h
++++ b/drivers/net/ethernet/intel/ice/ice_base.h
+@@ -6,7 +6,8 @@
+
+ #include "ice.h"
+
+-int ice_vsi_cfg_rxq(struct ice_rx_ring *ring);
++int ice_vsi_cfg_single_rxq(struct ice_vsi *vsi, u16 q_idx);
++int ice_vsi_cfg_rxqs(struct ice_vsi *vsi);
+ int __ice_vsi_get_qs(struct ice_qs_cfg *qs_cfg);
+ int
+ ice_vsi_ctrl_one_rx_ring(struct ice_vsi *vsi, bool ena, u16 rxq_idx, bool wait);
+@@ -14,9 +15,10 @@ int ice_vsi_wait_one_rx_ring(struct ice_vsi *vsi, bool ena, u16 rxq_idx);
+ int ice_vsi_alloc_q_vectors(struct ice_vsi *vsi);
+ void ice_vsi_map_rings_to_vectors(struct ice_vsi *vsi);
+ void ice_vsi_free_q_vectors(struct ice_vsi *vsi);
+-int
+-ice_vsi_cfg_txq(struct ice_vsi *vsi, struct ice_tx_ring *ring,
+- struct ice_aqc_add_tx_qgrp *qg_buf);
++int ice_vsi_cfg_single_txq(struct ice_vsi *vsi, struct ice_tx_ring **tx_rings,
++ u16 q_idx);
++int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi);
++int ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi);
+ void ice_cfg_itr(struct ice_hw *hw, struct ice_q_vector *q_vector);
+ void
+ ice_cfg_txq_interrupt(struct ice_vsi *vsi, u16 txq, u16 msix_idx, u16 itr_idx);
+diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
+index 10c32cd80fff6..ce50a322daa91 100644
+--- a/drivers/net/ethernet/intel/ice/ice_common.c
++++ b/drivers/net/ethernet/intel/ice/ice_common.c
+@@ -4700,7 +4700,7 @@ ice_dis_vsi_txq(struct ice_port_info *pi, u16 vsi_handle, u8 tc, u8 num_queues,
+ enum ice_disq_rst_src rst_src, u16 vmvf_num,
+ struct ice_sq_cd *cd)
+ {
+- DEFINE_FLEX(struct ice_aqc_dis_txq_item, qg_list, q_id, 1);
++ DEFINE_RAW_FLEX(struct ice_aqc_dis_txq_item, qg_list, q_id, 1);
+ u16 i, buf_size = __struct_size(qg_list);
+ struct ice_q_ctx *q_ctx;
+ int status = -ENOENT;
+@@ -4922,7 +4922,7 @@ int
+ ice_dis_vsi_rdma_qset(struct ice_port_info *pi, u16 count, u32 *qset_teid,
+ u16 *q_id)
+ {
+- DEFINE_FLEX(struct ice_aqc_dis_txq_item, qg_list, q_id, 1);
++ DEFINE_RAW_FLEX(struct ice_aqc_dis_txq_item, qg_list, q_id, 1);
+ u16 qg_size = __struct_size(qg_list);
+ struct ice_hw *hw;
+ int status = 0;
+diff --git a/drivers/net/ethernet/intel/ice/ice_ddp.c b/drivers/net/ethernet/intel/ice/ice_ddp.c
+index 8b7504a9df316..1bf8ee98f06f9 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ddp.c
++++ b/drivers/net/ethernet/intel/ice/ice_ddp.c
+@@ -1424,14 +1424,14 @@ ice_dwnld_sign_and_cfg_segs(struct ice_hw *hw, struct ice_pkg_hdr *pkg_hdr,
+ goto exit;
+ }
+
+- conf_idx = le32_to_cpu(seg->signed_seg_idx);
+- start = le32_to_cpu(seg->signed_buf_start);
+ count = le32_to_cpu(seg->signed_buf_count);
+-
+ state = ice_download_pkg_sig_seg(hw, seg);
+- if (state)
++ if (state || !count)
+ goto exit;
+
++ conf_idx = le32_to_cpu(seg->signed_seg_idx);
++ start = le32_to_cpu(seg->signed_buf_start);
++
+ state = ice_download_pkg_config_seg(hw, pkg_hdr, conf_idx, start,
+ count);
+
+@@ -1934,8 +1934,8 @@ static enum ice_ddp_state ice_init_pkg_info(struct ice_hw *hw,
+ */
+ static enum ice_ddp_state ice_get_pkg_info(struct ice_hw *hw)
+ {
+- DEFINE_FLEX(struct ice_aqc_get_pkg_info_resp, pkg_info, pkg_info,
+- ICE_PKG_CNT);
++ DEFINE_RAW_FLEX(struct ice_aqc_get_pkg_info_resp, pkg_info, pkg_info,
++ ICE_PKG_CNT);
+ u16 size = __struct_size(pkg_info);
+ u32 i;
+
+@@ -1986,8 +1986,8 @@ static enum ice_ddp_state ice_chk_pkg_compat(struct ice_hw *hw,
+ struct ice_pkg_hdr *ospkg,
+ struct ice_seg **seg)
+ {
+- DEFINE_FLEX(struct ice_aqc_get_pkg_info_resp, pkg, pkg_info,
+- ICE_PKG_CNT);
++ DEFINE_RAW_FLEX(struct ice_aqc_get_pkg_info_resp, pkg, pkg_info,
++ ICE_PKG_CNT);
+ u16 size = __struct_size(pkg);
+ enum ice_ddp_state state;
+ u32 i;
+diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c
+index a7a342809935f..f0e76f0a6d603 100644
+--- a/drivers/net/ethernet/intel/ice/ice_lag.c
++++ b/drivers/net/ethernet/intel/ice/ice_lag.c
+@@ -491,7 +491,7 @@ static void
+ ice_lag_move_vf_node_tc(struct ice_lag *lag, u8 oldport, u8 newport,
+ u16 vsi_num, u8 tc)
+ {
+- DEFINE_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
++ DEFINE_RAW_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
+ struct device *dev = ice_pf_to_dev(lag->pf);
+ u16 numq, valq, num_moved, qbuf_size;
+ u16 buf_size = __struct_size(buf);
+@@ -849,7 +849,7 @@ static void
+ ice_lag_reclaim_vf_tc(struct ice_lag *lag, struct ice_hw *src_hw, u16 vsi_num,
+ u8 tc)
+ {
+- DEFINE_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
++ DEFINE_RAW_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
+ struct device *dev = ice_pf_to_dev(lag->pf);
+ u16 numq, valq, num_moved, qbuf_size;
+ u16 buf_size = __struct_size(buf);
+@@ -1873,7 +1873,7 @@ static void
+ ice_lag_move_vf_nodes_tc_sync(struct ice_lag *lag, struct ice_hw *dest_hw,
+ u16 vsi_num, u8 tc)
+ {
+- DEFINE_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
++ DEFINE_RAW_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
+ struct device *dev = ice_pf_to_dev(lag->pf);
+ u16 numq, valq, num_moved, qbuf_size;
+ u16 buf_size = __struct_size(buf);
+diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c
+index cfc20684f25ab..15bdf6ef3c099 100644
+--- a/drivers/net/ethernet/intel/ice/ice_lib.c
++++ b/drivers/net/ethernet/intel/ice/ice_lib.c
+@@ -1671,27 +1671,6 @@ static void ice_vsi_set_rss_flow_fld(struct ice_vsi *vsi)
+ }
+ }
+
+-/**
+- * ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length
+- * @vsi: VSI
+- */
+-static void ice_vsi_cfg_frame_size(struct ice_vsi *vsi)
+-{
+- if (!vsi->netdev || test_bit(ICE_FLAG_LEGACY_RX, vsi->back->flags)) {
+- vsi->max_frame = ICE_MAX_FRAME_LEGACY_RX;
+- vsi->rx_buf_len = ICE_RXBUF_1664;
+-#if (PAGE_SIZE < 8192)
+- } else if (!ICE_2K_TOO_SMALL_WITH_PADDING &&
+- (vsi->netdev->mtu <= ETH_DATA_LEN)) {
+- vsi->max_frame = ICE_RXBUF_1536 - NET_IP_ALIGN;
+- vsi->rx_buf_len = ICE_RXBUF_1536 - NET_IP_ALIGN;
+-#endif
+- } else {
+- vsi->max_frame = ICE_AQ_SET_MAC_FRAME_SIZE_MAX;
+- vsi->rx_buf_len = ICE_RXBUF_3072;
+- }
+-}
+-
+ /**
+ * ice_pf_state_is_nominal - checks the PF for nominal state
+ * @pf: pointer to PF to check
+@@ -1795,114 +1774,6 @@ ice_write_qrxflxp_cntxt(struct ice_hw *hw, u16 pf_q, u32 rxdid, u32 prio,
+ wr32(hw, QRXFLXP_CNTXT(pf_q), regval);
+ }
+
+-int ice_vsi_cfg_single_rxq(struct ice_vsi *vsi, u16 q_idx)
+-{
+- if (q_idx >= vsi->num_rxq)
+- return -EINVAL;
+-
+- return ice_vsi_cfg_rxq(vsi->rx_rings[q_idx]);
+-}
+-
+-int ice_vsi_cfg_single_txq(struct ice_vsi *vsi, struct ice_tx_ring **tx_rings, u16 q_idx)
+-{
+- DEFINE_FLEX(struct ice_aqc_add_tx_qgrp, qg_buf, txqs, 1);
+-
+- if (q_idx >= vsi->alloc_txq || !tx_rings || !tx_rings[q_idx])
+- return -EINVAL;
+-
+- qg_buf->num_txqs = 1;
+-
+- return ice_vsi_cfg_txq(vsi, tx_rings[q_idx], qg_buf);
+-}
+-
+-/**
+- * ice_vsi_cfg_rxqs - Configure the VSI for Rx
+- * @vsi: the VSI being configured
+- *
+- * Return 0 on success and a negative value on error
+- * Configure the Rx VSI for operation.
+- */
+-int ice_vsi_cfg_rxqs(struct ice_vsi *vsi)
+-{
+- u16 i;
+-
+- if (vsi->type == ICE_VSI_VF)
+- goto setup_rings;
+-
+- ice_vsi_cfg_frame_size(vsi);
+-setup_rings:
+- /* set up individual rings */
+- ice_for_each_rxq(vsi, i) {
+- int err = ice_vsi_cfg_rxq(vsi->rx_rings[i]);
+-
+- if (err)
+- return err;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * ice_vsi_cfg_txqs - Configure the VSI for Tx
+- * @vsi: the VSI being configured
+- * @rings: Tx ring array to be configured
+- * @count: number of Tx ring array elements
+- *
+- * Return 0 on success and a negative value on error
+- * Configure the Tx VSI for operation.
+- */
+-static int
+-ice_vsi_cfg_txqs(struct ice_vsi *vsi, struct ice_tx_ring **rings, u16 count)
+-{
+- DEFINE_FLEX(struct ice_aqc_add_tx_qgrp, qg_buf, txqs, 1);
+- int err = 0;
+- u16 q_idx;
+-
+- qg_buf->num_txqs = 1;
+-
+- for (q_idx = 0; q_idx < count; q_idx++) {
+- err = ice_vsi_cfg_txq(vsi, rings[q_idx], qg_buf);
+- if (err)
+- break;
+- }
+-
+- return err;
+-}
+-
+-/**
+- * ice_vsi_cfg_lan_txqs - Configure the VSI for Tx
+- * @vsi: the VSI being configured
+- *
+- * Return 0 on success and a negative value on error
+- * Configure the Tx VSI for operation.
+- */
+-int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi)
+-{
+- return ice_vsi_cfg_txqs(vsi, vsi->tx_rings, vsi->num_txq);
+-}
+-
+-/**
+- * ice_vsi_cfg_xdp_txqs - Configure Tx queues dedicated for XDP in given VSI
+- * @vsi: the VSI being configured
+- *
+- * Return 0 on success and a negative value on error
+- * Configure the Tx queues dedicated for XDP in given VSI for operation.
+- */
+-int ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi)
+-{
+- int ret;
+- int i;
+-
+- ret = ice_vsi_cfg_txqs(vsi, vsi->xdp_rings, vsi->num_xdp_txq);
+- if (ret)
+- return ret;
+-
+- ice_for_each_rxq(vsi, i)
+- ice_tx_xsk_pool(vsi, i);
+-
+- return 0;
+-}
+-
+ /**
+ * ice_intrl_usec_to_reg - convert interrupt rate limit to register value
+ * @intrl: interrupt rate limit in usecs
+diff --git a/drivers/net/ethernet/intel/ice/ice_lib.h b/drivers/net/ethernet/intel/ice/ice_lib.h
+index bfcfc582a4c04..b5a1ed7cc4b17 100644
+--- a/drivers/net/ethernet/intel/ice/ice_lib.h
++++ b/drivers/net/ethernet/intel/ice/ice_lib.h
+@@ -54,14 +54,6 @@ bool ice_pf_state_is_nominal(struct ice_pf *pf);
+
+ void ice_update_eth_stats(struct ice_vsi *vsi);
+
+-int ice_vsi_cfg_single_rxq(struct ice_vsi *vsi, u16 q_idx);
+-
+-int ice_vsi_cfg_single_txq(struct ice_vsi *vsi, struct ice_tx_ring **tx_rings, u16 q_idx);
+-
+-int ice_vsi_cfg_rxqs(struct ice_vsi *vsi);
+-
+-int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi);
+-
+ void ice_vsi_cfg_msix(struct ice_vsi *vsi);
+
+ int ice_vsi_start_all_rx_rings(struct ice_vsi *vsi);
+@@ -72,8 +64,6 @@ int
+ ice_vsi_stop_lan_tx_rings(struct ice_vsi *vsi, enum ice_disq_rst_src rst_src,
+ u16 rel_vmvf_num);
+
+-int ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi);
+-
+ int ice_vsi_stop_xdp_tx_rings(struct ice_vsi *vsi);
+
+ void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create);
+diff --git a/drivers/net/ethernet/intel/ice/ice_sched.c b/drivers/net/ethernet/intel/ice/ice_sched.c
+index d174a4eeb899c..a1525992d14bc 100644
+--- a/drivers/net/ethernet/intel/ice/ice_sched.c
++++ b/drivers/net/ethernet/intel/ice/ice_sched.c
+@@ -237,7 +237,7 @@ static int
+ ice_sched_remove_elems(struct ice_hw *hw, struct ice_sched_node *parent,
+ u32 node_teid)
+ {
+- DEFINE_FLEX(struct ice_aqc_delete_elem, buf, teid, 1);
++ DEFINE_RAW_FLEX(struct ice_aqc_delete_elem, buf, teid, 1);
+ u16 buf_size = __struct_size(buf);
+ u16 num_groups_removed = 0;
+ int status;
+@@ -2219,7 +2219,7 @@ int
+ ice_sched_move_nodes(struct ice_port_info *pi, struct ice_sched_node *parent,
+ u16 num_items, u32 *list)
+ {
+- DEFINE_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
++ DEFINE_RAW_FLEX(struct ice_aqc_move_elem, buf, teid, 1);
+ u16 buf_len = __struct_size(buf);
+ struct ice_sched_node *node;
+ u16 i, grps_movd = 0;
+diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
+index ba0ef91e4c19c..b4ea935e83005 100644
+--- a/drivers/net/ethernet/intel/ice/ice_switch.c
++++ b/drivers/net/ethernet/intel/ice/ice_switch.c
+@@ -1812,7 +1812,7 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
+ enum ice_sw_lkup_type lkup_type,
+ enum ice_adminq_opc opc)
+ {
+- DEFINE_FLEX(struct ice_aqc_alloc_free_res_elem, sw_buf, elem, 1);
++ DEFINE_RAW_FLEX(struct ice_aqc_alloc_free_res_elem, sw_buf, elem, 1);
+ u16 buf_len = __struct_size(sw_buf);
+ struct ice_aqc_res_elem *vsi_ele;
+ int status;
+@@ -2081,7 +2081,7 @@ ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u64 *r_assoc,
+ */
+ int ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
+ {
+- DEFINE_FLEX(struct ice_aqc_alloc_free_res_elem, sw_buf, elem, 1);
++ DEFINE_RAW_FLEX(struct ice_aqc_alloc_free_res_elem, sw_buf, elem, 1);
+ u16 buf_len = __struct_size(sw_buf);
+ int status;
+
+@@ -4420,7 +4420,7 @@ int
+ ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
+ u16 *counter_id)
+ {
+- DEFINE_FLEX(struct ice_aqc_alloc_free_res_elem, buf, elem, 1);
++ DEFINE_RAW_FLEX(struct ice_aqc_alloc_free_res_elem, buf, elem, 1);
+ u16 buf_len = __struct_size(buf);
+ int status;
+
+@@ -4448,7 +4448,7 @@ int
+ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
+ u16 counter_id)
+ {
+- DEFINE_FLEX(struct ice_aqc_alloc_free_res_elem, buf, elem, 1);
++ DEFINE_RAW_FLEX(struct ice_aqc_alloc_free_res_elem, buf, elem, 1);
+ u16 buf_len = __struct_size(buf);
+ int status;
+
+@@ -4478,7 +4478,7 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
+ */
+ int ice_share_res(struct ice_hw *hw, u16 type, u8 shared, u16 res_id)
+ {
+- DEFINE_FLEX(struct ice_aqc_alloc_free_res_elem, buf, elem, 1);
++ DEFINE_RAW_FLEX(struct ice_aqc_alloc_free_res_elem, buf, elem, 1);
+ u16 buf_len = __struct_size(buf);
+ u16 res_type;
+ int status;
+diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c
+index 2eecd0f39aa69..1857220d27fee 100644
+--- a/drivers/net/ethernet/intel/ice/ice_xsk.c
++++ b/drivers/net/ethernet/intel/ice/ice_xsk.c
+@@ -218,42 +218,28 @@ static int ice_qp_dis(struct ice_vsi *vsi, u16 q_idx)
+ */
+ static int ice_qp_ena(struct ice_vsi *vsi, u16 q_idx)
+ {
+- DEFINE_FLEX(struct ice_aqc_add_tx_qgrp, qg_buf, txqs, 1);
+- u16 size = __struct_size(qg_buf);
+ struct ice_q_vector *q_vector;
+- struct ice_tx_ring *tx_ring;
+- struct ice_rx_ring *rx_ring;
+ int err;
+
+- if (q_idx >= vsi->num_rxq || q_idx >= vsi->num_txq)
+- return -EINVAL;
+-
+- qg_buf->num_txqs = 1;
+-
+- tx_ring = vsi->tx_rings[q_idx];
+- rx_ring = vsi->rx_rings[q_idx];
+- q_vector = rx_ring->q_vector;
+-
+- err = ice_vsi_cfg_txq(vsi, tx_ring, qg_buf);
++ err = ice_vsi_cfg_single_txq(vsi, vsi->tx_rings, q_idx);
+ if (err)
+ return err;
+
+ if (ice_is_xdp_ena_vsi(vsi)) {
+ struct ice_tx_ring *xdp_ring = vsi->xdp_rings[q_idx];
+
+- memset(qg_buf, 0, size);
+- qg_buf->num_txqs = 1;
+- err = ice_vsi_cfg_txq(vsi, xdp_ring, qg_buf);
++ err = ice_vsi_cfg_single_txq(vsi, vsi->xdp_rings, q_idx);
+ if (err)
+ return err;
+ ice_set_ring_xdp(xdp_ring);
+ ice_tx_xsk_pool(vsi, q_idx);
+ }
+
+- err = ice_vsi_cfg_rxq(rx_ring);
++ err = ice_vsi_cfg_single_rxq(vsi, q_idx);
+ if (err)
+ return err;
+
++ q_vector = vsi->rx_rings[q_idx]->q_vector;
+ ice_qvec_cfg_msix(vsi, q_vector);
+
+ err = ice_vsi_ctrl_one_rx_ring(vsi, true, q_idx, true);
+diff --git a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c
+index 986d429d11755..6972d728431cb 100644
+--- a/drivers/net/ethernet/intel/idpf/idpf_ethtool.c
++++ b/drivers/net/ethernet/intel/idpf/idpf_ethtool.c
+@@ -376,7 +376,8 @@ static int idpf_set_ringparam(struct net_device *netdev,
+ new_tx_count);
+
+ if (new_tx_count == vport->txq_desc_count &&
+- new_rx_count == vport->rxq_desc_count)
++ new_rx_count == vport->rxq_desc_count &&
++ kring->tcp_data_split == idpf_vport_get_hsplit(vport))
+ goto unlock_mutex;
+
+ if (!idpf_vport_set_hsplit(vport, kring->tcp_data_split)) {
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+index caa13b9cedff0..d7d73295f0dc4 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -110,16 +110,16 @@ static const struct mtk_reg_map mt7986_reg_map = {
+ .tx_irq_mask = 0x461c,
+ .tx_irq_status = 0x4618,
+ .pdma = {
+- .rx_ptr = 0x6100,
+- .rx_cnt_cfg = 0x6104,
+- .pcrx_ptr = 0x6108,
+- .glo_cfg = 0x6204,
+- .rst_idx = 0x6208,
+- .delay_irq = 0x620c,
+- .irq_status = 0x6220,
+- .irq_mask = 0x6228,
+- .adma_rx_dbg0 = 0x6238,
+- .int_grp = 0x6250,
++ .rx_ptr = 0x4100,
++ .rx_cnt_cfg = 0x4104,
++ .pcrx_ptr = 0x4108,
++ .glo_cfg = 0x4204,
++ .rst_idx = 0x4208,
++ .delay_irq = 0x420c,
++ .irq_status = 0x4220,
++ .irq_mask = 0x4228,
++ .adma_rx_dbg0 = 0x4238,
++ .int_grp = 0x4250,
+ },
+ .qdma = {
+ .qtx_cfg = 0x4400,
+@@ -1107,7 +1107,7 @@ static bool mtk_rx_get_desc(struct mtk_eth *eth, struct mtk_rx_dma_v2 *rxd,
+ rxd->rxd1 = READ_ONCE(dma_rxd->rxd1);
+ rxd->rxd3 = READ_ONCE(dma_rxd->rxd3);
+ rxd->rxd4 = READ_ONCE(dma_rxd->rxd4);
+- if (mtk_is_netsys_v2_or_greater(eth)) {
++ if (mtk_is_netsys_v3_or_greater(eth)) {
+ rxd->rxd5 = READ_ONCE(dma_rxd->rxd5);
+ rxd->rxd6 = READ_ONCE(dma_rxd->rxd6);
+ }
+@@ -1139,7 +1139,7 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
+ eth->scratch_ring = eth->sram_base;
+ else
+ eth->scratch_ring = dma_alloc_coherent(eth->dma_dev,
+- cnt * soc->txrx.txd_size,
++ cnt * soc->tx.desc_size,
+ ð->phy_scratch_ring,
+ GFP_KERNEL);
+ if (unlikely(!eth->scratch_ring))
+@@ -1155,17 +1155,17 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
+ if (unlikely(dma_mapping_error(eth->dma_dev, dma_addr)))
+ return -ENOMEM;
+
+- phy_ring_tail = eth->phy_scratch_ring + soc->txrx.txd_size * (cnt - 1);
++ phy_ring_tail = eth->phy_scratch_ring + soc->tx.desc_size * (cnt - 1);
+
+ for (i = 0; i < cnt; i++) {
+ dma_addr_t addr = dma_addr + i * MTK_QDMA_PAGE_SIZE;
+ struct mtk_tx_dma_v2 *txd;
+
+- txd = eth->scratch_ring + i * soc->txrx.txd_size;
++ txd = eth->scratch_ring + i * soc->tx.desc_size;
+ txd->txd1 = addr;
+ if (i < cnt - 1)
+ txd->txd2 = eth->phy_scratch_ring +
+- (i + 1) * soc->txrx.txd_size;
++ (i + 1) * soc->tx.desc_size;
+
+ txd->txd3 = TX_DMA_PLEN0(MTK_QDMA_PAGE_SIZE);
+ if (MTK_HAS_CAPS(soc->caps, MTK_36BIT_DMA))
+@@ -1416,7 +1416,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
+ if (itxd == ring->last_free)
+ return -ENOMEM;
+
+- itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size);
++ itx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size);
+ memset(itx_buf, 0, sizeof(*itx_buf));
+
+ txd_info.addr = dma_map_single(eth->dma_dev, skb->data, txd_info.size,
+@@ -1457,7 +1457,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
+
+ memset(&txd_info, 0, sizeof(struct mtk_tx_dma_desc_info));
+ txd_info.size = min_t(unsigned int, frag_size,
+- soc->txrx.dma_max_len);
++ soc->tx.dma_max_len);
+ txd_info.qid = queue;
+ txd_info.last = i == skb_shinfo(skb)->nr_frags - 1 &&
+ !(frag_size - txd_info.size);
+@@ -1470,7 +1470,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
+ mtk_tx_set_dma_desc(dev, txd, &txd_info);
+
+ tx_buf = mtk_desc_to_tx_buf(ring, txd,
+- soc->txrx.txd_size);
++ soc->tx.desc_size);
+ if (new_desc)
+ memset(tx_buf, 0, sizeof(*tx_buf));
+ tx_buf->data = (void *)MTK_DMA_DUMMY_DESC;
+@@ -1513,7 +1513,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
+ } else {
+ int next_idx;
+
+- next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->txrx.txd_size),
++ next_idx = NEXT_DESP_IDX(txd_to_idx(ring, txd, soc->tx.desc_size),
+ ring->dma_size);
+ mtk_w32(eth, next_idx, MT7628_TX_CTX_IDX0);
+ }
+@@ -1522,7 +1522,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct net_device *dev,
+
+ err_dma:
+ do {
+- tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->txrx.txd_size);
++ tx_buf = mtk_desc_to_tx_buf(ring, itxd, soc->tx.desc_size);
+
+ /* unmap dma */
+ mtk_tx_unmap(eth, tx_buf, NULL, false);
+@@ -1547,7 +1547,7 @@ static int mtk_cal_txd_req(struct mtk_eth *eth, struct sk_buff *skb)
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ frag = &skb_shinfo(skb)->frags[i];
+ nfrags += DIV_ROUND_UP(skb_frag_size(frag),
+- eth->soc->txrx.dma_max_len);
++ eth->soc->tx.dma_max_len);
+ }
+ } else {
+ nfrags += skb_shinfo(skb)->nr_frags;
+@@ -1654,7 +1654,7 @@ static struct mtk_rx_ring *mtk_get_rx_ring(struct mtk_eth *eth)
+
+ ring = ð->rx_ring[i];
+ idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
+- rxd = ring->dma + idx * eth->soc->txrx.rxd_size;
++ rxd = ring->dma + idx * eth->soc->rx.desc_size;
+ if (rxd->rxd2 & RX_DMA_DONE) {
+ ring->calc_idx_update = true;
+ return ring;
+@@ -1822,7 +1822,7 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf,
+ }
+ htxd = txd;
+
+- tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->txrx.txd_size);
++ tx_buf = mtk_desc_to_tx_buf(ring, txd, soc->tx.desc_size);
+ memset(tx_buf, 0, sizeof(*tx_buf));
+ htx_buf = tx_buf;
+
+@@ -1841,7 +1841,7 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf,
+ goto unmap;
+
+ tx_buf = mtk_desc_to_tx_buf(ring, txd,
+- soc->txrx.txd_size);
++ soc->tx.desc_size);
+ memset(tx_buf, 0, sizeof(*tx_buf));
+ n_desc++;
+ }
+@@ -1879,7 +1879,7 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf,
+ } else {
+ int idx;
+
+- idx = txd_to_idx(ring, txd, soc->txrx.txd_size);
++ idx = txd_to_idx(ring, txd, soc->tx.desc_size);
+ mtk_w32(eth, NEXT_DESP_IDX(idx, ring->dma_size),
+ MT7628_TX_CTX_IDX0);
+ }
+@@ -1890,7 +1890,7 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf,
+
+ unmap:
+ while (htxd != txd) {
+- tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->txrx.txd_size);
++ tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->tx.desc_size);
+ mtk_tx_unmap(eth, tx_buf, NULL, false);
+
+ htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
+@@ -2021,14 +2021,14 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+ goto rx_done;
+
+ idx = NEXT_DESP_IDX(ring->calc_idx, ring->dma_size);
+- rxd = ring->dma + idx * eth->soc->txrx.rxd_size;
++ rxd = ring->dma + idx * eth->soc->rx.desc_size;
+ data = ring->data[idx];
+
+ if (!mtk_rx_get_desc(eth, &trxd, rxd))
+ break;
+
+ /* find out which mac the packet come from. values start at 1 */
+- if (mtk_is_netsys_v2_or_greater(eth)) {
++ if (mtk_is_netsys_v3_or_greater(eth)) {
+ u32 val = RX_DMA_GET_SPORT_V2(trxd.rxd5);
+
+ switch (val) {
+@@ -2140,7 +2140,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+ skb->dev = netdev;
+ bytes += skb->len;
+
+- if (mtk_is_netsys_v2_or_greater(eth)) {
++ if (mtk_is_netsys_v3_or_greater(eth)) {
+ reason = FIELD_GET(MTK_RXD5_PPE_CPU_REASON, trxd.rxd5);
+ hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY;
+ if (hash != MTK_RXD5_FOE_ENTRY)
+@@ -2156,7 +2156,7 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
+ rxdcsum = &trxd.rxd4;
+ }
+
+- if (*rxdcsum & eth->soc->txrx.rx_dma_l4_valid)
++ if (*rxdcsum & eth->soc->rx.dma_l4_valid)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ else
+ skb_checksum_none_assert(skb);
+@@ -2280,7 +2280,7 @@ static int mtk_poll_tx_qdma(struct mtk_eth *eth, int budget,
+ break;
+
+ tx_buf = mtk_desc_to_tx_buf(ring, desc,
+- eth->soc->txrx.txd_size);
++ eth->soc->tx.desc_size);
+ if (!tx_buf->data)
+ break;
+
+@@ -2331,7 +2331,7 @@ static int mtk_poll_tx_pdma(struct mtk_eth *eth, int budget,
+ }
+ mtk_tx_unmap(eth, tx_buf, &bq, true);
+
+- desc = ring->dma + cpu * eth->soc->txrx.txd_size;
++ desc = ring->dma + cpu * eth->soc->tx.desc_size;
+ ring->last_free = desc;
+ atomic_inc(&ring->free_count);
+
+@@ -2421,7 +2421,7 @@ static int mtk_napi_rx(struct napi_struct *napi, int budget)
+ do {
+ int rx_done;
+
+- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask,
++ mtk_w32(eth, eth->soc->rx.irq_done_mask,
+ reg_map->pdma.irq_status);
+ rx_done = mtk_poll_rx(napi, budget - rx_done_total, eth);
+ rx_done_total += rx_done;
+@@ -2437,10 +2437,10 @@ static int mtk_napi_rx(struct napi_struct *napi, int budget)
+ return budget;
+
+ } while (mtk_r32(eth, reg_map->pdma.irq_status) &
+- eth->soc->txrx.rx_irq_done_mask);
++ eth->soc->rx.irq_done_mask);
+
+ if (napi_complete_done(napi, rx_done_total))
+- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask);
++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask);
+
+ return rx_done_total;
+ }
+@@ -2449,7 +2449,7 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
+ {
+ const struct mtk_soc_data *soc = eth->soc;
+ struct mtk_tx_ring *ring = ð->tx_ring;
+- int i, sz = soc->txrx.txd_size;
++ int i, sz = soc->tx.desc_size;
+ struct mtk_tx_dma_v2 *txd;
+ int ring_size;
+ u32 ofs, val;
+@@ -2572,14 +2572,14 @@ static void mtk_tx_clean(struct mtk_eth *eth)
+ }
+ if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && ring->dma) {
+ dma_free_coherent(eth->dma_dev,
+- ring->dma_size * soc->txrx.txd_size,
++ ring->dma_size * soc->tx.desc_size,
+ ring->dma, ring->phys);
+ ring->dma = NULL;
+ }
+
+ if (ring->dma_pdma) {
+ dma_free_coherent(eth->dma_dev,
+- ring->dma_size * soc->txrx.txd_size,
++ ring->dma_size * soc->tx.desc_size,
+ ring->dma_pdma, ring->phys_pdma);
+ ring->dma_pdma = NULL;
+ }
+@@ -2634,15 +2634,15 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
+ if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SRAM) ||
+ rx_flag != MTK_RX_FLAGS_NORMAL) {
+ ring->dma = dma_alloc_coherent(eth->dma_dev,
+- rx_dma_size * eth->soc->txrx.rxd_size,
+- &ring->phys, GFP_KERNEL);
++ rx_dma_size * eth->soc->rx.desc_size,
++ &ring->phys, GFP_KERNEL);
+ } else {
+ struct mtk_tx_ring *tx_ring = ð->tx_ring;
+
+ ring->dma = tx_ring->dma + tx_ring_size *
+- eth->soc->txrx.txd_size * (ring_no + 1);
++ eth->soc->tx.desc_size * (ring_no + 1);
+ ring->phys = tx_ring->phys + tx_ring_size *
+- eth->soc->txrx.txd_size * (ring_no + 1);
++ eth->soc->tx.desc_size * (ring_no + 1);
+ }
+
+ if (!ring->dma)
+@@ -2653,7 +2653,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
+ dma_addr_t dma_addr;
+ void *data;
+
+- rxd = ring->dma + i * eth->soc->txrx.rxd_size;
++ rxd = ring->dma + i * eth->soc->rx.desc_size;
+ if (ring->page_pool) {
+ data = mtk_page_pool_get_buff(ring->page_pool,
+ &dma_addr, GFP_KERNEL);
+@@ -2690,7 +2690,7 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
+
+ rxd->rxd3 = 0;
+ rxd->rxd4 = 0;
+- if (mtk_is_netsys_v2_or_greater(eth)) {
++ if (mtk_is_netsys_v3_or_greater(eth)) {
+ rxd->rxd5 = 0;
+ rxd->rxd6 = 0;
+ rxd->rxd7 = 0;
+@@ -2744,7 +2744,7 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_
+ if (!ring->data[i])
+ continue;
+
+- rxd = ring->dma + i * eth->soc->txrx.rxd_size;
++ rxd = ring->dma + i * eth->soc->rx.desc_size;
+ if (!rxd->rxd1)
+ continue;
+
+@@ -2761,7 +2761,7 @@ static void mtk_rx_clean(struct mtk_eth *eth, struct mtk_rx_ring *ring, bool in_
+
+ if (!in_sram && ring->dma) {
+ dma_free_coherent(eth->dma_dev,
+- ring->dma_size * eth->soc->txrx.rxd_size,
++ ring->dma_size * eth->soc->rx.desc_size,
+ ring->dma, ring->phys);
+ ring->dma = NULL;
+ }
+@@ -3124,7 +3124,7 @@ static void mtk_dma_free(struct mtk_eth *eth)
+ netdev_reset_queue(eth->netdev[i]);
+ if (!MTK_HAS_CAPS(soc->caps, MTK_SRAM) && eth->scratch_ring) {
+ dma_free_coherent(eth->dma_dev,
+- MTK_QDMA_RING_SIZE * soc->txrx.txd_size,
++ MTK_QDMA_RING_SIZE * soc->tx.desc_size,
+ eth->scratch_ring, eth->phy_scratch_ring);
+ eth->scratch_ring = NULL;
+ eth->phy_scratch_ring = 0;
+@@ -3174,7 +3174,7 @@ static irqreturn_t mtk_handle_irq_rx(int irq, void *_eth)
+
+ eth->rx_events++;
+ if (likely(napi_schedule_prep(ð->rx_napi))) {
+- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask);
++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask);
+ __napi_schedule(ð->rx_napi);
+ }
+
+@@ -3200,9 +3200,9 @@ static irqreturn_t mtk_handle_irq(int irq, void *_eth)
+ const struct mtk_reg_map *reg_map = eth->soc->reg_map;
+
+ if (mtk_r32(eth, reg_map->pdma.irq_mask) &
+- eth->soc->txrx.rx_irq_done_mask) {
++ eth->soc->rx.irq_done_mask) {
+ if (mtk_r32(eth, reg_map->pdma.irq_status) &
+- eth->soc->txrx.rx_irq_done_mask)
++ eth->soc->rx.irq_done_mask)
+ mtk_handle_irq_rx(irq, _eth);
+ }
+ if (mtk_r32(eth, reg_map->tx_irq_mask) & MTK_TX_DONE_INT) {
+@@ -3220,10 +3220,10 @@ static void mtk_poll_controller(struct net_device *dev)
+ struct mtk_eth *eth = mac->hw;
+
+ mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
+- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask);
++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask);
+ mtk_handle_irq_rx(eth->irq[2], dev);
+ mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
+- mtk_rx_irq_enable(eth, eth->soc->txrx.rx_irq_done_mask);
++ mtk_rx_irq_enable(eth, eth->soc->rx.irq_done_mask);
+ }
+ #endif
+
+@@ -3387,7 +3387,7 @@ static int mtk_open(struct net_device *dev)
+ napi_enable(ð->tx_napi);
+ napi_enable(ð->rx_napi);
+ mtk_tx_irq_enable(eth, MTK_TX_DONE_INT);
+- mtk_rx_irq_enable(eth, soc->txrx.rx_irq_done_mask);
++ mtk_rx_irq_enable(eth, soc->rx.irq_done_mask);
+ refcount_set(ð->dma_refcnt, 1);
+ }
+ else
+@@ -3471,7 +3471,7 @@ static int mtk_stop(struct net_device *dev)
+ mtk_gdm_config(eth, MTK_GDMA_DROP_ALL);
+
+ mtk_tx_irq_disable(eth, MTK_TX_DONE_INT);
+- mtk_rx_irq_disable(eth, eth->soc->txrx.rx_irq_done_mask);
++ mtk_rx_irq_disable(eth, eth->soc->rx.irq_done_mask);
+ napi_disable(ð->tx_napi);
+ napi_disable(ð->rx_napi);
+
+@@ -3893,7 +3893,7 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset)
+ else
+ mtk_hw_reset(eth);
+
+- if (mtk_is_netsys_v2_or_greater(eth)) {
++ if (mtk_is_netsys_v3_or_greater(eth)) {
+ /* Set FE to PDMAv2 if necessary */
+ val = mtk_r32(eth, MTK_FE_GLO_MISC);
+ mtk_w32(eth, val | BIT(4), MTK_FE_GLO_MISC);
+@@ -3947,9 +3947,9 @@ static int mtk_hw_init(struct mtk_eth *eth, bool reset)
+
+ /* FE int grouping */
+ mtk_w32(eth, MTK_TX_DONE_INT, reg_map->pdma.int_grp);
+- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->pdma.int_grp + 4);
++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->pdma.int_grp + 4);
+ mtk_w32(eth, MTK_TX_DONE_INT, reg_map->qdma.int_grp);
+- mtk_w32(eth, eth->soc->txrx.rx_irq_done_mask, reg_map->qdma.int_grp + 4);
++ mtk_w32(eth, eth->soc->rx.irq_done_mask, reg_map->qdma.int_grp + 4);
+ mtk_w32(eth, 0x21021000, MTK_FE_INT_GRP);
+
+ if (mtk_is_netsys_v3_or_greater(eth)) {
+@@ -5039,11 +5039,15 @@ static const struct mtk_soc_data mt2701_data = {
+ .required_clks = MT7623_CLKS_BITMAP,
+ .required_pctl = true,
+ .version = 1,
+- .txrx = {
+- .txd_size = sizeof(struct mtk_tx_dma),
+- .rxd_size = sizeof(struct mtk_rx_dma),
+- .rx_irq_done_mask = MTK_RX_DONE_INT,
+- .rx_dma_l4_valid = RX_DMA_L4_VALID,
++ .tx = {
++ .desc_size = sizeof(struct mtk_tx_dma),
++ .dma_max_len = MTK_TX_DMA_BUF_LEN,
++ .dma_len_offset = 16,
++ },
++ .rx = {
++ .desc_size = sizeof(struct mtk_rx_dma),
++ .irq_done_mask = MTK_RX_DONE_INT,
++ .dma_l4_valid = RX_DMA_L4_VALID,
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = 16,
+ },
+@@ -5059,11 +5063,15 @@ static const struct mtk_soc_data mt7621_data = {
+ .offload_version = 1,
+ .hash_offset = 2,
+ .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
+- .txrx = {
+- .txd_size = sizeof(struct mtk_tx_dma),
+- .rxd_size = sizeof(struct mtk_rx_dma),
+- .rx_irq_done_mask = MTK_RX_DONE_INT,
+- .rx_dma_l4_valid = RX_DMA_L4_VALID,
++ .tx = {
++ .desc_size = sizeof(struct mtk_tx_dma),
++ .dma_max_len = MTK_TX_DMA_BUF_LEN,
++ .dma_len_offset = 16,
++ },
++ .rx = {
++ .desc_size = sizeof(struct mtk_rx_dma),
++ .irq_done_mask = MTK_RX_DONE_INT,
++ .dma_l4_valid = RX_DMA_L4_VALID,
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = 16,
+ },
+@@ -5081,11 +5089,15 @@ static const struct mtk_soc_data mt7622_data = {
+ .hash_offset = 2,
+ .has_accounting = true,
+ .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
+- .txrx = {
+- .txd_size = sizeof(struct mtk_tx_dma),
+- .rxd_size = sizeof(struct mtk_rx_dma),
+- .rx_irq_done_mask = MTK_RX_DONE_INT,
+- .rx_dma_l4_valid = RX_DMA_L4_VALID,
++ .tx = {
++ .desc_size = sizeof(struct mtk_tx_dma),
++ .dma_max_len = MTK_TX_DMA_BUF_LEN,
++ .dma_len_offset = 16,
++ },
++ .rx = {
++ .desc_size = sizeof(struct mtk_rx_dma),
++ .irq_done_mask = MTK_RX_DONE_INT,
++ .dma_l4_valid = RX_DMA_L4_VALID,
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = 16,
+ },
+@@ -5102,11 +5114,15 @@ static const struct mtk_soc_data mt7623_data = {
+ .hash_offset = 2,
+ .foe_entry_size = MTK_FOE_ENTRY_V1_SIZE,
+ .disable_pll_modes = true,
+- .txrx = {
+- .txd_size = sizeof(struct mtk_tx_dma),
+- .rxd_size = sizeof(struct mtk_rx_dma),
+- .rx_irq_done_mask = MTK_RX_DONE_INT,
+- .rx_dma_l4_valid = RX_DMA_L4_VALID,
++ .tx = {
++ .desc_size = sizeof(struct mtk_tx_dma),
++ .dma_max_len = MTK_TX_DMA_BUF_LEN,
++ .dma_len_offset = 16,
++ },
++ .rx = {
++ .desc_size = sizeof(struct mtk_rx_dma),
++ .irq_done_mask = MTK_RX_DONE_INT,
++ .dma_l4_valid = RX_DMA_L4_VALID,
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = 16,
+ },
+@@ -5121,11 +5137,15 @@ static const struct mtk_soc_data mt7629_data = {
+ .required_pctl = false,
+ .has_accounting = true,
+ .version = 1,
+- .txrx = {
+- .txd_size = sizeof(struct mtk_tx_dma),
+- .rxd_size = sizeof(struct mtk_rx_dma),
+- .rx_irq_done_mask = MTK_RX_DONE_INT,
+- .rx_dma_l4_valid = RX_DMA_L4_VALID,
++ .tx = {
++ .desc_size = sizeof(struct mtk_tx_dma),
++ .dma_max_len = MTK_TX_DMA_BUF_LEN,
++ .dma_len_offset = 16,
++ },
++ .rx = {
++ .desc_size = sizeof(struct mtk_rx_dma),
++ .irq_done_mask = MTK_RX_DONE_INT,
++ .dma_l4_valid = RX_DMA_L4_VALID,
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = 16,
+ },
+@@ -5143,14 +5163,18 @@ static const struct mtk_soc_data mt7981_data = {
+ .hash_offset = 4,
+ .has_accounting = true,
+ .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
+- .txrx = {
+- .txd_size = sizeof(struct mtk_tx_dma_v2),
+- .rxd_size = sizeof(struct mtk_rx_dma_v2),
+- .rx_irq_done_mask = MTK_RX_DONE_INT_V2,
+- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
++ .tx = {
++ .desc_size = sizeof(struct mtk_tx_dma_v2),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = 8,
+ },
++ .rx = {
++ .desc_size = sizeof(struct mtk_rx_dma),
++ .irq_done_mask = MTK_RX_DONE_INT,
++ .dma_l4_valid = RX_DMA_L4_VALID_V2,
++ .dma_max_len = MTK_TX_DMA_BUF_LEN,
++ .dma_len_offset = 16,
++ },
+ };
+
+ static const struct mtk_soc_data mt7986_data = {
+@@ -5165,14 +5189,18 @@ static const struct mtk_soc_data mt7986_data = {
+ .hash_offset = 4,
+ .has_accounting = true,
+ .foe_entry_size = MTK_FOE_ENTRY_V2_SIZE,
+- .txrx = {
+- .txd_size = sizeof(struct mtk_tx_dma_v2),
+- .rxd_size = sizeof(struct mtk_rx_dma_v2),
+- .rx_irq_done_mask = MTK_RX_DONE_INT_V2,
+- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
++ .tx = {
++ .desc_size = sizeof(struct mtk_tx_dma_v2),
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = 8,
+ },
++ .rx = {
++ .desc_size = sizeof(struct mtk_rx_dma),
++ .irq_done_mask = MTK_RX_DONE_INT,
++ .dma_l4_valid = RX_DMA_L4_VALID_V2,
++ .dma_max_len = MTK_TX_DMA_BUF_LEN,
++ .dma_len_offset = 16,
++ },
+ };
+
+ static const struct mtk_soc_data mt7988_data = {
+@@ -5187,11 +5215,15 @@ static const struct mtk_soc_data mt7988_data = {
+ .hash_offset = 4,
+ .has_accounting = true,
+ .foe_entry_size = MTK_FOE_ENTRY_V3_SIZE,
+- .txrx = {
+- .txd_size = sizeof(struct mtk_tx_dma_v2),
+- .rxd_size = sizeof(struct mtk_rx_dma_v2),
+- .rx_irq_done_mask = MTK_RX_DONE_INT_V2,
+- .rx_dma_l4_valid = RX_DMA_L4_VALID_V2,
++ .tx = {
++ .desc_size = sizeof(struct mtk_tx_dma_v2),
++ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
++ .dma_len_offset = 8,
++ },
++ .rx = {
++ .desc_size = sizeof(struct mtk_rx_dma_v2),
++ .irq_done_mask = MTK_RX_DONE_INT_V2,
++ .dma_l4_valid = RX_DMA_L4_VALID_V2,
+ .dma_max_len = MTK_TX_DMA_BUF_LEN_V2,
+ .dma_len_offset = 8,
+ },
+@@ -5204,11 +5236,15 @@ static const struct mtk_soc_data rt5350_data = {
+ .required_clks = MT7628_CLKS_BITMAP,
+ .required_pctl = false,
+ .version = 1,
+- .txrx = {
+- .txd_size = sizeof(struct mtk_tx_dma),
+- .rxd_size = sizeof(struct mtk_rx_dma),
+- .rx_irq_done_mask = MTK_RX_DONE_INT,
+- .rx_dma_l4_valid = RX_DMA_L4_VALID_PDMA,
++ .tx = {
++ .desc_size = sizeof(struct mtk_tx_dma),
++ .dma_max_len = MTK_TX_DMA_BUF_LEN,
++ .dma_len_offset = 16,
++ },
++ .rx = {
++ .desc_size = sizeof(struct mtk_rx_dma),
++ .irq_done_mask = MTK_RX_DONE_INT,
++ .dma_l4_valid = RX_DMA_L4_VALID_PDMA,
+ .dma_max_len = MTK_TX_DMA_BUF_LEN,
+ .dma_len_offset = 16,
+ },
+diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+index 9ae3b8a71d0e6..39b50de1decbf 100644
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -327,8 +327,8 @@
+ /* QDMA descriptor txd3 */
+ #define TX_DMA_OWNER_CPU BIT(31)
+ #define TX_DMA_LS0 BIT(30)
+-#define TX_DMA_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset)
+-#define TX_DMA_PLEN1(x) ((x) & eth->soc->txrx.dma_max_len)
++#define TX_DMA_PLEN0(x) (((x) & eth->soc->tx.dma_max_len) << eth->soc->tx.dma_len_offset)
++#define TX_DMA_PLEN1(x) ((x) & eth->soc->tx.dma_max_len)
+ #define TX_DMA_SWC BIT(14)
+ #define TX_DMA_PQID GENMASK(3, 0)
+ #define TX_DMA_ADDR64_MASK GENMASK(3, 0)
+@@ -348,8 +348,8 @@
+ /* QDMA descriptor rxd2 */
+ #define RX_DMA_DONE BIT(31)
+ #define RX_DMA_LSO BIT(30)
+-#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->txrx.dma_max_len) << eth->soc->txrx.dma_len_offset)
+-#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->txrx.dma_len_offset) & eth->soc->txrx.dma_max_len)
++#define RX_DMA_PREP_PLEN0(x) (((x) & eth->soc->rx.dma_max_len) << eth->soc->rx.dma_len_offset)
++#define RX_DMA_GET_PLEN0(x) (((x) >> eth->soc->rx.dma_len_offset) & eth->soc->rx.dma_max_len)
+ #define RX_DMA_VTAG BIT(15)
+ #define RX_DMA_ADDR64_MASK GENMASK(3, 0)
+ #if IS_ENABLED(CONFIG_64BIT)
+@@ -1153,10 +1153,9 @@ struct mtk_reg_map {
+ * @foe_entry_size Foe table entry size.
+ * @has_accounting Bool indicating support for accounting of
+ * offloaded flows.
+- * @txd_size Tx DMA descriptor size.
+- * @rxd_size Rx DMA descriptor size.
+- * @rx_irq_done_mask Rx irq done register mask.
+- * @rx_dma_l4_valid Rx DMA valid register mask.
++ * @desc_size Tx/Rx DMA descriptor size.
++ * @irq_done_mask Rx irq done register mask.
++ * @dma_l4_valid Rx DMA valid register mask.
+ * @dma_max_len Max DMA tx/rx buffer length.
+ * @dma_len_offset Tx/Rx DMA length field offset.
+ */
+@@ -1174,13 +1173,17 @@ struct mtk_soc_data {
+ bool has_accounting;
+ bool disable_pll_modes;
+ struct {
+- u32 txd_size;
+- u32 rxd_size;
+- u32 rx_irq_done_mask;
+- u32 rx_dma_l4_valid;
++ u32 desc_size;
+ u32 dma_max_len;
+ u32 dma_len_offset;
+- } txrx;
++ } tx;
++ struct {
++ u32 desc_size;
++ u32 irq_done_mask;
++ u32 dma_l4_valid;
++ u32 dma_max_len;
++ u32 dma_len_offset;
++ } rx;
+ };
+
+ #define MTK_DMA_MONITOR_TIMEOUT msecs_to_jiffies(1000)
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+index 4957412ff1f65..20768ef2e9d2b 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+@@ -969,19 +969,32 @@ static void cmd_work_handler(struct work_struct *work)
+ bool poll_cmd = ent->polling;
+ struct mlx5_cmd_layout *lay;
+ struct mlx5_core_dev *dev;
+- unsigned long cb_timeout;
+- struct semaphore *sem;
++ unsigned long timeout;
+ unsigned long flags;
+ int alloc_ret;
+ int cmd_mode;
+
++ complete(&ent->handling);
++
+ dev = container_of(cmd, struct mlx5_core_dev, cmd);
+- cb_timeout = msecs_to_jiffies(mlx5_tout_ms(dev, CMD));
++ timeout = msecs_to_jiffies(mlx5_tout_ms(dev, CMD));
+
+- complete(&ent->handling);
+- sem = ent->page_queue ? &cmd->vars.pages_sem : &cmd->vars.sem;
+- down(sem);
+ if (!ent->page_queue) {
++ if (down_timeout(&cmd->vars.sem, timeout)) {
++ mlx5_core_warn(dev, "%s(0x%x) timed out while waiting for a slot.\n",
++ mlx5_command_str(ent->op), ent->op);
++ if (ent->callback) {
++ ent->callback(-EBUSY, ent->context);
++ mlx5_free_cmd_msg(dev, ent->out);
++ free_msg(dev, ent->in);
++ cmd_ent_put(ent);
++ } else {
++ ent->ret = -EBUSY;
++ complete(&ent->done);
++ }
++ complete(&ent->slotted);
++ return;
++ }
+ alloc_ret = cmd_alloc_index(cmd, ent);
+ if (alloc_ret < 0) {
+ mlx5_core_err_rl(dev, "failed to allocate command entry\n");
+@@ -994,10 +1007,11 @@ static void cmd_work_handler(struct work_struct *work)
+ ent->ret = -EAGAIN;
+ complete(&ent->done);
+ }
+- up(sem);
++ up(&cmd->vars.sem);
+ return;
+ }
+ } else {
++ down(&cmd->vars.pages_sem);
+ ent->idx = cmd->vars.max_reg_cmds;
+ spin_lock_irqsave(&cmd->alloc_lock, flags);
+ clear_bit(ent->idx, &cmd->vars.bitmask);
+@@ -1005,6 +1019,8 @@ static void cmd_work_handler(struct work_struct *work)
+ spin_unlock_irqrestore(&cmd->alloc_lock, flags);
+ }
+
++ complete(&ent->slotted);
++
+ lay = get_inst(cmd, ent->idx);
+ ent->lay = lay;
+ memset(lay, 0, sizeof(*lay));
+@@ -1023,7 +1039,7 @@ static void cmd_work_handler(struct work_struct *work)
+ ent->ts1 = ktime_get_ns();
+ cmd_mode = cmd->mode;
+
+- if (ent->callback && schedule_delayed_work(&ent->cb_timeout_work, cb_timeout))
++ if (ent->callback && schedule_delayed_work(&ent->cb_timeout_work, timeout))
+ cmd_ent_get(ent);
+ set_bit(MLX5_CMD_ENT_STATE_PENDING_COMP, &ent->state);
+
+@@ -1143,6 +1159,9 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
+ ent->ret = -ECANCELED;
+ goto out_err;
+ }
++
++ wait_for_completion(&ent->slotted);
++
+ if (cmd->mode == CMD_MODE_POLLING || ent->polling)
+ wait_for_completion(&ent->done);
+ else if (!wait_for_completion_timeout(&ent->done, timeout))
+@@ -1157,6 +1176,9 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
+ } else if (err == -ECANCELED) {
+ mlx5_core_warn(dev, "%s(0x%x) canceled on out of queue timeout.\n",
+ mlx5_command_str(ent->op), ent->op);
++ } else if (err == -EBUSY) {
++ mlx5_core_warn(dev, "%s(0x%x) timeout while waiting for command semaphore.\n",
++ mlx5_command_str(ent->op), ent->op);
+ }
+ mlx5_core_dbg(dev, "err %d, delivery status %s(%d)\n",
+ err, deliv_status_to_str(ent->status), ent->status);
+@@ -1208,6 +1230,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
+ ent->polling = force_polling;
+
+ init_completion(&ent->handling);
++ init_completion(&ent->slotted);
+ if (!callback)
+ init_completion(&ent->done);
+
+@@ -1225,7 +1248,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
+ return 0; /* mlx5_cmd_comp_handler() will put(ent) */
+
+ err = wait_func(dev, ent);
+- if (err == -ETIMEDOUT || err == -ECANCELED)
++ if (err == -ETIMEDOUT || err == -ECANCELED || err == -EBUSY)
+ goto out_free;
+
+ ds = ent->ts2 - ent->ts1;
+@@ -1611,6 +1634,9 @@ static int cmd_comp_notifier(struct notifier_block *nb,
+ dev = container_of(cmd, struct mlx5_core_dev, cmd);
+ eqe = data;
+
++ if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
++ return NOTIFY_DONE;
++
+ mlx5_cmd_comp_handler(dev, be32_to_cpu(eqe->data.cmd.vector), false);
+
+ return NOTIFY_OK;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
+index 82e6abbc17342..c969b8e709804 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
+@@ -28,8 +28,10 @@ bool mlx5e_validate_xsk_param(struct mlx5e_params *params,
+ struct mlx5e_xsk_param *xsk,
+ struct mlx5_core_dev *mdev)
+ {
+- /* AF_XDP doesn't support frames larger than PAGE_SIZE. */
+- if (xsk->chunk_size > PAGE_SIZE || xsk->chunk_size < MLX5E_MIN_XSK_CHUNK_SIZE) {
++ /* AF_XDP doesn't support frames larger than PAGE_SIZE,
++ * and xsk->chunk_size is limited to 65535 bytes.
++ */
++ if ((size_t)xsk->chunk_size > PAGE_SIZE || xsk->chunk_size < MLX5E_MIN_XSK_CHUNK_SIZE) {
+ mlx5_core_err(mdev, "XSK chunk size %u out of bounds [%u, %lu]\n", xsk->chunk_size,
+ MLX5E_MIN_XSK_CHUNK_SIZE, PAGE_SIZE);
+ return false;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
+index 1b9bc32efd6fa..c5ea1d1d2b035 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
+@@ -1874,7 +1874,7 @@ int mlx5_esw_bridge_port_mdb_add(struct net_device *dev, u16 vport_num, u16 esw_
+ "Failed to lookup bridge port vlan metadata to create MDB (MAC=%pM,vid=%u,vport=%u)\n",
+ addr, vid, vport_num);
+ NL_SET_ERR_MSG_FMT_MOD(extack,
+- "Failed to lookup bridge port vlan metadata to create MDB (MAC=%pM,vid=%u,vport=%u)\n",
++ "Failed to lookup vlan metadata for MDB (MAC=%pM,vid=%u,vport=%u)\n",
+ addr, vid, vport_num);
+ return -EINVAL;
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+index 349e28a6dd8df..ef55674876cb4 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+@@ -833,7 +833,7 @@ int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw,
+ struct mlx5_eswitch *slave_esw, int max_slaves);
+ void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw,
+ struct mlx5_eswitch *slave_esw);
+-int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw);
++int mlx5_eswitch_reload_ib_reps(struct mlx5_eswitch *esw);
+
+ bool mlx5_eswitch_block_encap(struct mlx5_core_dev *dev);
+ void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev);
+@@ -925,7 +925,7 @@ mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw,
+ static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw) { return 0; }
+
+ static inline int
+-mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw)
++mlx5_eswitch_reload_ib_reps(struct mlx5_eswitch *esw)
+ {
+ return 0;
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+index e3cce110e52fd..58529d1a98b37 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+@@ -2501,6 +2501,16 @@ void esw_offloads_cleanup(struct mlx5_eswitch *esw)
+ esw_offloads_cleanup_reps(esw);
+ }
+
++static int __esw_offloads_load_rep(struct mlx5_eswitch *esw,
++ struct mlx5_eswitch_rep *rep, u8 rep_type)
++{
++ if (atomic_cmpxchg(&rep->rep_data[rep_type].state,
++ REP_REGISTERED, REP_LOADED) == REP_REGISTERED)
++ return esw->offloads.rep_ops[rep_type]->load(esw->dev, rep);
++
++ return 0;
++}
++
+ static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw,
+ struct mlx5_eswitch_rep *rep, u8 rep_type)
+ {
+@@ -2525,13 +2535,11 @@ static int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num)
+ int err;
+
+ rep = mlx5_eswitch_get_rep(esw, vport_num);
+- for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++)
+- if (atomic_cmpxchg(&rep->rep_data[rep_type].state,
+- REP_REGISTERED, REP_LOADED) == REP_REGISTERED) {
+- err = esw->offloads.rep_ops[rep_type]->load(esw->dev, rep);
+- if (err)
+- goto err_reps;
+- }
++ for (rep_type = 0; rep_type < NUM_REP_TYPES; rep_type++) {
++ err = __esw_offloads_load_rep(esw, rep, rep_type);
++ if (err)
++ goto err_reps;
++ }
+
+ return 0;
+
+@@ -3276,7 +3284,7 @@ static void esw_destroy_offloads_acl_tables(struct mlx5_eswitch *esw)
+ esw_vport_destroy_offloads_acl_tables(esw, vport);
+ }
+
+-int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw)
++int mlx5_eswitch_reload_ib_reps(struct mlx5_eswitch *esw)
+ {
+ struct mlx5_eswitch_rep *rep;
+ unsigned long i;
+@@ -3289,13 +3297,13 @@ int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw)
+ if (atomic_read(&rep->rep_data[REP_ETH].state) != REP_LOADED)
+ return 0;
+
+- ret = mlx5_esw_offloads_rep_load(esw, MLX5_VPORT_UPLINK);
++ ret = __esw_offloads_load_rep(esw, rep, REP_IB);
+ if (ret)
+ return ret;
+
+ mlx5_esw_for_each_rep(esw, i, rep) {
+ if (atomic_read(&rep->rep_data[REP_ETH].state) == REP_LOADED)
+- mlx5_esw_offloads_rep_load(esw, rep->vport);
++ __esw_offloads_load_rep(esw, rep, REP_IB);
+ }
+
+ return 0;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+index 69d482f7c5a29..37598d116f3b8 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+@@ -814,7 +814,7 @@ void mlx5_disable_lag(struct mlx5_lag *ldev)
+ if (shared_fdb)
+ for (i = 0; i < ldev->ports; i++)
+ if (!(ldev->pf[i].dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV))
+- mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
++ mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch);
+ }
+
+ static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
+@@ -922,7 +922,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
+ mlx5_rescan_drivers_locked(dev0);
+
+ for (i = 0; i < ldev->ports; i++) {
+- err = mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
++ err = mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch);
+ if (err)
+ break;
+ }
+@@ -933,7 +933,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
+ mlx5_deactivate_lag(ldev);
+ mlx5_lag_add_devices(ldev);
+ for (i = 0; i < ldev->ports; i++)
+- mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
++ mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch);
+ mlx5_core_err(dev0, "Failed to enable lag\n");
+ return;
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
+index 82889f30506ea..571ea26edd0ca 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
+@@ -99,7 +99,7 @@ static int enable_mpesw(struct mlx5_lag *ldev)
+ dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
+ mlx5_rescan_drivers_locked(dev0);
+ for (i = 0; i < ldev->ports; i++) {
+- err = mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
++ err = mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch);
+ if (err)
+ goto err_rescan_drivers;
+ }
+@@ -113,7 +113,7 @@ static int enable_mpesw(struct mlx5_lag *ldev)
+ err_add_devices:
+ mlx5_lag_add_devices(ldev);
+ for (i = 0; i < ldev->ports; i++)
+- mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
++ mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch);
+ mlx5_mpesw_metadata_cleanup(ldev);
+ return err;
+ }
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
+index e285823bd08f0..0288e19e3a68e 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
+@@ -1680,6 +1680,8 @@ int mlx5_init_one_light(struct mlx5_core_dev *dev)
+ struct devlink *devlink = priv_to_devlink(dev);
+ int err;
+
++ devl_lock(devlink);
++ devl_register(devlink);
+ dev->state = MLX5_DEVICE_STATE_UP;
+ err = mlx5_function_enable(dev, true, mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT));
+ if (err) {
+@@ -1693,27 +1695,21 @@ int mlx5_init_one_light(struct mlx5_core_dev *dev)
+ goto query_hca_caps_err;
+ }
+
+- devl_lock(devlink);
+- devl_register(devlink);
+-
+ err = mlx5_devlink_params_register(priv_to_devlink(dev));
+ if (err) {
+ mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err);
+- goto params_reg_err;
++ goto query_hca_caps_err;
+ }
+
+ devl_unlock(devlink);
+ return 0;
+
+-params_reg_err:
+- devl_unregister(devlink);
+- devl_unlock(devlink);
+ query_hca_caps_err:
+- devl_unregister(devlink);
+- devl_unlock(devlink);
+ mlx5_function_disable(dev, true);
+ out:
+ dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
++ devl_unregister(devlink);
++ devl_unlock(devlink);
+ return err;
+ }
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
+index 7ebe712808275..b2986175d9afe 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c
+@@ -60,6 +60,13 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
+ goto remap_err;
+ }
+
++ /* Peer devlink logic expects to work on unregistered devlink instance. */
++ err = mlx5_core_peer_devlink_set(sf_dev, devlink);
++ if (err) {
++ mlx5_core_warn(mdev, "mlx5_core_peer_devlink_set err=%d\n", err);
++ goto peer_devlink_set_err;
++ }
++
+ if (MLX5_ESWITCH_MANAGER(sf_dev->parent_mdev))
+ err = mlx5_init_one_light(mdev);
+ else
+@@ -69,20 +76,10 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia
+ goto init_one_err;
+ }
+
+- err = mlx5_core_peer_devlink_set(sf_dev, devlink);
+- if (err) {
+- mlx5_core_warn(mdev, "mlx5_core_peer_devlink_set err=%d\n", err);
+- goto peer_devlink_set_err;
+- }
+-
+ return 0;
+
+-peer_devlink_set_err:
+- if (mlx5_dev_is_lightweight(sf_dev->mdev))
+- mlx5_uninit_one_light(sf_dev->mdev);
+- else
+- mlx5_uninit_one(sf_dev->mdev);
+ init_one_err:
++peer_devlink_set_err:
+ iounmap(mdev->iseg);
+ remap_err:
+ mlx5_mdev_uninit(mdev);
+diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+index 2635ef8958c80..61d88207eed42 100644
+--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+@@ -1087,8 +1087,6 @@ static int lan966x_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, lan966x);
+ lan966x->dev = &pdev->dev;
+
+- lan966x->debugfs_root = debugfs_create_dir("lan966x", NULL);
+-
+ if (!device_get_mac_address(&pdev->dev, mac_addr)) {
+ ether_addr_copy(lan966x->base_mac, mac_addr);
+ } else {
+@@ -1179,6 +1177,8 @@ static int lan966x_probe(struct platform_device *pdev)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "no ethernet-ports child found\n");
+
++ lan966x->debugfs_root = debugfs_create_dir("lan966x", NULL);
++
+ /* init switch */
+ lan966x_init(lan966x);
+ lan966x_stats_init(lan966x);
+@@ -1257,6 +1257,8 @@ static int lan966x_probe(struct platform_device *pdev)
+ destroy_workqueue(lan966x->stats_queue);
+ mutex_destroy(&lan966x->stats_lock);
+
++ debugfs_remove_recursive(lan966x->debugfs_root);
++
+ return err;
+ }
+
+diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c
+index 2729a2c5acf9c..ca814fe8a775b 100644
+--- a/drivers/net/ethernet/microsoft/mana/hw_channel.c
++++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c
+@@ -848,7 +848,7 @@ int mana_hwc_send_request(struct hw_channel_context *hwc, u32 req_len,
+ }
+
+ if (!wait_for_completion_timeout(&ctx->comp_event,
+- (msecs_to_jiffies(hwc->hwc_timeout) * HZ))) {
++ (msecs_to_jiffies(hwc->hwc_timeout)))) {
+ dev_err(hwc->dev, "HWC: Request timed out!\n");
+ err = -ETIMEDOUT;
+ goto out;
+diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
+index c278f8893042b..8159b4c315b5d 100644
+--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
++++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
+@@ -1206,7 +1206,6 @@ static void qed_slowpath_task(struct work_struct *work)
+ static int qed_slowpath_wq_start(struct qed_dev *cdev)
+ {
+ struct qed_hwfn *hwfn;
+- char name[NAME_SIZE];
+ int i;
+
+ if (IS_VF(cdev))
+@@ -1215,11 +1214,11 @@ static int qed_slowpath_wq_start(struct qed_dev *cdev)
+ for_each_hwfn(cdev, i) {
+ hwfn = &cdev->hwfns[i];
+
+- snprintf(name, NAME_SIZE, "slowpath-%02x:%02x.%02x",
+- cdev->pdev->bus->number,
+- PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id);
++ hwfn->slowpath_wq = alloc_workqueue("slowpath-%02x:%02x.%02x",
++ 0, 0, cdev->pdev->bus->number,
++ PCI_SLOT(cdev->pdev->devfn),
++ hwfn->abs_pf_id);
+
+- hwfn->slowpath_wq = alloc_workqueue(name, 0, 0);
+ if (!hwfn->slowpath_wq) {
+ DP_NOTICE(hwfn, "Cannot create slowpath workqueue\n");
+ return -ENOMEM;
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index 32b73f3988e8c..70d0b32395cde 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -4221,11 +4221,11 @@ static void rtl8169_doorbell(struct rtl8169_private *tp)
+ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+ {
+- unsigned int frags = skb_shinfo(skb)->nr_frags;
+ struct rtl8169_private *tp = netdev_priv(dev);
+ unsigned int entry = tp->cur_tx % NUM_TX_DESC;
+ struct TxDesc *txd_first, *txd_last;
+ bool stop_queue, door_bell;
++ unsigned int frags;
+ u32 opts[2];
+
+ if (unlikely(!rtl_tx_slots_avail(tp))) {
+@@ -4248,6 +4248,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
+
+ txd_first = tp->TxDescArray + entry;
+
++ frags = skb_shinfo(skb)->nr_frags;
+ if (frags) {
+ if (rtl8169_xmit_frags(tp, skb, opts, entry))
+ goto err_dma_1;
+@@ -4541,10 +4542,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
+ rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
+ }
+
+- if (napi_schedule_prep(&tp->napi)) {
+- rtl_irq_disable(tp);
+- __napi_schedule(&tp->napi);
+- }
++ rtl_irq_disable(tp);
++ napi_schedule(&tp->napi);
+ out:
+ rtl_ack_events(tp, status);
+
+diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
+index 46eee747c6992..45ef5ac0788a8 100644
+--- a/drivers/net/ethernet/smsc/smc91x.h
++++ b/drivers/net/ethernet/smsc/smc91x.h
+@@ -156,8 +156,8 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
+ writew(*wp++, a);
+ }
+
+-#define SMC_inw(a, r) _swapw(readw((a) + (r)))
+-#define SMC_outw(lp, v, a, r) writew(_swapw(v), (a) + (r))
++#define SMC_inw(a, r) ioread16be((a) + (r))
++#define SMC_outw(lp, v, a, r) iowrite16be(v, (a) + (r))
+ #define SMC_insw(a, r, p, l) mcf_insw(a + r, p, l)
+ #define SMC_outsw(a, r, p, l) mcf_outsw(a + r, p, l)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
+index 5a1d46dcd5de0..618d455b457c7 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/common.h
++++ b/drivers/net/ethernet/stmicro/stmmac/common.h
+@@ -225,6 +225,8 @@ struct stmmac_extra_stats {
+ unsigned long mtl_est_hlbf;
+ unsigned long mtl_est_btre;
+ unsigned long mtl_est_btrlm;
++ unsigned long max_sdu_txq_drop[MTL_MAX_TX_QUEUES];
++ unsigned long mtl_est_txq_hlbf[MTL_MAX_TX_QUEUES];
+ /* per queue statistics */
+ struct stmmac_txq_stats txq_stats[MTL_MAX_TX_QUEUES];
+ struct stmmac_rxq_stats rxq_stats[MTL_MAX_RX_QUEUES];
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+index f155e4841c62b..1db1359d154f3 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+@@ -260,6 +260,8 @@ struct stmmac_priv {
+ struct stmmac_extra_stats xstats ____cacheline_aligned_in_smp;
+ struct stmmac_safety_stats sstats;
+ struct plat_stmmacenet_data *plat;
++ /* Protect est parameters */
++ struct mutex est_lock;
+ struct dma_features dma_cap;
+ struct stmmac_counters mmc;
+ int hw_cap_support;
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_est.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_est.c
+index 4da6ccc17c205..c9693f77e1f61 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_est.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_est.c
+@@ -81,6 +81,7 @@ static void est_irq_status(struct stmmac_priv *priv, struct net_device *dev,
+ u32 status, value, feqn, hbfq, hbfs, btrl, btrl_max;
+ void __iomem *est_addr = priv->estaddr;
+ u32 txqcnt_mask = BIT(txqcnt) - 1;
++ int i;
+
+ status = readl(est_addr + EST_STATUS);
+
+@@ -125,6 +126,11 @@ static void est_irq_status(struct stmmac_priv *priv, struct net_device *dev,
+
+ x->mtl_est_hlbf++;
+
++ for (i = 0; i < txqcnt; i++) {
++ if (feqn & BIT(i))
++ x->mtl_est_txq_hlbf[i]++;
++ }
++
+ /* Clear Interrupt */
+ writel(feqn, est_addr + EST_FRM_SZ_ERR);
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 83b732c30c1bb..12f4c0da838da 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -2491,6 +2491,13 @@ static bool stmmac_xdp_xmit_zc(struct stmmac_priv *priv, u32 queue, u32 budget)
+ if (!xsk_tx_peek_desc(pool, &xdp_desc))
+ break;
+
++ if (priv->plat->est && priv->plat->est->enable &&
++ priv->plat->est->max_sdu[queue] &&
++ xdp_desc.len > priv->plat->est->max_sdu[queue]) {
++ priv->xstats.max_sdu_txq_drop[queue]++;
++ continue;
++ }
++
+ if (likely(priv->extend_desc))
+ tx_desc = (struct dma_desc *)(tx_q->dma_etx + entry);
+ else if (tx_q->tbs & STMMAC_TBS_AVAIL)
+@@ -4485,6 +4492,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
+ return stmmac_tso_xmit(skb, dev);
+ }
+
++ if (priv->plat->est && priv->plat->est->enable &&
++ priv->plat->est->max_sdu[queue] &&
++ skb->len > priv->plat->est->max_sdu[queue]){
++ priv->xstats.max_sdu_txq_drop[queue]++;
++ goto max_sdu_err;
++ }
++
+ if (unlikely(stmmac_tx_avail(priv, queue) < nfrags + 1)) {
+ if (!netif_tx_queue_stopped(netdev_get_tx_queue(dev, queue))) {
+ netif_tx_stop_queue(netdev_get_tx_queue(priv->dev,
+@@ -4702,6 +4716,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ dma_map_err:
+ netdev_err(priv->dev, "Tx DMA map failed\n");
++max_sdu_err:
+ dev_kfree_skb(skb);
+ priv->xstats.tx_dropped++;
+ return NETDEV_TX_OK;
+@@ -4858,6 +4873,13 @@ static int stmmac_xdp_xmit_xdpf(struct stmmac_priv *priv, int queue,
+ if (stmmac_tx_avail(priv, queue) < STMMAC_TX_THRESH(priv))
+ return STMMAC_XDP_CONSUMED;
+
++ if (priv->plat->est && priv->plat->est->enable &&
++ priv->plat->est->max_sdu[queue] &&
++ xdpf->len > priv->plat->est->max_sdu[queue]) {
++ priv->xstats.max_sdu_txq_drop[queue]++;
++ return STMMAC_XDP_CONSUMED;
++ }
++
+ if (likely(priv->extend_desc))
+ tx_desc = (struct dma_desc *)(tx_q->dma_etx + entry);
+ else if (tx_q->tbs & STMMAC_TBS_AVAIL)
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+index e04830a3a1fb1..0c5aab6dd7a73 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+@@ -70,11 +70,11 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
+ /* If EST is enabled, disabled it before adjust ptp time. */
+ if (priv->plat->est && priv->plat->est->enable) {
+ est_rst = true;
+- mutex_lock(&priv->plat->est->lock);
++ mutex_lock(&priv->est_lock);
+ priv->plat->est->enable = false;
+ stmmac_est_configure(priv, priv, priv->plat->est,
+ priv->plat->clk_ptp_rate);
+- mutex_unlock(&priv->plat->est->lock);
++ mutex_unlock(&priv->est_lock);
+ }
+
+ write_lock_irqsave(&priv->ptp_lock, flags);
+@@ -87,7 +87,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
+ ktime_t current_time_ns, basetime;
+ u64 cycle_time;
+
+- mutex_lock(&priv->plat->est->lock);
++ mutex_lock(&priv->est_lock);
+ priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, ¤t_time);
+ current_time_ns = timespec64_to_ktime(current_time);
+ time.tv_nsec = priv->plat->est->btr_reserve[0];
+@@ -104,7 +104,7 @@ static int stmmac_adjust_time(struct ptp_clock_info *ptp, s64 delta)
+ priv->plat->est->enable = true;
+ ret = stmmac_est_configure(priv, priv, priv->plat->est,
+ priv->plat->clk_ptp_rate);
+- mutex_unlock(&priv->plat->est->lock);
++ mutex_unlock(&priv->est_lock);
+ if (ret)
+ netdev_err(priv->dev, "failed to configure EST\n");
+ }
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+index 26fa33e5ec34f..620c16e9be3a6 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+@@ -915,8 +915,30 @@ struct timespec64 stmmac_calc_tas_basetime(ktime_t old_base_time,
+ return time;
+ }
+
+-static int tc_setup_taprio(struct stmmac_priv *priv,
+- struct tc_taprio_qopt_offload *qopt)
++static void tc_taprio_map_maxsdu_txq(struct stmmac_priv *priv,
++ struct tc_taprio_qopt_offload *qopt)
++{
++ struct plat_stmmacenet_data *plat = priv->plat;
++ u32 num_tc = qopt->mqprio.qopt.num_tc;
++ u32 offset, count, i, j;
++
++ /* QueueMaxSDU received from the driver corresponds to the Linux traffic
++ * class. Map queueMaxSDU per Linux traffic class to DWMAC Tx queues.
++ */
++ for (i = 0; i < num_tc; i++) {
++ if (!qopt->max_sdu[i])
++ continue;
++
++ offset = qopt->mqprio.qopt.offset[i];
++ count = qopt->mqprio.qopt.count[i];
++
++ for (j = offset; j < offset + count; j++)
++ plat->est->max_sdu[j] = qopt->max_sdu[i] + ETH_HLEN - ETH_TLEN;
++ }
++}
++
++static int tc_taprio_configure(struct stmmac_priv *priv,
++ struct tc_taprio_qopt_offload *qopt)
+ {
+ u32 size, wid = priv->dma_cap.estwid, dep = priv->dma_cap.estdep;
+ struct plat_stmmacenet_data *plat = priv->plat;
+@@ -968,8 +990,6 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
+
+ if (qopt->cmd == TAPRIO_CMD_DESTROY)
+ goto disable;
+- else if (qopt->cmd != TAPRIO_CMD_REPLACE)
+- return -EOPNOTSUPP;
+
+ if (qopt->num_entries >= dep)
+ return -EINVAL;
+@@ -984,17 +1004,19 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
+ if (!plat->est)
+ return -ENOMEM;
+
+- mutex_init(&priv->plat->est->lock);
++ mutex_init(&priv->est_lock);
+ } else {
++ mutex_lock(&priv->est_lock);
+ memset(plat->est, 0, sizeof(*plat->est));
++ mutex_unlock(&priv->est_lock);
+ }
+
+ size = qopt->num_entries;
+
+- mutex_lock(&priv->plat->est->lock);
++ mutex_lock(&priv->est_lock);
+ priv->plat->est->gcl_size = size;
+ priv->plat->est->enable = qopt->cmd == TAPRIO_CMD_REPLACE;
+- mutex_unlock(&priv->plat->est->lock);
++ mutex_unlock(&priv->est_lock);
+
+ for (i = 0; i < size; i++) {
+ s64 delta_ns = qopt->entries[i].interval;
+@@ -1025,7 +1047,7 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
+ priv->plat->est->gcl[i] = delta_ns | (gates << wid);
+ }
+
+- mutex_lock(&priv->plat->est->lock);
++ mutex_lock(&priv->est_lock);
+ /* Adjust for real system time */
+ priv->ptp_clock_ops.gettime64(&priv->ptp_clock_ops, ¤t_time);
+ current_time_ns = timespec64_to_ktime(current_time);
+@@ -1045,8 +1067,10 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
+
+ priv->plat->est->ter = qopt->cycle_time_extension;
+
++ tc_taprio_map_maxsdu_txq(priv, qopt);
++
+ if (fpe && !priv->dma_cap.fpesel) {
+- mutex_unlock(&priv->plat->est->lock);
++ mutex_unlock(&priv->est_lock);
+ return -EOPNOTSUPP;
+ }
+
+@@ -1057,7 +1081,7 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
+
+ ret = stmmac_est_configure(priv, priv, priv->plat->est,
+ priv->plat->clk_ptp_rate);
+- mutex_unlock(&priv->plat->est->lock);
++ mutex_unlock(&priv->est_lock);
+ if (ret) {
+ netdev_err(priv->dev, "failed to configure EST\n");
+ goto disable;
+@@ -1074,11 +1098,16 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
+
+ disable:
+ if (priv->plat->est) {
+- mutex_lock(&priv->plat->est->lock);
++ mutex_lock(&priv->est_lock);
+ priv->plat->est->enable = false;
+ stmmac_est_configure(priv, priv, priv->plat->est,
+ priv->plat->clk_ptp_rate);
+- mutex_unlock(&priv->plat->est->lock);
++ /* Reset taprio status */
++ for (i = 0; i < priv->plat->tx_queues_to_use; i++) {
++ priv->xstats.max_sdu_txq_drop[i] = 0;
++ priv->xstats.mtl_est_txq_hlbf[i] = 0;
++ }
++ mutex_unlock(&priv->est_lock);
+ }
+
+ priv->plat->fpe_cfg->enable = false;
+@@ -1095,6 +1124,57 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
+ return ret;
+ }
+
++static void tc_taprio_stats(struct stmmac_priv *priv,
++ struct tc_taprio_qopt_offload *qopt)
++{
++ u64 window_drops = 0;
++ int i = 0;
++
++ for (i = 0; i < priv->plat->tx_queues_to_use; i++)
++ window_drops += priv->xstats.max_sdu_txq_drop[i] +
++ priv->xstats.mtl_est_txq_hlbf[i];
++ qopt->stats.window_drops = window_drops;
++
++ /* Transmission overrun doesn't happen for stmmac, hence always 0 */
++ qopt->stats.tx_overruns = 0;
++}
++
++static void tc_taprio_queue_stats(struct stmmac_priv *priv,
++ struct tc_taprio_qopt_offload *qopt)
++{
++ struct tc_taprio_qopt_queue_stats *q_stats = &qopt->queue_stats;
++ int queue = qopt->queue_stats.queue;
++
++ q_stats->stats.window_drops = priv->xstats.max_sdu_txq_drop[queue] +
++ priv->xstats.mtl_est_txq_hlbf[queue];
++
++ /* Transmission overrun doesn't happen for stmmac, hence always 0 */
++ q_stats->stats.tx_overruns = 0;
++}
++
++static int tc_setup_taprio(struct stmmac_priv *priv,
++ struct tc_taprio_qopt_offload *qopt)
++{
++ int err = 0;
++
++ switch (qopt->cmd) {
++ case TAPRIO_CMD_REPLACE:
++ case TAPRIO_CMD_DESTROY:
++ err = tc_taprio_configure(priv, qopt);
++ break;
++ case TAPRIO_CMD_STATS:
++ tc_taprio_stats(priv, qopt);
++ break;
++ case TAPRIO_CMD_QUEUE_STATS:
++ tc_taprio_queue_stats(priv, qopt);
++ break;
++ default:
++ err = -EOPNOTSUPP;
++ }
++
++ return err;
++}
++
+ static int tc_setup_etf(struct stmmac_priv *priv,
+ struct tc_etf_qopt_offload *qopt)
+ {
+@@ -1126,6 +1206,7 @@ static int tc_query_caps(struct stmmac_priv *priv,
+ return -EOPNOTSUPP;
+
+ caps->gate_mask_per_txq = true;
++ caps->supports_queue_max_sdu = true;
+
+ return 0;
+ }
+diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
+index 9bd1df8308d24..d3a2fbb14140e 100644
+--- a/drivers/net/ethernet/sun/sungem.c
++++ b/drivers/net/ethernet/sun/sungem.c
+@@ -949,17 +949,6 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
+ return IRQ_HANDLED;
+ }
+
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+-static void gem_poll_controller(struct net_device *dev)
+-{
+- struct gem *gp = netdev_priv(dev);
+-
+- disable_irq(gp->pdev->irq);
+- gem_interrupt(gp->pdev->irq, dev);
+- enable_irq(gp->pdev->irq);
+-}
+-#endif
+-
+ static void gem_tx_timeout(struct net_device *dev, unsigned int txqueue)
+ {
+ struct gem *gp = netdev_priv(dev);
+@@ -2839,9 +2828,6 @@ static const struct net_device_ops gem_netdev_ops = {
+ .ndo_change_mtu = gem_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = gem_set_mac_address,
+-#ifdef CONFIG_NET_POLL_CONTROLLER
+- .ndo_poll_controller = gem_poll_controller,
+-#endif
+ };
+
+ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+index 4a78e8a1cabf4..3fa49448a74bb 100644
+--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
++++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+@@ -2156,7 +2156,12 @@ static int prueth_probe(struct platform_device *pdev)
+
+ prueth->registered_netdevs[PRUETH_MAC0] = prueth->emac[PRUETH_MAC0]->ndev;
+
+- emac_phy_connect(prueth->emac[PRUETH_MAC0]);
++ ret = emac_phy_connect(prueth->emac[PRUETH_MAC0]);
++ if (ret) {
++ dev_err(dev,
++ "can't connect to MII0 PHY, error -%d", ret);
++ goto netdev_unregister;
++ }
+ phy_attached_info(prueth->emac[PRUETH_MAC0]->ndev->phydev);
+ }
+
+@@ -2168,7 +2173,12 @@ static int prueth_probe(struct platform_device *pdev)
+ }
+
+ prueth->registered_netdevs[PRUETH_MAC1] = prueth->emac[PRUETH_MAC1]->ndev;
+- emac_phy_connect(prueth->emac[PRUETH_MAC1]);
++ ret = emac_phy_connect(prueth->emac[PRUETH_MAC1]);
++ if (ret) {
++ dev_err(dev,
++ "can't connect to MII1 PHY, error %d", ret);
++ goto netdev_unregister;
++ }
+ phy_attached_info(prueth->emac[PRUETH_MAC1]->ndev->phydev);
+ }
+
+diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+index 1db754615cca3..c09a6f7445754 100644
+--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
++++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+@@ -1958,7 +1958,7 @@ int wx_sw_init(struct wx *wx)
+ return -ENOMEM;
+ }
+
+- wx->msix_in_use = false;
++ bitmap_zero(wx->state, WX_STATE_NBITS);
+
+ return 0;
+ }
+diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+index 08d3e4069c5fa..c87afe5de1dd8 100644
+--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
++++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+@@ -1614,14 +1614,12 @@ static int wx_acquire_msix_vectors(struct wx *wx)
+ /* One for non-queue interrupts */
+ nvecs += 1;
+
+- if (!wx->msix_in_use) {
+- wx->msix_entry = kcalloc(1, sizeof(struct msix_entry),
+- GFP_KERNEL);
+- if (!wx->msix_entry) {
+- kfree(wx->msix_q_entries);
+- wx->msix_q_entries = NULL;
+- return -ENOMEM;
+- }
++ wx->msix_entry = kcalloc(1, sizeof(struct msix_entry),
++ GFP_KERNEL);
++ if (!wx->msix_entry) {
++ kfree(wx->msix_q_entries);
++ wx->msix_q_entries = NULL;
++ return -ENOMEM;
+ }
+
+ nvecs = pci_alloc_irq_vectors_affinity(wx->pdev, nvecs,
+@@ -1931,10 +1929,8 @@ void wx_reset_interrupt_capability(struct wx *wx)
+ if (pdev->msix_enabled) {
+ kfree(wx->msix_q_entries);
+ wx->msix_q_entries = NULL;
+- if (!wx->msix_in_use) {
+- kfree(wx->msix_entry);
+- wx->msix_entry = NULL;
+- }
++ kfree(wx->msix_entry);
++ wx->msix_entry = NULL;
+ }
+ pci_free_irq_vectors(wx->pdev);
+ }
+@@ -2694,15 +2690,63 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)
+ wx->rss_enabled = false;
+ }
+
+- if (changed &
+- (NETIF_F_HW_VLAN_CTAG_RX |
+- NETIF_F_HW_VLAN_STAG_RX))
++ netdev->features = features;
++
++ if (wx->mac.type == wx_mac_sp && changed & NETIF_F_HW_VLAN_CTAG_RX)
++ wx->do_reset(netdev);
++ else if (changed & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER))
+ wx_set_rx_mode(netdev);
+
+- return 1;
++ return 0;
+ }
+ EXPORT_SYMBOL(wx_set_features);
+
++#define NETIF_VLAN_STRIPPING_FEATURES (NETIF_F_HW_VLAN_CTAG_RX | \
++ NETIF_F_HW_VLAN_STAG_RX)
++
++#define NETIF_VLAN_INSERTION_FEATURES (NETIF_F_HW_VLAN_CTAG_TX | \
++ NETIF_F_HW_VLAN_STAG_TX)
++
++#define NETIF_VLAN_FILTERING_FEATURES (NETIF_F_HW_VLAN_CTAG_FILTER | \
++ NETIF_F_HW_VLAN_STAG_FILTER)
++
++netdev_features_t wx_fix_features(struct net_device *netdev,
++ netdev_features_t features)
++{
++ netdev_features_t changed = netdev->features ^ features;
++ struct wx *wx = netdev_priv(netdev);
++
++ if (changed & NETIF_VLAN_STRIPPING_FEATURES) {
++ if ((features & NETIF_VLAN_STRIPPING_FEATURES) != NETIF_VLAN_STRIPPING_FEATURES &&
++ (features & NETIF_VLAN_STRIPPING_FEATURES) != 0) {
++ features &= ~NETIF_VLAN_STRIPPING_FEATURES;
++ features |= netdev->features & NETIF_VLAN_STRIPPING_FEATURES;
++ wx_err(wx, "802.1Q and 802.1ad VLAN stripping must be either both on or both off.");
++ }
++ }
++
++ if (changed & NETIF_VLAN_INSERTION_FEATURES) {
++ if ((features & NETIF_VLAN_INSERTION_FEATURES) != NETIF_VLAN_INSERTION_FEATURES &&
++ (features & NETIF_VLAN_INSERTION_FEATURES) != 0) {
++ features &= ~NETIF_VLAN_INSERTION_FEATURES;
++ features |= netdev->features & NETIF_VLAN_INSERTION_FEATURES;
++ wx_err(wx, "802.1Q and 802.1ad VLAN insertion must be either both on or both off.");
++ }
++ }
++
++ if (changed & NETIF_VLAN_FILTERING_FEATURES) {
++ if ((features & NETIF_VLAN_FILTERING_FEATURES) != NETIF_VLAN_FILTERING_FEATURES &&
++ (features & NETIF_VLAN_FILTERING_FEATURES) != 0) {
++ features &= ~NETIF_VLAN_FILTERING_FEATURES;
++ features |= netdev->features & NETIF_VLAN_FILTERING_FEATURES;
++ wx_err(wx, "802.1Q and 802.1ad VLAN filtering must be either both on or both off.");
++ }
++ }
++
++ return features;
++}
++EXPORT_SYMBOL(wx_fix_features);
++
+ void wx_set_ring(struct wx *wx, u32 new_tx_count,
+ u32 new_rx_count, struct wx_ring *temp_ring)
+ {
+diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
+index ec909e876720c..c41b29ea812ff 100644
+--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h
++++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
+@@ -30,6 +30,8 @@ int wx_setup_resources(struct wx *wx);
+ void wx_get_stats64(struct net_device *netdev,
+ struct rtnl_link_stats64 *stats);
+ int wx_set_features(struct net_device *netdev, netdev_features_t features);
++netdev_features_t wx_fix_features(struct net_device *netdev,
++ netdev_features_t features);
+ void wx_set_ring(struct wx *wx, u32 new_tx_count,
+ u32 new_rx_count, struct wx_ring *temp_ring);
+
+diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
+index b4dc4f3411174..5aaf7b1fa2db9 100644
+--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
++++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
+@@ -982,8 +982,13 @@ struct wx_hw_stats {
+ u64 qmprc;
+ };
+
++enum wx_state {
++ WX_STATE_RESETTING,
++ WX_STATE_NBITS, /* must be last */
++};
+ struct wx {
+ unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
++ DECLARE_BITMAP(state, WX_STATE_NBITS);
+
+ void *priv;
+ u8 __iomem *hw_addr;
+@@ -1047,7 +1052,6 @@ struct wx {
+ unsigned int queues_per_pool;
+ struct msix_entry *msix_q_entries;
+ struct msix_entry *msix_entry;
+- bool msix_in_use;
+ struct wx_ring_feature ring_feature[RING_F_ARRAY_SIZE];
+
+ /* misc interrupt status block */
+@@ -1072,6 +1076,8 @@ struct wx {
+ u64 hw_csum_rx_good;
+ u64 hw_csum_rx_error;
+ u64 alloc_rx_buff_failed;
++
++ void (*do_reset)(struct net_device *netdev);
+ };
+
+ #define WX_INTR_ALL (~0ULL)
+@@ -1132,4 +1138,19 @@ static inline struct wx *phylink_to_wx(struct phylink_config *config)
+ return container_of(config, struct wx, phylink_config);
+ }
+
++static inline int wx_set_state_reset(struct wx *wx)
++{
++ u8 timeout = 50;
++
++ while (test_and_set_bit(WX_STATE_RESETTING, wx->state)) {
++ timeout--;
++ if (!timeout)
++ return -EBUSY;
++
++ usleep_range(1000, 2000);
++ }
++
++ return 0;
++}
++
+ #endif /* _WX_TYPE_H_ */
+diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+index 786a652ae64f3..46a5a3e952021 100644
+--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
++++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+@@ -52,7 +52,7 @@ static int ngbe_set_ringparam(struct net_device *netdev,
+ struct wx *wx = netdev_priv(netdev);
+ u32 new_rx_count, new_tx_count;
+ struct wx_ring *temp_ring;
+- int i;
++ int i, err = 0;
+
+ new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
+ new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
+@@ -64,6 +64,10 @@ static int ngbe_set_ringparam(struct net_device *netdev,
+ new_rx_count == wx->rx_ring_count)
+ return 0;
+
++ err = wx_set_state_reset(wx);
++ if (err)
++ return err;
++
+ if (!netif_running(wx->netdev)) {
+ for (i = 0; i < wx->num_tx_queues; i++)
+ wx->tx_ring[i]->count = new_tx_count;
+@@ -72,14 +76,16 @@ static int ngbe_set_ringparam(struct net_device *netdev,
+ wx->tx_ring_count = new_tx_count;
+ wx->rx_ring_count = new_rx_count;
+
+- return 0;
++ goto clear_reset;
+ }
+
+ /* allocate temporary buffer to store rings in */
+ i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
+ temp_ring = kvmalloc_array(i, sizeof(struct wx_ring), GFP_KERNEL);
+- if (!temp_ring)
+- return -ENOMEM;
++ if (!temp_ring) {
++ err = -ENOMEM;
++ goto clear_reset;
++ }
+
+ ngbe_down(wx);
+
+@@ -89,7 +95,9 @@ static int ngbe_set_ringparam(struct net_device *netdev,
+ wx_configure(wx);
+ ngbe_up(wx);
+
+- return 0;
++clear_reset:
++ clear_bit(WX_STATE_RESETTING, wx->state);
++ return err;
+ }
+
+ static int ngbe_set_channels(struct net_device *dev,
+diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+index fdd6b4f70b7a5..e894e01d030d1 100644
+--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
++++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+@@ -499,6 +499,7 @@ static const struct net_device_ops ngbe_netdev_ops = {
+ .ndo_start_xmit = wx_xmit_frame,
+ .ndo_set_rx_mode = wx_set_rx_mode,
+ .ndo_set_features = wx_set_features,
++ .ndo_fix_features = wx_fix_features,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = wx_set_mac,
+ .ndo_get_stats64 = wx_get_stats64,
+diff --git a/drivers/net/ethernet/wangxun/txgbe/Makefile b/drivers/net/ethernet/wangxun/txgbe/Makefile
+index 7507f762edfe5..42718875277c8 100644
+--- a/drivers/net/ethernet/wangxun/txgbe/Makefile
++++ b/drivers/net/ethernet/wangxun/txgbe/Makefile
+@@ -9,4 +9,5 @@ obj-$(CONFIG_TXGBE) += txgbe.o
+ txgbe-objs := txgbe_main.o \
+ txgbe_hw.o \
+ txgbe_phy.o \
++ txgbe_irq.o \
+ txgbe_ethtool.o
+diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+index db675512ce4dc..31fde3fa7c6b5 100644
+--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
+@@ -19,7 +19,7 @@ static int txgbe_set_ringparam(struct net_device *netdev,
+ struct wx *wx = netdev_priv(netdev);
+ u32 new_rx_count, new_tx_count;
+ struct wx_ring *temp_ring;
+- int i;
++ int i, err = 0;
+
+ new_tx_count = clamp_t(u32, ring->tx_pending, WX_MIN_TXD, WX_MAX_TXD);
+ new_tx_count = ALIGN(new_tx_count, WX_REQ_TX_DESCRIPTOR_MULTIPLE);
+@@ -31,6 +31,10 @@ static int txgbe_set_ringparam(struct net_device *netdev,
+ new_rx_count == wx->rx_ring_count)
+ return 0;
+
++ err = wx_set_state_reset(wx);
++ if (err)
++ return err;
++
+ if (!netif_running(wx->netdev)) {
+ for (i = 0; i < wx->num_tx_queues; i++)
+ wx->tx_ring[i]->count = new_tx_count;
+@@ -39,14 +43,16 @@ static int txgbe_set_ringparam(struct net_device *netdev,
+ wx->tx_ring_count = new_tx_count;
+ wx->rx_ring_count = new_rx_count;
+
+- return 0;
++ goto clear_reset;
+ }
+
+ /* allocate temporary buffer to store rings in */
+ i = max_t(int, wx->num_tx_queues, wx->num_rx_queues);
+ temp_ring = kvmalloc_array(i, sizeof(struct wx_ring), GFP_KERNEL);
+- if (!temp_ring)
+- return -ENOMEM;
++ if (!temp_ring) {
++ err = -ENOMEM;
++ goto clear_reset;
++ }
+
+ txgbe_down(wx);
+
+@@ -55,7 +61,9 @@ static int txgbe_set_ringparam(struct net_device *netdev,
+
+ txgbe_up(wx);
+
+- return 0;
++clear_reset:
++ clear_bit(WX_STATE_RESETTING, wx->state);
++ return err;
+ }
+
+ static int txgbe_set_channels(struct net_device *dev,
+diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
+new file mode 100644
+index 0000000000000..b3e3605d1edb3
+--- /dev/null
++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
+@@ -0,0 +1,269 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */
++
++#include <linux/irqdomain.h>
++#include <linux/pci.h>
++
++#include "../libwx/wx_type.h"
++#include "../libwx/wx_lib.h"
++#include "../libwx/wx_hw.h"
++#include "txgbe_type.h"
++#include "txgbe_phy.h"
++#include "txgbe_irq.h"
++
++/**
++ * txgbe_irq_enable - Enable default interrupt generation settings
++ * @wx: pointer to private structure
++ * @queues: enable irqs for queues
++ **/
++void txgbe_irq_enable(struct wx *wx, bool queues)
++{
++ wr32(wx, WX_PX_MISC_IEN, TXGBE_PX_MISC_IEN_MASK);
++
++ /* unmask interrupt */
++ wx_intr_enable(wx, TXGBE_INTR_MISC);
++ if (queues)
++ wx_intr_enable(wx, TXGBE_INTR_QALL(wx));
++}
++
++/**
++ * txgbe_intr - msi/legacy mode Interrupt Handler
++ * @irq: interrupt number
++ * @data: pointer to a network interface device structure
++ **/
++static irqreturn_t txgbe_intr(int __always_unused irq, void *data)
++{
++ struct wx_q_vector *q_vector;
++ struct wx *wx = data;
++ struct pci_dev *pdev;
++ u32 eicr;
++
++ q_vector = wx->q_vector[0];
++ pdev = wx->pdev;
++
++ eicr = wx_misc_isb(wx, WX_ISB_VEC0);
++ if (!eicr) {
++ /* shared interrupt alert!
++ * the interrupt that we masked before the ICR read.
++ */
++ if (netif_running(wx->netdev))
++ txgbe_irq_enable(wx, true);
++ return IRQ_NONE; /* Not our interrupt */
++ }
++ wx->isb_mem[WX_ISB_VEC0] = 0;
++ if (!(pdev->msi_enabled))
++ wr32(wx, WX_PX_INTA, 1);
++
++ wx->isb_mem[WX_ISB_MISC] = 0;
++ /* would disable interrupts here but it is auto disabled */
++ napi_schedule_irqoff(&q_vector->napi);
++
++ /* re-enable link(maybe) and non-queue interrupts, no flush.
++ * txgbe_poll will re-enable the queue interrupts
++ */
++ if (netif_running(wx->netdev))
++ txgbe_irq_enable(wx, false);
++
++ return IRQ_HANDLED;
++}
++
++/**
++ * txgbe_request_msix_irqs - Initialize MSI-X interrupts
++ * @wx: board private structure
++ *
++ * Allocate MSI-X vectors and request interrupts from the kernel.
++ **/
++static int txgbe_request_msix_irqs(struct wx *wx)
++{
++ struct net_device *netdev = wx->netdev;
++ int vector, err;
++
++ for (vector = 0; vector < wx->num_q_vectors; vector++) {
++ struct wx_q_vector *q_vector = wx->q_vector[vector];
++ struct msix_entry *entry = &wx->msix_q_entries[vector];
++
++ if (q_vector->tx.ring && q_vector->rx.ring)
++ snprintf(q_vector->name, sizeof(q_vector->name) - 1,
++ "%s-TxRx-%d", netdev->name, entry->entry);
++ else
++ /* skip this unused q_vector */
++ continue;
++
++ err = request_irq(entry->vector, wx_msix_clean_rings, 0,
++ q_vector->name, q_vector);
++ if (err) {
++ wx_err(wx, "request_irq failed for MSIX interrupt %s Error: %d\n",
++ q_vector->name, err);
++ goto free_queue_irqs;
++ }
++ }
++
++ return 0;
++
++free_queue_irqs:
++ while (vector) {
++ vector--;
++ free_irq(wx->msix_q_entries[vector].vector,
++ wx->q_vector[vector]);
++ }
++ wx_reset_interrupt_capability(wx);
++ return err;
++}
++
++/**
++ * txgbe_request_irq - initialize interrupts
++ * @wx: board private structure
++ *
++ * Attempt to configure interrupts using the best available
++ * capabilities of the hardware and kernel.
++ **/
++int txgbe_request_irq(struct wx *wx)
++{
++ struct net_device *netdev = wx->netdev;
++ struct pci_dev *pdev = wx->pdev;
++ int err;
++
++ if (pdev->msix_enabled)
++ err = txgbe_request_msix_irqs(wx);
++ else if (pdev->msi_enabled)
++ err = request_irq(wx->pdev->irq, &txgbe_intr, 0,
++ netdev->name, wx);
++ else
++ err = request_irq(wx->pdev->irq, &txgbe_intr, IRQF_SHARED,
++ netdev->name, wx);
++
++ if (err)
++ wx_err(wx, "request_irq failed, Error %d\n", err);
++
++ return err;
++}
++
++static int txgbe_request_gpio_irq(struct txgbe *txgbe)
++{
++ txgbe->gpio_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_GPIO);
++ return request_threaded_irq(txgbe->gpio_irq, NULL,
++ txgbe_gpio_irq_handler,
++ IRQF_ONESHOT, "txgbe-gpio-irq", txgbe);
++}
++
++static int txgbe_request_link_irq(struct txgbe *txgbe)
++{
++ txgbe->link_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_LINK);
++ return request_threaded_irq(txgbe->link_irq, NULL,
++ txgbe_link_irq_handler,
++ IRQF_ONESHOT, "txgbe-link-irq", txgbe);
++}
++
++static const struct irq_chip txgbe_irq_chip = {
++ .name = "txgbe-misc-irq",
++};
++
++static int txgbe_misc_irq_domain_map(struct irq_domain *d,
++ unsigned int irq,
++ irq_hw_number_t hwirq)
++{
++ struct txgbe *txgbe = d->host_data;
++
++ irq_set_chip_data(irq, txgbe);
++ irq_set_chip(irq, &txgbe->misc.chip);
++ irq_set_nested_thread(irq, true);
++ irq_set_noprobe(irq);
++
++ return 0;
++}
++
++static const struct irq_domain_ops txgbe_misc_irq_domain_ops = {
++ .map = txgbe_misc_irq_domain_map,
++};
++
++static irqreturn_t txgbe_misc_irq_handle(int irq, void *data)
++{
++ struct txgbe *txgbe = data;
++ struct wx *wx = txgbe->wx;
++ unsigned int nhandled = 0;
++ unsigned int sub_irq;
++ u32 eicr;
++
++ eicr = wx_misc_isb(wx, WX_ISB_MISC);
++ if (eicr & TXGBE_PX_MISC_GPIO) {
++ sub_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_GPIO);
++ handle_nested_irq(sub_irq);
++ nhandled++;
++ }
++ if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN |
++ TXGBE_PX_MISC_ETH_AN)) {
++ sub_irq = irq_find_mapping(txgbe->misc.domain, TXGBE_IRQ_LINK);
++ handle_nested_irq(sub_irq);
++ nhandled++;
++ }
++
++ wx_intr_enable(wx, TXGBE_INTR_MISC);
++ return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
++}
++
++static void txgbe_del_irq_domain(struct txgbe *txgbe)
++{
++ int hwirq, virq;
++
++ for (hwirq = 0; hwirq < txgbe->misc.nirqs; hwirq++) {
++ virq = irq_find_mapping(txgbe->misc.domain, hwirq);
++ irq_dispose_mapping(virq);
++ }
++
++ irq_domain_remove(txgbe->misc.domain);
++}
++
++void txgbe_free_misc_irq(struct txgbe *txgbe)
++{
++ free_irq(txgbe->gpio_irq, txgbe);
++ free_irq(txgbe->link_irq, txgbe);
++ free_irq(txgbe->misc.irq, txgbe);
++ txgbe_del_irq_domain(txgbe);
++}
++
++int txgbe_setup_misc_irq(struct txgbe *txgbe)
++{
++ struct wx *wx = txgbe->wx;
++ int hwirq, err;
++
++ txgbe->misc.nirqs = 2;
++ txgbe->misc.domain = irq_domain_add_simple(NULL, txgbe->misc.nirqs, 0,
++ &txgbe_misc_irq_domain_ops, txgbe);
++ if (!txgbe->misc.domain)
++ return -ENOMEM;
++
++ for (hwirq = 0; hwirq < txgbe->misc.nirqs; hwirq++)
++ irq_create_mapping(txgbe->misc.domain, hwirq);
++
++ txgbe->misc.chip = txgbe_irq_chip;
++ if (wx->pdev->msix_enabled)
++ txgbe->misc.irq = wx->msix_entry->vector;
++ else
++ txgbe->misc.irq = wx->pdev->irq;
++
++ err = request_threaded_irq(txgbe->misc.irq, NULL,
++ txgbe_misc_irq_handle,
++ IRQF_ONESHOT,
++ wx->netdev->name, txgbe);
++ if (err)
++ goto del_misc_irq;
++
++ err = txgbe_request_gpio_irq(txgbe);
++ if (err)
++ goto free_msic_irq;
++
++ err = txgbe_request_link_irq(txgbe);
++ if (err)
++ goto free_gpio_irq;
++
++ return 0;
++
++free_gpio_irq:
++ free_irq(txgbe->gpio_irq, txgbe);
++free_msic_irq:
++ free_irq(txgbe->misc.irq, txgbe);
++del_misc_irq:
++ txgbe_del_irq_domain(txgbe);
++
++ return err;
++}
+diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.h
+new file mode 100644
+index 0000000000000..b77945e7a0f26
+--- /dev/null
++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.h
+@@ -0,0 +1,7 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */
++
++void txgbe_irq_enable(struct wx *wx, bool queues);
++int txgbe_request_irq(struct wx *wx);
++void txgbe_free_misc_irq(struct txgbe *txgbe);
++int txgbe_setup_misc_irq(struct txgbe *txgbe);
+diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+index 3b151c410a5c2..8c7a74981b907 100644
+--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+@@ -17,6 +17,7 @@
+ #include "txgbe_type.h"
+ #include "txgbe_hw.h"
+ #include "txgbe_phy.h"
++#include "txgbe_irq.h"
+ #include "txgbe_ethtool.h"
+
+ char txgbe_driver_name[] = "txgbe";
+@@ -76,137 +77,11 @@ static int txgbe_enumerate_functions(struct wx *wx)
+ return physfns;
+ }
+
+-/**
+- * txgbe_irq_enable - Enable default interrupt generation settings
+- * @wx: pointer to private structure
+- * @queues: enable irqs for queues
+- **/
+-static void txgbe_irq_enable(struct wx *wx, bool queues)
+-{
+- wr32(wx, WX_PX_MISC_IEN, TXGBE_PX_MISC_IEN_MASK);
+-
+- /* unmask interrupt */
+- wx_intr_enable(wx, TXGBE_INTR_MISC);
+- if (queues)
+- wx_intr_enable(wx, TXGBE_INTR_QALL(wx));
+-}
+-
+-/**
+- * txgbe_intr - msi/legacy mode Interrupt Handler
+- * @irq: interrupt number
+- * @data: pointer to a network interface device structure
+- **/
+-static irqreturn_t txgbe_intr(int __always_unused irq, void *data)
+-{
+- struct wx_q_vector *q_vector;
+- struct wx *wx = data;
+- struct pci_dev *pdev;
+- u32 eicr;
+-
+- q_vector = wx->q_vector[0];
+- pdev = wx->pdev;
+-
+- eicr = wx_misc_isb(wx, WX_ISB_VEC0);
+- if (!eicr) {
+- /* shared interrupt alert!
+- * the interrupt that we masked before the ICR read.
+- */
+- if (netif_running(wx->netdev))
+- txgbe_irq_enable(wx, true);
+- return IRQ_NONE; /* Not our interrupt */
+- }
+- wx->isb_mem[WX_ISB_VEC0] = 0;
+- if (!(pdev->msi_enabled))
+- wr32(wx, WX_PX_INTA, 1);
+-
+- wx->isb_mem[WX_ISB_MISC] = 0;
+- /* would disable interrupts here but it is auto disabled */
+- napi_schedule_irqoff(&q_vector->napi);
+-
+- /* re-enable link(maybe) and non-queue interrupts, no flush.
+- * txgbe_poll will re-enable the queue interrupts
+- */
+- if (netif_running(wx->netdev))
+- txgbe_irq_enable(wx, false);
+-
+- return IRQ_HANDLED;
+-}
+-
+-/**
+- * txgbe_request_msix_irqs - Initialize MSI-X interrupts
+- * @wx: board private structure
+- *
+- * Allocate MSI-X vectors and request interrupts from the kernel.
+- **/
+-static int txgbe_request_msix_irqs(struct wx *wx)
+-{
+- struct net_device *netdev = wx->netdev;
+- int vector, err;
+-
+- for (vector = 0; vector < wx->num_q_vectors; vector++) {
+- struct wx_q_vector *q_vector = wx->q_vector[vector];
+- struct msix_entry *entry = &wx->msix_q_entries[vector];
+-
+- if (q_vector->tx.ring && q_vector->rx.ring)
+- snprintf(q_vector->name, sizeof(q_vector->name) - 1,
+- "%s-TxRx-%d", netdev->name, entry->entry);
+- else
+- /* skip this unused q_vector */
+- continue;
+-
+- err = request_irq(entry->vector, wx_msix_clean_rings, 0,
+- q_vector->name, q_vector);
+- if (err) {
+- wx_err(wx, "request_irq failed for MSIX interrupt %s Error: %d\n",
+- q_vector->name, err);
+- goto free_queue_irqs;
+- }
+- }
+-
+- return 0;
+-
+-free_queue_irqs:
+- while (vector) {
+- vector--;
+- free_irq(wx->msix_q_entries[vector].vector,
+- wx->q_vector[vector]);
+- }
+- wx_reset_interrupt_capability(wx);
+- return err;
+-}
+-
+-/**
+- * txgbe_request_irq - initialize interrupts
+- * @wx: board private structure
+- *
+- * Attempt to configure interrupts using the best available
+- * capabilities of the hardware and kernel.
+- **/
+-static int txgbe_request_irq(struct wx *wx)
+-{
+- struct net_device *netdev = wx->netdev;
+- struct pci_dev *pdev = wx->pdev;
+- int err;
+-
+- if (pdev->msix_enabled)
+- err = txgbe_request_msix_irqs(wx);
+- else if (pdev->msi_enabled)
+- err = request_irq(wx->pdev->irq, &txgbe_intr, 0,
+- netdev->name, wx);
+- else
+- err = request_irq(wx->pdev->irq, &txgbe_intr, IRQF_SHARED,
+- netdev->name, wx);
+-
+- if (err)
+- wx_err(wx, "request_irq failed, Error %d\n", err);
+-
+- return err;
+-}
+-
+ static void txgbe_up_complete(struct wx *wx)
+ {
+ struct net_device *netdev = wx->netdev;
+
++ txgbe_reinit_gpio_intr(wx);
+ wx_control_hw(wx, true);
+ wx_configure_vectors(wx);
+
+@@ -394,6 +269,8 @@ static int txgbe_sw_init(struct wx *wx)
+ wx->tx_work_limit = TXGBE_DEFAULT_TX_WORK;
+ wx->rx_work_limit = TXGBE_DEFAULT_RX_WORK;
+
++ wx->do_reset = txgbe_do_reset;
++
+ return 0;
+ }
+
+@@ -518,6 +395,7 @@ static void txgbe_shutdown(struct pci_dev *pdev)
+ int txgbe_setup_tc(struct net_device *dev, u8 tc)
+ {
+ struct wx *wx = netdev_priv(dev);
++ struct txgbe *txgbe = wx->priv;
+
+ /* Hardware has to reinitialize queues and interrupts to
+ * match packet buffer alignment. Unfortunately, the
+@@ -528,6 +406,7 @@ int txgbe_setup_tc(struct net_device *dev, u8 tc)
+ else
+ txgbe_reset(wx);
+
++ txgbe_free_misc_irq(txgbe);
+ wx_clear_interrupt_scheme(wx);
+
+ if (tc)
+@@ -536,6 +415,7 @@ int txgbe_setup_tc(struct net_device *dev, u8 tc)
+ netdev_reset_tc(dev);
+
+ wx_init_interrupt_scheme(wx);
++ txgbe_setup_misc_irq(txgbe);
+
+ if (netif_running(dev))
+ txgbe_open(dev);
+@@ -543,6 +423,34 @@ int txgbe_setup_tc(struct net_device *dev, u8 tc)
+ return 0;
+ }
+
++static void txgbe_reinit_locked(struct wx *wx)
++{
++ int err = 0;
++
++ netif_trans_update(wx->netdev);
++
++ err = wx_set_state_reset(wx);
++ if (err) {
++ wx_err(wx, "wait device reset timeout\n");
++ return;
++ }
++
++ txgbe_down(wx);
++ txgbe_up(wx);
++
++ clear_bit(WX_STATE_RESETTING, wx->state);
++}
++
++void txgbe_do_reset(struct net_device *netdev)
++{
++ struct wx *wx = netdev_priv(netdev);
++
++ if (netif_running(netdev))
++ txgbe_reinit_locked(wx);
++ else
++ txgbe_reset(wx);
++}
++
+ static const struct net_device_ops txgbe_netdev_ops = {
+ .ndo_open = txgbe_open,
+ .ndo_stop = txgbe_close,
+@@ -550,6 +458,7 @@ static const struct net_device_ops txgbe_netdev_ops = {
+ .ndo_start_xmit = wx_xmit_frame,
+ .ndo_set_rx_mode = wx_set_rx_mode,
+ .ndo_set_features = wx_set_features,
++ .ndo_fix_features = wx_fix_features,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = wx_set_mac,
+ .ndo_get_stats64 = wx_get_stats64,
+@@ -751,10 +660,14 @@ static int txgbe_probe(struct pci_dev *pdev,
+ txgbe->wx = wx;
+ wx->priv = txgbe;
+
+- err = txgbe_init_phy(txgbe);
++ err = txgbe_setup_misc_irq(txgbe);
+ if (err)
+ goto err_release_hw;
+
++ err = txgbe_init_phy(txgbe);
++ if (err)
++ goto err_free_misc_irq;
++
+ err = register_netdev(netdev);
+ if (err)
+ goto err_remove_phy;
+@@ -781,6 +694,8 @@ static int txgbe_probe(struct pci_dev *pdev,
+
+ err_remove_phy:
+ txgbe_remove_phy(txgbe);
++err_free_misc_irq:
++ txgbe_free_misc_irq(txgbe);
+ err_release_hw:
+ wx_clear_interrupt_scheme(wx);
+ wx_control_hw(wx, false);
+@@ -813,6 +728,7 @@ static void txgbe_remove(struct pci_dev *pdev)
+ unregister_netdev(netdev);
+
+ txgbe_remove_phy(txgbe);
++ txgbe_free_misc_irq(txgbe);
+
+ pci_release_selected_regions(pdev,
+ pci_select_bars(pdev, IORESOURCE_MEM));
+diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
+index 8cddc9ddb3392..93295916b1d2b 100644
+--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
+@@ -20,8 +20,6 @@
+ #include "txgbe_phy.h"
+ #include "txgbe_hw.h"
+
+-#define TXGBE_I2C_CLK_DEV_NAME "i2c_dw"
+-
+ static int txgbe_swnodes_register(struct txgbe *txgbe)
+ {
+ struct txgbe_nodes *nodes = &txgbe->nodes;
+@@ -294,6 +292,21 @@ static int txgbe_phylink_init(struct txgbe *txgbe)
+ return 0;
+ }
+
++irqreturn_t txgbe_link_irq_handler(int irq, void *data)
++{
++ struct txgbe *txgbe = data;
++ struct wx *wx = txgbe->wx;
++ u32 status;
++ bool up;
++
++ status = rd32(wx, TXGBE_CFG_PORT_ST);
++ up = !!(status & TXGBE_CFG_PORT_ST_LINK_UP);
++
++ phylink_mac_change(wx->phylink, up);
++
++ return IRQ_HANDLED;
++}
++
+ static int txgbe_gpio_get(struct gpio_chip *chip, unsigned int offset)
+ {
+ struct wx *wx = gpiochip_get_data(chip);
+@@ -439,7 +452,7 @@ static int txgbe_gpio_set_type(struct irq_data *d, unsigned int type)
+ }
+
+ static const struct irq_chip txgbe_gpio_irq_chip = {
+- .name = "txgbe_gpio_irq",
++ .name = "txgbe-gpio-irq",
+ .irq_ack = txgbe_gpio_irq_ack,
+ .irq_mask = txgbe_gpio_irq_mask,
+ .irq_unmask = txgbe_gpio_irq_unmask,
+@@ -448,29 +461,25 @@ static const struct irq_chip txgbe_gpio_irq_chip = {
+ GPIOCHIP_IRQ_RESOURCE_HELPERS,
+ };
+
+-static void txgbe_irq_handler(struct irq_desc *desc)
++irqreturn_t txgbe_gpio_irq_handler(int irq, void *data)
+ {
+- struct irq_chip *chip = irq_desc_get_chip(desc);
+- struct wx *wx = irq_desc_get_handler_data(desc);
+- struct txgbe *txgbe = wx->priv;
++ struct txgbe *txgbe = data;
++ struct wx *wx = txgbe->wx;
+ irq_hw_number_t hwirq;
+ unsigned long gpioirq;
+ struct gpio_chip *gc;
+ unsigned long flags;
+- u32 eicr;
+-
+- eicr = wx_misc_isb(wx, WX_ISB_MISC);
+-
+- chained_irq_enter(chip, desc);
+
+ gpioirq = rd32(wx, WX_GPIO_INTSTATUS);
+
+ gc = txgbe->gpio;
+ for_each_set_bit(hwirq, &gpioirq, gc->ngpio) {
+ int gpio = irq_find_mapping(gc->irq.domain, hwirq);
++ struct irq_data *d = irq_get_irq_data(gpio);
+ u32 irq_type = irq_get_trigger_type(gpio);
+
+- generic_handle_domain_irq(gc->irq.domain, hwirq);
++ txgbe_gpio_irq_ack(d);
++ handle_nested_irq(gpio);
+
+ if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
+@@ -479,17 +488,34 @@ static void txgbe_irq_handler(struct irq_desc *desc)
+ }
+ }
+
+- chained_irq_exit(chip, desc);
++ return IRQ_HANDLED;
++}
++
++void txgbe_reinit_gpio_intr(struct wx *wx)
++{
++ struct txgbe *txgbe = wx->priv;
++ irq_hw_number_t hwirq;
++ unsigned long gpioirq;
++ struct gpio_chip *gc;
++ unsigned long flags;
++
++ /* for gpio interrupt pending before irq enable */
++ gpioirq = rd32(wx, WX_GPIO_INTSTATUS);
+
+- if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN |
+- TXGBE_PX_MISC_ETH_AN)) {
+- u32 reg = rd32(wx, TXGBE_CFG_PORT_ST);
++ gc = txgbe->gpio;
++ for_each_set_bit(hwirq, &gpioirq, gc->ngpio) {
++ int gpio = irq_find_mapping(gc->irq.domain, hwirq);
++ struct irq_data *d = irq_get_irq_data(gpio);
++ u32 irq_type = irq_get_trigger_type(gpio);
+
+- phylink_mac_change(wx->phylink, !!(reg & TXGBE_CFG_PORT_ST_LINK_UP));
+- }
++ txgbe_gpio_irq_ack(d);
+
+- /* unmask interrupt */
+- wx_intr_enable(wx, TXGBE_INTR_MISC);
++ if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
++ raw_spin_lock_irqsave(&wx->gpio_lock, flags);
++ txgbe_toggle_trigger(gc, hwirq);
++ raw_spin_unlock_irqrestore(&wx->gpio_lock, flags);
++ }
++ }
+ }
+
+ static int txgbe_gpio_init(struct txgbe *txgbe)
+@@ -526,19 +552,6 @@ static int txgbe_gpio_init(struct txgbe *txgbe)
+
+ girq = &gc->irq;
+ gpio_irq_chip_set_chip(girq, &txgbe_gpio_irq_chip);
+- girq->parent_handler = txgbe_irq_handler;
+- girq->parent_handler_data = wx;
+- girq->num_parents = 1;
+- girq->parents = devm_kcalloc(dev, girq->num_parents,
+- sizeof(*girq->parents), GFP_KERNEL);
+- if (!girq->parents)
+- return -ENOMEM;
+-
+- /* now only suuported on MSI-X interrupt */
+- if (!wx->msix_entry)
+- return -EPERM;
+-
+- girq->parents[0] = wx->msix_entry->vector;
+ girq->default_type = IRQ_TYPE_NONE;
+ girq->handler = handle_bad_irq;
+
+@@ -558,8 +571,8 @@ static int txgbe_clock_register(struct txgbe *txgbe)
+ char clk_name[32];
+ struct clk *clk;
+
+- snprintf(clk_name, sizeof(clk_name), "%s.%d",
+- TXGBE_I2C_CLK_DEV_NAME, pci_dev_id(pdev));
++ snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d",
++ pci_dev_id(pdev));
+
+ clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000);
+ if (IS_ERR(clk))
+@@ -621,7 +634,7 @@ static int txgbe_i2c_register(struct txgbe *txgbe)
+
+ info.parent = &pdev->dev;
+ info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]);
+- info.name = TXGBE_I2C_CLK_DEV_NAME;
++ info.name = "i2c_designware";
+ info.id = pci_dev_id(pdev);
+
+ info.res = &DEFINE_RES_IRQ(pdev->irq);
+@@ -756,8 +769,6 @@ int txgbe_init_phy(struct txgbe *txgbe)
+ goto err_unregister_i2c;
+ }
+
+- wx->msix_in_use = true;
+-
+ return 0;
+
+ err_unregister_i2c:
+@@ -790,5 +801,4 @@ void txgbe_remove_phy(struct txgbe *txgbe)
+ phylink_destroy(txgbe->wx->phylink);
+ xpcs_destroy(txgbe->xpcs);
+ software_node_unregister_node_group(txgbe->nodes.group);
+- txgbe->wx->msix_in_use = false;
+ }
+diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h
+index 1ab592124986a..8a026d804fe24 100644
+--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h
++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h
+@@ -4,6 +4,9 @@
+ #ifndef _TXGBE_PHY_H_
+ #define _TXGBE_PHY_H_
+
++irqreturn_t txgbe_gpio_irq_handler(int irq, void *data);
++void txgbe_reinit_gpio_intr(struct wx *wx);
++irqreturn_t txgbe_link_irq_handler(int irq, void *data);
+ int txgbe_init_phy(struct txgbe *txgbe);
+ void txgbe_remove_phy(struct txgbe *txgbe);
+
+diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
+index 270a6fd9ad0b0..f434a7865cb7b 100644
+--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
+@@ -5,6 +5,7 @@
+ #define _TXGBE_TYPE_H_
+
+ #include <linux/property.h>
++#include <linux/irq.h>
+
+ /* Device IDs */
+ #define TXGBE_DEV_ID_SP1000 0x1001
+@@ -133,6 +134,7 @@ extern char txgbe_driver_name[];
+ void txgbe_down(struct wx *wx);
+ void txgbe_up(struct wx *wx);
+ int txgbe_setup_tc(struct net_device *dev, u8 tc);
++void txgbe_do_reset(struct net_device *netdev);
+
+ #define NODE_PROP(_NAME, _PROP) \
+ (const struct software_node) { \
+@@ -169,15 +171,31 @@ struct txgbe_nodes {
+ const struct software_node *group[SWNODE_MAX + 1];
+ };
+
++enum txgbe_misc_irqs {
++ TXGBE_IRQ_GPIO = 0,
++ TXGBE_IRQ_LINK,
++ TXGBE_IRQ_MAX
++};
++
++struct txgbe_irq {
++ struct irq_chip chip;
++ struct irq_domain *domain;
++ int nirqs;
++ int irq;
++};
++
+ struct txgbe {
+ struct wx *wx;
+ struct txgbe_nodes nodes;
++ struct txgbe_irq misc;
+ struct dw_xpcs *xpcs;
+ struct platform_device *sfp_dev;
+ struct platform_device *i2c_dev;
+ struct clk_lookup *clock;
+ struct clk *clk;
+ struct gpio_chip *gpio;
++ unsigned int gpio_irq;
++ unsigned int link_irq;
+ };
+
+ #endif /* _TXGBE_TYPE_H_ */
+diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
+index 1f950c824418f..827db6a6ff397 100644
+--- a/drivers/net/phy/micrel.c
++++ b/drivers/net/phy/micrel.c
+@@ -4635,7 +4635,8 @@ static int lan8841_suspend(struct phy_device *phydev)
+ struct kszphy_priv *priv = phydev->priv;
+ struct kszphy_ptp_priv *ptp_priv = &priv->ptp_priv;
+
+- ptp_cancel_worker_sync(ptp_priv->ptp_clock);
++ if (ptp_priv->ptp_clock)
++ ptp_cancel_worker_sync(ptp_priv->ptp_clock);
+
+ return genphy_suspend(phydev);
+ }
+diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c
+index 7b8afa589a53c..284375f662f1e 100644
+--- a/drivers/net/usb/aqc111.c
++++ b/drivers/net/usb/aqc111.c
+@@ -1141,17 +1141,15 @@ static int aqc111_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+ continue;
+ }
+
+- /* Clone SKB */
+- new_skb = skb_clone(skb, GFP_ATOMIC);
++ new_skb = netdev_alloc_skb_ip_align(dev->net, pkt_len);
+
+ if (!new_skb)
+ goto err;
+
+- new_skb->len = pkt_len;
++ skb_put(new_skb, pkt_len);
++ memcpy(new_skb->data, skb->data, pkt_len);
+ skb_pull(new_skb, AQ_RX_HW_PAD);
+- skb_set_tail_pointer(new_skb, new_skb->len);
+
+- new_skb->truesize = SKB_TRUESIZE(new_skb->len);
+ if (aqc111_data->rx_checksum)
+ aqc111_rx_checksum(new_skb, pkt_desc);
+
+diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
+index edc34402e787f..a5469cf5cf670 100644
+--- a/drivers/net/usb/qmi_wwan.c
++++ b/drivers/net/usb/qmi_wwan.c
+@@ -1368,6 +1368,9 @@ static const struct usb_device_id products[] = {
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1060, 2)}, /* Telit LN920 */
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1070, 2)}, /* Telit FN990 */
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1080, 2)}, /* Telit FE990 */
++ {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a0, 0)}, /* Telit FN920C04 */
++ {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a4, 0)}, /* Telit FN920C04 */
++ {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a9, 0)}, /* Telit FN920C04 */
+ {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */
+ {QMI_FIXED_INTF(0x1bc7, 0x1101, 3)}, /* Telit ME910 dual modem */
+ {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */
+diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
+index 2fa46baa589e5..cbea246664795 100644
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -1810,9 +1810,11 @@ static int smsc95xx_reset_resume(struct usb_interface *intf)
+
+ static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
+ {
+- skb->csum = *(u16 *)(skb_tail_pointer(skb) - 2);
++ u16 *csum_ptr = (u16 *)(skb_tail_pointer(skb) - 2);
++
++ skb->csum = (__force __wsum)get_unaligned(csum_ptr);
+ skb->ip_summed = CHECKSUM_COMPLETE;
+- skb_trim(skb, skb->len - 2);
++ skb_trim(skb, skb->len - 2); /* remove csum */
+ }
+
+ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+@@ -1870,25 +1872,22 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+ if (dev->net->features & NETIF_F_RXCSUM)
+ smsc95xx_rx_csum_offload(skb);
+ skb_trim(skb, skb->len - 4); /* remove fcs */
+- skb->truesize = size + sizeof(struct sk_buff);
+
+ return 1;
+ }
+
+- ax_skb = skb_clone(skb, GFP_ATOMIC);
++ ax_skb = netdev_alloc_skb_ip_align(dev->net, size);
+ if (unlikely(!ax_skb)) {
+ netdev_warn(dev->net, "Error allocating skb\n");
+ return 0;
+ }
+
+- ax_skb->len = size;
+- ax_skb->data = packet;
+- skb_set_tail_pointer(ax_skb, size);
++ skb_put(ax_skb, size);
++ memcpy(ax_skb->data, packet, size);
+
+ if (dev->net->features & NETIF_F_RXCSUM)
+ smsc95xx_rx_csum_offload(ax_skb);
+ skb_trim(ax_skb, ax_skb->len - 4); /* remove fcs */
+- ax_skb->truesize = size + sizeof(struct sk_buff);
+
+ usbnet_skb_return(dev, ax_skb);
+ }
+diff --git a/drivers/net/usb/sr9700.c b/drivers/net/usb/sr9700.c
+index 3164451e1010c..0a662e42ed965 100644
+--- a/drivers/net/usb/sr9700.c
++++ b/drivers/net/usb/sr9700.c
+@@ -421,19 +421,15 @@ static int sr9700_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+ skb_pull(skb, 3);
+ skb->len = len;
+ skb_set_tail_pointer(skb, len);
+- skb->truesize = len + sizeof(struct sk_buff);
+ return 2;
+ }
+
+- /* skb_clone is used for address align */
+- sr_skb = skb_clone(skb, GFP_ATOMIC);
++ sr_skb = netdev_alloc_skb_ip_align(dev->net, len);
+ if (!sr_skb)
+ return 0;
+
+- sr_skb->len = len;
+- sr_skb->data = skb->data + 3;
+- skb_set_tail_pointer(sr_skb, len);
+- sr_skb->truesize = len + sizeof(struct sk_buff);
++ skb_put(sr_skb, len);
++ memcpy(sr_skb->data, skb->data + 3, len);
+ usbnet_skb_return(dev, sr_skb);
+
+ skb_pull(skb, len + SR_RX_OVERHEAD);
+diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c
+index a742cec44e3db..91ddbe6136e00 100644
+--- a/drivers/net/wireless/ath/ar5523/ar5523.c
++++ b/drivers/net/wireless/ath/ar5523/ar5523.c
+@@ -1590,6 +1590,20 @@ static int ar5523_probe(struct usb_interface *intf,
+ struct ar5523 *ar;
+ int error = -ENOMEM;
+
++ static const u8 bulk_ep_addr[] = {
++ AR5523_CMD_TX_PIPE | USB_DIR_OUT,
++ AR5523_DATA_TX_PIPE | USB_DIR_OUT,
++ AR5523_CMD_RX_PIPE | USB_DIR_IN,
++ AR5523_DATA_RX_PIPE | USB_DIR_IN,
++ 0};
++
++ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr)) {
++ dev_err(&dev->dev,
++ "Could not find all expected endpoints\n");
++ error = -ENODEV;
++ goto out;
++ }
++
+ /*
+ * Load firmware if the device requires it. This will return
+ * -ENXIO on success and we'll get called back afer the usb
+diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
+index 0032f8aa892ff..4e3736d7aff77 100644
+--- a/drivers/net/wireless/ath/ath10k/core.c
++++ b/drivers/net/wireless/ath/ath10k/core.c
+@@ -720,6 +720,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
+ .max_spatial_stream = 4,
+ .fw = {
+ .dir = WCN3990_HW_1_0_FW_DIR,
++ .board = WCN3990_HW_1_0_BOARD_DATA_FILE,
++ .board_size = WCN3990_BOARD_DATA_SZ,
++ .board_ext_size = WCN3990_BOARD_EXT_DATA_SZ,
+ },
+ .sw_decrypt_mcast_mgmt = true,
+ .rx_desc_ops = &wcn3990_rx_desc_ops,
+diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
+index 394bf3c32abff..0f6de862c3a9b 100644
+--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c
++++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
+@@ -439,7 +439,7 @@ ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
+ }
+ out:
+ mutex_unlock(&ar->conf_mutex);
+- return count;
++ return ret ?: count;
+ }
+
+ static const struct file_operations fops_peer_debug_trigger = {
+diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
+index 93c0730919966..9aa2d821b5078 100644
+--- a/drivers/net/wireless/ath/ath10k/hw.h
++++ b/drivers/net/wireless/ath/ath10k/hw.h
+@@ -133,6 +133,7 @@ enum qca9377_chip_id_rev {
+ /* WCN3990 1.0 definitions */
+ #define WCN3990_HW_1_0_DEV_VERSION ATH10K_HW_WCN3990
+ #define WCN3990_HW_1_0_FW_DIR ATH10K_FW_DIR "/WCN3990/hw1.0"
++#define WCN3990_HW_1_0_BOARD_DATA_FILE "board.bin"
+
+ #define ATH10K_FW_FILE_BASE "firmware"
+ #define ATH10K_FW_API_MAX 6
+diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h
+index ec556bb88d658..ba37e6c7ced08 100644
+--- a/drivers/net/wireless/ath/ath10k/targaddrs.h
++++ b/drivers/net/wireless/ath/ath10k/targaddrs.h
+@@ -491,4 +491,7 @@ struct host_interest {
+ #define QCA4019_BOARD_DATA_SZ 12064
+ #define QCA4019_BOARD_EXT_DATA_SZ 0
+
++#define WCN3990_BOARD_DATA_SZ 26328
++#define WCN3990_BOARD_EXT_DATA_SZ 0
++
+ #endif /* __TARGADDRS_H__ */
+diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
+index 88befe92f95dc..24f1ab2785214 100644
+--- a/drivers/net/wireless/ath/ath10k/wmi.c
++++ b/drivers/net/wireless/ath/ath10k/wmi.c
+@@ -1763,12 +1763,32 @@ void ath10k_wmi_put_wmi_channel(struct ath10k *ar, struct wmi_channel *ch,
+
+ int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
+ {
+- unsigned long time_left;
++ unsigned long time_left, i;
+
+ time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
+ WMI_SERVICE_READY_TIMEOUT_HZ);
+- if (!time_left)
+- return -ETIMEDOUT;
++ if (!time_left) {
++ /* Sometimes the PCI HIF doesn't receive interrupt
++ * for the service ready message even if the buffer
++ * was completed. PCIe sniffer shows that it's
++ * because the corresponding CE ring doesn't fires
++ * it. Workaround here by polling CE rings once.
++ */
++ ath10k_warn(ar, "failed to receive service ready completion, polling..\n");
++
++ for (i = 0; i < CE_COUNT; i++)
++ ath10k_hif_send_complete_check(ar, i, 1);
++
++ time_left = wait_for_completion_timeout(&ar->wmi.service_ready,
++ WMI_SERVICE_READY_TIMEOUT_HZ);
++ if (!time_left) {
++ ath10k_warn(ar, "polling timed out\n");
++ return -ETIMEDOUT;
++ }
++
++ ath10k_warn(ar, "service ready completion received, continuing normally\n");
++ }
++
+ return 0;
+ }
+
+diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
+index cc80310088ce1..a46b8e677cd1f 100644
+--- a/drivers/net/wireless/ath/ath11k/mac.c
++++ b/drivers/net/wireless/ath/ath11k/mac.c
+@@ -1234,14 +1234,7 @@ static int ath11k_mac_vif_setup_ps(struct ath11k_vif *arvif)
+
+ enable_ps = arvif->ps;
+
+- if (!arvif->is_started) {
+- /* mac80211 can update vif powersave state while disconnected.
+- * Firmware doesn't behave nicely and consumes more power than
+- * necessary if PS is disabled on a non-started vdev. Hence
+- * force-enable PS for non-running vdevs.
+- */
+- psmode = WMI_STA_PS_MODE_ENABLED;
+- } else if (enable_ps) {
++ if (enable_ps) {
+ psmode = WMI_STA_PS_MODE_ENABLED;
+ param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
+
+diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
+index 77a132f6bbd1b..b3440a5e38af0 100644
+--- a/drivers/net/wireless/ath/ath12k/qmi.c
++++ b/drivers/net/wireless/ath/ath12k/qmi.c
+@@ -2941,6 +2941,9 @@ static const struct qmi_msg_handler ath12k_qmi_msg_handlers[] = {
+ .decoded_size = sizeof(struct qmi_wlanfw_fw_ready_ind_msg_v01),
+ .fn = ath12k_qmi_msg_fw_ready_cb,
+ },
++
++ /* end of list */
++ {},
+ };
+
+ static int ath12k_qmi_ops_new_server(struct qmi_handle *qmi_hdl,
+diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
+index 11cc3005c0f98..035d8f247e23e 100644
+--- a/drivers/net/wireless/ath/ath12k/wmi.c
++++ b/drivers/net/wireless/ath/ath12k/wmi.c
+@@ -1836,7 +1836,7 @@ static void ath12k_wmi_copy_peer_flags(struct wmi_peer_assoc_complete_cmd *cmd,
+ if (arg->bw_160)
+ cmd->peer_flags |= cpu_to_le32(WMI_PEER_160MHZ);
+ if (arg->bw_320)
+- cmd->peer_flags |= cpu_to_le32(WMI_PEER_EXT_320MHZ);
++ cmd->peer_flags_ext |= cpu_to_le32(WMI_PEER_EXT_320MHZ);
+
+ /* Typically if STBC is enabled for VHT it should be enabled
+ * for HT as well
+diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
+index 6bb9aa2bfe654..88ef6e023f826 100644
+--- a/drivers/net/wireless/ath/carl9170/tx.c
++++ b/drivers/net/wireless/ath/carl9170/tx.c
+@@ -280,7 +280,8 @@ static void carl9170_tx_release(struct kref *ref)
+ * carl9170_tx_fill_rateinfo() has filled the rate information
+ * before we get to this point.
+ */
+- memset_after(&txinfo->status, 0, rates);
++ memset(&txinfo->pad, 0, sizeof(txinfo->pad));
++ memset(&txinfo->rate_driver_data, 0, sizeof(txinfo->rate_driver_data));
+
+ if (atomic_read(&ar->tx_total_queued))
+ ar->tx_schedule = true;
+diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
+index c4edf83559410..a3e03580cd9ff 100644
+--- a/drivers/net/wireless/ath/carl9170/usb.c
++++ b/drivers/net/wireless/ath/carl9170/usb.c
+@@ -1069,6 +1069,38 @@ static int carl9170_usb_probe(struct usb_interface *intf,
+ ar->usb_ep_cmd_is_bulk = true;
+ }
+
++ /* Verify that all expected endpoints are present */
++ if (ar->usb_ep_cmd_is_bulk) {
++ u8 bulk_ep_addr[] = {
++ AR9170_USB_EP_RX | USB_DIR_IN,
++ AR9170_USB_EP_TX | USB_DIR_OUT,
++ AR9170_USB_EP_CMD | USB_DIR_OUT,
++ 0};
++ u8 int_ep_addr[] = {
++ AR9170_USB_EP_IRQ | USB_DIR_IN,
++ 0};
++ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
++ !usb_check_int_endpoints(intf, int_ep_addr))
++ err = -ENODEV;
++ } else {
++ u8 bulk_ep_addr[] = {
++ AR9170_USB_EP_RX | USB_DIR_IN,
++ AR9170_USB_EP_TX | USB_DIR_OUT,
++ 0};
++ u8 int_ep_addr[] = {
++ AR9170_USB_EP_IRQ | USB_DIR_IN,
++ AR9170_USB_EP_CMD | USB_DIR_OUT,
++ 0};
++ if (!usb_check_bulk_endpoints(intf, bulk_ep_addr) ||
++ !usb_check_int_endpoints(intf, int_ep_addr))
++ err = -ENODEV;
++ }
++
++ if (err) {
++ carl9170_free(ar);
++ return err;
++ }
++
+ usb_set_intfdata(intf, ar);
+ SET_IEEE80211_DEV(ar->hw, &intf->dev);
+
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+index d7fb88bb6ae1a..06698a714b523 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+@@ -1675,6 +1675,15 @@ struct brcmf_random_seed_footer {
+ #define BRCMF_RANDOM_SEED_MAGIC 0xfeedc0de
+ #define BRCMF_RANDOM_SEED_LENGTH 0x100
+
++static noinline_for_stack void
++brcmf_pcie_provide_random_bytes(struct brcmf_pciedev_info *devinfo, u32 address)
++{
++ u8 randbuf[BRCMF_RANDOM_SEED_LENGTH];
++
++ get_random_bytes(randbuf, BRCMF_RANDOM_SEED_LENGTH);
++ memcpy_toio(devinfo->tcm + address, randbuf, BRCMF_RANDOM_SEED_LENGTH);
++}
++
+ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
+ const struct firmware *fw, void *nvram,
+ u32 nvram_len)
+@@ -1717,7 +1726,6 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
+ .length = cpu_to_le32(rand_len),
+ .magic = cpu_to_le32(BRCMF_RANDOM_SEED_MAGIC),
+ };
+- void *randbuf;
+
+ /* Some Apple chips/firmwares expect a buffer of random
+ * data to be present before NVRAM
+@@ -1729,10 +1737,7 @@ static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
+ sizeof(footer));
+
+ address -= rand_len;
+- randbuf = kzalloc(rand_len, GFP_KERNEL);
+- get_random_bytes(randbuf, rand_len);
+- memcpy_toio(devinfo->tcm + address, randbuf, rand_len);
+- kfree(randbuf);
++ brcmf_pcie_provide_random_bytes(devinfo, address);
+ }
+ } else {
+ brcmf_dbg(PCIE, "No matching NVRAM file found %s\n",
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+index e321d41d1aba2..05735817918be 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
+@@ -1547,6 +1547,17 @@ static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm,
+ IWL_STA_MULTICAST);
+ }
+
++void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif)
++{
++ lockdep_assert_held(&mvm->mutex);
++
++ if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
++ return;
++
++ INIT_DELAYED_WORK(&mvmvif->csa_work,
++ iwl_mvm_channel_switch_disconnect_wk);
++}
++
+ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+ {
+@@ -1557,6 +1568,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
+
+ mutex_lock(&mvm->mutex);
+
++ iwl_mvm_mac_init_mvmvif(mvm, mvmvif);
++
+ mvmvif->mvm = mvm;
+
+ /* the first link always points to the default one */
+@@ -1632,8 +1645,6 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
+ mvm->p2p_device_vif = vif;
+
+ iwl_mvm_tcm_add_vif(mvm, vif);
+- INIT_DELAYED_WORK(&mvmvif->csa_work,
+- iwl_mvm_channel_switch_disconnect_wk);
+
+ if (vif->type == NL80211_IFTYPE_MONITOR) {
+ mvm->monitor_on = true;
+@@ -1671,6 +1682,8 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
+ void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
+ {
++ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
++
+ if (vif->type == NL80211_IFTYPE_P2P_DEVICE) {
+ /*
+ * Flush the ROC worker which will flush the OFFCHANNEL queue.
+@@ -1679,6 +1692,8 @@ void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
+ */
+ flush_work(&mvm->roc_done_wk);
+ }
++
++ cancel_delayed_work_sync(&mvmvif->csa_work);
+ }
+
+ /* This function is doing the common part of removing the interface for
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+index 893b69fc841b8..1b39c9ea55fa3 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c
+@@ -14,6 +14,8 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw,
+
+ mutex_lock(&mvm->mutex);
+
++ iwl_mvm_mac_init_mvmvif(mvm, mvmvif);
++
+ mvmvif->mvm = mvm;
+
+ /* Not much to do here. The stack will not allow interface
+@@ -189,17 +191,13 @@ static void iwl_mvm_mld_mac_remove_interface(struct ieee80211_hw *hw,
+ mutex_unlock(&mvm->mutex);
+ }
+
+-static unsigned int iwl_mvm_mld_count_active_links(struct ieee80211_vif *vif)
++static unsigned int iwl_mvm_mld_count_active_links(struct iwl_mvm_vif *mvmvif)
+ {
+ unsigned int n_active = 0;
+ int i;
+
+ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+- struct ieee80211_bss_conf *link_conf;
+-
+- link_conf = link_conf_dereference_protected(vif, i);
+- if (link_conf &&
+- rcu_access_pointer(link_conf->chanctx_conf))
++ if (mvmvif->link[i] && mvmvif->link[i]->phy_ctxt)
+ n_active++;
+ }
+
+@@ -245,21 +243,18 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
+ {
+ u16 *phy_ctxt_id = (u16 *)ctx->drv_priv;
+ struct iwl_mvm_phy_ctxt *phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
+- unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
++ unsigned int n_active = iwl_mvm_mld_count_active_links(mvmvif);
+ unsigned int link_id = link_conf->link_id;
+ int ret;
+
+- /* if the assigned one was not counted yet, count it now */
+- if (!rcu_access_pointer(link_conf->chanctx_conf))
+- n_active++;
+-
+- if (n_active > iwl_mvm_max_active_links(mvm, vif))
+- return -EOPNOTSUPP;
+-
+ if (WARN_ON_ONCE(!mvmvif->link[link_id]))
+ return -EINVAL;
+
++ /* if the assigned one was not counted yet, count it now */
++ if (!mvmvif->link[link_id]->phy_ctxt)
++ n_active++;
++
+ /* mac parameters such as HE support can change at this stage
+ * For sta, need first to configure correct state from drv_sta_state
+ * and only after that update mac config.
+@@ -299,13 +294,8 @@ __iwl_mvm_mld_assign_vif_chanctx(struct iwl_mvm *mvm,
+ * this needs the phy context assigned (and in FW?), and we cannot
+ * do it later because it needs to be initialized as soon as we're
+ * able to TX on the link, i.e. when active.
+- *
+- * Firmware restart isn't quite correct yet for MLO, but we don't
+- * need to do it in that case anyway since it will happen from the
+- * normal station state callback.
+ */
+- if (mvmvif->ap_sta &&
+- !test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
++ if (mvmvif->ap_sta) {
+ struct ieee80211_link_sta *link_sta;
+
+ rcu_read_lock();
+@@ -419,7 +409,7 @@ __iwl_mvm_mld_unassign_vif_chanctx(struct iwl_mvm *mvm,
+
+ {
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+- unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
++ unsigned int n_active = iwl_mvm_mld_count_active_links(mvmvif);
+ unsigned int link_id = link_conf->link_id;
+
+ /* shouldn't happen, but verify link_id is valid before accessing */
+@@ -1122,17 +1112,12 @@ iwl_mvm_mld_change_vif_links(struct ieee80211_hw *hw,
+ struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
+ {
+ struct iwl_mvm_vif_link_info *new_link[IEEE80211_MLD_MAX_NUM_LINKS] = {};
+- unsigned int n_active = iwl_mvm_mld_count_active_links(vif);
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ u16 removed = old_links & ~new_links;
+ u16 added = new_links & ~old_links;
+ int err, i;
+
+- if (hweight16(new_links) > 1 &&
+- n_active > iwl_mvm_max_active_links(mvm, vif))
+- return -EOPNOTSUPP;
+-
+ for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+ int r;
+
+@@ -1224,6 +1209,15 @@ iwl_mvm_mld_change_sta_links(struct ieee80211_hw *hw,
+ return ret;
+ }
+
++static bool iwl_mvm_mld_can_activate_links(struct ieee80211_hw *hw,
++ struct ieee80211_vif *vif,
++ u16 desired_links)
++{
++ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
++
++ return hweight16(desired_links) <= iwl_mvm_max_active_links(mvm, vif);
++}
++
+ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
+ .tx = iwl_mvm_mac_tx,
+ .wake_tx_queue = iwl_mvm_mac_wake_tx_queue,
+@@ -1318,4 +1312,5 @@ const struct ieee80211_ops iwl_mvm_mld_hw_ops = {
+
+ .change_vif_links = iwl_mvm_mld_change_vif_links,
+ .change_sta_links = iwl_mvm_mld_change_sta_links,
++ .can_activate_links = iwl_mvm_mld_can_activate_links,
+ };
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+index 23e64a757cfe8..36dc291d98dd6 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c
+@@ -9,7 +9,9 @@
+ u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+ int filter_link_id)
+ {
++ struct ieee80211_link_sta *link_sta;
+ struct iwl_mvm_sta *mvmsta;
++ struct ieee80211_vif *vif;
+ unsigned int link_id;
+ u32 result = 0;
+
+@@ -17,26 +19,27 @@ u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
+ return 0;
+
+ mvmsta = iwl_mvm_sta_from_mac80211(sta);
++ vif = mvmsta->vif;
+
+ /* it's easy when the STA is not an MLD */
+ if (!sta->valid_links)
+ return BIT(mvmsta->deflink.sta_id);
+
+ /* but if it is an MLD, get the mask of all the FW STAs it has ... */
+- for (link_id = 0; link_id < ARRAY_SIZE(mvmsta->link); link_id++) {
+- struct iwl_mvm_link_sta *link_sta;
++ for_each_sta_active_link(vif, sta, link_sta, link_id) {
++ struct iwl_mvm_link_sta *mvm_link_sta;
+
+ /* unless we have a specific link in mind */
+ if (filter_link_id >= 0 && link_id != filter_link_id)
+ continue;
+
+- link_sta =
++ mvm_link_sta =
+ rcu_dereference_check(mvmsta->link[link_id],
+ lockdep_is_held(&mvm->mutex));
+- if (!link_sta)
++ if (!mvm_link_sta)
+ continue;
+
+- result |= BIT(link_sta->sta_id);
++ result |= BIT(mvm_link_sta->sta_id);
+ }
+
+ return result;
+@@ -582,14 +585,14 @@ static int iwl_mvm_mld_alloc_sta_links(struct iwl_mvm *mvm,
+ struct ieee80211_sta *sta)
+ {
+ struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
++ struct ieee80211_link_sta *link_sta;
+ unsigned int link_id;
+ int ret;
+
+ lockdep_assert_held(&mvm->mutex);
+
+- for (link_id = 0; link_id < ARRAY_SIZE(sta->link); link_id++) {
+- if (!rcu_access_pointer(sta->link[link_id]) ||
+- mvm_sta->link[link_id])
++ for_each_sta_active_link(vif, sta, link_sta, link_id) {
++ if (WARN_ON(mvm_sta->link[link_id]))
+ continue;
+
+ ret = iwl_mvm_mld_alloc_sta_link(mvm, vif, sta, link_id);
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+index fe0fa9ff533d7..4653f608355cc 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+@@ -1769,6 +1769,8 @@ int iwl_mvm_load_d3_fw(struct iwl_mvm *mvm);
+
+ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm);
+
++void iwl_mvm_mac_init_mvmvif(struct iwl_mvm *mvm, struct iwl_mvm_vif *mvmvif);
++
+ /*
+ * FW notifications / CMD responses handlers
+ * Convention: iwl_mvm_rx_<NAME OF THE CMD>
+diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+index 97d44354dbbb5..3dc6fb0600aae 100644
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+@@ -3173,8 +3173,13 @@ void iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
+ struct iwl_mvm_vif_link_info *link_info =
+ scan_vif->link[mvm->scan_link_id];
+
+- if (!WARN_ON(!link_info))
++ /* It is possible that by the time the scan is complete the link
++ * was already removed and is not valid.
++ */
++ if (link_info)
+ memcpy(info.tsf_bssid, link_info->bssid, ETH_ALEN);
++ else
++ IWL_DEBUG_SCAN(mvm, "Scan link is no longer valid\n");
+
+ ieee80211_scan_completed(mvm->hw, &info);
+ mvm->scan_vif = NULL;
+diff --git a/drivers/net/wireless/marvell/mwl8k.c b/drivers/net/wireless/marvell/mwl8k.c
+index 13bcb123d1223..c0ecd769ada76 100644
+--- a/drivers/net/wireless/marvell/mwl8k.c
++++ b/drivers/net/wireless/marvell/mwl8k.c
+@@ -2718,7 +2718,7 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti,
+ cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
+ cmd->numaddr = cpu_to_le16(mc_count);
+ netdev_hw_addr_list_for_each(ha, mc_list) {
+- memcpy(cmd->addr[i], ha->addr, ETH_ALEN);
++ memcpy(cmd->addr[i++], ha->addr, ETH_ALEN);
+ }
+ }
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
+index 7a2f5d38562b4..14304b0637158 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/dma.c
+@@ -4,6 +4,13 @@
+ #include "mac.h"
+ #include "../dma.h"
+
++static const u8 wmm_queue_map[] = {
++ [IEEE80211_AC_BK] = 0,
++ [IEEE80211_AC_BE] = 1,
++ [IEEE80211_AC_VI] = 2,
++ [IEEE80211_AC_VO] = 3,
++};
++
+ static void
+ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
+ {
+@@ -22,10 +29,10 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
+ struct ieee80211_sta *sta;
+ struct mt7603_sta *msta;
+ struct mt76_wcid *wcid;
++ u8 tid = 0, hwq = 0;
+ void *priv;
+ int idx;
+ u32 val;
+- u8 tid = 0;
+
+ if (skb->len < MT_TXD_SIZE + sizeof(struct ieee80211_hdr))
+ goto free;
+@@ -42,19 +49,36 @@ mt7603_rx_loopback_skb(struct mt7603_dev *dev, struct sk_buff *skb)
+ goto free;
+
+ priv = msta = container_of(wcid, struct mt7603_sta, wcid);
+- val = le32_to_cpu(txd[0]);
+- val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX);
+- val |= FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_HW_QUEUE_MGMT);
+- txd[0] = cpu_to_le32(val);
+
+ sta = container_of(priv, struct ieee80211_sta, drv_priv);
+ hdr = (struct ieee80211_hdr *)&skb->data[MT_TXD_SIZE];
+- if (ieee80211_is_data_qos(hdr->frame_control))
++
++ hwq = wmm_queue_map[IEEE80211_AC_BE];
++ if (ieee80211_is_data_qos(hdr->frame_control)) {
+ tid = *ieee80211_get_qos_ctl(hdr) &
+- IEEE80211_QOS_CTL_TAG1D_MASK;
+- skb_set_queue_mapping(skb, tid_to_ac[tid]);
++ IEEE80211_QOS_CTL_TAG1D_MASK;
++ u8 qid = tid_to_ac[tid];
++ hwq = wmm_queue_map[qid];
++ skb_set_queue_mapping(skb, qid);
++ } else if (ieee80211_is_data(hdr->frame_control)) {
++ skb_set_queue_mapping(skb, IEEE80211_AC_BE);
++ hwq = wmm_queue_map[IEEE80211_AC_BE];
++ } else {
++ skb_pull(skb, MT_TXD_SIZE);
++ if (!ieee80211_is_bufferable_mmpdu(skb))
++ goto free;
++ skb_push(skb, MT_TXD_SIZE);
++ skb_set_queue_mapping(skb, MT_TXQ_PSD);
++ hwq = MT_TX_HW_QUEUE_MGMT;
++ }
++
+ ieee80211_sta_set_buffered(sta, tid, true);
+
++ val = le32_to_cpu(txd[0]);
++ val &= ~(MT_TXD0_P_IDX | MT_TXD0_Q_IDX);
++ val |= FIELD_PREP(MT_TXD0_Q_IDX, hwq);
++ txd[0] = cpu_to_le32(val);
++
+ spin_lock_bh(&dev->ps_lock);
+ __skb_queue_tail(&msta->psq, skb);
+ if (skb_queue_len(&msta->psq) >= 64) {
+@@ -151,12 +175,6 @@ static int mt7603_poll_tx(struct napi_struct *napi, int budget)
+
+ int mt7603_dma_init(struct mt7603_dev *dev)
+ {
+- static const u8 wmm_queue_map[] = {
+- [IEEE80211_AC_BK] = 0,
+- [IEEE80211_AC_BE] = 1,
+- [IEEE80211_AC_VI] = 2,
+- [IEEE80211_AC_VO] = 3,
+- };
+ int ret;
+ int i;
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+index cf21d06257e53..dc8a77f0a1cc4 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7603/mac.c
+@@ -1393,6 +1393,7 @@ void mt7603_pse_client_reset(struct mt7603_dev *dev)
+ MT_CLIENT_RESET_TX_R_E_2_S);
+
+ /* Start PSE client TX abort */
++ mt76_set(dev, MT_WPDMA_GLO_CFG, MT_WPDMA_GLO_CFG_FORCE_TX_EOF);
+ mt76_set(dev, addr, MT_CLIENT_RESET_TX_R_E_1);
+ mt76_poll_msec(dev, addr, MT_CLIENT_RESET_TX_R_E_1_S,
+ MT_CLIENT_RESET_TX_R_E_1_S, 500);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+index ae19174b46ee5..5809555a909d7 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+@@ -2524,6 +2524,7 @@ int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend)
+ __le16 tag;
+ __le16 len;
+ u8 suspend;
++ u8 pad[7];
+ } __packed hif_suspend;
+ } req = {
+ .hif_suspend = {
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
+index 6c3696c8c7002..450f4d221184b 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
+@@ -1049,6 +1049,7 @@ static ssize_t
+ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+ {
++ int i, ret, pwr, pwr160 = 0, pwr80 = 0, pwr40 = 0, pwr20 = 0;
+ struct mt7915_phy *phy = file->private_data;
+ struct mt7915_dev *dev = phy->dev;
+ struct mt76_phy *mphy = phy->mt76;
+@@ -1057,7 +1058,6 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
+ .band_idx = phy->mt76->band_idx,
+ };
+ char buf[100];
+- int i, ret, pwr160 = 0, pwr80 = 0, pwr40 = 0, pwr20 = 0;
+ enum mac80211_rx_encoding mode;
+ u32 offs = 0, len = 0;
+
+@@ -1130,8 +1130,8 @@ mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
+ if (ret)
+ goto out;
+
+- mphy->txpower_cur = max(mphy->txpower_cur,
+- max(pwr160, max(pwr80, max(pwr40, pwr20))));
++ pwr = max3(pwr80, pwr40, pwr20);
++ mphy->txpower_cur = max3(mphy->txpower_cur, pwr160, pwr);
+ out:
+ mutex_unlock(&dev->mt76.mutex);
+
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
+index 2cf39276118eb..1599338e06310 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.h
+@@ -535,7 +535,7 @@ struct mt7925_wow_pattern_tlv {
+ u8 offset;
+ u8 mask[MT76_CONNAC_WOW_MASK_MAX_LEN];
+ u8 pattern[MT76_CONNAC_WOW_PATTEN_MAX_LEN];
+- u8 rsv[4];
++ u8 rsv[7];
+ } __packed;
+
+ static inline enum connac3_mcu_cipher_type
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+index 9e70b960086ac..10d13fa45c5a1 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+@@ -3733,6 +3733,7 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy)
+ } __packed * res;
+ struct sk_buff *skb;
+ int ret;
++ u32 temp;
+
+ ret = mt76_mcu_send_and_get_msg(&phy->dev->mt76, MCU_WM_UNI_CMD(THERMAL),
+ &req, sizeof(req), true, &skb);
+@@ -3740,8 +3741,10 @@ int mt7996_mcu_get_temperature(struct mt7996_phy *phy)
+ return ret;
+
+ res = (void *)skb->data;
++ temp = le32_to_cpu(res->temperature);
++ dev_kfree_skb(skb);
+
+- return le32_to_cpu(res->temperature);
++ return temp;
+ }
+
+ int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state)
+@@ -4468,7 +4471,7 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
+ u8 band_idx;
+ } __packed req = {
+ .tag = cpu_to_le16(UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL),
+- .len = cpu_to_le16(sizeof(req) + MT7996_SKU_RATE_NUM - 4),
++ .len = cpu_to_le16(sizeof(req) + MT7996_SKU_PATH_NUM - 4),
+ .power_ctrl_id = UNI_TXPOWER_POWER_LIMIT_TABLE_CTRL,
+ .power_limit_type = TX_POWER_LIMIT_TABLE_RATE,
+ .band_idx = phy->mt76->band_idx,
+@@ -4483,7 +4486,7 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
+ mphy->txpower_cur = tx_power;
+
+ skb = mt76_mcu_msg_alloc(&dev->mt76, NULL,
+- sizeof(req) + MT7996_SKU_RATE_NUM);
++ sizeof(req) + MT7996_SKU_PATH_NUM);
+ if (!skb)
+ return -ENOMEM;
+
+@@ -4507,6 +4510,9 @@ int mt7996_mcu_set_txpower_sku(struct mt7996_phy *phy)
+ /* eht */
+ skb_put_data(skb, &la.eht[0], sizeof(la.eht));
+
++ /* padding */
++ skb_put_zero(skb, MT7996_SKU_PATH_NUM - MT7996_SKU_RATE_NUM);
++
+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+ MCU_WM_UNI_CMD(TXPOWER), true);
+ }
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
+index efd4a767eb37d..c93f82548beeb 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mmio.c
+@@ -519,7 +519,7 @@ static void mt7996_irq_tasklet(struct tasklet_struct *t)
+ struct mt7996_dev *dev = from_tasklet(dev, t, mt76.irq_tasklet);
+ struct mtk_wed_device *wed = &dev->mt76.mmio.wed;
+ struct mtk_wed_device *wed_hif2 = &dev->mt76.mmio.wed_hif2;
+- u32 i, intr, mask, intr1;
++ u32 i, intr, mask, intr1 = 0;
+
+ if (dev->hif2 && mtk_wed_device_active(wed_hif2)) {
+ mtk_wed_device_irq_set_mask(wed_hif2, 0);
+diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+index 36d1f247d55aa..ddeb40d522c5a 100644
+--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+@@ -50,6 +50,7 @@
+ #define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */
+
+ #define MT7996_SKU_RATE_NUM 417
++#define MT7996_SKU_PATH_NUM 494
+
+ #define MT7996_MAX_TWT_AGRT 16
+ #define MT7996_MAX_STA_TWT_AGRT 8
+diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
+index 917c01e5e9eda..e86d5588ec609 100644
+--- a/drivers/net/wireless/realtek/rtw89/ps.c
++++ b/drivers/net/wireless/realtek/rtw89/ps.c
+@@ -54,7 +54,8 @@ static void rtw89_ps_power_mode_change_with_hci(struct rtw89_dev *rtwdev,
+
+ static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
+ {
+- if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode))
++ if (rtwdev->chip->low_power_hci_modes & BIT(rtwdev->ps_mode) &&
++ !test_bit(RTW89_FLAG_WOWLAN, rtwdev->flags))
+ rtw89_ps_power_mode_change_with_hci(rtwdev, enter);
+ else
+ rtw89_mac_power_mode_change(rtwdev, enter);
+diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c
+index 5c7ca36c09b6b..abb4d1cc55d0e 100644
+--- a/drivers/net/wireless/realtek/rtw89/wow.c
++++ b/drivers/net/wireless/realtek/rtw89/wow.c
+@@ -489,14 +489,17 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
+ struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
+ struct ieee80211_vif *wow_vif = rtw_wow->wow_vif;
+ struct rtw89_vif *rtwvif = (struct rtw89_vif *)wow_vif->drv_priv;
++ enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ bool include_bb = !!chip->bbmcu_nr;
++ bool disable_intr_for_dlfw = false;
+ struct ieee80211_sta *wow_sta;
+ struct rtw89_sta *rtwsta = NULL;
+ bool is_conn = true;
+ int ret;
+
+- rtw89_hci_disable_intr(rtwdev);
++ if (chip_id == RTL8852C || chip_id == RTL8922A)
++ disable_intr_for_dlfw = true;
+
+ wow_sta = ieee80211_find_sta(wow_vif, rtwvif->bssid);
+ if (wow_sta)
+@@ -504,12 +507,18 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
+ else
+ is_conn = false;
+
++ if (disable_intr_for_dlfw)
++ rtw89_hci_disable_intr(rtwdev);
++
+ ret = rtw89_fw_download(rtwdev, fw_type, include_bb);
+ if (ret) {
+ rtw89_warn(rtwdev, "download fw failed\n");
+ return ret;
+ }
+
++ if (disable_intr_for_dlfw)
++ rtw89_hci_enable_intr(rtwdev);
++
+ rtw89_phy_init_rf_reg(rtwdev, true);
+
+ ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta,
+@@ -552,7 +561,6 @@ static int rtw89_wow_swap_fw(struct rtw89_dev *rtwdev, bool wow)
+ }
+
+ rtw89_mac_hw_mgnt_sec(rtwdev, wow);
+- rtw89_hci_enable_intr(rtwdev);
+
+ return 0;
+ }
+diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
+index 26153cb7647d7..3cc79817e4d75 100644
+--- a/drivers/nvme/host/core.c
++++ b/drivers/nvme/host/core.c
+@@ -619,27 +619,6 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl,
+ }
+ EXPORT_SYMBOL_GPL(nvme_change_ctrl_state);
+
+-/*
+- * Returns true for sink states that can't ever transition back to live.
+- */
+-static bool nvme_state_terminal(struct nvme_ctrl *ctrl)
+-{
+- switch (nvme_ctrl_state(ctrl)) {
+- case NVME_CTRL_NEW:
+- case NVME_CTRL_LIVE:
+- case NVME_CTRL_RESETTING:
+- case NVME_CTRL_CONNECTING:
+- return false;
+- case NVME_CTRL_DELETING:
+- case NVME_CTRL_DELETING_NOIO:
+- case NVME_CTRL_DEAD:
+- return true;
+- default:
+- WARN_ONCE(1, "Unhandled ctrl state:%d", ctrl->state);
+- return true;
+- }
+-}
+-
+ /*
+ * Waits for the controller state to be resetting, or returns false if it is
+ * not possible to ever transition to that state.
+diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
+index 74de1e64aeead..75386d3e0f981 100644
+--- a/drivers/nvme/host/multipath.c
++++ b/drivers/nvme/host/multipath.c
+@@ -247,7 +247,8 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node)
+ if (nvme_path_is_disabled(ns))
+ continue;
+
+- if (READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_NUMA)
++ if (ns->ctrl->numa_node != NUMA_NO_NODE &&
++ READ_ONCE(head->subsys->iopolicy) == NVME_IOPOLICY_NUMA)
+ distance = node_distance(node, ns->ctrl->numa_node);
+ else
+ distance = LOCAL_DISTANCE;
+diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
+index 738719085e054..2a7bf574284f6 100644
+--- a/drivers/nvme/host/nvme.h
++++ b/drivers/nvme/host/nvme.h
+@@ -745,6 +745,27 @@ static inline bool nvme_is_aen_req(u16 qid, __u16 command_id)
+ nvme_tag_from_cid(command_id) >= NVME_AQ_BLK_MQ_DEPTH;
+ }
+
++/*
++ * Returns true for sink states that can't ever transition back to live.
++ */
++static inline bool nvme_state_terminal(struct nvme_ctrl *ctrl)
++{
++ switch (nvme_ctrl_state(ctrl)) {
++ case NVME_CTRL_NEW:
++ case NVME_CTRL_LIVE:
++ case NVME_CTRL_RESETTING:
++ case NVME_CTRL_CONNECTING:
++ return false;
++ case NVME_CTRL_DELETING:
++ case NVME_CTRL_DELETING_NOIO:
++ case NVME_CTRL_DEAD:
++ return true;
++ default:
++ WARN_ONCE(1, "Unhandled ctrl state:%d", ctrl->state);
++ return true;
++ }
++}
++
+ void nvme_complete_rq(struct request *req);
+ void nvme_complete_batch_req(struct request *req);
+
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index 02565dc99ad85..710043086dffa 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -1286,6 +1286,9 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
+ u32 csts = readl(dev->bar + NVME_REG_CSTS);
+ u8 opcode;
+
++ if (nvme_state_terminal(&dev->ctrl))
++ goto disable;
++
+ /* If PCI error recovery process is happening, we cannot reset or
+ * the recovery mechanism will surely fail.
+ */
+@@ -1390,8 +1393,11 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
+ return BLK_EH_RESET_TIMER;
+
+ disable:
+- if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING))
++ if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING)) {
++ if (nvme_state_terminal(&dev->ctrl))
++ nvme_dev_disable(dev, true);
+ return BLK_EH_DONE;
++ }
+
+ nvme_dev_disable(dev, false);
+ if (nvme_try_sched_reset(&dev->ctrl))
+diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
+index a6d596e056021..6eeb96578d1b4 100644
+--- a/drivers/nvme/host/tcp.c
++++ b/drivers/nvme/host/tcp.c
+@@ -352,12 +352,18 @@ static inline void nvme_tcp_send_all(struct nvme_tcp_queue *queue)
+ } while (ret > 0);
+ }
+
+-static inline bool nvme_tcp_queue_more(struct nvme_tcp_queue *queue)
++static inline bool nvme_tcp_queue_has_pending(struct nvme_tcp_queue *queue)
+ {
+ return !list_empty(&queue->send_list) ||
+ !llist_empty(&queue->req_list);
+ }
+
++static inline bool nvme_tcp_queue_more(struct nvme_tcp_queue *queue)
++{
++ return !nvme_tcp_tls(&queue->ctrl->ctrl) &&
++ nvme_tcp_queue_has_pending(queue);
++}
++
+ static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
+ bool sync, bool last)
+ {
+@@ -378,7 +384,7 @@ static inline void nvme_tcp_queue_request(struct nvme_tcp_request *req,
+ mutex_unlock(&queue->send_mutex);
+ }
+
+- if (last && nvme_tcp_queue_more(queue))
++ if (last && nvme_tcp_queue_has_pending(queue))
+ queue_work_on(queue->io_cpu, nvme_tcp_wq, &queue->io_work);
+ }
+
+diff --git a/drivers/nvme/target/auth.c b/drivers/nvme/target/auth.c
+index 3ddbc3880cac8..fb518b00f71f6 100644
+--- a/drivers/nvme/target/auth.c
++++ b/drivers/nvme/target/auth.c
+@@ -285,9 +285,9 @@ int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
+ }
+
+ if (shash_len != crypto_shash_digestsize(shash_tfm)) {
+- pr_debug("%s: hash len mismatch (len %d digest %d)\n",
+- __func__, shash_len,
+- crypto_shash_digestsize(shash_tfm));
++ pr_err("%s: hash len mismatch (len %d digest %d)\n",
++ __func__, shash_len,
++ crypto_shash_digestsize(shash_tfm));
+ ret = -EINVAL;
+ goto out_free_tfm;
+ }
+@@ -370,7 +370,7 @@ int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
+ nvme_auth_free_key(transformed_key);
+ out_free_tfm:
+ crypto_free_shash(shash_tfm);
+- return 0;
++ return ret;
+ }
+
+ int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response,
+diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
+index 2482a0db25043..3ef6bc655661d 100644
+--- a/drivers/nvme/target/configfs.c
++++ b/drivers/nvme/target/configfs.c
+@@ -728,6 +728,18 @@ static struct configfs_attribute *nvmet_ns_attrs[] = {
+ NULL,
+ };
+
++bool nvmet_subsys_nsid_exists(struct nvmet_subsys *subsys, u32 nsid)
++{
++ struct config_item *ns_item;
++ char name[12];
++
++ snprintf(name, sizeof(name), "%u", nsid);
++ mutex_lock(&subsys->namespaces_group.cg_subsys->su_mutex);
++ ns_item = config_group_find_item(&subsys->namespaces_group, name);
++ mutex_unlock(&subsys->namespaces_group.cg_subsys->su_mutex);
++ return ns_item != NULL;
++}
++
+ static void nvmet_ns_release(struct config_item *item)
+ {
+ struct nvmet_ns *ns = to_nvmet_ns(item);
+diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
+index 8658e9c08534d..7a6b3d37cca70 100644
+--- a/drivers/nvme/target/core.c
++++ b/drivers/nvme/target/core.c
+@@ -425,10 +425,13 @@ void nvmet_stop_keep_alive_timer(struct nvmet_ctrl *ctrl)
+ u16 nvmet_req_find_ns(struct nvmet_req *req)
+ {
+ u32 nsid = le32_to_cpu(req->cmd->common.nsid);
++ struct nvmet_subsys *subsys = nvmet_req_subsys(req);
+
+- req->ns = xa_load(&nvmet_req_subsys(req)->namespaces, nsid);
++ req->ns = xa_load(&subsys->namespaces, nsid);
+ if (unlikely(!req->ns)) {
+ req->error_loc = offsetof(struct nvme_common_command, nsid);
++ if (nvmet_subsys_nsid_exists(subsys, nsid))
++ return NVME_SC_INTERNAL_PATH_ERROR;
+ return NVME_SC_INVALID_NS | NVME_SC_DNR;
+ }
+
+diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
+index 6c8acebe1a1a6..477416abf85ab 100644
+--- a/drivers/nvme/target/nvmet.h
++++ b/drivers/nvme/target/nvmet.h
+@@ -542,6 +542,7 @@ void nvmet_subsys_disc_changed(struct nvmet_subsys *subsys,
+ struct nvmet_host *host);
+ void nvmet_add_async_event(struct nvmet_ctrl *ctrl, u8 event_type,
+ u8 event_info, u8 log_page);
++bool nvmet_subsys_nsid_exists(struct nvmet_subsys *subsys, u32 nsid);
+
+ #define NVMET_QUEUE_SIZE 1024
+ #define NVMET_NR_QUEUES 128
+diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c
+index c8655fc5aa5b8..8d4531a1606d1 100644
+--- a/drivers/nvme/target/tcp.c
++++ b/drivers/nvme/target/tcp.c
+@@ -348,6 +348,7 @@ static int nvmet_tcp_check_ddgst(struct nvmet_tcp_queue *queue, void *pdu)
+ return 0;
+ }
+
++/* If cmd buffers are NULL, no operation is performed */
+ static void nvmet_tcp_free_cmd_buffers(struct nvmet_tcp_cmd *cmd)
+ {
+ kfree(cmd->iov);
+@@ -1580,13 +1581,9 @@ static void nvmet_tcp_free_cmd_data_in_buffers(struct nvmet_tcp_queue *queue)
+ struct nvmet_tcp_cmd *cmd = queue->cmds;
+ int i;
+
+- for (i = 0; i < queue->nr_cmds; i++, cmd++) {
+- if (nvmet_tcp_need_data_in(cmd))
+- nvmet_tcp_free_cmd_buffers(cmd);
+- }
+-
+- if (!queue->nr_cmds && nvmet_tcp_need_data_in(&queue->connect))
+- nvmet_tcp_free_cmd_buffers(&queue->connect);
++ for (i = 0; i < queue->nr_cmds; i++, cmd++)
++ nvmet_tcp_free_cmd_buffers(cmd);
++ nvmet_tcp_free_cmd_buffers(&queue->connect);
+ }
+
+ static void nvmet_tcp_release_queue_work(struct work_struct *w)
+diff --git a/drivers/of/module.c b/drivers/of/module.c
+index f58e624953a20..780fd82a7ecc5 100644
+--- a/drivers/of/module.c
++++ b/drivers/of/module.c
+@@ -29,14 +29,15 @@ ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
+ csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
+ of_node_get_device_type(np));
+ tsize = csize;
++ if (csize >= len)
++ csize = len > 0 ? len - 1 : 0;
+ len -= csize;
+- if (str)
+- str += csize;
++ str += csize;
+
+ of_property_for_each_string(np, "compatible", p, compat) {
+ csize = strlen(compat) + 1;
+ tsize += csize;
+- if (csize > len)
++ if (csize >= len)
+ continue;
+
+ csize = snprintf(str, len, "C%s", compat);
+diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c
+index b90ba8aca3fa5..ec4d5fc30781c 100644
+--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c
++++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c
+@@ -337,15 +337,27 @@ static bool hisi_pcie_pmu_validate_event_group(struct perf_event *event)
+ return false;
+
+ for (num = 0; num < counters; num++) {
++ /*
++ * If we find a related event, then it's a valid group
++ * since we don't need to allocate a new counter for it.
++ */
+ if (hisi_pcie_pmu_cmp_event(event_group[num], sibling))
+ break;
+ }
+
++ /*
++ * Otherwise it's a new event but if there's no available counter,
++ * fail the check since we cannot schedule all the events in
++ * the group simultaneously.
++ */
++ if (num == HISI_PCIE_MAX_COUNTERS)
++ return false;
++
+ if (num == counters)
+ event_group[counters++] = sibling;
+ }
+
+- return counters <= HISI_PCIE_MAX_COUNTERS;
++ return true;
+ }
+
+ static int hisi_pcie_pmu_event_init(struct perf_event *event)
+diff --git a/drivers/perf/hisilicon/hns3_pmu.c b/drivers/perf/hisilicon/hns3_pmu.c
+index 16869bf5bf4cc..60062eaa342aa 100644
+--- a/drivers/perf/hisilicon/hns3_pmu.c
++++ b/drivers/perf/hisilicon/hns3_pmu.c
+@@ -1085,15 +1085,27 @@ static bool hns3_pmu_validate_event_group(struct perf_event *event)
+ return false;
+
+ for (num = 0; num < counters; num++) {
++ /*
++ * If we find a related event, then it's a valid group
++ * since we don't need to allocate a new counter for it.
++ */
+ if (hns3_pmu_cmp_event(event_group[num], sibling))
+ break;
+ }
+
++ /*
++ * Otherwise it's a new event but if there's no available counter,
++ * fail the check since we cannot schedule all the events in
++ * the group simultaneously.
++ */
++ if (num == HNS3_PMU_MAX_HW_EVENTS)
++ return false;
++
+ if (num == counters)
+ event_group[counters++] = sibling;
+ }
+
+- return counters <= HNS3_PMU_MAX_HW_EVENTS;
++ return true;
+ }
+
+ static u32 hns3_pmu_get_filter_condition(struct perf_event *event)
+@@ -1515,7 +1527,7 @@ static int hns3_pmu_irq_register(struct pci_dev *pdev,
+ return ret;
+ }
+
+- ret = devm_add_action(&pdev->dev, hns3_pmu_free_irq, pdev);
++ ret = devm_add_action_or_reset(&pdev->dev, hns3_pmu_free_irq, pdev);
+ if (ret) {
+ pci_err(pdev, "failed to add free irq action, ret = %d.\n", ret);
+ return ret;
+diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
+index 30951f7131cd9..1accdaaf282c5 100644
+--- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
++++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c
+@@ -721,6 +721,7 @@ static struct miscdevice isst_if_char_driver = {
+ static const struct x86_cpu_id hpm_cpu_ids[] = {
+ X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_D, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_X, NULL),
++ X86_MATCH_INTEL_FAM6_MODEL(ATOM_CRESTMONT, NULL),
+ X86_MATCH_INTEL_FAM6_MODEL(ATOM_CRESTMONT_X, NULL),
+ {}
+ };
+diff --git a/drivers/platform/x86/xiaomi-wmi.c b/drivers/platform/x86/xiaomi-wmi.c
+index 54a2546bb93bf..be80f0bda9484 100644
+--- a/drivers/platform/x86/xiaomi-wmi.c
++++ b/drivers/platform/x86/xiaomi-wmi.c
+@@ -2,8 +2,10 @@
+ /* WMI driver for Xiaomi Laptops */
+
+ #include <linux/acpi.h>
++#include <linux/device.h>
+ #include <linux/input.h>
+ #include <linux/module.h>
++#include <linux/mutex.h>
+ #include <linux/wmi.h>
+
+ #include <uapi/linux/input-event-codes.h>
+@@ -20,12 +22,21 @@
+
+ struct xiaomi_wmi {
+ struct input_dev *input_dev;
++ struct mutex key_lock; /* Protects the key event sequence */
+ unsigned int key_code;
+ };
+
++static void xiaomi_mutex_destroy(void *data)
++{
++ struct mutex *lock = data;
++
++ mutex_destroy(lock);
++}
++
+ static int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
+ {
+ struct xiaomi_wmi *data;
++ int ret;
+
+ if (wdev == NULL || context == NULL)
+ return -EINVAL;
+@@ -35,6 +46,11 @@ static int xiaomi_wmi_probe(struct wmi_device *wdev, const void *context)
+ return -ENOMEM;
+ dev_set_drvdata(&wdev->dev, data);
+
++ mutex_init(&data->key_lock);
++ ret = devm_add_action_or_reset(&wdev->dev, xiaomi_mutex_destroy, &data->key_lock);
++ if (ret < 0)
++ return ret;
++
+ data->input_dev = devm_input_allocate_device(&wdev->dev);
+ if (data->input_dev == NULL)
+ return -ENOMEM;
+@@ -59,10 +75,12 @@ static void xiaomi_wmi_notify(struct wmi_device *wdev, union acpi_object *dummy)
+ if (data == NULL)
+ return;
+
++ mutex_lock(&data->key_lock);
+ input_report_key(data->input_dev, data->key_code, 1);
+ input_sync(data->input_dev);
+ input_report_key(data->input_dev, data->key_code, 0);
+ input_sync(data->input_dev);
++ mutex_unlock(&data->key_lock);
+ }
+
+ static const struct wmi_device_id xiaomi_wmi_id_table[] = {
+diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
+index 5f858e426bbd5..05b8f325a887d 100644
+--- a/drivers/ptp/ptp_ocp.c
++++ b/drivers/ptp/ptp_ocp.c
+@@ -4277,7 +4277,7 @@ static int ptp_ocp_dpll_direction_set(const struct dpll_pin *pin,
+ return -EOPNOTSUPP;
+ mode = direction == DPLL_PIN_DIRECTION_INPUT ?
+ SMA_MODE_IN : SMA_MODE_OUT;
+- return ptp_ocp_sma_store_val(bp, 0, mode, sma_nr);
++ return ptp_ocp_sma_store_val(bp, 0, mode, sma_nr + 1);
+ }
+
+ static int ptp_ocp_dpll_frequency_set(const struct dpll_pin *pin,
+@@ -4298,7 +4298,7 @@ static int ptp_ocp_dpll_frequency_set(const struct dpll_pin *pin,
+ tbl = bp->sma_op->tbl[sma->mode];
+ for (i = 0; tbl[i].name; i++)
+ if (tbl[i].frequency == frequency)
+- return ptp_ocp_sma_store_val(bp, i, sma->mode, sma_nr);
++ return ptp_ocp_sma_store_val(bp, i, sma->mode, sma_nr + 1);
+ return -EINVAL;
+ }
+
+@@ -4315,7 +4315,7 @@ static int ptp_ocp_dpll_frequency_get(const struct dpll_pin *pin,
+ u32 val;
+ int i;
+
+- val = bp->sma_op->get(bp, sma_nr);
++ val = bp->sma_op->get(bp, sma_nr + 1);
+ tbl = bp->sma_op->tbl[sma->mode];
+ for (i = 0; tbl[i].name; i++)
+ if (val == tbl[i].value) {
+diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
+index f2728ee787d7a..9d2dc5e1c8aac 100644
+--- a/drivers/pwm/core.c
++++ b/drivers/pwm/core.c
+@@ -24,277 +24,358 @@
+ #define CREATE_TRACE_POINTS
+ #include <trace/events/pwm.h>
+
+-static DEFINE_MUTEX(pwm_lookup_lock);
+-static LIST_HEAD(pwm_lookup_list);
+-
+ /* protects access to pwm_chips */
+ static DEFINE_MUTEX(pwm_lock);
+
+ static DEFINE_IDR(pwm_chips);
+
+-static struct pwm_chip *pwmchip_find_by_name(const char *name)
++static void pwm_apply_debug(struct pwm_device *pwm,
++ const struct pwm_state *state)
+ {
+- struct pwm_chip *chip;
+- unsigned long id, tmp;
+-
+- if (!name)
+- return NULL;
+-
+- mutex_lock(&pwm_lock);
++ struct pwm_state *last = &pwm->last;
++ struct pwm_chip *chip = pwm->chip;
++ struct pwm_state s1 = { 0 }, s2 = { 0 };
++ int err;
+
+- idr_for_each_entry_ul(&pwm_chips, chip, tmp, id) {
+- const char *chip_name = dev_name(chip->dev);
++ if (!IS_ENABLED(CONFIG_PWM_DEBUG))
++ return;
+
+- if (chip_name && strcmp(chip_name, name) == 0) {
+- mutex_unlock(&pwm_lock);
+- return chip;
+- }
+- }
++ /* No reasonable diagnosis possible without .get_state() */
++ if (!chip->ops->get_state)
++ return;
+
+- mutex_unlock(&pwm_lock);
++ /*
++ * *state was just applied. Read out the hardware state and do some
++ * checks.
++ */
+
+- return NULL;
+-}
++ err = chip->ops->get_state(chip, pwm, &s1);
++ trace_pwm_get(pwm, &s1, err);
++ if (err)
++ /* If that failed there isn't much to debug */
++ return;
+
+-static int pwm_device_request(struct pwm_device *pwm, const char *label)
+-{
+- int err;
+- struct pwm_chip *chip = pwm->chip;
+- const struct pwm_ops *ops = chip->ops;
++ /*
++ * The lowlevel driver either ignored .polarity (which is a bug) or as
++ * best effort inverted .polarity and fixed .duty_cycle respectively.
++ * Undo this inversion and fixup for further tests.
++ */
++ if (s1.enabled && s1.polarity != state->polarity) {
++ s2.polarity = state->polarity;
++ s2.duty_cycle = s1.period - s1.duty_cycle;
++ s2.period = s1.period;
++ s2.enabled = s1.enabled;
++ } else {
++ s2 = s1;
++ }
+
+- if (test_bit(PWMF_REQUESTED, &pwm->flags))
+- return -EBUSY;
++ if (s2.polarity != state->polarity &&
++ state->duty_cycle < state->period)
++ dev_warn(pwmchip_parent(chip), ".apply ignored .polarity\n");
+
+- if (!try_module_get(chip->owner))
+- return -ENODEV;
++ if (state->enabled &&
++ last->polarity == state->polarity &&
++ last->period > s2.period &&
++ last->period <= state->period)
++ dev_warn(pwmchip_parent(chip),
++ ".apply didn't pick the best available period (requested: %llu, applied: %llu, possible: %llu)\n",
++ state->period, s2.period, last->period);
+
+- if (ops->request) {
+- err = ops->request(chip, pwm);
+- if (err) {
+- module_put(chip->owner);
+- return err;
+- }
+- }
++ if (state->enabled && state->period < s2.period)
++ dev_warn(pwmchip_parent(chip),
++ ".apply is supposed to round down period (requested: %llu, applied: %llu)\n",
++ state->period, s2.period);
+
+- if (ops->get_state) {
+- /*
+- * Zero-initialize state because most drivers are unaware of
+- * .usage_power. The other members of state are supposed to be
+- * set by lowlevel drivers. We still initialize the whole
+- * structure for simplicity even though this might paper over
+- * faulty implementations of .get_state().
+- */
+- struct pwm_state state = { 0, };
++ if (state->enabled &&
++ last->polarity == state->polarity &&
++ last->period == s2.period &&
++ last->duty_cycle > s2.duty_cycle &&
++ last->duty_cycle <= state->duty_cycle)
++ dev_warn(pwmchip_parent(chip),
++ ".apply didn't pick the best available duty cycle (requested: %llu/%llu, applied: %llu/%llu, possible: %llu/%llu)\n",
++ state->duty_cycle, state->period,
++ s2.duty_cycle, s2.period,
++ last->duty_cycle, last->period);
+
+- err = ops->get_state(chip, pwm, &state);
+- trace_pwm_get(pwm, &state, err);
++ if (state->enabled && state->duty_cycle < s2.duty_cycle)
++ dev_warn(pwmchip_parent(chip),
++ ".apply is supposed to round down duty_cycle (requested: %llu/%llu, applied: %llu/%llu)\n",
++ state->duty_cycle, state->period,
++ s2.duty_cycle, s2.period);
+
+- if (!err)
+- pwm->state = state;
++ if (!state->enabled && s2.enabled && s2.duty_cycle > 0)
++ dev_warn(pwmchip_parent(chip),
++ "requested disabled, but yielded enabled with duty > 0\n");
+
+- if (IS_ENABLED(CONFIG_PWM_DEBUG))
+- pwm->last = pwm->state;
++ /* reapply the state that the driver reported being configured. */
++ err = chip->ops->apply(chip, pwm, &s1);
++ trace_pwm_apply(pwm, &s1, err);
++ if (err) {
++ *last = s1;
++ dev_err(pwmchip_parent(chip), "failed to reapply current setting\n");
++ return;
+ }
+
+- set_bit(PWMF_REQUESTED, &pwm->flags);
+- pwm->label = label;
++ *last = (struct pwm_state){ 0 };
++ err = chip->ops->get_state(chip, pwm, last);
++ trace_pwm_get(pwm, last, err);
++ if (err)
++ return;
+
+- return 0;
++ /* reapplication of the current state should give an exact match */
++ if (s1.enabled != last->enabled ||
++ s1.polarity != last->polarity ||
++ (s1.enabled && s1.period != last->period) ||
++ (s1.enabled && s1.duty_cycle != last->duty_cycle)) {
++ dev_err(pwmchip_parent(chip),
++ ".apply is not idempotent (ena=%d pol=%d %llu/%llu) -> (ena=%d pol=%d %llu/%llu)\n",
++ s1.enabled, s1.polarity, s1.duty_cycle, s1.period,
++ last->enabled, last->polarity, last->duty_cycle,
++ last->period);
++ }
+ }
+
+-struct pwm_device *
+-of_pwm_xlate_with_flags(struct pwm_chip *chip, const struct of_phandle_args *args)
++/**
++ * __pwm_apply() - atomically apply a new state to a PWM device
++ * @pwm: PWM device
++ * @state: new state to apply
++ */
++static int __pwm_apply(struct pwm_device *pwm, const struct pwm_state *state)
+ {
+- struct pwm_device *pwm;
++ struct pwm_chip *chip;
++ int err;
+
+- if (chip->of_pwm_n_cells < 2)
+- return ERR_PTR(-EINVAL);
++ if (!pwm || !state || !state->period ||
++ state->duty_cycle > state->period)
++ return -EINVAL;
+
+- /* flags in the third cell are optional */
+- if (args->args_count < 2)
+- return ERR_PTR(-EINVAL);
++ chip = pwm->chip;
+
+- if (args->args[0] >= chip->npwm)
+- return ERR_PTR(-EINVAL);
++ if (state->period == pwm->state.period &&
++ state->duty_cycle == pwm->state.duty_cycle &&
++ state->polarity == pwm->state.polarity &&
++ state->enabled == pwm->state.enabled &&
++ state->usage_power == pwm->state.usage_power)
++ return 0;
+
+- pwm = pwm_request_from_chip(chip, args->args[0], NULL);
+- if (IS_ERR(pwm))
+- return pwm;
++ err = chip->ops->apply(chip, pwm, state);
++ trace_pwm_apply(pwm, state, err);
++ if (err)
++ return err;
+
+- pwm->args.period = args->args[1];
+- pwm->args.polarity = PWM_POLARITY_NORMAL;
++ pwm->state = *state;
+
+- if (chip->of_pwm_n_cells >= 3) {
+- if (args->args_count > 2 && args->args[2] & PWM_POLARITY_INVERTED)
+- pwm->args.polarity = PWM_POLARITY_INVERSED;
+- }
++ /*
++ * only do this after pwm->state was applied as some
++ * implementations of .get_state depend on this
++ */
++ pwm_apply_debug(pwm, state);
+
+- return pwm;
++ return 0;
+ }
+-EXPORT_SYMBOL_GPL(of_pwm_xlate_with_flags);
+
+-struct pwm_device *
+-of_pwm_single_xlate(struct pwm_chip *chip, const struct of_phandle_args *args)
++/**
++ * pwm_apply_might_sleep() - atomically apply a new state to a PWM device
++ * Cannot be used in atomic context.
++ * @pwm: PWM device
++ * @state: new state to apply
++ */
++int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state)
+ {
+- struct pwm_device *pwm;
+-
+- if (chip->of_pwm_n_cells < 1)
+- return ERR_PTR(-EINVAL);
++ int err;
+
+- /* validate that one cell is specified, optionally with flags */
+- if (args->args_count != 1 && args->args_count != 2)
+- return ERR_PTR(-EINVAL);
++ /*
++ * Some lowlevel driver's implementations of .apply() make use of
++ * mutexes, also with some drivers only returning when the new
++ * configuration is active calling pwm_apply_might_sleep() from atomic context
++ * is a bad idea. So make it explicit that calling this function might
++ * sleep.
++ */
++ might_sleep();
+
+- pwm = pwm_request_from_chip(chip, 0, NULL);
+- if (IS_ERR(pwm))
+- return pwm;
++ if (IS_ENABLED(CONFIG_PWM_DEBUG) && pwm->chip->atomic) {
++ /*
++ * Catch any drivers that have been marked as atomic but
++ * that will sleep anyway.
++ */
++ non_block_start();
++ err = __pwm_apply(pwm, state);
++ non_block_end();
++ } else {
++ err = __pwm_apply(pwm, state);
++ }
+
+- pwm->args.period = args->args[0];
+- pwm->args.polarity = PWM_POLARITY_NORMAL;
++ return err;
++}
++EXPORT_SYMBOL_GPL(pwm_apply_might_sleep);
+
+- if (args->args_count == 2 && args->args[1] & PWM_POLARITY_INVERTED)
+- pwm->args.polarity = PWM_POLARITY_INVERSED;
++/**
++ * pwm_apply_atomic() - apply a new state to a PWM device from atomic context
++ * Not all PWM devices support this function, check with pwm_might_sleep().
++ * @pwm: PWM device
++ * @state: new state to apply
++ */
++int pwm_apply_atomic(struct pwm_device *pwm, const struct pwm_state *state)
++{
++ WARN_ONCE(!pwm->chip->atomic,
++ "sleeping PWM driver used in atomic context\n");
+
+- return pwm;
++ return __pwm_apply(pwm, state);
+ }
+-EXPORT_SYMBOL_GPL(of_pwm_single_xlate);
++EXPORT_SYMBOL_GPL(pwm_apply_atomic);
+
+-static void of_pwmchip_add(struct pwm_chip *chip)
++/**
++ * pwm_adjust_config() - adjust the current PWM config to the PWM arguments
++ * @pwm: PWM device
++ *
++ * This function will adjust the PWM config to the PWM arguments provided
++ * by the DT or PWM lookup table. This is particularly useful to adapt
++ * the bootloader config to the Linux one.
++ */
++int pwm_adjust_config(struct pwm_device *pwm)
+ {
+- if (!chip->dev || !chip->dev->of_node)
+- return;
++ struct pwm_state state;
++ struct pwm_args pargs;
+
+- if (!chip->of_xlate) {
+- u32 pwm_cells;
++ pwm_get_args(pwm, &pargs);
++ pwm_get_state(pwm, &state);
+
+- if (of_property_read_u32(chip->dev->of_node, "#pwm-cells",
+- &pwm_cells))
+- pwm_cells = 2;
++ /*
++ * If the current period is zero it means that either the PWM driver
++ * does not support initial state retrieval or the PWM has not yet
++ * been configured.
++ *
++ * In either case, we setup the new period and polarity, and assign a
++ * duty cycle of 0.
++ */
++ if (!state.period) {
++ state.duty_cycle = 0;
++ state.period = pargs.period;
++ state.polarity = pargs.polarity;
+
+- chip->of_xlate = of_pwm_xlate_with_flags;
+- chip->of_pwm_n_cells = pwm_cells;
++ return pwm_apply_might_sleep(pwm, &state);
+ }
+
+- of_node_get(chip->dev->of_node);
+-}
+-
+-static void of_pwmchip_remove(struct pwm_chip *chip)
+-{
+- if (chip->dev)
+- of_node_put(chip->dev->of_node);
+-}
+-
+-static bool pwm_ops_check(const struct pwm_chip *chip)
+-{
+- const struct pwm_ops *ops = chip->ops;
+-
+- if (!ops->apply)
+- return false;
++ /*
++ * Adjust the PWM duty cycle/period based on the period value provided
++ * in PWM args.
++ */
++ if (pargs.period != state.period) {
++ u64 dutycycle = (u64)state.duty_cycle * pargs.period;
+
+- if (IS_ENABLED(CONFIG_PWM_DEBUG) && !ops->get_state)
+- dev_warn(chip->dev,
+- "Please implement the .get_state() callback\n");
++ do_div(dutycycle, state.period);
++ state.duty_cycle = dutycycle;
++ state.period = pargs.period;
++ }
+
+- return true;
++ /*
++ * If the polarity changed, we should also change the duty cycle.
++ */
++ if (pargs.polarity != state.polarity) {
++ state.polarity = pargs.polarity;
++ state.duty_cycle = state.period - state.duty_cycle;
++ }
++
++ return pwm_apply_might_sleep(pwm, &state);
+ }
++EXPORT_SYMBOL_GPL(pwm_adjust_config);
+
+ /**
+- * __pwmchip_add() - register a new PWM chip
+- * @chip: the PWM chip to add
+- * @owner: reference to the module providing the chip.
+- *
+- * Register a new PWM chip. @owner is supposed to be THIS_MODULE, use the
+- * pwmchip_add wrapper to do this right.
++ * pwm_capture() - capture and report a PWM signal
++ * @pwm: PWM device
++ * @result: structure to fill with capture result
++ * @timeout: time to wait, in milliseconds, before giving up on capture
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+-int __pwmchip_add(struct pwm_chip *chip, struct module *owner)
++int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
++ unsigned long timeout)
+ {
+- unsigned int i;
+- int ret;
++ int err;
+
+- if (!chip || !chip->dev || !chip->ops || !chip->npwm)
++ if (!pwm || !pwm->chip->ops)
+ return -EINVAL;
+
+- if (!pwm_ops_check(chip))
+- return -EINVAL;
++ if (!pwm->chip->ops->capture)
++ return -ENOSYS;
+
+- chip->owner = owner;
++ mutex_lock(&pwm_lock);
++ err = pwm->chip->ops->capture(pwm->chip, pwm, result, timeout);
++ mutex_unlock(&pwm_lock);
+
+- chip->pwms = kcalloc(chip->npwm, sizeof(*chip->pwms), GFP_KERNEL);
+- if (!chip->pwms)
+- return -ENOMEM;
++ return err;
++}
++EXPORT_SYMBOL_GPL(pwm_capture);
+
+- mutex_lock(&pwm_lock);
++static struct pwm_chip *pwmchip_find_by_name(const char *name)
++{
++ struct pwm_chip *chip;
++ unsigned long id, tmp;
+
+- ret = idr_alloc(&pwm_chips, chip, 0, 0, GFP_KERNEL);
+- if (ret < 0) {
+- mutex_unlock(&pwm_lock);
+- kfree(chip->pwms);
+- return ret;
+- }
++ if (!name)
++ return NULL;
+
+- chip->id = ret;
++ mutex_lock(&pwm_lock);
+
+- for (i = 0; i < chip->npwm; i++) {
+- struct pwm_device *pwm = &chip->pwms[i];
++ idr_for_each_entry_ul(&pwm_chips, chip, tmp, id) {
++ const char *chip_name = dev_name(pwmchip_parent(chip));
+
+- pwm->chip = chip;
+- pwm->hwpwm = i;
++ if (chip_name && strcmp(chip_name, name) == 0) {
++ mutex_unlock(&pwm_lock);
++ return chip;
++ }
+ }
+
+ mutex_unlock(&pwm_lock);
+
+- if (IS_ENABLED(CONFIG_OF))
+- of_pwmchip_add(chip);
+-
+- pwmchip_sysfs_export(chip);
+-
+- return 0;
++ return NULL;
+ }
+-EXPORT_SYMBOL_GPL(__pwmchip_add);
+
+-/**
+- * pwmchip_remove() - remove a PWM chip
+- * @chip: the PWM chip to remove
+- *
+- * Removes a PWM chip.
+- */
+-void pwmchip_remove(struct pwm_chip *chip)
++static int pwm_device_request(struct pwm_device *pwm, const char *label)
+ {
+- pwmchip_sysfs_unexport(chip);
+-
+- if (IS_ENABLED(CONFIG_OF))
+- of_pwmchip_remove(chip);
++ int err;
++ struct pwm_chip *chip = pwm->chip;
++ const struct pwm_ops *ops = chip->ops;
+
+- mutex_lock(&pwm_lock);
++ if (test_bit(PWMF_REQUESTED, &pwm->flags))
++ return -EBUSY;
+
+- idr_remove(&pwm_chips, chip->id);
++ if (!try_module_get(chip->owner))
++ return -ENODEV;
+
+- mutex_unlock(&pwm_lock);
++ if (ops->request) {
++ err = ops->request(chip, pwm);
++ if (err) {
++ module_put(chip->owner);
++ return err;
++ }
++ }
+
+- kfree(chip->pwms);
+-}
+-EXPORT_SYMBOL_GPL(pwmchip_remove);
++ if (ops->get_state) {
++ /*
++ * Zero-initialize state because most drivers are unaware of
++ * .usage_power. The other members of state are supposed to be
++ * set by lowlevel drivers. We still initialize the whole
++ * structure for simplicity even though this might paper over
++ * faulty implementations of .get_state().
++ */
++ struct pwm_state state = { 0, };
+
+-static void devm_pwmchip_remove(void *data)
+-{
+- struct pwm_chip *chip = data;
++ err = ops->get_state(chip, pwm, &state);
++ trace_pwm_get(pwm, &state, err);
+
+- pwmchip_remove(chip);
+-}
++ if (!err)
++ pwm->state = state;
+
+-int __devm_pwmchip_add(struct device *dev, struct pwm_chip *chip, struct module *owner)
+-{
+- int ret;
++ if (IS_ENABLED(CONFIG_PWM_DEBUG))
++ pwm->last = pwm->state;
++ }
+
+- ret = __pwmchip_add(chip, owner);
+- if (ret)
+- return ret;
++ set_bit(PWMF_REQUESTED, &pwm->flags);
++ pwm->label = label;
+
+- return devm_add_action_or_reset(dev, devm_pwmchip_remove, chip);
++ return 0;
+ }
+-EXPORT_SYMBOL_GPL(__devm_pwmchip_add);
+
+ /**
+ * pwm_request_from_chip() - request a PWM device relative to a PWM chip
+@@ -328,301 +409,179 @@ struct pwm_device *pwm_request_from_chip(struct pwm_chip *chip,
+ }
+ EXPORT_SYMBOL_GPL(pwm_request_from_chip);
+
+-static void pwm_apply_debug(struct pwm_device *pwm,
+- const struct pwm_state *state)
+-{
+- struct pwm_state *last = &pwm->last;
+- struct pwm_chip *chip = pwm->chip;
+- struct pwm_state s1 = { 0 }, s2 = { 0 };
+- int err;
+-
+- if (!IS_ENABLED(CONFIG_PWM_DEBUG))
+- return;
+-
+- /* No reasonable diagnosis possible without .get_state() */
+- if (!chip->ops->get_state)
+- return;
+-
+- /*
+- * *state was just applied. Read out the hardware state and do some
+- * checks.
+- */
+-
+- err = chip->ops->get_state(chip, pwm, &s1);
+- trace_pwm_get(pwm, &s1, err);
+- if (err)
+- /* If that failed there isn't much to debug */
+- return;
+-
+- /*
+- * The lowlevel driver either ignored .polarity (which is a bug) or as
+- * best effort inverted .polarity and fixed .duty_cycle respectively.
+- * Undo this inversion and fixup for further tests.
+- */
+- if (s1.enabled && s1.polarity != state->polarity) {
+- s2.polarity = state->polarity;
+- s2.duty_cycle = s1.period - s1.duty_cycle;
+- s2.period = s1.period;
+- s2.enabled = s1.enabled;
+- } else {
+- s2 = s1;
+- }
+-
+- if (s2.polarity != state->polarity &&
+- state->duty_cycle < state->period)
+- dev_warn(chip->dev, ".apply ignored .polarity\n");
+-
+- if (state->enabled &&
+- last->polarity == state->polarity &&
+- last->period > s2.period &&
+- last->period <= state->period)
+- dev_warn(chip->dev,
+- ".apply didn't pick the best available period (requested: %llu, applied: %llu, possible: %llu)\n",
+- state->period, s2.period, last->period);
+-
+- if (state->enabled && state->period < s2.period)
+- dev_warn(chip->dev,
+- ".apply is supposed to round down period (requested: %llu, applied: %llu)\n",
+- state->period, s2.period);
+-
+- if (state->enabled &&
+- last->polarity == state->polarity &&
+- last->period == s2.period &&
+- last->duty_cycle > s2.duty_cycle &&
+- last->duty_cycle <= state->duty_cycle)
+- dev_warn(chip->dev,
+- ".apply didn't pick the best available duty cycle (requested: %llu/%llu, applied: %llu/%llu, possible: %llu/%llu)\n",
+- state->duty_cycle, state->period,
+- s2.duty_cycle, s2.period,
+- last->duty_cycle, last->period);
+-
+- if (state->enabled && state->duty_cycle < s2.duty_cycle)
+- dev_warn(chip->dev,
+- ".apply is supposed to round down duty_cycle (requested: %llu/%llu, applied: %llu/%llu)\n",
+- state->duty_cycle, state->period,
+- s2.duty_cycle, s2.period);
+-
+- if (!state->enabled && s2.enabled && s2.duty_cycle > 0)
+- dev_warn(chip->dev,
+- "requested disabled, but yielded enabled with duty > 0\n");
+-
+- /* reapply the state that the driver reported being configured. */
+- err = chip->ops->apply(chip, pwm, &s1);
+- trace_pwm_apply(pwm, &s1, err);
+- if (err) {
+- *last = s1;
+- dev_err(chip->dev, "failed to reapply current setting\n");
+- return;
+- }
+-
+- *last = (struct pwm_state){ 0 };
+- err = chip->ops->get_state(chip, pwm, last);
+- trace_pwm_get(pwm, last, err);
+- if (err)
+- return;
+-
+- /* reapplication of the current state should give an exact match */
+- if (s1.enabled != last->enabled ||
+- s1.polarity != last->polarity ||
+- (s1.enabled && s1.period != last->period) ||
+- (s1.enabled && s1.duty_cycle != last->duty_cycle)) {
+- dev_err(chip->dev,
+- ".apply is not idempotent (ena=%d pol=%d %llu/%llu) -> (ena=%d pol=%d %llu/%llu)\n",
+- s1.enabled, s1.polarity, s1.duty_cycle, s1.period,
+- last->enabled, last->polarity, last->duty_cycle,
+- last->period);
+- }
+-}
+
+-/**
+- * __pwm_apply() - atomically apply a new state to a PWM device
+- * @pwm: PWM device
+- * @state: new state to apply
+- */
+-static int __pwm_apply(struct pwm_device *pwm, const struct pwm_state *state)
++struct pwm_device *
++of_pwm_xlate_with_flags(struct pwm_chip *chip, const struct of_phandle_args *args)
+ {
+- struct pwm_chip *chip;
+- int err;
++ struct pwm_device *pwm;
+
+- if (!pwm || !state || !state->period ||
+- state->duty_cycle > state->period)
+- return -EINVAL;
++ /* period in the second cell and flags in the third cell are optional */
++ if (args->args_count < 1)
++ return ERR_PTR(-EINVAL);
+
+- chip = pwm->chip;
++ pwm = pwm_request_from_chip(chip, args->args[0], NULL);
++ if (IS_ERR(pwm))
++ return pwm;
+
+- if (state->period == pwm->state.period &&
+- state->duty_cycle == pwm->state.duty_cycle &&
+- state->polarity == pwm->state.polarity &&
+- state->enabled == pwm->state.enabled &&
+- state->usage_power == pwm->state.usage_power)
+- return 0;
++ if (args->args_count > 1)
++ pwm->args.period = args->args[1];
+
+- err = chip->ops->apply(chip, pwm, state);
+- trace_pwm_apply(pwm, state, err);
+- if (err)
+- return err;
++ pwm->args.polarity = PWM_POLARITY_NORMAL;
++ if (args->args_count > 2 && args->args[2] & PWM_POLARITY_INVERTED)
++ pwm->args.polarity = PWM_POLARITY_INVERSED;
+
+- pwm->state = *state;
++ return pwm;
++}
++EXPORT_SYMBOL_GPL(of_pwm_xlate_with_flags);
+
+- /*
+- * only do this after pwm->state was applied as some
+- * implementations of .get_state depend on this
+- */
+- pwm_apply_debug(pwm, state);
++struct pwm_device *
++of_pwm_single_xlate(struct pwm_chip *chip, const struct of_phandle_args *args)
++{
++ struct pwm_device *pwm;
+
+- return 0;
++ pwm = pwm_request_from_chip(chip, 0, NULL);
++ if (IS_ERR(pwm))
++ return pwm;
++
++ if (args->args_count > 0)
++ pwm->args.period = args->args[0];
++
++ pwm->args.polarity = PWM_POLARITY_NORMAL;
++ if (args->args_count > 1 && args->args[1] & PWM_POLARITY_INVERTED)
++ pwm->args.polarity = PWM_POLARITY_INVERSED;
++
++ return pwm;
+ }
++EXPORT_SYMBOL_GPL(of_pwm_single_xlate);
+
+-/**
+- * pwm_apply_might_sleep() - atomically apply a new state to a PWM device
+- * Cannot be used in atomic context.
+- * @pwm: PWM device
+- * @state: new state to apply
+- */
+-int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state)
++static void of_pwmchip_add(struct pwm_chip *chip)
+ {
+- int err;
++ if (!pwmchip_parent(chip) || !pwmchip_parent(chip)->of_node)
++ return;
+
+- /*
+- * Some lowlevel driver's implementations of .apply() make use of
+- * mutexes, also with some drivers only returning when the new
+- * configuration is active calling pwm_apply_might_sleep() from atomic context
+- * is a bad idea. So make it explicit that calling this function might
+- * sleep.
+- */
+- might_sleep();
++ if (!chip->of_xlate)
++ chip->of_xlate = of_pwm_xlate_with_flags;
+
+- if (IS_ENABLED(CONFIG_PWM_DEBUG) && pwm->chip->atomic) {
+- /*
+- * Catch any drivers that have been marked as atomic but
+- * that will sleep anyway.
+- */
+- non_block_start();
+- err = __pwm_apply(pwm, state);
+- non_block_end();
+- } else {
+- err = __pwm_apply(pwm, state);
+- }
++ of_node_get(pwmchip_parent(chip)->of_node);
++}
+
+- return err;
++static void of_pwmchip_remove(struct pwm_chip *chip)
++{
++ if (pwmchip_parent(chip))
++ of_node_put(pwmchip_parent(chip)->of_node);
+ }
+-EXPORT_SYMBOL_GPL(pwm_apply_might_sleep);
+
+-/**
+- * pwm_apply_atomic() - apply a new state to a PWM device from atomic context
+- * Not all PWM devices support this function, check with pwm_might_sleep().
+- * @pwm: PWM device
+- * @state: new state to apply
+- */
+-int pwm_apply_atomic(struct pwm_device *pwm, const struct pwm_state *state)
++static bool pwm_ops_check(const struct pwm_chip *chip)
+ {
+- WARN_ONCE(!pwm->chip->atomic,
+- "sleeping PWM driver used in atomic context\n");
++ const struct pwm_ops *ops = chip->ops;
+
+- return __pwm_apply(pwm, state);
++ if (!ops->apply)
++ return false;
++
++ if (IS_ENABLED(CONFIG_PWM_DEBUG) && !ops->get_state)
++ dev_warn(pwmchip_parent(chip),
++ "Please implement the .get_state() callback\n");
++
++ return true;
+ }
+-EXPORT_SYMBOL_GPL(pwm_apply_atomic);
+
+ /**
+- * pwm_capture() - capture and report a PWM signal
+- * @pwm: PWM device
+- * @result: structure to fill with capture result
+- * @timeout: time to wait, in milliseconds, before giving up on capture
++ * __pwmchip_add() - register a new PWM chip
++ * @chip: the PWM chip to add
++ * @owner: reference to the module providing the chip.
++ *
++ * Register a new PWM chip. @owner is supposed to be THIS_MODULE, use the
++ * pwmchip_add wrapper to do this right.
+ *
+ * Returns: 0 on success or a negative error code on failure.
+ */
+-int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result,
+- unsigned long timeout)
++int __pwmchip_add(struct pwm_chip *chip, struct module *owner)
+ {
+- int err;
++ unsigned int i;
++ int ret;
+
+- if (!pwm || !pwm->chip->ops)
++ if (!chip || !pwmchip_parent(chip) || !chip->ops || !chip->npwm)
+ return -EINVAL;
+
+- if (!pwm->chip->ops->capture)
+- return -ENOSYS;
++ if (!pwm_ops_check(chip))
++ return -EINVAL;
++
++ chip->owner = owner;
++
++ chip->pwms = kcalloc(chip->npwm, sizeof(*chip->pwms), GFP_KERNEL);
++ if (!chip->pwms)
++ return -ENOMEM;
+
+ mutex_lock(&pwm_lock);
+- err = pwm->chip->ops->capture(pwm->chip, pwm, result, timeout);
++
++ ret = idr_alloc(&pwm_chips, chip, 0, 0, GFP_KERNEL);
++ if (ret < 0) {
++ mutex_unlock(&pwm_lock);
++ kfree(chip->pwms);
++ return ret;
++ }
++
++ chip->id = ret;
++
++ for (i = 0; i < chip->npwm; i++) {
++ struct pwm_device *pwm = &chip->pwms[i];
++
++ pwm->chip = chip;
++ pwm->hwpwm = i;
++ }
++
+ mutex_unlock(&pwm_lock);
+
+- return err;
++ if (IS_ENABLED(CONFIG_OF))
++ of_pwmchip_add(chip);
++
++ pwmchip_sysfs_export(chip);
++
++ return 0;
+ }
+-EXPORT_SYMBOL_GPL(pwm_capture);
++EXPORT_SYMBOL_GPL(__pwmchip_add);
+
+ /**
+- * pwm_adjust_config() - adjust the current PWM config to the PWM arguments
+- * @pwm: PWM device
++ * pwmchip_remove() - remove a PWM chip
++ * @chip: the PWM chip to remove
+ *
+- * This function will adjust the PWM config to the PWM arguments provided
+- * by the DT or PWM lookup table. This is particularly useful to adapt
+- * the bootloader config to the Linux one.
++ * Removes a PWM chip.
+ */
+-int pwm_adjust_config(struct pwm_device *pwm)
++void pwmchip_remove(struct pwm_chip *chip)
+ {
+- struct pwm_state state;
+- struct pwm_args pargs;
+-
+- pwm_get_args(pwm, &pargs);
+- pwm_get_state(pwm, &state);
+-
+- /*
+- * If the current period is zero it means that either the PWM driver
+- * does not support initial state retrieval or the PWM has not yet
+- * been configured.
+- *
+- * In either case, we setup the new period and polarity, and assign a
+- * duty cycle of 0.
+- */
+- if (!state.period) {
+- state.duty_cycle = 0;
+- state.period = pargs.period;
+- state.polarity = pargs.polarity;
++ pwmchip_sysfs_unexport(chip);
+
+- return pwm_apply_might_sleep(pwm, &state);
+- }
++ if (IS_ENABLED(CONFIG_OF))
++ of_pwmchip_remove(chip);
+
+- /*
+- * Adjust the PWM duty cycle/period based on the period value provided
+- * in PWM args.
+- */
+- if (pargs.period != state.period) {
+- u64 dutycycle = (u64)state.duty_cycle * pargs.period;
++ mutex_lock(&pwm_lock);
+
+- do_div(dutycycle, state.period);
+- state.duty_cycle = dutycycle;
+- state.period = pargs.period;
+- }
++ idr_remove(&pwm_chips, chip->id);
+
+- /*
+- * If the polarity changed, we should also change the duty cycle.
+- */
+- if (pargs.polarity != state.polarity) {
+- state.polarity = pargs.polarity;
+- state.duty_cycle = state.period - state.duty_cycle;
+- }
++ mutex_unlock(&pwm_lock);
+
+- return pwm_apply_might_sleep(pwm, &state);
++ kfree(chip->pwms);
+ }
+-EXPORT_SYMBOL_GPL(pwm_adjust_config);
++EXPORT_SYMBOL_GPL(pwmchip_remove);
+
+-static struct pwm_chip *fwnode_to_pwmchip(struct fwnode_handle *fwnode)
++static void devm_pwmchip_remove(void *data)
+ {
+- struct pwm_chip *chip;
+- unsigned long id, tmp;
++ struct pwm_chip *chip = data;
+
+- mutex_lock(&pwm_lock);
++ pwmchip_remove(chip);
++}
+
+- idr_for_each_entry_ul(&pwm_chips, chip, tmp, id)
+- if (chip->dev && device_match_fwnode(chip->dev, fwnode)) {
+- mutex_unlock(&pwm_lock);
+- return chip;
+- }
++int __devm_pwmchip_add(struct device *dev, struct pwm_chip *chip, struct module *owner)
++{
++ int ret;
+
+- mutex_unlock(&pwm_lock);
++ ret = __pwmchip_add(chip, owner);
++ if (ret)
++ return ret;
+
+- return ERR_PTR(-EPROBE_DEFER);
++ return devm_add_action_or_reset(dev, devm_pwmchip_remove, chip);
+ }
++EXPORT_SYMBOL_GPL(__devm_pwmchip_add);
+
+ static struct device_link *pwm_device_link_add(struct device *dev,
+ struct pwm_device *pwm)
+@@ -635,21 +594,39 @@ static struct device_link *pwm_device_link_add(struct device *dev,
+ * impact the PM sequence ordering: the PWM supplier may get
+ * suspended before the consumer.
+ */
+- dev_warn(pwm->chip->dev,
++ dev_warn(pwmchip_parent(pwm->chip),
+ "No consumer device specified to create a link to\n");
+ return NULL;
+ }
+
+- dl = device_link_add(dev, pwm->chip->dev, DL_FLAG_AUTOREMOVE_CONSUMER);
++ dl = device_link_add(dev, pwmchip_parent(pwm->chip), DL_FLAG_AUTOREMOVE_CONSUMER);
+ if (!dl) {
+ dev_err(dev, "failed to create device link to %s\n",
+- dev_name(pwm->chip->dev));
++ dev_name(pwmchip_parent(pwm->chip)));
+ return ERR_PTR(-EINVAL);
+ }
+
+ return dl;
+ }
+
++static struct pwm_chip *fwnode_to_pwmchip(struct fwnode_handle *fwnode)
++{
++ struct pwm_chip *chip;
++ unsigned long id, tmp;
++
++ mutex_lock(&pwm_lock);
++
++ idr_for_each_entry_ul(&pwm_chips, chip, tmp, id)
++ if (pwmchip_parent(chip) && device_match_fwnode(pwmchip_parent(chip), fwnode)) {
++ mutex_unlock(&pwm_lock);
++ return chip;
++ }
++
++ mutex_unlock(&pwm_lock);
++
++ return ERR_PTR(-EPROBE_DEFER);
++}
++
+ /**
+ * of_pwm_get() - request a PWM via the PWM framework
+ * @dev: device for PWM consumer
+@@ -784,6 +761,9 @@ static struct pwm_device *acpi_pwm_get(const struct fwnode_handle *fwnode)
+ return pwm;
+ }
+
++static DEFINE_MUTEX(pwm_lookup_lock);
++static LIST_HEAD(pwm_lookup_list);
++
+ /**
+ * pwm_add_table() - register PWM device consumers
+ * @table: array of consumers to register
+@@ -1105,8 +1085,8 @@ static int pwm_seq_show(struct seq_file *s, void *v)
+
+ seq_printf(s, "%s%d: %s/%s, %d PWM device%s\n",
+ (char *)s->private, chip->id,
+- chip->dev->bus ? chip->dev->bus->name : "no-bus",
+- dev_name(chip->dev), chip->npwm,
++ pwmchip_parent(chip)->bus ? pwmchip_parent(chip)->bus->name : "no-bus",
++ dev_name(pwmchip_parent(chip)), chip->npwm,
+ (chip->npwm != 1) ? "s" : "");
+
+ pwm_dbg_show(chip, s);
+diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c
+index 42179b3f7ec39..06562d4bb9633 100644
+--- a/drivers/pwm/pwm-clps711x.c
++++ b/drivers/pwm/pwm-clps711x.c
+@@ -103,7 +103,6 @@ static int clps711x_pwm_probe(struct platform_device *pdev)
+ priv->chip.dev = &pdev->dev;
+ priv->chip.npwm = 2;
+ priv->chip.of_xlate = clps711x_pwm_xlate;
+- priv->chip.of_pwm_n_cells = 1;
+
+ spin_lock_init(&priv->lock);
+
+diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c
+index 5fe303b8656de..339cedf3a7b18 100644
+--- a/drivers/pwm/pwm-cros-ec.c
++++ b/drivers/pwm/pwm-cros-ec.c
+@@ -279,7 +279,6 @@ static int cros_ec_pwm_probe(struct platform_device *pdev)
+ chip->dev = dev;
+ chip->ops = &cros_ec_pwm_ops;
+ chip->of_xlate = cros_ec_pwm_xlate;
+- chip->of_pwm_n_cells = 1;
+
+ if (ec_pwm->use_pwm_type) {
+ chip->npwm = CROS_EC_PWM_DT_COUNT;
+diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
+index 2971bbf3b5e7c..52ac3277f4204 100644
+--- a/drivers/pwm/pwm-meson.c
++++ b/drivers/pwm/pwm-meson.c
+@@ -122,7 +122,7 @@ static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+ {
+ struct meson_pwm *meson = to_meson_pwm(chip);
+ struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
+- struct device *dev = chip->dev;
++ struct device *dev = pwmchip_parent(chip);
+ int err;
+
+ err = clk_prepare_enable(channel->clk);
+@@ -143,12 +143,13 @@ static void meson_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+ clk_disable_unprepare(channel->clk);
+ }
+
+-static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
++static int meson_pwm_calc(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+ {
++ struct meson_pwm *meson = to_meson_pwm(chip);
+ struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
+ unsigned int cnt, duty_cnt;
+- unsigned long fin_freq;
++ long fin_freq;
+ u64 duty, period, freq;
+
+ duty = state->duty_cycle;
+@@ -168,20 +169,21 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
+ freq = ULONG_MAX;
+
+ fin_freq = clk_round_rate(channel->clk, freq);
+- if (fin_freq == 0) {
+- dev_err(meson->chip.dev, "invalid source clock frequency\n");
+- return -EINVAL;
++ if (fin_freq <= 0) {
++ dev_err(pwmchip_parent(chip),
++ "invalid source clock frequency %llu\n", freq);
++ return fin_freq ? fin_freq : -EINVAL;
+ }
+
+- dev_dbg(meson->chip.dev, "fin_freq: %lu Hz\n", fin_freq);
++ dev_dbg(pwmchip_parent(chip), "fin_freq: %ld Hz\n", fin_freq);
+
+- cnt = div_u64(fin_freq * period, NSEC_PER_SEC);
++ cnt = mul_u64_u64_div_u64(fin_freq, period, NSEC_PER_SEC);
+ if (cnt > 0xffff) {
+- dev_err(meson->chip.dev, "unable to get period cnt\n");
++ dev_err(pwmchip_parent(chip), "unable to get period cnt\n");
+ return -EINVAL;
+ }
+
+- dev_dbg(meson->chip.dev, "period=%llu cnt=%u\n", period, cnt);
++ dev_dbg(pwmchip_parent(chip), "period=%llu cnt=%u\n", period, cnt);
+
+ if (duty == period) {
+ channel->hi = cnt;
+@@ -190,9 +192,9 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
+ channel->hi = 0;
+ channel->lo = cnt;
+ } else {
+- duty_cnt = div_u64(fin_freq * duty, NSEC_PER_SEC);
++ duty_cnt = mul_u64_u64_div_u64(fin_freq, duty, NSEC_PER_SEC);
+
+- dev_dbg(meson->chip.dev, "duty=%llu duty_cnt=%u\n", duty, duty_cnt);
++ dev_dbg(pwmchip_parent(chip), "duty=%llu duty_cnt=%u\n", duty, duty_cnt);
+
+ channel->hi = duty_cnt;
+ channel->lo = cnt - duty_cnt;
+@@ -203,8 +205,9 @@ static int meson_pwm_calc(struct meson_pwm *meson, struct pwm_device *pwm,
+ return 0;
+ }
+
+-static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm)
++static void meson_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+ {
++ struct meson_pwm *meson = to_meson_pwm(chip);
+ struct meson_pwm_channel *channel = &meson->channels[pwm->hwpwm];
+ struct meson_pwm_channel_data *channel_data;
+ unsigned long flags;
+@@ -215,7 +218,7 @@ static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm)
+
+ err = clk_set_rate(channel->clk, channel->rate);
+ if (err)
+- dev_err(meson->chip.dev, "setting clock rate failed\n");
++ dev_err(pwmchip_parent(chip), "setting clock rate failed\n");
+
+ spin_lock_irqsave(&meson->lock, flags);
+
+@@ -230,8 +233,9 @@ static void meson_pwm_enable(struct meson_pwm *meson, struct pwm_device *pwm)
+ spin_unlock_irqrestore(&meson->lock, flags);
+ }
+
+-static void meson_pwm_disable(struct meson_pwm *meson, struct pwm_device *pwm)
++static void meson_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+ {
++ struct meson_pwm *meson = to_meson_pwm(chip);
+ unsigned long flags;
+ u32 value;
+
+@@ -269,16 +273,16 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ channel->hi = ~0;
+ channel->lo = 0;
+
+- meson_pwm_enable(meson, pwm);
++ meson_pwm_enable(chip, pwm);
+ } else {
+- meson_pwm_disable(meson, pwm);
++ meson_pwm_disable(chip, pwm);
+ }
+ } else {
+- err = meson_pwm_calc(meson, pwm, state);
++ err = meson_pwm_calc(chip, pwm, state);
+ if (err < 0)
+ return err;
+
+- meson_pwm_enable(meson, pwm);
++ meson_pwm_enable(chip, pwm);
+ }
+
+ return 0;
+@@ -432,10 +436,11 @@ static const struct of_device_id meson_pwm_matches[] = {
+ };
+ MODULE_DEVICE_TABLE(of, meson_pwm_matches);
+
+-static int meson_pwm_init_channels(struct meson_pwm *meson)
++static int meson_pwm_init_channels(struct pwm_chip *chip)
+ {
++ struct meson_pwm *meson = to_meson_pwm(chip);
+ struct clk_parent_data mux_parent_data[MESON_MAX_MUX_PARENTS] = {};
+- struct device *dev = meson->chip.dev;
++ struct device *dev = pwmchip_parent(chip);
+ unsigned int i;
+ char name[255];
+ int err;
+@@ -445,7 +450,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson)
+ mux_parent_data[i].name = meson->data->parent_names[i];
+ }
+
+- for (i = 0; i < meson->chip.npwm; i++) {
++ for (i = 0; i < chip->npwm; i++) {
+ struct meson_pwm_channel *channel = &meson->channels[i];
+ struct clk_parent_data div_parent = {}, gate_parent = {};
+ struct clk_init_data init = {};
+@@ -543,7 +548,7 @@ static int meson_pwm_probe(struct platform_device *pdev)
+
+ meson->data = of_device_get_match_data(&pdev->dev);
+
+- err = meson_pwm_init_channels(meson);
++ err = meson_pwm_init_channels(&meson->chip);
+ if (err < 0)
+ return err;
+
+diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
+index 76685f926c758..61b74fa1d3481 100644
+--- a/drivers/pwm/pwm-pxa.c
++++ b/drivers/pwm/pwm-pxa.c
+@@ -180,10 +180,8 @@ static int pwm_probe(struct platform_device *pdev)
+ pc->chip.ops = &pxa_pwm_ops;
+ pc->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1;
+
+- if (IS_ENABLED(CONFIG_OF)) {
++ if (IS_ENABLED(CONFIG_OF))
+ pc->chip.of_xlate = of_pwm_single_xlate;
+- pc->chip.of_pwm_n_cells = 1;
+- }
+
+ pc->mmio_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pc->mmio_base))
+diff --git a/drivers/pwm/pwm-sti.c b/drivers/pwm/pwm-sti.c
+index 69b1113c6b821..f3df7b1895d35 100644
+--- a/drivers/pwm/pwm-sti.c
++++ b/drivers/pwm/pwm-sti.c
+@@ -570,6 +570,7 @@ static int sti_pwm_probe(struct platform_device *pdev)
+ {
+ struct device *dev = &pdev->dev;
+ struct sti_pwm_compat_data *cdata;
++ struct pwm_chip *chip;
+ struct sti_pwm_chip *pc;
+ unsigned int i;
+ int irq, ret;
+@@ -577,6 +578,7 @@ static int sti_pwm_probe(struct platform_device *pdev)
+ pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
+ if (!pc)
+ return -ENOMEM;
++ chip = &pc->chip;
+
+ cdata = devm_kzalloc(dev, sizeof(*cdata), GFP_KERNEL);
+ if (!cdata)
+@@ -622,40 +624,28 @@ static int sti_pwm_probe(struct platform_device *pdev)
+ return ret;
+
+ if (cdata->pwm_num_devs) {
+- pc->pwm_clk = of_clk_get_by_name(dev->of_node, "pwm");
++ pc->pwm_clk = devm_clk_get_prepared(dev, "pwm");
+ if (IS_ERR(pc->pwm_clk)) {
+ dev_err(dev, "failed to get PWM clock\n");
+ return PTR_ERR(pc->pwm_clk);
+ }
+-
+- ret = clk_prepare(pc->pwm_clk);
+- if (ret) {
+- dev_err(dev, "failed to prepare clock\n");
+- return ret;
+- }
+ }
+
+ if (cdata->cpt_num_devs) {
+- pc->cpt_clk = of_clk_get_by_name(dev->of_node, "capture");
++ pc->cpt_clk = devm_clk_get_prepared(dev, "capture");
+ if (IS_ERR(pc->cpt_clk)) {
+ dev_err(dev, "failed to get PWM capture clock\n");
+ return PTR_ERR(pc->cpt_clk);
+ }
+
+- ret = clk_prepare(pc->cpt_clk);
+- if (ret) {
+- dev_err(dev, "failed to prepare clock\n");
+- return ret;
+- }
+-
+ cdata->ddata = devm_kzalloc(dev, cdata->cpt_num_devs * sizeof(*cdata->ddata), GFP_KERNEL);
+ if (!cdata->ddata)
+ return -ENOMEM;
+ }
+
+- pc->chip.dev = dev;
+- pc->chip.ops = &sti_pwm_ops;
+- pc->chip.npwm = max(cdata->pwm_num_devs, cdata->cpt_num_devs);
++ chip->dev = dev;
++ chip->ops = &sti_pwm_ops;
++ chip->npwm = max(cdata->pwm_num_devs, cdata->cpt_num_devs);
+
+ for (i = 0; i < cdata->cpt_num_devs; i++) {
+ struct sti_cpt_ddata *ddata = &cdata->ddata[i];
+@@ -664,26 +654,7 @@ static int sti_pwm_probe(struct platform_device *pdev)
+ mutex_init(&ddata->lock);
+ }
+
+- ret = pwmchip_add(&pc->chip);
+- if (ret < 0) {
+- clk_unprepare(pc->pwm_clk);
+- clk_unprepare(pc->cpt_clk);
+- return ret;
+- }
+-
+- platform_set_drvdata(pdev, pc);
+-
+- return 0;
+-}
+-
+-static void sti_pwm_remove(struct platform_device *pdev)
+-{
+- struct sti_pwm_chip *pc = platform_get_drvdata(pdev);
+-
+- pwmchip_remove(&pc->chip);
+-
+- clk_unprepare(pc->pwm_clk);
+- clk_unprepare(pc->cpt_clk);
++ return devm_pwmchip_add(dev, chip);
+ }
+
+ static const struct of_device_id sti_pwm_of_match[] = {
+@@ -698,7 +669,6 @@ static struct platform_driver sti_pwm_driver = {
+ .of_match_table = sti_pwm_of_match,
+ },
+ .probe = sti_pwm_probe,
+- .remove_new = sti_pwm_remove,
+ };
+ module_platform_driver(sti_pwm_driver);
+
+diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
+index 1698609d91c8a..3f434a771fb52 100644
+--- a/drivers/pwm/sysfs.c
++++ b/drivers/pwm/sysfs.c
+@@ -509,10 +509,10 @@ void pwmchip_sysfs_export(struct pwm_chip *chip)
+ * If device_create() fails the pwm_chip is still usable by
+ * the kernel it's just not exported.
+ */
+- parent = device_create(&pwm_class, chip->dev, MKDEV(0, 0), chip,
++ parent = device_create(&pwm_class, pwmchip_parent(chip), MKDEV(0, 0), chip,
+ "pwmchip%d", chip->id);
+ if (IS_ERR(parent)) {
+- dev_warn(chip->dev,
++ dev_warn(pwmchip_parent(chip),
+ "device_create failed for pwm_chip sysfs export\n");
+ }
+ }
+diff --git a/drivers/regulator/irq_helpers.c b/drivers/regulator/irq_helpers.c
+index fe7ae0f3f46af..5ab1a0befe12f 100644
+--- a/drivers/regulator/irq_helpers.c
++++ b/drivers/regulator/irq_helpers.c
+@@ -352,6 +352,9 @@ void *regulator_irq_helper(struct device *dev,
+
+ h->irq = irq;
+ h->desc = *d;
++ h->desc.name = devm_kstrdup(dev, d->name, GFP_KERNEL);
++ if (!h->desc.name)
++ return ERR_PTR(-ENOMEM);
+
+ ret = init_rdev_state(dev, h, rdev, common_errs, per_rdev_errs,
+ rdev_amount);
+diff --git a/drivers/regulator/qcom-refgen-regulator.c b/drivers/regulator/qcom-refgen-regulator.c
+index 656fe330d38f0..063e12c08e75f 100644
+--- a/drivers/regulator/qcom-refgen-regulator.c
++++ b/drivers/regulator/qcom-refgen-regulator.c
+@@ -140,6 +140,7 @@ static const struct of_device_id qcom_refgen_match_table[] = {
+ { .compatible = "qcom,sm8250-refgen-regulator", .data = &sm8250_refgen_desc },
+ { }
+ };
++MODULE_DEVICE_TABLE(of, qcom_refgen_match_table);
+
+ static struct platform_driver qcom_refgen_driver = {
+ .probe = qcom_refgen_probe,
+diff --git a/drivers/regulator/vqmmc-ipq4019-regulator.c b/drivers/regulator/vqmmc-ipq4019-regulator.c
+index 086da36abc0b4..4955616517ce9 100644
+--- a/drivers/regulator/vqmmc-ipq4019-regulator.c
++++ b/drivers/regulator/vqmmc-ipq4019-regulator.c
+@@ -84,6 +84,7 @@ static const struct of_device_id regulator_ipq4019_of_match[] = {
+ { .compatible = "qcom,vqmmc-ipq4019-regulator", },
+ {},
+ };
++MODULE_DEVICE_TABLE(of, regulator_ipq4019_of_match);
+
+ static struct platform_driver ipq4019_regulator_driver = {
+ .probe = ipq4019_regulator_probe,
+diff --git a/drivers/s390/cio/trace.h b/drivers/s390/cio/trace.h
+index 86993de253451..a4c5c6736b310 100644
+--- a/drivers/s390/cio/trace.h
++++ b/drivers/s390/cio/trace.h
+@@ -50,7 +50,7 @@ DECLARE_EVENT_CLASS(s390_class_schib,
+ __entry->devno = schib->pmcw.dev;
+ __entry->schib = *schib;
+ __entry->pmcw_ena = schib->pmcw.ena;
+- __entry->pmcw_st = schib->pmcw.ena;
++ __entry->pmcw_st = schib->pmcw.st;
+ __entry->pmcw_dnv = schib->pmcw.dnv;
+ __entry->pmcw_dev = schib->pmcw.dev;
+ __entry->pmcw_lpm = schib->pmcw.lpm;
+diff --git a/drivers/scsi/bfa/bfad_debugfs.c b/drivers/scsi/bfa/bfad_debugfs.c
+index 52db147d9979d..f6dd077d47c9a 100644
+--- a/drivers/scsi/bfa/bfad_debugfs.c
++++ b/drivers/scsi/bfa/bfad_debugfs.c
+@@ -250,7 +250,7 @@ bfad_debugfs_write_regrd(struct file *file, const char __user *buf,
+ unsigned long flags;
+ void *kern_buf;
+
+- kern_buf = memdup_user(buf, nbytes);
++ kern_buf = memdup_user_nul(buf, nbytes);
+ if (IS_ERR(kern_buf))
+ return PTR_ERR(kern_buf);
+
+@@ -317,7 +317,7 @@ bfad_debugfs_write_regwr(struct file *file, const char __user *buf,
+ unsigned long flags;
+ void *kern_buf;
+
+- kern_buf = memdup_user(buf, nbytes);
++ kern_buf = memdup_user_nul(buf, nbytes);
+ if (IS_ERR(kern_buf))
+ return PTR_ERR(kern_buf);
+
+diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
+index af18d20f30794..49c57a9c110b5 100644
+--- a/drivers/scsi/hpsa.c
++++ b/drivers/scsi/hpsa.c
+@@ -5850,7 +5850,7 @@ static int hpsa_scsi_host_alloc(struct ctlr_info *h)
+ {
+ struct Scsi_Host *sh;
+
+- sh = scsi_host_alloc(&hpsa_driver_template, sizeof(struct ctlr_info));
++ sh = scsi_host_alloc(&hpsa_driver_template, sizeof(struct ctlr_info *));
+ if (sh == NULL) {
+ dev_err(&h->pdev->dev, "scsi_host_alloc failed\n");
+ return -ENOMEM;
+diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
+index f6e6db8b8aba9..e97f4e01a865a 100644
+--- a/drivers/scsi/libsas/sas_expander.c
++++ b/drivers/scsi/libsas/sas_expander.c
+@@ -239,8 +239,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
+ /* help some expanders that fail to zero sas_address in the 'no
+ * device' case
+ */
+- if (phy->attached_dev_type == SAS_PHY_UNUSED ||
+- phy->linkrate < SAS_LINK_RATE_1_5_GBPS)
++ if (phy->attached_dev_type == SAS_PHY_UNUSED)
+ memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
+ else
+ memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE);
+diff --git a/drivers/scsi/qedf/qedf_debugfs.c b/drivers/scsi/qedf/qedf_debugfs.c
+index 451fd236bfd05..96174353e3898 100644
+--- a/drivers/scsi/qedf/qedf_debugfs.c
++++ b/drivers/scsi/qedf/qedf_debugfs.c
+@@ -170,7 +170,7 @@ qedf_dbg_debug_cmd_write(struct file *filp, const char __user *buffer,
+ if (!count || *ppos)
+ return 0;
+
+- kern_buf = memdup_user(buffer, count);
++ kern_buf = memdup_user_nul(buffer, count);
+ if (IS_ERR(kern_buf))
+ return PTR_ERR(kern_buf);
+
+diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
+index 55ff3d7482b3e..a1545dad0c0ce 100644
+--- a/drivers/scsi/qla2xxx/qla_dfs.c
++++ b/drivers/scsi/qla2xxx/qla_dfs.c
+@@ -274,7 +274,7 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused)
+ seq_printf(s, "Driver: estimate iocb used [%d] high water limit [%d]\n",
+ iocbs_used, ha->base_qpair->fwres.iocbs_limit);
+
+- seq_printf(s, "estimate exchange used[%d] high water limit [%d] n",
++ seq_printf(s, "estimate exchange used[%d] high water limit [%d]\n",
+ exch_used, ha->base_qpair->fwres.exch_limit);
+
+ if (ql2xenforce_iocb_limit == 2) {
+diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c
+index b0cd071c4719b..0b2e5690dacfa 100644
+--- a/drivers/soc/mediatek/mtk-cmdq-helper.c
++++ b/drivers/soc/mediatek/mtk-cmdq-helper.c
+@@ -14,7 +14,8 @@
+ #define CMDQ_POLL_ENABLE_MASK BIT(0)
+ #define CMDQ_EOC_IRQ_EN BIT(0)
+ #define CMDQ_REG_TYPE 1
+-#define CMDQ_JUMP_RELATIVE 1
++#define CMDQ_JUMP_RELATIVE 0
++#define CMDQ_JUMP_ABSOLUTE 1
+
+ struct cmdq_instruction {
+ union {
+@@ -397,7 +398,7 @@ int cmdq_pkt_jump(struct cmdq_pkt *pkt, dma_addr_t addr)
+ struct cmdq_instruction inst = {};
+
+ inst.op = CMDQ_CODE_JUMP;
+- inst.offset = CMDQ_JUMP_RELATIVE;
++ inst.offset = CMDQ_JUMP_ABSOLUTE;
+ inst.value = addr >>
+ cmdq_get_shift_pa(((struct cmdq_client *)pkt->cl)->chan);
+ return cmdq_pkt_append_command(pkt, inst);
+diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c
+index f913e9bd57ed4..823fd108fa039 100644
+--- a/drivers/soc/qcom/pmic_glink.c
++++ b/drivers/soc/qcom/pmic_glink.c
+@@ -11,6 +11,7 @@
+ #include <linux/slab.h>
+ #include <linux/soc/qcom/pdr.h>
+ #include <linux/soc/qcom/pmic_glink.h>
++#include <linux/spinlock.h>
+
+ enum {
+ PMIC_GLINK_CLIENT_BATT = 0,
+@@ -36,7 +37,7 @@ struct pmic_glink {
+ unsigned int pdr_state;
+
+ /* serializing clients list updates */
+- struct mutex client_lock;
++ spinlock_t client_lock;
+ struct list_head clients;
+ };
+
+@@ -58,10 +59,11 @@ static void _devm_pmic_glink_release_client(struct device *dev, void *res)
+ {
+ struct pmic_glink_client *client = (struct pmic_glink_client *)res;
+ struct pmic_glink *pg = client->pg;
++ unsigned long flags;
+
+- mutex_lock(&pg->client_lock);
++ spin_lock_irqsave(&pg->client_lock, flags);
+ list_del(&client->node);
+- mutex_unlock(&pg->client_lock);
++ spin_unlock_irqrestore(&pg->client_lock, flags);
+ }
+
+ struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev,
+@@ -72,6 +74,7 @@ struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev,
+ {
+ struct pmic_glink_client *client;
+ struct pmic_glink *pg = dev_get_drvdata(dev->parent);
++ unsigned long flags;
+
+ client = devres_alloc(_devm_pmic_glink_release_client, sizeof(*client), GFP_KERNEL);
+ if (!client)
+@@ -83,9 +86,14 @@ struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev,
+ client->pdr_notify = pdr;
+ client->priv = priv;
+
+- mutex_lock(&pg->client_lock);
++ mutex_lock(&pg->state_lock);
++ spin_lock_irqsave(&pg->client_lock, flags);
++
+ list_add(&client->node, &pg->clients);
+- mutex_unlock(&pg->client_lock);
++ client->pdr_notify(client->priv, pg->client_state);
++
++ spin_unlock_irqrestore(&pg->client_lock, flags);
++ mutex_unlock(&pg->state_lock);
+
+ devres_add(dev, client);
+
+@@ -107,6 +115,7 @@ static int pmic_glink_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
+ struct pmic_glink_client *client;
+ struct pmic_glink_hdr *hdr;
+ struct pmic_glink *pg = dev_get_drvdata(&rpdev->dev);
++ unsigned long flags;
+
+ if (len < sizeof(*hdr)) {
+ dev_warn(pg->dev, "ignoring truncated message\n");
+@@ -115,10 +124,12 @@ static int pmic_glink_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
+
+ hdr = data;
+
++ spin_lock_irqsave(&pg->client_lock, flags);
+ list_for_each_entry(client, &pg->clients, node) {
+ if (client->id == le32_to_cpu(hdr->owner))
+ client->cb(data, len, client->priv);
+ }
++ spin_unlock_irqrestore(&pg->client_lock, flags);
+
+ return 0;
+ }
+@@ -158,6 +169,7 @@ static void pmic_glink_state_notify_clients(struct pmic_glink *pg)
+ {
+ struct pmic_glink_client *client;
+ unsigned int new_state = pg->client_state;
++ unsigned long flags;
+
+ if (pg->client_state != SERVREG_SERVICE_STATE_UP) {
+ if (pg->pdr_state == SERVREG_SERVICE_STATE_UP && pg->ept)
+@@ -168,8 +180,10 @@ static void pmic_glink_state_notify_clients(struct pmic_glink *pg)
+ }
+
+ if (new_state != pg->client_state) {
++ spin_lock_irqsave(&pg->client_lock, flags);
+ list_for_each_entry(client, &pg->clients, node)
+ client->pdr_notify(client->priv, new_state);
++ spin_unlock_irqrestore(&pg->client_lock, flags);
+ pg->client_state = new_state;
+ }
+ }
+@@ -256,7 +270,7 @@ static int pmic_glink_probe(struct platform_device *pdev)
+ pg->dev = &pdev->dev;
+
+ INIT_LIST_HEAD(&pg->clients);
+- mutex_init(&pg->client_lock);
++ spin_lock_init(&pg->client_lock);
+ mutex_init(&pg->state_lock);
+
+ match_data = (unsigned long *)of_device_get_match_data(&pdev->dev);
+diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c
+index f35c90809414c..638f08b3f21be 100644
+--- a/drivers/staging/media/atomisp/pci/sh_css.c
++++ b/drivers/staging/media/atomisp/pci/sh_css.c
+@@ -4719,6 +4719,7 @@ static int load_video_binaries(struct ia_css_pipe *pipe)
+ sizeof(struct ia_css_binary),
+ GFP_KERNEL);
+ if (!mycs->yuv_scaler_binary) {
++ mycs->num_yuv_scaler = 0;
+ err = -ENOMEM;
+ return err;
+ }
+diff --git a/drivers/staging/media/starfive/camss/stf-camss.c b/drivers/staging/media/starfive/camss/stf-camss.c
+index a587f860101ae..323aa70fdeaf1 100644
+--- a/drivers/staging/media/starfive/camss/stf-camss.c
++++ b/drivers/staging/media/starfive/camss/stf-camss.c
+@@ -162,6 +162,12 @@ static int stfcamss_register_devs(struct stfcamss *stfcamss)
+
+ static void stfcamss_unregister_devs(struct stfcamss *stfcamss)
+ {
++ struct stf_capture *cap_yuv = &stfcamss->captures[STF_CAPTURE_YUV];
++ struct stf_isp_dev *isp_dev = &stfcamss->isp_dev;
++
++ media_entity_remove_links(&isp_dev->subdev.entity);
++ media_entity_remove_links(&cap_yuv->video.vdev.entity);
++
+ stf_isp_unregister(&stfcamss->isp_dev);
+ stf_capture_unregister(stfcamss);
+ }
+diff --git a/drivers/thermal/mediatek/lvts_thermal.c b/drivers/thermal/mediatek/lvts_thermal.c
+index fd4bd650c77a6..4e5c213a89225 100644
+--- a/drivers/thermal/mediatek/lvts_thermal.c
++++ b/drivers/thermal/mediatek/lvts_thermal.c
+@@ -1530,11 +1530,15 @@ static const struct lvts_data mt7988_lvts_ap_data = {
+ static const struct lvts_data mt8192_lvts_mcu_data = {
+ .lvts_ctrl = mt8192_lvts_mcu_data_ctrl,
+ .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_mcu_data_ctrl),
++ .temp_factor = LVTS_COEFF_A_MT8195,
++ .temp_offset = LVTS_COEFF_B_MT8195,
+ };
+
+ static const struct lvts_data mt8192_lvts_ap_data = {
+ .lvts_ctrl = mt8192_lvts_ap_data_ctrl,
+ .num_lvts_ctrl = ARRAY_SIZE(mt8192_lvts_ap_data_ctrl),
++ .temp_factor = LVTS_COEFF_A_MT8195,
++ .temp_offset = LVTS_COEFF_B_MT8195,
+ };
+
+ static const struct lvts_data mt8195_lvts_mcu_data = {
+diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
+index 6d7c16ccb44dc..4edee8d929a75 100644
+--- a/drivers/thermal/qcom/tsens.c
++++ b/drivers/thermal/qcom/tsens.c
+@@ -264,7 +264,7 @@ void compute_intercept_slope(struct tsens_priv *priv, u32 *p1,
+ for (i = 0; i < priv->num_sensors; i++) {
+ dev_dbg(priv->dev,
+ "%s: sensor%d - data_point1:%#x data_point2:%#x\n",
+- __func__, i, p1[i], p2[i]);
++ __func__, i, p1[i], p2 ? p2[i] : 0);
+
+ if (!priv->sensor[i].slope)
+ priv->sensor[i].slope = SLOPE_DEFAULT;
+diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
+index dfaa6341694a0..5975bf380826d 100644
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -432,7 +432,6 @@ static void update_temperature(struct thermal_zone_device *tz)
+ trace_thermal_temperature(tz);
+
+ thermal_genl_sampling_temp(tz->id, temp);
+- thermal_debug_update_temp(tz);
+ }
+
+ static void thermal_zone_device_check(struct work_struct *work)
+@@ -476,6 +475,8 @@ void __thermal_zone_device_update(struct thermal_zone_device *tz,
+ for_each_trip(tz, trip)
+ handle_thermal_trip(tz, trip);
+
++ thermal_debug_update_temp(tz);
++
+ monitor_thermal_zone(tz);
+ }
+
+@@ -898,6 +899,7 @@ __thermal_cooling_device_register(struct device_node *np,
+ {
+ struct thermal_cooling_device *cdev;
+ struct thermal_zone_device *pos = NULL;
++ unsigned long current_state;
+ int id, ret;
+
+ if (!ops || !ops->get_max_state || !ops->get_cur_state ||
+@@ -935,6 +937,10 @@ __thermal_cooling_device_register(struct device_node *np,
+ if (ret)
+ goto out_cdev_type;
+
++ ret = cdev->ops->get_cur_state(cdev, ¤t_state);
++ if (ret)
++ goto out_cdev_type;
++
+ thermal_cooling_device_setup_sysfs(cdev);
+
+ ret = dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
+@@ -948,6 +954,8 @@ __thermal_cooling_device_register(struct device_node *np,
+ return ERR_PTR(ret);
+ }
+
++ thermal_debug_cdev_add(cdev, current_state);
++
+ /* Add 'this' new cdev to the global cdev list */
+ mutex_lock(&thermal_list_lock);
+
+@@ -963,8 +971,6 @@ __thermal_cooling_device_register(struct device_node *np,
+
+ mutex_unlock(&thermal_list_lock);
+
+- thermal_debug_cdev_add(cdev);
+-
+ return cdev;
+
+ out_cooling_dev:
+diff --git a/drivers/thermal/thermal_debugfs.c b/drivers/thermal/thermal_debugfs.c
+index 5693cc8b231aa..403f74d663dce 100644
+--- a/drivers/thermal/thermal_debugfs.c
++++ b/drivers/thermal/thermal_debugfs.c
+@@ -435,6 +435,14 @@ void thermal_debug_cdev_state_update(const struct thermal_cooling_device *cdev,
+ }
+
+ cdev_dbg->current_state = new_state;
++
++ /*
++ * Create a record for the new state if it is not there, so its
++ * duration will be printed by cdev_dt_seq_show() as expected if it
++ * runs before the next state transition.
++ */
++ thermal_debugfs_cdev_record_get(thermal_dbg, cdev_dbg->durations, new_state);
++
+ transition = (old_state << 16) | new_state;
+
+ /*
+@@ -460,8 +468,9 @@ void thermal_debug_cdev_state_update(const struct thermal_cooling_device *cdev,
+ * Allocates a cooling device object for debug, initializes the
+ * statistics and create the entries in sysfs.
+ * @cdev: a pointer to a cooling device
++ * @state: current state of the cooling device
+ */
+-void thermal_debug_cdev_add(struct thermal_cooling_device *cdev)
++void thermal_debug_cdev_add(struct thermal_cooling_device *cdev, int state)
+ {
+ struct thermal_debugfs *thermal_dbg;
+ struct cdev_debugfs *cdev_dbg;
+@@ -478,9 +487,16 @@ void thermal_debug_cdev_add(struct thermal_cooling_device *cdev)
+ INIT_LIST_HEAD(&cdev_dbg->durations[i]);
+ }
+
+- cdev_dbg->current_state = 0;
++ cdev_dbg->current_state = state;
+ cdev_dbg->timestamp = ktime_get();
+
++ /*
++ * Create a record for the initial cooling device state, so its
++ * duration will be printed by cdev_dt_seq_show() as expected if it
++ * runs before the first state transition.
++ */
++ thermal_debugfs_cdev_record_get(thermal_dbg, cdev_dbg->durations, state);
++
+ debugfs_create_file("trans_table", 0400, thermal_dbg->d_top,
+ thermal_dbg, &tt_fops);
+
+@@ -555,7 +571,6 @@ void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
+ struct tz_episode *tze;
+ struct tz_debugfs *tz_dbg;
+ struct thermal_debugfs *thermal_dbg = tz->debugfs;
+- int temperature = tz->temperature;
+ int trip_id = thermal_zone_trip_id(tz, trip);
+ ktime_t now = ktime_get();
+
+@@ -624,12 +639,6 @@ void thermal_debug_tz_trip_up(struct thermal_zone_device *tz,
+
+ tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node);
+ tze->trip_stats[trip_id].timestamp = now;
+- tze->trip_stats[trip_id].max = max(tze->trip_stats[trip_id].max, temperature);
+- tze->trip_stats[trip_id].min = min(tze->trip_stats[trip_id].min, temperature);
+- tze->trip_stats[trip_id].count++;
+- tze->trip_stats[trip_id].avg = tze->trip_stats[trip_id].avg +
+- (temperature - tze->trip_stats[trip_id].avg) /
+- tze->trip_stats[trip_id].count;
+
+ unlock:
+ mutex_unlock(&thermal_dbg->lock);
+diff --git a/drivers/thermal/thermal_debugfs.h b/drivers/thermal/thermal_debugfs.h
+index 155b9af5fe870..c28bd4c114124 100644
+--- a/drivers/thermal/thermal_debugfs.h
++++ b/drivers/thermal/thermal_debugfs.h
+@@ -2,7 +2,7 @@
+
+ #ifdef CONFIG_THERMAL_DEBUGFS
+ void thermal_debug_init(void);
+-void thermal_debug_cdev_add(struct thermal_cooling_device *cdev);
++void thermal_debug_cdev_add(struct thermal_cooling_device *cdev, int state);
+ void thermal_debug_cdev_remove(struct thermal_cooling_device *cdev);
+ void thermal_debug_cdev_state_update(const struct thermal_cooling_device *cdev, int state);
+ void thermal_debug_tz_add(struct thermal_zone_device *tz);
+@@ -14,7 +14,7 @@ void thermal_debug_tz_trip_down(struct thermal_zone_device *tz,
+ void thermal_debug_update_temp(struct thermal_zone_device *tz);
+ #else
+ static inline void thermal_debug_init(void) {}
+-static inline void thermal_debug_cdev_add(struct thermal_cooling_device *cdev) {}
++static inline void thermal_debug_cdev_add(struct thermal_cooling_device *cdev, int state) {}
+ static inline void thermal_debug_cdev_remove(struct thermal_cooling_device *cdev) {}
+ static inline void thermal_debug_cdev_state_update(const struct thermal_cooling_device *cdev,
+ int state) {}
+diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
+index 4036566febcba..afbf7837b53ec 100644
+--- a/drivers/tty/n_gsm.c
++++ b/drivers/tty/n_gsm.c
+@@ -245,16 +245,18 @@ enum gsm_encoding {
+
+ enum gsm_mux_state {
+ GSM_SEARCH,
+- GSM_START,
+- GSM_ADDRESS,
+- GSM_CONTROL,
+- GSM_LEN,
+- GSM_DATA,
+- GSM_FCS,
+- GSM_OVERRUN,
+- GSM_LEN0,
+- GSM_LEN1,
+- GSM_SSOF,
++ GSM0_ADDRESS,
++ GSM0_CONTROL,
++ GSM0_LEN0,
++ GSM0_LEN1,
++ GSM0_DATA,
++ GSM0_FCS,
++ GSM0_SSOF,
++ GSM1_START,
++ GSM1_ADDRESS,
++ GSM1_CONTROL,
++ GSM1_DATA,
++ GSM1_OVERRUN,
+ };
+
+ /*
+@@ -2847,6 +2849,30 @@ static void gsm_queue(struct gsm_mux *gsm)
+ return;
+ }
+
++/**
++ * gsm0_receive_state_check_and_fix - check and correct receive state
++ * @gsm: gsm data for this ldisc instance
++ *
++ * Ensures that the current receive state is valid for basic option mode.
++ */
++
++static void gsm0_receive_state_check_and_fix(struct gsm_mux *gsm)
++{
++ switch (gsm->state) {
++ case GSM_SEARCH:
++ case GSM0_ADDRESS:
++ case GSM0_CONTROL:
++ case GSM0_LEN0:
++ case GSM0_LEN1:
++ case GSM0_DATA:
++ case GSM0_FCS:
++ case GSM0_SSOF:
++ break;
++ default:
++ gsm->state = GSM_SEARCH;
++ break;
++ }
++}
+
+ /**
+ * gsm0_receive - perform processing for non-transparency
+@@ -2860,26 +2886,27 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c)
+ {
+ unsigned int len;
+
++ gsm0_receive_state_check_and_fix(gsm);
+ switch (gsm->state) {
+ case GSM_SEARCH: /* SOF marker */
+ if (c == GSM0_SOF) {
+- gsm->state = GSM_ADDRESS;
++ gsm->state = GSM0_ADDRESS;
+ gsm->address = 0;
+ gsm->len = 0;
+ gsm->fcs = INIT_FCS;
+ }
+ break;
+- case GSM_ADDRESS: /* Address EA */
++ case GSM0_ADDRESS: /* Address EA */
+ gsm->fcs = gsm_fcs_add(gsm->fcs, c);
+ if (gsm_read_ea(&gsm->address, c))
+- gsm->state = GSM_CONTROL;
++ gsm->state = GSM0_CONTROL;
+ break;
+- case GSM_CONTROL: /* Control Byte */
++ case GSM0_CONTROL: /* Control Byte */
+ gsm->fcs = gsm_fcs_add(gsm->fcs, c);
+ gsm->control = c;
+- gsm->state = GSM_LEN0;
++ gsm->state = GSM0_LEN0;
+ break;
+- case GSM_LEN0: /* Length EA */
++ case GSM0_LEN0: /* Length EA */
+ gsm->fcs = gsm_fcs_add(gsm->fcs, c);
+ if (gsm_read_ea(&gsm->len, c)) {
+ if (gsm->len > gsm->mru) {
+@@ -2889,14 +2916,14 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c)
+ }
+ gsm->count = 0;
+ if (!gsm->len)
+- gsm->state = GSM_FCS;
++ gsm->state = GSM0_FCS;
+ else
+- gsm->state = GSM_DATA;
++ gsm->state = GSM0_DATA;
+ break;
+ }
+- gsm->state = GSM_LEN1;
++ gsm->state = GSM0_LEN1;
+ break;
+- case GSM_LEN1:
++ case GSM0_LEN1:
+ gsm->fcs = gsm_fcs_add(gsm->fcs, c);
+ len = c;
+ gsm->len |= len << 7;
+@@ -2907,26 +2934,29 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c)
+ }
+ gsm->count = 0;
+ if (!gsm->len)
+- gsm->state = GSM_FCS;
++ gsm->state = GSM0_FCS;
+ else
+- gsm->state = GSM_DATA;
++ gsm->state = GSM0_DATA;
+ break;
+- case GSM_DATA: /* Data */
++ case GSM0_DATA: /* Data */
+ gsm->buf[gsm->count++] = c;
+- if (gsm->count == gsm->len) {
++ if (gsm->count >= MAX_MRU) {
++ gsm->bad_size++;
++ gsm->state = GSM_SEARCH;
++ } else if (gsm->count >= gsm->len) {
+ /* Calculate final FCS for UI frames over all data */
+ if ((gsm->control & ~PF) != UIH) {
+ gsm->fcs = gsm_fcs_add_block(gsm->fcs, gsm->buf,
+ gsm->count);
+ }
+- gsm->state = GSM_FCS;
++ gsm->state = GSM0_FCS;
+ }
+ break;
+- case GSM_FCS: /* FCS follows the packet */
++ case GSM0_FCS: /* FCS follows the packet */
+ gsm->fcs = gsm_fcs_add(gsm->fcs, c);
+- gsm->state = GSM_SSOF;
++ gsm->state = GSM0_SSOF;
+ break;
+- case GSM_SSOF:
++ case GSM0_SSOF:
+ gsm->state = GSM_SEARCH;
+ if (c == GSM0_SOF)
+ gsm_queue(gsm);
+@@ -2939,6 +2969,29 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c)
+ }
+ }
+
++/**
++ * gsm1_receive_state_check_and_fix - check and correct receive state
++ * @gsm: gsm data for this ldisc instance
++ *
++ * Ensures that the current receive state is valid for advanced option mode.
++ */
++
++static void gsm1_receive_state_check_and_fix(struct gsm_mux *gsm)
++{
++ switch (gsm->state) {
++ case GSM_SEARCH:
++ case GSM1_START:
++ case GSM1_ADDRESS:
++ case GSM1_CONTROL:
++ case GSM1_DATA:
++ case GSM1_OVERRUN:
++ break;
++ default:
++ gsm->state = GSM_SEARCH;
++ break;
++ }
++}
++
+ /**
+ * gsm1_receive - perform processing for non-transparency
+ * @gsm: gsm data for this ldisc instance
+@@ -2949,6 +3002,7 @@ static void gsm0_receive(struct gsm_mux *gsm, u8 c)
+
+ static void gsm1_receive(struct gsm_mux *gsm, u8 c)
+ {
++ gsm1_receive_state_check_and_fix(gsm);
+ /* handle XON/XOFF */
+ if ((c & ISO_IEC_646_MASK) == XON) {
+ gsm->constipated = true;
+@@ -2961,11 +3015,11 @@ static void gsm1_receive(struct gsm_mux *gsm, u8 c)
+ }
+ if (c == GSM1_SOF) {
+ /* EOF is only valid in frame if we have got to the data state */
+- if (gsm->state == GSM_DATA) {
++ if (gsm->state == GSM1_DATA) {
+ if (gsm->count < 1) {
+ /* Missing FSC */
+ gsm->malformed++;
+- gsm->state = GSM_START;
++ gsm->state = GSM1_START;
+ return;
+ }
+ /* Remove the FCS from data */
+@@ -2981,14 +3035,14 @@ static void gsm1_receive(struct gsm_mux *gsm, u8 c)
+ gsm->fcs = gsm_fcs_add(gsm->fcs, gsm->buf[gsm->count]);
+ gsm->len = gsm->count;
+ gsm_queue(gsm);
+- gsm->state = GSM_START;
++ gsm->state = GSM1_START;
+ return;
+ }
+ /* Any partial frame was a runt so go back to start */
+- if (gsm->state != GSM_START) {
++ if (gsm->state != GSM1_START) {
+ if (gsm->state != GSM_SEARCH)
+ gsm->malformed++;
+- gsm->state = GSM_START;
++ gsm->state = GSM1_START;
+ }
+ /* A SOF in GSM_START means we are still reading idling or
+ framing bytes */
+@@ -3009,30 +3063,30 @@ static void gsm1_receive(struct gsm_mux *gsm, u8 c)
+ gsm->escape = false;
+ }
+ switch (gsm->state) {
+- case GSM_START: /* First byte after SOF */
++ case GSM1_START: /* First byte after SOF */
+ gsm->address = 0;
+- gsm->state = GSM_ADDRESS;
++ gsm->state = GSM1_ADDRESS;
+ gsm->fcs = INIT_FCS;
+ fallthrough;
+- case GSM_ADDRESS: /* Address continuation */
++ case GSM1_ADDRESS: /* Address continuation */
+ gsm->fcs = gsm_fcs_add(gsm->fcs, c);
+ if (gsm_read_ea(&gsm->address, c))
+- gsm->state = GSM_CONTROL;
++ gsm->state = GSM1_CONTROL;
+ break;
+- case GSM_CONTROL: /* Control Byte */
++ case GSM1_CONTROL: /* Control Byte */
+ gsm->fcs = gsm_fcs_add(gsm->fcs, c);
+ gsm->control = c;
+ gsm->count = 0;
+- gsm->state = GSM_DATA;
++ gsm->state = GSM1_DATA;
+ break;
+- case GSM_DATA: /* Data */
+- if (gsm->count > gsm->mru) { /* Allow one for the FCS */
+- gsm->state = GSM_OVERRUN;
++ case GSM1_DATA: /* Data */
++ if (gsm->count > gsm->mru || gsm->count > MAX_MRU) { /* Allow one for the FCS */
++ gsm->state = GSM1_OVERRUN;
+ gsm->bad_size++;
+ } else
+ gsm->buf[gsm->count++] = c;
+ break;
+- case GSM_OVERRUN: /* Over-long - eg a dropped SOF */
++ case GSM1_OVERRUN: /* Over-long - eg a dropped SOF */
+ break;
+ default:
+ pr_debug("%s: unhandled state: %d\n", __func__, gsm->state);
+diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c
+index 504c4c0208577..4f8b70f8ce19f 100644
+--- a/drivers/tty/serial/8250/8250_bcm7271.c
++++ b/drivers/tty/serial/8250/8250_bcm7271.c
+@@ -676,18 +676,46 @@ static void init_real_clk_rates(struct device *dev, struct brcmuart_priv *priv)
+ clk_set_rate(priv->baud_mux_clk, priv->default_mux_rate);
+ }
+
++static u32 find_quot(struct device *dev, u32 freq, u32 baud, u32 *percent)
++{
++ u32 quot;
++ u32 rate;
++ u64 hires_rate;
++ u64 hires_baud;
++ u64 hires_err;
++
++ rate = freq / 16;
++ quot = DIV_ROUND_CLOSEST(rate, baud);
++ if (!quot)
++ return 0;
++
++ /* increase resolution to get xx.xx percent */
++ hires_rate = div_u64((u64)rate * 10000, (u64)quot);
++ hires_baud = (u64)baud * 10000;
++
++ /* get the delta */
++ if (hires_rate > hires_baud)
++ hires_err = (hires_rate - hires_baud);
++ else
++ hires_err = (hires_baud - hires_rate);
++
++ *percent = (unsigned long)DIV_ROUND_CLOSEST_ULL(hires_err, baud);
++
++ dev_dbg(dev, "Baud rate: %u, MUX Clk: %u, Error: %u.%u%%\n",
++ baud, freq, *percent / 100, *percent % 100);
++
++ return quot;
++}
++
+ static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv,
+ u32 baud)
+ {
+ u32 percent;
+ u32 best_percent = UINT_MAX;
+ u32 quot;
++ u32 freq;
+ u32 best_quot = 1;
+- u32 rate;
+- int best_index = -1;
+- u64 hires_rate;
+- u64 hires_baud;
+- u64 hires_err;
++ u32 best_freq = 0;
+ int rc;
+ int i;
+ int real_baud;
+@@ -696,44 +724,35 @@ static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv,
+ if (priv->baud_mux_clk == NULL)
+ return;
+
+- /* Find the closest match for specified baud */
+- for (i = 0; i < ARRAY_SIZE(priv->real_rates); i++) {
+- if (priv->real_rates[i] == 0)
+- continue;
+- rate = priv->real_rates[i] / 16;
+- quot = DIV_ROUND_CLOSEST(rate, baud);
+- if (!quot)
+- continue;
+-
+- /* increase resolution to get xx.xx percent */
+- hires_rate = (u64)rate * 10000;
+- hires_baud = (u64)baud * 10000;
+-
+- hires_err = div_u64(hires_rate, (u64)quot);
+-
+- /* get the delta */
+- if (hires_err > hires_baud)
+- hires_err = (hires_err - hires_baud);
+- else
+- hires_err = (hires_baud - hires_err);
+-
+- percent = (unsigned long)DIV_ROUND_CLOSEST_ULL(hires_err, baud);
+- dev_dbg(up->dev,
+- "Baud rate: %u, MUX Clk: %u, Error: %u.%u%%\n",
+- baud, priv->real_rates[i], percent / 100,
+- percent % 100);
+- if (percent < best_percent) {
+- best_percent = percent;
+- best_index = i;
+- best_quot = quot;
++ /* Try default_mux_rate first */
++ quot = find_quot(up->dev, priv->default_mux_rate, baud, &percent);
++ if (quot) {
++ best_percent = percent;
++ best_freq = priv->default_mux_rate;
++ best_quot = quot;
++ }
++ /* If more than 1% error, find the closest match for specified baud */
++ if (best_percent > 100) {
++ for (i = 0; i < ARRAY_SIZE(priv->real_rates); i++) {
++ freq = priv->real_rates[i];
++ if (freq == 0 || freq == priv->default_mux_rate)
++ continue;
++ quot = find_quot(up->dev, freq, baud, &percent);
++ if (!quot)
++ continue;
++
++ if (percent < best_percent) {
++ best_percent = percent;
++ best_freq = freq;
++ best_quot = quot;
++ }
+ }
+ }
+- if (best_index == -1) {
++ if (!best_freq) {
+ dev_err(up->dev, "Error, %d BAUD rate is too fast.\n", baud);
+ return;
+ }
+- rate = priv->real_rates[best_index];
+- rc = clk_set_rate(priv->baud_mux_clk, rate);
++ rc = clk_set_rate(priv->baud_mux_clk, best_freq);
+ if (rc)
+ dev_err(up->dev, "Error selecting BAUD MUX clock\n");
+
+@@ -742,8 +761,8 @@ static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv,
+ dev_err(up->dev, "Error, baud: %d has %u.%u%% error\n",
+ baud, percent / 100, percent % 100);
+
+- real_baud = rate / 16 / best_quot;
+- dev_dbg(up->dev, "Selecting BAUD MUX rate: %u\n", rate);
++ real_baud = best_freq / 16 / best_quot;
++ dev_dbg(up->dev, "Selecting BAUD MUX rate: %u\n", best_freq);
+ dev_dbg(up->dev, "Requested baud: %u, Actual baud: %u\n",
+ baud, real_baud);
+
+@@ -752,7 +771,7 @@ static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv,
+ i += (i / 2);
+ priv->char_wait = ns_to_ktime(i);
+
+- up->uartclk = rate;
++ up->uartclk = best_freq;
+ }
+
+ static void brcmstb_set_termios(struct uart_port *up,
+diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
+index 9ff6bbe9c0863..d14988d1492fe 100644
+--- a/drivers/tty/serial/8250/8250_mtk.c
++++ b/drivers/tty/serial/8250/8250_mtk.c
+@@ -209,15 +209,19 @@ static int mtk8250_startup(struct uart_port *port)
+
+ static void mtk8250_shutdown(struct uart_port *port)
+ {
+-#ifdef CONFIG_SERIAL_8250_DMA
+ struct uart_8250_port *up = up_to_u8250p(port);
+ struct mtk8250_data *data = port->private_data;
++ int irq = data->rx_wakeup_irq;
+
++#ifdef CONFIG_SERIAL_8250_DMA
+ if (up->dma)
+ data->rx_status = DMA_RX_SHUTDOWN;
+ #endif
+
+- return serial8250_do_shutdown(port);
++ serial8250_do_shutdown(port);
++
++ if (irq >= 0)
++ serial8250_do_set_mctrl(&up->port, TIOCM_RTS);
+ }
+
+ static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask)
+diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
+index 929206a9a6e11..12915fffac279 100644
+--- a/drivers/tty/serial/sc16is7xx.c
++++ b/drivers/tty/serial/sc16is7xx.c
+@@ -554,16 +554,28 @@ static bool sc16is7xx_regmap_noinc(struct device *dev, unsigned int reg)
+ return reg == SC16IS7XX_RHR_REG;
+ }
+
++/*
++ * Configure programmable baud rate generator (divisor) according to the
++ * desired baud rate.
++ *
++ * From the datasheet, the divisor is computed according to:
++ *
++ * XTAL1 input frequency
++ * -----------------------
++ * prescaler
++ * divisor = ---------------------------
++ * baud-rate x sampling-rate
++ */
+ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
+ {
+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
+ u8 lcr;
+- u8 prescaler = 0;
++ unsigned int prescaler = 1;
+ unsigned long clk = port->uartclk, div = clk / 16 / baud;
+
+ if (div >= BIT(16)) {
+- prescaler = SC16IS7XX_MCR_CLKSEL_BIT;
+- div /= 4;
++ prescaler = 4;
++ div /= prescaler;
+ }
+
+ /* Enable enhanced features */
+@@ -573,9 +585,10 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
+ SC16IS7XX_EFR_ENABLE_BIT);
+ sc16is7xx_efr_unlock(port);
+
++ /* If bit MCR_CLKSEL is set, the divide by 4 prescaler is activated. */
+ sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
+ SC16IS7XX_MCR_CLKSEL_BIT,
+- prescaler);
++ prescaler == 1 ? 0 : SC16IS7XX_MCR_CLKSEL_BIT);
+
+ /* Backup LCR and access special register set (DLL/DLH) */
+ lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG);
+@@ -591,7 +604,7 @@ static int sc16is7xx_set_baud(struct uart_port *port, int baud)
+ /* Restore LCR and access to general register set */
+ sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr);
+
+- return DIV_ROUND_CLOSEST(clk / 16, div);
++ return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div);
+ }
+
+ static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen,
+diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c
+index c873fd8239427..7ae3096814282 100644
+--- a/drivers/ufs/core/ufs-mcq.c
++++ b/drivers/ufs/core/ufs-mcq.c
+@@ -597,8 +597,7 @@ static bool ufshcd_mcq_sqe_search(struct ufs_hba *hba,
+ addr = le64_to_cpu(cmd_desc_base_addr) & CQE_UCD_BA;
+
+ while (sq_head_slot != hwq->sq_tail_slot) {
+- utrd = hwq->sqe_base_addr +
+- sq_head_slot * sizeof(struct utp_transfer_req_desc);
++ utrd = hwq->sqe_base_addr + sq_head_slot;
+ match = le64_to_cpu(utrd->command_desc_base_addr) & CQE_UCD_BA;
+ if (addr == match) {
+ ufshcd_mcq_nullify_sqe(utrd);
+diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
+index 4a07a18cf835d..24b54aa094812 100644
+--- a/drivers/ufs/core/ufshcd.c
++++ b/drivers/ufs/core/ufshcd.c
+@@ -4244,7 +4244,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
+ * Make sure UIC command completion interrupt is disabled before
+ * issuing UIC command.
+ */
+- wmb();
++ ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+ reenable_intr = true;
+ }
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+@@ -10353,7 +10353,7 @@ int ufshcd_system_restore(struct device *dev)
+ * are updated with the latest queue addresses. Only after
+ * updating these addresses, we can queue the new commands.
+ */
+- mb();
++ ufshcd_readl(hba, REG_UTP_TASK_REQ_LIST_BASE_H);
+
+ /* Resuming from hibernate, assume that link was OFF */
+ ufshcd_set_link_off(hba);
+@@ -10570,7 +10570,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
+ * Make sure that UFS interrupts are disabled and any pending interrupt
+ * status is cleared before registering UFS interrupt handler.
+ */
+- mb();
++ ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+
+ /* IRQ registration */
+ err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
+diff --git a/drivers/ufs/host/cdns-pltfrm.c b/drivers/ufs/host/cdns-pltfrm.c
+index bb30267da4711..66811d8d1929c 100644
+--- a/drivers/ufs/host/cdns-pltfrm.c
++++ b/drivers/ufs/host/cdns-pltfrm.c
+@@ -136,7 +136,7 @@ static int cdns_ufs_set_hclkdiv(struct ufs_hba *hba)
+ * Make sure the register was updated,
+ * UniPro layer will not work with an incorrect value.
+ */
+- mb();
++ ufshcd_readl(hba, CDNS_UFS_REG_HCLKDIV);
+
+ return 0;
+ }
+diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
+index bcbcf758925be..e5a4bf1c553bb 100644
+--- a/drivers/ufs/host/ufs-qcom.c
++++ b/drivers/ufs/host/ufs-qcom.c
+@@ -284,9 +284,6 @@ static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host)
+
+ if (host->hw_ver.major >= 0x05)
+ ufshcd_rmwl(host->hba, QUNIPRO_G4_SEL, 0, REG_UFS_CFG0);
+-
+- /* make sure above configuration is applied before we return */
+- mb();
+ }
+
+ /*
+@@ -415,7 +412,7 @@ static void ufs_qcom_enable_hw_clk_gating(struct ufs_hba *hba)
+ REG_UFS_CFG2);
+
+ /* Ensure that HW clock gating is enabled before next operations */
+- mb();
++ ufshcd_readl(hba, REG_UFS_CFG2);
+ }
+
+ static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
+@@ -507,7 +504,7 @@ static int ufs_qcom_cfg_timers(struct ufs_hba *hba, u32 gear,
+ * make sure above write gets applied before we return from
+ * this function.
+ */
+- mb();
++ ufshcd_readl(hba, REG_UFS_SYS1CLK_1US);
+ }
+
+ return 0;
+diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
+index 9dd9a391ebb76..b9de170983c9e 100644
+--- a/drivers/ufs/host/ufs-qcom.h
++++ b/drivers/ufs/host/ufs-qcom.h
+@@ -151,10 +151,10 @@ static inline void ufs_qcom_assert_reset(struct ufs_hba *hba)
+ ufshcd_rmwl(hba, UFS_PHY_SOFT_RESET, UFS_PHY_SOFT_RESET, REG_UFS_CFG1);
+
+ /*
+- * Make sure assertion of ufs phy reset is written to
+- * register before returning
++ * Dummy read to ensure the write takes effect before doing any sort
++ * of delay
+ */
+- mb();
++ ufshcd_readl(hba, REG_UFS_CFG1);
+ }
+
+ static inline void ufs_qcom_deassert_reset(struct ufs_hba *hba)
+@@ -162,10 +162,10 @@ static inline void ufs_qcom_deassert_reset(struct ufs_hba *hba)
+ ufshcd_rmwl(hba, UFS_PHY_SOFT_RESET, 0, REG_UFS_CFG1);
+
+ /*
+- * Make sure de-assertion of ufs phy reset is written to
+- * register before returning
++ * Dummy read to ensure the write takes effect before doing any sort
++ * of delay
+ */
+- mb();
++ ufshcd_readl(hba, REG_UFS_CFG1);
+ }
+
+ /* Host controller hardware version: major.minor.step */
+diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
+index ba4ab33f6094b..411bf2b2c4d03 100644
+--- a/drivers/video/fbdev/Kconfig
++++ b/drivers/video/fbdev/Kconfig
+@@ -1680,8 +1680,8 @@ config FB_COBALT
+ select FB_IOMEM_HELPERS
+
+ config FB_SH7760
+- bool "SH7760/SH7763/SH7720/SH7721 LCDC support"
+- depends on FB=y && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \
++ tristate "SH7760/SH7763/SH7720/SH7721 LCDC support"
++ depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \
+ || CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721)
+ select FB_IOMEM_HELPERS
+ help
+diff --git a/drivers/video/fbdev/core/Kconfig b/drivers/video/fbdev/core/Kconfig
+index 21053bf00dc58..c0a5e4cbe0ac2 100644
+--- a/drivers/video/fbdev/core/Kconfig
++++ b/drivers/video/fbdev/core/Kconfig
+@@ -144,6 +144,12 @@ config FB_DMAMEM_HELPERS
+ select FB_SYS_IMAGEBLIT
+ select FB_SYSMEM_FOPS
+
++config FB_DMAMEM_HELPERS_DEFERRED
++ bool
++ depends on FB_CORE
++ select FB_DEFERRED_IO
++ select FB_DMAMEM_HELPERS
++
+ config FB_IOMEM_FOPS
+ tristate
+ depends on FB_CORE
+diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c
+index eb2297b37504c..d35d2cf999988 100644
+--- a/drivers/video/fbdev/sh_mobile_lcdcfb.c
++++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c
+@@ -1575,7 +1575,7 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl)
+ */
+ info->fix = sh_mobile_lcdc_overlay_fix;
+ snprintf(info->fix.id, sizeof(info->fix.id),
+- "SH Mobile LCDC Overlay %u", ovl->index);
++ "SHMobile ovl %u", ovl->index);
+ info->fix.smem_start = ovl->dma_handle;
+ info->fix.smem_len = ovl->fb_size;
+ info->fix.line_length = ovl->pitch;
+diff --git a/drivers/video/fbdev/sis/init301.c b/drivers/video/fbdev/sis/init301.c
+index a8fb41f1a2580..09329072004f4 100644
+--- a/drivers/video/fbdev/sis/init301.c
++++ b/drivers/video/fbdev/sis/init301.c
+@@ -172,7 +172,7 @@ static const unsigned char SiS_HiTVGroup3_2[] = {
+ };
+
+ /* 301C / 302ELV extended Part2 TV registers (4 tap scaler) */
+-
++#ifdef CONFIG_FB_SIS_315
+ static const unsigned char SiS_Part2CLVX_1[] = {
+ 0x00,0x00,
+ 0x00,0x20,0x00,0x00,0x7F,0x20,0x02,0x7F,0x7D,0x20,0x04,0x7F,0x7D,0x1F,0x06,0x7E,
+@@ -245,7 +245,6 @@ static const unsigned char SiS_Part2CLVX_6[] = { /* 1080i */
+ 0xFF,0xFF,
+ };
+
+-#ifdef CONFIG_FB_SIS_315
+ /* 661 et al LCD data structure (2.03.00) */
+ static const unsigned char SiS_LCDStruct661[] = {
+ /* 1024x768 */
+diff --git a/drivers/virt/acrn/mm.c b/drivers/virt/acrn/mm.c
+index fa5d9ca6be570..9c75de0656d8d 100644
+--- a/drivers/virt/acrn/mm.c
++++ b/drivers/virt/acrn/mm.c
+@@ -155,43 +155,83 @@ int acrn_vm_memseg_unmap(struct acrn_vm *vm, struct acrn_vm_memmap *memmap)
+ int acrn_vm_ram_map(struct acrn_vm *vm, struct acrn_vm_memmap *memmap)
+ {
+ struct vm_memory_region_batch *regions_info;
+- int nr_pages, i = 0, order, nr_regions = 0;
++ int nr_pages, i, order, nr_regions = 0;
+ struct vm_memory_mapping *region_mapping;
+ struct vm_memory_region_op *vm_region;
+ struct page **pages = NULL, *page;
+ void *remap_vaddr;
+ int ret, pinned;
+ u64 user_vm_pa;
+- unsigned long pfn;
+ struct vm_area_struct *vma;
+
+ if (!vm || !memmap)
+ return -EINVAL;
+
++ /* Get the page number of the map region */
++ nr_pages = memmap->len >> PAGE_SHIFT;
++ if (!nr_pages)
++ return -EINVAL;
++
+ mmap_read_lock(current->mm);
+ vma = vma_lookup(current->mm, memmap->vma_base);
+ if (vma && ((vma->vm_flags & VM_PFNMAP) != 0)) {
++ unsigned long start_pfn, cur_pfn;
++ spinlock_t *ptl;
++ bool writable;
++ pte_t *ptep;
++
+ if ((memmap->vma_base + memmap->len) > vma->vm_end) {
+ mmap_read_unlock(current->mm);
+ return -EINVAL;
+ }
+
+- ret = follow_pfn(vma, memmap->vma_base, &pfn);
++ for (i = 0; i < nr_pages; i++) {
++ ret = follow_pte(vma->vm_mm,
++ memmap->vma_base + i * PAGE_SIZE,
++ &ptep, &ptl);
++ if (ret)
++ break;
++
++ cur_pfn = pte_pfn(ptep_get(ptep));
++ if (i == 0)
++ start_pfn = cur_pfn;
++ writable = !!pte_write(ptep_get(ptep));
++ pte_unmap_unlock(ptep, ptl);
++
++ /* Disallow write access if the PTE is not writable. */
++ if (!writable &&
++ (memmap->attr & ACRN_MEM_ACCESS_WRITE)) {
++ ret = -EFAULT;
++ break;
++ }
++
++ /* Disallow refcounted pages. */
++ if (pfn_valid(cur_pfn) &&
++ !PageReserved(pfn_to_page(cur_pfn))) {
++ ret = -EFAULT;
++ break;
++ }
++
++ /* Disallow non-contiguous ranges. */
++ if (cur_pfn != start_pfn + i) {
++ ret = -EINVAL;
++ break;
++ }
++ }
+ mmap_read_unlock(current->mm);
+- if (ret < 0) {
++
++ if (ret) {
+ dev_dbg(acrn_dev.this_device,
+ "Failed to lookup PFN at VMA:%pK.\n", (void *)memmap->vma_base);
+ return ret;
+ }
+
+ return acrn_mm_region_add(vm, memmap->user_vm_pa,
+- PFN_PHYS(pfn), memmap->len,
++ PFN_PHYS(start_pfn), memmap->len,
+ ACRN_MEM_TYPE_WB, memmap->attr);
+ }
+ mmap_read_unlock(current->mm);
+
+- /* Get the page number of the map region */
+- nr_pages = memmap->len >> PAGE_SHIFT;
+ pages = vzalloc(array_size(nr_pages, sizeof(*pages)));
+ if (!pages)
+ return -ENOMEM;
+@@ -235,12 +275,11 @@ int acrn_vm_ram_map(struct acrn_vm *vm, struct acrn_vm_memmap *memmap)
+ mutex_unlock(&vm->regions_mapping_lock);
+
+ /* Calculate count of vm_memory_region_op */
+- while (i < nr_pages) {
++ for (i = 0; i < nr_pages; i += 1 << order) {
+ page = pages[i];
+ VM_BUG_ON_PAGE(PageTail(page), page);
+ order = compound_order(page);
+ nr_regions++;
+- i += 1 << order;
+ }
+
+ /* Prepare the vm_memory_region_batch */
+@@ -257,8 +296,7 @@ int acrn_vm_ram_map(struct acrn_vm *vm, struct acrn_vm_memmap *memmap)
+ regions_info->vmid = vm->vmid;
+ regions_info->regions_gpa = virt_to_phys(vm_region);
+ user_vm_pa = memmap->user_vm_pa;
+- i = 0;
+- while (i < nr_pages) {
++ for (i = 0; i < nr_pages; i += 1 << order) {
+ u32 region_size;
+
+ page = pages[i];
+@@ -274,7 +312,6 @@ int acrn_vm_ram_map(struct acrn_vm *vm, struct acrn_vm_memmap *memmap)
+
+ vm_region++;
+ user_vm_pa += region_size;
+- i += 1 << order;
+ }
+
+ /* Inform the ACRN Hypervisor to set up EPT mappings */
+diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
+index 6b93fae74403d..8851ba7a1e271 100644
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -3722,15 +3722,43 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
+ goto drop_write;
+ }
+
+- down_write(&fs_info->subvol_sem);
+-
+ switch (sa->cmd) {
+ case BTRFS_QUOTA_CTL_ENABLE:
+ case BTRFS_QUOTA_CTL_ENABLE_SIMPLE_QUOTA:
++ down_write(&fs_info->subvol_sem);
+ ret = btrfs_quota_enable(fs_info, sa);
++ up_write(&fs_info->subvol_sem);
+ break;
+ case BTRFS_QUOTA_CTL_DISABLE:
++ /*
++ * Lock the cleaner mutex to prevent races with concurrent
++ * relocation, because relocation may be building backrefs for
++ * blocks of the quota root while we are deleting the root. This
++ * is like dropping fs roots of deleted snapshots/subvolumes, we
++ * need the same protection.
++ *
++ * This also prevents races between concurrent tasks trying to
++ * disable quotas, because we will unlock and relock
++ * qgroup_ioctl_lock across BTRFS_FS_QUOTA_ENABLED changes.
++ *
++ * We take this here because we have the dependency of
++ *
++ * inode_lock -> subvol_sem
++ *
++ * because of rename. With relocation we can prealloc extents,
++ * so that makes the dependency chain
++ *
++ * cleaner_mutex -> inode_lock -> subvol_sem
++ *
++ * so we must take the cleaner_mutex here before we take the
++ * subvol_sem. The deadlock can't actually happen, but this
++ * quiets lockdep.
++ */
++ mutex_lock(&fs_info->cleaner_mutex);
++ down_write(&fs_info->subvol_sem);
+ ret = btrfs_quota_disable(fs_info);
++ up_write(&fs_info->subvol_sem);
++ mutex_unlock(&fs_info->cleaner_mutex);
+ break;
+ default:
+ ret = -EINVAL;
+@@ -3738,7 +3766,6 @@ static long btrfs_ioctl_quota_ctl(struct file *file, void __user *arg)
+ }
+
+ kfree(sa);
+- up_write(&fs_info->subvol_sem);
+ drop_write:
+ mnt_drop_write_file(file);
+ return ret;
+diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
+index 82d4559eb4b1e..cacc12d0ff33f 100644
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -1342,16 +1342,10 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
+ lockdep_assert_held_write(&fs_info->subvol_sem);
+
+ /*
+- * Lock the cleaner mutex to prevent races with concurrent relocation,
+- * because relocation may be building backrefs for blocks of the quota
+- * root while we are deleting the root. This is like dropping fs roots
+- * of deleted snapshots/subvolumes, we need the same protection.
+- *
+- * This also prevents races between concurrent tasks trying to disable
+- * quotas, because we will unlock and relock qgroup_ioctl_lock across
+- * BTRFS_FS_QUOTA_ENABLED changes.
++ * Relocation will mess with backrefs, so make sure we have the
++ * cleaner_mutex held to protect us from relocate.
+ */
+- mutex_lock(&fs_info->cleaner_mutex);
++ lockdep_assert_held(&fs_info->cleaner_mutex);
+
+ mutex_lock(&fs_info->qgroup_ioctl_lock);
+ if (!fs_info->quota_root)
+@@ -1373,9 +1367,13 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
+ clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
+ btrfs_qgroup_wait_for_completion(fs_info, false);
+
++ /*
++ * We have nothing held here and no trans handle, just return the error
++ * if there is one.
++ */
+ ret = flush_reservations(fs_info);
+ if (ret)
+- goto out_unlock_cleaner;
++ return ret;
+
+ /*
+ * 1 For the root item
+@@ -1439,9 +1437,6 @@ int btrfs_quota_disable(struct btrfs_fs_info *fs_info)
+ btrfs_end_transaction(trans);
+ else if (trans)
+ ret = btrfs_commit_transaction(trans);
+-out_unlock_cleaner:
+- mutex_unlock(&fs_info->cleaner_mutex);
+-
+ return ret;
+ }
+
+diff --git a/fs/dlm/ast.c b/fs/dlm/ast.c
+index 1f2f70a1b824e..decedc4ee15f6 100644
+--- a/fs/dlm/ast.c
++++ b/fs/dlm/ast.c
+@@ -12,6 +12,7 @@
+ #include <trace/events/dlm.h>
+
+ #include "dlm_internal.h"
++#include "lvb_table.h"
+ #include "memory.h"
+ #include "lock.h"
+ #include "user.h"
+@@ -42,6 +43,7 @@ int dlm_enqueue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
+ struct dlm_ls *ls = lkb->lkb_resource->res_ls;
+ int rv = DLM_ENQUEUE_CALLBACK_SUCCESS;
+ struct dlm_callback *cb;
++ int copy_lvb = 0;
+ int prev_mode;
+
+ if (flags & DLM_CB_BAST) {
+@@ -73,6 +75,17 @@ int dlm_enqueue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
+ goto out;
+ }
+ }
++ } else if (flags & DLM_CB_CAST) {
++ if (test_bit(DLM_DFL_USER_BIT, &lkb->lkb_dflags)) {
++ if (lkb->lkb_last_cast)
++ prev_mode = lkb->lkb_last_cb->mode;
++ else
++ prev_mode = -1;
++
++ if (!status && lkb->lkb_lksb->sb_lvbptr &&
++ dlm_lvb_operations[prev_mode + 1][mode + 1])
++ copy_lvb = 1;
++ }
+ }
+
+ cb = dlm_allocate_cb();
+@@ -85,6 +98,7 @@ int dlm_enqueue_lkb_callback(struct dlm_lkb *lkb, uint32_t flags, int mode,
+ cb->mode = mode;
+ cb->sb_status = status;
+ cb->sb_flags = (sbflags & 0x000000FF);
++ cb->copy_lvb = copy_lvb;
+ kref_init(&cb->ref);
+ if (!test_and_set_bit(DLM_IFL_CB_PENDING_BIT, &lkb->lkb_iflags))
+ rv = DLM_ENQUEUE_CALLBACK_NEED_SCHED;
+diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
+index dfc444dad3298..511d0b984f580 100644
+--- a/fs/dlm/dlm_internal.h
++++ b/fs/dlm/dlm_internal.h
+@@ -222,6 +222,7 @@ struct dlm_callback {
+ int sb_status; /* copy to lksb status */
+ uint8_t sb_flags; /* copy to lksb flags */
+ int8_t mode; /* rq mode of bast, gr mode of cast */
++ int copy_lvb;
+
+ struct list_head list;
+ struct kref ref;
+diff --git a/fs/dlm/user.c b/fs/dlm/user.c
+index 9f9b68448830e..12a483deeef5e 100644
+--- a/fs/dlm/user.c
++++ b/fs/dlm/user.c
+@@ -21,7 +21,6 @@
+ #include "dlm_internal.h"
+ #include "lockspace.h"
+ #include "lock.h"
+-#include "lvb_table.h"
+ #include "user.h"
+ #include "ast.h"
+ #include "config.h"
+@@ -806,8 +805,7 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
+ struct dlm_lkb *lkb;
+ DECLARE_WAITQUEUE(wait, current);
+ struct dlm_callback *cb;
+- int rv, ret, copy_lvb = 0;
+- int old_mode, new_mode;
++ int rv, ret;
+
+ if (count == sizeof(struct dlm_device_version)) {
+ rv = copy_version_to_user(buf, count);
+@@ -864,9 +862,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
+
+ lkb = list_first_entry(&proc->asts, struct dlm_lkb, lkb_cb_list);
+
+- /* rem_lkb_callback sets a new lkb_last_cast */
+- old_mode = lkb->lkb_last_cast->mode;
+-
+ rv = dlm_dequeue_lkb_callback(lkb, &cb);
+ switch (rv) {
+ case DLM_DEQUEUE_CALLBACK_EMPTY:
+@@ -895,12 +890,6 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
+ if (cb->flags & DLM_CB_BAST) {
+ trace_dlm_bast(lkb->lkb_resource->res_ls, lkb, cb->mode);
+ } else if (cb->flags & DLM_CB_CAST) {
+- new_mode = cb->mode;
+-
+- if (!cb->sb_status && lkb->lkb_lksb->sb_lvbptr &&
+- dlm_lvb_operations[old_mode + 1][new_mode + 1])
+- copy_lvb = 1;
+-
+ lkb->lkb_lksb->sb_status = cb->sb_status;
+ lkb->lkb_lksb->sb_flags = cb->sb_flags;
+ trace_dlm_ast(lkb->lkb_resource->res_ls, lkb);
+@@ -908,7 +897,7 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
+
+ ret = copy_result_to_user(lkb->lkb_ua,
+ test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
+- cb->flags, cb->mode, copy_lvb, buf, count);
++ cb->flags, cb->mode, cb->copy_lvb, buf, count);
+
+ kref_put(&cb->ref, dlm_release_callback);
+
+diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
+index 3fe41964c0d8d..7f9f68c00ef63 100644
+--- a/fs/ecryptfs/keystore.c
++++ b/fs/ecryptfs/keystore.c
+@@ -300,9 +300,11 @@ write_tag_66_packet(char *signature, u8 cipher_code,
+ * | Key Identifier Size | 1 or 2 bytes |
+ * | Key Identifier | arbitrary |
+ * | File Encryption Key Size | 1 or 2 bytes |
++ * | Cipher Code | 1 byte |
+ * | File Encryption Key | arbitrary |
++ * | Checksum | 2 bytes |
+ */
+- data_len = (5 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size);
++ data_len = (8 + ECRYPTFS_SIG_SIZE_HEX + crypt_stat->key_size);
+ *packet = kmalloc(data_len, GFP_KERNEL);
+ message = *packet;
+ if (!message) {
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index 3534d36a14740..c5a9a483fb538 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -875,6 +875,34 @@ static __poll_t __ep_eventpoll_poll(struct file *file, poll_table *wait, int dep
+ return res;
+ }
+
++/*
++ * The ffd.file pointer may be in the process of being torn down due to
++ * being closed, but we may not have finished eventpoll_release() yet.
++ *
++ * Normally, even with the atomic_long_inc_not_zero, the file may have
++ * been free'd and then gotten re-allocated to something else (since
++ * files are not RCU-delayed, they are SLAB_TYPESAFE_BY_RCU).
++ *
++ * But for epoll, users hold the ep->mtx mutex, and as such any file in
++ * the process of being free'd will block in eventpoll_release_file()
++ * and thus the underlying file allocation will not be free'd, and the
++ * file re-use cannot happen.
++ *
++ * For the same reason we can avoid a rcu_read_lock() around the
++ * operation - 'ffd.file' cannot go away even if the refcount has
++ * reached zero (but we must still not call out to ->poll() functions
++ * etc).
++ */
++static struct file *epi_fget(const struct epitem *epi)
++{
++ struct file *file;
++
++ file = epi->ffd.file;
++ if (!atomic_long_inc_not_zero(&file->f_count))
++ file = NULL;
++ return file;
++}
++
+ /*
+ * Differs from ep_eventpoll_poll() in that internal callers already have
+ * the ep->mtx so we need to start from depth=1, such that mutex_lock_nested()
+@@ -883,14 +911,22 @@ static __poll_t __ep_eventpoll_poll(struct file *file, poll_table *wait, int dep
+ static __poll_t ep_item_poll(const struct epitem *epi, poll_table *pt,
+ int depth)
+ {
+- struct file *file = epi->ffd.file;
++ struct file *file = epi_fget(epi);
+ __poll_t res;
+
++ /*
++ * We could return EPOLLERR | EPOLLHUP or something, but let's
++ * treat this more as "file doesn't exist, poll didn't happen".
++ */
++ if (!file)
++ return 0;
++
+ pt->_key = epi->event.events;
+ if (!is_file_epoll(file))
+ res = vfs_poll(file, pt);
+ else
+ res = __ep_eventpoll_poll(file, pt, depth);
++ fput(file);
+ return res & epi->event.events;
+ }
+
+diff --git a/fs/exec.c b/fs/exec.c
+index 5ee2545c3e183..f11cfd7bce0b1 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -67,6 +67,7 @@
+ #include <linux/time_namespace.h>
+ #include <linux/user_events.h>
+ #include <linux/rseq.h>
++#include <linux/ksm.h>
+
+ #include <linux/uaccess.h>
+ #include <asm/mmu_context.h>
+@@ -267,6 +268,14 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
+ goto err_free;
+ }
+
++ /*
++ * Need to be called with mmap write lock
++ * held, to avoid race with ksmd.
++ */
++ err = ksm_execve(mm);
++ if (err)
++ goto err_ksm;
++
+ /*
+ * Place the stack at the largest stack address the architecture
+ * supports. Later, we'll move this to an appropriate place. We don't
+@@ -288,6 +297,8 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
+ bprm->p = vma->vm_end - sizeof(void *);
+ return 0;
+ err:
++ ksm_exit(mm);
++err_ksm:
+ mmap_write_unlock(mm);
+ err_free:
+ bprm->vma = NULL;
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 2ccf3b5e3a7c4..31604907af50e 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2887,9 +2887,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
+ if (IS_ERR(folio))
+ return PTR_ERR(folio);
+
+- /* In case writeback began while the folio was unlocked */
+- folio_wait_stable(folio);
+-
+ #ifdef CONFIG_FS_ENCRYPTION
+ ret = ext4_block_write_begin(folio, pos, len, ext4_da_get_block_prep);
+ #else
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index cf407425d0f30..00b0839b534da 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -6119,6 +6119,7 @@ ext4_mb_new_blocks_simple(struct ext4_allocation_request *ar, int *errp)
+ ext4_mb_mark_bb(sb, block, 1, true);
+ ar->len = 1;
+
++ *errp = 0;
+ return block;
+ }
+
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 05b647e6bc195..58fee3c6febcb 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2898,7 +2898,7 @@ static int ext4_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
+ inode = ext4_new_inode_start_handle(idmap, dir, mode,
+ NULL, 0, NULL,
+ EXT4_HT_DIR,
+- EXT4_MAXQUOTAS_INIT_BLOCKS(dir->i_sb) +
++ EXT4_MAXQUOTAS_TRANS_BLOCKS(dir->i_sb) +
+ 4 + EXT4_XATTR_TRANS_BLOCKS);
+ handle = ext4_journal_current_handle();
+ err = PTR_ERR(inode);
+diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
+index 34540f9d011ca..2507fe34cbdf0 100644
+--- a/fs/gfs2/glock.c
++++ b/fs/gfs2/glock.c
+@@ -166,19 +166,45 @@ static bool glock_blocked_by_withdraw(struct gfs2_glock *gl)
+ return true;
+ }
+
+-void gfs2_glock_free(struct gfs2_glock *gl)
++static void __gfs2_glock_free(struct gfs2_glock *gl)
+ {
+- struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
+-
+- gfs2_glock_assert_withdraw(gl, atomic_read(&gl->gl_revokes) == 0);
+ rhashtable_remove_fast(&gl_hash_table, &gl->gl_node, ht_parms);
+ smp_mb();
+ wake_up_glock(gl);
+ call_rcu(&gl->gl_rcu, gfs2_glock_dealloc);
++}
++
++void gfs2_glock_free(struct gfs2_glock *gl) {
++ struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
++
++ __gfs2_glock_free(gl);
++ if (atomic_dec_and_test(&sdp->sd_glock_disposal))
++ wake_up(&sdp->sd_kill_wait);
++}
++
++void gfs2_glock_free_later(struct gfs2_glock *gl) {
++ struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
++
++ spin_lock(&lru_lock);
++ list_add(&gl->gl_lru, &sdp->sd_dead_glocks);
++ spin_unlock(&lru_lock);
+ if (atomic_dec_and_test(&sdp->sd_glock_disposal))
+ wake_up(&sdp->sd_kill_wait);
+ }
+
++static void gfs2_free_dead_glocks(struct gfs2_sbd *sdp)
++{
++ struct list_head *list = &sdp->sd_dead_glocks;
++
++ while(!list_empty(list)) {
++ struct gfs2_glock *gl;
++
++ gl = list_first_entry(list, struct gfs2_glock, gl_lru);
++ list_del_init(&gl->gl_lru);
++ __gfs2_glock_free(gl);
++ }
++}
++
+ /**
+ * gfs2_glock_hold() - increment reference count on glock
+ * @gl: The glock to hold
+@@ -591,7 +617,6 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
+ struct gfs2_holder *gh;
+ unsigned state = ret & LM_OUT_ST_MASK;
+
+- spin_lock(&gl->gl_lockref.lock);
+ trace_gfs2_glock_state_change(gl, state);
+ state_change(gl, state);
+ gh = find_first_waiter(gl);
+@@ -639,7 +664,6 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
+ gl->gl_target, state);
+ GLOCK_BUG_ON(gl, 1);
+ }
+- spin_unlock(&gl->gl_lockref.lock);
+ return;
+ }
+
+@@ -662,7 +686,6 @@ static void finish_xmote(struct gfs2_glock *gl, unsigned int ret)
+ }
+ out:
+ clear_bit(GLF_LOCK, &gl->gl_flags);
+- spin_unlock(&gl->gl_lockref.lock);
+ }
+
+ static bool is_system_glock(struct gfs2_glock *gl)
+@@ -690,6 +713,7 @@ __acquires(&gl->gl_lockref.lock)
+ {
+ const struct gfs2_glock_operations *glops = gl->gl_ops;
+ struct gfs2_sbd *sdp = gl->gl_name.ln_sbd;
++ struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+ unsigned int lck_flags = (unsigned int)(gh ? gh->gh_flags : 0);
+ int ret;
+
+@@ -718,6 +742,9 @@ __acquires(&gl->gl_lockref.lock)
+ (gl->gl_state == LM_ST_EXCLUSIVE) ||
+ (lck_flags & (LM_FLAG_TRY|LM_FLAG_TRY_1CB)))
+ clear_bit(GLF_BLOCKING, &gl->gl_flags);
++ if (!glops->go_inval && !glops->go_sync)
++ goto skip_inval;
++
+ spin_unlock(&gl->gl_lockref.lock);
+ if (glops->go_sync) {
+ ret = glops->go_sync(gl);
+@@ -730,6 +757,7 @@ __acquires(&gl->gl_lockref.lock)
+ fs_err(sdp, "Error %d syncing glock \n", ret);
+ gfs2_dump_glock(NULL, gl, true);
+ }
++ spin_lock(&gl->gl_lockref.lock);
+ goto skip_inval;
+ }
+ }
+@@ -750,9 +778,10 @@ __acquires(&gl->gl_lockref.lock)
+ glops->go_inval(gl, target == LM_ST_DEFERRED ? 0 : DIO_METADATA);
+ clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
+ }
++ spin_lock(&gl->gl_lockref.lock);
+
+ skip_inval:
+- gfs2_glock_hold(gl);
++ gl->gl_lockref.count++;
+ /*
+ * Check for an error encountered since we called go_sync and go_inval.
+ * If so, we can't withdraw from the glock code because the withdraw
+@@ -794,31 +823,37 @@ __acquires(&gl->gl_lockref.lock)
+ */
+ clear_bit(GLF_LOCK, &gl->gl_flags);
+ clear_bit(GLF_DEMOTE_IN_PROGRESS, &gl->gl_flags);
+- gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD);
+- goto out;
++ __gfs2_glock_queue_work(gl, GL_GLOCK_DFT_HOLD);
++ return;
+ } else {
+ clear_bit(GLF_INVALIDATE_IN_PROGRESS, &gl->gl_flags);
+ }
+ }
+
+- if (sdp->sd_lockstruct.ls_ops->lm_lock) {
+- /* lock_dlm */
+- ret = sdp->sd_lockstruct.ls_ops->lm_lock(gl, target, lck_flags);
++ if (ls->ls_ops->lm_lock) {
++ spin_unlock(&gl->gl_lockref.lock);
++ ret = ls->ls_ops->lm_lock(gl, target, lck_flags);
++ spin_lock(&gl->gl_lockref.lock);
++
+ if (ret == -EINVAL && gl->gl_target == LM_ST_UNLOCKED &&
+ target == LM_ST_UNLOCKED &&
+- test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags)) {
+- finish_xmote(gl, target);
+- gfs2_glock_queue_work(gl, 0);
++ test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) {
++ /*
++ * The lockspace has been released and the lock has
++ * been unlocked implicitly.
++ */
+ } else if (ret) {
+ fs_err(sdp, "lm_lock ret %d\n", ret);
+- GLOCK_BUG_ON(gl, !gfs2_withdrawing_or_withdrawn(sdp));
++ target = gl->gl_state | LM_OUT_ERROR;
++ } else {
++ /* The operation will be completed asynchronously. */
++ return;
+ }
+- } else { /* lock_nolock */
+- finish_xmote(gl, target);
+- gfs2_glock_queue_work(gl, 0);
+ }
+-out:
+- spin_lock(&gl->gl_lockref.lock);
++
++ /* Complete the operation now. */
++ finish_xmote(gl, target);
++ __gfs2_glock_queue_work(gl, 0);
+ }
+
+ /**
+@@ -1071,11 +1106,12 @@ static void glock_work_func(struct work_struct *work)
+ struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_work.work);
+ unsigned int drop_refs = 1;
+
+- if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) {
++ spin_lock(&gl->gl_lockref.lock);
++ if (test_bit(GLF_REPLY_PENDING, &gl->gl_flags)) {
++ clear_bit(GLF_REPLY_PENDING, &gl->gl_flags);
+ finish_xmote(gl, gl->gl_reply);
+ drop_refs++;
+ }
+- spin_lock(&gl->gl_lockref.lock);
+ if (test_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) &&
+ gl->gl_state != LM_ST_UNLOCKED &&
+ gl->gl_demote_state != LM_ST_EXCLUSIVE) {
+@@ -2148,8 +2184,11 @@ static void thaw_glock(struct gfs2_glock *gl)
+ return;
+ if (!lockref_get_not_dead(&gl->gl_lockref))
+ return;
++
++ spin_lock(&gl->gl_lockref.lock);
+ set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
+- gfs2_glock_queue_work(gl, 0);
++ __gfs2_glock_queue_work(gl, 0);
++ spin_unlock(&gl->gl_lockref.lock);
+ }
+
+ /**
+@@ -2225,6 +2264,8 @@ void gfs2_gl_hash_clear(struct gfs2_sbd *sdp)
+ wait_event_timeout(sdp->sd_kill_wait,
+ atomic_read(&sdp->sd_glock_disposal) == 0,
+ HZ * 600);
++ gfs2_lm_unmount(sdp);
++ gfs2_free_dead_glocks(sdp);
+ glock_hash_walk(dump_glock_func, sdp);
+ }
+
+diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h
+index 0114f3e0ebe01..86987a59a0580 100644
+--- a/fs/gfs2/glock.h
++++ b/fs/gfs2/glock.h
+@@ -252,6 +252,7 @@ void gfs2_gl_dq_holders(struct gfs2_sbd *sdp);
+ void gfs2_glock_thaw(struct gfs2_sbd *sdp);
+ void gfs2_glock_add_to_lru(struct gfs2_glock *gl);
+ void gfs2_glock_free(struct gfs2_glock *gl);
++void gfs2_glock_free_later(struct gfs2_glock *gl);
+
+ int __init gfs2_glock_init(void);
+ void gfs2_glock_exit(void);
+diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
+index 45653cbc8a87d..e0e8dfeee777d 100644
+--- a/fs/gfs2/glops.c
++++ b/fs/gfs2/glops.c
+@@ -82,6 +82,9 @@ static void __gfs2_ail_flush(struct gfs2_glock *gl, bool fsync,
+ GLOCK_BUG_ON(gl, !fsync && atomic_read(&gl->gl_ail_count));
+ spin_unlock(&sdp->sd_ail_lock);
+ gfs2_log_unlock(sdp);
++
++ if (gfs2_withdrawing(sdp))
++ gfs2_withdraw(sdp);
+ }
+
+
+diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
+index 95a334d64da2a..60abd7050c998 100644
+--- a/fs/gfs2/incore.h
++++ b/fs/gfs2/incore.h
+@@ -838,6 +838,7 @@ struct gfs2_sbd {
+ /* For quiescing the filesystem */
+ struct gfs2_holder sd_freeze_gh;
+ struct mutex sd_freeze_mutex;
++ struct list_head sd_dead_glocks;
+
+ char sd_fsname[GFS2_FSNAME_LEN + 3 * sizeof(int) + 2];
+ char sd_table_name[GFS2_FSNAME_LEN];
+diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
+index d1ac5d0679ea6..e028e55e67d95 100644
+--- a/fs/gfs2/lock_dlm.c
++++ b/fs/gfs2/lock_dlm.c
+@@ -121,6 +121,11 @@ static void gdlm_ast(void *arg)
+ struct gfs2_glock *gl = arg;
+ unsigned ret = gl->gl_state;
+
++ /* If the glock is dead, we only react to a dlm_unlock() reply. */
++ if (__lockref_is_dead(&gl->gl_lockref) &&
++ gl->gl_lksb.sb_status != -DLM_EUNLOCK)
++ return;
++
+ gfs2_update_reply_times(gl);
+ BUG_ON(gl->gl_lksb.sb_flags & DLM_SBF_DEMOTED);
+
+@@ -171,6 +176,9 @@ static void gdlm_bast(void *arg, int mode)
+ {
+ struct gfs2_glock *gl = arg;
+
++ if (__lockref_is_dead(&gl->gl_lockref))
++ return;
++
+ switch (mode) {
+ case DLM_LOCK_EX:
+ gfs2_glock_cb(gl, LM_ST_UNLOCKED);
+@@ -291,8 +299,12 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
+ struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+ int error;
+
+- if (gl->gl_lksb.sb_lkid == 0)
+- goto out_free;
++ BUG_ON(!__lockref_is_dead(&gl->gl_lockref));
++
++ if (gl->gl_lksb.sb_lkid == 0) {
++ gfs2_glock_free(gl);
++ return;
++ }
+
+ clear_bit(GLF_BLOCKING, &gl->gl_flags);
+ gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT);
+@@ -300,13 +312,17 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
+ gfs2_update_request_times(gl);
+
+ /* don't want to call dlm if we've unmounted the lock protocol */
+- if (test_bit(DFL_UNMOUNT, &ls->ls_recover_flags))
+- goto out_free;
++ if (test_bit(DFL_UNMOUNT, &ls->ls_recover_flags)) {
++ gfs2_glock_free(gl);
++ return;
++ }
+ /* don't want to skip dlm_unlock writing the lvb when lock has one */
+
+ if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) &&
+- !gl->gl_lksb.sb_lvbptr)
+- goto out_free;
++ !gl->gl_lksb.sb_lvbptr) {
++ gfs2_glock_free_later(gl);
++ return;
++ }
+
+ again:
+ error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK,
+@@ -321,10 +337,6 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
+ gl->gl_name.ln_type,
+ (unsigned long long)gl->gl_name.ln_number, error);
+ }
+- return;
+-
+-out_free:
+- gfs2_glock_free(gl);
+ }
+
+ static void gdlm_cancel(struct gfs2_glock *gl)
+diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
+index 1281e60be6390..db0df091a6a76 100644
+--- a/fs/gfs2/ops_fstype.c
++++ b/fs/gfs2/ops_fstype.c
+@@ -136,6 +136,7 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)
+ atomic_set(&sdp->sd_log_in_flight, 0);
+ init_waitqueue_head(&sdp->sd_log_flush_wait);
+ mutex_init(&sdp->sd_freeze_mutex);
++ INIT_LIST_HEAD(&sdp->sd_dead_glocks);
+
+ return sdp;
+
+diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
+index e5f79466340d2..2d780b4701a23 100644
+--- a/fs/gfs2/super.c
++++ b/fs/gfs2/super.c
+@@ -646,10 +646,7 @@ static void gfs2_put_super(struct super_block *sb)
+ gfs2_gl_hash_clear(sdp);
+ truncate_inode_pages_final(&sdp->sd_aspace);
+ gfs2_delete_debugfs_file(sdp);
+- /* Unmount the locking protocol */
+- gfs2_lm_unmount(sdp);
+
+- /* At this point, we're through participating in the lockspace */
+ gfs2_sys_fs_del(sdp);
+ free_sbd(sdp);
+ }
+diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c
+index f52141ce94853..fc3ecb180ac53 100644
+--- a/fs/gfs2/util.c
++++ b/fs/gfs2/util.c
+@@ -350,7 +350,6 @@ int gfs2_withdraw(struct gfs2_sbd *sdp)
+ fs_err(sdp, "telling LM to unmount\n");
+ lm->lm_unmount(sdp);
+ }
+- set_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags);
+ fs_err(sdp, "File system withdrawn\n");
+ dump_stack();
+ clear_bit(SDF_WITHDRAW_IN_PROG, &sdp->sd_flags);
+diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c
+index 00224f3a8d6e7..defb4162c3d5b 100644
+--- a/fs/jffs2/xattr.c
++++ b/fs/jffs2/xattr.c
+@@ -1110,6 +1110,9 @@ int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname,
+ return rc;
+
+ request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size);
++ if (request > c->sector_size - c->cleanmarker_size)
++ return -ERANGE;
++
+ rc = jffs2_reserve_space(c, request, &length,
+ ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE);
+ if (rc) {
+diff --git a/fs/libfs.c b/fs/libfs.c
+index eec6031b01554..ef700d39f0f35 100644
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -240,17 +240,22 @@ const struct inode_operations simple_dir_inode_operations = {
+ };
+ EXPORT_SYMBOL(simple_dir_inode_operations);
+
+-static void offset_set(struct dentry *dentry, u32 offset)
++/* 0 is '.', 1 is '..', so always start with offset 2 or more */
++enum {
++ DIR_OFFSET_MIN = 2,
++};
++
++static void offset_set(struct dentry *dentry, long offset)
+ {
+- dentry->d_fsdata = (void *)((uintptr_t)(offset));
++ dentry->d_fsdata = (void *)offset;
+ }
+
+-static u32 dentry2offset(struct dentry *dentry)
++static long dentry2offset(struct dentry *dentry)
+ {
+- return (u32)((uintptr_t)(dentry->d_fsdata));
++ return (long)dentry->d_fsdata;
+ }
+
+-static struct lock_class_key simple_offset_xa_lock;
++static struct lock_class_key simple_offset_lock_class;
+
+ /**
+ * simple_offset_init - initialize an offset_ctx
+@@ -259,11 +264,9 @@ static struct lock_class_key simple_offset_xa_lock;
+ */
+ void simple_offset_init(struct offset_ctx *octx)
+ {
+- xa_init_flags(&octx->xa, XA_FLAGS_ALLOC1);
+- lockdep_set_class(&octx->xa.xa_lock, &simple_offset_xa_lock);
+-
+- /* 0 is '.', 1 is '..', so always start with offset 2 */
+- octx->next_offset = 2;
++ mt_init_flags(&octx->mt, MT_FLAGS_ALLOC_RANGE);
++ lockdep_set_class(&octx->mt.ma_lock, &simple_offset_lock_class);
++ octx->next_offset = DIR_OFFSET_MIN;
+ }
+
+ /**
+@@ -271,20 +274,19 @@ void simple_offset_init(struct offset_ctx *octx)
+ * @octx: directory offset ctx to be updated
+ * @dentry: new dentry being added
+ *
+- * Returns zero on success. @so_ctx and the dentry offset are updated.
++ * Returns zero on success. @octx and the dentry's offset are updated.
+ * Otherwise, a negative errno value is returned.
+ */
+ int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry)
+ {
+- static const struct xa_limit limit = XA_LIMIT(2, U32_MAX);
+- u32 offset;
++ unsigned long offset;
+ int ret;
+
+ if (dentry2offset(dentry) != 0)
+ return -EBUSY;
+
+- ret = xa_alloc_cyclic(&octx->xa, &offset, dentry, limit,
+- &octx->next_offset, GFP_KERNEL);
++ ret = mtree_alloc_cyclic(&octx->mt, &offset, dentry, DIR_OFFSET_MIN,
++ LONG_MAX, &octx->next_offset, GFP_KERNEL);
+ if (ret < 0)
+ return ret;
+
+@@ -292,6 +294,18 @@ int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry)
+ return 0;
+ }
+
++static int simple_offset_replace(struct offset_ctx *octx, struct dentry *dentry,
++ long offset)
++{
++ int ret;
++
++ ret = mtree_store(&octx->mt, offset, dentry, GFP_KERNEL);
++ if (ret)
++ return ret;
++ offset_set(dentry, offset);
++ return 0;
++}
++
+ /**
+ * simple_offset_remove - Remove an entry to a directory's offset map
+ * @octx: directory offset ctx to be updated
+@@ -300,16 +314,78 @@ int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry)
+ */
+ void simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry)
+ {
+- u32 offset;
++ long offset;
+
+ offset = dentry2offset(dentry);
+ if (offset == 0)
+ return;
+
+- xa_erase(&octx->xa, offset);
++ mtree_erase(&octx->mt, offset);
+ offset_set(dentry, 0);
+ }
+
++/**
++ * simple_offset_empty - Check if a dentry can be unlinked
++ * @dentry: dentry to be tested
++ *
++ * Returns 0 if @dentry is a non-empty directory; otherwise returns 1.
++ */
++int simple_offset_empty(struct dentry *dentry)
++{
++ struct inode *inode = d_inode(dentry);
++ struct offset_ctx *octx;
++ struct dentry *child;
++ unsigned long index;
++ int ret = 1;
++
++ if (!inode || !S_ISDIR(inode->i_mode))
++ return ret;
++
++ index = DIR_OFFSET_MIN;
++ octx = inode->i_op->get_offset_ctx(inode);
++ mt_for_each(&octx->mt, child, index, LONG_MAX) {
++ spin_lock(&child->d_lock);
++ if (simple_positive(child)) {
++ spin_unlock(&child->d_lock);
++ ret = 0;
++ break;
++ }
++ spin_unlock(&child->d_lock);
++ }
++
++ return ret;
++}
++
++/**
++ * simple_offset_rename - handle directory offsets for rename
++ * @old_dir: parent directory of source entry
++ * @old_dentry: dentry of source entry
++ * @new_dir: parent_directory of destination entry
++ * @new_dentry: dentry of destination
++ *
++ * Caller provides appropriate serialization.
++ *
++ * User space expects the directory offset value of the replaced
++ * (new) directory entry to be unchanged after a rename.
++ *
++ * Returns zero on success, a negative errno value on failure.
++ */
++int simple_offset_rename(struct inode *old_dir, struct dentry *old_dentry,
++ struct inode *new_dir, struct dentry *new_dentry)
++{
++ struct offset_ctx *old_ctx = old_dir->i_op->get_offset_ctx(old_dir);
++ struct offset_ctx *new_ctx = new_dir->i_op->get_offset_ctx(new_dir);
++ long new_offset = dentry2offset(new_dentry);
++
++ simple_offset_remove(old_ctx, old_dentry);
++
++ if (new_offset) {
++ offset_set(new_dentry, 0);
++ return simple_offset_replace(new_ctx, old_dentry, new_offset);
++ }
++ return simple_offset_add(new_ctx, old_dentry);
++}
++
+ /**
+ * simple_offset_rename_exchange - exchange rename with directory offsets
+ * @old_dir: parent of dentry being moved
+@@ -317,6 +393,9 @@ void simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry)
+ * @new_dir: destination parent
+ * @new_dentry: destination dentry
+ *
++ * This API preserves the directory offset values. Caller provides
++ * appropriate serialization.
++ *
+ * Returns zero on success. Otherwise a negative errno is returned and the
+ * rename is rolled back.
+ */
+@@ -327,18 +406,18 @@ int simple_offset_rename_exchange(struct inode *old_dir,
+ {
+ struct offset_ctx *old_ctx = old_dir->i_op->get_offset_ctx(old_dir);
+ struct offset_ctx *new_ctx = new_dir->i_op->get_offset_ctx(new_dir);
+- u32 old_index = dentry2offset(old_dentry);
+- u32 new_index = dentry2offset(new_dentry);
++ long old_index = dentry2offset(old_dentry);
++ long new_index = dentry2offset(new_dentry);
+ int ret;
+
+ simple_offset_remove(old_ctx, old_dentry);
+ simple_offset_remove(new_ctx, new_dentry);
+
+- ret = simple_offset_add(new_ctx, old_dentry);
++ ret = simple_offset_replace(new_ctx, old_dentry, new_index);
+ if (ret)
+ goto out_restore;
+
+- ret = simple_offset_add(old_ctx, new_dentry);
++ ret = simple_offset_replace(old_ctx, new_dentry, old_index);
+ if (ret) {
+ simple_offset_remove(new_ctx, old_dentry);
+ goto out_restore;
+@@ -353,10 +432,8 @@ int simple_offset_rename_exchange(struct inode *old_dir,
+ return 0;
+
+ out_restore:
+- offset_set(old_dentry, old_index);
+- xa_store(&old_ctx->xa, old_index, old_dentry, GFP_KERNEL);
+- offset_set(new_dentry, new_index);
+- xa_store(&new_ctx->xa, new_index, new_dentry, GFP_KERNEL);
++ (void)simple_offset_replace(old_ctx, old_dentry, old_index);
++ (void)simple_offset_replace(new_ctx, new_dentry, new_index);
+ return ret;
+ }
+
+@@ -369,7 +446,7 @@ int simple_offset_rename_exchange(struct inode *old_dir,
+ */
+ void simple_offset_destroy(struct offset_ctx *octx)
+ {
+- xa_destroy(&octx->xa);
++ mtree_destroy(&octx->mt);
+ }
+
+ /**
+@@ -399,15 +476,16 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence)
+
+ /* In this case, ->private_data is protected by f_pos_lock */
+ file->private_data = NULL;
+- return vfs_setpos(file, offset, U32_MAX);
++ return vfs_setpos(file, offset, LONG_MAX);
+ }
+
+-static struct dentry *offset_find_next(struct xa_state *xas)
++static struct dentry *offset_find_next(struct offset_ctx *octx, loff_t offset)
+ {
++ MA_STATE(mas, &octx->mt, offset, offset);
+ struct dentry *child, *found = NULL;
+
+ rcu_read_lock();
+- child = xas_next_entry(xas, U32_MAX);
++ child = mas_find(&mas, LONG_MAX);
+ if (!child)
+ goto out;
+ spin_lock(&child->d_lock);
+@@ -421,8 +499,8 @@ static struct dentry *offset_find_next(struct xa_state *xas)
+
+ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry)
+ {
+- u32 offset = dentry2offset(dentry);
+ struct inode *inode = d_inode(dentry);
++ long offset = dentry2offset(dentry);
+
+ return ctx->actor(ctx, dentry->d_name.name, dentry->d_name.len, offset,
+ inode->i_ino, fs_umode_to_dtype(inode->i_mode));
+@@ -430,12 +508,11 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry)
+
+ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
+ {
+- struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode);
+- XA_STATE(xas, &so_ctx->xa, ctx->pos);
++ struct offset_ctx *octx = inode->i_op->get_offset_ctx(inode);
+ struct dentry *dentry;
+
+ while (true) {
+- dentry = offset_find_next(&xas);
++ dentry = offset_find_next(octx, ctx->pos);
+ if (!dentry)
+ return ERR_PTR(-ENOENT);
+
+@@ -444,8 +521,8 @@ static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
+ break;
+ }
+
++ ctx->pos = dentry2offset(dentry) + 1;
+ dput(dentry);
+- ctx->pos = xas.xa_index + 1;
+ }
+ return NULL;
+ }
+@@ -481,7 +558,7 @@ static int offset_readdir(struct file *file, struct dir_context *ctx)
+ return 0;
+
+ /* In this case, ->private_data is protected by f_pos_lock */
+- if (ctx->pos == 2)
++ if (ctx->pos == DIR_OFFSET_MIN)
+ file->private_data = NULL;
+ else if (file->private_data == ERR_PTR(-ENOENT))
+ return 0;
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index ea3c8114245c2..d8f54eb7455e3 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -48,12 +48,10 @@ enum {
+ NFSD_MaxBlkSize,
+ NFSD_MaxConnections,
+ NFSD_Filecache,
+-#ifdef CONFIG_NFSD_V4
+ NFSD_Leasetime,
+ NFSD_Gracetime,
+ NFSD_RecoveryDir,
+ NFSD_V4EndGrace,
+-#endif
+ NFSD_MaxReserved
+ };
+
+@@ -1359,7 +1357,9 @@ static int nfsd_fill_super(struct super_block *sb, struct fs_context *fc)
+ #ifdef CONFIG_NFSD_V4
+ [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
+ [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
++#ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING
+ [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
++#endif
+ [NFSD_V4EndGrace] = {"v4_end_grace", &transaction_ops, S_IWUSR|S_IRUGO},
+ #endif
+ /* last one */ {""}
+diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
+index cfb6aca5ec383..d6e3f20e8872e 100644
+--- a/fs/nilfs2/ioctl.c
++++ b/fs/nilfs2/ioctl.c
+@@ -60,7 +60,7 @@ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs,
+ if (argv->v_nmembs == 0)
+ return 0;
+
+- if (argv->v_size > PAGE_SIZE)
++ if ((size_t)argv->v_size > PAGE_SIZE)
+ return -EINVAL;
+
+ /*
+diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
+index 2bfb08052d399..5b3f53001641d 100644
+--- a/fs/nilfs2/segment.c
++++ b/fs/nilfs2/segment.c
+@@ -2161,8 +2161,10 @@ static void nilfs_segctor_start_timer(struct nilfs_sc_info *sci)
+ {
+ spin_lock(&sci->sc_state_lock);
+ if (!(sci->sc_state & NILFS_SEGCTOR_COMMIT)) {
+- sci->sc_timer.expires = jiffies + sci->sc_interval;
+- add_timer(&sci->sc_timer);
++ if (sci->sc_task) {
++ sci->sc_timer.expires = jiffies + sci->sc_interval;
++ add_timer(&sci->sc_timer);
++ }
+ sci->sc_state |= NILFS_SEGCTOR_COMMIT;
+ }
+ spin_unlock(&sci->sc_state_lock);
+@@ -2209,19 +2211,36 @@ static int nilfs_segctor_sync(struct nilfs_sc_info *sci)
+ struct nilfs_segctor_wait_request wait_req;
+ int err = 0;
+
+- spin_lock(&sci->sc_state_lock);
+ init_wait(&wait_req.wq);
+ wait_req.err = 0;
+ atomic_set(&wait_req.done, 0);
++ init_waitqueue_entry(&wait_req.wq, current);
++
++ /*
++ * To prevent a race issue where completion notifications from the
++ * log writer thread are missed, increment the request sequence count
++ * "sc_seq_request" and insert a wait queue entry using the current
++ * sequence number into the "sc_wait_request" queue at the same time
++ * within the lock section of "sc_state_lock".
++ */
++ spin_lock(&sci->sc_state_lock);
+ wait_req.seq = ++sci->sc_seq_request;
++ add_wait_queue(&sci->sc_wait_request, &wait_req.wq);
+ spin_unlock(&sci->sc_state_lock);
+
+- init_waitqueue_entry(&wait_req.wq, current);
+- add_wait_queue(&sci->sc_wait_request, &wait_req.wq);
+- set_current_state(TASK_INTERRUPTIBLE);
+ wake_up(&sci->sc_wait_daemon);
+
+ for (;;) {
++ set_current_state(TASK_INTERRUPTIBLE);
++
++ /*
++ * Synchronize only while the log writer thread is alive.
++ * Leave flushing out after the log writer thread exits to
++ * the cleanup work in nilfs_segctor_destroy().
++ */
++ if (!sci->sc_task)
++ break;
++
+ if (atomic_read(&wait_req.done)) {
+ err = wait_req.err;
+ break;
+@@ -2237,7 +2256,7 @@ static int nilfs_segctor_sync(struct nilfs_sc_info *sci)
+ return err;
+ }
+
+-static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err)
++static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err, bool force)
+ {
+ struct nilfs_segctor_wait_request *wrq, *n;
+ unsigned long flags;
+@@ -2245,7 +2264,7 @@ static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err)
+ spin_lock_irqsave(&sci->sc_wait_request.lock, flags);
+ list_for_each_entry_safe(wrq, n, &sci->sc_wait_request.head, wq.entry) {
+ if (!atomic_read(&wrq->done) &&
+- nilfs_cnt32_ge(sci->sc_seq_done, wrq->seq)) {
++ (force || nilfs_cnt32_ge(sci->sc_seq_done, wrq->seq))) {
+ wrq->err = err;
+ atomic_set(&wrq->done, 1);
+ }
+@@ -2363,10 +2382,21 @@ int nilfs_construct_dsync_segment(struct super_block *sb, struct inode *inode,
+ */
+ static void nilfs_segctor_accept(struct nilfs_sc_info *sci)
+ {
++ bool thread_is_alive;
++
+ spin_lock(&sci->sc_state_lock);
+ sci->sc_seq_accepted = sci->sc_seq_request;
++ thread_is_alive = (bool)sci->sc_task;
+ spin_unlock(&sci->sc_state_lock);
+- del_timer_sync(&sci->sc_timer);
++
++ /*
++ * This function does not race with the log writer thread's
++ * termination. Therefore, deleting sc_timer, which should not be
++ * done after the log writer thread exits, can be done safely outside
++ * the area protected by sc_state_lock.
++ */
++ if (thread_is_alive)
++ del_timer_sync(&sci->sc_timer);
+ }
+
+ /**
+@@ -2383,7 +2413,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err)
+ if (mode == SC_LSEG_SR) {
+ sci->sc_state &= ~NILFS_SEGCTOR_COMMIT;
+ sci->sc_seq_done = sci->sc_seq_accepted;
+- nilfs_segctor_wakeup(sci, err);
++ nilfs_segctor_wakeup(sci, err, false);
+ sci->sc_flush_request = 0;
+ } else {
+ if (mode == SC_FLUSH_FILE)
+@@ -2392,7 +2422,7 @@ static void nilfs_segctor_notify(struct nilfs_sc_info *sci, int mode, int err)
+ sci->sc_flush_request &= ~FLUSH_DAT_BIT;
+
+ /* re-enable timer if checkpoint creation was not done */
+- if ((sci->sc_state & NILFS_SEGCTOR_COMMIT) &&
++ if ((sci->sc_state & NILFS_SEGCTOR_COMMIT) && sci->sc_task &&
+ time_before(jiffies, sci->sc_timer.expires))
+ add_timer(&sci->sc_timer);
+ }
+@@ -2582,6 +2612,7 @@ static int nilfs_segctor_thread(void *arg)
+ int timeout = 0;
+
+ sci->sc_timer_task = current;
++ timer_setup(&sci->sc_timer, nilfs_construction_timeout, 0);
+
+ /* start sync. */
+ sci->sc_task = current;
+@@ -2649,6 +2680,7 @@ static int nilfs_segctor_thread(void *arg)
+ end_thread:
+ /* end sync. */
+ sci->sc_task = NULL;
++ timer_shutdown_sync(&sci->sc_timer);
+ wake_up(&sci->sc_wait_task); /* for nilfs_segctor_kill_thread() */
+ spin_unlock(&sci->sc_state_lock);
+ return 0;
+@@ -2712,7 +2744,6 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct super_block *sb,
+ INIT_LIST_HEAD(&sci->sc_gc_inodes);
+ INIT_LIST_HEAD(&sci->sc_iput_queue);
+ INIT_WORK(&sci->sc_iput_work, nilfs_iput_work_func);
+- timer_setup(&sci->sc_timer, nilfs_construction_timeout, 0);
+
+ sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT;
+ sci->sc_mjcp_freq = HZ * NILFS_SC_DEFAULT_SR_FREQ;
+@@ -2766,6 +2797,13 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
+ || sci->sc_seq_request != sci->sc_seq_done);
+ spin_unlock(&sci->sc_state_lock);
+
++ /*
++ * Forcibly wake up tasks waiting in nilfs_segctor_sync(), which can
++ * be called from delayed iput() via nilfs_evict_inode() and can race
++ * with the above log writer thread termination.
++ */
++ nilfs_segctor_wakeup(sci, 0, true);
++
+ if (flush_work(&sci->sc_iput_work))
+ flag = true;
+
+@@ -2791,7 +2829,6 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
+
+ down_write(&nilfs->ns_segctor_sem);
+
+- timer_shutdown_sync(&sci->sc_timer);
+ kfree(sci);
+ }
+
+diff --git a/fs/ntfs3/dir.c b/fs/ntfs3/dir.c
+index 5cf3d9decf646..45e556fd7c54f 100644
+--- a/fs/ntfs3/dir.c
++++ b/fs/ntfs3/dir.c
+@@ -475,6 +475,7 @@ static int ntfs_readdir(struct file *file, struct dir_context *ctx)
+ vbo = (u64)bit << index_bits;
+ if (vbo >= i_size) {
+ ntfs_inode_err(dir, "Looks like your dir is corrupt");
++ ctx->pos = eod;
+ err = -EINVAL;
+ goto out;
+ }
+diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c
+index daabaad63aaf6..14284f0ed46aa 100644
+--- a/fs/ntfs3/index.c
++++ b/fs/ntfs3/index.c
+@@ -1533,6 +1533,11 @@ static int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni,
+ goto out1;
+ }
+
++ if (data_size <= le64_to_cpu(alloc->nres.data_size)) {
++ /* Reuse index. */
++ goto out;
++ }
++
+ /* Increase allocation. */
+ err = attr_set_size(ni, ATTR_ALLOC, in->name, in->name_len,
+ &indx->alloc_run, data_size, &data_size, true,
+@@ -1546,6 +1551,7 @@ static int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni,
+ if (in->name == I30_NAME)
+ i_size_write(&ni->vfs_inode, data_size);
+
++out:
+ *vbn = bit << indx->idx2vbn_bits;
+
+ return 0;
+diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c
+index eb7a8c9fba018..05f169018c4e9 100644
+--- a/fs/ntfs3/inode.c
++++ b/fs/ntfs3/inode.c
+@@ -37,7 +37,7 @@ static struct inode *ntfs_read_mft(struct inode *inode,
+ bool is_dir;
+ unsigned long ino = inode->i_ino;
+ u32 rp_fa = 0, asize, t32;
+- u16 roff, rsize, names = 0;
++ u16 roff, rsize, names = 0, links = 0;
+ const struct ATTR_FILE_NAME *fname = NULL;
+ const struct INDEX_ROOT *root;
+ struct REPARSE_DATA_BUFFER rp; // 0x18 bytes
+@@ -200,11 +200,12 @@ static struct inode *ntfs_read_mft(struct inode *inode,
+ rsize < SIZEOF_ATTRIBUTE_FILENAME)
+ goto out;
+
++ names += 1;
+ fname = Add2Ptr(attr, roff);
+ if (fname->type == FILE_NAME_DOS)
+ goto next_attr;
+
+- names += 1;
++ links += 1;
+ if (name && name->len == fname->name_len &&
+ !ntfs_cmp_names_cpu(name, (struct le_str *)&fname->name_len,
+ NULL, false))
+@@ -429,7 +430,7 @@ static struct inode *ntfs_read_mft(struct inode *inode,
+ ni->mi.dirty = true;
+ }
+
+- set_nlink(inode, names);
++ set_nlink(inode, links);
+
+ if (S_ISDIR(mode)) {
+ ni->std_fa |= FILE_ATTRIBUTE_DIRECTORY;
+diff --git a/fs/ntfs3/record.c b/fs/ntfs3/record.c
+index 6aa3a9d44df1b..6c76503edc200 100644
+--- a/fs/ntfs3/record.c
++++ b/fs/ntfs3/record.c
+@@ -534,16 +534,9 @@ bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
+ if (aoff + asize > used)
+ return false;
+
+- if (ni && is_attr_indexed(attr)) {
++ if (ni && is_attr_indexed(attr) && attr->type == ATTR_NAME) {
+ u16 links = le16_to_cpu(ni->mi.mrec->hard_links);
+- struct ATTR_FILE_NAME *fname =
+- attr->type != ATTR_NAME ?
+- NULL :
+- resident_data_ex(attr,
+- SIZEOF_ATTRIBUTE_FILENAME);
+- if (fname && fname->type == FILE_NAME_DOS) {
+- /* Do not decrease links count deleting DOS name. */
+- } else if (!links) {
++ if (!links) {
+ /* minor error. Not critical. */
+ } else {
+ ni->mi.mrec->hard_links = cpu_to_le16(links - 1);
+diff --git a/fs/ntfs3/super.c b/fs/ntfs3/super.c
+index cef5467fd9283..4643b06b1550f 100644
+--- a/fs/ntfs3/super.c
++++ b/fs/ntfs3/super.c
+@@ -1804,8 +1804,6 @@ static int __init init_ntfs_fs(void)
+ {
+ int err;
+
+- pr_info("ntfs3: Max link count %u\n", NTFS_LINK_MAX);
+-
+ if (IS_ENABLED(CONFIG_NTFS3_FS_POSIX_ACL))
+ pr_info("ntfs3: Enabled Linux POSIX ACLs support\n");
+ if (IS_ENABLED(CONFIG_NTFS3_64BIT_CLUSTER))
+diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
+index c4b65a6d41cc3..5cf1809d47bdb 100644
+--- a/fs/openpromfs/inode.c
++++ b/fs/openpromfs/inode.c
+@@ -355,10 +355,10 @@ static struct inode *openprom_iget(struct super_block *sb, ino_t ino)
+ return inode;
+ }
+
+-static int openprom_remount(struct super_block *sb, int *flags, char *data)
++static int openpromfs_reconfigure(struct fs_context *fc)
+ {
+- sync_filesystem(sb);
+- *flags |= SB_NOATIME;
++ sync_filesystem(fc->root->d_sb);
++ fc->sb_flags |= SB_NOATIME;
+ return 0;
+ }
+
+@@ -366,7 +366,6 @@ static const struct super_operations openprom_sops = {
+ .alloc_inode = openprom_alloc_inode,
+ .free_inode = openprom_free_inode,
+ .statfs = simple_statfs,
+- .remount_fs = openprom_remount,
+ };
+
+ static int openprom_fill_super(struct super_block *s, struct fs_context *fc)
+@@ -415,6 +414,7 @@ static int openpromfs_get_tree(struct fs_context *fc)
+
+ static const struct fs_context_operations openpromfs_context_ops = {
+ .get_tree = openpromfs_get_tree,
++ .reconfigure = openpromfs_reconfigure,
+ };
+
+ static int openpromfs_init_fs_context(struct fs_context *fc)
+diff --git a/fs/smb/server/mgmt/share_config.c b/fs/smb/server/mgmt/share_config.c
+index a2f0a2edceb8a..e0a6b758094fc 100644
+--- a/fs/smb/server/mgmt/share_config.c
++++ b/fs/smb/server/mgmt/share_config.c
+@@ -165,8 +165,12 @@ static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
+
+ share->path = kstrndup(ksmbd_share_config_path(resp), path_len,
+ GFP_KERNEL);
+- if (share->path)
++ if (share->path) {
+ share->path_sz = strlen(share->path);
++ while (share->path_sz > 1 &&
++ share->path[share->path_sz - 1] == '/')
++ share->path[--share->path_sz] = '\0';
++ }
+ share->create_mask = resp->create_mask;
+ share->directory_mask = resp->directory_mask;
+ share->force_create_mode = resp->force_create_mode;
+diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
+index dc729ab980dc0..2292ca6ff00b6 100644
+--- a/fs/smb/server/oplock.c
++++ b/fs/smb/server/oplock.c
+@@ -613,19 +613,24 @@ static int oplock_break_pending(struct oplock_info *opinfo, int req_op_level)
+ if (opinfo->op_state == OPLOCK_CLOSING)
+ return -ENOENT;
+ else if (opinfo->level <= req_op_level) {
+- if (opinfo->is_lease &&
+- opinfo->o_lease->state !=
+- (SMB2_LEASE_HANDLE_CACHING_LE |
+- SMB2_LEASE_READ_CACHING_LE))
++ if (opinfo->is_lease == false)
++ return 1;
++
++ if (opinfo->o_lease->state !=
++ (SMB2_LEASE_HANDLE_CACHING_LE |
++ SMB2_LEASE_READ_CACHING_LE))
+ return 1;
+ }
+ }
+
+ if (opinfo->level <= req_op_level) {
+- if (opinfo->is_lease &&
+- opinfo->o_lease->state !=
+- (SMB2_LEASE_HANDLE_CACHING_LE |
+- SMB2_LEASE_READ_CACHING_LE)) {
++ if (opinfo->is_lease == false) {
++ wake_up_oplock_break(opinfo);
++ return 1;
++ }
++ if (opinfo->o_lease->state !=
++ (SMB2_LEASE_HANDLE_CACHING_LE |
++ SMB2_LEASE_READ_CACHING_LE)) {
+ wake_up_oplock_break(opinfo);
+ return 1;
+ }
+diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h
+index 863b2e7add29e..472359a9d6756 100644
+--- a/include/drm/display/drm_dp_helper.h
++++ b/include/drm/display/drm_dp_helper.h
+@@ -463,9 +463,15 @@ struct drm_dp_aux {
+ * @is_remote: Is this AUX CH actually using sideband messaging.
+ */
+ bool is_remote;
++
++ /**
++ * @powered_down: If true then the remote endpoint is powered down.
++ */
++ bool powered_down;
+ };
+
+ int drm_dp_dpcd_probe(struct drm_dp_aux *aux, unsigned int offset);
++void drm_dp_dpcd_set_powered(struct drm_dp_aux *aux, bool powered);
+ ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
+ void *buffer, size_t size);
+ ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
+diff --git a/include/drm/drm_displayid.h b/include/drm/drm_displayid.h
+index 566497eeb3b81..bc1f6b378195f 100644
+--- a/include/drm/drm_displayid.h
++++ b/include/drm/drm_displayid.h
+@@ -30,7 +30,6 @@ struct drm_edid;
+ #define VESA_IEEE_OUI 0x3a0292
+
+ /* DisplayID Structure versions */
+-#define DISPLAY_ID_STRUCTURE_VER_12 0x12
+ #define DISPLAY_ID_STRUCTURE_VER_20 0x20
+
+ /* DisplayID Structure v1r2 Data Blocks */
+diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h
+index c0aec0d4d664e..3011d33eccbd2 100644
+--- a/include/drm/drm_mipi_dsi.h
++++ b/include/drm/drm_mipi_dsi.h
+@@ -241,9 +241,9 @@ int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi);
+ int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi);
+ int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
+ u16 value);
+-ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable);
+-ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
+- const struct drm_dsc_picture_parameter_set *pps);
++int mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable);
++int mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
++ const struct drm_dsc_picture_parameter_set *pps);
+
+ ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
+ size_t size);
+diff --git a/include/linux/acpi.h b/include/linux/acpi.h
+index b7165e52b3c68..de1263b1da3bc 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -573,9 +573,13 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
+ #define OSC_SB_CPCV2_SUPPORT 0x00000040
+ #define OSC_SB_PCLPI_SUPPORT 0x00000080
+ #define OSC_SB_OSLPI_SUPPORT 0x00000100
++#define OSC_SB_FAST_THERMAL_SAMPLING_SUPPORT 0x00000200
++#define OSC_SB_OVER_16_PSTATES_SUPPORT 0x00000400
++#define OSC_SB_GED_SUPPORT 0x00000800
+ #define OSC_SB_CPC_DIVERSE_HIGH_SUPPORT 0x00001000
+-#define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00002000
++#define OSC_SB_IRQ_RESOURCE_SOURCE_SUPPORT 0x00002000
+ #define OSC_SB_CPC_FLEXIBLE_ADR_SPACE 0x00004000
++#define OSC_SB_GENERIC_INITIATOR_SUPPORT 0x00020000
+ #define OSC_SB_NATIVE_USB4_SUPPORT 0x00040000
+ #define OSC_SB_PRM_SUPPORT 0x00200000
+ #define OSC_SB_FFH_OPR_SUPPORT 0x00400000
+diff --git a/include/linux/bitops.h b/include/linux/bitops.h
+index 2ba557e067fe6..f7f5a783da2aa 100644
+--- a/include/linux/bitops.h
++++ b/include/linux/bitops.h
+@@ -80,6 +80,7 @@ __check_bitop_pr(__test_and_set_bit);
+ __check_bitop_pr(__test_and_clear_bit);
+ __check_bitop_pr(__test_and_change_bit);
+ __check_bitop_pr(test_bit);
++__check_bitop_pr(test_bit_acquire);
+
+ #undef __check_bitop_pr
+
+diff --git a/include/linux/cpu.h b/include/linux/cpu.h
+index 8654714421a0d..75f0344bd3b94 100644
+--- a/include/linux/cpu.h
++++ b/include/linux/cpu.h
+@@ -219,7 +219,18 @@ void cpuhp_report_idle_dead(void);
+ static inline void cpuhp_report_idle_dead(void) { }
+ #endif /* #ifdef CONFIG_HOTPLUG_CPU */
+
++#ifdef CONFIG_CPU_MITIGATIONS
+ extern bool cpu_mitigations_off(void);
+ extern bool cpu_mitigations_auto_nosmt(void);
++#else
++static inline bool cpu_mitigations_off(void)
++{
++ return true;
++}
++static inline bool cpu_mitigations_auto_nosmt(void)
++{
++ return false;
++}
++#endif
+
+ #endif /* _LINUX_CPU_H_ */
+diff --git a/include/linux/dev_printk.h b/include/linux/dev_printk.h
+index 6bfe70decc9fb..ae80a303c216b 100644
+--- a/include/linux/dev_printk.h
++++ b/include/linux/dev_printk.h
+@@ -129,6 +129,16 @@ void _dev_info(const struct device *dev, const char *fmt, ...)
+ _dev_printk(level, dev, fmt, ##__VA_ARGS__); \
+ })
+
++/*
++ * Dummy dev_printk for disabled debugging statements to use whilst maintaining
++ * gcc's format checking.
++ */
++#define dev_no_printk(level, dev, fmt, ...) \
++ ({ \
++ if (0) \
++ _dev_printk(level, dev, fmt, ##__VA_ARGS__); \
++ })
++
+ /*
+ * #defines for all the dev_<level> macros to prefix with whatever
+ * possible use of #define dev_fmt(fmt) ...
+@@ -158,10 +168,7 @@ void _dev_info(const struct device *dev, const char *fmt, ...)
+ dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
+ #else
+ #define dev_dbg(dev, fmt, ...) \
+-({ \
+- if (0) \
+- dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
+-})
++ dev_no_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
+ #endif
+
+ #ifdef CONFIG_PRINTK
+@@ -247,20 +254,14 @@ do { \
+ } while (0)
+ #else
+ #define dev_dbg_ratelimited(dev, fmt, ...) \
+-do { \
+- if (0) \
+- dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
+-} while (0)
++ dev_no_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
+ #endif
+
+ #ifdef VERBOSE_DEBUG
+ #define dev_vdbg dev_dbg
+ #else
+ #define dev_vdbg(dev, fmt, ...) \
+-({ \
+- if (0) \
+- dev_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__); \
+-})
++ dev_no_printk(KERN_DEBUG, dev, dev_fmt(fmt), ##__VA_ARGS__)
+ #endif
+
+ /*
+diff --git a/include/linux/fb.h b/include/linux/fb.h
+index 05dc9624897df..25ca209e4d21d 100644
+--- a/include/linux/fb.h
++++ b/include/linux/fb.h
+@@ -686,6 +686,10 @@ extern int fb_deferred_io_fsync(struct file *file, loff_t start,
+ __FB_GEN_DEFAULT_DEFERRED_OPS_RDWR(__prefix, __damage_range, sys) \
+ __FB_GEN_DEFAULT_DEFERRED_OPS_DRAW(__prefix, __damage_area, sys)
+
++#define FB_GEN_DEFAULT_DEFERRED_DMAMEM_OPS(__prefix, __damage_range, __damage_area) \
++ __FB_GEN_DEFAULT_DEFERRED_OPS_RDWR(__prefix, __damage_range, sys) \
++ __FB_GEN_DEFAULT_DEFERRED_OPS_DRAW(__prefix, __damage_area, sys)
++
+ /*
+ * Initializes struct fb_ops for deferred I/O.
+ */
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 08ecac9d7b8ba..10e32c8ef1e9c 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -43,6 +43,7 @@
+ #include <linux/cred.h>
+ #include <linux/mnt_idmapping.h>
+ #include <linux/slab.h>
++#include <linux/maple_tree.h>
+
+ #include <asm/byteorder.h>
+ #include <uapi/linux/fs.h>
+@@ -3259,13 +3260,16 @@ extern ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
+ const void __user *from, size_t count);
+
+ struct offset_ctx {
+- struct xarray xa;
+- u32 next_offset;
++ struct maple_tree mt;
++ unsigned long next_offset;
+ };
+
+ void simple_offset_init(struct offset_ctx *octx);
+ int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry);
+ void simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry);
++int simple_offset_empty(struct dentry *dentry);
++int simple_offset_rename(struct inode *old_dir, struct dentry *old_dentry,
++ struct inode *new_dir, struct dentry *new_dentry);
+ int simple_offset_rename_exchange(struct inode *old_dir,
+ struct dentry *old_dentry,
+ struct inode *new_dir,
+diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
+index 83c4d060a5596..b69771a2e4e74 100644
+--- a/include/linux/ieee80211.h
++++ b/include/linux/ieee80211.h
+@@ -5145,7 +5145,7 @@ static inline bool ieee80211_mle_basic_sta_prof_size_ok(const u8 *data,
+ info_len += 1;
+
+ return prof->sta_info_len >= info_len &&
+- fixed + prof->sta_info_len <= len;
++ fixed + prof->sta_info_len - 1 <= len;
+ }
+
+ /**
+diff --git a/include/linux/ksm.h b/include/linux/ksm.h
+index 401348e9f92b4..7e2b1de3996ac 100644
+--- a/include/linux/ksm.h
++++ b/include/linux/ksm.h
+@@ -59,6 +59,14 @@ static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm)
+ return 0;
+ }
+
++static inline int ksm_execve(struct mm_struct *mm)
++{
++ if (test_bit(MMF_VM_MERGE_ANY, &mm->flags))
++ return __ksm_enter(mm);
++
++ return 0;
++}
++
+ static inline void ksm_exit(struct mm_struct *mm)
+ {
+ if (test_bit(MMF_VM_MERGEABLE, &mm->flags))
+@@ -107,6 +115,11 @@ static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm)
+ return 0;
+ }
+
++static inline int ksm_execve(struct mm_struct *mm)
++{
++ return 0;
++}
++
+ static inline void ksm_exit(struct mm_struct *mm)
+ {
+ }
+diff --git a/include/linux/maple_tree.h b/include/linux/maple_tree.h
+index b3d63123b945b..a53ad4dabd7e8 100644
+--- a/include/linux/maple_tree.h
++++ b/include/linux/maple_tree.h
+@@ -171,6 +171,7 @@ enum maple_type {
+ #define MT_FLAGS_LOCK_IRQ 0x100
+ #define MT_FLAGS_LOCK_BH 0x200
+ #define MT_FLAGS_LOCK_EXTERN 0x300
++#define MT_FLAGS_ALLOC_WRAPPED 0x0800
+
+ #define MAPLE_HEIGHT_MAX 31
+
+@@ -319,6 +320,9 @@ int mtree_insert_range(struct maple_tree *mt, unsigned long first,
+ int mtree_alloc_range(struct maple_tree *mt, unsigned long *startp,
+ void *entry, unsigned long size, unsigned long min,
+ unsigned long max, gfp_t gfp);
++int mtree_alloc_cyclic(struct maple_tree *mt, unsigned long *startp,
++ void *entry, unsigned long range_lo, unsigned long range_hi,
++ unsigned long *next, gfp_t gfp);
+ int mtree_alloc_rrange(struct maple_tree *mt, unsigned long *startp,
+ void *entry, unsigned long size, unsigned long min,
+ unsigned long max, gfp_t gfp);
+@@ -499,6 +503,9 @@ void *mas_find_range(struct ma_state *mas, unsigned long max);
+ void *mas_find_rev(struct ma_state *mas, unsigned long min);
+ void *mas_find_range_rev(struct ma_state *mas, unsigned long max);
+ int mas_preallocate(struct ma_state *mas, void *entry, gfp_t gfp);
++int mas_alloc_cyclic(struct ma_state *mas, unsigned long *startp,
++ void *entry, unsigned long range_lo, unsigned long range_hi,
++ unsigned long *next, gfp_t gfp);
+
+ bool mas_nomem(struct ma_state *mas, gfp_t gfp);
+ void mas_pause(struct ma_state *mas);
+diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
+index 41f03b352401e..38d425a187fa3 100644
+--- a/include/linux/mlx5/driver.h
++++ b/include/linux/mlx5/driver.h
+@@ -861,6 +861,7 @@ struct mlx5_cmd_work_ent {
+ void *context;
+ int idx;
+ struct completion handling;
++ struct completion slotted;
+ struct completion done;
+ struct mlx5_cmd *cmd;
+ struct work_struct work;
+diff --git a/include/linux/numa.h b/include/linux/numa.h
+index 915033a757315..1d43371fafd2f 100644
+--- a/include/linux/numa.h
++++ b/include/linux/numa.h
+@@ -36,12 +36,7 @@ int memory_add_physaddr_to_nid(u64 start);
+ int phys_to_target_node(u64 start);
+ #endif
+
+-#ifndef numa_fill_memblks
+-static inline int __init numa_fill_memblks(u64 start, u64 end)
+-{
+- return NUMA_NO_MEMBLK;
+-}
+-#endif
++int numa_fill_memblks(u64 start, u64 end);
+
+ #else /* !CONFIG_NUMA */
+ static inline int numa_nearest_node(int node, unsigned int state)
+diff --git a/include/linux/overflow.h b/include/linux/overflow.h
+index 51af56522915e..ab4fa77516236 100644
+--- a/include/linux/overflow.h
++++ b/include/linux/overflow.h
+@@ -321,7 +321,7 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
+ * @count: Number of elements in the array; must be compile-time const.
+ * @initializer: initializer expression (could be empty for no init).
+ */
+-#define _DEFINE_FLEX(type, name, member, count, initializer) \
++#define _DEFINE_FLEX(type, name, member, count, initializer...) \
+ _Static_assert(__builtin_constant_p(count), \
+ "onstack flex array members require compile-time const count"); \
+ union { \
+@@ -331,8 +331,8 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
+ type *name = (type *)&name##_u
+
+ /**
+- * DEFINE_FLEX() - Define an on-stack instance of structure with a trailing
+- * flexible array member.
++ * DEFINE_RAW_FLEX() - Define an on-stack instance of structure with a trailing
++ * flexible array member, when it does not have a __counted_by annotation.
+ *
+ * @type: structure type name, including "struct" keyword.
+ * @name: Name for a variable to define.
+@@ -343,7 +343,24 @@ static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend)
+ * flexible array member.
+ * Use __struct_size(@name) to get compile-time size of it afterwards.
+ */
+-#define DEFINE_FLEX(type, name, member, count) \
++#define DEFINE_RAW_FLEX(type, name, member, count) \
+ _DEFINE_FLEX(type, name, member, count, = {})
+
++/**
++ * DEFINE_FLEX() - Define an on-stack instance of structure with a trailing
++ * flexible array member.
++ *
++ * @TYPE: structure type name, including "struct" keyword.
++ * @NAME: Name for a variable to define.
++ * @MEMBER: Name of the array member.
++ * @COUNTER: Name of the __counted_by member.
++ * @COUNT: Number of elements in the array; must be compile-time const.
++ *
++ * Define a zeroed, on-stack, instance of @TYPE structure with a trailing
++ * flexible array member.
++ * Use __struct_size(@NAME) to get compile-time size of it afterwards.
++ */
++#define DEFINE_FLEX(TYPE, NAME, MEMBER, COUNTER, COUNT) \
++ _DEFINE_FLEX(TYPE, NAME, MEMBER, COUNT, = { .obj.COUNTER = COUNT, })
++
+ #endif /* __LINUX_OVERFLOW_H */
+diff --git a/include/linux/printk.h b/include/linux/printk.h
+index 955e31860095e..2fde40cc96778 100644
+--- a/include/linux/printk.h
++++ b/include/linux/printk.h
+@@ -126,7 +126,7 @@ struct va_format {
+ #define no_printk(fmt, ...) \
+ ({ \
+ if (0) \
+- printk(fmt, ##__VA_ARGS__); \
++ _printk(fmt, ##__VA_ARGS__); \
+ 0; \
+ })
+
+diff --git a/include/linux/pwm.h b/include/linux/pwm.h
+index fcc2c4496f731..07af6910bdced 100644
+--- a/include/linux/pwm.h
++++ b/include/linux/pwm.h
+@@ -271,7 +271,6 @@ struct pwm_ops {
+ * @id: unique number of this PWM chip
+ * @npwm: number of PWMs controlled by this chip
+ * @of_xlate: request a PWM device given a device tree PWM specifier
+- * @of_pwm_n_cells: number of cells expected in the device tree PWM specifier
+ * @atomic: can the driver's ->apply() be called in atomic context
+ * @pwms: array of PWM devices allocated by the framework
+ */
+@@ -284,13 +283,17 @@ struct pwm_chip {
+
+ struct pwm_device * (*of_xlate)(struct pwm_chip *chip,
+ const struct of_phandle_args *args);
+- unsigned int of_pwm_n_cells;
+ bool atomic;
+
+ /* only used internally by the PWM framework */
+ struct pwm_device *pwms;
+ };
+
++static inline struct device *pwmchip_parent(const struct pwm_chip *chip)
++{
++ return chip->dev;
++}
++
+ #if IS_ENABLED(CONFIG_PWM)
+ /* PWM user APIs */
+ int pwm_apply_might_sleep(struct pwm_device *pwm, const struct pwm_state *state);
+diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
+index dee5ad6e48c5a..c0d74f97fd187 100644
+--- a/include/linux/stmmac.h
++++ b/include/linux/stmmac.h
+@@ -117,7 +117,6 @@ struct stmmac_axi {
+
+ #define EST_GCL 1024
+ struct stmmac_est {
+- struct mutex lock;
+ int enable;
+ u32 btr_reserve[2];
+ u32 btr_offset[2];
+@@ -127,6 +126,7 @@ struct stmmac_est {
+ u32 gcl_unaligned[EST_GCL];
+ u32 gcl[EST_GCL];
+ u32 gcl_size;
++ u32 max_sdu[MTL_MAX_TX_QUEUES];
+ };
+
+ struct stmmac_rxq_cfg {
+diff --git a/include/net/ax25.h b/include/net/ax25.h
+index 0d939e5aee4ec..c2a85fd3f5ea4 100644
+--- a/include/net/ax25.h
++++ b/include/net/ax25.h
+@@ -216,7 +216,7 @@ typedef struct {
+ struct ctl_table;
+
+ typedef struct ax25_dev {
+- struct ax25_dev *next;
++ struct list_head list;
+
+ struct net_device *dev;
+ netdevice_tracker dev_tracker;
+@@ -330,7 +330,6 @@ int ax25_addr_size(const ax25_digi *);
+ void ax25_digi_invert(const ax25_digi *, ax25_digi *);
+
+ /* ax25_dev.c */
+-extern ax25_dev *ax25_dev_list;
+ extern spinlock_t ax25_dev_lock;
+
+ #if IS_ENABLED(CONFIG_AX25)
+diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
+index eaec5d6caa29d..b3228bd6cd6be 100644
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -285,7 +285,7 @@ void bt_err_ratelimited(const char *fmt, ...);
+ bt_err_ratelimited("%s: " fmt, bt_dev_name(hdev), ##__VA_ARGS__)
+
+ /* Connection and socket states */
+-enum {
++enum bt_sock_state {
+ BT_CONNECTED = 1, /* Equal to TCP_ESTABLISHED to make net code happy */
+ BT_OPEN,
+ BT_BOUND,
+diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
+index f9db2d1ca5d37..9eb3d2360b1ae 100644
+--- a/include/net/bluetooth/hci.h
++++ b/include/net/bluetooth/hci.h
+@@ -33,9 +33,6 @@
+ #define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4)
+
+ #define HCI_LINK_KEY_SIZE 16
+-#define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE)
+-
+-#define HCI_MAX_AMP_ASSOC_SIZE 672
+
+ #define HCI_MAX_CPB_DATA_SIZE 252
+
+@@ -71,26 +68,6 @@
+ #define HCI_SMD 9
+ #define HCI_VIRTIO 10
+
+-/* HCI controller types */
+-#define HCI_PRIMARY 0x00
+-#define HCI_AMP 0x01
+-
+-/* First BR/EDR Controller shall have ID = 0 */
+-#define AMP_ID_BREDR 0x00
+-
+-/* AMP controller types */
+-#define AMP_TYPE_BREDR 0x00
+-#define AMP_TYPE_80211 0x01
+-
+-/* AMP controller status */
+-#define AMP_STATUS_POWERED_DOWN 0x00
+-#define AMP_STATUS_BLUETOOTH_ONLY 0x01
+-#define AMP_STATUS_NO_CAPACITY 0x02
+-#define AMP_STATUS_LOW_CAPACITY 0x03
+-#define AMP_STATUS_MEDIUM_CAPACITY 0x04
+-#define AMP_STATUS_HIGH_CAPACITY 0x05
+-#define AMP_STATUS_FULL_CAPACITY 0x06
+-
+ /* HCI device quirks */
+ enum {
+ /* When this quirk is set, the HCI Reset command is send when
+@@ -527,7 +504,6 @@ enum {
+ #define ESCO_LINK 0x02
+ /* Low Energy links do not have defined link type. Use invented one */
+ #define LE_LINK 0x80
+-#define AMP_LINK 0x81
+ #define ISO_LINK 0x82
+ #define INVALID_LINK 0xff
+
+@@ -943,56 +919,6 @@ struct hci_cp_io_capability_neg_reply {
+ __u8 reason;
+ } __packed;
+
+-#define HCI_OP_CREATE_PHY_LINK 0x0435
+-struct hci_cp_create_phy_link {
+- __u8 phy_handle;
+- __u8 key_len;
+- __u8 key_type;
+- __u8 key[HCI_AMP_LINK_KEY_SIZE];
+-} __packed;
+-
+-#define HCI_OP_ACCEPT_PHY_LINK 0x0436
+-struct hci_cp_accept_phy_link {
+- __u8 phy_handle;
+- __u8 key_len;
+- __u8 key_type;
+- __u8 key[HCI_AMP_LINK_KEY_SIZE];
+-} __packed;
+-
+-#define HCI_OP_DISCONN_PHY_LINK 0x0437
+-struct hci_cp_disconn_phy_link {
+- __u8 phy_handle;
+- __u8 reason;
+-} __packed;
+-
+-struct ext_flow_spec {
+- __u8 id;
+- __u8 stype;
+- __le16 msdu;
+- __le32 sdu_itime;
+- __le32 acc_lat;
+- __le32 flush_to;
+-} __packed;
+-
+-#define HCI_OP_CREATE_LOGICAL_LINK 0x0438
+-#define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439
+-struct hci_cp_create_accept_logical_link {
+- __u8 phy_handle;
+- struct ext_flow_spec tx_flow_spec;
+- struct ext_flow_spec rx_flow_spec;
+-} __packed;
+-
+-#define HCI_OP_DISCONN_LOGICAL_LINK 0x043a
+-struct hci_cp_disconn_logical_link {
+- __le16 log_handle;
+-} __packed;
+-
+-#define HCI_OP_LOGICAL_LINK_CANCEL 0x043b
+-struct hci_cp_logical_link_cancel {
+- __u8 phy_handle;
+- __u8 flow_spec_id;
+-} __packed;
+-
+ #define HCI_OP_ENHANCED_SETUP_SYNC_CONN 0x043d
+ struct hci_coding_format {
+ __u8 id;
+@@ -1614,46 +1540,6 @@ struct hci_rp_read_enc_key_size {
+ __u8 key_size;
+ } __packed;
+
+-#define HCI_OP_READ_LOCAL_AMP_INFO 0x1409
+-struct hci_rp_read_local_amp_info {
+- __u8 status;
+- __u8 amp_status;
+- __le32 total_bw;
+- __le32 max_bw;
+- __le32 min_latency;
+- __le32 max_pdu;
+- __u8 amp_type;
+- __le16 pal_cap;
+- __le16 max_assoc_size;
+- __le32 max_flush_to;
+- __le32 be_flush_to;
+-} __packed;
+-
+-#define HCI_OP_READ_LOCAL_AMP_ASSOC 0x140a
+-struct hci_cp_read_local_amp_assoc {
+- __u8 phy_handle;
+- __le16 len_so_far;
+- __le16 max_len;
+-} __packed;
+-struct hci_rp_read_local_amp_assoc {
+- __u8 status;
+- __u8 phy_handle;
+- __le16 rem_len;
+- __u8 frag[];
+-} __packed;
+-
+-#define HCI_OP_WRITE_REMOTE_AMP_ASSOC 0x140b
+-struct hci_cp_write_remote_amp_assoc {
+- __u8 phy_handle;
+- __le16 len_so_far;
+- __le16 rem_len;
+- __u8 frag[];
+-} __packed;
+-struct hci_rp_write_remote_amp_assoc {
+- __u8 status;
+- __u8 phy_handle;
+-} __packed;
+-
+ #define HCI_OP_GET_MWS_TRANSPORT_CONFIG 0x140c
+
+ #define HCI_OP_ENABLE_DUT_MODE 0x1803
+@@ -2034,7 +1920,7 @@ struct hci_cp_le_set_ext_adv_data {
+ __u8 operation;
+ __u8 frag_pref;
+ __u8 length;
+- __u8 data[];
++ __u8 data[] __counted_by(length);
+ } __packed;
+
+ #define HCI_OP_LE_SET_EXT_SCAN_RSP_DATA 0x2038
+@@ -2043,7 +1929,7 @@ struct hci_cp_le_set_ext_scan_rsp_data {
+ __u8 operation;
+ __u8 frag_pref;
+ __u8 length;
+- __u8 data[];
++ __u8 data[] __counted_by(length);
+ } __packed;
+
+ #define HCI_OP_LE_SET_EXT_ADV_ENABLE 0x2039
+@@ -2069,7 +1955,7 @@ struct hci_cp_le_set_per_adv_data {
+ __u8 handle;
+ __u8 operation;
+ __u8 length;
+- __u8 data[];
++ __u8 data[] __counted_by(length);
+ } __packed;
+
+ #define HCI_OP_LE_SET_PER_ADV_ENABLE 0x2040
+@@ -2170,7 +2056,7 @@ struct hci_cis {
+
+ struct hci_cp_le_create_cis {
+ __u8 num_cis;
+- struct hci_cis cis[];
++ struct hci_cis cis[] __counted_by(num_cis);
+ } __packed;
+
+ #define HCI_OP_LE_REMOVE_CIG 0x2065
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index 8504e10f51700..5277c6d5134ca 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -1,7 +1,7 @@
+ /*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
+- Copyright 2023 NXP
++ Copyright 2023-2024 NXP
+
+ Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
+
+@@ -126,7 +126,6 @@ enum suspended_state {
+ struct hci_conn_hash {
+ struct list_head list;
+ unsigned int acl_num;
+- unsigned int amp_num;
+ unsigned int sco_num;
+ unsigned int iso_num;
+ unsigned int le_num;
+@@ -247,6 +246,7 @@ struct adv_info {
+ bool periodic;
+ __u8 mesh;
+ __u8 instance;
++ __u8 handle;
+ __u32 flags;
+ __u16 timeout;
+ __u16 remaining_time;
+@@ -341,14 +341,6 @@ struct adv_monitor {
+ /* Default authenticated payload timeout 30s */
+ #define DEFAULT_AUTH_PAYLOAD_TIMEOUT 0x0bb8
+
+-struct amp_assoc {
+- __u16 len;
+- __u16 offset;
+- __u16 rem_len;
+- __u16 len_so_far;
+- __u8 data[HCI_MAX_AMP_ASSOC_SIZE];
+-};
+-
+ #define HCI_MAX_PAGES 3
+
+ struct hci_dev {
+@@ -361,7 +353,6 @@ struct hci_dev {
+ unsigned long flags;
+ __u16 id;
+ __u8 bus;
+- __u8 dev_type;
+ bdaddr_t bdaddr;
+ bdaddr_t setup_addr;
+ bdaddr_t public_addr;
+@@ -467,21 +458,6 @@ struct hci_dev {
+ __u16 sniff_min_interval;
+ __u16 sniff_max_interval;
+
+- __u8 amp_status;
+- __u32 amp_total_bw;
+- __u32 amp_max_bw;
+- __u32 amp_min_latency;
+- __u32 amp_max_pdu;
+- __u8 amp_type;
+- __u16 amp_pal_cap;
+- __u16 amp_assoc_size;
+- __u32 amp_max_flush_to;
+- __u32 amp_be_flush_to;
+-
+- struct amp_assoc loc_assoc;
+-
+- __u8 flow_ctl_mode;
+-
+ unsigned int auto_accept_delay;
+
+ unsigned long quirks;
+@@ -501,11 +477,6 @@ struct hci_dev {
+ unsigned int le_pkts;
+ unsigned int iso_pkts;
+
+- __u16 block_len;
+- __u16 block_mtu;
+- __u16 num_blocks;
+- __u16 block_cnt;
+-
+ unsigned long acl_last_tx;
+ unsigned long sco_last_tx;
+ unsigned long le_last_tx;
+@@ -778,7 +749,6 @@ struct hci_conn {
+ void *l2cap_data;
+ void *sco_data;
+ void *iso_data;
+- struct amp_mgr *amp_mgr;
+
+ struct list_head link_list;
+ struct hci_conn *parent;
+@@ -805,7 +775,6 @@ struct hci_chan {
+ struct sk_buff_head data_q;
+ unsigned int sent;
+ __u8 state;
+- bool amp;
+ };
+
+ struct hci_conn_params {
+@@ -1014,9 +983,6 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
+ case ACL_LINK:
+ h->acl_num++;
+ break;
+- case AMP_LINK:
+- h->amp_num++;
+- break;
+ case LE_LINK:
+ h->le_num++;
+ if (c->role == HCI_ROLE_SLAVE)
+@@ -1043,9 +1009,6 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
+ case ACL_LINK:
+ h->acl_num--;
+ break;
+- case AMP_LINK:
+- h->amp_num--;
+- break;
+ case LE_LINK:
+ h->le_num--;
+ if (c->role == HCI_ROLE_SLAVE)
+@@ -1067,8 +1030,6 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
+ switch (type) {
+ case ACL_LINK:
+ return h->acl_num;
+- case AMP_LINK:
+- return h->amp_num;
+ case LE_LINK:
+ return h->le_num;
+ case SCO_LINK:
+@@ -1085,7 +1046,7 @@ static inline unsigned int hci_conn_count(struct hci_dev *hdev)
+ {
+ struct hci_conn_hash *c = &hdev->conn_hash;
+
+- return c->acl_num + c->amp_num + c->sco_num + c->le_num + c->iso_num;
++ return c->acl_num + c->sco_num + c->le_num + c->iso_num;
+ }
+
+ static inline bool hci_conn_valid(struct hci_dev *hdev, struct hci_conn *conn)
+@@ -1533,8 +1494,8 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
+ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
+ __u8 dst_type, struct bt_iso_qos *qos,
+ __u8 data_len, __u8 *data);
+-int hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type,
+- __u8 sid, struct bt_iso_qos *qos);
++struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
++ __u8 dst_type, __u8 sid, struct bt_iso_qos *qos);
+ int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
+ struct bt_iso_qos *qos,
+ __u16 sync_handle, __u8 num_bis, __u8 bis[]);
+@@ -1611,10 +1572,6 @@ static inline void hci_conn_drop(struct hci_conn *conn)
+ }
+ break;
+
+- case AMP_LINK:
+- timeo = conn->disc_timeout;
+- break;
+-
+ default:
+ timeo = 0;
+ break;
+diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
+index a4278aa618ab1..3434cfc26b6af 100644
+--- a/include/net/bluetooth/l2cap.h
++++ b/include/net/bluetooth/l2cap.h
+@@ -548,6 +548,9 @@ struct l2cap_chan {
+ __u16 tx_credits;
+ __u16 rx_credits;
+
++ /* estimated available receive buffer space or -1 if unknown */
++ ssize_t rx_avail;
++
+ __u8 tx_state;
+ __u8 rx_state;
+
+@@ -682,10 +685,15 @@ struct l2cap_user {
+ /* ----- L2CAP socket info ----- */
+ #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
+
++struct l2cap_rx_busy {
++ struct list_head list;
++ struct sk_buff *skb;
++};
++
+ struct l2cap_pinfo {
+ struct bt_sock bt;
+ struct l2cap_chan *chan;
+- struct sk_buff *rx_busy_skb;
++ struct list_head rx_busy;
+ };
+
+ enum {
+@@ -943,6 +951,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
+ int l2cap_chan_reconfigure(struct l2cap_chan *chan, __u16 mtu);
+ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
+ void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
++void l2cap_chan_rx_avail(struct l2cap_chan *chan, ssize_t rx_avail);
+ int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator);
+ void l2cap_chan_set_defaults(struct l2cap_chan *chan);
+ int l2cap_ertm_init(struct l2cap_chan *chan);
+diff --git a/include/net/mac80211.h b/include/net/mac80211.h
+index d400fe2e8668d..df9b578e58bb2 100644
+--- a/include/net/mac80211.h
++++ b/include/net/mac80211.h
+@@ -932,6 +932,8 @@ enum mac80211_tx_info_flags {
+ * of their QoS TID or other priority field values.
+ * @IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX: first MLO TX, used mostly internally
+ * for sequence number assignment
++ * @IEEE80211_TX_CTRL_SCAN_TX: Indicates that this frame is transmitted
++ * due to scanning, not in normal operation on the interface.
+ * @IEEE80211_TX_CTRL_MLO_LINK: If not @IEEE80211_LINK_UNSPECIFIED, this
+ * frame should be transmitted on the specific link. This really is
+ * only relevant for frames that do not have data present, and is
+@@ -952,6 +954,7 @@ enum mac80211_tx_control_flags {
+ IEEE80211_TX_CTRL_NO_SEQNO = BIT(7),
+ IEEE80211_TX_CTRL_DONT_REORDER = BIT(8),
+ IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX = BIT(9),
++ IEEE80211_TX_CTRL_SCAN_TX = BIT(10),
+ IEEE80211_TX_CTRL_MLO_LINK = 0xf0000000,
+ };
+
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index f6eba9652d010..ab62e53f187c5 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -1494,11 +1494,10 @@ static inline int tcp_space_from_win(const struct sock *sk, int win)
+ return __tcp_space_from_win(tcp_sk(sk)->scaling_ratio, win);
+ }
+
+-/* Assume a conservative default of 1200 bytes of payload per 4K page.
++/* Assume a 50% default for skb->len/skb->truesize ratio.
+ * This may be adjusted later in tcp_measure_rcv_mss().
+ */
+-#define TCP_DEFAULT_SCALING_RATIO ((1200 << TCP_RMEM_TO_WIN_SCALE) / \
+- SKB_TRUESIZE(4096))
++#define TCP_DEFAULT_SCALING_RATIO (1 << (TCP_RMEM_TO_WIN_SCALE - 1))
+
+ static inline void tcp_scaling_ratio_init(struct sock *sk)
+ {
+diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h
+index 4d8ef71090af1..97a434d021356 100644
+--- a/include/trace/events/asoc.h
++++ b/include/trace/events/asoc.h
+@@ -12,6 +12,8 @@
+ #define DAPM_DIRECT "(direct)"
+ #define DAPM_ARROW(dir) (((dir) == SND_SOC_DAPM_DIR_OUT) ? "->" : "<-")
+
++TRACE_DEFINE_ENUM(SND_SOC_DAPM_DIR_OUT);
++
+ struct snd_soc_jack;
+ struct snd_soc_card;
+ struct snd_soc_dapm_widget;
+diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
+index 754e68ca8744c..83f31916e2635 100644
+--- a/include/uapi/linux/bpf.h
++++ b/include/uapi/linux/bpf.h
+@@ -7040,7 +7040,7 @@ struct bpf_fib_lookup {
+
+ /* output: MTU value */
+ __u16 mtu_result;
+- };
++ } __attribute__((packed, aligned(2)));
+ /* input: L3 device index for lookup
+ * output: device index from FIB lookup
+ */
+diff --git a/include/uapi/linux/virtio_bt.h b/include/uapi/linux/virtio_bt.h
+index af798f4c96804..3cc7d633456b6 100644
+--- a/include/uapi/linux/virtio_bt.h
++++ b/include/uapi/linux/virtio_bt.h
+@@ -13,7 +13,6 @@
+
+ enum virtio_bt_config_type {
+ VIRTIO_BT_CONFIG_TYPE_PRIMARY = 0,
+- VIRTIO_BT_CONFIG_TYPE_AMP = 1,
+ };
+
+ enum virtio_bt_config_vendor {
+diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c
+index 522196dfb0ff5..318ed067dbf64 100644
+--- a/io_uring/io-wq.c
++++ b/io_uring/io-wq.c
+@@ -564,10 +564,7 @@ static void io_worker_handle_work(struct io_wq_acct *acct,
+ * clear the stalled flag.
+ */
+ work = io_get_next_work(acct, worker);
+- raw_spin_unlock(&acct->lock);
+ if (work) {
+- __io_worker_busy(wq, worker);
+-
+ /*
+ * Make sure cancelation can find this, even before
+ * it becomes the active work. That avoids a window
+@@ -578,9 +575,15 @@ static void io_worker_handle_work(struct io_wq_acct *acct,
+ raw_spin_lock(&worker->lock);
+ worker->next_work = work;
+ raw_spin_unlock(&worker->lock);
+- } else {
+- break;
+ }
++
++ raw_spin_unlock(&acct->lock);
++
++ if (!work)
++ break;
++
++ __io_worker_busy(wq, worker);
++
+ io_assign_current_work(worker, work);
+ __set_current_state(TASK_RUNNING);
+
+diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h
+index d5495710c1787..c0cff024db7b4 100644
+--- a/io_uring/io_uring.h
++++ b/io_uring/io_uring.h
+@@ -301,7 +301,7 @@ static inline int io_run_task_work(void)
+
+ static inline bool io_task_work_pending(struct io_ring_ctx *ctx)
+ {
+- return task_work_pending(current) || !wq_list_empty(&ctx->work_llist);
++ return task_work_pending(current) || !llist_empty(&ctx->work_llist);
+ }
+
+ static inline void io_tw_lock(struct io_ring_ctx *ctx, struct io_tw_state *ts)
+diff --git a/io_uring/net.c b/io_uring/net.c
+index 46ea09e1e3829..dbabe0058f1cb 100644
+--- a/io_uring/net.c
++++ b/io_uring/net.c
+@@ -311,7 +311,10 @@ int io_send_prep_async(struct io_kiocb *req)
+ struct io_async_msghdr *io;
+ int ret;
+
+- if (!zc->addr || req_has_async_data(req))
++ if (req_has_async_data(req))
++ return 0;
++ zc->done_io = 0;
++ if (!zc->addr)
+ return 0;
+ io = io_msg_alloc_async_prep(req);
+ if (!io)
+@@ -338,8 +341,10 @@ static int io_setup_async_addr(struct io_kiocb *req,
+
+ int io_sendmsg_prep_async(struct io_kiocb *req)
+ {
++ struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
+ int ret;
+
++ sr->done_io = 0;
+ if (!io_msg_alloc_async_prep(req))
+ return -ENOMEM;
+ ret = io_sendmsg_copy_hdr(req, req->async_data);
+@@ -359,6 +364,8 @@ int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+ {
+ struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
+
++ sr->done_io = 0;
++
+ if (req->opcode == IORING_OP_SEND) {
+ if (READ_ONCE(sqe->__pad3[0]))
+ return -EINVAL;
+@@ -381,7 +388,6 @@ int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+ if (req->ctx->compat)
+ sr->msg_flags |= MSG_CMSG_COMPAT;
+ #endif
+- sr->done_io = 0;
+ return 0;
+ }
+
+@@ -585,9 +591,11 @@ static int io_recvmsg_copy_hdr(struct io_kiocb *req,
+
+ int io_recvmsg_prep_async(struct io_kiocb *req)
+ {
++ struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
+ struct io_async_msghdr *iomsg;
+ int ret;
+
++ sr->done_io = 0;
+ if (!io_msg_alloc_async_prep(req))
+ return -ENOMEM;
+ iomsg = req->async_data;
+@@ -603,6 +611,8 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+ {
+ struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
+
++ sr->done_io = 0;
++
+ if (unlikely(sqe->file_index || sqe->addr2))
+ return -EINVAL;
+
+@@ -639,7 +649,6 @@ int io_recvmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+ if (req->ctx->compat)
+ sr->msg_flags |= MSG_CMSG_COMPAT;
+ #endif
+- sr->done_io = 0;
+ sr->nr_multishot_loops = 0;
+ return 0;
+ }
+@@ -1019,6 +1028,9 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+ struct io_ring_ctx *ctx = req->ctx;
+ struct io_kiocb *notif;
+
++ zc->done_io = 0;
++ req->flags |= REQ_F_POLL_NO_LAZY;
++
+ if (unlikely(READ_ONCE(sqe->__pad2[0]) || READ_ONCE(sqe->addr3)))
+ return -EINVAL;
+ /* we don't support IOSQE_CQE_SKIP_SUCCESS just yet */
+@@ -1071,8 +1083,6 @@ int io_send_zc_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+ if (zc->msg_flags & MSG_DONTWAIT)
+ req->flags |= REQ_F_NOWAIT;
+
+- zc->done_io = 0;
+-
+ #ifdef CONFIG_COMPAT
+ if (req->ctx->compat)
+ zc->msg_flags |= MSG_CMSG_COMPAT;
+@@ -1318,7 +1328,7 @@ void io_sendrecv_fail(struct io_kiocb *req)
+ {
+ struct io_sr_msg *sr = io_kiocb_to_cmd(req, struct io_sr_msg);
+
+- if (req->flags & REQ_F_PARTIAL_IO)
++ if (sr->done_io)
+ req->cqe.res = sr->done_io;
+
+ if ((req->flags & REQ_F_NEED_CLEANUP) &&
+diff --git a/io_uring/nop.c b/io_uring/nop.c
+index d956599a3c1b8..1a4e312dfe510 100644
+--- a/io_uring/nop.c
++++ b/io_uring/nop.c
+@@ -12,6 +12,8 @@
+
+ int io_nop_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+ {
++ if (READ_ONCE(sqe->rw_flags))
++ return -EINVAL;
+ return 0;
+ }
+
+diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
+index 0f90b6b27430d..1860ba343726d 100644
+--- a/kernel/bpf/syscall.c
++++ b/kernel/bpf/syscall.c
+@@ -3852,6 +3852,11 @@ static int bpf_prog_attach_check_attach_type(const struct bpf_prog *prog,
+ * check permissions at attach time.
+ */
+ return -EPERM;
++
++ ptype = attach_type_to_prog_type(attach_type);
++ if (prog->type != ptype)
++ return -EINVAL;
++
+ return prog->enforce_expected_attach_type &&
+ prog->expected_attach_type != attach_type ?
+ -EINVAL : 0;
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 11bc3af33f34f..6edfcc3375082 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -2328,6 +2328,8 @@ static void mark_btf_ld_reg(struct bpf_verifier_env *env,
+ regs[regno].type = PTR_TO_BTF_ID | flag;
+ regs[regno].btf = btf;
+ regs[regno].btf_id = btf_id;
++ if (type_may_be_null(flag))
++ regs[regno].id = ++env->id_gen;
+ }
+
+ #define DEF_NOT_SUBREG (0)
+@@ -3584,7 +3586,8 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
+ * sreg needs precision before this insn
+ */
+ bt_clear_reg(bt, dreg);
+- bt_set_reg(bt, sreg);
++ if (sreg != BPF_REG_FP)
++ bt_set_reg(bt, sreg);
+ } else {
+ /* dreg = K
+ * dreg needs precision after this insn.
+@@ -3600,7 +3603,8 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
+ * both dreg and sreg need precision
+ * before this insn
+ */
+- bt_set_reg(bt, sreg);
++ if (sreg != BPF_REG_FP)
++ bt_set_reg(bt, sreg);
+ } /* else dreg += K
+ * dreg still needs precision before this insn
+ */
+@@ -5320,8 +5324,6 @@ static int check_map_kptr_access(struct bpf_verifier_env *env, u32 regno,
+ */
+ mark_btf_ld_reg(env, cur_regs(env), value_regno, PTR_TO_BTF_ID, kptr_field->kptr.btf,
+ kptr_field->kptr.btf_id, btf_ld_kptr_type(env, kptr_field));
+- /* For mark_ptr_or_null_reg */
+- val_reg->id = ++env->id_gen;
+ } else if (class == BPF_STX) {
+ val_reg = reg_state(env, value_regno);
+ if (!register_is_null(val_reg) &&
+@@ -5632,7 +5634,8 @@ static bool is_trusted_reg(const struct bpf_reg_state *reg)
+ return true;
+
+ /* Types listed in the reg2btf_ids are always trusted */
+- if (reg2btf_ids[base_type(reg->type)])
++ if (reg2btf_ids[base_type(reg->type)] &&
++ !bpf_type_has_unsafe_modifiers(reg->type))
+ return true;
+
+ /* If a register is not referenced, it is trusted if it has the
+@@ -6242,6 +6245,7 @@ static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val,
+ #define BTF_TYPE_SAFE_RCU(__type) __PASTE(__type, __safe_rcu)
+ #define BTF_TYPE_SAFE_RCU_OR_NULL(__type) __PASTE(__type, __safe_rcu_or_null)
+ #define BTF_TYPE_SAFE_TRUSTED(__type) __PASTE(__type, __safe_trusted)
++#define BTF_TYPE_SAFE_TRUSTED_OR_NULL(__type) __PASTE(__type, __safe_trusted_or_null)
+
+ /*
+ * Allow list few fields as RCU trusted or full trusted.
+@@ -6305,7 +6309,7 @@ BTF_TYPE_SAFE_TRUSTED(struct dentry) {
+ struct inode *d_inode;
+ };
+
+-BTF_TYPE_SAFE_TRUSTED(struct socket) {
++BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct socket) {
+ struct sock *sk;
+ };
+
+@@ -6340,11 +6344,20 @@ static bool type_is_trusted(struct bpf_verifier_env *env,
+ BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct linux_binprm));
+ BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct file));
+ BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct dentry));
+- BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED(struct socket));
+
+ return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id, "__safe_trusted");
+ }
+
++static bool type_is_trusted_or_null(struct bpf_verifier_env *env,
++ struct bpf_reg_state *reg,
++ const char *field_name, u32 btf_id)
++{
++ BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct socket));
++
++ return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id,
++ "__safe_trusted_or_null");
++}
++
+ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
+ struct bpf_reg_state *regs,
+ int regno, int off, int size,
+@@ -6453,6 +6466,8 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
+ */
+ if (type_is_trusted(env, reg, field_name, btf_id)) {
+ flag |= PTR_TRUSTED;
++ } else if (type_is_trusted_or_null(env, reg, field_name, btf_id)) {
++ flag |= PTR_TRUSTED | PTR_MAYBE_NULL;
+ } else if (in_rcu_cs(env) && !type_may_be_null(reg->type)) {
+ if (type_is_rcu(env, reg, field_name, btf_id)) {
+ /* ignore __rcu tag and mark it MEM_RCU */
+diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
+index 927bef3a598ad..6d6e540bacbfb 100644
+--- a/kernel/cgroup/cpuset.c
++++ b/kernel/cgroup/cpuset.c
+@@ -2948,7 +2948,7 @@ bool current_cpuset_is_being_rebound(void)
+ static int update_relax_domain_level(struct cpuset *cs, s64 val)
+ {
+ #ifdef CONFIG_SMP
+- if (val < -1 || val >= sched_domain_level_max)
++ if (val < -1 || val > sched_domain_level_max + 1)
+ return -EINVAL;
+ #endif
+
+diff --git a/kernel/cpu.c b/kernel/cpu.c
+index f8a0406ce8ba5..bac70ea54e349 100644
+--- a/kernel/cpu.c
++++ b/kernel/cpu.c
+@@ -3196,6 +3196,7 @@ void __init boot_cpu_hotplug_init(void)
+ this_cpu_write(cpuhp_state.target, CPUHP_ONLINE);
+ }
+
++#ifdef CONFIG_CPU_MITIGATIONS
+ /*
+ * These are used for a global "mitigations=" cmdline option for toggling
+ * optional CPU mitigations.
+@@ -3206,9 +3207,7 @@ enum cpu_mitigations {
+ CPU_MITIGATIONS_AUTO_NOSMT,
+ };
+
+-static enum cpu_mitigations cpu_mitigations __ro_after_init =
+- IS_ENABLED(CONFIG_CPU_MITIGATIONS) ? CPU_MITIGATIONS_AUTO :
+- CPU_MITIGATIONS_OFF;
++static enum cpu_mitigations cpu_mitigations __ro_after_init = CPU_MITIGATIONS_AUTO;
+
+ static int __init mitigations_parse_cmdline(char *arg)
+ {
+@@ -3224,7 +3223,6 @@ static int __init mitigations_parse_cmdline(char *arg)
+
+ return 0;
+ }
+-early_param("mitigations", mitigations_parse_cmdline);
+
+ /* mitigations=off */
+ bool cpu_mitigations_off(void)
+@@ -3239,3 +3237,11 @@ bool cpu_mitigations_auto_nosmt(void)
+ return cpu_mitigations == CPU_MITIGATIONS_AUTO_NOSMT;
+ }
+ EXPORT_SYMBOL_GPL(cpu_mitigations_auto_nosmt);
++#else
++static int __init mitigations_parse_cmdline(char *arg)
++{
++ pr_crit("Kernel compiled without mitigations, ignoring 'mitigations'; system may still be vulnerable\n");
++ return 0;
++}
++#endif
++early_param("mitigations", mitigations_parse_cmdline);
+diff --git a/kernel/rcu/tasks.h b/kernel/rcu/tasks.h
+index 732ad5b39946a..3f64268fe9ead 100644
+--- a/kernel/rcu/tasks.h
++++ b/kernel/rcu/tasks.h
+@@ -1941,7 +1941,7 @@ void show_rcu_tasks_trace_gp_kthread(void)
+ {
+ char buf[64];
+
+- sprintf(buf, "N%lu h:%lu/%lu/%lu",
++ snprintf(buf, sizeof(buf), "N%lu h:%lu/%lu/%lu",
+ data_race(n_trc_holdouts),
+ data_race(n_heavy_reader_ofl_updates),
+ data_race(n_heavy_reader_updates),
+diff --git a/kernel/rcu/tree_stall.h b/kernel/rcu/tree_stall.h
+index 5d666428546b0..b5ec62b2d850a 100644
+--- a/kernel/rcu/tree_stall.h
++++ b/kernel/rcu/tree_stall.h
+@@ -504,7 +504,8 @@ static void print_cpu_stall_info(int cpu)
+ rcu_dynticks_in_eqs(rcu_dynticks_snap(cpu));
+ rcuc_starved = rcu_is_rcuc_kthread_starving(rdp, &j);
+ if (rcuc_starved)
+- sprintf(buf, " rcuc=%ld jiffies(starved)", j);
++ // Print signed value, as negative values indicate a probable bug.
++ snprintf(buf, sizeof(buf), " rcuc=%ld jiffies(starved)", j);
+ pr_err("\t%d-%c%c%c%c: (%lu %s) idle=%04x/%ld/%#lx softirq=%u/%u fqs=%ld%s%s\n",
+ cpu,
+ "O."[!!cpu_online(cpu)],
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 9116bcc903467..d3aef6283931e 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -11381,7 +11381,7 @@ static ssize_t cpu_max_write(struct kernfs_open_file *of,
+ {
+ struct task_group *tg = css_tg(of_css(of));
+ u64 period = tg_get_cfs_period(tg);
+- u64 burst = tg_get_cfs_burst(tg);
++ u64 burst = tg->cfs_bandwidth.burst;
+ u64 quota;
+ int ret;
+
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index aee5e7a70170c..a01269ed968a7 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -6669,22 +6669,42 @@ static inline void hrtick_update(struct rq *rq)
+ #ifdef CONFIG_SMP
+ static inline bool cpu_overutilized(int cpu)
+ {
+- unsigned long rq_util_min = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MIN);
+- unsigned long rq_util_max = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MAX);
++ unsigned long rq_util_min, rq_util_max;
++
++ if (!sched_energy_enabled())
++ return false;
++
++ rq_util_min = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MIN);
++ rq_util_max = uclamp_rq_get(cpu_rq(cpu), UCLAMP_MAX);
+
+ /* Return true only if the utilization doesn't fit CPU's capacity */
+ return !util_fits_cpu(cpu_util_cfs(cpu), rq_util_min, rq_util_max, cpu);
+ }
+
+-static inline void update_overutilized_status(struct rq *rq)
++static inline void set_rd_overutilized_status(struct root_domain *rd,
++ unsigned int status)
+ {
+- if (!READ_ONCE(rq->rd->overutilized) && cpu_overutilized(rq->cpu)) {
+- WRITE_ONCE(rq->rd->overutilized, SG_OVERUTILIZED);
+- trace_sched_overutilized_tp(rq->rd, SG_OVERUTILIZED);
+- }
++ if (!sched_energy_enabled())
++ return;
++
++ WRITE_ONCE(rd->overutilized, status);
++ trace_sched_overutilized_tp(rd, !!status);
++}
++
++static inline void check_update_overutilized_status(struct rq *rq)
++{
++ /*
++ * overutilized field is used for load balancing decisions only
++ * if energy aware scheduler is being used
++ */
++ if (!sched_energy_enabled())
++ return;
++
++ if (!READ_ONCE(rq->rd->overutilized) && cpu_overutilized(rq->cpu))
++ set_rd_overutilized_status(rq->rd, SG_OVERUTILIZED);
+ }
+ #else
+-static inline void update_overutilized_status(struct rq *rq) { }
++static inline void check_update_overutilized_status(struct rq *rq) { }
+ #endif
+
+ /* Runqueue only has SCHED_IDLE tasks enqueued */
+@@ -6785,7 +6805,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
+ * and the following generally works well enough in practice.
+ */
+ if (!task_new)
+- update_overutilized_status(rq);
++ check_update_overutilized_status(rq);
+
+ enqueue_throttle:
+ assert_list_leaf_cfs_rq(rq);
+@@ -10621,19 +10641,14 @@ static inline void update_sd_lb_stats(struct lb_env *env, struct sd_lb_stats *sd
+ env->fbq_type = fbq_classify_group(&sds->busiest_stat);
+
+ if (!env->sd->parent) {
+- struct root_domain *rd = env->dst_rq->rd;
+-
+ /* update overload indicator if we are at root domain */
+- WRITE_ONCE(rd->overload, sg_status & SG_OVERLOAD);
++ WRITE_ONCE(env->dst_rq->rd->overload, sg_status & SG_OVERLOAD);
+
+ /* Update over-utilization (tipping point, U >= 0) indicator */
+- WRITE_ONCE(rd->overutilized, sg_status & SG_OVERUTILIZED);
+- trace_sched_overutilized_tp(rd, sg_status & SG_OVERUTILIZED);
++ set_rd_overutilized_status(env->dst_rq->rd,
++ sg_status & SG_OVERUTILIZED);
+ } else if (sg_status & SG_OVERUTILIZED) {
+- struct root_domain *rd = env->dst_rq->rd;
+-
+- WRITE_ONCE(rd->overutilized, SG_OVERUTILIZED);
+- trace_sched_overutilized_tp(rd, SG_OVERUTILIZED);
++ set_rd_overutilized_status(env->dst_rq->rd, SG_OVERUTILIZED);
+ }
+
+ update_idle_cpu_scan(env, sum_util);
+@@ -12639,7 +12654,7 @@ static void task_tick_fair(struct rq *rq, struct task_struct *curr, int queued)
+ task_tick_numa(rq, curr);
+
+ update_misfit_status(curr, rq);
+- update_overutilized_status(task_rq(curr));
++ check_update_overutilized_status(task_rq(curr));
+
+ task_tick_core(rq, curr);
+ }
+diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c
+index 373d42c707bc5..82e2f7fc7c267 100644
+--- a/kernel/sched/isolation.c
++++ b/kernel/sched/isolation.c
+@@ -109,6 +109,7 @@ static void __init housekeeping_setup_type(enum hk_type type,
+ static int __init housekeeping_setup(char *str, unsigned long flags)
+ {
+ cpumask_var_t non_housekeeping_mask, housekeeping_staging;
++ unsigned int first_cpu;
+ int err = 0;
+
+ if ((flags & HK_FLAG_TICK) && !(housekeeping.flags & HK_FLAG_TICK)) {
+@@ -129,7 +130,8 @@ static int __init housekeeping_setup(char *str, unsigned long flags)
+ cpumask_andnot(housekeeping_staging,
+ cpu_possible_mask, non_housekeeping_mask);
+
+- if (!cpumask_intersects(cpu_present_mask, housekeeping_staging)) {
++ first_cpu = cpumask_first_and(cpu_present_mask, housekeeping_staging);
++ if (first_cpu >= nr_cpu_ids || first_cpu >= setup_max_cpus) {
+ __cpumask_set_cpu(smp_processor_id(), housekeeping_staging);
+ __cpumask_clear_cpu(smp_processor_id(), non_housekeeping_mask);
+ if (!housekeeping.flags) {
+@@ -138,6 +140,9 @@ static int __init housekeeping_setup(char *str, unsigned long flags)
+ }
+ }
+
++ if (cpumask_empty(non_housekeeping_mask))
++ goto free_housekeeping_staging;
++
+ if (!housekeeping.flags) {
+ /* First setup call ("nohz_full=" or "isolcpus=") */
+ enum hk_type type;
+diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
+index 10d1391e74161..4fdab14953fc9 100644
+--- a/kernel/sched/topology.c
++++ b/kernel/sched/topology.c
+@@ -1468,7 +1468,7 @@ static void set_domain_attribute(struct sched_domain *sd,
+ } else
+ request = attr->relax_domain_level;
+
+- if (sd->level > request) {
++ if (sd->level >= request) {
+ /* Turn off idle balance on this domain: */
+ sd->flags &= ~(SD_BALANCE_WAKE|SD_BALANCE_NEWIDLE);
+ }
+diff --git a/kernel/softirq.c b/kernel/softirq.c
+index 210cf5f8d92c2..bd9716d7bb638 100644
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -507,7 +507,7 @@ static inline bool lockdep_softirq_start(void) { return false; }
+ static inline void lockdep_softirq_end(bool in_hardirq) { }
+ #endif
+
+-asmlinkage __visible void __softirq_entry __do_softirq(void)
++static void handle_softirqs(bool ksirqd)
+ {
+ unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
+ unsigned long old_flags = current->flags;
+@@ -562,8 +562,7 @@ asmlinkage __visible void __softirq_entry __do_softirq(void)
+ pending >>= softirq_bit;
+ }
+
+- if (!IS_ENABLED(CONFIG_PREEMPT_RT) &&
+- __this_cpu_read(ksoftirqd) == current)
++ if (!IS_ENABLED(CONFIG_PREEMPT_RT) && ksirqd)
+ rcu_softirq_qs();
+
+ local_irq_disable();
+@@ -583,6 +582,11 @@ asmlinkage __visible void __softirq_entry __do_softirq(void)
+ current_restore_flags(old_flags, PF_MEMALLOC);
+ }
+
++asmlinkage __visible void __softirq_entry __do_softirq(void)
++{
++ handle_softirqs(false);
++}
++
+ /**
+ * irq_enter_rcu - Enter an interrupt context with RCU watching
+ */
+@@ -918,7 +922,7 @@ static void run_ksoftirqd(unsigned int cpu)
+ * We can safely run softirq on inline stack, as we are not deep
+ * in the task stack here.
+ */
+- __do_softirq();
++ handle_softirqs(true);
+ ksoftirqd_run_end();
+ cond_resched();
+ return;
+diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
+index 83ba342aef31f..2f80239348f5d 100644
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -1595,12 +1595,15 @@ static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end)
+ unsigned long ftrace_location_range(unsigned long start, unsigned long end)
+ {
+ struct dyn_ftrace *rec;
++ unsigned long ip = 0;
+
++ rcu_read_lock();
+ rec = lookup_rec(start, end);
+ if (rec)
+- return rec->ip;
++ ip = rec->ip;
++ rcu_read_unlock();
+
+- return 0;
++ return ip;
+ }
+
+ /**
+@@ -1613,25 +1616,22 @@ unsigned long ftrace_location_range(unsigned long start, unsigned long end)
+ */
+ unsigned long ftrace_location(unsigned long ip)
+ {
+- struct dyn_ftrace *rec;
++ unsigned long loc;
+ unsigned long offset;
+ unsigned long size;
+
+- rec = lookup_rec(ip, ip);
+- if (!rec) {
++ loc = ftrace_location_range(ip, ip);
++ if (!loc) {
+ if (!kallsyms_lookup_size_offset(ip, &size, &offset))
+ goto out;
+
+ /* map sym+0 to __fentry__ */
+ if (!offset)
+- rec = lookup_rec(ip, ip + size - 1);
++ loc = ftrace_location_range(ip, ip + size - 1);
+ }
+
+- if (rec)
+- return rec->ip;
+-
+ out:
+- return 0;
++ return loc;
+ }
+
+ /**
+@@ -6593,6 +6593,8 @@ static int ftrace_process_locs(struct module *mod,
+ /* We should have used all pages unless we skipped some */
+ if (pg_unuse) {
+ WARN_ON(!skipped);
++ /* Need to synchronize with ftrace_location_range() */
++ synchronize_rcu();
+ ftrace_free_pages(pg_unuse);
+ }
+ return ret;
+@@ -6806,6 +6808,9 @@ void ftrace_release_mod(struct module *mod)
+ out_unlock:
+ mutex_unlock(&ftrace_lock);
+
++ /* Need to synchronize with ftrace_location_range() */
++ if (tmp_page)
++ synchronize_rcu();
+ for (pg = tmp_page; pg; pg = tmp_page) {
+
+ /* Needs to be called outside of ftrace_lock */
+@@ -7139,6 +7144,7 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
+ unsigned long start = (unsigned long)(start_ptr);
+ unsigned long end = (unsigned long)(end_ptr);
+ struct ftrace_page **last_pg = &ftrace_pages_start;
++ struct ftrace_page *tmp_page = NULL;
+ struct ftrace_page *pg;
+ struct dyn_ftrace *rec;
+ struct dyn_ftrace key;
+@@ -7180,12 +7186,8 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
+ ftrace_update_tot_cnt--;
+ if (!pg->index) {
+ *last_pg = pg->next;
+- if (pg->records) {
+- free_pages((unsigned long)pg->records, pg->order);
+- ftrace_number_of_pages -= 1 << pg->order;
+- }
+- ftrace_number_of_groups--;
+- kfree(pg);
++ pg->next = tmp_page;
++ tmp_page = pg;
+ pg = container_of(last_pg, struct ftrace_page, next);
+ if (!(*last_pg))
+ ftrace_pages = pg;
+@@ -7202,6 +7204,11 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
+ clear_func_from_hashes(func);
+ kfree(func);
+ }
++ /* Need to synchronize with ftrace_location_range() */
++ if (tmp_page) {
++ synchronize_rcu();
++ ftrace_free_pages(tmp_page);
++ }
+ }
+
+ void __init ftrace_free_init_mem(void)
+diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
+index faf56d9a9e88e..943850b25fcb7 100644
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -1456,6 +1456,11 @@ static void rb_check_bpage(struct ring_buffer_per_cpu *cpu_buffer,
+ *
+ * As a safety measure we check to make sure the data pages have not
+ * been corrupted.
++ *
++ * Callers of this function need to guarantee that the list of pages doesn't get
++ * modified during the check. In particular, if it's possible that the function
++ * is invoked with concurrent readers which can swap in a new reader page then
++ * the caller should take cpu_buffer->reader_lock.
+ */
+ static void rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer)
+ {
+@@ -2205,8 +2210,12 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
+ */
+ synchronize_rcu();
+ for_each_buffer_cpu(buffer, cpu) {
++ unsigned long flags;
++
+ cpu_buffer = buffer->buffers[cpu];
++ raw_spin_lock_irqsave(&cpu_buffer->reader_lock, flags);
+ rb_check_pages(cpu_buffer);
++ raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags);
+ }
+ atomic_dec(&buffer->record_disabled);
+ }
+diff --git a/kernel/trace/trace_events_user.c b/kernel/trace/trace_events_user.c
+index e76f5e1efdf2d..704de62f7ae16 100644
+--- a/kernel/trace/trace_events_user.c
++++ b/kernel/trace/trace_events_user.c
+@@ -202,6 +202,8 @@ static struct user_event_mm *user_event_mm_get(struct user_event_mm *mm);
+ static struct user_event_mm *user_event_mm_get_all(struct user_event *user);
+ static void user_event_mm_put(struct user_event_mm *mm);
+ static int destroy_user_event(struct user_event *user);
++static bool user_fields_match(struct user_event *user, int argc,
++ const char **argv);
+
+ static u32 user_event_key(char *name)
+ {
+@@ -1493,17 +1495,24 @@ static int destroy_user_event(struct user_event *user)
+ }
+
+ static struct user_event *find_user_event(struct user_event_group *group,
+- char *name, u32 *outkey)
++ char *name, int argc, const char **argv,
++ u32 flags, u32 *outkey)
+ {
+ struct user_event *user;
+ u32 key = user_event_key(name);
+
+ *outkey = key;
+
+- hash_for_each_possible(group->register_table, user, node, key)
+- if (!strcmp(EVENT_NAME(user), name))
++ hash_for_each_possible(group->register_table, user, node, key) {
++ if (strcmp(EVENT_NAME(user), name))
++ continue;
++
++ if (user_fields_match(user, argc, argv))
+ return user_event_get(user);
+
++ return ERR_PTR(-EADDRINUSE);
++ }
++
+ return NULL;
+ }
+
+@@ -1860,6 +1869,9 @@ static bool user_fields_match(struct user_event *user, int argc,
+ struct list_head *head = &user->fields;
+ int i = 0;
+
++ if (argc == 0)
++ return list_empty(head);
++
+ list_for_each_entry_reverse(field, head, link) {
+ if (!user_field_match(field, argc, argv, &i))
+ return false;
+@@ -1880,10 +1892,8 @@ static bool user_event_match(const char *system, const char *event,
+ match = strcmp(EVENT_NAME(user), event) == 0 &&
+ (!system || strcmp(system, USER_EVENTS_SYSTEM) == 0);
+
+- if (match && argc > 0)
++ if (match)
+ match = user_fields_match(user, argc, argv);
+- else if (match && argc == 0)
+- match = list_empty(&user->fields);
+
+ return match;
+ }
+@@ -1913,6 +1923,80 @@ static int user_event_trace_register(struct user_event *user)
+ return ret;
+ }
+
++/*
++ * Counts how many ';' without a trailing space are in the args.
++ */
++static int count_semis_no_space(char *args)
++{
++ int count = 0;
++
++ while ((args = strchr(args, ';'))) {
++ args++;
++
++ if (!isspace(*args))
++ count++;
++ }
++
++ return count;
++}
++
++/*
++ * Copies the arguments while ensuring all ';' have a trailing space.
++ */
++static char *insert_space_after_semis(char *args, int count)
++{
++ char *fixed, *pos;
++ int len;
++
++ len = strlen(args) + count;
++ fixed = kmalloc(len + 1, GFP_KERNEL);
++
++ if (!fixed)
++ return NULL;
++
++ pos = fixed;
++
++ /* Insert a space after ';' if there is no trailing space. */
++ while (*args) {
++ *pos = *args++;
++
++ if (*pos++ == ';' && !isspace(*args))
++ *pos++ = ' ';
++ }
++
++ *pos = '\0';
++
++ return fixed;
++}
++
++static char **user_event_argv_split(char *args, int *argc)
++{
++ char **split;
++ char *fixed;
++ int count;
++
++ /* Count how many ';' without a trailing space */
++ count = count_semis_no_space(args);
++
++ /* No fixup is required */
++ if (!count)
++ return argv_split(GFP_KERNEL, args, argc);
++
++ /* We must fixup 'field;field' to 'field; field' */
++ fixed = insert_space_after_semis(args, count);
++
++ if (!fixed)
++ return NULL;
++
++ /* We do a normal split afterwards */
++ split = argv_split(GFP_KERNEL, fixed, argc);
++
++ /* We can free since argv_split makes a copy */
++ kfree(fixed);
++
++ return split;
++}
++
+ /*
+ * Parses the event name, arguments and flags then registers if successful.
+ * The name buffer lifetime is owned by this method for success cases only.
+@@ -1922,11 +2006,11 @@ static int user_event_parse(struct user_event_group *group, char *name,
+ char *args, char *flags,
+ struct user_event **newuser, int reg_flags)
+ {
+- int ret;
+- u32 key;
+ struct user_event *user;
++ char **argv = NULL;
+ int argc = 0;
+- char **argv;
++ int ret;
++ u32 key;
+
+ /* Currently don't support any text based flags */
+ if (flags != NULL)
+@@ -1935,41 +2019,34 @@ static int user_event_parse(struct user_event_group *group, char *name,
+ if (!user_event_capable(reg_flags))
+ return -EPERM;
+
++ if (args) {
++ argv = user_event_argv_split(args, &argc);
++
++ if (!argv)
++ return -ENOMEM;
++ }
++
+ /* Prevent dyn_event from racing */
+ mutex_lock(&event_mutex);
+- user = find_user_event(group, name, &key);
++ user = find_user_event(group, name, argc, (const char **)argv,
++ reg_flags, &key);
+ mutex_unlock(&event_mutex);
+
+- if (user) {
+- if (args) {
+- argv = argv_split(GFP_KERNEL, args, &argc);
+- if (!argv) {
+- ret = -ENOMEM;
+- goto error;
+- }
++ if (argv)
++ argv_free(argv);
+
+- ret = user_fields_match(user, argc, (const char **)argv);
+- argv_free(argv);
+-
+- } else
+- ret = list_empty(&user->fields);
+-
+- if (ret) {
+- *newuser = user;
+- /*
+- * Name is allocated by caller, free it since it already exists.
+- * Caller only worries about failure cases for freeing.
+- */
+- kfree(name);
+- } else {
+- ret = -EADDRINUSE;
+- goto error;
+- }
++ if (IS_ERR(user))
++ return PTR_ERR(user);
++
++ if (user) {
++ *newuser = user;
++ /*
++ * Name is allocated by caller, free it since it already exists.
++ * Caller only worries about failure cases for freeing.
++ */
++ kfree(name);
+
+ return 0;
+-error:
+- user_event_put(user, false);
+- return ret;
+ }
+
+ user = kzalloc(sizeof(*user), GFP_KERNEL_ACCOUNT);
+@@ -2052,25 +2129,33 @@ static int user_event_parse(struct user_event_group *group, char *name,
+ }
+
+ /*
+- * Deletes a previously created event if it is no longer being used.
++ * Deletes previously created events if they are no longer being used.
+ */
+ static int delete_user_event(struct user_event_group *group, char *name)
+ {
+- u32 key;
+- struct user_event *user = find_user_event(group, name, &key);
++ struct user_event *user;
++ struct hlist_node *tmp;
++ u32 key = user_event_key(name);
++ int ret = -ENOENT;
+
+- if (!user)
+- return -ENOENT;
++ /* Attempt to delete all event(s) with the name passed in */
++ hash_for_each_possible_safe(group->register_table, user, tmp, node, key) {
++ if (strcmp(EVENT_NAME(user), name))
++ continue;
+
+- user_event_put(user, true);
++ if (!user_event_last_ref(user))
++ return -EBUSY;
+
+- if (!user_event_last_ref(user))
+- return -EBUSY;
++ if (!user_event_capable(user->reg_flags))
++ return -EPERM;
+
+- if (!user_event_capable(user->reg_flags))
+- return -EPERM;
++ ret = destroy_user_event(user);
+
+- return destroy_user_event(user);
++ if (ret)
++ goto out;
++ }
++out:
++ return ret;
+ }
+
+ /*
+diff --git a/lib/fortify_kunit.c b/lib/fortify_kunit.c
+index 2e4fedc816210..7830a9e64ead7 100644
+--- a/lib/fortify_kunit.c
++++ b/lib/fortify_kunit.c
+@@ -229,28 +229,28 @@ DEFINE_ALLOC_SIZE_TEST_PAIR(vmalloc)
+ \
+ checker((expected_pages) * PAGE_SIZE, \
+ kvmalloc((alloc_pages) * PAGE_SIZE, gfp), \
+- vfree(p)); \
++ kvfree(p)); \
+ checker((expected_pages) * PAGE_SIZE, \
+ kvmalloc_node((alloc_pages) * PAGE_SIZE, gfp, NUMA_NO_NODE), \
+- vfree(p)); \
++ kvfree(p)); \
+ checker((expected_pages) * PAGE_SIZE, \
+ kvzalloc((alloc_pages) * PAGE_SIZE, gfp), \
+- vfree(p)); \
++ kvfree(p)); \
+ checker((expected_pages) * PAGE_SIZE, \
+ kvzalloc_node((alloc_pages) * PAGE_SIZE, gfp, NUMA_NO_NODE), \
+- vfree(p)); \
++ kvfree(p)); \
+ checker((expected_pages) * PAGE_SIZE, \
+ kvcalloc(1, (alloc_pages) * PAGE_SIZE, gfp), \
+- vfree(p)); \
++ kvfree(p)); \
+ checker((expected_pages) * PAGE_SIZE, \
+ kvcalloc((alloc_pages) * PAGE_SIZE, 1, gfp), \
+- vfree(p)); \
++ kvfree(p)); \
+ checker((expected_pages) * PAGE_SIZE, \
+ kvmalloc_array(1, (alloc_pages) * PAGE_SIZE, gfp), \
+- vfree(p)); \
++ kvfree(p)); \
+ checker((expected_pages) * PAGE_SIZE, \
+ kvmalloc_array((alloc_pages) * PAGE_SIZE, 1, gfp), \
+- vfree(p)); \
++ kvfree(p)); \
+ \
+ prev_size = (expected_pages) * PAGE_SIZE; \
+ orig = kvmalloc(prev_size, gfp); \
+diff --git a/lib/kunit/device.c b/lib/kunit/device.c
+index 9ea399049749e..3a31fe9ed6fc5 100644
+--- a/lib/kunit/device.c
++++ b/lib/kunit/device.c
+@@ -51,7 +51,7 @@ int kunit_bus_init(void)
+
+ error = bus_register(&kunit_bus_type);
+ if (error)
+- bus_unregister(&kunit_bus_type);
++ root_device_unregister(kunit_bus_device);
+ return error;
+ }
+
+diff --git a/lib/kunit/test.c b/lib/kunit/test.c
+index 1d1475578515c..b8514dbb337c0 100644
+--- a/lib/kunit/test.c
++++ b/lib/kunit/test.c
+@@ -712,6 +712,9 @@ int __kunit_test_suites_init(struct kunit_suite * const * const suites, int num_
+ {
+ unsigned int i;
+
++ if (num_suites == 0)
++ return 0;
++
+ if (!kunit_enabled() && num_suites > 0) {
+ pr_info("kunit: disabled\n");
+ return 0;
+diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c
+index f7825991d576a..d9d1df28cc52e 100644
+--- a/lib/kunit/try-catch.c
++++ b/lib/kunit/try-catch.c
+@@ -11,6 +11,7 @@
+ #include <linux/completion.h>
+ #include <linux/kernel.h>
+ #include <linux/kthread.h>
++#include <linux/sched/task.h>
+
+ #include "try-catch-impl.h"
+
+@@ -65,13 +66,14 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
+ try_catch->context = context;
+ try_catch->try_completion = &try_completion;
+ try_catch->try_result = 0;
+- task_struct = kthread_run(kunit_generic_run_threadfn_adapter,
+- try_catch,
+- "kunit_try_catch_thread");
++ task_struct = kthread_create(kunit_generic_run_threadfn_adapter,
++ try_catch, "kunit_try_catch_thread");
+ if (IS_ERR(task_struct)) {
+ try_catch->catch(try_catch->context);
+ return;
+ }
++ get_task_struct(task_struct);
++ wake_up_process(task_struct);
+
+ time_remaining = wait_for_completion_timeout(&try_completion,
+ kunit_test_timeout());
+@@ -81,6 +83,7 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
+ kthread_stop(task_struct);
+ }
+
++ put_task_struct(task_struct);
+ exit_code = try_catch->try_result;
+
+ if (!exit_code)
+diff --git a/lib/maple_tree.c b/lib/maple_tree.c
+index d70db05757091..fe6092a1dc353 100644
+--- a/lib/maple_tree.c
++++ b/lib/maple_tree.c
+@@ -4290,6 +4290,56 @@ static inline void *mas_insert(struct ma_state *mas, void *entry)
+
+ }
+
++/**
++ * mas_alloc_cyclic() - Internal call to find somewhere to store an entry
++ * @mas: The maple state.
++ * @startp: Pointer to ID.
++ * @range_lo: Lower bound of range to search.
++ * @range_hi: Upper bound of range to search.
++ * @entry: The entry to store.
++ * @next: Pointer to next ID to allocate.
++ * @gfp: The GFP_FLAGS to use for allocations.
++ *
++ * Return: 0 if the allocation succeeded without wrapping, 1 if the
++ * allocation succeeded after wrapping, or -EBUSY if there are no
++ * free entries.
++ */
++int mas_alloc_cyclic(struct ma_state *mas, unsigned long *startp,
++ void *entry, unsigned long range_lo, unsigned long range_hi,
++ unsigned long *next, gfp_t gfp)
++{
++ unsigned long min = range_lo;
++ int ret = 0;
++
++ range_lo = max(min, *next);
++ ret = mas_empty_area(mas, range_lo, range_hi, 1);
++ if ((mas->tree->ma_flags & MT_FLAGS_ALLOC_WRAPPED) && ret == 0) {
++ mas->tree->ma_flags &= ~MT_FLAGS_ALLOC_WRAPPED;
++ ret = 1;
++ }
++ if (ret < 0 && range_lo > min) {
++ ret = mas_empty_area(mas, min, range_hi, 1);
++ if (ret == 0)
++ ret = 1;
++ }
++ if (ret < 0)
++ return ret;
++
++ do {
++ mas_insert(mas, entry);
++ } while (mas_nomem(mas, gfp));
++ if (mas_is_err(mas))
++ return xa_err(mas->node);
++
++ *startp = mas->index;
++ *next = *startp + 1;
++ if (*next == 0)
++ mas->tree->ma_flags |= MT_FLAGS_ALLOC_WRAPPED;
++
++ return ret;
++}
++EXPORT_SYMBOL(mas_alloc_cyclic);
++
+ static __always_inline void mas_rewalk(struct ma_state *mas, unsigned long index)
+ {
+ retry:
+@@ -6443,6 +6493,49 @@ int mtree_alloc_range(struct maple_tree *mt, unsigned long *startp,
+ }
+ EXPORT_SYMBOL(mtree_alloc_range);
+
++/**
++ * mtree_alloc_cyclic() - Find somewhere to store this entry in the tree.
++ * @mt: The maple tree.
++ * @startp: Pointer to ID.
++ * @range_lo: Lower bound of range to search.
++ * @range_hi: Upper bound of range to search.
++ * @entry: The entry to store.
++ * @next: Pointer to next ID to allocate.
++ * @gfp: The GFP_FLAGS to use for allocations.
++ *
++ * Finds an empty entry in @mt after @next, stores the new index into
++ * the @id pointer, stores the entry at that index, then updates @next.
++ *
++ * @mt must be initialized with the MT_FLAGS_ALLOC_RANGE flag.
++ *
++ * Context: Any context. Takes and releases the mt.lock. May sleep if
++ * the @gfp flags permit.
++ *
++ * Return: 0 if the allocation succeeded without wrapping, 1 if the
++ * allocation succeeded after wrapping, -ENOMEM if memory could not be
++ * allocated, -EINVAL if @mt cannot be used, or -EBUSY if there are no
++ * free entries.
++ */
++int mtree_alloc_cyclic(struct maple_tree *mt, unsigned long *startp,
++ void *entry, unsigned long range_lo, unsigned long range_hi,
++ unsigned long *next, gfp_t gfp)
++{
++ int ret;
++
++ MA_STATE(mas, mt, 0, 0);
++
++ if (!mt_is_alloc(mt))
++ return -EINVAL;
++ if (WARN_ON_ONCE(mt_is_reserved(entry)))
++ return -EINVAL;
++ mtree_lock(mt);
++ ret = mas_alloc_cyclic(&mas, startp, entry, range_lo, range_hi,
++ next, gfp);
++ mtree_unlock(mt);
++ return ret;
++}
++EXPORT_SYMBOL(mtree_alloc_cyclic);
++
+ int mtree_alloc_rrange(struct maple_tree *mt, unsigned long *startp,
+ void *entry, unsigned long size, unsigned long min,
+ unsigned long max, gfp_t gfp)
+diff --git a/lib/overflow_kunit.c b/lib/overflow_kunit.c
+index c527f6b757894..c85c8b121d350 100644
+--- a/lib/overflow_kunit.c
++++ b/lib/overflow_kunit.c
+@@ -1113,6 +1113,24 @@ static void castable_to_type_test(struct kunit *test)
+ #undef TEST_CASTABLE_TO_TYPE
+ }
+
++struct foo {
++ int a;
++ u32 counter;
++ s16 array[] __counted_by(counter);
++};
++
++static void DEFINE_FLEX_test(struct kunit *test)
++{
++ DEFINE_RAW_FLEX(struct foo, two, array, 2);
++ DEFINE_FLEX(struct foo, eight, array, counter, 8);
++ DEFINE_FLEX(struct foo, empty, array, counter, 0);
++
++ KUNIT_EXPECT_EQ(test, __struct_size(two),
++ sizeof(struct foo) + sizeof(s16) + sizeof(s16));
++ KUNIT_EXPECT_EQ(test, __struct_size(eight), 24);
++ KUNIT_EXPECT_EQ(test, __struct_size(empty), sizeof(struct foo));
++}
++
+ static struct kunit_case overflow_test_cases[] = {
+ KUNIT_CASE(u8_u8__u8_overflow_test),
+ KUNIT_CASE(s8_s8__s8_overflow_test),
+@@ -1135,6 +1153,7 @@ static struct kunit_case overflow_test_cases[] = {
+ KUNIT_CASE(overflows_type_test),
+ KUNIT_CASE(same_type_test),
+ KUNIT_CASE(castable_to_type_test),
++ KUNIT_CASE(DEFINE_FLEX_test),
+ {}
+ };
+
+diff --git a/lib/slub_kunit.c b/lib/slub_kunit.c
+index d4a3730b08fa7..4ce9604388069 100644
+--- a/lib/slub_kunit.c
++++ b/lib/slub_kunit.c
+@@ -55,7 +55,7 @@ static void test_next_pointer(struct kunit *test)
+
+ ptr_addr = (unsigned long *)(p + s->offset);
+ tmp = *ptr_addr;
+- p[s->offset] = 0x12;
++ p[s->offset] = ~p[s->offset];
+
+ /*
+ * Expecting three errors.
+diff --git a/lib/test_hmm.c b/lib/test_hmm.c
+index 717dcb8301273..b823ba7cb6a15 100644
+--- a/lib/test_hmm.c
++++ b/lib/test_hmm.c
+@@ -1226,8 +1226,8 @@ static void dmirror_device_evict_chunk(struct dmirror_chunk *chunk)
+ unsigned long *src_pfns;
+ unsigned long *dst_pfns;
+
+- src_pfns = kcalloc(npages, sizeof(*src_pfns), GFP_KERNEL);
+- dst_pfns = kcalloc(npages, sizeof(*dst_pfns), GFP_KERNEL);
++ src_pfns = kvcalloc(npages, sizeof(*src_pfns), GFP_KERNEL | __GFP_NOFAIL);
++ dst_pfns = kvcalloc(npages, sizeof(*dst_pfns), GFP_KERNEL | __GFP_NOFAIL);
+
+ migrate_device_range(src_pfns, start_pfn, npages);
+ for (i = 0; i < npages; i++) {
+@@ -1250,8 +1250,8 @@ static void dmirror_device_evict_chunk(struct dmirror_chunk *chunk)
+ }
+ migrate_device_pages(src_pfns, dst_pfns, npages);
+ migrate_device_finalize(src_pfns, dst_pfns, npages);
+- kfree(src_pfns);
+- kfree(dst_pfns);
++ kvfree(src_pfns);
++ kvfree(dst_pfns);
+ }
+
+ /* Removes free pages from the free list so they can't be re-allocated */
+diff --git a/mm/shmem.c b/mm/shmem.c
+index 5853f3ae36e53..935f3647bb3a1 100644
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -3368,7 +3368,7 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
+
+ static int shmem_rmdir(struct inode *dir, struct dentry *dentry)
+ {
+- if (!simple_empty(dentry))
++ if (!simple_offset_empty(dentry))
+ return -ENOTEMPTY;
+
+ drop_nlink(d_inode(dentry));
+@@ -3425,7 +3425,7 @@ static int shmem_rename2(struct mnt_idmap *idmap,
+ return simple_offset_rename_exchange(old_dir, old_dentry,
+ new_dir, new_dentry);
+
+- if (!simple_empty(new_dentry))
++ if (!simple_offset_empty(new_dentry))
+ return -ENOTEMPTY;
+
+ if (flags & RENAME_WHITEOUT) {
+@@ -3434,8 +3434,7 @@ static int shmem_rename2(struct mnt_idmap *idmap,
+ return error;
+ }
+
+- simple_offset_remove(shmem_get_offset_ctx(old_dir), old_dentry);
+- error = simple_offset_add(shmem_get_offset_ctx(new_dir), old_dentry);
++ error = simple_offset_rename(old_dir, old_dentry, new_dir, new_dentry);
+ if (error)
+ return error;
+
+diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
+index 313f1c42768a6..aa8f5a6c324ee 100644
+--- a/mm/userfaultfd.c
++++ b/mm/userfaultfd.c
+@@ -213,6 +213,38 @@ static int mfill_atomic_pte_copy(pmd_t *dst_pmd,
+ goto out;
+ }
+
++static int mfill_atomic_pte_zeroed_folio(pmd_t *dst_pmd,
++ struct vm_area_struct *dst_vma,
++ unsigned long dst_addr)
++{
++ struct folio *folio;
++ int ret = -ENOMEM;
++
++ folio = vma_alloc_zeroed_movable_folio(dst_vma, dst_addr);
++ if (!folio)
++ return ret;
++
++ if (mem_cgroup_charge(folio, dst_vma->vm_mm, GFP_KERNEL))
++ goto out_put;
++
++ /*
++ * The memory barrier inside __folio_mark_uptodate makes sure that
++ * zeroing out the folio become visible before mapping the page
++ * using set_pte_at(). See do_anonymous_page().
++ */
++ __folio_mark_uptodate(folio);
++
++ ret = mfill_atomic_install_pte(dst_pmd, dst_vma, dst_addr,
++ &folio->page, true, 0);
++ if (ret)
++ goto out_put;
++
++ return 0;
++out_put:
++ folio_put(folio);
++ return ret;
++}
++
+ static int mfill_atomic_pte_zeropage(pmd_t *dst_pmd,
+ struct vm_area_struct *dst_vma,
+ unsigned long dst_addr)
+@@ -221,6 +253,9 @@ static int mfill_atomic_pte_zeropage(pmd_t *dst_pmd,
+ spinlock_t *ptl;
+ int ret;
+
++ if (mm_forbids_zeropage(dst_vma->vm_mm))
++ return mfill_atomic_pte_zeroed_folio(dst_pmd, dst_vma, dst_addr);
++
+ _dst_pte = pte_mkspecial(pfn_pte(my_zero_pfn(dst_addr),
+ dst_vma->vm_page_prot));
+ ret = -EAGAIN;
+diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
+index 282ec581c0720..c9d55b99a7a57 100644
+--- a/net/ax25/ax25_dev.c
++++ b/net/ax25/ax25_dev.c
+@@ -22,11 +22,12 @@
+ #include <net/sock.h>
+ #include <linux/uaccess.h>
+ #include <linux/fcntl.h>
++#include <linux/list.h>
+ #include <linux/mm.h>
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
+
+-ax25_dev *ax25_dev_list;
++static LIST_HEAD(ax25_dev_list);
+ DEFINE_SPINLOCK(ax25_dev_lock);
+
+ ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
+@@ -34,10 +35,11 @@ ax25_dev *ax25_addr_ax25dev(ax25_address *addr)
+ ax25_dev *ax25_dev, *res = NULL;
+
+ spin_lock_bh(&ax25_dev_lock);
+- for (ax25_dev = ax25_dev_list; ax25_dev != NULL; ax25_dev = ax25_dev->next)
++ list_for_each_entry(ax25_dev, &ax25_dev_list, list)
+ if (ax25cmp(addr, (const ax25_address *)ax25_dev->dev->dev_addr) == 0) {
+ res = ax25_dev;
+ ax25_dev_hold(ax25_dev);
++ break;
+ }
+ spin_unlock_bh(&ax25_dev_lock);
+
+@@ -59,7 +61,6 @@ void ax25_dev_device_up(struct net_device *dev)
+ }
+
+ refcount_set(&ax25_dev->refcount, 1);
+- dev->ax25_ptr = ax25_dev;
+ ax25_dev->dev = dev;
+ netdev_hold(dev, &ax25_dev->dev_tracker, GFP_KERNEL);
+ ax25_dev->forward = NULL;
+@@ -85,10 +86,9 @@ void ax25_dev_device_up(struct net_device *dev)
+ #endif
+
+ spin_lock_bh(&ax25_dev_lock);
+- ax25_dev->next = ax25_dev_list;
+- ax25_dev_list = ax25_dev;
++ list_add(&ax25_dev->list, &ax25_dev_list);
++ dev->ax25_ptr = ax25_dev;
+ spin_unlock_bh(&ax25_dev_lock);
+- ax25_dev_hold(ax25_dev);
+
+ ax25_register_dev_sysctl(ax25_dev);
+ }
+@@ -111,32 +111,19 @@ void ax25_dev_device_down(struct net_device *dev)
+ /*
+ * Remove any packet forwarding that points to this device.
+ */
+- for (s = ax25_dev_list; s != NULL; s = s->next)
++ list_for_each_entry(s, &ax25_dev_list, list)
+ if (s->forward == dev)
+ s->forward = NULL;
+
+- if ((s = ax25_dev_list) == ax25_dev) {
+- ax25_dev_list = s->next;
+- goto unlock_put;
+- }
+-
+- while (s != NULL && s->next != NULL) {
+- if (s->next == ax25_dev) {
+- s->next = ax25_dev->next;
+- goto unlock_put;
++ list_for_each_entry(s, &ax25_dev_list, list) {
++ if (s == ax25_dev) {
++ list_del(&s->list);
++ break;
+ }
+-
+- s = s->next;
+ }
+- spin_unlock_bh(&ax25_dev_lock);
+- dev->ax25_ptr = NULL;
+- ax25_dev_put(ax25_dev);
+- return;
+
+-unlock_put:
+- spin_unlock_bh(&ax25_dev_lock);
+- ax25_dev_put(ax25_dev);
+ dev->ax25_ptr = NULL;
++ spin_unlock_bh(&ax25_dev_lock);
+ netdev_put(dev, &ax25_dev->dev_tracker);
+ ax25_dev_put(ax25_dev);
+ }
+@@ -200,16 +187,13 @@ struct net_device *ax25_fwd_dev(struct net_device *dev)
+ */
+ void __exit ax25_dev_free(void)
+ {
+- ax25_dev *s, *ax25_dev;
++ ax25_dev *s, *n;
+
+ spin_lock_bh(&ax25_dev_lock);
+- ax25_dev = ax25_dev_list;
+- while (ax25_dev != NULL) {
+- s = ax25_dev;
+- netdev_put(ax25_dev->dev, &ax25_dev->dev_tracker);
+- ax25_dev = ax25_dev->next;
++ list_for_each_entry_safe(s, n, &ax25_dev_list, list) {
++ netdev_put(s->dev, &s->dev_tracker);
++ list_del(&s->list);
+ kfree(s);
+ }
+- ax25_dev_list = NULL;
+ spin_unlock_bh(&ax25_dev_lock);
+ }
+diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
+index 9a369bc14fd57..7f78fc6c29cf5 100644
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -1,7 +1,7 @@
+ /*
+ BlueZ - Bluetooth protocol stack for Linux
+ Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
+- Copyright 2023 NXP
++ Copyright 2023-2024 NXP
+
+ Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
+
+@@ -1173,8 +1173,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src, uint8_t src_type)
+
+ list_for_each_entry(d, &hci_dev_list, list) {
+ if (!test_bit(HCI_UP, &d->flags) ||
+- hci_dev_test_flag(d, HCI_USER_CHANNEL) ||
+- d->dev_type != HCI_PRIMARY)
++ hci_dev_test_flag(d, HCI_USER_CHANNEL))
+ continue;
+
+ /* Simple routing:
+@@ -2086,18 +2085,31 @@ static int create_pa_sync(struct hci_dev *hdev, void *data)
+ return hci_update_passive_scan_sync(hdev);
+ }
+
+-int hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type,
+- __u8 sid, struct bt_iso_qos *qos)
++struct hci_conn *hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst,
++ __u8 dst_type, __u8 sid,
++ struct bt_iso_qos *qos)
+ {
+ struct hci_cp_le_pa_create_sync *cp;
++ struct hci_conn *conn;
++ int err;
+
+ if (hci_dev_test_and_set_flag(hdev, HCI_PA_SYNC))
+- return -EBUSY;
++ return ERR_PTR(-EBUSY);
++
++ conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_SLAVE);
++ if (!conn)
++ return ERR_PTR(-ENOMEM);
++
++ conn->iso_qos = *qos;
++ conn->state = BT_LISTEN;
++
++ hci_conn_hold(conn);
+
+ cp = kzalloc(sizeof(*cp), GFP_KERNEL);
+ if (!cp) {
+ hci_dev_clear_flag(hdev, HCI_PA_SYNC);
+- return -ENOMEM;
++ hci_conn_drop(conn);
++ return ERR_PTR(-ENOMEM);
+ }
+
+ cp->options = qos->bcast.options;
+@@ -2109,7 +2121,14 @@ int hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type,
+ cp->sync_cte_type = qos->bcast.sync_cte_type;
+
+ /* Queue start pa_create_sync and scan */
+- return hci_cmd_sync_queue(hdev, create_pa_sync, cp, create_pa_complete);
++ err = hci_cmd_sync_queue(hdev, create_pa_sync, cp, create_pa_complete);
++ if (err < 0) {
++ hci_conn_drop(conn);
++ kfree(cp);
++ return ERR_PTR(err);
++ }
++
++ return conn;
+ }
+
+ int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index befe645d3f9bf..e946ac46a1762 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -395,11 +395,6 @@ int hci_inquiry(void __user *arg)
+ goto done;
+ }
+
+- if (hdev->dev_type != HCI_PRIMARY) {
+- err = -EOPNOTSUPP;
+- goto done;
+- }
+-
+ if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
+ err = -EOPNOTSUPP;
+ goto done;
+@@ -752,11 +747,6 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
+ goto done;
+ }
+
+- if (hdev->dev_type != HCI_PRIMARY) {
+- err = -EOPNOTSUPP;
+- goto done;
+- }
+-
+ if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
+ err = -EOPNOTSUPP;
+ goto done;
+@@ -910,7 +900,7 @@ int hci_get_dev_info(void __user *arg)
+
+ strscpy(di.name, hdev->name, sizeof(di.name));
+ di.bdaddr = hdev->bdaddr;
+- di.type = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4);
++ di.type = (hdev->bus & 0x0f);
+ di.flags = flags;
+ di.pkt_type = hdev->pkt_type;
+ if (lmp_bredr_capable(hdev)) {
+@@ -995,8 +985,7 @@ static void hci_power_on(struct work_struct *work)
+ */
+ if (hci_dev_test_flag(hdev, HCI_RFKILLED) ||
+ hci_dev_test_flag(hdev, HCI_UNCONFIGURED) ||
+- (hdev->dev_type == HCI_PRIMARY &&
+- !bacmp(&hdev->bdaddr, BDADDR_ANY) &&
++ (!bacmp(&hdev->bdaddr, BDADDR_ANY) &&
+ !bacmp(&hdev->static_addr, BDADDR_ANY))) {
+ hci_dev_clear_flag(hdev, HCI_AUTO_OFF);
+ hci_dev_do_close(hdev);
+@@ -1738,6 +1727,15 @@ struct adv_info *hci_add_adv_instance(struct hci_dev *hdev, u8 instance,
+
+ adv->pending = true;
+ adv->instance = instance;
++
++ /* If controller support only one set and the instance is set to
++ * 1 then there is no option other than using handle 0x00.
++ */
++ if (hdev->le_num_of_adv_sets == 1 && instance == 1)
++ adv->handle = 0x00;
++ else
++ adv->handle = instance;
++
+ list_add(&adv->list, &hdev->adv_instances);
+ hdev->adv_instance_cnt++;
+ }
+@@ -2604,20 +2602,7 @@ int hci_register_dev(struct hci_dev *hdev)
+ if (!hdev->open || !hdev->close || !hdev->send)
+ return -EINVAL;
+
+- /* Do not allow HCI_AMP devices to register at index 0,
+- * so the index can be used as the AMP controller ID.
+- */
+- switch (hdev->dev_type) {
+- case HCI_PRIMARY:
+- id = ida_simple_get(&hci_index_ida, 0, HCI_MAX_ID, GFP_KERNEL);
+- break;
+- case HCI_AMP:
+- id = ida_simple_get(&hci_index_ida, 1, HCI_MAX_ID, GFP_KERNEL);
+- break;
+- default:
+- return -EINVAL;
+- }
+-
++ id = ida_alloc_max(&hci_index_ida, HCI_MAX_ID - 1, GFP_KERNEL);
+ if (id < 0)
+ return id;
+
+@@ -2669,12 +2654,10 @@ int hci_register_dev(struct hci_dev *hdev)
+ hci_dev_set_flag(hdev, HCI_SETUP);
+ hci_dev_set_flag(hdev, HCI_AUTO_OFF);
+
+- if (hdev->dev_type == HCI_PRIMARY) {
+- /* Assume BR/EDR support until proven otherwise (such as
+- * through reading supported features during init.
+- */
+- hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
+- }
++ /* Assume BR/EDR support until proven otherwise (such as
++ * through reading supported features during init.
++ */
++ hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
+
+ write_lock(&hci_dev_list_lock);
+ list_add(&hdev->list, &hci_dev_list);
+@@ -2711,7 +2694,7 @@ int hci_register_dev(struct hci_dev *hdev)
+ destroy_workqueue(hdev->workqueue);
+ destroy_workqueue(hdev->req_workqueue);
+ err:
+- ida_simple_remove(&hci_index_ida, hdev->id);
++ ida_free(&hci_index_ida, hdev->id);
+
+ return error;
+ }
+@@ -2793,7 +2776,7 @@ void hci_release_dev(struct hci_dev *hdev)
+ hci_dev_unlock(hdev);
+
+ ida_destroy(&hdev->unset_handle_ida);
+- ida_simple_remove(&hci_index_ida, hdev->id);
++ ida_free(&hci_index_ida, hdev->id);
+ kfree_skb(hdev->sent_cmd);
+ kfree_skb(hdev->req_skb);
+ kfree_skb(hdev->recv_event);
+@@ -3210,17 +3193,7 @@ static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue,
+
+ hci_skb_pkt_type(skb) = HCI_ACLDATA_PKT;
+
+- switch (hdev->dev_type) {
+- case HCI_PRIMARY:
+- hci_add_acl_hdr(skb, conn->handle, flags);
+- break;
+- case HCI_AMP:
+- hci_add_acl_hdr(skb, chan->handle, flags);
+- break;
+- default:
+- bt_dev_err(hdev, "unknown dev_type %d", hdev->dev_type);
+- return;
+- }
++ hci_add_acl_hdr(skb, conn->handle, flags);
+
+ list = skb_shinfo(skb)->frag_list;
+ if (!list) {
+@@ -3380,9 +3353,6 @@ static inline void hci_quote_sent(struct hci_conn *conn, int num, int *quote)
+ case ACL_LINK:
+ cnt = hdev->acl_cnt;
+ break;
+- case AMP_LINK:
+- cnt = hdev->block_cnt;
+- break;
+ case SCO_LINK:
+ case ESCO_LINK:
+ cnt = hdev->sco_cnt;
+@@ -3580,12 +3550,6 @@ static void hci_prio_recalculate(struct hci_dev *hdev, __u8 type)
+
+ }
+
+-static inline int __get_blocks(struct hci_dev *hdev, struct sk_buff *skb)
+-{
+- /* Calculate count of blocks used by this packet */
+- return DIV_ROUND_UP(skb->len - HCI_ACL_HDR_SIZE, hdev->block_len);
+-}
+-
+ static void __check_timeout(struct hci_dev *hdev, unsigned int cnt, u8 type)
+ {
+ unsigned long last_tx;
+@@ -3699,81 +3663,15 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev)
+ hci_prio_recalculate(hdev, ACL_LINK);
+ }
+
+-static void hci_sched_acl_blk(struct hci_dev *hdev)
+-{
+- unsigned int cnt = hdev->block_cnt;
+- struct hci_chan *chan;
+- struct sk_buff *skb;
+- int quote;
+- u8 type;
+-
+- BT_DBG("%s", hdev->name);
+-
+- if (hdev->dev_type == HCI_AMP)
+- type = AMP_LINK;
+- else
+- type = ACL_LINK;
+-
+- __check_timeout(hdev, cnt, type);
+-
+- while (hdev->block_cnt > 0 &&
+- (chan = hci_chan_sent(hdev, type, "e))) {
+- u32 priority = (skb_peek(&chan->data_q))->priority;
+- while (quote > 0 && (skb = skb_peek(&chan->data_q))) {
+- int blocks;
+-
+- BT_DBG("chan %p skb %p len %d priority %u", chan, skb,
+- skb->len, skb->priority);
+-
+- /* Stop if priority has changed */
+- if (skb->priority < priority)
+- break;
+-
+- skb = skb_dequeue(&chan->data_q);
+-
+- blocks = __get_blocks(hdev, skb);
+- if (blocks > hdev->block_cnt)
+- return;
+-
+- hci_conn_enter_active_mode(chan->conn,
+- bt_cb(skb)->force_active);
+-
+- hci_send_frame(hdev, skb);
+- hdev->acl_last_tx = jiffies;
+-
+- hdev->block_cnt -= blocks;
+- quote -= blocks;
+-
+- chan->sent += blocks;
+- chan->conn->sent += blocks;
+- }
+- }
+-
+- if (cnt != hdev->block_cnt)
+- hci_prio_recalculate(hdev, type);
+-}
+-
+ static void hci_sched_acl(struct hci_dev *hdev)
+ {
+ BT_DBG("%s", hdev->name);
+
+ /* No ACL link over BR/EDR controller */
+- if (!hci_conn_num(hdev, ACL_LINK) && hdev->dev_type == HCI_PRIMARY)
+- return;
+-
+- /* No AMP link over AMP controller */
+- if (!hci_conn_num(hdev, AMP_LINK) && hdev->dev_type == HCI_AMP)
++ if (!hci_conn_num(hdev, ACL_LINK))
+ return;
+
+- switch (hdev->flow_ctl_mode) {
+- case HCI_FLOW_CTL_MODE_PACKET_BASED:
+- hci_sched_acl_pkt(hdev);
+- break;
+-
+- case HCI_FLOW_CTL_MODE_BLOCK_BASED:
+- hci_sched_acl_blk(hdev);
+- break;
+- }
++ hci_sched_acl_pkt(hdev);
+ }
+
+ static void hci_sched_le(struct hci_dev *hdev)
+diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
+index c19d78e5d2053..cce73749f2dce 100644
+--- a/net/bluetooth/hci_event.c
++++ b/net/bluetooth/hci_event.c
+@@ -913,21 +913,6 @@ static u8 hci_cc_read_local_ext_features(struct hci_dev *hdev, void *data,
+ return rp->status;
+ }
+
+-static u8 hci_cc_read_flow_control_mode(struct hci_dev *hdev, void *data,
+- struct sk_buff *skb)
+-{
+- struct hci_rp_read_flow_control_mode *rp = data;
+-
+- bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+-
+- if (rp->status)
+- return rp->status;
+-
+- hdev->flow_ctl_mode = rp->mode;
+-
+- return rp->status;
+-}
+-
+ static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data,
+ struct sk_buff *skb)
+ {
+@@ -1071,28 +1056,6 @@ static u8 hci_cc_write_page_scan_type(struct hci_dev *hdev, void *data,
+ return rp->status;
+ }
+
+-static u8 hci_cc_read_data_block_size(struct hci_dev *hdev, void *data,
+- struct sk_buff *skb)
+-{
+- struct hci_rp_read_data_block_size *rp = data;
+-
+- bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+-
+- if (rp->status)
+- return rp->status;
+-
+- hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
+- hdev->block_len = __le16_to_cpu(rp->block_len);
+- hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
+-
+- hdev->block_cnt = hdev->num_blocks;
+-
+- BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
+- hdev->block_cnt, hdev->block_len);
+-
+- return rp->status;
+-}
+-
+ static u8 hci_cc_read_clock(struct hci_dev *hdev, void *data,
+ struct sk_buff *skb)
+ {
+@@ -1127,30 +1090,6 @@ static u8 hci_cc_read_clock(struct hci_dev *hdev, void *data,
+ return rp->status;
+ }
+
+-static u8 hci_cc_read_local_amp_info(struct hci_dev *hdev, void *data,
+- struct sk_buff *skb)
+-{
+- struct hci_rp_read_local_amp_info *rp = data;
+-
+- bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
+-
+- if (rp->status)
+- return rp->status;
+-
+- hdev->amp_status = rp->amp_status;
+- hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
+- hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
+- hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
+- hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
+- hdev->amp_type = rp->amp_type;
+- hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
+- hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
+- hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
+- hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
+-
+- return rp->status;
+-}
+-
+ static u8 hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, void *data,
+ struct sk_buff *skb)
+ {
+@@ -4121,12 +4060,6 @@ static const struct hci_cc {
+ HCI_CC(HCI_OP_READ_PAGE_SCAN_TYPE, hci_cc_read_page_scan_type,
+ sizeof(struct hci_rp_read_page_scan_type)),
+ HCI_CC_STATUS(HCI_OP_WRITE_PAGE_SCAN_TYPE, hci_cc_write_page_scan_type),
+- HCI_CC(HCI_OP_READ_DATA_BLOCK_SIZE, hci_cc_read_data_block_size,
+- sizeof(struct hci_rp_read_data_block_size)),
+- HCI_CC(HCI_OP_READ_FLOW_CONTROL_MODE, hci_cc_read_flow_control_mode,
+- sizeof(struct hci_rp_read_flow_control_mode)),
+- HCI_CC(HCI_OP_READ_LOCAL_AMP_INFO, hci_cc_read_local_amp_info,
+- sizeof(struct hci_rp_read_local_amp_info)),
+ HCI_CC(HCI_OP_READ_CLOCK, hci_cc_read_clock,
+ sizeof(struct hci_rp_read_clock)),
+ HCI_CC(HCI_OP_READ_ENC_KEY_SIZE, hci_cc_read_enc_key_size,
+@@ -4317,7 +4250,7 @@ static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
+ hci_dev_lock(hdev);
+
+ /* Remove connection if command failed */
+- for (i = 0; cp->num_cis; cp->num_cis--, i++) {
++ for (i = 0; i < cp->num_cis; i++) {
+ struct hci_conn *conn;
+ u16 handle;
+
+@@ -4333,6 +4266,7 @@ static void hci_cs_le_create_cis(struct hci_dev *hdev, u8 status)
+ hci_conn_del(conn);
+ }
+ }
++ cp->num_cis = 0;
+
+ if (pending)
+ hci_le_create_cis_pending(hdev);
+@@ -4461,11 +4395,6 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
+ flex_array_size(ev, handles, ev->num)))
+ return;
+
+- if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
+- bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
+- return;
+- }
+-
+ bt_dev_dbg(hdev, "num %d", ev->num);
+
+ for (i = 0; i < ev->num; i++) {
+@@ -4533,78 +4462,6 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
+ queue_work(hdev->workqueue, &hdev->tx_work);
+ }
+
+-static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
+- __u16 handle)
+-{
+- struct hci_chan *chan;
+-
+- switch (hdev->dev_type) {
+- case HCI_PRIMARY:
+- return hci_conn_hash_lookup_handle(hdev, handle);
+- case HCI_AMP:
+- chan = hci_chan_lookup_handle(hdev, handle);
+- if (chan)
+- return chan->conn;
+- break;
+- default:
+- bt_dev_err(hdev, "unknown dev_type %d", hdev->dev_type);
+- break;
+- }
+-
+- return NULL;
+-}
+-
+-static void hci_num_comp_blocks_evt(struct hci_dev *hdev, void *data,
+- struct sk_buff *skb)
+-{
+- struct hci_ev_num_comp_blocks *ev = data;
+- int i;
+-
+- if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_BLOCKS,
+- flex_array_size(ev, handles, ev->num_hndl)))
+- return;
+-
+- if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
+- bt_dev_err(hdev, "wrong event for mode %d",
+- hdev->flow_ctl_mode);
+- return;
+- }
+-
+- bt_dev_dbg(hdev, "num_blocks %d num_hndl %d", ev->num_blocks,
+- ev->num_hndl);
+-
+- for (i = 0; i < ev->num_hndl; i++) {
+- struct hci_comp_blocks_info *info = &ev->handles[i];
+- struct hci_conn *conn = NULL;
+- __u16 handle, block_count;
+-
+- handle = __le16_to_cpu(info->handle);
+- block_count = __le16_to_cpu(info->blocks);
+-
+- conn = __hci_conn_lookup_handle(hdev, handle);
+- if (!conn)
+- continue;
+-
+- conn->sent -= block_count;
+-
+- switch (conn->type) {
+- case ACL_LINK:
+- case AMP_LINK:
+- hdev->block_cnt += block_count;
+- if (hdev->block_cnt > hdev->num_blocks)
+- hdev->block_cnt = hdev->num_blocks;
+- break;
+-
+- default:
+- bt_dev_err(hdev, "unknown type %d conn %p",
+- conn->type, conn);
+- break;
+- }
+- }
+-
+- queue_work(hdev->workqueue, &hdev->tx_work);
+-}
+-
+ static void hci_mode_change_evt(struct hci_dev *hdev, void *data,
+ struct sk_buff *skb)
+ {
+@@ -5697,150 +5554,6 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, void *edata,
+ hci_dev_unlock(hdev);
+ }
+
+-#if IS_ENABLED(CONFIG_BT_HS)
+-static void hci_chan_selected_evt(struct hci_dev *hdev, void *data,
+- struct sk_buff *skb)
+-{
+- struct hci_ev_channel_selected *ev = data;
+- struct hci_conn *hcon;
+-
+- bt_dev_dbg(hdev, "handle 0x%2.2x", ev->phy_handle);
+-
+- hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+- if (!hcon)
+- return;
+-
+- amp_read_loc_assoc_final_data(hdev, hcon);
+-}
+-
+-static void hci_phy_link_complete_evt(struct hci_dev *hdev, void *data,
+- struct sk_buff *skb)
+-{
+- struct hci_ev_phy_link_complete *ev = data;
+- struct hci_conn *hcon, *bredr_hcon;
+-
+- bt_dev_dbg(hdev, "handle 0x%2.2x status 0x%2.2x", ev->phy_handle,
+- ev->status);
+-
+- hci_dev_lock(hdev);
+-
+- hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+- if (!hcon)
+- goto unlock;
+-
+- if (!hcon->amp_mgr)
+- goto unlock;
+-
+- if (ev->status) {
+- hci_conn_del(hcon);
+- goto unlock;
+- }
+-
+- bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
+-
+- hcon->state = BT_CONNECTED;
+- bacpy(&hcon->dst, &bredr_hcon->dst);
+-
+- hci_conn_hold(hcon);
+- hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
+- hci_conn_drop(hcon);
+-
+- hci_debugfs_create_conn(hcon);
+- hci_conn_add_sysfs(hcon);
+-
+- amp_physical_cfm(bredr_hcon, hcon);
+-
+-unlock:
+- hci_dev_unlock(hdev);
+-}
+-
+-static void hci_loglink_complete_evt(struct hci_dev *hdev, void *data,
+- struct sk_buff *skb)
+-{
+- struct hci_ev_logical_link_complete *ev = data;
+- struct hci_conn *hcon;
+- struct hci_chan *hchan;
+- struct amp_mgr *mgr;
+-
+- bt_dev_dbg(hdev, "log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
+- le16_to_cpu(ev->handle), ev->phy_handle, ev->status);
+-
+- hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+- if (!hcon)
+- return;
+-
+- /* Create AMP hchan */
+- hchan = hci_chan_create(hcon);
+- if (!hchan)
+- return;
+-
+- hchan->handle = le16_to_cpu(ev->handle);
+- hchan->amp = true;
+-
+- BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
+-
+- mgr = hcon->amp_mgr;
+- if (mgr && mgr->bredr_chan) {
+- struct l2cap_chan *bredr_chan = mgr->bredr_chan;
+-
+- l2cap_chan_lock(bredr_chan);
+-
+- bredr_chan->conn->mtu = hdev->block_mtu;
+- l2cap_logical_cfm(bredr_chan, hchan, 0);
+- hci_conn_hold(hcon);
+-
+- l2cap_chan_unlock(bredr_chan);
+- }
+-}
+-
+-static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, void *data,
+- struct sk_buff *skb)
+-{
+- struct hci_ev_disconn_logical_link_complete *ev = data;
+- struct hci_chan *hchan;
+-
+- bt_dev_dbg(hdev, "handle 0x%4.4x status 0x%2.2x",
+- le16_to_cpu(ev->handle), ev->status);
+-
+- if (ev->status)
+- return;
+-
+- hci_dev_lock(hdev);
+-
+- hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
+- if (!hchan || !hchan->amp)
+- goto unlock;
+-
+- amp_destroy_logical_link(hchan, ev->reason);
+-
+-unlock:
+- hci_dev_unlock(hdev);
+-}
+-
+-static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, void *data,
+- struct sk_buff *skb)
+-{
+- struct hci_ev_disconn_phy_link_complete *ev = data;
+- struct hci_conn *hcon;
+-
+- bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
+-
+- if (ev->status)
+- return;
+-
+- hci_dev_lock(hdev);
+-
+- hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
+- if (hcon && hcon->type == AMP_LINK) {
+- hcon->state = BT_CLOSED;
+- hci_disconn_cfm(hcon, ev->reason);
+- hci_conn_del(hcon);
+- }
+-
+- hci_dev_unlock(hdev);
+-}
+-#endif
+-
+ static void le_conn_update_addr(struct hci_conn *conn, bdaddr_t *bdaddr,
+ u8 bdaddr_type, bdaddr_t *local_rpa)
+ {
+@@ -7656,28 +7369,6 @@ static const struct hci_ev {
+ /* [0x3e = HCI_EV_LE_META] */
+ HCI_EV_REQ_VL(HCI_EV_LE_META, hci_le_meta_evt,
+ sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE),
+-#if IS_ENABLED(CONFIG_BT_HS)
+- /* [0x40 = HCI_EV_PHY_LINK_COMPLETE] */
+- HCI_EV(HCI_EV_PHY_LINK_COMPLETE, hci_phy_link_complete_evt,
+- sizeof(struct hci_ev_phy_link_complete)),
+- /* [0x41 = HCI_EV_CHANNEL_SELECTED] */
+- HCI_EV(HCI_EV_CHANNEL_SELECTED, hci_chan_selected_evt,
+- sizeof(struct hci_ev_channel_selected)),
+- /* [0x42 = HCI_EV_DISCONN_PHY_LINK_COMPLETE] */
+- HCI_EV(HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE,
+- hci_disconn_loglink_complete_evt,
+- sizeof(struct hci_ev_disconn_logical_link_complete)),
+- /* [0x45 = HCI_EV_LOGICAL_LINK_COMPLETE] */
+- HCI_EV(HCI_EV_LOGICAL_LINK_COMPLETE, hci_loglink_complete_evt,
+- sizeof(struct hci_ev_logical_link_complete)),
+- /* [0x46 = HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE] */
+- HCI_EV(HCI_EV_DISCONN_PHY_LINK_COMPLETE,
+- hci_disconn_phylink_complete_evt,
+- sizeof(struct hci_ev_disconn_phy_link_complete)),
+-#endif
+- /* [0x48 = HCI_EV_NUM_COMP_BLOCKS] */
+- HCI_EV(HCI_EV_NUM_COMP_BLOCKS, hci_num_comp_blocks_evt,
+- sizeof(struct hci_ev_num_comp_blocks)),
+ /* [0xff = HCI_EV_VENDOR] */
+ HCI_EV_VL(HCI_EV_VENDOR, msft_vendor_evt, 0, HCI_MAX_EVENT_SIZE),
+ };
+diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
+index 3f5f0932330d2..69c2ba1e843eb 100644
+--- a/net/bluetooth/hci_sock.c
++++ b/net/bluetooth/hci_sock.c
+@@ -101,7 +101,7 @@ static bool hci_sock_gen_cookie(struct sock *sk)
+ int id = hci_pi(sk)->cookie;
+
+ if (!id) {
+- id = ida_simple_get(&sock_cookie_ida, 1, 0, GFP_KERNEL);
++ id = ida_alloc_min(&sock_cookie_ida, 1, GFP_KERNEL);
+ if (id < 0)
+ id = 0xffffffff;
+
+@@ -119,7 +119,7 @@ static void hci_sock_free_cookie(struct sock *sk)
+
+ if (id) {
+ hci_pi(sk)->cookie = 0xffffffff;
+- ida_simple_remove(&sock_cookie_ida, id);
++ ida_free(&sock_cookie_ida, id);
+ }
+ }
+
+@@ -485,7 +485,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event)
+ return NULL;
+
+ ni = skb_put(skb, HCI_MON_NEW_INDEX_SIZE);
+- ni->type = hdev->dev_type;
++ ni->type = 0x00; /* Old hdev->dev_type */
+ ni->bus = hdev->bus;
+ bacpy(&ni->bdaddr, &hdev->bdaddr);
+ memcpy_and_pad(ni->name, sizeof(ni->name), hdev->name,
+@@ -1007,9 +1007,6 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
+ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
+ return -EOPNOTSUPP;
+
+- if (hdev->dev_type != HCI_PRIMARY)
+- return -EOPNOTSUPP;
+-
+ switch (cmd) {
+ case HCISETRAW:
+ if (!capable(CAP_NET_ADMIN))
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 40b71bc505730..097d1c8713d8c 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -1043,11 +1043,10 @@ static int hci_disable_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance)
+ struct hci_cp_ext_adv_set *set;
+ u8 data[sizeof(*cp) + sizeof(*set) * 1];
+ u8 size;
++ struct adv_info *adv = NULL;
+
+ /* If request specifies an instance that doesn't exist, fail */
+ if (instance > 0) {
+- struct adv_info *adv;
+-
+ adv = hci_find_adv_instance(hdev, instance);
+ if (!adv)
+ return -EINVAL;
+@@ -1066,7 +1065,7 @@ static int hci_disable_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance)
+ cp->num_of_sets = !!instance;
+ cp->enable = 0x00;
+
+- set->handle = instance;
++ set->handle = adv ? adv->handle : instance;
+
+ size = sizeof(*cp) + sizeof(*set) * cp->num_of_sets;
+
+@@ -1235,31 +1234,27 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance)
+
+ static int hci_set_ext_scan_rsp_data_sync(struct hci_dev *hdev, u8 instance)
+ {
+- struct {
+- struct hci_cp_le_set_ext_scan_rsp_data cp;
+- u8 data[HCI_MAX_EXT_AD_LENGTH];
+- } pdu;
++ DEFINE_FLEX(struct hci_cp_le_set_ext_scan_rsp_data, pdu, data, length,
++ HCI_MAX_EXT_AD_LENGTH);
+ u8 len;
+ struct adv_info *adv = NULL;
+ int err;
+
+- memset(&pdu, 0, sizeof(pdu));
+-
+ if (instance) {
+ adv = hci_find_adv_instance(hdev, instance);
+ if (!adv || !adv->scan_rsp_changed)
+ return 0;
+ }
+
+- len = eir_create_scan_rsp(hdev, instance, pdu.data);
++ len = eir_create_scan_rsp(hdev, instance, pdu->data);
+
+- pdu.cp.handle = instance;
+- pdu.cp.length = len;
+- pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
+- pdu.cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
++ pdu->handle = adv ? adv->handle : instance;
++ pdu->length = len;
++ pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE;
++ pdu->frag_pref = LE_SET_ADV_DATA_NO_FRAG;
+
+ err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA,
+- sizeof(pdu.cp) + len, &pdu.cp,
++ struct_size(pdu, data, len), pdu,
+ HCI_CMD_TIMEOUT);
+ if (err)
+ return err;
+@@ -1267,7 +1262,7 @@ static int hci_set_ext_scan_rsp_data_sync(struct hci_dev *hdev, u8 instance)
+ if (adv) {
+ adv->scan_rsp_changed = false;
+ } else {
+- memcpy(hdev->scan_rsp_data, pdu.data, len);
++ memcpy(hdev->scan_rsp_data, pdu->data, len);
+ hdev->scan_rsp_data_len = len;
+ }
+
+@@ -1335,7 +1330,7 @@ int hci_enable_ext_advertising_sync(struct hci_dev *hdev, u8 instance)
+
+ memset(set, 0, sizeof(*set));
+
+- set->handle = instance;
++ set->handle = adv ? adv->handle : instance;
+
+ /* Set duration per instance since controller is responsible for
+ * scheduling it.
+@@ -1411,29 +1406,25 @@ static int hci_set_per_adv_params_sync(struct hci_dev *hdev, u8 instance,
+
+ static int hci_set_per_adv_data_sync(struct hci_dev *hdev, u8 instance)
+ {
+- struct {
+- struct hci_cp_le_set_per_adv_data cp;
+- u8 data[HCI_MAX_PER_AD_LENGTH];
+- } pdu;
++ DEFINE_FLEX(struct hci_cp_le_set_per_adv_data, pdu, data, length,
++ HCI_MAX_PER_AD_LENGTH);
+ u8 len;
+-
+- memset(&pdu, 0, sizeof(pdu));
++ struct adv_info *adv = NULL;
+
+ if (instance) {
+- struct adv_info *adv = hci_find_adv_instance(hdev, instance);
+-
++ adv = hci_find_adv_instance(hdev, instance);
+ if (!adv || !adv->periodic)
+ return 0;
+ }
+
+- len = eir_create_per_adv_data(hdev, instance, pdu.data);
++ len = eir_create_per_adv_data(hdev, instance, pdu->data);
+
+- pdu.cp.length = len;
+- pdu.cp.handle = instance;
+- pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
++ pdu->length = len;
++ pdu->handle = adv ? adv->handle : instance;
++ pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE;
+
+ return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_PER_ADV_DATA,
+- sizeof(pdu.cp) + len, &pdu,
++ struct_size(pdu, data, len), pdu,
+ HCI_CMD_TIMEOUT);
+ }
+
+@@ -1727,31 +1718,27 @@ int hci_le_terminate_big_sync(struct hci_dev *hdev, u8 handle, u8 reason)
+
+ static int hci_set_ext_adv_data_sync(struct hci_dev *hdev, u8 instance)
+ {
+- struct {
+- struct hci_cp_le_set_ext_adv_data cp;
+- u8 data[HCI_MAX_EXT_AD_LENGTH];
+- } pdu;
++ DEFINE_FLEX(struct hci_cp_le_set_ext_adv_data, pdu, data, length,
++ HCI_MAX_EXT_AD_LENGTH);
+ u8 len;
+ struct adv_info *adv = NULL;
+ int err;
+
+- memset(&pdu, 0, sizeof(pdu));
+-
+ if (instance) {
+ adv = hci_find_adv_instance(hdev, instance);
+ if (!adv || !adv->adv_data_changed)
+ return 0;
+ }
+
+- len = eir_create_adv_data(hdev, instance, pdu.data);
++ len = eir_create_adv_data(hdev, instance, pdu->data);
+
+- pdu.cp.length = len;
+- pdu.cp.handle = instance;
+- pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE;
+- pdu.cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG;
++ pdu->length = len;
++ pdu->handle = adv ? adv->handle : instance;
++ pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE;
++ pdu->frag_pref = LE_SET_ADV_DATA_NO_FRAG;
+
+ err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_ADV_DATA,
+- sizeof(pdu.cp) + len, &pdu.cp,
++ struct_size(pdu, data, len), pdu,
+ HCI_CMD_TIMEOUT);
+ if (err)
+ return err;
+@@ -1760,7 +1747,7 @@ static int hci_set_ext_adv_data_sync(struct hci_dev *hdev, u8 instance)
+ if (adv) {
+ adv->adv_data_changed = false;
+ } else {
+- memcpy(hdev->adv_data, pdu.data, len);
++ memcpy(hdev->adv_data, pdu->data, len);
+ hdev->adv_data_len = len;
+ }
+
+@@ -3488,10 +3475,6 @@ static int hci_unconf_init_sync(struct hci_dev *hdev)
+ /* Read Local Supported Features. */
+ static int hci_read_local_features_sync(struct hci_dev *hdev)
+ {
+- /* Not all AMP controllers support this command */
+- if (hdev->dev_type == HCI_AMP && !(hdev->commands[14] & 0x20))
+- return 0;
+-
+ return __hci_cmd_sync_status(hdev, HCI_OP_READ_LOCAL_FEATURES,
+ 0, NULL, HCI_CMD_TIMEOUT);
+ }
+@@ -3526,51 +3509,6 @@ static int hci_read_local_cmds_sync(struct hci_dev *hdev)
+ return 0;
+ }
+
+-/* Read Local AMP Info */
+-static int hci_read_local_amp_info_sync(struct hci_dev *hdev)
+-{
+- return __hci_cmd_sync_status(hdev, HCI_OP_READ_LOCAL_AMP_INFO,
+- 0, NULL, HCI_CMD_TIMEOUT);
+-}
+-
+-/* Read Data Blk size */
+-static int hci_read_data_block_size_sync(struct hci_dev *hdev)
+-{
+- return __hci_cmd_sync_status(hdev, HCI_OP_READ_DATA_BLOCK_SIZE,
+- 0, NULL, HCI_CMD_TIMEOUT);
+-}
+-
+-/* Read Flow Control Mode */
+-static int hci_read_flow_control_mode_sync(struct hci_dev *hdev)
+-{
+- return __hci_cmd_sync_status(hdev, HCI_OP_READ_FLOW_CONTROL_MODE,
+- 0, NULL, HCI_CMD_TIMEOUT);
+-}
+-
+-/* Read Location Data */
+-static int hci_read_location_data_sync(struct hci_dev *hdev)
+-{
+- return __hci_cmd_sync_status(hdev, HCI_OP_READ_LOCATION_DATA,
+- 0, NULL, HCI_CMD_TIMEOUT);
+-}
+-
+-/* AMP Controller init stage 1 command sequence */
+-static const struct hci_init_stage amp_init1[] = {
+- /* HCI_OP_READ_LOCAL_VERSION */
+- HCI_INIT(hci_read_local_version_sync),
+- /* HCI_OP_READ_LOCAL_COMMANDS */
+- HCI_INIT(hci_read_local_cmds_sync),
+- /* HCI_OP_READ_LOCAL_AMP_INFO */
+- HCI_INIT(hci_read_local_amp_info_sync),
+- /* HCI_OP_READ_DATA_BLOCK_SIZE */
+- HCI_INIT(hci_read_data_block_size_sync),
+- /* HCI_OP_READ_FLOW_CONTROL_MODE */
+- HCI_INIT(hci_read_flow_control_mode_sync),
+- /* HCI_OP_READ_LOCATION_DATA */
+- HCI_INIT(hci_read_location_data_sync),
+- {}
+-};
+-
+ static int hci_init1_sync(struct hci_dev *hdev)
+ {
+ int err;
+@@ -3584,28 +3522,9 @@ static int hci_init1_sync(struct hci_dev *hdev)
+ return err;
+ }
+
+- switch (hdev->dev_type) {
+- case HCI_PRIMARY:
+- hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED;
+- return hci_init_stage_sync(hdev, br_init1);
+- case HCI_AMP:
+- hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED;
+- return hci_init_stage_sync(hdev, amp_init1);
+- default:
+- bt_dev_err(hdev, "Unknown device type %d", hdev->dev_type);
+- break;
+- }
+-
+- return 0;
++ return hci_init_stage_sync(hdev, br_init1);
+ }
+
+-/* AMP Controller init stage 2 command sequence */
+-static const struct hci_init_stage amp_init2[] = {
+- /* HCI_OP_READ_LOCAL_FEATURES */
+- HCI_INIT(hci_read_local_features_sync),
+- {}
+-};
+-
+ /* Read Buffer Size (ACL mtu, max pkt, etc.) */
+ static int hci_read_buffer_size_sync(struct hci_dev *hdev)
+ {
+@@ -3863,9 +3782,6 @@ static int hci_init2_sync(struct hci_dev *hdev)
+
+ bt_dev_dbg(hdev, "");
+
+- if (hdev->dev_type == HCI_AMP)
+- return hci_init_stage_sync(hdev, amp_init2);
+-
+ err = hci_init_stage_sync(hdev, hci_init2);
+ if (err)
+ return err;
+@@ -4703,13 +4619,6 @@ static int hci_init_sync(struct hci_dev *hdev)
+ if (err < 0)
+ return err;
+
+- /* HCI_PRIMARY covers both single-mode LE, BR/EDR and dual-mode
+- * BR/EDR/LE type controllers. AMP controllers only need the
+- * first two stages of init.
+- */
+- if (hdev->dev_type != HCI_PRIMARY)
+- return 0;
+-
+ err = hci_init3_sync(hdev);
+ if (err < 0)
+ return err;
+@@ -4938,12 +4847,8 @@ int hci_dev_open_sync(struct hci_dev *hdev)
+ * In case of user channel usage, it is not important
+ * if a public address or static random address is
+ * available.
+- *
+- * This check is only valid for BR/EDR controllers
+- * since AMP controllers do not have an address.
+ */
+ if (!hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
+- hdev->dev_type == HCI_PRIMARY &&
+ !bacmp(&hdev->bdaddr, BDADDR_ANY) &&
+ !bacmp(&hdev->static_addr, BDADDR_ANY)) {
+ ret = -EADDRNOTAVAIL;
+@@ -4978,8 +4883,7 @@ int hci_dev_open_sync(struct hci_dev *hdev)
+ !hci_dev_test_flag(hdev, HCI_CONFIG) &&
+ !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
+ !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
+- hci_dev_test_flag(hdev, HCI_MGMT) &&
+- hdev->dev_type == HCI_PRIMARY) {
++ hci_dev_test_flag(hdev, HCI_MGMT)) {
+ ret = hci_powered_update_sync(hdev);
+ mgmt_power_on(hdev, ret);
+ }
+@@ -5124,8 +5028,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+
+ auto_off = hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF);
+
+- if (!auto_off && hdev->dev_type == HCI_PRIMARY &&
+- !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
++ if (!auto_off && !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) &&
+ hci_dev_test_flag(hdev, HCI_MGMT))
+ __mgmt_power_off(hdev);
+
+@@ -5187,9 +5090,6 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+ hdev->flags &= BIT(HCI_RAW);
+ hci_dev_clear_volatile_flags(hdev);
+
+- /* Controller radio is available but is currently powered down */
+- hdev->amp_status = AMP_STATUS_POWERED_DOWN;
+-
+ memset(hdev->eir, 0, sizeof(hdev->eir));
+ memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
+ bacpy(&hdev->random_addr, BDADDR_ANY);
+@@ -5226,8 +5126,7 @@ static int hci_power_on_sync(struct hci_dev *hdev)
+ */
+ if (hci_dev_test_flag(hdev, HCI_RFKILLED) ||
+ hci_dev_test_flag(hdev, HCI_UNCONFIGURED) ||
+- (hdev->dev_type == HCI_PRIMARY &&
+- !bacmp(&hdev->bdaddr, BDADDR_ANY) &&
++ (!bacmp(&hdev->bdaddr, BDADDR_ANY) &&
+ !bacmp(&hdev->static_addr, BDADDR_ANY))) {
+ hci_dev_clear_flag(hdev, HCI_AUTO_OFF);
+ hci_dev_close_sync(hdev);
+@@ -5329,27 +5228,11 @@ int hci_stop_discovery_sync(struct hci_dev *hdev)
+ return 0;
+ }
+
+-static int hci_disconnect_phy_link_sync(struct hci_dev *hdev, u16 handle,
+- u8 reason)
+-{
+- struct hci_cp_disconn_phy_link cp;
+-
+- memset(&cp, 0, sizeof(cp));
+- cp.phy_handle = HCI_PHY_HANDLE(handle);
+- cp.reason = reason;
+-
+- return __hci_cmd_sync_status(hdev, HCI_OP_DISCONN_PHY_LINK,
+- sizeof(cp), &cp, HCI_CMD_TIMEOUT);
+-}
+-
+ static int hci_disconnect_sync(struct hci_dev *hdev, struct hci_conn *conn,
+ u8 reason)
+ {
+ struct hci_cp_disconnect cp;
+
+- if (conn->type == AMP_LINK)
+- return hci_disconnect_phy_link_sync(hdev, conn->handle, reason);
+-
+ if (test_bit(HCI_CONN_BIG_CREATED, &conn->flags)) {
+ /* This is a BIS connection, hci_conn_del will
+ * do the necessary cleanup.
+@@ -6462,10 +6345,8 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)
+
+ int hci_le_create_cis_sync(struct hci_dev *hdev)
+ {
+- struct {
+- struct hci_cp_le_create_cis cp;
+- struct hci_cis cis[0x1f];
+- } cmd;
++ DEFINE_FLEX(struct hci_cp_le_create_cis, cmd, cis, num_cis, 0x1f);
++ size_t aux_num_cis = 0;
+ struct hci_conn *conn;
+ u8 cig = BT_ISO_QOS_CIG_UNSET;
+
+@@ -6492,8 +6373,6 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
+ * remains pending.
+ */
+
+- memset(&cmd, 0, sizeof(cmd));
+-
+ hci_dev_lock(hdev);
+
+ rcu_read_lock();
+@@ -6530,7 +6409,7 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
+ goto done;
+
+ list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
+- struct hci_cis *cis = &cmd.cis[cmd.cp.num_cis];
++ struct hci_cis *cis = &cmd->cis[aux_num_cis];
+
+ if (hci_conn_check_create_cis(conn) ||
+ conn->iso_qos.ucast.cig != cig)
+@@ -6539,25 +6418,25 @@ int hci_le_create_cis_sync(struct hci_dev *hdev)
+ set_bit(HCI_CONN_CREATE_CIS, &conn->flags);
+ cis->acl_handle = cpu_to_le16(conn->parent->handle);
+ cis->cis_handle = cpu_to_le16(conn->handle);
+- cmd.cp.num_cis++;
++ aux_num_cis++;
+
+- if (cmd.cp.num_cis >= ARRAY_SIZE(cmd.cis))
++ if (aux_num_cis >= 0x1f)
+ break;
+ }
++ cmd->num_cis = aux_num_cis;
+
+ done:
+ rcu_read_unlock();
+
+ hci_dev_unlock(hdev);
+
+- if (!cmd.cp.num_cis)
++ if (!aux_num_cis)
+ return 0;
+
+ /* Wait for HCI_LE_CIS_Established */
+ return __hci_cmd_sync_status_sk(hdev, HCI_OP_LE_CREATE_CIS,
+- sizeof(cmd.cp) + sizeof(cmd.cis[0]) *
+- cmd.cp.num_cis, &cmd,
+- HCI_EVT_LE_CIS_ESTABLISHED,
++ struct_size(cmd, cis, cmd->num_cis),
++ cmd, HCI_EVT_LE_CIS_ESTABLISHED,
+ conn->conn_timeout, NULL);
+ }
+
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index 6d217df75c62c..6cb41f9d174e2 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -3,7 +3,7 @@
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2022 Intel Corporation
+- * Copyright 2023 NXP
++ * Copyright 2023-2024 NXP
+ */
+
+ #include <linux/module.h>
+@@ -85,8 +85,9 @@ static void iso_sock_disconn(struct sock *sk);
+
+ typedef bool (*iso_sock_match_t)(struct sock *sk, void *data);
+
+-static struct sock *iso_get_sock_listen(bdaddr_t *src, bdaddr_t *dst,
+- iso_sock_match_t match, void *data);
++static struct sock *iso_get_sock(bdaddr_t *src, bdaddr_t *dst,
++ enum bt_sock_state state,
++ iso_sock_match_t match, void *data);
+
+ /* ---- ISO timers ---- */
+ #define ISO_CONN_TIMEOUT (HZ * 40)
+@@ -233,10 +234,11 @@ static void iso_conn_del(struct hci_conn *hcon, int err)
+ * terminated are not processed anymore.
+ */
+ if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
+- parent = iso_get_sock_listen(&hcon->src,
+- &hcon->dst,
+- iso_match_conn_sync_handle,
+- hcon);
++ parent = iso_get_sock(&hcon->src,
++ &hcon->dst,
++ BT_LISTEN,
++ iso_match_conn_sync_handle,
++ hcon);
+
+ if (parent) {
+ set_bit(BT_SK_PA_SYNC_TERM,
+@@ -581,22 +583,23 @@ static struct sock *__iso_get_sock_listen_by_sid(bdaddr_t *ba, bdaddr_t *bc,
+ return NULL;
+ }
+
+-/* Find socket listening:
++/* Find socket in given state:
+ * source bdaddr (Unicast)
+ * destination bdaddr (Broadcast only)
+ * match func - pass NULL to ignore
+ * match func data - pass -1 to ignore
+ * Returns closest match.
+ */
+-static struct sock *iso_get_sock_listen(bdaddr_t *src, bdaddr_t *dst,
+- iso_sock_match_t match, void *data)
++static struct sock *iso_get_sock(bdaddr_t *src, bdaddr_t *dst,
++ enum bt_sock_state state,
++ iso_sock_match_t match, void *data)
+ {
+ struct sock *sk = NULL, *sk1 = NULL;
+
+ read_lock(&iso_sk_list.lock);
+
+ sk_for_each(sk, &iso_sk_list.head) {
+- if (sk->sk_state != BT_LISTEN)
++ if (sk->sk_state != state)
+ continue;
+
+ /* Match Broadcast destination */
+@@ -690,11 +693,8 @@ static void iso_sock_cleanup_listen(struct sock *parent)
+ iso_sock_kill(sk);
+ }
+
+- /* If listening socket stands for a PA sync connection,
+- * properly disconnect the hcon and socket.
+- */
+- if (iso_pi(parent)->conn && iso_pi(parent)->conn->hcon &&
+- test_bit(HCI_CONN_PA_SYNC, &iso_pi(parent)->conn->hcon->flags)) {
++ /* If listening socket has a hcon, properly disconnect it */
++ if (iso_pi(parent)->conn && iso_pi(parent)->conn->hcon) {
+ iso_sock_disconn(parent);
+ return;
+ }
+@@ -1076,6 +1076,8 @@ static int iso_listen_bis(struct sock *sk)
+ {
+ struct hci_dev *hdev;
+ int err = 0;
++ struct iso_conn *conn;
++ struct hci_conn *hcon;
+
+ BT_DBG("%pMR -> %pMR (SID 0x%2.2x)", &iso_pi(sk)->src,
+ &iso_pi(sk)->dst, iso_pi(sk)->bc_sid);
+@@ -1096,18 +1098,40 @@ static int iso_listen_bis(struct sock *sk)
+ if (!hdev)
+ return -EHOSTUNREACH;
+
++ hci_dev_lock(hdev);
++
+ /* Fail if user set invalid QoS */
+ if (iso_pi(sk)->qos_user_set && !check_bcast_qos(&iso_pi(sk)->qos)) {
+ iso_pi(sk)->qos = default_qos;
+- return -EINVAL;
++ err = -EINVAL;
++ goto unlock;
++ }
++
++ hcon = hci_pa_create_sync(hdev, &iso_pi(sk)->dst,
++ le_addr_type(iso_pi(sk)->dst_type),
++ iso_pi(sk)->bc_sid, &iso_pi(sk)->qos);
++ if (IS_ERR(hcon)) {
++ err = PTR_ERR(hcon);
++ goto unlock;
++ }
++
++ conn = iso_conn_add(hcon);
++ if (!conn) {
++ hci_conn_drop(hcon);
++ err = -ENOMEM;
++ goto unlock;
+ }
+
+- err = hci_pa_create_sync(hdev, &iso_pi(sk)->dst,
+- le_addr_type(iso_pi(sk)->dst_type),
+- iso_pi(sk)->bc_sid, &iso_pi(sk)->qos);
++ err = iso_chan_add(conn, sk, NULL);
++ if (err) {
++ hci_conn_drop(hcon);
++ goto unlock;
++ }
+
+ hci_dev_put(hdev);
+
++unlock:
++ hci_dev_unlock(hdev);
+ return err;
+ }
+
+@@ -1756,32 +1780,37 @@ static void iso_conn_ready(struct iso_conn *conn)
+ HCI_EVT_LE_BIG_SYNC_ESTABILISHED);
+
+ /* Get reference to PA sync parent socket, if it exists */
+- parent = iso_get_sock_listen(&hcon->src,
+- &hcon->dst,
+- iso_match_pa_sync_flag, NULL);
++ parent = iso_get_sock(&hcon->src, &hcon->dst,
++ BT_LISTEN,
++ iso_match_pa_sync_flag,
++ NULL);
+ if (!parent && ev)
+- parent = iso_get_sock_listen(&hcon->src,
+- &hcon->dst,
+- iso_match_big, ev);
++ parent = iso_get_sock(&hcon->src,
++ &hcon->dst,
++ BT_LISTEN,
++ iso_match_big, ev);
+ } else if (test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
+ ev2 = hci_recv_event_data(hcon->hdev,
+ HCI_EV_LE_PA_SYNC_ESTABLISHED);
+ if (ev2)
+- parent = iso_get_sock_listen(&hcon->src,
+- &hcon->dst,
+- iso_match_sid, ev2);
++ parent = iso_get_sock(&hcon->src,
++ &hcon->dst,
++ BT_LISTEN,
++ iso_match_sid, ev2);
+ } else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags)) {
+ ev3 = hci_recv_event_data(hcon->hdev,
+ HCI_EVT_LE_BIG_INFO_ADV_REPORT);
+ if (ev3)
+- parent = iso_get_sock_listen(&hcon->src,
+- &hcon->dst,
+- iso_match_sync_handle, ev3);
++ parent = iso_get_sock(&hcon->src,
++ &hcon->dst,
++ BT_LISTEN,
++ iso_match_sync_handle,
++ ev3);
+ }
+
+ if (!parent)
+- parent = iso_get_sock_listen(&hcon->src,
+- BDADDR_ANY, NULL, NULL);
++ parent = iso_get_sock(&hcon->src, BDADDR_ANY,
++ BT_LISTEN, NULL, NULL);
+
+ if (!parent)
+ return;
+@@ -1883,7 +1912,6 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
+ struct hci_evt_le_big_info_adv_report *ev2;
+ struct hci_ev_le_per_adv_report *ev3;
+ struct sock *sk;
+- int lm = 0;
+
+ bt_dev_dbg(hdev, "bdaddr %pMR", bdaddr);
+
+@@ -1903,8 +1931,8 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
+ */
+ ev1 = hci_recv_event_data(hdev, HCI_EV_LE_PA_SYNC_ESTABLISHED);
+ if (ev1) {
+- sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr, iso_match_sid,
+- ev1);
++ sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
++ iso_match_sid, ev1);
+ if (sk && !ev1->status)
+ iso_pi(sk)->sync_handle = le16_to_cpu(ev1->handle);
+
+@@ -1914,12 +1942,12 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
+ ev2 = hci_recv_event_data(hdev, HCI_EVT_LE_BIG_INFO_ADV_REPORT);
+ if (ev2) {
+ /* Try to get PA sync listening socket, if it exists */
+- sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
+- iso_match_pa_sync_flag, NULL);
++ sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
++ iso_match_pa_sync_flag, NULL);
+
+ if (!sk) {
+- sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
+- iso_match_sync_handle, ev2);
++ sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
++ iso_match_sync_handle, ev2);
+
+ /* If PA Sync is in process of terminating,
+ * do not handle any more BIGInfo adv reports.
+@@ -1927,7 +1955,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
+
+ if (sk && test_bit(BT_SK_PA_SYNC_TERM,
+ &iso_pi(sk)->flags))
+- return lm;
++ return 0;
+ }
+
+ if (sk) {
+@@ -1959,8 +1987,8 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
+ u8 *base;
+ struct hci_conn *hcon;
+
+- sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
+- iso_match_sync_handle_pa_report, ev3);
++ sk = iso_get_sock(&hdev->bdaddr, bdaddr, BT_LISTEN,
++ iso_match_sync_handle_pa_report, ev3);
+ if (!sk)
+ goto done;
+
+@@ -2009,21 +2037,20 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
+ hcon->le_per_adv_data_len = 0;
+ }
+ } else {
+- sk = iso_get_sock_listen(&hdev->bdaddr, BDADDR_ANY, NULL, NULL);
++ sk = iso_get_sock(&hdev->bdaddr, BDADDR_ANY,
++ BT_LISTEN, NULL, NULL);
+ }
+
+ done:
+ if (!sk)
+- return lm;
+-
+- lm |= HCI_LM_ACCEPT;
++ return 0;
+
+ if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags))
+ *flags |= HCI_PROTO_DEFER;
+
+ sock_put(sk);
+
+- return lm;
++ return HCI_LM_ACCEPT;
+ }
+
+ static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 3f7a82f10fe98..4a633c1b68825 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -457,6 +457,9 @@ struct l2cap_chan *l2cap_chan_create(void)
+ /* Set default lock nesting level */
+ atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
+
++ /* Available receive buffer space is initially unknown */
++ chan->rx_avail = -1;
++
+ write_lock(&chan_list_lock);
+ list_add(&chan->global_l, &chan_list);
+ write_unlock(&chan_list_lock);
+@@ -538,6 +541,28 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan)
+ }
+ EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults);
+
++static __u16 l2cap_le_rx_credits(struct l2cap_chan *chan)
++{
++ size_t sdu_len = chan->sdu ? chan->sdu->len : 0;
++
++ if (chan->mps == 0)
++ return 0;
++
++ /* If we don't know the available space in the receiver buffer, give
++ * enough credits for a full packet.
++ */
++ if (chan->rx_avail == -1)
++ return (chan->imtu / chan->mps) + 1;
++
++ /* If we know how much space is available in the receive buffer, give
++ * out as many credits as would fill the buffer.
++ */
++ if (chan->rx_avail <= sdu_len)
++ return 0;
++
++ return DIV_ROUND_UP(chan->rx_avail - sdu_len, chan->mps);
++}
++
+ static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
+ {
+ chan->sdu = NULL;
+@@ -546,8 +571,7 @@ static void l2cap_le_flowctl_init(struct l2cap_chan *chan, u16 tx_credits)
+ chan->tx_credits = tx_credits;
+ /* Derive MPS from connection MTU to stop HCI fragmentation */
+ chan->mps = min_t(u16, chan->imtu, chan->conn->mtu - L2CAP_HDR_SIZE);
+- /* Give enough credits for a full packet */
+- chan->rx_credits = (chan->imtu / chan->mps) + 1;
++ chan->rx_credits = l2cap_le_rx_credits(chan);
+
+ skb_queue_head_init(&chan->tx_q);
+ }
+@@ -559,7 +583,7 @@ static void l2cap_ecred_init(struct l2cap_chan *chan, u16 tx_credits)
+ /* L2CAP implementations shall support a minimum MPS of 64 octets */
+ if (chan->mps < L2CAP_ECRED_MIN_MPS) {
+ chan->mps = L2CAP_ECRED_MIN_MPS;
+- chan->rx_credits = (chan->imtu / chan->mps) + 1;
++ chan->rx_credits = l2cap_le_rx_credits(chan);
+ }
+ }
+
+@@ -3906,7 +3930,7 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn,
+ }
+
+ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
+- u8 *data, u8 rsp_code, u8 amp_id)
++ u8 *data, u8 rsp_code)
+ {
+ struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
+ struct l2cap_conn_rsp rsp;
+@@ -3985,17 +4009,8 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
+ status = L2CAP_CS_AUTHOR_PEND;
+ chan->ops->defer(chan);
+ } else {
+- /* Force pending result for AMP controllers.
+- * The connection will succeed after the
+- * physical link is up.
+- */
+- if (amp_id == AMP_ID_BREDR) {
+- l2cap_state_change(chan, BT_CONFIG);
+- result = L2CAP_CR_SUCCESS;
+- } else {
+- l2cap_state_change(chan, BT_CONNECT2);
+- result = L2CAP_CR_PEND;
+- }
++ l2cap_state_change(chan, BT_CONNECT2);
++ result = L2CAP_CR_PEND;
+ status = L2CAP_CS_NO_INFO;
+ }
+ } else {
+@@ -4060,7 +4075,7 @@ static int l2cap_connect_req(struct l2cap_conn *conn,
+ mgmt_device_connected(hdev, hcon, NULL, 0);
+ hci_dev_unlock(hdev);
+
+- l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
++ l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP);
+ return 0;
+ }
+
+@@ -6513,9 +6528,7 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
+ {
+ struct l2cap_conn *conn = chan->conn;
+ struct l2cap_le_credits pkt;
+- u16 return_credits;
+-
+- return_credits = (chan->imtu / chan->mps) + 1;
++ u16 return_credits = l2cap_le_rx_credits(chan);
+
+ if (chan->rx_credits >= return_credits)
+ return;
+@@ -6534,6 +6547,19 @@ static void l2cap_chan_le_send_credits(struct l2cap_chan *chan)
+ l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CREDITS, sizeof(pkt), &pkt);
+ }
+
++void l2cap_chan_rx_avail(struct l2cap_chan *chan, ssize_t rx_avail)
++{
++ if (chan->rx_avail == rx_avail)
++ return;
++
++ BT_DBG("chan %p has %zd bytes avail for rx", chan, rx_avail);
++
++ chan->rx_avail = rx_avail;
++
++ if (chan->state == BT_CONNECTED)
++ l2cap_chan_le_send_credits(chan);
++}
++
+ static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb)
+ {
+ int err;
+@@ -6543,6 +6569,12 @@ static int l2cap_ecred_recv(struct l2cap_chan *chan, struct sk_buff *skb)
+ /* Wait recv to confirm reception before updating the credits */
+ err = chan->ops->recv(chan, skb);
+
++ if (err < 0 && chan->rx_avail != -1) {
++ BT_ERR("Queueing received LE L2CAP data failed");
++ l2cap_send_disconn_req(chan, ECONNRESET);
++ return err;
++ }
++
+ /* Update credits whenever an SDU is received */
+ l2cap_chan_le_send_credits(chan);
+
+@@ -6565,7 +6597,8 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
+ }
+
+ chan->rx_credits--;
+- BT_DBG("rx_credits %u -> %u", chan->rx_credits + 1, chan->rx_credits);
++ BT_DBG("chan %p: rx_credits %u -> %u",
++ chan, chan->rx_credits + 1, chan->rx_credits);
+
+ /* Update if remote had run out of credits, this should only happens
+ * if the remote is not using the entire MPS.
+@@ -7453,10 +7486,6 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
+ struct l2cap_conn *conn = hcon->l2cap_data;
+ int len;
+
+- /* For AMP controller do not create l2cap conn */
+- if (!conn && hcon->hdev->dev_type != HCI_PRIMARY)
+- goto drop;
+-
+ if (!conn)
+ conn = l2cap_conn_add(hcon);
+
+diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
+index 5cc83f906c123..8645461d45e81 100644
+--- a/net/bluetooth/l2cap_sock.c
++++ b/net/bluetooth/l2cap_sock.c
+@@ -1131,6 +1131,34 @@ static int l2cap_sock_sendmsg(struct socket *sock, struct msghdr *msg,
+ return err;
+ }
+
++static void l2cap_publish_rx_avail(struct l2cap_chan *chan)
++{
++ struct sock *sk = chan->data;
++ ssize_t avail = sk->sk_rcvbuf - atomic_read(&sk->sk_rmem_alloc);
++ int expected_skbs, skb_overhead;
++
++ if (avail <= 0) {
++ l2cap_chan_rx_avail(chan, 0);
++ return;
++ }
++
++ if (!chan->mps) {
++ l2cap_chan_rx_avail(chan, -1);
++ return;
++ }
++
++ /* Correct available memory by estimated sk_buff overhead.
++ * This is significant due to small transfer sizes. However, accept
++ * at least one full packet if receive space is non-zero.
++ */
++ expected_skbs = DIV_ROUND_UP(avail, chan->mps);
++ skb_overhead = expected_skbs * sizeof(struct sk_buff);
++ if (skb_overhead < avail)
++ l2cap_chan_rx_avail(chan, avail - skb_overhead);
++ else
++ l2cap_chan_rx_avail(chan, -1);
++}
++
+ static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg,
+ size_t len, int flags)
+ {
+@@ -1167,28 +1195,33 @@ static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg,
+ else
+ err = bt_sock_recvmsg(sock, msg, len, flags);
+
+- if (pi->chan->mode != L2CAP_MODE_ERTM)
++ if (pi->chan->mode != L2CAP_MODE_ERTM &&
++ pi->chan->mode != L2CAP_MODE_LE_FLOWCTL &&
++ pi->chan->mode != L2CAP_MODE_EXT_FLOWCTL)
+ return err;
+
+- /* Attempt to put pending rx data in the socket buffer */
+-
+ lock_sock(sk);
+
+- if (!test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state))
+- goto done;
++ l2cap_publish_rx_avail(pi->chan);
+
+- if (pi->rx_busy_skb) {
+- if (!__sock_queue_rcv_skb(sk, pi->rx_busy_skb))
+- pi->rx_busy_skb = NULL;
+- else
++ /* Attempt to put pending rx data in the socket buffer */
++ while (!list_empty(&pi->rx_busy)) {
++ struct l2cap_rx_busy *rx_busy =
++ list_first_entry(&pi->rx_busy,
++ struct l2cap_rx_busy,
++ list);
++ if (__sock_queue_rcv_skb(sk, rx_busy->skb) < 0)
+ goto done;
++ list_del(&rx_busy->list);
++ kfree(rx_busy);
+ }
+
+ /* Restore data flow when half of the receive buffer is
+ * available. This avoids resending large numbers of
+ * frames.
+ */
+- if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf >> 1)
++ if (test_bit(CONN_LOCAL_BUSY, &pi->chan->conn_state) &&
++ atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf >> 1)
+ l2cap_chan_busy(pi->chan, 0);
+
+ done:
+@@ -1449,17 +1482,20 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
+ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
+ {
+ struct sock *sk = chan->data;
++ struct l2cap_pinfo *pi = l2cap_pi(sk);
+ int err;
+
+ lock_sock(sk);
+
+- if (l2cap_pi(sk)->rx_busy_skb) {
++ if (chan->mode == L2CAP_MODE_ERTM && !list_empty(&pi->rx_busy)) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ if (chan->mode != L2CAP_MODE_ERTM &&
+- chan->mode != L2CAP_MODE_STREAMING) {
++ chan->mode != L2CAP_MODE_STREAMING &&
++ chan->mode != L2CAP_MODE_LE_FLOWCTL &&
++ chan->mode != L2CAP_MODE_EXT_FLOWCTL) {
+ /* Even if no filter is attached, we could potentially
+ * get errors from security modules, etc.
+ */
+@@ -1470,7 +1506,9 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
+
+ err = __sock_queue_rcv_skb(sk, skb);
+
+- /* For ERTM, handle one skb that doesn't fit into the recv
++ l2cap_publish_rx_avail(chan);
++
++ /* For ERTM and LE, handle a skb that doesn't fit into the recv
+ * buffer. This is important to do because the data frames
+ * have already been acked, so the skb cannot be discarded.
+ *
+@@ -1479,8 +1517,18 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
+ * acked and reassembled until there is buffer space
+ * available.
+ */
+- if (err < 0 && chan->mode == L2CAP_MODE_ERTM) {
+- l2cap_pi(sk)->rx_busy_skb = skb;
++ if (err < 0 &&
++ (chan->mode == L2CAP_MODE_ERTM ||
++ chan->mode == L2CAP_MODE_LE_FLOWCTL ||
++ chan->mode == L2CAP_MODE_EXT_FLOWCTL)) {
++ struct l2cap_rx_busy *rx_busy =
++ kmalloc(sizeof(*rx_busy), GFP_KERNEL);
++ if (!rx_busy) {
++ err = -ENOMEM;
++ goto done;
++ }
++ rx_busy->skb = skb;
++ list_add_tail(&rx_busy->list, &pi->rx_busy);
+ l2cap_chan_busy(chan, 1);
+ err = 0;
+ }
+@@ -1706,6 +1754,8 @@ static const struct l2cap_ops l2cap_chan_ops = {
+
+ static void l2cap_sock_destruct(struct sock *sk)
+ {
++ struct l2cap_rx_busy *rx_busy, *next;
++
+ BT_DBG("sk %p", sk);
+
+ if (l2cap_pi(sk)->chan) {
+@@ -1713,9 +1763,10 @@ static void l2cap_sock_destruct(struct sock *sk)
+ l2cap_chan_put(l2cap_pi(sk)->chan);
+ }
+
+- if (l2cap_pi(sk)->rx_busy_skb) {
+- kfree_skb(l2cap_pi(sk)->rx_busy_skb);
+- l2cap_pi(sk)->rx_busy_skb = NULL;
++ list_for_each_entry_safe(rx_busy, next, &l2cap_pi(sk)->rx_busy, list) {
++ kfree_skb(rx_busy->skb);
++ list_del(&rx_busy->list);
++ kfree(rx_busy);
+ }
+
+ skb_queue_purge(&sk->sk_receive_queue);
+@@ -1799,6 +1850,8 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)
+
+ chan->data = sk;
+ chan->ops = &l2cap_chan_ops;
++
++ l2cap_publish_rx_avail(chan);
+ }
+
+ static struct proto l2cap_proto = {
+@@ -1820,6 +1873,8 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
+ sk->sk_destruct = l2cap_sock_destruct;
+ sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;
+
++ INIT_LIST_HEAD(&l2cap_pi(sk)->rx_busy);
++
+ chan = l2cap_chan_create();
+ if (!chan) {
+ sk_free(sk);
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index b8e05ddeedba9..d58d3e13910fa 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -443,8 +443,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
+
+ count = 0;
+ list_for_each_entry(d, &hci_dev_list, list) {
+- if (d->dev_type == HCI_PRIMARY &&
+- !hci_dev_test_flag(d, HCI_UNCONFIGURED))
++ if (!hci_dev_test_flag(d, HCI_UNCONFIGURED))
+ count++;
+ }
+
+@@ -468,8 +467,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
+ if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
+ continue;
+
+- if (d->dev_type == HCI_PRIMARY &&
+- !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
++ if (!hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
+ rp->index[count++] = cpu_to_le16(d->id);
+ bt_dev_dbg(hdev, "Added hci%u", d->id);
+ }
+@@ -503,8 +501,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
+
+ count = 0;
+ list_for_each_entry(d, &hci_dev_list, list) {
+- if (d->dev_type == HCI_PRIMARY &&
+- hci_dev_test_flag(d, HCI_UNCONFIGURED))
++ if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
+ count++;
+ }
+
+@@ -528,8 +525,7 @@ static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
+ if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
+ continue;
+
+- if (d->dev_type == HCI_PRIMARY &&
+- hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
++ if (hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
+ rp->index[count++] = cpu_to_le16(d->id);
+ bt_dev_dbg(hdev, "Added hci%u", d->id);
+ }
+@@ -561,10 +557,8 @@ static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
+ read_lock(&hci_dev_list_lock);
+
+ count = 0;
+- list_for_each_entry(d, &hci_dev_list, list) {
+- if (d->dev_type == HCI_PRIMARY || d->dev_type == HCI_AMP)
+- count++;
+- }
++ list_for_each_entry(d, &hci_dev_list, list)
++ count++;
+
+ rp = kmalloc(struct_size(rp, entry, count), GFP_ATOMIC);
+ if (!rp) {
+@@ -585,16 +579,10 @@ static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
+ if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
+ continue;
+
+- if (d->dev_type == HCI_PRIMARY) {
+- if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
+- rp->entry[count].type = 0x01;
+- else
+- rp->entry[count].type = 0x00;
+- } else if (d->dev_type == HCI_AMP) {
+- rp->entry[count].type = 0x02;
+- } else {
+- continue;
+- }
++ if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
++ rp->entry[count].type = 0x01;
++ else
++ rp->entry[count].type = 0x00;
+
+ rp->entry[count].bus = d->bus;
+ rp->entry[count++].index = cpu_to_le16(d->id);
+@@ -9325,23 +9313,14 @@ void mgmt_index_added(struct hci_dev *hdev)
+ if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+ return;
+
+- switch (hdev->dev_type) {
+- case HCI_PRIMARY:
+- if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
+- mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
+- NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
+- ev.type = 0x01;
+- } else {
+- mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
+- HCI_MGMT_INDEX_EVENTS);
+- ev.type = 0x00;
+- }
+- break;
+- case HCI_AMP:
+- ev.type = 0x02;
+- break;
+- default:
+- return;
++ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
++ mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0,
++ HCI_MGMT_UNCONF_INDEX_EVENTS);
++ ev.type = 0x01;
++ } else {
++ mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
++ HCI_MGMT_INDEX_EVENTS);
++ ev.type = 0x00;
+ }
+
+ ev.bus = hdev->bus;
+@@ -9358,25 +9337,16 @@ void mgmt_index_removed(struct hci_dev *hdev)
+ if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+ return;
+
+- switch (hdev->dev_type) {
+- case HCI_PRIMARY:
+- mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
++ mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
+
+- if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
+- mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
+- NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
+- ev.type = 0x01;
+- } else {
+- mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
+- HCI_MGMT_INDEX_EVENTS);
+- ev.type = 0x00;
+- }
+- break;
+- case HCI_AMP:
+- ev.type = 0x02;
+- break;
+- default:
+- return;
++ if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
++ mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0,
++ HCI_MGMT_UNCONF_INDEX_EVENTS);
++ ev.type = 0x01;
++ } else {
++ mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
++ HCI_MGMT_INDEX_EVENTS);
++ ev.type = 0x00;
+ }
+
+ ev.bus = hdev->bus;
+diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
+index 65cee0ad3c1b6..79b822be6c2e5 100644
+--- a/net/bridge/br_device.c
++++ b/net/bridge/br_device.c
+@@ -27,6 +27,7 @@ EXPORT_SYMBOL_GPL(nf_br_ops);
+ /* net device transmit always called with BH disabled */
+ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
++ enum skb_drop_reason reason = pskb_may_pull_reason(skb, ETH_HLEN);
+ struct net_bridge_mcast_port *pmctx_null = NULL;
+ struct net_bridge *br = netdev_priv(dev);
+ struct net_bridge_mcast *brmctx = &br->multicast_ctx;
+@@ -38,6 +39,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
+ const unsigned char *dest;
+ u16 vid = 0;
+
++ if (unlikely(reason != SKB_NOT_DROPPED_YET)) {
++ kfree_skb_reason(skb, reason);
++ return NETDEV_TX_OK;
++ }
++
+ memset(skb->cb, 0, sizeof(struct br_input_skb_cb));
+ br_tc_skb_miss_set(skb, false);
+
+diff --git a/net/bridge/br_mst.c b/net/bridge/br_mst.c
+index ee680adcee179..3c66141d34d62 100644
+--- a/net/bridge/br_mst.c
++++ b/net/bridge/br_mst.c
+@@ -78,7 +78,7 @@ static void br_mst_vlan_set_state(struct net_bridge_port *p, struct net_bridge_v
+ {
+ struct net_bridge_vlan_group *vg = nbp_vlan_group(p);
+
+- if (v->state == state)
++ if (br_vlan_get_state(v) == state)
+ return;
+
+ br_vlan_set_state(v, state);
+@@ -100,11 +100,12 @@ int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,
+ };
+ struct net_bridge_vlan_group *vg;
+ struct net_bridge_vlan *v;
+- int err;
++ int err = 0;
+
++ rcu_read_lock();
+ vg = nbp_vlan_group(p);
+ if (!vg)
+- return 0;
++ goto out;
+
+ /* MSTI 0 (CST) state changes are notified via the regular
+ * SWITCHDEV_ATTR_ID_PORT_STP_STATE.
+@@ -112,17 +113,20 @@ int br_mst_set_state(struct net_bridge_port *p, u16 msti, u8 state,
+ if (msti) {
+ err = switchdev_port_attr_set(p->dev, &attr, extack);
+ if (err && err != -EOPNOTSUPP)
+- return err;
++ goto out;
+ }
+
+- list_for_each_entry(v, &vg->vlan_list, vlist) {
++ err = 0;
++ list_for_each_entry_rcu(v, &vg->vlan_list, vlist) {
+ if (v->brvlan->msti != msti)
+ continue;
+
+ br_mst_vlan_set_state(p, v, state);
+ }
+
+- return 0;
++out:
++ rcu_read_unlock();
++ return err;
+ }
+
+ static void br_mst_vlan_sync_state(struct net_bridge_vlan *pv, u16 msti)
+diff --git a/net/core/dev.c b/net/core/dev.c
+index c365aa06f886f..a32811aebde59 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -10455,8 +10455,9 @@ static struct net_device *netdev_wait_allrefs_any(struct list_head *list)
+ rebroadcast_time = jiffies;
+ }
+
++ rcu_barrier();
++
+ if (!wait) {
+- rcu_barrier();
+ wait = WAIT_REFS_MIN_MSECS;
+ } else {
+ msleep(wait);
+diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
+index 68a065c0e5081..abd47159d7e4d 100644
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -2000,7 +2000,7 @@ int tcp_v4_early_demux(struct sk_buff *skb)
+ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb,
+ enum skb_drop_reason *reason)
+ {
+- u32 limit, tail_gso_size, tail_gso_segs;
++ u32 tail_gso_size, tail_gso_segs;
+ struct skb_shared_info *shinfo;
+ const struct tcphdr *th;
+ struct tcphdr *thtail;
+@@ -2009,6 +2009,7 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb,
+ bool fragstolen;
+ u32 gso_segs;
+ u32 gso_size;
++ u64 limit;
+ int delta;
+
+ /* In case all data was pulled from skb frags (in __pskb_pull_tail()),
+@@ -2106,7 +2107,13 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb,
+ __skb_push(skb, hdrlen);
+
+ no_coalesce:
+- limit = (u32)READ_ONCE(sk->sk_rcvbuf) + (u32)(READ_ONCE(sk->sk_sndbuf) >> 1);
++ /* sk->sk_backlog.len is reset only at the end of __release_sock().
++ * Both sk->sk_backlog.len and sk->sk_rmem_alloc could reach
++ * sk_rcvbuf in normal conditions.
++ */
++ limit = ((u64)READ_ONCE(sk->sk_rcvbuf)) << 1;
++
++ limit += ((u32)READ_ONCE(sk->sk_sndbuf)) >> 1;
+
+ /* Only socket owner can try to collapse/prune rx queues
+ * to reduce memory overhead, so add a little headroom here.
+@@ -2114,6 +2121,8 @@ bool tcp_add_backlog(struct sock *sk, struct sk_buff *skb,
+ */
+ limit += 64 * 1024;
+
++ limit = min_t(u64, limit, UINT_MAX);
++
+ if (unlikely(sk_add_backlog(sk, skb, limit))) {
+ bh_unlock_sock(sk);
+ *reason = SKB_DROP_REASON_SOCKET_BACKLOG;
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 9120694359af4..e980869f18176 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -429,15 +429,21 @@ static struct sock *udp4_lib_lookup2(struct net *net,
+ {
+ struct sock *sk, *result;
+ int score, badness;
++ bool need_rescore;
+
+ result = NULL;
+ badness = 0;
+ udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
+- score = compute_score(sk, net, saddr, sport,
+- daddr, hnum, dif, sdif);
++ need_rescore = false;
++rescore:
++ score = compute_score(need_rescore ? result : sk, net, saddr,
++ sport, daddr, hnum, dif, sdif);
+ if (score > badness) {
+ badness = score;
+
++ if (need_rescore)
++ continue;
++
+ if (sk->sk_state == TCP_ESTABLISHED) {
+ result = sk;
+ continue;
+@@ -458,9 +464,14 @@ static struct sock *udp4_lib_lookup2(struct net *net,
+ if (IS_ERR(result))
+ continue;
+
+- badness = compute_score(result, net, saddr, sport,
+- daddr, hnum, dif, sdif);
+-
++ /* compute_score is too long of a function to be
++ * inlined, and calling it again here yields
++ * measureable overhead for some
++ * workloads. Work around it by jumping
++ * backwards to rescore 'result'.
++ */
++ need_rescore = true;
++ goto rescore;
+ }
+ }
+ return result;
+diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
+index 5ebc47da1000c..2af98edef87ee 100644
+--- a/net/ipv6/reassembly.c
++++ b/net/ipv6/reassembly.c
+@@ -369,7 +369,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
+ * the source of the fragment, with the Pointer field set to zero.
+ */
+ nexthdr = hdr->nexthdr;
+- if (ipv6frag_thdr_truncated(skb, skb_transport_offset(skb), &nexthdr)) {
++ if (ipv6frag_thdr_truncated(skb, skb_network_offset(skb) + sizeof(struct ipv6hdr), &nexthdr)) {
+ __IP6_INC_STATS(net, __in6_dev_get_safely(skb->dev),
+ IPSTATS_MIB_INHDRERRORS);
+ icmpv6_param_prob(skb, ICMPV6_HDR_INCOMP, 0);
+diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
+index 35508abd76f43..a31521e270f78 100644
+--- a/net/ipv6/seg6.c
++++ b/net/ipv6/seg6.c
+@@ -551,6 +551,8 @@ int __init seg6_init(void)
+ #endif
+ #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
+ out_unregister_genl:
++#endif
++#if IS_ENABLED(CONFIG_IPV6_SEG6_LWTUNNEL) || IS_ENABLED(CONFIG_IPV6_SEG6_HMAC)
+ genl_unregister_family(&seg6_genl_family);
+ #endif
+ out_unregister_pernet:
+@@ -564,8 +566,9 @@ void seg6_exit(void)
+ seg6_hmac_exit();
+ #endif
+ #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
++ seg6_local_exit();
+ seg6_iptunnel_exit();
+ #endif
+- unregister_pernet_subsys(&ip6_segments_ops);
+ genl_unregister_family(&seg6_genl_family);
++ unregister_pernet_subsys(&ip6_segments_ops);
+ }
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index 785b2d076a6b3..936b51f358a9a 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -171,15 +171,21 @@ static struct sock *udp6_lib_lookup2(struct net *net,
+ {
+ struct sock *sk, *result;
+ int score, badness;
++ bool need_rescore;
+
+ result = NULL;
+ badness = -1;
+ udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {
+- score = compute_score(sk, net, saddr, sport,
+- daddr, hnum, dif, sdif);
++ need_rescore = false;
++rescore:
++ score = compute_score(need_rescore ? result : sk, net, saddr,
++ sport, daddr, hnum, dif, sdif);
+ if (score > badness) {
+ badness = score;
+
++ if (need_rescore)
++ continue;
++
+ if (sk->sk_state == TCP_ESTABLISHED) {
+ result = sk;
+ continue;
+@@ -200,8 +206,14 @@ static struct sock *udp6_lib_lookup2(struct net *net,
+ if (IS_ERR(result))
+ continue;
+
+- badness = compute_score(sk, net, saddr, sport,
+- daddr, hnum, dif, sdif);
++ /* compute_score is too long of a function to be
++ * inlined, and calling it again here yields
++ * measureable overhead for some
++ * workloads. Work around it by jumping
++ * backwards to rescore 'result'.
++ */
++ need_rescore = true;
++ goto rescore;
+ }
+ }
+ return result;
+diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
+index 8d21ff25f1602..4a0fb8731eee9 100644
+--- a/net/l2tp/l2tp_core.c
++++ b/net/l2tp/l2tp_core.c
+@@ -887,22 +887,20 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
+ return 1;
+ }
+
+-/* UDP encapsulation receive handler. See net/ipv4/udp.c.
+- * Return codes:
+- * 0 : success.
+- * <0: error
+- * >0: skb should be passed up to userspace as UDP.
++/* UDP encapsulation receive and error receive handlers.
++ * See net/ipv4/udp.c for details.
++ *
++ * Note that these functions are called from inside an
++ * RCU-protected region, but without the socket being locked.
++ *
++ * Hence we use rcu_dereference_sk_user_data to access the
++ * tunnel data structure rather the usual l2tp_sk_to_tunnel
++ * accessor function.
+ */
+ int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
+ {
+ struct l2tp_tunnel *tunnel;
+
+- /* Note that this is called from the encap_rcv hook inside an
+- * RCU-protected region, but without the socket being locked.
+- * Hence we use rcu_dereference_sk_user_data to access the
+- * tunnel data structure rather the usual l2tp_sk_to_tunnel
+- * accessor function.
+- */
+ tunnel = rcu_dereference_sk_user_data(sk);
+ if (!tunnel)
+ goto pass_up;
+@@ -919,6 +917,29 @@ int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
+ }
+ EXPORT_SYMBOL_GPL(l2tp_udp_encap_recv);
+
++static void l2tp_udp_encap_err_recv(struct sock *sk, struct sk_buff *skb, int err,
++ __be16 port, u32 info, u8 *payload)
++{
++ struct l2tp_tunnel *tunnel;
++
++ tunnel = rcu_dereference_sk_user_data(sk);
++ if (!tunnel || tunnel->fd < 0)
++ return;
++
++ sk->sk_err = err;
++ sk_error_report(sk);
++
++ if (ip_hdr(skb)->version == IPVERSION) {
++ if (inet_test_bit(RECVERR, sk))
++ return ip_icmp_error(sk, skb, err, port, info, payload);
++#if IS_ENABLED(CONFIG_IPV6)
++ } else {
++ if (inet6_test_bit(RECVERR6, sk))
++ return ipv6_icmp_error(sk, skb, err, port, info, payload);
++#endif
++ }
++}
++
+ /************************************************************************
+ * Transmit handling
+ ***********************************************************************/
+@@ -1493,6 +1514,7 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
+ .sk_user_data = tunnel,
+ .encap_type = UDP_ENCAP_L2TPINUDP,
+ .encap_rcv = l2tp_udp_encap_recv,
++ .encap_err_rcv = l2tp_udp_encap_err_recv,
+ .encap_destroy = l2tp_udp_encap_destroy,
+ };
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index ac0073c8f96f4..df26672fb3383 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -6184,7 +6184,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
+ link->u.mgd.dtim_period = elems->dtim_period;
+ link->u.mgd.have_beacon = true;
+ ifmgd->assoc_data->need_beacon = false;
+- if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) {
++ if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY) &&
++ !ieee80211_is_s1g_beacon(hdr->frame_control)) {
+ link->conf->sync_tsf =
+ le64_to_cpu(mgmt->u.beacon.timestamp);
+ link->conf->sync_device_ts =
+diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
+index 0efdaa8f2a92e..3cf252418bd38 100644
+--- a/net/mac80211/rate.c
++++ b/net/mac80211/rate.c
+@@ -877,6 +877,7 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_supported_band *sband;
++ u32 mask = ~0;
+
+ rate_control_fill_sta_table(sta, info, dest, max_rates);
+
+@@ -889,9 +890,12 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
+ if (ieee80211_is_tx_data(skb))
+ rate_control_apply_mask(sdata, sta, sband, dest, max_rates);
+
++ if (!(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX))
++ mask = sdata->rc_rateidx_mask[info->band];
++
+ if (dest[0].idx < 0)
+ __rate_control_send_low(&sdata->local->hw, sband, sta, info,
+- sdata->rc_rateidx_mask[info->band]);
++ mask);
+
+ if (sta)
+ rate_fixup_ratelist(vif, sband, info, dest, max_rates);
+diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
+index f9d5842601fa9..d613a9e3ae1fd 100644
+--- a/net/mac80211/scan.c
++++ b/net/mac80211/scan.c
+@@ -638,6 +638,7 @@ static void ieee80211_send_scan_probe_req(struct ieee80211_sub_if_data *sdata,
+ cpu_to_le16(IEEE80211_SN_TO_SEQ(sn));
+ }
+ IEEE80211_SKB_CB(skb)->flags |= tx_flags;
++ IEEE80211_SKB_CB(skb)->control.flags |= IEEE80211_TX_CTRL_SCAN_TX;
+ ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band);
+ }
+ }
+@@ -694,19 +695,11 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
+ return -EBUSY;
+
+ /* For an MLO connection, if a link ID was specified, validate that it
+- * is indeed active. If no link ID was specified, select one of the
+- * active links.
++ * is indeed active.
+ */
+- if (ieee80211_vif_is_mld(&sdata->vif)) {
+- if (req->tsf_report_link_id >= 0) {
+- if (!(sdata->vif.active_links &
+- BIT(req->tsf_report_link_id)))
+- return -EINVAL;
+- } else {
+- req->tsf_report_link_id =
+- __ffs(sdata->vif.active_links);
+- }
+- }
++ if (ieee80211_vif_is_mld(&sdata->vif) && req->tsf_report_link_id >= 0 &&
++ !(sdata->vif.active_links & BIT(req->tsf_report_link_id)))
++ return -EINVAL;
+
+ if (!__ieee80211_can_leave_ch(sdata))
+ return -EBUSY;
+diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
+index 6fbb15b65902c..a8a4912bf2cb4 100644
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -701,11 +701,16 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
+ txrc.bss_conf = &tx->sdata->vif.bss_conf;
+ txrc.skb = tx->skb;
+ txrc.reported_rate.idx = -1;
+- txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band];
+
+- if (tx->sdata->rc_has_mcs_mask[info->band])
+- txrc.rate_idx_mcs_mask =
+- tx->sdata->rc_rateidx_mcs_mask[info->band];
++ if (unlikely(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX)) {
++ txrc.rate_idx_mask = ~0;
++ } else {
++ txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band];
++
++ if (tx->sdata->rc_has_mcs_mask[info->band])
++ txrc.rate_idx_mcs_mask =
++ tx->sdata->rc_rateidx_mcs_mask[info->band];
++ }
+
+ txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP ||
+ tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
+diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
+index 74c1faec271d1..54e29ab911f0d 100644
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -1687,15 +1687,6 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool
+ }
+ }
+
+-static void mptcp_set_nospace(struct sock *sk)
+-{
+- /* enable autotune */
+- set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+-
+- /* will be cleared on avail space */
+- set_bit(MPTCP_NOSPACE, &mptcp_sk(sk)->flags);
+-}
+-
+ static int mptcp_disconnect(struct sock *sk, int flags);
+
+ static int mptcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
+@@ -1766,6 +1757,30 @@ static int do_copy_data_nocache(struct sock *sk, int copy,
+ return 0;
+ }
+
++/* open-code sk_stream_memory_free() plus sent limit computation to
++ * avoid indirect calls in fast-path.
++ * Called under the msk socket lock, so we can avoid a bunch of ONCE
++ * annotations.
++ */
++static u32 mptcp_send_limit(const struct sock *sk)
++{
++ const struct mptcp_sock *msk = mptcp_sk(sk);
++ u32 limit, not_sent;
++
++ if (sk->sk_wmem_queued >= READ_ONCE(sk->sk_sndbuf))
++ return 0;
++
++ limit = mptcp_notsent_lowat(sk);
++ if (limit == UINT_MAX)
++ return UINT_MAX;
++
++ not_sent = msk->write_seq - msk->snd_nxt;
++ if (not_sent >= limit)
++ return 0;
++
++ return limit - not_sent;
++}
++
+ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ {
+ struct mptcp_sock *msk = mptcp_sk(sk);
+@@ -1810,6 +1825,12 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ struct mptcp_data_frag *dfrag;
+ bool dfrag_collapsed;
+ size_t psize, offset;
++ u32 copy_limit;
++
++ /* ensure fitting the notsent_lowat() constraint */
++ copy_limit = mptcp_send_limit(sk);
++ if (!copy_limit)
++ goto wait_for_memory;
+
+ /* reuse tail pfrag, if possible, or carve a new one from the
+ * page allocator
+@@ -1817,9 +1838,6 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ dfrag = mptcp_pending_tail(sk);
+ dfrag_collapsed = mptcp_frag_can_collapse_to(msk, pfrag, dfrag);
+ if (!dfrag_collapsed) {
+- if (!sk_stream_memory_free(sk))
+- goto wait_for_memory;
+-
+ if (!mptcp_page_frag_refill(sk, pfrag))
+ goto wait_for_memory;
+
+@@ -1834,6 +1852,7 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ offset = dfrag->offset + dfrag->data_len;
+ psize = pfrag->size - offset;
+ psize = min_t(size_t, psize, msg_data_left(msg));
++ psize = min_t(size_t, psize, copy_limit);
+ total_ts = psize + frag_truesize;
+
+ if (!sk_wmem_schedule(sk, total_ts))
+@@ -1869,7 +1888,7 @@ static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
+ continue;
+
+ wait_for_memory:
+- mptcp_set_nospace(sk);
++ set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+ __mptcp_push_pending(sk, msg->msg_flags);
+ ret = sk_stream_wait_memory(sk, &timeo);
+ if (ret)
+@@ -3770,6 +3789,7 @@ static struct proto mptcp_prot = {
+ .unhash = mptcp_unhash,
+ .get_port = mptcp_get_port,
+ .forward_alloc_get = mptcp_forward_alloc_get,
++ .stream_memory_free = mptcp_stream_memory_free,
+ .sockets_allocated = &mptcp_sockets_allocated,
+
+ .memory_allocated = &tcp_memory_allocated,
+@@ -3941,12 +3961,12 @@ static __poll_t mptcp_check_writeable(struct mptcp_sock *msk)
+ {
+ struct sock *sk = (struct sock *)msk;
+
+- if (sk_stream_is_writeable(sk))
++ if (__mptcp_stream_is_writeable(sk, 1))
+ return EPOLLOUT | EPOLLWRNORM;
+
+- mptcp_set_nospace(sk);
+- smp_mb__after_atomic(); /* msk->flags is changed by write_space cb */
+- if (sk_stream_is_writeable(sk))
++ set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
++ smp_mb__after_atomic(); /* NOSPACE is changed by mptcp_write_space() */
++ if (__mptcp_stream_is_writeable(sk, 1))
+ return EPOLLOUT | EPOLLWRNORM;
+
+ return 0;
+diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
+index 07f6242afc1ae..5f4c10c41c77d 100644
+--- a/net/mptcp/protocol.h
++++ b/net/mptcp/protocol.h
+@@ -113,10 +113,9 @@
+ #define MPTCP_RST_TRANSIENT BIT(0)
+
+ /* MPTCP socket atomic flags */
+-#define MPTCP_NOSPACE 1
+-#define MPTCP_WORK_RTX 2
+-#define MPTCP_FALLBACK_DONE 4
+-#define MPTCP_WORK_CLOSE_SUBFLOW 5
++#define MPTCP_WORK_RTX 1
++#define MPTCP_FALLBACK_DONE 2
++#define MPTCP_WORK_CLOSE_SUBFLOW 3
+
+ /* MPTCP socket release cb flags */
+ #define MPTCP_PUSH_PENDING 1
+@@ -306,6 +305,10 @@ struct mptcp_sock {
+ in_accept_queue:1,
+ free_first:1,
+ rcvspace_init:1;
++ u32 notsent_lowat;
++ int keepalive_cnt;
++ int keepalive_idle;
++ int keepalive_intvl;
+ struct work_struct work;
+ struct sk_buff *ooo_last_skb;
+ struct rb_root out_of_order_queue;
+@@ -790,14 +793,36 @@ static inline bool mptcp_data_fin_enabled(const struct mptcp_sock *msk)
+ READ_ONCE(msk->write_seq) == READ_ONCE(msk->snd_nxt);
+ }
+
++static inline u32 mptcp_notsent_lowat(const struct sock *sk)
++{
++ struct net *net = sock_net(sk);
++ u32 val;
++
++ val = READ_ONCE(mptcp_sk(sk)->notsent_lowat);
++ return val ?: READ_ONCE(net->ipv4.sysctl_tcp_notsent_lowat);
++}
++
++static inline bool mptcp_stream_memory_free(const struct sock *sk, int wake)
++{
++ const struct mptcp_sock *msk = mptcp_sk(sk);
++ u32 notsent_bytes;
++
++ notsent_bytes = READ_ONCE(msk->write_seq) - READ_ONCE(msk->snd_nxt);
++ return (notsent_bytes << wake) < mptcp_notsent_lowat(sk);
++}
++
++static inline bool __mptcp_stream_is_writeable(const struct sock *sk, int wake)
++{
++ return mptcp_stream_memory_free(sk, wake) &&
++ __sk_stream_is_writeable(sk, wake);
++}
++
+ static inline void mptcp_write_space(struct sock *sk)
+ {
+- if (sk_stream_is_writeable(sk)) {
+- /* pairs with memory barrier in mptcp_poll */
+- smp_mb();
+- if (test_and_clear_bit(MPTCP_NOSPACE, &mptcp_sk(sk)->flags))
+- sk_stream_write_space(sk);
+- }
++ /* pairs with memory barrier in mptcp_poll */
++ smp_mb();
++ if (mptcp_stream_memory_free(sk, 1))
++ sk_stream_write_space(sk);
+ }
+
+ static inline void __mptcp_sync_sndbuf(struct sock *sk)
+diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c
+index ef3edba754a32..47aa826ba5fea 100644
+--- a/net/mptcp/sockopt.c
++++ b/net/mptcp/sockopt.c
+@@ -181,8 +181,6 @@ static int mptcp_setsockopt_sol_socket_int(struct mptcp_sock *msk, int optname,
+
+ switch (optname) {
+ case SO_KEEPALIVE:
+- mptcp_sol_socket_sync_intval(msk, optname, val);
+- return 0;
+ case SO_DEBUG:
+ case SO_MARK:
+ case SO_PRIORITY:
+@@ -624,20 +622,36 @@ static int mptcp_setsockopt_sol_tcp_congestion(struct mptcp_sock *msk, sockptr_t
+ return ret;
+ }
+
+-static int mptcp_setsockopt_sol_tcp_cork(struct mptcp_sock *msk, sockptr_t optval,
+- unsigned int optlen)
++static int __mptcp_setsockopt_set_val(struct mptcp_sock *msk, int max,
++ int (*set_val)(struct sock *, int),
++ int *msk_val, int val)
+ {
+ struct mptcp_subflow_context *subflow;
+- struct sock *sk = (struct sock *)msk;
+- int val;
++ int err = 0;
+
+- if (optlen < sizeof(int))
+- return -EINVAL;
++ mptcp_for_each_subflow(msk, subflow) {
++ struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
++ int ret;
+
+- if (copy_from_sockptr(&val, optval, sizeof(val)))
+- return -EFAULT;
++ lock_sock(ssk);
++ ret = set_val(ssk, val);
++ err = err ? : ret;
++ release_sock(ssk);
++ }
++
++ if (!err) {
++ *msk_val = val;
++ sockopt_seq_inc(msk);
++ }
++
++ return err;
++}
++
++static int __mptcp_setsockopt_sol_tcp_cork(struct mptcp_sock *msk, int val)
++{
++ struct mptcp_subflow_context *subflow;
++ struct sock *sk = (struct sock *)msk;
+
+- lock_sock(sk);
+ sockopt_seq_inc(msk);
+ msk->cork = !!val;
+ mptcp_for_each_subflow(msk, subflow) {
+@@ -649,25 +663,15 @@ static int mptcp_setsockopt_sol_tcp_cork(struct mptcp_sock *msk, sockptr_t optva
+ }
+ if (!val)
+ mptcp_check_and_set_pending(sk);
+- release_sock(sk);
+
+ return 0;
+ }
+
+-static int mptcp_setsockopt_sol_tcp_nodelay(struct mptcp_sock *msk, sockptr_t optval,
+- unsigned int optlen)
++static int __mptcp_setsockopt_sol_tcp_nodelay(struct mptcp_sock *msk, int val)
+ {
+ struct mptcp_subflow_context *subflow;
+ struct sock *sk = (struct sock *)msk;
+- int val;
+-
+- if (optlen < sizeof(int))
+- return -EINVAL;
+-
+- if (copy_from_sockptr(&val, optval, sizeof(val)))
+- return -EFAULT;
+
+- lock_sock(sk);
+ sockopt_seq_inc(msk);
+ msk->nodelay = !!val;
+ mptcp_for_each_subflow(msk, subflow) {
+@@ -679,8 +683,6 @@ static int mptcp_setsockopt_sol_tcp_nodelay(struct mptcp_sock *msk, sockptr_t op
+ }
+ if (val)
+ mptcp_check_and_set_pending(sk);
+- release_sock(sk);
+-
+ return 0;
+ }
+
+@@ -803,25 +805,10 @@ static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
+ int ret, val;
+
+ switch (optname) {
+- case TCP_INQ:
+- ret = mptcp_get_int_option(msk, optval, optlen, &val);
+- if (ret)
+- return ret;
+- if (val < 0 || val > 1)
+- return -EINVAL;
+-
+- lock_sock(sk);
+- msk->recvmsg_inq = !!val;
+- release_sock(sk);
+- return 0;
+ case TCP_ULP:
+ return -EOPNOTSUPP;
+ case TCP_CONGESTION:
+ return mptcp_setsockopt_sol_tcp_congestion(msk, optval, optlen);
+- case TCP_CORK:
+- return mptcp_setsockopt_sol_tcp_cork(msk, optval, optlen);
+- case TCP_NODELAY:
+- return mptcp_setsockopt_sol_tcp_nodelay(msk, optval, optlen);
+ case TCP_DEFER_ACCEPT:
+ /* See tcp.c: TCP_DEFER_ACCEPT does not fail */
+ mptcp_setsockopt_first_sf_only(msk, SOL_TCP, optname, optval, optlen);
+@@ -834,7 +821,50 @@ static int mptcp_setsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
+ optval, optlen);
+ }
+
+- return -EOPNOTSUPP;
++ ret = mptcp_get_int_option(msk, optval, optlen, &val);
++ if (ret)
++ return ret;
++
++ lock_sock(sk);
++ switch (optname) {
++ case TCP_INQ:
++ if (val < 0 || val > 1)
++ ret = -EINVAL;
++ else
++ msk->recvmsg_inq = !!val;
++ break;
++ case TCP_NOTSENT_LOWAT:
++ WRITE_ONCE(msk->notsent_lowat, val);
++ mptcp_write_space(sk);
++ break;
++ case TCP_CORK:
++ ret = __mptcp_setsockopt_sol_tcp_cork(msk, val);
++ break;
++ case TCP_NODELAY:
++ ret = __mptcp_setsockopt_sol_tcp_nodelay(msk, val);
++ break;
++ case TCP_KEEPIDLE:
++ ret = __mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPIDLE,
++ &tcp_sock_set_keepidle_locked,
++ &msk->keepalive_idle, val);
++ break;
++ case TCP_KEEPINTVL:
++ ret = __mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPINTVL,
++ &tcp_sock_set_keepintvl,
++ &msk->keepalive_intvl, val);
++ break;
++ case TCP_KEEPCNT:
++ ret = __mptcp_setsockopt_set_val(msk, MAX_TCP_KEEPCNT,
++ &tcp_sock_set_keepcnt,
++ &msk->keepalive_cnt,
++ val);
++ break;
++ default:
++ ret = -ENOPROTOOPT;
++ }
++
++ release_sock(sk);
++ return ret;
+ }
+
+ int mptcp_setsockopt(struct sock *sk, int level, int optname,
+@@ -1331,6 +1361,8 @@ static int mptcp_put_int_option(struct mptcp_sock *msk, char __user *optval,
+ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
+ char __user *optval, int __user *optlen)
+ {
++ struct sock *sk = (void *)msk;
++
+ switch (optname) {
+ case TCP_ULP:
+ case TCP_CONGESTION:
+@@ -1349,6 +1381,20 @@ static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname,
+ return mptcp_put_int_option(msk, optval, optlen, msk->cork);
+ case TCP_NODELAY:
+ return mptcp_put_int_option(msk, optval, optlen, msk->nodelay);
++ case TCP_KEEPIDLE:
++ return mptcp_put_int_option(msk, optval, optlen,
++ msk->keepalive_idle ? :
++ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_time) / HZ);
++ case TCP_KEEPINTVL:
++ return mptcp_put_int_option(msk, optval, optlen,
++ msk->keepalive_intvl ? :
++ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_intvl) / HZ);
++ case TCP_KEEPCNT:
++ return mptcp_put_int_option(msk, optval, optlen,
++ msk->keepalive_cnt ? :
++ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_keepalive_probes));
++ case TCP_NOTSENT_LOWAT:
++ return mptcp_put_int_option(msk, optval, optlen, msk->notsent_lowat);
+ }
+ return -EOPNOTSUPP;
+ }
+@@ -1464,6 +1510,9 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
+ tcp_set_congestion_control(ssk, msk->ca_name, false, true);
+ __tcp_sock_set_cork(ssk, !!msk->cork);
+ __tcp_sock_set_nodelay(ssk, !!msk->nodelay);
++ tcp_sock_set_keepidle_locked(ssk, msk->keepalive_idle);
++ tcp_sock_set_keepintvl(ssk, msk->keepalive_intvl);
++ tcp_sock_set_keepcnt(ssk, msk->keepalive_cnt);
+
+ inet_assign_bit(TRANSPARENT, ssk, inet_test_bit(TRANSPARENT, sk));
+ inet_assign_bit(FREEBIND, ssk, inet_test_bit(FREEBIND, sk));
+diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
+index 70480869ad1c5..bd2b17b219ae9 100644
+--- a/net/netrom/nr_route.c
++++ b/net/netrom/nr_route.c
+@@ -285,22 +285,14 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic,
+ return 0;
+ }
+
+-static inline void __nr_remove_node(struct nr_node *nr_node)
++static void nr_remove_node_locked(struct nr_node *nr_node)
+ {
++ lockdep_assert_held(&nr_node_list_lock);
++
+ hlist_del_init(&nr_node->node_node);
+ nr_node_put(nr_node);
+ }
+
+-#define nr_remove_node_locked(__node) \
+- __nr_remove_node(__node)
+-
+-static void nr_remove_node(struct nr_node *nr_node)
+-{
+- spin_lock_bh(&nr_node_list_lock);
+- __nr_remove_node(nr_node);
+- spin_unlock_bh(&nr_node_list_lock);
+-}
+-
+ static inline void __nr_remove_neigh(struct nr_neigh *nr_neigh)
+ {
+ hlist_del_init(&nr_neigh->neigh_node);
+@@ -339,6 +331,7 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n
+ return -EINVAL;
+ }
+
++ spin_lock_bh(&nr_node_list_lock);
+ nr_node_lock(nr_node);
+ for (i = 0; i < nr_node->count; i++) {
+ if (nr_node->routes[i].neighbour == nr_neigh) {
+@@ -352,7 +345,7 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n
+ nr_node->count--;
+
+ if (nr_node->count == 0) {
+- nr_remove_node(nr_node);
++ nr_remove_node_locked(nr_node);
+ } else {
+ switch (i) {
+ case 0:
+@@ -367,12 +360,14 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n
+ nr_node_put(nr_node);
+ }
+ nr_node_unlock(nr_node);
++ spin_unlock_bh(&nr_node_list_lock);
+
+ return 0;
+ }
+ }
+ nr_neigh_put(nr_neigh);
+ nr_node_unlock(nr_node);
++ spin_unlock_bh(&nr_node_list_lock);
+ nr_node_put(nr_node);
+
+ return -EINVAL;
+diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
+index 33b21a0c05481..8a848ce72e291 100644
+--- a/net/openvswitch/flow.c
++++ b/net/openvswitch/flow.c
+@@ -561,7 +561,6 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
+ */
+ key->tp.src = htons(icmp->icmp6_type);
+ key->tp.dst = htons(icmp->icmp6_code);
+- memset(&key->ipv6.nd, 0, sizeof(key->ipv6.nd));
+
+ if (icmp->icmp6_code == 0 &&
+ (icmp->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION ||
+@@ -570,6 +569,8 @@ static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
+ struct nd_msg *nd;
+ int offset;
+
++ memset(&key->ipv6.nd, 0, sizeof(key->ipv6.nd));
++
+ /* In order to process neighbor discovery options, we need the
+ * entire packet.
+ */
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
+index e6a8701a38dbe..91c9dc0108a2d 100644
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -2522,8 +2522,7 @@ static void tpacket_destruct_skb(struct sk_buff *skb)
+ ts = __packet_set_timestamp(po, ph, skb);
+ __packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts);
+
+- if (!packet_read_pending(&po->tx_ring))
+- complete(&po->skb_completion);
++ complete(&po->skb_completion);
+ }
+
+ sock_wfree(skb);
+diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c
+index abb0c70ffc8b0..654a3cc0d3479 100644
+--- a/net/qrtr/ns.c
++++ b/net/qrtr/ns.c
+@@ -725,6 +725,24 @@ int qrtr_ns_init(void)
+ if (ret < 0)
+ goto err_wq;
+
++ /* As the qrtr ns socket owner and creator is the same module, we have
++ * to decrease the qrtr module reference count to guarantee that it
++ * remains zero after the ns socket is created, otherwise, executing
++ * "rmmod" command is unable to make the qrtr module deleted after the
++ * qrtr module is inserted successfully.
++ *
++ * However, the reference count is increased twice in
++ * sock_create_kern(): one is to increase the reference count of owner
++ * of qrtr socket's proto_ops struct; another is to increment the
++ * reference count of owner of qrtr proto struct. Therefore, we must
++ * decrement the module reference count twice to ensure that it keeps
++ * zero after server's listening socket is created. Of course, we
++ * must bump the module reference count twice as well before the socket
++ * is closed.
++ */
++ module_put(qrtr_ns.sock->ops->owner);
++ module_put(qrtr_ns.sock->sk->sk_prot_creator->owner);
++
+ return 0;
+
+ err_wq:
+@@ -739,6 +757,15 @@ void qrtr_ns_remove(void)
+ {
+ cancel_work_sync(&qrtr_ns.work);
+ destroy_workqueue(qrtr_ns.workqueue);
++
++ /* sock_release() expects the two references that were put during
++ * qrtr_ns_init(). This function is only called during module remove,
++ * so try_stop_module() has already set the refcnt to 0. Use
++ * __module_get() instead of try_module_get() to successfully take two
++ * references.
++ */
++ __module_get(qrtr_ns.sock->ops->owner);
++ __module_get(qrtr_ns.sock->sk->sk_prot_creator->owner);
+ sock_release(qrtr_ns.sock);
+ }
+ EXPORT_SYMBOL_GPL(qrtr_ns_remove);
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index 24de941847003..96ab50eda9c2e 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -1033,17 +1033,11 @@ svcauth_gss_proc_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
+
+ static void gss_free_in_token_pages(struct gssp_in_token *in_token)
+ {
+- u32 inlen;
+ int i;
+
+ i = 0;
+- inlen = in_token->page_len;
+- while (inlen) {
+- if (in_token->pages[i])
+- put_page(in_token->pages[i]);
+- inlen -= inlen > PAGE_SIZE ? PAGE_SIZE : inlen;
+- }
+-
++ while (in_token->pages[i])
++ put_page(in_token->pages[i++]);
+ kfree(in_token->pages);
+ in_token->pages = NULL;
+ }
+diff --git a/net/sunrpc/stats.c b/net/sunrpc/stats.c
+index 65fc1297c6dfa..383860cb1d5b0 100644
+--- a/net/sunrpc/stats.c
++++ b/net/sunrpc/stats.c
+@@ -314,7 +314,7 @@ EXPORT_SYMBOL_GPL(rpc_proc_unregister);
+ struct proc_dir_entry *
+ svc_proc_register(struct net *net, struct svc_stat *statp, const struct proc_ops *proc_ops)
+ {
+- return do_register(net, statp->program->pg_name, statp, proc_ops);
++ return do_register(net, statp->program->pg_name, net, proc_ops);
+ }
+ EXPORT_SYMBOL_GPL(svc_proc_register);
+
+diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
+index b969e505c7b77..bd61e257cda6a 100644
+--- a/net/sunrpc/svc.c
++++ b/net/sunrpc/svc.c
+@@ -1263,8 +1263,6 @@ svc_generic_init_request(struct svc_rqst *rqstp,
+ if (rqstp->rq_proc >= versp->vs_nproc)
+ goto err_bad_proc;
+ rqstp->rq_procinfo = procp = &versp->vs_proc[rqstp->rq_proc];
+- if (!procp)
+- goto err_bad_proc;
+
+ /* Initialize storage for argp and resp */
+ memset(rqstp->rq_argp, 0, procp->pc_argzero);
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index 9df15a7bc2569..eb90a255507ef 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -2209,7 +2209,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
+ goto out_err;
+ }
+
+- if (sk->sk_shutdown & SEND_SHUTDOWN)
++ if (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN)
+ goto pipe_err;
+
+ while (sent < len) {
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index daac83aa8988e..4e7b517c78bfd 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -9148,6 +9148,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
+ struct wiphy *wiphy;
+ int err, tmp, n_ssids = 0, n_channels, i;
+ size_t ie_len, size;
++ size_t ssids_offset, ie_offset;
+
+ wiphy = &rdev->wiphy;
+
+@@ -9193,21 +9194,20 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
+ return -EINVAL;
+
+ size = struct_size(request, channels, n_channels);
++ ssids_offset = size;
+ size = size_add(size, array_size(sizeof(*request->ssids), n_ssids));
++ ie_offset = size;
+ size = size_add(size, ie_len);
+ request = kzalloc(size, GFP_KERNEL);
+ if (!request)
+ return -ENOMEM;
++ request->n_channels = n_channels;
+
+ if (n_ssids)
+- request->ssids = (void *)&request->channels[n_channels];
++ request->ssids = (void *)request + ssids_offset;
+ request->n_ssids = n_ssids;
+- if (ie_len) {
+- if (n_ssids)
+- request->ie = (void *)(request->ssids + n_ssids);
+- else
+- request->ie = (void *)(request->channels + n_channels);
+- }
++ if (ie_len)
++ request->ie = (void *)request + ie_offset;
+
+ i = 0;
+ if (scan_freqs) {
+diff --git a/net/wireless/trace.h b/net/wireless/trace.h
+index cc3fd4177bcee..0cf8f958081eb 100644
+--- a/net/wireless/trace.h
++++ b/net/wireless/trace.h
+@@ -1747,7 +1747,7 @@ TRACE_EVENT(rdev_return_void_tx_rx,
+
+ DECLARE_EVENT_CLASS(tx_rx_evt,
+ TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
+- TP_ARGS(wiphy, rx, tx),
++ TP_ARGS(wiphy, tx, rx),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ __field(u32, tx)
+@@ -1764,7 +1764,7 @@ DECLARE_EVENT_CLASS(tx_rx_evt,
+
+ DEFINE_EVENT(tx_rx_evt, rdev_set_antenna,
+ TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx),
+- TP_ARGS(wiphy, rx, tx)
++ TP_ARGS(wiphy, tx, rx)
+ );
+
+ DECLARE_EVENT_CLASS(wiphy_netdev_id_evt,
+diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c
+index 08596c0ef0707..e6c59f688573a 100644
+--- a/samples/landlock/sandboxer.c
++++ b/samples/landlock/sandboxer.c
+@@ -151,7 +151,7 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd,
+ const __u64 allowed_access)
+ {
+ int ret = 1;
+- char *env_port_name, *strport;
++ char *env_port_name, *env_port_name_next, *strport;
+ struct landlock_net_port_attr net_port = {
+ .allowed_access = allowed_access,
+ .port = 0,
+@@ -163,7 +163,8 @@ static int populate_ruleset_net(const char *const env_var, const int ruleset_fd,
+ env_port_name = strdup(env_port_name);
+ unsetenv(env_var);
+
+- while ((strport = strsep(&env_port_name, ENV_DELIMITER))) {
++ env_port_name_next = env_port_name;
++ while ((strport = strsep(&env_port_name_next, ENV_DELIMITER))) {
+ net_port.port = atoi(strport);
+ if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
+ &net_port, 0)) {
+diff --git a/scripts/module.lds.S b/scripts/module.lds.S
+index bf5bcf2836d81..89ff01a22634f 100644
+--- a/scripts/module.lds.S
++++ b/scripts/module.lds.S
+@@ -13,6 +13,7 @@ SECTIONS {
+ /DISCARD/ : {
+ *(.discard)
+ *(.discard.*)
++ *(.export_symbol)
+ }
+
+ __ksymtab 0 : { *(SORT(___ksymtab+*)) }
+diff --git a/sound/core/init.c b/sound/core/init.c
+index 22c0d217b8608..d97b8af897ee4 100644
+--- a/sound/core/init.c
++++ b/sound/core/init.c
+@@ -312,8 +312,8 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
+ card->number = idx;
+ #ifdef MODULE
+ WARN_ON(!module);
+- card->module = module;
+ #endif
++ card->module = module;
+ INIT_LIST_HEAD(&card->devices);
+ init_rwsem(&card->controls_rwsem);
+ rwlock_init(&card->ctl_files_rwlock);
+@@ -523,6 +523,14 @@ void snd_card_disconnect(struct snd_card *card)
+ }
+ spin_unlock(&card->files_lock);
+
++#ifdef CONFIG_PM
++ /* wake up sleepers here before other callbacks for avoiding potential
++ * deadlocks with other locks (e.g. in kctls);
++ * then this notifies the shutdown and sleepers would abort immediately
++ */
++ wake_up_all(&card->power_sleep);
++#endif
++
+ /* notify all connected devices about disconnection */
+ /* at this point, they cannot respond to any calls except release() */
+
+@@ -550,7 +558,6 @@ void snd_card_disconnect(struct snd_card *card)
+ mutex_unlock(&snd_card_mutex);
+
+ #ifdef CONFIG_PM
+- wake_up(&card->power_sleep);
+ snd_power_sync_ref(card);
+ #endif
+ }
+diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
+index 6a384b922e4fa..d1f6cdcf1866e 100644
+--- a/sound/hda/intel-dsp-config.c
++++ b/sound/hda/intel-dsp-config.c
+@@ -557,9 +557,32 @@ static const struct config_entry *snd_intel_dsp_find_config
+ if (table->codec_hid) {
+ int i;
+
+- for (i = 0; i < table->codec_hid->num_codecs; i++)
+- if (acpi_dev_present(table->codec_hid->codecs[i], NULL, -1))
++ for (i = 0; i < table->codec_hid->num_codecs; i++) {
++ struct nhlt_acpi_table *nhlt;
++ bool ssp_found = false;
++
++ if (!acpi_dev_present(table->codec_hid->codecs[i], NULL, -1))
++ continue;
++
++ nhlt = intel_nhlt_init(&pci->dev);
++ if (!nhlt) {
++ dev_warn(&pci->dev, "%s: NHLT table not found, skipped HID %s\n",
++ __func__, table->codec_hid->codecs[i]);
++ continue;
++ }
++
++ if (intel_nhlt_has_endpoint_type(nhlt, NHLT_LINK_SSP) &&
++ intel_nhlt_ssp_endpoint_mask(nhlt, NHLT_DEVICE_I2S))
++ ssp_found = true;
++
++ intel_nhlt_free(nhlt);
++
++ if (ssp_found)
+ break;
++
++ dev_warn(&pci->dev, "%s: no valid SSP found for HID %s, skipped\n",
++ __func__, table->codec_hid->codecs[i]);
++ }
+ if (i == table->codec_hid->num_codecs)
+ continue;
+ }
+diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
+index 74df2330015f6..5cb8acf5b158c 100644
+--- a/sound/pci/emu10k1/io.c
++++ b/sound/pci/emu10k1/io.c
+@@ -285,6 +285,7 @@ static void snd_emu1010_fpga_write_locked(struct snd_emu10k1 *emu, u32 reg, u32
+ outw(value, emu->port + A_GPIO);
+ udelay(10);
+ outw(value | 0x80 , emu->port + A_GPIO); /* High bit clocks the value into the fpga. */
++ udelay(10);
+ }
+
+ void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value)
+diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c
+index 4d1f8734d13f3..c2067e8083c0f 100644
+--- a/sound/pci/hda/cs35l41_hda_property.c
++++ b/sound/pci/hda/cs35l41_hda_property.c
+@@ -99,8 +99,8 @@ static const struct cs35l41_config cs35l41_config_table[] = {
+ { "10431F62", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 0, 0, 0 },
+ { "10433A60", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
+ { "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
+- { "17AA3877", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
+- { "17AA3878", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
++ { "17AA3877", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
++ { "17AA3878", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
+ { "17AA38A9", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
+ { "17AA38AB", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
+ { "17AA38B4", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 1, -1, 0, 0, 0 },
+diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c
+index 43a445bd961fb..de58a953b48d2 100644
+--- a/sound/pci/hda/cs35l56_hda.c
++++ b/sound/pci/hda/cs35l56_hda.c
+@@ -629,6 +629,8 @@ static int cs35l56_hda_fw_load(struct cs35l56_hda *cs35l56)
+ ret = cs35l56_wait_for_firmware_boot(&cs35l56->base);
+ if (ret)
+ goto err_powered_up;
++
++ regcache_cache_only(cs35l56->base.regmap, false);
+ }
+
+ /* Disable auto-hibernate so that runtime_pm has control */
+@@ -978,6 +980,8 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int id)
+ if (ret)
+ goto err;
+
++ regcache_cache_only(cs35l56->base.regmap, false);
++
+ ret = cs35l56_set_patch(&cs35l56->base);
+ if (ret)
+ goto err;
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 7c82f93ba9197..c0e12e6746922 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -10089,8 +10089,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x8c70, "HP EliteBook 835 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8c71, "HP EliteBook 845 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8c72, "HP EliteBook 865 G11", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
++ SND_PCI_QUIRK(0x103c, 0x8c89, "HP ProBook 460 G11", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8c8a, "HP EliteBook 630", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8c8c, "HP EliteBook 660", ALC236_FIXUP_HP_GPIO_LED),
++ SND_PCI_QUIRK(0x103c, 0x8c8d, "HP ProBook 440 G11", ALC236_FIXUP_HP_GPIO_LED),
++ SND_PCI_QUIRK(0x103c, 0x8c8e, "HP ProBook 460 G11", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8c90, "HP EliteBook 640", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8c91, "HP EliteBook 660", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8c96, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
+index 69c68d8e7a6b5..1760b5d42460a 100644
+--- a/sound/soc/amd/yc/acp6x-mach.c
++++ b/sound/soc/amd/yc/acp6x-mach.c
+@@ -430,6 +430,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
+ DMI_MATCH(DMI_BOARD_NAME, "MRID6"),
+ }
+ },
++ {
++ .driver_data = &acp6x_card,
++ .matches = {
++ DMI_MATCH(DMI_BOARD_VENDOR, "MDC"),
++ DMI_MATCH(DMI_BOARD_NAME, "Herbag_MDU"),
++ }
++ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c
+index dfb4ce53491bb..f8e57a2fc3e32 100644
+--- a/sound/soc/codecs/cs35l41.c
++++ b/sound/soc/codecs/cs35l41.c
+@@ -1094,6 +1094,7 @@ static int cs35l41_handle_pdata(struct device *dev, struct cs35l41_hw_cfg *hw_cf
+ static int cs35l41_dsp_init(struct cs35l41_private *cs35l41)
+ {
+ struct wm_adsp *dsp;
++ uint32_t dsp1rx5_src;
+ int ret;
+
+ dsp = &cs35l41->dsp;
+@@ -1113,16 +1114,29 @@ static int cs35l41_dsp_init(struct cs35l41_private *cs35l41)
+ return ret;
+ }
+
+- ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX5_SRC,
+- CS35L41_INPUT_SRC_VPMON);
++ switch (cs35l41->hw_cfg.bst_type) {
++ case CS35L41_INT_BOOST:
++ case CS35L41_SHD_BOOST_ACTV:
++ dsp1rx5_src = CS35L41_INPUT_SRC_VPMON;
++ break;
++ case CS35L41_EXT_BOOST:
++ case CS35L41_SHD_BOOST_PASS:
++ dsp1rx5_src = CS35L41_INPUT_SRC_VBSTMON;
++ break;
++ default:
++ dev_err(cs35l41->dev, "wm_halo_init failed - Invalid Boost Type: %d\n",
++ cs35l41->hw_cfg.bst_type);
++ goto err_dsp;
++ }
++
++ ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX5_SRC, dsp1rx5_src);
+ if (ret < 0) {
+- dev_err(cs35l41->dev, "Write INPUT_SRC_VPMON failed: %d\n", ret);
++ dev_err(cs35l41->dev, "Write DSP1RX5_SRC: %d failed: %d\n", dsp1rx5_src, ret);
+ goto err_dsp;
+ }
+- ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX6_SRC,
+- CS35L41_INPUT_SRC_CLASSH);
++ ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX6_SRC, CS35L41_INPUT_SRC_VBSTMON);
+ if (ret < 0) {
+- dev_err(cs35l41->dev, "Write INPUT_SRC_CLASSH failed: %d\n", ret);
++ dev_err(cs35l41->dev, "Write CS35L41_INPUT_SRC_VBSTMON failed: %d\n", ret);
+ goto err_dsp;
+ }
+ ret = regmap_write(cs35l41->regmap, CS35L41_DSP1_RX7_SRC,
+diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c
+index 6dd0319bc843c..ea72afe3f906f 100644
+--- a/sound/soc/codecs/cs35l56.c
++++ b/sound/soc/codecs/cs35l56.c
+@@ -1297,6 +1297,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
+ "spk-id-gpios", ACPI_TYPE_PACKAGE, &obj);
+ if (ret) {
+ dev_dbg(cs35l56->base.dev, "Could not get spk-id-gpios package: %d\n", ret);
++ fwnode_handle_put(af01_fwnode);
+ return -ENOENT;
+ }
+
+@@ -1304,6 +1305,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
+ if (obj->package.count != 4) {
+ dev_warn(cs35l56->base.dev, "Unexpected spk-id element count %d\n",
+ obj->package.count);
++ fwnode_handle_put(af01_fwnode);
+ return -ENOENT;
+ }
+
+@@ -1318,6 +1320,7 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
+ */
+ ret = acpi_dev_add_driver_gpios(adev, cs35l56_af01_spkid_gpios_mapping);
+ if (ret) {
++ fwnode_handle_put(af01_fwnode);
+ return dev_err_probe(cs35l56->base.dev, ret,
+ "Failed to add gpio mapping to AF01\n");
+ }
+@@ -1325,14 +1328,17 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
+ ret = devm_add_action_or_reset(cs35l56->base.dev,
+ cs35l56_acpi_dev_release_driver_gpios,
+ adev);
+- if (ret)
++ if (ret) {
++ fwnode_handle_put(af01_fwnode);
+ return ret;
++ }
+
+ dev_dbg(cs35l56->base.dev, "Added spk-id-gpios mapping to AF01\n");
+ }
+
+ desc = fwnode_gpiod_get_index(af01_fwnode, "spk-id", 0, GPIOD_IN, NULL);
+ if (IS_ERR(desc)) {
++ fwnode_handle_put(af01_fwnode);
+ ret = PTR_ERR(desc);
+ return dev_err_probe(cs35l56->base.dev, ret, "Get GPIO from AF01 failed\n");
+ }
+@@ -1341,9 +1347,12 @@ static int cs35l56_try_get_broken_sdca_spkid_gpio(struct cs35l56_private *cs35l5
+ gpiod_put(desc);
+
+ if (ret < 0) {
++ fwnode_handle_put(af01_fwnode);
+ dev_err_probe(cs35l56->base.dev, ret, "Error reading spk-id GPIO\n");
+ return ret;
+- }
++ }
++
++ fwnode_handle_put(af01_fwnode);
+
+ dev_info(cs35l56->base.dev, "Got spk-id from AF01\n");
+
+diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c
+index 6bc068cdcbe2a..15e5e3eb592b3 100644
+--- a/sound/soc/codecs/da7219-aad.c
++++ b/sound/soc/codecs/da7219-aad.c
+@@ -671,8 +671,10 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev)
+ return NULL;
+
+ aad_pdata = devm_kzalloc(dev, sizeof(*aad_pdata), GFP_KERNEL);
+- if (!aad_pdata)
++ if (!aad_pdata) {
++ fwnode_handle_put(aad_np);
+ return NULL;
++ }
+
+ aad_pdata->irq = i2c->irq;
+
+@@ -753,6 +755,8 @@ static struct da7219_aad_pdata *da7219_aad_fw_to_pdata(struct device *dev)
+ else
+ aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1;
+
++ fwnode_handle_put(aad_np);
++
+ return aad_pdata;
+ }
+
+diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
+index 20191a4473c2d..0384e237a548e 100644
+--- a/sound/soc/codecs/rt5645.c
++++ b/sound/soc/codecs/rt5645.c
+@@ -444,6 +444,7 @@ struct rt5645_priv {
+ struct regmap *regmap;
+ struct i2c_client *i2c;
+ struct gpio_desc *gpiod_hp_det;
++ struct gpio_desc *gpiod_cbj_sleeve;
+ struct snd_soc_jack *hp_jack;
+ struct snd_soc_jack *mic_jack;
+ struct snd_soc_jack *btn_jack;
+@@ -3186,6 +3187,9 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
+ regmap_update_bits(rt5645->regmap, RT5645_IN1_CTRL2,
+ RT5645_CBJ_MN_JD, 0);
+
++ if (rt5645->gpiod_cbj_sleeve)
++ gpiod_set_value(rt5645->gpiod_cbj_sleeve, 1);
++
+ msleep(600);
+ regmap_read(rt5645->regmap, RT5645_IN1_CTRL3, &val);
+ val &= 0x7;
+@@ -3202,6 +3206,8 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
+ snd_soc_dapm_disable_pin(dapm, "Mic Det Power");
+ snd_soc_dapm_sync(dapm);
+ rt5645->jack_type = SND_JACK_HEADPHONE;
++ if (rt5645->gpiod_cbj_sleeve)
++ gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
+ }
+ if (rt5645->pdata.level_trigger_irq)
+ regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
+@@ -3229,6 +3235,9 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse
+ if (rt5645->pdata.level_trigger_irq)
+ regmap_update_bits(rt5645->regmap, RT5645_IRQ_CTRL2,
+ RT5645_JD_1_1_MASK, RT5645_JD_1_1_INV);
++
++ if (rt5645->gpiod_cbj_sleeve)
++ gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
+ }
+
+ return rt5645->jack_type;
+@@ -4012,6 +4021,16 @@ static int rt5645_i2c_probe(struct i2c_client *i2c)
+ return ret;
+ }
+
++ rt5645->gpiod_cbj_sleeve = devm_gpiod_get_optional(&i2c->dev, "cbj-sleeve",
++ GPIOD_OUT_LOW);
++
++ if (IS_ERR(rt5645->gpiod_cbj_sleeve)) {
++ ret = PTR_ERR(rt5645->gpiod_cbj_sleeve);
++ dev_info(&i2c->dev, "failed to initialize gpiod, ret=%d\n", ret);
++ if (ret != -ENOENT)
++ return ret;
++ }
++
+ for (i = 0; i < ARRAY_SIZE(rt5645->supplies); i++)
+ rt5645->supplies[i].supply = rt5645_supply_names[i];
+
+@@ -4259,6 +4278,9 @@ static void rt5645_i2c_remove(struct i2c_client *i2c)
+ cancel_delayed_work_sync(&rt5645->jack_detect_work);
+ cancel_delayed_work_sync(&rt5645->rcclock_work);
+
++ if (rt5645->gpiod_cbj_sleeve)
++ gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
++
+ regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies);
+ }
+
+@@ -4274,6 +4296,9 @@ static void rt5645_i2c_shutdown(struct i2c_client *i2c)
+ 0);
+ msleep(20);
+ regmap_write(rt5645->regmap, RT5645_RESET, 0);
++
++ if (rt5645->gpiod_cbj_sleeve)
++ gpiod_set_value(rt5645->gpiod_cbj_sleeve, 0);
+ }
+
+ static int __maybe_unused rt5645_sys_suspend(struct device *dev)
+diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c
+index 4533eedd7e189..27d17e3cc8027 100644
+--- a/sound/soc/codecs/rt715-sdca.c
++++ b/sound/soc/codecs/rt715-sdca.c
+@@ -316,7 +316,7 @@ static int rt715_sdca_set_amp_gain_8ch_get(struct snd_kcontrol *kcontrol,
+ return 0;
+ }
+
+-static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -17625, 375, 0);
++static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0);
+ static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0);
+
+ static int rt715_sdca_get_volsw(struct snd_kcontrol *kcontrol,
+@@ -477,7 +477,7 @@ static const struct snd_kcontrol_new rt715_sdca_snd_controls[] = {
+ RT715_SDCA_FU_VOL_CTRL, CH_01),
+ SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL,
+ RT715_SDCA_FU_VOL_CTRL, CH_02),
+- 0x2f, 0x7f, 0,
++ 0x2f, 0x3f, 0,
+ rt715_sdca_set_amp_gain_get, rt715_sdca_set_amp_gain_put,
+ in_vol_tlv),
+ RT715_SDCA_EXT_TLV("FU02 Capture Volume",
+@@ -485,13 +485,13 @@ static const struct snd_kcontrol_new rt715_sdca_snd_controls[] = {
+ RT715_SDCA_FU_VOL_CTRL, CH_01),
+ rt715_sdca_set_amp_gain_4ch_get,
+ rt715_sdca_set_amp_gain_4ch_put,
+- in_vol_tlv, 4, 0x7f),
++ in_vol_tlv, 4, 0x3f),
+ RT715_SDCA_EXT_TLV("FU06 Capture Volume",
+ SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL,
+ RT715_SDCA_FU_VOL_CTRL, CH_01),
+ rt715_sdca_set_amp_gain_4ch_get,
+ rt715_sdca_set_amp_gain_4ch_put,
+- in_vol_tlv, 4, 0x7f),
++ in_vol_tlv, 4, 0x3f),
+ /* MIC Boost Control */
+ RT715_SDCA_BOOST_EXT_TLV("FU0E Boost",
+ SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN,
+diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c
+index 21f37babd148a..376585f5a8dd8 100644
+--- a/sound/soc/codecs/rt715-sdw.c
++++ b/sound/soc/codecs/rt715-sdw.c
+@@ -111,6 +111,7 @@ static bool rt715_readable_register(struct device *dev, unsigned int reg)
+ case 0x839d:
+ case 0x83a7:
+ case 0x83a9:
++ case 0x752001:
+ case 0x752039:
+ return true;
+ default:
+diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c
+index 0e1c65a20392a..9ff607984ea19 100644
+--- a/sound/soc/codecs/rt722-sdca.c
++++ b/sound/soc/codecs/rt722-sdca.c
+@@ -1329,7 +1329,7 @@ static struct snd_soc_dai_driver rt722_sdca_dai[] = {
+ .capture = {
+ .stream_name = "DP6 DMic Capture",
+ .channels_min = 1,
+- .channels_max = 2,
++ .channels_max = 4,
+ .rates = RT722_STEREO_RATES,
+ .formats = RT722_FORMATS,
+ },
+@@ -1438,9 +1438,12 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
+ int loop_check, chk_cnt = 100, ret;
+ unsigned int calib_status = 0;
+
+- /* Read eFuse */
+- rt722_sdca_index_write(rt722, RT722_VENDOR_SPK_EFUSE, RT722_DC_CALIB_CTRL,
+- 0x4808);
++ /* Config analog bias */
++ rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_ANALOG_BIAS_CTL3,
++ 0xa081);
++ /* GE related settings */
++ rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_GE_RELATED_CTL2,
++ 0xa009);
+ /* Button A, B, C, D bypass mode */
+ rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_UMP_HID_CTL4,
+ 0xcf00);
+@@ -1474,9 +1477,6 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
+ if ((calib_status & 0x0040) == 0x0)
+ break;
+ }
+- /* Release HP-JD, EN_CBJ_TIE_GL/R open, en_osw gating auto done bit */
+- rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4,
+- 0x0010);
+ /* Set ADC09 power entity floating control */
+ rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ADC0A_08_PDE_FLOAT_CTL,
+ 0x2a12);
+@@ -1489,8 +1489,21 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
+ /* Set DAC03 and HP power entity floating control */
+ rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_DAC03_HP_PDE_FLOAT_CTL,
+ 0x4040);
++ rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ENT_FLOAT_CTRL_1,
++ 0x4141);
++ rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_FLOAT_CTRL_1,
++ 0x0101);
+ /* Fine tune PDE40 latency */
+ regmap_write(rt722->regmap, 0x2f58, 0x07);
++ regmap_write(rt722->regmap, 0x2f03, 0x06);
++ /* MIC VRefo */
++ rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
++ RT722_COMBO_JACK_AUTO_CTL1, 0x0200, 0x0200);
++ rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
++ RT722_VREFO_GAT, 0x4000, 0x4000);
++ /* Release HP-JD, EN_CBJ_TIE_GL/R open, en_osw gating auto done bit */
++ rt722_sdca_index_write(rt722, RT722_VENDOR_REG, RT722_DIGITAL_MISC_CTRL4,
++ 0x0010);
+ }
+
+ int rt722_sdca_io_init(struct device *dev, struct sdw_slave *slave)
+diff --git a/sound/soc/codecs/rt722-sdca.h b/sound/soc/codecs/rt722-sdca.h
+index 44af8901352eb..2464361a7958c 100644
+--- a/sound/soc/codecs/rt722-sdca.h
++++ b/sound/soc/codecs/rt722-sdca.h
+@@ -69,6 +69,7 @@ struct rt722_sdca_dmic_kctrl_priv {
+ #define RT722_COMBO_JACK_AUTO_CTL2 0x46
+ #define RT722_COMBO_JACK_AUTO_CTL3 0x47
+ #define RT722_DIGITAL_MISC_CTRL4 0x4a
++#define RT722_VREFO_GAT 0x63
+ #define RT722_FSM_CTL 0x67
+ #define RT722_SDCA_INTR_REC 0x82
+ #define RT722_SW_CONFIG1 0x8a
+@@ -127,6 +128,8 @@ struct rt722_sdca_dmic_kctrl_priv {
+ #define RT722_UMP_HID_CTL6 0x66
+ #define RT722_UMP_HID_CTL7 0x67
+ #define RT722_UMP_HID_CTL8 0x68
++#define RT722_FLOAT_CTRL_1 0x70
++#define RT722_ENT_FLOAT_CTRL_1 0x76
+
+ /* Parameter & Verb control 01 (0x1a)(NID:20h) */
+ #define RT722_HIDDEN_REG_SW_RESET (0x1 << 14)
+diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c
+index 4a0e136835ff5..b64be685dc23b 100644
+--- a/sound/soc/intel/avs/boards/ssm4567.c
++++ b/sound/soc/intel/avs/boards/ssm4567.c
+@@ -172,7 +172,6 @@ static int avs_ssm4567_probe(struct platform_device *pdev)
+ card->dapm_routes = card_base_routes;
+ card->num_dapm_routes = ARRAY_SIZE(card_base_routes);
+ card->fully_routed = true;
+- card->disable_route_checks = true;
+
+ ret = snd_soc_fixup_dai_links_platform_name(card, pname);
+ if (ret)
+diff --git a/sound/soc/intel/avs/cldma.c b/sound/soc/intel/avs/cldma.c
+index d7a9390b5e483..585579840b646 100644
+--- a/sound/soc/intel/avs/cldma.c
++++ b/sound/soc/intel/avs/cldma.c
+@@ -35,7 +35,7 @@ struct hda_cldma {
+
+ unsigned int buffer_size;
+ unsigned int num_periods;
+- unsigned int stream_tag;
++ unsigned char stream_tag;
+ void __iomem *sd_addr;
+
+ struct snd_dma_buffer dmab_data;
+diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c
+index 3aa16ee8d34c1..2fae84727a3bd 100644
+--- a/sound/soc/intel/avs/path.c
++++ b/sound/soc/intel/avs/path.c
+@@ -367,6 +367,7 @@ static int avs_asrc_create(struct avs_dev *adev, struct avs_path_module *mod)
+ struct avs_tplg_module *t = mod->template;
+ struct avs_asrc_cfg cfg;
+
++ memset(&cfg, 0, sizeof(cfg));
+ cfg.base.cpc = t->cfg_base->cpc;
+ cfg.base.ibs = t->cfg_base->ibs;
+ cfg.base.obs = t->cfg_base->obs;
+diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c
+index 4dfc5a1ebb7c2..f25a293c0915d 100644
+--- a/sound/soc/intel/avs/pcm.c
++++ b/sound/soc/intel/avs/pcm.c
+@@ -356,6 +356,7 @@ static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct sn
+ stream_info->sig_bits);
+ format_val = snd_hdac_stream_format(runtime->channels, bits, runtime->rate);
+
++ snd_hdac_ext_stream_decouple(bus, link_stream, true);
+ snd_hdac_ext_stream_reset(link_stream);
+ snd_hdac_ext_stream_setup(link_stream, format_val);
+
+@@ -611,6 +612,7 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so
+ struct avs_dev *adev = to_avs_dev(dai->dev);
+ struct hdac_ext_stream *host_stream;
+ unsigned int format_val;
++ struct hdac_bus *bus;
+ unsigned int bits;
+ int ret;
+
+@@ -620,6 +622,8 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so
+ if (hdac_stream(host_stream)->prepared)
+ return 0;
+
++ bus = hdac_stream(host_stream)->bus;
++ snd_hdac_ext_stream_decouple(bus, data->host_stream, true);
+ snd_hdac_stream_reset(hdac_stream(host_stream));
+
+ stream_info = snd_soc_dai_get_pcm_stream(dai, substream->stream);
+diff --git a/sound/soc/intel/avs/probes.c b/sound/soc/intel/avs/probes.c
+index 817e543036f29..7e781a3156909 100644
+--- a/sound/soc/intel/avs/probes.c
++++ b/sound/soc/intel/avs/probes.c
+@@ -19,8 +19,11 @@ static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id
+ struct avs_probe_cfg cfg = {{0}};
+ struct avs_module_entry mentry;
+ u8 dummy;
++ int ret;
+
+- avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry);
++ ret = avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry);
++ if (ret)
++ return ret;
+
+ /*
+ * Probe module uses no cycles, audio data format and input and output
+@@ -39,11 +42,12 @@ static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id
+ static void avs_dsp_delete_probe(struct avs_dev *adev)
+ {
+ struct avs_module_entry mentry;
++ int ret;
+
+- avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry);
+-
+- /* There is only ever one probe module instance. */
+- avs_dsp_delete_module(adev, mentry.module_id, 0, INVALID_PIPELINE_ID, 0);
++ ret = avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry);
++ if (!ret)
++ /* There is only ever one probe module instance. */
++ avs_dsp_delete_module(adev, mentry.module_id, 0, INVALID_PIPELINE_ID, 0);
+ }
+
+ static inline struct hdac_ext_stream *avs_compr_get_host_stream(struct snd_compr_stream *cstream)
+diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c
+index 540f7a29310a9..3fe3f38c6cb69 100644
+--- a/sound/soc/intel/boards/bxt_da7219_max98357a.c
++++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c
+@@ -768,6 +768,7 @@ static struct snd_soc_card broxton_audio_card = {
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = bxt_card_late_probe,
+ };
+
+diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c
+index c0eb65c14aa97..afc499be8db26 100644
+--- a/sound/soc/intel/boards/bxt_rt298.c
++++ b/sound/soc/intel/boards/bxt_rt298.c
+@@ -574,6 +574,7 @@ static struct snd_soc_card broxton_rt298 = {
+ .dapm_routes = broxton_rt298_map,
+ .num_dapm_routes = ARRAY_SIZE(broxton_rt298_map),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = bxt_card_late_probe,
+
+ };
+diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
+index 05f38d1f7d824..b41a1147f1c34 100644
+--- a/sound/soc/intel/boards/bytcr_rt5640.c
++++ b/sound/soc/intel/boards/bytcr_rt5640.c
+@@ -636,28 +636,30 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
+ BYT_RT5640_USE_AMCR0F28),
+ },
+ {
++ /* Asus T100TAF, unlike other T100TA* models this one has a mono speaker */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TA"),
++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
+ },
+ .driver_data = (void *)(BYT_RT5640_IN1_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_2000UA |
+ BYT_RT5640_OVCD_SF_0P75 |
++ BYT_RT5640_MONO_SPEAKER |
++ BYT_RT5640_DIFF_MIC |
++ BYT_RT5640_SSP0_AIF2 |
+ BYT_RT5640_MCLK_EN),
+ },
+ {
++ /* Asus T100TA and T100TAM, must come after T100TAF (mono spk) match */
+ .matches = {
+- DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"),
++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
++ DMI_MATCH(DMI_PRODUCT_NAME, "T100TA"),
+ },
+ .driver_data = (void *)(BYT_RT5640_IN1_MAP |
+ BYT_RT5640_JD_SRC_JD2_IN4N |
+ BYT_RT5640_OVCD_TH_2000UA |
+ BYT_RT5640_OVCD_SF_0P75 |
+- BYT_RT5640_MONO_SPEAKER |
+- BYT_RT5640_DIFF_MIC |
+- BYT_RT5640_SSP0_AIF2 |
+ BYT_RT5640_MCLK_EN),
+ },
+ {
+diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c
+index 657e4658234ce..4098b2d32f9bc 100644
+--- a/sound/soc/intel/boards/glk_rt5682_max98357a.c
++++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c
+@@ -649,6 +649,8 @@ static int geminilake_audio_probe(struct platform_device *pdev)
+ card = &glk_audio_card_rt5682_m98357a;
+ card->dev = &pdev->dev;
+ snd_soc_card_set_drvdata(card, ctx);
++ if (!snd_soc_acpi_sof_parent(&pdev->dev))
++ card->disable_route_checks = true;
+
+ /* override platform name, if required */
+ mach = pdev->dev.platform_data;
+diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c
+index a5d8965303a88..9dbc15f9d1c9b 100644
+--- a/sound/soc/intel/boards/kbl_da7219_max98357a.c
++++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c
+@@ -639,6 +639,7 @@ static struct snd_soc_card kabylake_audio_card_da7219_m98357a = {
+ .dapm_routes = kabylake_map,
+ .num_dapm_routes = ARRAY_SIZE(kabylake_map),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = kabylake_card_late_probe,
+ };
+
+diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c
+index 98c11ec0adc01..e662da5af83b5 100644
+--- a/sound/soc/intel/boards/kbl_da7219_max98927.c
++++ b/sound/soc/intel/boards/kbl_da7219_max98927.c
+@@ -1036,6 +1036,7 @@ static struct snd_soc_card kbl_audio_card_da7219_m98927 = {
+ .codec_conf = max98927_codec_conf,
+ .num_configs = ARRAY_SIZE(max98927_codec_conf),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = kabylake_card_late_probe,
+ };
+
+@@ -1054,6 +1055,7 @@ static struct snd_soc_card kbl_audio_card_max98927 = {
+ .codec_conf = max98927_codec_conf,
+ .num_configs = ARRAY_SIZE(max98927_codec_conf),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = kabylake_card_late_probe,
+ };
+
+@@ -1071,6 +1073,7 @@ static struct snd_soc_card kbl_audio_card_da7219_m98373 = {
+ .codec_conf = max98373_codec_conf,
+ .num_configs = ARRAY_SIZE(max98373_codec_conf),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = kabylake_card_late_probe,
+ };
+
+@@ -1088,6 +1091,7 @@ static struct snd_soc_card kbl_audio_card_max98373 = {
+ .codec_conf = max98373_codec_conf,
+ .num_configs = ARRAY_SIZE(max98373_codec_conf),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = kabylake_card_late_probe,
+ };
+
+diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c
+index 30e0aca161cd5..894d127c482a3 100644
+--- a/sound/soc/intel/boards/kbl_rt5660.c
++++ b/sound/soc/intel/boards/kbl_rt5660.c
+@@ -518,6 +518,7 @@ static struct snd_soc_card kabylake_audio_card_rt5660 = {
+ .dapm_routes = kabylake_rt5660_map,
+ .num_dapm_routes = ARRAY_SIZE(kabylake_rt5660_map),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = kabylake_card_late_probe,
+ };
+
+diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c
+index 9071b1f1cbd00..646e8ff8e9619 100644
+--- a/sound/soc/intel/boards/kbl_rt5663_max98927.c
++++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c
+@@ -966,6 +966,7 @@ static struct snd_soc_card kabylake_audio_card_rt5663_m98927 = {
+ .codec_conf = max98927_codec_conf,
+ .num_configs = ARRAY_SIZE(max98927_codec_conf),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = kabylake_card_late_probe,
+ };
+
+@@ -982,6 +983,7 @@ static struct snd_soc_card kabylake_audio_card_rt5663 = {
+ .dapm_routes = kabylake_5663_map,
+ .num_dapm_routes = ARRAY_SIZE(kabylake_5663_map),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = kabylake_card_late_probe,
+ };
+
+diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
+index 178fe9c37df62..924d5d1de03ac 100644
+--- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
++++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c
+@@ -791,6 +791,7 @@ static struct snd_soc_card kabylake_audio_card = {
+ .codec_conf = max98927_codec_conf,
+ .num_configs = ARRAY_SIZE(max98927_codec_conf),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = kabylake_card_late_probe,
+ };
+
+diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c
+index 6e172719c9795..4aa7fd2a05e46 100644
+--- a/sound/soc/intel/boards/skl_hda_dsp_generic.c
++++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c
+@@ -227,6 +227,8 @@ static int skl_hda_audio_probe(struct platform_device *pdev)
+ ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv;
+
+ hda_soc_card.dev = &pdev->dev;
++ if (!snd_soc_acpi_sof_parent(&pdev->dev))
++ hda_soc_card.disable_route_checks = true;
+
+ if (mach->mach_params.dmic_num > 0) {
+ snprintf(hda_soc_components, sizeof(hda_soc_components),
+diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c
+index 0e7025834594a..e4630c33176e2 100644
+--- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c
++++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c
+@@ -654,6 +654,7 @@ static struct snd_soc_card skylake_audio_card = {
+ .dapm_routes = skylake_map,
+ .num_dapm_routes = ARRAY_SIZE(skylake_map),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = skylake_card_late_probe,
+ };
+
+diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c
+index c59c60e280916..9a80442749081 100644
+--- a/sound/soc/intel/boards/skl_rt286.c
++++ b/sound/soc/intel/boards/skl_rt286.c
+@@ -523,6 +523,7 @@ static struct snd_soc_card skylake_rt286 = {
+ .dapm_routes = skylake_rt286_map,
+ .num_dapm_routes = ARRAY_SIZE(skylake_rt286_map),
+ .fully_routed = true,
++ .disable_route_checks = true,
+ .late_probe = skylake_card_late_probe,
+ };
+
+diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
+index dd2f806526c10..ef00792e1d49a 100644
+--- a/sound/soc/kirkwood/kirkwood-dma.c
++++ b/sound/soc/kirkwood/kirkwood-dma.c
+@@ -182,6 +182,9 @@ static int kirkwood_dma_hw_params(struct snd_soc_component *component,
+ const struct mbus_dram_target_info *dram = mv_mbus_dram_info();
+ unsigned long addr = substream->runtime->dma_addr;
+
++ if (!dram)
++ return 0;
++
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ kirkwood_dma_conf_mbus_windows(priv->io,
+ KIRKWOOD_PLAYBACK_WIN, addr, dram);
+diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c
+index a58e1e3674dec..000a086a8cf44 100644
+--- a/sound/soc/mediatek/common/mtk-soundcard-driver.c
++++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c
+@@ -22,7 +22,11 @@ static int set_card_codec_info(struct snd_soc_card *card,
+
+ codec_node = of_get_child_by_name(sub_node, "codec");
+ if (!codec_node) {
+- dev_dbg(dev, "%s no specified codec\n", dai_link->name);
++ dev_dbg(dev, "%s no specified codec: setting dummy.\n", dai_link->name);
++
++ dai_link->codecs = &snd_soc_dummy_dlc;
++ dai_link->num_codecs = 1;
++ dai_link->dynamic = 1;
+ return 0;
+ }
+
+diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c
+index f4cbc0ad5de3b..0e665c0840d71 100644
+--- a/sound/soc/sof/intel/hda-dai.c
++++ b/sound/soc/sof/intel/hda-dai.c
+@@ -434,10 +434,17 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
+ int link_id)
+ {
+ struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream);
++ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ const struct hda_dai_widget_dma_ops *ops;
++ struct snd_soc_dai_link_ch_map *ch_maps;
+ struct hdac_ext_stream *hext_stream;
++ struct snd_soc_dai *dai;
+ struct snd_sof_dev *sdev;
++ bool cpu_dai_found = false;
++ int cpu_dai_id;
++ int ch_mask;
+ int ret;
++ int j;
+
+ ret = non_hda_dai_hw_params(substream, params, cpu_dai);
+ if (ret < 0) {
+@@ -452,9 +459,29 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
+ if (!hext_stream)
+ return -ENODEV;
+
+- /* in the case of SoundWire we need to program the PCMSyCM registers */
++ /*
++ * in the case of SoundWire we need to program the PCMSyCM registers. In case
++ * of aggregated devices, we need to define the channel mask for each sublink
++ * by reconstructing the split done in soc-pcm.c
++ */
++ for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) {
++ if (dai == cpu_dai) {
++ cpu_dai_found = true;
++ break;
++ }
++ }
++
++ if (!cpu_dai_found)
++ return -ENODEV;
++
++ ch_mask = 0;
++ for_each_link_ch_maps(rtd->dai_link, j, ch_maps) {
++ if (ch_maps->cpu == cpu_dai_id)
++ ch_mask |= ch_maps->ch_mask;
++ }
++
+ ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id,
+- GENMASK(params_channels(params) - 1, 0),
++ ch_mask,
+ hdac_stream(hext_stream)->stream_tag,
+ substream->stream);
+ if (ret < 0) {
+diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c
+index 555a51c688dc6..d6c4d6cd20b05 100644
+--- a/sound/soc/sof/intel/lnl.c
++++ b/sound/soc/sof/intel/lnl.c
+@@ -16,6 +16,7 @@
+ #include "hda-ipc.h"
+ #include "../sof-audio.h"
+ #include "mtl.h"
++#include "lnl.h"
+ #include <sound/hda-mlink.h>
+
+ /* LunarLake ops */
+@@ -176,7 +177,7 @@ const struct sof_intel_dsp_desc lnl_chip_info = {
+ .ipc_ack = MTL_DSP_REG_HFIPCXIDA,
+ .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
+ .ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
+- .rom_status_reg = MTL_DSP_ROM_STS,
++ .rom_status_reg = LNL_DSP_REG_HFDSC,
+ .rom_init_timeout = 300,
+ .ssp_count = MTL_SSP_COUNT,
+ .d0i3_offset = MTL_HDA_VS_D0I3C,
+diff --git a/sound/soc/sof/intel/lnl.h b/sound/soc/sof/intel/lnl.h
+new file mode 100644
+index 0000000000000..4f4734fe7e089
+--- /dev/null
++++ b/sound/soc/sof/intel/lnl.h
+@@ -0,0 +1,15 @@
++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
++/*
++ * This file is provided under a dual BSD/GPLv2 license. When using or
++ * redistributing this file, you may do so under either license.
++ *
++ * Copyright(c) 2024 Intel Corporation. All rights reserved.
++ */
++
++#ifndef __SOF_INTEL_LNL_H
++#define __SOF_INTEL_LNL_H
++
++#define LNL_DSP_REG_HFDSC 0x160200 /* DSP core0 status */
++#define LNL_DSP_REG_HFDEC 0x160204 /* DSP core0 error */
++
++#endif /* __SOF_INTEL_LNL_H */
+diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c
+index 060c34988e90d..05023763080d9 100644
+--- a/sound/soc/sof/intel/mtl.c
++++ b/sound/soc/sof/intel/mtl.c
+@@ -439,7 +439,7 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
+ {
+ struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
+ const struct sof_intel_dsp_desc *chip = hda->desc;
+- unsigned int status;
++ unsigned int status, target_status;
+ u32 ipc_hdr, flags;
+ char *dump_msg;
+ int ret;
+@@ -485,13 +485,40 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
+
+ mtl_enable_ipc_interrupts(sdev);
+
++ if (chip->rom_status_reg == MTL_DSP_ROM_STS) {
++ /*
++ * Workaround: when the ROM status register is pointing to
++ * the SRAM window (MTL_DSP_ROM_STS) the platform cannot catch
++ * ROM_INIT_DONE because of a very short timing window.
++ * Follow the recommendations and skip target state waiting.
++ */
++ return 0;
++ }
++
+ /*
+- * ACE workaround: don't wait for ROM INIT.
+- * The platform cannot catch ROM_INIT_DONE because of a very short
+- * timing window. Follow the recommendations and skip this part.
++ * step 7:
++ * - Cold/Full boot: wait for ROM init to proceed to download the firmware
++ * - IMR boot: wait for ROM firmware entered (firmware booted up from IMR)
+ */
++ if (imr_boot)
++ target_status = FSR_STATE_FW_ENTERED;
++ else
++ target_status = FSR_STATE_INIT_DONE;
+
+- return 0;
++ ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR,
++ chip->rom_status_reg, status,
++ (FSR_TO_STATE_CODE(status) == target_status),
++ HDA_DSP_REG_POLL_INTERVAL_US,
++ chip->rom_init_timeout *
++ USEC_PER_MSEC);
++
++ if (!ret)
++ return 0;
++
++ if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS)
++ dev_err(sdev->dev,
++ "%s: timeout with rom_status_reg (%#x) read\n",
++ __func__, chip->rom_status_reg);
+
+ err:
+ flags = SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX | SOF_DBG_DUMP_OPTIONAL;
+@@ -503,6 +530,7 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
+ dump_msg = kasprintf(GFP_KERNEL, "Boot iteration failed: %d/%d",
+ hda->boot_iteration, HDA_FW_BOOT_ATTEMPTS);
+ snd_sof_dsp_dbg_dump(sdev, dump_msg, flags);
++ mtl_enable_interrupts(sdev, false);
+ mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE);
+
+ kfree(dump_msg);
+@@ -727,7 +755,7 @@ const struct sof_intel_dsp_desc mtl_chip_info = {
+ .ipc_ack = MTL_DSP_REG_HFIPCXIDA,
+ .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
+ .ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
+- .rom_status_reg = MTL_DSP_ROM_STS,
++ .rom_status_reg = MTL_DSP_REG_HFFLGPXQWY,
+ .rom_init_timeout = 300,
+ .ssp_count = MTL_SSP_COUNT,
+ .ssp_base_offset = CNL_SSP_BASE_OFFSET,
+@@ -755,7 +783,7 @@ const struct sof_intel_dsp_desc arl_s_chip_info = {
+ .ipc_ack = MTL_DSP_REG_HFIPCXIDA,
+ .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
+ .ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
+- .rom_status_reg = MTL_DSP_ROM_STS,
++ .rom_status_reg = MTL_DSP_REG_HFFLGPXQWY,
+ .rom_init_timeout = 300,
+ .ssp_count = MTL_SSP_COUNT,
+ .ssp_base_offset = CNL_SSP_BASE_OFFSET,
+diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h
+index ea8c1b83f7127..3c56427a966bf 100644
+--- a/sound/soc/sof/intel/mtl.h
++++ b/sound/soc/sof/intel/mtl.h
+@@ -70,8 +70,8 @@
+ #define MTL_DSP_ROM_STS MTL_SRAM_WINDOW_OFFSET(0) /* ROM status */
+ #define MTL_DSP_ROM_ERROR (MTL_SRAM_WINDOW_OFFSET(0) + 0x4) /* ROM error code */
+
+-#define MTL_DSP_REG_HFFLGPXQWY 0x163200 /* ROM debug status */
+-#define MTL_DSP_REG_HFFLGPXQWY_ERROR 0x163204 /* ROM debug error code */
++#define MTL_DSP_REG_HFFLGPXQWY 0x163200 /* DSP core0 status */
++#define MTL_DSP_REG_HFFLGPXQWY_ERROR 0x163204 /* DSP core0 error */
+ #define MTL_DSP_REG_HfIMRIS1 0x162088
+ #define MTL_DSP_REG_HfIMRIS1_IU_MASK BIT(0)
+
+diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c
+index 330f04bcd75d2..a7cf52fd76455 100644
+--- a/sound/soc/sof/ipc3-pcm.c
++++ b/sound/soc/sof/ipc3-pcm.c
+@@ -409,4 +409,5 @@ const struct sof_ipc_pcm_ops ipc3_pcm_ops = {
+ .trigger = sof_ipc3_pcm_trigger,
+ .dai_link_fixup = sof_ipc3_pcm_dai_link_fixup,
+ .reset_hw_params_during_stop = true,
++ .d0i3_supported_in_s0ix = true,
+ };
+diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c
+index a99fced908251..d07c1b06207a5 100644
+--- a/sound/soc/sof/ipc4-pcm.c
++++ b/sound/soc/sof/ipc4-pcm.c
+@@ -37,6 +37,22 @@ struct sof_ipc4_timestamp_info {
+ snd_pcm_sframes_t delay;
+ };
+
++/**
++ * struct sof_ipc4_pcm_stream_priv - IPC4 specific private data
++ * @time_info: pointer to time info struct if it is supported, otherwise NULL
++ */
++struct sof_ipc4_pcm_stream_priv {
++ struct sof_ipc4_timestamp_info *time_info;
++};
++
++static inline struct sof_ipc4_timestamp_info *
++sof_ipc4_sps_to_time_info(struct snd_sof_pcm_stream *sps)
++{
++ struct sof_ipc4_pcm_stream_priv *stream_priv = sps->private;
++
++ return stream_priv->time_info;
++}
++
+ static int sof_ipc4_set_multi_pipeline_state(struct snd_sof_dev *sdev, u32 state,
+ struct ipc4_pipeline_set_state_data *trigger_list)
+ {
+@@ -435,7 +451,7 @@ static int sof_ipc4_trigger_pipelines(struct snd_soc_component *component,
+ * Invalidate the stream_start_offset to make sure that it is
+ * going to be updated if the stream resumes
+ */
+- time_info = spcm->stream[substream->stream].private;
++ time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
+ if (time_info)
+ time_info->stream_start_offset = SOF_IPC4_INVALID_STREAM_POSITION;
+
+@@ -689,12 +705,16 @@ static int sof_ipc4_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
+ static void sof_ipc4_pcm_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm)
+ {
+ struct snd_sof_pcm_stream_pipeline_list *pipeline_list;
++ struct sof_ipc4_pcm_stream_priv *stream_priv;
+ int stream;
+
+ for_each_pcm_streams(stream) {
+ pipeline_list = &spcm->stream[stream].pipeline_list;
+ kfree(pipeline_list->pipelines);
+ pipeline_list->pipelines = NULL;
++
++ stream_priv = spcm->stream[stream].private;
++ kfree(stream_priv->time_info);
+ kfree(spcm->stream[stream].private);
+ spcm->stream[stream].private = NULL;
+ }
+@@ -704,7 +724,8 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
+ {
+ struct snd_sof_pcm_stream_pipeline_list *pipeline_list;
+ struct sof_ipc4_fw_data *ipc4_data = sdev->private;
+- struct sof_ipc4_timestamp_info *stream_info;
++ struct sof_ipc4_pcm_stream_priv *stream_priv;
++ struct sof_ipc4_timestamp_info *time_info;
+ bool support_info = true;
+ u32 abi_version;
+ u32 abi_offset;
+@@ -732,33 +753,41 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
+ return -ENOMEM;
+ }
+
++ stream_priv = kzalloc(sizeof(*stream_priv), GFP_KERNEL);
++ if (!stream_priv) {
++ sof_ipc4_pcm_free(sdev, spcm);
++ return -ENOMEM;
++ }
++
++ spcm->stream[stream].private = stream_priv;
++
+ if (!support_info)
+ continue;
+
+- stream_info = kzalloc(sizeof(*stream_info), GFP_KERNEL);
+- if (!stream_info) {
++ time_info = kzalloc(sizeof(*time_info), GFP_KERNEL);
++ if (!time_info) {
+ sof_ipc4_pcm_free(sdev, spcm);
+ return -ENOMEM;
+ }
+
+- spcm->stream[stream].private = stream_info;
++ stream_priv->time_info = time_info;
+ }
+
+ return 0;
+ }
+
+-static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *spcm)
++static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sps)
+ {
+ struct sof_ipc4_copier *host_copier = NULL;
+ struct sof_ipc4_copier *dai_copier = NULL;
+ struct sof_ipc4_llp_reading_slot llp_slot;
+- struct sof_ipc4_timestamp_info *info;
++ struct sof_ipc4_timestamp_info *time_info;
+ struct snd_soc_dapm_widget *widget;
+ struct snd_sof_dai *dai;
+ int i;
+
+ /* find host & dai to locate info in memory window */
+- for_each_dapm_widgets(spcm->list, i, widget) {
++ for_each_dapm_widgets(sps->list, i, widget) {
+ struct snd_sof_widget *swidget = widget->dobj.private;
+
+ if (!swidget)
+@@ -778,44 +807,44 @@ static void sof_ipc4_build_time_info(struct snd_sof_dev *sdev, struct snd_sof_pc
+ return;
+ }
+
+- info = spcm->private;
+- info->host_copier = host_copier;
+- info->dai_copier = dai_copier;
+- info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_gpdma_reading_slots) +
+- sdev->fw_info_box.offset;
++ time_info = sof_ipc4_sps_to_time_info(sps);
++ time_info->host_copier = host_copier;
++ time_info->dai_copier = dai_copier;
++ time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers,
++ llp_gpdma_reading_slots) + sdev->fw_info_box.offset;
+
+ /* find llp slot used by current dai */
+ for (i = 0; i < SOF_IPC4_MAX_LLP_GPDMA_READING_SLOTS; i++) {
+- sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot));
++ sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot));
+ if (llp_slot.node_id == dai_copier->data.gtw_cfg.node_id)
+ break;
+
+- info->llp_offset += sizeof(llp_slot);
++ time_info->llp_offset += sizeof(llp_slot);
+ }
+
+ if (i < SOF_IPC4_MAX_LLP_GPDMA_READING_SLOTS)
+ return;
+
+ /* if no llp gpdma slot is used, check aggregated sdw slot */
+- info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_sndw_reading_slots) +
+- sdev->fw_info_box.offset;
++ time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers,
++ llp_sndw_reading_slots) + sdev->fw_info_box.offset;
+ for (i = 0; i < SOF_IPC4_MAX_LLP_SNDW_READING_SLOTS; i++) {
+- sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot));
++ sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot));
+ if (llp_slot.node_id == dai_copier->data.gtw_cfg.node_id)
+ break;
+
+- info->llp_offset += sizeof(llp_slot);
++ time_info->llp_offset += sizeof(llp_slot);
+ }
+
+ if (i < SOF_IPC4_MAX_LLP_SNDW_READING_SLOTS)
+ return;
+
+ /* check EVAD slot */
+- info->llp_offset = offsetof(struct sof_ipc4_fw_registers, llp_evad_reading_slot) +
+- sdev->fw_info_box.offset;
+- sof_mailbox_read(sdev, info->llp_offset, &llp_slot, sizeof(llp_slot));
++ time_info->llp_offset = offsetof(struct sof_ipc4_fw_registers,
++ llp_evad_reading_slot) + sdev->fw_info_box.offset;
++ sof_mailbox_read(sdev, time_info->llp_offset, &llp_slot, sizeof(llp_slot));
+ if (llp_slot.node_id != dai_copier->data.gtw_cfg.node_id)
+- info->llp_offset = 0;
++ time_info->llp_offset = 0;
+ }
+
+ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
+@@ -832,7 +861,7 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
+ if (!spcm)
+ return -EINVAL;
+
+- time_info = spcm->stream[substream->stream].private;
++ time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
+ /* delay calculation is not supported by current fw_reg ABI */
+ if (!time_info)
+ return 0;
+@@ -847,7 +876,7 @@ static int sof_ipc4_pcm_hw_params(struct snd_soc_component *component,
+
+ static int sof_ipc4_get_stream_start_offset(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+- struct snd_sof_pcm_stream *stream,
++ struct snd_sof_pcm_stream *sps,
+ struct sof_ipc4_timestamp_info *time_info)
+ {
+ struct sof_ipc4_copier *host_copier = time_info->host_copier;
+@@ -901,7 +930,7 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
+ struct sof_ipc4_timestamp_info *time_info;
+ struct sof_ipc4_llp_reading_slot llp;
+ snd_pcm_uframes_t head_cnt, tail_cnt;
+- struct snd_sof_pcm_stream *stream;
++ struct snd_sof_pcm_stream *sps;
+ u64 dai_cnt, host_cnt, host_ptr;
+ struct snd_sof_pcm *spcm;
+ int ret;
+@@ -910,8 +939,8 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
+ if (!spcm)
+ return -EOPNOTSUPP;
+
+- stream = &spcm->stream[substream->stream];
+- time_info = stream->private;
++ sps = &spcm->stream[substream->stream];
++ time_info = sof_ipc4_sps_to_time_info(sps);
+ if (!time_info)
+ return -EOPNOTSUPP;
+
+@@ -921,7 +950,7 @@ static int sof_ipc4_pcm_pointer(struct snd_soc_component *component,
+ * the statistics is complete. And it will not change after the first initiailization.
+ */
+ if (time_info->stream_start_offset == SOF_IPC4_INVALID_STREAM_POSITION) {
+- ret = sof_ipc4_get_stream_start_offset(sdev, substream, stream, time_info);
++ ret = sof_ipc4_get_stream_start_offset(sdev, substream, sps, time_info);
+ if (ret < 0)
+ return -EOPNOTSUPP;
+ }
+@@ -1013,15 +1042,13 @@ static snd_pcm_sframes_t sof_ipc4_pcm_delay(struct snd_soc_component *component,
+ {
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct sof_ipc4_timestamp_info *time_info;
+- struct snd_sof_pcm_stream *stream;
+ struct snd_sof_pcm *spcm;
+
+ spcm = snd_sof_find_spcm_dai(component, rtd);
+ if (!spcm)
+ return 0;
+
+- stream = &spcm->stream[substream->stream];
+- time_info = stream->private;
++ time_info = sof_ipc4_sps_to_time_info(&spcm->stream[substream->stream]);
+ /*
+ * Report the stored delay value calculated in the pointer callback.
+ * In the unlikely event that the calculation was skipped/aborted, the
+diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c
+index f03cee94bce62..8804e00e7251b 100644
+--- a/sound/soc/sof/pcm.c
++++ b/sound/soc/sof/pcm.c
+@@ -325,14 +325,13 @@ static int sof_pcm_trigger(struct snd_soc_component *component,
+ ipc_first = true;
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+- if (sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
++ /*
++ * If DSP D0I3 is allowed during S0iX, set the suspend_ignored flag for
++ * D0I3-compatible streams to keep the firmware pipeline running
++ */
++ if (pcm_ops && pcm_ops->d0i3_supported_in_s0ix &&
++ sdev->system_suspend_target == SOF_SUSPEND_S0IX &&
+ spcm->stream[substream->stream].d0i3_compatible) {
+- /*
+- * trap the event, not sending trigger stop to
+- * prevent the FW pipelines from being stopped,
+- * and mark the flag to ignore the upcoming DAPM
+- * PM events.
+- */
+ spcm->stream[substream->stream].suspend_ignored = true;
+ return 0;
+ }
+diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h
+index 85b26e3fefa8f..05e2a899d746c 100644
+--- a/sound/soc/sof/sof-audio.h
++++ b/sound/soc/sof/sof-audio.h
+@@ -116,6 +116,7 @@ struct snd_sof_dai_config_data {
+ * triggers. The FW keeps the host DMA running in this case and
+ * therefore the host must do the same and should stop the DMA during
+ * hw_free.
++ * @d0i3_supported_in_s0ix: Allow DSP D0I3 during S0iX
+ */
+ struct sof_ipc_pcm_ops {
+ int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream,
+@@ -135,6 +136,7 @@ struct sof_ipc_pcm_ops {
+ bool reset_hw_params_during_stop;
+ bool ipc_first_on_start;
+ bool platform_stop_during_hw_free;
++ bool d0i3_supported_in_s0ix;
+ };
+
+ /**
+diff --git a/tools/arch/x86/lib/x86-opcode-map.txt b/tools/arch/x86/lib/x86-opcode-map.txt
+index 5168ee0360b24..d1ccd06c53127 100644
+--- a/tools/arch/x86/lib/x86-opcode-map.txt
++++ b/tools/arch/x86/lib/x86-opcode-map.txt
+@@ -148,7 +148,7 @@ AVXcode:
+ 65: SEG=GS (Prefix)
+ 66: Operand-Size (Prefix)
+ 67: Address-Size (Prefix)
+-68: PUSH Iz (d64)
++68: PUSH Iz
+ 69: IMUL Gv,Ev,Iz
+ 6a: PUSH Ib (d64)
+ 6b: IMUL Gv,Ev,Ib
+@@ -698,10 +698,10 @@ AVXcode: 2
+ 4d: vrcp14ss/d Vsd,Hpd,Wsd (66),(ev)
+ 4e: vrsqrt14ps/d Vpd,Wpd (66),(ev)
+ 4f: vrsqrt14ss/d Vsd,Hsd,Wsd (66),(ev)
+-50: vpdpbusd Vx,Hx,Wx (66),(ev)
+-51: vpdpbusds Vx,Hx,Wx (66),(ev)
+-52: vdpbf16ps Vx,Hx,Wx (F3),(ev) | vpdpwssd Vx,Hx,Wx (66),(ev) | vp4dpwssd Vdqq,Hdqq,Wdq (F2),(ev)
+-53: vpdpwssds Vx,Hx,Wx (66),(ev) | vp4dpwssds Vdqq,Hdqq,Wdq (F2),(ev)
++50: vpdpbusd Vx,Hx,Wx (66)
++51: vpdpbusds Vx,Hx,Wx (66)
++52: vdpbf16ps Vx,Hx,Wx (F3),(ev) | vpdpwssd Vx,Hx,Wx (66) | vp4dpwssd Vdqq,Hdqq,Wdq (F2),(ev)
++53: vpdpwssds Vx,Hx,Wx (66) | vp4dpwssds Vdqq,Hdqq,Wdq (F2),(ev)
+ 54: vpopcntb/w Vx,Wx (66),(ev)
+ 55: vpopcntd/q Vx,Wx (66),(ev)
+ 58: vpbroadcastd Vx,Wx (66),(v)
+diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
+index cc6e6aae2447d..958e92acca8e2 100644
+--- a/tools/bpf/bpftool/common.c
++++ b/tools/bpf/bpftool/common.c
+@@ -244,29 +244,101 @@ int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type)
+ return fd;
+ }
+
+-int mount_bpffs_for_pin(const char *name, bool is_dir)
++int create_and_mount_bpffs_dir(const char *dir_name)
+ {
+ char err_str[ERR_MAX_LEN];
+- char *file;
+- char *dir;
++ bool dir_exists;
+ int err = 0;
+
+- if (is_dir && is_bpffs(name))
++ if (is_bpffs(dir_name))
+ return err;
+
+- file = malloc(strlen(name) + 1);
+- if (!file) {
++ dir_exists = access(dir_name, F_OK) == 0;
++
++ if (!dir_exists) {
++ char *temp_name;
++ char *parent_name;
++
++ temp_name = strdup(dir_name);
++ if (!temp_name) {
++ p_err("mem alloc failed");
++ return -1;
++ }
++
++ parent_name = dirname(temp_name);
++
++ if (is_bpffs(parent_name)) {
++ /* nothing to do if already mounted */
++ free(temp_name);
++ return err;
++ }
++
++ if (access(parent_name, F_OK) == -1) {
++ p_err("can't create dir '%s' to pin BPF object: parent dir '%s' doesn't exist",
++ dir_name, parent_name);
++ free(temp_name);
++ return -1;
++ }
++
++ free(temp_name);
++ }
++
++ if (block_mount) {
++ p_err("no BPF file system found, not mounting it due to --nomount option");
++ return -1;
++ }
++
++ if (!dir_exists) {
++ err = mkdir(dir_name, S_IRWXU);
++ if (err) {
++ p_err("failed to create dir '%s': %s", dir_name, strerror(errno));
++ return err;
++ }
++ }
++
++ err = mnt_fs(dir_name, "bpf", err_str, ERR_MAX_LEN);
++ if (err) {
++ err_str[ERR_MAX_LEN - 1] = '\0';
++ p_err("can't mount BPF file system on given dir '%s': %s",
++ dir_name, err_str);
++
++ if (!dir_exists)
++ rmdir(dir_name);
++ }
++
++ return err;
++}
++
++int mount_bpffs_for_file(const char *file_name)
++{
++ char err_str[ERR_MAX_LEN];
++ char *temp_name;
++ char *dir;
++ int err = 0;
++
++ if (access(file_name, F_OK) != -1) {
++ p_err("can't pin BPF object: path '%s' already exists", file_name);
++ return -1;
++ }
++
++ temp_name = strdup(file_name);
++ if (!temp_name) {
+ p_err("mem alloc failed");
+ return -1;
+ }
+
+- strcpy(file, name);
+- dir = dirname(file);
++ dir = dirname(temp_name);
+
+ if (is_bpffs(dir))
+ /* nothing to do if already mounted */
+ goto out_free;
+
++ if (access(dir, F_OK) == -1) {
++ p_err("can't pin BPF object: dir '%s' doesn't exist", dir);
++ err = -1;
++ goto out_free;
++ }
++
+ if (block_mount) {
+ p_err("no BPF file system found, not mounting it due to --nomount option");
+ err = -1;
+@@ -276,12 +348,12 @@ int mount_bpffs_for_pin(const char *name, bool is_dir)
+ err = mnt_fs(dir, "bpf", err_str, ERR_MAX_LEN);
+ if (err) {
+ err_str[ERR_MAX_LEN - 1] = '\0';
+- p_err("can't mount BPF file system to pin the object (%s): %s",
+- name, err_str);
++ p_err("can't mount BPF file system to pin the object '%s': %s",
++ file_name, err_str);
+ }
+
+ out_free:
+- free(file);
++ free(temp_name);
+ return err;
+ }
+
+@@ -289,7 +361,7 @@ int do_pin_fd(int fd, const char *name)
+ {
+ int err;
+
+- err = mount_bpffs_for_pin(name, false);
++ err = mount_bpffs_for_file(name);
+ if (err)
+ return err;
+
+diff --git a/tools/bpf/bpftool/iter.c b/tools/bpf/bpftool/iter.c
+index 6b0e5202ca7a9..5c39c2ed36a2b 100644
+--- a/tools/bpf/bpftool/iter.c
++++ b/tools/bpf/bpftool/iter.c
+@@ -76,7 +76,7 @@ static int do_pin(int argc, char **argv)
+ goto close_obj;
+ }
+
+- err = mount_bpffs_for_pin(path, false);
++ err = mount_bpffs_for_file(path);
+ if (err)
+ goto close_link;
+
+diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
+index b8bb08d10dec9..9eb764fe4cc8b 100644
+--- a/tools/bpf/bpftool/main.h
++++ b/tools/bpf/bpftool/main.h
+@@ -142,7 +142,8 @@ const char *get_fd_type_name(enum bpf_obj_type type);
+ char *get_fdinfo(int fd, const char *key);
+ int open_obj_pinned(const char *path, bool quiet);
+ int open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type);
+-int mount_bpffs_for_pin(const char *name, bool is_dir);
++int mount_bpffs_for_file(const char *file_name);
++int create_and_mount_bpffs_dir(const char *dir_name);
+ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(int *, char ***));
+ int do_pin_fd(int fd, const char *name);
+
+diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
+index 9cb42a3366c07..4c4cf16a40ba7 100644
+--- a/tools/bpf/bpftool/prog.c
++++ b/tools/bpf/bpftool/prog.c
+@@ -1778,7 +1778,10 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
+ goto err_close_obj;
+ }
+
+- err = mount_bpffs_for_pin(pinfile, !first_prog_only);
++ if (first_prog_only)
++ err = mount_bpffs_for_file(pinfile);
++ else
++ err = create_and_mount_bpffs_dir(pinfile);
+ if (err)
+ goto err_close_obj;
+
+diff --git a/tools/bpf/bpftool/skeleton/pid_iter.bpf.c b/tools/bpf/bpftool/skeleton/pid_iter.bpf.c
+index 26004f0c5a6ae..7bdbcac3cf628 100644
+--- a/tools/bpf/bpftool/skeleton/pid_iter.bpf.c
++++ b/tools/bpf/bpftool/skeleton/pid_iter.bpf.c
+@@ -102,8 +102,8 @@ int iter(struct bpf_iter__task_file *ctx)
+ BPF_LINK_TYPE_PERF_EVENT___local)) {
+ struct bpf_link *link = (struct bpf_link *) file->private_data;
+
+- if (link->type == bpf_core_enum_value(enum bpf_link_type___local,
+- BPF_LINK_TYPE_PERF_EVENT___local)) {
++ if (BPF_CORE_READ(link, type) == bpf_core_enum_value(enum bpf_link_type___local,
++ BPF_LINK_TYPE_PERF_EVENT___local)) {
+ e.has_bpf_cookie = true;
+ e.bpf_cookie = get_bpf_cookie(link);
+ }
+diff --git a/tools/bpf/bpftool/struct_ops.c b/tools/bpf/bpftool/struct_ops.c
+index d573f2640d8e9..aa43dead249cb 100644
+--- a/tools/bpf/bpftool/struct_ops.c
++++ b/tools/bpf/bpftool/struct_ops.c
+@@ -515,7 +515,7 @@ static int do_register(int argc, char **argv)
+ if (argc == 1)
+ linkdir = GET_ARG();
+
+- if (linkdir && mount_bpffs_for_pin(linkdir, true)) {
++ if (linkdir && create_and_mount_bpffs_dir(linkdir)) {
+ p_err("can't mount bpffs for pinning");
+ return -1;
+ }
+diff --git a/tools/include/nolibc/stdlib.h b/tools/include/nolibc/stdlib.h
+index bacfd35c51565..5be9d3c7435a8 100644
+--- a/tools/include/nolibc/stdlib.h
++++ b/tools/include/nolibc/stdlib.h
+@@ -185,7 +185,7 @@ void *realloc(void *old_ptr, size_t new_size)
+ if (__builtin_expect(!ret, 0))
+ return NULL;
+
+- memcpy(ret, heap->user_p, heap->len);
++ memcpy(ret, heap->user_p, user_p_len);
+ munmap(heap, heap->len);
+ return ret;
+ }
+diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
+index 7f24d898efbb4..a12f597a1c47f 100644
+--- a/tools/include/uapi/linux/bpf.h
++++ b/tools/include/uapi/linux/bpf.h
+@@ -7039,7 +7039,7 @@ struct bpf_fib_lookup {
+
+ /* output: MTU value */
+ __u16 mtu_result;
+- };
++ } __attribute__((packed, aligned(2)));
+ /* input: L3 device index for lookup
+ * output: device index from FIB lookup
+ */
+diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
+index 92bca96587a4a..028d8f014c871 100644
+--- a/tools/lib/bpf/libbpf.c
++++ b/tools/lib/bpf/libbpf.c
+@@ -7456,9 +7456,9 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog
+ char *cp, errmsg[STRERR_BUFSIZE];
+ size_t log_buf_size = 0;
+ char *log_buf = NULL, *tmp;
+- int btf_fd, ret, err;
+ bool own_log_buf = true;
+ __u32 log_level = prog->log_level;
++ int ret, err;
+
+ if (prog->type == BPF_PROG_TYPE_UNSPEC) {
+ /*
+@@ -7482,9 +7482,8 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog
+ load_attr.prog_ifindex = prog->prog_ifindex;
+
+ /* specify func_info/line_info only if kernel supports them */
+- btf_fd = btf__fd(obj->btf);
+- if (btf_fd >= 0 && kernel_supports(obj, FEAT_BTF_FUNC)) {
+- load_attr.prog_btf_fd = btf_fd;
++ if (obj->btf && btf__fd(obj->btf) >= 0 && kernel_supports(obj, FEAT_BTF_FUNC)) {
++ load_attr.prog_btf_fd = btf__fd(obj->btf);
+ load_attr.func_info = prog->func_info;
+ load_attr.func_info_rec_size = prog->func_info_rec_size;
+ load_attr.func_info_cnt = prog->func_info_cnt;
+@@ -11562,7 +11561,7 @@ static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, stru
+
+ n = sscanf(spec, "%m[a-zA-Z0-9_.*?]", &pattern);
+ if (n < 1) {
+- pr_warn("kprobe multi pattern is invalid: %s\n", pattern);
++ pr_warn("kprobe multi pattern is invalid: %s\n", spec);
+ return -EINVAL;
+ }
+
+diff --git a/tools/testing/selftests/bpf/cgroup_helpers.c b/tools/testing/selftests/bpf/cgroup_helpers.c
+index 19be9c63d5e84..e812876d79c7e 100644
+--- a/tools/testing/selftests/bpf/cgroup_helpers.c
++++ b/tools/testing/selftests/bpf/cgroup_helpers.c
+@@ -508,6 +508,9 @@ int cgroup_setup_and_join(const char *path) {
+ /**
+ * setup_classid_environment() - Setup the cgroupv1 net_cls environment
+ *
++ * This function should only be called in a custom mount namespace, e.g.
++ * created by running setup_cgroup_environment.
++ *
+ * After calling this function, cleanup_classid_environment should be called
+ * once testing is complete.
+ *
+diff --git a/tools/testing/selftests/bpf/network_helpers.c b/tools/testing/selftests/bpf/network_helpers.c
+index 6db27a9088e97..be96bf022316f 100644
+--- a/tools/testing/selftests/bpf/network_helpers.c
++++ b/tools/testing/selftests/bpf/network_helpers.c
+@@ -461,6 +461,8 @@ struct nstoken *open_netns(const char *name)
+
+ return token;
+ fail:
++ if (token->orig_netns_fd != -1)
++ close(token->orig_netns_fd);
+ free(token);
+ return NULL;
+ }
+diff --git a/tools/testing/selftests/bpf/prog_tests/cgroup1_hierarchy.c b/tools/testing/selftests/bpf/prog_tests/cgroup1_hierarchy.c
+index 74d6d7546f40f..25332e596750f 100644
+--- a/tools/testing/selftests/bpf/prog_tests/cgroup1_hierarchy.c
++++ b/tools/testing/selftests/bpf/prog_tests/cgroup1_hierarchy.c
+@@ -87,9 +87,12 @@ void test_cgroup1_hierarchy(void)
+ goto destroy;
+
+ /* Setup cgroup1 hierarchy */
++ err = setup_cgroup_environment();
++ if (!ASSERT_OK(err, "setup_cgroup_environment"))
++ goto destroy;
+ err = setup_classid_environment();
+ if (!ASSERT_OK(err, "setup_classid_environment"))
+- goto destroy;
++ goto cleanup_cgroup;
+
+ err = join_classid();
+ if (!ASSERT_OK(err, "join_cgroup1"))
+@@ -153,6 +156,8 @@ void test_cgroup1_hierarchy(void)
+
+ cleanup:
+ cleanup_classid_environment();
++cleanup_cgroup:
++ cleanup_cgroup_environment();
+ destroy:
+ test_cgroup1_hierarchy__destroy(skel);
+ }
+diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c b/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c
+index 498d3bdaa4b0b..bad0ea167be70 100644
+--- a/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c
++++ b/tools/testing/selftests/bpf/prog_tests/xdp_do_redirect.c
+@@ -107,8 +107,8 @@ void test_xdp_do_redirect(void)
+ .attach_point = BPF_TC_INGRESS);
+
+ memcpy(&data[sizeof(__u64)], &pkt_udp, sizeof(pkt_udp));
+- *((__u32 *)data) = 0x42; /* metadata test value */
+- *((__u32 *)data + 4) = 0;
++ ((__u32 *)data)[0] = 0x42; /* metadata test value */
++ ((__u32 *)data)[1] = 0;
+
+ skel = test_xdp_do_redirect__open();
+ if (!ASSERT_OK_PTR(skel, "skel"))
+diff --git a/tools/testing/selftests/bpf/progs/bench_local_storage_create.c b/tools/testing/selftests/bpf/progs/bench_local_storage_create.c
+index e4bfbba6c1936..c8ec0d0368e4a 100644
+--- a/tools/testing/selftests/bpf/progs/bench_local_storage_create.c
++++ b/tools/testing/selftests/bpf/progs/bench_local_storage_create.c
+@@ -61,14 +61,15 @@ SEC("lsm.s/socket_post_create")
+ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,
+ int protocol, int kern)
+ {
++ struct sock *sk = sock->sk;
+ struct storage *stg;
+ __u32 pid;
+
+ pid = bpf_get_current_pid_tgid() >> 32;
+- if (pid != bench_pid)
++ if (pid != bench_pid || !sk)
+ return 0;
+
+- stg = bpf_sk_storage_get(&sk_storage_map, sock->sk, NULL,
++ stg = bpf_sk_storage_get(&sk_storage_map, sk, NULL,
+ BPF_LOCAL_STORAGE_GET_F_CREATE);
+
+ if (stg)
+diff --git a/tools/testing/selftests/bpf/progs/local_storage.c b/tools/testing/selftests/bpf/progs/local_storage.c
+index e5e3a8b8dd075..637e75df2e146 100644
+--- a/tools/testing/selftests/bpf/progs/local_storage.c
++++ b/tools/testing/selftests/bpf/progs/local_storage.c
+@@ -140,11 +140,12 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
+ {
+ __u32 pid = bpf_get_current_pid_tgid() >> 32;
+ struct local_storage *storage;
++ struct sock *sk = sock->sk;
+
+- if (pid != monitored_pid)
++ if (pid != monitored_pid || !sk)
+ return 0;
+
+- storage = bpf_sk_storage_get(&sk_storage_map, sock->sk, 0, 0);
++ storage = bpf_sk_storage_get(&sk_storage_map, sk, 0, 0);
+ if (!storage)
+ return 0;
+
+@@ -155,24 +156,24 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
+ /* This tests that we can associate multiple elements
+ * with the local storage.
+ */
+- storage = bpf_sk_storage_get(&sk_storage_map2, sock->sk, 0,
++ storage = bpf_sk_storage_get(&sk_storage_map2, sk, 0,
+ BPF_LOCAL_STORAGE_GET_F_CREATE);
+ if (!storage)
+ return 0;
+
+- if (bpf_sk_storage_delete(&sk_storage_map2, sock->sk))
++ if (bpf_sk_storage_delete(&sk_storage_map2, sk))
+ return 0;
+
+- storage = bpf_sk_storage_get(&sk_storage_map2, sock->sk, 0,
++ storage = bpf_sk_storage_get(&sk_storage_map2, sk, 0,
+ BPF_LOCAL_STORAGE_GET_F_CREATE);
+ if (!storage)
+ return 0;
+
+- if (bpf_sk_storage_delete(&sk_storage_map, sock->sk))
++ if (bpf_sk_storage_delete(&sk_storage_map, sk))
+ return 0;
+
+ /* Ensure that the sk_storage_map is disconnected from the storage. */
+- if (!sock->sk->sk_bpf_storage || sock->sk->sk_bpf_storage->smap)
++ if (!sk->sk_bpf_storage || sk->sk_bpf_storage->smap)
+ return 0;
+
+ sk_storage_result = 0;
+@@ -185,11 +186,12 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,
+ {
+ __u32 pid = bpf_get_current_pid_tgid() >> 32;
+ struct local_storage *storage;
++ struct sock *sk = sock->sk;
+
+- if (pid != monitored_pid)
++ if (pid != monitored_pid || !sk)
+ return 0;
+
+- storage = bpf_sk_storage_get(&sk_storage_map, sock->sk, 0,
++ storage = bpf_sk_storage_get(&sk_storage_map, sk, 0,
+ BPF_LOCAL_STORAGE_GET_F_CREATE);
+ if (!storage)
+ return 0;
+diff --git a/tools/testing/selftests/bpf/progs/lsm_cgroup.c b/tools/testing/selftests/bpf/progs/lsm_cgroup.c
+index 02c11d16b692a..d7598538aa2da 100644
+--- a/tools/testing/selftests/bpf/progs/lsm_cgroup.c
++++ b/tools/testing/selftests/bpf/progs/lsm_cgroup.c
+@@ -103,11 +103,15 @@ static __always_inline int real_bind(struct socket *sock,
+ int addrlen)
+ {
+ struct sockaddr_ll sa = {};
++ struct sock *sk = sock->sk;
+
+- if (sock->sk->__sk_common.skc_family != AF_PACKET)
++ if (!sk)
++ return 1;
++
++ if (sk->__sk_common.skc_family != AF_PACKET)
+ return 1;
+
+- if (sock->sk->sk_kern_sock)
++ if (sk->sk_kern_sock)
+ return 1;
+
+ bpf_probe_read_kernel(&sa, sizeof(sa), address);
+diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c
+index 024a0faafb3be..43612de44fbf5 100644
+--- a/tools/testing/selftests/bpf/test_sockmap.c
++++ b/tools/testing/selftests/bpf/test_sockmap.c
+@@ -2104,9 +2104,9 @@ int main(int argc, char **argv)
+ free(options.whitelist);
+ if (options.blacklist)
+ free(options.blacklist);
++ close(cg_fd);
+ if (cg_created)
+ cleanup_cgroup_environment();
+- close(cg_fd);
+ return err;
+ }
+
+diff --git a/tools/testing/selftests/cgroup/cgroup_util.c b/tools/testing/selftests/cgroup/cgroup_util.c
+index 0340d4ca8f51c..432db923bced0 100644
+--- a/tools/testing/selftests/cgroup/cgroup_util.c
++++ b/tools/testing/selftests/cgroup/cgroup_util.c
+@@ -195,10 +195,10 @@ int cg_write_numeric(const char *cgroup, const char *control, long value)
+ return cg_write(cgroup, control, buf);
+ }
+
+-int cg_find_unified_root(char *root, size_t len)
++int cg_find_unified_root(char *root, size_t len, bool *nsdelegate)
+ {
+ char buf[10 * PAGE_SIZE];
+- char *fs, *mount, *type;
++ char *fs, *mount, *type, *options;
+ const char delim[] = "\n\t ";
+
+ if (read_text("/proc/self/mounts", buf, sizeof(buf)) <= 0)
+@@ -211,12 +211,14 @@ int cg_find_unified_root(char *root, size_t len)
+ for (fs = strtok(buf, delim); fs; fs = strtok(NULL, delim)) {
+ mount = strtok(NULL, delim);
+ type = strtok(NULL, delim);
+- strtok(NULL, delim);
++ options = strtok(NULL, delim);
+ strtok(NULL, delim);
+ strtok(NULL, delim);
+
+ if (strcmp(type, "cgroup2") == 0) {
+ strncpy(root, mount, len);
++ if (nsdelegate)
++ *nsdelegate = !!strstr(options, "nsdelegate");
+ return 0;
+ }
+ }
+diff --git a/tools/testing/selftests/cgroup/cgroup_util.h b/tools/testing/selftests/cgroup/cgroup_util.h
+index 1df7f202214af..89e8519fb2719 100644
+--- a/tools/testing/selftests/cgroup/cgroup_util.h
++++ b/tools/testing/selftests/cgroup/cgroup_util.h
+@@ -21,7 +21,7 @@ static inline int values_close(long a, long b, int err)
+ return abs(a - b) <= (a + b) / 100 * err;
+ }
+
+-extern int cg_find_unified_root(char *root, size_t len);
++extern int cg_find_unified_root(char *root, size_t len, bool *nsdelegate);
+ extern char *cg_name(const char *root, const char *name);
+ extern char *cg_name_indexed(const char *root, const char *name, int index);
+ extern char *cg_control(const char *cgroup, const char *control);
+diff --git a/tools/testing/selftests/cgroup/test_core.c b/tools/testing/selftests/cgroup/test_core.c
+index 80aa6b2373b96..a5672a91d273c 100644
+--- a/tools/testing/selftests/cgroup/test_core.c
++++ b/tools/testing/selftests/cgroup/test_core.c
+@@ -18,6 +18,8 @@
+ #include "../kselftest.h"
+ #include "cgroup_util.h"
+
++static bool nsdelegate;
++
+ static int touch_anon(char *buf, size_t size)
+ {
+ int fd;
+@@ -775,6 +777,9 @@ static int test_cgcore_lesser_ns_open(const char *root)
+ pid_t pid;
+ int status;
+
++ if (!nsdelegate)
++ return KSFT_SKIP;
++
+ cg_test_a = cg_name(root, "cg_test_a");
+ cg_test_b = cg_name(root, "cg_test_b");
+
+@@ -862,7 +867,7 @@ int main(int argc, char *argv[])
+ char root[PATH_MAX];
+ int i, ret = EXIT_SUCCESS;
+
+- if (cg_find_unified_root(root, sizeof(root)))
++ if (cg_find_unified_root(root, sizeof(root), &nsdelegate))
+ ksft_exit_skip("cgroup v2 isn't mounted\n");
+
+ if (cg_read_strstr(root, "cgroup.subtree_control", "memory"))
+diff --git a/tools/testing/selftests/cgroup/test_cpu.c b/tools/testing/selftests/cgroup/test_cpu.c
+index 24020a2c68dcd..186bf96f6a284 100644
+--- a/tools/testing/selftests/cgroup/test_cpu.c
++++ b/tools/testing/selftests/cgroup/test_cpu.c
+@@ -700,7 +700,7 @@ int main(int argc, char *argv[])
+ char root[PATH_MAX];
+ int i, ret = EXIT_SUCCESS;
+
+- if (cg_find_unified_root(root, sizeof(root)))
++ if (cg_find_unified_root(root, sizeof(root), NULL))
+ ksft_exit_skip("cgroup v2 isn't mounted\n");
+
+ if (cg_read_strstr(root, "cgroup.subtree_control", "cpu"))
+diff --git a/tools/testing/selftests/cgroup/test_cpuset.c b/tools/testing/selftests/cgroup/test_cpuset.c
+index b061ed1e05b4d..4034d14ba69ac 100644
+--- a/tools/testing/selftests/cgroup/test_cpuset.c
++++ b/tools/testing/selftests/cgroup/test_cpuset.c
+@@ -249,7 +249,7 @@ int main(int argc, char *argv[])
+ char root[PATH_MAX];
+ int i, ret = EXIT_SUCCESS;
+
+- if (cg_find_unified_root(root, sizeof(root)))
++ if (cg_find_unified_root(root, sizeof(root), NULL))
+ ksft_exit_skip("cgroup v2 isn't mounted\n");
+
+ if (cg_read_strstr(root, "cgroup.subtree_control", "cpuset"))
+diff --git a/tools/testing/selftests/cgroup/test_freezer.c b/tools/testing/selftests/cgroup/test_freezer.c
+index 8845353aca53b..8730645d363a7 100644
+--- a/tools/testing/selftests/cgroup/test_freezer.c
++++ b/tools/testing/selftests/cgroup/test_freezer.c
+@@ -827,7 +827,7 @@ int main(int argc, char *argv[])
+ char root[PATH_MAX];
+ int i, ret = EXIT_SUCCESS;
+
+- if (cg_find_unified_root(root, sizeof(root)))
++ if (cg_find_unified_root(root, sizeof(root), NULL))
+ ksft_exit_skip("cgroup v2 isn't mounted\n");
+ for (i = 0; i < ARRAY_SIZE(tests); i++) {
+ switch (tests[i].fn(root)) {
+diff --git a/tools/testing/selftests/cgroup/test_hugetlb_memcg.c b/tools/testing/selftests/cgroup/test_hugetlb_memcg.c
+index f0fefeb4cc24c..856f9508ea562 100644
+--- a/tools/testing/selftests/cgroup/test_hugetlb_memcg.c
++++ b/tools/testing/selftests/cgroup/test_hugetlb_memcg.c
+@@ -214,7 +214,7 @@ int main(int argc, char **argv)
+ return ret;
+ }
+
+- if (cg_find_unified_root(root, sizeof(root)))
++ if (cg_find_unified_root(root, sizeof(root), NULL))
+ ksft_exit_skip("cgroup v2 isn't mounted\n");
+
+ switch (test_hugetlb_memcg(root)) {
+diff --git a/tools/testing/selftests/cgroup/test_kill.c b/tools/testing/selftests/cgroup/test_kill.c
+index 6153690319c9c..0e5bb6c7307a5 100644
+--- a/tools/testing/selftests/cgroup/test_kill.c
++++ b/tools/testing/selftests/cgroup/test_kill.c
+@@ -276,7 +276,7 @@ int main(int argc, char *argv[])
+ char root[PATH_MAX];
+ int i, ret = EXIT_SUCCESS;
+
+- if (cg_find_unified_root(root, sizeof(root)))
++ if (cg_find_unified_root(root, sizeof(root), NULL))
+ ksft_exit_skip("cgroup v2 isn't mounted\n");
+ for (i = 0; i < ARRAY_SIZE(tests); i++) {
+ switch (tests[i].fn(root)) {
+diff --git a/tools/testing/selftests/cgroup/test_kmem.c b/tools/testing/selftests/cgroup/test_kmem.c
+index c82f974b85c94..137506db03127 100644
+--- a/tools/testing/selftests/cgroup/test_kmem.c
++++ b/tools/testing/selftests/cgroup/test_kmem.c
+@@ -420,7 +420,7 @@ int main(int argc, char **argv)
+ char root[PATH_MAX];
+ int i, ret = EXIT_SUCCESS;
+
+- if (cg_find_unified_root(root, sizeof(root)))
++ if (cg_find_unified_root(root, sizeof(root), NULL))
+ ksft_exit_skip("cgroup v2 isn't mounted\n");
+
+ /*
+diff --git a/tools/testing/selftests/cgroup/test_memcontrol.c b/tools/testing/selftests/cgroup/test_memcontrol.c
+index c7c9572003a8c..b462416b38061 100644
+--- a/tools/testing/selftests/cgroup/test_memcontrol.c
++++ b/tools/testing/selftests/cgroup/test_memcontrol.c
+@@ -1314,7 +1314,7 @@ int main(int argc, char **argv)
+ char root[PATH_MAX];
+ int i, proc_status, ret = EXIT_SUCCESS;
+
+- if (cg_find_unified_root(root, sizeof(root)))
++ if (cg_find_unified_root(root, sizeof(root), NULL))
+ ksft_exit_skip("cgroup v2 isn't mounted\n");
+
+ /*
+diff --git a/tools/testing/selftests/cgroup/test_zswap.c b/tools/testing/selftests/cgroup/test_zswap.c
+index 47fdaa1464430..e1169d3e620f0 100644
+--- a/tools/testing/selftests/cgroup/test_zswap.c
++++ b/tools/testing/selftests/cgroup/test_zswap.c
+@@ -324,7 +324,7 @@ int main(int argc, char **argv)
+ char root[PATH_MAX];
+ int i, ret = EXIT_SUCCESS;
+
+- if (cg_find_unified_root(root, sizeof(root)))
++ if (cg_find_unified_root(root, sizeof(root), NULL))
+ ksft_exit_skip("cgroup v2 isn't mounted\n");
+
+ if (!zswap_configured())
+diff --git a/tools/testing/selftests/damon/_damon_sysfs.py b/tools/testing/selftests/damon/_damon_sysfs.py
+index e98cf4b6a4b76..f9fead3d0f018 100644
+--- a/tools/testing/selftests/damon/_damon_sysfs.py
++++ b/tools/testing/selftests/damon/_damon_sysfs.py
+@@ -241,6 +241,8 @@ class DamonCtx:
+ nr_schemes_file = os.path.join(
+ self.sysfs_dir(), 'schemes', 'nr_schemes')
+ content, err = read_file(nr_schemes_file)
++ if err is not None:
++ return err
+ if int(content) != len(self.schemes):
+ err = write_file(nr_schemes_file, '%d' % len(self.schemes))
+ if err != None:
+diff --git a/tools/testing/selftests/filesystems/binderfs/Makefile b/tools/testing/selftests/filesystems/binderfs/Makefile
+index c2f7cef919c04..eb4c3b4119348 100644
+--- a/tools/testing/selftests/filesystems/binderfs/Makefile
++++ b/tools/testing/selftests/filesystems/binderfs/Makefile
+@@ -3,6 +3,4 @@
+ CFLAGS += $(KHDR_INCLUDES) -pthread
+ TEST_GEN_PROGS := binderfs_test
+
+-binderfs_test: binderfs_test.c ../../kselftest.h ../../kselftest_harness.h
+-
+ include ../../lib.mk
+diff --git a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc
+index b9c21a81d2481..c0cdad4c400e8 100644
+--- a/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc
++++ b/tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc
+@@ -53,7 +53,7 @@ fi
+
+ echo > dynamic_events
+
+-if [ "$FIELDS" ] ; then
++if [ "$FIELDS" -a "$FPROBES" ] ; then
+ echo "t:tpevent ${TP2} obj_size=s->object_size" >> dynamic_events
+ echo "f:fpevent ${TP3}%return path=\$retval->name:string" >> dynamic_events
+ echo "t:tpevent2 ${TP4} p->se.group_node.next->prev" >> dynamic_events
+diff --git a/tools/testing/selftests/kcmp/kcmp_test.c b/tools/testing/selftests/kcmp/kcmp_test.c
+index 25110c7c0b3ed..d7a8e321bb16b 100644
+--- a/tools/testing/selftests/kcmp/kcmp_test.c
++++ b/tools/testing/selftests/kcmp/kcmp_test.c
+@@ -91,7 +91,7 @@ int main(int argc, char **argv)
+ ksft_print_header();
+ ksft_set_plan(3);
+
+- fd2 = open(kpath, O_RDWR, 0644);
++ fd2 = open(kpath, O_RDWR);
+ if (fd2 < 0) {
+ perror("Can't open file");
+ ksft_exit_fail();
+diff --git a/tools/testing/selftests/kvm/aarch64/vgic_init.c b/tools/testing/selftests/kvm/aarch64/vgic_init.c
+index eef816b80993f..ca917c71ff602 100644
+--- a/tools/testing/selftests/kvm/aarch64/vgic_init.c
++++ b/tools/testing/selftests/kvm/aarch64/vgic_init.c
+@@ -84,6 +84,18 @@ static struct vm_gic vm_gic_create_with_vcpus(uint32_t gic_dev_type,
+ return v;
+ }
+
++static struct vm_gic vm_gic_create_barebones(uint32_t gic_dev_type)
++{
++ struct vm_gic v;
++
++ v.gic_dev_type = gic_dev_type;
++ v.vm = vm_create_barebones();
++ v.gic_fd = kvm_create_device(v.vm, gic_dev_type);
++
++ return v;
++}
++
++
+ static void vm_gic_destroy(struct vm_gic *v)
+ {
+ close(v->gic_fd);
+@@ -357,6 +369,40 @@ static void test_vcpus_then_vgic(uint32_t gic_dev_type)
+ vm_gic_destroy(&v);
+ }
+
++#define KVM_VGIC_V2_ATTR(offset, cpu) \
++ (FIELD_PREP(KVM_DEV_ARM_VGIC_OFFSET_MASK, offset) | \
++ FIELD_PREP(KVM_DEV_ARM_VGIC_CPUID_MASK, cpu))
++
++#define GIC_CPU_CTRL 0x00
++
++static void test_v2_uaccess_cpuif_no_vcpus(void)
++{
++ struct vm_gic v;
++ u64 val = 0;
++ int ret;
++
++ v = vm_gic_create_barebones(KVM_DEV_TYPE_ARM_VGIC_V2);
++ subtest_dist_rdist(&v);
++
++ ret = __kvm_has_device_attr(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
++ KVM_VGIC_V2_ATTR(GIC_CPU_CTRL, 0));
++ TEST_ASSERT(ret && errno == EINVAL,
++ "accessed non-existent CPU interface, want errno: %i",
++ EINVAL);
++ ret = __kvm_device_attr_get(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
++ KVM_VGIC_V2_ATTR(GIC_CPU_CTRL, 0), &val);
++ TEST_ASSERT(ret && errno == EINVAL,
++ "accessed non-existent CPU interface, want errno: %i",
++ EINVAL);
++ ret = __kvm_device_attr_set(v.gic_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
++ KVM_VGIC_V2_ATTR(GIC_CPU_CTRL, 0), &val);
++ TEST_ASSERT(ret && errno == EINVAL,
++ "accessed non-existent CPU interface, want errno: %i",
++ EINVAL);
++
++ vm_gic_destroy(&v);
++}
++
+ static void test_v3_new_redist_regions(void)
+ {
+ struct kvm_vcpu *vcpus[NR_VCPUS];
+@@ -675,6 +721,9 @@ void run_tests(uint32_t gic_dev_type)
+ test_vcpus_then_vgic(gic_dev_type);
+ test_vgic_then_vcpus(gic_dev_type);
+
++ if (VGIC_DEV_IS_V2(gic_dev_type))
++ test_v2_uaccess_cpuif_no_vcpus();
++
+ if (VGIC_DEV_IS_V3(gic_dev_type)) {
+ test_v3_new_redist_regions();
+ test_v3_typer_accesses();
+diff --git a/tools/testing/selftests/lib.mk b/tools/testing/selftests/lib.mk
+index aa646e0661f36..a8f0442a36bca 100644
+--- a/tools/testing/selftests/lib.mk
++++ b/tools/testing/selftests/lib.mk
+@@ -7,6 +7,8 @@ else ifneq ($(filter -%,$(LLVM)),)
+ LLVM_SUFFIX := $(LLVM)
+ endif
+
++CLANG := $(LLVM_PREFIX)clang$(LLVM_SUFFIX)
++
+ CLANG_TARGET_FLAGS_arm := arm-linux-gnueabi
+ CLANG_TARGET_FLAGS_arm64 := aarch64-linux-gnu
+ CLANG_TARGET_FLAGS_hexagon := hexagon-linux-musl
+@@ -18,7 +20,13 @@ CLANG_TARGET_FLAGS_riscv := riscv64-linux-gnu
+ CLANG_TARGET_FLAGS_s390 := s390x-linux-gnu
+ CLANG_TARGET_FLAGS_x86 := x86_64-linux-gnu
+ CLANG_TARGET_FLAGS_x86_64 := x86_64-linux-gnu
+-CLANG_TARGET_FLAGS := $(CLANG_TARGET_FLAGS_$(ARCH))
++
++# Default to host architecture if ARCH is not explicitly given.
++ifeq ($(ARCH),)
++CLANG_TARGET_FLAGS := $(shell $(CLANG) -print-target-triple)
++else
++CLANG_TARGET_FLAGS := $(CLANG_TARGET_FLAGS_$(ARCH))
++endif
+
+ ifeq ($(CROSS_COMPILE),)
+ ifeq ($(CLANG_TARGET_FLAGS),)
+@@ -30,7 +38,7 @@ else
+ CLANG_FLAGS += --target=$(notdir $(CROSS_COMPILE:%-=%))
+ endif # CROSS_COMPILE
+
+-CC := $(LLVM_PREFIX)clang$(LLVM_SUFFIX) $(CLANG_FLAGS) -fintegrated-as
++CC := $(CLANG) $(CLANG_FLAGS) -fintegrated-as
+ else
+ CC := $(CROSS_COMPILE)gcc
+ endif # LLVM
+diff --git a/tools/testing/selftests/net/amt.sh b/tools/testing/selftests/net/amt.sh
+index 75528788cb95e..5175a42cbe8a2 100755
+--- a/tools/testing/selftests/net/amt.sh
++++ b/tools/testing/selftests/net/amt.sh
+@@ -210,8 +210,8 @@ check_features()
+
+ test_ipv4_forward()
+ {
+- RESULT4=$(ip netns exec "${LISTENER}" nc -w 1 -l -u 239.0.0.1 4000)
+- if [ "$RESULT4" == "172.17.0.2" ]; then
++ RESULT4=$(ip netns exec "${LISTENER}" timeout 15 socat - UDP4-LISTEN:4000,readbytes=128 || true)
++ if echo "$RESULT4" | grep -q "172.17.0.2"; then
+ printf "TEST: %-60s [ OK ]\n" "IPv4 amt multicast forwarding"
+ exit 0
+ else
+@@ -222,8 +222,8 @@ test_ipv4_forward()
+
+ test_ipv6_forward()
+ {
+- RESULT6=$(ip netns exec "${LISTENER}" nc -w 1 -l -u ff0e::5:6 6000)
+- if [ "$RESULT6" == "2001:db8:3::2" ]; then
++ RESULT6=$(ip netns exec "${LISTENER}" timeout 15 socat - UDP6-LISTEN:6000,readbytes=128 || true)
++ if echo "$RESULT6" | grep -q "2001:db8:3::2"; then
+ printf "TEST: %-60s [ OK ]\n" "IPv6 amt multicast forwarding"
+ exit 0
+ else
+@@ -236,14 +236,14 @@ send_mcast4()
+ {
+ sleep 2
+ ip netns exec "${SOURCE}" bash -c \
+- 'echo 172.17.0.2 | nc -w 1 -u 239.0.0.1 4000' &
++ 'printf "%s %128s" 172.17.0.2 | nc -w 1 -u 239.0.0.1 4000' &
+ }
+
+ send_mcast6()
+ {
+ sleep 2
+ ip netns exec "${SOURCE}" bash -c \
+- 'echo 2001:db8:3::2 | nc -w 1 -u ff0e::5:6 6000' &
++ 'printf "%s %128s" 2001:db8:3::2 | nc -w 1 -u ff0e::5:6 6000' &
+ }
+
+ check_features
+diff --git a/tools/testing/selftests/net/config b/tools/testing/selftests/net/config
+index 5e4390cac17ed..04de7a6ba6f31 100644
+--- a/tools/testing/selftests/net/config
++++ b/tools/testing/selftests/net/config
+@@ -30,6 +30,7 @@ CONFIG_IP_GRE=m
+ CONFIG_NETFILTER=y
+ CONFIG_NETFILTER_ADVANCED=y
+ CONFIG_NF_CONNTRACK=m
++CONFIG_IPV6_MROUTE=y
+ CONFIG_IPV6_SIT=y
+ CONFIG_IP_DCCP=m
+ CONFIG_NF_NAT=m
+diff --git a/tools/testing/selftests/net/forwarding/bridge_igmp.sh b/tools/testing/selftests/net/forwarding/bridge_igmp.sh
+index 2aa66d2a1702b..e6a3e04fd83f3 100755
+--- a/tools/testing/selftests/net/forwarding/bridge_igmp.sh
++++ b/tools/testing/selftests/net/forwarding/bridge_igmp.sh
+@@ -478,10 +478,10 @@ v3exc_timeout_test()
+ RET=0
+ local X=("192.0.2.20" "192.0.2.30")
+
+- # GMI should be 3 seconds
++ # GMI should be 5 seconds
+ ip link set dev br0 type bridge mcast_query_interval 100 \
+ mcast_query_response_interval 100 \
+- mcast_membership_interval 300
++ mcast_membership_interval 500
+
+ v3exclude_prepare $h1 $ALL_MAC $ALL_GROUP
+ ip link set dev br0 type bridge mcast_query_interval 500 \
+@@ -489,7 +489,7 @@ v3exc_timeout_test()
+ mcast_membership_interval 1500
+
+ $MZ $h1 -c 1 -b $ALL_MAC -B $ALL_GROUP -t ip "proto=2,p=$MZPKT_ALLOW2" -q
+- sleep 3
++ sleep 5
+ bridge -j -d -s mdb show dev br0 \
+ | jq -e ".[].mdb[] | \
+ select(.grp == \"$TEST_GROUP\" and \
+diff --git a/tools/testing/selftests/net/forwarding/bridge_mld.sh b/tools/testing/selftests/net/forwarding/bridge_mld.sh
+index e2b9ff773c6b6..f84ab2e657547 100755
+--- a/tools/testing/selftests/net/forwarding/bridge_mld.sh
++++ b/tools/testing/selftests/net/forwarding/bridge_mld.sh
+@@ -478,10 +478,10 @@ mldv2exc_timeout_test()
+ RET=0
+ local X=("2001:db8:1::20" "2001:db8:1::30")
+
+- # GMI should be 3 seconds
++ # GMI should be 5 seconds
+ ip link set dev br0 type bridge mcast_query_interval 100 \
+ mcast_query_response_interval 100 \
+- mcast_membership_interval 300
++ mcast_membership_interval 500
+
+ mldv2exclude_prepare $h1
+ ip link set dev br0 type bridge mcast_query_interval 500 \
+@@ -489,7 +489,7 @@ mldv2exc_timeout_test()
+ mcast_membership_interval 1500
+
+ $MZ $h1 -c 1 $MZPKT_ALLOW2 -q
+- sleep 3
++ sleep 5
+ bridge -j -d -s mdb show dev br0 \
+ | jq -e ".[].mdb[] | \
+ select(.grp == \"$TEST_GROUP\" and \
+diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/net/lib.sh
+index f9fe182dfbd44..56a9454b7ba35 100644
+--- a/tools/testing/selftests/net/lib.sh
++++ b/tools/testing/selftests/net/lib.sh
+@@ -73,15 +73,17 @@ setup_ns()
+ local ns=""
+ local ns_name=""
+ local ns_list=""
++ local ns_exist=
+ for ns_name in "$@"; do
+ # Some test may setup/remove same netns multi times
+ if unset ${ns_name} 2> /dev/null; then
+ ns="${ns_name,,}-$(mktemp -u XXXXXX)"
+ eval readonly ${ns_name}="$ns"
++ ns_exist=false
+ else
+ eval ns='$'${ns_name}
+ cleanup_ns "$ns"
+-
++ ns_exist=true
+ fi
+
+ if ! ip netns add "$ns"; then
+@@ -90,7 +92,7 @@ setup_ns()
+ return $ksft_skip
+ fi
+ ip -n "$ns" link set lo up
+- ns_list="$ns_list $ns"
++ ! $ns_exist && ns_list="$ns_list $ns"
+ done
+ NS_LIST="$NS_LIST $ns_list"
+ }
+diff --git a/tools/testing/selftests/resctrl/Makefile b/tools/testing/selftests/resctrl/Makefile
+index 2deac2031de9e..021863f86053a 100644
+--- a/tools/testing/selftests/resctrl/Makefile
++++ b/tools/testing/selftests/resctrl/Makefile
+@@ -5,6 +5,8 @@ CFLAGS += $(KHDR_INCLUDES)
+
+ TEST_GEN_PROGS := resctrl_tests
+
++LOCAL_HDRS += $(wildcard *.h)
++
+ include ../lib.mk
+
+-$(OUTPUT)/resctrl_tests: $(wildcard *.[ch])
++$(OUTPUT)/resctrl_tests: $(wildcard *.c)
+diff --git a/tools/testing/selftests/syscall_user_dispatch/sud_test.c b/tools/testing/selftests/syscall_user_dispatch/sud_test.c
+index b5d592d4099e8..d975a67673299 100644
+--- a/tools/testing/selftests/syscall_user_dispatch/sud_test.c
++++ b/tools/testing/selftests/syscall_user_dispatch/sud_test.c
+@@ -158,6 +158,20 @@ static void handle_sigsys(int sig, siginfo_t *info, void *ucontext)
+
+ /* In preparation for sigreturn. */
+ SYSCALL_DISPATCH_OFF(glob_sel);
++
++ /*
++ * The tests for argument handling assume that `syscall(x) == x`. This
++ * is a NOP on x86 because the syscall number is passed in %rax, which
++ * happens to also be the function ABI return register. Other
++ * architectures may need to swizzle the arguments around.
++ */
++#if defined(__riscv)
++/* REG_A7 is not defined in libc headers */
++# define REG_A7 (REG_A0 + 7)
++
++ ((ucontext_t *)ucontext)->uc_mcontext.__gregs[REG_A0] =
++ ((ucontext_t *)ucontext)->uc_mcontext.__gregs[REG_A7];
++#endif
+ }
+
+ TEST(dispatch_and_return)
+diff --git a/tools/tracing/latency/latency-collector.c b/tools/tracing/latency/latency-collector.c
+index 0fd9c747d396d..cf263fe9deaf4 100644
+--- a/tools/tracing/latency/latency-collector.c
++++ b/tools/tracing/latency/latency-collector.c
+@@ -935,12 +935,12 @@ static void show_available(void)
+ }
+
+ if (!tracers) {
+- warnx(no_tracer_msg);
++ warnx("%s", no_tracer_msg);
+ return;
+ }
+
+ if (!found) {
+- warnx(no_latency_tr_msg);
++ warnx("%s", no_latency_tr_msg);
+ tracefs_list_free(tracers);
+ return;
+ }
+@@ -983,7 +983,7 @@ static const char *find_default_tracer(void)
+ for (i = 0; relevant_tracers[i]; i++) {
+ valid = tracer_valid(relevant_tracers[i], ¬racer);
+ if (notracer)
+- errx(EXIT_FAILURE, no_tracer_msg);
++ errx(EXIT_FAILURE, "%s", no_tracer_msg);
+ if (valid)
+ return relevant_tracers[i];
+ }
+@@ -1878,7 +1878,7 @@ static void scan_arguments(int argc, char *argv[])
+ }
+ valid = tracer_valid(current_tracer, ¬racer);
+ if (notracer)
+- errx(EXIT_FAILURE, no_tracer_msg);
++ errx(EXIT_FAILURE, "%s", no_tracer_msg);
+ if (!valid)
+ errx(EXIT_FAILURE,
+ "The tracer %s is not supported by your kernel!\n", current_tracer);
^ permalink raw reply related [flat|nested] 25+ messages in thread
end of thread, other threads:[~2024-05-30 11:58 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-02 15:14 [gentoo-commits] proj/linux-patches:6.8 commit in: / Mike Pagano
-- strict thread matches above, loose matches on Subject: below --
2024-05-30 11:58 Mike Pagano
2024-05-25 15:18 Mike Pagano
2024-05-17 11:34 Mike Pagano
2024-05-05 18:02 Mike Pagano
2024-05-05 18:01 Mike Pagano
2024-04-28 22:04 Mike Pagano
2024-04-27 22:03 Mike Pagano
2024-04-27 17:04 Mike Pagano
2024-04-21 22:25 Mike Pagano
2024-04-18 6:31 Alice Ferrazzi
2024-04-18 5:31 Alice Ferrazzi
2024-04-18 3:04 Alice Ferrazzi
2024-04-13 13:05 Mike Pagano
2024-04-11 14:47 Mike Pagano
2024-04-10 15:08 Mike Pagano
2024-04-04 19:22 Mike Pagano
2024-04-04 19:05 Mike Pagano
2024-04-03 14:20 Mike Pagano
2024-03-27 11:46 Mike Pagano
2024-03-27 11:29 Mike Pagano
2024-03-27 11:22 Mike Pagano
2024-03-15 21:58 Mike Pagano
2024-03-11 21:02 Mike Pagano
2024-03-11 20:59 Mike Pagano
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox