diff options
Diffstat (limited to 'SOURCES/0001-amd-pstate.patch')
-rw-r--r-- | SOURCES/0001-amd-pstate.patch | 734 |
1 files changed, 0 insertions, 734 deletions
diff --git a/SOURCES/0001-amd-pstate.patch b/SOURCES/0001-amd-pstate.patch deleted file mode 100644 index c865d00..0000000 --- a/SOURCES/0001-amd-pstate.patch +++ /dev/null @@ -1,734 +0,0 @@ -From 06c02d91fcfeb0fde264f03f0e364161b11a678d Mon Sep 17 00:00:00 2001 -From: Peter Jung <admin@ptr1337.dev> -Date: Sat, 3 Aug 2024 09:32:45 +0200 -Subject: [PATCH 01/12] amd-pstate - -Signed-off-by: Peter Jung <admin@ptr1337.dev> ---- - 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/Kconfig.x86 | 1 + - drivers/cpufreq/acpi-cpufreq.c | 3 +- - drivers/cpufreq/amd-pstate.c | 307 ++++++++++++++------ - drivers/cpufreq/amd-pstate.h | 2 + - drivers/cpufreq/cpufreq.c | 11 +- - 9 files changed, 251 insertions(+), 95 deletions(-) - -diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst -index 1e0d101b020a..d0324d44f548 100644 ---- a/Documentation/admin-guide/pm/amd-pstate.rst -+++ b/Documentation/admin-guide/pm/amd-pstate.rst -@@ -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. - -+``boost`` -+The `boost` sysfs attribute provides control over the CPU core -+performance boost, allowing users to manage the maximum frequency limitation -+of the CPU. This attribute can be used to enable or disable the boost feature -+on individual CPUs. -+ -+When the boost feature is enabled, the CPU can dynamically increase its frequency -+beyond the base frequency, providing enhanced performance for demanding workloads. -+On the other hand, disabling the boost feature restricts the CPU to operate at the -+base frequency, which may be desirable in certain scenarios to prioritize power -+efficiency or manage temperature. -+ -+To manipulate the `boost` attribute, users can write a value of `0` to disable the -+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. -+ - Other performance and frequency values can be read back from - ``/sys/devices/system/cpu/cpuX/acpi_cppc/``, see :ref:`cppc_sysfs`. - -@@ -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`` -- Operation mode of the driver: "active", "passive" or "disable". -+ Operation mode of the driver: "active", "passive", "guided" or "disable". - - "active" - The driver is functional and in the ``active mode`` -diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h -index 3c7434329661..6c128d463a14 100644 ---- a/arch/x86/include/asm/cpufeatures.h -+++ b/arch/x86/include/asm/cpufeatures.h -@@ -470,6 +470,7 @@ - #define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */ - #define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */ - #define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */ -+#define X86_FEATURE_FAST_CPPC (21*32 + 5) /* "" AMD Fast CPPC */ - - /* - * BUG word(s) -diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h -index e022e6eb766c..384739d592af 100644 ---- a/arch/x86/include/asm/msr-index.h -+++ b/arch/x86/include/asm/msr-index.h -@@ -781,6 +781,8 @@ - #define MSR_K7_HWCR_IRPERF_EN BIT_ULL(MSR_K7_HWCR_IRPERF_EN_BIT) - #define MSR_K7_FID_VID_CTL 0xc0010041 - #define MSR_K7_FID_VID_STATUS 0xc0010042 -+#define MSR_K7_HWCR_CPB_DIS_BIT 25 -+#define MSR_K7_HWCR_CPB_DIS BIT_ULL(MSR_K7_HWCR_CPB_DIS_BIT) - - /* K6 MSRs */ - #define MSR_K6_WHCR 0xc0000082 -diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c -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[] = { - { X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 }, - { X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 }, - { X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 }, -+ { X86_FEATURE_FAST_CPPC, CPUID_EDX, 15, 0x80000007, 0 }, - { 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 4ac3a35dcd98..f4f8587c4ea0 100644 ---- a/drivers/cpufreq/acpi-cpufreq.c -+++ b/drivers/cpufreq/acpi-cpufreq.c -@@ -50,8 +50,6 @@ enum { - #define AMD_MSR_RANGE (0x7) - #define HYGON_MSR_RANGE (0x7) - --#define MSR_K7_HWCR_CPB_DIS (1ULL << 25) -- - struct acpi_cpufreq_data { - unsigned int resume; - unsigned int cpu_feature; -@@ -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; - - return 0; - } -diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c -index a092b13ffbc2..804fab4ebb26 100644 ---- a/drivers/cpufreq/amd-pstate.c -+++ b/drivers/cpufreq/amd-pstate.c -@@ -51,6 +51,7 @@ - - #define AMD_PSTATE_TRANSITION_LATENCY 20000 - #define AMD_PSTATE_TRANSITION_DELAY 1000 -+#define AMD_PSTATE_FAST_CPPC_TRANSITION_DELAY 600 - #define CPPC_HIGHEST_PERF_PERFORMANCE 196 - #define CPPC_HIGHEST_PERF_DEFAULT 166 - -@@ -85,15 +86,6 @@ struct quirk_entry { - u32 lowest_freq; - }; - --/* -- * TODO: We need more time to fine tune processors with shared memory solution -- * with community together. -- * -- * There are some performance drops on the CPU benchmarks which reports from -- * Suse. We are co-working with them to fine tune the shared memory solution. So -- * we disable it by default to go acpi-cpufreq on these processors and add a -- * module parameter to be able to enable it manually for debugging. -- */ - static struct cpufreq_driver *current_pstate_driver; - static struct cpufreq_driver amd_pstate_driver; - static struct cpufreq_driver amd_pstate_epp_driver; -@@ -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 - */ -- if (boot_cpu_has(X86_FEATURE_ZEN2)) { -+ if (cpu_feature_enabled(X86_FEATURE_ZEN2)) { - quirks = dmi->driver_data; - pr_info("Overriding nominal and lowest frequencies for %s\n", dmi->ident); - return 1; -@@ -199,7 +191,7 @@ static s16 amd_pstate_get_epp(struct amd_cpudata *cpudata, u64 cppc_req_cached) - u64 epp; - int ret; - -- if (boot_cpu_has(X86_FEATURE_CPPC)) { -+ if (cpu_feature_enabled(X86_FEATURE_CPPC)) { - if (!cppc_req_cached) { - epp = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, - &cppc_req_cached); -@@ -272,7 +264,7 @@ static int amd_pstate_set_epp(struct amd_cpudata *cpudata, u32 epp) - int ret; - struct cppc_perf_ctrls perf_ctrls; - -- if (boot_cpu_has(X86_FEATURE_CPPC)) { -+ if (cpu_feature_enabled(X86_FEATURE_CPPC)) { - u64 value = READ_ONCE(cpudata->cppc_req_cached); - - value &= ~GENMASK_ULL(31, 24); -@@ -524,7 +514,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) - { -+ unsigned long max_freq; -+ struct cpufreq_policy *policy = cpufreq_cpu_get(cpudata->cpu); - u64 prev = READ_ONCE(cpudata->cppc_req_cached); -+ u32 nominal_perf = READ_ONCE(cpudata->nominal_perf); - u64 value = prev; - - min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf, -@@ -533,6 +526,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); - -+ max_freq = READ_ONCE(cpudata->max_limit_freq); -+ policy->cur = div_u64(des_perf * max_freq, max_perf); -+ - if ((cppc_state == AMD_PSTATE_GUIDED) && (gov_flags & CPUFREQ_GOV_DYNAMIC_SWITCHING)) { - min_perf = des_perf; - des_perf = 0; -@@ -544,6 +540,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 (!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); - -@@ -654,10 +654,9 @@ static void amd_pstate_adjust_perf(unsigned int cpu, - unsigned long capacity) - { - unsigned long max_perf, min_perf, des_perf, -- cap_perf, lowest_nonlinear_perf, max_freq; -+ cap_perf, lowest_nonlinear_perf; - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); - struct amd_cpudata *cpudata = policy->driver_data; -- unsigned int target_freq; - - if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq) - amd_pstate_update_min_max_limit(policy); -@@ -665,7 +664,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); -- max_freq = READ_ONCE(cpudata->max_freq); - - des_perf = cap_perf; - if (target_perf < capacity) -@@ -683,51 +681,111 @@ 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); -- target_freq = div_u64(des_perf * max_freq, max_perf); -- policy->cur = target_freq; - - amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true, - policy->governor->flags); - cpufreq_cpu_put(policy); - } - --static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state) -+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; - -- if (!cpudata->boost_supported) { -- pr_err("Boost mode is not supported by this processor or SBIOS\n"); -- return -EINVAL; -+ 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 (state) -- policy->cpuinfo.max_freq = cpudata->max_freq; -- else -- policy->cpuinfo.max_freq = cpudata->nominal_freq * 1000; -+ 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; - -- ret = freq_qos_update_request(&cpudata->req[1], -- policy->cpuinfo.max_freq); -- if (ret < 0) -- return ret; -+ 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 0; -+ return ret < 0 ? ret : 0; - } - --static void amd_pstate_boost_init(struct amd_cpudata *cpudata) -+static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state) - { -- u32 highest_perf, nominal_perf; -+ struct amd_cpudata *cpudata = policy->driver_data; -+ int ret; - -- highest_perf = READ_ONCE(cpudata->highest_perf); -- nominal_perf = READ_ONCE(cpudata->nominal_perf); -+ if (!cpudata->boost_supported) { -+ pr_err("Boost mode is not supported by this processor or SBIOS\n"); -+ return -EOPNOTSUPP; -+ } -+ mutex_lock(&amd_pstate_driver_lock); -+ 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 (highest_perf <= nominal_perf) -- return; -+ return ret; -+} - -- cpudata->boost_supported = true; -+static int amd_pstate_init_boost_support(struct amd_cpudata *cpudata) -+{ -+ u64 boost_val; -+ int ret = -1; -+ -+ /* -+ * 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)) { -+ pr_debug_once("Boost CPB capabilities not present in the processor\n"); -+ ret = 0; -+ goto exit_err; -+ } -+ -+ /* at least one CPU supports CPB, even if others fail later on to set up */ - current_pstate_driver->boost_enabled = true; -+ -+ 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; -+ } -+ -+ if (!(boost_val & MSR_K7_HWCR_CPB_DIS)) -+ cpudata->boost_supported = true; -+ -+ return 0; -+ -+exit_err: -+ cpudata->boost_supported = false; -+ return ret; - } - - static void amd_perf_ctl_reset(unsigned int cpu) -@@ -756,7 +814,7 @@ static int amd_pstate_get_highest_perf(int cpu, u32 *highest_perf) - { - int ret; - -- if (boot_cpu_has(X86_FEATURE_CPPC)) { -+ if (cpu_feature_enabled(X86_FEATURE_CPPC)) { - u64 cap1; - - ret = rdmsrl_safe_on_cpu(cpu, MSR_AMD_CPPC_CAP1, &cap1); -@@ -852,8 +910,12 @@ static u32 amd_pstate_get_transition_delay_us(unsigned int cpu) - u32 transition_delay_ns; - - transition_delay_ns = cppc_get_transition_latency(cpu); -- if (transition_delay_ns == CPUFREQ_ETERNAL) -- return AMD_PSTATE_TRANSITION_DELAY; -+ if (transition_delay_ns == CPUFREQ_ETERNAL) { -+ if (cpu_feature_enabled(X86_FEATURE_FAST_CPPC)) -+ return AMD_PSTATE_FAST_CPPC_TRANSITION_DELAY; -+ else -+ return AMD_PSTATE_TRANSITION_DELAY; -+ } - - return transition_delay_ns / NSEC_PER_USEC; - } -@@ -924,12 +986,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); - -+ /** -+ * Below values need to be initialized correctly, otherwise driver will fail to load -+ * max_freq is calculated according to (nominal_freq * highest_perf)/nominal_perf -+ * lowest_nonlinear_freq is a value between [min_freq, nominal_freq] -+ * Check _CPC in ACPI table objects if any values are incorrect -+ */ -+ if (min_freq <= 0 || max_freq <= 0 || nominal_freq <= 0 || min_freq > max_freq) { -+ pr_err("min_freq(%d) or max_freq(%d) or nominal_freq(%d) value is incorrect\n", -+ min_freq, max_freq, nominal_freq * 1000); -+ return -EINVAL; -+ } -+ -+ if (lowest_nonlinear_freq <= min_freq || lowest_nonlinear_freq > nominal_freq * 1000) { -+ pr_err("lowest_nonlinear_freq(%d) value is out of range [min_freq(%d), nominal_freq(%d)]\n", -+ lowest_nonlinear_freq, min_freq, nominal_freq * 1000); -+ return -EINVAL; -+ } -+ - return 0; - } - - static int amd_pstate_cpu_init(struct cpufreq_policy *policy) - { -- int min_freq, max_freq, nominal_freq, ret; -+ int min_freq, max_freq, ret; - struct device *dev; - struct amd_cpudata *cpudata; - -@@ -958,18 +1038,12 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy) - if (ret) - 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); -- nominal_freq = READ_ONCE(cpudata->nominal_freq); -- -- if (min_freq <= 0 || max_freq <= 0 || -- nominal_freq <= 0 || min_freq > max_freq) { -- dev_err(dev, -- "min_freq(%d) or max_freq(%d) or nominal_freq (%d) value is incorrect, check _CPC in ACPI tables\n", -- min_freq, max_freq, nominal_freq); -- ret = -EINVAL; -- goto free_cpudata1; -- } - - policy->cpuinfo.transition_latency = amd_pstate_get_transition_latency(policy->cpu); - policy->transition_delay_us = amd_pstate_get_transition_delay_us(policy->cpu); -@@ -980,10 +1054,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; - -- if (boot_cpu_has(X86_FEATURE_CPPC)) -+ if (cpu_feature_enabled(X86_FEATURE_CPPC)) - policy->fast_switch_possible = true; - - ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0], -@@ -1005,7 +1081,6 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy) - - policy->driver_data = cpudata; - -- amd_pstate_boost_init(cpudata); - if (!current_pstate_driver->adjust_perf) - current_pstate_driver->adjust_perf = amd_pstate_adjust_perf; - -@@ -1216,7 +1291,7 @@ static int amd_pstate_change_mode_without_dvr_change(int mode) - - cppc_state = mode; - -- if (boot_cpu_has(X86_FEATURE_CPPC) || cppc_state == AMD_PSTATE_ACTIVE) -+ if (cpu_feature_enabled(X86_FEATURE_CPPC) || cppc_state == AMD_PSTATE_ACTIVE) - return 0; - - for_each_present_cpu(cpu) { -@@ -1389,7 +1464,7 @@ static bool amd_pstate_acpi_pm_profile_undefined(void) - - static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) - { -- int min_freq, max_freq, nominal_freq, ret; -+ int min_freq, max_freq, ret; - struct amd_cpudata *cpudata; - struct device *dev; - u64 value; -@@ -1420,17 +1495,12 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) - if (ret) - 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); -- nominal_freq = READ_ONCE(cpudata->nominal_freq); -- if (min_freq <= 0 || max_freq <= 0 || -- nominal_freq <= 0 || min_freq > max_freq) { -- dev_err(dev, -- "min_freq(%d) or max_freq(%d) or nominal_freq(%d) value is incorrect, check _CPC in ACPI tables\n", -- min_freq, max_freq, nominal_freq); -- ret = -EINVAL; -- goto free_cpudata1; -- } - - policy->cpuinfo.min_freq = min_freq; - policy->cpuinfo.max_freq = max_freq; -@@ -1439,11 +1509,13 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) - - policy->driver_data = cpudata; - - cpudata->epp_cached = cpudata->epp_default = amd_pstate_get_epp(cpudata, 0); - - policy->min = policy->cpuinfo.min_freq; - policy->max = policy->cpuinfo.max_freq; - -+ 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. -@@ -1454,7 +1526,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) - else - policy->policy = CPUFREQ_POLICY_POWERSAVE; - -- if (boot_cpu_has(X86_FEATURE_CPPC)) { -+ if (cpu_feature_enabled(X86_FEATURE_CPPC)) { - ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value); - if (ret) - return ret; -@@ -1465,7 +1537,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) - return ret; - WRITE_ONCE(cpudata->cppc_cap1_cached, value); - } -- amd_pstate_boost_init(cpudata); - - return 0; - -@@ -1544,7 +1615,7 @@ static void amd_pstate_epp_update_limit(struct cpufreq_policy *policy) - epp = 0; - - /* Set initial EPP value */ -- if (boot_cpu_has(X86_FEATURE_CPPC)) { -+ if (cpu_feature_enabled(X86_FEATURE_CPPC)) { - value &= ~GENMASK_ULL(31, 24); - value |= (u64)epp << 24; - } -@@ -1567,6 +1638,12 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy) - - amd_pstate_epp_update_limit(policy); - -+ /* -+ * policy->cur is never updated with the amd_pstate_epp driver, but it -+ * is used as a stale frequency value. So, keep it within limits. -+ */ -+ policy->cur = policy->min; -+ - return 0; - } - -@@ -1583,7 +1660,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); - -- if (boot_cpu_has(X86_FEATURE_CPPC)) { -+ if (cpu_feature_enabled(X86_FEATURE_CPPC)) { - wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value); - } else { - perf_ctrls.max_perf = max_perf; -@@ -1617,7 +1694,7 @@ static void amd_pstate_epp_offline(struct cpufreq_policy *policy) - value = READ_ONCE(cpudata->cppc_req_cached); - - mutex_lock(&amd_pstate_limits_lock); -- if (boot_cpu_has(X86_FEATURE_CPPC)) { -+ if (cpu_feature_enabled(X86_FEATURE_CPPC)) { - cpudata->epp_policy = CPUFREQ_POLICY_UNKNOWN; - - /* Set max perf same as min perf */ -@@ -1721,6 +1798,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, -+ .set_boost = amd_pstate_set_boost, - .name = "amd-pstate-epp", - .attr = amd_pstate_epp_attr, - }; -@@ -1744,6 +1822,46 @@ static int __init amd_pstate_set_driver(int mode_idx) - return -EINVAL; - } - -+/** -+ * CPPC function is not supported for family ID 17H with model_ID ranging from 0x10 to 0x2F. -+ * show the debug message that helps to check if the CPU has CPPC support for loading issue. -+ */ -+static bool amd_cppc_supported(void) -+{ -+ struct cpuinfo_x86 *c = &cpu_data(0); -+ bool warn = false; -+ -+ if ((boot_cpu_data.x86 == 0x17) && (boot_cpu_data.x86_model < 0x30)) { -+ pr_debug_once("CPPC feature is not supported by the processor\n"); -+ return false; -+ } -+ -+ /* -+ * If the CPPC feature is disabled in the BIOS for processors that support MSR-based CPPC, -+ * the AMD Pstate driver may not function correctly. -+ * Check the CPPC flag and display a warning message if the platform supports CPPC. -+ * Note: below checking code will not abort the driver registeration process because of -+ * the code is added for debugging purposes. -+ */ -+ if (!cpu_feature_enabled(X86_FEATURE_CPPC)) { -+ if (cpu_feature_enabled(X86_FEATURE_ZEN1) || cpu_feature_enabled(X86_FEATURE_ZEN2)) { -+ if (c->x86_model > 0x60 && c->x86_model < 0xaf) -+ warn = true; -+ } else if (cpu_feature_enabled(X86_FEATURE_ZEN3) || cpu_feature_enabled(X86_FEATURE_ZEN4)) { -+ if ((c->x86_model > 0x10 && c->x86_model < 0x1F) || -+ (c->x86_model > 0x40 && c->x86_model < 0xaf)) -+ warn = true; -+ } else if (cpu_feature_enabled(X86_FEATURE_ZEN5)) { -+ warn = true; -+ } -+ } -+ -+ if (warn) -+ pr_warn_once("The CPPC feature is supported but currently disabled by the BIOS.\n" -+ "Please enable it if your BIOS has the CPPC option.\n"); -+ return true; -+} -+ - static int __init amd_pstate_init(void) - { - struct device *dev_root; -@@ -1752,6 +1870,11 @@ static int __init amd_pstate_init(void) - if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) - return -ENODEV; - -+ /* show debug message only if CPPC is not supported */ -+ if (!amd_cppc_supported()) -+ return -EOPNOTSUPP; -+ -+ /* show warning message when BIOS broken or ACPI disabled */ - if (!acpi_cpc_valid()) { - pr_warn_once("the _CPC object is not present in SBIOS or ACPI disabled\n"); - return -ENODEV; -@@ -1774,11 +1899,9 @@ static int __init amd_pstate_init(void) - /* Disable on the following configs by default: - * 1. Undefined platforms - * 2. Server platforms -- * 3. Shared memory designs - */ - if (amd_pstate_acpi_pm_profile_undefined() || -- amd_pstate_acpi_pm_profile_server() || -- !boot_cpu_has(X86_FEATURE_CPPC)) { -+ amd_pstate_acpi_pm_profile_server()) { - pr_info("driver load is disabled, boot with specific mode to enable this\n"); - return -ENODEV; - } -@@ -1802,7 +1925,7 @@ static int __init amd_pstate_init(void) - } - - /* capability check */ -- if (boot_cpu_has(X86_FEATURE_CPPC)) { -+ if (cpu_feature_enabled(X86_FEATURE_CPPC)) { - 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; -@@ -1821,8 +1944,10 @@ static int __init amd_pstate_init(void) - } - - ret = cpufreq_register_driver(current_pstate_driver); -- if (ret) -+ if (ret) { - pr_err("failed to register with return %d\n", ret); -+ goto disable_driver; -+ } - - dev_root = bus_get_dev_root(&cpu_subsys); - if (dev_root) { -@@ -1830,6 +1963,8 @@ static int __init amd_pstate_init(void) - - global_attr_free: - cpufreq_unregister_driver(current_pstate_driver); -+disable_driver: -+ 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 e6a28e7f4dbf..cc8bb2bc325a 100644 ---- a/drivers/cpufreq/amd-pstate.h -+++ b/drivers/cpufreq/amd-pstate.h -@@ -99,7 +99,8 @@ struct amd_cpudata { - u32 policy; - u64 cppc_cap1_cached; - bool suspended; - s16 epp_default; -+ bool boost_state; - }; - - #endif /* _LINUX_AMD_PSTATE_H */ -diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c -index 9e5060b27864..270ea04fb616 100644 ---- a/drivers/cpufreq/cpufreq.c -+++ b/drivers/cpufreq/cpufreq.c -@@ -614,10 +614,9 @@ static ssize_t show_boost(struct kobject *kobj, - static ssize_t store_boost(struct kobject *kobj, struct kobj_attribute *attr, - const char *buf, size_t count) - { -- int ret, enable; -+ bool enable; - -- ret = sscanf(buf, "%d", &enable); -- if (ret != 1 || enable < 0 || enable > 1) -+ if (kstrtobool(buf, &enable)) - return -EINVAL; - - if (cpufreq_boost_trigger_state(enable)) { -@@ -641,10 +640,10 @@ static ssize_t show_local_boost(struct cpufreq_policy *policy, char *buf) - static ssize_t store_local_boost(struct cpufreq_policy *policy, - const char *buf, size_t count) - { -- int ret, enable; -+ int ret; -+ bool enable; - -- ret = kstrtoint(buf, 10, &enable); -- if (ret || enable < 0 || enable > 1) -+ if (kstrtobool(buf, &enable)) - return -EINVAL; - - if (!cpufreq_driver->boost_enabled) --- -2.46.0.rc1 - |