diff options
author | James Bottomley <JBottomley@Parallels.com> | 2011-07-23 21:09:03 +0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-23 21:09:03 +0400 |
commit | 87045b033a62777337ae4aa62834876da09b5fb5 (patch) | |
tree | 26aefd28e436668ff906e42b1e0d75c056e33e01 /drivers/usb/core/message.c | |
parent | 0d83ab65ff1b54ce8b6cd172285cf71a38c4cceb (diff) | |
parent | bfe159a51203c15d23cb3158fffdc25ec4b4dda1 (diff) |
Merge branch 'scsi-fixes'
Diffstat (limited to 'drivers/usb/core/message.c')
-rw-r--r-- | drivers/usb/core/message.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 64c7ab4702d..0b5ec234c78 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1147,6 +1147,14 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) * any drivers bound to them (a key side effect) */ if (dev->actconfig) { + /* + * FIXME: In order to avoid self-deadlock involving the + * bandwidth_mutex, we have to mark all the interfaces + * before unregistering any of them. + */ + for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) + dev->actconfig->interface[i]->unregistering = 1; + for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *interface; @@ -1156,7 +1164,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) continue; dev_dbg(&dev->dev, "unregistering interface %s\n", dev_name(&interface->dev)); - interface->unregistering = 1; remove_intf_ep_devs(interface); device_del(&interface->dev); } @@ -1286,6 +1293,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) interface); return -EINVAL; } + if (iface->unregistering) + return -ENODEV; alt = usb_altnum_to_altsetting(iface, alternate); if (!alt) { |