Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2464064 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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: default avatarTakashi Iwai <tiwai@suse.de>
parent 34356dbd
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -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))

+15 −38
Original line number Diff line number Diff line
@@ -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);
	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;
}

+1 −1
Original line number Diff line number Diff line
@@ -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);
+1 −1
Original line number Diff line number Diff line
@@ -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);