diff options
Diffstat (limited to 'arch/arm/kernel/smp.c')
| -rw-r--r-- | arch/arm/kernel/smp.c | 47 | 
1 files changed, 42 insertions, 5 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index edb5a406922f..e55ea952f7aa 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c  | |||
| @@ -142,7 +142,7 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
| 142 | ret = -EIO; | 142 | ret = -EIO; | 
| 143 | } | 143 | } | 
| 144 | 144 | ||
| 145 | secondary_data.stack = 0; | 145 | secondary_data.stack = NULL; | 
| 146 | secondary_data.pgdir = 0; | 146 | secondary_data.pgdir = 0; | 
| 147 | 147 | ||
| 148 | *pmd_offset(pgd, PHYS_OFFSET) = __pmd(0); | 148 | *pmd_offset(pgd, PHYS_OFFSET) = __pmd(0); | 
| @@ -185,6 +185,11 @@ int __cpuexit __cpu_disable(void) | |||
| 185 | migrate_irqs(); | 185 | migrate_irqs(); | 
| 186 | 186 | ||
| 187 | /* | 187 | /* | 
| 188 | * Stop the local timer for this CPU. | ||
| 189 | */ | ||
| 190 | local_timer_stop(cpu); | ||
| 191 | |||
| 192 | /* | ||
| 188 | * Flush user cache and TLB mappings, and then remove this CPU | 193 | * Flush user cache and TLB mappings, and then remove this CPU | 
| 189 | * from the vm mask set of all processes. | 194 | * from the vm mask set of all processes. | 
| 190 | */ | 195 | */ | 
| @@ -251,7 +256,9 @@ void __cpuexit cpu_die(void) | |||
| 251 | asmlinkage void __cpuinit secondary_start_kernel(void) | 256 | asmlinkage void __cpuinit secondary_start_kernel(void) | 
| 252 | { | 257 | { | 
| 253 | struct mm_struct *mm = &init_mm; | 258 | struct mm_struct *mm = &init_mm; | 
| 254 | unsigned int cpu = smp_processor_id(); | 259 | unsigned int cpu; | 
| 260 | |||
| 261 | cpu = smp_processor_id(); | ||
| 255 | 262 | ||
| 256 | printk("CPU%u: Booted secondary processor\n", cpu); | 263 | printk("CPU%u: Booted secondary processor\n", cpu); | 
| 257 | 264 | ||
| @@ -268,6 +275,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
| 268 | local_flush_tlb_all(); | 275 | local_flush_tlb_all(); | 
| 269 | 276 | ||
| 270 | cpu_init(); | 277 | cpu_init(); | 
| 278 | preempt_disable(); | ||
| 271 | 279 | ||
| 272 | /* | 280 | /* | 
| 273 | * Give the platform a chance to do its own initialisation. | 281 | * Give the platform a chance to do its own initialisation. | 
| @@ -290,6 +298,11 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
| 290 | cpu_set(cpu, cpu_online_map); | 298 | cpu_set(cpu, cpu_online_map); | 
| 291 | 299 | ||
| 292 | /* | 300 | /* | 
| 301 | * Setup local timer for this CPU. | ||
| 302 | */ | ||
| 303 | local_timer_setup(cpu); | ||
| 304 | |||
| 305 | /* | ||
| 293 | * OK, it's off to the idle thread for us | 306 | * OK, it's off to the idle thread for us | 
| 294 | */ | 307 | */ | 
| 295 | cpu_idle(); | 308 | cpu_idle(); | 
| @@ -359,8 +372,8 @@ static void send_ipi_message(cpumask_t callmap, enum ipi_msg_type msg) | |||
| 359 | * You must not call this function with disabled interrupts, from a | 372 | * You must not call this function with disabled interrupts, from a | 
| 360 | * hardware interrupt handler, nor from a bottom half handler. | 373 | * hardware interrupt handler, nor from a bottom half handler. | 
| 361 | */ | 374 | */ | 
| 362 | int smp_call_function_on_cpu(void (*func)(void *info), void *info, int retry, | 375 | static int smp_call_function_on_cpu(void (*func)(void *info), void *info, | 
| 363 | int wait, cpumask_t callmap) | 376 | int retry, int wait, cpumask_t callmap) | 
| 364 | { | 377 | { | 
| 365 | struct smp_call_struct data; | 378 | struct smp_call_struct data; | 
| 366 | unsigned long timeout; | 379 | unsigned long timeout; | 
| @@ -454,6 +467,18 @@ void show_ipi_list(struct seq_file *p) | |||
| 454 | seq_putc(p, '\n'); | 467 | seq_putc(p, '\n'); | 
| 455 | } | 468 | } | 
| 456 | 469 | ||
| 470 | void show_local_irqs(struct seq_file *p) | ||
| 471 | { | ||
| 472 | unsigned int cpu; | ||
| 473 | |||
| 474 | seq_printf(p, "LOC: "); | ||
| 475 | |||
| 476 | for_each_present_cpu(cpu) | ||
| 477 | seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs); | ||
| 478 | |||
| 479 | seq_putc(p, '\n'); | ||
| 480 | } | ||
| 481 | |||
| 457 | static void ipi_timer(struct pt_regs *regs) | 482 | static void ipi_timer(struct pt_regs *regs) | 
| 458 | { | 483 | { | 
| 459 | int user = user_mode(regs); | 484 | int user = user_mode(regs); | 
| @@ -464,6 +489,18 @@ static void ipi_timer(struct pt_regs *regs) | |||
| 464 | irq_exit(); | 489 | irq_exit(); | 
| 465 | } | 490 | } | 
| 466 | 491 | ||
| 492 | #ifdef CONFIG_LOCAL_TIMERS | ||
| 493 | asmlinkage void do_local_timer(struct pt_regs *regs) | ||
| 494 | { | ||
| 495 | int cpu = smp_processor_id(); | ||
| 496 | |||
| 497 | if (local_timer_ack()) { | ||
| 498 | irq_stat[cpu].local_timer_irqs++; | ||
| 499 | ipi_timer(regs); | ||
| 500 | } | ||
| 501 | } | ||
| 502 | #endif | ||
| 503 | |||
| 467 | /* | 504 | /* | 
| 468 | * ipi_call_function - handle IPI from smp_call_function() | 505 | * ipi_call_function - handle IPI from smp_call_function() | 
| 469 | * | 506 | * | 
| @@ -515,7 +552,7 @@ static void ipi_cpu_stop(unsigned int cpu) | |||
| 515 | * | 552 | * | 
| 516 | * Bit 0 - Inter-processor function call | 553 | * Bit 0 - Inter-processor function call | 
| 517 | */ | 554 | */ | 
| 518 | void do_IPI(struct pt_regs *regs) | 555 | asmlinkage void do_IPI(struct pt_regs *regs) | 
| 519 | { | 556 | { | 
| 520 | unsigned int cpu = smp_processor_id(); | 557 | unsigned int cpu = smp_processor_id(); | 
| 521 | struct ipi_data *ipi = &per_cpu(ipi_data, cpu); | 558 | struct ipi_data *ipi = &per_cpu(ipi_data, cpu); | 
