aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-bus-usb12
-rw-r--r--drivers/usb/core/hub.c100
-rw-r--r--drivers/usb/core/message.c11
-rw-r--r--drivers/usb/core/sysfs.c10
-rw-r--r--drivers/usb/core/usb.c1
-rw-r--r--drivers/usb/host/xhci-hub.c6
-rw-r--r--include/linux/usb.h12
7 files changed, 131 insertions, 21 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index 6df4e6f57560..5f75f8f7df34 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -208,3 +208,15 @@ Description:
208 such as ACPI. This file will read either "removable" or 208 such as ACPI. This file will read either "removable" or
209 "fixed" if the information is available, and "unknown" 209 "fixed" if the information is available, and "unknown"
210 otherwise. 210 otherwise.
211
212What: /sys/bus/usb/devices/.../ltm_capable
213Date: July 2012
214Contact: Sarah Sharp <sarah.a.sharp@linux.intel.com>
215Description:
216 USB 3.0 devices may optionally support Latency Tolerance
217 Messaging (LTM). They indicate their support by setting a bit
218 in the bmAttributes field of their SuperSpeed BOS descriptors.
219 If that bit is set for the device, ltm_capable will read "yes".
220 If the device doesn't support LTM, the file will read "no".
221 The file will be present for all speeds of USB devices, and will
222 always read "no" for USB 1.1 and USB 2.0 devices.
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}
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 8b9d669e3784..0ab7da2283e3 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1174,6 +1174,8 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
1174 put_device(&dev->actconfig->interface[i]->dev); 1174 put_device(&dev->actconfig->interface[i]->dev);
1175 dev->actconfig->interface[i] = NULL; 1175 dev->actconfig->interface[i] = NULL;
1176 } 1176 }
1177 usb_unlocked_disable_lpm(dev);
1178 usb_disable_ltm(dev);
1177 dev->actconfig = NULL; 1179 dev->actconfig = NULL;
1178 if (dev->state == USB_STATE_CONFIGURED) 1180 if (dev->state == USB_STATE_CONFIGURED)
1179 usb_set_device_state(dev, USB_STATE_ADDRESS); 1181 usb_set_device_state(dev, USB_STATE_ADDRESS);
@@ -1792,14 +1794,15 @@ free_interfaces:
1792 * installed, so that the xHCI driver can recalculate the U1/U2 1794 * installed, so that the xHCI driver can recalculate the U1/U2
1793 * timeouts. 1795 * timeouts.
1794 */ 1796 */
1795 if (usb_disable_lpm(dev)) { 1797 if (dev->actconfig && usb_disable_lpm(dev)) {
1796 dev_err(&dev->dev, "%s Failed to disable LPM\n.", __func__); 1798 dev_err(&dev->dev, "%s Failed to disable LPM\n.", __func__);
1797 mutex_unlock(hcd->bandwidth_mutex); 1799 mutex_unlock(hcd->bandwidth_mutex);
1798 return -ENOMEM; 1800 return -ENOMEM;
1799 } 1801 }
1800 ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL); 1802 ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
1801 if (ret < 0) { 1803 if (ret < 0) {
1802 usb_enable_lpm(dev); 1804 if (dev->actconfig)
1805 usb_enable_lpm(dev);
1803 mutex_unlock(hcd->bandwidth_mutex); 1806 mutex_unlock(hcd->bandwidth_mutex);
1804 usb_autosuspend_device(dev); 1807 usb_autosuspend_device(dev);
1805 goto free_interfaces; 1808 goto free_interfaces;
@@ -1819,7 +1822,7 @@ free_interfaces:
1819 if (!cp) { 1822 if (!cp) {
1820 usb_set_device_state(dev, USB_STATE_ADDRESS); 1823 usb_set_device_state(dev, USB_STATE_ADDRESS);
1821 usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); 1824 usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
1822 usb_enable_lpm(dev); 1825 /* Leave LPM disabled while the device is unconfigured. */
1823 mutex_unlock(hcd->bandwidth_mutex); 1826 mutex_unlock(hcd->bandwidth_mutex);
1824 usb_autosuspend_device(dev); 1827 usb_autosuspend_device(dev);
1825 goto free_interfaces; 1828 goto free_interfaces;
@@ -1877,6 +1880,8 @@ free_interfaces:
1877 1880
1878 /* Now that the interfaces are installed, re-enable LPM. */ 1881 /* Now that the interfaces are installed, re-enable LPM. */
1879 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);
1880 1885
1881 /* Now that all the interfaces are set up, register them 1886 /* Now that all the interfaces are set up, register them
1882 * to trigger binding of drivers to interfaces. probe() 1887 * to trigger binding of drivers to interfaces. probe()
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 777f03c37725..682e8256b95d 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -253,6 +253,15 @@ show_removable(struct device *dev, struct device_attribute *attr, char *buf)
253} 253}
254static DEVICE_ATTR(removable, S_IRUGO, show_removable, NULL); 254static DEVICE_ATTR(removable, S_IRUGO, show_removable, NULL);
255 255
256static ssize_t
257show_ltm_capable(struct device *dev, struct device_attribute *attr, char *buf)
258{
259 if (usb_device_supports_ltm(to_usb_device(dev)))
260 return sprintf(buf, "%s\n", "yes");
261 return sprintf(buf, "%s\n", "no");
262}
263static DEVICE_ATTR(ltm_capable, S_IRUGO, show_ltm_capable, NULL);
264
256#ifdef CONFIG_PM 265#ifdef CONFIG_PM
257 266
258static ssize_t 267static ssize_t
@@ -649,6 +658,7 @@ static struct attribute *dev_attrs[] = {
649 &dev_attr_authorized.attr, 658 &dev_attr_authorized.attr,
650 &dev_attr_remove.attr, 659 &dev_attr_remove.attr,
651 &dev_attr_removable.attr, 660 &dev_attr_removable.attr,
661 &dev_attr_ltm_capable.attr,
652 NULL, 662 NULL,
653}; 663};
654static struct attribute_group dev_attr_grp = { 664static struct attribute_group dev_attr_grp = {
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 25d0c61c3f8a..cd8fb44a3e16 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -396,6 +396,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent,
396 dev->dev.dma_mask = bus->controller->dma_mask; 396 dev->dev.dma_mask = bus->controller->dma_mask;
397 set_dev_node(&dev->dev, dev_to_node(bus->controller)); 397 set_dev_node(&dev->dev, dev_to_node(bus->controller));
398 dev->state = USB_STATE_ATTACHED; 398 dev->state = USB_STATE_ATTACHED;
399 dev->lpm_disable_count = 1;
399 atomic_set(&dev->urbnum, 0); 400 atomic_set(&dev->urbnum, 0);
400 401
401 INIT_LIST_HEAD(&dev->ep0.urb_list); 402 INIT_LIST_HEAD(&dev->ep0.urb_list);
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 7b01094d7993..74bfc868b7ad 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -544,12 +544,18 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
544 if (hcd->speed != HCD_USB3) 544 if (hcd->speed != HCD_USB3)
545 goto error; 545 goto error;
546 546
547 /* Set the U1 and U2 exit latencies. */
547 memcpy(buf, &usb_bos_descriptor, 548 memcpy(buf, &usb_bos_descriptor,
548 USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE); 549 USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE);
549 temp = xhci_readl(xhci, &xhci->cap_regs->hcs_params3); 550 temp = xhci_readl(xhci, &xhci->cap_regs->hcs_params3);
550 buf[12] = HCS_U1_LATENCY(temp); 551 buf[12] = HCS_U1_LATENCY(temp);
551 put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]); 552 put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]);
552 553
554 /* Indicate whether the host has LTM support. */
555 temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
556 if (HCC_LTC(temp))
557 buf[8] |= USB_LTM_SUPPORT;
558
553 spin_unlock_irqrestore(&xhci->lock, flags); 559 spin_unlock_irqrestore(&xhci->lock, flags);
554 return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE; 560 return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE;
555 case GetPortStatus: 561 case GetPortStatus:
diff --git a/include/linux/usb.h b/include/linux/usb.h
index d4f9de1acd45..f8506ed0f97b 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -561,7 +561,6 @@ struct usb_device {
561 struct usb3_lpm_parameters u1_params; 561 struct usb3_lpm_parameters u1_params;
562 struct usb3_lpm_parameters u2_params; 562 struct usb3_lpm_parameters u2_params;
563 unsigned lpm_disable_count; 563 unsigned lpm_disable_count;
564 unsigned hub_initiated_lpm_disable_count;
565}; 564};
566#define to_usb_device(d) container_of(d, struct usb_device, dev) 565#define to_usb_device(d) container_of(d, struct usb_device, dev)
567 566
@@ -634,6 +633,17 @@ extern void usb_enable_lpm(struct usb_device *udev);
634extern int usb_unlocked_disable_lpm(struct usb_device *udev); 633extern int usb_unlocked_disable_lpm(struct usb_device *udev);
635extern void usb_unlocked_enable_lpm(struct usb_device *udev); 634extern void usb_unlocked_enable_lpm(struct usb_device *udev);
636 635
636extern int usb_disable_ltm(struct usb_device *udev);
637extern void usb_enable_ltm(struct usb_device *udev);
638
639static inline bool usb_device_supports_ltm(struct usb_device *udev)
640{
641 if (udev->speed != USB_SPEED_SUPER || !udev->bos || !udev->bos->ss_cap)
642 return false;
643 return udev->bos->ss_cap->bmAttributes & USB_LTM_SUPPORT;
644}
645
646
637/*-------------------------------------------------------------------------*/ 647/*-------------------------------------------------------------------------*/
638 648
639/* for drivers using iso endpoints */ 649/* for drivers using iso endpoints */