diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index f29182512b98..8ca2bce4341a 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -302,6 +302,13 @@ static bool hwp_forced __read_mostly; static struct cpufreq_driver *intel_pstate_driver __read_mostly; +#define HYBRID_SCALING_FACTOR 78741 + +static inline int core_get_scaling(void) +{ + return 100000; +} + #ifdef CONFIG_ACPI static bool acpi_ppc; #endif @@ -400,6 +407,26 @@ static int intel_pstate_get_cppc_guaranteed(int cpu) return cppc_perf.nominal_perf; } + +static int intel_pstate_cppc_get_scaling(int cpu) +{ + struct cppc_perf_caps cppc_perf; + int ret; + + ret = cppc_get_perf_caps(cpu, &cppc_perf); + + /* + * If the nominal frequency and the nominal performance are not + * zero and the ratio between them is not 100, return the hybrid + * scaling factor. + */ + if (!ret && cppc_perf.nominal_perf && cppc_perf.nominal_freq && + cppc_perf.nominal_perf * 100 != cppc_perf.nominal_freq) + return HYBRID_SCALING_FACTOR; + + return core_get_scaling(); +} + #else /* CONFIG_ACPI_CPPC_LIB */ static inline void intel_pstate_set_itmt_prio(int cpu) { @@ -492,6 +519,11 @@ static inline int intel_pstate_get_cppc_guaranteed(int cpu) { return -ENOTSUPP; } + +static int intel_pstate_cppc_get_scaling(int cpu) +{ + return core_get_scaling(); +} #endif /* CONFIG_ACPI_CPPC_LIB */ /** @@ -1897,11 +1929,6 @@ static int core_get_turbo_pstate(int cpu) return ret; } -static inline int core_get_scaling(void) -{ - return 100000; -} - static u64 core_get_val(struct cpudata *cpudata, int pstate) { u64 val; @@ -1938,16 +1965,28 @@ static void hybrid_get_type(void *data) *cpu_type = get_this_hybrid_cpu_type(); } -static int hybrid_get_cpu_scaling(int cpu) +static int hwp_get_cpu_scaling(int cpu) { u8 cpu_type = 0; smp_call_function_single(cpu, hybrid_get_type, &cpu_type, 1); /* P-cores have a smaller perf level-to-freqency scaling factor. */ if (cpu_type == 0x40) - return 78741; + return HYBRID_SCALING_FACTOR; - return core_get_scaling(); + /* Use default core scaling for E-cores */ + if (cpu_type == 0x20) + return core_get_scaling(); + + /* + * If reached here, this system is either non-hybrid (like Tiger + * Lake) or hybrid-capable (like Alder Lake or Raptor Lake) with + * no E cores (in which case CPUID for hybrid support is 0). + * + * The CPPC nominal_frequency field is 0 for non-hybrid systems, + * so the default core scaling will be used for them. + */ + return intel_pstate_cppc_get_scaling(cpu); } static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) @@ -3395,8 +3434,7 @@ static int __init intel_pstate_init(void) if (!default_driver) default_driver = &intel_pstate; - if (boot_cpu_has(X86_FEATURE_HYBRID_CPU)) - pstate_funcs.get_cpu_scaling = hybrid_get_cpu_scaling; + pstate_funcs.get_cpu_scaling = hwp_get_cpu_scaling; goto hwp_cpu_matched; }