USB: Force unbinding of drivers lacking reset_resume or other methods
This patch (as1024) takes care of a FIXME issue: Drivers that don't have the necessary suspend, resume, reset_resume, pre_reset, or post_reset methods will be unbound and their interface reprobed when one of the unsupported events occurs. This is made slightly more difficult by the fact that bind operations won't work during a system sleep transition. So instead the code has to defer the operation until the transition ends. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
64b3d6d119
commit
78d9a487ee
@@ -3367,6 +3367,11 @@ re_enumerate:
|
||||
* this from a driver probe() routine after downloading new firmware.
|
||||
* For calls that might not occur during probe(), drivers should lock
|
||||
* the device using usb_lock_device_for_reset().
|
||||
*
|
||||
* If an interface is currently being probed or disconnected, we assume
|
||||
* its driver knows how to handle resets. For all other interfaces,
|
||||
* if the driver doesn't have pre_reset and post_reset methods then
|
||||
* we attempt to unbind it and rebind afterward.
|
||||
*/
|
||||
int usb_reset_device(struct usb_device *udev)
|
||||
{
|
||||
@@ -3388,12 +3393,17 @@ int usb_reset_device(struct usb_device *udev)
|
||||
for (i = 0; i < config->desc.bNumInterfaces; ++i) {
|
||||
struct usb_interface *cintf = config->interface[i];
|
||||
struct usb_driver *drv;
|
||||
int unbind = 0;
|
||||
|
||||
if (cintf->dev.driver) {
|
||||
drv = to_usb_driver(cintf->dev.driver);
|
||||
if (drv->pre_reset)
|
||||
(drv->pre_reset)(cintf);
|
||||
/* FIXME: Unbind if pre_reset returns an error or isn't defined */
|
||||
if (drv->pre_reset && drv->post_reset)
|
||||
unbind = (drv->pre_reset)(cintf);
|
||||
else if (cintf->condition ==
|
||||
USB_INTERFACE_BOUND)
|
||||
unbind = 1;
|
||||
if (unbind)
|
||||
usb_forced_unbind_intf(cintf);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3404,13 +3414,18 @@ int usb_reset_device(struct usb_device *udev)
|
||||
for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) {
|
||||
struct usb_interface *cintf = config->interface[i];
|
||||
struct usb_driver *drv;
|
||||
int rebind = cintf->needs_binding;
|
||||
|
||||
if (cintf->dev.driver) {
|
||||
if (!rebind && cintf->dev.driver) {
|
||||
drv = to_usb_driver(cintf->dev.driver);
|
||||
if (drv->post_reset)
|
||||
(drv->post_reset)(cintf);
|
||||
/* FIXME: Unbind if post_reset returns an error or isn't defined */
|
||||
rebind = (drv->post_reset)(cintf);
|
||||
else if (cintf->condition ==
|
||||
USB_INTERFACE_BOUND)
|
||||
rebind = 1;
|
||||
}
|
||||
if (rebind)
|
||||
usb_rebind_intf(cintf);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user