{
        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;
 }
 
 {
        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;
 }
 
 
 
 #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);
        }
 
 #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 */
 
 /*
 
 {
        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;
 }
 
                        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,
                                        "wakeup, status %d\n", status);
                }
                status = 0;
-
-       } else if (udev->devnum <= 0) {
-               dev_dbg(&udev->dev, "bogus resume!\n");
-               status = -EINVAL;
        }
        return status;
 }
                        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 \
                                                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)
 {
        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;