diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 9a5464c62..91142959c 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -341,17 +341,20 @@ static u64 notrace arm64_858921_read_cntvct_el0(void) * with all ones or all zeros in the low bits. Bound the loop by the maximum * number of CPU cycles in 3 consecutive 24 MHz counter periods. */ -#define __sun50i_a64_read_reg(reg) ({ \ - u64 _val; \ - int _retries = 150; \ - \ - do { \ - _val = read_sysreg(reg); \ - _retries--; \ - } while (((_val + 1) & GENMASK(8, 0)) <= 1 && _retries); \ - \ - WARN_ON_ONCE(!_retries); \ - _val; \ +#define __sun50i_a64_read_reg(reg) ({ \ + register u64 _tries = 5, _old, _new; \ + \ + do { \ + if (unlikely(_tries < 3)) \ + isb(); \ + _old = read_sysreg(reg); \ + _new = read_sysreg(reg); \ + } while (unlikely((_new - _old) >> 4) && --_tries); \ + \ + if (unlikely(!_tries)) \ + pr_err("(cpu %d) returning possibly incorrect counter value %llx (%llx)\n", \ + smp_processor_id() + 1, _new, _old); \ + _new; \ }) static u64 notrace sun50i_a64_read_cntpct_el0(void)