summary refs log tree commit diff
path: root/drivers/usb
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2007-04-05 16:06:53 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-05-22 23:45:48 -0700
commit4fe5354f61cad4c0550285283c83c66c070c198e (patch)
treec8e3cfb80587124c6753e0ad7e64b84bf6834c9d /drivers/usb
parent36433127ae7a842482ba857f5ad3c431817a9542 (diff)
downloadlinux-4fe5354f61cad4c0550285283c83c66c070c198e.tar.gz
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 <stern@rowland.harvard.edu>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/pci-quirks.c9
1 files changed, 9 insertions, 0 deletions
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;