aboutsummaryrefslogtreecommitdiff
path: root/sound/core
diff options
context:
space:
mode:
authorTakashi Iwai2021-07-31 10:34:46 +0200
committerTakashi Iwai2021-07-31 10:36:06 +0200
commit825a52482a616d74bd2f5eacc0f8946d025499a7 (patch)
treec9c83fbe54d3590b7f1b1b621bbc4a0bf4267cf0 /sound/core
parentfac24b0f34c179c6ca863f5205fad42a676caf9a (diff)
ALSA: core: Fix double calls of snd_card_free() via devres
At the transition to the devres-managed card release, we've put the check of double-free at trigger_card_release(). But this wasn't enough, as the code path calls snd_card_free() again, and it would lead to the doubly snd_card_free() calls. Actually the v1 patch was correct to handle this, but I forgot that corner case and moved the check to the more obvious place as I thought it's clearer. But, as usual, devils live in details. This patch corrects the check of the double-free to the right place, with a bit more comments. Fixes: e8ad415b7a55 ("ALSA: core: Add managed card creation") Link: https://lore.kernel.org/r/20210731083446.26680-1-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core')
-rw-r--r--sound/core/init.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/sound/core/init.c b/sound/core/init.c
index e985185ebc91..ac335f5906c6 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -605,6 +605,15 @@ int snd_card_free(struct snd_card *card)
DECLARE_COMPLETION_ONSTACK(released);
int ret;
+ /* The call of snd_card_free() is allowed from various code paths;
+ * a manual call from the driver and the call via devres_free, and
+ * we need to avoid double-free. Moreover, the release via devres
+ * may call snd_card_free() twice due to its nature, we need to have
+ * the check here at the beginning.
+ */
+ if (card->releasing)
+ return 0;
+
card->release_completion = &released;
ret = snd_card_free_when_closed(card);
if (ret)
@@ -813,10 +822,7 @@ EXPORT_SYMBOL_GPL(snd_card_add_dev_attr);
static void trigger_card_free(void *data)
{
- struct snd_card *card = data;
-
- if (!card->releasing)
- snd_card_free(data);
+ snd_card_free(data);
}
/**