aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clocksource/arm_arch_timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
-rw-r--r--drivers/clocksource/arm_arch_timer.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index a0c9ee80147e..4551587bcb44 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -235,7 +235,8 @@ static u64 notrace hisi_161010101_read_cntvct_el0(void)
235#endif 235#endif
236 236
237#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND 237#ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND
238const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround = NULL; 238DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *,
239 timer_unstable_counter_workaround);
239EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); 240EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround);
240 241
241DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled); 242DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled);
@@ -338,9 +339,18 @@ arch_timer_iterate_errata(enum arch_timer_erratum_match_type type,
338} 339}
339 340
340static 341static
341void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa) 342void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa,
343 bool local)
342{ 344{
343 timer_unstable_counter_workaround = wa; 345 int i;
346
347 if (local) {
348 __this_cpu_write(timer_unstable_counter_workaround, wa);
349 } else {
350 for_each_possible_cpu(i)
351 per_cpu(timer_unstable_counter_workaround, i) = wa;
352 }
353
344 static_branch_enable(&arch_timer_read_ool_enabled); 354 static_branch_enable(&arch_timer_read_ool_enabled);
345} 355}
346 356
@@ -369,14 +379,17 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t
369 return; 379 return;
370 380
371 if (needs_unstable_timer_counter_workaround()) { 381 if (needs_unstable_timer_counter_workaround()) {
372 if (wa != timer_unstable_counter_workaround) 382 const struct arch_timer_erratum_workaround *__wa;
383 __wa = __this_cpu_read(timer_unstable_counter_workaround);
384 if (__wa && wa != __wa)
373 pr_warn("Can't enable workaround for %s (clashes with %s\n)", 385 pr_warn("Can't enable workaround for %s (clashes with %s\n)",
374 wa->desc, 386 wa->desc, __wa->desc);
375 timer_unstable_counter_workaround->desc); 387
376 return; 388 if (__wa)
389 return;
377 } 390 }
378 391
379 arch_timer_enable_workaround(wa); 392 arch_timer_enable_workaround(wa, local);
380 pr_info("Enabling %s workaround for %s\n", 393 pr_info("Enabling %s workaround for %s\n",
381 local ? "local" : "global", wa->desc); 394 local ? "local" : "global", wa->desc);
382} 395}
@@ -384,10 +397,15 @@ static void arch_timer_check_ool_workaround(enum arch_timer_erratum_match_type t
384#define erratum_handler(fn, r, ...) \ 397#define erratum_handler(fn, r, ...) \
385({ \ 398({ \
386 bool __val; \ 399 bool __val; \
387 if (needs_unstable_timer_counter_workaround() && \ 400 if (needs_unstable_timer_counter_workaround()) { \
388 timer_unstable_counter_workaround->fn) { \ 401 const struct arch_timer_erratum_workaround *__wa; \
389 r = timer_unstable_counter_workaround->fn(__VA_ARGS__); \ 402 __wa = __this_cpu_read(timer_unstable_counter_workaround); \
390 __val = true; \ 403 if (__wa && __wa->fn) { \
404 r = __wa->fn(__VA_ARGS__); \
405 __val = true; \
406 } else { \
407 __val = false; \
408 } \
391 } else { \ 409 } else { \
392 __val = false; \ 410 __val = false; \
393 } \ 411 } \