From: Pierre-Louis Bossart Date: Wed, 6 Apr 2022 19:16:06 +0000 (-0500) Subject: ASoC: SOF: topology: cleanup dailinks on widget unload X-Git-Tag: v6.6.17~7583^2~18^2~7 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=20744617bdbafe2e7fb7bf5401f616e24bde4471;p=platform%2Fkernel%2Flinux-rpi.git ASoC: SOF: topology: cleanup dailinks on widget unload We set the cpu_dai capture_ or playback_widget on widget_ready but never clear them, which leads to failures when unloading/reloading a topology in modprobe/rmmod tests BugLink: https://github.com/thesofproject/linux/issues/3535 Fixes: 311ce4fe7637 ("ASoC: SOF: Add support for loading topologies") Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20220406191606.254576-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 75d78f9..5953d10 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1070,6 +1070,46 @@ static int sof_connect_dai_widget(struct snd_soc_component *scomp, return 0; } +static void sof_disconnect_dai_widget(struct snd_soc_component *scomp, + struct snd_soc_dapm_widget *w) +{ + struct snd_soc_card *card = scomp->card; + struct snd_soc_pcm_runtime *rtd; + struct snd_soc_dai *cpu_dai; + int i; + + if (!w->sname) + return; + + list_for_each_entry(rtd, &card->rtd_list, list) { + /* does stream match DAI link ? */ + if (!rtd->dai_link->stream_name || + strcmp(w->sname, rtd->dai_link->stream_name)) + continue; + + switch (w->id) { + case snd_soc_dapm_dai_out: + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { + if (cpu_dai->capture_widget == w) { + cpu_dai->capture_widget = NULL; + break; + } + } + break; + case snd_soc_dapm_dai_in: + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { + if (cpu_dai->playback_widget == w) { + cpu_dai->playback_widget = NULL; + break; + } + } + break; + default: + break; + } + } +} + /* bind PCM ID to host component ID */ static int spcm_bind(struct snd_soc_component *scomp, struct snd_sof_pcm *spcm, int dir) @@ -1355,6 +1395,9 @@ static int sof_widget_unload(struct snd_soc_component *scomp, if (dai) list_del(&dai->list); + + sof_disconnect_dai_widget(scomp, widget); + break; default: break;