Skip to content

Commit 41abd47

Browse files
committed
Merge tag 'amd-pstate-v6.16-2025-05-08' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/superm1/linux
Merge amd-pstate content for 6.16 (5/8/25) from Mario Limonciello: - Add support for a new feature on some BIOS that allows setting "lowest CPU minimum frequency". - Fix the amd-pstate-ut unit tests to restore system settings when done. * tag 'amd-pstate-v6.16-2025-05-08' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/superm1/linux: amd-pstate-ut: Reset amd-pstate driver mode after running selftests cpufreq/amd-pstate: Add support for the "Requested CPU Min frequency" BIOS option cpufreq/amd-pstate: Add offline, online and suspend callbacks for amd_pstate_driver cpufreq/amd-pstate: Move max_perf limiting in amd_pstate_update
2 parents f1a5049 + d26d164 commit 41abd47

File tree

3 files changed

+103
-32
lines changed

3 files changed

+103
-32
lines changed

drivers/cpufreq/amd-pstate-ut.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ static int amd_pstate_set_mode(enum amd_pstate_mode mode)
242242
static int amd_pstate_ut_check_driver(u32 index)
243243
{
244244
enum amd_pstate_mode mode1, mode2 = AMD_PSTATE_DISABLE;
245+
enum amd_pstate_mode orig_mode = amd_pstate_get_status();
246+
int ret;
245247

246248
for (mode1 = AMD_PSTATE_DISABLE; mode1 < AMD_PSTATE_MAX; mode1++) {
247249
int ret = amd_pstate_set_mode(mode1);
@@ -251,16 +253,19 @@ static int amd_pstate_ut_check_driver(u32 index)
251253
if (mode1 == mode2)
252254
continue;
253255
ret = amd_pstate_set_mode(mode2);
254-
if (ret) {
255-
pr_err("%s: failed to update status for %s->%s\n", __func__,
256-
amd_pstate_get_mode_string(mode1),
257-
amd_pstate_get_mode_string(mode2));
258-
return ret;
259-
}
256+
if (ret)
257+
goto out;
260258
}
261259
}
262260

263-
return 0;
261+
out:
262+
if (ret)
263+
pr_warn("%s: failed to update status for %s->%s: %d\n", __func__,
264+
amd_pstate_get_mode_string(mode1),
265+
amd_pstate_get_mode_string(mode2), ret);
266+
267+
amd_pstate_set_mode(orig_mode);
268+
return ret;
264269
}
265270

266271
static int __init amd_pstate_ut_init(void)

drivers/cpufreq/amd-pstate.c

Lines changed: 88 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,8 @@ static inline int amd_pstate_cppc_enable(struct cpufreq_policy *policy)
389389
static int msr_init_perf(struct amd_cpudata *cpudata)
390390
{
391391
union perf_cached perf = READ_ONCE(cpudata->perf);
392-
u64 cap1, numerator;
392+
u64 cap1, numerator, cppc_req;
393+
u8 min_perf;
393394

394395
int ret = rdmsrl_safe_on_cpu(cpudata->cpu, MSR_AMD_CPPC_CAP1,
395396
&cap1);
@@ -400,6 +401,22 @@ static int msr_init_perf(struct amd_cpudata *cpudata)
400401
if (ret)
401402
return ret;
402403

404+
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &cppc_req);
405+
if (ret)
406+
return ret;
407+
408+
WRITE_ONCE(cpudata->cppc_req_cached, cppc_req);
409+
min_perf = FIELD_GET(AMD_CPPC_MIN_PERF_MASK, cppc_req);
410+
411+
/*
412+
* Clear out the min_perf part to check if the rest of the MSR is 0, if yes, this is an
413+
* indication that the min_perf value is the one specified through the BIOS option
414+
*/
415+
cppc_req &= ~(AMD_CPPC_MIN_PERF_MASK);
416+
417+
if (!cppc_req)
418+
perf.bios_min_perf = min_perf;
419+
403420
perf.highest_perf = numerator;
404421
perf.max_limit_perf = numerator;
405422
perf.min_limit_perf = FIELD_GET(AMD_CPPC_LOWEST_PERF_MASK, cap1);
@@ -554,6 +571,10 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u8 min_perf,
554571
if (!policy)
555572
return;
556573

574+
/* limit the max perf when core performance boost feature is disabled */
575+
if (!cpudata->boost_supported)
576+
max_perf = min_t(u8, perf.nominal_perf, max_perf);
577+
557578
des_perf = clamp_t(u8, des_perf, min_perf, max_perf);
558579

559580
policy->cur = perf_to_freq(perf, cpudata->nominal_freq, des_perf);
@@ -563,10 +584,6 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u8 min_perf,
563584
des_perf = 0;
564585
}
565586

