aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2015-11-16 14:13:27 -0500
committerThomas Gleixner <tglx@linutronix.de>2015-11-17 08:25:58 -0500
commit92eda4ad4371225d6ccf9cded74315547e9a3153 (patch)
tree151830ddfb508dacb90b229191f9cd170d20e435 /drivers/irqchip
parent0eece2b22849c90b730815c893425a36b9d10fd5 (diff)
irqchip/gic: Clear enable bits before restoring them
When restoring the GIC state (after a suspend/resume cycle, for example), the driver directly writes the 'enabled' state it has saved by accessing GICD_ISENABLERn, which performs an OR operation between the value present in the register and the value we write. If whatever code that has run before we reentered the kernel has enabled an interrupt that was previously disabled, we won't restore that disabled state. Making sure we first clear the register (by writting to GICD_ICENABLERn) before restoring the enabled state. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Cc: <linux-arm-kernel@lists.infradead.org> Cc: Jason Cooper <jason@lakedaemon.net> Cc: Russell King <linux@arm.linux.org.uk> Link: http://lkml.kernel.org/r/1447701208-18150-4-git-send-email-marc.zyngier@arm.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-gic.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 515c823c1c95..bc846e7fec44 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -604,9 +604,12 @@ static void gic_dist_restore(unsigned int gic_nr)
604 writel_relaxed(gic_data[gic_nr].saved_spi_target[i], 604 writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
605 dist_base + GIC_DIST_TARGET + i * 4); 605 dist_base + GIC_DIST_TARGET + i * 4);
606 606
607 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) 607 for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
608 writel_relaxed(GICD_INT_EN_CLR_X32,
609 dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
608 writel_relaxed(gic_data[gic_nr].saved_spi_enable[i], 610 writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
609 dist_base + GIC_DIST_ENABLE_SET + i * 4); 611 dist_base + GIC_DIST_ENABLE_SET + i * 4);
612 }
610 613
611 writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL); 614 writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL);
612} 615}
@@ -654,8 +657,11 @@ static void gic_cpu_restore(unsigned int gic_nr)
654 return; 657 return;
655 658
656 ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_enable); 659 ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
657 for (i = 0; i < DIV_ROUND_UP(32, 32); i++) 660 for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
661 writel_relaxed(GICD_INT_EN_CLR_X32,
662 dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
658 writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4); 663 writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
664 }
659 665
660 ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf); 666 ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
661 for (i = 0; i < DIV_ROUND_UP(32, 16); i++) 667 for (i = 0; i < DIV_ROUND_UP(32, 16); i++)