ChangeSet 1.1760.26.5, 2004/06/24 10:21:05-07:00, david-b@pacbell.net [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 Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman drivers/usb/host/ehci-hcd.c | 29 ++++++++++++++++++----------- 1 files changed, 18 insertions(+), 11 deletions(-) diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c --- a/drivers/usb/host/ehci-hcd.c 2004-06-29 16:26:32 -07:00 +++ b/drivers/usb/host/ehci-hcd.c 2004-06-29 16:26:32 -07:00 @@ -425,7 +425,6 @@ 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 @@ /* * 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 @@ goto done2; } + writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ + create_debug_files (ehci); return 0; @@ -573,6 +575,7 @@ 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 @@ 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 @@ 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 @@ } 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 @@ if (bh) ehci_work (ehci, regs); -done: spin_unlock (&ehci->lock); return IRQ_HANDLED; }