summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-11-06 13:04:49 +0100
committerTakashi Iwai <tiwai@suse.de>2014-11-06 13:04:49 +0100
commit67e225009bb15403341d313f51326113c61af7df (patch)
treea92fd6b4d300b3ec750df1503bfe3af61cb19aac
parent9bc889b4ba88a3f2d81e4b799d47d71d7381573a (diff)
downloadop-kernel-dev-67e225009bb15403341d313f51326113c61af7df.zip
op-kernel-dev-67e225009bb15403341d313f51326113c61af7df.tar.gz
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>
-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 167d0c1..a467991 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);
OpenPOWER on IntegriCloud