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: Alan Stern <stern@rowland.harvard.edu> Cc: David Brownell <david-b@pacbell.net> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Родитель
5863964608
Коммит
67b2e02974
|
@ -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,18 +734,17 @@ 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);
|
||||
/* 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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче