Skip to content

Commit

Permalink
cpufreq: intel_pstate: Read all MSRs on the target CPU
Browse files Browse the repository at this point in the history
commit 8dbab94 upstream.

Some of the MSR accesses in intel_pstate are carried out on the CPU
that is running the code, but the values coming from them are used
for the performance scaling of the other CPUs.

This is problematic, for example, on hybrid platforms where
MSR_TURBO_RATIO_LIMIT for P-cores and E-cores is different, so the
values read from it on a P-core are generally not applicable to E-cores
and the other way around.

For this reason, make the driver access all MSRs on the target CPU on
platforms using the "core" pstate_funcs callbacks which is the case for
all of the hybrid platforms released to date.  For this purpose, pass
a CPU argument to the ->get_max(), ->get_max_physical(), ->get_min()
and ->get_turbo() pstate_funcs callbacks and from there pass it to
rdmsrl_on_cpu() or rdmsrl_safe_on_cpu() to access the MSR on the target
CPU.

Fixes: 46573fd ("cpufreq: intel_pstate: hybrid: Rework HWP calibration")
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Tested-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Cc: 5.15+ <stable@vger.kernel.org> # 5.15+
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
rafaeljw authored and gregkh committed Nov 3, 2022
1 parent cc6a724 commit 3423a34
Showing 1 changed file with 33 additions and 33 deletions.
66 changes: 33 additions & 33 deletions drivers/cpufreq/intel_pstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,10 +277,10 @@ static struct cpudata **all_cpu_data;
* structure is used to store those callbacks.
*/
struct pstate_funcs {
int (*get_max)(void);
int (*get_max_physical)(void);
int (*get_min)(void);
int (*get_turbo)(void);
int (*get_max)(int cpu);
int (*get_max_physical)(int cpu);
int (*get_min)(int cpu);
int (*get_turbo)(int cpu);
int (*get_scaling)(void);
int (*get_cpu_scaling)(int cpu);
int (*get_aperf_mperf_shift)(void);
Expand Down Expand Up @@ -528,12 +528,12 @@ static void intel_pstate_hybrid_hwp_adjust(struct cpudata *cpu)
{
int perf_ctl_max_phys = cpu->pstate.max_pstate_physical;
int perf_ctl_scaling = cpu->pstate.perf_ctl_scaling;
int perf_ctl_turbo = pstate_funcs.get_turbo();
int perf_ctl_turbo = pstate_funcs.get_turbo(cpu->cpu);
int turbo_freq = perf_ctl_turbo * perf_ctl_scaling;
int scaling = cpu->pstate.scaling;

pr_debug("CPU%d: perf_ctl_max_phys = %d\n", cpu->cpu, perf_ctl_max_phys);
pr_debug("CPU%d: perf_ctl_max = %d\n", cpu->cpu, pstate_funcs.get_max());
pr_debug("CPU%d: perf_ctl_max = %d\n", cpu->cpu, pstate_funcs.get_max(cpu->cpu));
pr_debug("CPU%d: perf_ctl_turbo = %d\n", cpu->cpu, perf_ctl_turbo);
pr_debug("CPU%d: perf_ctl_scaling = %d\n", cpu->cpu, perf_ctl_scaling);
pr_debug("CPU%d: HWP_CAP guaranteed = %d\n", cpu->cpu, cpu->pstate.max_pstate);
Expand Down Expand Up @@ -1581,23 +1581,23 @@ static void intel_pstate_hwp_enable(struct cpudata *cpudata)
cpudata->epp_default = intel_pstate_get_epp(cpudata, 0);
}

static int atom_get_min_pstate(void)
static int atom_get_min_pstate(int not_used)
{
u64 value;

rdmsrl(MSR_ATOM_CORE_RATIOS, value);
return (value >> 8) & 0x7F;
}

static int atom_get_max_pstate(void)
static int atom_get_max_pstate(int not_used)
{
u64 value;

rdmsrl(MSR_ATOM_CORE_RATIOS, value);
return (value >> 16) & 0x7F;
}

static int atom_get_turbo_pstate(void)
static int atom_get_turbo_pstate(int not_used)
{
u64 value;

Expand Down Expand Up @@ -1675,23 +1675,23 @@ static void atom_get_vid(struct cpudata *cpudata)
cpudata->vid.turbo = value & 0x7f;
}

static int core_get_min_pstate(void)
static int core_get_min_pstate(int cpu)
{
u64 value;

rdmsrl(MSR_PLATFORM_INFO, value);
rdmsrl_on_cpu(cpu, MSR_PLATFORM_INFO, &value);
return (value >> 40) & 0xFF;
}

static int core_get_max_pstate_physical(void)
static int core_get_max_pstate_physical(int cpu)
{
u64 value;

rdmsrl(MSR_PLATFORM_INFO, value);
rdmsrl_on_cpu(cpu, MSR_PLATFORM_INFO, &value);
return (value >> 8) & 0xFF;
}

static int core_get_tdp_ratio(u64 plat_info)
static int core_get_tdp_ratio(int cpu, u64 plat_info)
{
/* Check how many TDP levels present */
if (plat_info & 0x600000000) {
Expand All @@ -1701,13 +1701,13 @@ static int core_get_tdp_ratio(u64 plat_info)
int err;

/* Get the TDP level (0, 1, 2) to get ratios */
err = rdmsrl_safe(MSR_CONFIG_TDP_CONTROL, &tdp_ctrl);
err = rdmsrl_safe_on_cpu(cpu, MSR_CONFIG_TDP_CONTROL, &tdp_ctrl);
if (err)
return err;

/* TDP MSR are continuous starting at 0x648 */
tdp_msr = MSR_CONFIG_TDP_NOMINAL + (tdp_ctrl & 0x03);
err = rdmsrl_safe(tdp_msr, &tdp_ratio);
err = rdmsrl_safe_on_cpu(cpu, tdp_msr, &tdp_ratio);
if (err)
return err;

Expand All @@ -1724,18 +1724,18 @@ static int core_get_tdp_ratio(u64 plat_info)
return -ENXIO;
}

static int core_get_max_pstate(void)
static int core_get_max_pstate(int cpu)
{
u64 tar;
u64 plat_info;
int max_pstate;
int tdp_ratio;
int err;

rdmsrl(MSR_PLATFORM_INFO, plat_info);
rdmsrl_on_cpu(cpu, MSR_PLATFORM_INFO, &plat_info);
max_pstate = (plat_info >> 8) & 0xFF;

tdp_ratio = core_get_tdp_ratio(plat_info);
tdp_ratio = core_get_tdp_ratio(cpu, plat_info);
if (tdp_ratio <= 0)
return max_pstate;

Expand All @@ -1744,7 +1744,7 @@ static int core_get_max_pstate(void)
return tdp_ratio;
}

err = rdmsrl_safe(MSR_TURBO_ACTIVATION_RATIO, &tar);
err = rdmsrl_safe_on_cpu(cpu, MSR_TURBO_ACTIVATION_RATIO, &tar);
if (!err) {
int tar_levels;

Expand All @@ -1759,13 +1759,13 @@ static int core_get_max_pstate(void)
return max_pstate;
}

static int core_get_turbo_pstate(void)
static int core_get_turbo_pstate(int cpu)
{
u64 value;
int nont, ret;

rdmsrl(MSR_TURBO_RATIO_LIMIT, value);
nont = core_get_max_pstate();
rdmsrl_on_cpu(cpu, MSR_TURBO_RATIO_LIMIT, &value);
nont = core_get_max_pstate(cpu);
ret = (value) & 255;
if (ret <= nont)
ret = nont;
Expand Down Expand Up @@ -1793,13 +1793,13 @@ static int knl_get_aperf_mperf_shift(void)
return 10;
}

static int knl_get_turbo_pstate(void)
static int knl_get_turbo_pstate(int cpu)
{
u64 value;
int nont, ret;

rdmsrl(MSR_TURBO_RATIO_LIMIT, value);
nont = core_get_max_pstate();
rdmsrl_on_cpu(cpu, MSR_TURBO_RATIO_LIMIT, &value);
nont = core_get_max_pstate(cpu);
ret = (((value) >> 8) & 0xFF);
if (ret <= nont)
ret = nont;
Expand Down Expand Up @@ -1866,10 +1866,10 @@ static void intel_pstate_max_within_limits(struct cpudata *cpu)

static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
{
int perf_ctl_max_phys = pstate_funcs.get_max_physical();
int perf_ctl_max_phys = pstate_funcs.get_max_physical(cpu->cpu);
int perf_ctl_scaling = pstate_funcs.get_scaling();

cpu->pstate.min_pstate = pstate_funcs.get_min();
cpu->pstate.min_pstate = pstate_funcs.get_min(cpu->cpu);
cpu->pstate.max_pstate_physical = perf_ctl_max_phys;
cpu->pstate.perf_ctl_scaling = perf_ctl_scaling;

Expand All @@ -1885,8 +1885,8 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
}
} else {
cpu->pstate.scaling = perf_ctl_scaling;
cpu->pstate.max_pstate = pstate_funcs.get_max();
cpu->pstate.turbo_pstate = pstate_funcs.get_turbo();
cpu->pstate.max_pstate = pstate_funcs.get_max(cpu->cpu);
cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(cpu->cpu);
}

if (cpu->pstate.scaling == perf_ctl_scaling) {
Expand Down Expand Up @@ -3063,9 +3063,9 @@ static unsigned int force_load __initdata;

static int __init intel_pstate_msrs_not_valid(void)
{
if (!pstate_funcs.get_max() ||
!pstate_funcs.get_min() ||
!pstate_funcs.get_turbo())
if (!pstate_funcs.get_max(0) ||
!pstate_funcs.get_min(0) ||
!pstate_funcs.get_turbo(0))
return -ENODEV;

return 0;
Expand Down

0 comments on commit 3423a34

Please sign in to comment.