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

Signed-off-by: Felipe Balbi <ba...@ti.com>
---
 drivers/mfd/twl4030-irq.c |  131 +++++++++++++--------------------------------
 1 files changed, 38 insertions(+), 93 deletions(-)

diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index 5d3a147..91331a7 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -30,7 +30,6 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/kthread.h>
 #include <linux/slab.h>
 
 #include <linux/i2c/twl.h>
@@ -278,91 +277,50 @@ static const struct sih sih_modules_twl5031[8] = {
 
 static unsigned twl4030_irq_base;
 
-static struct completion irq_event;
-
 /*
  * This thread processes interrupts reported by the Primary Interrupt Handler.
  */
-static int twl4030_irq_thread(void *data)
+static irqreturn_t twl4030_irq_thread(int irq, void *unused)
 {
-       long irq = (long)data;
-       static unsigned i2c_errors;
-       static const unsigned max_i2c_errors = 100;
-
-
-       current->flags |= PF_NOFREEZE;
-
-       while (!kthread_should_stop()) {
-               int ret;
-               int module_irq;
-               u8 pih_isr;
-
-               /* Wait for IRQ, then read PIH irq status (also blocking) */
-               wait_for_completion_interruptible(&irq_event);
-
-               ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
-                                         REG_PIH_ISR_P1);
-               if (ret) {
-                       pr_warning("twl4030: 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;
-               }
+       int ret;
+       int module_irq;
+       u8 pih_isr;
+
+       ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
+                       REG_PIH_ISR_P1);
+       if (ret) {
+               pr_warning("twl4030: I2C error %d reading PIH ISR\n",
+                               ret);
+               return IRQ_NONE;
+       }
 
-               /* these handlers deal with the relevant SIH irq status */
-               local_irq_disable();
-               for (module_irq = twl4030_irq_base;
-                               pih_isr;
-                               pih_isr >>= 1, module_irq++) {
-                       if (pih_isr & 0x1) {
-                               struct irq_desc *d = irq_to_desc(module_irq);
-
-                               if (!d) {
-                                       pr_err("twl4030: Invalid SIH IRQ: %d\n",
-                                              module_irq);
-                                       return -EINVAL;
-                               }
-
-                               /* 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);
+       /* these handlers deal with the relevant SIH irq status */
+       for (module_irq = twl4030_irq_base;
+                       pih_isr;
+                       pih_isr >>= 1, module_irq++) {
+               if (pih_isr & 0x1) {
+                       struct irq_desc *d = irq_to_desc(module_irq);
+
+                       if (!d) {
+                               pr_err("twl4030: Invalid SIH IRQ: %d\n",
+                                               module_irq);
+                               return IRQ_NONE;
                        }
-               }
-               local_irq_enable();
 
-               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);
+               }
        }
 
-       return 0;
-}
-
-/*
- * handle_twl4030_pih() is the desc->handle method for the twl4030 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 twl4030 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_twl4030_pih(int irq, void *devid)
-{
-       /* Acknowledge, clear *AND* mask the interrupt... */
-       disable_irq_nosync(irq);
-       complete(devid);
        return IRQ_HANDLED;
 }
+
 /*----------------------------------------------------------------------*/
 
 /*
@@ -788,7 +746,6 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, 
unsigned irq_end)
 
        int                     status;
        int                     i;
-       struct task_struct      *task;
 
        /*
         * Mask and clear all TWL4030 interrupts since initially we do
@@ -817,6 +774,7 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, 
unsigned irq_end)
        for (i = irq_base; i < irq_end; i++) {
                set_irq_chip_and_handler(i, &twl4030_irq_chip,
                                handle_simple_irq);
+               set_irq_nested_thread(i, 1);
                activate_irq(i);
        }
        twl4030_irq_next = i;
@@ -830,28 +788,15 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, 
unsigned irq_end)
                goto fail;
        }
 
-       /* install an irq handler to demultiplex the TWL4030 interrupt */
-
-
-       init_completion(&irq_event);
-
-       status = request_irq(irq_num, handle_twl4030_pih, IRQF_DISABLED,
-                               "TWL4030-PIH", &irq_event);
+       status = request_threaded_irq(irq_num, NULL, twl4030_irq_thread,
+                       IRQF_DISABLED, "TWL4030-PIH", NULL);
        if (status < 0) {
                pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status);
                goto fail_rqirq;
        }
 
-       task = kthread_run(twl4030_irq_thread, (void *)(long)irq_num,
-                                                               "twl4030-irq");
-       if (IS_ERR(task)) {
-               pr_err("twl4030: could not create irq %d thread!\n", irq_num);
-               status = PTR_ERR(task);
-               goto fail_kthread;
-       }
-       return status;
-fail_kthread:
-       free_irq(irq_num, &irq_event);
+       return 0;
+
 fail_rqirq:
        /* clean up twl4030_sih_setup */
 fail:
-- 
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