]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.6
authorSasha Levin <sashal@kernel.org>
Sat, 3 Aug 2024 14:48:11 +0000 (10:48 -0400)
committerSasha Levin <sashal@kernel.org>
Sat, 3 Aug 2024 14:48:11 +0000 (10:48 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
50 files changed:
queue-6.6/arm64-dts-qcom-ipq8074-disable-ss-instance-in-parkmo.patch [new file with mode: 0644]
queue-6.6/arm64-dts-qcom-msm8998-disable-ss-instance-in-parkmo.patch [new file with mode: 0644]
queue-6.6/arm64-dts-qcom-msm8998-switch-usb-qmp-phy-to-new-sty.patch [new file with mode: 0644]
queue-6.6/arm64-dts-qcom-sc7180-disable-superspeed-instances-i.patch [new file with mode: 0644]
queue-6.6/arm64-dts-qcom-sc7180-switch-usb-dp-qmp-phy-to-new-s.patch [new file with mode: 0644]
queue-6.6/arm64-dts-qcom-sc7280-disable-superspeed-instances-i.patch [new file with mode: 0644]
queue-6.6/arm64-dts-qcom-sc7280-switch-usb-dp-qmp-phy-to-new-s.patch [new file with mode: 0644]
queue-6.6/arm64-dts-qcom-sdm845-disable-ss-instance-in-parkmod.patch [new file with mode: 0644]
queue-6.6/arm64-dts-qcom-sdm845-switch-usb-dp-qmp-phy-to-new-s.patch [new file with mode: 0644]
queue-6.6/arm64-dts-qcom-sdm845-switch-usb-qmp-phy-to-new-styl.patch [new file with mode: 0644]
queue-6.6/cpufreq-qcom-nvmem-fix-memory-leaks-in-probe-error-p.patch [new file with mode: 0644]
queue-6.6/cpufreq-qcom-nvmem-simplify-driver-data-allocation.patch [new file with mode: 0644]
queue-6.6/dmaengine-fsl-edma-add-address-for-channel-mux-regis.patch [new file with mode: 0644]
queue-6.6/dmaengine-fsl-edma-add-i.mx8ulp-edma-support.patch [new file with mode: 0644]
queue-6.6/dmaengine-fsl-edma-change-the-memory-access-from-loc.patch [new file with mode: 0644]
queue-6.6/dmaengine-fsl-edma-clean-up-unused-fsl-imx8qm-adma-c.patch [new file with mode: 0644]
queue-6.6/ext4-check-the-extent-status-again-before-inserting-.patch [new file with mode: 0644]
queue-6.6/ext4-convert-to-exclusive-lock-while-inserting-delal.patch [new file with mode: 0644]
queue-6.6/ext4-factor-out-a-common-helper-to-query-extent-map.patch [new file with mode: 0644]
queue-6.6/ext4-refactor-ext4_da_map_blocks.patch [new file with mode: 0644]
queue-6.6/f2fs-assign-curseg_all_data_atgc-if-blkaddr-is-valid.patch [new file with mode: 0644]
queue-6.6/f2fs-fix-to-avoid-use-ssr-allocate-when-do-defragmen.patch [new file with mode: 0644]
queue-6.6/fbdev-vesafb-detect-vga-compatibility-from-screen-in.patch [new file with mode: 0644]
queue-6.6/fbdev-vesafb-replace-references-to-global-screen_inf.patch [new file with mode: 0644]
queue-6.6/firmware-sysfb-update-screen_info-for-relocated-efi-.patch [new file with mode: 0644]
queue-6.6/kvm-nvmx-add-a-helper-to-get-highest-pending-from-po.patch [new file with mode: 0644]
queue-6.6/kvm-nvmx-check-for-pending-posted-interrupts-when-lo.patch [new file with mode: 0644]
queue-6.6/kvm-vmx-move-posted-interrupt-descriptor-out-of-vmx-.patch [new file with mode: 0644]
queue-6.6/kvm-vmx-split-off-vmx_onhyperv.-ch-from-hyperv.-ch.patch [new file with mode: 0644]
queue-6.6/leds-trigger-call-synchronize_rcu-before-calling-tri.patch [new file with mode: 0644]
queue-6.6/leds-trigger-remove-unused-function-led_trigger_rena.patch [new file with mode: 0644]
queue-6.6/leds-trigger-store-brightness-set-by-led_trigger_eve.patch [new file with mode: 0644]
queue-6.6/leds-triggers-flush-pending-brightness-before-activa.patch [new file with mode: 0644]
queue-6.6/mips-dts-loongson-fix-liointc-irq-polarity.patch [new file with mode: 0644]
queue-6.6/mips-dts-loongson-fix-ls2k1000-rtc-interrupt.patch [new file with mode: 0644]
queue-6.6/mips-loongson64-dts-fix-pcie-port-nodes-for-ls7a.patch [new file with mode: 0644]
queue-6.6/mm-page_alloc-control-latency-caused-by-zone-pcp-dra.patch [new file with mode: 0644]
queue-6.6/mm-page_alloc-fix-pcp-count-race-between-drain_pages.patch [new file with mode: 0644]
queue-6.6/mm-restrict-the-pcp-batch-scale-factor-to-avoid-too-.patch [new file with mode: 0644]
queue-6.6/pci-add-pci_get_base_class-helper.patch [new file with mode: 0644]
queue-6.6/perf-imx_perf-fix-counter-start-and-config-sequence.patch [new file with mode: 0644]
queue-6.6/series [new file with mode: 0644]
queue-6.6/sysctl-allow-change-system-v-ipc-sysctls-inside-ipc-.patch [new file with mode: 0644]
queue-6.6/sysctl-allow-to-change-limits-for-posix-messages-que.patch [new file with mode: 0644]
queue-6.6/sysctl-always-initialize-i_uid-i_gid.patch [new file with mode: 0644]
queue-6.6/sysctl-treewide-drop-unused-argument-ctl_table_root-.patch [new file with mode: 0644]
queue-6.6/thermal-bcm2835-convert-to-platform-remove-callback-.patch [new file with mode: 0644]
queue-6.6/thermal-drivers-broadcom-fix-race-between-removal-an.patch [new file with mode: 0644]
queue-6.6/video-add-helpers-for-decoding-screen_info.patch [new file with mode: 0644]
queue-6.6/video-provide-screen_info_get_pci_dev-to-find-screen.patch [new file with mode: 0644]

diff --git a/queue-6.6/arm64-dts-qcom-ipq8074-disable-ss-instance-in-parkmo.patch b/queue-6.6/arm64-dts-qcom-ipq8074-disable-ss-instance-in-parkmo.patch
new file mode 100644 (file)
index 0000000..4c3cfcd
--- /dev/null
@@ -0,0 +1,53 @@
+From e049dbf8374e821257d8b9c318b92bc4b1acd251 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jul 2024 20:58:42 +0530
+Subject: arm64: dts: qcom: ipq8074: Disable SS instance in Parkmode for USB
+
+From: Krishna Kurapati <quic_kriskura@quicinc.com>
+
+[ Upstream commit dc6ba95c6c4400a84cca5b419b34ae852a08cfb5 ]
+
+For Gen-1 targets like IPQ8074, it is seen that stressing out the
+controller in host mode results in HC died error:
+
+ xhci-hcd.12.auto: xHCI host not responding to stop endpoint command
+ xhci-hcd.12.auto: xHCI host controller not responding, assume dead
+ xhci-hcd.12.auto: HC died; cleaning up
+
+And at this instant only restarting the host mode fixes it. Disable
+SuperSpeed instance in park mode for IPQ8074 to mitigate this issue.
+
+Cc: stable@vger.kernel.org
+Fixes: 5e09bc51d07b ("arm64: dts: ipq8074: enable USB support")
+Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20240704152848.3380602-3-quic_kriskura@quicinc.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+index 5effd8180cc41..e5993a365870c 100644
+--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+@@ -641,6 +641,7 @@ dwc_0: usb@8a00000 {
+                               interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+                               phys = <&qusb_phy_0>, <&usb0_ssphy>;
+                               phy-names = "usb2-phy", "usb3-phy";
++                              snps,parkmode-disable-ss-quirk;
+                               snps,is-utmi-l1-suspend;
+                               snps,hird-threshold = /bits/ 8 <0x0>;
+                               snps,dis_u2_susphy_quirk;
+@@ -683,6 +684,7 @@ dwc_1: usb@8c00000 {
+                               interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+                               phys = <&qusb_phy_1>, <&usb1_ssphy>;
+                               phy-names = "usb2-phy", "usb3-phy";
++                              snps,parkmode-disable-ss-quirk;
+                               snps,is-utmi-l1-suspend;
+                               snps,hird-threshold = /bits/ 8 <0x0>;
+                               snps,dis_u2_susphy_quirk;
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-dts-qcom-msm8998-disable-ss-instance-in-parkmo.patch b/queue-6.6/arm64-dts-qcom-msm8998-disable-ss-instance-in-parkmo.patch
new file mode 100644 (file)
index 0000000..9a8872e
--- /dev/null
@@ -0,0 +1,45 @@
+From fa49691b09625e179f2d68d6dd54ecf5902da707 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jul 2024 20:58:43 +0530
+Subject: arm64: dts: qcom: msm8998: Disable SS instance in Parkmode for USB
+
+From: Krishna Kurapati <quic_kriskura@quicinc.com>
+
+[ Upstream commit 0046325ae52079b46da13a7f84dd7b2a6f7c38f8 ]
+
+For Gen-1 targets like MSM8998, it is seen that stressing out the
+controller in host mode results in HC died error:
+
+ xhci-hcd.12.auto: xHCI host not responding to stop endpoint command
+ xhci-hcd.12.auto: xHCI host controller not responding, assume dead
+ xhci-hcd.12.auto: HC died; cleaning up
+
+And at this instant only restarting the host mode fixes it. Disable
+SuperSpeed instance in park mode for MSM8998 to mitigate this issue.
+
+Cc: stable@vger.kernel.org
+Fixes: 026dad8f5873 ("arm64: dts: qcom: msm8998: Add USB-related nodes")
+Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20240704152848.3380602-4-quic_kriskura@quicinc.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/msm8998.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi
+index d49764eeab9c9..7fcc15b6946ae 100644
+--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi
++++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi
+@@ -2159,6 +2159,7 @@ usb3_dwc3: usb@a800000 {
+                               interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+                               snps,dis_u2_susphy_quirk;
+                               snps,dis_enblslpm_quirk;
++                              snps,parkmode-disable-ss-quirk;
+                               phys = <&qusb2phy>, <&usb3phy>;
+                               phy-names = "usb2-phy", "usb3-phy";
+                               snps,has-lpm-erratum;
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-dts-qcom-msm8998-switch-usb-qmp-phy-to-new-sty.patch b/queue-6.6/arm64-dts-qcom-msm8998-switch-usb-qmp-phy-to-new-sty.patch
new file mode 100644 (file)
index 0000000..c36b610
--- /dev/null
@@ -0,0 +1,85 @@
+From 6fd50975f0541b2fb1a8987a5ea79a03a82eba9a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Aug 2023 00:19:46 +0300
+Subject: arm64: dts: qcom: msm8998: switch USB QMP PHY to new style of
+ bindings
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit b7efebfeb2e8ad8187cdabba5f0212ba2e6c1069 ]
+
+Change the USB QMP PHY to use newer style of QMP PHY bindings (single
+resource region, no per-PHY subnodes).
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20230824211952.1397699-11-dmitry.baryshkov@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Stable-dep-of: 0046325ae520 ("arm64: dts: qcom: msm8998: Disable SS instance in Parkmode for USB")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/msm8998.dtsi | 35 +++++++++++----------------
+ 1 file changed, 14 insertions(+), 21 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi
+index 9c072ce197358..d49764eeab9c9 100644
+--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi
++++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi
+@@ -2159,7 +2159,7 @@ usb3_dwc3: usb@a800000 {
+                               interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+                               snps,dis_u2_susphy_quirk;
+                               snps,dis_enblslpm_quirk;
+-                              phys = <&qusb2phy>, <&usb1_ssphy>;
++                              phys = <&qusb2phy>, <&usb3phy>;
+                               phy-names = "usb2-phy", "usb3-phy";
+                               snps,has-lpm-erratum;
+                               snps,hird-threshold = /bits/ 8 <0x10>;
+@@ -2168,33 +2168,26 @@ usb3_dwc3: usb@a800000 {
+               usb3phy: phy@c010000 {
+                       compatible = "qcom,msm8998-qmp-usb3-phy";
+-                      reg = <0x0c010000 0x18c>;
+-                      status = "disabled";
+-                      #address-cells = <1>;
+-                      #size-cells = <1>;
+-                      ranges;
++                      reg = <0x0c010000 0x1000>;
+                       clocks = <&gcc GCC_USB3_PHY_AUX_CLK>,
++                               <&gcc GCC_USB3_CLKREF_CLK>,
+                                <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+-                               <&gcc GCC_USB3_CLKREF_CLK>;
+-                      clock-names = "aux", "cfg_ahb", "ref";
++                               <&gcc GCC_USB3_PHY_PIPE_CLK>;
++                      clock-names = "aux",
++                                    "ref",
++                                    "cfg_ahb",
++                                    "pipe";
++                      clock-output-names = "usb3_phy_pipe_clk_src";
++                      #clock-cells = <0>;
++                      #phy-cells = <0>;
+                       resets = <&gcc GCC_USB3_PHY_BCR>,
+                                <&gcc GCC_USB3PHY_PHY_BCR>;
+-                      reset-names = "phy", "common";
++                      reset-names = "phy",
++                                    "phy_phy";
+-                      usb1_ssphy: phy@c010200 {
+-                              reg = <0xc010200 0x128>,
+-                                    <0xc010400 0x200>,
+-                                    <0xc010c00 0x20c>,
+-                                    <0xc010600 0x128>,
+-                                    <0xc010800 0x200>;
+-                              #phy-cells = <0>;
+-                              #clock-cells = <0>;
+-                              clocks = <&gcc GCC_USB3_PHY_PIPE_CLK>;
+-                              clock-names = "pipe0";
+-                              clock-output-names = "usb3_phy_pipe_clk_src";
+-                      };
++                      status = "disabled";
+               };
+               qusb2phy: phy@c012000 {
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-dts-qcom-sc7180-disable-superspeed-instances-i.patch b/queue-6.6/arm64-dts-qcom-sc7180-disable-superspeed-instances-i.patch
new file mode 100644 (file)
index 0000000..15349a5
--- /dev/null
@@ -0,0 +1,46 @@
+From 272963ade147430b36a947efea83d0102ad707f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jun 2024 11:36:58 +0530
+Subject: arm64: dts: qcom: sc7180: Disable SuperSpeed instances in park mode
+
+From: Krishna Kurapati <quic_kriskura@quicinc.com>
+
+[ Upstream commit 5b8baed4b88132c12010ce6ca1b56f00d122e376 ]
+
+On SC7180, in host mode, it is observed that stressing out controller
+results in HC died error:
+
+ xhci-hcd.12.auto: xHCI host not responding to stop endpoint command
+ xhci-hcd.12.auto: xHCI host controller not responding, assume dead
+ xhci-hcd.12.auto: HC died; cleaning up
+
+And at this instant only restarting the host mode fixes it. Disable
+SuperSpeed instances in park mode for SC7180 to mitigate this issue.
+
+Reported-by: Doug Anderson <dianders@google.com>
+Cc: stable@vger.kernel.org
+Fixes: 0b766e7fe5a2 ("arm64: dts: qcom: sc7180: Add USB related nodes")
+Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20240604060659.1449278-2-quic_kriskura@quicinc.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sc7180.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
+index 18ef8fb5c8c7a..68b1c017a9fd5 100644
+--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
++++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
+@@ -2981,6 +2981,7 @@ usb_1_dwc3: usb@a600000 {
+                               iommus = <&apps_smmu 0x540 0>;
+                               snps,dis_u2_susphy_quirk;
+                               snps,dis_enblslpm_quirk;
++                              snps,parkmode-disable-ss-quirk;
+                               phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
+                               phy-names = "usb2-phy", "usb3-phy";
+                               maximum-speed = "super-speed";
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-dts-qcom-sc7180-switch-usb-dp-qmp-phy-to-new-s.patch b/queue-6.6/arm64-dts-qcom-sc7180-switch-usb-dp-qmp-phy-to-new-s.patch
new file mode 100644 (file)
index 0000000..9a86cc9
--- /dev/null
@@ -0,0 +1,132 @@
+From 1f1b66357768bb6be884e37de9b5bb412478b6b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jul 2023 15:09:11 +0300
+Subject: arm64: dts: qcom: sc7180: switch USB+DP QMP PHY to new style of
+ bindings
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit ebb840b00b7f9fc15153b37a7d9ec5b47a5308c1 ]
+
+Change the USB QMP PHY to use newer style of QMP PHY bindings (single
+resource region, no per-PHY subnodes).
+
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20230711120916.4165894-6-dmitry.baryshkov@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Stable-dep-of: 5b8baed4b881 ("arm64: dts: qcom: sc7180: Disable SuperSpeed instances in park mode")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sc7180.dtsi | 57 ++++++++++------------------
+ 1 file changed, 19 insertions(+), 38 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
+index f7c528ecb224b..18ef8fb5c8c7a 100644
+--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
++++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
+@@ -15,6 +15,7 @@
+ #include <dt-bindings/interconnect/qcom,osm-l3.h>
+ #include <dt-bindings/interconnect/qcom,sc7180.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
++#include <dt-bindings/phy/phy-qcom-qmp.h>
+ #include <dt-bindings/phy/phy-qcom-qusb2.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+ #include <dt-bindings/reset/qcom,sdm845-aoss.h>
+@@ -2795,49 +2796,28 @@ usb_1_hsphy: phy@88e3000 {
+                       nvmem-cells = <&qusb2p_hstx_trim>;
+               };
+-              usb_1_qmpphy: phy-wrapper@88e9000 {
++              usb_1_qmpphy: phy@88e8000 {
+                       compatible = "qcom,sc7180-qmp-usb3-dp-phy";
+-                      reg = <0 0x088e9000 0 0x18c>,
+-                            <0 0x088e8000 0 0x3c>,
+-                            <0 0x088ea000 0 0x18c>;
++                      reg = <0 0x088e8000 0 0x3000>;
+                       status = "disabled";
+-                      #address-cells = <2>;
+-                      #size-cells = <2>;
+-                      ranges;
+                       clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
+-                               <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+                                <&gcc GCC_USB3_PRIM_CLKREF_CLK>,
+-                               <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
+-                      clock-names = "aux", "cfg_ahb", "ref", "com_aux";
++                               <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
++                               <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>,
++                               <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>;
++                      clock-names = "aux",
++                                    "ref",
++                                    "com_aux",
++                                    "usb3_pipe",
++                                    "cfg_ahb";
+                       resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
+                                <&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
+                       reset-names = "phy", "common";
+-                      usb_1_ssphy: usb3-phy@88e9200 {
+-                              reg = <0 0x088e9200 0 0x128>,
+-                                    <0 0x088e9400 0 0x200>,
+-                                    <0 0x088e9c00 0 0x218>,
+-                                    <0 0x088e9600 0 0x128>,
+-                                    <0 0x088e9800 0 0x200>,
+-                                    <0 0x088e9a00 0 0x18>;
+-                              #clock-cells = <0>;
+-                              #phy-cells = <0>;
+-                              clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+-                              clock-names = "pipe0";
+-                              clock-output-names = "usb3_phy_pipe_clk_src";
+-                      };
+-
+-                      dp_phy: dp-phy@88ea200 {
+-                              reg = <0 0x088ea200 0 0x200>,
+-                                    <0 0x088ea400 0 0x200>,
+-                                    <0 0x088eaa00 0 0x200>,
+-                                    <0 0x088ea600 0 0x200>,
+-                                    <0 0x088ea800 0 0x200>;
+-                              #clock-cells = <1>;
+-                              #phy-cells = <0>;
+-                      };
++                      #clock-cells = <1>;
++                      #phy-cells = <1>;
+               };
+               pmu@90b6300 {
+@@ -3001,7 +2981,7 @@ usb_1_dwc3: usb@a600000 {
+                               iommus = <&apps_smmu 0x540 0>;
+                               snps,dis_u2_susphy_quirk;
+                               snps,dis_enblslpm_quirk;
+-                              phys = <&usb_1_hsphy>, <&usb_1_ssphy>;
++                              phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
+                               phy-names = "usb2-phy", "usb3-phy";
+                               maximum-speed = "super-speed";
+                       };
+@@ -3307,8 +3287,9 @@ mdss_dp: displayport-controller@ae90000 {
+                                             "ctrl_link_iface", "stream_pixel";
+                               assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
+                                                 <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
+-                              assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>;
+-                              phys = <&dp_phy>;
++                              assigned-clock-parents = <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
++                                                       <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
++                              phys = <&usb_1_qmpphy QMP_USB43DP_DP_PHY>;
+                               phy-names = "dp";
+                               operating-points-v2 = <&dp_opp_table>;
+@@ -3365,8 +3346,8 @@ dispcc: clock-controller@af00000 {
+                                <&gcc GCC_DISP_GPLL0_CLK_SRC>,
+                                <&mdss_dsi0_phy 0>,
+                                <&mdss_dsi0_phy 1>,
+-                               <&dp_phy 0>,
+-                               <&dp_phy 1>;
++                               <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
++                               <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
+                       clock-names = "bi_tcxo",
+                                     "gcc_disp_gpll0_clk_src",
+                                     "dsi0_phy_pll_out_byteclk",
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-dts-qcom-sc7280-disable-superspeed-instances-i.patch b/queue-6.6/arm64-dts-qcom-sc7280-disable-superspeed-instances-i.patch
new file mode 100644 (file)
index 0000000..7375996
--- /dev/null
@@ -0,0 +1,46 @@
+From e7db29acff625344c8e5663ff4bbff74edca2bfd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 4 Jun 2024 11:36:59 +0530
+Subject: arm64: dts: qcom: sc7280: Disable SuperSpeed instances in park mode
+
+From: Krishna Kurapati <quic_kriskura@quicinc.com>
+
+[ Upstream commit 3d930f1750ce30a6c36dbc71f8ff7e20322b94d7 ]
+
+On SC7280, in host mode, it is observed that stressing out controller
+results in HC died error:
+
+ xhci-hcd.12.auto: xHCI host not responding to stop endpoint command
+ xhci-hcd.12.auto: xHCI host controller not responding, assume dead
+ xhci-hcd.12.auto: HC died; cleaning up
+
+And at this instant only restarting the host mode fixes it. Disable
+SuperSpeed instances in park mode for SC7280 to mitigate this issue.
+
+Reported-by: Doug Anderson <dianders@google.com>
+Cc: stable@vger.kernel.org
+Fixes: bb9efa59c665 ("arm64: dts: qcom: sc7280: Add USB related nodes")
+Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20240604060659.1449278-3-quic_kriskura@quicinc.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sc7280.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
+index dd1d9d10c6615..149c7962f2cbb 100644
+--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
++++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
+@@ -3680,6 +3680,7 @@ usb_1_dwc3: usb@a600000 {
+                               iommus = <&apps_smmu 0xe0 0x0>;
+                               snps,dis_u2_susphy_quirk;
+                               snps,dis_enblslpm_quirk;
++                              snps,parkmode-disable-ss-quirk;
+                               phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
+                               phy-names = "usb2-phy", "usb3-phy";
+                               maximum-speed = "super-speed";
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-dts-qcom-sc7280-switch-usb-dp-qmp-phy-to-new-s.patch b/queue-6.6/arm64-dts-qcom-sc7280-switch-usb-dp-qmp-phy-to-new-s.patch
new file mode 100644 (file)
index 0000000..d488af7
--- /dev/null
@@ -0,0 +1,139 @@
+From 2da451421a06aa7e800f090dc816848ca8c61ce3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jul 2023 15:09:13 +0300
+Subject: arm64: dts: qcom: sc7280: switch USB+DP QMP PHY to new style of
+ bindings
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 36888ed83f998c3335272f9e353eaf6d109e2429 ]
+
+Change the USB QMP PHY to use newer style of QMP PHY bindings (single
+resource region, no per-PHY subnodes).
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20230711120916.4165894-8-dmitry.baryshkov@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Stable-dep-of: 3d930f1750ce ("arm64: dts: qcom: sc7280: Disable SuperSpeed instances in park mode")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sc7280.dtsi | 59 +++++++++-------------------
+ 1 file changed, 19 insertions(+), 40 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
+index b75de7caaa7e5..dd1d9d10c6615 100644
+--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
++++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
+@@ -18,6 +18,7 @@
+ #include <dt-bindings/interconnect/qcom,sc7280.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/mailbox/qcom-ipcc.h>
++#include <dt-bindings/phy/phy-qcom-qmp.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+ #include <dt-bindings/reset/qcom,sdm845-aoss.h>
+ #include <dt-bindings/reset/qcom,sdm845-pdc.h>
+@@ -858,7 +859,7 @@ gcc: clock-controller@100000 {
+                                <&rpmhcc RPMH_CXO_CLK_A>, <&sleep_clk>,
+                                <0>, <&pcie1_lane>,
+                                <0>, <0>, <0>,
+-                               <&usb_1_ssphy>;
++                               <&usb_1_qmpphy QMP_USB43DP_USB3_PIPE_CLK>;
+                       clock-names = "bi_tcxo", "bi_tcxo_ao", "sleep_clk",
+                                     "pcie_0_pipe_clk", "pcie_1_pipe_clk",
+                                     "ufs_phy_rx_symbol_0_clk", "ufs_phy_rx_symbol_1_clk",
+@@ -3351,49 +3352,26 @@ usb_2_hsphy: phy@88e4000 {
+                       resets = <&gcc GCC_QUSB2PHY_SEC_BCR>;
+               };
+-              usb_1_qmpphy: phy-wrapper@88e9000 {
+-                      compatible = "qcom,sc7280-qmp-usb3-dp-phy",
+-                                   "qcom,sm8250-qmp-usb3-dp-phy";
+-                      reg = <0 0x088e9000 0 0x200>,
+-                            <0 0x088e8000 0 0x40>,
+-                            <0 0x088ea000 0 0x200>;
++              usb_1_qmpphy: phy@88e8000 {
++                      compatible = "qcom,sc7280-qmp-usb3-dp-phy";
++                      reg = <0 0x088e8000 0 0x3000>;
+                       status = "disabled";
+-                      #address-cells = <2>;
+-                      #size-cells = <2>;
+-                      ranges;
+                       clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
+                                <&rpmhcc RPMH_CXO_CLK>,
+-                               <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
+-                      clock-names = "aux", "ref_clk_src", "com_aux";
++                               <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
++                               <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
++                      clock-names = "aux",
++                                    "ref",
++                                    "com_aux",
++                                    "usb3_pipe";
+                       resets = <&gcc GCC_USB3_DP_PHY_PRIM_BCR>,
+                                <&gcc GCC_USB3_PHY_PRIM_BCR>;
+                       reset-names = "phy", "common";
+-                      usb_1_ssphy: usb3-phy@88e9200 {
+-                              reg = <0 0x088e9200 0 0x200>,
+-                                    <0 0x088e9400 0 0x200>,
+-                                    <0 0x088e9c00 0 0x400>,
+-                                    <0 0x088e9600 0 0x200>,
+-                                    <0 0x088e9800 0 0x200>,
+-                                    <0 0x088e9a00 0 0x100>;
+-                              #clock-cells = <0>;
+-                              #phy-cells = <0>;
+-                              clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+-                              clock-names = "pipe0";
+-                              clock-output-names = "usb3_phy_pipe_clk_src";
+-                      };
+-
+-                      dp_phy: dp-phy@88ea200 {
+-                              reg = <0 0x088ea200 0 0x200>,
+-                                    <0 0x088ea400 0 0x200>,
+-                                    <0 0x088eaa00 0 0x200>,
+-                                    <0 0x088ea600 0 0x200>,
+-                                    <0 0x088ea800 0 0x200>;
+-                              #phy-cells = <0>;
+-                              #clock-cells = <1>;
+-                      };
++                      #clock-cells = <1>;
++                      #phy-cells = <1>;
+               };
+               usb_2: usb@8cf8800 {
+@@ -3702,7 +3680,7 @@ usb_1_dwc3: usb@a600000 {
+                               iommus = <&apps_smmu 0xe0 0x0>;
+                               snps,dis_u2_susphy_quirk;
+                               snps,dis_enblslpm_quirk;
+-                              phys = <&usb_1_hsphy>, <&usb_1_ssphy>;
++                              phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
+                               phy-names = "usb2-phy", "usb3-phy";
+                               maximum-speed = "super-speed";
+                       };
+@@ -3807,8 +3785,8 @@ dispcc: clock-controller@af00000 {
+                                <&gcc GCC_DISP_GPLL0_CLK_SRC>,
+                                <&mdss_dsi_phy 0>,
+                                <&mdss_dsi_phy 1>,
+-                               <&dp_phy 0>,
+-                               <&dp_phy 1>,
++                               <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
++                               <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>,
+                                <&mdss_edp_phy 0>,
+                                <&mdss_edp_phy 1>;
+                       clock-names = "bi_tcxo",
+@@ -4144,8 +4122,9 @@ mdss_dp: displayport-controller@ae90000 {
+                                               "stream_pixel";
+                               assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
+                                                 <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
+-                              assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>;
+-                              phys = <&dp_phy>;
++                              assigned-clock-parents = <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
++                                                       <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
++                              phys = <&usb_1_qmpphy QMP_USB43DP_DP_PHY>;
+                               phy-names = "dp";
+                               operating-points-v2 = <&dp_opp_table>;
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-dts-qcom-sdm845-disable-ss-instance-in-parkmod.patch b/queue-6.6/arm64-dts-qcom-sdm845-disable-ss-instance-in-parkmod.patch
new file mode 100644 (file)
index 0000000..7331300
--- /dev/null
@@ -0,0 +1,53 @@
+From 24887ea03af82d4722fb2c1818d2c8172acd8441 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jul 2024 20:58:48 +0530
+Subject: arm64: dts: qcom: sdm845: Disable SS instance in Parkmode for USB
+
+From: Krishna Kurapati <quic_kriskura@quicinc.com>
+
+[ Upstream commit cf4d6d54eadb60d2ee4d31c9d92299f5e8dcb55c ]
+
+For Gen-1 targets like SDM845, it is seen that stressing out the
+controller in host mode results in HC died error:
+
+ xhci-hcd.12.auto: xHCI host not responding to stop endpoint command
+ xhci-hcd.12.auto: xHCI host controller not responding, assume dead
+ xhci-hcd.12.auto: HC died; cleaning up
+
+And at this instant only restarting the host mode fixes it. Disable
+SuperSpeed instance in park mode for SDM845 to mitigate this issue.
+
+Cc: stable@vger.kernel.org
+Fixes: ca4db2b538a1 ("arm64: dts: qcom: sdm845: Add USB-related nodes")
+Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20240704152848.3380602-9-quic_kriskura@quicinc.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sdm845.dtsi | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
+index abffd0ad6e90c..dcdc8a0cd1819 100644
+--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
++++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
+@@ -4080,6 +4080,7 @@ usb_1_dwc3: usb@a600000 {
+                               iommus = <&apps_smmu 0x740 0>;
+                               snps,dis_u2_susphy_quirk;
+                               snps,dis_enblslpm_quirk;
++                              snps,parkmode-disable-ss-quirk;
+                               phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
+                               phy-names = "usb2-phy", "usb3-phy";
+                       };
+@@ -4131,6 +4132,7 @@ usb_2_dwc3: usb@a800000 {
+                               iommus = <&apps_smmu 0x760 0>;
+                               snps,dis_u2_susphy_quirk;
+                               snps,dis_enblslpm_quirk;
++                              snps,parkmode-disable-ss-quirk;
+                               phys = <&usb_2_hsphy>, <&usb_2_qmpphy>;
+                               phy-names = "usb2-phy", "usb3-phy";
+                       };
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-dts-qcom-sdm845-switch-usb-dp-qmp-phy-to-new-s.patch b/queue-6.6/arm64-dts-qcom-sdm845-switch-usb-dp-qmp-phy-to-new-s.patch
new file mode 100644 (file)
index 0000000..f49a726
--- /dev/null
@@ -0,0 +1,132 @@
+From e107f476bf8765454a4764b74d807bc22558e61b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Jul 2023 15:09:14 +0300
+Subject: arm64: dts: qcom: sdm845: switch USB+DP QMP PHY to new style of
+ bindings
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit a9ecdec45a3a59057a68cf61ba4569d34caea5fc ]
+
+Change the USB QMP PHY to use newer style of QMP PHY bindings (single
+resource region, no per-PHY subnodes).
+
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20230711120916.4165894-9-dmitry.baryshkov@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Stable-dep-of: cf4d6d54eadb ("arm64: dts: qcom: sdm845: Disable SS instance in Parkmode for USB")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sdm845.dtsi | 57 ++++++++++------------------
+ 1 file changed, 19 insertions(+), 38 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
+index 9d9b378c07e14..494eac409ee9f 100644
+--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
++++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
+@@ -18,6 +18,7 @@
+ #include <dt-bindings/interconnect/qcom,osm-l3.h>
+ #include <dt-bindings/interconnect/qcom,sdm845.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
++#include <dt-bindings/phy/phy-qcom-qmp.h>
+ #include <dt-bindings/phy/phy-qcom-qusb2.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+ #include <dt-bindings/reset/qcom,sdm845-aoss.h>
+@@ -3983,49 +3984,28 @@ usb_2_hsphy: phy@88e3000 {
+                       nvmem-cells = <&qusb2s_hstx_trim>;
+               };
+-              usb_1_qmpphy: phy@88e9000 {
++              usb_1_qmpphy: phy@88e8000 {
+                       compatible = "qcom,sdm845-qmp-usb3-dp-phy";
+-                      reg = <0 0x088e9000 0 0x18c>,
+-                            <0 0x088e8000 0 0x38>,
+-                            <0 0x088ea000 0 0x40>;
++                      reg = <0 0x088e8000 0 0x3000>;
+                       status = "disabled";
+-                      #address-cells = <2>;
+-                      #size-cells = <2>;
+-                      ranges;
+                       clocks = <&gcc GCC_USB3_PRIM_PHY_AUX_CLK>,
+-                               <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+                                <&gcc GCC_USB3_PRIM_CLKREF_CLK>,
+-                               <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
+-                      clock-names = "aux", "cfg_ahb", "ref", "com_aux";
++                               <&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>,
++                               <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>,
++                               <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>;
++                      clock-names = "aux",
++                                    "ref",
++                                    "com_aux",
++                                    "usb3_pipe",
++                                    "cfg_ahb";
+                       resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
+                                <&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
+                       reset-names = "phy", "common";
+-                      usb_1_ssphy: usb3-phy@88e9200 {
+-                              reg = <0 0x088e9200 0 0x128>,
+-                                    <0 0x088e9400 0 0x200>,
+-                                    <0 0x088e9c00 0 0x218>,
+-                                    <0 0x088e9600 0 0x128>,
+-                                    <0 0x088e9800 0 0x200>,
+-                                    <0 0x088e9a00 0 0x100>;
+-                              #clock-cells = <0>;
+-                              #phy-cells = <0>;
+-                              clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+-                              clock-names = "pipe0";
+-                              clock-output-names = "usb3_phy_pipe_clk_src";
+-                      };
+-
+-                      dp_phy: dp-phy@88ea200 {
+-                              reg = <0 0x088ea200 0 0x200>,
+-                                    <0 0x088ea400 0 0x200>,
+-                                    <0 0x088eaa00 0 0x200>,
+-                                    <0 0x088ea600 0 0x200>,
+-                                    <0 0x088ea800 0 0x200>;
+-                              #clock-cells = <1>;
+-                              #phy-cells = <0>;
+-                      };
++                      #clock-cells = <1>;
++                      #phy-cells = <1>;
+               };
+               usb_2_qmpphy: phy@88eb000 {
+@@ -4105,7 +4085,7 @@ usb_1_dwc3: usb@a600000 {
+                               iommus = <&apps_smmu 0x740 0>;
+                               snps,dis_u2_susphy_quirk;
+                               snps,dis_enblslpm_quirk;
+-                              phys = <&usb_1_hsphy>, <&usb_1_ssphy>;
++                              phys = <&usb_1_hsphy>, <&usb_1_qmpphy QMP_USB43DP_USB3_PHY>;
+                               phy-names = "usb2-phy", "usb3-phy";
+                       };
+               };
+@@ -4573,8 +4553,9 @@ mdss_dp: displayport-controller@ae90000 {
+                                             "ctrl_link_iface", "stream_pixel";
+                               assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
+                                                 <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
+-                              assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>;
+-                              phys = <&dp_phy>;
++                              assigned-clock-parents = <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
++                                                       <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
++                              phys = <&usb_1_qmpphy QMP_USB43DP_DP_PHY>;
+                               phy-names = "dp";
+                               operating-points-v2 = <&dp_opp_table>;
+@@ -4912,8 +4893,8 @@ dispcc: clock-controller@af00000 {
+                                <&mdss_dsi0_phy 1>,
+                                <&mdss_dsi1_phy 0>,
+                                <&mdss_dsi1_phy 1>,
+-                               <&dp_phy 0>,
+-                               <&dp_phy 1>;
++                               <&usb_1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
++                               <&usb_1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
+                       clock-names = "bi_tcxo",
+                                     "gcc_disp_gpll0_clk_src",
+                                     "gcc_disp_gpll0_div_clk_src",
+-- 
+2.43.0
+
diff --git a/queue-6.6/arm64-dts-qcom-sdm845-switch-usb-qmp-phy-to-new-styl.patch b/queue-6.6/arm64-dts-qcom-sdm845-switch-usb-qmp-phy-to-new-styl.patch
new file mode 100644 (file)
index 0000000..4886e82
--- /dev/null
@@ -0,0 +1,87 @@
+From 14bf84cd632af11b20c9a30638e655ab2302a1f0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Aug 2023 00:19:47 +0300
+Subject: arm64: dts: qcom: sdm845: switch USB QMP PHY to new style of bindings
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit ca5ca568d7388b38039c8d658735fc539352b1db ]
+
+Change the USB QMP PHY to use newer style of QMP PHY bindings (single
+resource region, no per-PHY subnodes).
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20230824211952.1397699-12-dmitry.baryshkov@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Stable-dep-of: cf4d6d54eadb ("arm64: dts: qcom: sdm845: Disable SS instance in Parkmode for USB")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sdm845.dtsi | 39 ++++++++++++----------------
+ 1 file changed, 17 insertions(+), 22 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
+index 494eac409ee9f..abffd0ad6e90c 100644
+--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
++++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
+@@ -4010,33 +4010,28 @@ usb_1_qmpphy: phy@88e8000 {
+               usb_2_qmpphy: phy@88eb000 {
+                       compatible = "qcom,sdm845-qmp-usb3-uni-phy";
+-                      reg = <0 0x088eb000 0 0x18c>;
+-                      status = "disabled";
+-                      #address-cells = <2>;
+-                      #size-cells = <2>;
+-                      ranges;
++                      reg = <0 0x088eb000 0 0x1000>;
+                       clocks = <&gcc GCC_USB3_SEC_PHY_AUX_CLK>,
+                                <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+                                <&gcc GCC_USB3_SEC_CLKREF_CLK>,
+-                               <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>;
+-                      clock-names = "aux", "cfg_ahb", "ref", "com_aux";
++                               <&gcc GCC_USB3_SEC_PHY_COM_AUX_CLK>,
++                               <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
++                      clock-names = "aux",
++                                    "cfg_ahb",
++                                    "ref",
++                                    "com_aux",
++                                    "pipe";
++                      clock-output-names = "usb3_uni_phy_pipe_clk_src";
++                      #clock-cells = <0>;
++                      #phy-cells = <0>;
+-                      resets = <&gcc GCC_USB3PHY_PHY_SEC_BCR>,
+-                               <&gcc GCC_USB3_PHY_SEC_BCR>;
+-                      reset-names = "phy", "common";
++                      resets = <&gcc GCC_USB3_PHY_SEC_BCR>,
++                               <&gcc GCC_USB3PHY_PHY_SEC_BCR>;
++                      reset-names = "phy",
++                                    "phy_phy";
+-                      usb_2_ssphy: phy@88eb200 {
+-                              reg = <0 0x088eb200 0 0x128>,
+-                                    <0 0x088eb400 0 0x1fc>,
+-                                    <0 0x088eb800 0 0x218>,
+-                                    <0 0x088eb600 0 0x70>;
+-                              #clock-cells = <0>;
+-                              #phy-cells = <0>;
+-                              clocks = <&gcc GCC_USB3_SEC_PHY_PIPE_CLK>;
+-                              clock-names = "pipe0";
+-                              clock-output-names = "usb3_uni_phy_pipe_clk_src";
+-                      };
++                      status = "disabled";
+               };
+               usb_1: usb@a6f8800 {
+@@ -4136,7 +4131,7 @@ usb_2_dwc3: usb@a800000 {
+                               iommus = <&apps_smmu 0x760 0>;
+                               snps,dis_u2_susphy_quirk;
+                               snps,dis_enblslpm_quirk;
+-                              phys = <&usb_2_hsphy>, <&usb_2_ssphy>;
++                              phys = <&usb_2_hsphy>, <&usb_2_qmpphy>;
+                               phy-names = "usb2-phy", "usb3-phy";
+                       };
+               };
+-- 
+2.43.0
+
diff --git a/queue-6.6/cpufreq-qcom-nvmem-fix-memory-leaks-in-probe-error-p.patch b/queue-6.6/cpufreq-qcom-nvmem-fix-memory-leaks-in-probe-error-p.patch
new file mode 100644 (file)
index 0000000..9606a3e
--- /dev/null
@@ -0,0 +1,65 @@
+From 3b6f27b5250d0d617b0a74fa9c346bbfb0295a5c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 May 2024 23:24:59 +0200
+Subject: cpufreq: qcom-nvmem: fix memory leaks in probe error paths
+
+From: Javier Carrasco <javier.carrasco.cruz@gmail.com>
+
+[ Upstream commit d01c84b97f19f1137211e90b0a910289a560019e ]
+
+The code refactoring added new error paths between the np device node
+allocation and the call to of_node_put(), which leads to memory leaks if
+any of those errors occur.
+
+Add the missing of_node_put() in the error paths that require it.
+
+Cc: stable@vger.kernel.org
+Fixes: 57f2f8b4aa0c ("cpufreq: qcom: Refactor the driver to make it easier to extend")
+Signed-off-by: Javier Carrasco <javier.carrasco.cruz@gmail.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/qcom-cpufreq-nvmem.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+index 03586fee15aac..ef51dfb39baa9 100644
+--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+@@ -249,23 +249,30 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
+       drv = devm_kzalloc(&pdev->dev, struct_size(drv, cpus, num_possible_cpus()),
+                          GFP_KERNEL);
+-      if (!drv)
++      if (!drv) {
++              of_node_put(np);
+               return -ENOMEM;
++      }
+       match = pdev->dev.platform_data;
+       drv->data = match->data;
+-      if (!drv->data)
++      if (!drv->data) {
++              of_node_put(np);
+               return -ENODEV;
++      }
+       if (drv->data->get_version) {
+               speedbin_nvmem = of_nvmem_cell_get(np, NULL);
+-              if (IS_ERR(speedbin_nvmem))
++              if (IS_ERR(speedbin_nvmem)) {
++                      of_node_put(np);
+                       return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
+                                            "Could not get nvmem cell\n");
++              }
+               ret = drv->data->get_version(cpu_dev,
+                                                       speedbin_nvmem, &pvs_name, drv);
+               if (ret) {
++                      of_node_put(np);
+                       nvmem_cell_put(speedbin_nvmem);
+                       return ret;
+               }
+-- 
+2.43.0
+
diff --git a/queue-6.6/cpufreq-qcom-nvmem-simplify-driver-data-allocation.patch b/queue-6.6/cpufreq-qcom-nvmem-simplify-driver-data-allocation.patch
new file mode 100644 (file)
index 0000000..ead44d2
--- /dev/null
@@ -0,0 +1,135 @@
+From c160679379f5a41cb3811d06ab586e5357d4e3c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 Oct 2023 10:06:02 +0200
+Subject: cpufreq: qcom-nvmem: Simplify driver data allocation
+
+From: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
+
+[ Upstream commit 2a5d46c3ad6b0e62d2b04356ad999d504fb564e0 ]
+
+Simplify the allocation and cleanup of driver data by using devm
+together with a flexible array. Prepare for adding additional per-CPU
+data by defining a struct qcom_cpufreq_drv_cpu instead of storing the
+opp_tokens directly.
+
+Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Stable-dep-of: d01c84b97f19 ("cpufreq: qcom-nvmem: fix memory leaks in probe error paths")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/qcom-cpufreq-nvmem.c | 49 ++++++++++------------------
+ 1 file changed, 18 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+index 84d7033e5efe8..03586fee15aac 100644
+--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+@@ -40,10 +40,14 @@ struct qcom_cpufreq_match_data {
+       const char **genpd_names;
+ };
++struct qcom_cpufreq_drv_cpu {
++      int opp_token;
++};
++
+ struct qcom_cpufreq_drv {
+-      int *opp_tokens;
+       u32 versions;
+       const struct qcom_cpufreq_match_data *data;
++      struct qcom_cpufreq_drv_cpu cpus[];
+ };
+ static struct platform_device *cpufreq_dt_pdev, *cpufreq_pdev;
+@@ -243,42 +247,32 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
+               return -ENOENT;
+       }
+-      drv = kzalloc(sizeof(*drv), GFP_KERNEL);
++      drv = devm_kzalloc(&pdev->dev, struct_size(drv, cpus, num_possible_cpus()),
++                         GFP_KERNEL);
+       if (!drv)
+               return -ENOMEM;
+       match = pdev->dev.platform_data;
+       drv->data = match->data;
+-      if (!drv->data) {
+-              ret = -ENODEV;
+-              goto free_drv;
+-      }
++      if (!drv->data)
++              return -ENODEV;
+       if (drv->data->get_version) {
+               speedbin_nvmem = of_nvmem_cell_get(np, NULL);
+-              if (IS_ERR(speedbin_nvmem)) {
+-                      ret = dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
+-                                          "Could not get nvmem cell\n");
+-                      goto free_drv;
+-              }
++              if (IS_ERR(speedbin_nvmem))
++                      return dev_err_probe(cpu_dev, PTR_ERR(speedbin_nvmem),
++                                           "Could not get nvmem cell\n");
+               ret = drv->data->get_version(cpu_dev,
+                                                       speedbin_nvmem, &pvs_name, drv);
+               if (ret) {
+                       nvmem_cell_put(speedbin_nvmem);
+-                      goto free_drv;
++                      return ret;
+               }
+               nvmem_cell_put(speedbin_nvmem);
+       }
+       of_node_put(np);
+-      drv->opp_tokens = kcalloc(num_possible_cpus(), sizeof(*drv->opp_tokens),
+-                                GFP_KERNEL);
+-      if (!drv->opp_tokens) {
+-              ret = -ENOMEM;
+-              goto free_drv;
+-      }
+-
+       for_each_possible_cpu(cpu) {
+               struct dev_pm_opp_config config = {
+                       .supported_hw = NULL,
+@@ -304,9 +298,9 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
+               }
+               if (config.supported_hw || config.genpd_names) {
+-                      drv->opp_tokens[cpu] = dev_pm_opp_set_config(cpu_dev, &config);
+-                      if (drv->opp_tokens[cpu] < 0) {
+-                              ret = drv->opp_tokens[cpu];
++                      drv->cpus[cpu].opp_token = dev_pm_opp_set_config(cpu_dev, &config);
++                      if (drv->cpus[cpu].opp_token < 0) {
++                              ret = drv->cpus[cpu].opp_token;
+                               dev_err(cpu_dev, "Failed to set OPP config\n");
+                               goto free_opp;
+                       }
+@@ -325,11 +319,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
+ free_opp:
+       for_each_possible_cpu(cpu)
+-              dev_pm_opp_clear_config(drv->opp_tokens[cpu]);
+-      kfree(drv->opp_tokens);
+-free_drv:
+-      kfree(drv);
+-
++              dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
+       return ret;
+ }
+@@ -341,10 +331,7 @@ static void qcom_cpufreq_remove(struct platform_device *pdev)
+       platform_device_unregister(cpufreq_dt_pdev);
+       for_each_possible_cpu(cpu)
+-              dev_pm_opp_clear_config(drv->opp_tokens[cpu]);
+-
+-      kfree(drv->opp_tokens);
+-      kfree(drv);
++              dev_pm_opp_clear_config(drv->cpus[cpu].opp_token);
+ }
+ static struct platform_driver qcom_cpufreq_driver = {
+-- 
+2.43.0
+
diff --git a/queue-6.6/dmaengine-fsl-edma-add-address-for-channel-mux-regis.patch b/queue-6.6/dmaengine-fsl-edma-add-address-for-channel-mux-regis.patch
new file mode 100644 (file)
index 0000000..c3b3013
--- /dev/null
@@ -0,0 +1,95 @@
+From bb334457797da6b70683c6c8ac71826261f43c2d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Dec 2023 10:35:25 -0500
+Subject: dmaengine: fsl-edma: add address for channel mux register in
+ fsl_edma_chan
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit e0a08ed25492b6437e366b347113db484037b9b9 ]
+
+iMX95 move channel mux register to management page address space. This
+prepare to support iMX95.
+
+Add mux_addr in struct fsl_edma_chan. No function change.
+
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20231221153528.1588049-4-Frank.Li@nxp.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: 8ddad5589970 ("dmaengine: fsl-edma: change the memory access from local into remote mode in i.MX 8QM")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/fsl-edma-common.c | 6 +++---
+ drivers/dma/fsl-edma-common.h | 3 +++
+ drivers/dma/fsl-edma-main.c   | 3 +++
+ 3 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
+index 793f1a7ad5e34..d42e48ce5de44 100644
+--- a/drivers/dma/fsl-edma-common.c
++++ b/drivers/dma/fsl-edma-common.c
+@@ -97,8 +97,8 @@ static void fsl_edma3_enable_request(struct fsl_edma_chan *fsl_chan)
+                * ch_mux: With the exception of 0, attempts to write a value
+                * already in use will be forced to 0.
+                */
+-              if (!edma_readl_chreg(fsl_chan, ch_mux))
+-                      edma_writel_chreg(fsl_chan, fsl_chan->srcid, ch_mux);
++              if (!edma_readl(fsl_chan->edma, fsl_chan->mux_addr))
++                      edma_writel(fsl_chan->edma, fsl_chan->srcid, fsl_chan->mux_addr);
+       }
+       val = edma_readl_chreg(fsl_chan, ch_csr);
+@@ -134,7 +134,7 @@ static void fsl_edma3_disable_request(struct fsl_edma_chan *fsl_chan)
+       flags = fsl_edma_drvflags(fsl_chan);
+       if (flags & FSL_EDMA_DRV_HAS_CHMUX)
+-              edma_writel_chreg(fsl_chan, 0, ch_mux);
++              edma_writel(fsl_chan->edma, 0, fsl_chan->mux_addr);
+       val &= ~EDMA_V3_CH_CSR_ERQ;
+       edma_writel_chreg(fsl_chan, val, ch_csr);
+diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
+index 92fe53faa53b1..b567da379fc33 100644
+--- a/drivers/dma/fsl-edma-common.h
++++ b/drivers/dma/fsl-edma-common.h
+@@ -146,6 +146,7 @@ struct fsl_edma_chan {
+       enum dma_data_direction         dma_dir;
+       char                            chan_name[32];
+       struct fsl_edma_hw_tcd __iomem *tcd;
++      void __iomem                    *mux_addr;
+       u32                             real_count;
+       struct work_struct              issue_worker;
+       struct platform_device          *pdev;
+@@ -207,6 +208,8 @@ struct fsl_edma_drvdata {
+       u32                     chreg_off;
+       u32                     chreg_space_sz;
+       u32                     flags;
++      u32                     mux_off;        /* channel mux register offset */
++      u32                     mux_skip;       /* how much skip for each channel */
+       int                     (*setup_irq)(struct platform_device *pdev,
+                                            struct fsl_edma_engine *fsl_edma);
+ };
+diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
+index 42a338cbe6143..de4f548f0ad87 100644
+--- a/drivers/dma/fsl-edma-main.c
++++ b/drivers/dma/fsl-edma-main.c
+@@ -364,6 +364,8 @@ static struct fsl_edma_drvdata imx93_data4 = {
+       .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA4,
+       .chreg_space_sz = 0x8000,
+       .chreg_off = 0x10000,
++      .mux_off = 0x10000 + offsetof(struct fsl_edma3_ch_reg, ch_mux),
++      .mux_skip = 0x8000,
+       .setup_irq = fsl_edma3_irq_init,
+ };
+@@ -540,6 +542,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
+                               offsetof(struct fsl_edma3_ch_reg, tcd) : 0;
+               fsl_chan->tcd = fsl_edma->membase
+                               + i * drvdata->chreg_space_sz + drvdata->chreg_off + len;
++              fsl_chan->mux_addr = fsl_edma->membase + drvdata->mux_off + i * drvdata->mux_skip;
+               fsl_chan->pdev = pdev;
+               vchan_init(&fsl_chan->vchan, &fsl_edma->dma_dev);
+-- 
+2.43.0
+
diff --git a/queue-6.6/dmaengine-fsl-edma-add-i.mx8ulp-edma-support.patch b/queue-6.6/dmaengine-fsl-edma-add-i.mx8ulp-edma-support.patch
new file mode 100644 (file)
index 0000000..e3e086f
--- /dev/null
@@ -0,0 +1,117 @@
+From ed5b2515122d9dc42b0dbef544e384b942c4d79a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 Mar 2024 11:34:54 -0400
+Subject: dmaengine: fsl-edma: add i.MX8ULP edma support
+
+From: Joy Zou <joy.zou@nxp.com>
+
+[ Upstream commit d8d4355861d874cbd1395ec0edcbe4e0f6940738 ]
+
+Add support for the i.MX8ULP platform to the eDMA driver. Introduce the use
+of the correct FSL_EDMA_DRV_HAS_CHCLK flag to handle per-channel clock
+configurations.
+
+Signed-off-by: Joy Zou <joy.zou@nxp.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20240323-8ulp_edma-v3-5-c0e981027c05@nxp.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: 8ddad5589970 ("dmaengine: fsl-edma: change the memory access from local into remote mode in i.MX 8QM")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/fsl-edma-common.c |  6 ++++++
+ drivers/dma/fsl-edma-main.c   | 22 ++++++++++++++++++++++
+ 2 files changed, 28 insertions(+)
+
+diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
+index d42e48ce5de44..12e605a756cad 100644
+--- a/drivers/dma/fsl-edma-common.c
++++ b/drivers/dma/fsl-edma-common.c
+@@ -3,6 +3,7 @@
+ // Copyright (c) 2013-2014 Freescale Semiconductor, Inc
+ // Copyright (c) 2017 Sysam, Angelo Dureghello  <angelo@sysam.it>
++#include <linux/clk.h>
+ #include <linux/dmapool.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+@@ -802,6 +803,9 @@ int fsl_edma_alloc_chan_resources(struct dma_chan *chan)
+ {
+       struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
++      if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK)
++              clk_prepare_enable(fsl_chan->clk);
++
+       fsl_chan->tcd_pool = dma_pool_create("tcd_pool", chan->device->dev,
+                               sizeof(struct fsl_edma_hw_tcd),
+                               32, 0);
+@@ -829,6 +833,8 @@ void fsl_edma_free_chan_resources(struct dma_chan *chan)
+       fsl_chan->tcd_pool = NULL;
+       fsl_chan->is_sw = false;
+       fsl_chan->srcid = 0;
++      if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK)
++              clk_disable_unprepare(fsl_chan->clk);
+ }
+ void fsl_edma_cleanup_vchan(struct dma_device *dmadev)
+diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
+index de4f548f0ad87..4a3edba315887 100644
+--- a/drivers/dma/fsl-edma-main.c
++++ b/drivers/dma/fsl-edma-main.c
+@@ -353,6 +353,16 @@ static struct fsl_edma_drvdata imx8qm_audio_data = {
+       .setup_irq = fsl_edma3_irq_init,
+ };
++static struct fsl_edma_drvdata imx8ulp_data = {
++      .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_CHCLK | FSL_EDMA_DRV_HAS_DMACLK |
++               FSL_EDMA_DRV_EDMA3,
++      .chreg_space_sz = 0x10000,
++      .chreg_off = 0x10000,
++      .mux_off = 0x10000 + offsetof(struct fsl_edma3_ch_reg, ch_mux),
++      .mux_skip = 0x10000,
++      .setup_irq = fsl_edma3_irq_init,
++};
++
+ static struct fsl_edma_drvdata imx93_data3 = {
+       .flags = FSL_EDMA_DRV_HAS_DMACLK | FSL_EDMA_DRV_EDMA3,
+       .chreg_space_sz = 0x10000,
+@@ -375,6 +385,7 @@ static const struct of_device_id fsl_edma_dt_ids[] = {
+       { .compatible = "fsl,imx7ulp-edma", .data = &imx7ulp_data},
+       { .compatible = "fsl,imx8qm-edma", .data = &imx8qm_data},
+       { .compatible = "fsl,imx8qm-adma", .data = &imx8qm_audio_data},
++      { .compatible = "fsl,imx8ulp-edma", .data = &imx8ulp_data},
+       { .compatible = "fsl,imx93-edma3", .data = &imx93_data3},
+       { .compatible = "fsl,imx93-edma4", .data = &imx93_data4},
+       { /* sentinel */ }
+@@ -429,6 +440,7 @@ static int fsl_edma_probe(struct platform_device *pdev)
+       struct fsl_edma_engine *fsl_edma;
+       const struct fsl_edma_drvdata *drvdata = NULL;
+       u32 chan_mask[2] = {0, 0};
++      char clk_name[36];
+       struct edma_regs *regs;
+       int chans;
+       int ret, i;
+@@ -544,11 +556,21 @@ static int fsl_edma_probe(struct platform_device *pdev)
+                               + i * drvdata->chreg_space_sz + drvdata->chreg_off + len;
+               fsl_chan->mux_addr = fsl_edma->membase + drvdata->mux_off + i * drvdata->mux_skip;
++              if (drvdata->flags & FSL_EDMA_DRV_HAS_CHCLK) {
++                      snprintf(clk_name, sizeof(clk_name), "ch%02d", i);
++                      fsl_chan->clk = devm_clk_get_enabled(&pdev->dev,
++                                                           (const char *)clk_name);
++
++                      if (IS_ERR(fsl_chan->clk))
++                              return PTR_ERR(fsl_chan->clk);
++              }
+               fsl_chan->pdev = pdev;
+               vchan_init(&fsl_chan->vchan, &fsl_edma->dma_dev);
+               edma_write_tcdreg(fsl_chan, 0, csr);
+               fsl_edma_chan_mux(fsl_chan, 0, false);
++              if (fsl_chan->edma->drvdata->flags & FSL_EDMA_DRV_HAS_CHCLK)
++                      clk_disable_unprepare(fsl_chan->clk);
+       }
+       ret = fsl_edma->drvdata->setup_irq(pdev, fsl_edma);
+-- 
+2.43.0
+
diff --git a/queue-6.6/dmaengine-fsl-edma-change-the-memory-access-from-loc.patch b/queue-6.6/dmaengine-fsl-edma-change-the-memory-access-from-loc.patch
new file mode 100644 (file)
index 0000000..dad1c51
--- /dev/null
@@ -0,0 +1,89 @@
+From 66c4fd587d3c9e3fc37aa426684c8aaf09d0f8ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 May 2024 11:09:34 +0800
+Subject: dmaengine: fsl-edma: change the memory access from local into remote
+ mode in i.MX 8QM
+
+From: Joy Zou <joy.zou@nxp.com>
+
+[ Upstream commit 8ddad558997002ce67980e30c9e8dfaa696e163b ]
+
+Fix the issue where MEM_TO_MEM fail on i.MX8QM due to the requirement
+that both source and destination addresses need pass through the IOMMU.
+Typically, peripheral FIFO addresses bypass the IOMMU, necessitating
+only one of the source or destination to go through it.
+
+Set "is_remote" to true to ensure both source and destination
+addresses pass through the IOMMU.
+
+iMX8 Spec define "Local" and "Remote" bus as below.
+Local bus: bypass IOMMU to directly access other peripheral register,
+such as FIFO.
+Remote bus: go through IOMMU to access system memory.
+
+The test fail log as follow:
+[ 66.268506] dmatest: dma0chan0-copy0: result #1: 'test timed out' with src_off=0x100 dst_off=0x80 len=0x3ec0 (0)
+[ 66.278785] dmatest: dma0chan0-copy0: summary 1 tests, 1 failures 0.32 iops 4 KB/s (0)
+
+Fixes: 72f5801a4e2b ("dmaengine: fsl-edma: integrate v3 support")
+Signed-off-by: Joy Zou <joy.zou@nxp.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20240510030959.703663-1-joy.zou@nxp.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/fsl-edma-common.c | 3 +++
+ drivers/dma/fsl-edma-common.h | 1 +
+ drivers/dma/fsl-edma-main.c   | 2 +-
+ 3 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
+index a1ac404977fd8..53fdfd32a7e77 100644
+--- a/drivers/dma/fsl-edma-common.c
++++ b/drivers/dma/fsl-edma-common.c
+@@ -747,6 +747,8 @@ struct dma_async_tx_descriptor *fsl_edma_prep_memcpy(struct dma_chan *chan,
+       fsl_desc->iscyclic = false;
+       fsl_chan->is_sw = true;
++      if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_MEM_REMOTE)
++              fsl_chan->is_remote = true;
+       /* To match with copy_align and max_seg_size so 1 tcd is enough */
+       fsl_edma_fill_tcd(fsl_chan, fsl_desc->tcd[0].vtcd, dma_src, dma_dst,
+@@ -825,6 +827,7 @@ void fsl_edma_free_chan_resources(struct dma_chan *chan)
+       fsl_chan->tcd_pool = NULL;
+       fsl_chan->is_sw = false;
+       fsl_chan->srcid = 0;
++      fsl_chan->is_remote = false;
+       if (fsl_edma_drvflags(fsl_chan) & FSL_EDMA_DRV_HAS_CHCLK)
+               clk_disable_unprepare(fsl_chan->clk);
+ }
+diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
+index 20e29a42fcd8d..6028389de408b 100644
+--- a/drivers/dma/fsl-edma-common.h
++++ b/drivers/dma/fsl-edma-common.h
+@@ -178,6 +178,7 @@ struct fsl_edma_desc {
+ #define FSL_EDMA_DRV_HAS_PD           BIT(5)
+ #define FSL_EDMA_DRV_HAS_CHCLK                BIT(6)
+ #define FSL_EDMA_DRV_HAS_CHMUX                BIT(7)
++#define FSL_EDMA_DRV_MEM_REMOTE               BIT(8)
+ /* control and status register is in tcd address space, edma3 reg layout */
+ #define FSL_EDMA_DRV_SPLIT_REG                BIT(9)
+ #define FSL_EDMA_DRV_BUS_8BYTE                BIT(10)
+diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
+index c96b893d2ac35..8a0ae90548997 100644
+--- a/drivers/dma/fsl-edma-main.c
++++ b/drivers/dma/fsl-edma-main.c
+@@ -340,7 +340,7 @@ static struct fsl_edma_drvdata imx7ulp_data = {
+ };
+ static struct fsl_edma_drvdata imx8qm_data = {
+-      .flags = FSL_EDMA_DRV_HAS_PD | FSL_EDMA_DRV_EDMA3,
++      .flags = FSL_EDMA_DRV_HAS_PD | FSL_EDMA_DRV_EDMA3 | FSL_EDMA_DRV_MEM_REMOTE,
+       .chreg_space_sz = 0x10000,
+       .chreg_off = 0x10000,
+       .setup_irq = fsl_edma3_irq_init,
+-- 
+2.43.0
+
diff --git a/queue-6.6/dmaengine-fsl-edma-clean-up-unused-fsl-imx8qm-adma-c.patch b/queue-6.6/dmaengine-fsl-edma-clean-up-unused-fsl-imx8qm-adma-c.patch
new file mode 100644 (file)
index 0000000..d6e301b
--- /dev/null
@@ -0,0 +1,94 @@
+From f342365f0faf711ff1b64c6ab6ffe9a48647c968 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Apr 2024 14:45:07 +0800
+Subject: dmaengine: fsl-edma: clean up unused "fsl,imx8qm-adma" compatible
+ string
+
+From: Joy Zou <joy.zou@nxp.com>
+
+[ Upstream commit 77584368a0f3d9eba112c3df69f1df7f282dbfe9 ]
+
+The eDMA hardware issue only exist imx8QM A0. A0 never mass production.
+So remove the workaround safely.
+
+Signed-off-by: Joy Zou <joy.zou@nxp.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20240424064508.1886764-2-joy.zou@nxp.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: 8ddad5589970 ("dmaengine: fsl-edma: change the memory access from local into remote mode in i.MX 8QM")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/fsl-edma-common.c | 16 ++++------------
+ drivers/dma/fsl-edma-common.h |  2 --
+ drivers/dma/fsl-edma-main.c   |  8 --------
+ 3 files changed, 4 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
+index 12e605a756cad..a1ac404977fd8 100644
+--- a/drivers/dma/fsl-edma-common.c
++++ b/drivers/dma/fsl-edma-common.c
+@@ -75,18 +75,10 @@ static void fsl_edma3_enable_request(struct fsl_edma_chan *fsl_chan)
+       flags = fsl_edma_drvflags(fsl_chan);
+       val = edma_readl_chreg(fsl_chan, ch_sbr);
+-      /* Remote/local swapped wrongly on iMX8 QM Audio edma */
+-      if (flags & FSL_EDMA_DRV_QUIRK_SWAPPED) {
+-              if (!fsl_chan->is_rxchan)
+-                      val |= EDMA_V3_CH_SBR_RD;
+-              else
+-                      val |= EDMA_V3_CH_SBR_WR;
+-      } else {
+-              if (fsl_chan->is_rxchan)
+-                      val |= EDMA_V3_CH_SBR_RD;
+-              else
+-                      val |= EDMA_V3_CH_SBR_WR;
+-      }
++      if (fsl_chan->is_rxchan)
++              val |= EDMA_V3_CH_SBR_RD;
++      else
++              val |= EDMA_V3_CH_SBR_WR;
+       if (fsl_chan->is_remote)
+               val &= ~(EDMA_V3_CH_SBR_RD | EDMA_V3_CH_SBR_WR);
+diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
+index b567da379fc33..20e29a42fcd8d 100644
+--- a/drivers/dma/fsl-edma-common.h
++++ b/drivers/dma/fsl-edma-common.h
+@@ -178,8 +178,6 @@ struct fsl_edma_desc {
+ #define FSL_EDMA_DRV_HAS_PD           BIT(5)
+ #define FSL_EDMA_DRV_HAS_CHCLK                BIT(6)
+ #define FSL_EDMA_DRV_HAS_CHMUX                BIT(7)
+-/* imx8 QM audio edma remote local swapped */
+-#define FSL_EDMA_DRV_QUIRK_SWAPPED    BIT(8)
+ /* control and status register is in tcd address space, edma3 reg layout */
+ #define FSL_EDMA_DRV_SPLIT_REG                BIT(9)
+ #define FSL_EDMA_DRV_BUS_8BYTE                BIT(10)
+diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
+index 4a3edba315887..c96b893d2ac35 100644
+--- a/drivers/dma/fsl-edma-main.c
++++ b/drivers/dma/fsl-edma-main.c
+@@ -346,13 +346,6 @@ static struct fsl_edma_drvdata imx8qm_data = {
+       .setup_irq = fsl_edma3_irq_init,
+ };
+-static struct fsl_edma_drvdata imx8qm_audio_data = {
+-      .flags = FSL_EDMA_DRV_QUIRK_SWAPPED | FSL_EDMA_DRV_HAS_PD | FSL_EDMA_DRV_EDMA3,
+-      .chreg_space_sz = 0x10000,
+-      .chreg_off = 0x10000,
+-      .setup_irq = fsl_edma3_irq_init,
+-};
+-
+ static struct fsl_edma_drvdata imx8ulp_data = {
+       .flags = FSL_EDMA_DRV_HAS_CHMUX | FSL_EDMA_DRV_HAS_CHCLK | FSL_EDMA_DRV_HAS_DMACLK |
+                FSL_EDMA_DRV_EDMA3,
+@@ -384,7 +377,6 @@ static const struct of_device_id fsl_edma_dt_ids[] = {
+       { .compatible = "fsl,ls1028a-edma", .data = &ls1028a_data},
+       { .compatible = "fsl,imx7ulp-edma", .data = &imx7ulp_data},
+       { .compatible = "fsl,imx8qm-edma", .data = &imx8qm_data},
+-      { .compatible = "fsl,imx8qm-adma", .data = &imx8qm_audio_data},
+       { .compatible = "fsl,imx8ulp-edma", .data = &imx8ulp_data},
+       { .compatible = "fsl,imx93-edma3", .data = &imx93_data3},
+       { .compatible = "fsl,imx93-edma4", .data = &imx93_data4},
+-- 
+2.43.0
+
diff --git a/queue-6.6/ext4-check-the-extent-status-again-before-inserting-.patch b/queue-6.6/ext4-check-the-extent-status-again-before-inserting-.patch
new file mode 100644 (file)
index 0000000..7778c0f
--- /dev/null
@@ -0,0 +1,100 @@
+From 23136c890b3cbe78363afb1ff1b7ad4a10b684dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 May 2024 20:39:57 +0800
+Subject: ext4: check the extent status again before inserting delalloc block
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ Upstream commit 0ea6560abb3bac1ffcfa4bf6b2c4d344fdc27b3c ]
+
+ext4_da_map_blocks looks up for any extent entry in the extent status
+tree (w/o i_data_sem) and then the looks up for any ondisk extent
+mapping (with i_data_sem in read mode).
+
+If it finds a hole in the extent status tree or if it couldn't find any
+entry at all, it then takes the i_data_sem in write mode to add a da
+entry into the extent status tree. This can actually race with page
+mkwrite & fallocate path.
+
+Note that this is ok between
+1. ext4 buffered-write path v/s ext4_page_mkwrite(), because of the
+   folio lock
+2. ext4 buffered write path v/s ext4 fallocate because of the inode
+   lock.
+
+But this can race between ext4_page_mkwrite() & ext4 fallocate path
+
+ext4_page_mkwrite()             ext4_fallocate()
+ block_page_mkwrite()
+  ext4_da_map_blocks()
+   //find hole in extent status tree
+                                 ext4_alloc_file_blocks()
+                                  ext4_map_blocks()
+                                   //allocate block and unwritten extent
+   ext4_insert_delayed_block()
+    ext4_da_reserve_space()
+     //reserve one more block
+    ext4_es_insert_delayed_block()
+     //drop unwritten extent and add delayed extent by mistake
+
+Then, the delalloc extent is wrong until writeback and the extra
+reserved block can't be released any more and it triggers below warning:
+
+ EXT4-fs (pmem2): Inode 13 (00000000bbbd4d23): i_reserved_data_blocks(1) not cleared!
+
+Fix the problem by looking up extent status tree again while the
+i_data_sem is held in write mode. If it still can't find any entry, then
+we insert a new da entry into the extent status tree.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240517124005.347221-3-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index b8b2f731f1d0e..cef119a2476bb 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1737,6 +1737,7 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+               if (ext4_es_is_hole(&es))
+                       goto add_delayed;
++found:
+               /*
+                * Delayed extent could be allocated by fallocate.
+                * So we need to check it.
+@@ -1781,6 +1782,26 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+ add_delayed:
+       down_write(&EXT4_I(inode)->i_data_sem);
++      /*
++       * Page fault path (ext4_page_mkwrite does not take i_rwsem)
++       * and fallocate path (no folio lock) can race. Make sure we
++       * lookup the extent status tree here again while i_data_sem
++       * is held in write mode, before inserting a new da entry in
++       * the extent status tree.
++       */
++      if (ext4_es_lookup_extent(inode, iblock, NULL, &es)) {
++              if (!ext4_es_is_hole(&es)) {
++                      up_write(&EXT4_I(inode)->i_data_sem);
++                      goto found;
++              }
++      } else if (!ext4_has_inline_data(inode)) {
++              retval = ext4_map_query_blocks(NULL, inode, map);
++              if (retval) {
++                      up_write(&EXT4_I(inode)->i_data_sem);
++                      return retval;
++              }
++      }
++
+       retval = ext4_insert_delayed_block(inode, map->m_lblk);
+       up_write(&EXT4_I(inode)->i_data_sem);
+       if (retval)
+-- 
+2.43.0
+
diff --git a/queue-6.6/ext4-convert-to-exclusive-lock-while-inserting-delal.patch b/queue-6.6/ext4-convert-to-exclusive-lock-while-inserting-delal.patch
new file mode 100644 (file)
index 0000000..f3c6ece
--- /dev/null
@@ -0,0 +1,114 @@
+From d3ff186b36bc2b970221ca5db8b8d72cba4874fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 27 Jan 2024 09:58:01 +0800
+Subject: ext4: convert to exclusive lock while inserting delalloc extents
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ Upstream commit acf795dc161f3cf481db20f05db4250714e375e5 ]
+
+ext4_da_map_blocks() only hold i_data_sem in shared mode and i_rwsem
+when inserting delalloc extents, it could be raced by another querying
+path of ext4_map_blocks() without i_rwsem, .e.g buffered read path.
+Suppose we buffered read a file containing just a hole, and without any
+cached extents tree, then it is raced by another delayed buffered write
+to the same area or the near area belongs to the same hole, and the new
+delalloc extent could be overwritten to a hole extent.
+
+ pread()                           pwrite()
+  filemap_read_folio()
+   ext4_mpage_readpages()
+    ext4_map_blocks()
+     down_read(i_data_sem)
+     ext4_ext_determine_hole()
+     //find hole
+     ext4_ext_put_gap_in_cache()
+      ext4_es_find_extent_range()
+      //no delalloc extent
+                                    ext4_da_map_blocks()
+                                     down_read(i_data_sem)
+                                     ext4_insert_delayed_block()
+                                     //insert delalloc extent
+      ext4_es_insert_extent()
+      //overwrite delalloc extent to hole
+
+This race could lead to inconsistent delalloc extents tree and
+incorrect reserved space counter. Fix this by converting to hold
+i_data_sem in exclusive mode when adding a new delalloc extent in
+ext4_da_map_blocks().
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Suggested-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20240127015825.1608160-3-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 0ea6560abb3b ("ext4: check the extent status again before inserting delalloc block")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 25 +++++++++++--------------
+ 1 file changed, 11 insertions(+), 14 deletions(-)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index b8eab9cf36b98..c8a1db2164dfb 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1705,10 +1705,8 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+       /* Lookup extent status tree firstly */
+       if (ext4_es_lookup_extent(inode, iblock, NULL, &es)) {
+-              if (ext4_es_is_hole(&es)) {
+-                      down_read(&EXT4_I(inode)->i_data_sem);
++              if (ext4_es_is_hole(&es))
+                       goto add_delayed;
+-              }
+               /*
+                * Delayed extent could be allocated by fallocate.
+@@ -1750,8 +1748,10 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+               retval = ext4_ext_map_blocks(NULL, inode, map, 0);
+       else
+               retval = ext4_ind_map_blocks(NULL, inode, map, 0);
+-      if (retval < 0)
+-              goto out_unlock;
++      if (retval < 0) {
++              up_read(&EXT4_I(inode)->i_data_sem);
++              return retval;
++      }
+       if (retval > 0) {
+               unsigned int status;
+@@ -1767,24 +1767,21 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+                               EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
+               ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
+                                     map->m_pblk, status);
+-              goto out_unlock;
++              up_read(&EXT4_I(inode)->i_data_sem);
++              return retval;
+       }
++      up_read(&EXT4_I(inode)->i_data_sem);
+ add_delayed:
+-      /*
+-       * XXX: __block_prepare_write() unmaps passed block,
+-       * is it OK?
+-       */
++      down_write(&EXT4_I(inode)->i_data_sem);
+       retval = ext4_insert_delayed_block(inode, map->m_lblk);
++      up_write(&EXT4_I(inode)->i_data_sem);
+       if (retval)
+-              goto out_unlock;
++              return retval;
+       map_bh(bh, inode->i_sb, invalid_block);
+       set_buffer_new(bh);
+       set_buffer_delay(bh);
+-
+-out_unlock:
+-      up_read((&EXT4_I(inode)->i_data_sem));
+       return retval;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/ext4-factor-out-a-common-helper-to-query-extent-map.patch b/queue-6.6/ext4-factor-out-a-common-helper-to-query-extent-map.patch
new file mode 100644 (file)
index 0000000..2bfb574
--- /dev/null
@@ -0,0 +1,104 @@
+From 00632e1b1d3ee374b3058c12f3e1cb65358131df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 May 2024 20:39:56 +0800
+Subject: ext4: factor out a common helper to query extent map
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ Upstream commit 8e4e5cdf2fdeb99445a468b6b6436ad79b9ecb30 ]
+
+Factor out a new common helper ext4_map_query_blocks() from the
+ext4_da_map_blocks(), it query and return the extent map status on the
+inode's extent path, no logic changes.
+
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Link: https://patch.msgid.link/20240517124005.347221-2-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 0ea6560abb3b ("ext4: check the extent status again before inserting delalloc block")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 57 +++++++++++++++++++++++++++----------------------
+ 1 file changed, 32 insertions(+), 25 deletions(-)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index c8a1db2164dfb..b8b2f731f1d0e 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -453,6 +453,35 @@ static void ext4_map_blocks_es_recheck(handle_t *handle,
+ }
+ #endif /* ES_AGGRESSIVE_TEST */
++static int ext4_map_query_blocks(handle_t *handle, struct inode *inode,
++                               struct ext4_map_blocks *map)
++{
++      unsigned int status;
++      int retval;
++
++      if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
++              retval = ext4_ext_map_blocks(handle, inode, map, 0);
++      else
++              retval = ext4_ind_map_blocks(handle, inode, map, 0);
++
++      if (retval <= 0)
++              return retval;
++
++      if (unlikely(retval != map->m_len)) {
++              ext4_warning(inode->i_sb,
++                           "ES len assertion failed for inode "
++                           "%lu: retval %d != map->m_len %d",
++                           inode->i_ino, retval, map->m_len);
++              WARN_ON(1);
++      }
++
++      status = map->m_flags & EXT4_MAP_UNWRITTEN ?
++                      EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
++      ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
++                            map->m_pblk, status);
++      return retval;
++}
++
+ /*
+  * The ext4_map_blocks() function tries to look up the requested blocks,
+  * and returns if the blocks are already mapped.
+@@ -1744,33 +1773,11 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+       down_read(&EXT4_I(inode)->i_data_sem);
+       if (ext4_has_inline_data(inode))
+               retval = 0;
+-      else if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+-              retval = ext4_ext_map_blocks(NULL, inode, map, 0);
+       else
+-              retval = ext4_ind_map_blocks(NULL, inode, map, 0);
+-      if (retval < 0) {
+-              up_read(&EXT4_I(inode)->i_data_sem);
+-              return retval;
+-      }
+-      if (retval > 0) {
+-              unsigned int status;
+-
+-              if (unlikely(retval != map->m_len)) {
+-                      ext4_warning(inode->i_sb,
+-                                   "ES len assertion failed for inode "
+-                                   "%lu: retval %d != map->m_len %d",
+-                                   inode->i_ino, retval, map->m_len);
+-                      WARN_ON(1);
+-              }
+-
+-              status = map->m_flags & EXT4_MAP_UNWRITTEN ?
+-                              EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
+-              ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
+-                                    map->m_pblk, status);
+-              up_read(&EXT4_I(inode)->i_data_sem);
+-              return retval;
+-      }
++              retval = ext4_map_query_blocks(NULL, inode, map);
+       up_read(&EXT4_I(inode)->i_data_sem);
++      if (retval)
++              return retval;
+ add_delayed:
+       down_write(&EXT4_I(inode)->i_data_sem);
+-- 
+2.43.0
+
diff --git a/queue-6.6/ext4-refactor-ext4_da_map_blocks.patch b/queue-6.6/ext4-refactor-ext4_da_map_blocks.patch
new file mode 100644 (file)
index 0000000..f1461d1
--- /dev/null
@@ -0,0 +1,93 @@
+From a772934c48f0157eb94d2d92d3a88570a5391f27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 27 Jan 2024 09:58:00 +0800
+Subject: ext4: refactor ext4_da_map_blocks()
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ Upstream commit 3fcc2b887a1ba4c1f45319cd8c54daa263ecbc36 ]
+
+Refactor and cleanup ext4_da_map_blocks(), reduce some unnecessary
+parameters and branches, no logic changes.
+
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20240127015825.1608160-2-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 0ea6560abb3b ("ext4: check the extent status again before inserting delalloc block")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 39 +++++++++++++++++----------------------
+ 1 file changed, 17 insertions(+), 22 deletions(-)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index d5eb8d44c6c81..b8eab9cf36b98 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1706,7 +1706,6 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+       /* Lookup extent status tree firstly */
+       if (ext4_es_lookup_extent(inode, iblock, NULL, &es)) {
+               if (ext4_es_is_hole(&es)) {
+-                      retval = 0;
+                       down_read(&EXT4_I(inode)->i_data_sem);
+                       goto add_delayed;
+               }
+@@ -1751,26 +1750,9 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+               retval = ext4_ext_map_blocks(NULL, inode, map, 0);
+       else
+               retval = ext4_ind_map_blocks(NULL, inode, map, 0);
+-
+-add_delayed:
+-      if (retval == 0) {
+-              int ret;
+-
+-              /*
+-               * XXX: __block_prepare_write() unmaps passed block,
+-               * is it OK?
+-               */
+-
+-              ret = ext4_insert_delayed_block(inode, map->m_lblk);
+-              if (ret != 0) {
+-                      retval = ret;
+-                      goto out_unlock;
+-              }
+-
+-              map_bh(bh, inode->i_sb, invalid_block);
+-              set_buffer_new(bh);
+-              set_buffer_delay(bh);
+-      } else if (retval > 0) {
++      if (retval < 0)
++              goto out_unlock;
++      if (retval > 0) {
+               unsigned int status;
+               if (unlikely(retval != map->m_len)) {
+@@ -1785,11 +1767,24 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+                               EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
+               ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
+                                     map->m_pblk, status);
++              goto out_unlock;
+       }
++add_delayed:
++      /*
++       * XXX: __block_prepare_write() unmaps passed block,
++       * is it OK?
++       */
++      retval = ext4_insert_delayed_block(inode, map->m_lblk);
++      if (retval)
++              goto out_unlock;
++
++      map_bh(bh, inode->i_sb, invalid_block);
++      set_buffer_new(bh);
++      set_buffer_delay(bh);
++
+ out_unlock:
+       up_read((&EXT4_I(inode)->i_data_sem));
+-
+       return retval;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-assign-curseg_all_data_atgc-if-blkaddr-is-valid.patch b/queue-6.6/f2fs-assign-curseg_all_data_atgc-if-blkaddr-is-valid.patch
new file mode 100644 (file)
index 0000000..69f9adb
--- /dev/null
@@ -0,0 +1,59 @@
+From 2cddf54552b6fc61aea77ffcee7cadc6e37be688 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Jun 2024 02:15:38 +0000
+Subject: f2fs: assign CURSEG_ALL_DATA_ATGC if blkaddr is valid
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+[ Upstream commit 8cb1f4080dd91c6e6b01dbea013a3f42341cb6a1 ]
+
+mkdir /mnt/test/comp
+f2fs_io setflags compression /mnt/test/comp
+dd if=/dev/zero of=/mnt/test/comp/testfile bs=16k count=1
+truncate --size 13 /mnt/test/comp/testfile
+
+In the above scenario, we can get a BUG_ON.
+ kernel BUG at fs/f2fs/segment.c:3589!
+ Call Trace:
+  do_write_page+0x78/0x390 [f2fs]
+  f2fs_outplace_write_data+0x62/0xb0 [f2fs]
+  f2fs_do_write_data_page+0x275/0x740 [f2fs]
+  f2fs_write_single_data_page+0x1dc/0x8f0 [f2fs]
+  f2fs_write_multi_pages+0x1e5/0xae0 [f2fs]
+  f2fs_write_cache_pages+0xab1/0xc60 [f2fs]
+  f2fs_write_data_pages+0x2d8/0x330 [f2fs]
+  do_writepages+0xcf/0x270
+  __writeback_single_inode+0x44/0x350
+  writeback_sb_inodes+0x242/0x530
+  __writeback_inodes_wb+0x54/0xf0
+  wb_writeback+0x192/0x310
+  wb_workfn+0x30d/0x400
+
+The reason is we gave CURSEG_ALL_DATA_ATGC to COMPR_ADDR where the
+page was set the gcing flag by set_cluster_dirty().
+
+Cc: stable@vger.kernel.org
+Fixes: 4961acdd65c9 ("f2fs: fix to tag gcing flag on page during block migration")
+Reviewed-by: Chao Yu <chao@kernel.org>
+Tested-by: Will McVicker <willmcvicker@google.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/segment.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+index 6d6c47df36ec0..804958c6de34c 100644
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -3351,6 +3351,7 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
+                       if (fio->sbi->am.atgc_enabled &&
+                               (fio->io_type == FS_DATA_IO) &&
+                               (fio->sbi->gc_mode != GC_URGENT_HIGH) &&
++                              __is_valid_data_blkaddr(fio->old_blkaddr) &&
+                               !is_inode_flag_set(inode, FI_OPU_WRITE))
+                               return CURSEG_ALL_DATA_ATGC;
+                       else
+-- 
+2.43.0
+
diff --git a/queue-6.6/f2fs-fix-to-avoid-use-ssr-allocate-when-do-defragmen.patch b/queue-6.6/f2fs-fix-to-avoid-use-ssr-allocate-when-do-defragmen.patch
new file mode 100644 (file)
index 0000000..9060487
--- /dev/null
@@ -0,0 +1,75 @@
+From 6dee8cc8ab58aef4fa09219cfa6e739f3023b2f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 May 2024 17:47:00 +0800
+Subject: f2fs: fix to avoid use SSR allocate when do defragment
+
+From: Zhiguo Niu <zhiguo.niu@unisoc.com>
+
+[ Upstream commit 21327a042dd94bc73181d7300e688699cb1f467e ]
+
+SSR allocate mode will be used when doing file defragment
+if ATGC is working at the same time, that is because
+set_page_private_gcing may make CURSEG_ALL_DATA_ATGC segment
+type got in f2fs_allocate_data_block when defragment page
+is writeback, which may cause file fragmentation is worse.
+
+A file with 2 fragmentations is changed as following after defragment:
+
+----------------file info-------------------
+sensorsdata :
+--------------------------------------------
+dev       [254:48]
+ino       [0x    3029 : 12329]
+mode      [0x    81b0 : 33200]
+nlink     [0x       1 : 1]
+uid       [0x    27e6 : 10214]
+gid       [0x    27e6 : 10214]
+size      [0x  242000 : 2367488]
+blksize   [0x    1000 : 4096]
+blocks    [0x    1210 : 4624]
+--------------------------------------------
+
+file_pos   start_blk     end_blk        blks
+       0    11361121    11361207          87
+  356352    11361215    11361216           2
+  364544    11361218    11361218           1
+  368640    11361220    11361221           2
+  376832    11361224    11361225           2
+  385024    11361227    11361238          12
+  434176    11361240    11361252          13
+  487424    11361254    11361254           1
+  491520    11361271    11361279           9
+  528384     3681794     3681795           2
+  536576     3681797     3681797           1
+  540672     3681799     3681799           1
+  544768     3681803     3681803           1
+  548864     3681805     3681805           1
+  552960     3681807     3681807           1
+  557056     3681809     3681809           1
+
+Signed-off-by: Zhiguo Niu <zhiguo.niu@unisoc.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 8cb1f4080dd9 ("f2fs: assign CURSEG_ALL_DATA_ATGC if blkaddr is valid")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/segment.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+index 22080606b8769..6d6c47df36ec0 100644
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -3350,7 +3350,8 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
+               if (page_private_gcing(fio->page)) {
+                       if (fio->sbi->am.atgc_enabled &&
+                               (fio->io_type == FS_DATA_IO) &&
+-                              (fio->sbi->gc_mode != GC_URGENT_HIGH))
++                              (fio->sbi->gc_mode != GC_URGENT_HIGH) &&
++                              !is_inode_flag_set(inode, FI_OPU_WRITE))
+                               return CURSEG_ALL_DATA_ATGC;
+                       else
+                               return CURSEG_COLD_DATA;
+-- 
+2.43.0
+
diff --git a/queue-6.6/fbdev-vesafb-detect-vga-compatibility-from-screen-in.patch b/queue-6.6/fbdev-vesafb-detect-vga-compatibility-from-screen-in.patch
new file mode 100644 (file)
index 0000000..19df67c
--- /dev/null
@@ -0,0 +1,81 @@
+From e1d2254b288296e8238741fd68a211f3887f7e12 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jun 2024 13:06:27 +0200
+Subject: fbdev: vesafb: Detect VGA compatibility from screen info's VESA
+ attributes
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit c2bc958b2b03e361f14df99983bc64a39a7323a3 ]
+
+Test the vesa_attributes field in struct screen_info for compatibility
+with VGA hardware. Vesafb currently tests bit 1 in screen_info's
+capabilities field which indicates a 64-bit lfb address and is
+unrelated to VGA compatibility.
+
+Section 4.4 of the Vesa VBE 2.0 specifications defines that bit 5 in
+the mode's attributes field signals VGA compatibility. The mode is
+compatible with VGA hardware if the bit is clear. In that case, the
+driver can access VGA state of the VBE's underlying hardware. The
+vesafb driver uses this feature to program the color LUT in palette
+modes. Without, colors might be incorrect.
+
+The problem got introduced in commit 89ec4c238e7a ("[PATCH] vesafb: Fix
+incorrect logo colors in x86_64"). It incorrectly stores the mode
+attributes in the screen_info's capabilities field and updates vesafb
+accordingly. Later, commit 5e8ddcbe8692 ("Video mode probing support for
+the new x86 setup code") fixed the screen_info, but did not update vesafb.
+Color output still tends to work, because bit 1 in capabilities is
+usually 0.
+
+Besides fixing the bug in vesafb, this commit introduces a helper that
+reads the correct bit from screen_info.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Fixes: 5e8ddcbe8692 ("Video mode probing support for the new x86 setup code")
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Cc: <stable@vger.kernel.org> # v2.6.23+
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/vesafb.c |  2 +-
+ include/linux/screen_info.h  | 10 ++++++++++
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/video/fbdev/vesafb.c b/drivers/video/fbdev/vesafb.c
+index ea89accbec385..a21581b40256c 100644
+--- a/drivers/video/fbdev/vesafb.c
++++ b/drivers/video/fbdev/vesafb.c
+@@ -259,7 +259,7 @@ static int vesafb_probe(struct platform_device *dev)
+       if (si->orig_video_isVGA != VIDEO_TYPE_VLFB)
+               return -ENODEV;
+-      vga_compat = (si->capabilities & 2) ? 0 : 1;
++      vga_compat = !__screen_info_vbe_mode_nonvga(si);
+       vesafb_fix.smem_start = si->lfb_base;
+       vesafb_defined.bits_per_pixel = si->lfb_depth;
+       if (15 == vesafb_defined.bits_per_pixel)
+diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
+index 75303c126285a..6a4a3cec4638b 100644
+--- a/include/linux/screen_info.h
++++ b/include/linux/screen_info.h
+@@ -49,6 +49,16 @@ static inline u64 __screen_info_lfb_size(const struct screen_info *si, unsigned
+       return lfb_size;
+ }
++static inline bool __screen_info_vbe_mode_nonvga(const struct screen_info *si)
++{
++      /*
++       * VESA modes typically run on VGA hardware. Set bit 5 signals that this
++       * is not the case. Drivers can then not make use of VGA resources. See
++       * Sec 4.4 of the VBE 2.0 spec.
++       */
++      return si->vesa_attributes & BIT(5);
++}
++
+ static inline unsigned int __screen_info_video_type(unsigned int type)
+ {
+       switch (type) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/fbdev-vesafb-replace-references-to-global-screen_inf.patch b/queue-6.6/fbdev-vesafb-replace-references-to-global-screen_inf.patch
new file mode 100644 (file)
index 0000000..eb2dd62
--- /dev/null
@@ -0,0 +1,159 @@
+From da83c44e9ff5c01779868182e8ec907b5c519e2e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Dec 2023 14:50:28 +0100
+Subject: fbdev/vesafb: Replace references to global screen_info by local
+ pointer
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 3218286bbb78cac3dde713514529e0480d678173 ]
+
+Get the global screen_info's address once and access the data via
+this pointer. Limits the use of global state.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20231206135153.2599-4-tzimmermann@suse.de
+Stable-dep-of: c2bc958b2b03 ("fbdev: vesafb: Detect VGA compatibility from screen info's VESA attributes")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/fbdev/vesafb.c | 66 +++++++++++++++++++-----------------
+ 1 file changed, 35 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/video/fbdev/vesafb.c b/drivers/video/fbdev/vesafb.c
+index c0edceea0a793..ea89accbec385 100644
+--- a/drivers/video/fbdev/vesafb.c
++++ b/drivers/video/fbdev/vesafb.c
+@@ -243,6 +243,7 @@ static int vesafb_setup(char *options)
+ static int vesafb_probe(struct platform_device *dev)
+ {
++      struct screen_info *si = &screen_info;
+       struct fb_info *info;
+       struct vesafb_par *par;
+       int i, err;
+@@ -255,17 +256,17 @@ static int vesafb_probe(struct platform_device *dev)
+       fb_get_options("vesafb", &option);
+       vesafb_setup(option);
+-      if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB)
++      if (si->orig_video_isVGA != VIDEO_TYPE_VLFB)
+               return -ENODEV;
+-      vga_compat = (screen_info.capabilities & 2) ? 0 : 1;
+-      vesafb_fix.smem_start = screen_info.lfb_base;
+-      vesafb_defined.bits_per_pixel = screen_info.lfb_depth;
++      vga_compat = (si->capabilities & 2) ? 0 : 1;
++      vesafb_fix.smem_start = si->lfb_base;
++      vesafb_defined.bits_per_pixel = si->lfb_depth;
+       if (15 == vesafb_defined.bits_per_pixel)
+               vesafb_defined.bits_per_pixel = 16;
+-      vesafb_defined.xres = screen_info.lfb_width;
+-      vesafb_defined.yres = screen_info.lfb_height;
+-      vesafb_fix.line_length = screen_info.lfb_linelength;
++      vesafb_defined.xres = si->lfb_width;
++      vesafb_defined.yres = si->lfb_height;
++      vesafb_fix.line_length = si->lfb_linelength;
+       vesafb_fix.visual   = (vesafb_defined.bits_per_pixel == 8) ?
+               FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+@@ -277,7 +278,7 @@ static int vesafb_probe(struct platform_device *dev)
+       /*   size_total -- all video memory we have. Used for mtrr
+        *                 entries, resource allocation and bounds
+        *                 checking. */
+-      size_total = screen_info.lfb_size * 65536;
++      size_total = si->lfb_size * 65536;
+       if (vram_total)
+               size_total = vram_total * 1024 * 1024;
+       if (size_total < size_vmode)
+@@ -297,7 +298,7 @@ static int vesafb_probe(struct platform_device *dev)
+       vesafb_fix.smem_len = size_remap;
+ #ifndef __i386__
+-      screen_info.vesapm_seg = 0;
++      si->vesapm_seg = 0;
+ #endif
+       if (!request_mem_region(vesafb_fix.smem_start, size_total, "vesafb")) {
+@@ -317,23 +318,26 @@ static int vesafb_probe(struct platform_device *dev)
+       par = info->par;
+       info->pseudo_palette = par->pseudo_palette;
+-      par->base = screen_info.lfb_base;
++      par->base = si->lfb_base;
+       par->size = size_total;
+       printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
+-             vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages);
++             vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel,
++             vesafb_fix.line_length, si->pages);
+-      if (screen_info.vesapm_seg) {
++      if (si->vesapm_seg) {
+               printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n",
+-                     screen_info.vesapm_seg,screen_info.vesapm_off);
++                     si->vesapm_seg, si->vesapm_off);
+       }
+-      if (screen_info.vesapm_seg < 0xc000)
++      if (si->vesapm_seg < 0xc000)
+               ypan = pmi_setpal = 0; /* not available or some DOS TSR ... */
+       if (ypan || pmi_setpal) {
++              unsigned long pmi_phys;
+               unsigned short *pmi_base;
+-              pmi_base  = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off);
++              pmi_phys  = ((unsigned long)si->vesapm_seg << 4) + si->vesapm_off;
++              pmi_base  = (unsigned short *)phys_to_virt(pmi_phys);
+               pmi_start = (void*)((char*)pmi_base + pmi_base[1]);
+               pmi_pal   = (void*)((char*)pmi_base + pmi_base[2]);
+               printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal);
+@@ -377,14 +381,14 @@ static int vesafb_probe(struct platform_device *dev)
+       vesafb_defined.left_margin  = (vesafb_defined.xres / 8) & 0xf8;
+       vesafb_defined.hsync_len    = (vesafb_defined.xres / 8) & 0xf8;
+-      vesafb_defined.red.offset    = screen_info.red_pos;
+-      vesafb_defined.red.length    = screen_info.red_size;
+-      vesafb_defined.green.offset  = screen_info.green_pos;
+-      vesafb_defined.green.length  = screen_info.green_size;
+-      vesafb_defined.blue.offset   = screen_info.blue_pos;
+-      vesafb_defined.blue.length   = screen_info.blue_size;
+-      vesafb_defined.transp.offset = screen_info.rsvd_pos;
+-      vesafb_defined.transp.length = screen_info.rsvd_size;
++      vesafb_defined.red.offset    = si->red_pos;
++      vesafb_defined.red.length    = si->red_size;
++      vesafb_defined.green.offset  = si->green_pos;
++      vesafb_defined.green.length  = si->green_size;
++      vesafb_defined.blue.offset   = si->blue_pos;
++      vesafb_defined.blue.length   = si->blue_size;
++      vesafb_defined.transp.offset = si->rsvd_pos;
++      vesafb_defined.transp.length = si->rsvd_size;
+       if (vesafb_defined.bits_per_pixel <= 8) {
+               depth = vesafb_defined.green.length;
+@@ -399,14 +403,14 @@ static int vesafb_probe(struct platform_device *dev)
+              (vesafb_defined.bits_per_pixel > 8) ?
+              "Truecolor" : (vga_compat || pmi_setpal) ?
+              "Pseudocolor" : "Static Pseudocolor",
+-             screen_info.rsvd_size,
+-             screen_info.red_size,
+-             screen_info.green_size,
+-             screen_info.blue_size,
+-             screen_info.rsvd_pos,
+-             screen_info.red_pos,
+-             screen_info.green_pos,
+-             screen_info.blue_pos);
++             si->rsvd_size,
++             si->red_size,
++             si->green_size,
++             si->blue_size,
++             si->rsvd_pos,
++             si->red_pos,
++             si->green_pos,
++             si->blue_pos);
+       vesafb_fix.ypanstep  = ypan     ? 1 : 0;
+       vesafb_fix.ywrapstep = (ypan>1) ? 1 : 0;
+-- 
+2.43.0
+
diff --git a/queue-6.6/firmware-sysfb-update-screen_info-for-relocated-efi-.patch b/queue-6.6/firmware-sysfb-update-screen_info-for-relocated-efi-.patch
new file mode 100644 (file)
index 0000000..22f4ec2
--- /dev/null
@@ -0,0 +1,191 @@
+From a0ac8a148219079d571521436d1df6735f4488db Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Feb 2024 10:06:15 +0100
+Subject: firmware/sysfb: Update screen_info for relocated EFI framebuffers
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 78aa89d1dfba1e3cf4a2e053afa3b4c4ec622371 ]
+
+On ARM PCI systems, the PCI hierarchy might be reconfigured during
+boot and the firmware framebuffer might move as a result of that.
+The values in screen_info will then be invalid.
+
+Work around this problem by tracking the framebuffer's initial
+location before it get relocated; then fix the screen_info state
+between reloaction and creating the firmware framebuffer's device.
+
+This functionality has been lifted from efifb. See the commit message
+of commit 55d728a40d36 ("efi/fb: Avoid reconfiguration of BAR that
+covers the framebuffer") for more information.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240212090736.11464-8-tzimmermann@suse.de
+Stable-dep-of: c2bc958b2b03 ("fbdev: vesafb: Detect VGA compatibility from screen info's VESA attributes")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/sysfb.c        |  2 +
+ drivers/video/screen_info_pci.c | 88 +++++++++++++++++++++++++++++++++
+ include/linux/screen_info.h     | 16 ++++++
+ 3 files changed, 106 insertions(+)
+
+diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
+index 3c197db42c9d9..defd7a36cb08a 100644
+--- a/drivers/firmware/sysfb.c
++++ b/drivers/firmware/sysfb.c
+@@ -77,6 +77,8 @@ static __init int sysfb_init(void)
+       bool compatible;
+       int ret = 0;
++      screen_info_apply_fixups();
++
+       mutex_lock(&disable_lock);
+       if (disabled)
+               goto unlock_mutex;
+diff --git a/drivers/video/screen_info_pci.c b/drivers/video/screen_info_pci.c
+index d8985a54ce717..6c58335171410 100644
+--- a/drivers/video/screen_info_pci.c
++++ b/drivers/video/screen_info_pci.c
+@@ -1,7 +1,95 @@
+ // SPDX-License-Identifier: GPL-2.0
+ #include <linux/pci.h>
++#include <linux/printk.h>
+ #include <linux/screen_info.h>
++#include <linux/string.h>
++
++static struct pci_dev *screen_info_lfb_pdev;
++static size_t screen_info_lfb_bar;
++static resource_size_t screen_info_lfb_offset;
++static struct resource screen_info_lfb_res = DEFINE_RES_MEM(0, 0);
++
++static bool __screen_info_relocation_is_valid(const struct screen_info *si, struct resource *pr)
++{
++      u64 size = __screen_info_lfb_size(si, screen_info_video_type(si));
++
++      if (screen_info_lfb_offset > resource_size(pr))
++              return false;
++      if (size > resource_size(pr))
++              return false;
++      if (resource_size(pr) - size < screen_info_lfb_offset)
++              return false;
++
++      return true;
++}
++
++void screen_info_apply_fixups(void)
++{
++      struct screen_info *si = &screen_info;
++
++      if (screen_info_lfb_pdev) {
++              struct resource *pr = &screen_info_lfb_pdev->resource[screen_info_lfb_bar];
++
++              if (pr->start != screen_info_lfb_res.start) {
++                      if (__screen_info_relocation_is_valid(si, pr)) {
++                              /*
++                               * Only update base if we have an actual
++                               * relocation to a valid I/O range.
++                               */
++                              __screen_info_set_lfb_base(si, pr->start + screen_info_lfb_offset);
++                              pr_info("Relocating firmware framebuffer to offset %pa[d] within %pr\n",
++                                      &screen_info_lfb_offset, pr);
++                      } else {
++                              pr_warn("Invalid relocating, disabling firmware framebuffer\n");
++                      }
++              }
++      }
++}
++
++static void screen_info_fixup_lfb(struct pci_dev *pdev)
++{
++      unsigned int type;
++      struct resource res[SCREEN_INFO_MAX_RESOURCES];
++      size_t i, numres;
++      int ret;
++      const struct screen_info *si = &screen_info;
++
++      if (screen_info_lfb_pdev)
++              return; // already found
++
++      type = screen_info_video_type(si);
++      if (type != VIDEO_TYPE_EFI)
++              return; // only applies to EFI
++
++      ret = screen_info_resources(si, res, ARRAY_SIZE(res));
++      if (ret < 0)
++              return;
++      numres = ret;
++
++      for (i = 0; i < numres; ++i) {
++              struct resource *r = &res[i];
++              const struct resource *pr;
++
++              if (!(r->flags & IORESOURCE_MEM))
++                      continue;
++              pr = pci_find_resource(pdev, r);
++              if (!pr)
++                      continue;
++
++              /*
++               * We've found a PCI device with the framebuffer
++               * resource. Store away the parameters to track
++               * relocation of the framebuffer aperture.
++               */
++              screen_info_lfb_pdev = pdev;
++              screen_info_lfb_bar = pr - pdev->resource;
++              screen_info_lfb_offset = r->start - pr->start;
++              memcpy(&screen_info_lfb_res, r, sizeof(screen_info_lfb_res));
++      }
++}
++DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY, 16,
++                             screen_info_fixup_lfb);
+ static struct pci_dev *__screen_info_pci_dev(struct resource *res)
+ {
+diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
+index 0eae08e3c6f90..75303c126285a 100644
+--- a/include/linux/screen_info.h
++++ b/include/linux/screen_info.h
+@@ -4,6 +4,8 @@
+ #include <uapi/linux/screen_info.h>
++#include <linux/bits.h>
++
+ /**
+  * SCREEN_INFO_MAX_RESOURCES - maximum number of resources per screen_info
+  */
+@@ -27,6 +29,17 @@ static inline u64 __screen_info_lfb_base(const struct screen_info *si)
+       return lfb_base;
+ }
++static inline void __screen_info_set_lfb_base(struct screen_info *si, u64 lfb_base)
++{
++      si->lfb_base = lfb_base & GENMASK_ULL(31, 0);
++      si->ext_lfb_base = (lfb_base & GENMASK_ULL(63, 32)) >> 32;
++
++      if (si->ext_lfb_base)
++              si->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
++      else
++              si->capabilities &= ~VIDEO_CAPABILITY_64BIT_BASE;
++}
++
+ static inline u64 __screen_info_lfb_size(const struct screen_info *si, unsigned int type)
+ {
+       u64 lfb_size = si->lfb_size;
+@@ -106,8 +119,11 @@ static inline unsigned int screen_info_video_type(const struct screen_info *si)
+ ssize_t screen_info_resources(const struct screen_info *si, struct resource *r, size_t num);
+ #if defined(CONFIG_PCI)
++void screen_info_apply_fixups(void);
+ struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
+ #else
++static inline void screen_info_apply_fixups(void)
++{ }
+ static inline struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
+ {
+       return NULL;
+-- 
+2.43.0
+
diff --git a/queue-6.6/kvm-nvmx-add-a-helper-to-get-highest-pending-from-po.patch b/queue-6.6/kvm-nvmx-add-a-helper-to-get-highest-pending-from-po.patch
new file mode 100644 (file)
index 0000000..f915cae
--- /dev/null
@@ -0,0 +1,81 @@
+From 84b719ce71f9017aa147913fcb7148880203a5ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Jun 2024 10:26:04 -0700
+Subject: KVM: nVMX: Add a helper to get highest pending from Posted Interrupt
+ vector
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit d83c36d822be44db4bad0c43bea99c8908f54117 ]
+
+Add a helper to retrieve the highest pending vector given a Posted
+Interrupt descriptor.  While the actual operation is straightforward, it's
+surprisingly easy to mess up, e.g. if one tries to reuse lapic.c's
+find_highest_vector(), which doesn't work with PID.PIR due to the APIC's
+IRR and ISR component registers being physically discontiguous (they're
+4-byte registers aligned at 16-byte intervals).
+
+To make PIR handling more consistent with respect to IRR and ISR handling,
+return -1 to indicate "no interrupt pending".
+
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20240607172609.3205077-2-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/nested.c      |  5 +++--
+ arch/x86/kvm/vmx/posted_intr.h | 10 ++++++++++
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
+index d1b4a85def0a6..5f85375f75b48 100644
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -12,6 +12,7 @@
+ #include "mmu.h"
+ #include "nested.h"
+ #include "pmu.h"
++#include "posted_intr.h"
+ #include "sgx.h"
+ #include "trace.h"
+ #include "vmx.h"
+@@ -3830,8 +3831,8 @@ static int vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
+       if (!pi_test_and_clear_on(vmx->nested.pi_desc))
+               return 0;
+-      max_irr = find_last_bit((unsigned long *)vmx->nested.pi_desc->pir, 256);
+-      if (max_irr != 256) {
++      max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
++      if (max_irr > 0) {
+               vapic_page = vmx->nested.virtual_apic_map.hva;
+               if (!vapic_page)
+                       goto mmio_needed;
+diff --git a/arch/x86/kvm/vmx/posted_intr.h b/arch/x86/kvm/vmx/posted_intr.h
+index 6b2a0226257ea..1715d2ab07be5 100644
+--- a/arch/x86/kvm/vmx/posted_intr.h
++++ b/arch/x86/kvm/vmx/posted_intr.h
+@@ -1,6 +1,8 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+ #ifndef __KVM_X86_VMX_POSTED_INTR_H
+ #define __KVM_X86_VMX_POSTED_INTR_H
++
++#include <linux/find.h>
+ #include <asm/posted_intr.h>
+ void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu);
+@@ -12,4 +14,12 @@ int vmx_pi_update_irte(struct kvm *kvm, unsigned int host_irq,
+                      uint32_t guest_irq, bool set);
+ void vmx_pi_start_assignment(struct kvm *kvm);
++static inline int pi_find_highest_vector(struct pi_desc *pi_desc)
++{
++      int vec;
++
++      vec = find_last_bit((unsigned long *)pi_desc->pir, 256);
++      return vec < 256 ? vec : -1;
++}
++
+ #endif /* __KVM_X86_VMX_POSTED_INTR_H */
+-- 
+2.43.0
+
diff --git a/queue-6.6/kvm-nvmx-check-for-pending-posted-interrupts-when-lo.patch b/queue-6.6/kvm-nvmx-check-for-pending-posted-interrupts-when-lo.patch
new file mode 100644 (file)
index 0000000..6fd5f1c
--- /dev/null
@@ -0,0 +1,81 @@
+From fbd77caec10aae04a920819111c076592bc0437c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Jun 2024 10:26:07 -0700
+Subject: KVM: nVMX: Check for pending posted interrupts when looking for
+ nested events
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 27c4fa42b11af780d49ce704f7fa67b3c2544df4 ]
+
+Check for pending (and notified!) posted interrupts when checking if L2
+has a pending wake event, as fully posted/notified virtual interrupt is a
+valid wake event for HLT.
+
+Note that KVM must check vmx->nested.pi_pending to avoid prematurely
+waking L2, e.g. even if KVM sees a non-zero PID.PIR and PID.0N=1, the
+virtual interrupt won't actually be recognized until a notification IRQ is
+received by the vCPU or the vCPU does (nested) VM-Enter.
+
+Fixes: 26844fee6ade ("KVM: x86: never write to memory from kvm_vcpu_check_block()")
+Cc: stable@vger.kernel.org
+Cc: Maxim Levitsky <mlevitsk@redhat.com>
+Reported-by: Jim Mattson <jmattson@google.com>
+Closes: https://lore.kernel.org/all/20231207010302.2240506-1-jmattson@google.com
+Link: https://lore.kernel.org/r/20240607172609.3205077-5-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/nested.c | 36 ++++++++++++++++++++++++++++++++++--
+ 1 file changed, 34 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
+index 5f85375f75b48..0ad66b9207e85 100644
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -3965,8 +3965,40 @@ static bool nested_vmx_preemption_timer_pending(struct kvm_vcpu *vcpu)
+ static bool vmx_has_nested_events(struct kvm_vcpu *vcpu, bool for_injection)
+ {
+-      return nested_vmx_preemption_timer_pending(vcpu) ||
+-             to_vmx(vcpu)->nested.mtf_pending;
++      struct vcpu_vmx *vmx = to_vmx(vcpu);
++      void *vapic = vmx->nested.virtual_apic_map.hva;
++      int max_irr, vppr;
++
++      if (nested_vmx_preemption_timer_pending(vcpu) ||
++          vmx->nested.mtf_pending)
++              return true;
++
++      /*
++       * Virtual Interrupt Delivery doesn't require manual injection.  Either
++       * the interrupt is already in GUEST_RVI and will be recognized by CPU
++       * at VM-Entry, or there is a KVM_REQ_EVENT pending and KVM will move
++       * the interrupt from the PIR to RVI prior to entering the guest.
++       */
++      if (for_injection)
++              return false;
++
++      if (!nested_cpu_has_vid(get_vmcs12(vcpu)) ||
++          __vmx_interrupt_blocked(vcpu))
++              return false;
++
++      if (!vapic)
++              return false;
++
++      vppr = *((u32 *)(vapic + APIC_PROCPRI));
++
++      if (vmx->nested.pi_pending && vmx->nested.pi_desc &&
++          pi_test_on(vmx->nested.pi_desc)) {
++              max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
++              if (max_irr > 0 && (max_irr & 0xf0) > (vppr & 0xf0))
++                      return true;
++      }
++
++      return false;
+ }
+ /*
+-- 
+2.43.0
+
diff --git a/queue-6.6/kvm-vmx-move-posted-interrupt-descriptor-out-of-vmx-.patch b/queue-6.6/kvm-vmx-move-posted-interrupt-descriptor-out-of-vmx-.patch
new file mode 100644 (file)
index 0000000..1d727ce
--- /dev/null
@@ -0,0 +1,255 @@
+From 40b064edb66ce131945a7f18730a03c4fee8d170 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Apr 2024 10:41:03 -0700
+Subject: KVM: VMX: Move posted interrupt descriptor out of VMX code
+
+From: Jacob Pan <jacob.jun.pan@linux.intel.com>
+
+[ Upstream commit 699f67512f04cbaee965fad872702c06eaf440f6 ]
+
+To prepare native usage of posted interrupts, move the PID declarations out
+of VMX code such that they can be shared.
+
+Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Sean Christopherson <seanjc@google.com>
+Link: https://lore.kernel.org/r/20240423174114.526704-2-jacob.jun.pan@linux.intel.com
+Stable-dep-of: d83c36d822be ("KVM: nVMX: Add a helper to get highest pending from Posted Interrupt vector")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/posted_intr.h | 88 ++++++++++++++++++++++++++++
+ arch/x86/kvm/vmx/posted_intr.h     | 93 +-----------------------------
+ arch/x86/kvm/vmx/vmx.c             |  1 +
+ arch/x86/kvm/vmx/vmx.h             |  2 +-
+ 4 files changed, 91 insertions(+), 93 deletions(-)
+ create mode 100644 arch/x86/include/asm/posted_intr.h
+
+diff --git a/arch/x86/include/asm/posted_intr.h b/arch/x86/include/asm/posted_intr.h
+new file mode 100644
+index 0000000000000..f0324c56f7af5
+--- /dev/null
++++ b/arch/x86/include/asm/posted_intr.h
+@@ -0,0 +1,88 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _X86_POSTED_INTR_H
++#define _X86_POSTED_INTR_H
++
++#define POSTED_INTR_ON  0
++#define POSTED_INTR_SN  1
++
++#define PID_TABLE_ENTRY_VALID 1
++
++/* Posted-Interrupt Descriptor */
++struct pi_desc {
++      u32 pir[8];     /* Posted interrupt requested */
++      union {
++              struct {
++                              /* bit 256 - Outstanding Notification */
++                      u16     on      : 1,
++                              /* bit 257 - Suppress Notification */
++                              sn      : 1,
++                              /* bit 271:258 - Reserved */
++                              rsvd_1  : 14;
++                              /* bit 279:272 - Notification Vector */
++                      u8      nv;
++                              /* bit 287:280 - Reserved */
++                      u8      rsvd_2;
++                              /* bit 319:288 - Notification Destination */
++                      u32     ndst;
++              };
++              u64 control;
++      };
++      u32 rsvd[6];
++} __aligned(64);
++
++static inline bool pi_test_and_set_on(struct pi_desc *pi_desc)
++{
++      return test_and_set_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control);
++}
++
++static inline bool pi_test_and_clear_on(struct pi_desc *pi_desc)
++{
++      return test_and_clear_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control);
++}
++
++static inline bool pi_test_and_clear_sn(struct pi_desc *pi_desc)
++{
++      return test_and_clear_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control);
++}
++
++static inline bool pi_test_and_set_pir(int vector, struct pi_desc *pi_desc)
++{
++      return test_and_set_bit(vector, (unsigned long *)pi_desc->pir);
++}
++
++static inline bool pi_is_pir_empty(struct pi_desc *pi_desc)
++{
++      return bitmap_empty((unsigned long *)pi_desc->pir, NR_VECTORS);
++}
++
++static inline void pi_set_sn(struct pi_desc *pi_desc)
++{
++      set_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control);
++}
++
++static inline void pi_set_on(struct pi_desc *pi_desc)
++{
++      set_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control);
++}
++
++static inline void pi_clear_on(struct pi_desc *pi_desc)
++{
++      clear_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control);
++}
++
++static inline void pi_clear_sn(struct pi_desc *pi_desc)
++{
++      clear_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control);
++}
++
++static inline bool pi_test_on(struct pi_desc *pi_desc)
++{
++      return test_bit(POSTED_INTR_ON, (unsigned long *)&pi_desc->control);
++}
++
++static inline bool pi_test_sn(struct pi_desc *pi_desc)
++{
++      return test_bit(POSTED_INTR_SN, (unsigned long *)&pi_desc->control);
++}
++
++#endif /* _X86_POSTED_INTR_H */
+diff --git a/arch/x86/kvm/vmx/posted_intr.h b/arch/x86/kvm/vmx/posted_intr.h
+index 26992076552ef..6b2a0226257ea 100644
+--- a/arch/x86/kvm/vmx/posted_intr.h
++++ b/arch/x86/kvm/vmx/posted_intr.h
+@@ -1,98 +1,7 @@
+ /* SPDX-License-Identifier: GPL-2.0 */
+ #ifndef __KVM_X86_VMX_POSTED_INTR_H
+ #define __KVM_X86_VMX_POSTED_INTR_H
+-
+-#define POSTED_INTR_ON  0
+-#define POSTED_INTR_SN  1
+-
+-#define PID_TABLE_ENTRY_VALID 1
+-
+-/* Posted-Interrupt Descriptor */
+-struct pi_desc {
+-      u32 pir[8];     /* Posted interrupt requested */
+-      union {
+-              struct {
+-                              /* bit 256 - Outstanding Notification */
+-                      u16     on      : 1,
+-                              /* bit 257 - Suppress Notification */
+-                              sn      : 1,
+-                              /* bit 271:258 - Reserved */
+-                              rsvd_1  : 14;
+-                              /* bit 279:272 - Notification Vector */
+-                      u8      nv;
+-                              /* bit 287:280 - Reserved */
+-                      u8      rsvd_2;
+-                              /* bit 319:288 - Notification Destination */
+-                      u32     ndst;
+-              };
+-              u64 control;
+-      };
+-      u32 rsvd[6];
+-} __aligned(64);
+-
+-static inline bool pi_test_and_set_on(struct pi_desc *pi_desc)
+-{
+-      return test_and_set_bit(POSTED_INTR_ON,
+-                      (unsigned long *)&pi_desc->control);
+-}
+-
+-static inline bool pi_test_and_clear_on(struct pi_desc *pi_desc)
+-{
+-      return test_and_clear_bit(POSTED_INTR_ON,
+-                      (unsigned long *)&pi_desc->control);
+-}
+-
+-static inline bool pi_test_and_clear_sn(struct pi_desc *pi_desc)
+-{
+-      return test_and_clear_bit(POSTED_INTR_SN,
+-                      (unsigned long *)&pi_desc->control);
+-}
+-
+-static inline bool pi_test_and_set_pir(int vector, struct pi_desc *pi_desc)
+-{
+-      return test_and_set_bit(vector, (unsigned long *)pi_desc->pir);
+-}
+-
+-static inline bool pi_is_pir_empty(struct pi_desc *pi_desc)
+-{
+-      return bitmap_empty((unsigned long *)pi_desc->pir, NR_VECTORS);
+-}
+-
+-static inline void pi_set_sn(struct pi_desc *pi_desc)
+-{
+-      set_bit(POSTED_INTR_SN,
+-              (unsigned long *)&pi_desc->control);
+-}
+-
+-static inline void pi_set_on(struct pi_desc *pi_desc)
+-{
+-      set_bit(POSTED_INTR_ON,
+-              (unsigned long *)&pi_desc->control);
+-}
+-
+-static inline void pi_clear_on(struct pi_desc *pi_desc)
+-{
+-      clear_bit(POSTED_INTR_ON,
+-              (unsigned long *)&pi_desc->control);
+-}
+-
+-static inline void pi_clear_sn(struct pi_desc *pi_desc)
+-{
+-      clear_bit(POSTED_INTR_SN,
+-              (unsigned long *)&pi_desc->control);
+-}
+-
+-static inline bool pi_test_on(struct pi_desc *pi_desc)
+-{
+-      return test_bit(POSTED_INTR_ON,
+-                      (unsigned long *)&pi_desc->control);
+-}
+-
+-static inline bool pi_test_sn(struct pi_desc *pi_desc)
+-{
+-      return test_bit(POSTED_INTR_SN,
+-                      (unsigned long *)&pi_desc->control);
+-}
++#include <asm/posted_intr.h>
+ void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu);
+ void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu);
+diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
+index 09d26b46800d4..2e0106d9d371c 100644
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -67,6 +67,7 @@
+ #include "x86.h"
+ #include "smm.h"
+ #include "vmx_onhyperv.h"
++#include "posted_intr.h"
+ MODULE_AUTHOR("Qumranet");
+ MODULE_LICENSE("GPL");
+diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
+index 912b0c4697429..6be1627d888e5 100644
+--- a/arch/x86/kvm/vmx/vmx.h
++++ b/arch/x86/kvm/vmx/vmx.h
+@@ -7,10 +7,10 @@
+ #include <asm/kvm.h>
+ #include <asm/intel_pt.h>
+ #include <asm/perf_event.h>
++#include <asm/posted_intr.h>
+ #include "capabilities.h"
+ #include "../kvm_cache_regs.h"
+-#include "posted_intr.h"
+ #include "vmcs.h"
+ #include "vmx_ops.h"
+ #include "../cpuid.h"
+-- 
+2.43.0
+
diff --git a/queue-6.6/kvm-vmx-split-off-vmx_onhyperv.-ch-from-hyperv.-ch.patch b/queue-6.6/kvm-vmx-split-off-vmx_onhyperv.-ch-from-hyperv.-ch.patch
new file mode 100644 (file)
index 0000000..0b26e94
--- /dev/null
@@ -0,0 +1,643 @@
+From 8339c1753fb9f735a4c2edb8c28907e141d4805e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Dec 2023 11:36:17 +0100
+Subject: KVM: VMX: Split off vmx_onhyperv.{ch} from hyperv.{ch}
+
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+
+[ Upstream commit 50a82b0eb88c108d1ebc73a97f5b81df0d5918e0 ]
+
+hyperv.{ch} is currently a mix of stuff which is needed by both Hyper-V on
+KVM and KVM on Hyper-V. As a preparation to making Hyper-V emulation
+optional, put KVM-on-Hyper-V specific code into dedicated files.
+
+No functional change intended.
+
+Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
+Tested-by: Jeremi Piotrowski <jpiotrowski@linux.microsoft.com>
+Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Link: https://lore.kernel.org/r/20231205103630.1391318-4-vkuznets@redhat.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Stable-dep-of: d83c36d822be ("KVM: nVMX: Add a helper to get highest pending from Posted Interrupt vector")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/Makefile           |   4 +
+ arch/x86/kvm/vmx/hyperv.c       | 139 --------------------
+ arch/x86/kvm/vmx/hyperv.h       | 217 ++++++++++++++++----------------
+ arch/x86/kvm/vmx/vmx.c          |   1 +
+ arch/x86/kvm/vmx/vmx_onhyperv.c |  36 ++++++
+ arch/x86/kvm/vmx/vmx_onhyperv.h | 124 ++++++++++++++++++
+ arch/x86/kvm/vmx/vmx_ops.h      |   2 +-
+ 7 files changed, 271 insertions(+), 252 deletions(-)
+ create mode 100644 arch/x86/kvm/vmx/vmx_onhyperv.c
+ create mode 100644 arch/x86/kvm/vmx/vmx_onhyperv.h
+
+diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
+index 80e3fe184d17e..a99ffc3f3a3fd 100644
+--- a/arch/x86/kvm/Makefile
++++ b/arch/x86/kvm/Makefile
+@@ -26,6 +26,10 @@ kvm-intel-y         += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \
+                          vmx/hyperv.o vmx/nested.o vmx/posted_intr.o
+ kvm-intel-$(CONFIG_X86_SGX_KVM)       += vmx/sgx.o
++ifdef CONFIG_HYPERV
++kvm-intel-y           += vmx/vmx_onhyperv.o
++endif
++
+ kvm-amd-y             += svm/svm.o svm/vmenter.o svm/pmu.o svm/nested.o svm/avic.o \
+                          svm/sev.o svm/hyperv.o
+diff --git a/arch/x86/kvm/vmx/hyperv.c b/arch/x86/kvm/vmx/hyperv.c
+index 313b8bb5b8a7c..de13dc14fe1d2 100644
+--- a/arch/x86/kvm/vmx/hyperv.c
++++ b/arch/x86/kvm/vmx/hyperv.c
+@@ -13,111 +13,6 @@
+ #define CC KVM_NESTED_VMENTER_CONSISTENCY_CHECK
+-/*
+- * Enlightened VMCSv1 doesn't support these:
+- *
+- *    POSTED_INTR_NV                  = 0x00000002,
+- *    GUEST_INTR_STATUS               = 0x00000810,
+- *    APIC_ACCESS_ADDR                = 0x00002014,
+- *    POSTED_INTR_DESC_ADDR           = 0x00002016,
+- *    EOI_EXIT_BITMAP0                = 0x0000201c,
+- *    EOI_EXIT_BITMAP1                = 0x0000201e,
+- *    EOI_EXIT_BITMAP2                = 0x00002020,
+- *    EOI_EXIT_BITMAP3                = 0x00002022,
+- *    GUEST_PML_INDEX                 = 0x00000812,
+- *    PML_ADDRESS                     = 0x0000200e,
+- *    VM_FUNCTION_CONTROL             = 0x00002018,
+- *    EPTP_LIST_ADDRESS               = 0x00002024,
+- *    VMREAD_BITMAP                   = 0x00002026,
+- *    VMWRITE_BITMAP                  = 0x00002028,
+- *
+- *    TSC_MULTIPLIER                  = 0x00002032,
+- *    PLE_GAP                         = 0x00004020,
+- *    PLE_WINDOW                      = 0x00004022,
+- *    VMX_PREEMPTION_TIMER_VALUE      = 0x0000482E,
+- *
+- * Currently unsupported in KVM:
+- *    GUEST_IA32_RTIT_CTL             = 0x00002814,
+- */
+-#define EVMCS1_SUPPORTED_PINCTRL                                      \
+-      (PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |                          \
+-       PIN_BASED_EXT_INTR_MASK |                                      \
+-       PIN_BASED_NMI_EXITING |                                        \
+-       PIN_BASED_VIRTUAL_NMIS)
+-
+-#define EVMCS1_SUPPORTED_EXEC_CTRL                                    \
+-      (CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR |                          \
+-       CPU_BASED_HLT_EXITING |                                        \
+-       CPU_BASED_CR3_LOAD_EXITING |                                   \
+-       CPU_BASED_CR3_STORE_EXITING |                                  \
+-       CPU_BASED_UNCOND_IO_EXITING |                                  \
+-       CPU_BASED_MOV_DR_EXITING |                                     \
+-       CPU_BASED_USE_TSC_OFFSETTING |                                 \
+-       CPU_BASED_MWAIT_EXITING |                                      \
+-       CPU_BASED_MONITOR_EXITING |                                    \
+-       CPU_BASED_INVLPG_EXITING |                                     \
+-       CPU_BASED_RDPMC_EXITING |                                      \
+-       CPU_BASED_INTR_WINDOW_EXITING |                                \
+-       CPU_BASED_CR8_LOAD_EXITING |                                   \
+-       CPU_BASED_CR8_STORE_EXITING |                                  \
+-       CPU_BASED_RDTSC_EXITING |                                      \
+-       CPU_BASED_TPR_SHADOW |                                         \
+-       CPU_BASED_USE_IO_BITMAPS |                                     \
+-       CPU_BASED_MONITOR_TRAP_FLAG |                                  \
+-       CPU_BASED_USE_MSR_BITMAPS |                                    \
+-       CPU_BASED_NMI_WINDOW_EXITING |                                 \
+-       CPU_BASED_PAUSE_EXITING |                                      \
+-       CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
+-
+-#define EVMCS1_SUPPORTED_2NDEXEC                                      \
+-      (SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |                        \
+-       SECONDARY_EXEC_WBINVD_EXITING |                                \
+-       SECONDARY_EXEC_ENABLE_VPID |                                   \
+-       SECONDARY_EXEC_ENABLE_EPT |                                    \
+-       SECONDARY_EXEC_UNRESTRICTED_GUEST |                            \
+-       SECONDARY_EXEC_DESC |                                          \
+-       SECONDARY_EXEC_ENABLE_RDTSCP |                                 \
+-       SECONDARY_EXEC_ENABLE_INVPCID |                                \
+-       SECONDARY_EXEC_ENABLE_XSAVES |                                 \
+-       SECONDARY_EXEC_RDSEED_EXITING |                                \
+-       SECONDARY_EXEC_RDRAND_EXITING |                                \
+-       SECONDARY_EXEC_TSC_SCALING |                                   \
+-       SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE |                         \
+-       SECONDARY_EXEC_PT_USE_GPA |                                    \
+-       SECONDARY_EXEC_PT_CONCEAL_VMX |                                \
+-       SECONDARY_EXEC_BUS_LOCK_DETECTION |                            \
+-       SECONDARY_EXEC_NOTIFY_VM_EXITING |                             \
+-       SECONDARY_EXEC_ENCLS_EXITING)
+-
+-#define EVMCS1_SUPPORTED_3RDEXEC (0ULL)
+-
+-#define EVMCS1_SUPPORTED_VMEXIT_CTRL                                  \
+-      (VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR |                            \
+-       VM_EXIT_SAVE_DEBUG_CONTROLS |                                  \
+-       VM_EXIT_ACK_INTR_ON_EXIT |                                     \
+-       VM_EXIT_HOST_ADDR_SPACE_SIZE |                                 \
+-       VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL |                           \
+-       VM_EXIT_SAVE_IA32_PAT |                                        \
+-       VM_EXIT_LOAD_IA32_PAT |                                        \
+-       VM_EXIT_SAVE_IA32_EFER |                                       \
+-       VM_EXIT_LOAD_IA32_EFER |                                       \
+-       VM_EXIT_CLEAR_BNDCFGS |                                        \
+-       VM_EXIT_PT_CONCEAL_PIP |                                       \
+-       VM_EXIT_CLEAR_IA32_RTIT_CTL)
+-
+-#define EVMCS1_SUPPORTED_VMENTRY_CTRL                                 \
+-      (VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR |                           \
+-       VM_ENTRY_LOAD_DEBUG_CONTROLS |                                 \
+-       VM_ENTRY_IA32E_MODE |                                          \
+-       VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL |                          \
+-       VM_ENTRY_LOAD_IA32_PAT |                                       \
+-       VM_ENTRY_LOAD_IA32_EFER |                                      \
+-       VM_ENTRY_LOAD_BNDCFGS |                                        \
+-       VM_ENTRY_PT_CONCEAL_PIP |                                      \
+-       VM_ENTRY_LOAD_IA32_RTIT_CTL)
+-
+-#define EVMCS1_SUPPORTED_VMFUNC (0)
+-
+ #define EVMCS1_OFFSET(x) offsetof(struct hv_enlightened_vmcs, x)
+ #define EVMCS1_FIELD(number, name, clean_field)[ROL16(number, 6)] = \
+               {EVMCS1_OFFSET(name), clean_field}
+@@ -608,40 +503,6 @@ int nested_evmcs_check_controls(struct vmcs12 *vmcs12)
+       return 0;
+ }
+-#if IS_ENABLED(CONFIG_HYPERV)
+-DEFINE_STATIC_KEY_FALSE(__kvm_is_using_evmcs);
+-
+-/*
+- * KVM on Hyper-V always uses the latest known eVMCSv1 revision, the assumption
+- * is: in case a feature has corresponding fields in eVMCS described and it was
+- * exposed in VMX feature MSRs, KVM is free to use it. Warn if KVM meets a
+- * feature which has no corresponding eVMCS field, this likely means that KVM
+- * needs to be updated.
+- */
+-#define evmcs_check_vmcs_conf(field, ctrl)                                    \
+-      do {                                                                    \
+-              typeof(vmcs_conf->field) unsupported;                           \
+-                                                                              \
+-              unsupported = vmcs_conf->field & ~EVMCS1_SUPPORTED_ ## ctrl;    \
+-              if (unsupported) {                                              \
+-                      pr_warn_once(#field " unsupported with eVMCS: 0x%llx\n",\
+-                                   (u64)unsupported);                         \
+-                      vmcs_conf->field &= EVMCS1_SUPPORTED_ ## ctrl;          \
+-              }                                                               \
+-      }                                                                       \
+-      while (0)
+-
+-void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf)
+-{
+-      evmcs_check_vmcs_conf(cpu_based_exec_ctrl, EXEC_CTRL);
+-      evmcs_check_vmcs_conf(pin_based_exec_ctrl, PINCTRL);
+-      evmcs_check_vmcs_conf(cpu_based_2nd_exec_ctrl, 2NDEXEC);
+-      evmcs_check_vmcs_conf(cpu_based_3rd_exec_ctrl, 3RDEXEC);
+-      evmcs_check_vmcs_conf(vmentry_ctrl, VMENTRY_CTRL);
+-      evmcs_check_vmcs_conf(vmexit_ctrl, VMEXIT_CTRL);
+-}
+-#endif
+-
+ int nested_enable_evmcs(struct kvm_vcpu *vcpu,
+                       uint16_t *vmcs_version)
+ {
+diff --git a/arch/x86/kvm/vmx/hyperv.h b/arch/x86/kvm/vmx/hyperv.h
+index 9623fe1651c48..9401dbfaea7ce 100644
+--- a/arch/x86/kvm/vmx/hyperv.h
++++ b/arch/x86/kvm/vmx/hyperv.h
+@@ -14,12 +14,113 @@
+ #include "vmcs.h"
+ #include "vmcs12.h"
+-struct vmcs_config;
+-
+-#define current_evmcs ((struct hv_enlightened_vmcs *)this_cpu_read(current_vmcs))
+-
+ #define KVM_EVMCS_VERSION 1
++/*
++ * Enlightened VMCSv1 doesn't support these:
++ *
++ *    POSTED_INTR_NV                  = 0x00000002,
++ *    GUEST_INTR_STATUS               = 0x00000810,
++ *    APIC_ACCESS_ADDR                = 0x00002014,
++ *    POSTED_INTR_DESC_ADDR           = 0x00002016,
++ *    EOI_EXIT_BITMAP0                = 0x0000201c,
++ *    EOI_EXIT_BITMAP1                = 0x0000201e,
++ *    EOI_EXIT_BITMAP2                = 0x00002020,
++ *    EOI_EXIT_BITMAP3                = 0x00002022,
++ *    GUEST_PML_INDEX                 = 0x00000812,
++ *    PML_ADDRESS                     = 0x0000200e,
++ *    VM_FUNCTION_CONTROL             = 0x00002018,
++ *    EPTP_LIST_ADDRESS               = 0x00002024,
++ *    VMREAD_BITMAP                   = 0x00002026,
++ *    VMWRITE_BITMAP                  = 0x00002028,
++ *
++ *    TSC_MULTIPLIER                  = 0x00002032,
++ *    PLE_GAP                         = 0x00004020,
++ *    PLE_WINDOW                      = 0x00004022,
++ *    VMX_PREEMPTION_TIMER_VALUE      = 0x0000482E,
++ *
++ * Currently unsupported in KVM:
++ *    GUEST_IA32_RTIT_CTL             = 0x00002814,
++ */
++#define EVMCS1_SUPPORTED_PINCTRL                                      \
++      (PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |                          \
++       PIN_BASED_EXT_INTR_MASK |                                      \
++       PIN_BASED_NMI_EXITING |                                        \
++       PIN_BASED_VIRTUAL_NMIS)
++
++#define EVMCS1_SUPPORTED_EXEC_CTRL                                    \
++      (CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR |                          \
++       CPU_BASED_HLT_EXITING |                                        \
++       CPU_BASED_CR3_LOAD_EXITING |                                   \
++       CPU_BASED_CR3_STORE_EXITING |                                  \
++       CPU_BASED_UNCOND_IO_EXITING |                                  \
++       CPU_BASED_MOV_DR_EXITING |                                     \
++       CPU_BASED_USE_TSC_OFFSETTING |                                 \
++       CPU_BASED_MWAIT_EXITING |                                      \
++       CPU_BASED_MONITOR_EXITING |                                    \
++       CPU_BASED_INVLPG_EXITING |                                     \
++       CPU_BASED_RDPMC_EXITING |                                      \
++       CPU_BASED_INTR_WINDOW_EXITING |                                \
++       CPU_BASED_CR8_LOAD_EXITING |                                   \
++       CPU_BASED_CR8_STORE_EXITING |                                  \
++       CPU_BASED_RDTSC_EXITING |                                      \
++       CPU_BASED_TPR_SHADOW |                                         \
++       CPU_BASED_USE_IO_BITMAPS |                                     \
++       CPU_BASED_MONITOR_TRAP_FLAG |                                  \
++       CPU_BASED_USE_MSR_BITMAPS |                                    \
++       CPU_BASED_NMI_WINDOW_EXITING |                                 \
++       CPU_BASED_PAUSE_EXITING |                                      \
++       CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
++
++#define EVMCS1_SUPPORTED_2NDEXEC                                      \
++      (SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |                        \
++       SECONDARY_EXEC_WBINVD_EXITING |                                \
++       SECONDARY_EXEC_ENABLE_VPID |                                   \
++       SECONDARY_EXEC_ENABLE_EPT |                                    \
++       SECONDARY_EXEC_UNRESTRICTED_GUEST |                            \
++       SECONDARY_EXEC_DESC |                                          \
++       SECONDARY_EXEC_ENABLE_RDTSCP |                                 \
++       SECONDARY_EXEC_ENABLE_INVPCID |                                \
++       SECONDARY_EXEC_ENABLE_XSAVES |                                 \
++       SECONDARY_EXEC_RDSEED_EXITING |                                \
++       SECONDARY_EXEC_RDRAND_EXITING |                                \
++       SECONDARY_EXEC_TSC_SCALING |                                   \
++       SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE |                         \
++       SECONDARY_EXEC_PT_USE_GPA |                                    \
++       SECONDARY_EXEC_PT_CONCEAL_VMX |                                \
++       SECONDARY_EXEC_BUS_LOCK_DETECTION |                            \
++       SECONDARY_EXEC_NOTIFY_VM_EXITING |                             \
++       SECONDARY_EXEC_ENCLS_EXITING)
++
++#define EVMCS1_SUPPORTED_3RDEXEC (0ULL)
++
++#define EVMCS1_SUPPORTED_VMEXIT_CTRL                                  \
++      (VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR |                            \
++       VM_EXIT_SAVE_DEBUG_CONTROLS |                                  \
++       VM_EXIT_ACK_INTR_ON_EXIT |                                     \
++       VM_EXIT_HOST_ADDR_SPACE_SIZE |                                 \
++       VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL |                           \
++       VM_EXIT_SAVE_IA32_PAT |                                        \
++       VM_EXIT_LOAD_IA32_PAT |                                        \
++       VM_EXIT_SAVE_IA32_EFER |                                       \
++       VM_EXIT_LOAD_IA32_EFER |                                       \
++       VM_EXIT_CLEAR_BNDCFGS |                                        \
++       VM_EXIT_PT_CONCEAL_PIP |                                       \
++       VM_EXIT_CLEAR_IA32_RTIT_CTL)
++
++#define EVMCS1_SUPPORTED_VMENTRY_CTRL                                 \
++      (VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR |                           \
++       VM_ENTRY_LOAD_DEBUG_CONTROLS |                                 \
++       VM_ENTRY_IA32E_MODE |                                          \
++       VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL |                          \
++       VM_ENTRY_LOAD_IA32_PAT |                                       \
++       VM_ENTRY_LOAD_IA32_EFER |                                      \
++       VM_ENTRY_LOAD_BNDCFGS |                                        \
++       VM_ENTRY_PT_CONCEAL_PIP |                                      \
++       VM_ENTRY_LOAD_IA32_RTIT_CTL)
++
++#define EVMCS1_SUPPORTED_VMFUNC (0)
++
+ struct evmcs_field {
+       u16 offset;
+       u16 clean_field;
+@@ -65,114 +166,6 @@ static inline u64 evmcs_read_any(struct hv_enlightened_vmcs *evmcs,
+       return vmcs12_read_any((void *)evmcs, field, offset);
+ }
+-#if IS_ENABLED(CONFIG_HYPERV)
+-
+-DECLARE_STATIC_KEY_FALSE(__kvm_is_using_evmcs);
+-
+-static __always_inline bool kvm_is_using_evmcs(void)
+-{
+-      return static_branch_unlikely(&__kvm_is_using_evmcs);
+-}
+-
+-static __always_inline int get_evmcs_offset(unsigned long field,
+-                                          u16 *clean_field)
+-{
+-      int offset = evmcs_field_offset(field, clean_field);
+-
+-      WARN_ONCE(offset < 0, "accessing unsupported EVMCS field %lx\n", field);
+-      return offset;
+-}
+-
+-static __always_inline void evmcs_write64(unsigned long field, u64 value)
+-{
+-      u16 clean_field;
+-      int offset = get_evmcs_offset(field, &clean_field);
+-
+-      if (offset < 0)
+-              return;
+-
+-      *(u64 *)((char *)current_evmcs + offset) = value;
+-
+-      current_evmcs->hv_clean_fields &= ~clean_field;
+-}
+-
+-static __always_inline void evmcs_write32(unsigned long field, u32 value)
+-{
+-      u16 clean_field;
+-      int offset = get_evmcs_offset(field, &clean_field);
+-
+-      if (offset < 0)
+-              return;
+-
+-      *(u32 *)((char *)current_evmcs + offset) = value;
+-      current_evmcs->hv_clean_fields &= ~clean_field;
+-}
+-
+-static __always_inline void evmcs_write16(unsigned long field, u16 value)
+-{
+-      u16 clean_field;
+-      int offset = get_evmcs_offset(field, &clean_field);
+-
+-      if (offset < 0)
+-              return;
+-
+-      *(u16 *)((char *)current_evmcs + offset) = value;
+-      current_evmcs->hv_clean_fields &= ~clean_field;
+-}
+-
+-static __always_inline u64 evmcs_read64(unsigned long field)
+-{
+-      int offset = get_evmcs_offset(field, NULL);
+-
+-      if (offset < 0)
+-              return 0;
+-
+-      return *(u64 *)((char *)current_evmcs + offset);
+-}
+-
+-static __always_inline u32 evmcs_read32(unsigned long field)
+-{
+-      int offset = get_evmcs_offset(field, NULL);
+-
+-      if (offset < 0)
+-              return 0;
+-
+-      return *(u32 *)((char *)current_evmcs + offset);
+-}
+-
+-static __always_inline u16 evmcs_read16(unsigned long field)
+-{
+-      int offset = get_evmcs_offset(field, NULL);
+-
+-      if (offset < 0)
+-              return 0;
+-
+-      return *(u16 *)((char *)current_evmcs + offset);
+-}
+-
+-static inline void evmcs_load(u64 phys_addr)
+-{
+-      struct hv_vp_assist_page *vp_ap =
+-              hv_get_vp_assist_page(smp_processor_id());
+-
+-      if (current_evmcs->hv_enlightenments_control.nested_flush_hypercall)
+-              vp_ap->nested_control.features.directhypercall = 1;
+-      vp_ap->current_nested_vmcs = phys_addr;
+-      vp_ap->enlighten_vmentry = 1;
+-}
+-
+-void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf);
+-#else /* !IS_ENABLED(CONFIG_HYPERV) */
+-static __always_inline bool kvm_is_using_evmcs(void) { return false; }
+-static __always_inline void evmcs_write64(unsigned long field, u64 value) {}
+-static __always_inline void evmcs_write32(unsigned long field, u32 value) {}
+-static __always_inline void evmcs_write16(unsigned long field, u16 value) {}
+-static __always_inline u64 evmcs_read64(unsigned long field) { return 0; }
+-static __always_inline u32 evmcs_read32(unsigned long field) { return 0; }
+-static __always_inline u16 evmcs_read16(unsigned long field) { return 0; }
+-static inline void evmcs_load(u64 phys_addr) {}
+-#endif /* IS_ENABLED(CONFIG_HYPERV) */
+-
+ #define EVMPTR_INVALID (-1ULL)
+ #define EVMPTR_MAP_PENDING (-2ULL)
+diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
+index f5f652a546bf2..09d26b46800d4 100644
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -66,6 +66,7 @@
+ #include "vmx.h"
+ #include "x86.h"
+ #include "smm.h"
++#include "vmx_onhyperv.h"
+ MODULE_AUTHOR("Qumranet");
+ MODULE_LICENSE("GPL");
+diff --git a/arch/x86/kvm/vmx/vmx_onhyperv.c b/arch/x86/kvm/vmx/vmx_onhyperv.c
+new file mode 100644
+index 0000000000000..b9a8b91166d02
+--- /dev/null
++++ b/arch/x86/kvm/vmx/vmx_onhyperv.c
+@@ -0,0 +1,36 @@
++// SPDX-License-Identifier: GPL-2.0-only
++
++#include "capabilities.h"
++#include "vmx_onhyperv.h"
++
++DEFINE_STATIC_KEY_FALSE(__kvm_is_using_evmcs);
++
++/*
++ * KVM on Hyper-V always uses the latest known eVMCSv1 revision, the assumption
++ * is: in case a feature has corresponding fields in eVMCS described and it was
++ * exposed in VMX feature MSRs, KVM is free to use it. Warn if KVM meets a
++ * feature which has no corresponding eVMCS field, this likely means that KVM
++ * needs to be updated.
++ */
++#define evmcs_check_vmcs_conf(field, ctrl)                                    \
++      do {                                                                    \
++              typeof(vmcs_conf->field) unsupported;                           \
++                                                                              \
++              unsupported = vmcs_conf->field & ~EVMCS1_SUPPORTED_ ## ctrl;    \
++              if (unsupported) {                                              \
++                      pr_warn_once(#field " unsupported with eVMCS: 0x%llx\n",\
++                                   (u64)unsupported);                         \
++                      vmcs_conf->field &= EVMCS1_SUPPORTED_ ## ctrl;          \
++              }                                                               \
++      }                                                                       \
++      while (0)
++
++void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf)
++{
++      evmcs_check_vmcs_conf(cpu_based_exec_ctrl, EXEC_CTRL);
++      evmcs_check_vmcs_conf(pin_based_exec_ctrl, PINCTRL);
++      evmcs_check_vmcs_conf(cpu_based_2nd_exec_ctrl, 2NDEXEC);
++      evmcs_check_vmcs_conf(cpu_based_3rd_exec_ctrl, 3RDEXEC);
++      evmcs_check_vmcs_conf(vmentry_ctrl, VMENTRY_CTRL);
++      evmcs_check_vmcs_conf(vmexit_ctrl, VMEXIT_CTRL);
++}
+diff --git a/arch/x86/kvm/vmx/vmx_onhyperv.h b/arch/x86/kvm/vmx/vmx_onhyperv.h
+new file mode 100644
+index 0000000000000..11541d272dbd8
+--- /dev/null
++++ b/arch/x86/kvm/vmx/vmx_onhyperv.h
+@@ -0,0 +1,124 @@
++/* SPDX-License-Identifier: GPL-2.0-only */
++
++#ifndef __ARCH_X86_KVM_VMX_ONHYPERV_H__
++#define __ARCH_X86_KVM_VMX_ONHYPERV_H__
++
++#include <asm/hyperv-tlfs.h>
++
++#include <linux/jump_label.h>
++
++#include "capabilities.h"
++#include "hyperv.h"
++#include "vmcs12.h"
++
++#define current_evmcs ((struct hv_enlightened_vmcs *)this_cpu_read(current_vmcs))
++
++#if IS_ENABLED(CONFIG_HYPERV)
++
++DECLARE_STATIC_KEY_FALSE(__kvm_is_using_evmcs);
++
++static __always_inline bool kvm_is_using_evmcs(void)
++{
++      return static_branch_unlikely(&__kvm_is_using_evmcs);
++}
++
++static __always_inline int get_evmcs_offset(unsigned long field,
++                                          u16 *clean_field)
++{
++      int offset = evmcs_field_offset(field, clean_field);
++
++      WARN_ONCE(offset < 0, "accessing unsupported EVMCS field %lx\n", field);
++      return offset;
++}
++
++static __always_inline void evmcs_write64(unsigned long field, u64 value)
++{
++      u16 clean_field;
++      int offset = get_evmcs_offset(field, &clean_field);
++
++      if (offset < 0)
++              return;
++
++      *(u64 *)((char *)current_evmcs + offset) = value;
++
++      current_evmcs->hv_clean_fields &= ~clean_field;
++}
++
++static __always_inline void evmcs_write32(unsigned long field, u32 value)
++{
++      u16 clean_field;
++      int offset = get_evmcs_offset(field, &clean_field);
++
++      if (offset < 0)
++              return;
++
++      *(u32 *)((char *)current_evmcs + offset) = value;
++      current_evmcs->hv_clean_fields &= ~clean_field;
++}
++
++static __always_inline void evmcs_write16(unsigned long field, u16 value)
++{
++      u16 clean_field;
++      int offset = get_evmcs_offset(field, &clean_field);
++
++      if (offset < 0)
++              return;
++
++      *(u16 *)((char *)current_evmcs + offset) = value;
++      current_evmcs->hv_clean_fields &= ~clean_field;
++}
++
++static __always_inline u64 evmcs_read64(unsigned long field)
++{
++      int offset = get_evmcs_offset(field, NULL);
++
++      if (offset < 0)
++              return 0;
++
++      return *(u64 *)((char *)current_evmcs + offset);
++}
++
++static __always_inline u32 evmcs_read32(unsigned long field)
++{
++      int offset = get_evmcs_offset(field, NULL);
++
++      if (offset < 0)
++              return 0;
++
++      return *(u32 *)((char *)current_evmcs + offset);
++}
++
++static __always_inline u16 evmcs_read16(unsigned long field)
++{
++      int offset = get_evmcs_offset(field, NULL);
++
++      if (offset < 0)
++              return 0;
++
++      return *(u16 *)((char *)current_evmcs + offset);
++}
++
++static inline void evmcs_load(u64 phys_addr)
++{
++      struct hv_vp_assist_page *vp_ap =
++              hv_get_vp_assist_page(smp_processor_id());
++
++      if (current_evmcs->hv_enlightenments_control.nested_flush_hypercall)
++              vp_ap->nested_control.features.directhypercall = 1;
++      vp_ap->current_nested_vmcs = phys_addr;
++      vp_ap->enlighten_vmentry = 1;
++}
++
++void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf);
++#else /* !IS_ENABLED(CONFIG_HYPERV) */
++static __always_inline bool kvm_is_using_evmcs(void) { return false; }
++static __always_inline void evmcs_write64(unsigned long field, u64 value) {}
++static __always_inline void evmcs_write32(unsigned long field, u32 value) {}
++static __always_inline void evmcs_write16(unsigned long field, u16 value) {}
++static __always_inline u64 evmcs_read64(unsigned long field) { return 0; }
++static __always_inline u32 evmcs_read32(unsigned long field) { return 0; }
++static __always_inline u16 evmcs_read16(unsigned long field) { return 0; }
++static inline void evmcs_load(u64 phys_addr) {}
++#endif /* IS_ENABLED(CONFIG_HYPERV) */
++
++#endif /* __ARCH_X86_KVM_VMX_ONHYPERV_H__ */
+diff --git a/arch/x86/kvm/vmx/vmx_ops.h b/arch/x86/kvm/vmx/vmx_ops.h
+index 6a0c6e81f7f3e..8060e5fc6dbd8 100644
+--- a/arch/x86/kvm/vmx/vmx_ops.h
++++ b/arch/x86/kvm/vmx/vmx_ops.h
+@@ -6,7 +6,7 @@
+ #include <asm/vmx.h>
+-#include "hyperv.h"
++#include "vmx_onhyperv.h"
+ #include "vmcs.h"
+ #include "../x86.h"
+-- 
+2.43.0
+
diff --git a/queue-6.6/leds-trigger-call-synchronize_rcu-before-calling-tri.patch b/queue-6.6/leds-trigger-call-synchronize_rcu-before-calling-tri.patch
new file mode 100644 (file)
index 0000000..59a8237
--- /dev/null
@@ -0,0 +1,60 @@
+From 3a52063c3f8a3658f7570e691738eea2372254ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 May 2024 14:01:24 +0200
+Subject: leds: trigger: Call synchronize_rcu() before calling trig->activate()
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit b1bbd20f35e19774ea01989320495e09ac44fba3 ]
+
+Some triggers call led_trigger_event() from their activate() callback
+to initialize the brightness of the LED for which the trigger is being
+activated.
+
+In order for the LED's initial state to be set correctly this requires that
+the led_trigger_event() call uses the new version of trigger->led_cdevs,
+which has the new LED.
+
+AFAICT led_trigger_event() will always use the new version when it is
+running on the same CPU as where the list_add_tail_rcu() call was made,
+which is why the missing synchronize_rcu() has not lead to bug reports.
+But if activate() is pre-empted, sleeps or uses a worker then
+the led_trigger_event() call may run on another CPU which may still use
+the old trigger->led_cdevs list.
+
+Add a synchronize_rcu() call to ensure that any led_trigger_event() calls
+done from activate() always use the new list.
+
+Triggers using led_trigger_event() from their activate() callback are:
+net/bluetooth/leds.c, net/rfkill/core.c and drivers/tty/vt/keyboard.c.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20240531120124.75662-1-hdegoede@redhat.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Stable-dep-of: ab477b766edd ("leds: triggers: Flush pending brightness before activating trigger")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/led-triggers.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
+index 38f7896f374f6..baa5365c26047 100644
+--- a/drivers/leds/led-triggers.c
++++ b/drivers/leds/led-triggers.c
+@@ -194,6 +194,13 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
+               spin_unlock(&trig->leddev_list_lock);
+               led_cdev->trigger = trig;
++              /*
++               * Some activate() calls use led_trigger_event() to initialize
++               * the brightness of the LED for which the trigger is being set.
++               * Ensure the led_cdev is visible on trig->led_cdevs for this.
++               */
++              synchronize_rcu();
++
+               ret = 0;
+               if (trig->activate)
+                       ret = trig->activate(led_cdev);
+-- 
+2.43.0
+
diff --git a/queue-6.6/leds-trigger-remove-unused-function-led_trigger_rena.patch b/queue-6.6/leds-trigger-remove-unused-function-led_trigger_rena.patch
new file mode 100644 (file)
index 0000000..29d9f97
--- /dev/null
@@ -0,0 +1,77 @@
+From 793adb4eca7d8567f77d5aeaafde64f6bc691437 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Dec 2023 23:56:41 +0100
+Subject: leds: trigger: Remove unused function led_trigger_rename_static()
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit c82a1662d4548c454de5343b88f69b9fc82266b3 ]
+
+This function was added with a8df7b1ab70b ("leds: add led_trigger_rename
+function") 11 yrs ago, but it has no users. So remove it.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/d90f30be-f661-4db7-b0b5-d09d07a78a68@gmail.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Stable-dep-of: ab477b766edd ("leds: triggers: Flush pending brightness before activating trigger")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/led-triggers.c | 13 -------------
+ include/linux/leds.h        | 17 -----------------
+ 2 files changed, 30 deletions(-)
+
+diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
+index 4f5829b726a75..081acf1f345b3 100644
+--- a/drivers/leds/led-triggers.c
++++ b/drivers/leds/led-triggers.c
+@@ -269,19 +269,6 @@ void led_trigger_set_default(struct led_classdev *led_cdev)
+ }
+ EXPORT_SYMBOL_GPL(led_trigger_set_default);
+-void led_trigger_rename_static(const char *name, struct led_trigger *trig)
+-{
+-      /* new name must be on a temporary string to prevent races */
+-      BUG_ON(name == trig->name);
+-
+-      down_write(&triggers_list_lock);
+-      /* this assumes that trig->name was originaly allocated to
+-       * non constant storage */
+-      strcpy((char *)trig->name, name);
+-      up_write(&triggers_list_lock);
+-}
+-EXPORT_SYMBOL_GPL(led_trigger_rename_static);
+-
+ /* LED Trigger Interface */
+ int led_trigger_register(struct led_trigger *trig)
+diff --git a/include/linux/leds.h b/include/linux/leds.h
+index aa16dc2a8230f..6a4973feecd65 100644
+--- a/include/linux/leds.h
++++ b/include/linux/leds.h
+@@ -527,23 +527,6 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
+       return led_cdev->trigger_data;
+ }
+-/**
+- * led_trigger_rename_static - rename a trigger
+- * @name: the new trigger name
+- * @trig: the LED trigger to rename
+- *
+- * Change a LED trigger name by copying the string passed in
+- * name into current trigger name, which MUST be large
+- * enough for the new string.
+- *
+- * Note that name must NOT point to the same string used
+- * during LED registration, as that could lead to races.
+- *
+- * This is meant to be used on triggers with statically
+- * allocated name.
+- */
+-void led_trigger_rename_static(const char *name, struct led_trigger *trig);
+-
+ #define module_led_trigger(__led_trigger) \
+       module_driver(__led_trigger, led_trigger_register, \
+                     led_trigger_unregister)
+-- 
+2.43.0
+
diff --git a/queue-6.6/leds-trigger-store-brightness-set-by-led_trigger_eve.patch b/queue-6.6/leds-trigger-store-brightness-set-by-led_trigger_eve.patch
new file mode 100644 (file)
index 0000000..007ca32
--- /dev/null
@@ -0,0 +1,98 @@
+From 3830b540c7ec401419f44240eac2326305886425 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 21:57:30 +0100
+Subject: leds: trigger: Store brightness set by led_trigger_event()
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit 822c91e72eac568ed8d83765634f00decb45666c ]
+
+If a simple trigger is assigned to a LED, then the LED may be off until
+the next led_trigger_event() call. This may be an issue for simple
+triggers with rare led_trigger_event() calls, e.g. power supply
+charging indicators (drivers/power/supply/power_supply_leds.c).
+Therefore persist the brightness value of the last led_trigger_event()
+call and use this value if the trigger is assigned to a LED.
+In addition add a getter for the trigger brightness value.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Link: https://lore.kernel.org/r/b1358b25-3f30-458d-8240-5705ae007a8a@gmail.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Stable-dep-of: ab477b766edd ("leds: triggers: Flush pending brightness before activating trigger")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/led-triggers.c |  6 ++++--
+ include/linux/leds.h        | 15 +++++++++++++++
+ 2 files changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
+index 081acf1f345b3..38f7896f374f6 100644
+--- a/drivers/leds/led-triggers.c
++++ b/drivers/leds/led-triggers.c
+@@ -194,11 +194,11 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
+               spin_unlock(&trig->leddev_list_lock);
+               led_cdev->trigger = trig;
++              ret = 0;
+               if (trig->activate)
+                       ret = trig->activate(led_cdev);
+               else
+-                      ret = 0;
+-
++                      led_set_brightness(led_cdev, trig->brightness);
+               if (ret)
+                       goto err_activate;
+@@ -373,6 +373,8 @@ void led_trigger_event(struct led_trigger *trig,
+       if (!trig)
+               return;
++      trig->brightness = brightness;
++
+       rcu_read_lock();
+       list_for_each_entry_rcu(led_cdev, &trig->led_cdevs, trig_list)
+               led_set_brightness(led_cdev, brightness);
+diff --git a/include/linux/leds.h b/include/linux/leds.h
+index 6a4973feecd65..d3056bc6f0a1a 100644
+--- a/include/linux/leds.h
++++ b/include/linux/leds.h
+@@ -474,6 +474,9 @@ struct led_trigger {
+       int             (*activate)(struct led_classdev *led_cdev);
+       void            (*deactivate)(struct led_classdev *led_cdev);
++      /* Brightness set by led_trigger_event */
++      enum led_brightness brightness;
++
+       /* LED-private triggers have this set */
+       struct led_hw_trigger_type *trigger_type;
+@@ -527,6 +530,12 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
+       return led_cdev->trigger_data;
+ }
++static inline enum led_brightness
++led_trigger_get_brightness(const struct led_trigger *trigger)
++{
++      return trigger ? trigger->brightness : LED_OFF;
++}
++
+ #define module_led_trigger(__led_trigger) \
+       module_driver(__led_trigger, led_trigger_register, \
+                     led_trigger_unregister)
+@@ -563,6 +572,12 @@ static inline void *led_get_trigger_data(struct led_classdev *led_cdev)
+       return NULL;
+ }
++static inline enum led_brightness
++led_trigger_get_brightness(const struct led_trigger *trigger)
++{
++      return LED_OFF;
++}
++
+ #endif /* CONFIG_LEDS_TRIGGERS */
+ /* Trigger specific enum */
+-- 
+2.43.0
+
diff --git a/queue-6.6/leds-triggers-flush-pending-brightness-before-activa.patch b/queue-6.6/leds-triggers-flush-pending-brightness-before-activa.patch
new file mode 100644 (file)
index 0000000..c1ba56b
--- /dev/null
@@ -0,0 +1,66 @@
+From 1c90e2761168949bac909059f34b37f9e633a159 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Jun 2024 17:24:51 +0200
+Subject: leds: triggers: Flush pending brightness before activating trigger
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit ab477b766edd3bfb6321a6e3df4c790612613fae ]
+
+The race fixed in timer_trig_activate() between a blocking
+set_brightness() call and trigger->activate() can affect any trigger.
+So move the call to flush_work() into led_trigger_set() where it can
+avoid the race for all triggers.
+
+Fixes: 0db37915d912 ("leds: avoid races with workqueue")
+Fixes: 8c0f693c6eff ("leds: avoid flush_work in atomic context")
+Cc: stable@vger.kernel.org
+Tested-by: Dustin L. Howett <dustin@howett.net>
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Link: https://lore.kernel.org/r/20240613-led-trigger-flush-v2-1-f4f970799d77@weissschuh.net
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/led-triggers.c          | 6 ++++++
+ drivers/leds/trigger/ledtrig-timer.c | 5 -----
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
+index baa5365c26047..72fd2fe8f6fe8 100644
+--- a/drivers/leds/led-triggers.c
++++ b/drivers/leds/led-triggers.c
+@@ -201,6 +201,12 @@ int led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
+                */
+               synchronize_rcu();
++              /*
++               * If "set brightness to 0" is pending in workqueue,
++               * we don't want that to be reordered after ->activate()
++               */
++              flush_work(&led_cdev->set_brightness_work);
++
+               ret = 0;
+               if (trig->activate)
+                       ret = trig->activate(led_cdev);
+diff --git a/drivers/leds/trigger/ledtrig-timer.c b/drivers/leds/trigger/ledtrig-timer.c
+index b4688d1d9d2b2..1d213c999d40a 100644
+--- a/drivers/leds/trigger/ledtrig-timer.c
++++ b/drivers/leds/trigger/ledtrig-timer.c
+@@ -110,11 +110,6 @@ static int timer_trig_activate(struct led_classdev *led_cdev)
+               led_cdev->flags &= ~LED_INIT_DEFAULT_TRIGGER;
+       }
+-      /*
+-       * If "set brightness to 0" is pending in workqueue, we don't
+-       * want that to be reordered after blink_set()
+-       */
+-      flush_work(&led_cdev->set_brightness_work);
+       led_blink_set(led_cdev, &led_cdev->blink_delay_on,
+                     &led_cdev->blink_delay_off);
+-- 
+2.43.0
+
diff --git a/queue-6.6/mips-dts-loongson-fix-liointc-irq-polarity.patch b/queue-6.6/mips-dts-loongson-fix-liointc-irq-polarity.patch
new file mode 100644 (file)
index 0000000..4c632b5
--- /dev/null
@@ -0,0 +1,172 @@
+From 3e7487e6b042ff4461b2eea8c71577eab26bbe64 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 16:40:10 +0100
+Subject: MIPS: dts: loongson: Fix liointc IRQ polarity
+
+From: Jiaxun Yang <jiaxun.yang@flygoat.com>
+
+[ Upstream commit dbb69b9d6234aad23b3ecd33e5bc8a8ae1485b7d ]
+
+All internal liointc interrupts are high level triggered.
+
+Fixes: b1a792601f26 ("MIPS: Loongson64: DeviceTree for Loongson-2K1000")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../boot/dts/loongson/loongson64-2k1000.dtsi  | 42 +++++++++----------
+ 1 file changed, 21 insertions(+), 21 deletions(-)
+
+diff --git a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+index c1d3092fdd870..eec8243be6499 100644
+--- a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
++++ b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+@@ -100,7 +100,7 @@ rtc0: rtc@1fe07800 {
+                       compatible = "loongson,ls2k1000-rtc";
+                       reg = <0 0x1fe07800 0 0x78>;
+                       interrupt-parent = <&liointc0>;
+-                      interrupts = <60 IRQ_TYPE_LEVEL_LOW>;
++                      interrupts = <60 IRQ_TYPE_LEVEL_HIGH>;
+               };
+               uart0: serial@1fe00000 {
+@@ -108,7 +108,7 @@ uart0: serial@1fe00000 {
+                       reg = <0 0x1fe00000 0 0x8>;
+                       clock-frequency = <125000000>;
+                       interrupt-parent = <&liointc0>;
+-                      interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
++                      interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+                       no-loopback-test;
+               };
+@@ -131,8 +131,8 @@ gmac@3,0 {
+                                                  "pciclass0c03";
+                               reg = <0x1800 0x0 0x0 0x0 0x0>;
+-                              interrupts = <12 IRQ_TYPE_LEVEL_LOW>,
+-                                           <13 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <12 IRQ_TYPE_LEVEL_HIGH>,
++                                           <13 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "macirq", "eth_lpi";
+                               interrupt-parent = <&liointc0>;
+                               phy-mode = "rgmii-id";
+@@ -155,8 +155,8 @@ gmac@3,1 {
+                                                  "loongson, pci-gmac";
+                               reg = <0x1900 0x0 0x0 0x0 0x0>;
+-                              interrupts = <14 IRQ_TYPE_LEVEL_LOW>,
+-                                           <15 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <14 IRQ_TYPE_LEVEL_HIGH>,
++                                           <15 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "macirq", "eth_lpi";
+                               interrupt-parent = <&liointc0>;
+                               phy-mode = "rgmii-id";
+@@ -178,7 +178,7 @@ ehci@4,1 {
+                                                  "pciclass0c03";
+                               reg = <0x2100 0x0 0x0 0x0 0x0>;
+-                              interrupts = <18 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <18 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                       };
+@@ -189,7 +189,7 @@ ohci@4,2 {
+                                                  "pciclass0c03";
+                               reg = <0x2200 0x0 0x0 0x0 0x0>;
+-                              interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <19 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                       };
+@@ -200,7 +200,7 @@ sata@8,0 {
+                                                  "pciclass0106";
+                               reg = <0x4000 0x0 0x0 0x0 0x0>;
+-                              interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <19 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc0>;
+                       };
+@@ -215,10 +215,10 @@ pcie@9,0 {
+                               #size-cells = <2>;
+                               device_type = "pci";
+                               #interrupt-cells = <1>;
+-                              interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &liointc1 0 IRQ_TYPE_LEVEL_LOW>;
++                              interrupt-map = <0 0 0 0 &liointc1 0 IRQ_TYPE_LEVEL_HIGH>;
+                               ranges;
+                               external-facing;
+                       };
+@@ -234,10 +234,10 @@ pcie@a,0 {
+                               #size-cells = <2>;
+                               device_type = "pci";
+                               #interrupt-cells = <1>;
+-                              interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &liointc1 1 IRQ_TYPE_LEVEL_LOW>;
++                              interrupt-map = <0 0 0 0 &liointc1 1 IRQ_TYPE_LEVEL_HIGH>;
+                               ranges;
+                               external-facing;
+                       };
+@@ -253,10 +253,10 @@ pcie@b,0 {
+                               #size-cells = <2>;
+                               device_type = "pci";
+                               #interrupt-cells = <1>;
+-                              interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &liointc1 2 IRQ_TYPE_LEVEL_LOW>;
++                              interrupt-map = <0 0 0 0 &liointc1 2 IRQ_TYPE_LEVEL_HIGH>;
+                               ranges;
+                               external-facing;
+                       };
+@@ -272,10 +272,10 @@ pcie@c,0 {
+                               #size-cells = <2>;
+                               device_type = "pci";
+                               #interrupt-cells = <1>;
+-                              interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &liointc1 3 IRQ_TYPE_LEVEL_LOW>;
++                              interrupt-map = <0 0 0 0 &liointc1 3 IRQ_TYPE_LEVEL_HIGH>;
+                               ranges;
+                               external-facing;
+                       };
+@@ -291,10 +291,10 @@ pcie@d,0 {
+                               #size-cells = <2>;
+                               device_type = "pci";
+                               #interrupt-cells = <1>;
+-                              interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &liointc1 4 IRQ_TYPE_LEVEL_LOW>;
++                              interrupt-map = <0 0 0 0 &liointc1 4 IRQ_TYPE_LEVEL_HIGH>;
+                               ranges;
+                               external-facing;
+                       };
+@@ -310,10 +310,10 @@ pcie@e,0 {
+                               #size-cells = <2>;
+                               device_type = "pci";
+                               #interrupt-cells = <1>;
+-                              interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &liointc1 5 IRQ_TYPE_LEVEL_LOW>;
++                              interrupt-map = <0 0 0 0 &liointc1 5 IRQ_TYPE_LEVEL_HIGH>;
+                               ranges;
+                               external-facing;
+                       };
+-- 
+2.43.0
+
diff --git a/queue-6.6/mips-dts-loongson-fix-ls2k1000-rtc-interrupt.patch b/queue-6.6/mips-dts-loongson-fix-ls2k1000-rtc-interrupt.patch
new file mode 100644 (file)
index 0000000..6f1ccfc
--- /dev/null
@@ -0,0 +1,38 @@
+From e87e764893e08797d8bd0c045d59cd52ea459edd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 16:40:11 +0100
+Subject: MIPS: dts: loongson: Fix ls2k1000-rtc interrupt
+
+From: Jiaxun Yang <jiaxun.yang@flygoat.com>
+
+[ Upstream commit f70fd92df7529e7283e02a6c3a2510075f13ba30 ]
+
+The correct interrupt line for RTC is line 8 on liointc1.
+
+Fixes: e47084e116fc ("MIPS: Loongson64: DTS: Add RTC support to Loongson-2K1000")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+index eec8243be6499..cc7747c5f21f3 100644
+--- a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
++++ b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+@@ -99,8 +99,8 @@ liointc1: interrupt-controller@1fe11440 {
+               rtc0: rtc@1fe07800 {
+                       compatible = "loongson,ls2k1000-rtc";
+                       reg = <0 0x1fe07800 0 0x78>;
+-                      interrupt-parent = <&liointc0>;
+-                      interrupts = <60 IRQ_TYPE_LEVEL_HIGH>;
++                      interrupt-parent = <&liointc1>;
++                      interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+               };
+               uart0: serial@1fe00000 {
+-- 
+2.43.0
+
diff --git a/queue-6.6/mips-loongson64-dts-fix-pcie-port-nodes-for-ls7a.patch b/queue-6.6/mips-loongson64-dts-fix-pcie-port-nodes-for-ls7a.patch
new file mode 100644 (file)
index 0000000..b70c2a5
--- /dev/null
@@ -0,0 +1,161 @@
+From 9918a24a27bfede8b27b057a9079be92af462aab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 May 2024 19:51:22 +0100
+Subject: MIPS: Loongson64: DTS: Fix PCIe port nodes for ls7a
+
+From: Jiaxun Yang <jiaxun.yang@flygoat.com>
+
+[ Upstream commit d89a415ff8d5e0aad4963f2d8ebb0f9e8110b7fa ]
+
+Add various required properties to silent warnings:
+
+arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi:116.16-297.5: Warning (interrupt_provider): /bus@10000000/pci@1a000000: '#interrupt-cells' found, but node is not an interrupt provider
+arch/mips/boot/dts/loongson/loongson64_2core_2k1000.dtb: Warning (interrupt_map): Failed prerequisite 'interrupt_provider'
+
+Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Stable-dep-of: dbb69b9d6234 ("MIPS: dts: loongson: Fix liointc IRQ polarity")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../boot/dts/loongson/loongson64-2k1000.dtsi  | 37 +++++++++++++++----
+ 1 file changed, 30 insertions(+), 7 deletions(-)
+
+diff --git a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+index c0be84a6e81fd..c1d3092fdd870 100644
+--- a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
++++ b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+@@ -117,7 +117,6 @@ pci@1a000000 {
+                       device_type = "pci";
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+-                      #interrupt-cells = <2>;
+                       reg = <0 0x1a000000 0 0x02000000>,
+                               <0xfe 0x00000000 0 0x20000000>;
+@@ -205,93 +204,117 @@ sata@8,0 {
+                               interrupt-parent = <&liointc0>;
+                       };
+-                      pci_bridge@9,0 {
++                      pcie@9,0 {
+                               compatible = "pci0014,7a19.0",
+                                                  "pci0014,7a19",
+                                                  "pciclass060400",
+                                                  "pciclass0604";
+                               reg = <0x4800 0x0 0x0 0x0 0x0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              device_type = "pci";
+                               #interrupt-cells = <1>;
+                               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &liointc1 0 IRQ_TYPE_LEVEL_LOW>;
++                              ranges;
+                               external-facing;
+                       };
+-                      pci_bridge@a,0 {
++                      pcie@a,0 {
+                               compatible = "pci0014,7a09.0",
+                                                  "pci0014,7a09",
+                                                  "pciclass060400",
+                                                  "pciclass0604";
+                               reg = <0x5000 0x0 0x0 0x0 0x0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              device_type = "pci";
+                               #interrupt-cells = <1>;
+                               interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &liointc1 1 IRQ_TYPE_LEVEL_LOW>;
++                              ranges;
+                               external-facing;
+                       };
+-                      pci_bridge@b,0 {
++                      pcie@b,0 {
+                               compatible = "pci0014,7a09.0",
+                                                  "pci0014,7a09",
+                                                  "pciclass060400",
+                                                  "pciclass0604";
+                               reg = <0x5800 0x0 0x0 0x0 0x0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              device_type = "pci";
+                               #interrupt-cells = <1>;
+                               interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &liointc1 2 IRQ_TYPE_LEVEL_LOW>;
++                              ranges;
+                               external-facing;
+                       };
+-                      pci_bridge@c,0 {
++                      pcie@c,0 {
+                               compatible = "pci0014,7a09.0",
+                                                  "pci0014,7a09",
+                                                  "pciclass060400",
+                                                  "pciclass0604";
+                               reg = <0x6000 0x0 0x0 0x0 0x0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              device_type = "pci";
+                               #interrupt-cells = <1>;
+                               interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &liointc1 3 IRQ_TYPE_LEVEL_LOW>;
++                              ranges;
+                               external-facing;
+                       };
+-                      pci_bridge@d,0 {
++                      pcie@d,0 {
+                               compatible = "pci0014,7a19.0",
+                                                  "pci0014,7a19",
+                                                  "pciclass060400",
+                                                  "pciclass0604";
+                               reg = <0x6800 0x0 0x0 0x0 0x0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              device_type = "pci";
+                               #interrupt-cells = <1>;
+                               interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &liointc1 4 IRQ_TYPE_LEVEL_LOW>;
++                              ranges;
+                               external-facing;
+                       };
+-                      pci_bridge@e,0 {
++                      pcie@e,0 {
+                               compatible = "pci0014,7a09.0",
+                                                  "pci0014,7a09",
+                                                  "pciclass060400",
+                                                  "pciclass0604";
+                               reg = <0x7000 0x0 0x0 0x0 0x0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              device_type = "pci";
+                               #interrupt-cells = <1>;
+                               interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &liointc1 5 IRQ_TYPE_LEVEL_LOW>;
++                              ranges;
+                               external-facing;
+                       };
+-- 
+2.43.0
+
diff --git a/queue-6.6/mm-page_alloc-control-latency-caused-by-zone-pcp-dra.patch b/queue-6.6/mm-page_alloc-control-latency-caused-by-zone-pcp-dra.patch
new file mode 100644 (file)
index 0000000..eb72c78
--- /dev/null
@@ -0,0 +1,118 @@
+From a70d3d95f23d43e0e7c08bac8a6ab092feb1eb96 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 Mar 2024 21:07:36 +0100
+Subject: mm: page_alloc: control latency caused by zone PCP draining
+
+From: Lucas Stach <l.stach@pengutronix.de>
+
+[ Upstream commit 55f77df7d715110299f12c27f4365bd6332d1adb ]
+
+Patch series "mm/treewide: Remove pXd_huge() API", v2.
+
+In previous work [1], we removed the pXd_large() API, which is arch
+specific.  This patchset further removes the hugetlb pXd_huge() API.
+
+Hugetlb was never special on creating huge mappings when compared with
+other huge mappings.  Having a standalone API just to detect such pgtable
+entries is more or less redundant, especially after the pXd_leaf() API set
+is introduced with/without CONFIG_HUGETLB_PAGE.
+
+When looking at this problem, a few issues are also exposed that we don't
+have a clear definition of the *_huge() variance API.  This patchset
+started by cleaning these issues first, then replace all *_huge() users to
+use *_leaf(), then drop all *_huge() code.
+
+On x86/sparc, swap entries will be reported "true" in pXd_huge(), while
+for all the rest archs they're reported "false" instead.  This part is
+done in patch 1-5, in which I suspect patch 1 can be seen as a bug fix,
+but I'll leave that to hmm experts to decide.
+
+Besides, there are three archs (arm, arm64, powerpc) that have slightly
+different definitions between the *_huge() v.s.  *_leaf() variances.  I
+tackled them separately so that it'll be easier for arch experts to chim
+in when necessary.  This part is done in patch 6-9.
+
+The final patches 10-14 do the rest on the final removal, since *_leaf()
+will be the ultimate API in the future, and we seem to have quite some
+confusions on how *_huge() APIs can be defined, provide a rich comment for
+*_leaf() API set to define them properly to avoid future misuse, and
+hopefully that'll also help new archs to start support huge mappings and
+avoid traps (like either swap entries, or PROT_NONE entry checks).
+
+[1] https://lore.kernel.org/r/20240305043750.93762-1-peterx@redhat.com
+
+This patch (of 14):
+
+When the complete PCP is drained a much larger number of pages than the
+usual batch size might be freed at once, causing large IRQ and preemption
+latency spikes, as they are all freed while holding the pcp and zone
+spinlocks.
+
+To avoid those latency spikes, limit the number of pages freed in a single
+bulk operation to common batch limits.
+
+Link: https://lkml.kernel.org/r/20240318200404.448346-1-peterx@redhat.com
+Link: https://lkml.kernel.org/r/20240318200736.2835502-1-l.stach@pengutronix.de
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+Signed-off-by: Peter Xu <peterx@redhat.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Jason Gunthorpe <jgg@nvidia.com>
+Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>
+Cc: Mike Rapoport (IBM) <rppt@kernel.org>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Alistair Popple <apopple@nvidia.com>
+Cc: Andreas Larsson <andreas@gaisler.com>
+Cc: "Aneesh Kumar K.V" <aneesh.kumar@kernel.org>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Bjorn Andersson <andersson@kernel.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Cc: David S. Miller <davem@davemloft.net>
+Cc: Fabio Estevam <festevam@denx.de>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Konrad Dybcio <konrad.dybcio@linaro.org>
+Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Cc: Mark Salter <msalter@redhat.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: "Naveen N. Rao" <naveen.n.rao@linux.ibm.com>
+Cc: Nicholas Piggin <npiggin@gmail.com>
+Cc: Russell King <linux@armlinux.org.uk>
+Cc: Shawn Guo <shawnguo@kernel.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Will Deacon <will@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 66eca1021a42 ("mm/page_alloc: fix pcp->count race between drain_pages_zone() vs __rmqueue_pcplist()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/page_alloc.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index d3a2c4d3dc3eb..2c40cf4f1eb2d 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -2185,12 +2185,15 @@ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp)
+  */
+ static void drain_pages_zone(unsigned int cpu, struct zone *zone)
+ {
+-      struct per_cpu_pages *pcp;
++      struct per_cpu_pages *pcp = per_cpu_ptr(zone->per_cpu_pageset, cpu);
++      int count = READ_ONCE(pcp->count);
++
++      while (count) {
++              int to_drain = min(count, pcp->batch << CONFIG_PCP_BATCH_SCALE_MAX);
++              count -= to_drain;
+-      pcp = per_cpu_ptr(zone->per_cpu_pageset, cpu);
+-      if (pcp->count) {
+               spin_lock(&pcp->lock);
+-              free_pcppages_bulk(zone, pcp->count, pcp, 0);
++              free_pcppages_bulk(zone, to_drain, pcp, 0);
+               spin_unlock(&pcp->lock);
+       }
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/mm-page_alloc-fix-pcp-count-race-between-drain_pages.patch b/queue-6.6/mm-page_alloc-fix-pcp-count-race-between-drain_pages.patch
new file mode 100644 (file)
index 0000000..5c54ade
--- /dev/null
@@ -0,0 +1,99 @@
+From 478b0f5dd0b5cb386eb827e98b0e534ec2313ade Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Jul 2024 14:44:28 +0800
+Subject: mm/page_alloc: fix pcp->count race between drain_pages_zone() vs
+ __rmqueue_pcplist()
+
+From: Li Zhijian <lizhijian@fujitsu.com>
+
+[ Upstream commit 66eca1021a42856d6af2a9802c99e160278aed91 ]
+
+It's expected that no page should be left in pcp_list after calling
+zone_pcp_disable() in offline_pages().  Previously, it's observed that
+offline_pages() gets stuck [1] due to some pages remaining in pcp_list.
+
+Cause:
+There is a race condition between drain_pages_zone() and __rmqueue_pcplist()
+involving the pcp->count variable. See below scenario:
+
+         CPU0                              CPU1
+    ----------------                    ---------------
+                                      spin_lock(&pcp->lock);
+                                      __rmqueue_pcplist() {
+zone_pcp_disable() {
+                                        /* list is empty */
+                                        if (list_empty(list)) {
+                                          /* add pages to pcp_list */
+                                          alloced = rmqueue_bulk()
+  mutex_lock(&pcp_batch_high_lock)
+  ...
+  __drain_all_pages() {
+    drain_pages_zone() {
+      /* read pcp->count, it's 0 here */
+      count = READ_ONCE(pcp->count)
+      /* 0 means nothing to drain */
+                                          /* update pcp->count */
+                                          pcp->count += alloced << order;
+      ...
+                                      ...
+                                      spin_unlock(&pcp->lock);
+
+In this case, after calling zone_pcp_disable() though, there are still some
+pages in pcp_list. And these pages in pcp_list are neither movable nor
+isolated, offline_pages() gets stuck as a result.
+
+Solution:
+Expand the scope of the pcp->lock to also protect pcp->count in
+drain_pages_zone(), to ensure no pages are left in the pcp list after
+zone_pcp_disable()
+
+[1] https://lore.kernel.org/linux-mm/6a07125f-e720-404c-b2f9-e55f3f166e85@fujitsu.com/
+
+Link: https://lkml.kernel.org/r/20240723064428.1179519-1-lizhijian@fujitsu.com
+Fixes: 4b23a68f9536 ("mm/page_alloc: protect PCP lists with a spinlock")
+Signed-off-by: Li Zhijian <lizhijian@fujitsu.com>
+Reported-by: Yao Xingtao <yaoxt.fnst@fujitsu.com>
+Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/page_alloc.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 2c40cf4f1eb2d..39bdbfb5313fb 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -2186,16 +2186,20 @@ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp)
+ static void drain_pages_zone(unsigned int cpu, struct zone *zone)
+ {
+       struct per_cpu_pages *pcp = per_cpu_ptr(zone->per_cpu_pageset, cpu);
+-      int count = READ_ONCE(pcp->count);
+-
+-      while (count) {
+-              int to_drain = min(count, pcp->batch << CONFIG_PCP_BATCH_SCALE_MAX);
+-              count -= to_drain;
++      int count;
++      do {
+               spin_lock(&pcp->lock);
+-              free_pcppages_bulk(zone, to_drain, pcp, 0);
++              count = pcp->count;
++              if (count) {
++                      int to_drain = min(count,
++                              pcp->batch << CONFIG_PCP_BATCH_SCALE_MAX);
++
++                      free_pcppages_bulk(zone, to_drain, pcp, 0);
++                      count -= to_drain;
++              }
+               spin_unlock(&pcp->lock);
+-      }
++      } while (count);
+ }
+ /*
+-- 
+2.43.0
+
diff --git a/queue-6.6/mm-restrict-the-pcp-batch-scale-factor-to-avoid-too-.patch b/queue-6.6/mm-restrict-the-pcp-batch-scale-factor-to-avoid-too-.patch
new file mode 100644 (file)
index 0000000..e4cf139
--- /dev/null
@@ -0,0 +1,181 @@
+From 31311eae50a7586a982c83d223f2e87bc0b62dc5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Oct 2023 13:29:57 +0800
+Subject: mm: restrict the pcp batch scale factor to avoid too long latency
+
+From: Huang Ying <ying.huang@intel.com>
+
+[ Upstream commit 52166607ecc980391b1fffbce0be3074a96d0c7b ]
+
+In page allocator, PCP (Per-CPU Pageset) is refilled and drained in
+batches to increase page allocation throughput, reduce page
+allocation/freeing latency per page, and reduce zone lock contention.  But
+too large batch size will cause too long maximal allocation/freeing
+latency, which may punish arbitrary users.  So the default batch size is
+chosen carefully (in zone_batchsize(), the value is 63 for zone > 1GB) to
+avoid that.
+
+In commit 3b12e7e97938 ("mm/page_alloc: scale the number of pages that are
+batch freed"), the batch size will be scaled for large number of page
+freeing to improve page freeing performance and reduce zone lock
+contention.  Similar optimization can be used for large number of pages
+allocation too.
+
+To find out a suitable max batch scale factor (that is, max effective
+batch size), some tests and measurement on some machines were done as
+follows.
+
+A set of debug patches are implemented as follows,
+
+- Set PCP high to be 2 * batch to reduce the effect of PCP high
+
+- Disable free batch size scaling to get the raw performance.
+
+- The code with zone lock held is extracted from rmqueue_bulk() and
+  free_pcppages_bulk() to 2 separate functions to make it easy to
+  measure the function run time with ftrace function_graph tracer.
+
+- The batch size is hard coded to be 63 (default), 127, 255, 511,
+  1023, 2047, 4095.
+
+Then will-it-scale/page_fault1 is used to generate the page
+allocation/freeing workload.  The page allocation/freeing throughput
+(page/s) is measured via will-it-scale.  The page allocation/freeing
+average latency (alloc/free latency avg, in us) and allocation/freeing
+latency at 99 percentile (alloc/free latency 99%, in us) are measured with
+ftrace function_graph tracer.
+
+The test results are as follows,
+
+Sapphire Rapids Server
+======================
+Batch  throughput      free latency    free latency    alloc latency   alloc latency
+       page/s          avg / us        99% / us        avg / us        99% / us
+-----  ----------      ------------    ------------    -------------   -------------
+  63   513633.4         2.33            3.57            2.67             6.83
+ 127   517616.7         4.35            6.65            4.22            13.03
+ 255   520822.8         8.29           13.32            7.52            25.24
+ 511   524122.0        15.79           23.42           14.02            49.35
+1023   525980.5        30.25           44.19           25.36            94.88
+2047   526793.6        59.39           84.50           45.22           140.81
+
+Ice Lake Server
+===============
+Batch  throughput      free latency    free latency    alloc latency   alloc latency
+       page/s          avg / us        99% / us        avg / us        99% / us
+-----  ----------      ------------    ------------    -------------   -------------
+  63   620210.3         2.21            3.68            2.02            4.35
+ 127   627003.0         4.09            6.86            3.51            8.28
+ 255   630777.5         7.70           13.50            6.17           15.97
+ 511   633651.5        14.85           22.62           11.66           31.08
+1023   637071.1        28.55           42.02           20.81           54.36
+2047   638089.7        56.54           84.06           39.28           91.68
+
+Cascade Lake Server
+===================
+Batch  throughput      free latency    free latency    alloc latency   alloc latency
+       page/s          avg / us        99% / us        avg / us        99% / us
+-----  ----------      ------------    ------------    -------------   -------------
+  63   404706.7         3.29             5.03           3.53             4.75
+ 127   422475.2         6.12             9.09           6.36             8.76
+ 255   411522.2        11.68            16.97          10.90            16.39
+ 511   428124.1        22.54            31.28          19.86            32.25
+1023   414718.4        43.39            62.52          40.00            66.33
+2047   429848.7        86.64           120.34          71.14           106.08
+
+Commet Lake Desktop
+===================
+Batch  throughput      free latency    free latency    alloc latency   alloc latency
+       page/s          avg / us        99% / us        avg / us        99% / us
+-----  ----------      ------------    ------------    -------------   -------------
+
+  63   795183.13        2.18            3.55            2.03            3.05
+ 127   803067.85        3.91            6.56            3.85            5.52
+ 255   812771.10        7.35           10.80            7.14           10.20
+ 511   817723.48       14.17           27.54           13.43           30.31
+1023   818870.19       27.72           40.10           27.89           46.28
+
+Coffee Lake Desktop
+===================
+Batch  throughput      free latency    free latency    alloc latency   alloc latency
+       page/s          avg / us        99% / us        avg / us        99% / us
+-----  ----------      ------------    ------------    -------------   -------------
+  63   510542.8         3.13             4.40           2.48            3.43
+ 127   514288.6         5.97             7.89           4.65            6.04
+ 255   516889.7        11.86            15.58           8.96           12.55
+ 511   519802.4        23.10            28.81          16.95           26.19
+1023   520802.7        45.30            52.51          33.19           45.95
+2047   519997.1        90.63           104.00          65.26           81.74
+
+From the above data, to restrict the allocation/freeing latency to be less
+than 100 us in most times, the max batch scale factor needs to be less
+than or equal to 5.
+
+Although it is reasonable to use 5 as max batch scale factor for the
+systems tested, there are also slower systems.  Where smaller value should
+be used to constrain the page allocation/freeing latency.
+
+So, in this patch, a new kconfig option (PCP_BATCH_SCALE_MAX) is added to
+set the max batch scale factor.  Whose default value is 5, and users can
+reduce it when necessary.
+
+Link: https://lkml.kernel.org/r/20231016053002.756205-5-ying.huang@intel.com
+Signed-off-by: "Huang, Ying" <ying.huang@intel.com>
+Acked-by: Andrew Morton <akpm@linux-foundation.org>
+Acked-by: Mel Gorman <mgorman@techsingularity.net>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Johannes Weiner <jweiner@redhat.com>
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: Christoph Lameter <cl@linux.com>
+Cc: Arjan van de Ven <arjan@linux.intel.com>
+Cc: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 66eca1021a42 ("mm/page_alloc: fix pcp->count race between drain_pages_zone() vs __rmqueue_pcplist()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/Kconfig      | 11 +++++++++++
+ mm/page_alloc.c |  2 +-
+ 2 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/mm/Kconfig b/mm/Kconfig
+index 264a2df5ecf5b..ece4f2847e2b4 100644
+--- a/mm/Kconfig
++++ b/mm/Kconfig
+@@ -704,6 +704,17 @@ config HUGETLB_PAGE_SIZE_VARIABLE
+ config CONTIG_ALLOC
+       def_bool (MEMORY_ISOLATION && COMPACTION) || CMA
++config PCP_BATCH_SCALE_MAX
++      int "Maximum scale factor of PCP (Per-CPU pageset) batch allocate/free"
++      default 5
++      range 0 6
++      help
++        In page allocator, PCP (Per-CPU pageset) is refilled and drained in
++        batches.  The batch number is scaled automatically to improve page
++        allocation/free throughput.  But too large scale factor may hurt
++        latency.  This option sets the upper limit of scale factor to limit
++        the maximum latency.
++
+ config PHYS_ADDR_T_64BIT
+       def_bool 64BIT
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index e99d3223f0fc2..d3a2c4d3dc3eb 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -2343,7 +2343,7 @@ static int nr_pcp_free(struct per_cpu_pages *pcp, int high, bool free_high)
+        * freeing of pages without any allocation.
+        */
+       batch <<= pcp->free_factor;
+-      if (batch < max_nr_free)
++      if (batch < max_nr_free && pcp->free_factor < CONFIG_PCP_BATCH_SCALE_MAX)
+               pcp->free_factor++;
+       batch = clamp(batch, min_nr_free, max_nr_free);
+-- 
+2.43.0
+
diff --git a/queue-6.6/pci-add-pci_get_base_class-helper.patch b/queue-6.6/pci-add-pci_get_base_class-helper.patch
new file mode 100644 (file)
index 0000000..b555db5
--- /dev/null
@@ -0,0 +1,102 @@
+From 742984d0f3bc49648a46348c8f875ed615a4bfb9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Aug 2023 14:27:10 +0800
+Subject: PCI: Add pci_get_base_class() helper
+
+From: Sui Jingfeng <suijingfeng@loongson.cn>
+
+[ Upstream commit d427da2323b093a65d8317783e76ab8fad2e2ef0 ]
+
+There is no function to get all PCI devices in a system by matching
+against the base class code only, ignoring the sub-class code and
+the programming interface.  Add pci_get_base_class() to suit the
+need.
+
+For example, if a driver wants to process all PCI display devices in
+a system, it can do so like this:
+
+  pdev = NULL;
+  while ((pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) {
+    do_something_for_pci_display_device(pdev);
+  }
+
+Link: https://lore.kernel.org/r/20230825062714.6325-2-sui.jingfeng@linux.dev
+Signed-off-by: Sui Jingfeng <suijingfeng@loongson.cn>
+[bhelgaas: reword commit log]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: c2bc958b2b03 ("fbdev: vesafb: Detect VGA compatibility from screen info's VESA attributes")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/search.c | 31 +++++++++++++++++++++++++++++++
+ include/linux/pci.h  |  5 +++++
+ 2 files changed, 36 insertions(+)
+
+diff --git a/drivers/pci/search.c b/drivers/pci/search.c
+index b4c138a6ec025..53840634fbfc2 100644
+--- a/drivers/pci/search.c
++++ b/drivers/pci/search.c
+@@ -363,6 +363,37 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)
+ }
+ EXPORT_SYMBOL(pci_get_class);
++/**
++ * pci_get_base_class - searching for a PCI device by matching against the base class code only
++ * @class: search for a PCI device with this base class code
++ * @from: Previous PCI device found in search, or %NULL for new search.
++ *
++ * Iterates through the list of known PCI devices. If a PCI device is found
++ * with a matching base class code, the reference count to the device is
++ * incremented. See pci_match_one_device() to figure out how does this works.
++ * A new search is initiated by passing %NULL as the @from argument.
++ * Otherwise if @from is not %NULL, searches continue from next device on the
++ * global list. The reference count for @from is always decremented if it is
++ * not %NULL.
++ *
++ * Returns:
++ * A pointer to a matched PCI device, %NULL Otherwise.
++ */
++struct pci_dev *pci_get_base_class(unsigned int class, struct pci_dev *from)
++{
++      struct pci_device_id id = {
++              .vendor = PCI_ANY_ID,
++              .device = PCI_ANY_ID,
++              .subvendor = PCI_ANY_ID,
++              .subdevice = PCI_ANY_ID,
++              .class_mask = 0xFF0000,
++              .class = class << 16,
++      };
++
++      return pci_get_dev_by_id(&id, from);
++}
++EXPORT_SYMBOL(pci_get_base_class);
++
+ /**
+  * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not.
+  * @ids: A pointer to a null terminated list of struct pci_device_id structures
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index f141300116219..7b18a4b3efb0e 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -1182,6 +1182,8 @@ struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn);
+ struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
+                                           unsigned int devfn);
+ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from);
++struct pci_dev *pci_get_base_class(unsigned int class, struct pci_dev *from);
++
+ int pci_dev_present(const struct pci_device_id *ids);
+ int pci_bus_read_config_byte(struct pci_bus *bus, unsigned int devfn,
+@@ -1958,6 +1960,9 @@ static inline struct pci_dev *pci_get_class(unsigned int class,
+                                           struct pci_dev *from)
+ { return NULL; }
++static inline struct pci_dev *pci_get_base_class(unsigned int class,
++                                               struct pci_dev *from)
++{ return NULL; }
+ static inline int pci_dev_present(const struct pci_device_id *ids)
+ { return 0; }
+-- 
+2.43.0
+
diff --git a/queue-6.6/perf-imx_perf-fix-counter-start-and-config-sequence.patch b/queue-6.6/perf-imx_perf-fix-counter-start-and-config-sequence.patch
new file mode 100644 (file)
index 0000000..eabdb66
--- /dev/null
@@ -0,0 +1,47 @@
+From a0bf93f28f3a01e537cf93d8ea70115c84ab3467 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 May 2024 16:03:55 +0800
+Subject: perf: imx_perf: fix counter start and config sequence
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+[ Upstream commit ac9aa295f7a89d38656739628796f086f0b160e2 ]
+
+In current driver, the counter will start firstly and then be configured.
+This sequence is not correct for AXI filter events since the correct
+AXI_MASK and AXI_ID are not set yet. Then the results may be inaccurate.
+
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Fixes: 55691f99d417 ("drivers/perf: imx_ddr: Add support for NXP i.MX9 SoC DDRC PMU driver")
+cc: stable@vger.kernel.org
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Link: https://lore.kernel.org/r/20240529080358.703784-5-xu.yang_2@nxp.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/perf/fsl_imx9_ddr_perf.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/perf/fsl_imx9_ddr_perf.c b/drivers/perf/fsl_imx9_ddr_perf.c
+index 5cf770a1bc312..4f6eade522024 100644
+--- a/drivers/perf/fsl_imx9_ddr_perf.c
++++ b/drivers/perf/fsl_imx9_ddr_perf.c
+@@ -476,12 +476,12 @@ static int ddr_perf_event_add(struct perf_event *event, int flags)
+       hwc->idx = counter;
+       hwc->state |= PERF_HES_STOPPED;
+-      if (flags & PERF_EF_START)
+-              ddr_perf_event_start(event, flags);
+-
+       /* read trans, write trans, read beat */
+       ddr_perf_monitor_config(pmu, cfg, cfg1, cfg2);
++      if (flags & PERF_EF_START)
++              ddr_perf_event_start(event, flags);
++
+       return 0;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/series b/queue-6.6/series
new file mode 100644 (file)
index 0000000..e8fc4a6
--- /dev/null
@@ -0,0 +1,49 @@
+arm64-dts-qcom-sc7180-switch-usb-dp-qmp-phy-to-new-s.patch
+arm64-dts-qcom-sc7180-disable-superspeed-instances-i.patch
+arm64-dts-qcom-sc7280-switch-usb-dp-qmp-phy-to-new-s.patch
+arm64-dts-qcom-sc7280-disable-superspeed-instances-i.patch
+arm64-dts-qcom-msm8998-switch-usb-qmp-phy-to-new-sty.patch
+arm64-dts-qcom-msm8998-disable-ss-instance-in-parkmo.patch
+arm64-dts-qcom-ipq8074-disable-ss-instance-in-parkmo.patch
+arm64-dts-qcom-sdm845-switch-usb-dp-qmp-phy-to-new-s.patch
+arm64-dts-qcom-sdm845-switch-usb-qmp-phy-to-new-styl.patch
+arm64-dts-qcom-sdm845-disable-ss-instance-in-parkmod.patch
+thermal-bcm2835-convert-to-platform-remove-callback-.patch
+thermal-drivers-broadcom-fix-race-between-removal-an.patch
+sysctl-allow-change-system-v-ipc-sysctls-inside-ipc-.patch
+sysctl-allow-to-change-limits-for-posix-messages-que.patch
+sysctl-treewide-drop-unused-argument-ctl_table_root-.patch
+sysctl-always-initialize-i_uid-i_gid.patch
+ext4-refactor-ext4_da_map_blocks.patch
+ext4-convert-to-exclusive-lock-while-inserting-delal.patch
+ext4-factor-out-a-common-helper-to-query-extent-map.patch
+ext4-check-the-extent-status-again-before-inserting-.patch
+cpufreq-qcom-nvmem-simplify-driver-data-allocation.patch
+cpufreq-qcom-nvmem-fix-memory-leaks-in-probe-error-p.patch
+leds-trigger-remove-unused-function-led_trigger_rena.patch
+leds-trigger-store-brightness-set-by-led_trigger_eve.patch
+leds-trigger-call-synchronize_rcu-before-calling-tri.patch
+leds-triggers-flush-pending-brightness-before-activa.patch
+kvm-vmx-split-off-vmx_onhyperv.-ch-from-hyperv.-ch.patch
+kvm-vmx-move-posted-interrupt-descriptor-out-of-vmx-.patch
+kvm-nvmx-add-a-helper-to-get-highest-pending-from-po.patch
+kvm-nvmx-check-for-pending-posted-interrupts-when-lo.patch
+pci-add-pci_get_base_class-helper.patch
+fbdev-vesafb-replace-references-to-global-screen_inf.patch
+video-add-helpers-for-decoding-screen_info.patch
+video-provide-screen_info_get_pci_dev-to-find-screen.patch
+firmware-sysfb-update-screen_info-for-relocated-efi-.patch
+fbdev-vesafb-detect-vga-compatibility-from-screen-in.patch
+mm-restrict-the-pcp-batch-scale-factor-to-avoid-too-.patch
+mm-page_alloc-control-latency-caused-by-zone-pcp-dra.patch
+mm-page_alloc-fix-pcp-count-race-between-drain_pages.patch
+f2fs-fix-to-avoid-use-ssr-allocate-when-do-defragmen.patch
+f2fs-assign-curseg_all_data_atgc-if-blkaddr-is-valid.patch
+dmaengine-fsl-edma-add-address-for-channel-mux-regis.patch
+dmaengine-fsl-edma-add-i.mx8ulp-edma-support.patch
+dmaengine-fsl-edma-clean-up-unused-fsl-imx8qm-adma-c.patch
+dmaengine-fsl-edma-change-the-memory-access-from-loc.patch
+perf-imx_perf-fix-counter-start-and-config-sequence.patch
+mips-loongson64-dts-fix-pcie-port-nodes-for-ls7a.patch
+mips-dts-loongson-fix-liointc-irq-polarity.patch
+mips-dts-loongson-fix-ls2k1000-rtc-interrupt.patch
diff --git a/queue-6.6/sysctl-allow-change-system-v-ipc-sysctls-inside-ipc-.patch b/queue-6.6/sysctl-allow-change-system-v-ipc-sysctls-inside-ipc-.patch
new file mode 100644 (file)
index 0000000..e428f09
--- /dev/null
@@ -0,0 +1,140 @@
+From 7d69f81c1db52f19266b1c1845ca2f6e1a294ff0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jan 2024 15:46:41 +0000
+Subject: sysctl: allow change system v ipc sysctls inside ipc namespace
+
+From: Alexey Gladkov <legion@kernel.org>
+
+[ Upstream commit 50ec499b9a43e46200c9f7b7d723ab2e4af540b3 ]
+
+Patch series "Allow to change ipc/mq sysctls inside ipc namespace", v3.
+
+Right now ipc and mq limits count as per ipc namespace, but only real root
+can change them.  By default, the current values of these limits are such
+that it can only be reduced.  Since only root can change the values, it is
+impossible to reduce these limits in the rootless container.
+
+We can allow limit changes within ipc namespace because mq parameters are
+limited by RLIMIT_MSGQUEUE and ipc parameters are not limited to anything
+other than cgroups.
+
+This patch (of 3):
+
+Rootless containers are not allowed to modify kernel IPC parameters.
+
+All default limits are set to such high values that in fact there are no
+limits at all.  All limits are not inherited and are initialized to
+default values when a new ipc_namespace is created.
+
+For new ipc_namespace:
+
+size_t       ipc_ns.shm_ctlmax = SHMMAX; // (ULONG_MAX - (1UL << 24))
+size_t       ipc_ns.shm_ctlall = SHMALL; // (ULONG_MAX - (1UL << 24))
+int          ipc_ns.shm_ctlmni = IPCMNI; // (1 << 15)
+int          ipc_ns.shm_rmid_forced = 0;
+unsigned int ipc_ns.msg_ctlmax = MSGMAX; // 8192
+unsigned int ipc_ns.msg_ctlmni = MSGMNI; // 32000
+unsigned int ipc_ns.msg_ctlmnb = MSGMNB; // 16384
+
+The shm_tot (total amount of shared pages) has also ceased to be global,
+it is located in ipc_namespace and is not inherited from anywhere.
+
+In such conditions, it cannot be said that these limits limit anything.
+The real limiter for them is cgroups.
+
+If we allow rootless containers to change these parameters, then it can
+only be reduced.
+
+Link: https://lkml.kernel.org/r/cover.1705333426.git.legion@kernel.org
+Link: https://lkml.kernel.org/r/d2f4603305cbfed58a24755aa61d027314b73a45.1705333426.git.legion@kernel.org
+Signed-off-by: Alexey Gladkov <legion@kernel.org>
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Link: https://lkml.kernel.org/r/e2d84d3ec0172cfff759e6065da84ce0cc2736f8.1663756794.git.legion@kernel.org
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: Joel Granados <joel.granados@gmail.com>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Luis Chamberlain <mcgrof@kernel.org>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Cc: Davidlohr Bueso <dave@stgolabs.net>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 98ca62ba9e2b ("sysctl: always initialize i_uid/i_gid")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ ipc/ipc_sysctl.c | 37 +++++++++++++++++++++++++++++++++++--
+ 1 file changed, 35 insertions(+), 2 deletions(-)
+
+diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
+index 8c62e443f78b3..01c4a50d22b2d 100644
+--- a/ipc/ipc_sysctl.c
++++ b/ipc/ipc_sysctl.c
+@@ -14,6 +14,7 @@
+ #include <linux/ipc_namespace.h>
+ #include <linux/msg.h>
+ #include <linux/slab.h>
++#include <linux/cred.h>
+ #include "util.h"
+ static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
+@@ -190,25 +191,57 @@ static int set_is_seen(struct ctl_table_set *set)
+       return &current->nsproxy->ipc_ns->ipc_set == set;
+ }
++static void ipc_set_ownership(struct ctl_table_header *head,
++                            struct ctl_table *table,
++                            kuid_t *uid, kgid_t *gid)
++{
++      struct ipc_namespace *ns =
++              container_of(head->set, struct ipc_namespace, ipc_set);
++
++      kuid_t ns_root_uid = make_kuid(ns->user_ns, 0);
++      kgid_t ns_root_gid = make_kgid(ns->user_ns, 0);
++
++      *uid = uid_valid(ns_root_uid) ? ns_root_uid : GLOBAL_ROOT_UID;
++      *gid = gid_valid(ns_root_gid) ? ns_root_gid : GLOBAL_ROOT_GID;
++}
++
+ static int ipc_permissions(struct ctl_table_header *head, struct ctl_table *table)
+ {
+       int mode = table->mode;
+ #ifdef CONFIG_CHECKPOINT_RESTORE
+-      struct ipc_namespace *ns = current->nsproxy->ipc_ns;
++      struct ipc_namespace *ns =
++              container_of(head->set, struct ipc_namespace, ipc_set);
+       if (((table->data == &ns->ids[IPC_SEM_IDS].next_id) ||
+            (table->data == &ns->ids[IPC_MSG_IDS].next_id) ||
+            (table->data == &ns->ids[IPC_SHM_IDS].next_id)) &&
+           checkpoint_restore_ns_capable(ns->user_ns))
+               mode = 0666;
++      else
+ #endif
+-      return mode;
++      {
++              kuid_t ns_root_uid;
++              kgid_t ns_root_gid;
++
++              ipc_set_ownership(head, table, &ns_root_uid, &ns_root_gid);
++
++              if (uid_eq(current_euid(), ns_root_uid))
++                      mode >>= 6;
++
++              else if (in_egroup_p(ns_root_gid))
++                      mode >>= 3;
++      }
++
++      mode &= 7;
++
++      return (mode << 6) | (mode << 3) | mode;
+ }
+ static struct ctl_table_root set_root = {
+       .lookup = set_lookup,
+       .permissions = ipc_permissions,
++      .set_ownership = ipc_set_ownership,
+ };
+ bool setup_ipc_sysctls(struct ipc_namespace *ns)
+-- 
+2.43.0
+
diff --git a/queue-6.6/sysctl-allow-to-change-limits-for-posix-messages-que.patch b/queue-6.6/sysctl-allow-to-change-limits-for-posix-messages-que.patch
new file mode 100644 (file)
index 0000000..e603740
--- /dev/null
@@ -0,0 +1,95 @@
+From 5a552c8d6bcc1f57f7c0272f60c5c5ac60ebaa6e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jan 2024 15:46:43 +0000
+Subject: sysctl: allow to change limits for posix messages queues
+
+From: Alexey Gladkov <legion@kernel.org>
+
+[ Upstream commit f9436a5d0497f759330d07e1189565edd4456be8 ]
+
+All parameters of posix messages queues (queues_max/msg_max/msgsize_max)
+end up being limited by RLIMIT_MSGQUEUE.  The code in mqueue_get_inode is
+where that limiting happens.
+
+The RLIMIT_MSGQUEUE is bound to the user namespace and is counted
+hierarchically.
+
+We can allow root in the user namespace to modify the posix messages
+queues parameters.
+
+Link: https://lkml.kernel.org/r/6ad67f23d1459a4f4339f74aa73bac0ecf3995e1.1705333426.git.legion@kernel.org
+Signed-off-by: Alexey Gladkov <legion@kernel.org>
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Link: https://lkml.kernel.org/r/7eb21211c8622e91d226e63416b1b93c079f60ee.1663756794.git.legion@kernel.org
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: Davidlohr Bueso <dave@stgolabs.net>
+Cc: Joel Granados <joel.granados@gmail.com>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Luis Chamberlain <mcgrof@kernel.org>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 98ca62ba9e2b ("sysctl: always initialize i_uid/i_gid")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ ipc/mq_sysctl.c | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c
+index ebb5ed81c151a..21fba3a6edaf7 100644
+--- a/ipc/mq_sysctl.c
++++ b/ipc/mq_sysctl.c
+@@ -12,6 +12,7 @@
+ #include <linux/stat.h>
+ #include <linux/capability.h>
+ #include <linux/slab.h>
++#include <linux/cred.h>
+ static int msg_max_limit_min = MIN_MSGMAX;
+ static int msg_max_limit_max = HARD_MSGMAX;
+@@ -76,8 +77,43 @@ static int set_is_seen(struct ctl_table_set *set)
+       return &current->nsproxy->ipc_ns->mq_set == set;
+ }
++static void mq_set_ownership(struct ctl_table_header *head,
++                           struct ctl_table *table,
++                           kuid_t *uid, kgid_t *gid)
++{
++      struct ipc_namespace *ns =
++              container_of(head->set, struct ipc_namespace, mq_set);
++
++      kuid_t ns_root_uid = make_kuid(ns->user_ns, 0);
++      kgid_t ns_root_gid = make_kgid(ns->user_ns, 0);
++
++      *uid = uid_valid(ns_root_uid) ? ns_root_uid : GLOBAL_ROOT_UID;
++      *gid = gid_valid(ns_root_gid) ? ns_root_gid : GLOBAL_ROOT_GID;
++}
++
++static int mq_permissions(struct ctl_table_header *head, struct ctl_table *table)
++{
++      int mode = table->mode;
++      kuid_t ns_root_uid;
++      kgid_t ns_root_gid;
++
++      mq_set_ownership(head, table, &ns_root_uid, &ns_root_gid);
++
++      if (uid_eq(current_euid(), ns_root_uid))
++              mode >>= 6;
++
++      else if (in_egroup_p(ns_root_gid))
++              mode >>= 3;
++
++      mode &= 7;
++
++      return (mode << 6) | (mode << 3) | mode;
++}
++
+ static struct ctl_table_root set_root = {
+       .lookup = set_lookup,
++      .permissions = mq_permissions,
++      .set_ownership = mq_set_ownership,
+ };
+ bool setup_mq_sysctls(struct ipc_namespace *ns)
+-- 
+2.43.0
+
diff --git a/queue-6.6/sysctl-always-initialize-i_uid-i_gid.patch b/queue-6.6/sysctl-always-initialize-i_uid-i_gid.patch
new file mode 100644 (file)
index 0000000..9cea275
--- /dev/null
@@ -0,0 +1,52 @@
+From 978372c2ff5843a25e3a5914eab63e1d5e6d4b3c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Apr 2024 23:10:34 +0200
+Subject: sysctl: always initialize i_uid/i_gid
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit 98ca62ba9e2be5863c7d069f84f7166b45a5b2f4 ]
+
+Always initialize i_uid/i_gid inside the sysfs core so set_ownership()
+can safely skip setting them.
+
+Commit 5ec27ec735ba ("fs/proc/proc_sysctl.c: fix the default values of
+i_uid/i_gid on /proc/sys inodes.") added defaults for i_uid/i_gid when
+set_ownership() was not implemented. It also missed adjusting
+net_ctl_set_ownership() to use the same default values in case the
+computation of a better value failed.
+
+Fixes: 5ec27ec735ba ("fs/proc/proc_sysctl.c: fix the default values of i_uid/i_gid on /proc/sys inodes.")
+Cc: stable@vger.kernel.org
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Joel Granados <j.granados@samsung.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/proc/proc_sysctl.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
+index cec67e6a6678f..071a71eb1a2d4 100644
+--- a/fs/proc/proc_sysctl.c
++++ b/fs/proc/proc_sysctl.c
+@@ -480,12 +480,10 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
+                       make_empty_dir_inode(inode);
+       }
++      inode->i_uid = GLOBAL_ROOT_UID;
++      inode->i_gid = GLOBAL_ROOT_GID;
+       if (root->set_ownership)
+               root->set_ownership(head, &inode->i_uid, &inode->i_gid);
+-      else {
+-              inode->i_uid = GLOBAL_ROOT_UID;
+-              inode->i_gid = GLOBAL_ROOT_GID;
+-      }
+       return inode;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/sysctl-treewide-drop-unused-argument-ctl_table_root-.patch b/queue-6.6/sysctl-treewide-drop-unused-argument-ctl_table_root-.patch
new file mode 100644 (file)
index 0000000..ec37dc9
--- /dev/null
@@ -0,0 +1,127 @@
+From fc7a41ff3afb2dcbee7911847a17c634e46a127e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Mar 2024 19:11:30 +0100
+Subject: sysctl: treewide: drop unused argument
+ ctl_table_root::set_ownership(table)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit 520713a93d550406dae14d49cdb8778d70cecdfd ]
+
+Remove the 'table' argument from set_ownership as it is never used. This
+change is a step towards putting "struct ctl_table" into .rodata and
+eventually having sysctl core only use "const struct ctl_table".
+
+The patch was created with the following coccinelle script:
+
+  @@
+  identifier func, head, table, uid, gid;
+  @@
+
+  void func(
+    struct ctl_table_header *head,
+  - struct ctl_table *table,
+    kuid_t *uid, kgid_t *gid)
+  { ... }
+
+No additional occurrences of 'set_ownership' were found after doing a
+tree-wide search.
+
+Reviewed-by: Joel Granados <j.granados@samsung.com>
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Joel Granados <j.granados@samsung.com>
+Stable-dep-of: 98ca62ba9e2b ("sysctl: always initialize i_uid/i_gid")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/proc/proc_sysctl.c  | 2 +-
+ include/linux/sysctl.h | 1 -
+ ipc/ipc_sysctl.c       | 3 +--
+ ipc/mq_sysctl.c        | 3 +--
+ net/sysctl_net.c       | 1 -
+ 5 files changed, 3 insertions(+), 7 deletions(-)
+
+diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
+index 5b5cdc747cef3..cec67e6a6678f 100644
+--- a/fs/proc/proc_sysctl.c
++++ b/fs/proc/proc_sysctl.c
+@@ -481,7 +481,7 @@ static struct inode *proc_sys_make_inode(struct super_block *sb,
+       }
+       if (root->set_ownership)
+-              root->set_ownership(head, table, &inode->i_uid, &inode->i_gid);
++              root->set_ownership(head, &inode->i_uid, &inode->i_gid);
+       else {
+               inode->i_uid = GLOBAL_ROOT_UID;
+               inode->i_gid = GLOBAL_ROOT_GID;
+diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
+index 61b40ea81f4d3..698a71422a14b 100644
+--- a/include/linux/sysctl.h
++++ b/include/linux/sysctl.h
+@@ -205,7 +205,6 @@ struct ctl_table_root {
+       struct ctl_table_set default_set;
+       struct ctl_table_set *(*lookup)(struct ctl_table_root *root);
+       void (*set_ownership)(struct ctl_table_header *head,
+-                            struct ctl_table *table,
+                             kuid_t *uid, kgid_t *gid);
+       int (*permissions)(struct ctl_table_header *head, struct ctl_table *table);
+ };
+diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
+index 01c4a50d22b2d..b2f39a86f4734 100644
+--- a/ipc/ipc_sysctl.c
++++ b/ipc/ipc_sysctl.c
+@@ -192,7 +192,6 @@ static int set_is_seen(struct ctl_table_set *set)
+ }
+ static void ipc_set_ownership(struct ctl_table_header *head,
+-                            struct ctl_table *table,
+                             kuid_t *uid, kgid_t *gid)
+ {
+       struct ipc_namespace *ns =
+@@ -224,7 +223,7 @@ static int ipc_permissions(struct ctl_table_header *head, struct ctl_table *tabl
+               kuid_t ns_root_uid;
+               kgid_t ns_root_gid;
+-              ipc_set_ownership(head, table, &ns_root_uid, &ns_root_gid);
++              ipc_set_ownership(head, &ns_root_uid, &ns_root_gid);
+               if (uid_eq(current_euid(), ns_root_uid))
+                       mode >>= 6;
+diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c
+index 21fba3a6edaf7..6bb1c5397c69b 100644
+--- a/ipc/mq_sysctl.c
++++ b/ipc/mq_sysctl.c
+@@ -78,7 +78,6 @@ static int set_is_seen(struct ctl_table_set *set)
+ }
+ static void mq_set_ownership(struct ctl_table_header *head,
+-                           struct ctl_table *table,
+                            kuid_t *uid, kgid_t *gid)
+ {
+       struct ipc_namespace *ns =
+@@ -97,7 +96,7 @@ static int mq_permissions(struct ctl_table_header *head, struct ctl_table *table
+       kuid_t ns_root_uid;
+       kgid_t ns_root_gid;
+-      mq_set_ownership(head, table, &ns_root_uid, &ns_root_gid);
++      mq_set_ownership(head, &ns_root_uid, &ns_root_gid);
+       if (uid_eq(current_euid(), ns_root_uid))
+               mode >>= 6;
+diff --git a/net/sysctl_net.c b/net/sysctl_net.c
+index 051ed5f6fc937..a0a7a79991f9f 100644
+--- a/net/sysctl_net.c
++++ b/net/sysctl_net.c
+@@ -54,7 +54,6 @@ static int net_ctl_permissions(struct ctl_table_header *head,
+ }
+ static void net_ctl_set_ownership(struct ctl_table_header *head,
+-                                struct ctl_table *table,
+                                 kuid_t *uid, kgid_t *gid)
+ {
+       struct net *net = container_of(head->set, struct net, sysctls);
+-- 
+2.43.0
+
diff --git a/queue-6.6/thermal-bcm2835-convert-to-platform-remove-callback-.patch b/queue-6.6/thermal-bcm2835-convert-to-platform-remove-callback-.patch
new file mode 100644 (file)
index 0000000..e1c6aa4
--- /dev/null
@@ -0,0 +1,63 @@
+From a3fbf18844ae89cf621420aa04ba9095fc5cefdf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 Sep 2023 21:37:08 +0200
+Subject: thermal: bcm2835: Convert to platform remove callback returning void
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit f29ecd3748a28d0b52512afc81b3c13fd4a00c9b ]
+
+The .remove() callback for a platform driver returns an int which makes
+many driver authors wrongly assume it's possible to do error handling by
+returning an error code. However the value returned is ignored (apart
+from emitting a warning) and this typically results in resource leaks.
+
+To improve here there is a quest to make the remove callback return
+void. In the first step of this quest all drivers are converted to
+.remove_new(), which already returns void. Eventually after all drivers
+are converted, .remove_new() will be renamed to .remove().
+
+Trivially convert this driver from always returning zero in the remove
+callback to the void returning variant.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Stable-dep-of: e90c369cc2ff ("thermal/drivers/broadcom: Fix race between removal and clock disable")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/thermal/broadcom/bcm2835_thermal.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c
+index 3acc9288b3105..5c1cebe075801 100644
+--- a/drivers/thermal/broadcom/bcm2835_thermal.c
++++ b/drivers/thermal/broadcom/bcm2835_thermal.c
+@@ -282,19 +282,17 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
+       return err;
+ }
+-static int bcm2835_thermal_remove(struct platform_device *pdev)
++static void bcm2835_thermal_remove(struct platform_device *pdev)
+ {
+       struct bcm2835_thermal_data *data = platform_get_drvdata(pdev);
+       debugfs_remove_recursive(data->debugfsdir);
+       clk_disable_unprepare(data->clk);
+-
+-      return 0;
+ }
+ static struct platform_driver bcm2835_thermal_driver = {
+       .probe = bcm2835_thermal_probe,
+-      .remove = bcm2835_thermal_remove,
++      .remove_new = bcm2835_thermal_remove,
+       .driver = {
+               .name = "bcm2835_thermal",
+               .of_match_table = bcm2835_thermal_of_match_table,
+-- 
+2.43.0
+
diff --git a/queue-6.6/thermal-drivers-broadcom-fix-race-between-removal-an.patch b/queue-6.6/thermal-drivers-broadcom-fix-race-between-removal-an.patch
new file mode 100644 (file)
index 0000000..4c15c9b
--- /dev/null
@@ -0,0 +1,105 @@
+From 2baa80182561a0e62050aa262b1e09abb84af0d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Jul 2024 14:59:31 +0200
+Subject: thermal/drivers/broadcom: Fix race between removal and clock disable
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit e90c369cc2ffcf7145a46448de101f715a1f5584 ]
+
+During the probe, driver enables clocks necessary to access registers
+(in get_temp()) and then registers thermal zone with managed-resources
+(devm) interface.  Removal of device is not done in reversed order,
+because:
+1. Clock will be disabled in driver remove() callback - thermal zone is
+   still registered and accessible to users,
+2. devm interface will unregister thermal zone.
+
+This leaves short window between (1) and (2) for accessing the
+get_temp() callback with disabled clock.
+
+Fix this by enabling clock also via devm-interface, so entire cleanup
+path will be in proper, reversed order.
+
+Fixes: 8454c8c09c77 ("thermal/drivers/bcm2835: Remove buggy call to thermal_of_zone_unregister")
+Cc: stable@vger.kernel.org
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20240709-thermal-probe-v1-1-241644e2b6e0@linaro.org
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/thermal/broadcom/bcm2835_thermal.c | 19 ++++---------------
+ 1 file changed, 4 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c
+index 5c1cebe075801..3b1030fc4fbfe 100644
+--- a/drivers/thermal/broadcom/bcm2835_thermal.c
++++ b/drivers/thermal/broadcom/bcm2835_thermal.c
+@@ -185,7 +185,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
+               return err;
+       }
+-      data->clk = devm_clk_get(&pdev->dev, NULL);
++      data->clk = devm_clk_get_enabled(&pdev->dev, NULL);
+       if (IS_ERR(data->clk)) {
+               err = PTR_ERR(data->clk);
+               if (err != -EPROBE_DEFER)
+@@ -193,10 +193,6 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
+               return err;
+       }
+-      err = clk_prepare_enable(data->clk);
+-      if (err)
+-              return err;
+-
+       rate = clk_get_rate(data->clk);
+       if ((rate < 1920000) || (rate > 5000000))
+               dev_warn(&pdev->dev,
+@@ -211,7 +207,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
+               dev_err(&pdev->dev,
+                       "Failed to register the thermal device: %d\n",
+                       err);
+-              goto err_clk;
++              return err;
+       }
+       /*
+@@ -236,7 +232,7 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
+                       dev_err(&pdev->dev,
+                               "Not able to read trip_temp: %d\n",
+                               err);
+-                      goto err_tz;
++                      return err;
+               }
+               /* set bandgap reference voltage and enable voltage regulator */
+@@ -269,17 +265,11 @@ static int bcm2835_thermal_probe(struct platform_device *pdev)
+        */
+       err = thermal_add_hwmon_sysfs(tz);
+       if (err)
+-              goto err_tz;
++              return err;
+       bcm2835_thermal_debugfs(pdev);
+       return 0;
+-err_tz:
+-      devm_thermal_of_zone_unregister(&pdev->dev, tz);
+-err_clk:
+-      clk_disable_unprepare(data->clk);
+-
+-      return err;
+ }
+ static void bcm2835_thermal_remove(struct platform_device *pdev)
+@@ -287,7 +277,6 @@ static void bcm2835_thermal_remove(struct platform_device *pdev)
+       struct bcm2835_thermal_data *data = platform_get_drvdata(pdev);
+       debugfs_remove_recursive(data->debugfsdir);
+-      clk_disable_unprepare(data->clk);
+ }
+ static struct platform_driver bcm2835_thermal_driver = {
+-- 
+2.43.0
+
diff --git a/queue-6.6/video-add-helpers-for-decoding-screen_info.patch b/queue-6.6/video-add-helpers-for-decoding-screen_info.patch
new file mode 100644 (file)
index 0000000..a208a99
--- /dev/null
@@ -0,0 +1,355 @@
+From 0b160bbb835bd6bfa264b86bc2bfcbb56e88a6e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Feb 2024 10:06:09 +0100
+Subject: video: Add helpers for decoding screen_info
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 75fa9b7e375e35739663cde0252d31e586c6314a ]
+
+The plain values as stored in struct screen_info need to be decoded
+before being used. Add helpers that decode the type of video output
+and the framebuffer I/O aperture.
+
+Old or non-x86 systems may not set the type of video directly, but
+only indicate the presence by storing 0x01 in orig_video_isVGA. The
+decoding logic in screen_info_video_type() takes this into account.
+It then follows similar code in vgacon's vgacon_startup() to detect
+the video type from the given values.
+
+A call to screen_info_resources() returns all known resources of the
+given screen_info. The resources' values have been taken from existing
+code in vgacon and vga16fb. These drivers can later be converted to
+use the new interfaces.
+
+v2:
+       * return ssize_t from screen_info_resources()
+       * don't call __screen_info_has_lfb() unnecessarily
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240212090736.11464-2-tzimmermann@suse.de
+Stable-dep-of: c2bc958b2b03 ("fbdev: vesafb: Detect VGA compatibility from screen info's VESA attributes")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/Kconfig            |   1 +
+ drivers/video/Kconfig               |   4 +
+ drivers/video/Makefile              |   3 +
+ drivers/video/screen_info_generic.c | 146 ++++++++++++++++++++++++++++
+ include/linux/screen_info.h         | 100 +++++++++++++++++++
+ 5 files changed, 254 insertions(+)
+ create mode 100644 drivers/video/screen_info_generic.c
+
+diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
+index b59e3041fd627..f0e9f250669e2 100644
+--- a/drivers/firmware/Kconfig
++++ b/drivers/firmware/Kconfig
+@@ -229,6 +229,7 @@ config QCOM_SCM_DOWNLOAD_MODE_DEFAULT
+ config SYSFB
+       bool
+       select BOOT_VESA_SUPPORT
++      select SCREEN_INFO
+ config SYSFB_SIMPLEFB
+       bool "Mark VGA/VBE/EFI FB as generic system framebuffer"
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index b694d7669d320..1eb755a94940a 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -11,6 +11,10 @@ config APERTURE_HELPERS
+         Support tracking and hand-over of aperture ownership. Required
+         by graphics drivers for firmware-provided framebuffers.
++config SCREEN_INFO
++      bool
++      default n
++
+ config STI_CORE
+       bool
+       depends on PARISC
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 6bbc039508995..b929b664d52cd 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -1,12 +1,15 @@
+ # SPDX-License-Identifier: GPL-2.0
+ obj-$(CONFIG_APERTURE_HELPERS)    += aperture.o
++obj-$(CONFIG_SCREEN_INFO)         += screen_info.o
+ obj-$(CONFIG_STI_CORE)            += sticore.o
+ obj-$(CONFIG_VGASTATE)            += vgastate.o
+ obj-$(CONFIG_VIDEO_CMDLINE)       += cmdline.o
+ obj-$(CONFIG_VIDEO_NOMODESET)     += nomodeset.o
+ obj-$(CONFIG_HDMI)                += hdmi.o
++screen_info-y                   := screen_info_generic.o
++
+ obj-$(CONFIG_VT)                += console/
+ obj-$(CONFIG_FB_STI)            += console/
+ obj-$(CONFIG_LOGO)              += logo/
+diff --git a/drivers/video/screen_info_generic.c b/drivers/video/screen_info_generic.c
+new file mode 100644
+index 0000000000000..64117c6367abb
+--- /dev/null
++++ b/drivers/video/screen_info_generic.c
+@@ -0,0 +1,146 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include <linux/export.h>
++#include <linux/ioport.h>
++#include <linux/screen_info.h>
++#include <linux/string.h>
++
++static void resource_init_named(struct resource *r,
++                              resource_size_t start, resource_size_t size,
++                              const char *name, unsigned int flags)
++{
++      memset(r, 0, sizeof(*r));
++
++      r->start = start;
++      r->end = start + size - 1;
++      r->name = name;
++      r->flags = flags;
++}
++
++static void resource_init_io_named(struct resource *r,
++                                 resource_size_t start, resource_size_t size,
++                                 const char *name)
++{
++      resource_init_named(r, start, size, name, IORESOURCE_IO);
++}
++
++static void resource_init_mem_named(struct resource *r,
++                                 resource_size_t start, resource_size_t size,
++                                 const char *name)
++{
++      resource_init_named(r, start, size, name, IORESOURCE_MEM);
++}
++
++static inline bool __screen_info_has_ega_gfx(unsigned int mode)
++{
++      switch (mode) {
++      case 0x0d:      /* 320x200-4 */
++      case 0x0e:      /* 640x200-4 */
++      case 0x0f:      /* 640x350-1 */
++      case 0x10:      /* 640x350-4 */
++              return true;
++      default:
++              return false;
++      }
++}
++
++static inline bool __screen_info_has_vga_gfx(unsigned int mode)
++{
++      switch (mode) {
++      case 0x10:      /* 640x480-1 */
++      case 0x12:      /* 640x480-4 */
++      case 0x13:      /* 320-200-8 */
++      case 0x6a:      /* 800x600-4 (VESA) */
++              return true;
++      default:
++              return __screen_info_has_ega_gfx(mode);
++      }
++}
++
++/**
++ * screen_info_resources() - Get resources from screen_info structure
++ * @si: the screen_info
++ * @r: pointer to an array of resource structures
++ * @num: number of elements in @r:
++ *
++ * Returns:
++ * The number of resources stored in @r on success, or a negative errno code otherwise.
++ *
++ * A call to screen_info_resources() returns the resources consumed by the
++ * screen_info's device or framebuffer. The result is stored in the caller-supplied
++ * array @r with up to @num elements. The function returns the number of
++ * initialized elements.
++ */
++ssize_t screen_info_resources(const struct screen_info *si, struct resource *r, size_t num)
++{
++      struct resource *pos = r;
++      unsigned int type = screen_info_video_type(si);
++      u64 base, size;
++
++      switch (type) {
++      case VIDEO_TYPE_MDA:
++              if (num > 0)
++                      resource_init_io_named(pos++, 0x3b0, 12, "mda");
++              if (num > 1)
++                      resource_init_io_named(pos++, 0x3bf, 0x01, "mda");
++              if (num > 2)
++                      resource_init_mem_named(pos++, 0xb0000, 0x2000, "mda");
++              break;
++      case VIDEO_TYPE_CGA:
++              if (num > 0)
++                      resource_init_io_named(pos++, 0x3d4, 0x02, "cga");
++              if (num > 1)
++                      resource_init_mem_named(pos++, 0xb8000, 0x2000, "cga");
++              break;
++      case VIDEO_TYPE_EGAM:
++              if (num > 0)
++                      resource_init_io_named(pos++, 0x3bf, 0x10, "ega");
++              if (num > 1)
++                      resource_init_mem_named(pos++, 0xb0000, 0x8000, "ega");
++              break;
++      case VIDEO_TYPE_EGAC:
++              if (num > 0)
++                      resource_init_io_named(pos++, 0x3c0, 0x20, "ega");
++              if (num > 1) {
++                      if (__screen_info_has_ega_gfx(si->orig_video_mode))
++                              resource_init_mem_named(pos++, 0xa0000, 0x10000, "ega");
++                      else
++                              resource_init_mem_named(pos++, 0xb8000, 0x8000, "ega");
++              }
++              break;
++      case VIDEO_TYPE_VGAC:
++              if (num > 0)
++                      resource_init_io_named(pos++, 0x3c0, 0x20, "vga+");
++              if (num > 1) {
++                      if (__screen_info_has_vga_gfx(si->orig_video_mode))
++                              resource_init_mem_named(pos++, 0xa0000, 0x10000, "vga+");
++                      else
++                              resource_init_mem_named(pos++, 0xb8000, 0x8000, "vga+");
++              }
++              break;
++      case VIDEO_TYPE_VLFB:
++      case VIDEO_TYPE_EFI:
++              base = __screen_info_lfb_base(si);
++              if (!base)
++                      break;
++              size = __screen_info_lfb_size(si, type);
++              if (!size)
++                      break;
++              if (num > 0)
++                      resource_init_mem_named(pos++, base, size, "lfb");
++              break;
++      case VIDEO_TYPE_PICA_S3:
++      case VIDEO_TYPE_MIPS_G364:
++      case VIDEO_TYPE_SGI:
++      case VIDEO_TYPE_TGAC:
++      case VIDEO_TYPE_SUN:
++      case VIDEO_TYPE_SUNPCI:
++      case VIDEO_TYPE_PMAC:
++      default:
++              /* not supported */
++              return -EINVAL;
++      }
++
++      return pos - r;
++}
++EXPORT_SYMBOL(screen_info_resources);
+diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
+index eab7081392d50..e7a02c5609d12 100644
+--- a/include/linux/screen_info.h
++++ b/include/linux/screen_info.h
+@@ -4,6 +4,106 @@
+ #include <uapi/linux/screen_info.h>
++/**
++ * SCREEN_INFO_MAX_RESOURCES - maximum number of resources per screen_info
++ */
++#define SCREEN_INFO_MAX_RESOURCES     3
++
++struct resource;
++
++static inline bool __screen_info_has_lfb(unsigned int type)
++{
++      return (type == VIDEO_TYPE_VLFB) || (type == VIDEO_TYPE_EFI);
++}
++
++static inline u64 __screen_info_lfb_base(const struct screen_info *si)
++{
++      u64 lfb_base = si->lfb_base;
++
++      if (si->capabilities & VIDEO_CAPABILITY_64BIT_BASE)
++              lfb_base |= (u64)si->ext_lfb_base << 32;
++
++      return lfb_base;
++}
++
++static inline u64 __screen_info_lfb_size(const struct screen_info *si, unsigned int type)
++{
++      u64 lfb_size = si->lfb_size;
++
++      if (type == VIDEO_TYPE_VLFB)
++              lfb_size <<= 16;
++      return lfb_size;
++}
++
++static inline unsigned int __screen_info_video_type(unsigned int type)
++{
++      switch (type) {
++      case VIDEO_TYPE_MDA:
++      case VIDEO_TYPE_CGA:
++      case VIDEO_TYPE_EGAM:
++      case VIDEO_TYPE_EGAC:
++      case VIDEO_TYPE_VGAC:
++      case VIDEO_TYPE_VLFB:
++      case VIDEO_TYPE_PICA_S3:
++      case VIDEO_TYPE_MIPS_G364:
++      case VIDEO_TYPE_SGI:
++      case VIDEO_TYPE_TGAC:
++      case VIDEO_TYPE_SUN:
++      case VIDEO_TYPE_SUNPCI:
++      case VIDEO_TYPE_PMAC:
++      case VIDEO_TYPE_EFI:
++              return type;
++      default:
++              return 0;
++      }
++}
++
++/**
++ * screen_info_video_type() - Decodes the video type from struct screen_info
++ * @si: an instance of struct screen_info
++ *
++ * Returns:
++ * A VIDEO_TYPE_ constant representing si's type of video display, or 0 otherwise.
++ */
++static inline unsigned int screen_info_video_type(const struct screen_info *si)
++{
++      unsigned int type;
++
++      // check if display output is on
++      if (!si->orig_video_isVGA)
++              return 0;
++
++      // check for a known VIDEO_TYPE_ constant
++      type = __screen_info_video_type(si->orig_video_isVGA);
++      if (type)
++              return si->orig_video_isVGA;
++
++      // check if text mode has been initialized
++      if (!si->orig_video_lines || !si->orig_video_cols)
++              return 0;
++
++      // 80x25 text, mono
++      if (si->orig_video_mode == 0x07) {
++              if ((si->orig_video_ega_bx & 0xff) != 0x10)
++                      return VIDEO_TYPE_EGAM;
++              else
++                      return VIDEO_TYPE_MDA;
++      }
++
++      // EGA/VGA, 16 colors
++      if ((si->orig_video_ega_bx & 0xff) != 0x10) {
++              if (si->orig_video_isVGA)
++                      return VIDEO_TYPE_VGAC;
++              else
++                      return VIDEO_TYPE_EGAC;
++      }
++
++      // the rest...
++      return VIDEO_TYPE_CGA;
++}
++
++ssize_t screen_info_resources(const struct screen_info *si, struct resource *r, size_t num);
++
+ extern struct screen_info screen_info;
+ #endif /* _SCREEN_INFO_H */
+-- 
+2.43.0
+
diff --git a/queue-6.6/video-provide-screen_info_get_pci_dev-to-find-screen.patch b/queue-6.6/video-provide-screen_info_get_pci_dev-to-find-screen.patch
new file mode 100644 (file)
index 0000000..c7ce94e
--- /dev/null
@@ -0,0 +1,127 @@
+From ba9cccb2883b7e562e95b1d77654742594db9b23 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 Feb 2024 10:06:10 +0100
+Subject: video: Provide screen_info_get_pci_dev() to find screen_info's PCI
+ device
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 036105e3a776b6fc2fe0d262896a23ff2cc2e6b1 ]
+
+Add screen_info_get_pci_dev() to find the PCI device of an instance
+of screen_info. Does nothing on systems without PCI bus.
+
+v3:
+       * search PCI device with pci_get_base_class() (Sui)
+v2:
+       * remove ret from screen_info_pci_dev() (Javier)
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240212090736.11464-3-tzimmermann@suse.de
+Stable-dep-of: c2bc958b2b03 ("fbdev: vesafb: Detect VGA compatibility from screen info's VESA attributes")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/Makefile          |  1 +
+ drivers/video/screen_info_pci.c | 48 +++++++++++++++++++++++++++++++++
+ include/linux/screen_info.h     | 10 +++++++
+ 3 files changed, 59 insertions(+)
+ create mode 100644 drivers/video/screen_info_pci.c
+
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index b929b664d52cd..6bbf87c1b579e 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -9,6 +9,7 @@ obj-$(CONFIG_VIDEO_NOMODESET)     += nomodeset.o
+ obj-$(CONFIG_HDMI)                += hdmi.o
+ screen_info-y                   := screen_info_generic.o
++screen_info-$(CONFIG_PCI)         += screen_info_pci.o
+ obj-$(CONFIG_VT)                += console/
+ obj-$(CONFIG_FB_STI)            += console/
+diff --git a/drivers/video/screen_info_pci.c b/drivers/video/screen_info_pci.c
+new file mode 100644
+index 0000000000000..d8985a54ce717
+--- /dev/null
++++ b/drivers/video/screen_info_pci.c
+@@ -0,0 +1,48 @@
++// SPDX-License-Identifier: GPL-2.0
++
++#include <linux/pci.h>
++#include <linux/screen_info.h>
++
++static struct pci_dev *__screen_info_pci_dev(struct resource *res)
++{
++      struct pci_dev *pdev = NULL;
++      const struct resource *r = NULL;
++
++      if (!(res->flags & IORESOURCE_MEM))
++              return NULL;
++
++      while (!r && (pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) {
++              r = pci_find_resource(pdev, res);
++      }
++
++      return pdev;
++}
++
++/**
++ * screen_info_pci_dev() - Return PCI parent device that contains screen_info's framebuffer
++ * @si: the screen_info
++ *
++ * Returns:
++ * The screen_info's parent device or NULL on success, or a pointer-encoded
++ * errno value otherwise. The value NULL is not an error. It signals that no
++ * PCI device has been found.
++ */
++struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
++{
++      struct resource res[SCREEN_INFO_MAX_RESOURCES];
++      ssize_t i, numres;
++
++      numres = screen_info_resources(si, res, ARRAY_SIZE(res));
++      if (numres < 0)
++              return ERR_PTR(numres);
++
++      for (i = 0; i < numres; ++i) {
++              struct pci_dev *pdev = __screen_info_pci_dev(&res[i]);
++
++              if (pdev)
++                      return pdev;
++      }
++
++      return NULL;
++}
++EXPORT_SYMBOL(screen_info_pci_dev);
+diff --git a/include/linux/screen_info.h b/include/linux/screen_info.h
+index e7a02c5609d12..0eae08e3c6f90 100644
+--- a/include/linux/screen_info.h
++++ b/include/linux/screen_info.h
+@@ -9,6 +9,7 @@
+  */
+ #define SCREEN_INFO_MAX_RESOURCES     3
++struct pci_dev;
+ struct resource;
+ static inline bool __screen_info_has_lfb(unsigned int type)
+@@ -104,6 +105,15 @@ static inline unsigned int screen_info_video_type(const struct screen_info *si)
+ ssize_t screen_info_resources(const struct screen_info *si, struct resource *r, size_t num);
++#if defined(CONFIG_PCI)
++struct pci_dev *screen_info_pci_dev(const struct screen_info *si);
++#else
++static inline struct pci_dev *screen_info_pci_dev(const struct screen_info *si)
++{
++      return NULL;
++}
++#endif
++
+ extern struct screen_info screen_info;
+ #endif /* _SCREEN_INFO_H */
+-- 
+2.43.0
+