Skip to content

Commit 608a76b

Browse files
dhananjay-AMDsuperm1
authored andcommitted
cpufreq/amd-pstate: Add support for the "Requested CPU Min frequency" BIOS option
Initialize lower frequency limit to the "Requested CPU Min frequency" BIOS option (if it is set) value as part of the driver->init() callback. The BIOS specified value is passed by the PMFW as min_perf in CPPC_REQ MSR. To ensure that we don't mistake a stale min_perf value in CPPC_REQ value as the "Requested CPU Min frequency" during a kexec wakeup, reset the CPPC_REQ.min_perf value back to the BIOS specified one in the offline, exit and suspend callbacks. amd_pstate_target() and amd_pstate_epp_update_limit() which are invoked as part of the resume() and online() callbacks will take care of restoring the CPPC_REQ back to the correct values. Signed-off-by: Dhananjay Ugwekar <dhananjay.ugwekar@amd.com> Reviewed-by: Mario Limonciello <mario.limonciello@amd.com> Link: https://lore.kernel.org/r/20250428071623.4309-1-dhananjay.ugwekar@amd.com Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
1 parent 98b52c6 commit 608a76b

File tree

2 files changed

+71
-13
lines changed

2 files changed

+71
-13
lines changed

drivers/cpufreq/amd-pstate.c

Lines changed: 69 additions & 13 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);
@@ -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);
@@ -1024,6 +1047,10 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
10241047
static void amd_pstate_cpu_exit(struct cpufreq_policy *policy)
10251048
{
10261049
struct amd_cpudata *cpudata = policy->driver_data;
1050+
union perf_cached perf = READ_ONCE(cpudata->perf);
1051+
1052+
/* Reset CPPC_REQ MSR to the BIOS value */
1053+
amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
10271054

10281055
freq_qos_remove_request(&cpudata->req[1]);
10291056
freq_qos_remove_request(&cpudata->req[0]);
@@ -1419,7 +1446,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14191446
struct amd_cpudata *cpudata;
14201447
union perf_cached perf;
14211448
struct device *dev;
1422-
u64 value;
14231449
int ret;
14241450

14251451
/*
@@ -1484,12 +1510,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14841510
cpudata->epp_default = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
14851511
}
14861512

1487-
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
1488-
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
1489-
if (ret)
1490-
return ret;
1491-
WRITE_ONCE(cpudata->cppc_req_cached, value);
1492-
}
14931513
ret = amd_pstate_set_epp(policy, cpudata->epp_default);
14941514
if (ret)
14951515
return ret;
@@ -1509,6 +1529,11 @@ static void amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
15091529
struct amd_cpudata *cpudata = policy->driver_data;
15101530

15111531
if (cpudata) {
1532+
union perf_cached perf = READ_ONCE(cpudata->perf);
1533+
1534+
/* Reset CPPC_REQ MSR to the BIOS value */
1535+
amd_pstate_update_perf(policy, perf.bios_min_perf, 0U, 0U, 0U, false);
1536+
15121537
kfree(cpudata);
15131538
policy->driver_data = NULL;
15141539
}
@@ -1566,12 +1591,31 @@ static int amd_pstate_cpu_online(struct cpufreq_policy *policy)
15661591

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

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

15761620
/* invalidate to ensure it's rewritten during resume */
15771621
cpudata->cppc_req_cached = 0;
@@ -1582,6 +1626,17 @@ static int amd_pstate_suspend(struct cpufreq_policy *policy)
15821626
return 0;
15831627
}
15841628

1629+
static int amd_pstate_resume(struct cpufreq_policy *policy)
1630+
{
1631+
struct amd_cpudata *cpudata = policy->driver_data;
1632+
union perf_cached perf = READ_ONCE(cpudata->perf);
1633+
int cur_perf = freq_to_perf(perf, cpudata->nominal_freq, policy->cur);
1634+
1635+
/* Set CPPC_REQ to last sane value until the governor updates it */
1636+
return amd_pstate_update_perf(policy, perf.min_limit_perf, cur_perf, perf.max_limit_perf,
1637+
0U, false);
1638+
}
1639+
15851640
static int amd_pstate_epp_resume(struct cpufreq_policy *policy)
15861641
{
15871642
struct amd_cpudata *cpudata = policy->driver_data;
@@ -1610,6 +1665,7 @@ static struct cpufreq_driver amd_pstate_driver = {
16101665
.online = amd_pstate_cpu_online,
16111666
.offline = amd_pstate_cpu_offline,
16121667
.suspend = amd_pstate_suspend,
1668+
.resume = amd_pstate_resume,
16131669
.set_boost = amd_pstate_set_boost,
16141670
.update_limits = amd_pstate_update_limits,
16151671
.name = "amd-pstate",

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)