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)
ehci_mem_cleanup (ehci);
return retval;
}
writel (INTR_MASK, &ehci->regs->intr_enable);
writel (ehci->periodic_dma, &ehci->regs->frame_list);
#ifdef CONFIG_PCI
......@@ -531,7 +530,8 @@ static int ehci_start (struct usb_hcd *hcd)
/*
* Start, enabling full USB 2.0 functionality ... usb 1.1 devices
* 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;
register_reboot_notifier (&ehci->reboot_notifier);
......@@ -563,6 +563,8 @@ static int ehci_start (struct usb_hcd *hcd)
goto done2;
}
writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */
create_debug_files (ehci);
return 0;
......@@ -573,6 +575,7 @@ static int ehci_start (struct usb_hcd *hcd)
static void ehci_stop (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u8 rh_ports, port;
ehci_dbg (ehci, "stop\n");
......@@ -584,7 +587,16 @@ static void ehci_stop (struct usb_hcd *hcd)
return;
}
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);
writel (0, &ehci->regs->intr_enable);
/* let companion controllers work when we aren't */
writel (0, &ehci->regs->configured_flag);
......@@ -704,12 +716,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
status = readl (&ehci->regs->status);
/* shared irq */
if (status == 0) {
spin_unlock (&ehci->lock);
return IRQ_NONE;
}
/* e.g. cardbus physical eject */
if (status == ~(u32) 0) {
ehci_dbg (ehci, "device removed\n");
......@@ -717,8 +723,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
}
status &= INTR_MASK;
if (!status) /* irq sharing? */
goto done;
if (!status) { /* irq sharing? */
spin_unlock(&ehci->lock);
return IRQ_NONE;
}
/* clear (just) interrupts */
writel (status, &ehci->regs->status);
......@@ -789,7 +797,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
if (bh)
ehci_work (ehci, regs);
done:
spin_unlock (&ehci->lock);
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