Author: thompsa
Date: Tue Feb  9 00:38:40 2010
New Revision: 203693
URL: http://svn.freebsd.org/changeset/base/203693

Log:
  Disable the use of the IAAD usb doorbell on NVidia controllers as it can cause
  the hardware to stall.
  
  Submitted by: Hans Petter Selasky

Modified:
  head/sys/dev/usb/controller/ehci.c
  head/sys/dev/usb/controller/ehci.h
  head/sys/dev/usb/controller/ehci_pci.c

Modified: head/sys/dev/usb/controller/ehci.c
==============================================================================
--- head/sys/dev/usb/controller/ehci.c  Mon Feb  8 23:30:28 2010        
(r203692)
+++ head/sys/dev/usb/controller/ehci.c  Tue Feb  9 00:38:40 2010        
(r203693)
@@ -92,15 +92,23 @@ __FBSDID("$FreeBSD$");
 #if USB_DEBUG
 static int ehcidebug = 0;
 static int ehcinohighspeed = 0;
+static int ehciiaadbug = 0;
+static int ehcilostintrbug = 0;
 
 SYSCTL_NODE(_hw_usb, OID_AUTO, ehci, CTLFLAG_RW, 0, "USB ehci");
 SYSCTL_INT(_hw_usb_ehci, OID_AUTO, debug, CTLFLAG_RW,
     &ehcidebug, 0, "Debug level");
 SYSCTL_INT(_hw_usb_ehci, OID_AUTO, no_hs, CTLFLAG_RW,
     &ehcinohighspeed, 0, "Disable High Speed USB");
+SYSCTL_INT(_hw_usb_ehci, OID_AUTO, iaadbug, CTLFLAG_RW,
+    &ehciiaadbug, 0, "Enable doorbell bug workaround");
+SYSCTL_INT(_hw_usb_ehci, OID_AUTO, lostintrbug, CTLFLAG_RW,
+    &ehcilostintrbug, 0, "Enable lost interrupt bug workaround");
 
 TUNABLE_INT("hw.usb.ehci.debug", &ehcidebug);
 TUNABLE_INT("hw.usb.ehci.no_hs", &ehcinohighspeed);
+TUNABLE_INT("hw.usb.ehci.iaadbug", &ehciiaadbug);
+TUNABLE_INT("hw.usb.ehci.lostintrbug", &ehcilostintrbug);
 
 static void ehci_dump_regs(ehci_softc_t *sc);
 static void ehci_dump_sqh(ehci_softc_t *sc, ehci_qh_t *sqh);
@@ -251,6 +259,10 @@ ehci_init(ehci_softc_t *sc)
        usb_callout_init_mtx(&sc->sc_tmo_poll, &sc->sc_bus.bus_mtx, 0);
 
 #if USB_DEBUG
+       if (ehciiaadbug)
+               sc->sc_flags |= EHCI_SCFLG_IAADBUG;
+       if (ehcilostintrbug)
+               sc->sc_flags |= EHCI_SCFLG_LOSTINTRBUG;
        if (ehcidebug > 2) {
                ehci_dump_regs(sc);
        }
@@ -2280,6 +2292,13 @@ ehci_device_bulk_start(struct usb_xfer *
        /* put transfer on interrupt queue */
        ehci_transfer_intr_enqueue(xfer);
 
+       /* 
+        * XXX Certain nVidia chipsets choke when using the IAAD
+        * feature too frequently.
+        */
+       if (sc->sc_flags & EHCI_SCFLG_IAADBUG)
+               return;
+
        /* XXX Performance quirk: Some Host Controllers have a too low
         * interrupt rate. Issue an IAAD to stimulate the Host
         * Controller after queueing the BULK transfer.

Modified: head/sys/dev/usb/controller/ehci.h
==============================================================================
--- head/sys/dev/usb/controller/ehci.h  Mon Feb  8 23:30:28 2010        
(r203692)
+++ head/sys/dev/usb/controller/ehci.h  Tue Feb  9 00:38:40 2010        
(r203693)
@@ -350,6 +350,7 @@ typedef struct ehci_softc {
 #define        EHCI_SCFLG_BIGEMMIO     0x0010  /* big-endian byte order MMIO */
 #define        EHCI_SCFLG_TT           0x0020  /* transaction translator 
present */
 #define        EHCI_SCFLG_LOSTINTRBUG  0x0040  /* workaround for VIA / ATI 
chipsets */
+#define        EHCI_SCFLG_IAADBUG      0x0080  /* workaround for nVidia 
chipsets */
 
        uint8_t sc_offs;                /* offset to operational registers */
        uint8_t sc_doorbell_disable;    /* set on doorbell failure */

Modified: head/sys/dev/usb/controller/ehci_pci.c
==============================================================================
--- head/sys/dev/usb/controller/ehci_pci.c      Mon Feb  8 23:30:28 2010        
(r203692)
+++ head/sys/dev/usb/controller/ehci_pci.c      Tue Feb  9 00:38:40 2010        
(r203693)
@@ -466,6 +466,19 @@ ehci_pci_attach(device_t self)
                break;
        }
 
+       /* Doorbell feature workaround */
+       switch (pci_get_vendor(self)) {
+       case PCI_EHCI_VENDORID_NVIDIA:
+       case PCI_EHCI_VENDORID_NVIDIA2:
+               sc->sc_flags |= EHCI_SCFLG_IAADBUG;
+               if (bootverbose)
+                       device_printf(self,
+                           "Doorbell workaround enabled\n");
+               break;
+       default:
+               break;
+       }
+
        err = ehci_init(sc);
        if (!err) {
                err = device_probe_and_attach(sc->sc_bus.bdev);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to