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>
This commit is contained in:
Kery Qi 2026-01-07 23:48:37 +08:00 committed by Mark Brown
parent 2fa0eaf78c
commit 5b577d214f
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0

View File

@ -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;
}