diff options
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r-- | drivers/usb/core/driver.c | 71 |
1 files changed, 42 insertions, 29 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index eefc98584ea..92ecc4eb1e8 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -755,48 +755,57 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister); static int suspend_device(struct usb_device *udev, pm_message_t msg) { struct usb_device_driver *udriver; + int status = 0; if (udev->dev.driver == NULL) - return 0; + goto done; udriver = to_usb_device_driver(udev->dev.driver); if (udev->dev.power.power_state.event == msg.event) - return 0; - return udriver->suspend(udev, msg); + goto done; + status = udriver->suspend(udev, msg); + +done: + if (status == 0) + udev->dev.power.power_state.event = msg.event; + return status; } /* Caller has locked udev */ static int resume_device(struct usb_device *udev) { struct usb_device_driver *udriver; + int status = 0; if (udev->dev.power.power_state.event == PM_EVENT_ON) - return 0; - - /* mark things as "on" immediately, no matter what errors crop up */ - udev->dev.power.power_state.event = PM_EVENT_ON; + goto done; if (udev->dev.driver == NULL) - return 0; + goto done; udriver = to_usb_device_driver(udev->dev.driver); if (udev->state == USB_STATE_NOTATTACHED) - return 0; - return udriver->resume(udev); + goto done; + status = udriver->resume(udev); + +done: + if (status == 0) + udev->dev.power.power_state.event = PM_EVENT_ON; + return status; } /* Caller has locked intf's usb_device */ static int suspend_interface(struct usb_interface *intf, pm_message_t msg) { struct usb_driver *driver; - int status; + int status = 0; if (intf->dev.driver == NULL) - return 0; + goto done; driver = to_usb_driver(intf->dev.driver); /* with no hardware, USB interfaces only use FREEZE and ON states */ if (!is_active(intf)) - return 0; + goto done; if (driver->suspend && driver->resume) { status = driver->suspend(intf, msg); @@ -810,8 +819,11 @@ static int suspend_interface(struct usb_interface *intf, pm_message_t msg) dev_warn(&intf->dev, "no suspend for driver %s?\n", driver->name); mark_quiesced(intf); - status = 0; } + +done: + if (status == 0) + intf->dev.power.power_state.event = msg.event; return status; } @@ -820,24 +832,19 @@ static int resume_interface(struct usb_interface *intf) { struct usb_driver *driver; struct usb_device *udev; - int status; + int status = 0; if (intf->dev.power.power_state.event == PM_EVENT_ON) - return 0; - - /* mark things as "on" immediately, no matter what errors crop up */ - intf->dev.power.power_state.event = PM_EVENT_ON; + goto done; - if (intf->dev.driver == NULL) { - intf->dev.power.power_state.event = PM_EVENT_FREEZE; - return 0; - } + if (intf->dev.driver == NULL) + goto done; driver = to_usb_driver(intf->dev.driver); udev = interface_to_usbdev(intf); if (udev->state == USB_STATE_NOTATTACHED) - return 0; + goto done; /* if driver was suspended, it has a resume method; * however, sysfs can wrongly mark things as suspended @@ -845,15 +852,21 @@ static int resume_interface(struct usb_interface *intf) */ if (driver->resume) { status = driver->resume(intf); - if (status) { + if (status) dev_err(&intf->dev, "%s error %d\n", "resume", status); - mark_quiesced(intf); - } - } else + else + mark_active(intf); + } else { dev_warn(&intf->dev, "no resume for driver %s?\n", driver->name); - return 0; + mark_active(intf); + } + +done: + if (status == 0) + intf->dev.power.power_state.event = PM_EVENT_ON; + return status; } /* Caller has locked udev */ |