diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-02-08 15:03:11 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-02-08 15:03:11 -0500 |
commit | ceb675a9e25c0c11f76f8e72a862caf08d3934d3 (patch) | |
tree | 6c79ad3468e7923f5da9f9ccd6678e0e4e3cd874 /drivers/usb/core | |
parent | 9662ced3527f5994e83957cf40765ed126abe97f (diff) | |
parent | 200e0d994d9d1919b28c87f1a5fb99a8e13b8a0f (diff) |
Merge usb-linus branch into usb-next
This pulls in a bunch of fixes that are in Linus's tree because we need them
here for testing and development.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/hcd.c | 44 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 70 |
2 files changed, 96 insertions, 18 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 2459896d040a..99b34a30354f 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <asm/unaligned.h> | 39 | #include <asm/unaligned.h> |
40 | #include <linux/platform_device.h> | 40 | #include <linux/platform_device.h> |
41 | #include <linux/workqueue.h> | 41 | #include <linux/workqueue.h> |
42 | #include <linux/pm_runtime.h> | ||
42 | 43 | ||
43 | #include <linux/usb.h> | 44 | #include <linux/usb.h> |
44 | #include <linux/usb/hcd.h> | 45 | #include <linux/usb/hcd.h> |
@@ -1029,6 +1030,49 @@ static int register_root_hub(struct usb_hcd *hcd) | |||
1029 | return retval; | 1030 | return retval; |
1030 | } | 1031 | } |
1031 | 1032 | ||
1033 | /* | ||
1034 | * usb_hcd_start_port_resume - a root-hub port is sending a resume signal | ||
1035 | * @bus: the bus which the root hub belongs to | ||
1036 | * @portnum: the port which is being resumed | ||
1037 | * | ||
1038 | * HCDs should call this function when they know that a resume signal is | ||
1039 | * being sent to a root-hub port. The root hub will be prevented from | ||
1040 | * going into autosuspend until usb_hcd_end_port_resume() is called. | ||
1041 | * | ||
1042 | * The bus's private lock must be held by the caller. | ||
1043 | */ | ||
1044 | void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum) | ||
1045 | { | ||
1046 | unsigned bit = 1 << portnum; | ||
1047 | |||
1048 | if (!(bus->resuming_ports & bit)) { | ||
1049 | bus->resuming_ports |= bit; | ||
1050 | pm_runtime_get_noresume(&bus->root_hub->dev); | ||
1051 | } | ||
1052 | } | ||
1053 | EXPORT_SYMBOL_GPL(usb_hcd_start_port_resume); | ||
1054 | |||
1055 | /* | ||
1056 | * usb_hcd_end_port_resume - a root-hub port has stopped sending a resume signal | ||
1057 | * @bus: the bus which the root hub belongs to | ||
1058 | * @portnum: the port which is being resumed | ||
1059 | * | ||
1060 | * HCDs should call this function when they know that a resume signal has | ||
1061 | * stopped being sent to a root-hub port. The root hub will be allowed to | ||
1062 | * autosuspend again. | ||
1063 | * | ||
1064 | * The bus's private lock must be held by the caller. | ||
1065 | */ | ||
1066 | void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum) | ||
1067 | { | ||
1068 | unsigned bit = 1 << portnum; | ||
1069 | |||
1070 | if (bus->resuming_ports & bit) { | ||
1071 | bus->resuming_ports &= ~bit; | ||
1072 | pm_runtime_put_noidle(&bus->root_hub->dev); | ||
1073 | } | ||
1074 | } | ||
1075 | EXPORT_SYMBOL_GPL(usb_hcd_end_port_resume); | ||
1032 | 1076 | ||
1033 | /*-------------------------------------------------------------------------*/ | 1077 | /*-------------------------------------------------------------------------*/ |
1034 | 1078 | ||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0883364e7347..1775ad471edd 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -2822,6 +2822,23 @@ void usb_enable_ltm(struct usb_device *udev) | |||
2822 | EXPORT_SYMBOL_GPL(usb_enable_ltm); | 2822 | EXPORT_SYMBOL_GPL(usb_enable_ltm); |
2823 | 2823 | ||
2824 | #ifdef CONFIG_USB_SUSPEND | 2824 | #ifdef CONFIG_USB_SUSPEND |
2825 | /* | ||
2826 | * usb_disable_function_remotewakeup - disable usb3.0 | ||
2827 | * device's function remote wakeup | ||
2828 | * @udev: target device | ||
2829 | * | ||
2830 | * Assume there's only one function on the USB 3.0 | ||
2831 | * device and disable remote wake for the first | ||
2832 | * interface. FIXME if the interface association | ||
2833 | * descriptor shows there's more than one function. | ||
2834 | */ | ||
2835 | static int usb_disable_function_remotewakeup(struct usb_device *udev) | ||
2836 | { | ||
2837 | return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
2838 | USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, | ||
2839 | USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, | ||
2840 | USB_CTRL_SET_TIMEOUT); | ||
2841 | } | ||
2825 | 2842 | ||
2826 | /* | 2843 | /* |
2827 | * usb_port_suspend - suspend a usb device's upstream port | 2844 | * usb_port_suspend - suspend a usb device's upstream port |
@@ -2939,12 +2956,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2939 | dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", | 2956 | dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", |
2940 | port1, status); | 2957 | port1, status); |
2941 | /* paranoia: "should not happen" */ | 2958 | /* paranoia: "should not happen" */ |
2942 | if (udev->do_remote_wakeup) | 2959 | if (udev->do_remote_wakeup) { |
2943 | (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 2960 | if (!hub_is_superspeed(hub->hdev)) { |
2944 | USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, | 2961 | (void) usb_control_msg(udev, |
2945 | USB_DEVICE_REMOTE_WAKEUP, 0, | 2962 | usb_sndctrlpipe(udev, 0), |
2946 | NULL, 0, | 2963 | USB_REQ_CLEAR_FEATURE, |
2947 | USB_CTRL_SET_TIMEOUT); | 2964 | USB_RECIP_DEVICE, |
2965 | USB_DEVICE_REMOTE_WAKEUP, 0, | ||
2966 | NULL, 0, | ||
2967 | USB_CTRL_SET_TIMEOUT); | ||
2968 | } else | ||
2969 | (void) usb_disable_function_remotewakeup(udev); | ||
2970 | |||
2971 | } | ||
2948 | 2972 | ||
2949 | /* Try to enable USB2 hardware LPM again */ | 2973 | /* Try to enable USB2 hardware LPM again */ |
2950 | if (udev->usb2_hw_lpm_capable == 1) | 2974 | if (udev->usb2_hw_lpm_capable == 1) |
@@ -3051,20 +3075,30 @@ static int finish_port_resume(struct usb_device *udev) | |||
3051 | * udev->reset_resume | 3075 | * udev->reset_resume |
3052 | */ | 3076 | */ |
3053 | } else if (udev->actconfig && !udev->reset_resume) { | 3077 | } else if (udev->actconfig && !udev->reset_resume) { |
3054 | le16_to_cpus(&devstatus); | 3078 | if (!hub_is_superspeed(udev->parent)) { |
3055 | if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { | 3079 | le16_to_cpus(&devstatus); |
3056 | status = usb_control_msg(udev, | 3080 | if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) |
3057 | usb_sndctrlpipe(udev, 0), | 3081 | status = usb_control_msg(udev, |
3058 | USB_REQ_CLEAR_FEATURE, | 3082 | usb_sndctrlpipe(udev, 0), |
3083 | USB_REQ_CLEAR_FEATURE, | ||
3059 | USB_RECIP_DEVICE, | 3084 | USB_RECIP_DEVICE, |
3060 | USB_DEVICE_REMOTE_WAKEUP, 0, | 3085 | USB_DEVICE_REMOTE_WAKEUP, 0, |
3061 | NULL, 0, | 3086 | NULL, 0, |
3062 | USB_CTRL_SET_TIMEOUT); | 3087 | USB_CTRL_SET_TIMEOUT); |
3063 | if (status) | 3088 | } else { |
3064 | dev_dbg(&udev->dev, | 3089 | status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, |
3065 | "disable remote wakeup, status %d\n", | 3090 | &devstatus); |
3066 | status); | 3091 | le16_to_cpus(&devstatus); |
3092 | if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP | ||
3093 | | USB_INTRF_STAT_FUNC_RW)) | ||
3094 | status = | ||
3095 | usb_disable_function_remotewakeup(udev); | ||
3067 | } | 3096 | } |
3097 | |||
3098 | if (status) | ||
3099 | dev_dbg(&udev->dev, | ||
3100 | "disable remote wakeup, status %d\n", | ||
3101 | status); | ||
3068 | status = 0; | 3102 | status = 0; |
3069 | } | 3103 | } |
3070 | return status; | 3104 | return status; |