From patchwork Tue Dec 28 17:14:17 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Felipe Balbi X-Patchwork-Id: 436831 X-Patchwork-Delegate: me@felipebalbi.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oBSHHirx005756 for ; Tue, 28 Dec 2010 17:17:44 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754067Ab0L1RQ5 (ORCPT ); Tue, 28 Dec 2010 12:16:57 -0500 Received: from na3sys009aog104.obsmtp.com ([74.125.149.73]:54447 "EHLO na3sys009aog104.obsmtp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753447Ab0L1RQz (ORCPT ); Tue, 28 Dec 2010 12:16:55 -0500 Received: from source ([209.85.215.178]) (using TLSv1) by na3sys009aob104.postini.com ([74.125.148.12]) with SMTP ID DSNKTRobhscmk1CpNBq6A74JzcVajnV3Ddh5@postini.com; Tue, 28 Dec 2010 09:16:55 PST Received: by mail-ey0-f178.google.com with SMTP id 5so4510786eyh.23 for ; Tue, 28 Dec 2010 09:16:54 -0800 (PST) Received: by 10.213.105.205 with SMTP id u13mr844960ebo.25.1293556614584; Tue, 28 Dec 2010 09:16:54 -0800 (PST) Received: from localhost (cs181221087.pp.htv.fi [82.181.221.87]) by mx.google.com with ESMTPS id x54sm9859265eeh.23.2010.12.28.09.16.52 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 28 Dec 2010 09:16:53 -0800 (PST) From: Felipe Balbi To: Linux Kernel Mailing List , Linux OMAP Mailing List Cc: Tony Lindgren , David Brownell , Thomas Gleixner , Mark Brown , Felipe Balbi Subject: [RFC/PATCH 1/3] mfd: twl4030-irq: move to threaded_irq Date: Tue, 28 Dec 2010 19:14:17 +0200 Message-Id: <1293556459-28613-2-git-send-email-balbi@ti.com> X-Mailer: git-send-email 1.7.3.4.598.g85356 In-Reply-To: <1293556459-28613-1-git-send-email-balbi@ti.com> References: <20101228161657.GF2239@legolas.emea.dhcp.ti.com> <1293556459-28613-1-git-send-email-balbi@ti.com> Organization: Texas Instruments\n Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Tue, 28 Dec 2010 17:17:44 +0000 (UTC) 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 #include #include -#include #include #include @@ -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: