Skip to content

Commit c7e29dc

Browse files
committed
Merge branch 'amd-pstate'
Merge AMD P-state driver changes from Perry Yuan for v6.10: "- Enable CPPC v2 for certain processors in the family 17H, as requested by TR40 processor users who expect improved performance and lower system temperature. - Change latency and delay values to be read from platform firmware firstly for more accurate timing. - A new quirk is introduced for supporting amd-pstate on legacy processors which either lack CPPC capability, or only only have CPPC v2 capability." * amd-pstate: MAINTAINERS: cpufreq: amd-pstate: Add co-maintainers and reviewer cpufreq: amd-pstate: remove unused variable lowest_nonlinear_freq cpufreq: amd-pstate: fix code format problems cpufreq: amd-pstate: Add quirk for the pstate CPPC capabilities missing cppc_acpi: print error message if CPPC is unsupported cpufreq: amd-pstate: get transition delay and latency value from ACPI tables cpufreq: amd-pstate: Bail out if min/max/nominal_freq is 0 cpufreq: amd-pstate: Remove amd_get_{min,max,nominal,lowest_nonlinear}_freq() cpufreq: amd-pstate: Unify computation of {max,min,nominal,lowest_nonlinear}_freq cpufreq: amd-pstate: Document the units for freq variables in amd_cpudata cpufreq: amd-pstate: Document *_limit_* fields in struct amd_cpudata
2 parents a2bd1d2 + 70f83f5 commit c7e29dc

File tree

4 files changed

+176
-109
lines changed

4 files changed

+176
-109
lines changed

MAINTAINERS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,9 @@ F: drivers/gpu/drm/amd/pm/
10621062

10631063
AMD PSTATE DRIVER
10641064
M: Huang Rui <[email protected]>
1065+
M: Gautham R. Shenoy <[email protected]>
1066+
M: Mario Limonciello <[email protected]>
1067+
R: Perry Yuan <[email protected]>
10651068
10661069
S: Supported
10671070
F: Documentation/admin-guide/pm/amd-pstate.rst

drivers/acpi/cppc_acpi.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,8 +686,10 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
686686

687687
if (!osc_sb_cppc2_support_acked) {
688688
pr_debug("CPPC v2 _OSC not acked\n");
689-
if (!cpc_supported_by_cpu())
689+
if (!cpc_supported_by_cpu()) {
690+
pr_debug("CPPC is not supported by the CPU\n");
690691
return -ENODEV;
692+
}
691693
}
692694

693695
/* Parse the ACPI _CPC table for this CPU. */

drivers/cpufreq/amd-pstate.c

Lines changed: 155 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ static struct cpufreq_driver amd_pstate_epp_driver;
6767
static int cppc_state = AMD_PSTATE_UNDEFINED;
6868
static bool cppc_enabled;
6969
static bool amd_pstate_prefcore = true;
70+
static struct quirk_entry *quirks;
7071

7172
/*
7273
* AMD Energy Preference Performance (EPP)
@@ -111,6 +112,41 @@ static unsigned int epp_values[] = {
111112

112113
typedef int (*cppc_mode_transition_fn)(int);
113114

115+
static struct quirk_entry quirk_amd_7k62 = {
116+
.nominal_freq = 2600,
117+
.lowest_freq = 550,
118+
};
119+
120+
static int __init dmi_matched_7k62_bios_bug(const struct dmi_system_id *dmi)
121+
{
122+
/**
123+
* match the broken bios for family 17h processor support CPPC V2
124+
* broken BIOS lack of nominal_freq and lowest_freq capabilities
125+
* definition in ACPI tables
126+
*/
127+
if (boot_cpu_has(X86_FEATURE_ZEN2)) {
128+
quirks = dmi->driver_data;
129+
pr_info("Overriding nominal and lowest frequencies for %s\n", dmi->ident);
130+
return 1;
131+
}
132+
133+
return 0;
134+
}
135+
136+
static const struct dmi_system_id amd_pstate_quirks_table[] __initconst = {
137+
{
138+
.callback = dmi_matched_7k62_bios_bug,
139+
.ident = "AMD EPYC 7K62",
140+
.matches = {
141+
DMI_MATCH(DMI_BIOS_VERSION, "5.14"),
142+
DMI_MATCH(DMI_BIOS_RELEASE, "12/12/2019"),
143+
},
144+
.driver_data = &quirk_amd_7k62,
145+
},
146+
{}
147+
};
148+
MODULE_DEVICE_TABLE(dmi, amd_pstate_quirks_table);
149+
114150
static inline int get_mode_idx_from_str(const char *str, size_t size)
115151
{
116152
int i;
@@ -604,78 +640,6 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
604640
cpufreq_cpu_put(policy);
605641
}
606642

607-
static int amd_get_min_freq(struct amd_cpudata *cpudata)
608-
{
609-
struct cppc_perf_caps cppc_perf;
610-
611-
int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
612-
if (ret)
613-
return ret;
614-
615-
/* Switch to khz */
616-
return cppc_perf.lowest_freq * 1000;
617-
}
618-
619-
static int amd_get_max_freq(struct amd_cpudata *cpudata)
620-
{
621-
struct cppc_perf_caps cppc_perf;
622-
u32 max_perf, max_freq, nominal_freq, nominal_perf;
623-
u64 boost_ratio;
624-
625-
int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
626-
if (ret)
627-
return ret;
628-
629-
nominal_freq = cppc_perf.nominal_freq;
630-
nominal_perf = READ_ONCE(cpudata->nominal_perf);
631-
max_perf = READ_ONCE(cpudata->highest_perf);
632-
633-
boost_ratio = div_u64(max_perf << SCHED_CAPACITY_SHIFT,
634-
nominal_perf);
635-
636-
max_freq = nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT;
637-
638-
/* Switch to khz */
639-
return max_freq * 1000;
640-
}
641-
642-
static int amd_get_nominal_freq(struct amd_cpudata *cpudata)
643-
{
644-
struct cppc_perf_caps cppc_perf;
645-
646-
int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
647-
if (ret)
648-
return ret;
649-
650-
/* Switch to khz */
651-
return cppc_perf.nominal_freq * 1000;
652-
}
653-
654-
static int amd_get_lowest_nonlinear_freq(struct amd_cpudata *cpudata)
655-
{
656-
struct cppc_perf_caps cppc_perf;
657-
u32 lowest_nonlinear_freq, lowest_nonlinear_perf,
658-
nominal_freq, nominal_perf;
659-
u64 lowest_nonlinear_ratio;
660-
661-
int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
662-
if (ret)
663-
return ret;
664-
665-
nominal_freq = cppc_perf.nominal_freq;
666-
nominal_perf = READ_ONCE(cpudata->nominal_perf);
667-
668-
lowest_nonlinear_perf = cppc_perf.lowest_nonlinear_perf;
669-
670-
lowest_nonlinear_ratio = div_u64(lowest_nonlinear_perf << SCHED_CAPACITY_SHIFT,
671-
nominal_perf);
672-
673-
lowest_nonlinear_freq = nominal_freq * lowest_nonlinear_ratio >> SCHED_CAPACITY_SHIFT;
674-
675-
/* Switch to khz */
676-
return lowest_nonlinear_freq * 1000;
677-
}
678-
679643
static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
680644
{
681645
struct amd_cpudata *cpudata = policy->driver_data;
@@ -828,9 +792,93 @@ static void amd_pstate_update_limits(unsigned int cpu)
828792
mutex_unlock(&amd_pstate_driver_lock);
829793
}
830794

