diff options
Diffstat (limited to 'SOURCES/0001-amd-pstate.patch')
-rw-r--r-- | SOURCES/0001-amd-pstate.patch | 304 |
1 files changed, 67 insertions, 237 deletions
diff --git a/SOURCES/0001-amd-pstate.patch b/SOURCES/0001-amd-pstate.patch index 74fc021..8e7b5cb 100644 --- a/SOURCES/0001-amd-pstate.patch +++ b/SOURCES/0001-amd-pstate.patch @@ -1,151 +1,66 @@ -From f3018861226770c17b47bcda4d4fd4291ad00ae6 Mon Sep 17 00:00:00 2001 +From 14416a42f37d3455e6de7d249df9a76b40a456bf Mon Sep 17 00:00:00 2001 From: Peter Jung <admin@ptr1337.dev> -Date: Sun, 16 Jun 2024 15:33:06 +0200 +Date: Fri, 21 Jun 2024 15:31:56 +0200 Subject: [PATCH 02/10] amd-pstate Signed-off-by: Peter Jung <admin@ptr1337.dev> --- - drivers/cpufreq/amd-pstate.c | 265 +++++++++++++++++++++-------------- - include/linux/amd-pstate.h | 20 ++- - 2 files changed, 177 insertions(+), 108 deletions(-) + drivers/cpufreq/amd-pstate.c | 115 +++++++++++++++++++---------------- + drivers/cpufreq/amd-pstate.h | 14 +++-- + 2 files changed, 70 insertions(+), 59 deletions(-) diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c -index e263db0385ab..cde3b91b4422 100644 +index 6c989d859b39..c08463f8dcac 100644 --- a/drivers/cpufreq/amd-pstate.c +++ b/drivers/cpufreq/amd-pstate.c -@@ -68,6 +68,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) -@@ -112,6 +113,41 @@ static unsigned int epp_values[] = { - - typedef int (*cppc_mode_transition_fn)(int); +@@ -85,15 +85,6 @@ struct quirk_entry { + u32 lowest_freq; + }; -+static struct quirk_entry quirk_amd_7k62 = { -+ .nominal_freq = 2600, -+ .lowest_freq = 550, -+}; -+ -+static int __init dmi_matched_7k62_bios_bug(const struct dmi_system_id *dmi) -+{ -+ /** -+ * match the broken bios for family 17h processor support CPPC V2 -+ * broken BIOS lack of nominal_freq and lowest_freq capabilities -+ * definition in ACPI tables -+ */ -+ if (boot_cpu_has(X86_FEATURE_ZEN2)) { -+ quirks = dmi->driver_data; -+ pr_info("Overriding nominal and lowest frequencies for %s\n", dmi->ident); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static const struct dmi_system_id amd_pstate_quirks_table[] __initconst = { -+ { -+ .callback = dmi_matched_7k62_bios_bug, -+ .ident = "AMD EPYC 7K62", -+ .matches = { -+ DMI_MATCH(DMI_BIOS_VERSION, "5.14"), -+ DMI_MATCH(DMI_BIOS_RELEASE, "12/12/2019"), -+ }, -+ .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; -@@ -620,78 +656,6 @@ static void amd_pstate_adjust_perf(unsigned int cpu, +-/* +- * 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; +@@ -688,26 +679,6 @@ static void amd_pstate_adjust_perf(unsigned int cpu, cpufreq_cpu_put(policy); } -static int amd_get_min_freq(struct amd_cpudata *cpudata) -{ -- struct cppc_perf_caps cppc_perf; -- -- int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); -- if (ret) -- return ret; -- -- /* Switch to khz */ -- return cppc_perf.lowest_freq * 1000; +- return READ_ONCE(cpudata->min_freq); -} - -static int amd_get_max_freq(struct amd_cpudata *cpudata) -{ -- struct cppc_perf_caps cppc_perf; -- u32 max_perf, max_freq, nominal_freq, nominal_perf; -- u64 boost_ratio; -- -- int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); -- if (ret) -- return ret; -- -- nominal_freq = cppc_perf.nominal_freq; -- nominal_perf = READ_ONCE(cpudata->nominal_perf); -- max_perf = READ_ONCE(cpudata->highest_perf); -- -- boost_ratio = div_u64(max_perf << SCHED_CAPACITY_SHIFT, -- nominal_perf); -- -- max_freq = nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT; -- -- /* Switch to khz */ -- return max_freq * 1000; +- return READ_ONCE(cpudata->max_freq); -} - -static int amd_get_nominal_freq(struct amd_cpudata *cpudata) -{ -- struct cppc_perf_caps cppc_perf; -- -- int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); -- if (ret) -- return ret; -- -- /* Switch to khz */ -- return cppc_perf.nominal_freq * 1000; +- return READ_ONCE(cpudata->nominal_freq); -} - -static int amd_get_lowest_nonlinear_freq(struct amd_cpudata *cpudata) -{ -- struct cppc_perf_caps cppc_perf; -- u32 lowest_nonlinear_freq, lowest_nonlinear_perf, -- nominal_freq, nominal_perf; -- u64 lowest_nonlinear_ratio; -- -- int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); -- if (ret) -- return ret; -- -- nominal_freq = cppc_perf.nominal_freq; -- nominal_perf = READ_ONCE(cpudata->nominal_perf); -- -- lowest_nonlinear_perf = cppc_perf.lowest_nonlinear_perf; -- -- lowest_nonlinear_ratio = div_u64(lowest_nonlinear_perf << SCHED_CAPACITY_SHIFT, -- nominal_perf); -- -- lowest_nonlinear_freq = nominal_freq * lowest_nonlinear_ratio >> SCHED_CAPACITY_SHIFT; -- -- /* Switch to khz */ -- return lowest_nonlinear_freq * 1000; +- return READ_ONCE(cpudata->lowest_nonlinear_freq); -} - static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state) { struct amd_cpudata *cpudata = policy->driver_data; -@@ -844,9 +808,93 @@ static void amd_pstate_update_limits(unsigned int cpu) +@@ -860,7 +831,37 @@ 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. @@ -177,59 +92,19 @@ index e263db0385ab..cde3b91b4422 100644 +} + +/* -+ * amd_pstate_init_freq: Initialize the max_freq, min_freq, -+ * nominal_freq and lowest_nonlinear_freq for -+ * the @cpudata object. -+ * -+ * Requires: highest_perf, lowest_perf, nominal_perf and -+ * lowest_nonlinear_perf members of @cpudata to be -+ * initialized. -+ * -+ * Returns 0 on success, non-zero value on failure. -+ */ -+static int amd_pstate_init_freq(struct amd_cpudata *cpudata) -+{ -+ int ret; -+ u32 min_freq; -+ u32 highest_perf, max_freq; -+ u32 nominal_perf, nominal_freq; -+ u32 lowest_nonlinear_perf, lowest_nonlinear_freq; -+ u32 boost_ratio, lowest_nonlinear_ratio; -+ struct cppc_perf_caps cppc_perf; -+ -+ ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); -+ if (ret) -+ return ret; -+ -+ if (quirks && quirks->lowest_freq) -+ min_freq = quirks->lowest_freq * 1000; -+ else -+ min_freq = cppc_perf.lowest_freq * 1000; -+ -+ if (quirks && quirks->nominal_freq) -+ nominal_freq = quirks->nominal_freq ; -+ else -+ nominal_freq = cppc_perf.nominal_freq; -+ -+ nominal_perf = READ_ONCE(cpudata->nominal_perf); -+ -+ highest_perf = READ_ONCE(cpudata->highest_perf); -+ boost_ratio = div_u64(highest_perf << SCHED_CAPACITY_SHIFT, nominal_perf); -+ max_freq = (nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT) * 1000; -+ -+ lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf); -+ lowest_nonlinear_ratio = div_u64(lowest_nonlinear_perf << SCHED_CAPACITY_SHIFT, -+ nominal_perf); -+ lowest_nonlinear_freq = (nominal_freq * lowest_nonlinear_ratio >> SCHED_CAPACITY_SHIFT) * 1000; -+ -+ WRITE_ONCE(cpudata->min_freq, min_freq); -+ WRITE_ONCE(cpudata->lowest_nonlinear_freq, lowest_nonlinear_freq); -+ WRITE_ONCE(cpudata->nominal_freq, nominal_freq); -+ WRITE_ONCE(cpudata->max_freq, max_freq); -+ -+ return 0; -+} -+ + * amd_pstate_init_freq: Initialize the max_freq, min_freq, + * nominal_freq and lowest_nonlinear_freq for + * the @cpudata object. +@@ -881,7 +882,6 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata) + u32 boost_ratio, lowest_nonlinear_ratio; + struct cppc_perf_caps cppc_perf; + +- + ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); + if (ret) + return ret; +@@ -917,7 +917,7 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata) + static int amd_pstate_cpu_init(struct cpufreq_policy *policy) { - int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret; @@ -237,7 +112,7 @@ index e263db0385ab..cde3b91b4422 100644 struct device *dev; struct amd_cpudata *cpudata; -@@ -871,20 +919,25 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy) +@@ -946,20 +946,21 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy) if (ret) goto free_cpudata1; @@ -245,17 +120,13 @@ index e263db0385ab..cde3b91b4422 100644 - max_freq = amd_get_max_freq(cpudata); - nominal_freq = amd_get_nominal_freq(cpudata); - lowest_nonlinear_freq = amd_get_lowest_nonlinear_freq(cpudata); -+ ret = amd_pstate_init_freq(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 || min_freq > max_freq) { - dev_err(dev, "min_freq(%d) or max_freq(%d) value is incorrect\n", - min_freq, max_freq); -+ 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, @@ -272,21 +143,7 @@ index e263db0385ab..cde3b91b4422 100644 policy->min = min_freq; policy->max = max_freq; -@@ -912,13 +965,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy) - goto free_cpudata2; - } - -- /* Initial processor data capability frequencies */ -- cpudata->max_freq = max_freq; -- 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; - -@@ -982,7 +1030,7 @@ static ssize_t show_amd_pstate_max_freq(struct cpufreq_policy *policy, +@@ -1052,7 +1053,7 @@ static ssize_t show_amd_pstate_max_freq(struct cpufreq_policy *policy, int max_freq; struct amd_cpudata *cpudata = policy->driver_data; @@ -295,7 +152,7 @@ index e263db0385ab..cde3b91b4422 100644 if (max_freq < 0) return max_freq; -@@ -995,7 +1043,7 @@ static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *poli +@@ -1065,7 +1066,7 @@ static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *poli int freq; struct amd_cpudata *cpudata = policy->driver_data; @@ -304,7 +161,7 @@ index e263db0385ab..cde3b91b4422 100644 if (freq < 0) return freq; -@@ -1306,7 +1354,7 @@ static bool amd_pstate_acpi_pm_profile_undefined(void) +@@ -1376,7 +1377,7 @@ static bool amd_pstate_acpi_pm_profile_undefined(void) static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) { @@ -313,7 +170,7 @@ index e263db0385ab..cde3b91b4422 100644 struct amd_cpudata *cpudata; struct device *dev; u64 value; -@@ -1333,13 +1381,18 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) +@@ -1407,13 +1408,14 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) if (ret) goto free_cpudata1; @@ -324,10 +181,6 @@ index e263db0385ab..cde3b91b4422 100644 - 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); -+ ret = amd_pstate_init_freq(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); @@ -339,20 +192,7 @@ index e263db0385ab..cde3b91b4422 100644 ret = -EINVAL; goto free_cpudata1; } -@@ -1349,12 +1402,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) - /* It will be updated by governor */ - policy->cur = policy->cpuinfo.min_freq; - -- /* 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; - - cpudata->epp_cached = amd_pstate_get_epp(cpudata, 0); -@@ -1394,6 +1441,13 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) +@@ -1462,6 +1464,13 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) static int amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy) { @@ -366,23 +206,24 @@ index e263db0385ab..cde3b91b4422 100644 pr_debug("CPU %d exiting\n", policy->cpu); return 0; } -@@ -1672,6 +1726,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: +@@ -1750,11 +1759,9 @@ static int __init amd_pstate_init(void) /* Disable on the following configs by default: -diff --git a/include/linux/amd-pstate.h b/include/linux/amd-pstate.h -index d21838835abd..d58fc022ec46 100644 ---- a/include/linux/amd-pstate.h -+++ b/include/linux/amd-pstate.h -@@ -49,13 +49,17 @@ struct amd_aperf_mperf { + * 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; + } +diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h +index bc341f35908d..e6a28e7f4dbf 100644 +--- a/drivers/cpufreq/amd-pstate.h ++++ b/drivers/cpufreq/amd-pstate.h +@@ -42,13 +42,17 @@ struct amd_aperf_mperf { * @lowest_perf: the absolute lowest performance level of the processor * @prefcore_ranking: the preferred core ranking, the higher value indicates a higher * priority. @@ -405,17 +246,6 @@ index d21838835abd..d58fc022ec46 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, -@@ -124,4 +128,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 */ -- 2.45.2 |