Skip to content

Commit b59528c

Browse files
committed
Merge: cpufreq/amd-pstate: Updates to support for the "Requested CPU Min frequency" BIOS option
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1491 Description: updates for the "Requested CPU Min frequency" BIOS option JIRA: https://issues.redhat.com/browse/RHEL-106954 Build Info: 68963996 Tested: Successful platform test results on AMD (amd-turin-volcano-06) system. Signed-off-by: Steve Best <sbest@redhat.com> Approved-by: Lenny Szubowicz <lszubowi@redhat.com> Approved-by: David Arcari <darcari@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Scott Weaver <scweaver@redhat.com>
2 parents cc50bc1 + 7e86cf1 commit b59528c

File tree

2 files changed

+83
-23
lines changed

2 files changed

+83
-23
lines changed

drivers/cpufreq/amd-pstate.c

Lines changed: 81 additions & 23 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);
@@ -581,20 +598,26 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy_data)
581598
{
582599
/*
583600
* Initialize lower frequency limit (i.e.policy->min) with
584-
* lowest_nonlinear_frequency which is the most energy efficient
585-
* frequency. Override the initial value set by cpufreq core and
586-
* amd-pstate qos_requests.
601+
* lowest_nonlinear_frequency or the min frequency (if) specified in BIOS,
602+
* Override the initial value set by cpufreq core and amd-pstate qos_requests.
587603
*/
588604
if (policy_data->min == FREQ_QOS_MIN_DEFAULT_VALUE) {
589605
struct cpufreq_policy *policy __free(put_cpufreq_policy) =
590606
cpufreq_cpu_get(policy_data->cpu);
591607
struct amd_cpudata *cpudata;
608+
union perf_cached perf;
592609

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

596613
cpudata = policy->driver_data;
597-
policy_data->min = cpudata->lowest_nonlinear_freq;
614+
perf = READ_ONCE(cpudata->perf);
615+
616+
if (perf.bios_min_perf)
617+
policy_data->min = perf_to_freq(perf, cpudata->nominal_freq,
618+
perf.bios_min_perf);
619+
else
620+
policy_data->min = cpudata->lowest_nonlinear_freq;
598621
}
599622

600623
cpufreq_verify_within_cpu_limits(policy_data);
@@ -1027,6 +1050,10 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
10271050
static void amd_pstate_cpu_exit(struct cpufreq_policy *policy)
10281051
{
10291052
struct amd_cpudata *cpudata = policy->driver_data;
1053+
union perf_cached perf = READ_ONCE(cpudata->perf);
1054+
1055+
/* Reset CPPC_REQ MSR to the BIOS value */
1056+
amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
10301057

10311058
freq_qos_remove_request(&cpudata->req[1]);
10321059
freq_qos_remove_request(&cpudata->req[0]);
@@ -1422,7 +1449,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14221449
struct amd_cpudata *cpudata;
14231450
union perf_cached perf;
14241451
struct device *dev;
1425-
u64 value;
14261452
int ret;
14271453

14281454
/*
@@ -1487,12 +1513,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14871513
cpudata->epp_default = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
14881514
}
14891515

1490-
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
1491-
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
1492-
if (ret)
1493-
return ret;
1494-
WRITE_ONCE(cpudata->cppc_req_cached, value);
1495-
}
14961516
ret = amd_pstate_set_epp(policy, cpudata->epp_default);
14971517
if (ret)
14981518
return ret;
@@ -1512,6 +1532,11 @@ static void amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
15121532
struct amd_cpudata *cpudata = policy->driver_data;
15131533

15141534
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+
15151540
kfree(cpudata);
15161541
policy->driver_data = NULL;
15171542
}
@@ -1562,31 +1587,60 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
15621587
return 0;
15631588
}
15641589

1565-
static int amd_pstate_epp_cpu_online(struct cpufreq_policy *policy)
1590+
static int amd_pstate_cpu_online(struct cpufreq_policy *policy)
15661591
{
1567-
pr_debug("AMD CPU Core %d going online\n", policy->cpu);
1568-
15691592
return amd_pstate_cppc_enable(policy);
15701593
}
15711594

1572-
static int amd_pstate_epp_cpu_offline(struct cpufreq_policy *policy)
1595+
static int amd_pstate_cpu_offline(struct cpufreq_policy *policy)
15731596
{
1574-
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);
15751606
}
15761607

1577-
static int amd_pstate_epp_suspend(struct cpufreq_policy *policy)
1608+
static int amd_pstate_suspend(struct cpufreq_policy *policy)
15781609
{
15791610
struct amd_cpudata *cpudata = policy->driver_data;
1611+
union perf_cached perf = READ_ONCE(cpudata->perf);
1612+
int ret;
15801613

1581-
/* invalidate to ensure it's rewritten during resume */
1582-
cpudata->cppc_req_cached = 0;
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,
1620+
FIELD_GET(AMD_CPPC_DES_PERF_MASK, cpudata->cppc_req_cached),
1621+
FIELD_GET(AMD_CPPC_MAX_PERF_MASK, cpudata->cppc_req_cached),
1622+
FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached),
1623+
false);
1624+
if (ret)
1625+
return ret;
15831626

15841627
/* set this flag to avoid setting core offline*/
15851628
cpudata->suspended = true;
15861629

15871630
return 0;
15881631
}
15891632

1633+
static int amd_pstate_resume(struct cpufreq_policy *policy)
1634+
{
1635+
struct amd_cpudata *cpudata = policy->driver_data;
1636+
union perf_cached perf = READ_ONCE(cpudata->perf);
1637+
int cur_perf = freq_to_perf(perf, cpudata->nominal_freq, policy->cur);
1638+
1639+
/* Set CPPC_REQ to last sane value until the governor updates it */
1640+
return amd_pstate_update_perf(policy, perf.min_limit_perf, cur_perf, perf.max_limit_perf,
1641+
0U, false);
1642+
}
1643+
15901644
static int amd_pstate_epp_resume(struct cpufreq_policy *policy)
15911645
{
15921646
struct amd_cpudata *cpudata = policy->driver_data;
@@ -1612,6 +1666,10 @@ static struct cpufreq_driver amd_pstate_driver = {
16121666
.fast_switch = amd_pstate_fast_switch,
16131667
.init = amd_pstate_cpu_init,
16141668
.exit = amd_pstate_cpu_exit,
1669+
.online = amd_pstate_cpu_online,
1670+
.offline = amd_pstate_cpu_offline,
1671+
.suspend = amd_pstate_suspend,
1672+
.resume = amd_pstate_resume,
16151673
.set_boost = amd_pstate_set_boost,
16161674
.update_limits = amd_pstate_update_limits,
16171675
.name = "amd-pstate",
@@ -1624,9 +1682,9 @@ static struct cpufreq_driver amd_pstate_epp_driver = {
16241682
.setpolicy = amd_pstate_epp_set_policy,
16251683
.init = amd_pstate_epp_cpu_init,
16261684
.exit = amd_pstate_epp_cpu_exit,
1627-
.offline = amd_pstate_epp_cpu_offline,
1628-
.online = amd_pstate_epp_cpu_online,
1629-
.suspend = amd_pstate_epp_suspend,
1685+
.offline = amd_pstate_cpu_offline,
1686+
.online = amd_pstate_cpu_online,
1687+
.suspend = amd_pstate_suspend,
16301688
.resume = amd_pstate_epp_resume,
16311689
.update_limits = amd_pstate_update_limits,
16321690
.set_boost = amd_pstate_set_boost,

drivers/cpufreq/amd-pstate.h

Lines changed: 2 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
};

0 commit comments

Comments
 (0)