diff options
author | Mark Brown <broonie@kernel.org> | 2018-01-25 18:16:26 +0000 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2018-01-25 18:16:26 +0000 |
commit | 0b5eca67bd2d0e6f6d0ccdc316aced0cc4bf2e9f (patch) | |
tree | b6597ffe774a67ab5b8eebd57c9a723732d3a39c /sound/core/init.c | |
parent | 3bb0f7c31b1aedd0f85c675297031281799145d7 (diff) | |
parent | 93a00c467fe998bf5716cbc9cabc127046054782 (diff) | |
download | linux-0b5eca67bd2d0e6f6d0ccdc316aced0cc4bf2e9f.tar.bz2 |
Merge branches 'topic/twl4030' and 'topic/twl6040' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-twl-breakage
Diffstat (limited to 'sound/core/init.c')
-rw-r--r-- | sound/core/init.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/sound/core/init.c b/sound/core/init.c index 32ebe2f6bc59..168ae03d3a1c 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -255,6 +255,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid, #ifdef CONFIG_PM init_waitqueue_head(&card->power_sleep); #endif + init_waitqueue_head(&card->remove_sleep); device_initialize(&card->card_dev); card->card_dev.parent = parent; @@ -452,6 +453,35 @@ int snd_card_disconnect(struct snd_card *card) } EXPORT_SYMBOL(snd_card_disconnect); +/** + * snd_card_disconnect_sync - disconnect card and wait until files get closed + * @card: card object to disconnect + * + * This calls snd_card_disconnect() for disconnecting all belonging components + * and waits until all pending files get closed. + * It assures that all accesses from user-space finished so that the driver + * can release its resources gracefully. + */ +void snd_card_disconnect_sync(struct snd_card *card) +{ + int err; + + err = snd_card_disconnect(card); + if (err < 0) { + dev_err(card->dev, + "snd_card_disconnect error (%d), skipping sync\n", + err); + return; + } + + spin_lock_irq(&card->files_lock); + wait_event_lock_irq(card->remove_sleep, + list_empty(&card->files_list), + card->files_lock); + spin_unlock_irq(&card->files_lock); +} +EXPORT_SYMBOL_GPL(snd_card_disconnect_sync); + static int snd_card_do_free(struct snd_card *card) { #if IS_ENABLED(CONFIG_SND_MIXER_OSS) @@ -957,6 +987,8 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) break; } } + if (list_empty(&card->files_list)) + wake_up_all(&card->remove_sleep); spin_unlock(&card->files_lock); if (!found) { dev_err(card->dev, "card file remove problem (%p)\n", file); |