aboutsummaryrefslogtreecommitdiffstats
path: root/sound/core/pcm.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2012-10-12 09:07:34 -0400
committerTakashi Iwai <tiwai@suse.de>2012-10-30 06:06:48 -0400
commit9b0573c07f278e9888c352aa9724035c75784ea0 (patch)
treea5729ddd409994d5912ba71b372169e3fa7f879d /sound/core/pcm.c
parent1693849f71b818be9e6e2b6e6fbcb45f6f518f96 (diff)
ALSA: PCM: Fix some races at disconnection
Fix races at PCM disconnection: - while a PCM device is being opened or closed - while the PCM state is being changed without lock in prepare, hw_params, hw_free ops Reported-by: Matthieu CASTET <matthieu.castet@parrot.com> Cc: <stable@vger.kernel.org> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/core/pcm.c')
-rw-r--r--sound/core/pcm.c7
1 files changed, 6 insertions, 1 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(&register_mutex); 1119 mutex_unlock(&register_mutex);
1115 return 0; 1120 return 0;