Skip to content

drivers/usbhost: Fix xHCI faults on a conforming controller. - #19745

Merged
acassis merged 5 commits into
apache:masterfrom
Fishwaldo:upstream-usbhost-xhci
Aug 17, 2026
Merged

drivers/usbhost: Fix xHCI faults on a conforming controller.#19745
acassis merged 5 commits into
apache:masterfrom
Fishwaldo:upstream-usbhost-xhci

Conversation

@Fishwaldo

@Fishwaldo Fishwaldo commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

This replaces the previous contents of this PR. The single large commit
reviewers objected to has been split, and the rest of the work moved to
follow-up PRs so each can be reviewed on its own. This PR is now the first of
four and carries only the fixes needed to reach a device at all.

Five independent faults, one commit each:

  • Register access width. xHCI requires aligned accesses of each register's
    own size and a controller may ignore narrower ones. volatile does not pin
    the width: GCC 16.1.0 at -Os narrows a 32-bit load feeding a single-bit
    test into a byte load, so polling USBSTS for HCH never observes the halted
    state. Every accessor now launders the value through a register with an empty
    asm, on loads and stores. This is the only compiler-related fix in the set;
    the driver works with earlier compilers.
  • Zero scratchpad buffers. HCSPARAMS2 may report none, as QEMU's controller
    does. The driver sized the array from that count unconditionally and read the
    NULL from a zero-byte kmm_memalign() as -ENOMEM, so such a controller
    never started.
  • Halting. xhci_ctrl_halt() wrote USBCMD zero unconditionally and waited
    for HCH on a controller that was already halted, and cleared INTE and HSEE
    along with R/S.
  • Port reset. Eight PORTSC bits are write-one-to-clear, so writing back the
    value just read cleared PED and every change bit, disabling the port being
    reset.
  • Command completion. xhci_command() returned -ETIMEDOUT when a
    completion arrived without an interrupt, even though the fallback poll had
    already retrieved the event, so callers unwound work the controller had done.

Follow-ups, in order: separating the driver from the PCI bus, the data path
fixes for real devices, and hub support.

Impact

USBHOST_XHCI_PCI users only. No API or configuration change, and no
behavioural change on a controller that already worked.

Testing

Built for qemu-intel64:nsh with USBHOST_XHCI_PCI, USBHOST_MSC and
USBHOST_HIDKBD, driver object confirmed in the link.

Run at this commit under QEMU with -device qemu-xhci and a usb-storage
device:

nsh> ls /dev
 sda
nsh> mount -t vfat /dev/sda /mnt
nsh> cat /mnt/HELLO.TXT
qemu-xhci-regression-ok

Not tested standalone on hardware, and it cannot be: the EIC7700 EVB attaches
through include/nuttx/usb/xhci.h, which the next PR introduces. The full
four-PR series was exercised on that board, where a USB flash disk behind a
6-port hub mounts and reads.

@github-actions github-actions Bot added Size: XL The size of the change in this PR is very large. Consider breaking down the PR into smaller pieces. Area: USB labels Aug 8, 2026
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

MemBrowse Memory Report

No memory changes detected for:

acassis
acassis previously approved these changes Aug 8, 2026
Comment thread drivers/usbhost/usbhost_xhci_pci.c Outdated
Comment thread drivers/usbhost/usbhost_xhci_pci.c Outdated
Comment thread drivers/usbhost/usbhost_xhci.c Outdated
Comment thread drivers/usbhost/usbhost_xhci.c Outdated
Comment thread drivers/usbhost/usbhost_xhci.c Outdated
Comment thread drivers/usbhost/usbhost_xhci.c Outdated
@raiden00pl

Copy link
Copy Markdown
Member

@acassis did you even look through this massive PR or did you blindly approved?

this PR should be tested on real intel64 HW before merge

@raiden00pl raiden00pl left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

319aadf touches too many things. Please break this down into smaller parts because right now it's unclear what fixes are for gcc16 and what fixes qemu. Your description is misleading because this driver works with gcc version lower than 16. It looks like AI ​​couldn't find a real problem and fixed everything one by one and put it in one commit. The real issue here is gcc16 and memory access.

Was this PR completely generated by AI or did you verify its output? Some of the claims in it seem like BS, like this:

The driver worked that count into a size and asked the
allocator for it, and a zero-byte allocation returns NULL,
indistinguishable from being out of memory, so a controller asking for
no scratch space was refused for lack of it before it was ever started.

Comment thread drivers/usbhost/usbhost_xhci.c Outdated
@acassis

acassis commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

@acassis did you even look through this massive PR or did you blindly approved?

