mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-07 23:28:55 +00:00
device property: Fix usecount for of_graph_get_port_parent()
Fix inconsistent use of of_graph_get_port_parent() where asoc_simple_card_parse_graph_dai() does of_node_get() before calling it while other callers do not. We can fix this by not trashing the node passed to of_graph_get_port_parent(). Let's also make sure the callers have correct refcounts and remove related incorrect of_node_put() calls for of_for_each_phandle as that's done by of_phandle_iterator_next() except when we break out of the loop early. Let's fix both issues with a single patch to avoid kobject refcounts getting messed up more if two patches are merged separately. Otherwise strange issues can happen caused by memory corruption caused by too many kobject_del() calls such as: BUG: sleeping function called from invalid context at kernel/locking/mutex.c:747 ... (___might_sleep) (__mutex_lock) (mutex_lock_nested) (kernfs_remove) (kobject_del) (kobject_put) (of_get_next_parent) (of_graph_get_port_parent) (asoc_simple_card_parse_graph_dai [snd_soc_simple_card_utils]) (asoc_graph_card_probe [snd_soc_audio_graph_card]) Fixes:0ef472a973
("of_graph: add of_graph_get_port_parent()") Fixes:2692c1c63c
("ASoC: add audio-graph-card support") Fixes:1689333f83
("ASoC: simple-card-utils: add asoc_simple_card_parse_graph_dai()") Signed-off-by: Tony Lindgren <tony@atomide.com> Reviewed-by: Rob Herring <robh@kernel.org> Tested-by: Antonio Borneo <borneo.antonio@gmail.com> Tested-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
5771a8c088
commit
c0a480d1ac
5 changed files with 34 additions and 18 deletions
|
@ -708,6 +708,15 @@ struct device_node *of_graph_get_port_parent(struct device_node *node)
|
||||||
{
|
{
|
||||||
unsigned int depth;
|
unsigned int depth;
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Preserve usecount for passed in node as of_get_next_parent()
|
||||||
|
* will do of_node_put() on it.
|
||||||
|
*/
|
||||||
|
of_node_get(node);
|
||||||
|
|
||||||
/* Walk 3 levels up only if there is 'ports' node. */
|
/* Walk 3 levels up only if there is 'ports' node. */
|
||||||
for (depth = 3; depth && node; depth--) {
|
for (depth = 3; depth && node; depth--) {
|
||||||
node = of_get_next_parent(node);
|
node = of_get_next_parent(node);
|
||||||
|
@ -728,12 +737,16 @@ EXPORT_SYMBOL(of_graph_get_port_parent);
|
||||||
struct device_node *of_graph_get_remote_port_parent(
|
struct device_node *of_graph_get_remote_port_parent(
|
||||||
const struct device_node *node)
|
const struct device_node *node)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np, *pp;
|
||||||
|
|
||||||
/* Get remote endpoint node. */
|
/* Get remote endpoint node. */
|
||||||
np = of_graph_get_remote_endpoint(node);
|
np = of_graph_get_remote_endpoint(node);
|
||||||
|
|
||||||
return of_graph_get_port_parent(np);
|
pp = of_graph_get_port_parent(np);
|
||||||
|
|
||||||
|
of_node_put(np);
|
||||||
|
|
||||||
|
return pp;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(of_graph_get_remote_port_parent);
|
EXPORT_SYMBOL(of_graph_get_remote_port_parent);
|
||||||
|
|
||||||
|
|
|
@ -224,9 +224,11 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv)
|
||||||
|
|
||||||
of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
|
of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
|
||||||
ret = asoc_graph_card_dai_link_of(it.node, priv, idx++);
|
ret = asoc_graph_card_dai_link_of(it.node, priv, idx++);
|
||||||
of_node_put(it.node);
|
if (ret < 0) {
|
||||||
if (ret < 0)
|
of_node_put(it.node);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return asoc_simple_card_parse_card_name(card, NULL);
|
return asoc_simple_card_parse_card_name(card, NULL);
|
||||||
|
@ -239,10 +241,8 @@ static int asoc_graph_get_dais_count(struct device *dev)
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
of_for_each_phandle(&it, rc, node, "dais", NULL, 0) {
|
of_for_each_phandle(&it, rc, node, "dais", NULL, 0)
|
||||||
count++;
|
count++;
|
||||||
of_node_put(it.node);
|
|
||||||
}
|
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,7 +215,6 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv)
|
||||||
codec_ep = of_graph_get_remote_endpoint(cpu_ep);
|
codec_ep = of_graph_get_remote_endpoint(cpu_ep);
|
||||||
rcpu_ep = of_graph_get_remote_endpoint(codec_ep);
|
rcpu_ep = of_graph_get_remote_endpoint(codec_ep);
|
||||||
|
|
||||||
of_node_put(cpu_port);
|
|
||||||
of_node_put(cpu_ep);
|
of_node_put(cpu_ep);
|
||||||
of_node_put(codec_ep);
|
of_node_put(codec_ep);
|
||||||
of_node_put(rcpu_ep);
|
of_node_put(rcpu_ep);
|
||||||
|
@ -232,8 +231,10 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv)
|
||||||
|
|
||||||
ret = asoc_simple_card_parse_daifmt(dev, cpu_ep, codec_ep,
|
ret = asoc_simple_card_parse_daifmt(dev, cpu_ep, codec_ep,
|
||||||
NULL, &daifmt);
|
NULL, &daifmt);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
|
of_node_put(cpu_port);
|
||||||
goto parse_of_err;
|
goto parse_of_err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dai_idx = 0;
|
dai_idx = 0;
|
||||||
|
@ -250,7 +251,6 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv)
|
||||||
codec_ep = of_graph_get_remote_endpoint(cpu_ep);
|
codec_ep = of_graph_get_remote_endpoint(cpu_ep);
|
||||||
codec_port = of_graph_get_port_parent(codec_ep);
|
codec_port = of_graph_get_port_parent(codec_ep);
|
||||||
|
|
||||||
of_node_put(cpu_port);
|
|
||||||
of_node_put(cpu_ep);
|
of_node_put(cpu_ep);
|
||||||
of_node_put(codec_ep);
|
of_node_put(codec_ep);
|
||||||
of_node_put(codec_port);
|
of_node_put(codec_port);
|
||||||
|
@ -266,13 +266,17 @@ static int asoc_graph_card_parse_of(struct graph_card_data *priv)
|
||||||
|
|
||||||
/* Back-End (= Codec) */
|
/* Back-End (= Codec) */
|
||||||
ret = asoc_graph_card_dai_link_of(codec_ep, priv, daifmt, dai_idx++, 0);
|
ret = asoc_graph_card_dai_link_of(codec_ep, priv, daifmt, dai_idx++, 0);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
|
of_node_put(cpu_port);
|
||||||
goto parse_of_err;
|
goto parse_of_err;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Front-End (= CPU) */
|
/* Front-End (= CPU) */
|
||||||
ret = asoc_graph_card_dai_link_of(cpu_ep, priv, daifmt, dai_idx++, 1);
|
ret = asoc_graph_card_dai_link_of(cpu_ep, priv, daifmt, dai_idx++, 1);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
|
of_node_put(cpu_port);
|
||||||
goto parse_of_err;
|
goto parse_of_err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,7 +310,6 @@ static int asoc_graph_get_dais_count(struct device *dev)
|
||||||
codec_ep = of_graph_get_remote_endpoint(cpu_ep);
|
codec_ep = of_graph_get_remote_endpoint(cpu_ep);
|
||||||
codec_port = of_graph_get_port_parent(codec_ep);
|
codec_port = of_graph_get_port_parent(codec_ep);
|
||||||
|
|
||||||
of_node_put(cpu_port);
|
|
||||||
of_node_put(cpu_ep);
|
of_node_put(cpu_ep);
|
||||||
of_node_put(codec_ep);
|
of_node_put(codec_ep);
|
||||||
of_node_put(codec_port);
|
of_node_put(codec_port);
|
||||||
|
|
|
@ -263,6 +263,9 @@ static int asoc_simple_card_get_dai_id(struct device_node *ep)
|
||||||
id = i;
|
id = i;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
of_node_put(node);
|
||||||
|
|
||||||
if (id < 0)
|
if (id < 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
@ -282,11 +285,6 @@ int asoc_simple_card_parse_graph_dai(struct device_node *ep,
|
||||||
if (!dai_name)
|
if (!dai_name)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* of_graph_get_port_parent() will call
|
|
||||||
* of_node_put(). So, call of_node_get() here
|
|
||||||
*/
|
|
||||||
of_node_get(ep);
|
|
||||||
node = of_graph_get_port_parent(ep);
|
node = of_graph_get_port_parent(ep);
|
||||||
|
|
||||||
/* Get dai->name */
|
/* Get dai->name */
|
||||||
|
|
|
@ -4113,6 +4113,8 @@ int snd_soc_get_dai_id(struct device_node *ep)
|
||||||
}
|
}
|
||||||
mutex_unlock(&client_mutex);
|
mutex_unlock(&client_mutex);
|
||||||
|
|
||||||
|
of_node_put(node);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(snd_soc_get_dai_id);
|
EXPORT_SYMBOL_GPL(snd_soc_get_dai_id);
|
||||||
|
|
Loading…
Add table
Reference in a new issue