]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 7 Nov 2012 15:00:09 +0000 (16:00 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 7 Nov 2012 15:00:09 +0000 (16:00 +0100)
added patches:
alsa-pcm-fix-some-races-at-disconnection.patch

queue-3.4/alsa-pcm-fix-some-races-at-disconnection.patch [new file with mode: 0644]
queue-3.4/series

diff --git a/queue-3.4/alsa-pcm-fix-some-races-at-disconnection.patch b/queue-3.4/alsa-pcm-fix-some-races-at-disconnection.patch
new file mode 100644 (file)
index 0000000..a83b11b
--- /dev/null
@@ -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 <tiwai@suse.de>
+
+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 <matthieu.castet@parrot.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -1086,11 +1086,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);
+       }
+@@ -1106,6 +1110,7 @@ static int snd_pcm_dev_disconnect(struct
+               }
+               snd_unregister_device(devtype, pcm->card, pcm->device);
+       }
++      mutex_unlock(&pcm->open_mutex);
+  unlock:
+       mutex_unlock(&register_mutex);
+       return 0;
+--- a/sound/core/pcm_native.c
++++ b/sound/core/pcm_native.c
+@@ -369,6 +369,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)
+ {
+@@ -452,7 +460,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);
+@@ -464,7 +472,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;
+@@ -512,7 +520,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;
+ }
+@@ -1320,7 +1328,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 = {
index d299ff94fa9c9e298d8249707bf888cd2af20c25..feccc7a947717e5b9304ea256c937e60cb5f476b 100644 (file)
@@ -28,3 +28,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