diff options
| author | Sam Ravnborg <sam@ravnborg.org> | 2013-02-15 09:52:06 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2013-02-20 16:36:50 -0500 |
| commit | f9fd3488f6a3c2c5cc8613e4fd7fbbaa57f6bf8f (patch) | |
| tree | dfc2f084424f34f257dcca83d495bf216dcdfd2b | |
| parent | 76968ad2eac6456270353de168b21f04f4b3d1d3 (diff) | |
sparc32: refactor smp boot
Introduce a common smp_callin() function to call
from trampoline_32.S.
Add platform specific functions to handle the
platform details.
This is in preparation for a patch that will
unify the smp boot stuff for all architectures.
sparc32 was significantly different to warrant
this patch in preparation.
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Acked-by: David S. Miller <davem@davemloft.net>
Cc: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Acked-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | arch/sparc/kernel/kernel.h | 12 | ||||
| -rw-r--r-- | arch/sparc/kernel/leon_smp.c | 33 | ||||
| -rw-r--r-- | arch/sparc/kernel/smp_32.c | 86 | ||||
| -rw-r--r-- | arch/sparc/kernel/sun4d_smp.c | 29 | ||||
| -rw-r--r-- | arch/sparc/kernel/sun4m_smp.c | 33 | ||||
| -rw-r--r-- | arch/sparc/kernel/trampoline_32.S | 17 |
6 files changed, 132 insertions, 78 deletions
diff --git a/arch/sparc/kernel/kernel.h b/arch/sparc/kernel/kernel.h index 291bb5de9ce0..a702d9ab019c 100644 --- a/arch/sparc/kernel/kernel.h +++ b/arch/sparc/kernel/kernel.h | |||
| @@ -48,6 +48,10 @@ extern void sun4m_init_IRQ(void); | |||
| 48 | extern void sun4m_unmask_profile_irq(void); | 48 | extern void sun4m_unmask_profile_irq(void); |
| 49 | extern void sun4m_clear_profile_irq(int cpu); | 49 | extern void sun4m_clear_profile_irq(int cpu); |
| 50 | 50 | ||
| 51 | /* sun4m_smp.c */ | ||
| 52 | void sun4m_cpu_pre_starting(void *arg); | ||
| 53 | void sun4m_cpu_pre_online(void *arg); | ||
| 54 | |||
| 51 | /* sun4d_irq.c */ | 55 | /* sun4d_irq.c */ |
| 52 | extern spinlock_t sun4d_imsk_lock; | 56 | extern spinlock_t sun4d_imsk_lock; |
| 53 | 57 | ||
| @@ -60,6 +64,14 @@ extern int show_sun4d_interrupts(struct seq_file *, void *); | |||
| 60 | extern void sun4d_distribute_irqs(void); | 64 | extern void sun4d_distribute_irqs(void); |
| 61 | extern void sun4d_free_irq(unsigned int irq, void *dev_id); | 65 | extern void sun4d_free_irq(unsigned int irq, void *dev_id); |
| 62 | 66 | ||
| 67 | /* sun4d_smp.c */ | ||
| 68 | void sun4d_cpu_pre_starting(void *arg); | ||
| 69 | void sun4d_cpu_pre_online(void *arg); | ||
| 70 | |||
| 71 | /* leon_smp.c */ | ||
| 72 | void leon_cpu_pre_starting(void *arg); | ||
| 73 | void leon_cpu_pre_online(void *arg); | ||
| 74 | |||
| 63 | /* head_32.S */ | 75 | /* head_32.S */ |
| 64 | extern unsigned int t_nmi[]; | 76 | extern unsigned int t_nmi[]; |
| 65 | extern unsigned int linux_trap_ipi15_sun4d[]; | 77 | extern unsigned int linux_trap_ipi15_sun4d[]; |
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 0f3fb6d9c8ef..9b40c9c12a0c 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c | |||
| @@ -69,31 +69,19 @@ static inline unsigned long do_swap(volatile unsigned long *ptr, | |||
| 69 | return val; | 69 | return val; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | void __cpuinit leon_callin(void) | 72 | void __cpuinit leon_cpu_pre_starting(void *arg) |
| 73 | { | 73 | { |
| 74 | int cpuid = hard_smp_processor_id(); | ||
| 75 | |||
| 76 | local_ops->cache_all(); | ||
| 77 | local_ops->tlb_all(); | ||
| 78 | leon_configure_cache_smp(); | 74 | leon_configure_cache_smp(); |
| 75 | } | ||
| 79 | 76 | ||
| 80 | notify_cpu_starting(cpuid); | 77 | void __cpuinit leon_cpu_pre_online(void *arg) |
| 81 | 78 | { | |
| 82 | /* Get our local ticker going. */ | 79 | int cpuid = hard_smp_processor_id(); |
| 83 | register_percpu_ce(cpuid); | ||
| 84 | |||
| 85 | calibrate_delay(); | ||
| 86 | smp_store_cpu_info(cpuid); | ||
| 87 | |||
| 88 | local_ops->cache_all(); | ||
| 89 | local_ops->tlb_all(); | ||
| 90 | 80 | ||
| 91 | /* | 81 | /* Allow master to continue. The master will then give us the |
| 92 | * Unblock the master CPU _only_ when the scheduler state | 82 | * go-ahead by setting the smp_commenced_mask and will wait without |
| 93 | * of all secondary CPUs will be up-to-date, so after | 83 | * timeouts until our setup is completed fully (signified by |
| 94 | * the SMP initialization the master will be just allowed | 84 | * our bit being set in the cpu_online_mask). |
| 95 | * to call the scheduler code. | ||
| 96 | * Allow master to continue. | ||
| 97 | */ | 85 | */ |
| 98 | do_swap(&cpu_callin_map[cpuid], 1); | 86 | do_swap(&cpu_callin_map[cpuid], 1); |
| 99 | 87 | ||
| @@ -110,9 +98,6 @@ void __cpuinit leon_callin(void) | |||
| 110 | 98 | ||
| 111 | while (!cpumask_test_cpu(cpuid, &smp_commenced_mask)) | 99 | while (!cpumask_test_cpu(cpuid, &smp_commenced_mask)) |
| 112 | mb(); | 100 | mb(); |
| 113 | |||
| 114 | local_irq_enable(); | ||
| 115 | set_cpu_online(cpuid, true); | ||
| 116 | } | 101 | } |
| 117 | 102 | ||
| 118 | /* | 103 | /* |
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index 79db45e5134a..9e7e6d718367 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
| 21 | #include <linux/cache.h> | 21 | #include <linux/cache.h> |
| 22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| 23 | #include <linux/cpu.h> | ||
| 23 | 24 | ||
| 24 | #include <asm/ptrace.h> | 25 | #include <asm/ptrace.h> |
| 25 | #include <linux/atomic.h> | 26 | #include <linux/atomic.h> |
| @@ -32,8 +33,10 @@ | |||
| 32 | #include <asm/cacheflush.h> | 33 | #include <asm/cacheflush.h> |
| 33 | #include <asm/tlbflush.h> | 34 | #include <asm/tlbflush.h> |
| 34 | #include <asm/cpudata.h> | 35 | #include <asm/cpudata.h> |
| 36 | #include <asm/timer.h> | ||
| 35 | #include <asm/leon.h> | 37 | #include <asm/leon.h> |
| 36 | 38 | ||
| 39 | #include "kernel.h" | ||
| 37 | #include "irq.h" | 40 | #include "irq.h" |
| 38 | 41 | ||
| 39 | volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,}; | 42 | volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,}; |
| @@ -294,6 +297,89 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle) | |||
| 294 | return ret; | 297 | return ret; |
| 295 | } | 298 | } |
| 296 | 299 | ||
| 300 | void __cpuinit arch_cpu_pre_starting(void *arg) | ||
| 301 | { | ||
| 302 | local_ops->cache_all(); | ||
| 303 | local_ops->tlb_all(); | ||
| 304 | |||
| 305 | switch(sparc_cpu_model) { | ||
| 306 | case sun4m: | ||
| 307 | sun4m_cpu_pre_starting(arg); | ||
| 308 | break; | ||
| 309 | case sun4d: | ||
| 310 | sun4d_cpu_pre_starting(arg); | ||
| 311 | break; | ||
| 312 | case sparc_leon: | ||
| 313 | leon_cpu_pre_starting(arg); | ||
| 314 | break; | ||
| 315 | default: | ||
| 316 | BUG(); | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | void __cpuinit arch_cpu_pre_online(void *arg) | ||
| 321 | { | ||
| 322 | unsigned int cpuid = hard_smp_processor_id(); | ||
| 323 | |||
| 324 | register_percpu_ce(cpuid); | ||
| 325 | |||
| 326 | calibrate_delay(); | ||
| 327 | smp_store_cpu_info(cpuid); | ||
| 328 | |||
| 329 | local_ops->cache_all(); | ||
| 330 | local_ops->tlb_all(); | ||
| 331 | |||
| 332 | switch(sparc_cpu_model) { | ||
| 333 | case sun4m: | ||
| 334 | sun4m_cpu_pre_online(arg); | ||
| 335 | break; | ||
| 336 | case sun4d: | ||
| 337 | sun4d_cpu_pre_online(arg); | ||
| 338 | break; | ||
| 339 | case sparc_leon: | ||
| 340 | leon_cpu_pre_online(arg); | ||
| 341 | break; | ||
| 342 | default: | ||
| 343 | BUG(); | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | void __cpuinit sparc_start_secondary(void *arg) | ||
| 348 | { | ||
| 349 | unsigned int cpu; | ||
| 350 | |||
| 351 | /* | ||
| 352 | * SMP booting is extremely fragile in some architectures. So run | ||
| 353 | * the cpu initialization code first before anything else. | ||
| 354 | */ | ||
| 355 | arch_cpu_pre_starting(arg); | ||
| 356 | |||
| 357 | preempt_disable(); | ||
| 358 | cpu = smp_processor_id(); | ||
| 359 | |||
| 360 | /* Invoke the CPU_STARTING notifier callbacks */ | ||
| 361 | notify_cpu_starting(cpu); | ||
| 362 | |||
| 363 | arch_cpu_pre_online(arg); | ||
| 364 | |||
| 365 | /* Set the CPU in the cpu_online_mask */ | ||
| 366 | set_cpu_online(cpu, true); | ||
| 367 | |||
| 368 | /* Enable local interrupts now */ | ||
| 369 | local_irq_enable(); | ||
| 370 | |||
| 371 | wmb(); | ||
| 372 | cpu_idle(); | ||
| 373 | |||
| 374 | /* We should never reach here! */ | ||
| 375 | BUG(); | ||
| 376 | } | ||
| 377 | |||
| 378 | void __cpuinit smp_callin(void) | ||
| 379 | { | ||
| 380 | sparc_start_secondary(NULL); | ||
| 381 | } | ||
| 382 | |||
| 297 | void smp_bogo(struct seq_file *m) | 383 | void smp_bogo(struct seq_file *m) |
| 298 | { | 384 | { |
| 299 | int i; | 385 | int i; |
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index ddaea31de586..c9eb82f23d92 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c | |||
| @@ -50,10 +50,9 @@ static inline void show_leds(int cpuid) | |||
| 50 | "i" (ASI_M_CTL)); | 50 | "i" (ASI_M_CTL)); |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | void __cpuinit smp4d_callin(void) | 53 | void __cpuinit sun4d_cpu_pre_starting(void *arg) |
| 54 | { | 54 | { |
| 55 | int cpuid = hard_smp_processor_id(); | 55 | int cpuid = hard_smp_processor_id(); |
| 56 | unsigned long flags; | ||
| 57 | 56 | ||
| 58 | /* Show we are alive */ | 57 | /* Show we are alive */ |
| 59 | cpu_leds[cpuid] = 0x6; | 58 | cpu_leds[cpuid] = 0x6; |
| @@ -61,26 +60,20 @@ void __cpuinit smp4d_callin(void) | |||
| 61 | 60 | ||
| 62 | /* Enable level15 interrupt, disable level14 interrupt for now */ | 61 | /* Enable level15 interrupt, disable level14 interrupt for now */ |
| 63 | cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000); | 62 | cc_set_imsk((cc_get_imsk() & ~0x8000) | 0x4000); |
| 63 | } | ||
| 64 | 64 | ||
| 65 | local_ops->cache_all(); | 65 | void __cpuinit sun4d_cpu_pre_online(void *arg) |
| 66 | local_ops->tlb_all(); | 66 | { |
| 67 | unsigned long flags; | ||
| 68 | int cpuid; | ||
| 67 | 69 | ||
| 68 | notify_cpu_starting(cpuid); | 70 | cpuid = hard_smp_processor_id(); |
| 69 | /* | 71 | |
| 70 | * Unblock the master CPU _only_ when the scheduler state | 72 | /* Unblock the master CPU _only_ when the scheduler state |
| 71 | * of all secondary CPUs will be up-to-date, so after | 73 | * of all secondary CPUs will be up-to-date, so after |
| 72 | * the SMP initialization the master will be just allowed | 74 | * the SMP initialization the master will be just allowed |
| 73 | * to call the scheduler code. | 75 | * to call the scheduler code. |
| 74 | */ | 76 | */ |
| 75 | /* Get our local ticker going. */ | ||
| 76 | register_percpu_ce(cpuid); | ||
| 77 | |||
| 78 | calibrate_delay(); | ||
| 79 | smp_store_cpu_info(cpuid); | ||
| 80 | local_ops->cache_all(); | ||
| 81 | local_ops->tlb_all(); | ||
| 82 | |||
| 83 | /* Allow master to continue. */ | ||
| 84 | sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1); | 77 | sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1); |
| 85 | local_ops->cache_all(); | 78 | local_ops->cache_all(); |
| 86 | local_ops->tlb_all(); | 79 | local_ops->tlb_all(); |
| @@ -106,16 +99,12 @@ void __cpuinit smp4d_callin(void) | |||
| 106 | local_ops->cache_all(); | 99 | local_ops->cache_all(); |
| 107 | local_ops->tlb_all(); | 100 | local_ops->tlb_all(); |
| 108 | 101 | ||
| 109 | local_irq_enable(); /* We don't allow PIL 14 yet */ | ||
| 110 | |||
| 111 | while (!cpumask_test_cpu(cpuid, &smp_commenced_mask)) | 102 | while (!cpumask_test_cpu(cpuid, &smp_commenced_mask)) |
| 112 | barrier(); | 103 | barrier(); |
| 113 | 104 | ||
| 114 | spin_lock_irqsave(&sun4d_imsk_lock, flags); | 105 | spin_lock_irqsave(&sun4d_imsk_lock, flags); |
| 115 | cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */ | 106 | cc_set_imsk(cc_get_imsk() & ~0x4000); /* Allow PIL 14 as well */ |
| 116 | spin_unlock_irqrestore(&sun4d_imsk_lock, flags); | 107 | spin_unlock_irqrestore(&sun4d_imsk_lock, flags); |
| 117 | set_cpu_online(cpuid, true); | ||
| 118 | |||
| 119 | } | 108 | } |
| 120 | 109 | ||
| 121 | /* | 110 | /* |
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 128af7304288..8a65f158153d 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c | |||
| @@ -34,30 +34,19 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val) | |||
| 34 | return val; | 34 | return val; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | void __cpuinit smp4m_callin(void) | 37 | void __cpuinit sun4m_cpu_pre_starting(void *arg) |
| 38 | { | 38 | { |
| 39 | int cpuid = hard_smp_processor_id(); | 39 | } |
| 40 | |||
| 41 | local_ops->cache_all(); | ||
| 42 | local_ops->tlb_all(); | ||
| 43 | |||
| 44 | notify_cpu_starting(cpuid); | ||
| 45 | |||
| 46 | register_percpu_ce(cpuid); | ||
| 47 | |||
| 48 | calibrate_delay(); | ||
| 49 | smp_store_cpu_info(cpuid); | ||
| 50 | 40 | ||
| 51 | local_ops->cache_all(); | 41 | void __cpuinit sun4m_cpu_pre_online(void *arg) |
| 52 | local_ops->tlb_all(); | 42 | { |
| 43 | int cpuid = hard_smp_processor_id(); | ||
| 53 | 44 | ||
| 54 | /* | 45 | /* Allow master to continue. The master will then give us the |
| 55 | * Unblock the master CPU _only_ when the scheduler state | 46 | * go-ahead by setting the smp_commenced_mask and will wait without |
| 56 | * of all secondary CPUs will be up-to-date, so after | 47 | * timeouts until our setup is completed fully (signified by |
| 57 | * the SMP initialization the master will be just allowed | 48 | * our bit being set in the cpu_online_mask). |
| 58 | * to call the scheduler code. | ||
| 59 | */ | 49 | */ |
| 60 | /* Allow master to continue. */ | ||
| 61 | swap_ulong(&cpu_callin_map[cpuid], 1); | 50 | swap_ulong(&cpu_callin_map[cpuid], 1); |
| 62 | 51 | ||
| 63 | /* XXX: What's up with all the flushes? */ | 52 | /* XXX: What's up with all the flushes? */ |
| @@ -75,10 +64,6 @@ void __cpuinit smp4m_callin(void) | |||
| 75 | 64 | ||
| 76 | while (!cpumask_test_cpu(cpuid, &smp_commenced_mask)) | 65 | while (!cpumask_test_cpu(cpuid, &smp_commenced_mask)) |
| 77 | mb(); | 66 | mb(); |
| 78 | |||
| 79 | local_irq_enable(); | ||
| 80 | |||
| 81 | set_cpu_online(cpuid, true); | ||
| 82 | } | 67 | } |
| 83 | 68 | ||
| 84 | /* | 69 | /* |
diff --git a/arch/sparc/kernel/trampoline_32.S b/arch/sparc/kernel/trampoline_32.S index af27acab4486..6cdb08cdabf0 100644 --- a/arch/sparc/kernel/trampoline_32.S +++ b/arch/sparc/kernel/trampoline_32.S | |||
| @@ -79,18 +79,15 @@ cpu3_startup: | |||
| 79 | nop | 79 | nop |
| 80 | 80 | ||
| 81 | /* Start this processor. */ | 81 | /* Start this processor. */ |
| 82 | call smp4m_callin | 82 | call smp_callin |
| 83 | nop | 83 | nop |
| 84 | 84 | ||
| 85 | b,a smp_do_cpu_idle | 85 | b,a smp_panic |
| 86 | 86 | ||
| 87 | .text | 87 | .text |
| 88 | .align 4 | 88 | .align 4 |
| 89 | 89 | ||
| 90 | smp_do_cpu_idle: | 90 | smp_panic: |
| 91 | call cpu_idle | ||
| 92 | mov 0, %o0 | ||
| 93 | |||
| 94 | call cpu_panic | 91 | call cpu_panic |
| 95 | nop | 92 | nop |
| 96 | 93 | ||
| @@ -144,10 +141,10 @@ sun4d_cpu_startup: | |||
| 144 | nop | 141 | nop |
| 145 | 142 | ||
| 146 | /* Start this processor. */ | 143 | /* Start this processor. */ |
| 147 | call smp4d_callin | 144 | call smp_callin |
| 148 | nop | 145 | nop |
| 149 | 146 | ||
| 150 | b,a smp_do_cpu_idle | 147 | b,a smp_panic |
| 151 | 148 | ||
| 152 | __CPUINIT | 149 | __CPUINIT |
| 153 | .align 4 | 150 | .align 4 |
| @@ -201,7 +198,7 @@ leon_smp_cpu_startup: | |||
| 201 | nop | 198 | nop |
| 202 | 199 | ||
| 203 | /* Start this processor. */ | 200 | /* Start this processor. */ |
| 204 | call leon_callin | 201 | call smp_callin |
| 205 | nop | 202 | nop |
| 206 | 203 | ||
| 207 | b,a smp_do_cpu_idle | 204 | b,a smp_panic |
