ASoC: stm32: sai: fix device and OF node leaks on probe
Subsystems (5)
cover ASoC: stm32: sai: fix device and OF node leaks on probe
This series fixes device and OF node reference leaks during probe and a clock prepare imbalance on probe failures.
Included is a related cleanup of an error path.
Johan
Johan Hovold (4):
ASoC: stm32: sai: fix device leak on probe
ASoC: stm32: sai: fix clk prepare imbalance on probe failure
ASoC: stm32: sai: fix OF node leak on probe
ASoC: stm32: sai: clean up probe error path
sound/soc/stm/stm32_sai.c | 14 +++------ sound/soc/stm/stm32_sai_sub.c | 57 ++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 27 deletions(-)
Signature · 1 line
2.51.2
PATCH 1/4 ASoC: stm32: sai: fix device leak on probe
Make sure to drop the reference taken when looking up the sync provider device and its driver data during DAI probe on probe failures and on unbind.
Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.
--- sound/soc/stm/stm32_sai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/stm/stm32_sai.c +1 -1
@@ -143,6 +143,7 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client, } sai_provider =platform_get_drvdata (pdev); +put_device (&pdev->dev);if (!sai_provider) {dev_err (&sai_client->pdev->dev,"SAI sync provider data not found\n" );
@@ -159,7 +160,6 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client, ret =stm32_sai_sync_conf_provider (sai_provider, synco); error: -put_device (&pdev->dev);of_node_put (np_provider);return ret; }
Signature · 1 line
2.51.2
Re: [PATCH 1/4] ASoC: stm32: sai: fix device leak on probe
Hi Johan,
Thanks for your fixes.
Quoted 7 lines · Johan Hovold
Make sure to drop the reference taken when looking up the sync provider device and its driver data during DAI probe on probe failures and on unbind.
Note that holding a reference to a device does not prevent its driver data from going away so there is no point in keeping the reference.
Quoted 6 lines
Fixes 7dd0d835582f ("ASoC: stm32: sai: simplify sync modes management")Fixes 1c3816a19487 ("ASoC: stm32: sai: add missing put_device()")Cc [email protected] # 4.16: 1c3816a19487Cc olivier moysan <[email protected]>Cc Wen Yang <[email protected]>Signed-off-by Johan Hovold <[email protected]>
Quoted 24 lines
--- sound/soc/stm/stm32_sai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)sound/soc/stm/stm32_sai.c +1
-1@@ -143,6 +143,7 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client, } sai_provider =platform_get_drvdata (pdev); +put_device (&pdev->dev);if (!sai_provider) {dev_err (&sai_client->pdev->dev,"SAI sync provider data not found\n" );@@ -159,7 +160,6 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client, ret =stm32_sai_sync_conf_provider (sai_provider, synco); error: -put_device (&pdev->dev);of_node_put (np_provider);return ret; }
PATCH 2/4 ASoC: stm32: sai: fix clk prepare imbalance on probe failure
In reply to Johan HovoldMake sure to unprepare the parent clock also on probe failures (e.g. probe deferral).
--- sound/soc/stm/stm32_sai_sub.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)
sound/soc/stm/stm32_sai_sub.c +21 -7
@@ -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)
Signature · 1 line
2.51.2
Re: [PATCH 2/4] ASoC: stm32: sai: fix clk prepare imbalance on probe failure
Quoted 7 lines · Johan Hovold
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 [email protected] # 5.5Cc Olivier Moysan <[email protected]>Signed-off-by Johan Hovold <[email protected]>
Olivier
Quoted 71 lines
--- sound/soc/stm/stm32_sai_sub.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-)sound/soc/stm/stm32_sai_sub.c +21
-7@@ -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)
PATCH 3/4 ASoC: stm32: sai: fix OF node leak on probe
In reply to Johan HovoldThe reference taken to the sync provider OF node when probing the platform device is currently only dropped if the set_sync() callback fails during DAI probe.
Make sure to drop the reference on platform probe failures (e.g. probe deferral) and on driver unbind.
This also avoids a potential use-after-free in case the DAI is ever reprobed without first rebinding the platform driver.
--- sound/soc/stm/stm32_sai.c | 12 +++--------- sound/soc/stm/stm32_sai_sub.c | 23 ++++++++++++++++------- 2 files changed, 19 insertions(+), 16 deletions(-)
sound/soc/stm/stm32_sai.c +3 -9
@@ -138,7 +138,6 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client,if (!pdev) {dev_err (&sai_client->pdev->dev,"Device not found for node %pOFn\n" , np_provider); -of_node_put (np_provider);return -ENODEV ; }
@@ -147,21 +146,16 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client,if (!sai_provider) {dev_err (&sai_client->pdev->dev,"SAI sync provider data not found\n" ); - ret = -EINVAL ; - goto error; +return -EINVAL ; }/* Configure sync client */ ret =stm32_sai_sync_conf_client (sai_client, synci);if (ret <0 ) - goto error; +return ret;/* Configure sync provider */ - ret =stm32_sai_sync_conf_provider (sai_provider, synco); - -error: -of_node_put (np_provider); -return ret; +return stm32_sai_sync_conf_provider (sai_provider, synco); }static int stm32_sai_get_parent_clk (struct stm32_sai_data *sai)
sound/soc/stm/stm32_sai_sub.c +16 -7
@@ -1586,7 +1586,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,dev_err (&pdev->dev,"External synchro not supported\n" );of_node_put (args.np); -return -EINVAL ; + ret = -EINVAL ; + goto err_put_sync_provider; } sai->sync =SAI_SYNC_EXTERNAL ;
@@ -1595,7 +1596,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, (sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) {dev_err (&pdev->dev,"Wrong SAI index\n" );of_node_put (args.np); -return -EINVAL ; + ret = -EINVAL ; + goto err_put_sync_provider; } if (of_property_match_string(args.np, "compatible",
@@ -1609,7 +1611,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,if (!sai->synco) {dev_err (&pdev->dev,"Unknown SAI sub-block\n" );of_node_put (args.np); -return -EINVAL ; + ret = -EINVAL ; + goto err_put_sync_provider; } }
@@ -1619,13 +1622,15 @@ 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)) -return dev_err_probe (&pdev->dev,PTR_ERR (sai->sai_ck), -"Missing kernel clock sai_ck\n" ); +if (IS_ERR (sai->sai_ck)) { + ret =dev_err_probe (&pdev->dev,PTR_ERR (sai->sai_ck), +"Missing kernel clock sai_ck\n" ); + goto err_put_sync_provider; + } ret =clk_prepare (sai->pdata->pclk);if (ret <0 ) -return ret; + goto err_put_sync_provider;if (STM_SAI_IS_F4 (sai->pdata))return 0 ;
@@ -1647,6 +1652,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, err_unprepare_pclk:clk_unprepare (sai->pdata->pclk); +err_put_sync_provider: +of_node_put (sai->np_sync_provider);return ret; }
@@ -1720,6 +1727,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) err_unprepare_pclk:clk_unprepare (sai->pdata->pclk); +of_node_put (sai->np_sync_provider);return ret; }
@@ -1732,6 +1740,7 @@ static void stm32_sai_sub_remove(struct platform_device *pdev)snd_dmaengine_pcm_unregister (&pdev->dev);snd_soc_unregister_component (&pdev->dev);pm_runtime_disable (&pdev->dev); +of_node_put (sai->np_sync_provider); }static int stm32_sai_sub_suspend (struct device *dev)
Signature · 1 line
2.51.2
Re: [PATCH 3/4] ASoC: stm32: sai: fix OF node leak on probe
Quoted 7 lines · Johan Hovold
The reference taken to the sync provider OF node when probing the platform device is currently only dropped if the
set_sync()callback fails during DAI probe.Make sure to drop the reference on platform probe failures (e.g. probe deferral) and on driver unbind.
Quoted 6 lines
This also avoids a potential use-after-free in case the DAI is ever reprobed without first rebinding the platform driver.
Fixes 5914d285f6b7 ("ASoC: stm32: sai: Add synchronization support")Fixes d4180b4c02e7 ("ASoC: stm32: sai: fix set_sync service")Cc Olivier Moysan <[email protected]>
Olivier
Quoted 123 lines
Cc [email protected] # 4.16: d4180b4c02e7Signed-off-by Johan Hovold <[email protected]>--- sound/soc/stm/stm32_sai.c | 12 +++--------- sound/soc/stm/stm32_sai_sub.c | 23 ++++++++++++++++------- 2 files changed, 19 insertions(+), 16 deletions(-)sound/soc/stm/stm32_sai.c +3
-9@@ -138,7 +138,6 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client,if (!pdev) {dev_err (&sai_client->pdev->dev,"Device not found for node %pOFn\n" , np_provider); -of_node_put (np_provider);return -ENODEV ; }@@ -147,21 +146,16 @@ static int stm32_sai_set_sync(struct stm32_sai_data *sai_client,if (!sai_provider) {dev_err (&sai_client->pdev->dev,"SAI sync provider data not found\n" ); - ret = -EINVAL ; - goto error; +return -EINVAL ; }/* Configure sync client */ ret =stm32_sai_sync_conf_client (sai_client, synci);if (ret <0 ) - goto error; +return ret;/* Configure sync provider */ - ret =stm32_sai_sync_conf_provider (sai_provider, synco); - -error: -of_node_put (np_provider); -return ret; +return stm32_sai_sync_conf_provider (sai_provider, synco); }static int stm32_sai_get_parent_clk (struct stm32_sai_data *sai)sound/soc/stm/stm32_sai_sub.c +16
-7@@ -1586,7 +1586,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,dev_err (&pdev->dev,"External synchro not supported\n" );of_node_put (args.np); -return -EINVAL ; + ret = -EINVAL ; + goto err_put_sync_provider; } sai->sync =SAI_SYNC_EXTERNAL ;@@ -1595,7 +1596,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, (sai->synci > (SAI_GCR_SYNCIN_MAX + 1))) {dev_err (&pdev->dev,"Wrong SAI index\n" );of_node_put (args.np); -return -EINVAL ; + ret = -EINVAL ; + goto err_put_sync_provider; } if (of_property_match_string(args.np, "compatible",@@ -1609,7 +1611,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev,if (!sai->synco) {dev_err (&pdev->dev,"Unknown SAI sub-block\n" );of_node_put (args.np); -return -EINVAL ; + ret = -EINVAL ; + goto err_put_sync_provider; } }@@ -1619,13 +1622,15 @@ 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)) -return dev_err_probe (&pdev->dev,PTR_ERR (sai->sai_ck), -"Missing kernel clock sai_ck\n" ); +if (IS_ERR (sai->sai_ck)) { + ret =dev_err_probe (&pdev->dev,PTR_ERR (sai->sai_ck), +"Missing kernel clock sai_ck\n" ); + goto err_put_sync_provider; + } ret =clk_prepare (sai->pdata->pclk);if (ret <0 ) -return ret; + goto err_put_sync_provider;if (STM_SAI_IS_F4 (sai->pdata))return 0 ;@@ -1647,6 +1652,8 @@ static int stm32_sai_sub_parse_of(struct platform_device *pdev, err_unprepare_pclk:clk_unprepare (sai->pdata->pclk); +err_put_sync_provider: +of_node_put (sai->np_sync_provider);return ret; }@@ -1720,6 +1727,7 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) err_unprepare_pclk:clk_unprepare (sai->pdata->pclk); +of_node_put (sai->np_sync_provider);return ret; }@@ -1732,6 +1740,7 @@ static void stm32_sai_sub_remove(struct platform_device *pdev)snd_dmaengine_pcm_unregister (&pdev->dev);snd_soc_unregister_component (&pdev->dev);pm_runtime_disable (&pdev->dev); +of_node_put (sai->np_sync_provider); }static int stm32_sai_sub_suspend (struct device *dev)
PATCH 4/4 ASoC: stm32: sai: clean up probe error path
In reply to Johan HovoldUse an error label for deregistering also the PCM DMA for consistency.
--- sound/soc/stm/stm32_sai_sub.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
sound/soc/stm/stm32_sai_sub.c +4 -4
@@ -1716,15 +1716,15 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) ret =snd_soc_register_component (&pdev->dev, &stm32_component, &sai->cpu_dai_drv,1 ); -if (ret) { -snd_dmaengine_pcm_unregister (&pdev->dev); - goto err_unprepare_pclk; - } +if (ret) + goto err_deregister_pcm_dma;pm_runtime_enable (&pdev->dev);return 0 ; +err_deregister_pcm_dma: +snd_dmaengine_pcm_unregister (&pdev->dev); err_unprepare_pclk:clk_unprepare (sai->pdata->pclk);of_node_put (sai->np_sync_provider);
Signature · 1 line
2.51.2
Re: [PATCH 4/4] ASoC: stm32: sai: clean up probe error path
Quoted 3 lines · Johan Hovold
Use an error label for deregistering also the PCM DMA for consistency.
Signed-off-by Johan Hovold <[email protected]>
Olivier
Quoted 28 lines
--- sound/soc/stm/stm32_sai_sub.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)sound/soc/stm/stm32_sai_sub.c +4
-4@@ -1716,15 +1716,15 @@ static int stm32_sai_sub_probe(struct platform_device *pdev) ret =snd_soc_register_component (&pdev->dev, &stm32_component, &sai->cpu_dai_drv,1 ); -if (ret) { -snd_dmaengine_pcm_unregister (&pdev->dev); - goto err_unprepare_pclk; - } +if (ret) + goto err_deregister_pcm_dma;pm_runtime_enable (&pdev->dev);return 0 ; +err_deregister_pcm_dma: +snd_dmaengine_pcm_unregister (&pdev->dev); err_unprepare_pclk:clk_unprepare (sai->pdata->pclk);of_node_put (sai->np_sync_provider);
Mark Brown
maintainerQuoted 8 lines · Johan Hovold
This series fixes device and OF node reference leaks during probe and a clock prepare imbalance on probe failures.
Included is a related cleanup of an error path.
Johan
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
Thanks!
[1/4] ASoC: stm32: sai: fix device leak on probe
commit: e26ff429eaf10c4ef1bc3dabd9bf27eb54b7e1f4
[2/4] ASoC: stm32: sai: fix clk prepare imbalance on probe failure
commit: 312ec2f0d9d1a5656f76d770bbf1d967e9289aa7
[3/4] ASoC: stm32: sai: fix OF node leak on probe
commit: 23261f0de09427367e99f39f588e31e2856a690e
[4/4] ASoC: stm32: sai: clean up probe error path
commit: 3a03de362975398b39d4c6df7325ccb982026a8fAll being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks,
Mark
Hello Mark,
2025. 11. 25. 20:22 keltezéssel, Mark Brown írta:
Quoted 6 lines · Johan Hovold
Quoted 5 lines
This series fixes device and OF node reference leaks during probe and a clock prepare imbalance on probe failures.
Included is a related cleanup of an error path.
Quoted 7 lines
Quoted 3 lines
Johan
[...]
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next
It seems that the SPI tree is not the correct place for this series.
Regards,
Gabor