Commit b8b58a59 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: EHCI IRQ tweaks

Various tweaks to EHCI IRQ handling, these may affact some systems.

 - Delays enabling IRQs until the root hub is more fully set up, so
   any "resume detect" IRQs can be handled properly.  (Craig Nadler)

 - Power down ports on driver shutdown.  (Craig Nadler)

 - Remove some duplicate irq-sharing logic that somehow crept in; check
   only once, and return IRQ_NONE to detect IRQ storms better (db)

 - Minor comment fix re integrated TTs.  (db)

From:          Craig Nadler <craig.nadler@arc.com>
Signed-off-by: default avatarDavid Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 2311ac09
...@@ -425,7 +425,6 @@ static int ehci_start (struct usb_hcd *hcd) ...@@ -425,7 +425,6 @@ static int ehci_start (struct usb_hcd *hcd)
ehci_mem_cleanup (ehci); ehci_mem_cleanup (ehci);
return retval; return retval;
} }
writel (INTR_MASK, &ehci->regs->intr_enable);
writel (ehci->periodic_dma, &ehci->regs->frame_list); writel (ehci->periodic_dma, &ehci->regs->frame_list);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
...@@ -531,7 +530,8 @@ static int ehci_start (struct usb_hcd *hcd) ...@@ -531,7 +530,8 @@ static int ehci_start (struct usb_hcd *hcd)
/* /*
* Start, enabling full USB 2.0 functionality ... usb 1.1 devices * Start, enabling full USB 2.0 functionality ... usb 1.1 devices
* are explicitly handed to companion controller(s), so no TT is * are explicitly handed to companion controller(s), so no TT is
* involved with the root hub. * involved with the root hub. (Except where one is integrated,
* and there's no companion controller unless maybe for USB OTG.)
*/ */
ehci->reboot_notifier.notifier_call = ehci_reboot; ehci->reboot_notifier.notifier_call = ehci_reboot;
register_reboot_notifier (&ehci->reboot_notifier); register_reboot_notifier (&ehci->reboot_notifier);
...@@ -563,6 +563,8 @@ static int ehci_start (struct usb_hcd *hcd) ...@@ -563,6 +563,8 @@ static int ehci_start (struct usb_hcd *hcd)
goto done2; goto done2;
} }
writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */
create_debug_files (ehci); create_debug_files (ehci);
return 0; return 0;
...@@ -573,6 +575,7 @@ static int ehci_start (struct usb_hcd *hcd) ...@@ -573,6 +575,7 @@ static int ehci_start (struct usb_hcd *hcd)
static void ehci_stop (struct usb_hcd *hcd) static void ehci_stop (struct usb_hcd *hcd)
{ {
struct ehci_hcd *ehci = hcd_to_ehci (hcd); struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u8 rh_ports, port;
ehci_dbg (ehci, "stop\n"); ehci_dbg (ehci, "stop\n");
...@@ -584,7 +587,16 @@ static void ehci_stop (struct usb_hcd *hcd) ...@@ -584,7 +587,16 @@ static void ehci_stop (struct usb_hcd *hcd)
return; return;
} }
del_timer_sync (&ehci->watchdog); del_timer_sync (&ehci->watchdog);
/* Turn off port power on all root hub ports. */
rh_ports = HCS_N_PORTS (ehci->hcs_params);
for (port = 1; port <= rh_ports; port++) {
ehci_hub_control(hcd, ClearPortFeature, USB_PORT_FEAT_POWER,
port, NULL, 0);
}
ehci_reset (ehci); ehci_reset (ehci);
writel (0, &ehci->regs->intr_enable);
/* let companion controllers work when we aren't */ /* let companion controllers work when we aren't */
writel (0, &ehci->regs->configured_flag); writel (0, &ehci->regs->configured_flag);
...@@ -704,12 +716,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) ...@@ -704,12 +716,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
status = readl (&ehci->regs->status); status = readl (&ehci->regs->status);
/* shared irq */
if (status == 0) {
spin_unlock (&ehci->lock);
return IRQ_NONE;
}
/* e.g. cardbus physical eject */ /* e.g. cardbus physical eject */
if (status == ~(u32) 0) { if (status == ~(u32) 0) {
ehci_dbg (ehci, "device removed\n"); ehci_dbg (ehci, "device removed\n");
...@@ -717,8 +723,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) ...@@ -717,8 +723,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
} }
status &= INTR_MASK; status &= INTR_MASK;
if (!status) /* irq sharing? */ if (!status) { /* irq sharing? */
goto done; spin_unlock(&ehci->lock);
return IRQ_NONE;
}
/* clear (just) interrupts */ /* clear (just) interrupts */
writel (status, &ehci->regs->status); writel (status, &ehci->regs->status);
...@@ -789,7 +797,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs) ...@@ -789,7 +797,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
if (bh) if (bh)
ehci_work (ehci, regs); ehci_work (ehci, regs);
done:
spin_unlock (&ehci->lock); spin_unlock (&ehci->lock);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment