[RFC PATCH] usb: xhci: report USB2 resume-exit timeout as an error
From: Pengpeng Hou
Date: Tue Jun 23 2026 - 10:07:47 EST
xhci_handle_usb2_port_link_resume() waits for the USB2 resume exit
completion after requesting U0. If that wait times out, it only logs a
warning and then continues through the normal resume-done path, ending
the port resume and marking the suspend change as completed.
Return -ETIMEDOUT on resume-exit timeout so the port status path reports
an error instead of a successful resume. The patch still ends the
usbcore port-resume accounting before returning. This is intended as an
RFC patch because xHCI resume state handling is policy-sensitive.
Signed-off-by: Pengpeng Hou <pengpeng@xxxxxxxxxxx>
---
drivers/usb/host/xhci-hub.c | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index b0264bd85..b7b7d8b31 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -998,21 +998,23 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
- if (time_left) {
- if (!port->slot_id) {
- xhci_dbg(xhci, "slot_id is zero\n");
- return -ENODEV;
- }
- xhci_ring_device(xhci, port->slot_id);
- } else {
+ if (!time_left) {
int port_status = xhci_portsc_readl(port);
xhci_warn(xhci, "Port resume timed out, port %d-%d: 0x%x\n",
hcd->self.busnum, wIndex + 1, port_status);
/*
* keep rexit_active set if U0 transition failed so we
* know to report PORT_STAT_SUSPEND status back to
* usbcore. It will be cleared later once the port is
* out of RESUME/U3 state
*/
+ usb_hcd_end_port_resume(&hcd->self, wIndex);
+ return -ETIMEDOUT;
}
+ if (!port->slot_id) {
+ xhci_dbg(xhci, "slot_id is zero\n");
+ return -ENODEV;
+ }
+ xhci_ring_device(xhci, port->slot_id);
+
usb_hcd_end_port_resume(&hcd->self, wIndex);
bus_state->port_c_suspend |= 1 << wIndex;
bus_state->suspended_ports &= ~(1 << wIndex);
--
2.50.1 (Apple Git-155)