aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/arm_arch_timer.c
diff options
context:
space:
mode:
authorJulien Thierry <julien.thierry@arm.com>2017-10-13 09:32:55 -0400
committerWill Deacon <will.deacon@arm.com>2017-10-13 13:55:05 -0400
commitec5c8e429d07737ee94ee1fd2ae5029547484194 (patch)
tree8272f13001ee42fc7ba31115a4c2d119a77b27ea /drivers/clocksource/arm_arch_timer.c
parent611a7bc74ed2dcbab6693c20bb534cfcf15f9d1d (diff)
arm_arch_timer: Expose event stream status
The arch timer configuration for a CPU might get reset after suspending said CPU. In order to reliably use the event stream in the kernel (e.g. for delays), we keep track of the state where we can safely consider the event stream as properly configured. After writing to cntkctl, we issue an ISB to ensure that subsequent delay loops can rely on the event stream being enabled. Signed-off-by: Julien Thierry <julien.thierry@arm.com> Acked-by: Mark Rutland <mark.rutland@arm.com> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: Russell King <linux@armlinux.org.uk> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Will Deacon <will.deacon@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r--drivers/clocksource/arm_arch_timer.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index fd4b7f684bd0..13e6baa13a89 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -77,6 +77,7 @@ static bool arch_timer_mem_use_virtual;
77static bool arch_counter_suspend_stop; 77static bool arch_counter_suspend_stop;
78static bool vdso_default = true; 78static bool vdso_default = true;
79 79
80static cpumask_t evtstrm_available = CPU_MASK_NONE;
80static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM); 81static bool evtstrm_enable = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EVTSTREAM);
81 82
82static int __init early_evtstrm_cfg(char *buf) 83static int __init early_evtstrm_cfg(char *buf)
@@ -740,6 +741,7 @@ static void arch_timer_evtstrm_enable(int divider)
740#ifdef CONFIG_COMPAT 741#ifdef CONFIG_COMPAT
741 compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM; 742 compat_elf_hwcap |= COMPAT_HWCAP_EVTSTRM;
742#endif 743#endif
744 cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
743} 745}
744 746
745static void arch_timer_configure_evtstream(void) 747static void arch_timer_configure_evtstream(void)
@@ -864,6 +866,16 @@ u32 arch_timer_get_rate(void)
864 return arch_timer_rate; 866 return arch_timer_rate;
865} 867}
866 868
869bool arch_timer_evtstrm_available(void)
870{
871 /*
872 * We might get called from a preemptible context. This is fine
873 * because availability of the event stream should be always the same
874 * for a preemptible context and context where we might resume a task.
875 */
876 return cpumask_test_cpu(raw_smp_processor_id(), &evtstrm_available);
877}
878
867static u64 arch_counter_get_cntvct_mem(void) 879static u64 arch_counter_get_cntvct_mem(void)
868{ 880{
869 u32 vct_lo, vct_hi, tmp_hi; 881 u32 vct_lo, vct_hi, tmp_hi;
@@ -929,6 +941,8 @@ static int arch_timer_dying_cpu(unsigned int cpu)
929{ 941{
930 struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt); 942 struct clock_event_device *clk = this_cpu_ptr(arch_timer_evt);
931 943
944 cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
945
932 arch_timer_stop(clk); 946 arch_timer_stop(clk);
933 return 0; 947 return 0;
934} 948}
@@ -938,10 +952,16 @@ static DEFINE_PER_CPU(unsigned long, saved_cntkctl);
938static int arch_timer_cpu_pm_notify(struct notifier_block *self, 952static int arch_timer_cpu_pm_notify(struct notifier_block *self,
939 unsigned long action, void *hcpu) 953 unsigned long action, void *hcpu)
940{ 954{
941 if (action == CPU_PM_ENTER) 955 if (action == CPU_PM_ENTER) {
942 __this_cpu_write(saved_cntkctl, arch_timer_get_cntkctl()); 956 __this_cpu_write(saved_cntkctl, arch_timer_get_cntkctl());
943 else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) 957
958 cpumask_clear_cpu(smp_processor_id(), &evtstrm_available);
959 } else if (action == CPU_PM_ENTER_FAILED || action == CPU_PM_EXIT) {
944 arch_timer_set_cntkctl(__this_cpu_read(saved_cntkctl)); 960 arch_timer_set_cntkctl(__this_cpu_read(saved_cntkctl));
961
962 if (elf_hwcap & HWCAP_EVTSTRM)
963 cpumask_set_cpu(smp_processor_id(), &evtstrm_available);
964 }
945 return NOTIFY_OK; 965 return NOTIFY_OK;
946} 966}
947 967
@@ -1017,7 +1037,6 @@ static int __init arch_timer_register(void)
1017 if (err) 1037 if (err)
1018 goto out_unreg_notify; 1038 goto out_unreg_notify;
1019 1039
1020
1021 /* Register and immediately configure the timer on the boot CPU */ 1040 /* Register and immediately configure the timer on the boot CPU */
1022 err = cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_STARTING, 1041 err = cpuhp_setup_state(CPUHP_AP_ARM_ARCH_TIMER_STARTING,
1023 "clockevents/arm/arch_timer:starting", 1042 "clockevents/arm/arch_timer:starting",