Commit Graph

51 Commits

Author SHA1 Message Date
Red Bear OS 5f78ad843a usbhubd: info-level HUBFLOW traces at attach decision points (diagnostic)
Post-debounce state, pre-attach state, and attach() result logged at
info level to pinpoint where hub-child enumeration stalls in QEMU.
Diagnostic; level to be revisited.
2026-07-19 12:00:45 +09:00
Red Bear OS 5803f4c6f2 xhcid: info-level attach_device milestone traces (diagnostic)
Temporary info-level ATTACH milestones in attach_device (begin, slot,
addressed, desc8, desc-full, drivers spawned) to trace hub-child
enumeration in QEMU — the kbd behind a hub reaches port-enable but
produces no visible outcome at the default log level. Level to be
revisited after the hub-child attach path is diagnosed.
2026-07-19 11:39:44 +09:00
Red Bear OS b16e6ca399 usbhubd: judge debounce stability on connection state, not change bit
The debounce's inner clear of C_PORT_CONNECTION could hang or be
ignored by the hub, and our control transfers have no timeout — so a
literal port of Linux's clear-inside-the-loop design deadlocked hub
enumeration: the debounce never converged and the reset/attach path was
never reached (observed on QEMU as usbhubd logging the port's first
status with connection_changed=true and then going silent forever).

Judge the 100ms stable window on the connection STATE alone (the same
stability property hub_port_debounce_be_connected protects): a stuck or
hung change bit can no longer deadlock enumeration — it only
re-triggers a poll, and is cleared once, best-effort, after a
successful attach (matching Linux port_event's C_PORT_CONNECTION
clear). New regression test debounce_stuck_change_bit_still_converges
locks the deadlock scenario; 15/15 tests pass.
2026-07-19 10:59:35 +09:00
Red Bear OS 8cd2f71ddd usbhubd: bound EP1 wait via worker thread + recv_timeout poll fallback
Root cause of hub-child enumeration stalling: after a synchronous
action (power-on, reset) the port's state changes WITHOUT a new
interrupt ever being generated, and the loop's next step was a blocking
EP1 transfer_read with no timeout — the daemon never woke to observe
the state it had just caused, so devices behind a hub sat
enabled-but-never-attached forever.

Move the blocking transfer_read onto a worker thread that forwards each
interrupt bitmap as a u64 mask over an mpsc channel. The main loop
waits with recv_timeout(POLL_FALLBACK_MS): a real bitmap processes only
the changed ports (interrupt fast path), while timeout/disconnect/error
falls back to an all-ports poll (progress guarantee). Matches the Linux
model where hub_irq is the accelerator but port status reads are always
authoritative.
2026-07-19 10:11:38 +09:00
Red Bear OS 9317d4874b usbhubd: fix status-bitmap off-by-one + add initial full port scan
Two latent bugs exposed by test-usb-hub-qemu.sh against a real hub
topology (QEMU usb-hub with usb-kbd behind it):

1. Status-change bitmap was indexed off by one: the loop checked
   bit (port - 1), but USB 2.0 spec 11.12.4 defines bit 0 = hub status
   change and bit N = port N status change (Linux hub_irq uses bit i
   for port i). Every change was processed on the wrong port — a device
   on port N was never enumerated (its bit was read as port N+1).

2. The event loop's first action was a blocking EP1 interrupt read;
   when the hub delivers no immediate status-change interrupt the
   daemon hung before ever scanning a port. Linux hub_activate()
   performs a full port scan before arming the status-change endpoint;
   the first iteration now forces an all-ports mask with the same
   semantics. Also widened the fallback all-ports mask to bits 1..=ports
   (bit 0 = hub, skipped).
2026-07-19 09:46:05 +09:00
Red Bear OS d7f31916bc xhcid: open hub-child port dirs before enumeration (scheme bootstrap)
open_handle_port required a PortState for every port<N> directory open,
but hub child ports have no PortState until the hub daemon triggers
attach_device via port<N>/attach — an endpoint that itself is
state-free (open_handle_attach_device). This made XhciClientHandle::new
fail with ENOENT for unenumerated hub children, deadlocking the attach
flow: usbhubd could never start enumeration for a device behind a
non-root hub (panic at startup, caught by test-usb-hub-qemu.sh).

Open the directory with the static listing when no PortState exists
yet; state-dependent subpaths (descriptors, state, configure) still
gate on the PortState being present.
2026-07-19 09:15:33 +09:00
Red Bear OS 9bbdc2cafa Merge upstream/main (59cf8189) into submodule/base
Sync the base fork with 13 upstream commits (xhci event-processing
dedup + IRQ race fix, randd permission simplification, nvmed TimeSpec
fix, /dev/ptmx, fpath legacy-path cleanup, dynamically-linked init
fix, and more). Brings process_one_event into the tree, satisfying the
verify-fork-functions gate for base.

Conflicts resolved (3 of 8 overlapping files; 5 auto-merged):

- drivers/usb/xhcid/src/xhci/irq_reactor.rs: took upstream's
  process_one_event/EventProcessResult refactor (b2ed85ea) including
  the a01d3ce6 race fix (process events between NoEvent and
  unmasking), and re-applied the Red Bear SPURIOUS_REBOOT quirk on the
  NoEvent warning (downgrade to debug when quirked).

- randd/src/main.rs: took upstream's permission-handling
  simplification (e26db606); re-applied the RB fcntl improvement
  (F_GETFL/F_GETFD/F_SETFL/F_SETFD handling, Linux random_fops xref)
  and the is_cpu_feature_detected early-return cleanup. Dropped
  test_scheme_perms (deleted by upstream's simplification).

- Makefile: kept upstream's new /dev symlink block (dev/null, ptmx,
  random, urandom, zero, tty, stdin/stdout/stderr).

Verified: cargo check clean; 57/57 tests pass (xhcid 35, usbhubd 14,
xhci trb 8); verify-fork-functions.sh --no-fetch base reports all
upstream functions present.
2026-07-19 05:47:27 +09:00
Red Bear OS bd379e0771 usbhubd: full Linux 7.1 hub enumeration state machine (P3-A)
Port the Linux 7.1 hub.c port state machine into usbhubd, replacing the
minimal connect/reset handling:

New module port_ops.rs (pure logic, side effects injected, 14 unit
tests):
- debounce_until_connected: hub_port_debounce_be_connected() port
  (hub.c:4696-4737) — 25ms polls, connection stable for 100ms, 2s
  budget, connection-change bit cleared in-loop.
- wait_for_reset: hub_port_wait_reset() port (hub.c:2953-3047) — 10ms
  polls until RESET clears with CONNECTION set, escalate to 200ms after
  two short waits, 800ms budget; then 50ms TRSTRCY recovery (hub.c:3159)
  and C_PORT_RESET clear. Replaces the previous bare sleep(10ms).
- wait_for_u0: USB 3.0 polling→U0 wait after port power-on — 36ms steps,
  400ms ceiling (tPollingLFPSTimeout = 360ms; Linux hub.c:1226 debounce
  path).
- accumulate_hub_delay_ns: wHubDelay chain rule (hub.c:1507-1519:
  wHubDelay + parent->hub_delay + 40ns, cap 65535ns).

main.rs wiring:
- Port status normalized to PortStatusSnapshot (decouples the state
  machine from the V2/V3 wire formats; V3 link state extracted from
  bits 8:5).
- Debounce on connection-change before attach; C_PORT_ENABLE cleared
  once handled (Linux port_event semantics).
- Reset path uses wait_for_reset instead of sleep(10ms).
- USB 3 power-on path waits for U0 before proceeding.
- wHubDelay: ancestor-chain walk fetching USB 3 ancestor hub
  descriptors, accumulated per Linux; delivered to newly attached
  SuperSpeed children via SET_ISOCH_DELAY (USB 3.0 9.4.11; Linux
  message.c:1142 — hubs and non-SS skipped, children inherit the hub's
  accumulated delay verbatim per hub.c:5128-5129).
- attach/detach failure logs now identify the port.

hub.rs (xhcid usb module):
- HubDescriptorV3 extended with device_removable: u16 — the SS hub
  descriptor is 12 bytes (spec Table 10-15); the old struct under-read
  by 2 bytes. Stale TODO corrected: SS descriptors have no
  PortPwrCtrlMask (that is USB 2.0-only, still unparsed).

Verified: cargo check clean (0 usbhubd warnings), 14/14 usbhubd tests,
xhcid unaffected (43/43 tests).
2026-07-19 00:27:49 +09:00
Red Bear OS 260003331e xhcid: fix restart_endpoint deadlock, doorbell ordering, NoOp priming (P2-C)
Three bugs in the xHCI endpoint-restart path used by all error recovery
(stall hard reset, transaction-error soft retry, resource retry,
split/babble hard reset):

1. Latent deadlock: restart_endpoint held the port_states write guard
   across set_tr_deque_ptr(), which internally re-acquires a read guard
   on the same key (std RwLock read-while-write on one thread).
   Unobserved because error injection is not yet exercised at runtime
   (P8-C). Fixed by scoping phase-1 ring priming so the guard drops
   before the async command.

2. Doorbell ordering violated xHCI spec 4.6.8/4.6.10: after Reset
   Endpoint the TR Dequeue Pointer is undefined, so Set TR Dequeue
   Pointer must complete BEFORE the doorbell transitions the endpoint
   Stopped->Running. The old order (doorbell first) ran the endpoint
   with an undefined dequeue pointer — undefined xHC behavior on real
   hardware. Linux rings the doorbell from the Set TR Dequeue command
   completion path (xhci_handle_cmd_set_deq, ring.c:1416-1554); xhcid
   now issues Set TR Dequeue, awaits completion, then rings.

3. Priming NoOp never executed: ring.register() was captured after
   ring.next() advanced the enqueue index, so the dequeue pointed past
   the NoOp (dead TRB). Now captured before next(), priming the
   hardware dequeue AT the NoOp so the xHC executes it on restart —
   same semantics as Linux xhci_move_dequeue_past_td pointing at the
   first valid TRB.

Verified: cargo check clean (138 warnings, unchanged), 43/43 tests pass.
2026-07-18 23:14:14 +09:00
Red Bear OS d20557f726 xhcid: gate xHCI 1.1+ features on HCCPARAMS2 + protocol-caps bits (P2-B)
Gate xHCI 1.1+ features on their capability bits, cross-referenced with
Linux 7.1 xhci driver behavior:

LEC (HCC2_LEC, scheme.rs):
- lec now uses Linux xhci-mem.c:1350 exact condition:
  hci_version > 0x100 && hcc_params2 & HCC2_LEC (HCCPARAMS2 register
  space is reserved on 1.0 controllers).
- Max ESIT Payload Hi zeroed when LEC=0 (spec Table 6-8 RsvdZ).

U3C (HCC2_U3C, mod.rs suspend_port):
- Refuse SuperSpeed U3 entry with ENOSYS when hci_ver >= 0x110 and
  HCC2_U3C=0 (spec 4.15.1). USB2 suspend unaffected. Linux 7.1 defines
  but never gates this bit; xhcid follows the spec.

CIC (HCC2_CIC): CIE gate pre-existing (set_cie from cic()); added the
hci_ver > 0x100 version guard. HCC2 capability log block similarly
guarded.

HW LPM (extended.rs, mod.rs, port.rs):
- New SupportedProtoCap::{l1_capable,hw_lpm_capable,besl_lpm_capable}
  reading protocol-defined bits (Linux xhci-ext-caps.h:62-66 L1C/HLC/BLC).
- Xhci::hw_lpm_support computed per Linux xhci-mem.c:2137:
  hci_ver >= 0x100 && !HW_LPM_DISABLE && any USB2 protocol cap has HLC.
- attach_device(): defensive LPM clear on USB 2.0 protocol ports
  (rev_major() != 3) when hw_lpm_support is false — Linux xhci.c:4725
  disable path; USB3 excluded because PORTPMSC L1DS aliases U2 timeout.
- Port::enable_lpm/disable_lpm register targets fixed: HLE/HIRD/RWE/
  L1DS belong in PORTPMSC (offset 0x04), not PORTHLPMC (0x0C, bit 16
  RsvdZ) — spec Tables 5-21/5-23, Linux xhci-port.h:135-158. Helpers
  rewritten to Linux xhci.c:4686-4737 two-register sequence.
- Per-device L1 enablement (BESL, MEL Evaluate Context) defers to P3.

Bug fix: removed bogus CapabilityRegs::hlc() + HCC_PARAMS1_HLC_BIT —
they read xECP pointer bits 16-31 of HCCPARAMS1 (spec Table 5-13), not
HLC. HLC lives in the Supported Protocol capability port_info DWORD.

Verification: cargo check clean (138 warnings, -2 vs baseline: the new
disable_lpm call site also revived PORT_HLE/PORT_HIRD_MASK), 43/43
tests pass.
2026-07-18 22:33:38 +09:00
Red Bear OS 9fc1947d53 xhcid: converge xHCI quirks to canonical redox-driver-sys path
Replace xhcid's self-contained 294-line xhci/quirks.rs (7-flag bitflags
type + ~30-entry quirk table) with a thin re-export shim that delegates
to redox-driver-sys::quirks, which now carries all 51 Linux 7.1 quirk
flags and the full ~85-entry canonical controller table.

Changes:
- Cargo.toml: add redox-driver-sys path dependency
- xhci/quirks.rs: replace table with pub use XhciControllerQuirkFlags
  as XhciQuirks + delegating lookup_quirks(vendor, device, revision,
  hci_version)
- main.rs: read real HCIVERSION from MMIO offset 0x04 via
  cap.hci_ver.read() instead of hardcoded 0x100 — matches Linux 7.1
  xhci_gen_setup() at xhci.c:5455. Two table entries depend on the
  value: AMD_0x96_HOST (xhci-pci.c:308) and >= 0x120 spec rule
  (xhci-pci.c:511).
- main.rs: resolve quirks BEFORE get_int_method() so BROKEN_MSI skips
  MSI/MSI-X probing entirely (matching Linux xhci_try_enable_msi at
  xhci-pci.c:143-209). Previously the quirk only overrode the method
  label while irq_file still held the MSI handle — a mismatch causing
  silent interrupt-delivery failures on BROKEN_MSI controllers.
- get_int_method (both cfg variants): accept quirks parameter
2026-07-18 21:52:05 +09:00
Red Bear OS ad4bedd46d xhcid: expand xHCI completion-code error recovery to all 36 codes
maybe_recover_transfer_error previously handled only the first-tier
codes (UsbTransaction, Resource, Stall, BabbleDetected, DataBuffer,
Trb, SplitTransaction) and silently returned Ok(false) for every
other completion code via a catch-all arm.

Cross-referenced Linux 7.1 drivers/usb/host/xhci-ring.c
handle_tx_event() (line 2608+) and handle_transferless_tx_event()
(line 2561+) to add explicit recovery for the remaining ~29 codes:

- Stopped/StoppedLengthInvalid/StoppedShortPacket: restart endpoint
  + retry (up to MAX_SOFT_RETRY), then hard-reset
- InvalidStreamType/InvalidStreamId: soft reset + retry, then
  hard-reset
- IncompatibleDevice: disable slot (device must re-enumerate)
- MissedService/NoPingResponse: log informational, surface to caller
- ContextState/Parameter: hard-reset to resync driver/xHC state
- Bandwidth/BandwidthOverrun/SecondaryBandwidth: log, no transfer
  recovery (config must change)
- IsochBuffer: hard-reset endpoint
- MaxExitLatencyTooLarge: log, surface
- EventLost/Undefined: hard-reset (event ring may be corrupted)
- SlotNotEnabled/EndpointNotEnabled/NoSlotsAvailable: log driver
  state mismatch
- CommandRingStopped/CommandAborted: log xHC state confusion
- Reserved/vendor: default arm logs explicitly

Added completion_code_to_errno() mapping transfer completion codes
to POSIX errnos matching Linux 7.1 semantics:
  Stall -> EPIPE
  BabbleDetected -> EOVERFLOW
  UsbTransaction/SplitTransaction/IncompatibleDevice -> EPROTO
  Trb -> EILSEQ
  DataBuffer -> ENOSR
  SlotNotEnabled/EndpointNotEnabled/NoSlotsAvailable -> ENODEV
  default -> EIO

Rewrote handle_transfer_event_trb() to use the new errno mapping
instead of always returning EIO.

Added 14 unit tests covering all errno mappings and transfer
event handling paths. Full suite (41 tests) passes.
2026-07-18 20:55:41 +09:00
bjorn3 a01d3ce6e5 Fix a race condition when receiving events before unmasking interrupts 2026-07-13 20:23:20 +02:00
bjorn3 b2ed85ea0d Deduplicate event trb processing between polling and interrupt reactor 2026-07-13 20:19:49 +02:00
Red Bear OS bd595851e2 base: apply Red Bear patches on latest upstream/main
251 files: init, acpid, ipcd, netcfg, ihdgd, virtio-gpud, scheme-utils,
inputd, block driver, ptyd, ramfs, randd, initfs bootstrap, path deps,
version +rb0.3.1, author attribution
2026-07-11 11:39:24 +03:00
Jeremy Soller 74eb45cb26 xhcid: fix endpoint handling issues and use newtype for endpoint number 2026-06-25 14:21:09 -06:00
Jeremy Soller 76385adca3 xhcid: do not read interface names and add more debugging 2026-06-25 13:03:19 -06:00
Jeremy Soller ff7492949e Initial gamepad support 2026-06-23 17:29:25 -06:00
bjorn3 d528fb73b4 drivers: Use map_bar instead of physmap where possible
Physmap requires root, while map_bar in the future could be run as
unprivileged process given a pcid handle for the target device.
2026-05-09 20:12:41 +02:00
Antoine Reversat 3f6c0c706f Run cargo fmt 2026-05-07 15:22:33 -04:00
Antoine Reversat e22712d920 Replace hid_descs with unknown_descs 2026-05-07 12:20:07 -04:00
bjorn3 e217ff2c6a drivers/usb/xhcid: Load config files at runtime rather than compile time 2026-04-22 22:36:40 +02:00
bjorn3 daf726c30d scheme-utils: Have FpathWriter handle writing the scheme name 2026-04-19 19:07:41 +02:00
bjorn3 64d23e9e05 scheme-utils: Introduce FpathWriter helper 2026-04-19 19:07:41 +02:00
bjorn3 28900f7c49 scheme-utils: Introduce Blocking as counterpart to ReadinessBased for blocking schemes 2026-04-19 11:05:04 +02:00
bjorn3 6686c73d26 Implement on_close method of SchemeSync instead of using a separate method 2026-04-19 10:42:19 +02:00
auronandace 29b4782015 update thiserror and add to workspace 2026-03-23 07:58:57 +00:00
auronandace 557a3d1954 consolidate several dependencies into the workspace 2026-03-22 15:11:33 +00:00
auronandace 2f0f5160bb update clap for usbctl 2026-03-22 09:45:09 +00:00
auronandace c88ab21c3f update bitflags for xhcid 2026-03-20 12:07:36 +00:00
Ribbon 90ea974ce0 Add missing Cargo package description and update drivers README 2026-03-16 10:39:15 -06:00
bjorn3 9795abb0ea Fix a bunch of warnings 2026-03-11 22:05:44 +01:00
Ibuki Omatsu 2738f69224 feat: Implement std_fs_call handling to initfs, ramfs, acpi and xhci 2026-02-28 08:15:16 -07:00
auronandace 7849aa23b3 make serde and toml workspace dependencies 2026-02-27 08:39:29 +00:00
bjorn3 a7ee3a2364 Update to toml 1.0 2026-02-26 17:28:12 +01:00
auronandace 4e77bb0f96 add precedence lint to drivers 2026-02-20 15:00:43 +00:00
Jeremy Soller 19c71bba06 xhcid: remove unnecessary eprintln 2026-01-29 11:20:18 -07:00
Jeremy Soller 3d56a47aeb xhcid: reduce logging 2026-01-29 11:02:13 -07:00
bjorn3 fc1c391340 Move common::init call into pcid_interface::pci_daemon 2026-01-25 20:08:49 +01:00
Wildan M 7a350efae4 Fix fmt 2026-01-23 01:13:41 +07:00
Jeremy Soller d7303832b1 Fix usb error message typo 2026-01-22 14:54:38 -07:00
Ibuki Omatsu 334928f151 feat: Introduce userspace namespace manager and adapt all schemes. 2026-01-20 20:56:58 -07:00
Jeremy Soller f740b61774 Use workspace dependencies for many common crates 2026-01-20 10:12:08 -07:00
Wildan M d08c6cbe6f Split driver log level env 2026-01-10 06:35:06 +07:00
Jeremy Soller c49075a3be Disable usbscsid until it is more reliable 2025-12-18 10:48:06 -07:00
Ibuki Omatsu 3681e1b74a refactor: Replace unlink and rmdir with unlinkat in ramfs. Update redox-scheme and redox-rt for bootstrap. 2025-12-17 18:46:05 -07:00
bjorn3 d27e7296fc drivers/usb/xhcid: Update to redox-scheme 0.8 2025-12-13 13:08:31 +01:00
bjorn3 3abe41d258 drivers/pcid: Add pci_daemon function
This handles daemonization and getting the PciFunctionHandle.
2025-12-04 11:44:29 +01:00
bjorn3 f1057b6750 daemon: Abort on errors
All users did this anyway. And handling it inside the daemon crate
allows avoiding a panic of the parent process when the child process
panicked.
2025-12-03 21:55:47 +01:00
bjorn3 54d81e7423 Merge redox-daemon into this repo 2025-12-03 21:07:13 +01:00