On Tue, 17 Oct 2017, Mathias Nyman wrote:

> 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
> 
> Cc: Stable <sta...@vger.kernel.org>
> Signed-off-by: Mathias Nyman <mathias.ny...@linux.intel.com>
> ---
> v2 changes:
>   clear connect change bit in hub_port_wait_reset() where it was detected
> 
>  drivers/usb/core/hub.c | 11 +++++++----
>  1 file changed, 7 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 41eaf0b..763b455 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -2710,13 +2710,16 @@ static int hub_port_wait_reset(struct usb_hub *hub, 
> int port1,
>       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;
> 

Acked-by: Alan Stern <st...@rowland.harvard.edu>

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to