OSDN Git Service

ASoC: simple-card-utils: Allocate link info structure on heap
authorThierry Reding <treding@nvidia.com>
Mon, 19 Apr 2021 16:41:17 +0000 (18:41 +0200)
committerMark Brown <broonie@kernel.org>
Tue, 20 Apr 2021 12:47:30 +0000 (13:47 +0100)
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>
sound/soc/generic/audio-graph-card.c
sound/soc/generic/simple-card.c

index c7369be..e45a560 100644 (file)
@@ -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:
index 8b9964d..ca27cb9 100644 (file)
@@ -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);