From: Sasha Levin Date: Sat, 3 Aug 2024 14:48:11 +0000 (-0400) Subject: Fixes for 6.6 X-Git-Tag: v6.1.104~33 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2a38b6ea1499fa7af2c99cfacfbc1657eb1ab0f8;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.6 Signed-off-by: Sasha Levin --- 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 index 00000000000..4c3cfcd6534 --- /dev/null +++ b/queue-6.6/arm64-dts-qcom-ipq8074-disable-ss-instance-in-parkmo.patch @@ -0,0 +1,53 @@ +From e049dbf8374e821257d8b9c318b92bc4b1acd251 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jul 2024 20:58:42 +0530 +Subject: arm64: dts: qcom: ipq8074: Disable SS instance in Parkmode for USB + +From: Krishna Kurapati + +[ 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 +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20240704152848.3380602-3-quic_kriskura@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 = ; + 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 = ; + 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 index 00000000000..9a8872eb3d6 --- /dev/null +++ b/queue-6.6/arm64-dts-qcom-msm8998-disable-ss-instance-in-parkmo.patch @@ -0,0 +1,45 @@ +From fa49691b09625e179f2d68d6dd54ecf5902da707 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jul 2024 20:58:43 +0530 +Subject: arm64: dts: qcom: msm8998: Disable SS instance in Parkmode for USB + +From: Krishna Kurapati + +[ 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 +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20240704152848.3380602-4-quic_kriskura@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 = ; + 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 index 00000000000..c36b61087b4 --- /dev/null +++ b/queue-6.6/arm64-dts-qcom-msm8998-switch-usb-qmp-phy-to-new-sty.patch @@ -0,0 +1,85 @@ +From 6fd50975f0541b2fb1a8987a5ea79a03a82eba9a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20230824211952.1397699-11-dmitry.baryshkov@linaro.org +Signed-off-by: Bjorn Andersson +Stable-dep-of: 0046325ae520 ("arm64: dts: qcom: msm8998: Disable SS instance in Parkmode for USB") +Signed-off-by: Sasha Levin +--- + 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 = ; + 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 index 00000000000..15349a56c4d --- /dev/null +++ b/queue-6.6/arm64-dts-qcom-sc7180-disable-superspeed-instances-i.patch @@ -0,0 +1,46 @@ +From 272963ade147430b36a947efea83d0102ad707f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Jun 2024 11:36:58 +0530 +Subject: arm64: dts: qcom: sc7180: Disable SuperSpeed instances in park mode + +From: Krishna Kurapati + +[ 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 +Cc: stable@vger.kernel.org +Fixes: 0b766e7fe5a2 ("arm64: dts: qcom: sc7180: Add USB related nodes") +Signed-off-by: Krishna Kurapati +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20240604060659.1449278-2-quic_kriskura@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..9a86cc932df --- /dev/null +++ b/queue-6.6/arm64-dts-qcom-sc7180-switch-usb-dp-qmp-phy-to-new-s.patch @@ -0,0 +1,132 @@ +From 1f1b66357768bb6be884e37de9b5bb412478b6b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20230711120916.4165894-6-dmitry.baryshkov@linaro.org +Signed-off-by: Bjorn Andersson +Stable-dep-of: 5b8baed4b881 ("arm64: dts: qcom: sc7180: Disable SuperSpeed instances in park mode") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 00000000000..73759961ef0 --- /dev/null +++ b/queue-6.6/arm64-dts-qcom-sc7280-disable-superspeed-instances-i.patch @@ -0,0 +1,46 @@ +From e7db29acff625344c8e5663ff4bbff74edca2bfd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 4 Jun 2024 11:36:59 +0530 +Subject: arm64: dts: qcom: sc7280: Disable SuperSpeed instances in park mode + +From: Krishna Kurapati + +[ 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 +Cc: stable@vger.kernel.org +Fixes: bb9efa59c665 ("arm64: dts: qcom: sc7280: Add USB related nodes") +Signed-off-by: Krishna Kurapati +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20240604060659.1449278-3-quic_kriskura@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..d488af7341e --- /dev/null +++ b/queue-6.6/arm64-dts-qcom-sc7280-switch-usb-dp-qmp-phy-to-new-s.patch @@ -0,0 +1,139 @@ +From 2da451421a06aa7e800f090dc816848ca8c61ce3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20230711120916.4165894-8-dmitry.baryshkov@linaro.org +Signed-off-by: Bjorn Andersson +Stable-dep-of: 3d930f1750ce ("arm64: dts: qcom: sc7280: Disable SuperSpeed instances in park mode") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 00000000000..73313009443 --- /dev/null +++ b/queue-6.6/arm64-dts-qcom-sdm845-disable-ss-instance-in-parkmod.patch @@ -0,0 +1,53 @@ +From 24887ea03af82d4722fb2c1818d2c8172acd8441 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jul 2024 20:58:48 +0530 +Subject: arm64: dts: qcom: sdm845: Disable SS instance in Parkmode for USB + +From: Krishna Kurapati + +[ 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 +Reviewed-by: Konrad Dybcio +Link: https://lore.kernel.org/r/20240704152848.3380602-9-quic_kriskura@quicinc.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f49a726880b --- /dev/null +++ b/queue-6.6/arm64-dts-qcom-sdm845-switch-usb-dp-qmp-phy-to-new-s.patch @@ -0,0 +1,132 @@ +From e107f476bf8765454a4764b74d807bc22558e61b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Dmitry Baryshkov +Link: https://lore.kernel.org/r/20230711120916.4165894-9-dmitry.baryshkov@linaro.org +Signed-off-by: Bjorn Andersson +Stable-dep-of: cf4d6d54eadb ("arm64: dts: qcom: sdm845: Disable SS instance in Parkmode for USB") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 index 00000000000..4886e8296c6 --- /dev/null +++ b/queue-6.6/arm64-dts-qcom-sdm845-switch-usb-qmp-phy-to-new-styl.patch @@ -0,0 +1,87 @@ +From 14bf84cd632af11b20c9a30638e655ab2302a1f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20230824211952.1397699-12-dmitry.baryshkov@linaro.org +Signed-off-by: Bjorn Andersson +Stable-dep-of: cf4d6d54eadb ("arm64: dts: qcom: sdm845: Disable SS instance in Parkmode for USB") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..9606a3e8ffb --- /dev/null +++ b/queue-6.6/cpufreq-qcom-nvmem-fix-memory-leaks-in-probe-error-p.patch @@ -0,0 +1,65 @@ +From 3b6f27b5250d0d617b0a74fa9c346bbfb0295a5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 May 2024 23:24:59 +0200 +Subject: cpufreq: qcom-nvmem: fix memory leaks in probe error paths + +From: Javier Carrasco + +[ 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 +Signed-off-by: Viresh Kumar +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ead44d2f0b4 --- /dev/null +++ b/queue-6.6/cpufreq-qcom-nvmem-simplify-driver-data-allocation.patch @@ -0,0 +1,135 @@ +From c160679379f5a41cb3811d06ab586e5357d4e3c1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Oct 2023 10:06:02 +0200 +Subject: cpufreq: qcom-nvmem: Simplify driver data allocation + +From: Stephan Gerhold + +[ 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 +Reviewed-by: Konrad Dybcio +Signed-off-by: Viresh Kumar +Stable-dep-of: d01c84b97f19 ("cpufreq: qcom-nvmem: fix memory leaks in probe error paths") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c3b30135651 --- /dev/null +++ b/queue-6.6/dmaengine-fsl-edma-add-address-for-channel-mux-regis.patch @@ -0,0 +1,95 @@ +From bb334457797da6b70683c6c8ac71826261f43c2d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20231221153528.1588049-4-Frank.Li@nxp.com +Signed-off-by: Vinod Koul +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 +--- + 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 index 00000000000..e3e086f7323 --- /dev/null +++ b/queue-6.6/dmaengine-fsl-edma-add-i.mx8ulp-edma-support.patch @@ -0,0 +1,117 @@ +From ed5b2515122d9dc42b0dbef544e384b942c4d79a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Mar 2024 11:34:54 -0400 +Subject: dmaengine: fsl-edma: add i.MX8ULP edma support + +From: Joy Zou + +[ 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 +Reviewed-by: Frank Li +Link: https://lore.kernel.org/r/20240323-8ulp_edma-v3-5-c0e981027c05@nxp.com +Signed-off-by: Vinod Koul +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 +--- + 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 + ++#include + #include + #include + #include +@@ -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 index 00000000000..dad1c518098 --- /dev/null +++ b/queue-6.6/dmaengine-fsl-edma-change-the-memory-access-from-loc.patch @@ -0,0 +1,89 @@ +From 66c4fd587d3c9e3fc37aa426684c8aaf09d0f8ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: stable@vger.kernel.org +Reviewed-by: Frank Li +Link: https://lore.kernel.org/r/20240510030959.703663-1-joy.zou@nxp.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..d6e301be022 --- /dev/null +++ b/queue-6.6/dmaengine-fsl-edma-clean-up-unused-fsl-imx8qm-adma-c.patch @@ -0,0 +1,94 @@ +From f342365f0faf711ff1b64c6ab6ffe9a48647c968 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Apr 2024 14:45:07 +0800 +Subject: dmaengine: fsl-edma: clean up unused "fsl,imx8qm-adma" compatible + string + +From: Joy Zou + +[ 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 +Reviewed-by: Frank Li +Link: https://lore.kernel.org/r/20240424064508.1886764-2-joy.zou@nxp.com +Signed-off-by: Vinod Koul +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 +--- + 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 index 00000000000..7778c0f2d3c --- /dev/null +++ b/queue-6.6/ext4-check-the-extent-status-again-before-inserting-.patch @@ -0,0 +1,100 @@ +From 23136c890b3cbe78363afb1ff1b7ad4a10b684dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 May 2024 20:39:57 +0800 +Subject: ext4: check the extent status again before inserting delalloc block + +From: Zhang Yi + +[ 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 +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/20240517124005.347221-3-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f3c6ecefe60 --- /dev/null +++ b/queue-6.6/ext4-convert-to-exclusive-lock-while-inserting-delal.patch @@ -0,0 +1,114 @@ +From d3ff186b36bc2b970221ca5db8b8d72cba4874fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jan 2024 09:58:01 +0800 +Subject: ext4: convert to exclusive lock while inserting delalloc extents + +From: Zhang Yi + +[ 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 +Suggested-by: Jan Kara +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20240127015825.1608160-3-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 0ea6560abb3b ("ext4: check the extent status again before inserting delalloc block") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..2bfb574d86e --- /dev/null +++ b/queue-6.6/ext4-factor-out-a-common-helper-to-query-extent-map.patch @@ -0,0 +1,104 @@ +From 00632e1b1d3ee374b3058c12f3e1cb65358131df Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 May 2024 20:39:56 +0800 +Subject: ext4: factor out a common helper to query extent map + +From: Zhang Yi + +[ 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 +Reviewed-by: Jan Kara +Reviewed-by: Ritesh Harjani (IBM) +Link: https://patch.msgid.link/20240517124005.347221-2-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 0ea6560abb3b ("ext4: check the extent status again before inserting delalloc block") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f1461d1d7a1 --- /dev/null +++ b/queue-6.6/ext4-refactor-ext4_da_map_blocks.patch @@ -0,0 +1,93 @@ +From a772934c48f0157eb94d2d92d3a88570a5391f27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 27 Jan 2024 09:58:00 +0800 +Subject: ext4: refactor ext4_da_map_blocks() + +From: Zhang Yi + +[ Upstream commit 3fcc2b887a1ba4c1f45319cd8c54daa263ecbc36 ] + +Refactor and cleanup ext4_da_map_blocks(), reduce some unnecessary +parameters and branches, no logic changes. + +Signed-off-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20240127015825.1608160-2-yi.zhang@huaweicloud.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: 0ea6560abb3b ("ext4: check the extent status again before inserting delalloc block") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..69f9adbb128 --- /dev/null +++ b/queue-6.6/f2fs-assign-curseg_all_data_atgc-if-blkaddr-is-valid.patch @@ -0,0 +1,59 @@ +From 2cddf54552b6fc61aea77ffcee7cadc6e37be688 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 18 Jun 2024 02:15:38 +0000 +Subject: f2fs: assign CURSEG_ALL_DATA_ATGC if blkaddr is valid + +From: Jaegeuk Kim + +[ 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 +Tested-by: Will McVicker +Signed-off-by: Jaegeuk Kim +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..9060487c461 --- /dev/null +++ b/queue-6.6/f2fs-fix-to-avoid-use-ssr-allocate-when-do-defragmen.patch @@ -0,0 +1,75 @@ +From 6dee8cc8ab58aef4fa09219cfa6e739f3023b2f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 May 2024 17:47:00 +0800 +Subject: f2fs: fix to avoid use SSR allocate when do defragment + +From: Zhiguo Niu + +[ 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 +Reviewed-by: Chao Yu +Signed-off-by: Jaegeuk Kim +Stable-dep-of: 8cb1f4080dd9 ("f2fs: assign CURSEG_ALL_DATA_ATGC if blkaddr is valid") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..19df67c9121 --- /dev/null +++ b/queue-6.6/fbdev-vesafb-detect-vga-compatibility-from-screen-in.patch @@ -0,0 +1,81 @@ +From e1d2254b288296e8238741fd68a211f3887f7e12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Jun 2024 13:06:27 +0200 +Subject: fbdev: vesafb: Detect VGA compatibility from screen info's VESA + attributes + +From: Thomas Zimmermann + +[ 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 +Fixes: 5e8ddcbe8692 ("Video mode probing support for the new x86 setup code") +Reviewed-by: Javier Martinez Canillas +Cc: # v2.6.23+ +Signed-off-by: Helge Deller +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..eb2dd6268eb --- /dev/null +++ b/queue-6.6/fbdev-vesafb-replace-references-to-global-screen_inf.patch @@ -0,0 +1,159 @@ +From da83c44e9ff5c01779868182e8ec907b5c519e2e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Dec 2023 14:50:28 +0100 +Subject: fbdev/vesafb: Replace references to global screen_info by local + pointer + +From: Thomas Zimmermann + +[ 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 +Reviewed-by: Javier Martinez Canillas +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 +--- + 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 index 00000000000..22f4ec26dcb --- /dev/null +++ b/queue-6.6/firmware-sysfb-update-screen_info-for-relocated-efi-.patch @@ -0,0 +1,191 @@ +From a0ac8a148219079d571521436d1df6735f4488db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Feb 2024 10:06:15 +0100 +Subject: firmware/sysfb: Update screen_info for relocated EFI framebuffers + +From: Thomas Zimmermann + +[ 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 +Reviewed-by: Javier Martinez Canillas +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 +--- + 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 ++#include + #include ++#include ++ ++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 + ++#include ++ + /** + * 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 index 00000000000..f915cae489b --- /dev/null +++ b/queue-6.6/kvm-nvmx-add-a-helper-to-get-highest-pending-from-po.patch @@ -0,0 +1,81 @@ +From 84b719ce71f9017aa147913fcb7148880203a5ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 + #include + + 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 index 00000000000..6fd5f1caaca --- /dev/null +++ b/queue-6.6/kvm-nvmx-check-for-pending-posted-interrupts-when-lo.patch @@ -0,0 +1,81 @@ +From fbd77caec10aae04a920819111c076592bc0437c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reported-by: Jim Mattson +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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..1d727ce236e --- /dev/null +++ b/queue-6.6/kvm-vmx-move-posted-interrupt-descriptor-out-of-vmx-.patch @@ -0,0 +1,255 @@ +From 40b064edb66ce131945a7f18730a03c4fee8d170 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Apr 2024 10:41:03 -0700 +Subject: KVM: VMX: Move posted interrupt descriptor out of VMX code + +From: Jacob Pan + +[ 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 +Signed-off-by: Thomas Gleixner +Acked-by: Sean Christopherson +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 +--- + 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 + + 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 + #include + #include ++#include + + #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 index 00000000000..0b26e944e46 --- /dev/null +++ b/queue-6.6/kvm-vmx-split-off-vmx_onhyperv.-ch-from-hyperv.-ch.patch @@ -0,0 +1,643 @@ +From 8339c1753fb9f735a4c2edb8c28907e141d4805e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Dec 2023 11:36:17 +0100 +Subject: KVM: VMX: Split off vmx_onhyperv.{ch} from hyperv.{ch} + +From: Vitaly Kuznetsov + +[ 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 +Tested-by: Jeremi Piotrowski +Signed-off-by: Vitaly Kuznetsov +Link: https://lore.kernel.org/r/20231205103630.1391318-4-vkuznets@redhat.com +Signed-off-by: Sean Christopherson +Stable-dep-of: d83c36d822be ("KVM: nVMX: Add a helper to get highest pending from Posted Interrupt vector") +Signed-off-by: Sasha Levin +--- + 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 ++ ++#include ++ ++#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 + +-#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 index 00000000000..59a8237d0f0 --- /dev/null +++ b/queue-6.6/leds-trigger-call-synchronize_rcu-before-calling-tri.patch @@ -0,0 +1,60 @@ +From 3a52063c3f8a3658f7570e691738eea2372254ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 31 May 2024 14:01:24 +0200 +Subject: leds: trigger: Call synchronize_rcu() before calling trig->activate() + +From: Hans de Goede + +[ 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 +Link: https://lore.kernel.org/r/20240531120124.75662-1-hdegoede@redhat.com +Signed-off-by: Lee Jones +Stable-dep-of: ab477b766edd ("leds: triggers: Flush pending brightness before activating trigger") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..29d9f97c3c5 --- /dev/null +++ b/queue-6.6/leds-trigger-remove-unused-function-led_trigger_rena.patch @@ -0,0 +1,77 @@ +From 793adb4eca7d8567f77d5aeaafde64f6bc691437 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Dec 2023 23:56:41 +0100 +Subject: leds: trigger: Remove unused function led_trigger_rename_static() + +From: Heiner Kallweit + +[ 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 +Link: https://lore.kernel.org/r/d90f30be-f661-4db7-b0b5-d09d07a78a68@gmail.com +Signed-off-by: Lee Jones +Stable-dep-of: ab477b766edd ("leds: triggers: Flush pending brightness before activating trigger") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..007ca321a55 --- /dev/null +++ b/queue-6.6/leds-trigger-store-brightness-set-by-led_trigger_eve.patch @@ -0,0 +1,98 @@ +From 3830b540c7ec401419f44240eac2326305886425 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Mar 2024 21:57:30 +0100 +Subject: leds: trigger: Store brightness set by led_trigger_event() + +From: Heiner Kallweit + +[ 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 +Reviewed-by: Takashi Iwai +Link: https://lore.kernel.org/r/b1358b25-3f30-458d-8240-5705ae007a8a@gmail.com +Signed-off-by: Lee Jones +Stable-dep-of: ab477b766edd ("leds: triggers: Flush pending brightness before activating trigger") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c1ba56b841e --- /dev/null +++ b/queue-6.6/leds-triggers-flush-pending-brightness-before-activa.patch @@ -0,0 +1,66 @@ +From 1c90e2761168949bac909059f34b37f9e633a159 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Thomas Weißschuh +Link: https://lore.kernel.org/r/20240613-led-trigger-flush-v2-1-f4f970799d77@weissschuh.net +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..4c632b5fea9 --- /dev/null +++ b/queue-6.6/mips-dts-loongson-fix-liointc-irq-polarity.patch @@ -0,0 +1,172 @@ +From 3e7487e6b042ff4461b2eea8c71577eab26bbe64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Jun 2024 16:40:10 +0100 +Subject: MIPS: dts: loongson: Fix liointc IRQ polarity + +From: Jiaxun Yang + +[ 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 +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..6f1ccfc251b --- /dev/null +++ b/queue-6.6/mips-dts-loongson-fix-ls2k1000-rtc-interrupt.patch @@ -0,0 +1,38 @@ +From e87e764893e08797d8bd0c045d59cd52ea459edd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 14 Jun 2024 16:40:11 +0100 +Subject: MIPS: dts: loongson: Fix ls2k1000-rtc interrupt + +From: Jiaxun Yang + +[ 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 +Signed-off-by: Thomas Bogendoerfer +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b70c2a540a0 --- /dev/null +++ b/queue-6.6/mips-loongson64-dts-fix-pcie-port-nodes-for-ls7a.patch @@ -0,0 +1,161 @@ +From 9918a24a27bfede8b27b057a9079be92af462aab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 May 2024 19:51:22 +0100 +Subject: MIPS: Loongson64: DTS: Fix PCIe port nodes for ls7a + +From: Jiaxun Yang + +[ 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 +Signed-off-by: Thomas Bogendoerfer +Stable-dep-of: dbb69b9d6234 ("MIPS: dts: loongson: Fix liointc IRQ polarity") +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..eb72c788421 --- /dev/null +++ b/queue-6.6/mm-page_alloc-control-latency-caused-by-zone-pcp-dra.patch @@ -0,0 +1,118 @@ +From a70d3d95f23d43e0e7c08bac8a6ab092feb1eb96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Mar 2024 21:07:36 +0100 +Subject: mm: page_alloc: control latency caused by zone PCP draining + +From: Lucas Stach + +[ 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 +Signed-off-by: Peter Xu +Cc: Christophe Leroy +Cc: Jason Gunthorpe +Cc: "Matthew Wilcox (Oracle)" +Cc: Mike Rapoport (IBM) +Cc: Muchun Song +Cc: Alistair Popple +Cc: Andreas Larsson +Cc: "Aneesh Kumar K.V" +Cc: Arnd Bergmann +Cc: Bjorn Andersson +Cc: Borislav Petkov +Cc: Catalin Marinas +Cc: Dave Hansen +Cc: David S. Miller +Cc: Fabio Estevam +Cc: Ingo Molnar +Cc: Konrad Dybcio +Cc: Krzysztof Kozlowski +Cc: Mark Salter +Cc: Michael Ellerman +Cc: Naoya Horiguchi +Cc: "Naveen N. Rao" +Cc: Nicholas Piggin +Cc: Russell King +Cc: Shawn Guo +Cc: Thomas Gleixner +Cc: Will Deacon +Signed-off-by: Andrew Morton +Stable-dep-of: 66eca1021a42 ("mm/page_alloc: fix pcp->count race between drain_pages_zone() vs __rmqueue_pcplist()") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5c54ade2de4 --- /dev/null +++ b/queue-6.6/mm-page_alloc-fix-pcp-count-race-between-drain_pages.patch @@ -0,0 +1,99 @@ +From 478b0f5dd0b5cb386eb827e98b0e534ec2313ade Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reported-by: Yao Xingtao +Reviewed-by: Vlastimil Babka +Cc: David Hildenbrand +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e4cf139ff21 --- /dev/null +++ b/queue-6.6/mm-restrict-the-pcp-batch-scale-factor-to-avoid-too-.patch @@ -0,0 +1,181 @@ +From 31311eae50a7586a982c83d223f2e87bc0b62dc5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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" +Acked-by: Andrew Morton +Acked-by: Mel Gorman +Cc: Vlastimil Babka +Cc: David Hildenbrand +Cc: Johannes Weiner +Cc: Dave Hansen +Cc: Michal Hocko +Cc: Pavel Tatashin +Cc: Matthew Wilcox +Cc: Christoph Lameter +Cc: Arjan van de Ven +Cc: Sudeep Holla +Signed-off-by: Andrew Morton +Stable-dep-of: 66eca1021a42 ("mm/page_alloc: fix pcp->count race between drain_pages_zone() vs __rmqueue_pcplist()") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b555db52e2d --- /dev/null +++ b/queue-6.6/pci-add-pci_get_base_class-helper.patch @@ -0,0 +1,102 @@ +From 742984d0f3bc49648a46348c8f875ed615a4bfb9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 25 Aug 2023 14:27:10 +0800 +Subject: PCI: Add pci_get_base_class() helper + +From: Sui Jingfeng + +[ 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 +[bhelgaas: reword commit log] +Signed-off-by: Bjorn Helgaas +Reviewed-by: Alex Deucher +Stable-dep-of: c2bc958b2b03 ("fbdev: vesafb: Detect VGA compatibility from screen info's VESA attributes") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..eabdb666cb4 --- /dev/null +++ b/queue-6.6/perf-imx_perf-fix-counter-start-and-config-sequence.patch @@ -0,0 +1,47 @@ +From a0bf93f28f3a01e537cf93d8ea70115c84ab3467 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 May 2024 16:03:55 +0800 +Subject: perf: imx_perf: fix counter start and config sequence + +From: Xu Yang + +[ 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 +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 +Link: https://lore.kernel.org/r/20240529080358.703784-5-xu.yang_2@nxp.com +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e8fc4a61cec --- /dev/null +++ b/queue-6.6/series @@ -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 index 00000000000..e428f095fb8 --- /dev/null +++ b/queue-6.6/sysctl-allow-change-system-v-ipc-sysctls-inside-ipc-.patch @@ -0,0 +1,140 @@ +From 7d69f81c1db52f19266b1c1845ca2f6e1a294ff0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Jan 2024 15:46:41 +0000 +Subject: sysctl: allow change system v ipc sysctls inside ipc namespace + +From: Alexey Gladkov + +[ 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 +Signed-off-by: Eric W. Biederman +Link: https://lkml.kernel.org/r/e2d84d3ec0172cfff759e6065da84ce0cc2736f8.1663756794.git.legion@kernel.org +Cc: Christian Brauner +Cc: Joel Granados +Cc: Kees Cook +Cc: Luis Chamberlain +Cc: Manfred Spraul +Cc: Davidlohr Bueso +Signed-off-by: Andrew Morton +Stable-dep-of: 98ca62ba9e2b ("sysctl: always initialize i_uid/i_gid") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #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 ¤t->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 index 00000000000..e603740f969 --- /dev/null +++ b/queue-6.6/sysctl-allow-to-change-limits-for-posix-messages-que.patch @@ -0,0 +1,95 @@ +From 5a552c8d6bcc1f57f7c0272f60c5c5ac60ebaa6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 15 Jan 2024 15:46:43 +0000 +Subject: sysctl: allow to change limits for posix messages queues + +From: Alexey Gladkov + +[ 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 +Signed-off-by: Eric W. Biederman +Link: https://lkml.kernel.org/r/7eb21211c8622e91d226e63416b1b93c079f60ee.1663756794.git.legion@kernel.org +Cc: Christian Brauner +Cc: Davidlohr Bueso +Cc: Joel Granados +Cc: Kees Cook +Cc: Luis Chamberlain +Cc: Manfred Spraul +Signed-off-by: Andrew Morton +Stable-dep-of: 98ca62ba9e2b ("sysctl: always initialize i_uid/i_gid") +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + + 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 ¤t->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 index 00000000000..9cea2753511 --- /dev/null +++ b/queue-6.6/sysctl-always-initialize-i_uid-i_gid.patch @@ -0,0 +1,52 @@ +From 978372c2ff5843a25e3a5914eab63e1d5e6d4b3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Joel Granados +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ec37dc982af --- /dev/null +++ b/queue-6.6/sysctl-treewide-drop-unused-argument-ctl_table_root-.patch @@ -0,0 +1,127 @@ +From fc7a41ff3afb2dcbee7911847a17c634e46a127e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Thomas Weißschuh +Signed-off-by: Joel Granados +Stable-dep-of: 98ca62ba9e2b ("sysctl: always initialize i_uid/i_gid") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e1c6aa46139 --- /dev/null +++ b/queue-6.6/thermal-bcm2835-convert-to-platform-remove-callback-.patch @@ -0,0 +1,63 @@ +From a3fbf18844ae89cf621420aa04ba9095fc5cefdf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Acked-by: Daniel Lezcano +Signed-off-by: Rafael J. Wysocki +Stable-dep-of: e90c369cc2ff ("thermal/drivers/broadcom: Fix race between removal and clock disable") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..4c15c9be707 --- /dev/null +++ b/queue-6.6/thermal-drivers-broadcom-fix-race-between-removal-an.patch @@ -0,0 +1,105 @@ +From 2baa80182561a0e62050aa262b1e09abb84af0d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jul 2024 14:59:31 +0200 +Subject: thermal/drivers/broadcom: Fix race between removal and clock disable + +From: Krzysztof Kozlowski + +[ 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 +Link: https://lore.kernel.org/r/20240709-thermal-probe-v1-1-241644e2b6e0@linaro.org +Signed-off-by: Daniel Lezcano +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a208a99049a --- /dev/null +++ b/queue-6.6/video-add-helpers-for-decoding-screen_info.patch @@ -0,0 +1,355 @@ +From 0b160bbb835bd6bfa264b86bc2bfcbb56e88a6e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 12 Feb 2024 10:06:09 +0100 +Subject: video: Add helpers for decoding screen_info + +From: Thomas Zimmermann + +[ 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 +Reviewed-by: Javier Martinez Canillas +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 +--- + 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 ++#include ++#include ++#include ++ ++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 + ++/** ++ * 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 index 00000000000..c7ce94e220f --- /dev/null +++ b/queue-6.6/video-provide-screen_info_get_pci_dev-to-find-screen.patch @@ -0,0 +1,127 @@ +From ba9cccb2883b7e562e95b1d77654742594db9b23 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Javier Martinez Canillas +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 +--- + 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 ++#include ++ ++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 +