]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.6
authorSasha Levin <sashal@kernel.org>
Sat, 26 Apr 2025 13:23:09 +0000 (09:23 -0400)
committerSasha Levin <sashal@kernel.org>
Sat, 26 Apr 2025 13:23:09 +0000 (09:23 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
44 files changed:
queue-6.6/arm64-tegra-remove-the-orin-nx-nano-suspend-key.patch [new file with mode: 0644]
queue-6.6/asoc-q6apm-dai-make-use-of-q6apm_get_hw_pointer.patch [new file with mode: 0644]
queue-6.6/asoc-q6apm-dai-schedule-all-available-frames-to-avoi.patch [new file with mode: 0644]
queue-6.6/asoc-qcom-fix-trivial-code-style-issues.patch [new file with mode: 0644]
queue-6.6/asoc-qcom-lpass-make-asoc_qcom_lpass_cpu_platform_re.patch [new file with mode: 0644]
queue-6.6/asoc-qcom-q6apm-dai-drop-unused-q6apm_dai_rtd-fields.patch [new file with mode: 0644]
queue-6.6/auxdisplay-hd44780-convert-to-platform-remove-callba.patch [new file with mode: 0644]
queue-6.6/auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch [new file with mode: 0644]
queue-6.6/clk-renesas-r9a07g04-34-fix-typo-for-sel_shdi-variab.patch [new file with mode: 0644]
queue-6.6/clk-renesas-r9a07g04-34-use-sel_sdhi1_sts-status-con.patch [new file with mode: 0644]
queue-6.6/clk-renesas-r9a07g043-fix-hp-clock-source-for-rz-fiv.patch [new file with mode: 0644]
queue-6.6/clk-renesas-rzg2l-add-struct-clk_hw_data.patch [new file with mode: 0644]
queue-6.6/clk-renesas-rzg2l-refactor-sd-mux-driver.patch [new file with mode: 0644]
queue-6.6/clk-renesas-rzg2l-remove-cpg_sdhi_dsel-from-generic-.patch [new file with mode: 0644]
queue-6.6/clk-renesas-rzg2l-use-u32-for-flag-and-mux_flags.patch [new file with mode: 0644]
queue-6.6/cpufreq-sched-explicitly-synchronize-limits_changed-.patch [new file with mode: 0644]
queue-6.6/iio-adc-ad7768-1-fix-conversion-result-sign.patch [new file with mode: 0644]
queue-6.6/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch [new file with mode: 0644]
queue-6.6/media-subdev-add-v4l2_subdev_is_streaming.patch [new file with mode: 0644]
queue-6.6/media-subdev-fix-use-of-sd-enabled_streams-in-call_s.patch [new file with mode: 0644]
queue-6.6/media-subdev-improve-v4l2_subdev_enable-disable_stre.patch [new file with mode: 0644]
queue-6.6/media-vimc-skip-.s_stream-for-stopped-entities.patch [new file with mode: 0644]
queue-6.6/memcg-drain-obj-stock-on-cpu-hotplug-teardown.patch [new file with mode: 0644]
queue-6.6/mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qc.patch [new file with mode: 0644]
queue-6.6/net-dsa-mv88e6xxx-fix-internal-phys-for-6320-family.patch [new file with mode: 0644]
queue-6.6/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch [new file with mode: 0644]
queue-6.6/of-resolver-fix-device-node-refcount-leakage-in-of_r.patch [new file with mode: 0644]
queue-6.6/of-resolver-simplify-of_resolve_phandles-using-__fre.patch [new file with mode: 0644]
queue-6.6/pci-fix-reference-leak-in-pci_register_host_bridge.patch [new file with mode: 0644]
queue-6.6/s390-pci-report-pci-error-recovery-results-via-sclp.patch [new file with mode: 0644]
queue-6.6/s390-pci-support-mmap-of-pci-resources-except-for-is.patch [new file with mode: 0644]
queue-6.6/s390-sclp-allow-user-space-to-provide-pci-reports-fo.patch [new file with mode: 0644]
queue-6.6/s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-.patch [new file with mode: 0644]
queue-6.6/s390-virtio_ccw-fix-virtual-vs-physical-address-conf.patch [new file with mode: 0644]
queue-6.6/sched-cpufreq-rework-schedutil-governor-performance-.patch [new file with mode: 0644]
queue-6.6/sched-topology-consolidate-and-clean-up-access-to-a-.patch [new file with mode: 0644]
queue-6.6/scsi-ufs-qcom-fix-dev-reference-leaked-through-of_qc.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/soc-qcom-ice-introduce-devm_of_qcom_ice_get.patch [new file with mode: 0644]
queue-6.6/tracing-add-__print_dynamic_array-helper.patch [new file with mode: 0644]
queue-6.6/tracing-add-__string_len-example.patch [new file with mode: 0644]
queue-6.6/tracing-verify-event-formats-that-have-p.patch [new file with mode: 0644]
queue-6.6/x86-extable-remove-unused-fixup-type-ex_type_copy.patch [new file with mode: 0644]
queue-6.6/x86-mce-use-is_copy_from_user-to-determine-copy-from.patch [new file with mode: 0644]

diff --git a/queue-6.6/arm64-tegra-remove-the-orin-nx-nano-suspend-key.patch b/queue-6.6/arm64-tegra-remove-the-orin-nx-nano-suspend-key.patch
new file mode 100644 (file)
index 0000000..57ab3c5
--- /dev/null
@@ -0,0 +1,50 @@
+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
+
diff --git a/queue-6.6/asoc-q6apm-dai-make-use-of-q6apm_get_hw_pointer.patch b/queue-6.6/asoc-q6apm-dai-make-use-of-q6apm_get_hw_pointer.patch
new file mode 100644 (file)
index 0000000..1d0852c
--- /dev/null
@@ -0,0 +1,106 @@
+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
+
diff --git a/queue-6.6/asoc-q6apm-dai-schedule-all-available-frames-to-avoi.patch b/queue-6.6/asoc-q6apm-dai-schedule-all-available-frames-to-avoi.patch
new file mode 100644 (file)
index 0000000..6e01d5d
--- /dev/null
@@ -0,0 +1,101 @@
+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
+
diff --git a/queue-6.6/asoc-qcom-fix-trivial-code-style-issues.patch b/queue-6.6/asoc-qcom-fix-trivial-code-style-issues.patch
new file mode 100644 (file)
index 0000000..b49e1a5
--- /dev/null
@@ -0,0 +1,309 @@
+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
+
diff --git a/queue-6.6/asoc-qcom-lpass-make-asoc_qcom_lpass_cpu_platform_re.patch b/queue-6.6/asoc-qcom-lpass-make-asoc_qcom_lpass_cpu_platform_re.patch
new file mode 100644 (file)
index 0000000..efc1831
--- /dev/null
@@ -0,0 +1,128 @@
+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
+
diff --git a/queue-6.6/asoc-qcom-q6apm-dai-drop-unused-q6apm_dai_rtd-fields.patch b/queue-6.6/asoc-qcom-q6apm-dai-drop-unused-q6apm_dai_rtd-fields.patch
new file mode 100644 (file)
index 0000000..aa79719
--- /dev/null
@@ -0,0 +1,59 @@
+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
+
diff --git a/queue-6.6/auxdisplay-hd44780-convert-to-platform-remove-callba.patch b/queue-6.6/auxdisplay-hd44780-convert-to-platform-remove-callba.patch
new file mode 100644 (file)
index 0000000..aded7ec
--- /dev/null
@@ -0,0 +1,68 @@
+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
+
diff --git a/queue-6.6/auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch b/queue-6.6/auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch
new file mode 100644 (file)
index 0000000..8ff13f1
--- /dev/null
@@ -0,0 +1,48 @@
+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
+
diff --git a/queue-6.6/clk-renesas-r9a07g04-34-fix-typo-for-sel_shdi-variab.patch b/queue-6.6/clk-renesas-r9a07g04-34-fix-typo-for-sel_shdi-variab.patch
new file mode 100644 (file)
index 0000000..7047db7
--- /dev/null
@@ -0,0 +1,75 @@
+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
+
diff --git a/queue-6.6/clk-renesas-r9a07g04-34-use-sel_sdhi1_sts-status-con.patch b/queue-6.6/clk-renesas-r9a07g04-34-use-sel_sdhi1_sts-status-con.patch
new file mode 100644 (file)
index 0000000..5ec5560
--- /dev/null
@@ -0,0 +1,54 @@
+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
+
diff --git a/queue-6.6/clk-renesas-r9a07g043-fix-hp-clock-source-for-rz-fiv.patch b/queue-6.6/clk-renesas-r9a07g043-fix-hp-clock-source-for-rz-fiv.patch
new file mode 100644 (file)
index 0000000..e337394
--- /dev/null
@@ -0,0 +1,59 @@
+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
+
diff --git a/queue-6.6/clk-renesas-rzg2l-add-struct-clk_hw_data.patch b/queue-6.6/clk-renesas-rzg2l-add-struct-clk_hw_data.patch
new file mode 100644 (file)
index 0000000..9080895
--- /dev/null
@@ -0,0 +1,137 @@
+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
+
diff --git a/queue-6.6/clk-renesas-rzg2l-refactor-sd-mux-driver.patch b/queue-6.6/clk-renesas-rzg2l-refactor-sd-mux-driver.patch
new file mode 100644 (file)
index 0000000..c5d7af3
--- /dev/null
@@ -0,0 +1,423 @@
+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
+
diff --git a/queue-6.6/clk-renesas-rzg2l-remove-cpg_sdhi_dsel-from-generic-.patch b/queue-6.6/clk-renesas-rzg2l-remove-cpg_sdhi_dsel-from-generic-.patch
new file mode 100644 (file)
index 0000000..fa6d891
--- /dev/null
@@ -0,0 +1,85 @@
+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
+
diff --git a/queue-6.6/clk-renesas-rzg2l-use-u32-for-flag-and-mux_flags.patch b/queue-6.6/clk-renesas-rzg2l-use-u32-for-flag-and-mux_flags.patch
new file mode 100644 (file)
index 0000000..68c62fd
--- /dev/null
@@ -0,0 +1,39 @@
+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
+
diff --git a/queue-6.6/cpufreq-sched-explicitly-synchronize-limits_changed-.patch b/queue-6.6/cpufreq-sched-explicitly-synchronize-limits_changed-.patch
new file mode 100644 (file)
index 0000000..a915236
--- /dev/null
@@ -0,0 +1,98 @@
+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
+
diff --git a/queue-6.6/iio-adc-ad7768-1-fix-conversion-result-sign.patch b/queue-6.6/iio-adc-ad7768-1-fix-conversion-result-sign.patch
new file mode 100644 (file)
index 0000000..0cccfeb
--- /dev/null
@@ -0,0 +1,55 @@
+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
+
diff --git a/queue-6.6/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch b/queue-6.6/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch
new file mode 100644 (file)
index 0000000..eaf12cc
--- /dev/null
@@ -0,0 +1,47 @@
+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
+
diff --git a/queue-6.6/media-subdev-add-v4l2_subdev_is_streaming.patch b/queue-6.6/media-subdev-add-v4l2_subdev_is_streaming.patch
new file mode 100644 (file)
index 0000000..056a4d1
--- /dev/null
@@ -0,0 +1,86 @@
+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
+
diff --git a/queue-6.6/media-subdev-fix-use-of-sd-enabled_streams-in-call_s.patch b/queue-6.6/media-subdev-fix-use-of-sd-enabled_streams-in-call_s.patch
new file mode 100644 (file)
index 0000000..7414cb8
--- /dev/null
@@ -0,0 +1,88 @@
+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
+
diff --git a/queue-6.6/media-subdev-improve-v4l2_subdev_enable-disable_stre.patch b/queue-6.6/media-subdev-improve-v4l2_subdev_enable-disable_stre.patch
new file mode 100644 (file)
index 0000000..d2778f6
--- /dev/null
@@ -0,0 +1,192 @@
+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
+
diff --git a/queue-6.6/media-vimc-skip-.s_stream-for-stopped-entities.patch b/queue-6.6/media-vimc-skip-.s_stream-for-stopped-entities.patch
new file mode 100644 (file)
index 0000000..1b1b3f5
--- /dev/null
@@ -0,0 +1,77 @@
+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
+
diff --git a/queue-6.6/memcg-drain-obj-stock-on-cpu-hotplug-teardown.patch b/queue-6.6/memcg-drain-obj-stock-on-cpu-hotplug-teardown.patch
new file mode 100644 (file)
index 0000000..6325400
--- /dev/null
@@ -0,0 +1,55 @@
+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
+
diff --git a/queue-6.6/mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qc.patch b/queue-6.6/mmc-sdhci-msm-fix-dev-reference-leaked-through-of_qc.patch
new file mode 100644 (file)
index 0000000..0595184
--- /dev/null
@@ -0,0 +1,42 @@
+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
+
diff --git a/queue-6.6/net-dsa-mv88e6xxx-fix-internal-phys-for-6320-family.patch b/queue-6.6/net-dsa-mv88e6xxx-fix-internal-phys-for-6320-family.patch
new file mode 100644 (file)
index 0000000..4a2de90
--- /dev/null
@@ -0,0 +1,53 @@
+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
+
diff --git a/queue-6.6/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch b/queue-6.6/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch
new file mode 100644 (file)
index 0000000..146db19
--- /dev/null
@@ -0,0 +1,55 @@
+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
+
diff --git a/queue-6.6/of-resolver-fix-device-node-refcount-leakage-in-of_r.patch b/queue-6.6/of-resolver-fix-device-node-refcount-leakage-in-of_r.patch
new file mode 100644 (file)
index 0000000..b00b6d3
--- /dev/null
@@ -0,0 +1,45 @@
+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
+
diff --git a/queue-6.6/of-resolver-simplify-of_resolve_phandles-using-__fre.patch b/queue-6.6/of-resolver-simplify-of_resolve_phandles-using-__fre.patch
new file mode 100644 (file)
index 0000000..f12a102
--- /dev/null
@@ -0,0 +1,114 @@
+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
+
diff --git a/queue-6.6/pci-fix-reference-leak-in-pci_register_host_bridge.patch b/queue-6.6/pci-fix-reference-leak-in-pci_register_host_bridge.patch
new file mode 100644 (file)
index 0000000..1e66120
--- /dev/null
@@ -0,0 +1,67 @@
+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
+
diff --git a/queue-6.6/s390-pci-report-pci-error-recovery-results-via-sclp.patch b/queue-6.6/s390-pci-report-pci-error-recovery-results-via-sclp.patch
new file mode 100644 (file)
index 0000000..495ca18
--- /dev/null
@@ -0,0 +1,380 @@
+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
+
diff --git a/queue-6.6/s390-pci-support-mmap-of-pci-resources-except-for-is.patch b/queue-6.6/s390-pci-support-mmap-of-pci-resources-except-for-is.patch
new file mode 100644 (file)
index 0000000..be707dd
--- /dev/null
@@ -0,0 +1,154 @@
+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
+
diff --git a/queue-6.6/s390-sclp-allow-user-space-to-provide-pci-reports-fo.patch b/queue-6.6/s390-sclp-allow-user-space-to-provide-pci-reports-fo.patch
new file mode 100644 (file)
index 0000000..2028f42
--- /dev/null
@@ -0,0 +1,44 @@
+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
+
diff --git a/queue-6.6/s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-.patch b/queue-6.6/s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-.patch
new file mode 100644 (file)
index 0000000..76902af
--- /dev/null
@@ -0,0 +1,145 @@
+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
+
diff --git a/queue-6.6/s390-virtio_ccw-fix-virtual-vs-physical-address-conf.patch b/queue-6.6/s390-virtio_ccw-fix-virtual-vs-physical-address-conf.patch
new file mode 100644 (file)
index 0000000..eadef7b
--- /dev/null
@@ -0,0 +1,320 @@
+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
+
diff --git a/queue-6.6/sched-cpufreq-rework-schedutil-governor-performance-.patch b/queue-6.6/sched-cpufreq-rework-schedutil-governor-performance-.patch
new file mode 100644 (file)
index 0000000..1f3c286
--- /dev/null
@@ -0,0 +1,375 @@
+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
+
diff --git a/queue-6.6/sched-topology-consolidate-and-clean-up-access-to-a-.patch b/queue-6.6/sched-topology-consolidate-and-clean-up-access-to-a-.patch
new file mode 100644 (file)
index 0000000..293b4ff
--- /dev/null
@@ -0,0 +1,276 @@
+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
+
diff --git a/queue-6.6/scsi-ufs-qcom-fix-dev-reference-leaked-through-of_qc.patch b/queue-6.6/scsi-ufs-qcom-fix-dev-reference-leaked-through-of_qc.patch
new file mode 100644 (file)
index 0000000..50e185a
--- /dev/null
@@ -0,0 +1,42 @@
+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
+
index 673df00e1a3ed9c0832c90f662fbd29e0f1a4030..fc293d40dd8ce69142948ecbc16087bbed8252b5 100644 (file)
@@ -1 +1,44 @@
 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
diff --git a/queue-6.6/soc-qcom-ice-introduce-devm_of_qcom_ice_get.patch b/queue-6.6/soc-qcom-ice-introduce-devm_of_qcom_ice_get.patch
new file mode 100644 (file)
index 0000000..acd5a76
--- /dev/null
@@ -0,0 +1,107 @@
+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
+
diff --git a/queue-6.6/tracing-add-__print_dynamic_array-helper.patch b/queue-6.6/tracing-add-__print_dynamic_array-helper.patch
new file mode 100644 (file)
index 0000000..1e145b8
--- /dev/null
@@ -0,0 +1,94 @@
+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
+
diff --git a/queue-6.6/tracing-add-__string_len-example.patch b/queue-6.6/tracing-add-__string_len-example.patch
new file mode 100644 (file)
index 0000000..f496abe
--- /dev/null
@@ -0,0 +1,63 @@
+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
+
diff --git a/queue-6.6/tracing-verify-event-formats-that-have-p.patch b/queue-6.6/tracing-verify-event-formats-that-have-p.patch
new file mode 100644 (file)
index 0000000..2b90968
--- /dev/null
@@ -0,0 +1,93 @@
+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
+
diff --git a/queue-6.6/x86-extable-remove-unused-fixup-type-ex_type_copy.patch b/queue-6.6/x86-extable-remove-unused-fixup-type-ex_type_copy.patch
new file mode 100644 (file)
index 0000000..6d096e5
--- /dev/null
@@ -0,0 +1,100 @@
+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
+
diff --git a/queue-6.6/x86-mce-use-is_copy_from_user-to-determine-copy-from.patch b/queue-6.6/x86-mce-use-is_copy_from_user-to-determine-copy-from.patch
new file mode 100644 (file)
index 0000000..666eb09
--- /dev/null
@@ -0,0 +1,215 @@
+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
+