Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=565227c08226e458da191518251dbff6831624c2
Commit:     565227c08226e458da191518251dbff6831624c2
Parent:     08cbc706acd2dd601b0663e28fa97ffb0564e105
Author:     Benjamin Herrenschmidt <[EMAIL PROTECTED]>
AuthorDate: Thu Dec 6 13:28:25 2007 -0800
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Mon Dec 17 10:47:15 2007 -0800

    usb: Remove broken optimisation in OHCI IRQ handler
    
    The OHCI IRQ handler has an optimisation that avoids reading some
    chip registers when the controller reports that the interrupt was
    triggered *only* because completed requests were written into the
    controller's "done list" and handed to the host.
    
    This mechanism can't be used on some controllers.  Among others, it
    fails for the SA1111 and the AMCC 440EP PowerPC processor.
    
    This patch removes the optimisation and makes the code clearer.
    
    Signed-off-by: Benjamin Herrenschmidt <[EMAIL PROTECTED]>
    Signed-off-by: David Brownell <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/host/ohci-hcd.c |   23 +++++++++++++----------
 1 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 704f33f..ecfe800 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -732,24 +732,27 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
        struct ohci_regs __iomem *regs = ohci->regs;
        int                     ints;
 
-       /* we can eliminate a (slow) ohci_readl()
-        * if _only_ WDH caused this irq
+       /* Read interrupt status (and flush pending writes).  We ignore the
+        * optimization of checking the LSB of hcca->done_head; it doesn't
+        * work on all systems (edge triggering for OHCI can be a factor).
         */
-       if ((ohci->hcca->done_head != 0)
-                       && ! (hc32_to_cpup (ohci, &ohci->hcca->done_head)
-                               & 0x01)) {
-               ints =  OHCI_INTR_WDH;
+       ints = ohci_readl(ohci, &regs->intrstatus);
 
-       /* cardbus/... hardware gone before remove() */
-       } else if ((ints = ohci_readl (ohci, &regs->intrstatus)) == ~(u32)0) {
+       /* Check for an all 1's result which is a typical consequence
+        * of dead, unclocked, or unplugged (CardBus...) devices
+        */
+       if (ints == ~(u32)0) {
                disable (ohci);
                ohci_dbg (ohci, "device removed!\n");
                return IRQ_HANDLED;
+       }
+
+       /* We only care about interrupts that are enabled */
+       ints &= ohci_readl(ohci, &regs->intrenable);
 
        /* interrupt for some other device? */
-       } else if ((ints &= ohci_readl (ohci, &regs->intrenable)) == 0) {
+       if (ints == 0)
                return IRQ_NOTMINE;
-       }
 
        if (ints & OHCI_INTR_UE) {
                // e.g. due to PCI Master/Target Abort
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to