diff options
Diffstat (limited to 'drivers/clocksource/arm_arch_timer.c')
| -rw-r--r-- | drivers/clocksource/arm_arch_timer.c | 42 |
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 |
| 238 | const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround = NULL; | 238 | DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, |
| 239 | timer_unstable_counter_workaround); | ||
| 239 | EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); | 240 | EXPORT_SYMBOL_GPL(timer_unstable_counter_workaround); |
| 240 | 241 | ||
| 241 | DEFINE_STATIC_KEY_FALSE(arch_timer_read_ool_enabled); | 242 | DEFINE_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 | ||
| 340 | static | 341 | static |
| 341 | void arch_timer_enable_workaround(const struct arch_timer_erratum_workaround *wa) | 342 | void 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 | } \ |
