Skip to content

Commit 9b18d53

Browse files
committed
cpufreq: intel_pstate: Use CPPC to get scaling factors
The perf-to-frequency scaling factors are used by intel_pstate on hybrid platforms to cast performance levels to frequency on different types of CPUs which is needed because the generic cpufreq sysfs interface works in the frequency domain. For some hybrid platforms already in the field, the scaling factors are known, but for others (including some upcoming ones) they most likely will be different and the only way to get them that scales is to use information provided by the platform firmware. In this particular case, the requisite information can be obtained via CPPC. If the P-core hybrid scaling factor for the given processor model is not known, use CPPC to compute hybrid scaling factors for all CPUs. Since the current default hybrid scaling factor is only suitable for a few early hybrid platforms, add intel_hybrid_scaling_factor[] entries for them and initialize the scaling factor to zero ("unknown") by default. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Link: https://patch.msgid.link/8476313.T7Z3S40VBb@rjwysocki.net
1 parent fac04ef commit 9b18d53

File tree

1 file changed

+33
-24
lines changed

1 file changed

+33
-24
lines changed

drivers/cpufreq/intel_pstate.c

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/pm_qos.h>
2929
#include <linux/bitfield.h>
3030
#include <trace/events/power.h>
31+
#include <linux/units.h>
3132

3233
#include <asm/cpu.h>
3334
#include <asm/div64.h>
@@ -302,11 +303,11 @@ static bool hwp_is_hybrid;
302303

303304
static struct cpufreq_driver *intel_pstate_driver __read_mostly;
304305

305-
#define HYBRID_SCALING_FACTOR 78741
306+
#define HYBRID_SCALING_FACTOR_ADL 78741
306307
#define HYBRID_SCALING_FACTOR_MTL 80000
307308
#define HYBRID_SCALING_FACTOR_LNL 86957
308309

309-
static int hybrid_scaling_factor = HYBRID_SCALING_FACTOR;
310+
static int hybrid_scaling_factor;
310311

311312
static inline int core_get_scaling(void)
312313
{
@@ -414,18 +415,15 @@ static int intel_pstate_get_cppc_guaranteed(int cpu)
414415
static int intel_pstate_cppc_get_scaling(int cpu)
415416
{
416417
struct cppc_perf_caps cppc_perf;
417-
int ret;
418-
419-
ret = cppc_get_perf_caps(cpu, &cppc_perf);
420418

421419
/*
422-
* If the nominal frequency and the nominal performance are not
423-
* zero and the ratio between them is not 100, return the hybrid
424-
* scaling factor.
420+
* Compute the perf-to-frequency scaling factor for the given CPU if
421+
* possible, unless it would be 0.
425422
*/
426-
if (!ret && cppc_perf.nominal_perf && cppc_perf.nominal_freq &&
427-
cppc_perf.nominal_perf * 100 != cppc_perf.nominal_freq)
428-
return hybrid_scaling_factor;
423+
if (!cppc_get_perf_caps(cpu, &cppc_perf) &&
424+
cppc_perf.nominal_perf && cppc_perf.nominal_freq)
425+
return div_u64(cppc_perf.nominal_freq * KHZ_PER_MHZ,
426+
cppc_perf.nominal_perf);
429427

430428
return core_get_scaling();
431429
}
@@ -2211,24 +2209,30 @@ static void hybrid_get_type(void *data)
22112209

22122210
static int hwp_get_cpu_scaling(int cpu)
22132211
{
2214-
u8 cpu_type = 0;
2212+
if (hybrid_scaling_factor) {
2213+
u8 cpu_type = 0;
22152214

2216-
smp_call_function_single(cpu, hybrid_get_type, &cpu_type, 1);
2217-
/* P-cores have a smaller perf level-to-freqency scaling factor. */
2218-
if (cpu_type == 0x40)
2219-
return hybrid_scaling_factor;
2215+
smp_call_function_single(cpu, hybrid_get_type, &cpu_type, 1);
22202216

2221-
/* Use default core scaling for E-cores */
2222-
if (cpu_type == 0x20)
2217+
/*
2218+
* Return the hybrid scaling factor for P-cores and use the
2219+
* default core scaling for E-cores.
2220+
*/
2221+
if (cpu_type == 0x40)
2222+
return hybrid_scaling_factor;
2223+
2224+
if (cpu_type == 0x20)
2225+
return core_get_scaling();
2226+
}
2227+
2228+
/* Use core scaling on non-hybrid systems. */
2229+
if (!cpu_feature_enabled(X86_FEATURE_HYBRID_CPU))
22232230
return core_get_scaling();
22242231

22252232
/*
2226-
* If reached here, this system is either non-hybrid (like Tiger
2227-
* Lake) or hybrid-capable (like Alder Lake or Raptor Lake) with
2228-
* no E cores (in which case CPUID for hybrid support is 0).
2229-
*
2230-
* The CPPC nominal_frequency field is 0 for non-hybrid systems,
2231-
* so the default core scaling will be used for them.
2233+
* The system is hybrid, but the hybrid scaling factor is not known or
2234+
* the CPU type is not one of the above, so use CPPC to compute the
2235+
* scaling factor for this CPU.
22322236
*/
22332237
return intel_pstate_cppc_get_scaling(cpu);
22342238
}
@@ -3665,6 +3669,11 @@ static const struct x86_cpu_id intel_epp_default[] = {
36653669
};
36663670

36673671
static const struct x86_cpu_id intel_hybrid_scaling_factor[] = {
3672+
X86_MATCH_VFM(INTEL_ALDERLAKE, HYBRID_SCALING_FACTOR_ADL),
3673+
X86_MATCH_VFM(INTEL_ALDERLAKE_L, HYBRID_SCALING_FACTOR_ADL),
3674+
X86_MATCH_VFM(INTEL_RAPTORLAKE, HYBRID_SCALING_FACTOR_ADL),
3675+
X86_MATCH_VFM(INTEL_RAPTORLAKE_P, HYBRID_SCALING_FACTOR_ADL),
3676+
X86_MATCH_VFM(INTEL_RAPTORLAKE_S, HYBRID_SCALING_FACTOR_ADL),
36683677
X86_MATCH_VFM(INTEL_METEORLAKE_L, HYBRID_SCALING_FACTOR_MTL),
36693678
X86_MATCH_VFM(INTEL_ARROWLAKE, HYBRID_SCALING_FACTOR_MTL),
36703679
X86_MATCH_VFM(INTEL_LUNARLAKE_M, HYBRID_SCALING_FACTOR_LNL),

0 commit comments

Comments
 (0)