diff options
author | Richard Cochran <rcochran@linutronix.de> | 2016-07-13 13:16:39 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-07-15 04:40:24 -0400 |
commit | 7e86e8bd8dd67649d176e08d8dfb90039f0a1e98 (patch) | |
tree | 27d075e1a8d404276455061b6756efc4156e4b15 /drivers/clocksource/arm_arch_timer.c | |
parent | e1272f541c6ad476426ef24b56b4e1d3403db513 (diff) |
clocksource/arm_arch_timer: Convert to hotplug state machine
Install the callbacks via the state machine and let the core invoke
the callbacks on the already online CPUs.
Signed-off-by: Richard Cochran <rcochran@linutronix.de>
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: rt@linutronix.de
Link: http://lkml.kernel.org/r/20160713153336.048259040@linutronix.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 54 |
1 files changed, 26 insertions, 28 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 5effd3027319..28bce3f4f81d 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c | |||
@@ -370,8 +370,10 @@ static bool arch_timer_has_nonsecure_ppi(void) | |||
370 | arch_timer_ppi[PHYS_NONSECURE_PPI]); | 370 | arch_timer_ppi[PHYS_NONSECURE_PPI]); |
371 | } | 371 | } |
372 | 372 | ||
373 | static int arch_timer_setup(struct clock_event_device *clk) | 373 | static int arch_timer_starting_cpu(unsigned int cpu) |
374 | { | 374 | { |
375 | struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); | ||
376 | |||
375 | __arch_timer_setup(ARCH_CP15_TIMER, clk); | 377 | __arch_timer_setup(ARCH_CP15_TIMER, clk); |
376 | 378 | ||
377 | enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0); | 379 | enable_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], 0); |
@@ -527,29 +529,14 @@ static void arch_timer_stop(struct clock_event_device *clk) | |||
527 | clk->set_state_shutdown(clk); | 529 | clk->set_state_shutdown(clk); |
528 | } | 530 | } |
529 | 531 | ||
530 | static int arch_timer_cpu_notify(struct notifier_block *self, | 532 | static int arch_timer_dying_cpu(unsigned int cpu) |
531 | unsigned long action, void *hcpu) | ||
532 | { | 533 | { |
533 | /* | 534 | struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); |
534 | * Grab cpu pointer in each case to avoid spurious | ||
535 | * preemptible warnings | ||
536 | */ | ||
537 | switch (action & ~CPU_TASKS_FROZEN) { | ||
538 | case CPU_STARTING: | ||
539 | arch_timer_setup(this_cpu_ptr(arch_timer_evt)); | ||
540 | break; | ||
541 | case CPU_DYING: | ||
542 | arch_timer_stop(this_cpu_ptr(arch_timer_evt)); | ||
543 | break; | ||
544 | } | ||
545 | 535 | ||
546 | return NOTIFY_OK; | 536 | arch_timer_stop(clk); |
537 | return 0; | ||
547 | } | 538 | } |
548 | 539 | ||
549 | static struct notifier_block arch_timer_cpu_nb = { | ||
550 | .notifier_call = arch_timer_cpu_notify, | ||
551 | }; | ||
552 | |||
553 | #ifdef CONFIG_CPU_PM | 540 | #ifdef CONFIG_CPU_PM |
554 | static unsigned int saved_cntkctl; | 541 | static unsigned int saved_cntkctl; |
555 | static int arch_timer_cpu_pm_notify(struct notifier_block *self, | 542 | static int arch_timer_cpu_pm_notify(struct notifier_block *self, |
@@ -570,11 +557,21 @@ static int __init arch_timer_cpu_pm_init(void) | |||
570 | { | 557 | { |
571 | return cpu_pm_register_notifier(&arch_timer_cpu_pm_notifier); | 558 | return cpu_pm_register_notifier(&arch_timer_cpu_pm_notifier); |
572 | } | 559 | } |
560 | |||
561 | static void __init arch_timer_cpu_pm_deinit(void) | ||
562 | { | ||
563 | WARN_ON(cpu_pm_unregister_notifier(&arch_timer_cpu_pm_notifier)); | ||
564 | } | ||
565 | |||
573 | #else | 566 | #else |
574 | static int __init arch_timer_cpu_pm_init(void) | 567 | static int __init arch_timer_cpu_pm_init(void) |
575 | { | 568 | { |
576 | return 0; | 569 | return 0; |
577 | } | 570 | } |
571 | |||
572 | static void __init arch_timer_cpu_pm_deinit(void) | ||
573 | { | ||
574 | } | ||
578 | #endif | 575 | #endif |
579 | 576 | ||
580 | static int __init arch_timer_register(void) | 577 | static int __init arch_timer_register(void) |
@@ -621,22 +618,23 @@ static int __init arch_timer_register(void) | |||
621 | goto out_free; | 618 | goto out_free; |
622 | } | 619 | } |
623 | 620 | ||
624 | err = register_cpu_notifier(&arch_timer_cpu_nb); | ||
625 | if (err) | ||
626 | goto out_free_irq; | ||
627 | |||
628 | err = arch_timer_cpu_pm_init(); | 621 | err = arch_timer_cpu_pm_init(); |
629 | if (err) | 622 | if (err) |
630 | goto out_unreg_notify; | 623 | goto out_unreg_notify; |
631 | 624 | ||
632 | /* Immediately configure the timer on the boot CPU */ | ||
633 | arch_timer_setup(this_cpu_ptr(arch_timer_evt)); | ||
634 | 625 | ||
626 | /* Register and immediately configure the timer on the boot CPU */ | ||
627 | err = cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_STARTING, | ||
628 | "AP_ARM_ARCH_TIMER_STARTING", | ||
629 | arch_timer_starting_cpu, arch_timer_dying_cpu); | ||
630 | if (err) | ||
631 | goto out_unreg_cpupm; | ||
635 | return 0; | 632 | return 0; |
636 | 633 | ||
634 | out_unreg_cpupm: | ||
635 | arch_timer_cpu_pm_deinit(); | ||
636 | |||
637 | out_unreg_notify: | 637 | out_unreg_notify: |
638 | unregister_cpu_notifier(&arch_timer_cpu_nb); | ||
639 | out_free_irq: | ||
640 | free_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], arch_timer_evt); | 638 | free_percpu_irq(arch_timer_ppi[arch_timer_uses_ppi], arch_timer_evt); |
641 | if (arch_timer_has_nonsecure_ppi()) | 639 | if (arch_timer_has_nonsecure_ppi()) |
642 | free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], | 640 | free_percpu_irq(arch_timer_ppi[PHYS_NONSECURE_PPI], |