Skip to content

Commit 6d45b71

Browse files
committed
intel_pstate: Fix intel_pstate_get()
After commit 8fa520a "intel_pstate: Remove freq calculation from intel_pstate_calc_busy()" intel_pstate_get() calls get_avg_frequency() to compute the average frequency, which is problematic for two reasons. First, intel_pstate_get() may be invoked before the driver reads the CPU feedback registers for the first time and if that happens, get_avg_frequency() will attempt to divide by zero. Second, the get_avg_frequency() call in intel_pstate_get() is racy with respect to intel_pstate_sample() and it may end up returning completely meaningless values for this reason. Moreover, after commit 7349ec0 "intel_pstate: Move intel_pstate_calc_busy() into get_target_pstate_use_performance()" sample.core_pct_busy is never computed on Atom, but it is used in intel_pstate_adjust_busy_pstate() in that case too. To address those problems notice that if sample.core_pct_busy was used in the average frequency computation carried out by get_avg_frequency(), both the divide by zero problem and the race with respect to intel_pstate_sample() would be avoided. Accordingly, move the invocation of intel_pstate_calc_busy() from get_target_pstate_use_performance() to intel_pstate_update_util(), which also will take care of the uninitialized sample.core_pct_busy on Atom, and modify get_avg_frequency() to use sample.core_pct_busy as per the above. Reported-by: kernel test robot <ying.huang@linux.intel.com> Link: http://marc.info/?l=linux-kernel&m=146226437623173&w=4 Fixes: 8fa520a "intel_pstate: Remove freq calculation from intel_pstate_calc_busy()" Fixes: 7349ec0 "intel_pstate: Move intel_pstate_calc_busy() into get_target_pstate_use_performance()" Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent ba41e1b commit 6d45b71

File tree

1 file changed

+8
-6
lines changed

1 file changed

+8
-6
lines changed

drivers/cpufreq/intel_pstate.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,8 +1070,9 @@ static inline bool intel_pstate_sample(struct cpudata *cpu, u64 time)
10701070

10711071
static inline int32_t get_avg_frequency(struct cpudata *cpu)
10721072
{
1073-
return div64_u64(cpu->pstate.max_pstate_physical * cpu->sample.aperf *
1074-
cpu->pstate.scaling, cpu->sample.mperf);
1073+
return fp_toint(mul_fp(cpu->sample.core_pct_busy,
1074+
int_tofp(cpu->pstate.max_pstate_physical *
1075+
cpu->pstate.scaling / 100)));
10751076
}
10761077

10771078
static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
@@ -1114,8 +1115,6 @@ static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
11141115
int32_t core_busy, max_pstate, current_pstate, sample_ratio;
11151116
u64 duration_ns;
11161117

1117-
intel_pstate_calc_busy(cpu);
1118-
11191118
/*
11201119
* core_busy is the ratio of actual performance to max
11211120
* max_pstate is the max non turbo pstate available
@@ -1199,8 +1198,11 @@ static void intel_pstate_update_util(struct update_util_data *data, u64 time,
11991198
if ((s64)delta_ns >= pid_params.sample_rate_ns) {
12001199
bool sample_taken = intel_pstate_sample(cpu, time);
12011200

1202-
if (sample_taken && !hwp_active)
1203-
intel_pstate_adjust_busy_pstate(cpu);
1201+
if (sample_taken) {
1202+
intel_pstate_calc_busy(cpu);
1203+
if (!hwp_active)
1204+
intel_pstate_adjust_busy_pstate(cpu);
1205+
}
12041206
}
12051207
}
12061208

0 commit comments

Comments
 (0)