summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2012-10-05 10:32:07 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-28 10:56:14 -0700
commit4e0532a22664501721fdd89a00d61948c1e34a23 (patch)
tree83b74a32ce7e7b312714a02c7fbe62411a714296
parent094c5b6410392321492c59603879f8ec7d87358a (diff)
downloadlinux-stable-4e0532a22664501721fdd89a00d61948c1e34a23.tar.gz
linux-stable-4e0532a22664501721fdd89a00d61948c1e34a23.tar.bz2
linux-stable-4e0532a22664501721fdd89a00d61948c1e34a23.zip
usb: Send Set SEL before enabling parent U1/U2 timeout.
commit 65a95b75bc5afa7bbb844e222481044c1c4767eb upstream. The Set SEL control transfer tells a device the exit latencies associated with a device-initated U1 or U2 exit. Since a parent hub may initiate a transition to U1 soon after a downstream port's U1 timeout is set, we need to make sure the device receives the Set SEL transfer before the parent hub timeout is set. This patch should be backported to kernels as old as 3.5, that contain the commit 1ea7e0e8e3d0f50901d335ea4178ab2aa8c88201 "USB: Add support to enable/disable USB3 link states." Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/core/hub.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d1a43ab01167..bbff14318c1f 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3258,16 +3258,6 @@ static int usb_set_device_initiated_lpm(struct usb_device *udev,
if (enable) {
/*
- * First, let the device know about the exit latencies
- * associated with the link state we're about to enable.
- */
- ret = usb_req_set_sel(udev, state);
- if (ret < 0) {
- dev_warn(&udev->dev, "Set SEL for device-initiated "
- "%s failed.\n", usb3_lpm_names[state]);
- return -EBUSY;
- }
- /*
* Now send the control transfer to enable device-initiated LPM
* for either U1 or U2.
*/
@@ -3352,7 +3342,7 @@ static int usb_set_lpm_timeout(struct usb_device *udev,
static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
enum usb3_link_state state)
{
- int timeout;
+ int timeout, ret;
__u8 u1_mel = udev->bos->ss_cap->bU1devExitLat;
__le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat;
@@ -3364,6 +3354,17 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
(state == USB3_LPM_U2 && u2_mel == 0))
return;
+ /*
+ * First, let the device know about the exit latencies
+ * associated with the link state we're about to enable.
+ */
+ ret = usb_req_set_sel(udev, state);
+ if (ret < 0) {
+ dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n",
+ usb3_lpm_names[state]);
+ return;
+ }
+
/* We allow the host controller to set the U1/U2 timeout internally
* first, so that it can change its schedule to account for the
* additional latency to send data to a device in a lower power