aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/core.h6
-rw-r--r--sound/core/init.c42
2 files changed, 18 insertions, 30 deletions
diff --git a/include/sound/core.h b/include/sound/core.h
index f632484bc743..bd4529e0c27e 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -97,9 +97,9 @@ struct snd_device {
97 97
98struct snd_monitor_file { 98struct snd_monitor_file {
99 struct file *file; 99 struct file *file;
100 struct snd_monitor_file *next;
101 const struct file_operations *disconnected_f_op; 100 const struct file_operations *disconnected_f_op;
102 struct list_head shutdown_list; 101 struct list_head shutdown_list; /* still need to shutdown */
102 struct list_head list; /* link of monitor files */
103}; 103};
104 104
105/* main structure for soundcard */ 105/* main structure for soundcard */
@@ -134,7 +134,7 @@ struct snd_card {
134 struct snd_info_entry *proc_id; /* the card id */ 134 struct snd_info_entry *proc_id; /* the card id */
135 struct proc_dir_entry *proc_root_link; /* number link to real id */ 135 struct proc_dir_entry *proc_root_link; /* number link to real id */
136 136
137 struct snd_monitor_file *files; /* all files associated to this card */ 137 struct list_head files_list; /* all files associated to this card */
138 struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown 138 struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown
139 state */ 139 state */
140 spinlock_t files_lock; /* lock the files for this card */ 140 spinlock_t files_lock; /* lock the files for this card */
diff --git a/sound/core/init.c b/sound/core/init.c
index 0d5520c415d3..05c6da554cbf 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -195,6 +195,7 @@ struct snd_card *snd_card_new(int idx, const char *xid,
195 INIT_LIST_HEAD(&card->controls); 195 INIT_LIST_HEAD(&card->controls);
196 INIT_LIST_HEAD(&card->ctl_files); 196 INIT_LIST_HEAD(&card->ctl_files);
197 spin_lock_init(&card->files_lock); 197 spin_lock_init(&card->files_lock);
198 INIT_LIST_HEAD(&card->files_list);
198 init_waitqueue_head(&card->shutdown_sleep); 199 init_waitqueue_head(&card->shutdown_sleep);
199#ifdef CONFIG_PM 200#ifdef CONFIG_PM
200 mutex_init(&card->power_lock); 201 mutex_init(&card->power_lock);
@@ -259,6 +260,7 @@ static int snd_disconnect_release(struct inode *inode, struct file *file)
259 list_for_each_entry(_df, &shutdown_files, shutdown_list) { 260 list_for_each_entry(_df, &shutdown_files, shutdown_list) {
260 if (_df->file == file) { 261 if (_df->file == file) {
261 df = _df; 262 df = _df;
263 list_del_init(&df->shutdown_list);
262 break; 264 break;
263 } 265 }
264 } 266 }
@@ -347,8 +349,7 @@ int snd_card_disconnect(struct snd_card *card)
347 /* phase 2: replace file->f_op with special dummy operations */ 349 /* phase 2: replace file->f_op with special dummy operations */
348 350
349 spin_lock(&card->files_lock); 351 spin_lock(&card->files_lock);
350 mfile = card->files; 352 list_for_each_entry(mfile, &card->files_list, list) {
351 while (mfile) {
352 file = mfile->file; 353 file = mfile->file;
353 354
354 /* it's critical part, use endless loop */ 355 /* it's critical part, use endless loop */
@@ -361,8 +362,6 @@ int snd_card_disconnect(struct snd_card *card)
361 362
362 mfile->file->f_op = &snd_shutdown_f_ops; 363 mfile->file->f_op = &snd_shutdown_f_ops;
363 fops_get(mfile->file->f_op); 364 fops_get(mfile->file->f_op);
364
365 mfile = mfile->next;
366 } 365 }
367 spin_unlock(&card->files_lock); 366 spin_unlock(&card->files_lock);
368 367
@@ -442,7 +441,7 @@ int snd_card_free_when_closed(struct snd_card *card)
442 return ret; 441 return ret;
443 442
444 spin_lock(&card->files_lock); 443 spin_lock(&card->files_lock);
445 if (card->files == NULL) 444 if (list_empty(&card->files_list))
446 free_now = 1; 445 free_now = 1;
447 else 446 else
448 card->free_on_last_close = 1; 447 card->free_on_last_close = 1;
@@ -462,7 +461,7 @@ int snd_card_free(struct snd_card *card)
462 return ret; 461 return ret;
463 462
464 /* wait, until all devices are ready for the free operation */ 463 /* wait, until all devices are ready for the free operation */
465 wait_event(card->shutdown_sleep, card->files == NULL); 464 wait_event(card->shutdown_sleep, list_empty(&card->files_list));
466 snd_card_do_free(card); 465 snd_card_do_free(card);
467 return 0; 466 return 0;
468} 467}
@@ -809,15 +808,13 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
809 return -ENOMEM; 808 return -ENOMEM;
810 mfile->file = file; 809 mfile->file = file;
811 mfile->disconnected_f_op = NULL; 810 mfile->disconnected_f_op = NULL;
812 mfile->next = NULL;
813 spin_lock(&card->files_lock); 811 spin_lock(&card->files_lock);
814 if (card->shutdown) { 812 if (card->shutdown) {
815 spin_unlock(&card->files_lock); 813 spin_unlock(&card->files_lock);
816 kfree(mfile); 814 kfree(mfile);
817 return -ENODEV; 815 return -ENODEV;
818 } 816 }
819 mfile->next = card->files; 817 list_add(&mfile->list, &card->files_list);
820 card->files = mfile;
821 spin_unlock(&card->files_lock); 818 spin_unlock(&card->files_lock);
822 return 0; 819 return 0;
823} 820}
@@ -839,29 +836,20 @@ EXPORT_SYMBOL(snd_card_file_add);
839 */ 836 */
840int snd_card_file_remove(struct snd_card *card, struct file *file) 837int snd_card_file_remove(struct snd_card *card, struct file *file)
841{ 838{
842 struct snd_monitor_file *mfile, *pfile = NULL; 839 struct snd_monitor_file *mfile, *found = NULL;
843 int last_close = 0; 840 int last_close = 0;
844 841
845 spin_lock(&card->files_lock); 842 spin_lock(&card->files_lock);
846 mfile = card->files; 843 list_for_each_entry(mfile, &card->files_list, list) {
847 while (mfile) {
848 if (mfile->file == file) { 844 if (mfile->file == file) {
849 if (pfile) 845 list_del(&mfile->list);
850 pfile->next = mfile->next; 846 if (mfile->disconnected_f_op)
851 else 847 fops_put(mfile->disconnected_f_op);
852 card->files = mfile->next; 848 found = mfile;
853 break; 849 break;
854 } 850 }
855 pfile = mfile;
856 mfile = mfile->next;
857 }
858 if (mfile && mfile->disconnected_f_op) {
859 fops_put(mfile->disconnected_f_op);
860 spin_lock(&shutdown_lock);
861 list_del(&mfile->shutdown_list);
862 spin_unlock(&shutdown_lock);
863 } 851 }
864 if (card->files == NULL) 852 if (list_empty(&card->files_list))
865 last_close = 1; 853 last_close = 1;
866 spin_unlock(&card->files_lock); 854 spin_unlock(&card->files_lock);
867 if (last_close) { 855 if (last_close) {
@@ -869,11 +857,11 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
869 if (card->free_on_last_close) 857 if (card->free_on_last_close)
870 snd_card_do_free(card); 858 snd_card_do_free(card);
871 } 859 }
872 if (!mfile) { 860 if (!found) {
873 snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); 861 snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
874 return -ENOENT; 862 return -ENOENT;
875 } 863 }
876 kfree(mfile); 864 kfree(found);
877 return 0; 865 return 0;
878} 866}
879 867