IB/ipath: Better handling of unexpected GPIO interrupts
authorMichael Albaugh <Michael.Albaugh@Qlogic.com>
Wed, 3 Oct 2007 17:47:38 +0000 (10:47 -0700)
committerRoland Dreier <rolandd@cisco.com>
Wed, 10 Oct 2007 04:00:47 +0000 (21:00 -0700)
The General Purpose I/O pins can be configured to cause interrupts. At
the end of the interrupt code dealing with all known causes, a message
is output if any bits remain un-handled. Since this is a "can't happen"
scenario, it should only be triggered by bugs elsewhere. It is harmless,
and potentially beneficial, to limit the damage by masking any such
unexpected interrupts.

This patch adds disabling of interrupts from any pins that should
not have been allowed to interrupt, in addition to emitting a message.

Signed-off-by: Michael Albaugh <Michael.Albaugh@Qlogic.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
drivers/infiniband/hw/ipath/ipath_intr.c

index 61eac8cc0d9f1836909087149c81e8f697fe2d3d..801a20d06de680316165f4c74ccbeeb4ec7a5f26 100644 (file)
@@ -1124,10 +1124,8 @@ irqreturn_t ipath_intr(int irq, void *data)
                        /*
                         * Some unexpected bits remain. If they could have
                         * caused the interrupt, complain and clear.
-                        * MEA: this is almost certainly non-ideal.
-                        * we should look into auto-disable of unexpected
-                        * GPIO interrupts, possibly on a "three strikes"
-                        * basis.
+                        * To avoid repetition of this condition, also clear
+                        * the mask. It is almost certainly due to error.
                         */
                        const u32 mask = (u32) dd->ipath_gpio_mask;
 
@@ -1135,6 +1133,10 @@ irqreturn_t ipath_intr(int irq, void *data)
                                ipath_dbg("Unexpected GPIO IRQ bits %x\n",
                                  gpiostatus & mask);
                                to_clear |= (gpiostatus & mask);
+                               dd->ipath_gpio_mask &= ~(gpiostatus & mask);
+                               ipath_write_kreg(dd,
+                                       dd->ipath_kregs->kr_gpio_mask,
+                                       dd->ipath_gpio_mask);
                        }
                }
                if (to_clear) {