|
Jiri Slaby |
e01e9d |
From: Alan Stern <stern@rowland.harvard.edu>
|
|
Jiri Slaby |
e01e9d |
Date: Tue, 1 Aug 2017 10:41:56 -0400
|
|
Jiri Slaby |
e01e9d |
Subject: [PATCH] USB: Check for dropped connection before switching to full
|
|
Jiri Slaby |
e01e9d |
speed
|
|
Jiri Slaby |
e01e9d |
References: bnc#1060662
|
|
Thomas Zimmermann |
1d81d2 |
Patch-mainline: v4.12.8
|
|
Jiri Slaby |
e01e9d |
Git-commit: 94c43b9897abf4ea366ed4dba027494e080c7050
|
|
Jiri Slaby |
e01e9d |
|
|
Jiri Slaby |
e01e9d |
commit 94c43b9897abf4ea366ed4dba027494e080c7050 upstream.
|
|
Jiri Slaby |
e01e9d |
|
|
Jiri Slaby |
e01e9d |
Some buggy USB disk adapters disconnect and reconnect multiple times
|
|
Jiri Slaby |
e01e9d |
during the enumeration procedure. This may lead to a device
|
|
Jiri Slaby |
e01e9d |
connecting at full speed instead of high speed, because when the USB
|
|
Jiri Slaby |
e01e9d |
stack sees that a device isn't able to enumerate at high speed, it
|
|
Jiri Slaby |
e01e9d |
tries to hand the connection over to a full-speed companion
|
|
Jiri Slaby |
e01e9d |
controller.
|
|
Jiri Slaby |
e01e9d |
|
|
Jiri Slaby |
e01e9d |
The logic for doing this is careful to check that the device is still
|
|
Jiri Slaby |
e01e9d |
connected. But this check is inadequate if the device disconnects and
|
|
Jiri Slaby |
e01e9d |
reconnects before the check is done. The symptom is that a device
|
|
Jiri Slaby |
e01e9d |
works, but much more slowly than it is capable of operating.
|
|
Jiri Slaby |
e01e9d |
|
|
Jiri Slaby |
e01e9d |
The situation was made worse recently by commit 22547c4cc4fe ("usb:
|
|
Jiri Slaby |
e01e9d |
hub: Wait for connection to be reestablished after port reset"), which
|
|
Jiri Slaby |
e01e9d |
increases the delay following a reset before a disconnect is
|
|
Jiri Slaby |
e01e9d |
recognized, thus giving the device more time to reconnect.
|
|
Jiri Slaby |
e01e9d |
|
|
Jiri Slaby |
e01e9d |
This patch makes the check more robust. If the device was
|
|
Jiri Slaby |
e01e9d |
disconnected at any time during enumeration, we will now skip the
|
|
Jiri Slaby |
e01e9d |
full-speed handover.
|
|
Jiri Slaby |
e01e9d |
|
|
Jiri Slaby |
e01e9d |
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
|
|
Jiri Slaby |
e01e9d |
Reported-and-tested-by: Zdenek Kabelac <zkabelac@redhat.com>
|
|
Jiri Slaby |
e01e9d |
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
|
|
Jiri Slaby |
e01e9d |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
Jiri Slaby |
e01e9d |
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
|
|
Jiri Slaby |
e01e9d |
---
|
|
Jiri Slaby |
e01e9d |
drivers/usb/core/hub.c | 10 ++++++----
|
|
Jiri Slaby |
e01e9d |
1 file changed, 6 insertions(+), 4 deletions(-)
|
|
Jiri Slaby |
e01e9d |
|
|
Jiri Slaby |
e01e9d |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
|
|
Jiri Slaby |
e01e9d |
index b8bb20d7acdb..0881a3e8131c 100644
|
|
Jiri Slaby |
e01e9d |
--- a/drivers/usb/core/hub.c
|
|
Jiri Slaby |
e01e9d |
+++ b/drivers/usb/core/hub.c
|
|
Jiri Slaby |
e01e9d |
@@ -4730,7 +4730,8 @@ hub_power_remaining(struct usb_hub *hub)
|
|
Jiri Slaby |
e01e9d |
static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
|
|
Jiri Slaby |
e01e9d |
u16 portchange)
|
|
Jiri Slaby |
e01e9d |
{
|
|
Jiri Slaby |
e01e9d |
- int status, i;
|
|
Jiri Slaby |
e01e9d |
+ int status = -ENODEV;
|
|
Jiri Slaby |
e01e9d |
+ int i;
|
|
Jiri Slaby |
e01e9d |
unsigned unit_load;
|
|
Jiri Slaby |
e01e9d |
struct usb_device *hdev = hub->hdev;
|
|
Jiri Slaby |
e01e9d |
struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
|
|
Jiri Slaby |
e01e9d |
@@ -4934,9 +4935,10 @@ loop:
|
|
Jiri Slaby |
e01e9d |
|
|
Jiri Slaby |
e01e9d |
done:
|
|
Jiri Slaby |
e01e9d |
hub_port_disable(hub, port1, 1);
|
|
Jiri Slaby |
e01e9d |
- if (hcd->driver->relinquish_port && !hub->hdev->parent)
|
|
Jiri Slaby |
e01e9d |
- hcd->driver->relinquish_port(hcd, port1);
|
|
Jiri Slaby |
e01e9d |
-
|
|
Jiri Slaby |
e01e9d |
+ if (hcd->driver->relinquish_port && !hub->hdev->parent) {
|
|
Jiri Slaby |
e01e9d |
+ if (status != -ENOTCONN && status != -ENODEV)
|
|
Jiri Slaby |
e01e9d |
+ hcd->driver->relinquish_port(hcd, port1);
|
|
Jiri Slaby |
e01e9d |
+ }
|
|
Jiri Slaby |
e01e9d |
}
|
|
Jiri Slaby |
e01e9d |
|
|
Jiri Slaby |
e01e9d |
/* Handle physical or logical connection change events.
|
|
Jiri Slaby |
e01e9d |
--
|
|
Jiri Slaby |
e01e9d |
2.14.2
|
|
Jiri Slaby |
e01e9d |
|