linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: maxime.ripard@free-electrons.com (Maxime Ripard)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 5/5] pinctrl: sunxi: Define enable / disable irq callbacks for level triggered irqs
Date: Tue, 3 Jun 2014 15:47:53 +0200	[thread overview]
Message-ID: <20140603134753.GL27722@lukather> (raw)
In-Reply-To: <1401544899-405-6-git-send-email-hdegoede@redhat.com>

On Sat, May 31, 2014 at 04:01:39PM +0200, Hans de Goede wrote:
> Some drivers use disable_irq / enable_irq and do the work clearing the source
> in another thread instead of using a threaded interrupt handler.
> 
> The irqchip used not having irq_disable and irq_enable callbacks in this case,
> will lead to unnecessary spurious interrupts:
> 
> On a disable_irq in a chip without a handller for this, the irq core will
> remember the disable, but not actually call into the irqchip. With a level
> triggered interrupt (where the source has not been cleared) this will lead
> to an immediate retrigger, at which point the irq-core will mask the irq.
> So having an irq_disable callback in the irqchip will save us the interrupt
> firing a 2nd time for nothing.

Judging by the comments there, it seems more like a feature.

> Drivers using disable / enable_irq like this, will call enable_irq when
> they finally have cleared the interrupt source, without an enable_irq callback,
> this will turn into an unmask, at which point the irq will trigger immediately
> because when it was originally acked the level was still high, so the ack was
> a nop.

I don't think enable_irq offers any warranty regarding the state of
the interrupt. It's up to the driver to clear the interrupts before
calling enable_irq if it doesn't want any irrelevant/spurious
interrupts.

> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
>  drivers/pinctrl/sunxi/pinctrl-sunxi.c | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
> 
> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> index 418a430..6ccbe43 100644
> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> @@ -34,6 +34,7 @@
>  static void sunxi_pinctrl_irq_ack(struct irq_data *d);
>  static void sunxi_pinctrl_irq_mask(struct irq_data *d);
>  static void sunxi_pinctrl_irq_unmask(struct irq_data *d);
> +static void sunxi_pinctrl_irq_ack_unmask(struct irq_data *d);
>  static int sunxi_pinctrl_irq_set_type(struct irq_data *d, unsigned int type);
>  
>  static struct sunxi_pinctrl_group *
> @@ -563,6 +564,10 @@ static struct irq_chip sunxi_pinctrl_level_irq_chip = {
>  	.irq_eoi		= sunxi_pinctrl_irq_ack,
>  	.irq_mask		= sunxi_pinctrl_irq_mask,
>  	.irq_unmask		= sunxi_pinctrl_irq_unmask,
> +	/* Define irq_enable / disable to avoid spurious irqs for drivers
> +	 * using these to suppress irqs while they clear the irq source */

What "drivers" are we talking about? I grepped for a while, and didn't
any obvious candidates.

But again, I feel like if a driver wants to work outside of the usual
interrupt workflow, it's up to the driver itself to know what it's
doing.

> +	.irq_enable		= sunxi_pinctrl_irq_ack_unmask,
> +	.irq_disable		= sunxi_pinctrl_irq_mask,
>  	.irq_request_resources	= sunxi_pinctrl_irq_request_resources,
>  	.irq_set_type		= sunxi_pinctrl_irq_set_type,
>  	.flags			= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_EOI_THREADED
> @@ -662,6 +667,28 @@ static void sunxi_pinctrl_irq_unmask(struct irq_data *d)
>  	spin_unlock_irqrestore(&pctl->lock, flags);
>  }
>  
> +static void sunxi_pinctrl_irq_ack_unmask(struct irq_data *d)
> +{
> +	struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d);
> +	u32 ctrl_reg = sunxi_irq_ctrl_reg(d->hwirq);
> +	u8 ctrl_idx = sunxi_irq_ctrl_offset(d->hwirq);
> +	u32 status_reg = sunxi_irq_status_reg(d->hwirq);
> +	u8 status_idx = sunxi_irq_status_offset(d->hwirq);
> +	unsigned long flags;
> +	u32 val;
> +
> +	spin_lock_irqsave(&pctl->lock, flags);
> +
> +	/* Clear the IRQ */
> +	writel(1 << status_idx, pctl->membase + status_reg);
> +
> +	/* Unmask the IRQ */
> +	val = readl(pctl->membase + ctrl_reg);
> +	writel(val | (1 << ctrl_idx), pctl->membase + ctrl_reg);
> +
> +	spin_unlock_irqrestore(&pctl->lock, flags);
> +}

Please at least call sunxi_pinctrl_irq_ack and
sunxi_pinctrl_irq_unmask if you're doing this.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140603/08da55c8/attachment.sig>

  reply	other threads:[~2014-06-03 13:47 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-05-31 14:01 [PATCH v2 0/5] pinctrl: sunxi: Fix level triggered interrupt support Hans de Goede
2014-05-31 14:01 ` [PATCH v2 1/5] pinctrl: sunxi: Fix sunxi_irq_cfg_reg not working for irqs >= 8 Hans de Goede
2014-06-02 10:18   ` Maxime Ripard
2014-06-09 13:21     ` Linus Walleij
2014-06-09 13:45       ` Hans de Goede
2014-05-31 14:01 ` [PATCH v2 2/5] pinctrl: sunxi: Add IRQCHIP_SKIP_SET_WAKE flag for pinctrl irq chip Hans de Goede
2014-06-02 10:34   ` Maxime Ripard
2014-05-31 14:01 ` [PATCH v2 3/5] pinctrl: sunxi: Move setting of mux to irq type from unmask to request_resources Hans de Goede
2014-06-02 11:59   ` Maxime Ripard
2014-06-03 15:42     ` Hans de Goede
2014-05-31 14:01 ` [PATCH v2 4/5] pinctrl: sunxi: Properly handle level triggered gpio interrupts Hans de Goede
2014-06-03 13:30   ` Maxime Ripard
2014-06-03 15:13     ` Hans de Goede
2014-06-17 18:43       ` Maxime Ripard
2014-06-23 14:53         ` Hans de Goede
2014-05-31 14:01 ` [PATCH v2 5/5] pinctrl: sunxi: Define enable / disable irq callbacks for level triggered irqs Hans de Goede
2014-06-03 13:47   ` Maxime Ripard [this message]
2014-06-03 15:34     ` Hans de Goede

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=20140603134753.GL27722@lukather \
    --to=maxime.ripard@free-electrons.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).