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.c119
1 files changed, 52 insertions, 67 deletions
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c
index 540b2fec09f0..f9a1a33cbb2c 100644
--- a/arch/sparc/kernel/sun4d_smp.c
+++ b/arch/sparc/kernel/sun4d_smp.c
@@ -6,16 +6,20 @@
6 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) 6 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
7 */ 7 */
8 8
9#include <linux/clockchips.h>
9#include <linux/interrupt.h> 10#include <linux/interrupt.h>
10#include <linux/profile.h> 11#include <linux/profile.h>
11#include <linux/delay.h> 12#include <linux/delay.h>
13#include <linux/sched.h>
12#include <linux/cpu.h> 14#include <linux/cpu.h>
13 15
16#include <asm/cacheflush.h>
17#include <asm/switch_to.h>
18#include <asm/tlbflush.h>
19#include <asm/timer.h>
20#include <asm/oplib.h>
14#include <asm/sbi.h> 21#include <asm/sbi.h>
15#include <asm/mmu.h> 22#include <asm/mmu.h>
16#include <asm/tlbflush.h>
17#include <asm/switch_to.h>
18#include <asm/cacheflush.h>
19 23
20#include "kernel.h" 24#include "kernel.h"
21#include "irq.h" 25#include "irq.h"
@@ -34,7 +38,6 @@ static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned lon
34} 38}
35 39
36static void smp4d_ipi_init(void); 40static void smp4d_ipi_init(void);
37static void smp_setup_percpu_timer(void);
38 41
39static unsigned char cpu_leds[32]; 42static unsigned char cpu_leds[32];
40 43
@@ -49,7 +52,7 @@ static inline void show_leds(int cpuid)
49 52
50void __cpuinit smp4d_callin(void) 53void __cpuinit smp4d_callin(void)
51{ 54{
52 int cpuid = hard_smp4d_processor_id(); 55 int cpuid = hard_smp_processor_id();
53 unsigned long flags; 56 unsigned long flags;
54 57
55 /* Show we are alive */ 58 /* Show we are alive */
@@ -59,8 +62,8 @@ void __cpuinit smp4d_callin(void)
59 /* Enable level15 interrupt, disable level14 interrupt for now */ 62 /* Enable level15 interrupt, disable level14 interrupt for now */
60 cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000); 63 cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000);
61 64
62 local_flush_cache_all(); 65 local_ops->cache_all();
63 local_flush_tlb_all(); 66 local_ops->tlb_all();
64 67
65 notify_cpu_starting(cpuid); 68 notify_cpu_starting(cpuid);
66 /* 69 /*
@@ -70,17 +73,17 @@ void __cpuinit smp4d_callin(void)
70 * to call the scheduler code. 73 * to call the scheduler code.
71 */ 74 */
72 /* Get our local ticker going. */ 75 /* Get our local ticker going. */
73 smp_setup_percpu_timer(); 76 register_percpu_ce(cpuid);
74 77
75 calibrate_delay(); 78 calibrate_delay();
76 smp_store_cpu_info(cpuid); 79 smp_store_cpu_info(cpuid);
77 local_flush_cache_all(); 80 local_ops->cache_all();
78 local_flush_tlb_all(); 81 local_ops->tlb_all();
79 82
80 /* Allow master to continue. */ 83 /* Allow master to continue. */
81 sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1); 84 sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1);
82 local_flush_cache_all(); 85 local_ops->cache_all();
83 local_flush_tlb_all(); 86 local_ops->tlb_all();
84 87
85 while ((unsigned long)current_set[cpuid] < PAGE_OFFSET) 88 while ((unsigned long)current_set[cpuid] < PAGE_OFFSET)
86 barrier(); 89 barrier();
@@ -100,8 +103,8 @@ void __cpuinit smp4d_callin(void)
100 atomic_inc(&init_mm.mm_count); 103 atomic_inc(&init_mm.mm_count);
101 current->active_mm = &init_mm; 104 current->active_mm = &init_mm;
102 105
103 local_flush_cache_all(); 106 local_ops->cache_all();
104 local_flush_tlb_all(); 107 local_ops->tlb_all();
105 108
106 local_irq_enable(); /* We don't allow PIL 14 yet */ 109 local_irq_enable(); /* We don't allow PIL 14 yet */
107 110
@@ -123,8 +126,7 @@ void __init smp4d_boot_cpus(void)
123 smp4d_ipi_init(); 126 smp4d_ipi_init();
124 if (boot_cpu_id) 127 if (boot_cpu_id)
125 current_set[0] = NULL; 128 current_set[0] = NULL;
126 smp_setup_percpu_timer(); 129 local_ops->cache_all();
127 local_flush_cache_all();
128} 130}
129 131
130int __cpuinit smp4d_boot_one_cpu(int i) 132int __cpuinit smp4d_boot_one_cpu(int i)
@@ -150,7 +152,7 @@ int __cpuinit smp4d_boot_one_cpu(int i)
150 152
151 /* whirrr, whirrr, whirrrrrrrrr... */ 153 /* whirrr, whirrr, whirrrrrrrrr... */
152 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry); 154 printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
153 local_flush_cache_all(); 155 local_ops->cache_all();
154 prom_startcpu(cpu_node, 156 prom_startcpu(cpu_node,
155 &smp_penguin_ctable, 0, (char *)entry); 157 &smp_penguin_ctable, 0, (char *)entry);
156 158
@@ -168,7 +170,7 @@ int __cpuinit smp4d_boot_one_cpu(int i)
168 return -ENODEV; 170 return -ENODEV;
169 171
170 } 172 }
171 local_flush_cache_all(); 173 local_ops->cache_all();
172 return 0; 174 return 0;
173} 175}
174 176
@@ -185,7 +187,7 @@ void __init smp4d_smp_done(void)
185 prev = &cpu_data(i).next; 187 prev = &cpu_data(i).next;
186 } 188 }
187 *prev = first; 189 *prev = first;
188 local_flush_cache_all(); 190 local_ops->cache_all();
189 191
190 /* Ok, they are spinning and ready to go. */ 192 /* Ok, they are spinning and ready to go. */
191 smp_processors_ready = 1; 193 smp_processors_ready = 1;
@@ -233,7 +235,20 @@ void sun4d_ipi_interrupt(void)
233 } 235 }
234} 236}
235 237
236static void smp4d_ipi_single(int cpu) 238/* +-------+-------------+-----------+------------------------------------+
239 * | bcast | devid | sid | levels mask |
240 * +-------+-------------+-----------+------------------------------------+
241 * 31 30 23 22 15 14 0
242 */
243#define IGEN_MESSAGE(bcast, devid, sid, levels) \
244 (((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels))
245
246static void sun4d_send_ipi(int cpu, int level)
247{
248 cc_set_igen(IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1)));
249}
250
251static void sun4d_ipi_single(int cpu)
237{ 252{
238 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); 253 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
239 254
@@ -244,7 +259,7 @@ static void smp4d_ipi_single(int cpu)
244 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); 259 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
245} 260}
246 261
247static void smp4d_ipi_mask_one(int cpu) 262static void sun4d_ipi_mask_one(int cpu)
248{ 263{
249 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); 264 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
250 265
@@ -255,7 +270,7 @@ static void smp4d_ipi_mask_one(int cpu)
255 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ); 270 sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
256} 271}
257 272
258static void smp4d_ipi_resched(int cpu) 273static void sun4d_ipi_resched(int cpu)
259{ 274{
260 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu); 275 struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);
261 276
@@ -280,7 +295,7 @@ static struct smp_funcall {
280static DEFINE_SPINLOCK(cross_call_lock); 295static DEFINE_SPINLOCK(cross_call_lock);
281 296
282/* Cross calls must be serialized, at least currently. */ 297/* Cross calls must be serialized, at least currently. */
283static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, 298static void sun4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
284 unsigned long arg2, unsigned long arg3, 299 unsigned long arg2, unsigned long arg3,
285 unsigned long arg4) 300 unsigned long arg4)
286{ 301{
@@ -352,7 +367,7 @@ static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1,
352/* Running cross calls. */ 367/* Running cross calls. */
353void smp4d_cross_call_irq(void) 368void smp4d_cross_call_irq(void)
354{ 369{
355 int i = hard_smp4d_processor_id(); 370 int i = hard_smp_processor_id();
356 371
357 ccall_info.processors_in[i] = 1; 372 ccall_info.processors_in[i] = 1;
358 ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3, 373 ccall_info.func(ccall_info.arg1, ccall_info.arg2, ccall_info.arg3,
@@ -363,7 +378,8 @@ void smp4d_cross_call_irq(void)
363void smp4d_percpu_timer_interrupt(struct pt_regs *regs) 378void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
364{ 379{
365 struct pt_regs *old_regs; 380 struct pt_regs *old_regs;
366 int cpu = hard_smp4d_processor_id(); 381 int cpu = hard_smp_processor_id();
382 struct clock_event_device *ce;
367 static int cpu_tick[NR_CPUS]; 383 static int cpu_tick[NR_CPUS];
368 static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd }; 384 static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd };
369 385
@@ -379,45 +395,21 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
379 show_leds(cpu); 395 show_leds(cpu);
380 } 396 }
381 397
382 profile_tick(CPU_PROFILING); 398 ce = &per_cpu(sparc32_clockevent, cpu);
383
384 if (!--prof_counter(cpu)) {
385 int user = user_mode(regs);
386 399
387 irq_enter(); 400 irq_enter();
388 update_process_times(user); 401 ce->event_handler(ce);
389 irq_exit(); 402 irq_exit();
390 403
391 prof_counter(cpu) = prof_multiplier(cpu);
392 }
393 set_irq_regs(old_regs); 404 set_irq_regs(old_regs);
394} 405}
395 406
396static void __cpuinit smp_setup_percpu_timer(void) 407static const struct sparc32_ipi_ops sun4d_ipi_ops = {
397{ 408 .cross_call = sun4d_cross_call,
398 int cpu = hard_smp4d_processor_id(); 409 .resched = sun4d_ipi_resched,
399 410 .single = sun4d_ipi_single,
400 prof_counter(cpu) = prof_multiplier(cpu) = 1; 411 .mask_one = sun4d_ipi_mask_one,
401 load_profile_irq(cpu, lvl14_resolution); 412};
402}
403
404void __init smp4d_blackbox_id(unsigned *addr)
405{
406 int rd = *addr & 0x3e000000;
407
408 addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */
409 addr[1] = 0x01000000; /* nop */
410 addr[2] = 0x01000000; /* nop */
411}
412
413void __init smp4d_blackbox_current(unsigned *addr)
414{
415 int rd = *addr & 0x3e000000;
416
417 addr[0] = 0xc0800800 | rd; /* lda [%g0] ASI_M_VIKING_TMP1, reg */
418 addr[2] = 0x81282002 | rd | (rd >> 11); /* sll reg, 2, reg */
419 addr[4] = 0x01000000; /* nop */
420}
421 413
422void __init sun4d_init_smp(void) 414void __init sun4d_init_smp(void)
423{ 415{
@@ -426,14 +418,7 @@ void __init sun4d_init_smp(void)
426 /* Patch ipi15 trap table */ 418 /* Patch ipi15 trap table */
427 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m); 419 t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m);
428 420
429 /* And set btfixup... */ 421 sparc32_ipi_ops = &sun4d_ipi_ops;
430 BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id);
431 BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
432 BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
433 BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
434 BTFIXUPSET_CALL(smp_ipi_resched, smp4d_ipi_resched, BTFIXUPCALL_NORM);
435 BTFIXUPSET_CALL(smp_ipi_single, smp4d_ipi_single, BTFIXUPCALL_NORM);
436 BTFIXUPSET_CALL(smp_ipi_mask_one, smp4d_ipi_mask_one, BTFIXUPCALL_NORM);
437 422
438 for (i = 0; i < NR_CPUS; i++) { 423 for (i = 0; i < NR_CPUS; i++) {
439 ccall_info.processors_in[i] = 1; 424 ccall_info.processors_in[i] = 1;