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