From 267840f3397fd9f6a2bdde14de38b9d29d525d7b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 23 Aug 2011 22:20:03 +0100 Subject: ARM: 7061/1: gic: convert logical CPU numbers into physical numbers The GIC driver must convert logical CPU numbers passed in from Linux into physical CPU numbers that are understood by the hardware. This patch uses the new cpu_logical_map macro for performing the conversion inside the GIC driver. Signed-off-by: Will Deacon Signed-off-by: Russell King --- arch/arm/common/gic.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'arch/arm/common/gic.c') diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 3227ca952a12..666b278e56d7 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -180,7 +180,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, return -EINVAL; mask = 0xff << shift; - bit = 1 << (cpu + shift); + bit = 1 << (cpu_logical_map(cpu) + shift); spin_lock(&irq_controller_lock); val = readl_relaxed(reg) & ~mask; @@ -259,9 +259,15 @@ static void __init gic_dist_init(struct gic_chip_data *gic, unsigned int irq_start) { unsigned int gic_irqs, irq_limit, i; + u32 cpumask; void __iomem *base = gic->dist_base; - u32 cpumask = 1 << smp_processor_id(); + u32 cpu = 0; +#ifdef CONFIG_SMP + cpu = cpu_logical_map(smp_processor_id()); +#endif + + cpumask = 1 << cpu; cpumask |= cpumask << 8; cpumask |= cpumask << 16; @@ -382,7 +388,12 @@ void __cpuinit gic_enable_ppi(unsigned int irq) #ifdef CONFIG_SMP void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { - unsigned long map = *cpus_addr(*mask); + int cpu; + unsigned long map = 0; + + /* Convert our logical CPU mask into a physical one. */ + for_each_cpu(cpu, mask) + map |= 1 << cpu_logical_map(cpu); /* * Ensure that stores to Normal memory are visible to the -- cgit v1.2.1 From 292b293ceef2eda1f96f0c90b96e954d7bdabd1c Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Wed, 20 Jul 2011 16:24:14 +0100 Subject: ARM: gic: consolidate PPI handling PPI handling is a bit of an odd beast. It uses its own low level handling code and is hardwired to the local timers (hence lacking a registration interface). Instead, switch the low handling to the normal SPI handling code. PPIs are handled by the handle_percpu_devid_irq flow. This also allows the removal of some duplicated code. Cc: Kukjin Kim Cc: David Brown Cc: Bryan Huntsman Cc: Tony Lindgren Cc: Paul Mundt Cc: Magnus Damm Cc: Thomas Gleixner Acked-by: David Brown Tested-by: David Brown Tested-by: Shawn Guo Signed-off-by: Marc Zyngier --- arch/arm/common/gic.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) (limited to 'arch/arm/common/gic.c') diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 666b278e56d7..bbea0168779b 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -28,10 +28,14 @@ #include #include #include +#include +#include +#include #include #include #include +#include static DEFINE_SPINLOCK(irq_controller_lock); @@ -255,6 +259,32 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) irq_set_chained_handler(irq, gic_handle_cascade_irq); } +#ifdef CONFIG_LOCAL_TIMERS +#define gic_ppi_handler percpu_timer_handler +#else +static irqreturn_t gic_ppi_handler(int irq, void *dev_id) +{ + return IRQ_NONE; +} +#endif + +#define PPI_IRQACT(nr) \ + { \ + .handler = gic_ppi_handler, \ + .flags = IRQF_PERCPU | IRQF_TIMER, \ + .irq = nr, \ + .name = "PPI-" # nr, \ + } + +static struct irqaction ppi_irqaction_template[16] __initdata = { + PPI_IRQACT(0), PPI_IRQACT(1), PPI_IRQACT(2), PPI_IRQACT(3), + PPI_IRQACT(4), PPI_IRQACT(5), PPI_IRQACT(6), PPI_IRQACT(7), + PPI_IRQACT(8), PPI_IRQACT(9), PPI_IRQACT(10), PPI_IRQACT(11), + PPI_IRQACT(12), PPI_IRQACT(13), PPI_IRQACT(14), PPI_IRQACT(15), +}; + +static struct irqaction *ppi_irqaction; + static void __init gic_dist_init(struct gic_chip_data *gic, unsigned int irq_start) { @@ -262,6 +292,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic, u32 cpumask; void __iomem *base = gic->dist_base; u32 cpu = 0; + u32 nrppis = 0, ppi_base = 0; #ifdef CONFIG_SMP cpu = cpu_logical_map(smp_processor_id()); @@ -282,6 +313,33 @@ static void __init gic_dist_init(struct gic_chip_data *gic, if (gic_irqs > 1020) gic_irqs = 1020; + /* + * Nobody would be insane enough to use PPIs on a secondary + * GIC, right? + */ + if (gic == &gic_data[0]) { + nrppis = (32 - irq_start) & 31; + + /* The GIC only supports up to 16 PPIs. */ + if (nrppis > 16) + BUG(); + + ppi_base = gic->irq_offset + 32 - nrppis; + + ppi_irqaction = kmemdup(&ppi_irqaction_template[16 - nrppis], + sizeof(*ppi_irqaction) * nrppis, + GFP_KERNEL); + + if (nrppis && !ppi_irqaction) { + pr_err("GIC: Can't allocate PPI memory"); + nrppis = 0; + ppi_base = 0; + } + } + + pr_info("Configuring GIC with %d sources (%d PPIs)\n", + gic_irqs, (gic == &gic_data[0]) ? nrppis : 0); + /* * Set all global interrupts to be level triggered, active low. */ @@ -317,7 +375,22 @@ static void __init gic_dist_init(struct gic_chip_data *gic, /* * Setup the Linux IRQ subsystem. */ - for (i = irq_start; i < irq_limit; i++) { + for (i = 0; i < nrppis; i++) { + int ppi = i + ppi_base; + int err; + + irq_set_percpu_devid(ppi); + irq_set_chip_and_handler(ppi, &gic_chip, + handle_percpu_devid_irq); + irq_set_chip_data(ppi, gic); + set_irq_flags(ppi, IRQF_VALID | IRQF_NOAUTOEN); + + err = setup_percpu_irq(ppi, &ppi_irqaction[i]); + if (err) + pr_err("GIC: can't setup PPI%d (%d)\n", ppi, err); + } + + for (i = irq_start + nrppis; i < irq_limit; i++) { irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq); irq_set_chip_data(i, gic); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); -- cgit v1.2.1 From 28af690a284dfcb627bd69d0963db1c0f412cb8c Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 22 Jul 2011 12:52:37 +0100 Subject: ARM: gic, local timers: use the request_percpu_irq() interface This patch remove the hardcoded link between local timers and PPIs, and convert the PPI users (TWD, MCT and MSM timers) to the new *_percpu_irq interface. Also some collateral cleanup (local_timer_ack() is gone, and the interrupt handler is strictly private to each driver). PPIs are now useable for more than just the local timers. Additional testing by David Brown (msm8250 and msm8660) and Shawn Guo (imx6q). Cc: David Brown Cc: Thomas Gleixner Acked-by: David Brown Tested-by: David Brown Tested-by: Shawn Guo Signed-off-by: Marc Zyngier --- arch/arm/common/gic.c | 52 --------------------------------------------------- 1 file changed, 52 deletions(-) (limited to 'arch/arm/common/gic.c') diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index bbea0168779b..a2b320503931 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -35,7 +35,6 @@ #include #include #include -#include static DEFINE_SPINLOCK(irq_controller_lock); @@ -259,32 +258,6 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq) irq_set_chained_handler(irq, gic_handle_cascade_irq); } -#ifdef CONFIG_LOCAL_TIMERS -#define gic_ppi_handler percpu_timer_handler -#else -static irqreturn_t gic_ppi_handler(int irq, void *dev_id) -{ - return IRQ_NONE; -} -#endif - -#define PPI_IRQACT(nr) \ - { \ - .handler = gic_ppi_handler, \ - .flags = IRQF_PERCPU | IRQF_TIMER, \ - .irq = nr, \ - .name = "PPI-" # nr, \ - } - -static struct irqaction ppi_irqaction_template[16] __initdata = { - PPI_IRQACT(0), PPI_IRQACT(1), PPI_IRQACT(2), PPI_IRQACT(3), - PPI_IRQACT(4), PPI_IRQACT(5), PPI_IRQACT(6), PPI_IRQACT(7), - PPI_IRQACT(8), PPI_IRQACT(9), PPI_IRQACT(10), PPI_IRQACT(11), - PPI_IRQACT(12), PPI_IRQACT(13), PPI_IRQACT(14), PPI_IRQACT(15), -}; - -static struct irqaction *ppi_irqaction; - static void __init gic_dist_init(struct gic_chip_data *gic, unsigned int irq_start) { @@ -325,16 +298,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic, BUG(); ppi_base = gic->irq_offset + 32 - nrppis; - - ppi_irqaction = kmemdup(&ppi_irqaction_template[16 - nrppis], - sizeof(*ppi_irqaction) * nrppis, - GFP_KERNEL); - - if (nrppis && !ppi_irqaction) { - pr_err("GIC: Can't allocate PPI memory"); - nrppis = 0; - ppi_base = 0; - } } pr_info("Configuring GIC with %d sources (%d PPIs)\n", @@ -377,17 +340,12 @@ static void __init gic_dist_init(struct gic_chip_data *gic, */ for (i = 0; i < nrppis; i++) { int ppi = i + ppi_base; - int err; irq_set_percpu_devid(ppi); irq_set_chip_and_handler(ppi, &gic_chip, handle_percpu_devid_irq); irq_set_chip_data(ppi, gic); set_irq_flags(ppi, IRQF_VALID | IRQF_NOAUTOEN); - - err = setup_percpu_irq(ppi, &ppi_irqaction[i]); - if (err) - pr_err("GIC: can't setup PPI%d (%d)\n", ppi, err); } for (i = irq_start + nrppis; i < irq_limit; i++) { @@ -448,16 +406,6 @@ void __cpuinit gic_secondary_init(unsigned int gic_nr) gic_cpu_init(&gic_data[gic_nr]); } -void __cpuinit gic_enable_ppi(unsigned int irq) -{ - unsigned long flags; - - local_irq_save(flags); - irq_set_status_flags(irq, IRQ_NOPROBE); - gic_unmask_irq(irq_get_irq_data(irq)); - local_irq_restore(flags); -} - #ifdef CONFIG_SMP void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) { -- cgit v1.2.1