Skip to content

Commit

Permalink
usbd: device_next: cdc: wait IN EP ready before enqueue data to EP
Browse files Browse the repository at this point in the history
Under the current structure of usbd_cdc_acm, there is a possibility that
TX data is enqueued to UDC driver before the previous transaction is
completed, hence causing the dropped data. This commit adds a mechanism
for usbd_cdc_acm driver to wait for IN endpoint to complete existing
transaction before allows the subsequent transaction to be enqueued.

Signed-off-by: Chew Zeh Yang <[email protected]>

usbd: device_next: cdc: fix possible CPU hogging issue

As pointed out by tmon-nordic, the method to re-queue CDC tx transaction
has possible issue of CPU hogging that could start system workqueue and
lower priority thread. Instead of keep requeing the tx_fifo work, simply
raise altered flag. The pending TX transaction will be triggered when
TX transfer completion interrupt is raised.

Signed-off-by: Chew Zeh Yang <[email protected]>
  • Loading branch information
zeonchew committed Sep 30, 2024
1 parent 7e892f8 commit 27486c5
Showing 1 changed file with 9 additions and 0 deletions.
9 changes: 9 additions & 0 deletions subsys/usb/device_next/class/usbd_cdc_acm.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ UDC_BUF_POOL_DEFINE(cdc_acm_ep_pool,
#define CDC_ACM_IRQ_TX_ENABLED 3
#define CDC_ACM_RX_FIFO_BUSY 4
#define CDC_ACM_LOCK 5
#define CDC_ACM_TX_EP_BUSY 6

static struct k_work_q cdc_acm_work_q;
static K_KERNEL_STACK_DEFINE(cdc_acm_stack,
Expand Down Expand Up @@ -215,6 +216,8 @@ static int usbd_cdc_acm_request(struct usbd_class_data *const c_data,

if (bi->ep == cdc_acm_get_bulk_out(c_data)) {
atomic_clear_bit(&data->state, CDC_ACM_RX_FIFO_BUSY);
} else if (bi->ep == cdc_acm_get_bulk_in(c_data)) {
atomic_clear_bit(&data->state, CDC_ACM_TX_EP_BUSY);
}

goto ep_request_error;
Expand All @@ -236,6 +239,7 @@ static int usbd_cdc_acm_request(struct usbd_class_data *const c_data,

if (bi->ep == cdc_acm_get_bulk_in(c_data)) {
/* TX transfer completion */
atomic_clear_bit(&data->state, CDC_ACM_TX_EP_BUSY);
if (data->cb) {
cdc_acm_work_submit(&data->irq_cb_work);
}
Expand Down Expand Up @@ -540,6 +544,11 @@ static void cdc_acm_tx_fifo_handler(struct k_work *work)
return;
}

if (atomic_test_and_set_bit(&data->state, CDC_ACM_TX_EP_BUSY)) {
data->tx_fifo.altered = true;
goto tx_fifo_handler_exit;
}

buf = cdc_acm_buf_alloc(cdc_acm_get_bulk_in(c_data));
if (buf == NULL) {
cdc_acm_work_submit(&data->tx_fifo_work);
Expand Down

0 comments on commit 27486c5

Please sign in to comment.