this PR should be tested on real intel64 HW before merge

@raiden00pl I look the diff code and for some files that github didn't accepted to show the diff I saw the final file, nothing too suspect here. He also provided the QEMU test results. Are you planing to do real test on real HW?

@linguini1 linguini1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please split this patch into multiple PRs, this is a massive code change for just one.

@raiden00pl

Copy link
Copy Markdown
Member

@acassis I'll test it on intel HW probably tomorrow

@Fishwaldo
Fishwaldo force-pushed the upstream-usbhost-xhci branch 2 times, most recently from e65e134 to d22191c Compare August 15, 2026 04:43
@Fishwaldo

Fishwaldo commented Aug 15, 2026

Copy link
Copy Markdown
Contributor Author

Hi @raiden00pl I'll split that large commit up into GCC and Qemu fixes. I originally squashed some commits together with a broad goal of:

  1. Get QEMU working again
  2. Split out PCI specific code so we could have a generic XHCI implementation to bolt PCI & directly mapped implementations (like the EIC7700) on top
  3. Get USB Hub working (as the StarPro64 uses a onboard hub between the SOC and ports

Agree it's a large change, but with only one other in tree board (the qemu-intel jumbo) I hoped you guys could accept it via one PR rather than multiple.

(Honest fact. I really don't have a lot of spare time to iterate on these PR's. We have had this running in somewhat of a production setting at work on an older 12 Frankenstein branch and I'm just trying to send these changes back as best I can during my spare time. I did use Claude to tidy up and forward port some of these changes but it's a mix of Human and AI fixes. - the scratchpad at 0 was human debugged as we didn't see it on our EIC7700 board at all. I don't know if that's a qemu quirk or legit, but it's what I observed trying to get things up and running)

xHCI requires aligned accesses of each register's own size, and a
controller may ignore narrower ones; QEMU's does.  volatile does not pin
the access width: GCC 16.1.0 at -Os narrows a 32-bit load feeding a
single bit test into a byte load, so polling USBSTS for HCH never
observes the halted state.

Launder each register value through a register with an empty asm, on
loads and stores both, so the access is the width the source specifies.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
HCSPARAMS2 may report zero scratchpad buffers; QEMU's does.  The driver
sized the array from that count unconditionally and read the NULL from a
zero byte kmm_memalign() as -ENOMEM, so such a controller never started.

Skip the allocation when no_scratch is zero, leaving DCBAA[0] clear.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
xhci_ctrl_halt() wrote USBCMD zero unconditionally and then waited for
HCH.  A controller that was never started is already halted, so the wait
ran to its full length, and clearing the whole register also dropped
INTE and HSEE.

Test HCH first, clear only R/S when it is set, bound the wait with
XHCI_HALT_TIMEOUT_MS, and report USBCMD and USBSTS on failure.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
Eight PORTSC bits are write-one-to-clear, so writing back a value just
read clears PED and every change bit that was set, disabling the port
being reset.  Mask them out using the new XHCI_PORTSC_RW1C.

The wait after reset also decided on its own counter rather than on the
port, reporting a timeout for a port that enabled on the last iteration.
Test PED, and report PORTSC when it does time out.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
xhci_command() returned -ETIMEDOUT when a completion arrived without an
interrupt, although the fallback poll had already retrieved the event,
so callers unwound work the controller had completed.

Use the event's completion code whichever path retrieved it.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Justin Hammond <justin@dynam.ac>
@Fishwaldo
Fishwaldo force-pushed the upstream-usbhost-xhci branch from d22191c to e0679d6 Compare August 16, 2026 09:06
@Fishwaldo Fishwaldo changed the title drivers/usbhost: Make the xHCI driver work, and support hubs. drivers/usbhost: Fix xHCI faults on a conforming controller. Aug 16, 2026
@github-actions github-actions Bot removed the Size: XL The size of the change in this PR is very large. Consider breaking down the PR into smaller pieces. label Aug 16, 2026
@raiden00pl

raiden00pl commented Aug 17, 2026

Copy link
Copy Markdown
Member

@Fishwaldo I've tested this patchset on Intel64 hardware. Everything from this PR and USB HUB PR works fine. Thanks.

@Fishwaldo

Copy link
Copy Markdown
Contributor Author

@raiden00pl Cheers for testing - Appreciate it :)

@acassis
acassis dismissed linguini1’s stale review August 17, 2026 13:10

it was divided in multiples commits and PRs

@acassis
acassis merged commit 3b7e453 into apache:master Aug 17, 2026
65 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: USB Size: M The size of the change in this PR is medium

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants