This patch refactors some shutdown code so it can be shared between
ehci_stop() and ehci_shutdown().

This also fixes a couple potential bugs:
 - ehci_shutdown() was not locking ehci->lock before halting the HC.
 - ehci_shutdown() didn't disable the watchdog and IAA timers.
 - ehci_stop() was resetting the host controller when it may have been
   running, which the EHCI spec says "may result in undefined behavior".

ehci_stop() was calling port_power() to turn off the ports, which waited
20ms after applying the port change.  The msleep was for the case where
the HC might take 20ms to turn the ports on; since we're shutting them
off, we can avoid the msleep and just use ehci_turn_off_ports().

ehci_stop() doesn't need to clear the intr_enable register or revert
ownership of the companion controllers to the BIOS, because the host
controller reset should have done that.  There might be a buggy host
controller that doesn't follow the reset rules, but for now we assume
it's redundant code and remove it.

Signed-off-by: Sarah Sharp <[EMAIL PROTECTED]>
---
 drivers/usb/host/ehci-hcd.c |   41 +++++++++++++++++++++++++----------------
 1 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 4caa6a8..b35285b 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -334,17 +334,13 @@ static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
                                &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.
+/*
+ * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
+ * Should be called with ehci->lock held.
  */
-static void
-ehci_shutdown (struct usb_hcd *hcd)
+static void ehci_silence_controller(struct ehci_hcd *ehci)
 {
-       struct ehci_hcd *ehci;
-
-       ehci = hcd_to_ehci (hcd);
-       (void) ehci_halt (ehci);
+       ehci_halt(ehci);
        ehci_turn_off_all_ports(ehci);
 
        /* make BIOS/etc use companion controller during reboot */
@@ -354,6 +350,22 @@ ehci_shutdown (struct usb_hcd *hcd)
        ehci_readl(ehci, &ehci->regs->configured_flag);
 }
 
+/* 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.
+ */
+static void ehci_shutdown(struct usb_hcd *hcd)
+{
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+       del_timer_sync(&ehci->watchdog);
+       del_timer_sync(&ehci->iaa_watchdog);
+
+       spin_lock_irq(&ehci->lock);
+       ehci_silence_controller(ehci);
+       spin_unlock_irq(&ehci->lock);
+}
+
 static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
 {
        unsigned port;
@@ -404,15 +416,15 @@ static void ehci_work (struct ehci_hcd *ehci)
                timer_action (ehci, TIMER_IO_WATCHDOG);
 }
 
+/*
+ * Called when the ehci_hcd module is removed.
+ */
 static void ehci_stop (struct usb_hcd *hcd)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
 
        ehci_dbg (ehci, "stop\n");
 
-       /* Turn off port power on all root hub ports. */
-       ehci_port_power (ehci, 0);
-
        /* no more interrupts ... */
        del_timer_sync (&ehci->watchdog);
        del_timer_sync(&ehci->iaa_watchdog);
@@ -421,13 +433,10 @@ static void ehci_stop (struct usb_hcd *hcd)
        if (HC_IS_RUNNING (hcd->state))
                ehci_quiesce (ehci);
 
+       ehci_silence_controller(ehci);
        ehci_reset (ehci);
-       ehci_writel(ehci, 0, &ehci->regs->intr_enable);
        spin_unlock_irq(&ehci->lock);
 
-       /* let companion controllers work when we aren't */
-       ehci_writel(ehci, 0, &ehci->regs->configured_flag);
-
        remove_companion_file(ehci);
        remove_debug_files (ehci);
 
-- 
1.5.3.4

-
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to