cdcacm_sndpacket() runs from task context and from the bulk IN
completion callback, which may be interrupt context. cdcuart_dmasend()
advances the xmit tail non-atomically, so a completion arriving mid
setup re-sends the same region and advances the tail past the head,
re-transmitting a ring of stale data.
c497c5feb0 dropped the critical section that used to cover this.
Restore it with priv->lock held across the setup and EP_SUBMIT; the
submit must stay inside to keep request order. cdcuart_dmasend() now
runs with the lock held, so its own acquisition is removed.
The race needs the writer to keep the ring non-empty across
completions, so it only appears at high sustained write rates. On
nRF52840, 131072-byte writes were received as ~147600 bytes - one extra
CDCACM_TXBUFSIZE of stale data per hit. With this change the host
receives exactly what was sent.
Assisted-by: Claude Code
Signed-off-by: raiden00pl <raiden00@railab.me>