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 | } |
