Skip to content

Commit

Permalink
sh: Support CPU affinity masks for INTC controllers.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Paul Mundt committed Mar 8, 2010
1 parent 25cf84c commit a8941da
Showing 1 changed file with 30 additions and 1 deletion.
31 changes: 30 additions & 1 deletion drivers/sh/intc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Shared interrupt handling code for IPR and INTC2 types of IRQs.
*
* Copyright (C) 2007, 2008 Magnus Damm
* Copyright (C) 2009 Paul Mundt
* Copyright (C) 2009, 2010 Paul Mundt
*
* Based on intc2.c and ipr.c
*
Expand All @@ -26,6 +26,7 @@
#include <linux/list.h>
#include <linux/topology.h>
#include <linux/bitmap.h>
#include <linux/cpumask.h>

#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
Expand Down Expand Up @@ -234,6 +235,10 @@ static inline void _intc_enable(unsigned int irq, unsigned long handle)
unsigned int cpu;

for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
#ifdef CONFIG_SMP
if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
continue;
#endif
addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
[_INTC_FN(handle)], irq);
Expand All @@ -253,6 +258,10 @@ static void intc_disable(unsigned int irq)
unsigned int cpu;

for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
#ifdef CONFIG_SMP
if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
continue;
#endif
addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
[_INTC_FN(handle)], irq);
Expand Down Expand Up @@ -301,6 +310,23 @@ static int intc_set_wake(unsigned int irq, unsigned int on)
return 0; /* allow wakeup, but setup hardware in intc_suspend() */
}

#ifdef CONFIG_SMP
/*
* This is held with the irq desc lock held, so we don't require any
* additional locking here at the intc desc level. The affinity mask is
* later tested in the enable/disable paths.
*/
static int intc_set_affinity(unsigned int irq, const struct cpumask *cpumask)
{
if (!cpumask_intersects(cpumask, cpu_online_mask))
return -1;

cpumask_copy(irq_to_desc(irq)->affinity, cpumask);

return 0;
}
#endif

static void intc_mask_ack(unsigned int irq)
{
struct intc_desc_int *d = get_intc_desc(irq);
Expand Down Expand Up @@ -843,6 +869,9 @@ void __init register_intc_controller(struct intc_desc *desc)
d->chip.shutdown = intc_disable;
d->chip.set_type = intc_set_sense;
d->chip.set_wake = intc_set_wake;
#ifdef CONFIG_SMP
d->chip.set_affinity = intc_set_affinity;
#endif

if (hw->ack_regs) {
for (i = 0; i < hw->nr_ack_regs; i++)
Expand Down

0 comments on commit a8941da

Please sign in to comment.