PM: USB HCDs use PM_EVENT_PRETHAW
authorDavid Brownell <david-b@pacbell.net>
Tue, 15 Aug 2006 06:11:06 +0000 (23:11 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 26 Sep 2006 04:08:37 +0000 (21:08 -0700)
This teaches several USB host controller drivers to treat PRETHAW as a chip
reset since the controller, and all devices connected to it, are no longer in
states compatible with how the snapshotted suspend() left them.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Cc: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/core/hcd-pci.c
drivers/usb/host/ehci-pci.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/sl811-hcd.c
drivers/usb/host/uhci-hcd.c

index 5078fb3375e34e5c573ef86113b81437ffff1d32..fa36391fedd39676b7c9621fcb39539079f50d02 100644 (file)
@@ -281,7 +281,7 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message)
                        (void) usb_hcd_pci_resume (dev);
                }
 
-       } else {
+       } else if (hcd->state != HC_STATE_HALT) {
                dev_dbg (hcd->self.controller, "hcd state %d; not suspended\n",
                        hcd->state);
                WARN_ON(1);
index cadffacd945b9d392ab93a96663b7233865ed918..6967ab71e28281d8330395e14d3bf55af9a9ea84 100644 (file)
@@ -238,6 +238,12 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
        writel (0, &ehci->regs->intr_enable);
        (void)readl(&ehci->regs->intr_enable);
 
+       /* make sure snapshot being resumed re-enumerates everything */
+       if (message.event == PM_EVENT_PRETHAW) {
+               ehci_halt(ehci);
+               ehci_reset(ehci);
+       }
+
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
  bail:
        spin_unlock_irqrestore (&ehci->lock, flags);
index b268537e389eb04a228bab160b00e0f20dabd60d..37e122812b6797ee7a934a0fecd3cd0eaab1406b 100644 (file)
@@ -135,6 +135,11 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message)
        }
        ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
        (void)ohci_readl(ohci, &ohci->regs->intrdisable);
+
+       /* make sure snapshot being resumed re-enumerates everything */
+       if (message.event == PM_EVENT_PRETHAW)
+               ohci_usb_reset(ohci);
+
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
  bail:
        spin_unlock_irqrestore (&ohci->lock, flags);
index fa34092bbcde1e82ac9338d7a2366aea48c2e1d3..9de115d9db2703bad97f57506cf3a9d55d9a106c 100644 (file)
@@ -1783,10 +1783,15 @@ sl811h_suspend(struct platform_device *dev, pm_message_t state)
        struct sl811    *sl811 = hcd_to_sl811(hcd);
        int             retval = 0;
 
-       if (state.event == PM_EVENT_FREEZE)
+       switch (state.event) {
+       case PM_EVENT_FREEZE:
                retval = sl811h_bus_suspend(hcd);
-       else if (state.event == PM_EVENT_SUSPEND)
+               break;
+       case PM_EVENT_SUSPEND:
+       case PM_EVENT_PRETHAW:          /* explicitly discard hw state */
                port_power(sl811, 0);
+               break;
+       }
        if (retval == 0)
                dev->dev.power.power_state = state;
        return retval;
index 4151f618602d13bb801f9f2360d290c898733830..b7402ceb3e93c535f9223548770f193657141b9d 100644 (file)
@@ -734,6 +734,10 @@ static int uhci_suspend(struct usb_hcd *hcd, pm_message_t message)
 
        /* FIXME: Enable non-PME# remote wakeup? */
 
+       /* make sure snapshot being resumed re-enumerates everything */
+       if (message.event == PM_EVENT_PRETHAW)
+               uhci_hc_died(uhci);
+
 done_okay:
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 done: