diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-06-23 08:38:23 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-09-23 04:36:58 -0400 |
commit | c461482c8072bb073e6146db320d3da85cdc89ad (patch) | |
tree | 3b69cfd292a488a8cb57ac9b040bd2b1b1a1e26d /sound | |
parent | 746d4a02e68499fc6c1f8d0c43d2271853ade181 (diff) |
[ALSA] Unregister device files at disconnection
Orignally proposed by Sam Revitch <sam.revitch@gmail.com>.
Unregister device files at disconnection to avoid the futher accesses.
Also, the dev_unregister callback is removed and replaced with the
combination of disconnect + free.
A new function snd_card_free_when_closed() is introduced, which is
used in USB disconnect callback.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/control.c | 27 | ||||
-rw-r--r-- | sound/core/device.c | 20 | ||||
-rw-r--r-- | sound/core/hwdep.c | 10 | ||||
-rw-r--r-- | sound/core/init.c | 69 | ||||
-rw-r--r-- | sound/core/oss/mixer_oss.c | 16 | ||||
-rw-r--r-- | sound/core/oss/pcm_oss.c | 16 | ||||
-rw-r--r-- | sound/core/pcm.c | 48 | ||||
-rw-r--r-- | sound/core/rawmidi.c | 35 | ||||
-rw-r--r-- | sound/core/rtctimer.c | 2 | ||||
-rw-r--r-- | sound/core/seq/seq_device.c | 11 | ||||
-rw-r--r-- | sound/core/timer.c | 52 | ||||
-rw-r--r-- | sound/pci/ac97/ac97_codec.c | 8 | ||||
-rw-r--r-- | sound/usb/usbaudio.c | 2 |
13 files changed, 146 insertions, 170 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index e9c8854d2f7b..f0c7272a2d48 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -1375,6 +1375,11 @@ static int snd_ctl_dev_disconnect(struct snd_device *device) | |||
1375 | struct snd_card *card = device->device_data; | 1375 | struct snd_card *card = device->device_data; |
1376 | struct list_head *flist; | 1376 | struct list_head *flist; |
1377 | struct snd_ctl_file *ctl; | 1377 | struct snd_ctl_file *ctl; |
1378 | int err, cardnum; | ||
1379 | |||
1380 | snd_assert(card != NULL, return -ENXIO); | ||
1381 | cardnum = card->number; | ||
1382 | snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); | ||
1378 | 1383 | ||
1379 | down_read(&card->controls_rwsem); | 1384 | down_read(&card->controls_rwsem); |
1380 | list_for_each(flist, &card->ctl_files) { | 1385 | list_for_each(flist, &card->ctl_files) { |
@@ -1383,6 +1388,10 @@ static int snd_ctl_dev_disconnect(struct snd_device *device) | |||
1383 | kill_fasync(&ctl->fasync, SIGIO, POLL_ERR); | 1388 | kill_fasync(&ctl->fasync, SIGIO, POLL_ERR); |
1384 | } | 1389 | } |
1385 | up_read(&card->controls_rwsem); | 1390 | up_read(&card->controls_rwsem); |
1391 | |||
1392 | if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, | ||
1393 | card, -1)) < 0) | ||
1394 | return err; | ||
1386 | return 0; | 1395 | return 0; |
1387 | } | 1396 | } |
1388 | 1397 | ||
@@ -1404,23 +1413,6 @@ static int snd_ctl_dev_free(struct snd_device *device) | |||
1404 | } | 1413 | } |
1405 | 1414 | ||
1406 | /* | 1415 | /* |
1407 | * de-registration of the control device | ||
1408 | */ | ||
1409 | static int snd_ctl_dev_unregister(struct snd_device *device) | ||
1410 | { | ||
1411 | struct snd_card *card = device->device_data; | ||
1412 | int err, cardnum; | ||
1413 | |||
1414 | snd_assert(card != NULL, return -ENXIO); | ||
1415 | cardnum = card->number; | ||
1416 | snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); | ||
1417 | if ((err = snd_unregister_device(SNDRV_DEVICE_TYPE_CONTROL, | ||
1418 | card, -1)) < 0) | ||
1419 | return err; | ||
1420 | return snd_ctl_dev_free(device); | ||
1421 | } | ||
1422 | |||
1423 | /* | ||
1424 | * create control core: | 1416 | * create control core: |
1425 | * called from init.c | 1417 | * called from init.c |
1426 | */ | 1418 | */ |
@@ -1430,7 +1422,6 @@ int snd_ctl_create(struct snd_card *card) | |||
1430 | .dev_free = snd_ctl_dev_free, | 1422 | .dev_free = snd_ctl_dev_free, |
1431 | .dev_register = snd_ctl_dev_register, | 1423 | .dev_register = snd_ctl_dev_register, |
1432 | .dev_disconnect = snd_ctl_dev_disconnect, | 1424 | .dev_disconnect = snd_ctl_dev_disconnect, |
1433 | .dev_unregister = snd_ctl_dev_unregister | ||
1434 | }; | 1425 | }; |
1435 | 1426 | ||
1436 | snd_assert(card != NULL, return -ENXIO); | 1427 | snd_assert(card != NULL, return -ENXIO); |
diff --git a/sound/core/device.c b/sound/core/device.c index 6ce4da4a1081..ccb25816ac9e 100644 --- a/sound/core/device.c +++ b/sound/core/device.c | |||
@@ -71,7 +71,7 @@ EXPORT_SYMBOL(snd_device_new); | |||
71 | * @device_data: the data pointer to release | 71 | * @device_data: the data pointer to release |
72 | * | 72 | * |
73 | * Removes the device from the list on the card and invokes the | 73 | * Removes the device from the list on the card and invokes the |
74 | * callback, dev_unregister or dev_free, corresponding to the state. | 74 | * callbacks, dev_disconnect and dev_free, corresponding to the state. |
75 | * Then release the device. | 75 | * Then release the device. |
76 | * | 76 | * |
77 | * Returns zero if successful, or a negative error code on failure or if the | 77 | * Returns zero if successful, or a negative error code on failure or if the |
@@ -90,16 +90,14 @@ int snd_device_free(struct snd_card *card, void *device_data) | |||
90 | continue; | 90 | continue; |
91 | /* unlink */ | 91 | /* unlink */ |
92 | list_del(&dev->list); | 92 | list_del(&dev->list); |
93 | if ((dev->state == SNDRV_DEV_REGISTERED || | 93 | if (dev->state == SNDRV_DEV_REGISTERED && |
94 | dev->state == SNDRV_DEV_DISCONNECTED) && | 94 | dev->ops->dev_disconnect) |
95 | dev->ops->dev_unregister) { | 95 | if (dev->ops->dev_disconnect(dev)) |
96 | if (dev->ops->dev_unregister(dev)) | 96 | snd_printk(KERN_ERR |
97 | snd_printk(KERN_ERR "device unregister failure\n"); | 97 | "device disconnect failure\n"); |
98 | } else { | 98 | if (dev->ops->dev_free) { |
99 | if (dev->ops->dev_free) { | 99 | if (dev->ops->dev_free(dev)) |
100 | if (dev->ops->dev_free(dev)) | 100 | snd_printk(KERN_ERR "device free failure\n"); |
101 | snd_printk(KERN_ERR "device free failure\n"); | ||
102 | } | ||
103 | } | 101 | } |
104 | kfree(dev); | 102 | kfree(dev); |
105 | return 0; | 103 | return 0; |
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index cbd8a63282b6..9aa9d94891f0 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c | |||
@@ -42,7 +42,7 @@ static DEFINE_MUTEX(register_mutex); | |||
42 | static int snd_hwdep_free(struct snd_hwdep *hwdep); | 42 | static int snd_hwdep_free(struct snd_hwdep *hwdep); |
43 | static int snd_hwdep_dev_free(struct snd_device *device); | 43 | static int snd_hwdep_dev_free(struct snd_device *device); |
44 | static int snd_hwdep_dev_register(struct snd_device *device); | 44 | static int snd_hwdep_dev_register(struct snd_device *device); |
45 | static int snd_hwdep_dev_unregister(struct snd_device *device); | 45 | static int snd_hwdep_dev_disconnect(struct snd_device *device); |
46 | 46 | ||
47 | 47 | ||
48 | static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device) | 48 | static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device) |
@@ -353,7 +353,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device, | |||
353 | static struct snd_device_ops ops = { | 353 | static struct snd_device_ops ops = { |
354 | .dev_free = snd_hwdep_dev_free, | 354 | .dev_free = snd_hwdep_dev_free, |
355 | .dev_register = snd_hwdep_dev_register, | 355 | .dev_register = snd_hwdep_dev_register, |
356 | .dev_unregister = snd_hwdep_dev_unregister | 356 | .dev_disconnect = snd_hwdep_dev_disconnect, |
357 | }; | 357 | }; |
358 | 358 | ||
359 | snd_assert(rhwdep != NULL, return -EINVAL); | 359 | snd_assert(rhwdep != NULL, return -EINVAL); |
@@ -439,7 +439,7 @@ static int snd_hwdep_dev_register(struct snd_device *device) | |||
439 | return 0; | 439 | return 0; |
440 | } | 440 | } |
441 | 441 | ||
442 | static int snd_hwdep_dev_unregister(struct snd_device *device) | 442 | static int snd_hwdep_dev_disconnect(struct snd_device *device) |
443 | { | 443 | { |
444 | struct snd_hwdep *hwdep = device->device_data; | 444 | struct snd_hwdep *hwdep = device->device_data; |
445 | 445 | ||
@@ -454,9 +454,9 @@ static int snd_hwdep_dev_unregister(struct snd_device *device) | |||
454 | snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); | 454 | snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); |
455 | #endif | 455 | #endif |
456 | snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); | 456 | snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); |
457 | list_del(&hwdep->list); | 457 | list_del_init(&hwdep->list); |
458 | mutex_unlock(®ister_mutex); | 458 | mutex_unlock(®ister_mutex); |
459 | return snd_hwdep_free(hwdep); | 459 | return 0; |
460 | } | 460 | } |
461 | 461 | ||
462 | #ifdef CONFIG_PROC_FS | 462 | #ifdef CONFIG_PROC_FS |
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 | */ |
330 | int snd_card_free(struct snd_card *card) | 330 | static 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 | |||
366 | static 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 | |||
381 | int 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 | |||
400 | EXPORT_SYMBOL(snd_card_free_when_closed); | ||
401 | |||
402 | int 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); | |||
718 | int snd_card_file_remove(struct snd_card *card, struct file *file) | 751 | int 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; |
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 00c95def95aa..f4c67042e3ac 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
@@ -1310,21 +1310,19 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd) | |||
1310 | card->mixer_oss = mixer; | 1310 | card->mixer_oss = mixer; |
1311 | snd_mixer_oss_build(mixer); | 1311 | snd_mixer_oss_build(mixer); |
1312 | snd_mixer_oss_proc_init(mixer); | 1312 | snd_mixer_oss_proc_init(mixer); |
1313 | } else if (cmd == SND_MIXER_OSS_NOTIFY_DISCONNECT) { | 1313 | } else { |
1314 | mixer = card->mixer_oss; | ||
1315 | if (mixer == NULL || !mixer->oss_dev_alloc) | ||
1316 | return 0; | ||
1317 | snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0); | ||
1318 | mixer->oss_dev_alloc = 0; | ||
1319 | } else { /* free */ | ||
1320 | mixer = card->mixer_oss; | 1314 | mixer = card->mixer_oss; |
1321 | if (mixer == NULL) | 1315 | if (mixer == NULL) |
1322 | return 0; | 1316 | return 0; |
1317 | if (mixer->oss_dev_alloc) { | ||
1323 | #ifdef SNDRV_OSS_INFO_DEV_MIXERS | 1318 | #ifdef SNDRV_OSS_INFO_DEV_MIXERS |
1324 | snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIXERS, mixer->card->number); | 1319 | snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIXERS, mixer->card->number); |
1325 | #endif | 1320 | #endif |
1326 | if (mixer->oss_dev_alloc) | ||
1327 | snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0); | 1321 | snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0); |
1322 | mixer->oss_dev_alloc = 0; | ||
1323 | } | ||
1324 | if (cmd == SND_MIXER_OSS_NOTIFY_DISCONNECT) | ||
1325 | return 0; | ||
1328 | snd_mixer_oss_proc_done(mixer); | 1326 | snd_mixer_oss_proc_done(mixer); |
1329 | return snd_mixer_oss_free1(mixer); | 1327 | return snd_mixer_oss_free1(mixer); |
1330 | } | 1328 | } |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index a92b93e5ebd5..505b23ec4058 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -2929,25 +2929,23 @@ static int snd_pcm_oss_disconnect_minor(struct snd_pcm *pcm) | |||
2929 | snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, | 2929 | snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_PCM, |
2930 | pcm->card, 1); | 2930 | pcm->card, 1); |
2931 | } | 2931 | } |
2932 | } | ||
2933 | return 0; | ||
2934 | } | ||
2935 | |||
2936 | static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm) | ||
2937 | { | ||
2938 | snd_pcm_oss_disconnect_minor(pcm); | ||
2939 | if (pcm->oss.reg) { | ||
2940 | if (dsp_map[pcm->card->number] == (int)pcm->device) { | 2932 | if (dsp_map[pcm->card->number] == (int)pcm->device) { |
2941 | #ifdef SNDRV_OSS_INFO_DEV_AUDIO | 2933 | #ifdef SNDRV_OSS_INFO_DEV_AUDIO |
2942 | snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number); | 2934 | snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_AUDIO, pcm->card->number); |
2943 | #endif | 2935 | #endif |
2944 | } | 2936 | } |
2945 | pcm->oss.reg = 0; | 2937 | pcm->oss.reg = 0; |
2946 | snd_pcm_oss_proc_done(pcm); | ||
2947 | } | 2938 | } |
2948 | return 0; | 2939 | return 0; |
2949 | } | 2940 | } |
2950 | 2941 | ||
2942 | static int snd_pcm_oss_unregister_minor(struct snd_pcm *pcm) | ||
2943 | { | ||
2944 | snd_pcm_oss_disconnect_minor(pcm); | ||
2945 | snd_pcm_oss_proc_done(pcm); | ||
2946 | return 0; | ||
2947 | } | ||
2948 | |||
2951 | static struct snd_pcm_notify snd_pcm_oss_notify = | 2949 | static struct snd_pcm_notify snd_pcm_oss_notify = |
2952 | { | 2950 | { |
2953 | .n_register = snd_pcm_oss_register_minor, | 2951 | .n_register = snd_pcm_oss_register_minor, |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index b8602471f7e5..f52178abf120 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -42,7 +42,6 @@ static int snd_pcm_free(struct snd_pcm *pcm); | |||
42 | static int snd_pcm_dev_free(struct snd_device *device); | 42 | static int snd_pcm_dev_free(struct snd_device *device); |
43 | static int snd_pcm_dev_register(struct snd_device *device); | 43 | static int snd_pcm_dev_register(struct snd_device *device); |
44 | static int snd_pcm_dev_disconnect(struct snd_device *device); | 44 | static int snd_pcm_dev_disconnect(struct snd_device *device); |
45 | static int snd_pcm_dev_unregister(struct snd_device *device); | ||
46 | 45 | ||
47 | static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) | 46 | static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) |
48 | { | 47 | { |
@@ -680,7 +679,6 @@ int snd_pcm_new(struct snd_card *card, char *id, int device, | |||
680 | .dev_free = snd_pcm_dev_free, | 679 | .dev_free = snd_pcm_dev_free, |
681 | .dev_register = snd_pcm_dev_register, | 680 | .dev_register = snd_pcm_dev_register, |
682 | .dev_disconnect = snd_pcm_dev_disconnect, | 681 | .dev_disconnect = snd_pcm_dev_disconnect, |
683 | .dev_unregister = snd_pcm_dev_unregister | ||
684 | }; | 682 | }; |
685 | 683 | ||
686 | snd_assert(rpcm != NULL, return -EINVAL); | 684 | snd_assert(rpcm != NULL, return -EINVAL); |
@@ -724,6 +722,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr) | |||
724 | substream = pstr->substream; | 722 | substream = pstr->substream; |
725 | while (substream) { | 723 | while (substream) { |
726 | substream_next = substream->next; | 724 | substream_next = substream->next; |
725 | snd_pcm_timer_done(substream); | ||
727 | snd_pcm_substream_proc_done(substream); | 726 | snd_pcm_substream_proc_done(substream); |
728 | kfree(substream); | 727 | kfree(substream); |
729 | substream = substream_next; | 728 | substream = substream_next; |
@@ -740,7 +739,12 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr) | |||
740 | 739 | ||
741 | static int snd_pcm_free(struct snd_pcm *pcm) | 740 | static int snd_pcm_free(struct snd_pcm *pcm) |
742 | { | 741 | { |
742 | struct snd_pcm_notify *notify; | ||
743 | |||
743 | snd_assert(pcm != NULL, return -ENXIO); | 744 | snd_assert(pcm != NULL, return -ENXIO); |
745 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { | ||
746 | notify->n_unregister(pcm); | ||
747 | } | ||
744 | if (pcm->private_free) | 748 | if (pcm->private_free) |
745 | pcm->private_free(pcm); | 749 | pcm->private_free(pcm); |
746 | snd_pcm_lib_preallocate_free_for_all(pcm); | 750 | snd_pcm_lib_preallocate_free_for_all(pcm); |
@@ -955,35 +959,22 @@ static int snd_pcm_dev_register(struct snd_device *device) | |||
955 | static int snd_pcm_dev_disconnect(struct snd_device *device) | 959 | static int snd_pcm_dev_disconnect(struct snd_device *device) |
956 | { | 960 | { |
957 | struct snd_pcm *pcm = device->device_data; | 961 | struct snd_pcm *pcm = device->device_data; |
958 | struct list_head *list; | 962 | struct snd_pcm_notify *notify; |
959 | struct snd_pcm_substream *substream; | 963 | struct snd_pcm_substream *substream; |
960 | int cidx; | 964 | int cidx, devtype; |
961 | 965 | ||
962 | mutex_lock(®ister_mutex); | 966 | mutex_lock(®ister_mutex); |
967 | if (list_empty(&pcm->list)) | ||
968 | goto unlock; | ||
969 | |||
963 | list_del_init(&pcm->list); | 970 | list_del_init(&pcm->list); |
964 | for (cidx = 0; cidx < 2; cidx++) | 971 | for (cidx = 0; cidx < 2; cidx++) |
965 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) | 972 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) |
966 | if (substream->runtime) | 973 | if (substream->runtime) |
967 | substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; | 974 | substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; |
968 | list_for_each(list, &snd_pcm_notify_list) { | 975 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { |
969 | struct snd_pcm_notify *notify; | ||
970 | notify = list_entry(list, struct snd_pcm_notify, list); | ||
971 | notify->n_disconnect(pcm); | 976 | notify->n_disconnect(pcm); |
972 | } | 977 | } |
973 | mutex_unlock(®ister_mutex); | ||
974 | return 0; | ||
975 | } | ||
976 | |||
977 | static int snd_pcm_dev_unregister(struct snd_device *device) | ||
978 | { | ||
979 | int cidx, devtype; | ||
980 | struct snd_pcm_substream *substream; | ||
981 | struct list_head *list; | ||
982 | struct snd_pcm *pcm = device->device_data; | ||
983 | |||
984 | snd_assert(pcm != NULL, return -ENXIO); | ||
985 | mutex_lock(®ister_mutex); | ||
986 | list_del(&pcm->list); | ||
987 | for (cidx = 0; cidx < 2; cidx++) { | 978 | for (cidx = 0; cidx < 2; cidx++) { |
988 | devtype = -1; | 979 | devtype = -1; |
989 | switch (cidx) { | 980 | switch (cidx) { |
@@ -995,23 +986,20 @@ static int snd_pcm_dev_unregister(struct snd_device *device) | |||
995 | break; | 986 | break; |
996 | } | 987 | } |
997 | snd_unregister_device(devtype, pcm->card, pcm->device); | 988 | snd_unregister_device(devtype, pcm->card, pcm->device); |
998 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) | ||
999 | snd_pcm_timer_done(substream); | ||
1000 | } | ||
1001 | list_for_each(list, &snd_pcm_notify_list) { | ||
1002 | struct snd_pcm_notify *notify; | ||
1003 | notify = list_entry(list, struct snd_pcm_notify, list); | ||
1004 | notify->n_unregister(pcm); | ||
1005 | } | 989 | } |
990 | unlock: | ||
1006 | mutex_unlock(®ister_mutex); | 991 | mutex_unlock(®ister_mutex); |
1007 | return snd_pcm_free(pcm); | 992 | return 0; |
1008 | } | 993 | } |
1009 | 994 | ||
1010 | int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) | 995 | int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) |
1011 | { | 996 | { |
1012 | struct list_head *p; | 997 | struct list_head *p; |
1013 | 998 | ||
1014 | snd_assert(notify != NULL && notify->n_register != NULL && notify->n_unregister != NULL, return -EINVAL); | 999 | snd_assert(notify != NULL && |
1000 | notify->n_register != NULL && | ||
1001 | notify->n_unregister != NULL && | ||
1002 | notify->n_disconnect, return -EINVAL); | ||
1015 | mutex_lock(®ister_mutex); | 1003 | mutex_lock(®ister_mutex); |
1016 | if (nfree) { | 1004 | if (nfree) { |
1017 | list_del(¬ify->list); | 1005 | list_del(¬ify->list); |
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 51577c22f8ce..8a2bdfae63e3 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
@@ -55,7 +55,6 @@ static int snd_rawmidi_free(struct snd_rawmidi *rawmidi); | |||
55 | static int snd_rawmidi_dev_free(struct snd_device *device); | 55 | static int snd_rawmidi_dev_free(struct snd_device *device); |
56 | static int snd_rawmidi_dev_register(struct snd_device *device); | 56 | static int snd_rawmidi_dev_register(struct snd_device *device); |
57 | static int snd_rawmidi_dev_disconnect(struct snd_device *device); | 57 | static int snd_rawmidi_dev_disconnect(struct snd_device *device); |
58 | static int snd_rawmidi_dev_unregister(struct snd_device *device); | ||
59 | 58 | ||
60 | static LIST_HEAD(snd_rawmidi_devices); | 59 | static LIST_HEAD(snd_rawmidi_devices); |
61 | static DEFINE_MUTEX(register_mutex); | 60 | static DEFINE_MUTEX(register_mutex); |
@@ -1426,7 +1425,6 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device, | |||
1426 | .dev_free = snd_rawmidi_dev_free, | 1425 | .dev_free = snd_rawmidi_dev_free, |
1427 | .dev_register = snd_rawmidi_dev_register, | 1426 | .dev_register = snd_rawmidi_dev_register, |
1428 | .dev_disconnect = snd_rawmidi_dev_disconnect, | 1427 | .dev_disconnect = snd_rawmidi_dev_disconnect, |
1429 | .dev_unregister = snd_rawmidi_dev_unregister | ||
1430 | }; | 1428 | }; |
1431 | 1429 | ||
1432 | snd_assert(rrawmidi != NULL, return -EINVAL); | 1430 | snd_assert(rrawmidi != NULL, return -EINVAL); |
@@ -1479,6 +1477,14 @@ static void snd_rawmidi_free_substreams(struct snd_rawmidi_str *stream) | |||
1479 | static int snd_rawmidi_free(struct snd_rawmidi *rmidi) | 1477 | static int snd_rawmidi_free(struct snd_rawmidi *rmidi) |
1480 | { | 1478 | { |
1481 | snd_assert(rmidi != NULL, return -ENXIO); | 1479 | snd_assert(rmidi != NULL, return -ENXIO); |
1480 | |||
1481 | snd_info_free_entry(rmidi->proc_entry); | ||
1482 | rmidi->proc_entry = NULL; | ||
1483 | mutex_lock(®ister_mutex); | ||
1484 | if (rmidi->ops && rmidi->ops->dev_unregister) | ||
1485 | rmidi->ops->dev_unregister(rmidi); | ||
1486 | mutex_unlock(®ister_mutex); | ||
1487 | |||
1482 | snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); | 1488 | snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); |
1483 | snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); | 1489 | snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); |
1484 | if (rmidi->private_free) | 1490 | if (rmidi->private_free) |
@@ -1587,21 +1593,6 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) | |||
1587 | 1593 | ||
1588 | mutex_lock(®ister_mutex); | 1594 | mutex_lock(®ister_mutex); |
1589 | list_del_init(&rmidi->list); | 1595 | list_del_init(&rmidi->list); |
1590 | mutex_unlock(®ister_mutex); | ||
1591 | return 0; | ||
1592 | } | ||
1593 | |||
1594 | static int snd_rawmidi_dev_unregister(struct snd_device *device) | ||
1595 | { | ||
1596 | struct snd_rawmidi *rmidi = device->device_data; | ||
1597 | |||
1598 | snd_assert(rmidi != NULL, return -ENXIO); | ||
1599 | mutex_lock(®ister_mutex); | ||
1600 | list_del(&rmidi->list); | ||
1601 | if (rmidi->proc_entry) { | ||
1602 | snd_info_free_entry(rmidi->proc_entry); | ||
1603 | rmidi->proc_entry = NULL; | ||
1604 | } | ||
1605 | #ifdef CONFIG_SND_OSSEMUL | 1596 | #ifdef CONFIG_SND_OSSEMUL |
1606 | if (rmidi->ossreg) { | 1597 | if (rmidi->ossreg) { |
1607 | if ((int)rmidi->device == midi_map[rmidi->card->number]) { | 1598 | if ((int)rmidi->device == midi_map[rmidi->card->number]) { |
@@ -1615,17 +1606,9 @@ static int snd_rawmidi_dev_unregister(struct snd_device *device) | |||
1615 | rmidi->ossreg = 0; | 1606 | rmidi->ossreg = 0; |
1616 | } | 1607 | } |
1617 | #endif /* CONFIG_SND_OSSEMUL */ | 1608 | #endif /* CONFIG_SND_OSSEMUL */ |
1618 | if (rmidi->ops && rmidi->ops->dev_unregister) | ||
1619 | rmidi->ops->dev_unregister(rmidi); | ||
1620 | snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); | 1609 | snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); |
1621 | mutex_unlock(®ister_mutex); | 1610 | mutex_unlock(®ister_mutex); |
1622 | #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)) | 1611 | return 0; |
1623 | if (rmidi->seq_dev) { | ||
1624 | snd_device_free(rmidi->card, rmidi->seq_dev); | ||
1625 | rmidi->seq_dev = NULL; | ||
1626 | } | ||
1627 | #endif | ||
1628 | return snd_rawmidi_free(rmidi); | ||
1629 | } | 1612 | } |
1630 | 1613 | ||
1631 | /** | 1614 | /** |
diff --git a/sound/core/rtctimer.c b/sound/core/rtctimer.c index 84704ccb1829..412dd62b654e 100644 --- a/sound/core/rtctimer.c +++ b/sound/core/rtctimer.c | |||
@@ -156,7 +156,7 @@ static int __init rtctimer_init(void) | |||
156 | static void __exit rtctimer_exit(void) | 156 | static void __exit rtctimer_exit(void) |
157 | { | 157 | { |
158 | if (rtctimer) { | 158 | if (rtctimer) { |
159 | snd_timer_global_unregister(rtctimer); | 159 | snd_timer_global_free(rtctimer); |
160 | rtctimer = NULL; | 160 | rtctimer = NULL; |
161 | } | 161 | } |
162 | } | 162 | } |
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c index b85954e956d4..b79d011813c0 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq/seq_device.c | |||
@@ -90,7 +90,6 @@ static int snd_seq_device_free(struct snd_seq_device *dev); | |||
90 | static int snd_seq_device_dev_free(struct snd_device *device); | 90 | static int snd_seq_device_dev_free(struct snd_device *device); |
91 | static int snd_seq_device_dev_register(struct snd_device *device); | 91 | static int snd_seq_device_dev_register(struct snd_device *device); |
92 | static int snd_seq_device_dev_disconnect(struct snd_device *device); | 92 | static int snd_seq_device_dev_disconnect(struct snd_device *device); |
93 | static int snd_seq_device_dev_unregister(struct snd_device *device); | ||
94 | 93 | ||
95 | static int init_device(struct snd_seq_device *dev, struct ops_list *ops); | 94 | static int init_device(struct snd_seq_device *dev, struct ops_list *ops); |
96 | static int free_device(struct snd_seq_device *dev, struct ops_list *ops); | 95 | static int free_device(struct snd_seq_device *dev, struct ops_list *ops); |
@@ -189,7 +188,6 @@ int snd_seq_device_new(struct snd_card *card, int device, char *id, int argsize, | |||
189 | .dev_free = snd_seq_device_dev_free, | 188 | .dev_free = snd_seq_device_dev_free, |
190 | .dev_register = snd_seq_device_dev_register, | 189 | .dev_register = snd_seq_device_dev_register, |
191 | .dev_disconnect = snd_seq_device_dev_disconnect, | 190 | .dev_disconnect = snd_seq_device_dev_disconnect, |
192 | .dev_unregister = snd_seq_device_dev_unregister | ||
193 | }; | 191 | }; |
194 | 192 | ||
195 | if (result) | 193 | if (result) |
@@ -309,15 +307,6 @@ static int snd_seq_device_dev_disconnect(struct snd_device *device) | |||
309 | } | 307 | } |
310 | 308 | ||
311 | /* | 309 | /* |
312 | * unregister the existing device | ||
313 | */ | ||
314 | static int snd_seq_device_dev_unregister(struct snd_device *device) | ||
315 | { | ||
316 | struct snd_seq_device *dev = device->device_data; | ||
317 | return snd_seq_device_free(dev); | ||
318 | } | ||
319 | |||
320 | /* | ||
321 | * register device driver | 310 | * register device driver |
322 | * id = driver id | 311 | * id = driver id |
323 | * entry = driver operators - duplicated to each instance | 312 | * entry = driver operators - duplicated to each instance |
diff --git a/sound/core/timer.c b/sound/core/timer.c index 52ecbe1e9abb..7e5e562fe356 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -88,7 +88,7 @@ static DEFINE_MUTEX(register_mutex); | |||
88 | static int snd_timer_free(struct snd_timer *timer); | 88 | static int snd_timer_free(struct snd_timer *timer); |
89 | static int snd_timer_dev_free(struct snd_device *device); | 89 | static int snd_timer_dev_free(struct snd_device *device); |
90 | static int snd_timer_dev_register(struct snd_device *device); | 90 | static int snd_timer_dev_register(struct snd_device *device); |
91 | static int snd_timer_dev_unregister(struct snd_device *device); | 91 | static int snd_timer_dev_disconnect(struct snd_device *device); |
92 | 92 | ||
93 | static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left); | 93 | static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_left); |
94 | 94 | ||
@@ -773,7 +773,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, | |||
773 | static struct snd_device_ops ops = { | 773 | static struct snd_device_ops ops = { |
774 | .dev_free = snd_timer_dev_free, | 774 | .dev_free = snd_timer_dev_free, |
775 | .dev_register = snd_timer_dev_register, | 775 | .dev_register = snd_timer_dev_register, |
776 | .dev_unregister = snd_timer_dev_unregister | 776 | .dev_disconnect = snd_timer_dev_disconnect, |
777 | }; | 777 | }; |
778 | 778 | ||
779 | snd_assert(tid != NULL, return -EINVAL); | 779 | snd_assert(tid != NULL, return -EINVAL); |
@@ -813,6 +813,21 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, | |||
813 | static int snd_timer_free(struct snd_timer *timer) | 813 | static int snd_timer_free(struct snd_timer *timer) |
814 | { | 814 | { |
815 | snd_assert(timer != NULL, return -ENXIO); | 815 | snd_assert(timer != NULL, return -ENXIO); |
816 | |||
817 | mutex_lock(®ister_mutex); | ||
818 | if (! list_empty(&timer->open_list_head)) { | ||
819 | struct list_head *p, *n; | ||
820 | struct snd_timer_instance *ti; | ||
821 | snd_printk(KERN_WARNING "timer %p is busy?\n", timer); | ||
822 | list_for_each_safe(p, n, &timer->open_list_head) { | ||
823 | list_del_init(p); | ||
824 | ti = list_entry(p, struct snd_timer_instance, open_list); | ||
825 | ti->timer = NULL; | ||
826 | } | ||
827 | } | ||
828 | list_del(&timer->device_list); | ||
829 | mutex_unlock(®ister_mutex); | ||
830 | |||
816 | if (timer->private_free) | 831 | if (timer->private_free) |
817 | timer->private_free(timer); | 832 | timer->private_free(timer); |
818 | kfree(timer); | 833 | kfree(timer); |
@@ -867,30 +882,13 @@ static int snd_timer_dev_register(struct snd_device *dev) | |||
867 | return 0; | 882 | return 0; |
868 | } | 883 | } |
869 | 884 | ||
870 | static int snd_timer_unregister(struct snd_timer *timer) | 885 | static int snd_timer_dev_disconnect(struct snd_device *device) |
871 | { | 886 | { |
872 | struct list_head *p, *n; | 887 | struct snd_timer *timer = device->device_data; |
873 | struct snd_timer_instance *ti; | ||
874 | |||
875 | snd_assert(timer != NULL, return -ENXIO); | ||
876 | mutex_lock(®ister_mutex); | 888 | mutex_lock(®ister_mutex); |
877 | if (! list_empty(&timer->open_list_head)) { | 889 | list_del_init(&timer->device_list); |
878 | snd_printk(KERN_WARNING "timer 0x%lx is busy?\n", (long)timer); | ||
879 | list_for_each_safe(p, n, &timer->open_list_head) { | ||
880 | list_del_init(p); | ||
881 | ti = list_entry(p, struct snd_timer_instance, open_list); | ||
882 | ti->timer = NULL; | ||
883 | } | ||
884 | } | ||
885 | list_del(&timer->device_list); | ||
886 | mutex_unlock(®ister_mutex); | 890 | mutex_unlock(®ister_mutex); |
887 | return snd_timer_free(timer); | 891 | return 0; |
888 | } | ||
889 | |||
890 | static int snd_timer_dev_unregister(struct snd_device *device) | ||
891 | { | ||
892 | struct snd_timer *timer = device->device_data; | ||
893 | return snd_timer_unregister(timer); | ||
894 | } | 892 | } |
895 | 893 | ||
896 | void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp) | 894 | void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp) |
@@ -955,11 +953,6 @@ int snd_timer_global_register(struct snd_timer *timer) | |||
955 | return snd_timer_dev_register(&dev); | 953 | return snd_timer_dev_register(&dev); |
956 | } | 954 | } |
957 | 955 | ||
958 | int snd_timer_global_unregister(struct snd_timer *timer) | ||
959 | { | ||
960 | return snd_timer_unregister(timer); | ||
961 | } | ||
962 | |||
963 | /* | 956 | /* |
964 | * System timer | 957 | * System timer |
965 | */ | 958 | */ |
@@ -1982,7 +1975,7 @@ static void __exit alsa_timer_exit(void) | |||
1982 | /* unregister the system timer */ | 1975 | /* unregister the system timer */ |
1983 | list_for_each_safe(p, n, &snd_timer_list) { | 1976 | list_for_each_safe(p, n, &snd_timer_list) { |
1984 | struct snd_timer *timer = list_entry(p, struct snd_timer, device_list); | 1977 | struct snd_timer *timer = list_entry(p, struct snd_timer, device_list); |
1985 | snd_timer_unregister(timer); | 1978 | snd_timer_free(timer); |
1986 | } | 1979 | } |
1987 | snd_timer_proc_done(); | 1980 | snd_timer_proc_done(); |
1988 | #ifdef SNDRV_OSS_INFO_DEV_TIMERS | 1981 | #ifdef SNDRV_OSS_INFO_DEV_TIMERS |
@@ -2005,5 +1998,4 @@ EXPORT_SYMBOL(snd_timer_notify); | |||
2005 | EXPORT_SYMBOL(snd_timer_global_new); | 1998 | EXPORT_SYMBOL(snd_timer_global_new); |
2006 | EXPORT_SYMBOL(snd_timer_global_free); | 1999 | EXPORT_SYMBOL(snd_timer_global_free); |
2007 | EXPORT_SYMBOL(snd_timer_global_register); | 2000 | EXPORT_SYMBOL(snd_timer_global_register); |
2008 | EXPORT_SYMBOL(snd_timer_global_unregister); | ||
2009 | EXPORT_SYMBOL(snd_timer_interrupt); | 2001 | EXPORT_SYMBOL(snd_timer_interrupt); |
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 51e83d7a839a..b35280ca2465 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c | |||
@@ -1817,13 +1817,13 @@ static int snd_ac97_dev_register(struct snd_device *device) | |||
1817 | return 0; | 1817 | return 0; |
1818 | } | 1818 | } |
1819 | 1819 | ||
1820 | /* unregister ac97 codec */ | 1820 | /* disconnect ac97 codec */ |
1821 | static int snd_ac97_dev_unregister(struct snd_device *device) | 1821 | static int snd_ac97_dev_disconnect(struct snd_device *device) |
1822 | { | 1822 | { |
1823 | struct snd_ac97 *ac97 = device->device_data; | 1823 | struct snd_ac97 *ac97 = device->device_data; |
1824 | if (ac97->dev.bus) | 1824 | if (ac97->dev.bus) |
1825 | device_unregister(&ac97->dev); | 1825 | device_unregister(&ac97->dev); |
1826 | return snd_ac97_free(ac97); | 1826 | return 0; |
1827 | } | 1827 | } |
1828 | 1828 | ||
1829 | /* build_ops to do nothing */ | 1829 | /* build_ops to do nothing */ |
@@ -1860,7 +1860,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, | |||
1860 | static struct snd_device_ops ops = { | 1860 | static struct snd_device_ops ops = { |
1861 | .dev_free = snd_ac97_dev_free, | 1861 | .dev_free = snd_ac97_dev_free, |
1862 | .dev_register = snd_ac97_dev_register, | 1862 | .dev_register = snd_ac97_dev_register, |
1863 | .dev_unregister = snd_ac97_dev_unregister, | 1863 | .dev_disconnect = snd_ac97_dev_disconnect, |
1864 | }; | 1864 | }; |
1865 | 1865 | ||
1866 | snd_assert(rac97 != NULL, return -EINVAL); | 1866 | snd_assert(rac97 != NULL, return -EINVAL); |
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 1b7f499c549d..314431385913 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -3499,7 +3499,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr) | |||
3499 | } | 3499 | } |
3500 | usb_chip[chip->index] = NULL; | 3500 | usb_chip[chip->index] = NULL; |
3501 | mutex_unlock(®ister_mutex); | 3501 | mutex_unlock(®ister_mutex); |
3502 | snd_card_free(card); | 3502 | snd_card_free_when_closed(card); |
3503 | } else { | 3503 | } else { |
3504 | mutex_unlock(®ister_mutex); | 3504 | mutex_unlock(®ister_mutex); |
3505 | } | 3505 | } |