Re: xHCI host dies on device unplug

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



+Cc Mathias as he last touched this code path and may know more :)

On Tue, Dec 06, 2022 at 02:17:08PM +0100, Ladislav Michl wrote:
> On Mon, Dec 05, 2022 at 10:27:57PM +0100, Ladislav Michl wrote:
> > I'm running current linux.git on custom Marvell OCTEON III CN7020
> > based board. USB devices like FTDI (idVendor=0403, idProduct=6001,
> > bcdDevice= 6.00) Realtek WiFi dongle (idVendor=0bda, idProduct=8179,
> > bcdDevice= 0.00) works without issues, while Ralink WiFi dongle 
> > (idVendor=148f, idProduct=5370, bcdDevice= 1.01) kills the host on
> > disconnect:
> > xhci-hcd xhci-hcd.0.auto: xHCI host not responding to stop endpoint command
> > xhci-hcd xhci-hcd.0.auto: xHCI host controller not responding, assume dead
> > xhci-hcd xhci-hcd.0.auto: HC died; cleaning up
> > 
> > Unfortunately I do not have a datasheet for CN7020 SoC, so it is hard
> > to tell if there is any errata :/ In case anyone see a clue in debug
> > logs bellow, I'll happily give it a try.
> 
> So I do have datasheet now. As a wild guess I tried to use dlmc_ref_clk0
> instead of dlmc_ref_clk1 as a refclk-type-ss and it fixed unplug death.
> I have no clue why, but anyway - sorry for the noise :) Perhaps Octeon's
> clock init is worth to be verified...

After all whenever xhci dies with "xHCI host not responding to stop endpoint
command" depends also on temperature, so there seems to be race somewhere.

As a quick and dirty verification, whenever xhci really died, following patch
was tested and it fixed issue. It just treats ep as if stop endpoint command
succeeded. Any clues? I'll happily provide more traces.

--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1582,21 +1582,37 @@ void xhci_handle_command_timeout(struct work_struct *work)
 
 	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_warn(xhci, "Command timeout, USBSTS:%s\n", xhci_decode_usbsts(str, usbsts));
 
 	/* 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;
+		struct xhci_td *td = NULL;
+		enum xhci_ep_reset_type reset_type;
+		int err;
 
 		xhci_warn(xhci, "xHCI host not responding to stop endpoint command\n");
 
 		ep = xhci_get_virt_ep(xhci, TRB_TO_SLOT_ID(cmd_field3),
 				      TRB_TO_EP_INDEX(cmd_field3));
-		if (ep)
+		if (ep) {
+			xhci_dbg(xhci, "huhuhu\n");
+			if (ep->ep_state & EP_HAS_STREAMS) {
+				reset_type = EP_SOFT_RESET;
+			} else {
+				reset_type = EP_HARD_RESET;
+				td = find_halted_td(ep);
+				if (td)
+					td->status = -EPROTO;
+			}
+			/* reset ep, reset handler cleans up cancelled tds */
+			err = xhci_handle_halted_endpoint(xhci, ep, 0, td,
+							  reset_type);
 			ep->ep_state &= ~EP_STOP_CMD_PENDING;
-
-		xhci_halt(xhci);
-		xhci_hc_died(xhci);
+		} else {
+			xhci_halt(xhci);
+			xhci_hc_died(xhci);
+		}
 		goto time_out_completed;
 	}
 




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux