From 7286457ae2c99de89d770f24b070fbc1ca33e9e5 Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Tue, 7 Jul 2026 17:44:31 +0300 Subject: [PATCH] =?UTF-8?q?USB:=20runtime=20quirk=20enforcement=20?= =?UTF-8?q?=E2=80=94=20BROKEN=5FMSI,=20RESET=5FON=5FRESUME,=20RESET=5FTO?= =?UTF-8?q?=5FDEFAULT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cross-referenced with Linux 7.1 drivers/usb/host/xhci-pci.c. main.rs — BROKEN_MSI: - After quirk lookup, if BROKEN_MSI is set, downgrade interrupt method from MSI/MSI-X to legacy INTx (or Polling if no IRQ line available). Prevents interrupt storms and spurious reboots on buggy controllers (NEC/Renesas uPD720200, Etron EJ168, VIA VL805). mod.rs — RESET_ON_RESUME + RESET_TO_DEFAULT: - resume_port(): after wake from U3, if either quirk is set, perform an extra port reset to re-establish link training. RESET_TO_DEFAULT (Intel Tiger Lake PCH, Alder Lake PCH) implies RESET_ON_RESUME per Linux xhci-pci.c init path. - Prevents USB 3.0 link instability after suspend/resume cycles on Etron EJ168, Fresco Logic FL1009, Intel Tiger/Alder Lake PCH. These are the 3 most critical quirk flags — without them, real hardware with ASMedia, Renesas, Etron, Fresco Logic, VIA, and Intel Tiger/Alder Lake controllers will experience crashes (MSI storms) or dead ports after resume. Previous quirk enforced: NO_SOFT_RETRY (scheme.rs:600). Previous quirk effectively enforced: AVOID_BEI (always false). Total quirk flags now RUNTIME-ENFORCED: 5/50 (+4 from 1). --- drivers/usb/xhcid/src/main.rs | 18 +++++++++++++++++- drivers/usb/xhcid/src/xhci/mod.rs | 13 +++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/drivers/usb/xhcid/src/main.rs b/drivers/usb/xhcid/src/main.rs index 6898057fa5..1e2693ddbd 100644 --- a/drivers/usb/xhcid/src/main.rs +++ b/drivers/usb/xhcid/src/main.rs @@ -142,7 +142,7 @@ fn daemon_with_context_size( let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize; - let (irq_file, interrupt_method) = get_int_method(&mut pcid_handle); + let (irq_file, mut interrupt_method) = get_int_method(&mut pcid_handle); log::info!("XHCI {}", pci_config.func.display()); @@ -158,6 +158,22 @@ fn daemon_with_context_size( vendor, device, hci_version, quirks.bits() ); + // Linux 7.1 xhci-pci.c: if BROKEN_MSI quirk is set, fall back from + // MSI/MSI-X to legacy INTx or Polling to avoid interrupt storms + // and spurious reboots on buggy controller implementations. + let interrupt_method = if quirks.contains(xhci::quirks::XhciQuirks::BROKEN_MSI) { + log::warn!("xhcid: BROKEN_MSI quirk active — falling back from MSI to legacy INTx/polling"); + if let Some(irq) = pci_config.func.legacy_interrupt_line { + log::info!("xhcid: using legacy IRQ {}", irq); + InterruptMethod::Intx + } else { + log::warn!("xhcid: no legacy IRQ available — using polling mode"); + InterruptMethod::Polling + } + } else { + interrupt_method + }; + let scheme_name = scheme_path(&name); let socket = Socket::create().expect("xhcid: failed to create usb scheme"); let handler = Blocking::new(&socket, 16); diff --git a/drivers/usb/xhcid/src/xhci/mod.rs b/drivers/usb/xhcid/src/xhci/mod.rs index 6a9ac6e543..61df7452c0 100644 --- a/drivers/usb/xhcid/src/xhci/mod.rs +++ b/drivers/usb/xhcid/src/xhci/mod.rs @@ -771,6 +771,19 @@ impl Xhci { .ok_or_else(|| Error::new(EINVAL))?; log::info!("xhcid: resume port {} to U0", port_id); port.resume(); + drop(ports); + + // Linux 7.1 xhci-pci.c: RESET_ON_RESUME and RESET_TO_DEFAULT + // (which implies RESET_ON_RESUME for Tiger/Alder Lake). + // Some controllers (Etron EJ168, Fresco Logic FL1009, Intel + // Tiger Lake PCH, Alder Lake PCH) need an extra port reset + // after wake from U3 to re-establish link training. + if self.quirks.contains(crate::xhci::quirks::XhciQuirks::RESET_ON_RESUME) + || self.quirks.contains(crate::xhci::quirks::XhciQuirks::RESET_TO_DEFAULT) + { + log::info!("xhcid: RESET quirk active — extra port reset after resume on port {}", port_id); + self.reset_port(port_id)?; + } Ok(()) }