diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-bus-usb | 12 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 100 | ||||
-rw-r--r-- | drivers/usb/core/message.c | 11 | ||||
-rw-r--r-- | drivers/usb/core/sysfs.c | 10 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/xhci-hub.c | 6 | ||||
-rw-r--r-- | include/linux/usb.h | 12 |
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 | |||
212 | What: /sys/bus/usb/devices/.../ltm_capable | ||
213 | Date: July 2012 | ||
214 | Contact: Sarah Sharp <sarah.a.sharp@linux.intel.com> | ||
215 | Description: | ||
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 | ||
2617 | int 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 | } | ||
2637 | EXPORT_SYMBOL_GPL(usb_disable_ltm); | ||
2638 | |||
2639 | void 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 | } | ||
2659 | EXPORT_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 | ||
3493 | void usb_unlocked_enable_lpm(struct usb_device *udev) { } | 3544 | void usb_unlocked_enable_lpm(struct usb_device *udev) { } |
3494 | EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm); | 3545 | EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm); |
3546 | |||
3547 | int usb_disable_ltm(struct usb_device *udev) | ||
3548 | { | ||
3549 | return 0; | ||
3550 | } | ||
3551 | EXPORT_SYMBOL_GPL(usb_disable_ltm); | ||
3552 | |||
3553 | void usb_enable_ltm(struct usb_device *udev) { } | ||
3554 | EXPORT_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); | ||
4778 | done: | 4840 | done: |
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 | ||
4781 | re_enumerate: | 4846 | re_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 | } |
254 | static DEVICE_ATTR(removable, S_IRUGO, show_removable, NULL); | 254 | static DEVICE_ATTR(removable, S_IRUGO, show_removable, NULL); |
255 | 255 | ||
256 | static ssize_t | ||
257 | show_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 | } | ||
263 | static DEVICE_ATTR(ltm_capable, S_IRUGO, show_ltm_capable, NULL); | ||
264 | |||
256 | #ifdef CONFIG_PM | 265 | #ifdef CONFIG_PM |
257 | 266 | ||
258 | static ssize_t | 267 | static 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 | }; |
654 | static struct attribute_group dev_attr_grp = { | 664 | static 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); | |||
634 | extern int usb_unlocked_disable_lpm(struct usb_device *udev); | 633 | extern int usb_unlocked_disable_lpm(struct usb_device *udev); |
635 | extern void usb_unlocked_enable_lpm(struct usb_device *udev); | 634 | extern void usb_unlocked_enable_lpm(struct usb_device *udev); |
636 | 635 | ||
636 | extern int usb_disable_ltm(struct usb_device *udev); | ||
637 | extern void usb_enable_ltm(struct usb_device *udev); | ||
638 | |||
639 | static 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 */ |