Skip to content

Commit 16fb8d8

Browse files
Henry Tsengrafaeljw
authored andcommitted
cpufreq: acpi-cpufreq: use DMI max speed when CPPC is unavailable
On AMD Ryzen Embedded V1780B (Family 17h, Zen 1), the BIOS does not provide ACPI _CPC objects and the CPU does not support MSR-based CPPC (X86_FEATURE_CPPC). The _PSS table only lists nominal P-states (P0 = 3350 MHz), so when get_max_boost_ratio() fails at cppc_get_perf_caps(), cpuinfo_max_freq reports only the base frequency instead of the rated boost frequency (3600 MHz). dmesg: ACPI CPPC: No CPC descriptor for CPU:0 acpi_cpufreq: CPU0: Unable to get performance capabilities (-19) cppc-cpufreq already has a DMI fallback (cppc_get_dmi_max_khz()) that reads the processor max speed from SMBIOS Type 4. Export it and reuse it in acpi-cpufreq as a last-resort source for the boost frequency. A sanity check ensures the DMI value is above the _PSS P0 frequency and within 2x of it; values outside that range are ignored and the existing arch_set_max_freq_ratio() path is taken instead. The 2x upper bound is based on a survey of the AMD Ryzen Embedded V1000 series, where the highest boost-to-base ratio is 1.8x (V1404I: 2.0 GHz base / 3.6 GHz boost). The DMI lookup and sanity check are wrapped in a helper, acpi_cpufreq_resolve_max_freq(), which falls through to arch_set_max_freq_ratio() if the DMI value is absent or out of range. Tested on AMD Ryzen Embedded V1780B with v7.0-rc4: Before: cpuinfo_max_freq = 3350000 (base only) After: cpuinfo_max_freq = 3600000 (includes boost) Link: https://www.amd.com/en/products/embedded/ryzen/ryzen-v1000-series.html#specifications Signed-off-by: Henry Tseng <henrytseng@qnap.com> Link: https://patch.msgid.link/20260324090948.1667340-1-henrytseng@qnap.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 16c1e83 commit 16fb8d8

3 files changed

Lines changed: 27 additions & 8 deletions

File tree

drivers/acpi/cppc_acpi.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1944,7 +1944,7 @@ static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private)
19441944
}
19451945

19461946
/* Look up the max frequency in DMI */
1947-
static u64 cppc_get_dmi_max_khz(void)
1947+
u64 cppc_get_dmi_max_khz(void)
19481948
{
19491949
u16 mhz = 0;
19501950

@@ -1958,6 +1958,7 @@ static u64 cppc_get_dmi_max_khz(void)
19581958

19591959
return KHZ_PER_MHZ * mhz;
19601960
}
1961+
EXPORT_SYMBOL_GPL(cppc_get_dmi_max_khz);
19611962

19621963
/*
19631964
* If CPPC lowest_freq and nominal_freq registers are exposed then we can

drivers/cpufreq/acpi-cpufreq.c

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,29 @@ static inline u64 get_max_boost_ratio(unsigned int cpu, u64 *nominal_freq)
675675
}
676676
#endif
677677

678+
static void acpi_cpufreq_resolve_max_freq(struct cpufreq_policy *policy,
679+
unsigned int pss_max_freq)
680+
{
681+
#ifdef CONFIG_ACPI_CPPC_LIB
682+
u64 max_speed = cppc_get_dmi_max_khz();
683+
/*
684+
* Use DMI "Max Speed" if it looks plausible: must be
685+
* above _PSS P0 frequency and within 2x of it.
686+
*/
687+
if (max_speed > pss_max_freq && max_speed < pss_max_freq * 2) {
688+
policy->cpuinfo.max_freq = max_speed;
689+
return;
690+
}
691+
#endif
692+
/*
693+
* If the maximum "boost" frequency is unknown, ask the arch
694+
* scale-invariance code to use the "nominal" performance for
695+
* CPU utilization scaling so as to prevent the schedutil
696+
* governor from selecting inadequate CPU frequencies.
697+
*/
698+
arch_set_max_freq_ratio(true);
699+
}
700+
678701
static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
679702
{
680703
struct cpufreq_frequency_table *freq_table;
@@ -849,13 +872,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
849872

850873
policy->cpuinfo.max_freq = freq * max_boost_ratio >> SCHED_CAPACITY_SHIFT;
851874
} else {
852-
/*
853-
* If the maximum "boost" frequency is unknown, ask the arch
854-
* scale-invariance code to use the "nominal" performance for
855-
* CPU utilization scaling so as to prevent the schedutil
856-
* governor from selecting inadequate CPU frequencies.
857-
*/
858-
arch_set_max_freq_ratio(true);
875+
acpi_cpufreq_resolve_max_freq(policy, freq_table[0].frequency);
859876
}
860877

861878
policy->freq_table = freq_table;

include/acpi/cppc_acpi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ extern int cppc_set_enable(int cpu, bool enable);
156156
extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps);
157157
extern bool cppc_perf_ctrs_in_pcc_cpu(unsigned int cpu);
158158
extern bool cppc_perf_ctrs_in_pcc(void);
159+
extern u64 cppc_get_dmi_max_khz(void);
159160
extern unsigned int cppc_perf_to_khz(struct cppc_perf_caps *caps, unsigned int perf);
160161
extern unsigned int cppc_khz_to_perf(struct cppc_perf_caps *caps, unsigned int freq);
161162
extern bool acpi_cpc_valid(void);

0 commit comments

Comments
 (0)