aboutsummaryrefslogtreecommitdiff
path: root/SOURCES/0001-amd-pstate.patch
diff options
context:
space:
mode:
Diffstat (limited to 'SOURCES/0001-amd-pstate.patch')
-rw-r--r--SOURCES/0001-amd-pstate.patch561
1 files changed, 182 insertions, 379 deletions
diff --git a/SOURCES/0001-amd-pstate.patch b/SOURCES/0001-amd-pstate.patch
index f654f25..72d5cc6 100644
--- a/SOURCES/0001-amd-pstate.patch
+++ b/SOURCES/0001-amd-pstate.patch
@@ -1,27 +1,26 @@
-From b36ccc153f8a2ee04f046a4e10220dbe308f37ef Mon Sep 17 00:00:00 2001
+From b2368823f6d79235b4e706263855373ff2fed1e5 Mon Sep 17 00:00:00 2001
From: Peter Jung <admin@ptr1337.dev>
-Date: Tue, 25 Jun 2024 13:29:13 +0200
+Date: Fri, 5 Jul 2024 10:31:29 +0200
Subject: [PATCH 02/10] amd-pstate
Signed-off-by: Peter Jung <admin@ptr1337.dev>
---
- Documentation/admin-guide/pm/amd-pstate.rst | 40 +-
+ Documentation/admin-guide/pm/amd-pstate.rst | 18 +-
arch/x86/include/asm/cpufeatures.h | 1 +
arch/x86/include/asm/msr-index.h | 2 +
arch/x86/kernel/cpu/scattered.c | 1 +
- drivers/cpufreq/acpi-cpufreq.c | 2 -
- drivers/cpufreq/amd-pstate-ut.c | 2 +-
- drivers/cpufreq/amd-pstate.c | 463 +++++++++++++++-----
- drivers/cpufreq/amd-pstate.h | 29 +-
- drivers/cpufreq/cpufreq.c | 25 +-
- include/linux/cpufreq.h | 2 +
- 10 files changed, 436 insertions(+), 131 deletions(-)
+ drivers/cpufreq/Kconfig.x86 | 1 +
+ drivers/cpufreq/acpi-cpufreq.c | 3 +-
+ drivers/cpufreq/amd-pstate.c | 356 ++++++++++++++------
+ drivers/cpufreq/amd-pstate.h | 16 +-
+ drivers/cpufreq/cpufreq.c | 14 +-
+ 9 files changed, 292 insertions(+), 120 deletions(-)
diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
-index 1e0d101b020a0..57995f54f0c88 100644
+index 1e0d101b020a..d0324d44f548 100644
--- a/Documentation/admin-guide/pm/amd-pstate.rst
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
-@@ -281,6 +281,27 @@ integer values defined between 0 to 255 when EPP feature is enabled by platform
+@@ -281,6 +281,22 @@ integer values defined between 0 to 255 when EPP feature is enabled by platform
firmware, if EPP feature is disabled, driver will ignore the written value
This attribute is read-write.
@@ -41,15 +40,10 @@ index 1e0d101b020a0..57995f54f0c88 100644
+boost or `1` to enable it, for the respective CPU using the sysfs path
+`/sys/devices/system/cpu/cpuX/cpufreq/boost`, where `X` represents the CPU number.
+
-+It is important to note that modifying the global variable
-+`/sys/devices/system/cpu/amd_pstate/cpb_boost` will override the individual CPU
-+settings.
-+
-+
Other performance and frequency values can be read back from
``/sys/devices/system/cpu/cpuX/acpi_cppc/``, see :ref:`cppc_sysfs`.
-@@ -406,7 +427,7 @@ control its functionality at the system level. They are located in the
+@@ -406,7 +422,7 @@ control its functionality at the system level. They are located in the
``/sys/devices/system/cpu/amd_pstate/`` directory and affect all CPUs.
``status``
@@ -58,32 +52,8 @@ index 1e0d101b020a0..57995f54f0c88 100644
"active"
The driver is functional and in the ``active mode``
-@@ -440,6 +461,23 @@ control its functionality at the system level. They are located in the
- This attribute is read-only to check the state of preferred core set
- by the kernel parameter.
-
-+``cpb_boost``
-+ Specifies whether core performance boost is requested to be enabled or disabled
-+ If core performance boost is disabled while a core is in a boosted P-state, the
-+ core automatically transitions to the highest performance non-boosted P-state.
-+ AMD Core Performance Boost(CPB) is controlled by this attribute file which allows
-+ user to change all cores frequency boosting state. It supports all amd-pstate modes.
-+
-+ States of the driver "/sys/devices/system/cpu/amd_pstate/cpb_boost"
-+ "disabled" Core Performance Boosting Disabled.
-+ "enabled" Core Performance Boosting Enabled.
-+
-+ To enable core performance boost:
-+ # echo "enabled" > /sys/devices/system/cpu/amd_pstate/cpb_boost
-+
-+ To disable core performance boost:
-+ # echo "disabled" > /sys/devices/system/cpu/amd_pstate/cpb_boost
-+
- ``cpupower`` tool support for ``amd-pstate``
- ===============================================
-
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
-index 3c7434329661c..6c128d463a143 100644
+index 3c7434329661..6c128d463a14 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -470,6 +470,7 @@
@@ -95,7 +65,7 @@ index 3c7434329661c..6c128d463a143 100644
/*
* BUG word(s)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
-index e72c2b8729579..8738a7b3917d8 100644
+index e72c2b872957..8738a7b3917d 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -782,6 +782,8 @@
@@ -108,7 +78,7 @@ index e72c2b8729579..8738a7b3917d8 100644
/* K6 MSRs */
#define MSR_K6_WHCR 0xc0000082
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
-index af5aa2c754c22..c84c30188fdf2 100644
+index af5aa2c754c2..c84c30188fdf 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -45,6 +45,7 @@ static const struct cpuid_bit cpuid_bits[] = {
@@ -119,8 +89,20 @@ index af5aa2c754c22..c84c30188fdf2 100644
{ X86_FEATURE_MBA, CPUID_EBX, 6, 0x80000008, 0 },
{ X86_FEATURE_SMBA, CPUID_EBX, 2, 0x80000020, 0 },
{ X86_FEATURE_BMEC, CPUID_EBX, 3, 0x80000020, 0 },
+diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
+index 438c9e75a04d..97c2d4f15d76 100644
+--- a/drivers/cpufreq/Kconfig.x86
++++ b/drivers/cpufreq/Kconfig.x86
+@@ -71,6 +71,7 @@ config X86_AMD_PSTATE_DEFAULT_MODE
+ config X86_AMD_PSTATE_UT
+ tristate "selftest for AMD Processor P-State driver"
+ depends on X86 && ACPI_PROCESSOR
++ depends on X86_AMD_PSTATE
+ default n
+ help
+ This kernel module is used for testing. It's safe to say M here.
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
-index 37f1cdf46d291..2fc82831bddd5 100644
+index 37f1cdf46d29..094f1f91a9b3 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -50,8 +50,6 @@ enum {
@@ -132,21 +114,16 @@ index 37f1cdf46d291..2fc82831bddd5 100644
struct acpi_cpufreq_data {
unsigned int resume;
unsigned int cpu_feature;
-diff --git a/drivers/cpufreq/amd-pstate-ut.c b/drivers/cpufreq/amd-pstate-ut.c
-index fc275d41d51e9..b528f198f4c36 100644
---- a/drivers/cpufreq/amd-pstate-ut.c
-+++ b/drivers/cpufreq/amd-pstate-ut.c
-@@ -227,7 +227,7 @@ static void amd_pstate_ut_check_freq(u32 index)
- goto skip_test;
- }
+@@ -139,6 +137,7 @@ static int set_boost(struct cpufreq_policy *policy, int val)
+ (void *)(long)val, 1);
+ pr_debug("CPU %*pbl: Core Boosting %s.\n",
+ cpumask_pr_args(policy->cpus), str_enabled_disabled(val));
++ policy->boost_enabled = val;
-- if (cpudata->boost_supported) {
-+ if (amd_pstate_global_params.cpb_boost) {
- if ((policy->max == cpudata->max_freq) ||
- (policy->max == cpudata->nominal_freq))
- amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS;
+ return 0;
+ }
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
-index 6af175e6c08ac..6eeba793bf442 100644
+index 6af175e6c08a..80eaa58f1405 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -51,6 +51,7 @@
@@ -173,36 +150,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
static struct cpufreq_driver *current_pstate_driver;
static struct cpufreq_driver amd_pstate_driver;
static struct cpufreq_driver amd_pstate_epp_driver;
-@@ -102,6 +94,11 @@ static bool cppc_enabled;
- static bool amd_pstate_prefcore = true;
- static struct quirk_entry *quirks;
-
-+/* export the amd_pstate_global_params for unit test */
-+struct amd_pstate_global_params amd_pstate_global_params;
-+EXPORT_SYMBOL_GPL(amd_pstate_global_params);
-+static int amd_pstate_cpu_boost(int cpu, bool state);
-+
- /*
- * AMD Energy Preference Performance (EPP)
- * The EPP is used in the CCLK DPM controller to drive
-@@ -143,6 +140,16 @@ static unsigned int epp_values[] = {
- [EPP_INDEX_POWERSAVE] = AMD_CPPC_EPP_POWERSAVE,
- };
-
-+enum CPB_STATE_INDEX {
-+ CPB_STATE_DISABLED = 0,
-+ CPB_STATE_ENABLED = 1,
-+};
-+
-+static const char * const cpb_state[] = {
-+ [CPB_STATE_DISABLED] = "disabled",
-+ [CPB_STATE_ENABLED] = "enabled",
-+};
-+
- typedef int (*cppc_mode_transition_fn)(int);
-
- static struct quirk_entry quirk_amd_7k62 = {
-@@ -157,7 +164,7 @@ static int __init dmi_matched_7k62_bios_bug(const struct dmi_system_id *dmi)
+@@ -157,7 +149,7 @@ static int __init dmi_matched_7k62_bios_bug(const struct dmi_system_id *dmi)
* broken BIOS lack of nominal_freq and lowest_freq capabilities
* definition in ACPI tables
*/
@@ -211,7 +159,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
quirks = dmi->driver_data;
pr_info("Overriding nominal and lowest frequencies for %s\n", dmi->ident);
return 1;
-@@ -199,7 +206,7 @@ static s16 amd_pstate_get_epp(struct amd_cpudata *cpudata, u64 cppc_req_cached)
+@@ -199,7 +191,7 @@ static s16 amd_pstate_get_epp(struct amd_cpudata *cpudata, u64 cppc_req_cached)
u64 epp;
int ret;
@@ -220,7 +168,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
if (!cppc_req_cached) {
epp = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ,
&cppc_req_cached);
-@@ -252,7 +259,7 @@ static int amd_pstate_set_epp(struct amd_cpudata *cpudata, u32 epp)
+@@ -252,7 +244,7 @@ static int amd_pstate_set_epp(struct amd_cpudata *cpudata, u32 epp)
int ret;
struct cppc_perf_ctrls perf_ctrls;
@@ -229,7 +177,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
u64 value = READ_ONCE(cpudata->cppc_req_cached);
value &= ~GENMASK_ULL(31, 24);
-@@ -281,10 +288,8 @@ static int amd_pstate_set_energy_pref_index(struct amd_cpudata *cpudata,
+@@ -281,10 +273,8 @@ static int amd_pstate_set_energy_pref_index(struct amd_cpudata *cpudata,
int epp = -EINVAL;
int ret;
@@ -242,7 +190,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
if (epp == -EINVAL)
epp = epp_values[pref_index];
-@@ -521,7 +526,10 @@ static inline bool amd_pstate_sample(struct amd_cpudata *cpudata)
+@@ -521,7 +511,10 @@ static inline bool amd_pstate_sample(struct amd_cpudata *cpudata)
static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
u32 des_perf, u32 max_perf, bool fast_switch, int gov_flags)
{
@@ -253,7 +201,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
u64 value = prev;
min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf,
-@@ -530,6 +538,9 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
+@@ -530,6 +523,9 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
cpudata->max_limit_perf);
des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
@@ -263,18 +211,18 @@ index 6af175e6c08ac..6eeba793bf442 100644
if ((cppc_state == AMD_PSTATE_GUIDED) && (gov_flags & CPUFREQ_GOV_DYNAMIC_SWITCHING)) {
min_perf = des_perf;
des_perf = 0;
-@@ -541,6 +552,10 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
+@@ -541,6 +537,10 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
value &= ~AMD_CPPC_DES_PERF(~0L);
value |= AMD_CPPC_DES_PERF(des_perf);
+ /* limit the max perf when core performance boost feature is disabled */
-+ if (!amd_pstate_global_params.cpb_boost)
++ if (!cpudata->boost_supported)
+ max_perf = min_t(unsigned long, nominal_perf, max_perf);
+
value &= ~AMD_CPPC_MAX_PERF(~0L);
value |= AMD_CPPC_MAX_PERF(max_perf);
-@@ -651,10 +666,9 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
+@@ -651,10 +651,9 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
unsigned long capacity)
{
unsigned long max_perf, min_perf, des_perf,
@@ -286,7 +234,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq)
amd_pstate_update_min_max_limit(policy);
-@@ -662,7 +676,6 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
+@@ -662,7 +661,6 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
cap_perf = READ_ONCE(cpudata->highest_perf);
lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
@@ -294,7 +242,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
des_perf = cap_perf;
if (target_perf < capacity)
-@@ -680,34 +693,12 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
+@@ -680,32 +678,57 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
max_perf = min_perf;
des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
@@ -307,66 +255,100 @@ index 6af175e6c08ac..6eeba793bf442 100644
}
-static int amd_get_min_freq(struct amd_cpudata *cpudata)
--{
++static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on)
+ {
- return READ_ONCE(cpudata->min_freq);
-}
--
++ struct amd_cpudata *cpudata = policy->driver_data;
++ struct cppc_perf_ctrls perf_ctrls;
++ u32 highest_perf, nominal_perf, nominal_freq, max_freq;
++ int ret;
+
-static int amd_get_max_freq(struct amd_cpudata *cpudata)
-{
- return READ_ONCE(cpudata->max_freq);
-}
--
++ highest_perf = READ_ONCE(cpudata->highest_perf);
++ nominal_perf = READ_ONCE(cpudata->nominal_perf);
++ nominal_freq = READ_ONCE(cpudata->nominal_freq);
++ max_freq = READ_ONCE(cpudata->max_freq);
+
-static int amd_get_nominal_freq(struct amd_cpudata *cpudata)
-{
- return READ_ONCE(cpudata->nominal_freq);
-}
--
++ if (boot_cpu_has(X86_FEATURE_CPPC)) {
++ u64 value = READ_ONCE(cpudata->cppc_req_cached);
+
-static int amd_get_lowest_nonlinear_freq(struct amd_cpudata *cpudata)
-{
- return READ_ONCE(cpudata->lowest_nonlinear_freq);
--}
--
++ value &= ~GENMASK_ULL(7, 0);
++ value |= on ? highest_perf : nominal_perf;
++ WRITE_ONCE(cpudata->cppc_req_cached, value);
++
++ wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
++ } else {
++ perf_ctrls.max_perf = on ? highest_perf : nominal_perf;
++ ret = cppc_set_perf(cpudata->cpu, &perf_ctrls);
++ if (ret) {
++ cpufreq_cpu_release(policy);
++ pr_debug("Failed to set max perf on CPU:%d. ret:%d\n",
++ cpudata->cpu, ret);
++ return ret;
++ }
++ }
++
++ if (on)
++ policy->cpuinfo.max_freq = max_freq;
++ else if (policy->cpuinfo.max_freq > nominal_freq * 1000)
++ policy->cpuinfo.max_freq = nominal_freq * 1000;
++
++ policy->max = policy->cpuinfo.max_freq;
++
++ if (cppc_state == AMD_PSTATE_PASSIVE) {
++ ret = freq_qos_update_request(&cpudata->req[1], policy->cpuinfo.max_freq);
++ if (ret < 0)
++ pr_debug("Failed to update freq constraint: CPU%d\n", cpudata->cpu);
++ }
++
++ return ret < 0 ? ret : 0;
+ }
+
static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
- {
- struct amd_cpudata *cpudata = policy->driver_data;
-@@ -715,36 +706,53 @@ static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
+@@ -715,36 +738,51 @@ static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state)
if (!cpudata->boost_supported) {
pr_err("Boost mode is not supported by this processor or SBIOS\n");
- return -EINVAL;
-+ return -ENOTSUPP;
++ return -EOPNOTSUPP;
}
+ mutex_lock(&amd_pstate_driver_lock);
-+ ret = amd_pstate_cpu_boost(policy->cpu, state);
++ ret = amd_pstate_cpu_boost_update(policy, state);
++ WRITE_ONCE(cpudata->boost_state, !ret ? state : false);
++ policy->boost_enabled = !ret ? state : false;
++ refresh_frequency_limits(policy);
+ mutex_unlock(&amd_pstate_driver_lock);
- if (state)
- policy->cpuinfo.max_freq = cpudata->max_freq;
- else
- policy->cpuinfo.max_freq = cpudata->nominal_freq * 1000;
--
-- policy->max = policy->cpuinfo.max_freq;
--
-- ret = freq_qos_update_request(&cpudata->req[1],
-- policy->cpuinfo.max_freq);
-- if (ret < 0)
-- return ret;
--
-- return 0;
-+ return ret < 0 ? ret : 0;
- }
++ return ret;
++}
--static void amd_pstate_boost_init(struct amd_cpudata *cpudata)
+- policy->max = policy->cpuinfo.max_freq;
+static int amd_pstate_init_boost_support(struct amd_cpudata *cpudata)
- {
-- u32 highest_perf, nominal_perf;
++{
+ u64 boost_val;
+ int ret = -1;
-- highest_perf = READ_ONCE(cpudata->highest_perf);
-- nominal_perf = READ_ONCE(cpudata->nominal_perf);
+- ret = freq_qos_update_request(&cpudata->req[1],
+- policy->cpuinfo.max_freq);
+- if (ret < 0)
+- return ret;
+ /*
-+ * If platform has no CPB support or disble it, initialize current driver
++ * If platform has no CPB support or disable it, initialize current driver
+ * boost_enabled state to be false, it is not an error for cpufreq core to handle.
+ */
+ if (!cpu_feature_enabled(X86_FEATURE_CPB)) {
@@ -375,37 +357,39 @@ index 6af175e6c08ac..6eeba793bf442 100644
+ goto exit_err;
+ }
-- if (highest_perf <= nominal_perf)
-- return;
+- return 0;
+-}
++ /* at least one CPU supports CPB, even if others fail later on to set up */
++ current_pstate_driver->boost_enabled = true;
+
+-static void amd_pstate_boost_init(struct amd_cpudata *cpudata)
+-{
+- u32 highest_perf, nominal_perf;
+ ret = rdmsrl_on_cpu(cpudata->cpu, MSR_K7_HWCR, &boost_val);
+ if (ret) {
+ pr_err_once("failed to read initial CPU boost state!\n");
+ ret = -EIO;
+ goto exit_err;
+ }
-+
-+ amd_pstate_global_params.cpb_supported = !(boost_val & MSR_K7_HWCR_CPB_DIS);
-+ if (amd_pstate_global_params.cpb_supported) {
-+ current_pstate_driver->boost_enabled = true;
+
+- highest_perf = READ_ONCE(cpudata->highest_perf);
+- nominal_perf = READ_ONCE(cpudata->nominal_perf);
++ if (!(boost_val & MSR_K7_HWCR_CPB_DIS))
+ cpudata->boost_supported = true;
-+ cpudata->boost_state = true;
-+ }
+
+- if (highest_perf <= nominal_perf)
+- return;
++ return 0;
- cpudata->boost_supported = true;
- current_pstate_driver->boost_enabled = true;
-+ amd_pstate_global_params.cpb_boost = amd_pstate_global_params.cpb_supported;
-+ return 0;
-+
+exit_err:
+ cpudata->boost_supported = false;
-+ cpudata->boost_state = false;
-+ current_pstate_driver->boost_enabled = false;
-+ amd_pstate_global_params.cpb_boost = false;
+ return ret;
}
static void amd_perf_ctl_reset(unsigned int cpu)
-@@ -773,7 +781,7 @@ static int amd_pstate_get_highest_perf(int cpu, u32 *highest_perf)
+@@ -773,7 +811,7 @@ static int amd_pstate_get_highest_perf(int cpu, u32 *highest_perf)
{
int ret;
@@ -414,7 +398,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
u64 cap1;
ret = rdmsrl_safe_on_cpu(cpu, MSR_AMD_CPPC_CAP1, &cap1);
-@@ -860,7 +868,41 @@ static void amd_pstate_update_limits(unsigned int cpu)
+@@ -860,7 +898,41 @@ static void amd_pstate_update_limits(unsigned int cpu)
mutex_unlock(&amd_pstate_driver_lock);
}
@@ -457,7 +441,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
* amd_pstate_init_freq: Initialize the max_freq, min_freq,
* nominal_freq and lowest_nonlinear_freq for
* the @cpudata object.
-@@ -881,7 +923,6 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
+@@ -881,7 +953,6 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
u32 boost_ratio, lowest_nonlinear_ratio;
struct cppc_perf_caps cppc_perf;
@@ -465,7 +449,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
if (ret)
return ret;
-@@ -912,12 +953,30 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
+@@ -912,12 +983,30 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
WRITE_ONCE(cpudata->nominal_freq, nominal_freq);
WRITE_ONCE(cpudata->max_freq, max_freq);
@@ -497,7 +481,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
struct device *dev;
struct amd_cpudata *cpudata;
-@@ -946,20 +1005,11 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
+@@ -946,20 +1035,15 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
if (ret)
goto free_cpudata1;
@@ -510,19 +494,27 @@ index 6af175e6c08ac..6eeba793bf442 100644
- dev_err(dev, "min_freq(%d) or max_freq(%d) value is incorrect\n",
- min_freq, max_freq);
- ret = -EINVAL;
-- goto free_cpudata1;
++ ret = amd_pstate_init_boost_support(cpudata);
++ if (ret)
+ goto free_cpudata1;
- }
-+ min_freq = READ_ONCE(cpudata->min_freq);
-+ max_freq = READ_ONCE(cpudata->max_freq);
- policy->cpuinfo.transition_latency = AMD_PSTATE_TRANSITION_LATENCY;
- policy->transition_delay_us = AMD_PSTATE_TRANSITION_DELAY;
++ min_freq = READ_ONCE(cpudata->min_freq);
++ max_freq = READ_ONCE(cpudata->max_freq);
++
+ policy->cpuinfo.transition_latency = amd_pstate_get_transition_latency(policy->cpu);
+ policy->transition_delay_us = amd_pstate_get_transition_delay_us(policy->cpu);
policy->min = min_freq;
policy->max = max_freq;
-@@ -970,7 +1020,7 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
+@@ -967,10 +1051,12 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
+ policy->cpuinfo.min_freq = min_freq;
+ policy->cpuinfo.max_freq = max_freq;
+
++ policy->boost_enabled = READ_ONCE(cpudata->boost_supported);
++
/* It will be updated by governor */
policy->cur = policy->cpuinfo.min_freq;
@@ -531,7 +523,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
policy->fast_switch_possible = true;
ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0],
-@@ -992,7 +1042,6 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
+@@ -992,7 +1078,6 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
policy->driver_data = cpudata;
@@ -539,7 +531,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
if (!current_pstate_driver->adjust_perf)
current_pstate_driver->adjust_perf = amd_pstate_adjust_perf;
-@@ -1052,7 +1101,7 @@ static ssize_t show_amd_pstate_max_freq(struct cpufreq_policy *policy,
+@@ -1052,7 +1137,7 @@ static ssize_t show_amd_pstate_max_freq(struct cpufreq_policy *policy,
int max_freq;
struct amd_cpudata *cpudata = policy->driver_data;
@@ -548,7 +540,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
if (max_freq < 0)
return max_freq;
-@@ -1065,7 +1114,7 @@ static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *poli
+@@ -1065,7 +1150,7 @@ static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *poli
int freq;
struct amd_cpudata *cpudata = policy->driver_data;
@@ -557,7 +549,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
if (freq < 0)
return freq;
-@@ -1203,7 +1252,7 @@ static int amd_pstate_change_mode_without_dvr_change(int mode)
+@@ -1203,7 +1288,7 @@ static int amd_pstate_change_mode_without_dvr_change(int mode)
cppc_state = mode;
@@ -566,160 +558,8 @@ index 6af175e6c08ac..6eeba793bf442 100644
return 0;
for_each_present_cpu(cpu) {
-@@ -1312,6 +1361,118 @@ static ssize_t prefcore_show(struct device *dev,
- return sysfs_emit(buf, "%s\n", str_enabled_disabled(amd_pstate_prefcore));
- }
-
-+static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on)
-+{
-+ struct amd_cpudata *cpudata = policy->driver_data;
-+ struct cppc_perf_ctrls perf_ctrls;
-+ u32 highest_perf, nominal_perf, nominal_freq, max_freq;
-+ int ret;
-+
-+ highest_perf = READ_ONCE(cpudata->highest_perf);
-+ nominal_perf = READ_ONCE(cpudata->nominal_perf);
-+ nominal_freq = READ_ONCE(cpudata->nominal_freq);
-+ max_freq = READ_ONCE(cpudata->max_freq);
-+
-+ if (boot_cpu_has(X86_FEATURE_CPPC)) {
-+ u64 value = READ_ONCE(cpudata->cppc_req_cached);
-+
-+ value &= ~GENMASK_ULL(7, 0);
-+ value |= on ? highest_perf : nominal_perf;
-+ WRITE_ONCE(cpudata->cppc_req_cached, value);
-+
-+ wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
-+ } else {
-+ perf_ctrls.max_perf = on ? highest_perf : nominal_perf;
-+ ret = cppc_set_perf(cpudata->cpu, &perf_ctrls);
-+ if (ret) {
-+ cpufreq_cpu_release(policy);
-+ pr_debug("Failed to set max perf on CPU:%d. ret:%d\n",
-+ cpudata->cpu, ret);
-+ return ret;
-+ }
-+ }
-+
-+ if (on)
-+ policy->cpuinfo.max_freq = max_freq;
-+ else
-+ policy->cpuinfo.max_freq = nominal_freq * 1000;
-+
-+ policy->max = policy->cpuinfo.max_freq;
-+
-+ if (cppc_state == AMD_PSTATE_PASSIVE) {
-+ ret = freq_qos_update_request(&cpudata->req[1], policy->cpuinfo.max_freq);
-+ if (ret < 0)
-+ pr_debug("Failed to update freq constraint: CPU%d\n", cpudata->cpu);
-+ }
-+
-+ return ret < 0 ? ret : 0;
-+}
-+
-+static int amd_pstate_cpu_boost(int cpu, bool state)
-+{
-+ int ret;
-+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
-+ struct amd_cpudata *cpudata = policy->driver_data;
-+
-+ if (!policy) {
-+ pr_err("policy is NULL\n");
-+ ret = -ENODATA;
-+ goto err_exit;
-+ }
-+
-+ ret = amd_pstate_cpu_boost_update(policy, state);
-+ refresh_frequency_limits(policy);
-+ WRITE_ONCE(cpudata->boost_state, state);
-+ policy->boost_enabled = state;
-+
-+err_exit:
-+ cpufreq_cpu_put(policy);
-+ return ret < 0 ? ret : 0;
-+}
-+
-+static ssize_t cpb_boost_show(struct device *dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ bool cpb_idx;
-+
-+ cpb_idx = amd_pstate_global_params.cpb_boost;
-+
-+ return sysfs_emit(buf, "%s\n", cpb_state[cpb_idx]);
-+}
-+
-+static ssize_t cpb_boost_store(struct device *dev, struct device_attribute *b,
-+ const char *buf, size_t count)
-+{
-+ bool new_state;
-+ ssize_t ret;
-+ int cpu, cpb_idx;
-+
-+ if (!amd_pstate_global_params.cpb_supported) {
-+ pr_err("Boost mode is not supported by this processor or SBIOS\n");
-+ return -EINVAL;
-+ }
-+
-+ cpb_idx = sysfs_match_string(cpb_state, buf);
-+ if (cpb_idx < 0)
-+ return -EINVAL;
-+
-+ new_state = cpb_idx;
-+
-+ mutex_lock(&amd_pstate_driver_lock);
-+ for_each_present_cpu(cpu) {
-+ ret = amd_pstate_cpu_boost(cpu, new_state);
-+ if (ret < 0) {
-+ pr_warn("failed to update cpu boost for CPU%d (%zd)\n", cpu, ret);
-+ goto err_exit;
-+ }
-+ }
-+ amd_pstate_global_params.cpb_boost = !!new_state;
-+
-+err_exit:
-+ mutex_unlock(&amd_pstate_driver_lock);
-+ return ret < 0 ? ret : count;
-+}
-+
- cpufreq_freq_attr_ro(amd_pstate_max_freq);
- cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
-
-@@ -1322,6 +1483,7 @@ cpufreq_freq_attr_rw(energy_performance_preference);
- cpufreq_freq_attr_ro(energy_performance_available_preferences);
- static DEVICE_ATTR_RW(status);
- static DEVICE_ATTR_RO(prefcore);
-+static DEVICE_ATTR_RW(cpb_boost);
-
- static struct freq_attr *amd_pstate_attr[] = {
- &amd_pstate_max_freq,
-@@ -1346,6 +1508,7 @@ static struct freq_attr *amd_pstate_epp_attr[] = {
- static struct attribute *pstate_global_attributes[] = {
- &dev_attr_status.attr,
- &dev_attr_prefcore.attr,
-+ &dev_attr_cpb_boost.attr,
- NULL
- };
+@@ -1376,7 +1461,7 @@ static bool amd_pstate_acpi_pm_profile_undefined(void)
-@@ -1374,9 +1537,24 @@ static bool amd_pstate_acpi_pm_profile_undefined(void)
- return false;
- }
-
-+static int amd_pstate_init_boost(struct cpufreq_policy *policy)
-+{
-+ struct amd_cpudata *cpudata = policy->driver_data;
-+ int ret;
-+
-+ /* initialize cpu cores boot state */
-+ ret = amd_pstate_init_boost_support(cpudata);
-+ if (ret)
-+ return ret;
-+
-+ policy->boost_enabled = READ_ONCE(cpudata->boost_state);
-+
-+ return 0;
-+}
-+
static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
{
- int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
@@ -727,7 +567,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
struct amd_cpudata *cpudata;
struct device *dev;
u64 value;
-@@ -1407,16 +1585,8 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
+@@ -1407,16 +1492,12 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
if (ret)
goto free_cpudata1;
@@ -739,14 +579,17 @@ index 6af175e6c08ac..6eeba793bf442 100644
- dev_err(dev, "min_freq(%d) or max_freq(%d) value is incorrect\n",
- min_freq, max_freq);
- ret = -EINVAL;
-- goto free_cpudata1;
++ ret = amd_pstate_init_boost_support(cpudata);
++ if (ret)
+ goto free_cpudata1;
- }
++
+ min_freq = READ_ONCE(cpudata->min_freq);
+ max_freq = READ_ONCE(cpudata->max_freq);
policy->cpuinfo.min_freq = min_freq;
policy->cpuinfo.max_freq = max_freq;
-@@ -1425,7 +1595,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
+@@ -1425,11 +1506,13 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
policy->driver_data = cpudata;
@@ -755,7 +598,13 @@ index 6af175e6c08ac..6eeba793bf442 100644
policy->min = policy->cpuinfo.min_freq;
policy->max = policy->cpuinfo.max_freq;
-@@ -1440,7 +1610,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
+
++ policy->boost_enabled = READ_ONCE(cpudata->boost_supported);
++
+ /*
+ * Set the policy to provide a valid fallback value in case
+ * the default cpufreq governor is neither powersave nor performance.
+@@ -1440,7 +1523,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
else
policy->policy = CPUFREQ_POLICY_POWERSAVE;
@@ -764,7 +613,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
if (ret)
return ret;
-@@ -1451,7 +1621,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
+@@ -1451,7 +1534,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
return ret;
WRITE_ONCE(cpudata->cppc_cap1_cached, value);
}
@@ -772,7 +621,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
return 0;
-@@ -1530,7 +1699,7 @@ static void amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
+@@ -1530,7 +1612,7 @@ static void amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
epp = 0;
/* Set initial EPP value */
@@ -781,7 +630,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
value &= ~GENMASK_ULL(31, 24);
value |= (u64)epp << 24;
}
-@@ -1553,6 +1722,12 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
+@@ -1553,6 +1635,12 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
amd_pstate_epp_update_limit(policy);
@@ -794,7 +643,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
return 0;
}
-@@ -1569,7 +1744,7 @@ static void amd_pstate_epp_reenable(struct amd_cpudata *cpudata)
+@@ -1569,7 +1657,7 @@ static void amd_pstate_epp_reenable(struct amd_cpudata *cpudata)
value = READ_ONCE(cpudata->cppc_req_cached);
max_perf = READ_ONCE(cpudata->highest_perf);
@@ -803,7 +652,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
} else {
perf_ctrls.max_perf = max_perf;
-@@ -1603,7 +1778,7 @@ static void amd_pstate_epp_offline(struct cpufreq_policy *policy)
+@@ -1603,7 +1691,7 @@ static void amd_pstate_epp_offline(struct cpufreq_policy *policy)
value = READ_ONCE(cpudata->cppc_req_cached);
mutex_lock(&amd_pstate_limits_lock);
@@ -812,24 +661,15 @@ index 6af175e6c08ac..6eeba793bf442 100644
cpudata->epp_policy = CPUFREQ_POLICY_UNKNOWN;
/* Set max perf same as min perf */
-@@ -1690,6 +1865,7 @@ static struct cpufreq_driver amd_pstate_driver = {
- .exit = amd_pstate_cpu_exit,
- .suspend = amd_pstate_cpu_suspend,
- .resume = amd_pstate_cpu_resume,
-+ .init_boost = amd_pstate_init_boost,
- .set_boost = amd_pstate_set_boost,
- .update_limits = amd_pstate_update_limits,
- .name = "amd-pstate",
-@@ -1707,6 +1883,8 @@ static struct cpufreq_driver amd_pstate_epp_driver = {
+@@ -1707,6 +1795,7 @@ static struct cpufreq_driver amd_pstate_epp_driver = {
.suspend = amd_pstate_epp_suspend,
.resume = amd_pstate_epp_resume,
.update_limits = amd_pstate_update_limits,
-+ .init_boost = amd_pstate_init_boost,
+ .set_boost = amd_pstate_set_boost,
.name = "amd-pstate-epp",
.attr = amd_pstate_epp_attr,
};
-@@ -1730,6 +1908,46 @@ static int __init amd_pstate_set_driver(int mode_idx)
+@@ -1730,6 +1819,46 @@ static int __init amd_pstate_set_driver(int mode_idx)
return -EINVAL;
}
@@ -876,7 +716,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
static int __init amd_pstate_init(void)
{
struct device *dev_root;
-@@ -1738,6 +1956,11 @@ static int __init amd_pstate_init(void)
+@@ -1738,6 +1867,11 @@ static int __init amd_pstate_init(void)
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
return -ENODEV;
@@ -888,7 +728,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
if (!acpi_cpc_valid()) {
pr_warn_once("the _CPC object is not present in SBIOS or ACPI disabled\n");
return -ENODEV;
-@@ -1752,35 +1975,43 @@ static int __init amd_pstate_init(void)
+@@ -1752,35 +1886,43 @@ static int __init amd_pstate_init(void)
/* check if this machine need CPPC quirks */
dmi_check_system(amd_pstate_quirks_table);
@@ -942,7 +782,7 @@ index 6af175e6c08ac..6eeba793bf442 100644
pr_debug("AMD CPPC MSR based functionality is supported\n");
if (cppc_state != AMD_PSTATE_ACTIVE)
current_pstate_driver->adjust_perf = amd_pstate_adjust_perf;
-@@ -1794,13 +2025,15 @@ static int __init amd_pstate_init(void)
+@@ -1794,13 +1936,15 @@ static int __init amd_pstate_init(void)
/* enable amd pstate feature */
ret = amd_pstate_enable(true);
if (ret) {
@@ -953,24 +793,24 @@ index 6af175e6c08ac..6eeba793bf442 100644
ret = cpufreq_register_driver(current_pstate_driver);
- if (ret)
-+ if (ret) {
++ if (ret) {
pr_err("failed to register with return %d\n", ret);
-+ goto disable_driver;
-+ }
++ goto disable_driver;
++ }
dev_root = bus_get_dev_root(&cpu_subsys);
if (dev_root) {
-@@ -1816,6 +2049,8 @@ static int __init amd_pstate_init(void)
+@@ -1816,6 +1960,8 @@ static int __init amd_pstate_init(void)
global_attr_free:
cpufreq_unregister_driver(current_pstate_driver);
+disable_driver:
-+ amd_pstate_enable(false);
++ amd_pstate_enable(false);
return ret;
}
device_initcall(amd_pstate_init);
diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
-index bc341f35908d7..fb240a8702892 100644
+index bc341f35908d..cc8bb2bc325a 100644
--- a/drivers/cpufreq/amd-pstate.h
+++ b/drivers/cpufreq/amd-pstate.h
@@ -42,13 +42,17 @@ struct amd_aperf_mperf {
@@ -996,7 +836,7 @@ index bc341f35908d7..fb240a8702892 100644
* @boost_supported: check whether the Processor or SBIOS supports boost mode
* @hw_prefcore: check whether HW supports preferred core featue.
* Only when hw_prefcore and early prefcore param are true,
-@@ -95,6 +99,21 @@ struct amd_cpudata {
+@@ -95,6 +99,8 @@ struct amd_cpudata {
u32 policy;
u64 cppc_cap1_cached;
bool suspended;
@@ -1004,22 +844,9 @@ index bc341f35908d7..fb240a8702892 100644
+ bool boost_state;
};
-+/**
-+ * struct amd_pstate_global_params - Global parameters, mostly tunable via sysfs.
-+ * @cpb_boost: Whether or not to use boost CPU P-states.
-+ * @cpb_supported: Whether or not CPU boost P-states are available
-+ * based on the MSR_K7_HWCR bit[25] state
-+ */
-+struct amd_pstate_global_params {
-+ bool cpb_boost;
-+ bool cpb_supported;
-+};
-+
-+extern struct amd_pstate_global_params amd_pstate_global_params;
-+
#endif /* _LINUX_AMD_PSTATE_H */
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
-index fd9c3ed21f49c..35296d8f9cdfa 100644
+index fd9c3ed21f49..bbbeb8b90313 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -614,10 +614,9 @@ static ssize_t show_boost(struct kobject *kobj,
@@ -1049,40 +876,16 @@ index fd9c3ed21f49c..35296d8f9cdfa 100644
return -EINVAL;
if (!cpufreq_driver->boost_enabled)
-@@ -1430,8 +1429,18 @@ static int cpufreq_online(unsigned int cpu)
- goto out_free_policy;
+@@ -1431,7 +1430,8 @@ static int cpufreq_online(unsigned int cpu)
}
-- /* Let the per-policy boost flag mirror the cpufreq_driver boost during init */
+ /* Let the per-policy boost flag mirror the cpufreq_driver boost during init */
- policy->boost_enabled = cpufreq_boost_enabled() && policy_has_boost_freq(policy);
-+ /* init boost state to prepare set_boost callback for each CPU */
-+ if (cpufreq_driver->init_boost) {
-+ ret = cpufreq_driver->init_boost(policy);
-+ if (ret) {
-+ pr_debug("%s: %d: boost initialization failed\n", __func__,
-+ __LINE__);
-+ goto out_offline_policy;
-+ }
-+ } else {
-+ /* Let the per-policy boost flag mirror the cpufreq_driver boost during init */
-+ policy->boost_enabled = cpufreq_boost_enabled() && policy_has_boost_freq(policy);
-+ }
++ if (cpufreq_boost_enabled() && policy_has_boost_freq(policy))
++ policy->boost_enabled = true;
/*
* The initialization has succeeded and the policy is online.
-diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
-index 9956afb9acc23..3eb5ce712c587 100644
---- a/include/linux/cpufreq.h
-+++ b/include/linux/cpufreq.h
-@@ -399,6 +399,8 @@ struct cpufreq_driver {
- bool boost_enabled;
- int (*set_boost)(struct cpufreq_policy *policy, int state);
-
-+ /* initialize boost state to be consistent before calling set_boost */
-+ int (*init_boost)(struct cpufreq_policy *policy);
- /*
- * Set by drivers that want to register with the energy model after the
- * policy is properly initialized, but before the governor is started.
--
2.45.2