summaryrefslogtreecommitdiff
path: root/sound/soc
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2021-04-19 18:41:17 +0200
committerMark Brown <broonie@kernel.org>2021-04-20 13:47:30 +0100
commitec1af6c64db94e4f24e53011a77b2bf2220ae000 (patch)
treebd2ec434df0717514d8fc8c03e07fa478067bb86 /sound/soc
parent7f51384f17b3e1039fbb2d3535cc777585dc3175 (diff)
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: 343e55e71877 ("ASoC: simple-card-utils: Increase maximum number of links to 128") Reported-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Thierry Reding <treding@nvidia.com> Acked-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> Link: https://lore.kernel.org/r/20210419164117.1422242-1-thierry.reding@gmail.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/generic/audio-graph-card.c18
-rw-r--r--sound/soc/generic/simple-card.c23
2 files changed, 24 insertions, 17 deletions
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index c7369beee805..e45a560aa9b0 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -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)
{
struct snd_soc_card *card = simple_priv_to_card(priv);
- struct link_info li;
+ struct link_info *li;
int ret;
+ li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
+ if (!li)
+ return -ENOMEM;
+
card->owner = THIS_MODULE;
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)
return ret;
- if (!li.link)
+ if (!li->link)
return -EINVAL;
- ret = asoc_simple_init_priv(priv, &li);
+ ret = asoc_simple_init_priv(priv, li);
if (ret < 0)
return ret;
@@ -581,8 +584,8 @@ int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev)
if (ret < 0)
return ret;
- memset(&li, 0, sizeof(li));
- ret = graph_for_each_link(priv, &li,
+ memset(li, 0, sizeof(*li));
+ ret = graph_for_each_link(priv, li,
graph_dai_link_of,
graph_dai_link_of_dpcm);
if (ret < 0)
@@ -600,6 +603,7 @@ int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev)
if (ret < 0)
goto err;
+ devm_kfree(dev, li);
return 0;
err:
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 8b9964d25757..ca27cb9ff9e1 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -442,10 +442,9 @@ static int simple_for_each_link(struct asoc_simple_priv *priv,
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 link_info li;
int ret;
ret = asoc_simple_parse_widgets(card, PREFIX);
@@ -461,8 +460,8 @@ static int simple_parse_of(struct asoc_simple_priv *priv)
return ret;
/* Single/Muti DAI link(s) & New style of DT node */
- memset(&li, 0, sizeof(li));
- ret = simple_for_each_link(priv, &li,
+ memset(li, 0, sizeof(*li));
+ ret = simple_for_each_link(priv, li,
simple_dai_link_of,
simple_dai_link_of_dpcm);
if (ret < 0)
@@ -612,7 +611,7 @@ static int asoc_simple_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct snd_soc_card *card;
- struct link_info li;
+ struct link_info *li;
int ret;
/* Allocate the private data and the DAI link array */
@@ -625,21 +624,24 @@ static int asoc_simple_probe(struct platform_device *pdev)
card->dev = dev;
card->probe = simple_soc_probe;
- memset(&li, 0, sizeof(li));
- ret = simple_get_dais_count(priv, &li);
+ li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL);
+ if (!li)
+ return -ENOMEM;
+
+ ret = simple_get_dais_count(priv, li);
if (ret < 0)
return ret;
- if (!li.link)
+ if (!li->link)
return -EINVAL;
- ret = asoc_simple_init_priv(priv, &li);
+ ret = asoc_simple_init_priv(priv, li);
if (ret < 0)
return ret;
if (np && of_device_is_available(np)) {
- ret = simple_parse_of(priv);
+ ret = simple_parse_of(priv, li);
if (ret < 0) {
if (ret != -EPROBE_DEFER)
dev_err(dev, "parse error %d\n", ret);
@@ -698,6 +700,7 @@ static int asoc_simple_probe(struct platform_device *pdev)
if (ret < 0)
goto err;
+ devm_kfree(dev, li);
return 0;
err:
asoc_simple_clean_reference(card);