static kmem_cache_t *uhci_up_cachep;   /* urb_priv */
 
+static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state);
+static void wakeup_rh(struct uhci_hcd *uhci);
 static void uhci_get_current_frame_number(struct uhci_hcd *uhci);
 
 /* If a transfer is still active after this much time, turn off FSBR */
        outw(0, uhci->io_addr + USBINTR);
        outw(0, uhci->io_addr + USBCMD);
 
-       uhci->resume_detect = 0;
        uhci->port_c_suspend = uhci->suspended_ports =
                        uhci->resuming_ports = 0;
        uhci->rh_state = UHCI_RH_RESET;
        uhci->is_stopped = UHCI_IS_STOPPED;
        uhci_to_hcd(uhci)->state = HC_STATE_HALT;
+       uhci_to_hcd(uhci)->poll_rh = 0;
 }
 
 /*
 {
        reset_hc(uhci);
        uhci->hc_inaccessible = 1;
+       del_timer(&uhci->stall_timer);
 }
 
 /*
 
        uhci->rh_state = new_state;
        uhci->is_stopped = UHCI_IS_STOPPED;
-       uhci->resume_detect = 0;
+       del_timer(&uhci->stall_timer);
+       uhci_to_hcd(uhci)->poll_rh = !int_enable;
 
        uhci_scan_schedule(uhci, NULL);
 }
 
 static void start_rh(struct uhci_hcd *uhci)
 {
-       uhci->rh_state = UHCI_RH_RUNNING;
        uhci->is_stopped = 0;
        smp_wmb();
 
        outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
                        uhci->io_addr + USBINTR);
        mb();
+       uhci->rh_state = UHCI_RH_RUNNING;
+       uhci_to_hcd(uhci)->poll_rh = 1;
+       restart_timer(uhci);
 }
 
 static void wakeup_rh(struct uhci_hcd *uhci)
        }
 
        start_rh(uhci);
-}
-
-static void rh_state_transitions(struct uhci_hcd *uhci)
-{
-       switch (uhci->rh_state) {
-           case UHCI_RH_RUNNING:
-               /* are any devices attached? */
-               if (!any_ports_active(uhci)) {
-                       uhci->rh_state = UHCI_RH_RUNNING_NODEVS;
-                       uhci->auto_stop_time = jiffies + HZ;
-               }
-               break;
 
-           case UHCI_RH_RUNNING_NODEVS:
-               /* auto-stop if nothing connected for 1 second */
-               if (any_ports_active(uhci))
-                       uhci->rh_state = UHCI_RH_RUNNING;
-               else if (time_after_eq(jiffies, uhci->auto_stop_time))
-                       suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
-               break;
-
-           case UHCI_RH_AUTO_STOPPED:
-               /* wakeup if requested by a device */
-               if (uhci->resume_detect)
-                       wakeup_rh(uhci);
-               break;
-
-           default:
-               break;
-       }
+       /* Restart root hub polling */
+       mod_timer(&uhci_to_hcd(uhci)->rh_timer, jiffies);
 }
 
 static void stall_callback(unsigned long _uhci)
        uhci_scan_schedule(uhci, NULL);
        check_fsbr(uhci);
 
-       /* Poll for and perform state transitions */
-       if (!uhci->hc_inaccessible) {
-               rh_state_transitions(uhci);
-               if (uhci->suspended_ports)
-                       uhci_check_ports(uhci);
-       }
-
-       restart_timer(uhci);
+       if (!uhci->is_stopped)
+               restart_timer(uhci);
        spin_unlock_irqrestore(&uhci->lock, flags);
 }
 
        }
 
        if (status & USBSTS_RD)
-               uhci->resume_detect = 1;
+               usb_hcd_poll_rh_status(hcd);
 
        spin_lock_irqsave(&uhci->lock, flags);
        uhci_scan_schedule(uhci, regs);
        struct dentry *dentry;
 
        io_size = (unsigned) hcd->rsrc_len;
+       hcd->uses_new_polling = 1;
        if (pci_find_capability(to_pci_dev(uhci_dev(uhci)), PCI_CAP_ID_PM))
                hcd->can_wakeup = 1;            /* Assume it supports PME# */
 
        configure_hc(uhci);
        start_rh(uhci);
 
-       restart_timer(uhci);
-
        udev->speed = USB_SPEED_FULL;
 
        if (usb_hcd_register_root_hub(udev, hcd) != 0) {
  * error exits:
  */
 err_start_root_hub:
-       del_timer_sync(&uhci->stall_timer);
        reset_hc(uhci);
+       del_timer_sync(&uhci->stall_timer);
 
 err_alloc_skelqh:
        for (i = 0; i < UHCI_NUM_SKELQH; i++)
 {
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
-       del_timer_sync(&uhci->stall_timer);
-
        spin_lock_irq(&uhci->lock);
        reset_hc(uhci);
        uhci_scan_schedule(uhci, NULL);
        spin_unlock_irq(&uhci->lock);
-       
+
+       del_timer_sync(&uhci->stall_timer);
        release_uhci(uhci);
 }
 
 
 done:
        spin_unlock_irq(&uhci->lock);
+       if (rc == 0)
+               del_timer_sync(&hcd->rh_timer);
        return rc;
 }
 
                suspend_rh(uhci, UHCI_RH_SUSPENDED);
 
        spin_unlock_irq(&uhci->lock);
