diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
| -rw-r--r-- | drivers/usb/core/hub.c | 139 |
1 files changed, 110 insertions, 29 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 8fb484984c86..821126eb8176 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/usb.h> | 20 | #include <linux/usb.h> |
| 21 | #include <linux/usbdevice_fs.h> | 21 | #include <linux/usbdevice_fs.h> |
| 22 | #include <linux/usb/hcd.h> | 22 | #include <linux/usb/hcd.h> |
| 23 | #include <linux/usb/otg.h> | ||
| 23 | #include <linux/usb/quirks.h> | 24 | #include <linux/usb/quirks.h> |
| 24 | #include <linux/kthread.h> | 25 | #include <linux/kthread.h> |
| 25 | #include <linux/mutex.h> | 26 | #include <linux/mutex.h> |
| @@ -81,7 +82,7 @@ struct usb_hub { | |||
| 81 | u8 indicator[USB_MAXCHILDREN]; | 82 | u8 indicator[USB_MAXCHILDREN]; |
| 82 | struct delayed_work leds; | 83 | struct delayed_work leds; |
| 83 | struct delayed_work init_work; | 84 | struct delayed_work init_work; |
| 84 | void **port_owners; | 85 | struct dev_state **port_owners; |
| 85 | }; | 86 | }; |
| 86 | 87 | ||
| 87 | static inline int hub_is_superspeed(struct usb_device *hdev) | 88 | static inline int hub_is_superspeed(struct usb_device *hdev) |
| @@ -1271,7 +1272,8 @@ static int hub_configure(struct usb_hub *hub, | |||
| 1271 | 1272 | ||
| 1272 | hdev->children = kzalloc(hdev->maxchild * | 1273 | hdev->children = kzalloc(hdev->maxchild * |
| 1273 | sizeof(struct usb_device *), GFP_KERNEL); | 1274 | sizeof(struct usb_device *), GFP_KERNEL); |
| 1274 | hub->port_owners = kzalloc(hdev->maxchild * sizeof(void *), GFP_KERNEL); | 1275 | hub->port_owners = kzalloc(hdev->maxchild * sizeof(struct dev_state *), |
| 1276 | GFP_KERNEL); | ||
| 1275 | if (!hdev->children || !hub->port_owners) { | 1277 | if (!hdev->children || !hub->port_owners) { |
| 1276 | ret = -ENOMEM; | 1278 | ret = -ENOMEM; |
| 1277 | goto fail; | 1279 | goto fail; |
| @@ -1649,7 +1651,7 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) | |||
| 1649 | * to one of these "claimed" ports, the program will "own" the device. | 1651 | * to one of these "claimed" ports, the program will "own" the device. |
| 1650 | */ | 1652 | */ |
| 1651 | static int find_port_owner(struct usb_device *hdev, unsigned port1, | 1653 | static int find_port_owner(struct usb_device *hdev, unsigned port1, |
| 1652 | void ***ppowner) | 1654 | struct dev_state ***ppowner) |
| 1653 | { | 1655 | { |
| 1654 | if (hdev->state == USB_STATE_NOTATTACHED) | 1656 | if (hdev->state == USB_STATE_NOTATTACHED) |
| 1655 | return -ENODEV; | 1657 | return -ENODEV; |
| @@ -1664,10 +1666,11 @@ static int find_port_owner(struct usb_device *hdev, unsigned port1, | |||
| 1664 | } | 1666 | } |
| 1665 | 1667 | ||
| 1666 | /* In the following three functions, the caller must hold hdev's lock */ | 1668 | /* In the following three functions, the caller must hold hdev's lock */ |
| 1667 | int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, void *owner) | 1669 | int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, |
| 1670 | struct dev_state *owner) | ||
| 1668 | { | 1671 | { |
| 1669 | int rc; | 1672 | int rc; |
| 1670 | void **powner; | 1673 | struct dev_state **powner; |
| 1671 | 1674 | ||
| 1672 | rc = find_port_owner(hdev, port1, &powner); | 1675 | rc = find_port_owner(hdev, port1, &powner); |
| 1673 | if (rc) | 1676 | if (rc) |
| @@ -1678,10 +1681,11 @@ int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, void *owner) | |||
| 1678 | return rc; | 1681 | return rc; |
| 1679 | } | 1682 | } |
| 1680 | 1683 | ||
| 1681 | int usb_hub_release_port(struct usb_device *hdev, unsigned port1, void *owner) | 1684 | int usb_hub_release_port(struct usb_device *hdev, unsigned port1, |
| 1685 | struct dev_state *owner) | ||
| 1682 | { | 1686 | { |
| 1683 | int rc; | 1687 | int rc; |
| 1684 | void **powner; | 1688 | struct dev_state **powner; |
| 1685 | 1689 | ||
| 1686 | rc = find_port_owner(hdev, port1, &powner); | 1690 | rc = find_port_owner(hdev, port1, &powner); |
| 1687 | if (rc) | 1691 | if (rc) |
| @@ -1692,10 +1696,10 @@ int usb_hub_release_port(struct usb_device *hdev, unsigned port1, void *owner) | |||
| 1692 | return rc; | 1696 | return rc; |
| 1693 | } | 1697 | } |
| 1694 | 1698 | ||
| 1695 | void usb_hub_release_all_ports(struct usb_device *hdev, void *owner) | 1699 | void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner) |
| 1696 | { | 1700 | { |
| 1697 | int n; | 1701 | int n; |
| 1698 | void **powner; | 1702 | struct dev_state **powner; |
| 1699 | 1703 | ||
| 1700 | n = find_port_owner(hdev, 1, &powner); | 1704 | n = find_port_owner(hdev, 1, &powner); |
| 1701 | if (n == 0) { | 1705 | if (n == 0) { |
| @@ -2065,7 +2069,7 @@ static int usb_enumerate_device(struct usb_device *udev) | |||
| 2065 | if (err < 0) { | 2069 | if (err < 0) { |
| 2066 | dev_err(&udev->dev, "can't read configurations, error %d\n", | 2070 | dev_err(&udev->dev, "can't read configurations, error %d\n", |
| 2067 | err); | 2071 | err); |
| 2068 | goto fail; | 2072 | return err; |
| 2069 | } | 2073 | } |
| 2070 | } | 2074 | } |
| 2071 | if (udev->wusb == 1 && udev->authorized == 0) { | 2075 | if (udev->wusb == 1 && udev->authorized == 0) { |
| @@ -2081,8 +2085,12 @@ static int usb_enumerate_device(struct usb_device *udev) | |||
| 2081 | udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); | 2085 | udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); |
| 2082 | } | 2086 | } |
| 2083 | err = usb_enumerate_device_otg(udev); | 2087 | err = usb_enumerate_device_otg(udev); |
| 2084 | fail: | 2088 | if (err < 0) |
| 2085 | return err; | 2089 | return err; |
| 2090 | |||
| 2091 | usb_detect_interface_quirks(udev); | ||
| 2092 | |||
| 2093 | return 0; | ||
| 2086 | } | 2094 | } |
| 2087 | 2095 | ||
| 2088 | static void set_usb_port_removable(struct usb_device *udev) | 2096 | static void set_usb_port_removable(struct usb_device *udev) |
| @@ -2611,6 +2619,50 @@ static int check_port_resume_type(struct usb_device *udev, | |||
| 2611 | return status; | 2619 | return status; |
| 2612 | } | 2620 | } |
| 2613 | 2621 | ||
| 2622 | int usb_disable_ltm(struct usb_device *udev) | ||
| 2623 | { | ||
| 2624 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); | ||
| 2625 | |||
| 2626 | /* Check if the roothub and device supports LTM. */ | ||
| 2627 | if (!usb_device_supports_ltm(hcd->self.root_hub) || | ||
| 2628 | !usb_device_supports_ltm(udev)) | ||
| 2629 | return 0; | ||
| 2630 | |||
| 2631 | /* Clear Feature LTM Enable can only be sent if the device is | ||
| 2632 | * configured. | ||
| 2633 | */ | ||
| 2634 | if (!udev->actconfig) | ||
| 2635 | return 0; | ||
| 2636 | |||
| 2637 | return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 2638 | USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, | ||
| 2639 | USB_DEVICE_LTM_ENABLE, 0, NULL, 0, | ||
| 2640 | USB_CTRL_SET_TIMEOUT); | ||
| 2641 | } | ||
| 2642 | EXPORT_SYMBOL_GPL(usb_disable_ltm); | ||
| 2643 | |||
| 2644 | void usb_enable_ltm(struct usb_device *udev) | ||
| 2645 | { | ||
| 2646 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); | ||
| 2647 | |||
| 2648 | /* Check if the roothub and device supports LTM. */ | ||
| 2649 | if (!usb_device_supports_ltm(hcd->self.root_hub) || | ||
| 2650 | !usb_device_supports_ltm(udev)) | ||
| 2651 | return; | ||
| 2652 | |||
| 2653 | /* Set Feature LTM Enable can only be sent if the device is | ||
| 2654 | * configured. | ||
| 2655 | */ | ||
| 2656 | if (!udev->actconfig) | ||
| 2657 | return; | ||
| 2658 | |||
| 2659 | usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
| 2660 | USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, | ||
| 2661 | USB_DEVICE_LTM_ENABLE, 0, NULL, 0, | ||
| 2662 | USB_CTRL_SET_TIMEOUT); | ||
| 2663 | } | ||
| 2664 | EXPORT_SYMBOL_GPL(usb_enable_ltm); | ||
| 2665 | |||
| 2614 | #ifdef CONFIG_USB_SUSPEND | 2666 | #ifdef CONFIG_USB_SUSPEND |
| 2615 | 2667 | ||
| 2616 | /* | 2668 | /* |
| @@ -2706,6 +2758,11 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
| 2706 | if (udev->usb2_hw_lpm_enabled == 1) | 2758 | if (udev->usb2_hw_lpm_enabled == 1) |
| 2707 | usb_set_usb2_hardware_lpm(udev, 0); | 2759 | usb_set_usb2_hardware_lpm(udev, 0); |
| 2708 | 2760 | ||
| 2761 | if (usb_disable_ltm(udev)) { | ||
| 2762 | dev_err(&udev->dev, "%s Failed to disable LTM before suspend\n.", | ||
| 2763 | __func__); | ||
| 2764 | return -ENOMEM; | ||
| 2765 | } | ||
| 2709 | if (usb_unlocked_disable_lpm(udev)) { | 2766 | if (usb_unlocked_disable_lpm(udev)) { |
| 2710 | dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.", | 2767 | dev_err(&udev->dev, "%s Failed to disable LPM before suspend\n.", |
| 2711 | __func__); | 2768 | __func__); |
| @@ -2735,7 +2792,8 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
| 2735 | if (udev->usb2_hw_lpm_capable == 1) | 2792 | if (udev->usb2_hw_lpm_capable == 1) |
| 2736 | usb_set_usb2_hardware_lpm(udev, 1); | 2793 | usb_set_usb2_hardware_lpm(udev, 1); |
| 2737 | 2794 | ||
| 2738 | /* Try to enable USB3 LPM again */ | 2795 | /* Try to enable USB3 LTM and LPM again */ |
| 2796 | usb_enable_ltm(udev); | ||
| 2739 | usb_unlocked_enable_lpm(udev); | 2797 | usb_unlocked_enable_lpm(udev); |
| 2740 | 2798 | ||
| 2741 | /* System sleep transitions should never fail */ | 2799 | /* System sleep transitions should never fail */ |
| @@ -2936,7 +2994,8 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) | |||
| 2936 | if (udev->usb2_hw_lpm_capable == 1) | 2994 | if (udev->usb2_hw_lpm_capable == 1) |
| 2937 | usb_set_usb2_hardware_lpm(udev, 1); | 2995 | usb_set_usb2_hardware_lpm(udev, 1); |
| 2938 | 2996 | ||
| 2939 | /* Try to enable USB3 LPM */ | 2997 | /* Try to enable USB3 LTM and LPM */ |
| 2998 | usb_enable_ltm(udev); | ||
| 2940 | usb_unlocked_enable_lpm(udev); | 2999 | usb_unlocked_enable_lpm(udev); |
| 2941 | } | 3000 | } |
| 2942 | 3001 | ||
| @@ -3489,6 +3548,15 @@ EXPORT_SYMBOL_GPL(usb_unlocked_disable_lpm); | |||
| 3489 | 3548 | ||
| 3490 | void usb_unlocked_enable_lpm(struct usb_device *udev) { } | 3549 | void usb_unlocked_enable_lpm(struct usb_device *udev) { } |
| 3491 | EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm); | 3550 | EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm); |
| 3551 | |||
| 3552 | int usb_disable_ltm(struct usb_device *udev) | ||
| 3553 | { | ||
| 3554 | return 0; | ||
| 3555 | } | ||
| 3556 | EXPORT_SYMBOL_GPL(usb_disable_ltm); | ||
| 3557 | |||
| 3558 | void usb_enable_ltm(struct usb_device *udev) { } | ||
| 3559 | EXPORT_SYMBOL_GPL(usb_enable_ltm); | ||
| 3492 | #endif | 3560 | #endif |
| 3493 | 3561 | ||
| 3494 | 3562 | ||
| @@ -4038,6 +4106,13 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, | |||
| 4038 | } | 4106 | } |
| 4039 | } | 4107 | } |
| 4040 | 4108 | ||
| 4109 | if (hcd->phy && !hdev->parent) { | ||
| 4110 | if (portstatus & USB_PORT_STAT_CONNECTION) | ||
| 4111 | usb_phy_notify_connect(hcd->phy, port1); | ||
| 4112 | else | ||
| 4113 | usb_phy_notify_disconnect(hcd->phy, port1); | ||
| 4114 | } | ||
| 4115 | |||
| 4041 | /* Return now if debouncing failed or nothing is connected or | 4116 | /* Return now if debouncing failed or nothing is connected or |
| 4042 | * the device was "removed". | 4117 | * the device was "removed". |
| 4043 | */ | 4118 | */ |
| @@ -4672,6 +4747,23 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
| 4672 | } | 4747 | } |
| 4673 | parent_hub = hdev_to_hub(parent_hdev); | 4748 | parent_hub = hdev_to_hub(parent_hdev); |
| 4674 | 4749 | ||
| 4750 | /* Disable LPM and LTM while we reset the device and reinstall the alt | ||
| 4751 | * settings. Device-initiated LPM settings, and system exit latency | ||
| 4752 | * settings are cleared when the device is reset, so we have to set | ||
| 4753 | * them up again. | ||
| 4754 | */ | ||
| 4755 | ret = usb_unlocked_disable_lpm(udev); | ||
| 4756 | if (ret) { | ||
| 4757 | dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__); | ||
| 4758 | goto re_enumerate; | ||
| 4759 | } | ||
| 4760 | ret = usb_disable_ltm(udev); | ||
| 4761 | if (ret) { | ||
| 4762 | dev_err(&udev->dev, "%s Failed to disable LTM\n.", | ||
| 4763 | __func__); | ||
| 4764 | goto re_enumerate; | ||
| 4765 | } | ||
| 4766 | |||
| 4675 | set_bit(port1, parent_hub->busy_bits); | 4767 | set_bit(port1, parent_hub->busy_bits); |
| 4676 | for (i = 0; i < SET_CONFIG_TRIES; ++i) { | 4768 | for (i = 0; i < SET_CONFIG_TRIES; ++i) { |
| 4677 | 4769 | ||
| @@ -4699,22 +4791,11 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
| 4699 | goto done; | 4791 | goto done; |
| 4700 | 4792 | ||
| 4701 | mutex_lock(hcd->bandwidth_mutex); | 4793 | mutex_lock(hcd->bandwidth_mutex); |
| 4702 | /* Disable LPM while we reset the device and reinstall the alt settings. | ||
| 4703 | * Device-initiated LPM settings, and system exit latency settings are | ||
| 4704 | * cleared when the device is reset, so we have to set them up again. | ||
| 4705 | */ | ||
| 4706 | ret = usb_disable_lpm(udev); | ||
| 4707 | if (ret) { | ||
| 4708 | dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__); | ||
| 4709 | mutex_unlock(hcd->bandwidth_mutex); | ||
| 4710 | goto done; | ||
| 4711 | } | ||
| 4712 | ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL); | 4794 | ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL); |
| 4713 | if (ret < 0) { | 4795 | if (ret < 0) { |
| 4714 | dev_warn(&udev->dev, | 4796 | dev_warn(&udev->dev, |
| 4715 | "Busted HC? Not enough HCD resources for " | 4797 | "Busted HC? Not enough HCD resources for " |
| 4716 | "old configuration.\n"); | 4798 | "old configuration.\n"); |
| 4717 | usb_enable_lpm(udev); | ||
| 4718 | mutex_unlock(hcd->bandwidth_mutex); | 4799 | mutex_unlock(hcd->bandwidth_mutex); |
| 4719 | goto re_enumerate; | 4800 | goto re_enumerate; |
| 4720 | } | 4801 | } |
| @@ -4726,7 +4807,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
| 4726 | dev_err(&udev->dev, | 4807 | dev_err(&udev->dev, |
| 4727 | "can't restore configuration #%d (error=%d)\n", | 4808 | "can't restore configuration #%d (error=%d)\n", |
| 4728 | udev->actconfig->desc.bConfigurationValue, ret); | 4809 | udev->actconfig->desc.bConfigurationValue, ret); |
| 4729 | usb_enable_lpm(udev); | ||
| 4730 | mutex_unlock(hcd->bandwidth_mutex); | 4810 | mutex_unlock(hcd->bandwidth_mutex); |
| 4731 | goto re_enumerate; | 4811 | goto re_enumerate; |
| 4732 | } | 4812 | } |
| @@ -4765,17 +4845,18 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
| 4765 | desc->bInterfaceNumber, | 4845 | desc->bInterfaceNumber, |
| 4766 | desc->bAlternateSetting, | 4846 | desc->bAlternateSetting, |
| 4767 | ret); | 4847 | ret); |
| 4768 | usb_unlocked_enable_lpm(udev); | ||
| 4769 | goto re_enumerate; | 4848 | goto re_enumerate; |
| 4770 | } | 4849 | } |
| 4771 | } | 4850 | } |
| 4772 | 4851 | ||
| 4773 | /* Now that the alt settings are re-installed, enable LPM. */ | ||
| 4774 | usb_unlocked_enable_lpm(udev); | ||
| 4775 | done: | 4852 | done: |
| 4853 | /* Now that the alt settings are re-installed, enable LTM and LPM. */ | ||
| 4854 | usb_unlocked_enable_lpm(udev); | ||
| 4855 | usb_enable_ltm(udev); | ||
| 4776 | return 0; | 4856 | return 0; |
| 4777 | 4857 | ||
| 4778 | re_enumerate: | 4858 | re_enumerate: |
| 4859 | /* LPM state doesn't matter when we're about to destroy the device. */ | ||
| 4779 | hub_port_logical_disconnect(parent_hub, port1); | 4860 | hub_port_logical_disconnect(parent_hub, port1); |
| 4780 | return -ENODEV; | 4861 | return -ENODEV; |
| 4781 | } | 4862 | } |
