diff options
Diffstat (limited to 'arch/arm/kernel/smp.c')
| -rw-r--r-- | arch/arm/kernel/smp.c | 89 |
1 files changed, 43 insertions, 46 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index d88ff0230e82..ef5640b9e218 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 | /* |
| @@ -437,10 +460,6 @@ u64 smp_irq_stat_cpu(unsigned int cpu) | |||
| 437 | for (i = 0; i < NR_IPI; i++) | 460 | for (i = 0; i < NR_IPI; i++) |
| 438 | sum += __get_irq_stat(cpu, ipi_irqs[i]); | 461 | sum += __get_irq_stat(cpu, ipi_irqs[i]); |
| 439 | 462 | ||
| 440 | #ifdef CONFIG_LOCAL_TIMERS | ||
| 441 | sum += __get_irq_stat(cpu, local_timer_irqs); | ||
| 442 | #endif | ||
| 443 | |||
| 444 | return sum; | 463 | return sum; |
| 445 | } | 464 | } |
| 446 | 465 | ||
| @@ -457,33 +476,6 @@ static void ipi_timer(void) | |||
| 457 | irq_exit(); | 476 | irq_exit(); |
| 458 | } | 477 | } |
| 459 | 478 | ||
| 460 | #ifdef CONFIG_LOCAL_TIMERS | ||
| 461 | asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs) | ||
| 462 | { | ||
| 463 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
| 464 | int cpu = smp_processor_id(); | ||
| 465 | |||
| 466 | if (local_timer_ack()) { | ||
| 467 | __inc_irq_stat(cpu, local_timer_irqs); | ||
| 468 | ipi_timer(); | ||
| 469 | } | ||
| 470 | |||
| 471 | set_irq_regs(old_regs); | ||
| 472 | } | ||
| 473 | |||
| 474 | void show_local_irqs(struct seq_file *p, int prec) | ||
| 475 | { | ||
| 476 | unsigned int cpu; | ||
| 477 | |||
| 478 | seq_printf(p, "%*s: ", prec, "LOC"); | ||
| 479 | |||
| 480 | for_each_present_cpu(cpu) | ||
| 481 | seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs)); | ||
| 482 | |||
| 483 | seq_printf(p, " Local timer interrupts\n"); | ||
| 484 | } | ||
| 485 | #endif | ||
| 486 | |||
| 487 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | 479 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST |
| 488 | static void smp_timer_broadcast(const struct cpumask *mask) | 480 | static void smp_timer_broadcast(const struct cpumask *mask) |
| 489 | { | 481 | { |
| @@ -534,11 +526,11 @@ static void percpu_timer_stop(void) | |||
| 534 | unsigned int cpu = smp_processor_id(); | 526 | unsigned int cpu = smp_processor_id(); |
| 535 | struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); | 527 | struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); |
| 536 | 528 | ||
| 537 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); | 529 | local_timer_stop(evt); |
| 538 | } | 530 | } |
| 539 | #endif | 531 | #endif |
| 540 | 532 | ||
| 541 | static DEFINE_SPINLOCK(stop_lock); | 533 | static DEFINE_RAW_SPINLOCK(stop_lock); |
| 542 | 534 | ||
| 543 | /* | 535 | /* |
| 544 | * ipi_cpu_stop - handle IPI from smp_send_stop() | 536 | * ipi_cpu_stop - handle IPI from smp_send_stop() |
| @@ -547,10 +539,10 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
| 547 | { | 539 | { |
| 548 | if (system_state == SYSTEM_BOOTING || | 540 | if (system_state == SYSTEM_BOOTING || |
| 549 | system_state == SYSTEM_RUNNING) { | 541 | system_state == SYSTEM_RUNNING) { |
| 550 | spin_lock(&stop_lock); | 542 | raw_spin_lock(&stop_lock); |
| 551 | printk(KERN_CRIT "CPU%u: stopping\n", cpu); | 543 | printk(KERN_CRIT "CPU%u: stopping\n", cpu); |
| 552 | dump_stack(); | 544 | dump_stack(); |
| 553 | spin_unlock(&stop_lock); | 545 | raw_spin_unlock(&stop_lock); |
| 554 | } | 546 | } |
| 555 | 547 | ||
| 556 | set_cpu_online(cpu, false); | 548 | set_cpu_online(cpu, false); |
| @@ -567,6 +559,11 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
| 567 | */ | 559 | */ |
| 568 | asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) | 560 | asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) |
| 569 | { | 561 | { |
| 562 | handle_IPI(ipinr, regs); | ||
| 563 | } | ||
| 564 | |||
| 565 | void handle_IPI(int ipinr, struct pt_regs *regs) | ||
| 566 | { | ||
| 570 | unsigned int cpu = smp_processor_id(); | 567 | unsigned int cpu = smp_processor_id(); |
| 571 | struct pt_regs *old_regs = set_irq_regs(regs); | 568 | struct pt_regs *old_regs = set_irq_regs(regs); |
| 572 | 569 | ||
