aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/driver.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-05-30 15:38:16 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-07-12 19:34:30 -0400
commitf07600cf9eb3ee92777b2001e564faa413144a99 (patch)
treee48f2e3051fde642e80269bf9c54b289d4abdb44 /drivers/usb/core/driver.c
parent624d6c0732d2c4ac00945ad79dbb6ff39ba90ee3 (diff)
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>
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r--drivers/usb/core/driver.c51
1 files changed, 40 insertions, 11 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 6c62a6d91484..3cd9af2638fc 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -915,21 +915,37 @@ static int usb_resume_interface(struct usb_interface *intf, int reset_resume)
915 } 915 }
916 driver = to_usb_driver(intf->dev.driver); 916 driver = to_usb_driver(intf->dev.driver);
917 917
918 if (reset_resume && driver->post_reset) 918 if (reset_resume) {
919 driver->post_reset(intf, reset_resume); 919 if (driver->reset_resume) {
920 else if (driver->resume) { 920 status = driver->reset_resume(intf);
921 status = driver->resume(intf); 921 if (status)
922 if (status) 922 dev_err(&intf->dev, "%s error %d\n",
923 dev_err(&intf->dev, "%s error %d\n", 923 "reset_resume", status);
924 "resume", status); 924 } else {
925 } else 925 // status = -EOPNOTSUPP;
926 dev_warn(&intf->dev, "no resume for driver %s?\n", 926 dev_warn(&intf->dev, "no %s for driver %s?\n",
927 driver->name); 927 "reset_resume", driver->name);
928 }
929 } else {
930 if (driver->resume) {
931 status = driver->resume(intf);
932 if (status)
933 dev_err(&intf->dev, "%s error %d\n",
934 "resume", status);
935 } else {
936 // status = -EOPNOTSUPP;
937 dev_warn(&intf->dev, "no %s for driver %s?\n",
938 "resume", driver->name);
939 }
940 }
928 941
929done: 942done:
930 dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status); 943 dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status);
931 if (status == 0) 944 if (status == 0)
932 mark_active(intf); 945 mark_active(intf);
946
947 /* FIXME: Unbind the driver and reprobe if the resume failed
948 * (not possible if auto_pm is set) */
933 return status; 949 return status;
934} 950}
935 951
@@ -966,6 +982,18 @@ static int autosuspend_check(struct usb_device *udev)
966 "for autosuspend\n"); 982 "for autosuspend\n");
967 return -EOPNOTSUPP; 983 return -EOPNOTSUPP;
968 } 984 }
985
986 /* Don't allow autosuspend if the device will need
987 * a reset-resume and any of its interface drivers
988 * doesn't include support.
989 */
990 if (udev->quirks & USB_QUIRK_RESET_RESUME) {
991 struct usb_driver *driver;
992
993 driver = to_usb_driver(intf->dev.driver);
994 if (!driver->reset_resume)
995 return -EOPNOTSUPP;
996 }
969 } 997 }
970 } 998 }
971 999
@@ -1146,7 +1174,8 @@ static int usb_resume_both(struct usb_device *udev)
1146 status = usb_autoresume_device(parent); 1174 status = usb_autoresume_device(parent);
1147 if (status == 0) { 1175 if (status == 0) {
1148 status = usb_resume_device(udev); 1176 status = usb_resume_device(udev);
1149 if (status) { 1177 if (status || udev->state ==
1178 USB_STATE_NOTATTACHED) {
1150 usb_autosuspend_device(parent); 1179 usb_autosuspend_device(parent);
1151 1180
1152 /* It's possible usb_resume_device() 1181 /* It's possible usb_resume_device()