aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/pcm_native.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/core/pcm_native.c')
-rw-r--r--sound/core/pcm_native.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 5e12e5bacbba..6e8872de5ba0 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)
369 return usecs; 369 return usecs;
370} 370}
371 371
372static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
373{
374 snd_pcm_stream_lock_irq(substream);
375 if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
376 substream->runtime->status->state = state;
377 snd_pcm_stream_unlock_irq(substream);
378}
379
372static int snd_pcm_hw_params(struct snd_pcm_substream *substream, 380static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
373 struct snd_pcm_hw_params *params) 381 struct snd_pcm_hw_params *params)
374{ 382{
@@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
452 runtime->boundary *= 2; 460 runtime->boundary *= 2;
453 461
454 snd_pcm_timer_resolution_change(substream); 462 snd_pcm_timer_resolution_change(substream);
455 runtime->status->state = SNDRV_PCM_STATE_SETUP; 463 snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
456 464
457 if (pm_qos_request_active(&substream->latency_pm_qos_req)) 465 if (pm_qos_request_active(&substream->latency_pm_qos_req))
458 pm_qos_remove_request(&substream->latency_pm_qos_req); 466 pm_qos_remove_request(&substream->latency_pm_qos_req);
@@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
464 /* hardware might be unusable from this time, 472 /* hardware might be unusable from this time,
465 so we force application to retry to set 473 so we force application to retry to set
466 the correct hardware parameter settings */ 474 the correct hardware parameter settings */
467 runtime->status->state = SNDRV_PCM_STATE_OPEN; 475 snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
468 if (substream->ops->hw_free != NULL) 476 if (substream->ops->hw_free != NULL)
469 substream->ops->hw_free(substream); 477 substream->ops->hw_free(substream);
470 return err; 478 return err;
@@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
512 return -EBADFD; 520 return -EBADFD;
513 if (substream->ops->hw_free) 521 if (substream->ops->hw_free)
514 result = substream->ops->hw_free(substream); 522 result = substream->ops->hw_free(substream);
515 runtime->status->state = SNDRV_PCM_STATE_OPEN; 523 snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
516 pm_qos_remove_request(&substream->latency_pm_qos_req); 524 pm_qos_remove_request(&substream->latency_pm_qos_req);
517 return result; 525 return result;
518} 526}
@@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
1320{ 1328{
1321 struct snd_pcm_runtime *runtime = substream->runtime; 1329 struct snd_pcm_runtime *runtime = substream->runtime;
1322 runtime->control->appl_ptr = runtime->status->hw_ptr; 1330 runtime->control->appl_ptr = runtime->status->hw_ptr;
1323 runtime->status->state = SNDRV_PCM_STATE_PREPARED; 1331 snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
1324} 1332}
1325 1333
1326static struct action_ops snd_pcm_action_prepare = { 1334static struct action_ops snd_pcm_action_prepare = {
@@ -1510,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
1510 down_read(&snd_pcm_link_rwsem); 1518 down_read(&snd_pcm_link_rwsem);
1511 snd_pcm_stream_lock_irq(substream); 1519 snd_pcm_stream_lock_irq(substream);
1512 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 }
1513 if (tout == 0) { 1525 if (tout == 0) {
1514 if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) 1526 if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
1515 result = -ESTRPIPE; 1527 result = -ESTRPIPE;
@@ -1634,6 +1646,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
1634 write_unlock_irq(&snd_pcm_link_rwlock); 1646 write_unlock_irq(&snd_pcm_link_rwlock);
1635 up_write(&snd_pcm_link_rwsem); 1647 up_write(&snd_pcm_link_rwsem);
1636 _nolock: 1648 _nolock:
1649 snd_card_unref(substream1->pcm->card);
1637 fput_light(file, fput_needed); 1650 fput_light(file, fput_needed);
1638 if (res < 0) 1651 if (res < 0)
1639 kfree(group); 1652 kfree(group);
@@ -2108,7 +2121,9 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file)
2108 return err; 2121 return err;
2109 pcm = snd_lookup_minor_data(iminor(inode), 2122 pcm = snd_lookup_minor_data(iminor(inode),
2110 SNDRV_DEVICE_TYPE_PCM_PLAYBACK); 2123 SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
2111 return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); 2124 err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
2125 snd_card_unref(pcm->card);
2126 return err;
2112} 2127}
2113 2128
2114static int snd_pcm_capture_open(struct inode *inode, struct file *file) 2129static int snd_pcm_capture_open(struct inode *inode, struct file *file)
@@ -2119,7 +2134,9 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file)
2119 return err; 2134 return err;
2120 pcm = snd_lookup_minor_data(iminor(inode), 2135 pcm = snd_lookup_minor_data(iminor(inode),
2121 SNDRV_DEVICE_TYPE_PCM_CAPTURE); 2136 SNDRV_DEVICE_TYPE_PCM_CAPTURE);
2122 return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); 2137 err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
2138 snd_card_unref(pcm->card);
2139 return err;
2123} 2140}
2124 2141
2125static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) 2142static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
@@ -2156,6 +2173,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
2156 mutex_unlock(&pcm->open_mutex); 2173 mutex_unlock(&pcm->open_mutex);
2157 schedule(); 2174 schedule();
2158 mutex_lock(&pcm->open_mutex); 2175 mutex_lock(&pcm->open_mutex);
2176 if (pcm->card->shutdown) {
2177 err = -ENODEV;
2178 break;
2179 }
2159 if (signal_pending(current)) { 2180 if (signal_pending(current)) {
2160 err = -ERESTARTSYS; 2181 err = -ERESTARTSYS;
2161 break; 2182 break;