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
This commit is contained in:
commit
4143fc83bb
|
@ -84,12 +84,15 @@ void __init gic_dist_config(void __iomem *base, int gic_irqs,
|
|||
writel_relaxed(GICD_INT_DEF_PRI_X4, base + GIC_DIST_PRI + i);
|
||||
|
||||
/*
|
||||
* Disable all interrupts. Leave the PPI and SGIs alone
|
||||
* as they are enabled by redistributor registers.
|
||||
* Deactivate and disable all SPIs. Leave the PPI and SGIs
|
||||
* alone as they are in the redistributor registers on GICv3.
|
||||
*/
|
||||
for (i = 32; i < gic_irqs; i += 32)
|
||||
for (i = 32; i < gic_irqs; i += 32) {
|
||||
writel_relaxed(GICD_INT_EN_CLR_X32,
|
||||
base + GIC_DIST_ENABLE_CLEAR + i / 8);
|
||||
base + GIC_DIST_ACTIVE_CLEAR + i / 8);
|
||||
writel_relaxed(GICD_INT_EN_CLR_X32,
|
||||
base + GIC_DIST_ENABLE_CLEAR + i / 8);
|
||||
}
|
||||
|
||||
if (sync_access)
|
||||
sync_access();
|
||||
|
@ -102,7 +105,9 @@ void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
|
|||
/*
|
||||
* Deal with the banked PPI and SGI interrupts - disable all
|
||||
* PPI interrupts, ensure all SGI interrupts are enabled.
|
||||
* Make sure everything is deactivated.
|
||||
*/
|
||||
writel_relaxed(GICD_INT_EN_CLR_X32, base + GIC_DIST_ACTIVE_CLEAR);
|
||||
writel_relaxed(GICD_INT_EN_CLR_PPI, base + GIC_DIST_ENABLE_CLEAR);
|
||||
writel_relaxed(GICD_INT_EN_SET_SGI, base + GIC_DIST_ENABLE_SET);
|
||||
|
||||
|
|
|
@ -73,9 +73,11 @@ struct gic_chip_data {
|
|||
union gic_base cpu_base;
|
||||
#ifdef CONFIG_CPU_PM
|
||||
u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
|
||||
u32 saved_spi_active[DIV_ROUND_UP(1020, 32)];
|
||||
u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
|
||||
u32 saved_spi_target[DIV_ROUND_UP(1020, 4)];
|
||||
u32 __percpu *saved_ppi_enable;
|
||||
u32 __percpu *saved_ppi_active;
|
||||
u32 __percpu *saved_ppi_conf;
|
||||
#endif
|
||||
struct irq_domain *domain;
|
||||
|
@ -566,6 +568,10 @@ static void gic_dist_save(unsigned int gic_nr)
|
|||
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
|
||||
gic_data[gic_nr].saved_spi_enable[i] =
|
||||
readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
||||
|
||||
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
|
||||
gic_data[gic_nr].saved_spi_active[i] =
|
||||
readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -604,9 +610,19 @@ static void gic_dist_restore(unsigned int gic_nr)
|
|||
writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
|
||||
dist_base + GIC_DIST_TARGET + i * 4);
|
||||
|
||||
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
|
||||
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
|
||||
writel_relaxed(GICD_INT_EN_CLR_X32,
|
||||
dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
|
||||
writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
|
||||
dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
||||
}
|
||||
|
||||
for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++) {
|
||||
writel_relaxed(GICD_INT_EN_CLR_X32,
|
||||
dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
|
||||
writel_relaxed(gic_data[gic_nr].saved_spi_active[i],
|
||||
dist_base + GIC_DIST_ACTIVE_SET + i * 4);
|
||||
}
|
||||
|
||||
writel_relaxed(GICD_ENABLE, dist_base + GIC_DIST_CTRL);
|
||||
}
|
||||
|
@ -631,6 +647,10 @@ static void gic_cpu_save(unsigned int gic_nr)
|
|||
for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
|
||||
ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
||||
|
||||
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_active);
|
||||
for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
|
||||
ptr[i] = readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
|
||||
|
||||
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
|
||||
for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
|
||||
ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
|
||||
|
@ -654,8 +674,18 @@ static void gic_cpu_restore(unsigned int gic_nr)
|
|||
return;
|
||||
|
||||
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
|
||||
for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
|
||||
for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
|
||||
writel_relaxed(GICD_INT_EN_CLR_X32,
|
||||
dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
|
||||
writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
|
||||
}
|
||||
|
||||
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_active);
|
||||
for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
|
||||
writel_relaxed(GICD_INT_EN_CLR_X32,
|
||||
dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
|
||||
writel_relaxed(ptr[i], dist_base + GIC_DIST_ACTIVE_SET + i * 4);
|
||||
}
|
||||
|
||||
ptr = raw_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
|
||||
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)
|
|||
sizeof(u32));
|
||||
BUG_ON(!gic->saved_ppi_enable);
|
||||
|
||||
gic->saved_ppi_active = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
|
||||
sizeof(u32));
|
||||
BUG_ON(!gic->saved_ppi_active);
|
||||
|
||||
gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
|
||||
sizeof(u32));
|
||||
BUG_ON(!gic->saved_ppi_conf);
|
||||
|
|
Loading…
Reference in a new issue