On Tue, Jul 31, 2012 at 05:48:38PM -0500, Alexis R. Cortes wrote: > This patch is intended to work around a known issue on the > SN65LVPE502CP USB3.0 re-driver that can delay the negotiation > between a device and the host past the usual handshake timeout, > and if that happens on the first insertion, the host controller > port will enter in Compliance Mode as per xHCI Spec. The patch > creates a timer which polls every 2 seconds the link state of each > host controller's port (this by reading the PORTSC register) and > recovers the port by issuing a Warm reset every time Compliance mode > is detected. > > Signed-off-by: Alexis R. Cortes <alexis.cortes@xxxxxx> > --- > drivers/usb/host/xhci-hub.c | 27 ++++++++++++++ > drivers/usb/host/xhci.c | 81 +++++++++++++++++++++++++++++++++++++++++++ > drivers/usb/host/xhci.h | 6 +++ > 3 files changed, 114 insertions(+), 0 deletions(-) > > diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c > index 7b01094..4ea498d 100644 > --- a/drivers/usb/host/xhci-hub.c > +++ b/drivers/usb/host/xhci-hub.c > @@ -493,7 +493,19 @@ static void xhci_hub_report_link_state(u32 *status, u32 status_reg) > * when this bit is set. > */ > pls |= USB_PORT_STAT_CONNECTION; > + } else { > + /* > + * If CAS bit isn't set but the Port is already at > + * Compliance Mode, fake a connection so the USB core > + * notices the Compliance state and resets the port. > + * This resolves an issue generated by the SN65LVPE502CP > + * in which sometimes the port enters compliance mode > + * caused by a delay on the host-device negotiation. > + */ > + if (pls == USB_SS_PORT_LS_COMP_MOD) > + pls |= USB_PORT_STAT_CONNECTION; > } > + > /* update status field */ > *status |= pls; > } > @@ -645,6 +657,21 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, > /* Update Port Link State for super speed ports*/ > if (hcd->speed == HCD_USB3) { > xhci_hub_report_link_state(&status, temp); > + /* > + * Verify if all USB3 Ports Have entered U0. Delete compliance > + * mode timer if so. > + */ > + if (xhci->quirks & XHCI_COMP_MODE_QUIRK) { > + if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1)) { > + if ((temp & PORT_PLS_MASK) == XDEV_U0) > + xhci->port_status_u0 |= 1 << wIndex; > + } else { > + /* Deleting Compliance Mode Recovery Timer */ > + if (del_timer_sync(&xhci->comp_mode_recovery_timer)) > + xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted. " > + "All USB3 ports have entered U0 at least once.\n"); You need to disable the quirk flag here now, right? Otherwise can't the timer be deleted twice if the module is unloaded after this happens? thanks, greg k-h -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html