+ /* If any port is suspended, we know we can/must resume the HC. */
+ for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; ) {
+ u32 status;
+ port--;
+ status = readl (&ehci->regs->port_status [port]);
+ if (status & PORT_SUSPEND) {
+ down (&hcd->self.root_hub->serialize);
+ retval = ehci_hub_resume (hcd);
+ up (&hcd->self.root_hub->serialize);
+ break;
+ }
+ if ((status & PORT_POWER) == 0)
+ powerup = 1;
+ if (!root->children [port])
+ continue;
+ dbg_port (ehci, __FUNCTION__, port + 1, status);
+ usb_set_device_state (root->children[port],
+ USB_STATE_NOTATTACHED);
+ }
+
+ /* Else reset, to cope with power loss or flush-to-storage
+ * style "resume" having activated BIOS during reboot.
+ */
+ if (port == 0) {
+ (void) ehci_halt (ehci);
+ (void) ehci_reset (ehci);
+ (void) ehci_hc_reset (hcd);
+
+ /* emptying the schedule aborts any urbs */
+ spin_lock_irq (&ehci->lock);
+ if (ehci->reclaim)
+ ehci->reclaim_ready = 1;
+ ehci_work (ehci, NULL);
+ spin_unlock_irq (&ehci->lock);
+
+ /* restart; khubd will disconnect devices */
+ retval = ehci_start (hcd);
+
+ /* here we "know" root ports should always stay powered;
+ * but some controllers may lost all power.
+ */
+ if (powerup) {
+ ehci_dbg (ehci, "...powerup ports...\n");
+ for (port = HCS_N_PORTS (ehci->hcs_params); port > 0; )
+ (void) ehci_hub_control(hcd,
+ SetPortFeature, USB_PORT_FEAT_POWER,
+ port--, NULL, 0);
+ msleep(20);
+ }
+ }
+