| From 1ac7db63333db1eeff901bfd6bbcd502b4634fa4 Mon Sep 17 00:00:00 2001 |
| From: Mathias Nyman <mathias.nyman@linux.intel.com> |
| Date: Tue, 17 Oct 2017 16:07:33 +0300 |
| Subject: usb: hub: Allow reset retry for USB2 devices on connect bounce |
| |
| From: Mathias Nyman <mathias.nyman@linux.intel.com> |
| |
| commit 1ac7db63333db1eeff901bfd6bbcd502b4634fa4 upstream. |
| |
| If the connect status change is set during reset signaling, but |
| the status remains connected just retry port reset. |
| |
| This solves an issue with connecting a 90W HP Thunderbolt 3 dock |
| with a Lenovo Carbon x1 (5th generation) which causes a 30min loop |
| of a high speed device being re-discovererd before usb ports starts |
| working. |
| |
| [...] |
| [ 389.023845] usb 3-1: new high-speed USB device number 55 using xhci_hcd |
| [ 389.491841] usb 3-1: new high-speed USB device number 56 using xhci_hcd |
| [ 389.959928] usb 3-1: new high-speed USB device number 57 using xhci_hcd |
| [...] |
| |
| This is caused by a high speed device that doesn't successfully go to the |
| enabled state after the second port reset. Instead the connection bounces |
| (connected, with connect status change), bailing out completely from |
| enumeration just to restart from scratch. |
| |
| Link: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1716332 |
| |
| Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> |
| Acked-by: Alan Stern <stern@rowland.harvard.edu> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/core/hub.c | 11 +++++++---- |
| 1 file changed, 7 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/usb/core/hub.c |
| +++ b/drivers/usb/core/hub.c |
| @@ -2667,13 +2667,16 @@ static int hub_port_wait_reset(struct us |
| if (!(portstatus & USB_PORT_STAT_CONNECTION)) |
| return -ENOTCONN; |
| |
| - /* bomb out completely if the connection bounced. A USB 3.0 |
| - * connection may bounce if multiple warm resets were issued, |
| + /* Retry if connect change is set but status is still connected. |
| + * A USB 3.0 connection may bounce if multiple warm resets were issued, |
| * but the device may have successfully re-connected. Ignore it. |
| */ |
| if (!hub_is_superspeed(hub->hdev) && |
| - (portchange & USB_PORT_STAT_C_CONNECTION)) |
| - return -ENOTCONN; |
| + (portchange & USB_PORT_STAT_C_CONNECTION)) { |
| + usb_clear_port_feature(hub->hdev, port1, |
| + USB_PORT_FEAT_C_CONNECTION); |
| + return -EAGAIN; |
| + } |
| |
| if (!(portstatus & USB_PORT_STAT_ENABLE)) |
| return -EBUSY; |