aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/hub.c')
-rw-r--r--drivers/usb/core/hub.c44
1 files changed, 33 insertions, 11 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index bdeadc112d29..ddbf32d599cb 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -124,6 +124,10 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev)
124 124
125int usb_device_supports_lpm(struct usb_device *udev) 125int usb_device_supports_lpm(struct usb_device *udev)
126{ 126{
127 /* Some devices have trouble with LPM */
128 if (udev->quirks & USB_QUIRK_NO_LPM)
129 return 0;
130
127 /* USB 2.1 (and greater) devices indicate LPM support through 131 /* USB 2.1 (and greater) devices indicate LPM support through
128 * their USB 2.0 Extended Capabilities BOS descriptor. 132 * their USB 2.0 Extended Capabilities BOS descriptor.
129 */ 133 */
@@ -1031,10 +1035,20 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
1031 unsigned delay; 1035 unsigned delay;
1032 1036
1033 /* Continue a partial initialization */ 1037 /* Continue a partial initialization */
1034 if (type == HUB_INIT2) 1038 if (type == HUB_INIT2 || type == HUB_INIT3) {
1035 goto init2; 1039 device_lock(hub->intfdev);
1036 if (type == HUB_INIT3) 1040
1041 /* Was the hub disconnected while we were waiting? */
1042 if (hub->disconnected) {
1043 device_unlock(hub->intfdev);
1044 kref_put(&hub->kref, hub_release);
1045 return;
1046 }
1047 if (type == HUB_INIT2)
1048 goto init2;
1037 goto init3; 1049 goto init3;
1050 }
1051 kref_get(&hub->kref);
1038 1052
1039 /* The superspeed hub except for root hub has to use Hub Depth 1053 /* The superspeed hub except for root hub has to use Hub Depth
1040 * value as an offset into the route string to locate the bits 1054 * value as an offset into the route string to locate the bits
@@ -1232,6 +1246,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
1232 queue_delayed_work(system_power_efficient_wq, 1246 queue_delayed_work(system_power_efficient_wq,
1233 &hub->init_work, 1247 &hub->init_work,
1234 msecs_to_jiffies(delay)); 1248 msecs_to_jiffies(delay));
1249 device_unlock(hub->intfdev);
1235 return; /* Continues at init3: below */ 1250 return; /* Continues at init3: below */
1236 } else { 1251 } else {
1237 msleep(delay); 1252 msleep(delay);
@@ -1253,6 +1268,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
1253 /* Allow autosuspend if it was suppressed */ 1268 /* Allow autosuspend if it was suppressed */
1254 if (type <= HUB_INIT3) 1269 if (type <= HUB_INIT3)
1255 usb_autopm_put_interface_async(to_usb_interface(hub->intfdev)); 1270 usb_autopm_put_interface_async(to_usb_interface(hub->intfdev));
1271
1272 if (type == HUB_INIT2 || type == HUB_INIT3)
1273 device_unlock(hub->intfdev);
1274
1275 kref_put(&hub->kref, hub_release);
1256} 1276}
1257 1277
1258/* Implement the continuations for the delays above */ 1278/* Implement the continuations for the delays above */
@@ -4512,6 +4532,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
4512 goto fail; 4532 goto fail;
4513 } 4533 }
4514 4534
4535 usb_detect_quirks(udev);
4536
4515 if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) { 4537 if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) {
4516 retval = usb_get_bos_descriptor(udev); 4538 retval = usb_get_bos_descriptor(udev);
4517 if (!retval) { 4539 if (!retval) {
@@ -4710,7 +4732,6 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
4710 if (status < 0) 4732 if (status < 0)
4711 goto loop; 4733 goto loop;
4712 4734
4713 usb_detect_quirks(udev);
4714 if (udev->quirks & USB_QUIRK_DELAY_INIT) 4735 if (udev->quirks & USB_QUIRK_DELAY_INIT)
4715 msleep(1000); 4736 msleep(1000);
4716 4737
@@ -5326,9 +5347,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
5326 if (udev->usb2_hw_lpm_enabled == 1) 5347 if (udev->usb2_hw_lpm_enabled == 1)
5327 usb_set_usb2_hardware_lpm(udev, 0); 5348 usb_set_usb2_hardware_lpm(udev, 0);
5328 5349
5329 bos = udev->bos;
5330 udev->bos = NULL;
5331
5332 /* Disable LPM and LTM while we reset the device and reinstall the alt 5350 /* Disable LPM and LTM while we reset the device and reinstall the alt
5333 * settings. Device-initiated LPM settings, and system exit latency 5351 * settings. Device-initiated LPM settings, and system exit latency
5334 * settings are cleared when the device is reset, so we have to set 5352 * settings are cleared when the device is reset, so we have to set
@@ -5337,15 +5355,18 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
5337 ret = usb_unlocked_disable_lpm(udev); 5355 ret = usb_unlocked_disable_lpm(udev);
5338 if (ret) { 5356 if (ret) {
5339 dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__); 5357 dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__);
5340 goto re_enumerate; 5358 goto re_enumerate_no_bos;
5341 } 5359 }
5342 ret = usb_disable_ltm(udev); 5360 ret = usb_disable_ltm(udev);
5343 if (ret) { 5361 if (ret) {
5344 dev_err(&udev->dev, "%s Failed to disable LTM\n.", 5362 dev_err(&udev->dev, "%s Failed to disable LTM\n.",
5345 __func__); 5363 __func__);
5346 goto re_enumerate; 5364 goto re_enumerate_no_bos;
5347 } 5365 }
5348 5366
5367 bos = udev->bos;
5368 udev->bos = NULL;
5369
5349 for (i = 0; i < SET_CONFIG_TRIES; ++i) { 5370 for (i = 0; i < SET_CONFIG_TRIES; ++i) {
5350 5371
5351 /* ep0 maxpacket size may change; let the HCD know about it. 5372 /* ep0 maxpacket size may change; let the HCD know about it.
@@ -5442,10 +5463,11 @@ done:
5442 return 0; 5463 return 0;
5443 5464
5444re_enumerate: 5465re_enumerate:
5445 /* LPM state doesn't matter when we're about to destroy the device. */
5446 hub_port_logical_disconnect(parent_hub, port1);
5447 usb_release_bos_descriptor(udev); 5466 usb_release_bos_descriptor(udev);
5448 udev->bos = bos; 5467 udev->bos = bos;
5468re_enumerate_no_bos:
5469 /* LPM state doesn't matter when we're about to destroy the device. */
5470 hub_port_logical_disconnect(parent_hub, port1);
5449 return -ENODEV; 5471 return -ENODEV;
5450} 5472}
5451 5473