The patch below does not apply to the 5.15-stable tree. If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to stable@vger.kernel.org.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y git checkout FETCH_HEAD git cherry-pick -x 312ec2f0d9d1a5656f76d770bbf1d967e9289aa7 # <resolve conflicts, build, test, etc.> git commit -s git send-email --to 'stable@vger.kernel.org' --in-reply-to '2026010531-vendor-unissued-6b5a@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 312ec2f0d9d1a5656f76d770bbf1d967e9289aa7 Mon Sep 17 00:00:00 2001 From: Johan Hovold johan@kernel.org Date: Mon, 24 Nov 2025 11:49:06 +0100 Subject: [PATCH] ASoC: stm32: sai: fix clk prepare imbalance on probe failure
Make sure to unprepare the parent clock also on probe failures (e.g. probe deferral).
Fixes: a14bf98c045b ("ASoC: stm32: sai: fix possible circular locking") Cc: stable@vger.kernel.org # 5.5 Cc: Olivier Moysan olivier.moysan@st.com Signed-off-by: Johan Hovold johan@kernel.org Reviewed-by: olivier moysan olivier.moysan@foss.st.com Link: https://patch.msgid.link/20251124104908.15754-3-johan@kernel.org Signed-off-by: Mark Brown broonie@kernel.org
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 0ae1eae2a59e..7a005b4ad304 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1634,14 +1634,21 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, if (of_property_present(np, "#clock-cells")) { ret = stm32_sai_add_mclk_provider(sai); if (ret < 0) - return ret; + goto err_unprepare_pclk; } else { sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK"); - if (IS_ERR(sai->sai_mclk)) - return PTR_ERR(sai->sai_mclk); + if (IS_ERR(sai->sai_mclk)) { + ret = PTR_ERR(sai->sai_mclk); + goto err_unprepare_pclk; + } }
return 0; + +err_unprepare_pclk: + clk_unprepare(sai->pdata->pclk); + + return ret; }
static int stm32_sai_sub_probe(struct platform_device *pdev) @@ -1688,26 +1695,33 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) IRQF_SHARED, dev_name(&pdev->dev), sai); if (ret) { dev_err(&pdev->dev, "IRQ request returned %d\n", ret); - return ret; + goto err_unprepare_pclk; }
if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) conf = &stm32_sai_pcm_config_spdif;
ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0); - if (ret) - return dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n"); + if (ret) { + ret = dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n"); + goto err_unprepare_pclk; + }
ret = snd_soc_register_component(&pdev->dev, &stm32_component, &sai->cpu_dai_drv, 1); if (ret) { snd_dmaengine_pcm_unregister(&pdev->dev); - return ret; + goto err_unprepare_pclk; }
pm_runtime_enable(&pdev->dev);
return 0; + +err_unprepare_pclk: + clk_unprepare(sai->pdata->pclk); + + return ret; }
static void stm32_sai_sub_remove(struct platform_device *pdev)
From: Kuninori Morimoto kuninori.morimoto.gx@renesas.com
[ Upstream commit efc162cbd480f1fb47d439c193ec9731bcc6c749 ]
Use the dev_err_probe() helper, instead of open-coding the same operation.
Signed-off-by: Kuninori Morimoto kuninori.morimoto.gx@renesas.com Link: https://lore.kernel.org/r/20211214020843.2225831-22-kuninori.morimoto.gx@ren... Signed-off-by: Mark Brown broonie@kernel.org Stable-dep-of: 312ec2f0d9d1 ("ASoC: stm32: sai: fix clk prepare imbalance on probe failure") Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/stm/stm32_i2s.c | 62 ++++++++++++----------------------- sound/soc/stm/stm32_sai.c | 37 ++++++++------------- sound/soc/stm/stm32_sai_sub.c | 25 +++++--------- sound/soc/stm/stm32_spdifrx.c | 44 +++++++++---------------- 4 files changed, 57 insertions(+), 111 deletions(-)
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c index 717f45a83445..08db73c2ed78 100644 --- a/sound/soc/stm/stm32_i2s.c +++ b/sound/soc/stm/stm32_i2s.c @@ -1044,36 +1044,24 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
/* Get clocks */ i2s->pclk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(i2s->pclk)) { - if (PTR_ERR(i2s->pclk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Could not get pclk: %ld\n", - PTR_ERR(i2s->pclk)); - return PTR_ERR(i2s->pclk); - } + if (IS_ERR(i2s->pclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2s->pclk), + "Could not get pclk\n");
i2s->i2sclk = devm_clk_get(&pdev->dev, "i2sclk"); - if (IS_ERR(i2s->i2sclk)) { - if (PTR_ERR(i2s->i2sclk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Could not get i2sclk: %ld\n", - PTR_ERR(i2s->i2sclk)); - return PTR_ERR(i2s->i2sclk); - } + if (IS_ERR(i2s->i2sclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2s->i2sclk), + "Could not get i2sclk\n");
i2s->x8kclk = devm_clk_get(&pdev->dev, "x8k"); - if (IS_ERR(i2s->x8kclk)) { - if (PTR_ERR(i2s->x8kclk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Could not get x8k parent clock: %ld\n", - PTR_ERR(i2s->x8kclk)); - return PTR_ERR(i2s->x8kclk); - } + if (IS_ERR(i2s->x8kclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x8kclk), + "Could not get x8k parent clock\n");
i2s->x11kclk = devm_clk_get(&pdev->dev, "x11k"); - if (IS_ERR(i2s->x11kclk)) { - if (PTR_ERR(i2s->x11kclk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Could not get x11k parent clock: %ld\n", - PTR_ERR(i2s->x11kclk)); - return PTR_ERR(i2s->x11kclk); - } + if (IS_ERR(i2s->x11kclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2s->x11kclk), + "Could not get x11k parent clock\n");
/* Register mclk provider if requested */ if (of_find_property(np, "#clock-cells", NULL)) { @@ -1096,12 +1084,10 @@ static int stm32_i2s_parse_dt(struct platform_device *pdev,
/* Reset */ rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); - if (IS_ERR(rst)) { - if (PTR_ERR(rst) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Reset controller error %ld\n", - PTR_ERR(rst)); - return PTR_ERR(rst); - } + if (IS_ERR(rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(rst), + "Reset controller error\n"); + reset_control_assert(rst); udelay(2); reset_control_deassert(rst); @@ -1143,19 +1129,13 @@ static int stm32_i2s_probe(struct platform_device *pdev)
i2s->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "pclk", i2s->base, i2s->regmap_conf); - if (IS_ERR(i2s->regmap)) { - if (PTR_ERR(i2s->regmap) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Regmap init error %ld\n", - PTR_ERR(i2s->regmap)); - return PTR_ERR(i2s->regmap); - } + if (IS_ERR(i2s->regmap)) + return dev_err_probe(&pdev->dev, PTR_ERR(i2s->regmap), + "Regmap init error\n");
ret = snd_dmaengine_pcm_register(&pdev->dev, &stm32_i2s_pcm_config, 0); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "PCM DMA register error %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "PCM DMA register error\n");
ret = snd_soc_register_component(&pdev->dev, &stm32_i2s_component, i2s->dai_drv, 1); diff --git a/sound/soc/stm/stm32_sai.c b/sound/soc/stm/stm32_sai.c index 058757c721f0..8e21e6f886fc 100644 --- a/sound/soc/stm/stm32_sai.c +++ b/sound/soc/stm/stm32_sai.c @@ -173,29 +173,20 @@ static int stm32_sai_probe(struct platform_device *pdev)
if (!STM_SAI_IS_F4(sai)) { sai->pclk = devm_clk_get(&pdev->dev, "pclk"); - if (IS_ERR(sai->pclk)) { - if (PTR_ERR(sai->pclk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "missing bus clock pclk: %ld\n", - PTR_ERR(sai->pclk)); - return PTR_ERR(sai->pclk); - } + if (IS_ERR(sai->pclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(sai->pclk), + "missing bus clock pclk\n"); }
sai->clk_x8k = devm_clk_get(&pdev->dev, "x8k"); - if (IS_ERR(sai->clk_x8k)) { - if (PTR_ERR(sai->clk_x8k) != -EPROBE_DEFER) - dev_err(&pdev->dev, "missing x8k parent clock: %ld\n", - PTR_ERR(sai->clk_x8k)); - return PTR_ERR(sai->clk_x8k); - } + if (IS_ERR(sai->clk_x8k)) + return dev_err_probe(&pdev->dev, PTR_ERR(sai->clk_x8k), + "missing x8k parent clock\n");
sai->clk_x11k = devm_clk_get(&pdev->dev, "x11k"); - if (IS_ERR(sai->clk_x11k)) { - if (PTR_ERR(sai->clk_x11k) != -EPROBE_DEFER) - dev_err(&pdev->dev, "missing x11k parent clock: %ld\n", - PTR_ERR(sai->clk_x11k)); - return PTR_ERR(sai->clk_x11k); - } + if (IS_ERR(sai->clk_x11k)) + return dev_err_probe(&pdev->dev, PTR_ERR(sai->clk_x11k), + "missing x11k parent clock\n");
/* init irqs */ sai->irq = platform_get_irq(pdev, 0); @@ -204,12 +195,10 @@ static int stm32_sai_probe(struct platform_device *pdev)
/* reset */ rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); - if (IS_ERR(rst)) { - if (PTR_ERR(rst) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Reset controller error %ld\n", - PTR_ERR(rst)); - return PTR_ERR(rst); - } + if (IS_ERR(rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(rst), + "Reset controller error\n"); + reset_control_assert(rst); udelay(2); reset_control_deassert(rst); diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index d71b4aecd269..0db307cdb825 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1379,12 +1379,9 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, */ sai->regmap = devm_regmap_init_mmio(&pdev->dev, base, sai->regmap_config); - if (IS_ERR(sai->regmap)) { - if (PTR_ERR(sai->regmap) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Regmap init error %ld\n", - PTR_ERR(sai->regmap)); - return PTR_ERR(sai->regmap); - } + if (IS_ERR(sai->regmap)) + return dev_err_probe(&pdev->dev, PTR_ERR(sai->regmap), + "Regmap init error\n");
/* Get direction property */ if (of_property_match_string(np, "dma-names", "tx") >= 0) { @@ -1472,12 +1469,9 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,
of_node_put(args.np); sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck"); - if (IS_ERR(sai->sai_ck)) { - if (PTR_ERR(sai->sai_ck) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Missing kernel clock sai_ck: %ld\n", - PTR_ERR(sai->sai_ck)); - return PTR_ERR(sai->sai_ck); - } + if (IS_ERR(sai->sai_ck)) + return dev_err_probe(&pdev->dev, PTR_ERR(sai->sai_ck), + "Missing kernel clock sai_ck\n");
ret = clk_prepare(sai->pdata->pclk); if (ret < 0) @@ -1551,11 +1545,8 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) conf = &stm32_sai_pcm_config_spdif;
ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "Could not register pcm dma\n"); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n");
ret = snd_soc_register_component(&pdev->dev, &stm32_component, &sai->cpu_dai_drv, 1); diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c index e3d6258afbac..80f7761cbcb7 100644 --- a/sound/soc/stm/stm32_spdifrx.c +++ b/sound/soc/stm/stm32_spdifrx.c @@ -405,12 +405,9 @@ static int stm32_spdifrx_dma_ctrl_register(struct device *dev, int ret;
spdifrx->ctrl_chan = dma_request_chan(dev, "rx-ctrl"); - if (IS_ERR(spdifrx->ctrl_chan)) { - if (PTR_ERR(spdifrx->ctrl_chan) != -EPROBE_DEFER) - dev_err(dev, "dma_request_slave_channel error %ld\n", - PTR_ERR(spdifrx->ctrl_chan)); - return PTR_ERR(spdifrx->ctrl_chan); - } + if (IS_ERR(spdifrx->ctrl_chan)) + return dev_err_probe(dev, PTR_ERR(spdifrx->ctrl_chan), + "dma_request_slave_channel error\n");
spdifrx->dmab = devm_kzalloc(dev, sizeof(struct snd_dma_buffer), GFP_KERNEL); @@ -929,12 +926,9 @@ static int stm32_spdifrx_parse_of(struct platform_device *pdev, spdifrx->phys_addr = res->start;
spdifrx->kclk = devm_clk_get(&pdev->dev, "kclk"); - if (IS_ERR(spdifrx->kclk)) { - if (PTR_ERR(spdifrx->kclk) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Could not get kclk: %ld\n", - PTR_ERR(spdifrx->kclk)); - return PTR_ERR(spdifrx->kclk); - } + if (IS_ERR(spdifrx->kclk)) + return dev_err_probe(&pdev->dev, PTR_ERR(spdifrx->kclk), + "Could not get kclk\n");
spdifrx->irq = platform_get_irq(pdev, 0); if (spdifrx->irq < 0) @@ -985,12 +979,9 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) spdifrx->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "kclk", spdifrx->base, spdifrx->regmap_conf); - if (IS_ERR(spdifrx->regmap)) { - if (PTR_ERR(spdifrx->regmap) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Regmap init error %ld\n", - PTR_ERR(spdifrx->regmap)); - return PTR_ERR(spdifrx->regmap); - } + if (IS_ERR(spdifrx->regmap)) + return dev_err_probe(&pdev->dev, PTR_ERR(spdifrx->regmap), + "Regmap init error\n");
ret = devm_request_irq(&pdev->dev, spdifrx->irq, stm32_spdifrx_isr, 0, dev_name(&pdev->dev), spdifrx); @@ -1000,23 +991,18 @@ static int stm32_spdifrx_probe(struct platform_device *pdev) }
rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); - if (IS_ERR(rst)) { - if (PTR_ERR(rst) != -EPROBE_DEFER) - dev_err(&pdev->dev, "Reset controller error %ld\n", - PTR_ERR(rst)); - return PTR_ERR(rst); - } + if (IS_ERR(rst)) + return dev_err_probe(&pdev->dev, PTR_ERR(rst), + "Reset controller error\n"); + reset_control_assert(rst); udelay(2); reset_control_deassert(rst);
pcm_config = &stm32_spdifrx_pcm_config; ret = snd_dmaengine_pcm_register(&pdev->dev, pcm_config, 0); - if (ret) { - if (ret != -EPROBE_DEFER) - dev_err(&pdev->dev, "PCM DMA register error %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(&pdev->dev, ret, "PCM DMA register error\n");
ret = snd_soc_register_component(&pdev->dev, &stm32_spdifrx_component,
From: Christophe JAILLET christophe.jaillet@wanadoo.fr
[ Upstream commit 374628fb668e50b42fe81f2a63af616182415bcd ]
Use devm_clk_get_optional() instead of hand writing it. This saves some LoC and improves the semantic.
Signed-off-by: Christophe JAILLET christophe.jaillet@wanadoo.fr Link: https://lore.kernel.org/r/f7987f18dadf77bfa09969fd4c82d5a0f4e4e3b7.168459483... Signed-off-by: Mark Brown broonie@kernel.org Stable-dep-of: 312ec2f0d9d1 ("ASoC: stm32: sai: fix clk prepare imbalance on probe failure") Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/stm/stm32_sai_sub.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 0db307cdb825..15f8322d2e43 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1486,12 +1486,9 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, if (ret < 0) return ret; } else { - sai->sai_mclk = devm_clk_get(&pdev->dev, "MCLK"); - if (IS_ERR(sai->sai_mclk)) { - if (PTR_ERR(sai->sai_mclk) != -ENOENT) - return PTR_ERR(sai->sai_mclk); - sai->sai_mclk = NULL; - } + sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK"); + if (IS_ERR(sai->sai_mclk)) + return PTR_ERR(sai->sai_mclk); }
return 0;
From: Johan Hovold johan@kernel.org
[ Upstream commit 312ec2f0d9d1a5656f76d770bbf1d967e9289aa7 ]
Make sure to unprepare the parent clock also on probe failures (e.g. probe deferral).
Fixes: a14bf98c045b ("ASoC: stm32: sai: fix possible circular locking") Cc: stable@vger.kernel.org # 5.5 Cc: Olivier Moysan olivier.moysan@st.com Signed-off-by: Johan Hovold johan@kernel.org Reviewed-by: olivier moysan olivier.moysan@foss.st.com Link: https://patch.msgid.link/20251124104908.15754-3-johan@kernel.org Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- sound/soc/stm/stm32_sai_sub.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 15f8322d2e43..2a2fc2f0ebbd 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -1484,14 +1484,21 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, if (of_find_property(np, "#clock-cells", NULL)) { ret = stm32_sai_add_mclk_provider(sai); if (ret < 0) - return ret; + goto err_unprepare_pclk; } else { sai->sai_mclk = devm_clk_get_optional(&pdev->dev, "MCLK"); - if (IS_ERR(sai->sai_mclk)) - return PTR_ERR(sai->sai_mclk); + if (IS_ERR(sai->sai_mclk)) { + ret = PTR_ERR(sai->sai_mclk); + goto err_unprepare_pclk; + } }
return 0; + +err_unprepare_pclk: + clk_unprepare(sai->pdata->pclk); + + return ret; }
static int stm32_sai_sub_probe(struct platform_device *pdev) @@ -1535,26 +1542,33 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) IRQF_SHARED, dev_name(&pdev->dev), sai); if (ret) { dev_err(&pdev->dev, "IRQ request returned %d\n", ret); - return ret; + goto err_unprepare_pclk; }
if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) conf = &stm32_sai_pcm_config_spdif;
ret = snd_dmaengine_pcm_register(&pdev->dev, conf, 0); - if (ret) - return dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n"); + if (ret) { + ret = dev_err_probe(&pdev->dev, ret, "Could not register pcm dma\n"); + goto err_unprepare_pclk; + }
ret = snd_soc_register_component(&pdev->dev, &stm32_component, &sai->cpu_dai_drv, 1); if (ret) { snd_dmaengine_pcm_unregister(&pdev->dev); - return ret; + goto err_unprepare_pclk; }
pm_runtime_enable(&pdev->dev);
return 0; + +err_unprepare_pclk: + clk_unprepare(sai->pdata->pclk); + + return ret; }
static int stm32_sai_sub_remove(struct platform_device *pdev)
linux-stable-mirror@lists.linaro.org