aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/usb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/usb.c')
-rw-r--r--drivers/usb/core/usb.c53
1 files changed, 32 insertions, 21 deletions
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 25cf7e9eccfa..a3c42203213a 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -293,7 +293,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
293 /* if interface was already added, bind now; else let 293 /* if interface was already added, bind now; else let
294 * the future device_add() bind it, bypassing probe() 294 * the future device_add() bind it, bypassing probe()
295 */ 295 */
296 if (!list_empty (&dev->bus_list)) 296 if (klist_node_attached(&dev->knode_bus))
297 device_bind_driver(dev); 297 device_bind_driver(dev);
298 298
299 return 0; 299 return 0;
@@ -322,9 +322,15 @@ void usb_driver_release_interface(struct usb_driver *driver,
322 if (!dev->driver || dev->driver != &driver->driver) 322 if (!dev->driver || dev->driver != &driver->driver)
323 return; 323 return;
324 324
325 /* don't disconnect from disconnect(), or before dev_add() */ 325 /* don't release from within disconnect() */
326 if (!list_empty (&dev->driver_list) && !list_empty (&dev->bus_list)) 326 if (iface->condition != USB_INTERFACE_BOUND)
327 return;
328
329 /* release only after device_add() */
330 if (klist_node_attached(&dev->knode_bus)) {
331 iface->condition = USB_INTERFACE_UNBINDING;
327 device_release_driver(dev); 332 device_release_driver(dev);
333 }
328 334
329 dev->driver = NULL; 335 dev->driver = NULL;
330 usb_set_intfdata(iface, NULL); 336 usb_set_intfdata(iface, NULL);
@@ -462,6 +468,25 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
462 return NULL; 468 return NULL;
463} 469}
464 470
471
472static int __find_interface(struct device * dev, void * data)
473{
474 struct usb_interface ** ret = (struct usb_interface **)data;
475 struct usb_interface * intf = *ret;
476 int *minor = (int *)data;
477
478 /* can't look at usb devices, only interfaces */
479 if (dev->driver == &usb_generic_driver)
480 return 0;
481
482 intf = to_usb_interface(dev);
483 if (intf->minor != -1 && intf->minor == *minor) {
484 *ret = intf;
485 return 1;
486 }
487 return 0;
488}
489
465/** 490/**
466 * usb_find_interface - find usb_interface pointer for driver and device 491 * usb_find_interface - find usb_interface pointer for driver and device
467 * @drv: the driver whose current configuration is considered 492 * @drv: the driver whose current configuration is considered
@@ -473,26 +498,12 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
473 */ 498 */
474struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) 499struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
475{ 500{
476 struct list_head *entry; 501 struct usb_interface *intf = (struct usb_interface *)(long)minor;
477 struct device *dev; 502 int ret;
478 struct usb_interface *intf;
479 503
480 list_for_each(entry, &drv->driver.devices) { 504 ret = driver_for_each_device(&drv->driver, NULL, &intf, __find_interface);
481 dev = container_of(entry, struct device, driver_list);
482
483 /* can't look at usb devices, only interfaces */
484 if (dev->driver == &usb_generic_driver)
485 continue;
486
487 intf = to_usb_interface(dev);
488 if (intf->minor == -1)
489 continue;
490 if (intf->minor == minor)
491 return intf;
492 }
493 505
494 /* no device found that matches */ 506 return ret ? intf : NULL;
495 return NULL;
496} 507}
497 508
498static int usb_device_match (struct device *dev, struct device_driver *drv) 509static int usb_device_match (struct device *dev, struct device_driver *drv)