aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Hunter <jonathanh@nvidia.com>2015-07-31 04:44:12 -0400
committerThomas Gleixner <tglx@linutronix.de>2015-08-04 08:14:06 -0400
commit4c2880b31c700b03f3f115b5ca64be615783aa9c (patch)
tree08b1c3c680db1324cf0700f87e852f648de93520
parent567e5a014848c6aeb1d6fc862b1b5d0183760259 (diff)
irqchip/gic: Ensure gic_cpu_if_up/down() programs correct GIC instance
Commit 3228950621d9 ("irqchip: gic: Preserve gic V2 bypass bits in cpu ctrl register") added a new function, gic_cpu_if_up(), to program the GIC CPU_CTRL register. This function assumes that there is only one GIC instance present and hence always uses the chip data for the primary GIC controller. Although it is not common for there to be a secondary, some devices do support a secondary. Therefore, fix this by passing gic_cpu_if_up() a pointer to the appropriate chip data structure. Similarly, the function gic_cpu_if_down() only assumes that there is a single GIC instance present. Update this function so that an instance number is passed for the appropriate GIC and return an error code on failure. The vexpress TC2 (which has a single GIC) is currently the only user of this function and so update it accordingly. Note that because the TC2 only has a single GIC, the call to gic_cpu_if_down() should always be successful. Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Reviewed-by: Marc Zyngier <marc.zyngier@arm.com> Cc: <linux-arm-kernel@lists.infradead.org> Cc: Russell King <linux@arm.linux.org.uk> Cc: Nicolas Pitre <nicolas.pitre@linaro.org> Cc: Jason Cooper <jason@lakedaemon.net> Link: http://lkml.kernel.org/r/1438332252-25248-2-git-send-email-jonathanh@nvidia.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/arm/mach-vexpress/tc2_pm.c2
-rw-r--r--drivers/irqchip/irq-gic.c18
-rw-r--r--include/linux/irqchip/arm-gic.h2
3 files changed, 14 insertions, 8 deletions
diff --git a/arch/arm/mach-vexpress/tc2_pm.c b/arch/arm/mach-vexpress/tc2_pm.c
index b3328cd46c33..1aa4ccece69f 100644
--- a/arch/arm/mach-vexpress/tc2_pm.c
+++ b/arch/arm/mach-vexpress/tc2_pm.c
@@ -80,7 +80,7 @@ static void tc2_pm_cpu_powerdown_prepare(unsigned int cpu, unsigned int cluster)
80 * to the CPU by disabling the GIC CPU IF to prevent wfi 80 * to the CPU by disabling the GIC CPU IF to prevent wfi
81 * from completing execution behind power controller back 81 * from completing execution behind power controller back
82 */ 82 */
83 gic_cpu_if_down(); 83 gic_cpu_if_down(0);
84} 84}
85 85
86static void tc2_pm_cluster_powerdown_prepare(unsigned int cluster) 86static void tc2_pm_cluster_powerdown_prepare(unsigned int cluster)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 84fc622d0309..aa3e7b8a69c4 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -356,9 +356,9 @@ static u8 gic_get_cpumask(struct gic_chip_data *gic)
356 return mask; 356 return mask;
357} 357}
358 358
359static void gic_cpu_if_up(void) 359static void gic_cpu_if_up(struct gic_chip_data *gic)
360{ 360{
361 void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]); 361 void __iomem *cpu_base = gic_data_cpu_base(gic);
362 u32 bypass = 0; 362 u32 bypass = 0;
363 363
364 /* 364 /*
@@ -426,17 +426,23 @@ static void gic_cpu_init(struct gic_chip_data *gic)
426 gic_cpu_config(dist_base, NULL); 426 gic_cpu_config(dist_base, NULL);
427 427
428 writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK); 428 writel_relaxed(GICC_INT_PRI_THRESHOLD, base + GIC_CPU_PRIMASK);
429 gic_cpu_if_up(); 429 gic_cpu_if_up(gic);
430} 430}
431 431
432void gic_cpu_if_down(void) 432int gic_cpu_if_down(unsigned int gic_nr)
433{ 433{
434 void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]); 434 void __iomem *cpu_base;
435 u32 val = 0; 435 u32 val = 0;
436 436
437 if (gic_nr >= MAX_GIC_NR)
438 return -EINVAL;
439
440 cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
437 val = readl(cpu_base + GIC_CPU_CTRL); 441 val = readl(cpu_base + GIC_CPU_CTRL);
438 val &= ~GICC_ENABLE; 442 val &= ~GICC_ENABLE;
439 writel_relaxed(val, cpu_base + GIC_CPU_CTRL); 443 writel_relaxed(val, cpu_base + GIC_CPU_CTRL);
444
445 return 0;
440} 446}
441 447
442#ifdef CONFIG_CPU_PM 448#ifdef CONFIG_CPU_PM
@@ -572,7 +578,7 @@ static void gic_cpu_restore(unsigned int gic_nr)
572 dist_base + GIC_DIST_PRI + i * 4); 578 dist_base + GIC_DIST_PRI + i * 4);
573 579
574 writel_relaxed(GICC_INT_PRI_THRESHOLD, cpu_base + GIC_CPU_PRIMASK); 580 writel_relaxed(GICC_INT_PRI_THRESHOLD, cpu_base + GIC_CPU_PRIMASK);
575 gic_cpu_if_up(); 581 gic_cpu_if_up(&gic_data[gic_nr]);
576} 582}
577 583
578static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) 584static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v)
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 61a2007eb49a..65da435d01c1 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -98,7 +98,7 @@ struct device_node;
98void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, 98void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
99 u32 offset, struct device_node *); 99 u32 offset, struct device_node *);
100void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); 100void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
101void gic_cpu_if_down(void); 101int gic_cpu_if_down(unsigned int gic_nr);
102 102
103static inline void gic_init(unsigned int nr, int start, 103static inline void gic_init(unsigned int nr, int start,
104 void __iomem *dist , void __iomem *cpu) 104 void __iomem *dist , void __iomem *cpu)