aboutsummaryrefslogtreecommitdiffstats
path: root/sound/usb
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-11-06 07:04:49 -0500
committerTakashi Iwai <tiwai@suse.de>2014-11-06 07:04:49 -0500
commit67e225009bb15403341d313f51326113c61af7df (patch)
treea92fd6b4d300b3ec750df1503bfe3af61cb19aac /sound/usb
parent9bc889b4ba88a3f2d81e4b799d47d71d7381573a (diff)
ALSA: usb-audio: Trigger PCM XRUN at XRUN
The usb-audio driver detects XRUN at its complete callback, but the actual code to trigger PCM XRUN is commented out because it caused deadlock in the past. This patch revives the PCM trigger properly. It resulted in more than just enabling snd_pcm_stop(), but it had to deduce the PCM substream with proper NULL checks and holds the stream lock around the call. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/endpoint.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 167d0c1643e1..a4679913b0aa 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -348,6 +348,8 @@ static void snd_complete_urb(struct urb *urb)
348{ 348{
349 struct snd_urb_ctx *ctx = urb->context; 349 struct snd_urb_ctx *ctx = urb->context;
350 struct snd_usb_endpoint *ep = ctx->ep; 350 struct snd_usb_endpoint *ep = ctx->ep;
351 struct snd_pcm_substream *substream;
352 unsigned long flags;
351 int err; 353 int err;
352 354
353 if (unlikely(urb->status == -ENOENT || /* unlinked */ 355 if (unlikely(urb->status == -ENOENT || /* unlinked */
@@ -364,8 +366,6 @@ static void snd_complete_urb(struct urb *urb)
364 goto exit_clear; 366 goto exit_clear;
365 367
366 if (snd_usb_endpoint_implicit_feedback_sink(ep)) { 368 if (snd_usb_endpoint_implicit_feedback_sink(ep)) {
367 unsigned long flags;
368
369 spin_lock_irqsave(&ep->lock, flags); 369 spin_lock_irqsave(&ep->lock, flags);
370 list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs); 370 list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
371 spin_unlock_irqrestore(&ep->lock, flags); 371 spin_unlock_irqrestore(&ep->lock, flags);
@@ -389,7 +389,12 @@ static void snd_complete_urb(struct urb *urb)
389 return; 389 return;
390 390
391 usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err); 391 usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err);
392 //snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN); 392 if (ep->data_subs && ep->data_subs->pcm_substream) {
393 substream = ep->data_subs->pcm_substream;
394 snd_pcm_stream_lock_irqsave(substream, flags);
395 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
396 snd_pcm_stream_unlock_irqrestore(substream, flags);
397 }
393 398
394exit_clear: 399exit_clear:
395 clear_bit(ctx->index, &ep->active_mask); 400 clear_bit(ctx->index, &ep->active_mask);