Commit f2cb36c1 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] update PCI early-handoff handling for OHCI

The PCI "early usb handoff" quirk logic didn't work like "ohci-hcd" ...
This patch makes it do so by:

  - Resetting the controller after kicking BIOS off, matching the
    normal "chip in hardware reset" startup mode;

  - Reporting any BIOS that borks this simple handoff; it's likely
    got a few other surprises for us too.

  - Ignoring that handoff on HPPA;

The diagnostic string is mostly shared with EHCI, saving a few bytes.
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>

 drivers/usb/host/pci-quirks.c |   22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)
parent f197b2c5
...@@ -60,6 +60,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_2, qui ...@@ -60,6 +60,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_2, qui
#define OHCI_INTRENABLE 0x10 #define OHCI_INTRENABLE 0x10
#define OHCI_INTRDISABLE 0x14 #define OHCI_INTRDISABLE 0x14
#define OHCI_OCR (1 << 3) /* ownership change request */ #define OHCI_OCR (1 << 3) /* ownership change request */
#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ #define OHCI_CTRL_IR (1 << 8) /* interrupt routing */
#define OHCI_INTR_OC (1 << 30) /* ownership change */ #define OHCI_INTR_OC (1 << 30) /* ownership change */
...@@ -140,13 +141,17 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) ...@@ -140,13 +141,17 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
{ {
void __iomem *base; void __iomem *base;
int wait_time; int wait_time;
u32 control;
base = ioremap_nocache(pci_resource_start(pdev, 0), base = ioremap_nocache(pci_resource_start(pdev, 0),
pci_resource_len(pdev, 0)); pci_resource_len(pdev, 0));
if (base == NULL) return; if (base == NULL) return;
if (readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) { /* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
wait_time = 500; /* 0.5 seconds */ #ifndef __hppa__
control = readl(base + OHCI_CONTROL);
if (control & OHCI_CTRL_IR) {
wait_time = 500; /* arbitrary; 5 seconds */
writel(OHCI_INTR_OC, base + OHCI_INTRENABLE); writel(OHCI_INTR_OC, base + OHCI_INTRENABLE);
writel(OHCI_OCR, base + OHCI_CMDSTATUS); writel(OHCI_OCR, base + OHCI_CMDSTATUS);
while (wait_time > 0 && while (wait_time > 0 &&
...@@ -154,7 +159,15 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) ...@@ -154,7 +159,15 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
wait_time -= 10; wait_time -= 10;
msleep(10); msleep(10);
} }
if (wait_time <= 0)
printk(KERN_WARNING "%s %s: early BIOS handoff "
"failed (BIOS bug ?)\n",
pdev->dev.bus_id, "OHCI");
/* reset controller, preserving RWC */
writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
} }
#endif
/* /*
* disable interrupts * disable interrupts
...@@ -211,8 +224,9 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) ...@@ -211,8 +224,9 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
/* /*
* well, possibly buggy BIOS... * well, possibly buggy BIOS...
*/ */
printk(KERN_WARNING "EHCI early BIOS handoff " printk(KERN_WARNING "%s %s: early BIOS handoff "
"failed (BIOS bug ?)\n"); "failed (BIOS bug ?)\n",
pdev->dev.bus_id, "EHCI");
pci_write_config_dword(pdev, pci_write_config_dword(pdev,
hcc_params + EHCI_USBLEGSUP, hcc_params + EHCI_USBLEGSUP,
EHCI_USBLEGSUP_OS); EHCI_USBLEGSUP_OS);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment