]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.1
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>
42 files changed:
queue-6.1/asoc-qcom-fix-sc7280-lpass-potential-buffer-overflow.patch [new file with mode: 0644]
queue-6.1/asoc-qcom-q6dsp-add-support-to-more-display-ports.patch [new file with mode: 0644]
queue-6.1/auxdisplay-hd44780-convert-to-platform-remove-callba.patch [new file with mode: 0644]
queue-6.1/auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch [new file with mode: 0644]
queue-6.1/backlight-led_bl-convert-to-platform-remove-callback.patch [new file with mode: 0644]
queue-6.1/backlight-led_bl-hold-led_access-lock-when-calling-l.patch [new file with mode: 0644]
queue-6.1/clk-renesas-r9a07g04-34-fix-typo-for-sel_shdi-variab.patch [new file with mode: 0644]
queue-6.1/clk-renesas-r9a07g04-34-use-sel_sdhi1_sts-status-con.patch [new file with mode: 0644]
queue-6.1/clk-renesas-r9a07g043-fix-hp-clock-source-for-rz-fiv.patch [new file with mode: 0644]
queue-6.1/clk-renesas-rzg2l-add-struct-clk_hw_data.patch [new file with mode: 0644]
queue-6.1/clk-renesas-rzg2l-refactor-sd-mux-driver.patch [new file with mode: 0644]
queue-6.1/clk-renesas-rzg2l-remove-cpg_sdhi_dsel-from-generic-.patch [new file with mode: 0644]
queue-6.1/clk-renesas-rzg2l-use-u32-for-flag-and-mux_flags.patch [new file with mode: 0644]
queue-6.1/iio-adc-ad7768-1-fix-conversion-result-sign.patch [new file with mode: 0644]
queue-6.1/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch [new file with mode: 0644]
queue-6.1/memcg-drain-obj-stock-on-cpu-hotplug-teardown.patch [new file with mode: 0644]
queue-6.1/net-dsa-add-support-for-mac_prepare-and-mac_finish-c.patch [new file with mode: 0644]
queue-6.1/net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch [new file with mode: 0644]
queue-6.1/net-dsa-mv88e6xxx-don-t-dispose-of-global2-irq-mappi.patch [new file with mode: 0644]
queue-6.1/net-dsa-mv88e6xxx-fix-internal-phys-for-6320-family.patch [new file with mode: 0644]
queue-6.1/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch [new file with mode: 0644]
queue-6.1/net-dsa-mv88e6xxx-move-link-forcing-to-mac_prepare-m.patch [new file with mode: 0644]
queue-6.1/net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch [new file with mode: 0644]
queue-6.1/of-resolver-fix-device-node-refcount-leakage-in-of_r.patch [new file with mode: 0644]
queue-6.1/of-resolver-simplify-of_resolve_phandles-using-__fre.patch [new file with mode: 0644]
queue-6.1/pci-assign-pci-domain-ids-by-ida_alloc.patch [new file with mode: 0644]
queue-6.1/pci-fix-reference-leak-in-pci_register_host_bridge.patch [new file with mode: 0644]
queue-6.1/phy-freescale-imx8m-pcie-add-i.mx8mp-pcie-phy-suppor.patch [new file with mode: 0644]
queue-6.1/phy-freescale-imx8m-pcie-assert-phy-reset-and-perst-.patch [new file with mode: 0644]
queue-6.1/s390-pci-report-pci-error-recovery-results-via-sclp.patch [new file with mode: 0644]
queue-6.1/s390-pci-support-mmap-of-pci-resources-except-for-is.patch [new file with mode: 0644]
queue-6.1/s390-sclp-allow-user-space-to-provide-pci-reports-fo.patch [new file with mode: 0644]
queue-6.1/s390-virtio-sort-out-physical-vs-virtual-pointers-us.patch [new file with mode: 0644]
queue-6.1/s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-.patch [new file with mode: 0644]
queue-6.1/s390-virtio_ccw-fix-virtual-vs-physical-address-conf.patch [new file with mode: 0644]
queue-6.1/selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/tracing-add-__cpumask-to-denote-a-trace-event-field-.patch [new file with mode: 0644]
queue-6.1/tracing-add-__print_dynamic_array-helper.patch [new file with mode: 0644]
queue-6.1/tracing-add-__string_len-example.patch [new file with mode: 0644]
queue-6.1/tracing-fix-cpumask-example-typo.patch [new file with mode: 0644]
queue-6.1/tracing-verify-event-formats-that-have-p.patch [new file with mode: 0644]

