aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sh/intc.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-03-07 23:33:17 -0500
committerPaul Mundt <lethal@linux-sh.org>2010-03-07 23:33:17 -0500
commita8941dad1f12b4e8a87a517ed27f29d0209c817c (patch)
treead2efbcf2bd39f023450fe247f0a5622d671e780 /drivers/sh/intc.c
parent25cf84cf377c0aae5dbcf937ea89bc7893db5176 (diff)
sh: Support CPU affinity masks for INTC controllers.
This hooks up the ->set_affinity() for the INTC controllers, which can be done as just a simple copy of the cpumask. The enable/disable paths already handle SMP register strides, so we just test the affinity mask in these paths to determine which strides to skip over. The early enable/disable path happens prior to the IRQs being registered, so we have no affinity mask established at that point, in which case we just default to CPU_MASK_ALL. This is left as it is to permit the force enable/disable code to retain existing semantics. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/sh/intc.c')
-rw-r--r--drivers/sh/intc.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
index 3a5a17db9474..b8983fed76f5 100644
--- a/drivers/sh/intc.c
+++ b/drivers/sh/intc.c
@@ -2,7 +2,7 @@
2 * Shared interrupt handling code for IPR and INTC2 types of IRQs. 2 * Shared interrupt handling code for IPR and INTC2 types of IRQs.
3 * 3 *
4 * Copyright (C) 2007, 2008 Magnus Damm 4 * Copyright (C) 2007, 2008 Magnus Damm
5 * Copyright (C) 2009 Paul Mundt 5 * Copyright (C) 2009, 2010 Paul Mundt
6 * 6 *
7 * Based on intc2.c and ipr.c 7 * Based on intc2.c and ipr.c
8 * 8 *
@@ -26,6 +26,7 @@
26#include <linux/list.h> 26#include <linux/list.h>
27#include <linux/topology.h> 27#include <linux/topology.h>
28#include <linux/bitmap.h> 28#include <linux/bitmap.h>
29#include <linux/cpumask.h>
29 30
30#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ 31#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
31 ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ 32 ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
@@ -234,6 +235,10 @@ static inline void _intc_enable(unsigned int irq, unsigned long handle)
234 unsigned int cpu; 235 unsigned int cpu;
235 236
236 for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) { 237 for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
238#ifdef CONFIG_SMP
239 if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
240 continue;
241#endif
237 addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu); 242 addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
238 intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\ 243 intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
239 [_INTC_FN(handle)], irq); 244 [_INTC_FN(handle)], irq);
@@ -253,6 +258,10 @@ static void intc_disable(unsigned int irq)
253 unsigned int cpu; 258 unsigned int cpu;
254 259
255 for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) { 260 for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
261#ifdef CONFIG_SMP
262 if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
263 continue;
264#endif
256 addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu); 265 addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
257 intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\ 266 intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
258 [_INTC_FN(handle)], irq); 267 [_INTC_FN(handle)], irq);
@@ -301,6 +310,23 @@ static int intc_set_wake(unsigned int irq, unsigned int on)
301 return 0; /* allow wakeup, but setup hardware in intc_suspend() */ 310 return 0; /* allow wakeup, but setup hardware in intc_suspend() */
302} 311}
303 312
313#ifdef CONFIG_SMP
314/*
315 * This is held with the irq desc lock held, so we don't require any
316 * additional locking here at the intc desc level. The affinity mask is
317 * later tested in the enable/disable paths.
318 */
319static int intc_set_affinity(unsigned int irq, const struct cpumask *cpumask)
320{
321 if (!cpumask_intersects(cpumask, cpu_online_mask))
322 return -1;
323
324 cpumask_copy(irq_to_desc(irq)->affinity, cpumask);
325
326 return 0;
327}
328#endif
329
304static void intc_mask_ack(unsigned int irq) 330static void intc_mask_ack(unsigned int irq)
305{ 331{
306 struct intc_desc_int *d = get_intc_desc(irq); 332 struct intc_desc_int *d = get_intc_desc(irq);
@@ -843,6 +869,9 @@ void __init register_intc_controller(struct intc_desc *desc)
843 d->chip.shutdown = intc_disable; 869 d->chip.shutdown = intc_disable;
844 d->chip.set_type = intc_set_sense; 870 d->chip.set_type = intc_set_sense;
845 d->chip.set_wake = intc_set_wake; 871 d->chip.set_wake = intc_set_wake;
872#ifdef CONFIG_SMP
873 d->chip.set_affinity = intc_set_affinity;
874#endif
846 875
847 if (hw->ack_regs) { 876 if (hw->ack_regs) {
848 for (i = 0; i < hw->nr_ack_regs; i++) 877 for (i = 0; i < hw->nr_ack_regs; i++)