USB: add reset_resume method
This patch (as918) introduces a new USB driver method: reset_resume. It is called when a device needs to be reset as part of a resume procedure (whether because of a device quirk or because of the USB-Persist facility), thereby taking over a role formerly assigned to the post_reset method. As a consequence, post_reset no longer needs an argument indicating whether it is being called as part of a reset-resume. This separation of functions makes the code clearer. In addition, the pre_reset and post_reset method return types are changed; they now must return an error code. The return value is unused at present, but at some later time we may unbind drivers and re-probe if they encounter an error during reset handling. The existing pre_reset and post_reset methods in the usbhid, usb-storage, and hub drivers are updated to match the new requirements. For usbhid the post_reset routine is also used for reset_resume (duplicate method pointers); for the other drivers a new reset_resume routine is added. The change to hub.c looks bigger than it really is, because mark_children_for_reset_resume() gets moved down next to the new hub_reset_resume() routine. A minor change to usb-storage makes the usb_stor_report_bus_reset() routine acquire the host lock instead of requiring the caller to hold it already. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Jiri Kosina <jkosina@suse.cz> CC: Matthew Dharm <mdharm-usb@one-eyed-alien.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
624d6c0732
commit
f07600cf9e
@ -915,21 +915,37 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
|
||||
}
|
||||
driver = to_usb_driver(intf->dev.driver);
|
||||
|
||||
if (reset_resume && driver->post_reset)
|
||||
driver->post_reset(intf, reset_resume);
|
||||
else if (driver->resume) {
|
||||
status = driver->resume(intf);
|
||||
if (status)
|
||||
dev_err(&intf->dev, "%s error %d\n",
|
||||
"resume", status);
|
||||
} else
|
||||
dev_warn(&intf->dev, "no resume for driver %s?\n",
|
||||
driver->name);
|
||||
if (reset_resume) {
|
||||
if (driver->reset_resume) {
|
||||
status = driver->reset_resume(intf);
|
||||
if (status)
|
||||
dev_err(&intf->dev, "%s error %d\n",
|
||||
"reset_resume", status);
|
||||
} else {
|
||||
// status = -EOPNOTSUPP;
|
||||
dev_warn(&intf->dev, "no %s for driver %s?\n",
|
||||
"reset_resume", driver->name);
|
||||
}
|
||||
} else {
|
||||
if (driver->resume) {
|
||||
status = driver->resume(intf);
|
||||
if (status)
|
||||
dev_err(&intf->dev, "%s error %d\n",
|
||||
"resume", status);
|
||||
} else {
|
||||
// status = -EOPNOTSUPP;
|
||||
dev_warn(&intf->dev, "no %s for driver %s?\n",
|
||||
"resume", driver->name);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
|
||||
if (status == 0)
|
||||
mark_active(intf);
|
||||
|
||||
/* FIXME: Unbind the driver and reprobe if the resume failed
|
||||
* (not possible if auto_pm is set) */
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -966,6 +982,18 @@ static int autosuspend_check(struct usb_device *udev)
|
||||
"for autosuspend\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* Don't allow autosuspend if the device will need
|
||||
* a reset-resume and any of its interface drivers
|
||||
* doesn't include support.
|
||||
*/
|
||||
if (udev->quirks & USB_QUIRK_RESET_RESUME) {
|
||||
struct usb_driver *driver;
|
||||
|
||||
driver = to_usb_driver(intf->dev.driver);
|
||||
if (!driver->reset_resume)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1146,7 +1174,8 @@ static int usb_resume_both(struct usb_device *udev)
|
||||
status = usb_autoresume_device(parent);
|
||||
if (status == 0) {
|
||||
status = usb_resume_device(udev);
|
||||
if (status) {
|
||||
if (status || udev->state ==
|
||||
USB_STATE_NOTATTACHED) {
|
||||
usb_autosuspend_device(parent);
|
||||
|
||||
/* It's possible usb_resume_device()
|
||||
|
Reference in New Issue
Block a user