795+
/*
796+
* Get pstate transition delay time from ACPI tables that firmware set
797+
* instead of using hardcode value directly.
798+
*/
799+
static u32 amd_pstate_get_transition_delay_us(unsigned int cpu)
800+
{
801+
u32 transition_delay_ns;
802+
803+
transition_delay_ns = cppc_get_transition_latency(cpu);
804+
if (transition_delay_ns == CPUFREQ_ETERNAL)
805+
return AMD_PSTATE_TRANSITION_DELAY;
806+
807+
return transition_delay_ns / NSEC_PER_USEC;
808+
}
809+
810+
/*
811+
* Get pstate transition latency value from ACPI tables that firmware
812+
* set instead of using hardcode value directly.
813+
*/
814+
static u32 amd_pstate_get_transition_latency(unsigned int cpu)
815+
{
816+
u32 transition_latency;
817+
818+
transition_latency = cppc_get_transition_latency(cpu);
819+
if (transition_latency == CPUFREQ_ETERNAL)
820+
return AMD_PSTATE_TRANSITION_LATENCY;
821+
822+
return transition_latency;
823+
}
824+
825+
/*
826+
* amd_pstate_init_freq: Initialize the max_freq, min_freq,
827+
* nominal_freq and lowest_nonlinear_freq for
828+
* the @cpudata object.
829+
*
830+
* Requires: highest_perf, lowest_perf, nominal_perf and
831+
* lowest_nonlinear_perf members of @cpudata to be
832+
* initialized.
833+
*
834+
* Returns 0 on success, non-zero value on failure.
835+
*/
836+
static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
837+
{
838+
int ret;
839+
u32 min_freq;
840+
u32 highest_perf, max_freq;
841+
u32 nominal_perf, nominal_freq;
842+
u32 lowest_nonlinear_perf, lowest_nonlinear_freq;
843+
u32 boost_ratio, lowest_nonlinear_ratio;
844+
struct cppc_perf_caps cppc_perf;
845+
846+
ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
847+
if (ret)
848+
return ret;
849+
850+
if (quirks && quirks->lowest_freq)
851+
min_freq = quirks->lowest_freq * 1000;
852+
else
853+
min_freq = cppc_perf.lowest_freq * 1000;
854+
855+
if (quirks && quirks->nominal_freq)
856+
nominal_freq = quirks->nominal_freq ;
857+
else
858+
nominal_freq = cppc_perf.nominal_freq;
859+
860+
nominal_perf = READ_ONCE(cpudata->nominal_perf);
861+
862+
highest_perf = READ_ONCE(cpudata->highest_perf);
863+
boost_ratio = div_u64(highest_perf << SCHED_CAPACITY_SHIFT, nominal_perf);
864+
max_freq = (nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT) * 1000;
865+
866+
lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
867+
lowest_nonlinear_ratio = div_u64(lowest_nonlinear_perf << SCHED_CAPACITY_SHIFT,
868+
nominal_perf);
869+
lowest_nonlinear_freq = (nominal_freq * lowest_nonlinear_ratio >> SCHED_CAPACITY_SHIFT) * 1000;
870+
871+
WRITE_ONCE(cpudata->min_freq, min_freq);
872+
WRITE_ONCE(cpudata->lowest_nonlinear_freq, lowest_nonlinear_freq);
873+
WRITE_ONCE(cpudata->nominal_freq, nominal_freq);
874+
WRITE_ONCE(cpudata->max_freq, max_freq);
875+
876+
return 0;
877+
}
878+
831879
static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
832880
{
833-
int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
881+
int min_freq, max_freq, nominal_freq, ret;
834882
struct device *dev;
835883
struct amd_cpudata *cpudata;
836884

@@ -855,20 +903,25 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
855903
if (ret)
856904
goto free_cpudata1;
857905

858-
min_freq = amd_get_min_freq(cpudata);
859-
max_freq = amd_get_max_freq(cpudata);
860-
nominal_freq = amd_get_nominal_freq(cpudata);
861-
lowest_nonlinear_freq = amd_get_lowest_nonlinear_freq(cpudata);
906+
ret = amd_pstate_init_freq(cpudata);
907+
if (ret)
908+
goto free_cpudata1;
862909

863-
if (min_freq < 0 || max_freq < 0 || min_freq > max_freq) {
864-
dev_err(dev, "min_freq(%d) or max_freq(%d) value is incorrect\n",
865-
min_freq, max_freq);
910+
min_freq = READ_ONCE(cpudata->min_freq);
911+
max_freq = READ_ONCE(cpudata->max_freq);
912+
nominal_freq = READ_ONCE(cpudata->nominal_freq);
913+
914+
if (min_freq <= 0 || max_freq <= 0 ||
915+
nominal_freq <= 0 || min_freq > max_freq) {
916+
dev_err(dev,
917+
"min_freq(%d) or max_freq(%d) or nominal_freq (%d) value is incorrect, check _CPC in ACPI tables\n",
918+
min_freq, max_freq, nominal_freq);
866919
ret = -EINVAL;
867920
goto free_cpudata1;
868921
}
869922

870-
policy->cpuinfo.transition_latency = AMD_PSTATE_TRANSITION_LATENCY;
871-
policy->transition_delay_us = AMD_PSTATE_TRANSITION_DELAY;
923+
policy->cpuinfo.transition_latency = amd_pstate_get_transition_latency(policy->cpu);
924+
policy->transition_delay_us = amd_pstate_get_transition_delay_us(policy->cpu);
872925

873926
policy->min = min_freq;
874927
policy->max = max_freq;
@@ -896,13 +949,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
896949
goto free_cpudata2;
897950
}
898951

899-
/* Initial processor data capability frequencies */
900-
cpudata->max_freq = max_freq;
901-
cpudata->min_freq = min_freq;
902952
cpudata->max_limit_freq = max_freq;
903953
cpudata->min_limit_freq = min_freq;
904-
cpudata->nominal_freq = nominal_freq;
905-
cpudata->lowest_nonlinear_freq = lowest_nonlinear_freq;
906954

907955
policy->driver_data = cpudata;
908956

@@ -966,7 +1014,7 @@ static ssize_t show_amd_pstate_max_freq(struct cpufreq_policy *policy,
9661014
int max_freq;
9671015
struct amd_cpudata *cpudata = policy->driver_data;
9681016

969-
max_freq = amd_get_max_freq(cpudata);
1017+
max_freq = READ_ONCE(cpudata->max_freq);
9701018
if (max_freq < 0)
9711019
return max_freq;
9721020

@@ -979,7 +1027,7 @@ static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *poli
9791027
int freq;
9801028
struct amd_cpudata *cpudata = policy->driver_data;
9811029

982-
freq = amd_get_lowest_nonlinear_freq(cpudata);
1030+
freq = READ_ONCE(cpudata->lowest_nonlinear_freq);
9831031
if (freq < 0)
9841032
return freq;
9851033

@@ -1290,7 +1338,7 @@ static bool amd_pstate_acpi_pm_profile_undefined(void)
12901338

12911339
static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
12921340
{
1293-
int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
1341+
int min_freq, max_freq, nominal_freq, ret;
12941342
struct amd_cpudata *cpudata;
12951343
struct device *dev;
12961344
u64 value;
@@ -1317,13 +1365,18 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
13171365
if (ret)
13181366
goto free_cpudata1;
13191367

1320-
min_freq = amd_get_min_freq(cpudata);
1321-
max_freq = amd_get_max_freq(cpudata);
1322-
nominal_freq = amd_get_nominal_freq(cpudata);
1323-
lowest_nonlinear_freq = amd_get_lowest_nonlinear_freq(cpudata);
1324-
if (min_freq < 0 || max_freq < 0 || min_freq > max_freq) {
1325-
dev_err(dev, "min_freq(%d) or max_freq(%d) value is incorrect\n",
1326-
min_freq, max_freq);
1368+
ret = amd_pstate_init_freq(cpudata);
1369+
if (ret)
1370+
goto free_cpudata1;
1371+
1372+
min_freq = READ_ONCE(cpudata->min_freq);
1373+
max_freq = READ_ONCE(cpudata->max_freq);
1374+
nominal_freq = READ_ONCE(cpudata->nominal_freq);
1375+
if (min_freq <= 0 || max_freq <= 0 ||
1376+
nominal_freq <= 0 || min_freq > max_freq) {
1377+
dev_err(dev,
1378+
"min_freq(%d) or max_freq(%d) or nominal_freq(%d) value is incorrect, check _CPC in ACPI tables\n",
1379+
min_freq, max_freq, nominal_freq);
13271380
ret = -EINVAL;
13281381
goto free_cpudata1;
13291382
}
@@ -1333,12 +1386,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
13331386
/* It will be updated by governor */
13341387
policy->cur = policy->cpuinfo.min_freq;
13351388

1336-
/* Initial processor data capability frequencies */
1337-
cpudata->max_freq = max_freq;
1338-
cpudata->min_freq = min_freq;
1339-
cpudata->nominal_freq = nominal_freq;
1340-
cpudata->lowest_nonlinear_freq = lowest_nonlinear_freq;
1341-
13421389
policy->driver_data = cpudata;
13431390

13441391
cpudata->epp_cached = amd_pstate_get_epp(cpudata, 0);
@@ -1656,6 +1703,11 @@ static int __init amd_pstate_init(void)
16561703
if (cpufreq_get_current_driver())
16571704
return -EEXIST;
16581705

1706+
quirks = NULL;
1707+
1708+
/* check if this machine need CPPC quirks */
1709+
dmi_check_system(amd_pstate_quirks_table);
1710+
16591711
switch (cppc_state) {
16601712
case AMD_PSTATE_UNDEFINED:
16611713
/* Disable on the following configs by default:

0 commit comments

Comments
 (0)