aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2012-10-05 13:32:07 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-10-08 14:48:28 -0400
commit65a95b75bc5afa7bbb844e222481044c1c4767eb (patch)
tree8c1e4fa2389264c23050e4e4718e8cb7a6231e78 /drivers/usb
parentae8963adb4ad8c5f2a89ca1d99fb7bb721e7599f (diff)
usb: Send Set SEL before enabling parent U1/U2 timeout.
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> Cc: stable@vger.kernel.org
Diffstat (limited to 'drivers/usb')
-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 8f0478709323..b8e11fff17be 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3320,16 +3320,6 @@ static int usb_set_device_initiated_lpm(struct usb_device *udev,
3320 3320
3321 if (enable) { 3321 if (enable) {
3322 /* 3322 /*
3323 * First, let the device know about the exit latencies
3324 * associated with the link state we're about to enable.
3325 */
3326 ret = usb_req_set_sel(udev, state);
3327 if (ret < 0) {
3328 dev_warn(&udev->dev, "Set SEL for device-initiated "
3329 "%s failed.\n", usb3_lpm_names[state]);
3330 return -EBUSY;
3331 }
3332 /*
3333 * Now send the control transfer to enable device-initiated LPM 3323 * Now send the control transfer to enable device-initiated LPM
3334 * for either U1 or U2. 3324 * for either U1 or U2.
3335 */ 3325 */
@@ -3414,7 +3404,7 @@ static int usb_set_lpm_timeout(struct usb_device *udev,
3414static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, 3404static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
3415 enum usb3_link_state state) 3405 enum usb3_link_state state)
3416{ 3406{
3417 int timeout; 3407 int timeout, ret;
3418 __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat; 3408 __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat;
3419 __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat; 3409 __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat;
3420 3410
@@ -3426,6 +3416,17 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
3426 (state == USB3_LPM_U2 && u2_mel == 0)) 3416 (state == USB3_LPM_U2 && u2_mel == 0))
3427 return; 3417 return;
3428 3418
3419 /*
3420 * First, let the device know about the exit latencies
3421 * associated with the link state we're about to enable.
3422 */
3423 ret = usb_req_set_sel(udev, state);
3424 if (ret < 0) {
3425 dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n",
3426 usb3_lpm_names[state]);
3427 return;
3428 }
3429
3429 /* We allow the host controller to set the U1/U2 timeout internally 3430 /* We allow the host controller to set the U1/U2 timeout internally
3430 * first, so that it can change its schedule to account for the 3431 * first, so that it can change its schedule to account for the
3431 * additional latency to send data to a device in a lower power 3432 * additional latency to send data to a device in a lower power