USB: OHCI: fix root-hub resume bug
authorAlan Stern <stern@rowland.harvard.edu>
Tue, 24 Oct 2006 16:04:22 +0000 (12:04 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 16 Nov 2006 22:26:11 +0000 (14:26 -0800)
When a suspended OHCI controller sees a port's status change, it sets
both the Root-Hub-Status-Change and the Resume-Detect bits in the
Interrupt Status register.  Processing both these bits, the driver
tries to resume the root hub twice!

This patch (as807) fixes the bug by ignoring RD if RHSC is set.  It
also prints a slightly more informative log message when a
remote-wakeup event occurs.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hub.c

index 9be6b303e7846a5ff2e5e21919b385b158543ddb..ea4714e557e465ca2eb6df2ff1dcb3a7f06d7e0c 100644 (file)
@@ -715,13 +715,6 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
                return IRQ_NOTMINE;
        }
 
-       if (ints & OHCI_INTR_RHSC) {
-               ohci_vdbg (ohci, "rhsc\n");
-               ohci->next_statechange = jiffies + STATECHANGE_DELAY;
-               ohci_writel (ohci, OHCI_INTR_RHSC, &regs->intrstatus);
-               usb_hcd_poll_rh_status(hcd);
-       }
-
        if (ints & OHCI_INTR_UE) {
                disable (ohci);
                ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
@@ -731,9 +724,21 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
                ohci_usb_reset (ohci);
        }
 
-       if (ints & OHCI_INTR_RD) {
-               ohci_vdbg (ohci, "resume detect\n");
-               ohci_writel (ohci, OHCI_INTR_RD, &regs->intrstatus);
+       if (ints & OHCI_INTR_RHSC) {
+               ohci_vdbg(ohci, "rhsc\n");
+               ohci->next_statechange = jiffies + STATECHANGE_DELAY;
+               ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC,
+                               &regs->intrstatus);
+               usb_hcd_poll_rh_status(hcd);
+       }
+
+       /* For connect and disconnect events, we expect the controller
+        * to turn on RHSC along with RD.  But for remote wakeup events
+        * this might not happen.
+        */
+       else if (ints & OHCI_INTR_RD) {
+               ohci_vdbg(ohci, "resume detect\n");
+               ohci_writel(ohci, OHCI_INTR_RD, &regs->intrstatus);
                hcd->poll_rh = 1;
                if (ohci->autostop) {
                        spin_lock (&ohci->lock);
index da09e7930c1b4baf0db594de23bc84fcdf84bc83..6995ea36f2e874499ae407e9b699931ceba117bd 100644 (file)
@@ -169,7 +169,8 @@ __acquires(ohci->lock)
                break;
        case OHCI_USB_RESUME:
                /* HCFS changes sometime after INTR_RD */
-               ohci_info (ohci, "wakeup\n");
+               ohci_info(ohci, "%swakeup\n",
+                               autostopped ? "auto-" : "");
                break;
        case OHCI_USB_OPER:
                /* this can happen after resuming a swsusp snapshot */