summaryrefslogtreecommitdiffstats
path: root/arch/arm/common/gic.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-12 11:30:02 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-12 11:30:02 -0800
commitb1286f4e9ac14c8973140b338b4d3c5691264d3b (patch)
tree5a67788bb2276cd67230d24b5a6994ddafb10707 /arch/arm/common/gic.c
parent6facac1ab68fbf9cbad31a9d521f3a0d6aa9470e (diff)
parent0fa5d3996dbda1ee9653c43d39b7ef159fb57ee7 (diff)
Merge branch 'for-linus' of git://git.linaro.org/people/rmk/linux-arm
Pull ARM updates from Russell King: "Here's the updates for ARM for this merge window, which cover quite a variety of areas. There's a bunch of patch series from Will tackling various bugs like the PROT_NONE handling, ASID allocation, cluster boot protocol and ASID TLB tagging updates. We move to a build-time sorted exception table rather than doing the sorting at run-time, add support for the secure computing filter, and some updates to the perf code. We also have sorted out the placement of some headers, fixed some build warnings, fixed some hotplug problems with the per-cpu TWD code." * 'for-linus' of git://git.linaro.org/people/rmk/linux-arm: (73 commits) ARM: 7594/1: Add .smp entry for REALVIEW_EB ARM: 7599/1: head: Remove boot-time HYP mode check for v5 and below ARM: 7598/1: net: bpf_jit_32: fix sp-relative load/stores offsets. ARM: 7595/1: syscall: rework ordering in syscall_trace_exit ARM: 7596/1: mmci: replace readsl/writesl with ioread32_rep/iowrite32_rep ARM: 7597/1: net: bpf_jit_32: fix kzalloc gfp/size mismatch. ARM: 7593/1: nommu: do not enable DCACHE_WORD_ACCESS when !CONFIG_MMU ARM: 7592/1: nommu: prevent generation of kernel unaligned memory accesses ARM: 7591/1: nommu: Enable the strict alignment (CR_A) bit only if ARCH < v6 ARM: 7590/1: /proc/interrupts: limit the display of IPIs to online CPUs only ARM: 7587/1: implement optimized percpu variable access ARM: 7589/1: integrator: pass the lm resource to amba ARM: 7588/1: amba: create a resource parent registrator ARM: 7582/2: rename kvm_seq to vmalloc_seq so to avoid confusion with KVM ARM: 7585/1: kernel: fix nr_cpu_ids check in DT logical map init ARM: 7584/1: perf: fix link error when CONFIG_HW_PERF_EVENTS is not selected ARM: gic: use a private mapping for CPU target interfaces ARM: kernel: add logical mappings look-up ARM: kernel: add cpu logical map DT init in setup_arch ARM: kernel: add device tree init map function ...
Diffstat (limited to 'arch/arm/common/gic.c')
-rw-r--r--arch/arm/common/gic.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index aa526998418..36ae03a3f5d 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -70,6 +70,14 @@ struct gic_chip_data {
static DEFINE_RAW_SPINLOCK(irq_controller_lock);
/*
+ * The GIC mapping of CPU interfaces does not necessarily match
+ * the logical CPU numbering. Let's use a mapping as returned
+ * by the GIC itself.
+ */
+#define NR_GIC_CPU_IF 8
+static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
+
+/*
* Supported arch specific GIC irq extension.
* Default make them NULL.
*/
@@ -238,11 +246,11 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
u32 val, mask, bit;
- if (cpu >= 8 || cpu >= nr_cpu_ids)
+ if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
return -EINVAL;
mask = 0xff << shift;
- bit = 1 << (cpu_logical_map(cpu) + shift);
+ bit = gic_cpu_map[cpu] << shift;
raw_spin_lock(&irq_controller_lock);
val = readl_relaxed(reg) & ~mask;
@@ -349,11 +357,6 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
u32 cpumask;
unsigned int gic_irqs = gic->gic_irqs;
void __iomem *base = gic_data_dist_base(gic);
- u32 cpu = cpu_logical_map(smp_processor_id());
-
- cpumask = 1 << cpu;
- cpumask |= cpumask << 8;
- cpumask |= cpumask << 16;
writel_relaxed(0, base + GIC_DIST_CTRL);
@@ -366,6 +369,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic)
/*
* Set all global interrupts to this CPU only.
*/
+ cpumask = readl_relaxed(base + GIC_DIST_TARGET + 0);
for (i = 32; i < gic_irqs; i += 4)
writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
@@ -389,9 +393,25 @@ static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
{
void __iomem *dist_base = gic_data_dist_base(gic);
void __iomem *base = gic_data_cpu_base(gic);
+ unsigned int cpu_mask, cpu = smp_processor_id();
int i;
/*
+ * Get what the GIC says our CPU mask is.
+ */
+ BUG_ON(cpu >= NR_GIC_CPU_IF);
+ cpu_mask = readl_relaxed(dist_base + GIC_DIST_TARGET + 0);
+ gic_cpu_map[cpu] = cpu_mask;
+
+ /*
+ * Clear our mask from the other map entries in case they're
+ * still undefined.
+ */
+ for (i = 0; i < NR_GIC_CPU_IF; i++)
+ if (i != cpu)
+ gic_cpu_map[i] &= ~cpu_mask;
+
+ /*
* Deal with the banked PPI and SGI interrupts - disable all
* PPI interrupts, ensure all SGI interrupts are enabled.
*/
@@ -646,7 +666,7 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
{
irq_hw_number_t hwirq_base;
struct gic_chip_data *gic;
- int gic_irqs, irq_base;
+ int gic_irqs, irq_base, i;
BUG_ON(gic_nr >= MAX_GIC_NR);
@@ -683,6 +703,13 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
}
/*
+ * Initialize the CPU interface map to all CPUs.
+ * It will be refined as each CPU probes its ID.
+ */
+ for (i = 0; i < NR_GIC_CPU_IF; i++)
+ gic_cpu_map[i] = 0xff;
+
+ /*
* For primary GICs, skip over SGIs.
* For secondary GICs, skip over PPIs, too.
*/
@@ -737,7 +764,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
/* Convert our logical CPU mask into a physical one. */
for_each_cpu(cpu, mask)
- map |= 1 << cpu_logical_map(cpu);
+ map |= gic_cpu_map[cpu];
/*
* Ensure that stores to Normal memory are visible to the