diff options
author | Dave Airlie <airlied@redhat.com> | 2009-03-28 20:22:18 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-03-28 20:22:18 -0400 |
commit | 90f959bcb386da2c71613dcefc6a285e054a539e (patch) | |
tree | ee3e9dd4111d4aad12e579cb0c2c159114dff263 /sound/core/init.c | |
parent | 41f13fe81dd1b08723ab9f3fc3c7f29cfa81f1a5 (diff) | |
parent | 07d43ba98621f08e252a48c96b258b4d572b0257 (diff) |
drm: merge Linux master into HEAD
Conflicts:
drivers/gpu/drm/drm_info.c
drivers/gpu/drm/drm_proc.c
drivers/gpu/drm/i915/i915_gem_debugfs.c
Diffstat (limited to 'sound/core/init.c')
-rw-r--r-- | sound/core/init.c | 89 |
1 files changed, 46 insertions, 43 deletions
diff --git a/sound/core/init.c b/sound/core/init.c index 0d5520c415d3..fd56afe846ed 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
@@ -121,31 +121,44 @@ static inline int init_info_for_card(struct snd_card *card) | |||
121 | #endif | 121 | #endif |
122 | 122 | ||
123 | /** | 123 | /** |
124 | * snd_card_new - create and initialize a soundcard structure | 124 | * snd_card_create - create and initialize a soundcard structure |
125 | * @idx: card index (address) [0 ... (SNDRV_CARDS-1)] | 125 | * @idx: card index (address) [0 ... (SNDRV_CARDS-1)] |
126 | * @xid: card identification (ASCII string) | 126 | * @xid: card identification (ASCII string) |
127 | * @module: top level module for locking | 127 | * @module: top level module for locking |
128 | * @extra_size: allocate this extra size after the main soundcard structure | 128 | * @extra_size: allocate this extra size after the main soundcard structure |
129 | * @card_ret: the pointer to store the created card instance | ||
129 | * | 130 | * |
130 | * Creates and initializes a soundcard structure. | 131 | * Creates and initializes a soundcard structure. |
131 | * | 132 | * |
132 | * Returns kmallocated snd_card structure. Creates the ALSA control interface | 133 | * The function allocates snd_card instance via kzalloc with the given |
133 | * (which is blocked until snd_card_register function is called). | 134 | * space for the driver to use freely. The allocated struct is stored |
135 | * in the given card_ret pointer. | ||
136 | * | ||
137 | * Returns zero if successful or a negative error code. | ||
134 | */ | 138 | */ |
135 | struct snd_card *snd_card_new(int idx, const char *xid, | 139 | int snd_card_create(int idx, const char *xid, |
136 | struct module *module, int extra_size) | 140 | struct module *module, int extra_size, |
141 | struct snd_card **card_ret) | ||
137 | { | 142 | { |
138 | struct snd_card *card; | 143 | struct snd_card *card; |
139 | int err, idx2; | 144 | int err, idx2; |
140 | 145 | ||
146 | if (snd_BUG_ON(!card_ret)) | ||
147 | return -EINVAL; | ||
148 | *card_ret = NULL; | ||
149 | |||
141 | if (extra_size < 0) | 150 | if (extra_size < 0) |
142 | extra_size = 0; | 151 | extra_size = 0; |
143 | card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); | 152 | card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL); |
144 | if (card == NULL) | 153 | if (!card) |
145 | return NULL; | 154 | return -ENOMEM; |
146 | if (xid) { | 155 | if (xid) { |
147 | if (!snd_info_check_reserved_words(xid)) | 156 | if (!snd_info_check_reserved_words(xid)) { |
157 | snd_printk(KERN_ERR | ||
158 | "given id string '%s' is reserved.\n", xid); | ||
159 | err = -EBUSY; | ||
148 | goto __error; | 160 | goto __error; |
161 | } | ||
149 | strlcpy(card->id, xid, sizeof(card->id)); | 162 | strlcpy(card->id, xid, sizeof(card->id)); |
150 | } | 163 | } |
151 | err = 0; | 164 | err = 0; |
@@ -195,6 +208,7 @@ struct snd_card *snd_card_new(int idx, const char *xid, | |||
195 | INIT_LIST_HEAD(&card->controls); | 208 | INIT_LIST_HEAD(&card->controls); |
196 | INIT_LIST_HEAD(&card->ctl_files); | 209 | INIT_LIST_HEAD(&card->ctl_files); |
197 | spin_lock_init(&card->files_lock); | 210 | spin_lock_init(&card->files_lock); |
211 | INIT_LIST_HEAD(&card->files_list); | ||
198 | init_waitqueue_head(&card->shutdown_sleep); | 212 | init_waitqueue_head(&card->shutdown_sleep); |
199 | #ifdef CONFIG_PM | 213 | #ifdef CONFIG_PM |
200 | mutex_init(&card->power_lock); | 214 | mutex_init(&card->power_lock); |
@@ -202,26 +216,28 @@ struct snd_card *snd_card_new(int idx, const char *xid, | |||
202 | #endif | 216 | #endif |
203 | /* the control interface cannot be accessed from the user space until */ | 217 | /* the control interface cannot be accessed from the user space until */ |
204 | /* snd_cards_bitmask and snd_cards are set with snd_card_register */ | 218 | /* snd_cards_bitmask and snd_cards are set with snd_card_register */ |
205 | if ((err = snd_ctl_create(card)) < 0) { | 219 | err = snd_ctl_create(card); |
206 | snd_printd("unable to register control minors\n"); | 220 | if (err < 0) { |
221 | snd_printk(KERN_ERR "unable to register control minors\n"); | ||
207 | goto __error; | 222 | goto __error; |
208 | } | 223 | } |
209 | if ((err = snd_info_card_create(card)) < 0) { | 224 | err = snd_info_card_create(card); |
210 | snd_printd("unable to create card info\n"); | 225 | if (err < 0) { |
226 | snd_printk(KERN_ERR "unable to create card info\n"); | ||
211 | goto __error_ctl; | 227 | goto __error_ctl; |
212 | } | 228 | } |
213 | if (extra_size > 0) | 229 | if (extra_size > 0) |
214 | card->private_data = (char *)card + sizeof(struct snd_card); | 230 | card->private_data = (char *)card + sizeof(struct snd_card); |
215 | return card; | 231 | *card_ret = card; |
232 | return 0; | ||
216 | 233 | ||
217 | __error_ctl: | 234 | __error_ctl: |
218 | snd_device_free_all(card, SNDRV_DEV_CMD_PRE); | 235 | snd_device_free_all(card, SNDRV_DEV_CMD_PRE); |
219 | __error: | 236 | __error: |
220 | kfree(card); | 237 | kfree(card); |
221 | return NULL; | 238 | return err; |
222 | } | 239 | } |
223 | 240 | EXPORT_SYMBOL(snd_card_create); | |
224 | EXPORT_SYMBOL(snd_card_new); | ||
225 | 241 | ||
226 | /* return non-zero if a card is already locked */ | 242 | /* return non-zero if a card is already locked */ |
227 | int snd_card_locked(int card) | 243 | int snd_card_locked(int card) |
@@ -259,6 +275,7 @@ static int snd_disconnect_release(struct inode *inode, struct file *file) | |||
259 | list_for_each_entry(_df, &shutdown_files, shutdown_list) { | 275 | list_for_each_entry(_df, &shutdown_files, shutdown_list) { |
260 | if (_df->file == file) { | 276 | if (_df->file == file) { |
261 | df = _df; | 277 | df = _df; |
278 | list_del_init(&df->shutdown_list); | ||
262 | break; | 279 | break; |
263 | } | 280 | } |
264 | } | 281 | } |
@@ -347,8 +364,7 @@ int snd_card_disconnect(struct snd_card *card) | |||
347 | /* phase 2: replace file->f_op with special dummy operations */ | 364 | /* phase 2: replace file->f_op with special dummy operations */ |
348 | 365 | ||
349 | spin_lock(&card->files_lock); | 366 | spin_lock(&card->files_lock); |
350 | mfile = card->files; | 367 | list_for_each_entry(mfile, &card->files_list, list) { |
351 | while (mfile) { | ||
352 | file = mfile->file; | 368 | file = mfile->file; |
353 | 369 | ||
354 | /* it's critical part, use endless loop */ | 370 | /* it's critical part, use endless loop */ |
@@ -361,8 +377,6 @@ int snd_card_disconnect(struct snd_card *card) | |||
361 | 377 | ||
362 | mfile->file->f_op = &snd_shutdown_f_ops; | 378 | mfile->file->f_op = &snd_shutdown_f_ops; |
363 | fops_get(mfile->file->f_op); | 379 | fops_get(mfile->file->f_op); |
364 | |||
365 | mfile = mfile->next; | ||
366 | } | 380 | } |
367 | spin_unlock(&card->files_lock); | 381 | spin_unlock(&card->files_lock); |
368 | 382 | ||
@@ -442,7 +456,7 @@ int snd_card_free_when_closed(struct snd_card *card) | |||
442 | return ret; | 456 | return ret; |
443 | 457 | ||
444 | spin_lock(&card->files_lock); | 458 | spin_lock(&card->files_lock); |
445 | if (card->files == NULL) | 459 | if (list_empty(&card->files_list)) |
446 | free_now = 1; | 460 | free_now = 1; |
447 | else | 461 | else |
448 | card->free_on_last_close = 1; | 462 | card->free_on_last_close = 1; |
@@ -462,7 +476,7 @@ int snd_card_free(struct snd_card *card) | |||
462 | return ret; | 476 | return ret; |
463 | 477 | ||
464 | /* wait, until all devices are ready for the free operation */ | 478 | /* wait, until all devices are ready for the free operation */ |
465 | wait_event(card->shutdown_sleep, card->files == NULL); | 479 | wait_event(card->shutdown_sleep, list_empty(&card->files_list)); |
466 | snd_card_do_free(card); | 480 | snd_card_do_free(card); |
467 | return 0; | 481 | return 0; |
468 | } | 482 | } |
@@ -809,15 +823,13 @@ int snd_card_file_add(struct snd_card *card, struct file *file) | |||
809 | return -ENOMEM; | 823 | return -ENOMEM; |
810 | mfile->file = file; | 824 | mfile->file = file; |
811 | mfile->disconnected_f_op = NULL; | 825 | mfile->disconnected_f_op = NULL; |
812 | mfile->next = NULL; | ||
813 | spin_lock(&card->files_lock); | 826 | spin_lock(&card->files_lock); |
814 | if (card->shutdown) { | 827 | if (card->shutdown) { |
815 | spin_unlock(&card->files_lock); | 828 | spin_unlock(&card->files_lock); |
816 | kfree(mfile); | 829 | kfree(mfile); |
817 | return -ENODEV; | 830 | return -ENODEV; |
818 | } | 831 | } |
819 | mfile->next = card->files; | 832 | list_add(&mfile->list, &card->files_list); |
820 | card->files = mfile; | ||
821 | spin_unlock(&card->files_lock); | 833 | spin_unlock(&card->files_lock); |
822 | return 0; | 834 | return 0; |
823 | } | 835 | } |
@@ -839,29 +851,20 @@ EXPORT_SYMBOL(snd_card_file_add); | |||
839 | */ | 851 | */ |
840 | int snd_card_file_remove(struct snd_card *card, struct file *file) | 852 | int snd_card_file_remove(struct snd_card *card, struct file *file) |
841 | { | 853 | { |
842 | struct snd_monitor_file *mfile, *pfile = NULL; | 854 | struct snd_monitor_file *mfile, *found = NULL; |
843 | int last_close = 0; | 855 | int last_close = 0; |
844 | 856 | ||
845 | spin_lock(&card->files_lock); | 857 | spin_lock(&card->files_lock); |
846 | mfile = card->files; | 858 | list_for_each_entry(mfile, &card->files_list, list) { |
847 | while (mfile) { | ||
848 | if (mfile->file == file) { | 859 | if (mfile->file == file) { |
849 | if (pfile) | 860 | list_del(&mfile->list); |
850 | pfile->next = mfile->next; | 861 | if (mfile->disconnected_f_op) |
851 | else | 862 | fops_put(mfile->disconnected_f_op); |
852 | card->files = mfile->next; | 863 | found = mfile; |
853 | break; | 864 | break; |
854 | } | 865 | } |
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 | } | 866 | } |
864 | if (card->files == NULL) | 867 | if (list_empty(&card->files_list)) |
865 | last_close = 1; | 868 | last_close = 1; |
866 | spin_unlock(&card->files_lock); | 869 | spin_unlock(&card->files_lock); |
867 | if (last_close) { | 870 | if (last_close) { |
@@ -869,11 +872,11 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) | |||
869 | if (card->free_on_last_close) | 872 | if (card->free_on_last_close) |
870 | snd_card_do_free(card); | 873 | snd_card_do_free(card); |
871 | } | 874 | } |
872 | if (!mfile) { | 875 | if (!found) { |
873 | snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); | 876 | snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); |
874 | return -ENOENT; | 877 | return -ENOENT; |
875 | } | 878 | } |
876 | kfree(mfile); | 879 | kfree(found); |
877 | return 0; | 880 | return 0; |
878 | } | 881 | } |
879 | 882 | ||