From: Sasha Levin Date: Sat, 26 Apr 2025 13:23:09 +0000 (-0400) Subject: Fixes for 6.1 X-Git-Tag: v5.4.293~88 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=03af651e54f2ac6e342380064ad73ae49197dbc9;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.1 Signed-off-by: Sasha Levin --- 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 index 0000000000..a08aeb0766 --- /dev/null +++ b/queue-6.1/asoc-qcom-fix-sc7280-lpass-potential-buffer-overflow.patch @@ -0,0 +1,51 @@ +From 29e85b7eb175f45a319297a03568b5002c9df9bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 1 Apr 2025 23:40:58 +0300 +Subject: ASoC: qcom: Fix sc7280 lpass potential buffer overflow + +From: Evgeny Pimenov + +[ 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 +Suggested-by: Alexey Khoroshilov +Signed-off-by: Evgeny Pimenov +Link: https://patch.msgid.link/20250401204058.32261-1-pimenoveu12@gmail.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#include + #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 index 0000000000..83200e0024 --- /dev/null +++ b/queue-6.1/asoc-qcom-q6dsp-add-support-to-more-display-ports.patch @@ -0,0 +1,114 @@ +From 6f112bf8b64f338a1a8f375d1514a1c504666d4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 May 2023 12:22:01 +0100 +Subject: ASoC: qcom: q6dsp: add support to more display ports + +From: Srinivas Kandagatla + +[ 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 +--- + .../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 index 0000000000..9fb967634c --- /dev/null +++ b/queue-6.1/auxdisplay-hd44780-convert-to-platform-remove-callba.patch @@ -0,0 +1,68 @@ +From 1807818a218d6b1203655f641fb4aa0487b729fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Andy Shevchenko +Stable-dep-of: 9b98a7d2e5f4 ("auxdisplay: hd44780: Fix an API misuse in hd44780.c") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..954690b93f --- /dev/null +++ b/queue-6.1/auxdisplay-hd44780-fix-an-api-misuse-in-hd44780.c.patch @@ -0,0 +1,48 @@ +From c33001b04a2331008447bcb50240f9b2da5d5923 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 18:15:27 +0800 +Subject: auxdisplay: hd44780: Fix an API misuse in hd44780.c + +From: Haoxiang Li + +[ 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 +Reviewed-by: Geert Uytterhoeven +Signed-off-by: Andy Shevchenko +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..3f7d8f2acd --- /dev/null +++ b/queue-6.1/backlight-led_bl-convert-to-platform-remove-callback.patch @@ -0,0 +1,67 @@ +From 1bad9321b05568d81ebe356b79efa549dc6744ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Daniel Thompson +Signed-off-by: Lee Jones +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 +--- + 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 index 0000000000..f08200b92a --- /dev/null +++ b/queue-6.1/backlight-led_bl-hold-led_access-lock-when-calling-l.patch @@ -0,0 +1,56 @@ +From 2a8057bf149e83474c50d86605dcb15cc4bda858 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20250122091914.309533-1-herve.codina@bootlin.com +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..570dc3901d --- /dev/null +++ b/queue-6.1/clk-renesas-r9a07g04-34-fix-typo-for-sel_shdi-variab.patch @@ -0,0 +1,75 @@ +From 9e76563149ad5e728bd6274175e3007b340b8704 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jan 2024 12:29:30 +0200 +Subject: clk: renesas: r9a07g04[34]: Fix typo for sel_shdi variable + +From: Claudiu Beznea + +[ Upstream commit 46fb5dd9ca289953fa791b2bb060dac7f8002ae0 ] + +Fix typo for sel_shdi variable. + +Signed-off-by: Claudiu Beznea +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20240131102930.1841901-3-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..7953ddb12f --- /dev/null +++ b/queue-6.1/clk-renesas-r9a07g04-34-use-sel_sdhi1_sts-status-con.patch @@ -0,0 +1,54 @@ +From 5420ac6e9e50c237e129e10b62a5afefb9a4fec8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Claudiu Beznea +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20240131102930.1841901-2-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..4b40d10f1c --- /dev/null +++ b/queue-6.1/clk-renesas-r9a07g043-fix-hp-clock-source-for-rz-fiv.patch @@ -0,0 +1,59 @@ +From 9e621c7a3e234e35020640301215111680656e52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 27 Jan 2025 17:31:59 +0000 +Subject: clk: renesas: r9a07g043: Fix HP clock source for RZ/Five + +From: Lad Prabhakar + +[ 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 +Signed-off-by: Lad Prabhakar +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/20250127173159.34572-1-prabhakar.mahadev-lad.rj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..2427fb3501 --- /dev/null +++ b/queue-6.1/clk-renesas-rzg2l-add-struct-clk_hw_data.patch @@ -0,0 +1,137 @@ +From 3943decb0e79f7c4e543803858ceee77266aefd3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Sep 2023 08:38:55 +0300 +Subject: clk: renesas: rzg2l: Add struct clk_hw_data + +From: Claudiu Beznea + +[ 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 +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20230929053915.1530607-9-claudiu.beznea@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..0553444613 --- /dev/null +++ b/queue-6.1/clk-renesas-rzg2l-refactor-sd-mux-driver.patch @@ -0,0 +1,423 @@ +From 4870db097e423d2bd24216c0c0cb51e3b05fde22 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Oct 2023 13:39:57 +0300 +Subject: clk: renesas: rzg2l: Refactor SD mux driver + +From: Claudiu Beznea + +[ 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 +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20231006103959.197485-3-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five") +Signed-off-by: Sasha Levin +--- + 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 ++ + #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 index 0000000000..08343f4a8e --- /dev/null +++ b/queue-6.1/clk-renesas-rzg2l-remove-cpg_sdhi_dsel-from-generic-.patch @@ -0,0 +1,85 @@ +From 0e8bf632139ca2a80122e02a499d1913d9331f8c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Sep 2023 08:38:56 +0300 +Subject: clk: renesas: rzg2l: Remove CPG_SDHI_DSEL from generic header + +From: Claudiu Beznea + +[ 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 +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20230929053915.1530607-10-claudiu.beznea@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..812f300ff4 --- /dev/null +++ b/queue-6.1/clk-renesas-rzg2l-use-u32-for-flag-and-mux_flags.patch @@ -0,0 +1,39 @@ +From 91180e6edf6c39ad7a0fd23d075db5be888bc17e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Sep 2023 07:51:34 +0300 +Subject: clk: renesas: rzg2l: Use u32 for flag and mux_flags + +From: Claudiu Beznea + +[ Upstream commit 897a3e34d6e73d2386715d5c44c57992f2c0eada ] + +flag and mux_flags are intended to keep bit masks. Use u32 type for it. + +Signed-off-by: Claudiu Beznea +Reviewed-by: Geert Uytterhoeven +Link: https://lore.kernel.org/r/20230912045157.177966-15-claudiu.beznea.uj@bp.renesas.com +Signed-off-by: Geert Uytterhoeven +Stable-dep-of: 7f22a298d926 ("clk: renesas: r9a07g043: Fix HP clock source for RZ/Five") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..c9588192d4 --- /dev/null +++ b/queue-6.1/iio-adc-ad7768-1-fix-conversion-result-sign.patch @@ -0,0 +1,55 @@ +From 813242925bc4c99ddf708587e1ef1be2ed17a6f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 6 Mar 2025 18:00:29 -0300 +Subject: iio: adc: ad7768-1: Fix conversion result sign + +From: Sergiu Cuciurean + +[ 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 +Reviewed-by: Marcelo Schmitt +Signed-off-by: Sergiu Cuciurean +Signed-off-by: Jonathan Santos +Cc: +Link: https://patch.msgid.link/505994d3b71c2aa38ba714d909a68e021f12124c.1741268122.git.Jonathan.Santos@analog.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..2bba62f2e9 --- /dev/null +++ b/queue-6.1/iio-adc-ad7768-1-move-setting-of-val-a-bit-later-to-.patch @@ -0,0 +1,47 @@ +From 18dc577a413429deff37736154becbbe38a3102b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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á +Link: https://patch.msgid.link/20250217141630.897334-13-jic23@kernel.org +Signed-off-by: Jonathan Cameron +Stable-dep-of: 8236644f5ecb ("iio: adc: ad7768-1: Fix conversion result sign") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..97ad124696 --- /dev/null +++ b/queue-6.1/memcg-drain-obj-stock-on-cpu-hotplug-teardown.patch @@ -0,0 +1,55 @@ +From 4bf25ac76b51c1ea05eb2dca2dcb3961bf01e1f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 10 Mar 2025 16:09:34 -0700 +Subject: memcg: drain obj stock on cpu hotplug teardown + +From: Shakeel Butt + +[ 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 +Reviewed-by: Roman Gushchin +Acked-by: Johannes Weiner +Cc: Michal Hocko +Cc: Muchun Song +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..6986c793a4 --- /dev/null +++ b/queue-6.1/net-dsa-add-support-for-mac_prepare-and-mac_finish-c.patch @@ -0,0 +1,111 @@ +From d630505f406c50c183756857eeee85b399f99e24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Signed-off-by: Russell King (Oracle) +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Stable-dep-of: 52fdc41c3278 ("net: dsa: mv88e6xxx: fix internal PHYs for 6320 family") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..2e2c5a3c92 --- /dev/null +++ b/queue-6.1/net-dsa-mv88e6xxx-add-field-to-specify-internal-phys.patch @@ -0,0 +1,84 @@ +From c45b4824b3d0a84ed0cba9a94f616d7222461cf3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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é + +[ 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é +Reviewed-by: Andrew Lunn +Signed-off-by: Jakub Kicinski +Stable-dep-of: 52fdc41c3278 ("net: dsa: mv88e6xxx: fix internal PHYs for 6320 family") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..f0380a2975 --- /dev/null +++ b/queue-6.1/net-dsa-mv88e6xxx-don-t-dispose-of-global2-irq-mappi.patch @@ -0,0 +1,136 @@ +From 0fd88096931e6ed7604937a2a41ca29ed663ccf8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Klaus Kudielka +Tested-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Stable-dep-of: 52fdc41c3278 ("net: dsa: mv88e6xxx: fix internal PHYs for 6320 family") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..d6dce14e01 --- /dev/null +++ b/queue-6.1/net-dsa-mv88e6xxx-fix-internal-phys-for-6320-family.patch @@ -0,0 +1,53 @@ +From f87a6a15e67173cabf809b9acef2362d69c84887 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: # 6.6.x +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250317173250.28780-7-kabel@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..f9690bec54 --- /dev/null +++ b/queue-6.1/net-dsa-mv88e6xxx-fix-vtu-methods-for-6320-family.patch @@ -0,0 +1,55 @@ +From a3a84b4abbd6485965b4970c5f50fb5266b5602e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: # 5.15.x +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250317173250.28780-2-kabel@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..64f98413b0 --- /dev/null +++ b/queue-6.1/net-dsa-mv88e6xxx-move-link-forcing-to-mac_prepare-m.patch @@ -0,0 +1,140 @@ +From 490cacb47b8f833bd0d61b21f10e89b8936c3996 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Signed-off-by: Russell King (Oracle) +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Stable-dep-of: 52fdc41c3278 ("net: dsa: mv88e6xxx: fix internal PHYs for 6320 family") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..4590b65552 --- /dev/null +++ b/queue-6.1/net-dsa-mv88e6xxx-pass-directly-chip-structure-to-mv.patch @@ -0,0 +1,75 @@ +From 66d34fcc02e14531bd917455151d24af92d6840c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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é + +[ 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é +Reviewed-by: Russell King (Oracle) +Reviewed-by: Florian Fainelli +Signed-off-by: Jakub Kicinski +Stable-dep-of: 52fdc41c3278 ("net: dsa: mv88e6xxx: fix internal PHYs for 6320 family") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..2916af2ed8 --- /dev/null +++ b/queue-6.1/of-resolver-fix-device-node-refcount-leakage-in-of_r.patch @@ -0,0 +1,45 @@ +From 92adda4d021c532c120dd7f8d6ee84f5c54f7c50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 24 Feb 2025 17:01:55 -0600 +Subject: of: resolver: Fix device node refcount leakage in + of_resolve_phandles() + +From: Zijun Hu + +[ 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 +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) +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..b052c2a697 --- /dev/null +++ b/queue-6.1/of-resolver-simplify-of_resolve_phandles-using-__fre.patch @@ -0,0 +1,114 @@ +From 09a4ac3e5c2002933ffa8e7a9565fca4f203a188 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Feb 2025 20:59:02 +0800 +Subject: of: resolver: Simplify of_resolve_phandles() using __free() + +From: Rob Herring (Arm) + +[ Upstream commit 5275e8b5293f65cc82a5ee5eab02dd573b911d6e ] + +Use the __free() cleanup to simplify of_resolve_phandles() and remove +all the goto's. + +Signed-off-by: Rob Herring (Arm) +Stable-dep-of: a46a0805635d ("of: resolver: Fix device node refcount leakage in of_resolve_phandles()") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..9c0308f472 --- /dev/null +++ b/queue-6.1/pci-assign-pci-domain-ids-by-ida_alloc.patch @@ -0,0 +1,227 @@ +From 46df1ef1c918c5c96ff50e7c7001a2b0103e2e6c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Bjorn Helgaas +Stable-dep-of: 804443c1f278 ("PCI: Fix reference leak in pci_register_host_bridge()") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..15eb9dc4d2 --- /dev/null +++ b/queue-6.1/pci-fix-reference-leak-in-pci_register_host_bridge.patch @@ -0,0 +1,67 @@ +From 86ec43fa14f1e86543d97202cf17c73ba81a3ede Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Feb 2025 10:14:40 +0800 +Subject: PCI: Fix reference leak in pci_register_host_bridge() + +From: Ma Ke + +[ 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 +[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 +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..198e999e16 --- /dev/null +++ b/queue-6.1/phy-freescale-imx8m-pcie-add-i.mx8mp-pcie-phy-suppor.patch @@ -0,0 +1,112 @@ +From c52f5dbbf11277052c51e9ebdfa675b952ea930b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Oct 2022 09:47:02 +0800 +Subject: phy: freescale: imx8m-pcie: Add i.MX8MP PCIe PHY support + +From: Richard Zhu + +[ Upstream commit dce9edff16ee8df20e791e82e0704c4667cc3908 ] + +Add i.MX8MP PCIe PHY support. + +Signed-off-by: Richard Zhu +Signed-off-by: Lucas Stach +Tested-by: Marek Vasut +Tested-by: Richard Leitner +Tested-by: Alexander Stein +Reviewed-by: Lucas Stach +Reviewed-by: Ahmad Fatoum +Link: https://lore.kernel.org/r/1665625622-20551-5-git-send-email-hongxing.zhu@nxp.com +Signed-off-by: Vinod Koul +Stable-dep-of: aecb63e88c5e ("phy: freescale: imx8m-pcie: assert phy reset and perst in power off") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..df03fef576 --- /dev/null +++ b/queue-6.1/phy-freescale-imx8m-pcie-assert-phy-reset-and-perst-.patch @@ -0,0 +1,69 @@ +From cbd6d20afb86c2ac0c2f81ab3cbad45f4be66b13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Frank Li +Link: https://lore.kernel.org/r/20250305144355.20364-3-eichest@gmail.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..3e4d469820 --- /dev/null +++ b/queue-6.1/s390-pci-report-pci-error-recovery-results-via-sclp.patch @@ -0,0 +1,380 @@ +From d254d444ebcd0fc1d68b88dfc8516ff09d26cef5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 13 Dec 2024 14:47:28 +0100 +Subject: s390/pci: Report PCI error recovery results via SCLP + +From: Niklas Schnelle + +[ 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 +Signed-off-by: Niklas Schnelle +Signed-off-by: Alexander Gordeev +Stable-dep-of: aa9f168d55dc ("s390/pci: Support mmap() of PCI resources except for ISM devices") +Signed-off-by: Sasha Levin +--- + 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 + #include +@@ -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 + + #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 ++ * ++ */ ++ ++#define KMSG_COMPONENT "zpci" ++#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt ++ ++#include ++#include ++#include ++ ++#include ++ ++#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 ++ * ++ */ ++#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 index 0000000000..0779680be4 --- /dev/null +++ b/queue-6.1/s390-pci-support-mmap-of-pci-resources-except-for-is.patch @@ -0,0 +1,154 @@ +From fef357f4fd69df1dd912eb0caf083d0ca75a85a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 13:07:47 +0100 +Subject: s390/pci: Support mmap() of PCI resources except for ISM devices + +From: Niklas Schnelle + +[ 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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Sasha Levin +--- + 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 + #include + ++#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 ++ */ ++#include ++ ++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 index 0000000000..212bd0988d --- /dev/null +++ b/queue-6.1/s390-sclp-allow-user-space-to-provide-pci-reports-fo.patch @@ -0,0 +1,44 @@ +From b4978abba91d51e4fb7d5564561dc1c066003825 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Heiko Carstens +Stable-dep-of: aa9f168d55dc ("s390/pci: Support mmap() of PCI resources except for ISM devices") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..7e85945838 --- /dev/null +++ b/queue-6.1/s390-virtio-sort-out-physical-vs-virtual-pointers-us.patch @@ -0,0 +1,209 @@ +From 09b30c7c08325e0ff85e19885726b2274dd33d74 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 29 Jan 2021 12:29:06 +0100 +Subject: s390/virtio: sort out physical vs virtual pointers usage + +From: Alexander Gordeev + +[ Upstream commit 5fc5b94a273655128159186c87662105db8afeb5 ] + +This does not fix a real bug, since virtual addresses +are currently indentical to physical ones. + +Reviewed-by: Nico Boehr +Signed-off-by: Alexander Gordeev +Signed-off-by: Janosch Frank +Stable-dep-of: 2ccd42b959aa ("s390/virtio_ccw: Don't allocate/assign airqs for non-existing queues") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..a56c43ee21 --- /dev/null +++ b/queue-6.1/s390-virtio_ccw-don-t-allocate-assign-airqs-for-non-.patch @@ -0,0 +1,145 @@ +From 3557152649172140e721e26ce539250133ce4a93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: stable@vger.kernel.org +Signed-off-by: David Hildenbrand +Tested-by: Thomas Huth +Reviewed-by: Thomas Huth +Reviewed-by: Cornelia Huck +Acked-by: Michael S. Tsirkin +Acked-by: Christian Borntraeger +Link: https://lore.kernel.org/r/20250402203621.940090-1-david@redhat.com +Signed-off-by: Heiko Carstens +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..a7068e2d45 --- /dev/null +++ b/queue-6.1/s390-virtio_ccw-fix-virtual-vs-physical-address-conf.patch @@ -0,0 +1,320 @@ +From f558381e2515aa14b943fbf184de6ac0c9342887 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Mar 2024 13:28:07 +0100 +Subject: s390/virtio_ccw: fix virtual vs physical address confusion + +From: Halil Pasic + +[ 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 +Reviewed-by: Eric Farman +Signed-off-by: Heiko Carstens +Stable-dep-of: 2ccd42b959aa ("s390/virtio_ccw: Don't allocate/assign airqs for non-existing queues") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..e2ec774907 --- /dev/null +++ b/queue-6.1/selftests-mm-generate-a-temporary-mountpoint-for-cgr.patch @@ -0,0 +1,79 @@ +From 88a3d32994eef02213e8b5a87f193f68a61a4246 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Apr 2025 17:42:32 +0100 +Subject: selftests/mm: generate a temporary mountpoint for cgroup filesystem + +From: Mark Brown + +[ 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 +Cc: Aishwarya TCV +Cc: Mark Brown +Cc: Mina Almasry +Cc: Shuah Khan +Cc: Waiman Long +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/series b/queue-6.1/series index 673df00e1a..a95b12b29f 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -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 index 0000000000..09f6a905a0 --- /dev/null +++ b/queue-6.1/tracing-add-__cpumask-to-denote-a-trace-event-field-.patch @@ -0,0 +1,396 @@ +From 2416a5a01fceafac481754bfeca7f6e3daad2110 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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) + +[ 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 +Reviewed-by: Valentin Schneider +Signed-off-by: Valentin Schneider +Signed-off-by: Steven Rostedt (Google) +Stable-dep-of: ea8d7647f9dd ("tracing: Verify event formats that have "%*p.."") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..f70856c740 --- /dev/null +++ b/queue-6.1/tracing-add-__print_dynamic_array-helper.patch @@ -0,0 +1,94 @@ +From 803bb93aba6416a0ade484d8761cbdb1df01f0d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 22 Oct 2024 19:36:28 +0000 +Subject: tracing: Add __print_dynamic_array() helper + +From: Steven Rostedt + +[ 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) +Signed-off-by: Avadhut Naik +Signed-off-by: Borislav Petkov (AMD) +Reviewed-by: Qiuxu Zhuo +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 +--- + 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 index 0000000000..46c9d61000 --- /dev/null +++ b/queue-6.1/tracing-add-__string_len-example.patch @@ -0,0 +1,63 @@ +From 8c5e7f2c817a1176f2915ad438486f9526c9bf89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 23 Feb 2024 15:28:27 -0500 +Subject: tracing: Add __string_len() example + +From: Steven Rostedt (Google) + +[ 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 +Cc: Mathieu Desnoyers +Signed-off-by: Steven Rostedt (Google) +Stable-dep-of: ea8d7647f9dd ("tracing: Verify event formats that have "%*p.."") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..9fca64e0c6 --- /dev/null +++ b/queue-6.1/tracing-fix-cpumask-example-typo.patch @@ -0,0 +1,44 @@ +From 8d055c06b7fc4a4c5f60acb40ba0a1086e472b62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Dec 2022 22:12:27 -0500 +Subject: tracing: Fix cpumask() example typo + +From: Steven Rostedt (Google) + +[ 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 +Acked-by: Masami Hiramatsu (Google) +Signed-off-by: Steven Rostedt (Google) +Stable-dep-of: ea8d7647f9dd ("tracing: Verify event formats that have "%*p.."") +Signed-off-by: Sasha Levin +--- + 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 index 0000000000..7cb8f0483a --- /dev/null +++ b/queue-6.1/tracing-verify-event-formats-that-have-p.patch @@ -0,0 +1,93 @@ +From c97a31b3618e960efe772ebe96dcbf4366d3a061 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Mar 2025 19:53:11 -0400 +Subject: tracing: Verify event formats that have "%*p.." + +From: Steven Rostedt + +[ 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 +Cc: Mathieu Desnoyers +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 +Reviewed-by: Libo Chen +Tested-by: Libo Chen +Signed-off-by: Steven Rostedt (Google) +Signed-off-by: Sasha Levin +--- + 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 +