From: "Mike Pagano" <mpagano@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/linux-patches:6.0 commit in: /
Date: Thu, 10 Nov 2022 18:10:02 +0000 (UTC) [thread overview]
Message-ID: <1668103787.8b3e419be10860f5c8692b5fb9acaaee189b3279.mpagano@gentoo> (raw)
commit: 8b3e419be10860f5c8692b5fb9acaaee189b3279
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Thu Nov 10 18:09:47 2022 +0000
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Thu Nov 10 18:09:47 2022 +0000
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=8b3e419b
Linux patch 6.0.8
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
0000_README | 4 +
1007_linux-6.0.8.patch | 7683 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 7687 insertions(+)
diff --git a/0000_README b/0000_README
index 004afc57..52ac8549 100644
--- a/0000_README
+++ b/0000_README
@@ -71,6 +71,10 @@ Patch: 1006_linux-6.0.7.patch
From: http://www.kernel.org
Desc: Linux 6.0.7
+Patch: 1007_linux-6.0.8.patch
+From: http://www.kernel.org
+Desc: Linux 6.0.8
+
Patch: 1500_XATTR_USER_PREFIX.patch
From: https://bugs.gentoo.org/show_bug.cgi?id=470644
Desc: Support for namespace user.pax.* on tmpfs.
diff --git a/1007_linux-6.0.8.patch b/1007_linux-6.0.8.patch
new file mode 100644
index 00000000..c970b363
--- /dev/null
+++ b/1007_linux-6.0.8.patch
@@ -0,0 +1,7683 @@
+diff --git a/Documentation/process/howto.rst b/Documentation/process/howto.rst
+index cd6997a9d2032..8fc5398c732bc 100644
+--- a/Documentation/process/howto.rst
++++ b/Documentation/process/howto.rst
+@@ -36,7 +36,7 @@ experience, the following books are good for, if anything, reference:
+ - "C: A Reference Manual" by Harbison and Steele [Prentice Hall]
+
+ The kernel is written using GNU C and the GNU toolchain. While it
+-adheres to the ISO C89 standard, it uses a number of extensions that are
++adheres to the ISO C11 standard, it uses a number of extensions that are
+ not featured in the standard. The kernel is a freestanding C
+ environment, with no reliance on the standard C library, so some
+ portions of the C standard are not supported. Arbitrary long long
+diff --git a/Documentation/trace/histogram.rst b/Documentation/trace/histogram.rst
+index 859fd1b76c638..69354e1e7b255 100644
+--- a/Documentation/trace/histogram.rst
++++ b/Documentation/trace/histogram.rst
+@@ -39,7 +39,7 @@ Documentation written by Tom Zanussi
+ will use the event's kernel stacktrace as the key. The keywords
+ 'keys' or 'key' can be used to specify keys, and the keywords
+ 'values', 'vals', or 'val' can be used to specify values. Compound
+- keys consisting of up to two fields can be specified by the 'keys'
++ keys consisting of up to three fields can be specified by the 'keys'
+ keyword. Hashing a compound key produces a unique entry in the
+ table for each unique combination of component keys, and can be
+ useful for providing more fine-grained summaries of event data.
+diff --git a/Documentation/translations/it_IT/process/howto.rst b/Documentation/translations/it_IT/process/howto.rst
+index 16ad5622d5495..67b84f015da8a 100644
+--- a/Documentation/translations/it_IT/process/howto.rst
++++ b/Documentation/translations/it_IT/process/howto.rst
+@@ -44,7 +44,7 @@ altro, utili riferimenti:
+ - "C: A Reference Manual" di Harbison and Steele [Prentice Hall]
+
+ Il kernel è stato scritto usando GNU C e la toolchain GNU.
+-Sebbene si attenga allo standard ISO C89, esso utilizza una serie di
++Sebbene si attenga allo standard ISO C11, esso utilizza una serie di
+ estensioni che non sono previste in questo standard. Il kernel è un
+ ambiente C indipendente, che non ha alcuna dipendenza dalle librerie
+ C standard, così alcune parti del C standard non sono supportate.
+diff --git a/Documentation/translations/ja_JP/howto.rst b/Documentation/translations/ja_JP/howto.rst
+index 649e2ff2a407e..e2e946a4298ad 100644
+--- a/Documentation/translations/ja_JP/howto.rst
++++ b/Documentation/translations/ja_JP/howto.rst
+@@ -65,7 +65,7 @@ Linux カーネル開発のやり方
+ - 『新・詳説 C 言語 H&S リファレンス』 (サミュエル P ハービソン/ガイ L スティール共著 斉藤 信男監訳)[ソフトバンク]
+
+ カーネルは GNU C と GNU ツールチェインを使って書かれています。カーネル
+-は ISO C89 仕様に準拠して書く一方で、標準には無い言語拡張を多く使って
++は ISO C11 仕様に準拠して書く一方で、標準には無い言語拡張を多く使って
+ います。カーネルは標準 C ライブラリに依存しない、C 言語非依存環境です。
+ そのため、C の標準の中で使えないものもあります。特に任意の long long
+ の除算や浮動小数点は使えません。カーネルがツールチェインや C 言語拡張
+diff --git a/Documentation/translations/ko_KR/howto.rst b/Documentation/translations/ko_KR/howto.rst
+index e43970584ca4d..2a7ab4257e44c 100644
+--- a/Documentation/translations/ko_KR/howto.rst
++++ b/Documentation/translations/ko_KR/howto.rst
+@@ -62,7 +62,7 @@ Documentation/process/howto.rst
+ - "Practical C Programming" by Steve Oualline [O'Reilly]
+ - "C: A Reference Manual" by Harbison and Steele [Prentice Hall]
+
+-커널은 GNU C와 GNU 툴체인을 사용하여 작성되었다. 이 툴들은 ISO C89 표준을
++커널은 GNU C와 GNU 툴체인을 사용하여 작성되었다. 이 툴들은 ISO C11 표준을
+ 따르는 반면 표준에 있지 않은 많은 확장기능도 가지고 있다. 커널은 표준 C
+ 라이브러리와는 관계없이 freestanding C 환경이어서 C 표준의 일부는
+ 지원되지 않는다. 임의의 long long 나누기나 floating point는 지원되지 않는다.
+diff --git a/Documentation/translations/zh_CN/process/howto.rst b/Documentation/translations/zh_CN/process/howto.rst
+index 1455190dc087a..e7e4bb000b8a5 100644
+--- a/Documentation/translations/zh_CN/process/howto.rst
++++ b/Documentation/translations/zh_CN/process/howto.rst
+@@ -45,7 +45,7 @@ Linux内核大部分是由C语言写成的,一些体系结构相关的代码
+ - "C: A Reference Manual" by Harbison and Steele [Prentice Hall]
+ 《C语言参考手册(原书第5版)》(邱仲潘 等译)[机械工业出版社]
+
+-Linux内核使用GNU C和GNU工具链开发。虽然它遵循ISO C89标准,但也用到了一些
++Linux内核使用GNU C和GNU工具链开发。虽然它遵循ISO C11标准,但也用到了一些
+ 标准中没有定义的扩展。内核是自给自足的C环境,不依赖于标准C库的支持,所以
+ 并不支持C标准中的部分定义。比如long long类型的大数除法和浮点运算就不允许
+ 使用。有时候确实很难弄清楚内核对工具链的要求和它所使用的扩展,不幸的是目
+diff --git a/Documentation/translations/zh_TW/process/howto.rst b/Documentation/translations/zh_TW/process/howto.rst
+index 68ae4411285b8..e335789d7e26c 100644
+--- a/Documentation/translations/zh_TW/process/howto.rst
++++ b/Documentation/translations/zh_TW/process/howto.rst
+@@ -48,7 +48,7 @@ Linux內核大部分是由C語言寫成的,一些體系結構相關的代碼
+ - "C: A Reference Manual" by Harbison and Steele [Prentice Hall]
+ 《C語言參考手冊(原書第5版)》(邱仲潘 等譯)[機械工業出版社]
+
+-Linux內核使用GNU C和GNU工具鏈開發。雖然它遵循ISO C89標準,但也用到了一些
++Linux內核使用GNU C和GNU工具鏈開發。雖然它遵循ISO C11標準,但也用到了一些
+ 標準中沒有定義的擴展。內核是自給自足的C環境,不依賴於標準C庫的支持,所以
+ 並不支持C標準中的部分定義。比如long long類型的大數除法和浮點運算就不允許
+ 使用。有時候確實很難弄清楚內核對工具鏈的要求和它所使用的擴展,不幸的是目
+diff --git a/Makefile b/Makefile
+index c2144a4bb2efe..bcb76d4fdbc11 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 6
+ PATCHLEVEL = 0
+-SUBLEVEL = 7
++SUBLEVEL = 8
+ EXTRAVERSION =
+ NAME = Hurr durr I'ma ninja sloth
+
+diff --git a/arch/arm/boot/dts/imx6q-yapp4-crux.dts b/arch/arm/boot/dts/imx6q-yapp4-crux.dts
+index 15f4824a5142a..bddf3822ebf73 100644
+--- a/arch/arm/boot/dts/imx6q-yapp4-crux.dts
++++ b/arch/arm/boot/dts/imx6q-yapp4-crux.dts
+@@ -33,6 +33,10 @@
+ status = "okay";
+ };
+
++®_pu {
++ regulator-always-on;
++};
++
+ ®_usb_h1_vbus {
+ status = "okay";
+ };
+diff --git a/arch/arm/boot/dts/imx6qdl-gw5910.dtsi b/arch/arm/boot/dts/imx6qdl-gw5910.dtsi
+index 68e5ab2e27e22..6bb4855d13ce5 100644
+--- a/arch/arm/boot/dts/imx6qdl-gw5910.dtsi
++++ b/arch/arm/boot/dts/imx6qdl-gw5910.dtsi
+@@ -29,7 +29,7 @@
+
+ user-pb {
+ label = "user_pb";
+- gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
++ gpios = <&gsc_gpio 2 GPIO_ACTIVE_LOW>;
+ linux,code = <BTN_0>;
+ };
+
+diff --git a/arch/arm/boot/dts/imx6qdl-gw5913.dtsi b/arch/arm/boot/dts/imx6qdl-gw5913.dtsi
+index 8e23cec7149e5..696427b487f01 100644
+--- a/arch/arm/boot/dts/imx6qdl-gw5913.dtsi
++++ b/arch/arm/boot/dts/imx6qdl-gw5913.dtsi
+@@ -26,7 +26,7 @@
+
+ user-pb {
+ label = "user_pb";
+- gpios = <&gsc_gpio 0 GPIO_ACTIVE_LOW>;
++ gpios = <&gsc_gpio 2 GPIO_ACTIVE_LOW>;
+ linux,code = <BTN_0>;
+ };
+
+diff --git a/arch/arm/boot/dts/imx6qp-yapp4-crux-plus.dts b/arch/arm/boot/dts/imx6qp-yapp4-crux-plus.dts
+index cea165f2161a3..afaf4a6759d4b 100644
+--- a/arch/arm/boot/dts/imx6qp-yapp4-crux-plus.dts
++++ b/arch/arm/boot/dts/imx6qp-yapp4-crux-plus.dts
+@@ -33,6 +33,10 @@
+ status = "okay";
+ };
+
++®_pu {
++ regulator-always-on;
++};
++
+ ®_usb_h1_vbus {
+ status = "okay";
+ };
+diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi
+index fbaa0ce464271..8f1bb78fc1e48 100644
+--- a/arch/arm/boot/dts/ste-href.dtsi
++++ b/arch/arm/boot/dts/ste-href.dtsi
+@@ -24,6 +24,14 @@
+ polling-delay = <0>;
+ polling-delay-passive = <0>;
+ thermal-sensors = <&bat_therm>;
++
++ trips {
++ battery-crit-hi {
++ temperature = <70000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts
+index 1c9094f248939..e2f0cdacba7d1 100644
+--- a/arch/arm/boot/dts/ste-snowball.dts
++++ b/arch/arm/boot/dts/ste-snowball.dts
+@@ -28,6 +28,14 @@
+ polling-delay = <0>;
+ polling-delay-passive = <0>;
+ thermal-sensors = <&bat_therm>;
++
++ trips {
++ battery-crit-hi {
++ temperature = <70000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts b/arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts
+index d6940e0afa863..27a3ab7e25e13 100644
+--- a/arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts
++++ b/arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts
+@@ -44,6 +44,14 @@
+ polling-delay = <0>;
+ polling-delay-passive = <0>;
+ thermal-sensors = <&bat_therm>;
++
++ trips {
++ battery-crit-hi {
++ temperature = <70000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/ste-ux500-samsung-codina.dts b/arch/arm/boot/dts/ste-ux500-samsung-codina.dts
+index 5f41256d7f4b4..b88f0c07873dd 100644
+--- a/arch/arm/boot/dts/ste-ux500-samsung-codina.dts
++++ b/arch/arm/boot/dts/ste-ux500-samsung-codina.dts
+@@ -57,6 +57,14 @@
+ polling-delay = <0>;
+ polling-delay-passive = <0>;
+ thermal-sensors = <&bat_therm>;
++
++ trips {
++ battery-crit-hi {
++ temperature = <70000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts b/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts
+index 806da3fc33cd7..7231bc7452000 100644
+--- a/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts
++++ b/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts
+@@ -30,6 +30,14 @@
+ polling-delay = <0>;
+ polling-delay-passive = <0>;
+ thermal-sensors = <&bat_therm>;
++
++ trips {
++ battery-crit-hi {
++ temperature = <70000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/ste-ux500-samsung-golden.dts b/arch/arm/boot/dts/ste-ux500-samsung-golden.dts
+index b0dce91aff4be..9604695edf530 100644
+--- a/arch/arm/boot/dts/ste-ux500-samsung-golden.dts
++++ b/arch/arm/boot/dts/ste-ux500-samsung-golden.dts
+@@ -35,6 +35,14 @@
+ polling-delay = <0>;
+ polling-delay-passive = <0>;
+ thermal-sensors = <&bat_therm>;
++
++ trips {
++ battery-crit-hi {
++ temperature = <70000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/ste-ux500-samsung-janice.dts b/arch/arm/boot/dts/ste-ux500-samsung-janice.dts
+index ed5c79c3d04b0..69387e8754a95 100644
+--- a/arch/arm/boot/dts/ste-ux500-samsung-janice.dts
++++ b/arch/arm/boot/dts/ste-ux500-samsung-janice.dts
+@@ -30,6 +30,14 @@
+ polling-delay = <0>;
+ polling-delay-passive = <0>;
+ thermal-sensors = <&bat_therm>;
++
++ trips {
++ battery-crit-hi {
++ temperature = <70000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts b/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts
+index c57676faf181b..167846df31045 100644
+--- a/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts
++++ b/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts
+@@ -34,6 +34,14 @@
+ polling-delay = <0>;
+ polling-delay-passive = <0>;
+ thermal-sensors = <&bat_therm>;
++
++ trips {
++ battery-crit-hi {
++ temperature = <70000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
+ };
+ };
+
+diff --git a/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts b/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts
+index 81b341a5ae451..93e5f5ed888d1 100644
+--- a/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts
++++ b/arch/arm/boot/dts/ste-ux500-samsung-skomer.dts
+@@ -30,6 +30,14 @@
+ polling-delay = <0>;
+ polling-delay-passive = <0>;
+ thermal-sensors = <&bat_therm>;
++
++ trips {
++ battery-crit-hi {
++ temperature = <70000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
+ };
+ };
+
+diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi
+index 2f27619d8abd5..8b4d280b1e7e7 100644
+--- a/arch/arm64/boot/dts/arm/juno-base.dtsi
++++ b/arch/arm64/boot/dts/arm/juno-base.dtsi
+@@ -751,12 +751,26 @@
+ polling-delay = <1000>;
+ polling-delay-passive = <100>;
+ thermal-sensors = <&scpi_sensors0 0>;
++ trips {
++ pmic_crit0: trip0 {
++ temperature = <90000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
+ };
+
+ soc {
+ polling-delay = <1000>;
+ polling-delay-passive = <100>;
+ thermal-sensors = <&scpi_sensors0 3>;
++ trips {
++ soc_crit0: trip0 {
++ temperature = <80000>;
++ hysteresis = <2000>;
++ type = "critical";
++ };
++ };
+ };
+
+ big_cluster_thermal_zone: big-cluster {
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+index 421d879013d7f..260d045dbd9a8 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
+@@ -779,6 +779,9 @@
+ little-endian;
+ #address-cells = <1>;
+ #size-cells = <0>;
++ clock-frequency = <2500000>;
++ clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
++ QORIQ_CLK_PLL_DIV(1)>;
+ status = "disabled";
+ };
+
+@@ -788,6 +791,9 @@
+ little-endian;
+ #address-cells = <1>;
+ #size-cells = <0>;
++ clock-frequency = <2500000>;
++ clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
++ QORIQ_CLK_PLL_DIV(1)>;
+ status = "disabled";
+ };
+
+diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
+index d76f1c42f3fa5..7bb33933c2cb2 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
+@@ -533,6 +533,9 @@
+ little-endian;
+ #address-cells = <1>;
+ #size-cells = <0>;
++ clock-frequency = <2500000>;
++ clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
++ QORIQ_CLK_PLL_DIV(2)>;
+ status = "disabled";
+ };
+
+@@ -542,6 +545,9 @@
+ little-endian;
+ #address-cells = <1>;
+ #size-cells = <0>;
++ clock-frequency = <2500000>;
++ clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
++ QORIQ_CLK_PLL_DIV(2)>;
+ status = "disabled";
+ };
+
+diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
+index 6680fb2a6dc92..8c76d86cb7566 100644
+--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
++++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
+@@ -1385,6 +1385,9 @@
+ #address-cells = <1>;
+ #size-cells = <0>;
+ little-endian;
++ clock-frequency = <2500000>;
++ clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
++ QORIQ_CLK_PLL_DIV(2)>;
+ status = "disabled";
+ };
+
+@@ -1395,6 +1398,9 @@
+ little-endian;
+ #address-cells = <1>;
+ #size-cells = <0>;
++ clock-frequency = <2500000>;
++ clocks = <&clockgen QORIQ_CLK_PLATFORM_PLL
++ QORIQ_CLK_PLL_DIV(2)>;
+ status = "disabled";
+ };
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
+index 82a1c44883786..10370d1a6c6de 100644
+--- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
+@@ -38,9 +38,9 @@ conn_subsys: bus@5b000000 {
+ interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x5b010000 0x10000>;
+ clocks = <&sdhc0_lpcg IMX_LPCG_CLK_4>,
+- <&sdhc0_lpcg IMX_LPCG_CLK_5>,
+- <&sdhc0_lpcg IMX_LPCG_CLK_0>;
+- clock-names = "ipg", "per", "ahb";
++ <&sdhc0_lpcg IMX_LPCG_CLK_0>,
++ <&sdhc0_lpcg IMX_LPCG_CLK_5>;
++ clock-names = "ipg", "ahb", "per";
+ power-domains = <&pd IMX_SC_R_SDHC_0>;
+ status = "disabled";
+ };
+@@ -49,9 +49,9 @@ conn_subsys: bus@5b000000 {
+ interrupts = <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x5b020000 0x10000>;
+ clocks = <&sdhc1_lpcg IMX_LPCG_CLK_4>,
+- <&sdhc1_lpcg IMX_LPCG_CLK_5>,
+- <&sdhc1_lpcg IMX_LPCG_CLK_0>;
+- clock-names = "ipg", "per", "ahb";
++ <&sdhc1_lpcg IMX_LPCG_CLK_0>,
++ <&sdhc1_lpcg IMX_LPCG_CLK_5>;
++ clock-names = "ipg", "ahb", "per";
+ power-domains = <&pd IMX_SC_R_SDHC_1>;
+ fsl,tuning-start-tap = <20>;
+ fsl,tuning-step = <2>;
+@@ -62,9 +62,9 @@ conn_subsys: bus@5b000000 {
+ interrupts = <GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x5b030000 0x10000>;
+ clocks = <&sdhc2_lpcg IMX_LPCG_CLK_4>,
+- <&sdhc2_lpcg IMX_LPCG_CLK_5>,
+- <&sdhc2_lpcg IMX_LPCG_CLK_0>;
+- clock-names = "ipg", "per", "ahb";
++ <&sdhc2_lpcg IMX_LPCG_CLK_0>,
++ <&sdhc2_lpcg IMX_LPCG_CLK_5>;
++ clock-names = "ipg", "ahb", "per";
+ power-domains = <&pd IMX_SC_R_SDHC_2>;
+ status = "disabled";
+ };
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm-mx8menlo.dts b/arch/arm64/boot/dts/freescale/imx8mm-mx8menlo.dts
+index 32f6f2f50c10c..43e89859c0445 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm-mx8menlo.dts
++++ b/arch/arm64/boot/dts/freescale/imx8mm-mx8menlo.dts
+@@ -250,21 +250,21 @@
+ /* SODIMM 96 */
+ MX8MM_IOMUXC_SAI1_RXD2_GPIO4_IO4 0x1c4
+ /* CPLD_D[7] */
+- MX8MM_IOMUXC_SAI1_RXD3_GPIO4_IO5 0x1c4
++ MX8MM_IOMUXC_SAI1_RXD3_GPIO4_IO5 0x184
+ /* CPLD_D[6] */
+- MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x1c4
++ MX8MM_IOMUXC_SAI1_RXFS_GPIO4_IO0 0x184
+ /* CPLD_D[5] */
+- MX8MM_IOMUXC_SAI1_TXC_GPIO4_IO11 0x1c4
++ MX8MM_IOMUXC_SAI1_TXC_GPIO4_IO11 0x184
+ /* CPLD_D[4] */
+- MX8MM_IOMUXC_SAI1_TXD0_GPIO4_IO12 0x1c4
++ MX8MM_IOMUXC_SAI1_TXD0_GPIO4_IO12 0x184
+ /* CPLD_D[3] */
+- MX8MM_IOMUXC_SAI1_TXD1_GPIO4_IO13 0x1c4
++ MX8MM_IOMUXC_SAI1_TXD1_GPIO4_IO13 0x184
+ /* CPLD_D[2] */
+- MX8MM_IOMUXC_SAI1_TXD2_GPIO4_IO14 0x1c4
++ MX8MM_IOMUXC_SAI1_TXD2_GPIO4_IO14 0x184
+ /* CPLD_D[1] */
+- MX8MM_IOMUXC_SAI1_TXD3_GPIO4_IO15 0x1c4
++ MX8MM_IOMUXC_SAI1_TXD3_GPIO4_IO15 0x184
+ /* CPLD_D[0] */
+- MX8MM_IOMUXC_SAI1_TXD4_GPIO4_IO16 0x1c4
++ MX8MM_IOMUXC_SAI1_TXD4_GPIO4_IO16 0x184
+ /* KBD_intK */
+ MX8MM_IOMUXC_SAI2_MCLK_GPIO4_IO27 0x1c4
+ /* DISP_reset */
+diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+index afb90f59c83c5..dabd94dc30c4b 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+@@ -276,6 +276,7 @@
+ assigned-clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_100M>;
+ clock-names = "main_clk";
++ power-domains = <&pgc_otg1>;
+ };
+
+ usbphynop2: usbphynop2 {
+@@ -285,6 +286,7 @@
+ assigned-clocks = <&clk IMX8MM_CLK_USB_PHY_REF>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_100M>;
+ clock-names = "main_clk";
++ power-domains = <&pgc_otg2>;
+ };
+
+ soc: soc@0 {
+@@ -674,13 +676,11 @@
+ pgc_otg1: power-domain@2 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MM_POWER_DOMAIN_OTG1>;
+- power-domains = <&pgc_hsiomix>;
+ };
+
+ pgc_otg2: power-domain@3 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MM_POWER_DOMAIN_OTG2>;
+- power-domains = <&pgc_hsiomix>;
+ };
+
+ pgc_gpumix: power-domain@4 {
+@@ -1186,7 +1186,7 @@
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
+ phys = <&usbphynop1>;
+ fsl,usbmisc = <&usbmisc1 0>;
+- power-domains = <&pgc_otg1>;
++ power-domains = <&pgc_hsiomix>;
+ status = "disabled";
+ };
+
+@@ -1206,7 +1206,7 @@
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_500M>;
+ phys = <&usbphynop2>;
+ fsl,usbmisc = <&usbmisc2 0>;
+- power-domains = <&pgc_otg2>;
++ power-domains = <&pgc_hsiomix>;
+ status = "disabled";
+ };
+
+diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+index cb2836bfbd95c..ad0b99adf6911 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+@@ -662,7 +662,6 @@
+ pgc_otg1: power-domain@1 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MN_POWER_DOMAIN_OTG1>;
+- power-domains = <&pgc_hsiomix>;
+ };
+
+ pgc_gpumix: power-domain@2 {
+@@ -1076,7 +1075,7 @@
+ assigned-clock-parents = <&clk IMX8MN_SYS_PLL2_500M>;
+ phys = <&usbphynop1>;
+ fsl,usbmisc = <&usbmisc1 0>;
+- power-domains = <&pgc_otg1>;
++ power-domains = <&pgc_hsiomix>;
+ status = "disabled";
+ };
+
+@@ -1175,5 +1174,6 @@
+ assigned-clocks = <&clk IMX8MN_CLK_USB_PHY_REF>;
+ assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_100M>;
+ clock-names = "main_clk";
++ power-domains = <&pgc_otg1>;
+ };
+ };
+diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
+index 1c74c6a194491..360be51a35274 100644
+--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
+@@ -339,16 +339,6 @@
+ "SODIMM_82",
+ "SODIMM_70",
+ "SODIMM_72";
+-
+- ctrl-sleep-moci-hog {
+- gpio-hog;
+- /* Verdin CTRL_SLEEP_MOCI# (SODIMM 256) */
+- gpios = <29 GPIO_ACTIVE_HIGH>;
+- line-name = "CTRL_SLEEP_MOCI#";
+- output-high;
+- pinctrl-names = "default";
+- pinctrl-0 = <&pinctrl_ctrl_sleep_moci>;
+- };
+ };
+
+ &gpio3 {
+@@ -417,6 +407,16 @@
+ "SODIMM_256",
+ "SODIMM_48",
+ "SODIMM_44";
++
++ ctrl-sleep-moci-hog {
++ gpio-hog;
++ /* Verdin CTRL_SLEEP_MOCI# (SODIMM 256) */
++ gpios = <29 GPIO_ACTIVE_HIGH>;
++ line-name = "CTRL_SLEEP_MOCI#";
++ output-high;
++ pinctrl-names = "default";
++ pinctrl-0 = <&pinctrl_ctrl_sleep_moci>;
++ };
+ };
+
+ /* On-module I2C */
+diff --git a/arch/arm64/boot/dts/freescale/imx93.dtsi b/arch/arm64/boot/dts/freescale/imx93.dtsi
+index f83a07c7c9b1e..6981d3b0e2740 100644
+--- a/arch/arm64/boot/dts/freescale/imx93.dtsi
++++ b/arch/arm64/boot/dts/freescale/imx93.dtsi
+@@ -295,7 +295,10 @@
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+- gpio-ranges = <&iomuxc 0 32 32>;
++ clocks = <&clk IMX93_CLK_GPIO2_GATE>,
++ <&clk IMX93_CLK_GPIO2_GATE>;
++ clock-names = "gpio", "port";
++ gpio-ranges = <&iomuxc 0 4 30>;
+ };
+
+ gpio3: gpio@43820080 {
+@@ -306,7 +309,11 @@
+ interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+- gpio-ranges = <&iomuxc 0 64 32>;
++ clocks = <&clk IMX93_CLK_GPIO3_GATE>,
++ <&clk IMX93_CLK_GPIO3_GATE>;
++ clock-names = "gpio", "port";
++ gpio-ranges = <&iomuxc 0 84 8>, <&iomuxc 8 66 18>,
++ <&iomuxc 26 34 2>, <&iomuxc 28 0 4>;
+ };
+
+ gpio4: gpio@43830080 {
+@@ -317,7 +324,10 @@
+ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+- gpio-ranges = <&iomuxc 0 96 32>;
++ clocks = <&clk IMX93_CLK_GPIO4_GATE>,
++ <&clk IMX93_CLK_GPIO4_GATE>;
++ clock-names = "gpio", "port";
++ gpio-ranges = <&iomuxc 0 38 28>, <&iomuxc 28 36 2>;
+ };
+
+ gpio1: gpio@47400080 {
+@@ -328,7 +338,10 @@
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+- gpio-ranges = <&iomuxc 0 0 32>;
++ clocks = <&clk IMX93_CLK_GPIO1_GATE>,
++ <&clk IMX93_CLK_GPIO1_GATE>;
++ clock-names = "gpio", "port";
++ gpio-ranges = <&iomuxc 0 92 16>;
+ };
+ };
+ };
+diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
+index c75ca36b4a491..deb2897f39d63 100644
+--- a/arch/arm64/kernel/entry-common.c
++++ b/arch/arm64/kernel/entry-common.c
+@@ -329,7 +329,8 @@ static void cortex_a76_erratum_1463225_svc_handler(void)
+ __this_cpu_write(__in_cortex_a76_erratum_1463225_wa, 0);
+ }
+
+-static bool cortex_a76_erratum_1463225_debug_handler(struct pt_regs *regs)
++static __always_inline bool
++cortex_a76_erratum_1463225_debug_handler(struct pt_regs *regs)
+ {
+ if (!__this_cpu_read(__in_cortex_a76_erratum_1463225_wa))
+ return false;
+diff --git a/arch/arm64/kvm/hyp/exception.c b/arch/arm64/kvm/hyp/exception.c
+index b7557b25ed568..791d3de767713 100644
+--- a/arch/arm64/kvm/hyp/exception.c
++++ b/arch/arm64/kvm/hyp/exception.c
+@@ -13,6 +13,7 @@
+ #include <hyp/adjust_pc.h>
+ #include <linux/kvm_host.h>
+ #include <asm/kvm_emulate.h>
++#include <asm/kvm_mmu.h>
+
+ #if !defined (__KVM_NVHE_HYPERVISOR__) && !defined (__KVM_VHE_HYPERVISOR__)
+ #error Hypervisor code only!
+@@ -115,7 +116,7 @@ static void enter_exception64(struct kvm_vcpu *vcpu, unsigned long target_mode,
+ new |= (old & PSR_C_BIT);
+ new |= (old & PSR_V_BIT);
+
+- if (kvm_has_mte(vcpu->kvm))
++ if (kvm_has_mte(kern_hyp_va(vcpu->kvm)))
+ new |= PSR_TCO_BIT;
+
+ new |= (old & PSR_DIT_BIT);
+diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h
+index 6cbbb6c02f663..3330d1b76bdd2 100644
+--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
++++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
+@@ -87,6 +87,17 @@ static inline void __activate_traps_common(struct kvm_vcpu *vcpu)
+
+ vcpu->arch.mdcr_el2_host = read_sysreg(mdcr_el2);
+ write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
++
++ if (cpus_have_final_cap(ARM64_SME)) {
++ sysreg_clear_set_s(SYS_HFGRTR_EL2,
++ HFGxTR_EL2_nSMPRI_EL1_MASK |
++ HFGxTR_EL2_nTPIDR2_EL0_MASK,
++ 0);
++ sysreg_clear_set_s(SYS_HFGWTR_EL2,
++ HFGxTR_EL2_nSMPRI_EL1_MASK |
++ HFGxTR_EL2_nTPIDR2_EL0_MASK,
++ 0);
++ }
+ }
+
+ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
+@@ -96,6 +107,15 @@ static inline void __deactivate_traps_common(struct kvm_vcpu *vcpu)
+ write_sysreg(0, hstr_el2);
+ if (kvm_arm_support_pmu_v3())
+ write_sysreg(0, pmuserenr_el0);
++
++ if (cpus_have_final_cap(ARM64_SME)) {
++ sysreg_clear_set_s(SYS_HFGRTR_EL2, 0,
++ HFGxTR_EL2_nSMPRI_EL1_MASK |
++ HFGxTR_EL2_nTPIDR2_EL0_MASK);
++ sysreg_clear_set_s(SYS_HFGWTR_EL2, 0,
++ HFGxTR_EL2_nSMPRI_EL1_MASK |
++ HFGxTR_EL2_nTPIDR2_EL0_MASK);
++ }
+ }
+
+ static inline void ___activate_traps(struct kvm_vcpu *vcpu)
+diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
+index 9f63857020618..c5f6fd8a94405 100644
+--- a/arch/arm64/kvm/hyp/nvhe/switch.c
++++ b/arch/arm64/kvm/hyp/nvhe/switch.c
+@@ -55,18 +55,6 @@ static void __activate_traps(struct kvm_vcpu *vcpu)
+ write_sysreg(val, cptr_el2);
+ write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el2);
+
+- if (cpus_have_final_cap(ARM64_SME)) {
+- val = read_sysreg_s(SYS_HFGRTR_EL2);
+- val &= ~(HFGxTR_EL2_nTPIDR2_EL0_MASK |
+- HFGxTR_EL2_nSMPRI_EL1_MASK);
+- write_sysreg_s(val, SYS_HFGRTR_EL2);
+-
+- val = read_sysreg_s(SYS_HFGWTR_EL2);
+- val &= ~(HFGxTR_EL2_nTPIDR2_EL0_MASK |
+- HFGxTR_EL2_nSMPRI_EL1_MASK);
+- write_sysreg_s(val, SYS_HFGWTR_EL2);
+- }
+-
+ if (cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT)) {
+ struct kvm_cpu_context *ctxt = &vcpu->arch.ctxt;
+
+@@ -110,20 +98,6 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
+
+ write_sysreg(this_cpu_ptr(&kvm_init_params)->hcr_el2, hcr_el2);
+
+- if (cpus_have_final_cap(ARM64_SME)) {
+- u64 val;
+-
+- val = read_sysreg_s(SYS_HFGRTR_EL2);
+- val |= HFGxTR_EL2_nTPIDR2_EL0_MASK |
+- HFGxTR_EL2_nSMPRI_EL1_MASK;
+- write_sysreg_s(val, SYS_HFGRTR_EL2);
+-
+- val = read_sysreg_s(SYS_HFGWTR_EL2);
+- val |= HFGxTR_EL2_nTPIDR2_EL0_MASK |
+- HFGxTR_EL2_nSMPRI_EL1_MASK;
+- write_sysreg_s(val, SYS_HFGWTR_EL2);
+- }
+-
+ cptr = CPTR_EL2_DEFAULT;
+ if (vcpu_has_sve(vcpu) && (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED))
+ cptr |= CPTR_EL2_TZ;
+diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
+index 7acb87eaa0925..1a97391fedd29 100644
+--- a/arch/arm64/kvm/hyp/vhe/switch.c
++++ b/arch/arm64/kvm/hyp/vhe/switch.c
+@@ -63,10 +63,6 @@ static void __activate_traps(struct kvm_vcpu *vcpu)
+ __activate_traps_fpsimd32(vcpu);
+ }
+
+- if (cpus_have_final_cap(ARM64_SME))
+- write_sysreg(read_sysreg(sctlr_el2) & ~SCTLR_ELx_ENTP2,
+- sctlr_el2);
+-
+ write_sysreg(val, cpacr_el1);
+
+ write_sysreg(__this_cpu_read(kvm_hyp_vector), vbar_el1);
+@@ -88,10 +84,6 @@ static void __deactivate_traps(struct kvm_vcpu *vcpu)
+ */
+ asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_SPECULATIVE_AT));
+
+- if (cpus_have_final_cap(ARM64_SME))
+- write_sysreg(read_sysreg(sctlr_el2) | SCTLR_ELx_ENTP2,
+- sctlr_el2);
+-
+ write_sysreg(CPACR_EL1_DEFAULT, cpacr_el1);
+
+ if (!arm64_kernel_unmapped_at_el0())
+diff --git a/arch/parisc/include/asm/hardware.h b/arch/parisc/include/asm/hardware.h
+index 9d3d7737c58b1..a005ebc547793 100644
+--- a/arch/parisc/include/asm/hardware.h
++++ b/arch/parisc/include/asm/hardware.h
+@@ -10,12 +10,12 @@
+ #define SVERSION_ANY_ID PA_SVERSION_ANY_ID
+
+ struct hp_hardware {
+- unsigned short hw_type:5; /* HPHW_xxx */
+- unsigned short hversion;
+- unsigned long sversion:28;
+- unsigned short opt;
+- const char name[80]; /* The hardware description */
+-};
++ unsigned int hw_type:8; /* HPHW_xxx */
++ unsigned int hversion:12;
++ unsigned int sversion:12;
++ unsigned char opt;
++ unsigned char name[59]; /* The hardware description */
++} __packed;
+
+ struct parisc_device;
+
+diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
+index d126e78e101ae..e7ee0c0c91d35 100644
+--- a/arch/parisc/kernel/drivers.c
++++ b/arch/parisc/kernel/drivers.c
+@@ -882,15 +882,13 @@ void __init walk_central_bus(void)
+ &root);
+ }
+
+-static void print_parisc_device(struct parisc_device *dev)
++static __init void print_parisc_device(struct parisc_device *dev)
+ {
+- char hw_path[64];
+- static int count;
++ static int count __initdata;
+
+- print_pa_hwpath(dev, hw_path);
+- pr_info("%d. %s at %pap [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }",
+- ++count, dev->name, &(dev->hpa.start), hw_path, dev->id.hw_type,
+- dev->id.hversion_rev, dev->id.hversion, dev->id.sversion);
++ pr_info("%d. %s at %pap { type:%d, hv:%#x, sv:%#x, rev:%#x }",
++ ++count, dev->name, &(dev->hpa.start), dev->id.hw_type,
++ dev->id.hversion, dev->id.sversion, dev->id.hversion_rev);
+
+ if (dev->num_addrs) {
+ int k;
+@@ -1079,7 +1077,7 @@ static __init int qemu_print_iodc_data(struct device *lin_dev, void *data)
+
+
+
+-static int print_one_device(struct device * dev, void * data)
++static __init int print_one_device(struct device * dev, void * data)
+ {
+ struct parisc_device * pdev = to_parisc_device(dev);
+
+diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
+index 928dcf7a20d98..b8998cf0508a6 100644
+--- a/arch/x86/coco/tdx/tdx.c
++++ b/arch/x86/coco/tdx/tdx.c
+@@ -34,6 +34,8 @@
+ #define VE_GET_PORT_NUM(e) ((e) >> 16)
+ #define VE_IS_IO_STRING(e) ((e) & BIT(4))
+
++#define ATTR_SEPT_VE_DISABLE BIT(28)
++
+ /*
+ * Wrapper for standard use of __tdx_hypercall with no output aside from
+ * return code.
+@@ -98,10 +100,11 @@ static inline void tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
+ panic("TDCALL %lld failed (Buggy TDX module!)\n", fn);
+ }
+
+-static u64 get_cc_mask(void)
++static void tdx_parse_tdinfo(u64 *cc_mask)
+ {
+ struct tdx_module_output out;
+ unsigned int gpa_width;
++ u64 td_attr;
+
+ /*
+ * TDINFO TDX module call is used to get the TD execution environment
+@@ -109,19 +112,27 @@ static u64 get_cc_mask(void)
+ * information, etc. More details about the ABI can be found in TDX
+ * Guest-Host-Communication Interface (GHCI), section 2.4.2 TDCALL
+ * [TDG.VP.INFO].
++ */
++ tdx_module_call(TDX_GET_INFO, 0, 0, 0, 0, &out);
++
++ /*
++ * The highest bit of a guest physical address is the "sharing" bit.
++ * Set it for shared pages and clear it for private pages.
+ *
+ * The GPA width that comes out of this call is critical. TDX guests
+ * can not meaningfully run without it.
+ */
+- tdx_module_call(TDX_GET_INFO, 0, 0, 0, 0, &out);
+-
+ gpa_width = out.rcx & GENMASK(5, 0);
++ *cc_mask = BIT_ULL(gpa_width - 1);
+
+ /*
+- * The highest bit of a guest physical address is the "sharing" bit.
+- * Set it for shared pages and clear it for private pages.
++ * The kernel can not handle #VE's when accessing normal kernel
++ * memory. Ensure that no #VE will be delivered for accesses to
++ * TD-private memory. Only VMM-shared memory (MMIO) will #VE.
+ */
+- return BIT_ULL(gpa_width - 1);
++ td_attr = out.rdx;
++ if (!(td_attr & ATTR_SEPT_VE_DISABLE))
++ panic("TD misconfiguration: SEPT_VE_DISABLE attibute must be set.\n");
+ }
+
+ /*
+@@ -758,7 +769,7 @@ void __init tdx_early_init(void)
+ setup_force_cpu_cap(X86_FEATURE_TDX_GUEST);
+
+ cc_set_vendor(CC_VENDOR_INTEL);
+- cc_mask = get_cc_mask();
++ tdx_parse_tdinfo(&cc_mask);
+ cc_set_mask(cc_mask);
+
+ /*
+diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
+index c20d8cd47c484..3bfd0c5e01593 100644
+--- a/arch/x86/events/intel/core.c
++++ b/arch/x86/events/intel/core.c
+@@ -4891,6 +4891,7 @@ static const struct x86_cpu_desc isolation_ucodes[] = {
+ INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X, 5, 0x00000000),
+ INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X, 6, 0x00000000),
+ INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X, 7, 0x00000000),
++ INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X, 11, 0x00000000),
+ INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_L, 3, 0x0000007c),
+ INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE, 3, 0x0000007c),
+ INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE, 9, 0x0000004e),
+diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
+index ac973c6f82ad6..d1b9d2ad03476 100644
+--- a/arch/x86/events/intel/ds.c
++++ b/arch/x86/events/intel/ds.c
+@@ -982,8 +982,13 @@ struct event_constraint intel_icl_pebs_event_constraints[] = {
+ INTEL_FLAGS_UEVENT_CONSTRAINT(0x0400, 0x800000000ULL), /* SLOTS */
+
+ INTEL_PLD_CONSTRAINT(0x1cd, 0xff), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
+- INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x1d0, 0xf), /* MEM_INST_RETIRED.LOAD */
+- INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x2d0, 0xf), /* MEM_INST_RETIRED.STORE */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_LOADS */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_STORES */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x21d0, 0xf), /* MEM_INST_RETIRED.LOCK_LOADS */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x41d0, 0xf), /* MEM_INST_RETIRED.SPLIT_LOADS */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x42d0, 0xf), /* MEM_INST_RETIRED.SPLIT_STORES */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x81d0, 0xf), /* MEM_INST_RETIRED.ALL_LOADS */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x82d0, 0xf), /* MEM_INST_RETIRED.ALL_STORES */
+
+ INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD_RANGE(0xd1, 0xd4, 0xf), /* MEM_LOAD_*_RETIRED.* */
+
+@@ -1004,8 +1009,13 @@ struct event_constraint intel_spr_pebs_event_constraints[] = {
+ INTEL_FLAGS_EVENT_CONSTRAINT(0xc0, 0xfe),
+ INTEL_PLD_CONSTRAINT(0x1cd, 0xfe),
+ INTEL_PSD_CONSTRAINT(0x2cd, 0x1),
+- INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x1d0, 0xf),
+- INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x2d0, 0xf),
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_LOADS */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_STORES */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x21d0, 0xf), /* MEM_INST_RETIRED.LOCK_LOADS */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x41d0, 0xf), /* MEM_INST_RETIRED.SPLIT_LOADS */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x42d0, 0xf), /* MEM_INST_RETIRED.SPLIT_STORES */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x81d0, 0xf), /* MEM_INST_RETIRED.ALL_LOADS */
++ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x82d0, 0xf), /* MEM_INST_RETIRED.ALL_STORES */
+
+ INTEL_FLAGS_EVENT_CONSTRAINT_DATALA_LD_RANGE(0xd1, 0xd4, 0xf),
+
+diff --git a/arch/x86/include/asm/syscall_wrapper.h b/arch/x86/include/asm/syscall_wrapper.h
+index 59358d1bf8800..fd2669b1cb2d9 100644
+--- a/arch/x86/include/asm/syscall_wrapper.h
++++ b/arch/x86/include/asm/syscall_wrapper.h
+@@ -6,7 +6,7 @@
+ #ifndef _ASM_X86_SYSCALL_WRAPPER_H
+ #define _ASM_X86_SYSCALL_WRAPPER_H
+
+-struct pt_regs;
++#include <asm/ptrace.h>
+
+ extern long __x64_sys_ni_syscall(const struct pt_regs *regs);
+ extern long __ia32_sys_ni_syscall(const struct pt_regs *regs);
+diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
+index 2796dde06302a..28ab0b9484d33 100644
+--- a/arch/x86/kvm/cpuid.c
++++ b/arch/x86/kvm/cpuid.c
+@@ -1117,11 +1117,13 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
+ entry->eax = max(entry->eax, 0x80000021);
+ break;
+ case 0x80000001:
++ entry->ebx &= ~GENMASK(27, 16);
+ cpuid_entry_override(entry, CPUID_8000_0001_EDX);
+ cpuid_entry_override(entry, CPUID_8000_0001_ECX);
+ break;
+ case 0x80000006:
+- /* L2 cache and TLB: pass through host info. */
++ /* Drop reserved bits, pass host L2 cache and TLB info. */
++ entry->edx &= ~GENMASK(17, 16);
+ break;
+ case 0x80000007: /* Advanced power management */
+ /* invariant TSC is CPUID.80000007H:EDX[8] */
+@@ -1151,6 +1153,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
+ g_phys_as = phys_as;
+
+ entry->eax = g_phys_as | (virt_as << 8);
++ entry->ecx &= ~(GENMASK(31, 16) | GENMASK(11, 8));
+ entry->edx = 0;
+ cpuid_entry_override(entry, CPUID_8000_0008_EBX);
+ break;
+@@ -1170,6 +1173,9 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
+ entry->ecx = entry->edx = 0;
+ break;
+ case 0x8000001a:
++ entry->eax &= GENMASK(2, 0);
++ entry->ebx = entry->ecx = entry->edx = 0;
++ break;
+ case 0x8000001e:
+ break;
+ case 0x8000001F:
+@@ -1177,7 +1183,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
+ entry->eax = entry->ebx = entry->ecx = entry->edx = 0;
+ } else {
+ cpuid_entry_override(entry, CPUID_8000_001F_EAX);
+-
++ /* Clear NumVMPL since KVM does not support VMPL. */
++ entry->ebx &= ~GENMASK(31, 12);
+ /*
+ * Enumerate '0' for "PA bits reduction", the adjusted
+ * MAXPHYADDR is enumerated directly (see 0x80000008).
+diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
+index 883e380e5801d..fdb20b3c38f5f 100644
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -791,8 +791,7 @@ static int linearize(struct x86_emulate_ctxt *ctxt,
+ ctxt->mode, linear);
+ }
+
+-static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst,
+- enum x86emul_mode mode)
++static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst)
+ {
+ ulong linear;
+ int rc;
+@@ -802,41 +801,71 @@ static inline int assign_eip(struct x86_emulate_ctxt *ctxt, ulong dst,
+
+ if (ctxt->op_bytes != sizeof(unsigned long))
+ addr.ea = dst & ((1UL << (ctxt->op_bytes << 3)) - 1);
+- rc = __linearize(ctxt, addr, &max_size, 1, false, true, mode, &linear);
++ rc = __linearize(ctxt, addr, &max_size, 1, false, true, ctxt->mode, &linear);
+ if (rc == X86EMUL_CONTINUE)
+ ctxt->_eip = addr.ea;
+ return rc;
+ }
+
++static inline int emulator_recalc_and_set_mode(struct x86_emulate_ctxt *ctxt)
++{
++ u64 efer;
++ struct desc_struct cs;
++ u16 selector;
++ u32 base3;
++
++ ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
++
++ if (!(ctxt->ops->get_cr(ctxt, 0) & X86_CR0_PE)) {
++ /* Real mode. cpu must not have long mode active */
++ if (efer & EFER_LMA)
++ return X86EMUL_UNHANDLEABLE;
++ ctxt->mode = X86EMUL_MODE_REAL;
++ return X86EMUL_CONTINUE;
++ }
++
++ if (ctxt->eflags & X86_EFLAGS_VM) {
++ /* Protected/VM86 mode. cpu must not have long mode active */
++ if (efer & EFER_LMA)
++ return X86EMUL_UNHANDLEABLE;
++ ctxt->mode = X86EMUL_MODE_VM86;
++ return X86EMUL_CONTINUE;
++ }
++
++ if (!ctxt->ops->get_segment(ctxt, &selector, &cs, &base3, VCPU_SREG_CS))
++ return X86EMUL_UNHANDLEABLE;
++
++ if (efer & EFER_LMA) {
++ if (cs.l) {
++ /* Proper long mode */
++ ctxt->mode = X86EMUL_MODE_PROT64;
++ } else if (cs.d) {
++ /* 32 bit compatibility mode*/
++ ctxt->mode = X86EMUL_MODE_PROT32;
++ } else {
++ ctxt->mode = X86EMUL_MODE_PROT16;
++ }
++ } else {
++ /* Legacy 32 bit / 16 bit mode */
++ ctxt->mode = cs.d ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
++ }
++
++ return X86EMUL_CONTINUE;
++}
++
+ static inline int assign_eip_near(struct x86_emulate_ctxt *ctxt, ulong dst)
+ {
+- return assign_eip(ctxt, dst, ctxt->mode);
++ return assign_eip(ctxt, dst);
+ }
+
+-static int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst,
+- const struct desc_struct *cs_desc)
++static int assign_eip_far(struct x86_emulate_ctxt *ctxt, ulong dst)
+ {
+- enum x86emul_mode mode = ctxt->mode;
+- int rc;
++ int rc = emulator_recalc_and_set_mode(ctxt);
+
+-#ifdef CONFIG_X86_64
+- if (ctxt->mode >= X86EMUL_MODE_PROT16) {
+- if (cs_desc->l) {
+- u64 efer = 0;
++ if (rc != X86EMUL_CONTINUE)
++ return rc;
+
+- ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
+- if (efer & EFER_LMA)
+- mode = X86EMUL_MODE_PROT64;
+- } else
+- mode = X86EMUL_MODE_PROT32; /* temporary value */
+- }
+-#endif
+- if (mode == X86EMUL_MODE_PROT16 || mode == X86EMUL_MODE_PROT32)
+- mode = cs_desc->d ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
+- rc = assign_eip(ctxt, dst, mode);
+- if (rc == X86EMUL_CONTINUE)
+- ctxt->mode = mode;
+- return rc;
++ return assign_eip(ctxt, dst);
+ }
+
+ static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
+@@ -2170,7 +2199,7 @@ static int em_jmp_far(struct x86_emulate_ctxt *ctxt)
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+- rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc);
++ rc = assign_eip_far(ctxt, ctxt->src.val);
+ /* Error handling is not implemented. */
+ if (rc != X86EMUL_CONTINUE)
+ return X86EMUL_UNHANDLEABLE;
+@@ -2248,7 +2277,7 @@ static int em_ret_far(struct x86_emulate_ctxt *ctxt)
+ &new_desc);
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+- rc = assign_eip_far(ctxt, eip, &new_desc);
++ rc = assign_eip_far(ctxt, eip);
+ /* Error handling is not implemented. */
+ if (rc != X86EMUL_CONTINUE)
+ return X86EMUL_UNHANDLEABLE;
+@@ -2430,7 +2459,7 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt,
+ ctxt->eflags = GET_SMSTATE(u32, smstate, 0x7ff4) | X86_EFLAGS_FIXED;
+ ctxt->_eip = GET_SMSTATE(u32, smstate, 0x7ff0);
+
+- for (i = 0; i < NR_EMULATOR_GPRS; i++)
++ for (i = 0; i < 8; i++)
+ *reg_write(ctxt, i) = GET_SMSTATE(u32, smstate, 0x7fd0 + i * 4);
+
+ val = GET_SMSTATE(u32, smstate, 0x7fcc);
+@@ -2487,7 +2516,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt,
+ u16 selector;
+ int i, r;
+
+- for (i = 0; i < NR_EMULATOR_GPRS; i++)
++ for (i = 0; i < 16; i++)
+ *reg_write(ctxt, i) = GET_SMSTATE(u64, smstate, 0x7ff8 - i * 8);
+
+ ctxt->_eip = GET_SMSTATE(u64, smstate, 0x7f78);
+@@ -2631,7 +2660,7 @@ static int em_rsm(struct x86_emulate_ctxt *ctxt)
+ * those side effects need to be explicitly handled for both success
+ * and shutdown.
+ */
+- return X86EMUL_CONTINUE;
++ return emulator_recalc_and_set_mode(ctxt);
+
+ emulate_shutdown:
+ ctxt->ops->triple_fault(ctxt);
+@@ -2874,6 +2903,7 @@ static int em_sysexit(struct x86_emulate_ctxt *ctxt)
+ ops->set_segment(ctxt, ss_sel, &ss, 0, VCPU_SREG_SS);
+
+ ctxt->_eip = rdx;
++ ctxt->mode = usermode;
+ *reg_write(ctxt, VCPU_REGS_RSP) = rcx;
+
+ return X86EMUL_CONTINUE;
+@@ -3467,7 +3497,7 @@ static int em_call_far(struct x86_emulate_ctxt *ctxt)
+ if (rc != X86EMUL_CONTINUE)
+ return rc;
+
+- rc = assign_eip_far(ctxt, ctxt->src.val, &new_desc);
++ rc = assign_eip_far(ctxt, ctxt->src.val);
+ if (rc != X86EMUL_CONTINUE)
+ goto fail;
+
+@@ -3609,11 +3639,25 @@ static int em_movbe(struct x86_emulate_ctxt *ctxt)
+
+ static int em_cr_write(struct x86_emulate_ctxt *ctxt)
+ {
+- if (ctxt->ops->set_cr(ctxt, ctxt->modrm_reg, ctxt->src.val))
++ int cr_num = ctxt->modrm_reg;
++ int r;
++
++ if (ctxt->ops->set_cr(ctxt, cr_num, ctxt->src.val))
+ return emulate_gp(ctxt, 0);
+
+ /* Disable writeback. */
+ ctxt->dst.type = OP_NONE;
++
++ if (cr_num == 0) {
++ /*
++ * CR0 write might have updated CR0.PE and/or CR0.PG
++ * which can affect the cpu's execution mode.
++ */
++ r = emulator_recalc_and_set_mode(ctxt);
++ if (r != X86EMUL_CONTINUE)
++ return r;
++ }
++
+ return X86EMUL_CONTINUE;
+ }
+
+diff --git a/arch/x86/kvm/vmx/capabilities.h b/arch/x86/kvm/vmx/capabilities.h
+index c5e5dfef69c7f..2bd599d61b9bf 100644
+--- a/arch/x86/kvm/vmx/capabilities.h
++++ b/arch/x86/kvm/vmx/capabilities.h
+@@ -24,8 +24,6 @@ extern int __read_mostly pt_mode;
+ #define PMU_CAP_FW_WRITES (1ULL << 13)
+ #define PMU_CAP_LBR_FMT 0x3f
+
+-#define DEBUGCTLMSR_LBR_MASK (DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI)
+-
+ struct nested_vmx_msrs {
+ /*
+ * We only store the "true" versions of the VMX capability MSRs. We
+@@ -404,6 +402,7 @@ static inline bool vmx_pebs_supported(void)
+ static inline u64 vmx_get_perf_capabilities(void)
+ {
+ u64 perf_cap = PMU_CAP_FW_WRITES;
++ struct x86_pmu_lbr lbr;
+ u64 host_perf_cap = 0;
+
+ if (!enable_pmu)
+@@ -412,7 +411,8 @@ static inline u64 vmx_get_perf_capabilities(void)
+ if (boot_cpu_has(X86_FEATURE_PDCM))
+ rdmsrl(MSR_IA32_PERF_CAPABILITIES, host_perf_cap);
+
+- perf_cap |= host_perf_cap & PMU_CAP_LBR_FMT;
++ if (x86_perf_get_lbr(&lbr) >= 0 && lbr.nr)
++ perf_cap |= host_perf_cap & PMU_CAP_LBR_FMT;
+
+ if (vmx_pebs_supported()) {
+ perf_cap |= host_perf_cap & PERF_CAP_PEBS_MASK;
+@@ -423,19 +423,6 @@ static inline u64 vmx_get_perf_capabilities(void)
+ return perf_cap;
+ }
+
+-static inline u64 vmx_supported_debugctl(void)
+-{
+- u64 debugctl = 0;
+-
+- if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT))
+- debugctl |= DEBUGCTLMSR_BUS_LOCK_DETECT;
+-
+- if (vmx_get_perf_capabilities() & PMU_CAP_LBR_FMT)
+- debugctl |= DEBUGCTLMSR_LBR_MASK;
+-
+- return debugctl;
+-}
+-
+ static inline bool cpu_has_notify_vmexit(void)
+ {
+ return vmcs_config.cpu_based_2nd_exec_ctrl &
+diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
+index 7f3581960eb5d..74de8c9e401b1 100644
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -2016,15 +2016,17 @@ static u64 nested_vmx_truncate_sysenter_addr(struct kvm_vcpu *vcpu,
+ return (unsigned long)data;
+ }
+
+-static u64 vcpu_supported_debugctl(struct kvm_vcpu *vcpu)
++static u64 vmx_get_supported_debugctl(struct kvm_vcpu *vcpu, bool host_initiated)
+ {
+- u64 debugctl = vmx_supported_debugctl();
++ u64 debugctl = 0;
+
+- if (!intel_pmu_lbr_is_enabled(vcpu))
+- debugctl &= ~DEBUGCTLMSR_LBR_MASK;
++ if (boot_cpu_has(X86_FEATURE_BUS_LOCK_DETECT) &&
++ (host_initiated || guest_cpuid_has(vcpu, X86_FEATURE_BUS_LOCK_DETECT)))
++ debugctl |= DEBUGCTLMSR_BUS_LOCK_DETECT;
+
+- if (!guest_cpuid_has(vcpu, X86_FEATURE_BUS_LOCK_DETECT))
+- debugctl &= ~DEBUGCTLMSR_BUS_LOCK_DETECT;
++ if ((vmx_get_perf_capabilities() & PMU_CAP_LBR_FMT) &&
++ (host_initiated || intel_pmu_lbr_is_enabled(vcpu)))
++ debugctl |= DEBUGCTLMSR_LBR | DEBUGCTLMSR_FREEZE_LBRS_ON_PMI;
+
+ return debugctl;
+ }
+@@ -2098,7 +2100,9 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ vmcs_writel(GUEST_SYSENTER_ESP, data);
+ break;
+ case MSR_IA32_DEBUGCTLMSR: {
+- u64 invalid = data & ~vcpu_supported_debugctl(vcpu);
++ u64 invalid;
++
++ invalid = data & ~vmx_get_supported_debugctl(vcpu, msr_info->host_initiated);
+ if (invalid & (DEBUGCTLMSR_BTF|DEBUGCTLMSR_LBR)) {
+ if (report_ignored_msrs)
+ vcpu_unimpl(vcpu, "%s: BTF|LBR in IA32_DEBUGCTLMSR 0x%llx, nop\n",
+@@ -8277,6 +8281,11 @@ static __init int hardware_setup(void)
+ if (!cpu_has_virtual_nmis())
+ enable_vnmi = 0;
+
++#ifdef CONFIG_X86_SGX_KVM
++ if (!cpu_has_vmx_encls_vmexit())
++ enable_sgx = false;
++#endif
++
+ /*
+ * set_apic_access_page_addr() is used to reload apic access
+ * page upon invalidation. No need to do anything if not
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 86c3b29f1abc0..05f4424eb0c52 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -2304,11 +2304,11 @@ static void kvm_write_system_time(struct kvm_vcpu *vcpu, gpa_t system_time,
+
+ /* we verify if the enable bit is set... */
+ if (system_time & 1) {
+- kvm_gfn_to_pfn_cache_init(vcpu->kvm, &vcpu->arch.pv_time, vcpu,
+- KVM_HOST_USES_PFN, system_time & ~1ULL,
+- sizeof(struct pvclock_vcpu_time_info));
++ kvm_gpc_activate(vcpu->kvm, &vcpu->arch.pv_time, vcpu,
++ KVM_HOST_USES_PFN, system_time & ~1ULL,
++ sizeof(struct pvclock_vcpu_time_info));
+ } else {
+- kvm_gfn_to_pfn_cache_destroy(vcpu->kvm, &vcpu->arch.pv_time);
++ kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.pv_time);
+ }
+
+ return;
+@@ -3377,7 +3377,7 @@ static int kvm_pv_enable_async_pf_int(struct kvm_vcpu *vcpu, u64 data)
+
+ static void kvmclock_reset(struct kvm_vcpu *vcpu)
+ {
+- kvm_gfn_to_pfn_cache_destroy(vcpu->kvm, &vcpu->arch.pv_time);
++ kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.pv_time);
+ vcpu->arch.time = 0;
+ }
+
+@@ -11629,6 +11629,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
+ vcpu->arch.regs_avail = ~0;
+ vcpu->arch.regs_dirty = ~0;
+
++ kvm_gpc_init(&vcpu->arch.pv_time);
++
+ if (!irqchip_in_kernel(vcpu->kvm) || kvm_vcpu_is_reset_bsp(vcpu))
+ vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
+ else
+diff --git a/arch/x86/kvm/xen.c b/arch/x86/kvm/xen.c
+index 280cb5dc7341a..cecf8299b187b 100644
+--- a/arch/x86/kvm/xen.c
++++ b/arch/x86/kvm/xen.c
+@@ -42,13 +42,13 @@ static int kvm_xen_shared_info_init(struct kvm *kvm, gfn_t gfn)
+ int idx = srcu_read_lock(&kvm->srcu);
+
+ if (gfn == GPA_INVALID) {
+- kvm_gfn_to_pfn_cache_destroy(kvm, gpc);
++ kvm_gpc_deactivate(kvm, gpc);
+ goto out;
+ }
+
+ do {
+- ret = kvm_gfn_to_pfn_cache_init(kvm, gpc, NULL, KVM_HOST_USES_PFN,
+- gpa, PAGE_SIZE);
++ ret = kvm_gpc_activate(kvm, gpc, NULL, KVM_HOST_USES_PFN, gpa,
++ PAGE_SIZE);
+ if (ret)
+ goto out;
+
+@@ -554,15 +554,15 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
+ offsetof(struct compat_vcpu_info, time));
+
+ if (data->u.gpa == GPA_INVALID) {
+- kvm_gfn_to_pfn_cache_destroy(vcpu->kvm, &vcpu->arch.xen.vcpu_info_cache);
++ kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.xen.vcpu_info_cache);
+ r = 0;
+ break;
+ }
+
+- r = kvm_gfn_to_pfn_cache_init(vcpu->kvm,
+- &vcpu->arch.xen.vcpu_info_cache,
+- NULL, KVM_HOST_USES_PFN, data->u.gpa,
+- sizeof(struct vcpu_info));
++ r = kvm_gpc_activate(vcpu->kvm,
++ &vcpu->arch.xen.vcpu_info_cache, NULL,
++ KVM_HOST_USES_PFN, data->u.gpa,
++ sizeof(struct vcpu_info));
+ if (!r)
+ kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
+
+@@ -570,16 +570,16 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
+
+ case KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO:
+ if (data->u.gpa == GPA_INVALID) {
+- kvm_gfn_to_pfn_cache_destroy(vcpu->kvm,
+- &vcpu->arch.xen.vcpu_time_info_cache);
++ kvm_gpc_deactivate(vcpu->kvm,
++ &vcpu->arch.xen.vcpu_time_info_cache);
+ r = 0;
+ break;
+ }
+
+- r = kvm_gfn_to_pfn_cache_init(vcpu->kvm,
+- &vcpu->arch.xen.vcpu_time_info_cache,
+- NULL, KVM_HOST_USES_PFN, data->u.gpa,
+- sizeof(struct pvclock_vcpu_time_info));
++ r = kvm_gpc_activate(vcpu->kvm,
++ &vcpu->arch.xen.vcpu_time_info_cache,
++ NULL, KVM_HOST_USES_PFN, data->u.gpa,
++ sizeof(struct pvclock_vcpu_time_info));
+ if (!r)
+ kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
+ break;
+@@ -590,16 +590,15 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
+ break;
+ }
+ if (data->u.gpa == GPA_INVALID) {
+- kvm_gfn_to_pfn_cache_destroy(vcpu->kvm,
+- &vcpu->arch.xen.runstate_cache);
++ kvm_gpc_deactivate(vcpu->kvm,
++ &vcpu->arch.xen.runstate_cache);
+ r = 0;
+ break;
+ }
+
+- r = kvm_gfn_to_pfn_cache_init(vcpu->kvm,
+- &vcpu->arch.xen.runstate_cache,
+- NULL, KVM_HOST_USES_PFN, data->u.gpa,
+- sizeof(struct vcpu_runstate_info));
++ r = kvm_gpc_activate(vcpu->kvm, &vcpu->arch.xen.runstate_cache,
++ NULL, KVM_HOST_USES_PFN, data->u.gpa,
++ sizeof(struct vcpu_runstate_info));
+ break;
+
+ case KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT:
+@@ -1817,7 +1816,12 @@ void kvm_xen_init_vcpu(struct kvm_vcpu *vcpu)
+ {
+ vcpu->arch.xen.vcpu_id = vcpu->vcpu_idx;
+ vcpu->arch.xen.poll_evtchn = 0;
++
+ timer_setup(&vcpu->arch.xen.poll_timer, cancel_evtchn_poll, 0);
++
++ kvm_gpc_init(&vcpu->arch.xen.runstate_cache);
++ kvm_gpc_init(&vcpu->arch.xen.vcpu_info_cache);
++ kvm_gpc_init(&vcpu->arch.xen.vcpu_time_info_cache);
+ }
+
+ void kvm_xen_destroy_vcpu(struct kvm_vcpu *vcpu)
+@@ -1825,18 +1829,17 @@ void kvm_xen_destroy_vcpu(struct kvm_vcpu *vcpu)
+ if (kvm_xen_timer_enabled(vcpu))
+ kvm_xen_stop_timer(vcpu);
+
+- kvm_gfn_to_pfn_cache_destroy(vcpu->kvm,
+- &vcpu->arch.xen.runstate_cache);
+- kvm_gfn_to_pfn_cache_destroy(vcpu->kvm,
+- &vcpu->arch.xen.vcpu_info_cache);
+- kvm_gfn_to_pfn_cache_destroy(vcpu->kvm,
+- &vcpu->arch.xen.vcpu_time_info_cache);
++ kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.xen.runstate_cache);
++ kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.xen.vcpu_info_cache);
++ kvm_gpc_deactivate(vcpu->kvm, &vcpu->arch.xen.vcpu_time_info_cache);
++
+ del_timer_sync(&vcpu->arch.xen.poll_timer);
+ }
+
+ void kvm_xen_init_vm(struct kvm *kvm)
+ {
+ idr_init(&kvm->arch.xen.evtchn_ports);
++ kvm_gpc_init(&kvm->arch.xen.shinfo_cache);
+ }
+
+ void kvm_xen_destroy_vm(struct kvm *kvm)
+@@ -1844,7 +1847,7 @@ void kvm_xen_destroy_vm(struct kvm *kvm)
+ struct evtchnfd *evtchnfd;
+ int i;
+
+- kvm_gfn_to_pfn_cache_destroy(kvm, &kvm->arch.xen.shinfo_cache);
++ kvm_gpc_deactivate(kvm, &kvm->arch.xen.shinfo_cache);
+
+ idr_for_each_entry(&kvm->arch.xen.evtchn_ports, evtchnfd, i) {
+ if (!evtchnfd->deliver.port.port)
+diff --git a/block/bio.c b/block/bio.c
+index 77e3b764a0784..fc2364cf17750 100644
+--- a/block/bio.c
++++ b/block/bio.c
+@@ -741,7 +741,7 @@ void bio_put(struct bio *bio)
+ return;
+ }
+
+- if (bio->bi_opf & REQ_ALLOC_CACHE) {
++ if ((bio->bi_opf & REQ_ALLOC_CACHE) && !WARN_ON_ONCE(in_interrupt())) {
+ struct bio_alloc_cache *cache;
+
+ bio_uninit(bio);
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index fe840536e6ac4..edf41959a705f 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -4104,9 +4104,7 @@ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
+ return 0;
+
+ err_hctxs:
+- xa_destroy(&q->hctx_table);
+- q->nr_hw_queues = 0;
+- blk_mq_sysfs_deinit(q);
++ blk_mq_release(q);
+ err_poll:
+ blk_stat_free_callback(q->poll_cb);
+ q->poll_cb = NULL;
+diff --git a/block/genhd.c b/block/genhd.c
+index 988ba52fd3316..044ff97381e33 100644
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -519,6 +519,7 @@ out_unregister_bdi:
+ bdi_unregister(disk->bdi);
+ out_unregister_queue:
+ blk_unregister_queue(disk);
++ rq_qos_exit(disk->queue);
+ out_put_slave_dir:
+ kobject_put(disk->slave_dir);
+ out_put_holder_dir:
+diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
+index 80ad530583c9c..9952f3a792bad 100644
+--- a/drivers/acpi/apei/ghes.c
++++ b/drivers/acpi/apei/ghes.c
+@@ -163,7 +163,7 @@ static void ghes_unmap(void __iomem *vaddr, enum fixed_addresses fixmap_idx)
+ clear_fixmap(fixmap_idx);
+ }
+
+-int ghes_estatus_pool_init(int num_ghes)
++int ghes_estatus_pool_init(unsigned int num_ghes)
+ {
+ unsigned long addr, len;
+ int rc;
+diff --git a/drivers/acpi/numa/srat.c b/drivers/acpi/numa/srat.c
+index 3b818ab186be8..1f4fc5f8a819d 100644
+--- a/drivers/acpi/numa/srat.c
++++ b/drivers/acpi/numa/srat.c
+@@ -327,6 +327,7 @@ static int __init acpi_parse_cfmws(union acpi_subtable_headers *header,
+ pr_warn("ACPI NUMA: Failed to add memblk for CFMWS node %d [mem %#llx-%#llx]\n",
+ node, start, end);
+ }
++ node_set(node, numa_nodes_parsed);
+
+ /* Set the next available fake_pxm value */
+ (*fake_pxm)++;
+diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
+index 0a8bf09a5c19e..03c580625c2cc 100644
+--- a/drivers/ata/pata_legacy.c
++++ b/drivers/ata/pata_legacy.c
+@@ -315,9 +315,10 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ outb(inb(0x1F4) & 0x07, 0x1F4);
+
+ rt = inb(0x1F3);
+- rt &= 0x07 << (3 * adev->devno);
++ rt &= ~(0x07 << (3 * !adev->devno));
+ if (pio)
+- rt |= (1 + 3 * pio) << (3 * adev->devno);
++ rt |= (1 + 3 * pio) << (3 * !adev->devno);
++ outb(rt, 0x1F3);
+
+ udelay(100);
+ outb(inb(0x1F2) | 0x01, 0x1F2);
+diff --git a/drivers/ata/pata_palmld.c b/drivers/ata/pata_palmld.c
+index 400e65190904f..51caa2a427dd8 100644
+--- a/drivers/ata/pata_palmld.c
++++ b/drivers/ata/pata_palmld.c
+@@ -63,8 +63,8 @@ static int palmld_pata_probe(struct platform_device *pdev)
+
+ /* remap drive's physical memory address */
+ mem = devm_platform_ioremap_resource(pdev, 0);
+- if (!mem)
+- return -ENOMEM;
++ if (IS_ERR(mem))
++ return PTR_ERR(mem);
+
+ /* request and activate power and reset GPIOs */
+ lda->power = devm_gpiod_get(dev, "power", GPIOD_OUT_HIGH);
+diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
+index 6a4a94b4cdf42..31a8715d3a4d3 100644
+--- a/drivers/block/ublk_drv.c
++++ b/drivers/block/ublk_drv.c
+@@ -1507,6 +1507,9 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)
+ */
+ ub->dev_info.flags &= UBLK_F_ALL;
+
++ if (!IS_BUILTIN(CONFIG_BLK_DEV_UBLK))
++ ub->dev_info.flags |= UBLK_F_URING_CMD_COMP_IN_TASK;
++
+ /* We are not ready to support zero copy */
+ ub->dev_info.flags &= ~UBLK_F_SUPPORT_ZERO_COPY;
+
+diff --git a/drivers/bluetooth/virtio_bt.c b/drivers/bluetooth/virtio_bt.c
+index 67c21263f9e0f..fd281d4395055 100644
+--- a/drivers/bluetooth/virtio_bt.c
++++ b/drivers/bluetooth/virtio_bt.c
+@@ -219,7 +219,7 @@ static void virtbt_rx_work(struct work_struct *work)
+ if (!skb)
+ return;
+
+- skb->len = len;
++ skb_put(skb, len);
+ virtbt_rx_handle(vbt, skb);
+
+ if (virtbt_add_inbuf(vbt) < 0)
+diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c
+index e7dd457e9b22b..e98fcac578d66 100644
+--- a/drivers/char/hw_random/bcm2835-rng.c
++++ b/drivers/char/hw_random/bcm2835-rng.c
+@@ -71,7 +71,7 @@ static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
+ while ((rng_readl(priv, RNG_STATUS) >> 24) == 0) {
+ if (!wait)
+ return 0;
+- cpu_relax();
++ hwrng_msleep(rng, 1000);
+ }
+
+ num_words = rng_readl(priv, RNG_STATUS) >> 24;
+diff --git a/drivers/clk/clk-renesas-pcie.c b/drivers/clk/clk-renesas-pcie.c
+index 4f5df1fc74b46..e6247141d0c05 100644
+--- a/drivers/clk/clk-renesas-pcie.c
++++ b/drivers/clk/clk-renesas-pcie.c
+@@ -90,13 +90,66 @@ static const struct regmap_access_table rs9_writeable_table = {
+ .n_yes_ranges = ARRAY_SIZE(rs9_writeable_ranges),
+ };
+
++static int rs9_regmap_i2c_write(void *context,
++ unsigned int reg, unsigned int val)
++{
++ struct i2c_client *i2c = context;
++ const u8 data[3] = { reg, 1, val };
++ const int count = ARRAY_SIZE(data);
++ int ret;
++
++ ret = i2c_master_send(i2c, data, count);
++ if (ret == count)
++ return 0;
++ else if (ret < 0)
++ return ret;
++ else
++ return -EIO;
++}
++
++static int rs9_regmap_i2c_read(void *context,
++ unsigned int reg, unsigned int *val)
++{
++ struct i2c_client *i2c = context;
++ struct i2c_msg xfer[2];
++ u8 txdata = reg;
++ u8 rxdata[2];
++ int ret;
++
++ xfer[0].addr = i2c->addr;
++ xfer[0].flags = 0;
++ xfer[0].len = 1;
++ xfer[0].buf = (void *)&txdata;
++
++ xfer[1].addr = i2c->addr;
++ xfer[1].flags = I2C_M_RD;
++ xfer[1].len = 2;
++ xfer[1].buf = (void *)rxdata;
++
++ ret = i2c_transfer(i2c->adapter, xfer, 2);
++ if (ret < 0)
++ return ret;
++ if (ret != 2)
++ return -EIO;
++
++ /*
++ * Byte 0 is transfer length, which is always 1 due
++ * to BCP register programming to 1 in rs9_probe(),
++ * ignore it and use data from Byte 1.
++ */
++ *val = rxdata[1];
++ return 0;
++}
++
+ static const struct regmap_config rs9_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+- .cache_type = REGCACHE_FLAT,
+- .max_register = 0x8,
++ .cache_type = REGCACHE_NONE,
++ .max_register = RS9_REG_BCP,
+ .rd_table = &rs9_readable_table,
+ .wr_table = &rs9_writeable_table,
++ .reg_write = rs9_regmap_i2c_write,
++ .reg_read = rs9_regmap_i2c_read,
+ };
+
+ static int rs9_get_output_config(struct rs9_driver_data *rs9, int idx)
+@@ -242,11 +295,17 @@ static int rs9_probe(struct i2c_client *client)
+ return ret;
+ }
+
+- rs9->regmap = devm_regmap_init_i2c(client, &rs9_regmap_config);
++ rs9->regmap = devm_regmap_init(&client->dev, NULL,
++ client, &rs9_regmap_config);
+ if (IS_ERR(rs9->regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(rs9->regmap),
+ "Failed to allocate register map\n");
+
++ /* Always read back 1 Byte via I2C */
++ ret = regmap_write(rs9->regmap, RS9_REG_BCP, 1);
++ if (ret < 0)
++ return ret;
++
+ /* Register clock */
+ for (i = 0; i < rs9->chip_info->num_clks; i++) {
+ snprintf(name, 5, "DIF%d", i);
+diff --git a/drivers/clk/qcom/gcc-sc7280.c b/drivers/clk/qcom/gcc-sc7280.c
+index 7ff64d4d5920d..2360f3f956184 100644
+--- a/drivers/clk/qcom/gcc-sc7280.c
++++ b/drivers/clk/qcom/gcc-sc7280.c
+@@ -3467,6 +3467,7 @@ static int gcc_sc7280_probe(struct platform_device *pdev)
+ regmap_update_bits(regmap, 0x28004, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x28014, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x71004, BIT(0), BIT(0));
++ regmap_update_bits(regmap, 0x7100C, BIT(13), BIT(13));
+
+ ret = qcom_cc_register_rcg_dfs(regmap, gcc_dfs_clocks,
+ ARRAY_SIZE(gcc_dfs_clocks));
+diff --git a/drivers/clk/qcom/gpucc-sc7280.c b/drivers/clk/qcom/gpucc-sc7280.c
+index 9a832f2bcf491..1490cd45a654a 100644
+--- a/drivers/clk/qcom/gpucc-sc7280.c
++++ b/drivers/clk/qcom/gpucc-sc7280.c
+@@ -463,6 +463,7 @@ static int gpu_cc_sc7280_probe(struct platform_device *pdev)
+ */
+ regmap_update_bits(regmap, 0x1170, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x1098, BIT(0), BIT(0));
++ regmap_update_bits(regmap, 0x1098, BIT(13), BIT(13));
+
+ return qcom_cc_really_probe(pdev, &gpu_cc_sc7280_desc, regmap);
+ }
+diff --git a/drivers/clk/renesas/r8a779g0-cpg-mssr.c b/drivers/clk/renesas/r8a779g0-cpg-mssr.c
+index 3fc4233b1ead8..7beb0e3b18724 100644
+--- a/drivers/clk/renesas/r8a779g0-cpg-mssr.c
++++ b/drivers/clk/renesas/r8a779g0-cpg-mssr.c
+@@ -47,6 +47,7 @@ enum clk_ids {
+ CLK_S0_VIO,
+ CLK_S0_VC,
+ CLK_S0_HSC,
++ CLK_SASYNCPER,
+ CLK_SV_VIP,
+ CLK_SV_IR,
+ CLK_SDSRC,
+@@ -84,6 +85,7 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
+ DEF_FIXED(".s0_vio", CLK_S0_VIO, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0_vc", CLK_S0_VC, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".s0_hsc", CLK_S0_HSC, CLK_PLL1_DIV2, 2, 1),
++ DEF_FIXED(".sasyncper", CLK_SASYNCPER, CLK_PLL5_DIV4, 3, 1),
+ DEF_FIXED(".sv_vip", CLK_SV_VIP, CLK_PLL1, 5, 1),
+ DEF_FIXED(".sv_ir", CLK_SV_IR, CLK_PLL1, 5, 1),
+ DEF_BASE(".sdsrc", CLK_SDSRC, CLK_TYPE_GEN4_SDSRC, CLK_PLL5),
+@@ -128,6 +130,9 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
+ DEF_FIXED("s0d4_hsc", R8A779G0_CLK_S0D4_HSC, CLK_S0_HSC, 4, 1),
+ DEF_FIXED("cl16m_hsc", R8A779G0_CLK_CL16M_HSC, CLK_S0_HSC, 48, 1),
+ DEF_FIXED("s0d2_cc", R8A779G0_CLK_S0D2_CC, CLK_S0, 2, 1),
++ DEF_FIXED("sasyncperd1",R8A779G0_CLK_SASYNCPERD1, CLK_SASYNCPER,1, 1),
++ DEF_FIXED("sasyncperd2",R8A779G0_CLK_SASYNCPERD2, CLK_SASYNCPER,2, 1),
++ DEF_FIXED("sasyncperd4",R8A779G0_CLK_SASYNCPERD4, CLK_SASYNCPER,4, 1),
+ DEF_FIXED("svd1_ir", R8A779G0_CLK_SVD1_IR, CLK_SV_IR, 1, 1),
+ DEF_FIXED("svd2_ir", R8A779G0_CLK_SVD2_IR, CLK_SV_IR, 2, 1),
+ DEF_FIXED("svd1_vip", R8A779G0_CLK_SVD1_VIP, CLK_SV_VIP, 1, 1),
+@@ -150,10 +155,10 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
+ };
+
+ static const struct mssr_mod_clk r8a779g0_mod_clks[] __initconst = {
+- DEF_MOD("hscif0", 514, R8A779G0_CLK_S0D3_PER),
+- DEF_MOD("hscif1", 515, R8A779G0_CLK_S0D3_PER),
+- DEF_MOD("hscif2", 516, R8A779G0_CLK_S0D3_PER),
+- DEF_MOD("hscif3", 517, R8A779G0_CLK_S0D3_PER),
++ DEF_MOD("hscif0", 514, R8A779G0_CLK_SASYNCPERD1),
++ DEF_MOD("hscif1", 515, R8A779G0_CLK_SASYNCPERD1),
++ DEF_MOD("hscif2", 516, R8A779G0_CLK_SASYNCPERD1),
++ DEF_MOD("hscif3", 517, R8A779G0_CLK_SASYNCPERD1),
+ };
+
+ /*
+diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c
+index 1d12a8206444e..36aa5070d9024 100644
+--- a/drivers/cxl/core/pmem.c
++++ b/drivers/cxl/core/pmem.c
+@@ -188,6 +188,7 @@ static void cxl_nvdimm_release(struct device *dev)
+ {
+ struct cxl_nvdimm *cxl_nvd = to_cxl_nvdimm(dev);
+
++ xa_destroy(&cxl_nvd->pmem_regions);
+ kfree(cxl_nvd);
+ }
+
+@@ -230,6 +231,7 @@ static struct cxl_nvdimm *cxl_nvdimm_alloc(struct cxl_memdev *cxlmd)
+
+ dev = &cxl_nvd->dev;
+ cxl_nvd->cxlmd = cxlmd;
++ xa_init(&cxl_nvd->pmem_regions);
+ device_initialize(dev);
+ lockdep_set_class(&dev->mutex, &cxl_nvdimm_key);
+ device_set_pm_not_required(dev);
+diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
+index bffde862de0bf..e7556864ea808 100644
+--- a/drivers/cxl/core/port.c
++++ b/drivers/cxl/core/port.c
+@@ -811,6 +811,7 @@ static struct cxl_dport *find_dport(struct cxl_port *port, int id)
+ static int add_dport(struct cxl_port *port, struct cxl_dport *new)
+ {
+ struct cxl_dport *dup;
++ int rc;
+
+ device_lock_assert(&port->dev);
+ dup = find_dport(port, new->port_id);
+@@ -821,8 +822,14 @@ static int add_dport(struct cxl_port *port, struct cxl_dport *new)
+ dev_name(dup->dport));
+ return -EBUSY;
+ }
+- return xa_insert(&port->dports, (unsigned long)new->dport, new,
+- GFP_KERNEL);
++
++ rc = xa_insert(&port->dports, (unsigned long)new->dport, new,
++ GFP_KERNEL);
++ if (rc)
++ return rc;
++
++ port->nr_dports++;
++ return 0;
+ }
+
+ /*
+diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
+index 4011480169784..6b7fb955a05ac 100644
+--- a/drivers/cxl/core/region.c
++++ b/drivers/cxl/core/region.c
+@@ -657,6 +657,9 @@ static struct cxl_region_ref *alloc_region_ref(struct cxl_port *port,
+ xa_for_each(&port->regions, index, iter) {
+ struct cxl_region_params *ip = &iter->region->params;
+
++ if (!ip->res)
++ continue;
++
+ if (ip->res->start > p->res->start) {
+ dev_dbg(&cxlr->dev,
+ "%s: HPA order violation %s:%pr vs %pr\n",
+@@ -686,18 +689,27 @@ static struct cxl_region_ref *alloc_region_ref(struct cxl_port *port,
+ return cxl_rr;
+ }
+
+-static void free_region_ref(struct cxl_region_ref *cxl_rr)
++static void cxl_rr_free_decoder(struct cxl_region_ref *cxl_rr)
+ {
+- struct cxl_port *port = cxl_rr->port;
+ struct cxl_region *cxlr = cxl_rr->region;
+ struct cxl_decoder *cxld = cxl_rr->decoder;
+
++ if (!cxld)
++ return;
++
+ dev_WARN_ONCE(&cxlr->dev, cxld->region != cxlr, "region mismatch\n");
+ if (cxld->region == cxlr) {
+ cxld->region = NULL;
+ put_device(&cxlr->dev);
+ }
++}
++
++static void free_region_ref(struct cxl_region_ref *cxl_rr)
++{
++ struct cxl_port *port = cxl_rr->port;
++ struct cxl_region *cxlr = cxl_rr->region;
+
++ cxl_rr_free_decoder(cxl_rr);
+ xa_erase(&port->regions, (unsigned long)cxlr);
+ xa_destroy(&cxl_rr->endpoints);
+ kfree(cxl_rr);
+@@ -728,6 +740,33 @@ static int cxl_rr_ep_add(struct cxl_region_ref *cxl_rr,
+ return 0;
+ }
+
++static int cxl_rr_alloc_decoder(struct cxl_port *port, struct cxl_region *cxlr,
++ struct cxl_endpoint_decoder *cxled,
++ struct cxl_region_ref *cxl_rr)
++{
++ struct cxl_decoder *cxld;
++
++ if (port == cxled_to_port(cxled))
++ cxld = &cxled->cxld;
++ else
++ cxld = cxl_region_find_decoder(port, cxlr);
++ if (!cxld) {
++ dev_dbg(&cxlr->dev, "%s: no decoder available\n",
++ dev_name(&port->dev));
++ return -EBUSY;
++ }
++
++ if (cxld->region) {
++ dev_dbg(&cxlr->dev, "%s: %s already attached to %s\n",
++ dev_name(&port->dev), dev_name(&cxld->dev),
++ dev_name(&cxld->region->dev));
++ return -EBUSY;
++ }
++
++ cxl_rr->decoder = cxld;
++ return 0;
++}
++
+ /**
+ * cxl_port_attach_region() - track a region's interest in a port by endpoint
+ * @port: port to add a new region reference 'struct cxl_region_ref'
+@@ -794,12 +833,6 @@ static int cxl_port_attach_region(struct cxl_port *port,
+ cxl_rr->nr_targets++;
+ nr_targets_inc = true;
+ }
+-
+- /*
+- * The decoder for @cxlr was allocated when the region was first
+- * attached to @port.
+- */
+- cxld = cxl_rr->decoder;
+ } else {
+ cxl_rr = alloc_region_ref(port, cxlr);
+ if (IS_ERR(cxl_rr)) {
+@@ -810,26 +843,11 @@ static int cxl_port_attach_region(struct cxl_port *port,
+ }
+ nr_targets_inc = true;
+
+- if (port == cxled_to_port(cxled))
+- cxld = &cxled->cxld;
+- else
+- cxld = cxl_region_find_decoder(port, cxlr);
+- if (!cxld) {
+- dev_dbg(&cxlr->dev, "%s: no decoder available\n",
+- dev_name(&port->dev));
+- goto out_erase;
+- }
+-
+- if (cxld->region) {
+- dev_dbg(&cxlr->dev, "%s: %s already attached to %s\n",
+- dev_name(&port->dev), dev_name(&cxld->dev),
+- dev_name(&cxld->region->dev));
+- rc = -EBUSY;
++ rc = cxl_rr_alloc_decoder(port, cxlr, cxled, cxl_rr);
++ if (rc)
+ goto out_erase;
+- }
+-
+- cxl_rr->decoder = cxld;
+ }
++ cxld = cxl_rr->decoder;
+
+ rc = cxl_rr_ep_add(cxl_rr, cxled);
+ if (rc) {
+@@ -971,7 +989,14 @@ static int cxl_port_setup_targets(struct cxl_port *port,
+ if (cxl_rr->nr_targets_set) {
+ int i, distance;
+
+- distance = p->nr_targets / cxl_rr->nr_targets;
++ /*
++ * Passthrough ports impose no distance requirements between
++ * peers
++ */
++ if (port->nr_dports == 1)
++ distance = 0;
++ else
++ distance = p->nr_targets / cxl_rr->nr_targets;
+ for (i = 0; i < cxl_rr->nr_targets_set; i++)
+ if (ep->dport == cxlsd->target[i]) {
+ rc = check_last_peer(cxled, ep, cxl_rr,
+@@ -1538,8 +1563,19 @@ static struct cxl_region *to_cxl_region(struct device *dev)
+ static void unregister_region(void *dev)
+ {
+ struct cxl_region *cxlr = to_cxl_region(dev);
++ struct cxl_region_params *p = &cxlr->params;
++ int i;
+
+ device_del(dev);
++
++ /*
++ * Now that region sysfs is shutdown, the parameter block is now
++ * read-only, so no need to hold the region rwsem to access the
++ * region parameters.
++ */
++ for (i = 0; i < p->interleave_ways; i++)
++ detach_target(cxlr, i);
++
+ cxl_region_iomem_release(cxlr);
+ put_device(dev);
+ }
+diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
+index f680450f0b16c..ac75554b5d763 100644
+--- a/drivers/cxl/cxl.h
++++ b/drivers/cxl/cxl.h
+@@ -423,7 +423,7 @@ struct cxl_nvdimm {
+ struct device dev;
+ struct cxl_memdev *cxlmd;
+ struct cxl_nvdimm_bridge *bridge;
+- struct cxl_pmem_region *region;
++ struct xarray pmem_regions;
+ };
+
+ struct cxl_pmem_region_mapping {
+@@ -457,6 +457,7 @@ struct cxl_pmem_region {
+ * @regions: cxl_region_ref instances, regions mapped by this port
+ * @parent_dport: dport that points to this port in the parent
+ * @decoder_ida: allocator for decoder ids
++ * @nr_dports: number of entries in @dports
+ * @hdm_end: track last allocated HDM decoder instance for allocation ordering
+ * @commit_end: cursor to track highest committed decoder for commit ordering
+ * @component_reg_phys: component register capability base address (optional)
+@@ -475,6 +476,7 @@ struct cxl_port {
+ struct xarray regions;
+ struct cxl_dport *parent_dport;
+ struct ida decoder_ida;
++ int nr_dports;
+ int hdm_end;
+ int commit_end;
+ resource_size_t component_reg_phys;
+diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c
+index 7dc0a2fa1a6b6..faade12279f02 100644
+--- a/drivers/cxl/pmem.c
++++ b/drivers/cxl/pmem.c
+@@ -30,17 +30,20 @@ static void unregister_nvdimm(void *nvdimm)
+ struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
+ struct cxl_nvdimm_bridge *cxl_nvb = cxl_nvd->bridge;
+ struct cxl_pmem_region *cxlr_pmem;
++ unsigned long index;
+
+ device_lock(&cxl_nvb->dev);
+- cxlr_pmem = cxl_nvd->region;
+ dev_set_drvdata(&cxl_nvd->dev, NULL);
+- cxl_nvd->region = NULL;
+- device_unlock(&cxl_nvb->dev);
++ xa_for_each(&cxl_nvd->pmem_regions, index, cxlr_pmem) {
++ get_device(&cxlr_pmem->dev);
++ device_unlock(&cxl_nvb->dev);
+
+- if (cxlr_pmem) {
+ device_release_driver(&cxlr_pmem->dev);
+ put_device(&cxlr_pmem->dev);
++
++ device_lock(&cxl_nvb->dev);
+ }
++ device_unlock(&cxl_nvb->dev);
+
+ nvdimm_delete(nvdimm);
+ cxl_nvd->bridge = NULL;
+@@ -366,25 +369,49 @@ static int match_cxl_nvdimm(struct device *dev, void *data)
+
+ static void unregister_nvdimm_region(void *nd_region)
+ {
+- struct cxl_nvdimm_bridge *cxl_nvb;
+- struct cxl_pmem_region *cxlr_pmem;
++ nvdimm_region_delete(nd_region);
++}
++
++static int cxl_nvdimm_add_region(struct cxl_nvdimm *cxl_nvd,
++ struct cxl_pmem_region *cxlr_pmem)
++{
++ int rc;
++
++ rc = xa_insert(&cxl_nvd->pmem_regions, (unsigned long)cxlr_pmem,
++ cxlr_pmem, GFP_KERNEL);
++ if (rc)
++ return rc;
++
++ get_device(&cxlr_pmem->dev);
++ return 0;
++}
++
++static void cxl_nvdimm_del_region(struct cxl_nvdimm *cxl_nvd,
++ struct cxl_pmem_region *cxlr_pmem)
++{
++ /*
++ * It is possible this is called without a corresponding
++ * cxl_nvdimm_add_region for @cxlr_pmem
++ */
++ cxlr_pmem = xa_erase(&cxl_nvd->pmem_regions, (unsigned long)cxlr_pmem);
++ if (cxlr_pmem)
++ put_device(&cxlr_pmem->dev);
++}
++
++static void release_mappings(void *data)
++{
+ int i;
++ struct cxl_pmem_region *cxlr_pmem = data;
++ struct cxl_nvdimm_bridge *cxl_nvb = cxlr_pmem->bridge;
+
+- cxlr_pmem = nd_region_provider_data(nd_region);
+- cxl_nvb = cxlr_pmem->bridge;
+ device_lock(&cxl_nvb->dev);
+ for (i = 0; i < cxlr_pmem->nr_mappings; i++) {
+ struct cxl_pmem_region_mapping *m = &cxlr_pmem->mapping[i];
+ struct cxl_nvdimm *cxl_nvd = m->cxl_nvd;
+
+- if (cxl_nvd->region) {
+- put_device(&cxlr_pmem->dev);
+- cxl_nvd->region = NULL;
+- }
++ cxl_nvdimm_del_region(cxl_nvd, cxlr_pmem);
+ }
+ device_unlock(&cxl_nvb->dev);
+-
+- nvdimm_region_delete(nd_region);
+ }
+
+ static void cxlr_pmem_remove_resource(void *res)
+@@ -422,7 +449,7 @@ static int cxl_pmem_region_probe(struct device *dev)
+ if (!cxl_nvb->nvdimm_bus) {
+ dev_dbg(dev, "nvdimm bus not found\n");
+ rc = -ENXIO;
+- goto err;
++ goto out_nvb;
+ }
+
+ memset(&mappings, 0, sizeof(mappings));
+@@ -431,7 +458,7 @@ static int cxl_pmem_region_probe(struct device *dev)
+ res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
+ if (!res) {
+ rc = -ENOMEM;
+- goto err;
++ goto out_nvb;
+ }
+
+ res->name = "Persistent Memory";
+@@ -442,11 +469,11 @@ static int cxl_pmem_region_probe(struct device *dev)
+
+ rc = insert_resource(&iomem_resource, res);
+ if (rc)
+- goto err;
++ goto out_nvb;
+
+ rc = devm_add_action_or_reset(dev, cxlr_pmem_remove_resource, res);
+ if (rc)
+- goto err;
++ goto out_nvb;
+
+ ndr_desc.res = res;
+ ndr_desc.provider_data = cxlr_pmem;
+@@ -462,7 +489,7 @@ static int cxl_pmem_region_probe(struct device *dev)
+ nd_set = devm_kzalloc(dev, sizeof(*nd_set), GFP_KERNEL);
+ if (!nd_set) {
+ rc = -ENOMEM;
+- goto err;
++ goto out_nvb;
+ }
+
+ ndr_desc.memregion = cxlr->id;
+@@ -472,9 +499,13 @@ static int cxl_pmem_region_probe(struct device *dev)
+ info = kmalloc_array(cxlr_pmem->nr_mappings, sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ rc = -ENOMEM;
+- goto err;
++ goto out_nvb;
+ }
+
++ rc = devm_add_action_or_reset(dev, release_mappings, cxlr_pmem);
++ if (rc)
++ goto out_nvd;
++
+ for (i = 0; i < cxlr_pmem->nr_mappings; i++) {
+ struct cxl_pmem_region_mapping *m = &cxlr_pmem->mapping[i];
+ struct cxl_memdev *cxlmd = m->cxlmd;
+@@ -486,7 +517,7 @@ static int cxl_pmem_region_probe(struct device *dev)
+ dev_dbg(dev, "[%d]: %s: no cxl_nvdimm found\n", i,
+ dev_name(&cxlmd->dev));
+ rc = -ENODEV;
+- goto err;
++ goto out_nvd;
+ }
+
+ /* safe to drop ref now with bridge lock held */
+@@ -498,10 +529,17 @@ static int cxl_pmem_region_probe(struct device *dev)
+ dev_dbg(dev, "[%d]: %s: no nvdimm found\n", i,
+ dev_name(&cxlmd->dev));
+ rc = -ENODEV;
+- goto err;
++ goto out_nvd;
+ }
+- cxl_nvd->region = cxlr_pmem;
+- get_device(&cxlr_pmem->dev);
++
++ /*
++ * Pin the region per nvdimm device as those may be released
++ * out-of-order with respect to the region, and a single nvdimm
++ * maybe associated with multiple regions
++ */
++ rc = cxl_nvdimm_add_region(cxl_nvd, cxlr_pmem);
++ if (rc)
++ goto out_nvd;
+ m->cxl_nvd = cxl_nvd;
+ mappings[i] = (struct nd_mapping_desc) {
+ .nvdimm = nvdimm,
+@@ -527,27 +565,18 @@ static int cxl_pmem_region_probe(struct device *dev)
+ nvdimm_pmem_region_create(cxl_nvb->nvdimm_bus, &ndr_desc);
+ if (!cxlr_pmem->nd_region) {
+ rc = -ENOMEM;
+- goto err;
++ goto out_nvd;
+ }
+
+ rc = devm_add_action_or_reset(dev, unregister_nvdimm_region,
+ cxlr_pmem->nd_region);
+-out:
++out_nvd:
+ kfree(info);
++out_nvb:
+ device_unlock(&cxl_nvb->dev);
+ put_device(&cxl_nvb->dev);
+
+ return rc;
+-
+-err:
+- dev_dbg(dev, "failed to create nvdimm region\n");
+- for (i--; i >= 0; i--) {
+- nvdimm = mappings[i].nvdimm;
+- cxl_nvd = nvdimm_provider_data(nvdimm);
+- put_device(&cxl_nvd->region->dev);
+- cxl_nvd->region = NULL;
+- }
+- goto out;
+ }
+
+ static struct cxl_driver cxl_pmem_region_driver = {
+diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
+index 609ebedee9cb6..9022f5ee29aa8 100644
+--- a/drivers/firmware/arm_scmi/driver.c
++++ b/drivers/firmware/arm_scmi/driver.c
+@@ -2044,8 +2044,12 @@ scmi_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id)
+ {
+ int ret = scmi_chan_setup(info, dev, prot_id, true);
+
+- if (!ret) /* Rx is optional, hence no error check */
+- scmi_chan_setup(info, dev, prot_id, false);
++ if (!ret) {
++ /* Rx is optional, report only memory errors */
++ ret = scmi_chan_setup(info, dev, prot_id, false);
++ if (ret && ret != -ENOMEM)
++ ret = 0;
++ }
+
+ return ret;
+ }
+@@ -2571,6 +2575,7 @@ MODULE_DEVICE_TABLE(of, scmi_of_match);
+ static struct platform_driver scmi_driver = {
+ .driver = {
+ .name = "arm-scmi",
++ .suppress_bind_attrs = true,
+ .of_match_table = scmi_of_match,
+ .dev_groups = versions_groups,
+ },
+diff --git a/drivers/firmware/arm_scmi/virtio.c b/drivers/firmware/arm_scmi/virtio.c
+index 14709dbc96a1a..33c9b81a55cd1 100644
+--- a/drivers/firmware/arm_scmi/virtio.c
++++ b/drivers/firmware/arm_scmi/virtio.c
+@@ -148,7 +148,6 @@ static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch)
+ {
+ unsigned long flags;
+ DECLARE_COMPLETION_ONSTACK(vioch_shutdown_done);
+- void *deferred_wq = NULL;
+
+ /*
+ * Prepare to wait for the last release if not already released
+@@ -162,16 +161,11 @@ static void scmi_vio_channel_cleanup_sync(struct scmi_vio_channel *vioch)
+
+ vioch->shutdown_done = &vioch_shutdown_done;
+ virtio_break_device(vioch->vqueue->vdev);
+- if (!vioch->is_rx && vioch->deferred_tx_wq) {
+- deferred_wq = vioch->deferred_tx_wq;
++ if (!vioch->is_rx && vioch->deferred_tx_wq)
+ /* Cannot be kicked anymore after this...*/
+ vioch->deferred_tx_wq = NULL;
+- }
+ spin_unlock_irqrestore(&vioch->lock, flags);
+
+- if (deferred_wq)
+- destroy_workqueue(deferred_wq);
+-
+ scmi_vio_channel_release(vioch);
+
+ /* Let any possibly concurrent RX path release the channel */
+@@ -416,6 +410,11 @@ static bool virtio_chan_available(struct device *dev, int idx)
+ return vioch && !vioch->cinfo;
+ }
+
++static void scmi_destroy_tx_workqueue(void *deferred_tx_wq)
++{
++ destroy_workqueue(deferred_tx_wq);
++}
++
+ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
+ bool tx)
+ {
+@@ -430,6 +429,8 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
+
+ /* Setup a deferred worker for polling. */
+ if (tx && !vioch->deferred_tx_wq) {
++ int ret;
++
+ vioch->deferred_tx_wq =
+ alloc_workqueue(dev_name(&scmi_vdev->dev),
+ WQ_UNBOUND | WQ_FREEZABLE | WQ_SYSFS,
+@@ -437,6 +438,11 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
+ if (!vioch->deferred_tx_wq)
+ return -ENOMEM;
+
++ ret = devm_add_action_or_reset(dev, scmi_destroy_tx_workqueue,
++ vioch->deferred_tx_wq);
++ if (ret)
++ return ret;
++
+ INIT_WORK(&vioch->deferred_tx_work,
+ scmi_vio_deferred_tx_worker);
+ }
+@@ -444,12 +450,12 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
+ for (i = 0; i < vioch->max_msg; i++) {
+ struct scmi_vio_msg *msg;
+
+- msg = devm_kzalloc(cinfo->dev, sizeof(*msg), GFP_KERNEL);
++ msg = devm_kzalloc(dev, sizeof(*msg), GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ if (tx) {
+- msg->request = devm_kzalloc(cinfo->dev,
++ msg->request = devm_kzalloc(dev,
+ VIRTIO_SCMI_MAX_PDU_SIZE,
+ GFP_KERNEL);
+ if (!msg->request)
+@@ -458,7 +464,7 @@ static int virtio_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
+ refcount_set(&msg->users, 1);
+ }
+
+- msg->input = devm_kzalloc(cinfo->dev, VIRTIO_SCMI_MAX_PDU_SIZE,
++ msg->input = devm_kzalloc(dev, VIRTIO_SCMI_MAX_PDU_SIZE,
+ GFP_KERNEL);
+ if (!msg->input)
+ return -ENOMEM;
+diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
+index aa6d109fac08b..a06decee51e06 100644
+--- a/drivers/firmware/efi/efi.c
++++ b/drivers/firmware/efi/efi.c
+@@ -608,7 +608,7 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
+
+ seed = early_memremap(efi_rng_seed, sizeof(*seed));
+ if (seed != NULL) {
+- size = READ_ONCE(seed->size);
++ size = min(seed->size, EFI_RANDOM_SEED_SIZE);
+ early_memunmap(seed, sizeof(*seed));
+ } else {
+ pr_err("Could not map UEFI random seed!\n");
+diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
+index 24aa375353724..33ab567695951 100644
+--- a/drivers/firmware/efi/libstub/random.c
++++ b/drivers/firmware/efi/libstub/random.c
+@@ -75,7 +75,12 @@ efi_status_t efi_random_get_seed(void)
+ if (status != EFI_SUCCESS)
+ return status;
+
+- status = efi_bs_call(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
++ /*
++ * Use EFI_ACPI_RECLAIM_MEMORY here so that it is guaranteed that the
++ * allocation will survive a kexec reboot (although we refresh the seed
++ * beforehand)
++ */
++ status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
+ sizeof(*seed) + EFI_RANDOM_SEED_SIZE,
+ (void **)&seed);
+ if (status != EFI_SUCCESS)
+diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c
+index 8f665678e9e39..e8d69bd548f3f 100644
+--- a/drivers/firmware/efi/tpm.c
++++ b/drivers/firmware/efi/tpm.c
+@@ -97,7 +97,7 @@ int __init efi_tpm_eventlog_init(void)
+ goto out_calc;
+ }
+
+- memblock_reserve((unsigned long)final_tbl,
++ memblock_reserve(efi.tpm_final_log,
+ tbl_size + sizeof(*final_tbl));
+ efi_tpm_final_log_size = tbl_size;
+
+diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c
+index 433b615871395..0ba9f18312f5b 100644
+--- a/drivers/firmware/efi/vars.c
++++ b/drivers/firmware/efi/vars.c
+@@ -21,29 +21,22 @@ static struct efivars *__efivars;
+
+ static DEFINE_SEMAPHORE(efivars_lock);
+
+-static efi_status_t check_var_size(u32 attributes, unsigned long size)
+-{
+- const struct efivar_operations *fops;
+-
+- fops = __efivars->ops;
+-
+- if (!fops->query_variable_store)
+- return (size <= SZ_64K) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
+-
+- return fops->query_variable_store(attributes, size, false);
+-}
+-
+-static
+-efi_status_t check_var_size_nonblocking(u32 attributes, unsigned long size)
++static efi_status_t check_var_size(bool nonblocking, u32 attributes,
++ unsigned long size)
+ {
+ const struct efivar_operations *fops;
++ efi_status_t status;
+
+ fops = __efivars->ops;
+
+ if (!fops->query_variable_store)
++ status = EFI_UNSUPPORTED;
++ else
++ status = fops->query_variable_store(attributes, size,
++ nonblocking);
++ if (status == EFI_UNSUPPORTED)
+ return (size <= SZ_64K) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
+-
+- return fops->query_variable_store(attributes, size, true);
++ return status;
+ }
+
+ /**
+@@ -195,26 +188,6 @@ efi_status_t efivar_get_next_variable(unsigned long *name_size,
+ }
+ EXPORT_SYMBOL_NS_GPL(efivar_get_next_variable, EFIVAR);
+
+-/*
+- * efivar_set_variable_blocking() - local helper function for set_variable
+- *
+- * Must be called with efivars_lock held.
+- */
+-static efi_status_t
+-efivar_set_variable_blocking(efi_char16_t *name, efi_guid_t *vendor,
+- u32 attr, unsigned long data_size, void *data)
+-{
+- efi_status_t status;
+-
+- if (data_size > 0) {
+- status = check_var_size(attr, data_size +
+- ucs2_strsize(name, 1024));
+- if (status != EFI_SUCCESS)
+- return status;
+- }
+- return __efivars->ops->set_variable(name, vendor, attr, data_size, data);
+-}
+-
+ /*
+ * efivar_set_variable_locked() - set a variable identified by name/vendor
+ *
+@@ -228,23 +201,21 @@ efi_status_t efivar_set_variable_locked(efi_char16_t *name, efi_guid_t *vendor,
+ efi_set_variable_t *setvar;
+ efi_status_t status;
+
+- if (!nonblocking)
+- return efivar_set_variable_blocking(name, vendor, attr,
+- data_size, data);
++ if (data_size > 0) {
++ status = check_var_size(nonblocking, attr,
++ data_size + ucs2_strsize(name, 1024));
++ if (status != EFI_SUCCESS)
++ return status;
++ }
+
+ /*
+ * If no _nonblocking variant exists, the ordinary one
+ * is assumed to be non-blocking.
+ */
+- setvar = __efivars->ops->set_variable_nonblocking ?:
+- __efivars->ops->set_variable;
++ setvar = __efivars->ops->set_variable_nonblocking;
++ if (!setvar || !nonblocking)
++ setvar = __efivars->ops->set_variable;
+
+- if (data_size > 0) {
+- status = check_var_size_nonblocking(attr, data_size +
+- ucs2_strsize(name, 1024));
+- if (status != EFI_SUCCESS)
+- return status;
+- }
+ return setvar(name, vendor, attr, data_size, data);
+ }
+ EXPORT_SYMBOL_NS_GPL(efivar_set_variable_locked, EFIVAR);
+@@ -264,7 +235,8 @@ efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor,
+ if (efivar_lock())
+ return EFI_ABORTED;
+
+- status = efivar_set_variable_blocking(name, vendor, attr, data_size, data);
++ status = efivar_set_variable_locked(name, vendor, attr, data_size,
++ data, false);
+ efivar_unlock();
+ return status;
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+index 5e53a52939356..0d939f07d5061 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+@@ -703,6 +703,13 @@ err:
+
+ void amdgpu_amdkfd_set_compute_idle(struct amdgpu_device *adev, bool idle)
+ {
++ /* Temporary workaround to fix issues observed in some
++ * compute applications when GFXOFF is enabled on GFX11.
++ */
++ if (IP_VERSION_MAJ(adev->ip_versions[GC_HWIP][0]) == 11) {
++ pr_debug("GFXOFF is %s\n", idle ? "enabled" : "disabled");
++ amdgpu_gfx_off_ctrl(adev, idle);
++ }
+ amdgpu_dpm_switch_power_profile(adev,
+ PP_SMC_POWER_PROFILE_COMPUTE,
+ !idle);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c
+index 0b0a72ca56956..7e80caa05060b 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v11.c
+@@ -111,7 +111,7 @@ static int init_interrupts_v11(struct amdgpu_device *adev, uint32_t pipe_id)
+
+ lock_srbm(adev, mec, pipe, 0, 0);
+
+- WREG32(SOC15_REG_OFFSET(GC, 0, regCPC_INT_CNTL),
++ WREG32_SOC15(GC, 0, regCPC_INT_CNTL,
+ CP_INT_CNTL_RING0__TIME_STAMP_INT_ENABLE_MASK |
+ CP_INT_CNTL_RING0__OPCODE_ERROR_INT_ENABLE_MASK);
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+index 9be57389301b4..af5aeb0ec2e92 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+@@ -726,6 +726,12 @@ void amdgpu_detect_virtualization(struct amdgpu_device *adev)
+ adev->virt.caps |= AMDGPU_PASSTHROUGH_MODE;
+ }
+
++ if (amdgpu_sriov_vf(adev) && adev->asic_type == CHIP_SIENNA_CICHLID)
++ /* VF MMIO access (except mailbox range) from CPU
++ * will be blocked during sriov runtime
++ */
++ adev->virt.caps |= AMDGPU_VF_MMIO_ACCESS_PROTECT;
++
+ /* we have the ability to check now */
+ if (amdgpu_sriov_vf(adev)) {
+ switch (adev->asic_type) {
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
+index 239f232f9c026..617d072275ebe 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
+@@ -31,6 +31,7 @@
+ #define AMDGPU_SRIOV_CAPS_IS_VF (1 << 2) /* this GPU is a virtual function */
+ #define AMDGPU_PASSTHROUGH_MODE (1 << 3) /* thw whole GPU is pass through for VM */
+ #define AMDGPU_SRIOV_CAPS_RUNTIME (1 << 4) /* is out of full access mode */
++#define AMDGPU_VF_MMIO_ACCESS_PROTECT (1 << 5) /* MMIO write access is not allowed in sriov runtime */
+
+ /* flags for indirect register access path supported by rlcg for sriov */
+ #define AMDGPU_RLCG_GC_WRITE_LEGACY (0x8 << 28)
+@@ -294,6 +295,9 @@ struct amdgpu_video_codec_info;
+ #define amdgpu_passthrough(adev) \
+ ((adev)->virt.caps & AMDGPU_PASSTHROUGH_MODE)
+
++#define amdgpu_sriov_vf_mmio_access_protection(adev) \
++((adev)->virt.caps & AMDGPU_VF_MMIO_ACCESS_PROTECT)
++
+ static inline bool is_virtual_machine(void)
+ {
+ #if defined(CONFIG_X86)
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+index 690fd4f639f19..04130f8813ef1 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+@@ -2301,7 +2301,11 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
+ */
+ #ifdef CONFIG_X86_64
+ if (amdgpu_vm_update_mode == -1) {
+- if (amdgpu_gmc_vram_full_visible(&adev->gmc))
++ /* For asic with VF MMIO access protection
++ * avoid using CPU for VM table updates
++ */
++ if (amdgpu_gmc_vram_full_visible(&adev->gmc) &&
++ !amdgpu_sriov_vf_mmio_access_protection(adev))
+ adev->vm_manager.vm_update_mode =
+ AMDGPU_VM_USE_CPU_FOR_COMPUTE;
+ else
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+index daf8ba8235cd0..03775e0a81004 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+@@ -1729,7 +1729,7 @@ static void gfx_v11_0_init_compute_vmid(struct amdgpu_device *adev)
+ WREG32_SOC15(GC, 0, regSH_MEM_BASES, sh_mem_bases);
+
+ /* Enable trap for each kfd vmid. */
+- data = RREG32(SOC15_REG_OFFSET(GC, 0, regSPI_GDBG_PER_VMID_CNTL));
++ data = RREG32_SOC15(GC, 0, regSPI_GDBG_PER_VMID_CNTL);
+ data = REG_SET_FIELD(data, SPI_GDBG_PER_VMID_CNTL, TRAP_EN, 1);
+ }
+ soc21_grbm_select(adev, 0, 0, 0, 0);
+diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+index 1471bfb9ae38e..2475fdbe80104 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+@@ -185,6 +185,10 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
+ /* Use register 17 for GART */
+ const unsigned eng = 17;
+ unsigned int i;
++ unsigned char hub_ip = 0;
++
++ hub_ip = (vmhub == AMDGPU_GFXHUB_0) ?
++ GC_HWIP : MMHUB_HWIP;
+
+ spin_lock(&adev->gmc.invalidate_lock);
+ /*
+@@ -198,8 +202,8 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
+ if (use_semaphore) {
+ for (i = 0; i < adev->usec_timeout; i++) {
+ /* a read return value of 1 means semaphore acuqire */
+- tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem +
+- hub->eng_distance * eng);
++ tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem +
++ hub->eng_distance * eng, hub_ip);
+ if (tmp & 0x1)
+ break;
+ udelay(1);
+@@ -209,12 +213,12 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
+ DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
+ }
+
+- WREG32_NO_KIQ(hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req);
++ WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req, hub_ip);
+
+ /* Wait for ACK with a delay.*/
+ for (i = 0; i < adev->usec_timeout; i++) {
+- tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_ack +
+- hub->eng_distance * eng);
++ tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_ack +
++ hub->eng_distance * eng, hub_ip);
+ tmp &= 1 << vmid;
+ if (tmp)
+ break;
+@@ -228,8 +232,8 @@ static void gmc_v11_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
+ * add semaphore release after invalidation,
+ * write with 0 means semaphore release
+ */
+- WREG32_NO_KIQ(hub->vm_inv_eng0_sem +
+- hub->eng_distance * eng, 0);
++ WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem +
++ hub->eng_distance * eng, 0, hub_ip);
+
+ /* Issue additional private vm invalidation to MMHUB */
+ if ((vmhub != AMDGPU_GFXHUB_0) &&
+diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+index f92744b8d79df..2dd827472d6e4 100644
+--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+@@ -1145,6 +1145,42 @@ static int mes_v11_0_sw_fini(void *handle)
+ return 0;
+ }
+
++static void mes_v11_0_kiq_dequeue_sched(struct amdgpu_device *adev)
++{
++ uint32_t data;
++ int i;
++
++ mutex_lock(&adev->srbm_mutex);
++ soc21_grbm_select(adev, 3, AMDGPU_MES_SCHED_PIPE, 0, 0);
++
++ /* disable the queue if it's active */
++ if (RREG32_SOC15(GC, 0, regCP_HQD_ACTIVE) & 1) {
++ WREG32_SOC15(GC, 0, regCP_HQD_DEQUEUE_REQUEST, 1);
++ for (i = 0; i < adev->usec_timeout; i++) {
++ if (!(RREG32_SOC15(GC, 0, regCP_HQD_ACTIVE) & 1))
++ break;
++ udelay(1);
++ }
++ }
++ data = RREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL);
++ data = REG_SET_FIELD(data, CP_HQD_PQ_DOORBELL_CONTROL,
++ DOORBELL_EN, 0);
++ data = REG_SET_FIELD(data, CP_HQD_PQ_DOORBELL_CONTROL,
++ DOORBELL_HIT, 1);
++ WREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL, data);
++
++ WREG32_SOC15(GC, 0, regCP_HQD_PQ_DOORBELL_CONTROL, 0);
++
++ WREG32_SOC15(GC, 0, regCP_HQD_PQ_WPTR_LO, 0);
++ WREG32_SOC15(GC, 0, regCP_HQD_PQ_WPTR_HI, 0);
++ WREG32_SOC15(GC, 0, regCP_HQD_PQ_RPTR, 0);
++
++ soc21_grbm_select(adev, 0, 0, 0, 0);
++ mutex_unlock(&adev->srbm_mutex);
++
++ adev->mes.ring.sched.ready = false;
++}
++
+ static void mes_v11_0_kiq_setting(struct amdgpu_ring *ring)
+ {
+ uint32_t tmp;
+@@ -1196,6 +1232,9 @@ failure:
+
+ static int mes_v11_0_kiq_hw_fini(struct amdgpu_device *adev)
+ {
++ if (adev->mes.ring.sched.ready)
++ mes_v11_0_kiq_dequeue_sched(adev);
++
+ mes_v11_0_enable(adev, false);
+ return 0;
+ }
+@@ -1251,9 +1290,6 @@ failure:
+
+ static int mes_v11_0_hw_fini(void *handle)
+ {
+- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+-
+- adev->mes.ring.sched.ready = false;
+ return 0;
+ }
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
+index 6d721fadcbee6..7f5e039893e89 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
+@@ -847,7 +847,7 @@ static const struct resource_caps res_cap_dcn314 = {
+ .num_ddc = 5,
+ .num_vmid = 16,
+ .num_mpc_3dlut = 2,
+- .num_dsc = 3,
++ .num_dsc = 4,
+ };
+
+ static const struct dc_plane_cap plane_cap = {
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
+index b6369758b4912..aa976fe4d426d 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn321/dcn321_fpu.c
+@@ -119,15 +119,15 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_21_soc = {
+ },
+ },
+ .num_states = 1,
+- .sr_exit_time_us = 12.36,
+- .sr_enter_plus_exit_time_us = 16.72,
++ .sr_exit_time_us = 19.95,
++ .sr_enter_plus_exit_time_us = 24.36,
+ .sr_exit_z8_time_us = 285.0,
+ .sr_enter_plus_exit_z8_time_us = 320,
+ .writeback_latency_us = 12.0,
+ .round_trip_ping_latency_dcfclk_cycles = 263,
+- .urgent_latency_pixel_data_only_us = 4.0,
+- .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
+- .urgent_latency_vm_data_only_us = 4.0,
++ .urgent_latency_pixel_data_only_us = 9.35,
++ .urgent_latency_pixel_mixed_with_vm_data_us = 9.35,
++ .urgent_latency_vm_data_only_us = 9.35,
+ .fclk_change_latency_us = 20,
+ .usr_retraining_latency_us = 2,
+ .smn_latency_us = 2,
+diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
+index e85364dff4e04..5cb3e8634739d 100644
+--- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
++++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h
+@@ -262,8 +262,9 @@ struct kfd2kgd_calls {
+ uint32_t queue_id);
+
+ int (*hqd_destroy)(struct amdgpu_device *adev, void *mqd,
+- uint32_t reset_type, unsigned int timeout,
+- uint32_t pipe_id, uint32_t queue_id);
++ enum kfd_preempt_type reset_type,
++ unsigned int timeout, uint32_t pipe_id,
++ uint32_t queue_id);
+
+ bool (*hqd_sdma_is_occupied)(struct amdgpu_device *adev, void *mqd);
+
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
+index 93f9b8377539a..750d8da84fac4 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
+@@ -210,7 +210,8 @@ int smu_v13_0_init_pptable_microcode(struct smu_context *smu)
+ return 0;
+
+ if ((adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 7)) ||
+- (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0)))
++ (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 0)) ||
++ (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 10)))
+ return 0;
+
+ /* override pptable_id from driver parameter */
+diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
+index 19122bc6d2aba..b5f65b093c106 100644
+--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
++++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
+@@ -2747,13 +2747,10 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
+ if (!intel_sdvo_connector)
+ return false;
+
+- if (device == 0) {
+- intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS0;
++ if (device == 0)
+ intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS0;
+- } else if (device == 1) {
+- intel_sdvo->controlled_output |= SDVO_OUTPUT_TMDS1;
++ else if (device == 1)
+ intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS1;
+- }
+
+ intel_connector = &intel_sdvo_connector->base;
+ connector = &intel_connector->base;
+@@ -2808,7 +2805,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
+ encoder->encoder_type = DRM_MODE_ENCODER_TVDAC;
+ connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO;
+
+- intel_sdvo->controlled_output |= type;
+ intel_sdvo_connector->output_flag = type;
+
+ if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
+@@ -2849,13 +2845,10 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
+ encoder->encoder_type = DRM_MODE_ENCODER_DAC;
+ connector->connector_type = DRM_MODE_CONNECTOR_VGA;
+
+- if (device == 0) {
+- intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB0;
++ if (device == 0)
+ intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB0;
+- } else if (device == 1) {
+- intel_sdvo->controlled_output |= SDVO_OUTPUT_RGB1;
++ else if (device == 1)
+ intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
+- }
+
+ if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
+ kfree(intel_sdvo_connector);
+@@ -2885,13 +2878,10 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
+ encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
+ connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
+
+- if (device == 0) {
+- intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS0;
++ if (device == 0)
+ intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0;
+- } else if (device == 1) {
+- intel_sdvo->controlled_output |= SDVO_OUTPUT_LVDS1;
++ else if (device == 1)
+ intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
+- }
+
+ if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
+ kfree(intel_sdvo_connector);
+@@ -2926,16 +2916,39 @@ err:
+ return false;
+ }
+
++static u16 intel_sdvo_filter_output_flags(u16 flags)
++{
++ flags &= SDVO_OUTPUT_MASK;
++
++ /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/
++ if (!(flags & SDVO_OUTPUT_TMDS0))
++ flags &= ~SDVO_OUTPUT_TMDS1;
++
++ if (!(flags & SDVO_OUTPUT_RGB0))
++ flags &= ~SDVO_OUTPUT_RGB1;
++
++ if (!(flags & SDVO_OUTPUT_LVDS0))
++ flags &= ~SDVO_OUTPUT_LVDS1;
++
++ return flags;
++}
++
+ static bool
+ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags)
+ {
+- /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/
++ struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev);
++
++ flags = intel_sdvo_filter_output_flags(flags);
++
++ intel_sdvo->controlled_output = flags;
++
++ intel_sdvo_select_ddc_bus(i915, intel_sdvo);
+
+ if (flags & SDVO_OUTPUT_TMDS0)
+ if (!intel_sdvo_dvi_init(intel_sdvo, 0))
+ return false;
+
+- if ((flags & SDVO_TMDS_MASK) == SDVO_TMDS_MASK)
++ if (flags & SDVO_OUTPUT_TMDS1)
+ if (!intel_sdvo_dvi_init(intel_sdvo, 1))
+ return false;
+
+@@ -2956,7 +2969,7 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags)
+ if (!intel_sdvo_analog_init(intel_sdvo, 0))
+ return false;
+
+- if ((flags & SDVO_RGB_MASK) == SDVO_RGB_MASK)
++ if (flags & SDVO_OUTPUT_RGB1)
+ if (!intel_sdvo_analog_init(intel_sdvo, 1))
+ return false;
+
+@@ -2964,14 +2977,13 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags)
+ if (!intel_sdvo_lvds_init(intel_sdvo, 0))
+ return false;
+
+- if ((flags & SDVO_LVDS_MASK) == SDVO_LVDS_MASK)
++ if (flags & SDVO_OUTPUT_LVDS1)
+ if (!intel_sdvo_lvds_init(intel_sdvo, 1))
+ return false;
+
+- if ((flags & SDVO_OUTPUT_MASK) == 0) {
++ if (flags == 0) {
+ unsigned char bytes[2];
+
+- intel_sdvo->controlled_output = 0;
+ memcpy(bytes, &intel_sdvo->caps.output_flags, 2);
+ DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n",
+ SDVO_NAME(intel_sdvo),
+@@ -3383,8 +3395,6 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
+ */
+ intel_sdvo->base.cloneable = 0;
+
+- intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo);
+-
+ /* Set the input timing to the screen. Assume always input 0. */
+ if (!intel_sdvo_set_target_input(intel_sdvo))
+ goto err_output;
+diff --git a/drivers/gpu/drm/i915/gem/i915_gem_internal.c b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
+index c698f95af15fe..629acb403a2c9 100644
+--- a/drivers/gpu/drm/i915/gem/i915_gem_internal.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
+@@ -6,7 +6,6 @@
+
+ #include <linux/scatterlist.h>
+ #include <linux/slab.h>
+-#include <linux/swiotlb.h>
+
+ #include "i915_drv.h"
+ #include "i915_gem.h"
+@@ -38,22 +37,12 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
+ struct scatterlist *sg;
+ unsigned int sg_page_sizes;
+ unsigned int npages;
+- int max_order;
++ int max_order = MAX_ORDER;
++ unsigned int max_segment;
+ gfp_t gfp;
+
+- max_order = MAX_ORDER;
+-#ifdef CONFIG_SWIOTLB
+- if (is_swiotlb_active(obj->base.dev->dev)) {
+- unsigned int max_segment;
+-
+- max_segment = swiotlb_max_segment();
+- if (max_segment) {
+- max_segment = max_t(unsigned int, max_segment,
+- PAGE_SIZE) >> PAGE_SHIFT;
+- max_order = min(max_order, ilog2(max_segment));
+- }
+- }
+-#endif
++ max_segment = i915_sg_segment_size(i915->drm.dev) >> PAGE_SHIFT;
++ max_order = min(max_order, get_order(max_segment));
+
+ gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_RECLAIMABLE;
+ if (IS_I965GM(i915) || IS_I965G(i915)) {
+diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+index 4eed3dd90ba8b..34b9c76cd8e66 100644
+--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+@@ -194,7 +194,7 @@ static int shmem_get_pages(struct drm_i915_gem_object *obj)
+ struct intel_memory_region *mem = obj->mm.region;
+ struct address_space *mapping = obj->base.filp->f_mapping;
+ const unsigned long page_count = obj->base.size / PAGE_SIZE;
+- unsigned int max_segment = i915_sg_segment_size();
++ unsigned int max_segment = i915_sg_segment_size(i915->drm.dev);
+ struct sg_table *st;
+ struct sgt_iter sgt_iter;
+ struct page *page;
+diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+index 6f3ab7ade41ad..e85cfc36359a4 100644
+--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+@@ -189,7 +189,7 @@ static int i915_ttm_tt_shmem_populate(struct ttm_device *bdev,
+ struct drm_i915_private *i915 = container_of(bdev, typeof(*i915), bdev);
+ struct intel_memory_region *mr = i915->mm.regions[INTEL_MEMORY_SYSTEM];
+ struct i915_ttm_tt *i915_tt = container_of(ttm, typeof(*i915_tt), ttm);
+- const unsigned int max_segment = i915_sg_segment_size();
++ const unsigned int max_segment = i915_sg_segment_size(i915->drm.dev);
+ const size_t size = (size_t)ttm->num_pages << PAGE_SHIFT;
+ struct file *filp = i915_tt->filp;
+ struct sgt_iter sgt_iter;
+@@ -568,7 +568,7 @@ static struct i915_refct_sgt *i915_ttm_tt_get_st(struct ttm_tt *ttm)
+ ret = sg_alloc_table_from_pages_segment(st,
+ ttm->pages, ttm->num_pages,
+ 0, (unsigned long)ttm->num_pages << PAGE_SHIFT,
+- i915_sg_segment_size(), GFP_KERNEL);
++ i915_sg_segment_size(i915_tt->dev), GFP_KERNEL);
+ if (ret) {
+ st->sgl = NULL;
+ return ERR_PTR(ret);
+diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+index 8423df021b713..e4515d6acd43c 100644
+--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+@@ -129,7 +129,7 @@ static void i915_gem_object_userptr_drop_ref(struct drm_i915_gem_object *obj)
+ static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
+ {
+ const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
+- unsigned int max_segment = i915_sg_segment_size();
++ unsigned int max_segment = i915_sg_segment_size(obj->base.dev->dev);
+ struct sg_table *st;
+ unsigned int sg_page_sizes;
+ struct page **pvec;
+diff --git a/drivers/gpu/drm/i915/i915_scatterlist.h b/drivers/gpu/drm/i915/i915_scatterlist.h
+index 9ddb3e743a3e5..b0a1db44f8950 100644
+--- a/drivers/gpu/drm/i915/i915_scatterlist.h
++++ b/drivers/gpu/drm/i915/i915_scatterlist.h
+@@ -9,7 +9,8 @@
+
+ #include <linux/pfn.h>
+ #include <linux/scatterlist.h>
+-#include <linux/swiotlb.h>
++#include <linux/dma-mapping.h>
++#include <xen/xen.h>
+
+ #include "i915_gem.h"
+
+@@ -127,19 +128,26 @@ static inline unsigned int i915_sg_dma_sizes(struct scatterlist *sg)
+ return page_sizes;
+ }
+
+-static inline unsigned int i915_sg_segment_size(void)
++static inline unsigned int i915_sg_segment_size(struct device *dev)
+ {
+- unsigned int size = swiotlb_max_segment();
+-
+- if (size == 0)
+- size = UINT_MAX;
+-
+- size = rounddown(size, PAGE_SIZE);
+- /* swiotlb_max_segment_size can return 1 byte when it means one page. */
+- if (size < PAGE_SIZE)
+- size = PAGE_SIZE;
+-
+- return size;
++ size_t max = min_t(size_t, UINT_MAX, dma_max_mapping_size(dev));
++
++ /*
++ * For Xen PV guests pages aren't contiguous in DMA (machine) address
++ * space. The DMA API takes care of that both in dma_alloc_* (by
++ * calling into the hypervisor to make the pages contiguous) and in
++ * dma_map_* (by bounce buffering). But i915 abuses ignores the
++ * coherency aspects of the DMA API and thus can't cope with bounce
++ * buffering actually happening, so add a hack here to force small
++ * allocations and mappings when running in PV mode on Xen.
++ *
++ * Note this will still break if bounce buffering is required for other
++ * reasons, like confidential computing hypervisors or PCIe root ports
++ * with addressing limitations.
++ */
++ if (xen_pv_domain())
++ max = PAGE_SIZE;
++ return round_down(max, PAGE_SIZE);
+ }
+
+ bool i915_sg_trim(struct sg_table *orig_st);
+diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
+index 110e83aad9bb4..1aa3700551f4d 100644
+--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
++++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
+@@ -1031,23 +1031,31 @@ static int dw_mipi_dsi_rockchip_host_attach(void *priv_data,
+ if (ret) {
+ DRM_DEV_ERROR(dsi->dev, "Failed to register component: %d\n",
+ ret);
+- return ret;
++ goto out;
+ }
+
+ second = dw_mipi_dsi_rockchip_find_second(dsi);
+- if (IS_ERR(second))
+- return PTR_ERR(second);
++ if (IS_ERR(second)) {
++ ret = PTR_ERR(second);
++ goto out;
++ }
+ if (second) {
+ ret = component_add(second, &dw_mipi_dsi_rockchip_ops);
+ if (ret) {
+ DRM_DEV_ERROR(second,
+ "Failed to register component: %d\n",
+ ret);
+- return ret;
++ goto out;
+ }
+ }
+
+ return 0;
++
++out:
++ mutex_lock(&dsi->usage_mutex);
++ dsi->usage_mode = DW_DSI_USAGE_IDLE;
++ mutex_unlock(&dsi->usage_mutex);
++ return ret;
+ }
+
+ static int dw_mipi_dsi_rockchip_host_detach(void *priv_data,
+@@ -1634,5 +1642,11 @@ struct platform_driver dw_mipi_dsi_rockchip_driver = {
+ .of_match_table = dw_mipi_dsi_rockchip_dt_ids,
+ .pm = &dw_mipi_dsi_rockchip_pm_ops,
+ .name = "dw-mipi-dsi-rockchip",
++ /*
++ * For dual-DSI display, one DSI pokes at the other DSI's
++ * drvdata in dw_mipi_dsi_rockchip_find_second(). This is not
++ * safe for asynchronous probe.
++ */
++ .probe_type = PROBE_FORCE_SYNCHRONOUS,
+ },
+ };
+diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+index c14f888938688..2f4b8f64cbad3 100644
+--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
++++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+@@ -565,7 +565,8 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master,
+
+ ret = rockchip_hdmi_parse_dt(hdmi);
+ if (ret) {
+- DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n");
++ if (ret != -EPROBE_DEFER)
++ DRM_DEV_ERROR(hdmi->dev, "Unable to parse OF data\n");
+ return ret;
+ }
+
+diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+index 985584147da10..cf8322c300bd5 100644
+--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
++++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+@@ -364,9 +364,12 @@ rockchip_gem_create_with_handle(struct drm_file *file_priv,
+ {
+ struct rockchip_gem_object *rk_obj;
+ struct drm_gem_object *obj;
++ bool is_framebuffer;
+ int ret;
+
+- rk_obj = rockchip_gem_create_object(drm, size, false);
++ is_framebuffer = drm->fb_helper && file_priv == drm->fb_helper->client.file;
++
++ rk_obj = rockchip_gem_create_object(drm, size, is_framebuffer);
+ if (IS_ERR(rk_obj))
+ return ERR_CAST(rk_obj);
+
+diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
+index 780a19a75c3f5..874c6bd787c56 100644
+--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
++++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
+@@ -2869,6 +2869,7 @@ static int vc4_hdmi_runtime_resume(struct device *dev)
+ struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
+ unsigned long __maybe_unused flags;
+ u32 __maybe_unused value;
++ unsigned long rate;
+ int ret;
+
+ /*
+@@ -2884,6 +2885,21 @@ static int vc4_hdmi_runtime_resume(struct device *dev)
+ if (ret)
+ return ret;
+
++ /*
++ * Whenever the RaspberryPi boots without an HDMI monitor
++ * plugged in, the firmware won't have initialized the HSM clock
++ * rate and it will be reported as 0.
++ *
++ * If we try to access a register of the controller in such a
++ * case, it will lead to a silent CPU stall. Let's make sure we
++ * prevent such a case.
++ */
++ rate = clk_get_rate(vc4_hdmi->hsm_clock);
++ if (!rate) {
++ ret = -EINVAL;
++ goto err_disable_clk;
++ }
++
+ if (vc4_hdmi->variant->reset)
+ vc4_hdmi->variant->reset(vc4_hdmi);
+
+@@ -2905,6 +2921,10 @@ static int vc4_hdmi_runtime_resume(struct device *dev)
+ #endif
+
+ return 0;
++
++err_disable_clk:
++ clk_disable_unprepare(vc4_hdmi->hsm_clock);
++ return ret;
+ }
+
+ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index 043cf1cc87946..256795ed6247e 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -867,6 +867,7 @@
+ #define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540
+ #define USB_DEVICE_ID_MADCATZ_RAT5 0x1705
+ #define USB_DEVICE_ID_MADCATZ_RAT9 0x1709
++#define USB_DEVICE_ID_MADCATZ_MMO7 0x1713
+
+ #define USB_VENDOR_ID_MCC 0x09db
+ #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
+diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c
+index 70f602c64fd13..50e1c717fc0a3 100644
+--- a/drivers/hid/hid-quirks.c
++++ b/drivers/hid/hid-quirks.c
+@@ -620,6 +620,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
+ { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_MMO7) },
+ #endif
+ #if IS_ENABLED(CONFIG_HID_SAMSUNG)
+ { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
+diff --git a/drivers/hid/hid-saitek.c b/drivers/hid/hid-saitek.c
+index c7bf14c019605..b84e975977c42 100644
+--- a/drivers/hid/hid-saitek.c
++++ b/drivers/hid/hid-saitek.c
+@@ -187,6 +187,8 @@ static const struct hid_device_id saitek_devices[] = {
+ .driver_data = SAITEK_RELEASE_MODE_RAT7 },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7),
+ .driver_data = SAITEK_RELEASE_MODE_MMO7 },
++ { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_MMO7),
++ .driver_data = SAITEK_RELEASE_MODE_MMO7 },
+ { }
+ };
+
+diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
+index 39cb1b7bb8656..809fbd014cd68 100644
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -1080,6 +1080,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ "", &piix4_main_adapters[0]);
+ if (retval < 0)
+ return retval;
++ piix4_adapter_count = 1;
+ }
+
+ /* Check for auxiliary SMBus on some AMD chipsets */
+diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
+index b3fe6b2aa3ca9..277a02455cddd 100644
+--- a/drivers/i2c/busses/i2c-xiic.c
++++ b/drivers/i2c/busses/i2c-xiic.c
+@@ -920,6 +920,7 @@ static struct platform_driver xiic_i2c_driver = {
+
+ module_platform_driver(xiic_i2c_driver);
+
++MODULE_ALIAS("platform:" DRIVER_NAME);
+ MODULE_AUTHOR("info@mocean-labs.com");
+ MODULE_DESCRIPTION("Xilinx I2C bus driver");
+ MODULE_LICENSE("GPL v2");
+diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
+index 130e8dd6f0c89..7719f7f93c3f0 100644
+--- a/drivers/iio/adc/stm32-adc.c
++++ b/drivers/iio/adc/stm32-adc.c
+@@ -2064,18 +2064,19 @@ static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
+ stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val,
+ vin[1], scan_index, differential);
+
++ val = 0;
+ ret = of_property_read_u32(child, "st,min-sample-time-ns", &val);
+ /* st,min-sample-time-ns is optional */
+- if (!ret) {
+- stm32_adc_smpr_init(adc, channels[scan_index].channel, val);
+- if (differential)
+- stm32_adc_smpr_init(adc, vin[1], val);
+- } else if (ret != -EINVAL) {
++ if (ret && ret != -EINVAL) {
+ dev_err(&indio_dev->dev, "Invalid st,min-sample-time-ns property %d\n",
+ ret);
+ goto err;
+ }
+
++ stm32_adc_smpr_init(adc, channels[scan_index].channel, val);
++ if (differential)
++ stm32_adc_smpr_init(adc, vin[1], val);
++
+ scan_index++;
+ }
+
+diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
+index be317f2665a9e..ff8821f79feca 100644
+--- a/drivers/infiniband/core/cma.c
++++ b/drivers/infiniband/core/cma.c
+@@ -1556,7 +1556,7 @@ static bool validate_ipv4_net_dev(struct net_device *net_dev,
+ return false;
+
+ memset(&fl4, 0, sizeof(fl4));
+- fl4.flowi4_iif = net_dev->ifindex;
++ fl4.flowi4_oif = net_dev->ifindex;
+ fl4.daddr = daddr;
+ fl4.saddr = saddr;
+
+diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
+index d275db195f1a1..4053a09b8d33e 100644
+--- a/drivers/infiniband/core/device.c
++++ b/drivers/infiniband/core/device.c
+@@ -2815,10 +2815,18 @@ static int __init ib_core_init(void)
+
+ nldev_init();
+ rdma_nl_register(RDMA_NL_LS, ibnl_ls_cb_table);
+- roce_gid_mgmt_init();
++ ret = roce_gid_mgmt_init();
++ if (ret) {
++ pr_warn("Couldn't init RoCE GID management\n");
++ goto err_parent;
++ }
+
+ return 0;
+
++err_parent:
++ rdma_nl_unregister(RDMA_NL_LS);
++ nldev_exit();
++ unregister_pernet_device(&rdma_dev_net_ops);
+ err_compat:
+ unregister_blocking_lsm_notifier(&ibdev_lsm_nb);
+ err_sa:
+diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
+index b92358f606d00..12dc97067ed2b 100644
+--- a/drivers/infiniband/core/nldev.c
++++ b/drivers/infiniband/core/nldev.c
+@@ -2537,7 +2537,7 @@ void __init nldev_init(void)
+ rdma_nl_register(RDMA_NL_NLDEV, nldev_cb_table);
+ }
+
+-void __exit nldev_exit(void)
++void nldev_exit(void)
+ {
+ rdma_nl_unregister(RDMA_NL_NLDEV);
+ }
+diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c
+index 3d42bd2b36bd4..51ae58c02b15c 100644
+--- a/drivers/infiniband/hw/hfi1/pio.c
++++ b/drivers/infiniband/hw/hfi1/pio.c
+@@ -913,8 +913,7 @@ void sc_disable(struct send_context *sc)
+ spin_unlock(&sc->release_lock);
+
+ write_seqlock(&sc->waitlock);
+- if (!list_empty(&sc->piowait))
+- list_move(&sc->piowait, &wake_list);
++ list_splice_init(&sc->piowait, &wake_list);
+ write_sequnlock(&sc->waitlock);
+ while (!list_empty(&wake_list)) {
+ struct iowait *wait;
+diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+index c780646bd60ac..105888c6ccb77 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+@@ -118,7 +118,6 @@ static const u32 hns_roce_op_code[] = {
+ HR_OPC_MAP(ATOMIC_CMP_AND_SWP, ATOM_CMP_AND_SWAP),
+ HR_OPC_MAP(ATOMIC_FETCH_AND_ADD, ATOM_FETCH_AND_ADD),
+ HR_OPC_MAP(SEND_WITH_INV, SEND_WITH_INV),
+- HR_OPC_MAP(LOCAL_INV, LOCAL_INV),
+ HR_OPC_MAP(MASKED_ATOMIC_CMP_AND_SWP, ATOM_MSK_CMP_AND_SWAP),
+ HR_OPC_MAP(MASKED_ATOMIC_FETCH_AND_ADD, ATOM_MSK_FETCH_AND_ADD),
+ HR_OPC_MAP(REG_MR, FAST_REG_PMR),
+@@ -560,9 +559,6 @@ static int set_rc_opcode(struct hns_roce_dev *hr_dev,
+ else
+ ret = -EOPNOTSUPP;
+ break;
+- case IB_WR_LOCAL_INV:
+- hr_reg_enable(rc_sq_wqe, RC_SEND_WQE_SO);
+- fallthrough;
+ case IB_WR_SEND_WITH_INV:
+ rc_sq_wqe->inv_key = cpu_to_le32(wr->ex.invalidate_rkey);
+ break;
+@@ -2809,8 +2805,12 @@ static int free_mr_modify_qp(struct hns_roce_dev *hr_dev)
+
+ static int free_mr_init(struct hns_roce_dev *hr_dev)
+ {
++ struct hns_roce_v2_priv *priv = hr_dev->priv;
++ struct hns_roce_v2_free_mr *free_mr = &priv->free_mr;
+ int ret;
+
++ mutex_init(&free_mr->mutex);
++
+ ret = free_mr_alloc_res(hr_dev);
+ if (ret)
+ return ret;
+@@ -3226,7 +3226,6 @@ static int hns_roce_v2_write_mtpt(struct hns_roce_dev *hr_dev,
+
+ hr_reg_write(mpt_entry, MPT_ST, V2_MPT_ST_VALID);
+ hr_reg_write(mpt_entry, MPT_PD, mr->pd);
+- hr_reg_enable(mpt_entry, MPT_L_INV_EN);
+
+ hr_reg_write_bool(mpt_entry, MPT_BIND_EN,
+ mr->access & IB_ACCESS_MW_BIND);
+@@ -3317,7 +3316,6 @@ static int hns_roce_v2_frmr_write_mtpt(struct hns_roce_dev *hr_dev,
+
+ hr_reg_enable(mpt_entry, MPT_RA_EN);
+ hr_reg_enable(mpt_entry, MPT_R_INV_EN);
+- hr_reg_enable(mpt_entry, MPT_L_INV_EN);
+
+ hr_reg_enable(mpt_entry, MPT_FRE);
+ hr_reg_clear(mpt_entry, MPT_MR_MW);
+@@ -3349,7 +3347,6 @@ static int hns_roce_v2_mw_write_mtpt(void *mb_buf, struct hns_roce_mw *mw)
+ hr_reg_write(mpt_entry, MPT_PD, mw->pdn);
+
+ hr_reg_enable(mpt_entry, MPT_R_INV_EN);
+- hr_reg_enable(mpt_entry, MPT_L_INV_EN);
+ hr_reg_enable(mpt_entry, MPT_LW_EN);
+
+ hr_reg_enable(mpt_entry, MPT_MR_MW);
+@@ -3798,7 +3795,6 @@ static const u32 wc_send_op_map[] = {
+ HR_WC_OP_MAP(RDMA_READ, RDMA_READ),
+ HR_WC_OP_MAP(RDMA_WRITE, RDMA_WRITE),
+ HR_WC_OP_MAP(RDMA_WRITE_WITH_IMM, RDMA_WRITE),
+- HR_WC_OP_MAP(LOCAL_INV, LOCAL_INV),
+ HR_WC_OP_MAP(ATOM_CMP_AND_SWAP, COMP_SWAP),
+ HR_WC_OP_MAP(ATOM_FETCH_AND_ADD, FETCH_ADD),
+ HR_WC_OP_MAP(ATOM_MSK_CMP_AND_SWAP, MASKED_COMP_SWAP),
+@@ -3848,9 +3844,6 @@ static void fill_send_wc(struct ib_wc *wc, struct hns_roce_v2_cqe *cqe)
+ case HNS_ROCE_V2_WQE_OP_RDMA_WRITE_WITH_IMM:
+ wc->wc_flags |= IB_WC_WITH_IMM;
+ break;
+- case HNS_ROCE_V2_WQE_OP_LOCAL_INV:
+- wc->wc_flags |= IB_WC_WITH_INVALIDATE;
+- break;
+ case HNS_ROCE_V2_WQE_OP_ATOM_CMP_AND_SWAP:
+ case HNS_ROCE_V2_WQE_OP_ATOM_FETCH_AND_ADD:
+ case HNS_ROCE_V2_WQE_OP_ATOM_MSK_CMP_AND_SWAP:
+diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
+index 64797109bab63..4544a8775ce5a 100644
+--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
++++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h
+@@ -182,7 +182,6 @@ enum {
+ HNS_ROCE_V2_WQE_OP_ATOM_MSK_CMP_AND_SWAP = 0x8,
+ HNS_ROCE_V2_WQE_OP_ATOM_MSK_FETCH_AND_ADD = 0x9,
+ HNS_ROCE_V2_WQE_OP_FAST_REG_PMR = 0xa,
+- HNS_ROCE_V2_WQE_OP_LOCAL_INV = 0xb,
+ HNS_ROCE_V2_WQE_OP_BIND_MW = 0xc,
+ HNS_ROCE_V2_WQE_OP_MASK = 0x1f,
+ };
+@@ -916,7 +915,6 @@ struct hns_roce_v2_rc_send_wqe {
+ #define RC_SEND_WQE_OWNER RC_SEND_WQE_FIELD_LOC(7, 7)
+ #define RC_SEND_WQE_CQE RC_SEND_WQE_FIELD_LOC(8, 8)
+ #define RC_SEND_WQE_FENCE RC_SEND_WQE_FIELD_LOC(9, 9)
+-#define RC_SEND_WQE_SO RC_SEND_WQE_FIELD_LOC(10, 10)
+ #define RC_SEND_WQE_SE RC_SEND_WQE_FIELD_LOC(11, 11)
+ #define RC_SEND_WQE_INLINE RC_SEND_WQE_FIELD_LOC(12, 12)
+ #define RC_SEND_WQE_WQE_INDEX RC_SEND_WQE_FIELD_LOC(30, 15)
+diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c
+index 5152f10d2e6de..ba0c3e4c07d85 100644
+--- a/drivers/infiniband/hw/qedr/main.c
++++ b/drivers/infiniband/hw/qedr/main.c
+@@ -344,6 +344,10 @@ static int qedr_alloc_resources(struct qedr_dev *dev)
+ if (IS_IWARP(dev)) {
+ xa_init(&dev->qps);
+ dev->iwarp_wq = create_singlethread_workqueue("qedr_iwarpq");
++ if (!dev->iwarp_wq) {
++ rc = -ENOMEM;
++ goto err1;
++ }
+ }
+
+ /* Allocate Status blocks for CNQ */
+@@ -351,7 +355,7 @@ static int qedr_alloc_resources(struct qedr_dev *dev)
+ GFP_KERNEL);
+ if (!dev->sb_array) {
+ rc = -ENOMEM;
+- goto err1;
++ goto err_destroy_wq;
+ }
+
+ dev->cnq_array = kcalloc(dev->num_cnq,
+@@ -402,6 +406,9 @@ err3:
+ kfree(dev->cnq_array);
+ err2:
+ kfree(dev->sb_array);
++err_destroy_wq:
++ if (IS_IWARP(dev))
++ destroy_workqueue(dev->iwarp_wq);
+ err1:
+ kfree(dev->sgid_tbl);
+ return rc;
+diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c
+index 7c336db5cb547..f8b1d9fa04941 100644
+--- a/drivers/infiniband/sw/rxe/rxe_resp.c
++++ b/drivers/infiniband/sw/rxe/rxe_resp.c
+@@ -806,8 +806,10 @@ static enum resp_states read_reply(struct rxe_qp *qp,
+
+ skb = prepare_ack_packet(qp, &ack_pkt, opcode, payload,
+ res->cur_psn, AETH_ACK_UNLIMITED);
+- if (!skb)
++ if (!skb) {
++ rxe_put(mr);
+ return RESPST_ERR_RNR;
++ }
+
+ rxe_mr_copy(mr, res->read.va, payload_addr(&ack_pkt),
+ payload, RXE_FROM_MR_OBJ);
+diff --git a/drivers/isdn/hardware/mISDN/netjet.c b/drivers/isdn/hardware/mISDN/netjet.c
+index a52f275f82634..f8447135a9022 100644
+--- a/drivers/isdn/hardware/mISDN/netjet.c
++++ b/drivers/isdn/hardware/mISDN/netjet.c
+@@ -956,7 +956,7 @@ nj_release(struct tiger_hw *card)
+ }
+ if (card->irq > 0)
+ free_irq(card->irq, card);
+- if (card->isac.dch.dev.dev.class)
++ if (device_is_registered(&card->isac.dch.dev.dev))
+ mISDN_unregister_device(&card->isac.dch.dev);
+
+ for (i = 0; i < 2; i++) {
+diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c
+index a41b4b2645941..7ea0100f218a0 100644
+--- a/drivers/isdn/mISDN/core.c
++++ b/drivers/isdn/mISDN/core.c
+@@ -233,11 +233,12 @@ mISDN_register_device(struct mISDNdevice *dev,
+ if (debug & DEBUG_CORE)
+ printk(KERN_DEBUG "mISDN_register %s %d\n",
+ dev_name(&dev->dev), dev->id);
++ dev->dev.class = &mISDN_class;
++
+ err = create_stack(dev);
+ if (err)
+ goto error1;
+
+- dev->dev.class = &mISDN_class;
+ dev->dev.platform_data = dev;
+ dev->dev.parent = parent;
+ dev_set_drvdata(&dev->dev, dev);
+@@ -249,8 +250,8 @@ mISDN_register_device(struct mISDNdevice *dev,
+
+ error3:
+ delete_stack(dev);
+- return err;
+ error1:
++ put_device(&dev->dev);
+ return err;
+
+ }
+diff --git a/drivers/media/cec/platform/cros-ec/cros-ec-cec.c b/drivers/media/cec/platform/cros-ec/cros-ec-cec.c
+index 3b583ed4da9df..6ebedc71d67d4 100644
+--- a/drivers/media/cec/platform/cros-ec/cros-ec-cec.c
++++ b/drivers/media/cec/platform/cros-ec/cros-ec-cec.c
+@@ -44,6 +44,8 @@ static void handle_cec_message(struct cros_ec_cec *cros_ec_cec)
+ uint8_t *cec_message = cros_ec->event_data.data.cec_message;
+ unsigned int len = cros_ec->event_size;
+
++ if (len > CEC_MAX_MSG_SIZE)
++ len = CEC_MAX_MSG_SIZE;
+ cros_ec_cec->rx_msg.len = len;
+ memcpy(cros_ec_cec->rx_msg.msg, cec_message, len);
+
+@@ -221,6 +223,8 @@ static const struct cec_dmi_match cec_dmi_match_table[] = {
+ { "Google", "Moli", "0000:00:02.0", "Port B" },
+ /* Google Kinox */
+ { "Google", "Kinox", "0000:00:02.0", "Port B" },
++ /* Google Kuldax */
++ { "Google", "Kuldax", "0000:00:02.0", "Port B" },
+ };
+
+ static struct device *cros_ec_cec_find_hdmi_dev(struct device *dev,
+diff --git a/drivers/media/cec/platform/s5p/s5p_cec.c b/drivers/media/cec/platform/s5p/s5p_cec.c
+index ce9a9d922f116..0a30e7acdc10e 100644
+--- a/drivers/media/cec/platform/s5p/s5p_cec.c
++++ b/drivers/media/cec/platform/s5p/s5p_cec.c
+@@ -115,6 +115,8 @@ static irqreturn_t s5p_cec_irq_handler(int irq, void *priv)
+ dev_dbg(cec->dev, "Buffer overrun (worker did not process previous message)\n");
+ cec->rx = STATE_BUSY;
+ cec->msg.len = status >> 24;
++ if (cec->msg.len > CEC_MAX_MSG_SIZE)
++ cec->msg.len = CEC_MAX_MSG_SIZE;
+ cec->msg.rx_status = CEC_RX_STATUS_OK;
+ s5p_cec_get_rx_buf(cec, cec->msg.len,
+ cec->msg.msg);
+diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c
+index 9430295a8175c..ef0d063ec3526 100644
+--- a/drivers/media/dvb-frontends/drxk_hard.c
++++ b/drivers/media/dvb-frontends/drxk_hard.c
+@@ -6660,7 +6660,7 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
+ static int drxk_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+ {
+ struct drxk_state *state = fe->demodulator_priv;
+- u16 err;
++ u16 err = 0;
+
+ dprintk(1, "\n");
+
+diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
+index d5904c96ff3fc..c66963a2ccd99 100644
+--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
++++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-capture.c
+@@ -1273,11 +1273,12 @@ static int rkisp1_capture_link_validate(struct media_link *link)
+ struct rkisp1_capture *cap = video_get_drvdata(vdev);
+ const struct rkisp1_capture_fmt_cfg *fmt =
+ rkisp1_find_fmt_cfg(cap, cap->pix.fmt.pixelformat);
+- struct v4l2_subdev_format sd_fmt;
++ struct v4l2_subdev_format sd_fmt = {
++ .which = V4L2_SUBDEV_FORMAT_ACTIVE,
++ .pad = link->source->index,
++ };
+ int ret;
+
+- sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+- sd_fmt.pad = link->source->index;
+ ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sd_fmt);
+ if (ret)
+ return ret;
+diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
+index 383a3ec83ca9f..00032b849a076 100644
+--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
++++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-isp.c
+@@ -472,23 +472,43 @@ static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp,
+ struct v4l2_mbus_framefmt *format,
+ unsigned int which)
+ {
+- const struct rkisp1_mbus_info *mbus_info;
++ const struct rkisp1_mbus_info *sink_info;
++ const struct rkisp1_mbus_info *src_info;
++ struct v4l2_mbus_framefmt *sink_fmt;
+ struct v4l2_mbus_framefmt *src_fmt;
+ const struct v4l2_rect *src_crop;
+
++ sink_fmt = rkisp1_isp_get_pad_fmt(isp, sd_state,
++ RKISP1_ISP_PAD_SINK_VIDEO, which);
+ src_fmt = rkisp1_isp_get_pad_fmt(isp, sd_state,
+ RKISP1_ISP_PAD_SOURCE_VIDEO, which);
+ src_crop = rkisp1_isp_get_pad_crop(isp, sd_state,
+ RKISP1_ISP_PAD_SOURCE_VIDEO, which);
+
++ /*
++ * Media bus code. The ISP can operate in pass-through mode (Bayer in,
++ * Bayer out or YUV in, YUV out) or process Bayer data to YUV, but
++ * can't convert from YUV to Bayer.
++ */
++ sink_info = rkisp1_mbus_info_get_by_code(sink_fmt->code);
++
+ src_fmt->code = format->code;
+- mbus_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
+- if (!mbus_info || !(mbus_info->direction & RKISP1_ISP_SD_SRC)) {
++ src_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
++ if (!src_info || !(src_info->direction & RKISP1_ISP_SD_SRC)) {
+ src_fmt->code = RKISP1_DEF_SRC_PAD_FMT;
+- mbus_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
++ src_info = rkisp1_mbus_info_get_by_code(src_fmt->code);
+ }
+- if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
+- isp->src_fmt = mbus_info;
++
++ if (sink_info->pixel_enc == V4L2_PIXEL_ENC_YUV &&
++ src_info->pixel_enc == V4L2_PIXEL_ENC_BAYER) {
++ src_fmt->code = sink_fmt->code;
++ src_info = sink_info;
++ }
++
++ /*
++ * The source width and height must be identical to the source crop
++ * size.
++ */
+ src_fmt->width = src_crop->width;
+ src_fmt->height = src_crop->height;
+
+@@ -498,14 +518,18 @@ static void rkisp1_isp_set_src_fmt(struct rkisp1_isp *isp,
+ */
+ if (format->flags & V4L2_MBUS_FRAMEFMT_SET_CSC &&
+ format->quantization == V4L2_QUANTIZATION_FULL_RANGE &&
+- mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
++ src_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
+ src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+- else if (mbus_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
++ else if (src_info->pixel_enc == V4L2_PIXEL_ENC_YUV)
+ src_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE;
+ else
+ src_fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+
+ *format = *src_fmt;
++
++ /* Store the source format info when setting the active format. */
++ if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
++ isp->src_fmt = src_info;
+ }
+
+ static void rkisp1_isp_set_src_crop(struct rkisp1_isp *isp,
+diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+index 9da7dc1bc6909..02ac3043badd4 100644
+--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
++++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-params.c
+@@ -343,7 +343,7 @@ static void rkisp1_lsc_config(struct rkisp1_params *params,
+ RKISP1_CIF_ISP_LSC_XSIZE_01 + i * 4, data);
+
+ /* program x grad tables */
+- data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->x_grad_tbl[i * 2],
++ data = RKISP1_CIF_ISP_LSC_SECT_GRAD(arg->x_grad_tbl[i * 2],
+ arg->x_grad_tbl[i * 2 + 1]);
+ rkisp1_write(params->rkisp1,
+ RKISP1_CIF_ISP_LSC_XGRAD_01 + i * 4, data);
+@@ -355,7 +355,7 @@ static void rkisp1_lsc_config(struct rkisp1_params *params,
+ RKISP1_CIF_ISP_LSC_YSIZE_01 + i * 4, data);
+
+ /* program y grad tables */
+- data = RKISP1_CIF_ISP_LSC_SECT_SIZE(arg->y_grad_tbl[i * 2],
++ data = RKISP1_CIF_ISP_LSC_SECT_GRAD(arg->y_grad_tbl[i * 2],
+ arg->y_grad_tbl[i * 2 + 1]);
+ rkisp1_write(params->rkisp1,
+ RKISP1_CIF_ISP_LSC_YGRAD_01 + i * 4, data);
+@@ -1066,7 +1066,7 @@ static void rkisp1_ie_enable(struct rkisp1_params *params, bool en)
+ }
+ }
+
+-static void rkisp1_csm_config(struct rkisp1_params *params, bool full_range)
++static void rkisp1_csm_config(struct rkisp1_params *params)
+ {
+ static const u16 full_range_coeff[] = {
+ 0x0026, 0x004b, 0x000f,
+@@ -1080,7 +1080,7 @@ static void rkisp1_csm_config(struct rkisp1_params *params, bool full_range)
+ };
+ unsigned int i;
+
+- if (full_range) {
++ if (params->quantization == V4L2_QUANTIZATION_FULL_RANGE) {
+ for (i = 0; i < ARRAY_SIZE(full_range_coeff); i++)
+ rkisp1_write(params->rkisp1,
+ RKISP1_CIF_ISP_CC_COEFF_0 + i * 4,
+@@ -1552,11 +1552,7 @@ static void rkisp1_params_config_parameter(struct rkisp1_params *params)
+ rkisp1_param_set_bits(params, RKISP1_CIF_ISP_HIST_PROP_V10,
+ rkisp1_hst_params_default_config.mode);
+
+- /* set the range */
+- if (params->quantization == V4L2_QUANTIZATION_FULL_RANGE)
+- rkisp1_csm_config(params, true);
+- else
+- rkisp1_csm_config(params, false);
++ rkisp1_csm_config(params);
+
+ spin_lock_irq(¶ms->config_lock);
+
+diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h b/drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h
+index dd3e6c38be677..025491f8793f6 100644
+--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h
++++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-regs.h
+@@ -576,7 +576,7 @@
+ (((v0) & 0x1FFF) | (((v1) & 0x1FFF) << 13))
+ #define RKISP1_CIF_ISP_LSC_SECT_SIZE(v0, v1) \
+ (((v0) & 0xFFF) | (((v1) & 0xFFF) << 16))
+-#define RKISP1_CIF_ISP_LSC_GRAD_SIZE(v0, v1) \
++#define RKISP1_CIF_ISP_LSC_SECT_GRAD(v0, v1) \
+ (((v0) & 0xFFF) | (((v1) & 0xFFF) << 16))
+
+ /* LSC: ISP_LSC_TABLE_SEL */
+diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c
+index f4caa8f684aad..a2dc6f60d9cf6 100644
+--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c
++++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-resizer.c
+@@ -411,6 +411,10 @@ static int rkisp1_rsz_init_config(struct v4l2_subdev *sd,
+ sink_fmt->height = RKISP1_DEFAULT_HEIGHT;
+ sink_fmt->field = V4L2_FIELD_NONE;
+ sink_fmt->code = RKISP1_DEF_FMT;
++ sink_fmt->colorspace = V4L2_COLORSPACE_SRGB;
++ sink_fmt->xfer_func = V4L2_XFER_FUNC_SRGB;
++ sink_fmt->ycbcr_enc = V4L2_YCBCR_ENC_601;
++ sink_fmt->quantization = V4L2_QUANTIZATION_LIM_RANGE;
+
+ sink_crop = v4l2_subdev_get_try_crop(sd, sd_state,
+ RKISP1_RSZ_PAD_SINK);
+diff --git a/drivers/net/dsa/dsa_loop.c b/drivers/net/dsa/dsa_loop.c
+index 263e41191c292..0d20ebafbd03a 100644
+--- a/drivers/net/dsa/dsa_loop.c
++++ b/drivers/net/dsa/dsa_loop.c
+@@ -378,6 +378,17 @@ static struct mdio_driver dsa_loop_drv = {
+
+ #define NUM_FIXED_PHYS (DSA_LOOP_NUM_PORTS - 2)
+
++static void dsa_loop_phydevs_unregister(void)
++{
++ unsigned int i;
++
++ for (i = 0; i < NUM_FIXED_PHYS; i++)
++ if (!IS_ERR(phydevs[i])) {
++ fixed_phy_unregister(phydevs[i]);
++ phy_device_free(phydevs[i]);
++ }
++}
++
+ static int __init dsa_loop_init(void)
+ {
+ struct fixed_phy_status status = {
+@@ -385,23 +396,23 @@ static int __init dsa_loop_init(void)
+ .speed = SPEED_100,
+ .duplex = DUPLEX_FULL,
+ };
+- unsigned int i;
++ unsigned int i, ret;
+
+ for (i = 0; i < NUM_FIXED_PHYS; i++)
+ phydevs[i] = fixed_phy_register(PHY_POLL, &status, NULL);
+
+- return mdio_driver_register(&dsa_loop_drv);
++ ret = mdio_driver_register(&dsa_loop_drv);
++ if (ret)
++ dsa_loop_phydevs_unregister();
++
++ return ret;
+ }
+ module_init(dsa_loop_init);
+
+ static void __exit dsa_loop_exit(void)
+ {
+- unsigned int i;
+-
+ mdio_driver_unregister(&dsa_loop_drv);
+- for (i = 0; i < NUM_FIXED_PHYS; i++)
+- if (!IS_ERR(phydevs[i]))
+- fixed_phy_unregister(phydevs[i]);
++ dsa_loop_phydevs_unregister();
+ }
+ module_exit(dsa_loop_exit);
+
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index a486435ceee2c..5aa254eaa8d02 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -657,7 +657,7 @@ fec_enet_txq_put_data_tso(struct fec_enet_priv_tx_q *txq, struct sk_buff *skb,
+ dev_kfree_skb_any(skb);
+ if (net_ratelimit())
+ netdev_err(ndev, "Tx DMA memory map failed\n");
+- return NETDEV_TX_BUSY;
++ return NETDEV_TX_OK;
+ }
+
+ bdp->cbd_datlen = cpu_to_fec16(size);
+@@ -719,7 +719,7 @@ fec_enet_txq_put_hdr_tso(struct fec_enet_priv_tx_q *txq,
+ dev_kfree_skb_any(skb);
+ if (net_ratelimit())
+ netdev_err(ndev, "Tx DMA memory map failed\n");
+- return NETDEV_TX_BUSY;
++ return NETDEV_TX_OK;
+ }
+ }
+
+diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
+index 5ab7c0f81e9af..e6b141536879f 100644
+--- a/drivers/net/ethernet/ibm/ibmvnic.c
++++ b/drivers/net/ethernet/ibm/ibmvnic.c
+@@ -3007,19 +3007,19 @@ static void __ibmvnic_reset(struct work_struct *work)
+ rwi = get_next_rwi(adapter);
+
+ /*
+- * If there is another reset queued, free the previous rwi
+- * and process the new reset even if previous reset failed
+- * (the previous reset could have failed because of a fail
+- * over for instance, so process the fail over).
+- *
+ * If there are no resets queued and the previous reset failed,
+ * the adapter would be in an undefined state. So retry the
+ * previous reset as a hard reset.
++ *
++ * Else, free the previous rwi and, if there is another reset
++ * queued, process the new reset even if previous reset failed
++ * (the previous reset could have failed because of a fail
++ * over for instance, so process the fail over).
+ */
+- if (rwi)
+- kfree(tmprwi);
+- else if (rc)
++ if (!rwi && rc)
+ rwi = tmprwi;
++ else
++ kfree(tmprwi);
+
+ if (rwi && (rwi->reset_reason == VNIC_RESET_FAILOVER ||
+ rwi->reset_reason == VNIC_RESET_MOBILITY || rc))
+diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
+index 69f741db25b1f..3a1a0f9178c01 100644
+--- a/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
+@@ -414,13 +414,15 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx)
+ /* Get the received frame and unmap it */
+ db = &rx->dcbs[rx->dcb_index].db[rx->db_index];
+ page = rx->page[rx->dcb_index][rx->db_index];
++
++ dma_sync_single_for_cpu(lan966x->dev, (dma_addr_t)db->dataptr,
++ FDMA_DCB_STATUS_BLOCKL(db->status),
++ DMA_FROM_DEVICE);
++
+ skb = build_skb(page_address(page), PAGE_SIZE << rx->page_order);
+ if (unlikely(!skb))
+ goto unmap_page;
+
+- dma_unmap_single(lan966x->dev, (dma_addr_t)db->dataptr,
+- FDMA_DCB_STATUS_BLOCKL(db->status),
+- DMA_FROM_DEVICE);
+ skb_put(skb, FDMA_DCB_STATUS_BLOCKL(db->status));
+
+ lan966x_ifh_get_src_port(skb->data, &src_port);
+@@ -429,6 +431,10 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx)
+ if (WARN_ON(src_port >= lan966x->num_phys_ports))
+ goto free_skb;
+
++ dma_unmap_single_attrs(lan966x->dev, (dma_addr_t)db->dataptr,
++ PAGE_SIZE << rx->page_order, DMA_FROM_DEVICE,
++ DMA_ATTR_SKIP_CPU_SYNC);
++
+ skb->dev = lan966x->ports[src_port]->dev;
+ skb_pull(skb, IFH_LEN * sizeof(u32));
+
+@@ -454,9 +460,9 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx)
+ free_skb:
+ kfree_skb(skb);
+ unmap_page:
+- dma_unmap_page(lan966x->dev, (dma_addr_t)db->dataptr,
+- FDMA_DCB_STATUS_BLOCKL(db->status),
+- DMA_FROM_DEVICE);
++ dma_unmap_single_attrs(lan966x->dev, (dma_addr_t)db->dataptr,
++ PAGE_SIZE << rx->page_order, DMA_FROM_DEVICE,
++ DMA_ATTR_SKIP_CPU_SYNC);
+ __free_pages(page, rx->page_order);
+
+ return NULL;
+@@ -668,12 +674,14 @@ static int lan966x_fdma_get_max_mtu(struct lan966x *lan966x)
+ int i;
+
+ for (i = 0; i < lan966x->num_phys_ports; ++i) {
++ struct lan966x_port *port;
+ int mtu;
+
+- if (!lan966x->ports[i])
++ port = lan966x->ports[i];
++ if (!port)
+ continue;
+
+- mtu = lan966x->ports[i]->dev->mtu;
++ mtu = lan_rd(lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port));
+ if (mtu > max_mtu)
+ max_mtu = mtu;
+ }
+@@ -733,6 +741,8 @@ int lan966x_fdma_change_mtu(struct lan966x *lan966x)
+
+ max_mtu = lan966x_fdma_get_max_mtu(lan966x);
+ max_mtu += IFH_LEN * sizeof(u32);
++ max_mtu += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
++ max_mtu += VLAN_HLEN * 2;
+
+ if (round_up(max_mtu, PAGE_SIZE) / PAGE_SIZE - 1 ==
+ lan966x->rx.page_order)
+diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+index d928b75f37803..4a3cb75794202 100644
+--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+@@ -385,7 +385,7 @@ static int lan966x_port_change_mtu(struct net_device *dev, int new_mtu)
+ int old_mtu = dev->mtu;
+ int err;
+
+- lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(new_mtu),
++ lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(LAN966X_HW_MTU(new_mtu)),
+ lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port));
+ dev->mtu = new_mtu;
+
+@@ -394,7 +394,7 @@ static int lan966x_port_change_mtu(struct net_device *dev, int new_mtu)
+
+ err = lan966x_fdma_change_mtu(lan966x);
+ if (err) {
+- lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(old_mtu),
++ lan_wr(DEV_MAC_MAXLEN_CFG_MAX_LEN_SET(LAN966X_HW_MTU(old_mtu)),
+ lan966x, DEV_MAC_MAXLEN_CFG(port->chip_port));
+ dev->mtu = old_mtu;
+ }
+diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
+index 2787055c18475..e316bfe186d74 100644
+--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.h
+@@ -24,6 +24,8 @@
+ #define LAN966X_BUFFER_MEMORY (160 * 1024)
+ #define LAN966X_BUFFER_MIN_SZ 60
+
++#define LAN966X_HW_MTU(mtu) ((mtu) + ETH_HLEN + ETH_FCS_LEN)
++
+ #define PGID_AGGR 64
+ #define PGID_SRC 80
+ #define PGID_ENTRIES 89
+diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
+index 8265ad89f0bcb..357ecc2f1089d 100644
+--- a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
+@@ -444,6 +444,21 @@ enum lan966x_target {
+ #define DEV_MAC_MAXLEN_CFG_MAX_LEN_GET(x)\
+ FIELD_GET(DEV_MAC_MAXLEN_CFG_MAX_LEN, x)
+
++/* DEV:MAC_CFG_STATUS:MAC_TAGS_CFG */
++#define DEV_MAC_TAGS_CFG(t) __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 12, 0, 1, 4)
++
++#define DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA BIT(1)
++#define DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_SET(x)\
++ FIELD_PREP(DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA, x)
++#define DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_GET(x)\
++ FIELD_GET(DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA, x)
++
++#define DEV_MAC_TAGS_CFG_VLAN_AWR_ENA BIT(0)
++#define DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(x)\
++ FIELD_PREP(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA, x)
++#define DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_GET(x)\
++ FIELD_GET(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA, x)
++
+ /* DEV:MAC_CFG_STATUS:MAC_IFG_CFG */
+ #define DEV_MAC_IFG_CFG(t) __REG(TARGET_DEV, t, 8, 28, 0, 1, 44, 20, 0, 1, 4)
+
+diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_vlan.c b/drivers/net/ethernet/microchip/lan966x/lan966x_vlan.c
+index 8d7260cd7da9c..3c44660128dae 100644
+--- a/drivers/net/ethernet/microchip/lan966x/lan966x_vlan.c
++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_vlan.c
+@@ -169,6 +169,12 @@ void lan966x_vlan_port_apply(struct lan966x_port *port)
+ ANA_VLAN_CFG_VLAN_POP_CNT,
+ lan966x, ANA_VLAN_CFG(port->chip_port));
+
++ lan_rmw(DEV_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(port->vlan_aware) |
++ DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA_SET(port->vlan_aware),
++ DEV_MAC_TAGS_CFG_VLAN_AWR_ENA |
++ DEV_MAC_TAGS_CFG_VLAN_DBL_AWR_ENA,
++ lan966x, DEV_MAC_TAGS_CFG(port->chip_port));
++
+ /* Drop frames with multicast source address */
+ val = ANA_DROP_CFG_DROP_MC_SMAC_ENA_SET(1);
+ if (port->vlan_aware && !pvid)
+diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
+index 153d68e29b8b3..68a68477ab7bc 100644
+--- a/drivers/net/ethernet/sfc/efx.c
++++ b/drivers/net/ethernet/sfc/efx.c
+@@ -1059,8 +1059,10 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
+
+ /* Allocate and initialise a struct net_device */
+ net_dev = alloc_etherdev_mq(sizeof(probe_data), EFX_MAX_CORE_TX_QUEUES);
+- if (!net_dev)
+- return -ENOMEM;
++ if (!net_dev) {
++ rc = -ENOMEM;
++ goto fail0;
++ }
+ probe_ptr = netdev_priv(net_dev);
+ *probe_ptr = probe_data;
+ efx->net_dev = net_dev;
+@@ -1132,6 +1134,8 @@ static int efx_pci_probe(struct pci_dev *pci_dev,
+ WARN_ON(rc > 0);
+ netif_dbg(efx, drv, efx->net_dev, "initialisation failed. rc=%d\n", rc);
+ free_netdev(net_dev);
++ fail0:
++ kfree(probe_data);
+ return rc;
+ }
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+index 017dbbda0c1c4..79fa7870563b8 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+@@ -51,7 +51,6 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
+ struct stmmac_resources res;
+ struct device_node *np;
+ int ret, i, phy_mode;
+- bool mdio = false;
+
+ np = dev_of_node(&pdev->dev);
+
+@@ -69,12 +68,10 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
+ if (!plat)
+ return -ENOMEM;
+
++ plat->mdio_node = of_get_child_by_name(np, "mdio");
+ if (plat->mdio_node) {
+- dev_err(&pdev->dev, "Found MDIO subnode\n");
+- mdio = true;
+- }
++ dev_info(&pdev->dev, "Found MDIO subnode\n");
+
+- if (mdio) {
+ plat->mdio_bus_data = devm_kzalloc(&pdev->dev,
+ sizeof(*plat->mdio_bus_data),
+ GFP_KERNEL);
+diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
+index 8a2dbe849866d..1bc988d9f2e8a 100644
+--- a/drivers/net/phy/mdio_bus.c
++++ b/drivers/net/phy/mdio_bus.c
+@@ -583,7 +583,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
+ }
+
+ for (i = 0; i < PHY_MAX_ADDR; i++) {
+- if ((bus->phy_mask & (1 << i)) == 0) {
++ if ((bus->phy_mask & BIT(i)) == 0) {
+ struct phy_device *phydev;
+
+ phydev = mdiobus_scan(bus, i);
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index db736b944016e..b02bd0a6c0a93 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -1459,7 +1459,8 @@ static struct sk_buff *tun_napi_alloc_frags(struct tun_file *tfile,
+ int err;
+ int i;
+
+- if (it->nr_segs > MAX_SKB_FRAGS + 1)
++ if (it->nr_segs > MAX_SKB_FRAGS + 1 ||
++ len > (ETH_MAX_MTU - NET_SKB_PAD - NET_IP_ALIGN))
+ return ERR_PTR(-EMSGSIZE);
+
+ local_bh_disable();
+diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+index bc3f4e4edcdf9..dac7eb77799bd 100644
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+@@ -228,6 +228,10 @@ static void brcmf_fweh_event_worker(struct work_struct *work)
+ brcmf_fweh_event_name(event->code), event->code,
+ event->emsg.ifidx, event->emsg.bsscfgidx,
+ event->emsg.addr);
++ if (event->emsg.bsscfgidx >= BRCMF_MAX_IFS) {
++ bphy_err(drvr, "invalid bsscfg index: %u\n", event->emsg.bsscfgidx);
++ goto event_free;
++ }
+
+ /* convert event message */
+ emsg_be = &event->emsg;
+diff --git a/drivers/nfc/fdp/fdp.c b/drivers/nfc/fdp/fdp.c
+index c6b3334f24c9e..f12f903a9dd13 100644
+--- a/drivers/nfc/fdp/fdp.c
++++ b/drivers/nfc/fdp/fdp.c
+@@ -249,11 +249,19 @@ static int fdp_nci_close(struct nci_dev *ndev)
+ static int fdp_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
+ {
+ struct fdp_nci_info *info = nci_get_drvdata(ndev);
++ int ret;
+
+ if (atomic_dec_and_test(&info->data_pkt_counter))
+ info->data_pkt_counter_cb(ndev);
+
+- return info->phy_ops->write(info->phy, skb);
++ ret = info->phy_ops->write(info->phy, skb);
++ if (ret < 0) {
++ kfree_skb(skb);
++ return ret;
++ }
++
++ consume_skb(skb);
++ return 0;
+ }
+
+ static int fdp_nci_request_firmware(struct nci_dev *ndev)
+diff --git a/drivers/nfc/nfcmrvl/i2c.c b/drivers/nfc/nfcmrvl/i2c.c
+index 01329b91d59d5..a902720cd8493 100644
+--- a/drivers/nfc/nfcmrvl/i2c.c
++++ b/drivers/nfc/nfcmrvl/i2c.c
+@@ -132,10 +132,15 @@ static int nfcmrvl_i2c_nci_send(struct nfcmrvl_private *priv,
+ ret = -EREMOTEIO;
+ } else
+ ret = 0;
++ }
++
++ if (ret) {
+ kfree_skb(skb);
++ return ret;
+ }
+
+- return ret;
++ consume_skb(skb);
++ return 0;
+ }
+
+ static void nfcmrvl_i2c_nci_update_config(struct nfcmrvl_private *priv,
+diff --git a/drivers/nfc/nxp-nci/core.c b/drivers/nfc/nxp-nci/core.c
+index 7c93d484dc1bc..580cb6ecffee4 100644
+--- a/drivers/nfc/nxp-nci/core.c
++++ b/drivers/nfc/nxp-nci/core.c
+@@ -80,10 +80,13 @@ static int nxp_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
+ return -EINVAL;
+
+ r = info->phy_ops->write(info->phy_id, skb);
+- if (r < 0)
++ if (r < 0) {
+ kfree_skb(skb);
++ return r;
++ }
+
+- return r;
++ consume_skb(skb);
++ return 0;
+ }
+
+ static int nxp_nci_rf_pll_unlocked_ntf(struct nci_dev *ndev,
+diff --git a/drivers/nfc/s3fwrn5/core.c b/drivers/nfc/s3fwrn5/core.c
+index 1c412007fabb6..0270e05b68dff 100644
+--- a/drivers/nfc/s3fwrn5/core.c
++++ b/drivers/nfc/s3fwrn5/core.c
+@@ -110,11 +110,15 @@ static int s3fwrn5_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
+ }
+
+ ret = s3fwrn5_write(info, skb);
+- if (ret < 0)
++ if (ret < 0) {
+ kfree_skb(skb);
++ mutex_unlock(&info->mutex);
++ return ret;
++ }
+
++ consume_skb(skb);
+ mutex_unlock(&info->mutex);
+- return ret;
++ return 0;
+ }
+
+ static int s3fwrn5_nci_post_setup(struct nci_dev *ndev)
+diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
+index 57cc2bb5b1a2b..554468ea5a2a9 100644
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -3508,6 +3508,16 @@ static const struct pci_device_id nvme_id_table[] = {
+ .driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
+ { PCI_DEVICE(0x2646, 0x2263), /* KINGSTON A2000 NVMe SSD */
+ .driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
++ { PCI_DEVICE(0x2646, 0x5018), /* KINGSTON OM8SFP4xxxxP OS21012 NVMe SSD */
++ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
++ { PCI_DEVICE(0x2646, 0x5016), /* KINGSTON OM3PGP4xxxxP OS21011 NVMe SSD */
++ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
++ { PCI_DEVICE(0x2646, 0x501A), /* KINGSTON OM8PGP4xxxxP OS21005 NVMe SSD */
++ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
++ { PCI_DEVICE(0x2646, 0x501B), /* KINGSTON OM8PGP4xxxxQ OS21005 NVMe SSD */
++ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
++ { PCI_DEVICE(0x2646, 0x501E), /* KINGSTON OM3PGP4xxxxQ OS21011 NVMe SSD */
++ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+ { PCI_DEVICE(0x1e4B, 0x1001), /* MAXIO MAP1001 */
+ .driver_data = NVME_QUIRK_BOGUS_NID, },
+ { PCI_DEVICE(0x1e4B, 0x1002), /* MAXIO MAP1002 */
+diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
+index bdef7a8d6ab8e..bcc1dae007803 100644
+--- a/drivers/parisc/iosapic.c
++++ b/drivers/parisc/iosapic.c
+@@ -866,6 +866,7 @@ int iosapic_serial_irq(struct parisc_device *dev)
+
+ return vi->txn_irq;
+ }
++EXPORT_SYMBOL(iosapic_serial_irq);
+ #endif
+
+
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 5d61f58399dca..dc41d7c6b9b19 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -828,6 +828,14 @@ store_state_field(struct device *dev, struct device_attribute *attr,
+ }
+
+ mutex_lock(&sdev->state_mutex);
++ switch (sdev->sdev_state) {
++ case SDEV_RUNNING:
++ case SDEV_OFFLINE:
++ break;
++ default:
++ mutex_unlock(&sdev->state_mutex);
++ return -EINVAL;
++ }
+ if (sdev->sdev_state == SDEV_RUNNING && state == SDEV_RUNNING) {
+ ret = 0;
+ } else {
+diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c
+index 2036f72eeb4af..1dd8312d824ce 100644
+--- a/drivers/staging/media/hantro/hantro_drv.c
++++ b/drivers/staging/media/hantro/hantro_drv.c
+@@ -251,6 +251,11 @@ queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
+
+ static int hantro_try_ctrl(struct v4l2_ctrl *ctrl)
+ {
++ struct hantro_ctx *ctx;
++
++ ctx = container_of(ctrl->handler,
++ struct hantro_ctx, ctrl_handler);
++
+ if (ctrl->id == V4L2_CID_STATELESS_H264_SPS) {
+ const struct v4l2_ctrl_h264_sps *sps = ctrl->p_new.p_h264_sps;
+
+@@ -272,6 +277,8 @@ static int hantro_try_ctrl(struct v4l2_ctrl *ctrl)
+ if (sps->bit_depth_luma_minus8 != 0)
+ /* Only 8-bit is supported */
+ return -EINVAL;
++
++ ctx->bit_depth = sps->bit_depth_luma_minus8 + 8;
+ } else if (ctrl->id == V4L2_CID_STATELESS_VP9_FRAME) {
+ const struct v4l2_ctrl_vp9_frame *dec_params = ctrl->p_new.p_vp9_frame;
+
+diff --git a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c
+index 233ecd863d5f1..a917079a6ed30 100644
+--- a/drivers/staging/media/hantro/hantro_g2_hevc_dec.c
++++ b/drivers/staging/media/hantro/hantro_g2_hevc_dec.c
+@@ -12,7 +12,7 @@
+
+ static size_t hantro_hevc_chroma_offset(struct hantro_ctx *ctx)
+ {
+- return ctx->dst_fmt.width * ctx->dst_fmt.height;
++ return ctx->dst_fmt.width * ctx->dst_fmt.height * ctx->bit_depth / 8;
+ }
+
+ static size_t hantro_hevc_motion_vectors_offset(struct hantro_ctx *ctx)
+diff --git a/drivers/staging/media/hantro/hantro_hevc.c b/drivers/staging/media/hantro/hantro_hevc.c
+index b990bc98164c3..9383fb7081f6c 100644
+--- a/drivers/staging/media/hantro/hantro_hevc.c
++++ b/drivers/staging/media/hantro/hantro_hevc.c
+@@ -104,7 +104,7 @@ static int tile_buffer_reallocate(struct hantro_ctx *ctx)
+ hevc_dec->tile_bsd.cpu = NULL;
+ }
+
+- size = VERT_FILTER_RAM_SIZE * height64 * (num_tile_cols - 1);
++ size = (VERT_FILTER_RAM_SIZE * height64 * (num_tile_cols - 1) * ctx->bit_depth) / 8;
+ hevc_dec->tile_filter.cpu = dma_alloc_coherent(vpu->dev, size,
+ &hevc_dec->tile_filter.dma,
+ GFP_KERNEL);
+@@ -112,7 +112,7 @@ static int tile_buffer_reallocate(struct hantro_ctx *ctx)
+ goto err_free_tile_buffers;
+ hevc_dec->tile_filter.size = size;
+
+- size = VERT_SAO_RAM_SIZE * height64 * (num_tile_cols - 1);
++ size = (VERT_SAO_RAM_SIZE * height64 * (num_tile_cols - 1) * ctx->bit_depth) / 8;
+ hevc_dec->tile_sao.cpu = dma_alloc_coherent(vpu->dev, size,
+ &hevc_dec->tile_sao.dma,
+ GFP_KERNEL);
+diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c
+index 8549d95be0f25..52f224d8def10 100644
+--- a/drivers/staging/media/meson/vdec/vdec.c
++++ b/drivers/staging/media/meson/vdec/vdec.c
+@@ -1102,6 +1102,7 @@ static int vdec_probe(struct platform_device *pdev)
+
+ err_vdev_release:
+ video_device_release(vdev);
++ v4l2_device_unregister(&core->v4l2_dev);
+ return ret;
+ }
+
+@@ -1110,6 +1111,7 @@ static int vdec_remove(struct platform_device *pdev)
+ struct amvdec_core *core = platform_get_drvdata(pdev);
+
+ video_unregister_device(core->vdev_dec);
++ v4l2_device_unregister(&core->v4l2_dev);
+
+ return 0;
+ }
+diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
+index d0b49e15fbf5e..7b3ffb7f50aba 100644
+--- a/drivers/tty/serial/8250/Kconfig
++++ b/drivers/tty/serial/8250/Kconfig
+@@ -118,7 +118,7 @@ config SERIAL_8250_CONSOLE
+
+ config SERIAL_8250_GSC
+ tristate
+- depends on SERIAL_8250 && GSC
++ depends on SERIAL_8250 && PARISC
+ default SERIAL_8250
+
+ config SERIAL_8250_DMA
+diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
+index ccc818b409774..21c478df6aef4 100644
+--- a/fs/btrfs/backref.c
++++ b/fs/btrfs/backref.c
+@@ -289,8 +289,10 @@ static void prelim_release(struct preftree *preftree)
+ struct prelim_ref *ref, *next_ref;
+
+ rbtree_postorder_for_each_entry_safe(ref, next_ref,
+- &preftree->root.rb_root, rbnode)
++ &preftree->root.rb_root, rbnode) {
++ free_inode_elem_list(ref->inode_list);
+ free_pref(ref);
++ }
+
+ preftree->root = RB_ROOT_CACHED;
+ preftree->count = 0;
+@@ -648,6 +650,18 @@ unode_aux_to_inode_list(struct ulist_node *node)
+ return (struct extent_inode_elem *)(uintptr_t)node->aux;
+ }
+
++static void free_leaf_list(struct ulist *ulist)
++{
++ struct ulist_node *node;
++ struct ulist_iterator uiter;
++
++ ULIST_ITER_INIT(&uiter);
++ while ((node = ulist_next(ulist, &uiter)))
++ free_inode_elem_list(unode_aux_to_inode_list(node));
++
++ ulist_free(ulist);
++}
++
+ /*
+ * We maintain three separate rbtrees: one for direct refs, one for
+ * indirect refs which have a key, and one for indirect refs which do not
+@@ -762,7 +776,11 @@ static int resolve_indirect_refs(struct btrfs_fs_info *fs_info,
+ cond_resched();
+ }
+ out:
+- ulist_free(parents);
++ /*
++ * We may have inode lists attached to refs in the parents ulist, so we
++ * must free them before freeing the ulist and its refs.
++ */
++ free_leaf_list(parents);
+ return ret;
+ }
+
+@@ -1368,6 +1386,12 @@ again:
+ if (ret < 0)
+ goto out;
+ ref->inode_list = eie;
++ /*
++ * We transferred the list ownership to the ref,
++ * so set to NULL to avoid a double free in case
++ * an error happens after this.
++ */
++ eie = NULL;
+ }
+ ret = ulist_add_merge_ptr(refs, ref->parent,
+ ref->inode_list,
+@@ -1393,6 +1417,14 @@ again:
+ eie->next = ref->inode_list;
+ }
+ eie = NULL;
++ /*
++ * We have transferred the inode list ownership from
++ * this ref to the ref we added to the 'refs' ulist.
++ * So set this ref's inode list to NULL to avoid
++ * use-after-free when our caller uses it or double
++ * frees in case an error happens before we return.
++ */
++ ref->inode_list = NULL;
+ }
+ cond_resched();
+ }
+@@ -1409,24 +1441,6 @@ out:
+ return ret;
+ }
+
+-static void free_leaf_list(struct ulist *blocks)
+-{
+- struct ulist_node *node = NULL;
+- struct extent_inode_elem *eie;
+- struct ulist_iterator uiter;
+-
+- ULIST_ITER_INIT(&uiter);
+- while ((node = ulist_next(blocks, &uiter))) {
+- if (!node->aux)
+- continue;
+- eie = unode_aux_to_inode_list(node);
+- free_inode_elem_list(eie);
+- node->aux = 0;
+- }
+-
+- ulist_free(blocks);
+-}
+-
+ /*
+ * Finds all leafs with a reference to the specified combination of bytenr and
+ * offset. key_list_head will point to a list of corresponding keys (caller must
+diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
+index df8c99c99df92..bad06add93d7e 100644
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -3407,7 +3407,10 @@ ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
+ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
+ const struct btrfs_ioctl_encoded_io_args *encoded);
+
+-ssize_t btrfs_dio_rw(struct kiocb *iocb, struct iov_iter *iter, size_t done_before);
++ssize_t btrfs_dio_read(struct kiocb *iocb, struct iov_iter *iter,
++ size_t done_before);
++struct iomap_dio *btrfs_dio_write(struct kiocb *iocb, struct iov_iter *iter,
++ size_t done_before);
+
+ extern const struct dentry_operations btrfs_dentry_operations;
+
+diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
+index 1d4c2397d0d62..fab7eb76e53b2 100644
+--- a/fs/btrfs/export.c
++++ b/fs/btrfs/export.c
+@@ -58,7 +58,7 @@ static int btrfs_encode_fh(struct inode *inode, u32 *fh, int *max_len,
+ }
+
+ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
+- u64 root_objectid, u32 generation,
++ u64 root_objectid, u64 generation,
+ int check_generation)
+ {
+ struct btrfs_fs_info *fs_info = btrfs_sb(sb);
+diff --git a/fs/btrfs/export.h b/fs/btrfs/export.h
+index f32f4113c976a..5afb7ca428289 100644
+--- a/fs/btrfs/export.h
++++ b/fs/btrfs/export.h
+@@ -19,7 +19,7 @@ struct btrfs_fid {
+ } __attribute__ ((packed));
+
+ struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
+- u64 root_objectid, u32 generation,
++ u64 root_objectid, u64 generation,
+ int check_generation);
+ struct dentry *btrfs_get_parent(struct dentry *child);
+
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index cfbbd7dc3c46b..32c3a5e5a3dd7 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -3294,21 +3294,22 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,
+ }
+
+ /*
+- * If this is a leaf and there are tree mod log users, we may
+- * have recorded mod log operations that point to this leaf.
+- * So we must make sure no one reuses this leaf's extent before
+- * mod log operations are applied to a node, otherwise after
+- * rewinding a node using the mod log operations we get an
+- * inconsistent btree, as the leaf's extent may now be used as
+- * a node or leaf for another different btree.
++ * If there are tree mod log users we may have recorded mod log
++ * operations for this node. If we re-allocate this node we
++ * could replay operations on this node that happened when it
++ * existed in a completely different root. For example if it
++ * was part of root A, then was reallocated to root B, and we
++ * are doing a btrfs_old_search_slot(root b), we could replay
++ * operations that happened when the block was part of root A,
++ * giving us an inconsistent view of the btree.
++ *
+ * We are safe from races here because at this point no other
+ * node or root points to this extent buffer, so if after this
+- * check a new tree mod log user joins, it will not be able to
+- * find a node pointing to this leaf and record operations that
+- * point to this leaf.
++ * check a new tree mod log user joins we will not have an
++ * existing log of operations on this node that we have to
++ * contend with.
+ */
+- if (btrfs_header_level(buf) == 0 &&
+- test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags))
++ if (test_bit(BTRFS_FS_TREE_MOD_LOG_USERS, &fs_info->flags))
+ must_pin = true;
+
+ if (must_pin || btrfs_is_zoned(fs_info)) {
+diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
+index 19e9df0c86496..db7c6d22190de 100644
+--- a/fs/btrfs/file.c
++++ b/fs/btrfs/file.c
+@@ -1889,6 +1889,7 @@ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from)
+ loff_t endbyte;
+ ssize_t err;
+ unsigned int ilock_flags = 0;
++ struct iomap_dio *dio;
+
+ if (iocb->ki_flags & IOCB_NOWAIT)
+ ilock_flags |= BTRFS_ILOCK_TRY;
+@@ -1949,11 +1950,22 @@ relock:
+ * So here we disable page faults in the iov_iter and then retry if we
+ * got -EFAULT, faulting in the pages before the retry.
+ */
+-again:
+ from->nofault = true;
+- err = btrfs_dio_rw(iocb, from, written);
++ dio = btrfs_dio_write(iocb, from, written);
+ from->nofault = false;
+
++ /*
++ * iomap_dio_complete() will call btrfs_sync_file() if we have a dsync
++ * iocb, and that needs to lock the inode. So unlock it before calling
++ * iomap_dio_complete() to avoid a deadlock.
++ */
++ btrfs_inode_unlock(inode, ilock_flags);
++
++ if (IS_ERR_OR_NULL(dio))
++ err = PTR_ERR_OR_ZERO(dio);
++ else
++ err = iomap_dio_complete(dio);
++
+ /* No increment (+=) because iomap returns a cumulative value. */
+ if (err > 0)
+ written = err;
+@@ -1979,12 +1991,10 @@ again:
+ } else {
+ fault_in_iov_iter_readable(from, left);
+ prev_left = left;
+- goto again;
++ goto relock;
+ }
+ }
+
+- btrfs_inode_unlock(inode, ilock_flags);
+-
+ /*
+ * If 'err' is -ENOTBLK or we have not written all data, then it means
+ * we must fallback to buffered IO.
+@@ -3787,7 +3797,7 @@ again:
+ */
+ pagefault_disable();
+ to->nofault = true;
+- ret = btrfs_dio_rw(iocb, to, read);
++ ret = btrfs_dio_read(iocb, to, read);
+ to->nofault = false;
+ pagefault_enable();
+
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index 1372210869b14..893693112fb80 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -8142,7 +8142,7 @@ static void btrfs_submit_direct(const struct iomap_iter *iter,
+ */
+ status = BLK_STS_RESOURCE;
+ dip->csums = kcalloc(nr_sectors, fs_info->csum_size, GFP_NOFS);
+- if (!dip)
++ if (!dip->csums)
+ goto out_err;
+
+ status = btrfs_lookup_bio_sums(inode, dio_bio, dip->csums);
+@@ -8241,13 +8241,21 @@ static const struct iomap_dio_ops btrfs_dio_ops = {
+ .bio_set = &btrfs_dio_bioset,
+ };
+
+-ssize_t btrfs_dio_rw(struct kiocb *iocb, struct iov_iter *iter, size_t done_before)
++ssize_t btrfs_dio_read(struct kiocb *iocb, struct iov_iter *iter, size_t done_before)
+ {
+ struct btrfs_dio_data data;
+
+ return iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
+- IOMAP_DIO_PARTIAL | IOMAP_DIO_NOSYNC,
+- &data, done_before);
++ IOMAP_DIO_PARTIAL, &data, done_before);
++}
++
++struct iomap_dio *btrfs_dio_write(struct kiocb *iocb, struct iov_iter *iter,
++ size_t done_before)
++{
++ struct btrfs_dio_data data;
++
++ return __iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
++ IOMAP_DIO_PARTIAL, &data, done_before);
+ }
+
+ static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
+diff --git a/fs/btrfs/tests/qgroup-tests.c b/fs/btrfs/tests/qgroup-tests.c
+index eee1e44595410..843dd3d3adbe7 100644
+--- a/fs/btrfs/tests/qgroup-tests.c
++++ b/fs/btrfs/tests/qgroup-tests.c
+@@ -232,8 +232,10 @@ static int test_no_shared_qgroup(struct btrfs_root *root,
+
+ ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
+ BTRFS_FS_TREE_OBJECTID);
+- if (ret)
++ if (ret) {
++ ulist_free(old_roots);
+ return ret;
++ }
+
+ ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
+ if (ret) {
+@@ -266,8 +268,10 @@ static int test_no_shared_qgroup(struct btrfs_root *root,
+ }
+
+ ret = remove_extent_item(root, nodesize, nodesize);
+- if (ret)
++ if (ret) {
++ ulist_free(old_roots);
+ return -EINVAL;
++ }
+
+ ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
+ if (ret) {
+@@ -329,8 +333,10 @@ static int test_multiple_refs(struct btrfs_root *root,
+
+ ret = insert_normal_tree_ref(root, nodesize, nodesize, 0,
+ BTRFS_FS_TREE_OBJECTID);
+- if (ret)
++ if (ret) {
++ ulist_free(old_roots);
+ return ret;
++ }
+
+ ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
+ if (ret) {
+@@ -362,8 +368,10 @@ static int test_multiple_refs(struct btrfs_root *root,
+
+ ret = add_tree_ref(root, nodesize, nodesize, 0,
+ BTRFS_FIRST_FREE_OBJECTID);
+- if (ret)
++ if (ret) {
++ ulist_free(old_roots);
+ return ret;
++ }
+
+ ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
+ if (ret) {
+@@ -401,8 +409,10 @@ static int test_multiple_refs(struct btrfs_root *root,
+
+ ret = remove_extent_ref(root, nodesize, nodesize, 0,
+ BTRFS_FIRST_FREE_OBJECTID);
+- if (ret)
++ if (ret) {
++ ulist_free(old_roots);
+ return ret;
++ }
+
+ ret = btrfs_find_all_roots(&trans, fs_info, nodesize, 0, &new_roots, false);
+ if (ret) {
+diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
+index f63ff91e28837..5d004772ab493 100644
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -7029,6 +7029,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
+ u64 devid;
+ u64 type;
+ u8 uuid[BTRFS_UUID_SIZE];
++ int index;
+ int num_stripes;
+ int ret;
+ int i;
+@@ -7036,6 +7037,7 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
+ logical = key->offset;
+ length = btrfs_chunk_length(leaf, chunk);
+ type = btrfs_chunk_type(leaf, chunk);
++ index = btrfs_bg_flags_to_raid_index(type);
+ num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
+
+ #if BITS_PER_LONG == 32
+@@ -7089,7 +7091,15 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
+ map->io_align = btrfs_chunk_io_align(leaf, chunk);
+ map->stripe_len = btrfs_chunk_stripe_len(leaf, chunk);
+ map->type = type;
+- map->sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk);
++ /*
++ * We can't use the sub_stripes value, as for profiles other than
++ * RAID10, they may have 0 as sub_stripes for filesystems created by
++ * older mkfs (<v5.4).
++ * In that case, it can cause divide-by-zero errors later.
++ * Since currently sub_stripes is fixed for each profile, let's
++ * use the trusted value instead.
++ */
++ map->sub_stripes = btrfs_raid_array[index].sub_stripes;
+ map->verified_stripes = 0;
+ em->orig_block_len = btrfs_calc_stripe_length(em);
+ for (i = 0; i < num_stripes; i++) {
+diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
+index e960dda893c63..c2c36451a8837 100644
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -3921,12 +3921,11 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
+ pSMB->AndXCommand = 0xFF;
+ pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
+ bcc_ptr = &pSMB->Password[0];
+- if (tcon->pipe || (ses->server->sec_mode & SECMODE_USER)) {
+- pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
+- *bcc_ptr = 0; /* password is null byte */
+- bcc_ptr++; /* skip password */
+- /* already aligned so no need to do it below */
+- }
++
++ pSMB->PasswordLength = cpu_to_le16(1); /* minimum */
++ *bcc_ptr = 0; /* password is null byte */
++ bcc_ptr++; /* skip password */
++ /* already aligned so no need to do it below */
+
+ if (ses->server->sign)
+ smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
+index 3afdaa0847736..577cae7facb01 100644
+--- a/fs/crypto/fscrypt_private.h
++++ b/fs/crypto/fscrypt_private.h
+@@ -225,7 +225,7 @@ struct fscrypt_info {
+ * will be NULL if the master key was found in a process-subscribed
+ * keyring rather than in the filesystem-level keyring.
+ */
+- struct key *ci_master_key;
++ struct fscrypt_master_key *ci_master_key;
+
+ /*
+ * Link in list of inodes that were unlocked with the master key.
+@@ -436,6 +436,40 @@ struct fscrypt_master_key_secret {
+ */
+ struct fscrypt_master_key {
+
++ /*
++ * Back-pointer to the super_block of the filesystem to which this
++ * master key has been added. Only valid if ->mk_active_refs > 0.
++ */
++ struct super_block *mk_sb;
++
++ /*
++ * Link in ->mk_sb->s_master_keys->key_hashtable.
++ * Only valid if ->mk_active_refs > 0.
++ */
++ struct hlist_node mk_node;
++
++ /* Semaphore that protects ->mk_secret and ->mk_users */
++ struct rw_semaphore mk_sem;
++
++ /*
++ * Active and structural reference counts. An active ref guarantees
++ * that the struct continues to exist, continues to be in the keyring
++ * ->mk_sb->s_master_keys, and that any embedded subkeys (e.g.
++ * ->mk_direct_keys) that have been prepared continue to exist.
++ * A structural ref only guarantees that the struct continues to exist.
++ *
++ * There is one active ref associated with ->mk_secret being present,
++ * and one active ref for each inode in ->mk_decrypted_inodes.
++ *
++ * There is one structural ref associated with the active refcount being
++ * nonzero. Finding a key in the keyring also takes a structural ref,
++ * which is then held temporarily while the key is operated on.
++ */
++ refcount_t mk_active_refs;
++ refcount_t mk_struct_refs;
++
++ struct rcu_head mk_rcu_head;
++
+ /*
+ * The secret key material. After FS_IOC_REMOVE_ENCRYPTION_KEY is
+ * executed, this is wiped and no new inodes can be unlocked with this
+@@ -444,7 +478,10 @@ struct fscrypt_master_key {
+ * FS_IOC_REMOVE_ENCRYPTION_KEY can be retried, or
+ * FS_IOC_ADD_ENCRYPTION_KEY can add the secret again.
+ *
+- * Locking: protected by this master key's key->sem.
++ * While ->mk_secret is present, one ref in ->mk_active_refs is held.
++ *
++ * Locking: protected by ->mk_sem. The manipulation of ->mk_active_refs
++ * associated with this field is protected by ->mk_sem as well.
+ */
+ struct fscrypt_master_key_secret mk_secret;
+
+@@ -465,22 +502,12 @@ struct fscrypt_master_key {
+ *
+ * This is NULL for v1 policy keys; those can only be added by root.
+ *
+- * Locking: in addition to this keyring's own semaphore, this is
+- * protected by this master key's key->sem, so we can do atomic
+- * search+insert. It can also be searched without taking any locks, but
+- * in that case the returned key may have already been removed.
++ * Locking: protected by ->mk_sem. (We don't just rely on the keyrings
++ * subsystem semaphore ->mk_users->sem, as we need support for atomic
++ * search+insert along with proper synchronization with ->mk_secret.)
+ */
+ struct key *mk_users;
+
+- /*
+- * Length of ->mk_decrypted_inodes, plus one if mk_secret is present.
+- * Once this goes to 0, the master key is removed from ->s_master_keys.
+- * The 'struct fscrypt_master_key' will continue to live as long as the
+- * 'struct key' whose payload it is, but we won't let this reference
+- * count rise again.
+- */
+- refcount_t mk_refcount;
+-
+ /*
+ * List of inodes that were unlocked using this key. This allows the
+ * inodes to be evicted efficiently if the key is removed.
+@@ -506,10 +533,10 @@ static inline bool
+ is_master_key_secret_present(const struct fscrypt_master_key_secret *secret)
+ {
+ /*
+- * The READ_ONCE() is only necessary for fscrypt_drop_inode() and
+- * fscrypt_key_describe(). These run in atomic context, so they can't
+- * take the key semaphore and thus 'secret' can change concurrently
+- * which would be a data race. But they only need to know whether the
++ * The READ_ONCE() is only necessary for fscrypt_drop_inode().
++ * fscrypt_drop_inode() runs in atomic context, so it can't take the key
++ * semaphore and thus 'secret' can change concurrently which would be a
++ * data race. But fscrypt_drop_inode() only need to know whether the
+ * secret *was* present at the time of check, so READ_ONCE() suffices.
+ */
+ return READ_ONCE(secret->size) != 0;
+@@ -538,7 +565,11 @@ static inline int master_key_spec_len(const struct fscrypt_key_specifier *spec)
+ return 0;
+ }
+
+-struct key *
++void fscrypt_put_master_key(struct fscrypt_master_key *mk);
++
++void fscrypt_put_master_key_activeref(struct fscrypt_master_key *mk);
++
++struct fscrypt_master_key *
+ fscrypt_find_master_key(struct super_block *sb,
+ const struct fscrypt_key_specifier *mk_spec);
+
+diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
+index 7c01025879b38..7b8c5a1104b58 100644
+--- a/fs/crypto/hooks.c
++++ b/fs/crypto/hooks.c
+@@ -5,8 +5,6 @@
+ * Encryption hooks for higher-level filesystem operations.
+ */
+
+-#include <linux/key.h>
+-
+ #include "fscrypt_private.h"
+
+ /**
+@@ -142,7 +140,6 @@ int fscrypt_prepare_setflags(struct inode *inode,
+ unsigned int oldflags, unsigned int flags)
+ {
+ struct fscrypt_info *ci;
+- struct key *key;
+ struct fscrypt_master_key *mk;
+ int err;
+
+@@ -158,14 +155,13 @@ int fscrypt_prepare_setflags(struct inode *inode,
+ ci = inode->i_crypt_info;
+ if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
+ return -EINVAL;
+- key = ci->ci_master_key;
+- mk = key->payload.data[0];
+- down_read(&key->sem);
++ mk = ci->ci_master_key;
++ down_read(&mk->mk_sem);
+ if (is_master_key_secret_present(&mk->mk_secret))
+ err = fscrypt_derive_dirhash_key(ci, mk);
+ else
+ err = -ENOKEY;
+- up_read(&key->sem);
++ up_read(&mk->mk_sem);
+ return err;
+ }
+ return 0;
+diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
+index caee9f8620dd9..f10ace12c05f8 100644
+--- a/fs/crypto/keyring.c
++++ b/fs/crypto/keyring.c
+@@ -18,6 +18,7 @@
+ * information about these ioctls.
+ */
+
++#include <asm/unaligned.h>
+ #include <crypto/skcipher.h>
+ #include <linux/key-type.h>
+ #include <linux/random.h>
+@@ -25,6 +26,18 @@
+
+ #include "fscrypt_private.h"
+
++/* The master encryption keys for a filesystem (->s_master_keys) */
++struct fscrypt_keyring {
++ /*
++ * Lock that protects ->key_hashtable. It does *not* protect the
++ * fscrypt_master_key structs themselves.
++ */
++ spinlock_t lock;
++
++ /* Hash table that maps fscrypt_key_specifier to fscrypt_master_key */
++ struct hlist_head key_hashtable[128];
++};
++
+ static void wipe_master_key_secret(struct fscrypt_master_key_secret *secret)
+ {
+ fscrypt_destroy_hkdf(&secret->hkdf);
+@@ -38,20 +51,70 @@ static void move_master_key_secret(struct fscrypt_master_key_secret *dst,
+ memzero_explicit(src, sizeof(*src));
+ }
+
+-static void free_master_key(struct fscrypt_master_key *mk)
++static void fscrypt_free_master_key(struct rcu_head *head)
++{
++ struct fscrypt_master_key *mk =
++ container_of(head, struct fscrypt_master_key, mk_rcu_head);
++ /*
++ * The master key secret and any embedded subkeys should have already
++ * been wiped when the last active reference to the fscrypt_master_key
++ * struct was dropped; doing it here would be unnecessarily late.
++ * Nevertheless, use kfree_sensitive() in case anything was missed.
++ */
++ kfree_sensitive(mk);
++}
++
++void fscrypt_put_master_key(struct fscrypt_master_key *mk)
++{
++ if (!refcount_dec_and_test(&mk->mk_struct_refs))
++ return;
++ /*
++ * No structural references left, so free ->mk_users, and also free the
++ * fscrypt_master_key struct itself after an RCU grace period ensures
++ * that concurrent keyring lookups can no longer find it.
++ */
++ WARN_ON(refcount_read(&mk->mk_active_refs) != 0);
++ key_put(mk->mk_users);
++ mk->mk_users = NULL;
++ call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key);
++}
++
++void fscrypt_put_master_key_activeref(struct fscrypt_master_key *mk)
+ {
++ struct super_block *sb = mk->mk_sb;
++ struct fscrypt_keyring *keyring = sb->s_master_keys;
+ size_t i;
+
+- wipe_master_key_secret(&mk->mk_secret);
++ if (!refcount_dec_and_test(&mk->mk_active_refs))
++ return;
++ /*
++ * No active references left, so complete the full removal of this
++ * fscrypt_master_key struct by removing it from the keyring and
++ * destroying any subkeys embedded in it.
++ */
++
++ spin_lock(&keyring->lock);
++ hlist_del_rcu(&mk->mk_node);
++ spin_unlock(&keyring->lock);
++
++ /*
++ * ->mk_active_refs == 0 implies that ->mk_secret is not present and
++ * that ->mk_decrypted_inodes is empty.
++ */
++ WARN_ON(is_master_key_secret_present(&mk->mk_secret));
++ WARN_ON(!list_empty(&mk->mk_decrypted_inodes));
+
+ for (i = 0; i <= FSCRYPT_MODE_MAX; i++) {
+ fscrypt_destroy_prepared_key(&mk->mk_direct_keys[i]);
+ fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_64_keys[i]);
+ fscrypt_destroy_prepared_key(&mk->mk_iv_ino_lblk_32_keys[i]);
+ }
++ memzero_explicit(&mk->mk_ino_hash_key,
++ sizeof(mk->mk_ino_hash_key));
++ mk->mk_ino_hash_key_initialized = false;
+
+- key_put(mk->mk_users);
+- kfree_sensitive(mk);
++ /* Drop the structural ref associated with the active refs. */
++ fscrypt_put_master_key(mk);
+ }
+
+ static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec)
+@@ -61,44 +124,6 @@ static inline bool valid_key_spec(const struct fscrypt_key_specifier *spec)
+ return master_key_spec_len(spec) != 0;
+ }
+
+-static int fscrypt_key_instantiate(struct key *key,
+- struct key_preparsed_payload *prep)
+-{
+- key->payload.data[0] = (struct fscrypt_master_key *)prep->data;
+- return 0;
+-}
+-
+-static void fscrypt_key_destroy(struct key *key)
+-{
+- free_master_key(key->payload.data[0]);
+-}
+-
+-static void fscrypt_key_describe(const struct key *key, struct seq_file *m)
+-{
+- seq_puts(m, key->description);
+-
+- if (key_is_positive(key)) {
+- const struct fscrypt_master_key *mk = key->payload.data[0];
+-
+- if (!is_master_key_secret_present(&mk->mk_secret))
+- seq_puts(m, ": secret removed");
+- }
+-}
+-
+-/*
+- * Type of key in ->s_master_keys. Each key of this type represents a master
+- * key which has been added to the filesystem. Its payload is a
+- * 'struct fscrypt_master_key'. The "." prefix in the key type name prevents
+- * users from adding keys of this type via the keyrings syscalls rather than via
+- * the intended method of FS_IOC_ADD_ENCRYPTION_KEY.
+- */
+-static struct key_type key_type_fscrypt = {
+- .name = "._fscrypt",
+- .instantiate = fscrypt_key_instantiate,
+- .destroy = fscrypt_key_destroy,
+- .describe = fscrypt_key_describe,
+-};
+-
+ static int fscrypt_user_key_instantiate(struct key *key,
+ struct key_preparsed_payload *prep)
+ {
+@@ -131,32 +156,6 @@ static struct key_type key_type_fscrypt_user = {
+ .describe = fscrypt_user_key_describe,
+ };
+
+-/* Search ->s_master_keys or ->mk_users */
+-static struct key *search_fscrypt_keyring(struct key *keyring,
+- struct key_type *type,
+- const char *description)
+-{
+- /*
+- * We need to mark the keyring reference as "possessed" so that we
+- * acquire permission to search it, via the KEY_POS_SEARCH permission.
+- */
+- key_ref_t keyref = make_key_ref(keyring, true /* possessed */);
+-
+- keyref = keyring_search(keyref, type, description, false);
+- if (IS_ERR(keyref)) {
+- if (PTR_ERR(keyref) == -EAGAIN || /* not found */
+- PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */
+- keyref = ERR_PTR(-ENOKEY);
+- return ERR_CAST(keyref);
+- }
+- return key_ref_to_ptr(keyref);
+-}
+-
+-#define FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE \
+- (CONST_STRLEN("fscrypt-") + sizeof_field(struct super_block, s_id))
+-
+-#define FSCRYPT_MK_DESCRIPTION_SIZE (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1)
+-
+ #define FSCRYPT_MK_USERS_DESCRIPTION_SIZE \
+ (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \
+ CONST_STRLEN("-users") + 1)
+@@ -164,21 +163,6 @@ static struct key *search_fscrypt_keyring(struct key *keyring,
+ #define FSCRYPT_MK_USER_DESCRIPTION_SIZE \
+ (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1)
+
+-static void format_fs_keyring_description(
+- char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE],
+- const struct super_block *sb)
+-{
+- sprintf(description, "fscrypt-%s", sb->s_id);
+-}
+-
+-static void format_mk_description(
+- char description[FSCRYPT_MK_DESCRIPTION_SIZE],
+- const struct fscrypt_key_specifier *mk_spec)
+-{
+- sprintf(description, "%*phN",
+- master_key_spec_len(mk_spec), (u8 *)&mk_spec->u);
+-}
+-
+ static void format_mk_users_keyring_description(
+ char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE],
+ const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
+@@ -199,20 +183,15 @@ static void format_mk_user_description(
+ /* Create ->s_master_keys if needed. Synchronized by fscrypt_add_key_mutex. */
+ static int allocate_filesystem_keyring(struct super_block *sb)
+ {
+- char description[FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE];
+- struct key *keyring;
++ struct fscrypt_keyring *keyring;
+
+ if (sb->s_master_keys)
+ return 0;
+
+- format_fs_keyring_description(description, sb);
+- keyring = keyring_alloc(description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
+- current_cred(), KEY_POS_SEARCH |
+- KEY_USR_SEARCH | KEY_USR_READ | KEY_USR_VIEW,
+- KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
+- if (IS_ERR(keyring))
+- return PTR_ERR(keyring);
+-
++ keyring = kzalloc(sizeof(*keyring), GFP_KERNEL);
++ if (!keyring)
++ return -ENOMEM;
++ spin_lock_init(&keyring->lock);
+ /*
+ * Pairs with the smp_load_acquire() in fscrypt_find_master_key().
+ * I.e., here we publish ->s_master_keys with a RELEASE barrier so that
+@@ -222,21 +201,80 @@ static int allocate_filesystem_keyring(struct super_block *sb)
+ return 0;
+ }
+
+-void fscrypt_sb_free(struct super_block *sb)
++/*
++ * Release all encryption keys that have been added to the filesystem, along
++ * with the keyring that contains them.
++ *
++ * This is called at unmount time. The filesystem's underlying block device(s)
++ * are still available at this time; this is important because after user file
++ * accesses have been allowed, this function may need to evict keys from the
++ * keyslots of an inline crypto engine, which requires the block device(s).
++ *
++ * This is also called when the super_block is being freed. This is needed to
++ * avoid a memory leak if mounting fails after the "test_dummy_encryption"
++ * option was processed, as in that case the unmount-time call isn't made.
++ */
++void fscrypt_destroy_keyring(struct super_block *sb)
+ {
+- key_put(sb->s_master_keys);
++ struct fscrypt_keyring *keyring = sb->s_master_keys;
++ size_t i;
++
++ if (!keyring)
++ return;
++
++ for (i = 0; i < ARRAY_SIZE(keyring->key_hashtable); i++) {
++ struct hlist_head *bucket = &keyring->key_hashtable[i];
++ struct fscrypt_master_key *mk;
++ struct hlist_node *tmp;
++
++ hlist_for_each_entry_safe(mk, tmp, bucket, mk_node) {
++ /*
++ * Since all inodes were already evicted, every key
++ * remaining in the keyring should have an empty inode
++ * list, and should only still be in the keyring due to
++ * the single active ref associated with ->mk_secret.
++ * There should be no structural refs beyond the one
++ * associated with the active ref.
++ */
++ WARN_ON(refcount_read(&mk->mk_active_refs) != 1);
++ WARN_ON(refcount_read(&mk->mk_struct_refs) != 1);
++ WARN_ON(!is_master_key_secret_present(&mk->mk_secret));
++ wipe_master_key_secret(&mk->mk_secret);
++ fscrypt_put_master_key_activeref(mk);
++ }
++ }
++ kfree_sensitive(keyring);
+ sb->s_master_keys = NULL;
+ }
+
++static struct hlist_head *
++fscrypt_mk_hash_bucket(struct fscrypt_keyring *keyring,
++ const struct fscrypt_key_specifier *mk_spec)
++{
++ /*
++ * Since key specifiers should be "random" values, it is sufficient to
++ * use a trivial hash function that just takes the first several bits of
++ * the key specifier.
++ */
++ unsigned long i = get_unaligned((unsigned long *)&mk_spec->u);
++
++ return &keyring->key_hashtable[i % ARRAY_SIZE(keyring->key_hashtable)];
++}
++
+ /*
+- * Find the specified master key in ->s_master_keys.
+- * Returns ERR_PTR(-ENOKEY) if not found.
++ * Find the specified master key struct in ->s_master_keys and take a structural
++ * ref to it. The structural ref guarantees that the key struct continues to
++ * exist, but it does *not* guarantee that ->s_master_keys continues to contain
++ * the key struct. The structural ref needs to be dropped by
++ * fscrypt_put_master_key(). Returns NULL if the key struct is not found.
+ */
+-struct key *fscrypt_find_master_key(struct super_block *sb,
+- const struct fscrypt_key_specifier *mk_spec)
++struct fscrypt_master_key *
++fscrypt_find_master_key(struct super_block *sb,
++ const struct fscrypt_key_specifier *mk_spec)
+ {
+- struct key *keyring;
+- char description[FSCRYPT_MK_DESCRIPTION_SIZE];
++ struct fscrypt_keyring *keyring;
++ struct hlist_head *bucket;
++ struct fscrypt_master_key *mk;
+
+ /*
+ * Pairs with the smp_store_release() in allocate_filesystem_keyring().
+@@ -246,10 +284,38 @@ struct key *fscrypt_find_master_key(struct super_block *sb,
+ */
+ keyring = smp_load_acquire(&sb->s_master_keys);
+ if (keyring == NULL)
+- return ERR_PTR(-ENOKEY); /* No keyring yet, so no keys yet. */
+-
+- format_mk_description(description, mk_spec);
+- return search_fscrypt_keyring(keyring, &key_type_fscrypt, description);
++ return NULL; /* No keyring yet, so no keys yet. */
++
++ bucket = fscrypt_mk_hash_bucket(keyring, mk_spec);
++ rcu_read_lock();
++ switch (mk_spec->type) {
++ case FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR:
++ hlist_for_each_entry_rcu(mk, bucket, mk_node) {
++ if (mk->mk_spec.type ==
++ FSCRYPT_KEY_SPEC_TYPE_DESCRIPTOR &&
++ memcmp(mk->mk_spec.u.descriptor,
++ mk_spec->u.descriptor,
++ FSCRYPT_KEY_DESCRIPTOR_SIZE) == 0 &&
++ refcount_inc_not_zero(&mk->mk_struct_refs))
++ goto out;
++ }
++ break;
++ case FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER:
++ hlist_for_each_entry_rcu(mk, bucket, mk_node) {
++ if (mk->mk_spec.type ==
++ FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER &&
++ memcmp(mk->mk_spec.u.identifier,
++ mk_spec->u.identifier,
++ FSCRYPT_KEY_IDENTIFIER_SIZE) == 0 &&
++ refcount_inc_not_zero(&mk->mk_struct_refs))
++ goto out;
++ }
++ break;
++ }
++ mk = NULL;
++out:
++ rcu_read_unlock();
++ return mk;
+ }
+
+ static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
+@@ -277,17 +343,30 @@ static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk)
+ static struct key *find_master_key_user(struct fscrypt_master_key *mk)
+ {
+ char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE];
++ key_ref_t keyref;
+
+ format_mk_user_description(description, mk->mk_spec.u.identifier);
+- return search_fscrypt_keyring(mk->mk_users, &key_type_fscrypt_user,
+- description);
++
++ /*
++ * We need to mark the keyring reference as "possessed" so that we
++ * acquire permission to search it, via the KEY_POS_SEARCH permission.
++ */
++ keyref = keyring_search(make_key_ref(mk->mk_users, true /*possessed*/),
++ &key_type_fscrypt_user, description, false);
++ if (IS_ERR(keyref)) {
++ if (PTR_ERR(keyref) == -EAGAIN || /* not found */
++ PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */
++ keyref = ERR_PTR(-ENOKEY);
++ return ERR_CAST(keyref);
++ }
++ return key_ref_to_ptr(keyref);
+ }
+
+ /*
+ * Give the current user a "key" in ->mk_users. This charges the user's quota
+ * and marks the master key as added by the current user, so that it cannot be
+- * removed by another user with the key. Either the master key's key->sem must
+- * be held for write, or the master key must be still undergoing initialization.
++ * removed by another user with the key. Either ->mk_sem must be held for
++ * write, or the master key must be still undergoing initialization.
+ */
+ static int add_master_key_user(struct fscrypt_master_key *mk)
+ {
+@@ -309,7 +388,7 @@ static int add_master_key_user(struct fscrypt_master_key *mk)
+
+ /*
+ * Remove the current user's "key" from ->mk_users.
+- * The master key's key->sem must be held for write.
++ * ->mk_sem must be held for write.
+ *
+ * Returns 0 if removed, -ENOKEY if not found, or another -errno code.
+ */
+@@ -327,63 +406,49 @@ static int remove_master_key_user(struct fscrypt_master_key *mk)
+ }
+
+ /*
+- * Allocate a new fscrypt_master_key which contains the given secret, set it as
+- * the payload of a new 'struct key' of type fscrypt, and link the 'struct key'
+- * into the given keyring. Synchronized by fscrypt_add_key_mutex.
++ * Allocate a new fscrypt_master_key, transfer the given secret over to it, and
++ * insert it into sb->s_master_keys.
+ */
+-static int add_new_master_key(struct fscrypt_master_key_secret *secret,
+- const struct fscrypt_key_specifier *mk_spec,
+- struct key *keyring)
++static int add_new_master_key(struct super_block *sb,
++ struct fscrypt_master_key_secret *secret,
++ const struct fscrypt_key_specifier *mk_spec)
+ {
++ struct fscrypt_keyring *keyring = sb->s_master_keys;
+ struct fscrypt_master_key *mk;
+- char description[FSCRYPT_MK_DESCRIPTION_SIZE];
+- struct key *key;
+ int err;
+
+ mk = kzalloc(sizeof(*mk), GFP_KERNEL);
+ if (!mk)
+ return -ENOMEM;
+
++ mk->mk_sb = sb;
++ init_rwsem(&mk->mk_sem);
++ refcount_set(&mk->mk_struct_refs, 1);
+ mk->mk_spec = *mk_spec;
+
+- move_master_key_secret(&mk->mk_secret, secret);
+-
+- refcount_set(&mk->mk_refcount, 1); /* secret is present */
+ INIT_LIST_HEAD(&mk->mk_decrypted_inodes);
+ spin_lock_init(&mk->mk_decrypted_inodes_lock);
+
+ if (mk_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) {
+ err = allocate_master_key_users_keyring(mk);
+ if (err)
+- goto out_free_mk;
++ goto out_put;
+ err = add_master_key_user(mk);
+ if (err)
+- goto out_free_mk;
++ goto out_put;
+ }
+
+- /*
+- * Note that we don't charge this key to anyone's quota, since when
+- * ->mk_users is in use those keys are charged instead, and otherwise
+- * (when ->mk_users isn't in use) only root can add these keys.
+- */
+- format_mk_description(description, mk_spec);
+- key = key_alloc(&key_type_fscrypt, description,
+- GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(),
+- KEY_POS_SEARCH | KEY_USR_SEARCH | KEY_USR_VIEW,
+- KEY_ALLOC_NOT_IN_QUOTA, NULL);
+- if (IS_ERR(key)) {
+- err = PTR_ERR(key);
+- goto out_free_mk;
+- }
+- err = key_instantiate_and_link(key, mk, sizeof(*mk), keyring, NULL);
+- key_put(key);
+- if (err)
+- goto out_free_mk;
++ move_master_key_secret(&mk->mk_secret, secret);
++ refcount_set(&mk->mk_active_refs, 1); /* ->mk_secret is present */
+
++ spin_lock(&keyring->lock);
++ hlist_add_head_rcu(&mk->mk_node,
++ fscrypt_mk_hash_bucket(keyring, mk_spec));
++ spin_unlock(&keyring->lock);
+ return 0;
+
+-out_free_mk:
+- free_master_key(mk);
++out_put:
++ fscrypt_put_master_key(mk);
+ return err;
+ }
+
+@@ -392,42 +457,34 @@ out_free_mk:
+ static int add_existing_master_key(struct fscrypt_master_key *mk,
+ struct fscrypt_master_key_secret *secret)
+ {
+- struct key *mk_user;
+- bool rekey;
+ int err;
+
+ /*
+ * If the current user is already in ->mk_users, then there's nothing to
+- * do. (Not applicable for v1 policy keys, which have NULL ->mk_users.)
++ * do. Otherwise, we need to add the user to ->mk_users. (Neither is
++ * applicable for v1 policy keys, which have NULL ->mk_users.)
+ */
+ if (mk->mk_users) {
+- mk_user = find_master_key_user(mk);
++ struct key *mk_user = find_master_key_user(mk);
++
+ if (mk_user != ERR_PTR(-ENOKEY)) {
+ if (IS_ERR(mk_user))
+ return PTR_ERR(mk_user);
+ key_put(mk_user);
+ return 0;
+ }
+- }
+-
+- /* If we'll be re-adding ->mk_secret, try to take the reference. */
+- rekey = !is_master_key_secret_present(&mk->mk_secret);
+- if (rekey && !refcount_inc_not_zero(&mk->mk_refcount))
+- return KEY_DEAD;
+-
+- /* Add the current user to ->mk_users, if applicable. */
+- if (mk->mk_users) {
+ err = add_master_key_user(mk);
+- if (err) {
+- if (rekey && refcount_dec_and_test(&mk->mk_refcount))
+- return KEY_DEAD;
++ if (err)
+ return err;
+- }
+ }
+
+ /* Re-add the secret if needed. */
+- if (rekey)
++ if (!is_master_key_secret_present(&mk->mk_secret)) {
++ if (!refcount_inc_not_zero(&mk->mk_active_refs))
++ return KEY_DEAD;
+ move_master_key_secret(&mk->mk_secret, secret);
++ }
++
+ return 0;
+ }
+
+@@ -436,38 +493,36 @@ static int do_add_master_key(struct super_block *sb,
+ const struct fscrypt_key_specifier *mk_spec)
+ {
+ static DEFINE_MUTEX(fscrypt_add_key_mutex);
+- struct key *key;
++ struct fscrypt_master_key *mk;
+ int err;
+
+ mutex_lock(&fscrypt_add_key_mutex); /* serialize find + link */
+-retry:
+- key = fscrypt_find_master_key(sb, mk_spec);
+- if (IS_ERR(key)) {
+- err = PTR_ERR(key);
+- if (err != -ENOKEY)
+- goto out_unlock;
++
++ mk = fscrypt_find_master_key(sb, mk_spec);
++ if (!mk) {
+ /* Didn't find the key in ->s_master_keys. Add it. */
+ err = allocate_filesystem_keyring(sb);
+- if (err)
+- goto out_unlock;
+- err = add_new_master_key(secret, mk_spec, sb->s_master_keys);
++ if (!err)
++ err = add_new_master_key(sb, secret, mk_spec);
+ } else {
+ /*
+ * Found the key in ->s_master_keys. Re-add the secret if
+ * needed, and add the user to ->mk_users if needed.
+ */
+- down_write(&key->sem);
+- err = add_existing_master_key(key->payload.data[0], secret);
+- up_write(&key->sem);
++ down_write(&mk->mk_sem);
++ err = add_existing_master_key(mk, secret);
++ up_write(&mk->mk_sem);
+ if (err == KEY_DEAD) {
+- /* Key being removed or needs to be removed */
+- key_invalidate(key);
+- key_put(key);
+- goto retry;
++ /*
++ * We found a key struct, but it's already been fully
++ * removed. Ignore the old struct and add a new one.
++ * fscrypt_add_key_mutex means we don't need to worry
++ * about concurrent adds.
++ */
++ err = add_new_master_key(sb, secret, mk_spec);
+ }
+- key_put(key);
++ fscrypt_put_master_key(mk);
+ }
+-out_unlock:
+ mutex_unlock(&fscrypt_add_key_mutex);
+ return err;
+ }
+@@ -771,19 +826,19 @@ int fscrypt_verify_key_added(struct super_block *sb,
+ const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE])
+ {
+ struct fscrypt_key_specifier mk_spec;
+- struct key *key, *mk_user;
+ struct fscrypt_master_key *mk;
++ struct key *mk_user;
+ int err;
+
+ mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER;
+ memcpy(mk_spec.u.identifier, identifier, FSCRYPT_KEY_IDENTIFIER_SIZE);
+
+- key = fscrypt_find_master_key(sb, &mk_spec);
+- if (IS_ERR(key)) {
+- err = PTR_ERR(key);
++ mk = fscrypt_find_master_key(sb, &mk_spec);
++ if (!mk) {
++ err = -ENOKEY;
+ goto out;
+ }
+- mk = key->payload.data[0];
++ down_read(&mk->mk_sem);
+ mk_user = find_master_key_user(mk);
+ if (IS_ERR(mk_user)) {
+ err = PTR_ERR(mk_user);
+@@ -791,7 +846,8 @@ int fscrypt_verify_key_added(struct super_block *sb,
+ key_put(mk_user);
+ err = 0;
+ }
+- key_put(key);
++ up_read(&mk->mk_sem);
++ fscrypt_put_master_key(mk);
+ out:
+ if (err == -ENOKEY && capable(CAP_FOWNER))
+ err = 0;
+@@ -953,11 +1009,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
+ struct super_block *sb = file_inode(filp)->i_sb;
+ struct fscrypt_remove_key_arg __user *uarg = _uarg;
+ struct fscrypt_remove_key_arg arg;
+- struct key *key;
+ struct fscrypt_master_key *mk;
+ u32 status_flags = 0;
+ int err;
+- bool dead;
++ bool inodes_remain;
+
+ if (copy_from_user(&arg, uarg, sizeof(arg)))
+ return -EFAULT;
+@@ -977,12 +1032,10 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
+ return -EACCES;
+
+ /* Find the key being removed. */
+- key = fscrypt_find_master_key(sb, &arg.key_spec);
+- if (IS_ERR(key))
+- return PTR_ERR(key);
+- mk = key->payload.data[0];
+-
+- down_write(&key->sem);
++ mk = fscrypt_find_master_key(sb, &arg.key_spec);
++ if (!mk)
++ return -ENOKEY;
++ down_write(&mk->mk_sem);
+
+ /* If relevant, remove current user's (or all users) claim to the key */
+ if (mk->mk_users && mk->mk_users->keys.nr_leaves_on_tree != 0) {
+@@ -991,7 +1044,7 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
+ else
+ err = remove_master_key_user(mk);
+ if (err) {
+- up_write(&key->sem);
++ up_write(&mk->mk_sem);
+ goto out_put_key;
+ }
+ if (mk->mk_users->keys.nr_leaves_on_tree != 0) {
+@@ -1003,26 +1056,22 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
+ status_flags |=
+ FSCRYPT_KEY_REMOVAL_STATUS_FLAG_OTHER_USERS;
+ err = 0;
+- up_write(&key->sem);
++ up_write(&mk->mk_sem);
+ goto out_put_key;
+ }
+ }
+
+ /* No user claims remaining. Go ahead and wipe the secret. */
+- dead = false;
++ err = -ENOKEY;
+ if (is_master_key_secret_present(&mk->mk_secret)) {
+ wipe_master_key_secret(&mk->mk_secret);
+- dead = refcount_dec_and_test(&mk->mk_refcount);
+- }
+- up_write(&key->sem);
+- if (dead) {
+- /*
+- * No inodes reference the key, and we wiped the secret, so the
+- * key object is free to be removed from the keyring.
+- */
+- key_invalidate(key);
++ fscrypt_put_master_key_activeref(mk);
+ err = 0;
+- } else {
++ }
++ inodes_remain = refcount_read(&mk->mk_active_refs) > 0;
++ up_write(&mk->mk_sem);
++
++ if (inodes_remain) {
+ /* Some inodes still reference this key; try to evict them. */
+ err = try_to_lock_encrypted_files(sb, mk);
+ if (err == -EBUSY) {
+@@ -1038,7 +1087,7 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users)
+ * has been fully removed including all files locked.
+ */
+ out_put_key:
+- key_put(key);
++ fscrypt_put_master_key(mk);
+ if (err == 0)
+ err = put_user(status_flags, &uarg->removal_status_flags);
+ return err;
+@@ -1085,7 +1134,6 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
+ {
+ struct super_block *sb = file_inode(filp)->i_sb;
+ struct fscrypt_get_key_status_arg arg;
+- struct key *key;
+ struct fscrypt_master_key *mk;
+ int err;
+
+@@ -1102,19 +1150,18 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
+ arg.user_count = 0;
+ memset(arg.__out_reserved, 0, sizeof(arg.__out_reserved));
+
+- key = fscrypt_find_master_key(sb, &arg.key_spec);
+- if (IS_ERR(key)) {
+- if (key != ERR_PTR(-ENOKEY))
+- return PTR_ERR(key);
++ mk = fscrypt_find_master_key(sb, &arg.key_spec);
++ if (!mk) {
+ arg.status = FSCRYPT_KEY_STATUS_ABSENT;
+ err = 0;
+ goto out;
+ }
+- mk = key->payload.data[0];
+- down_read(&key->sem);
++ down_read(&mk->mk_sem);
+
+ if (!is_master_key_secret_present(&mk->mk_secret)) {
+- arg.status = FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED;
++ arg.status = refcount_read(&mk->mk_active_refs) > 0 ?
++ FSCRYPT_KEY_STATUS_INCOMPLETELY_REMOVED :
++ FSCRYPT_KEY_STATUS_ABSENT /* raced with full removal */;
+ err = 0;
+ goto out_release_key;
+ }
+@@ -1136,8 +1183,8 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg)
+ }
+ err = 0;
+ out_release_key:
+- up_read(&key->sem);
+- key_put(key);
++ up_read(&mk->mk_sem);
++ fscrypt_put_master_key(mk);
+ out:
+ if (!err && copy_to_user(uarg, &arg, sizeof(arg)))
+ err = -EFAULT;
+@@ -1149,13 +1196,9 @@ int __init fscrypt_init_keyring(void)
+ {
+ int err;
+
+- err = register_key_type(&key_type_fscrypt);
+- if (err)
+- return err;
+-
+ err = register_key_type(&key_type_fscrypt_user);
+ if (err)
+- goto err_unregister_fscrypt;
++ return err;
+
+ err = register_key_type(&key_type_fscrypt_provisioning);
+ if (err)
+@@ -1165,7 +1208,5 @@ int __init fscrypt_init_keyring(void)
+
+ err_unregister_fscrypt_user:
+ unregister_key_type(&key_type_fscrypt_user);
+-err_unregister_fscrypt:
+- unregister_key_type(&key_type_fscrypt);
+ return err;
+ }
+diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
+index fbc71abdabe32..e037a7b8e9e42 100644
+--- a/fs/crypto/keysetup.c
++++ b/fs/crypto/keysetup.c
+@@ -9,7 +9,6 @@
+ */
+
+ #include <crypto/skcipher.h>
+-#include <linux/key.h>
+ #include <linux/random.h>
+
+ #include "fscrypt_private.h"
+@@ -159,6 +158,7 @@ void fscrypt_destroy_prepared_key(struct fscrypt_prepared_key *prep_key)
+ {
+ crypto_free_skcipher(prep_key->tfm);
+ fscrypt_destroy_inline_crypt_key(prep_key);
++ memzero_explicit(prep_key, sizeof(*prep_key));
+ }
+
+ /* Given a per-file encryption key, set up the file's crypto transform object */
+@@ -412,20 +412,18 @@ static bool fscrypt_valid_master_key_size(const struct fscrypt_master_key *mk,
+ /*
+ * Find the master key, then set up the inode's actual encryption key.
+ *
+- * If the master key is found in the filesystem-level keyring, then the
+- * corresponding 'struct key' is returned in *master_key_ret with its semaphore
+- * read-locked. This is needed to ensure that only one task links the
+- * fscrypt_info into ->mk_decrypted_inodes (as multiple tasks may race to create
+- * an fscrypt_info for the same inode), and to synchronize the master key being
+- * removed with a new inode starting to use it.
++ * If the master key is found in the filesystem-level keyring, then it is
++ * returned in *mk_ret with its semaphore read-locked. This is needed to ensure
++ * that only one task links the fscrypt_info into ->mk_decrypted_inodes (as
++ * multiple tasks may race to create an fscrypt_info for the same inode), and to
++ * synchronize the master key being removed with a new inode starting to use it.
+ */
+ static int setup_file_encryption_key(struct fscrypt_info *ci,
+ bool need_dirhash_key,
+- struct key **master_key_ret)
++ struct fscrypt_master_key **mk_ret)
+ {
+- struct key *key;
+- struct fscrypt_master_key *mk = NULL;
+ struct fscrypt_key_specifier mk_spec;
++ struct fscrypt_master_key *mk;
+ int err;
+
+ err = fscrypt_select_encryption_impl(ci);
+@@ -436,11 +434,10 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
+ if (err)
+ return err;
+
+- key = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec);
+- if (IS_ERR(key)) {
+- if (key != ERR_PTR(-ENOKEY) ||
+- ci->ci_policy.version != FSCRYPT_POLICY_V1)
+- return PTR_ERR(key);
++ mk = fscrypt_find_master_key(ci->ci_inode->i_sb, &mk_spec);
++ if (!mk) {
++ if (ci->ci_policy.version != FSCRYPT_POLICY_V1)
++ return -ENOKEY;
+
+ /*
+ * As a legacy fallback for v1 policies, search for the key in
+@@ -450,9 +447,7 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
+ */
+ return fscrypt_setup_v1_file_key_via_subscribed_keyrings(ci);
+ }
+-
+- mk = key->payload.data[0];
+- down_read(&key->sem);
++ down_read(&mk->mk_sem);
+
+ /* Has the secret been removed (via FS_IOC_REMOVE_ENCRYPTION_KEY)? */
+ if (!is_master_key_secret_present(&mk->mk_secret)) {
+@@ -480,18 +475,18 @@ static int setup_file_encryption_key(struct fscrypt_info *ci,
+ if (err)
+ goto out_release_key;
+
+- *master_key_ret = key;
++ *mk_ret = mk;
+ return 0;
+
+ out_release_key:
+- up_read(&key->sem);
+- key_put(key);
++ up_read(&mk->mk_sem);
++ fscrypt_put_master_key(mk);
+ return err;
+ }
+
+ static void put_crypt_info(struct fscrypt_info *ci)
+ {
+- struct key *key;
++ struct fscrypt_master_key *mk;
+
+ if (!ci)
+ return;
+@@ -501,24 +496,18 @@ static void put_crypt_info(struct fscrypt_info *ci)
+ else if (ci->ci_owns_key)
+ fscrypt_destroy_prepared_key(&ci->ci_enc_key);
+
+- key = ci->ci_master_key;
+- if (key) {
+- struct fscrypt_master_key *mk = key->payload.data[0];
+-
++ mk = ci->ci_master_key;
++ if (mk) {
+ /*
+ * Remove this inode from the list of inodes that were unlocked
+- * with the master key.
+- *
+- * In addition, if we're removing the last inode from a key that
+- * already had its secret removed, invalidate the key so that it
+- * gets removed from ->s_master_keys.
++ * with the master key. In addition, if we're removing the last
++ * inode from a master key struct that already had its secret
++ * removed, then complete the full removal of the struct.
+ */
+ spin_lock(&mk->mk_decrypted_inodes_lock);
+ list_del(&ci->ci_master_key_link);
+ spin_unlock(&mk->mk_decrypted_inodes_lock);
+- if (refcount_dec_and_test(&mk->mk_refcount))
+- key_invalidate(key);
+- key_put(key);
++ fscrypt_put_master_key_activeref(mk);
+ }
+ memzero_explicit(ci, sizeof(*ci));
+ kmem_cache_free(fscrypt_info_cachep, ci);
+@@ -532,7 +521,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
+ {
+ struct fscrypt_info *crypt_info;
+ struct fscrypt_mode *mode;
+- struct key *master_key = NULL;
++ struct fscrypt_master_key *mk = NULL;
+ int res;
+
+ res = fscrypt_initialize(inode->i_sb->s_cop->flags);
+@@ -555,8 +544,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
+ WARN_ON(mode->ivsize > FSCRYPT_MAX_IV_SIZE);
+ crypt_info->ci_mode = mode;
+
+- res = setup_file_encryption_key(crypt_info, need_dirhash_key,
+- &master_key);
++ res = setup_file_encryption_key(crypt_info, need_dirhash_key, &mk);
+ if (res)
+ goto out;
+
+@@ -571,12 +559,9 @@ fscrypt_setup_encryption_info(struct inode *inode,
+ * We won the race and set ->i_crypt_info to our crypt_info.
+ * Now link it into the master key's inode list.
+ */
+- if (master_key) {
+- struct fscrypt_master_key *mk =
+- master_key->payload.data[0];
+-
+- refcount_inc(&mk->mk_refcount);
+- crypt_info->ci_master_key = key_get(master_key);
++ if (mk) {
++ crypt_info->ci_master_key = mk;
++ refcount_inc(&mk->mk_active_refs);
+ spin_lock(&mk->mk_decrypted_inodes_lock);
+ list_add(&crypt_info->ci_master_key_link,
+ &mk->mk_decrypted_inodes);
+@@ -586,9 +571,9 @@ fscrypt_setup_encryption_info(struct inode *inode,
+ }
+ res = 0;
+ out:
+- if (master_key) {
+- up_read(&master_key->sem);
+- key_put(master_key);
++ if (mk) {
++ up_read(&mk->mk_sem);
++ fscrypt_put_master_key(mk);
+ }
+ put_crypt_info(crypt_info);
+ return res;
+@@ -753,7 +738,6 @@ EXPORT_SYMBOL(fscrypt_free_inode);
+ int fscrypt_drop_inode(struct inode *inode)
+ {
+ const struct fscrypt_info *ci = fscrypt_get_info(inode);
+- const struct fscrypt_master_key *mk;
+
+ /*
+ * If ci is NULL, then the inode doesn't have an encryption key set up
+@@ -763,7 +747,6 @@ int fscrypt_drop_inode(struct inode *inode)
+ */
+ if (!ci || !ci->ci_master_key)
+ return 0;
+- mk = ci->ci_master_key->payload.data[0];
+
+ /*
+ * With proper, non-racy use of FS_IOC_REMOVE_ENCRYPTION_KEY, all inodes
+@@ -782,6 +765,6 @@ int fscrypt_drop_inode(struct inode *inode)
+ * then the thread removing the key will either evict the inode itself
+ * or will correctly detect that it wasn't evicted due to the race.
+ */
+- return !is_master_key_secret_present(&mk->mk_secret);
++ return !is_master_key_secret_present(&ci->ci_master_key->mk_secret);
+ }
+ EXPORT_SYMBOL_GPL(fscrypt_drop_inode);
+diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c
+index 80b8ca0f340b2..8485e7eaee2b3 100644
+--- a/fs/crypto/policy.c
++++ b/fs/crypto/policy.c
+@@ -744,12 +744,8 @@ int fscrypt_set_context(struct inode *inode, void *fs_data)
+ * delayed key setup that requires the inode number.
+ */
+ if (ci->ci_policy.version == FSCRYPT_POLICY_V2 &&
+- (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) {
+- const struct fscrypt_master_key *mk =
+- ci->ci_master_key->payload.data[0];
+-
+- fscrypt_hash_inode_number(ci, mk);
+- }
++ (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
++ fscrypt_hash_inode_number(ci, ci->ci_master_key);
+
+ return inode->i_sb->s_cop->set_context(inode, &ctx, ctxsize, fs_data);
+ }
+diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
+index ad3a294a88eb2..eed8bd7812d58 100644
+--- a/fs/ext4/ioctl.c
++++ b/fs/ext4/ioctl.c
+@@ -145,9 +145,8 @@ static int ext4_update_backup_sb(struct super_block *sb,
+ if (ext4_has_metadata_csum(sb) &&
+ es->s_checksum != ext4_superblock_csum(sb, es)) {
+ ext4_msg(sb, KERN_ERR, "Invalid checksum for backup "
+- "superblock %llu\n", sb_block);
++ "superblock %llu", sb_block);
+ unlock_buffer(bh);
+- err = -EFSBADCRC;
+ goto out_bh;
+ }
+ func(es, arg);
+diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
+index 54e7d3c95fd71..35ca468109be9 100644
+--- a/fs/ext4/migrate.c
++++ b/fs/ext4/migrate.c
+@@ -425,7 +425,8 @@ int ext4_ext_migrate(struct inode *inode)
+ * already is extent-based, error out.
+ */
+ if (!ext4_has_feature_extents(inode->i_sb) ||
+- (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)))
++ ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) ||
++ ext4_has_inline_data(inode))
+ return -EINVAL;
+
+ if (S_ISLNK(inode->i_mode) && inode->i_blocks == 0)
+diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
+index 4183a4cb4a21e..be8136aafa22c 100644
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2259,8 +2259,16 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
+ memset(de, 0, len); /* wipe old data */
+ de = (struct ext4_dir_entry_2 *) data2;
+ top = data2 + len;
+- while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top)
++ while ((char *)(de2 = ext4_next_entry(de, blocksize)) < top) {
++ if (ext4_check_dir_entry(dir, NULL, de, bh2, data2, len,
++ (data2 + (blocksize - csum_size) -
++ (char *) de))) {
++ brelse(bh2);
++ brelse(bh);
++ return -EFSCORRUPTED;
++ }
+ de = de2;
++ }
+ de->rec_len = ext4_rec_len_to_disk(data2 + (blocksize - csum_size) -
+ (char *) de, blocksize);
+
+diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
+index 6dfe9ccae0c50..46b87ffeb3045 100644
+--- a/fs/ext4/resize.c
++++ b/fs/ext4/resize.c
+@@ -1158,6 +1158,7 @@ static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
+ while (group < sbi->s_groups_count) {
+ struct buffer_head *bh;
+ ext4_fsblk_t backup_block;
++ struct ext4_super_block *es;
+
+ /* Out of journal space, and can't get more - abort - so sad */
+ err = ext4_resize_ensure_credits_batch(handle, 1);
+@@ -1186,6 +1187,10 @@ static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
+ memcpy(bh->b_data, data, size);
+ if (rest)
+ memset(bh->b_data + size, 0, rest);
++ es = (struct ext4_super_block *) bh->b_data;
++ es->s_block_group_nr = cpu_to_le16(group);
++ if (ext4_has_metadata_csum(sb))
++ es->s_checksum = ext4_superblock_csum(sb, es);
+ set_buffer_uptodate(bh);
+ unlock_buffer(bh);
+ err = ext4_handle_dirty_metadata(handle, NULL, bh);
+diff --git a/fs/ext4/verity.c b/fs/ext4/verity.c
+index b051d19b5c8a0..94442c690ca7d 100644
+--- a/fs/ext4/verity.c
++++ b/fs/ext4/verity.c
+@@ -365,13 +365,14 @@ static struct page *ext4_read_merkle_tree_page(struct inode *inode,
+ pgoff_t index,
+ unsigned long num_ra_pages)
+ {
+- DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index);
+ struct page *page;
+
+ index += ext4_verity_metadata_pos(inode) >> PAGE_SHIFT;
+
+ page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
+ if (!page || !PageUptodate(page)) {
++ DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index);
++
+ if (page)
+ put_page(page);
+ else if (num_ra_pages > 1)
+diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c
+index 7b8f2b41c29b1..c0733f8670746 100644
+--- a/fs/f2fs/verity.c
++++ b/fs/f2fs/verity.c
+@@ -262,13 +262,14 @@ static struct page *f2fs_read_merkle_tree_page(struct inode *inode,
+ pgoff_t index,
+ unsigned long num_ra_pages)
+ {
+- DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index);
+ struct page *page;
+
+ index += f2fs_verity_metadata_pos(inode) >> PAGE_SHIFT;
+
+ page = find_get_page_flags(inode->i_mapping, index, FGP_ACCESSED);
+ if (!page || !PageUptodate(page)) {
++ DEFINE_READAHEAD(ractl, NULL, NULL, inode->i_mapping, index);
++
+ if (page)
+ put_page(page);
+ else if (num_ra_pages > 1)
+diff --git a/fs/fuse/file.c b/fs/fuse/file.c
+index 1a3afd469e3a9..71bfb663aac58 100644
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -3001,6 +3001,10 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
+ goto out;
+ }
+
++ err = file_modified(file);
++ if (err)
++ goto out;
++
+ if (!(mode & FALLOC_FL_KEEP_SIZE))
+ set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
+
+diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c
+index b4e5657110457..e8deaacf1832a 100644
+--- a/fs/fuse/readdir.c
++++ b/fs/fuse/readdir.c
+@@ -77,8 +77,10 @@ static void fuse_add_dirent_to_cache(struct file *file,
+ goto unlock;
+
+ addr = kmap_local_page(page);
+- if (!offset)
++ if (!offset) {
+ clear_page(addr);
++ SetPageUptodate(page);
++ }
+ memcpy(addr + offset, dirent, reclen);
+ kunmap_local(addr);
+ fi->rdc.size = (index << PAGE_SHIFT) + offset + reclen;
+@@ -516,6 +518,12 @@ retry_locked:
+
+ page = find_get_page_flags(file->f_mapping, index,
+ FGP_ACCESSED | FGP_LOCK);
++ /* Page gone missing, then re-added to cache, but not initialized? */
++ if (page && !PageUptodate(page)) {
++ unlock_page(page);
++ put_page(page);
++ page = NULL;
++ }
+ spin_lock(&fi->rdc.lock);
+ if (!page) {
+ /*
+diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
+index 5c97cad741a73..ead8a0e06abf9 100644
+--- a/fs/nfs/delegation.c
++++ b/fs/nfs/delegation.c
+@@ -228,8 +228,7 @@ again:
+ *
+ */
+ void nfs_inode_reclaim_delegation(struct inode *inode, const struct cred *cred,
+- fmode_t type,
+- const nfs4_stateid *stateid,
++ fmode_t type, const nfs4_stateid *stateid,
+ unsigned long pagemod_limit)
+ {
+ struct nfs_delegation *delegation;
+@@ -239,25 +238,24 @@ void nfs_inode_reclaim_delegation(struct inode *inode, const struct cred *cred,
+ delegation = rcu_dereference(NFS_I(inode)->delegation);
+ if (delegation != NULL) {
+ spin_lock(&delegation->lock);
+- if (nfs4_is_valid_delegation(delegation, 0)) {
+- nfs4_stateid_copy(&delegation->stateid, stateid);
+- delegation->type = type;
+- delegation->pagemod_limit = pagemod_limit;
+- oldcred = delegation->cred;
+- delegation->cred = get_cred(cred);
+- clear_bit(NFS_DELEGATION_NEED_RECLAIM,
+- &delegation->flags);
+- spin_unlock(&delegation->lock);
+- rcu_read_unlock();
+- put_cred(oldcred);
+- trace_nfs4_reclaim_delegation(inode, type);
+- return;
+- }
+- /* We appear to have raced with a delegation return. */
++ nfs4_stateid_copy(&delegation->stateid, stateid);
++ delegation->type = type;
++ delegation->pagemod_limit = pagemod_limit;
++ oldcred = delegation->cred;
++ delegation->cred = get_cred(cred);
++ clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
++ if (test_and_clear_bit(NFS_DELEGATION_REVOKED,
++ &delegation->flags))
++ atomic_long_inc(&nfs_active_delegations);
+ spin_unlock(&delegation->lock);
++ rcu_read_unlock();
++ put_cred(oldcred);
++ trace_nfs4_reclaim_delegation(inode, type);
++ } else {
++ rcu_read_unlock();
++ nfs_inode_set_delegation(inode, cred, type, stateid,
++ pagemod_limit);
+ }
+- rcu_read_unlock();
+- nfs_inode_set_delegation(inode, cred, type, stateid, pagemod_limit);
+ }
+
+ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
+diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
+index 6dab9e4083729..21c9e97c3ba30 100644
+--- a/fs/nfs/nfs42proc.c
++++ b/fs/nfs/nfs42proc.c
+@@ -1093,6 +1093,9 @@ static int _nfs42_proc_clone(struct rpc_message *msg, struct file *src_f,
+ &args.seq_args, &res.seq_res, 0);
+ trace_nfs4_clone(src_inode, dst_inode, &args, status);
+ if (status == 0) {
++ /* a zero-length count means clone to EOF in src */
++ if (count == 0 && res.dst_fattr->valid & NFS_ATTR_FATTR_SIZE)
++ count = nfs_size_to_loff_t(res.dst_fattr->size) - dst_offset;
+ nfs42_copy_dest_done(dst_inode, dst_offset, count);
+ status = nfs_post_op_update_inode(dst_inode, res.dst_fattr);
+ }
+diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
+index 3c5678aec006f..8ae2827da28d8 100644
+--- a/fs/nfs/nfs4client.c
++++ b/fs/nfs/nfs4client.c
+@@ -346,6 +346,7 @@ int nfs40_init_client(struct nfs_client *clp)
+ ret = nfs4_setup_slot_table(tbl, NFS4_MAX_SLOT_TABLE,
+ "NFSv4.0 transport Slot table");
+ if (ret) {
++ nfs4_shutdown_slot_table(tbl);
+ kfree(tbl);
+ return ret;
+ }
+diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
+index 9bab3e9c702a4..a629d7db9420a 100644
+--- a/fs/nfs/nfs4state.c
++++ b/fs/nfs/nfs4state.c
+@@ -1787,6 +1787,7 @@ static void nfs4_state_mark_reclaim_helper(struct nfs_client *clp,
+
+ static void nfs4_state_start_reclaim_reboot(struct nfs_client *clp)
+ {
++ set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state);
+ /* Mark all delegations for reclaim */
+ nfs_delegation_mark_reclaim(clp);
+ nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_reboot);
+@@ -2671,6 +2672,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
+ if (status < 0)
+ goto out_error;
+ nfs4_state_end_reclaim_reboot(clp);
++ continue;
+ }
+
+ /* Detect expired delegations... */
+diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c
+index eeed4ae5b4ad9..173b38ffa4238 100644
+--- a/fs/nfsd/filecache.c
++++ b/fs/nfsd/filecache.c
+@@ -405,22 +405,15 @@ nfsd_file_unhash(struct nfsd_file *nf)
+ return false;
+ }
+
+-/*
+- * Return true if the file was unhashed.
+- */
+-static bool
++static void
+ nfsd_file_unhash_and_dispose(struct nfsd_file *nf, struct list_head *dispose)
+ {
+ trace_nfsd_file_unhash_and_dispose(nf);
+- if (!nfsd_file_unhash(nf))
+- return false;
+- /* keep final reference for nfsd_file_lru_dispose */
+- if (refcount_dec_not_one(&nf->nf_ref))
+- return true;
+-
+- nfsd_file_lru_remove(nf);
+- list_add(&nf->nf_lru, dispose);
+- return true;
++ if (nfsd_file_unhash(nf)) {
++ /* caller must call nfsd_file_dispose_list() later */
++ nfsd_file_lru_remove(nf);
++ list_add(&nf->nf_lru, dispose);
++ }
+ }
+
+ static void
+@@ -562,8 +555,6 @@ nfsd_file_dispose_list_delayed(struct list_head *dispose)
+ * @lock: LRU list lock (unused)
+ * @arg: dispose list
+ *
+- * Note this can deadlock with nfsd_file_cache_purge.
+- *
+ * Return values:
+ * %LRU_REMOVED: @item was removed from the LRU
+ * %LRU_ROTATE: @item is to be moved to the LRU tail
+@@ -748,8 +739,6 @@ nfsd_file_close_inode(struct inode *inode)
+ *
+ * Walk the LRU list and close any entries that have not been used since
+ * the last scan.
+- *
+- * Note this can deadlock with nfsd_file_cache_purge.
+ */
+ static void
+ nfsd_file_delayed_close(struct work_struct *work)
+@@ -891,16 +880,12 @@ out_err:
+ goto out;
+ }
+
+-/*
+- * Note this can deadlock with nfsd_file_lru_cb.
+- */
+ static void
+ __nfsd_file_cache_purge(struct net *net)
+ {
+ struct rhashtable_iter iter;
+ struct nfsd_file *nf;
+ LIST_HEAD(dispose);
+- bool del;
+
+ rhashtable_walk_enter(&nfsd_file_rhash_tbl, &iter);
+ do {
+@@ -908,16 +893,8 @@ __nfsd_file_cache_purge(struct net *net)
+
+ nf = rhashtable_walk_next(&iter);
+ while (!IS_ERR_OR_NULL(nf)) {
+- if (net && nf->nf_net != net)
+- continue;
+- del = nfsd_file_unhash_and_dispose(nf, &dispose);
+-
+- /*
+- * Deadlock detected! Something marked this entry as
+- * unhased, but hasn't removed it from the hash list.
+- */
+- WARN_ON_ONCE(!del);
+-
++ if (!net || nf->nf_net == net)
++ nfsd_file_unhash_and_dispose(nf, &dispose);
+ nf = rhashtable_walk_next(&iter);
+ }
+
+diff --git a/fs/super.c b/fs/super.c
+index 734ed584a946e..8d39e4f11cfa3 100644
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -291,7 +291,7 @@ static void __put_super(struct super_block *s)
+ WARN_ON(s->s_inode_lru.node);
+ WARN_ON(!list_empty(&s->s_mounts));
+ security_sb_free(s);
+- fscrypt_sb_free(s);
++ fscrypt_destroy_keyring(s);
+ put_user_ns(s->s_user_ns);
+ kfree(s->s_subtype);
+ call_rcu(&s->rcu, destroy_super_rcu);
+@@ -480,6 +480,7 @@ void generic_shutdown_super(struct super_block *sb)
+ evict_inodes(sb);
+ /* only nonzero refcount inodes can have marks */
+ fsnotify_sb_delete(sb);
++ fscrypt_destroy_keyring(sb);
+ security_sb_delete(sb);
+
+ if (sb->s_dio_done_wq) {
+diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
+index 34fb3431a8f36..292a5c40bd0c6 100644
+--- a/include/acpi/ghes.h
++++ b/include/acpi/ghes.h
+@@ -71,7 +71,7 @@ int ghes_register_vendor_record_notifier(struct notifier_block *nb);
+ void ghes_unregister_vendor_record_notifier(struct notifier_block *nb);
+ #endif
+
+-int ghes_estatus_pool_init(int num_ghes);
++int ghes_estatus_pool_init(unsigned int num_ghes);
+
+ /* From drivers/edac/ghes_edac.c */
+
+diff --git a/include/linux/efi.h b/include/linux/efi.h
+index 4459794b65db0..f87b2f5db9f83 100644
+--- a/include/linux/efi.h
++++ b/include/linux/efi.h
+@@ -1192,7 +1192,7 @@ efi_status_t efi_random_get_seed(void);
+ arch_efi_call_virt_teardown(); \
+ })
+
+-#define EFI_RANDOM_SEED_SIZE 64U
++#define EFI_RANDOM_SEED_SIZE 32U // BLAKE2S_HASH_SIZE
+
+ struct linux_efi_random_seed {
+ u32 size;
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index 56a4b4b02477d..7203f5582fd44 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1472,7 +1472,7 @@ struct super_block {
+ const struct xattr_handler **s_xattr;
+ #ifdef CONFIG_FS_ENCRYPTION
+ const struct fscrypt_operations *s_cop;
+- struct key *s_master_keys; /* master crypto keys in use */
++ struct fscrypt_keyring *s_master_keys; /* master crypto keys in use */
+ #endif
+ #ifdef CONFIG_FS_VERITY
+ const struct fsverity_operations *s_vop;
+diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
+index 7d2f1e0f23b1f..d0e40a20ff810 100644
+--- a/include/linux/fscrypt.h
++++ b/include/linux/fscrypt.h
+@@ -312,7 +312,7 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
+ }
+
+ /* keyring.c */
+-void fscrypt_sb_free(struct super_block *sb);
++void fscrypt_destroy_keyring(struct super_block *sb);
+ int fscrypt_ioctl_add_key(struct file *filp, void __user *arg);
+ int fscrypt_add_test_dummy_key(struct super_block *sb,
+ const struct fscrypt_dummy_policy *dummy_policy);
+@@ -526,7 +526,7 @@ fscrypt_free_dummy_policy(struct fscrypt_dummy_policy *dummy_policy)
+ }
+
+ /* keyring.c */
+-static inline void fscrypt_sb_free(struct super_block *sb)
++static inline void fscrypt_destroy_keyring(struct super_block *sb)
+ {
+ }
+
+diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
+index 7a40f9bdc173e..dd8f994b8052b 100644
+--- a/include/linux/kvm_host.h
++++ b/include/linux/kvm_host.h
+@@ -1241,8 +1241,18 @@ int kvm_vcpu_write_guest(struct kvm_vcpu *vcpu, gpa_t gpa, const void *data,
+ void kvm_vcpu_mark_page_dirty(struct kvm_vcpu *vcpu, gfn_t gfn);
+
+ /**
+- * kvm_gfn_to_pfn_cache_init - prepare a cached kernel mapping and HPA for a
+- * given guest physical address.
++ * kvm_gpc_init - initialize gfn_to_pfn_cache.
++ *
++ * @gpc: struct gfn_to_pfn_cache object.
++ *
++ * This sets up a gfn_to_pfn_cache by initializing locks. Note, the cache must
++ * be zero-allocated (or zeroed by the caller before init).
++ */
++void kvm_gpc_init(struct gfn_to_pfn_cache *gpc);
++
++/**
++ * kvm_gpc_activate - prepare a cached kernel mapping and HPA for a given guest
++ * physical address.
+ *
+ * @kvm: pointer to kvm instance.
+ * @gpc: struct gfn_to_pfn_cache object.
+@@ -1266,9 +1276,9 @@ void kvm_vcpu_mark_page_dirty(struct kvm_vcpu *vcpu, gfn_t gfn);
+ * kvm_gfn_to_pfn_cache_check() to ensure that the cache is valid before
+ * accessing the target page.
+ */
+-int kvm_gfn_to_pfn_cache_init(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+- struct kvm_vcpu *vcpu, enum pfn_cache_usage usage,
+- gpa_t gpa, unsigned long len);
++int kvm_gpc_activate(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
++ struct kvm_vcpu *vcpu, enum pfn_cache_usage usage,
++ gpa_t gpa, unsigned long len);
+
+ /**
+ * kvm_gfn_to_pfn_cache_check - check validity of a gfn_to_pfn_cache.
+@@ -1325,7 +1335,7 @@ int kvm_gfn_to_pfn_cache_refresh(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+ void kvm_gfn_to_pfn_cache_unmap(struct kvm *kvm, struct gfn_to_pfn_cache *gpc);
+
+ /**
+- * kvm_gfn_to_pfn_cache_destroy - destroy and unlink a gfn_to_pfn_cache.
++ * kvm_gpc_deactivate - deactivate and unlink a gfn_to_pfn_cache.
+ *
+ * @kvm: pointer to kvm instance.
+ * @gpc: struct gfn_to_pfn_cache object.
+@@ -1333,7 +1343,7 @@ void kvm_gfn_to_pfn_cache_unmap(struct kvm *kvm, struct gfn_to_pfn_cache *gpc);
+ * This removes a cache from the @kvm's list to be processed on MMU notifier
+ * invocation.
+ */
+-void kvm_gfn_to_pfn_cache_destroy(struct kvm *kvm, struct gfn_to_pfn_cache *gpc);
++void kvm_gpc_deactivate(struct kvm *kvm, struct gfn_to_pfn_cache *gpc);
+
+ void kvm_sigset_activate(struct kvm_vcpu *vcpu);
+ void kvm_sigset_deactivate(struct kvm_vcpu *vcpu);
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index 9689f38a0af1f..ec1896886dbd6 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -1046,6 +1046,8 @@ v4l2_subdev_get_pad_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ unsigned int pad)
+ {
++ if (WARN_ON(!state))
++ return NULL;
+ if (WARN_ON(pad >= sd->entity.num_pads))
+ pad = 0;
+ return &state->pads[pad].try_fmt;
+@@ -1064,6 +1066,8 @@ v4l2_subdev_get_pad_crop(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ unsigned int pad)
+ {
++ if (WARN_ON(!state))
++ return NULL;
+ if (WARN_ON(pad >= sd->entity.num_pads))
+ pad = 0;
+ return &state->pads[pad].try_crop;
+@@ -1082,6 +1086,8 @@ v4l2_subdev_get_pad_compose(struct v4l2_subdev *sd,
+ struct v4l2_subdev_state *state,
+ unsigned int pad)
+ {
++ if (WARN_ON(!state))
++ return NULL;
+ if (WARN_ON(pad >= sd->entity.num_pads))
+ pad = 0;
+ return &state->pads[pad].try_compose;
+diff --git a/include/net/sock.h b/include/net/sock.h
+index 8a98ea9360fb7..f6e6838c82dfa 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -1871,6 +1871,13 @@ void sock_kfree_s(struct sock *sk, void *mem, int size);
+ void sock_kzfree_s(struct sock *sk, void *mem, int size);
+ void sk_send_sigurg(struct sock *sk);
+
++static inline void sock_replace_proto(struct sock *sk, struct proto *proto)
++{
++ if (sk->sk_socket)
++ clear_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);
++ WRITE_ONCE(sk->sk_prot, proto);
++}
++
+ struct sockcm_cookie {
+ u64 transmit_time;
+ u32 mark;
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index c5dd483a7de2f..d29f397f095ee 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -2653,15 +2653,12 @@ static __cold void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx)
+ io_poll_remove_all(ctx, NULL, true);
+ mutex_unlock(&ctx->uring_lock);
+
+- /* failed during ring init, it couldn't have issued any requests */
+- if (ctx->rings) {
++ /*
++ * If we failed setting up the ctx, we might not have any rings
++ * and therefore did not submit any requests
++ */
++ if (ctx->rings)
+ io_kill_timeouts(ctx, NULL, true);
+- /* if we failed setting up the ctx, we might not have any rings */
+- io_iopoll_try_reap_events(ctx);
+- /* drop cached put refs after potentially doing completions */
+- if (current->io_uring)
+- io_uring_drop_tctx_refs(current);
+- }
+
+ INIT_WORK(&ctx->exit_work, io_ring_exit_work);
+ /*
+diff --git a/kernel/kprobes.c b/kernel/kprobes.c
+index ca9d834d0b843..917b92ae23821 100644
+--- a/kernel/kprobes.c
++++ b/kernel/kprobes.c
+@@ -2425,8 +2425,11 @@ int enable_kprobe(struct kprobe *kp)
+ if (!kprobes_all_disarmed && kprobe_disabled(p)) {
+ p->flags &= ~KPROBE_FLAG_DISABLED;
+ ret = arm_kprobe(p);
+- if (ret)
++ if (ret) {
+ p->flags |= KPROBE_FLAG_DISABLED;
++ if (p != kp)
++ kp->flags |= KPROBE_FLAG_DISABLED;
++ }
+ }
+ out:
+ mutex_unlock(&kprobe_mutex);
+diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c
+index aac63ca9c3d1e..e8143e3680744 100644
+--- a/kernel/trace/fprobe.c
++++ b/kernel/trace/fprobe.c
+@@ -141,6 +141,8 @@ static int fprobe_init_rethook(struct fprobe *fp, int num)
+ return -E2BIG;
+
+ fp->rethook = rethook_alloc((void *)fp, fprobe_exit_handler);
++ if (!fp->rethook)
++ return -ENOMEM;
+ for (i = 0; i < size; i++) {
+ struct fprobe_rethook_node *node;
+
+@@ -301,7 +303,8 @@ int unregister_fprobe(struct fprobe *fp)
+ {
+ int ret;
+
+- if (!fp || fp->ops.func != fprobe_handler)
++ if (!fp || (fp->ops.saved_func != fprobe_handler &&
++ fp->ops.saved_func != fprobe_kprobe_handler))
+ return -EINVAL;
+
+ /*
+diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
+index 83362a1557916..8cc9eb60c3c2a 100644
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -3031,18 +3031,8 @@ int ftrace_shutdown(struct ftrace_ops *ops, int command)
+ command |= FTRACE_UPDATE_TRACE_FUNC;
+ }
+
+- if (!command || !ftrace_enabled) {
+- /*
+- * If these are dynamic or per_cpu ops, they still
+- * need their data freed. Since, function tracing is
+- * not currently active, we can just free them
+- * without synchronizing all CPUs.
+- */
+- if (ops->flags & FTRACE_OPS_FL_DYNAMIC)
+- goto free_ops;
+-
+- return 0;
+- }
++ if (!command || !ftrace_enabled)
++ goto out;
+
+ /*
+ * If the ops uses a trampoline, then it needs to be
+@@ -3079,6 +3069,7 @@ int ftrace_shutdown(struct ftrace_ops *ops, int command)
+ removed_ops = NULL;
+ ops->flags &= ~FTRACE_OPS_FL_REMOVING;
+
++out:
+ /*
+ * Dynamic ops may be freed, we must make sure that all
+ * callers are done before leaving this function.
+@@ -3106,7 +3097,6 @@ int ftrace_shutdown(struct ftrace_ops *ops, int command)
+ if (IS_ENABLED(CONFIG_PREEMPTION))
+ synchronize_rcu_tasks();
+
+- free_ops:
+ ftrace_trampoline_free(ops);
+ }
+
+diff --git a/kernel/trace/kprobe_event_gen_test.c b/kernel/trace/kprobe_event_gen_test.c
+index 80e04a1e19772..d81f7c51025c7 100644
+--- a/kernel/trace/kprobe_event_gen_test.c
++++ b/kernel/trace/kprobe_event_gen_test.c
+@@ -100,20 +100,20 @@ static int __init test_gen_kprobe_cmd(void)
+ KPROBE_GEN_TEST_FUNC,
+ KPROBE_GEN_TEST_ARG0, KPROBE_GEN_TEST_ARG1);
+ if (ret)
+- goto free;
++ goto out;
+
+ /* Use kprobe_event_add_fields to add the rest of the fields */
+
+ ret = kprobe_event_add_fields(&cmd, KPROBE_GEN_TEST_ARG2, KPROBE_GEN_TEST_ARG3);
+ if (ret)
+- goto free;
++ goto out;
+
+ /*
+ * This actually creates the event.
+ */
+ ret = kprobe_event_gen_cmd_end(&cmd);
+ if (ret)
+- goto free;
++ goto out;
+
+ /*
+ * Now get the gen_kprobe_test event file. We need to prevent
+@@ -136,13 +136,11 @@ static int __init test_gen_kprobe_cmd(void)
+ goto delete;
+ }
+ out:
++ kfree(buf);
+ return ret;
+ delete:
+ /* We got an error after creating the event, delete it */
+ ret = kprobe_event_delete("gen_kprobe_test");
+- free:
+- kfree(buf);
+-
+ goto out;
+ }
+
+@@ -170,14 +168,14 @@ static int __init test_gen_kretprobe_cmd(void)
+ KPROBE_GEN_TEST_FUNC,
+ "$retval");
+ if (ret)
+- goto free;
++ goto out;
+
+ /*
+ * This actually creates the event.
+ */
+ ret = kretprobe_event_gen_cmd_end(&cmd);
+ if (ret)
+- goto free;
++ goto out;
+
+ /*
+ * Now get the gen_kretprobe_test event file. We need to
+@@ -201,13 +199,11 @@ static int __init test_gen_kretprobe_cmd(void)
+ goto delete;
+ }
+ out:
++ kfree(buf);
+ return ret;
+ delete:
+ /* We got an error after creating the event, delete it */
+ ret = kprobe_event_delete("gen_kretprobe_test");
+- free:
+- kfree(buf);
+-
+ goto out;
+ }
+
+diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
+index c3f354cfc5ba1..9c72571ffb0bf 100644
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -937,6 +937,9 @@ void ring_buffer_wake_waiters(struct trace_buffer *buffer, int cpu)
+ struct ring_buffer_per_cpu *cpu_buffer;
+ struct rb_irq_work *rbwork;
+
++ if (!buffer)
++ return;
++
+ if (cpu == RING_BUFFER_ALL_CPUS) {
+
+ /* Wake up individual ones too. One level recursion */
+@@ -945,7 +948,15 @@ void ring_buffer_wake_waiters(struct trace_buffer *buffer, int cpu)
+
+ rbwork = &buffer->irq_work;
+ } else {
++ if (WARN_ON_ONCE(!buffer->buffers))
++ return;
++ if (WARN_ON_ONCE(cpu >= nr_cpu_ids))
++ return;
++
+ cpu_buffer = buffer->buffers[cpu];
++ /* The CPU buffer may not have been initialized yet */
++ if (!cpu_buffer)
++ return;
+ rbwork = &cpu_buffer->irq_work;
+ }
+
+diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
+index 9777e7b109eee..f26ed278d9e3c 100644
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -1003,10 +1003,21 @@ int hci_conn_del(struct hci_conn *conn)
+ hdev->acl_cnt += conn->sent;
+ } else {
+ struct hci_conn *acl = conn->link;
++
+ if (acl) {
+ acl->link = NULL;
+ hci_conn_drop(acl);
+ }
++
++ /* Unacked ISO frames */
++ if (conn->type == ISO_LINK) {
++ if (hdev->iso_pkts)
++ hdev->iso_cnt += conn->sent;
++ else if (hdev->le_pkts)
++ hdev->le_cnt += conn->sent;
++ else
++ hdev->acl_cnt += conn->sent;
++ }
+ }
+
+ if (conn->amp_mgr)
+@@ -1697,6 +1708,7 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
+ if (!cis)
+ return ERR_PTR(-ENOMEM);
+ cis->cleanup = cis_cleanup;
++ cis->dst_type = dst_type;
+ }
+
+ if (cis->state == BT_CONNECTED)
+@@ -2076,12 +2088,6 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
+ struct hci_conn *le;
+ struct hci_conn *cis;
+
+- /* Convert from ISO socket address type to HCI address type */
+- if (dst_type == BDADDR_LE_PUBLIC)
+- dst_type = ADDR_LE_DEV_PUBLIC;
+- else
+- dst_type = ADDR_LE_DEV_RANDOM;
+-
+ if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
+ le = hci_connect_le(hdev, dst, dst_type, false,
+ BT_SECURITY_LOW,
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index 613039ba5dbf5..f825857db6d0b 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -235,6 +235,14 @@ static int iso_chan_add(struct iso_conn *conn, struct sock *sk,
+ return err;
+ }
+
++static inline u8 le_addr_type(u8 bdaddr_type)
++{
++ if (bdaddr_type == BDADDR_LE_PUBLIC)
++ return ADDR_LE_DEV_PUBLIC;
++ else
++ return ADDR_LE_DEV_RANDOM;
++}
++
+ static int iso_connect_bis(struct sock *sk)
+ {
+ struct iso_conn *conn;
+@@ -328,14 +336,16 @@ static int iso_connect_cis(struct sock *sk)
+ /* Just bind if DEFER_SETUP has been set */
+ if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
+ hcon = hci_bind_cis(hdev, &iso_pi(sk)->dst,
+- iso_pi(sk)->dst_type, &iso_pi(sk)->qos);
++ le_addr_type(iso_pi(sk)->dst_type),
++ &iso_pi(sk)->qos);
+ if (IS_ERR(hcon)) {
+ err = PTR_ERR(hcon);
+ goto done;
+ }
+ } else {
+ hcon = hci_connect_cis(hdev, &iso_pi(sk)->dst,
+- iso_pi(sk)->dst_type, &iso_pi(sk)->qos);
++ le_addr_type(iso_pi(sk)->dst_type),
++ &iso_pi(sk)->qos);
+ if (IS_ERR(hcon)) {
+ err = PTR_ERR(hcon);
+ goto done;
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 1f34b82ca0ec9..4df3d0ed6c80d 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -3764,7 +3764,8 @@ done:
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
+
+- if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
++ if (remote_efs &&
++ test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
+ chan->remote_id = efs.id;
+ chan->remote_stype = efs.stype;
+ chan->remote_msdu = le16_to_cpu(efs.msdu);
+@@ -5813,6 +5814,19 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
+ BT_DBG("psm 0x%2.2x scid 0x%4.4x mtu %u mps %u", __le16_to_cpu(psm),
+ scid, mtu, mps);
+
++ /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
++ * page 1059:
++ *
++ * Valid range: 0x0001-0x00ff
++ *
++ * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
++ */
++ if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
++ result = L2CAP_CR_LE_BAD_PSM;
++ chan = NULL;
++ goto response;
++ }
++
+ /* Check if we have socket listening on psm */
+ pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src,
+ &conn->hcon->dst, LE_LINK);
+@@ -6001,6 +6015,18 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
+
+ psm = req->psm;
+
++ /* BLUETOOTH CORE SPECIFICATION Version 5.3 | Vol 3, Part A
++ * page 1059:
++ *
++ * Valid range: 0x0001-0x00ff
++ *
++ * Table 4.15: L2CAP_LE_CREDIT_BASED_CONNECTION_REQ SPSM ranges
++ */
++ if (!psm || __le16_to_cpu(psm) > L2CAP_PSM_LE_DYN_END) {
++ result = L2CAP_CR_LE_BAD_PSM;
++ goto response;
++ }
++
+ BT_DBG("psm 0x%2.2x mtu %u mps %u", __le16_to_cpu(psm), mtu, mps);
+
+ memset(&pdu, 0, sizeof(pdu));
+@@ -6885,6 +6911,7 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,
+ struct l2cap_ctrl *control,
+ struct sk_buff *skb, u8 event)
+ {
++ struct l2cap_ctrl local_control;
+ int err = 0;
+ bool skb_in_use = false;
+
+@@ -6909,15 +6936,32 @@ static int l2cap_rx_state_recv(struct l2cap_chan *chan,
+ chan->buffer_seq = chan->expected_tx_seq;
+ skb_in_use = true;
+
++ /* l2cap_reassemble_sdu may free skb, hence invalidate
++ * control, so make a copy in advance to use it after
++ * l2cap_reassemble_sdu returns and to avoid the race
++ * condition, for example:
++ *
++ * The current thread calls:
++ * l2cap_reassemble_sdu
++ * chan->ops->recv == l2cap_sock_recv_cb
++ * __sock_queue_rcv_skb
++ * Another thread calls:
++ * bt_sock_recvmsg
++ * skb_recv_datagram
++ * skb_free_datagram
++ * Then the current thread tries to access control, but
++ * it was freed by skb_free_datagram.
++ */
++ local_control = *control;
+ err = l2cap_reassemble_sdu(chan, skb, control);
+ if (err)
+ break;
+
+- if (control->final) {
++ if (local_control.final) {
+ if (!test_and_clear_bit(CONN_REJ_ACT,
+ &chan->conn_state)) {
+- control->final = 0;
+- l2cap_retransmit_all(chan, control);
++ local_control.final = 0;
++ l2cap_retransmit_all(chan, &local_control);
+ l2cap_ertm_send(chan);
+ }
+ }
+@@ -7297,11 +7341,27 @@ static int l2cap_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
+ static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
+ struct sk_buff *skb)
+ {
++ /* l2cap_reassemble_sdu may free skb, hence invalidate control, so store
++ * the txseq field in advance to use it after l2cap_reassemble_sdu
++ * returns and to avoid the race condition, for example:
++ *
++ * The current thread calls:
++ * l2cap_reassemble_sdu
++ * chan->ops->recv == l2cap_sock_recv_cb
++ * __sock_queue_rcv_skb
++ * Another thread calls:
++ * bt_sock_recvmsg
++ * skb_recv_datagram
++ * skb_free_datagram
++ * Then the current thread tries to access control, but it was freed by
++ * skb_free_datagram.
++ */
++ u16 txseq = control->txseq;
++
+ BT_DBG("chan %p, control %p, skb %p, state %d", chan, control, skb,
+ chan->rx_state);
+
+- if (l2cap_classify_txseq(chan, control->txseq) ==
+- L2CAP_TXSEQ_EXPECTED) {
++ if (l2cap_classify_txseq(chan, txseq) == L2CAP_TXSEQ_EXPECTED) {
+ l2cap_pass_to_tx(chan, control);
+
+ BT_DBG("buffer_seq %u->%u", chan->buffer_seq,
+@@ -7324,8 +7384,8 @@ static int l2cap_stream_rx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
+ }
+ }
+
+- chan->last_acked_seq = control->txseq;
+- chan->expected_tx_seq = __next_seq(chan, control->txseq);
++ chan->last_acked_seq = txseq;
++ chan->expected_tx_seq = __next_seq(chan, txseq);
+
+ return 0;
+ }
+@@ -7581,6 +7641,7 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid,
+ return;
+ }
+
++ l2cap_chan_hold(chan);
+ l2cap_chan_lock(chan);
+ } else {
+ BT_DBG("unknown cid 0x%4.4x", cid);
+@@ -8426,9 +8487,8 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
+ * expected length.
+ */
+ if (skb->len < L2CAP_LEN_SIZE) {
+- if (l2cap_recv_frag(conn, skb, conn->mtu) < 0)
+- goto drop;
+- return;
++ l2cap_recv_frag(conn, skb, conn->mtu);
++ break;
+ }
+
+ len = get_unaligned_le16(skb->data) + L2CAP_HDR_SIZE;
+@@ -8472,7 +8532,7 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
+
+ /* Header still could not be read just continue */
+ if (conn->rx_skb->len < L2CAP_LEN_SIZE)
+- return;
++ break;
+ }
+
+ if (skb->len > conn->rx_len) {
+diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
+index 5aeb3646e74c7..d087fd4c784ac 100644
+--- a/net/bridge/br_netlink.c
++++ b/net/bridge/br_netlink.c
+@@ -1332,7 +1332,7 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
+
+ if (data[IFLA_BR_FDB_FLUSH]) {
+ struct net_bridge_fdb_flush_desc desc = {
+- .flags_mask = BR_FDB_STATIC
++ .flags_mask = BIT(BR_FDB_STATIC)
+ };
+
+ br_fdb_flush(br, &desc);
+diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
+index 612e367fff20d..ea733542244c7 100644
+--- a/net/bridge/br_sysfs_br.c
++++ b/net/bridge/br_sysfs_br.c
+@@ -345,7 +345,7 @@ static int set_flush(struct net_bridge *br, unsigned long val,
+ struct netlink_ext_ack *extack)
+ {
+ struct net_bridge_fdb_flush_desc desc = {
+- .flags_mask = BR_FDB_STATIC
++ .flags_mask = BIT(BR_FDB_STATIC)
+ };
+
+ br_fdb_flush(br, &desc);
+diff --git a/net/core/neighbour.c b/net/core/neighbour.c
+index 78cc8fb688140..84755db81e9d9 100644
+--- a/net/core/neighbour.c
++++ b/net/core/neighbour.c
+@@ -409,7 +409,7 @@ static int __neigh_ifdown(struct neigh_table *tbl, struct net_device *dev,
+ write_lock_bh(&tbl->lock);
+ neigh_flush_dev(tbl, dev, skip_perm);
+ pneigh_ifdown_and_unlock(tbl, dev);
+- pneigh_queue_purge(&tbl->proxy_queue, dev_net(dev));
++ pneigh_queue_purge(&tbl->proxy_queue, dev ? dev_net(dev) : NULL);
+ if (skb_queue_empty_lockless(&tbl->proxy_queue))
+ del_timer_sync(&tbl->proxy_timer);
+ return 0;
+diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
+index cac48a741f27c..e537655e442b8 100644
+--- a/net/dsa/dsa2.c
++++ b/net/dsa/dsa2.c
+@@ -1407,9 +1407,9 @@ static enum dsa_tag_protocol dsa_get_tag_protocol(struct dsa_port *dp,
+ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master,
+ const char *user_protocol)
+ {
++ const struct dsa_device_ops *tag_ops = NULL;
+ struct dsa_switch *ds = dp->ds;
+ struct dsa_switch_tree *dst = ds->dst;
+- const struct dsa_device_ops *tag_ops;
+ enum dsa_tag_protocol default_proto;
+
+ /* Find out which protocol the switch would prefer. */
+@@ -1432,10 +1432,17 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *master,
+ }
+
+ tag_ops = dsa_find_tagger_by_name(user_protocol);
+- } else {
+- tag_ops = dsa_tag_driver_get(default_proto);
++ if (IS_ERR(tag_ops)) {
++ dev_warn(ds->dev,
++ "Failed to find a tagging driver for protocol %s, using default\n",
++ user_protocol);
++ tag_ops = NULL;
++ }
+ }
+
++ if (!tag_ops)
++ tag_ops = dsa_tag_driver_get(default_proto);
++
+ if (IS_ERR(tag_ops)) {
+ if (PTR_ERR(tag_ops) == -ENOPROTOOPT)
+ return -EPROBE_DEFER;
+diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
+index 3ca0cc4678862..7f6d7c355e38e 100644
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -748,6 +748,8 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags,
+ (TCPF_ESTABLISHED | TCPF_SYN_RECV |
+ TCPF_CLOSE_WAIT | TCPF_CLOSE)));
+
++ if (test_bit(SOCK_SUPPORT_ZC, &sock->flags))
++ set_bit(SOCK_SUPPORT_ZC, &newsock->flags);
+ sock_graft(sk2, newsock);
+
+ newsock->state = SS_CONNECTED;
+diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
+index a1626afe87a10..c501c329b1dbe 100644
+--- a/net/ipv4/tcp_bpf.c
++++ b/net/ipv4/tcp_bpf.c
+@@ -607,7 +607,7 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
+ } else {
+ sk->sk_write_space = psock->saved_write_space;
+ /* Pairs with lockless read in sk_clone_lock() */
+- WRITE_ONCE(sk->sk_prot, psock->sk_proto);
++ sock_replace_proto(sk, psock->sk_proto);
+ }
+ return 0;
+ }
+@@ -620,7 +620,7 @@ int tcp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
+ }
+
+ /* Pairs with lockless read in sk_clone_lock() */
+- WRITE_ONCE(sk->sk_prot, &tcp_bpf_prots[family][config]);
++ sock_replace_proto(sk, &tcp_bpf_prots[family][config]);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(tcp_bpf_update_proto);
+diff --git a/net/ipv4/tcp_ulp.c b/net/ipv4/tcp_ulp.c
+index 7c27aa629af19..9ae50b1bd8444 100644
+--- a/net/ipv4/tcp_ulp.c
++++ b/net/ipv4/tcp_ulp.c
+@@ -136,6 +136,9 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops)
+ if (icsk->icsk_ulp_ops)
+ goto out_err;
+
++ if (sk->sk_socket)
++ clear_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags);
++
+ err = ulp_ops->init(sk);
+ if (err)
+ goto out_err;
+diff --git a/net/ipv4/udp_bpf.c b/net/ipv4/udp_bpf.c
+index ff15918b7bdc7..e5dc91d0e0793 100644
+--- a/net/ipv4/udp_bpf.c
++++ b/net/ipv4/udp_bpf.c
+@@ -141,14 +141,14 @@ int udp_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
+
+ if (restore) {
+ sk->sk_write_space = psock->saved_write_space;
+- WRITE_ONCE(sk->sk_prot, psock->sk_proto);
++ sock_replace_proto(sk, psock->sk_proto);
+ return 0;
+ }
+
+ if (sk->sk_family == AF_INET6)
+ udp_bpf_check_v6_needs_rebuild(psock->sk_proto);
+
+- WRITE_ONCE(sk->sk_prot, &udp_bpf_prots[family]);
++ sock_replace_proto(sk, &udp_bpf_prots[family]);
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(udp_bpf_update_proto);
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index 69252eb462b2d..2f355f0ec32ac 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -6555,10 +6555,16 @@ static void __net_exit ip6_route_net_exit(struct net *net)
+ static int __net_init ip6_route_net_init_late(struct net *net)
+ {
+ #ifdef CONFIG_PROC_FS
+- proc_create_net("ipv6_route", 0, net->proc_net, &ipv6_route_seq_ops,
+- sizeof(struct ipv6_route_iter));
+- proc_create_net_single("rt6_stats", 0444, net->proc_net,
+- rt6_stats_seq_show, NULL);
++ if (!proc_create_net("ipv6_route", 0, net->proc_net,
++ &ipv6_route_seq_ops,
++ sizeof(struct ipv6_route_iter)))
++ return -ENOMEM;
++
++ if (!proc_create_net_single("rt6_stats", 0444, net->proc_net,
++ rt6_stats_seq_show, NULL)) {
++ remove_proc_entry("ipv6_route", net->proc_net);
++ return -ENOMEM;
++ }
+ #endif
+ return 0;
+ }
+diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
+index 6e391308431da..3adc291d9ce18 100644
+--- a/net/netfilter/ipset/ip_set_hash_gen.h
++++ b/net/netfilter/ipset/ip_set_hash_gen.h
+@@ -42,31 +42,8 @@
+ #define AHASH_MAX_SIZE (6 * AHASH_INIT_SIZE)
+ /* Max muber of elements in the array block when tuned */
+ #define AHASH_MAX_TUNED 64
+-
+ #define AHASH_MAX(h) ((h)->bucketsize)
+
+-/* Max number of elements can be tuned */
+-#ifdef IP_SET_HASH_WITH_MULTI
+-static u8
+-tune_bucketsize(u8 curr, u32 multi)
+-{
+- u32 n;
+-
+- if (multi < curr)
+- return curr;
+-
+- n = curr + AHASH_INIT_SIZE;
+- /* Currently, at listing one hash bucket must fit into a message.
+- * Therefore we have a hard limit here.
+- */
+- return n > curr && n <= AHASH_MAX_TUNED ? n : curr;
+-}
+-#define TUNE_BUCKETSIZE(h, multi) \
+- ((h)->bucketsize = tune_bucketsize((h)->bucketsize, multi))
+-#else
+-#define TUNE_BUCKETSIZE(h, multi)
+-#endif
+-
+ /* A hash bucket */
+ struct hbucket {
+ struct rcu_head rcu; /* for call_rcu */
+@@ -936,7 +913,12 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
+ goto set_full;
+ /* Create a new slot */
+ if (n->pos >= n->size) {
+- TUNE_BUCKETSIZE(h, multi);
++#ifdef IP_SET_HASH_WITH_MULTI
++ if (h->bucketsize >= AHASH_MAX_TUNED)
++ goto set_full;
++ else if (h->bucketsize < multi)
++ h->bucketsize += AHASH_INIT_SIZE;
++#endif
+ if (n->size >= AHASH_MAX(h)) {
+ /* Trigger rehashing */
+ mtype_data_next(&h->next, d);
+diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c
+index f9b16f2b22191..fdacbc3c15bef 100644
+--- a/net/netfilter/ipvs/ip_vs_app.c
++++ b/net/netfilter/ipvs/ip_vs_app.c
+@@ -599,13 +599,19 @@ static const struct seq_operations ip_vs_app_seq_ops = {
+ int __net_init ip_vs_app_net_init(struct netns_ipvs *ipvs)
+ {
+ INIT_LIST_HEAD(&ipvs->app_list);
+- proc_create_net("ip_vs_app", 0, ipvs->net->proc_net, &ip_vs_app_seq_ops,
+- sizeof(struct seq_net_private));
++#ifdef CONFIG_PROC_FS
++ if (!proc_create_net("ip_vs_app", 0, ipvs->net->proc_net,
++ &ip_vs_app_seq_ops,
++ sizeof(struct seq_net_private)))
++ return -ENOMEM;
++#endif
+ return 0;
+ }
+
+ void __net_exit ip_vs_app_net_cleanup(struct netns_ipvs *ipvs)
+ {
+ unregister_ip_vs_app(ipvs, NULL /* all */);
++#ifdef CONFIG_PROC_FS
+ remove_proc_entry("ip_vs_app", ipvs->net->proc_net);
++#endif
+ }
+diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
+index fb67f1ca2495b..cb6d68220c265 100644
+--- a/net/netfilter/ipvs/ip_vs_conn.c
++++ b/net/netfilter/ipvs/ip_vs_conn.c
+@@ -1265,8 +1265,8 @@ static inline int todrop_entry(struct ip_vs_conn *cp)
+ * The drop rate array needs tuning for real environments.
+ * Called from timer bh only => no locking
+ */
+- static const char todrop_rate[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
+- static char todrop_counter[9] = {0};
++ static const signed char todrop_rate[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
++ static signed char todrop_counter[9] = {0};
+ int i;
+
+ /* if the conn entry hasn't lasted for 60 seconds, don't drop it.
+@@ -1447,20 +1447,36 @@ int __net_init ip_vs_conn_net_init(struct netns_ipvs *ipvs)
+ {
+ atomic_set(&ipvs->conn_count, 0);
+
+- proc_create_net("ip_vs_conn", 0, ipvs->net->proc_net,
+- &ip_vs_conn_seq_ops, sizeof(struct ip_vs_iter_state));
+- proc_create_net("ip_vs_conn_sync", 0, ipvs->net->proc_net,
+- &ip_vs_conn_sync_seq_ops,
+- sizeof(struct ip_vs_iter_state));
++#ifdef CONFIG_PROC_FS
++ if (!proc_create_net("ip_vs_conn", 0, ipvs->net->proc_net,
++ &ip_vs_conn_seq_ops,
++ sizeof(struct ip_vs_iter_state)))
++ goto err_conn;
++
++ if (!proc_create_net("ip_vs_conn_sync", 0, ipvs->net->proc_net,
++ &ip_vs_conn_sync_seq_ops,
++ sizeof(struct ip_vs_iter_state)))
++ goto err_conn_sync;
++#endif
++
+ return 0;
++
++#ifdef CONFIG_PROC_FS
++err_conn_sync:
++ remove_proc_entry("ip_vs_conn", ipvs->net->proc_net);
++err_conn:
++ return -ENOMEM;
++#endif
+ }
+
+ void __net_exit ip_vs_conn_net_cleanup(struct netns_ipvs *ipvs)
+ {
+ /* flush all the connection entries first */
+ ip_vs_conn_flush(ipvs);
++#ifdef CONFIG_PROC_FS
+ remove_proc_entry("ip_vs_conn", ipvs->net->proc_net);
+ remove_proc_entry("ip_vs_conn_sync", ipvs->net->proc_net);
++#endif
+ }
+
+ int __init ip_vs_conn_init(void)
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 5897afd124668..879f4a1a27d54 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -8465,9 +8465,6 @@ static void nft_commit_release(struct nft_trans *trans)
+ nf_tables_chain_destroy(&trans->ctx);
+ break;
+ case NFT_MSG_DELRULE:
+- if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
+- nft_flow_rule_destroy(nft_trans_flow_rule(trans));
+-
+ nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
+ break;
+ case NFT_MSG_DELSET:
+@@ -8973,6 +8970,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+ nft_rule_expr_deactivate(&trans->ctx,
+ nft_trans_rule(trans),
+ NFT_TRANS_COMMIT);
++
++ if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
++ nft_flow_rule_destroy(nft_trans_flow_rule(trans));
+ break;
+ case NFT_MSG_NEWSET:
+ nft_clear(net, nft_trans_set(trans));
+@@ -10030,6 +10030,8 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
+ nft_net = nft_pernet(net);
+ deleted = 0;
+ mutex_lock(&nft_net->commit_mutex);
++ if (!list_empty(&nf_tables_destroy_list))
++ rcu_barrier();
+ again:
+ list_for_each_entry(table, &nft_net->tables, list) {
+ if (nft_table_has_owner(table) &&
+diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c
+index 8b96a56d3a49b..0f77ae8ef944a 100644
+--- a/net/rose/rose_link.c
++++ b/net/rose/rose_link.c
+@@ -236,6 +236,9 @@ void rose_transmit_clear_request(struct rose_neigh *neigh, unsigned int lci, uns
+ unsigned char *dptr;
+ int len;
+
++ if (!neigh->dev)
++ return;
++
+ len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 3;
+
+ if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
+diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
+index f1e013e3f04a9..935d90874b1b7 100644
+--- a/net/sched/sch_red.c
++++ b/net/sched/sch_red.c
+@@ -72,6 +72,7 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+ {
+ struct red_sched_data *q = qdisc_priv(sch);
+ struct Qdisc *child = q->qdisc;
++ unsigned int len;
+ int ret;
+
+ q->vars.qavg = red_calc_qavg(&q->parms,
+@@ -126,9 +127,10 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+ break;
+ }
+
++ len = qdisc_pkt_len(skb);
+ ret = qdisc_enqueue(skb, child, to_free);
+ if (likely(ret == NET_XMIT_SUCCESS)) {
+- qdisc_qstats_backlog_inc(sch, skb);
++ sch->qstats.backlog += len;
+ sch->q.qlen++;
+ } else if (net_xmit_drop_count(ret)) {
+ q->stats.pdrop++;
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index 0939cc3b915af..58ff5f33b3700 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -3380,14 +3380,14 @@ static int __init smc_init(void)
+
+ rc = register_pernet_subsys(&smc_net_stat_ops);
+ if (rc)
+- return rc;
++ goto out_pernet_subsys;
+
+ smc_ism_init();
+ smc_clc_init();
+
+ rc = smc_nl_init();
+ if (rc)
+- goto out_pernet_subsys;
++ goto out_pernet_subsys_stat;
+
+ rc = smc_pnet_init();
+ if (rc)
+@@ -3480,6 +3480,8 @@ out_pnet:
+ smc_pnet_exit();
+ out_nl:
+ smc_nl_exit();
++out_pernet_subsys_stat:
++ unregister_pernet_subsys(&smc_net_stat_ops);
+ out_pernet_subsys:
+ unregister_pernet_subsys(&smc_net_ops);
+
+diff --git a/net/sunrpc/sysfs.c b/net/sunrpc/sysfs.c
+index c65c90ad626ad..c1f559892ae8a 100644
+--- a/net/sunrpc/sysfs.c
++++ b/net/sunrpc/sysfs.c
+@@ -518,13 +518,16 @@ void rpc_sysfs_client_setup(struct rpc_clnt *clnt,
+ struct net *net)
+ {
+ struct rpc_sysfs_client *rpc_client;
++ struct rpc_sysfs_xprt_switch *xswitch =
++ (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs;
++
++ if (!xswitch)
++ return;
+
+ rpc_client = rpc_sysfs_client_alloc(rpc_sunrpc_client_kobj,
+ net, clnt->cl_clid);
+ if (rpc_client) {
+ char name[] = "switch";
+- struct rpc_sysfs_xprt_switch *xswitch =
+- (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs;
+ int ret;
+
+ clnt->cl_sysfs = rpc_client;
+@@ -558,6 +561,8 @@ void rpc_sysfs_xprt_switch_setup(struct rpc_xprt_switch *xprt_switch,
+ rpc_xprt_switch->xprt_switch = xprt_switch;
+ rpc_xprt_switch->xprt = xprt;
+ kobject_uevent(&rpc_xprt_switch->kobject, KOBJ_ADD);
++ } else {
++ xprt_switch->xps_sysfs = NULL;
+ }
+ }
+
+@@ -569,6 +574,9 @@ void rpc_sysfs_xprt_setup(struct rpc_xprt_switch *xprt_switch,
+ struct rpc_sysfs_xprt_switch *switch_obj =
+ (struct rpc_sysfs_xprt_switch *)xprt_switch->xps_sysfs;
+
++ if (!switch_obj)
++ return;
++
+ rpc_xprt = rpc_sysfs_xprt_alloc(&switch_obj->kobject, xprt, gfp_flags);
+ if (rpc_xprt) {
+ xprt->xprt_sysfs = rpc_xprt;
+diff --git a/net/unix/unix_bpf.c b/net/unix/unix_bpf.c
+index 7cf14c6b17254..e9bf155139612 100644
+--- a/net/unix/unix_bpf.c
++++ b/net/unix/unix_bpf.c
+@@ -145,12 +145,12 @@ int unix_dgram_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool re
+
+ if (restore) {
+ sk->sk_write_space = psock->saved_write_space;
+- WRITE_ONCE(sk->sk_prot, psock->sk_proto);
++ sock_replace_proto(sk, psock->sk_proto);
+ return 0;
+ }
+
+ unix_dgram_bpf_check_needs_rebuild(psock->sk_proto);
+- WRITE_ONCE(sk->sk_prot, &unix_dgram_bpf_prot);
++ sock_replace_proto(sk, &unix_dgram_bpf_prot);
+ return 0;
+ }
+
+@@ -158,12 +158,12 @@ int unix_stream_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool r
+ {
+ if (restore) {
+ sk->sk_write_space = psock->saved_write_space;
+- WRITE_ONCE(sk->sk_prot, psock->sk_proto);
++ sock_replace_proto(sk, psock->sk_proto);
+ return 0;
+ }
+
+ unix_stream_bpf_check_needs_rebuild(psock->sk_proto);
+- WRITE_ONCE(sk->sk_prot, &unix_stream_bpf_prot);
++ sock_replace_proto(sk, &unix_stream_bpf_prot);
+ return 0;
+ }
+
+diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
+index b4ee163154a68..e5ab2418f9d6b 100644
+--- a/net/vmw_vsock/af_vsock.c
++++ b/net/vmw_vsock/af_vsock.c
+@@ -1894,8 +1894,11 @@ static int vsock_connectible_wait_data(struct sock *sk,
+ err = 0;
+ transport = vsk->transport;
+
+- while ((data = vsock_connectible_has_data(vsk)) == 0) {
++ while (1) {
+ prepare_to_wait(sk_sleep(sk), wait, TASK_INTERRUPTIBLE);
++ data = vsock_connectible_has_data(vsk);
++ if (data != 0)
++ break;
+
+ if (sk->sk_err != 0 ||
+ (sk->sk_shutdown & RCV_SHUTDOWN) ||
+diff --git a/security/commoncap.c b/security/commoncap.c
+index 5fc8986c3c77c..bc751fa5adad7 100644
+--- a/security/commoncap.c
++++ b/security/commoncap.c
+@@ -401,8 +401,10 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns,
+ &tmpbuf, size, GFP_NOFS);
+ dput(dentry);
+
+- if (ret < 0 || !tmpbuf)
+- return ret;
++ if (ret < 0 || !tmpbuf) {
++ size = ret;
++ goto out_free;
++ }
+
+ fs_ns = inode->i_sb->s_user_ns;
+ cap = (struct vfs_cap_data *) tmpbuf;
+diff --git a/tools/include/nolibc/string.h b/tools/include/nolibc/string.h
+index bef35bee9c44c..ad97c0d522b8e 100644
+--- a/tools/include/nolibc/string.h
++++ b/tools/include/nolibc/string.h
+@@ -19,9 +19,9 @@ static __attribute__((unused))
+ int memcmp(const void *s1, const void *s2, size_t n)
+ {
+ size_t ofs = 0;
+- char c1 = 0;
++ int c1 = 0;
+
+- while (ofs < n && !(c1 = ((char *)s1)[ofs] - ((char *)s2)[ofs])) {
++ while (ofs < n && !(c1 = ((unsigned char *)s1)[ofs] - ((unsigned char *)s2)[ofs])) {
+ ofs++;
+ }
+ return c1;
+@@ -125,14 +125,18 @@ char *strcpy(char *dst, const char *src)
+ }
+
+ /* this function is only used with arguments that are not constants or when
+- * it's not known because optimizations are disabled.
++ * it's not known because optimizations are disabled. Note that gcc 12
++ * recognizes an strlen() pattern and replaces it with a jump to strlen(),
++ * thus itself, hence the asm() statement below that's meant to disable this
++ * confusing practice.
+ */
+ static __attribute__((unused))
+-size_t nolibc_strlen(const char *str)
++size_t strlen(const char *str)
+ {
+ size_t len;
+
+- for (len = 0; str[len]; len++);
++ for (len = 0; str[len]; len++)
++ asm("");
+ return len;
+ }
+
+@@ -140,13 +144,12 @@ size_t nolibc_strlen(const char *str)
+ * the two branches, then will rely on an external definition of strlen().
+ */
+ #if defined(__OPTIMIZE__)
++#define nolibc_strlen(x) strlen(x)
+ #define strlen(str) ({ \
+ __builtin_constant_p((str)) ? \
+ __builtin_strlen((str)) : \
+ nolibc_strlen((str)); \
+ })
+-#else
+-#define strlen(str) nolibc_strlen((str))
+ #endif
+
+ static __attribute__((unused))
+diff --git a/tools/testing/selftests/landlock/Makefile b/tools/testing/selftests/landlock/Makefile
+index 6632bfff486b8..348e2dbdb4e0b 100644
+--- a/tools/testing/selftests/landlock/Makefile
++++ b/tools/testing/selftests/landlock/Makefile
+@@ -3,7 +3,6 @@
+ # First run: make -C ../../../.. headers_install
+
+ CFLAGS += -Wall -O2 $(KHDR_INCLUDES)
+-LDLIBS += -lcap
+
+ LOCAL_HDRS += common.h
+
+@@ -13,10 +12,12 @@ TEST_GEN_PROGS := $(src_test:.c=)
+
+ TEST_GEN_PROGS_EXTENDED := true
+
+-# Static linking for short targets:
++# Short targets:
++$(TEST_GEN_PROGS): LDLIBS += -lcap
+ $(TEST_GEN_PROGS_EXTENDED): LDFLAGS += -static
+
+ include ../lib.mk
+
+-# Static linking for targets with $(OUTPUT)/ prefix:
++# Targets with $(OUTPUT)/ prefix:
++$(TEST_GEN_PROGS): LDLIBS += -lcap
+ $(TEST_GEN_PROGS_EXTENDED): LDFLAGS += -static
+diff --git a/virt/kvm/pfncache.c b/virt/kvm/pfncache.c
+index 68ff41d395452..346e47f155724 100644
+--- a/virt/kvm/pfncache.c
++++ b/virt/kvm/pfncache.c
+@@ -81,6 +81,9 @@ bool kvm_gfn_to_pfn_cache_check(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+ {
+ struct kvm_memslots *slots = kvm_memslots(kvm);
+
++ if (!gpc->active)
++ return false;
++
+ if ((gpa & ~PAGE_MASK) + len > PAGE_SIZE)
+ return false;
+
+@@ -240,10 +243,11 @@ int kvm_gfn_to_pfn_cache_refresh(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+ {
+ struct kvm_memslots *slots = kvm_memslots(kvm);
+ unsigned long page_offset = gpa & ~PAGE_MASK;
+- kvm_pfn_t old_pfn, new_pfn;
++ bool unmap_old = false;
+ unsigned long old_uhva;
++ kvm_pfn_t old_pfn;
+ void *old_khva;
+- int ret = 0;
++ int ret;
+
+ /*
+ * If must fit within a single page. The 'len' argument is
+@@ -261,6 +265,11 @@ int kvm_gfn_to_pfn_cache_refresh(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+
+ write_lock_irq(&gpc->lock);
+
++ if (!gpc->active) {
++ ret = -EINVAL;
++ goto out_unlock;
++ }
++
+ old_pfn = gpc->pfn;
+ old_khva = gpc->khva - offset_in_page(gpc->khva);
+ old_uhva = gpc->uhva;
+@@ -291,6 +300,7 @@ int kvm_gfn_to_pfn_cache_refresh(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+ /* If the HVA→PFN mapping was already valid, don't unmap it. */
+ old_pfn = KVM_PFN_ERR_FAULT;
+ old_khva = NULL;
++ ret = 0;
+ }
+
+ out:
+@@ -305,14 +315,15 @@ int kvm_gfn_to_pfn_cache_refresh(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+ gpc->khva = NULL;
+ }
+
+- /* Snapshot the new pfn before dropping the lock! */
+- new_pfn = gpc->pfn;
++ /* Detect a pfn change before dropping the lock! */
++ unmap_old = (old_pfn != gpc->pfn);
+
++out_unlock:
+ write_unlock_irq(&gpc->lock);
+
+ mutex_unlock(&gpc->refresh_lock);
+
+- if (old_pfn != new_pfn)
++ if (unmap_old)
+ gpc_unmap_khva(kvm, old_pfn, old_khva);
+
+ return ret;
+@@ -346,42 +357,61 @@ void kvm_gfn_to_pfn_cache_unmap(struct kvm *kvm, struct gfn_to_pfn_cache *gpc)
+ }
+ EXPORT_SYMBOL_GPL(kvm_gfn_to_pfn_cache_unmap);
+
++void kvm_gpc_init(struct gfn_to_pfn_cache *gpc)
++{
++ rwlock_init(&gpc->lock);
++ mutex_init(&gpc->refresh_lock);
++}
++EXPORT_SYMBOL_GPL(kvm_gpc_init);
+
+-int kvm_gfn_to_pfn_cache_init(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
+- struct kvm_vcpu *vcpu, enum pfn_cache_usage usage,
+- gpa_t gpa, unsigned long len)
++int kvm_gpc_activate(struct kvm *kvm, struct gfn_to_pfn_cache *gpc,
++ struct kvm_vcpu *vcpu, enum pfn_cache_usage usage,
++ gpa_t gpa, unsigned long len)
+ {
+ WARN_ON_ONCE(!usage || (usage & KVM_GUEST_AND_HOST_USE_PFN) != usage);
+
+ if (!gpc->active) {
+- rwlock_init(&gpc->lock);
+- mutex_init(&gpc->refresh_lock);
+-
+ gpc->khva = NULL;
+ gpc->pfn = KVM_PFN_ERR_FAULT;
+ gpc->uhva = KVM_HVA_ERR_BAD;
+ gpc->vcpu = vcpu;
+ gpc->usage = usage;
+ gpc->valid = false;
+- gpc->active = true;
+
+ spin_lock(&kvm->gpc_lock);
+ list_add(&gpc->list, &kvm->gpc_list);
+ spin_unlock(&kvm->gpc_lock);
++
++ /*
++ * Activate the cache after adding it to the list, a concurrent
++ * refresh must not establish a mapping until the cache is
++ * reachable by mmu_notifier events.
++ */
++ write_lock_irq(&gpc->lock);
++ gpc->active = true;
++ write_unlock_irq(&gpc->lock);
+ }
+ return kvm_gfn_to_pfn_cache_refresh(kvm, gpc, gpa, len);
+ }
+-EXPORT_SYMBOL_GPL(kvm_gfn_to_pfn_cache_init);
++EXPORT_SYMBOL_GPL(kvm_gpc_activate);
+
+-void kvm_gfn_to_pfn_cache_destroy(struct kvm *kvm, struct gfn_to_pfn_cache *gpc)
++void kvm_gpc_deactivate(struct kvm *kvm, struct gfn_to_pfn_cache *gpc)
+ {
+ if (gpc->active) {
++ /*
++ * Deactivate the cache before removing it from the list, KVM
++ * must stall mmu_notifier events until all users go away, i.e.
++ * until gpc->lock is dropped and refresh is guaranteed to fail.
++ */
++ write_lock_irq(&gpc->lock);
++ gpc->active = false;
++ write_unlock_irq(&gpc->lock);
++
+ spin_lock(&kvm->gpc_lock);
+ list_del(&gpc->list);
+ spin_unlock(&kvm->gpc_lock);
+
+ kvm_gfn_to_pfn_cache_unmap(kvm, gpc);
+- gpc->active = false;
+ }
+ }
+-EXPORT_SYMBOL_GPL(kvm_gfn_to_pfn_cache_destroy);
++EXPORT_SYMBOL_GPL(kvm_gpc_deactivate);
next reply other threads:[~2022-11-10 18:10 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-10 18:10 Mike Pagano [this message]
-- strict thread matches above, loose matches on Subject: below --
2023-01-12 12:17 [gentoo-commits] proj/linux-patches:6.0 commit in: / Mike Pagano
2023-01-07 11:11 Mike Pagano
2023-01-04 11:38 Mike Pagano
2022-12-31 15:29 Mike Pagano
2022-12-21 18:50 Alice Ferrazzi
2022-12-19 12:23 Alice Ferrazzi
2022-12-16 19:56 Mike Pagano
2022-12-14 12:51 Mike Pagano
2022-12-14 12:13 Mike Pagano
2022-12-08 11:40 Alice Ferrazzi
2022-12-06 13:46 Mike Pagano
2022-12-06 13:00 Mike Pagano
2022-12-02 17:23 Mike Pagano
2022-11-26 11:55 Mike Pagano
2022-11-16 11:16 Alice Ferrazzi
2022-11-10 18:18 Mike Pagano
2022-11-09 19:00 Mike Pagano
2022-11-03 15:27 Mike Pagano
2022-11-01 12:46 Mike Pagano
2022-10-29 9:54 Mike Pagano
2022-10-26 11:24 Mike Pagano
2022-10-21 13:14 Mike Pagano
2022-10-15 10:03 Mike Pagano
2022-10-12 11:16 Mike Pagano
2022-10-03 9:31 Mike Pagano
2022-09-11 22:30 Mike Pagano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1668103787.8b3e419be10860f5c8692b5fb9acaaee189b3279.mpagano@gentoo \
--to=mpagano@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox