From d7f31916bc70f3ff89a264177c245146db8ea719 Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Sun, 19 Jul 2026 09:15:33 +0900 Subject: [PATCH] xhcid: open hub-child port dirs before enumeration (scheme bootstrap) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit open_handle_port required a PortState for every port directory open, but hub child ports have no PortState until the hub daemon triggers attach_device via port/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. --- drivers/usb/xhcid/src/xhci/scheme.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/usb/xhcid/src/xhci/scheme.rs b/drivers/usb/xhcid/src/xhci/scheme.rs index e676355289..6cab973dcd 100644 --- a/drivers/usb/xhcid/src/xhci/scheme.rs +++ b/drivers/usb/xhcid/src/xhci/scheme.rs @@ -2481,14 +2481,16 @@ impl Xhci { write!(contents, "descriptors\nendpoints\n").unwrap(); - if self.slot_state( - self.port_states - .get(&port_num) - .ok_or(Error::new(ENOENT))? - .slot as usize, - ) != SlotState::Configured as u8 - { - write!(contents, "configure\n").unwrap(); + // A hub child port has no PortState until the hub daemon + // triggers attach_device() for it via port/attach — an + // endpoint that itself needs no state (open_handle_attach_device). + // Open the directory anyway so that attach flow can start the + // enumeration; state-dependent subpaths (descriptors, state, + // configure) still gate on the PortState existing. + if let Some(port_state) = self.port_states.get(&port_num) { + if self.slot_state(port_state.slot as usize) != SlotState::Configured as u8 { + write!(contents, "configure\n").unwrap(); + } } Ok(Handle::Port(port_num, contents))