Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit f53b4bb

Browse files
committed
Merge tag 'amd-pstate-v6.11-2024-06-26' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/superm1/linux
Merge more amd-pstate driver updates for 6.11 from Mario Limonciello: "Add support for amd-pstate core performance boost support which allows controlling which CPU cores can operate above nominal frequencies for short periods of time." * tag 'amd-pstate-v6.11-2024-06-26' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/superm1/linux: Documentation: cpufreq: amd-pstate: update doc for Per CPU boost control method cpufreq: amd-pstate: Cap the CPPC.max_perf to nominal_perf if CPB is off cpufreq: amd-pstate: initialize core precision boost state cpufreq: acpi: move MSR_K7_HWCR_CPB_DIS_BIT into msr-index.h
2 parents b11ec63 + 6d58889 commit f53b4bb

File tree

5 files changed

+119
-24
lines changed

5 files changed

+119
-24
lines changed

Documentation/admin-guide/pm/amd-pstate.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,22 @@ integer values defined between 0 to 255 when EPP feature is enabled by platform
281281
firmware, if EPP feature is disabled, driver will ignore the written value
282282
This attribute is read-write.
283283

284+
``boost``
285+
The `boost` sysfs attribute provides control over the CPU core
286+
performance boost, allowing users to manage the maximum frequency limitation
287+
of the CPU. This attribute can be used to enable or disable the boost feature
288+
on individual CPUs.
289+
290+
When the boost feature is enabled, the CPU can dynamically increase its frequency
291+
beyond the base frequency, providing enhanced performance for demanding workloads.
292+
On the other hand, disabling the boost feature restricts the CPU to operate at the
293+
base frequency, which may be desirable in certain scenarios to prioritize power
294+
efficiency or manage temperature.
295+
296+
To manipulate the `boost` attribute, users can write a value of `0` to disable the
297+
boost or `1` to enable it, for the respective CPU using the sysfs path
298+
`/sys/devices/system/cpu/cpuX/cpufreq/boost`, where `X` represents the CPU number.
299+
284300
Other performance and frequency values can be read back from
285301
``/sys/devices/system/cpu/cpuX/acpi_cppc/``, see :ref:`cppc_sysfs`.
286302

arch/x86/include/asm/msr-index.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,8 @@
781781
#define MSR_K7_HWCR_IRPERF_EN BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT)
782782
#define MSR_K7_FID_VID_CTL 0xc0010041
783783
#define MSR_K7_FID_VID_STATUS 0xc0010042
784+
#define MSR_K7_HWCR_CPB_DIS_BIT 25
785+
#define MSR_K7_HWCR_CPB_DIS BIT_ULL(MSR_K7_HWCR_CPB_DIS_BIT)
784786

785787
/* K6 MSRs */
786788
#define MSR_K6_WHCR 0xc0000082

