... and while at that, also start using
handle_nested_irq() as we should.

Signed-off-by: Felipe Balbi <ba...@ti.com>
---
 drivers/mfd/twl6030-irq.c |  141 ++++++++++++++++-----------------------------
 1 files changed, 49 insertions(+), 92 deletions(-)

diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index aaedb11..1530411 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -84,99 +84,64 @@ static int twl6030_interrupt_mapping[24] = {
 
 static unsigned twl6030_irq_base;
 
-static struct completion irq_event;
-
 /*
  * This thread processes interrupts reported by the Primary Interrupt Handler.
  */
-static int twl6030_irq_thread(void *data)
+static irqreturn_t twl6030_irq_thread(int irq, void *unused)
 {
-       long irq = (long)data;
-       static unsigned i2c_errors;
-       static const unsigned max_i2c_errors = 100;
        int ret;
-
-       current->flags |= PF_NOFREEZE;
-
-       while (!kthread_should_stop()) {
-               int i;
-               union {
+       int i;
+       union {
                u8 bytes[4];
                u32 int_sts;
-               } sts;
-
-               /* Wait for IRQ, then read PIH irq status (also blocking) */
-               wait_for_completion_interruptible(&irq_event);
-
-               /* read INT_STS_A, B and C in one shot using a burst read */
-               ret = twl_i2c_read(TWL_MODULE_PIH, sts.bytes,
-                               REG_INT_STS_A, 3);
-               if (ret) {
-                       pr_warning("twl6030: I2C error %d reading PIH ISR\n",
-                                       ret);
-                       if (++i2c_errors >= max_i2c_errors) {
-                               printk(KERN_ERR "Maximum I2C error count"
-                                               " exceeded.  Terminating %s.\n",
-                                               __func__);
-                               break;
-                       }
-                       complete(&irq_event);
-                       continue;
-               }
-
+       } sts;
 
+       disable_irq_nosync(irq);
 
-               sts.bytes[3] = 0; /* Only 24 bits are valid*/
+       /* read INT_STS_A, B and C in one shot using a burst read */
+       ret = twl_i2c_read(TWL_MODULE_PIH, sts.bytes,
+                       REG_INT_STS_A, 3);
+       if (ret) {
+               pr_warning("twl6030: I2C error %d reading PIH ISR\n",
+                               ret);
+               return IRQ_NONE;
+       }
 
-               for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++) {
-                       local_irq_disable();
-                       if (sts.int_sts & 0x1) {
-                               int module_irq = twl6030_irq_base +
-                                       twl6030_interrupt_mapping[i];
-                               struct irq_desc *d = irq_to_desc(module_irq);
 
-                               if (!d) {
-                                       pr_err("twl6030: Invalid SIH IRQ: %d\n",
-                                              module_irq);
-                                       return -EINVAL;
-                               }
+       sts.bytes[3] = 0; /* Only 24 bits are valid*/
 
-                               /* These can't be masked ... always warn
-                                * if we get any surprises.
-                                */
-                               if (d->status & IRQ_DISABLED)
-                                       note_interrupt(module_irq, d,
-                                                       IRQ_NONE);
-                               else
-                                       d->handle_irq(module_irq, d);
+       for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++) {
+               local_irq_disable();
+               if (sts.int_sts & 0x1) {
+                       int module_irq = twl6030_irq_base +
+                               twl6030_interrupt_mapping[i];
+                       struct irq_desc *d = irq_to_desc(module_irq);
 
+                       if (!d) {
+                               pr_err("twl6030: Invalid SIH IRQ: %d\n",
+                                               module_irq);
+                               return IRQ_NONE;
                        }
-               local_irq_enable();
-               }
-               ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes,
-                               REG_INT_STS_A, 3); /* clear INT_STS_A */
-               if (ret)
-                       pr_warning("twl6030: I2C error in clearing PIH ISR\n");
 
-               enable_irq(irq);
+                       /* These can't be masked ... always warn
+                        * if we get any surprises.
+                        */
+                       if (d->status & IRQ_DISABLED)
+                               note_interrupt(module_irq, d,
+                                               IRQ_NONE);
+                       else
+                               handle_nested_irq(module_irq);
+
+               }
+               local_irq_enable();
        }
+       ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes,
+                       REG_INT_STS_A, 3); /* clear INT_STS_A */
+       if (ret)
+               pr_warning("twl6030: I2C error in clearing PIH ISR\n");
 
-       return 0;
-}
+       enable_irq(irq);
 
-/*
- * handle_twl6030_int() is the desc->handle method for the twl6030 interrupt.
- * This is a chained interrupt, so there is no desc->action method for it.
- * Now we need to query the interrupt controller in the twl6030 to determine
- * which module is generating the interrupt request.  However, we can't do i2c
- * transactions in interrupt context, so we must defer that work to a kernel
- * thread.  All we do here is acknowledge and mask the interrupt and wakeup
- * the kernel thread.
- */
-static irqreturn_t handle_twl6030_pih(int irq, void *devid)
-{
-       disable_irq_nosync(irq);
-       complete(devid);
        return IRQ_HANDLED;
 }
 
@@ -303,7 +268,6 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, 
unsigned irq_end)
 
        int     status = 0;
        int     i;
-       struct task_struct      *task;
        int ret;
        u8 mask[4];
 
@@ -337,28 +301,21 @@ int twl6030_init_irq(int irq_num, unsigned irq_base, 
unsigned irq_end)
        pr_info("twl6030: %s (irq %d) chaining IRQs %d..%d\n", "PIH",
                        irq_num, irq_base, twl6030_irq_next - 1);
 
-       /* install an irq handler to demultiplex the TWL6030 interrupt */
-       init_completion(&irq_event);
-       task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq");
-       if (IS_ERR(task)) {
-               pr_err("twl6030: could not create irq %d thread!\n", irq_num);
-               status = PTR_ERR(task);
-               goto fail_kthread;
-       }
-
-       status = request_irq(irq_num, handle_twl6030_pih, IRQF_DISABLED,
-                               "TWL6030-PIH", &irq_event);
+       status = request_threaded_irq(irq_num, NULL, twl6030_irq_thread,
+                       IRQF_DISABLED, "TWL6030-PIH", NULL);
        if (status < 0) {
                pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status);
-               goto fail_irq;
+               goto fail;
        }
-       return status;
-fail_irq:
-       free_irq(irq_num, &irq_event);
 
-fail_kthread:
+       return 0;
+
+fail:
+       free_irq(irq_num, NULL);
+
        for (i = irq_base; i < irq_end; i++)
                set_irq_chip_and_handler(i, NULL, NULL);
+
        return status;
 }
 
-- 
1.7.3.4.598.g85356

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to