Skip to content

Commit

Permalink
USB: ehci-dbgp: Execute early BIOS hand off
Browse files Browse the repository at this point in the history
The PCI quirk code executes a BIOS hand off to obtain full control of
the EHCI host controller, the self contained ehci-dbgp driver must do
the same thing using the early PCI API, else the BIOS can cause a
fatal fault.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: dbrownell@users.sourceforge.net
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Jason Wessel authored and Greg Kroah-Hartman committed Sep 23, 2009
1 parent 87a5d15 commit 093344e
Showing 1 changed file with 49 additions and 0 deletions.
49 changes: 49 additions & 0 deletions drivers/usb/early/ehci-dbgp.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,53 @@ static void __init detect_set_debug_port(void)
}
}

/* The code in early_ehci_bios_handoff() is derived from the usb pci
* quirk initialization, but altered so as to use the early PCI
* routines. */
#define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */
#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */
static void __init early_ehci_bios_handoff(void)
{
u32 hcc_params = readl(&ehci_caps->hcc_params);
int offset = (hcc_params >> 8) & 0xff;
u32 cap;
int msec;

if (!offset)
return;

cap = read_pci_config(ehci_dev.bus, ehci_dev.slot,
ehci_dev.func, offset);
dbgp_printk("dbgp: ehci BIOS state %08x\n", cap);

if ((cap & 0xff) == 1 && (cap & EHCI_USBLEGSUP_BIOS)) {
dbgp_printk("dbgp: BIOS handoff\n");
write_pci_config_byte(ehci_dev.bus, ehci_dev.slot,
ehci_dev.func, offset + 3, 1);
}

/* if boot firmware now owns EHCI, spin till it hands it over. */
msec = 1000;
while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
mdelay(10);
msec -= 10;
cap = read_pci_config(ehci_dev.bus, ehci_dev.slot,
ehci_dev.func, offset);
}

if (cap & EHCI_USBLEGSUP_BIOS) {
/* well, possibly buggy BIOS... try to shut it down,
* and hope nothing goes too wrong */
dbgp_printk("dbgp: BIOS handoff failed: %08x\n", cap);
write_pci_config_byte(ehci_dev.bus, ehci_dev.slot,
ehci_dev.func, offset + 2, 0);
}

/* just in case, always disable EHCI SMIs */
write_pci_config_byte(ehci_dev.bus, ehci_dev.slot, ehci_dev.func,
offset + EHCI_USBLEGCTLSTS, 0);
}

static int __init ehci_setup(void)
{
struct usb_debug_descriptor dbgp_desc;
Expand All @@ -446,6 +493,8 @@ static int __init ehci_setup(void)
int port_map_tried;
int playtimes = 3;

early_ehci_bios_handoff();

try_next_time:
port_map_tried = 0;

Expand Down

0 comments on commit 093344e

Please sign in to comment.