drivers/cpufreq/acpi-cpufreq.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ enum {
5050
#define AMD_MSR_RANGE (0x7)
5151
#define HYGON_MSR_RANGE (0x7)
5252

53-
#define MSR_K7_HWCR_CPB_DIS (1ULL << 25)
54-
5553
struct acpi_cpufreq_data {
5654
unsigned int resume;
5755
unsigned int cpu_feature;

drivers/cpufreq/amd-pstate.c

Lines changed: 100 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,7 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
514514
unsigned long max_freq;
515515
struct cpufreq_policy *policy = cpufreq_cpu_get(cpudata->cpu);
516516
u64 prev = READ_ONCE(cpudata->cppc_req_cached);
517+
u32 nominal_perf = READ_ONCE(cpudata->nominal_perf);
517518
u64 value = prev;
518519

519520
min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf,
@@ -536,6 +537,10 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
536537
value &= ~AMD_CPPC_DES_PERF(~0L);
537538
value |= AMD_CPPC_DES_PERF(des_perf);
538539

540+
/* limit the max perf when core performance boost feature is disabled */
541+
if (!cpudata->boost_supported)
542+
max_perf = min_t(unsigned long, nominal_perf, max_perf);
543+
539544
value &= ~AMD_CPPC_MAX_PERF(~0L);
540545
value |= AMD_CPPC_MAX_PERF(max_perf);
541546

@@ -679,43 +684,105 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
679684
cpufreq_cpu_put(policy);
680685
}
681686

682-
static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
687+
static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on)
683688
{
684689
struct amd_cpudata *cpudata = policy->driver_data;
690+
struct cppc_perf_ctrls perf_ctrls;
691+
u32 highest_perf, nominal_perf, nominal_freq, max_freq;
685692
int ret;
686693

687-
if (!cpudata->boost_supported) {
688-
pr_err("Boost mode is not supported by this processor or SBIOS\n");
689-
return -EINVAL;
694+
highest_perf = READ_ONCE(cpudata->highest_perf);
695+
nominal_perf = READ_ONCE(cpudata->nominal_perf);
696+
nominal_freq = READ_ONCE(cpudata->nominal_freq);
697+
max_freq = READ_ONCE(cpudata->max_freq);
698+
699+
if (boot_cpu_has(X86_FEATURE_CPPC)) {
700+
u64 value = READ_ONCE(cpudata->cppc_req_cached);
701+
702+
value &= ~GENMASK_ULL(7, 0);
703+
value |= on ? highest_perf : nominal_perf;
704+
WRITE_ONCE(cpudata->cppc_req_cached, value);
705+
706+
wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
707+
} else {
708+
perf_ctrls.max_perf = on ? highest_perf : nominal_perf;
709+
ret = cppc_set_perf(cpudata->cpu, &perf_ctrls);
710+
if (ret) {
711+
cpufreq_cpu_release(policy);
712+
pr_debug("Failed to set max perf on CPU:%d. ret:%d\n",
713+
cpudata->cpu, ret);
714+
return ret;
715+
}
690716
}
691717

692-
if (state)
693-
policy->cpuinfo.max_freq = cpudata->max_freq;
694-
else
695-
policy->cpuinfo.max_freq = cpudata->nominal_freq * 1000;
718+
if (on)
719+
policy->cpuinfo.max_freq = max_freq;
720+
else if (policy->cpuinfo.max_freq > nominal_freq * 1000)
721+
policy->cpuinfo.max_freq = nominal_freq * 1000;
696722

697723
policy->max = policy->cpuinfo.max_freq;
698724

699-
ret = freq_qos_update_request(&cpudata->req[1],
700-
policy->cpuinfo.max_freq);
701-
if (ret < 0)
702-
return ret;
725+
if (cppc_state == AMD_PSTATE_PASSIVE) {
726+
ret = freq_qos_update_request(&cpudata->req[1], policy->cpuinfo.max_freq);
727+
if (ret < 0)
728+
pr_debug("Failed to update freq constraint: CPU%d\n", cpudata->cpu);
729+
}
703730

704-
return 0;
731+
return ret < 0 ? ret : 0;
705732
}
706733

707-
static void amd_pstate_boost_init(struct amd_cpudata *cpudata)
734+
static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
708735
{
709-
u32 highest_perf, nominal_perf;
736+
struct amd_cpudata *cpudata = policy->driver_data;
737+
int ret;
710738

711-
highest_perf = READ_ONCE(cpudata->highest_perf);
712-
nominal_perf = READ_ONCE(cpudata->nominal_perf);
739+
if (!cpudata->boost_supported) {
740+
pr_err("Boost mode is not supported by this processor or SBIOS\n");
741+
return -EOPNOTSUPP;
742+
}
743+
mutex_lock(&amd_pstate_driver_lock);
744+
ret = amd_pstate_cpu_boost_update(policy, state);
745+
WRITE_ONCE(cpudata->boost_state, !ret ? state : false);
746+
policy->boost_enabled = !ret ? state : false;
747+
refresh_frequency_limits(policy);
748+
mutex_unlock(&amd_pstate_driver_lock);
713749

714-
if (highest_perf <= nominal_perf)
715-
return;
750+
return ret;
751+
}
716752

717-
cpudata->boost_supported = true;
753+
static int amd_pstate_init_boost_support(struct amd_cpudata *cpudata)
754+
{
755+
u64 boost_val;
756+
int ret = -1;
757+
758+
/*
759+
* If platform has no CPB support or disable it, initialize current driver
760+
* boost_enabled state to be false, it is not an error for cpufreq core to handle.
761+
*/
762+
if (!cpu_feature_enabled(X86_FEATURE_CPB)) {
763+
pr_debug_once("Boost CPB capabilities not present in the processor\n");
764+
ret = 0;
765+
goto exit_err;
766+
}
767+
768+
/* at least one CPU supports CPB, even if others fail later on to set up */
718769
current_pstate_driver->boost_enabled = true;
770+
771+
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_K7_HWCR, &boost_val);
772+
if (ret) {
773+
pr_err_once("failed to read initial CPU boost state!\n");
774+
ret = -EIO;
775+
goto exit_err;
776+
}
777+
778+
if (!(boost_val & MSR_K7_HWCR_CPB_DIS))
779+
cpudata->boost_supported = true;
780+
781+
return 0;
782+
783+
exit_err:
784+
cpudata->boost_supported = false;
785+
return ret;
719786
}
720787

