mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
Two device-controller defects that break standard host error recovery, found while root-causing why macOS never mounts a NuttX mass-storage function (full analysis and host traces in apache/nuttx#19435): 1. epsubmit() aborted (-EBUSY) any IN request submitted while the endpoint was halted. The mass storage class halts bulk-IN for a failed device-to-host command (BOT-legal) and then submits the CSW; the CSW was dropped on the floor, so after the host's Clear-Halt the endpoint NAKed forever and the host timed out (macOS: 30 s, then a Bulk-Only-reset/device-reset spiral until it disables the port). This is exactly the race documented for years in the usbmsc_scsi.c header (David Hewson's analysis); the USBMSC_STALL_RACEWAR sleep workaround only survives hosts that clear the halt within 100 ms -- Linux does, macOS does not, which is why Linux testing never saw it. Implement the stall-queueing contract instead: requests submitted while an endpoint is halted are queued without arming the hardware (arming rewrites the buffer control word and would silently clear the STALL bit); a halt terminates any in-flight IN transfer (its hardware buffer is disarmed by the STALL write and would never complete); clearing the halt resets the data toggle and re-arms the head of the queue; stale buffer completions latched for transfers aborted by a halt are ignored. RP2040/RP23XX now select ARCH_USBDEV_STALLQUEUE, which also retires the RACEWAR's two 100 ms sleeps per failed command. 2. The USB_REQ_GETSTATUS handler in ep0setup() validated the request but never queued the two-byte response, for all three recipients (device/interface/endpoint), so EP0 NAKed the host's data stage forever and every GET STATUS timed out. macOS issues GetPipeStatus = GET STATUS(endpoint) on a halted pipe before running Bulk-Only reset recovery and hit this on every probe; lsusb -v's device-status query hangs on it as well. Send the response: endpoint recipient reports the halt bit, device recipient reports self-powered, interface reports zeros; the status stage is armed by handle_zlp() exactly as for class-dispatched IN transfers. Validated on RP2350 silicon (Raspberry Pi Pico 2 W, composite CDC-ACM + CDC-NCM + USBMSC): pre-fix, a raw-usbfs replay of macOS's sequence and timing reproduced both defects deterministically (CSW read ETIMEDOUT after a delayed clear-halt; all GET STATUS variants ETIMEDOUT). Post-fix: the CSW survives the halt and is delivered after Clear-Halt with correct tag/status/residue across a post-stall delay sweep of 0-1000 ms; all GET STATUS variants answer immediately with correct halt reporting; no regressions in the exact-length SCSI suite, Bulk-Only reset, FAT mount and full reads, CDC-NCM/ACM, or warm reboots; and macOS now mounts the volume (together with the companion usbmsc fixes). The rp2040 driver shares the code and receives the identical fix (build-tested). Assisted-by: Claude (Anthropic Claude Code) Signed-off-by: Ricard Rosson <ricard@groundbits.com> |
||
|---|---|---|
| .. | ||
| arm | ||
| arm64 | ||
| avr | ||
| ceva | ||
| dummy | ||
| hc | ||
| mips | ||
| misoc | ||
| or1k | ||
| renesas | ||
| risc-v | ||
| sim | ||
| sparc | ||
| tricore | ||
| x86 | ||
| x86_64 | ||
| xtensa | ||
| z16 | ||
| z80 | ||
| CMakeLists.txt | ||
| Kconfig | ||