From: Greg Kroah-Hartman Date: Wed, 7 Nov 2012 14:59:58 +0000 (+0100) Subject: 3.0-stable patches X-Git-Tag: v3.0.52~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=43c69243f401963fe438aae428db839ccd843d7c;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches added patches: alsa-pcm-fix-some-races-at-disconnection.patch --- diff --git a/queue-3.0/alsa-pcm-fix-some-races-at-disconnection.patch b/queue-3.0/alsa-pcm-fix-some-races-at-disconnection.patch new file mode 100644 index 00000000000..e4a5035b871 --- /dev/null +++ b/queue-3.0/alsa-pcm-fix-some-races-at-disconnection.patch @@ -0,0 +1,103 @@ +From tiwai@suse.de Wed Nov 7 15:55:23 2012 +From: tiwai@suse.de +Date: Wed, 7 Nov 2012 12:39:51 +0100 +Subject: ALSA: PCM: Fix some races at disconnection +To: stable@vger.kernel.org + +From: Takashi Iwai + +commit 9b0573c07f278e9888c352aa9724035c75784ea0 upstream. + +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 +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman +--- + sound/core/pcm.c | 7 ++++++- + sound/core/pcm_native.c | 16 ++++++++++++---- + 2 files changed, 18 insertions(+), 5 deletions(-) + +--- a/sound/core/pcm.c ++++ b/sound/core/pcm.c +@@ -1045,11 +1045,15 @@ static int snd_pcm_dev_disconnect(struct + if (list_empty(&pcm->list)) + goto unlock; + ++ mutex_lock(&pcm->open_mutex); + list_del_init(&pcm->list); + for (cidx = 0; cidx < 2; cidx++) +- for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) ++ for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { ++ snd_pcm_stream_lock_irq(substream); + if (substream->runtime) + substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; ++ snd_pcm_stream_unlock_irq(substream); ++ } + list_for_each_entry(notify, &snd_pcm_notify_list, list) { + notify->n_disconnect(pcm); + } +@@ -1065,6 +1069,7 @@ static int snd_pcm_dev_disconnect(struct + } + snd_unregister_device(devtype, pcm->card, pcm->device); + } ++ mutex_unlock(&pcm->open_mutex); + unlock: + mutex_unlock(®ister_mutex); + return 0; +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -368,6 +368,14 @@ static int period_to_usecs(struct snd_pc + return usecs; + } + ++static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state) ++{ ++ snd_pcm_stream_lock_irq(substream); ++ if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) ++ substream->runtime->status->state = state; ++ snd_pcm_stream_unlock_irq(substream); ++} ++ + static int snd_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) + { +@@ -451,7 +459,7 @@ static int snd_pcm_hw_params(struct snd_ + runtime->boundary *= 2; + + snd_pcm_timer_resolution_change(substream); +- runtime->status->state = SNDRV_PCM_STATE_SETUP; ++ snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP); + + if (pm_qos_request_active(&substream->latency_pm_qos_req)) + pm_qos_remove_request(&substream->latency_pm_qos_req); +@@ -463,7 +471,7 @@ static int snd_pcm_hw_params(struct snd_ + /* hardware might be unusable from this time, + so we force application to retry to set + the correct hardware parameter settings */ +- runtime->status->state = SNDRV_PCM_STATE_OPEN; ++ snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); + if (substream->ops->hw_free != NULL) + substream->ops->hw_free(substream); + return err; +@@ -511,7 +519,7 @@ static int snd_pcm_hw_free(struct snd_pc + return -EBADFD; + if (substream->ops->hw_free) + result = substream->ops->hw_free(substream); +- runtime->status->state = SNDRV_PCM_STATE_OPEN; ++ snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); + pm_qos_remove_request(&substream->latency_pm_qos_req); + return result; + } +@@ -1319,7 +1327,7 @@ static void snd_pcm_post_prepare(struct + { + struct snd_pcm_runtime *runtime = substream->runtime; + runtime->control->appl_ptr = runtime->status->hw_ptr; +- runtime->status->state = SNDRV_PCM_STATE_PREPARED; ++ snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED); + } + + static struct action_ops snd_pcm_action_prepare = { diff --git a/queue-3.0/series b/queue-3.0/series index c97700bdce3..84cba1089d1 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -15,3 +15,4 @@ nfs-fix-bug-in-legacy-dns-resolver.patch nfs-fix-oopses-in-nfs_lookup_revalidate-and-nfs4_lookup_revalidate.patch drm-restore-open_count-if-drm_setup-fails.patch hwmon-w83627ehf-force-initial-bank-selection.patch +alsa-pcm-fix-some-races-at-disconnection.patch