Skip to content

Commit fe4d8a6

Browse files
jfischer-nofabiobaltieri
authored andcommitted
usb: device_next: use delayable work for TX FIFO in CDC ACM
Use delayable work to reduce CPU load when there is no transfer flow in the host direction. This also improves the performance of poll out, as introduced in commit commit fed6bde ("usb: device: cdc_acm: send more than 1 byte in poll out") for the legacy CDC ACM implementation. Signed-off-by: Johann Fischer <[email protected]>
1 parent 4875aa3 commit fe4d8a6

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

subsys/usb/device_next/class/usbd_cdc_acm.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ struct cdc_acm_uart_data {
109109
*/
110110
bool flow_ctrl;
111111
/* USBD CDC ACM TX fifo work */
112-
struct k_work tx_fifo_work;
112+
struct k_work_delayable tx_fifo_work;
113113
/* USBD CDC ACM RX fifo work */
114114
struct k_work rx_fifo_work;
115115
atomic_t state;
@@ -140,6 +140,12 @@ static ALWAYS_INLINE int cdc_acm_work_submit(struct k_work *work)
140140
return k_work_submit_to_queue(&cdc_acm_work_q, work);
141141
}
142142

143+
static ALWAYS_INLINE int cdc_acm_work_schedule(struct k_work_delayable *work,
144+
k_timeout_t delay)
145+
{
146+
return k_work_schedule_for_queue(&cdc_acm_work_q, work, delay);
147+
}
148+
143149
static ALWAYS_INLINE bool check_wq_ctx(const struct device *dev)
144150
{
145151
return k_current_get() == k_work_queue_thread_get(&cdc_acm_work_q);
@@ -277,7 +283,7 @@ static void usbd_cdc_acm_enable(struct usbd_class_data *const c_data)
277283
cdc_acm_work_submit(&data->irq_cb_work);
278284
} else {
279285
/* Queue pending TX data on IN endpoint */
280-
cdc_acm_work_submit(&data->tx_fifo_work);
286+
cdc_acm_work_schedule(&data->tx_fifo_work, K_NO_WAIT);
281287
}
282288
}
283289
}
@@ -520,13 +526,14 @@ static int cdc_acm_send_notification(const struct device *dev,
520526
*/
521527
static void cdc_acm_tx_fifo_handler(struct k_work *work)
522528
{
529+
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
523530
struct cdc_acm_uart_data *data;
524531
struct usbd_class_data *c_data;
525532
struct net_buf *buf;
526533
size_t len;
527534
int ret;
528535

529-
data = CONTAINER_OF(work, struct cdc_acm_uart_data, tx_fifo_work);
536+
data = CONTAINER_OF(dwork, struct cdc_acm_uart_data, tx_fifo_work);
530537
c_data = data->c_data;
531538

532539
if (!atomic_test_bit(&data->state, CDC_ACM_CLASS_ENABLED)) {
@@ -541,7 +548,7 @@ static void cdc_acm_tx_fifo_handler(struct k_work *work)
541548

542549
buf = cdc_acm_buf_alloc(cdc_acm_get_bulk_in(c_data));
543550
if (buf == NULL) {
544-
cdc_acm_work_submit(&data->tx_fifo_work);
551+
cdc_acm_work_schedule(&data->tx_fifo_work, K_MSEC(1));
545552
return;
546553
}
547554

@@ -819,7 +826,7 @@ static void cdc_acm_irq_cb_handler(struct k_work *work)
819826

820827
if (data->tx_fifo.altered) {
821828
LOG_DBG("tx fifo altered, submit work");
822-
cdc_acm_work_submit(&data->tx_fifo_work);
829+
cdc_acm_work_schedule(&data->tx_fifo_work, K_NO_WAIT);
823830
}
824831

825832
if (atomic_test_bit(&data->state, CDC_ACM_IRQ_RX_ENABLED) &&
@@ -887,7 +894,11 @@ static void cdc_acm_poll_out(const struct device *dev, const unsigned char c)
887894
k_msleep(1);
888895
}
889896

890-
cdc_acm_work_submit(&data->tx_fifo_work);
897+
/* Schedule with minimal timeout to make it possible to send more than
898+
* one byte per USB transfer. The latency increase is negligible while
899+
* the increased throughput and reduced CPU usage is easily observable.
900+
*/
901+
cdc_acm_work_schedule(&data->tx_fifo_work, K_MSEC(1));
891902
}
892903

893904
#ifdef CONFIG_UART_LINE_CTRL
@@ -1006,7 +1017,7 @@ static int usbd_cdc_acm_preinit(const struct device *dev)
10061017

10071018
k_thread_name_set(&cdc_acm_work_q.thread, "cdc_acm_work_q");
10081019

1009-
k_work_init(&data->tx_fifo_work, cdc_acm_tx_fifo_handler);
1020+
k_work_init_delayable(&data->tx_fifo_work, cdc_acm_tx_fifo_handler);
10101021
k_work_init(&data->rx_fifo_work, cdc_acm_rx_fifo_handler);
10111022
k_work_init(&data->irq_cb_work, cdc_acm_irq_cb_handler);
10121023

0 commit comments

Comments
 (0)