diff options
Diffstat (limited to 'arch/arm/kernel/smp.c')
-rw-r--r-- | arch/arm/kernel/smp.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index d88ff0230e82..94f34a6c8610 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/cache.h> | 16 | #include <linux/cache.h> |
17 | #include <linux/profile.h> | 17 | #include <linux/profile.h> |
18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
19 | #include <linux/ftrace.h> | ||
20 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
21 | #include <linux/err.h> | 20 | #include <linux/err.h> |
22 | #include <linux/cpu.h> | 21 | #include <linux/cpu.h> |
@@ -31,6 +30,8 @@ | |||
31 | #include <asm/cacheflush.h> | 30 | #include <asm/cacheflush.h> |
32 | #include <asm/cpu.h> | 31 | #include <asm/cpu.h> |
33 | #include <asm/cputype.h> | 32 | #include <asm/cputype.h> |
33 | #include <asm/exception.h> | ||
34 | #include <asm/topology.h> | ||
34 | #include <asm/mmu_context.h> | 35 | #include <asm/mmu_context.h> |
35 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
36 | #include <asm/pgalloc.h> | 37 | #include <asm/pgalloc.h> |
@@ -39,6 +40,7 @@ | |||
39 | #include <asm/tlbflush.h> | 40 | #include <asm/tlbflush.h> |
40 | #include <asm/ptrace.h> | 41 | #include <asm/ptrace.h> |
41 | #include <asm/localtimer.h> | 42 | #include <asm/localtimer.h> |
43 | #include <asm/smp_plat.h> | ||
42 | 44 | ||
43 | /* | 45 | /* |
44 | * as from 2.5, kernels no longer have an init_tasks structure | 46 | * as from 2.5, kernels no longer have an init_tasks structure |
@@ -259,6 +261,20 @@ void __ref cpu_die(void) | |||
259 | } | 261 | } |
260 | #endif /* CONFIG_HOTPLUG_CPU */ | 262 | #endif /* CONFIG_HOTPLUG_CPU */ |
261 | 263 | ||
264 | int __cpu_logical_map[NR_CPUS]; | ||
265 | |||
266 | void __init smp_setup_processor_id(void) | ||
267 | { | ||
268 | int i; | ||
269 | u32 cpu = is_smp() ? read_cpuid_mpidr() & 0xff : 0; | ||
270 | |||
271 | cpu_logical_map(0) = cpu; | ||
272 | for (i = 1; i < NR_CPUS; ++i) | ||
273 | cpu_logical_map(i) = i == cpu ? 0 : i; | ||
274 | |||
275 | printk(KERN_INFO "Booting Linux on physical CPU %d\n", cpu); | ||
276 | } | ||
277 | |||
262 | /* | 278 | /* |
263 | * Called by both boot and secondaries to move global data into | 279 | * Called by both boot and secondaries to move global data into |
264 | * per-processor storage. | 280 | * per-processor storage. |
@@ -268,6 +284,8 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid) | |||
268 | struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); | 284 | struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); |
269 | 285 | ||
270 | cpu_info->loops_per_jiffy = loops_per_jiffy; | 286 | cpu_info->loops_per_jiffy = loops_per_jiffy; |
287 | |||
288 | store_cpu_topology(cpuid); | ||
271 | } | 289 | } |
272 | 290 | ||
273 | /* | 291 | /* |
@@ -301,17 +319,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
301 | */ | 319 | */ |
302 | platform_secondary_init(cpu); | 320 | platform_secondary_init(cpu); |
303 | 321 | ||
304 | /* | ||
305 | * Enable local interrupts. | ||
306 | */ | ||
307 | notify_cpu_starting(cpu); | 322 | notify_cpu_starting(cpu); |
308 | local_irq_enable(); | ||
309 | local_fiq_enable(); | ||
310 | |||
311 | /* | ||
312 | * Setup the percpu timer for this CPU. | ||
313 | */ | ||
314 | percpu_timer_setup(); | ||
315 | 323 | ||
316 | calibrate_delay(); | 324 | calibrate_delay(); |
317 | 325 | ||
@@ -323,10 +331,23 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
323 | * before we continue. | 331 | * before we continue. |
324 | */ | 332 | */ |
325 | set_cpu_online(cpu, true); | 333 | set_cpu_online(cpu, true); |
334 | |||
335 | /* | ||
336 | * Setup the percpu timer for this CPU. | ||
337 | */ | ||
338 | percpu_timer_setup(); | ||
339 | |||
326 | while (!cpu_active(cpu)) | 340 | while (!cpu_active(cpu)) |
327 | cpu_relax(); | 341 | cpu_relax(); |
328 | 342 | ||
329 | /* | 343 | /* |
344 | * cpu_active bit is set, so it's safe to enalbe interrupts | ||
345 | * now. | ||
346 | */ | ||
347 | local_irq_enable(); | ||
348 | local_fiq_enable(); | ||
349 | |||
350 | /* | ||
330 | * OK, it's off to the idle thread for us | 351 | * OK, it's off to the idle thread for us |
331 | */ | 352 | */ |
332 | cpu_idle(); | 353 | cpu_idle(); |
@@ -358,6 +379,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
358 | { | 379 | { |
359 | unsigned int ncores = num_possible_cpus(); | 380 | unsigned int ncores = num_possible_cpus(); |
360 | 381 | ||
382 | init_cpu_topology(); | ||
383 | |||
361 | smp_store_cpu_info(smp_processor_id()); | 384 | smp_store_cpu_info(smp_processor_id()); |
362 | 385 | ||
363 | /* | 386 | /* |
@@ -460,6 +483,11 @@ static void ipi_timer(void) | |||
460 | #ifdef CONFIG_LOCAL_TIMERS | 483 | #ifdef CONFIG_LOCAL_TIMERS |
461 | asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) | 484 | asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) |
462 | { | 485 | { |
486 | handle_local_timer(regs); | ||
487 | } | ||
488 | |||
489 | void handle_local_timer(struct pt_regs *regs) | ||
490 | { | ||
463 | struct pt_regs *old_regs = set_irq_regs(regs); | 491 | struct pt_regs *old_regs = set_irq_regs(regs); |
464 | int cpu = smp_processor_id(); | 492 | int cpu = smp_processor_id(); |
465 | 493 | ||
@@ -538,7 +566,7 @@ static void percpu_timer_stop(void) | |||
538 | } | 566 | } |
539 | #endif | 567 | #endif |
540 | 568 | ||
541 | static DEFINE_SPINLOCK(stop_lock); | 569 | static DEFINE_RAW_SPINLOCK(stop_lock); |
542 | 570 | ||
543 | /* | 571 | /* |
544 | * ipi_cpu_stop - handle IPI from smp_send_stop() | 572 | * ipi_cpu_stop - handle IPI from smp_send_stop() |
@@ -547,10 +575,10 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
547 | { | 575 | { |
548 | if (system_state == SYSTEM_BOOTING || | 576 | if (system_state == SYSTEM_BOOTING || |
549 | system_state == SYSTEM_RUNNING) { | 577 | system_state == SYSTEM_RUNNING) { |
550 | spin_lock(&stop_lock); | 578 | raw_spin_lock(&stop_lock); |
551 | printk(KERN_CRIT "CPU%u: stopping\n", cpu); | 579 | printk(KERN_CRIT "CPU%u: stopping\n", cpu); |
552 | dump_stack(); | 580 | dump_stack(); |
553 | spin_unlock(&stop_lock); | 581 | raw_spin_unlock(&stop_lock); |
554 | } | 582 | } |
555 | 583 | ||
556 | set_cpu_online(cpu, false); | 584 | set_cpu_online(cpu, false); |
@@ -567,6 +595,11 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
567 | */ | 595 | */ |
568 | asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) | 596 | asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) |
569 | { | 597 | { |
598 | handle_IPI(ipinr, regs); | ||
599 | } | ||
600 | |||
601 | void handle_IPI(int ipinr, struct pt_regs *regs) | ||
602 | { | ||
570 | unsigned int cpu = smp_processor_id(); | 603 | unsigned int cpu = smp_processor_id(); |
571 | struct pt_regs *old_regs = set_irq_regs(regs); | 604 | struct pt_regs *old_regs = set_irq_regs(regs); |
572 | 605 | ||