[PATCH 3.12 08/58] usb: Add connected retry on resume for non SS devices

From: Jiri Slaby
Date: Wed Mar 16 2016 - 07:14:57 EST


From: Al Cooper <alcooperx@xxxxxxxxx>

3.12-stable review patch. If anyone has any objections, please let me know.

===============

commit 6b82b1223e3b14afd89d167795671a9f4f77b2f0 upstream.

Currently usb_port_resume waits for up to 2 seconds for CONNECT
status for SS devices only. This change will do the same thing for
non-SS devices even though the reason is a little different. This
will fix an issue where VBUS is turned off during system wide
"suspend to ram" and some 2.0 devices take greater than the current
max of 100ms to show connected after VBUS is enabled. This is most
commonly seen on hard drive based devices and USB3.0 devices plugged
into a 2.0 only port.

Signed-off-by: Al Cooper <alcooperx@xxxxxxxxx>
Acked-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Jiri Slaby <jslaby@xxxxxxx>
---
drivers/usb/core/hub.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 3afe47870e95..a7de5daae6d3 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3167,7 +3167,7 @@ static int finish_port_resume(struct usb_device *udev)
/*
* There are some SS USB devices which take longer time for link training.
* XHCI specs 4.19.4 says that when Link training is successful, port
- * sets CSC bit to 1. So if SW reads port status before successful link
+ * sets CCS bit to 1. So if SW reads port status before successful link
* training, then it will not find device to be present.
* USB Analyzer log with such buggy devices show that in some cases
* device switch on the RX termination after long delay of host enabling
@@ -3178,14 +3178,17 @@ static int finish_port_resume(struct usb_device *udev)
* routine implements a 2000 ms timeout for link training. If in a case
* link trains before timeout, loop will exit earlier.
*
+ * There are also some 2.0 hard drive based devices and 3.0 thumb
+ * drives that, when plugged into a 2.0 only port, take a long
+ * time to set CCS after VBUS enable.
+ *
* FIXME: If a device was connected before suspend, but was removed
* while system was asleep, then the loop in the following routine will
* only exit at timeout.
*
- * This routine should only be called when persist is enabled for a SS
- * device.
+ * This routine should only be called when persist is enabled.
*/
-static int wait_for_ss_port_enable(struct usb_device *udev,
+static int wait_for_connected(struct usb_device *udev,
struct usb_hub *hub, int *port1,
u16 *portchange, u16 *portstatus)
{
@@ -3198,6 +3201,7 @@ static int wait_for_ss_port_enable(struct usb_device *udev,
delay_ms += 20;
status = hub_port_status(hub, *port1, portstatus, portchange);
}
+ dev_dbg(&udev->dev, "Waited %dms for CONNECT\n", delay_ms);
return status;
}

@@ -3303,8 +3307,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)

clear_bit(port1, hub->busy_bits);

- if (udev->persist_enabled && hub_is_superspeed(hub->hdev))
- status = wait_for_ss_port_enable(udev, hub, &port1, &portchange,
+ if (udev->persist_enabled)
+ status = wait_for_connected(udev, hub, &port1, &portchange,
&portstatus);

status = check_port_resume_type(udev,
--
2.7.3