Commit 3610ea53 authored by Andy Ross's avatar Andy Ross Committed by Greg Kroah-Hartman

ehci: workaround for pci quirk timeout on ExoPC

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: default avatarAndy Ross <andy.ross@windriver.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 5c853013
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/dmi.h>
#include "pci-quirks.h" #include "pci-quirks.h"
#include "xhci-ext-caps.h" #include "xhci-ext-caps.h"
...@@ -507,9 +508,20 @@ static void __devinit ehci_bios_handoff(struct pci_dev *pdev, ...@@ -507,9 +508,20 @@ static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
void __iomem *op_reg_base, void __iomem *op_reg_base,
u32 cap, u8 offset) u32 cap, u8 offset)
{ {
int msec, tried_handoff = 0; int try_handoff = 1, tried_handoff = 0;
if (cap & EHCI_USBLEGSUP_BIOS) { /* 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 (try_handoff && (cap & EHCI_USBLEGSUP_BIOS)) {
dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n"); dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n");
#if 0 #if 0
...@@ -534,18 +546,21 @@ static void __devinit ehci_bios_handoff(struct pci_dev *pdev, ...@@ -534,18 +546,21 @@ static void __devinit ehci_bios_handoff(struct pci_dev *pdev,
} }
/* if boot firmware now owns EHCI, spin till it hands it over. */ /* if boot firmware now owns EHCI, spin till it hands it over. */
msec = 1000; if (try_handoff) {
int msec = 1000;
while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
tried_handoff = 1; tried_handoff = 1;
msleep(10); msleep(10);
msec -= 10; msec -= 10;
pci_read_config_dword(pdev, offset, &cap); pci_read_config_dword(pdev, offset, &cap);
} }
}
if (cap & EHCI_USBLEGSUP_BIOS) { if (cap & EHCI_USBLEGSUP_BIOS) {
/* well, possibly buggy BIOS... try to shut it down, /* well, possibly buggy BIOS... try to shut it down,
* and hope nothing goes too wrong * and hope nothing goes too wrong
*/ */
if (try_handoff)
dev_warn(&pdev->dev, "EHCI: BIOS handoff failed" dev_warn(&pdev->dev, "EHCI: BIOS handoff failed"
" (BIOS bug?) %08x\n", cap); " (BIOS bug?) %08x\n", cap);
pci_write_config_byte(pdev, offset + 2, 0); pci_write_config_byte(pdev, offset + 2, 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment