maybe_print_eds (controller, "donehead",
                        ohci_readl (controller, ®s->donehead), next, size);
-
-       /* broken fminterval means traffic won't flow! */ 
-       ohci_dbg (controller, "fminterval %08x\n", 
-                       ohci_readl (controller, ®s->fminterval));
 }
 
 #define dbg_port_sw(hc,num,value,next,size) \
 
                ohci_vdbg (ohci, "resume detect\n");
                ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus);
                if (hcd->state != HC_STATE_QUIESCING)
-                       schedule_work(&ohci->rh_resume);
+                       usb_hcd_resume_root_hub(hcd);
        }
 
        if (ints & OHCI_INTR_WDH) {
 
        ohci_dbg (ohci, "suspend root hub\n");
 
        /* First stop any processing */
-       hcd->state = HC_STATE_QUIESCING;
        if (ohci->hc_control & OHCI_SCHED_ENABLES) {
                int             limit;
 
        else
                ohci->hc_control &= ~OHCI_CTRL_RWE;
 
-       /* Suspend hub */
+       /* Suspend hub ... this is the "global (to this bus) suspend" mode,
+        * which doesn't imply ports will first be individually suspended.
+        */
        ohci->hc_control &= ~OHCI_CTRL_HCFS;
        ohci->hc_control |= OHCI_USB_SUSPEND;
        ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
        ohci->next_statechange = jiffies + msecs_to_jiffies (5);
 
 done:
+       /* external suspend vs self autosuspend ... same effect */
        if (status == 0)
-               hcd->state = HC_STATE_SUSPENDED;
+               usb_hcd_suspend_root_hub(hcd);
        spin_unlock_irqrestore (&ohci->lock, flags);
        return status;
 }
        ohci->hc_control = ohci_readl (ohci, &ohci->regs->control);
 
        if (ohci->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) {
-               /* this can happen after suspend-to-disk */
+               /* this can happen after resuming a swsusp snapshot */
                if (hcd->state == HC_STATE_RESUMING) {
                        ohci_dbg (ohci, "BIOS/SMM active, control %03x\n",
                                        ohci->hc_control);
                ohci_info (ohci, "wakeup\n");
                break;
        case OHCI_USB_OPER:
-               ohci_dbg (ohci, "already resumed\n");
-               status = 0;
+               /* this can happen after resuming a swsusp snapshot */
+               ohci_dbg (ohci, "snapshot resume? reinit\n");
+               status = -EBUSY;
                break;
        default:                /* RESET, we lost power */
-               ohci_dbg (ohci, "root hub hardware reset\n");
+               ohci_dbg (ohci, "lost power\n");
                status = -EBUSY;
        }
        spin_unlock_irq (&ohci->lock);
        }
 
        /* Some controllers (lucent erratum) need extra-long delays */
-       hcd->state = HC_STATE_RESUMING;
-       mdelay (20 /* usb 11.5.1.10 */ + 15);
+       msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
 
        temp = ohci_readl (ohci, &ohci->regs->control);
        temp &= OHCI_CTRL_HCFS;
                (void) ohci_readl (ohci, &ohci->regs->control);
        }
 
-       hcd->state = HC_STATE_RUNNING;
        return 0;
 }
 
-static void ohci_rh_resume (void *_hcd)
-{
-       struct usb_hcd  *hcd = _hcd;
-
-       usb_lock_device (hcd->self.root_hub);
-       (void) ohci_hub_resume (hcd);
-       usb_unlock_device (hcd->self.root_hub);
-}
-
-#else
-
-static void ohci_rh_resume (void *_hcd)
-{
-       struct ohci_hcd *ohci = hcd_to_ohci (_hcd);
-       ohci_dbg(ohci, "rh_resume ??\n");
-}
-
 #endif /* CONFIG_PM */
 
 /*-------------------------------------------------------------------------*/
 #ifdef CONFIG_PM
        /* save power by suspending idle root hubs;
         * INTR_RD wakes us when there's work
-        * NOTE: if we can do this, we don't need a root hub timer!
         */
        if (can_suspend
                        && !changed
                        ) {
                ohci_vdbg (ohci, "autosuspend\n");
                (void) ohci_hub_suspend (hcd);
-               hcd->state = HC_STATE_RUNNING;
                usb_unlock_device (hcd->self.root_hub);
        }
 #endif
                        temp = RH_PS_POCI;
                        if ((ohci->hc_control & OHCI_CTRL_HCFS)
                                        != OHCI_USB_OPER)
