From 6555e3e2832abd9b45c52e514902b49eda183658 Mon Sep 17 00:00:00 2001 From: Ricard Rosson Date: Sat, 18 Jul 2026 13:42:12 +0100 Subject: [PATCH] drivers/usbdev/cdcncm: send TX immediately, not after a tick-quantized delay cdcncm_send() defers each transmit with MSEC2TICK(CDCNCM_DGRAM_COMBINE_PERIOD) (1 ms). MSEC2TICK() rounds up to the system tick, so at the default 100 Hz tick the "1 ms" coalescing window becomes a full 10 ms tick (10-20 ms with phase), adding that latency to every single-datagram reply (ICMP echo, TCP ACK, one-MSS HTTP segment) and dominating the CDC-NCM round-trip time. The window only coalesces datagrams appended within the same synchronous TX burst (already queued before the worker runs), so an inter-burst delay adds latency without batching benefit in the common case. Fire the transmit worker immediately (delay 0); within-burst coalescing is preserved. On RP2350 (Pico 2 W) USB-NIC at 100 Hz tick: ping RTT 21.7 -> 2.8 ms, a 257 KB HTTP download 5.79 -> 0.92 s (44.5 -> 279 KB/s). Signed-off-by: Ricard Rosson Assisted-by: Claude (Anthropic Claude Code) Signed-off-by: Ricard Rosson --- drivers/usbdev/cdcncm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/usbdev/cdcncm.c b/drivers/usbdev/cdcncm.c index d9fa738c600..7f10e5355e3 100644 --- a/drivers/usbdev/cdcncm.c +++ b/drivers/usbdev/cdcncm.c @@ -1331,8 +1331,13 @@ 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 to the work thread with zero delay. A non-zero delay is + * rounded up to a full tick (10ms at 100Hz), which dominated the + * USB-NIC round-trip; delay 0 wakes the worker immediately while + * still coalescing datagrams appended in the same TX burst. + */ + + work_queue(ETHWORK, &self->delaywork, cdcncm_transmit_work, self, 0); } return OK;