summaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorOliver Neukum <oliver@neukum.org>2009-08-27 16:46:56 +0200
committerGreg Kroah-Hartman <gregkh@suse.de>2009-09-23 06:46:39 -0700
commit1e5ea5e32043094d96ca1e501110c1fbb631f693 (patch)
tree2bbf4930d45221889d100ac03f346e041aebfc2f /drivers/usb
parent01c6460f968d7b57fc6f98adb587952628c6e099 (diff)
downloadkernel-crypto-1e5ea5e32043094d96ca1e501110c1fbb631f693.tar.gz
kernel-crypto-1e5ea5e32043094d96ca1e501110c1fbb631f693.tar.xz
kernel-crypto-1e5ea5e32043094d96ca1e501110c1fbb631f693.zip
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.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 1c976c141f3..4f864472c5c 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)
/* Carry out a deferred switch to altsetting 0 */
if (intf->needs_altsetting0) {
- usb_set_interface(udev, intf->altsetting[0].
+ error = usb_set_interface(udev, intf->altsetting[0].
desc.bInterfaceNumber, 0);
+ if (error < 0)
+ goto err;
+
intf->needs_altsetting0 = 0;
}
error = driver->probe(intf, id);
- if (error) {
- mark_quiesced(intf);
- intf->needs_remote_wakeup = 0;
- intf->condition = USB_INTERFACE_UNBOUND;
- usb_cancel_queued_reset(intf);
- } else
- intf->condition = USB_INTERFACE_BOUND;
+ if (error)
+ goto err;
+ intf->condition = USB_INTERFACE_BOUND;
usb_autosuspend_device(udev);
}
return error;
+
+err:
+ mark_quiesced(intf);
+ intf->needs_remote_wakeup = 0;
+ intf->condition = USB_INTERFACE_UNBOUND;
+ usb_cancel_queued_reset(intf);
+ usb_autosuspend_device(udev);
+ return error;
}
/* called from driver core with dev locked */
@@ -265,7 +272,7 @@ static int usb_unbind_interface(struct device *dev)
struct usb_driver *driver = to_usb_driver(dev->driver);
struct usb_interface *intf = to_usb_interface(dev);
struct usb_device *udev;
- int error;
+ int error, r;
intf->condition = USB_INTERFACE_UNBINDING;
@@ -293,11 +300,14 @@ static int usb_unbind_interface(struct device *dev)
* Just re-enable it without affecting the endpoint toggles.
*/
usb_enable_interface(udev, intf, false);
- } else if (!error && intf->dev.power.status == DPM_ON)
- usb_set_interface(udev, intf->altsetting[0].
+ } else if (!error && intf->dev.power.status == DPM_ON) {
+ r = usb_set_interface(udev, intf->altsetting[0].
desc.bInterfaceNumber, 0);
- else
+ if (r < 0)
+ intf->needs_altsetting0 = 1;
+ } else {
intf->needs_altsetting0 = 1;
+ }
usb_set_intfdata(intf, NULL);
intf->condition = USB_INTERFACE_UNBOUND;