mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-22 17:01:14 +00:00
USB: ehci-dbgp: Execute early BIOS hand off
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>
This commit is contained in:
parent
87a5d15154
commit
093344e136
1 changed files with 49 additions and 0 deletions
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue