lkml.org 
[lkml]   [2015]   [Sep]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip:irq/urgent] irqchip/atmel-aic5: Use per chip mask caches in mask/unmask()
    Commit-ID:  d32dc9aa10c739363c775baf4499416b2e0dc11f
    Gitweb: http://git.kernel.org/tip/d32dc9aa10c739363c775baf4499416b2e0dc11f
    Author: Ludovic Desroches <ludovic.desroches@atmel.com>
    AuthorDate: Mon, 21 Sep 2015 15:46:04 +0200
    Committer: Thomas Gleixner <tglx@linutronix.de>
    CommitDate: Tue, 22 Sep 2015 15:55:51 +0200

    irqchip/atmel-aic5: Use per chip mask caches in mask/unmask()

    When masking/unmasking interrupts, mask_cache is updated and used later
    for suspend/resume. Unfortunately, it always was the mask_cache
    associated with the first irq chip which was updated. So when performing
    resume, only irqs 0-31 could be enabled.

    Fixes: b1479ebb7720 ("irqchip: atmel-aic: Add atmel AIC/AIC5 drivers")
    Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
    Cc: <sasha.levin@oracle.com>
    Cc: <linux-arm-kernel@lists.infradead.org>
    Cc: <nicolas.ferre@atmel.com>
    Cc: <alexandre.belloni@free-electrons.com>
    Cc: <boris.brezillon@free-electrons.com>
    Cc: <Wenyou.Yang@atmel.com>
    Cc: <jason@lakedaemon.net>
    Cc: <marc.zyngier@arm.com>
    Cc: stable@vger.kernel.org #3.18
    Link: http://lkml.kernel.org/r/1442843173-2390-1-git-send-email-ludovic.desroches@atmel.com
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    ---
    drivers/irqchip/irq-atmel-aic5.c | 24 ++++++++++++++++--------
    1 file changed, 16 insertions(+), 8 deletions(-)

    diff --git a/drivers/irqchip/irq-atmel-aic5.c b/drivers/irqchip/irq-atmel-aic5.c
    index 9da9942..f6d6804 100644
    --- a/drivers/irqchip/irq-atmel-aic5.c
    +++ b/drivers/irqchip/irq-atmel-aic5.c
    @@ -88,28 +88,36 @@ static void aic5_mask(struct irq_data *d)
    {
    struct irq_domain *domain = d->domain;
    struct irq_domain_chip_generic *dgc = domain->gc;
    - struct irq_chip_generic *gc = dgc->gc[0];
    + struct irq_chip_generic *bgc = dgc->gc[0];
    + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);

    - /* Disable interrupt on AIC5 */
    - irq_gc_lock(gc);
    + /*
    + * Disable interrupt on AIC5. We always take the lock of the
    + * first irq chip as all chips share the same registers.
    + */
    + irq_gc_lock(bgc);
    irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR);
    irq_reg_writel(gc, 1, AT91_AIC5_IDCR);
    gc->mask_cache &= ~d->mask;
    - irq_gc_unlock(gc);
    + irq_gc_unlock(bgc);
    }

    static void aic5_unmask(struct irq_data *d)
    {
    struct irq_domain *domain = d->domain;
    struct irq_domain_chip_generic *dgc = domain->gc;
    - struct irq_chip_generic *gc = dgc->gc[0];
    + struct irq_chip_generic *bgc = dgc->gc[0];
    + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);

    - /* Enable interrupt on AIC5 */
    - irq_gc_lock(gc);
    + /*
    + * Enable interrupt on AIC5. We always take the lock of the
    + * first irq chip as all chips share the same registers.
    + */
    + irq_gc_lock(bgc);
    irq_reg_writel(gc, d->hwirq, AT91_AIC5_SSR);
    irq_reg_writel(gc, 1, AT91_AIC5_IECR);
    gc->mask_cache |= d->mask;
    - irq_gc_unlock(gc);
    + irq_gc_unlock(bgc);
    }

    static int aic5_retrigger(struct irq_data *d)

    \
     
     \ /
      Last update: 2015-09-22 16:21    [W:2.395 / U:0.204 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site