Skip to content

Commit

Permalink
USB: OHCI: fix root-hub resume bug
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Nov 16, 2006
1 parent 51b5bce commit 583cead
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 11 deletions.
25 changes: 15 additions & 10 deletions drivers/usb/host/ohci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion drivers/usb/host/ohci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit 583cead

Please sign in to comment.