diff options
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r-- | drivers/usb/core/driver.c | 56 |
1 files changed, 26 insertions, 30 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index d0a21a5f8201..69e5773abfce 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -154,16 +154,11 @@ static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *in | |||
154 | static int usb_probe_device(struct device *dev) | 154 | static int usb_probe_device(struct device *dev) |
155 | { | 155 | { |
156 | struct usb_device_driver *udriver = to_usb_device_driver(dev->driver); | 156 | struct usb_device_driver *udriver = to_usb_device_driver(dev->driver); |
157 | struct usb_device *udev; | 157 | struct usb_device *udev = to_usb_device(dev); |
158 | int error = -ENODEV; | 158 | int error = -ENODEV; |
159 | 159 | ||
160 | dev_dbg(dev, "%s\n", __func__); | 160 | dev_dbg(dev, "%s\n", __func__); |
161 | 161 | ||
162 | if (!is_usb_device(dev)) /* Sanity check */ | ||
163 | return error; | ||
164 | |||
165 | udev = to_usb_device(dev); | ||
166 | |||
167 | /* TODO: Add real matching code */ | 162 | /* TODO: Add real matching code */ |
168 | 163 | ||
169 | /* The device should always appear to be in use | 164 | /* The device should always appear to be in use |
@@ -203,18 +198,13 @@ static void usb_cancel_queued_reset(struct usb_interface *iface) | |||
203 | static int usb_probe_interface(struct device *dev) | 198 | static int usb_probe_interface(struct device *dev) |
204 | { | 199 | { |
205 | struct usb_driver *driver = to_usb_driver(dev->driver); | 200 | struct usb_driver *driver = to_usb_driver(dev->driver); |
206 | struct usb_interface *intf; | 201 | struct usb_interface *intf = to_usb_interface(dev); |
207 | struct usb_device *udev; | 202 | struct usb_device *udev = interface_to_usbdev(intf); |
208 | const struct usb_device_id *id; | 203 | const struct usb_device_id *id; |
209 | int error = -ENODEV; | 204 | int error = -ENODEV; |
210 | 205 | ||
211 | dev_dbg(dev, "%s\n", __func__); | 206 | dev_dbg(dev, "%s\n", __func__); |
212 | 207 | ||
213 | if (is_usb_device(dev)) /* Sanity check */ | ||
214 | return error; | ||
215 | |||
216 | intf = to_usb_interface(dev); | ||
217 | udev = interface_to_usbdev(intf); | ||
218 | intf->needs_binding = 0; | 208 | intf->needs_binding = 0; |
219 | 209 | ||
220 | if (udev->authorized == 0) { | 210 | if (udev->authorized == 0) { |
@@ -385,7 +375,6 @@ void usb_driver_release_interface(struct usb_driver *driver, | |||
385 | struct usb_interface *iface) | 375 | struct usb_interface *iface) |
386 | { | 376 | { |
387 | struct device *dev = &iface->dev; | 377 | struct device *dev = &iface->dev; |
388 | struct usb_device *udev = interface_to_usbdev(iface); | ||
389 | 378 | ||
390 | /* this should never happen, don't release something that's not ours */ | 379 | /* this should never happen, don't release something that's not ours */ |
391 | if (!dev->driver || dev->driver != &driver->drvwrap.driver) | 380 | if (!dev->driver || dev->driver != &driver->drvwrap.driver) |
@@ -394,23 +383,19 @@ void usb_driver_release_interface(struct usb_driver *driver, | |||
394 | /* don't release from within disconnect() */ | 383 | /* don't release from within disconnect() */ |
395 | if (iface->condition != USB_INTERFACE_BOUND) | 384 | if (iface->condition != USB_INTERFACE_BOUND) |
396 | return; | 385 | return; |
386 | iface->condition = USB_INTERFACE_UNBINDING; | ||
397 | 387 | ||
398 | /* don't release if the interface hasn't been added yet */ | 388 | /* Release via the driver core only if the interface |
389 | * has already been registered | ||
390 | */ | ||
399 | if (device_is_registered(dev)) { | 391 | if (device_is_registered(dev)) { |
400 | iface->condition = USB_INTERFACE_UNBINDING; | ||
401 | device_release_driver(dev); | 392 | device_release_driver(dev); |
402 | } else { | 393 | } else { |
403 | iface->condition = USB_INTERFACE_UNBOUND; | 394 | down(&dev->sem); |
404 | usb_cancel_queued_reset(iface); | 395 | usb_unbind_interface(dev); |
396 | dev->driver = NULL; | ||
397 | up(&dev->sem); | ||
405 | } | 398 | } |
406 | dev->driver = NULL; | ||
407 | usb_set_intfdata(iface, NULL); | ||
408 | |||
409 | usb_pm_lock(udev); | ||
410 | iface->condition = USB_INTERFACE_UNBOUND; | ||
411 | mark_quiesced(iface); | ||
412 | iface->needs_remote_wakeup = 0; | ||
413 | usb_pm_unlock(udev); | ||
414 | } | 399 | } |
415 | EXPORT_SYMBOL_GPL(usb_driver_release_interface); | 400 | EXPORT_SYMBOL_GPL(usb_driver_release_interface); |
416 | 401 | ||
@@ -598,7 +583,7 @@ static int usb_device_match(struct device *dev, struct device_driver *drv) | |||
598 | /* TODO: Add real matching code */ | 583 | /* TODO: Add real matching code */ |
599 | return 1; | 584 | return 1; |
600 | 585 | ||
601 | } else { | 586 | } else if (is_usb_interface(dev)) { |
602 | struct usb_interface *intf; | 587 | struct usb_interface *intf; |
603 | struct usb_driver *usb_drv; | 588 | struct usb_driver *usb_drv; |
604 | const struct usb_device_id *id; | 589 | const struct usb_device_id *id; |
@@ -630,11 +615,14 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
630 | /* driver is often null here; dev_dbg() would oops */ | 615 | /* driver is often null here; dev_dbg() would oops */ |
631 | pr_debug("usb %s: uevent\n", dev_name(dev)); | 616 | pr_debug("usb %s: uevent\n", dev_name(dev)); |
632 | 617 | ||
633 | if (is_usb_device(dev)) | 618 | if (is_usb_device(dev)) { |
634 | usb_dev = to_usb_device(dev); | 619 | usb_dev = to_usb_device(dev); |
635 | else { | 620 | } else if (is_usb_interface(dev)) { |
636 | struct usb_interface *intf = to_usb_interface(dev); | 621 | struct usb_interface *intf = to_usb_interface(dev); |
622 | |||
637 | usb_dev = interface_to_usbdev(intf); | 623 | usb_dev = interface_to_usbdev(intf); |
624 | } else { | ||
625 | return 0; | ||
638 | } | 626 | } |
639 | 627 | ||
640 | if (usb_dev->devnum < 0) { | 628 | if (usb_dev->devnum < 0) { |
@@ -1762,6 +1750,7 @@ int usb_suspend(struct device *dev, pm_message_t msg) | |||
1762 | int usb_resume(struct device *dev, pm_message_t msg) | 1750 | int usb_resume(struct device *dev, pm_message_t msg) |
1763 | { | 1751 | { |
1764 | struct usb_device *udev; | 1752 | struct usb_device *udev; |
1753 | int status; | ||
1765 | 1754 | ||
1766 | udev = to_usb_device(dev); | 1755 | udev = to_usb_device(dev); |
1767 | 1756 | ||
@@ -1771,7 +1760,14 @@ int usb_resume(struct device *dev, pm_message_t msg) | |||
1771 | */ | 1760 | */ |
1772 | if (udev->skip_sys_resume) | 1761 | if (udev->skip_sys_resume) |
1773 | return 0; | 1762 | return 0; |
1774 | return usb_external_resume_device(udev, msg); | 1763 | status = usb_external_resume_device(udev, msg); |
1764 | |||
1765 | /* Avoid PM error messages for devices disconnected while suspended | ||
1766 | * as we'll display regular disconnect messages just a bit later. | ||
1767 | */ | ||
1768 | if (status == -ENODEV) | ||
1769 | return 0; | ||
1770 | return status; | ||
1775 | } | 1771 | } |
1776 | 1772 | ||
1777 | #endif /* CONFIG_PM */ | 1773 | #endif /* CONFIG_PM */ |