From f3387c73641948cfa0d98078c247eec81bf46032 Mon Sep 17 00:00:00 2001 From: Jan200101 Date: Sun, 10 Mar 2024 18:22:44 +0100 Subject: kernel 6.7.9 amd pstate fixes --- SOURCES/0001-amd-pstate.patch | 471 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 467 insertions(+), 4 deletions(-) (limited to 'SOURCES') diff --git a/SOURCES/0001-amd-pstate.patch b/SOURCES/0001-amd-pstate.patch index d7fd4b3..da6f35d 100644 --- a/SOURCES/0001-amd-pstate.patch +++ b/SOURCES/0001-amd-pstate.patch @@ -1,9 +1,10 @@ -From 1449b07b2bd2af451bba8ba17f7b01cf30b6471f Mon Sep 17 00:00:00 2001 +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Peter Jung Date: Fri, 23 Feb 2024 17:11:08 +0100 -Subject: [PATCH 1/7] amd-pstate +Subject: [PATCH] amd-pstate Signed-off-by: Peter Jung +Signed-off-by: Jan200101 --- .../admin-guide/kernel-parameters.txt | 5 + Documentation/admin-guide/pm/amd-pstate.rst | 59 +++++- @@ -573,6 +574,468 @@ index 1c5ca92a0555..5d62beea2712 100644 #endif #ifdef CONFIG_CPU_FREQ_STAT --- -2.43.2 +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Perry Yuan +Date: Wed, 31 Jan 2024 16:50:15 +0800 +Subject: [PATCH] AMD Pstate Fixes And Enhancements + +The patch series adds some fixes and enhancements to the AMD pstate driver. +It enables CPPC v2 for certain processors in the family 17H, as requested +by TR40 processor users who expect improved performance and lower system +temperature. + +Additionally, it fixes the initialization of nominal_freq for each cpudata +and changes latency and delay values to be read from platform firmware firstly +for more accurate timing. + +A new quirk is also added for legacy processors that lack CPPC capabilities, +which caused the pstate driver to fail loading. + +I would greatly appreciate any feedbacks. + +Thank you! + +Perry Yuan (6): + ACPI: CPPC: enable AMD CPPC V2 support for family 17h processors + cpufreq:amd-pstate: fix the nominal freq value set + cpufreq:amd-pstate: initialize nominal_freq of each cpudata + cpufreq:amd-pstate: get pstate transition delay and latency value from + ACPI tables + cppc_acpi: print error message if CPPC is unsupported + cpufreq:amd-pstate: add quirk for the pstate CPPC capabilities missing + + arch/x86/kernel/acpi/cppc.c | 2 +- + drivers/acpi/cppc_acpi.c | 6 +- + drivers/cpufreq/amd-pstate.c | 112 ++++++++++++++++++++++++++++------- + include/linux/amd-pstate.h | 6 ++ + 4 files changed, 102 insertions(+), 24 deletions(-) + +-- +2.34.1 + +Signed-off-by: Jan200101 + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Perry Yuan +Date: Wed, 31 Jan 2024 16:50:16 +0800 +Subject: [PATCH] ACPI: CPPC: enable AMD CPPC V2 support for family 17h + processors + +As there are some AMD processors which only support CPPC V2 firmware and +BIOS implementation, the amd_pstate driver will be failed to load when +system booting with below kernel warning message: + +[ 0.477523] amd_pstate: the _CPC object is not present in SBIOS or ACPI disabled + +To make the amd_pstate driver can be loaded on those TR40 processors, it +needs to match x86_model from 0x30 to 0x7F for family 17H. +With the change, the system can load amd_pstate driver as expected. + +Reported-by: Gino Badouri +Issue: https://bugzilla.kernel.org/show_bug.cgi?id=218171 +Fixes: fbd74d1689 ("ACPI: CPPC: Fix enabling CPPC on AMD systems with shared memory") +Signed-off-by: Perry Yuan +Signed-off-by: Jan200101 +--- + arch/x86/kernel/acpi/cppc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c +index 8d8752b44f11..ff8f25faca3d 100644 +--- a/arch/x86/kernel/acpi/cppc.c ++++ b/arch/x86/kernel/acpi/cppc.c +@@ -20,7 +20,7 @@ bool cpc_supported_by_cpu(void) + (boot_cpu_data.x86_model >= 0x20 && boot_cpu_data.x86_model <= 0x2f))) + return true; + else if (boot_cpu_data.x86 == 0x17 && +- boot_cpu_data.x86_model >= 0x70 && boot_cpu_data.x86_model <= 0x7f) ++ boot_cpu_data.x86_model >= 0x30 && boot_cpu_data.x86_model <= 0x7f) + return true; + return boot_cpu_has(X86_FEATURE_CPPC); + } + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Perry Yuan +Date: Wed, 31 Jan 2024 16:50:17 +0800 +Subject: [PATCH] cpufreq:amd-pstate: fix the nominal freq value set + +Address an untested error where the nominal_freq was returned in KHz +instead of the correct MHz units, this oversight led to a wrong +nominal_freq set and resued, it will cause the max frequency of core to +be initialized with a wrong frequency value. + +Cc: stable@vger.kernel.org +Fixes: ec437d71db7 ("cpufreq: amd-pstate: Introduce a new AMD P-State driver to support future processors") +Signed-off-by: Perry Yuan +Signed-off-by: Jan200101 +--- + drivers/cpufreq/amd-pstate.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index 54df68773620..d2591ef3b4f6 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -638,8 +638,7 @@ static int amd_get_nominal_freq(struct amd_cpudata *cpudata) + if (ret) + return ret; + +- /* Switch to khz */ +- return cppc_perf.nominal_freq * 1000; ++ return cppc_perf.nominal_freq; + } + + static int amd_get_lowest_nonlinear_freq(struct amd_cpudata *cpudata) + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Perry Yuan +Date: Wed, 31 Jan 2024 16:50:18 +0800 +Subject: [PATCH] cpufreq:amd-pstate: initialize nominal_freq of each cpudata + +Optimizes the process of retrieving the nominal frequency by utilizing +'cpudata->nominal_freq' instead of repeatedly accessing the cppc_acpi interface. + +To enhance efficiency and reduce the CPU load, shifted to using +'cpudata->nominal_freq'. It allows for the nominal frequency to be accessed +directly from the cached data in 'cpudata' of each CPU. +It will also slightly reduce the frequency change latency while using pstate +driver passive mode. + +Signed-off-by: Perry Yuan +Signed-off-by: Jan200101 +--- + drivers/cpufreq/amd-pstate.c | 26 ++++++++++++++------------ + 1 file changed, 14 insertions(+), 12 deletions(-) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index d2591ef3b4f6..fa4908b37793 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -617,7 +617,7 @@ static int amd_get_max_freq(struct amd_cpudata *cpudata) + if (ret) + return ret; + +- nominal_freq = cppc_perf.nominal_freq; ++ nominal_freq = READ_ONCE(cpudata->nominal_freq); + nominal_perf = READ_ONCE(cpudata->nominal_perf); + max_perf = READ_ONCE(cpudata->highest_perf); + +@@ -652,7 +652,7 @@ static int amd_get_lowest_nonlinear_freq(struct amd_cpudata *cpudata) + if (ret) + return ret; + +- nominal_freq = cppc_perf.nominal_freq; ++ nominal_freq = READ_ONCE(cpudata->nominal_freq); + nominal_perf = READ_ONCE(cpudata->nominal_perf); + + lowest_nonlinear_perf = cppc_perf.lowest_nonlinear_perf; +@@ -846,13 +846,15 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy) + goto free_cpudata1; + + min_freq = amd_get_min_freq(cpudata); +- max_freq = amd_get_max_freq(cpudata); + nominal_freq = amd_get_nominal_freq(cpudata); ++ cpudata->nominal_freq = nominal_freq; ++ max_freq = amd_get_max_freq(cpudata); + lowest_nonlinear_freq = amd_get_lowest_nonlinear_freq(cpudata); + +- if (min_freq < 0 || max_freq < 0 || min_freq > max_freq) { +- dev_err(dev, "min_freq(%d) or max_freq(%d) value is incorrect\n", +- min_freq, max_freq); ++ if (min_freq < 0 || max_freq < 0 || min_freq > max_freq || nominal_freq == 0) { ++ dev_err(dev, "min_freq(%d) or max_freq(%d) or nominal_freq(%d) \ ++ value is incorrect\n", \ ++ min_freq, max_freq, nominal_freq); + ret = -EINVAL; + goto free_cpudata1; + } +@@ -891,7 +893,6 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy) + cpudata->min_freq = min_freq; + cpudata->max_limit_freq = max_freq; + cpudata->min_limit_freq = min_freq; +- cpudata->nominal_freq = nominal_freq; + cpudata->lowest_nonlinear_freq = lowest_nonlinear_freq; + + policy->driver_data = cpudata; +@@ -1308,12 +1309,14 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) + goto free_cpudata1; + + min_freq = amd_get_min_freq(cpudata); +- max_freq = amd_get_max_freq(cpudata); + nominal_freq = amd_get_nominal_freq(cpudata); ++ cpudata->nominal_freq = nominal_freq; ++ max_freq = amd_get_max_freq(cpudata); + lowest_nonlinear_freq = amd_get_lowest_nonlinear_freq(cpudata); +- if (min_freq < 0 || max_freq < 0 || min_freq > max_freq) { +- dev_err(dev, "min_freq(%d) or max_freq(%d) value is incorrect\n", +- min_freq, max_freq); ++ if (min_freq < 0 || max_freq < 0 || min_freq > max_freq || nominal_freq == 0) { ++ dev_err(dev, "min_freq(%d) or max_freq(%d) or nominal_freq(%d) \ ++ value is incorrect\n", \ ++ min_freq, max_freq, nominal_freq); + ret = -EINVAL; + goto free_cpudata1; + } +@@ -1326,7 +1329,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) + /* Initial processor data capability frequencies */ + cpudata->max_freq = max_freq; + cpudata->min_freq = min_freq; +- cpudata->nominal_freq = nominal_freq; + cpudata->lowest_nonlinear_freq = lowest_nonlinear_freq; + + policy->driver_data = cpudata; + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Perry Yuan +Date: Wed, 31 Jan 2024 16:50:19 +0800 +Subject: [PATCH] cpufreq:amd-pstate: get pstate transition delay and latency + value from ACPI tables + +make pstate driver initially retrieve the P-state transition delay and latency +values from the BIOS ACPI tables which has more reasonable delay and latency +values according to the platform design and requirements. + +Previously there values were hardcoded at specific value which may +have conflicted with platform and it might not reflect the most accurate or +optimized setting for the processor. + +[054h 0084 8] Preserve Mask : FFFFFFFF00000000 +[05Ch 0092 8] Write Mask : 0000000000000001 +[064h 0100 4] Command Latency : 00000FA0 +[068h 0104 4] Maximum Access Rate : 0000EA60 +[06Ch 0108 2] Minimum Turnaround Time : 0000 + +Signed-off-by: Perry Yuan +Signed-off-by: Jan200101 +--- + drivers/cpufreq/amd-pstate.c | 34 ++++++++++++++++++++++++++++++++-- + 1 file changed, 32 insertions(+), 2 deletions(-) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index fa4908b37793..484e89c9cd86 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -818,6 +818,36 @@ static void amd_pstate_update_limits(unsigned int cpu) + mutex_unlock(&amd_pstate_driver_lock); + } + ++/** ++ * Get pstate transition delay time from ACPI tables that firmware set ++ * instead of using hardcode value directly. ++ */ ++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; ++ ++ return transition_delay_ns / NSEC_PER_USEC; ++} ++ ++/** ++ * Get pstate transition latency value from ACPI tables that firmware set ++ * instead of using hardcode value directly. ++ */ ++static u32 amd_pstate_get_transition_latency(unsigned int cpu) ++{ ++ u32 transition_latency; ++ ++ transition_latency = cppc_get_transition_latency(cpu); ++ if (transition_latency == CPUFREQ_ETERNAL) ++ return AMD_PSTATE_TRANSITION_LATENCY; ++ ++ return transition_latency; ++} ++ + static int amd_pstate_cpu_init(struct cpufreq_policy *policy) + { + int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret; +@@ -859,8 +889,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy) + goto free_cpudata1; + } + +- policy->cpuinfo.transition_latency = AMD_PSTATE_TRANSITION_LATENCY; +- policy->transition_delay_us = AMD_PSTATE_TRANSITION_DELAY; ++ 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; + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Perry Yuan +Date: Wed, 31 Jan 2024 16:50:20 +0800 +Subject: [PATCH] cppc_acpi: print error message if CPPC is unsupported + +to be more clear what is wrong with CPPC when pstate driver failed to +load which has dependency on the CPPC capabilities. + +Add one more debug message to notify user if CPPC is not supported by +the CPU, then it will be easy to find out what need to fix for pstate +driver loading issue. + +[ 0.477523] amd_pstate: the _CPC object is not present in SBIOS or ACPI disabled + +Above message is not clear enough to verify whether CPPC is not supported. + +Signed-off-by: Perry Yuan +Signed-off-by: Jan200101 +--- + drivers/acpi/cppc_acpi.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c +index ad388a0e8484..6e89fc97c82f 100644 +--- a/drivers/acpi/cppc_acpi.c ++++ b/drivers/acpi/cppc_acpi.c +@@ -676,8 +676,10 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr) + + if (!osc_sb_cppc2_support_acked) { + pr_debug("CPPC v2 _OSC not acked\n"); +- if (!cpc_supported_by_cpu()) +- return -ENODEV; ++ if (!cpc_supported_by_cpu()) { ++ pr_debug("CPPC is not supported\n"); ++ return -ENODEV; ++ } + } + + /* Parse the ACPI _CPC table for this CPU. */ + +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Perry Yuan +Date: Wed, 31 Jan 2024 16:50:21 +0800 +Subject: [PATCH] cpufreq:amd-pstate: add quirk for the pstate CPPC + capabilities missing + +Add quirk table to get CPPC capabilities issue fixed by providing +correct perf or frequency values while driver loading. + +If CPPC capabilities are not defined in the ACPI tables or wrongly +defined by platform firmware, it needs to use quick to get those +issues fixed with correct workaround values to make pstate driver +can be loaded even though there are CPPC capabilities errors. + +Signed-off-by: Perry Yuan +Signed-off-by: Jan200101 +--- + drivers/cpufreq/amd-pstate.c | 51 +++++++++++++++++++++++++++++++----- + include/linux/amd-pstate.h | 6 +++++ + 2 files changed, 51 insertions(+), 6 deletions(-) + +diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c +index 484e89c9cd86..01ae446c08e6 100644 +--- a/drivers/cpufreq/amd-pstate.c ++++ b/drivers/cpufreq/amd-pstate.c +@@ -66,6 +66,7 @@ static struct cpufreq_driver amd_pstate_epp_driver; + static int cppc_state = AMD_PSTATE_UNDEFINED; + static bool cppc_enabled; + static bool amd_pstate_prefcore = true; ++static struct quirk_entry *quirks; + + /* + * AMD Energy Preference Performance (EPP) +@@ -110,6 +111,32 @@ static unsigned int epp_values[] = { + + typedef int (*cppc_mode_transition_fn)(int); + ++static struct quirk_entry quirk_amd_7k62 = { ++ .nominal_freq = 2600, ++ .lowest_freq = 550, ++}; ++ ++static int __init dmi_matched(const struct dmi_system_id *dmi) ++{ ++ quirks = dmi->driver_data; ++ ++ return 1; ++} ++ ++static const struct dmi_system_id amd_pstate_quirks_table[] __initconst = { ++ { ++ .callback = dmi_matched, ++ .ident = "AMD EPYC 7K62", ++ .matches = { ++ DMI_MATCH(DMI_PRODUCT_VERSION, "C1"), ++ DMI_MATCH(DMI_PRODUCT_SERIAL, "FX19911000028"), ++ }, ++ .driver_data = &quirk_amd_7k62, ++ }, ++ {} ++}; ++MODULE_DEVICE_TABLE(dmi, amd_pstate_quirks_table); ++ + static inline int get_mode_idx_from_str(const char *str, size_t size) + { + int i; +@@ -598,13 +625,19 @@ static void amd_pstate_adjust_perf(unsigned int cpu, + static int amd_get_min_freq(struct amd_cpudata *cpudata) + { + struct cppc_perf_caps cppc_perf; ++ u32 lowest_freq; + + int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); + if (ret) + return ret; + ++ if (quirks && quirks->lowest_freq) ++ lowest_freq = quirks->lowest_freq; ++ else ++ lowest_freq = cppc_perf.lowest_freq; ++ + /* Switch to khz */ +- return cppc_perf.lowest_freq * 1000; ++ return lowest_freq * 1000; + } + + static int amd_get_max_freq(struct amd_cpudata *cpudata) +@@ -632,13 +665,14 @@ static int amd_get_max_freq(struct amd_cpudata *cpudata) + + static int amd_get_nominal_freq(struct amd_cpudata *cpudata) + { +- struct cppc_perf_caps cppc_perf; ++ u32 nominal_freq; + +- int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); +- if (ret) +- return ret; ++ if (quirks && quirks->nominal_freq) ++ nominal_freq = quirks->nominal_freq; ++ else ++ nominal_freq = READ_ONCE(cpudata->nominal_freq); + +- return cppc_perf.nominal_freq; ++ return nominal_freq; + } + + static int amd_get_lowest_nonlinear_freq(struct amd_cpudata *cpudata) +@@ -1672,6 +1706,11 @@ static int __init amd_pstate_init(void) + if (cpufreq_get_current_driver()) + return -EEXIST; + ++ quirks = NULL; ++ ++ /* check if this machine need CPPC quirks */ ++ dmi_check_system(amd_pstate_quirks_table); ++ + switch (cppc_state) { + case AMD_PSTATE_UNDEFINED: + /* Disable on the following configs by default: +diff --git a/include/linux/amd-pstate.h b/include/linux/amd-pstate.h +index d21838835abd..7b2cbb892fd9 100644 +--- a/include/linux/amd-pstate.h ++++ b/include/linux/amd-pstate.h +@@ -124,4 +124,10 @@ static const char * const amd_pstate_mode_string[] = { + [AMD_PSTATE_GUIDED] = "guided", + NULL, + }; ++ ++struct quirk_entry { ++ u32 nominal_freq; ++ u32 lowest_freq; ++}; ++ + #endif /* _LINUX_AMD_PSTATE_H */ -- cgit v1.2.3