diff options
-rw-r--r-- | include/sound/core.h | 6 | ||||
-rw-r--r-- | sound/core/init.c | 42 |
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 | ||
98 | struct snd_monitor_file { | 98 | struct 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 | */ |
840 | int snd_card_file_remove(struct snd_card *card, struct file *file) | 837 | int 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 | ||