summaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/hub.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 026b652d4f38..572e8c26a129 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3999,6 +3999,9 @@ static int usb_set_lpm_timeout(struct usb_device *udev,
* control transfers to set the hub timeout or enable device-initiated U1/U2
* will be successful.
*
+ * If the control transfer to enable device-initiated U1/U2 entry fails, then
+ * hub-initiated U1/U2 will be disabled.
+ *
* If we cannot set the parent hub U1/U2 timeout, we attempt to let the xHCI
* driver know about it. If that call fails, it should be harmless, and just
* take up more slightly more bus bandwidth for unnecessary U1/U2 exit latency.
@@ -4053,23 +4056,24 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
* host know that this link state won't be enabled.
*/
hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state);
- } else {
- /* Only a configured device will accept the Set Feature
- * U1/U2_ENABLE
- */
- if (udev->actconfig)
- usb_set_device_initiated_lpm(udev, state, true);
+ return;
+ }
- /* As soon as usb_set_lpm_timeout(timeout) returns 0, the
- * hub-initiated LPM is enabled. Thus, LPM is enabled no
- * matter the result of usb_set_device_initiated_lpm().
- * The only difference is whether device is able to initiate
- * LPM.
- */
+ /* Only a configured device will accept the Set Feature
+ * U1/U2_ENABLE
+ */
+ if (udev->actconfig &&
+ usb_set_device_initiated_lpm(udev, state, true) == 0) {
if (state == USB3_LPM_U1)
udev->usb3_lpm_u1_enabled = 1;
else if (state == USB3_LPM_U2)
udev->usb3_lpm_u2_enabled = 1;
+ } else {
+ /* Don't request U1/U2 entry if the device
+ * cannot transition to U1/U2.
+ */
+ usb_set_lpm_timeout(udev, state, 0);
+ hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state);
}
}