summaryrefslogtreecommitdiff
path: root/drivers/usb/core/usb.c
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2005-09-13 19:57:27 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 16:47:38 -0700
commit390a8c345e6415cbf811232feedac70b56c9fc8d (patch)
tree5a27e9421575c080d31884c4eedeed710d7134f1 /drivers/usb/core/usb.c
parentc9f89fa40cf274130b56475175a35af961d4b165 (diff)
[PATCH] remove usb_suspend_device() parameter
This patch removes the extra usb_suspend_device() parameter. The original reason to pass that parameter was so that this routine could suspend any active children. A previous patch removed that functionality ... leaving no reason to pass the parameter. A close analogy is pci_set_power_state, which doesn't need a pm_message_t either. On the internal code path that comes through the driver model, the parameter is now used to distinguish cases where USB devices need to "freeze" but not suspend. It also checks for an error case that's accessible through sysfs: attempting to suspend a device before its interfaces (or for hubs, ports). Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> drivers/usb/core/hub.c | 34 +++++++++++++++++++++------------- drivers/usb/core/usb.c | 23 +++++++++++++++++++++-- drivers/usb/host/ehci-hcd.c | 2 +- drivers/usb/host/isp116x-hcd.c | 2 +- drivers/usb/host/ohci-pci.c | 2 +- include/linux/usb.h | 2 +- 6 files changed, 46 insertions(+), 19 deletions(-)
Diffstat (limited to 'drivers/usb/core/usb.c')
-rw-r--r--drivers/usb/core/usb.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 6ecfdce4f848..e89dbd43e952 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -1414,14 +1414,33 @@ void usb_buffer_unmap_sg (struct usb_device *dev, unsigned pipe,
usb_pipein (pipe) ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
}
+static int verify_suspended(struct device *dev, void *unused)
+{
+ return (dev->power.power_state.event == PM_EVENT_ON) ? -EBUSY : 0;
+}
+
static int usb_generic_suspend(struct device *dev, pm_message_t message)
{
struct usb_interface *intf;
struct usb_driver *driver;
int status;
- if (dev->driver == &usb_generic_driver)
- return usb_suspend_device (to_usb_device(dev), message);
+ /* USB devices enter SUSPEND state through their hubs, but can be
+ * marked for FREEZE as soon as their children are already idled.
+ */
+ if (dev->driver == &usb_generic_driver) {
+ if (dev->power.power_state.event == message.event)
+ return 0;
+ /* we need to rule out bogus requests through sysfs */
+ status = device_for_each_child(dev, NULL, verify_suspended);
+ if (status)
+ return status;
+ if (message.event == PM_EVENT_FREEZE) {
+ dev->power.power_state = message;
+ return 0;
+ }
+ return usb_suspend_device (to_usb_device(dev));
+ }
if ((dev->driver == NULL) ||
(dev->driver_data == &usb_generic_driver_data))