+
+       if (hcd->poll_rh)
+               usb_hcd_poll_rh_status(hcd);
        return 0;
 }
 #endif
 
  * driver learns to autosuspend.)
  */
 enum uhci_rh_state {
-       /* In the next 4 states the HC must be halted */
-       UHCI_RH_RESET,                  /* These two must come first */
+       /* In the following states the HC must be halted.
+        * These two must come first */
+       UHCI_RH_RESET,
        UHCI_RH_SUSPENDED,
 
        UHCI_RH_AUTO_STOPPED,
        UHCI_RH_RESUMING,
 
-       /* In the next state the HC changes from running to halted, so it
-        * can legally appear either way */
+       /* In this state the HC changes from running to halted,
+        * so it can legally appear either way. */
        UHCI_RH_SUSPENDING,
 
-       /* In the next two states it's an error if the HC is halted.
+       /* In the following states it's an error if the HC is halted.
         * These two must come last */
        UHCI_RH_RUNNING,                /* The normal state */
        UHCI_RH_RUNNING_NODEVS,         /* Running with no devices attached */
 
        unsigned int scan_in_progress:1;        /* Schedule scan is running */
        unsigned int need_rescan:1;             /* Redo the schedule scan */
-       unsigned int resume_detect:1;           /* Need a Global Resume */
        unsigned int hc_inaccessible:1;         /* HC is suspended or dead */
 
        /* Support for port suspend/resume/reset */
 
        return 0;
 }
 
-static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
+static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
 {
-       struct uhci_hcd *uhci = hcd_to_uhci(hcd);
        int port;
 
-       if (uhci->hc_inaccessible)
-               return 0;
-
        *buf = 0;
        for (port = 0; port < uhci->rh_numports; ++port) {
                if ((inw(uhci->io_addr + USBPORTSC1 + port * 2) & RWC_BITS) ||
                                test_bit(port, &uhci->port_c_suspend))
                        *buf |= (1 << (port + 1));
        }
-       if (*buf && uhci->is_stopped)
-               uhci->resume_detect = 1;
        return !!*buf;
 }
 
                                set_bit(port, &uhci->resuming_ports);
                                uhci->ports_timeout = jiffies +
                                                msecs_to_jiffies(20);
+
+                               /* Make sure we see the port again
+                                * after the resuming period is over. */
+                               mod_timer(&uhci_to_hcd(uhci)->rh_timer,
+                                               uhci->ports_timeout);
                        } else if (time_after_eq(jiffies,
                                                uhci->ports_timeout)) {
                                uhci_finish_suspend(uhci, port, port_addr);
        }
 }
 
+static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf)
+{
+       struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+       unsigned long flags;
+       int status;
+
+       spin_lock_irqsave(&uhci->lock, flags);
+       if (uhci->hc_inaccessible) {
+               status = 0;
+               goto done;
+       }
+
+       uhci_check_ports(uhci);
+       status = get_hub_status_data(uhci, buf);
+
+       switch (uhci->rh_state) {
+           case UHCI_RH_SUSPENDING:
+           case UHCI_RH_SUSPENDED:
+               /* if port change, ask to be resumed */
+               if (status)
+                       usb_hcd_resume_root_hub(hcd);
+               break;
+
+           case UHCI_RH_AUTO_STOPPED:
+               /* if port change, auto start */
+               if (status)
+                       wakeup_rh(uhci);
+               break;
+
+           case UHCI_RH_RUNNING:
+               /* are any devices attached? */
+               if (!any_ports_active(uhci)) {
+                       uhci->rh_state = UHCI_RH_RUNNING_NODEVS;
+                       uhci->auto_stop_time = jiffies + HZ;
+               }
+               break;
+
+           case UHCI_RH_RUNNING_NODEVS:
+               /* auto-stop if nothing connected for 1 second */
+               if (any_ports_active(uhci))
+                       uhci->rh_state = UHCI_RH_RUNNING;
+               else if (time_after_eq(jiffies, uhci->auto_stop_time))
+                       suspend_rh(uhci, UHCI_RH_AUTO_STOPPED);
+               break;
+
+           default:
+               break;
+       }
+
+done:
+       spin_unlock_irqrestore(&uhci->lock, flags);
+       return status;
+}
+
 /* size of returned buffer is part of USB spec */
 static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        u16 wIndex, char *buf, u16 wLength)