aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2012-08-29 07:17:05 -0400
committerTakashi Iwai <tiwai@suse.de>2012-08-30 01:46:27 -0400
commit015618b902ae8e28705b7af9b4668615fea48ddd (patch)
tree43832c8eeaad08cf294da8a438512815858cfa66
parentc36b5b054aaf14d68261970e3769398110e636d8 (diff)
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+] Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/endpoint.c11
-rw-r--r--sound/usb/endpoint.h2
-rw-r--r--sound/usb/pcm.c13
3 files changed, 15 insertions, 11 deletions
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index c41181202688..b896c5559524 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,
799/** 799/**
800 * snd_usb_endpoint_start: start an snd_usb_endpoint 800 * snd_usb_endpoint_start: start an snd_usb_endpoint
801 * 801 *
802 * @ep: the endpoint to start 802 * @ep: the endpoint to start
803 * @can_sleep: flag indicating whether the operation is executed in
804 * non-atomic context
803 * 805 *
804 * A call to this function will increment the use count of the endpoint. 806 * A call to this function will increment the use count of the endpoint.
805 * In case it is not already running, the URBs for this endpoint will be 807 * 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,
809 * 811 *
810 * Returns an error if the URB submission failed, 0 in all other cases. 812 * Returns an error if the URB submission failed, 0 in all other cases.
811 */ 813 */
812int snd_usb_endpoint_start(struct snd_usb_endpoint *ep) 814int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
813{ 815{
814 int err; 816 int err;
815 unsigned int i; 817 unsigned int i;
@@ -821,6 +823,11 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
821 if (++ep->use_count != 1) 823 if (++ep->use_count != 1)
822 return 0; 824 return 0;
823 825
826 /* just to be sure */
827 deactivate_urbs(ep, 0, can_sleep);
828 if (can_sleep)
829 wait_clear_urbs(ep);
830
824 ep->active_mask = 0; 831 ep->active_mask = 0;
825 ep->unlink_mask = 0; 832 ep->unlink_mask = 0;
826 ep->phase = 0; 833 ep->phase = 0;
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index ee2723fb174f..a8e60c1408e5 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,
13 struct audioformat *fmt, 13 struct audioformat *fmt,
14 struct snd_usb_endpoint *sync_ep); 14 struct snd_usb_endpoint *sync_ep);
15 15
16int snd_usb_endpoint_start(struct snd_usb_endpoint *ep); 16int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);
17void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, 17void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
18 int force, int can_sleep, int wait); 18 int force, int can_sleep, int wait);
19int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep); 19int snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 62ec808ed792..1546577ae458 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,
212 } 212 }
213} 213}
214 214
215static int start_endpoints(struct snd_usb_substream *subs) 215static int start_endpoints(struct snd_usb_substream *subs, int can_sleep)
216{ 216{
217 int err; 217 int err;
218 218
@@ -225,7 +225,7 @@ static int start_endpoints(struct snd_usb_substream *subs)
225 snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep); 225 snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep);
226 226
227 ep->data_subs = subs; 227 ep->data_subs = subs;
228 err = snd_usb_endpoint_start(ep); 228 err = snd_usb_endpoint_start(ep, can_sleep);
229 if (err < 0) { 229 if (err < 0) {
230 clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags); 230 clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
231 return err; 231 return err;
@@ -239,7 +239,7 @@ static int start_endpoints(struct snd_usb_substream *subs)
239 snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep); 239 snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep);
240 240
241 ep->sync_slave = subs->data_endpoint; 241 ep->sync_slave = subs->data_endpoint;
242 err = snd_usb_endpoint_start(ep); 242 err = snd_usb_endpoint_start(ep, can_sleep);
243 if (err < 0) { 243 if (err < 0) {
244 clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags); 244 clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
245 return err; 245 return err;
@@ -544,13 +544,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
544 subs->last_frame_number = 0; 544 subs->last_frame_number = 0;
545 runtime->delay = 0; 545 runtime->delay = 0;
546 546
547 /* clear the pending deactivation on the target EPs */
548 deactivate_endpoints(subs);
549
550 /* for playback, submit the URBs now; otherwise, the first hwptr_done 547 /* for playback, submit the URBs now; otherwise, the first hwptr_done
551 * updates for all URBs would happen at the same time when starting */ 548 * updates for all URBs would happen at the same time when starting */
552 if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) 549 if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
553 return start_endpoints(subs); 550 return start_endpoints(subs, 1);
554 551
555 return 0; 552 return 0;
556} 553}
@@ -1175,7 +1172,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
1175 1172
1176 switch (cmd) { 1173 switch (cmd) {
1177 case SNDRV_PCM_TRIGGER_START: 1174 case SNDRV_PCM_TRIGGER_START:
1178 err = start_endpoints(subs); 1175 err = start_endpoints(subs, 0);
1179 if (err < 0) 1176 if (err < 0)
1180 return err; 1177 return err;
1181 1178