usb: device_next: cdc_acm: clear TX_FIFO_BUSY on disable; retry when stuck - #1
usb: device_next: cdc_acm: clear TX_FIFO_BUSY on disable; retry when stuck#1Mikefly123 wants to merge 1 commit into
Conversation
…stuck Problem: if the USB host stops issuing IN tokens while a CDC-ACM TX transfer is in flight (e.g. a host-side driver that pauses polling without disconnecting), CDC_ACM_TX_FIFO_BUSY is left set indefinitely. The existing error-completion path clears the flag on disconnect or transfer cancellation, but a passive stall that never fires a completion leaves it stuck. Once stuck, uart_poll_out() keeps scheduling cdc_acm_tx_fifo_handler(), but the handler returns immediately on every invocation because the busy check short-circuits it, so the TX path stops draining permanently even after the host resumes polling. Mechanism: usbd_cdc_acm_disable() now clears CDC_ACM_TX_FIFO_BUSY, guaranteeing the flag starts clean on the next enable/reconnect cycle. Additionally, when cdc_acm_tx_fifo_handler() finds BUSY already set and the ring buffer still has data pending, it reschedules itself after a 10 ms delay instead of returning permanently. If BUSY clears normally when the in-flight transfer completes, the retry fires once more and is a no-op (the ring buffer is already drained). If BUSY is stuck because the host stopped acknowledging the IN endpoint, the handler keeps retrying every 10 ms at negligible CPU cost until the host resumes polling and the transfer completes. Fix: the pending retry re-arms the IN endpoint as soon as the host resumes issuing IN tokens, instead of requiring an explicit disable/enable cycle (e.g. USB replug) to recover the TX path. Signed-off-by: Michael Pham <phamlongmichael@gmail.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Stack position 1/2 (stack zephyrproject-rtos#4, base of stack, targets |
Pruning this PR — validated by a CI negative control (2026-08-01)Closing as part of the pre-merge trim of the USP radio changeset. Unlike the The argument that was made for keeping itThat Why that does not holdThe integration runner is Linux, and this is a macOS host quirk.
The Korad argument is backwards. The power-cycle cuts power to the board. The negative controlPhase A/B never ran one — every soak ran with this patch present, which the Full CI green, run ConsequenceWith this pruned, the fork's delta against The value that remains is real but local: on the macOS HWIL bench this patch Credit where due: the prune was proposed by @Mikefly123 pushing back on the |
|
Closed as pruned — validated by the CI negative control on pcr zephyrproject-rtos#487 (stock Zephyr v4.4.1, full green including integration-uart and integration-radio on real hardware). See the rationale comment above. Branch retained. |
Base branch note
This fork's
maintracks upstreamzephyrproject-rtos/zephyrmain, which has divergedsubstantially from the v4.4.1 release this organization currently pins. To keep this PR's
diff scoped to the actual change (rather than the full main/v4.4.1 delta), it targets a new
v4.4.1-basebranch pushed to point at the upstreamv4.4.1tag commit(
1f6485eca25431b5ff27ce9a754218c9e559bbbb).What
Clears
CDC_ACM_TX_FIFO_BUSYinusbd_cdc_acm_disable(), and makescdc_acm_tx_fifo_handler()self-reschedule with a 10 ms delay when it findsBUSYalready set and the TX ring buffer still has data pending.
Why
If a USB host stops issuing IN tokens while a CDC-ACM TX transfer is in flight (a
passive stall, not a disconnect),
CDC_ACM_TX_FIFO_BUSYis left set indefinitely. Theexisting error-completion path only clears the flag on disconnect/cancel
(
ECONNABORTED), so a stall that never fires a completion leaves the flag stuck.Once stuck,
uart_poll_out()keeps scheduling the TX FIFO work handler, but thehandler returns immediately every time because of the busy short-circuit — the TX
path stops draining permanently, even after the host resumes polling, until an
explicit disable/enable cycle (e.g. a USB replug).
The fix re-arms the drain:
usbd_cdc_acm_disable()clears the busy flag so it startsclean on the next enable/reconnect, and the handler retries every 10 ms while busy
and non-empty, so the TX path recovers on its own as soon as the host resumes
acknowledging the IN endpoint.
This has been carried and HWIL-proven as a downstream patch on PROVES FCB v5e
(RP2350, macOS USB host), where the observed failure mode was secondary silence on
the USB CDC-ACM TX path after an initial burst of frames: the host driver paused
issuing IN tokens while a downstream consumer processed the burst,
TX_FIFO_BUSYstuck, and the console/telemetry path never recovered without a physical replug.
Companion HWIL/CI verification: Open-Source-Space-Foundation/proves-core-reference#439
Not intended for merge into upstream
zephyrproject-rtos/zephyrfrom this fork.