Tool/software: Linux
Hi champs,
Some problems here are faced with AM4378 USB Host driver (usbdwc3 with chip revision: 5533240a) when disconnecting an USB Storage (pendrive) on a custom design
When using Linux Kernel version 4.1.18 with Xenoami support and extracting the USB Storage while is writing some times the following error is seen :
<4>[ 246.157546] xhci-hcd xhci-hcd.0.auto: xHCI host not responding to stop endpoint command.
<4>[ 246.166860] xhci-hcd xhci-hcd.0.auto: Assuming host is dying, halting host.
<4>[ 246.200068] xhci-hcd xhci-hcd.0.auto: Host not halted after 16000 microseconds.
<4>[ 246.208164] xhci-hcd xhci-hcd.0.auto: Non-responsive xHCI host is not halting.
<4>[ 246.216111] xhci-hcd xhci-hcd.0.auto: Completing active URBs anyway.
<3>[ 246.223177] xhci-hcd xhci-hcd.0.auto: HC died; cleaning up
and other times a kernel panic pops up :
2000/01/11,07:11:05 any kern.info kernel: [ 389.957554] usb 1-1: new high-speed USB device number 4 using xhci-hcd
[ 390.100234] Alignment trap: not handling instruction e1932f9f at [<c025ccb0>]
2000/01/11,07:11:05 any kern.info kernel: [ 390.099019] usb 1-1: New USB device found, idVendor=8564, idProduct=1000
2000/01/11,07:11:05 any kern.info kernel: [ 390.099040] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
2000/01/11,07:11:05 any kern.[ 390.129792] Unhandled fault: alignment exception (0x011) at 0x00312d51
[ 390.141195] pgd = c0004000
[ 390.144189] [00312d51] *pgd=00000000
When updating only the usb part (driver/usb/) to 4.1.37, the kernel panics seem solved, but the "USB xHCI Port Disable Feature Does not work" (issue 896 for another micro http://www.ti.com/lit/er/sprz429j/sprz429j.pdf) seems to happen still.
After forums review the following patch issued by that Felipe Balbi <balbi@ti.com> has been found :
https://patchwork.kernel.org/patch/9439257/
https://patchwork.kernel.org/patch/5655271/
A patch has been made manually (attached) and solve the problem, but we want to make sure that patch works ok in all contexts
QUESTIONS : Is there an easy way to reproduce the failure to make sure that patch is working ok?
This is an important question since if it occurs once then it needs a reboot to attach again the USB storage and this should be avoided
Thanks
Best regards,
Guillaume
Patch adapted manually from ti-kernel-4.4 to solve the problem described in the link https://lkml.org/lkml/2015/1/12/587. Our revision is less than DWC3_REVISION_300A --- linux-4.1.18-base/drivers/usb/dwc3/core.h 2017-01-16 15:45:18.362726000 +0100 +++ linux-4.1.18/drivers/usb/dwc3/core.h 2017-01-16 15:47:28.082726000 +0100 @@ -784,6 +784,8 @@ #define DWC3_REVISION_260A 0x5533260a #define DWC3_REVISION_270A 0x5533270a #define DWC3_REVISION_280A 0x5533280a +#define DWC3_REVISION_290A 0x5533290a +#define DWC3_REVISION_300A 0x5533300a /* * NOTICE: we're using bit 31 as a "is usb 3.1" flag. This is really --- linux-4.1.18-base/drivers/usb/dwc3/host.c 2017-01-16 15:45:18.362726000 +0100 +++ linux-4.1.18/drivers/usb/dwc3/host.c 2017-01-16 15:46:57.146726000 +0100 @@ -51,6 +51,19 @@ pdata.usb3_lpm_capable = dwc->usb3_lpm_capable; + /** + * WORKAROUND: dwc3 revisions <=3.00a have a limitation + * where Port Disable command doesn't work. + * + * The suggested workaround is that we avoid Port Disable + * completely. + * + * This following flag tells XHCI to do just that. + */ + dev_info(dwc->dev, "dwc3 revision: %x\n", dwc->revision); + if (dwc->revision <= DWC3_REVISION_300A) + pdata.quirk_port_broken_pe = true; + ret = platform_device_add_data(xhci, &pdata, sizeof(pdata)); if (ret) { dev_err(dwc->dev, "couldn't add platform data to xHCI device\n"); --- linux-4.1.18-base/drivers/usb/host/xhci.h 2017-01-16 15:45:18.370726000 +0100 +++ linux-4.1.18/drivers/usb/host/xhci.h 2017-01-16 15:49:05.794726000 +0100 @@ -1572,6 +1572,8 @@ #define XHCI_SPURIOUS_WAKEUP (1 << 18) /* For controllers with a broken beyond repair streams implementation */ #define XHCI_BROKEN_STREAMS (1 << 19) +/* For controller with a broken Port Disable implementation */ +#define XHCI_BROKEN_PORT_PE (1 << 21) #define XHCI_PME_STUCK_QUIRK (1 << 20) #define XHCI_SSIC_PORT_UNUSED (1 << 22) #define XHCI_NO_64BIT_SUPPORT (1 << 23) --- linux-4.1.18-base/drivers/usb/host/xhci-hub.c 2017-01-16 15:45:18.370726000 +0100 +++ linux-4.1.18/drivers/usb/host/xhci-hub.c 2017-01-16 15:50:05.369016000 +0100 @@ -348,6 +348,13 @@ return; } + if (xhci->quirks & XHCI_BROKEN_PORT_PE) { + xhci_dbg(xhci, "Broken Port Enabled/Disabled, ignoring " + "port disable request.\n"); + return; + } + + /* Write 1 to disable the port */ writel(port_status | PORT_PE, addr); port_status = readl(addr); --- linux-4.1.18-base/drivers/usb/host/xhci-plat.c 2017-01-16 15:45:18.370726000 +0100 +++ linux-4.1.18/drivers/usb/host/xhci-plat.c 2017-01-16 15:48:21.198726000 +0100 @@ -150,6 +150,9 @@ if ((node && of_property_read_bool(node, "usb3-lpm-capable")) || (pdata && pdata->usb3_lpm_capable)) xhci->quirks |= XHCI_LPM_SUPPORT; + + if (pdata && pdata->quirk_port_broken_pe) + xhci->quirks |= XHCI_BROKEN_PORT_PE; /* * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset) * is called by usb_add_hcd(). --- linux-4.1.18-base/include/linux/usb/xhci_pdriver.h 2017-01-16 15:45:20.302726000 +0100 +++ linux-4.1.18/include/linux/usb/xhci_pdriver.h 2017-01-16 15:52:58.905016000 +0100 @@ -18,10 +18,12 @@ * * @usb3_lpm_capable: determines if this xhci platform supports USB3 * LPM capability + * @quirk_port_broken_pe: If true, XHCI will not use Port Disable. * */ struct usb_xhci_pdata { unsigned usb3_lpm_capable:1; + unsigned quirk_port_broken_pe:1; }; #endif /* __USB_CORE_XHCI_PDRIVER_H */