USB - Fix polling code
authorMatthew Dillon <dillon@apollo.backplane.com>
Mon, 8 Jun 2009 18:46:43 +0000 (11:46 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Mon, 8 Jun 2009 18:46:43 +0000 (11:46 -0700)
The polling code now calls the intr function instead of trying
to optimize/shortcut the pending-interrupt test.  There are
additional conditions which need action which the test was
not covering.

The polling code now calls the softintr function as well,
as it may be non-operational when the polling code
is being used.

sys/bus/usb/ehci.c
sys/bus/usb/ohci.c
sys/bus/usb/uhci.c

index 628d64c..39e92b4 100644 (file)
@@ -323,6 +323,8 @@ ehci_init(ehci_softc_t *sc)
        vers = EREAD2(sc, EHCI_HCIVERSION);
        device_printf(sc->sc_bus.bdev,
            "EHCI version %x.%x\n", vers >> 8, vers & 0xff);
+       /* Disable all interrupts */
+       EOWRITE4(sc, EHCI_USBINTR, 0);
 
        sparams = EREAD4(sc, EHCI_HCSPARAMS);
        DPRINTF(("ehci_init: sparams=0x%x\n", sparams));
@@ -843,9 +845,10 @@ ehci_poll(struct usbd_bus *bus)
                last = new;
        }
 #endif
-
-       if (EOREAD4(sc, EHCI_USBSTS) & sc->sc_eintrs)
-               ehci_intr1(sc);
+       crit_enter();
+       ehci_intr1(sc);
+       ehci_softintr(sc);
+       crit_exit();
 }
 
 int
index 67362a8..23116eb 100644 (file)
@@ -645,6 +645,12 @@ ohci_init(ohci_softc_t *sc)
            OHCI_REV_HI(rev), OHCI_REV_LO(rev),
            OHCI_REV_LEGACY(rev) ? ", legacy support" : "");
 
+       /*
+        * Make sure all interrupts are disabled before we start messing
+        * with things.
+        */
+       OWRITE4(sc, OHCI_INTERRUPT_DISABLE, -1);
+
        if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) {
                device_printf(sc->sc_bus.bdev, "unsupported OHCI revision\n");
                sc->sc_bus.usbrev = USBREV_UNKNOWN;
@@ -832,9 +838,8 @@ ohci_controller_init(ohci_softc_t *sc)
        OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0));
        OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr);
        OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr);
-       /* disable all interrupts and then switch on all desired interrupts */
+       /* disable all interrupts */
        OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
-       OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE);
        /* switch on desired functional features */
        ctl = OREAD4(sc, OHCI_CONTROL);
        ctl &= ~(OHCI_CBSR_MASK | OHCI_LES | OHCI_HCFS_MASK | OHCI_IR);
@@ -871,6 +876,11 @@ ohci_controller_init(ohci_softc_t *sc)
                sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A));
        }
 
+       /*
+        * Enable desired interrupts
+        */
+       OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE);
+
 #ifdef USB_DEBUG
        if (ohcidebug > 5)
                ohci_dumpregs(sc);
@@ -1117,8 +1127,9 @@ ohci_intr1(ohci_softc_t *sc)
                        done &= ~OHCI_DONE_INTRS;
                }
                sc->sc_hcca->hcca_done_head = 0;
-       } else
+       } else {
                intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & ~OHCI_WDH;
+       }
 
        if (intrs == 0)         /* nothing to be done (PCI shared interrupt) */
                return (0);
@@ -1621,15 +1632,17 @@ ohci_poll(struct usbd_bus *bus)
 #ifdef USB_DEBUG
        static int last;
        int new;
+
        new = OREAD4(sc, OHCI_INTERRUPT_STATUS);
        if (new != last) {
                DPRINTFN(10,("ohci_poll: intrs=0x%04x\n", new));
                last = new;
        }
 #endif
-
-       if (OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs)
-               ohci_intr1(sc);
+       crit_enter();
+       ohci_intr1(sc);
+       ohci_softintr(sc);
+       crit_exit();
 }
 
 usbd_status
index 8776797..cd7fb3f 100644 (file)
@@ -1483,8 +1483,10 @@ uhci_poll(struct usbd_bus *bus)
 {
        uhci_softc_t *sc = (uhci_softc_t *)bus;
 
-       if (UREAD2(sc, UHCI_STS) & UHCI_STS_ALLINTRS)
-               uhci_intr1(sc);
+        crit_enter();
+        uhci_intr1(sc);
+        uhci_softintr(sc);
+        crit_exit();
 }
 
 void