driver inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/8860 ---------------------------------------------------------------------- In cppc_get_perf_ctrs_pair(), cond_resched() eventually calls irq_work_queue() to queue an async item if the CPU is a nohz_full one following this call chain: cond_resched() └── preempt_schedule_common() └── __schedule() └── context_switch() └── finish_task_switch() └── tick_nohz_task_switch() └── tick_nohz_full_kick() └── irq_work_queue() When irq_exit() is called, tick_nohz_restart_sched_tick() will be called to update jiffies fallowing: irq_exit() └── __irq_exit_rcu() └── tick_nohz_irq_exit() └── tick_nohz_full_update_tick() └── tick_nohz_restart_sched_tick() └── tick_do_update_jiffies64() This irregular updating may cause jiffies to grow too rapidly in a short period of time, and makes cppc_get_perf_ctrs_pair() to think it has waited long enough and exit the while loop, eventually leads to inaccurate reading frequency. Use `ktime` instead of `jiffies` to obtain system time will solve this problem. Fixes: 7404f3db35e3 ("cpufreq: CPPC: Eliminate the impact of cpc_read() latency error") Signed-off-by: Lifeng Zheng <zhenglifeng1@huawei.com> Signed-off-by: Hongye Lin <linhongye@h-partners.com> --- drivers/cpufreq/cppc_cpufreq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index c34d04a3bf65..b0a73531a4ea 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -758,7 +758,7 @@ static int cppc_get_perf_ctrs_pair(void *val) struct fb_ctr_pair *fb_ctrs = val; int cpu = fb_ctrs->cpu; int ret; - unsigned long timeout; + ktime_t timeout; ret = cppc_get_perf_ctrs(cpu, &fb_ctrs->fb_ctrs_t0); if (ret) @@ -770,8 +770,8 @@ static int cppc_get_perf_ctrs_pair(void *val) * to the idle task to prevent the AMU counters from * stopping working. */ - timeout = jiffies + msecs_to_jiffies(1); - while (!time_after(jiffies, timeout)) + timeout = ktime_add_ms(ktime_get(), 1); + while (ktime_before(ktime_get(), timeout)) cond_resched(); } else { pr_warn_once("CPU%d: Get rate in atomic context", cpu); -- 2.33.0