ASoC: dapm: Fix NULL pointer deference on CODEC to CODEC DAIs
authorCharles Keepax <ckeepax@opensource.cirrus.com>
Wed, 15 Aug 2018 12:11:35 +0000 (13:11 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 15 Aug 2018 14:52:20 +0000 (15:52 +0100)
Commit a655de808cbde ("ASoC: core: Allow topology to override
machine driver FE DAI link config.") caused soc_dai_hw_params to
be come dependent on the substream private_data being set with
a pointer to the snd_soc_pcm_runtime. Currently, CODEC to CODEC
links don't set this, which causes a NULL pointer dereference:

[<4069de54>] (soc_dai_hw_params) from
[<40694b68>] (snd_soc_dai_link_event+0x1a0/0x380)

Since the ASoC core in general assumes that the substream
private_data will be set to a pointer to the snd_soc_pcm_runtime,
update the CODEC to CODEC links to respect this.

Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/soc-dapm.h
sound/soc/soc-core.c
sound/soc/soc-dapm.c

index af9ef16cc34d36f6fd314cc2522997a4b2dbc12f..fdaaafdc7a0039a0c4a6e93b6d2b7ed88ea5b74a 100644 (file)
@@ -407,6 +407,7 @@ int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
 int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card);
 void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card);
 int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
+                        struct snd_soc_pcm_runtime *rtd,
                         const struct snd_soc_pcm_stream *params,
                         unsigned int num_params,
                         struct snd_soc_dapm_widget *source,
index 9cfe10d8040cf8f0cea83d85d2dfb68a6b508f6d..473eefe8658e9a22af71b2f3af42f1f92cf00acd 100644 (file)
@@ -1447,7 +1447,7 @@ static int soc_link_dai_widgets(struct snd_soc_card *card,
        sink = codec_dai->playback_widget;
        source = cpu_dai->capture_widget;
        if (sink && source) {
-               ret = snd_soc_dapm_new_pcm(card, dai_link->params,
+               ret = snd_soc_dapm_new_pcm(card, rtd, dai_link->params,
                                           dai_link->num_params,
                                           source, sink);
                if (ret != 0) {
@@ -1460,7 +1460,7 @@ static int soc_link_dai_widgets(struct snd_soc_card *card,
        sink = cpu_dai->playback_widget;
        source = codec_dai->capture_widget;
        if (sink && source) {
-               ret = snd_soc_dapm_new_pcm(card, dai_link->params,
+               ret = snd_soc_dapm_new_pcm(card, rtd, dai_link->params,
                                           dai_link->num_params,
                                           source, sink);
                if (ret != 0) {
index 7e96793050c9b1a1b634d34e4e0ad9a658cf4111..461d951917c0569096eacd4274fd9eb1ade8f9c5 100644 (file)
@@ -3652,6 +3652,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
 {
        struct snd_soc_dapm_path *source_p, *sink_p;
        struct snd_soc_dai *source, *sink;
+       struct snd_soc_pcm_runtime *rtd = w->priv;
        const struct snd_soc_pcm_stream *config = w->params + w->params_select;
        struct snd_pcm_substream substream;
        struct snd_pcm_hw_params *params = NULL;
@@ -3711,6 +3712,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w,
                goto out;
        }
        substream.runtime = runtime;
+       substream.private_data = rtd;
 
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
@@ -3895,6 +3897,7 @@ outfree_w_param:
 }
 
 int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
+                        struct snd_soc_pcm_runtime *rtd,
                         const struct snd_soc_pcm_stream *params,
                         unsigned int num_params,
                         struct snd_soc_dapm_widget *source,
@@ -3963,6 +3966,7 @@ int snd_soc_dapm_new_pcm(struct snd_soc_card *card,
 
        w->params = params;
        w->num_params = num_params;
+       w->priv = rtd;
 
        ret = snd_soc_dapm_add_path(&card->dapm, source, w, NULL, NULL);
        if (ret)