[patch 40/46] USB: EHCI: fix handling of dead controllers

From: Greg KH
Date: Mon Nov 17 2008 - 02:34:45 EST


2.6.27-stable review patch. If anyone has any objections, please let us know.

------------------

From: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>

commit 67b2e029743a52670d77864723b4d0d40f7733b5 upstream.

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: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>
Cc: David Brownell <david-b@xxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>

---
drivers/usb/host/ehci-hcd.c | 25 ++++++++++++-------------
1 file changed, 12 insertions(+), 13 deletions(-)

--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -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_
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;

@@ -731,19 +731,18 @@ static irqreturn_t ehci_irq (struct usb_

/* PCI errors [4.15.2.4] */
if (unlikely ((status & STS_FATAL) != 0)) {
+ ehci_err(ehci, "fatal error\n");
dbg_cmd (ehci, "fatal", ehci_readl(ehci,
&ehci->regs->command));
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);
- /* generic layer kills/unlinks all urbs, then
- * uses ehci_stop to clean up the rest
- */
- bh = 1;
- }
+ ehci_reset(ehci);
+ ehci_writel(ehci, 0, &ehci->regs->configured_flag);
+ /* generic layer kills/unlinks all urbs, then
+ * uses ehci_stop to clean up the rest
+ */
+ bh = 1;
}

if (bh)

--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/