aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hub.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-16 19:58:30 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-16 19:58:30 -0400
commit6470cbc486652942dcf6c4b6420e3a521e766bbf (patch)
tree3244e6e1998031ac17e12283b2f797e60743d93b /drivers/usb/core/hub.c
parent43fe3a99d9caf10b25f9c596e9854cdae30db418 (diff)
parent024f117c2f3c4bb5df6e6696b709e0f3ed7e5dbb (diff)
Merge tag 'for-usb-next-2012-07-11' of git://git.kernel.org/pub/scm/linux/kernel/git/sarah/xhci into usb-next
USB: Link PM fixes and Latency Tolerance Messaging Hi Greg, Here's four bug fix patches for Link PM (LPM), which are marked for 3.5-stable. There's also three patches that turn on Latency Tolerance Messaging (LTM) for xHCI host controllers and USB 3.0 devices that support this low power feature. Please queue for 3.6. Sarah Sharp
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r--drivers/usb/core/hub.c100
1 files changed, 83 insertions, 17 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 9e900f9a2ef7..3febe54883bd 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2614,6 +2614,50 @@ static int check_port_resume_type(struct usb_device *udev,
2614 return status; 2614 return status;
2615} 2615}
2616 2616
2617int usb_disable_ltm(struct usb_device *udev)
2618{
2619 struct usb_hcd *hcd = bus_to_hcd(udev->bus);
2620
2621 /* Check if the roothub and device supports LTM. */
2622 if (!usb_device_supports_ltm(hcd->self.root_hub) ||
2623 !usb_device_supports_ltm(udev))
2624 return 0;
2625
2626 /* Clear Feature LTM Enable can only be sent if the device is
2627 * configured.
2628 */
2629 if (!udev->actconfig)
2630 return 0;
2631
2632 return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
2633 USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
2634 USB_DEVICE_LTM_ENABLE, 0, NULL, 0,
2635 USB_CTRL_SET_TIMEOUT);
2636}
2637EXPORT_SYMBOL_GPL(usb_disable_ltm);
2638
2639void usb_enable_ltm(struct usb_device *udev)
2640{
2641 struct usb_hcd *hcd = bus_to_hcd(udev->bus);
2642
2643 /* Check if the roothub and device supports LTM. */
2644 if (!usb_device_supports_ltm(hcd->self.root_hub) ||
2645 !usb_device_supports_ltm(udev))
2646 return;
2647
2648 /* Set Feature LTM Enable can only be sent if the device is
2649 * configured.
2650 */
2651 if (!udev->actconfig)
2652 return;
2653
2654 usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
2655 USB_REQ_SET_FEATURE, USB_RECIP_DEVICE,
2656 USB_DEVICE_LTM_ENABLE, 0, NULL, 0,
2657 USB_CTRL_SET_TIMEOUT);
2658}
2659EXPORT_SYMBOL_GPL(usb_enable_ltm);
2660
2617#ifdef CONFIG_USB_SUSPEND 2661#ifdef CONFIG_USB_SUSPEND
2618 2662
2619/* 2663/*
@@ -2709,6 +2753,11 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
2709 if (udev->usb2_hw_lpm_enabled == 1) 2753 if (udev->usb2_hw_lpm_enabled == 1)
2710 usb_set_usb2_hardware_lpm(udev, 0); 2754 usb_set_usb2_hardware_lpm(udev, 0);
2711 2755
2756 if (usb_disable_ltm(udev)) {
2757 dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.",
2758 __func__);
2759 return -ENOMEM;
2760 }
2712 if (usb_unlocked_disable_lpm(udev)) { 2761 if (usb_unlocked_disable_lpm(udev)) {
2713 dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.", 2762 dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.",
2714 __func__); 2763 __func__);
@@ -2738,7 +2787,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
2738 if (udev->usb2_hw_lpm_capable == 1) 2787 if (udev->usb2_hw_lpm_capable == 1)
2739 usb_set_usb2_hardware_lpm(udev, 1); 2788 usb_set_usb2_hardware_lpm(udev, 1);
2740 2789
2741 /* Try to enable USB3 LPM again */ 2790 /* Try to enable USB3 LTM and LPM again */
2791 usb_enable_ltm(udev);
2742 usb_unlocked_enable_lpm(udev); 2792 usb_unlocked_enable_lpm(udev);
2743 2793
2744 /* System sleep transitions should never fail */ 2794 /* System sleep transitions should never fail */
@@ -2939,7 +2989,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
2939 if (udev->usb2_hw_lpm_capable == 1) 2989 if (udev->usb2_hw_lpm_capable == 1)
2940 usb_set_usb2_hardware_lpm(udev, 1); 2990 usb_set_usb2_hardware_lpm(udev, 1);
2941 2991
2942 /* Try to enable USB3 LPM */ 2992 /* Try to enable USB3 LTM and LPM */
2993 usb_enable_ltm(udev);
2943 usb_unlocked_enable_lpm(udev); 2994 usb_unlocked_enable_lpm(udev);
2944 } 2995 }
2945 2996
@@ -3492,6 +3543,15 @@ EXPORT_SYMBOL_GPL(usb_unlocked_disable_lpm);
3492 3543
3493void usb_unlocked_enable_lpm(struct usb_device *udev) { } 3544void usb_unlocked_enable_lpm(struct usb_device *udev) { }
3494EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm); 3545EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm);
3546
3547int usb_disable_ltm(struct usb_device *udev)
3548{
3549 return 0;
3550}
3551EXPORT_SYMBOL_GPL(usb_disable_ltm);
3552
3553void usb_enable_ltm(struct usb_device *udev) { }
3554EXPORT_SYMBOL_GPL(usb_enable_ltm);
3495#endif 3555#endif
3496 3556
3497 3557
@@ -4675,6 +4735,23 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
4675 } 4735 }
4676 parent_hub = hdev_to_hub(parent_hdev); 4736 parent_hub = hdev_to_hub(parent_hdev);
4677 4737
4738 /* Disable LPM and LTM while we reset the device and reinstall the alt
4739 * settings. Device-initiated LPM settings, and system exit latency
4740 * settings are cleared when the device is reset, so we have to set
4741 * them up again.
4742 */
4743 ret = usb_unlocked_disable_lpm(udev);
4744 if (ret) {
4745 dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__);
4746 goto re_enumerate;
4747 }
4748 ret = usb_disable_ltm(udev);
4749 if (ret) {
4750 dev_err(&udev->dev, "%s Failed to disable LTM\n.",
4751 __func__);
4752 goto re_enumerate;
4753 }
4754
4678 set_bit(port1, parent_hub->busy_bits); 4755 set_bit(port1, parent_hub->busy_bits);
4679 for (i = 0; i < SET_CONFIG_TRIES; ++i) { 4756 for (i = 0; i < SET_CONFIG_TRIES; ++i) {
4680 4757
@@ -4702,22 +4779,11 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
4702 goto done; 4779 goto done;
4703 4780
4704 mutex_lock(hcd->bandwidth_mutex); 4781 mutex_lock(hcd->bandwidth_mutex);
4705 /* Disable LPM while we reset the device and reinstall the alt settings.
4706 * Device-initiated LPM settings, and system exit latency settings are
4707 * cleared when the device is reset, so we have to set them up again.
4708 */
4709 ret = usb_disable_lpm(udev);
4710 if (ret) {
4711 dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__);
4712 mutex_unlock(hcd->bandwidth_mutex);
4713 goto done;
4714 }
4715 ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL); 4782 ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL);
4716 if (ret < 0) { 4783 if (ret < 0) {
4717 dev_warn(&udev->dev, 4784 dev_warn(&udev->dev,
4718 "Busted HC? Not enough HCD resources for " 4785 "Busted HC? Not enough HCD resources for "
4719 "old configuration.\n"); 4786 "old configuration.\n");
4720 usb_enable_lpm(udev);
4721 mutex_unlock(hcd->bandwidth_mutex); 4787 mutex_unlock(hcd->bandwidth_mutex);
4722 goto re_enumerate; 4788 goto re_enumerate;
4723 } 4789 }
@@ -4729,7 +4795,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
4729 dev_err(&udev->dev, 4795 dev_err(&udev->dev,
4730 "can't restore configuration #%d (error=%d)\n", 4796 "can't restore configuration #%d (error=%d)\n",
4731 udev->actconfig->desc.bConfigurationValue, ret); 4797 udev->actconfig->desc.bConfigurationValue, ret);
4732 usb_enable_lpm(udev);
4733 mutex_unlock(hcd->bandwidth_mutex); 4798 mutex_unlock(hcd->bandwidth_mutex);
4734 goto re_enumerate; 4799 goto re_enumerate;
4735 } 4800 }
@@ -4768,17 +4833,18 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
4768 desc->bInterfaceNumber, 4833 desc->bInterfaceNumber,
4769 desc->bAlternateSetting, 4834 desc->bAlternateSetting,
4770 ret); 4835 ret);
4771 usb_unlocked_enable_lpm(udev);
4772 goto re_enumerate; 4836 goto re_enumerate;
4773 } 4837 }
4774 } 4838 }
4775 4839
4776 /* Now that the alt settings are re-installed, enable LPM. */
4777 usb_unlocked_enable_lpm(udev);
4778done: 4840done:
4841 /* Now that the alt settings are re-installed, enable LTM and LPM. */
4842 usb_unlocked_enable_lpm(udev);
4843 usb_enable_ltm(udev);
4779 return 0; 4844 return 0;
4780 4845
4781re_enumerate: 4846re_enumerate:
4847 /* LPM state doesn't matter when we're about to destroy the device. */
4782 hub_port_logical_disconnect(parent_hub, port1); 4848 hub_port_logical_disconnect(parent_hub, port1);
4783 return -ENODEV; 4849 return -ENODEV;
4784} 4850}