566-
/* limit the max perf when core performance boost feature is disabled */
567-
if (!cpudata->boost_supported)
568-
max_perf = min_t(u8, perf.nominal_perf, max_perf);
569-
570587
if (trace_amd_pstate_perf_enabled() && amd_pstate_sample(cpudata)) {
571588
trace_amd_pstate_perf(min_perf, des_perf, max_perf, cpudata->freq,
572589
cpudata->cur.mperf, cpudata->cur.aperf, cpudata->cur.tsc,
@@ -580,20 +597,26 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy_data)
580597
{
581598
/*
582599
* Initialize lower frequency limit (i.e.policy->min) with
583-
* lowest_nonlinear_frequency which is the most energy efficient
584-
* frequency. Override the initial value set by cpufreq core and
585-
* amd-pstate qos_requests.
600+
* lowest_nonlinear_frequency or the min frequency (if) specified in BIOS,
601+
* Override the initial value set by cpufreq core and amd-pstate qos_requests.
586602
*/
587603
if (policy_data->min == FREQ_QOS_MIN_DEFAULT_VALUE) {
588604
struct cpufreq_policy *policy __free(put_cpufreq_policy) =
589605
cpufreq_cpu_get(policy_data->cpu);
590606
struct amd_cpudata *cpudata;
607+
union perf_cached perf;
591608

592609
if (!policy)
593610
return -EINVAL;
594611

595612
cpudata = policy->driver_data;
596-
policy_data->min = cpudata->lowest_nonlinear_freq;
613+
perf = READ_ONCE(cpudata->perf);
614+
615+
if (perf.bios_min_perf)
616+
policy_data->min = perf_to_freq(perf, cpudata->nominal_freq,
617+
perf.bios_min_perf);
618+
else
619+
policy_data->min = cpudata->lowest_nonlinear_freq;
597620
}
598621

599622
cpufreq_verify_within_cpu_limits(policy_data);
@@ -1021,6 +1044,10 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
10211044
static void amd_pstate_cpu_exit(struct cpufreq_policy *policy)
10221045
{
10231046
struct amd_cpudata *cpudata = policy->driver_data;
1047+
union perf_cached perf = READ_ONCE(cpudata->perf);
1048+
1049+
/* Reset CPPC_REQ MSR to the BIOS value */
1050+
amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
10241051

10251052
freq_qos_remove_request(&cpudata->req[1]);
10261053
freq_qos_remove_request(&cpudata->req[0]);
@@ -1302,6 +1329,12 @@ static ssize_t amd_pstate_show_status(char *buf)
13021329
return sysfs_emit(buf, "%s\n", amd_pstate_mode_string[cppc_state]);
13031330
}
13041331

1332+
int amd_pstate_get_status(void)
1333+
{
1334+
return cppc_state;
1335+
}
1336+
EXPORT_SYMBOL_GPL(amd_pstate_get_status);
1337+
13051338
int amd_pstate_update_status(const char *buf, size_t size)
13061339
{
13071340
int mode_idx;
@@ -1416,7 +1449,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14161449
struct amd_cpudata *cpudata;
14171450
union perf_cached perf;
14181451
struct device *dev;
1419-
u64 value;
14201452
int ret;
14211453

14221454
/*
@@ -1481,12 +1513,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14811513
cpudata->epp_default = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
14821514
}
14831515

1484-
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
1485-
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
1486-
if (ret)
1487-
return ret;
1488-
WRITE_ONCE(cpudata->cppc_req_cached, value);
1489-
}
14901516
ret = amd_pstate_set_epp(policy, cpudata->epp_default);
14911517
if (ret)
14921518
return ret;
@@ -1506,6 +1532,11 @@ static void amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
15061532
struct amd_cpudata *cpudata = policy->driver_data;
15071533

15081534
if (cpudata) {
1535+
union perf_cached perf = READ_ONCE(cpudata->perf);
1536+
1537+
/* Reset CPPC_REQ MSR to the BIOS value */
1538+
amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
1539+
15091540
kfree(cpudata);
15101541
policy->driver_data = NULL;
15111542
}
@@ -1556,21 +1587,38 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
15561587
return 0;
15571588
}
15581589

1559-
static int amd_pstate_epp_cpu_online(struct cpufreq_policy *policy)
1590+
static int amd_pstate_cpu_online(struct cpufreq_policy *policy)
15601591
{
1561-
pr_debug("AMD CPU Core %d going online\n", policy->cpu);
1562-
15631592
return amd_pstate_cppc_enable(policy);
15641593
}
15651594

1566-
static int amd_pstate_epp_cpu_offline(struct cpufreq_policy *policy)
1595+
static int amd_pstate_cpu_offline(struct cpufreq_policy *policy)
15671596
{
1568-
return 0;
1597+
struct amd_cpudata *cpudata = policy->driver_data;
1598+
union perf_cached perf = READ_ONCE(cpudata->perf);
1599+
1600+
/*
1601+
* Reset CPPC_REQ MSR to the BIOS value, this will allow us to retain the BIOS specified
1602+
* min_perf value across kexec reboots. If this CPU is just onlined normally after this, the
1603+
* limits, epp and desired perf will get reset to the cached values in cpudata struct
1604+
*/
1605+
return amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
15691606
}
15701607

1571-
static int amd_pstate_epp_suspend(struct cpufreq_policy *policy)
1608+
static int amd_pstate_suspend(struct cpufreq_policy *policy)
15721609
{
15731610
struct amd_cpudata *cpudata = policy->driver_data;
1611+
union perf_cached perf = READ_ONCE(cpudata->perf);
1612+
int ret;
1613+
1614+
/*
1615+
* Reset CPPC_REQ MSR to the BIOS value, this will allow us to retain the BIOS specified
1616+
* min_perf value across kexec reboots. If this CPU is just resumed back without kexec,
1617+
* the limits, epp and desired perf will get reset to the cached values in cpudata struct
1618+
*/
1619+
ret = amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
1620+
if (ret)
1621+
return ret;
15741622

15751623
/* invalidate to ensure it's rewritten during resume */
15761624
cpudata->cppc_req_cached = 0;
@@ -1581,6 +1629,17 @@ static int amd_pstate_epp_suspend(struct cpufreq_policy *policy)
15811629
return 0;
15821630
}
15831631

1632+
static int amd_pstate_resume(struct cpufreq_policy *policy)
1633+
{
1634+
struct amd_cpudata *cpudata = policy->driver_data;
1635+
union perf_cached perf = READ_ONCE(cpudata->perf);
1636+
int cur_perf = freq_to_perf(perf, cpudata->nominal_freq, policy->cur);
1637+
1638+
/* Set CPPC_REQ to last sane value until the governor updates it */
1639+
return amd_pstate_update_perf(policy, perf.min_limit_perf, cur_perf, perf.max_limit_perf,
1640+
0U, false);
1641+
}
1642+
15841643
static int amd_pstate_epp_resume(struct cpufreq_policy *policy)
15851644
{
15861645
struct amd_cpudata *cpudata = policy->driver_data;
@@ -1606,6 +1665,10 @@ static struct cpufreq_driver amd_pstate_driver = {
16061665
.fast_switch = amd_pstate_fast_switch,
16071666
.init = amd_pstate_cpu_init,
16081667
.exit = amd_pstate_cpu_exit,
1668+
.online = amd_pstate_cpu_online,
1669+
.offline = amd_pstate_cpu_offline,
1670+
.suspend = amd_pstate_suspend,
1671+
.resume = amd_pstate_resume,
16091672
.set_boost = amd_pstate_set_boost,
16101673
.update_limits = amd_pstate_update_limits,
16111674
.name = "amd-pstate",
@@ -1618,9 +1681,9 @@ static struct cpufreq_driver amd_pstate_epp_driver = {
16181681
.setpolicy = amd_pstate_epp_set_policy,
16191682
.init = amd_pstate_epp_cpu_init,
16201683
.exit = amd_pstate_epp_cpu_exit,
1621-
.offline = amd_pstate_epp_cpu_offline,
1622-
.online = amd_pstate_epp_cpu_online,
1623-
.suspend = amd_pstate_epp_suspend,
1684+
.offline = amd_pstate_cpu_offline,
1685+
.online = amd_pstate_cpu_online,
1686+
.suspend = amd_pstate_suspend,
16241687
.resume = amd_pstate_epp_resume,
16251688
.update_limits = amd_pstate_update_limits,
16261689
.set_boost = amd_pstate_set_boost,

drivers/cpufreq/amd-pstate.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
* @lowest_perf: the absolute lowest performance level of the processor
3131
* @min_limit_perf: Cached value of the performance corresponding to policy->min
3232
* @max_limit_perf: Cached value of the performance corresponding to policy->max
33+
* @bios_min_perf: Cached perf value corresponding to the "Requested CPU Min Frequency" BIOS option
3334
*/
3435
union perf_cached {
3536
struct {
@@ -39,6 +40,7 @@ union perf_cached {
3940
u8 lowest_perf;
4041
u8 min_limit_perf;
4142
u8 max_limit_perf;
43+
u8 bios_min_perf;
4244
};
4345
u64 val;
4446
};
@@ -119,6 +121,7 @@ enum amd_pstate_mode {
119121
AMD_PSTATE_MAX,
120122
};
121123
const char *amd_pstate_get_mode_string(enum amd_pstate_mode mode);
124+
int amd_pstate_get_status(void);
122125
int amd_pstate_update_status(const char *buf, size_t size);
123126

124127
#endif /* _LINUX_AMD_PSTATE_H */

0 commit comments

Comments
 (0)