aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/hub.c87
-rw-r--r--drivers/usb/core/message.c3
2 files changed, 84 insertions, 6 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 5c31d2c2f95a..b5bd6bd8fd12 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2610,6 +2610,57 @@ static int check_port_resume_type(struct usb_device *udev,
2610 return status; 2610 return status;
2611} 2611}
2612 2612
2613static bool usb_device_supports_ltm(struct usb_device *udev)
2614{
2615 if (udev->speed != USB_SPEED_SUPER || !udev->bos || !udev->bos->ss_cap)
2616 return false;
2617 return udev->bos->ss_cap->bmAttributes & USB_LTM_SUPPORT;
2618}
2619
2620int usb_disable_ltm(struct usb_device *udev)
2621{
2622 struct usb_hcd *hcd = bus_to_hcd(udev->bus);
2623
2624 /* Check if the roothub and device supports LTM. */
2625 if (!usb_device_supports_ltm(hcd->self.root_hub) ||
2626 !usb_device_supports_ltm(udev))
2627 return 0;
2628
2629 /* Clear Feature LTM Enable can only be sent if the device is
2630 * configured.
2631 */
2632 if (!udev->actconfig)
2633 return 0;
2634
2635 return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
2636 USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
2637 USB_DEVICE_LTM_ENABLE, 0, NULL, 0,
2638 USB_CTRL_SET_TIMEOUT);
2639}
2640EXPORT_SYMBOL_GPL(usb_disable_ltm);
2641
2642void usb_enable_ltm(struct usb_device *udev)
2643{
2644 struct usb_hcd *hcd = bus_to_hcd(udev->bus);
2645
2646 /* Check if the roothub and device supports LTM. */
2647 if (!usb_device_supports_ltm(hcd->self.root_hub) ||
2648 !usb_device_supports_ltm(udev))
2649 return;
2650
2651 /* Set Feature LTM Enable can only be sent if the device is
2652 * configured.
2653 */
2654 if (!udev->actconfig)
2655 return;
2656
2657 usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
2658 USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
2659 USB_DEVICE_LTM_ENABLE, 0, NULL, 0,
2660 USB_CTRL_SET_TIMEOUT);
2661}
2662EXPORT_SYMBOL_GPL(usb_enable_ltm);
2663
2613#ifdef CONFIG_USB_SUSPEND 2664#ifdef CONFIG_USB_SUSPEND
2614 2665
2615/* 2666/*
@@ -2705,6 +2756,11 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
2705 if (udev->usb2_hw_lpm_enabled == 1) 2756 if (udev->usb2_hw_lpm_enabled == 1)
2706 usb_set_usb2_hardware_lpm(udev, 0); 2757 usb_set_usb2_hardware_lpm(udev, 0);
2707 2758
2759 if (usb_disable_ltm(udev)) {
2760 dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.",
2761 __func__);
2762 return -ENOMEM;
2763 }
2708 if (usb_unlocked_disable_lpm(udev)) { 2764 if (usb_unlocked_disable_lpm(udev)) {
2709 dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.", 2765 dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.",
2710 __func__); 2766 __func__);
@@ -2734,7 +2790,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
2734 if (udev->usb2_hw_lpm_capable == 1) 2790 if (udev->usb2_hw_lpm_capable == 1)
2735 usb_set_usb2_hardware_lpm(udev, 1); 2791 usb_set_usb2_hardware_lpm(udev, 1);
2736 2792
2737 /* Try to enable USB3 LPM again */ 2793 /* Try to enable USB3 LTM and LPM again */
2794 usb_enable_ltm(udev);
2738 usb_unlocked_enable_lpm(udev); 2795 usb_unlocked_enable_lpm(udev);
2739 2796
2740 /* System sleep transitions should never fail */ 2797 /* System sleep transitions should never fail */
@@ -2935,7 +2992,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
2935 if (udev->usb2_hw_lpm_capable == 1) 2992 if (udev->usb2_hw_lpm_capable == 1)
2936 usb_set_usb2_hardware_lpm(udev, 1); 2993 usb_set_usb2_hardware_lpm(udev, 1);
2937 2994
2938 /* Try to enable USB3 LPM */ 2995 /* Try to enable USB3 LTM and LPM */
2996 usb_enable_ltm(udev);
2939 usb_unlocked_enable_lpm(udev); 2997 usb_unlocked_enable_lpm(udev);
2940 } 2998 }
2941 2999
@@ -3488,6 +3546,15 @@ EXPORT_SYMBOL_GPL(usb_unlocked_disable_lpm);
3488 3546
3489void usb_unlocked_enable_lpm(struct usb_device *udev) { } 3547void usb_unlocked_enable_lpm(struct usb_device *udev) { }
3490EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm); 3548EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm);
3549
3550int usb_disable_ltm(struct usb_device *udev)
3551{
3552 return 0;
3553}
3554EXPORT_SYMBOL_GPL(usb_disable_ltm);
3555
3556void usb_enable_ltm(struct usb_device *udev) { }
3557EXPORT_SYMBOL_GPL(usb_enable_ltm);
3491#endif 3558#endif
3492 3559
3493 3560
@@ -4673,15 +4740,22 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
4673 } 4740 }
4674 parent_hub = hdev_to_hub(parent_hdev); 4741 parent_hub = hdev_to_hub(parent_hdev);
4675 4742
4676 /* Disable LPM while we reset the device and reinstall the alt settings. 4743 /* Disable LPM and LTM while we reset the device and reinstall the alt
4677 * Device-initiated LPM settings, and system exit latency settings are 4744 * settings. Device-initiated LPM settings, and system exit latency
4678 * cleared when the device is reset, so we have to set them up again. 4745 * settings are cleared when the device is reset, so we have to set
4746 * them up again.
4679 */ 4747 */
4680 ret = usb_unlocked_disable_lpm(udev); 4748 ret = usb_unlocked_disable_lpm(udev);
4681 if (ret) { 4749 if (ret) {
4682 dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__); 4750 dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__);
4683 goto re_enumerate; 4751 goto re_enumerate;
4684 } 4752 }
4753 ret = usb_disable_ltm(udev);
4754 if (ret) {
4755 dev_err(&udev->dev, "%s Failed to disable LTM\n.",
4756 __func__);
4757 goto re_enumerate;
4758 }
4685 4759
4686 set_bit(port1, parent_hub->busy_bits); 4760 set_bit(port1, parent_hub->busy_bits);
4687 for (i = 0; i < SET_CONFIG_TRIES; ++i) { 4761 for (i = 0; i < SET_CONFIG_TRIES; ++i) {
@@ -4769,8 +4843,9 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
4769 } 4843 }
4770 4844
4771done: 4845done:
4772 /* Now that the alt settings are re-installed, enable LPM. */ 4846 /* Now that the alt settings are re-installed, enable LTM and LPM. */
4773 usb_unlocked_enable_lpm(udev); 4847 usb_unlocked_enable_lpm(udev);
4848 usb_enable_ltm(udev);
4774 return 0; 4849 return 0;
4775 4850
4776re_enumerate: 4851re_enumerate:
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index c0877b7f505a..0ab7da2283e3 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1175,6 +1175,7 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
1175 dev->actconfig->interface[i] = NULL; 1175 dev->actconfig->interface[i] = NULL;
1176 } 1176 }
1177 usb_unlocked_disable_lpm(dev); 1177 usb_unlocked_disable_lpm(dev);
1178 usb_disable_ltm(dev);
1178 dev->actconfig = NULL; 1179 dev->actconfig = NULL;
1179 if (dev->state == USB_STATE_CONFIGURED) 1180 if (dev->state == USB_STATE_CONFIGURED)
1180 usb_set_device_state(dev, USB_STATE_ADDRESS); 1181 usb_set_device_state(dev, USB_STATE_ADDRESS);
@@ -1879,6 +1880,8 @@ free_interfaces:
1879 1880
1880 /* Now that the interfaces are installed, re-enable LPM. */ 1881 /* Now that the interfaces are installed, re-enable LPM. */
1881 usb_unlocked_enable_lpm(dev); 1882 usb_unlocked_enable_lpm(dev);
1883 /* Enable LTM if it was turned off by usb_disable_device. */
1884 usb_enable_ltm(dev);
1882 1885
1883 /* Now that all the interfaces are set up, register them 1886 /* Now that all the interfaces are set up, register them
1884 * to trigger binding of drivers to interfaces. probe() 1887 * to trigger binding of drivers to interfaces. probe()