ricardgb commented on issue #19435:
URL: https://github.com/apache/nuttx/issues/19435#issuecomment-4984407428

   ## Bug 5 — the one that still broke macOS after the previous fixes: the 
rp2040/rp23xx DCD drops requests submitted while an endpoint is halted (the 
CSW-loss race)
   
   macOS still failed to mount with fixes 1-3 applied. The failing command 
turned out to be
   one the earlier validation never sent: macOS probes **MODE SENSE(6) with 
PAGE CODE 0x00**
   (write-protect header sniff; the IOUSBMassStorageDriver RwC trace shows CDB 
`1A 00 00 00`,
   allocation length 4 and then 0xC0). `usbmsc_modepage()` only implements 
pages 0x08/0x3F,
   so the command fails — which is fine and spec-legal: for a failed Hi>Di 
command with no
   data, `usbmsc_cmdfinishstate()` halts the bulk-IN endpoint (BOT 6.7.2) and
   `usbmsc_cmdstatusstate()` then submits the CSW (status = failed).
   
   The bug: `rp23xx_epsubmit()` / `rp2040_epsubmit()` **reject IN requests 
submitted while
   the endpoint is halted** (`stalled && in` -> abort with -EBUSY). The CSW is 
therefore
   dropped on the floor. When the host clears the halt and reads the CSW, the 
endpoint NAKs
   forever; macOS times out after 30 s and enters a 
Bulk-Only-reset/device-reset spiral that
   ends with the port disabled ("persistent enumeration failures").
   
   This is precisely the race documented for over a decade in the header 
comment of
   `drivers/usbdev/usbmsc_scsi.c` (David Hewson's analysis): "the subsequent 
transfer for
   the CSW would be dropped on the floor (by the epsubmit() function) if the 
end point was
   still stalled". The `USBMSC_STALL_RACEWAR` sleep-workaround was active 
(these chips do not
   declare `CONFIG_ARCH_USBDEV_STALLQUEUE`), but it only survives hosts that 
clear the halt
   within its 100 ms sleep. Linux's usb-storage does; macOS does not — and 
Linux's SCSI probe
   also never sends a failing MODE SENSE page (it uses 0x3F), which is why the 
earlier
   validation passed while macOS kept failing.
   
   ### Fix (both rp2040_usbdev.c and rp23xx_usbdev.c): implement stall queuing 
in the DCD
   
   1. `epsubmit()`: while the endpoint is halted, requests are queued but the 
hardware is
      not armed (IN and OUT — arming an OUT endpoint rewrites the DPSRAM 
buffer-control
      word and would silently clear the STALL bit). The -EBUSY abort is removed.
   2. `epstall(stall)`: after applying the hardware stall, cancel in-flight IN 
requests —
      their armed buffer was just disarmed and would never complete.
   3. `epstall(resume)`: after clearing the halt (and resetting the data 
toggle), re-arm
      the head of the request queue — this delivers the queued CSW.
   4. Buffer-status IRQ: ignore completions latched for transfers aborted by a 
halt.
   5. `arch/arm/Kconfig`: RP2040/RP23XX now `select ARCH_USBDEV_STALLQUEUE`, 
which also
      retires the RACEWAR's two 100 ms sleeps per failed command.
   
   The class driver is untouched by this fix (its behavior is BOT-correct).
   
   ### Validation (silicon, RP2350 / Pico 2 W, composite ACM+NCM+MSC, Linux 
host)
   
   An important subtlety: **Linux cannot reproduce this bug via 
sg_raw/usb-storage**, because
   usb-storage clears the halt within microseconds — inside the RACEWAR's 100 
ms window — so
   the CSW submit finds the endpoint already resumed. (`sg_raw -r 4 /dev/sgX 1a 
00 00 00 04
   00` on the *broken* firmware completes fine in 0.23 s, of which 0.2 s are 
the two RACEWAR
   sleeps.) The repro needs macOS's *timing* over raw usbfs: CBW MODE SENSE(6) 
page 0x00
   alloc 4 → data-IN stall → **wait 1 s** (past the RACEWAR window) → 
clear-halt → read CSW.
   
   A/B on the same board, same script, same 1 s delay:
   
   - **Before (bugs 1-3 fixed, no stall queuing):** data-IN `EPIPE` at +0.10 s 
(RACEWAR sleep
     visible), clear-halt OK, **CSW read `ETIMEDOUT`** — the CSW had been 
aborted with -EBUSY
     at submit time. This is the macOS failure exactly (its log then shows a 30 
s bulk-IN
     timeout followed by the BOT-reset/device-reset spiral until the port is 
disabled).
   - **After (stall queuing):** data-IN `EPIPE` immediately (RACEWAR retired), 
clear-halt OK,
     **CSW delivered instantly**: status=FAIL(1), dCSWDataResidue=4, tag 
correct.
   
   Full macOS-equivalent probe replay over raw usbfs (TUR, INQUIRY ×2, MODE 
SENSE page 0
   alloc 4 and 0xC0 with clear-halt recovery and CSW 
signature/tag/status/residue checks,
   REQUEST SENSE, READ CAPACITY exact-8, MODE SENSE 0x3F control, START STOP 
UNIT ×2
   variants, MSRESET + clear-halts mid-probe): **5 cycles, zero failures**.
   
   Regressions, all clean: page-0 MODE SENSE through usb-storage now returns 
CHECK
   CONDITION / Illegal Request in 0.017 s (previously 0.23 s through the 
RACEWAR sleeps);
   MODE SENSE 0x3F, INQUIRY 255, REQUEST SENSE 252, READ CAPACITY exact-8 all 
Good;
   GET MAX LUN + MSRESET 10/10 via raw usbfs; FAT drive mounts and full-reads; 
CDC-NCM and
   CDC-ACM up; warm reboots re-enumerate cleanly.
   
   macOS mount retest is next; will report the result here.
   
   ### Remaining loose end (honest)
   
   In the macOS failure log there is also a ~1 s EP0 control-transfer timeout 
immediately
   after the first bulk-IN stall, before the 30 s CSW timeout. Clear-halt is 
handled directly
   in the USB IRQ and should be instant, so this is not fully explained by the 
CSW loss;
   candidates are a SIE disturbance from writing buffer-control while the host 
is actively
   IN-polling the endpoint, or the deferred MSRESET response racing a 1 s host 
deadline. If
   it persists on the macOS retest with this fix it will be investigated 
separately.
   
   ## Disclosure
   
   As above: this investigation and the fixes were performed by an AI agent 
(Claude Code),
   operated and directed by the submitter, and reviewed by the submitter before 
posting.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to