--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
--- /dev/null
+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 ¤t->nsproxy->ipc_ns->ipc_set == set;
+ }
+
++static void ipc_set_ownership(struct ctl_table_header *head,
++ struct ctl_table *table,
++ kuid_t *uid, kgid_t *gid)
++{
++ struct ipc_namespace *ns =
++ container_of(head->set, struct ipc_namespace, ipc_set);
++
++ kuid_t ns_root_uid = make_kuid(ns->user_ns, 0);
++ kgid_t ns_root_gid = make_kgid(ns->user_ns, 0);
++
++ *uid = uid_valid(ns_root_uid) ? ns_root_uid : GLOBAL_ROOT_UID;
++ *gid = gid_valid(ns_root_gid) ? ns_root_gid : GLOBAL_ROOT_GID;
++}
++
+ static int ipc_permissions(struct ctl_table_header *head, struct ctl_table *table)
+ {
+ int mode = table->mode;
+
+ #ifdef CONFIG_CHECKPOINT_RESTORE
+- struct ipc_namespace *ns = current->nsproxy->ipc_ns;
++ struct ipc_namespace *ns =
++ container_of(head->set, struct ipc_namespace, ipc_set);
+
+ if (((table->data == &ns->ids[IPC_SEM_IDS].next_id) ||
+ (table->data == &ns->ids[IPC_MSG_IDS].next_id) ||
+ (table->data == &ns->ids[IPC_SHM_IDS].next_id)) &&
+ checkpoint_restore_ns_capable(ns->user_ns))
+ mode = 0666;
++ else
+ #endif
+- return mode;
++ {
++ kuid_t ns_root_uid;
++ kgid_t ns_root_gid;
++
++ ipc_set_ownership(head, table, &ns_root_uid, &ns_root_gid);
++
++ if (uid_eq(current_euid(), ns_root_uid))
++ mode >>= 6;
++
++ else if (in_egroup_p(ns_root_gid))
++ mode >>= 3;
++ }
++
++ mode &= 7;
++
++ return (mode << 6) | (mode << 3) | mode;
+ }
+
+ static struct ctl_table_root set_root = {
+ .lookup = set_lookup,
+ .permissions = ipc_permissions,
++ .set_ownership = ipc_set_ownership,
+ };
+
+ bool setup_ipc_sysctls(struct ipc_namespace *ns)
+--
+2.43.0
+
--- /dev/null
+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 ¤t->nsproxy->ipc_ns->mq_set == set;
+ }
+
++static void mq_set_ownership(struct ctl_table_header *head,
++ struct ctl_table *table,
++ kuid_t *uid, kgid_t *gid)
++{
++ struct ipc_namespace *ns =
++ container_of(head->set, struct ipc_namespace, mq_set);
++
++ kuid_t ns_root_uid = make_kuid(ns->user_ns, 0);
++ kgid_t ns_root_gid = make_kgid(ns->user_ns, 0);
++
++ *uid = uid_valid(ns_root_uid) ? ns_root_uid : GLOBAL_ROOT_UID;
++ *gid = gid_valid(ns_root_gid) ? ns_root_gid : GLOBAL_ROOT_GID;
++}
++
++static int mq_permissions(struct ctl_table_header *head, struct ctl_table *table)
++{
++ int mode = table->mode;
++ kuid_t ns_root_uid;
++ kgid_t ns_root_gid;
++
++ mq_set_ownership(head, table, &ns_root_uid, &ns_root_gid);
++
++ if (uid_eq(current_euid(), ns_root_uid))
++ mode >>= 6;
++
++ else if (in_egroup_p(ns_root_gid))
++ mode >>= 3;
++
++ mode &= 7;
++
++ return (mode << 6) | (mode << 3) | mode;
++}
++
+ static struct ctl_table_root set_root = {
+ .lookup = set_lookup,
++ .permissions = mq_permissions,
++ .set_ownership = mq_set_ownership,
+ };
+
+ bool setup_mq_sysctls(struct ipc_namespace *ns)
+--
+2.43.0
+
--- /dev/null
+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
+
--- /dev/null
+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
+