ChangeSet 1.1931, 2004/04/22 13:43:11-07:00, [EMAIL PROTECTED]
[PATCH] USB: ehci handles pci misbehavior better
Cope better when PCI misbehaves badly and registers misbehave:
- terminate some loops before they get to infinity
* capability scan
* port reset
- after init failure, memory may already be cleaned up
Some systems have been reporting such problems after ACPI resume.
drivers/usb/host/ehci-hcd.c | 17 ++++++++++++++---
drivers/usb/host/ehci-hub.c | 16 ++++++++++------
2 files changed, 24 insertions(+), 9 deletions(-)
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c Thu Apr 22 14:41:25 2004
+++ b/drivers/usb/host/ehci-hcd.c Thu Apr 22 14:41:25 2004
@@ -330,6 +330,7 @@
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp;
+ unsigned count = 256/4;
spin_lock_init (&ehci->lock);
@@ -345,16 +346,21 @@
temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
else
temp = 0;
- while (temp) {
+ while (temp && count--) {
u32 cap;
- pci_read_config_dword (to_pci_dev(ehci->hcd.self.controller), temp,
&cap);
+ pci_read_config_dword (to_pci_dev(ehci->hcd.self.controller),
+ temp, &cap);
ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp);
switch (cap & 0xff) {
case 1: /* BIOS/SMM/... handoff */
if (bios_handoff (ehci, temp, cap) != 0)
return -EOPNOTSUPP;
break;
+ case 0x0a: /* appendix C */
+ ehci_dbg (ehci, "debug registers, BAR %d offset %d\n",
+ (cap >> 29) & 0x07, (cap >> 16) & 0x0fff);
+ break;
case 0: /* illegal reserved capability */
ehci_warn (ehci, "illegal capability!\n");
cap = 0;
@@ -364,6 +370,10 @@
}
temp = (cap >> 8) & 0xff;
}
+ if (!count) {
+ ehci_err (ehci, "bogus capabilities ... PCI problems!\n");
+ return -EIO;
+ }
#endif
/* cache this readonly data; minimize PCI reads */
@@ -577,7 +587,8 @@
/* root hub is shut down separately (first, when possible) */
spin_lock_irq (&ehci->lock);
- ehci_work (ehci, NULL);
+ if (ehci->async)
+ ehci_work (ehci, NULL);
spin_unlock_irq (&ehci->lock);
ehci_mem_cleanup (ehci);
diff -Nru a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
--- a/drivers/usb/host/ehci-hub.c Thu Apr 22 14:41:25 2004
+++ b/drivers/usb/host/ehci-hub.c Thu Apr 22 14:41:25 2004
@@ -252,14 +252,18 @@
/* force reset to complete */
writel (temp & ~PORT_RESET,
&ehci->regs->port_status [wIndex]);
- do {
- temp = readl (
- &ehci->regs->port_status [wIndex]);
- udelay (10);
- } while (temp & PORT_RESET);
+ retval = handshake (
+ &ehci->regs->port_status [wIndex],
+ PORT_RESET, 0, 500);
+ if (retval != 0) {
+ ehci_err (ehci, "port %d reset error %d\n",
+ wIndex + 1, retval);
+ goto error;
+ }
/* see what we found out */
- temp = check_reset_complete (ehci, wIndex, temp);
+ temp = check_reset_complete (ehci, wIndex,
+ readl (&ehci->regs->port_status [wIndex]));
}
// don't show wPortStatus if it's owned by a companion hc
-------------------------------------------------------
This SF.net email is sponsored by: The Robotic Monkeys at ThinkGeek
For a limited time only, get FREE Ground shipping on all orders of $35
or more. Hurry up and shop folks, this offer expires April 30th!
http://www.thinkgeek.com/freeshipping/?cpg297
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel