Skip to content

Commit 5c56bc8

Browse files
committed
[nrf fromtree] usb: device_next: uac2: Double buffering on data OUT endpoints
Enable double buffering on data OUT endpoints to allow USB stack to enqueue next transfer as soon as possible. This is especially useful when operating at High-Speed where there is significantly less time between subsequent SOF packets. Signed-off-by: Tomasz Moń <[email protected]> (cherry picked from commit 2f343bf)
1 parent 2e09426 commit 5c56bc8

File tree

1 file changed

+15
-6
lines changed

1 file changed

+15
-6
lines changed

subsys/usb/device_next/class/usbd_uac2.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ LOG_MODULE_REGISTER(usbd_uac2, CONFIG_USBD_UAC2_LOG_LEVEL);
2828
IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \
2929
+ AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node) \
3030
+ AS_IS_USB_ISO_IN(node) /* ISO IN double buffering */ \
31+
+ AS_IS_USB_ISO_OUT(node) /* ISO OUT double buffering */ \
3132
+ AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node)))
3233
#define COUNT_UAC2_EP_BUFFERS(i) \
3334
+ DT_PROP(DT_DRV_INST(i), interrupt_endpoint) \
@@ -348,6 +349,7 @@ static void schedule_iso_out_read(struct usbd_class_data *const c_data,
348349
const struct uac2_cfg *cfg = dev->config;
349350
struct uac2_ctx *ctx = dev->data;
350351
struct net_buf *buf;
352+
atomic_t *queued_bits = &ctx->as_queued;
351353
void *data_buf;
352354
int as_idx = terminal_to_as_interface(dev, terminal);
353355
int ret;
@@ -364,16 +366,19 @@ static void schedule_iso_out_read(struct usbd_class_data *const c_data,
364366
return;
365367
}
366368

367-
if (atomic_test_and_set_bit(&ctx->as_queued, as_idx)) {
368-
/* Transfer already queued - do not requeue */
369-
return;
369+
if (atomic_test_and_set_bit(queued_bits, as_idx)) {
370+
queued_bits = &ctx->as_double;
371+
if (atomic_test_and_set_bit(queued_bits, as_idx)) {
372+
/* Transfer already double queued - nothing to do */
373+
return;
374+
}
370375
}
371376

372377
/* Prepare transfer to read audio OUT data from host */
373378
data_buf = ctx->ops->get_recv_buf(dev, terminal, mps, ctx->user_data);
374379
if (!data_buf) {
375380
LOG_ERR("No data buffer for terminal %d", terminal);
376-
atomic_clear_bit(&ctx->as_queued, as_idx);
381+
atomic_clear_bit(queued_bits, as_idx);
377382
return;
378383
}
379384

@@ -386,15 +391,15 @@ static void schedule_iso_out_read(struct usbd_class_data *const c_data,
386391
*/
387392
ctx->ops->data_recv_cb(dev, terminal,
388393
data_buf, 0, ctx->user_data);
389-
atomic_clear_bit(&ctx->as_queued, as_idx);
394+
atomic_clear_bit(queued_bits, as_idx);
390395
return;
391396
}
392397

393398
ret = usbd_ep_enqueue(c_data, buf);
394399
if (ret) {
395400
LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep);
396401
net_buf_unref(buf);
397-
atomic_clear_bit(&ctx->as_queued, as_idx);
402+
atomic_clear_bit(queued_bits, as_idx);
398403
}
399404
}
400405

@@ -814,6 +819,10 @@ static int uac2_request(struct usbd_class_data *const c_data, struct net_buf *bu
814819
if (USB_EP_DIR_IS_OUT(ep)) {
815820
ctx->ops->data_recv_cb(dev, terminal, buf->__buf, buf->len,
816821
ctx->user_data);
822+
if (buf->frags) {
823+
ctx->ops->data_recv_cb(dev, terminal, buf->frags->__buf,
824+
buf->frags->len, ctx->user_data);
825+
}
817826
} else if (!is_feedback) {
818827
ctx->ops->buf_release_cb(dev, terminal, buf->__buf, ctx->user_data);
819828
if (buf->frags) {

0 commit comments

Comments
 (0)