Skip to content

Commit 4f9d674

Browse files
committed
ALSA: usb-audio: Notify xrun for low-latency mode
The low-latency mode of USB-audio driver uses a similar approach like the implicit feedback mode but it has an explicit queuing at the trigger start time. The difference is, however, that no packet will be handled any longer after all queued packets are handled but no enough data is fed. In the case of implicit feedback mode, the capture-side packet handling triggers the re-queuing, and this checks the XRUN. OTOH, in the low-latency mode, it just stops without XRUN notification unless any new action is taken from user-space via ack callback. For example, when you stop the stream in aplay, no XRUN is reported. This patch adds the XRUN check at the packet complete callback in the case all pending URBs are exhausted. Strictly speaking, this state doesn't match really with XRUN; in theory the application may queue immediately after this happens. But such behavior is only for 1-period configuration, which the USB-audio driver doesn't support. So we may conclude that this situation leads certainly to XRUN. A caveat is that the XRUN should be triggered only for the PCM RUNNING state, and not during DRAINING. This additional state check is put in notify_xrun(), too. Fixes: d5f871f ("ALSA: usb-audio: Improved lowlatency playback support") Reported-by: Leonard Crestez <[email protected]> Link: https://lore.kernel.org/[email protected] Link: https://patch.msgid.link/[email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent 947c401 commit 4f9d674

File tree

1 file changed

+11
-3
lines changed

1 file changed

+11
-3
lines changed

sound/usb/endpoint.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -403,10 +403,15 @@ static int prepare_inbound_urb(struct snd_usb_endpoint *ep,
403403
static void notify_xrun(struct snd_usb_endpoint *ep)
404404
{
405405
struct snd_usb_substream *data_subs;
406+
struct snd_pcm_substream *psubs;
406407

407408
data_subs = READ_ONCE(ep->data_subs);
408-
if (data_subs && data_subs->pcm_substream)
409-
snd_pcm_stop_xrun(data_subs->pcm_substream);
409+
if (!data_subs)
410+
return;
411+
psubs = data_subs->pcm_substream;
412+
if (psubs && psubs->runtime &&
413+
psubs->runtime->state == SNDRV_PCM_STATE_RUNNING)
414+
snd_pcm_stop_xrun(psubs);
410415
}
411416

412417
static struct snd_usb_packet_info *
@@ -562,7 +567,10 @@ static void snd_complete_urb(struct urb *urb)
562567
push_back_to_ready_list(ep, ctx);
563568
clear_bit(ctx->index, &ep->active_mask);
564569
snd_usb_queue_pending_output_urbs(ep, false);
565-
atomic_dec(&ep->submitted_urbs); /* decrement at last */
570+
/* decrement at last, and check xrun */
571+
if (atomic_dec_and_test(&ep->submitted_urbs) &&
572+
!snd_usb_endpoint_implicit_feedback_sink(ep))
573+
notify_xrun(ep);
566574
return;
567575
}
568576

0 commit comments

Comments
 (0)