summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-02-13 14:53:06 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-03-09 10:50:21 -0800
commit5edd24258c5eae0a5cadc612ea1d6e13ec54e536 (patch)
tree17f4532906fb53c016aee4d1f803fe8bdef6afde /drivers
parent849fa1fbe0247239aa774397665527fe6a1abd89 (diff)
EHCI: turn off remote wakeup during shutdown
This patch (as850b) disables remote wakeup (and everything else!) on all EHCI ports when the shutdown() method is called. If remote wakeup is left active then some systems will reboot instead of powering off. This fixes Bugzilla #7828. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/ehci-hcd.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 025d33313681..6e9fdd60c808 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -296,6 +296,18 @@ static void ehci_watchdog (unsigned long param)
spin_unlock_irqrestore (&ehci->lock, flags);
}
+/* On some systems, leaving remote wakeup enabled prevents system shutdown.
+ * The firmware seems to think that powering off is a wakeup event!
+ * This routine turns off remote wakeup and everything else, on all ports.
+ */
+static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
+{
+ int port = HCS_N_PORTS(ehci->hcs_params);
+
+ while (port--)
+ writel(PORT_RWC_BITS, &ehci->regs->port_status[port]);
+}
+
/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
* This forcibly disables dma and IRQs, helping kexec and other cases
* where the next system software may expect clean state.
@@ -307,9 +319,13 @@ ehci_shutdown (struct usb_hcd *hcd)
ehci = hcd_to_ehci (hcd);
(void) ehci_halt (ehci);
+ ehci_turn_off_all_ports(ehci);
/* make BIOS/etc use companion controller during reboot */
writel (0, &ehci->regs->configured_flag);
+
+ /* unblock posted writes */
+ readl(&ehci->regs->configured_flag);
}
static void ehci_port_power (struct ehci_hcd *ehci, int is_on)