diff options
author | Jonas Gorski <jogo@openwrt.org> | 2014-07-12 06:49:42 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-07-30 09:30:23 -0400 |
commit | b37f0f691e69b0325b6f448679e0e338dbd076e2 (patch) | |
tree | 4275bf54d1d80f3e445bf9243c07371284c4525d /arch/mips/bcm63xx | |
parent | 553e25b3da2f1c8e30cc20499ae3593815df97e9 (diff) |
MIPS: BCM63xx: Allow setting affinity for IPIC
Wire up the set_affinity call for the internal PIC if booting on
a cpu supporting it.
Affinity is kept to boot cpu as default.
Signed-off-by: Jonas Gorski <jogo@openwrt.org>
Cc: linux-mips@linux-mips.org
Cc: John Crispin <blogic@openwrt.org>
Cc: Maxime Bizon <mbizon@freebox.fr>
Cc: Florian Fainelli <florian@openwrt.org>
Cc: Kevin Cernekee <cernekee@gmail.com>
Cc: Gregory Fong <gregory.0xf0@gmail.com>
Patchwork: https://patchwork.linux-mips.org/patch/7323/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/bcm63xx')
-rw-r--r-- | arch/mips/bcm63xx/irq.c | 46 |
1 files changed, 40 insertions, 6 deletions
diff --git a/arch/mips/bcm63xx/irq.c b/arch/mips/bcm63xx/irq.c index a53305fbedb8..37eb2d1fa69a 100644 --- a/arch/mips/bcm63xx/irq.c +++ b/arch/mips/bcm63xx/irq.c | |||
@@ -32,7 +32,7 @@ static unsigned int ext_irq_count; | |||
32 | static unsigned int ext_irq_start, ext_irq_end; | 32 | static unsigned int ext_irq_start, ext_irq_end; |
33 | static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2; | 33 | static unsigned int ext_irq_cfg_reg1, ext_irq_cfg_reg2; |
34 | static void (*internal_irq_mask)(struct irq_data *d); | 34 | static void (*internal_irq_mask)(struct irq_data *d); |
35 | static void (*internal_irq_unmask)(struct irq_data *d); | 35 | static void (*internal_irq_unmask)(struct irq_data *d, const struct cpumask *m); |
36 | 36 | ||
37 | 37 | ||
38 | static inline u32 get_ext_irq_perf_reg(int irq) | 38 | static inline u32 get_ext_irq_perf_reg(int irq) |
@@ -51,6 +51,20 @@ static inline void handle_internal(int intbit) | |||
51 | do_IRQ(intbit + IRQ_INTERNAL_BASE); | 51 | do_IRQ(intbit + IRQ_INTERNAL_BASE); |
52 | } | 52 | } |
53 | 53 | ||
54 | static inline int enable_irq_for_cpu(int cpu, struct irq_data *d, | ||
55 | const struct cpumask *m) | ||
56 | { | ||
57 | bool enable = cpu_online(cpu); | ||
58 | |||
59 | #ifdef CONFIG_SMP | ||
60 | if (m) | ||
61 | enable &= cpu_isset(cpu, *m); | ||
62 | else if (irqd_affinity_was_set(d)) | ||
63 | enable &= cpu_isset(cpu, *d->affinity); | ||
64 | #endif | ||
65 | return enable; | ||
66 | } | ||
67 | |||
54 | /* | 68 | /* |
55 | * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not | 69 | * dispatch internal devices IRQ (uart, enet, watchdog, ...). do not |
56 | * prioritize any interrupt relatively to another. the static counter | 70 | * prioritize any interrupt relatively to another. the static counter |
@@ -117,7 +131,8 @@ static void __internal_irq_mask_##width(struct irq_data *d) \ | |||
117 | spin_unlock_irqrestore(&ipic_lock, flags); \ | 131 | spin_unlock_irqrestore(&ipic_lock, flags); \ |
118 | } \ | 132 | } \ |
119 | \ | 133 | \ |
120 | static void __internal_irq_unmask_##width(struct irq_data *d) \ | 134 | static void __internal_irq_unmask_##width(struct irq_data *d, \ |
135 | const struct cpumask *m) \ | ||
121 | { \ | 136 | { \ |
122 | u32 val; \ | 137 | u32 val; \ |
123 | unsigned irq = d->irq - IRQ_INTERNAL_BASE; \ | 138 | unsigned irq = d->irq - IRQ_INTERNAL_BASE; \ |
@@ -132,7 +147,7 @@ static void __internal_irq_unmask_##width(struct irq_data *d) \ | |||
132 | break; \ | 147 | break; \ |
133 | \ | 148 | \ |
134 | val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\ | 149 | val = bcm_readl(irq_mask_addr[cpu] + reg * sizeof(u32));\ |
135 | if (cpu_online(cpu)) \ | 150 | if (enable_irq_for_cpu(cpu, d, m)) \ |
136 | val |= (1 << bit); \ | 151 | val |= (1 << bit); \ |
137 | else \ | 152 | else \ |
138 | val &= ~(1 << bit); \ | 153 | val &= ~(1 << bit); \ |
@@ -189,7 +204,7 @@ static void bcm63xx_internal_irq_mask(struct irq_data *d) | |||
189 | 204 | ||
190 | static void bcm63xx_internal_irq_unmask(struct irq_data *d) | 205 | static void bcm63xx_internal_irq_unmask(struct irq_data *d) |
191 | { | 206 | { |
192 | internal_irq_unmask(d); | 207 | internal_irq_unmask(d, NULL); |
193 | } | 208 | } |
194 | 209 | ||
195 | /* | 210 | /* |
@@ -237,7 +252,8 @@ static void bcm63xx_external_irq_unmask(struct irq_data *d) | |||
237 | spin_unlock_irqrestore(&epic_lock, flags); | 252 | spin_unlock_irqrestore(&epic_lock, flags); |
238 | 253 | ||
239 | if (is_ext_irq_cascaded) | 254 | if (is_ext_irq_cascaded) |
240 | internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start)); | 255 | internal_irq_unmask(irq_get_irq_data(irq + ext_irq_start), |
256 | NULL); | ||
241 | } | 257 | } |
242 | 258 | ||
243 | static void bcm63xx_external_irq_clear(struct irq_data *d) | 259 | static void bcm63xx_external_irq_clear(struct irq_data *d) |
@@ -356,6 +372,18 @@ static int bcm63xx_external_irq_set_type(struct irq_data *d, | |||
356 | return IRQ_SET_MASK_OK_NOCOPY; | 372 | return IRQ_SET_MASK_OK_NOCOPY; |
357 | } | 373 | } |
358 | 374 | ||
375 | #ifdef CONFIG_SMP | ||
376 | static int bcm63xx_internal_set_affinity(struct irq_data *data, | ||
377 | const struct cpumask *dest, | ||
378 | bool force) | ||
379 | { | ||
380 | if (!irqd_irq_disabled(data)) | ||
381 | internal_irq_unmask(data, dest); | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | #endif | ||
386 | |||
359 | static struct irq_chip bcm63xx_internal_irq_chip = { | 387 | static struct irq_chip bcm63xx_internal_irq_chip = { |
360 | .name = "bcm63xx_ipic", | 388 | .name = "bcm63xx_ipic", |
361 | .irq_mask = bcm63xx_internal_irq_mask, | 389 | .irq_mask = bcm63xx_internal_irq_mask, |
@@ -523,7 +551,13 @@ void __init arch_init_irq(void) | |||
523 | 551 | ||
524 | setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action); | 552 | setup_irq(MIPS_CPU_IRQ_BASE + 2, &cpu_ip2_cascade_action); |
525 | #ifdef CONFIG_SMP | 553 | #ifdef CONFIG_SMP |
526 | if (is_ext_irq_cascaded) | 554 | if (is_ext_irq_cascaded) { |
527 | setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action); | 555 | setup_irq(MIPS_CPU_IRQ_BASE + 3, &cpu_ip3_cascade_action); |
556 | bcm63xx_internal_irq_chip.irq_set_affinity = | ||
557 | bcm63xx_internal_set_affinity; | ||
558 | |||
559 | cpumask_clear(irq_default_affinity); | ||
560 | cpumask_set_cpu(smp_processor_id(), irq_default_affinity); | ||
561 | } | ||
528 | #endif | 562 | #endif |
529 | } | 563 | } |