Skip to content

EHCI bug hunt & reinit on host system error#667

Open
adamgreloch wants to merge 18 commits into
masterfrom
adamgreloch/usb-fixes
Open

EHCI bug hunt & reinit on host system error#667
adamgreloch wants to merge 18 commits into
masterfrom
adamgreloch/usb-fixes

Conversation

@adamgreloch

@adamgreloch adamgreloch commented Jun 1, 2026

Copy link
Copy Markdown
Member

Description

Motivation and Context

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Chore (refactoring, style fixes, git/CI config, submodule management, no code logic changes)

How Has This Been Tested?

  • Already covered by automatic testing.
  • New test added: (add PR link here).
  • Tested by hand on: SEN

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing linter checks and tests passed.
  • My changes generate no new compilation warnings for any of the targets.

Special treatment

  • This PR needs additional PRs to work (list the PRs, preferably in merge-order).
  • I will merge this PR by myself when appropriate.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the EHCI USB driver to improve stability and error recovery. Key changes include replacing infinite polling loops with a timed ehci_handshake helper, implementing a controller reset mechanism (ehci_resetController) to recover from Host System Errors, utilizing atomic operations for status flags, and adding teardown routines for periodic and asynchronous lists. However, several critical issues were identified in the review: incorrect indexing of the uint16_t array desc->wData leads to an out-of-bounds write during UTF-16 encoding; modifying node->next in ehci_tearDownPeriodic corrupts shared periodic lists and causes memory leaks; the 20ms port reset handshake timeout is too short and may cause premature timeouts; and ignoring the return value of ehci_stopAsync in ehci_transferDequeue could lead to race conditions if the controller fails to stop.

Comment thread usb/ehci/ehci-hub.c
Comment thread usb/ehci/ehci.c
Comment thread usb/ehci/ehci-hub.c Outdated
Comment thread usb/ehci/ehci.c Outdated
@github-actions

github-actions Bot commented Jun 1, 2026

Copy link
Copy Markdown

Unit Test Results

10 890 tests  ±0   10 220 ✅ ±0   54m 25s ⏱️ + 1m 26s
   680 suites ±0      670 💤 ±0 
     1 files   ±0        0 ❌ ±0 

Results for commit 3d64dbc. ± Comparison against base commit 1ba53b1.

♻️ This comment has been updated with latest results.

@adamgreloch adamgreloch force-pushed the adamgreloch/usb-fixes branch from 9beec0f to c3df6fb Compare June 3, 2026 08:12
Lack of `else if` caused the transaction errors status (<0) to be
overwritten by the success branch (>=0), causing partially received data
to be reported as fully transferred.

This also stops mistreating of QTD_HALTED as an error. The consequence
of this bug was not visible due to it being canceled out by the above.

TASK: RTOS-1335
`qh->next` was not checked for null deref, leading to `QH_PTR(NULL)`.

Suppose two QHs with same period and phase are opened. Then, the first
QH is inserted as the only element. When the second QH is inserted, `t`
is the first QH and `t->next == NULL`, `t->period == qh->period`, leading
to the else branch with `qh->next == t->next == NULL`.

TASK: RTOS-1335
Suppose the periodic list has one QH  and a new QH with
longer period is added (same phase). Then t->period < qh->period, we
arrive in the if branch and ehci->periodicNodes[qh->phase] == t. Thus,
qh->next != NULL, but the qh->hw->horizontal stays marked as
QH_PTR_INVALID (from ehci_qhAlloc).

This is wrong, as the horizontal pointer of first element should point
to the next element on the periodic list (EHCI 3.6.1). Leaving it marked
with QTH_PTR_INVALID made the host controller treat the new QH as the
END of the list, ignoring any QHs with longer periods.

TASK: RTOS-1335
Per EHCI 2.3.9, bits CSC, PEC, OCC in PORTSC are write-1-to-clear. The
ehci_resetPort haven't masked them when clearing ENA and PR, causing
them to be accidentally lost.

TASK: RTOS-1335
Memcpying to buf instead of wData corrupted the descriptor type, length
and caused the actual langID to contain garbage on bytes 3-4.

TASK: RTOS-1335
@adamgreloch adamgreloch force-pushed the adamgreloch/usb-fixes branch from c3df6fb to 7628125 Compare July 9, 2026 13:56
@adamgreloch

