USB: ehci: stop vt6212 bus hogging
authorRene Herman <rene.herman@gmail.com>
Thu, 20 Mar 2008 07:58:16 +0000 (00:58 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 25 Mar 2008 05:26:15 +0000 (22:26 -0700)
The VIA VT6212 defaults to only waiting 1us between passes over EHCI's
async ring, which hammers PCI badly ... and by preventing other devices
from accessing the bus, causes problems like drops in IDE throughput,
a problem that's been bugging users of those chips for several years.

A (partial) datasheet for this chip eventually turned up, letting us
see how to make it use a VIA-specific register to switch over to the
the normal 10us value instead, as suggested by the EHCI specification
Solution noted by Lev A. Melnikovsky.

It's not clear whether this register exists on other VIA chips; we
know that it's ineffective on the vt8235.  So this patch only applies
to chips that seem to be incarnations of the (discrete) vt6212.

Signed-off-by: Rene Herman <rene.herman@gmail.com>
Tested-by: Lev A. Melnikovsky <melnikovsky@mail.ru>
Tested-by: Alessandro Suardi <alessandro.suardi@gmail.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/ehci-pci.c

index 3ba01664f82154b00bef518eea7c3e809566f63b..72ccd56e36dd46665712ea26d5944312f8a10635 100644 (file)
@@ -152,6 +152,20 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                        break;
                }
                break;
+       case PCI_VENDOR_ID_VIA:
+               if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x60) {
+                       u8 tmp;
+
+                       /* The VT6212 defaults to a 1 usec EHCI sleep time which
+                        * hogs the PCI bus *badly*. Setting bit 5 of 0x4B makes
+                        * that sleep time use the conventional 10 usec.
+                        */
+                       pci_read_config_byte(pdev, 0x4b, &tmp);
+                       if (tmp & 0x20)
+                               break;
+                       pci_write_config_byte(pdev, 0x4b, tmp | 0x20);
+               }
+               break;
        }
 
        ehci_reset(ehci);