-                               schedule_work (&ohci->rh_resume);
+                               usb_hcd_resume_root_hub(hcd);
                        break;
                case USB_PORT_FEAT_C_SUSPEND:
                        temp = RH_PS_PSSC;
 
        ohci->next_statechange = jiffies;
        spin_lock_init (&ohci->lock);
        INIT_LIST_HEAD (&ohci->pending);
-       INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci));
        ohci->reboot_notifier.notifier_call = ohci_reboot;
 }
 
 
 static int ohci_omap_suspend(struct device *dev, pm_message_t message)
 {
        struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
-       int             status = -EINVAL;
-
-       down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-       status = ohci_hub_suspend(ohci_to_hcd(ohci));
-       if (status == 0) {
-               omap_ohci_clock_power(0);
-               ohci_to_hcd(ohci)->self.root_hub->state =
-                       USB_STATE_SUSPENDED;
-               ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
-               dev->power.power_state = PMSG_SUSPEND;
-       }
-       up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-       return status;
+
+       if (time_before(jiffies, ohci->next_statechange))
+               msleep(5);
+       ohci->next_statechange = jiffies;
+
+       omap_ohci_clock_power(0);
+       ohci_to_hcd(ohci)->state = HC_STATE_SUSPENDED;
+       dev->power.power_state = PMSG_SUSPEND;
+       return 0;
 }
 
 static int ohci_omap_resume(struct device *dev)
 {
        struct ohci_hcd *ohci = hcd_to_ohci(dev_get_drvdata(dev));
-       int             status = 0;
 
        if (time_before(jiffies, ohci->next_statechange))
                msleep(5);
        ohci->next_statechange = jiffies;
+
        omap_ohci_clock_power(1);
-#ifdef CONFIG_USB_SUSPEND
-       /* get extra cleanup even if remote wakeup isn't in use */
-       status = usb_resume_device(ohci_to_hcd(ohci)->self.root_hub);
-#else
-       down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-       status = ohci_hub_resume(ohci_to_hcd(ohci));
-       up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
-#endif
-       if (status == 0)
-               dev->power.power_state = PMSG_ON;
-       return status;
+       dev->power.power_state = PMSG_ON;
+       usb_hcd_resume_root_hub(dev_get_drvdata(dev));
+       return 0;
 }
 
 #endif
 
 
 static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
 {
-       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
-
-       /* suspend root hub, hoping it keeps power during suspend */
-       if (time_before (jiffies, ohci->next_statechange))
-               msleep (100);
-
-#ifdef CONFIG_USB_SUSPEND
-       (void) usb_suspend_device (hcd->self.root_hub);
-#else
-       usb_lock_device (hcd->self.root_hub);
-       (void) ohci_hub_suspend (hcd);
-       usb_unlock_device (hcd->self.root_hub);
-#endif
+       /* root hub was already suspended */
 
-       /* let things settle down a bit */
-       msleep (100);
-       
+       /* FIXME these PMAC things get called in the wrong places.  ASIC
+        * clocks should be turned off AFTER entering D3, and on BEFORE
+        * trying to enter D0.  Evidently the PCI layer doesn't currently
+        * provide the right sort of platform hooks for this ...
+        */
 #ifdef CONFIG_PPC_PMAC
        if (_machine == _MACH_Pmac) {
                struct device_node      *of_node;
 
 static int ohci_pci_resume (struct usb_hcd *hcd)
 {
-       struct ohci_hcd         *ohci = hcd_to_ohci (hcd);
-       int                     retval = 0;
-
 #ifdef CONFIG_PPC_PMAC
        if (_machine == _MACH_Pmac) {
                struct device_node *of_node;
        }
 #endif /* CONFIG_PPC_PMAC */
 
-       /* resume root hub */
-       if (time_before (jiffies, ohci->next_statechange))
-               msleep (100);
-#ifdef CONFIG_USB_SUSPEND
-       /* get extra cleanup even if remote wakeup isn't in use */
-       retval = usb_resume_device (hcd->self.root_hub);
-#else
-       usb_lock_device (hcd->self.root_hub);
-       retval = ohci_hub_resume (hcd);
-       usb_unlock_device (hcd->self.root_hub);
-#endif
-
-       return retval;
+       usb_hcd_resume_root_hub(hcd);
+       return 0;
 }
 
 #endif /* CONFIG_PM */
 
        unsigned long           next_statechange;       /* suspend/resume */
        u32                     fminterval;             /* saved register */
 
-       struct work_struct      rh_resume;
        struct notifier_block   reboot_notifier;
 
        unsigned long           flags;          /* for HC bugs */