summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKery Qi <qikeyu2017@gmail.com>2026-01-07 18:48:37 +0300
committerMark Brown <broonie@kernel.org>2026-01-08 20:31:15 +0300
commit5b577d214fcc109707bcb77b4ae72a31cfd86798 (patch)
tree3748c9b48b8a6a505b800744f2c45c6d1c650503
parent2fa0eaf78c4bb24c2b05a4db3e0d86a7dcd8fd9f (diff)
downloadlinux-5b577d214fcc109707bcb77b4ae72a31cfd86798.tar.xz
ASoC: davinci-evm: Fix reference leak in davinci_evm_probe
The davinci_evm_probe() function calls of_parse_phandle() to acquire device nodes for "ti,audio-codec" and "ti,mcasp-controller". These functions return device nodes with incremented reference counts. However, in several error paths (e.g., when the second of_parse_phandle(), snd_soc_of_parse_card_name(), or devm_snd_soc_register_card() fails), the function returns directly without releasing the acquired nodes, leading to reference leaks. This patch adds an error handling path 'err_put' to properly release the device nodes using of_node_put() and clean up the pointers when an error occurs. Signed-off-by: Kery Qi <qikeyu2017@gmail.com> Link: https://patch.msgid.link/20260107154836.1521-2-qikeyu2017@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/ti/davinci-evm.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/sound/soc/ti/davinci-evm.c b/sound/soc/ti/davinci-evm.c
index 3848766d96c3..ad514c2e5a25 100644
--- a/sound/soc/ti/davinci-evm.c
+++ b/sound/soc/ti/davinci-evm.c
@@ -194,27 +194,32 @@ static int davinci_evm_probe(struct platform_device *pdev)
return -EINVAL;
dai->cpus->of_node = of_parse_phandle(np, "ti,mcasp-controller", 0);
- if (!dai->cpus->of_node)
- return -EINVAL;
+ if (!dai->cpus->of_node) {
+ ret = -EINVAL;
+ goto err_put;
+ }
dai->platforms->of_node = dai->cpus->of_node;
evm_soc_card.dev = &pdev->dev;
ret = snd_soc_of_parse_card_name(&evm_soc_card, "ti,model");
if (ret)
- return ret;
+ goto err_put;
mclk = devm_clk_get(&pdev->dev, "mclk");
if (PTR_ERR(mclk) == -EPROBE_DEFER) {
- return -EPROBE_DEFER;
+ ret = -EPROBE_DEFER;
+ goto err_put;
} else if (IS_ERR(mclk)) {
dev_dbg(&pdev->dev, "mclk not found.\n");
mclk = NULL;
}
drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
- if (!drvdata)
- return -ENOMEM;
+ if (!drvdata) {
+ ret = -ENOMEM;
+ goto err_put;
+ }
drvdata->mclk = mclk;
@@ -224,7 +229,8 @@ static int davinci_evm_probe(struct platform_device *pdev)
if (!drvdata->mclk) {
dev_err(&pdev->dev,
"No clock or clock rate defined.\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto err_put;
}
drvdata->sysclk = clk_get_rate(drvdata->mclk);
} else if (drvdata->mclk) {
@@ -240,8 +246,25 @@ static int davinci_evm_probe(struct platform_device *pdev)
snd_soc_card_set_drvdata(&evm_soc_card, drvdata);
ret = devm_snd_soc_register_card(&pdev->dev, &evm_soc_card);
- if (ret)
+ if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+ goto err_put;
+ }
+
+ return ret;
+
+err_put:
+ dai->platforms->of_node = NULL;
+
+ if (dai->cpus->of_node) {
+ of_node_put(dai->cpus->of_node);
+ dai->cpus->of_node = NULL;
+ }
+
+ if (dai->codecs->of_node) {
+ of_node_put(dai->codecs->of_node);
+ dai->codecs->of_node = NULL;
+ }
return ret;
}