release 6.12.4 (preliminary)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
From 3427331872c37b2edb42406c65764e1565b0591b Mon Sep 17 00:00:00 2001
|
||||
From f077f4265c59f5d417aa40eaf82bb632c891b221 Mon Sep 17 00:00:00 2001
|
||||
From: Perry Yuan <perry.yuan@amd.com>
|
||||
Date: Fri, 9 Aug 2024 14:09:05 +0800
|
||||
Subject: cpufreq: amd-pstate: add quirk for Ryzen 3000 series processor
|
||||
@@ -17,7 +17,7 @@ Signed-off-by: Perry Yuan <perry.yuan@amd.com>
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -142,6 +142,11 @@ static struct quirk_entry quirk_amd_7k62
|
||||
@@ -136,6 +136,11 @@ static struct quirk_entry quirk_amd_7k62
|
||||
.lowest_freq = 550,
|
||||
};
|
||||
|
||||
@@ -29,7 +29,7 @@ Signed-off-by: Perry Yuan <perry.yuan@amd.com>
|
||||
static int __init dmi_matched_7k62_bios_bug(const struct dmi_system_id *dmi)
|
||||
{
|
||||
/**
|
||||
@@ -158,6 +163,21 @@ static int __init dmi_matched_7k62_bios_
|
||||
@@ -152,6 +157,21 @@ static int __init dmi_matched_7k62_bios_
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ Signed-off-by: Perry Yuan <perry.yuan@amd.com>
|
||||
static const struct dmi_system_id amd_pstate_quirks_table[] __initconst = {
|
||||
{
|
||||
.callback = dmi_matched_7k62_bios_bug,
|
||||
@@ -168,6 +188,16 @@ static const struct dmi_system_id amd_ps
|
||||
@@ -162,6 +182,16 @@ static const struct dmi_system_id amd_ps
|
||||
},
|
||||
.driver_data = &quirk_amd_7k62,
|
||||
},
|
||||
|
@@ -1,88 +0,0 @@
|
||||
From 44f21855901b1fd618ac16b07dbd14e8fea4ee13 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Sat, 31 Aug 2024 21:49:11 -0500
|
||||
Subject: cpufreq/amd-pstate: Export symbols for changing modes
|
||||
|
||||
In order to effectively test all mode switch combinations export
|
||||
everything necessarily for amd-pstate-ut to trigger a mode switch.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 23 ++++++++++-------------
|
||||
drivers/cpufreq/amd-pstate.h | 14 ++++++++++++++
|
||||
2 files changed, 24 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -60,18 +60,6 @@
|
||||
#define AMD_CPPC_EPP_BALANCE_POWERSAVE 0xBF
|
||||
#define AMD_CPPC_EPP_POWERSAVE 0xFF
|
||||
|
||||
-/*
|
||||
- * enum amd_pstate_mode - driver working mode of amd pstate
|
||||
- */
|
||||
-enum amd_pstate_mode {
|
||||
- AMD_PSTATE_UNDEFINED = 0,
|
||||
- AMD_PSTATE_DISABLE,
|
||||
- AMD_PSTATE_PASSIVE,
|
||||
- AMD_PSTATE_ACTIVE,
|
||||
- AMD_PSTATE_GUIDED,
|
||||
- AMD_PSTATE_MAX,
|
||||
-};
|
||||
-
|
||||
static const char * const amd_pstate_mode_string[] = {
|
||||
[AMD_PSTATE_UNDEFINED] = "undefined",
|
||||
[AMD_PSTATE_DISABLE] = "disable",
|
||||
@@ -81,6 +69,14 @@ static const char * const amd_pstate_mod
|
||||
NULL,
|
||||
};
|
||||
|
||||
+const char *amd_pstate_get_mode_string(enum amd_pstate_mode mode)
|
||||
+{
|
||||
+ if (mode < 0 || mode >= AMD_PSTATE_MAX)
|
||||
+ return NULL;
|
||||
+ return amd_pstate_mode_string[mode];
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(amd_pstate_get_mode_string);
|
||||
+
|
||||
struct quirk_entry {
|
||||
u32 nominal_freq;
|
||||
u32 lowest_freq;
|
||||
@@ -1380,7 +1376,7 @@ static ssize_t amd_pstate_show_status(ch
|
||||
return sysfs_emit(buf, "%s\n", amd_pstate_mode_string[cppc_state]);
|
||||
}
|
||||
|
||||
-static int amd_pstate_update_status(const char *buf, size_t size)
|
||||
+int amd_pstate_update_status(const char *buf, size_t size)
|
||||
{
|
||||
int mode_idx;
|
||||
|
||||
@@ -1397,6 +1393,7 @@ static int amd_pstate_update_status(cons
|
||||
|
||||
return 0;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(amd_pstate_update_status);
|
||||
|
||||
static ssize_t status_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
--- a/drivers/cpufreq/amd-pstate.h
|
||||
+++ b/drivers/cpufreq/amd-pstate.h
|
||||
@@ -103,4 +103,18 @@ struct amd_cpudata {
|
||||
bool boost_state;
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * enum amd_pstate_mode - driver working mode of amd pstate
|
||||
+ */
|
||||
+enum amd_pstate_mode {
|
||||
+ AMD_PSTATE_UNDEFINED = 0,
|
||||
+ AMD_PSTATE_DISABLE,
|
||||
+ AMD_PSTATE_PASSIVE,
|
||||
+ AMD_PSTATE_ACTIVE,
|
||||
+ AMD_PSTATE_GUIDED,
|
||||
+ AMD_PSTATE_MAX,
|
||||
+};
|
||||
+const char *amd_pstate_get_mode_string(enum amd_pstate_mode mode);
|
||||
+int amd_pstate_update_status(const char *buf, size_t size);
|
||||
+
|
||||
#endif /* _LINUX_AMD_PSTATE_H */
|
@@ -1,4 +1,4 @@
|
||||
From 2e2ba39aec71fb51e897c3275b255ef806800cf0 Mon Sep 17 00:00:00 2001
|
||||
From da2702cb43c82219d4624135d85e2fc8768aeb09 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Sep 2024 11:23:51 -0500
|
||||
Subject: cpufreq/amd-pstate: Fix non kerneldoc comment
|
||||
@@ -13,7 +13,7 @@ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1774,7 +1774,7 @@ static int __init amd_pstate_set_driver(
|
||||
@@ -1782,7 +1782,7 @@ static int __init amd_pstate_set_driver(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From d74ce254cc470da670d6b90c69bab553cdbde62b Mon Sep 17 00:00:00 2001
|
||||
From a7b86a6057ccc8f5b5ab4d08e753b2a034fa7d28 Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Tue, 17 Sep 2024 09:14:35 +0000
|
||||
Subject: cpufreq/amd-pstate: Rename MSR and shared memory specific functions
|
||||
@@ -93,7 +93,7 @@ Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
u32 min_perf, u32 des_perf,
|
||||
u32 max_perf, bool fast_switch)
|
||||
{
|
||||
@@ -1897,9 +1897,9 @@ static int __init amd_pstate_init(void)
|
||||
@@ -1905,9 +1905,9 @@ static int __init amd_pstate_init(void)
|
||||
current_pstate_driver->adjust_perf = amd_pstate_adjust_perf;
|
||||
} else {
|
||||
pr_debug("AMD CPPC shared memory based functionality is supported\n");
|
@@ -1,77 +0,0 @@
|
||||
From aabfc7370a7da9c52be97c79ba70a20201e6864a Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Sat, 31 Aug 2024 21:49:12 -0500
|
||||
Subject: cpufreq/amd-pstate-ut: Add test case for mode switches
|
||||
|
||||
There is a state machine in the amd-pstate driver utilized for
|
||||
switches for all modes. To make sure that cleanup and setup works
|
||||
properly for each mode add a unit test case that tries all
|
||||
combinations.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate-ut.c | 41 ++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 40 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate-ut.c
|
||||
+++ b/drivers/cpufreq/amd-pstate-ut.c
|
||||
@@ -54,12 +54,14 @@ static void amd_pstate_ut_acpi_cpc_valid
|
||||
static void amd_pstate_ut_check_enabled(u32 index);
|
||||
static void amd_pstate_ut_check_perf(u32 index);
|
||||
static void amd_pstate_ut_check_freq(u32 index);
|
||||
+static void amd_pstate_ut_check_driver(u32 index);
|
||||
|
||||
static struct amd_pstate_ut_struct amd_pstate_ut_cases[] = {
|
||||
{"amd_pstate_ut_acpi_cpc_valid", amd_pstate_ut_acpi_cpc_valid },
|
||||
{"amd_pstate_ut_check_enabled", amd_pstate_ut_check_enabled },
|
||||
{"amd_pstate_ut_check_perf", amd_pstate_ut_check_perf },
|
||||
- {"amd_pstate_ut_check_freq", amd_pstate_ut_check_freq }
|
||||
+ {"amd_pstate_ut_check_freq", amd_pstate_ut_check_freq },
|
||||
+ {"amd_pstate_ut_check_driver", amd_pstate_ut_check_driver }
|
||||
};
|
||||
|
||||
static bool get_shared_mem(void)
|
||||
@@ -257,6 +259,43 @@ skip_test:
|
||||
cpufreq_cpu_put(policy);
|
||||
}
|
||||
|
||||
+static int amd_pstate_set_mode(enum amd_pstate_mode mode)
|
||||
+{
|
||||
+ const char *mode_str = amd_pstate_get_mode_string(mode);
|
||||
+
|
||||
+ pr_debug("->setting mode to %s\n", mode_str);
|
||||
+
|
||||
+ return amd_pstate_update_status(mode_str, strlen(mode_str));
|
||||
+}
|
||||
+
|
||||
+static void amd_pstate_ut_check_driver(u32 index)
|
||||
+{
|
||||
+ enum amd_pstate_mode mode1, mode2;
|
||||
+ int ret;
|
||||
+
|
||||
+ for (mode1 = AMD_PSTATE_DISABLE; mode1 < AMD_PSTATE_MAX; mode1++) {
|
||||
+ ret = amd_pstate_set_mode(mode1);
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+ for (mode2 = AMD_PSTATE_DISABLE; mode2 < AMD_PSTATE_MAX; mode2++) {
|
||||
+ if (mode1 == mode2)
|
||||
+ continue;
|
||||
+ ret = amd_pstate_set_mode(mode2);
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+out:
|
||||
+ if (ret)
|
||||
+ pr_warn("%s: failed to update status for %s->%s: %d\n", __func__,
|
||||
+ amd_pstate_get_mode_string(mode1),
|
||||
+ amd_pstate_get_mode_string(mode2), ret);
|
||||
+
|
||||
+ amd_pstate_ut_cases[index].result = ret ?
|
||||
+ AMD_PSTATE_UT_RESULT_FAIL :
|
||||
+ AMD_PSTATE_UT_RESULT_PASS;
|
||||
+}
|
||||
+
|
||||
static int __init amd_pstate_ut_init(void)
|
||||
{
|
||||
u32 i = 0, arr_size = ARRAY_SIZE(amd_pstate_ut_cases);
|
@@ -1,60 +0,0 @@
|
||||
From 24e62fbc101d079d398ac6fc76f458676d3d9491 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Sun, 1 Sep 2024 00:00:35 -0500
|
||||
Subject: cpufreq/amd-pstate: Catch failures for amd_pstate_epp_update_limit()
|
||||
|
||||
amd_pstate_set_epp() calls cppc_set_epp_perf() which can fail for
|
||||
a variety of reasons but this is ignored. Change the return flow
|
||||
to allow failures.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 11 +++++++----
|
||||
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1583,7 +1583,7 @@ static void amd_pstate_epp_cpu_exit(stru
|
||||
pr_debug("CPU %d exiting\n", policy->cpu);
|
||||
}
|
||||
|
||||
-static void amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
|
||||
+static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
u32 max_perf, min_perf, min_limit_perf, max_limit_perf;
|
||||
@@ -1633,7 +1633,7 @@ static void amd_pstate_epp_update_limit(
|
||||
* This return value can only be negative for shared_memory
|
||||
* systems where EPP register read/write not supported.
|
||||
*/
|
||||
- return;
|
||||
+ return epp;
|
||||
}
|
||||
|
||||
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
|
||||
@@ -1646,12 +1646,13 @@ static void amd_pstate_epp_update_limit(
|
||||
}
|
||||
|
||||
WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
- amd_pstate_set_epp(cpudata, epp);
|
||||
+ return amd_pstate_set_epp(cpudata, epp);
|
||||
}
|
||||
|
||||
static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
+ int ret;
|
||||
|
||||
if (!policy->cpuinfo.max_freq)
|
||||
return -ENODEV;
|
||||
@@ -1661,7 +1662,9 @@ static int amd_pstate_epp_set_policy(str
|
||||
|
||||
cpudata->policy = policy->policy;
|
||||
|
||||
- amd_pstate_epp_update_limit(policy);
|
||||
+ ret = amd_pstate_epp_update_limit(policy);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
/*
|
||||
* policy->cur is never updated with the amd_pstate_epp driver, but it
|
@@ -1,4 +1,4 @@
|
||||
From 684d162c08ab86fff02861c907ecc92bf9c09af4 Mon Sep 17 00:00:00 2001
|
||||
From 4e784acad1b275ddcb105b053922ab2179ab3f86 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Sat, 12 Oct 2024 12:45:18 -0500
|
||||
Subject: cpufreq/amd-pstate: Use amd_pstate_update_min_max_limit() for EPP
|
||||
@@ -17,7 +17,7 @@ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1505,26 +1505,13 @@ static void amd_pstate_epp_cpu_exit(stru
|
||||
@@ -1515,26 +1515,13 @@ static void amd_pstate_epp_cpu_exit(stru
|
||||
static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
@@ -1,4 +1,4 @@
|
||||
From fa46d2873c9fa4060ce407e4bc5c7e29babce9d0 Mon Sep 17 00:00:00 2001
|
||||
From ed39a400d49baf070571bb1da475297a8495aa67 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Sat, 12 Oct 2024 12:45:19 -0500
|
||||
Subject: cpufreq/amd-pstate: Drop needless EPP initialization
|
||||
@@ -14,7 +14,7 @@ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1548,12 +1548,6 @@ static int amd_pstate_epp_update_limit(s
|
||||
@@ -1558,12 +1558,6 @@ static int amd_pstate_epp_update_limit(s
|
||||
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
|
||||
epp = 0;
|
||||
|
@@ -1,67 +0,0 @@
|
||||
From 29c0347dd542e091e2f7e5980dd885f918f5f676 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Sep 2024 11:29:57 -0500
|
||||
Subject: x86/amd: Move amd_get_highest_perf() from amd.c to cppc.c
|
||||
|
||||
To prepare to let amd_get_highest_perf() detect preferred cores
|
||||
it will require CPPC functions. Move amd_get_highest_perf() to
|
||||
cppc.c to prepare for 'preferred core detection' rework.
|
||||
|
||||
No functional changes intended.
|
||||
|
||||
Reviewed-by: Perry Yuan <perry.yuan@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.sheoy@amd.com>
|
||||
---
|
||||
arch/x86/kernel/acpi/cppc.c | 16 ++++++++++++++++
|
||||
arch/x86/kernel/cpu/amd.c | 16 ----------------
|
||||
2 files changed, 16 insertions(+), 16 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/acpi/cppc.c
|
||||
+++ b/arch/x86/kernel/acpi/cppc.c
|
||||
@@ -116,3 +116,19 @@ void init_freq_invariance_cppc(void)
|
||||
init_done = true;
|
||||
mutex_unlock(&freq_invariance_lock);
|
||||
}
|
||||
+
|
||||
+u32 amd_get_highest_perf(void)
|
||||
+{
|
||||
+ struct cpuinfo_x86 *c = &boot_cpu_data;
|
||||
+
|
||||
+ if (c->x86 == 0x17 && ((c->x86_model >= 0x30 && c->x86_model < 0x40) ||
|
||||
+ (c->x86_model >= 0x70 && c->x86_model < 0x80)))
|
||||
+ return 166;
|
||||
+
|
||||
+ if (c->x86 == 0x19 && ((c->x86_model >= 0x20 && c->x86_model < 0x30) ||
|
||||
+ (c->x86_model >= 0x40 && c->x86_model < 0x70)))
|
||||
+ return 166;
|
||||
+
|
||||
+ return 255;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(amd_get_highest_perf);
|
||||
--- a/arch/x86/kernel/cpu/amd.c
|
||||
+++ b/arch/x86/kernel/cpu/amd.c
|
||||
@@ -1202,22 +1202,6 @@ unsigned long amd_get_dr_addr_mask(unsig
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(amd_get_dr_addr_mask);
|
||||
|
||||
-u32 amd_get_highest_perf(void)
|
||||
-{
|
||||
- struct cpuinfo_x86 *c = &boot_cpu_data;
|
||||
-
|
||||
- if (c->x86 == 0x17 && ((c->x86_model >= 0x30 && c->x86_model < 0x40) ||
|
||||
- (c->x86_model >= 0x70 && c->x86_model < 0x80)))
|
||||
- return 166;
|
||||
-
|
||||
- if (c->x86 == 0x19 && ((c->x86_model >= 0x20 && c->x86_model < 0x30) ||
|
||||
- (c->x86_model >= 0x40 && c->x86_model < 0x70)))
|
||||
- return 166;
|
||||
-
|
||||
- return 255;
|
||||
-}
|
||||
-EXPORT_SYMBOL_GPL(amd_get_highest_perf);
|
||||
-
|
||||
static void zenbleed_check_cpu(void *unused)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
|
@@ -1,95 +0,0 @@
|
||||
From 072efeb45349edd8ba9def11b6a450eaf56690a8 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Sep 2024 11:29:58 -0500
|
||||
Subject: ACPI: CPPC: Adjust return code for inline functions in
|
||||
!CONFIG_ACPI_CPPC_LIB
|
||||
|
||||
Checkpath emits the following warning:
|
||||
```
|
||||
WARNING: ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP
|
||||
```
|
||||
|
||||
Adjust the code accordingly.
|
||||
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.sheoy@amd.com>
|
||||
---
|
||||
include/acpi/cppc_acpi.h | 26 +++++++++++++-------------
|
||||
1 file changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/include/acpi/cppc_acpi.h
|
||||
+++ b/include/acpi/cppc_acpi.h
|
||||
@@ -164,31 +164,31 @@ extern int cppc_set_auto_sel(int cpu, bo
|
||||
#else /* !CONFIG_ACPI_CPPC_LIB */
|
||||
static inline int cppc_get_desired_perf(int cpunum, u64 *desired_perf)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_get_nominal_perf(int cpunum, u64 *nominal_perf)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_get_highest_perf(int cpunum, u64 *highest_perf)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_set_enable(int cpu, bool enable)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
static inline bool cppc_perf_ctrs_in_pcc(void)
|
||||
{
|
||||
@@ -212,27 +212,27 @@ static inline bool cpc_ffh_supported(voi
|
||||
}
|
||||
static inline int cpc_read_ffh(int cpunum, struct cpc_reg *reg, u64 *val)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cpc_write_ffh(int cpunum, struct cpc_reg *reg, u64 val)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_set_epp_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls, bool enable)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_get_epp_perf(int cpunum, u64 *epp_perf)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_set_auto_sel(int cpu, bool enable)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps)
|
||||
{
|
||||
- return -ENOTSUPP;
|
||||
+ return -EOPNOTSUPP;
|
||||
}
|
||||
#endif /* !CONFIG_ACPI_CPPC_LIB */
|
||||
|
@@ -0,0 +1,54 @@
|
||||
From 2a012fdcef91db6e380000b8042f90544ea49fd7 Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Thu, 17 Oct 2024 05:39:28 +0000
|
||||
Subject: cpufreq/amd-pstate: Remove the redundant verify() function
|
||||
|
||||
Merge the two verify() callback functions and rename the
|
||||
cpufreq_policy_data argument for better readability.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 15 ++++-----------
|
||||
1 file changed, 4 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -557,10 +557,10 @@ cpufreq_policy_put:
|
||||
cpufreq_cpu_put(policy);
|
||||
}
|
||||
|
||||
-static int amd_pstate_verify(struct cpufreq_policy_data *policy)
|
||||
+static int amd_pstate_verify(struct cpufreq_policy_data *policy_data)
|
||||
{
|
||||
- cpufreq_verify_within_cpu_limits(policy);
|
||||
-
|
||||
+ cpufreq_verify_within_cpu_limits(policy_data);
|
||||
+ pr_debug("policy_max =%d, policy_min=%d\n", policy_data->max, policy_data->min);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1668,13 +1668,6 @@ static int amd_pstate_epp_cpu_offline(st
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int amd_pstate_epp_verify_policy(struct cpufreq_policy_data *policy)
|
||||
-{
|
||||
- cpufreq_verify_within_cpu_limits(policy);
|
||||
- pr_debug("policy_max =%d, policy_min=%d\n", policy->max, policy->min);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int amd_pstate_epp_suspend(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
@@ -1730,7 +1723,7 @@ static struct cpufreq_driver amd_pstate_
|
||||
|
||||
static struct cpufreq_driver amd_pstate_epp_driver = {
|
||||
.flags = CPUFREQ_CONST_LOOPS,
|
||||
- .verify = amd_pstate_epp_verify_policy,
|
||||
+ .verify = amd_pstate_verify,
|
||||
.setpolicy = amd_pstate_epp_set_policy,
|
||||
.init = amd_pstate_epp_cpu_init,
|
||||
.exit = amd_pstate_epp_cpu_exit,
|
@@ -1,6 +1,6 @@
|
||||
From f5b234be445a45b0bcacc37e0aad7a6bc7900eac Mon Sep 17 00:00:00 2001
|
||||
From ba9f0c8ca71a1c44e35dd8d3221abda0bd4e465a Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Thu, 3 Oct 2024 08:39:54 +0000
|
||||
Date: Thu, 17 Oct 2024 05:39:30 +0000
|
||||
Subject: cpufreq/amd-pstate: Set the initial min_freq to lowest_nonlinear_freq
|
||||
|
||||
According to the AMD architectural programmer's manual volume 2 [1], in
|
||||
@@ -20,60 +20,55 @@ are completed sooner). This has shown a power benefit in some systems,
|
||||
in other systems, power consumption has increased but so has the
|
||||
throughput/watt.
|
||||
|
||||
Use the get_init_min_freq() callback to set the initial lower limit for
|
||||
amd-pstate driver to lowest_nonlinear_freq instead of lowest_freq.
|
||||
Modify the initial policy_data->min set by cpufreq-core to
|
||||
lowest_nonlinear_freq, in the ->verify() callback. Also set the
|
||||
cpudata->req[0] to FREQ_QOS_MIN_DEFAULT_VALUE (i.e. 0), so that it also
|
||||
gets overriden by the check in verify function.
|
||||
|
||||
Link: https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/24593.pdf [1]
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 16 +++++++++-------
|
||||
1 file changed, 9 insertions(+), 7 deletions(-)
|
||||
drivers/cpufreq/amd-pstate.c | 21 ++++++++++++++++++++-
|
||||
1 file changed, 20 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1003,13 +1003,6 @@ static int amd_pstate_cpu_init(struct cp
|
||||
if (cpu_feature_enabled(X86_FEATURE_CPPC))
|
||||
policy->fast_switch_possible = true;
|
||||
@@ -559,8 +559,27 @@ cpufreq_policy_put:
|
||||
|
||||
- ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0],
|
||||
- FREQ_QOS_MIN, policy->cpuinfo.min_freq);
|
||||
- if (ret < 0) {
|
||||
- dev_err(dev, "Failed to add min-freq constraint (%d)\n", ret);
|
||||
- goto free_cpudata1;
|
||||
- }
|
||||
-
|
||||
ret = freq_qos_add_request(&policy->constraints, &cpudata->req[1],
|
||||
FREQ_QOS_MAX, policy->cpuinfo.max_freq);
|
||||
if (ret < 0) {
|
||||
@@ -1724,6 +1717,13 @@ static int amd_pstate_epp_resume(struct
|
||||
static int amd_pstate_verify(struct cpufreq_policy_data *policy_data)
|
||||
{
|
||||
+ /*
|
||||
+ * Initialize lower frequency limit (i.e.policy->min) with
|
||||
+ * lowest_nonlinear_frequency which is the most energy efficient
|
||||
+ * frequency. Override the initial value set by cpufreq core and
|
||||
+ * amd-pstate qos_requests.
|
||||
+ */
|
||||
+ if (policy_data->min == FREQ_QOS_MIN_DEFAULT_VALUE) {
|
||||
+ struct cpufreq_policy *policy = cpufreq_cpu_get(policy_data->cpu);
|
||||
+ struct amd_cpudata *cpudata;
|
||||
+
|
||||
+ if (!policy)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ cpudata = policy->driver_data;
|
||||
+ policy_data->min = cpudata->lowest_nonlinear_freq;
|
||||
+ cpufreq_cpu_put(policy);
|
||||
+ }
|
||||
+
|
||||
cpufreq_verify_within_cpu_limits(policy_data);
|
||||
pr_debug("policy_max =%d, policy_min=%d\n", policy_data->max, policy_data->min);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int amd_pstate_get_init_min_freq(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ struct amd_cpudata *cpudata = policy->driver_data;
|
||||
+
|
||||
+ return READ_ONCE(cpudata->lowest_nonlinear_freq);
|
||||
+}
|
||||
+
|
||||
static struct cpufreq_driver amd_pstate_driver = {
|
||||
.flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
|
||||
.verify = amd_pstate_verify,
|
||||
@@ -1737,6 +1737,7 @@ static struct cpufreq_driver amd_pstate_
|
||||
.update_limits = amd_pstate_update_limits,
|
||||
.name = "amd-pstate",
|
||||
.attr = amd_pstate_attr,
|
||||
+ .get_init_min_freq = amd_pstate_get_init_min_freq,
|
||||
};
|
||||
@@ -1009,7 +1028,7 @@ static int amd_pstate_cpu_init(struct cp
|
||||
policy->fast_switch_possible = true;
|
||||
|
||||
static struct cpufreq_driver amd_pstate_epp_driver = {
|
||||
@@ -1753,6 +1754,7 @@ static struct cpufreq_driver amd_pstate_
|
||||
.set_boost = amd_pstate_set_boost,
|
||||
.name = "amd-pstate-epp",
|
||||
.attr = amd_pstate_epp_attr,
|
||||
+ .get_init_min_freq = amd_pstate_get_init_min_freq,
|
||||
};
|
||||
|
||||
static int __init amd_pstate_set_driver(int mode_idx)
|
||||
ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0],
|
||||
- FREQ_QOS_MIN, policy->cpuinfo.min_freq);
|
||||
+ FREQ_QOS_MIN, FREQ_QOS_MIN_DEFAULT_VALUE);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to add min-freq constraint (%d)\n", ret);
|
||||
goto free_cpudata1;
|
@@ -1,162 +0,0 @@
|
||||
From 21492d91ffc7c3fdb6507f64a74abf8326c75141 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Sep 2024 11:29:59 -0500
|
||||
Subject: x86/amd: Rename amd_get_highest_perf() to
|
||||
amd_get_boost_ratio_numerator()
|
||||
|
||||
The function name is ambiguous because it returns an intermediate value
|
||||
for calculating maximum frequency rather than the CPPC 'Highest Perf'
|
||||
register.
|
||||
|
||||
Rename the function to clarify its use and allow the function to return
|
||||
errors. Adjust the consumer in acpi-cpufreq to catch errors.
|
||||
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.sheoy@amd.com>
|
||||
---
|
||||
arch/x86/include/asm/processor.h | 3 ---
|
||||
arch/x86/kernel/acpi/cppc.c | 44 +++++++++++++++++++++++---------
|
||||
drivers/cpufreq/acpi-cpufreq.c | 12 ++++++---
|
||||
include/acpi/cppc_acpi.h | 5 ++++
|
||||
4 files changed, 46 insertions(+), 18 deletions(-)
|
||||
|
||||
--- a/arch/x86/include/asm/processor.h
|
||||
+++ b/arch/x86/include/asm/processor.h
|
||||
@@ -691,8 +691,6 @@ static inline u32 per_cpu_l2c_id(unsigne
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CPU_SUP_AMD
|
||||
-extern u32 amd_get_highest_perf(void);
|
||||
-
|
||||
/*
|
||||
* Issue a DIV 0/1 insn to clear any division data from previous DIV
|
||||
* operations.
|
||||
@@ -705,7 +703,6 @@ static __always_inline void amd_clear_di
|
||||
|
||||
extern void amd_check_microcode(void);
|
||||
#else
|
||||
-static inline u32 amd_get_highest_perf(void) { return 0; }
|
||||
static inline void amd_clear_divider(void) { }
|
||||
static inline void amd_check_microcode(void) { }
|
||||
#endif
|
||||
--- a/arch/x86/kernel/acpi/cppc.c
|
||||
+++ b/arch/x86/kernel/acpi/cppc.c
|
||||
@@ -69,7 +69,7 @@ int cpc_write_ffh(int cpunum, struct cpc
|
||||
static void amd_set_max_freq_ratio(void)
|
||||
{
|
||||
struct cppc_perf_caps perf_caps;
|
||||
- u64 highest_perf, nominal_perf;
|
||||
+ u64 numerator, nominal_perf;
|
||||
u64 perf_ratio;
|
||||
int rc;
|
||||
|
||||
@@ -79,15 +79,19 @@ static void amd_set_max_freq_ratio(void)
|
||||
return;
|
||||
}
|
||||
|
||||
- highest_perf = amd_get_highest_perf();
|
||||
+ rc = amd_get_boost_ratio_numerator(0, &numerator);
|
||||
+ if (rc) {
|
||||
+ pr_debug("Could not retrieve highest performance (%d)\n", rc);
|
||||
+ return;
|
||||
+ }
|
||||
nominal_perf = perf_caps.nominal_perf;
|
||||
|
||||
- if (!highest_perf || !nominal_perf) {
|
||||
- pr_debug("Could not retrieve highest or nominal performance\n");
|
||||
+ if (!nominal_perf) {
|
||||
+ pr_debug("Could not retrieve nominal performance\n");
|
||||
return;
|
||||
}
|
||||
|
||||
- perf_ratio = div_u64(highest_perf * SCHED_CAPACITY_SCALE, nominal_perf);
|
||||
+ perf_ratio = div_u64(numerator * SCHED_CAPACITY_SCALE, nominal_perf);
|
||||
/* midpoint between max_boost and max_P */
|
||||
perf_ratio = (perf_ratio + SCHED_CAPACITY_SCALE) >> 1;
|
||||
if (!perf_ratio) {
|
||||
@@ -117,18 +121,34 @@ void init_freq_invariance_cppc(void)
|
||||
mutex_unlock(&freq_invariance_lock);
|
||||
}
|
||||
|
||||
-u32 amd_get_highest_perf(void)
|
||||
+/**
|
||||
+ * amd_get_boost_ratio_numerator: Get the numerator to use for boost ratio calculation
|
||||
+ * @cpu: CPU to get numerator for.
|
||||
+ * @numerator: Output variable for numerator.
|
||||
+ *
|
||||
+ * Determine the numerator to use for calculating the boost ratio on
|
||||
+ * a CPU. On systems that support preferred cores, this will be a hardcoded
|
||||
+ * value. On other systems this will the highest performance register value.
|
||||
+ *
|
||||
+ * Return: 0 for success, negative error code otherwise.
|
||||
+ */
|
||||
+int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
|
||||
{
|
||||
struct cpuinfo_x86 *c = &boot_cpu_data;
|
||||
|
||||
if (c->x86 == 0x17 && ((c->x86_model >= 0x30 && c->x86_model < 0x40) ||
|
||||
- (c->x86_model >= 0x70 && c->x86_model < 0x80)))
|
||||
- return 166;
|
||||
+ (c->x86_model >= 0x70 && c->x86_model < 0x80))) {
|
||||
+ *numerator = 166;
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
if (c->x86 == 0x19 && ((c->x86_model >= 0x20 && c->x86_model < 0x30) ||
|
||||
- (c->x86_model >= 0x40 && c->x86_model < 0x70)))
|
||||
- return 166;
|
||||
+ (c->x86_model >= 0x40 && c->x86_model < 0x70))) {
|
||||
+ *numerator = 166;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ *numerator = 255;
|
||||
|
||||
- return 255;
|
||||
+ return 0;
|
||||
}
|
||||
-EXPORT_SYMBOL_GPL(amd_get_highest_perf);
|
||||
+EXPORT_SYMBOL_GPL(amd_get_boost_ratio_numerator);
|
||||
--- a/drivers/cpufreq/acpi-cpufreq.c
|
||||
+++ b/drivers/cpufreq/acpi-cpufreq.c
|
||||
@@ -642,10 +642,16 @@ static u64 get_max_boost_ratio(unsigned
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
|
||||
- highest_perf = amd_get_highest_perf();
|
||||
- else
|
||||
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
|
||||
+ ret = amd_get_boost_ratio_numerator(cpu, &highest_perf);
|
||||
+ if (ret) {
|
||||
+ pr_debug("CPU%d: Unable to get boost ratio numerator (%d)\n",
|
||||
+ cpu, ret);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ } else {
|
||||
highest_perf = perf_caps.highest_perf;
|
||||
+ }
|
||||
|
||||
nominal_perf = perf_caps.nominal_perf;
|
||||
|
||||
--- a/include/acpi/cppc_acpi.h
|
||||
+++ b/include/acpi/cppc_acpi.h
|
||||
@@ -161,6 +161,7 @@ extern int cppc_get_epp_perf(int cpunum,
|
||||
extern int cppc_set_epp_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls, bool enable);
|
||||
extern int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps);
|
||||
extern int cppc_set_auto_sel(int cpu, bool enable);
|
||||
+extern int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator);
|
||||
#else /* !CONFIG_ACPI_CPPC_LIB */
|
||||
static inline int cppc_get_desired_perf(int cpunum, u64 *desired_perf)
|
||||
{
|
||||
@@ -234,6 +235,10 @@ static inline int cppc_get_auto_sel_caps
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
+static inline int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
|
||||
+{
|
||||
+ return -EOPNOTSUPP;
|
||||
+}
|
||||
#endif /* !CONFIG_ACPI_CPPC_LIB */
|
||||
|
||||
#endif /* _CPPC_ACPI_H*/
|
@@ -1,35 +0,0 @@
|
||||
From 6f10d066dce0f1781b514a0352f0b427a32b1bb2 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Sep 2024 11:30:00 -0500
|
||||
Subject: ACPI: CPPC: Drop check for non zero perf ratio
|
||||
|
||||
perf_ratio is a u64 and SCHED_CAPACITY_SCALE is a large number.
|
||||
Shifting by one will never have a zero value.
|
||||
|
||||
Drop the check.
|
||||
|
||||
Suggested-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.sheoy@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
---
|
||||
arch/x86/kernel/acpi/cppc.c | 7 +------
|
||||
1 file changed, 1 insertion(+), 6 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/acpi/cppc.c
|
||||
+++ b/arch/x86/kernel/acpi/cppc.c
|
||||
@@ -91,13 +91,8 @@ static void amd_set_max_freq_ratio(void)
|
||||
return;
|
||||
}
|
||||
|
||||
- perf_ratio = div_u64(numerator * SCHED_CAPACITY_SCALE, nominal_perf);
|
||||
/* midpoint between max_boost and max_P */
|
||||
- perf_ratio = (perf_ratio + SCHED_CAPACITY_SCALE) >> 1;
|
||||
- if (!perf_ratio) {
|
||||
- pr_debug("Non-zero highest/nominal perf values led to a 0 ratio\n");
|
||||
- return;
|
||||
- }
|
||||
+ perf_ratio = (div_u64(numerator * SCHED_CAPACITY_SCALE, nominal_perf) + SCHED_CAPACITY_SCALE) >> 1;
|
||||
|
||||
freq_invariance_set_perf_ratio(perf_ratio, false);
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
From db147a0a6341822a15fd9c4cd51f8dc4a9a1747b Mon Sep 17 00:00:00 2001
|
||||
From e50aedf7fcd345c6f2e22a942deae007d71582df Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Thu, 17 Oct 2024 10:05:27 +0000
|
||||
Subject: cpufreq/amd-pstate: Call amd_pstate_register() in amd_pstate_init()
|
@@ -1,44 +0,0 @@
|
||||
From 8c142a91a58f24119e99d4e66b11890f4a4ef984 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Sep 2024 11:30:01 -0500
|
||||
Subject: ACPI: CPPC: Adjust debug messages in amd_set_max_freq_ratio() to warn
|
||||
|
||||
If the boost ratio isn't calculated properly for the system for any
|
||||
reason this can cause other problems that are non-obvious.
|
||||
|
||||
Raise all messages to warn instead.
|
||||
|
||||
Suggested-by: Perry Yuan <Perry.Yuan@amd.com>
|
||||
Reviewed-by: Perry Yuan <perry.yuan@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.sheoy@amd.com>
|
||||
---
|
||||
arch/x86/kernel/acpi/cppc.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/acpi/cppc.c
|
||||
+++ b/arch/x86/kernel/acpi/cppc.c
|
||||
@@ -75,19 +75,19 @@ static void amd_set_max_freq_ratio(void)
|
||||
|
||||
rc = cppc_get_perf_caps(0, &perf_caps);
|
||||
if (rc) {
|
||||
- pr_debug("Could not retrieve perf counters (%d)\n", rc);
|
||||
+ pr_warn("Could not retrieve perf counters (%d)\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = amd_get_boost_ratio_numerator(0, &numerator);
|
||||
if (rc) {
|
||||
- pr_debug("Could not retrieve highest performance (%d)\n", rc);
|
||||
+ pr_warn("Could not retrieve highest performance (%d)\n", rc);
|
||||
return;
|
||||
}
|
||||
nominal_perf = perf_caps.nominal_perf;
|
||||
|
||||
if (!nominal_perf) {
|
||||
- pr_debug("Could not retrieve nominal performance\n");
|
||||
+ pr_warn("Could not retrieve nominal performance\n");
|
||||
return;
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
From 7c658490b05f6ab4dd59e1c25e75ba1037f6cfeb Mon Sep 17 00:00:00 2001
|
||||
From 658af2bf561ee3883369b2caca4d688983f943de Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Thu, 17 Oct 2024 10:05:29 +0000
|
||||
Subject: cpufreq/amd-pstate: Call amd_pstate_set_driver() in
|
@@ -1,4 +1,4 @@
|
||||
From 55be5db97f4f52badc958463ee8d9cbc2ae91615 Mon Sep 17 00:00:00 2001
|
||||
From 0f2929e03651c101f1a6fa8ccf40167eb48c1789 Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Thu, 17 Oct 2024 10:05:31 +0000
|
||||
Subject: cpufreq/amd-pstate: Remove the switch case in amd_pstate_init()
|
@@ -1,138 +0,0 @@
|
||||
From 952e7bdc4cf67603f230f8eb91818ad4676e5a83 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Sep 2024 11:30:02 -0500
|
||||
Subject: x86/amd: Move amd_get_highest_perf() out of amd-pstate
|
||||
|
||||
amd_pstate_get_highest_perf() is a helper used to get the highest perf
|
||||
value on AMD systems. It's used in amd-pstate as part of preferred
|
||||
core handling, but applicable for acpi-cpufreq as well.
|
||||
|
||||
Move it out to cppc handling code as amd_get_highest_perf().
|
||||
|
||||
Reviewed-by: Perry Yuan <perry.yuan@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.sheoy@amd.com>
|
||||
---
|
||||
arch/x86/kernel/acpi/cppc.c | 30 ++++++++++++++++++++++++++++++
|
||||
drivers/cpufreq/amd-pstate.c | 34 ++--------------------------------
|
||||
include/acpi/cppc_acpi.h | 5 +++++
|
||||
3 files changed, 37 insertions(+), 32 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/acpi/cppc.c
|
||||
+++ b/arch/x86/kernel/acpi/cppc.c
|
||||
@@ -116,6 +116,36 @@ void init_freq_invariance_cppc(void)
|
||||
mutex_unlock(&freq_invariance_lock);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Get the highest performance register value.
|
||||
+ * @cpu: CPU from which to get highest performance.
|
||||
+ * @highest_perf: Return address for highest performance value.
|
||||
+ *
|
||||
+ * Return: 0 for success, negative error code otherwise.
|
||||
+ */
|
||||
+int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf)
|
||||
+{
|
||||
+ u64 val;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
||||
+ ret = rdmsrl_safe_on_cpu(cpu, MSR_AMD_CPPC_CAP1, &val);
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+
|
||||
+ val = AMD_CPPC_HIGHEST_PERF(val);
|
||||
+ } else {
|
||||
+ ret = cppc_get_highest_perf(cpu, &val);
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ WRITE_ONCE(*highest_perf, (u32)val);
|
||||
+out:
|
||||
+ return ret;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(amd_get_highest_perf);
|
||||
+
|
||||
/**
|
||||
* amd_get_boost_ratio_numerator: Get the numerator to use for boost ratio calculation
|
||||
* @cpu: CPU to get numerator for.
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -815,36 +815,6 @@ static void amd_pstste_sched_prefcore_wo
|
||||
}
|
||||
static DECLARE_WORK(sched_prefcore_work, amd_pstste_sched_prefcore_workfn);
|
||||
|
||||
-/*
|
||||
- * Get the highest performance register value.
|
||||
- * @cpu: CPU from which to get highest performance.
|
||||
- * @highest_perf: Return address.
|
||||
- *
|
||||
- * Return: 0 for success, -EIO otherwise.
|
||||
- */
|
||||
-static int amd_pstate_get_highest_perf(int cpu, u32 *highest_perf)
|
||||
-{
|
||||
- int ret;
|
||||
-
|
||||
- if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
||||
- u64 cap1;
|
||||
-
|
||||
- ret = rdmsrl_safe_on_cpu(cpu, MSR_AMD_CPPC_CAP1, &cap1);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
- WRITE_ONCE(*highest_perf, AMD_CPPC_HIGHEST_PERF(cap1));
|
||||
- } else {
|
||||
- u64 cppc_highest_perf;
|
||||
-
|
||||
- ret = cppc_get_highest_perf(cpu, &cppc_highest_perf);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
- WRITE_ONCE(*highest_perf, cppc_highest_perf);
|
||||
- }
|
||||
-
|
||||
- return (ret);
|
||||
-}
|
||||
-
|
||||
#define CPPC_MAX_PERF U8_MAX
|
||||
|
||||
static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata)
|
||||
@@ -852,7 +822,7 @@ static void amd_pstate_init_prefcore(str
|
||||
int ret, prio;
|
||||
u32 highest_perf;
|
||||
|
||||
- ret = amd_pstate_get_highest_perf(cpudata->cpu, &highest_perf);
|
||||
+ ret = amd_get_highest_perf(cpudata->cpu, &highest_perf);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
@@ -896,7 +866,7 @@ static void amd_pstate_update_limits(uns
|
||||
if ((!amd_pstate_prefcore) || (!cpudata->hw_prefcore))
|
||||
goto free_cpufreq_put;
|
||||
|
||||
- ret = amd_pstate_get_highest_perf(cpu, &cur_high);
|
||||
+ ret = amd_get_highest_perf(cpu, &cur_high);
|
||||
if (ret)
|
||||
goto free_cpufreq_put;
|
||||
|
||||
--- a/include/acpi/cppc_acpi.h
|
||||
+++ b/include/acpi/cppc_acpi.h
|
||||
@@ -161,6 +161,7 @@ extern int cppc_get_epp_perf(int cpunum,
|
||||
extern int cppc_set_epp_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls, bool enable);
|
||||
extern int cppc_get_auto_sel_caps(int cpunum, struct cppc_perf_caps *perf_caps);
|
||||
extern int cppc_set_auto_sel(int cpu, bool enable);
|
||||
+extern int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf);
|
||||
extern int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator);
|
||||
#else /* !CONFIG_ACPI_CPPC_LIB */
|
||||
static inline int cppc_get_desired_perf(int cpunum, u64 *desired_perf)
|
||||
@@ -235,6 +236,10 @@ static inline int cppc_get_auto_sel_caps
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
+static inline int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf)
|
||||
+{
|
||||
+ return -ENODEV;
|
||||
+}
|
||||
static inline int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
@@ -1,4 +1,4 @@
|
||||
From 7305364888151cb9e6b435c5f219ccfd18132b58 Mon Sep 17 00:00:00 2001
|
||||
From bec664db265db933a107bac290601eb89acb938b Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Thu, 17 Oct 2024 10:05:33 +0000
|
||||
Subject: cpufreq/amd-pstate: Remove the redundant amd_pstate_set_driver() call
|
@@ -1,251 +0,0 @@
|
||||
From 3ab7da5bbf2087982dbfe2b0f2937d0dddc3afb1 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Sep 2024 11:30:03 -0500
|
||||
Subject: x86/amd: Detect preferred cores in amd_get_boost_ratio_numerator()
|
||||
|
||||
AMD systems that support preferred cores will use "166" as their
|
||||
numerator for max frequency calculations instead of "255".
|
||||
|
||||
Add a function for detecting preferred cores by looking at the
|
||||
highest perf value on all cores.
|
||||
|
||||
If preferred cores are enabled return 166 and if disabled the
|
||||
value in the highest perf register. As the function will be called
|
||||
multiple times, cache the values for the boost numerator and if
|
||||
preferred cores will be enabled in global variables.
|
||||
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
arch/x86/kernel/acpi/cppc.c | 93 ++++++++++++++++++++++++++++++++----
|
||||
drivers/cpufreq/amd-pstate.c | 34 +++++--------
|
||||
include/acpi/cppc_acpi.h | 5 ++
|
||||
3 files changed, 101 insertions(+), 31 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/acpi/cppc.c
|
||||
+++ b/arch/x86/kernel/acpi/cppc.c
|
||||
@@ -9,6 +9,16 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/topology.h>
|
||||
|
||||
+#define CPPC_HIGHEST_PERF_PREFCORE 166
|
||||
+
|
||||
+enum amd_pref_core {
|
||||
+ AMD_PREF_CORE_UNKNOWN = 0,
|
||||
+ AMD_PREF_CORE_SUPPORTED,
|
||||
+ AMD_PREF_CORE_UNSUPPORTED,
|
||||
+};
|
||||
+static enum amd_pref_core amd_pref_core_detected;
|
||||
+static u64 boost_numerator;
|
||||
+
|
||||
/* Refer to drivers/acpi/cppc_acpi.c for the description of functions */
|
||||
|
||||
bool cpc_supported_by_cpu(void)
|
||||
@@ -147,6 +157,66 @@ out:
|
||||
EXPORT_SYMBOL_GPL(amd_get_highest_perf);
|
||||
|
||||
/**
|
||||
+ * amd_detect_prefcore: Detect if CPUs in the system support preferred cores
|
||||
+ * @detected: Output variable for the result of the detection.
|
||||
+ *
|
||||
+ * Determine whether CPUs in the system support preferred cores. On systems
|
||||
+ * that support preferred cores, different highest perf values will be found
|
||||
+ * on different cores. On other systems, the highest perf value will be the
|
||||
+ * same on all cores.
|
||||
+ *
|
||||
+ * The result of the detection will be stored in the 'detected' parameter.
|
||||
+ *
|
||||
+ * Return: 0 for success, negative error code otherwise
|
||||
+ */
|
||||
+int amd_detect_prefcore(bool *detected)
|
||||
+{
|
||||
+ int cpu, count = 0;
|
||||
+ u64 highest_perf[2] = {0};
|
||||
+
|
||||
+ if (WARN_ON(!detected))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ switch (amd_pref_core_detected) {
|
||||
+ case AMD_PREF_CORE_SUPPORTED:
|
||||
+ *detected = true;
|
||||
+ return 0;
|
||||
+ case AMD_PREF_CORE_UNSUPPORTED:
|
||||
+ *detected = false;
|
||||
+ return 0;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ for_each_present_cpu(cpu) {
|
||||
+ u32 tmp;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = amd_get_highest_perf(cpu, &tmp);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (!count || (count == 1 && tmp != highest_perf[0]))
|
||||
+ highest_perf[count++] = tmp;
|
||||
+
|
||||
+ if (count == 2)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ *detected = (count == 2);
|
||||
+ boost_numerator = highest_perf[0];
|
||||
+
|
||||
+ amd_pref_core_detected = *detected ? AMD_PREF_CORE_SUPPORTED :
|
||||
+ AMD_PREF_CORE_UNSUPPORTED;
|
||||
+
|
||||
+ pr_debug("AMD CPPC preferred core is %ssupported (highest perf: 0x%llx)\n",
|
||||
+ *detected ? "" : "un", highest_perf[0]);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(amd_detect_prefcore);
|
||||
+
|
||||
+/**
|
||||
* amd_get_boost_ratio_numerator: Get the numerator to use for boost ratio calculation
|
||||
* @cpu: CPU to get numerator for.
|
||||
* @numerator: Output variable for numerator.
|
||||
@@ -155,24 +225,27 @@ EXPORT_SYMBOL_GPL(amd_get_highest_perf);
|
||||
* a CPU. On systems that support preferred cores, this will be a hardcoded
|
||||
* value. On other systems this will the highest performance register value.
|
||||
*
|
||||
+ * If booting the system with amd-pstate enabled but preferred cores disabled then
|
||||
+ * the correct boost numerator will be returned to match hardware capabilities
|
||||
+ * even if the preferred cores scheduling hints are not enabled.
|
||||
+ *
|
||||
* Return: 0 for success, negative error code otherwise.
|
||||
*/
|
||||
int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
|
||||
{
|
||||
- struct cpuinfo_x86 *c = &boot_cpu_data;
|
||||
-
|
||||
- if (c->x86 == 0x17 && ((c->x86_model >= 0x30 && c->x86_model < 0x40) ||
|
||||
- (c->x86_model >= 0x70 && c->x86_model < 0x80))) {
|
||||
- *numerator = 166;
|
||||
- return 0;
|
||||
- }
|
||||
+ bool prefcore;
|
||||
+ int ret;
|
||||
|
||||
- if (c->x86 == 0x19 && ((c->x86_model >= 0x20 && c->x86_model < 0x30) ||
|
||||
- (c->x86_model >= 0x40 && c->x86_model < 0x70))) {
|
||||
- *numerator = 166;
|
||||
+ ret = amd_detect_prefcore(&prefcore);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* without preferred cores, return the highest perf register value */
|
||||
+ if (!prefcore) {
|
||||
+ *numerator = boost_numerator;
|
||||
return 0;
|
||||
}
|
||||
- *numerator = 255;
|
||||
+ *numerator = CPPC_HIGHEST_PERF_PREFCORE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -819,32 +819,18 @@ static DECLARE_WORK(sched_prefcore_work,
|
||||
|
||||
static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata)
|
||||
{
|
||||
- int ret, prio;
|
||||
- u32 highest_perf;
|
||||
-
|
||||
- ret = amd_get_highest_perf(cpudata->cpu, &highest_perf);
|
||||
- if (ret)
|
||||
+ /* user disabled or not detected */
|
||||
+ if (!amd_pstate_prefcore)
|
||||
return;
|
||||
|
||||
cpudata->hw_prefcore = true;
|
||||
- /* check if CPPC preferred core feature is enabled*/
|
||||
- if (highest_perf < CPPC_MAX_PERF)
|
||||
- prio = (int)highest_perf;
|
||||
- else {
|
||||
- pr_debug("AMD CPPC preferred core is unsupported!\n");
|
||||
- cpudata->hw_prefcore = false;
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- if (!amd_pstate_prefcore)
|
||||
- return;
|
||||
|
||||
/*
|
||||
* The priorities can be set regardless of whether or not
|
||||
* sched_set_itmt_support(true) has been called and it is valid to
|
||||
* update them at any time after it has been called.
|
||||
*/
|
||||
- sched_set_itmt_core_prio(prio, cpudata->cpu);
|
||||
+ sched_set_itmt_core_prio((int)READ_ONCE(cpudata->highest_perf), cpudata->cpu);
|
||||
|
||||
schedule_work(&sched_prefcore_work);
|
||||
}
|
||||
@@ -1015,12 +1001,12 @@ static int amd_pstate_cpu_init(struct cp
|
||||
|
||||
cpudata->cpu = policy->cpu;
|
||||
|
||||
- amd_pstate_init_prefcore(cpudata);
|
||||
-
|
||||
ret = amd_pstate_init_perf(cpudata);
|
||||
if (ret)
|
||||
goto free_cpudata1;
|
||||
|
||||
+ amd_pstate_init_prefcore(cpudata);
|
||||
+
|
||||
ret = amd_pstate_init_freq(cpudata);
|
||||
if (ret)
|
||||
goto free_cpudata1;
|
||||
@@ -1481,12 +1467,12 @@ static int amd_pstate_epp_cpu_init(struc
|
||||
cpudata->cpu = policy->cpu;
|
||||
cpudata->epp_policy = 0;
|
||||
|
||||
- amd_pstate_init_prefcore(cpudata);
|
||||
-
|
||||
ret = amd_pstate_init_perf(cpudata);
|
||||
if (ret)
|
||||
goto free_cpudata1;
|
||||
|
||||
+ amd_pstate_init_prefcore(cpudata);
|
||||
+
|
||||
ret = amd_pstate_init_freq(cpudata);
|
||||
if (ret)
|
||||
goto free_cpudata1;
|
||||
@@ -1948,6 +1934,12 @@ static int __init amd_pstate_init(void)
|
||||
static_call_update(amd_pstate_update_perf, cppc_update_perf);
|
||||
}
|
||||
|
||||
+ if (amd_pstate_prefcore) {
|
||||
+ ret = amd_detect_prefcore(&amd_pstate_prefcore);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
/* enable amd pstate feature */
|
||||
ret = amd_pstate_enable(true);
|
||||
if (ret) {
|
||||
--- a/include/acpi/cppc_acpi.h
|
||||
+++ b/include/acpi/cppc_acpi.h
|
||||
@@ -163,6 +163,7 @@ extern int cppc_get_auto_sel_caps(int cp
|
||||
extern int cppc_set_auto_sel(int cpu, bool enable);
|
||||
extern int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf);
|
||||
extern int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator);
|
||||
+extern int amd_detect_prefcore(bool *detected);
|
||||
#else /* !CONFIG_ACPI_CPPC_LIB */
|
||||
static inline int cppc_get_desired_perf(int cpunum, u64 *desired_perf)
|
||||
{
|
||||
@@ -244,6 +245,10 @@ static inline int amd_get_boost_ratio_nu
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
+static inline int amd_detect_prefcore(bool *detected)
|
||||
+{
|
||||
+ return -ENODEV;
|
||||
+}
|
||||
#endif /* !CONFIG_ACPI_CPPC_LIB */
|
||||
|
||||
#endif /* _CPPC_ACPI_H*/
|
@@ -1,169 +0,0 @@
|
||||
From 68d89574b86625f4bd7a784fe9bcc221dc290e4f Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Sep 2024 11:30:04 -0500
|
||||
Subject: cpufreq: amd-pstate: Merge amd_pstate_highest_perf_set() into
|
||||
amd_get_boost_ratio_numerator()
|
||||
|
||||
The special case in amd_pstate_highest_perf_set() is the value used
|
||||
for calculating the boost numerator. Merge this into
|
||||
amd_get_boost_ratio_numerator() and then use that to calculate boost
|
||||
ratio.
|
||||
|
||||
This allows dropping more special casing of the highest perf value.
|
||||
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.sheoy@amd.com>
|
||||
---
|
||||
Documentation/admin-guide/pm/amd-pstate.rst | 3 +-
|
||||
arch/x86/kernel/acpi/cppc.c | 16 +++++++
|
||||
drivers/cpufreq/amd-pstate.c | 52 ++++-----------------
|
||||
3 files changed, 28 insertions(+), 43 deletions(-)
|
||||
|
||||
--- a/Documentation/admin-guide/pm/amd-pstate.rst
|
||||
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
|
||||
@@ -251,7 +251,8 @@ performance supported in `AMD CPPC Perfo
|
||||
In some ASICs, the highest CPPC performance is not the one in the ``_CPC``
|
||||
table, so we need to expose it to sysfs. If boost is not active, but
|
||||
still supported, this maximum frequency will be larger than the one in
|
||||
-``cpuinfo``.
|
||||
+``cpuinfo``. On systems that support preferred core, the driver will have
|
||||
+different values for some cores than others.
|
||||
This attribute is read-only.
|
||||
|
||||
``amd_pstate_lowest_nonlinear_freq``
|
||||
--- a/arch/x86/kernel/acpi/cppc.c
|
||||
+++ b/arch/x86/kernel/acpi/cppc.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/topology.h>
|
||||
|
||||
+#define CPPC_HIGHEST_PERF_PERFORMANCE 196
|
||||
#define CPPC_HIGHEST_PERF_PREFCORE 166
|
||||
|
||||
enum amd_pref_core {
|
||||
@@ -245,6 +246,21 @@ int amd_get_boost_ratio_numerator(unsign
|
||||
*numerator = boost_numerator;
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+ /*
|
||||
+ * For AMD CPUs with Family ID 19H and Model ID range 0x70 to 0x7f,
|
||||
+ * the highest performance level is set to 196.
|
||||
+ * https://bugzilla.kernel.org/show_bug.cgi?id=218759
|
||||
+ */
|
||||
+ if (cpu_feature_enabled(X86_FEATURE_ZEN4)) {
|
||||
+ switch (boot_cpu_data.x86_model) {
|
||||
+ case 0x70 ... 0x7f:
|
||||
+ *numerator = CPPC_HIGHEST_PERF_PERFORMANCE;
|
||||
+ return 0;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
*numerator = CPPC_HIGHEST_PERF_PREFCORE;
|
||||
|
||||
return 0;
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -52,8 +52,6 @@
|
||||
#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
|
||||
|
||||
#define AMD_CPPC_EPP_PERFORMANCE 0x00
|
||||
#define AMD_CPPC_EPP_BALANCE_PERFORMANCE 0x80
|
||||
@@ -398,43 +396,17 @@ static inline int amd_pstate_enable(bool
|
||||
return static_call(amd_pstate_enable)(enable);
|
||||
}
|
||||
|
||||
-static u32 amd_pstate_highest_perf_set(struct amd_cpudata *cpudata)
|
||||
-{
|
||||
- struct cpuinfo_x86 *c = &cpu_data(0);
|
||||
-
|
||||
- /*
|
||||
- * For AMD CPUs with Family ID 19H and Model ID range 0x70 to 0x7f,
|
||||
- * the highest performance level is set to 196.
|
||||
- * https://bugzilla.kernel.org/show_bug.cgi?id=218759
|
||||
- */
|
||||
- if (c->x86 == 0x19 && (c->x86_model >= 0x70 && c->x86_model <= 0x7f))
|
||||
- return CPPC_HIGHEST_PERF_PERFORMANCE;
|
||||
-
|
||||
- return CPPC_HIGHEST_PERF_DEFAULT;
|
||||
-}
|
||||
-
|
||||
static int pstate_init_perf(struct amd_cpudata *cpudata)
|
||||
{
|
||||
u64 cap1;
|
||||
- u32 highest_perf;
|
||||
|
||||
int ret = rdmsrl_safe_on_cpu(cpudata->cpu, MSR_AMD_CPPC_CAP1,
|
||||
&cap1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- /* For platforms that do not support the preferred core feature, the
|
||||
- * highest_pef may be configured with 166 or 255, to avoid max frequency
|
||||
- * calculated wrongly. we take the AMD_CPPC_HIGHEST_PERF(cap1) value as
|
||||
- * the default max perf.
|
||||
- */
|
||||
- if (cpudata->hw_prefcore)
|
||||
- highest_perf = amd_pstate_highest_perf_set(cpudata);
|
||||
- else
|
||||
- highest_perf = AMD_CPPC_HIGHEST_PERF(cap1);
|
||||
-
|
||||
- WRITE_ONCE(cpudata->highest_perf, highest_perf);
|
||||
- WRITE_ONCE(cpudata->max_limit_perf, highest_perf);
|
||||
+ WRITE_ONCE(cpudata->highest_perf, AMD_CPPC_HIGHEST_PERF(cap1));
|
||||
+ WRITE_ONCE(cpudata->max_limit_perf, AMD_CPPC_HIGHEST_PERF(cap1));
|
||||
WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1));
|
||||
WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1));
|
||||
WRITE_ONCE(cpudata->lowest_perf, AMD_CPPC_LOWEST_PERF(cap1));
|
||||
@@ -446,19 +418,13 @@ static int pstate_init_perf(struct amd_c
|
||||
static int cppc_init_perf(struct amd_cpudata *cpudata)
|
||||
{
|
||||
struct cppc_perf_caps cppc_perf;
|
||||
- u32 highest_perf;
|
||||
|
||||
int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- if (cpudata->hw_prefcore)
|
||||
- highest_perf = amd_pstate_highest_perf_set(cpudata);
|
||||
- else
|
||||
- highest_perf = cppc_perf.highest_perf;
|
||||
-
|
||||
- WRITE_ONCE(cpudata->highest_perf, highest_perf);
|
||||
- WRITE_ONCE(cpudata->max_limit_perf, highest_perf);
|
||||
+ WRITE_ONCE(cpudata->highest_perf, cppc_perf.highest_perf);
|
||||
+ WRITE_ONCE(cpudata->max_limit_perf, cppc_perf.highest_perf);
|
||||
WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf);
|
||||
WRITE_ONCE(cpudata->lowest_nonlinear_perf,
|
||||
cppc_perf.lowest_nonlinear_perf);
|
||||
@@ -922,8 +888,8 @@ static u32 amd_pstate_get_transition_lat
|
||||
static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
|
||||
{
|
||||
int ret;
|
||||
- u32 min_freq;
|
||||
- u32 highest_perf, max_freq;
|
||||
+ u32 min_freq, max_freq;
|
||||
+ u64 numerator;
|
||||
u32 nominal_perf, nominal_freq;
|
||||
u32 lowest_nonlinear_perf, lowest_nonlinear_freq;
|
||||
u32 boost_ratio, lowest_nonlinear_ratio;
|
||||
@@ -945,8 +911,10 @@ static int amd_pstate_init_freq(struct a
|
||||
|
||||
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);
|
||||
+ ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ boost_ratio = div_u64(numerator << SCHED_CAPACITY_SHIFT, nominal_perf);
|
||||
max_freq = (nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT) * 1000;
|
||||
|
||||
lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
|
@@ -1,4 +1,4 @@
|
||||
From 5886ef269d069c72ea952cb00699e16221289e8c Mon Sep 17 00:00:00 2001
|
||||
From 82d4b19d01912cd9c2cfb3c638a43cc2b04ffc63 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 17 Oct 2024 12:34:39 -0500
|
||||
Subject: cpufreq/amd-pstate-ut: Add fix for min freq unit test
|
@@ -1,4 +1,4 @@
|
||||
From 497447cf96a785a4edd0756da5d5718037f5687c Mon Sep 17 00:00:00 2001
|
||||
From b1bc26a3ecd5afc4d6106332910fbdc3f6718acd Mon Sep 17 00:00:00 2001
|
||||
From: Swapnil Sapkal <swapnil.sapkal@amd.com>
|
||||
Date: Mon, 21 Oct 2024 15:48:36 +0530
|
||||
Subject: amd-pstate: Switch to amd-pstate by default on some Server platforms
|
@@ -1,42 +0,0 @@
|
||||
From deed718125e73b6bf280dcebb80c39108226388c Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Sep 2024 11:30:05 -0500
|
||||
Subject: cpufreq: amd-pstate: Optimize amd_pstate_update_limits()
|
||||
|
||||
Don't take and release the mutex when prefcore isn't present and
|
||||
avoid initialization of variables that will be initially set
|
||||
in the function.
|
||||
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Reviewed-by: Perry Yuan <perry.yuan@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.sheoy@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -814,17 +814,17 @@ static void amd_pstate_update_limits(uns
|
||||
|
||||
cpudata = policy->driver_data;
|
||||
|
||||
- mutex_lock(&amd_pstate_driver_lock);
|
||||
- if ((!amd_pstate_prefcore) || (!cpudata->hw_prefcore))
|
||||
- goto free_cpufreq_put;
|
||||
+ if (!amd_pstate_prefcore)
|
||||
+ return;
|
||||
|
||||
+ mutex_lock(&amd_pstate_driver_lock);
|
||||
ret = amd_get_highest_perf(cpu, &cur_high);
|
||||
if (ret)
|
||||
goto free_cpufreq_put;
|
||||
|
||||
prev_high = READ_ONCE(cpudata->prefcore_ranking);
|
||||
- if (prev_high != cur_high) {
|
||||
- highest_perf_changed = true;
|
||||
+ highest_perf_changed = (prev_high != cur_high);
|
||||
+ if (highest_perf_changed) {
|
||||
WRITE_ONCE(cpudata->prefcore_ranking, cur_high);
|
||||
|
||||
if (cur_high < CPPC_MAX_PERF)
|
@@ -1,29 +0,0 @@
|
||||
From 391075a34e392c7cacd338a6b034a21a10679855 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Sep 2024 11:30:06 -0500
|
||||
Subject: cpufreq: amd-pstate: Add documentation for `amd_pstate_hw_prefcore`
|
||||
|
||||
Explain that the sysfs file represents both preferred core being
|
||||
enabled by the user and supported by the hardware.
|
||||
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.sheoy@amd.com>
|
||||
---
|
||||
Documentation/admin-guide/pm/amd-pstate.rst | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
--- a/Documentation/admin-guide/pm/amd-pstate.rst
|
||||
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
|
||||
@@ -263,6 +263,11 @@ lowest non-linear performance in `AMD CP
|
||||
<perf_cap_>`_.)
|
||||
This attribute is read-only.
|
||||
|
||||
+``amd_pstate_hw_prefcore``
|
||||
+
|
||||
+Whether the platform supports the preferred core feature and it has been
|
||||
+enabled. This attribute is read-only.
|
||||
+
|
||||
``energy_performance_available_preferences``
|
||||
|
||||
A list of all the supported EPP preferences that could be used for
|
@@ -0,0 +1,121 @@
|
||||
From ca32f306d11e95ca133a2f90249bb4555c2742c3 Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Wed, 23 Oct 2024 10:21:06 +0000
|
||||
Subject: cpufreq/amd-pstate: Rename functions that enable CPPC
|
||||
|
||||
Explicitly rename functions that enable CPPC as *_cppc_*.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Perry Yuan <perry.yuan@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 26 +++++++++++++-------------
|
||||
1 file changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -336,7 +336,7 @@ static int amd_pstate_set_energy_pref_in
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static inline int msr_enable(bool enable)
|
||||
+static inline int msr_cppc_enable(bool enable)
|
||||
{
|
||||
int ret, cpu;
|
||||
unsigned long logical_proc_id_mask = 0;
|
||||
@@ -362,7 +362,7 @@ static inline int msr_enable(bool enable
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int shmem_enable(bool enable)
|
||||
+static int shmem_cppc_enable(bool enable)
|
||||
{
|
||||
int cpu, ret = 0;
|
||||
struct cppc_perf_ctrls perf_ctrls;
|
||||
@@ -389,11 +389,11 @@ static int shmem_enable(bool enable)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-DEFINE_STATIC_CALL(amd_pstate_enable, msr_enable);
|
||||
+DEFINE_STATIC_CALL(amd_pstate_cppc_enable, msr_cppc_enable);
|
||||
|
||||
-static inline int amd_pstate_enable(bool enable)
|
||||
+static inline int amd_pstate_cppc_enable(bool enable)
|
||||
{
|
||||
- return static_call(amd_pstate_enable)(enable);
|
||||
+ return static_call(amd_pstate_cppc_enable)(enable);
|
||||
}
|
||||
|
||||
static int msr_init_perf(struct amd_cpudata *cpudata)
|
||||
@@ -1072,7 +1072,7 @@ static int amd_pstate_cpu_resume(struct
|
||||
{
|
||||
int ret;
|
||||
|
||||
- ret = amd_pstate_enable(true);
|
||||
+ ret = amd_pstate_cppc_enable(true);
|
||||
if (ret)
|
||||
pr_err("failed to enable amd-pstate during resume, return %d\n", ret);
|
||||
|
||||
@@ -1083,7 +1083,7 @@ static int amd_pstate_cpu_suspend(struct
|
||||
{
|
||||
int ret;
|
||||
|
||||
- ret = amd_pstate_enable(false);
|
||||
+ ret = amd_pstate_cppc_enable(false);
|
||||
if (ret)
|
||||
pr_err("failed to disable amd-pstate during suspend, return %d\n", ret);
|
||||
|
||||
@@ -1216,7 +1216,7 @@ static ssize_t show_energy_performance_p
|
||||
|
||||
static void amd_pstate_driver_cleanup(void)
|
||||
{
|
||||
- amd_pstate_enable(false);
|
||||
+ amd_pstate_cppc_enable(false);
|
||||
cppc_state = AMD_PSTATE_DISABLE;
|
||||
current_pstate_driver = NULL;
|
||||
}
|
||||
@@ -1250,7 +1250,7 @@ static int amd_pstate_register_driver(in
|
||||
|
||||
cppc_state = mode;
|
||||
|
||||
- ret = amd_pstate_enable(true);
|
||||
+ ret = amd_pstate_cppc_enable(true);
|
||||
if (ret) {
|
||||
pr_err("failed to enable cppc during amd-pstate driver registration, return %d\n",
|
||||
ret);
|
||||
@@ -1629,7 +1629,7 @@ static void amd_pstate_epp_reenable(stru
|
||||
u64 value, max_perf;
|
||||
int ret;
|
||||
|
||||
- ret = amd_pstate_enable(true);
|
||||
+ ret = amd_pstate_cppc_enable(true);
|
||||
if (ret)
|
||||
pr_err("failed to enable amd pstate during resume, return %d\n", ret);
|
||||
|
||||
@@ -1716,7 +1716,7 @@ static int amd_pstate_epp_suspend(struct
|
||||
cpudata->suspended = true;
|
||||
|
||||
/* disable CPPC in lowlevel firmware */
|
||||
- ret = amd_pstate_enable(false);
|
||||
+ ret = amd_pstate_cppc_enable(false);
|
||||
if (ret)
|
||||
pr_err("failed to suspend, return %d\n", ret);
|
||||
|
||||
@@ -1891,7 +1891,7 @@ static int __init amd_pstate_init(void)
|
||||
current_pstate_driver->adjust_perf = amd_pstate_adjust_perf;
|
||||
} else {
|
||||
pr_debug("AMD CPPC shared memory based functionality is supported\n");
|
||||
- static_call_update(amd_pstate_enable, shmem_enable);
|
||||
+ static_call_update(amd_pstate_cppc_enable, shmem_cppc_enable);
|
||||
static_call_update(amd_pstate_init_perf, shmem_init_perf);
|
||||
static_call_update(amd_pstate_update_perf, shmem_update_perf);
|
||||
}
|
||||
@@ -1916,7 +1916,7 @@ static int __init amd_pstate_init(void)
|
||||
|
||||
global_attr_free:
|
||||
cpufreq_unregister_driver(current_pstate_driver);
|
||||
- amd_pstate_enable(false);
|
||||
+ amd_pstate_cppc_enable(false);
|
||||
return ret;
|
||||
}
|
||||
device_initcall(amd_pstate_init);
|
@@ -1,42 +0,0 @@
|
||||
From 2ed9874f6dcafcc2bee7a922af9e1d1c62dbeb18 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Sep 2024 11:30:07 -0500
|
||||
Subject: amd-pstate: Add missing documentation for
|
||||
`amd_pstate_prefcore_ranking`
|
||||
|
||||
`amd_pstate_prefcore_ranking` reflects the dynamic rankings of a CPU
|
||||
core based on platform conditions. Explicitly include it in the
|
||||
documentation.
|
||||
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.sheoy@amd.com>
|
||||
---
|
||||
Documentation/admin-guide/pm/amd-pstate.rst | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/Documentation/admin-guide/pm/amd-pstate.rst
|
||||
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
|
||||
@@ -252,7 +252,8 @@ In some ASICs, the highest CPPC performa
|
||||
table, so we need to expose it to sysfs. If boost is not active, but
|
||||
still supported, this maximum frequency will be larger than the one in
|
||||
``cpuinfo``. On systems that support preferred core, the driver will have
|
||||
-different values for some cores than others.
|
||||
+different values for some cores than others and this will reflect the values
|
||||
+advertised by the platform at bootup.
|
||||
This attribute is read-only.
|
||||
|
||||
``amd_pstate_lowest_nonlinear_freq``
|
||||
@@ -268,6 +269,12 @@ This attribute is read-only.
|
||||
Whether the platform supports the preferred core feature and it has been
|
||||
enabled. This attribute is read-only.
|
||||
|
||||
+``amd_pstate_prefcore_ranking``
|
||||
+
|
||||
+The performance ranking of the core. This number doesn't have any unit, but
|
||||
+larger numbers are preferred at the time of reading. This can change at
|
||||
+runtime based on platform conditions. This attribute is read-only.
|
||||
+
|
||||
``energy_performance_available_preferences``
|
||||
|
||||
A list of all the supported EPP preferences that could be used for
|
@@ -0,0 +1,30 @@
|
||||
From de31d4a11e894a73ed7ef2388fb27f0bb4036de3 Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Wed, 23 Oct 2024 10:21:08 +0000
|
||||
Subject: cpufreq/amd-pstate: Do not attempt to clear MSR_AMD_CPPC_ENABLE
|
||||
|
||||
MSR_AMD_CPPC_ENABLE is a write once register, i.e. attempting to clear
|
||||
it is futile, it will not take effect. Hence, return if disable (0)
|
||||
argument is passed to the msr_cppc_enable()
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -341,6 +341,12 @@ static inline int msr_cppc_enable(bool e
|
||||
int ret, cpu;
|
||||
unsigned long logical_proc_id_mask = 0;
|
||||
|
||||
+ /*
|
||||
+ * MSR_AMD_CPPC_ENABLE is write-once, once set it cannot be cleared.
|
||||
+ */
|
||||
+ if (!enable)
|
||||
+ return 0;
|
||||
+
|
||||
if (enable == cppc_enabled)
|
||||
return 0;
|
||||
|
@@ -0,0 +1,39 @@
|
||||
From c5eadae39ccdf6bada95c834147e285e445b12ad Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Wed, 23 Oct 2024 10:21:10 +0000
|
||||
Subject: cpufreq/amd-pstate: Call cppc_set_epp_perf in the reenable function
|
||||
|
||||
The EPP value being set in perf_ctrls.energy_perf is not being propagated
|
||||
to the shared memory, fix that.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Perry Yuan <perry.yuan@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1646,8 +1646,9 @@ static void amd_pstate_epp_reenable(stru
|
||||
wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
|
||||
} else {
|
||||
perf_ctrls.max_perf = max_perf;
|
||||
- perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(cpudata->epp_cached);
|
||||
cppc_set_perf(cpudata->cpu, &perf_ctrls);
|
||||
+ perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(cpudata->epp_cached);
|
||||
+ cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1688,8 +1689,9 @@ static void amd_pstate_epp_offline(struc
|
||||
} else {
|
||||
perf_ctrls.desired_perf = 0;
|
||||
perf_ctrls.max_perf = min_perf;
|
||||
- perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(HWP_EPP_BALANCE_POWERSAVE);
|
||||
cppc_set_perf(cpudata->cpu, &perf_ctrls);
|
||||
+ perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(HWP_EPP_BALANCE_POWERSAVE);
|
||||
+ cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1);
|
||||
}
|
||||
mutex_unlock(&amd_pstate_limits_lock);
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
From 275a7a8c95ac5d0c0ff586acd882d751478f6a00 Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Wed, 23 Oct 2024 10:21:12 +0000
|
||||
Subject: cpufreq/amd-pstate: Align offline flow of shared memory and MSR based
|
||||
systems
|
||||
|
||||
Set min_perf to lowest_perf for shared memory systems, similar to the MSR
|
||||
based systems.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1688,6 +1688,7 @@ static void amd_pstate_epp_offline(struc
|
||||
wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
|
||||
} else {
|
||||
perf_ctrls.desired_perf = 0;
|
||||
+ perf_ctrls.min_perf = min_perf;
|
||||
perf_ctrls.max_perf = min_perf;
|
||||
cppc_set_perf(cpudata->cpu, &perf_ctrls);
|
||||
perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(HWP_EPP_BALANCE_POWERSAVE);
|
@@ -1,24 +0,0 @@
|
||||
From 185e64a7e1a749593f3d6dadc666da9dda82d48c Mon Sep 17 00:00:00 2001
|
||||
From: Qianqiang Liu <qianqiang.liu@163.com>
|
||||
Date: Wed, 11 Sep 2024 07:39:24 +0800
|
||||
Subject: cpufreq/amd-pstate-ut: Fix an "Uninitialized variables" issue
|
||||
|
||||
Using uninitialized value "mode2" when calling "amd_pstate_get_mode_string".
|
||||
Set "mode2" to "AMD_PSTATE_DISABLE" by default.
|
||||
|
||||
Signed-off-by: Qianqiang Liu <qianqiang.liu@163.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate-ut.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate-ut.c
|
||||
+++ b/drivers/cpufreq/amd-pstate-ut.c
|
||||
@@ -270,7 +270,7 @@ static int amd_pstate_set_mode(enum amd_
|
||||
|
||||
static void amd_pstate_ut_check_driver(u32 index)
|
||||
{
|
||||
- enum amd_pstate_mode mode1, mode2;
|
||||
+ enum amd_pstate_mode mode1, mode2 = AMD_PSTATE_DISABLE;
|
||||
int ret;
|
||||
|
||||
for (mode1 = AMD_PSTATE_DISABLE; mode1 < AMD_PSTATE_MAX; mode1++) {
|
@@ -0,0 +1,60 @@
|
||||
From 173172a4604a050ccb5a6745acd9fa90d01257a7 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Fri, 25 Oct 2024 12:14:55 -0500
|
||||
Subject: x86/cpufeatures: Rename X86_FEATURE_FAST_CPPC to have AMD prefix
|
||||
|
||||
This feature is an AMD unique feature of some processors, so put
|
||||
AMD into the name.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
arch/x86/include/asm/cpufeatures.h | 2 +-
|
||||
arch/x86/kernel/cpu/scattered.c | 2 +-
|
||||
drivers/cpufreq/amd-pstate.c | 2 +-
|
||||
tools/arch/x86/include/asm/cpufeatures.h | 2 +-
|
||||
4 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/arch/x86/include/asm/cpufeatures.h
|
||||
+++ b/arch/x86/include/asm/cpufeatures.h
|
||||
@@ -473,7 +473,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 */
|
||||
+#define X86_FEATURE_AMD_FAST_CPPC (21*32 + 5) /* Fast CPPC */
|
||||
|
||||
/*
|
||||
* BUG word(s)
|
||||
--- a/arch/x86/kernel/cpu/scattered.c
|
||||
+++ b/arch/x86/kernel/cpu/scattered.c
|
||||
@@ -45,7 +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_AMD_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 },
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -880,7 +880,7 @@ static u32 amd_pstate_get_transition_del
|
||||
|
||||
transition_delay_ns = cppc_get_transition_latency(cpu);
|
||||
if (transition_delay_ns == CPUFREQ_ETERNAL) {
|
||||
- if (cpu_feature_enabled(X86_FEATURE_FAST_CPPC))
|
||||
+ if (cpu_feature_enabled(X86_FEATURE_AMD_FAST_CPPC))
|
||||
return AMD_PSTATE_FAST_CPPC_TRANSITION_DELAY;
|
||||
else
|
||||
return AMD_PSTATE_TRANSITION_DELAY;
|
||||
--- a/tools/arch/x86/include/asm/cpufeatures.h
|
||||
+++ b/tools/arch/x86/include/asm/cpufeatures.h
|
||||
@@ -472,7 +472,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 */
|
||||
+#define X86_FEATURE_AMD_FAST_CPPC (21*32 + 5) /* AMD Fast CPPC */
|
||||
|
||||
/*
|
||||
* BUG word(s)
|
@@ -1,115 +0,0 @@
|
||||
From 787175146e26a199c06be4e6bf8cf8da0f757271 Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Thu, 3 Oct 2024 08:39:52 +0000
|
||||
Subject: cpufreq: Add a callback to update the min_freq_req from drivers
|
||||
|
||||
Currently, there is no proper way to update the initial lower frequency
|
||||
limit from cpufreq drivers. Only way is to add a new min_freq qos
|
||||
request from the driver side, but it leads to the issue explained below.
|
||||
|
||||
The QoS infrastructure collates the constraints from multiple
|
||||
subsystems and saves them in a plist. The "current value" is defined to
|
||||
be the highest value in the plist for min_freq constraint.
|
||||
|
||||
The cpufreq core adds a qos_request for min_freq to be 0 and the amd-pstate
|
||||
driver today adds qos request for min_freq to be lowest_freq, where
|
||||
lowest_freq corresponds to CPPC.lowest_perf.
|
||||
|
||||
Eg: Suppose WLOG considering amd-pstate driver, lowest_freq is 400000 KHz,
|
||||
lowest_non_linear_freq is 1200000 KHz.
|
||||
|
||||
At this point of time, the min_freq QoS plist looks like:
|
||||
|
||||
head--> 400000 KHz (registered by amd-pstate) --> 0 KHz (registered by
|
||||
cpufreq core)
|
||||
|
||||
When a user updates /sys/devices/system/cpu/cpuX/cpufreq/scaling_min_freq,
|
||||
it only results in updating the cpufreq-core's node in the plist, where
|
||||
say 0 becomes the newly echoed value.
|
||||
|
||||
Now, if the user echoes a value 1000000 KHz, to scaling_min_freq, then the
|
||||
new list would be
|
||||
|
||||
head--> 1000000 KHz (registered by cpufreq core) --> 400000 KHz (registered
|
||||
by amd-pstate)
|
||||
|
||||
and the new "current value" of the min_freq QoS constraint will be 1000000
|
||||
KHz, this is the scenario where it works as expected.
|
||||
|
||||
Suppose we change the amd-pstate driver code's min_freq qos constraint
|
||||
to lowest_non_linear_freq instead of lowest_freq, then the user will
|
||||
never be able to request a value below that, due to the following:
|
||||
|
||||
At boot time, the min_freq QoS plist would be
|
||||
|
||||
head--> 1200000 KHz (registered by amd-pstate) --> 0 KHz (registered by
|
||||
cpufreq core)
|
||||
|
||||
When the user echoes a value of 1000000 KHz, to
|
||||
/sys/devices/..../scaling_min_freq, then the new list would be
|
||||
|
||||
head--> 1200000 KHz (registered by amd-pstate) --> 1000000 KHz (registered
|
||||
by cpufreq core)
|
||||
|
||||
with the new "current value" of the min_freq QoS remaining 1200000 KHz.
|
||||
Since the current value has not changed, there won't be any notifications
|
||||
sent to the subsystems which have added their QoS constraints. In
|
||||
particular, the amd-pstate driver will not get the notification, and thus,
|
||||
the user's request to lower the scaling_min_freq will be ineffective.
|
||||
|
||||
Hence, it is advisable to have a single source of truth for the min and
|
||||
max freq QoS constraints between the cpufreq and the cpufreq drivers.
|
||||
|
||||
So add a new callback get_init_min_freq() add in struct cpufreq_driver,
|
||||
which allows amd-pstate (or any other cpufreq driver) to override the
|
||||
default min_freq value being set in the policy->min_freq_req. Now
|
||||
scaling_min_freq can be modified by the user to any value (lower or
|
||||
higher than the init value) later on if desired.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/cpufreq.c | 6 +++++-
|
||||
include/linux/cpufreq.h | 6 ++++++
|
||||
2 files changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/cpufreq/cpufreq.c
|
||||
+++ b/drivers/cpufreq/cpufreq.c
|
||||
@@ -1380,6 +1380,7 @@ static int cpufreq_online(unsigned int c
|
||||
bool new_policy;
|
||||
unsigned long flags;
|
||||
unsigned int j;
|
||||
+ u32 init_min_freq = FREQ_QOS_MIN_DEFAULT_VALUE;
|
||||
int ret;
|
||||
|
||||
pr_debug("%s: bringing CPU%u online\n", __func__, cpu);
|
||||
@@ -1464,9 +1465,12 @@ static int cpufreq_online(unsigned int c
|
||||
goto out_destroy_policy;
|
||||
}
|
||||
|
||||
+ if (cpufreq_driver->get_init_min_freq)
|
||||
+ init_min_freq = cpufreq_driver->get_init_min_freq(policy);
|
||||
+
|
||||
ret = freq_qos_add_request(&policy->constraints,
|
||||
policy->min_freq_req, FREQ_QOS_MIN,
|
||||
- FREQ_QOS_MIN_DEFAULT_VALUE);
|
||||
+ init_min_freq);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* So we don't call freq_qos_remove_request() for an
|
||||
--- a/include/linux/cpufreq.h
|
||||
+++ b/include/linux/cpufreq.h
|
||||
@@ -414,6 +414,12 @@ struct cpufreq_driver {
|
||||
* policy is properly initialized, but before the governor is started.
|
||||
*/
|
||||
void (*register_em)(struct cpufreq_policy *policy);
|
||||
+
|
||||
+ /*
|
||||
+ * Set by drivers that want to initialize the policy->min_freq_req with
|
||||
+ * a value different from the default value (0) in cpufreq core.
|
||||
+ */
|
||||
+ int (*get_init_min_freq)(struct cpufreq_policy *policy);
|
||||
};
|
||||
|
||||
/* flags */
|
@@ -0,0 +1,43 @@
|
||||
From 34ef29430b9a217ef0811f218b8f86c631d6c574 Mon Sep 17 00:00:00 2001
|
||||
From: Perry Yuan <perry.yuan@amd.com>
|
||||
Date: Fri, 25 Oct 2024 12:14:56 -0500
|
||||
Subject: x86/cpufeatures: Add feature bits for AMD heterogeneous processor
|
||||
|
||||
CPUID leaf 0x80000026 advertises core types with different efficiency
|
||||
rankings.
|
||||
|
||||
Bit 30 indicates the heterogeneous core topology feature, if the bit
|
||||
set, it means not all instances at the current hierarchical level have
|
||||
the same core topology.
|
||||
|
||||
This is described in the AMD64 Architecture Programmers Manual Volume
|
||||
2 and 3, doc ID #25493 and #25494.
|
||||
|
||||
Signed-off-by: Perry Yuan <perry.yuan@amd.com>
|
||||
Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
arch/x86/include/asm/cpufeatures.h | 1 +
|
||||
arch/x86/kernel/cpu/scattered.c | 1 +
|
||||
2 files changed, 2 insertions(+)
|
||||
|
||||
--- a/arch/x86/include/asm/cpufeatures.h
|
||||
+++ b/arch/x86/include/asm/cpufeatures.h
|
||||
@@ -474,6 +474,7 @@
|
||||
#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_AMD_FAST_CPPC (21*32 + 5) /* Fast CPPC */
|
||||
+#define X86_FEATURE_AMD_HETEROGENEOUS_CORES (21*32 + 6) /* Heterogeneous Core Topology */
|
||||
|
||||
/*
|
||||
* BUG word(s)
|
||||
--- a/arch/x86/kernel/cpu/scattered.c
|
||||
+++ b/arch/x86/kernel/cpu/scattered.c
|
||||
@@ -52,6 +52,7 @@ static const struct cpuid_bit cpuid_bits
|
||||
{ X86_FEATURE_PERFMON_V2, CPUID_EAX, 0, 0x80000022, 0 },
|
||||
{ X86_FEATURE_AMD_LBR_V2, CPUID_EAX, 1, 0x80000022, 0 },
|
||||
{ X86_FEATURE_AMD_LBR_PMC_FREEZE, CPUID_EAX, 2, 0x80000022, 0 },
|
||||
+ { X86_FEATURE_AMD_HETEROGENEOUS_CORES, CPUID_EAX, 30, 0x80000026, 0 },
|
||||
{ 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
@@ -0,0 +1,32 @@
|
||||
From 5bd4c7b75f5588eb81bee35179569e27a4e164e4 Mon Sep 17 00:00:00 2001
|
||||
From: Perry Yuan <perry.yuan@amd.com>
|
||||
Date: Fri, 25 Oct 2024 12:14:57 -0500
|
||||
Subject: x86/cpu: Enable SD_ASYM_PACKING for PKG Domain on AMD Processors
|
||||
|
||||
Enable the SD_ASYM_PACKING domain flag for the PKG domain on AMD
|
||||
heterogeneous processors.
|
||||
This flag is beneficial for processors with one or more CCDs and
|
||||
relies on x86_sched_itmt_flags().
|
||||
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Signed-off-by: Perry Yuan <perry.yuan@amd.com>
|
||||
Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
arch/x86/kernel/smpboot.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/arch/x86/kernel/smpboot.c
|
||||
+++ b/arch/x86/kernel/smpboot.c
|
||||
@@ -497,8 +497,9 @@ static int x86_cluster_flags(void)
|
||||
|
||||
static int x86_die_flags(void)
|
||||
{
|
||||
- if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU))
|
||||
- return x86_sched_itmt_flags();
|
||||
+ if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU) ||
|
||||
+ cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES))
|
||||
+ return x86_sched_itmt_flags();
|
||||
|
||||
return 0;
|
||||
}
|
@@ -1,103 +0,0 @@
|
||||
From f7b2b3a1c0d015c4272793bed89734c5cffb354c Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Thu, 3 Oct 2024 08:39:56 +0000
|
||||
Subject: cpufreq/amd-pstate: Cleanup the old min_freq qos request remnants
|
||||
|
||||
Convert the freq_qos_request array in struct amd_cpudata to a single
|
||||
variable (only for max_freq request). Remove the references to cpudata->req
|
||||
array. Remove and rename the jump labels accordingly.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 19 ++++++++-----------
|
||||
drivers/cpufreq/amd-pstate.h | 4 ++--
|
||||
2 files changed, 10 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -704,7 +704,7 @@ static int amd_pstate_cpu_boost_update(s
|
||||
policy->max = policy->cpuinfo.max_freq;
|
||||
|
||||
if (cppc_state == AMD_PSTATE_PASSIVE) {
|
||||
- ret = freq_qos_update_request(&cpudata->req[1], policy->cpuinfo.max_freq);
|
||||
+ ret = freq_qos_update_request(&cpudata->max_freq_req, policy->cpuinfo.max_freq);
|
||||
if (ret < 0)
|
||||
pr_debug("Failed to update freq constraint: CPU%d\n", cpudata->cpu);
|
||||
}
|
||||
@@ -971,17 +971,17 @@ static int amd_pstate_cpu_init(struct cp
|
||||
|
||||
ret = amd_pstate_init_perf(cpudata);
|
||||
if (ret)
|
||||
- goto free_cpudata1;
|
||||
+ goto free_cpudata;
|
||||
|
||||
amd_pstate_init_prefcore(cpudata);
|
||||
|
||||
ret = amd_pstate_init_freq(cpudata);
|
||||
if (ret)
|
||||
- goto free_cpudata1;
|
||||
+ goto free_cpudata;
|
||||
|
||||
ret = amd_pstate_init_boost_support(cpudata);
|
||||
if (ret)
|
||||
- goto free_cpudata1;
|
||||
+ goto free_cpudata;
|
||||
|
||||
min_freq = READ_ONCE(cpudata->min_freq);
|
||||
max_freq = READ_ONCE(cpudata->max_freq);
|
||||
@@ -1003,11 +1003,11 @@ static int amd_pstate_cpu_init(struct cp
|
||||
if (cpu_feature_enabled(X86_FEATURE_CPPC))
|
||||
policy->fast_switch_possible = true;
|
||||
|
||||
- ret = freq_qos_add_request(&policy->constraints, &cpudata->req[1],
|
||||
+ ret = freq_qos_add_request(&policy->constraints, &cpudata->max_freq_req,
|
||||
FREQ_QOS_MAX, policy->cpuinfo.max_freq);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to add max-freq constraint (%d)\n", ret);
|
||||
- goto free_cpudata2;
|
||||
+ goto free_cpudata;
|
||||
}
|
||||
|
||||
cpudata->max_limit_freq = max_freq;
|
||||
@@ -1020,9 +1020,7 @@ static int amd_pstate_cpu_init(struct cp
|
||||
|
||||
return 0;
|
||||
|
||||
-free_cpudata2:
|
||||
- freq_qos_remove_request(&cpudata->req[0]);
|
||||
-free_cpudata1:
|
||||
+free_cpudata:
|
||||
kfree(cpudata);
|
||||
return ret;
|
||||
}
|
||||
@@ -1031,8 +1029,7 @@ static void amd_pstate_cpu_exit(struct c
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
|
||||
- freq_qos_remove_request(&cpudata->req[1]);
|
||||
- freq_qos_remove_request(&cpudata->req[0]);
|
||||
+ freq_qos_remove_request(&cpudata->max_freq_req);
|
||||
policy->fast_switch_possible = false;
|
||||
kfree(cpudata);
|
||||
}
|
||||
--- a/drivers/cpufreq/amd-pstate.h
|
||||
+++ b/drivers/cpufreq/amd-pstate.h
|
||||
@@ -28,7 +28,7 @@ struct amd_aperf_mperf {
|
||||
/**
|
||||
* struct amd_cpudata - private CPU data for AMD P-State
|
||||
* @cpu: CPU number
|
||||
- * @req: constraint request to apply
|
||||
+ * @max_freq_req: maximum frequency constraint request to apply
|
||||
* @cppc_req_cached: cached performance request hints
|
||||
* @highest_perf: the maximum performance an individual processor may reach,
|
||||
* assuming ideal conditions
|
||||
@@ -68,7 +68,7 @@ struct amd_aperf_mperf {
|
||||
struct amd_cpudata {
|
||||
int cpu;
|
||||
|
||||
- struct freq_qos_request req[2];
|
||||
+ struct freq_qos_request max_freq_req;
|
||||
u64 cppc_req_cached;
|
||||
|
||||
u32 highest_perf;
|
187
debian/patches/patchset-pf/amd-pstate/0021-x86-cpu-Add-CPU-type-to-struct-cpuinfo_topology.patch
vendored
Normal file
187
debian/patches/patchset-pf/amd-pstate/0021-x86-cpu-Add-CPU-type-to-struct-cpuinfo_topology.patch
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
From c30f11be765d5a5a68e975fbe720a4bdb6900388 Mon Sep 17 00:00:00 2001
|
||||
From: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
|
||||
Date: Fri, 25 Oct 2024 12:14:58 -0500
|
||||
Subject: x86/cpu: Add CPU type to struct cpuinfo_topology
|
||||
|
||||
Sometimes it is required to take actions based on if a CPU is a performance
|
||||
or efficiency core. As an example, intel_pstate driver uses the Intel
|
||||
core-type to determine CPU scaling. Also, some CPU vulnerabilities only
|
||||
affect a specific CPU type, like RFDS only affects Intel Atom. Hybrid
|
||||
systems that have variants P+E, P-only(Core) and E-only(Atom), it is not
|
||||
straightforward to identify which variant is affected by a type specific
|
||||
vulnerability.
|
||||
|
||||
Such processors do have CPUID field that can uniquely identify them. Like,
|
||||
P+E, P-only and E-only enumerates CPUID.1A.CORE_TYPE identification, while
|
||||
P+E additionally enumerates CPUID.7.HYBRID. Based on this information, it
|
||||
is possible for boot CPU to identify if a system has mixed CPU types.
|
||||
|
||||
Add a new field hw_cpu_type to struct cpuinfo_topology that stores the
|
||||
hardware specific CPU type. This saves the overhead of IPIs to get the CPU
|
||||
type of a different CPU. CPU type is populated early in the boot process,
|
||||
before vulnerabilities are enumerated.
|
||||
|
||||
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
|
||||
Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
|
||||
Co-developed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
arch/x86/include/asm/intel-family.h | 6 +++++
|
||||
arch/x86/include/asm/processor.h | 18 ++++++++++++++
|
||||
arch/x86/include/asm/topology.h | 9 +++++++
|
||||
arch/x86/kernel/cpu/debugfs.c | 1 +
|
||||
arch/x86/kernel/cpu/topology_amd.c | 3 +++
|
||||
arch/x86/kernel/cpu/topology_common.c | 34 +++++++++++++++++++++++++++
|
||||
6 files changed, 71 insertions(+)
|
||||
|
||||
--- a/arch/x86/include/asm/intel-family.h
|
||||
+++ b/arch/x86/include/asm/intel-family.h
|
||||
@@ -183,4 +183,10 @@
|
||||
/* Family 19 */
|
||||
#define INTEL_PANTHERCOVE_X IFM(19, 0x01) /* Diamond Rapids */
|
||||
|
||||
+/* CPU core types */
|
||||
+enum intel_cpu_type {
|
||||
+ INTEL_CPU_TYPE_ATOM = 0x20,
|
||||
+ INTEL_CPU_TYPE_CORE = 0x40,
|
||||
+};
|
||||
+
|
||||
#endif /* _ASM_X86_INTEL_FAMILY_H */
|
||||
--- a/arch/x86/include/asm/processor.h
|
||||
+++ b/arch/x86/include/asm/processor.h
|
||||
@@ -105,6 +105,24 @@ struct cpuinfo_topology {
|
||||
// Cache level topology IDs
|
||||
u32 llc_id;
|
||||
u32 l2c_id;
|
||||
+
|
||||
+ // Hardware defined CPU-type
|
||||
+ union {
|
||||
+ u32 cpu_type;
|
||||
+ struct {
|
||||
+ // CPUID.1A.EAX[23-0]
|
||||
+ u32 intel_native_model_id :24;
|
||||
+ // CPUID.1A.EAX[31-24]
|
||||
+ u32 intel_type :8;
|
||||
+ };
|
||||
+ struct {
|
||||
+ // CPUID 0x80000026.EBX
|
||||
+ u32 amd_num_processors :16,
|
||||
+ amd_power_eff_ranking :8,
|
||||
+ amd_native_model_id :4,
|
||||
+ amd_type :4;
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
|
||||
struct cpuinfo_x86 {
|
||||
--- a/arch/x86/include/asm/topology.h
|
||||
+++ b/arch/x86/include/asm/topology.h
|
||||
@@ -114,6 +114,12 @@ enum x86_topology_domains {
|
||||
TOPO_MAX_DOMAIN,
|
||||
};
|
||||
|
||||
+enum x86_topology_cpu_type {
|
||||
+ TOPO_CPU_TYPE_PERFORMANCE,
|
||||
+ TOPO_CPU_TYPE_EFFICIENCY,
|
||||
+ TOPO_CPU_TYPE_UNKNOWN,
|
||||
+};
|
||||
+
|
||||
struct x86_topology_system {
|
||||
unsigned int dom_shifts[TOPO_MAX_DOMAIN];
|
||||
unsigned int dom_size[TOPO_MAX_DOMAIN];
|
||||
@@ -149,6 +155,9 @@ extern unsigned int __max_threads_per_co
|
||||
extern unsigned int __num_threads_per_package;
|
||||
extern unsigned int __num_cores_per_package;
|
||||
|
||||
+const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c);
|
||||
+enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c);
|
||||
+
|
||||
static inline unsigned int topology_max_packages(void)
|
||||
{
|
||||
return __max_logical_packages;
|
||||
--- a/arch/x86/kernel/cpu/debugfs.c
|
||||
+++ b/arch/x86/kernel/cpu/debugfs.c
|
||||
@@ -22,6 +22,7 @@ static int cpu_debug_show(struct seq_fil
|
||||
seq_printf(m, "die_id: %u\n", c->topo.die_id);
|
||||
seq_printf(m, "cu_id: %u\n", c->topo.cu_id);
|
||||
seq_printf(m, "core_id: %u\n", c->topo.core_id);
|
||||
+ seq_printf(m, "cpu_type: %s\n", get_topology_cpu_type_name(c));
|
||||
seq_printf(m, "logical_pkg_id: %u\n", c->topo.logical_pkg_id);
|
||||
seq_printf(m, "logical_die_id: %u\n", c->topo.logical_die_id);
|
||||
seq_printf(m, "llc_id: %u\n", c->topo.llc_id);
|
||||
--- a/arch/x86/kernel/cpu/topology_amd.c
|
||||
+++ b/arch/x86/kernel/cpu/topology_amd.c
|
||||
@@ -182,6 +182,9 @@ static void parse_topology_amd(struct to
|
||||
if (cpu_feature_enabled(X86_FEATURE_TOPOEXT))
|
||||
has_topoext = cpu_parse_topology_ext(tscan);
|
||||
|
||||
+ if (cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES))
|
||||
+ tscan->c->topo.cpu_type = cpuid_ebx(0x80000026);
|
||||
+
|
||||
if (!has_topoext && !parse_8000_0008(tscan))
|
||||
return;
|
||||
|
||||
--- a/arch/x86/kernel/cpu/topology_common.c
|
||||
+++ b/arch/x86/kernel/cpu/topology_common.c
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <xen/xen.h>
|
||||
|
||||
+#include <asm/intel-family.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/smp.h>
|
||||
@@ -27,6 +28,36 @@ void topology_set_dom(struct topo_scan *
|
||||
}
|
||||
}
|
||||
|
||||
+enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c)
|
||||
+{
|
||||
+ if (c->x86_vendor == X86_VENDOR_INTEL) {
|
||||
+ switch (c->topo.intel_type) {
|
||||
+ case INTEL_CPU_TYPE_ATOM: return TOPO_CPU_TYPE_EFFICIENCY;
|
||||
+ case INTEL_CPU_TYPE_CORE: return TOPO_CPU_TYPE_PERFORMANCE;
|
||||
+ }
|
||||
+ }
|
||||
+ if (c->x86_vendor == X86_VENDOR_AMD) {
|
||||
+ switch (c->topo.amd_type) {
|
||||
+ case 0: return TOPO_CPU_TYPE_PERFORMANCE;
|
||||
+ case 1: return TOPO_CPU_TYPE_EFFICIENCY;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return TOPO_CPU_TYPE_UNKNOWN;
|
||||
+}
|
||||
+
|
||||
+const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c)
|
||||
+{
|
||||
+ switch (get_topology_cpu_type(c)) {
|
||||
+ case TOPO_CPU_TYPE_PERFORMANCE:
|
||||
+ return "performance";
|
||||
+ case TOPO_CPU_TYPE_EFFICIENCY:
|
||||
+ return "efficiency";
|
||||
+ default:
|
||||
+ return "unknown";
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static unsigned int __maybe_unused parse_num_cores_legacy(struct cpuinfo_x86 *c)
|
||||
{
|
||||
struct {
|
||||
@@ -87,6 +118,7 @@ static void parse_topology(struct topo_s
|
||||
.cu_id = 0xff,
|
||||
.llc_id = BAD_APICID,
|
||||
.l2c_id = BAD_APICID,
|
||||
+ .cpu_type = TOPO_CPU_TYPE_UNKNOWN,
|
||||
};
|
||||
struct cpuinfo_x86 *c = tscan->c;
|
||||
struct {
|
||||
@@ -132,6 +164,8 @@ static void parse_topology(struct topo_s
|
||||
case X86_VENDOR_INTEL:
|
||||
if (!IS_ENABLED(CONFIG_CPU_SUP_INTEL) || !cpu_parse_topology_ext(tscan))
|
||||
parse_legacy(tscan);
|
||||
+ if (c->cpuid_level >= 0x1a)
|
||||
+ c->topo.cpu_type = cpuid_eax(0x1a);
|
||||
break;
|
||||
case X86_VENDOR_HYGON:
|
||||
if (IS_ENABLED(CONFIG_CPU_SUP_HYGON))
|
@@ -1,57 +0,0 @@
|
||||
From c4fde0d177bdb33912f450914d84d6432391a8b5 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Sat, 12 Oct 2024 12:45:16 -0500
|
||||
Subject: cpufreq/amd-pstate: Use nominal perf for limits when boost is
|
||||
disabled
|
||||
|
||||
When boost has been disabled the limit for perf should be nominal perf not
|
||||
the highest perf. Using the latter to do calculations will lead to
|
||||
incorrect values that are still above nominal.
|
||||
|
||||
Fixes: ad4caad58d91 ("cpufreq: amd-pstate: Merge amd_pstate_highest_perf_set() into amd_get_boost_ratio_numerator()")
|
||||
Reported-by: Peter Jung <ptr1337@cachyos.org>
|
||||
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219348
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 20 ++++++++++++++------
|
||||
1 file changed, 14 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -566,11 +566,16 @@ static int amd_pstate_verify(struct cpuf
|
||||
|
||||
static int amd_pstate_update_min_max_limit(struct cpufreq_policy *policy)
|
||||
{
|
||||
- u32 max_limit_perf, min_limit_perf, lowest_perf;
|
||||
+ u32 max_limit_perf, min_limit_perf, lowest_perf, max_perf;
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
|
||||
- max_limit_perf = div_u64(policy->max * cpudata->highest_perf, cpudata->max_freq);
|
||||
- min_limit_perf = div_u64(policy->min * cpudata->highest_perf, cpudata->max_freq);
|
||||
+ if (cpudata->boost_supported && !policy->boost_enabled)
|
||||
+ max_perf = READ_ONCE(cpudata->nominal_perf);
|
||||
+ else
|
||||
+ max_perf = READ_ONCE(cpudata->highest_perf);
|
||||
+
|
||||
+ max_limit_perf = div_u64(policy->max * max_perf, policy->cpuinfo.max_freq);
|
||||
+ min_limit_perf = div_u64(policy->min * max_perf, policy->cpuinfo.max_freq);
|
||||
|
||||
lowest_perf = READ_ONCE(cpudata->lowest_perf);
|
||||
if (min_limit_perf < lowest_perf)
|
||||
@@ -1504,10 +1509,13 @@ static int amd_pstate_epp_update_limit(s
|
||||
u64 value;
|
||||
s16 epp;
|
||||
|
||||
- max_perf = READ_ONCE(cpudata->highest_perf);
|
||||
+ if (cpudata->boost_supported && !policy->boost_enabled)
|
||||
+ max_perf = READ_ONCE(cpudata->nominal_perf);
|
||||
+ else
|
||||
+ max_perf = READ_ONCE(cpudata->highest_perf);
|
||||
min_perf = READ_ONCE(cpudata->lowest_perf);
|
||||
- max_limit_perf = div_u64(policy->max * cpudata->highest_perf, cpudata->max_freq);
|
||||
- min_limit_perf = div_u64(policy->min * cpudata->highest_perf, cpudata->max_freq);
|
||||
+ max_limit_perf = div_u64(policy->max * max_perf, policy->cpuinfo.max_freq);
|
||||
+ min_limit_perf = div_u64(policy->min * max_perf, policy->cpuinfo.max_freq);
|
||||
|
||||
if (min_limit_perf < min_perf)
|
||||
min_limit_perf = min_perf;
|
@@ -0,0 +1,71 @@
|
||||
From ab9618cbe5e3d55b09b59f5e18e890be80ca1076 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Fri, 25 Oct 2024 12:14:59 -0500
|
||||
Subject: x86/amd: Use heterogeneous core topology for identifying boost
|
||||
numerator
|
||||
|
||||
AMD heterogeneous designs include two types of cores:
|
||||
* Performance
|
||||
* Efficiency
|
||||
|
||||
Each core type has different highest performance values configured by the
|
||||
platform. Drivers such as `amd_pstate` need to identify the type of
|
||||
core to correctly set an appropriate boost numerator to calculate the
|
||||
maximum frequency.
|
||||
|
||||
X86_FEATURE_AMD_HETEROGENEOUS_CORES is used to identify whether the SoC
|
||||
supports heterogeneous core type by reading CPUID leaf Fn_0x80000026.
|
||||
|
||||
On performance cores the scaling factor of 196 is used. On efficiency
|
||||
cores the scaling factor is the value reported as the highest perf.
|
||||
Efficiency cores have the same preferred core rankings.
|
||||
|
||||
Tested-by: Eric Naim <dnaim@cachyos.org>
|
||||
Tested-by: Peter Jung <ptr1337@cachyos.org>
|
||||
Suggested-by: Perry Yuan <perry.yuan@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
arch/x86/kernel/acpi/cppc.c | 23 +++++++++++++++++++++++
|
||||
1 file changed, 23 insertions(+)
|
||||
|
||||
--- a/arch/x86/kernel/acpi/cppc.c
|
||||
+++ b/arch/x86/kernel/acpi/cppc.c
|
||||
@@ -239,8 +239,10 @@ EXPORT_SYMBOL_GPL(amd_detect_prefcore);
|
||||
*/
|
||||
int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator)
|
||||
{
|
||||
+ enum x86_topology_cpu_type core_type = get_topology_cpu_type(&cpu_data(cpu));
|
||||
bool prefcore;
|
||||
int ret;
|
||||
+ u32 tmp;
|
||||
|
||||
ret = amd_detect_prefcore(&prefcore);
|
||||
if (ret)
|
||||
@@ -266,6 +268,27 @@ int amd_get_boost_ratio_numerator(unsign
|
||||
break;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ /* detect if running on heterogeneous design */
|
||||
+ if (cpu_feature_enabled(X86_FEATURE_AMD_HETEROGENEOUS_CORES)) {
|
||||
+ switch (core_type) {
|
||||
+ case TOPO_CPU_TYPE_UNKNOWN:
|
||||
+ pr_warn("Undefined core type found for cpu %d\n", cpu);
|
||||
+ break;
|
||||
+ case TOPO_CPU_TYPE_PERFORMANCE:
|
||||
+ /* use the max scale for performance cores */
|
||||
+ *numerator = CPPC_HIGHEST_PERF_PERFORMANCE;
|
||||
+ return 0;
|
||||
+ case TOPO_CPU_TYPE_EFFICIENCY:
|
||||
+ /* use the highest perf value for efficiency cores */
|
||||
+ ret = amd_get_highest_perf(cpu, &tmp);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ *numerator = tmp;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
*numerator = CPPC_HIGHEST_PERF_PREFCORE;
|
||||
|
||||
return 0;
|
@@ -1,4 +1,4 @@
|
||||
From a4d255935a1ea6e4b10167df942ec641079bcdf7 Mon Sep 17 00:00:00 2001
|
||||
From f1a423d6cfc0888638642bea1b8ed5c64770888c Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Mon, 28 Oct 2024 09:55:41 -0500
|
||||
Subject: cpufreq/amd-pstate: Push adjust_perf vfunc init into cpu_init
|
||||
@@ -18,7 +18,7 @@ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1528,6 +1528,8 @@ static int amd_pstate_epp_cpu_init(struc
|
||||
@@ -1534,6 +1534,8 @@ static int amd_pstate_epp_cpu_init(struc
|
||||
WRITE_ONCE(cpudata->cppc_cap1_cached, value);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
return 0;
|
||||
|
||||
free_cpudata1:
|
||||
@@ -1887,8 +1889,6 @@ static int __init amd_pstate_init(void)
|
||||
@@ -1896,8 +1898,6 @@ static int __init amd_pstate_init(void)
|
||||
/* capability check */
|
||||
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
||||
pr_debug("AMD CPPC MSR based functionality is supported\n");
|
||||
@@ -35,4 +35,4 @@ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
- current_pstate_driver->adjust_perf = amd_pstate_adjust_perf;
|
||||
} else {
|
||||
pr_debug("AMD CPPC shared memory based functionality is supported\n");
|
||||
static_call_update(amd_pstate_enable, shmem_enable);
|
||||
static_call_update(amd_pstate_cppc_enable, shmem_cppc_enable);
|
@@ -0,0 +1,47 @@
|
||||
From 242ffb086a15c8aec549096a6ad96d186b670fa9 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Mon, 28 Oct 2024 09:55:42 -0500
|
||||
Subject: cpufreq/amd-pstate: Move registration after static function call
|
||||
update
|
||||
|
||||
On shared memory designs the static functions need to work before
|
||||
registration is done or the system can hang at bootup.
|
||||
|
||||
Move the registration later in amd_pstate_init() to solve this.
|
||||
|
||||
Fixes: e238968a2087 ("cpufreq/amd-pstate: Remove the redundant amd_pstate_set_driver() call")
|
||||
Reported-by: Klara Modin <klarasmodin@gmail.com>
|
||||
Closes: https://lore.kernel.org/linux-pm/cf9c146d-bacf-444e-92e2-15ebf513af96@gmail.com/#t
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 12 ++++++------
|
||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1889,12 +1889,6 @@ static int __init amd_pstate_init(void)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
- ret = amd_pstate_register_driver(cppc_state);
|
||||
- if (ret) {
|
||||
- pr_err("failed to register with return %d\n", ret);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
/* capability check */
|
||||
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
||||
pr_debug("AMD CPPC MSR based functionality is supported\n");
|
||||
@@ -1905,6 +1899,12 @@ static int __init amd_pstate_init(void)
|
||||
static_call_update(amd_pstate_update_perf, shmem_update_perf);
|
||||
}
|
||||
|
||||
+ ret = amd_pstate_register_driver(cppc_state);
|
||||
+ if (ret) {
|
||||
+ pr_err("failed to register with return %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
if (amd_pstate_prefcore) {
|
||||
ret = amd_detect_prefcore(&amd_pstate_prefcore);
|
||||
if (ret)
|
@@ -0,0 +1,152 @@
|
||||
From f6e6b4ebc5ef3ad05b291928d31f597210a2eb6e Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Wed, 4 Dec 2024 14:48:38 +0000
|
||||
Subject: cpufreq/amd-pstate: Convert the amd_pstate_get/set_epp() to static
|
||||
calls
|
||||
|
||||
MSR and shared memory based systems have different mechanisms to get and
|
||||
set the epp value. Split those mechanisms into different functions and
|
||||
assign them appropriately to the static calls at boot time. This eliminates
|
||||
the need for the "if(cpu_feature_enabled(X86_FEATURE_CPPC))" checks at
|
||||
runtime.
|
||||
|
||||
Also, propagate the error code from rdmsrl_on_cpu() and cppc_get_epp_perf()
|
||||
to *_get_epp()'s caller, instead of returning -EIO unconditionally.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 92 +++++++++++++++++++++++-------------
|
||||
1 file changed, 60 insertions(+), 32 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -210,26 +210,40 @@ static inline int get_mode_idx_from_str(
|
||||
static DEFINE_MUTEX(amd_pstate_limits_lock);
|
||||
static DEFINE_MUTEX(amd_pstate_driver_lock);
|
||||
|
||||
-static s16 amd_pstate_get_epp(struct amd_cpudata *cpudata, u64 cppc_req_cached)
|
||||
+static s16 msr_get_epp(struct amd_cpudata *cpudata, u64 cppc_req_cached)
|
||||
{
|
||||
u64 epp;
|
||||
int ret;
|
||||
|
||||
- if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
||||
- if (!cppc_req_cached) {
|
||||
- epp = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ,
|
||||
- &cppc_req_cached);
|
||||
- if (epp)
|
||||
- return epp;
|
||||
- }
|
||||
- epp = (cppc_req_cached >> 24) & 0xFF;
|
||||
- } else {
|
||||
- ret = cppc_get_epp_perf(cpudata->cpu, &epp);
|
||||
+ if (!cppc_req_cached) {
|
||||
+ ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &cppc_req_cached);
|
||||
if (ret < 0) {
|
||||
pr_debug("Could not retrieve energy perf value (%d)\n", ret);
|
||||
- return -EIO;
|
||||
+ return ret;
|
||||
}
|
||||
}
|
||||
+ epp = (cppc_req_cached >> 24) & 0xFF;
|
||||
+
|
||||
+ return (s16)epp;
|
||||
+}
|
||||
+
|
||||
+DEFINE_STATIC_CALL(amd_pstate_get_epp, msr_get_epp);
|
||||
+
|
||||
+static inline s16 amd_pstate_get_epp(struct amd_cpudata *cpudata, u64 cppc_req_cached)
|
||||
+{
|
||||
+ return static_call(amd_pstate_get_epp)(cpudata, cppc_req_cached);
|
||||
+}
|
||||
+
|
||||
+static s16 shmem_get_epp(struct amd_cpudata *cpudata, u64 dummy)
|
||||
+{
|
||||
+ u64 epp;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = cppc_get_epp_perf(cpudata->cpu, &epp);
|
||||
+ if (ret < 0) {
|
||||
+ pr_debug("Could not retrieve energy perf value (%d)\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
|
||||
return (s16)(epp & 0xff);
|
||||
}
|
||||
@@ -283,33 +297,45 @@ static inline void amd_pstate_update_per
|
||||
max_perf, fast_switch);
|
||||
}
|
||||
|
||||
-static int amd_pstate_set_epp(struct amd_cpudata *cpudata, u32 epp)
|
||||
+static int msr_set_epp(struct amd_cpudata *cpudata, u32 epp)
|
||||
{
|
||||
int ret;
|
||||
- struct cppc_perf_ctrls perf_ctrls;
|
||||
|
||||
- if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
||||
- u64 value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
+ u64 value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
|
||||
- value &= ~GENMASK_ULL(31, 24);
|
||||
- value |= (u64)epp << 24;
|
||||
- WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
-
|
||||
- ret = wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
|
||||
- if (!ret)
|
||||
- cpudata->epp_cached = epp;
|
||||
- } else {
|
||||
- amd_pstate_update_perf(cpudata, cpudata->min_limit_perf, 0U,
|
||||
- cpudata->max_limit_perf, false);
|
||||
+ value &= ~GENMASK_ULL(31, 24);
|
||||
+ value |= (u64)epp << 24;
|
||||
+ WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
|
||||
- perf_ctrls.energy_perf = epp;
|
||||
- ret = cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1);
|
||||
- if (ret) {
|
||||
- pr_debug("failed to set energy perf value (%d)\n", ret);
|
||||
- return ret;
|
||||
- }
|
||||
+ ret = wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
|
||||
+ if (!ret)
|
||||
cpudata->epp_cached = epp;
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+DEFINE_STATIC_CALL(amd_pstate_set_epp, msr_set_epp);
|
||||
+
|
||||
+static inline int amd_pstate_set_epp(struct amd_cpudata *cpudata, u32 epp)
|
||||
+{
|
||||
+ return static_call(amd_pstate_set_epp)(cpudata, epp);
|
||||
+}
|
||||
+
|
||||
+static int shmem_set_epp(struct amd_cpudata *cpudata, u32 epp)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct cppc_perf_ctrls perf_ctrls;
|
||||
+
|
||||
+ amd_pstate_update_perf(cpudata, cpudata->min_limit_perf, 0U,
|
||||
+ cpudata->max_limit_perf, false);
|
||||
+
|
||||
+ perf_ctrls.energy_perf = epp;
|
||||
+ ret = cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1);
|
||||
+ if (ret) {
|
||||
+ pr_debug("failed to set energy perf value (%d)\n", ret);
|
||||
+ return ret;
|
||||
}
|
||||
+ cpudata->epp_cached = epp;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1897,6 +1923,8 @@ static int __init amd_pstate_init(void)
|
||||
static_call_update(amd_pstate_cppc_enable, shmem_cppc_enable);
|
||||
static_call_update(amd_pstate_init_perf, shmem_init_perf);
|
||||
static_call_update(amd_pstate_update_perf, shmem_update_perf);
|
||||
+ static_call_update(amd_pstate_get_epp, shmem_get_epp);
|
||||
+ static_call_update(amd_pstate_set_epp, shmem_set_epp);
|
||||
}
|
||||
|
||||
ret = amd_pstate_register_driver(cppc_state);
|
@@ -1,228 +0,0 @@
|
||||
From 649d296be0c7f0df6e71b4fca25fdbe75cb3994e Mon Sep 17 00:00:00 2001
|
||||
From: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Date: Thu, 17 Oct 2024 17:03:11 +0200
|
||||
Subject: amd-pstate-6.11: update setting the minimum frequency to
|
||||
lowest_nonlinear_freq patchset to v3
|
||||
|
||||
Signed-off-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 67 +++++++++++++++++++++---------------
|
||||
drivers/cpufreq/amd-pstate.h | 4 +--
|
||||
drivers/cpufreq/cpufreq.c | 6 +---
|
||||
include/linux/cpufreq.h | 6 ----
|
||||
4 files changed, 43 insertions(+), 40 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -557,9 +557,28 @@ cpufreq_policy_put:
|
||||
cpufreq_cpu_put(policy);
|
||||
}
|
||||
|
||||
-static int amd_pstate_verify(struct cpufreq_policy_data *policy)
|
||||
+static int amd_pstate_verify(struct cpufreq_policy_data *policy_data)
|
||||
{
|
||||
- cpufreq_verify_within_cpu_limits(policy);
|
||||
+ /*
|
||||
+ * Initialize lower frequency limit (i.e.policy->min) with
|
||||
+ * lowest_nonlinear_frequency which is the most energy efficient
|
||||
+ * frequency. Override the initial value set by cpufreq core and
|
||||
+ * amd-pstate qos_requests.
|
||||
+ */
|
||||
+ if (policy_data->min == FREQ_QOS_MIN_DEFAULT_VALUE) {
|
||||
+ struct cpufreq_policy *policy = cpufreq_cpu_get(policy_data->cpu);
|
||||
+ struct amd_cpudata *cpudata;
|
||||
+
|
||||
+ if (!policy)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ cpudata = policy->driver_data;
|
||||
+ policy_data->min = cpudata->lowest_nonlinear_freq;
|
||||
+ cpufreq_cpu_put(policy);
|
||||
+ }
|
||||
+
|
||||
+ cpufreq_verify_within_cpu_limits(policy_data);
|
||||
+ pr_debug("policy_max =%d, policy_min=%d\n", policy_data->max, policy_data->min);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -709,7 +728,7 @@ static int amd_pstate_cpu_boost_update(s
|
||||
policy->max = policy->cpuinfo.max_freq;
|
||||
|
||||
if (cppc_state == AMD_PSTATE_PASSIVE) {
|
||||
- ret = freq_qos_update_request(&cpudata->max_freq_req, policy->cpuinfo.max_freq);
|
||||
+ 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);
|
||||
}
|
||||
@@ -976,17 +995,17 @@ static int amd_pstate_cpu_init(struct cp
|
||||
|
||||
ret = amd_pstate_init_perf(cpudata);
|
||||
if (ret)
|
||||
- goto free_cpudata;
|
||||
+ goto free_cpudata1;
|
||||
|
||||
amd_pstate_init_prefcore(cpudata);
|
||||
|
||||
ret = amd_pstate_init_freq(cpudata);
|
||||
if (ret)
|
||||
- goto free_cpudata;
|
||||
+ goto free_cpudata1;
|
||||
|
||||
ret = amd_pstate_init_boost_support(cpudata);
|
||||
if (ret)
|
||||
- goto free_cpudata;
|
||||
+ goto free_cpudata1;
|
||||
|
||||
min_freq = READ_ONCE(cpudata->min_freq);
|
||||
max_freq = READ_ONCE(cpudata->max_freq);
|
||||
@@ -1008,11 +1027,18 @@ static int amd_pstate_cpu_init(struct cp
|
||||
if (cpu_feature_enabled(X86_FEATURE_CPPC))
|
||||
policy->fast_switch_possible = true;
|
||||
|
||||
- ret = freq_qos_add_request(&policy->constraints, &cpudata->max_freq_req,
|
||||
+ ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0],
|
||||
+ FREQ_QOS_MIN, FREQ_QOS_MIN_DEFAULT_VALUE);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(dev, "Failed to add min-freq constraint (%d)\n", ret);
|
||||
+ goto free_cpudata1;
|
||||
+ }
|
||||
+
|
||||
+ ret = freq_qos_add_request(&policy->constraints, &cpudata->req[1],
|
||||
FREQ_QOS_MAX, policy->cpuinfo.max_freq);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to add max-freq constraint (%d)\n", ret);
|
||||
- goto free_cpudata;
|
||||
+ goto free_cpudata2;
|
||||
}
|
||||
|
||||
cpudata->max_limit_freq = max_freq;
|
||||
@@ -1025,7 +1051,9 @@ static int amd_pstate_cpu_init(struct cp
|
||||
|
||||
return 0;
|
||||
|
||||
-free_cpudata:
|
||||
+free_cpudata2:
|
||||
+ freq_qos_remove_request(&cpudata->req[0]);
|
||||
+free_cpudata1:
|
||||
kfree(cpudata);
|
||||
return ret;
|
||||
}
|
||||
@@ -1034,7 +1062,8 @@ static void amd_pstate_cpu_exit(struct c
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
|
||||
- freq_qos_remove_request(&cpudata->max_freq_req);
|
||||
+ freq_qos_remove_request(&cpudata->req[1]);
|
||||
+ freq_qos_remove_request(&cpudata->req[0]);
|
||||
policy->fast_switch_possible = false;
|
||||
kfree(cpudata);
|
||||
}
|
||||
@@ -1658,13 +1687,6 @@ static int amd_pstate_epp_cpu_offline(st
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int amd_pstate_epp_verify_policy(struct cpufreq_policy_data *policy)
|
||||
-{
|
||||
- cpufreq_verify_within_cpu_limits(policy);
|
||||
- pr_debug("policy_max =%d, policy_min=%d\n", policy->max, policy->min);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int amd_pstate_epp_suspend(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
@@ -1703,13 +1725,6 @@ static int amd_pstate_epp_resume(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int amd_pstate_get_init_min_freq(struct cpufreq_policy *policy)
|
||||
-{
|
||||
- struct amd_cpudata *cpudata = policy->driver_data;
|
||||
-
|
||||
- return READ_ONCE(cpudata->lowest_nonlinear_freq);
|
||||
-}
|
||||
-
|
||||
static struct cpufreq_driver amd_pstate_driver = {
|
||||
.flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
|
||||
.verify = amd_pstate_verify,
|
||||
@@ -1723,12 +1738,11 @@ static struct cpufreq_driver amd_pstate_
|
||||
.update_limits = amd_pstate_update_limits,
|
||||
.name = "amd-pstate",
|
||||
.attr = amd_pstate_attr,
|
||||
- .get_init_min_freq = amd_pstate_get_init_min_freq,
|
||||
};
|
||||
|
||||
static struct cpufreq_driver amd_pstate_epp_driver = {
|
||||
.flags = CPUFREQ_CONST_LOOPS,
|
||||
- .verify = amd_pstate_epp_verify_policy,
|
||||
+ .verify = amd_pstate_verify,
|
||||
.setpolicy = amd_pstate_epp_set_policy,
|
||||
.init = amd_pstate_epp_cpu_init,
|
||||
.exit = amd_pstate_epp_cpu_exit,
|
||||
@@ -1740,7 +1754,6 @@ static struct cpufreq_driver amd_pstate_
|
||||
.set_boost = amd_pstate_set_boost,
|
||||
.name = "amd-pstate-epp",
|
||||
.attr = amd_pstate_epp_attr,
|
||||
- .get_init_min_freq = amd_pstate_get_init_min_freq,
|
||||
};
|
||||
|
||||
static int __init amd_pstate_set_driver(int mode_idx)
|
||||
--- a/drivers/cpufreq/amd-pstate.h
|
||||
+++ b/drivers/cpufreq/amd-pstate.h
|
||||
@@ -28,7 +28,7 @@ struct amd_aperf_mperf {
|
||||
/**
|
||||
* struct amd_cpudata - private CPU data for AMD P-State
|
||||
* @cpu: CPU number
|
||||
- * @max_freq_req: maximum frequency constraint request to apply
|
||||
+ * @req: constraint request to apply
|
||||
* @cppc_req_cached: cached performance request hints
|
||||
* @highest_perf: the maximum performance an individual processor may reach,
|
||||
* assuming ideal conditions
|
||||
@@ -68,7 +68,7 @@ struct amd_aperf_mperf {
|
||||
struct amd_cpudata {
|
||||
int cpu;
|
||||
|
||||
- struct freq_qos_request max_freq_req;
|
||||
+ struct freq_qos_request req[2];
|
||||
u64 cppc_req_cached;
|
||||
|
||||
u32 highest_perf;
|
||||
--- a/drivers/cpufreq/cpufreq.c
|
||||
+++ b/drivers/cpufreq/cpufreq.c
|
||||
@@ -1380,7 +1380,6 @@ static int cpufreq_online(unsigned int c
|
||||
bool new_policy;
|
||||
unsigned long flags;
|
||||
unsigned int j;
|
||||
- u32 init_min_freq = FREQ_QOS_MIN_DEFAULT_VALUE;
|
||||
int ret;
|
||||
|
||||
pr_debug("%s: bringing CPU%u online\n", __func__, cpu);
|
||||
@@ -1465,12 +1464,9 @@ static int cpufreq_online(unsigned int c
|
||||
goto out_destroy_policy;
|
||||
}
|
||||
|
||||
- if (cpufreq_driver->get_init_min_freq)
|
||||
- init_min_freq = cpufreq_driver->get_init_min_freq(policy);
|
||||
-
|
||||
ret = freq_qos_add_request(&policy->constraints,
|
||||
policy->min_freq_req, FREQ_QOS_MIN,
|
||||
- init_min_freq);
|
||||
+ FREQ_QOS_MIN_DEFAULT_VALUE);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* So we don't call freq_qos_remove_request() for an
|
||||
--- a/include/linux/cpufreq.h
|
||||
+++ b/include/linux/cpufreq.h
|
||||
@@ -414,12 +414,6 @@ struct cpufreq_driver {
|
||||
* policy is properly initialized, but before the governor is started.
|
||||
*/
|
||||
void (*register_em)(struct cpufreq_policy *policy);
|
||||
-
|
||||
- /*
|
||||
- * Set by drivers that want to initialize the policy->min_freq_req with
|
||||
- * a value different from the default value (0) in cpufreq core.
|
||||
- */
|
||||
- int (*get_init_min_freq)(struct cpufreq_policy *policy);
|
||||
};
|
||||
|
||||
/* flags */
|
@@ -0,0 +1,38 @@
|
||||
From e73d7f9cb6d8f0e79860788371c88f88057ae34b Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Wed, 4 Dec 2024 14:48:39 +0000
|
||||
Subject: cpufreq/amd-pstate: Move the invocation of amd_pstate_update_perf()
|
||||
|
||||
amd_pstate_update_perf() should not be a part of shmem_set_epp() function,
|
||||
so move it to the amd_pstate_epp_update_limit() function, where it is needed.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -326,9 +326,6 @@ static int shmem_set_epp(struct amd_cpud
|
||||
int ret;
|
||||
struct cppc_perf_ctrls perf_ctrls;
|
||||
|
||||
- amd_pstate_update_perf(cpudata, cpudata->min_limit_perf, 0U,
|
||||
- cpudata->max_limit_perf, false);
|
||||
-
|
||||
perf_ctrls.energy_perf = epp;
|
||||
ret = cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1);
|
||||
if (ret) {
|
||||
@@ -1628,6 +1625,10 @@ static int amd_pstate_epp_update_limit(s
|
||||
epp = 0;
|
||||
|
||||
WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
+
|
||||
+ amd_pstate_update_perf(cpudata, cpudata->min_limit_perf, 0U,
|
||||
+ cpudata->max_limit_perf, false);
|
||||
+
|
||||
return amd_pstate_set_epp(cpudata, epp);
|
||||
}
|
||||
|
@@ -0,0 +1,82 @@
|
||||
From 021028e977fcd835ed92a4543f7977a8aa0c1dd6 Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Wed, 4 Dec 2024 14:48:40 +0000
|
||||
Subject: cpufreq/amd-pstate: Refactor amd_pstate_epp_reenable() and
|
||||
amd_pstate_epp_offline()
|
||||
|
||||
Replace similar code chunks with amd_pstate_update_perf() and
|
||||
amd_pstate_set_epp() function calls.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 38 +++++++-----------------------------
|
||||
1 file changed, 7 insertions(+), 31 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1660,25 +1660,17 @@ static int amd_pstate_epp_set_policy(str
|
||||
|
||||
static void amd_pstate_epp_reenable(struct amd_cpudata *cpudata)
|
||||
{
|
||||
- struct cppc_perf_ctrls perf_ctrls;
|
||||
- u64 value, max_perf;
|
||||
+ u64 max_perf;
|
||||
int ret;
|
||||
|
||||
ret = amd_pstate_cppc_enable(true);
|
||||
if (ret)
|
||||
pr_err("failed to enable amd pstate during resume, return %d\n", ret);
|
||||
|
||||
- value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
max_perf = READ_ONCE(cpudata->highest_perf);
|
||||
|
||||
- if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
||||
- wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
|
||||
- } else {
|
||||
- perf_ctrls.max_perf = max_perf;
|
||||
- cppc_set_perf(cpudata->cpu, &perf_ctrls);
|
||||
- perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(cpudata->epp_cached);
|
||||
- cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1);
|
||||
- }
|
||||
+ amd_pstate_update_perf(cpudata, 0, 0, max_perf, false);
|
||||
+ amd_pstate_set_epp(cpudata, cpudata->epp_cached);
|
||||
}
|
||||
|
||||
static int amd_pstate_epp_cpu_online(struct cpufreq_policy *policy)
|
||||
@@ -1698,31 +1690,15 @@ static int amd_pstate_epp_cpu_online(str
|
||||
static void amd_pstate_epp_offline(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
- struct cppc_perf_ctrls perf_ctrls;
|
||||
int min_perf;
|
||||
- u64 value;
|
||||
|
||||
min_perf = READ_ONCE(cpudata->lowest_perf);
|
||||
- value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
|
||||
mutex_lock(&amd_pstate_limits_lock);
|
||||
- if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
||||
- cpudata->epp_policy = CPUFREQ_POLICY_UNKNOWN;
|
||||
|
||||
- /* Set max perf same as min perf */
|
||||
- value &= ~AMD_CPPC_MAX_PERF(~0L);
|
||||
- value |= AMD_CPPC_MAX_PERF(min_perf);
|
||||
- value &= ~AMD_CPPC_MIN_PERF(~0L);
|
||||
- value |= AMD_CPPC_MIN_PERF(min_perf);
|
||||
- wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
|
||||
- } else {
|
||||
- perf_ctrls.desired_perf = 0;
|
||||
- perf_ctrls.min_perf = min_perf;
|
||||
- perf_ctrls.max_perf = min_perf;
|
||||
- cppc_set_perf(cpudata->cpu, &perf_ctrls);
|
||||
- perf_ctrls.energy_perf = AMD_CPPC_ENERGY_PERF_PREF(HWP_EPP_BALANCE_POWERSAVE);
|
||||
- cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1);
|
||||
- }
|
||||
+ amd_pstate_update_perf(cpudata, min_perf, 0, min_perf, false);
|
||||
+ amd_pstate_set_epp(cpudata, AMD_CPPC_EPP_BALANCE_POWERSAVE);
|
||||
+
|
||||
mutex_unlock(&amd_pstate_limits_lock);
|
||||
}
|
||||
|
@@ -0,0 +1,43 @@
|
||||
From f94f6415c70f76d885dd542e8631f826f427941e Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Wed, 4 Dec 2024 14:48:41 +0000
|
||||
Subject: cpufreq/amd-pstate: Remove the cppc_state check in offline/online
|
||||
functions
|
||||
|
||||
Only amd_pstate_epp driver (i.e. cppc_state = ACTIVE) enters the
|
||||
amd_pstate_epp_offline() and amd_pstate_epp_cpu_online() functions,
|
||||
so remove the unnecessary if condition checking if cppc_state is
|
||||
equal to AMD_PSTATE_ACTIVE.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 9 +++------
|
||||
1 file changed, 3 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1679,10 +1679,8 @@ static int amd_pstate_epp_cpu_online(str
|
||||
|
||||
pr_debug("AMD CPU Core %d going online\n", cpudata->cpu);
|
||||
|
||||
- if (cppc_state == AMD_PSTATE_ACTIVE) {
|
||||
- amd_pstate_epp_reenable(cpudata);
|
||||
- cpudata->suspended = false;
|
||||
- }
|
||||
+ amd_pstate_epp_reenable(cpudata);
|
||||
+ cpudata->suspended = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1711,8 +1709,7 @@ static int amd_pstate_epp_cpu_offline(st
|
||||
if (cpudata->suspended)
|
||||
return 0;
|
||||
|
||||
- if (cppc_state == AMD_PSTATE_ACTIVE)
|
||||
- amd_pstate_epp_offline(policy);
|
||||
+ amd_pstate_epp_offline(policy);
|
||||
|
||||
return 0;
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
From 5aea3e8c4255cb04876e3af714d58ed329376b7f Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Wed, 4 Dec 2024 14:48:42 +0000
|
||||
Subject: cpufreq/amd-pstate: Merge amd_pstate_epp_cpu_offline() and
|
||||
amd_pstate_epp_offline()
|
||||
|
||||
amd_pstate_epp_offline() is only called from within
|
||||
amd_pstate_epp_cpu_offline() and doesn't make much sense to have it at all.
|
||||
Hence, remove it.
|
||||
|
||||
Also remove the unncessary debug print in the offline path while at it.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 17 ++++-------------
|
||||
1 file changed, 4 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1685,11 +1685,14 @@ static int amd_pstate_epp_cpu_online(str
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void amd_pstate_epp_offline(struct cpufreq_policy *policy)
|
||||
+static int amd_pstate_epp_cpu_offline(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
int min_perf;
|
||||
|
||||
+ if (cpudata->suspended)
|
||||
+ return 0;
|
||||
+
|
||||
min_perf = READ_ONCE(cpudata->lowest_perf);
|
||||
|
||||
mutex_lock(&amd_pstate_limits_lock);
|
||||
@@ -1698,18 +1701,6 @@ static void amd_pstate_epp_offline(struc
|
||||
amd_pstate_set_epp(cpudata, AMD_CPPC_EPP_BALANCE_POWERSAVE);
|
||||
|
||||
mutex_unlock(&amd_pstate_limits_lock);
|
||||
-}
|
||||
-
|
||||
-static int amd_pstate_epp_cpu_offline(struct cpufreq_policy *policy)
|
||||
-{
|
||||
- struct amd_cpudata *cpudata = policy->driver_data;
|
||||
-
|
||||
- pr_debug("AMD CPU Core %d going offline\n", cpudata->cpu);
|
||||
-
|
||||
- if (cpudata->suspended)
|
||||
- return 0;
|
||||
-
|
||||
- amd_pstate_epp_offline(policy);
|
||||
|
||||
return 0;
|
||||
}
|
@@ -0,0 +1,132 @@
|
||||
From ea6b500eb38124a59e83254435340e0390117c54 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:33 -0600
|
||||
Subject: cpufreq/amd-pstate: Add trace event for EPP perf updates
|
||||
|
||||
In "active" mode the most important thing for debugging whether
|
||||
an issue is hardware or software based is to look at what was the
|
||||
last thing written to the CPPC request MSR or shared memory region.
|
||||
|
||||
The 'amd_pstate_epp_perf' trace event shows the values being written
|
||||
for all CPUs.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Perry Yuan <perry.yuan@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate-trace.h | 45 ++++++++++++++++++++++++++++++
|
||||
drivers/cpufreq/amd-pstate.c | 28 +++++++++++++++++++
|
||||
2 files changed, 73 insertions(+)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate-trace.h
|
||||
+++ b/drivers/cpufreq/amd-pstate-trace.h
|
||||
@@ -88,6 +88,51 @@ TRACE_EVENT(amd_pstate_perf,
|
||||
)
|
||||
);
|
||||
|
||||
+TRACE_EVENT(amd_pstate_epp_perf,
|
||||
+
|
||||
+ TP_PROTO(unsigned int cpu_id,
|
||||
+ unsigned int highest_perf,
|
||||
+ unsigned int epp,
|
||||
+ unsigned int min_perf,
|
||||
+ unsigned int max_perf,
|
||||
+ bool boost
|
||||
+ ),
|
||||
+
|
||||
+ TP_ARGS(cpu_id,
|
||||
+ highest_perf,
|
||||
+ epp,
|
||||
+ min_perf,
|
||||
+ max_perf,
|
||||
+ boost),
|
||||
+
|
||||
+ TP_STRUCT__entry(
|
||||
+ __field(unsigned int, cpu_id)
|
||||
+ __field(unsigned int, highest_perf)
|
||||
+ __field(unsigned int, epp)
|
||||
+ __field(unsigned int, min_perf)
|
||||
+ __field(unsigned int, max_perf)
|
||||
+ __field(bool, boost)
|
||||
+ ),
|
||||
+
|
||||
+ TP_fast_assign(
|
||||
+ __entry->cpu_id = cpu_id;
|
||||
+ __entry->highest_perf = highest_perf;
|
||||
+ __entry->epp = epp;
|
||||
+ __entry->min_perf = min_perf;
|
||||
+ __entry->max_perf = max_perf;
|
||||
+ __entry->boost = boost;
|
||||
+ ),
|
||||
+
|
||||
+ TP_printk("cpu%u: [%u<->%u]/%u, epp=%u, boost=%u",
|
||||
+ (unsigned int)__entry->cpu_id,
|
||||
+ (unsigned int)__entry->min_perf,
|
||||
+ (unsigned int)__entry->max_perf,
|
||||
+ (unsigned int)__entry->highest_perf,
|
||||
+ (unsigned int)__entry->epp,
|
||||
+ (bool)__entry->boost
|
||||
+ )
|
||||
+);
|
||||
+
|
||||
#endif /* _AMD_PSTATE_TRACE_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -354,6 +354,14 @@ static int amd_pstate_set_energy_pref_in
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
+ if (trace_amd_pstate_epp_perf_enabled()) {
|
||||
+ trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf,
|
||||
+ epp,
|
||||
+ AMD_CPPC_MIN_PERF(cpudata->cppc_req_cached),
|
||||
+ AMD_CPPC_MAX_PERF(cpudata->cppc_req_cached),
|
||||
+ cpudata->boost_state);
|
||||
+ }
|
||||
+
|
||||
ret = amd_pstate_set_epp(cpudata, epp);
|
||||
|
||||
return ret;
|
||||
@@ -1626,6 +1634,13 @@ static int amd_pstate_epp_update_limit(s
|
||||
|
||||
WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
|
||||
+ if (trace_amd_pstate_epp_perf_enabled()) {
|
||||
+ trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf, epp,
|
||||
+ cpudata->min_limit_perf,
|
||||
+ cpudata->max_limit_perf,
|
||||
+ cpudata->boost_state);
|
||||
+ }
|
||||
+
|
||||
amd_pstate_update_perf(cpudata, cpudata->min_limit_perf, 0U,
|
||||
cpudata->max_limit_perf, false);
|
||||
|
||||
@@ -1669,6 +1684,13 @@ static void amd_pstate_epp_reenable(stru
|
||||
|
||||
max_perf = READ_ONCE(cpudata->highest_perf);
|
||||
|
||||
+ if (trace_amd_pstate_epp_perf_enabled()) {
|
||||
+ trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf,
|
||||
+ cpudata->epp_cached,
|
||||
+ AMD_CPPC_MIN_PERF(cpudata->cppc_req_cached),
|
||||
+ max_perf, cpudata->boost_state);
|
||||
+ }
|
||||
+
|
||||
amd_pstate_update_perf(cpudata, 0, 0, max_perf, false);
|
||||
amd_pstate_set_epp(cpudata, cpudata->epp_cached);
|
||||
}
|
||||
@@ -1697,6 +1719,12 @@ static int amd_pstate_epp_cpu_offline(st
|
||||
|
||||
mutex_lock(&amd_pstate_limits_lock);
|
||||
|
||||
+ if (trace_amd_pstate_epp_perf_enabled()) {
|
||||
+ trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf,
|
||||
+ AMD_CPPC_EPP_BALANCE_POWERSAVE,
|
||||
+ min_perf, min_perf, cpudata->boost_state);
|
||||
+ }
|
||||
+
|
||||
amd_pstate_update_perf(cpudata, min_perf, 0, min_perf, false);
|
||||
amd_pstate_set_epp(cpudata, AMD_CPPC_EPP_BALANCE_POWERSAVE);
|
||||
|
123
debian/patches/patchset-pf/amd-pstate/0031-cpufreq-amd-pstate-convert-mutex-use-to-guard.patch
vendored
Normal file
123
debian/patches/patchset-pf/amd-pstate/0031-cpufreq-amd-pstate-convert-mutex-use-to-guard.patch
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
From 57fdcf14dcd80808fc46edea6d31bb2a699c0fd1 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:34 -0600
|
||||
Subject: cpufreq/amd-pstate: convert mutex use to guard()
|
||||
|
||||
Using scoped guard declaration will unlock mutexes automatically.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 32 ++++++++++++--------------------
|
||||
1 file changed, 12 insertions(+), 20 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -782,12 +782,12 @@ static int amd_pstate_set_boost(struct c
|
||||
pr_err("Boost mode is not supported by this processor or SBIOS\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
- mutex_lock(&amd_pstate_driver_lock);
|
||||
+ guard(mutex)(&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);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -878,7 +878,8 @@ static void amd_pstate_update_limits(uns
|
||||
if (!amd_pstate_prefcore)
|
||||
return;
|
||||
|
||||
- mutex_lock(&amd_pstate_driver_lock);
|
||||
+ guard(mutex)(&amd_pstate_driver_lock);
|
||||
+
|
||||
ret = amd_get_highest_perf(cpu, &cur_high);
|
||||
if (ret)
|
||||
goto free_cpufreq_put;
|
||||
@@ -898,7 +899,6 @@ free_cpufreq_put:
|
||||
if (!highest_perf_changed)
|
||||
cpufreq_update_policy(cpu);
|
||||
|
||||
- mutex_unlock(&amd_pstate_driver_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1231,11 +1231,11 @@ static ssize_t store_energy_performance_
|
||||
if (ret < 0)
|
||||
return -EINVAL;
|
||||
|
||||
- mutex_lock(&amd_pstate_limits_lock);
|
||||
+ guard(mutex)(&amd_pstate_limits_lock);
|
||||
+
|
||||
ret = amd_pstate_set_energy_pref_index(cpudata, ret);
|
||||
- mutex_unlock(&amd_pstate_limits_lock);
|
||||
|
||||
- return ret ?: count;
|
||||
+ return ret ? ret : count;
|
||||
}
|
||||
|
||||
static ssize_t show_energy_performance_preference(
|
||||
@@ -1399,13 +1399,10 @@ EXPORT_SYMBOL_GPL(amd_pstate_update_stat
|
||||
static ssize_t status_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
- ssize_t ret;
|
||||
|
||||
- mutex_lock(&amd_pstate_driver_lock);
|
||||
- ret = amd_pstate_show_status(buf);
|
||||
- mutex_unlock(&amd_pstate_driver_lock);
|
||||
+ guard(mutex)(&amd_pstate_driver_lock);
|
||||
|
||||
- return ret;
|
||||
+ return amd_pstate_show_status(buf);
|
||||
}
|
||||
|
||||
static ssize_t status_store(struct device *a, struct device_attribute *b,
|
||||
@@ -1414,9 +1411,8 @@ static ssize_t status_store(struct devic
|
||||
char *p = memchr(buf, '\n', count);
|
||||
int ret;
|
||||
|
||||
- mutex_lock(&amd_pstate_driver_lock);
|
||||
+ guard(mutex)(&amd_pstate_driver_lock);
|
||||
ret = amd_pstate_update_status(buf, p ? p - buf : count);
|
||||
- mutex_unlock(&amd_pstate_driver_lock);
|
||||
|
||||
return ret < 0 ? ret : count;
|
||||
}
|
||||
@@ -1717,7 +1713,7 @@ static int amd_pstate_epp_cpu_offline(st
|
||||
|
||||
min_perf = READ_ONCE(cpudata->lowest_perf);
|
||||
|
||||
- mutex_lock(&amd_pstate_limits_lock);
|
||||
+ guard(mutex)(&amd_pstate_limits_lock);
|
||||
|
||||
if (trace_amd_pstate_epp_perf_enabled()) {
|
||||
trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf,
|
||||
@@ -1728,8 +1724,6 @@ static int amd_pstate_epp_cpu_offline(st
|
||||
amd_pstate_update_perf(cpudata, min_perf, 0, min_perf, false);
|
||||
amd_pstate_set_epp(cpudata, AMD_CPPC_EPP_BALANCE_POWERSAVE);
|
||||
|
||||
- mutex_unlock(&amd_pstate_limits_lock);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1758,13 +1752,11 @@ static int amd_pstate_epp_resume(struct
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
|
||||
if (cpudata->suspended) {
|
||||
- mutex_lock(&amd_pstate_limits_lock);
|
||||
+ guard(mutex)(&amd_pstate_limits_lock);
|
||||
|
||||
/* enable amd pstate from suspend state*/
|
||||
amd_pstate_epp_reenable(cpudata);
|
||||
|
||||
- mutex_unlock(&amd_pstate_limits_lock);
|
||||
-
|
||||
cpudata->suspended = false;
|
||||
}
|
||||
|
@@ -0,0 +1,52 @@
|
||||
From 06c52df851256238253ec286682cafbd5bb832d8 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:35 -0600
|
||||
Subject: cpufreq/amd-pstate: Drop cached epp_policy variable
|
||||
|
||||
epp_policy is not used by any of the current code and there
|
||||
is no need to cache it.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 3 ---
|
||||
drivers/cpufreq/amd-pstate.h | 2 --
|
||||
2 files changed, 5 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1506,7 +1506,6 @@ static int amd_pstate_epp_cpu_init(struc
|
||||
return -ENOMEM;
|
||||
|
||||
cpudata->cpu = policy->cpu;
|
||||
- cpudata->epp_policy = 0;
|
||||
|
||||
ret = amd_pstate_init_perf(cpudata);
|
||||
if (ret)
|
||||
@@ -1613,8 +1612,6 @@ static int amd_pstate_epp_update_limit(s
|
||||
value &= ~AMD_CPPC_DES_PERF(~0L);
|
||||
value |= AMD_CPPC_DES_PERF(0);
|
||||
|
||||
- cpudata->epp_policy = cpudata->policy;
|
||||
-
|
||||
/* Get BIOS pre-defined epp value */
|
||||
epp = amd_pstate_get_epp(cpudata, value);
|
||||
if (epp < 0) {
|
||||
--- a/drivers/cpufreq/amd-pstate.h
|
||||
+++ b/drivers/cpufreq/amd-pstate.h
|
||||
@@ -57,7 +57,6 @@ struct amd_aperf_mperf {
|
||||
* @hw_prefcore: check whether HW supports preferred core featue.
|
||||
* Only when hw_prefcore and early prefcore param are true,
|
||||
* AMD P-State driver supports preferred core featue.
|
||||
- * @epp_policy: Last saved policy used to set energy-performance preference
|
||||
* @epp_cached: Cached CPPC energy-performance preference value
|
||||
* @policy: Cpufreq policy value
|
||||
* @cppc_cap1_cached Cached MSR_AMD_CPPC_CAP1 register value
|
||||
@@ -94,7 +93,6 @@ struct amd_cpudata {
|
||||
bool hw_prefcore;
|
||||
|
||||
/* EPP feature related attributes*/
|
||||
- s16 epp_policy;
|
||||
s16 epp_cached;
|
||||
u32 policy;
|
||||
u64 cppc_cap1_cached;
|
@@ -0,0 +1,117 @@
|
||||
From da3e84f3dd424c1b7fa6d86484ddcccac391e49c Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:36 -0600
|
||||
Subject: cpufreq/amd-pstate: Use FIELD_PREP and FIELD_GET macros
|
||||
|
||||
The FIELD_PREP and FIELD_GET macros improve readability and help
|
||||
to avoid shifting bugs.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 45 ++++++++++++++++--------------------
|
||||
1 file changed, 20 insertions(+), 25 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
+#include <linux/bitfield.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
@@ -88,6 +89,11 @@ static bool cppc_enabled;
|
||||
static bool amd_pstate_prefcore = true;
|
||||
static struct quirk_entry *quirks;
|
||||
|
||||
+#define AMD_PSTATE_MAX_PERF_MASK GENMASK(7, 0)
|
||||
+#define AMD_PSTATE_MIN_PERF_MASK GENMASK(15, 8)
|
||||
+#define AMD_PSTATE_DES_PERF_MASK GENMASK(23, 16)
|
||||
+#define AMD_PSTATE_EPP_PERF_MASK GENMASK(31, 24)
|
||||
+
|
||||
/*
|
||||
* AMD Energy Preference Performance (EPP)
|
||||
* The EPP is used in the CCLK DPM controller to drive
|
||||
@@ -212,7 +218,6 @@ static DEFINE_MUTEX(amd_pstate_driver_lo
|
||||
|
||||
static s16 msr_get_epp(struct amd_cpudata *cpudata, u64 cppc_req_cached)
|
||||
{
|
||||
- u64 epp;
|
||||
int ret;
|
||||
|
||||
if (!cppc_req_cached) {
|
||||
@@ -222,9 +227,8 @@ static s16 msr_get_epp(struct amd_cpudat
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
- epp = (cppc_req_cached >> 24) & 0xFF;
|
||||
|
||||
- return (s16)epp;
|
||||
+ return FIELD_GET(AMD_PSTATE_EPP_PERF_MASK, cppc_req_cached);
|
||||
}
|
||||
|
||||
DEFINE_STATIC_CALL(amd_pstate_get_epp, msr_get_epp);
|
||||
@@ -299,12 +303,11 @@ static inline void amd_pstate_update_per
|
||||
|
||||
static int msr_set_epp(struct amd_cpudata *cpudata, u32 epp)
|
||||
{
|
||||
- int ret;
|
||||
-
|
||||
u64 value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
+ int ret;
|
||||
|
||||
- value &= ~GENMASK_ULL(31, 24);
|
||||
- value |= (u64)epp << 24;
|
||||
+ value &= ~AMD_PSTATE_EPP_PERF_MASK;
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_EPP_PERF_MASK, epp);
|
||||
WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
|
||||
ret = wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
|
||||
@@ -563,18 +566,15 @@ static void amd_pstate_update(struct amd
|
||||
des_perf = 0;
|
||||
}
|
||||
|
||||
- value &= ~AMD_CPPC_MIN_PERF(~0L);
|
||||
- value |= AMD_CPPC_MIN_PERF(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);
|
||||
+ value &= ~(AMD_PSTATE_MAX_PERF_MASK | AMD_PSTATE_MIN_PERF_MASK |
|
||||
+ AMD_PSTATE_DES_PERF_MASK);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_MAX_PERF_MASK, max_perf);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_DES_PERF_MASK, des_perf);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_MIN_PERF_MASK, min_perf);
|
||||
|
||||
if (trace_amd_pstate_perf_enabled() && amd_pstate_sample(cpudata)) {
|
||||
trace_amd_pstate_perf(min_perf, des_perf, max_perf, cpudata->freq,
|
||||
@@ -1601,16 +1601,11 @@ static int amd_pstate_epp_update_limit(s
|
||||
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
|
||||
min_perf = min(cpudata->nominal_perf, max_perf);
|
||||
|
||||
- /* Initial min/max values for CPPC Performance Controls Register */
|
||||
- value &= ~AMD_CPPC_MIN_PERF(~0L);
|
||||
- value |= AMD_CPPC_MIN_PERF(min_perf);
|
||||
-
|
||||
- value &= ~AMD_CPPC_MAX_PERF(~0L);
|
||||
- value |= AMD_CPPC_MAX_PERF(max_perf);
|
||||
-
|
||||
- /* CPPC EPP feature require to set zero to the desire perf bit */
|
||||
- value &= ~AMD_CPPC_DES_PERF(~0L);
|
||||
- value |= AMD_CPPC_DES_PERF(0);
|
||||
+ value &= ~(AMD_PSTATE_MAX_PERF_MASK | AMD_PSTATE_MIN_PERF_MASK |
|
||||
+ AMD_PSTATE_DES_PERF_MASK);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_MAX_PERF_MASK, max_perf);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_DES_PERF_MASK, 0);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_MIN_PERF_MASK, min_perf);
|
||||
|
||||
/* Get BIOS pre-defined epp value */
|
||||
epp = amd_pstate_get_epp(cpudata, value);
|
@@ -0,0 +1,103 @@
|
||||
From b1e3f18eb18f9febe9f4e32a1ef55cf60c97892a Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:37 -0600
|
||||
Subject: cpufreq/amd-pstate: Store the boost numerator as highest perf again
|
||||
|
||||
commit ad4caad58d91d ("cpufreq: amd-pstate: Merge
|
||||
amd_pstate_highest_perf_set() into amd_get_boost_ratio_numerator()")
|
||||
changed the semantics for highest perf and commit 18d9b52271213
|
||||
("cpufreq/amd-pstate: Use nominal perf for limits when boost is disabled")
|
||||
worked around those semantic changes.
|
||||
|
||||
This however is a confusing result and furthermore makes it awkward to
|
||||
change frequency limits and boost due to the scaling differences. Restore
|
||||
the boost numerator to highest perf again.
|
||||
|
||||
Suggested-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Fixes: ad4caad58d91 ("cpufreq: amd-pstate: Merge amd_pstate_highest_perf_set() into amd_get_boost_ratio_numerator()")
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
---
|
||||
Documentation/admin-guide/pm/amd-pstate.rst | 4 +---
|
||||
drivers/cpufreq/amd-pstate.c | 25 ++++++++++++---------
|
||||
2 files changed, 16 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/Documentation/admin-guide/pm/amd-pstate.rst
|
||||
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
|
||||
@@ -251,9 +251,7 @@ performance supported in `AMD CPPC Perfo
|
||||
In some ASICs, the highest CPPC performance is not the one in the ``_CPC``
|
||||
table, so we need to expose it to sysfs. If boost is not active, but
|
||||
still supported, this maximum frequency will be larger than the one in
|
||||
-``cpuinfo``. On systems that support preferred core, the driver will have
|
||||
-different values for some cores than others and this will reflect the values
|
||||
-advertised by the platform at bootup.
|
||||
+``cpuinfo``.
|
||||
This attribute is read-only.
|
||||
|
||||
``amd_pstate_lowest_nonlinear_freq``
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -438,15 +438,19 @@ static inline int amd_pstate_cppc_enable
|
||||
|
||||
static int msr_init_perf(struct amd_cpudata *cpudata)
|
||||
{
|
||||
- u64 cap1;
|
||||
+ u64 cap1, numerator;
|
||||
|
||||
int ret = rdmsrl_safe_on_cpu(cpudata->cpu, MSR_AMD_CPPC_CAP1,
|
||||
&cap1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- WRITE_ONCE(cpudata->highest_perf, AMD_CPPC_HIGHEST_PERF(cap1));
|
||||
- WRITE_ONCE(cpudata->max_limit_perf, AMD_CPPC_HIGHEST_PERF(cap1));
|
||||
+ ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ WRITE_ONCE(cpudata->highest_perf, numerator);
|
||||
+ WRITE_ONCE(cpudata->max_limit_perf, numerator);
|
||||
WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1));
|
||||
WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1));
|
||||
WRITE_ONCE(cpudata->lowest_perf, AMD_CPPC_LOWEST_PERF(cap1));
|
||||
@@ -458,13 +462,18 @@ static int msr_init_perf(struct amd_cpud
|
||||
static int shmem_init_perf(struct amd_cpudata *cpudata)
|
||||
{
|
||||
struct cppc_perf_caps cppc_perf;
|
||||
+ u64 numerator;
|
||||
|
||||
int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
- WRITE_ONCE(cpudata->highest_perf, cppc_perf.highest_perf);
|
||||
- WRITE_ONCE(cpudata->max_limit_perf, cppc_perf.highest_perf);
|
||||
+ ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ WRITE_ONCE(cpudata->highest_perf, numerator);
|
||||
+ WRITE_ONCE(cpudata->max_limit_perf, numerator);
|
||||
WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf);
|
||||
WRITE_ONCE(cpudata->lowest_nonlinear_perf,
|
||||
cppc_perf.lowest_nonlinear_perf);
|
||||
@@ -950,7 +959,6 @@ static int amd_pstate_init_freq(struct a
|
||||
{
|
||||
int ret;
|
||||
u32 min_freq, max_freq;
|
||||
- u64 numerator;
|
||||
u32 nominal_perf, nominal_freq;
|
||||
u32 lowest_nonlinear_perf, lowest_nonlinear_freq;
|
||||
u32 boost_ratio, lowest_nonlinear_ratio;
|
||||
@@ -972,10 +980,7 @@ static int amd_pstate_init_freq(struct a
|
||||
|
||||
nominal_perf = READ_ONCE(cpudata->nominal_perf);
|
||||
|
||||
- ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
- boost_ratio = div_u64(numerator << SCHED_CAPACITY_SHIFT, nominal_perf);
|
||||
+ boost_ratio = div_u64(cpudata->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);
|
@@ -1,183 +0,0 @@
|
||||
From 27b069b518f77fffc337286a2fad8a6305daa60f Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Mon, 4 Nov 2024 16:28:55 -0600
|
||||
Subject: ACPI: processor: Move arch_init_invariance_cppc() call later
|
||||
|
||||
arch_init_invariance_cppc() is called at the end of
|
||||
acpi_cppc_processor_probe() in order to configure frequency invariance
|
||||
based upon the values from _CPC.
|
||||
|
||||
This however doesn't work on AMD CPPC shared memory designs that have
|
||||
AMD preferred cores enabled because _CPC needs to be analyzed from all
|
||||
cores to judge if preferred cores are enabled.
|
||||
|
||||
This issue manifests to users as a warning since commit 21fb59ab4b97
|
||||
("ACPI: CPPC: Adjust debug messages in amd_set_max_freq_ratio() to warn"):
|
||||
```
|
||||
Could not retrieve highest performance (-19)
|
||||
```
|
||||
|
||||
However the warning isn't the cause of this, it was actually
|
||||
commit 279f838a61f9 ("x86/amd: Detect preferred cores in
|
||||
amd_get_boost_ratio_numerator()") which exposed the issue.
|
||||
|
||||
To fix this problem, change arch_init_invariance_cppc() into a new weak
|
||||
symbol that is called at the end of acpi_processor_driver_init().
|
||||
Each architecture that supports it can declare the symbol to override
|
||||
the weak one.
|
||||
|
||||
Fixes: 279f838a61f9 ("x86/amd: Detect preferred cores in amd_get_boost_ratio_numerator()")
|
||||
Reported-by: Ivan Shapovalov <intelfx@intelfx.name>
|
||||
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219431
|
||||
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
arch/arm64/include/asm/topology.h | 4 ----
|
||||
arch/x86/include/asm/topology.h | 5 -----
|
||||
arch/x86/kernel/acpi/cppc.c | 7 ++++++-
|
||||
drivers/acpi/cppc_acpi.c | 6 ------
|
||||
drivers/acpi/processor_driver.c | 9 +++++++++
|
||||
drivers/base/arch_topology.c | 6 +++++-
|
||||
include/acpi/processor.h | 2 ++
|
||||
include/linux/arch_topology.h | 4 ----
|
||||
8 files changed, 22 insertions(+), 21 deletions(-)
|
||||
|
||||
--- a/arch/arm64/include/asm/topology.h
|
||||
+++ b/arch/arm64/include/asm/topology.h
|
||||
@@ -25,10 +25,6 @@ void update_freq_counters_refs(void);
|
||||
#define arch_scale_freq_invariant topology_scale_freq_invariant
|
||||
#define arch_scale_freq_ref topology_get_freq_ref
|
||||
|
||||
-#ifdef CONFIG_ACPI_CPPC_LIB
|
||||
-#define arch_init_invariance_cppc topology_init_cpu_capacity_cppc
|
||||
-#endif
|
||||
-
|
||||
/* Replace task scheduler's default cpu-invariant accounting */
|
||||
#define arch_scale_cpu_capacity topology_get_cpu_scale
|
||||
|
||||
--- a/arch/x86/include/asm/topology.h
|
||||
+++ b/arch/x86/include/asm/topology.h
|
||||
@@ -292,9 +292,4 @@ static inline void freq_invariance_set_p
|
||||
extern void arch_scale_freq_tick(void);
|
||||
#define arch_scale_freq_tick arch_scale_freq_tick
|
||||
|
||||
-#ifdef CONFIG_ACPI_CPPC_LIB
|
||||
-void init_freq_invariance_cppc(void);
|
||||
-#define arch_init_invariance_cppc init_freq_invariance_cppc
|
||||
-#endif
|
||||
-
|
||||
#endif /* _ASM_X86_TOPOLOGY_H */
|
||||
--- a/arch/x86/kernel/acpi/cppc.c
|
||||
+++ b/arch/x86/kernel/acpi/cppc.c
|
||||
@@ -110,7 +110,7 @@ static void amd_set_max_freq_ratio(void)
|
||||
|
||||
static DEFINE_MUTEX(freq_invariance_lock);
|
||||
|
||||
-void init_freq_invariance_cppc(void)
|
||||
+static inline void init_freq_invariance_cppc(void)
|
||||
{
|
||||
static bool init_done;
|
||||
|
||||
@@ -127,6 +127,11 @@ void init_freq_invariance_cppc(void)
|
||||
mutex_unlock(&freq_invariance_lock);
|
||||
}
|
||||
|
||||
+void acpi_processor_init_invariance_cppc(void)
|
||||
+{
|
||||
+ init_freq_invariance_cppc();
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Get the highest performance register value.
|
||||
* @cpu: CPU from which to get highest performance.
|
||||
--- a/drivers/acpi/cppc_acpi.c
|
||||
+++ b/drivers/acpi/cppc_acpi.c
|
||||
@@ -671,10 +671,6 @@ static int pcc_data_alloc(int pcc_ss_id)
|
||||
* )
|
||||
*/
|
||||
|
||||
-#ifndef arch_init_invariance_cppc
|
||||
-static inline void arch_init_invariance_cppc(void) { }
|
||||
-#endif
|
||||
-
|
||||
/**
|
||||
* acpi_cppc_processor_probe - Search for per CPU _CPC objects.
|
||||
* @pr: Ptr to acpi_processor containing this CPU's logical ID.
|
||||
@@ -905,8 +901,6 @@ int acpi_cppc_processor_probe(struct acp
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
- arch_init_invariance_cppc();
|
||||
-
|
||||
kfree(output.pointer);
|
||||
return 0;
|
||||
|
||||
--- a/drivers/acpi/processor_driver.c
|
||||
+++ b/drivers/acpi/processor_driver.c
|
||||
@@ -237,6 +237,9 @@ static struct notifier_block acpi_proces
|
||||
.notifier_call = acpi_processor_notifier,
|
||||
};
|
||||
|
||||
+void __weak acpi_processor_init_invariance_cppc(void)
|
||||
+{ }
|
||||
+
|
||||
/*
|
||||
* We keep the driver loaded even when ACPI is not running.
|
||||
* This is needed for the powernow-k8 driver, that works even without
|
||||
@@ -270,6 +273,12 @@ static int __init acpi_processor_driver_
|
||||
NULL, acpi_soft_cpu_dead);
|
||||
|
||||
acpi_processor_throttling_init();
|
||||
+
|
||||
+ /*
|
||||
+ * Frequency invariance calculations on AMD platforms can't be run until
|
||||
+ * after acpi_cppc_processor_probe() has been called for all online CPUs
|
||||
+ */
|
||||
+ acpi_processor_init_invariance_cppc();
|
||||
return 0;
|
||||
err:
|
||||
driver_unregister(&acpi_processor_driver);
|
||||
--- a/drivers/base/arch_topology.c
|
||||
+++ b/drivers/base/arch_topology.c
|
||||
@@ -366,7 +366,7 @@ void __weak freq_inv_set_max_ratio(int c
|
||||
#ifdef CONFIG_ACPI_CPPC_LIB
|
||||
#include <acpi/cppc_acpi.h>
|
||||
|
||||
-void topology_init_cpu_capacity_cppc(void)
|
||||
+static inline void topology_init_cpu_capacity_cppc(void)
|
||||
{
|
||||
u64 capacity, capacity_scale = 0;
|
||||
struct cppc_perf_caps perf_caps;
|
||||
@@ -417,6 +417,10 @@ void topology_init_cpu_capacity_cppc(voi
|
||||
exit:
|
||||
free_raw_capacity();
|
||||
}
|
||||
+void acpi_processor_init_invariance_cppc(void)
|
||||
+{
|
||||
+ topology_init_cpu_capacity_cppc();
|
||||
+}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
--- a/include/acpi/processor.h
|
||||
+++ b/include/acpi/processor.h
|
||||
@@ -465,4 +465,6 @@ extern int acpi_processor_ffh_lpi_probe(
|
||||
extern int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi);
|
||||
#endif
|
||||
|
||||
+void acpi_processor_init_invariance_cppc(void);
|
||||
+
|
||||
#endif
|
||||
--- a/include/linux/arch_topology.h
|
||||
+++ b/include/linux/arch_topology.h
|
||||
@@ -11,10 +11,6 @@
|
||||
void topology_normalize_cpu_scale(void);
|
||||
int topology_update_cpu_topology(void);
|
||||
|
||||
-#ifdef CONFIG_ACPI_CPPC_LIB
|
||||
-void topology_init_cpu_capacity_cppc(void);
|
||||
-#endif
|
||||
-
|
||||
struct device_node;
|
||||
bool topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu);
|
||||
|
@@ -0,0 +1,45 @@
|
||||
From fab64249be63c384484cf82f4e08724577ad3b84 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:38 -0600
|
||||
Subject: cpufreq/amd-pstate: Use boost numerator for upper bound of
|
||||
frequencies
|
||||
|
||||
commit 18d9b5227121 ("cpufreq/amd-pstate: Use nominal perf for limits
|
||||
when boost is disabled") introduced different semantics for min/max limits
|
||||
based upon whether the user turned off boost from sysfs.
|
||||
|
||||
This however is not necessary when the highest perf value is the boost
|
||||
numerator.
|
||||
|
||||
Suggested-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Fixes: 18d9b5227121 ("cpufreq/amd-pstate: Use nominal perf for limits when boost is disabled")
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 13 +++++--------
|
||||
1 file changed, 5 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -631,16 +631,13 @@ static int amd_pstate_verify(struct cpuf
|
||||
|
||||
static int amd_pstate_update_min_max_limit(struct cpufreq_policy *policy)
|
||||
{
|
||||
- u32 max_limit_perf, min_limit_perf, lowest_perf, max_perf;
|
||||
+ u32 max_limit_perf, min_limit_perf, lowest_perf, max_perf, max_freq;
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
|
||||
- if (cpudata->boost_supported && !policy->boost_enabled)
|
||||
- max_perf = READ_ONCE(cpudata->nominal_perf);
|
||||
- else
|
||||
- max_perf = READ_ONCE(cpudata->highest_perf);
|
||||
-
|
||||
- max_limit_perf = div_u64(policy->max * max_perf, policy->cpuinfo.max_freq);
|
||||
- min_limit_perf = div_u64(policy->min * max_perf, policy->cpuinfo.max_freq);
|
||||
+ max_perf = READ_ONCE(cpudata->highest_perf);
|
||||
+ max_freq = READ_ONCE(cpudata->max_freq);
|
||||
+ max_limit_perf = div_u64(policy->max * max_perf, max_freq);
|
||||
+ min_limit_perf = div_u64(policy->min * max_perf, max_freq);
|
||||
|
||||
lowest_perf = READ_ONCE(cpudata->lowest_perf);
|
||||
if (min_limit_perf < lowest_perf)
|
@@ -0,0 +1,36 @@
|
||||
From a9b210306e861b7c2d3b8532c85e8cd54c3b322a Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:39 -0600
|
||||
Subject: cpufreq/amd-pstate: Only update the cached value in msr_set_epp() on
|
||||
success
|
||||
|
||||
If writing the MSR MSR_AMD_CPPC_REQ fails then the cached value in the
|
||||
amd_cpudata structure should not be updated.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 10 +++++++---
|
||||
1 file changed, 7 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -308,11 +308,15 @@ static int msr_set_epp(struct amd_cpudat
|
||||
|
||||
value &= ~AMD_PSTATE_EPP_PERF_MASK;
|
||||
value |= FIELD_PREP(AMD_PSTATE_EPP_PERF_MASK, epp);
|
||||
- WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
|
||||
ret = wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
|
||||
- if (!ret)
|
||||
- cpudata->epp_cached = epp;
|
||||
+ if (ret) {
|
||||
+ pr_err("failed to set energy perf value (%d)\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ cpudata->epp_cached = epp;
|
||||
+ WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
|
||||
return ret;
|
||||
}
|
@@ -0,0 +1,134 @@
|
||||
From 27a3d0642a3d26ba54e8a21575e6d2cb0ada55b3 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:40 -0600
|
||||
Subject: cpufreq/amd-pstate: store all values in cpudata struct in khz
|
||||
|
||||
Storing values in the cpudata structure in different units leads
|
||||
to confusion and hardcoded conversions elsewhere. After ratios are
|
||||
calculated store everything in khz for any future use. Adjust all
|
||||
relevant consumers for this change as well.
|
||||
|
||||
Suggested-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate-ut.c | 12 +++++-------
|
||||
drivers/cpufreq/amd-pstate.c | 30 +++++++++++++++---------------
|
||||
2 files changed, 20 insertions(+), 22 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate-ut.c
|
||||
+++ b/drivers/cpufreq/amd-pstate-ut.c
|
||||
@@ -207,7 +207,6 @@ static void amd_pstate_ut_check_freq(u32
|
||||
int cpu = 0;
|
||||
struct cpufreq_policy *policy = NULL;
|
||||
struct amd_cpudata *cpudata = NULL;
|
||||
- u32 nominal_freq_khz;
|
||||
|
||||
for_each_possible_cpu(cpu) {
|
||||
policy = cpufreq_cpu_get(cpu);
|
||||
@@ -215,14 +214,13 @@ static void amd_pstate_ut_check_freq(u32
|
||||
break;
|
||||
cpudata = policy->driver_data;
|
||||
|
||||
- nominal_freq_khz = cpudata->nominal_freq*1000;
|
||||
- if (!((cpudata->max_freq >= nominal_freq_khz) &&
|
||||
- (nominal_freq_khz > cpudata->lowest_nonlinear_freq) &&
|
||||
+ if (!((cpudata->max_freq >= cpudata->nominal_freq) &&
|
||||
+ (cpudata->nominal_freq > cpudata->lowest_nonlinear_freq) &&
|
||||
(cpudata->lowest_nonlinear_freq > cpudata->min_freq) &&
|
||||
(cpudata->min_freq > 0))) {
|
||||
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||
pr_err("%s cpu%d max=%d >= nominal=%d > lowest_nonlinear=%d > min=%d > 0, the formula is incorrect!\n",
|
||||
- __func__, cpu, cpudata->max_freq, nominal_freq_khz,
|
||||
+ __func__, cpu, cpudata->max_freq, cpudata->nominal_freq,
|
||||
cpudata->lowest_nonlinear_freq, cpudata->min_freq);
|
||||
goto skip_test;
|
||||
}
|
||||
@@ -236,13 +234,13 @@ static void amd_pstate_ut_check_freq(u32
|
||||
|
||||
if (cpudata->boost_supported) {
|
||||
if ((policy->max == cpudata->max_freq) ||
|
||||
- (policy->max == nominal_freq_khz))
|
||||
+ (policy->max == cpudata->nominal_freq))
|
||||
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_PASS;
|
||||
else {
|
||||
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||
pr_err("%s cpu%d policy_max=%d should be equal cpu_max=%d or cpu_nominal=%d !\n",
|
||||
__func__, cpu, policy->max, cpudata->max_freq,
|
||||
- nominal_freq_khz);
|
||||
+ cpudata->nominal_freq);
|
||||
goto skip_test;
|
||||
}
|
||||
} else {
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -769,8 +769,8 @@ static int amd_pstate_cpu_boost_update(s
|
||||
|
||||
if (on)
|
||||
policy->cpuinfo.max_freq = max_freq;
|
||||
- else if (policy->cpuinfo.max_freq > nominal_freq * 1000)
|
||||
- policy->cpuinfo.max_freq = nominal_freq * 1000;
|
||||
+ else if (policy->cpuinfo.max_freq > nominal_freq)
|
||||
+ policy->cpuinfo.max_freq = nominal_freq;
|
||||
|
||||
policy->max = policy->cpuinfo.max_freq;
|
||||
|
||||
@@ -970,29 +970,29 @@ static int amd_pstate_init_freq(struct a
|
||||
return ret;
|
||||
|
||||
if (quirks && quirks->lowest_freq)
|
||||
- min_freq = quirks->lowest_freq * 1000;
|
||||
+ min_freq = quirks->lowest_freq;
|
||||
else
|
||||
- min_freq = cppc_perf.lowest_freq * 1000;
|
||||
+ min_freq = cppc_perf.lowest_freq;
|
||||
|
||||
if (quirks && quirks->nominal_freq)
|
||||
- nominal_freq = quirks->nominal_freq ;
|
||||
+ nominal_freq = quirks->nominal_freq;
|
||||
else
|
||||
nominal_freq = cppc_perf.nominal_freq;
|
||||
|
||||
nominal_perf = READ_ONCE(cpudata->nominal_perf);
|
||||
|
||||
boost_ratio = div_u64(cpudata->highest_perf << SCHED_CAPACITY_SHIFT, nominal_perf);
|
||||
- max_freq = (nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT) * 1000;
|
||||
+ max_freq = (nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT);
|
||||
|
||||
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;
|
||||
+ lowest_nonlinear_freq = (nominal_freq * lowest_nonlinear_ratio >> SCHED_CAPACITY_SHIFT);
|
||||
|
||||
- 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);
|
||||
+ WRITE_ONCE(cpudata->min_freq, min_freq * 1000);
|
||||
+ WRITE_ONCE(cpudata->lowest_nonlinear_freq, lowest_nonlinear_freq * 1000);
|
||||
+ WRITE_ONCE(cpudata->nominal_freq, nominal_freq * 1000);
|
||||
+ WRITE_ONCE(cpudata->max_freq, max_freq * 1000);
|
||||
|
||||
/**
|
||||
* Below values need to be initialized correctly, otherwise driver will fail to load
|
||||
@@ -1000,15 +1000,15 @@ static int amd_pstate_init_freq(struct a
|
||||
* 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) {
|
||||
+ if (min_freq <= 0 || max_freq <= 0 || cpudata->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);
|
||||
+ min_freq, max_freq, cpudata->nominal_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- if (lowest_nonlinear_freq <= min_freq || lowest_nonlinear_freq > nominal_freq * 1000) {
|
||||
+ if (lowest_nonlinear_freq <= min_freq || lowest_nonlinear_freq > cpudata->nominal_freq) {
|
||||
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);
|
||||
+ lowest_nonlinear_freq, min_freq, cpudata->nominal_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@@ -0,0 +1,69 @@
|
||||
From b2a0f625fa30dc907daf1b07bf94b15872da096b Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:41 -0600
|
||||
Subject: cpufreq/amd-pstate: Change amd_pstate_update_perf() to return an int
|
||||
|
||||
As msr_update_perf() calls an MSR it's possible that it fails. Pass
|
||||
this return code up to the caller.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 22 ++++++++++++----------
|
||||
1 file changed, 12 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -281,24 +281,26 @@ static int amd_pstate_get_energy_pref_in
|
||||
return index;
|
||||
}
|
||||
|
||||
-static void msr_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
|
||||
+static int msr_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
|
||||
u32 des_perf, u32 max_perf, bool fast_switch)
|
||||
{
|
||||
- if (fast_switch)
|
||||
+ if (fast_switch) {
|
||||
wrmsrl(MSR_AMD_CPPC_REQ, READ_ONCE(cpudata->cppc_req_cached));
|
||||
- else
|
||||
- wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ,
|
||||
- READ_ONCE(cpudata->cppc_req_cached));
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ,
|
||||
+ READ_ONCE(cpudata->cppc_req_cached));
|
||||
}
|
||||
|
||||
DEFINE_STATIC_CALL(amd_pstate_update_perf, msr_update_perf);
|
||||
|
||||
-static inline void amd_pstate_update_perf(struct amd_cpudata *cpudata,
|
||||
+static inline int amd_pstate_update_perf(struct amd_cpudata *cpudata,
|
||||
u32 min_perf, u32 des_perf,
|
||||
u32 max_perf, bool fast_switch)
|
||||
{
|
||||
- static_call(amd_pstate_update_perf)(cpudata, min_perf, des_perf,
|
||||
- max_perf, fast_switch);
|
||||
+ return static_call(amd_pstate_update_perf)(cpudata, min_perf, des_perf,
|
||||
+ max_perf, fast_switch);
|
||||
}
|
||||
|
||||
static int msr_set_epp(struct amd_cpudata *cpudata, u32 epp)
|
||||
@@ -510,7 +512,7 @@ static inline int amd_pstate_init_perf(s
|
||||
return static_call(amd_pstate_init_perf)(cpudata);
|
||||
}
|
||||
|
||||
-static void shmem_update_perf(struct amd_cpudata *cpudata,
|
||||
+static int shmem_update_perf(struct amd_cpudata *cpudata,
|
||||
u32 min_perf, u32 des_perf,
|
||||
u32 max_perf, bool fast_switch)
|
||||
{
|
||||
@@ -520,7 +522,7 @@ static void shmem_update_perf(struct amd
|
||||
perf_ctrls.min_perf = min_perf;
|
||||
perf_ctrls.desired_perf = des_perf;
|
||||
|
||||
- cppc_set_perf(cpudata->cpu, &perf_ctrls);
|
||||
+ return cppc_set_perf(cpudata->cpu, &perf_ctrls);
|
||||
}
|
||||
|
||||
static inline bool amd_pstate_sample(struct amd_cpudata *cpudata)
|
85
debian/patches/patchset-pf/amd-pstate/0039-cpufreq-amd-pstate-Move-limit-updating-code.patch
vendored
Normal file
85
debian/patches/patchset-pf/amd-pstate/0039-cpufreq-amd-pstate-Move-limit-updating-code.patch
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
From 8399d57cda79a662800a4cd01bd7db951355f451 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:42 -0600
|
||||
Subject: cpufreq/amd-pstate: Move limit updating code
|
||||
|
||||
The limit updating code in amd_pstate_epp_update_limit() should not
|
||||
only apply to EPP updates. Move it to amd_pstate_update_min_max_limit()
|
||||
so other callers can benefit as well.
|
||||
|
||||
With this move it's not necessary to have clamp_t calls anymore because
|
||||
the verify callback is called when setting limits.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 28 +++++-----------------------
|
||||
1 file changed, 5 insertions(+), 23 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -567,10 +567,6 @@ static void amd_pstate_update(struct amd
|
||||
u32 nominal_perf = READ_ONCE(cpudata->nominal_perf);
|
||||
u64 value = prev;
|
||||
|
||||
- min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf,
|
||||
- cpudata->max_limit_perf);
|
||||
- max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_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);
|
||||
@@ -637,7 +633,7 @@ static int amd_pstate_verify(struct cpuf
|
||||
|
||||
static int amd_pstate_update_min_max_limit(struct cpufreq_policy *policy)
|
||||
{
|
||||
- u32 max_limit_perf, min_limit_perf, lowest_perf, max_perf, max_freq;
|
||||
+ u32 max_limit_perf, min_limit_perf, max_perf, max_freq;
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
|
||||
max_perf = READ_ONCE(cpudata->highest_perf);
|
||||
@@ -645,12 +641,8 @@ static int amd_pstate_update_min_max_lim
|
||||
max_limit_perf = div_u64(policy->max * max_perf, max_freq);
|
||||
min_limit_perf = div_u64(policy->min * max_perf, max_freq);
|
||||
|
||||
- lowest_perf = READ_ONCE(cpudata->lowest_perf);
|
||||
- if (min_limit_perf < lowest_perf)
|
||||
- min_limit_perf = lowest_perf;
|
||||
-
|
||||
- if (max_limit_perf < min_limit_perf)
|
||||
- max_limit_perf = min_limit_perf;
|
||||
+ if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
|
||||
+ min_limit_perf = min(cpudata->nominal_perf, max_limit_perf);
|
||||
|
||||
WRITE_ONCE(cpudata->max_limit_perf, max_limit_perf);
|
||||
WRITE_ONCE(cpudata->min_limit_perf, min_limit_perf);
|
||||
@@ -1592,28 +1584,18 @@ static void amd_pstate_epp_cpu_exit(stru
|
||||
static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
- u32 max_perf, min_perf;
|
||||
u64 value;
|
||||
s16 epp;
|
||||
|
||||
- max_perf = READ_ONCE(cpudata->highest_perf);
|
||||
- min_perf = READ_ONCE(cpudata->lowest_perf);
|
||||
amd_pstate_update_min_max_limit(policy);
|
||||
|
||||
- max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_perf,
|
||||
- cpudata->max_limit_perf);
|
||||
- min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf,
|
||||
- cpudata->max_limit_perf);
|
||||
value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
|
||||
- if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
|
||||
- min_perf = min(cpudata->nominal_perf, max_perf);
|
||||
-
|
||||
value &= ~(AMD_PSTATE_MAX_PERF_MASK | AMD_PSTATE_MIN_PERF_MASK |
|
||||
AMD_PSTATE_DES_PERF_MASK);
|
||||
- value |= FIELD_PREP(AMD_PSTATE_MAX_PERF_MASK, max_perf);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_MAX_PERF_MASK, cpudata->max_limit_perf);
|
||||
value |= FIELD_PREP(AMD_PSTATE_DES_PERF_MASK, 0);
|
||||
- value |= FIELD_PREP(AMD_PSTATE_MIN_PERF_MASK, min_perf);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_MIN_PERF_MASK, cpudata->min_limit_perf);
|
||||
|
||||
/* Get BIOS pre-defined epp value */
|
||||
epp = amd_pstate_get_epp(cpudata, value);
|
@@ -0,0 +1,233 @@
|
||||
From fe7f993593ee1891acc875dfb1e091cf17a43f7a Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:43 -0600
|
||||
Subject: cpufreq/amd-pstate: Cache EPP value and use that everywhere
|
||||
|
||||
Cache the value in cpudata->epp_cached, and use that for all callers.
|
||||
As all callers use cached value merge amd_pstate_get_energy_pref_index()
|
||||
into show_energy_performance_preference().
|
||||
|
||||
Check if the EPP value is changed before writing it to MSR or
|
||||
shared memory region.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 107 +++++++++++++++--------------------
|
||||
1 file changed, 45 insertions(+), 62 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -216,29 +216,28 @@ static inline int get_mode_idx_from_str(
|
||||
static DEFINE_MUTEX(amd_pstate_limits_lock);
|
||||
static DEFINE_MUTEX(amd_pstate_driver_lock);
|
||||
|
||||
-static s16 msr_get_epp(struct amd_cpudata *cpudata, u64 cppc_req_cached)
|
||||
+static s16 msr_get_epp(struct amd_cpudata *cpudata)
|
||||
{
|
||||
+ u64 value;
|
||||
int ret;
|
||||
|
||||
- if (!cppc_req_cached) {
|
||||
- ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &cppc_req_cached);
|
||||
- if (ret < 0) {
|
||||
- pr_debug("Could not retrieve energy perf value (%d)\n", ret);
|
||||
- return ret;
|
||||
- }
|
||||
+ ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
|
||||
+ if (ret < 0) {
|
||||
+ pr_debug("Could not retrieve energy perf value (%d)\n", ret);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
- return FIELD_GET(AMD_PSTATE_EPP_PERF_MASK, cppc_req_cached);
|
||||
+ return FIELD_GET(AMD_PSTATE_EPP_PERF_MASK, value);
|
||||
}
|
||||
|
||||
DEFINE_STATIC_CALL(amd_pstate_get_epp, msr_get_epp);
|
||||
|
||||
-static inline s16 amd_pstate_get_epp(struct amd_cpudata *cpudata, u64 cppc_req_cached)
|
||||
+static inline s16 amd_pstate_get_epp(struct amd_cpudata *cpudata)
|
||||
{
|
||||
- return static_call(amd_pstate_get_epp)(cpudata, cppc_req_cached);
|
||||
+ return static_call(amd_pstate_get_epp)(cpudata);
|
||||
}
|
||||
|
||||
-static s16 shmem_get_epp(struct amd_cpudata *cpudata, u64 dummy)
|
||||
+static s16 shmem_get_epp(struct amd_cpudata *cpudata)
|
||||
{
|
||||
u64 epp;
|
||||
int ret;
|
||||
@@ -252,35 +251,6 @@ static s16 shmem_get_epp(struct amd_cpud
|
||||
return (s16)(epp & 0xff);
|
||||
}
|
||||
|
||||
-static int amd_pstate_get_energy_pref_index(struct amd_cpudata *cpudata)
|
||||
-{
|
||||
- s16 epp;
|
||||
- int index = -EINVAL;
|
||||
-
|
||||
- epp = amd_pstate_get_epp(cpudata, 0);
|
||||
- if (epp < 0)
|
||||
- return epp;
|
||||
-
|
||||
- switch (epp) {
|
||||
- case AMD_CPPC_EPP_PERFORMANCE:
|
||||
- index = EPP_INDEX_PERFORMANCE;
|
||||
- break;
|
||||
- case AMD_CPPC_EPP_BALANCE_PERFORMANCE:
|
||||
- index = EPP_INDEX_BALANCE_PERFORMANCE;
|
||||
- break;
|
||||
- case AMD_CPPC_EPP_BALANCE_POWERSAVE:
|
||||
- index = EPP_INDEX_BALANCE_POWERSAVE;
|
||||
- break;
|
||||
- case AMD_CPPC_EPP_POWERSAVE:
|
||||
- index = EPP_INDEX_POWERSAVE;
|
||||
- break;
|
||||
- default:
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- return index;
|
||||
-}
|
||||
-
|
||||
static int msr_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
|
||||
u32 des_perf, u32 max_perf, bool fast_switch)
|
||||
{
|
||||
@@ -305,19 +275,23 @@ static inline int amd_pstate_update_perf
|
||||
|
||||
static int msr_set_epp(struct amd_cpudata *cpudata, u32 epp)
|
||||
{
|
||||
- u64 value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
+ u64 value, prev;
|
||||
int ret;
|
||||
|
||||
+ value = prev = READ_ONCE(cpudata->cppc_req_cached);
|
||||
value &= ~AMD_PSTATE_EPP_PERF_MASK;
|
||||
value |= FIELD_PREP(AMD_PSTATE_EPP_PERF_MASK, epp);
|
||||
|
||||
+ if (value == prev)
|
||||
+ return 0;
|
||||
+
|
||||
ret = wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
|
||||
if (ret) {
|
||||
pr_err("failed to set energy perf value (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
- cpudata->epp_cached = epp;
|
||||
+ WRITE_ONCE(cpudata->epp_cached, epp);
|
||||
WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
|
||||
return ret;
|
||||
@@ -335,13 +309,16 @@ static int shmem_set_epp(struct amd_cpud
|
||||
int ret;
|
||||
struct cppc_perf_ctrls perf_ctrls;
|
||||
|
||||
+ if (epp == cpudata->epp_cached)
|
||||
+ return 0;
|
||||
+
|
||||
perf_ctrls.energy_perf = epp;
|
||||
ret = cppc_set_epp_perf(cpudata->cpu, &perf_ctrls, 1);
|
||||
if (ret) {
|
||||
pr_debug("failed to set energy perf value (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
- cpudata->epp_cached = epp;
|
||||
+ WRITE_ONCE(cpudata->epp_cached, epp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1244,9 +1221,22 @@ static ssize_t show_energy_performance_p
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
int preference;
|
||||
|
||||
- preference = amd_pstate_get_energy_pref_index(cpudata);
|
||||
- if (preference < 0)
|
||||
- return preference;
|
||||
+ switch (cpudata->epp_cached) {
|
||||
+ case AMD_CPPC_EPP_PERFORMANCE:
|
||||
+ preference = EPP_INDEX_PERFORMANCE;
|
||||
+ break;
|
||||
+ case AMD_CPPC_EPP_BALANCE_PERFORMANCE:
|
||||
+ preference = EPP_INDEX_BALANCE_PERFORMANCE;
|
||||
+ break;
|
||||
+ case AMD_CPPC_EPP_BALANCE_POWERSAVE:
|
||||
+ preference = EPP_INDEX_BALANCE_POWERSAVE;
|
||||
+ break;
|
||||
+ case AMD_CPPC_EPP_POWERSAVE:
|
||||
+ preference = EPP_INDEX_POWERSAVE;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]);
|
||||
}
|
||||
@@ -1531,7 +1521,7 @@ static int amd_pstate_epp_cpu_init(struc
|
||||
|
||||
policy->driver_data = cpudata;
|
||||
|
||||
- cpudata->epp_cached = cpudata->epp_default = amd_pstate_get_epp(cpudata, 0);
|
||||
+ cpudata->epp_cached = cpudata->epp_default = amd_pstate_get_epp(cpudata);
|
||||
|
||||
policy->min = policy->cpuinfo.min_freq;
|
||||
policy->max = policy->cpuinfo.max_freq;
|
||||
@@ -1585,35 +1575,26 @@ static int amd_pstate_epp_update_limit(s
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
u64 value;
|
||||
- s16 epp;
|
||||
|
||||
amd_pstate_update_min_max_limit(policy);
|
||||
|
||||
value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
|
||||
value &= ~(AMD_PSTATE_MAX_PERF_MASK | AMD_PSTATE_MIN_PERF_MASK |
|
||||
- AMD_PSTATE_DES_PERF_MASK);
|
||||
+ AMD_PSTATE_DES_PERF_MASK | AMD_PSTATE_EPP_PERF_MASK);
|
||||
value |= FIELD_PREP(AMD_PSTATE_MAX_PERF_MASK, cpudata->max_limit_perf);
|
||||
value |= FIELD_PREP(AMD_PSTATE_DES_PERF_MASK, 0);
|
||||
value |= FIELD_PREP(AMD_PSTATE_MIN_PERF_MASK, cpudata->min_limit_perf);
|
||||
|
||||
- /* Get BIOS pre-defined epp value */
|
||||
- epp = amd_pstate_get_epp(cpudata, value);
|
||||
- if (epp < 0) {
|
||||
- /**
|
||||
- * This return value can only be negative for shared_memory
|
||||
- * systems where EPP register read/write not supported.
|
||||
- */
|
||||
- return epp;
|
||||
- }
|
||||
-
|
||||
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
|
||||
- epp = 0;
|
||||
+ WRITE_ONCE(cpudata->epp_cached, 0);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_EPP_PERF_MASK, cpudata->epp_cached);
|
||||
|
||||
WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
|
||||
if (trace_amd_pstate_epp_perf_enabled()) {
|
||||
- trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf, epp,
|
||||
+ trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf,
|
||||
+ cpudata->epp_cached,
|
||||
cpudata->min_limit_perf,
|
||||
cpudata->max_limit_perf,
|
||||
cpudata->boost_state);
|
||||
@@ -1622,7 +1603,7 @@ static int amd_pstate_epp_update_limit(s
|
||||
amd_pstate_update_perf(cpudata, cpudata->min_limit_perf, 0U,
|
||||
cpudata->max_limit_perf, false);
|
||||
|
||||
- return amd_pstate_set_epp(cpudata, epp);
|
||||
+ return amd_pstate_set_epp(cpudata, READ_ONCE(cpudata->epp_cached));
|
||||
}
|
||||
|
||||
static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
|
||||
@@ -1638,6 +1619,8 @@ static int amd_pstate_epp_set_policy(str
|
||||
|
||||
cpudata->policy = policy->policy;
|
||||
|
||||
+ guard(mutex)(&amd_pstate_limits_lock);
|
||||
+
|
||||
ret = amd_pstate_epp_update_limit(policy);
|
||||
if (ret)
|
||||
return ret;
|
@@ -0,0 +1,182 @@
|
||||
From 98f0f9202cd0fc549f5beaaaf8750658d8ee2140 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:44 -0600
|
||||
Subject: cpufreq/amd-pstate: Always write EPP value when updating perf
|
||||
|
||||
For MSR systems the EPP value is in the same register as perf targets
|
||||
and so divding them into two separate MSR writes is wasteful.
|
||||
|
||||
In msr_update_perf(), update both EPP and perf values in one write to
|
||||
MSR_AMD_CPPC_REQ, and cache them if successful.
|
||||
|
||||
To accomplish this plumb the EPP value into the update_perf call and modify
|
||||
all its callers to check the return value.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 71 ++++++++++++++++++++++--------------
|
||||
1 file changed, 43 insertions(+), 28 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -252,25 +252,36 @@ static s16 shmem_get_epp(struct amd_cpud
|
||||
}
|
||||
|
||||
static int msr_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
|
||||
- u32 des_perf, u32 max_perf, bool fast_switch)
|
||||
+ u32 des_perf, u32 max_perf, u32 epp, bool fast_switch)
|
||||
{
|
||||
+ u64 value;
|
||||
+
|
||||
+ value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
if (fast_switch) {
|
||||
wrmsrl(MSR_AMD_CPPC_REQ, READ_ONCE(cpudata->cppc_req_cached));
|
||||
return 0;
|
||||
+ } else {
|
||||
+ int ret = wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ,
|
||||
+ READ_ONCE(cpudata->cppc_req_cached));
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
- return wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ,
|
||||
- READ_ONCE(cpudata->cppc_req_cached));
|
||||
+ WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
+ WRITE_ONCE(cpudata->epp_cached, epp);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
DEFINE_STATIC_CALL(amd_pstate_update_perf, msr_update_perf);
|
||||
|
||||
static inline int amd_pstate_update_perf(struct amd_cpudata *cpudata,
|
||||
u32 min_perf, u32 des_perf,
|
||||
- u32 max_perf, bool fast_switch)
|
||||
+ u32 max_perf, u32 epp,
|
||||
+ bool fast_switch)
|
||||
{
|
||||
return static_call(amd_pstate_update_perf)(cpudata, min_perf, des_perf,
|
||||
- max_perf, fast_switch);
|
||||
+ max_perf, epp, fast_switch);
|
||||
}
|
||||
|
||||
static int msr_set_epp(struct amd_cpudata *cpudata, u32 epp)
|
||||
@@ -489,12 +500,19 @@ static inline int amd_pstate_init_perf(s
|
||||
return static_call(amd_pstate_init_perf)(cpudata);
|
||||
}
|
||||
|
||||
-static int shmem_update_perf(struct amd_cpudata *cpudata,
|
||||
- u32 min_perf, u32 des_perf,
|
||||
- u32 max_perf, bool fast_switch)
|
||||
+static int shmem_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
|
||||
+ u32 des_perf, u32 max_perf, u32 epp, bool fast_switch)
|
||||
{
|
||||
struct cppc_perf_ctrls perf_ctrls;
|
||||
|
||||
+ if (cppc_state == AMD_PSTATE_ACTIVE) {
|
||||
+ int ret = shmem_set_epp(cpudata, epp);
|
||||
+
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+ WRITE_ONCE(cpudata->epp_cached, epp);
|
||||
+ }
|
||||
+
|
||||
perf_ctrls.max_perf = max_perf;
|
||||
perf_ctrls.min_perf = min_perf;
|
||||
perf_ctrls.desired_perf = des_perf;
|
||||
@@ -575,10 +593,10 @@ static void amd_pstate_update(struct amd
|
||||
|
||||
WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
|
||||
- amd_pstate_update_perf(cpudata, min_perf, des_perf,
|
||||
- max_perf, fast_switch);
|
||||
+ amd_pstate_update_perf(cpudata, min_perf, des_perf, max_perf, 0, fast_switch);
|
||||
|
||||
cpufreq_policy_put:
|
||||
+
|
||||
cpufreq_cpu_put(policy);
|
||||
}
|
||||
|
||||
@@ -1575,6 +1593,7 @@ static int amd_pstate_epp_update_limit(s
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
u64 value;
|
||||
+ u32 epp;
|
||||
|
||||
amd_pstate_update_min_max_limit(policy);
|
||||
|
||||
@@ -1587,23 +1606,19 @@ static int amd_pstate_epp_update_limit(s
|
||||
value |= FIELD_PREP(AMD_PSTATE_MIN_PERF_MASK, cpudata->min_limit_perf);
|
||||
|
||||
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
|
||||
- WRITE_ONCE(cpudata->epp_cached, 0);
|
||||
- value |= FIELD_PREP(AMD_PSTATE_EPP_PERF_MASK, cpudata->epp_cached);
|
||||
-
|
||||
- WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
+ epp = 0;
|
||||
+ else
|
||||
+ epp = READ_ONCE(cpudata->epp_cached);
|
||||
|
||||
if (trace_amd_pstate_epp_perf_enabled()) {
|
||||
- trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf,
|
||||
- cpudata->epp_cached,
|
||||
+ trace_amd_pstate_epp_perf(cpudata->cpu, cpudata->highest_perf, epp,
|
||||
cpudata->min_limit_perf,
|
||||
cpudata->max_limit_perf,
|
||||
cpudata->boost_state);
|
||||
}
|
||||
|
||||
- amd_pstate_update_perf(cpudata, cpudata->min_limit_perf, 0U,
|
||||
- cpudata->max_limit_perf, false);
|
||||
-
|
||||
- return amd_pstate_set_epp(cpudata, READ_ONCE(cpudata->epp_cached));
|
||||
+ return amd_pstate_update_perf(cpudata, cpudata->min_limit_perf, 0U,
|
||||
+ cpudata->max_limit_perf, epp, false);
|
||||
}
|
||||
|
||||
static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
|
||||
@@ -1634,7 +1649,7 @@ static int amd_pstate_epp_set_policy(str
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void amd_pstate_epp_reenable(struct amd_cpudata *cpudata)
|
||||
+static int amd_pstate_epp_reenable(struct amd_cpudata *cpudata)
|
||||
{
|
||||
u64 max_perf;
|
||||
int ret;
|
||||
@@ -1652,17 +1667,19 @@ static void amd_pstate_epp_reenable(stru
|
||||
max_perf, cpudata->boost_state);
|
||||
}
|
||||
|
||||
- amd_pstate_update_perf(cpudata, 0, 0, max_perf, false);
|
||||
- amd_pstate_set_epp(cpudata, cpudata->epp_cached);
|
||||
+ return amd_pstate_update_perf(cpudata, 0, 0, max_perf, cpudata->epp_cached, false);
|
||||
}
|
||||
|
||||
static int amd_pstate_epp_cpu_online(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
+ int ret;
|
||||
|
||||
pr_debug("AMD CPU Core %d going online\n", cpudata->cpu);
|
||||
|
||||
- amd_pstate_epp_reenable(cpudata);
|
||||
+ ret = amd_pstate_epp_reenable(cpudata);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
cpudata->suspended = false;
|
||||
|
||||
return 0;
|
||||
@@ -1686,10 +1703,8 @@ static int amd_pstate_epp_cpu_offline(st
|
||||
min_perf, min_perf, cpudata->boost_state);
|
||||
}
|
||||
|
||||
- amd_pstate_update_perf(cpudata, min_perf, 0, min_perf, false);
|
||||
- amd_pstate_set_epp(cpudata, AMD_CPPC_EPP_BALANCE_POWERSAVE);
|
||||
-
|
||||
- return 0;
|
||||
+ return amd_pstate_update_perf(cpudata, min_perf, 0, min_perf,
|
||||
+ AMD_CPPC_EPP_BALANCE_POWERSAVE, false);
|
||||
}
|
||||
|
||||
static int amd_pstate_epp_suspend(struct cpufreq_policy *policy)
|
@@ -0,0 +1,158 @@
|
||||
From acf3f432287638044e472501a1d5969abee15043 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:45 -0600
|
||||
Subject: cpufreq/amd-pstate: Check if CPPC request has changed before writing
|
||||
to the MSR or shared memory
|
||||
|
||||
Move the common MSR field formatting code to msr_update_perf() from
|
||||
its callers.
|
||||
|
||||
Ensure that the MSR write is necessary before flushing a write out.
|
||||
Also drop the comparison from the passive flow tracing.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate-trace.h | 7 +----
|
||||
drivers/cpufreq/amd-pstate.c | 47 +++++++++++-------------------
|
||||
2 files changed, 18 insertions(+), 36 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate-trace.h
|
||||
+++ b/drivers/cpufreq/amd-pstate-trace.h
|
||||
@@ -32,7 +32,6 @@ TRACE_EVENT(amd_pstate_perf,
|
||||
u64 aperf,
|
||||
u64 tsc,
|
||||
unsigned int cpu_id,
|
||||
- bool changed,
|
||||
bool fast_switch
|
||||
),
|
||||
|
||||
@@ -44,7 +43,6 @@ TRACE_EVENT(amd_pstate_perf,
|
||||
aperf,
|
||||
tsc,
|
||||
cpu_id,
|
||||
- changed,
|
||||
fast_switch
|
||||
),
|
||||
|
||||
@@ -57,7 +55,6 @@ TRACE_EVENT(amd_pstate_perf,
|
||||
__field(unsigned long long, aperf)
|
||||
__field(unsigned long long, tsc)
|
||||
__field(unsigned int, cpu_id)
|
||||
- __field(bool, changed)
|
||||
__field(bool, fast_switch)
|
||||
),
|
||||
|
||||
@@ -70,11 +67,10 @@ TRACE_EVENT(amd_pstate_perf,
|
||||
__entry->aperf = aperf;
|
||||
__entry->tsc = tsc;
|
||||
__entry->cpu_id = cpu_id;
|
||||
- __entry->changed = changed;
|
||||
__entry->fast_switch = fast_switch;
|
||||
),
|
||||
|
||||
- TP_printk("amd_min_perf=%lu amd_des_perf=%lu amd_max_perf=%lu freq=%llu mperf=%llu aperf=%llu tsc=%llu cpu_id=%u changed=%s fast_switch=%s",
|
||||
+ TP_printk("amd_min_perf=%lu amd_des_perf=%lu amd_max_perf=%lu freq=%llu mperf=%llu aperf=%llu tsc=%llu cpu_id=%u fast_switch=%s",
|
||||
(unsigned long)__entry->min_perf,
|
||||
(unsigned long)__entry->target_perf,
|
||||
(unsigned long)__entry->capacity,
|
||||
@@ -83,7 +79,6 @@ TRACE_EVENT(amd_pstate_perf,
|
||||
(unsigned long long)__entry->aperf,
|
||||
(unsigned long long)__entry->tsc,
|
||||
(unsigned int)__entry->cpu_id,
|
||||
- (__entry->changed) ? "true" : "false",
|
||||
(__entry->fast_switch) ? "true" : "false"
|
||||
)
|
||||
);
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -254,15 +254,26 @@ static s16 shmem_get_epp(struct amd_cpud
|
||||
static int msr_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
|
||||
u32 des_perf, u32 max_perf, u32 epp, bool fast_switch)
|
||||
{
|
||||
- u64 value;
|
||||
+ u64 value, prev;
|
||||
+
|
||||
+ value = prev = READ_ONCE(cpudata->cppc_req_cached);
|
||||
+
|
||||
+ value &= ~(AMD_PSTATE_MAX_PERF_MASK | AMD_PSTATE_MIN_PERF_MASK |
|
||||
+ AMD_PSTATE_DES_PERF_MASK | AMD_PSTATE_EPP_PERF_MASK);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_MAX_PERF_MASK, max_perf);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_DES_PERF_MASK, des_perf);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_MIN_PERF_MASK, min_perf);
|
||||
+ value |= FIELD_PREP(AMD_PSTATE_EPP_PERF_MASK, epp);
|
||||
+
|
||||
+ if (value == prev)
|
||||
+ return 0;
|
||||
|
||||
- value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
if (fast_switch) {
|
||||
- wrmsrl(MSR_AMD_CPPC_REQ, READ_ONCE(cpudata->cppc_req_cached));
|
||||
+ wrmsrl(MSR_AMD_CPPC_REQ, value);
|
||||
return 0;
|
||||
} else {
|
||||
- int ret = wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ,
|
||||
- READ_ONCE(cpudata->cppc_req_cached));
|
||||
+ int ret = wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
|
||||
+
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@@ -558,9 +569,7 @@ static void amd_pstate_update(struct amd
|
||||
{
|
||||
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;
|
||||
|
||||
des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
|
||||
|
||||
@@ -576,27 +585,14 @@ static void amd_pstate_update(struct amd
|
||||
if (!cpudata->boost_supported)
|
||||
max_perf = min_t(unsigned long, nominal_perf, max_perf);
|
||||
|
||||
- value &= ~(AMD_PSTATE_MAX_PERF_MASK | AMD_PSTATE_MIN_PERF_MASK |
|
||||
- AMD_PSTATE_DES_PERF_MASK);
|
||||
- value |= FIELD_PREP(AMD_PSTATE_MAX_PERF_MASK, max_perf);
|
||||
- value |= FIELD_PREP(AMD_PSTATE_DES_PERF_MASK, des_perf);
|
||||
- value |= FIELD_PREP(AMD_PSTATE_MIN_PERF_MASK, min_perf);
|
||||
-
|
||||
if (trace_amd_pstate_perf_enabled() && amd_pstate_sample(cpudata)) {
|
||||
trace_amd_pstate_perf(min_perf, des_perf, max_perf, cpudata->freq,
|
||||
cpudata->cur.mperf, cpudata->cur.aperf, cpudata->cur.tsc,
|
||||
- cpudata->cpu, (value != prev), fast_switch);
|
||||
+ cpudata->cpu, fast_switch);
|
||||
}
|
||||
|
||||
- if (value == prev)
|
||||
- goto cpufreq_policy_put;
|
||||
-
|
||||
- WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
-
|
||||
amd_pstate_update_perf(cpudata, min_perf, des_perf, max_perf, 0, fast_switch);
|
||||
|
||||
-cpufreq_policy_put:
|
||||
-
|
||||
cpufreq_cpu_put(policy);
|
||||
}
|
||||
|
||||
@@ -1592,19 +1588,10 @@ static void amd_pstate_epp_cpu_exit(stru
|
||||
static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
- u64 value;
|
||||
u32 epp;
|
||||
|
||||
amd_pstate_update_min_max_limit(policy);
|
||||
|
||||
- value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
-
|
||||
- value &= ~(AMD_PSTATE_MAX_PERF_MASK | AMD_PSTATE_MIN_PERF_MASK |
|
||||
- AMD_PSTATE_DES_PERF_MASK | AMD_PSTATE_EPP_PERF_MASK);
|
||||
- value |= FIELD_PREP(AMD_PSTATE_MAX_PERF_MASK, cpudata->max_limit_perf);
|
||||
- value |= FIELD_PREP(AMD_PSTATE_DES_PERF_MASK, 0);
|
||||
- value |= FIELD_PREP(AMD_PSTATE_MIN_PERF_MASK, cpudata->min_limit_perf);
|
||||
-
|
||||
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
|
||||
epp = 0;
|
||||
else
|
@@ -0,0 +1,42 @@
|
||||
From 55bcae033b08b1b926f927616cca17242cfcfe59 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:46 -0600
|
||||
Subject: cpufreq/amd-pstate: Drop ret variable from
|
||||
amd_pstate_set_energy_pref_index()
|
||||
|
||||
The ret variable is not necessary.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 10 +++-------
|
||||
1 file changed, 3 insertions(+), 7 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -348,13 +348,11 @@ static int shmem_set_epp(struct amd_cpud
|
||||
static int amd_pstate_set_energy_pref_index(struct amd_cpudata *cpudata,
|
||||
int pref_index)
|
||||
{
|
||||
- int epp = -EINVAL;
|
||||
- int ret;
|
||||
+ int epp;
|
||||
|
||||
if (!pref_index)
|
||||
epp = cpudata->epp_default;
|
||||
-
|
||||
- if (epp == -EINVAL)
|
||||
+ else
|
||||
epp = epp_values[pref_index];
|
||||
|
||||
if (epp > 0 && cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
|
||||
@@ -370,9 +368,7 @@ static int amd_pstate_set_energy_pref_in
|
||||
cpudata->boost_state);
|
||||
}
|
||||
|
||||
- ret = amd_pstate_set_epp(cpudata, epp);
|
||||
-
|
||||
- return ret;
|
||||
+ return amd_pstate_set_epp(cpudata, epp);
|
||||
}
|
||||
|
||||
static inline int msr_cppc_enable(bool enable)
|
@@ -0,0 +1,58 @@
|
||||
From f1edcca6a96f087f5862a14012fafd4eb9738601 Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Thu, 5 Dec 2024 16:28:47 -0600
|
||||
Subject: cpufreq/amd-pstate: Set different default EPP policy for Epyc and
|
||||
Ryzen
|
||||
|
||||
For Ryzen systems the EPP policy set by the BIOS is generally configured
|
||||
to performance as this is the default register value for the CPPC request
|
||||
MSR.
|
||||
|
||||
If a user doesn't use additional software to configure EPP then the system
|
||||
will default biased towards performance and consume extra battery. Instead
|
||||
configure the default to "balanced_performance" for this case.
|
||||
|
||||
Suggested-by: Artem S. Tashkinov <aros@gmx.com>
|
||||
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219526
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 12 ++++++++----
|
||||
1 file changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1531,8 +1531,6 @@ static int amd_pstate_epp_cpu_init(struc
|
||||
|
||||
policy->driver_data = cpudata;
|
||||
|
||||
- cpudata->epp_cached = cpudata->epp_default = amd_pstate_get_epp(cpudata);
|
||||
-
|
||||
policy->min = policy->cpuinfo.min_freq;
|
||||
policy->max = policy->cpuinfo.max_freq;
|
||||
|
||||
@@ -1543,10 +1541,13 @@ static int amd_pstate_epp_cpu_init(struc
|
||||
* the default cpufreq governor is neither powersave nor performance.
|
||||
*/
|
||||
if (amd_pstate_acpi_pm_profile_server() ||
|
||||
- amd_pstate_acpi_pm_profile_undefined())
|
||||
+ amd_pstate_acpi_pm_profile_undefined()) {
|
||||
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
|
||||
- else
|
||||
+ cpudata->epp_default = amd_pstate_get_epp(cpudata);
|
||||
+ } else {
|
||||
policy->policy = CPUFREQ_POLICY_POWERSAVE;
|
||||
+ cpudata->epp_default = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
|
||||
+ }
|
||||
|
||||
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
||||
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
|
||||
@@ -1559,6 +1560,9 @@ static int amd_pstate_epp_cpu_init(struc
|
||||
return ret;
|
||||
WRITE_ONCE(cpudata->cppc_cap1_cached, value);
|
||||
}
|
||||
+ ret = amd_pstate_set_epp(cpudata, cpudata->epp_default);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
current_pstate_driver->adjust_perf = NULL;
|
||||
|
Reference in New Issue
Block a user