ehci: workaround for pci quirk timeout on ExoPC
authorAndy Ross <andy.ross@windriver.com>
Wed, 11 May 2011 22:52:38 +0000 (15:52 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 12 May 2011 16:42:01 +0000 (09:42 -0700)
The BIOS handoff for the unused EHCI controller on the ExoPC tablet
hangs for 90 seconds on boot.  Detect that device, skip negotiation
and force the handoff.

Signed-off-by: Andy Ross <andy.ross@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/pci-quirks.c

index e300509faa61119cc59b17daf46a3ceea95a8ec4..f16c59d5f48702cb4abb4c7bab1cc6e811ffda19 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 #include "pci-quirks.h"
 #include "xhci-ext-caps.h"
 
@@ -507,9 +508,20 @@ static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
                                        void __iomem *op_reg_base,
                                        u32 cap, u8 offset)
 {
-       int msec, tried_handoff = 0;
+       int try_handoff = 1, tried_handoff = 0;
+
+       /* The Pegatron Lucid (ExoPC) tablet sporadically waits for 90
+        * seconds trying the handoff on its unused controller.  Skip
+        * it. */
+       if (pdev->vendor == 0x8086 && pdev->device == 0x283a) {
+               const char *dmi_bn = dmi_get_system_info(DMI_BOARD_NAME);
+               const char *dmi_bv = dmi_get_system_info(DMI_BIOS_VERSION);
+               if (dmi_bn && !strcmp(dmi_bn, "EXOPG06411") &&
+                   dmi_bv && !strcmp(dmi_bv, "Lucid-CE-133"))
+                       try_handoff = 0;
+       }
 
-       if (cap & EHCI_USBLEGSUP_BIOS) {
+       if (try_handoff && (cap & EHCI_USBLEGSUP_BIOS)) {
                dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n");
 
 #if 0
@@ -534,20 +546,23 @@ static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
        }
 
        /* if boot firmware now owns EHCI, spin till it hands it over. */
-       msec = 1000;
-       while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
-               tried_handoff = 1;
-               msleep(10);
-               msec -= 10;
-               pci_read_config_dword(pdev, offset, &cap);
+       if (try_handoff) {
+               int msec = 1000;
+               while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
+                       tried_handoff = 1;
+                       msleep(10);
+                       msec -= 10;
+                       pci_read_config_dword(pdev, offset, &cap);
+               }
        }
 
        if (cap & EHCI_USBLEGSUP_BIOS) {
                /* well, possibly buggy BIOS... try to shut it down,
                 * and hope nothing goes too wrong
                 */
-               dev_warn(&pdev->dev, "EHCI: BIOS handoff failed"
-                        " (BIOS bug?) %08x\n", cap);
+               if (try_handoff)
+                       dev_warn(&pdev->dev, "EHCI: BIOS handoff failed"
+                                " (BIOS bug?) %08x\n", cap);
                pci_write_config_byte(pdev, offset + 2, 0);
        }