Skip to content

Commit d5f871f

Browse files
committed
ALSA: usb-audio: Improved lowlatency playback support
This is another attempt to improve further the handling of playback stream in the low latency mode. The latest workaround in commit 4267c5a ("ALSA: usb-audio: Work around for XRUN with low latency playback") revealed that submitting URBs forcibly in advance may trigger XRUN easily. In the classical mode, this problem was avoided by practically delaying the submission of the actual data with the pre-submissions of silent data before triggering the stream start. But that is exactly what we want to avoid. Now, in this patch, instead of the previous workaround, we take a similar approach as used in the implicit feedback mode. The URBs are queued at the PCM trigger start like before, but we check whether the buffer has been already filled enough before each submission, and stop queuing if the data overcomes the threshold. The remaining URBs are kept in the ready list, and they will be retrieved in the URB complete callback of other (already queued) URBs. In the complete callback, we try to fill the data and submit as much as possible again. When there is no more available in-flight URBs that may handle the pending data, we'll check in PCM ack callback and submit and process URBs there in addition. In this way, the amount of in-flight URBs may vary dynamically and flexibly depending on the available data without hitting XRUN. The following things are changed to achieve the behavior above: * The endpoint prepare callback is changed to return an error code; when there is no enough data available, it may return -EAGAIN. Currently only prepare_playback_urb() returns the error. The evaluation of the available data is a bit messy here; we can't check with snd_pcm_avail() at the point of prepare callback (as runtime->status->hwptr hasn't been updated yet), hence we manually estimate the appl_ptr and compare with the internal hwptr_done to calculate the available frames. * snd_usb_endpoint_start() doesn't submit full URBs if the prepare callback returns -EAGAIN, and puts the remaining URBs to the ready list for the later submission. * snd_complete_urb() treats the URBs in the low-latency mode similarly like the implicit feedback mode, and submissions are done in (now exported) snd_usb_queue_pending_output_urbs(). * snd_usb_queue_pending_output_urbs() again checks the error value from the prepare callback. If it's -EAGAIN for the normal stream (i.e. not implicit feedback mode), we push it back to the ready list again. * PCM ack callback is introduced for the playback stream, and it calls snd_usb_queue_pending_output_urbs() if there is no in-flight URB while the stream is running. This corresponds to the case where the system needs the appl_ptr update for re-submitting a new URB. * snd_usb_queue_pending_output_urbs() and the prepare EP callback receive in_stream_lock argument, which is a bool flag indicating the call path from PCM ack. It's needed for avoiding the deadlock of snd_pcm_period_elapsed() calls. * Set the new SNDRV_PCM_INFO_EXPLICIT_SYNC flag when the new low-latency mode is deployed. This assures catching each applptr update even in the mmap mode. Fixes: 4267c5a ("ALSA: usb-audio: Work around for XRUN with low latency playback") Link: https://lore.kernel.org/r/20210929080844.11583-9-tiwai@suse.de Signed-off-by: Takashi Iwai <tiwai@suse.de>
1 parent 0ef7436 commit d5f871f

File tree

4 files changed

+177
-68
lines changed

4 files changed

+177
-68
lines changed

sound/usb/card.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ struct snd_usb_endpoint {
7474

7575
atomic_t state; /* running state */
7676

77-
void (*prepare_data_urb) (struct snd_usb_substream *subs,
78-
struct urb *urb);
77+
int (*prepare_data_urb) (struct snd_usb_substream *subs,
78+
struct urb *urb,
79+
bool in_stream_lock);
7980
void (*retire_data_urb) (struct snd_usb_substream *subs,
8081
struct urb *urb);
8182

@@ -94,7 +95,6 @@ struct snd_usb_endpoint {
9495
struct list_head ready_playback_urbs; /* playback URB FIFO for implicit fb */
9596

9697
unsigned int nurbs; /* # urbs */
97-
unsigned int nominal_queue_size; /* total buffer sizes in URBs */
9898
unsigned long active_mask; /* bitmask of active urbs */
9999
unsigned long unlink_mask; /* bitmask of unlinked urbs */
100100
atomic_t submitted_urbs; /* currently submitted urbs */

sound/usb/endpoint.c

Lines changed: 88 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,9 @@ static void prepare_silent_urb(struct snd_usb_endpoint *ep,
307307
/*
308308
* Prepare a PLAYBACK urb for submission to the bus.
309309
*/
310-
static void prepare_outbound_urb(struct snd_usb_endpoint *ep,
311-
struct snd_urb_ctx *ctx)
310+
static int prepare_outbound_urb(struct snd_usb_endpoint *ep,
311+
struct snd_urb_ctx *ctx,
312+
bool in_stream_lock)
312313
{
313314
struct urb *urb = ctx->urb;
314315
unsigned char *cp = urb->transfer_buffer;
@@ -320,9 +321,9 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep,
320321
case SND_USB_ENDPOINT_TYPE_DATA:
321322
data_subs = READ_ONCE(ep->data_subs);
322323
if (data_subs && ep->prepare_data_urb)
323-
ep->prepare_data_urb(data_subs, urb);
324-
else /* no data provider, so send silence */
325-
prepare_silent_urb(ep, ctx);
324+
return ep->prepare_data_urb(data_subs, urb, in_stream_lock);
325+
/* no data provider, so send silence */
326+
prepare_silent_urb(ep, ctx);
326327
break;
327328

328329
case SND_USB_ENDPOINT_TYPE_SYNC:
@@ -351,13 +352,14 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep,
351352

352353
break;
353354
}
355+
return 0;
354356
}
355357

356358
/*
357359
* Prepare a CAPTURE or SYNC urb for submission to the bus.
358360
*/
359-
static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep,
360-
struct snd_urb_ctx *urb_ctx)
361+
static int prepare_inbound_urb(struct snd_usb_endpoint *ep,
362+
struct snd_urb_ctx *urb_ctx)
361363
{
362364
int i, offs;
363365
struct urb *urb = urb_ctx->urb;
@@ -382,6 +384,7 @@ static inline void prepare_inbound_urb(struct snd_usb_endpoint *ep,
382384
urb->iso_frame_desc[0].offset = 0;
383385
break;
384386
}
387+
return 0;
385388
}
386389

387390
/* notify an error as XRUN to the assigned PCM data substream */
@@ -417,6 +420,16 @@ next_packet_fifo_dequeue(struct snd_usb_endpoint *ep)
417420
return p;
418421
}
419422

423+
static void push_back_to_ready_list(struct snd_usb_endpoint *ep,
424+
struct snd_urb_ctx *ctx)
425+
{
426+
unsigned long flags;
427+
428+
spin_lock_irqsave(&ep->lock, flags);
429+
list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
430+
spin_unlock_irqrestore(&ep->lock, flags);
431+
}
432+
420433
/*
421434
* Send output urbs that have been prepared previously. URBs are dequeued
422435
* from ep->ready_playback_urbs and in case there aren't any available
@@ -427,12 +440,14 @@ next_packet_fifo_dequeue(struct snd_usb_endpoint *ep)
427440
* is that host controllers don't guarantee the order in which they return
428441
* inbound and outbound packets to their submitters.
429442
*
430-
* This function is only used for implicit feedback endpoints. For endpoints
431-
* driven by dedicated sync endpoints, URBs are immediately re-submitted
432-
* from their completion handler.
443+
* This function is used both for implicit feedback endpoints and in low-
444+
* latency playback mode.
433445
*/
434-
static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
446+
void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,
447+
bool in_stream_lock)
435448
{
449+
bool implicit_fb = snd_usb_endpoint_implicit_feedback_sink(ep);
450+
436451
while (ep_state_running(ep)) {
437452

438453
unsigned long flags;
@@ -441,26 +456,39 @@ static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
441456
int err, i;
442457

443458
spin_lock_irqsave(&ep->lock, flags);
444-
if (ep->next_packet_queued > 0 &&
459+
if ((!implicit_fb || ep->next_packet_queued > 0) &&
445460
!list_empty(&ep->ready_playback_urbs)) {
446461
/* take URB out of FIFO */
447462
ctx = list_first_entry(&ep->ready_playback_urbs,
448463
struct snd_urb_ctx, ready_list);
449464
list_del_init(&ctx->ready_list);
450-
451-
packet = next_packet_fifo_dequeue(ep);
465+
if (implicit_fb)
466+
packet = next_packet_fifo_dequeue(ep);
452467
}
453468
spin_unlock_irqrestore(&ep->lock, flags);
454469

455470
if (ctx == NULL)
456471
return;
457472

458473
/* copy over the length information */
459-
for (i = 0; i < packet->packets; i++)
460-
ctx->packet_size[i] = packet->packet_size[i];
474+
if (implicit_fb) {
475+
for (i = 0; i < packet->packets; i++)
476+
ctx->packet_size[i] = packet->packet_size[i];
477+
}
461478

462479
/* call the data handler to fill in playback data */
463-
prepare_outbound_urb(ep, ctx);
480+
err = prepare_outbound_urb(ep, ctx, in_stream_lock);
481+
/* can be stopped during prepare callback */
482+
if (unlikely(!ep_state_running(ep)))
483+
break;
484+
if (err < 0) {
485+
/* push back to ready list again for -EAGAIN */
486+
if (err == -EAGAIN)
487+
push_back_to_ready_list(ep, ctx);
488+
else
489+
notify_xrun(ep);
490+
return;
491+
}
464492

465493
err = usb_submit_urb(ctx->urb, GFP_ATOMIC);
466494
if (err < 0) {
@@ -483,7 +511,6 @@ static void snd_complete_urb(struct urb *urb)
483511
{
484512
struct snd_urb_ctx *ctx = urb->context;
485513
struct snd_usb_endpoint *ep = ctx->ep;
486-
unsigned long flags;
487514
int err;
488515

489516
if (unlikely(urb->status == -ENOENT || /* unlinked */
@@ -504,17 +531,20 @@ static void snd_complete_urb(struct urb *urb)
504531
if (unlikely(!ep_state_running(ep)))
505532
goto exit_clear;
506533

507-
if (snd_usb_endpoint_implicit_feedback_sink(ep)) {
508-
spin_lock_irqsave(&ep->lock, flags);
509-
list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
534+
/* in low-latency and implicit-feedback modes, push back the
535+
* URB to ready list at first, then process as much as possible
536+
*/
537+
if (ep->lowlatency_playback ||
538+
snd_usb_endpoint_implicit_feedback_sink(ep)) {
539+
push_back_to_ready_list(ep, ctx);
510540
clear_bit(ctx->index, &ep->active_mask);
511-
spin_unlock_irqrestore(&ep->lock, flags);
512-
queue_pending_output_urbs(ep);
541+
snd_usb_queue_pending_output_urbs(ep, false);
513542
atomic_dec(&ep->submitted_urbs); /* decrement at last */
514543
return;
515544
}
516545

517-
prepare_outbound_urb(ep, ctx);
546+
/* in non-lowlatency mode, no error handling for prepare */
547+
prepare_outbound_urb(ep, ctx, false);
518548
/* can be stopped during prepare callback */
519549
if (unlikely(!ep_state_running(ep)))
520550
goto exit_clear;
@@ -807,8 +837,9 @@ void snd_usb_endpoint_set_sync(struct snd_usb_audio *chip,
807837
* Pass NULL to deactivate each callback.
808838
*/
809839
void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep,
810-
void (*prepare)(struct snd_usb_substream *subs,
811-
struct urb *urb),
840+
int (*prepare)(struct snd_usb_substream *subs,
841+
struct urb *urb,
842+
bool in_stream_lock),
812843
void (*retire)(struct snd_usb_substream *subs,
813844
struct urb *urb),
814845
struct snd_usb_substream *data_subs)
@@ -1166,10 +1197,6 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
11661197
INIT_LIST_HEAD(&u->ready_list);
11671198
}
11681199

1169-
/* total buffer bytes of all URBs plus the next queue;
1170-
* referred in pcm.c
1171-
*/
1172-
ep->nominal_queue_size = maxsize * urb_packs * (ep->nurbs + 1);
11731200
return 0;
11741201

11751202
out_of_memory:
@@ -1408,6 +1435,7 @@ int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock)
14081435
*/
14091436
int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
14101437
{
1438+
bool is_playback = usb_pipeout(ep->pipe);
14111439
int err;
14121440
unsigned int i;
14131441

@@ -1444,13 +1472,9 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
14441472

14451473
if (snd_usb_endpoint_implicit_feedback_sink(ep) &&
14461474
!(ep->chip->quirk_flags & QUIRK_FLAG_PLAYBACK_FIRST)) {
1447-
for (i = 0; i < ep->nurbs; i++) {
1448-
struct snd_urb_ctx *ctx = ep->urb + i;
1449-
list_add_tail(&ctx->ready_list, &ep->ready_playback_urbs);
1450-
}
1451-
14521475
usb_audio_dbg(ep->chip, "No URB submission due to implicit fb sync\n");
1453-
return 0;
1476+
i = 0;
1477+
goto fill_rest;
14541478
}
14551479

14561480
for (i = 0; i < ep->nurbs; i++) {
@@ -1459,10 +1483,18 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
14591483
if (snd_BUG_ON(!urb))
14601484
goto __error;
14611485

1462-
if (usb_pipeout(ep->pipe)) {
1463-
prepare_outbound_urb(ep, urb->context);
1464-
} else {
1465-
prepare_inbound_urb(ep, urb->context);
1486+
if (is_playback)
1487+
err = prepare_outbound_urb(ep, urb->context, true);
1488+
else
1489+
err = prepare_inbound_urb(ep, urb->context);
1490+
if (err < 0) {
1491+
/* stop filling at applptr */
1492+
if (err == -EAGAIN)
1493+
break;
1494+
usb_audio_dbg(ep->chip,
1495+
"EP 0x%x: failed to prepare urb: %d\n",
1496+
ep->ep_num, err);
1497+
goto __error;
14661498
}
14671499

14681500
err = usb_submit_urb(urb, GFP_ATOMIC);
@@ -1476,8 +1508,22 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
14761508
atomic_inc(&ep->submitted_urbs);
14771509
}
14781510

1511+
if (!i) {
1512+
usb_audio_dbg(ep->chip, "XRUN at starting EP 0x%x\n",
1513+
ep->ep_num);
1514+
goto __error;
1515+
}
1516+
14791517
usb_audio_dbg(ep->chip, "%d URBs submitted for EP 0x%x\n",
1480-
ep->nurbs, ep->ep_num);
1518+
i, ep->ep_num);
1519+
1520+
fill_rest:
1521+
/* put the remaining URBs to ready list */
1522+
if (is_playback) {
1523+
for (; i < ep->nurbs; i++)
1524+
push_back_to_ready_list(ep, ep->urb + i);
1525+
}
1526+
14811527
return 0;
14821528

14831529
__error:
@@ -1629,7 +1675,7 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
16291675
}
16301676

16311677
spin_unlock_irqrestore(&ep->lock, flags);
1632-
queue_pending_output_urbs(ep);
1678+
snd_usb_queue_pending_output_urbs(ep, false);
16331679

16341680
return;
16351681
}

sound/usb/endpoint.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ void snd_usb_endpoint_set_sync(struct snd_usb_audio *chip,
3030
struct snd_usb_endpoint *data_ep,
3131
struct snd_usb_endpoint *sync_ep);
3232
void snd_usb_endpoint_set_callback(struct snd_usb_endpoint *ep,
33-
void (*prepare)(struct snd_usb_substream *subs,
34-
struct urb *urb),
33+
int (*prepare)(struct snd_usb_substream *subs,
34+
struct urb *urb,
35+
bool in_stream_lock),
3536
void (*retire)(struct snd_usb_substream *subs,
3637
struct urb *urb),
3738
struct snd_usb_substream *data_subs);
@@ -48,5 +49,7 @@ int snd_usb_endpoint_implicit_feedback_sink(struct snd_usb_endpoint *ep);
4849
int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep,
4950
struct snd_urb_ctx *ctx, int idx,
5051
unsigned int avail);
52+
void snd_usb_queue_pending_output_urbs(struct snd_usb_endpoint *ep,
53+
bool in_stream_lock);
5154

5255
#endif /* __USBAUDIO_ENDPOINT_H */

0 commit comments

Comments
 (0)