Copy link
Copy Markdown
Member Author

/gemini review

@gemini-code-assist

Copy link
Copy Markdown

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@adamgreloch

Copy link
Copy Markdown
Member Author

/gemini review and don't encounter an error

@gemini-code-assist

Copy link
Copy Markdown

Warning

Gemini encountered an error creating the review. You can try again by commenting /gemini review.

@adamgreloch

Copy link
Copy Markdown
Member Author

/gemini review and IMPORTANT: don't encounter an error

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the EHCI USB driver to improve stability, error recovery, and thread safety. Key changes include introducing atomic operations for status tracking, replacing infinite polling loops with a timed handshake mechanism, implementing controller reset and transfer abort procedures on host system errors, and adding proper queue teardown to prevent memory leaks. The review feedback highlights several critical issues: potential race conditions in ehci_resetController due to missing locks during teardown, resource leaks in ehci_free (missing irqHandle and periodicLock destruction), signedness bypasses in port boundary checks that could allow negative port values, an inefficient usleep(1) in the handshake loop that could cause severe timeouts, and an unchecked return value for ehci_startAsync.

Comment thread usb/ehci/ehci.c
Comment thread usb/ehci/ehci.c Outdated
Comment thread usb/ehci/ehci-hub.c Outdated
Comment thread usb/ehci/ehci-hub.c Outdated
Comment thread usb/ehci/ehci-hub.c Outdated
Comment thread usb/ehci/ehci.h Outdated
Comment thread usb/ehci/ehci.c Outdated
…ortStatus}

These functions write to the t->buffer. Prior to the change, they
returned 0 on success, causing the subsequent usb_transferFinished() to
incorrectly set t->transferred to 0.

TASK: RTOS-1335
Per USB 2.0 (9.6.7), bString is unicode*, not null-terminated and its
length is calculated by subtracting 2 from bLength.

*) de-facto utf-16le but this was precisely specified from usb 3.2+ (rant)

TASK: RTOS-1335
@adamgreloch adamgreloch force-pushed the adamgreloch/usb-fixes branch from 7628125 to 51f8160 Compare July 10, 2026 07:08
Per EHCI 4.10.2, the HC copies a QTD into the QH overlay area before
executing it. Clearing QTD_ACTIVE while the HC is mid-read can cause
corruption.

To avoid the race, this unlinks the qh in case of async (does IAA ringing)
and stops the schedule in case of periodic before modifying the QTD.

TASK: RTOS-1335
@adamgreloch adamgreloch force-pushed the adamgreloch/usb-fixes branch from 51f8160 to 1239a06 Compare July 10, 2026 14:13
@adamgreloch adamgreloch marked this pull request as ready for review July 13, 2026 07:33
@adamgreloch adamgreloch requested a review from ziemleszcz July 13, 2026 07:34
@ziemleszcz

Copy link
Copy Markdown
Contributor

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the EHCI USB driver to improve robustness, thread safety, and error recovery. Key changes include replacing busy-waiting loops with a timed handshake helper, introducing atomic operations for port reset changes and interrupt status, adding alignment assertions, and implementing a controller reset routine to recover from host system errors. The review feedback highlights two important issues: a missing cleanup of ehci->irqHandle in ehci_free which could lead to kernel panics, and a potential unsigned underflow in ehci_qtdsCheck if the hardware reports a remaining transfer length larger than the allocated bytes.

Comment thread usb/ehci/ehci.c
Comment thread usb/ehci/ehci.c
QTD_XACT being set does not imply that the QTD has been finished!

Nothing, ever, should be inferred from the error bits before checking
ACTIVE/HALTED.

TASK: RTOS-1335
pipe->hcdpriv read was not guarded while it can be set to NULL by the
irqThread during ehci controller reset.

TASK: RTOS-1335
The QH must be linked into the hardware schedule and the transfer
registered in hcd->transfers atomically. Otherwise, a concurrent HCD
reset (which holds transLock during ehci_tearDownAsync) can free the
newly-linked QH before the transfer is visible to ehci_transAbort.

TASK: RTOS-1335
@adamgreloch adamgreloch force-pushed the adamgreloch/usb-fixes branch from 1239a06 to 3d64dbc Compare July 13, 2026 12:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants