Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 583ceada authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

USB: OHCI: fix root-hub resume bug



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: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 51b5bce8
Loading
Loading
Loading
Loading
+15 −10
Original line number Original line Diff line number Diff line
@@ -715,13 +715,6 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
		return IRQ_NOTMINE;
		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) {
	if (ints & OHCI_INTR_UE) {
		disable (ohci);
		disable (ohci);
		ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
		ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
@@ -731,7 +724,19 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
		ohci_usb_reset (ohci);
		ohci_usb_reset (ohci);
	}
	}


	if (ints & OHCI_INTR_RD) {
	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_vdbg(ohci, "resume detect\n");
		ohci_writel(ohci, OHCI_INTR_RD, &regs->intrstatus);
		ohci_writel(ohci, OHCI_INTR_RD, &regs->intrstatus);
		hcd->poll_rh = 1;
		hcd->poll_rh = 1;
+2 −1
Original line number Original line Diff line number Diff line
@@ -169,7 +169,8 @@ __acquires(ohci->lock)
		break;
		break;
	case OHCI_USB_RESUME:
	case OHCI_USB_RESUME:
		/* HCFS changes sometime after INTR_RD */
		/* HCFS changes sometime after INTR_RD */
		ohci_info (ohci, "wakeup\n");
		ohci_info(ohci, "%swakeup\n",
				autostopped ? "auto-" : "");
		break;
		break;
	case OHCI_USB_OPER:
	case OHCI_USB_OPER:
		/* this can happen after resuming a swsusp snapshot */
		/* this can happen after resuming a swsusp snapshot */