aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/sun4d_smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/sun4d_smp.c')
-rw-r--r--arch/sparc/kernel/sun4d_smp.c93
1 files changed, 85 insertions, 8 deletions
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 475d50b96cd0..133387980b56 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -32,6 +32,7 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon
32 return val; 32 return val;
33} 33}
34 34
35static void smp4d_ipi_init(void);
35static void smp_setup_percpu_timer(void); 36static void smp_setup_percpu_timer(void);
36 37
37static unsigned char cpu_leds[32]; 38static unsigned char cpu_leds[32];
@@ -80,8 +81,6 @@ void __cpuinit smp4d_callin(void)
80 local_flush_cache_all(); 81 local_flush_cache_all();
81 local_flush_tlb_all(); 82 local_flush_tlb_all();
82 83
83 cpu_probe();
84
85 while ((unsigned long)current_set[cpuid] < PAGE_OFFSET) 84 while ((unsigned long)current_set[cpuid] < PAGE_OFFSET)
86 barrier(); 85 barrier();
87 86
@@ -105,7 +104,7 @@ void __cpuinit smp4d_callin(void)
105 104
106 local_irq_enable(); /* We don't allow PIL 14 yet */ 105 local_irq_enable(); /* We don't allow PIL 14 yet */
107 106
108 while (!cpu_isset(cpuid, smp_commenced_mask)) 107 while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
109 barrier(); 108 barrier();
110 109
111 spin_lock_irqsave(&sun4d_imsk_lock, flags); 110 spin_lock_irqsave(&sun4d_imsk_lock, flags);
@@ -120,6 +119,7 @@ void __cpuinit smp4d_callin(void)
120 */ 119 */
121void __init smp4d_boot_cpus(void) 120void __init smp4d_boot_cpus(void)
122{ 121{
122 smp4d_ipi_init();
123 if (boot_cpu_id) 123 if (boot_cpu_id)
124 current_set[0] = NULL; 124 current_set[0] = NULL;
125 smp_setup_percpu_timer(); 125 smp_setup_percpu_timer();
@@ -191,6 +191,80 @@ void __init smp4d_smp_done(void)
191 sun4d_distribute_irqs(); 191 sun4d_distribute_irqs();
192} 192}
193 193
194/* Memory structure giving interrupt handler information about IPI generated */
195struct sun4d_ipi_work {
196 int single;
197 int msk;
198 int resched;
199};
200
201static DEFINE_PER_CPU_SHARED_ALIGNED(struct sun4d_ipi_work, sun4d_ipi_work);
202
203/* Initialize IPIs on the SUN4D SMP machine */
204static void __init smp4d_ipi_init(void)
205{
206 int cpu;
207 struct sun4d_ipi_work *work;
208
209 printk(KERN_INFO "smp4d: setup IPI at IRQ %d\n", SUN4D_IPI_IRQ);
210
211 for_each_possible_cpu(cpu) {
212 work = &per_cpu(sun4d_ipi_work, cpu);
213 work->single = work->msk = work->resched = 0;
214 }
215}
216
217void sun4d_ipi_interrupt(void)
218{
219 struct sun4d_ipi_work *work = &__get_cpu_var(sun4d_ipi_work);
220
221 if (work->single) {
222 work->single = 0;
223 smp_call_function_single_interrupt();
224 }
225 if (work->msk) {
226 work->msk = 0;
227 smp_call_function_interrupt();
228 }
229 if (work->resched) {
230 work->resched = 0;
231 smp_resched_interrupt();
232 }
233}
234
235static void smp4d_ipi_single(int cpu)
236{
237 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
238
239 /* Mark work */
240 work->single = 1;
241
242 /* Generate IRQ on the CPU */
243 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
244}
245
246static void smp4d_ipi_mask_one(int cpu)
247{
248 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
249
250 /* Mark work */
251 work->msk = 1;
252
253 /* Generate IRQ on the CPU */
254 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
255}
256
257static void smp4d_ipi_resched(int cpu)
258{
259 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
260
261 /* Mark work */
262 work->resched = 1;
263
264 /* Generate IRQ on the CPU (any IRQ will cause resched) */
265 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
266}
267
194static struct smp_funcall { 268static struct smp_funcall {
195 smpfunc_t func; 269 smpfunc_t func;
196 unsigned long arg1; 270 unsigned long arg1;
@@ -239,10 +313,10 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
239 { 313 {
240 register int i; 314 register int i;
241 315
242 cpu_clear(smp_processor_id(), mask); 316 cpumask_clear_cpu(smp_processor_id(), &mask);
243 cpus_and(mask, cpu_online_map, mask); 317 cpumask_and(&mask, cpu_online_mask, &mask);
244 for (i = 0; i <= high; i++) { 318 for (i = 0; i <= high; i++) {
245 if (cpu_isset(i, mask)) { 319 if (cpumask_test_cpu(i, &mask)) {
246 ccall_info.processors_in[i] = 0; 320 ccall_info.processors_in[i] = 0;
247 ccall_info.processors_out[i] = 0; 321 ccall_info.processors_out[i] = 0;
248 sun4d_send_ipi(i, IRQ_CROSS_CALL); 322 sun4d_send_ipi(i, IRQ_CROSS_CALL);
@@ -255,7 +329,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
255 329
256 i = 0; 330 i = 0;
257 do { 331 do {
258 if (!cpu_isset(i, mask)) 332 if (!cpumask_test_cpu(i, &mask))
259 continue; 333 continue;
260 while (!ccall_info.processors_in[i]) 334 while (!ccall_info.processors_in[i])
261 barrier(); 335 barrier();
@@ -263,7 +337,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
263 337
264 i = 0; 338 i = 0;
265 do { 339 do {
266 if (!cpu_isset(i, mask)) 340 if (!cpumask_test_cpu(i, &mask))
267 continue; 341 continue;
268 while (!ccall_info.processors_out[i]) 342 while (!ccall_info.processors_out[i])
269 barrier(); 343 barrier();
@@ -356,6 +430,9 @@ void __init sun4d_init_smp(void)
356 BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current); 430 BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
357 BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM); 431 BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
358 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM); 432 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
433 BTFIXUPSET_CALL(smp_ipi_resched, smp4d_ipi_resched, BTFIXUPCALL_NORM);
434 BTFIXUPSET_CALL(smp_ipi_single, smp4d_ipi_single, BTFIXUPCALL_NORM);
435 BTFIXUPSET_CALL(smp_ipi_mask_one, smp4d_ipi_mask_one, BTFIXUPCALL_NORM);
359 436
360 for (i = 0; i < NR_CPUS; i++) { 437 for (i = 0; i < NR_CPUS; i++) {
361 ccall_info.processors_in[i] = 1; 438 ccall_info.processors_in[i] = 1;