From: Lee Jones <lee.jones@linaro.org>
To: Grygorii Strashko <grygorii.strashko@ti.com>
Cc: Samuel Ortiz <sameo@linux.intel.com>,
Kevin Hilman <khilman@linaro.org>,
Graeme Gregory <gg@slimlogic.co.uk>,
linux-omap@vger.kernel.org,
Ruslan Bilovol <ruslan.bilovol@ti.com>,
linux-kernel@vger.kernel.org,
Naga Venkata Srikanth V <vnv.srikanth@samsung.com>,
Oleg_Kosheliev <oleg.kosheliev@ti.com>
Subject: Re: [PATCH 1/4] mfd: twl6030-irq: migrate to IRQ threaded handler
Date: Wed, 24 Jul 2013 11:49:45 +0100 [thread overview]
Message-ID: <20130724104945.GH26801@laptop> (raw)
In-Reply-To: <1374595624-15054-2-git-send-email-grygorii.strashko@ti.com>
On Tue, 23 Jul 2013, Grygorii Strashko wrote:
> From: Naga Venkata Srikanth V <vnv.srikanth@samsung.com>
>
> 1) Removed request_irq() and replaced it with request_threaded_irq().
>
> 2) Removed generic_handle_irq() and replaced it with
> handle_nested_irq().
> Handling of these interrupts is nested, as we are handling an
> interrupt (for e.g rtc, mmc1) when we are still servicing TWL irq.
>
> 3) Removed I2C read-retry logic for the case when twl_i2c_read() is
> failed inside IRQ handler - there is no sense to do that, so just report
> an error and return.
>
> Signed-off-by: Naga Venkata Srikanth V <vnv.srikanth@samsung.com>
> Signed-off-by: Oleg_Kosheliev <oleg.kosheliev@ti.com>
> Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
> ---
> drivers/mfd/twl6030-irq.c | 146 +++++++++++++++------------------------------
> 1 file changed, 49 insertions(+), 97 deletions(-)
Besides the points I mention below I like the way this patch is
going.
> diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
> index 277a8db..b6030d9 100644
> --- a/drivers/mfd/twl6030-irq.c
> +++ b/drivers/mfd/twl6030-irq.c
> @@ -90,7 +90,6 @@ static unsigned twl6030_irq_base;
> static int twl_irq;
> static bool twl_irq_wake_enabled;
>
> -static struct completion irq_event;
> static atomic_t twl6030_wakeirqs = ATOMIC_INIT(0);
>
> static int twl6030_irq_pm_notifier(struct notifier_block *notifier,
> @@ -131,95 +130,57 @@ static struct notifier_block twl6030_irq_pm_notifier_block = {
> };
>
> /*
> - * This thread processes interrupts reported by the Primary Interrupt Handler.
> - */
> -static int twl6030_irq_thread(void *data)
> +* Threaded irq handler for the twl6030 interrupt.
> +* We query the interrupt controller in the twl6030 to determine
> +* which module is generating the interrupt request and call
> +* handle_nested_irq for that module.
> +*/
> +static irqreturn_t twl6030_irq_thread(int irq, void *data)
> {
> - long irq = (long)data;
> - static unsigned i2c_errors;
> - static const unsigned max_i2c_errors = 100;
> - int ret;
> -
> - while (!kthread_should_stop()) {
> - int i;
> - union {
> + int i, ret;
> + 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;
>
> + /* 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_warn("%s: I2C error %d reading PIH ISR\n", __func__, ret);
Does the user really care which function we're returning from.
Would it be better if you replace '__func__' with the device name?
> + return IRQ_HANDLED;
> + }
>
> - sts.bytes[3] = 0; /* Only 24 bits are valid*/
> + sts.bytes[3] = 0; /* Only 24 bits are valid*/
>
> - /*
> - * Since VBUS status bit is not reliable for VBUS disconnect
> - * use CHARGER VBUS detection status bit instead.
> - */
> - if (sts.bytes[2] & 0x10)
> - sts.bytes[2] |= 0x08;
> + /*
> + * Since VBUS status bit is not reliable for VBUS disconnect
> + * use CHARGER VBUS detection status bit instead.
> + */
> + if (sts.bytes[2] & 0x10)
> + sts.bytes[2] |= 0x08;
>
> - 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 +
> + for (i = 0; sts.int_sts; sts.int_sts >>= 1, i++)
> + if (sts.int_sts & 0x1) {
I'm a little confused by this. Where does sts.int_sts come from?
> + int module_irq = twl6030_irq_base +
> twl6030_interrupt_mapping[i];
> - generic_handle_irq(module_irq);
> -
> - }
> - local_irq_enable();
> + handle_nested_irq(module_irq);
> + pr_debug("%s: PIH ISR %u, virq%u\n",
> + __func__, i, module_irq);
> }
>
> - /*
> - * NOTE:
> - * Simulation confirms that documentation is wrong w.r.t the
> - * interrupt status clear operation. A single *byte* write to
> - * any one of STS_A to STS_C register results in all three
> - * STS registers being reset. Since it does not matter which
> - * value is written, all three registers are cleared on a
> - * single byte write, so we just use 0x0 to clear.
> - */
> - ret = twl_i2c_write_u8(TWL_MODULE_PIH, 0x00, REG_INT_STS_A);
> - if (ret)
> - pr_warning("twl6030: I2C error in clearing PIH ISR\n");
> -
> - enable_irq(irq);
> - }
> -
> - return 0;
> -}
> + /*
> + * NOTE:
> + * Simulation confirms that documentation is wrong w.r.t the
> + * interrupt status clear operation. A single *byte* write to
> + * any one of STS_A to STS_C register results in all three
> + * STS registers being reset. Since it does not matter which
> + * value is written, all three registers are cleared on a
> + * single byte write, so we just use 0x0 to clear.
> + */
> + ret = twl_i2c_write_u8(TWL_MODULE_PIH, 0x00, REG_INT_STS_A);
> + if (ret)
> + pr_warn("twl6030: I2C error in clearing PIH ISR\n");
>
> -/*
> - * 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;
> }
>
> @@ -351,7 +312,6 @@ int twl6030_init_irq(struct device *dev, int irq_num)
> {
> struct device_node *node = dev->of_node;
> int nr_irqs, irq_base, irq_end;
> - struct task_struct *task;
> static struct irq_chip twl6030_irq_chip;
> int status = 0;
> int i;
> @@ -396,36 +356,25 @@ int twl6030_init_irq(struct device *dev, int irq_num)
> irq_set_chip_and_handler(i, &twl6030_irq_chip,
> handle_simple_irq);
> irq_set_chip_data(i, (void *)irq_num);
> + irq_set_nested_thread(i, true);
> activate_irq(i);
> }
>
> - dev_info(dev, "PIH (irq %d) chaining IRQs %d..%d\n",
> - irq_num, irq_base, irq_end);
> + dev_info(dev, "PIH (irq %d) nested IRQs %d..%d\n",
> + irq_num, irq_base, irq_end);
>
> /* install an irq handler to demultiplex the TWL6030 interrupt */
> - init_completion(&irq_event);
> -
> - status = request_irq(irq_num, handle_twl6030_pih, 0, "TWL6030-PIH",
> - &irq_event);
> + status = request_threaded_irq(irq_num, NULL, twl6030_irq_thread,
> + IRQF_ONESHOT, "TWL6030-PIH", NULL);
> if (status < 0) {
> dev_err(dev, "could not claim irq %d: %d\n", irq_num, status);
> goto fail_irq;
> }
>
> - task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq");
> - if (IS_ERR(task)) {
> - dev_err(dev, "could not create irq %d thread!\n", irq_num);
> - status = PTR_ERR(task);
> - goto fail_kthread;
> - }
> -
> twl_irq = irq_num;
> register_pm_notifier(&twl6030_irq_pm_notifier_block);
> return irq_base;
>
> -fail_kthread:
> - free_irq(irq_num, &irq_event);
> -
> fail_irq:
> for (i = irq_base; i < irq_end; i++)
> irq_set_chip_and_handler(i, NULL, NULL);
> @@ -437,10 +386,13 @@ int twl6030_exit_irq(void)
> {
> unregister_pm_notifier(&twl6030_irq_pm_notifier_block);
>
> - if (twl6030_irq_base) {
> + if (!twl6030_irq_base) {
> pr_err("twl6030: can't yet clean up IRQs?\n");
> return -ENOSYS;
> }
> +
> + free_irq(twl_irq, NULL);
> +
If request_threaded_irq() fails, isn't there a chance that
twl6030_irq_base will be allocated, but twl_irq will still be
undefined?
> return 0;
> }
>
--
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
next prev parent reply other threads:[~2013-07-24 10:49 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-23 16:07 [PATCH 0/4] mfd: twl6030-irq: rework and add twl6032 support Grygorii Strashko
2013-07-23 16:07 ` Grygorii Strashko
2013-07-23 16:07 ` [PATCH 1/4] mfd: twl6030-irq: migrate to IRQ threaded handler Grygorii Strashko
2013-07-23 16:07 ` Grygorii Strashko
2013-07-24 10:49 ` Lee Jones [this message]
2013-07-24 11:54 ` Grygorii Strashko
2013-07-24 11:54 ` Grygorii Strashko
2013-07-24 12:50 ` Lee Jones
2013-07-24 12:50 ` Lee Jones
2013-07-24 13:17 ` Grygorii Strashko
2013-07-24 13:17 ` Grygorii Strashko
2013-07-24 11:54 ` Lee Jones
2013-07-24 11:54 ` Lee Jones
2013-07-23 16:07 ` [PATCH 2/4] mfd: twl6030-irq: add error check when IRQs are masked initially Grygorii Strashko
2013-07-23 16:07 ` Grygorii Strashko
2013-07-23 18:08 ` Graeme Gregory
2013-07-24 11:51 ` Grygorii Strashko
2013-07-24 11:51 ` Grygorii Strashko
2013-07-23 16:07 ` [PATCH 3/4] mfd: twl6030-irq: convert to use linear irq_domain Grygorii Strashko
2013-07-23 16:07 ` Grygorii Strashko
2013-07-24 11:35 ` Lee Jones
2013-07-24 11:35 ` Lee Jones
2013-07-24 13:37 ` Grygorii Strashko
2013-07-24 13:37 ` Grygorii Strashko
2013-07-23 16:07 ` [PATCH 4/4] mfd: twl6030-irq: Add interrupt mapping table for the twl6032 Grygorii Strashko
2013-07-23 16:07 ` Grygorii Strashko
2013-07-24 11:52 ` Lee Jones
2013-07-24 13:39 ` Grygorii Strashko
2013-07-24 13:39 ` Grygorii Strashko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130724104945.GH26801@laptop \
--to=lee.jones@linaro.org \
--cc=gg@slimlogic.co.uk \
--cc=grygorii.strashko@ti.com \
--cc=khilman@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-omap@vger.kernel.org \
--cc=oleg.kosheliev@ti.com \
--cc=ruslan.bilovol@ti.com \
--cc=sameo@linux.intel.com \
--cc=vnv.srikanth@samsung.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.