]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.1
authorSasha Levin <sashal@kernel.org>
Sat, 3 Aug 2024 14:48:12 +0000 (10:48 -0400)
committerSasha Levin <sashal@kernel.org>
Sat, 3 Aug 2024 14:48:12 +0000 (10:48 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
38 files changed:
queue-6.1/arm64-dts-qcom-ipq8074-disable-ss-instance-in-parkmo.patch [new file with mode: 0644]
queue-6.1/arm64-dts-qcom-msm8998-disable-ss-instance-in-parkmo.patch [new file with mode: 0644]
queue-6.1/arm64-dts-qcom-msm8998-switch-usb-qmp-phy-to-new-sty.patch [new file with mode: 0644]
queue-6.1/cpufreq-qcom-nvmem-convert-to-platform-remove-callba.patch [new file with mode: 0644]
queue-6.1/cpufreq-qcom-nvmem-fix-memory-leaks-in-probe-error-p.patch [new file with mode: 0644]
queue-6.1/cpufreq-qcom-nvmem-simplify-driver-data-allocation.patch [new file with mode: 0644]
queue-6.1/drm-i915-dp-don-t-switch-the-lttpr-mode-on-an-active.patch [new file with mode: 0644]
queue-6.1/drm-udl-move-connector-to-modesetting-code.patch [new file with mode: 0644]
queue-6.1/drm-udl-remove-drm_connector_poll_hpd.patch [new file with mode: 0644]
queue-6.1/drm-udl-rename-struct-udl_drm_connector-to-struct-ud.patch [new file with mode: 0644]
queue-6.1/drm-udl-test-pixel-limit-in-mode-config-s-mode-valid.patch [new file with mode: 0644]
queue-6.1/drm-udl-use-usb-timeout-constant-when-reading-edid.patch [new file with mode: 0644]
queue-6.1/drm-udl-various-improvements-to-the-connector.patch [new file with mode: 0644]
queue-6.1/ext4-check-the-extent-status-again-before-inserting-.patch [new file with mode: 0644]
queue-6.1/ext4-convert-to-exclusive-lock-while-inserting-delal.patch [new file with mode: 0644]
queue-6.1/ext4-factor-out-a-common-helper-to-query-extent-map.patch [new file with mode: 0644]
queue-6.1/ext4-make-ext4_es_insert_extent-return-void.patch [new file with mode: 0644]
queue-6.1/ext4-refactor-ext4_da_map_blocks.patch [new file with mode: 0644]
queue-6.1/f2fs-assign-curseg_all_data_atgc-if-blkaddr-is-valid.patch [new file with mode: 0644]
queue-6.1/f2fs-fix-to-avoid-use-ssr-allocate-when-do-defragmen.patch [new file with mode: 0644]
queue-6.1/irqdomain-fixed-unbalanced-fwnode-get-and-put.patch [new file with mode: 0644]
queue-6.1/irqdomain-use-return-value-of-strreplace.patch [new file with mode: 0644]
queue-6.1/leds-trigger-call-synchronize_rcu-before-calling-tri.patch [new file with mode: 0644]
queue-6.1/leds-trigger-remove-unused-function-led_trigger_rena.patch [new file with mode: 0644]
queue-6.1/leds-trigger-store-brightness-set-by-led_trigger_eve.patch [new file with mode: 0644]
queue-6.1/leds-triggers-flush-pending-brightness-before-activa.patch [new file with mode: 0644]
queue-6.1/mips-dts-loongson-fix-liointc-irq-polarity.patch [new file with mode: 0644]
queue-6.1/mips-dts-loongson-fix-ls2k1000-rtc-interrupt.patch [new file with mode: 0644]
queue-6.1/mips-loongson64-dts-add-rtc-support-to-loongson-2k10.patch [new file with mode: 0644]
queue-6.1/mips-loongson64-dts-fix-pcie-port-nodes-for-ls7a.patch [new file with mode: 0644]
queue-6.1/mm-page_alloc-control-latency-caused-by-zone-pcp-dra.patch [new file with mode: 0644]
queue-6.1/mm-page_alloc-fix-pcp-count-race-between-drain_pages.patch [new file with mode: 0644]
queue-6.1/mm-restrict-the-pcp-batch-scale-factor-to-avoid-too-.patch [new file with mode: 0644]
queue-6.1/series [new file with mode: 0644]
queue-6.1/sysctl-allow-change-system-v-ipc-sysctls-inside-ipc-.patch [new file with mode: 0644]
queue-6.1/sysctl-allow-to-change-limits-for-posix-messages-que.patch [new file with mode: 0644]
queue-6.1/sysctl-always-initialize-i_uid-i_gid.patch [new file with mode: 0644]
queue-6.1/sysctl-treewide-drop-unused-argument-ctl_table_root-.patch [new file with mode: 0644]

diff --git a/queue-6.1/arm64-dts-qcom-ipq8074-disable-ss-instance-in-parkmo.patch b/queue-6.1/arm64-dts-qcom-ipq8074-disable-ss-instance-in-parkmo.patch
new file mode 100644 (file)
index 0000000..b6ac113
--- /dev/null
@@ -0,0 +1,53 @@
+From ad6522cb8844d205f3f16fa111f7857900599149 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jul 2024 20:58:42 +0530
+Subject: arm64: dts: qcom: ipq8074: Disable SS instance in Parkmode for USB
+
+From: Krishna Kurapati <quic_kriskura@quicinc.com>
+
+[ Upstream commit dc6ba95c6c4400a84cca5b419b34ae852a08cfb5 ]
+
+For Gen-1 targets like IPQ8074, it is seen that stressing out the
+controller in host mode results in HC died error:
+
+ xhci-hcd.12.auto: xHCI host not responding to stop endpoint command
+ xhci-hcd.12.auto: xHCI host controller not responding, assume dead
+ xhci-hcd.12.auto: HC died; cleaning up
+
+And at this instant only restarting the host mode fixes it. Disable
+SuperSpeed instance in park mode for IPQ8074 to mitigate this issue.
+
+Cc: stable@vger.kernel.org
+Fixes: 5e09bc51d07b ("arm64: dts: ipq8074: enable USB support")
+Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20240704152848.3380602-3-quic_kriskura@quicinc.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/ipq8074.dtsi | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+index 3d8e5ba51ce0d..2f53c099634b5 100644
+--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
++++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+@@ -593,6 +593,7 @@ dwc_0: usb@8a00000 {
+                               interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+                               phys = <&qusb_phy_0>, <&usb0_ssphy>;
+                               phy-names = "usb2-phy", "usb3-phy";
++                              snps,parkmode-disable-ss-quirk;
+                               snps,is-utmi-l1-suspend;
+                               snps,hird-threshold = /bits/ 8 <0x0>;
+                               snps,dis_u2_susphy_quirk;
+@@ -635,6 +636,7 @@ dwc_1: usb@8c00000 {
+                               interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+                               phys = <&qusb_phy_1>, <&usb1_ssphy>;
+                               phy-names = "usb2-phy", "usb3-phy";
++                              snps,parkmode-disable-ss-quirk;
+                               snps,is-utmi-l1-suspend;
+                               snps,hird-threshold = /bits/ 8 <0x0>;
+                               snps,dis_u2_susphy_quirk;
+-- 
+2.43.0
+
diff --git a/queue-6.1/arm64-dts-qcom-msm8998-disable-ss-instance-in-parkmo.patch b/queue-6.1/arm64-dts-qcom-msm8998-disable-ss-instance-in-parkmo.patch
new file mode 100644 (file)
index 0000000..42d9395
--- /dev/null
@@ -0,0 +1,45 @@
+From 55dfc71f98c390ee4a3d5ce0eea51b6893a3c7ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Jul 2024 20:58:43 +0530
+Subject: arm64: dts: qcom: msm8998: Disable SS instance in Parkmode for USB
+
+From: Krishna Kurapati <quic_kriskura@quicinc.com>
+
+[ Upstream commit 0046325ae52079b46da13a7f84dd7b2a6f7c38f8 ]
+
+For Gen-1 targets like MSM8998, it is seen that stressing out the
+controller in host mode results in HC died error:
+
+ xhci-hcd.12.auto: xHCI host not responding to stop endpoint command
+ xhci-hcd.12.auto: xHCI host controller not responding, assume dead
+ xhci-hcd.12.auto: HC died; cleaning up
+
+And at this instant only restarting the host mode fixes it. Disable
+SuperSpeed instance in park mode for MSM8998 to mitigate this issue.
+
+Cc: stable@vger.kernel.org
+Fixes: 026dad8f5873 ("arm64: dts: qcom: msm8998: Add USB-related nodes")
+Signed-off-by: Krishna Kurapati <quic_kriskura@quicinc.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20240704152848.3380602-4-quic_kriskura@quicinc.com
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/msm8998.dtsi | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi
+index c19fb8ae2da2a..4de9ff045ff52 100644
+--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi
++++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi
+@@ -2029,6 +2029,7 @@ usb3_dwc3: usb@a800000 {
+                               interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+                               snps,dis_u2_susphy_quirk;
+                               snps,dis_enblslpm_quirk;
++                              snps,parkmode-disable-ss-quirk;
+                               phys = <&qusb2phy>, <&usb3phy>;
+                               phy-names = "usb2-phy", "usb3-phy";
+                               snps,has-lpm-erratum;
+-- 
+2.43.0
+
diff --git a/queue-6.1/arm64-dts-qcom-msm8998-switch-usb-qmp-phy-to-new-sty.patch b/queue-6.1/arm64-dts-qcom-msm8998-switch-usb-qmp-phy-to-new-sty.patch
new file mode 100644 (file)
index 0000000..1dd2ab4
--- /dev/null
@@ -0,0 +1,85 @@
+From 66b93700e98677fef7b62e72aa31d617829a1d58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Aug 2023 00:19:46 +0300
+Subject: arm64: dts: qcom: msm8998: switch USB QMP PHY to new style of
+ bindings
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit b7efebfeb2e8ad8187cdabba5f0212ba2e6c1069 ]
+
+Change the USB QMP PHY to use newer style of QMP PHY bindings (single
+resource region, no per-PHY subnodes).
+
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://lore.kernel.org/r/20230824211952.1397699-11-dmitry.baryshkov@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Stable-dep-of: 0046325ae520 ("arm64: dts: qcom: msm8998: Disable SS instance in Parkmode for USB")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/msm8998.dtsi | 35 +++++++++++----------------
+ 1 file changed, 14 insertions(+), 21 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi
+index 3d4941dc31d74..c19fb8ae2da2a 100644
+--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi
++++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi
+@@ -2029,7 +2029,7 @@ usb3_dwc3: usb@a800000 {
+                               interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+                               snps,dis_u2_susphy_quirk;
+                               snps,dis_enblslpm_quirk;
+-                              phys = <&qusb2phy>, <&usb1_ssphy>;
++                              phys = <&qusb2phy>, <&usb3phy>;
+                               phy-names = "usb2-phy", "usb3-phy";
+                               snps,has-lpm-erratum;
+                               snps,hird-threshold = /bits/ 8 <0x10>;
+@@ -2038,33 +2038,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.1/cpufreq-qcom-nvmem-convert-to-platform-remove-callba.patch b/queue-6.1/cpufreq-qcom-nvmem-convert-to-platform-remove-callba.patch
new file mode 100644 (file)
index 0000000..2c60ef5
--- /dev/null
@@ -0,0 +1,64 @@
+From 7c36ec163d96c4d00ff210fd15cdf8f369e1429f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Jul 2023 17:33:18 +0800
+Subject: cpufreq: qcom-nvmem: Convert to platform remove callback returning
+ void
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Yangtao Li <frank.li@vivo.com>
+
+[ Upstream commit 402732324b17a31f7e5dce9659d1b1f049fd65d3 ]
+
+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 (mostly) ignored
+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.
+
+Trivially convert this driver from always returning zero in the remove
+callback to the void returning variant.
+
+Cc: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Signed-off-by: Yangtao Li <frank.li@vivo.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Stable-dep-of: d01c84b97f19 ("cpufreq: qcom-nvmem: fix memory leaks in probe error paths")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/qcom-cpufreq-nvmem.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+index cb03bfb0435ea..91634b84baa87 100644
+--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+@@ -374,7 +374,7 @@ static int qcom_cpufreq_probe(struct platform_device *pdev)
+       return ret;
+ }
+-static int qcom_cpufreq_remove(struct platform_device *pdev)
++static void qcom_cpufreq_remove(struct platform_device *pdev)
+ {
+       struct qcom_cpufreq_drv *drv = platform_get_drvdata(pdev);
+       unsigned int cpu;
+@@ -386,13 +386,11 @@ static int qcom_cpufreq_remove(struct platform_device *pdev)
+       kfree(drv->opp_tokens);
+       kfree(drv);
+-
+-      return 0;
+ }
+ static struct platform_driver qcom_cpufreq_driver = {
+       .probe = qcom_cpufreq_probe,
+-      .remove = qcom_cpufreq_remove,
++      .remove_new = qcom_cpufreq_remove,
+       .driver = {
+               .name = "qcom-cpufreq-nvmem",
+       },
+-- 
+2.43.0
+
diff --git a/queue-6.1/cpufreq-qcom-nvmem-fix-memory-leaks-in-probe-error-p.patch b/queue-6.1/cpufreq-qcom-nvmem-fix-memory-leaks-in-probe-error-p.patch
new file mode 100644 (file)
index 0000000..b6b4430
--- /dev/null
@@ -0,0 +1,65 @@
+From 686316ae33c275ffc1e8e209b221e11a2492d227 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 May 2024 23:24:59 +0200
+Subject: cpufreq: qcom-nvmem: fix memory leaks in probe error paths
+
+From: Javier Carrasco <javier.carrasco.cruz@gmail.com>
+
+[ Upstream commit d01c84b97f19f1137211e90b0a910289a560019e ]
+
+The code refactoring added new error paths between the np device node
+allocation and the call to of_node_put(), which leads to memory leaks if
+any of those errors occur.
+
+Add the missing of_node_put() in the error paths that require it.
+
+Cc: stable@vger.kernel.org
+Fixes: 57f2f8b4aa0c ("cpufreq: qcom: Refactor the driver to make it easier to extend")
+Signed-off-by: Javier Carrasco <javier.carrasco.cruz@gmail.com>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/qcom-cpufreq-nvmem.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+index 983991c0afd5c..2edb66097cdb9 100644
+--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+@@ -290,23 +290,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.1/cpufreq-qcom-nvmem-simplify-driver-data-allocation.patch b/queue-6.1/cpufreq-qcom-nvmem-simplify-driver-data-allocation.patch
new file mode 100644 (file)
index 0000000..6f85c18
--- /dev/null
@@ -0,0 +1,135 @@
+From c4ebe3ac348552471d25a8edb1ea0b8df6aaf730 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 Oct 2023 10:06:02 +0200
+Subject: cpufreq: qcom-nvmem: Simplify driver data allocation
+
+From: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
+
+[ Upstream commit 2a5d46c3ad6b0e62d2b04356ad999d504fb564e0 ]
+
+Simplify the allocation and cleanup of driver data by using devm
+together with a flexible array. Prepare for adding additional per-CPU
+data by defining a struct qcom_cpufreq_drv_cpu instead of storing the
+opp_tokens directly.
+
+Signed-off-by: Stephan Gerhold <stephan.gerhold@kernkonzept.com>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Stable-dep-of: d01c84b97f19 ("cpufreq: qcom-nvmem: fix memory leaks in probe error paths")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/qcom-cpufreq-nvmem.c | 49 ++++++++++------------------
+ 1 file changed, 18 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/cpufreq/qcom-cpufreq-nvmem.c b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+index 91634b84baa87..983991c0afd5c 100644
+--- a/drivers/cpufreq/qcom-cpufreq-nvmem.c
++++ b/drivers/cpufreq/qcom-cpufreq-nvmem.c
+@@ -53,10 +53,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;
+@@ -284,42 +288,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,
+@@ -345,9 +339,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;
+                       }
+@@ -366,11 +360,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;
+ }
+@@ -382,10 +372,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.1/drm-i915-dp-don-t-switch-the-lttpr-mode-on-an-active.patch b/queue-6.1/drm-i915-dp-don-t-switch-the-lttpr-mode-on-an-active.patch
new file mode 100644 (file)
index 0000000..3a799a6
--- /dev/null
@@ -0,0 +1,134 @@
+From d239c5bf3eec4d7d87800fd37803960aa613f5b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Jul 2024 22:00:25 +0300
+Subject: drm/i915/dp: Don't switch the LTTPR mode on an active link
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Imre Deak <imre.deak@intel.com>
+
+[ Upstream commit 509580fad7323b6a5da27e8365cd488f3b57210e ]
+
+Switching to transparent mode leads to a loss of link synchronization,
+so prevent doing this on an active link. This happened at least on an
+Intel N100 system / DELL UD22 dock, the LTTPR residing either on the
+host or the dock. To fix the issue, keep the current mode on an active
+link, adjusting the LTTPR count accordingly (resetting it to 0 in
+transparent mode).
+
+v2: Adjust code comment during link training about reiniting the LTTPRs.
+   (Ville)
+
+Fixes: 7b2a4ab8b0ef ("drm/i915: Switch to LTTPR transparent mode link training")
+Reported-and-tested-by: Gareth Yu <gareth.yu@intel.com>
+Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10902
+Cc: <stable@vger.kernel.org> # v5.15+
+Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Reviewed-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
+Signed-off-by: Imre Deak <imre.deak@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240708190029.271247-3-imre.deak@intel.com
+(cherry picked from commit 211ad49cf8ccfdc798a719b4d1e000d0a8a9e588)
+Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../drm/i915/display/intel_dp_link_training.c | 54 ++++++++++++++++---
+ 1 file changed, 48 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+index 3d3efcf02011e..1d9e4534287bb 100644
+--- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c
++++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c
+@@ -103,12 +103,26 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
+       return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
+ }
+-static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE])
++static bool intel_dp_lttpr_transparent_mode_enabled(struct intel_dp *intel_dp)
++{
++      return intel_dp->lttpr_common_caps[DP_PHY_REPEATER_MODE -
++                                         DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV] ==
++              DP_PHY_REPEATER_MODE_TRANSPARENT;
++}
++
++/*
++ * Read the LTTPR common capabilities and switch the LTTPR PHYs to
++ * non-transparent mode if this is supported. Preserve the
++ * transparent/non-transparent mode on an active link.
++ *
++ * Return the number of detected LTTPRs in non-transparent mode or 0 if the
++ * LTTPRs are in transparent mode or the detection failed.
++ */
++static int intel_dp_init_lttpr_phys(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE])
+ {
+       struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
+       struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+       int lttpr_count;
+-      int i;
+       if (!intel_dp_read_lttpr_common_caps(intel_dp, dpcd))
+               return 0;
+@@ -122,6 +136,19 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEI
+       if (lttpr_count == 0)
+               return 0;
++      /*
++       * Don't change the mode on an active link, to prevent a loss of link
++       * synchronization. See DP Standard v2.0 3.6.7. about the LTTPR
++       * resetting its internal state when the mode is changed from
++       * non-transparent to transparent.
++       */
++      if (intel_dp->link_trained) {
++              if (lttpr_count < 0 || intel_dp_lttpr_transparent_mode_enabled(intel_dp))
++                      goto out_reset_lttpr_count;
++
++              return lttpr_count;
++      }
++
+       /*
+        * See DP Standard v2.0 3.6.6.1. about the explicit disabling of
+        * non-transparent mode and the disable->enable non-transparent mode
+@@ -143,11 +170,25 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEI
+                           encoder->base.base.id, encoder->base.name);
+               intel_dp_set_lttpr_transparent_mode(intel_dp, true);
+-              intel_dp_reset_lttpr_count(intel_dp);
+-              return 0;
++              goto out_reset_lttpr_count;
+       }
++      return lttpr_count;
++
++out_reset_lttpr_count:
++      intel_dp_reset_lttpr_count(intel_dp);
++
++      return 0;
++}
++
++static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE])
++{
++      int lttpr_count;
++      int i;
++
++      lttpr_count = intel_dp_init_lttpr_phys(intel_dp, dpcd);
++
+       for (i = 0; i < lttpr_count; i++)
+               intel_dp_read_lttpr_phy_caps(intel_dp, dpcd, DP_PHY_LTTPR(i));
+@@ -1435,8 +1476,9 @@ void intel_dp_start_link_train(struct intel_dp *intel_dp,
+ {
+       bool passed;
+       /*
+-       * TODO: Reiniting LTTPRs here won't be needed once proper connector
+-       * HW state readout is added.
++       * Reinit the LTTPRs here to ensure that they are switched to
++       * non-transparent mode. During an earlier LTTPR detection this
++       * could've been prevented by an active link.
+        */
+       int lttpr_count = intel_dp_init_lttpr_and_dprx_caps(intel_dp);
+-- 
+2.43.0
+
diff --git a/queue-6.1/drm-udl-move-connector-to-modesetting-code.patch b/queue-6.1/drm-udl-move-connector-to-modesetting-code.patch
new file mode 100644 (file)
index 0000000..cf35749
--- /dev/null
@@ -0,0 +1,372 @@
+From a2860b78ab12115e5aa70d3afbe9cbd1289a15da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Oct 2022 11:53:44 +0200
+Subject: drm/udl: Move connector to modesetting code
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 0862cfd3e22f3f936927f2f7381c2519ba034c6e ]
+
+Move the connector next to the rest of the modesetting code. No
+functional changes.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221006095355.23579-6-tzimmermann@suse.de
+Stable-dep-of: 5aed213c7c6c ("drm/udl: Remove DRM_CONNECTOR_POLL_HPD")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/udl/Makefile        |   2 +-
+ drivers/gpu/drm/udl/udl_connector.c | 132 ----------------------------
+ drivers/gpu/drm/udl/udl_connector.h |  21 -----
+ drivers/gpu/drm/udl/udl_drv.h       |  11 +++
+ drivers/gpu/drm/udl/udl_modeset.c   | 122 +++++++++++++++++++++++++
+ 5 files changed, 134 insertions(+), 154 deletions(-)
+ delete mode 100644 drivers/gpu/drm/udl/udl_connector.c
+ delete mode 100644 drivers/gpu/drm/udl/udl_connector.h
+
+diff --git a/drivers/gpu/drm/udl/Makefile b/drivers/gpu/drm/udl/Makefile
+index 24d61f61d7db2..3f6db179455d1 100644
+--- a/drivers/gpu/drm/udl/Makefile
++++ b/drivers/gpu/drm/udl/Makefile
+@@ -1,4 +1,4 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+-udl-y := udl_drv.o udl_modeset.o udl_connector.o udl_main.o udl_transfer.o
++udl-y := udl_drv.o udl_modeset.o udl_main.o udl_transfer.o
+ obj-$(CONFIG_DRM_UDL) := udl.o
+diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
+deleted file mode 100644
+index 538b47ffa67fa..0000000000000
+--- a/drivers/gpu/drm/udl/udl_connector.c
++++ /dev/null
+@@ -1,132 +0,0 @@
+-// SPDX-License-Identifier: GPL-2.0-only
+-/*
+- * Copyright (C) 2012 Red Hat
+- * based in parts on udlfb.c:
+- * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
+- * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
+- * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
+- */
+-
+-#include <drm/drm_atomic_state_helper.h>
+-#include <drm/drm_edid.h>
+-#include <drm/drm_crtc_helper.h>
+-#include <drm/drm_probe_helper.h>
+-
+-#include "udl_connector.h"
+-#include "udl_drv.h"
+-
+-static int udl_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
+-{
+-      struct udl_device *udl = data;
+-      struct drm_device *dev = &udl->drm;
+-      struct usb_device *udev = udl_to_usb_device(udl);
+-      u8 *read_buff;
+-      int ret;
+-      size_t i;
+-
+-      read_buff = kmalloc(2, GFP_KERNEL);
+-      if (!read_buff)
+-              return -ENOMEM;
+-
+-      for (i = 0; i < len; i++) {
+-              int bval = (i + block * EDID_LENGTH) << 8;
+-
+-              ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+-                                    0x02, (0x80 | (0x02 << 5)), bval,
+-                                    0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT);
+-              if (ret < 0) {
+-                      drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret);
+-                      goto err_kfree;
+-              } else if (ret < 1) {
+-                      ret = -EIO;
+-                      drm_err(dev, "Read EDID byte %zu failed\n", i);
+-                      goto err_kfree;
+-              }
+-
+-              buf[i] = read_buff[1];
+-      }
+-
+-      kfree(read_buff);
+-
+-      return 0;
+-
+-err_kfree:
+-      kfree(read_buff);
+-      return ret;
+-}
+-
+-static int udl_connector_helper_get_modes(struct drm_connector *connector)
+-{
+-      struct udl_connector *udl_connector = to_udl_connector(connector);
+-
+-      drm_connector_update_edid_property(connector, udl_connector->edid);
+-      if (udl_connector->edid)
+-              return drm_add_edid_modes(connector, udl_connector->edid);
+-
+-      return 0;
+-}
+-
+-static enum drm_connector_status udl_connector_detect(struct drm_connector *connector, bool force)
+-{
+-      struct udl_device *udl = to_udl(connector->dev);
+-      struct udl_connector *udl_connector = to_udl_connector(connector);
+-
+-      /* cleanup previous EDID */
+-      kfree(udl_connector->edid);
+-
+-      udl_connector->edid = drm_do_get_edid(connector, udl_get_edid_block, udl);
+-      if (!udl_connector->edid)
+-              return connector_status_disconnected;
+-
+-      return connector_status_connected;
+-}
+-
+-static void udl_connector_destroy(struct drm_connector *connector)
+-{
+-      struct udl_connector *udl_connector = to_udl_connector(connector);
+-
+-      drm_connector_cleanup(connector);
+-      kfree(udl_connector->edid);
+-      kfree(udl_connector);
+-}
+-
+-static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
+-      .get_modes = udl_connector_helper_get_modes,
+-};
+-
+-static const struct drm_connector_funcs udl_connector_funcs = {
+-      .reset = drm_atomic_helper_connector_reset,
+-      .detect = udl_connector_detect,
+-      .fill_modes = drm_helper_probe_single_connector_modes,
+-      .destroy = udl_connector_destroy,
+-      .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+-      .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+-};
+-
+-struct drm_connector *udl_connector_init(struct drm_device *dev)
+-{
+-      struct udl_connector *udl_connector;
+-      struct drm_connector *connector;
+-      int ret;
+-
+-      udl_connector = kzalloc(sizeof(*udl_connector), GFP_KERNEL);
+-      if (!udl_connector)
+-              return ERR_PTR(-ENOMEM);
+-
+-      connector = &udl_connector->connector;
+-      ret = drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_VGA);
+-      if (ret)
+-              goto err_kfree;
+-
+-      drm_connector_helper_add(connector, &udl_connector_helper_funcs);
+-
+-      connector->polled = DRM_CONNECTOR_POLL_HPD |
+-                          DRM_CONNECTOR_POLL_CONNECT |
+-                          DRM_CONNECTOR_POLL_DISCONNECT;
+-
+-      return connector;
+-
+-err_kfree:
+-      kfree(udl_connector);
+-      return ERR_PTR(ret);
+-}
+diff --git a/drivers/gpu/drm/udl/udl_connector.h b/drivers/gpu/drm/udl/udl_connector.h
+deleted file mode 100644
+index 74ad68fd3cc9f..0000000000000
+--- a/drivers/gpu/drm/udl/udl_connector.h
++++ /dev/null
+@@ -1,21 +0,0 @@
+-#ifndef __UDL_CONNECTOR_H__
+-#define __UDL_CONNECTOR_H__
+-
+-#include <linux/container_of.h>
+-
+-#include <drm/drm_connector.h>
+-
+-struct edid;
+-
+-struct udl_connector {
+-      struct drm_connector connector;
+-      /* last udl_detect edid */
+-      struct edid *edid;
+-};
+-
+-static inline struct udl_connector *to_udl_connector(struct drm_connector *connector)
+-{
+-      return container_of(connector, struct udl_connector, connector);
+-}
+-
+-#endif //__UDL_CONNECTOR_H__
+diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
+index b4cc7cc568c74..d7a3d495f2e7e 100644
+--- a/drivers/gpu/drm/udl/udl_drv.h
++++ b/drivers/gpu/drm/udl/udl_drv.h
+@@ -46,6 +46,17 @@ struct urb_list {
+       size_t size;
+ };
++struct udl_connector {
++      struct drm_connector connector;
++      /* last udl_detect edid */
++      struct edid *edid;
++};
++
++static inline struct udl_connector *to_udl_connector(struct drm_connector *connector)
++{
++      return container_of(connector, struct udl_connector, connector);
++}
++
+ struct udl_device {
+       struct drm_device drm;
+       struct device *dev;
+diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
+index c7adc29a53a18..93e7554e83fa3 100644
+--- a/drivers/gpu/drm/udl/udl_modeset.c
++++ b/drivers/gpu/drm/udl/udl_modeset.c
+@@ -11,11 +11,13 @@
+ #include <drm/drm_atomic_helper.h>
+ #include <drm/drm_crtc_helper.h>
+ #include <drm/drm_damage_helper.h>
++#include <drm/drm_edid.h>
+ #include <drm/drm_fourcc.h>
+ #include <drm/drm_gem_atomic_helper.h>
+ #include <drm/drm_gem_framebuffer_helper.h>
+ #include <drm/drm_gem_shmem_helper.h>
+ #include <drm/drm_modeset_helper_vtables.h>
++#include <drm/drm_probe_helper.h>
+ #include <drm/drm_vblank.h>
+ #include "udl_drv.h"
+@@ -403,6 +405,126 @@ static const struct drm_simple_display_pipe_funcs udl_simple_display_pipe_funcs
+       DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
+ };
++/*
++ * Connector
++ */
++
++static int udl_connector_helper_get_modes(struct drm_connector *connector)
++{
++      struct udl_connector *udl_connector = to_udl_connector(connector);
++
++      drm_connector_update_edid_property(connector, udl_connector->edid);
++      if (udl_connector->edid)
++              return drm_add_edid_modes(connector, udl_connector->edid);
++
++      return 0;
++}
++
++static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
++      .get_modes = udl_connector_helper_get_modes,
++};
++
++static int udl_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
++{
++      struct udl_device *udl = data;
++      struct drm_device *dev = &udl->drm;
++      struct usb_device *udev = udl_to_usb_device(udl);
++      u8 *read_buff;
++      int ret;
++      size_t i;
++
++      read_buff = kmalloc(2, GFP_KERNEL);
++      if (!read_buff)
++              return -ENOMEM;
++
++      for (i = 0; i < len; i++) {
++              int bval = (i + block * EDID_LENGTH) << 8;
++
++              ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
++                                    0x02, (0x80 | (0x02 << 5)), bval,
++                                    0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT);
++              if (ret < 0) {
++                      drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret);
++                      goto err_kfree;
++              } else if (ret < 1) {
++                      ret = -EIO;
++                      drm_err(dev, "Read EDID byte %zu failed\n", i);
++                      goto err_kfree;
++              }
++
++              buf[i] = read_buff[1];
++      }
++
++      kfree(read_buff);
++
++      return 0;
++
++err_kfree:
++      kfree(read_buff);
++      return ret;
++}
++
++static enum drm_connector_status udl_connector_detect(struct drm_connector *connector, bool force)
++{
++      struct udl_device *udl = to_udl(connector->dev);
++      struct udl_connector *udl_connector = to_udl_connector(connector);
++
++      /* cleanup previous EDID */
++      kfree(udl_connector->edid);
++
++      udl_connector->edid = drm_do_get_edid(connector, udl_get_edid_block, udl);
++      if (!udl_connector->edid)
++              return connector_status_disconnected;
++
++      return connector_status_connected;
++}
++
++static void udl_connector_destroy(struct drm_connector *connector)
++{
++      struct udl_connector *udl_connector = to_udl_connector(connector);
++
++      drm_connector_cleanup(connector);
++      kfree(udl_connector->edid);
++      kfree(udl_connector);
++}
++
++static const struct drm_connector_funcs udl_connector_funcs = {
++      .reset = drm_atomic_helper_connector_reset,
++      .detect = udl_connector_detect,
++      .fill_modes = drm_helper_probe_single_connector_modes,
++      .destroy = udl_connector_destroy,
++      .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
++      .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
++};
++
++struct drm_connector *udl_connector_init(struct drm_device *dev)
++{
++      struct udl_connector *udl_connector;
++      struct drm_connector *connector;
++      int ret;
++
++      udl_connector = kzalloc(sizeof(*udl_connector), GFP_KERNEL);
++      if (!udl_connector)
++              return ERR_PTR(-ENOMEM);
++
++      connector = &udl_connector->connector;
++      ret = drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_VGA);
++      if (ret)
++              goto err_kfree;
++
++      drm_connector_helper_add(connector, &udl_connector_helper_funcs);
++
++      connector->polled = DRM_CONNECTOR_POLL_HPD |
++                          DRM_CONNECTOR_POLL_CONNECT |
++                          DRM_CONNECTOR_POLL_DISCONNECT;
++
++      return connector;
++
++err_kfree:
++      kfree(udl_connector);
++      return ERR_PTR(ret);
++}
++
+ /*
+  * Modesetting
+  */
+-- 
+2.43.0
+
diff --git a/queue-6.1/drm-udl-remove-drm_connector_poll_hpd.patch b/queue-6.1/drm-udl-remove-drm_connector_poll_hpd.patch
new file mode 100644 (file)
index 0000000..07b2ed3
--- /dev/null
@@ -0,0 +1,46 @@
+From 53090b4c8a0018354e37be6994e8e0e5b068f1d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 May 2024 17:47:08 +0200
+Subject: drm/udl: Remove DRM_CONNECTOR_POLL_HPD
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 5aed213c7c6c4f5dcb1a3ef146f493f18fe703dc ]
+
+DisplayLink devices do not generate hotplug events. Remove the poll
+flag DRM_CONNECTOR_POLL_HPD, as it may not be specified together with
+DRM_CONNECTOR_POLL_CONNECT or DRM_CONNECTOR_POLL_DISCONNECT.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Fixes: afdfc4c6f55f ("drm/udl: Fixed problem with UDL adpater reconnection")
+Reviewed-by: Jani Nikula <jani.nikula@intel.com>
+Cc: Robert Tarasov <tutankhamen@chromium.org>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: Dave Airlie <airlied@redhat.com>
+Cc: Sean Paul <sean@poorly.run>
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+Cc: dri-devel@lists.freedesktop.org
+Cc: <stable@vger.kernel.org> # v4.15+
+Link: https://patchwork.freedesktop.org/patch/msgid/20240510154841.11370-2-tzimmermann@suse.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/udl/udl_modeset.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
+index 93e7554e83fa3..8f4c4a857b6e8 100644
+--- a/drivers/gpu/drm/udl/udl_modeset.c
++++ b/drivers/gpu/drm/udl/udl_modeset.c
+@@ -514,8 +514,7 @@ struct drm_connector *udl_connector_init(struct drm_device *dev)
+       drm_connector_helper_add(connector, &udl_connector_helper_funcs);
+-      connector->polled = DRM_CONNECTOR_POLL_HPD |
+-                          DRM_CONNECTOR_POLL_CONNECT |
++      connector->polled = DRM_CONNECTOR_POLL_CONNECT |
+                           DRM_CONNECTOR_POLL_DISCONNECT;
+       return connector;
+-- 
+2.43.0
+
diff --git a/queue-6.1/drm-udl-rename-struct-udl_drm_connector-to-struct-ud.patch b/queue-6.1/drm-udl-rename-struct-udl_drm_connector-to-struct-ud.patch
new file mode 100644 (file)
index 0000000..c3c1aad
--- /dev/null
@@ -0,0 +1,106 @@
+From 1c3b6b1e090363f4bbc4a502cb26ea7a5beb4d5f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Oct 2022 11:53:40 +0200
+Subject: drm/udl: Rename struct udl_drm_connector to struct udl_connector
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 59a811faa74f4326fe2d48d2b334c0ee95922628 ]
+
+Remove the _drm_ infix from struct udl_drm_connector and introduce a
+macro for upcasting from struct drm_connector. No functional changes.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221006095355.23579-2-tzimmermann@suse.de
+Stable-dep-of: 5aed213c7c6c ("drm/udl: Remove DRM_CONNECTOR_POLL_HPD")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/udl/udl_connector.c | 19 +++++--------------
+ drivers/gpu/drm/udl/udl_connector.h | 10 ++++++++--
+ 2 files changed, 13 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
+index fade4c7adbf78..3c80686263848 100644
+--- a/drivers/gpu/drm/udl/udl_connector.c
++++ b/drivers/gpu/drm/udl/udl_connector.c
+@@ -46,10 +46,7 @@ static int udl_get_edid_block(void *data, u8 *buf, unsigned int block,
+ static int udl_get_modes(struct drm_connector *connector)
+ {
+-      struct udl_drm_connector *udl_connector =
+-                                      container_of(connector,
+-                                      struct udl_drm_connector,
+-                                      connector);
++      struct udl_connector *udl_connector = to_udl_connector(connector);
+       drm_connector_update_edid_property(connector, udl_connector->edid);
+       if (udl_connector->edid)
+@@ -74,10 +71,7 @@ static enum drm_connector_status
+ udl_detect(struct drm_connector *connector, bool force)
+ {
+       struct udl_device *udl = to_udl(connector->dev);
+-      struct udl_drm_connector *udl_connector =
+-                                      container_of(connector,
+-                                      struct udl_drm_connector,
+-                                      connector);
++      struct udl_connector *udl_connector = to_udl_connector(connector);
+       /* cleanup previous edid */
+       if (udl_connector->edid != NULL) {
+@@ -94,10 +88,7 @@ udl_detect(struct drm_connector *connector, bool force)
+ static void udl_connector_destroy(struct drm_connector *connector)
+ {
+-      struct udl_drm_connector *udl_connector =
+-                                      container_of(connector,
+-                                      struct udl_drm_connector,
+-                                      connector);
++      struct udl_connector *udl_connector = to_udl_connector(connector);
+       drm_connector_cleanup(connector);
+       kfree(udl_connector->edid);
+@@ -120,10 +111,10 @@ static const struct drm_connector_funcs udl_connector_funcs = {
+ struct drm_connector *udl_connector_init(struct drm_device *dev)
+ {
+-      struct udl_drm_connector *udl_connector;
++      struct udl_connector *udl_connector;
+       struct drm_connector *connector;
+-      udl_connector = kzalloc(sizeof(struct udl_drm_connector), GFP_KERNEL);
++      udl_connector = kzalloc(sizeof(*udl_connector), GFP_KERNEL);
+       if (!udl_connector)
+               return ERR_PTR(-ENOMEM);
+diff --git a/drivers/gpu/drm/udl/udl_connector.h b/drivers/gpu/drm/udl/udl_connector.h
+index 7f2d392df1737..74ad68fd3cc9f 100644
+--- a/drivers/gpu/drm/udl/udl_connector.h
++++ b/drivers/gpu/drm/udl/udl_connector.h
+@@ -1,15 +1,21 @@
+ #ifndef __UDL_CONNECTOR_H__
+ #define __UDL_CONNECTOR_H__
+-#include <drm/drm_crtc.h>
++#include <linux/container_of.h>
++
++#include <drm/drm_connector.h>
+ struct edid;
+-struct udl_drm_connector {
++struct udl_connector {
+       struct drm_connector connector;
+       /* last udl_detect edid */
+       struct edid *edid;
+ };
++static inline struct udl_connector *to_udl_connector(struct drm_connector *connector)
++{
++      return container_of(connector, struct udl_connector, connector);
++}
+ #endif //__UDL_CONNECTOR_H__
+-- 
+2.43.0
+
diff --git a/queue-6.1/drm-udl-test-pixel-limit-in-mode-config-s-mode-valid.patch b/queue-6.1/drm-udl-test-pixel-limit-in-mode-config-s-mode-valid.patch
new file mode 100644 (file)
index 0000000..a23e4b2
--- /dev/null
@@ -0,0 +1,85 @@
+From 7ba5f10fd34a5b341e456b032811a03fa512cf91 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Oct 2022 11:53:41 +0200
+Subject: drm/udl: Test pixel limit in mode-config's mode-valid function
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit c020f66013b6136a68a3a4ad74cc7af3b3310586 ]
+
+The sku_pixel_limit is a per-device property, similar to the amount
+of available video memory. Move the respective mode-valid test from
+the connector to the mode-config structure.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221006095355.23579-3-tzimmermann@suse.de
+Stable-dep-of: 5aed213c7c6c ("drm/udl: Remove DRM_CONNECTOR_POLL_HPD")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/udl/udl_connector.c | 14 --------------
+ drivers/gpu/drm/udl/udl_modeset.c   | 14 ++++++++++++++
+ 2 files changed, 14 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
+index 3c80686263848..e9539829032c5 100644
+--- a/drivers/gpu/drm/udl/udl_connector.c
++++ b/drivers/gpu/drm/udl/udl_connector.c
+@@ -54,19 +54,6 @@ static int udl_get_modes(struct drm_connector *connector)
+       return 0;
+ }
+-static enum drm_mode_status udl_mode_valid(struct drm_connector *connector,
+-                        struct drm_display_mode *mode)
+-{
+-      struct udl_device *udl = to_udl(connector->dev);
+-      if (!udl->sku_pixel_limit)
+-              return 0;
+-
+-      if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit)
+-              return MODE_VIRTUAL_Y;
+-
+-      return 0;
+-}
+-
+ static enum drm_connector_status
+ udl_detect(struct drm_connector *connector, bool force)
+ {
+@@ -97,7 +84,6 @@ static void udl_connector_destroy(struct drm_connector *connector)
+ static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
+       .get_modes = udl_get_modes,
+-      .mode_valid = udl_mode_valid,
+ };
+ static const struct drm_connector_funcs udl_connector_funcs = {
+diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
+index ec6876f449f31..c7adc29a53a18 100644
+--- a/drivers/gpu/drm/udl/udl_modeset.c
++++ b/drivers/gpu/drm/udl/udl_modeset.c
+@@ -407,8 +407,22 @@ static const struct drm_simple_display_pipe_funcs udl_simple_display_pipe_funcs
+  * Modesetting
+  */
++static enum drm_mode_status udl_mode_config_mode_valid(struct drm_device *dev,
++                                                     const struct drm_display_mode *mode)
++{
++      struct udl_device *udl = to_udl(dev);
++
++      if (udl->sku_pixel_limit) {
++              if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit)
++                      return MODE_MEM;
++      }
++
++      return MODE_OK;
++}
++
+ static const struct drm_mode_config_funcs udl_mode_funcs = {
+       .fb_create = drm_gem_fb_create_with_dirty,
++      .mode_valid = udl_mode_config_mode_valid,
+       .atomic_check  = drm_atomic_helper_check,
+       .atomic_commit = drm_atomic_helper_commit,
+ };
+-- 
+2.43.0
+
diff --git a/queue-6.1/drm-udl-use-usb-timeout-constant-when-reading-edid.patch b/queue-6.1/drm-udl-use-usb-timeout-constant-when-reading-edid.patch
new file mode 100644 (file)
index 0000000..184d50d
--- /dev/null
@@ -0,0 +1,38 @@
+From a78979d508a4b80aeff706b3926df0d0679fa414 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Oct 2022 11:53:42 +0200
+Subject: drm/udl: Use USB timeout constant when reading EDID
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 2c1eafc40e53312864bf2fdccb55052dcbd9e8b2 ]
+
+Set the USB control-message timeout to the USB default of 5 seconds.
+Done for consistency with other uses of usb_control_msg() in udl and
+other drivers.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221006095355.23579-4-tzimmermann@suse.de
+Stable-dep-of: 5aed213c7c6c ("drm/udl: Remove DRM_CONNECTOR_POLL_HPD")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/udl/udl_connector.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
+index e9539829032c5..cb3d6820eaf93 100644
+--- a/drivers/gpu/drm/udl/udl_connector.c
++++ b/drivers/gpu/drm/udl/udl_connector.c
+@@ -31,7 +31,7 @@ static int udl_get_edid_block(void *data, u8 *buf, unsigned int block,
+               int bval = (i + block * EDID_LENGTH) << 8;
+               ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                                     0x02, (0x80 | (0x02 << 5)), bval,
+-                                    0xA1, read_buff, 2, 1000);
++                                    0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT);
+               if (ret < 1) {
+                       DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret);
+                       kfree(read_buff);
+-- 
+2.43.0
+
diff --git a/queue-6.1/drm-udl-various-improvements-to-the-connector.patch b/queue-6.1/drm-udl-various-improvements-to-the-connector.patch
new file mode 100644 (file)
index 0000000..217e071
--- /dev/null
@@ -0,0 +1,165 @@
+From a1cdaed90a551dc1873f502cfc77881352d5509b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Oct 2022 11:53:43 +0200
+Subject: drm/udl: Various improvements to the connector
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit 43858eb41e0dde6e48565c13cdabac95b5d9df90 ]
+
+Add style fixes, better error handling and reporting, and minor
+clean-up changes to the connector code before moving the code to
+the rest of the modesetting pipeline.
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221006095355.23579-5-tzimmermann@suse.de
+Stable-dep-of: 5aed213c7c6c ("drm/udl: Remove DRM_CONNECTOR_POLL_HPD")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/udl/udl_connector.c | 64 ++++++++++++++++++-----------
+ 1 file changed, 40 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
+index cb3d6820eaf93..538b47ffa67fa 100644
+--- a/drivers/gpu/drm/udl/udl_connector.c
++++ b/drivers/gpu/drm/udl/udl_connector.c
+@@ -15,56 +15,64 @@
+ #include "udl_connector.h"
+ #include "udl_drv.h"
+-static int udl_get_edid_block(void *data, u8 *buf, unsigned int block,
+-                             size_t len)
++static int udl_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
+ {
+-      int ret, i;
+-      u8 *read_buff;
+       struct udl_device *udl = data;
++      struct drm_device *dev = &udl->drm;
+       struct usb_device *udev = udl_to_usb_device(udl);
++      u8 *read_buff;
++      int ret;
++      size_t i;
+       read_buff = kmalloc(2, GFP_KERNEL);
+       if (!read_buff)
+-              return -1;
++              return -ENOMEM;
+       for (i = 0; i < len; i++) {
+               int bval = (i + block * EDID_LENGTH) << 8;
++
+               ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+                                     0x02, (0x80 | (0x02 << 5)), bval,
+                                     0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT);
+-              if (ret < 1) {
+-                      DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret);
+-                      kfree(read_buff);
+-                      return -1;
++              if (ret < 0) {
++                      drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret);
++                      goto err_kfree;
++              } else if (ret < 1) {
++                      ret = -EIO;
++                      drm_err(dev, "Read EDID byte %zu failed\n", i);
++                      goto err_kfree;
+               }
++
+               buf[i] = read_buff[1];
+       }
+       kfree(read_buff);
++
+       return 0;
++
++err_kfree:
++      kfree(read_buff);
++      return ret;
+ }
+-static int udl_get_modes(struct drm_connector *connector)
++static int udl_connector_helper_get_modes(struct drm_connector *connector)
+ {
+       struct udl_connector *udl_connector = to_udl_connector(connector);
+       drm_connector_update_edid_property(connector, udl_connector->edid);
+       if (udl_connector->edid)
+               return drm_add_edid_modes(connector, udl_connector->edid);
++
+       return 0;
+ }
+-static enum drm_connector_status
+-udl_detect(struct drm_connector *connector, bool force)
++static enum drm_connector_status udl_connector_detect(struct drm_connector *connector, bool force)
+ {
+       struct udl_device *udl = to_udl(connector->dev);
+       struct udl_connector *udl_connector = to_udl_connector(connector);
+-      /* cleanup previous edid */
+-      if (udl_connector->edid != NULL) {
+-              kfree(udl_connector->edid);
+-              udl_connector->edid = NULL;
+-      }
++      /* cleanup previous EDID */
++      kfree(udl_connector->edid);
+       udl_connector->edid = drm_do_get_edid(connector, udl_get_edid_block, udl);
+       if (!udl_connector->edid)
+@@ -79,38 +87,46 @@ static void udl_connector_destroy(struct drm_connector *connector)
+       drm_connector_cleanup(connector);
+       kfree(udl_connector->edid);
+-      kfree(connector);
++      kfree(udl_connector);
+ }
+ static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
+-      .get_modes = udl_get_modes,
++      .get_modes = udl_connector_helper_get_modes,
+ };
+ static const struct drm_connector_funcs udl_connector_funcs = {
+       .reset = drm_atomic_helper_connector_reset,
+-      .detect = udl_detect,
++      .detect = udl_connector_detect,
+       .fill_modes = drm_helper_probe_single_connector_modes,
+       .destroy = udl_connector_destroy,
+       .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+-      .atomic_destroy_state   = drm_atomic_helper_connector_destroy_state,
++      .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+ };
+ struct drm_connector *udl_connector_init(struct drm_device *dev)
+ {
+       struct udl_connector *udl_connector;
+       struct drm_connector *connector;
++      int ret;
+       udl_connector = kzalloc(sizeof(*udl_connector), GFP_KERNEL);
+       if (!udl_connector)
+               return ERR_PTR(-ENOMEM);
+       connector = &udl_connector->connector;
+-      drm_connector_init(dev, connector, &udl_connector_funcs,
+-                         DRM_MODE_CONNECTOR_VGA);
++      ret = drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_VGA);
++      if (ret)
++              goto err_kfree;
++
+       drm_connector_helper_add(connector, &udl_connector_helper_funcs);
+       connector->polled = DRM_CONNECTOR_POLL_HPD |
+-              DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
++                          DRM_CONNECTOR_POLL_CONNECT |
++                          DRM_CONNECTOR_POLL_DISCONNECT;
+       return connector;
++
++err_kfree:
++      kfree(udl_connector);
++      return ERR_PTR(ret);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.1/ext4-check-the-extent-status-again-before-inserting-.patch b/queue-6.1/ext4-check-the-extent-status-again-before-inserting-.patch
new file mode 100644 (file)
index 0000000..d907e0c
--- /dev/null
@@ -0,0 +1,100 @@
+From a09d8dcb497ba74e761a0f0fcd8302c03a61ea1c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 May 2024 20:39:57 +0800
+Subject: ext4: check the extent status again before inserting delalloc block
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ Upstream commit 0ea6560abb3bac1ffcfa4bf6b2c4d344fdc27b3c ]
+
+ext4_da_map_blocks looks up for any extent entry in the extent status
+tree (w/o i_data_sem) and then the looks up for any ondisk extent
+mapping (with i_data_sem in read mode).
+
+If it finds a hole in the extent status tree or if it couldn't find any
+entry at all, it then takes the i_data_sem in write mode to add a da
+entry into the extent status tree. This can actually race with page
+mkwrite & fallocate path.
+
+Note that this is ok between
+1. ext4 buffered-write path v/s ext4_page_mkwrite(), because of the
+   folio lock
+2. ext4 buffered write path v/s ext4 fallocate because of the inode
+   lock.
+
+But this can race between ext4_page_mkwrite() & ext4 fallocate path
+
+ext4_page_mkwrite()             ext4_fallocate()
+ block_page_mkwrite()
+  ext4_da_map_blocks()
+   //find hole in extent status tree
+                                 ext4_alloc_file_blocks()
+                                  ext4_map_blocks()
+                                   //allocate block and unwritten extent
+   ext4_insert_delayed_block()
+    ext4_da_reserve_space()
+     //reserve one more block
+    ext4_es_insert_delayed_block()
+     //drop unwritten extent and add delayed extent by mistake
+
+Then, the delalloc extent is wrong until writeback and the extra
+reserved block can't be released any more and it triggers below warning:
+
+ EXT4-fs (pmem2): Inode 13 (00000000bbbd4d23): i_reserved_data_blocks(1) not cleared!
+
+Fix the problem by looking up extent status tree again while the
+i_data_sem is held in write mode. If it still can't find any entry, then
+we insert a new da entry into the extent status tree.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20240517124005.347221-3-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index a0c6a173c14d5..93a1c22048de6 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1772,6 +1772,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.
+@@ -1816,6 +1817,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.1/ext4-convert-to-exclusive-lock-while-inserting-delal.patch b/queue-6.1/ext4-convert-to-exclusive-lock-while-inserting-delal.patch
new file mode 100644 (file)
index 0000000..847e02e
--- /dev/null
@@ -0,0 +1,114 @@
+From f55733e3df97e5c9a292b773ac397145d03c3eac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 27 Jan 2024 09:58:01 +0800
+Subject: ext4: convert to exclusive lock while inserting delalloc extents
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ Upstream commit acf795dc161f3cf481db20f05db4250714e375e5 ]
+
+ext4_da_map_blocks() only hold i_data_sem in shared mode and i_rwsem
+when inserting delalloc extents, it could be raced by another querying
+path of ext4_map_blocks() without i_rwsem, .e.g buffered read path.
+Suppose we buffered read a file containing just a hole, and without any
+cached extents tree, then it is raced by another delayed buffered write
+to the same area or the near area belongs to the same hole, and the new
+delalloc extent could be overwritten to a hole extent.
+
+ pread()                           pwrite()
+  filemap_read_folio()
+   ext4_mpage_readpages()
+    ext4_map_blocks()
+     down_read(i_data_sem)
+     ext4_ext_determine_hole()
+     //find hole
+     ext4_ext_put_gap_in_cache()
+      ext4_es_find_extent_range()
+      //no delalloc extent
+                                    ext4_da_map_blocks()
+                                     down_read(i_data_sem)
+                                     ext4_insert_delayed_block()
+                                     //insert delalloc extent
+      ext4_es_insert_extent()
+      //overwrite delalloc extent to hole
+
+This race could lead to inconsistent delalloc extents tree and
+incorrect reserved space counter. Fix this by converting to hold
+i_data_sem in exclusive mode when adding a new delalloc extent in
+ext4_da_map_blocks().
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Suggested-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20240127015825.1608160-3-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 0ea6560abb3b ("ext4: check the extent status again before inserting delalloc block")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 25 +++++++++++--------------
+ 1 file changed, 11 insertions(+), 14 deletions(-)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index eab9aefe96ce6..d6f7525a796c0 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1740,10 +1740,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.
+@@ -1785,8 +1783,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;
+@@ -1802,24 +1802,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.1/ext4-factor-out-a-common-helper-to-query-extent-map.patch b/queue-6.1/ext4-factor-out-a-common-helper-to-query-extent-map.patch
new file mode 100644 (file)
index 0000000..0e1e7ba
--- /dev/null
@@ -0,0 +1,104 @@
+From 4a85c2032f2e5bd2d1f148f2402c8b292bf50cc0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 May 2024 20:39:56 +0800
+Subject: ext4: factor out a common helper to query extent map
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ Upstream commit 8e4e5cdf2fdeb99445a468b6b6436ad79b9ecb30 ]
+
+Factor out a new common helper ext4_map_query_blocks() from the
+ext4_da_map_blocks(), it query and return the extent map status on the
+inode's extent path, no logic changes.
+
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Link: https://patch.msgid.link/20240517124005.347221-2-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 0ea6560abb3b ("ext4: check the extent status again before inserting delalloc block")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 57 +++++++++++++++++++++++++++----------------------
+ 1 file changed, 32 insertions(+), 25 deletions(-)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index d6f7525a796c0..a0c6a173c14d5 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -481,6 +481,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.
+@@ -1779,33 +1808,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.1/ext4-make-ext4_es_insert_extent-return-void.patch b/queue-6.1/ext4-make-ext4_es_insert_extent-return-void.patch
new file mode 100644 (file)
index 0000000..dcc967d
--- /dev/null
@@ -0,0 +1,158 @@
+From 728bbdc362f8b07fa57ca604320666f97bd67026 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Apr 2023 11:38:45 +0800
+Subject: ext4: make ext4_es_insert_extent() return void
+
+From: Baokun Li <libaokun1@huawei.com>
+
+[ Upstream commit 6c120399cde6b1b5cf65ce403765c579fb3d3e50 ]
+
+Now ext4_es_insert_extent() never return error, so make it return void.
+
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20230424033846.4732-12-libaokun1@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 0ea6560abb3b ("ext4: check the extent status again before inserting delalloc block")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/extents.c        |  5 +++--
+ fs/ext4/extents_status.c | 14 ++++++--------
+ fs/ext4/extents_status.h |  6 +++---
+ fs/ext4/inode.c          | 21 ++++++---------------
+ 4 files changed, 18 insertions(+), 28 deletions(-)
+
+diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
+index 67af684e44e6e..5cbe5ae5ad4a2 100644
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -3113,8 +3113,9 @@ static int ext4_zeroout_es(struct inode *inode, struct ext4_extent *ex)
+       if (ee_len == 0)
+               return 0;
+-      return ext4_es_insert_extent(inode, ee_block, ee_len, ee_pblock,
+-                                   EXTENT_STATUS_WRITTEN);
++      ext4_es_insert_extent(inode, ee_block, ee_len, ee_pblock,
++                            EXTENT_STATUS_WRITTEN);
++      return 0;
+ }
+ /* FIXME!! we need to try to merge to left or right after zero-out  */
+diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
+index 9766d3b21ca2e..592229027af72 100644
+--- a/fs/ext4/extents_status.c
++++ b/fs/ext4/extents_status.c
+@@ -847,12 +847,10 @@ static int __es_insert_extent(struct inode *inode, struct extent_status *newes,
+ /*
+  * ext4_es_insert_extent() adds information to an inode's extent
+  * status tree.
+- *
+- * Return 0 on success, error code on failure.
+  */
+-int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
+-                        ext4_lblk_t len, ext4_fsblk_t pblk,
+-                        unsigned int status)
++void ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
++                         ext4_lblk_t len, ext4_fsblk_t pblk,
++                         unsigned int status)
+ {
+       struct extent_status newes;
+       ext4_lblk_t end = lblk + len - 1;
+@@ -864,13 +862,13 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
+       bool revise_pending = false;
+       if (EXT4_SB(inode->i_sb)->s_mount_state & EXT4_FC_REPLAY)
+-              return 0;
++              return;
+       es_debug("add [%u/%u) %llu %x to extent status tree of inode %lu\n",
+                lblk, len, pblk, status, inode->i_ino);
+       if (!len)
+-              return 0;
++              return;
+       BUG_ON(end < lblk);
+@@ -939,7 +937,7 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
+               goto retry;
+       ext4_es_print_tree(inode);
+-      return 0;
++      return;
+ }
+ /*
+diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h
+index 4ec30a7982605..481ec4381bee6 100644
+--- a/fs/ext4/extents_status.h
++++ b/fs/ext4/extents_status.h
+@@ -127,9 +127,9 @@ extern int __init ext4_init_es(void);
+ extern void ext4_exit_es(void);
+ extern void ext4_es_init_tree(struct ext4_es_tree *tree);
+-extern int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
+-                               ext4_lblk_t len, ext4_fsblk_t pblk,
+-                               unsigned int status);
++extern void ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
++                                ext4_lblk_t len, ext4_fsblk_t pblk,
++                                unsigned int status);
+ extern void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk,
+                                ext4_lblk_t len, ext4_fsblk_t pblk,
+                                unsigned int status);
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 2479508deab3b..6dc15ad45ac95 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -595,10 +595,8 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+                   ext4_es_scan_range(inode, &ext4_es_is_delayed, map->m_lblk,
+                                      map->m_lblk + map->m_len - 1))
+                       status |= EXTENT_STATUS_DELAYED;
+-              ret = ext4_es_insert_extent(inode, map->m_lblk,
+-                                          map->m_len, map->m_pblk, status);
+-              if (ret < 0)
+-                      retval = ret;
++              ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
++                                    map->m_pblk, status);
+       }
+       up_read((&EXT4_I(inode)->i_data_sem));
+@@ -707,12 +705,8 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
+                   ext4_es_scan_range(inode, &ext4_es_is_delayed, map->m_lblk,
+                                      map->m_lblk + map->m_len - 1))
+                       status |= EXTENT_STATUS_DELAYED;
+-              ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
+-                                          map->m_pblk, status);
+-              if (ret < 0) {
+-                      retval = ret;
+-                      goto out_sem;
+-              }
++              ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
++                                    map->m_pblk, status);
+       }
+ out_sem:
+@@ -1812,7 +1806,6 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+               set_buffer_new(bh);
+               set_buffer_delay(bh);
+       } else if (retval > 0) {
+-              int ret;
+               unsigned int status;
+               if (unlikely(retval != map->m_len)) {
+@@ -1825,10 +1818,8 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
+               status = map->m_flags & EXT4_MAP_UNWRITTEN ?
+                               EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
+-              ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
+-                                          map->m_pblk, status);
+-              if (ret != 0)
+-                      retval = ret;
++              ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
++                                    map->m_pblk, status);
+       }
+ out_unlock:
+-- 
+2.43.0
+
diff --git a/queue-6.1/ext4-refactor-ext4_da_map_blocks.patch b/queue-6.1/ext4-refactor-ext4_da_map_blocks.patch
new file mode 100644 (file)
index 0000000..5ca8a01
--- /dev/null
@@ -0,0 +1,93 @@
+From aa2b2a1a2af2ae7add3b722840ccf9f8ef50d833 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 27 Jan 2024 09:58:00 +0800
+Subject: ext4: refactor ext4_da_map_blocks()
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ Upstream commit 3fcc2b887a1ba4c1f45319cd8c54daa263ecbc36 ]
+
+Refactor and cleanup ext4_da_map_blocks(), reduce some unnecessary
+parameters and branches, no logic changes.
+
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20240127015825.1608160-2-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 0ea6560abb3b ("ext4: check the extent status again before inserting delalloc block")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c | 39 +++++++++++++++++----------------------
+ 1 file changed, 17 insertions(+), 22 deletions(-)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 6dc15ad45ac95..eab9aefe96ce6 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1741,7 +1741,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;
+               }
+@@ -1786,26 +1785,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)) {
+@@ -1820,11 +1802,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.1/f2fs-assign-curseg_all_data_atgc-if-blkaddr-is-valid.patch b/queue-6.1/f2fs-assign-curseg_all_data_atgc-if-blkaddr-is-valid.patch
new file mode 100644 (file)
index 0000000..2e81c25
--- /dev/null
@@ -0,0 +1,59 @@
+From 6cea387d3292b7c667433802f34b3048962453f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Jun 2024 02:15:38 +0000
+Subject: f2fs: assign CURSEG_ALL_DATA_ATGC if blkaddr is valid
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+[ Upstream commit 8cb1f4080dd91c6e6b01dbea013a3f42341cb6a1 ]
+
+mkdir /mnt/test/comp
+f2fs_io setflags compression /mnt/test/comp
+dd if=/dev/zero of=/mnt/test/comp/testfile bs=16k count=1
+truncate --size 13 /mnt/test/comp/testfile
+
+In the above scenario, we can get a BUG_ON.
+ kernel BUG at fs/f2fs/segment.c:3589!
+ Call Trace:
+  do_write_page+0x78/0x390 [f2fs]
+  f2fs_outplace_write_data+0x62/0xb0 [f2fs]
+  f2fs_do_write_data_page+0x275/0x740 [f2fs]
+  f2fs_write_single_data_page+0x1dc/0x8f0 [f2fs]
+  f2fs_write_multi_pages+0x1e5/0xae0 [f2fs]
+  f2fs_write_cache_pages+0xab1/0xc60 [f2fs]
+  f2fs_write_data_pages+0x2d8/0x330 [f2fs]
+  do_writepages+0xcf/0x270
+  __writeback_single_inode+0x44/0x350
+  writeback_sb_inodes+0x242/0x530
+  __writeback_inodes_wb+0x54/0xf0
+  wb_writeback+0x192/0x310
+  wb_workfn+0x30d/0x400
+
+The reason is we gave CURSEG_ALL_DATA_ATGC to COMPR_ADDR where the
+page was set the gcing flag by set_cluster_dirty().
+
+Cc: stable@vger.kernel.org
+Fixes: 4961acdd65c9 ("f2fs: fix to tag gcing flag on page during block migration")
+Reviewed-by: Chao Yu <chao@kernel.org>
+Tested-by: Will McVicker <willmcvicker@google.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/segment.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+index 99391ee4c28c4..1264a350d4d75 100644
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -3186,6 +3186,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.1/f2fs-fix-to-avoid-use-ssr-allocate-when-do-defragmen.patch b/queue-6.1/f2fs-fix-to-avoid-use-ssr-allocate-when-do-defragmen.patch
new file mode 100644 (file)
index 0000000..02f1249
--- /dev/null
@@ -0,0 +1,75 @@
+From cc6b3e97782c5daa2869dbeacceea26aad4a6b6e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 May 2024 17:47:00 +0800
+Subject: f2fs: fix to avoid use SSR allocate when do defragment
+
+From: Zhiguo Niu <zhiguo.niu@unisoc.com>
+
+[ Upstream commit 21327a042dd94bc73181d7300e688699cb1f467e ]
+
+SSR allocate mode will be used when doing file defragment
+if ATGC is working at the same time, that is because
+set_page_private_gcing may make CURSEG_ALL_DATA_ATGC segment
+type got in f2fs_allocate_data_block when defragment page
+is writeback, which may cause file fragmentation is worse.
+
+A file with 2 fragmentations is changed as following after defragment:
+
+----------------file info-------------------
+sensorsdata :
+--------------------------------------------
+dev       [254:48]
+ino       [0x    3029 : 12329]
+mode      [0x    81b0 : 33200]
+nlink     [0x       1 : 1]
+uid       [0x    27e6 : 10214]
+gid       [0x    27e6 : 10214]
+size      [0x  242000 : 2367488]
+blksize   [0x    1000 : 4096]
+blocks    [0x    1210 : 4624]
+--------------------------------------------
+
+file_pos   start_blk     end_blk        blks
+       0    11361121    11361207          87
+  356352    11361215    11361216           2
+  364544    11361218    11361218           1
+  368640    11361220    11361221           2
+  376832    11361224    11361225           2
+  385024    11361227    11361238          12
+  434176    11361240    11361252          13
+  487424    11361254    11361254           1
+  491520    11361271    11361279           9
+  528384     3681794     3681795           2
+  536576     3681797     3681797           1
+  540672     3681799     3681799           1
+  544768     3681803     3681803           1
+  548864     3681805     3681805           1
+  552960     3681807     3681807           1
+  557056     3681809     3681809           1
+
+Signed-off-by: Zhiguo Niu <zhiguo.niu@unisoc.com>
+Reviewed-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Stable-dep-of: 8cb1f4080dd9 ("f2fs: assign CURSEG_ALL_DATA_ATGC if blkaddr is valid")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/segment.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
+index e19b569d938d8..99391ee4c28c4 100644
+--- a/fs/f2fs/segment.c
++++ b/fs/f2fs/segment.c
+@@ -3185,7 +3185,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.1/irqdomain-fixed-unbalanced-fwnode-get-and-put.patch b/queue-6.1/irqdomain-fixed-unbalanced-fwnode-get-and-put.patch
new file mode 100644 (file)
index 0000000..0faceee
--- /dev/null
@@ -0,0 +1,70 @@
+From 86149a873868c55caf9575063b939c46b3ebea0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 19:32:04 +0200
+Subject: irqdomain: Fixed unbalanced fwnode get and put
+
+From: Herve Codina <herve.codina@bootlin.com>
+
+[ Upstream commit 6ce3e98184b625d2870991880bf9586ded7ea7f9 ]
+
+fwnode_handle_get(fwnode) is called when a domain is created with fwnode
+passed as a function parameter. fwnode_handle_put(domain->fwnode) is called
+when the domain is destroyed but during the creation a path exists that
+does not set domain->fwnode.
+
+If this path is taken, the fwnode get will never be put.
+
+To avoid the unbalanced get and put, set domain->fwnode unconditionally.
+
+Fixes: d59f6617eef0 ("genirq: Allow fwnode to carry name information only")
+Signed-off-by: Herve Codina <herve.codina@bootlin.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20240614173232.1184015-4-herve.codina@bootlin.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/irq/irqdomain.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index e03baca901e76..b1ed088b23640 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -154,7 +154,6 @@ static struct irq_domain *__irq_domain_create(struct fwnode_handle *fwnode,
+               switch (fwid->type) {
+               case IRQCHIP_FWNODE_NAMED:
+               case IRQCHIP_FWNODE_NAMED_ID:
+-                      domain->fwnode = fwnode;
+                       domain->name = kstrdup(fwid->name, GFP_KERNEL);
+                       if (!domain->name) {
+                               kfree(domain);
+@@ -163,7 +162,6 @@ static struct irq_domain *__irq_domain_create(struct fwnode_handle *fwnode,
+                       domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;
+                       break;
+               default:
+-                      domain->fwnode = fwnode;
+                       domain->name = fwid->name;
+                       break;
+               }
+@@ -183,7 +181,6 @@ static struct irq_domain *__irq_domain_create(struct fwnode_handle *fwnode,
+               }
+               domain->name = strreplace(name, '/', ':');
+-              domain->fwnode = fwnode;
+               domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;
+       }
+@@ -199,8 +196,8 @@ static struct irq_domain *__irq_domain_create(struct fwnode_handle *fwnode,
+               domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;
+       }
+-      fwnode_handle_get(fwnode);
+-      fwnode_dev_initialized(fwnode, true);
++      domain->fwnode = fwnode_handle_get(fwnode);
++      fwnode_dev_initialized(domain->fwnode, true);
+       /* Fill structure */
+       INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
+-- 
+2.43.0
+
diff --git a/queue-6.1/irqdomain-use-return-value-of-strreplace.patch b/queue-6.1/irqdomain-use-return-value-of-strreplace.patch
new file mode 100644 (file)
index 0000000..2aea896
--- /dev/null
@@ -0,0 +1,39 @@
+From 75d4494abda65fead10f8060be8a200a8960a25f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jun 2023 18:02:51 +0300
+Subject: irqdomain: Use return value of strreplace()
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 67a4e1a3bf7c68ed3fbefc4213648165d912cabb ]
+
+Since strreplace() returns the pointer to the string itself, use it
+directly.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Link: https://lore.kernel.org/r/20230628150251.17832-1-andriy.shevchenko@linux.intel.com
+Stable-dep-of: 6ce3e98184b6 ("irqdomain: Fixed unbalanced fwnode get and put")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/irq/irqdomain.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
+index 607c0c3d3f5e1..e03baca901e76 100644
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -182,9 +182,7 @@ static struct irq_domain *__irq_domain_create(struct fwnode_handle *fwnode,
+                       return NULL;
+               }
+-              strreplace(name, '/', ':');
+-
+-              domain->name = name;
++              domain->name = strreplace(name, '/', ':');
+               domain->fwnode = fwnode;
+               domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.1/leds-trigger-call-synchronize_rcu-before-calling-tri.patch b/queue-6.1/leds-trigger-call-synchronize_rcu-before-calling-tri.patch
new file mode 100644 (file)
index 0000000..d854288
--- /dev/null
@@ -0,0 +1,60 @@
+From 67f293b9da62af08280dbb84887bee012aacd942 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 31 May 2024 14:01:24 +0200
+Subject: leds: trigger: Call synchronize_rcu() before calling trig->activate()
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ Upstream commit b1bbd20f35e19774ea01989320495e09ac44fba3 ]
+
+Some triggers call led_trigger_event() from their activate() callback
+to initialize the brightness of the LED for which the trigger is being
+activated.
+
+In order for the LED's initial state to be set correctly this requires that
+the led_trigger_event() call uses the new version of trigger->led_cdevs,
+which has the new LED.
+
+AFAICT led_trigger_event() will always use the new version when it is
+running on the same CPU as where the list_add_tail_rcu() call was made,
+which is why the missing synchronize_rcu() has not lead to bug reports.
+But if activate() is pre-empted, sleeps or uses a worker then
+the led_trigger_event() call may run on another CPU which may still use
+the old trigger->led_cdevs list.
+
+Add a synchronize_rcu() call to ensure that any led_trigger_event() calls
+done from activate() always use the new list.
+
+Triggers using led_trigger_event() from their activate() callback are:
+net/bluetooth/leds.c, net/rfkill/core.c and drivers/tty/vt/keyboard.c.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20240531120124.75662-1-hdegoede@redhat.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Stable-dep-of: ab477b766edd ("leds: triggers: Flush pending brightness before activating trigger")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/led-triggers.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
+index cdb446cb84af2..fe7fb2e7149c5 100644
+--- a/drivers/leds/led-triggers.c
++++ b/drivers/leds/led-triggers.c
+@@ -193,6 +193,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.1/leds-trigger-remove-unused-function-led_trigger_rena.patch b/queue-6.1/leds-trigger-remove-unused-function-led_trigger_rena.patch
new file mode 100644 (file)
index 0000000..c3f1668
--- /dev/null
@@ -0,0 +1,77 @@
+From a08d090901ca83b148970d6d9a1f9aef60767a7e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Dec 2023 23:56:41 +0100
+Subject: leds: trigger: Remove unused function led_trigger_rename_static()
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit c82a1662d4548c454de5343b88f69b9fc82266b3 ]
+
+This function was added with a8df7b1ab70b ("leds: add led_trigger_rename
+function") 11 yrs ago, but it has no users. So remove it.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/d90f30be-f661-4db7-b0b5-d09d07a78a68@gmail.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Stable-dep-of: ab477b766edd ("leds: triggers: Flush pending brightness before activating trigger")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/led-triggers.c | 13 -------------
+ include/linux/leds.h        | 17 -----------------
+ 2 files changed, 30 deletions(-)
+
+diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
+index 024b73f84ce0c..dddfc301d3414 100644
+--- a/drivers/leds/led-triggers.c
++++ b/drivers/leds/led-triggers.c
+@@ -268,19 +268,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 ba4861ec73d30..2bbff7519b731 100644
+--- a/include/linux/leds.h
++++ b/include/linux/leds.h
+@@ -409,23 +409,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.1/leds-trigger-store-brightness-set-by-led_trigger_eve.patch b/queue-6.1/leds-trigger-store-brightness-set-by-led_trigger_eve.patch
new file mode 100644 (file)
index 0000000..a8e74da
--- /dev/null
@@ -0,0 +1,98 @@
+From c149da8d9db43c4a715739a3d7bb9ecc26af186f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Mar 2024 21:57:30 +0100
+Subject: leds: trigger: Store brightness set by led_trigger_event()
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit 822c91e72eac568ed8d83765634f00decb45666c ]
+
+If a simple trigger is assigned to a LED, then the LED may be off until
+the next led_trigger_event() call. This may be an issue for simple
+triggers with rare led_trigger_event() calls, e.g. power supply
+charging indicators (drivers/power/supply/power_supply_leds.c).
+Therefore persist the brightness value of the last led_trigger_event()
+call and use this value if the trigger is assigned to a LED.
+In addition add a getter for the trigger brightness value.
+
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Takashi Iwai <tiwai@suse.de>
+Link: https://lore.kernel.org/r/b1358b25-3f30-458d-8240-5705ae007a8a@gmail.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Stable-dep-of: ab477b766edd ("leds: triggers: Flush pending brightness before activating trigger")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/led-triggers.c |  6 ++++--
+ include/linux/leds.h        | 15 +++++++++++++++
+ 2 files changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
+index dddfc301d3414..cdb446cb84af2 100644
+--- a/drivers/leds/led-triggers.c
++++ b/drivers/leds/led-triggers.c
+@@ -193,11 +193,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;
+@@ -372,6 +372,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 2bbff7519b731..79ab2dfd3c72f 100644
+--- a/include/linux/leds.h
++++ b/include/linux/leds.h
+@@ -356,6 +356,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;
+@@ -409,6 +412,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)
+@@ -445,6 +454,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 functions */
+-- 
+2.43.0
+
diff --git a/queue-6.1/leds-triggers-flush-pending-brightness-before-activa.patch b/queue-6.1/leds-triggers-flush-pending-brightness-before-activa.patch
new file mode 100644 (file)
index 0000000..e145dc7
--- /dev/null
@@ -0,0 +1,66 @@
+From 798aeb2d5853ac8f89476db89a455f965ee6be6e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Jun 2024 17:24:51 +0200
+Subject: leds: triggers: Flush pending brightness before activating trigger
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit ab477b766edd3bfb6321a6e3df4c790612613fae ]
+
+The race fixed in timer_trig_activate() between a blocking
+set_brightness() call and trigger->activate() can affect any trigger.
+So move the call to flush_work() into led_trigger_set() where it can
+avoid the race for all triggers.
+
+Fixes: 0db37915d912 ("leds: avoid races with workqueue")
+Fixes: 8c0f693c6eff ("leds: avoid flush_work in atomic context")
+Cc: stable@vger.kernel.org
+Tested-by: Dustin L. Howett <dustin@howett.net>
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Link: https://lore.kernel.org/r/20240613-led-trigger-flush-v2-1-f4f970799d77@weissschuh.net
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/leds/led-triggers.c          | 6 ++++++
+ drivers/leds/trigger/ledtrig-timer.c | 5 -----
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
+index fe7fb2e7149c5..3d3673c197e38 100644
+--- a/drivers/leds/led-triggers.c
++++ b/drivers/leds/led-triggers.c
+@@ -200,6 +200,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.1/mips-dts-loongson-fix-liointc-irq-polarity.patch b/queue-6.1/mips-dts-loongson-fix-liointc-irq-polarity.patch
new file mode 100644 (file)
index 0000000..c6085ce
--- /dev/null
@@ -0,0 +1,172 @@
+From 68059f4dafdd45336f5c8e3dc1ea7f65290d1aab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 16:40:10 +0100
+Subject: MIPS: dts: loongson: Fix liointc IRQ polarity
+
+From: Jiaxun Yang <jiaxun.yang@flygoat.com>
+
+[ Upstream commit dbb69b9d6234aad23b3ecd33e5bc8a8ae1485b7d ]
+
+All internal liointc interrupts are high level triggered.
+
+Fixes: b1a792601f26 ("MIPS: Loongson64: DeviceTree for Loongson-2K1000")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../boot/dts/loongson/loongson64-2k1000.dtsi  | 42 +++++++++----------
+ 1 file changed, 21 insertions(+), 21 deletions(-)
+
+diff --git a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+index c1d3092fdd870..eec8243be6499 100644
+--- a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
++++ b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+@@ -100,7 +100,7 @@ rtc0: rtc@1fe07800 {
+                       compatible = "loongson,ls2k1000-rtc";
+                       reg = <0 0x1fe07800 0 0x78>;
+                       interrupt-parent = <&liointc0>;
+-                      interrupts = <60 IRQ_TYPE_LEVEL_LOW>;
++                      interrupts = <60 IRQ_TYPE_LEVEL_HIGH>;
+               };
+               uart0: serial@1fe00000 {
+@@ -108,7 +108,7 @@ uart0: serial@1fe00000 {
+                       reg = <0 0x1fe00000 0 0x8>;
+                       clock-frequency = <125000000>;
+                       interrupt-parent = <&liointc0>;
+-                      interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
++                      interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+                       no-loopback-test;
+               };
+@@ -131,8 +131,8 @@ gmac@3,0 {
+                                                  "pciclass0c03";
+                               reg = <0x1800 0x0 0x0 0x0 0x0>;
+-                              interrupts = <12 IRQ_TYPE_LEVEL_LOW>,
+-                                           <13 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <12 IRQ_TYPE_LEVEL_HIGH>,
++                                           <13 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "macirq", "eth_lpi";
+                               interrupt-parent = <&liointc0>;
+                               phy-mode = "rgmii-id";
+@@ -155,8 +155,8 @@ gmac@3,1 {
+                                                  "loongson, pci-gmac";
+                               reg = <0x1900 0x0 0x0 0x0 0x0>;
+-                              interrupts = <14 IRQ_TYPE_LEVEL_LOW>,
+-                                           <15 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <14 IRQ_TYPE_LEVEL_HIGH>,
++                                           <15 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "macirq", "eth_lpi";
+                               interrupt-parent = <&liointc0>;
+                               phy-mode = "rgmii-id";
+@@ -178,7 +178,7 @@ ehci@4,1 {
+                                                  "pciclass0c03";
+                               reg = <0x2100 0x0 0x0 0x0 0x0>;
+-                              interrupts = <18 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <18 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                       };
+@@ -189,7 +189,7 @@ ohci@4,2 {
+                                                  "pciclass0c03";
+                               reg = <0x2200 0x0 0x0 0x0 0x0>;
+-                              interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <19 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                       };
+@@ -200,7 +200,7 @@ sata@8,0 {
+                                                  "pciclass0106";
+                               reg = <0x4000 0x0 0x0 0x0 0x0>;
+-                              interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <19 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc0>;
+                       };
+@@ -215,10 +215,10 @@ pcie@9,0 {
+                               #size-cells = <2>;
+                               device_type = "pci";
+                               #interrupt-cells = <1>;
+-                              interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &liointc1 0 IRQ_TYPE_LEVEL_LOW>;
++                              interrupt-map = <0 0 0 0 &liointc1 0 IRQ_TYPE_LEVEL_HIGH>;
+                               ranges;
+                               external-facing;
+                       };
+@@ -234,10 +234,10 @@ pcie@a,0 {
+                               #size-cells = <2>;
+                               device_type = "pci";
+                               #interrupt-cells = <1>;
+-                              interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &liointc1 1 IRQ_TYPE_LEVEL_LOW>;
++                              interrupt-map = <0 0 0 0 &liointc1 1 IRQ_TYPE_LEVEL_HIGH>;
+                               ranges;
+                               external-facing;
+                       };
+@@ -253,10 +253,10 @@ pcie@b,0 {
+                               #size-cells = <2>;
+                               device_type = "pci";
+                               #interrupt-cells = <1>;
+-                              interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &liointc1 2 IRQ_TYPE_LEVEL_LOW>;
++                              interrupt-map = <0 0 0 0 &liointc1 2 IRQ_TYPE_LEVEL_HIGH>;
+                               ranges;
+                               external-facing;
+                       };
+@@ -272,10 +272,10 @@ pcie@c,0 {
+                               #size-cells = <2>;
+                               device_type = "pci";
+                               #interrupt-cells = <1>;
+-                              interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &liointc1 3 IRQ_TYPE_LEVEL_LOW>;
++                              interrupt-map = <0 0 0 0 &liointc1 3 IRQ_TYPE_LEVEL_HIGH>;
+                               ranges;
+                               external-facing;
+                       };
+@@ -291,10 +291,10 @@ pcie@d,0 {
+                               #size-cells = <2>;
+                               device_type = "pci";
+                               #interrupt-cells = <1>;
+-                              interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &liointc1 4 IRQ_TYPE_LEVEL_LOW>;
++                              interrupt-map = <0 0 0 0 &liointc1 4 IRQ_TYPE_LEVEL_HIGH>;
+                               ranges;
+                               external-facing;
+                       };
+@@ -310,10 +310,10 @@ pcie@e,0 {
+                               #size-cells = <2>;
+                               device_type = "pci";
+                               #interrupt-cells = <1>;
+-                              interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
++                              interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &liointc1 5 IRQ_TYPE_LEVEL_LOW>;
++                              interrupt-map = <0 0 0 0 &liointc1 5 IRQ_TYPE_LEVEL_HIGH>;
+                               ranges;
+                               external-facing;
+                       };
+-- 
+2.43.0
+
diff --git a/queue-6.1/mips-dts-loongson-fix-ls2k1000-rtc-interrupt.patch b/queue-6.1/mips-dts-loongson-fix-ls2k1000-rtc-interrupt.patch
new file mode 100644 (file)
index 0000000..0bfb762
--- /dev/null
@@ -0,0 +1,38 @@
+From 281d66564ecb9d1452542e25bd67443e14b7bb32 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jun 2024 16:40:11 +0100
+Subject: MIPS: dts: loongson: Fix ls2k1000-rtc interrupt
+
+From: Jiaxun Yang <jiaxun.yang@flygoat.com>
+
+[ Upstream commit f70fd92df7529e7283e02a6c3a2510075f13ba30 ]
+
+The correct interrupt line for RTC is line 8 on liointc1.
+
+Fixes: e47084e116fc ("MIPS: Loongson64: DTS: Add RTC support to Loongson-2K1000")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+index eec8243be6499..cc7747c5f21f3 100644
+--- a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
++++ b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+@@ -99,8 +99,8 @@ liointc1: interrupt-controller@1fe11440 {
+               rtc0: rtc@1fe07800 {
+                       compatible = "loongson,ls2k1000-rtc";
+                       reg = <0 0x1fe07800 0 0x78>;
+-                      interrupt-parent = <&liointc0>;
+-                      interrupts = <60 IRQ_TYPE_LEVEL_HIGH>;
++                      interrupt-parent = <&liointc1>;
++                      interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+               };
+               uart0: serial@1fe00000 {
+-- 
+2.43.0
+
diff --git a/queue-6.1/mips-loongson64-dts-add-rtc-support-to-loongson-2k10.patch b/queue-6.1/mips-loongson64-dts-add-rtc-support-to-loongson-2k10.patch
new file mode 100644 (file)
index 0000000..a899f8e
--- /dev/null
@@ -0,0 +1,42 @@
+From 296c4889df72ddd4565cd795e5ae170991c9d154 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Jun 2023 17:50:50 +0800
+Subject: MIPS: Loongson64: DTS: Add RTC support to Loongson-2K1000
+
+From: Binbin Zhou <zhoubinbin@loongson.cn>
+
+[ Upstream commit e47084e116fccaa43644360d7c0b997979abce3e ]
+
+The module is now supported, enable it.
+
+Acked-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Signed-off-by: Binbin Zhou <zhoubinbin@loongson.cn>
+Signed-off-by: WANG Xuerui <git@xen0n.name>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Stable-dep-of: dbb69b9d6234 ("MIPS: dts: loongson: Fix liointc IRQ polarity")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+index 9089d1e4f3fee..c0be84a6e81fd 100644
+--- a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
++++ b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+@@ -96,6 +96,13 @@ liointc1: interrupt-controller@1fe11440 {
+                                               <0x00000000>; /* int3 */
+               };
++              rtc0: rtc@1fe07800 {
++                      compatible = "loongson,ls2k1000-rtc";
++                      reg = <0 0x1fe07800 0 0x78>;
++                      interrupt-parent = <&liointc0>;
++                      interrupts = <60 IRQ_TYPE_LEVEL_LOW>;
++              };
++
+               uart0: serial@1fe00000 {
+                       compatible = "ns16550a";
+                       reg = <0 0x1fe00000 0 0x8>;
+-- 
+2.43.0
+
diff --git a/queue-6.1/mips-loongson64-dts-fix-pcie-port-nodes-for-ls7a.patch b/queue-6.1/mips-loongson64-dts-fix-pcie-port-nodes-for-ls7a.patch
new file mode 100644 (file)
index 0000000..c34b575
--- /dev/null
@@ -0,0 +1,161 @@
+From 4423d6e7e4c5da7d588124b8f7fbf568774b391e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 May 2024 19:51:22 +0100
+Subject: MIPS: Loongson64: DTS: Fix PCIe port nodes for ls7a
+
+From: Jiaxun Yang <jiaxun.yang@flygoat.com>
+
+[ Upstream commit d89a415ff8d5e0aad4963f2d8ebb0f9e8110b7fa ]
+
+Add various required properties to silent warnings:
+
+arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi:116.16-297.5: Warning (interrupt_provider): /bus@10000000/pci@1a000000: '#interrupt-cells' found, but node is not an interrupt provider
+arch/mips/boot/dts/loongson/loongson64_2core_2k1000.dtb: Warning (interrupt_map): Failed prerequisite 'interrupt_provider'
+
+Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Stable-dep-of: dbb69b9d6234 ("MIPS: dts: loongson: Fix liointc IRQ polarity")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../boot/dts/loongson/loongson64-2k1000.dtsi  | 37 +++++++++++++++----
+ 1 file changed, 30 insertions(+), 7 deletions(-)
+
+diff --git a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+index c0be84a6e81fd..c1d3092fdd870 100644
+--- a/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
++++ b/arch/mips/boot/dts/loongson/loongson64-2k1000.dtsi
+@@ -117,7 +117,6 @@ pci@1a000000 {
+                       device_type = "pci";
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+-                      #interrupt-cells = <2>;
+                       reg = <0 0x1a000000 0 0x02000000>,
+                               <0xfe 0x00000000 0 0x20000000>;
+@@ -205,93 +204,117 @@ sata@8,0 {
+                               interrupt-parent = <&liointc0>;
+                       };
+-                      pci_bridge@9,0 {
++                      pcie@9,0 {
+                               compatible = "pci0014,7a19.0",
+                                                  "pci0014,7a19",
+                                                  "pciclass060400",
+                                                  "pciclass0604";
+                               reg = <0x4800 0x0 0x0 0x0 0x0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              device_type = "pci";
+                               #interrupt-cells = <1>;
+                               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &liointc1 0 IRQ_TYPE_LEVEL_LOW>;
++                              ranges;
+                               external-facing;
+                       };
+-                      pci_bridge@a,0 {
++                      pcie@a,0 {
+                               compatible = "pci0014,7a09.0",
+                                                  "pci0014,7a09",
+                                                  "pciclass060400",
+                                                  "pciclass0604";
+                               reg = <0x5000 0x0 0x0 0x0 0x0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              device_type = "pci";
+                               #interrupt-cells = <1>;
+                               interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &liointc1 1 IRQ_TYPE_LEVEL_LOW>;
++                              ranges;
+                               external-facing;
+                       };
+-                      pci_bridge@b,0 {
++                      pcie@b,0 {
+                               compatible = "pci0014,7a09.0",
+                                                  "pci0014,7a09",
+                                                  "pciclass060400",
+                                                  "pciclass0604";
+                               reg = <0x5800 0x0 0x0 0x0 0x0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              device_type = "pci";
+                               #interrupt-cells = <1>;
+                               interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &liointc1 2 IRQ_TYPE_LEVEL_LOW>;
++                              ranges;
+                               external-facing;
+                       };
+-                      pci_bridge@c,0 {
++                      pcie@c,0 {
+                               compatible = "pci0014,7a09.0",
+                                                  "pci0014,7a09",
+                                                  "pciclass060400",
+                                                  "pciclass0604";
+                               reg = <0x6000 0x0 0x0 0x0 0x0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              device_type = "pci";
+                               #interrupt-cells = <1>;
+                               interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &liointc1 3 IRQ_TYPE_LEVEL_LOW>;
++                              ranges;
+                               external-facing;
+                       };
+-                      pci_bridge@d,0 {
++                      pcie@d,0 {
+                               compatible = "pci0014,7a19.0",
+                                                  "pci0014,7a19",
+                                                  "pciclass060400",
+                                                  "pciclass0604";
+                               reg = <0x6800 0x0 0x0 0x0 0x0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              device_type = "pci";
+                               #interrupt-cells = <1>;
+                               interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &liointc1 4 IRQ_TYPE_LEVEL_LOW>;
++                              ranges;
+                               external-facing;
+                       };
+-                      pci_bridge@e,0 {
++                      pcie@e,0 {
+                               compatible = "pci0014,7a09.0",
+                                                  "pci0014,7a09",
+                                                  "pciclass060400",
+                                                  "pciclass0604";
+                               reg = <0x7000 0x0 0x0 0x0 0x0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              device_type = "pci";
+                               #interrupt-cells = <1>;
+                               interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-parent = <&liointc1>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &liointc1 5 IRQ_TYPE_LEVEL_LOW>;
++                              ranges;
+                               external-facing;
+                       };
+-- 
+2.43.0
+
diff --git a/queue-6.1/mm-page_alloc-control-latency-caused-by-zone-pcp-dra.patch b/queue-6.1/mm-page_alloc-control-latency-caused-by-zone-pcp-dra.patch
new file mode 100644 (file)
index 0000000..a25281d
--- /dev/null
@@ -0,0 +1,118 @@
+From 458b05c581cf671aa8ed527858c142ba78ebf8c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 Mar 2024 21:07:36 +0100
+Subject: mm: page_alloc: control latency caused by zone PCP draining
+
+From: Lucas Stach <l.stach@pengutronix.de>
+
+[ Upstream commit 55f77df7d715110299f12c27f4365bd6332d1adb ]
+
+Patch series "mm/treewide: Remove pXd_huge() API", v2.
+
+In previous work [1], we removed the pXd_large() API, which is arch
+specific.  This patchset further removes the hugetlb pXd_huge() API.
+
+Hugetlb was never special on creating huge mappings when compared with
+other huge mappings.  Having a standalone API just to detect such pgtable
+entries is more or less redundant, especially after the pXd_leaf() API set
+is introduced with/without CONFIG_HUGETLB_PAGE.
+
+When looking at this problem, a few issues are also exposed that we don't
+have a clear definition of the *_huge() variance API.  This patchset
+started by cleaning these issues first, then replace all *_huge() users to
+use *_leaf(), then drop all *_huge() code.
+
+On x86/sparc, swap entries will be reported "true" in pXd_huge(), while
+for all the rest archs they're reported "false" instead.  This part is
+done in patch 1-5, in which I suspect patch 1 can be seen as a bug fix,
+but I'll leave that to hmm experts to decide.
+
+Besides, there are three archs (arm, arm64, powerpc) that have slightly
+different definitions between the *_huge() v.s.  *_leaf() variances.  I
+tackled them separately so that it'll be easier for arch experts to chim
+in when necessary.  This part is done in patch 6-9.
+
+The final patches 10-14 do the rest on the final removal, since *_leaf()
+will be the ultimate API in the future, and we seem to have quite some
+confusions on how *_huge() APIs can be defined, provide a rich comment for
+*_leaf() API set to define them properly to avoid future misuse, and
+hopefully that'll also help new archs to start support huge mappings and
+avoid traps (like either swap entries, or PROT_NONE entry checks).
+
+[1] https://lore.kernel.org/r/20240305043750.93762-1-peterx@redhat.com
+
+This patch (of 14):
+
+When the complete PCP is drained a much larger number of pages than the
+usual batch size might be freed at once, causing large IRQ and preemption
+latency spikes, as they are all freed while holding the pcp and zone
+spinlocks.
+
+To avoid those latency spikes, limit the number of pages freed in a single
+bulk operation to common batch limits.
+
+Link: https://lkml.kernel.org/r/20240318200404.448346-1-peterx@redhat.com
+Link: https://lkml.kernel.org/r/20240318200736.2835502-1-l.stach@pengutronix.de
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+Signed-off-by: Peter Xu <peterx@redhat.com>
+Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
+Cc: Jason Gunthorpe <jgg@nvidia.com>
+Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>
+Cc: Mike Rapoport (IBM) <rppt@kernel.org>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: Alistair Popple <apopple@nvidia.com>
+Cc: Andreas Larsson <andreas@gaisler.com>
+Cc: "Aneesh Kumar K.V" <aneesh.kumar@kernel.org>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Bjorn Andersson <andersson@kernel.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Cc: David S. Miller <davem@davemloft.net>
+Cc: Fabio Estevam <festevam@denx.de>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Konrad Dybcio <konrad.dybcio@linaro.org>
+Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Cc: Mark Salter <msalter@redhat.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: "Naveen N. Rao" <naveen.n.rao@linux.ibm.com>
+Cc: Nicholas Piggin <npiggin@gmail.com>
+Cc: Russell King <linux@armlinux.org.uk>
+Cc: Shawn Guo <shawnguo@kernel.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Will Deacon <will@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 66eca1021a42 ("mm/page_alloc: fix pcp->count race between drain_pages_zone() vs __rmqueue_pcplist()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/page_alloc.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 8eaf51257db5f..4029d13636ece 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -3176,12 +3176,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.1/mm-page_alloc-fix-pcp-count-race-between-drain_pages.patch b/queue-6.1/mm-page_alloc-fix-pcp-count-race-between-drain_pages.patch
new file mode 100644 (file)
index 0000000..884d217
--- /dev/null
@@ -0,0 +1,99 @@
+From 1ca2834a9e51f776b251ede5bb86c7fcba7c7466 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Jul 2024 14:44:28 +0800
+Subject: mm/page_alloc: fix pcp->count race between drain_pages_zone() vs
+ __rmqueue_pcplist()
+
+From: Li Zhijian <lizhijian@fujitsu.com>
+
+[ Upstream commit 66eca1021a42856d6af2a9802c99e160278aed91 ]
+
+It's expected that no page should be left in pcp_list after calling
+zone_pcp_disable() in offline_pages().  Previously, it's observed that
+offline_pages() gets stuck [1] due to some pages remaining in pcp_list.
+
+Cause:
+There is a race condition between drain_pages_zone() and __rmqueue_pcplist()
+involving the pcp->count variable. See below scenario:
+
+         CPU0                              CPU1
+    ----------------                    ---------------
+                                      spin_lock(&pcp->lock);
+                                      __rmqueue_pcplist() {
+zone_pcp_disable() {
+                                        /* list is empty */
+                                        if (list_empty(list)) {
+                                          /* add pages to pcp_list */
+                                          alloced = rmqueue_bulk()
+  mutex_lock(&pcp_batch_high_lock)
+  ...
+  __drain_all_pages() {
+    drain_pages_zone() {
+      /* read pcp->count, it's 0 here */
+      count = READ_ONCE(pcp->count)
+      /* 0 means nothing to drain */
+                                          /* update pcp->count */
+                                          pcp->count += alloced << order;
+      ...
+                                      ...
+                                      spin_unlock(&pcp->lock);
+
+In this case, after calling zone_pcp_disable() though, there are still some
+pages in pcp_list. And these pages in pcp_list are neither movable nor
+isolated, offline_pages() gets stuck as a result.
+
+Solution:
+Expand the scope of the pcp->lock to also protect pcp->count in
+drain_pages_zone(), to ensure no pages are left in the pcp list after
+zone_pcp_disable()
+
+[1] https://lore.kernel.org/linux-mm/6a07125f-e720-404c-b2f9-e55f3f166e85@fujitsu.com/
+
+Link: https://lkml.kernel.org/r/20240723064428.1179519-1-lizhijian@fujitsu.com
+Fixes: 4b23a68f9536 ("mm/page_alloc: protect PCP lists with a spinlock")
+Signed-off-by: Li Zhijian <lizhijian@fujitsu.com>
+Reported-by: Yao Xingtao <yaoxt.fnst@fujitsu.com>
+Reviewed-by: Vlastimil Babka <vbabka@suse.cz>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/page_alloc.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 4029d13636ece..a905b850d31c4 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -3177,16 +3177,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.1/mm-restrict-the-pcp-batch-scale-factor-to-avoid-too-.patch b/queue-6.1/mm-restrict-the-pcp-batch-scale-factor-to-avoid-too-.patch
new file mode 100644 (file)
index 0000000..feaff03
--- /dev/null
@@ -0,0 +1,181 @@
+From 51188ccd359ebdfa65d97541fe77adad6c6417c6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Oct 2023 13:29:57 +0800
+Subject: mm: restrict the pcp batch scale factor to avoid too long latency
+
+From: Huang Ying <ying.huang@intel.com>
+
+[ Upstream commit 52166607ecc980391b1fffbce0be3074a96d0c7b ]
+
+In page allocator, PCP (Per-CPU Pageset) is refilled and drained in
+batches to increase page allocation throughput, reduce page
+allocation/freeing latency per page, and reduce zone lock contention.  But
+too large batch size will cause too long maximal allocation/freeing
+latency, which may punish arbitrary users.  So the default batch size is
+chosen carefully (in zone_batchsize(), the value is 63 for zone > 1GB) to
+avoid that.
+
+In commit 3b12e7e97938 ("mm/page_alloc: scale the number of pages that are
+batch freed"), the batch size will be scaled for large number of page
+freeing to improve page freeing performance and reduce zone lock
+contention.  Similar optimization can be used for large number of pages
+allocation too.
+
+To find out a suitable max batch scale factor (that is, max effective
+batch size), some tests and measurement on some machines were done as
+follows.
+
+A set of debug patches are implemented as follows,
+
+- Set PCP high to be 2 * batch to reduce the effect of PCP high
+
+- Disable free batch size scaling to get the raw performance.
+
+- The code with zone lock held is extracted from rmqueue_bulk() and
+  free_pcppages_bulk() to 2 separate functions to make it easy to
+  measure the function run time with ftrace function_graph tracer.
+
+- The batch size is hard coded to be 63 (default), 127, 255, 511,
+  1023, 2047, 4095.
+
+Then will-it-scale/page_fault1 is used to generate the page
+allocation/freeing workload.  The page allocation/freeing throughput
+(page/s) is measured via will-it-scale.  The page allocation/freeing
+average latency (alloc/free latency avg, in us) and allocation/freeing
+latency at 99 percentile (alloc/free latency 99%, in us) are measured with
+ftrace function_graph tracer.
+
+The test results are as follows,
+
+Sapphire Rapids Server
+======================
+Batch  throughput      free latency    free latency    alloc latency   alloc latency
+       page/s          avg / us        99% / us        avg / us        99% / us
+-----  ----------      ------------    ------------    -------------   -------------
+  63   513633.4         2.33            3.57            2.67             6.83
+ 127   517616.7         4.35            6.65            4.22            13.03
+ 255   520822.8         8.29           13.32            7.52            25.24
+ 511   524122.0        15.79           23.42           14.02            49.35
+1023   525980.5        30.25           44.19           25.36            94.88
+2047   526793.6        59.39           84.50           45.22           140.81
+
+Ice Lake Server
+===============
+Batch  throughput      free latency    free latency    alloc latency   alloc latency
+       page/s          avg / us        99% / us        avg / us        99% / us
+-----  ----------      ------------    ------------    -------------   -------------
+  63   620210.3         2.21            3.68            2.02            4.35
+ 127   627003.0         4.09            6.86            3.51            8.28
+ 255   630777.5         7.70           13.50            6.17           15.97
+ 511   633651.5        14.85           22.62           11.66           31.08
+1023   637071.1        28.55           42.02           20.81           54.36
+2047   638089.7        56.54           84.06           39.28           91.68
+
+Cascade Lake Server
+===================
+Batch  throughput      free latency    free latency    alloc latency   alloc latency
+       page/s          avg / us        99% / us        avg / us        99% / us
+-----  ----------      ------------    ------------    -------------   -------------
+  63   404706.7         3.29             5.03           3.53             4.75
+ 127   422475.2         6.12             9.09           6.36             8.76
+ 255   411522.2        11.68            16.97          10.90            16.39
+ 511   428124.1        22.54            31.28          19.86            32.25
+1023   414718.4        43.39            62.52          40.00            66.33
+2047   429848.7        86.64           120.34          71.14           106.08
+
+Commet Lake Desktop
+===================
+Batch  throughput      free latency    free latency    alloc latency   alloc latency
+       page/s          avg / us        99% / us        avg / us        99% / us
+-----  ----------      ------------    ------------    -------------   -------------
+
+  63   795183.13        2.18            3.55            2.03            3.05
+ 127   803067.85        3.91            6.56            3.85            5.52
+ 255   812771.10        7.35           10.80            7.14           10.20
+ 511   817723.48       14.17           27.54           13.43           30.31
+1023   818870.19       27.72           40.10           27.89           46.28
+
+Coffee Lake Desktop
+===================
+Batch  throughput      free latency    free latency    alloc latency   alloc latency
+       page/s          avg / us        99% / us        avg / us        99% / us
+-----  ----------      ------------    ------------    -------------   -------------
+  63   510542.8         3.13             4.40           2.48            3.43
+ 127   514288.6         5.97             7.89           4.65            6.04
+ 255   516889.7        11.86            15.58           8.96           12.55
+ 511   519802.4        23.10            28.81          16.95           26.19
+1023   520802.7        45.30            52.51          33.19           45.95
+2047   519997.1        90.63           104.00          65.26           81.74
+
+From the above data, to restrict the allocation/freeing latency to be less
+than 100 us in most times, the max batch scale factor needs to be less
+than or equal to 5.
+
+Although it is reasonable to use 5 as max batch scale factor for the
+systems tested, there are also slower systems.  Where smaller value should
+be used to constrain the page allocation/freeing latency.
+
+So, in this patch, a new kconfig option (PCP_BATCH_SCALE_MAX) is added to
+set the max batch scale factor.  Whose default value is 5, and users can
+reduce it when necessary.
+
+Link: https://lkml.kernel.org/r/20231016053002.756205-5-ying.huang@intel.com
+Signed-off-by: "Huang, Ying" <ying.huang@intel.com>
+Acked-by: Andrew Morton <akpm@linux-foundation.org>
+Acked-by: Mel Gorman <mgorman@techsingularity.net>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Johannes Weiner <jweiner@redhat.com>
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: Christoph Lameter <cl@linux.com>
+Cc: Arjan van de Ven <arjan@linux.intel.com>
+Cc: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 66eca1021a42 ("mm/page_alloc: fix pcp->count race between drain_pages_zone() vs __rmqueue_pcplist()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/Kconfig      | 11 +++++++++++
+ mm/page_alloc.c |  2 +-
+ 2 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/mm/Kconfig b/mm/Kconfig
+index 35109a4a2f7ce..a65145fe89f2b 100644
+--- a/mm/Kconfig
++++ b/mm/Kconfig
+@@ -627,6 +627,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 12412263d131e..8eaf51257db5f 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -3389,7 +3389,7 @@ static int nr_pcp_free(struct per_cpu_pages *pcp, int high, int batch,
+        * 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.1/series b/queue-6.1/series
new file mode 100644 (file)
index 0000000..c8c16a5
--- /dev/null
@@ -0,0 +1,37 @@
+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
+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-make-ext4_es_insert_extent-return-void.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-convert-to-platform-remove-callba.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
+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
+irqdomain-use-return-value-of-strreplace.patch
+irqdomain-fixed-unbalanced-fwnode-get-and-put.patch
+drm-udl-rename-struct-udl_drm_connector-to-struct-ud.patch
+drm-udl-test-pixel-limit-in-mode-config-s-mode-valid.patch
+drm-udl-use-usb-timeout-constant-when-reading-edid.patch
+drm-udl-various-improvements-to-the-connector.patch
+drm-udl-move-connector-to-modesetting-code.patch
+drm-udl-remove-drm_connector_poll_hpd.patch
+drm-i915-dp-don-t-switch-the-lttpr-mode-on-an-active.patch
+mips-loongson64-dts-add-rtc-support-to-loongson-2k10.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.1/sysctl-allow-change-system-v-ipc-sysctls-inside-ipc-.patch b/queue-6.1/sysctl-allow-change-system-v-ipc-sysctls-inside-ipc-.patch
new file mode 100644 (file)
index 0000000..27714ba
--- /dev/null
@@ -0,0 +1,140 @@
+From 884df3a11b1cfd4e10bf9287c450052c9da7b56a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jan 2024 15:46:41 +0000
+Subject: sysctl: allow change system v ipc sysctls inside ipc namespace
+
+From: Alexey Gladkov <legion@kernel.org>
+
+[ Upstream commit 50ec499b9a43e46200c9f7b7d723ab2e4af540b3 ]
+
+Patch series "Allow to change ipc/mq sysctls inside ipc namespace", v3.
+
+Right now ipc and mq limits count as per ipc namespace, but only real root
+can change them.  By default, the current values of these limits are such
+that it can only be reduced.  Since only root can change the values, it is
+impossible to reduce these limits in the rootless container.
+
+We can allow limit changes within ipc namespace because mq parameters are
+limited by RLIMIT_MSGQUEUE and ipc parameters are not limited to anything
+other than cgroups.
+
+This patch (of 3):
+
+Rootless containers are not allowed to modify kernel IPC parameters.
+
+All default limits are set to such high values that in fact there are no
+limits at all.  All limits are not inherited and are initialized to
+default values when a new ipc_namespace is created.
+
+For new ipc_namespace:
+
+size_t       ipc_ns.shm_ctlmax = SHMMAX; // (ULONG_MAX - (1UL << 24))
+size_t       ipc_ns.shm_ctlall = SHMALL; // (ULONG_MAX - (1UL << 24))
+int          ipc_ns.shm_ctlmni = IPCMNI; // (1 << 15)
+int          ipc_ns.shm_rmid_forced = 0;
+unsigned int ipc_ns.msg_ctlmax = MSGMAX; // 8192
+unsigned int ipc_ns.msg_ctlmni = MSGMNI; // 32000
+unsigned int ipc_ns.msg_ctlmnb = MSGMNB; // 16384
+
+The shm_tot (total amount of shared pages) has also ceased to be global,
+it is located in ipc_namespace and is not inherited from anywhere.
+
+In such conditions, it cannot be said that these limits limit anything.
+The real limiter for them is cgroups.
+
+If we allow rootless containers to change these parameters, then it can
+only be reduced.
+
+Link: https://lkml.kernel.org/r/cover.1705333426.git.legion@kernel.org
+Link: https://lkml.kernel.org/r/d2f4603305cbfed58a24755aa61d027314b73a45.1705333426.git.legion@kernel.org
+Signed-off-by: Alexey Gladkov <legion@kernel.org>
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Link: https://lkml.kernel.org/r/e2d84d3ec0172cfff759e6065da84ce0cc2736f8.1663756794.git.legion@kernel.org
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: Joel Granados <joel.granados@gmail.com>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Luis Chamberlain <mcgrof@kernel.org>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Cc: Davidlohr Bueso <dave@stgolabs.net>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 98ca62ba9e2b ("sysctl: always initialize i_uid/i_gid")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ ipc/ipc_sysctl.c | 37 +++++++++++++++++++++++++++++++++++--
+ 1 file changed, 35 insertions(+), 2 deletions(-)
+
+diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
+index ef313ecfb53a1..29c1d3ae2a5c8 100644
+--- a/ipc/ipc_sysctl.c
++++ b/ipc/ipc_sysctl.c
+@@ -14,6 +14,7 @@
+ #include <linux/ipc_namespace.h>
+ #include <linux/msg.h>
+ #include <linux/slab.h>
++#include <linux/cred.h>
+ #include "util.h"
+ static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
+@@ -190,25 +191,57 @@ static int set_is_seen(struct ctl_table_set *set)
+       return &current->nsproxy->ipc_ns->ipc_set == set;
+ }
++static void ipc_set_ownership(struct ctl_table_header *head,
++                            struct ctl_table *table,
++                            kuid_t *uid, kgid_t *gid)
++{
++      struct ipc_namespace *ns =
++              container_of(head->set, struct ipc_namespace, ipc_set);
++
++      kuid_t ns_root_uid = make_kuid(ns->user_ns, 0);
++      kgid_t ns_root_gid = make_kgid(ns->user_ns, 0);
++
++      *uid = uid_valid(ns_root_uid) ? ns_root_uid : GLOBAL_ROOT_UID;
++      *gid = gid_valid(ns_root_gid) ? ns_root_gid : GLOBAL_ROOT_GID;
++}
++
+ static int ipc_permissions(struct ctl_table_header *head, struct ctl_table *table)
+ {
+       int mode = table->mode;
+ #ifdef CONFIG_CHECKPOINT_RESTORE
+-      struct ipc_namespace *ns = current->nsproxy->ipc_ns;
++      struct ipc_namespace *ns =
++              container_of(head->set, struct ipc_namespace, ipc_set);
+       if (((table->data == &ns->ids[IPC_SEM_IDS].next_id) ||
+            (table->data == &ns->ids[IPC_MSG_IDS].next_id) ||
+            (table->data == &ns->ids[IPC_SHM_IDS].next_id)) &&
+           checkpoint_restore_ns_capable(ns->user_ns))
+               mode = 0666;
++      else
+ #endif
+-      return mode;
++      {
++              kuid_t ns_root_uid;
++              kgid_t ns_root_gid;
++
++              ipc_set_ownership(head, table, &ns_root_uid, &ns_root_gid);
++
++              if (uid_eq(current_euid(), ns_root_uid))
++                      mode >>= 6;
++
++              else if (in_egroup_p(ns_root_gid))
++                      mode >>= 3;
++      }
++
++      mode &= 7;
++
++      return (mode << 6) | (mode << 3) | mode;
+ }
+ static struct ctl_table_root set_root = {
+       .lookup = set_lookup,
+       .permissions = ipc_permissions,
++      .set_ownership = ipc_set_ownership,
+ };
+ bool setup_ipc_sysctls(struct ipc_namespace *ns)
+-- 
+2.43.0
+
diff --git a/queue-6.1/sysctl-allow-to-change-limits-for-posix-messages-que.patch b/queue-6.1/sysctl-allow-to-change-limits-for-posix-messages-que.patch
new file mode 100644 (file)
index 0000000..5e84574
--- /dev/null
@@ -0,0 +1,95 @@
+From b0543641855de8e889045e0cac33319f705a8749 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 Jan 2024 15:46:43 +0000
+Subject: sysctl: allow to change limits for posix messages queues
+
+From: Alexey Gladkov <legion@kernel.org>
+
+[ Upstream commit f9436a5d0497f759330d07e1189565edd4456be8 ]
+
+All parameters of posix messages queues (queues_max/msg_max/msgsize_max)
+end up being limited by RLIMIT_MSGQUEUE.  The code in mqueue_get_inode is
+where that limiting happens.
+
+The RLIMIT_MSGQUEUE is bound to the user namespace and is counted
+hierarchically.
+
+We can allow root in the user namespace to modify the posix messages
+queues parameters.
+
+Link: https://lkml.kernel.org/r/6ad67f23d1459a4f4339f74aa73bac0ecf3995e1.1705333426.git.legion@kernel.org
+Signed-off-by: Alexey Gladkov <legion@kernel.org>
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Link: https://lkml.kernel.org/r/7eb21211c8622e91d226e63416b1b93c079f60ee.1663756794.git.legion@kernel.org
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: Davidlohr Bueso <dave@stgolabs.net>
+Cc: Joel Granados <joel.granados@gmail.com>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Luis Chamberlain <mcgrof@kernel.org>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: 98ca62ba9e2b ("sysctl: always initialize i_uid/i_gid")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ ipc/mq_sysctl.c | 36 ++++++++++++++++++++++++++++++++++++
+ 1 file changed, 36 insertions(+)
+
+diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c
+index fbf6a8b93a265..ce03930aced55 100644
+--- a/ipc/mq_sysctl.c
++++ b/ipc/mq_sysctl.c
+@@ -12,6 +12,7 @@
+ #include <linux/stat.h>
+ #include <linux/capability.h>
+ #include <linux/slab.h>
++#include <linux/cred.h>
+ static int msg_max_limit_min = MIN_MSGMAX;
+ static int msg_max_limit_max = HARD_MSGMAX;
+@@ -76,8 +77,43 @@ static int set_is_seen(struct ctl_table_set *set)
+       return &current->nsproxy->ipc_ns->mq_set == set;
+ }
++static void mq_set_ownership(struct ctl_table_header *head,
++                           struct ctl_table *table,
++                           kuid_t *uid, kgid_t *gid)
++{
++      struct ipc_namespace *ns =
++              container_of(head->set, struct ipc_namespace, mq_set);
++
++      kuid_t ns_root_uid = make_kuid(ns->user_ns, 0);
++      kgid_t ns_root_gid = make_kgid(ns->user_ns, 0);
++
++      *uid = uid_valid(ns_root_uid) ? ns_root_uid : GLOBAL_ROOT_UID;
++      *gid = gid_valid(ns_root_gid) ? ns_root_gid : GLOBAL_ROOT_GID;
++}
++
++static int mq_permissions(struct ctl_table_header *head, struct ctl_table *table)
++{
++      int mode = table->mode;
++      kuid_t ns_root_uid;
++      kgid_t ns_root_gid;
++
++      mq_set_ownership(head, table, &ns_root_uid, &ns_root_gid);
++
++      if (uid_eq(current_euid(), ns_root_uid))
++              mode >>= 6;
++
++      else if (in_egroup_p(ns_root_gid))
++              mode >>= 3;
++
++      mode &= 7;
++
++      return (mode << 6) | (mode << 3) | mode;
++}
++
+ static struct ctl_table_root set_root = {
+       .lookup = set_lookup,
++      .permissions = mq_permissions,
++      .set_ownership = mq_set_ownership,
+ };
+ bool setup_mq_sysctls(struct ipc_namespace *ns)
+-- 
+2.43.0
+
diff --git a/queue-6.1/sysctl-always-initialize-i_uid-i_gid.patch b/queue-6.1/sysctl-always-initialize-i_uid-i_gid.patch
new file mode 100644 (file)
index 0000000..f493d98
--- /dev/null
@@ -0,0 +1,52 @@
+From b4c197c0c5ff48298e9bfd35df42ba749b9a0ef8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Apr 2024 23:10:34 +0200
+Subject: sysctl: always initialize i_uid/i_gid
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit 98ca62ba9e2be5863c7d069f84f7166b45a5b2f4 ]
+
+Always initialize i_uid/i_gid inside the sysfs core so set_ownership()
+can safely skip setting them.
+
+Commit 5ec27ec735ba ("fs/proc/proc_sysctl.c: fix the default values of
+i_uid/i_gid on /proc/sys inodes.") added defaults for i_uid/i_gid when
+set_ownership() was not implemented. It also missed adjusting
+net_ctl_set_ownership() to use the same default values in case the
+computation of a better value failed.
+
+Fixes: 5ec27ec735ba ("fs/proc/proc_sysctl.c: fix the default values of i_uid/i_gid on /proc/sys inodes.")
+Cc: stable@vger.kernel.org
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Joel Granados <j.granados@samsung.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/proc/proc_sysctl.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
+index c468cc0f6d69b..df77a7bcce498 100644
+--- a/fs/proc/proc_sysctl.c
++++ b/fs/proc/proc_sysctl.c
+@@ -483,12 +483,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.1/sysctl-treewide-drop-unused-argument-ctl_table_root-.patch b/queue-6.1/sysctl-treewide-drop-unused-argument-ctl_table_root-.patch
new file mode 100644 (file)
index 0000000..eb620d9
--- /dev/null
@@ -0,0 +1,127 @@
+From d1357307fcca327d023b05a7edf79914cc811755 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Mar 2024 19:11:30 +0100
+Subject: sysctl: treewide: drop unused argument
+ ctl_table_root::set_ownership(table)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Thomas Weißschuh <linux@weissschuh.net>
+
+[ Upstream commit 520713a93d550406dae14d49cdb8778d70cecdfd ]
+
+Remove the 'table' argument from set_ownership as it is never used. This
+change is a step towards putting "struct ctl_table" into .rodata and
+eventually having sysctl core only use "const struct ctl_table".
+
+The patch was created with the following coccinelle script:
+
+  @@
+  identifier func, head, table, uid, gid;
+  @@
+
+  void func(
+    struct ctl_table_header *head,
+  - struct ctl_table *table,
+    kuid_t *uid, kgid_t *gid)
+  { ... }
+
+No additional occurrences of 'set_ownership' were found after doing a
+tree-wide search.
+
+Reviewed-by: Joel Granados <j.granados@samsung.com>
+Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
+Signed-off-by: Joel Granados <j.granados@samsung.com>
+Stable-dep-of: 98ca62ba9e2b ("sysctl: always initialize i_uid/i_gid")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/proc/proc_sysctl.c  | 2 +-
+ include/linux/sysctl.h | 1 -
+ ipc/ipc_sysctl.c       | 3 +--
+ ipc/mq_sysctl.c        | 3 +--
+ net/sysctl_net.c       | 1 -
+ 5 files changed, 3 insertions(+), 7 deletions(-)
+
+diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
+index 4a4c04a3b1a0a..c468cc0f6d69b 100644
+--- a/fs/proc/proc_sysctl.c
++++ b/fs/proc/proc_sysctl.c
+@@ -484,7 +484,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 a207c7ed41bd2..9f24feb94b24d 100644
+--- a/include/linux/sysctl.h
++++ b/include/linux/sysctl.h
+@@ -185,7 +185,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 29c1d3ae2a5c8..d7ca2bdae9e82 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 ce03930aced55..c960691fc24d9 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 4b45ed631eb8b..2edb8040eb6c7 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
+