fix(xhci): bounded EnableSlot/AddressDevice retry — transient timeout no longer kills the mouse for the whole session#412
Open
ryanbreen wants to merge 2 commits into
Open
fix(xhci): bounded EnableSlot/AddressDevice retry — transient timeout no longer kills the mouse for the whole session#412ryanbreen wants to merge 2 commits into
ryanbreen wants to merge 2 commits into
Conversation
… timeout no longer kills a port (mouse dead all session) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…in smoke runs Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
xHCI port enumeration issued EnableSlot/AddressDevice single-shot, with no retry. A single transient timeout on port 1 (the mouse's port) meant the mouse silently enumerated onto slot 0 (or failed to enumerate at all) — the pointer would be frozen at 0,0 for the rest of the session, with no recovery path short of a reboot.
This was found live by the operator immediately after PR #411 landed, but
xhci.rswas untouched by that PR — this is pre-existing latent fragility that PR #411 merely made visible (or was coincidental timing), not a regression it introduced.The fix
Bounded 3-attempt retry around EnableSlot/AddressDevice, restricted to the cold enumeration path only (no changes to steady-state HID polling or any interrupt/syscall-hot-path code). A transient controller timeout on one attempt no longer permanently dooms that port's device for the session.
Harness assertion
scripts/parallels/launcher-smoke.shnow asserts onmouse=slotNwhere N != 0 — smoke runs FAIL if the mouse ends up bound to slot 0 (the failure signature this bug produces), so this class of regression can't silently reappear.Validation — 3/3 smoke boots PASS with mouse enumerated
[ { "boot": 1, "result": "PASS", "mouseEnumerated": true, "mouseEvidence": "[xhci] start_hid_polling: kbd=slot2/dci3 nkro=dci5 mouse=slot1/dci3 mouse2=dci5\n(no \"EnableSlot retry\" lines this run — all ports enumerated cleanly on first attempt: \"[xhci] port 1 EnableSlot -> slot 1\", \"[xhci] port 2 EnableSlot -> slot 2\", \"[xhci] port 3 EnableSlot -> slot 3\")", "evidencePath": "/Users/wrb/fun/code/breenix/logs/parallels-launcher-test/run-20260704-165209/" }, { "boot": 2, "result": "PASS", "mouseEnumerated": true, "mouseEvidence": "[smoke 16:55:57] USB mouse enumerated: slot 1 ([xhci] start_hid_polling: kbd=slot2/dci3 nkro=dci5 mouse=slot1/dci3 mouse2=dci5)", "evidencePath": "/private/tmp/claude-501/-Users-wrb-fun-code-breenix/94deec68-57ce-4666-8cb5-544f45bb0f62/scratchpad/launcher-smoke-boot2.log" }, { "boot": 3, "result": "PASS", "mouseEnumerated": true, "mouseEvidence": "[smoke 16:59:02] USB mouse enumerated: slot 1 ([xhci] start_hid_polling: kbd=slot2/dci3 nkro=dci5 mouse=slot1/dci3 mouse2=dci5)", "evidencePath": "/private/tmp/claude-501/-Users-wrb-fun-code-breenix/94deec68-57ce-4666-8cb5-544f45bb0f62/scratchpad/smoke-run3.log" } ]Note boot 1 had no retry lines at all (clean first-attempt enumeration on every port) — the harness assertion (mouse != slot0) holds regardless of whether the retry path was actually exercised in a given boot, which is the correct behavior for a bounded-retry safety net.
🤖 Generated with Claude Code