Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 317043
b: refs/heads/master
c: f74631e
h: refs/heads/master
i:
  317041: c8ffa55
  317039: 4432668
v: v3
  • Loading branch information
Sarah Sharp committed Jul 11, 2012
1 parent 04a6611 commit 637d527
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: af3a23ef4e5fbaf33f0afdda7d26442f036ba795
refs/heads/master: f74631e3426474183389e55f703797bd965cd356
87 changes: 81 additions & 6 deletions trunk/drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -2610,6 +2610,57 @@ static int check_port_resume_type(struct usb_device *udev,
return status;
}

static bool usb_device_supports_ltm(struct usb_device *udev)
{
if (udev->speed != USB_SPEED_SUPER || !udev->bos || !udev->bos->ss_cap)
return false;
return udev->bos->ss_cap->bmAttributes & USB_LTM_SUPPORT;
}

int usb_disable_ltm(struct usb_device *udev)
{
struct usb_hcd *hcd = bus_to_hcd(udev->bus);

/* Check if the roothub and device supports LTM. */
if (!usb_device_supports_ltm(hcd->self.root_hub) ||
!usb_device_supports_ltm(udev))
return 0;

/* Clear Feature LTM Enable can only be sent if the device is
* configured.
*/
if (!udev->actconfig)
return 0;

return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
USB_DEVICE_LTM_ENABLE, 0, NULL, 0,
USB_CTRL_SET_TIMEOUT);
}
EXPORT_SYMBOL_GPL(usb_disable_ltm);

void usb_enable_ltm(struct usb_device *udev)
{
struct usb_hcd *hcd = bus_to_hcd(udev->bus);

/* Check if the roothub and device supports LTM. */
if (!usb_device_supports_ltm(hcd->self.root_hub) ||
!usb_device_supports_ltm(udev))
return;

/* Set Feature LTM Enable can only be sent if the device is
* configured.
*/
if (!udev->actconfig)
return;

usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
USB_DEVICE_LTM_ENABLE, 0, NULL, 0,
USB_CTRL_SET_TIMEOUT);
}
EXPORT_SYMBOL_GPL(usb_enable_ltm);

#ifdef CONFIG_USB_SUSPEND

/*
Expand Down Expand Up @@ -2705,6 +2756,11 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
if (udev->usb2_hw_lpm_enabled == 1)
usb_set_usb2_hardware_lpm(udev, 0);

if (usb_disable_ltm(udev)) {
dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.",
__func__);
return -ENOMEM;
}
if (usb_unlocked_disable_lpm(udev)) {
dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.",
__func__);
Expand Down Expand Up @@ -2734,7 +2790,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
if (udev->usb2_hw_lpm_capable == 1)
usb_set_usb2_hardware_lpm(udev, 1);

/* Try to enable USB3 LPM again */
/* Try to enable USB3 LTM and LPM again */
usb_enable_ltm(udev);
usb_unlocked_enable_lpm(udev);

/* System sleep transitions should never fail */
Expand Down Expand Up @@ -2935,7 +2992,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
if (udev->usb2_hw_lpm_capable == 1)
usb_set_usb2_hardware_lpm(udev, 1);

/* Try to enable USB3 LPM */
/* Try to enable USB3 LTM and LPM */
usb_enable_ltm(udev);
usb_unlocked_enable_lpm(udev);
}

Expand Down Expand Up @@ -3488,6 +3546,15 @@ EXPORT_SYMBOL_GPL(usb_unlocked_disable_lpm);

void usb_unlocked_enable_lpm(struct usb_device *udev) { }
EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm);

int usb_disable_ltm(struct usb_device *udev)
{
return 0;
}
EXPORT_SYMBOL_GPL(usb_disable_ltm);

void usb_enable_ltm(struct usb_device *udev) { }
EXPORT_SYMBOL_GPL(usb_enable_ltm);
#endif


Expand Down Expand Up @@ -4673,15 +4740,22 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
}
parent_hub = hdev_to_hub(parent_hdev);

/* Disable LPM while we reset the device and reinstall the alt settings.
* Device-initiated LPM settings, and system exit latency settings are
* cleared when the device is reset, so we have to set them up again.
/* Disable LPM and LTM while we reset the device and reinstall the alt
* settings. Device-initiated LPM settings, and system exit latency
* settings are cleared when the device is reset, so we have to set
* them up again.
*/
ret = usb_unlocked_disable_lpm(udev);
if (ret) {
dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__);
goto re_enumerate;
}
ret = usb_disable_ltm(udev);
if (ret) {
dev_err(&udev->dev, "%s Failed to disable LTM\n.",
__func__);
goto re_enumerate;
}

set_bit(port1, parent_hub->busy_bits);
for (i = 0; i < SET_CONFIG_TRIES; ++i) {
Expand Down Expand Up @@ -4769,8 +4843,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
}

done:
/* Now that the alt settings are re-installed, enable LPM. */
/* Now that the alt settings are re-installed, enable LTM and LPM. */
usb_unlocked_enable_lpm(udev);
usb_enable_ltm(udev);
return 0;

re_enumerate:
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/usb/core/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
dev->actconfig->interface[i] = NULL;
}
usb_unlocked_disable_lpm(dev);
usb_disable_ltm(dev);
dev->actconfig = NULL;
if (dev->state == USB_STATE_CONFIGURED)
usb_set_device_state(dev, USB_STATE_ADDRESS);
Expand Down Expand Up @@ -1879,6 +1880,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration)

/* Now that the interfaces are installed, re-enable LPM. */
usb_unlocked_enable_lpm(dev);
/* Enable LTM if it was turned off by usb_disable_device. */
usb_enable_ltm(dev);

/* Now that all the interfaces are set up, register them
* to trigger binding of drivers to interfaces. probe()
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,9 @@ extern void usb_enable_lpm(struct usb_device *udev);
extern int usb_unlocked_disable_lpm(struct usb_device *udev);
extern void usb_unlocked_enable_lpm(struct usb_device *udev);

extern int usb_disable_ltm(struct usb_device *udev);
extern void usb_enable_ltm(struct usb_device *udev);

/*-------------------------------------------------------------------------*/

/* for drivers using iso endpoints */
Expand Down

0 comments on commit 637d527

Please sign in to comment.