diff options
Diffstat (limited to 'arch/sparc/kernel/sun4d_smp.c')
-rw-r--r-- | arch/sparc/kernel/sun4d_smp.c | 119 |
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 | ||
36 | static void smp4d_ipi_init(void); | 40 | static void smp4d_ipi_init(void); |
37 | static void smp_setup_percpu_timer(void); | ||
38 | 41 | ||
39 | static unsigned char cpu_leds[32]; | 42 | static unsigned char cpu_leds[32]; |
40 | 43 | ||
@@ -49,7 +52,7 @@ static inline void show_leds(int cpuid) | |||
49 | 52 | ||
50 | void __cpuinit smp4d_callin(void) | 53 | void __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 | ||
130 | int __cpuinit smp4d_boot_one_cpu(int i) | 132 | int __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 | ||
236 | static 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 | |||
246 | static 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 | |||
251 | static 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 | ||
247 | static void smp4d_ipi_mask_one(int cpu) | 262 | static 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 | ||
258 | static void smp4d_ipi_resched(int cpu) | 273 | static 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 { | |||
280 | static DEFINE_SPINLOCK(cross_call_lock); | 295 | static 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. */ |
283 | static void smp4d_cross_call(smpfunc_t func, cpumask_t mask, unsigned long arg1, | 298 | static 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. */ |
353 | void smp4d_cross_call_irq(void) | 368 | void 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) | |||
363 | void smp4d_percpu_timer_interrupt(struct pt_regs *regs) | 378 | void 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 | ||
396 | static void __cpuinit smp_setup_percpu_timer(void) | 407 | static 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 | |||
404 | void __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 | |||
413 | void __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 | ||
422 | void __init sun4d_init_smp(void) | 414 | void __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; |