diff options
| author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-11-16 11:41:51 +0200 | 
|---|---|---|
| committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2012-11-16 11:41:51 +0200 | 
| commit | 3c3dd225819112e56554162c6b37e61a31924e0c (patch) | |
| tree | 5bcd3a63010af2cd5bb946b5af21ef27f1dcfe3c /sound/core/init.c | |
| parent | a915d4ca24b814daee9cddbc42cd41f59fe4fa8f (diff) | |
| parent | 3d70f8c617a436c7146ecb81df2265b4626dfe89 (diff) | |
Merge tag 'v3.7-rc4'
Merge Linux 3.7-rc4 to get fixes for CMA.
Diffstat (limited to 'sound/core/init.c')
| -rw-r--r-- | sound/core/init.c | 50 | 
1 files changed, 30 insertions, 20 deletions
diff --git a/sound/core/init.c b/sound/core/init.c index d8ec849af12..7b012d15c2c 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid,  	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); @@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *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) +			snd_card_do_free(card); +	} +} +EXPORT_SYMBOL(snd_card_unref); +  int snd_card_free_when_closed(struct snd_card *card)  { -	int free_now = 0; -	int ret = snd_card_disconnect(card); -	if (ret) -		return ret; +	int ret; -	spin_lock(&card->files_lock); -	if (list_empty(&card->files_list)) -		free_now = 1; -	else -		card->free_on_last_close = 1; -	spin_unlock(&card->files_lock); +	atomic_inc(&card->refcount); +	ret = snd_card_disconnect(card); +	if (ret) { +		atomic_dec(&card->refcount); +		return ret; +	} -	if (free_now) +	card->free_on_last_close = 1; +	if (atomic_dec_and_test(&card->refcount))  		snd_card_do_free(card);  	return 0;  } @@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card)  		return ret;  	/* wait, until all devices are ready for the free operation */ -	wait_event(card->shutdown_sleep, list_empty(&card->files_list)); +	wait_event(card->shutdown_sleep, !atomic_read(&card->refcount));  	snd_card_do_free(card);  	return 0;  } @@ -886,6 +902,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);  	spin_unlock(&card->files_lock);  	return 0;  } @@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add);  int snd_card_file_remove(struct snd_card *card, struct file *file)  {  	struct snd_monitor_file *mfile, *found = NULL; -	int last_close = 0;  	spin_lock(&card->files_lock);  	list_for_each_entry(mfile, &card->files_list, list) { @@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)  			break;  		}  	} -	if (list_empty(&card->files_list)) -		last_close = 1;  	spin_unlock(&card->files_lock); -	if (last_close) { -		wake_up(&card->shutdown_sleep); -		if (card->free_on_last_close) -			snd_card_do_free(card); -	}  	if (!found) {  		snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);  		return -ENOENT;  	}  	kfree(found); +	snd_card_unref(card);  	return 0;  }  | 
