diff options
Diffstat (limited to 'arch/arm/kernel/smp.c')
-rw-r--r-- | arch/arm/kernel/smp.c | 56 |
1 files changed, 48 insertions, 8 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 6014dfd22af4..91130e218aef 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #include <linux/smp.h> | 22 | #include <linux/smp.h> |
23 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
24 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
25 | #include <linux/percpu.h> | ||
26 | #include <linux/clockchips.h> | ||
25 | 27 | ||
26 | #include <asm/atomic.h> | 28 | #include <asm/atomic.h> |
27 | #include <asm/cacheflush.h> | 29 | #include <asm/cacheflush.h> |
@@ -32,6 +34,7 @@ | |||
32 | #include <asm/processor.h> | 34 | #include <asm/processor.h> |
33 | #include <asm/tlbflush.h> | 35 | #include <asm/tlbflush.h> |
34 | #include <asm/ptrace.h> | 36 | #include <asm/ptrace.h> |
37 | #include <asm/localtimer.h> | ||
35 | 38 | ||
36 | /* | 39 | /* |
37 | * as from 2.5, kernels no longer have an init_tasks structure | 40 | * as from 2.5, kernels no longer have an init_tasks structure |
@@ -274,9 +277,9 @@ asmlinkage void __cpuinit secondary_start_kernel(void) | |||
274 | local_fiq_enable(); | 277 | local_fiq_enable(); |
275 | 278 | ||
276 | /* | 279 | /* |
277 | * Setup local timer for this CPU. | 280 | * Setup the percpu timer for this CPU. |
278 | */ | 281 | */ |
279 | local_timer_setup(); | 282 | percpu_timer_setup(); |
280 | 283 | ||
281 | calibrate_delay(); | 284 | calibrate_delay(); |
282 | 285 | ||
@@ -383,10 +386,16 @@ void show_local_irqs(struct seq_file *p) | |||
383 | seq_putc(p, '\n'); | 386 | seq_putc(p, '\n'); |
384 | } | 387 | } |
385 | 388 | ||
389 | /* | ||
390 | * Timer (local or broadcast) support | ||
391 | */ | ||
392 | static DEFINE_PER_CPU(struct clock_event_device, percpu_clockevent); | ||
393 | |||
386 | static void ipi_timer(void) | 394 | static void ipi_timer(void) |
387 | { | 395 | { |
396 | struct clock_event_device *evt = &__get_cpu_var(percpu_clockevent); | ||
388 | irq_enter(); | 397 | irq_enter(); |
389 | local_timer_interrupt(); | 398 | evt->event_handler(evt); |
390 | irq_exit(); | 399 | irq_exit(); |
391 | } | 400 | } |
392 | 401 | ||
@@ -405,6 +414,42 @@ asmlinkage void __exception do_local_timer(struct pt_regs *regs) | |||
405 | } | 414 | } |
406 | #endif | 415 | #endif |
407 | 416 | ||
417 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | ||
418 | static void smp_timer_broadcast(const struct cpumask *mask) | ||
419 | { | ||
420 | send_ipi_message(mask, IPI_TIMER); | ||
421 | } | ||
422 | |||
423 | static void broadcast_timer_set_mode(enum clock_event_mode mode, | ||
424 | struct clock_event_device *evt) | ||
425 | { | ||
426 | } | ||
427 | |||
428 | static void local_timer_setup(struct clock_event_device *evt) | ||
429 | { | ||
430 | evt->name = "dummy_timer"; | ||
431 | evt->features = CLOCK_EVT_FEAT_ONESHOT | | ||
432 | CLOCK_EVT_FEAT_PERIODIC | | ||
433 | CLOCK_EVT_FEAT_DUMMY; | ||
434 | evt->rating = 400; | ||
435 | evt->mult = 1; | ||
436 | evt->set_mode = broadcast_timer_set_mode; | ||
437 | evt->broadcast = smp_timer_broadcast; | ||
438 | |||
439 | clockevents_register_device(evt); | ||
440 | } | ||
441 | #endif | ||
442 | |||
443 | void __cpuinit percpu_timer_setup(void) | ||
444 | { | ||
445 | unsigned int cpu = smp_processor_id(); | ||
446 | struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); | ||
447 | |||
448 | evt->cpumask = cpumask_of(cpu); | ||
449 | |||
450 | local_timer_setup(evt); | ||
451 | } | ||
452 | |||
408 | static DEFINE_SPINLOCK(stop_lock); | 453 | static DEFINE_SPINLOCK(stop_lock); |
409 | 454 | ||
410 | /* | 455 | /* |
@@ -501,11 +546,6 @@ void smp_send_reschedule(int cpu) | |||
501 | send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); | 546 | send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); |
502 | } | 547 | } |
503 | 548 | ||
504 | void smp_timer_broadcast(const struct cpumask *mask) | ||
505 | { | ||
506 | send_ipi_message(mask, IPI_TIMER); | ||
507 | } | ||
508 | |||
509 | void smp_send_stop(void) | 549 | void smp_send_stop(void) |
510 | { | 550 | { |
511 | cpumask_t mask = cpu_online_map; | 551 | cpumask_t mask = cpu_online_map; |