stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mathias Nyman <mathias.nyman@linux.intel.com>
To: Alan Stern <stern@rowland.harvard.edu>
Cc: gregkh@linuxfoundation.org, linux-usb@vger.kernel.org,
	Stable <stable@vger.kernel.org>
Subject: Re: [PATCH] usb: hub: Allow reset retry for USB2 devices on connect bounce
Date: Tue, 17 Oct 2017 11:40:34 +0300	[thread overview]
Message-ID: <59E5C202.4060305@linux.intel.com> (raw)
In-Reply-To: <Pine.LNX.4.44L0.1710161516010.1377-100000@iolanthe.rowland.org>

On 16.10.2017 22:34, Alan Stern wrote:
> On Mon, 16 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 <stable@vger.kernel.org>
>> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
>> ---
>>   drivers/usb/core/hub.c | 10 +++++++---
>>   1 file changed, 7 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
>> index 41eaf0b..3461347 100644
>> --- a/drivers/usb/core/hub.c
>> +++ b/drivers/usb/core/hub.c
>> @@ -2710,13 +2710,13 @@ 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;
>> +		return -EAGAIN;
>>
>>   	if (!(portstatus & USB_PORT_STAT_ENABLE))
>>   		return -EBUSY;
>> @@ -2789,6 +2789,10 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
>>   				dev_dbg(hub->intfdev,
>>   						"port_wait_reset: err = %d\n",
>>   						status);
>> +			/* USB2 connection bounced, but remains connected */
>> +			if (status == -EAGAIN)
>> +				usb_clear_port_feature(hub->hdev, port1,
>> +						USB_PORT_FEAT_C_CONNECTION);
>
> There's something very awkward about issuing this call here.  For one
> thing, we don't really know at this point that the C_CONNECTION port
> status bit is set; we only know that the reset needs to be retried.
> For another, about 14 lines lower down the routine already clears that
> status bit anyway (although not for the USB-2.0 case).

Agree, but no other change bits were cleared in hub_port_wait_reset().
So I cleared it where the others were.

>
> In fact, it's awkward that we issue a bunch of unconditional
> Clear-Port-Feature calls just below this point, without knowing whether
> the corresponding status bits are set.  Ideally, hub_port_wait_reset()
> would return its portstatus and portchange values.  Or it would clear
> the extra status bits by itself.  Maybe that can all be cleaned up in a
> later patch.

True
hub_port_wait_reset() is only called by hub_port_reset() so I don't see any
reason why we couldn't clean up the change bits in hub_port_wait_reset().

Especially the connect change bit which we now want to clear in both
usb2 and usb3 case if set. I'll change the patch.

>
> Also, does this fully solve the problem?  I can see that it would
> prevent the lengthy repeated rediscoveries, but wouldn't it also
> prevent the device from working at all after the first few resets
> failed?
>

It does, the device enumerates fine after one more reset.
I don't know if the device just fails every second reset, or if it only fails to re-reset
after it just reached enable state.

-Mathias

      reply	other threads:[~2017-10-17  8:36 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-10-16 13:31 [PATCH] usb: hub: Allow reset retry for USB2 devices on connect bounce Mathias Nyman
2017-10-16 19:34 ` Alan Stern
2017-10-17  8:40   ` Mathias Nyman [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=59E5C202.4060305@linux.intel.com \
    --to=mathias.nyman@linux.intel.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=stern@rowland.harvard.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).