Commit ec1af6c6 authored by Thierry Reding's avatar Thierry Reding Committed by Mark Brown

ASoC: simple-card-utils: Allocate link info structure on heap

struct link_info can grow fairly large and may cause the stack frame
size to be exceeded when allocated on the stack. Some architectures
such as 32-bit ARM, RISC-V or PowerPC have small stack frames where
this causes a compiler warning, so allocate these structures on the
heap instead of the stack.

Fixes: 343e55e7 ("ASoC: simple-card-utils: Increase maximum number of links to 128")
Reported-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reported-by: default avatarStephen Rothwell <sfr@canb.auug.org.au>
Reported-by: default avatarkernel test robot <lkp@intel.com>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
Acked-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/20210419164117.1422242-1-thierry.reding@gmail.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 7f51384f
...@@ -548,21 +548,24 @@ static int graph_get_dais_count(struct asoc_simple_priv *priv, ...@@ -548,21 +548,24 @@ static int graph_get_dais_count(struct asoc_simple_priv *priv,
int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev) int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev)
{ {
struct snd_soc_card *card = simple_priv_to_card(priv); struct snd_soc_card *card = simple_priv_to_card(priv);
struct link_info li; struct link_info *li;
int ret; int ret;
li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
if (!li)
return -ENOMEM;
card->owner = THIS_MODULE; card->owner = THIS_MODULE;
card->dev = dev; card->dev = dev;
memset(&li, 0, sizeof(li)); ret = graph_get_dais_count(priv, li);
ret = graph_get_dais_count(priv, &li);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!li.link) if (!li->link)
return -EINVAL; return -EINVAL;
ret = asoc_simple_init_priv(priv, &li); ret = asoc_simple_init_priv(priv, li);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -581,8 +584,8 @@ int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev) ...@@ -581,8 +584,8 @@ int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev)
if (ret < 0) if (ret < 0)
return ret; return ret;
memset(&li, 0, sizeof(li)); memset(li, 0, sizeof(*li));
ret = graph_for_each_link(priv, &li, ret = graph_for_each_link(priv, li,
graph_dai_link_of, graph_dai_link_of,
graph_dai_link_of_dpcm); graph_dai_link_of_dpcm);
if (ret < 0) if (ret < 0)
...@@ -600,6 +603,7 @@ int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev) ...@@ -600,6 +603,7 @@ int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev)
if (ret < 0) if (ret < 0)
goto err; goto err;
devm_kfree(dev, li);
return 0; return 0;
err: err:
......
...@@ -442,10 +442,9 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, ...@@ -442,10 +442,9 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
return ret; return ret;
} }
static int simple_parse_of(struct asoc_simple_priv *priv) static int simple_parse_of(struct asoc_simple_priv *priv, struct link_info *li)
{ {
struct snd_soc_card *card = simple_priv_to_card(priv); struct snd_soc_card *card = simple_priv_to_card(priv);
struct link_info li;
int ret; int ret;
ret = asoc_simple_parse_widgets(card, PREFIX); ret = asoc_simple_parse_widgets(card, PREFIX);
...@@ -461,8 +460,8 @@ static int simple_parse_of(struct asoc_simple_priv *priv) ...@@ -461,8 +460,8 @@ static int simple_parse_of(struct asoc_simple_priv *priv)
return ret; return ret;
/* Single/Muti DAI link(s) & New style of DT node */ /* Single/Muti DAI link(s) & New style of DT node */
memset(&li, 0, sizeof(li)); memset(li, 0, sizeof(*li));
ret = simple_for_each_link(priv, &li, ret = simple_for_each_link(priv, li,
simple_dai_link_of, simple_dai_link_of,
simple_dai_link_of_dpcm); simple_dai_link_of_dpcm);
if (ret < 0) if (ret < 0)
...@@ -612,7 +611,7 @@ static int asoc_simple_probe(struct platform_device *pdev) ...@@ -612,7 +611,7 @@ static int asoc_simple_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct snd_soc_card *card; struct snd_soc_card *card;
struct link_info li; struct link_info *li;
int ret; int ret;
/* Allocate the private data and the DAI link array */ /* Allocate the private data and the DAI link array */
...@@ -625,21 +624,24 @@ static int asoc_simple_probe(struct platform_device *pdev) ...@@ -625,21 +624,24 @@ static int asoc_simple_probe(struct platform_device *pdev)
card->dev = dev; card->dev = dev;
card->probe = simple_soc_probe; card->probe = simple_soc_probe;
memset(&li, 0, sizeof(li)); li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
ret = simple_get_dais_count(priv, &li); if (!li)
return -ENOMEM;
ret = simple_get_dais_count(priv, li);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!li.link) if (!li->link)
return -EINVAL; return -EINVAL;
ret = asoc_simple_init_priv(priv, &li); ret = asoc_simple_init_priv(priv, li);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (np && of_device_is_available(np)) { if (np && of_device_is_available(np)) {
ret = simple_parse_of(priv); ret = simple_parse_of(priv, li);
if (ret < 0) { if (ret < 0) {
if (ret != -EPROBE_DEFER) if (ret != -EPROBE_DEFER)
dev_err(dev, "parse error %d\n", ret); dev_err(dev, "parse error %d\n", ret);
...@@ -698,6 +700,7 @@ static int asoc_simple_probe(struct platform_device *pdev) ...@@ -698,6 +700,7 @@ static int asoc_simple_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto err; goto err;
devm_kfree(dev, li);
return 0; return 0;
err: err:
asoc_simple_clean_reference(card); asoc_simple_clean_reference(card);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment