From 4fe5354f61cad4c0550285283c83c66c070c198e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 5 Apr 2007 16:06:53 -0400 Subject: [PATCH] EHCI: fix problem with BIOS handoff This patch (as882) fixes a problem with the EHCI BIOS handoff. On my machine, the BIOS configures the controller and the handoff fails, leaving the controller configured. During resume-from-disk, this confuses ehci-hcd into thinking that the controller has not been tampered with. The problem is fixed by turning off the Configured Flag whenever a BIOS handoff is attempted, whether it succeeds or not. Signed-off-by: Alan Stern Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 20861650905e..c225159ca3d3 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -44,6 +44,7 @@ #define EHCI_USBSTS 4 /* status register */ #define EHCI_USBSTS_HALTED (1 << 12) /* HCHalted bit */ #define EHCI_USBINTR 8 /* interrupt register */ +#define EHCI_CONFIGFLAG 0x40 /* configured flag register */ #define EHCI_USBLEGSUP 0 /* legacy support register */ #define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */ #define EHCI_USBLEGSUP_OS (1 << 24) /* OS semaphore */ @@ -216,6 +217,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) u32 hcc_params, val; u8 offset, cap_length; int count = 256/4; + int tried_handoff = 0; if (!mmio_resource_enabled(pdev, 0)) return; @@ -273,6 +275,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) */ msec = 5000; while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { + tried_handoff = 1; msleep(10); msec -= 10; pci_read_config_dword(pdev, offset, &cap); @@ -292,6 +295,12 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, 0); + + /* If the BIOS ever owned the controller then we + * can't expect any power sessions to remain intact. + */ + if (tried_handoff) + writel(0, op_reg_base + EHCI_CONFIGFLAG); break; case 0: /* illegal reserved capability */ cap = 0; -- 2.30.2