From: andrew@lunn.ch (Andrew Lunn)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH] fix for certain sequnce of request_irq can cause irq storm
Date: Sat, 26 Jul 2014 19:45:06 +0200 [thread overview]
Message-ID: <20140726174506.GB29849@lunn.ch> (raw)
In-Reply-To: <20140726155659.GA22977@fifteen>
On Sat, Jul 26, 2014 at 07:56:59PM +0400, Evgeniy Dushistov wrote:
> The problem is that hardware handled by arm/plat-orion/gpio.c,
> require ack for edge irq, and no ack for level irq.
>
> The code handle this issue, by two "struct irq_chip_type" per
> one "struct irq_chip_generic". For one "struct irq_chip_generic"
> irq_ack pointer is setted, for another it is NULL.
>
> But we have only one mask_cache per two "struct irq_chip_type".
> So if we
> 1)unmask interrupt A for "edge type" trigger,
> 2)unmask interrupt B for "level type" trigger,
> 3)unmask interrupt C for "edge type",
>
> we, because of usage of generic irq_gc_mask_clr_bit/irq_gc_mask_set_bit,
> have hardware configured to trigger interrupt B on "edge type",
> because of shared mask_cache. But kernel think that B is "level type",
> so when interrupt B occur via "edge" reason, we don't ack it,
> and B triggered again and again.
Hi Evgeniy
Did you look at the way gpio-mvebu.c handles this? It is a little bit
different from your solution. I'm wondering if gpio-mvebu.c is just
different, or wrong? It does seem to be using one mask_cache for both
edge and level trigger.
Thanks
Andrew
>
> Signed-off-by: Evgeniy A. Dushistov <dushistov@mail.ru>
> ---
> arch/arm/plat-orion/gpio.c | 36 ++++++++++++++++++++++++++++++++----
> 1 file changed, 32 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
> index b61a3bc..e048f61 100644
> --- a/arch/arm/plat-orion/gpio.c
> +++ b/arch/arm/plat-orion/gpio.c
> @@ -497,6 +497,34 @@ static void orion_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
> #define orion_gpio_dbg_show NULL
> #endif
>
> +static void orion_gpio_unmask_irq(struct irq_data *d)
> +{
> + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
> + struct irq_chip_type *ct = irq_data_get_chip_type(d);
> + u32 reg_val;
> + u32 mask = d->mask;
> +
> + irq_gc_lock(gc);
> + reg_val = irq_reg_readl(gc->reg_base + ct->regs.mask);
> + reg_val |= mask;
> + irq_reg_writel(reg_val, gc->reg_base + ct->regs.mask);
> + irq_gc_unlock(gc);
> +}
> +
> +static void orion_gpio_mask_irq(struct irq_data *d)
> +{
> + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
> + struct irq_chip_type *ct = irq_data_get_chip_type(d);
> + u32 mask = d->mask;
> + u32 reg_val;
> +
> + irq_gc_lock(gc);
> + reg_val = irq_reg_readl(gc->reg_base + ct->regs.mask);
> + reg_val &= ~mask;
> + irq_reg_writel(reg_val, gc->reg_base + ct->regs.mask);
> + irq_gc_unlock(gc);
> +}
> +
> void __init orion_gpio_init(struct device_node *np,
> int gpio_base, int ngpio,
> void __iomem *base, int mask_offset,
> @@ -565,8 +593,8 @@ void __init orion_gpio_init(struct device_node *np,
> ct = gc->chip_types;
> ct->regs.mask = ochip->mask_offset + GPIO_LEVEL_MASK_OFF;
> ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
> - ct->chip.irq_mask = irq_gc_mask_clr_bit;
> - ct->chip.irq_unmask = irq_gc_mask_set_bit;
> + ct->chip.irq_mask = orion_gpio_mask_irq;
> + ct->chip.irq_unmask = orion_gpio_unmask_irq;
> ct->chip.irq_set_type = gpio_irq_set_type;
> ct->chip.name = ochip->chip.label;
>
> @@ -575,8 +603,8 @@ void __init orion_gpio_init(struct device_node *np,
> ct->regs.ack = GPIO_EDGE_CAUSE_OFF;
> ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
> ct->chip.irq_ack = irq_gc_ack_clr_bit;
> - ct->chip.irq_mask = irq_gc_mask_clr_bit;
> - ct->chip.irq_unmask = irq_gc_mask_set_bit;
> + ct->chip.irq_mask = orion_gpio_mask_irq;
> + ct->chip.irq_unmask = orion_gpio_unmask_irq;
> ct->chip.irq_set_type = gpio_irq_set_type;
> ct->handler = handle_edge_irq;
> ct->chip.name = ochip->chip.label;
> --
> 1.8.5.5
>
> --
> /Evgeniy
next prev parent reply other threads:[~2014-07-26 17:45 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-26 15:56 [PATCH] fix for certain sequnce of request_irq can cause irq storm Evgeniy Dushistov
2014-07-26 16:56 ` Andrew Lunn
2014-07-26 17:12 ` Evgeniy Dushistov
2014-10-21 14:15 ` Thomas Petazzoni
2014-10-21 15:20 ` Evgeniy Dushistov
2014-10-21 15:37 ` Thomas Petazzoni
2014-10-21 18:54 ` Evgeniy Dushistov
2014-07-26 17:45 ` Andrew Lunn [this message]
2014-07-26 18:48 ` Evgeniy Dushistov
2014-10-15 0:08 ` Evgeniy Dushistov
2014-10-15 15:51 ` Jason Cooper
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=20140726174506.GB29849@lunn.ch \
--to=andrew@lunn.ch \
--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).