diff options
Diffstat (limited to '0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch')
-rw-r--r-- | 0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch b/0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch new file mode 100644 index 000000000..031888c3c --- /dev/null +++ b/0001-ALSA-snd-usb-Fix-URB-cancellation-at-stream-start.patch @@ -0,0 +1,131 @@ +From 42ff3e2d34427dc4c6faa09052a2531f2e71d7d6 Mon Sep 17 00:00:00 2001 +From: Daniel Mack <zonque@gmail.com> +Date: Wed, 29 Aug 2012 13:17:05 +0200 +Subject: [PATCH] ALSA: snd-usb: Fix URB cancellation at stream start + +Commit e9ba389c5 ("ALSA: usb-audio: Fix scheduling-while-atomic bug in +PCM capture stream") fixed a scheduling-while-atomic bug that happened +when snd_usb_endpoint_start was called from the trigger callback, which +is an atmic context. However, the patch breaks the idea of the endpoints +reference counting, which is the reason why the driver has been +refactored lately. + +Revert that commit and let snd_usb_endpoint_start() take care of the URB +cancellation again. As this function is called from both atomic and +non-atomic context, add a flag to denote whether the function may sleep. + +Signed-off-by: Daniel Mack <zonque@gmail.com> +Cc: stable@kernel.org [3.5+] +--- + sound/usb/endpoint.c | 11 +++++++++-- + sound/usb/endpoint.h | 2 +- + sound/usb/pcm.c | 13 +++++-------- + 3 files changed, 15 insertions(+), 11 deletions(-) + +diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c +index c411812..b896c55 100644 +--- a/sound/usb/endpoint.c ++++ b/sound/usb/endpoint.c +@@ -799,7 +799,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, + /** + * snd_usb_endpoint_start: start an snd_usb_endpoint + * +- * @ep: the endpoint to start ++ * @ep: the endpoint to start ++ * @can_sleep: flag indicating whether the operation is executed in ++ * non-atomic context + * + * A call to this function will increment the use count of the endpoint. + * In case it is not already running, the URBs for this endpoint will be +@@ -809,7 +811,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, + * + * Returns an error if the URB submission failed, 0 in all other cases. + */ +-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) ++int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep) + { + int err; + unsigned int i; +@@ -821,6 +823,11 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) + if (++ep->use_count != 1) + return 0; + ++ /* just to be sure */ ++ deactivate_urbs(ep, 0, can_sleep); ++ if (can_sleep) ++ wait_clear_urbs(ep); ++ + ep->active_mask = 0; + ep->unlink_mask = 0; + ep->phase = 0; +diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h +index ee2723f..a8e60c1 100644 +--- a/sound/usb/endpoint.h ++++ b/sound/usb/endpoint.h +@@ -13,7 +13,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, + struct audioformat *fmt, + struct snd_usb_endpoint *sync_ep); + +-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep); ++int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep); + void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, + int force, int can_sleep, int wait); + int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); +diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c +index 62ec808..1546577 100644 +--- a/sound/usb/pcm.c ++++ b/sound/usb/pcm.c +@@ -212,7 +212,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface, + } + } + +-static int start_endpoints(struct snd_usb_substream *subs) ++static int start_endpoints(struct snd_usb_substream *subs, int can_sleep) + { + int err; + +@@ -225,7 +225,7 @@ static int start_endpoints(struct snd_usb_substream *subs) + snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep); + + ep->data_subs = subs; +- err = snd_usb_endpoint_start(ep); ++ err = snd_usb_endpoint_start(ep, can_sleep); + if (err < 0) { + clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); + return err; +@@ -239,7 +239,7 @@ static int start_endpoints(struct snd_usb_substream *subs) + snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep); + + ep->sync_slave = subs->data_endpoint; +- err = snd_usb_endpoint_start(ep); ++ err = snd_usb_endpoint_start(ep, can_sleep); + if (err < 0) { + clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); + return err; +@@ -544,13 +544,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) + subs->last_frame_number = 0; + runtime->delay = 0; + +- /* clear the pending deactivation on the target EPs */ +- deactivate_endpoints(subs); +- + /* for playback, submit the URBs now; otherwise, the first hwptr_done + * updates for all URBs would happen at the same time when starting */ + if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) +- return start_endpoints(subs); ++ return start_endpoints(subs, 1); + + return 0; + } +@@ -1175,7 +1172,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: +- err = start_endpoints(subs); ++ err = start_endpoints(subs, 0); + if (err < 0) + return err; + +-- +1.7.11.4 + |