usb ehci - Fix machine freezes from shutdown race (missing commit)
authorMatthew Dillon <dillon@apollo.backplane.com>
Wed, 24 Jun 2009 17:28:55 +0000 (10:28 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Wed, 24 Jun 2009 17:28:55 +0000 (10:28 -0700)
EHCI's shutdown code was killing the chipset without first killing the
interrupt, and it was also handing EHCI back to the BIOS without first
waiting for the shutdown reset to complete.  Either can lock the machine

sys/bus/usb/ehci_pci.c

index 4707575..12d1bd9 100644 (file)
@@ -194,12 +194,12 @@ ehci_pci_shutdown(device_t self)
        int err;
 
        err = bus_generic_shutdown(self);
-       if (err)
-               return (err);
-       ehci_shutdown(sc);
-       ehci_pci_givecontroller(self);
+       if (sc->sc_flags & EHCI_SCFLG_DONEINIT) {
+               ehci_shutdown(sc);
+               ehci_pci_givecontroller(self);
+       }
 
-       return 0;
+       return err;
 }
 
 static const char *
@@ -515,6 +515,13 @@ ehci_pci_takecontroller(device_t self)
        }
 }
 
+/*
+ * Return the controller to the BIOS.  Do we really need to do this?
+ *
+ * One thing we do need to do is give the chip reset (from the shutdown)
+ * time to finish before handing anything back.  This fixes a machine
+ * lockup.
+ */
 static void
 ehci_pci_givecontroller(device_t self)
 {
@@ -522,6 +529,7 @@ ehci_pci_givecontroller(device_t self)
        u_int32_t cparams, eec, legsup;
        int eecp;
 
+       DELAY(1000);
        cparams = EREAD4(sc, EHCI_HCCPARAMS);
        for (eecp = EHCI_HCC_EECP(cparams); eecp != 0;
             eecp = EHCI_EECP_NEXT(eec)) {