]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
ASoC: davinci-evm: Fix reference leak in davinci_evm_probe
authorKery Qi <qikeyu2017@gmail.com>
Wed, 7 Jan 2026 15:48:37 +0000 (23:48 +0800)
committerMark Brown <broonie@kernel.org>
Thu, 8 Jan 2026 17:31:15 +0000 (17:31 +0000)
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>
sound/soc/ti/davinci-evm.c

index 3848766d96c3e33b10d7d79eb06e82be3c228ee0..ad514c2e5a254c93d1243fc5e78f4908ff542fa8 100644 (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;
 }