diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2007-05-30 15:34:36 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-07-12 16:34:29 -0700 |
commit | 686314cfbdac21c9019c0e04487b5d940db62406 (patch) | |
tree | 245810b09a9b19dc74e668a244e1d5ad88ff6bee /drivers/usb/core/hcd.c | |
parent | 4956eccdd6101c5abb71966079e8183d12796d6c (diff) | |
download | linux-686314cfbdac21c9019c0e04487b5d940db62406.tar.bz2 |
USB: separate root and non-root suspend/resume
This patch (as916) completes the separation of code paths for suspend
and resume of root hubs as opposed to non-root devices. Root hubs
will be power-managed through their bus_suspend and bus_resume
methods, whereas normal devices will use usb_port_suspend() and
usb_port_resume().
Changes to the hcd_bus_{suspend,resume} routines mostly represent
motion of code that was already present elsewhere. They include:
Adding debugging log messages,
Setting the device state appropriately, and
Adding a resume recovery time delay.
Changes to the port-suspend and port-resume routines in hub.c include:
Removal of checks for root devices (since they will never
be triggered), and
Removal of checks for NULL or invalid device pointers (these
were left over from earlier kernel versions and aren't needed
at all).
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core/hcd.c')
-rw-r--r-- | drivers/usb/core/hcd.c | 52 |
1 files changed, 33 insertions, 19 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 87d6edf11f92..e5058fb26a7e 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1257,40 +1257,54 @@ rescan: #ifdef CONFIG_PM -int hcd_bus_suspend (struct usb_bus *bus) +int hcd_bus_suspend(struct usb_device *rhdev) { - struct usb_hcd *hcd; - int status; + struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); + int status; + int old_state = hcd->state; - hcd = container_of (bus, struct usb_hcd, self); - if (!hcd->driver->bus_suspend) - return -ENOENT; - hcd->state = HC_STATE_QUIESCING; - status = hcd->driver->bus_suspend (hcd); - if (status == 0) + dev_dbg(&rhdev->dev, "bus %s%s\n", + rhdev->auto_pm ? "auto-" : "", "suspend"); + if (!hcd->driver->bus_suspend) { + status = -ENOENT; + } else { + hcd->state = HC_STATE_QUIESCING; + status = hcd->driver->bus_suspend(hcd); + } + if (status == 0) { + usb_set_device_state(rhdev, USB_STATE_SUSPENDED); hcd->state = HC_STATE_SUSPENDED; - else - dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n", + } else { + hcd->state = old_state; + dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", "suspend", status); + } return status; } -int hcd_bus_resume (struct usb_bus *bus) +int hcd_bus_resume(struct usb_device *rhdev) { - struct usb_hcd *hcd; - int status; + struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); + int status; - hcd = container_of (bus, struct usb_hcd, self); + dev_dbg(&rhdev->dev, "usb %s%s\n", + rhdev->auto_pm ? "auto-" : "", "resume"); if (!hcd->driver->bus_resume) return -ENOENT; if (hcd->state == HC_STATE_RUNNING) return 0; + hcd->state = HC_STATE_RESUMING; - status = hcd->driver->bus_resume (hcd); - if (status == 0) + status = hcd->driver->bus_resume(hcd); + if (status == 0) { + /* TRSMRCY = 10 msec */ + msleep(10); + usb_set_device_state(rhdev, rhdev->actconfig + ? USB_STATE_CONFIGURED + : USB_STATE_ADDRESS); hcd->state = HC_STATE_RUNNING; - else { - dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n", + } else { + dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", "resume", status); usb_hc_died(hcd); } |