diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
| -rw-r--r-- | drivers/usb/core/hub.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index cd50d86029e7..be86ae3f4088 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
| @@ -392,7 +392,7 @@ static void hub_irq(struct urb *urb) | |||
| 392 | { | 392 | { |
| 393 | struct usb_hub *hub = urb->context; | 393 | struct usb_hub *hub = urb->context; |
| 394 | int status = urb->status; | 394 | int status = urb->status; |
| 395 | int i; | 395 | unsigned i; |
| 396 | unsigned long bits; | 396 | unsigned long bits; |
| 397 | 397 | ||
| 398 | switch (status) { | 398 | switch (status) { |
| @@ -1305,6 +1305,7 @@ void usb_set_device_state(struct usb_device *udev, | |||
| 1305 | recursively_mark_NOTATTACHED(udev); | 1305 | recursively_mark_NOTATTACHED(udev); |
| 1306 | spin_unlock_irqrestore(&device_state_lock, flags); | 1306 | spin_unlock_irqrestore(&device_state_lock, flags); |
| 1307 | } | 1307 | } |
| 1308 | EXPORT_SYMBOL_GPL(usb_set_device_state); | ||
| 1308 | 1309 | ||
| 1309 | /* | 1310 | /* |
| 1310 | * WUSB devices are simple: they have no hubs behind, so the mapping | 1311 | * WUSB devices are simple: they have no hubs behind, so the mapping |
| @@ -2471,20 +2472,20 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
| 2471 | */ | 2472 | */ |
| 2472 | switch (udev->speed) { | 2473 | switch (udev->speed) { |
| 2473 | case USB_SPEED_VARIABLE: /* fixed at 512 */ | 2474 | case USB_SPEED_VARIABLE: /* fixed at 512 */ |
| 2474 | udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(512); | 2475 | udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); |
| 2475 | break; | 2476 | break; |
| 2476 | case USB_SPEED_HIGH: /* fixed at 64 */ | 2477 | case USB_SPEED_HIGH: /* fixed at 64 */ |
| 2477 | udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); | 2478 | udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); |
| 2478 | break; | 2479 | break; |
| 2479 | case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ | 2480 | case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ |
| 2480 | /* to determine the ep0 maxpacket size, try to read | 2481 | /* to determine the ep0 maxpacket size, try to read |
| 2481 | * the device descriptor to get bMaxPacketSize0 and | 2482 | * the device descriptor to get bMaxPacketSize0 and |
| 2482 | * then correct our initial guess. | 2483 | * then correct our initial guess. |
| 2483 | */ | 2484 | */ |
| 2484 | udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); | 2485 | udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); |
| 2485 | break; | 2486 | break; |
| 2486 | case USB_SPEED_LOW: /* fixed at 8 */ | 2487 | case USB_SPEED_LOW: /* fixed at 8 */ |
| 2487 | udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(8); | 2488 | udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8); |
| 2488 | break; | 2489 | break; |
| 2489 | default: | 2490 | default: |
| 2490 | goto fail; | 2491 | goto fail; |
| @@ -3392,10 +3393,10 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
| 3392 | udev->descriptor = descriptor; /* for disconnect() calls */ | 3393 | udev->descriptor = descriptor; /* for disconnect() calls */ |
| 3393 | goto re_enumerate; | 3394 | goto re_enumerate; |
| 3394 | } | 3395 | } |
| 3395 | 3396 | ||
| 3397 | /* Restore the device's previous configuration */ | ||
| 3396 | if (!udev->actconfig) | 3398 | if (!udev->actconfig) |
| 3397 | goto done; | 3399 | goto done; |
| 3398 | |||
| 3399 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 3400 | ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
| 3400 | USB_REQ_SET_CONFIGURATION, 0, | 3401 | USB_REQ_SET_CONFIGURATION, 0, |
| 3401 | udev->actconfig->desc.bConfigurationValue, 0, | 3402 | udev->actconfig->desc.bConfigurationValue, 0, |
| @@ -3408,16 +3409,25 @@ static int usb_reset_and_verify_device(struct usb_device *udev) | |||
| 3408 | } | 3409 | } |
| 3409 | usb_set_device_state(udev, USB_STATE_CONFIGURED); | 3410 | usb_set_device_state(udev, USB_STATE_CONFIGURED); |
| 3410 | 3411 | ||
| 3412 | /* Put interfaces back into the same altsettings as before. | ||
| 3413 | * Don't bother to send the Set-Interface request for interfaces | ||
| 3414 | * that were already in altsetting 0; besides being unnecessary, | ||
| 3415 | * many devices can't handle it. Instead just reset the host-side | ||
| 3416 | * endpoint state. | ||
| 3417 | */ | ||
| 3411 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { | 3418 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { |
| 3412 | struct usb_interface *intf = udev->actconfig->interface[i]; | 3419 | struct usb_interface *intf = udev->actconfig->interface[i]; |
| 3413 | struct usb_interface_descriptor *desc; | 3420 | struct usb_interface_descriptor *desc; |
| 3414 | 3421 | ||
| 3415 | /* set_interface resets host side toggle even | ||
| 3416 | * for altsetting zero. the interface may have no driver. | ||
| 3417 | */ | ||
| 3418 | desc = &intf->cur_altsetting->desc; | 3422 | desc = &intf->cur_altsetting->desc; |
| 3419 | ret = usb_set_interface(udev, desc->bInterfaceNumber, | 3423 | if (desc->bAlternateSetting == 0) { |
| 3420 | desc->bAlternateSetting); | 3424 | usb_disable_interface(udev, intf, true); |
| 3425 | usb_enable_interface(udev, intf, true); | ||
| 3426 | ret = 0; | ||
| 3427 | } else { | ||
| 3428 | ret = usb_set_interface(udev, desc->bInterfaceNumber, | ||
| 3429 | desc->bAlternateSetting); | ||
| 3430 | } | ||
| 3421 | if (ret < 0) { | 3431 | if (ret < 0) { |
| 3422 | dev_err(&udev->dev, "failed to restore interface %d " | 3432 | dev_err(&udev->dev, "failed to restore interface %d " |
| 3423 | "altsetting %d (error=%d)\n", | 3433 | "altsetting %d (error=%d)\n", |
