mfd: Fix twl-core oops while calling twl_i2c_* for unbound driver
[linux-2.6.git] / drivers / mfd / wm831x-irq.c
index 6c3408c..ada1835 100644 (file)
@@ -449,7 +449,7 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
 {
        struct wm831x *wm831x = data;
        unsigned int i;
-       int primary;
+       int primary, status_addr;
        int status_regs[WM831X_NUM_IRQ_REGS] = { 0 };
        int read[WM831X_NUM_IRQ_REGS] = { 0 };
        int *status;
@@ -484,8 +484,9 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
                /* Hopefully there should only be one register to read
                 * each time otherwise we ought to do a block read. */
                if (!read[offset]) {
-                       *status = wm831x_reg_read(wm831x,
-                                    irq_data_to_status_reg(&wm831x_irqs[i]));
+                       status_addr = irq_data_to_status_reg(&wm831x_irqs[i]);
+
+                       *status = wm831x_reg_read(wm831x, status_addr);
                        if (*status < 0) {
                                dev_err(wm831x->dev,
                                        "Failed to read IRQ status: %d\n",
@@ -494,26 +495,21 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
                        }
 
                        read[offset] = 1;
+
+                       /* Ignore any bits that we don't think are masked */
+                       *status &= ~wm831x->irq_masks_cur[offset];
+
+                       /* Acknowledge now so we don't miss
+                        * notifications while we handle.
+                        */
+                       wm831x_reg_write(wm831x, status_addr, *status);
                }
 
-               /* Report it if it isn't masked, or forget the status. */
-               if ((*status & ~wm831x->irq_masks_cur[offset])
-                   & wm831x_irqs[i].mask)
+               if (*status & wm831x_irqs[i].mask)
                        handle_nested_irq(wm831x->irq_base + i);
-               else
-                       *status &= ~wm831x_irqs[i].mask;
        }
 
 out:
-       /* Touchscreen interrupts are handled specially in the driver */
-       status_regs[0] &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT);
-
-       for (i = 0; i < ARRAY_SIZE(status_regs); i++) {
-               if (status_regs[i])
-                       wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i,
-                                        status_regs[i]);
-       }
-
        return IRQ_HANDLED;
 }