diff options
author | Oliver Neukum <oliver@neukum.org> | 2009-08-27 10:46:56 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-23 09:46:39 -0400 |
commit | 1e5ea5e32043094d96ca1e501110c1fbb631f693 (patch) | |
tree | 2bbf4930d45221889d100ac03f346e041aebfc2f /drivers/usb | |
parent | 01c6460f968d7b57fc6f98adb587952628c6e099 (diff) |
USB: fix missing error check in probing
usb: check for IO errors usb_set_interface can return
if they happen while unbinding a flag is set to retry upon probe
if they happen during probe they are handled as probe errors
Signed-off-by: Oliver Neukum <oliver@neukum.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/driver.c | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 1c976c141f33..4f864472c5c4 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -239,24 +239,31 @@ static int usb_probe_interface(struct device *dev) | |||
239 | 239 | ||
240 | /* Carry out a deferred switch to altsetting 0 */ | 240 | /* Carry out a deferred switch to altsetting 0 */ |
241 | if (intf->needs_altsetting0) { | 241 | if (intf->needs_altsetting0) { |
242 | usb_set_interface(udev, intf->altsetting[0]. | 242 | error = usb_set_interface(udev, intf->altsetting[0]. |
243 | desc.bInterfaceNumber, 0); | 243 | desc.bInterfaceNumber, 0); |
244 | if (error < 0) | ||
245 | goto err; | ||
246 | |||
244 | intf->needs_altsetting0 = 0; | 247 | intf->needs_altsetting0 = 0; |
245 | } | 248 | } |
246 | 249 | ||
247 | error = driver->probe(intf, id); | 250 | error = driver->probe(intf, id); |
248 | if (error) { | 251 | if (error) |
249 | mark_quiesced(intf); | 252 | goto err; |
250 | intf->needs_remote_wakeup = 0; | ||
251 | intf->condition = USB_INTERFACE_UNBOUND; | ||
252 | usb_cancel_queued_reset(intf); | ||
253 | } else | ||
254 | intf->condition = USB_INTERFACE_BOUND; | ||
255 | 253 | ||
254 | intf->condition = USB_INTERFACE_BOUND; | ||
256 | usb_autosuspend_device(udev); | 255 | usb_autosuspend_device(udev); |
257 | } | 256 | } |
258 | 257 | ||
259 | return error; | 258 | return error; |
259 | |||
260 | err: | ||
261 | mark_quiesced(intf); | ||
262 | intf->needs_remote_wakeup = 0; | ||
263 | intf->condition = USB_INTERFACE_UNBOUND; | ||
264 | usb_cancel_queued_reset(intf); | ||
265 | usb_autosuspend_device(udev); | ||
266 | return error; | ||
260 | } | 267 | } |
261 | 268 | ||
262 | /* called from driver core with dev locked */ | 269 | /* called from driver core with dev locked */ |
@@ -265,7 +272,7 @@ static int usb_unbind_interface(struct device *dev) | |||
265 | struct usb_driver *driver = to_usb_driver(dev->driver); | 272 | struct usb_driver *driver = to_usb_driver(dev->driver); |
266 | struct usb_interface *intf = to_usb_interface(dev); | 273 | struct usb_interface *intf = to_usb_interface(dev); |
267 | struct usb_device *udev; | 274 | struct usb_device *udev; |
268 | int error; | 275 | int error, r; |
269 | 276 | ||
270 | intf->condition = USB_INTERFACE_UNBINDING; | 277 | intf->condition = USB_INTERFACE_UNBINDING; |
271 | 278 | ||
@@ -293,11 +300,14 @@ static int usb_unbind_interface(struct device *dev) | |||
293 | * Just re-enable it without affecting the endpoint toggles. | 300 | * Just re-enable it without affecting the endpoint toggles. |
294 | */ | 301 | */ |
295 | usb_enable_interface(udev, intf, false); | 302 | usb_enable_interface(udev, intf, false); |
296 | } else if (!error && intf->dev.power.status == DPM_ON) | 303 | } else if (!error && intf->dev.power.status == DPM_ON) { |
297 | usb_set_interface(udev, intf->altsetting[0]. | 304 | r = usb_set_interface(udev, intf->altsetting[0]. |
298 | desc.bInterfaceNumber, 0); | 305 | desc.bInterfaceNumber, 0); |
299 | else | 306 | if (r < 0) |
307 | intf->needs_altsetting0 = 1; | ||
308 | } else { | ||
300 | intf->needs_altsetting0 = 1; | 309 | intf->needs_altsetting0 = 1; |
310 | } | ||
301 | usb_set_intfdata(intf, NULL); | 311 | usb_set_intfdata(intf, NULL); |
302 | 312 | ||
303 | intf->condition = USB_INTERFACE_UNBOUND; | 313 | intf->condition = USB_INTERFACE_UNBOUND; |