diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r-- | drivers/usb/core/hub.c | 48 |
1 files changed, 40 insertions, 8 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 4191db32f12c..4a8a1d68002c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -668,6 +668,15 @@ resubmit: | |||
668 | static inline int | 668 | static inline int |
669 | hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) | 669 | hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) |
670 | { | 670 | { |
671 | /* Need to clear both directions for control ep */ | ||
672 | if (((devinfo >> 11) & USB_ENDPOINT_XFERTYPE_MASK) == | ||
673 | USB_ENDPOINT_XFER_CONTROL) { | ||
674 | int status = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), | ||
675 | HUB_CLEAR_TT_BUFFER, USB_RT_PORT, | ||
676 | devinfo ^ 0x8000, tt, NULL, 0, 1000); | ||
677 | if (status) | ||
678 | return status; | ||
679 | } | ||
671 | return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), | 680 | return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), |
672 | HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo, | 681 | HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo, |
673 | tt, NULL, 0, 1000); | 682 | tt, NULL, 0, 1000); |
@@ -2848,6 +2857,15 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev) | |||
2848 | USB_CTRL_SET_TIMEOUT); | 2857 | USB_CTRL_SET_TIMEOUT); |
2849 | } | 2858 | } |
2850 | 2859 | ||
2860 | /* Count of wakeup-enabled devices at or below udev */ | ||
2861 | static unsigned wakeup_enabled_descendants(struct usb_device *udev) | ||
2862 | { | ||
2863 | struct usb_hub *hub = usb_hub_to_struct_hub(udev); | ||
2864 | |||
2865 | return udev->do_remote_wakeup + | ||
2866 | (hub ? hub->wakeup_enabled_descendants : 0); | ||
2867 | } | ||
2868 | |||
2851 | /* | 2869 | /* |
2852 | * usb_port_suspend - suspend a usb device's upstream port | 2870 | * usb_port_suspend - suspend a usb device's upstream port |
2853 | * @udev: device that's no longer in active use, not a root hub | 2871 | * @udev: device that's no longer in active use, not a root hub |
@@ -2888,8 +2906,8 @@ static int usb_disable_function_remotewakeup(struct usb_device *udev) | |||
2888 | * Linux (2.6) currently has NO mechanisms to initiate that: no khubd | 2906 | * Linux (2.6) currently has NO mechanisms to initiate that: no khubd |
2889 | * timer, no SRP, no requests through sysfs. | 2907 | * timer, no SRP, no requests through sysfs. |
2890 | * | 2908 | * |
2891 | * If Runtime PM isn't enabled or used, non-SuperSpeed devices really get | 2909 | * If Runtime PM isn't enabled or used, non-SuperSpeed devices may not get |
2892 | * suspended only when their bus goes into global suspend (i.e., the root | 2910 | * suspended until their bus goes into global suspend (i.e., the root |
2893 | * hub is suspended). Nevertheless, we change @udev->state to | 2911 | * hub is suspended). Nevertheless, we change @udev->state to |
2894 | * USB_STATE_SUSPENDED as this is the device's "logical" state. The actual | 2912 | * USB_STATE_SUSPENDED as this is the device's "logical" state. The actual |
2895 | * upstream port setting is stored in @udev->port_is_suspended. | 2913 | * upstream port setting is stored in @udev->port_is_suspended. |
@@ -2960,15 +2978,21 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2960 | /* see 7.1.7.6 */ | 2978 | /* see 7.1.7.6 */ |
2961 | if (hub_is_superspeed(hub->hdev)) | 2979 | if (hub_is_superspeed(hub->hdev)) |
2962 | status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3); | 2980 | status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3); |
2963 | else if (PMSG_IS_AUTO(msg)) | 2981 | |
2964 | status = set_port_feature(hub->hdev, port1, | ||
2965 | USB_PORT_FEAT_SUSPEND); | ||
2966 | /* | 2982 | /* |
2967 | * For system suspend, we do not need to enable the suspend feature | 2983 | * For system suspend, we do not need to enable the suspend feature |
2968 | * on individual USB-2 ports. The devices will automatically go | 2984 | * on individual USB-2 ports. The devices will automatically go |
2969 | * into suspend a few ms after the root hub stops sending packets. | 2985 | * into suspend a few ms after the root hub stops sending packets. |
2970 | * The USB 2.0 spec calls this "global suspend". | 2986 | * The USB 2.0 spec calls this "global suspend". |
2987 | * | ||
2988 | * However, many USB hubs have a bug: They don't relay wakeup requests | ||
2989 | * from a downstream port if the port's suspend feature isn't on. | ||
2990 | * Therefore we will turn on the suspend feature if udev or any of its | ||
2991 | * descendants is enabled for remote wakeup. | ||
2971 | */ | 2992 | */ |
2993 | else if (PMSG_IS_AUTO(msg) || wakeup_enabled_descendants(udev) > 0) | ||
2994 | status = set_port_feature(hub->hdev, port1, | ||
2995 | USB_PORT_FEAT_SUSPEND); | ||
2972 | else { | 2996 | else { |
2973 | really_suspend = false; | 2997 | really_suspend = false; |
2974 | status = 0; | 2998 | status = 0; |
@@ -3003,15 +3027,16 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
3003 | if (!PMSG_IS_AUTO(msg)) | 3027 | if (!PMSG_IS_AUTO(msg)) |
3004 | status = 0; | 3028 | status = 0; |
3005 | } else { | 3029 | } else { |
3006 | /* device has up to 10 msec to fully suspend */ | ||
3007 | dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n", | 3030 | dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n", |
3008 | (PMSG_IS_AUTO(msg) ? "auto-" : ""), | 3031 | (PMSG_IS_AUTO(msg) ? "auto-" : ""), |
3009 | udev->do_remote_wakeup); | 3032 | udev->do_remote_wakeup); |
3010 | usb_set_device_state(udev, USB_STATE_SUSPENDED); | ||
3011 | if (really_suspend) { | 3033 | if (really_suspend) { |
3012 | udev->port_is_suspended = 1; | 3034 | udev->port_is_suspended = 1; |
3035 | |||
3036 | /* device has up to 10 msec to fully suspend */ | ||
3013 | msleep(10); | 3037 | msleep(10); |
3014 | } | 3038 | } |
3039 | usb_set_device_state(udev, USB_STATE_SUSPENDED); | ||
3015 | } | 3040 | } |
3016 | 3041 | ||
3017 | /* | 3042 | /* |
@@ -3293,7 +3318,11 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
3293 | unsigned port1; | 3318 | unsigned port1; |
3294 | int status; | 3319 | int status; |
3295 | 3320 | ||
3296 | /* Warn if children aren't already suspended */ | 3321 | /* |
3322 | * Warn if children aren't already suspended. | ||
3323 | * Also, add up the number of wakeup-enabled descendants. | ||
3324 | */ | ||
3325 | hub->wakeup_enabled_descendants = 0; | ||
3297 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { | 3326 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { |
3298 | struct usb_device *udev; | 3327 | struct usb_device *udev; |
3299 | 3328 | ||
@@ -3303,6 +3332,9 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
3303 | if (PMSG_IS_AUTO(msg)) | 3332 | if (PMSG_IS_AUTO(msg)) |
3304 | return -EBUSY; | 3333 | return -EBUSY; |
3305 | } | 3334 | } |
3335 | if (udev) | ||
3336 | hub->wakeup_enabled_descendants += | ||
3337 | wakeup_enabled_descendants(udev); | ||
3306 | } | 3338 | } |
3307 | 3339 | ||
3308 | if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) { | 3340 | if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) { |