diff --git a/queue-6.1/asoc-qcom-fix-sc7280-lpass-potential-buffer-overflow.patch b/queue-6.1/asoc-qcom-fix-sc7280-lpass-potential-buffer-overflow.patch
new file mode 100644 (file)
index 0000000..a08aeb0
--- /dev/null
@@ -0,0 +1,51 @@
+From 29e85b7eb175f45a319297a03568b5002c9df9bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Apr 2025 23:40:58 +0300
+Subject: ASoC: qcom: Fix sc7280 lpass potential buffer overflow
+
+From: Evgeny Pimenov <pimenoveu12@gmail.com>
+
+[ Upstream commit a31a4934b31faea76e735bab17e63d02fcd8e029 ]
+
+Case values introduced in commit
+5f78e1fb7a3e ("ASoC: qcom: Add driver support for audioreach solution")
+cause out of bounds access in arrays of sc7280 driver data (e.g. in case
+of RX_CODEC_DMA_RX_0 in sc7280_snd_hw_params()).
+
+Redefine LPASS_MAX_PORTS to consider the maximum possible port id for
+q6dsp as sc7280 driver utilizes some of those values.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: 77d0ffef793d ("ASoC: qcom: Add macro for lpass DAI id's max limit")
+Cc: stable@vger.kernel.org # v6.0+
+Suggested-by: Mikhail Kobuk <m.kobuk@ispras.ru>
+Suggested-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
+Signed-off-by: Evgeny Pimenov <pimenoveu12@gmail.com>
+Link: https://patch.msgid.link/20250401204058.32261-1-pimenoveu12@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/qcom/lpass.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h
+index dd78600fc7b01..b96116ea81167 100644
+--- a/sound/soc/qcom/lpass.h
++++ b/sound/soc/qcom/lpass.h
+@@ -13,10 +13,11 @@
+ #include <linux/platform_device.h>
+ #include <linux/regmap.h>
+ #include <dt-bindings/sound/qcom,lpass.h>
++#include <dt-bindings/sound/qcom,q6afe.h>
+ #include "lpass-hdmi.h"
+ #define LPASS_AHBIX_CLOCK_FREQUENCY           131072000
+-#define LPASS_MAX_PORTS                       (LPASS_CDC_DMA_VA_TX8 + 1)
++#define LPASS_MAX_PORTS                       (DISPLAY_PORT_RX_7 + 1)
+ #define LPASS_MAX_MI2S_PORTS                  (8)
+ #define LPASS_MAX_DMA_CHANNELS                        (8)
+ #define LPASS_MAX_HDMI_DMA_CHANNELS           (4)
+-- 
+2.39.5
+
diff --git a/queue-6.1/asoc-qcom-q6dsp-add-support-to-more-display-ports.patch b/queue-6.1/asoc-qcom-q6dsp-add-support-to-more-display-ports.patch
new file mode 100644 (file)
index 0000000..83200e0
--- /dev/null
@@ -0,0 +1,114 @@
+From 6f112bf8b64f338a1a8f375d1514a1c504666d4f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 May 2023 12:22:01 +0100
+Subject: ASoC: qcom: q6dsp: add support to more display ports
+
+From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+[ Upstream commit 90848a2557fec0a6f1a35e58031a1f6f5e44e7d6 ]
+
+Existing code base only supports one display port, this patch adds
+support upto 8 display ports. This support is required to allow platforms
+like X13s which have 3 display ports, and some of the Qualcomm SoCs
+there are upto 7 Display ports.
+
+Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org
+Link: https://lore.kernel.org/r/20230509112202.21471-4-srinivas.kandagatla@linaro.org
+Signed-off-by: Mark Brown <broonie@kernel.org
+Stable-dep-of: a31a4934b31f ("ASoC: qcom: Fix sc7280 lpass potential buffer overflow")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../sound/qcom,q6dsp-lpass-ports.h            |  8 ++++
+ sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c      | 43 ++++++++++++-------
+ 2 files changed, 35 insertions(+), 16 deletions(-)
+
+diff --git a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
+index 9f7c5103bc82b..39f203256c4f6 100644
+--- a/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
++++ b/include/dt-bindings/sound/qcom,q6dsp-lpass-ports.h
+@@ -131,6 +131,14 @@
+ #define RX_CODEC_DMA_RX_7     126
+ #define QUINARY_MI2S_RX               127
+ #define QUINARY_MI2S_TX               128
++#define DISPLAY_PORT_RX_0     DISPLAY_PORT_RX
++#define DISPLAY_PORT_RX_1     129
++#define DISPLAY_PORT_RX_2     130
++#define DISPLAY_PORT_RX_3     131
++#define DISPLAY_PORT_RX_4     132
++#define DISPLAY_PORT_RX_5     133
++#define DISPLAY_PORT_RX_6     134
++#define DISPLAY_PORT_RX_7     135
+ #define LPASS_CLK_ID_PRI_MI2S_IBIT    1
+ #define LPASS_CLK_ID_PRI_MI2S_EBIT    2
+diff --git a/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c b/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c
+index f67c16fd90b9b..ac937a6bf909b 100644
+--- a/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c
++++ b/sound/soc/qcom/qdsp6/q6dsp-lpass-ports.c
+@@ -79,6 +79,22 @@
+               .id = did,                                              \
+       }
++#define Q6AFE_DP_RX_DAI(did) {                                                \
++              .playback = {                                           \
++                      .stream_name = #did" Playback",                 \
++                      .rates = SNDRV_PCM_RATE_48000 |                 \
++                              SNDRV_PCM_RATE_96000 |                  \
++                              SNDRV_PCM_RATE_192000,                  \
++                      .formats = SNDRV_PCM_FMTBIT_S16_LE |            \
++                                 SNDRV_PCM_FMTBIT_S24_LE,             \
++                      .channels_min = 2,                              \
++                      .channels_max = 8,                              \
++                      .rate_min = 48000,                              \
++                      .rate_max = 192000,                             \
++              },                                                      \
++              .name = #did,                                           \
++              .id = did,                                              \
++      }
+ static struct snd_soc_dai_driver q6dsp_audio_fe_dais[] = {
+       {
+@@ -528,22 +544,14 @@ static struct snd_soc_dai_driver q6dsp_audio_fe_dais[] = {
+       Q6AFE_TDM_CAP_DAI("Quinary", 5, QUINARY_TDM_TX_5),
+       Q6AFE_TDM_CAP_DAI("Quinary", 6, QUINARY_TDM_TX_6),
+       Q6AFE_TDM_CAP_DAI("Quinary", 7, QUINARY_TDM_TX_7),
+-      {
+-              .playback = {
+-                      .stream_name = "Display Port Playback",
+-                      .rates = SNDRV_PCM_RATE_48000 |
+-                               SNDRV_PCM_RATE_96000 |
+-                               SNDRV_PCM_RATE_192000,
+-                      .formats = SNDRV_PCM_FMTBIT_S16_LE |
+-                                 SNDRV_PCM_FMTBIT_S24_LE,
+-                      .channels_min = 2,
+-                      .channels_max = 8,
+-                      .rate_max =     192000,
+-                      .rate_min =     48000,
+-              },
+-              .id = DISPLAY_PORT_RX,
+-              .name = "DISPLAY_PORT",
+-      },
++      Q6AFE_DP_RX_DAI(DISPLAY_PORT_RX_0),
++      Q6AFE_DP_RX_DAI(DISPLAY_PORT_RX_1),
++      Q6AFE_DP_RX_DAI(DISPLAY_PORT_RX_2),
++      Q6AFE_DP_RX_DAI(DISPLAY_PORT_RX_3),
++      Q6AFE_DP_RX_DAI(DISPLAY_PORT_RX_4),
++      Q6AFE_DP_RX_DAI(DISPLAY_PORT_RX_5),
++      Q6AFE_DP_RX_DAI(DISPLAY_PORT_RX_6),
++      Q6AFE_DP_RX_DAI(DISPLAY_PORT_RX_7),
+       Q6AFE_CDC_DMA_RX_DAI(WSA_CODEC_DMA_RX_0),
+       Q6AFE_CDC_DMA_TX_DAI(WSA_CODEC_DMA_TX_0),
+       Q6AFE_CDC_DMA_RX_DAI(WSA_CODEC_DMA_RX_1),
+@@ -603,6 +611,9 @@ struct snd_soc_dai_driver *q6dsp_audio_ports_set_config(struct device *dev,
+               case DISPLAY_PORT_RX:
+                       q6dsp_audio_fe_dais[i].ops = cfg->q6hdmi_ops;
+                       break;
++              case DISPLAY_PORT_RX_1 ... DISPLAY_PORT_RX_7:
++                      q6dsp_audio_fe_dais[i].ops = cfg->q6hdmi_ops;
++                      break;
+               case SLIMBUS_0_RX ... SLIMBUS_6_TX:
+                       q6dsp_audio_fe_dais[i].ops = cfg->q6slim_ops;
+                       break;
+-- 
+2.39.5
+
diff --git a/queue-6.1/auxdisplay-hd44780-convert-to-platform-remove-callba.patch b/queue-6.1/auxdisplay-hd44780-convert-to-platform-remove-callba.patch
new file mode 100644 (file)
index 0000000..9fb9676
--- /dev/null
@@ -0,0 +1,68 @@
+From 1807818a218d6b1203655f641fb4aa0487b729fa 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.1/auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch b/queue-6.1/auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch
new file mode 100644 (file)
index 0000000..954690b
--- /dev/null
@@ -0,0 +1,48 @@
+From c33001b04a2331008447bcb50240f9b2da5d5923 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.1/backlight-led_bl-convert-to-platform-remove-callback.patch b/queue-6.1/backlight-led_bl-convert-to-platform-remove-callback.patch
new file mode 100644 (file)
index 0000000..3f7d8f2
--- /dev/null
@@ -0,0 +1,67 @@
+From 1bad9321b05568d81ebe356b79efa549dc6744ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Mar 2023 08:39:38 +0100
+Subject: backlight: led_bl: 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 c4c4fa57fd3cc00020152baa169337521f90b2ad ]
+
+The .remove() callback for a platform driver returns an int which makes
+many driver authors wrongly assume it's possible to do error handling by
+returning an error code. However the value returned is (mostly) ignored
+and this typically results in resource leaks. To improve here there is a
+quest to make the remove callback return void. In the first step of this
+quest all drivers are converted to .remove_new() which already returns
+void.
+
+Trivially convert this driver from always returning zero in the remove
+callback to the void returning variant.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org>
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://lore.kernel.org/r/20230308073945.2336302-7-u.kleine-koenig@pengutronix.de
+Stable-dep-of: 276822a00db3 ("backlight: led_bl: Hold led_access lock when calling led_sysfs_disable()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/backlight/led_bl.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c
+index f54d256e2d548..a1b6a2ad73a07 100644
+--- a/drivers/video/backlight/led_bl.c
++++ b/drivers/video/backlight/led_bl.c
+@@ -217,7 +217,7 @@ static int led_bl_probe(struct platform_device *pdev)
+       return 0;
+ }
+-static int led_bl_remove(struct platform_device *pdev)
++static void led_bl_remove(struct platform_device *pdev)
+ {
+       struct led_bl_data *priv = platform_get_drvdata(pdev);
+       struct backlight_device *bl = priv->bl_dev;
+@@ -228,8 +228,6 @@ static int led_bl_remove(struct platform_device *pdev)
+       led_bl_power_off(priv);
+       for (i = 0; i < priv->nb_leds; i++)
+               led_sysfs_enable(priv->leds[i]);
+-
+-      return 0;
+ }
+ static const struct of_device_id led_bl_of_match[] = {
+@@ -245,7 +243,7 @@ static struct platform_driver led_bl_driver = {
+               .of_match_table = of_match_ptr(led_bl_of_match),
+       },
+       .probe          = led_bl_probe,
+-      .remove         = led_bl_remove,
++      .remove_new     = led_bl_remove,
+ };
+ module_platform_driver(led_bl_driver);
+-- 
+2.39.5
+
diff --git a/queue-6.1/backlight-led_bl-hold-led_access-lock-when-calling-l.patch b/queue-6.1/backlight-led_bl-hold-led_access-lock-when-calling-l.patch
new file mode 100644 (file)
index 0000000..f08200b
--- /dev/null
@@ -0,0 +1,56 @@
+From 2a8057bf149e83474c50d86605dcb15cc4bda858 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 22 Jan 2025 10:19:14 +0100
+Subject: backlight: led_bl: Hold led_access lock when calling
+ led_sysfs_disable()
+
+From: Herve Codina <herve.codina@bootlin.com>
+
+[ Upstream commit 276822a00db3c1061382b41e72cafc09d6a0ec30 ]
+
+Lockdep detects the following issue on led-backlight removal:
+  [  142.315935] ------------[ cut here ]------------
+  [  142.315954] WARNING: CPU: 2 PID: 292 at drivers/leds/led-core.c:455 led_sysfs_enable+0x54/0x80
+  ...
+  [  142.500725] Call trace:
+  [  142.503176]  led_sysfs_enable+0x54/0x80 (P)
+  [  142.507370]  led_bl_remove+0x80/0xa8 [led_bl]
+  [  142.511742]  platform_remove+0x30/0x58
+  [  142.515501]  device_remove+0x54/0x90
+  ...
+
+Indeed, led_sysfs_enable() has to be called with the led_access
+lock held.
+
+Hold the lock when calling led_sysfs_disable().
+
+Fixes: ae232e45acf9 ("backlight: add led-backlight driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Herve Codina <herve.codina@bootlin.com>
+Link: https://lore.kernel.org/r/20250122091914.309533-1-herve.codina@bootlin.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/video/backlight/led_bl.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c
+index a1b6a2ad73a07..589dae9ebb638 100644
+--- a/drivers/video/backlight/led_bl.c
++++ b/drivers/video/backlight/led_bl.c
+@@ -226,8 +226,11 @@ static void led_bl_remove(struct platform_device *pdev)
+       backlight_device_unregister(bl);
+       led_bl_power_off(priv);
+-      for (i = 0; i < priv->nb_leds; i++)
++      for (i = 0; i < priv->nb_leds; i++) {
++              mutex_lock(&priv->leds[i]->led_access);
+               led_sysfs_enable(priv->leds[i]);
++              mutex_unlock(&priv->leds[i]->led_access);
++      }
+ }
+ static const struct of_device_id led_bl_of_match[] = {
+-- 
+2.39.5
+
diff --git a/queue-6.1/clk-renesas-r9a07g04-34-fix-typo-for-sel_shdi-variab.patch b/queue-6.1/clk-renesas-r9a07g04-34-fix-typo-for-sel_shdi-variab.patch
new file mode 100644 (file)
index 0000000..570dc39
--- /dev/null
@@ -0,0 +1,75 @@
+From 9e76563149ad5e728bd6274175e3007b340b8704 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 284bab8366ef5..1526de808576e 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 b61a17fd4cc33..77e1a3a4ef1e6 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.1/clk-renesas-r9a07g04-34-use-sel_sdhi1_sts-status-con.patch b/queue-6.1/clk-renesas-r9a07g04-34-use-sel_sdhi1_sts-status-con.patch
new file mode 100644 (file)
index 0000000..7953ddb
--- /dev/null
@@ -0,0 +1,54 @@
+From 5420ac6e9e50c237e129e10b62a5afefb9a4fec8 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 31b7c24fe4d0f..284bab8366ef5 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 3ae1c792b104c..b61a17fd4cc33 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.1/clk-renesas-r9a07g043-fix-hp-clock-source-for-rz-fiv.patch b/queue-6.1/clk-renesas-r9a07g043-fix-hp-clock-source-for-rz-fiv.patch
new file mode 100644 (file)
index 0000000..4b40d10
--- /dev/null
@@ -0,0 +1,59 @@
+From 9e621c7a3e234e35020640301215111680656e52 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 1526de808576e..ac60251d72845 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.1/clk-renesas-rzg2l-add-struct-clk_hw_data.patch b/queue-6.1/clk-renesas-rzg2l-add-struct-clk_hw_data.patch
new file mode 100644 (file)
index 0000000..2427fb3
--- /dev/null
@@ -0,0 +1,137 @@
+From 3943decb0e79f7c4e543803858ceee77266aefd3 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 5617040f307c4..2d298d94e1d85 100644
+--- a/drivers/clk/renesas/rzg2l-cpg.c
++++ b/drivers/clk/renesas/rzg2l-cpg.c
+@@ -59,13 +59,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;
+@@ -187,10 +203,10 @@ static int rzg2l_cpg_sd_clk_mux_determine_rate(struct clk_hw *hw,
+ 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;
+@@ -207,7 +223,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) {
+@@ -236,12 +252,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;
+ }
+@@ -257,17 +273,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;
+@@ -275,7 +291,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.1/clk-renesas-rzg2l-refactor-sd-mux-driver.patch b/queue-6.1/clk-renesas-rzg2l-refactor-sd-mux-driver.patch
new file mode 100644 (file)
index 0000000..0553444
--- /dev/null
@@ -0,0 +1,423 @@
+From 4870db097e423d2bd24216c0c0cb51e3b05fde22 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 866d355911818..31b7c24fe4d0f 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 ca56bc67da25e..3ae1c792b104c 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 2d298d94e1d85..af4f40c108d8c 100644
+--- a/drivers/clk/renesas/rzg2l-cpg.c
++++ b/drivers/clk/renesas/rzg2l-cpg.c
+@@ -57,31 +57,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;
+@@ -135,6 +141,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,
+@@ -204,48 +280,27 @@ static int rzg2l_cpg_sd_clk_mux_determine_rate(struct clk_hw *hw,
+ 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;
+ }
+@@ -253,13 +308,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 = {
+@@ -273,31 +330,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 a3f908e555552..6418961dc8822 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) \
+@@ -265,4 +269,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.1/clk-renesas-rzg2l-remove-cpg_sdhi_dsel-from-generic-.patch b/queue-6.1/clk-renesas-rzg2l-remove-cpg_sdhi_dsel-from-generic-.patch
new file mode 100644 (file)
index 0000000..08343f4
--- /dev/null
@@ -0,0 +1,85 @@
+From 0e8bf632139ca2a80122e02a499d1913d9331f8c 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 0b56688ecbfc4..866d355911818 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 02a4fc41bb6e1..ca56bc67da25e 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 f362a1d886338..a3f908e555552 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.1/clk-renesas-rzg2l-use-u32-for-flag-and-mux_flags.patch b/queue-6.1/clk-renesas-rzg2l-use-u32-for-flag-and-mux_flags.patch
new file mode 100644 (file)
index 0000000..812f300
--- /dev/null
@@ -0,0 +1,39 @@
+From 91180e6edf6c39ad7a0fd23d075db5be888bc17e 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 aefa53a900597..f362a1d886338 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.1/iio-adc-ad7768-1-fix-conversion-result-sign.patch b/queue-6.1/iio-adc-ad7768-1-fix-conversion-result-sign.patch
new file mode 100644 (file)
index 0000000..c958819
--- /dev/null
@@ -0,0 +1,55 @@
+From 813242925bc4c99ddf708587e1ef1be2ed17a6f5 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.1/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch b/queue-6.1/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch
new file mode 100644 (file)
index 0000000..2bba62f
--- /dev/null
@@ -0,0 +1,47 @@
+From 18dc577a413429deff37736154becbbe38a3102b 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.1/memcg-drain-obj-stock-on-cpu-hotplug-teardown.patch b/queue-6.1/memcg-drain-obj-stock-on-cpu-hotplug-teardown.patch
new file mode 100644 (file)
index 0000000..97ad124
--- /dev/null
@@ -0,0 +1,55 @@
+From 4bf25ac76b51c1ea05eb2dca2dcb3961bf01e1f4 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 3f7cab196eb62..8c586133abb7c 100644
+--- a/mm/memcontrol.c
++++ b/mm/memcontrol.c
+@@ -2368,9 +2368,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.1/net-dsa-add-support-for-mac_prepare-and-mac_finish-c.patch b/queue-6.1/net-dsa-add-support-for-mac_prepare-and-mac_finish-c.patch
new file mode 100644 (file)
index 0000000..6986c79
--- /dev/null
@@ -0,0 +1,111 @@
+From d630505f406c50c183756857eeee85b399f99e24 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 May 2023 11:38:44 +0100
+Subject: net: dsa: add support for mac_prepare() and mac_finish() calls
+
+From: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+
+[ Upstream commit dd805cf3e80e038aeb06902399ce9bd6fafb4ff3 ]
+
+Add DSA support for the phylink mac_prepare() and mac_finish() calls.
+These were introduced as part of the PCS support to allow MACs to
+perform preparatory steps prior to configuration, and finalisation
+steps after the MAC and PCS has been configured.
+
+Introducing phylink_pcs support to the mv88e6xxx DSA driver needs some
+code moved out of its mac_config() stage into the mac_prepare() and
+mac_finish() stages, and this commit facilitates such code in DSA
+drivers.
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 52fdc41c3278 ("net: dsa: mv88e6xxx: fix internal PHYs for 6320 family")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/dsa.h |  6 ++++++
+ net/dsa/port.c    | 32 ++++++++++++++++++++++++++++++++
+ 2 files changed, 38 insertions(+)
+
+diff --git a/include/net/dsa.h b/include/net/dsa.h
+index f96b61d9768e0..e26bace774799 100644
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -888,9 +888,15 @@ struct dsa_switch_ops {
+                                                     phy_interface_t iface);
+       int     (*phylink_mac_link_state)(struct dsa_switch *ds, int port,
+                                         struct phylink_link_state *state);
++      int     (*phylink_mac_prepare)(struct dsa_switch *ds, int port,
++                                     unsigned int mode,
++                                     phy_interface_t interface);
+       void    (*phylink_mac_config)(struct dsa_switch *ds, int port,
+                                     unsigned int mode,
+                                     const struct phylink_link_state *state);
++      int     (*phylink_mac_finish)(struct dsa_switch *ds, int port,
++                                    unsigned int mode,
++                                    phy_interface_t interface);
+       void    (*phylink_mac_an_restart)(struct dsa_switch *ds, int port);
+       void    (*phylink_mac_link_down)(struct dsa_switch *ds, int port,
+                                        unsigned int mode,
+diff --git a/net/dsa/port.c b/net/dsa/port.c
+index 750fe68d9b2a0..cd1741792f6a9 100644
+--- a/net/dsa/port.c
++++ b/net/dsa/port.c
+@@ -1599,6 +1599,21 @@ dsa_port_phylink_mac_select_pcs(struct phylink_config *config,
+       return pcs;
+ }
++static int dsa_port_phylink_mac_prepare(struct phylink_config *config,
++                                      unsigned int mode,
++                                      phy_interface_t interface)
++{
++      struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
++      struct dsa_switch *ds = dp->ds;
++      int err = 0;
++
++      if (ds->ops->phylink_mac_prepare)
++              err = ds->ops->phylink_mac_prepare(ds, dp->index, mode,
++                                                 interface);
++
++      return err;
++}
++
+ static void dsa_port_phylink_mac_config(struct phylink_config *config,
+                                       unsigned int mode,
+                                       const struct phylink_link_state *state)
+@@ -1612,6 +1627,21 @@ static void dsa_port_phylink_mac_config(struct phylink_config *config,
+       ds->ops->phylink_mac_config(ds, dp->index, mode, state);
+ }
++static int dsa_port_phylink_mac_finish(struct phylink_config *config,
++                                     unsigned int mode,
++                                     phy_interface_t interface)
++{
++      struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
++      struct dsa_switch *ds = dp->ds;
++      int err = 0;
++
++      if (ds->ops->phylink_mac_finish)
++              err = ds->ops->phylink_mac_finish(ds, dp->index, mode,
++                                                interface);
++
++      return err;
++}
++
+ static void dsa_port_phylink_mac_an_restart(struct phylink_config *config)
+ {
+       struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
+@@ -1667,7 +1697,9 @@ static const struct phylink_mac_ops dsa_port_phylink_mac_ops = {
+       .validate = dsa_port_phylink_validate,
+       .mac_select_pcs = dsa_port_phylink_mac_select_pcs,
+       .mac_pcs_get_state = dsa_port_phylink_mac_pcs_get_state,
++      .mac_prepare = dsa_port_phylink_mac_prepare,
+       .mac_config = dsa_port_phylink_mac_config,
++      .mac_finish = dsa_port_phylink_mac_finish,
+       .mac_an_restart = dsa_port_phylink_mac_an_restart,
+       .mac_link_down = dsa_port_phylink_mac_link_down,
+       .mac_link_up = dsa_port_phylink_mac_link_up,
+-- 
+2.39.5
+
diff --git a/queue-6.1/net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch b/queue-6.1/net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch
new file mode 100644 (file)
index 0000000..2e2c5a3
--- /dev/null
@@ -0,0 +1,84 @@
+From c45b4824b3d0a84ed0cba9a94f616d7222461cf3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 May 2023 10:02:43 +0200
+Subject: net: dsa: mv88e6xxx: add field to specify internal phys layout
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alexis Lothoré <alexis.lothore@bootlin.com>
+
+[ Upstream commit 3ba89b28adb21a5d5d78e905e2c3972816606bb4 ]
+
+mv88e6xxx currently assumes that switch equipped with internal phys have
+those phys mapped contiguously starting from port 0 (see
+mv88e6xxx_phy_is_internal). However, some switches have internal PHYs but
+NOT starting from port 0. For example 88e6393X, 88E6193X and 88E6191X have
+integrated PHYs available on ports 1 to 8
+To properly support this offset, add a new field to allow specifying an
+internal PHYs layout. If field is not set, default layout is assumed (start
+at port 0)
+
+Signed-off-by: Alexis Lothoré <alexis.lothore@bootlin.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 52fdc41c3278 ("net: dsa: mv88e6xxx: fix internal PHYs for 6320 family")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/mv88e6xxx/chip.c    | 4 +++-
+ drivers/net/dsa/mv88e6xxx/chip.h    | 5 +++++
+ drivers/net/dsa/mv88e6xxx/global2.c | 5 ++++-
+ 3 files changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
+index cabf97a902b52..c1a322d6432c0 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -472,7 +472,9 @@ static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
+ static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port)
+ {
+-      return port < chip->info->num_internal_phys;
++      return port >= chip->info->internal_phys_offset &&
++              port < chip->info->num_internal_phys +
++                      chip->info->internal_phys_offset;
+ }
+ static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port)
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
+index b34e96e689d5c..4a8b56ed1bd6c 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.h
++++ b/drivers/net/dsa/mv88e6xxx/chip.h
+@@ -167,6 +167,11 @@ struct mv88e6xxx_info {
+       /* Supports PTP */
+       bool ptp_support;
++
++      /* Internal PHY start index. 0 means that internal PHYs range starts at
++       * port 0, 1 means internal PHYs range starts at port 1, etc
++       */
++      unsigned int internal_phys_offset;
+ };
+ struct mv88e6xxx_atu_entry {
+diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
+index 79954e580c335..8480d08e6f944 100644
+--- a/drivers/net/dsa/mv88e6xxx/global2.c
++++ b/drivers/net/dsa/mv88e6xxx/global2.c
+@@ -1184,9 +1184,12 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
+ int mv88e6xxx_g2_irq_mdio_setup(struct mv88e6xxx_chip *chip,
+                               struct mii_bus *bus)
+ {
++      int phy_start = chip->info->internal_phys_offset;
++      int phy_end = chip->info->internal_phys_offset +
++                    chip->info->num_internal_phys;
+       int phy, irq;
+-      for (phy = 0; phy < chip->info->num_internal_phys; phy++) {
++      for (phy = phy_start; phy < phy_end; phy++) {
+               irq = irq_find_mapping(chip->g2_irq.domain, phy);
+               if (irq < 0)
+                       return irq;
+-- 
+2.39.5
+
diff --git a/queue-6.1/net-dsa-mv88e6xxx-don-t-dispose-of-global2-irq-mappi.patch b/queue-6.1/net-dsa-mv88e6xxx-don-t-dispose-of-global2-irq-mappi.patch
new file mode 100644 (file)
index 0000000..f0380a2
--- /dev/null
@@ -0,0 +1,136 @@
+From 0fd88096931e6ed7604937a2a41ca29ed663ccf8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Mar 2023 17:38:43 +0100
+Subject: net: dsa: mv88e6xxx: don't dispose of Global2 IRQ mappings from
+ mdiobus code
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit b1a2de9ccfe63b50e493ebb57b85beb5785200c7 ]
+
+irq_find_mapping() does not need irq_dispose_mapping(), only
+irq_create_mapping() does.
+
+Calling irq_dispose_mapping() from mv88e6xxx_g2_irq_mdio_free() and from
+the error path of mv88e6xxx_g2_irq_mdio_setup() effectively means that
+the mdiobus logic (for internal PHY interrupts) is disposing of a
+hwirq->virq mapping which it is not responsible of (but instead, the
+function pair mv88e6xxx_g2_irq_setup() + mv88e6xxx_g2_irq_free() is).
+
+With the current code structure, this isn't such a huge problem, because
+mv88e6xxx_g2_irq_mdio_free() is called relatively close to the real
+owner of the IRQ mappings:
+
+mv88e6xxx_remove()
+-> mv88e6xxx_unregister_switch()
+-> mv88e6xxx_mdios_unregister()
+   -> mv88e6xxx_g2_irq_mdio_free()
+-> mv88e6xxx_g2_irq_free()
+
+and the switch isn't 'live' in any way such that it would be able of
+generating interrupts at this point (mv88e6xxx_unregister_switch() has
+been called).
+
+However, there is a desire to split mv88e6xxx_mdios_unregister() and
+mv88e6xxx_g2_irq_free() such that mv88e6xxx_mdios_unregister() only gets
+called from mv88e6xxx_teardown(). This is much more problematic, as can
+be seen below.
+
+In a cross-chip scenario (say 3 switches d0032004.mdio-mii:10,
+d0032004.mdio-mii:11 and d0032004.mdio-mii:12 which form a single DSA
+tree), it is possible to unbind the device driver from a single switch
+(say d0032004.mdio-mii:10).
+
+When that happens, mv88e6xxx_remove() will be called for just that one
+switch, and this will call mv88e6xxx_unregister_switch() which will tear
+down the entire tree (calling mv88e6xxx_teardown() for all 3 switches).
+
+Assuming mv88e6xxx_mdios_unregister() was moved to mv88e6xxx_teardown(),
+at this stage, all 3 switches will have called irq_dispose_mapping() on
+their mdiobus virqs.
+
+When we bind again the device driver to d0032004.mdio-mii:10,
+mv88e6xxx_probe() is called for it, which calls dsa_register_switch().
+The DSA tree is now complete again, and mv88e6xxx_setup() is called for
+all 3 switches.
+
+Also assuming that mv88e6xxx_mdios_register() is moved to
+mv88e6xxx_setup() (the 2 assumptions go together), at this point,
+d0032004.mdio-mii:11 and d0032004.mdio-mii:12 don't have an IRQ mapping
+for the internal PHYs anymore, as they've disposed of it in
+mv88e6xxx_teardown(). Whereas switch d0032004.mdio-mii:10 has re-created
+it, because its code path comes from mv88e6xxx_probe().
+
+Simply put, this change prepares the driver to handle the movement of
+mv88e6xxx_mdios_register() to mv88e6xxx_setup() for cross-chip DSA trees.
+
+Also, the code being deleted was partially wrong anyway (in a way which
+may have hidden this other issue). mv88e6xxx_g2_irq_mdio_setup()
+populates bus->irq[] starting with offset chip->info->phy_base_addr, but
+the teardown path doesn't apply that offset too. So it disposes of virq
+0 for phy = [ 0, phy_base_addr ).
+
+All switch families have phy_base_addr = 0, except for MV88E6141 and
+MV88E6341 which have it as 0x10. I guess those families would have
+happened to work by mistake in cross-chip scenarios too.
+
+I'm deleting the body of mv88e6xxx_g2_irq_mdio_free() but leaving its
+call sites and prototype in place. This is because, if we ever need to
+add back some teardown procedure in the future, it will be perhaps
+error-prone to deduce the proper call sites again. Whereas like this,
+no extra code should get generated, it shouldn't bother anybody.
+
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Signed-off-by: Klaus Kudielka <klaus.kudielka@gmail.com>
+Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 52fdc41c3278 ("net: dsa: mv88e6xxx: fix internal PHYs for 6320 family")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/mv88e6xxx/global2.c | 20 ++++----------------
+ 1 file changed, 4 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c
+index ac302a935ce69..79954e580c335 100644
+--- a/drivers/net/dsa/mv88e6xxx/global2.c
++++ b/drivers/net/dsa/mv88e6xxx/global2.c
+@@ -1184,31 +1184,19 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip)
+ int mv88e6xxx_g2_irq_mdio_setup(struct mv88e6xxx_chip *chip,
+                               struct mii_bus *bus)
+ {
+-      int phy, irq, err, err_phy;
++      int phy, irq;
+       for (phy = 0; phy < chip->info->num_internal_phys; phy++) {
+               irq = irq_find_mapping(chip->g2_irq.domain, phy);
+-              if (irq < 0) {
+-                      err = irq;
+-                      goto out;
+-              }
++              if (irq < 0)
++                      return irq;
++
+               bus->irq[chip->info->phy_base_addr + phy] = irq;
+       }
+       return 0;
+-out:
+-      err_phy = phy;
+-
+-      for (phy = 0; phy < err_phy; phy++)
+-              irq_dispose_mapping(bus->irq[phy]);
+-
+-      return err;
+ }
+ void mv88e6xxx_g2_irq_mdio_free(struct mv88e6xxx_chip *chip,
+                               struct mii_bus *bus)
+ {
+-      int phy;
+-
+-      for (phy = 0; phy < chip->info->num_internal_phys; phy++)
+-              irq_dispose_mapping(bus->irq[phy]);
+ }
+-- 
+2.39.5
+
diff --git a/queue-6.1/net-dsa-mv88e6xxx-fix-internal-phys-for-6320-family.patch b/queue-6.1/net-dsa-mv88e6xxx-fix-internal-phys-for-6320-family.patch
new file mode 100644 (file)
index 0000000..d6dce14
--- /dev/null
@@ -0,0 +1,53 @@
+From f87a6a15e67173cabf809b9acef2362d69c84887 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 c1a322d6432c0..52dd00f2a83ca 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -6212,7 +6212,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,
+@@ -6237,7 +6238,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.1/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch b/queue-6.1/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch
new file mode 100644 (file)
index 0000000..f9690be
--- /dev/null
@@ -0,0 +1,55 @@
+From a3a84b4abbd6485965b4970c5f50fb5266b5602e 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 52dd00f2a83ca..0541c9a7fc49a 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -5197,8 +5197,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,
+@@ -5244,8 +5244,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.1/net-dsa-mv88e6xxx-move-link-forcing-to-mac_prepare-m.patch b/queue-6.1/net-dsa-mv88e6xxx-move-link-forcing-to-mac_prepare-m.patch
new file mode 100644 (file)
index 0000000..64f9841
--- /dev/null
@@ -0,0 +1,140 @@
+From 490cacb47b8f833bd0d61b21f10e89b8936c3996 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 May 2023 11:38:50 +0100
+Subject: net: dsa: mv88e6xxx: move link forcing to mac_prepare/mac_finish
+
+From: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+
+[ Upstream commit 267d7692f6cd5c9b8796324cdd54db594ca8d3e4 ]
+
+Move the link forcing out of mac_config() and into the mac_prepare()
+and mac_finish() methods. This results in no change to the order in
+which these operations are performed, but does mean when we convert
+mv88e6xxx to phylink_pcs support, we will continue to preserve this
+ordering.
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 52fdc41c3278 ("net: dsa: mv88e6xxx: fix internal PHYs for 6320 family")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/mv88e6xxx/chip.c | 65 ++++++++++++++++++++++----------
+ 1 file changed, 45 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
+index 4c60f79ce2697..b3744f2ea0f48 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -848,29 +848,38 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,
+       }
+ }
++static int mv88e6xxx_mac_prepare(struct dsa_switch *ds, int port,
++                               unsigned int mode, phy_interface_t interface)
++{
++      struct mv88e6xxx_chip *chip = ds->priv;
++      int err = 0;
++
++      /* In inband mode, the link may come up at any time while the link
++       * is not forced down. Force the link down while we reconfigure the
++       * interface mode.
++       */
++      if (mode == MLO_AN_INBAND &&
++          chip->ports[port].interface != interface &&
++          chip->info->ops->port_set_link) {
++              mv88e6xxx_reg_lock(chip);
++              err = chip->info->ops->port_set_link(chip, port,
++                                                   LINK_FORCED_DOWN);
++              mv88e6xxx_reg_unlock(chip);
++      }
++
++      return err;
++}
++
+ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
+                                unsigned int mode,
+                                const struct phylink_link_state *state)
+ {
+       struct mv88e6xxx_chip *chip = ds->priv;
+-      struct mv88e6xxx_port *p;
+       int err = 0;
+-      p = &chip->ports[port];
+-
+       mv88e6xxx_reg_lock(chip);
+       if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) {
+-              /* In inband mode, the link may come up at any time while the
+-               * link is not forced down. Force the link down while we
+-               * reconfigure the interface mode.
+-               */
+-              if (mode == MLO_AN_INBAND &&
+-                  p->interface != state->interface &&
+-                  chip->info->ops->port_set_link)
+-                      chip->info->ops->port_set_link(chip, port,
+-                                                     LINK_FORCED_DOWN);
+-
+               err = mv88e6xxx_port_config_interface(chip, port,
+                                                     state->interface);
+               if (err && err != -EOPNOTSUPP)
+@@ -887,24 +896,38 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
+                       err = 0;
+       }
++err_unlock:
++      mv88e6xxx_reg_unlock(chip);
++
++      if (err && err != -EOPNOTSUPP)
++              dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port);
++}
++
++static int mv88e6xxx_mac_finish(struct dsa_switch *ds, int port,
++                              unsigned int mode, phy_interface_t interface)
++{
++      struct mv88e6xxx_chip *chip = ds->priv;
++      int err = 0;
++
+       /* Undo the forced down state above after completing configuration
+        * irrespective of its state on entry, which allows the link to come
+        * up in the in-band case where there is no separate SERDES. Also
+        * ensure that the link can come up if the PPU is in use and we are
+        * in PHY mode (we treat the PPU as an effective in-band mechanism.)
+        */
++      mv88e6xxx_reg_lock(chip);
++
+       if (chip->info->ops->port_set_link &&
+-          ((mode == MLO_AN_INBAND && p->interface != state->interface) ||
++          ((mode == MLO_AN_INBAND &&
++            chip->ports[port].interface != interface) ||
+            (mode == MLO_AN_PHY && mv88e6xxx_port_ppu_updates(chip, port))))
+-              chip->info->ops->port_set_link(chip, port, LINK_UNFORCED);
++              err = chip->info->ops->port_set_link(chip, port, LINK_UNFORCED);
+-      p->interface = state->interface;
+-
+-err_unlock:
+       mv88e6xxx_reg_unlock(chip);
+-      if (err && err != -EOPNOTSUPP)
+-              dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port);
++      chip->ports[port].interface = interface;
++
++      return err;
+ }
+ static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port,
+@@ -7024,7 +7047,9 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
+       .port_teardown          = mv88e6xxx_port_teardown,
+       .phylink_get_caps       = mv88e6xxx_get_caps,
+       .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state,
++      .phylink_mac_prepare    = mv88e6xxx_mac_prepare,
+       .phylink_mac_config     = mv88e6xxx_mac_config,
++      .phylink_mac_finish     = mv88e6xxx_mac_finish,
+       .phylink_mac_an_restart = mv88e6xxx_serdes_pcs_an_restart,
+       .phylink_mac_link_down  = mv88e6xxx_mac_link_down,
+       .phylink_mac_link_up    = mv88e6xxx_mac_link_up,
+-- 
+2.39.5
+
diff --git a/queue-6.1/net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch b/queue-6.1/net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch
new file mode 100644 (file)
index 0000000..4590b65
--- /dev/null
@@ -0,0 +1,75 @@
+From 66d34fcc02e14531bd917455151d24af92d6840c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 May 2023 10:02:41 +0200
+Subject: net: dsa: mv88e6xxx: pass directly chip structure to
+ mv88e6xxx_phy_is_internal
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alexis Lothoré <alexis.lothore@bootlin.com>
+
+[ Upstream commit ca345931907ff1893f02f5fe1349b16c9fc27e4c ]
+
+Since this function is a simple helper, we do not need to pass a full
+dsa_switch structure, we can directly pass the mv88e6xxx_chip structure.
+Doing so will allow to share this function with any other function
+not manipulating dsa_switch structure but needing info about number of
+internal phys
+
+Signed-off-by: Alexis Lothoré <alexis.lothore@bootlin.com>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 52fdc41c3278 ("net: dsa: mv88e6xxx: fix internal PHYs for 6320 family")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/mv88e6xxx/chip.c | 10 ++++------
+ 1 file changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
+index b3744f2ea0f48..cabf97a902b52 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.c
++++ b/drivers/net/dsa/mv88e6xxx/chip.c
+@@ -470,10 +470,8 @@ static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port,
+       return err;
+ }
+-static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port)
++static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port)
+ {
+-      struct mv88e6xxx_chip *chip = ds->priv;
+-
+       return port < chip->info->num_internal_phys;
+ }
+@@ -591,7 +589,7 @@ static void mv88e6095_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
+       config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100;
+-      if (mv88e6xxx_phy_is_internal(chip->ds, port)) {
++      if (mv88e6xxx_phy_is_internal(chip, port)) {
+               __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces);
+       } else {
+               if (cmode < ARRAY_SIZE(mv88e6185_phy_interface_modes) &&
+@@ -839,7 +837,7 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,
+       chip->info->ops->phylink_get_caps(chip, port, config);
+       mv88e6xxx_reg_unlock(chip);
+-      if (mv88e6xxx_phy_is_internal(ds, port)) {
++      if (mv88e6xxx_phy_is_internal(chip, port)) {
+               __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+                         config->supported_interfaces);
+               /* Internal ports with no phy-mode need GMII for PHYLIB */
+@@ -879,7 +877,7 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port,
+       mv88e6xxx_reg_lock(chip);
+-      if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) {
++      if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(chip, port)) {
+               err = mv88e6xxx_port_config_interface(chip, port,
+                                                     state->interface);
+               if (err && err != -EOPNOTSUPP)
+-- 
+2.39.5
+
diff --git a/queue-6.1/of-resolver-fix-device-node-refcount-leakage-in-of_r.patch b/queue-6.1/of-resolver-fix-device-node-refcount-leakage-in-of_r.patch
new file mode 100644 (file)
index 0000000..2916af2
--- /dev/null
@@ -0,0 +1,45 @@
+From 92adda4d021c532c120dd7f8d6ee84f5c54f7c50 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.1/of-resolver-simplify-of_resolve_phandles-using-__fre.patch b/queue-6.1/of-resolver-simplify-of_resolve_phandles-using-__fre.patch
new file mode 100644 (file)
index 0000000..b052c2a
--- /dev/null
@@ -0,0 +1,114 @@
+From 09a4ac3e5c2002933ffa8e7a9565fca4f203a188 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.1/pci-assign-pci-domain-ids-by-ida_alloc.patch b/queue-6.1/pci-assign-pci-domain-ids-by-ida_alloc.patch
new file mode 100644 (file)
index 0000000..9c0308f
--- /dev/null
@@ -0,0 +1,227 @@
+From 46df1ef1c918c5c96ff50e7c7001a2b0103e2e6c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Jul 2022 20:41:30 +0200
+Subject: PCI: Assign PCI domain IDs by ida_alloc()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pali Rohár <pali@kernel.org>
+
+[ Upstream commit c14f7ccc9f5dcf9d06ddeec706f85405b2c80600 ]
+
+Replace assignment of PCI domain IDs from atomic_inc_return() to
+ida_alloc().
+
+Use two IDAs, one for static domain allocations (those which are defined in
+device tree) and second for dynamic allocations (all other).
+
+During removal of root bus / host bridge, also release the domain ID.  The
+released ID can be reused again, for example when dynamically loading and
+unloading native PCI host bridge drivers.
+
+This change also allows to mix static device tree assignment and dynamic by
+kernel as all static allocations are reserved in dynamic pool.
+
+[bhelgaas: set "err" if "bus->domain_nr < 0"]
+Link: https://lore.kernel.org/r/20220714184130.5436-1-pali@kernel.org
+Signed-off-by: Pali Rohár <pali@kernel.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Stable-dep-of: 804443c1f278 ("PCI: Fix reference leak in pci_register_host_bridge()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pci.c    | 103 +++++++++++++++++++++++++------------------
+ drivers/pci/probe.c  |   7 +++
+ drivers/pci/remove.c |   6 +++
+ include/linux/pci.h  |   1 +
+ 4 files changed, 74 insertions(+), 43 deletions(-)
+
+diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
+index 8a35a9887302d..10436a193b3b6 100644
+--- a/drivers/pci/pci.c
++++ b/drivers/pci/pci.c
+@@ -6808,60 +6808,70 @@ static void pci_no_domains(void)
+ }
+ #ifdef CONFIG_PCI_DOMAINS_GENERIC
+-static atomic_t __domain_nr = ATOMIC_INIT(-1);
++static DEFINE_IDA(pci_domain_nr_static_ida);
++static DEFINE_IDA(pci_domain_nr_dynamic_ida);
+-static int pci_get_new_domain_nr(void)
++static void of_pci_reserve_static_domain_nr(void)
+ {
+-      return atomic_inc_return(&__domain_nr);
++      struct device_node *np;
++      int domain_nr;
++
++      for_each_node_by_type(np, "pci") {
++              domain_nr = of_get_pci_domain_nr(np);
++              if (domain_nr < 0)
++                      continue;
++              /*
++               * Permanently allocate domain_nr in dynamic_ida
++               * to prevent it from dynamic allocation.
++               */
++              ida_alloc_range(&pci_domain_nr_dynamic_ida,
++                              domain_nr, domain_nr, GFP_KERNEL);
++      }
+ }
+ static int of_pci_bus_find_domain_nr(struct device *parent)
+ {
+-      static int use_dt_domains = -1;
+-      int domain = -1;
++      static bool static_domains_reserved = false;
++      int domain_nr;
+-      if (parent)
+-              domain = of_get_pci_domain_nr(parent->of_node);
++      /* On the first call scan device tree for static allocations. */
++      if (!static_domains_reserved) {
++              of_pci_reserve_static_domain_nr();
++              static_domains_reserved = true;
++      }
++
++      if (parent) {
++              /*
++               * If domain is in DT, allocate it in static IDA.  This
++               * prevents duplicate static allocations in case of errors
++               * in DT.
++               */
++              domain_nr = of_get_pci_domain_nr(parent->of_node);
++              if (domain_nr >= 0)
++                      return ida_alloc_range(&pci_domain_nr_static_ida,
++                                             domain_nr, domain_nr,
++                                             GFP_KERNEL);
++      }
+       /*
+-       * Check DT domain and use_dt_domains values.
+-       *
+-       * If DT domain property is valid (domain >= 0) and
+-       * use_dt_domains != 0, the DT assignment is valid since this means
+-       * we have not previously allocated a domain number by using
+-       * pci_get_new_domain_nr(); we should also update use_dt_domains to
+-       * 1, to indicate that we have just assigned a domain number from
+-       * DT.
+-       *
+-       * If DT domain property value is not valid (ie domain < 0), and we
+-       * have not previously assigned a domain number from DT
+-       * (use_dt_domains != 1) we should assign a domain number by
+-       * using the:
+-       *
+-       * pci_get_new_domain_nr()
+-       *
+-       * API and update the use_dt_domains value to keep track of method we
+-       * are using to assign domain numbers (use_dt_domains = 0).
+-       *
+-       * All other combinations imply we have a platform that is trying
+-       * to mix domain numbers obtained from DT and pci_get_new_domain_nr(),
+-       * which is a recipe for domain mishandling and it is prevented by
+-       * invalidating the domain value (domain = -1) and printing a
+-       * corresponding error.
++       * If domain was not specified in DT, choose a free ID from dynamic
++       * allocations. All domain numbers from DT are permanently in
++       * dynamic allocations to prevent assigning them to other DT nodes
++       * without static domain.
+        */
+-      if (domain >= 0 && use_dt_domains) {
+-              use_dt_domains = 1;
+-      } else if (domain < 0 && use_dt_domains != 1) {
+-              use_dt_domains = 0;
+-              domain = pci_get_new_domain_nr();
+-      } else {
+-              if (parent)
+-                      pr_err("Node %pOF has ", parent->of_node);
+-              pr_err("Inconsistent \"linux,pci-domain\" property in DT\n");
+-              domain = -1;
+-      }
++      return ida_alloc(&pci_domain_nr_dynamic_ida, GFP_KERNEL);
++}
+-      return domain;
++static void of_pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent)
++{
++      if (bus->domain_nr < 0)
++              return;
++
++      /* Release domain from IDA where it was allocated. */
++      if (of_get_pci_domain_nr(parent->of_node) == bus->domain_nr)
++              ida_free(&pci_domain_nr_static_ida, bus->domain_nr);
++      else
++              ida_free(&pci_domain_nr_dynamic_ida, bus->domain_nr);
+ }
+ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
+@@ -6869,6 +6879,13 @@ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent)
+       return acpi_disabled ? of_pci_bus_find_domain_nr(parent) :
+                              acpi_pci_bus_find_domain_nr(bus);
+ }
++
++void pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent)
++{
++      if (!acpi_disabled)
++              return;
++      of_pci_bus_release_domain_nr(bus, parent);
++}
+ #endif
+ /**
+diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
+index b4ed95c4a5a61..b818cb7d4f8ac 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -906,6 +906,10 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
+               bus->domain_nr = pci_bus_find_domain_nr(bus, parent);
+       else
+               bus->domain_nr = bridge->domain_nr;
++      if (bus->domain_nr < 0) {
++              err = bus->domain_nr;
++              goto free;
++      }
+ #endif
+       b = pci_find_bus(pci_domain_nr(bus), bridge->busnr);
+@@ -1032,6 +1036,9 @@ static int pci_register_host_bridge(struct pci_host_bridge *bridge)
+       device_del(&bridge->dev);
+ free:
++#ifdef CONFIG_PCI_DOMAINS_GENERIC
++      pci_bus_release_domain_nr(bus, parent);
++#endif
+       kfree(bus);
+       return err;
+ }
+diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
+index 4c54c75050dc1..0145aef1b9301 100644
+--- a/drivers/pci/remove.c
++++ b/drivers/pci/remove.c
+@@ -160,6 +160,12 @@ void pci_remove_root_bus(struct pci_bus *bus)
+       pci_remove_bus(bus);
+       host_bridge->bus = NULL;
++#ifdef CONFIG_PCI_DOMAINS_GENERIC
++      /* Release domain_nr if it was dynamically allocated */
++      if (host_bridge->domain_nr == PCI_DOMAIN_NR_NOT_SET)
++              pci_bus_release_domain_nr(bus, host_bridge->dev.parent);
++#endif
++
+       /* remove the host bridge */
+       device_del(&host_bridge->dev);
+ }
+diff --git a/include/linux/pci.h b/include/linux/pci.h
+index 28f91982402aa..2fd6c6050bb51 100644
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -1779,6 +1779,7 @@ static inline int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
+ { return 0; }
+ #endif
+ int pci_bus_find_domain_nr(struct pci_bus *bus, struct device *parent);
++void pci_bus_release_domain_nr(struct pci_bus *bus, struct device *parent);
+ #endif
+ /* Some architectures require additional setup to direct VGA traffic */
+-- 
+2.39.5
+
diff --git a/queue-6.1/pci-fix-reference-leak-in-pci_register_host_bridge.patch b/queue-6.1/pci-fix-reference-leak-in-pci_register_host_bridge.patch
new file mode 100644 (file)
index 0000000..15eb9dc
--- /dev/null
@@ -0,0 +1,67 @@
+From 86ec43fa14f1e86543d97202cf17c73ba81a3ede 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 b818cb7d4f8ac..03f7550d89827 100644
+--- a/drivers/pci/probe.c
++++ b/drivers/pci/probe.c
+@@ -888,6 +888,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;
+@@ -951,6 +952,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;
+@@ -1034,12 +1036,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.1/phy-freescale-imx8m-pcie-add-i.mx8mp-pcie-phy-suppor.patch b/queue-6.1/phy-freescale-imx8m-pcie-add-i.mx8mp-pcie-phy-suppor.patch
new file mode 100644 (file)
index 0000000..198e999
--- /dev/null
@@ -0,0 +1,112 @@
+From c52f5dbbf11277052c51e9ebdfa675b952ea930b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Oct 2022 09:47:02 +0800
+Subject: phy: freescale: imx8m-pcie: Add i.MX8MP PCIe PHY support
+
+From: Richard Zhu <hongxing.zhu@nxp.com>
+
+[ Upstream commit dce9edff16ee8df20e791e82e0704c4667cc3908 ]
+
+Add i.MX8MP PCIe PHY support.
+
+Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
+Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
+Tested-by: Marek Vasut <marex@denx.de>
+Tested-by: Richard Leitner <richard.leitner@skidata.com>
+Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Reviewed-by: Lucas Stach <l.stach@pengutronix.de>
+Reviewed-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
+Link: https://lore.kernel.org/r/1665625622-20551-5-git-send-email-hongxing.zhu@nxp.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: aecb63e88c5e ("phy: freescale: imx8m-pcie: assert phy reset and perst in power off")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 25 ++++++++++++++++++++--
+ 1 file changed, 23 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+index 211ce84d980f9..0082de17cf4de 100644
+--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
++++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+@@ -50,6 +50,7 @@
+ enum imx8_pcie_phy_type {
+       IMX8MM,
++      IMX8MP,
+ };
+ struct imx8_pcie_phy_drvdata {
+@@ -62,6 +63,7 @@ struct imx8_pcie_phy {
+       struct clk              *clk;
+       struct phy              *phy;
+       struct regmap           *iomuxc_gpr;
++      struct reset_control    *perst;
+       struct reset_control    *reset;
+       u32                     refclk_pad_mode;
+       u32                     tx_deemph_gen1;
+@@ -76,11 +78,11 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
+       u32 val, pad_mode;
+       struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
+-      reset_control_assert(imx8_phy->reset);
+-
+       pad_mode = imx8_phy->refclk_pad_mode;
+       switch (imx8_phy->drvdata->variant) {
+       case IMX8MM:
++              reset_control_assert(imx8_phy->reset);
++
+               /* Tune PHY de-emphasis setting to pass PCIe compliance. */
+               if (imx8_phy->tx_deemph_gen1)
+                       writel(imx8_phy->tx_deemph_gen1,
+@@ -89,6 +91,8 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
+                       writel(imx8_phy->tx_deemph_gen2,
+                              imx8_phy->base + PCIE_PHY_TRSV_REG6);
+               break;
++      case IMX8MP: /* Do nothing. */
++              break;
+       }
+       if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT ||
+@@ -145,6 +149,9 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
+                          IMX8MM_GPR_PCIE_CMN_RST);
+       switch (imx8_phy->drvdata->variant) {
++      case IMX8MP:
++              reset_control_deassert(imx8_phy->perst);
++              fallthrough;
+       case IMX8MM:
+               reset_control_deassert(imx8_phy->reset);
+               usleep_range(200, 500);
+@@ -186,8 +193,14 @@ static const struct imx8_pcie_phy_drvdata imx8mm_drvdata = {
+       .variant = IMX8MM,
+ };
++static const struct imx8_pcie_phy_drvdata imx8mp_drvdata = {
++      .gpr = "fsl,imx8mp-iomuxc-gpr",
++      .variant = IMX8MP,
++};
++
+ static const struct of_device_id imx8_pcie_phy_of_match[] = {
+       {.compatible = "fsl,imx8mm-pcie-phy", .data = &imx8mm_drvdata, },
++      {.compatible = "fsl,imx8mp-pcie-phy", .data = &imx8mp_drvdata, },
+       { },
+ };
+ MODULE_DEVICE_TABLE(of, imx8_pcie_phy_of_match);
+@@ -243,6 +256,14 @@ static int imx8_pcie_phy_probe(struct platform_device *pdev)
+               return PTR_ERR(imx8_phy->reset);
+       }
++      if (imx8_phy->drvdata->variant == IMX8MP) {
++              imx8_phy->perst =
++                      devm_reset_control_get_exclusive(dev, "perst");
++              if (IS_ERR(imx8_phy->perst))
++                      dev_err_probe(dev, PTR_ERR(imx8_phy->perst),
++                                    "Failed to get PCIE PHY PERST control\n");
++      }
++
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       imx8_phy->base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(imx8_phy->base))
+-- 
+2.39.5
+
diff --git a/queue-6.1/phy-freescale-imx8m-pcie-assert-phy-reset-and-perst-.patch b/queue-6.1/phy-freescale-imx8m-pcie-assert-phy-reset-and-perst-.patch
new file mode 100644 (file)
index 0000000..df03fef
--- /dev/null
@@ -0,0 +1,69 @@
+From cbd6d20afb86c2ac0c2f81ab3cbad45f4be66b13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Mar 2025 15:43:16 +0100
+Subject: phy: freescale: imx8m-pcie: assert phy reset and perst in power off
+
+From: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+
+[ Upstream commit aecb63e88c5e5fb9afb782a1577264c76f179af9 ]
+
+Ensure the PHY reset and perst is asserted during power-off to
+guarantee it is in a reset state upon repeated power-on calls. This
+resolves an issue where the PHY may not properly initialize during
+subsequent power-on cycles. Power-on will deassert the reset at the
+appropriate time after tuning the PHY parameters.
+
+During suspend/resume cycles, we observed that the PHY PLL failed to
+lock during resume when the CPU temperature increased from 65C to 75C.
+The observed errors were:
+  phy phy-32f00000.pcie-phy.3: phy poweron failed --> -110
+  imx6q-pcie 33800000.pcie: waiting for PHY ready timeout!
+  imx6q-pcie 33800000.pcie: PM: dpm_run_callback(): genpd_resume_noirq+0x0/0x80 returns -110
+  imx6q-pcie 33800000.pcie: PM: failed to resume noirq: error -110
+
+This resulted in a complete CPU freeze, which is resolved by ensuring
+the PHY is in reset during power-on, thus preventing PHY PLL failures.
+
+Cc: stable@vger.kernel.org
+Fixes: 1aa97b002258 ("phy: freescale: pcie: Initialize the imx8 pcie standalone phy driver")
+Signed-off-by: Stefan Eichenberger <stefan.eichenberger@toradex.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20250305144355.20364-3-eichest@gmail.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/phy/freescale/phy-fsl-imx8m-pcie.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+index 0082de17cf4de..8f9db654019e9 100644
+--- a/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
++++ b/drivers/phy/freescale/phy-fsl-imx8m-pcie.c
+@@ -165,6 +165,16 @@ static int imx8_pcie_phy_power_on(struct phy *phy)
+       return ret;
+ }
++static int imx8_pcie_phy_power_off(struct phy *phy)
++{
++      struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
++
++      reset_control_assert(imx8_phy->reset);
++      reset_control_assert(imx8_phy->perst);
++
++      return 0;
++}
++
+ static int imx8_pcie_phy_init(struct phy *phy)
+ {
+       struct imx8_pcie_phy *imx8_phy = phy_get_drvdata(phy);
+@@ -185,6 +195,7 @@ static const struct phy_ops imx8_pcie_phy_ops = {
+       .init           = imx8_pcie_phy_init,
+       .exit           = imx8_pcie_phy_exit,
+       .power_on       = imx8_pcie_phy_power_on,
++      .power_off      = imx8_pcie_phy_power_off,
+       .owner          = THIS_MODULE,
+ };
+-- 
+2.39.5
+
diff --git a/queue-6.1/s390-pci-report-pci-error-recovery-results-via-sclp.patch b/queue-6.1/s390-pci-report-pci-error-recovery-results-via-sclp.patch
new file mode 100644 (file)
index 0000000..3e4d469
--- /dev/null
@@ -0,0 +1,380 @@
+From d254d444ebcd0fc1d68b88dfc8516ff09d26cef5 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 9d4c7f71e070f..e64dac00e7bf7 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>
+@@ -107,6 +112,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 86dd2cde0f78b..805f0a1ca687f 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.1/s390-pci-support-mmap-of-pci-resources-except-for-is.patch b/queue-6.1/s390-pci-support-mmap-of-pci-resources-except-for-is.patch
new file mode 100644 (file)
index 0000000..0779680
--- /dev/null
@@ -0,0 +1,154 @@
+From fef357f4fd69df1dd912eb0caf083d0ca75a85a4 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 de575af02ffea..50a4a878bae6d 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
+@@ -213,6 +210,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 108e732d7b140..a4e9a6ecbd437 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 d34bb6ec1490f..c0e94e3fd6995 100644
+--- a/drivers/s390/net/ism_drv.c
++++ b/drivers/s390/net/ism_drv.c
+@@ -24,7 +24,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 9d7fb137bd939..db9f01db0ce8d 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -509,6 +509,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.1/s390-sclp-allow-user-space-to-provide-pci-reports-fo.patch b/queue-6.1/s390-sclp-allow-user-space-to-provide-pci-reports-fo.patch
new file mode 100644 (file)
index 0000000..212bd09
--- /dev/null
@@ -0,0 +1,44 @@
+From b4978abba91d51e4fb7d5564561dc1c066003825 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.1/s390-virtio-sort-out-physical-vs-virtual-pointers-us.patch b/queue-6.1/s390-virtio-sort-out-physical-vs-virtual-pointers-us.patch
new file mode 100644 (file)
index 0000000..7e85945
--- /dev/null
@@ -0,0 +1,209 @@
+From 09b30c7c08325e0ff85e19885726b2274dd33d74 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 Jan 2021 12:29:06 +0100
+Subject: s390/virtio: sort out physical vs virtual pointers usage
+
+From: Alexander Gordeev <agordeev@linux.ibm.com>
+
+[ Upstream commit 5fc5b94a273655128159186c87662105db8afeb5 ]
+
+This does not fix a real bug, since virtual addresses
+are currently indentical to physical ones.
+
+Reviewed-by: Nico Boehr <nrb@linux.ibm.com>
+Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
+Signed-off-by: Janosch Frank <frankja@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 | 46 +++++++++++++++++---------------
+ 1 file changed, 24 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
+index a10dbe632ef9b..954fc31b4bc74 100644
+--- a/drivers/s390/virtio/virtio_ccw.c
++++ b/drivers/s390/virtio/virtio_ccw.c
+@@ -363,7 +363,7 @@ static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev,
+               thinint_area->isc = VIRTIO_AIRQ_ISC;
+               ccw->cmd_code = CCW_CMD_SET_IND_ADAPTER;
+               ccw->count = sizeof(*thinint_area);
+-              ccw->cda = (__u32)(unsigned long) thinint_area;
++              ccw->cda = (__u32)virt_to_phys(thinint_area);
+       } else {
+               /* payload is the address of the indicators */
+               indicatorp = ccw_device_dma_zalloc(vcdev->cdev,
+@@ -373,7 +373,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)(unsigned long) indicatorp;
++              ccw->cda = (__u32)virt_to_phys(indicatorp);
+       }
+       /* Deregister indicators from host. */
+       *indicators(vcdev) = 0;
+@@ -417,7 +417,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)(unsigned long)(&vcdev->dma_area->config_block);
++      ccw->cda = (__u32)virt_to_phys(&vcdev->dma_area->config_block);
+       ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_VQ_CONF);
+       if (ret)
+               return ret;
+@@ -454,7 +454,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)(unsigned long)(info->info_block);
++      ccw->cda = (__u32)virt_to_phys(info->info_block);
+       ret = ccw_io_helper(vcdev, ccw,
+                           VIRTIO_CCW_DOING_SET_VQ | index);
+       /*
+@@ -556,7 +556,7 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
+       }
+       ccw->cmd_code = CCW_CMD_SET_VQ;
+       ccw->flags = 0;
+-      ccw->cda = (__u32)(unsigned long)(info->info_block);
++      ccw->cda = (__u32)virt_to_phys(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");
+@@ -590,6 +590,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;
+       struct airq_info *info;
+       thinint_area = ccw_device_dma_zalloc(vcdev->cdev,
+@@ -599,21 +600,22 @@ static int virtio_ccw_register_adapter_ind(struct virtio_ccw_device *vcdev,
+               goto out;
+       }
+       /* Try to get an indicator. */
+-      thinint_area->indicator = get_airq_indicator(vqs, nvqs,
+-                                                   &thinint_area->bit_nr,
+-                                                   &vcdev->airq_info);
+-      if (!thinint_area->indicator) {
++      indicator_addr = get_airq_indicator(vqs, nvqs,
++                                          &thinint_area->bit_nr,
++                                          &vcdev->airq_info);
++      if (!indicator_addr) {
+               ret = -ENOSPC;
+               goto out;
+       }
++      thinint_area->indicator = virt_to_phys((void *)indicator_addr);
+       info = vcdev->airq_info;
+       thinint_area->summary_indicator =
+-              (unsigned long) get_summary_indicator(info);
++              virt_to_phys(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)(unsigned long)thinint_area;
++      ccw->cda = (__u32)virt_to_phys(thinint_area);
+       ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND_ADAPTER);
+       if (ret) {
+               if (ret == -EOPNOTSUPP) {
+@@ -686,7 +688,7 @@ 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)(unsigned long) indicatorp;
++              ccw->cda = (__u32)virt_to_phys(indicatorp);
+               ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_IND);
+               if (ret)
+                       goto out;
+@@ -697,7 +699,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+       ccw->cmd_code = CCW_CMD_SET_CONF_IND;
+       ccw->flags = 0;
+       ccw->count = sizeof(indicators2(vcdev));
+-      ccw->cda = (__u32)(unsigned long) indicatorp;
++      ccw->cda = (__u32)virt_to_phys(indicatorp);
+       ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_SET_CONF_IND);
+       if (ret)
+               goto out;
+@@ -759,7 +761,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)(unsigned long)features;
++      ccw->cda = (__u32)virt_to_phys(features);
+       ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT);
+       if (ret) {
+               rc = 0;
+@@ -776,7 +778,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)(unsigned long)features;
++      ccw->cda = (__u32)virt_to_phys(features);
+       ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_FEAT);
+       if (ret == 0)
+               rc |= (u64)le32_to_cpu(features->features) << 32;
+@@ -829,7 +831,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)(unsigned long)features;
++      ccw->cda = (__u32)virt_to_phys(features);
+       ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT);
+       if (ret)
+               goto out_free;
+@@ -843,7 +845,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)(unsigned long)features;
++      ccw->cda = (__u32)virt_to_phys(features);
+       ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_FEAT);
+ out_free:
+@@ -875,7 +877,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)(unsigned long)config_area;
++      ccw->cda = (__u32)virt_to_phys(config_area);
+       ret = ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_READ_CONFIG);
+       if (ret)
+               goto out_free;
+@@ -922,7 +924,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)(unsigned long)config_area;
++      ccw->cda = (__u32)virt_to_phys(config_area);
+       ccw_io_helper(vcdev, ccw, VIRTIO_CCW_DOING_WRITE_CONFIG);
+ out_free:
+@@ -946,7 +948,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)(unsigned long)&vcdev->dma_area->status;
++      ccw->cda = (__u32)virt_to_phys(&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
+@@ -975,7 +977,7 @@ 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)(unsigned long)&vcdev->dma_area->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.
+@@ -1274,7 +1276,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)(unsigned long)rev;
++      ccw->cda = (__u32)virt_to_phys(rev);
+       vcdev->revision = VIRTIO_CCW_REV_MAX;
+       do {
+-- 
+2.39.5
+
diff --git a/queue-6.1/s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-.patch b/queue-6.1/s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-.patch
new file mode 100644 (file)
index 0000000..a56c43e
--- /dev/null
@@ -0,0 +1,145 @@
+From 3557152649172140e721e26ce539250133ce4a93 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 f2d54c7015de4..dab743724a982 100644
+--- a/drivers/s390/virtio/virtio_ccw.c
++++ b/drivers/s390/virtio/virtio_ccw.c
+@@ -264,11 +264,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])
+@@ -278,7 +284,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);
+@@ -287,8 +293,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.1/s390-virtio_ccw-fix-virtual-vs-physical-address-conf.patch b/queue-6.1/s390-virtio_ccw-fix-virtual-vs-physical-address-conf.patch
new file mode 100644 (file)
index 0000000..a7068e2
--- /dev/null
@@ -0,0 +1,320 @@
+From f558381e2515aa14b943fbf184de6ac0c9342887 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 954fc31b4bc74..f2d54c7015de4 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;
+@@ -261,12 +261,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++) {
+@@ -276,7 +276,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) {
+@@ -286,7 +286,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]);
+@@ -359,11 +359,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,
+@@ -373,7 +373,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;
+@@ -417,7 +417,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;
+@@ -454,7 +454,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);
+       /*
+@@ -541,22 +541,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");
+@@ -590,7 +590,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,
+@@ -607,15 +607,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) {
+@@ -643,7 +643,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;
+@@ -675,7 +675,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)
+@@ -688,18 +688,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;
+@@ -761,7 +761,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;
+@@ -778,7 +778,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;
+@@ -831,7 +831,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;
+@@ -845,7 +845,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:
+@@ -877,7 +877,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;
+@@ -924,7 +924,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:
+@@ -948,7 +948,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
+@@ -977,11 +977,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)
+@@ -1276,7 +1276,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.1/selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch b/queue-6.1/selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch
new file mode 100644 (file)
index 0000000..e2ec774
--- /dev/null
@@ -0,0 +1,79 @@
+From 88a3d32994eef02213e8b5a87f193f68a61a4246 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Apr 2025 17:42:32 +0100
+Subject: selftests/mm: generate a temporary mountpoint for cgroup filesystem
+
+From: Mark Brown <broonie@kernel.org>
+
+[ Upstream commit 9c02223e2d9df5cb37c51aedb78f3960294e09b5 ]
+
+Currently if the filesystem for the cgroups version it wants to use is not
+mounted charge_reserved_hugetlb.sh and hugetlb_reparenting_test.sh tests
+will attempt to mount it on the hard coded path /dev/cgroup/memory,
+deleting that directory when the test finishes.  This will fail if there
+is not a preexisting directory at that path, and since the directory is
+deleted subsequent runs of the test will fail.  Instead of relying on this
+hard coded directory name use mktemp to generate a temporary directory to
+use as a mountpoint, fixing both the assumption and the disruption caused
+by deleting a preexisting directory.
+
+This means that if the relevant cgroup filesystem is not already mounted
+then we rely on having coreutils (which provides mktemp) installed.  I
+suspect that many current users are relying on having things automounted
+by default, and given that the script relies on bash it's probably not an
+unreasonable requirement.
+
+Link: https://lkml.kernel.org/r/20250404-kselftest-mm-cgroup2-detection-v1-1-3dba6d32ba8c@kernel.org
+Fixes: 209376ed2a84 ("selftests/vm: make charge_reserved_hugetlb.sh work with existing cgroup setting")
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Cc: Aishwarya TCV <aishwarya.tcv@arm.com>
+Cc: Mark Brown <broonie@kernel.org>
+Cc: Mina Almasry <almasrymina@google.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Cc: Waiman Long <longman@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/vm/charge_reserved_hugetlb.sh  | 4 ++--
+ tools/testing/selftests/vm/hugetlb_reparenting_test.sh | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
+index 8e00276b4e69b..dc3fc438b3d9e 100644
+--- a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
++++ b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
+@@ -27,7 +27,7 @@ fi
+ if [[ $cgroup2 ]]; then
+   cgroup_path=$(mount -t cgroup2 | head -1 | awk '{print $3}')
+   if [[ -z "$cgroup_path" ]]; then
+-    cgroup_path=/dev/cgroup/memory
++    cgroup_path=$(mktemp -d)
+     mount -t cgroup2 none $cgroup_path
+     do_umount=1
+   fi
+@@ -35,7 +35,7 @@ if [[ $cgroup2 ]]; then
+ else
+   cgroup_path=$(mount -t cgroup | grep ",hugetlb" | awk '{print $3}')
+   if [[ -z "$cgroup_path" ]]; then
+-    cgroup_path=/dev/cgroup/memory
++    cgroup_path=$(mktemp -d)
+     mount -t cgroup memory,hugetlb $cgroup_path
+     do_umount=1
+   fi
+diff --git a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh
+index 14d26075c8635..302f2c7003f03 100644
+--- a/tools/testing/selftests/vm/hugetlb_reparenting_test.sh
++++ b/tools/testing/selftests/vm/hugetlb_reparenting_test.sh
+@@ -22,7 +22,7 @@ fi
+ if [[ $cgroup2 ]]; then
+   CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk '{print $3}')
+   if [[ -z "$CGROUP_ROOT" ]]; then
+-    CGROUP_ROOT=/dev/cgroup/memory
++    CGROUP_ROOT=$(mktemp -d)
+     mount -t cgroup2 none $CGROUP_ROOT
+     do_umount=1
+   fi
+-- 
+2.39.5
+
index 673df00e1a3ed9c0832c90f662fbd29e0f1a4030..a95b12b29f8c6d5062ff903c0b71d14aeafd0fdf 100644 (file)
@@ -1 +1,42 @@
 module-sign-with-sha512-instead-of-sha1-by-default.patch
+memcg-drain-obj-stock-on-cpu-hotplug-teardown.patch
+tracing-add-__cpumask-to-denote-a-trace-event-field-.patch
+tracing-fix-cpumask-example-typo.patch
+tracing-add-__string_len-example.patch
+tracing-add-__print_dynamic_array-helper.patch
+tracing-verify-event-formats-that-have-p.patch
+auxdisplay-hd44780-convert-to-platform-remove-callba.patch
+auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch
+net-dsa-mv88e6xxx-don-t-dispose-of-global2-irq-mappi.patch
+net-dsa-add-support-for-mac_prepare-and-mac_finish-c.patch
+net-dsa-mv88e6xxx-move-link-forcing-to-mac_prepare-m.patch
+net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch
+net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch
+net-dsa-mv88e6xxx-fix-internal-phys-for-6320-family.patch
+net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch
+iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch
+iio-adc-ad7768-1-fix-conversion-result-sign.patch
+backlight-led_bl-convert-to-platform-remove-callback.patch
+backlight-led_bl-hold-led_access-lock-when-calling-l.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-assign-pci-domain-ids-by-ida_alloc.patch
+pci-fix-reference-leak-in-pci_register_host_bridge.patch
+s390-virtio-sort-out-physical-vs-virtual-pointers-us.patch
+s390-virtio_ccw-fix-virtual-vs-physical-address-conf.patch
+s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-.patch
+phy-freescale-imx8m-pcie-add-i.mx8mp-pcie-phy-suppor.patch
+phy-freescale-imx8m-pcie-assert-phy-reset-and-perst-.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
+asoc-qcom-q6dsp-add-support-to-more-display-ports.patch
+asoc-qcom-fix-sc7280-lpass-potential-buffer-overflow.patch
+selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch
diff --git a/queue-6.1/tracing-add-__cpumask-to-denote-a-trace-event-field-.patch b/queue-6.1/tracing-add-__cpumask-to-denote-a-trace-event-field-.patch
new file mode 100644 (file)
index 0000000..09f6a90
--- /dev/null
@@ -0,0 +1,396 @@
+From 2416a5a01fceafac481754bfeca7f6e3daad2110 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Oct 2022 08:04:56 -0400
+Subject: tracing: Add __cpumask to denote a trace event field that is a
+ cpumask_t
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+[ Upstream commit 8230f27b1ccc4b8976c137e3d6d690f9d4ffca8d ]
+
+The trace events have a __bitmask field that can be used for anything
+that requires bitmasks. Although currently it is only used for CPU
+masks, it could be used in the future for any type of bitmasks.
+
+There is some user space tooling that wants to know if a field is a CPU
+mask and not just some random unsigned long bitmask. Introduce
+"__cpumask()" helper functions that work the same as the current
+__bitmask() helpers but displays in the format file:
+
+  field:__data_loc cpumask_t *[] mask;    offset:36;      size:4; signed:0;
+
+Instead of:
+
+  field:__data_loc unsigned long[] mask;  offset:32;      size:4; signed:0;
+
+The main difference is the type. Instead of "unsigned long" it is
+"cpumask_t *". Note, this type field needs to be a real type in the
+__dynamic_array() logic that both __cpumask and__bitmask use, but the
+comparison field requires it to be a scalar type whereas cpumask_t is a
+structure (non-scalar). But everything works when making it a pointer.
+
+Valentin added changes to remove the need of passing in "nr_bits" and the
+__cpumask will always use nr_cpumask_bits as its size.
+
+Link: https://lkml.kernel.org/r/20221014080456.1d32b989@rorschach.local.home
+
+Requested-by: Valentin Schneider <vschneid@redhat.com>
+Reviewed-by: Valentin Schneider <vschneid@redhat.com>
+Signed-off-by: Valentin Schneider <vschneid@redhat.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>
+---
+ include/trace/bpf_probe.h                    |  6 ++++
+ include/trace/perf.h                         |  6 ++++
+ include/trace/stages/stage1_struct_define.h  |  6 ++++
+ include/trace/stages/stage2_data_offsets.h   |  6 ++++
+ include/trace/stages/stage3_trace_output.h   |  6 ++++
+ include/trace/stages/stage4_event_fields.h   |  6 ++++
+ include/trace/stages/stage5_get_offsets.h    |  6 ++++
+ include/trace/stages/stage6_event_callback.h | 20 ++++++++++++
+ include/trace/stages/stage7_class_define.h   |  2 ++
+ samples/trace_events/trace-events-sample.c   |  2 +-
+ samples/trace_events/trace-events-sample.h   | 34 +++++++++++++++-----
+ 11 files changed, 91 insertions(+), 9 deletions(-)
+
+diff --git a/include/trace/bpf_probe.h b/include/trace/bpf_probe.h
+index 6a13220d2d27b..155c495b89ead 100644
+--- a/include/trace/bpf_probe.h
++++ b/include/trace/bpf_probe.h
+@@ -21,6 +21,9 @@
+ #undef __get_bitmask
+ #define __get_bitmask(field) (char *)__get_dynamic_array(field)
++#undef __get_cpumask
++#define __get_cpumask(field) (char *)__get_dynamic_array(field)
++
+ #undef __get_sockaddr
+ #define __get_sockaddr(field) ((struct sockaddr *)__get_dynamic_array(field))
+@@ -40,6 +43,9 @@
+ #undef __get_rel_bitmask
+ #define __get_rel_bitmask(field) (char *)__get_rel_dynamic_array(field)
++#undef __get_rel_cpumask
++#define __get_rel_cpumask(field) (char *)__get_rel_dynamic_array(field)
++
+ #undef __get_rel_sockaddr
+ #define __get_rel_sockaddr(field) ((struct sockaddr *)__get_rel_dynamic_array(field))
+diff --git a/include/trace/perf.h b/include/trace/perf.h
+index 5800d13146c3d..8f3bf1e177070 100644
+--- a/include/trace/perf.h
++++ b/include/trace/perf.h
+@@ -21,6 +21,9 @@
+ #undef __get_bitmask
+ #define __get_bitmask(field) (char *)__get_dynamic_array(field)
++#undef __get_cpumask
++#define __get_cpumask(field) (char *)__get_dynamic_array(field)
++
+ #undef __get_sockaddr
+ #define __get_sockaddr(field) ((struct sockaddr *)__get_dynamic_array(field))
+@@ -41,6 +44,9 @@
+ #undef __get_rel_bitmask
+ #define __get_rel_bitmask(field) (char *)__get_rel_dynamic_array(field)
++#undef __get_rel_cpumask
++#define __get_rel_cpumask(field) (char *)__get_rel_dynamic_array(field)
++
+ #undef __get_rel_sockaddr
+ #define __get_rel_sockaddr(field) ((struct sockaddr *)__get_rel_dynamic_array(field))
+diff --git a/include/trace/stages/stage1_struct_define.h b/include/trace/stages/stage1_struct_define.h
+index 1b7bab60434c1..69e0dae453bfa 100644
+--- a/include/trace/stages/stage1_struct_define.h
++++ b/include/trace/stages/stage1_struct_define.h
+@@ -32,6 +32,9 @@
+ #undef __bitmask
+ #define __bitmask(item, nr_bits) __dynamic_array(char, item, -1)
++#undef __cpumask
++#define __cpumask(item) __dynamic_array(char, item, -1)
++
+ #undef __sockaddr
+ #define __sockaddr(field, len) __dynamic_array(u8, field, len)
+@@ -47,6 +50,9 @@
+ #undef __rel_bitmask
+ #define __rel_bitmask(item, nr_bits) __rel_dynamic_array(char, item, -1)
++#undef __rel_cpumask
++#define __rel_cpumask(item) __rel_dynamic_array(char, item, -1)
++
+ #undef __rel_sockaddr
+ #define __rel_sockaddr(field, len) __rel_dynamic_array(u8, field, len)
+diff --git a/include/trace/stages/stage2_data_offsets.h b/include/trace/stages/stage2_data_offsets.h
+index 1b7a8f764fddd..469b6a64293de 100644
+--- a/include/trace/stages/stage2_data_offsets.h
++++ b/include/trace/stages/stage2_data_offsets.h
+@@ -38,6 +38,9 @@
+ #undef __bitmask
+ #define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, -1)
++#undef __cpumask
++#define __cpumask(item) __dynamic_array(unsigned long, item, -1)
++
+ #undef __sockaddr
+ #define __sockaddr(field, len) __dynamic_array(u8, field, len)
+@@ -53,5 +56,8 @@
+ #undef __rel_bitmask
+ #define __rel_bitmask(item, nr_bits) __rel_dynamic_array(unsigned long, item, -1)
++#undef __rel_cpumask
++#define __rel_cpumask(item) __rel_dynamic_array(unsigned long, item, -1)
++
+ #undef __rel_sockaddr
+ #define __rel_sockaddr(field, len) __rel_dynamic_array(u8, field, len)
+diff --git a/include/trace/stages/stage3_trace_output.h b/include/trace/stages/stage3_trace_output.h
+index e3b183e9d18ea..66374df61ed30 100644
+--- a/include/trace/stages/stage3_trace_output.h
++++ b/include/trace/stages/stage3_trace_output.h
+@@ -42,6 +42,9 @@
+               trace_print_bitmask_seq(p, __bitmask, __bitmask_size);  \
+       })
++#undef __get_cpumask
++#define __get_cpumask(field) __get_bitmask(field)
++
+ #undef __get_rel_bitmask
+ #define __get_rel_bitmask(field)                                              \
+       ({                                                              \
+@@ -51,6 +54,9 @@
+               trace_print_bitmask_seq(p, __bitmask, __bitmask_size);  \
+       })
++#undef __get_rel_cpumask
++#define __get_rel_cpumask(field) __get_rel_bitmask(field)
++
+ #undef __get_sockaddr
+ #define __get_sockaddr(field) ((struct sockaddr *)__get_dynamic_array(field))
+diff --git a/include/trace/stages/stage4_event_fields.h b/include/trace/stages/stage4_event_fields.h
+index fae467ccd0c3c..5e7ebe69de8c1 100644
+--- a/include/trace/stages/stage4_event_fields.h
++++ b/include/trace/stages/stage4_event_fields.h
+@@ -47,6 +47,9 @@
+ #undef __bitmask
+ #define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, -1)
++#undef __cpumask
++#define __cpumask(item) __dynamic_array(cpumask_t *, item, -1)
++
+ #undef __sockaddr
+ #define __sockaddr(field, len) __dynamic_array(u8, field, len)
+@@ -65,5 +68,8 @@
+ #undef __rel_bitmask
+ #define __rel_bitmask(item, nr_bits) __rel_dynamic_array(unsigned long, item, -1)
++#undef __rel_cpumask
++#define __rel_cpumask(item) __rel_dynamic_array(cpumask_t *, item, -1)
++
+ #undef __rel_sockaddr
+ #define __rel_sockaddr(field, len) __rel_dynamic_array(u8, field, len)
+diff --git a/include/trace/stages/stage5_get_offsets.h b/include/trace/stages/stage5_get_offsets.h
+index def36fbb8c5cd..e30a13be46ba5 100644
+--- a/include/trace/stages/stage5_get_offsets.h
++++ b/include/trace/stages/stage5_get_offsets.h
+@@ -95,10 +95,16 @@
+ #define __bitmask(item, nr_bits) __dynamic_array(unsigned long, item, \
+                                        __bitmask_size_in_longs(nr_bits))
++#undef __cpumask
++#define __cpumask(item) __bitmask(item, nr_cpumask_bits)
++
+ #undef __rel_bitmask
+ #define __rel_bitmask(item, nr_bits) __rel_dynamic_array(unsigned long, item, \
+                                        __bitmask_size_in_longs(nr_bits))
++#undef __rel_cpumask
++#define __rel_cpumask(item) __rel_bitmask(item, nr_cpumask_bits)
++
+ #undef __sockaddr
+ #define __sockaddr(field, len) __dynamic_array(u8, field, len)
+diff --git a/include/trace/stages/stage6_event_callback.h b/include/trace/stages/stage6_event_callback.h
+index 3c554a5853204..49c32394b53fb 100644
+--- a/include/trace/stages/stage6_event_callback.h
++++ b/include/trace/stages/stage6_event_callback.h
+@@ -57,6 +57,16 @@
+ #define __assign_bitmask(dst, src, nr_bits)                                   \
+       memcpy(__get_bitmask(dst), (src), __bitmask_size_in_bytes(nr_bits))
++#undef __cpumask
++#define __cpumask(item) __dynamic_array(unsigned long, item, -1)
++
++#undef __get_cpumask
++#define __get_cpumask(field) (char *)__get_dynamic_array(field)
++
++#undef __assign_cpumask
++#define __assign_cpumask(dst, src)                                    \
++      memcpy(__get_cpumask(dst), (src), __bitmask_size_in_bytes(nr_cpumask_bits))
++
+ #undef __sockaddr
+ #define __sockaddr(field, len) __dynamic_array(u8, field, len)
+@@ -98,6 +108,16 @@
+ #define __assign_rel_bitmask(dst, src, nr_bits)                                       \
+       memcpy(__get_rel_bitmask(dst), (src), __bitmask_size_in_bytes(nr_bits))
++#undef __rel_cpumask
++#define __rel_cpumask(item) __rel_dynamic_array(unsigned long, item, -1)
++
++#undef __get_rel_cpumask
++#define __get_rel_cpumask(field) (char *)__get_rel_dynamic_array(field)
++
++#undef __assign_rel_cpumask
++#define __assign_rel_cpumask(dst, src)                                        \
++      memcpy(__get_rel_cpumask(dst), (src), __bitmask_size_in_bytes(nr_cpumask_bits))
++
+ #undef __rel_sockaddr
+ #define __rel_sockaddr(field, len) __rel_dynamic_array(u8, field, len)
+diff --git a/include/trace/stages/stage7_class_define.h b/include/trace/stages/stage7_class_define.h
+index 8a7ec24c246dd..8795429f388b0 100644
+--- a/include/trace/stages/stage7_class_define.h
++++ b/include/trace/stages/stage7_class_define.h
+@@ -13,11 +13,13 @@
+ #undef __get_dynamic_array_len
+ #undef __get_str
+ #undef __get_bitmask
++#undef __get_cpumask
+ #undef __get_sockaddr
+ #undef __get_rel_dynamic_array
+ #undef __get_rel_dynamic_array_len
+ #undef __get_rel_str
+ #undef __get_rel_bitmask
++#undef __get_rel_cpumask
+ #undef __get_rel_sockaddr
+ #undef __print_array
+ #undef __print_hex_dump
+diff --git a/samples/trace_events/trace-events-sample.c b/samples/trace_events/trace-events-sample.c
+index 608c4ae3b08a3..ecc7db237f2ef 100644
+--- a/samples/trace_events/trace-events-sample.c
++++ b/samples/trace_events/trace-events-sample.c
+@@ -50,7 +50,7 @@ static void do_simple_thread_func(int cnt, const char *fmt, ...)
+       trace_foo_with_template_print("I have to be different", cnt);
+-      trace_foo_rel_loc("Hello __rel_loc", cnt, bitmask);
++      trace_foo_rel_loc("Hello __rel_loc", cnt, bitmask, current->cpus_ptr);
+ }
+ static void simple_thread_func(int cnt)
+diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h
+index 1a92226202fc5..fb4548a44153c 100644
+--- a/samples/trace_events/trace-events-sample.h
++++ b/samples/trace_events/trace-events-sample.h
+@@ -200,6 +200,16 @@
+  *
+  *         __assign_bitmask(target_cpus, cpumask_bits(bar), nr_cpumask_bits);
+  *
++ *   __cpumask: This is pretty much the same as __bitmask but is specific for
++ *         CPU masks. The type displayed to the user via the format files will
++ *         be "cpumaks_t" such that user space may deal with them differently
++ *         if they choose to do so, and the bits is always set to nr_cpumask_bits.
++ *
++ *         __cpumask(target_cpu)
++ *
++ *         To assign a cpumask, use the __assign_cpumask() helper macro.
++ *
++ *         __assign_cpumask(target_cpus, cpumask_bits(bar));
+  *
+  * fast_assign: This is a C like function that is used to store the items
+  *    into the ring buffer. A special variable called "__entry" will be the
+@@ -212,8 +222,8 @@
+  *    This is also used to print out the data from the trace files.
+  *    Again, the __entry macro is used to access the data from the ring buffer.
+  *
+- *    Note, __dynamic_array, __string, and __bitmask require special helpers
+- *       to access the data.
++ *    Note, __dynamic_array, __string, __bitmask and __cpumask require special
++ *       helpers to access the data.
+  *
+  *      For __dynamic_array(int, foo, bar) use __get_dynamic_array(foo)
+  *            Use __get_dynamic_array_len(foo) to get the length of the array
+@@ -226,6 +236,8 @@
+  *
+  *      For __bitmask(target_cpus, nr_cpumask_bits) use __get_bitmask(target_cpus)
+  *
++ *      For __cpumask(target_cpus) use __get_cpumask(target_cpus)
++ *
+  *
+  * Note, that for both the assign and the printk, __entry is the handler
+  * to the data structure in the ring buffer, and is defined by the
+@@ -288,6 +300,7 @@ TRACE_EVENT(foo_bar,
+               __dynamic_array(int,    list,   __length_of(lst))
+               __string(       str,    string                  )
+               __bitmask(      cpus,   num_possible_cpus()     )
++              __cpumask(      cpum                            )
+               __vstring(      vstr,   fmt,    va              )
+       ),
+@@ -299,9 +312,10 @@ TRACE_EVENT(foo_bar,
+               __assign_str(str, string);
+               __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", __entry->foo, __entry->bar,
++      TP_printk("foo %s %d %s %s %s %s (%s) (%s) %s", __entry->foo, __entry->bar,
+ /*
+  * Notice here the use of some helper functions. This includes:
+@@ -345,7 +359,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_str(vstr))
++                __get_str(str), __get_bitmask(cpus), __get_cpumask(cpus),
++                __get_str(vstr))
+ );
+ /*
+@@ -542,15 +557,16 @@ DEFINE_EVENT_PRINT(foo_template, foo_with_template_print,
+ TRACE_EVENT(foo_rel_loc,
+-      TP_PROTO(const char *foo, int bar, unsigned long *mask),
++      TP_PROTO(const char *foo, int bar, unsigned long *mask, const cpumask_t *cpus),
+-      TP_ARGS(foo, bar, mask),
++      TP_ARGS(foo, bar, mask, cpus),
+       TP_STRUCT__entry(
+               __rel_string(   foo,    foo     )
+               __field(        int,    bar     )
+               __rel_bitmask(  bitmask,
+                       BITS_PER_BYTE * sizeof(unsigned long)   )
++              __rel_cpumask(  cpumask )
+       ),
+       TP_fast_assign(
+@@ -558,10 +574,12 @@ TRACE_EVENT(foo_rel_loc,
+               __entry->bar = bar;
+               __assign_rel_bitmask(bitmask, mask,
+                       BITS_PER_BYTE * sizeof(unsigned long));
++              __assign_rel_cpumask(cpumask, cpus);
+       ),
+-      TP_printk("foo_rel_loc %s, %d, %s", __get_rel_str(foo), __entry->bar,
+-                __get_rel_bitmask(bitmask))
++      TP_printk("foo_rel_loc %s, %d, %s, %s", __get_rel_str(foo), __entry->bar,
++                __get_rel_bitmask(bitmask),
++                __get_rel_cpumask(cpumask))
+ );
+ #endif
+-- 
+2.39.5
+
diff --git a/queue-6.1/tracing-add-__print_dynamic_array-helper.patch b/queue-6.1/tracing-add-__print_dynamic_array-helper.patch
new file mode 100644 (file)
index 0000000..f70856c
--- /dev/null
@@ -0,0 +1,94 @@
+From 803bb93aba6416a0ade484d8761cbdb1df01f0d2 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 66374df61ed30..816c2da7a46ff 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 8795429f388b0..5e3e43adb73e6 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
+ /*
+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.1/tracing-add-__string_len-example.patch b/queue-6.1/tracing-add-__string_len-example.patch
new file mode 100644 (file)
index 0000000..46c9d61
--- /dev/null
@@ -0,0 +1,63 @@
+From 8c5e7f2c817a1176f2915ad438486f9526c9bf89 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.1/tracing-fix-cpumask-example-typo.patch b/queue-6.1/tracing-fix-cpumask-example-typo.patch
new file mode 100644 (file)
index 0000000..9fca64e
--- /dev/null
@@ -0,0 +1,44 @@
+From 8d055c06b7fc4a4c5f60acb40ba0a1086e472b62 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Dec 2022 22:12:27 -0500
+Subject: tracing: Fix cpumask() example typo
+
+From: Steven Rostedt (Google) <rostedt@goodmis.org>
+
+[ Upstream commit eb9d58947d40699d93e5e69e1ddc54e41da7e132 ]
+
+The sample code for using cpumask used the wrong field for the
+__get_cpumask() helper. It used "cpus" which is the bitmask (but would
+still give a proper example) instead of the "cpum" that was there to be
+used.
+
+Although it produces the same output, fix it, because it's an example and
+is confusing in how to properly use the cpumask() macro.
+
+Link: https://lore.kernel.org/linux-trace-kernel/20221213221227.56560374@gandalf.local.home
+
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+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 | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h
+index fb4548a44153c..1c6b843b8c4ee 100644
+--- a/samples/trace_events/trace-events-sample.h
++++ b/samples/trace_events/trace-events-sample.h
+@@ -359,7 +359,7 @@ 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(cpus),
++                __get_str(str), __get_bitmask(cpus), __get_cpumask(cpum),
+                 __get_str(vstr))
+ );
+-- 
+2.39.5
+
diff --git a/queue-6.1/tracing-verify-event-formats-that-have-p.patch b/queue-6.1/tracing-verify-event-formats-that-have-p.patch
new file mode 100644 (file)
index 0000000..7cb8f04
--- /dev/null
@@ -0,0 +1,93 @@
+From c97a31b3618e960efe772ebe96dcbf4366d3a061 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 ed0d0c8a2b4bb..8723ad2f9c63b 100644
+--- a/kernel/trace/trace_events.c
++++ b/kernel/trace/trace_events.c
+@@ -456,6 +456,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':
+@@ -484,6 +485,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
+