diff options
| -rw-r--r-- | Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl | 5 | ||||
| -rw-r--r-- | include/sound/core.h | 3 | ||||
| -rw-r--r-- | sound/core/init.c | 56 | ||||
| -rw-r--r-- | sound/drivers/mpu401/mpu401.c | 2 | ||||
| -rw-r--r-- | sound/pcmcia/pdaudiocf/pdaudiocf.c | 2 | ||||
| -rw-r--r-- | sound/pcmcia/vx/vxpocket.c | 4 |
6 files changed, 9 insertions, 63 deletions
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index b8dc51ca776c..4807ef79a94d 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl | |||
| @@ -1054,9 +1054,8 @@ | |||
| 1054 | 1054 | ||
| 1055 | <para> | 1055 | <para> |
| 1056 | For a device which allows hotplugging, you can use | 1056 | For a device which allows hotplugging, you can use |
| 1057 | <function>snd_card_free_in_thread</function>. This one will | 1057 | <function>snd_card_free_when_closed</function>. This one will |
| 1058 | postpone the destruction and wait in a kernel-thread until all | 1058 | postpone the destruction until all devices are closed. |
| 1059 | devices are closed. | ||
| 1060 | </para> | 1059 | </para> |
| 1061 | 1060 | ||
| 1062 | </section> | 1061 | </section> |
diff --git a/include/sound/core.h b/include/sound/core.h index cf4001cf6248..1359c532b68e 100644 --- a/include/sound/core.h +++ b/include/sound/core.h | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/sched.h> /* wake_up() */ | 25 | #include <linux/sched.h> /* wake_up() */ |
| 26 | #include <linux/mutex.h> /* struct mutex */ | 26 | #include <linux/mutex.h> /* struct mutex */ |
| 27 | #include <linux/rwsem.h> /* struct rw_semaphore */ | 27 | #include <linux/rwsem.h> /* struct rw_semaphore */ |
| 28 | #include <linux/workqueue.h> /* struct workqueue_struct */ | ||
| 29 | #include <linux/pm.h> /* pm_message_t */ | 28 | #include <linux/pm.h> /* pm_message_t */ |
| 30 | 29 | ||
| 31 | /* forward declarations */ | 30 | /* forward declarations */ |
| @@ -132,7 +131,6 @@ struct snd_card { | |||
| 132 | int shutdown; /* this card is going down */ | 131 | int shutdown; /* this card is going down */ |
| 133 | int free_on_last_close; /* free in context of file_release */ | 132 | int free_on_last_close; /* free in context of file_release */ |
| 134 | wait_queue_head_t shutdown_sleep; | 133 | wait_queue_head_t shutdown_sleep; |
| 135 | struct work_struct free_workq; /* for free in workqueue */ | ||
| 136 | struct device *dev; | 134 | struct device *dev; |
| 137 | 135 | ||
| 138 | #ifdef CONFIG_PM | 136 | #ifdef CONFIG_PM |
| @@ -245,7 +243,6 @@ struct snd_card *snd_card_new(int idx, const char *id, | |||
| 245 | int snd_card_disconnect(struct snd_card *card); | 243 | int snd_card_disconnect(struct snd_card *card); |
| 246 | int snd_card_free(struct snd_card *card); | 244 | int snd_card_free(struct snd_card *card); |
| 247 | int snd_card_free_when_closed(struct snd_card *card); | 245 | int snd_card_free_when_closed(struct snd_card *card); |
| 248 | int snd_card_free_in_thread(struct snd_card *card); | ||
| 249 | int snd_card_register(struct snd_card *card); | 246 | int snd_card_register(struct snd_card *card); |
| 250 | int snd_card_info_init(void); | 247 | int snd_card_info_init(void); |
| 251 | int snd_card_info_done(void); | 248 | int snd_card_info_done(void); |
diff --git a/sound/core/init.c b/sound/core/init.c index 5850d99d21e3..d7607a25acdf 100644 --- a/sound/core/init.c +++ b/sound/core/init.c | |||
| @@ -81,8 +81,6 @@ static inline int init_info_for_card(struct snd_card *card) | |||
| 81 | #define init_info_for_card(card) | 81 | #define init_info_for_card(card) |
| 82 | #endif | 82 | #endif |
| 83 | 83 | ||
| 84 | static void snd_card_free_thread(void * __card); | ||
| 85 | |||
| 86 | /** | 84 | /** |
| 87 | * snd_card_new - create and initialize a soundcard structure | 85 | * snd_card_new - create and initialize a soundcard structure |
| 88 | * @idx: card index (address) [0 ... (SNDRV_CARDS-1)] | 86 | * @idx: card index (address) [0 ... (SNDRV_CARDS-1)] |
| @@ -145,7 +143,6 @@ struct snd_card *snd_card_new(int idx, const char *xid, | |||
| 145 | INIT_LIST_HEAD(&card->ctl_files); | 143 | INIT_LIST_HEAD(&card->ctl_files); |
| 146 | spin_lock_init(&card->files_lock); | 144 | spin_lock_init(&card->files_lock); |
| 147 | init_waitqueue_head(&card->shutdown_sleep); | 145 | init_waitqueue_head(&card->shutdown_sleep); |
| 148 | INIT_WORK(&card->free_workq, snd_card_free_thread, card); | ||
| 149 | #ifdef CONFIG_PM | 146 | #ifdef CONFIG_PM |
| 150 | mutex_init(&card->power_lock); | 147 | mutex_init(&card->power_lock); |
| 151 | init_waitqueue_head(&card->power_sleep); | 148 | init_waitqueue_head(&card->power_sleep); |
| @@ -413,53 +410,6 @@ int snd_card_free(struct snd_card *card) | |||
| 413 | 410 | ||
| 414 | EXPORT_SYMBOL(snd_card_free); | 411 | EXPORT_SYMBOL(snd_card_free); |
| 415 | 412 | ||
| 416 | static void snd_card_free_thread(void * __card) | ||
| 417 | { | ||
| 418 | struct snd_card *card = __card; | ||
| 419 | struct module * module = card->module; | ||
| 420 | |||
| 421 | if (!try_module_get(module)) { | ||
| 422 | snd_printk(KERN_ERR "unable to lock toplevel module for card %i in free thread\n", card->number); | ||
| 423 | module = NULL; | ||
| 424 | } | ||
| 425 | |||
| 426 | snd_card_free(card); | ||
| 427 | |||
| 428 | module_put(module); | ||
| 429 | } | ||
| 430 | |||
| 431 | /** | ||
| 432 | * snd_card_free_in_thread - call snd_card_free() in thread | ||
| 433 | * @card: soundcard structure | ||
| 434 | * | ||
| 435 | * This function schedules the call of snd_card_free() function in a | ||
| 436 | * work queue. When all devices are released (non-busy), the work | ||
| 437 | * is woken up and calls snd_card_free(). | ||
| 438 | * | ||
| 439 | * When a card can be disconnected at any time by hotplug service, | ||
| 440 | * this function should be used in disconnect (or detach) callback | ||
| 441 | * instead of calling snd_card_free() directly. | ||
| 442 | * | ||
| 443 | * Returns - zero otherwise a negative error code if the start of thread failed. | ||
| 444 | */ | ||
| 445 | int snd_card_free_in_thread(struct snd_card *card) | ||
| 446 | { | ||
| 447 | if (card->files == NULL) { | ||
| 448 | snd_card_free(card); | ||
| 449 | return 0; | ||
| 450 | } | ||
| 451 | |||
| 452 | if (schedule_work(&card->free_workq)) | ||
| 453 | return 0; | ||
| 454 | |||
| 455 | snd_printk(KERN_ERR "schedule_work() failed in snd_card_free_in_thread for card %i\n", card->number); | ||
| 456 | /* try to free the structure immediately */ | ||
| 457 | snd_card_free(card); | ||
| 458 | return -EFAULT; | ||
| 459 | } | ||
| 460 | |||
| 461 | EXPORT_SYMBOL(snd_card_free_in_thread); | ||
| 462 | |||
| 463 | static void choose_default_id(struct snd_card *card) | 413 | static void choose_default_id(struct snd_card *card) |
| 464 | { | 414 | { |
| 465 | int i, len, idx_flag = 0, loops = SNDRV_CARDS; | 415 | int i, len, idx_flag = 0, loops = SNDRV_CARDS; |
| @@ -742,9 +692,9 @@ EXPORT_SYMBOL(snd_card_file_add); | |||
| 742 | * | 692 | * |
| 743 | * This function removes the file formerly added to the card via | 693 | * This function removes the file formerly added to the card via |
| 744 | * snd_card_file_add() function. | 694 | * snd_card_file_add() function. |
| 745 | * If all files are removed and the release of the card is | 695 | * If all files are removed and snd_card_free_when_closed() was |
| 746 | * scheduled, it will wake up the the thread to call snd_card_free() | 696 | * called beforehand, it processes the pending release of |
| 747 | * (see snd_card_free_in_thread() function). | 697 | * resources. |
| 748 | * | 698 | * |
| 749 | * Returns zero or a negative error code. | 699 | * Returns zero or a negative error code. |
| 750 | */ | 700 | */ |
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 17cc105b26fc..2de181ad0b05 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c | |||
| @@ -211,7 +211,7 @@ static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev) | |||
| 211 | struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev); | 211 | struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev); |
| 212 | 212 | ||
| 213 | snd_card_disconnect(card); | 213 | snd_card_disconnect(card); |
| 214 | snd_card_free_in_thread(card); | 214 | snd_card_free_when_closed(card); |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | static struct pnp_driver snd_mpu401_pnp_driver = { | 217 | static struct pnp_driver snd_mpu401_pnp_driver = { |
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 1c09e5f49da8..fd3590fcaedb 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c | |||
| @@ -206,7 +206,7 @@ static void snd_pdacf_detach(struct pcmcia_device *link) | |||
| 206 | snd_pdacf_powerdown(chip); | 206 | snd_pdacf_powerdown(chip); |
| 207 | chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; /* to be sure */ | 207 | chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; /* to be sure */ |
| 208 | snd_card_disconnect(chip->card); | 208 | snd_card_disconnect(chip->card); |
| 209 | snd_card_free_in_thread(chip->card); | 209 | snd_card_free_when_closed(chip->card); |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | /* | 212 | /* |
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index cafe6640cc1a..76c85cffb40e 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c | |||
| @@ -65,7 +65,7 @@ static void vxpocket_release(struct pcmcia_device *link) | |||
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | /* | 67 | /* |
| 68 | * destructor, called from snd_card_free_in_thread() | 68 | * destructor, called from snd_card_free_when_closed() |
| 69 | */ | 69 | */ |
| 70 | static int snd_vxpocket_dev_free(struct snd_device *device) | 70 | static int snd_vxpocket_dev_free(struct snd_device *device) |
| 71 | { | 71 | { |
| @@ -363,7 +363,7 @@ static void vxpocket_detach(struct pcmcia_device *link) | |||
| 363 | chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */ | 363 | chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */ |
| 364 | snd_card_disconnect(chip->card); | 364 | snd_card_disconnect(chip->card); |
| 365 | vxpocket_release(link); | 365 | vxpocket_release(link); |
| 366 | snd_card_free_in_thread(chip->card); | 366 | snd_card_free_when_closed(chip->card); |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | /* | 369 | /* |
