diff options
author | Thierry Reding <treding@nvidia.com> | 2021-04-19 19:41:17 +0300 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2021-04-20 15:47:30 +0300 |
commit | ec1af6c64db94e4f24e53011a77b2bf2220ae000 (patch) | |
tree | bd2ec434df0717514d8fc8c03e07fa478067bb86 /sound/soc | |
parent | 7f51384f17b3e1039fbb2d3535cc777585dc3175 (diff) | |
download | linux-ec1af6c64db94e4f24e53011a77b2bf2220ae000.tar.xz |
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.c | 18 | ||||
-rw-r--r-- | sound/soc/generic/simple-card.c | 23 |
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); |