diff options
| -rw-r--r-- | sound/core/pcm.c | 7 | ||||
| -rw-r--r-- | sound/core/pcm_native.c | 16 |
2 files changed, 18 insertions, 5 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index f2991940b271..993b2405fdfe 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
| @@ -1086,11 +1086,15 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
| 1086 | if (list_empty(&pcm->list)) | 1086 | if (list_empty(&pcm->list)) |
| 1087 | goto unlock; | 1087 | goto unlock; |
| 1088 | 1088 | ||
| 1089 | mutex_lock(&pcm->open_mutex); | ||
| 1089 | list_del_init(&pcm->list); | 1090 | list_del_init(&pcm->list); |
| 1090 | for (cidx = 0; cidx < 2; cidx++) | 1091 | for (cidx = 0; cidx < 2; cidx++) |
| 1091 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) | 1092 | for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { |
| 1093 | snd_pcm_stream_lock_irq(substream); | ||
| 1092 | if (substream->runtime) | 1094 | if (substream->runtime) |
| 1093 | substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; | 1095 | substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; |
| 1096 | snd_pcm_stream_unlock_irq(substream); | ||
| 1097 | } | ||
| 1094 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { | 1098 | list_for_each_entry(notify, &snd_pcm_notify_list, list) { |
| 1095 | notify->n_disconnect(pcm); | 1099 | notify->n_disconnect(pcm); |
| 1096 | } | 1100 | } |
| @@ -1110,6 +1114,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
| 1110 | pcm->streams[cidx].chmap_kctl = NULL; | 1114 | pcm->streams[cidx].chmap_kctl = NULL; |
| 1111 | } | 1115 | } |
| 1112 | } | 1116 | } |
| 1117 | mutex_unlock(&pcm->open_mutex); | ||
| 1113 | unlock: | 1118 | unlock: |
| 1114 | mutex_unlock(®ister_mutex); | 1119 | mutex_unlock(®ister_mutex); |
| 1115 | return 0; | 1120 | return 0; |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 5e12e5bacbba..8753c89f3290 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 | ||
| 372 | static 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 | |||
| 372 | static int snd_pcm_hw_params(struct snd_pcm_substream *substream, | 380 | static 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 | ||
| 1326 | static struct action_ops snd_pcm_action_prepare = { | 1334 | static struct action_ops snd_pcm_action_prepare = { |
