diff options
| author | Jan-Marek Glogowski <glogow@fbihome.de> | 2019-02-01 07:52:31 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-02-08 04:21:22 -0500 |
| commit | 4fdc1790e6a9ef22399c6bc6e63b80f4609f3b7e (patch) | |
| tree | a21ea27da696a856a796c1766309b5ae0a139e5e /drivers/usb/core | |
| parent | 68f1ec8ea14f5dcb91df6258e482afcb41610b2e (diff) | |
usb: handle warm-reset port requests on hub resume
On plug-in of my USB-C device, its USB_SS_PORT_LS_SS_INACTIVE
link state bit is set. Greping all the kernel for this bit shows
that the port status requests a warm-reset this way.
This just happens, if its the only device on the root hub, the hub
therefore resumes and the HCDs status_urb isn't yet available.
If a warm-reset request is detected, this sets the hubs event_bits,
which will prevent any auto-suspend and allows the hubs workqueue
to warm-reset the port later in port_event.
Signed-off-by: Jan-Marek Glogowski <glogow@fbihome.de>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/core')
| -rw-r--r-- | drivers/usb/core/hub.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index bb0830c72286..8d4631c81b9f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -108,6 +108,8 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); | |||
| 108 | static void hub_release(struct kref *kref); | 108 | static void hub_release(struct kref *kref); |
| 109 | static int usb_reset_and_verify_device(struct usb_device *udev); | 109 | static int usb_reset_and_verify_device(struct usb_device *udev); |
| 110 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state); | 110 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state); |
| 111 | static bool hub_port_warm_reset_required(struct usb_hub *hub, int port1, | ||
| 112 | u16 portstatus); | ||
| 111 | 113 | ||
| 112 | static inline char *portspeed(struct usb_hub *hub, int portstatus) | 114 | static inline char *portspeed(struct usb_hub *hub, int portstatus) |
| 113 | { | 115 | { |
| @@ -1137,6 +1139,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) | |||
| 1137 | USB_PORT_FEAT_ENABLE); | 1139 | USB_PORT_FEAT_ENABLE); |
| 1138 | } | 1140 | } |
| 1139 | 1141 | ||
| 1142 | /* Make sure a warm-reset request is handled by port_event */ | ||
| 1143 | if (type == HUB_RESUME && | ||
| 1144 | hub_port_warm_reset_required(hub, port1, portstatus)) | ||
| 1145 | set_bit(port1, hub->event_bits); | ||
| 1146 | |||
| 1140 | /* | 1147 | /* |
| 1141 | * Add debounce if USB3 link is in polling/link training state. | 1148 | * Add debounce if USB3 link is in polling/link training state. |
| 1142 | * Link will automatically transition to Enabled state after | 1149 | * Link will automatically transition to Enabled state after |
