On Tue, Jun 23, 2009 at 06:17:37AM -0400, Brad wrote:
> On Tue, Jun 23, 2009 at 05:06:19AM -0400, Brad wrote:
> > The following diff for the ATI SB600 / SB700 chipsets needs testing
> > with the EHCI controller. There is a temporary printf to see when the
> > workaround is being applied.
> > 
> > Attached patch is intended to avoid USB subsystem hang symptoms on
> > all ATI SB600 revisions and ATI SB700 south bridge revisions A12 and A13.
> > 
> > The USB subsystem hang symptom is observed when the system has multiple
> > USB devices connected to it. In some cases a USB hub may be required to
> > observe this symptom.
> > 
> > This patch works around the problem by correcting the internal register
> > setting that will help by changing the behavior of the internal logic to
> > avoid the USB subsystem hang issue. The change in the behavior of the
> > logic does not impact the normal operation of the USB subsystem.
> > 
> > From NetBSD (also in Linux)
> 
> Ok well as kettenis pointed out the previous diff was a bit overkill
> for infrastructure to do the job.. this is much simpler.
 
And a little simpler over the second rev..


Index: ehci_pci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/ehci_pci.c,v
retrieving revision 1.15
diff -u -p -r1.15 ehci_pci.c
--- ehci_pci.c  29 Mar 2009 21:53:52 -0000      1.15
+++ ehci_pci.c  23 Jun 2009 11:24:17 -0000
@@ -65,6 +65,11 @@ struct ehci_pci_softc {
        void                    *sc_ih;         /* interrupt vectoring */
 };
 
+int ehci_sb700_match(struct pci_attach_args *pa);
+
+#define EHCI_SBx00_WORKAROUND_REG      0x50
+#define EHCI_SBx00_WORKAROUND_ENABLE   (1 << 3)
+
 int    ehci_pci_match(struct device *, void *, void *);
 void   ehci_pci_attach(struct device *, struct device *, void *);
 int    ehci_pci_detach(struct device *, int);
@@ -77,7 +82,6 @@ struct cfattach ehci_pci_ca = {
        ehci_pci_detach, ehci_activate
 };
 
-
 int
 ehci_pci_match(struct device *parent, void *match, void *aux)
 {
@@ -122,6 +126,21 @@ ehci_pci_attach(struct device *parent, s
        DPRINTF(("%s: offs=%d\n", devname, sc->sc.sc_offs));
        EOWRITE2(&sc->sc, EHCI_USBINTR, 0);
 
+       /* Handle quirks */
+       if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ATI &&
+           ((PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SB600_EHCI ||
+             (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SB700_EHCI &&
+              pci_find_device(NULL, ehci_sb700_match))))) {
+               pcireg_t value;
+
+               printf(", applying ATI SB600/SB700 workaround");
+               value = pci_conf_read(sc->sc_pc, sc->sc_tag,
+                   EHCI_SBx00_WORKAROUND_REG);
+               pci_conf_write(sc->sc_pc, sc->sc_tag,
+                   EHCI_SBx00_WORKAROUND_REG, value |
+                   EHCI_SBx00_WORKAROUND_ENABLE);
+       }
+
        /* Map and establish the interrupt. */
        if (pci_intr_map(pa, &ih)) {
                printf(": couldn't map interrupt\n");
@@ -270,4 +289,16 @@ ehci_pci_shutdown(void *v)
        /* best not to do this anymore; BIOS SMM spins? */
        ehci_pci_givecontroller(sc);
 #endif
+}
+
+int
+ehci_sb700_match(struct pci_attach_args *pa)
+{
+       if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ATI &&
+           PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ATI_SBX00_SMB &&
+           (PCI_REVISION(pa->pa_class) == 0x3a ||
+            PCI_REVISION(pa->pa_class) == 0x3b))
+               return (1);
+
+       return (0);
 }

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

Reply via email to