ASoC: simple-card: Fix of-node refcount unbalance in DAI-link parser

The function simple_for_each_link() has a few missing places that
forgot unrefereing of-nodes after the use.  The main do-while loop
may abort when loop=0, and this leaves the node object still
referenced.  A similar leak is found in the error handling of NULL
codec that aborts the loop as well.  Last but not least, the inner
for_each_child_of_node() loop may abort in the middle, and this leaks
the refcount of the iterator node.

This patch addresses these missing refcount issues.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Takashi Iwai 2019-02-19 16:46:49 +01:00 committed by Mark Brown
parent 44662f90cd
commit 0b9c9ed6dd
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
1 changed files with 12 additions and 6 deletions

View File

@ -442,6 +442,7 @@ static int simple_for_each_link(struct simple_priv *priv,
struct device_node *top = dev->of_node; struct device_node *top = dev->of_node;
struct device_node *node; struct device_node *node;
bool is_top = 0; bool is_top = 0;
int ret = 0;
/* Check if it has dai-link */ /* Check if it has dai-link */
node = of_get_child_by_name(top, PREFIX "dai-link"); node = of_get_child_by_name(top, PREFIX "dai-link");
@ -456,13 +457,14 @@ static int simple_for_each_link(struct simple_priv *priv,
struct device_node *codec; struct device_node *codec;
struct device_node *np; struct device_node *np;
int num = of_get_child_count(node); int num = of_get_child_count(node);
int ret;
/* get codec */ /* get codec */
codec = of_get_child_by_name(node, is_top ? codec = of_get_child_by_name(node, is_top ?
PREFIX "codec" : "codec"); PREFIX "codec" : "codec");
if (!codec) if (!codec) {
return -ENODEV; ret = -ENODEV;
goto error;
}
of_node_put(codec); of_node_put(codec);
@ -485,14 +487,18 @@ static int simple_for_each_link(struct simple_priv *priv,
else else
ret = func_noml(priv, np, codec, li, is_top); ret = func_noml(priv, np, codec, li, is_top);
if (ret < 0) if (ret < 0) {
return ret; of_node_put(np);
goto error;
}
} }
node = of_get_next_child(top, node); node = of_get_next_child(top, node);
} while (!is_top && node); } while (!is_top && node);
return 0; error:
of_node_put(node);
return ret;
} }
static int simple_parse_aux_devs(struct device_node *node, static int simple_parse_aux_devs(struct device_node *node,