721788
static void amd_perf_ctl_reset(unsigned int cpu)
@@ -968,6 +1035,10 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
9681035
if (ret)
9691036
goto free_cpudata1;
9701037

1038+
ret = amd_pstate_init_boost_support(cpudata);
1039+
if (ret)
1040+
goto free_cpudata1;
1041+
9711042
min_freq = READ_ONCE(cpudata->min_freq);
9721043
max_freq = READ_ONCE(cpudata->max_freq);
9731044

@@ -980,6 +1051,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
9801051
policy->cpuinfo.min_freq = min_freq;
9811052
policy->cpuinfo.max_freq = max_freq;
9821053

1054+
policy->boost_enabled = READ_ONCE(cpudata->boost_supported);
1055+
9831056
/* It will be updated by governor */
9841057
policy->cur = policy->cpuinfo.min_freq;
9851058

@@ -1005,7 +1078,6 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
10051078

10061079
policy->driver_data = cpudata;
10071080

1008-
amd_pstate_boost_init(cpudata);
10091081
if (!current_pstate_driver->adjust_perf)
10101082
current_pstate_driver->adjust_perf = amd_pstate_adjust_perf;
10111083

@@ -1420,6 +1492,10 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14201492
if (ret)
14211493
goto free_cpudata1;
14221494

1495+
ret = amd_pstate_init_boost_support(cpudata);
1496+
if (ret)
1497+
goto free_cpudata1;
1498+
14231499
min_freq = READ_ONCE(cpudata->min_freq);
14241500
max_freq = READ_ONCE(cpudata->max_freq);
14251501

@@ -1435,6 +1511,8 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14351511
policy->min = policy->cpuinfo.min_freq;
14361512
policy->max = policy->cpuinfo.max_freq;
14371513

1514+
policy->boost_enabled = READ_ONCE(cpudata->boost_supported);
1515+
14381516
/*
14391517
* Set the policy to provide a valid fallback value in case
14401518
* the default cpufreq governor is neither powersave nor performance.
@@ -1456,7 +1534,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
14561534
return ret;
14571535
WRITE_ONCE(cpudata->cppc_cap1_cached, value);
14581536
}
1459-
amd_pstate_boost_init(cpudata);
14601537

14611538
return 0;
14621539

@@ -1718,6 +1795,7 @@ static struct cpufreq_driver amd_pstate_epp_driver = {
17181795
.suspend = amd_pstate_epp_suspend,
17191796
.resume = amd_pstate_epp_resume,
17201797
.update_limits = amd_pstate_update_limits,
1798+
.set_boost = amd_pstate_set_boost,
17211799
.name = "amd-pstate-epp",
17221800
.attr = amd_pstate_epp_attr,
17231801
};

drivers/cpufreq/amd-pstate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ struct amd_cpudata {
100100
u64 cppc_cap1_cached;
101101
bool suspended;
102102
s16 epp_default;
103+
bool boost_state;
103104
};
104105

105106
#endif /* _LINUX_AMD_PSTATE_H */

0 commit comments

Comments
 (0)