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 <ricard@groundbits.com>
Assisted-by: Claude (Anthropic Claude Code)
Signed-off-by: Ricard Rosson <ricard@groundbits.com>
This commit is contained in:
Ricard Rosson 2026-07-18 13:42:12 +01:00 committed by Alin Jerpelea
parent d5e6cd3aa5
commit 6555e3e283

View file

@ -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;