diff mbox

ALSA: usb-audio: Trigger PCM XRUN at XRUN

Message ID 1415278746-5112-1-git-send-email-tiwai@suse.de (mailing list archive)
State Accepted
Commit 67e225009bb15403341d313f51326113c61af7df
Delegated to: Takashi Iwai
Headers show

Commit Message

Takashi Iwai Nov. 6, 2014, 12:59 p.m. UTC
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>
---
 sound/usb/endpoint.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)
diff mbox

Patch

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)
 {
 	struct snd_urb_ctx *ctx = urb->context;
 	struct snd_usb_endpoint *ep = ctx->ep;
+	struct snd_pcm_substream *substream;
+	unsigned long flags;
 	int err;
 
 	if (unlikely(urb->status == -ENOENT ||		/* unlinked */
@@ -364,8 +366,6 @@  static void snd_complete_urb(struct urb *urb)
 			goto exit_clear;
 
 		if (snd_usb_endpoint_implicit_feedback_sink(ep)) {
-			unsigned long flags;
-
 			spin_lock_irqsave(&ep->lock, flags);
 			list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
 			spin_unlock_irqrestore(&ep->lock, flags);
@@ -389,7 +389,12 @@  static void snd_complete_urb(struct urb *urb)
 		return;
 
 	usb_audio_err(ep->chip, "cannot submit urb (err = %d)\n", err);
-	//snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+	if (ep->data_subs && ep->data_subs->pcm_substream) {
+		substream = ep->data_subs->pcm_substream;
+		snd_pcm_stream_lock_irqsave(substream, flags);
+		snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+		snd_pcm_stream_unlock_irqrestore(substream, flags);
+	}
 
 exit_clear:
 	clear_bit(ctx->index, &ep->active_mask);