]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Mon, 29 Jan 2024 00:17:58 +0000 (19:17 -0500)
committerSasha Levin <sashal@kernel.org>
Mon, 29 Jan 2024 00:17:58 +0000 (19:17 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
28 files changed:
queue-5.15/arm-dts-qcom-sdx55-fix-pdc-interrupt-cells.patch [new file with mode: 0644]
queue-5.15/arm-dts-qcom-sdx55-fix-usb-dp-dm-hs-phy-interrupts.patch [new file with mode: 0644]
queue-5.15/arm-dts-qcom-sdx55-fix-usb-ss-wakeup.patch [new file with mode: 0644]
queue-5.15/arm-dts-qcom-sdx55-fix-usb-wakeup-interrupt-types.patch [new file with mode: 0644]
queue-5.15/arm-dts-samsung-exynos4210-i9100-unconditionally-ena.patch [new file with mode: 0644]
queue-5.15/btrfs-add-definition-for-extent_tree_v2.patch [new file with mode: 0644]
queue-5.15/btrfs-don-t-abort-filesystem-when-attempting-to-snap.patch [new file with mode: 0644]
queue-5.15/bus-mhi-host-add-alignment-check-for-event-ring-read.patch [new file with mode: 0644]
queue-5.15/bus-mhi-host-rename-struct-mhi_tre-to-struct-mhi_rin.patch [new file with mode: 0644]
queue-5.15/cpufreq-intel_pstate-drop-redundant-intel_pstate_get.patch [new file with mode: 0644]
queue-5.15/cpufreq-intel_pstate-refine-computation-of-p-state-f.patch [new file with mode: 0644]
queue-5.15/fs-pipe-move-check-to-pipe_has_watch_queue.patch [new file with mode: 0644]
queue-5.15/ksmbd-fix-global-oob-in-ksmbd_nl_policy.patch [new file with mode: 0644]
queue-5.15/media-mtk-jpeg-fix-use-after-free-bug-due-to-error-p.patch [new file with mode: 0644]
queue-5.15/mm-sparsemem-fix-race-in-accessing-memory_section-us.patch [new file with mode: 0644]
queue-5.15/mm-use-__pfn_to_section-instead-of-open-coding-it.patch [new file with mode: 0644]
queue-5.15/nfsd-add-documenting-comment-for-nfsd4_release_locko.patch [new file with mode: 0644]
queue-5.15/nfsd-fix-release_lockowner.patch [new file with mode: 0644]
queue-5.15/nfsd-modernize-nfsd4_release_lockowner.patch [new file with mode: 0644]
queue-5.15/pipe-wakeup-wr_wait-after-setting-max_usage.patch [new file with mode: 0644]
queue-5.15/pm-core-remove-unnecessary-void-conversions.patch [new file with mode: 0644]
queue-5.15/pm-devfreq-add-cpu-based-scaling-support-to-passive-.patch [new file with mode: 0644]
queue-5.15/pm-devfreq-export-devfreq_get_freq_range-symbol-with.patch [new file with mode: 0644]
queue-5.15/pm-devfreq-fix-buffer-overflow-in-trans_stat_show.patch [new file with mode: 0644]
queue-5.15/pm-devfreq-passive-reduce-duplicate-code-when-passiv.patch [new file with mode: 0644]
queue-5.15/pm-devfreq-rework-freq_table-to-be-local-to-devfreq-.patch [new file with mode: 0644]
queue-5.15/pm-sleep-fix-possible-deadlocks-in-core-system-wide-.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/arm-dts-qcom-sdx55-fix-pdc-interrupt-cells.patch b/queue-5.15/arm-dts-qcom-sdx55-fix-pdc-interrupt-cells.patch
new file mode 100644 (file)
index 0000000..e608562
--- /dev/null
@@ -0,0 +1,41 @@
+From 5ac28110ac4e6591b9a3ecbb3d2bdae6cff04bf1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Dec 2023 18:31:29 +0100
+Subject: ARM: dts: qcom: sdx55: fix pdc '#interrupt-cells'
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit cc25bd06c16aa582596a058d375b2e3133f79b93 ]
+
+The Qualcomm PDC interrupt controller binding expects two cells in
+interrupt specifiers.
+
+Fixes: 9d038b2e62de ("ARM: dts: qcom: Add SDX55 platform and MTP board support")
+Cc: stable@vger.kernel.org      # 5.12
+Cc: Manivannan Sadhasivam <mani@kernel.org>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20231213173131.29436-2-johan+linaro@kernel.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/qcom-sdx55.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/qcom-sdx55.dtsi b/arch/arm/boot/dts/qcom-sdx55.dtsi
+index 4e7381d0e205..e8b4cbd39413 100644
+--- a/arch/arm/boot/dts/qcom-sdx55.dtsi
++++ b/arch/arm/boot/dts/qcom-sdx55.dtsi
+@@ -447,7 +447,7 @@ pdc: interrupt-controller@b210000 {
+                       compatible = "qcom,sdx55-pdc", "qcom,pdc";
+                       reg = <0x0b210000 0x30000>;
+                       qcom,pdc-ranges = <0 179 52>;
+-                      #interrupt-cells = <3>;
++                      #interrupt-cells = <2>;
+                       interrupt-parent = <&intc>;
+                       interrupt-controller;
+               };
+-- 
+2.43.0
+
diff --git a/queue-5.15/arm-dts-qcom-sdx55-fix-usb-dp-dm-hs-phy-interrupts.patch b/queue-5.15/arm-dts-qcom-sdx55-fix-usb-dp-dm-hs-phy-interrupts.patch
new file mode 100644 (file)
index 0000000..fbe456c
--- /dev/null
@@ -0,0 +1,55 @@
+From 3a22928cb52748862acefd72fc12c1938ea91a7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Dec 2023 18:31:30 +0100
+Subject: ARM: dts: qcom: sdx55: fix USB DP/DM HS PHY interrupts
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit de95f139394a5ed82270f005bc441d2e7c1e51b7 ]
+
+The USB DP/DM HS PHY interrupts need to be provided by the PDC interrupt
+controller in order to be able to wake the system up from low-power
+states and to be able to detect disconnect events, which requires
+triggering on falling edges.
+
+A recent commit updated the trigger type but failed to change the
+interrupt provider as required. This leads to the current Linux driver
+failing to probe instead of printing an error during suspend and USB
+wakeup not working as intended.
+
+Fixes: d0ec3c4c11c3 ("ARM: dts: qcom: sdx55: fix USB wakeup interrupt types")
+Fixes: fea4b41022f3 ("ARM: dts: qcom: sdx55: Add USB3 and PHY support")
+Cc: stable@vger.kernel.org     # 5.12
+Cc: Manivannan Sadhasivam <mani@kernel.org>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20231213173131.29436-3-johan+linaro@kernel.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/qcom-sdx55.dtsi | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/arch/arm/boot/dts/qcom-sdx55.dtsi b/arch/arm/boot/dts/qcom-sdx55.dtsi
+index e8b4cbd39413..9c0d2432f105 100644
+--- a/arch/arm/boot/dts/qcom-sdx55.dtsi
++++ b/arch/arm/boot/dts/qcom-sdx55.dtsi
+@@ -420,10 +420,10 @@ usb: usb@a6f8800 {
+                                         <&gcc GCC_USB30_MASTER_CLK>;
+                       assigned-clock-rates = <19200000>, <200000000>;
+-                      interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+-                                   <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
+-                                   <GIC_SPI 158 IRQ_TYPE_EDGE_BOTH>,
+-                                   <GIC_SPI 157 IRQ_TYPE_EDGE_BOTH>;
++                      interrupts-extended = <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
++                                            <&intc GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
++                                            <&pdc 11 IRQ_TYPE_EDGE_BOTH>,
++                                            <&pdc 10 IRQ_TYPE_EDGE_BOTH>;
+                       interrupt-names = "hs_phy_irq", "ss_phy_irq",
+                                         "dm_hs_phy_irq", "dp_hs_phy_irq";
+-- 
+2.43.0
+
diff --git a/queue-5.15/arm-dts-qcom-sdx55-fix-usb-ss-wakeup.patch b/queue-5.15/arm-dts-qcom-sdx55-fix-usb-ss-wakeup.patch
new file mode 100644 (file)
index 0000000..22ccc84
--- /dev/null
@@ -0,0 +1,42 @@
+From d1538f20b12a7550139abe78d64ab65a7624b39d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Dec 2023 18:31:31 +0100
+Subject: ARM: dts: qcom: sdx55: fix USB SS wakeup
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit 710dd03464e4ab5b3d329768388b165d61958577 ]
+
+The USB SS PHY interrupt needs to be provided by the PDC interrupt
+controller in order to be able to wake the system up from low-power
+states.
+
+Fixes: fea4b41022f3 ("ARM: dts: qcom: sdx55: Add USB3 and PHY support")
+Cc: stable@vger.kernel.org     # 5.12
+Cc: Manivannan Sadhasivam <mani@kernel.org>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20231213173131.29436-4-johan+linaro@kernel.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/qcom-sdx55.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/boot/dts/qcom-sdx55.dtsi b/arch/arm/boot/dts/qcom-sdx55.dtsi
+index 9c0d2432f105..67159e8608ed 100644
+--- a/arch/arm/boot/dts/qcom-sdx55.dtsi
++++ b/arch/arm/boot/dts/qcom-sdx55.dtsi
+@@ -421,7 +421,7 @@ usb: usb@a6f8800 {
+                       assigned-clock-rates = <19200000>, <200000000>;
+                       interrupts-extended = <&intc GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+-                                            <&intc GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
++                                            <&pdc 51 IRQ_TYPE_LEVEL_HIGH>,
+                                             <&pdc 11 IRQ_TYPE_EDGE_BOTH>,
+                                             <&pdc 10 IRQ_TYPE_EDGE_BOTH>;
+                       interrupt-names = "hs_phy_irq", "ss_phy_irq",
+-- 
+2.43.0
+
diff --git a/queue-5.15/arm-dts-qcom-sdx55-fix-usb-wakeup-interrupt-types.patch b/queue-5.15/arm-dts-qcom-sdx55-fix-usb-wakeup-interrupt-types.patch
new file mode 100644 (file)
index 0000000..5dbb7df
--- /dev/null
@@ -0,0 +1,42 @@
+From 81ab42f89ee8b35f438d2e21b318d12459f2b32e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Nov 2023 17:43:21 +0100
+Subject: ARM: dts: qcom: sdx55: fix USB wakeup interrupt types
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit d0ec3c4c11c3b30e1f2d344973b2a7bf0f986734 ]
+
+The DP/DM wakeup interrupts are edge triggered and which edge to trigger
+on depends on use-case and whether a Low speed or Full/High speed device
+is connected.
+
+Fixes: fea4b41022f3 ("ARM: dts: qcom: sdx55: Add USB3 and PHY support")
+Cc: stable@vger.kernel.org      # 5.12
+Cc: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Link: https://lore.kernel.org/r/20231120164331.8116-2-johan+linaro@kernel.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/qcom-sdx55.dtsi | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/boot/dts/qcom-sdx55.dtsi b/arch/arm/boot/dts/qcom-sdx55.dtsi
+index 73fa0ef6b69e..4e7381d0e205 100644
+--- a/arch/arm/boot/dts/qcom-sdx55.dtsi
++++ b/arch/arm/boot/dts/qcom-sdx55.dtsi
+@@ -422,8 +422,8 @@ usb: usb@a6f8800 {
+                       interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
+-                                   <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>,
+-                                   <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
++                                   <GIC_SPI 158 IRQ_TYPE_EDGE_BOTH>,
++                                   <GIC_SPI 157 IRQ_TYPE_EDGE_BOTH>;
+                       interrupt-names = "hs_phy_irq", "ss_phy_irq",
+                                         "dm_hs_phy_irq", "dp_hs_phy_irq";
+-- 
+2.43.0
+
diff --git a/queue-5.15/arm-dts-samsung-exynos4210-i9100-unconditionally-ena.patch b/queue-5.15/arm-dts-samsung-exynos4210-i9100-unconditionally-ena.patch
new file mode 100644 (file)
index 0000000..2384f99
--- /dev/null
@@ -0,0 +1,47 @@
+From d4e1dc126dce97720f2aed7d74115256f8db1475 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Dec 2023 23:15:54 +0100
+Subject: ARM: dts: samsung: exynos4210-i9100: Unconditionally enable LDO12
+
+From: Paul Cercueil <paul@crapouillou.net>
+
+[ Upstream commit 84228d5e29dbc7a6be51e221000e1d122125826c ]
+
+The kernel hangs for a good 12 seconds without any info being printed to
+dmesg, very early in the boot process, if this regulator is not enabled.
+
+Force-enable it to work around this issue, until we know more about the
+underlying problem.
+
+Signed-off-by: Paul Cercueil <paul@crapouillou.net>
+Fixes: 8620cc2f99b7 ("ARM: dts: exynos: Add devicetree file for the Galaxy S2")
+Cc: stable@vger.kernel.org # v5.8+
+Link: https://lore.kernel.org/r/20231206221556.15348-2-paul@crapouillou.net
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/boot/dts/exynos4210-i9100.dts | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/arch/arm/boot/dts/exynos4210-i9100.dts b/arch/arm/boot/dts/exynos4210-i9100.dts
+index 93880bdbcad9..8232d843bfe0 100644
+--- a/arch/arm/boot/dts/exynos4210-i9100.dts
++++ b/arch/arm/boot/dts/exynos4210-i9100.dts
+@@ -520,6 +520,14 @@ vtcam_reg: LDO12 {
+                               regulator-name = "VT_CAM_1.8V";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
++
++                              /*
++                               * Force-enable this regulator; otherwise the
++                               * kernel hangs very early in the boot process
++                               * for about 12 seconds, without apparent
++                               * reason.
++                               */
++                              regulator-always-on;
+                       };
+                       vcclcd_reg: LDO13 {
+-- 
+2.43.0
+
diff --git a/queue-5.15/btrfs-add-definition-for-extent_tree_v2.patch b/queue-5.15/btrfs-add-definition-for-extent_tree_v2.patch
new file mode 100644 (file)
index 0000000..11771d5
--- /dev/null
@@ -0,0 +1,107 @@
+From 2b5a8427f3f452bd6c02e781473eea4d4dd3f65d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Dec 2021 15:39:58 -0500
+Subject: btrfs: add definition for EXTENT_TREE_V2
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit 2c7d2a230237e7c43fa067d695937b7e484bb92a ]
+
+This adds the initial definition of the EXTENT_TREE_V2 incompat feature
+flag.  This also hides the support behind CONFIG_BTRFS_DEBUG.
+
+THIS IS A IN DEVELOPMENT FORMAT CHANGE, DO NOT USE UNLESS YOU ARE A
+DEVELOPER OR A TESTER.
+
+The format is in flux and will be added in stages, any fs will need to
+be re-made between updates to the format.
+
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 7081929ab257 ("btrfs: don't abort filesystem when attempting to snapshot deleted subvolume")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/ctree.h           | 21 +++++++++++++++++++++
+ fs/btrfs/sysfs.c           |  5 ++++-
+ include/uapi/linux/btrfs.h |  1 +
+ 3 files changed, 26 insertions(+), 1 deletion(-)
+
+diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
+index 7905f178efa3..17ebcf19b444 100644
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -282,6 +282,26 @@ struct btrfs_super_block {
+ #define BTRFS_FEATURE_COMPAT_RO_SAFE_SET      0ULL
+ #define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR    0ULL
++#ifdef CONFIG_BTRFS_DEBUG
++/*
++ * Extent tree v2 supported only with CONFIG_BTRFS_DEBUG
++ */
++#define BTRFS_FEATURE_INCOMPAT_SUPP                   \
++      (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF |         \
++       BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL |        \
++       BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS |          \
++       BTRFS_FEATURE_INCOMPAT_BIG_METADATA |          \
++       BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO |          \
++       BTRFS_FEATURE_INCOMPAT_COMPRESS_ZSTD |         \
++       BTRFS_FEATURE_INCOMPAT_RAID56 |                \
++       BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF |         \
++       BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA |       \
++       BTRFS_FEATURE_INCOMPAT_NO_HOLES        |       \
++       BTRFS_FEATURE_INCOMPAT_METADATA_UUID   |       \
++       BTRFS_FEATURE_INCOMPAT_RAID1C34        |       \
++       BTRFS_FEATURE_INCOMPAT_ZONED           |       \
++       BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2)
++#else
+ #define BTRFS_FEATURE_INCOMPAT_SUPP                   \
+       (BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF |         \
+        BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL |        \
+@@ -296,6 +316,7 @@ struct btrfs_super_block {
+        BTRFS_FEATURE_INCOMPAT_METADATA_UUID   |       \
+        BTRFS_FEATURE_INCOMPAT_RAID1C34        |       \
+        BTRFS_FEATURE_INCOMPAT_ZONED)
++#endif
+ #define BTRFS_FEATURE_INCOMPAT_SAFE_SET                       \
+       (BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF)
+diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
+index 899dda6eb835..93a9dfbc8d13 100644
+--- a/fs/btrfs/sysfs.c
++++ b/fs/btrfs/sysfs.c
+@@ -283,9 +283,11 @@ BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES);
+ BTRFS_FEAT_ATTR_INCOMPAT(metadata_uuid, METADATA_UUID);
+ BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE);
+ BTRFS_FEAT_ATTR_INCOMPAT(raid1c34, RAID1C34);
+-/* Remove once support for zoned allocation is feature complete */
+ #ifdef CONFIG_BTRFS_DEBUG
++/* Remove once support for zoned allocation is feature complete */
+ BTRFS_FEAT_ATTR_INCOMPAT(zoned, ZONED);
++/* Remove once support for extent tree v2 is feature complete */
++BTRFS_FEAT_ATTR_INCOMPAT(extent_tree_v2, EXTENT_TREE_V2);
+ #endif
+ #ifdef CONFIG_FS_VERITY
+ BTRFS_FEAT_ATTR_COMPAT_RO(verity, VERITY);
+@@ -314,6 +316,7 @@ static struct attribute *btrfs_supported_feature_attrs[] = {
+       BTRFS_FEAT_ATTR_PTR(raid1c34),
+ #ifdef CONFIG_BTRFS_DEBUG
+       BTRFS_FEAT_ATTR_PTR(zoned),
++      BTRFS_FEAT_ATTR_PTR(extent_tree_v2),
+ #endif
+ #ifdef CONFIG_FS_VERITY
+       BTRFS_FEAT_ATTR_PTR(verity),
+diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
+index 4693b6ba30a1..493b10b9fedd 100644
+--- a/include/uapi/linux/btrfs.h
++++ b/include/uapi/linux/btrfs.h
+@@ -310,6 +310,7 @@ struct btrfs_ioctl_fs_info_args {
+ #define BTRFS_FEATURE_INCOMPAT_METADATA_UUID  (1ULL << 10)
+ #define BTRFS_FEATURE_INCOMPAT_RAID1C34               (1ULL << 11)
+ #define BTRFS_FEATURE_INCOMPAT_ZONED          (1ULL << 12)
++#define BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2 (1ULL << 13)
+ struct btrfs_ioctl_feature_flags {
+       __u64 compat_flags;
+-- 
+2.43.0
+
diff --git a/queue-5.15/btrfs-don-t-abort-filesystem-when-attempting-to-snap.patch b/queue-5.15/btrfs-don-t-abort-filesystem-when-attempting-to-snap.patch
new file mode 100644 (file)
index 0000000..9028d88
--- /dev/null
@@ -0,0 +1,103 @@
+From 89c9aa2ee17347ff34f87961e2c1287bd351d3cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jan 2024 11:48:46 -0800
+Subject: btrfs: don't abort filesystem when attempting to snapshot deleted
+ subvolume
+
+From: Omar Sandoval <osandov@fb.com>
+
+[ Upstream commit 7081929ab2572920e94d70be3d332e5c9f97095a ]
+
+If the source file descriptor to the snapshot ioctl refers to a deleted
+subvolume, we get the following abort:
+
+  BTRFS: Transaction aborted (error -2)
+  WARNING: CPU: 0 PID: 833 at fs/btrfs/transaction.c:1875 create_pending_snapshot+0x1040/0x1190 [btrfs]
+  Modules linked in: pata_acpi btrfs ata_piix libata scsi_mod virtio_net blake2b_generic xor net_failover virtio_rng failover scsi_common rng_core raid6_pq libcrc32c
+  CPU: 0 PID: 833 Comm: t_snapshot_dele Not tainted 6.7.0-rc6 #2
+  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-1.fc39 04/01/2014
+  RIP: 0010:create_pending_snapshot+0x1040/0x1190 [btrfs]
+  RSP: 0018:ffffa09c01337af8 EFLAGS: 00010282
+  RAX: 0000000000000000 RBX: ffff9982053e7c78 RCX: 0000000000000027
+  RDX: ffff99827dc20848 RSI: 0000000000000001 RDI: ffff99827dc20840
+  RBP: ffffa09c01337c00 R08: 0000000000000000 R09: ffffa09c01337998
+  R10: 0000000000000003 R11: ffffffffb96da248 R12: fffffffffffffffe
+  R13: ffff99820535bb28 R14: ffff99820b7bd000 R15: ffff99820381ea80
+  FS:  00007fe20aadabc0(0000) GS:ffff99827dc00000(0000) knlGS:0000000000000000
+  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  CR2: 0000559a120b502f CR3: 00000000055b6000 CR4: 00000000000006f0
+  Call Trace:
+   <TASK>
+   ? create_pending_snapshot+0x1040/0x1190 [btrfs]
+   ? __warn+0x81/0x130
+   ? create_pending_snapshot+0x1040/0x1190 [btrfs]
+   ? report_bug+0x171/0x1a0
+   ? handle_bug+0x3a/0x70
+   ? exc_invalid_op+0x17/0x70
+   ? asm_exc_invalid_op+0x1a/0x20
+   ? create_pending_snapshot+0x1040/0x1190 [btrfs]
+   ? create_pending_snapshot+0x1040/0x1190 [btrfs]
+   create_pending_snapshots+0x92/0xc0 [btrfs]
+   btrfs_commit_transaction+0x66b/0xf40 [btrfs]
+   btrfs_mksubvol+0x301/0x4d0 [btrfs]
+   btrfs_mksnapshot+0x80/0xb0 [btrfs]
+   __btrfs_ioctl_snap_create+0x1c2/0x1d0 [btrfs]
+   btrfs_ioctl_snap_create_v2+0xc4/0x150 [btrfs]
+   btrfs_ioctl+0x8a6/0x2650 [btrfs]
+   ? kmem_cache_free+0x22/0x340
+   ? do_sys_openat2+0x97/0xe0
+   __x64_sys_ioctl+0x97/0xd0
+   do_syscall_64+0x46/0xf0
+   entry_SYSCALL_64_after_hwframe+0x6e/0x76
+  RIP: 0033:0x7fe20abe83af
+  RSP: 002b:00007ffe6eff1360 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
+  RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007fe20abe83af
+  RDX: 00007ffe6eff23c0 RSI: 0000000050009417 RDI: 0000000000000003
+  RBP: 0000000000000003 R08: 0000000000000000 R09: 00007fe20ad16cd0
+  R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+  R13: 00007ffe6eff13c0 R14: 00007fe20ad45000 R15: 0000559a120b6d58
+   </TASK>
+  ---[ end trace 0000000000000000 ]---
+  BTRFS: error (device vdc: state A) in create_pending_snapshot:1875: errno=-2 No such entry
+  BTRFS info (device vdc: state EA): forced readonly
+  BTRFS warning (device vdc: state EA): Skipping commit of aborted transaction.
+  BTRFS: error (device vdc: state EA) in cleanup_transaction:2055: errno=-2 No such entry
+
+This happens because create_pending_snapshot() initializes the new root
+item as a copy of the source root item. This includes the refs field,
+which is 0 for a deleted subvolume. The call to btrfs_insert_root()
+therefore inserts a root with refs == 0. btrfs_get_new_fs_root() then
+finds the root and returns -ENOENT if refs == 0, which causes
+create_pending_snapshot() to abort.
+
+Fix it by checking the source root's refs before attempting the
+snapshot, but after locking subvol_sem to avoid racing with deletion.
+
+CC: stable@vger.kernel.org # 4.14+
+Reviewed-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
+Reviewed-by: Anand Jain <anand.jain@oracle.com>
+Signed-off-by: Omar Sandoval <osandov@fb.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/ioctl.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
+index 37f4370a779d..768f58a53a94 100644
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -725,6 +725,9 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
+       struct btrfs_trans_handle *trans;
+       int ret;
++      if (btrfs_root_refs(&root->root_item) == 0)
++              return -ENOENT;
++
+       if (btrfs_root_refs(&root->root_item) == 0)
+               return -ENOENT;
+-- 
+2.43.0
+
diff --git a/queue-5.15/bus-mhi-host-add-alignment-check-for-event-ring-read.patch b/queue-5.15/bus-mhi-host-add-alignment-check-for-event-ring-read.patch
new file mode 100644 (file)
index 0000000..ba237f2
--- /dev/null
@@ -0,0 +1,46 @@
+From 1dd0380d4d6f0ebd7690cfcda6bc9fe0ce3f179a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 31 Oct 2023 15:21:05 +0530
+Subject: bus: mhi: host: Add alignment check for event ring read pointer
+
+From: Krishna chaitanya chundru <quic_krichai@quicinc.com>
+
+[ Upstream commit eff9704f5332a13b08fbdbe0f84059c9e7051d5f ]
+
+Though we do check the event ring read pointer by "is_valid_ring_ptr"
+to make sure it is in the buffer range, but there is another risk the
+pointer may be not aligned.  Since we are expecting event ring elements
+are 128 bits(struct mhi_ring_element) aligned, an unaligned read pointer
+could lead to multiple issues like DoS or ring buffer memory corruption.
+
+So add a alignment check for event ring read pointer.
+
+Fixes: ec32332df764 ("bus: mhi: core: Sanity check values from remote device before use")
+cc: stable@vger.kernel.org
+Signed-off-by: Krishna chaitanya chundru <quic_krichai@quicinc.com>
+Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20231031-alignment_check-v2-1-1441db7c5efd@quicinc.com
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bus/mhi/host/main.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c
+index 23bd1db94558..1cb7c60594f1 100644
+--- a/drivers/bus/mhi/host/main.c
++++ b/drivers/bus/mhi/host/main.c
+@@ -267,7 +267,8 @@ static void mhi_del_ring_element(struct mhi_controller *mhi_cntrl,
+ static bool is_valid_ring_ptr(struct mhi_ring *ring, dma_addr_t addr)
+ {
+-      return addr >= ring->iommu_base && addr < ring->iommu_base + ring->len;
++      return addr >= ring->iommu_base && addr < ring->iommu_base + ring->len &&
++                      !(addr & (sizeof(struct mhi_ring_element) - 1));
+ }
+ int mhi_destroy_device(struct device *dev, void *data)
+-- 
+2.43.0
+
diff --git a/queue-5.15/bus-mhi-host-rename-struct-mhi_tre-to-struct-mhi_rin.patch b/queue-5.15/bus-mhi-host-rename-struct-mhi_tre-to-struct-mhi_rin.patch
new file mode 100644 (file)
index 0000000..1476dc5
--- /dev/null
@@ -0,0 +1,162 @@
+From 09068651c6304d67704c3e713d38c722e2c0f1e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Mar 2022 21:33:06 +0530
+Subject: bus: mhi: host: Rename "struct mhi_tre" to "struct mhi_ring_element"
+
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+[ Upstream commit 84f5f31f110e5e8cd5581e8efdbf8c369e962eb9 ]
+
+Structure "struct mhi_tre" is representing a generic MHI ring element and
+not specifically a Transfer Ring Element (TRE). Fix the naming.
+
+Reviewed-by: Alex Elder <elder@linaro.org>
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20220301160308.107452-9-manivannan.sadhasivam@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: eff9704f5332 ("bus: mhi: host: Add alignment check for event ring read pointer")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bus/mhi/host/init.c     |  6 +++---
+ drivers/bus/mhi/host/internal.h |  2 +-
+ drivers/bus/mhi/host/main.c     | 20 ++++++++++----------
+ 3 files changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c
+index 829d4fca7ddc..7ccc5cd27fd0 100644
+--- a/drivers/bus/mhi/host/init.c
++++ b/drivers/bus/mhi/host/init.c
+@@ -338,7 +338,7 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl)
+               er_ctxt->msivec = cpu_to_le32(mhi_event->irq);
+               mhi_event->db_cfg.db_mode = true;
+-              ring->el_size = sizeof(struct mhi_tre);
++              ring->el_size = sizeof(struct mhi_ring_element);
+               ring->len = ring->el_size * ring->elements;
+               ret = mhi_alloc_aligned_ring(mhi_cntrl, ring, ring->len);
+               if (ret)
+@@ -370,7 +370,7 @@ int mhi_init_dev_ctxt(struct mhi_controller *mhi_cntrl)
+       for (i = 0; i < NR_OF_CMD_RINGS; i++, mhi_cmd++, cmd_ctxt++) {
+               struct mhi_ring *ring = &mhi_cmd->ring;
+-              ring->el_size = sizeof(struct mhi_tre);
++              ring->el_size = sizeof(struct mhi_ring_element);
+               ring->elements = CMD_EL_PER_RING;
+               ring->len = ring->el_size * ring->elements;
+               ret = mhi_alloc_aligned_ring(mhi_cntrl, ring, ring->len);
+@@ -613,7 +613,7 @@ int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl,
+       buf_ring = &mhi_chan->buf_ring;
+       tre_ring = &mhi_chan->tre_ring;
+-      tre_ring->el_size = sizeof(struct mhi_tre);
++      tre_ring->el_size = sizeof(struct mhi_ring_element);
+       tre_ring->len = tre_ring->el_size * tre_ring->elements;
+       chan_ctxt = &mhi_cntrl->mhi_ctxt->chan_ctxt[mhi_chan->chan];
+       ret = mhi_alloc_aligned_ring(mhi_cntrl, tre_ring, tre_ring->len);
+diff --git a/drivers/bus/mhi/host/internal.h b/drivers/bus/mhi/host/internal.h
+index 71f181402be9..df65bb17fdba 100644
+--- a/drivers/bus/mhi/host/internal.h
++++ b/drivers/bus/mhi/host/internal.h
+@@ -257,7 +257,7 @@ struct mhi_ctxt {
+       dma_addr_t cmd_ctxt_addr;
+ };
+-struct mhi_tre {
++struct mhi_ring_element {
+       __le64 ptr;
+       __le32 dword[2];
+ };
+diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c
+index 0d35acb2f7c0..23bd1db94558 100644
+--- a/drivers/bus/mhi/host/main.c
++++ b/drivers/bus/mhi/host/main.c
+@@ -556,7 +556,7 @@ static void mhi_recycle_ev_ring_element(struct mhi_controller *mhi_cntrl,
+ }
+ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
+-                          struct mhi_tre *event,
++                          struct mhi_ring_element *event,
+                           struct mhi_chan *mhi_chan)
+ {
+       struct mhi_ring *buf_ring, *tre_ring;
+@@ -592,7 +592,7 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
+       case MHI_EV_CC_EOT:
+       {
+               dma_addr_t ptr = MHI_TRE_GET_EV_PTR(event);
+-              struct mhi_tre *local_rp, *ev_tre;
++              struct mhi_ring_element *local_rp, *ev_tre;
+               void *dev_rp;
+               struct mhi_buf_info *buf_info;
+               u16 xfer_len;
+@@ -695,7 +695,7 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
+ }
+ static int parse_rsc_event(struct mhi_controller *mhi_cntrl,
+-                         struct mhi_tre *event,
++                         struct mhi_ring_element *event,
+                          struct mhi_chan *mhi_chan)
+ {
+       struct mhi_ring *buf_ring, *tre_ring;
+@@ -759,12 +759,12 @@ static int parse_rsc_event(struct mhi_controller *mhi_cntrl,
+ }
+ static void mhi_process_cmd_completion(struct mhi_controller *mhi_cntrl,
+-                                     struct mhi_tre *tre)
++                                     struct mhi_ring_element *tre)
+ {
+       dma_addr_t ptr = MHI_TRE_GET_EV_PTR(tre);
+       struct mhi_cmd *cmd_ring = &mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING];
+       struct mhi_ring *mhi_ring = &cmd_ring->ring;
+-      struct mhi_tre *cmd_pkt;
++      struct mhi_ring_element *cmd_pkt;
+       struct mhi_chan *mhi_chan;
+       u32 chan;
+@@ -797,7 +797,7 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl,
+                            struct mhi_event *mhi_event,
+                            u32 event_quota)
+ {
+-      struct mhi_tre *dev_rp, *local_rp;
++      struct mhi_ring_element *dev_rp, *local_rp;
+       struct mhi_ring *ev_ring = &mhi_event->ring;
+       struct mhi_event_ctxt *er_ctxt =
+               &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
+@@ -967,7 +967,7 @@ int mhi_process_data_event_ring(struct mhi_controller *mhi_cntrl,
+                               struct mhi_event *mhi_event,
+                               u32 event_quota)
+ {
+-      struct mhi_tre *dev_rp, *local_rp;
++      struct mhi_ring_element *dev_rp, *local_rp;
+       struct mhi_ring *ev_ring = &mhi_event->ring;
+       struct mhi_event_ctxt *er_ctxt =
+               &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
+@@ -1188,7 +1188,7 @@ int mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
+                       struct mhi_buf_info *info, enum mhi_flags flags)
+ {
+       struct mhi_ring *buf_ring, *tre_ring;
+-      struct mhi_tre *mhi_tre;
++      struct mhi_ring_element *mhi_tre;
+       struct mhi_buf_info *buf_info;
+       int eot, eob, chain, bei;
+       int ret;
+@@ -1266,7 +1266,7 @@ int mhi_send_cmd(struct mhi_controller *mhi_cntrl,
+                struct mhi_chan *mhi_chan,
+                enum mhi_cmd_type cmd)
+ {
+-      struct mhi_tre *cmd_tre = NULL;
++      struct mhi_ring_element *cmd_tre = NULL;
+       struct mhi_cmd *mhi_cmd = &mhi_cntrl->mhi_cmd[PRIMARY_CMD_RING];
+       struct mhi_ring *ring = &mhi_cmd->ring;
+       struct device *dev = &mhi_cntrl->mhi_dev->dev;
+@@ -1524,7 +1524,7 @@ static void mhi_mark_stale_events(struct mhi_controller *mhi_cntrl,
+                                 int chan)
+ {
+-      struct mhi_tre *dev_rp, *local_rp;
++      struct mhi_ring_element *dev_rp, *local_rp;
+       struct mhi_ring *ev_ring;
+       struct device *dev = &mhi_cntrl->mhi_dev->dev;
+       unsigned long flags;
+-- 
+2.43.0
+
diff --git a/queue-5.15/cpufreq-intel_pstate-drop-redundant-intel_pstate_get.patch b/queue-5.15/cpufreq-intel_pstate-drop-redundant-intel_pstate_get.patch
new file mode 100644 (file)
index 0000000..39ff4a1
--- /dev/null
@@ -0,0 +1,64 @@
+From 2af81d33442247fee488492a78d15042d9e78bb1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Dec 2021 17:12:18 +0100
+Subject: cpufreq: intel_pstate: Drop redundant intel_pstate_get_hwp_cap() call
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit 458b03f81afbb27143c45d47c2d8f418b2ba2407 ]
+
+It is not necessary to call intel_pstate_get_hwp_cap() from
+intel_pstate_update_perf_limits(), because it gets called from
+intel_pstate_verify_cpu_policy() which is either invoked directly
+right before intel_pstate_update_perf_limits(), in
+intel_cpufreq_verify_policy() in the passive mode, or called
+from driver callbacks in a sequence that causes it to be followed
+by an immediate intel_pstate_update_perf_limits().
+
+Namely, in the active mode intel_cpufreq_verify_policy() is called
+by intel_pstate_verify_policy() which is the ->verify() callback
+routine of intel_pstate and gets called by the cpufreq core right
+before intel_pstate_set_policy(), which is the driver's ->setoplicy()
+callback routine, where intel_pstate_update_perf_limits() is called.
+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: 192cdb1c907f ("cpufreq: intel_pstate: Refine computation of P-state for given frequency")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/intel_pstate.c | 20 ++++++++------------
+ 1 file changed, 8 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
+index 736cb2cfcbb0..f2a94afb6eec 100644
+--- a/drivers/cpufreq/intel_pstate.c
++++ b/drivers/cpufreq/intel_pstate.c
+@@ -2332,18 +2332,14 @@ static void intel_pstate_update_perf_limits(struct cpudata *cpu,
+        * HWP needs some special consideration, because HWP_REQUEST uses
+        * abstract values to represent performance rather than pure ratios.
+        */
+-      if (hwp_active) {
+-              intel_pstate_get_hwp_cap(cpu);
+-
+-              if (cpu->pstate.scaling != perf_ctl_scaling) {
+-                      int scaling = cpu->pstate.scaling;
+-                      int freq;
+-
+-                      freq = max_policy_perf * perf_ctl_scaling;
+-                      max_policy_perf = DIV_ROUND_UP(freq, scaling);
+-                      freq = min_policy_perf * perf_ctl_scaling;
+-                      min_policy_perf = DIV_ROUND_UP(freq, scaling);
+-              }
++      if (hwp_active && cpu->pstate.scaling != perf_ctl_scaling) {
++              int scaling = cpu->pstate.scaling;
++              int freq;
++
++              freq = max_policy_perf * perf_ctl_scaling;
++              max_policy_perf = DIV_ROUND_UP(freq, scaling);
++              freq = min_policy_perf * perf_ctl_scaling;
++              min_policy_perf = DIV_ROUND_UP(freq, scaling);
+       }
+       pr_debug("cpu:%d min_policy_perf:%d max_policy_perf:%d\n",
+-- 
+2.43.0
+
diff --git a/queue-5.15/cpufreq-intel_pstate-refine-computation-of-p-state-f.patch b/queue-5.15/cpufreq-intel_pstate-refine-computation-of-p-state-f.patch
new file mode 100644 (file)
index 0000000..fbc53ba
--- /dev/null
@@ -0,0 +1,144 @@
+From 1eeaa96a9ad602510eb2271ad6cb7f9255c8ab7d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jan 2024 15:18:11 +0100
+Subject: cpufreq: intel_pstate: Refine computation of P-state for given
+ frequency
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit 192cdb1c907fd8df2d764c5bb17496e415e59391 ]
+
+On systems using HWP, if a given frequency is equal to the maximum turbo
+frequency or the maximum non-turbo frequency, the HWP performance level
+corresponding to it is already known and can be used directly without
+any computation.
+
+Accordingly, adjust the code to use the known HWP performance levels in
+the cases mentioned above.
+
+This also helps to avoid limiting CPU capacity artificially in some
+cases when the BIOS produces the HWP_CAP numbers using a different
+E-core-to-P-core performance scaling factor than expected by the kernel.
+
+Fixes: f5c8cf2a4992 ("cpufreq: intel_pstate: hybrid: Use known scaling factor for P-cores")
+Cc: 6.1+ <stable@vger.kernel.org> # 6.1+
+Tested-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/intel_pstate.c | 55 +++++++++++++++++++++-------------
+ 1 file changed, 34 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
+index f2a94afb6eec..dd5f4eee9ffb 100644
+--- a/drivers/cpufreq/intel_pstate.c
++++ b/drivers/cpufreq/intel_pstate.c
+@@ -490,6 +490,30 @@ static inline int intel_pstate_get_cppc_guaranteed(int cpu)
+ }
+ #endif /* CONFIG_ACPI_CPPC_LIB */
++static int intel_pstate_freq_to_hwp_rel(struct cpudata *cpu, int freq,
++                                      unsigned int relation)
++{
++      if (freq == cpu->pstate.turbo_freq)
++              return cpu->pstate.turbo_pstate;
++
++      if (freq == cpu->pstate.max_freq)
++              return cpu->pstate.max_pstate;
++
++      switch (relation) {
++      case CPUFREQ_RELATION_H:
++              return freq / cpu->pstate.scaling;
++      case CPUFREQ_RELATION_C:
++              return DIV_ROUND_CLOSEST(freq, cpu->pstate.scaling);
++      }
++
++      return DIV_ROUND_UP(freq, cpu->pstate.scaling);
++}
++
++static int intel_pstate_freq_to_hwp(struct cpudata *cpu, int freq)
++{
++      return intel_pstate_freq_to_hwp_rel(cpu, freq, CPUFREQ_RELATION_L);
++}
++
+ /**
+  * intel_pstate_hybrid_hwp_adjust - Calibrate HWP performance levels.
+  * @cpu: Target CPU.
+@@ -507,6 +531,7 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
+       int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling;
+       int perf_ctl_turbo = pstate_funcs.get_turbo(cpu->cpu);
+       int scaling = cpu->pstate.scaling;
++      int freq;
+       pr_debug("CPU%d: perf_ctl_max_phys = %d\n", cpu->cpu, perf_ctl_max_phys);
+       pr_debug("CPU%d: perf_ctl_turbo = %d\n", cpu->cpu, perf_ctl_turbo);
+@@ -520,16 +545,16 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
+       cpu->pstate.max_freq = rounddown(cpu->pstate.max_pstate * scaling,
+                                        perf_ctl_scaling);
+-      cpu->pstate.max_pstate_physical =
+-                      DIV_ROUND_UP(perf_ctl_max_phys * perf_ctl_scaling,
+-                                   scaling);
++      freq = perf_ctl_max_phys * perf_ctl_scaling;
++      cpu->pstate.max_pstate_physical = intel_pstate_freq_to_hwp(cpu, freq);
+-      cpu->pstate.min_freq = cpu->pstate.min_pstate * perf_ctl_scaling;
++      freq = cpu->pstate.min_pstate * perf_ctl_scaling;
++      cpu->pstate.min_freq = freq;
+       /*
+        * Cast the min P-state value retrieved via pstate_funcs.get_min() to
+        * the effective range of HWP performance levels.
+        */
+-      cpu->pstate.min_pstate = DIV_ROUND_UP(cpu->pstate.min_freq, scaling);
++      cpu->pstate.min_pstate = intel_pstate_freq_to_hwp(cpu, freq);
+ }
+ static inline void update_turbo_state(void)
+@@ -2333,13 +2358,12 @@ static void intel_pstate_update_perf_limits(struct cpudata *cpu,
+        * abstract values to represent performance rather than pure ratios.
+        */
+       if (hwp_active && cpu->pstate.scaling != perf_ctl_scaling) {
+-              int scaling = cpu->pstate.scaling;
+               int freq;
+               freq = max_policy_perf * perf_ctl_scaling;
+-              max_policy_perf = DIV_ROUND_UP(freq, scaling);
++              max_policy_perf = intel_pstate_freq_to_hwp(cpu, freq);
+               freq = min_policy_perf * perf_ctl_scaling;
+-              min_policy_perf = DIV_ROUND_UP(freq, scaling);
++              min_policy_perf = intel_pstate_freq_to_hwp(cpu, freq);
+       }
+       pr_debug("cpu:%d min_policy_perf:%d max_policy_perf:%d\n",
+@@ -2708,18 +2732,7 @@ static int intel_cpufreq_target(struct cpufreq_policy *policy,
+       cpufreq_freq_transition_begin(policy, &freqs);
+-      switch (relation) {
+-      case CPUFREQ_RELATION_L:
+-              target_pstate = DIV_ROUND_UP(freqs.new, cpu->pstate.scaling);
+-              break;
+-      case CPUFREQ_RELATION_H:
+-              target_pstate = freqs.new / cpu->pstate.scaling;
+-              break;
+-      default:
+-              target_pstate = DIV_ROUND_CLOSEST(freqs.new, cpu->pstate.scaling);
+-              break;
+-      }
+-
++      target_pstate = intel_pstate_freq_to_hwp_rel(cpu, freqs.new, relation);
+       target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, false);
+       freqs.new = target_pstate * cpu->pstate.scaling;
+@@ -2737,7 +2750,7 @@ static unsigned int intel_cpufreq_fast_switch(struct cpufreq_policy *policy,
+       update_turbo_state();
+-      target_pstate = DIV_ROUND_UP(target_freq, cpu->pstate.scaling);
++      target_pstate = intel_pstate_freq_to_hwp(cpu, target_freq);
+       target_pstate = intel_cpufreq_update_pstate(policy, target_pstate, true);
+-- 
+2.43.0
+
diff --git a/queue-5.15/fs-pipe-move-check-to-pipe_has_watch_queue.patch b/queue-5.15/fs-pipe-move-check-to-pipe_has_watch_queue.patch
new file mode 100644 (file)
index 0000000..6cb7dfb
--- /dev/null
@@ -0,0 +1,96 @@
+From f96406b56380e050b931160af004c27c740bcaa9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Sep 2023 09:57:53 +0200
+Subject: fs/pipe: move check to pipe_has_watch_queue()
+
+From: Max Kellermann <max.kellermann@ionos.com>
+
+[ Upstream commit b4bd6b4bac8edd61eb8f7b836969d12c0c6af165 ]
+
+This declutters the code by reducing the number of #ifdefs and makes
+the watch_queue checks simpler.  This has no runtime effect; the
+machine code is identical.
+
+Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
+Message-Id: <20230921075755.1378787-2-max.kellermann@ionos.com>
+Reviewed-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Stable-dep-of: e95aada4cb93 ("pipe: wakeup wr_wait after setting max_usage")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/pipe.c                 | 12 +++---------
+ include/linux/pipe_fs_i.h | 16 ++++++++++++++++
+ 2 files changed, 19 insertions(+), 9 deletions(-)
+
+diff --git a/fs/pipe.c b/fs/pipe.c
+index e08f0fe55584..1a43948c0c36 100644
+--- a/fs/pipe.c
++++ b/fs/pipe.c
+@@ -435,12 +435,10 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
+               goto out;
+       }
+-#ifdef CONFIG_WATCH_QUEUE
+-      if (pipe->watch_queue) {
++      if (pipe_has_watch_queue(pipe)) {
+               ret = -EXDEV;
+               goto out;
+       }
+-#endif
+       /*
+        * If it wasn't empty we try to merge new data into
+@@ -1319,10 +1317,8 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
+       unsigned int nr_slots, size;
+       long ret = 0;
+-#ifdef CONFIG_WATCH_QUEUE
+-      if (pipe->watch_queue)
++      if (pipe_has_watch_queue(pipe))
+               return -EBUSY;
+-#endif
+       size = round_pipe_size(arg);
+       nr_slots = size >> PAGE_SHIFT;
+@@ -1374,10 +1370,8 @@ struct pipe_inode_info *get_pipe_info(struct file *file, bool for_splice)
+       if (file->f_op != &pipefifo_fops || !pipe)
+               return NULL;
+-#ifdef CONFIG_WATCH_QUEUE
+-      if (for_splice && pipe->watch_queue)
++      if (for_splice && pipe_has_watch_queue(pipe))
+               return NULL;
+-#endif
+       return pipe;
+ }
+diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
+index d15190b3e032..0613daf8997a 100644
+--- a/include/linux/pipe_fs_i.h
++++ b/include/linux/pipe_fs_i.h
+@@ -124,6 +124,22 @@ struct pipe_buf_operations {
+       bool (*get)(struct pipe_inode_info *, struct pipe_buffer *);
+ };
++/**
++ * pipe_has_watch_queue - Check whether the pipe is a watch_queue,
++ * i.e. it was created with O_NOTIFICATION_PIPE
++ * @pipe: The pipe to check
++ *
++ * Return: true if pipe is a watch queue, false otherwise.
++ */
++static inline bool pipe_has_watch_queue(const struct pipe_inode_info *pipe)
++{
++#ifdef CONFIG_WATCH_QUEUE
++      return pipe->watch_queue != NULL;
++#else
++      return false;
++#endif
++}
++
+ /**
+  * pipe_empty - Return true if the pipe is empty
+  * @head: The pipe ring head pointer
+-- 
+2.43.0
+
diff --git a/queue-5.15/ksmbd-fix-global-oob-in-ksmbd_nl_policy.patch b/queue-5.15/ksmbd-fix-global-oob-in-ksmbd_nl_policy.patch
new file mode 100644 (file)
index 0000000..f878d34
--- /dev/null
@@ -0,0 +1,133 @@
+From 4e84346099553d37dc99bd557b1d26292cd0e0d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 21 Jan 2024 15:35:06 +0800
+Subject: ksmbd: fix global oob in ksmbd_nl_policy
+
+From: Lin Ma <linma@zju.edu.cn>
+
+[ Upstream commit ebeae8adf89d9a82359f6659b1663d09beec2faa ]
+
+Similar to a reported issue (check the commit b33fb5b801c6 ("net:
+qualcomm: rmnet: fix global oob in rmnet_policy"), my local fuzzer finds
+another global out-of-bounds read for policy ksmbd_nl_policy. See bug
+trace below:
+
+==================================================================
+BUG: KASAN: global-out-of-bounds in validate_nla lib/nlattr.c:386 [inline]
+BUG: KASAN: global-out-of-bounds in __nla_validate_parse+0x24af/0x2750 lib/nlattr.c:600
+Read of size 1 at addr ffffffff8f24b100 by task syz-executor.1/62810
+
+CPU: 0 PID: 62810 Comm: syz-executor.1 Tainted: G                 N 6.1.0 #3
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:88 [inline]
+ dump_stack_lvl+0x8b/0xb3 lib/dump_stack.c:106
+ print_address_description mm/kasan/report.c:284 [inline]
+ print_report+0x172/0x475 mm/kasan/report.c:395
+ kasan_report+0xbb/0x1c0 mm/kasan/report.c:495
+ validate_nla lib/nlattr.c:386 [inline]
+ __nla_validate_parse+0x24af/0x2750 lib/nlattr.c:600
+ __nla_parse+0x3e/0x50 lib/nlattr.c:697
+ __nlmsg_parse include/net/netlink.h:748 [inline]
+ genl_family_rcv_msg_attrs_parse.constprop.0+0x1b0/0x290 net/netlink/genetlink.c:565
+ genl_family_rcv_msg_doit+0xda/0x330 net/netlink/genetlink.c:734
+ genl_family_rcv_msg net/netlink/genetlink.c:833 [inline]
+ genl_rcv_msg+0x441/0x780 net/netlink/genetlink.c:850
+ netlink_rcv_skb+0x14f/0x410 net/netlink/af_netlink.c:2540
+ genl_rcv+0x24/0x40 net/netlink/genetlink.c:861
+ netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline]
+ netlink_unicast+0x54e/0x800 net/netlink/af_netlink.c:1345
+ netlink_sendmsg+0x930/0xe50 net/netlink/af_netlink.c:1921
+ sock_sendmsg_nosec net/socket.c:714 [inline]
+ sock_sendmsg+0x154/0x190 net/socket.c:734
+ ____sys_sendmsg+0x6df/0x840 net/socket.c:2482
+ ___sys_sendmsg+0x110/0x1b0 net/socket.c:2536
+ __sys_sendmsg+0xf3/0x1c0 net/socket.c:2565
+ do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+ do_syscall_64+0x3b/0x90 arch/x86/entry/common.c:80
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+RIP: 0033:0x7fdd66a8f359
+Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 f1 19 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007fdd65e00168 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+RAX: ffffffffffffffda RBX: 00007fdd66bbcf80 RCX: 00007fdd66a8f359
+RDX: 0000000000000000 RSI: 0000000020000500 RDI: 0000000000000003
+RBP: 00007fdd66ada493 R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+R13: 00007ffc84b81aff R14: 00007fdd65e00300 R15: 0000000000022000
+ </TASK>
+
+The buggy address belongs to the variable:
+ ksmbd_nl_policy+0x100/0xa80
+
+The buggy address belongs to the physical page:
+page:0000000034f47940 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x1ccc4b
+flags: 0x200000000001000(reserved|node=0|zone=2)
+raw: 0200000000001000 ffffea00073312c8 ffffea00073312c8 0000000000000000
+raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
+page dumped because: kasan: bad access detected
+
+Memory state around the buggy address:
+ ffffffff8f24b000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ ffffffff8f24b080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+>ffffffff8f24b100: f9 f9 f9 f9 00 00 f9 f9 f9 f9 f9 f9 00 00 07 f9
+                   ^
+ ffffffff8f24b180: f9 f9 f9 f9 00 05 f9 f9 f9 f9 f9 f9 00 00 00 05
+ ffffffff8f24b200: f9 f9 f9 f9 00 00 03 f9 f9 f9 f9 f9 00 00 04 f9
+==================================================================
+
+To fix it, add a placeholder named __KSMBD_EVENT_MAX and let
+KSMBD_EVENT_MAX to be its original value - 1 according to what other
+netlink families do. Also change two sites that refer the
+KSMBD_EVENT_MAX to correct value.
+
+Cc: stable@vger.kernel.org
+Fixes: 0626e6641f6b ("cifsd: add server handler for central processing and tranport layers")
+Signed-off-by: Lin Ma <linma@zju.edu.cn>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ksmbd/ksmbd_netlink.h | 3 ++-
+ fs/ksmbd/transport_ipc.c | 4 ++--
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/fs/ksmbd/ksmbd_netlink.h b/fs/ksmbd/ksmbd_netlink.h
+index 821ed8e3cbee..ecffcb8a1557 100644
+--- a/fs/ksmbd/ksmbd_netlink.h
++++ b/fs/ksmbd/ksmbd_netlink.h
+@@ -304,7 +304,8 @@ enum ksmbd_event {
+       KSMBD_EVENT_SPNEGO_AUTHEN_REQUEST,
+       KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE      = 15,
+-      KSMBD_EVENT_MAX
++      __KSMBD_EVENT_MAX,
++      KSMBD_EVENT_MAX = __KSMBD_EVENT_MAX - 1
+ };
+ /*
+diff --git a/fs/ksmbd/transport_ipc.c b/fs/ksmbd/transport_ipc.c
+index 9560c704033e..2c9662e32799 100644
+--- a/fs/ksmbd/transport_ipc.c
++++ b/fs/ksmbd/transport_ipc.c
+@@ -74,7 +74,7 @@ static int handle_unsupported_event(struct sk_buff *skb, struct genl_info *info)
+ static int handle_generic_event(struct sk_buff *skb, struct genl_info *info);
+ static int ksmbd_ipc_heartbeat_request(void);
+-static const struct nla_policy ksmbd_nl_policy[KSMBD_EVENT_MAX] = {
++static const struct nla_policy ksmbd_nl_policy[KSMBD_EVENT_MAX + 1] = {
+       [KSMBD_EVENT_UNSPEC] = {
+               .len = 0,
+       },
+@@ -402,7 +402,7 @@ static int handle_generic_event(struct sk_buff *skb, struct genl_info *info)
+               return -EPERM;
+ #endif
+-      if (type >= KSMBD_EVENT_MAX) {
++      if (type > KSMBD_EVENT_MAX) {
+               WARN_ON(1);
+               return -EINVAL;
+       }
+-- 
+2.43.0
+
diff --git a/queue-5.15/media-mtk-jpeg-fix-use-after-free-bug-due-to-error-p.patch b/queue-5.15/media-mtk-jpeg-fix-use-after-free-bug-due-to-error-p.patch
new file mode 100644 (file)
index 0000000..e94e260
--- /dev/null
@@ -0,0 +1,75 @@
+From 67cfccae23323c9254f098a15decfd5c9012e929 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Nov 2023 15:48:10 +0100
+Subject: media: mtk-jpeg: Fix use after free bug due to error path handling in
+ mtk_jpeg_dec_device_run
+
+From: Zheng Wang <zyytlz.wz@163.com>
+
+[ Upstream commit 206c857dd17d4d026de85866f1b5f0969f2a109e ]
+
+In mtk_jpeg_probe, &jpeg->job_timeout_work is bound with
+mtk_jpeg_job_timeout_work.
+
+In mtk_jpeg_dec_device_run, if error happens in
+mtk_jpeg_set_dec_dst, it will finally start the worker while
+mark the job as finished by invoking v4l2_m2m_job_finish.
+
+There are two methods to trigger the bug. If we remove the
+module, it which will call mtk_jpeg_remove to make cleanup.
+The possible sequence is as follows, which will cause a
+use-after-free bug.
+
+CPU0                  CPU1
+mtk_jpeg_dec_...    |
+  start worker     |
+                    |mtk_jpeg_job_timeout_work
+mtk_jpeg_remove     |
+  v4l2_m2m_release  |
+    kfree(m2m_dev); |
+                    |
+                    | v4l2_m2m_get_curr_priv
+                    |   m2m_dev->curr_ctx //use
+
+If we close the file descriptor, which will call mtk_jpeg_release,
+it will have a similar sequence.
+
+Fix this bug by starting timeout worker only if started jpegdec worker
+successfully. Then v4l2_m2m_job_finish will only be called in
+either mtk_jpeg_job_timeout_work or mtk_jpeg_dec_device_run.
+
+Fixes: b2f0d2724ba4 ("[media] vcodec: mediatek: Add Mediatek JPEG Decoder Driver")
+Signed-off-by: Zheng Wang <zyytlz.wz@163.com>
+Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+index bc84274ba87a..ba490b06ff70 100644
+--- a/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
++++ b/drivers/media/platform/mtk-jpeg/mtk_jpeg_core.c
+@@ -977,13 +977,13 @@ static void mtk_jpeg_dec_device_run(void *priv)
+       if (ret < 0)
+               goto dec_end;
+-      schedule_delayed_work(&jpeg->job_timeout_work,
+-                            msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
+-
+       mtk_jpeg_set_dec_src(ctx, &src_buf->vb2_buf, &bs);
+       if (mtk_jpeg_set_dec_dst(ctx, &jpeg_src_buf->dec_param, &dst_buf->vb2_buf, &fb))
+               goto dec_end;
++      schedule_delayed_work(&jpeg->job_timeout_work,
++                            msecs_to_jiffies(MTK_JPEG_HW_TIMEOUT_MSEC));
++
+       spin_lock_irqsave(&jpeg->hw_lock, flags);
+       mtk_jpeg_dec_reset(jpeg->reg_base);
+       mtk_jpeg_dec_set_config(jpeg->reg_base,
+-- 
+2.43.0
+
diff --git a/queue-5.15/mm-sparsemem-fix-race-in-accessing-memory_section-us.patch b/queue-5.15/mm-sparsemem-fix-race-in-accessing-memory_section-us.patch
new file mode 100644 (file)
index 0000000..feecd81
--- /dev/null
@@ -0,0 +1,213 @@
+From 251410828c1f87e2c887ef1a1337183170a2b484 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Oct 2023 18:34:27 +0530
+Subject: mm/sparsemem: fix race in accessing memory_section->usage
+
+From: Charan Teja Kalla <quic_charante@quicinc.com>
+
+[ Upstream commit 5ec8e8ea8b7783fab150cf86404fc38cb4db8800 ]
+
+The below race is observed on a PFN which falls into the device memory
+region with the system memory configuration where PFN's are such that
+[ZONE_NORMAL ZONE_DEVICE ZONE_NORMAL].  Since normal zone start and end
+pfn contains the device memory PFN's as well, the compaction triggered
+will try on the device memory PFN's too though they end up in NOP(because
+pfn_to_online_page() returns NULL for ZONE_DEVICE memory sections).  When
+from other core, the section mappings are being removed for the
+ZONE_DEVICE region, that the PFN in question belongs to, on which
+compaction is currently being operated is resulting into the kernel crash
+with CONFIG_SPASEMEM_VMEMAP enabled.  The crash logs can be seen at [1].
+
+compact_zone()                 memunmap_pages
+-------------                  ---------------
+__pageblock_pfn_to_page
+   ......
+ (a)pfn_valid():
+     valid_section()//return true
+                             (b)__remove_pages()->
+                                 sparse_remove_section()->
+                                   section_deactivate():
+                                   [Free the array ms->usage and set
+                                    ms->usage = NULL]
+     pfn_section_valid()
+     [Access ms->usage which
+     is NULL]
+
+NOTE: From the above it can be said that the race is reduced to between
+the pfn_valid()/pfn_section_valid() and the section deactivate with
+SPASEMEM_VMEMAP enabled.
+
+The commit b943f045a9af("mm/sparse: fix kernel crash with
+pfn_section_valid check") tried to address the same problem by clearing
+the SECTION_HAS_MEM_MAP with the expectation of valid_section() returns
+false thus ms->usage is not accessed.
+
+Fix this issue by the below steps:
+
+a) Clear SECTION_HAS_MEM_MAP before freeing the ->usage.
+
+b) RCU protected read side critical section will either return NULL
+   when SECTION_HAS_MEM_MAP is cleared or can successfully access ->usage.
+
+c) Free the ->usage with kfree_rcu() and set ms->usage = NULL.  No
+   attempt will be made to access ->usage after this as the
+   SECTION_HAS_MEM_MAP is cleared thus valid_section() return false.
+
+Thanks to David/Pavan for their inputs on this patch.
+
+[1] https://lore.kernel.org/linux-mm/994410bb-89aa-d987-1f50-f514903c55aa@quicinc.com/
+
+On Snapdragon SoC, with the mentioned memory configuration of PFN's as
+[ZONE_NORMAL ZONE_DEVICE ZONE_NORMAL], we are able to see bunch of
+issues daily while testing on a device farm.
+
+For this particular issue below is the log.  Though the below log is
+not directly pointing to the pfn_section_valid(){ ms->usage;}, when we
+loaded this dump on T32 lauterbach tool, it is pointing.
+
+[  540.578056] Unable to handle kernel NULL pointer dereference at
+virtual address 0000000000000000
+[  540.578068] Mem abort info:
+[  540.578070]   ESR = 0x0000000096000005
+[  540.578073]   EC = 0x25: DABT (current EL), IL = 32 bits
+[  540.578077]   SET = 0, FnV = 0
+[  540.578080]   EA = 0, S1PTW = 0
+[  540.578082]   FSC = 0x05: level 1 translation fault
+[  540.578085] Data abort info:
+[  540.578086]   ISV = 0, ISS = 0x00000005
+[  540.578088]   CM = 0, WnR = 0
+[  540.579431] pstate: 82400005 (Nzcv daif +PAN -UAO +TCO -DIT -SSBSBTYPE=--)
+[  540.579436] pc : __pageblock_pfn_to_page+0x6c/0x14c
+[  540.579454] lr : compact_zone+0x994/0x1058
+[  540.579460] sp : ffffffc03579b510
+[  540.579463] x29: ffffffc03579b510 x28: 0000000000235800 x27:000000000000000c
+[  540.579470] x26: 0000000000235c00 x25: 0000000000000068 x24:ffffffc03579b640
+[  540.579477] x23: 0000000000000001 x22: ffffffc03579b660 x21:0000000000000000
+[  540.579483] x20: 0000000000235bff x19: ffffffdebf7e3940 x18:ffffffdebf66d140
+[  540.579489] x17: 00000000739ba063 x16: 00000000739ba063 x15:00000000009f4bff
+[  540.579495] x14: 0000008000000000 x13: 0000000000000000 x12:0000000000000001
+[  540.579501] x11: 0000000000000000 x10: 0000000000000000 x9 :ffffff897d2cd440
+[  540.579507] x8 : 0000000000000000 x7 : 0000000000000000 x6 :ffffffc03579b5b4
+[  540.579512] x5 : 0000000000027f25 x4 : ffffffc03579b5b8 x3 :0000000000000001
+[  540.579518] x2 : ffffffdebf7e3940 x1 : 0000000000235c00 x0 :0000000000235800
+[  540.579524] Call trace:
+[  540.579527]  __pageblock_pfn_to_page+0x6c/0x14c
+[  540.579533]  compact_zone+0x994/0x1058
+[  540.579536]  try_to_compact_pages+0x128/0x378
+[  540.579540]  __alloc_pages_direct_compact+0x80/0x2b0
+[  540.579544]  __alloc_pages_slowpath+0x5c0/0xe10
+[  540.579547]  __alloc_pages+0x250/0x2d0
+[  540.579550]  __iommu_dma_alloc_noncontiguous+0x13c/0x3fc
+[  540.579561]  iommu_dma_alloc+0xa0/0x320
+[  540.579565]  dma_alloc_attrs+0xd4/0x108
+
+[quic_charante@quicinc.com: use kfree_rcu() in place of synchronize_rcu(), per David]
+  Link: https://lkml.kernel.org/r/1698403778-20938-1-git-send-email-quic_charante@quicinc.com
+Link: https://lkml.kernel.org/r/1697202267-23600-1-git-send-email-quic_charante@quicinc.com
+Fixes: f46edbd1b151 ("mm/sparsemem: add helpers track active portions of a section at boot")
+Signed-off-by: Charan Teja Kalla <quic_charante@quicinc.com>
+Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
+Cc: Dan Williams <dan.j.williams@intel.com>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Mel Gorman <mgorman@techsingularity.net>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/mmzone.h | 14 +++++++++++---
+ mm/sparse.c            | 17 +++++++++--------
+ 2 files changed, 20 insertions(+), 11 deletions(-)
+
+diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
+index 9e1485083398..8b8349ffa1cd 100644
+--- a/include/linux/mmzone.h
++++ b/include/linux/mmzone.h
+@@ -1287,6 +1287,7 @@ static inline unsigned long section_nr_to_pfn(unsigned long sec)
+ #define SUBSECTION_ALIGN_DOWN(pfn) ((pfn) & PAGE_SUBSECTION_MASK)
+ struct mem_section_usage {
++      struct rcu_head rcu;
+ #ifdef CONFIG_SPARSEMEM_VMEMMAP
+       DECLARE_BITMAP(subsection_map, SUBSECTIONS_PER_SECTION);
+ #endif
+@@ -1457,7 +1458,7 @@ static inline int pfn_section_valid(struct mem_section *ms, unsigned long pfn)
+ {
+       int idx = subsection_map_index(pfn);
+-      return test_bit(idx, ms->usage->subsection_map);
++      return test_bit(idx, READ_ONCE(ms->usage)->subsection_map);
+ }
+ #else
+ static inline int pfn_section_valid(struct mem_section *ms, unsigned long pfn)
+@@ -1481,6 +1482,7 @@ static inline int pfn_section_valid(struct mem_section *ms, unsigned long pfn)
+ static inline int pfn_valid(unsigned long pfn)
+ {
+       struct mem_section *ms;
++      int ret;
+       /*
+        * Ensure the upper PAGE_SHIFT bits are clear in the
+@@ -1494,13 +1496,19 @@ static inline int pfn_valid(unsigned long pfn)
+       if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
+               return 0;
+       ms = __pfn_to_section(pfn);
+-      if (!valid_section(ms))
++      rcu_read_lock();
++      if (!valid_section(ms)) {
++              rcu_read_unlock();
+               return 0;
++      }
+       /*
+        * Traditionally early sections always returned pfn_valid() for
+        * the entire section-sized span.
+        */
+-      return early_section(ms) || pfn_section_valid(ms, pfn);
++      ret = early_section(ms) || pfn_section_valid(ms, pfn);
++      rcu_read_unlock();
++
++      return ret;
+ }
+ #endif
+diff --git a/mm/sparse.c b/mm/sparse.c
+index 120bc8ea5293..27092badd15b 100644
+--- a/mm/sparse.c
++++ b/mm/sparse.c
+@@ -789,6 +789,13 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages,
+       if (empty) {
+               unsigned long section_nr = pfn_to_section_nr(pfn);
++              /*
++               * Mark the section invalid so that valid_section()
++               * return false. This prevents code from dereferencing
++               * ms->usage array.
++               */
++              ms->section_mem_map &= ~SECTION_HAS_MEM_MAP;
++
+               /*
+                * When removing an early section, the usage map is kept (as the
+                * usage maps of other sections fall into the same page). It
+@@ -797,16 +804,10 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages,
+                * was allocated during boot.
+                */
+               if (!PageReserved(virt_to_page(ms->usage))) {
+-                      kfree(ms->usage);
+-                      ms->usage = NULL;
++                      kfree_rcu(ms->usage, rcu);
++                      WRITE_ONCE(ms->usage, NULL);
+               }
+               memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr);
+-              /*
+-               * Mark the section invalid so that valid_section()
+-               * return false. This prevents code from dereferencing
+-               * ms->usage array.
+-               */
+-              ms->section_mem_map &= ~SECTION_HAS_MEM_MAP;
+       }
+       /*
+-- 
+2.43.0
+
diff --git a/queue-5.15/mm-use-__pfn_to_section-instead-of-open-coding-it.patch b/queue-5.15/mm-use-__pfn_to_section-instead-of-open-coding-it.patch
new file mode 100644 (file)
index 0000000..9d9b056
--- /dev/null
@@ -0,0 +1,47 @@
+From dfd6261dddcc299b40b8d5cbe3e7023f2e295cee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Nov 2021 13:38:15 -0700
+Subject: mm: use __pfn_to_section() instead of open coding it
+
+From: Rolf Eike Beer <eb@emlix.com>
+
+[ Upstream commit f1dc0db296bd25960273649fc6ef2ecbf5aaa0e0 ]
+
+It is defined in the same file just a few lines above.
+
+Link: https://lkml.kernel.org/r/4598487.Rc0NezkW7i@mobilepool36.emlix.com
+Signed-off-by: Rolf Eike Beer <eb@emlix.com>
+Reviewed-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Stable-dep-of: 5ec8e8ea8b77 ("mm/sparsemem: fix race in accessing memory_section->usage")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/mmzone.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
+index 6ba100216530..9e1485083398 100644
+--- a/include/linux/mmzone.h
++++ b/include/linux/mmzone.h
+@@ -1493,7 +1493,7 @@ static inline int pfn_valid(unsigned long pfn)
+       if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
+               return 0;
+-      ms = __nr_to_section(pfn_to_section_nr(pfn));
++      ms = __pfn_to_section(pfn);
+       if (!valid_section(ms))
+               return 0;
+       /*
+@@ -1508,7 +1508,7 @@ static inline int pfn_in_present_section(unsigned long pfn)
+ {
+       if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
+               return 0;
+-      return present_section(__nr_to_section(pfn_to_section_nr(pfn)));
++      return present_section(__pfn_to_section(pfn));
+ }
+ static inline unsigned long next_present_section_nr(unsigned long section_nr)
+-- 
+2.43.0
+
diff --git a/queue-5.15/nfsd-add-documenting-comment-for-nfsd4_release_locko.patch b/queue-5.15/nfsd-add-documenting-comment-for-nfsd4_release_locko.patch
new file mode 100644 (file)
index 0000000..ad2737c
--- /dev/null
@@ -0,0 +1,73 @@
+From bfc7f89d24d6164689aed7061a97879ef05fd861 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 May 2022 12:34:38 -0400
+Subject: NFSD: Add documenting comment for nfsd4_release_lockowner()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 043862b09cc00273e35e6c3a6389957953a34207 ]
+
+And return explicit nfserr values that match what is documented in the
+new comment / API contract.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Stable-dep-of: edcf9725150e ("nfsd: fix RELEASE_LOCKOWNER")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/nfs4state.c | 23 ++++++++++++++++++++---
+ 1 file changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 798063b9b96f..f8533299db1c 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -7284,6 +7284,23 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
+       return status;
+ }
++/**
++ * nfsd4_release_lockowner - process NFSv4.0 RELEASE_LOCKOWNER operations
++ * @rqstp: RPC transaction
++ * @cstate: NFSv4 COMPOUND state
++ * @u: RELEASE_LOCKOWNER arguments
++ *
++ * The lockowner's so_count is bumped when a lock record is added
++ * or when copying a conflicting lock. The latter case is brief,
++ * but can lead to fleeting false positives when looking for
++ * locks-in-use.
++ *
++ * Return values:
++ *   %nfs_ok: lockowner released or not found
++ *   %nfserr_locks_held: lockowner still in use
++ *   %nfserr_stale_clientid: clientid no longer active
++ *   %nfserr_expired: clientid not recognized
++ */
+ __be32
+ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+                       struct nfsd4_compound_state *cstate,
+@@ -7310,7 +7327,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+       lo = find_lockowner_str_locked(clp, &rlockowner->rl_owner);
+       if (!lo) {
+               spin_unlock(&clp->cl_lock);
+-              return status;
++              return nfs_ok;
+       }
+       if (atomic_read(&lo->lo_owner.so_count) != 2) {
+               spin_unlock(&clp->cl_lock);
+@@ -7326,11 +7343,11 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+               put_ol_stateid_locked(stp, &reaplist);
+       }
+       spin_unlock(&clp->cl_lock);
++
+       free_ol_stateid_reaplist(&reaplist);
+       remove_blocked_locks(lo);
+       nfs4_put_stateowner(&lo->lo_owner);
+-
+-      return status;
++      return nfs_ok;
+ }
+ static inline struct nfs4_client_reclaim *
+-- 
+2.43.0
+
diff --git a/queue-5.15/nfsd-fix-release_lockowner.patch b/queue-5.15/nfsd-fix-release_lockowner.patch
new file mode 100644 (file)
index 0000000..6938f30
--- /dev/null
@@ -0,0 +1,149 @@
+From b99447c0e88afdb26e8907c0904190f6064f4f1b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jan 2024 14:58:16 +1100
+Subject: nfsd: fix RELEASE_LOCKOWNER
+
+From: NeilBrown <neilb@suse.de>
+
+[ Upstream commit edcf9725150e42beeca42d085149f4c88fa97afd ]
+
+The test on so_count in nfsd4_release_lockowner() is nonsense and
+harmful.  Revert to using check_for_locks(), changing that to not sleep.
+
+First: harmful.
+As is documented in the kdoc comment for nfsd4_release_lockowner(), the
+test on so_count can transiently return a false positive resulting in a
+return of NFS4ERR_LOCKS_HELD when in fact no locks are held.  This is
+clearly a protocol violation and with the Linux NFS client it can cause
+incorrect behaviour.
+
+If RELEASE_LOCKOWNER is sent while some other thread is still
+processing a LOCK request which failed because, at the time that request
+was received, the given owner held a conflicting lock, then the nfsd
+thread processing that LOCK request can hold a reference (conflock) to
+the lock owner that causes nfsd4_release_lockowner() to return an
+incorrect error.
+
+The Linux NFS client ignores that NFS4ERR_LOCKS_HELD error because it
+never sends NFS4_RELEASE_LOCKOWNER without first releasing any locks, so
+it knows that the error is impossible.  It assumes the lock owner was in
+fact released so it feels free to use the same lock owner identifier in
+some later locking request.
+
+When it does reuse a lock owner identifier for which a previous RELEASE
+failed, it will naturally use a lock_seqid of zero.  However the server,
+which didn't release the lock owner, will expect a larger lock_seqid and
+so will respond with NFS4ERR_BAD_SEQID.
+
+So clearly it is harmful to allow a false positive, which testing
+so_count allows.
+
+The test is nonsense because ... well... it doesn't mean anything.
+
+so_count is the sum of three different counts.
+1/ the set of states listed on so_stateids
+2/ the set of active vfs locks owned by any of those states
+3/ various transient counts such as for conflicting locks.
+
+When it is tested against '2' it is clear that one of these is the
+transient reference obtained by find_lockowner_str_locked().  It is not
+clear what the other one is expected to be.
+
+In practice, the count is often 2 because there is precisely one state
+on so_stateids.  If there were more, this would fail.
+
+In my testing I see two circumstances when RELEASE_LOCKOWNER is called.
+In one case, CLOSE is called before RELEASE_LOCKOWNER.  That results in
+all the lock states being removed, and so the lockowner being discarded
+(it is removed when there are no more references which usually happens
+when the lock state is discarded).  When nfsd4_release_lockowner() finds
+that the lock owner doesn't exist, it returns success.
+
+The other case shows an so_count of '2' and precisely one state listed
+in so_stateid.  It appears that the Linux client uses a separate lock
+owner for each file resulting in one lock state per lock owner, so this
+test on '2' is safe.  For another client it might not be safe.
+
+So this patch changes check_for_locks() to use the (newish)
+find_any_file_locked() so that it doesn't take a reference on the
+nfs4_file and so never calls nfsd_file_put(), and so never sleeps.  With
+this check is it safe to restore the use of check_for_locks() rather
+than testing so_count against the mysterious '2'.
+
+Fixes: ce3c4ad7f4ce ("NFSD: Fix possible sleep during nfsd4_release_lockowner()")
+Signed-off-by: NeilBrown <neilb@suse.de>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Cc: stable@vger.kernel.org # v6.2+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/nfs4state.c | 26 +++++++++++++++-----------
+ 1 file changed, 15 insertions(+), 11 deletions(-)
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index f8533299db1c..07ea35803629 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -7257,14 +7257,16 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
+ {
+       struct file_lock *fl;
+       int status = false;
+-      struct nfsd_file *nf = find_any_file(fp);
++      struct nfsd_file *nf;
+       struct inode *inode;
+       struct file_lock_context *flctx;
++      spin_lock(&fp->fi_lock);
++      nf = find_any_file_locked(fp);
+       if (!nf) {
+               /* Any valid lock stateid should have some sort of access */
+               WARN_ON_ONCE(1);
+-              return status;
++              goto out;
+       }
+       inode = locks_inode(nf->nf_file);
+@@ -7280,7 +7282,8 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
+               }
+               spin_unlock(&flctx->flc_lock);
+       }
+-      nfsd_file_put(nf);
++out:
++      spin_unlock(&fp->fi_lock);
+       return status;
+ }
+@@ -7290,10 +7293,8 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
+  * @cstate: NFSv4 COMPOUND state
+  * @u: RELEASE_LOCKOWNER arguments
+  *
+- * The lockowner's so_count is bumped when a lock record is added
+- * or when copying a conflicting lock. The latter case is brief,
+- * but can lead to fleeting false positives when looking for
+- * locks-in-use.
++ * Check if theree are any locks still held and if not - free the lockowner
++ * and any lock state that is owned.
+  *
+  * Return values:
+  *   %nfs_ok: lockowner released or not found
+@@ -7329,10 +7330,13 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+               spin_unlock(&clp->cl_lock);
+               return nfs_ok;
+       }
+-      if (atomic_read(&lo->lo_owner.so_count) != 2) {
+-              spin_unlock(&clp->cl_lock);
+-              nfs4_put_stateowner(&lo->lo_owner);
+-              return nfserr_locks_held;
++
++      list_for_each_entry(stp, &lo->lo_owner.so_stateids, st_perstateowner) {
++              if (check_for_locks(stp->st_stid.sc_file, lo)) {
++                      spin_unlock(&clp->cl_lock);
++                      nfs4_put_stateowner(&lo->lo_owner);
++                      return nfserr_locks_held;
++              }
+       }
+       unhash_lockowner_locked(lo);
+       while (!list_empty(&lo->lo_owner.so_stateids)) {
+-- 
+2.43.0
+
diff --git a/queue-5.15/nfsd-modernize-nfsd4_release_lockowner.patch b/queue-5.15/nfsd-modernize-nfsd4_release_lockowner.patch
new file mode 100644 (file)
index 0000000..5c1ac7d
--- /dev/null
@@ -0,0 +1,86 @@
+From 05aaa4892314880beb9474adeb0dd95d3b8086ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 May 2022 12:07:18 -0400
+Subject: NFSD: Modernize nfsd4_release_lockowner()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit bd8fdb6e545f950f4654a9a10d7e819ad48146e5 ]
+
+Refactor: Use existing helpers that other lock operations use. This
+change removes several automatic variables, so re-organize the
+variable declarations for readability.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Stable-dep-of: edcf9725150e ("nfsd: fix RELEASE_LOCKOWNER")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/nfs4state.c | 36 +++++++++++-------------------------
+ 1 file changed, 11 insertions(+), 25 deletions(-)
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 9b660491f393..798063b9b96f 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -7290,16 +7290,13 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+                       union nfsd4_op_u *u)
+ {
+       struct nfsd4_release_lockowner *rlockowner = &u->release_lockowner;
++      struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+       clientid_t *clid = &rlockowner->rl_clientid;
+-      struct nfs4_stateowner *sop;
+-      struct nfs4_lockowner *lo = NULL;
+       struct nfs4_ol_stateid *stp;
+-      struct xdr_netobj *owner = &rlockowner->rl_owner;
+-      unsigned int hashval = ownerstr_hashval(owner);
+-      __be32 status;
+-      struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
++      struct nfs4_lockowner *lo;
+       struct nfs4_client *clp;
+-      LIST_HEAD (reaplist);
++      LIST_HEAD(reaplist);
++      __be32 status;
+       dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
+               clid->cl_boot, clid->cl_id);
+@@ -7307,30 +7304,19 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+       status = set_client(clid, cstate, nn);
+       if (status)
+               return status;
+-
+       clp = cstate->clp;
+-      /* Find the matching lock stateowner */
+-      spin_lock(&clp->cl_lock);
+-      list_for_each_entry(sop, &clp->cl_ownerstr_hashtbl[hashval],
+-                          so_strhash) {
+-              if (sop->so_is_open_owner || !same_owner_str(sop, owner))
+-                      continue;
+-
+-              if (atomic_read(&sop->so_count) != 1) {
+-                      spin_unlock(&clp->cl_lock);
+-                      return nfserr_locks_held;
+-              }
+-
+-              lo = lockowner(sop);
+-              nfs4_get_stateowner(sop);
+-              break;
+-      }
++      spin_lock(&clp->cl_lock);
++      lo = find_lockowner_str_locked(clp, &rlockowner->rl_owner);
+       if (!lo) {
+               spin_unlock(&clp->cl_lock);
+               return status;
+       }
+-
++      if (atomic_read(&lo->lo_owner.so_count) != 2) {
++              spin_unlock(&clp->cl_lock);
++              nfs4_put_stateowner(&lo->lo_owner);
++              return nfserr_locks_held;
++      }
+       unhash_lockowner_locked(lo);
+       while (!list_empty(&lo->lo_owner.so_stateids)) {
+               stp = list_first_entry(&lo->lo_owner.so_stateids,
+-- 
+2.43.0
+
diff --git a/queue-5.15/pipe-wakeup-wr_wait-after-setting-max_usage.patch b/queue-5.15/pipe-wakeup-wr_wait-after-setting-max_usage.patch
new file mode 100644 (file)
index 0000000..fddd518
--- /dev/null
@@ -0,0 +1,62 @@
+From 5b7b64f163aaa80fab411ec73cbb0e94e184e90b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Dec 2023 11:11:28 +0100
+Subject: pipe: wakeup wr_wait after setting max_usage
+
+From: Lukas Schauer <lukas@schauer.dev>
+
+[ Upstream commit e95aada4cb93d42e25c30a0ef9eb2923d9711d4a ]
+
+Commit c73be61cede5 ("pipe: Add general notification queue support") a
+regression was introduced that would lock up resized pipes under certain
+conditions. See the reproducer in [1].
+
+The commit resizing the pipe ring size was moved to a different
+function, doing that moved the wakeup for pipe->wr_wait before actually
+raising pipe->max_usage. If a pipe was full before the resize occured it
+would result in the wakeup never actually triggering pipe_write.
+
+Set @max_usage and @nr_accounted before waking writers if this isn't a
+watch queue.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=212295 [1]
+Link: https://lore.kernel.org/r/20231201-orchideen-modewelt-e009de4562c6@brauner
+Fixes: c73be61cede5 ("pipe: Add general notification queue support")
+Reviewed-by: David Howells <dhowells@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Lukas Schauer <lukas@schauer.dev>
+[Christian Brauner <brauner@kernel.org>: rewrite to account for watch queues]
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/pipe.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/fs/pipe.c b/fs/pipe.c
+index 1a43948c0c36..a8b8ef2dae7b 100644
+--- a/fs/pipe.c
++++ b/fs/pipe.c
+@@ -1300,6 +1300,11 @@ int pipe_resize_ring(struct pipe_inode_info *pipe, unsigned int nr_slots)
+       pipe->tail = tail;
+       pipe->head = head;
++      if (!pipe_has_watch_queue(pipe)) {
++              pipe->max_usage = nr_slots;
++              pipe->nr_accounted = nr_slots;
++      }
++
+       spin_unlock_irq(&pipe->rd_wait.lock);
+       /* This might have made more room for writers */
+@@ -1351,8 +1356,6 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
+       if (ret < 0)
+               goto out_revert_acct;
+-      pipe->max_usage = nr_slots;
+-      pipe->nr_accounted = nr_slots;
+       return pipe->max_usage * PAGE_SIZE;
+ out_revert_acct:
+-- 
+2.43.0
+
diff --git a/queue-5.15/pm-core-remove-unnecessary-void-conversions.patch b/queue-5.15/pm-core-remove-unnecessary-void-conversions.patch
new file mode 100644 (file)
index 0000000..3321308
--- /dev/null
@@ -0,0 +1,83 @@
+From bf88a10594f21c21887f67a3a71aec20d58c99ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 26 Mar 2023 06:19:35 +0800
+Subject: PM: core: Remove unnecessary (void *) conversions
+
+From: Li zeming <zeming@nfschina.com>
+
+[ Upstream commit 73d73f5ee7fb0c42ff87091d105bee720a9565f1 ]
+
+Assignments from pointer variables of type (void *) do not require
+explicit type casts, so remove such type cases from the code in
+drivers/base/power/main.c where applicable.
+
+Signed-off-by: Li zeming <zeming@nfschina.com>
+[ rjw: Subject and changelog edits ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: 7839d0078e0d ("PM: sleep: Fix possible deadlocks in core system-wide PM code")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/power/main.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index 8c4819fe73d4..b4cd003d3e39 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -680,7 +680,7 @@ static bool dpm_async_fn(struct device *dev, async_func_t func)
+ static void async_resume_noirq(void *data, async_cookie_t cookie)
+ {
+-      struct device *dev = (struct device *)data;
++      struct device *dev = data;
+       int error;
+       error = device_resume_noirq(dev, pm_transition, true);
+@@ -819,7 +819,7 @@ static int device_resume_early(struct device *dev, pm_message_t state, bool asyn
+ static void async_resume_early(void *data, async_cookie_t cookie)
+ {
+-      struct device *dev = (struct device *)data;
++      struct device *dev = data;
+       int error;
+       error = device_resume_early(dev, pm_transition, true);
+@@ -983,7 +983,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
+ static void async_resume(void *data, async_cookie_t cookie)
+ {
+-      struct device *dev = (struct device *)data;
++      struct device *dev = data;
+       int error;
+       error = device_resume(dev, pm_transition, true);
+@@ -1272,7 +1272,7 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a
+ static void async_suspend_noirq(void *data, async_cookie_t cookie)
+ {
+-      struct device *dev = (struct device *)data;
++      struct device *dev = data;
+       int error;
+       error = __device_suspend_noirq(dev, pm_transition, true);
+@@ -1455,7 +1455,7 @@ static int __device_suspend_late(struct device *dev, pm_message_t state, bool as
+ static void async_suspend_late(void *data, async_cookie_t cookie)
+ {
+-      struct device *dev = (struct device *)data;
++      struct device *dev = data;
+       int error;
+       error = __device_suspend_late(dev, pm_transition, true);
+@@ -1731,7 +1731,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
+ static void async_suspend(void *data, async_cookie_t cookie)
+ {
+-      struct device *dev = (struct device *)data;
++      struct device *dev = data;
+       int error;
+       error = __device_suspend(dev, pm_transition, true);
+-- 
+2.43.0
+
diff --git a/queue-5.15/pm-devfreq-add-cpu-based-scaling-support-to-passive-.patch b/queue-5.15/pm-devfreq-add-cpu-based-scaling-support-to-passive-.patch
new file mode 100644 (file)
index 0000000..cd96a5c
--- /dev/null
@@ -0,0 +1,475 @@
+From 2fb24f0d287f9cf2db2cd73f41dba8b5a6710453 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Mar 2021 15:58:21 +0900
+Subject: PM / devfreq: Add cpu based scaling support to passive governor
+
+From: Saravana Kannan <skannan@codeaurora.org>
+
+[ Upstream commit a03dacb0316f74400846aaf144d6c73f4217ca08 ]
+
+Many CPU architectures have caches that can scale independent of the
+CPUs. Frequency scaling of the caches is necessary to make sure that the
+cache is not a performance bottleneck that leads to poor performance and
+power. The same idea applies for RAM/DDR.
+
+To achieve this, this patch adds support for cpu based scaling to the
+passive governor. This is accomplished by taking the current frequency
+of each CPU frequency domain and then adjust the frequency of the cache
+(or any devfreq device) based on the frequency of the CPUs. It listens
+to CPU frequency transition notifiers to keep itself up to date on the
+current CPU frequency.
+
+To decide the frequency of the device, the governor does one of the
+following:
+* Derives the optimal devfreq device opp from required-opps property of
+  the parent cpu opp_table.
+
+* Scales the device frequency in proportion to the CPU frequency. So, if
+  the CPUs are running at their max frequency, the device runs at its
+  max frequency. If the CPUs are running at their min frequency, the
+  device runs at its min frequency. It is interpolated for frequencies
+  in between.
+
+Tested-by: Chen-Yu Tsai <wenst@chromium.org>
+Tested-by: Johnson Wang <johnson.wang@mediatek.com>
+Signed-off-by: Saravana Kannan <skannan@codeaurora.org>
+[Sibi: Integrated cpu-freqmap governor into passive_governor]
+Signed-off-by: Sibi Sankar <sibis@codeaurora.org>
+[Chanwoo: Fix conflict with latest code and cleanup code]
+Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
+Stable-dep-of: 08e23d05fa6d ("PM / devfreq: Fix buffer overflow in trans_stat_show")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/devfreq/governor.h         |  22 +++
+ drivers/devfreq/governor_passive.c | 298 +++++++++++++++++++++++++++--
+ include/linux/devfreq.h            |  17 +-
+ 3 files changed, 323 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h
+index 9a9495f94ac6..3c36c92c89a9 100644
+--- a/drivers/devfreq/governor.h
++++ b/drivers/devfreq/governor.h
+@@ -47,6 +47,28 @@
+ #define DEVFREQ_GOV_ATTR_POLLING_INTERVAL             BIT(0)
+ #define DEVFREQ_GOV_ATTR_TIMER                                BIT(1)
++/**
++ * struct devfreq_cpu_data - Hold the per-cpu data
++ * @dev:      reference to cpu device.
++ * @first_cpu:        the cpumask of the first cpu of a policy.
++ * @opp_table:        reference to cpu opp table.
++ * @cur_freq: the current frequency of the cpu.
++ * @min_freq: the min frequency of the cpu.
++ * @max_freq: the max frequency of the cpu.
++ *
++ * This structure stores the required cpu_data of a cpu.
++ * This is auto-populated by the governor.
++ */
++struct devfreq_cpu_data {
++      struct device *dev;
++      unsigned int first_cpu;
++
++      struct opp_table *opp_table;
++      unsigned int cur_freq;
++      unsigned int min_freq;
++      unsigned int max_freq;
++};
++
+ /**
+  * struct devfreq_governor - Devfreq policy governor
+  * @node:             list node - contains registered devfreq governors
+diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c
+index fc09324a03e0..7f30088b500b 100644
+--- a/drivers/devfreq/governor_passive.c
++++ b/drivers/devfreq/governor_passive.c
+@@ -8,11 +8,85 @@
+  */
+ #include <linux/module.h>
++#include <linux/cpu.h>
++#include <linux/cpufreq.h>
++#include <linux/cpumask.h>
++#include <linux/slab.h>
+ #include <linux/device.h>
+ #include <linux/devfreq.h>
+ #include "governor.h"
+-static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
++#define HZ_PER_KHZ    1000
++
++static unsigned long get_target_freq_by_required_opp(struct device *p_dev,
++                                              struct opp_table *p_opp_table,
++                                              struct opp_table *opp_table,
++                                              unsigned long *freq)
++{
++      struct dev_pm_opp *opp = NULL, *p_opp = NULL;
++      unsigned long target_freq;
++
++      if (!p_dev || !p_opp_table || !opp_table || !freq)
++              return 0;
++
++      p_opp = devfreq_recommended_opp(p_dev, freq, 0);
++      if (IS_ERR(p_opp))
++              return 0;
++
++      opp = dev_pm_opp_xlate_required_opp(p_opp_table, opp_table, p_opp);
++      dev_pm_opp_put(p_opp);
++
++      if (IS_ERR(opp))
++              return 0;
++
++      target_freq = dev_pm_opp_get_freq(opp);
++      dev_pm_opp_put(opp);
++
++      return target_freq;
++}
++
++static int get_target_freq_with_cpufreq(struct devfreq *devfreq,
++                                      unsigned long *target_freq)
++{
++      struct devfreq_passive_data *p_data =
++                              (struct devfreq_passive_data *)devfreq->data;
++      struct devfreq_cpu_data *parent_cpu_data;
++      unsigned long cpu, cpu_cur, cpu_min, cpu_max, cpu_percent;
++      unsigned long dev_min, dev_max;
++      unsigned long freq = 0;
++
++      for_each_online_cpu(cpu) {
++              parent_cpu_data = p_data->parent_cpu_data[cpu];
++              if (!parent_cpu_data || parent_cpu_data->first_cpu != cpu)
++                      continue;
++
++              /* Get target freq via required opps */
++              cpu_cur = parent_cpu_data->cur_freq * HZ_PER_KHZ;
++              freq = get_target_freq_by_required_opp(parent_cpu_data->dev,
++                                      parent_cpu_data->opp_table,
++                                      devfreq->opp_table, &cpu_cur);
++              if (freq) {
++                      *target_freq = max(freq, *target_freq);
++                      continue;
++              }
++
++              /* Use interpolation if required opps is not available */
++              devfreq_get_freq_range(devfreq, &dev_min, &dev_max);
++
++              cpu_min = parent_cpu_data->min_freq;
++              cpu_max = parent_cpu_data->max_freq;
++              cpu_cur = parent_cpu_data->cur_freq;
++
++              cpu_percent = ((cpu_cur - cpu_min) * 100) / (cpu_max - cpu_min);
++              freq = dev_min + mult_frac(dev_max - dev_min, cpu_percent, 100);
++
++              *target_freq = max(freq, *target_freq);
++      }
++
++      return 0;
++}
++
++static int get_target_freq_with_devfreq(struct devfreq *devfreq,
+                                       unsigned long *freq)
+ {
+       struct devfreq_passive_data *p_data
+@@ -99,6 +173,181 @@ static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
+       return 0;
+ }
++static int devfreq_passive_get_target_freq(struct devfreq *devfreq,
++                                         unsigned long *freq)
++{
++      struct devfreq_passive_data *p_data =
++                              (struct devfreq_passive_data *)devfreq->data;
++      int ret;
++
++      if (!p_data)
++              return -EINVAL;
++
++      /*
++       * If the devfreq device with passive governor has the specific method
++       * to determine the next frequency, should use the get_target_freq()
++       * of struct devfreq_passive_data.
++       */
++      if (p_data->get_target_freq)
++              return p_data->get_target_freq(devfreq, freq);
++
++      switch (p_data->parent_type) {
++      case DEVFREQ_PARENT_DEV:
++              ret = get_target_freq_with_devfreq(devfreq, freq);
++              break;
++      case CPUFREQ_PARENT_DEV:
++              ret = get_target_freq_with_cpufreq(devfreq, freq);
++              break;
++      default:
++              ret = -EINVAL;
++              dev_err(&devfreq->dev, "Invalid parent type\n");
++              break;
++      }
++
++      return ret;
++}
++
++static int cpufreq_passive_notifier_call(struct notifier_block *nb,
++                                       unsigned long event, void *ptr)
++{
++      struct devfreq_passive_data *p_data =
++                      container_of(nb, struct devfreq_passive_data, nb);
++      struct devfreq *devfreq = (struct devfreq *)p_data->this;
++      struct devfreq_cpu_data *parent_cpu_data;
++      struct cpufreq_freqs *freqs = ptr;
++      unsigned int cur_freq;
++      int ret;
++
++      if (event != CPUFREQ_POSTCHANGE || !freqs ||
++              !p_data->parent_cpu_data[freqs->policy->cpu])
++              return 0;
++
++      parent_cpu_data = p_data->parent_cpu_data[freqs->policy->cpu];
++      if (parent_cpu_data->cur_freq == freqs->new)
++              return 0;
++
++      cur_freq = parent_cpu_data->cur_freq;
++      parent_cpu_data->cur_freq = freqs->new;
++
++      mutex_lock(&devfreq->lock);
++      ret = devfreq_update_target(devfreq, freqs->new);
++      mutex_unlock(&devfreq->lock);
++      if (ret) {
++              parent_cpu_data->cur_freq = cur_freq;
++              dev_err(&devfreq->dev, "failed to update the frequency.\n");
++              return ret;
++      }
++
++      return 0;
++}
++
++static int cpufreq_passive_unregister_notifier(struct devfreq *devfreq)
++{
++      struct devfreq_passive_data *p_data
++                      = (struct devfreq_passive_data *)devfreq->data;
++      struct devfreq_cpu_data *parent_cpu_data;
++      int cpu, ret;
++
++      if (p_data->nb.notifier_call) {
++              ret = cpufreq_unregister_notifier(&p_data->nb,
++                                      CPUFREQ_TRANSITION_NOTIFIER);
++              if (ret < 0)
++                      return ret;
++      }
++
++      for_each_possible_cpu(cpu) {
++              parent_cpu_data = p_data->parent_cpu_data[cpu];
++              if (!parent_cpu_data)
++                      continue;
++
++              if (parent_cpu_data->opp_table)
++                      dev_pm_opp_put_opp_table(parent_cpu_data->opp_table);
++              kfree(parent_cpu_data);
++      }
++
++      return 0;
++}
++
++static int cpufreq_passive_register_notifier(struct devfreq *devfreq)
++{
++      struct devfreq_passive_data *p_data
++                      = (struct devfreq_passive_data *)devfreq->data;
++      struct device *dev = devfreq->dev.parent;
++      struct opp_table *opp_table = NULL;
++      struct devfreq_cpu_data *parent_cpu_data;
++      struct cpufreq_policy *policy;
++      struct device *cpu_dev;
++      unsigned int cpu;
++      int ret;
++
++      p_data->nb.notifier_call = cpufreq_passive_notifier_call;
++      ret = cpufreq_register_notifier(&p_data->nb, CPUFREQ_TRANSITION_NOTIFIER);
++      if (ret) {
++              dev_err(dev, "failed to register cpufreq notifier\n");
++              p_data->nb.notifier_call = NULL;
++              goto err;
++      }
++
++      for_each_possible_cpu(cpu) {
++              if (p_data->parent_cpu_data[cpu])
++                      continue;
++
++              policy = cpufreq_cpu_get(cpu);
++              if (!policy) {
++                      ret = -EPROBE_DEFER;
++                      goto err;
++              }
++
++              parent_cpu_data = kzalloc(sizeof(*parent_cpu_data),
++                                              GFP_KERNEL);
++              if (!parent_cpu_data) {
++                      ret = -ENOMEM;
++                      goto err_put_policy;
++              }
++
++              cpu_dev = get_cpu_device(cpu);
++              if (!cpu_dev) {
++                      dev_err(dev, "failed to get cpu device\n");
++                      ret = -ENODEV;
++                      goto err_free_cpu_data;
++              }
++
++              opp_table = dev_pm_opp_get_opp_table(cpu_dev);
++              if (IS_ERR(opp_table)) {
++                      dev_err(dev, "failed to get opp_table of cpu%d\n", cpu);
++                      ret = PTR_ERR(opp_table);
++                      goto err_free_cpu_data;
++              }
++
++              parent_cpu_data->dev = cpu_dev;
++              parent_cpu_data->opp_table = opp_table;
++              parent_cpu_data->first_cpu = cpumask_first(policy->related_cpus);
++              parent_cpu_data->cur_freq = policy->cur;
++              parent_cpu_data->min_freq = policy->cpuinfo.min_freq;
++              parent_cpu_data->max_freq = policy->cpuinfo.max_freq;
++
++              p_data->parent_cpu_data[cpu] = parent_cpu_data;
++              cpufreq_cpu_put(policy);
++      }
++
++      mutex_lock(&devfreq->lock);
++      ret = devfreq_update_target(devfreq, 0L);
++      mutex_unlock(&devfreq->lock);
++      if (ret)
++              dev_err(dev, "failed to update the frequency\n");
++
++      return ret;
++
++err_free_cpu_data:
++      kfree(parent_cpu_data);
++err_put_policy:
++      cpufreq_cpu_put(policy);
++err:
++      WARN_ON(cpufreq_passive_unregister_notifier(devfreq));
++
++      return ret;
++}
++
+ static int devfreq_passive_notifier_call(struct notifier_block *nb,
+                               unsigned long event, void *ptr)
+ {
+@@ -131,30 +380,55 @@ static int devfreq_passive_notifier_call(struct notifier_block *nb,
+       return NOTIFY_DONE;
+ }
+-static int devfreq_passive_event_handler(struct devfreq *devfreq,
+-                              unsigned int event, void *data)
++static int devfreq_passive_unregister_notifier(struct devfreq *devfreq)
++{
++      struct devfreq_passive_data *p_data
++                      = (struct devfreq_passive_data *)devfreq->data;
++      struct devfreq *parent = (struct devfreq *)p_data->parent;
++      struct notifier_block *nb = &p_data->nb;
++
++      return devfreq_unregister_notifier(parent, nb, DEVFREQ_TRANSITION_NOTIFIER);
++}
++
++static int devfreq_passive_register_notifier(struct devfreq *devfreq)
+ {
+       struct devfreq_passive_data *p_data
+                       = (struct devfreq_passive_data *)devfreq->data;
+       struct devfreq *parent = (struct devfreq *)p_data->parent;
+       struct notifier_block *nb = &p_data->nb;
+-      int ret = 0;
+       if (!parent)
+               return -EPROBE_DEFER;
++      nb->notifier_call = devfreq_passive_notifier_call;
++      return devfreq_register_notifier(parent, nb, DEVFREQ_TRANSITION_NOTIFIER);
++}
++
++static int devfreq_passive_event_handler(struct devfreq *devfreq,
++                              unsigned int event, void *data)
++{
++      struct devfreq_passive_data *p_data
++                      = (struct devfreq_passive_data *)devfreq->data;
++      int ret = -EINVAL;
++
++      if (!p_data)
++              return -EINVAL;
++
++      if (!p_data->this)
++              p_data->this = devfreq;
++
+       switch (event) {
+       case DEVFREQ_GOV_START:
+-              if (!p_data->this)
+-                      p_data->this = devfreq;
+-
+-              nb->notifier_call = devfreq_passive_notifier_call;
+-              ret = devfreq_register_notifier(parent, nb,
+-                                      DEVFREQ_TRANSITION_NOTIFIER);
++              if (p_data->parent_type == DEVFREQ_PARENT_DEV)
++                      ret = devfreq_passive_register_notifier(devfreq);
++              else if (p_data->parent_type == CPUFREQ_PARENT_DEV)
++                      ret = cpufreq_passive_register_notifier(devfreq);
+               break;
+       case DEVFREQ_GOV_STOP:
+-              WARN_ON(devfreq_unregister_notifier(parent, nb,
+-                                      DEVFREQ_TRANSITION_NOTIFIER));
++              if (p_data->parent_type == DEVFREQ_PARENT_DEV)
++                      WARN_ON(devfreq_passive_unregister_notifier(devfreq));
++              else if (p_data->parent_type == CPUFREQ_PARENT_DEV)
++                      WARN_ON(cpufreq_passive_unregister_notifier(devfreq));
+               break;
+       default:
+               break;
+diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
+index d94b9ed9443e..86ef2885c04b 100644
+--- a/include/linux/devfreq.h
++++ b/include/linux/devfreq.h
+@@ -38,6 +38,7 @@ enum devfreq_timer {
+ struct devfreq;
+ struct devfreq_governor;
++struct devfreq_cpu_data;
+ struct thermal_cooling_device;
+ /**
+@@ -289,6 +290,11 @@ struct devfreq_simple_ondemand_data {
+ #endif
+ #if IS_ENABLED(CONFIG_DEVFREQ_GOV_PASSIVE)
++enum devfreq_parent_dev_type {
++      DEVFREQ_PARENT_DEV,
++      CPUFREQ_PARENT_DEV,
++};
++
+ /**
+  * struct devfreq_passive_data - ``void *data`` fed to struct devfreq
+  *    and devfreq_add_device
+@@ -300,8 +306,11 @@ struct devfreq_simple_ondemand_data {
+  *                    using governors except for passive governor.
+  *                    If the devfreq device has the specific method to decide
+  *                    the next frequency, should use this callback.
+- * @this:     the devfreq instance of own device.
+- * @nb:               the notifier block for DEVFREQ_TRANSITION_NOTIFIER list
++ * @parent_type:      the parent type of the device.
++ * @this:             the devfreq instance of own device.
++ * @nb:                       the notifier block for DEVFREQ_TRANSITION_NOTIFIER or
++ *                    CPUFREQ_TRANSITION_NOTIFIER list.
++ * @parent_cpu_data:  the state min/max/current frequency of all online cpu's.
+  *
+  * The devfreq_passive_data have to set the devfreq instance of parent
+  * device with governors except for the passive governor. But, don't need to
+@@ -315,9 +324,13 @@ struct devfreq_passive_data {
+       /* Optional callback to decide the next frequency of passvice device */
+       int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
++      /* Should set the type of parent device */
++      enum devfreq_parent_dev_type parent_type;
++
+       /* For passive governor's internal use. Don't need to set them */
+       struct devfreq *this;
+       struct notifier_block nb;
++      struct devfreq_cpu_data *parent_cpu_data[NR_CPUS];
+ };
+ #endif
+-- 
+2.43.0
+
diff --git a/queue-5.15/pm-devfreq-export-devfreq_get_freq_range-symbol-with.patch b/queue-5.15/pm-devfreq-export-devfreq_get_freq_range-symbol-with.patch
new file mode 100644 (file)
index 0000000..fb06604
--- /dev/null
@@ -0,0 +1,125 @@
+From 7cde1179118a6f4e0ea429fd4bb6659165ba0a96 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 1 Mar 2021 02:07:29 +0900
+Subject: PM / devfreq: Export devfreq_get_freq_range symbol within devfreq
+
+From: Chanwoo Choi <cw00.choi@samsung.com>
+
+[ Upstream commit 713472e53e6e53c985e283782b0fd76b8ecfd47e ]
+
+In order to get frequency range within devfreq governors,
+export devfreq_get_freq_range symbol within devfreq.
+
+Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
+Tested-by: Chen-Yu Tsai <wenst@chromium.org>
+Tested-by: Johnson Wang <johnson.wang@mediatek.com>
+Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
+Stable-dep-of: 08e23d05fa6d ("PM / devfreq: Fix buffer overflow in trans_stat_show")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/devfreq/devfreq.c  | 20 ++++++++++++--------
+ drivers/devfreq/governor.h |  2 ++
+ 2 files changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
+index 29a14b0ffe33..c8cee796a5a0 100644
+--- a/drivers/devfreq/devfreq.c
++++ b/drivers/devfreq/devfreq.c
+@@ -112,16 +112,16 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq)
+ }
+ /**
+- * get_freq_range() - Get the current freq range
++ * devfreq_get_freq_range() - Get the current freq range
+  * @devfreq:  the devfreq instance
+  * @min_freq: the min frequency
+  * @max_freq: the max frequency
+  *
+  * This takes into consideration all constraints.
+  */
+-static void get_freq_range(struct devfreq *devfreq,
+-                         unsigned long *min_freq,
+-                         unsigned long *max_freq)
++void devfreq_get_freq_range(struct devfreq *devfreq,
++                          unsigned long *min_freq,
++                          unsigned long *max_freq)
+ {
+       unsigned long *freq_table = devfreq->profile->freq_table;
+       s32 qos_min_freq, qos_max_freq;
+@@ -158,6 +158,7 @@ static void get_freq_range(struct devfreq *devfreq,
+       if (*min_freq > *max_freq)
+               *min_freq = *max_freq;
+ }
++EXPORT_SYMBOL(devfreq_get_freq_range);
+ /**
+  * devfreq_get_freq_level() - Lookup freq_table for the frequency
+@@ -418,7 +419,7 @@ int devfreq_update_target(struct devfreq *devfreq, unsigned long freq)
+       err = devfreq->governor->get_target_freq(devfreq, &freq);
+       if (err)
+               return err;
+-      get_freq_range(devfreq, &min_freq, &max_freq);
++      devfreq_get_freq_range(devfreq, &min_freq, &max_freq);
+       if (freq < min_freq) {
+               freq = min_freq;
+@@ -785,6 +786,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
+ {
+       struct devfreq *devfreq;
+       struct devfreq_governor *governor;
++      unsigned long min_freq, max_freq;
+       int err = 0;
+       if (!dev || !profile || !governor_name) {
+@@ -849,6 +851,8 @@ struct devfreq *devfreq_add_device(struct device *dev,
+               goto err_dev;
+       }
++      devfreq_get_freq_range(devfreq, &min_freq, &max_freq);
++
+       devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
+       devfreq->opp_table = dev_pm_opp_get_opp_table(dev);
+       if (IS_ERR(devfreq->opp_table))
+@@ -1560,7 +1564,7 @@ static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
+       unsigned long min_freq, max_freq;
+       mutex_lock(&df->lock);
+-      get_freq_range(df, &min_freq, &max_freq);
++      devfreq_get_freq_range(df, &min_freq, &max_freq);
+       mutex_unlock(&df->lock);
+       return sprintf(buf, "%lu\n", min_freq);
+@@ -1614,7 +1618,7 @@ static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr,
+       unsigned long min_freq, max_freq;
+       mutex_lock(&df->lock);
+-      get_freq_range(df, &min_freq, &max_freq);
++      devfreq_get_freq_range(df, &min_freq, &max_freq);
+       mutex_unlock(&df->lock);
+       return sprintf(buf, "%lu\n", max_freq);
+@@ -1928,7 +1932,7 @@ static int devfreq_summary_show(struct seq_file *s, void *data)
+               mutex_lock(&devfreq->lock);
+               cur_freq = devfreq->previous_freq;
+-              get_freq_range(devfreq, &min_freq, &max_freq);
++              devfreq_get_freq_range(devfreq, &min_freq, &max_freq);
+               timer = devfreq->profile->timer;
+               if (IS_SUPPORTED_ATTR(devfreq->governor->attrs, POLLING_INTERVAL))
+diff --git a/drivers/devfreq/governor.h b/drivers/devfreq/governor.h
+index 2d69a0ce6291..9a9495f94ac6 100644
+--- a/drivers/devfreq/governor.h
++++ b/drivers/devfreq/governor.h
+@@ -86,6 +86,8 @@ int devfreq_remove_governor(struct devfreq_governor *governor);
+ int devfreq_update_status(struct devfreq *devfreq, unsigned long freq);
+ int devfreq_update_target(struct devfreq *devfreq, unsigned long freq);
++void devfreq_get_freq_range(struct devfreq *devfreq, unsigned long *min_freq,
++                          unsigned long *max_freq);
+ static inline int devfreq_update_stats(struct devfreq *df)
+ {
+-- 
+2.43.0
+
diff --git a/queue-5.15/pm-devfreq-fix-buffer-overflow-in-trans_stat_show.patch b/queue-5.15/pm-devfreq-fix-buffer-overflow-in-trans_stat_show.patch
new file mode 100644 (file)
index 0000000..47bd00f
--- /dev/null
@@ -0,0 +1,143 @@
+From 0ad57c14361cffe2434a4de131b2a24f0898300a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 24 Oct 2023 20:30:15 +0200
+Subject: PM / devfreq: Fix buffer overflow in trans_stat_show
+
+From: Christian Marangi <ansuelsmth@gmail.com>
+
+[ Upstream commit 08e23d05fa6dc4fc13da0ccf09defdd4bbc92ff4 ]
+
+Fix buffer overflow in trans_stat_show().
+
+Convert simple snprintf to the more secure scnprintf with size of
+PAGE_SIZE.
+
+Add condition checking if we are exceeding PAGE_SIZE and exit early from
+loop. Also add at the end a warning that we exceeded PAGE_SIZE and that
+stats is disabled.
+
+Return -EFBIG in the case where we don't have enough space to write the
+full transition table.
+
+Also document in the ABI that this function can return -EFBIG error.
+
+Link: https://lore.kernel.org/all/20231024183016.14648-2-ansuelsmth@gmail.com/
+Cc: stable@vger.kernel.org
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218041
+Fixes: e552bbaf5b98 ("PM / devfreq: Add sysfs node for representing frequency transition information.")
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/ABI/testing/sysfs-class-devfreq |  3 +
+ drivers/devfreq/devfreq.c                     | 57 +++++++++++++------
+ 2 files changed, 42 insertions(+), 18 deletions(-)
+
+diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq
+index 5e6b74f30406..1e7e0bb4c14e 100644
+--- a/Documentation/ABI/testing/sysfs-class-devfreq
++++ b/Documentation/ABI/testing/sysfs-class-devfreq
+@@ -52,6 +52,9 @@ Description:
+                       echo 0 > /sys/class/devfreq/.../trans_stat
++              If the transition table is bigger than PAGE_SIZE, reading
++              this will return an -EFBIG error.
++
+ What:         /sys/class/devfreq/.../available_frequencies
+ Date:         October 2012
+ Contact:      Nishanth Menon <nm@ti.com>
+diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
+index 14b83b8531d7..96dc49c207c7 100644
+--- a/drivers/devfreq/devfreq.c
++++ b/drivers/devfreq/devfreq.c
+@@ -1656,7 +1656,7 @@ static ssize_t trans_stat_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+ {
+       struct devfreq *df = to_devfreq(dev);
+-      ssize_t len;
++      ssize_t len = 0;
+       int i, j;
+       unsigned int max_state;
+@@ -1665,7 +1665,7 @@ static ssize_t trans_stat_show(struct device *dev,
+       max_state = df->max_state;
+       if (max_state == 0)
+-              return sprintf(buf, "Not Supported.\n");
++              return scnprintf(buf, PAGE_SIZE, "Not Supported.\n");
+       mutex_lock(&df->lock);
+       if (!df->stop_polling &&
+@@ -1675,31 +1675,52 @@ static ssize_t trans_stat_show(struct device *dev,
+       }
+       mutex_unlock(&df->lock);
+-      len = sprintf(buf, "     From  :   To\n");
+-      len += sprintf(buf + len, "           :");
+-      for (i = 0; i < max_state; i++)
+-              len += sprintf(buf + len, "%10lu",
+-                              df->freq_table[i]);
++      len += scnprintf(buf + len, PAGE_SIZE - len, "     From  :   To\n");
++      len += scnprintf(buf + len, PAGE_SIZE - len, "           :");
++      for (i = 0; i < max_state; i++) {
++              if (len >= PAGE_SIZE - 1)
++                      break;
++              len += scnprintf(buf + len, PAGE_SIZE - len, "%10lu",
++                               df->freq_table[i]);
++      }
++      if (len >= PAGE_SIZE - 1)
++              return PAGE_SIZE - 1;
+-      len += sprintf(buf + len, "   time(ms)\n");
++      len += scnprintf(buf + len, PAGE_SIZE - len, "   time(ms)\n");
+       for (i = 0; i < max_state; i++) {
++              if (len >= PAGE_SIZE - 1)
++                      break;
+               if (df->freq_table[i] == df->previous_freq)
+-                      len += sprintf(buf + len, "*");
++                      len += scnprintf(buf + len, PAGE_SIZE - len, "*");
+               else
+-                      len += sprintf(buf + len, " ");
++                      len += scnprintf(buf + len, PAGE_SIZE - len, " ");
++              if (len >= PAGE_SIZE - 1)
++                      break;
++
++              len += scnprintf(buf + len, PAGE_SIZE - len, "%10lu:",
++                               df->freq_table[i]);
++              for (j = 0; j < max_state; j++) {
++                      if (len >= PAGE_SIZE - 1)
++                              break;
++                      len += scnprintf(buf + len, PAGE_SIZE - len, "%10u",
++                                       df->stats.trans_table[(i * max_state) + j]);
++              }
++              if (len >= PAGE_SIZE - 1)
++                      break;
++              len += scnprintf(buf + len, PAGE_SIZE - len, "%10llu\n", (u64)
++                               jiffies64_to_msecs(df->stats.time_in_state[i]));
++      }
+-              len += sprintf(buf + len, "%10lu:", df->freq_table[i]);
+-              for (j = 0; j < max_state; j++)
+-                      len += sprintf(buf + len, "%10u",
+-                              df->stats.trans_table[(i * max_state) + j]);
++      if (len < PAGE_SIZE - 1)
++              len += scnprintf(buf + len, PAGE_SIZE - len, "Total transition : %u\n",
++                               df->stats.total_trans);
+-              len += sprintf(buf + len, "%10llu\n", (u64)
+-                      jiffies64_to_msecs(df->stats.time_in_state[i]));
++      if (len >= PAGE_SIZE - 1) {
++              pr_warn_once("devfreq transition table exceeds PAGE_SIZE. Disabling\n");
++              return -EFBIG;
+       }
+-      len += sprintf(buf + len, "Total transition : %u\n",
+-                                      df->stats.total_trans);
+       return len;
+ }
+-- 
+2.43.0
+
diff --git a/queue-5.15/pm-devfreq-passive-reduce-duplicate-code-when-passiv.patch b/queue-5.15/pm-devfreq-passive-reduce-duplicate-code-when-passiv.patch
new file mode 100644 (file)
index 0000000..cc6e1e1
--- /dev/null
@@ -0,0 +1,121 @@
+From 38a1b2738c0915ede2421ea5df780f4ccbc99da0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Mar 2021 17:22:50 +0900
+Subject: PM / devfreq: passive: Reduce duplicate code when passive_devfreq
+ case
+
+From: Chanwoo Choi <cw00.choi@samsung.com>
+
+[ Upstream commit 05723e71234b60a1a47313ea1a889797ec648f1c ]
+
+In order to keep the consistent coding style between passive_devfreq
+and passive_cpufreq, use common code for handling required opp property.
+Also remove the unneed conditional statement and unify the comment
+of both passive_devfreq and passive_cpufreq when getting the target frequency.
+
+Tested-by: Chen-Yu Tsai <wenst@chromium.org>
+Tested-by: Johnson Wang <johnson.wang@mediatek.com>
+Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
+Stable-dep-of: 08e23d05fa6d ("PM / devfreq: Fix buffer overflow in trans_stat_show")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/devfreq/governor_passive.c | 66 ++++--------------------------
+ 1 file changed, 8 insertions(+), 58 deletions(-)
+
+diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c
+index 7f30088b500b..ffcce613a48c 100644
+--- a/drivers/devfreq/governor_passive.c
++++ b/drivers/devfreq/governor_passive.c
+@@ -93,65 +93,16 @@ static int get_target_freq_with_devfreq(struct devfreq *devfreq,
+                       = (struct devfreq_passive_data *)devfreq->data;
+       struct devfreq *parent_devfreq = (struct devfreq *)p_data->parent;
+       unsigned long child_freq = ULONG_MAX;
+-      struct dev_pm_opp *opp, *p_opp;
+       int i, count;
+-      /*
+-       * If the devfreq device with passive governor has the specific method
+-       * to determine the next frequency, should use the get_target_freq()
+-       * of struct devfreq_passive_data.
+-       */
+-      if (p_data->get_target_freq)
+-              return p_data->get_target_freq(devfreq, freq);
++      /* Get target freq via required opps */
++      child_freq = get_target_freq_by_required_opp(parent_devfreq->dev.parent,
++                                              parent_devfreq->opp_table,
++                                              devfreq->opp_table, freq);
++      if (child_freq)
++              goto out;
+-      /*
+-       * If the parent and passive devfreq device uses the OPP table,
+-       * get the next frequency by using the OPP table.
+-       */
+-
+-      /*
+-       * - parent devfreq device uses the governors except for passive.
+-       * - passive devfreq device uses the passive governor.
+-       *
+-       * Each devfreq has the OPP table. After deciding the new frequency
+-       * from the governor of parent devfreq device, the passive governor
+-       * need to get the index of new frequency on OPP table of parent
+-       * device. And then the index is used for getting the suitable
+-       * new frequency for passive devfreq device.
+-       */
+-      if (!devfreq->profile || !devfreq->profile->freq_table
+-              || devfreq->profile->max_state <= 0)
+-              return -EINVAL;
+-
+-      /*
+-       * The passive governor have to get the correct frequency from OPP
+-       * list of parent device. Because in this case, *freq is temporary
+-       * value which is decided by ondemand governor.
+-       */
+-      if (devfreq->opp_table && parent_devfreq->opp_table) {
+-              p_opp = devfreq_recommended_opp(parent_devfreq->dev.parent,
+-                                              freq, 0);
+-              if (IS_ERR(p_opp))
+-                      return PTR_ERR(p_opp);
+-
+-              opp = dev_pm_opp_xlate_required_opp(parent_devfreq->opp_table,
+-                                                  devfreq->opp_table, p_opp);
+-              dev_pm_opp_put(p_opp);
+-
+-              if (IS_ERR(opp))
+-                      goto no_required_opp;
+-
+-              *freq = dev_pm_opp_get_freq(opp);
+-              dev_pm_opp_put(opp);
+-
+-              return 0;
+-      }
+-
+-no_required_opp:
+-      /*
+-       * Get the OPP table's index of decided frequency by governor
+-       * of parent device.
+-       */
++      /* Use interpolation if required opps is not available */
+       for (i = 0; i < parent_devfreq->profile->max_state; i++)
+               if (parent_devfreq->profile->freq_table[i] == *freq)
+                       break;
+@@ -159,7 +110,6 @@ static int get_target_freq_with_devfreq(struct devfreq *devfreq,
+       if (i == parent_devfreq->profile->max_state)
+               return -EINVAL;
+-      /* Get the suitable frequency by using index of parent device. */
+       if (i < devfreq->profile->max_state) {
+               child_freq = devfreq->profile->freq_table[i];
+       } else {
+@@ -167,7 +117,7 @@ static int get_target_freq_with_devfreq(struct devfreq *devfreq,
+               child_freq = devfreq->profile->freq_table[count - 1];
+       }
+-      /* Return the suitable frequency for passive device. */
++out:
+       *freq = child_freq;
+       return 0;
+-- 
+2.43.0
+
diff --git a/queue-5.15/pm-devfreq-rework-freq_table-to-be-local-to-devfreq-.patch b/queue-5.15/pm-devfreq-rework-freq_table-to-be-local-to-devfreq-.patch
new file mode 100644 (file)
index 0000000..e81ca3a
--- /dev/null
@@ -0,0 +1,287 @@
+From 648562db5d7b7e518c785b460472ccd2fbdb1ecc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Jun 2022 00:03:51 +0200
+Subject: PM / devfreq: Rework freq_table to be local to devfreq struct
+
+From: Christian Marangi <ansuelsmth@gmail.com>
+
+[ Upstream commit b5d281f6c16dd432b618bdfd36ddba1a58d5b603 ]
+
+On a devfreq PROBE_DEFER, the freq_table in the driver profile struct,
+is never reset and may be leaved in an undefined state.
+
+This comes from the fact that we store the freq_table in the driver
+profile struct that is commonly defined as static and not reset on
+PROBE_DEFER.
+We currently skip the reinit of the freq_table if we found
+it's already defined since a driver may declare his own freq_table.
+
+This logic is flawed in the case devfreq core generate a freq_table, set
+it in the profile struct and then PROBE_DEFER, freeing the freq_table.
+In this case devfreq will found a NOT NULL freq_table that has been
+freed, skip the freq_table generation and probe the driver based on the
+wrong table.
+
+To fix this and correctly handle PROBE_DEFER, use a local freq_table and
+max_state in the devfreq struct and never modify the freq_table present
+in the profile struct if it does provide it.
+
+Fixes: 0ec09ac2cebe ("PM / devfreq: Set the freq_table of devfreq device")
+Cc: stable@vger.kernel.org
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
+Stable-dep-of: 08e23d05fa6d ("PM / devfreq: Fix buffer overflow in trans_stat_show")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/devfreq/devfreq.c          | 71 ++++++++++++++----------------
+ drivers/devfreq/governor_passive.c | 14 +++---
+ include/linux/devfreq.h            |  5 +++
+ 3 files changed, 46 insertions(+), 44 deletions(-)
+
+diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
+index c8cee796a5a0..14b83b8531d7 100644
+--- a/drivers/devfreq/devfreq.c
++++ b/drivers/devfreq/devfreq.c
+@@ -123,7 +123,7 @@ void devfreq_get_freq_range(struct devfreq *devfreq,
+                           unsigned long *min_freq,
+                           unsigned long *max_freq)
+ {
+-      unsigned long *freq_table = devfreq->profile->freq_table;
++      unsigned long *freq_table = devfreq->freq_table;
+       s32 qos_min_freq, qos_max_freq;
+       lockdep_assert_held(&devfreq->lock);
+@@ -133,11 +133,11 @@ void devfreq_get_freq_range(struct devfreq *devfreq,
+        * The devfreq drivers can initialize this in either ascending or
+        * descending order and devfreq core supports both.
+        */
+-      if (freq_table[0] < freq_table[devfreq->profile->max_state - 1]) {
++      if (freq_table[0] < freq_table[devfreq->max_state - 1]) {
+               *min_freq = freq_table[0];
+-              *max_freq = freq_table[devfreq->profile->max_state - 1];
++              *max_freq = freq_table[devfreq->max_state - 1];
+       } else {
+-              *min_freq = freq_table[devfreq->profile->max_state - 1];
++              *min_freq = freq_table[devfreq->max_state - 1];
+               *max_freq = freq_table[0];
+       }
+@@ -169,8 +169,8 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
+ {
+       int lev;
+-      for (lev = 0; lev < devfreq->profile->max_state; lev++)
+-              if (freq == devfreq->profile->freq_table[lev])
++      for (lev = 0; lev < devfreq->max_state; lev++)
++              if (freq == devfreq->freq_table[lev])
+                       return lev;
+       return -EINVAL;
+@@ -178,7 +178,6 @@ static int devfreq_get_freq_level(struct devfreq *devfreq, unsigned long freq)
+ static int set_freq_table(struct devfreq *devfreq)
+ {
+-      struct devfreq_dev_profile *profile = devfreq->profile;
+       struct dev_pm_opp *opp;
+       unsigned long freq;
+       int i, count;
+@@ -188,25 +187,22 @@ static int set_freq_table(struct devfreq *devfreq)
+       if (count <= 0)
+               return -EINVAL;
+-      profile->max_state = count;
+-      profile->freq_table = devm_kcalloc(devfreq->dev.parent,
+-                                      profile->max_state,
+-                                      sizeof(*profile->freq_table),
+-                                      GFP_KERNEL);
+-      if (!profile->freq_table) {
+-              profile->max_state = 0;
++      devfreq->max_state = count;
++      devfreq->freq_table = devm_kcalloc(devfreq->dev.parent,
++                                         devfreq->max_state,
++                                         sizeof(*devfreq->freq_table),
++                                         GFP_KERNEL);
++      if (!devfreq->freq_table)
+               return -ENOMEM;
+-      }
+-      for (i = 0, freq = 0; i < profile->max_state; i++, freq++) {
++      for (i = 0, freq = 0; i < devfreq->max_state; i++, freq++) {
+               opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);
+               if (IS_ERR(opp)) {
+-                      devm_kfree(devfreq->dev.parent, profile->freq_table);
+-                      profile->max_state = 0;
++                      devm_kfree(devfreq->dev.parent, devfreq->freq_table);
+                       return PTR_ERR(opp);
+               }
+               dev_pm_opp_put(opp);
+-              profile->freq_table[i] = freq;
++              devfreq->freq_table[i] = freq;
+       }
+       return 0;
+@@ -246,7 +242,7 @@ int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
+       if (lev != prev_lev) {
+               devfreq->stats.trans_table[
+-                      (prev_lev * devfreq->profile->max_state) + lev]++;
++                      (prev_lev * devfreq->max_state) + lev]++;
+               devfreq->stats.total_trans++;
+       }
+@@ -835,6 +831,9 @@ struct devfreq *devfreq_add_device(struct device *dev,
+               if (err < 0)
+                       goto err_dev;
+               mutex_lock(&devfreq->lock);
++      } else {
++              devfreq->freq_table = devfreq->profile->freq_table;
++              devfreq->max_state = devfreq->profile->max_state;
+       }
+       devfreq->scaling_min_freq = find_available_min_freq(devfreq);
+@@ -870,8 +869,8 @@ struct devfreq *devfreq_add_device(struct device *dev,
+       devfreq->stats.trans_table = devm_kzalloc(&devfreq->dev,
+                       array3_size(sizeof(unsigned int),
+-                                  devfreq->profile->max_state,
+-                                  devfreq->profile->max_state),
++                                  devfreq->max_state,
++                                  devfreq->max_state),
+                       GFP_KERNEL);
+       if (!devfreq->stats.trans_table) {
+               mutex_unlock(&devfreq->lock);
+@@ -880,7 +879,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
+       }
+       devfreq->stats.time_in_state = devm_kcalloc(&devfreq->dev,
+-                      devfreq->profile->max_state,
++                      devfreq->max_state,
+                       sizeof(*devfreq->stats.time_in_state),
+                       GFP_KERNEL);
+       if (!devfreq->stats.time_in_state) {
+@@ -1638,9 +1637,9 @@ static ssize_t available_frequencies_show(struct device *d,
+       mutex_lock(&df->lock);
+-      for (i = 0; i < df->profile->max_state; i++)
++      for (i = 0; i < df->max_state; i++)
+               count += scnprintf(&buf[count], (PAGE_SIZE - count - 2),
+-                              "%lu ", df->profile->freq_table[i]);
++                              "%lu ", df->freq_table[i]);
+       mutex_unlock(&df->lock);
+       /* Truncate the trailing space */
+@@ -1663,7 +1662,7 @@ static ssize_t trans_stat_show(struct device *dev,
+       if (!df->profile)
+               return -EINVAL;
+-      max_state = df->profile->max_state;
++      max_state = df->max_state;
+       if (max_state == 0)
+               return sprintf(buf, "Not Supported.\n");
+@@ -1680,19 +1679,17 @@ static ssize_t trans_stat_show(struct device *dev,
+       len += sprintf(buf + len, "           :");
+       for (i = 0; i < max_state; i++)
+               len += sprintf(buf + len, "%10lu",
+-                              df->profile->freq_table[i]);
++                              df->freq_table[i]);
+       len += sprintf(buf + len, "   time(ms)\n");
+       for (i = 0; i < max_state; i++) {
+-              if (df->profile->freq_table[i]
+-                                      == df->previous_freq) {
++              if (df->freq_table[i] == df->previous_freq)
+                       len += sprintf(buf + len, "*");
+-              } else {
++              else
+                       len += sprintf(buf + len, " ");
+-              }
+-              len += sprintf(buf + len, "%10lu:",
+-                              df->profile->freq_table[i]);
++
++              len += sprintf(buf + len, "%10lu:", df->freq_table[i]);
+               for (j = 0; j < max_state; j++)
+                       len += sprintf(buf + len, "%10u",
+                               df->stats.trans_table[(i * max_state) + j]);
+@@ -1716,7 +1713,7 @@ static ssize_t trans_stat_store(struct device *dev,
+       if (!df->profile)
+               return -EINVAL;
+-      if (df->profile->max_state == 0)
++      if (df->max_state == 0)
+               return count;
+       err = kstrtoint(buf, 10, &value);
+@@ -1724,11 +1721,11 @@ static ssize_t trans_stat_store(struct device *dev,
+               return -EINVAL;
+       mutex_lock(&df->lock);
+-      memset(df->stats.time_in_state, 0, (df->profile->max_state *
++      memset(df->stats.time_in_state, 0, (df->max_state *
+                                       sizeof(*df->stats.time_in_state)));
+       memset(df->stats.trans_table, 0, array3_size(sizeof(unsigned int),
+-                                      df->profile->max_state,
+-                                      df->profile->max_state));
++                                      df->max_state,
++                                      df->max_state));
+       df->stats.total_trans = 0;
+       df->stats.last_update = get_jiffies_64();
+       mutex_unlock(&df->lock);
+diff --git a/drivers/devfreq/governor_passive.c b/drivers/devfreq/governor_passive.c
+index ffcce613a48c..9997332af3df 100644
+--- a/drivers/devfreq/governor_passive.c
++++ b/drivers/devfreq/governor_passive.c
+@@ -103,18 +103,18 @@ static int get_target_freq_with_devfreq(struct devfreq *devfreq,
+               goto out;
+       /* Use interpolation if required opps is not available */
+-      for (i = 0; i < parent_devfreq->profile->max_state; i++)
+-              if (parent_devfreq->profile->freq_table[i] == *freq)
++      for (i = 0; i < parent_devfreq->max_state; i++)
++              if (parent_devfreq->freq_table[i] == *freq)
+                       break;
+-      if (i == parent_devfreq->profile->max_state)
++      if (i == parent_devfreq->max_state)
+               return -EINVAL;
+-      if (i < devfreq->profile->max_state) {
+-              child_freq = devfreq->profile->freq_table[i];
++      if (i < devfreq->max_state) {
++              child_freq = devfreq->freq_table[i];
+       } else {
+-              count = devfreq->profile->max_state;
+-              child_freq = devfreq->profile->freq_table[count - 1];
++              count = devfreq->max_state;
++              child_freq = devfreq->freq_table[count - 1];
+       }
+ out:
+diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
+index 86ef2885c04b..6084003ea509 100644
+--- a/include/linux/devfreq.h
++++ b/include/linux/devfreq.h
+@@ -148,6 +148,8 @@ struct devfreq_stats {
+  *            reevaluate operable frequencies. Devfreq users may use
+  *            devfreq.nb to the corresponding register notifier call chain.
+  * @work:     delayed work for load monitoring.
++ * @freq_table:               current frequency table used by the devfreq driver.
++ * @max_state:                count of entry present in the frequency table.
+  * @previous_freq:    previously configured frequency value.
+  * @last_status:      devfreq user device info, performance statistics
+  * @data:     devfreq driver pass to governors, governor should not change it.
+@@ -185,6 +187,9 @@ struct devfreq {
+       struct notifier_block nb;
+       struct delayed_work work;
++      unsigned long *freq_table;
++      unsigned int max_state;
++
+       unsigned long previous_freq;
+       struct devfreq_dev_status last_status;
+-- 
+2.43.0
+
diff --git a/queue-5.15/pm-sleep-fix-possible-deadlocks-in-core-system-wide-.patch b/queue-5.15/pm-sleep-fix-possible-deadlocks-in-core-system-wide-.patch
new file mode 100644 (file)
index 0000000..7a7159a
--- /dev/null
@@ -0,0 +1,329 @@
+From 952ee00ffbbc1090c33acf503238117f089595df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Dec 2023 21:41:06 +0100
+Subject: PM: sleep: Fix possible deadlocks in core system-wide PM code
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit 7839d0078e0d5e6cc2fa0b0dfbee71de74f1e557 ]
+
+It is reported that in low-memory situations the system-wide resume core
+code deadlocks, because async_schedule_dev() executes its argument
+function synchronously if it cannot allocate memory (and not only in
+that case) and that function attempts to acquire a mutex that is already
+held.  Executing the argument function synchronously from within
+dpm_async_fn() may also be problematic for ordering reasons (it may
+cause a consumer device's resume callback to be invoked before a
+requisite supplier device's one, for example).
+
+Address this by changing the code in question to use
+async_schedule_dev_nocall() for scheduling the asynchronous
+execution of device suspend and resume functions and to directly
+run them synchronously if async_schedule_dev_nocall() returns false.
+
+Link: https://lore.kernel.org/linux-pm/ZYvjiqX6EsL15moe@perf/
+Reported-by: Youngmin Nam <youngmin.nam@samsung.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Stanislaw Gruszka <stanislaw.gruszka@linux.intel.com>
+Tested-by: Youngmin Nam <youngmin.nam@samsung.com>
+Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
+Cc: 5.7+ <stable@vger.kernel.org> # 5.7+: 6aa09a5bccd8 async: Split async_schedule_node_domain()
+Cc: 5.7+ <stable@vger.kernel.org> # 5.7+: 7d4b5d7a37bd async: Introduce async_schedule_dev_nocall()
+Cc: 5.7+ <stable@vger.kernel.org> # 5.7+
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/power/main.c | 148 ++++++++++++++++++--------------------
+ 1 file changed, 68 insertions(+), 80 deletions(-)
+
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index b4cd003d3e39..185ea0d93a5e 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -580,7 +580,7 @@ bool dev_pm_skip_resume(struct device *dev)
+ }
+ /**
+- * device_resume_noirq - Execute a "noirq resume" callback for given device.
++ * __device_resume_noirq - Execute a "noirq resume" callback for given device.
+  * @dev: Device to handle.
+  * @state: PM transition of the system being carried out.
+  * @async: If true, the device is being resumed asynchronously.
+@@ -588,7 +588,7 @@ bool dev_pm_skip_resume(struct device *dev)
+  * The driver of @dev will not receive interrupts while this function is being
+  * executed.
+  */
+-static int device_resume_noirq(struct device *dev, pm_message_t state, bool async)
++static void __device_resume_noirq(struct device *dev, pm_message_t state, bool async)
+ {
+       pm_callback_t callback = NULL;
+       const char *info = NULL;
+@@ -656,7 +656,13 @@ static int device_resume_noirq(struct device *dev, pm_message_t state, bool asyn
+ Out:
+       complete_all(&dev->power.completion);
+       TRACE_RESUME(error);
+-      return error;
++
++      if (error) {
++              suspend_stats.failed_resume_noirq++;
++              dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
++              dpm_save_failed_dev(dev_name(dev));
++              pm_dev_err(dev, state, async ? " async noirq" : " noirq", error);
++      }
+ }
+ static bool is_async(struct device *dev)
+@@ -669,11 +675,15 @@ static bool dpm_async_fn(struct device *dev, async_func_t func)
+ {
+       reinit_completion(&dev->power.completion);
+-      if (is_async(dev)) {
+-              get_device(dev);
+-              async_schedule_dev(func, dev);
++      if (!is_async(dev))
++              return false;
++
++      get_device(dev);
++
++      if (async_schedule_dev_nocall(func, dev))
+               return true;
+-      }
++
++      put_device(dev);
+       return false;
+ }
+@@ -681,15 +691,19 @@ static bool dpm_async_fn(struct device *dev, async_func_t func)
+ static void async_resume_noirq(void *data, async_cookie_t cookie)
+ {
+       struct device *dev = data;
+-      int error;
+-
+-      error = device_resume_noirq(dev, pm_transition, true);
+-      if (error)
+-              pm_dev_err(dev, pm_transition, " async", error);
++      __device_resume_noirq(dev, pm_transition, true);
+       put_device(dev);
+ }
++static void device_resume_noirq(struct device *dev)
++{
++      if (dpm_async_fn(dev, async_resume_noirq))
++              return;
++
++      __device_resume_noirq(dev, pm_transition, false);
++}
++
+ static void dpm_noirq_resume_devices(pm_message_t state)
+ {
+       struct device *dev;
+@@ -699,14 +713,6 @@ static void dpm_noirq_resume_devices(pm_message_t state)
+       mutex_lock(&dpm_list_mtx);
+       pm_transition = state;
+-      /*
+-       * Advanced the async threads upfront,
+-       * in case the starting of async threads is
+-       * delayed by non-async resuming devices.
+-       */
+-      list_for_each_entry(dev, &dpm_noirq_list, power.entry)
+-              dpm_async_fn(dev, async_resume_noirq);
+-
+       while (!list_empty(&dpm_noirq_list)) {
+               dev = to_device(dpm_noirq_list.next);
+               get_device(dev);
+@@ -714,17 +720,7 @@ static void dpm_noirq_resume_devices(pm_message_t state)
+               mutex_unlock(&dpm_list_mtx);
+-              if (!is_async(dev)) {
+-                      int error;
+-
+-                      error = device_resume_noirq(dev, state, false);
+-                      if (error) {
+-                              suspend_stats.failed_resume_noirq++;
+-                              dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
+-                              dpm_save_failed_dev(dev_name(dev));
+-                              pm_dev_err(dev, state, " noirq", error);
+-                      }
+-              }
++              device_resume_noirq(dev);
+               put_device(dev);
+@@ -754,14 +750,14 @@ void dpm_resume_noirq(pm_message_t state)
+ }
+ /**
+- * device_resume_early - Execute an "early resume" callback for given device.
++ * __device_resume_early - Execute an "early resume" callback for given device.
+  * @dev: Device to handle.
+  * @state: PM transition of the system being carried out.
+  * @async: If true, the device is being resumed asynchronously.
+  *
+  * Runtime PM is disabled for @dev while this function is being executed.
+  */
+-static int device_resume_early(struct device *dev, pm_message_t state, bool async)
++static void __device_resume_early(struct device *dev, pm_message_t state, bool async)
+ {
+       pm_callback_t callback = NULL;
+       const char *info = NULL;
+@@ -814,21 +810,31 @@ static int device_resume_early(struct device *dev, pm_message_t state, bool asyn
+       pm_runtime_enable(dev);
+       complete_all(&dev->power.completion);
+-      return error;
++
++      if (error) {
++              suspend_stats.failed_resume_early++;
++              dpm_save_failed_step(SUSPEND_RESUME_EARLY);
++              dpm_save_failed_dev(dev_name(dev));
++              pm_dev_err(dev, state, async ? " async early" : " early", error);
++      }
+ }
+ static void async_resume_early(void *data, async_cookie_t cookie)
+ {
+       struct device *dev = data;
+-      int error;
+-
+-      error = device_resume_early(dev, pm_transition, true);
+-      if (error)
+-              pm_dev_err(dev, pm_transition, " async", error);
++      __device_resume_early(dev, pm_transition, true);
+       put_device(dev);
+ }
++static void device_resume_early(struct device *dev)
++{
++      if (dpm_async_fn(dev, async_resume_early))
++              return;
++
++      __device_resume_early(dev, pm_transition, false);
++}
++
+ /**
+  * dpm_resume_early - Execute "early resume" callbacks for all devices.
+  * @state: PM transition of the system being carried out.
+@@ -842,14 +848,6 @@ void dpm_resume_early(pm_message_t state)
+       mutex_lock(&dpm_list_mtx);
+       pm_transition = state;
+-      /*
+-       * Advanced the async threads upfront,
+-       * in case the starting of async threads is
+-       * delayed by non-async resuming devices.
+-       */
+-      list_for_each_entry(dev, &dpm_late_early_list, power.entry)
+-              dpm_async_fn(dev, async_resume_early);
+-
+       while (!list_empty(&dpm_late_early_list)) {
+               dev = to_device(dpm_late_early_list.next);
+               get_device(dev);
+@@ -857,17 +855,7 @@ void dpm_resume_early(pm_message_t state)
+               mutex_unlock(&dpm_list_mtx);
+-              if (!is_async(dev)) {
+-                      int error;
+-
+-                      error = device_resume_early(dev, state, false);
+-                      if (error) {
+-                              suspend_stats.failed_resume_early++;
+-                              dpm_save_failed_step(SUSPEND_RESUME_EARLY);
+-                              dpm_save_failed_dev(dev_name(dev));
+-                              pm_dev_err(dev, state, " early", error);
+-                      }
+-              }
++              device_resume_early(dev);
+               put_device(dev);
+@@ -891,12 +879,12 @@ void dpm_resume_start(pm_message_t state)
+ EXPORT_SYMBOL_GPL(dpm_resume_start);
+ /**
+- * device_resume - Execute "resume" callbacks for given device.
++ * __device_resume - Execute "resume" callbacks for given device.
+  * @dev: Device to handle.
+  * @state: PM transition of the system being carried out.
+  * @async: If true, the device is being resumed asynchronously.
+  */
+-static int device_resume(struct device *dev, pm_message_t state, bool async)
++static void __device_resume(struct device *dev, pm_message_t state, bool async)
+ {
+       pm_callback_t callback = NULL;
+       const char *info = NULL;
+@@ -978,20 +966,30 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
+       TRACE_RESUME(error);
+-      return error;
++      if (error) {
++              suspend_stats.failed_resume++;
++              dpm_save_failed_step(SUSPEND_RESUME);
++              dpm_save_failed_dev(dev_name(dev));
++              pm_dev_err(dev, state, async ? " async" : "", error);
++      }
+ }
+ static void async_resume(void *data, async_cookie_t cookie)
+ {
+       struct device *dev = data;
+-      int error;
+-      error = device_resume(dev, pm_transition, true);
+-      if (error)
+-              pm_dev_err(dev, pm_transition, " async", error);
++      __device_resume(dev, pm_transition, true);
+       put_device(dev);
+ }
++static void device_resume(struct device *dev)
++{
++      if (dpm_async_fn(dev, async_resume))
++              return;
++
++      __device_resume(dev, pm_transition, false);
++}
++
+ /**
+  * dpm_resume - Execute "resume" callbacks for non-sysdev devices.
+  * @state: PM transition of the system being carried out.
+@@ -1011,27 +1009,17 @@ void dpm_resume(pm_message_t state)
+       pm_transition = state;
+       async_error = 0;
+-      list_for_each_entry(dev, &dpm_suspended_list, power.entry)
+-              dpm_async_fn(dev, async_resume);
+-
+       while (!list_empty(&dpm_suspended_list)) {
+               dev = to_device(dpm_suspended_list.next);
++
+               get_device(dev);
+-              if (!is_async(dev)) {
+-                      int error;
+-                      mutex_unlock(&dpm_list_mtx);
++              mutex_unlock(&dpm_list_mtx);
++
++              device_resume(dev);
+-                      error = device_resume(dev, state, false);
+-                      if (error) {
+-                              suspend_stats.failed_resume++;
+-                              dpm_save_failed_step(SUSPEND_RESUME);
+-                              dpm_save_failed_dev(dev_name(dev));
+-                              pm_dev_err(dev, state, "", error);
+-                      }
++              mutex_lock(&dpm_list_mtx);
+-                      mutex_lock(&dpm_list_mtx);
+-              }
+               if (!list_empty(&dev->power.entry))
+                       list_move_tail(&dev->power.entry, &dpm_prepared_list);
+-- 
+2.43.0
+
index 7d09d68af2f5b444466833d594008155cba5fec6..256c015788b2356169d9a287551b1eb2a80d3376 100644 (file)
@@ -94,3 +94,30 @@ drm-bridge-nxp-ptn3460-fix-i2c_master_send-error-checking.patch
 drm-tidss-fix-atomic_flush-check.patch
 drm-bridge-nxp-ptn3460-simplify-some-error-checking.patch
 cifs-fix-off-by-one-in-smb2_query_info_init.patch
+pm-core-remove-unnecessary-void-conversions.patch
+pm-sleep-fix-possible-deadlocks-in-core-system-wide-.patch
+bus-mhi-host-rename-struct-mhi_tre-to-struct-mhi_rin.patch
+bus-mhi-host-add-alignment-check-for-event-ring-read.patch
+fs-pipe-move-check-to-pipe_has_watch_queue.patch
+pipe-wakeup-wr_wait-after-setting-max_usage.patch
+arm-dts-qcom-sdx55-fix-usb-wakeup-interrupt-types.patch
+arm-dts-samsung-exynos4210-i9100-unconditionally-ena.patch
+arm-dts-qcom-sdx55-fix-pdc-interrupt-cells.patch
+arm-dts-qcom-sdx55-fix-usb-dp-dm-hs-phy-interrupts.patch
+arm-dts-qcom-sdx55-fix-usb-ss-wakeup.patch
+media-mtk-jpeg-fix-use-after-free-bug-due-to-error-p.patch
+mm-use-__pfn_to_section-instead-of-open-coding-it.patch
+mm-sparsemem-fix-race-in-accessing-memory_section-us.patch
+pm-devfreq-export-devfreq_get_freq_range-symbol-with.patch
+pm-devfreq-add-cpu-based-scaling-support-to-passive-.patch
+pm-devfreq-passive-reduce-duplicate-code-when-passiv.patch
+pm-devfreq-rework-freq_table-to-be-local-to-devfreq-.patch
+pm-devfreq-fix-buffer-overflow-in-trans_stat_show.patch
+btrfs-add-definition-for-extent_tree_v2.patch
+btrfs-don-t-abort-filesystem-when-attempting-to-snap.patch
+nfsd-modernize-nfsd4_release_lockowner.patch
+nfsd-add-documenting-comment-for-nfsd4_release_locko.patch
+nfsd-fix-release_lockowner.patch
+ksmbd-fix-global-oob-in-ksmbd_nl_policy.patch
+cpufreq-intel_pstate-drop-redundant-intel_pstate_get.patch
+cpufreq-intel_pstate-refine-computation-of-p-state-f.patch