ASoC: simple-card: Fix the reference count of device nodes
authorJean-Francois Moine <moinejf@free.fr>
Tue, 11 Mar 2014 09:03:40 +0000 (10:03 +0100)
committerMark Brown <broonie@linaro.org>
Fri, 14 Mar 2014 19:56:55 +0000 (19:56 +0000)
The reference count of some device nodes is not correctly reset
at end of card probe.

Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
Signed-off-by: Mark Brown <broonie@linaro.org>
sound/soc/generic/simple-card.c

index 5dd47691ba417bde6f446ba65b368f4340798d30..dcf37fb69b35abe4341a29798b8d3a3be7f254e7 100644 (file)
@@ -105,12 +105,12 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
        /* get dai->name */
        ret = snd_soc_of_get_dai_name(np, name);
        if (ret < 0)
-               goto parse_error;
+               return ret;
 
        /* parse TDM slot */
        ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width);
        if (ret)
-               goto parse_error;
+               return ret;
 
        /*
         * bitclock-inversion, frame-inversion
@@ -130,7 +130,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
                clk = of_clk_get(np, 0);
                if (IS_ERR(clk)) {
                        ret = PTR_ERR(clk);
-                       goto parse_error;
+                       return ret;
                }
 
                dai->sysclk = clk_get_rate(clk);
@@ -144,12 +144,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
                        dai->sysclk = clk_get_rate(clk);
        }
 
-       ret = 0;
-
-parse_error:
-       of_node_put(node);
-
-       return ret;
+       return 0;
 }
 
 static int asoc_simple_card_parse_of(struct device_node *node,
@@ -187,22 +182,26 @@ static int asoc_simple_card_parse_of(struct device_node *node,
        /* CPU sub-node */
        ret = -EINVAL;
        np = of_get_child_by_name(node, "simple-audio-card,cpu");
-       if (np)
+       if (np) {
                ret = asoc_simple_card_sub_parse_of(np, priv->daifmt,
                                                  &priv->cpu_dai,
                                                  &dai_link->cpu_of_node,
                                                  &dai_link->cpu_dai_name);
+               of_node_put(np);
+       }
        if (ret < 0)
                return ret;
 
        /* CODEC sub-node */
        ret = -EINVAL;
        np = of_get_child_by_name(node, "simple-audio-card,codec");
-       if (np)
+       if (np) {
                ret = asoc_simple_card_sub_parse_of(np, priv->daifmt,
                                                  &priv->codec_dai,
                                                  &dai_link->codec_of_node,
                                                  &dai_link->codec_dai_name);
+               of_node_put(np);
+       }
        if (ret < 0)
                return ret;
 
@@ -248,6 +247,27 @@ static int asoc_simple_card_parse_of(struct device_node *node,
        return 0;
 }
 
+/* update the reference count of the devices nodes at end of probe */
+static int asoc_simple_card_unref(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct snd_soc_dai_link *dai_link;
+       struct device_node *np;
+       int num_links;
+
+       for (num_links = 0, dai_link = card->dai_link;
+            num_links < card->num_links;
+            num_links++, dai_link++) {
+               np = (struct device_node *) dai_link->cpu_of_node;
+               if (np)
+                       of_node_put(np);
+               np = (struct device_node *) dai_link->codec_of_node;
+               if (np)
+                       of_node_put(np);
+       }
+       return 0;
+}
+
 static int asoc_simple_card_probe(struct platform_device *pdev)
 {
        struct simple_card_data *priv;
@@ -275,7 +295,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
                if (ret < 0) {
                        if (ret != -EPROBE_DEFER)
                                dev_err(dev, "parse error %d\n", ret);
-                       return ret;
+                       goto err;
                }
        } else {
                struct asoc_simple_card_info *cinfo;
@@ -318,7 +338,11 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
 
        snd_soc_card_set_drvdata(&priv->snd_card, priv);
 
-       return devm_snd_soc_register_card(&pdev->dev, &priv->snd_card);
+       ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card);
+
+err:
+       asoc_simple_card_unref(pdev);
+       return ret;
 }
 
 static const struct of_device_id asoc_simple_of_match[] = {