Skip to content

Commit 4143fc8

Browse files
committed
Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fixes from Thomas Gleixner: "Three fixes for the ARM GIC interrupt controller from Marc addressing various shortcomings versus boot initialization and suspend/resume" * 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: irqchip/gic: Add save/restore of the active state irqchip/gic: Clear enable bits before restoring them irqchip/gic: Make sure all interrupts are deactivated at boot
2 parents 876454a + 1c7d4dd commit 4143fc8

File tree

2 files changed

+45
-6
lines changed

2 files changed

+45
-6
lines changed

drivers/irqchip/irq-gic-common.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,15 @@ void __init gic_dist_config(void __iomem *base, int gic_irqs,
8484
writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
8585

8686
/*
87-
* Disable all interrupts. Leave the PPI and SGIs alone
88-
* as they are enabled by redistributor registers.
87+
* Deactivate and disable all SPIs. Leave the PPI and SGIs
88+
* alone as they are in the redistributor registers on GICv3.
8989
*/
90-
for (i = 32; i < gic_irqs; i += 32)
90+
for (i = 32; i < gic_irqs; i += 32) {
9191
writel_relaxed(GICD_INT_EN_CLR_X32,
92-
base + GIC_DIST_ENABLE_CLEAR + i / 8);
92+
base + GIC_DIST_ACTIVE_CLEAR + i / 8);
93+
writel_relaxed(GICD_INT_EN_CLR_X32,
94+
base + GIC_DIST_ENABLE_CLEAR + i / 8);
95+
}
9396

9497
if (sync_access)
9598
sync_access();
@@ -102,7 +105,9 @@ void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
102105
/*
103106
* Deal with the banked PPI and SGI interrupts - disable all
104107
* PPI interrupts, ensure all SGI interrupts are enabled.
108+
* Make sure everything is deactivated.
105109
*/
110+
writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR);
106111
writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR);
107112
writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
108113

drivers/irqchip/irq-gic.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,11 @@ struct gic_chip_data {
7373
union gic_base cpu_base;
7474
#ifdef CONFIG_CPU_PM
7575
u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
76+
u32 saved_spi_active[DIV_ROUND_UP(1020, 32)];
7677
u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
7778
u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
7879
u32 __percpu *saved_ppi_enable;
80+
u32 __percpu *saved_ppi_active;
7981
u32 __percpu *saved_ppi_conf;
8082
#endif
8183
struct irq_domain *domain;
@@ -566,6 +568,10 @@ static void gic_dist_save(unsigned int gic_nr)
566568
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
567569
gic_data[gic_nr].saved_spi_enable[i] =
568570
readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
571+
572+
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
573+
gic_data[gic_nr].saved_spi_active[i] =
574+
readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
569575
}
570576

571577
/*
@@ -604,9 +610,19 @@ static void gic_dist_restore(unsigned int gic_nr)
604610
writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
605611
dist_base + GIC_DIST_TARGET + i * 4);
606612

607-
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
613+
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
614+
writel_relaxed(GICD_INT_EN_CLR_X32,
615+
dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
608616
writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
609617
dist_base + GIC_DIST_ENABLE_SET + i * 4);
618+
}
619+
620+
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
621+
writel_relaxed(GICD_INT_EN_CLR_X32,
622+
dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
623+
writel_relaxed(gic_data[gic_nr].saved_spi_active[i],
624+
dist_base + GIC_DIST_ACTIVE_SET + i * 4);
625+
}
610626

611627
writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL);
612628
}
@@ -631,6 +647,10 @@ static void gic_cpu_save(unsigned int gic_nr)
631647
for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
632648
ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
633649

650+
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_active);
651+
for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
652+
ptr[i] = readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
653+
634654
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
635655
for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
636656
ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
@@ -654,8 +674,18 @@ static void gic_cpu_restore(unsigned int gic_nr)
654674
return;
655675

656676
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
657-
for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
677+
for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
678+
writel_relaxed(GICD_INT_EN_CLR_X32,
679+
dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
658680
writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
681+
}
682+
683+
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_active);
684+
for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
685+
writel_relaxed(GICD_INT_EN_CLR_X32,
686+
dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
687+
writel_relaxed(ptr[i], dist_base + GIC_DIST_ACTIVE_SET + i * 4);
688+
}
659689

660690
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
661691
for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
@@ -710,6 +740,10 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
710740
sizeof(u32));
711741
BUG_ON(!gic->saved_ppi_enable);
712742

743+
gic->saved_ppi_active = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
744+
sizeof(u32));
745+
BUG_ON(!gic->saved_ppi_active);
746+
713747
gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
714748
sizeof(u32));
715749
BUG_ON(!gic->saved_ppi_conf);

0 commit comments

Comments
 (0)