diff options
Diffstat (limited to 'SOURCES/0001-amd-pstate.patch')
-rw-r--r-- | SOURCES/0001-amd-pstate.patch | 561 |
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 |