diff --git a/drivers/usbdev/cdcncm.c b/drivers/usbdev/cdcncm.c index d528d8f0da4c2..d892c563deb60 100644 --- a/drivers/usbdev/cdcncm.c +++ b/drivers/usbdev/cdcncm.c @@ -1302,8 +1302,18 @@ static int cdcncm_send(FAR struct netdev_lowerhalf_s *dev, FAR netpkt_t *pkt) } else { - work_queue(ETHWORK, &self->delaywork, cdcncm_transmit_work, self, - MSEC2TICK(CDCNCM_DGRAM_COMBINE_PERIOD)); + /* Defer the transmit to the work thread so the caller is not blocked + * on wrreq_idle, but do so with ZERO delay. A non-zero delay here is + * quantized to the system tick: MSEC2TICK(1) rounds *up* to a full + * tick (10ms at the default 100Hz), so the reply to every single + * datagram (ping, TCP ACK, one-MSS HTTP segment) was being held for + * 10-20ms, dominating the USB-NIC round-trip time. Delay 0 wakes the + * work thread immediately (sub-ms) while still coalescing any further + * datagrams that the network stack appends in the same TX burst before + * the worker gets to run. + */ + + work_queue(ETHWORK, &self->delaywork, cdcncm_transmit_work, self, 0); } return OK;