aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/leon_kernel.c
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-04-19 19:41:26 -0400
committerDavid S. Miller <davem@davemloft.net>2011-04-21 18:31:31 -0400
commit5eb1f4fc167f5adc5f15e722e25eff6713fb3406 (patch)
tree2e1ffeb506b3d09efc5e16045283430e3e362f63 /arch/sparc/kernel/leon_kernel.c
parenta481b5d0cb5d1884f16460b4846755518360f1ca (diff)
sparc32,leon: implement genirq CPU affinity
A simple implementation of CPU affinity, the first CPU in the affinity CPU mask always takes the IRQ. Signed-off-by: Daniel Hellstrom <daniel@gaisler.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/leon_kernel.c')
-rw-r--r--arch/sparc/kernel/leon_kernel.c64
1 files changed, 54 insertions, 10 deletions
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index d8fafeacb49..ab145845442 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -99,25 +99,68 @@ static inline unsigned long get_irqmask(unsigned int irq)
99 return mask; 99 return mask;
100} 100}
101 101
102#ifdef CONFIG_SMP
103static int irq_choose_cpu(const struct cpumask *affinity)
104{
105 cpumask_t mask;
106
107 cpus_and(mask, cpu_online_map, *affinity);
108 if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask))
109 return 0;
110 else
111 return first_cpu(mask);
112}
113#else
114#define irq_choose_cpu(affinity) 0
115#endif
116
117static int leon_set_affinity(struct irq_data *data, const struct cpumask *dest,
118 bool force)
119{
120 unsigned long mask, oldmask, flags;
121 int oldcpu, newcpu;
122
123 mask = (unsigned long)data->chip_data;
124 oldcpu = irq_choose_cpu(data->affinity);
125 newcpu = irq_choose_cpu(dest);
126
127 if (oldcpu == newcpu)
128 goto out;
129
130 /* unmask on old CPU first before enabling on the selected CPU */
131 spin_lock_irqsave(&leon_irq_lock, flags);
132 oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(oldcpu));
133 LEON3_BYPASS_STORE_PA(LEON_IMASK(oldcpu), (oldmask & ~mask));
134 oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(newcpu));
135 LEON3_BYPASS_STORE_PA(LEON_IMASK(newcpu), (oldmask | mask));
136 spin_unlock_irqrestore(&leon_irq_lock, flags);
137out:
138 return IRQ_SET_MASK_OK;
139}
140
102static void leon_unmask_irq(struct irq_data *data) 141static void leon_unmask_irq(struct irq_data *data)
103{ 142{
104 unsigned long mask, oldmask, flags; 143 unsigned long mask, oldmask, flags;
144 int cpu;
105 145
106 mask = (unsigned long)data->chip_data; 146 mask = (unsigned long)data->chip_data;
147 cpu = irq_choose_cpu(data->affinity);
107 spin_lock_irqsave(&leon_irq_lock, flags); 148 spin_lock_irqsave(&leon_irq_lock, flags);
108 oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0)); 149 oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu));
109 LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask | mask)); 150 LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask | mask));
110 spin_unlock_irqrestore(&leon_irq_lock, flags); 151 spin_unlock_irqrestore(&leon_irq_lock, flags);
111} 152}
112 153
113static void leon_mask_irq(struct irq_data *data) 154static void leon_mask_irq(struct irq_data *data)
114{ 155{
115 unsigned long mask, oldmask, flags; 156 unsigned long mask, oldmask, flags;
157 int cpu;
116 158
117 mask = (unsigned long)data->chip_data; 159 mask = (unsigned long)data->chip_data;
160 cpu = irq_choose_cpu(data->affinity);
118 spin_lock_irqsave(&leon_irq_lock, flags); 161 spin_lock_irqsave(&leon_irq_lock, flags);
119 oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(0)); 162 oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu));
120 LEON3_BYPASS_STORE_PA(LEON_IMASK(0), (oldmask & ~mask)); 163 LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask & ~mask));
121 spin_unlock_irqrestore(&leon_irq_lock, flags); 164 spin_unlock_irqrestore(&leon_irq_lock, flags);
122} 165}
123 166
@@ -144,12 +187,13 @@ static void leon_eoi_irq(struct irq_data *data)
144} 187}
145 188
146static struct irq_chip leon_irq = { 189static struct irq_chip leon_irq = {
147 .name = "leon", 190 .name = "leon",
148 .irq_startup = leon_startup_irq, 191 .irq_startup = leon_startup_irq,
149 .irq_shutdown = leon_shutdown_irq, 192 .irq_shutdown = leon_shutdown_irq,
150 .irq_mask = leon_mask_irq, 193 .irq_mask = leon_mask_irq,
151 .irq_unmask = leon_unmask_irq, 194 .irq_unmask = leon_unmask_irq,
152 .irq_eoi = leon_eoi_irq, 195 .irq_eoi = leon_eoi_irq,
196 .irq_set_affinity = leon_set_affinity,
153}; 197};
154 198
155/* 199/*