Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=686314cfbdac21c9019c0e04487b5d940db62406
Commit:     686314cfbdac21c9019c0e04487b5d940db62406
Parent:     4956eccdd6101c5abb71966079e8183d12796d6c
Author:     Alan Stern <[EMAIL PROTECTED]>
AuthorDate: Wed May 30 15:34:36 2007 -0400
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Thu Jul 12 16:34:29 2007 -0700

    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 <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/core/generic.c |   45 +++++++++++++------------------------
 drivers/usb/core/hcd.c     |   52 +++++++++++++++++++++++++++----------------
 drivers/usb/core/hcd.h     |   14 +----------
 drivers/usb/core/hub.c     |   42 ++++++----------------------------
 4 files changed, 59 insertions(+), 94 deletions(-)

diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index d363b0e..4cbe7b3 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -196,20 +196,15 @@ static int generic_suspend(struct usb_device *udev, 
pm_message_t msg)
 {
        int rc;
 
-       rc = usb_port_suspend(udev);
-
-       /* Root hubs don't have upstream ports to suspend,
-        * so the line above won't do much for them.  We have to
-        * shut down their downstream HC-to-USB interfaces manually,
-        * by doing a bus (or "global") suspend.
+       /* Normal USB devices suspend through their upstream port.
+        * Root hubs don't have upstream ports to suspend,
+        * so we have to shut down their downstream HC-to-USB
+        * interfaces manually by doing a bus (or "global") suspend.
         */
-       if (rc == 0 && !udev->parent) {
-               rc = hcd_bus_suspend(udev->bus);
-               if (rc) {
-                       dev_dbg(&udev->dev, "'global' suspend %d\n", rc);
-                       usb_port_resume(udev);
-               }
-       }
+       if (!udev->parent)
+               rc = hcd_bus_suspend(udev);
+       else
+               rc = usb_port_suspend(udev);
        return rc;
 }
 
@@ -217,25 +212,17 @@ static int generic_resume(struct usb_device *udev)
 {
        int rc;
 
-       if (udev->reset_resume)
+       /* Normal USB devices resume/reset through their upstream port.
+        * Root hubs don't have upstream ports to resume or reset,
+        * so we have to start up their downstream HC-to-USB
+        * interfaces manually by doing a bus (or "global") resume.
+        */
+       if (!udev->parent)
+               rc = hcd_bus_resume(udev);
+       else if (udev->reset_resume)
                rc = usb_reset_suspended_device(udev);
        else
                rc = usb_port_resume(udev);
-
-       /* Root hubs don't have upstream ports to resume or reset,
-        * so the line above won't do much for them.  We have to
-        * start up their downstream HC-to-USB interfaces manually,
-        * by doing a bus (or "global") resume.
-        */
-       if (rc == 0 && !udev->parent) {
-               rc = hcd_bus_resume(udev->bus);
-               if (rc)
-                       dev_dbg(&udev->dev, "'global' resume %d\n", rc);
-               else {
-                       /* TRSMRCY = 10 msec */
-                       msleep(10);
-               }
-       }
        return rc;
 }
 
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 87d6edf..e5058fb 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);
        }
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index ef50fa4..b5ebb73 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -364,23 +364,13 @@ extern int usb_find_interface_driver (struct usb_device 
*dev,
 #ifdef CONFIG_PM
 extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
 extern void usb_root_hub_lost_power (struct usb_device *rhdev);
-extern int hcd_bus_suspend (struct usb_bus *bus);
-extern int hcd_bus_resume (struct usb_bus *bus);
+extern int hcd_bus_suspend(struct usb_device *rhdev);
+extern int hcd_bus_resume(struct usb_device *rhdev);
 #else
 static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
 {
        return;
 }
-
-static inline int hcd_bus_suspend(struct usb_bus *bus)
-{
-       return 0;
-}
-
-static inline int hcd_bus_resume (struct usb_bus *bus)
-{
-       return 0;
-}
 #endif /* CONFIG_PM */
 
 /*
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 04d6fde..ac1ef15 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1722,17 +1722,8 @@ int usb_port_suspend(struct usb_device *udev)
 {
        int     status = 0;
 
-       /* we change the device's upstream USB link,
-        * but root hubs have no upstream USB link.
-        */
-       if (udev->parent)
-               status = hub_port_suspend(hdev_to_hub(udev->parent),
-                               udev->portnum, udev);
-       else {
-               dev_dbg(&udev->dev, "usb %ssuspend\n",
-                               udev->auto_pm ? "auto-" : "");
-               usb_set_device_state(udev, USB_STATE_SUSPENDED);
-       }
+       status = hub_port_suspend(hdev_to_hub(udev->parent),
+                       udev->portnum, udev);
        return status;
 }
 
@@ -1775,8 +1766,7 @@ static int finish_port_resume(struct usb_device *udev)
                        status);
        else if (udev->actconfig) {
                le16_to_cpus(&devstatus);
-               if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP))
-                               && udev->parent) {
+               if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
                        status = usb_control_msg(udev,
                                        usb_sndctrlpipe(udev, 0),
                                        USB_REQ_CLEAR_FEATURE,
@@ -1789,10 +1779,6 @@ static int finish_port_resume(struct usb_device *udev)
                                        "wakeup, status %d\n", status);
                }
                status = 0;
-
-       } else if (udev->devnum <= 0) {
-               dev_dbg(&udev->dev, "bogus resume!\n");
-               status = -EINVAL;
        }
        return status;
 }
@@ -1821,9 +1807,8 @@ hub_port_resume(struct usb_hub *hub, int port1, struct 
usb_device *udev)
                        port1, status);
        } else {
                /* drive resume for at least 20 msec */
-               if (udev)
-                       dev_dbg(&udev->dev, "usb %sresume\n",
-                                       udev->auto_pm ? "auto-" : "");
+               dev_dbg(&udev->dev, "usb %sresume\n",
+                               udev->auto_pm ? "auto-" : "");
                msleep(25);
 
 #define LIVE_FLAGS     ( USB_PORT_STAT_POWER \
@@ -1851,8 +1836,7 @@ SuspendCleared:
                                                USB_PORT_FEAT_C_SUSPEND);
                        /* TRSMRCY = 10 msec */
                        msleep(10);
-                       if (udev)
-                               status = finish_port_resume(udev);
+                       status = finish_port_resume(udev);
                }
        }
        if (status < 0)
@@ -1882,18 +1866,8 @@ int usb_port_resume(struct usb_device *udev)
 {
        int     status;
 
-       /* we change the device's upstream USB link,
-        * but root hubs have no upstream USB link.
-        */
-       if (udev->parent) {
-               // NOTE this fails if parent is also suspended...
-               status = hub_port_resume(hdev_to_hub(udev->parent),
-                               udev->portnum, udev);
-       } else {
-               dev_dbg(&udev->dev, "usb %sresume\n",
-                               udev->auto_pm ? "auto-" : "");
-               status = finish_port_resume(udev);
-       }
+       status = hub_port_resume(hdev_to_hub(udev->parent),
+                       udev->portnum, udev);
        if (status < 0)
                dev_dbg(&udev->dev, "can't resume, status %d\n", status);
        return status;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to