From: Jason Wessel <jason.wessel@xxxxxxxxxxxxx> 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@xxxxxxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxx> Cc: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> Cc: dbrownell@xxxxxxxxxxxxxxxxxxxxx Cc: Yinghai Lu <yinghai@xxxxxxxxxx> Cc: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx> --- drivers/usb/early/ehci-dbgp.c | 49 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 49 insertions(+), 0 deletions(-) diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 8de709a..7deae97 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -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; @@ -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; -- 1.6.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html