aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/init.c')
-rw-r--r--sound/core/init.c69
1 files changed, 54 insertions, 15 deletions
diff --git a/sound/core/init.c b/sound/core/init.c
index 1ecb029ff4c9..5850d99d21e3 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -327,22 +327,10 @@ EXPORT_SYMBOL(snd_card_disconnect);
327 * Returns zero. Frees all associated devices and frees the control 327 * Returns zero. Frees all associated devices and frees the control
328 * interface associated to given soundcard. 328 * interface associated to given soundcard.
329 */ 329 */
330int snd_card_free(struct snd_card *card) 330static int snd_card_do_free(struct snd_card *card)
331{ 331{
332 struct snd_shutdown_f_ops *s_f_ops; 332 struct snd_shutdown_f_ops *s_f_ops;
333 333
334 if (card == NULL)
335 return -EINVAL;
336 mutex_lock(&snd_card_mutex);
337 snd_cards[card->number] = NULL;
338 mutex_unlock(&snd_card_mutex);
339
340#ifdef CONFIG_PM
341 wake_up(&card->power_sleep);
342#endif
343 /* wait, until all devices are ready for the free operation */
344 wait_event(card->shutdown_sleep, card->files == NULL);
345
346#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) 334#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
347 if (snd_mixer_oss_notify_callback) 335 if (snd_mixer_oss_notify_callback)
348 snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE); 336 snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_FREE);
@@ -371,10 +359,55 @@ int snd_card_free(struct snd_card *card)
371 card->s_f_ops = s_f_ops->next; 359 card->s_f_ops = s_f_ops->next;
372 kfree(s_f_ops); 360 kfree(s_f_ops);
373 } 361 }
362 kfree(card);
363 return 0;
364}
365
366static int snd_card_free_prepare(struct snd_card *card)
367{
368 if (card == NULL)
369 return -EINVAL;
370 (void) snd_card_disconnect(card);
374 mutex_lock(&snd_card_mutex); 371 mutex_lock(&snd_card_mutex);
372 snd_cards[card->number] = NULL;
375 snd_cards_lock &= ~(1 << card->number); 373 snd_cards_lock &= ~(1 << card->number);
376 mutex_unlock(&snd_card_mutex); 374 mutex_unlock(&snd_card_mutex);
377 kfree(card); 375#ifdef CONFIG_PM
376 wake_up(&card->power_sleep);
377#endif
378 return 0;
379}
380
381int snd_card_free_when_closed(struct snd_card *card)
382{
383 int free_now = 0;
384 int ret = snd_card_free_prepare(card);
385 if (ret)
386 return ret;
387
388 spin_lock(&card->files_lock);
389 if (card->files == NULL)
390 free_now = 1;
391 else
392 card->free_on_last_close = 1;
393 spin_unlock(&card->files_lock);
394
395 if (free_now)
396 snd_card_do_free(card);
397 return 0;
398}
399
400EXPORT_SYMBOL(snd_card_free_when_closed);
401
402int snd_card_free(struct snd_card *card)
403{
404 int ret = snd_card_free_prepare(card);
405 if (ret)
406 return ret;
407
408 /* wait, until all devices are ready for the free operation */
409 wait_event(card->shutdown_sleep, card->files == NULL);
410 snd_card_do_free(card);
378 return 0; 411 return 0;
379} 412}
380 413
@@ -718,6 +751,7 @@ EXPORT_SYMBOL(snd_card_file_add);
718int snd_card_file_remove(struct snd_card *card, struct file *file) 751int snd_card_file_remove(struct snd_card *card, struct file *file)
719{ 752{
720 struct snd_monitor_file *mfile, *pfile = NULL; 753 struct snd_monitor_file *mfile, *pfile = NULL;
754 int last_close = 0;
721 755
722 spin_lock(&card->files_lock); 756 spin_lock(&card->files_lock);
723 mfile = card->files; 757 mfile = card->files;
@@ -732,9 +766,14 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
732 pfile = mfile; 766 pfile = mfile;
733 mfile = mfile->next; 767 mfile = mfile->next;
734 } 768 }
735 spin_unlock(&card->files_lock);
736 if (card->files == NULL) 769 if (card->files == NULL)
770 last_close = 1;
771 spin_unlock(&card->files_lock);
772 if (last_close) {
737 wake_up(&card->shutdown_sleep); 773 wake_up(&card->shutdown_sleep);
774 if (card->free_on_last_close)
775 snd_card_do_free(card);
776 }
738 if (!mfile) { 777 if (!mfile) {
739 snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); 778 snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
740 return -ENOENT; 779 return -ENOENT;