diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r-- | drivers/usb/core/hub.c | 70 |
1 files changed, 52 insertions, 18 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 957ed2c41482..cbf7168e3ce7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -2838,6 +2838,23 @@ void usb_enable_ltm(struct usb_device *udev) | |||
2838 | EXPORT_SYMBOL_GPL(usb_enable_ltm); | 2838 | EXPORT_SYMBOL_GPL(usb_enable_ltm); |
2839 | 2839 | ||
2840 | #ifdef CONFIG_USB_SUSPEND | 2840 | #ifdef CONFIG_USB_SUSPEND |
2841 | /* | ||
2842 | * usb_disable_function_remotewakeup - disable usb3.0 | ||
2843 | * device's function remote wakeup | ||
2844 | * @udev: target device | ||
2845 | * | ||
2846 | * Assume there's only one function on the USB 3.0 | ||
2847 | * device and disable remote wake for the first | ||
2848 | * interface. FIXME if the interface association | ||
2849 | * descriptor shows there's more than one function. | ||
2850 | */ | ||
2851 | static int usb_disable_function_remotewakeup(struct usb_device *udev) | ||
2852 | { | ||
2853 | return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
2854 | USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, | ||
2855 | USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, | ||
2856 | USB_CTRL_SET_TIMEOUT); | ||
2857 | } | ||
2841 | 2858 | ||
2842 | /* | 2859 | /* |
2843 | * usb_port_suspend - suspend a usb device's upstream port | 2860 | * usb_port_suspend - suspend a usb device's upstream port |
@@ -2955,12 +2972,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2955 | dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", | 2972 | dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", |
2956 | port1, status); | 2973 | port1, status); |
2957 | /* paranoia: "should not happen" */ | 2974 | /* paranoia: "should not happen" */ |
2958 | if (udev->do_remote_wakeup) | 2975 | if (udev->do_remote_wakeup) { |
2959 | (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 2976 | if (!hub_is_superspeed(hub->hdev)) { |
2960 | USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, | 2977 | (void) usb_control_msg(udev, |
2961 | USB_DEVICE_REMOTE_WAKEUP, 0, | 2978 | usb_sndctrlpipe(udev, 0), |
2962 | NULL, 0, | 2979 | USB_REQ_CLEAR_FEATURE, |
2963 | USB_CTRL_SET_TIMEOUT); | 2980 | USB_RECIP_DEVICE, |
2981 | USB_DEVICE_REMOTE_WAKEUP, 0, | ||
2982 | NULL, 0, | ||
2983 | USB_CTRL_SET_TIMEOUT); | ||
2984 | } else | ||
2985 | (void) usb_disable_function_remotewakeup(udev); | ||
2986 | |||
2987 | } | ||
2964 | 2988 | ||
2965 | /* Try to enable USB2 hardware LPM again */ | 2989 | /* Try to enable USB2 hardware LPM again */ |
2966 | if (udev->usb2_hw_lpm_capable == 1) | 2990 | if (udev->usb2_hw_lpm_capable == 1) |
@@ -3052,20 +3076,30 @@ static int finish_port_resume(struct usb_device *udev) | |||
3052 | * udev->reset_resume | 3076 | * udev->reset_resume |
3053 | */ | 3077 | */ |
3054 | } else if (udev->actconfig && !udev->reset_resume) { | 3078 | } else if (udev->actconfig && !udev->reset_resume) { |
3055 | le16_to_cpus(&devstatus); | 3079 | if (!hub_is_superspeed(udev->parent)) { |
3056 | if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { | 3080 | le16_to_cpus(&devstatus); |
3057 | status = usb_control_msg(udev, | 3081 | if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) |
3058 | usb_sndctrlpipe(udev, 0), | 3082 | status = usb_control_msg(udev, |
3059 | USB_REQ_CLEAR_FEATURE, | 3083 | usb_sndctrlpipe(udev, 0), |
3084 | USB_REQ_CLEAR_FEATURE, | ||
3060 | USB_RECIP_DEVICE, | 3085 | USB_RECIP_DEVICE, |
3061 | USB_DEVICE_REMOTE_WAKEUP, 0, | 3086 | USB_DEVICE_REMOTE_WAKEUP, 0, |
3062 | NULL, 0, | 3087 | NULL, 0, |
3063 | USB_CTRL_SET_TIMEOUT); | 3088 | USB_CTRL_SET_TIMEOUT); |
3064 | if (status) | 3089 | } else { |
3065 | dev_dbg(&udev->dev, | 3090 | status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, |
3066 | "disable remote wakeup, status %d\n", | 3091 | &devstatus); |
3067 | status); | 3092 | le16_to_cpus(&devstatus); |
3093 | if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP | ||
3094 | | USB_INTRF_STAT_FUNC_RW)) | ||
3095 | status = | ||
3096 | usb_disable_function_remotewakeup(udev); | ||
3068 | } | 3097 | } |
3098 | |||
3099 | if (status) | ||
3100 | dev_dbg(&udev->dev, | ||
3101 | "disable remote wakeup, status %d\n", | ||
3102 | status); | ||
3069 | status = 0; | 3103 | status = 0; |
3070 | } | 3104 | } |
3071 | return status; | 3105 | return status; |