aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2006-07-01 22:10:15 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-09-27 11:58:50 -0700
commit1cc8a25d5b680ff656927ffa9b66fae6b415b1d3 (patch)
tree4cc4f1f5f0266dab5408c1de77215517822be92a /drivers
parent782da727b0d59e93c84a627948b1535a3db90392 (diff)
downloadlinux-1cc8a25d5b680ff656927ffa9b66fae6b415b1d3.tar.gz
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')
-rw-r--r--drivers/usb/core/driver.c122
1 files changed, 77 insertions, 45 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index a62de0a854063..b0db1583c5222 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 = {