diff options
author | Takashi Iwai <tiwai@suse.de> | 2014-01-29 15:13:43 +0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2014-02-14 11:14:13 +0400 |
commit | f24640648186b59bd39f8cd640d631bdb61a3197 (patch) | |
tree | a73d73fd6d100ace77a0f67d7af3df367251d1bc /sound/core/init.c | |
parent | 34356dbdb64e9f12cc8ce1bb0d9e38a75b1e4638 (diff) | |
download | linux-f24640648186b59bd39f8cd640d631bdb61a3197.tar.xz |
ALSA: Use standard device refcount for card accounting
Drop the own refcount but use the standard device refcounting via
get_device() and put_device(). Introduce a new completion to snd_card
instead of the wait queue for syncing the last release, which is used
in snd_card_free().
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/init.c')
-rw-r--r-- | sound/core/init.c | 53 |
1 files changed, 15 insertions, 38 deletions
diff --git a/sound/core/init.c b/sound/core/init.c index ff96eda898e3..5b7c4eb46c10 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -28,6 +28,7 @@ #include <linux/time.h> #include <linux/ctype.h> #include <linux/pm.h> +#include <linux/completion.h> #include <sound/core.h> #include <sound/control.h> @@ -235,8 +236,6 @@ int snd_card_new(struct device *parent, int idx, const char *xid, INIT_LIST_HEAD(&card->ctl_files); spin_lock_init(&card->files_lock); INIT_LIST_HEAD(&card->files_list); - init_waitqueue_head(&card->shutdown_sleep); - atomic_set(&card->refcount, 0); #ifdef CONFIG_PM mutex_init(&card->power_lock); init_waitqueue_head(&card->power_sleep); @@ -474,58 +473,36 @@ static int snd_card_do_free(struct snd_card *card) snd_printk(KERN_WARNING "unable to free card info\n"); /* Not fatal error */ } + if (card->release_completion) + complete(card->release_completion); kfree(card); return 0; } -/** - * snd_card_unref - release the reference counter - * @card: the card instance - * - * Decrements the reference counter. When it reaches to zero, wake up - * the sleeper and call the destructor if needed. - */ -void snd_card_unref(struct snd_card *card) -{ - if (atomic_dec_and_test(&card->refcount)) { - wake_up(&card->shutdown_sleep); - if (card->free_on_last_close) - put_device(&card->card_dev); - } -} -EXPORT_SYMBOL(snd_card_unref); - int snd_card_free_when_closed(struct snd_card *card) { - int ret; - - atomic_inc(&card->refcount); - ret = snd_card_disconnect(card); - if (ret) { - atomic_dec(&card->refcount); + int ret = snd_card_disconnect(card); + if (ret) return ret; - } - - card->free_on_last_close = 1; - if (atomic_dec_and_test(&card->refcount)) - put_device(&card->card_dev); + put_device(&card->card_dev); return 0; } - EXPORT_SYMBOL(snd_card_free_when_closed); int snd_card_free(struct snd_card *card) { - int ret = snd_card_disconnect(card); + struct completion released; + int ret; + + init_completion(&released); + card->release_completion = &released; + ret = snd_card_free_when_closed(card); if (ret) return ret; - /* wait, until all devices are ready for the free operation */ - wait_event(card->shutdown_sleep, !atomic_read(&card->refcount)); - put_device(&card->card_dev); + wait_for_completion(&released); return 0; } - EXPORT_SYMBOL(snd_card_free); /* retrieve the last word of shortname or longname */ @@ -932,7 +909,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file) return -ENODEV; } list_add(&mfile->list, &card->files_list); - atomic_inc(&card->refcount); + get_device(&card->card_dev); spin_unlock(&card->files_lock); return 0; } @@ -975,7 +952,7 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) return -ENOENT; } kfree(found); - snd_card_unref(card); + put_device(&card->card_dev); return 0; } |