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

Commit 67b2e029 authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

USB: EHCI: fix handling of dead controllers



This patch (as1165) makes a few small changes in the logic used by
ehci-hcd when it encounters a controller error:

	Instead of printing out the masked status, it prints the
	original status as read directly from the hardware.

	It doesn't check for the STS_HALT status bit before taking
	action.  The mere fact that the STS_FATAL bit is set means
	that something bad has happened and the controller needs to
	be reset.  With the old code this test could never succeed
	because the STS_HALT bit was masked out from the status.

I anticipate that this will prevent the occasional "irq X: nobody cared"
problem people encounter when their EHCI controllers die.

Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Cc: David Brownell <david-b@pacbell.net>
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 58639646
Loading
Loading
Loading
Loading
+12 −13
Original line number Diff line number Diff line
@@ -643,7 +643,7 @@ static int ehci_run (struct usb_hcd *hcd)
static irqreturn_t ehci_irq (struct usb_hcd *hcd)
{
	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
	u32			status, pcd_status = 0, cmd;
	u32			status, masked_status, pcd_status = 0, cmd;
	int			bh;

	spin_lock (&ehci->lock);
@@ -656,14 +656,14 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
		goto dead;
	}

	status &= INTR_MASK;
	if (!status) {			/* irq sharing? */
	masked_status = status & INTR_MASK;
	if (!masked_status) {		/* irq sharing? */
		spin_unlock(&ehci->lock);
		return IRQ_NONE;
	}

	/* clear (just) interrupts */
	ehci_writel(ehci, status, &ehci->regs->status);
	ehci_writel(ehci, masked_status, &ehci->regs->status);
	cmd = ehci_readl(ehci, &ehci->regs->command);
	bh = 0;

@@ -734,10 +734,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)

	/* PCI errors [4.15.2.4] */
	if (unlikely ((status & STS_FATAL) != 0)) {
		ehci_err(ehci, "fatal error\n");
		dbg_cmd(ehci, "fatal", cmd);
		dbg_status(ehci, "fatal", status);
		if (status & STS_HALT) {
			ehci_err (ehci, "fatal error\n");
		ehci_halt(ehci);
dead:
		ehci_reset(ehci);
		ehci_writel(ehci, 0, &ehci->regs->configured_flag);
@@ -746,7 +746,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
		 */
		bh = 1;
	}
	}

	if (bh)
		ehci_work (ehci);