ASoC: soc-dapm: Remove widget from cache on removal

When a single DAPM widget is removed, it also needs to be removed from
the widget cache to prevent dapm_wcache_lookup() from using a dangling
pointer when checking if a widget is in cache. Since widgets may be
cached across different DAPM contexts on the card (e.g. card routes),
clear any matching cache entries across all DAPM contexts on the card.
Since dapm_free_widgets() calls snd_soc_dapm_free_widget() anyway, it
does not need to clear cache anymore.

Signed-off-by: Amadeusz Sławiński <amade@asmblr.net>
Link: https://patch.msgid.link/20261014200608.118770-9-amade@asmblr.net
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Amadeusz Sławiński 2026-10-14 22:06:08 +02:00 committed by Mark Brown
parent 9df30adce8
commit 568406bc83
No known key found for this signature in database
GPG Key ID: 2FEF73B0B3D03889

View File

@ -2869,6 +2869,7 @@ static void dapm_free_path(struct snd_soc_dapm_path *path)
*/
void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w)
{
struct snd_soc_dapm_context *d;
struct snd_soc_dapm_path *p, *next_p;
enum snd_soc_dapm_direction dir;
@ -2889,6 +2890,22 @@ void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w)
dapm_debugfs_free_widget(w);
if (w->dapm) {
if (w->dapm->card) {
for_each_card_dapms(w->dapm->card, d) {
if (d->wcache_sink == w)
d->wcache_sink = NULL;
if (d->wcache_source == w)
d->wcache_source = NULL;
}
} else {
if (w->dapm->wcache_sink == w)
w->dapm->wcache_sink = NULL;
if (w->dapm->wcache_source == w)
w->dapm->wcache_source = NULL;
}
}
kfree(w->kcontrols);
kfree_const(w->name);
kfree_const(w->sname);
@ -2906,9 +2923,6 @@ static void dapm_free_widgets(struct snd_soc_dapm_context *dapm)
continue;
snd_soc_dapm_free_widget(w);
}
dapm->wcache_sink = NULL;
dapm->wcache_source = NULL;
}
static struct snd_soc_dapm_widget *dapm_find_widget(