diff options
author | Takashi Iwai <tiwai@suse.de> | 2012-10-16 10:43:39 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-10-30 06:07:15 -0400 |
commit | 0914f7961babbf28aaa2f19b453951fb4841c03f (patch) | |
tree | fe5c14256a1d7b2116341300dd1e8ed94ac5f576 /sound | |
parent | a0830dbd4e42b38aefdf3fb61ba5019a1a99ea85 (diff) |
ALSA: Avoid endless sleep after disconnect
When disconnect callback is called, each component should wake up
sleepers and check card->shutdown flag for avoiding the endless sleep
blocking the proper resource release.
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/control.c | 2 | ||||
-rw-r--r-- | sound/core/hwdep.c | 7 | ||||
-rw-r--r-- | sound/core/oss/pcm_oss.c | 4 | ||||
-rw-r--r-- | sound/core/pcm.c | 6 | ||||
-rw-r--r-- | sound/core/pcm_native.c | 8 | ||||
-rw-r--r-- | sound/core/rawmidi.c | 20 |
6 files changed, 46 insertions, 1 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index 9768a3963c8f..8c7c2c9bba61 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -1437,6 +1437,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, | |||
1437 | spin_unlock_irq(&ctl->read_lock); | 1437 | spin_unlock_irq(&ctl->read_lock); |
1438 | schedule(); | 1438 | schedule(); |
1439 | remove_wait_queue(&ctl->change_sleep, &wait); | 1439 | remove_wait_queue(&ctl->change_sleep, &wait); |
1440 | if (ctl->card->shutdown) | ||
1441 | return -ENODEV; | ||
1440 | if (signal_pending(current)) | 1442 | if (signal_pending(current)) |
1441 | return -ERESTARTSYS; | 1443 | return -ERESTARTSYS; |
1442 | spin_lock_irq(&ctl->read_lock); | 1444 | spin_lock_irq(&ctl->read_lock); |
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 53a6ba5ad615..3f7f6628cf7b 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c | |||
@@ -131,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) | |||
131 | mutex_unlock(&hw->open_mutex); | 131 | mutex_unlock(&hw->open_mutex); |
132 | schedule(); | 132 | schedule(); |
133 | mutex_lock(&hw->open_mutex); | 133 | mutex_lock(&hw->open_mutex); |
134 | if (hw->card->shutdown) { | ||
135 | err = -ENODEV; | ||
136 | break; | ||
137 | } | ||
134 | if (signal_pending(current)) { | 138 | if (signal_pending(current)) { |
135 | err = -ERESTARTSYS; | 139 | err = -ERESTARTSYS; |
136 | break; | 140 | break; |
@@ -462,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) | |||
462 | mutex_unlock(®ister_mutex); | 466 | mutex_unlock(®ister_mutex); |
463 | return -EINVAL; | 467 | return -EINVAL; |
464 | } | 468 | } |
469 | mutex_lock(&hwdep->open_mutex); | ||
470 | wake_up(&hwdep->open_wait); | ||
465 | #ifdef CONFIG_SND_OSSEMUL | 471 | #ifdef CONFIG_SND_OSSEMUL |
466 | if (hwdep->ossreg) | 472 | if (hwdep->ossreg) |
467 | snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); | 473 | snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); |
468 | #endif | 474 | #endif |
469 | snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); | 475 | snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); |
470 | list_del_init(&hwdep->list); | 476 | list_del_init(&hwdep->list); |
477 | mutex_unlock(&hwdep->open_mutex); | ||
471 | mutex_unlock(®ister_mutex); | 478 | mutex_unlock(®ister_mutex); |
472 | return 0; | 479 | return 0; |
473 | } | 480 | } |
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 2529e01538e9..f337b66a020b 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c | |||
@@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) | |||
2441 | mutex_unlock(&pcm->open_mutex); | 2441 | mutex_unlock(&pcm->open_mutex); |
2442 | schedule(); | 2442 | schedule(); |
2443 | mutex_lock(&pcm->open_mutex); | 2443 | mutex_lock(&pcm->open_mutex); |
2444 | if (pcm->card->shutdown) { | ||
2445 | err = -ENODEV; | ||
2446 | break; | ||
2447 | } | ||
2444 | if (signal_pending(current)) { | 2448 | if (signal_pending(current)) { |
2445 | err = -ERESTARTSYS; | 2449 | err = -ERESTARTSYS; |
2446 | break; | 2450 | break; |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 993b2405fdfe..030102caeee9 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
@@ -1087,12 +1087,16 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
1087 | goto unlock; | 1087 | goto unlock; |
1088 | 1088 | ||
1089 | mutex_lock(&pcm->open_mutex); | 1089 | mutex_lock(&pcm->open_mutex); |
1090 | wake_up(&pcm->open_wait); | ||
1090 | list_del_init(&pcm->list); | 1091 | list_del_init(&pcm->list); |
1091 | for (cidx = 0; cidx < 2; cidx++) | 1092 | for (cidx = 0; cidx < 2; cidx++) |
1092 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { | 1093 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { |
1093 | snd_pcm_stream_lock_irq(substream); | 1094 | snd_pcm_stream_lock_irq(substream); |
1094 | if (substream->runtime) | 1095 | if (substream->runtime) { |
1095 | substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; | 1096 | substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; |
1097 | wake_up(&substream->runtime->sleep); | ||
1098 | wake_up(&substream->runtime->tsleep); | ||
1099 | } | ||
1096 | snd_pcm_stream_unlock_irq(substream); | 1100 | snd_pcm_stream_unlock_irq(substream); |
1097 | } | 1101 | } |
1098 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { | 1102 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 48c6a70ad69e..6e8872de5ba0 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -1518,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, | |||
1518 | down_read(&snd_pcm_link_rwsem); | 1518 | down_read(&snd_pcm_link_rwsem); |
1519 | snd_pcm_stream_lock_irq(substream); | 1519 | snd_pcm_stream_lock_irq(substream); |
1520 | remove_wait_queue(&to_check->sleep, &wait); | 1520 | remove_wait_queue(&to_check->sleep, &wait); |
1521 | if (card->shutdown) { | ||
1522 | result = -ENODEV; | ||
1523 | break; | ||
1524 | } | ||
1521 | if (tout == 0) { | 1525 | if (tout == 0) { |
1522 | if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) | 1526 | if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) |
1523 | result = -ESTRPIPE; | 1527 | result = -ESTRPIPE; |
@@ -2169,6 +2173,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) | |||
2169 | mutex_unlock(&pcm->open_mutex); | 2173 | mutex_unlock(&pcm->open_mutex); |
2170 | schedule(); | 2174 | schedule(); |
2171 | mutex_lock(&pcm->open_mutex); | 2175 | mutex_lock(&pcm->open_mutex); |
2176 | if (pcm->card->shutdown) { | ||
2177 | err = -ENODEV; | ||
2178 | break; | ||
2179 | } | ||
2172 | if (signal_pending(current)) { | 2180 | if (signal_pending(current)) { |
2173 | err = -ERESTARTSYS; | 2181 | err = -ERESTARTSYS; |
2174 | break; | 2182 | break; |
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 7d4f62ab6711..1bb95aeea084 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c | |||
@@ -424,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) | |||
424 | mutex_unlock(&rmidi->open_mutex); | 424 | mutex_unlock(&rmidi->open_mutex); |
425 | schedule(); | 425 | schedule(); |
426 | mutex_lock(&rmidi->open_mutex); | 426 | mutex_lock(&rmidi->open_mutex); |
427 | if (rmidi->card->shutdown) { | ||
428 | err = -ENODEV; | ||
429 | break; | ||
430 | } | ||
427 | if (signal_pending(current)) { | 431 | if (signal_pending(current)) { |
428 | err = -ERESTARTSYS; | 432 | err = -ERESTARTSYS; |
429 | break; | 433 | break; |
@@ -995,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun | |||
995 | spin_unlock_irq(&runtime->lock); | 999 | spin_unlock_irq(&runtime->lock); |
996 | schedule(); | 1000 | schedule(); |
997 | remove_wait_queue(&runtime->sleep, &wait); | 1001 | remove_wait_queue(&runtime->sleep, &wait); |
1002 | if (rfile->rmidi->card->shutdown) | ||
1003 | return -ENODEV; | ||
998 | if (signal_pending(current)) | 1004 | if (signal_pending(current)) |
999 | return result > 0 ? result : -ERESTARTSYS; | 1005 | return result > 0 ? result : -ERESTARTSYS; |
1000 | if (!runtime->avail) | 1006 | if (!runtime->avail) |
@@ -1238,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, | |||
1238 | spin_unlock_irq(&runtime->lock); | 1244 | spin_unlock_irq(&runtime->lock); |
1239 | timeout = schedule_timeout(30 * HZ); | 1245 | timeout = schedule_timeout(30 * HZ); |
1240 | remove_wait_queue(&runtime->sleep, &wait); | 1246 | remove_wait_queue(&runtime->sleep, &wait); |
1247 | if (rfile->rmidi->card->shutdown) | ||
1248 | return -ENODEV; | ||
1241 | if (signal_pending(current)) | 1249 | if (signal_pending(current)) |
1242 | return result > 0 ? result : -ERESTARTSYS; | 1250 | return result > 0 ? result : -ERESTARTSYS; |
1243 | if (!runtime->avail && !timeout) | 1251 | if (!runtime->avail && !timeout) |
@@ -1613,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device) | |||
1613 | static int snd_rawmidi_dev_disconnect(struct snd_device *device) | 1621 | static int snd_rawmidi_dev_disconnect(struct snd_device *device) |
1614 | { | 1622 | { |
1615 | struct snd_rawmidi *rmidi = device->device_data; | 1623 | struct snd_rawmidi *rmidi = device->device_data; |
1624 | int dir; | ||
1616 | 1625 | ||
1617 | mutex_lock(®ister_mutex); | 1626 | mutex_lock(®ister_mutex); |
1627 | mutex_lock(&rmidi->open_mutex); | ||
1628 | wake_up(&rmidi->open_wait); | ||
1618 | list_del_init(&rmidi->list); | 1629 | list_del_init(&rmidi->list); |
1630 | for (dir = 0; dir < 2; dir++) { | ||
1631 | struct snd_rawmidi_substream *s; | ||
1632 | list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { | ||
1633 | if (s->runtime) | ||
1634 | wake_up(&s->runtime->sleep); | ||
1635 | } | ||
1636 | } | ||
1637 | |||
1619 | #ifdef CONFIG_SND_OSSEMUL | 1638 | #ifdef CONFIG_SND_OSSEMUL |
1620 | if (rmidi->ossreg) { | 1639 | if (rmidi->ossreg) { |
1621 | if ((int)rmidi->device == midi_map[rmidi->card->number]) { | 1640 | if ((int)rmidi->device == midi_map[rmidi->card->number]) { |
@@ -1630,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) | |||
1630 | } | 1649 | } |
1631 | #endif /* CONFIG_SND_OSSEMUL */ | 1650 | #endif /* CONFIG_SND_OSSEMUL */ |
1632 | snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); | 1651 | snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); |
1652 | mutex_unlock(&rmidi->open_mutex); | ||
1633 | mutex_unlock(®ister_mutex); | 1653 | mutex_unlock(®ister_mutex); |
1634 | return 0; | 1654 | return 0; |
1635 | } | 1655 | } |