diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/driver.c | 31 |
1 files changed, 28 insertions, 3 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index ed1cc8530a93..637b2bea5563 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -230,6 +230,13 @@ static int usb_probe_interface(struct device *dev) | |||
230 | */ | 230 | */ |
231 | intf->pm_usage_cnt = !(driver->supports_autosuspend); | 231 | intf->pm_usage_cnt = !(driver->supports_autosuspend); |
232 | 232 | ||
233 | /* Carry out a deferred switch to altsetting 0 */ | ||
234 | if (intf->needs_altsetting0) { | ||
235 | usb_set_interface(udev, intf->altsetting[0]. | ||
236 | desc.bInterfaceNumber, 0); | ||
237 | intf->needs_altsetting0 = 0; | ||
238 | } | ||
239 | |||
233 | error = driver->probe(intf, id); | 240 | error = driver->probe(intf, id); |
234 | if (error) { | 241 | if (error) { |
235 | mark_quiesced(intf); | 242 | mark_quiesced(intf); |
@@ -266,8 +273,17 @@ static int usb_unbind_interface(struct device *dev) | |||
266 | 273 | ||
267 | driver->disconnect(intf); | 274 | driver->disconnect(intf); |
268 | 275 | ||
269 | /* reset other interface state */ | 276 | /* Reset other interface state. |
270 | usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0); | 277 | * We cannot do a Set-Interface if the device is suspended or |
278 | * if it is prepared for a system sleep (since installing a new | ||
279 | * altsetting means creating new endpoint device entries). | ||
280 | * When either of these happens, defer the Set-Interface. | ||
281 | */ | ||
282 | if (!error && intf->dev.power.status == DPM_ON) | ||
283 | usb_set_interface(udev, intf->altsetting[0]. | ||
284 | desc.bInterfaceNumber, 0); | ||
285 | else | ||
286 | intf->needs_altsetting0 = 1; | ||
271 | usb_set_intfdata(intf, NULL); | 287 | usb_set_intfdata(intf, NULL); |
272 | 288 | ||
273 | intf->condition = USB_INTERFACE_UNBOUND; | 289 | intf->condition = USB_INTERFACE_UNBOUND; |
@@ -975,8 +991,17 @@ static int usb_resume_interface(struct usb_device *udev, | |||
975 | goto done; | 991 | goto done; |
976 | 992 | ||
977 | /* Can't resume it if it doesn't have a driver. */ | 993 | /* Can't resume it if it doesn't have a driver. */ |
978 | if (intf->condition == USB_INTERFACE_UNBOUND) | 994 | if (intf->condition == USB_INTERFACE_UNBOUND) { |
995 | |||
996 | /* Carry out a deferred switch to altsetting 0 */ | ||
997 | if (intf->needs_altsetting0 && | ||
998 | intf->dev.power.status == DPM_ON) { | ||
999 | usb_set_interface(udev, intf->altsetting[0]. | ||
1000 | desc.bInterfaceNumber, 0); | ||
1001 | intf->needs_altsetting0 = 0; | ||
1002 | } | ||
979 | goto done; | 1003 | goto done; |
1004 | } | ||
980 | 1005 | ||
981 | /* Don't resume if the interface is marked for rebinding */ | 1006 | /* Don't resume if the interface is marked for rebinding */ |
982 | if (intf->needs_binding) | 1007 | if (intf->needs_binding) |