]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ALSA: Use standard device refcount for card accounting
authorTakashi Iwai <tiwai@suse.de>
Wed, 29 Jan 2014 11:13:43 +0000 (12:13 +0100)
committerTakashi Iwai <tiwai@suse.de>
Fri, 14 Feb 2014 07:14:13 +0000 (08:14 +0100)
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>
include/sound/core.h
sound/core/init.c
sound/core/sound.c
sound/core/sound_oss.c

index 7e4fb3e93fc7797b8bb66808ea940230cfe62491..4519dac98363e8f3bacc3445ebade7f97034a73c 100644 (file)
@@ -42,6 +42,7 @@
 /* forward declarations */
 struct pci_dev;
 struct module;
+struct completion;
 
 /* device allocation stuff */
 
@@ -130,9 +131,7 @@ struct snd_card {
                                                                state */
        spinlock_t files_lock;          /* lock the files for this card */
        int shutdown;                   /* this card is going down */
-       int free_on_last_close;         /* free in context of file_release */
-       wait_queue_head_t shutdown_sleep;
-       atomic_t refcount;              /* refcount for disconnection */
+       struct completion *release_completion;
        struct device *dev;             /* device assigned to this card */
        struct device card_dev;         /* cardX object for sysfs */
        bool registered;                /* card_dev is registered? */
@@ -306,7 +305,7 @@ int snd_card_info_done(void);
 int snd_component_add(struct snd_card *card, const char *component);
 int snd_card_file_add(struct snd_card *card, struct file *file);
 int snd_card_file_remove(struct snd_card *card, struct file *file);
-void snd_card_unref(struct snd_card *card);
+#define snd_card_unref(card)   put_device(&(card)->card_dev)
 
 #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))
 
index ff96eda898e3ecef02f50bf1fd8b1054b3706fb9..5b7c4eb46c10cdb32b0320347aa0f6bec225f616 100644 (file)
@@ -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;
 }
 
index 437c25ea640363b5d38d8214e873cb236f1aec43..4aaa53161644eac8d20d6baf551a33fb4de1bc59 100644 (file)
@@ -118,7 +118,7 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
        if (mreg && mreg->type == type) {
                private_data = mreg->private_data;
                if (private_data && mreg->card_ptr)
-                       atomic_inc(&mreg->card_ptr->refcount);
+                       get_device(&mreg->card_ptr->card_dev);
        } else
                private_data = NULL;
        mutex_unlock(&sound_mutex);
index b19184d45f19ffea951e956cdce16fc54539b3e1..573a65eb2b796961ed72b2999dc4b63fb05326ef 100644 (file)
@@ -55,7 +55,7 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type)
        if (mreg && mreg->type == type) {
                private_data = mreg->private_data;
                if (private_data && mreg->card_ptr)
-                       atomic_inc(&mreg->card_ptr->refcount);
+                       get_device(&mreg->card_ptr->card_dev);
        } else
                private_data = NULL;
        mutex_unlock(&sound_oss_mutex);