On Wed, Dec 21, 2022 at 11:11:19AM +0100, Ladislav Michl wrote: > On Wed, Dec 21, 2022 at 11:58:42AM +0200, Mathias Nyman wrote: > > Looked at that same series and turned patch 1/5 into a standalone quick hack that applies on 6.1 > > > > Untested, does it work for you? > > Applied on the top of you stop_endpoint_fixes, 6.1.0. is a base tree: > [ 24.800835] xhci-hcd xhci-hcd.0.auto: Delay clearing port-1 CSC > [ 24.806788] usb 1-1: USB disconnect, device number 2 > [ 28.148451] ieee80211 phy0: rt2x00usb_vendor_request: Error - Vendor Request 0x07 failed for offset 0x101c with error -19 > [ 29.828466] xhci-hcd xhci-hcd.0.auto: xHCI host not responding to stop endpoint command > [ 29.856656] xhci-hcd xhci-hcd.0.auto: xHCI host controller not responding, assume dead > [ 29.864804] xhci-hcd xhci-hcd.0.auto: HC died; cleaning up > [ 29.949460] xhci-hcd xhci-hcd.0.auto: Late clearing port-1 CSC, portsc 0x202a0 > > What about checking whenever anything is still connected on command timeout > and considering device autosuspended instead of killing it? Just completed test run, it is working, but I'd consider it insane at least... diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b07d3740f554..d7b7faaac647 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1580,6 +1580,21 @@ static bool xhci_pending_command_completion(struct xhci_hcd *xhci) return false; } +static bool xhci_is_anything_connected(struct xhci_hcd *xhci) +{ + struct usb_hcd *hcd = xhci_to_hcd(xhci); + struct xhci_hub *rhub = xhci_get_rhub(hcd); + struct xhci_port **ports = rhub->ports; + int i, max_ports = rhub->num_ports; + + max_ports = rhub->num_ports; + for (i = 0; i < max_ports; i++) + if (PORT_CONNECT & readl(ports[i]->addr)) + return true; + + return false; +} + void xhci_handle_command_timeout(struct work_struct *work) { struct xhci_hcd *xhci; @@ -1587,7 +1602,6 @@ void xhci_handle_command_timeout(struct work_struct *work) char str[XHCI_MSG_MAX]; u64 hw_ring_state; u32 cmd_field3; - u32 usbsts; xhci = container_of(to_delayed_work(work), struct xhci_hcd, cmd_timer); @@ -1602,9 +1616,9 @@ void xhci_handle_command_timeout(struct work_struct *work) return; } - cmd_field3 = le32_to_cpu(xhci->current_cmd->command_trb->generic.field[3]); - usbsts = readl(&xhci->op_regs->status); - xhci_dbg(xhci, "Command timeout, USBSTS:%s\n", xhci_decode_usbsts(str, usbsts)); + xhci_dbg(xhci, "Command timeout, USBSTS:%s, USBCMD: %08x\n", + xhci_decode_usbsts(str, readl(&xhci->op_regs->status)), + readl(&xhci->op_regs->command)); /* Did hw complete the command but event handler was blocked? */ if (xhci_pending_interrupt(xhci) > 0 && @@ -1616,10 +1630,16 @@ void xhci_handle_command_timeout(struct work_struct *work) return; } + cmd_field3 = le32_to_cpu(xhci->current_cmd->command_trb->generic.field[3]); /* Bail out and tear down xhci if a stop endpoint command failed */ if (TRB_FIELD_TO_TYPE(cmd_field3) == TRB_STOP_RING) { struct xhci_virt_ep *ep; + if (!(xhci_is_anything_connected(xhci))) { + xhci_info(xhci, "xHCI autosuspended?\n"); + goto time_out_completed; + } + xhci_warn(xhci, "xHCI host not responding to stop endpoint command\n"); ep = xhci_get_virt_ep(xhci, TRB_TO_SLOT_ID(cmd_field3),