Skip to content

Commit f6b8468

Browse files
committed
usb: device_next: class: cdc_acm: batch writes
Do not artificially limit the size of the USB request to the endpoint size, as this introduces multiple round trips through the CDC ACM class implementation. The USB stack handles packetizing to the maximum endpoint size. The maximum allocation size is limited to prevent starving other USB users. Throughput testing on a nRF52840DK with `CONFIG_UDC_BUF_POOL_SIZE=1024` shows a throughput increase from ~1.7 Mbps to ~2.7 Mbps. Signed-off-by: Jordan Yates <[email protected]>
1 parent af04b31 commit f6b8468

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

subsys/usb/device_next/class/usbd_cdc_acm.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,10 @@ UDC_BUF_POOL_DEFINE(cdc_acm_ep_pool,
135135
USBD_MAX_BULK_MPS, sizeof(struct udc_buf_info), NULL);
136136

137137
static struct net_buf *cdc_acm_buf_alloc(struct usbd_class_data *const c_data,
138-
const uint8_t ep)
138+
const uint8_t ep, const size_t size_hint)
139139
{
140140
ARG_UNUSED(c_data);
141+
ARG_UNUSED(size_hint);
141142
struct net_buf *buf = NULL;
142143
struct udc_buf_info *bi;
143144

@@ -157,9 +158,21 @@ static struct net_buf *cdc_acm_buf_alloc(struct usbd_class_data *const c_data,
157158
* common (UDC) buffer, as this results in a smaller footprint.
158159
*/
159160
static struct net_buf *cdc_acm_buf_alloc(struct usbd_class_data *const c_data,
160-
const uint8_t ep)
161+
const uint8_t ep, const size_t size_hint)
161162
{
162-
return usbd_ep_buf_alloc(c_data, ep, USBD_MAX_BULK_MPS);
163+
/* The lower layers handle packetizing to the endpoint MPS, therefore
164+
* allocating buffers largers than the endpoint MPS reduces the number
165+
* of round trips through this class driver when the TX FIFO size is
166+
* larger than the endpoint MPS, improving throughput.
167+
*
168+
* Limit the maximum allocation size to 1/4 of the total pool size
169+
* to prevent starving other USB users. Ensure the maximum allocation
170+
* never drops below USBD_MAX_BULK_MPS.
171+
*/
172+
size_t max_alloc = max(USBD_MAX_BULK_MPS, CONFIG_UDC_BUF_POOL_SIZE / 4);
173+
size_t alloc_size = min(max_alloc, size_hint);
174+
175+
return usbd_ep_buf_alloc(c_data, ep, alloc_size);
163176
}
164177
#endif /* CONFIG_USBD_CDC_ACM_BUF_POOL */
165178

@@ -651,7 +664,8 @@ static void cdc_acm_tx_fifo_handler(struct k_work *work)
651664
return;
652665
}
653666

654-
buf = cdc_acm_buf_alloc(c_data, cdc_acm_get_bulk_in(c_data));
667+
buf = cdc_acm_buf_alloc(c_data, cdc_acm_get_bulk_in(c_data),
668+
ring_buf_size_get(data->tx_fifo.rb));
655669
if (buf == NULL) {
656670
atomic_clear_bit(&data->state, CDC_ACM_TX_FIFO_BUSY);
657671
cdc_acm_work_schedule(&data->tx_fifo_work, K_MSEC(1));
@@ -707,7 +721,7 @@ static void cdc_acm_rx_fifo_handler(struct k_work *work)
707721
return;
708722
}
709723

710-
buf = cdc_acm_buf_alloc(c_data, cdc_acm_get_bulk_out(c_data));
724+
buf = cdc_acm_buf_alloc(c_data, cdc_acm_get_bulk_out(c_data), USBD_MAX_BULK_MPS);
711725
if (buf == NULL) {
712726
return;
713727
}

0 commit comments

Comments
 (0)