--- /dev/null
+From 41b69992d0010f57001c2bd8465cc301c6f2e53d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Feb 2025 22:40:34 +0000
+Subject: arm64: tegra: Remove the Orin NX/Nano suspend key
+
+From: Ninad Malwade <nmalwade@nvidia.com>
+
+[ Upstream commit bb8a3ad25f098b6ea9b1d0f522427b4ad53a7bba ]
+
+As per the Orin Nano Dev Kit schematic, GPIO_G.02 is not available
+on this device family. It should not be used at all on Orin NX/Nano.
+Having this unused pin mapped as the suspend key can lead to
+unpredictable behavior for low power modes.
+
+Orin NX/Nano uses GPIO_EE.04 as both a "power" button and a "suspend"
+button. However, we cannot have two gpio-keys mapped to the same
+GPIO. Therefore remove the "suspend" key.
+
+Cc: stable@vger.kernel.org
+Fixes: e63472eda5ea ("arm64: tegra: Support Jetson Orin NX reference platform")
+Signed-off-by: Ninad Malwade <nmalwade@nvidia.com>
+Signed-off-by: Ivy Huang <yijuh@nvidia.com>
+Link: https://lore.kernel.org/r/20250206224034.3691397-1-yijuh@nvidia.com
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi | 7 -------
+ 1 file changed, 7 deletions(-)
+
+diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi
+index 39110c1232e0d..db10b4b46cca9 100644
+--- a/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi
++++ b/arch/arm64/boot/dts/nvidia/tegra234-p3768-0000.dtsi
+@@ -196,13 +196,6 @@ key-power {
+ wakeup-event-action = <EV_ACT_ASSERTED>;
+ wakeup-source;
+ };
+-
+- key-suspend {
+- label = "Suspend";
+- gpios = <&gpio TEGRA234_MAIN_GPIO(G, 2) GPIO_ACTIVE_LOW>;
+- linux,input-type = <EV_KEY>;
+- linux,code = <KEY_SLEEP>;
+- };
+ };
+
+ fan: pwm-fan {
+--
+2.39.5
+
--- /dev/null
+From d933556fe7d4117d9a187a9724b11af377152e9a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Mar 2025 17:47:58 +0000
+Subject: ASoC: q6apm-dai: make use of q6apm_get_hw_pointer
+
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+[ Upstream commit a93dad6f4e6a04a5943f6ee5686585f24abf7063 ]
+
+With the existing code, the buffer position is only reset in pointer
+callback, which leaves the possiblity of it going over the size of
+buffer size and reporting incorrect position to userspace.
+
+Without this patch, its possible to see errors like:
+snd-x1e80100 sound: invalid position: pcmC0D0p:0, pos = 12288, buffer size = 12288, period size = 1536
+snd-x1e80100 sound: invalid position: pcmC0D0p:0, pos = 12288, buffer size = 12288, period size = 1536
+
+Fixes: 9b4fe0f1cd791 ("ASoC: qdsp6: audioreach: add q6apm-dai support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Tested-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Tested-by: Johan Hovold <johan+linaro@kernel.org>
+Link: https://patch.msgid.link/20250314174800.10142-4-srinivas.kandagatla@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/qcom/qdsp6/q6apm-dai.c | 23 ++++-------------------
+ 1 file changed, 4 insertions(+), 19 deletions(-)
+
+diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c
+index a52304bef9d92..179f4f7386dd0 100644
+--- a/sound/soc/qcom/qdsp6/q6apm-dai.c
++++ b/sound/soc/qcom/qdsp6/q6apm-dai.c
+@@ -64,7 +64,6 @@ struct q6apm_dai_rtd {
+ phys_addr_t phys;
+ unsigned int pcm_size;
+ unsigned int pcm_count;
+- unsigned int pos; /* Buffer position */
+ unsigned int periods;
+ unsigned int bytes_sent;
+ unsigned int bytes_received;
+@@ -124,23 +123,16 @@ static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, vo
+ {
+ struct q6apm_dai_rtd *prtd = priv;
+ struct snd_pcm_substream *substream = prtd->substream;
+- unsigned long flags;
+
+ switch (opcode) {
+ case APM_CLIENT_EVENT_CMD_EOS_DONE:
+ prtd->state = Q6APM_STREAM_STOPPED;
+ break;
+ case APM_CLIENT_EVENT_DATA_WRITE_DONE:
+- spin_lock_irqsave(&prtd->lock, flags);
+- prtd->pos += prtd->pcm_count;
+- spin_unlock_irqrestore(&prtd->lock, flags);
+ snd_pcm_period_elapsed(substream);
+
+ break;
+ case APM_CLIENT_EVENT_DATA_READ_DONE:
+- spin_lock_irqsave(&prtd->lock, flags);
+- prtd->pos += prtd->pcm_count;
+- spin_unlock_irqrestore(&prtd->lock, flags);
+ snd_pcm_period_elapsed(substream);
+ if (prtd->state == Q6APM_STREAM_RUNNING)
+ q6apm_read(prtd->graph);
+@@ -246,7 +238,6 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
+ }
+
+ prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
+- prtd->pos = 0;
+ /* rate and channels are sent to audio driver */
+ ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg);
+ if (ret < 0) {
+@@ -445,16 +436,12 @@ static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component,
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct q6apm_dai_rtd *prtd = runtime->private_data;
+ snd_pcm_uframes_t ptr;
+- unsigned long flags;
+
+- spin_lock_irqsave(&prtd->lock, flags);
+- if (prtd->pos == prtd->pcm_size)
+- prtd->pos = 0;
+-
+- ptr = bytes_to_frames(runtime, prtd->pos);
+- spin_unlock_irqrestore(&prtd->lock, flags);
++ ptr = q6apm_get_hw_pointer(prtd->graph, substream->stream) * runtime->period_size;
++ if (ptr)
++ return ptr - 1;
+
+- return ptr;
++ return 0;
+ }
+
+ static int q6apm_dai_hw_params(struct snd_soc_component *component,
+@@ -669,8 +656,6 @@ static int q6apm_dai_compr_set_params(struct snd_soc_component *component,
+ prtd->pcm_size = runtime->fragments * runtime->fragment_size;
+ prtd->bits_per_sample = 16;
+
+- prtd->pos = 0;
+-
+ if (prtd->next_track != true) {
+ memcpy(&prtd->codec, codec, sizeof(*codec));
+
+--
+2.39.5
+
--- /dev/null
+From a96ad67ff2025a363b96450fd290f95ad0b598f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Mar 2025 17:47:56 +0000
+Subject: ASoC: q6apm-dai: schedule all available frames to avoid dsp
+ under-runs
+
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+[ Upstream commit 3d4a4411aa8bbc3653ff22a1ff0432eb93d22ae0 ]
+
+With the existing code, we are only setting up one period at a time, in a
+ping-pong buffer style. This triggers lot of underruns in the dsp
+leading to jitter noise during audio playback.
+
+Fix this by scheduling all available periods, this will ensure that the dsp
+has enough buffer feed and ultimatley fixing the underruns and audio
+distortion.
+
+Fixes: 9b4fe0f1cd79 ("ASoC: qdsp6: audioreach: add q6apm-dai support")
+Cc: stable@vger.kernel.org
+Reported-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Tested-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Tested-by: Johan Hovold <johan+linaro@kernel.org>
+Link: https://patch.msgid.link/20250314174800.10142-2-srinivas.kandagatla@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/qcom/qdsp6/q6apm-dai.c | 28 +++++++++++++++++++++++-----
+ 1 file changed, 23 insertions(+), 5 deletions(-)
+
+diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c
+index 5573802e480ba..f188d00825c03 100644
+--- a/sound/soc/qcom/qdsp6/q6apm-dai.c
++++ b/sound/soc/qcom/qdsp6/q6apm-dai.c
+@@ -70,6 +70,7 @@ struct q6apm_dai_rtd {
+ unsigned int bytes_received;
+ unsigned int copied_total;
+ uint16_t bits_per_sample;
++ snd_pcm_uframes_t queue_ptr;
+ bool next_track;
+ enum stream_state state;
+ struct q6apm_graph *graph;
+@@ -134,8 +135,6 @@ static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, vo
+ prtd->pos += prtd->pcm_count;
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ snd_pcm_period_elapsed(substream);
+- if (prtd->state == Q6APM_STREAM_RUNNING)
+- q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0);
+
+ break;
+ case APM_CLIENT_EVENT_DATA_READ_DONE:
+@@ -293,6 +292,27 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
+ return 0;
+ }
+
++static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct q6apm_dai_rtd *prtd = runtime->private_data;
++ int i, ret = 0, avail_periods;
++
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++ avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size;
++ for (i = 0; i < avail_periods; i++) {
++ ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, NO_TIMESTAMP);
++ if (ret < 0) {
++ dev_err(component->dev, "Error queuing playback buffer %d\n", ret);
++ return ret;
++ }
++ prtd->queue_ptr += runtime->period_size;
++ }
++ }
++
++ return ret;
++}
++
+ static int q6apm_dai_trigger(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream, int cmd)
+ {
+@@ -304,9 +324,6 @@ static int q6apm_dai_trigger(struct snd_soc_component *component,
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+- /* start writing buffers for playback only as we already queued capture buffers */
+- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+- ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ /* TODO support be handled via SoftPause Module */
+@@ -834,6 +851,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = {
+ .hw_params = q6apm_dai_hw_params,
+ .pointer = q6apm_dai_pointer,
+ .trigger = q6apm_dai_trigger,
++ .ack = q6apm_dai_ack,
+ .compress_ops = &q6apm_dai_compress_ops,
+ .use_dai_pcm_id = true,
+ };
+--
+2.39.5
+
--- /dev/null
+From 6de6666884340b22f57e5cd7dfb6d7c5bea859d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Dec 2023 11:00:48 +0100
+Subject: ASoC: qcom: Fix trivial code style issues
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit bb3392453d3ba44e60b85381e3bfa3c551a44e5d ]
+
+Fix few trivial code style issues, pointed out by checkpatch, so they do
+not get copied to new code (when old code is used as template):
+
+ WARNING: Prefer "GPL" over "GPL v2" - see commit bf7fbeeae6db ("module: Cure the MODULE_LICENSE "GPL" vs. "GPL v2" bogosity")
+ WARNING: function definition argument 'struct platform_device *' should also have an identifier name
+ ERROR: code indent should use tabs where possible
+ WARNING: please, no spaces at the start of a line
+ WARNING: Missing a blank line after declarations
+ WARNING: unnecessary whitespace before a quoted newline
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://msgid.link/r/20231204100048.211800-1-krzysztof.kozlowski@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: a93dad6f4e6a ("ASoC: q6apm-dai: make use of q6apm_get_hw_pointer")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/qcom/apq8016_sbc.c | 2 +-
+ sound/soc/qcom/apq8096.c | 2 +-
+ sound/soc/qcom/common.c | 2 +-
+ sound/soc/qcom/lpass-apq8016.c | 2 +-
+ sound/soc/qcom/lpass-cpu.c | 2 +-
+ sound/soc/qcom/lpass-hdmi.c | 2 +-
+ sound/soc/qcom/lpass-ipq806x.c | 2 +-
+ sound/soc/qcom/lpass-platform.c | 2 +-
+ sound/soc/qcom/lpass-sc7180.c | 2 +-
+ sound/soc/qcom/lpass.h | 2 +-
+ sound/soc/qcom/qdsp6/q6afe.c | 8 ++++----
+ sound/soc/qcom/qdsp6/q6apm-dai.c | 4 ++--
+ sound/soc/qcom/qdsp6/q6asm.h | 20 ++++++++++----------
+ sound/soc/qcom/qdsp6/topology.c | 3 ++-
+ sound/soc/qcom/sc7180.c | 2 +-
+ sound/soc/qcom/sc8280xp.c | 2 +-
+ sound/soc/qcom/sdm845.c | 2 +-
+ sound/soc/qcom/sdw.c | 2 +-
+ sound/soc/qcom/sm8250.c | 2 +-
+ sound/soc/qcom/storm.c | 2 +-
+ 20 files changed, 34 insertions(+), 33 deletions(-)
+
+diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c
+index ff9f6a1c95df1..40b6a837f66bb 100644
+--- a/sound/soc/qcom/apq8016_sbc.c
++++ b/sound/soc/qcom/apq8016_sbc.c
+@@ -343,4 +343,4 @@ module_platform_driver(apq8016_sbc_platform_driver);
+
+ MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
+ MODULE_DESCRIPTION("APQ8016 ASoC Machine Driver");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/apq8096.c b/sound/soc/qcom/apq8096.c
+index cddeb47dbcf21..8f1475685cb20 100644
+--- a/sound/soc/qcom/apq8096.c
++++ b/sound/soc/qcom/apq8096.c
+@@ -142,4 +142,4 @@ static struct platform_driver msm_snd_apq8096_driver = {
+ module_platform_driver(msm_snd_apq8096_driver);
+ MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
+ MODULE_DESCRIPTION("APQ8096 ASoC Machine Driver");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c
+index f2d1e3009cd23..23beafbcc26c2 100644
+--- a/sound/soc/qcom/common.c
++++ b/sound/soc/qcom/common.c
+@@ -239,4 +239,4 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(qcom_snd_wcd_jack_setup);
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c
+index 06a4faae50875..63db0f152e9db 100644
+--- a/sound/soc/qcom/lpass-apq8016.c
++++ b/sound/soc/qcom/lpass-apq8016.c
+@@ -305,5 +305,5 @@ static struct platform_driver apq8016_lpass_cpu_platform_driver = {
+ module_platform_driver(apq8016_lpass_cpu_platform_driver);
+
+ MODULE_DESCRIPTION("APQ8016 LPASS CPU Driver");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+
+diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c
+index 92316768011ae..bdb5e0c740a90 100644
+--- a/sound/soc/qcom/lpass-cpu.c
++++ b/sound/soc/qcom/lpass-cpu.c
+@@ -1304,4 +1304,4 @@ void asoc_qcom_lpass_cpu_platform_shutdown(struct platform_device *pdev)
+ EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_shutdown);
+
+ MODULE_DESCRIPTION("QTi LPASS CPU Driver");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/lpass-hdmi.c b/sound/soc/qcom/lpass-hdmi.c
+index 24b1a7523adb9..ce753ebc08945 100644
+--- a/sound/soc/qcom/lpass-hdmi.c
++++ b/sound/soc/qcom/lpass-hdmi.c
+@@ -251,4 +251,4 @@ const struct snd_soc_dai_ops asoc_qcom_lpass_hdmi_dai_ops = {
+ EXPORT_SYMBOL_GPL(asoc_qcom_lpass_hdmi_dai_ops);
+
+ MODULE_DESCRIPTION("QTi LPASS HDMI Driver");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c
+index 10f7e2639c423..2a82684c04de4 100644
+--- a/sound/soc/qcom/lpass-ipq806x.c
++++ b/sound/soc/qcom/lpass-ipq806x.c
+@@ -177,4 +177,4 @@ static struct platform_driver ipq806x_lpass_cpu_platform_driver = {
+ module_platform_driver(ipq806x_lpass_cpu_platform_driver);
+
+ MODULE_DESCRIPTION("QTi LPASS CPU Driver");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
+index 73e3d39bd24c3..f918d9e16dc04 100644
+--- a/sound/soc/qcom/lpass-platform.c
++++ b/sound/soc/qcom/lpass-platform.c
+@@ -1383,4 +1383,4 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
+ EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register);
+
+ MODULE_DESCRIPTION("QTi LPASS Platform Driver");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/lpass-sc7180.c b/sound/soc/qcom/lpass-sc7180.c
+index 62e49a0d27ba2..98faf82c22568 100644
+--- a/sound/soc/qcom/lpass-sc7180.c
++++ b/sound/soc/qcom/lpass-sc7180.c
+@@ -322,4 +322,4 @@ static struct platform_driver sc7180_lpass_cpu_platform_driver = {
+ module_platform_driver(sc7180_lpass_cpu_platform_driver);
+
+ MODULE_DESCRIPTION("SC7180 LPASS CPU DRIVER");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h
+index f821271a11467..5caec24555ea2 100644
+--- a/sound/soc/qcom/lpass.h
++++ b/sound/soc/qcom/lpass.h
+@@ -399,7 +399,7 @@ struct lpass_pcm_data {
+ };
+
+ /* register the platform driver from the CPU DAI driver */
+-int asoc_qcom_lpass_platform_register(struct platform_device *);
++int asoc_qcom_lpass_platform_register(struct platform_device *pdev);
+ void asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev);
+ void asoc_qcom_lpass_cpu_platform_shutdown(struct platform_device *pdev);
+ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev);
+diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c
+index 919e326b9462b..fcef53b97ff98 100644
+--- a/sound/soc/qcom/qdsp6/q6afe.c
++++ b/sound/soc/qcom/qdsp6/q6afe.c
+@@ -552,13 +552,13 @@ struct q6afe_port {
+ };
+
+ struct afe_cmd_remote_lpass_core_hw_vote_request {
+- uint32_t hw_block_id;
+- char client_name[8];
++ uint32_t hw_block_id;
++ char client_name[8];
+ } __packed;
+
+ struct afe_cmd_remote_lpass_core_hw_devote_request {
+- uint32_t hw_block_id;
+- uint32_t client_handle;
++ uint32_t hw_block_id;
++ uint32_t client_handle;
+ } __packed;
+
+
+diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c
+index f188d00825c03..a52304bef9d92 100644
+--- a/sound/soc/qcom/qdsp6/q6apm-dai.c
++++ b/sound/soc/qcom/qdsp6/q6apm-dai.c
+@@ -131,14 +131,14 @@ static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, vo
+ prtd->state = Q6APM_STREAM_STOPPED;
+ break;
+ case APM_CLIENT_EVENT_DATA_WRITE_DONE:
+- spin_lock_irqsave(&prtd->lock, flags);
++ spin_lock_irqsave(&prtd->lock, flags);
+ prtd->pos += prtd->pcm_count;
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ snd_pcm_period_elapsed(substream);
+
+ break;
+ case APM_CLIENT_EVENT_DATA_READ_DONE:
+- spin_lock_irqsave(&prtd->lock, flags);
++ spin_lock_irqsave(&prtd->lock, flags);
+ prtd->pos += prtd->pcm_count;
+ spin_unlock_irqrestore(&prtd->lock, flags);
+ snd_pcm_period_elapsed(substream);
+diff --git a/sound/soc/qcom/qdsp6/q6asm.h b/sound/soc/qcom/qdsp6/q6asm.h
+index 394604c349432..a33d92c7bd6bf 100644
+--- a/sound/soc/qcom/qdsp6/q6asm.h
++++ b/sound/soc/qcom/qdsp6/q6asm.h
+@@ -36,16 +36,16 @@ enum {
+ #define ASM_LAST_BUFFER_FLAG BIT(30)
+
+ struct q6asm_flac_cfg {
+- u32 sample_rate;
+- u32 ext_sample_rate;
+- u32 min_frame_size;
+- u32 max_frame_size;
+- u16 stream_info_present;
+- u16 min_blk_size;
+- u16 max_blk_size;
+- u16 ch_cfg;
+- u16 sample_size;
+- u16 md5_sum;
++ u32 sample_rate;
++ u32 ext_sample_rate;
++ u32 min_frame_size;
++ u32 max_frame_size;
++ u16 stream_info_present;
++ u16 min_blk_size;
++ u16 max_blk_size;
++ u16 ch_cfg;
++ u16 sample_size;
++ u16 md5_sum;
+ };
+
+ struct q6asm_wma_cfg {
+diff --git a/sound/soc/qcom/qdsp6/topology.c b/sound/soc/qcom/qdsp6/topology.c
+index 130b22a34fb3b..70572c83e1017 100644
+--- a/sound/soc/qcom/qdsp6/topology.c
++++ b/sound/soc/qcom/qdsp6/topology.c
+@@ -545,6 +545,7 @@ static struct audioreach_module *audioreach_parse_common_tokens(struct q6apm *ap
+
+ if (mod) {
+ int pn, id = 0;
++
+ mod->module_id = module_id;
+ mod->max_ip_port = max_ip_port;
+ mod->max_op_port = max_op_port;
+@@ -1271,7 +1272,7 @@ int audioreach_tplg_init(struct snd_soc_component *component)
+
+ ret = request_firmware(&fw, tplg_fw_name, dev);
+ if (ret < 0) {
+- dev_err(dev, "tplg firmware loading %s failed %d \n", tplg_fw_name, ret);
++ dev_err(dev, "tplg firmware loading %s failed %d\n", tplg_fw_name, ret);
+ goto err;
+ }
+
+diff --git a/sound/soc/qcom/sc7180.c b/sound/soc/qcom/sc7180.c
+index d1fd40e3f7a9d..1367752f2b63a 100644
+--- a/sound/soc/qcom/sc7180.c
++++ b/sound/soc/qcom/sc7180.c
+@@ -428,4 +428,4 @@ static struct platform_driver sc7180_snd_driver = {
+ module_platform_driver(sc7180_snd_driver);
+
+ MODULE_DESCRIPTION("sc7180 ASoC Machine Driver");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c
+index 6e5f194bc34b0..d5cc967992d16 100644
+--- a/sound/soc/qcom/sc8280xp.c
++++ b/sound/soc/qcom/sc8280xp.c
+@@ -174,4 +174,4 @@ static struct platform_driver snd_sc8280xp_driver = {
+ module_platform_driver(snd_sc8280xp_driver);
+ MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
+ MODULE_DESCRIPTION("SC8280XP ASoC Machine Driver");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
+index 25b964dea6c56..3eb29645a6377 100644
+--- a/sound/soc/qcom/sdm845.c
++++ b/sound/soc/qcom/sdm845.c
+@@ -625,4 +625,4 @@ static struct platform_driver sdm845_snd_driver = {
+ module_platform_driver(sdm845_snd_driver);
+
+ MODULE_DESCRIPTION("sdm845 ASoC Machine Driver");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c
+index ce89c0a33ef05..e7413b1fd867e 100644
+--- a/sound/soc/qcom/sdw.c
++++ b/sound/soc/qcom/sdw.c
+@@ -117,4 +117,4 @@ int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free);
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c
+index 9eb8ae0196d91..88a7169336d61 100644
+--- a/sound/soc/qcom/sm8250.c
++++ b/sound/soc/qcom/sm8250.c
+@@ -170,4 +170,4 @@ static struct platform_driver snd_sm8250_driver = {
+ module_platform_driver(snd_sm8250_driver);
+ MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
+ MODULE_DESCRIPTION("SM8250 ASoC Machine Driver");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+diff --git a/sound/soc/qcom/storm.c b/sound/soc/qcom/storm.c
+index 553165f11d306..c8d5ac43a1766 100644
+--- a/sound/soc/qcom/storm.c
++++ b/sound/soc/qcom/storm.c
+@@ -140,4 +140,4 @@ static struct platform_driver storm_platform_driver = {
+ module_platform_driver(storm_platform_driver);
+
+ MODULE_DESCRIPTION("QTi IPQ806x-based Storm Machine Driver");
+-MODULE_LICENSE("GPL v2");
++MODULE_LICENSE("GPL");
+--
+2.39.5
+
--- /dev/null
+From 796d0408f71dcc47dee9376aa932459166a8a51b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 14 Oct 2023 00:19:52 +0200
+Subject: ASoC: qcom: lpass: Make asoc_qcom_lpass_cpu_platform_remove() return
+ void
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit d0cc676c426d1958989fac2a0d45179fb9992f0a ]
+
+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.
+
+asoc_qcom_lpass_cpu_platform_remove() returned zero unconditionally.
+Make it return void instead and convert all users to struct
+platform_device::remove_new().
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Link: https://lore.kernel.org/r/20231013221945.1489203-15-u.kleine-koenig@pengutronix.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: a93dad6f4e6a ("ASoC: q6apm-dai: make use of q6apm_get_hw_pointer")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/qcom/lpass-apq8016.c | 2 +-
+ sound/soc/qcom/lpass-cpu.c | 5 +----
+ sound/soc/qcom/lpass-ipq806x.c | 2 +-
+ sound/soc/qcom/lpass-sc7180.c | 2 +-
+ sound/soc/qcom/lpass-sc7280.c | 2 +-
+ sound/soc/qcom/lpass.h | 2 +-
+ 6 files changed, 6 insertions(+), 9 deletions(-)
+
+diff --git a/sound/soc/qcom/lpass-apq8016.c b/sound/soc/qcom/lpass-apq8016.c
+index f919d46e18caa..06a4faae50875 100644
+--- a/sound/soc/qcom/lpass-apq8016.c
++++ b/sound/soc/qcom/lpass-apq8016.c
+@@ -300,7 +300,7 @@ static struct platform_driver apq8016_lpass_cpu_platform_driver = {
+ .of_match_table = of_match_ptr(apq8016_lpass_cpu_device_id),
+ },
+ .probe = asoc_qcom_lpass_cpu_platform_probe,
+- .remove = asoc_qcom_lpass_cpu_platform_remove,
++ .remove_new = asoc_qcom_lpass_cpu_platform_remove,
+ };
+ module_platform_driver(apq8016_lpass_cpu_platform_driver);
+
+diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c
+index e587455dc40a0..92316768011ae 100644
+--- a/sound/soc/qcom/lpass-cpu.c
++++ b/sound/soc/qcom/lpass-cpu.c
+@@ -1284,15 +1284,12 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
+ }
+ EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_probe);
+
+-int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev)
++void asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev)
+ {
+ struct lpass_data *drvdata = platform_get_drvdata(pdev);
+
+ if (drvdata->variant->exit)
+ drvdata->variant->exit(pdev);
+-
+-
+- return 0;
+ }
+ EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_remove);
+
+diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c
+index 2c97f295e3940..10f7e2639c423 100644
+--- a/sound/soc/qcom/lpass-ipq806x.c
++++ b/sound/soc/qcom/lpass-ipq806x.c
+@@ -172,7 +172,7 @@ static struct platform_driver ipq806x_lpass_cpu_platform_driver = {
+ .of_match_table = of_match_ptr(ipq806x_lpass_cpu_device_id),
+ },
+ .probe = asoc_qcom_lpass_cpu_platform_probe,
+- .remove = asoc_qcom_lpass_cpu_platform_remove,
++ .remove_new = asoc_qcom_lpass_cpu_platform_remove,
+ };
+ module_platform_driver(ipq806x_lpass_cpu_platform_driver);
+
+diff --git a/sound/soc/qcom/lpass-sc7180.c b/sound/soc/qcom/lpass-sc7180.c
+index d16c0d83aaad9..62e49a0d27ba2 100644
+--- a/sound/soc/qcom/lpass-sc7180.c
++++ b/sound/soc/qcom/lpass-sc7180.c
+@@ -315,7 +315,7 @@ static struct platform_driver sc7180_lpass_cpu_platform_driver = {
+ .pm = &sc7180_lpass_pm_ops,
+ },
+ .probe = asoc_qcom_lpass_cpu_platform_probe,
+- .remove = asoc_qcom_lpass_cpu_platform_remove,
++ .remove_new = asoc_qcom_lpass_cpu_platform_remove,
+ .shutdown = asoc_qcom_lpass_cpu_platform_shutdown,
+ };
+
+diff --git a/sound/soc/qcom/lpass-sc7280.c b/sound/soc/qcom/lpass-sc7280.c
+index 6b2eb25ed9390..97b9053ed3b02 100644
+--- a/sound/soc/qcom/lpass-sc7280.c
++++ b/sound/soc/qcom/lpass-sc7280.c
+@@ -445,7 +445,7 @@ static struct platform_driver sc7280_lpass_cpu_platform_driver = {
+ .pm = &sc7280_lpass_pm_ops,
+ },
+ .probe = asoc_qcom_lpass_cpu_platform_probe,
+- .remove = asoc_qcom_lpass_cpu_platform_remove,
++ .remove_new = asoc_qcom_lpass_cpu_platform_remove,
+ .shutdown = asoc_qcom_lpass_cpu_platform_shutdown,
+ };
+
+diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h
+index ea12f02eca55f..f821271a11467 100644
+--- a/sound/soc/qcom/lpass.h
++++ b/sound/soc/qcom/lpass.h
+@@ -400,7 +400,7 @@ struct lpass_pcm_data {
+
+ /* register the platform driver from the CPU DAI driver */
+ int asoc_qcom_lpass_platform_register(struct platform_device *);
+-int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev);
++void asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev);
+ void asoc_qcom_lpass_cpu_platform_shutdown(struct platform_device *pdev);
+ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev);
+ extern const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops;
+--
+2.39.5
+
--- /dev/null
+From 223fad1b693f6885fafce892a3df5188c3999529 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Apr 2024 16:09:54 +0200
+Subject: ASoC: qcom: q6apm-dai: drop unused 'q6apm_dai_rtd' fields
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit bd381c9d151467e784988bbacf22bd7ca02455d6 ]
+
+Remove few unused fields from 'struct q6apm_dai_rtd'.
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Link: https://lore.kernel.org/r/20240430140954.328127-1-krzysztof.kozlowski@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 3d4a4411aa8b ("ASoC: q6apm-dai: schedule all available frames to avoid dsp under-runs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/qcom/qdsp6/q6apm-dai.c | 10 ++--------
+ 1 file changed, 2 insertions(+), 8 deletions(-)
+
+diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c
+index def05ce58d176..5573802e480ba 100644
+--- a/sound/soc/qcom/qdsp6/q6apm-dai.c
++++ b/sound/soc/qcom/qdsp6/q6apm-dai.c
+@@ -70,14 +70,10 @@ struct q6apm_dai_rtd {
+ unsigned int bytes_received;
+ unsigned int copied_total;
+ uint16_t bits_per_sample;
+- uint16_t source; /* Encoding source bit mask */
+- uint16_t session_id;
+ bool next_track;
+ enum stream_state state;
+ struct q6apm_graph *graph;
+ spinlock_t lock;
+- uint32_t initial_samples_drop;
+- uint32_t trailing_samples_drop;
+ bool notify_on_drain;
+ };
+
+@@ -721,14 +717,12 @@ static int q6apm_dai_compr_set_metadata(struct snd_soc_component *component,
+
+ switch (metadata->key) {
+ case SNDRV_COMPRESS_ENCODER_PADDING:
+- prtd->trailing_samples_drop = metadata->value[0];
+ q6apm_remove_trailing_silence(component->dev, prtd->graph,
+- prtd->trailing_samples_drop);
++ metadata->value[0]);
+ break;
+ case SNDRV_COMPRESS_ENCODER_DELAY:
+- prtd->initial_samples_drop = metadata->value[0];
+ q6apm_remove_initial_silence(component->dev, prtd->graph,
+- prtd->initial_samples_drop);
++ metadata->value[0]);
+ break;
+ default:
+ ret = -EINVAL;
+--
+2.39.5
+
--- /dev/null
+From 0c87d45b50512aa513998bffbe79fd79f46f299b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Mar 2024 22:59:23 +0100
+Subject: auxdisplay: hd44780: Convert to platform remove callback returning
+ void
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+
+[ Upstream commit 9ea02f7cc39d484d16e8a14f3713fefcd33407c0 ]
+
+The .remove() callback for a platform driver returns an int which makes
+many driver authors wrongly assume it's possible to do error handling by
+returning an error code. However the value returned is ignored (apart
+from emitting a warning) and this typically results in resource leaks.
+
+To improve here there is a quest to make the remove callback return
+void. In the first step of this quest all drivers are converted to
+.remove_new(), which already returns void. Eventually after all drivers
+are converted, .remove_new() will be renamed to .remove().
+
+Trivially convert this driver from always returning zero in the remove
+callback to the void returning variant.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Stable-dep-of: 9b98a7d2e5f4 ("auxdisplay: hd44780: Fix an API misuse in hd44780.c")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/auxdisplay/hd44780.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
+index d56a5d508ccd7..7ac0b1b1d5482 100644
+--- a/drivers/auxdisplay/hd44780.c
++++ b/drivers/auxdisplay/hd44780.c
+@@ -319,7 +319,7 @@ static int hd44780_probe(struct platform_device *pdev)
+ return ret;
+ }
+
+-static int hd44780_remove(struct platform_device *pdev)
++static void hd44780_remove(struct platform_device *pdev)
+ {
+ struct charlcd *lcd = platform_get_drvdata(pdev);
+ struct hd44780_common *hdc = lcd->drvdata;
+@@ -329,7 +329,6 @@ static int hd44780_remove(struct platform_device *pdev)
+ kfree(lcd->drvdata);
+
+ kfree(lcd);
+- return 0;
+ }
+
+ static const struct of_device_id hd44780_of_match[] = {
+@@ -340,7 +339,7 @@ MODULE_DEVICE_TABLE(of, hd44780_of_match);
+
+ static struct platform_driver hd44780_driver = {
+ .probe = hd44780_probe,
+- .remove = hd44780_remove,
++ .remove_new = hd44780_remove,
+ .driver = {
+ .name = "hd44780",
+ .of_match_table = hd44780_of_match,
+--
+2.39.5
+
--- /dev/null
+From 5d94c54b7fa06a21c2931fb347571cca3ba3f7fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 18:15:27 +0800
+Subject: auxdisplay: hd44780: Fix an API misuse in hd44780.c
+
+From: Haoxiang Li <haoxiang_li2024@163.com>
+
+[ Upstream commit 9b98a7d2e5f4e2beeff88f6571da0cdc5883c7fb ]
+
+Variable allocated by charlcd_alloc() should be released
+by charlcd_free(). The following patch changed kfree() to
+charlcd_free() to fix an API misuse.
+
+Fixes: 718e05ed92ec ("auxdisplay: Introduce hd44780_common.[ch]")
+Cc: stable@vger.kernel.org
+Signed-off-by: Haoxiang Li <haoxiang_li2024@163.com>
+Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/auxdisplay/hd44780.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
+index 7ac0b1b1d5482..8b690f59df27d 100644
+--- a/drivers/auxdisplay/hd44780.c
++++ b/drivers/auxdisplay/hd44780.c
+@@ -313,7 +313,7 @@ static int hd44780_probe(struct platform_device *pdev)
+ fail3:
+ kfree(hd);
+ fail2:
+- kfree(lcd);
++ charlcd_free(lcd);
+ fail1:
+ kfree(hdc);
+ return ret;
+@@ -328,7 +328,7 @@ static void hd44780_remove(struct platform_device *pdev)
+ kfree(hdc->hd44780);
+ kfree(lcd->drvdata);
+
+- kfree(lcd);
++ charlcd_free(lcd);
+ }
+
+ static const struct of_device_id hd44780_of_match[] = {
+--
+2.39.5
+
--- /dev/null
+From 9d40353865c599c49c9074e6b12d77bab44d12f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jan 2024 12:29:30 +0200
+Subject: clk: renesas: r9a07g04[34]: Fix typo for sel_shdi variable
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 46fb5dd9ca289953fa791b2bb060dac7f8002ae0 ]
+
+Fix typo for sel_shdi variable.
+
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/20240131102930.1841901-3-claudiu.beznea.uj@bp.renesas.com
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/renesas/r9a07g043-cpg.c | 6 +++---
+ drivers/clk/renesas/r9a07g044-cpg.c | 6 +++---
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c
+index 9ad7ceb3ab1ba..3a717dcecba56 100644
+--- a/drivers/clk/renesas/r9a07g043-cpg.c
++++ b/drivers/clk/renesas/r9a07g043-cpg.c
+@@ -87,7 +87,7 @@ static const struct clk_div_table dtable_1_32[] = {
+ /* Mux clock tables */
+ static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" };
+ static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
+-static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
++static const char * const sel_sdhi[] = { ".clk_533", ".clk_400", ".clk_266" };
+
+ static const u32 mtable_sdhi[] = { 1, 2, 3 };
+
+@@ -136,9 +136,9 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = {
+ DEF_MUX("HP", R9A07G043_CLK_HP, SEL_PLL6_2, sel_pll6_2),
+ DEF_FIXED("SPI0", R9A07G043_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2),
+ DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
+- DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi,
++ DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_sdhi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+- DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_shdi,
++ DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_sdhi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4),
+ DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4),
+diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c
+index bc822b9fd7ce6..48404cafea3f5 100644
+--- a/drivers/clk/renesas/r9a07g044-cpg.c
++++ b/drivers/clk/renesas/r9a07g044-cpg.c
+@@ -106,7 +106,7 @@ static const struct clk_div_table dtable_16_128[] = {
+ static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" };
+ static const char * const sel_pll5_4[] = { ".pll5_foutpostdiv", ".pll5_fout1ph0" };
+ static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
+-static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
++static const char * const sel_sdhi[] = { ".clk_533", ".clk_400", ".clk_266" };
+ static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" };
+
+ static const u32 mtable_sdhi[] = { 1, 2, 3 };
+@@ -176,9 +176,9 @@ static const struct {
+ DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, sel_pll6_2),
+ DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2),
+ DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
+- DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi,
++ DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_sdhi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+- DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_shdi,
++ DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_sdhi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4),
+ DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4),
+--
+2.39.5
+
--- /dev/null
+From 858f7fb5ed155ed2a5d614fa73526b139d68a5c4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jan 2024 12:29:29 +0200
+Subject: clk: renesas: r9a07g04[34]: Use SEL_SDHI1_STS status configuration
+ for SD1 mux
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 9b2a11c83859c06233049b134bd8ee974b284559 ]
+
+The status configuration for SD1 mux clock is SEL_SDHI1_STS. Fix it.
+
+Fixes: 16b86e5c03c5 ("clk: renesas: rzg2l: Refactor SD mux driver")
+Reported-by: Hien Huynh <hien.huynh.px@renesas.com>
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/20240131102930.1841901-2-claudiu.beznea.uj@bp.renesas.com
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/renesas/r9a07g043-cpg.c | 2 +-
+ drivers/clk/renesas/r9a07g044-cpg.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c
+index 55c58b9a9b804..9ad7ceb3ab1ba 100644
+--- a/drivers/clk/renesas/r9a07g043-cpg.c
++++ b/drivers/clk/renesas/r9a07g043-cpg.c
+@@ -138,7 +138,7 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = {
+ DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
+ DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+- DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi,
++ DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_shdi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4),
+ DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4),
+diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c
+index 1047278c9079a..bc822b9fd7ce6 100644
+--- a/drivers/clk/renesas/r9a07g044-cpg.c
++++ b/drivers/clk/renesas/r9a07g044-cpg.c
+@@ -178,7 +178,7 @@ static const struct {
+ DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
+ DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+- DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi,
++ DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI1_STS, sel_shdi,
+ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4),
+ DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4),
+--
+2.39.5
+
--- /dev/null
+From bac26a05796cebd5ca41ee5bd29bd0381a81a4f6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jan 2025 17:31:59 +0000
+Subject: clk: renesas: r9a07g043: Fix HP clock source for RZ/Five
+
+From: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+
+[ Upstream commit 7f22a298d926664b51fcfe2f8ea5feb7f8b79952 ]
+
+According to the Rev.1.20 hardware manual for the RZ/Five SoC, the clock
+source for HP is derived from PLL6 divided by 2. Correct the
+implementation by configuring HP as a fixed clock source instead of a
+MUX.
+
+The `CPG_PL6_ETH_SSEL' register, which is available on the RZ/G2UL SoC,
+is not present on the RZ/Five SoC, necessitating this change.
+
+Fixes: 95d48d270305ad2c ("clk: renesas: r9a07g043: Add support for RZ/Five SoC")
+Cc: stable@vger.kernel.org
+Reported-by: Hien Huynh <hien.huynh.px@renesas.com>
+Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/20250127173159.34572-1-prabhakar.mahadev-lad.rj@bp.renesas.com
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/renesas/r9a07g043-cpg.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c
+index 3a717dcecba56..865d47800791b 100644
+--- a/drivers/clk/renesas/r9a07g043-cpg.c
++++ b/drivers/clk/renesas/r9a07g043-cpg.c
+@@ -86,7 +86,9 @@ static const struct clk_div_table dtable_1_32[] = {
+
+ /* Mux clock tables */
+ static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" };
++#ifdef CONFIG_ARM64
+ static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
++#endif
+ static const char * const sel_sdhi[] = { ".clk_533", ".clk_400", ".clk_266" };
+
+ static const u32 mtable_sdhi[] = { 1, 2, 3 };
+@@ -133,7 +135,12 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = {
+ DEF_DIV("P2", R9A07G043_CLK_P2, CLK_PLL3_DIV2_4_2, DIVPL3A, dtable_1_32),
+ DEF_FIXED("M0", R9A07G043_CLK_M0, CLK_PLL3_DIV2_4, 1, 1),
+ DEF_FIXED("ZT", R9A07G043_CLK_ZT, CLK_PLL3_DIV2_4_2, 1, 1),
++#ifdef CONFIG_ARM64
+ DEF_MUX("HP", R9A07G043_CLK_HP, SEL_PLL6_2, sel_pll6_2),
++#endif
++#ifdef CONFIG_RISCV
++ DEF_FIXED("HP", R9A07G043_CLK_HP, CLK_PLL6_250, 1, 1),
++#endif
+ DEF_FIXED("SPI0", R9A07G043_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2),
+ DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
+ DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_sdhi,
+--
+2.39.5
+
--- /dev/null
+From 25f99f7d19c9237677792a2cc640d9e7fe5ba0c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Sep 2023 08:38:55 +0300
+Subject: clk: renesas: rzg2l: Add struct clk_hw_data
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 97c1c4ccda76d2919775d748cf223637cf0e82ae ]
+
+Add clk_hw_data struct that keeps the core part of the clock data.
+sd_hw_data embeds a member of type struct clk_hw_data along with other
+members (in the next commits). This commit prepares the field for
+refactoring the SD MUX clock driver.
+
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/20230929053915.1530607-9-claudiu.beznea@bp.renesas.com
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/renesas/rzg2l-cpg.c | 52 +++++++++++++++++++++------------
+ 1 file changed, 34 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
+index f8dbb092b9f1b..280d61f1e174c 100644
+--- a/drivers/clk/renesas/rzg2l-cpg.c
++++ b/drivers/clk/renesas/rzg2l-cpg.c
+@@ -58,13 +58,29 @@
+
+ #define MAX_VCLK_FREQ (148500000)
+
+-struct sd_hw_data {
++/**
++ * struct clk_hw_data - clock hardware data
++ * @hw: clock hw
++ * @conf: clock configuration (register offset, shift, width)
++ * @priv: CPG private data structure
++ */
++struct clk_hw_data {
+ struct clk_hw hw;
+ u32 conf;
+ struct rzg2l_cpg_priv *priv;
+ };
+
+-#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw)
++#define to_clk_hw_data(_hw) container_of(_hw, struct clk_hw_data, hw)
++
++/**
++ * struct sd_hw_data - SD clock hardware data
++ * @hw_data: clock hw data
++ */
++struct sd_hw_data {
++ struct clk_hw_data hw_data;
++};
++
++#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw_data)
+
+ struct rzg2l_pll5_param {
+ u32 pl5_fracin;
+@@ -183,10 +199,10 @@ rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core,
+
+ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+ {
+- struct sd_hw_data *hwdata = to_sd_hw_data(hw);
+- struct rzg2l_cpg_priv *priv = hwdata->priv;
+- u32 off = GET_REG_OFFSET(hwdata->conf);
+- u32 shift = GET_SHIFT(hwdata->conf);
++ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
++ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
++ u32 off = GET_REG_OFFSET(clk_hw_data->conf);
++ u32 shift = GET_SHIFT(clk_hw_data->conf);
+ const u32 clk_src_266 = 2;
+ u32 msk, val, bitmask;
+ unsigned long flags;
+@@ -203,7 +219,7 @@ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+ * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and
+ * the index to value mapping is done by adding 1 to the index.
+ */
+- bitmask = (GENMASK(GET_WIDTH(hwdata->conf) - 1, 0) << shift) << 16;
++ bitmask = (GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0) << shift) << 16;
+ msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS;
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+ if (index != clk_src_266) {
+@@ -232,12 +248,12 @@ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+
+ static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw)
+ {
+- struct sd_hw_data *hwdata = to_sd_hw_data(hw);
+- struct rzg2l_cpg_priv *priv = hwdata->priv;
+- u32 val = readl(priv->base + GET_REG_OFFSET(hwdata->conf));
++ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
++ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
++ u32 val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf));
+
+- val >>= GET_SHIFT(hwdata->conf);
+- val &= GENMASK(GET_WIDTH(hwdata->conf) - 1, 0);
++ val >>= GET_SHIFT(clk_hw_data->conf);
++ val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0);
+
+ return val ? val - 1 : 0;
+ }
+@@ -253,17 +269,17 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core,
+ void __iomem *base,
+ struct rzg2l_cpg_priv *priv)
+ {
+- struct sd_hw_data *clk_hw_data;
++ struct sd_hw_data *sd_hw_data;
+ struct clk_init_data init;
+ struct clk_hw *clk_hw;
+ int ret;
+
+- clk_hw_data = devm_kzalloc(priv->dev, sizeof(*clk_hw_data), GFP_KERNEL);
+- if (!clk_hw_data)
++ sd_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_hw_data), GFP_KERNEL);
++ if (!sd_hw_data)
+ return ERR_PTR(-ENOMEM);
+
+- clk_hw_data->priv = priv;
+- clk_hw_data->conf = core->conf;
++ sd_hw_data->hw_data.priv = priv;
++ sd_hw_data->hw_data.conf = core->conf;
+
+ init.name = GET_SHIFT(core->conf) ? "sd1" : "sd0";
+ init.ops = &rzg2l_cpg_sd_clk_mux_ops;
+@@ -271,7 +287,7 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core,
+ init.num_parents = core->num_parents;
+ init.parent_names = core->parent_names;
+
+- clk_hw = &clk_hw_data->hw;
++ clk_hw = &sd_hw_data->hw_data.hw;
+ clk_hw->init = &init;
+
+ ret = devm_clk_hw_register(priv->dev, clk_hw);
+--
+2.39.5
+
--- /dev/null
+From 5d8c3205387fa88daad4d14dd108caaa828a094e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Oct 2023 13:39:57 +0300
+Subject: clk: renesas: rzg2l: Refactor SD mux driver
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 16b86e5c03c5b3ef35bf5126b35384faa97428f0 ]
+
+Refactor SD MUX driver to be able to reuse the same code on RZ/G3S.
+RZ/G2{L,UL} has a limitation with regards to switching the clock source
+for SD MUX (MUX clock source has to be switched to 266MHz before
+switching b/w 533MHz and 400MHz). Rework the handling of this limitation
+to use a clock notifier that is registered according to platform based
+initialization data, so the SD MUX code can be reused on RZ/G3S.
+
+As RZ/G2{L,UL} and RZ/G3S use different bits in different registers to
+check if the clock switching has been done, this configuration (register
+offset, register bits and bitfield width) is now passed through struct
+cpg_core_clk::sconf (status configuration) from platform specific
+initialization code.
+
+Along with struct cpg_core_clk::sconf the mux table indices are also
+passed from platform specific initialization code.
+
+Also, mux flags are now passed to DEF_SD_MUX() as they will be used
+later by RZ/G3S.
+
+CPG_WEN_BIT macro has been introduced to select properly the WEN bit
+of various registers.
+
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/20231006103959.197485-3-claudiu.beznea.uj@bp.renesas.com
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/renesas/r9a07g043-cpg.c | 12 ++-
+ drivers/clk/renesas/r9a07g044-cpg.c | 12 ++-
+ drivers/clk/renesas/rzg2l-cpg.c | 150 ++++++++++++++++++++--------
+ drivers/clk/renesas/rzg2l-cpg.h | 16 ++-
+ 4 files changed, 139 insertions(+), 51 deletions(-)
+
+diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c
+index 8181ddf652fdc..55c58b9a9b804 100644
+--- a/drivers/clk/renesas/r9a07g043-cpg.c
++++ b/drivers/clk/renesas/r9a07g043-cpg.c
+@@ -21,6 +21,10 @@
+ #define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2)
+ #define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2)
+
++/* Clock status configuration. */
++#define SEL_SDHI0_STS SEL_PLL_PACK(CPG_CLKSTATUS, 28, 1)
++#define SEL_SDHI1_STS SEL_PLL_PACK(CPG_CLKSTATUS, 29, 1)
++
+ enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A07G043_CLK_P0_DIV2,
+@@ -85,6 +89,8 @@ static const char * const sel_pll3_3[] = { ".pll3_533", ".pll3_400" };
+ static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
+ static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
+
++static const u32 mtable_sdhi[] = { 1, 2, 3 };
++
+ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = {
+ /* External Clock Inputs */
+ DEF_INPUT("extal", CLK_EXTAL),
+@@ -130,8 +136,10 @@ static const struct cpg_core_clk r9a07g043_core_clks[] __initconst = {
+ DEF_MUX("HP", R9A07G043_CLK_HP, SEL_PLL6_2, sel_pll6_2),
+ DEF_FIXED("SPI0", R9A07G043_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2),
+ DEF_FIXED("SPI1", R9A07G043_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
+- DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, sel_shdi),
+- DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, sel_shdi),
++ DEF_SD_MUX("SD0", R9A07G043_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi,
++ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
++ DEF_SD_MUX("SD1", R9A07G043_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi,
++ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G043_CLK_SD0, 1, 4),
+ DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G043_CLK_SD1, 1, 4),
+ };
+diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c
+index d4dcf5d896d40..1047278c9079a 100644
+--- a/drivers/clk/renesas/r9a07g044-cpg.c
++++ b/drivers/clk/renesas/r9a07g044-cpg.c
+@@ -22,6 +22,10 @@
+ #define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2)
+ #define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2)
+
++/* Clock status configuration. */
++#define SEL_SDHI0_STS SEL_PLL_PACK(CPG_CLKSTATUS, 28, 1)
++#define SEL_SDHI1_STS SEL_PLL_PACK(CPG_CLKSTATUS, 29, 1)
++
+ enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A07G054_CLK_DRP_A,
+@@ -105,6 +109,8 @@ static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" };
+ static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" };
+ static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" };
+
++static const u32 mtable_sdhi[] = { 1, 2, 3 };
++
+ static const struct {
+ struct cpg_core_clk common[56];
+ #ifdef CONFIG_CLK_R9A07G054
+@@ -170,8 +176,10 @@ static const struct {
+ DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, sel_pll6_2),
+ DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2),
+ DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4),
+- DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, sel_shdi),
+- DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, sel_shdi),
++ DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, SEL_SDHI0_STS, sel_shdi,
++ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
++ DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, SEL_SDHI0_STS, sel_shdi,
++ mtable_sdhi, 0, rzg2l_cpg_sd_clk_mux_notifier),
+ DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4),
+ DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4),
+ DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8),
+diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
+index 280d61f1e174c..77eefb6ee4538 100644
+--- a/drivers/clk/renesas/rzg2l-cpg.c
++++ b/drivers/clk/renesas/rzg2l-cpg.c
+@@ -56,31 +56,37 @@
+ #define GET_REG_SAMPLL_CLK1(val) ((val >> 22) & 0xfff)
+ #define GET_REG_SAMPLL_CLK2(val) ((val >> 12) & 0xfff)
+
++#define CPG_WEN_BIT BIT(16)
++
+ #define MAX_VCLK_FREQ (148500000)
+
+ /**
+ * struct clk_hw_data - clock hardware data
+ * @hw: clock hw
+ * @conf: clock configuration (register offset, shift, width)
++ * @sconf: clock status configuration (register offset, shift, width)
+ * @priv: CPG private data structure
+ */
+ struct clk_hw_data {
+ struct clk_hw hw;
+ u32 conf;
++ u32 sconf;
+ struct rzg2l_cpg_priv *priv;
+ };
+
+ #define to_clk_hw_data(_hw) container_of(_hw, struct clk_hw_data, hw)
+
+ /**
+- * struct sd_hw_data - SD clock hardware data
++ * struct sd_mux_hw_data - SD MUX clock hardware data
+ * @hw_data: clock hw data
++ * @mtable: clock mux table
+ */
+-struct sd_hw_data {
++struct sd_mux_hw_data {
+ struct clk_hw_data hw_data;
++ const u32 *mtable;
+ };
+
+-#define to_sd_hw_data(_hw) container_of(_hw, struct sd_hw_data, hw_data)
++#define to_sd_mux_hw_data(_hw) container_of(_hw, struct sd_mux_hw_data, hw_data)
+
+ struct rzg2l_pll5_param {
+ u32 pl5_fracin;
+@@ -137,6 +143,76 @@ static void rzg2l_cpg_del_clk_provider(void *data)
+ of_clk_del_provider(data);
+ }
+
++/* Must be called in atomic context. */
++static int rzg2l_cpg_wait_clk_update_done(void __iomem *base, u32 conf)
++{
++ u32 bitmask = GENMASK(GET_WIDTH(conf) - 1, 0) << GET_SHIFT(conf);
++ u32 off = GET_REG_OFFSET(conf);
++ u32 val;
++
++ return readl_poll_timeout_atomic(base + off, val, !(val & bitmask), 10, 200);
++}
++
++int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event,
++ void *data)
++{
++ struct clk_notifier_data *cnd = data;
++ struct clk_hw *hw = __clk_get_hw(cnd->clk);
++ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
++ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
++ u32 off = GET_REG_OFFSET(clk_hw_data->conf);
++ u32 shift = GET_SHIFT(clk_hw_data->conf);
++ const u32 clk_src_266 = 3;
++ unsigned long flags;
++ int ret;
++
++ if (event != PRE_RATE_CHANGE || (cnd->new_rate / MEGA == 266))
++ return NOTIFY_DONE;
++
++ spin_lock_irqsave(&priv->rmw_lock, flags);
++
++ /*
++ * As per the HW manual, we should not directly switch from 533 MHz to
++ * 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz)
++ * to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first,
++ * and then switch to the target setting (2’b01 (533 MHz) or 2’b10
++ * (400 MHz)).
++ * Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock
++ * switching register is prohibited.
++ * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and
++ * the index to value mapping is done by adding 1 to the index.
++ */
++
++ writel((CPG_WEN_BIT | clk_src_266) << shift, priv->base + off);
++
++ /* Wait for the update done. */
++ ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf);
++
++ spin_unlock_irqrestore(&priv->rmw_lock, flags);
++
++ if (ret)
++ dev_err(priv->dev, "failed to switch to safe clk source\n");
++
++ return notifier_from_errno(ret);
++}
++
++static int rzg2l_register_notifier(struct clk_hw *hw, const struct cpg_core_clk *core,
++ struct rzg2l_cpg_priv *priv)
++{
++ struct notifier_block *nb;
++
++ if (!core->notifier)
++ return 0;
++
++ nb = devm_kzalloc(priv->dev, sizeof(*nb), GFP_KERNEL);
++ if (!nb)
++ return -ENOMEM;
++
++ nb->notifier_call = core->notifier;
++
++ return clk_notifier_register(hw->clk, nb);
++}
++
+ static struct clk * __init
+ rzg2l_cpg_div_clk_register(const struct cpg_core_clk *core,
+ struct clk **clks,
+@@ -200,48 +276,27 @@ rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core,
+ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+ {
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
++ struct sd_mux_hw_data *sd_mux_hw_data = to_sd_mux_hw_data(clk_hw_data);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+ u32 off = GET_REG_OFFSET(clk_hw_data->conf);
+ u32 shift = GET_SHIFT(clk_hw_data->conf);
+- const u32 clk_src_266 = 2;
+- u32 msk, val, bitmask;
+ unsigned long flags;
++ u32 val;
+ int ret;
+
+- /*
+- * As per the HW manual, we should not directly switch from 533 MHz to
+- * 400 MHz and vice versa. To change the setting from 2’b01 (533 MHz)
+- * to 2’b10 (400 MHz) or vice versa, Switch to 2’b11 (266 MHz) first,
+- * and then switch to the target setting (2’b01 (533 MHz) or 2’b10
+- * (400 MHz)).
+- * Setting a value of '0' to the SEL_SDHI0_SET or SEL_SDHI1_SET clock
+- * switching register is prohibited.
+- * The clock mux has 3 input clocks(533 MHz, 400 MHz, and 266 MHz), and
+- * the index to value mapping is done by adding 1 to the index.
+- */
+- bitmask = (GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0) << shift) << 16;
+- msk = off ? CPG_CLKSTATUS_SELSDHI1_STS : CPG_CLKSTATUS_SELSDHI0_STS;
++ val = clk_mux_index_to_val(sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, index);
++
+ spin_lock_irqsave(&priv->rmw_lock, flags);
+- if (index != clk_src_266) {
+- writel(bitmask | ((clk_src_266 + 1) << shift), priv->base + off);
+-
+- ret = readl_poll_timeout_atomic(priv->base + CPG_CLKSTATUS, val,
+- !(val & msk), 10,
+- CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
+- if (ret)
+- goto unlock;
+- }
+
+- writel(bitmask | ((index + 1) << shift), priv->base + off);
++ writel((CPG_WEN_BIT | val) << shift, priv->base + off);
++
++ /* Wait for the update done. */
++ ret = rzg2l_cpg_wait_clk_update_done(priv->base, clk_hw_data->sconf);
+
+- ret = readl_poll_timeout_atomic(priv->base + CPG_CLKSTATUS, val,
+- !(val & msk), 10,
+- CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US);
+-unlock:
+ spin_unlock_irqrestore(&priv->rmw_lock, flags);
+
+ if (ret)
+- dev_err(priv->dev, "failed to switch clk source\n");
++ dev_err(priv->dev, "Failed to switch parent\n");
+
+ return ret;
+ }
+@@ -249,13 +304,15 @@ static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
+ static u8 rzg2l_cpg_sd_clk_mux_get_parent(struct clk_hw *hw)
+ {
+ struct clk_hw_data *clk_hw_data = to_clk_hw_data(hw);
++ struct sd_mux_hw_data *sd_mux_hw_data = to_sd_mux_hw_data(clk_hw_data);
+ struct rzg2l_cpg_priv *priv = clk_hw_data->priv;
+- u32 val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf));
++ u32 val;
+
++ val = readl(priv->base + GET_REG_OFFSET(clk_hw_data->conf));
+ val >>= GET_SHIFT(clk_hw_data->conf);
+ val &= GENMASK(GET_WIDTH(clk_hw_data->conf) - 1, 0);
+
+- return val ? val - 1 : 0;
++ return clk_mux_val_to_index(hw, sd_mux_hw_data->mtable, CLK_MUX_ROUND_CLOSEST, val);
+ }
+
+ static const struct clk_ops rzg2l_cpg_sd_clk_mux_ops = {
+@@ -269,31 +326,40 @@ rzg2l_cpg_sd_mux_clk_register(const struct cpg_core_clk *core,
+ void __iomem *base,
+ struct rzg2l_cpg_priv *priv)
+ {
+- struct sd_hw_data *sd_hw_data;
++ struct sd_mux_hw_data *sd_mux_hw_data;
+ struct clk_init_data init;
+ struct clk_hw *clk_hw;
+ int ret;
+
+- sd_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_hw_data), GFP_KERNEL);
+- if (!sd_hw_data)
++ sd_mux_hw_data = devm_kzalloc(priv->dev, sizeof(*sd_mux_hw_data), GFP_KERNEL);
++ if (!sd_mux_hw_data)
+ return ERR_PTR(-ENOMEM);
+
+- sd_hw_data->hw_data.priv = priv;
+- sd_hw_data->hw_data.conf = core->conf;
++ sd_mux_hw_data->hw_data.priv = priv;
++ sd_mux_hw_data->hw_data.conf = core->conf;
++ sd_mux_hw_data->hw_data.sconf = core->sconf;
++ sd_mux_hw_data->mtable = core->mtable;
+
+ init.name = GET_SHIFT(core->conf) ? "sd1" : "sd0";
+ init.ops = &rzg2l_cpg_sd_clk_mux_ops;
+- init.flags = 0;
++ init.flags = core->flag;
+ init.num_parents = core->num_parents;
+ init.parent_names = core->parent_names;
+
+- clk_hw = &sd_hw_data->hw_data.hw;
++ clk_hw = &sd_mux_hw_data->hw_data.hw;
+ clk_hw->init = &init;
+
+ ret = devm_clk_hw_register(priv->dev, clk_hw);
+ if (ret)
+ return ERR_PTR(ret);
+
++ ret = rzg2l_register_notifier(clk_hw, core, priv);
++ if (ret) {
++ dev_err(priv->dev, "Failed to register notifier for %s\n",
++ core->name);
++ return ERR_PTR(ret);
++ }
++
+ return clk_hw->clk;
+ }
+
+diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
+index 705898bef438c..e662459cc6d96 100644
+--- a/drivers/clk/renesas/rzg2l-cpg.h
++++ b/drivers/clk/renesas/rzg2l-cpg.h
+@@ -9,6 +9,8 @@
+ #ifndef __RENESAS_RZG2L_CPG_H__
+ #define __RENESAS_RZG2L_CPG_H__
+
++#include <linux/notifier.h>
++
+ #define CPG_SIPLL5_STBY (0x140)
+ #define CPG_SIPLL5_CLK1 (0x144)
+ #define CPG_SIPLL5_CLK3 (0x14C)
+@@ -42,8 +44,6 @@
+ #define CPG_CLKSTATUS_SELSDHI0_STS BIT(28)
+ #define CPG_CLKSTATUS_SELSDHI1_STS BIT(29)
+
+-#define CPG_SDHI_CLK_SWITCH_STATUS_TIMEOUT_US 200
+-
+ /* n = 0/1/2 for PLL1/4/6 */
+ #define CPG_SAMPLL_CLK1(n) (0x04 + (16 * n))
+ #define CPG_SAMPLL_CLK2(n) (0x08 + (16 * n))
+@@ -86,8 +86,11 @@ struct cpg_core_clk {
+ unsigned int mult;
+ unsigned int type;
+ unsigned int conf;
++ unsigned int sconf;
+ const struct clk_div_table *dtable;
++ const u32 *mtable;
+ const char * const *parent_names;
++ notifier_fn_t notifier;
+ u32 flag;
+ u32 mux_flags;
+ int num_parents;
+@@ -147,10 +150,11 @@ enum clk_types {
+ .parent_names = _parent_names, \
+ .num_parents = ARRAY_SIZE(_parent_names), \
+ .mux_flags = CLK_MUX_READ_ONLY)
+-#define DEF_SD_MUX(_name, _id, _conf, _parent_names) \
+- DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, \
++#define DEF_SD_MUX(_name, _id, _conf, _sconf, _parent_names, _mtable, _clk_flags, _notifier) \
++ DEF_TYPE(_name, _id, CLK_TYPE_SD_MUX, .conf = _conf, .sconf = _sconf, \
+ .parent_names = _parent_names, \
+- .num_parents = ARRAY_SIZE(_parent_names))
++ .num_parents = ARRAY_SIZE(_parent_names), \
++ .mtable = _mtable, .flag = _clk_flags, .notifier = _notifier)
+ #define DEF_PLL5_FOUTPOSTDIV(_name, _id, _parent) \
+ DEF_TYPE(_name, _id, CLK_TYPE_SIPLL5, .parent = _parent)
+ #define DEF_PLL5_4_MUX(_name, _id, _conf, _parent_names) \
+@@ -269,4 +273,6 @@ extern const struct rzg2l_cpg_info r9a07g044_cpg_info;
+ extern const struct rzg2l_cpg_info r9a07g054_cpg_info;
+ extern const struct rzg2l_cpg_info r9a09g011_cpg_info;
+
++int rzg2l_cpg_sd_clk_mux_notifier(struct notifier_block *nb, unsigned long event, void *data);
++
+ #endif
+--
+2.39.5
+
--- /dev/null
+From 284cf9002b5ba9ae790bcce856d597906dfc1211 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Sep 2023 08:38:56 +0300
+Subject: clk: renesas: rzg2l: Remove CPG_SDHI_DSEL from generic header
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 3e8008fcf6b7f7c65ad2718c18fb79f37007f1a5 ]
+
+Remove CPG_SDHI_DSEL and its bits from the generic header as RZ/G3S has
+different offset registers and bits for this, thus avoid mixing them.
+
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/20230929053915.1530607-10-claudiu.beznea@bp.renesas.com
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/renesas/r9a07g043-cpg.c | 7 +++++++
+ drivers/clk/renesas/r9a07g044-cpg.c | 7 +++++++
+ drivers/clk/renesas/rzg2l-cpg.h | 4 ----
+ 3 files changed, 14 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c
+index 6c6bc79b2e9ce..8181ddf652fdc 100644
+--- a/drivers/clk/renesas/r9a07g043-cpg.c
++++ b/drivers/clk/renesas/r9a07g043-cpg.c
+@@ -14,6 +14,13 @@
+
+ #include "rzg2l-cpg.h"
+
++/* Specific registers. */
++#define CPG_PL2SDHI_DSEL (0x218)
++
++/* Clock select configuration. */
++#define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2)
++#define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2)
++
+ enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A07G043_CLK_P0_DIV2,
+diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c
+index c597414a94d8a..d4dcf5d896d40 100644
+--- a/drivers/clk/renesas/r9a07g044-cpg.c
++++ b/drivers/clk/renesas/r9a07g044-cpg.c
+@@ -15,6 +15,13 @@
+
+ #include "rzg2l-cpg.h"
+
++/* Specific registers. */
++#define CPG_PL2SDHI_DSEL (0x218)
++
++/* Clock select configuration. */
++#define SEL_SDHI0 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 0, 2)
++#define SEL_SDHI1 SEL_PLL_PACK(CPG_PL2SDHI_DSEL, 4, 2)
++
+ enum clk_ids {
+ /* Core Clock Outputs exported to DT */
+ LAST_DT_CORE_CLK = R9A07G054_CLK_DRP_A,
+diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
+index 097fd8f616806..705898bef438c 100644
+--- a/drivers/clk/renesas/rzg2l-cpg.h
++++ b/drivers/clk/renesas/rzg2l-cpg.h
+@@ -19,7 +19,6 @@
+ #define CPG_PL2_DDIV (0x204)
+ #define CPG_PL3A_DDIV (0x208)
+ #define CPG_PL6_DDIV (0x210)
+-#define CPG_PL2SDHI_DSEL (0x218)
+ #define CPG_CLKSTATUS (0x280)
+ #define CPG_PL3_SSEL (0x408)
+ #define CPG_PL6_SSEL (0x414)
+@@ -69,9 +68,6 @@
+ #define SEL_PLL6_2 SEL_PLL_PACK(CPG_PL6_ETH_SSEL, 0, 1)
+ #define SEL_GPU2 SEL_PLL_PACK(CPG_PL6_SSEL, 12, 1)
+
+-#define SEL_SDHI0 DDIV_PACK(CPG_PL2SDHI_DSEL, 0, 2)
+-#define SEL_SDHI1 DDIV_PACK(CPG_PL2SDHI_DSEL, 4, 2)
+-
+ #define EXTAL_FREQ_IN_MEGA_HZ (24)
+
+ /**
+--
+2.39.5
+
--- /dev/null
+From 0983110b896d891c66360dedb6730af4ac7bae61 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 07:51:34 +0300
+Subject: clk: renesas: rzg2l: Use u32 for flag and mux_flags
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 897a3e34d6e73d2386715d5c44c57992f2c0eada ]
+
+flag and mux_flags are intended to keep bit masks. Use u32 type for it.
+
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lore.kernel.org/r/20230912045157.177966-15-claudiu.beznea.uj@bp.renesas.com
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/clk/renesas/rzg2l-cpg.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
+index 91e9c2569f801..097fd8f616806 100644
+--- a/drivers/clk/renesas/rzg2l-cpg.h
++++ b/drivers/clk/renesas/rzg2l-cpg.h
+@@ -92,8 +92,8 @@ struct cpg_core_clk {
+ unsigned int conf;
+ const struct clk_div_table *dtable;
+ const char * const *parent_names;
+- int flag;
+- int mux_flags;
++ u32 flag;
++ u32 mux_flags;
+ int num_parents;
+ };
+
+--
+2.39.5
+
--- /dev/null
+From 729d8d5b761338514acf024014418fbfc19fca5c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Apr 2025 11:59:15 +0200
+Subject: cpufreq/sched: Explicitly synchronize limits_changed flag handling
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit 79443a7e9da3c9f68290a8653837e23aba0fa89f ]
+
+The handling of the limits_changed flag in struct sugov_policy needs to
+be explicitly synchronized to ensure that cpufreq policy limits updates
+will not be missed in some cases.
+
+Without that synchronization it is theoretically possible that
+the limits_changed update in sugov_should_update_freq() will be
+reordered with respect to the reads of the policy limits in
+cpufreq_driver_resolve_freq() and in that case, if the limits_changed
+update in sugov_limits() clobbers the one in sugov_should_update_freq(),
+the new policy limits may not take effect for a long time.
+
+Likewise, the limits_changed update in sugov_limits() may theoretically
+get reordered with respect to the updates of the policy limits in
+cpufreq_set_policy() and if sugov_should_update_freq() runs between
+them, the policy limits change may be missed.
+
+To ensure that the above situations will not take place, add memory
+barriers preventing the reordering in question from taking place and
+add READ_ONCE() and WRITE_ONCE() annotations around all of the
+limits_changed flag updates to prevent the compiler from messing up
+with that code.
+
+Fixes: 600f5badb78c ("cpufreq: schedutil: Don't skip freq update when limits change")
+Cc: 5.3+ <stable@vger.kernel.org> # 5.3+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Christian Loehle <christian.loehle@arm.com>
+Link: https://patch.msgid.link/3376719.44csPzL39Z@rjwysocki.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/cpufreq_schedutil.c | 28 ++++++++++++++++++++++++----
+ 1 file changed, 24 insertions(+), 4 deletions(-)
+
+diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
+index f84473f73ed00..776be0549162c 100644
+--- a/kernel/sched/cpufreq_schedutil.c
++++ b/kernel/sched/cpufreq_schedutil.c
+@@ -81,9 +81,20 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
+ if (!cpufreq_this_cpu_can_update(sg_policy->policy))
+ return false;
+
+- if (unlikely(sg_policy->limits_changed)) {
+- sg_policy->limits_changed = false;
++ if (unlikely(READ_ONCE(sg_policy->limits_changed))) {
++ WRITE_ONCE(sg_policy->limits_changed, false);
+ sg_policy->need_freq_update = true;
++
++ /*
++ * The above limits_changed update must occur before the reads
++ * of policy limits in cpufreq_driver_resolve_freq() or a policy
++ * limits update might be missed, so use a memory barrier to
++ * ensure it.
++ *
++ * This pairs with the write memory barrier in sugov_limits().
++ */
++ smp_mb();
++
+ return true;
+ }
+
+@@ -334,7 +345,7 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; }
+ static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu)
+ {
+ if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_min)
+- sg_cpu->sg_policy->limits_changed = true;
++ WRITE_ONCE(sg_cpu->sg_policy->limits_changed, true);
+ }
+
+ static inline bool sugov_update_single_common(struct sugov_cpu *sg_cpu,
+@@ -844,7 +855,16 @@ static void sugov_limits(struct cpufreq_policy *policy)
+ mutex_unlock(&sg_policy->work_lock);
+ }
+
+- sg_policy->limits_changed = true;
++ /*
++ * The limits_changed update below must take place before the updates
++ * of policy limits in cpufreq_set_policy() or a policy limits update
++ * might be missed, so use a memory barrier to ensure it.
++ *
++ * This pairs with the memory barrier in sugov_should_update_freq().
++ */
++ smp_wmb();
++
++ WRITE_ONCE(sg_policy->limits_changed, true);
+ }
+
+ struct cpufreq_governor schedutil_gov = {
+--
+2.39.5
+
--- /dev/null
+From e89390d52a59a6ac1ad6595a78fca9808a72fcdd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Mar 2025 18:00:29 -0300
+Subject: iio: adc: ad7768-1: Fix conversion result sign
+
+From: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
+
+[ Upstream commit 8236644f5ecb180e80ad92d691c22bc509b747bb ]
+
+The ad7768-1 ADC output code is two's complement, meaning that the voltage
+conversion result is a signed value.. Since the value is a 24 bit one,
+stored in a 32 bit variable, the sign should be extended in order to get
+the correct representation.
+
+Also the channel description has been updated to signed representation,
+to match the ADC specifications.
+
+Fixes: a5f8c7da3dbe ("iio: adc: Add AD7768-1 ADC basic support")
+Reviewed-by: David Lechner <dlechner@baylibre.com>
+Reviewed-by: Marcelo Schmitt <marcelo.schmitt@analog.com>
+Signed-off-by: Sergiu Cuciurean <sergiu.cuciurean@analog.com>
+Signed-off-by: Jonathan Santos <Jonathan.Santos@analog.com>
+Cc: <Stable@vger.kernel.org>
+Link: https://patch.msgid.link/505994d3b71c2aa38ba714d909a68e021f12124c.1741268122.git.Jonathan.Santos@analog.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/ad7768-1.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
+index 19d604f5701d6..74b0c85944bd6 100644
+--- a/drivers/iio/adc/ad7768-1.c
++++ b/drivers/iio/adc/ad7768-1.c
+@@ -142,7 +142,7 @@ static const struct iio_chan_spec ad7768_channels[] = {
+ .channel = 0,
+ .scan_index = 0,
+ .scan_type = {
+- .sign = 'u',
++ .sign = 's',
+ .realbits = 24,
+ .storagebits = 32,
+ .shift = 8,
+@@ -374,7 +374,7 @@ static int ad7768_read_raw(struct iio_dev *indio_dev,
+ iio_device_release_direct_mode(indio_dev);
+ if (ret < 0)
+ return ret;
+- *val = ret;
++ *val = sign_extend32(ret, chan->scan_type.realbits - 1);
+
+ return IIO_VAL_INT;
+
+--
+2.39.5
+
--- /dev/null
+From 026a1b9371f61a8942da5bb65d48f02d1e899ccf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Feb 2025 14:16:12 +0000
+Subject: iio: adc: ad7768-1: Move setting of val a bit later to avoid
+ unnecessary return value check
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+
+[ Upstream commit 0af1c801a15225304a6328258efbf2bee245c654 ]
+
+The data used is all in local variables so there is no advantage
+in setting *val = ret with the direct mode claim held.
+Move it later to after error check.
+
+Reviewed-by: Nuno Sá <nuno.sa@analog.com>
+Link: https://patch.msgid.link/20250217141630.897334-13-jic23@kernel.org
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Stable-dep-of: 8236644f5ecb ("iio: adc: ad7768-1: Fix conversion result sign")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/adc/ad7768-1.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/iio/adc/ad7768-1.c b/drivers/iio/adc/ad7768-1.c
+index 70a25949142c0..19d604f5701d6 100644
+--- a/drivers/iio/adc/ad7768-1.c
++++ b/drivers/iio/adc/ad7768-1.c
+@@ -370,12 +370,11 @@ static int ad7768_read_raw(struct iio_dev *indio_dev,
+ return ret;
+
+ ret = ad7768_scan_direct(indio_dev);
+- if (ret >= 0)
+- *val = ret;
+
+ iio_device_release_direct_mode(indio_dev);
+ if (ret < 0)
+ return ret;
++ *val = ret;
+
+ return IIO_VAL_INT;
+
+--
+2.39.5
+
--- /dev/null
+From c934048cb837aedc4a57e951e0a3708d8e5de14e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Apr 2024 18:39:09 +0300
+Subject: media: subdev: Add v4l2_subdev_is_streaming()
+
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+[ Upstream commit 5f3ce14fae742d1d23061c3122d93edb879ebf53 ]
+
+Add a helper function which returns whether the subdevice is streaming,
+i.e. if .s_stream or .enable_streams has been called successfully.
+
+Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Tested-by: Umang Jain <umang.jain@ideasonboard.com>
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Stable-dep-of: 36cef585e2a3 ("media: vimc: skip .s_stream() for stopped entities")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/v4l2-core/v4l2-subdev.c | 25 +++++++++++++++++++++++++
+ include/media/v4l2-subdev.h | 13 +++++++++++++
+ 2 files changed, 38 insertions(+)
+
+diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
+index f555fd3c4b76d..5f115438d0722 100644
+--- a/drivers/media/v4l2-core/v4l2-subdev.c
++++ b/drivers/media/v4l2-core/v4l2-subdev.c
+@@ -2240,6 +2240,31 @@ void v4l2_subdev_notify_event(struct v4l2_subdev *sd,
+ }
+ EXPORT_SYMBOL_GPL(v4l2_subdev_notify_event);
+
++bool v4l2_subdev_is_streaming(struct v4l2_subdev *sd)
++{
++ struct v4l2_subdev_state *state;
++
++ if (!v4l2_subdev_has_op(sd, pad, enable_streams))
++ return sd->s_stream_enabled;
++
++ if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS))
++ return !!sd->enabled_pads;
++
++ state = v4l2_subdev_get_locked_active_state(sd);
++
++ for (unsigned int i = 0; i < state->stream_configs.num_configs; ++i) {
++ const struct v4l2_subdev_stream_config *cfg;
++
++ cfg = &state->stream_configs.configs[i];
++
++ if (cfg->enabled)
++ return true;
++ }
++
++ return false;
++}
++EXPORT_SYMBOL_GPL(v4l2_subdev_is_streaming);
++
+ int v4l2_subdev_get_privacy_led(struct v4l2_subdev *sd)
+ {
+ #if IS_REACHABLE(CONFIG_LEDS_CLASS)
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index 0a8d75b009ea2..b4fcd0164048e 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -1918,4 +1918,17 @@ extern const struct v4l2_subdev_ops v4l2_subdev_call_wrappers;
+ void v4l2_subdev_notify_event(struct v4l2_subdev *sd,
+ const struct v4l2_event *ev);
+
++/**
++ * v4l2_subdev_is_streaming() - Returns if the subdevice is streaming
++ * @sd: The subdevice
++ *
++ * v4l2_subdev_is_streaming() tells if the subdevice is currently streaming.
++ * "Streaming" here means whether .s_stream() or .enable_streams() has been
++ * successfully called, and the streaming has not yet been disabled.
++ *
++ * If the subdevice implements .enable_streams() this function must be called
++ * while holding the active state lock.
++ */
++bool v4l2_subdev_is_streaming(struct v4l2_subdev *sd);
++
+ #endif /* _V4L2_SUBDEV_H */
+--
+2.39.5
+
--- /dev/null
+From dd7c987d06ba1d289b5b2df295bd1220dcb453ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Apr 2024 18:39:07 +0300
+Subject: media: subdev: Fix use of sd->enabled_streams in call_s_stream()
+
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+[ Upstream commit 1d7804281df3f09f0a109d00406e859a00bae7ae ]
+
+call_s_stream() uses sd->enabled_streams to track whether streaming has
+already been enabled. However,
+v4l2_subdev_enable/disable_streams_fallback(), which was the original
+user of this field, already uses it, and
+v4l2_subdev_enable/disable_streams_fallback() will call call_s_stream().
+
+This leads to a conflict as both functions set the field. Afaics, both
+functions set the field to the same value, so it won't cause a runtime
+bug, but it's still wrong and if we, e.g., change how
+v4l2_subdev_enable/disable_streams_fallback() operates we might easily
+cause bugs.
+
+Fix this by adding a new field, 's_stream_enabled', for
+call_s_stream().
+
+Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Tested-by: Umang Jain <umang.jain@ideasonboard.com>
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Stable-dep-of: 36cef585e2a3 ("media: vimc: skip .s_stream() for stopped entities")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/v4l2-core/v4l2-subdev.c | 8 ++------
+ include/media/v4l2-subdev.h | 3 +++
+ 2 files changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
+index a32ef739eb449..8bfbe9d5fe3c4 100644
+--- a/drivers/media/v4l2-core/v4l2-subdev.c
++++ b/drivers/media/v4l2-core/v4l2-subdev.c
+@@ -363,12 +363,8 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable)
+ * The .s_stream() operation must never be called to start or stop an
+ * already started or stopped subdev. Catch offenders but don't return
+ * an error yet to avoid regressions.
+- *
+- * As .s_stream() is mutually exclusive with the .enable_streams() and
+- * .disable_streams() operation, we can use the enabled_streams field
+- * to store the subdev streaming state.
+ */
+- if (WARN_ON(!!sd->enabled_streams == !!enable))
++ if (WARN_ON(sd->s_stream_enabled == !!enable))
+ return 0;
+
+ ret = sd->ops->video->s_stream(sd, enable);
+@@ -379,7 +375,7 @@ static int call_s_stream(struct v4l2_subdev *sd, int enable)
+ }
+
+ if (!ret) {
+- sd->enabled_streams = enable ? BIT(0) : 0;
++ sd->s_stream_enabled = enable;
+
+ #if IS_REACHABLE(CONFIG_LEDS_CLASS)
+ if (!IS_ERR_OR_NULL(sd->privacy_led)) {
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index ab2a7ef61d420..ee570dfbd791d 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -1042,6 +1042,8 @@ struct v4l2_subdev_platform_data {
+ * v4l2_subdev_enable_streams() and
+ * v4l2_subdev_disable_streams() helper functions for fallback
+ * cases.
++ * @s_stream_enabled: Tracks whether streaming has been enabled with s_stream.
++ * This is only for call_s_stream() internal use.
+ *
+ * Each instance of a subdev driver should create this struct, either
+ * stand-alone or embedded in a larger struct.
+@@ -1090,6 +1092,7 @@ struct v4l2_subdev {
+ */
+ struct v4l2_subdev_state *active_state;
+ u64 enabled_streams;
++ bool s_stream_enabled;
+ };
+
+
+--
+2.39.5
+
--- /dev/null
+From e11aaf8a58515fd209523fa67b68c01ba00ea543 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Apr 2024 18:39:08 +0300
+Subject: media: subdev: Improve v4l2_subdev_enable/disable_streams_fallback
+
+From: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+[ Upstream commit 61d6c8c896c1ccde350c281817847a32b0c6b83b ]
+
+v4l2_subdev_enable/disable_streams_fallback() supports falling back to
+.s_stream() for subdevs with a single source pad. It also tracks the
+enabled streams for that one pad in the sd->enabled_streams field.
+
+Tracking the enabled streams with sd->enabled_streams does not make
+sense, as with .s_stream() there can only be a single stream per pad.
+Thus, as the v4l2_subdev_enable/disable_streams_fallback() only supports
+a single source pad, all we really need is a boolean which tells whether
+streaming has been enabled on this pad or not.
+
+However, as we only need a true/false state for a pad (instead of
+tracking which streams have been enabled for a pad), we can easily
+extend the fallback mechanism to support multiple source pads as we only
+need to keep track of which pads have been enabled.
+
+Change the sd->enabled_streams field to sd->enabled_pads, which is a
+64-bit bitmask tracking the enabled source pads. With this change we can
+remove the restriction that
+v4l2_subdev_enable/disable_streams_fallback() only supports a single
+source pad.
+
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Tested-by: Umang Jain <umang.jain@ideasonboard.com>
+Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Stable-dep-of: 36cef585e2a3 ("media: vimc: skip .s_stream() for stopped entities")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/v4l2-core/v4l2-subdev.c | 68 ++++++++++++++++-----------
+ include/media/v4l2-subdev.h | 9 ++--
+ 2 files changed, 44 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
+index 8bfbe9d5fe3c4..f555fd3c4b76d 100644
+--- a/drivers/media/v4l2-core/v4l2-subdev.c
++++ b/drivers/media/v4l2-core/v4l2-subdev.c
+@@ -1925,37 +1925,43 @@ static int v4l2_subdev_enable_streams_fallback(struct v4l2_subdev *sd, u32 pad,
+ u64 streams_mask)
+ {
+ struct device *dev = sd->entity.graph_obj.mdev->dev;
+- unsigned int i;
+ int ret;
+
+ /*
+ * The subdev doesn't implement pad-based stream enable, fall back
+- * on the .s_stream() operation. This can only be done for subdevs that
+- * have a single source pad, as sd->enabled_streams is global to the
+- * subdev.
++ * to the .s_stream() operation.
+ */
+ if (!(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE))
+ return -EOPNOTSUPP;
+
+- for (i = 0; i < sd->entity.num_pads; ++i) {
+- if (i != pad && sd->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE)
+- return -EOPNOTSUPP;
+- }
++ /*
++ * .s_stream() means there is no streams support, so the only allowed
++ * stream is the implicit stream 0.
++ */
++ if (streams_mask != BIT_ULL(0))
++ return -EOPNOTSUPP;
++
++ /*
++ * We use a 64-bit bitmask for tracking enabled pads, so only subdevices
++ * with 64 pads or less can be supported.
++ */
++ if (pad >= sizeof(sd->enabled_pads) * BITS_PER_BYTE)
++ return -EOPNOTSUPP;
+
+- if (sd->enabled_streams & streams_mask) {
+- dev_dbg(dev, "set of streams %#llx already enabled on %s:%u\n",
+- streams_mask, sd->entity.name, pad);
++ if (sd->enabled_pads & BIT_ULL(pad)) {
++ dev_dbg(dev, "pad %u already enabled on %s\n",
++ pad, sd->entity.name);
+ return -EALREADY;
+ }
+
+- /* Start streaming when the first streams are enabled. */
+- if (!sd->enabled_streams) {
++ /* Start streaming when the first pad is enabled. */
++ if (!sd->enabled_pads) {
+ ret = v4l2_subdev_call(sd, video, s_stream, 1);
+ if (ret)
+ return ret;
+ }
+
+- sd->enabled_streams |= streams_mask;
++ sd->enabled_pads |= BIT_ULL(pad);
+
+ return 0;
+ }
+@@ -2042,37 +2048,43 @@ static int v4l2_subdev_disable_streams_fallback(struct v4l2_subdev *sd, u32 pad,
+ u64 streams_mask)
+ {
+ struct device *dev = sd->entity.graph_obj.mdev->dev;
+- unsigned int i;
+ int ret;
+
+ /*
+- * If the subdev doesn't implement pad-based stream enable, fall back
+- * on the .s_stream() operation. This can only be done for subdevs that
+- * have a single source pad, as sd->enabled_streams is global to the
+- * subdev.
++ * If the subdev doesn't implement pad-based stream enable, fall back
++ * to the .s_stream() operation.
+ */
+ if (!(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE))
+ return -EOPNOTSUPP;
+
+- for (i = 0; i < sd->entity.num_pads; ++i) {
+- if (i != pad && sd->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE)
+- return -EOPNOTSUPP;
+- }
++ /*
++ * .s_stream() means there is no streams support, so the only allowed
++ * stream is the implicit stream 0.
++ */
++ if (streams_mask != BIT_ULL(0))
++ return -EOPNOTSUPP;
++
++ /*
++ * We use a 64-bit bitmask for tracking enabled pads, so only subdevices
++ * with 64 pads or less can be supported.
++ */
++ if (pad >= sizeof(sd->enabled_pads) * BITS_PER_BYTE)
++ return -EOPNOTSUPP;
+
+- if ((sd->enabled_streams & streams_mask) != streams_mask) {
+- dev_dbg(dev, "set of streams %#llx already disabled on %s:%u\n",
+- streams_mask, sd->entity.name, pad);
++ if (!(sd->enabled_pads & BIT_ULL(pad))) {
++ dev_dbg(dev, "pad %u already disabled on %s\n",
++ pad, sd->entity.name);
+ return -EALREADY;
+ }
+
+ /* Stop streaming when the last streams are disabled. */
+- if (!(sd->enabled_streams & ~streams_mask)) {
++ if (!(sd->enabled_pads & ~BIT_ULL(pad))) {
+ ret = v4l2_subdev_call(sd, video, s_stream, 0);
+ if (ret)
+ return ret;
+ }
+
+- sd->enabled_streams &= ~streams_mask;
++ sd->enabled_pads &= ~BIT_ULL(pad);
+
+ return 0;
+ }
+diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
+index ee570dfbd791d..0a8d75b009ea2 100644
+--- a/include/media/v4l2-subdev.h
++++ b/include/media/v4l2-subdev.h
+@@ -1038,10 +1038,9 @@ struct v4l2_subdev_platform_data {
+ * @active_state: Active state for the subdev (NULL for subdevs tracking the
+ * state internally). Initialized by calling
+ * v4l2_subdev_init_finalize().
+- * @enabled_streams: Bitmask of enabled streams used by
+- * v4l2_subdev_enable_streams() and
+- * v4l2_subdev_disable_streams() helper functions for fallback
+- * cases.
++ * @enabled_pads: Bitmask of enabled pads used by v4l2_subdev_enable_streams()
++ * and v4l2_subdev_disable_streams() helper functions for
++ * fallback cases.
+ * @s_stream_enabled: Tracks whether streaming has been enabled with s_stream.
+ * This is only for call_s_stream() internal use.
+ *
+@@ -1091,7 +1090,7 @@ struct v4l2_subdev {
+ * doesn't support it.
+ */
+ struct v4l2_subdev_state *active_state;
+- u64 enabled_streams;
++ u64 enabled_pads;
+ bool s_stream_enabled;
+ };
+
+--
+2.39.5
+
--- /dev/null
+From 5174a714d9c786e83d548edae7added9c030eb13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 2 Mar 2025 17:58:25 +0300
+Subject: media: vimc: skip .s_stream() for stopped entities
+
+From: Nikita Zhandarovich <n.zhandarovich@fintech.ru>
+
+[ Upstream commit 36cef585e2a31e4ddf33a004b0584a7a572246de ]
+
+Syzbot reported [1] a warning prompted by a check in call_s_stream()
+that checks whether .s_stream() operation is warranted for unstarted
+or stopped subdevs.
+
+Add a simple fix in vimc_streamer_pipeline_terminate() ensuring that
+entities skip a call to .s_stream() unless they have been previously
+properly started.
+
+[1] Syzbot report:
+------------[ cut here ]------------
+WARNING: CPU: 0 PID: 5933 at drivers/media/v4l2-core/v4l2-subdev.c:460 call_s_stream+0x2df/0x350 drivers/media/v4l2-core/v4l2-subdev.c:460
+Modules linked in:
+CPU: 0 UID: 0 PID: 5933 Comm: syz-executor330 Not tainted 6.13.0-rc2-syzkaller-00362-g2d8308bf5b67 #0
+...
+Call Trace:
+ <TASK>
+ vimc_streamer_pipeline_terminate+0x218/0x320 drivers/media/test-drivers/vimc/vimc-streamer.c:62
+ vimc_streamer_pipeline_init drivers/media/test-drivers/vimc/vimc-streamer.c:101 [inline]
+ vimc_streamer_s_stream+0x650/0x9a0 drivers/media/test-drivers/vimc/vimc-streamer.c:203
+ vimc_capture_start_streaming+0xa1/0x130 drivers/media/test-drivers/vimc/vimc-capture.c:256
+ vb2_start_streaming+0x15f/0x5a0 drivers/media/common/videobuf2/videobuf2-core.c:1789
+ vb2_core_streamon+0x2a7/0x450 drivers/media/common/videobuf2/videobuf2-core.c:2348
+ vb2_streamon drivers/media/common/videobuf2/videobuf2-v4l2.c:875 [inline]
+ vb2_ioctl_streamon+0xf4/0x170 drivers/media/common/videobuf2/videobuf2-v4l2.c:1118
+ __video_do_ioctl+0xaf0/0xf00 drivers/media/v4l2-core/v4l2-ioctl.c:3122
+ video_usercopy+0x4d2/0x1620 drivers/media/v4l2-core/v4l2-ioctl.c:3463
+ v4l2_ioctl+0x1ba/0x250 drivers/media/v4l2-core/v4l2-dev.c:366
+ vfs_ioctl fs/ioctl.c:51 [inline]
+ __do_sys_ioctl fs/ioctl.c:906 [inline]
+ __se_sys_ioctl fs/ioctl.c:892 [inline]
+ __x64_sys_ioctl+0x190/0x200 fs/ioctl.c:892
+ do_syscall_x64 arch/x86/entry/common.c:52 [inline]
+ do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+RIP: 0033:0x7f2b85c01b19
+...
+
+Reported-by: syzbot+5bcd7c809d365e14c4df@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=5bcd7c809d365e14c4df
+Fixes: adc589d2a208 ("media: vimc: Add vimc-streamer for stream control")
+Cc: stable@vger.kernel.org
+Signed-off-by: Nikita Zhandarovich <n.zhandarovich@fintech.ru>
+Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/test-drivers/vimc/vimc-streamer.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/media/test-drivers/vimc/vimc-streamer.c b/drivers/media/test-drivers/vimc/vimc-streamer.c
+index 807551a5143b7..15d863f97cbf9 100644
+--- a/drivers/media/test-drivers/vimc/vimc-streamer.c
++++ b/drivers/media/test-drivers/vimc/vimc-streamer.c
+@@ -59,6 +59,12 @@ static void vimc_streamer_pipeline_terminate(struct vimc_stream *stream)
+ continue;
+
+ sd = media_entity_to_v4l2_subdev(ved->ent);
++ /*
++ * Do not call .s_stream() to stop an already
++ * stopped/unstarted subdev.
++ */
++ if (!v4l2_subdev_is_streaming(sd))
++ continue;
+ v4l2_subdev_call(sd, video, s_stream, 0);
+ }
+ }
+--
+2.39.5
+
--- /dev/null
+From 39e286a6981e02a7d95283925a8da6b714a2e347 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Mar 2025 16:09:34 -0700
+Subject: memcg: drain obj stock on cpu hotplug teardown
+
+From: Shakeel Butt <shakeel.butt@linux.dev>
+
+[ Upstream commit 9f01b4954490d4ccdbcc2b9be34a9921ceee9cbb ]
+
+Currently on cpu hotplug teardown, only memcg stock is drained but we
+need to drain the obj stock as well otherwise we will miss the stats
+accumulated on the target cpu as well as the nr_bytes cached. The stats
+include MEMCG_KMEM, NR_SLAB_RECLAIMABLE_B & NR_SLAB_UNRECLAIMABLE_B. In
+addition we are leaking reference to struct obj_cgroup object.
+
+Link: https://lkml.kernel.org/r/20250310230934.2913113-1-shakeel.butt@linux.dev
+Fixes: bf4f059954dc ("mm: memcg/slab: obj_cgroup API")
+Signed-off-by: Shakeel Butt <shakeel.butt@linux.dev>
+Reviewed-by: Roman Gushchin <roman.gushchin@linux.dev>
+Acked-by: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Michal Hocko <mhocko@kernel.org>
+Cc: Muchun Song <muchun.song@linux.dev>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/memcontrol.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/mm/memcontrol.c b/mm/memcontrol.c
+index 9bf5a69e20d87..ab9afcd372a93 100644
+--- a/mm/memcontrol.c
++++ b/mm/memcontrol.c
+@@ -2378,9 +2378,18 @@ static void drain_all_stock(struct mem_cgroup *root_memcg)
+ static int memcg_hotplug_cpu_dead(unsigned int cpu)
+ {
+ struct memcg_stock_pcp *stock;
++ struct obj_cgroup *old;
++ unsigned long flags;
+
+ stock = &per_cpu(memcg_stock, cpu);
++
++ /* drain_obj_stock requires stock_lock */
++ local_lock_irqsave(&memcg_stock.stock_lock, flags);
++ old = drain_obj_stock(stock);
++ local_unlock_irqrestore(&memcg_stock.stock_lock, flags);
++
+ drain_stock(stock);
++ obj_cgroup_put(old);
+
+ return 0;
+ }
+--
+2.39.5
+
--- /dev/null
+From b8c670593fd24deaae7765b8c422d2a89e1a9559 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jan 2025 14:18:51 +0000
+Subject: mmc: sdhci-msm: fix dev reference leaked through of_qcom_ice_get
+
+From: Tudor Ambarus <tudor.ambarus@linaro.org>
+
+[ Upstream commit cbef7442fba510b7eb229dcc9f39d3dde4a159a4 ]
+
+The driver leaks the device reference taken with
+of_find_device_by_node(). Fix the leak by using devm_of_qcom_ice_get().
+
+Fixes: c7eed31e235c ("mmc: sdhci-msm: Switch to the new ICE API")
+Cc: stable@vger.kernel.org
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
+Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-2-1ffa5b6884cb@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci-msm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
+index 945d08531de37..82808cc373f68 100644
+--- a/drivers/mmc/host/sdhci-msm.c
++++ b/drivers/mmc/host/sdhci-msm.c
+@@ -1866,7 +1866,7 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host,
+ if (!(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS))
+ return 0;
+
+- ice = of_qcom_ice_get(dev);
++ ice = devm_of_qcom_ice_get(dev);
+ if (ice == ERR_PTR(-EOPNOTSUPP)) {
+ dev_warn(dev, "Disabling inline encryption support\n");
+ ice = NULL;
+--
+2.39.5
+
--- /dev/null
+From fd9dff4ec1261b7ea9ac8f5cd89dc77757bec832 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Mar 2025 18:32:49 +0100
+Subject: net: dsa: mv88e6xxx: fix internal PHYs for 6320 family
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marek Behún <kabel@kernel.org>
+
+[ Upstream commit 52fdc41c3278c981066a461d03d5477ebfcf270c ]
+
+Fix internal PHYs definition for the 6320 family, which has only 2
+internal PHYs (on ports 3 and 4).
+
+Fixes: bc3931557d1d ("net: dsa: mv88e6xxx: Add number of internal PHYs")
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Cc: <stable@vger.kernel.org> # 6.6.x
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250317173250.28780-7-kabel@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/mv88e6xxx/chip.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
+index da7260e505a2e..d66448f0833cc 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -6114,7 +6114,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
+ .num_databases = 4096,
+ .num_macs = 8192,
+ .num_ports = 7,
+- .num_internal_phys = 5,
++ .num_internal_phys = 2,
++ .internal_phys_offset = 3,
+ .num_gpio = 15,
+ .max_vid = 4095,
+ .port_base_addr = 0x10,
+@@ -6139,7 +6140,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
+ .num_databases = 4096,
+ .num_macs = 8192,
+ .num_ports = 7,
+- .num_internal_phys = 5,
++ .num_internal_phys = 2,
++ .internal_phys_offset = 3,
+ .num_gpio = 15,
+ .max_vid = 4095,
+ .port_base_addr = 0x10,
+--
+2.39.5
+
--- /dev/null
+From a2b3dae082dfc1c3e9ef5bf75656a748a81a7b64 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Mar 2025 18:32:44 +0100
+Subject: net: dsa: mv88e6xxx: fix VTU methods for 6320 family
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Marek Behún <kabel@kernel.org>
+
+[ Upstream commit f9a457722cf5e3534be5ffab549d6b49737fca72 ]
+
+The VTU registers of the 6320 family use the 6352 semantics, not 6185.
+Fix it.
+
+Fixes: b8fee9571063 ("net: dsa: mv88e6xxx: add VLAN Get Next support")
+Signed-off-by: Marek Behún <kabel@kernel.org>
+Cc: <stable@vger.kernel.org> # 5.15.x
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20250317173250.28780-2-kabel@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/mv88e6xxx/chip.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
+index d66448f0833cc..bf93d700802be 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -5071,8 +5071,8 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
+ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+- .vtu_getnext = mv88e6185_g1_vtu_getnext,
+- .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
++ .vtu_getnext = mv88e6352_g1_vtu_getnext,
++ .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
+ .gpio_ops = &mv88e6352_gpio_ops,
+ .avb_ops = &mv88e6352_avb_ops,
+ .ptp_ops = &mv88e6352_ptp_ops,
+@@ -5120,8 +5120,8 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
+ .hardware_reset_pre = mv88e6xxx_g2_eeprom_wait,
+ .hardware_reset_post = mv88e6xxx_g2_eeprom_wait,
+ .reset = mv88e6352_g1_reset,
+- .vtu_getnext = mv88e6185_g1_vtu_getnext,
+- .vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
++ .vtu_getnext = mv88e6352_g1_vtu_getnext,
++ .vtu_loadpurge = mv88e6352_g1_vtu_loadpurge,
+ .gpio_ops = &mv88e6352_gpio_ops,
+ .avb_ops = &mv88e6352_avb_ops,
+ .ptp_ops = &mv88e6352_ptp_ops,
+--
+2.39.5
+
--- /dev/null
+From 84e7dd59cb3f1158a50edf794334fbe7de749cfe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Feb 2025 17:01:55 -0600
+Subject: of: resolver: Fix device node refcount leakage in
+ of_resolve_phandles()
+
+From: Zijun Hu <quic_zijuhu@quicinc.com>
+
+[ Upstream commit a46a0805635d07de50c2ac71588345323c13b2f9 ]
+
+In of_resolve_phandles(), refcount of device node @local_fixups will be
+increased if the for_each_child_of_node() exits early, but nowhere to
+decrease the refcount, so cause refcount leakage for the node.
+
+Fix by using __free() on @local_fixups.
+
+Fixes: da56d04c806a ("of/resolver: Switch to new local fixups format.")
+Cc: stable@vger.kernel.org
+Signed-off-by: Zijun Hu <quic_zijuhu@quicinc.com>
+Link: https://lore.kernel.org/r/20250209-of_irq_fix-v2-9-93e3a2659aa7@quicinc.com
+[robh: Use __free() instead]
+Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/of/resolver.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
+index 2dd19dc6987c7..d5c1b2a126a56 100644
+--- a/drivers/of/resolver.c
++++ b/drivers/of/resolver.c
+@@ -262,8 +262,9 @@ static int adjust_local_phandle_references(struct device_node *local_fixups,
+ */
+ int of_resolve_phandles(struct device_node *overlay)
+ {
+- struct device_node *child, *local_fixups, *refnode;
++ struct device_node *child, *refnode;
+ struct device_node *overlay_fixups;
++ struct device_node __free(device_node) *local_fixups = NULL;
+ struct property *prop;
+ const char *refpath;
+ phandle phandle, phandle_delta;
+--
+2.39.5
+
--- /dev/null
+From a4016669fb34722fcdd808db8371ef8146c36c82 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Feb 2025 20:59:02 +0800
+Subject: of: resolver: Simplify of_resolve_phandles() using __free()
+
+From: Rob Herring (Arm) <robh@kernel.org>
+
+[ Upstream commit 5275e8b5293f65cc82a5ee5eab02dd573b911d6e ]
+
+Use the __free() cleanup to simplify of_resolve_phandles() and remove
+all the goto's.
+
+Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
+Stable-dep-of: a46a0805635d ("of: resolver: Fix device node refcount leakage in of_resolve_phandles()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/of/resolver.c | 34 +++++++++++-----------------------
+ 1 file changed, 11 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
+index b278ab4338ceb..2dd19dc6987c7 100644
+--- a/drivers/of/resolver.c
++++ b/drivers/of/resolver.c
+@@ -263,24 +263,20 @@ static int adjust_local_phandle_references(struct device_node *local_fixups,
+ int of_resolve_phandles(struct device_node *overlay)
+ {
+ struct device_node *child, *local_fixups, *refnode;
+- struct device_node *tree_symbols, *overlay_fixups;
++ struct device_node *overlay_fixups;
+ struct property *prop;
+ const char *refpath;
+ phandle phandle, phandle_delta;
+ int err;
+
+- tree_symbols = NULL;
+-
+ if (!overlay) {
+ pr_err("null overlay\n");
+- err = -EINVAL;
+- goto out;
++ return -EINVAL;
+ }
+
+ if (!of_node_check_flag(overlay, OF_DETACHED)) {
+ pr_err("overlay not detached\n");
+- err = -EINVAL;
+- goto out;
++ return -EINVAL;
+ }
+
+ phandle_delta = live_tree_max_phandle() + 1;
+@@ -292,7 +288,7 @@ int of_resolve_phandles(struct device_node *overlay)
+
+ err = adjust_local_phandle_references(local_fixups, overlay, phandle_delta);
+ if (err)
+- goto out;
++ return err;
+
+ overlay_fixups = NULL;
+
+@@ -301,16 +297,13 @@ int of_resolve_phandles(struct device_node *overlay)
+ overlay_fixups = child;
+ }
+
+- if (!overlay_fixups) {
+- err = 0;
+- goto out;
+- }
++ if (!overlay_fixups)
++ return 0;
+
+- tree_symbols = of_find_node_by_path("/__symbols__");
++ struct device_node __free(device_node) *tree_symbols = of_find_node_by_path("/__symbols__");
+ if (!tree_symbols) {
+ pr_err("no symbols in root of device tree.\n");
+- err = -EINVAL;
+- goto out;
++ return -EINVAL;
+ }
+
+ for_each_property_of_node(overlay_fixups, prop) {
+@@ -324,14 +317,12 @@ int of_resolve_phandles(struct device_node *overlay)
+ if (err) {
+ pr_err("node label '%s' not found in live devicetree symbols table\n",
+ prop->name);
+- goto out;
++ return err;
+ }
+
+ refnode = of_find_node_by_path(refpath);
+- if (!refnode) {
+- err = -ENOENT;
+- goto out;
+- }
++ if (!refnode)
++ return -ENOENT;
+
+ phandle = refnode->phandle;
+ of_node_put(refnode);
+@@ -341,11 +332,8 @@ int of_resolve_phandles(struct device_node *overlay)
+ break;
+ }
+
+-out:
+ if (err)
+ pr_err("overlay phandle fixup failed: %d\n", err);
+- of_node_put(tree_symbols);
+-
+ return err;
+ }
+ EXPORT_SYMBOL_GPL(of_resolve_phandles);
+--
+2.39.5
+
--- /dev/null
+From 2509e58b469d642891e8e7e00597e39b82a9258c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Feb 2025 10:14:40 +0800
+Subject: PCI: Fix reference leak in pci_register_host_bridge()
+
+From: Ma Ke <make24@iscas.ac.cn>
+
+[ Upstream commit 804443c1f27883926de94c849d91f5b7d7d696e9 ]
+
+If device_register() fails, call put_device() to give up the reference to
+avoid a memory leak, per the comment at device_register().
+
+Found by code review.
+
+Link: https://lore.kernel.org/r/20250225021440.3130264-1-make24@iscas.ac.cn
+Fixes: 37d6a0a6f470 ("PCI: Add pci_register_host_bridge() interface")
+Signed-off-by: Ma Ke <make24@iscas.ac.cn>
+[bhelgaas: squash Dan Carpenter's double free fix from
+https://lore.kernel.org/r/db806a6c-a91b-4e5a-a84b-6b7e01bdac85@stanley.mountain]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/probe.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index 8e5d818c29a98..b7cec139d816b 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -885,6 +885,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
+ resource_size_t offset, next_offset;
+ LIST_HEAD(resources);
+ struct resource *res, *next_res;
++ bool bus_registered = false;
+ char addr[64], *fmt;
+ const char *name;
+ int err;
+@@ -948,6 +949,7 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
+ name = dev_name(&bus->dev);
+
+ err = device_register(&bus->dev);
++ bus_registered = true;
+ if (err)
+ goto unregister;
+
+@@ -1031,12 +1033,15 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
+ unregister:
+ put_device(&bridge->dev);
+ device_del(&bridge->dev);
+-
+ free:
+ #ifdef CONFIG_PCI_DOMAINS_GENERIC
+ pci_bus_release_domain_nr(bus, parent);
+ #endif
+- kfree(bus);
++ if (bus_registered)
++ put_device(&bus->dev);
++ else
++ kfree(bus);
++
+ return err;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From bc44df3dd096499912449d45aadf335fcb507754 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Dec 2024 14:47:28 +0100
+Subject: s390/pci: Report PCI error recovery results via SCLP
+
+From: Niklas Schnelle <schnelle@linux.ibm.com>
+
+[ Upstream commit 4ec6054e7321dc24ebccaa08b3af0d590f5666e6 ]
+
+Add a mechanism with which the status of PCI error recovery runs
+is reported to the platform. Together with the status supply additional
+information that may aid in problem determination.
+
+Reviewed-by: Halil Pasic <pasic@linux.ibm.com>
+Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Stable-dep-of: aa9f168d55dc ("s390/pci: Support mmap() of PCI resources except for ISM devices")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/include/asm/sclp.h | 33 +++++++++++
+ arch/s390/pci/Makefile | 2 +-
+ arch/s390/pci/pci_event.c | 21 +++++--
+ arch/s390/pci/pci_report.c | 111 +++++++++++++++++++++++++++++++++++
+ arch/s390/pci/pci_report.h | 16 +++++
+ drivers/s390/char/sclp.h | 14 -----
+ drivers/s390/char/sclp_pci.c | 19 ------
+ 7 files changed, 178 insertions(+), 38 deletions(-)
+ create mode 100644 arch/s390/pci/pci_report.c
+ create mode 100644 arch/s390/pci/pci_report.h
+
+diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
+index 5742d23bba137..d4a7a178e3584 100644
+--- a/arch/s390/include/asm/sclp.h
++++ b/arch/s390/include/asm/sclp.h
+@@ -16,6 +16,11 @@
+ /* 24 + 16 * SCLP_MAX_CORES */
+ #define EXT_SCCB_READ_CPU (3 * PAGE_SIZE)
+
++#define SCLP_ERRNOTIFY_AQ_RESET 0
++#define SCLP_ERRNOTIFY_AQ_REPAIR 1
++#define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
++#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
++
+ #ifndef __ASSEMBLY__
+ #include <linux/uio.h>
+ #include <asm/chpid.h>
+@@ -109,6 +114,34 @@ struct sclp_info {
+ };
+ extern struct sclp_info sclp;
+
++struct sccb_header {
++ u16 length;
++ u8 function_code;
++ u8 control_mask[3];
++ u16 response_code;
++} __packed;
++
++struct evbuf_header {
++ u16 length;
++ u8 type;
++ u8 flags;
++ u16 _reserved;
++} __packed;
++
++struct err_notify_evbuf {
++ struct evbuf_header header;
++ u8 action;
++ u8 atype;
++ u32 fh;
++ u32 fid;
++ u8 data[];
++} __packed;
++
++struct err_notify_sccb {
++ struct sccb_header header;
++ struct err_notify_evbuf evbuf;
++} __packed;
++
+ struct zpci_report_error_header {
+ u8 version; /* Interface version byte */
+ u8 action; /* Action qualifier byte
+diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
+index 5ae31ca9dd441..eeef68901a15c 100644
+--- a/arch/s390/pci/Makefile
++++ b/arch/s390/pci/Makefile
+@@ -5,5 +5,5 @@
+
+ obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_dma.o pci_clp.o pci_sysfs.o \
+ pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
+- pci_bus.o pci_kvm_hook.o
++ pci_bus.o pci_kvm_hook.o pci_report.o
+ obj-$(CONFIG_PCI_IOV) += pci_iov.o
+diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
+index b3961f1016ea0..ed8c7f61e642b 100644
+--- a/arch/s390/pci/pci_event.c
++++ b/arch/s390/pci/pci_event.c
+@@ -16,6 +16,7 @@
+ #include <asm/sclp.h>
+
+ #include "pci_bus.h"
++#include "pci_report.h"
+
+ /* Content Code Description for PCI Function Error */
+ struct zpci_ccdf_err {
+@@ -162,6 +163,8 @@ static pci_ers_result_t zpci_event_do_reset(struct pci_dev *pdev,
+ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
+ {
+ pci_ers_result_t ers_res = PCI_ERS_RESULT_DISCONNECT;
++ struct zpci_dev *zdev = to_zpci(pdev);
++ char *status_str = "success";
+ struct pci_driver *driver;
+
+ /*
+@@ -179,29 +182,37 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
+ if (is_passed_through(to_zpci(pdev))) {
+ pr_info("%s: Cannot be recovered in the host because it is a pass-through device\n",
+ pci_name(pdev));
++ status_str = "failed (pass-through)";
+ goto out_unlock;
+ }
+
+ driver = to_pci_driver(pdev->dev.driver);
+ if (!is_driver_supported(driver)) {
+- if (!driver)
++ if (!driver) {
+ pr_info("%s: Cannot be recovered because no driver is bound to the device\n",
+ pci_name(pdev));
+- else
++ status_str = "failed (no driver)";
++ } else {
+ pr_info("%s: The %s driver bound to the device does not support error recovery\n",
+ pci_name(pdev),
+ driver->name);
++ status_str = "failed (no driver support)";
++ }
+ goto out_unlock;
+ }
+
+ ers_res = zpci_event_notify_error_detected(pdev, driver);
+- if (ers_result_indicates_abort(ers_res))
++ if (ers_result_indicates_abort(ers_res)) {
++ status_str = "failed (abort on detection)";
+ goto out_unlock;
++ }
+
+ if (ers_res == PCI_ERS_RESULT_CAN_RECOVER) {
+ ers_res = zpci_event_do_error_state_clear(pdev, driver);
+- if (ers_result_indicates_abort(ers_res))
++ if (ers_result_indicates_abort(ers_res)) {
++ status_str = "failed (abort on MMIO enable)";
+ goto out_unlock;
++ }
+ }
+
+ if (ers_res == PCI_ERS_RESULT_NEED_RESET)
+@@ -210,6 +221,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
+ if (ers_res != PCI_ERS_RESULT_RECOVERED) {
+ pr_err("%s: Automatic recovery failed; operator intervention is required\n",
+ pci_name(pdev));
++ status_str = "failed (driver can't recover)";
+ goto out_unlock;
+ }
+
+@@ -218,6 +230,7 @@ static pci_ers_result_t zpci_event_attempt_error_recovery(struct pci_dev *pdev)
+ driver->err_handler->resume(pdev);
+ out_unlock:
+ pci_dev_unlock(pdev);
++ zpci_report_status(zdev, "recovery", status_str);
+
+ return ers_res;
+ }
+diff --git a/arch/s390/pci/pci_report.c b/arch/s390/pci/pci_report.c
+new file mode 100644
+index 0000000000000..2754c9c161f5b
+--- /dev/null
++++ b/arch/s390/pci/pci_report.c
+@@ -0,0 +1,111 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright IBM Corp. 2024
++ *
++ * Author(s):
++ * Niklas Schnelle <schnelle@linux.ibm.com>
++ *
++ */
++
++#define KMSG_COMPONENT "zpci"
++#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
++
++#include <linux/kernel.h>
++#include <linux/sprintf.h>
++#include <linux/pci.h>
++
++#include <asm/sclp.h>
++
++#include "pci_report.h"
++
++#define ZPCI_ERR_LOG_ID_KERNEL_REPORT 0x4714
++
++struct zpci_report_error_data {
++ u64 timestamp;
++ u64 err_log_id;
++ char log_data[];
++} __packed;
++
++#define ZPCI_REPORT_SIZE (PAGE_SIZE - sizeof(struct err_notify_sccb))
++#define ZPCI_REPORT_DATA_SIZE (ZPCI_REPORT_SIZE - sizeof(struct zpci_report_error_data))
++
++struct zpci_report_error {
++ struct zpci_report_error_header header;
++ struct zpci_report_error_data data;
++} __packed;
++
++static const char *zpci_state_str(pci_channel_state_t state)
++{
++ switch (state) {
++ case pci_channel_io_normal:
++ return "normal";
++ case pci_channel_io_frozen:
++ return "frozen";
++ case pci_channel_io_perm_failure:
++ return "permanent-failure";
++ default:
++ return "invalid";
++ };
++}
++
++/**
++ * zpci_report_status - Report the status of operations on a PCI device
++ * @zdev: The PCI device for which to report status
++ * @operation: A string representing the operation reported
++ * @status: A string representing the status of the operation
++ *
++ * This function creates a human readable report about an operation such as
++ * PCI device recovery and forwards this to the platform using the SCLP Write
++ * Event Data mechanism. Besides the operation and status strings the report
++ * also contains additional information about the device deemed useful for
++ * debug such as the currently bound device driver, if any, and error state.
++ *
++ * Return: 0 on success an error code < 0 otherwise.
++ */
++int zpci_report_status(struct zpci_dev *zdev, const char *operation, const char *status)
++{
++ struct zpci_report_error *report;
++ struct pci_driver *driver = NULL;
++ struct pci_dev *pdev = NULL;
++ char *buf, *end;
++ int ret;
++
++ if (!zdev || !zdev->zbus)
++ return -ENODEV;
++
++ /* Protected virtualization hosts get nothing from us */
++ if (prot_virt_guest)
++ return -ENODATA;
++
++ report = (void *)get_zeroed_page(GFP_KERNEL);
++ if (!report)
++ return -ENOMEM;
++ if (zdev->zbus->bus)
++ pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn);
++ if (pdev)
++ driver = to_pci_driver(pdev->dev.driver);
++
++ buf = report->data.log_data;
++ end = report->data.log_data + ZPCI_REPORT_DATA_SIZE;
++ buf += scnprintf(buf, end - buf, "report: %s\n", operation);
++ buf += scnprintf(buf, end - buf, "status: %s\n", status);
++ buf += scnprintf(buf, end - buf, "state: %s\n",
++ (pdev) ? zpci_state_str(pdev->error_state) : "n/a");
++ buf += scnprintf(buf, end - buf, "driver: %s\n", (driver) ? driver->name : "n/a");
++
++ report->header.version = 1;
++ report->header.action = SCLP_ERRNOTIFY_AQ_INFO_LOG;
++ report->header.length = buf - (char *)&report->data;
++ report->data.timestamp = ktime_get_clocktai_seconds();
++ report->data.err_log_id = ZPCI_ERR_LOG_ID_KERNEL_REPORT;
++
++ ret = sclp_pci_report(&report->header, zdev->fh, zdev->fid);
++ if (ret)
++ pr_err("Reporting PCI status failed with code %d\n", ret);
++ else
++ pr_info("Reported PCI device status\n");
++
++ free_page((unsigned long)report);
++
++ return ret;
++}
+diff --git a/arch/s390/pci/pci_report.h b/arch/s390/pci/pci_report.h
+new file mode 100644
+index 0000000000000..e08003d51a972
+--- /dev/null
++++ b/arch/s390/pci/pci_report.h
+@@ -0,0 +1,16 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * Copyright IBM Corp. 2024
++ *
++ * Author(s):
++ * Niklas Schnelle <schnelle@linux.ibm.com>
++ *
++ */
++#ifndef __S390_PCI_REPORT_H
++#define __S390_PCI_REPORT_H
++
++struct zpci_dev;
++
++int zpci_report_status(struct zpci_dev *zdev, const char *operation, const char *status);
++
++#endif /* __S390_PCI_REPORT_H */
+diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
+index 6a23ec286c702..25fd4d8547483 100644
+--- a/drivers/s390/char/sclp.h
++++ b/drivers/s390/char/sclp.h
+@@ -84,13 +84,6 @@ typedef unsigned int sclp_cmdw_t;
+
+ typedef u64 sccb_mask_t;
+
+-struct sccb_header {
+- u16 length;
+- u8 function_code;
+- u8 control_mask[3];
+- u16 response_code;
+-} __attribute__((packed));
+-
+ struct init_sccb {
+ struct sccb_header header;
+ u16 _reserved;
+@@ -237,13 +230,6 @@ struct gds_vector {
+ u16 gds_id;
+ } __attribute__((packed));
+
+-struct evbuf_header {
+- u16 length;
+- u8 type;
+- u8 flags;
+- u16 _reserved;
+-} __attribute__((packed));
+-
+ struct sclp_req {
+ struct list_head list; /* list_head for request queueing. */
+ sclp_cmdw_t command; /* sclp command to execute */
+diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c
+index c3466a8c56bb5..56400886f7fca 100644
+--- a/drivers/s390/char/sclp_pci.c
++++ b/drivers/s390/char/sclp_pci.c
+@@ -24,30 +24,11 @@
+
+ #define SCLP_ATYPE_PCI 2
+
+-#define SCLP_ERRNOTIFY_AQ_RESET 0
+-#define SCLP_ERRNOTIFY_AQ_REPAIR 1
+-#define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
+-#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
+-
+ static DEFINE_MUTEX(sclp_pci_mutex);
+ static struct sclp_register sclp_pci_event = {
+ .send_mask = EVTYP_ERRNOTIFY_MASK,
+ };
+
+-struct err_notify_evbuf {
+- struct evbuf_header header;
+- u8 action;
+- u8 atype;
+- u32 fh;
+- u32 fid;
+- u8 data[];
+-} __packed;
+-
+-struct err_notify_sccb {
+- struct sccb_header header;
+- struct err_notify_evbuf evbuf;
+-} __packed;
+-
+ struct pci_cfg_sccb {
+ struct sccb_header header;
+ u8 atype; /* adapter type */
+--
+2.39.5
+
--- /dev/null
+From bb8589b36d58725be67b9d983251d9a9b1437f2f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Feb 2025 13:07:47 +0100
+Subject: s390/pci: Support mmap() of PCI resources except for ISM devices
+
+From: Niklas Schnelle <schnelle@linux.ibm.com>
+
+[ Upstream commit aa9f168d55dc47c0de564f7dfe0e90467c9fee71 ]
+
+So far s390 does not allow mmap() of PCI resources to user-space via the
+usual mechanisms, though it does use it for RDMA. For the PCI sysfs
+resource files and /proc/bus/pci it defines neither HAVE_PCI_MMAP nor
+ARCH_GENERIC_PCI_MMAP_RESOURCE. For vfio-pci s390 previously relied on
+disabled VFIO_PCI_MMAP and now relies on setting pdev->non_mappable_bars
+for all devices.
+
+This is partly because access to mapped PCI resources from user-space
+requires special PCI load/store memory-I/O (MIO) instructions, or the
+special MMIO syscalls when these are not available. Still, such access is
+possible and useful not just for RDMA, in fact not being able to mmap() PCI
+resources has previously caused extra work when testing devices.
+
+One thing that doesn't work with PCI resources mapped to user-space though
+is the s390 specific virtual ISM device. Not only because the BAR size of
+256 TiB prevents mapping the whole BAR but also because access requires use
+of the legacy PCI instructions which are not accessible to user-space on
+systems with the newer MIO PCI instructions.
+
+Now with the pdev->non_mappable_bars flag ISM can be excluded from mapping
+its resources while making this functionality available for all other PCI
+devices. To this end introduce a minimal implementation of PCI_QUIRKS and
+use that to set pdev->non_mappable_bars for ISM devices only. Then also set
+ARCH_GENERIC_PCI_MMAP_RESOURCE to take advantage of the generic
+implementation of pci_mmap_resource_range() enabling only the newer sysfs
+mmap() interface. This follows the recommendation in
+Documentation/PCI/sysfs-pci.rst.
+
+Link: https://lore.kernel.org/r/20250226-vfio_pci_mmap-v7-3-c5c0f1d26efd@linux.ibm.com
+Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/Kconfig | 4 +---
+ arch/s390/include/asm/pci.h | 3 +++
+ arch/s390/pci/Makefile | 2 +-
+ arch/s390/pci/pci_fixup.c | 23 +++++++++++++++++++++++
+ drivers/s390/net/ism_drv.c | 1 -
+ include/linux/pci_ids.h | 1 +
+ 6 files changed, 29 insertions(+), 5 deletions(-)
+ create mode 100644 arch/s390/pci/pci_fixup.c
+
+diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
+index bd4782f23f66d..0882016af57c0 100644
+--- a/arch/s390/Kconfig
++++ b/arch/s390/Kconfig
+@@ -38,9 +38,6 @@ config AUDIT_ARCH
+ config NO_IOPORT_MAP
+ def_bool y
+
+-config PCI_QUIRKS
+- def_bool n
+-
+ config ARCH_SUPPORTS_UPROBES
+ def_bool y
+
+@@ -229,6 +226,7 @@ config S390
+ select PCI_DOMAINS if PCI
+ select PCI_MSI if PCI
+ select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
++ select PCI_QUIRKS if PCI
+ select SPARSE_IRQ
+ select SWIOTLB
+ select SYSCTL_EXCEPTION_TRACE
+diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
+index b248694e00247..211c69cd1f9c9 100644
+--- a/arch/s390/include/asm/pci.h
++++ b/arch/s390/include/asm/pci.h
+@@ -11,6 +11,9 @@
+ #include <asm/pci_insn.h>
+ #include <asm/sclp.h>
+
++#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
++#define arch_can_pci_mmap_wc() 1
++
+ #define PCIBIOS_MIN_IO 0x1000
+ #define PCIBIOS_MIN_MEM 0x10000000
+
+diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
+index eeef68901a15c..2f8dd3f688391 100644
+--- a/arch/s390/pci/Makefile
++++ b/arch/s390/pci/Makefile
+@@ -5,5 +5,5 @@
+
+ obj-$(CONFIG_PCI) += pci.o pci_irq.o pci_dma.o pci_clp.o pci_sysfs.o \
+ pci_event.o pci_debug.o pci_insn.o pci_mmio.o \
+- pci_bus.o pci_kvm_hook.o pci_report.o
++ pci_bus.o pci_kvm_hook.o pci_report.o pci_fixup.o
+ obj-$(CONFIG_PCI_IOV) += pci_iov.o
+diff --git a/arch/s390/pci/pci_fixup.c b/arch/s390/pci/pci_fixup.c
+new file mode 100644
+index 0000000000000..35688b6450983
+--- /dev/null
++++ b/arch/s390/pci/pci_fixup.c
+@@ -0,0 +1,23 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Exceptions for specific devices,
++ *
++ * Copyright IBM Corp. 2025
++ *
++ * Author(s):
++ * Niklas Schnelle <schnelle@linux.ibm.com>
++ */
++#include <linux/pci.h>
++
++static void zpci_ism_bar_no_mmap(struct pci_dev *pdev)
++{
++ /*
++ * ISM's BAR is special. Drivers written for ISM know
++ * how to handle this but others need to be aware of their
++ * special nature e.g. to prevent attempts to mmap() it.
++ */
++ pdev->non_mappable_bars = 1;
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_IBM,
++ PCI_DEVICE_ID_IBM_ISM,
++ zpci_ism_bar_no_mmap);
+diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c
+index af0d90beba638..390ebd4d7f3bc 100644
+--- a/drivers/s390/net/ism_drv.c
++++ b/drivers/s390/net/ism_drv.c
+@@ -20,7 +20,6 @@
+ MODULE_DESCRIPTION("ISM driver for s390");
+ MODULE_LICENSE("GPL");
+
+-#define PCI_DEVICE_ID_IBM_ISM 0x04ED
+ #define DRV_NAME "ism"
+
+ static const struct pci_device_id ism_device_table[] = {
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index 3dce2be622e74..dcb9d5ac06937 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -517,6 +517,7 @@
+ #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM 0x0251
+ #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
+ #define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252
++#define PCI_DEVICE_ID_IBM_ISM 0x04ed
+
+ #define PCI_SUBVENDOR_ID_IBM 0x1014
+ #define PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT 0x03d4
+--
+2.39.5
+
--- /dev/null
+From 3975b23c37050e63853cd7e5082ceda8ea50d152 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Oct 2024 15:07:27 +0200
+Subject: s390/sclp: Allow user-space to provide PCI reports for optical
+ modules
+
+From: Niklas Schnelle <schnelle@linux.ibm.com>
+
+[ Upstream commit e9ab04490667249633fb397be17db46a8fa6d130 ]
+
+The new SCLP action qualifier 3 is used by user-space code to provide
+optical module monitoring data to the platform.
+
+Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Stable-dep-of: aa9f168d55dc ("s390/pci: Support mmap() of PCI resources except for ISM devices")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/s390/char/sclp_pci.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/s390/char/sclp_pci.c b/drivers/s390/char/sclp_pci.c
+index a3e5a5fb0c1e7..c3466a8c56bb5 100644
+--- a/drivers/s390/char/sclp_pci.c
++++ b/drivers/s390/char/sclp_pci.c
+@@ -27,6 +27,7 @@
+ #define SCLP_ERRNOTIFY_AQ_RESET 0
+ #define SCLP_ERRNOTIFY_AQ_REPAIR 1
+ #define SCLP_ERRNOTIFY_AQ_INFO_LOG 2
++#define SCLP_ERRNOTIFY_AQ_OPTICS_DATA 3
+
+ static DEFINE_MUTEX(sclp_pci_mutex);
+ static struct sclp_register sclp_pci_event = {
+@@ -116,6 +117,7 @@ static int sclp_pci_check_report(struct zpci_report_error_header *report)
+ case SCLP_ERRNOTIFY_AQ_RESET:
+ case SCLP_ERRNOTIFY_AQ_REPAIR:
+ case SCLP_ERRNOTIFY_AQ_INFO_LOG:
++ case SCLP_ERRNOTIFY_AQ_OPTICS_DATA:
+ break;
+ default:
+ return -EINVAL;
+--
+2.39.5
+
--- /dev/null
+From 3867566eb8a43354f101dbb141dc38e7f9f8395f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Apr 2025 22:36:21 +0200
+Subject: s390/virtio_ccw: Don't allocate/assign airqs for non-existing queues
+
+From: David Hildenbrand <david@redhat.com>
+
+[ Upstream commit 2ccd42b959aaf490333dbd3b9b102eaf295c036a ]
+
+If we finds a vq without a name in our input array in
+virtio_ccw_find_vqs(), we treat it as "non-existing" and set the vq pointer
+to NULL; we will not call virtio_ccw_setup_vq() to allocate/setup a vq.
+
+Consequently, we create only a queue if it actually exists (name != NULL)
+and assign an incremental queue index to each such existing queue.
+
+However, in virtio_ccw_register_adapter_ind()->get_airq_indicator() we
+will not ignore these "non-existing queues", but instead assign an airq
+indicator to them.
+
+Besides never releasing them in virtio_ccw_drop_indicators() (because
+there is no virtqueue), the bigger issue seems to be that there will be a
+disagreement between the device and the Linux guest about the airq
+indicator to be used for notifying a queue, because the indicator bit
+for adapter I/O interrupt is derived from the queue index.
+
+The virtio spec states under "Setting Up Two-Stage Queue Indicators":
+
+ ... indicator contains the guest address of an area wherein the
+ indicators for the devices are contained, starting at bit_nr, one
+ bit per virtqueue of the device.
+
+And further in "Notification via Adapter I/O Interrupts":
+
+ For notifying the driver of virtqueue buffers, the device sets the
+ bit in the guest-provided indicator area at the corresponding
+ offset.
+
+For example, QEMU uses in virtio_ccw_notify() the queue index (passed as
+"vector") to select the relevant indicator bit. If a queue does not exist,
+it does not have a corresponding indicator bit assigned, because it
+effectively doesn't have a queue index.
+
+Using a virtio-balloon-ccw device under QEMU with free-page-hinting
+disabled ("free-page-hint=off") but free-page-reporting enabled
+("free-page-reporting=on") will result in free page reporting
+not working as expected: in the virtio_balloon driver, we'll be stuck
+forever in virtballoon_free_page_report()->wait_event(), because the
+waitqueue will not be woken up as the notification from the device is
+lost: it would use the wrong indicator bit.
+
+Free page reporting stops working and we get splats (when configured to
+detect hung wqs) like:
+
+ INFO: task kworker/1:3:463 blocked for more than 61 seconds.
+ Not tainted 6.14.0 #4
+ "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+ task:kworker/1:3 [...]
+ Workqueue: events page_reporting_process
+ Call Trace:
+ [<000002f404e6dfb2>] __schedule+0x402/0x1640
+ [<000002f404e6f22e>] schedule+0x3e/0xe0
+ [<000002f3846a88fa>] virtballoon_free_page_report+0xaa/0x110 [virtio_balloon]
+ [<000002f40435c8a4>] page_reporting_process+0x2e4/0x740
+ [<000002f403fd3ee2>] process_one_work+0x1c2/0x400
+ [<000002f403fd4b96>] worker_thread+0x296/0x420
+ [<000002f403fe10b4>] kthread+0x124/0x290
+ [<000002f403f4e0dc>] __ret_from_fork+0x3c/0x60
+ [<000002f404e77272>] ret_from_fork+0xa/0x38
+
+There was recently a discussion [1] whether the "holes" should be
+treated differently again, effectively assigning also non-existing
+queues a queue index: that should also fix the issue, but requires other
+workarounds to not break existing setups.
+
+Let's fix it without affecting existing setups for now by properly ignoring
+the non-existing queues, so the indicator bits will match the queue
+indexes.
+
+[1] https://lore.kernel.org/all/cover.1720611677.git.mst@redhat.com/
+
+Fixes: a229989d975e ("virtio: don't allocate vqs when names[i] = NULL")
+Reported-by: Chandra Merla <cmerla@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: David Hildenbrand <david@redhat.com>
+Tested-by: Thomas Huth <thuth@redhat.com>
+Reviewed-by: Thomas Huth <thuth@redhat.com>
+Reviewed-by: Cornelia Huck <cohuck@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Acked-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Link: https://lore.kernel.org/r/20250402203621.940090-1-david@redhat.com
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/s390/virtio/virtio_ccw.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
+index ac77951c30c46..75aeb7f8ed099 100644
+--- a/drivers/s390/virtio/virtio_ccw.c
++++ b/drivers/s390/virtio/virtio_ccw.c
+@@ -263,11 +263,17 @@ static struct airq_info *new_airq_info(int index)
+ static unsigned long *get_airq_indicator(struct virtqueue *vqs[], int nvqs,
+ u64 *first, void **airq_info)
+ {
+- int i, j;
++ int i, j, queue_idx, highest_queue_idx = -1;
+ struct airq_info *info;
+ unsigned long *indicator_addr = NULL;
+ unsigned long bit, flags;
+
++ /* Array entries without an actual queue pointer must be ignored. */
++ for (i = 0; i < nvqs; i++) {
++ if (vqs[i])
++ highest_queue_idx++;
++ }
++
+ for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) {
+ mutex_lock(&airq_areas_lock);
+ if (!airq_areas[i])
+@@ -277,7 +283,7 @@ static unsigned long *get_airq_indicator(struct virtqueue *vqs[], int nvqs,
+ if (!info)
+ return NULL;
+ write_lock_irqsave(&info->lock, flags);
+- bit = airq_iv_alloc(info->aiv, nvqs);
++ bit = airq_iv_alloc(info->aiv, highest_queue_idx + 1);
+ if (bit == -1UL) {
+ /* Not enough vacancies. */
+ write_unlock_irqrestore(&info->lock, flags);
+@@ -286,8 +292,10 @@ static unsigned long *get_airq_indicator(struct virtqueue *vqs[], int nvqs,
+ *first = bit;
+ *airq_info = info;
+ indicator_addr = info->aiv->vector;
+- for (j = 0; j < nvqs; j++) {
+- airq_iv_set_ptr(info->aiv, bit + j,
++ for (j = 0, queue_idx = 0; j < nvqs; j++) {
++ if (!vqs[j])
++ continue;
++ airq_iv_set_ptr(info->aiv, bit + queue_idx++,
+ (unsigned long)vqs[j]);
+ }
+ write_unlock_irqrestore(&info->lock, flags);
+--
+2.39.5
+
--- /dev/null
+From 060468bc4467e6f881fe984e6dc8054999ede5d7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Mar 2024 13:28:07 +0100
+Subject: s390/virtio_ccw: fix virtual vs physical address confusion
+
+From: Halil Pasic <pasic@linux.ibm.com>
+
+[ Upstream commit d5cc41686990fa522ce573e5c6c7a619f10c3fd1 ]
+
+Fix virtual vs physical address confusion and use new dma types and helper
+functions to allow for type checking. This does not fix a bug since virtual
+and physical address spaces are currently the same.
+
+Signed-off-by: Halil Pasic <pasic@linux.ibm.com>
+Reviewed-by: Eric Farman <farman@linux.ibm.com>
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Stable-dep-of: 2ccd42b959aa ("s390/virtio_ccw: Don't allocate/assign airqs for non-existing queues")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/s390/virtio/virtio_ccw.c | 78 ++++++++++++++++----------------
+ 1 file changed, 39 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
+index ac67576301bf5..ac77951c30c46 100644
+--- a/drivers/s390/virtio/virtio_ccw.c
++++ b/drivers/s390/virtio/virtio_ccw.c
+@@ -85,19 +85,19 @@ static inline unsigned long *indicators2(struct virtio_ccw_device *vcdev)
+ }
+
+ struct vq_info_block_legacy {
+- __u64 queue;
++ dma64_t queue;
+ __u32 align;
+ __u16 index;
+ __u16 num;
+ } __packed;
+
+ struct vq_info_block {
+- __u64 desc;
++ dma64_t desc;
+ __u32 res0;
+ __u16 index;
+ __u16 num;
+- __u64 avail;
+- __u64 used;
++ dma64_t avail;
++ dma64_t used;
+ } __packed;
+
+ struct virtio_feature_desc {
+@@ -106,8 +106,8 @@ struct virtio_feature_desc {
+ } __packed;
+
+ struct virtio_thinint_area {
+- unsigned long summary_indicator;
+- unsigned long indicator;
++ dma64_t summary_indicator;
++ dma64_t indicator;
+ u64 bit_nr;
+ u8 isc;
+ } __packed;
+@@ -260,12 +260,12 @@ static struct airq_info *new_airq_info(int index)
+ return info;
+ }
+
+-static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
+- u64 *first, void **airq_info)
++static unsigned long *get_airq_indicator(struct virtqueue *vqs[], int nvqs,
++ u64 *first, void **airq_info)
+ {
+ int i, j;
+ struct airq_info *info;
+- unsigned long indicator_addr = 0;
++ unsigned long *indicator_addr = NULL;
+ unsigned long bit, flags;
+
+ for (i = 0; i < MAX_AIRQ_AREAS && !indicator_addr; i++) {
+@@ -275,7 +275,7 @@ static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
+ info = airq_areas[i];
+ mutex_unlock(&airq_areas_lock);
+ if (!info)
+- return 0;
++ return NULL;
+ write_lock_irqsave(&info->lock, flags);
+ bit = airq_iv_alloc(info->aiv, nvqs);
+ if (bit == -1UL) {
+@@ -285,7 +285,7 @@ static unsigned long get_airq_indicator(struct virtqueue *vqs[], int nvqs,
+ }
+ *first = bit;
+ *airq_info = info;
+- indicator_addr = (unsigned long)info->aiv->vector;
++ indicator_addr = info->aiv->vector;
+ for (j = 0; j < nvqs; j++) {
+ airq_iv_set_ptr(info->aiv, bit + j,
+ (unsigned long)vqs[j]);
+@@ -358,11 +358,11 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
+ if (!thinint_area)
+ return;
+ thinint_area->summary_indicator =
+- (unsigned long) get_summary_indicator(airq_info);
++ virt_to_dma64(get_summary_indicator(airq_info));
+ thinint_area->isc = VIRTIO_AIRQ_ISC;
+ ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
+ ccw->count = sizeof(*thinint_area);
+- ccw->cda = (__u32)virt_to_phys(thinint_area);
++ ccw->cda = virt_to_dma32(thinint_area);
+ } else {
+ /* payload is the address of the indicators */
+ indicatorp = ccw_device_dma_zalloc(vcdev->cdev,
+@@ -372,7 +372,7 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
+ *indicatorp = 0;
+ ccw->cmd_code = CCW_CMD_SET_IND;
+ ccw->count = sizeof(indicators(vcdev));
+- ccw->cda = (__u32)virt_to_phys(indicatorp);
++ ccw->cda = virt_to_dma32(indicatorp);
+ }
+ /* Deregister indicators from host. */
+ *indicators(vcdev) = 0;
+@@ -426,7 +426,7 @@ static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev,
+ ccw->cmd_code = CCW_CMD_READ_VQ_CONF;
+ ccw->flags = 0;
+ ccw->count = sizeof(struct vq_config_block);
+- ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->config_block);
++ ccw->cda = virt_to_dma32(&vcdev->dma_area->config_block);
+ ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF);
+ if (ret)
+ return ret;
+@@ -463,7 +463,7 @@ static void virtio_ccw_del_vq(struct virtqueue *vq, struct ccw1 *ccw)
+ }
+ ccw->cmd_code = CCW_CMD_SET_VQ;
+ ccw->flags = 0;
+- ccw->cda = (__u32)virt_to_phys(info->info_block);
++ ccw->cda = virt_to_dma32(info->info_block);
+ ret = ccw_io_helper(vcdev, ccw,
+ VIRTIO_CCW_DOING_SET_VQ | index);
+ /*
+@@ -556,22 +556,22 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
+ /* Register it with the host. */
+ queue = virtqueue_get_desc_addr(vq);
+ if (vcdev->revision == 0) {
+- info->info_block->l.queue = queue;
++ info->info_block->l.queue = u64_to_dma64(queue);
+ info->info_block->l.align = KVM_VIRTIO_CCW_RING_ALIGN;
+ info->info_block->l.index = i;
+ info->info_block->l.num = info->num;
+ ccw->count = sizeof(info->info_block->l);
+ } else {
+- info->info_block->s.desc = queue;
++ info->info_block->s.desc = u64_to_dma64(queue);
+ info->info_block->s.index = i;
+ info->info_block->s.num = info->num;
+- info->info_block->s.avail = (__u64)virtqueue_get_avail_addr(vq);
+- info->info_block->s.used = (__u64)virtqueue_get_used_addr(vq);
++ info->info_block->s.avail = u64_to_dma64(virtqueue_get_avail_addr(vq));
++ info->info_block->s.used = u64_to_dma64(virtqueue_get_used_addr(vq));
+ ccw->count = sizeof(info->info_block->s);
+ }
+ ccw->cmd_code = CCW_CMD_SET_VQ;
+ ccw->flags = 0;
+- ccw->cda = (__u32)virt_to_phys(info->info_block);
++ ccw->cda = virt_to_dma32(info->info_block);
+ err = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_VQ | i);
+ if (err) {
+ dev_warn(&vcdev->cdev->dev, "SET_VQ failed\n");
+@@ -605,7 +605,7 @@ static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev,
+ {
+ int ret;
+ struct virtio_thinint_area *thinint_area = NULL;
+- unsigned long indicator_addr;
++ unsigned long *indicator_addr;
+ struct airq_info *info;
+
+ thinint_area = ccw_device_dma_zalloc(vcdev->cdev,
+@@ -622,15 +622,15 @@ static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev,
+ ret = -ENOSPC;
+ goto out;
+ }
+- thinint_area->indicator = virt_to_phys((void *)indicator_addr);
++ thinint_area->indicator = virt_to_dma64(indicator_addr);
+ info = vcdev->airq_info;
+ thinint_area->summary_indicator =
+- virt_to_phys(get_summary_indicator(info));
++ virt_to_dma64(get_summary_indicator(info));
+ thinint_area->isc = VIRTIO_AIRQ_ISC;
+ ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
+ ccw->flags = CCW_FLAG_SLI;
+ ccw->count = sizeof(*thinint_area);
+- ccw->cda = (__u32)virt_to_phys(thinint_area);
++ ccw->cda = virt_to_dma32(thinint_area);
+ ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND_ADAPTER);
+ if (ret) {
+ if (ret == -EOPNOTSUPP) {
+@@ -658,7 +658,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+ struct irq_affinity *desc)
+ {
+ struct virtio_ccw_device *vcdev = to_vc_device(vdev);
+- unsigned long *indicatorp = NULL;
++ dma64_t *indicatorp = NULL;
+ int ret, i, queue_idx = 0;
+ struct ccw1 *ccw;
+
+@@ -690,7 +690,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+ sizeof(indicators(vcdev)));
+ if (!indicatorp)
+ goto out;
+- *indicatorp = (unsigned long) indicators(vcdev);
++ *indicatorp = virt_to_dma64(indicators(vcdev));
+ if (vcdev->is_thinint) {
+ ret = virtio_ccw_register_adapter_ind(vcdev, vqs, nvqs, ccw);
+ if (ret)
+@@ -703,18 +703,18 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+ ccw->cmd_code = CCW_CMD_SET_IND;
+ ccw->flags = 0;
+ ccw->count = sizeof(indicators(vcdev));
+- ccw->cda = (__u32)virt_to_phys(indicatorp);
++ ccw->cda = virt_to_dma32(indicatorp);
+ ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND);
+ if (ret)
+ goto out;
+ }
+ /* Register indicators2 with host for config changes */
+- *indicatorp = (unsigned long) indicators2(vcdev);
++ *indicatorp = virt_to_dma64(indicators2(vcdev));
+ *indicators2(vcdev) = 0;
+ ccw->cmd_code = CCW_CMD_SET_CONF_IND;
+ ccw->flags = 0;
+ ccw->count = sizeof(indicators2(vcdev));
+- ccw->cda = (__u32)virt_to_phys(indicatorp);
++ ccw->cda = virt_to_dma32(indicatorp);
+ ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_CONF_IND);
+ if (ret)
+ goto out;
+@@ -776,7 +776,7 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev)
+ ccw->cmd_code = CCW_CMD_READ_FEAT;
+ ccw->flags = 0;
+ ccw->count = sizeof(*features);
+- ccw->cda = (__u32)virt_to_phys(features);
++ ccw->cda = virt_to_dma32(features);
+ ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT);
+ if (ret) {
+ rc = 0;
+@@ -793,7 +793,7 @@ static u64 virtio_ccw_get_features(struct virtio_device *vdev)
+ ccw->cmd_code = CCW_CMD_READ_FEAT;
+ ccw->flags = 0;
+ ccw->count = sizeof(*features);
+- ccw->cda = (__u32)virt_to_phys(features);
++ ccw->cda = virt_to_dma32(features);
+ ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT);
+ if (ret == 0)
+ rc |= (u64)le32_to_cpu(features->features) << 32;
+@@ -846,7 +846,7 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev)
+ ccw->cmd_code = CCW_CMD_WRITE_FEAT;
+ ccw->flags = 0;
+ ccw->count = sizeof(*features);
+- ccw->cda = (__u32)virt_to_phys(features);
++ ccw->cda = virt_to_dma32(features);
+ ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT);
+ if (ret)
+ goto out_free;
+@@ -860,7 +860,7 @@ static int virtio_ccw_finalize_features(struct virtio_device *vdev)
+ ccw->cmd_code = CCW_CMD_WRITE_FEAT;
+ ccw->flags = 0;
+ ccw->count = sizeof(*features);
+- ccw->cda = (__u32)virt_to_phys(features);
++ ccw->cda = virt_to_dma32(features);
+ ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT);
+
+ out_free:
+@@ -892,7 +892,7 @@ static void virtio_ccw_get_config(struct virtio_device *vdev,
+ ccw->cmd_code = CCW_CMD_READ_CONF;
+ ccw->flags = 0;
+ ccw->count = offset + len;
+- ccw->cda = (__u32)virt_to_phys(config_area);
++ ccw->cda = virt_to_dma32(config_area);
+ ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_CONFIG);
+ if (ret)
+ goto out_free;
+@@ -939,7 +939,7 @@ static void virtio_ccw_set_config(struct virtio_device *vdev,
+ ccw->cmd_code = CCW_CMD_WRITE_CONF;
+ ccw->flags = 0;
+ ccw->count = offset + len;
+- ccw->cda = (__u32)virt_to_phys(config_area);
++ ccw->cda = virt_to_dma32(config_area);
+ ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_CONFIG);
+
+ out_free:
+@@ -963,7 +963,7 @@ static u8 virtio_ccw_get_status(struct virtio_device *vdev)
+ ccw->cmd_code = CCW_CMD_READ_STATUS;
+ ccw->flags = 0;
+ ccw->count = sizeof(vcdev->dma_area->status);
+- ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->status);
++ ccw->cda = virt_to_dma32(&vcdev->dma_area->status);
+ ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_STATUS);
+ /*
+ * If the channel program failed (should only happen if the device
+@@ -992,11 +992,11 @@ static void virtio_ccw_set_status(struct virtio_device *vdev, u8 status)
+ ccw->cmd_code = CCW_CMD_WRITE_STATUS;
+ ccw->flags = 0;
+ ccw->count = sizeof(status);
+- ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->status);
+ /* We use ssch for setting the status which is a serializing
+ * instruction that guarantees the memory writes have
+ * completed before ssch.
+ */
++ ccw->cda = virt_to_dma32(&vcdev->dma_area->status);
+ ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_STATUS);
+ /* Write failed? We assume status is unchanged. */
+ if (ret)
+@@ -1291,7 +1291,7 @@ static int virtio_ccw_set_transport_rev(struct virtio_ccw_device *vcdev)
+ ccw->cmd_code = CCW_CMD_SET_VIRTIO_REV;
+ ccw->flags = 0;
+ ccw->count = sizeof(*rev);
+- ccw->cda = (__u32)virt_to_phys(rev);
++ ccw->cda = virt_to_dma32(rev);
+
+ vcdev->revision = VIRTIO_CCW_REV_MAX;
+ do {
+--
+2.39.5
+
--- /dev/null
+From c0590d9e18fc2cdf8387e49c05e551d43ba56f59 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Nov 2023 14:39:03 +0100
+Subject: sched/cpufreq: Rework schedutil governor performance estimation
+
+From: Vincent Guittot <vincent.guittot@linaro.org>
+
+[ Upstream commit 9c0b4bb7f6303c9c4e2e34984c46f5a86478f84d ]
+
+The current method to take into account uclamp hints when estimating the
+target frequency can end in a situation where the selected target
+frequency is finally higher than uclamp hints, whereas there are no real
+needs. Such cases mainly happen because we are currently mixing the
+traditional scheduler utilization signal with the uclamp performance
+hints. By adding these 2 metrics, we loose an important information when
+it comes to select the target frequency, and we have to make some
+assumptions which can't fit all cases.
+
+Rework the interface between the scheduler and schedutil governor in order
+to propagate all information down to the cpufreq governor.
+
+effective_cpu_util() interface changes and now returns the actual
+utilization of the CPU with 2 optional inputs:
+
+- The minimum performance for this CPU; typically the capacity to handle
+ the deadline task and the interrupt pressure. But also uclamp_min
+ request when available.
+
+- The maximum targeting performance for this CPU which reflects the
+ maximum level that we would like to not exceed. By default it will be
+ the CPU capacity but can be reduced because of some performance hints
+ set with uclamp. The value can be lower than actual utilization and/or
+ min performance level.
+
+A new sugov_effective_cpu_perf() interface is also available to compute
+the final performance level that is targeted for the CPU, after applying
+some cpufreq headroom and taking into account all inputs.
+
+With these 2 functions, schedutil is now able to decide when it must go
+above uclamp hints. It now also has a generic way to get the min
+performance level.
+
+The dependency between energy model and cpufreq governor and its headroom
+policy doesn't exist anymore.
+
+eenv_pd_max_util() asks schedutil for the targeted performance after
+applying the impact of the waking task.
+
+[ mingo: Refined the changelog & C comments. ]
+
+Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Acked-by: Rafael J. Wysocki <rafael@kernel.org>
+Link: https://lore.kernel.org/r/20231122133904.446032-2-vincent.guittot@linaro.org
+Stable-dep-of: 79443a7e9da3 ("cpufreq/sched: Explicitly synchronize limits_changed flag handling")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/energy_model.h | 1 -
+ kernel/sched/core.c | 90 ++++++++++++++------------------
+ kernel/sched/cpufreq_schedutil.c | 35 +++++++++----
+ kernel/sched/fair.c | 22 ++++++--
+ kernel/sched/sched.h | 24 +++------
+ 5 files changed, 89 insertions(+), 83 deletions(-)
+
+diff --git a/include/linux/energy_model.h b/include/linux/energy_model.h
+index b9caa01dfac48..adec808b371a1 100644
+--- a/include/linux/energy_model.h
++++ b/include/linux/energy_model.h
+@@ -243,7 +243,6 @@ static inline unsigned long em_cpu_energy(struct em_perf_domain *pd,
+ scale_cpu = arch_scale_cpu_capacity(cpu);
+ ps = &pd->table[pd->nr_perf_states - 1];
+
+- max_util = map_util_perf(max_util);
+ max_util = min(max_util, allowed_cpu_cap);
+ freq = map_util_freq(max_util, ps->frequency, scale_cpu);
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 41f035744683b..760a6c3781cbf 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -7406,18 +7406,13 @@ int sched_core_idle_cpu(int cpu)
+ * required to meet deadlines.
+ */
+ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
+- enum cpu_util_type type,
+- struct task_struct *p)
++ unsigned long *min,
++ unsigned long *max)
+ {
+- unsigned long dl_util, util, irq, max;
++ unsigned long util, irq, scale;
+ struct rq *rq = cpu_rq(cpu);
+
+- max = arch_scale_cpu_capacity(cpu);
+-
+- if (!uclamp_is_used() &&
+- type == FREQUENCY_UTIL && rt_rq_is_runnable(&rq->rt)) {
+- return max;
+- }
++ scale = arch_scale_cpu_capacity(cpu);
+
+ /*
+ * Early check to see if IRQ/steal time saturates the CPU, can be
+@@ -7425,45 +7420,49 @@ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
+ * update_irq_load_avg().
+ */
+ irq = cpu_util_irq(rq);
+- if (unlikely(irq >= max))
+- return max;
++ if (unlikely(irq >= scale)) {
++ if (min)
++ *min = scale;
++ if (max)
++ *max = scale;
++ return scale;
++ }
++
++ if (min) {
++ /*
++ * The minimum utilization returns the highest level between:
++ * - the computed DL bandwidth needed with the IRQ pressure which
++ * steals time to the deadline task.
++ * - The minimum performance requirement for CFS and/or RT.
++ */
++ *min = max(irq + cpu_bw_dl(rq), uclamp_rq_get(rq, UCLAMP_MIN));
++
++ /*
++ * When an RT task is runnable and uclamp is not used, we must
++ * ensure that the task will run at maximum compute capacity.
++ */
++ if (!uclamp_is_used() && rt_rq_is_runnable(&rq->rt))
++ *min = max(*min, scale);
++ }
+
+ /*
+ * Because the time spend on RT/DL tasks is visible as 'lost' time to
+ * CFS tasks and we use the same metric to track the effective
+ * utilization (PELT windows are synchronized) we can directly add them
+ * to obtain the CPU's actual utilization.
+- *
+- * CFS and RT utilization can be boosted or capped, depending on
+- * utilization clamp constraints requested by currently RUNNABLE
+- * tasks.
+- * When there are no CFS RUNNABLE tasks, clamps are released and
+- * frequency will be gracefully reduced with the utilization decay.
+ */
+ util = util_cfs + cpu_util_rt(rq);
+- if (type == FREQUENCY_UTIL)
+- util = uclamp_rq_util_with(rq, util, p);
+-
+- dl_util = cpu_util_dl(rq);
++ util += cpu_util_dl(rq);
+
+ /*
+- * For frequency selection we do not make cpu_util_dl() a permanent part
+- * of this sum because we want to use cpu_bw_dl() later on, but we need
+- * to check if the CFS+RT+DL sum is saturated (ie. no idle time) such
+- * that we select f_max when there is no idle time.
+- *
+- * NOTE: numerical errors or stop class might cause us to not quite hit
+- * saturation when we should -- something for later.
++ * The maximum hint is a soft bandwidth requirement, which can be lower
++ * than the actual utilization because of uclamp_max requirements.
+ */
+- if (util + dl_util >= max)
+- return max;
++ if (max)
++ *max = min(scale, uclamp_rq_get(rq, UCLAMP_MAX));
+
+- /*
+- * OTOH, for energy computation we need the estimated running time, so
+- * include util_dl and ignore dl_bw.
+- */
+- if (type == ENERGY_UTIL)
+- util += dl_util;
++ if (util >= scale)
++ return scale;
+
+ /*
+ * There is still idle time; further improve the number by using the
+@@ -7474,28 +7473,15 @@ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
+ * U' = irq + --------- * U
+ * max
+ */
+- util = scale_irq_capacity(util, irq, max);
++ util = scale_irq_capacity(util, irq, scale);
+ util += irq;
+
+- /*
+- * Bandwidth required by DEADLINE must always be granted while, for
+- * FAIR and RT, we use blocked utilization of IDLE CPUs as a mechanism
+- * to gracefully reduce the frequency when no tasks show up for longer
+- * periods of time.
+- *
+- * Ideally we would like to set bw_dl as min/guaranteed freq and util +
+- * bw_dl as requested freq. However, cpufreq is not yet ready for such
+- * an interface. So, we only do the latter for now.
+- */
+- if (type == FREQUENCY_UTIL)
+- util += cpu_bw_dl(rq);
+-
+- return min(max, util);
++ return min(scale, util);
+ }
+
+ unsigned long sched_cpu_util(int cpu)
+ {
+- return effective_cpu_util(cpu, cpu_util_cfs(cpu), ENERGY_UTIL, NULL);
++ return effective_cpu_util(cpu, cpu_util_cfs(cpu), NULL, NULL);
+ }
+ #endif /* CONFIG_SMP */
+
+diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
+index 259521b179aa1..f84473f73ed00 100644
+--- a/kernel/sched/cpufreq_schedutil.c
++++ b/kernel/sched/cpufreq_schedutil.c
+@@ -47,7 +47,7 @@ struct sugov_cpu {
+ u64 last_update;
+
+ unsigned long util;
+- unsigned long bw_dl;
++ unsigned long bw_min;
+
+ /* The field below is for single-CPU policies only: */
+ #ifdef CONFIG_NO_HZ_COMMON
+@@ -155,7 +155,6 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy,
+ unsigned int freq = arch_scale_freq_invariant() ?
+ policy->cpuinfo.max_freq : policy->cur;
+
+- util = map_util_perf(util);
+ freq = map_util_freq(util, freq, max);
+
+ if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update)
+@@ -165,14 +164,30 @@ static unsigned int get_next_freq(struct sugov_policy *sg_policy,
+ return cpufreq_driver_resolve_freq(policy, freq);
+ }
+
++unsigned long sugov_effective_cpu_perf(int cpu, unsigned long actual,
++ unsigned long min,
++ unsigned long max)
++{
++ /* Add dvfs headroom to actual utilization */
++ actual = map_util_perf(actual);
++ /* Actually we don't need to target the max performance */
++ if (actual < max)
++ max = actual;
++
++ /*
++ * Ensure at least minimum performance while providing more compute
++ * capacity when possible.
++ */
++ return max(min, max);
++}
++
+ static void sugov_get_util(struct sugov_cpu *sg_cpu)
+ {
+- unsigned long util = cpu_util_cfs_boost(sg_cpu->cpu);
+- struct rq *rq = cpu_rq(sg_cpu->cpu);
++ unsigned long min, max, util = cpu_util_cfs_boost(sg_cpu->cpu);
+
+- sg_cpu->bw_dl = cpu_bw_dl(rq);
+- sg_cpu->util = effective_cpu_util(sg_cpu->cpu, util,
+- FREQUENCY_UTIL, NULL);
++ util = effective_cpu_util(sg_cpu->cpu, util, &min, &max);
++ sg_cpu->bw_min = min;
++ sg_cpu->util = sugov_effective_cpu_perf(sg_cpu->cpu, util, min, max);
+ }
+
+ /**
+@@ -318,7 +333,7 @@ static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; }
+ */
+ static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu)
+ {
+- if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl)
++ if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_min)
+ sg_cpu->sg_policy->limits_changed = true;
+ }
+
+@@ -419,8 +434,8 @@ static void sugov_update_single_perf(struct update_util_data *hook, u64 time,
+ sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util)
+ sg_cpu->util = prev_util;
+
+- cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
+- map_util_perf(sg_cpu->util), max_cap);
++ cpufreq_driver_adjust_perf(sg_cpu->cpu, sg_cpu->bw_min,
++ sg_cpu->util, max_cap);
+
+ sg_cpu->sg_policy->last_freq_update_time = time;
+ }
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 050cc41585f8b..268e2a49b964e 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -7859,7 +7859,7 @@ static inline void eenv_pd_busy_time(struct energy_env *eenv,
+ for_each_cpu(cpu, pd_cpus) {
+ unsigned long util = cpu_util(cpu, p, -1, 0);
+
+- busy_time += effective_cpu_util(cpu, util, ENERGY_UTIL, NULL);
++ busy_time += effective_cpu_util(cpu, util, NULL, NULL);
+ }
+
+ eenv->pd_busy_time = min(eenv->pd_cap, busy_time);
+@@ -7882,7 +7882,7 @@ eenv_pd_max_util(struct energy_env *eenv, struct cpumask *pd_cpus,
+ for_each_cpu(cpu, pd_cpus) {
+ struct task_struct *tsk = (cpu == dst_cpu) ? p : NULL;
+ unsigned long util = cpu_util(cpu, p, dst_cpu, 1);
+- unsigned long eff_util;
++ unsigned long eff_util, min, max;
+
+ /*
+ * Performance domain frequency: utilization clamping
+@@ -7891,7 +7891,23 @@ eenv_pd_max_util(struct energy_env *eenv, struct cpumask *pd_cpus,
+ * NOTE: in case RT tasks are running, by default the
+ * FREQUENCY_UTIL's utilization can be max OPP.
+ */
+- eff_util = effective_cpu_util(cpu, util, FREQUENCY_UTIL, tsk);
++ eff_util = effective_cpu_util(cpu, util, &min, &max);
++
++ /* Task's uclamp can modify min and max value */
++ if (tsk && uclamp_is_used()) {
++ min = max(min, uclamp_eff_value(p, UCLAMP_MIN));
++
++ /*
++ * If there is no active max uclamp constraint,
++ * directly use task's one, otherwise keep max.
++ */
++ if (uclamp_rq_is_idle(cpu_rq(cpu)))
++ max = uclamp_eff_value(p, UCLAMP_MAX);
++ else
++ max = max(max, uclamp_eff_value(p, UCLAMP_MAX));
++ }
++
++ eff_util = sugov_effective_cpu_perf(cpu, eff_util, min, max);
+ max_util = max(max_util, eff_util);
+ }
+
+diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
+index f84b2e9feeb6d..60dc51f43dd91 100644
+--- a/kernel/sched/sched.h
++++ b/kernel/sched/sched.h
+@@ -2984,24 +2984,14 @@ static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {}
+ #endif
+
+ #ifdef CONFIG_SMP
+-/**
+- * enum cpu_util_type - CPU utilization type
+- * @FREQUENCY_UTIL: Utilization used to select frequency
+- * @ENERGY_UTIL: Utilization used during energy calculation
+- *
+- * The utilization signals of all scheduling classes (CFS/RT/DL) and IRQ time
+- * need to be aggregated differently depending on the usage made of them. This
+- * enum is used within effective_cpu_util() to differentiate the types of
+- * utilization expected by the callers, and adjust the aggregation accordingly.
+- */
+-enum cpu_util_type {
+- FREQUENCY_UTIL,
+- ENERGY_UTIL,
+-};
+-
+ unsigned long effective_cpu_util(int cpu, unsigned long util_cfs,
+- enum cpu_util_type type,
+- struct task_struct *p);
++ unsigned long *min,
++ unsigned long *max);
++
++unsigned long sugov_effective_cpu_perf(int cpu, unsigned long actual,
++ unsigned long min,
++ unsigned long max);
++
+
+ /*
+ * Verify the fitness of task @p to run on @cpu taking into account the
+--
+2.39.5
+
--- /dev/null
+From 353421b4bbdde7120bb1d8acbdc64bccd67e5fd6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Oct 2023 12:36:16 +0200
+Subject: sched/topology: Consolidate and clean up access to a CPU's max
+ compute capacity
+
+From: Vincent Guittot <vincent.guittot@linaro.org>
+
+[ Upstream commit 7bc263840bc3377186cb06b003ac287bb2f18ce2 ]
+
+Remove the rq::cpu_capacity_orig field and use arch_scale_cpu_capacity()
+instead.
+
+The scheduler uses 3 methods to get access to a CPU's max compute capacity:
+
+ - arch_scale_cpu_capacity(cpu) which is the default way to get a CPU's capacity.
+
+ - cpu_capacity_orig field which is periodically updated with
+ arch_scale_cpu_capacity().
+
+ - capacity_orig_of(cpu) which encapsulates rq->cpu_capacity_orig.
+
+There is no real need to save the value returned by arch_scale_cpu_capacity()
+in struct rq. arch_scale_cpu_capacity() returns:
+
+ - either a per_cpu variable.
+
+ - or a const value for systems which have only one capacity.
+
+Remove rq::cpu_capacity_orig and use arch_scale_cpu_capacity() everywhere.
+
+No functional changes.
+
+Some performance tests on Arm64:
+
+ - small SMP device (hikey): no noticeable changes
+ - HMP device (RB5): hackbench shows minor improvement (1-2%)
+ - large smp (thx2): hackbench and tbench shows minor improvement (1%)
+
+Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Link: https://lore.kernel.org/r/20231009103621.374412-2-vincent.guittot@linaro.org
+Stable-dep-of: 79443a7e9da3 ("cpufreq/sched: Explicitly synchronize limits_changed flag handling")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/scheduler/sched-capacity.rst | 13 +++++++------
+ kernel/sched/core.c | 2 +-
+ kernel/sched/cpudeadline.c | 2 +-
+ kernel/sched/deadline.c | 4 ++--
+ kernel/sched/fair.c | 18 ++++++++----------
+ kernel/sched/rt.c | 2 +-
+ kernel/sched/sched.h | 6 ------
+ kernel/sched/topology.c | 7 +++++--
+ 8 files changed, 25 insertions(+), 29 deletions(-)
+
+diff --git a/Documentation/scheduler/sched-capacity.rst b/Documentation/scheduler/sched-capacity.rst
+index e2c1cf7431588..de414b33dd2ab 100644
+--- a/Documentation/scheduler/sched-capacity.rst
++++ b/Documentation/scheduler/sched-capacity.rst
+@@ -39,14 +39,15 @@ per Hz, leading to::
+ -------------------
+
+ Two different capacity values are used within the scheduler. A CPU's
+-``capacity_orig`` is its maximum attainable capacity, i.e. its maximum
+-attainable performance level. A CPU's ``capacity`` is its ``capacity_orig`` to
+-which some loss of available performance (e.g. time spent handling IRQs) is
+-subtracted.
++``original capacity`` is its maximum attainable capacity, i.e. its maximum
++attainable performance level. This original capacity is returned by
++the function arch_scale_cpu_capacity(). A CPU's ``capacity`` is its ``original
++capacity`` to which some loss of available performance (e.g. time spent
++handling IRQs) is subtracted.
+
+ Note that a CPU's ``capacity`` is solely intended to be used by the CFS class,
+-while ``capacity_orig`` is class-agnostic. The rest of this document will use
+-the term ``capacity`` interchangeably with ``capacity_orig`` for the sake of
++while ``original capacity`` is class-agnostic. The rest of this document will use
++the term ``capacity`` interchangeably with ``original capacity`` for the sake of
+ brevity.
+
+ 1.3 Platform examples
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 8c5f75af07db0..41f035744683b 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -10048,7 +10048,7 @@ void __init sched_init(void)
+ #ifdef CONFIG_SMP
+ rq->sd = NULL;
+ rq->rd = NULL;
+- rq->cpu_capacity = rq->cpu_capacity_orig = SCHED_CAPACITY_SCALE;
++ rq->cpu_capacity = SCHED_CAPACITY_SCALE;
+ rq->balance_callback = &balance_push_callback;
+ rq->active_balance = 0;
+ rq->next_balance = jiffies;
+diff --git a/kernel/sched/cpudeadline.c b/kernel/sched/cpudeadline.c
+index 57c92d751bcd7..95baa12a10293 100644
+--- a/kernel/sched/cpudeadline.c
++++ b/kernel/sched/cpudeadline.c
+@@ -131,7 +131,7 @@ int cpudl_find(struct cpudl *cp, struct task_struct *p,
+ if (!dl_task_fits_capacity(p, cpu)) {
+ cpumask_clear_cpu(cpu, later_mask);
+
+- cap = capacity_orig_of(cpu);
++ cap = arch_scale_cpu_capacity(cpu);
+
+ if (cap > max_cap ||
+ (cpu == task_cpu(p) && cap == max_cap)) {
+diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
+index 6c639e48e49a9..a15cf7969953a 100644
+--- a/kernel/sched/deadline.c
++++ b/kernel/sched/deadline.c
+@@ -132,7 +132,7 @@ static inline unsigned long __dl_bw_capacity(const struct cpumask *mask)
+ int i;
+
+ for_each_cpu_and(i, mask, cpu_active_mask)
+- cap += capacity_orig_of(i);
++ cap += arch_scale_cpu_capacity(i);
+
+ return cap;
+ }
+@@ -144,7 +144,7 @@ static inline unsigned long __dl_bw_capacity(const struct cpumask *mask)
+ static inline unsigned long dl_bw_capacity(int i)
+ {
+ if (!sched_asym_cpucap_active() &&
+- capacity_orig_of(i) == SCHED_CAPACITY_SCALE) {
++ arch_scale_cpu_capacity(i) == SCHED_CAPACITY_SCALE) {
+ return dl_bw_cpus(i) << SCHED_CAPACITY_SHIFT;
+ } else {
+ RCU_LOCKDEP_WARN(!rcu_read_lock_sched_held(),
+diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
+index 2808dbdd03847..050cc41585f8b 100644
+--- a/kernel/sched/fair.c
++++ b/kernel/sched/fair.c
+@@ -4951,7 +4951,7 @@ static inline void util_est_update(struct cfs_rq *cfs_rq,
+ * To avoid overestimation of actual task utilization, skip updates if
+ * we cannot grant there is idle time in this CPU.
+ */
+- if (task_util(p) > capacity_orig_of(cpu_of(rq_of(cfs_rq))))
++ if (task_util(p) > arch_scale_cpu_capacity(cpu_of(rq_of(cfs_rq))))
+ return;
+
+ /*
+@@ -4999,14 +4999,14 @@ static inline int util_fits_cpu(unsigned long util,
+ return fits;
+
+ /*
+- * We must use capacity_orig_of() for comparing against uclamp_min and
++ * We must use arch_scale_cpu_capacity() for comparing against uclamp_min and
+ * uclamp_max. We only care about capacity pressure (by using
+ * capacity_of()) for comparing against the real util.
+ *
+ * If a task is boosted to 1024 for example, we don't want a tiny
+ * pressure to skew the check whether it fits a CPU or not.
+ *
+- * Similarly if a task is capped to capacity_orig_of(little_cpu), it
++ * Similarly if a task is capped to arch_scale_cpu_capacity(little_cpu), it
+ * should fit a little cpu even if there's some pressure.
+ *
+ * Only exception is for thermal pressure since it has a direct impact
+@@ -5018,7 +5018,7 @@ static inline int util_fits_cpu(unsigned long util,
+ * For uclamp_max, we can tolerate a drop in performance level as the
+ * goal is to cap the task. So it's okay if it's getting less.
+ */
+- capacity_orig = capacity_orig_of(cpu);
++ capacity_orig = arch_scale_cpu_capacity(cpu);
+ capacity_orig_thermal = capacity_orig - arch_scale_thermal_pressure(cpu);
+
+ /*
+@@ -7515,7 +7515,7 @@ select_idle_capacity(struct task_struct *p, struct sched_domain *sd, int target)
+ * Look for the CPU with best capacity.
+ */
+ else if (fits < 0)
+- cpu_cap = capacity_orig_of(cpu) - thermal_load_avg(cpu_rq(cpu));
++ cpu_cap = arch_scale_cpu_capacity(cpu) - thermal_load_avg(cpu_rq(cpu));
+
+ /*
+ * First, select CPU which fits better (-1 being better than 0).
+@@ -7757,7 +7757,7 @@ cpu_util(int cpu, struct task_struct *p, int dst_cpu, int boost)
+ util = max(util, util_est);
+ }
+
+- return min(util, capacity_orig_of(cpu));
++ return min(util, arch_scale_cpu_capacity(cpu));
+ }
+
+ unsigned long cpu_util_cfs(int cpu)
+@@ -9544,8 +9544,6 @@ static void update_cpu_capacity(struct sched_domain *sd, int cpu)
+ unsigned long capacity = scale_rt_capacity(cpu);
+ struct sched_group *sdg = sd->groups;
+
+- cpu_rq(cpu)->cpu_capacity_orig = arch_scale_cpu_capacity(cpu);
+-
+ if (!capacity)
+ capacity = 1;
+
+@@ -9621,7 +9619,7 @@ static inline int
+ check_cpu_capacity(struct rq *rq, struct sched_domain *sd)
+ {
+ return ((rq->cpu_capacity * sd->imbalance_pct) <
+- (rq->cpu_capacity_orig * 100));
++ (arch_scale_cpu_capacity(cpu_of(rq)) * 100));
+ }
+
+ /*
+@@ -9632,7 +9630,7 @@ check_cpu_capacity(struct rq *rq, struct sched_domain *sd)
+ static inline int check_misfit_status(struct rq *rq, struct sched_domain *sd)
+ {
+ return rq->misfit_task_load &&
+- (rq->cpu_capacity_orig < rq->rd->max_cpu_capacity ||
++ (arch_scale_cpu_capacity(rq->cpu) < rq->rd->max_cpu_capacity ||
+ check_cpu_capacity(rq, sd));
+ }
+
+diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
+index b89223a973168..91b1ee0d81fce 100644
+--- a/kernel/sched/rt.c
++++ b/kernel/sched/rt.c
+@@ -519,7 +519,7 @@ static inline bool rt_task_fits_capacity(struct task_struct *p, int cpu)
+ min_cap = uclamp_eff_value(p, UCLAMP_MIN);
+ max_cap = uclamp_eff_value(p, UCLAMP_MAX);
+
+- cpu_cap = capacity_orig_of(cpu);
++ cpu_cap = arch_scale_cpu_capacity(cpu);
+
+ return cpu_cap >= min(min_cap, max_cap);
+ }
+diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
+index d48c6a292a83d..f84b2e9feeb6d 100644
+--- a/kernel/sched/sched.h
++++ b/kernel/sched/sched.h
+@@ -1048,7 +1048,6 @@ struct rq {
+ struct sched_domain __rcu *sd;
+
+ unsigned long cpu_capacity;
+- unsigned long cpu_capacity_orig;
+
+ struct balance_callback *balance_callback;
+
+@@ -2985,11 +2984,6 @@ static inline void cpufreq_update_util(struct rq *rq, unsigned int flags) {}
+ #endif
+
+ #ifdef CONFIG_SMP
+-static inline unsigned long capacity_orig_of(int cpu)
+-{
+- return cpu_rq(cpu)->cpu_capacity_orig;
+-}
+-
+ /**
+ * enum cpu_util_type - CPU utilization type
+ * @FREQUENCY_UTIL: Utilization used to select frequency
+diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
+index 2ed884bb36213..c61698cff0f3a 100644
+--- a/kernel/sched/topology.c
++++ b/kernel/sched/topology.c
+@@ -2486,12 +2486,15 @@ build_sched_domains(const struct cpumask *cpu_map, struct sched_domain_attr *att
+ /* Attach the domains */
+ rcu_read_lock();
+ for_each_cpu(i, cpu_map) {
++ unsigned long capacity;
++
+ rq = cpu_rq(i);
+ sd = *per_cpu_ptr(d.sd, i);
+
++ capacity = arch_scale_cpu_capacity(i);
+ /* Use READ_ONCE()/WRITE_ONCE() to avoid load/store tearing: */
+- if (rq->cpu_capacity_orig > READ_ONCE(d.rd->max_cpu_capacity))
+- WRITE_ONCE(d.rd->max_cpu_capacity, rq->cpu_capacity_orig);
++ if (capacity > READ_ONCE(d.rd->max_cpu_capacity))
++ WRITE_ONCE(d.rd->max_cpu_capacity, capacity);
+
+ cpu_attach_domain(sd, d.rd, i);
+ }
+--
+2.39.5
+
--- /dev/null
+From caf79cff3aded95c4b9003cddc1d8117adcc74a8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jan 2025 14:18:52 +0000
+Subject: scsi: ufs: qcom: fix dev reference leaked through of_qcom_ice_get
+
+From: Tudor Ambarus <tudor.ambarus@linaro.org>
+
+[ Upstream commit ded40f32b55f7f2f4ed9627dd3c37a1fe89ed8c6 ]
+
+The driver leaks the device reference taken with
+of_find_device_by_node(). Fix the leak by using devm_of_qcom_ice_get().
+
+Fixes: 56541c7c4468 ("scsi: ufs: ufs-qcom: Switch to the new ICE API")
+Cc: stable@vger.kernel.org
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
+Acked-by: Martin K. Petersen <martin.petersen@oracle.com> # SCSI
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-3-1ffa5b6884cb@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ufs/host/ufs-qcom.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
+index 51ed40529f9a7..c6417ef074a47 100644
+--- a/drivers/ufs/host/ufs-qcom.c
++++ b/drivers/ufs/host/ufs-qcom.c
+@@ -121,7 +121,7 @@ static int ufs_qcom_ice_init(struct ufs_qcom_host *host)
+ struct device *dev = hba->dev;
+ struct qcom_ice *ice;
+
+- ice = of_qcom_ice_get(dev);
++ ice = devm_of_qcom_ice_get(dev);
+ if (ice == ERR_PTR(-EOPNOTSUPP)) {
+ dev_warn(dev, "Disabling inline encryption support\n");
+ ice = NULL;
+--
+2.39.5
+
module-sign-with-sha512-instead-of-sha1-by-default.patch
+memcg-drain-obj-stock-on-cpu-hotplug-teardown.patch
+x86-extable-remove-unused-fixup-type-ex_type_copy.patch
+x86-mce-use-is_copy_from_user-to-determine-copy-from.patch
+tracing-add-__string_len-example.patch
+tracing-add-__print_dynamic_array-helper.patch
+tracing-verify-event-formats-that-have-p.patch
+media-subdev-fix-use-of-sd-enabled_streams-in-call_s.patch
+media-subdev-improve-v4l2_subdev_enable-disable_stre.patch
+media-subdev-add-v4l2_subdev_is_streaming.patch
+media-vimc-skip-.s_stream-for-stopped-entities.patch
+soc-qcom-ice-introduce-devm_of_qcom_ice_get.patch
+mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qc.patch
+auxdisplay-hd44780-convert-to-platform-remove-callba.patch
+auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch
+net-dsa-mv88e6xxx-fix-internal-phys-for-6320-family.patch
+net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch
+asoc-qcom-q6apm-dai-drop-unused-q6apm_dai_rtd-fields.patch
+asoc-q6apm-dai-schedule-all-available-frames-to-avoi.patch
+asoc-qcom-lpass-make-asoc_qcom_lpass_cpu_platform_re.patch
+asoc-qcom-fix-trivial-code-style-issues.patch
+asoc-q6apm-dai-make-use-of-q6apm_get_hw_pointer.patch
+iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch
+iio-adc-ad7768-1-fix-conversion-result-sign.patch
+arm64-tegra-remove-the-orin-nx-nano-suspend-key.patch
+clk-renesas-rzg2l-use-u32-for-flag-and-mux_flags.patch
+clk-renesas-rzg2l-add-struct-clk_hw_data.patch
+clk-renesas-rzg2l-remove-cpg_sdhi_dsel-from-generic-.patch
+clk-renesas-rzg2l-refactor-sd-mux-driver.patch
+clk-renesas-r9a07g04-34-use-sel_sdhi1_sts-status-con.patch
+clk-renesas-r9a07g04-34-fix-typo-for-sel_shdi-variab.patch
+clk-renesas-r9a07g043-fix-hp-clock-source-for-rz-fiv.patch
+of-resolver-simplify-of_resolve_phandles-using-__fre.patch
+of-resolver-fix-device-node-refcount-leakage-in-of_r.patch
+pci-fix-reference-leak-in-pci_register_host_bridge.patch
+s390-virtio_ccw-fix-virtual-vs-physical-address-conf.patch
+s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-.patch
+scsi-ufs-qcom-fix-dev-reference-leaked-through-of_qc.patch
+s390-sclp-allow-user-space-to-provide-pci-reports-fo.patch
+s390-pci-report-pci-error-recovery-results-via-sclp.patch
+s390-pci-support-mmap-of-pci-resources-except-for-is.patch
+sched-topology-consolidate-and-clean-up-access-to-a-.patch
+sched-cpufreq-rework-schedutil-governor-performance-.patch
+cpufreq-sched-explicitly-synchronize-limits_changed-.patch
--- /dev/null
+From 40b27638f9cbdfc2f28f6e2019f479968a200d8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jan 2025 14:18:50 +0000
+Subject: soc: qcom: ice: introduce devm_of_qcom_ice_get
+
+From: Tudor Ambarus <tudor.ambarus@linaro.org>
+
+[ Upstream commit 1c13d6060d612601a61423f2e8fbf9e48126acca ]
+
+Callers of of_qcom_ice_get() leak the device reference taken by
+of_find_device_by_node(). Introduce devm variant for of_qcom_ice_get().
+Existing consumers need the ICE instance for the entire life of their
+device, thus exporting qcom_ice_put() is not required.
+
+Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Abel Vesa <abel.vesa@linaro.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20250117-qcom-ice-fix-dev-leak-v2-1-1ffa5b6884cb@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Stable-dep-of: cbef7442fba5 ("mmc: sdhci-msm: fix dev reference leaked through of_qcom_ice_get")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/qcom/ice.c | 48 ++++++++++++++++++++++++++++++++++++++++++
+ include/soc/qcom/ice.h | 2 ++
+ 2 files changed, 50 insertions(+)
+
+diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
+index fbab7fe5c652b..d6e205e3812a9 100644
+--- a/drivers/soc/qcom/ice.c
++++ b/drivers/soc/qcom/ice.c
+@@ -10,6 +10,7 @@
+ #include <linux/bitfield.h>
+ #include <linux/clk.h>
+ #include <linux/delay.h>
++#include <linux/device.h>
+ #include <linux/iopoll.h>
+ #include <linux/of.h>
+ #include <linux/of_platform.h>
+@@ -328,6 +329,53 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev)
+ }
+ EXPORT_SYMBOL_GPL(of_qcom_ice_get);
+
++static void qcom_ice_put(const struct qcom_ice *ice)
++{
++ struct platform_device *pdev = to_platform_device(ice->dev);
++
++ if (!platform_get_resource_byname(pdev, IORESOURCE_MEM, "ice"))
++ platform_device_put(pdev);
++}
++
++static void devm_of_qcom_ice_put(struct device *dev, void *res)
++{
++ qcom_ice_put(*(struct qcom_ice **)res);
++}
++
++/**
++ * devm_of_qcom_ice_get() - Devres managed helper to get an ICE instance from
++ * a DT node.
++ * @dev: device pointer for the consumer device.
++ *
++ * This function will provide an ICE instance either by creating one for the
++ * consumer device if its DT node provides the 'ice' reg range and the 'ice'
++ * clock (for legacy DT style). On the other hand, if consumer provides a
++ * phandle via 'qcom,ice' property to an ICE DT, the ICE instance will already
++ * be created and so this function will return that instead.
++ *
++ * Return: ICE pointer on success, NULL if there is no ICE data provided by the
++ * consumer or ERR_PTR() on error.
++ */
++struct qcom_ice *devm_of_qcom_ice_get(struct device *dev)
++{
++ struct qcom_ice *ice, **dr;
++
++ dr = devres_alloc(devm_of_qcom_ice_put, sizeof(*dr), GFP_KERNEL);
++ if (!dr)
++ return ERR_PTR(-ENOMEM);
++
++ ice = of_qcom_ice_get(dev);
++ if (!IS_ERR_OR_NULL(ice)) {
++ *dr = ice;
++ devres_add(dev, dr);
++ } else {
++ devres_free(dr);
++ }
++
++ return ice;
++}
++EXPORT_SYMBOL_GPL(devm_of_qcom_ice_get);
++
+ static int qcom_ice_probe(struct platform_device *pdev)
+ {
+ struct qcom_ice *engine;
+diff --git a/include/soc/qcom/ice.h b/include/soc/qcom/ice.h
+index 5870a94599a25..d5f6a228df659 100644
+--- a/include/soc/qcom/ice.h
++++ b/include/soc/qcom/ice.h
+@@ -34,4 +34,6 @@ int qcom_ice_program_key(struct qcom_ice *ice,
+ int slot);
+ int qcom_ice_evict_key(struct qcom_ice *ice, int slot);
+ struct qcom_ice *of_qcom_ice_get(struct device *dev);
++struct qcom_ice *devm_of_qcom_ice_get(struct device *dev);
++
+ #endif /* __QCOM_ICE_H__ */
+--
+2.39.5
+
--- /dev/null
+From 6df2d8dfa5e9dfaac719bc16a39fc3bdb0e18a3d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Oct 2024 19:36:28 +0000
+Subject: tracing: Add __print_dynamic_array() helper
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit e52750fb1458ae9ea5860a08ed7a149185bc5b97 ]
+
+When printing a dynamic array in a trace event, the method is rather ugly.
+It has the format of:
+
+ __print_array(__get_dynamic_array(array),
+ __get_dynmaic_array_len(array) / el_size, el_size)
+
+Since dynamic arrays are known to the tracing infrastructure, create a
+helper macro that does the above for you.
+
+ __print_dynamic_array(array, el_size)
+
+Which would expand to the same output.
+
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Avadhut Naik <avadhut.naik@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
+Link: https://lore.kernel.org/r/20241022194158.110073-3-avadhut.naik@amd.com
+Stable-dep-of: ea8d7647f9dd ("tracing: Verify event formats that have "%*p.."")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/stages/stage3_trace_output.h | 8 ++++++++
+ include/trace/stages/stage7_class_define.h | 1 +
+ samples/trace_events/trace-events-sample.h | 7 ++++++-
+ 3 files changed, 15 insertions(+), 1 deletion(-)
+
+diff --git a/include/trace/stages/stage3_trace_output.h b/include/trace/stages/stage3_trace_output.h
+index c1fb1355d3094..1e7b0bef95f52 100644
+--- a/include/trace/stages/stage3_trace_output.h
++++ b/include/trace/stages/stage3_trace_output.h
+@@ -119,6 +119,14 @@
+ trace_print_array_seq(p, array, count, el_size); \
+ })
+
++#undef __print_dynamic_array
++#define __print_dynamic_array(array, el_size) \
++ ({ \
++ __print_array(__get_dynamic_array(array), \
++ __get_dynamic_array_len(array) / (el_size), \
++ (el_size)); \
++ })
++
+ #undef __print_hex_dump
+ #define __print_hex_dump(prefix_str, prefix_type, \
+ rowsize, groupsize, buf, len, ascii) \
+diff --git a/include/trace/stages/stage7_class_define.h b/include/trace/stages/stage7_class_define.h
+index bcb960d16fc0e..fcd564a590f43 100644
+--- a/include/trace/stages/stage7_class_define.h
++++ b/include/trace/stages/stage7_class_define.h
+@@ -22,6 +22,7 @@
+ #undef __get_rel_cpumask
+ #undef __get_rel_sockaddr
+ #undef __print_array
++#undef __print_dynamic_array
+ #undef __print_hex_dump
+ #undef __get_buf
+
+diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h
+index 04541dfbd44cc..24ec968d481fb 100644
+--- a/samples/trace_events/trace-events-sample.h
++++ b/samples/trace_events/trace-events-sample.h
+@@ -317,7 +317,7 @@ TRACE_EVENT(foo_bar,
+ __assign_cpumask(cpum, cpumask_bits(mask));
+ ),
+
+- TP_printk("foo %s %d %s %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar,
++ TP_printk("foo %s %d %s %s %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar,
+
+ /*
+ * Notice here the use of some helper functions. This includes:
+@@ -361,6 +361,11 @@ TRACE_EVENT(foo_bar,
+ __print_array(__get_dynamic_array(list),
+ __get_dynamic_array_len(list) / sizeof(int),
+ sizeof(int)),
++
++/* A shortcut is to use __print_dynamic_array for dynamic arrays */
++
++ __print_dynamic_array(list, sizeof(int)),
++
+ __get_str(str), __get_str(lstr),
+ __get_bitmask(cpus), __get_cpumask(cpum),
+ __get_str(vstr))
+--
+2.39.5
+
--- /dev/null
+From 2434468173bcf0cd40b4214e532ae96afe32f738 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Feb 2024 15:28:27 -0500
+Subject: tracing: Add __string_len() example
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+[ Upstream commit dd6ae6d90a84d4bec49887c7aa2b22aa1c8b2897 ]
+
+There's no example code that uses __string_len(), and since the sample
+code is used for testing the event logic, add a use case.
+
+Link: https://lore.kernel.org/linux-trace-kernel/20240223152827.5f9f78e2@gandalf.local.home
+
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Stable-dep-of: ea8d7647f9dd ("tracing: Verify event formats that have "%*p.."")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ samples/trace_events/trace-events-sample.h | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h
+index 1c6b843b8c4ee..04541dfbd44cc 100644
+--- a/samples/trace_events/trace-events-sample.h
++++ b/samples/trace_events/trace-events-sample.h
+@@ -302,6 +302,7 @@ TRACE_EVENT(foo_bar,
+ __bitmask( cpus, num_possible_cpus() )
+ __cpumask( cpum )
+ __vstring( vstr, fmt, va )
++ __string_len( lstr, foo, bar / 2 < strlen(foo) ? bar / 2 : strlen(foo) )
+ ),
+
+ TP_fast_assign(
+@@ -310,12 +311,13 @@ TRACE_EVENT(foo_bar,
+ memcpy(__get_dynamic_array(list), lst,
+ __length_of(lst) * sizeof(int));
+ __assign_str(str, string);
++ __assign_str(lstr, foo);
+ __assign_vstr(vstr, fmt, va);
+ __assign_bitmask(cpus, cpumask_bits(mask), num_possible_cpus());
+ __assign_cpumask(cpum, cpumask_bits(mask));
+ ),
+
+- TP_printk("foo %s %d %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar,
++ TP_printk("foo %s %d %s %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar,
+
+ /*
+ * Notice here the use of some helper functions. This includes:
+@@ -359,7 +361,8 @@ TRACE_EVENT(foo_bar,
+ __print_array(__get_dynamic_array(list),
+ __get_dynamic_array_len(list) / sizeof(int),
+ sizeof(int)),
+- __get_str(str), __get_bitmask(cpus), __get_cpumask(cpum),
++ __get_str(str), __get_str(lstr),
++ __get_bitmask(cpus), __get_cpumask(cpum),
+ __get_str(vstr))
+ );
+
+--
+2.39.5
+
--- /dev/null
+From 38da287b837b0b7d2fffa21e297ee7abdf7eff5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Mar 2025 19:53:11 -0400
+Subject: tracing: Verify event formats that have "%*p.."
+
+From: Steven Rostedt <rostedt@goodmis.org>
+
+[ Upstream commit ea8d7647f9ddf1f81e2027ed305299797299aa03 ]
+
+The trace event verifier checks the formats of trace events to make sure
+that they do not point at memory that is not in the trace event itself or
+in data that will never be freed. If an event references data that was
+allocated when the event triggered and that same data is freed before the
+event is read, then the kernel can crash by reading freed memory.
+
+The verifier runs at boot up (or module load) and scans the print formats
+of the events and checks their arguments to make sure that dereferenced
+pointers are safe. If the format uses "%*p.." the verifier will ignore it,
+and that could be dangerous. Cover this case as well.
+
+Also add to the sample code a use case of "%*pbl".
+
+Link: https://lore.kernel.org/all/bcba4d76-2c3f-4d11-baf0-02905db953dd@oracle.com/
+
+Cc: stable@vger.kernel.org
+Cc: Masami Hiramatsu <mhiramat@kernel.org>
+Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Fixes: 5013f454a352c ("tracing: Add check of trace event print fmts for dereferencing pointers")
+Link: https://lore.kernel.org/20250327195311.2d89ec66@gandalf.local.home
+Reported-by: Libo Chen <libo.chen@oracle.com>
+Reviewed-by: Libo Chen <libo.chen@oracle.com>
+Tested-by: Libo Chen <libo.chen@oracle.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/trace_events.c | 7 +++++++
+ samples/trace_events/trace-events-sample.h | 8 ++++++--
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
+index 1a936978c2b1a..5f74e9f9c8a73 100644
+--- a/kernel/trace/trace_events.c
++++ b/kernel/trace/trace_events.c
+@@ -470,6 +470,7 @@ static void test_event_printk(struct trace_event_call *call)
+ case '%':
+ continue;
+ case 'p':
++ do_pointer:
+ /* Find dereferencing fields */
+ switch (fmt[i + 1]) {
+ case 'B': case 'R': case 'r':
+@@ -498,6 +499,12 @@ static void test_event_printk(struct trace_event_call *call)
+ continue;
+ if (fmt[i + j] == '*') {
+ star = true;
++ /* Handle %*pbl case */
++ if (!j && fmt[i + 1] == 'p') {
++ arg++;
++ i++;
++ goto do_pointer;
++ }
+ continue;
+ }
+ if ((fmt[i + j] == 's')) {
+diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h
+index 24ec968d481fb..06be777b3b14b 100644
+--- a/samples/trace_events/trace-events-sample.h
++++ b/samples/trace_events/trace-events-sample.h
+@@ -317,7 +317,8 @@ TRACE_EVENT(foo_bar,
+ __assign_cpumask(cpum, cpumask_bits(mask));
+ ),
+
+- TP_printk("foo %s %d %s %s %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar,
++ TP_printk("foo %s %d %s %s %s %s %s %s (%s) (%s) %s [%d] %*pbl",
++ __entry->foo, __entry->bar,
+
+ /*
+ * Notice here the use of some helper functions. This includes:
+@@ -368,7 +369,10 @@ TRACE_EVENT(foo_bar,
+
+ __get_str(str), __get_str(lstr),
+ __get_bitmask(cpus), __get_cpumask(cpum),
+- __get_str(vstr))
++ __get_str(vstr),
++ __get_dynamic_array_len(cpus),
++ __get_dynamic_array_len(cpus),
++ __get_dynamic_array(cpus))
+ );
+
+ /*
+--
+2.39.5
+
--- /dev/null
+From 70730dbdbf50453acfc8f859de449e0b91d8ac9a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 4 Feb 2024 16:26:25 +0800
+Subject: x86/extable: Remove unused fixup type EX_TYPE_COPY
+
+From: Tong Tiangen <tongtiangen@huawei.com>
+
+[ Upstream commit cb517619f96718a4c3c2534a3124177633f8998d ]
+
+After
+
+ 034ff37d3407 ("x86: rewrite '__copy_user_nocache' function")
+
+rewrote __copy_user_nocache() to use EX_TYPE_UACCESS instead of the
+EX_TYPE_COPY exception type, there are no more EX_TYPE_COPY users, so
+remove it.
+
+ [ bp: Massage commit message. ]
+
+Signed-off-by: Tong Tiangen <tongtiangen@huawei.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20240204082627.3892816-2-tongtiangen@huawei.com
+Stable-dep-of: 1a15bb8303b6 ("x86/mce: use is_copy_from_user() to determine copy-from-user context")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/asm.h | 3 ---
+ arch/x86/include/asm/extable_fixup_types.h | 2 +-
+ arch/x86/kernel/cpu/mce/severity.c | 1 -
+ arch/x86/mm/extable.c | 9 ---------
+ 4 files changed, 1 insertion(+), 14 deletions(-)
+
+diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
+index ca8eed1d496ab..2bec0c89a95c2 100644
+--- a/arch/x86/include/asm/asm.h
++++ b/arch/x86/include/asm/asm.h
+@@ -229,9 +229,6 @@ register unsigned long current_stack_pointer asm(_ASM_SP);
+ #define _ASM_EXTABLE_UA(from, to) \
+ _ASM_EXTABLE_TYPE(from, to, EX_TYPE_UACCESS)
+
+-#define _ASM_EXTABLE_CPY(from, to) \
+- _ASM_EXTABLE_TYPE(from, to, EX_TYPE_COPY)
+-
+ #define _ASM_EXTABLE_FAULT(from, to) \
+ _ASM_EXTABLE_TYPE(from, to, EX_TYPE_FAULT)
+
+diff --git a/arch/x86/include/asm/extable_fixup_types.h b/arch/x86/include/asm/extable_fixup_types.h
+index 991e31cfde94c..afad9c0b07e0c 100644
+--- a/arch/x86/include/asm/extable_fixup_types.h
++++ b/arch/x86/include/asm/extable_fixup_types.h
+@@ -36,7 +36,7 @@
+ #define EX_TYPE_DEFAULT 1
+ #define EX_TYPE_FAULT 2
+ #define EX_TYPE_UACCESS 3
+-#define EX_TYPE_COPY 4
++/* unused, was: #define EX_TYPE_COPY 4 */
+ #define EX_TYPE_CLEAR_FS 5
+ #define EX_TYPE_FPU_RESTORE 6
+ #define EX_TYPE_BPF 7
+diff --git a/arch/x86/kernel/cpu/mce/severity.c b/arch/x86/kernel/cpu/mce/severity.c
+index c4477162c07d1..bca780fa5e577 100644
+--- a/arch/x86/kernel/cpu/mce/severity.c
++++ b/arch/x86/kernel/cpu/mce/severity.c
+@@ -290,7 +290,6 @@ static noinstr int error_context(struct mce *m, struct pt_regs *regs)
+
+ switch (fixup_type) {
+ case EX_TYPE_UACCESS:
+- case EX_TYPE_COPY:
+ if (!copy_user)
+ return IN_KERNEL;
+ m->kflags |= MCE_IN_KERNEL_COPYIN;
+diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
+index 271dcb2deabc3..2354c0156e51c 100644
+--- a/arch/x86/mm/extable.c
++++ b/arch/x86/mm/extable.c
+@@ -163,13 +163,6 @@ static bool ex_handler_uaccess(const struct exception_table_entry *fixup,
+ return ex_handler_default(fixup, regs);
+ }
+
+-static bool ex_handler_copy(const struct exception_table_entry *fixup,
+- struct pt_regs *regs, int trapnr)
+-{
+- WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?");
+- return ex_handler_fault(fixup, regs, trapnr);
+-}
+-
+ static bool ex_handler_msr(const struct exception_table_entry *fixup,
+ struct pt_regs *regs, bool wrmsr, bool safe, int reg)
+ {
+@@ -267,8 +260,6 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
+ return ex_handler_fault(e, regs, trapnr);
+ case EX_TYPE_UACCESS:
+ return ex_handler_uaccess(e, regs, trapnr, fault_addr);
+- case EX_TYPE_COPY:
+- return ex_handler_copy(e, regs, trapnr);
+ case EX_TYPE_CLEAR_FS:
+ return ex_handler_clear_fs(e, regs);
+ case EX_TYPE_FPU_RESTORE:
+--
+2.39.5
+
--- /dev/null
+From 5cf79acb14c12a4486de5c5281419719a2098849 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 12 Mar 2025 19:28:50 +0800
+Subject: x86/mce: use is_copy_from_user() to determine copy-from-user context
+
+From: Shuai Xue <xueshuai@linux.alibaba.com>
+
+[ Upstream commit 1a15bb8303b6b104e78028b6c68f76a0d4562134 ]
+
+Patch series "mm/hwpoison: Fix regressions in memory failure handling",
+v4.
+
+## 1. What am I trying to do:
+
+This patchset resolves two critical regressions related to memory failure
+handling that have appeared in the upstream kernel since version 5.17, as
+compared to 5.10 LTS.
+
+ - copyin case: poison found in user page while kernel copying from user space
+ - instr case: poison found while instruction fetching in user space
+
+## 2. What is the expected outcome and why
+
+- For copyin case:
+
+Kernel can recover from poison found where kernel is doing get_user() or
+copy_from_user() if those places get an error return and the kernel return
+-EFAULT to the process instead of crashing. More specifily, MCE handler
+checks the fixup handler type to decide whether an in kernel #MC can be
+recovered. When EX_TYPE_UACCESS is found, the PC jumps to recovery code
+specified in _ASM_EXTABLE_FAULT() and return a -EFAULT to user space.
+
+- For instr case:
+
+If a poison found while instruction fetching in user space, full recovery
+is possible. User process takes #PF, Linux allocates a new page and fills
+by reading from storage.
+
+## 3. What actually happens and why
+
+- For copyin case: kernel panic since v5.17
+
+Commit 4c132d1d844a ("x86/futex: Remove .fixup usage") introduced a new
+extable fixup type, EX_TYPE_EFAULT_REG, and later patches updated the
+extable fixup type for copy-from-user operations, changing it from
+EX_TYPE_UACCESS to EX_TYPE_EFAULT_REG. It breaks previous EX_TYPE_UACCESS
+handling when posion found in get_user() or copy_from_user().
+
+- For instr case: user process is killed by a SIGBUS signal due to #CMCI
+ and #MCE race
+
+When an uncorrected memory error is consumed there is a race between the
+CMCI from the memory controller reporting an uncorrected error with a UCNA
+signature, and the core reporting and SRAR signature machine check when
+the data is about to be consumed.
+
+### Background: why *UN*corrected errors tied to *C*MCI in Intel platform [1]
+
+Prior to Icelake memory controllers reported patrol scrub events that
+detected a previously unseen uncorrected error in memory by signaling a
+broadcast machine check with an SRAO (Software Recoverable Action
+Optional) signature in the machine check bank. This was overkill because
+it's not an urgent problem that no core is on the verge of consuming that
+bad data. It's also found that multi SRAO UCE may cause nested MCE
+interrupts and finally become an IERR.
+
+Hence, Intel downgrades the machine check bank signature of patrol scrub
+from SRAO to UCNA (Uncorrected, No Action required), and signal changed to
+#CMCI. Just to add to the confusion, Linux does take an action (in
+uc_decode_notifier()) to try to offline the page despite the UC*NA*
+signature name.
+
+### Background: why #CMCI and #MCE race when poison is consuming in
+ Intel platform [1]
+
+Having decided that CMCI/UCNA is the best action for patrol scrub errors,
+the memory controller uses it for reads too. But the memory controller is
+executing asynchronously from the core, and can't tell the difference
+between a "real" read and a speculative read. So it will do CMCI/UCNA if
+an error is found in any read.
+
+Thus:
+
+1) Core is clever and thinks address A is needed soon, issues a
+ speculative read.
+
+2) Core finds it is going to use address A soon after sending the read
+ request
+
+3) The CMCI from the memory controller is in a race with MCE from the
+ core that will soon try to retire the load from address A.
+
+Quite often (because speculation has got better) the CMCI from the memory
+controller is delivered before the core is committed to the instruction
+reading address A, so the interrupt is taken, and Linux offlines the page
+(marking it as poison).
+
+## Why user process is killed for instr case
+
+Commit 046545a661af ("mm/hwpoison: fix error page recovered but reported
+"not recovered"") tries to fix noise message "Memory error not recovered"
+and skips duplicate SIGBUSs due to the race. But it also introduced a bug
+that kill_accessing_process() return -EHWPOISON for instr case, as result,
+kill_me_maybe() send a SIGBUS to user process.
+
+# 4. The fix, in my opinion, should be:
+
+- For copyin case:
+
+The key point is whether the error context is in a read from user memory.
+We do not care about the ex-type if we know its a MOV reading from
+userspace.
+
+is_copy_from_user() return true when both of the following two checks are
+true:
+
+ - the current instruction is copy
+ - source address is user memory
+
+If copy_user is true, we set
+
+m->kflags |= MCE_IN_KERNEL_COPYIN | MCE_IN_KERNEL_RECOV;
+
+Then do_machine_check() will try fixup_exception() first.
+
+- For instr case: let kill_accessing_process() return 0 to prevent a SIGBUS.
+
+- For patch 3:
+
+The return value of memory_failure() is quite important while discussed
+instr case regression with Tony and Miaohe for patch 2, so add comment
+about the return value.
+
+This patch (of 3):
+
+Commit 4c132d1d844a ("x86/futex: Remove .fixup usage") introduced a new
+extable fixup type, EX_TYPE_EFAULT_REG, and commit 4c132d1d844a
+("x86/futex: Remove .fixup usage") updated the extable fixup type for
+copy-from-user operations, changing it from EX_TYPE_UACCESS to
+EX_TYPE_EFAULT_REG. The error context for copy-from-user operations no
+longer functions as an in-kernel recovery context. Consequently, the
+error context for copy-from-user operations no longer functions as an
+in-kernel recovery context, resulting in kernel panics with the message:
+"Machine check: Data load in unrecoverable area of kernel."
+
+To address this, it is crucial to identify if an error context involves a
+read operation from user memory. The function is_copy_from_user() can be
+utilized to determine:
+
+ - the current operation is copy
+ - when reading user memory
+
+When these conditions are met, is_copy_from_user() will return true,
+confirming that it is indeed a direct copy from user memory. This check
+is essential for correctly handling the context of errors in these
+operations without relying on the extable fixup types that previously
+allowed for in-kernel recovery.
+
+So, use is_copy_from_user() to determine if a context is copy user directly.
+
+Link: https://lkml.kernel.org/r/20250312112852.82415-1-xueshuai@linux.alibaba.com
+Link: https://lkml.kernel.org/r/20250312112852.82415-2-xueshuai@linux.alibaba.com
+Fixes: 4c132d1d844a ("x86/futex: Remove .fixup usage")
+Signed-off-by: Shuai Xue <xueshuai@linux.alibaba.com>
+Suggested-by: Peter Zijlstra <peterz@infradead.org>
+Acked-by: Borislav Petkov (AMD) <bp@alien8.de>
+Tested-by: Tony Luck <tony.luck@intel.com>
+Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
+Cc: Borislav Betkov <bp@alien8.de>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Josh Poimboeuf <jpoimboe@kernel.org>
+Cc: Miaohe Lin <linmiaohe@huawei.com>
+Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
+Cc: Ruidong Tian <tianruidong@linux.alibaba.com>
+Cc: Thomas Gleinxer <tglx@linutronix.de>
+Cc: Yazen Ghannam <yazen.ghannam@amd.com>
+Cc: Jane Chu <jane.chu@oracle.com>
+Cc: Jarkko Sakkinen <jarkko@kernel.org>
+Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kernel/cpu/mce/severity.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/arch/x86/kernel/cpu/mce/severity.c b/arch/x86/kernel/cpu/mce/severity.c
+index bca780fa5e577..9c5754229d6ed 100644
+--- a/arch/x86/kernel/cpu/mce/severity.c
++++ b/arch/x86/kernel/cpu/mce/severity.c
+@@ -288,13 +288,12 @@ static noinstr int error_context(struct mce *m, struct pt_regs *regs)
+ copy_user = is_copy_from_user(regs);
+ instrumentation_end();
+
+- switch (fixup_type) {
+- case EX_TYPE_UACCESS:
+- if (!copy_user)
+- return IN_KERNEL;
+- m->kflags |= MCE_IN_KERNEL_COPYIN;
+- fallthrough;
++ if (copy_user) {
++ m->kflags |= MCE_IN_KERNEL_COPYIN | MCE_IN_KERNEL_RECOV;
++ return IN_KERNEL_RECOV;
++ }
+
++ switch (fixup_type) {
+ case EX_TYPE_FAULT_MCE_SAFE:
+ case EX_TYPE_DEFAULT_MCE_SAFE:
+ m->kflags |= MCE_IN_KERNEL_RECOV;
+--
+2.39.5
+