diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2006-07-02 02:10:15 (GMT) |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-09-27 18:58:50 (GMT) |
commit | 1cc8a25d5b680ff656927ffa9b66fae6b415b1d3 (patch) | |
tree | 4cc4f1f5f0266dab5408c1de77215517822be92a /drivers/usb/core/driver.c | |
parent | 782da727b0d59e93c84a627948b1535a3db90392 (diff) | |
download | linux-fsl-qoriq-1cc8a25d5b680ff656927ffa9b66fae6b415b1d3.tar.xz |
usbcore: split suspend/resume for device and interfaces
This patch (as716b) splits up the core suspend and resume routines into
two parts each: one for handling devices and one for handling
interfaces. The behavior of the parts should be the same as in the old
unified code.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r-- | drivers/usb/core/driver.c | 122 |
1 files changed, 77 insertions, 45 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index a62de0a..b0db158 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -751,81 +751,89 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister); #ifdef CONFIG_PM -static int usb_suspend(struct device *dev, pm_message_t message) +/* Caller has locked udev */ +static int suspend_device(struct usb_device *udev, pm_message_t msg) { - struct usb_device *udev; struct usb_device_driver *udriver; - struct usb_interface *intf; - struct usb_driver *driver; - int status; - if (is_usb_device(dev)) { - if (dev->driver == NULL) - return 0; - udev = to_usb_device(dev); - udriver = to_usb_device_driver(dev->driver); - if (dev->power.power_state.event == message.event) - return 0; - return udriver->suspend(udev, message); - } + if (udev->dev.driver == NULL) + return 0; + udriver = to_usb_device_driver(udev->dev.driver); + if (udev->dev.power.power_state.event == msg.event) + return 0; + return udriver->suspend(udev, msg); +} + +/* Caller has locked udev */ +static int resume_device(struct usb_device *udev) +{ + struct usb_device_driver *udriver; - if (dev->driver == NULL) + if (udev->dev.power.power_state.event == PM_EVENT_ON) return 0; - intf = to_usb_interface(dev); - driver = to_usb_driver(dev->driver); + /* mark things as "on" immediately, no matter what errors crop up */ + udev->dev.power.power_state.event = PM_EVENT_ON; + + if (udev->dev.driver == NULL) + return 0; + udriver = to_usb_device_driver(udev->dev.driver); + if (udev->state == USB_STATE_NOTATTACHED) + return 0; + return udriver->resume(udev); +} + +/* Caller has locked intf */ +static int suspend_interface(struct usb_interface *intf, pm_message_t msg) +{ + struct usb_driver *driver; + int status; + + if (intf->dev.driver == NULL) + return 0; + + driver = to_usb_driver(intf->dev.driver); /* with no hardware, USB interfaces only use FREEZE and ON states */ if (!is_active(intf)) return 0; if (driver->suspend && driver->resume) { - status = driver->suspend(intf, message); + status = driver->suspend(intf, msg); if (status) - dev_err(dev, "%s error %d\n", "suspend", status); + dev_err(&intf->dev, "%s error %d\n", + "suspend", status); else mark_quiesced(intf); } else { // FIXME else if there's no suspend method, disconnect... - dev_warn(dev, "no suspend for driver %s?\n", driver->name); + dev_warn(&intf->dev, "no suspend for driver %s?\n", + driver->name); mark_quiesced(intf); status = 0; } return status; } -static int usb_resume(struct device *dev) +/* Caller has locked intf */ +static int resume_interface(struct usb_interface *intf) { - struct usb_device *udev; - struct usb_device_driver *udriver; - struct usb_interface *intf; - struct usb_driver *driver; - int status; + struct usb_driver *driver; + struct usb_device *udev; + int status; - if (dev->power.power_state.event == PM_EVENT_ON) + if (intf->dev.power.power_state.event == PM_EVENT_ON) return 0; /* mark things as "on" immediately, no matter what errors crop up */ - dev->power.power_state.event = PM_EVENT_ON; + intf->dev.power.power_state.event = PM_EVENT_ON; - /* devices resume through their hubs */ - if (is_usb_device(dev)) { - if (dev->driver == NULL) - return 0; - udev = to_usb_device(dev); - udriver = to_usb_device_driver(dev->driver); - if (udev->state == USB_STATE_NOTATTACHED) - return 0; - return udriver->resume(udev); - } - - if (dev->driver == NULL) { - dev->power.power_state.event = PM_EVENT_FREEZE; + if (intf->dev.driver == NULL) { + intf->dev.power.power_state.event = PM_EVENT_FREEZE; return 0; } - intf = to_usb_interface(dev); - driver = to_usb_driver(dev->driver); + driver = to_usb_driver(intf->dev.driver); udev = interface_to_usbdev(intf); if (udev->state == USB_STATE_NOTATTACHED) @@ -838,14 +846,38 @@ static int usb_resume(struct device *dev) if (driver->resume) { status = driver->resume(intf); if (status) { - dev_err(dev, "%s error %d\n", "resume", status); + dev_err(&intf->dev, "%s error %d\n", + "resume", status); mark_quiesced(intf); } } else - dev_warn(dev, "no resume for driver %s?\n", driver->name); + dev_warn(&intf->dev, "no resume for driver %s?\n", + driver->name); return 0; } +static int usb_suspend(struct device *dev, pm_message_t message) +{ + int status; + + if (is_usb_device(dev)) + status = suspend_device(to_usb_device(dev), message); + else + status = suspend_interface(to_usb_interface(dev), message); + return status; +} + +static int usb_resume(struct device *dev) +{ + int status; + + if (is_usb_device(dev)) + status = resume_device(to_usb_device(dev)); + else + status = resume_interface(to_usb_interface(dev)); + return status; +} + #endif /* CONFIG_PM */ struct bus_type usb_bus_type = { |