On Mon, Jun 29, 2009 at 03:46:35PM -0400, Brad wrote:
> The following diff adds a workaround for an issue with the VIA VT6202
> EHCI controller hogging the PCI bus and causing poor performance for
> IDE and possibly other devices in the system.
> 
> Please test if your system has a VIA VT6202 EHCI controller and
> provide a dmesg. If the workaround is being applied for the
> chipset you have then a message will be printed (this is temporary
> only to verify it is being applied for the appropriate revision
> of the chipset).
> 
> 
> >From Linux
> 
> 

I tried out this patch, and found that the appropriate revision chip
is found in the thecus 2100 system (armish port). Initial testing showed
no performance difference. 

However, I looked at the diff more closely and found that it was wrong,
the original linux code would read/write one byte, however the OpenBSD
interface does word (32bit) reads and writes, howeve this register is
then misaligned.

After changing the code to do 32 bit accesses and to set the correct bit
in the little endian 32 bit register, the system saw a signficant performance
difference. dd if=/dev/zero of=file bs=1m saw a 10% speedup, and ftp
a file from the local network saw a 7% speedup.

Arm has a smaller cache that other systems, so may be affected by a
busy memory bus more than other platforms.

Working, tested diff (for armish).

I have not verified if this diff makes sense on big endian platforms yet.

Index: ehci_pci.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/ehci_pci.c,v
retrieving revision 1.16
diff -u -u -r1.16 ehci_pci.c
--- ehci_pci.c  25 Jun 2009 01:01:44 -0000      1.16
+++ ehci_pci.c  30 Jun 2009 02:56:22 -0000
@@ -69,6 +69,7 @@
 
 #define EHCI_SBx00_WORKAROUND_REG      0x50
 #define EHCI_SBx00_WORKAROUND_ENABLE   (1 << 3)
+#define EHCI_VT6202_WORKAROUND_REG     0x48
 
 int    ehci_pci_match(struct device *, void *, void *);
 void   ehci_pci_attach(struct device *, struct device *, void *);
@@ -127,18 +128,41 @@
        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;
-
-               /* apply the 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);
+       switch (PCI_VENDOR(pa->pa_id)) {
+       case PCI_VENDOR_ATI:
+               if (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;
+
+                       /* apply the 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);
+               }
+               break;
+
+       case PCI_VENDOR_VIATECH:
+               if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_VIATECH_VT6202 &&
+                   (PCI_REVISION(pa->pa_class) & 0xf0) == 0x60) {
+                       pcireg_t value;
+
+                       /*
+                        * The VT6202 defaults to a 1 usec EHCI sleep time
+                        * which hogs the PCI bus *badly*. Setting bit 5 of
+                        * the register makes that sleep time use the 
conventional
+                        * 10 usec.
+                        */
+                       value = pci_conf_read(sc->sc_pc, sc->sc_tag,
+                           EHCI_VT6202_WORKAROUND_REG);
+                       if ((value & 0x20000000) == 0)
+                               printf(", applying VIA VT6202 workaround");
+                       pci_conf_write(sc->sc_pc, sc->sc_tag,
+                           EHCI_VT6202_WORKAROUND_REG, value | 0x20000000);
+               }
+               break;
        }
 
        /* Map and establish the interrupt. */
Dale Rahn                               dr...@dalerahn.com

Reply via email to