ASoC: qcom: Fix of-node refcount unbalance in apq8016_sbc_parse_of() [Linux 5.1]

ASoC: qcom: Fix of-node refcount unbalance in apq8016_sbc_parse_of() [Linux 5.1]

This Linux kernel change "ASoC: qcom: Fix of-node refcount unbalance in apq8016_sbc_parse_of()" is included in the Linux 5.1 release. This change is authored by Takashi Iwai <tiwai [at] suse.de> on Tue Feb 19 16:46:50 2019 +0100. The commit for this change in Linux stable tree is 8d16672 (patch).

ASoC: qcom: Fix of-node refcount unbalance in apq8016_sbc_parse_of()

The apq8016 driver leaves the of-node refcount at aborting from the
loop of for_each_child_of_node() in the error path.  Not only the
iterator node of for_each_child_of_node(), the children nodes referred
from it for codec and cpu have to be properly unreferenced.

Fixes: bdb052e81f62 ("ASoC: qcom: add apq8016 sound card support")
Cc: Patrick Lai <plai@codeaurora.org>
Cc: Banajit Goswami <bgoswami@codeaurora.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Mark Brown <broonie@kernel.org>

There are 21 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 sound/soc/qcom/apq8016_sbc.c | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c
index 1dd23bb..4b55993 100644
--- a/sound/soc/qcom/apq8016_sbc.c
+++ b/sound/soc/qcom/apq8016_sbc.c
@@ -164,41 +164,52 @@ static struct apq8016_sbc_data *apq8016_sbc_parse_of(struct snd_soc_card *card)

        if (!cpu || !codec) {
            dev_err(dev, "Can't find cpu/codec DT node\n");
-           return ERR_PTR(-EINVAL);
+           ret = -EINVAL;
+           goto error;
        }

        link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0);
        if (!link->cpu_of_node) {
            dev_err(card->dev, "error getting cpu phandle\n");
-           return ERR_PTR(-EINVAL);
+           ret = -EINVAL;
+           goto error;
        }

        ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name);
        if (ret) {
            dev_err(card->dev, "error getting cpu dai name\n");
-           return ERR_PTR(ret);
+           goto error;
        }

        ret = snd_soc_of_get_dai_link_codecs(dev, codec, link);

        if (ret < 0) {
            dev_err(card->dev, "error getting codec dai name\n");
-           return ERR_PTR(ret);
+           goto error;
        }

        link->platform_of_node = link->cpu_of_node;
        ret = of_property_read_string(np, "link-name", &link->name);
        if (ret) {
            dev_err(card->dev, "error getting codec dai_link name\n");
-           return ERR_PTR(ret);
+           goto error;
        }

        link->stream_name = link->name;
        link->init = apq8016_sbc_dai_init;
        link++;
+
+       of_node_put(cpu);
+       of_node_put(codec);
    }

    return data;
+
+ error:
+   of_node_put(np);
+   of_node_put(cpu);
+   of_node_put(codec);
+   return ERR_PTR(ret);
 }

 static const struct snd_soc_dapm_widget apq8016_sbc_dapm_widgets[] = {

Leave a Reply

Your email address will not be published. Required fields are marked *