Skip to content

Commit 6e34e1f

Browse files
spandruvadarafaeljw
authored andcommitted
cpufreq: intel_pstate: Correct the busy calculation for KNL
The busy percent calculated for the Knights Landing (KNL) platform is 1024 times smaller than the correct busy value. This causes performance to get stuck at the lowest ratio. The scaling algorithm used for KNL is performance-based, but it still looks at the CPU load to set the scaled busy factor to 0 when the load is less than 1 percent. In this case, since the computed load is 1024x smaller than it should be, the scaled busy factor will always be 0, irrespective of CPU business. This needs a fix similar to the turbostat one in commit b2b34df (tools/power turbostat: KNL workaround for %Busy and Avg_MHz). For this reason, add one more callback to processor-specific callbacks to specify an MPERF multiplier represented by a number of bit positions to shift the value of that register to the left to copmensate for its rate difference with respect to the TSC. This shift value is used during CPU busy calculations. Fixes: ffb8105 (intel_pstate: Avoid getting stuck in high P-states when idle) Reported-and-tested-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Cc: 4.6+ <stable@vger.kernel.org> # 4.6+ [ rjw: Changelog ] Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent d4436c0 commit 6e34e1f

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

drivers/cpufreq/intel_pstate.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,9 @@ struct global_params {
225225
* @vid: Stores VID limits for this CPU
226226
* @pid: Stores PID parameters for this CPU
227227
* @last_sample_time: Last Sample time
228+
* @aperf_mperf_shift: Number of clock cycles after aperf, merf is incremented
229+
* This shift is a multiplier to mperf delta to
230+
* calculate CPU busy.
228231
* @prev_aperf: Last APERF value read from APERF MSR
229232
* @prev_mperf: Last MPERF value read from MPERF MSR
230233
* @prev_tsc: Last timestamp counter (TSC) value
@@ -259,6 +262,7 @@ struct cpudata {
259262

260263
u64 last_update;
261264
u64 last_sample_time;
265+
u64 aperf_mperf_shift;
262266
u64 prev_aperf;
263267
u64 prev_mperf;
264268
u64 prev_tsc;
@@ -321,6 +325,7 @@ struct pstate_funcs {
321325
int (*get_min)(void);
322326
int (*get_turbo)(void);
323327
int (*get_scaling)(void);
328+
int (*get_aperf_mperf_shift)(void);
324329
u64 (*get_val)(struct cpudata*, int pstate);
325330
void (*get_vid)(struct cpudata *);
326331
void (*update_util)(struct update_util_data *data, u64 time,
@@ -1490,6 +1495,11 @@ static u64 core_get_val(struct cpudata *cpudata, int pstate)
14901495
return val;
14911496
}
14921497

1498+
static int knl_get_aperf_mperf_shift(void)
1499+
{
1500+
return 10;
1501+
}
1502+
14931503
static int knl_get_turbo_pstate(void)
14941504
{
14951505
u64 value;
@@ -1547,6 +1557,9 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
15471557
cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling;
15481558
cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling;
15491559

1560+
if (pstate_funcs.get_aperf_mperf_shift)
1561+
cpu->aperf_mperf_shift = pstate_funcs.get_aperf_mperf_shift();
1562+
15501563
if (pstate_funcs.get_vid)
15511564
pstate_funcs.get_vid(cpu);
15521565

@@ -1620,7 +1633,8 @@ static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
16201633
int32_t busy_frac, boost;
16211634
int target, avg_pstate;
16221635

1623-
busy_frac = div_fp(sample->mperf, sample->tsc);
1636+
busy_frac = div_fp(sample->mperf << cpu->aperf_mperf_shift,
1637+
sample->tsc);
16241638

16251639
boost = cpu->iowait_boost;
16261640
cpu->iowait_boost >>= 1;
@@ -1679,7 +1693,8 @@ static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
16791693
sample_ratio = div_fp(pid_params.sample_rate_ns, duration_ns);
16801694
perf_scaled = mul_fp(perf_scaled, sample_ratio);
16811695
} else {
1682-
sample_ratio = div_fp(100 * cpu->sample.mperf, cpu->sample.tsc);
1696+
sample_ratio = div_fp(100 * (cpu->sample.mperf << cpu->aperf_mperf_shift),
1697+
cpu->sample.tsc);
16831698
if (sample_ratio < int_tofp(1))
16841699
perf_scaled = 0;
16851700
}
@@ -1811,6 +1826,7 @@ static const struct pstate_funcs knl_funcs = {
18111826
.get_max_physical = core_get_max_pstate_physical,
18121827
.get_min = core_get_min_pstate,
18131828
.get_turbo = knl_get_turbo_pstate,
1829+
.get_aperf_mperf_shift = knl_get_aperf_mperf_shift,
18141830
.get_scaling = core_get_scaling,
18151831
.get_val = core_get_val,
18161832
.update_util = intel_pstate_update_util_pid,
@@ -2407,6 +2423,7 @@ static void __init copy_cpu_funcs(struct pstate_funcs *funcs)
24072423
pstate_funcs.get_val = funcs->get_val;
24082424
pstate_funcs.get_vid = funcs->get_vid;
24092425
pstate_funcs.update_util = funcs->update_util;
2426+
pstate_funcs.get_aperf_mperf_shift = funcs->get_aperf_mperf_shift;
24102427

24112428
intel_pstate_use_acpi_profile();
24122429
}

0 commit comments

Comments
 (0)