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); |