add 3rd party/custom patches
3rd patchs (in alphabetical order): - bbr3 - ntsync5 - openwrt - pf-kernel - xanmod - zen no configuration changes for now
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
From 3427331872c37b2edb42406c65764e1565b0591b 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
|
||||
|
||||
The Ryzen 3000 series processors have been observed lacking the
|
||||
nominal_freq and lowest_freq parameters in their ACPI tables. This
|
||||
absence causes issues with loading the amd-pstate driver on these
|
||||
systems. Introduces a fix to resolve the dependency issue
|
||||
by adding a quirk specifically for the Ryzen 3000 series.
|
||||
|
||||
Reported-by: David Wang <00107082@163.com>
|
||||
Signed-off-by: Perry Yuan <perry.yuan@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 30 ++++++++++++++++++++++++++++++
|
||||
1 file changed, 30 insertions(+)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -142,6 +142,11 @@ static struct quirk_entry quirk_amd_7k62
|
||||
.lowest_freq = 550,
|
||||
};
|
||||
|
||||
+static struct quirk_entry quirk_amd_mts = {
|
||||
+ .nominal_freq = 3600,
|
||||
+ .lowest_freq = 550,
|
||||
+};
|
||||
+
|
||||
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_
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int __init dmi_matched_mts_bios_bug(const struct dmi_system_id *dmi)
|
||||
+{
|
||||
+ /**
|
||||
+ * match the broken bios for ryzen 3000 series processor support CPPC V2
|
||||
+ * broken BIOS lack of nominal_freq and lowest_freq capabilities
|
||||
+ * definition in ACPI tables
|
||||
+ */
|
||||
+ if (cpu_feature_enabled(X86_FEATURE_ZEN2)) {
|
||||
+ quirks = dmi->driver_data;
|
||||
+ pr_info("Overriding nominal and lowest frequencies for %s\n", dmi->ident);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
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
|
||||
},
|
||||
.driver_data = &quirk_amd_7k62,
|
||||
},
|
||||
+ {
|
||||
+ .callback = dmi_matched_mts_bios_bug,
|
||||
+ .ident = "AMD Ryzen 3000",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_PRODUCT_NAME, "B450M MORTAR MAX (MS-7B89)"),
|
||||
+ DMI_MATCH(DMI_BIOS_RELEASE, "06/10/2020"),
|
||||
+ DMI_MATCH(DMI_BIOS_VERSION, "5.14"),
|
||||
+ },
|
||||
+ .driver_data = &quirk_amd_mts,
|
||||
+ },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(dmi, amd_pstate_quirks_table);
|
@@ -0,0 +1,88 @@
|
||||
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;
|
||||
@@ -1392,7 +1388,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;
|
||||
|
||||
@@ -1409,6 +1405,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 */
|
@@ -0,0 +1,77 @@
|
||||
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);
|
@@ -0,0 +1,60 @@
|
||||
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
|
||||
@@ -1595,7 +1595,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;
|
||||
@@ -1645,7 +1645,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)
|
||||
@@ -1658,12 +1658,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;
|
||||
@@ -1673,7 +1674,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
|
@@ -0,0 +1,67 @@
|
||||
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
|
||||
@@ -1190,22 +1190,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());
|
@@ -0,0 +1,95 @@
|
||||
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,162 @@
|
||||
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*/
|
35
debian/patches/patchset-pf/amd-pstate/0008-ACPI-CPPC-Drop-check-for-non-zero-perf-ratio.patch
vendored
Normal file
35
debian/patches/patchset-pf/amd-pstate/0008-ACPI-CPPC-Drop-check-for-non-zero-perf-ratio.patch
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
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);
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
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;
|
||||
}
|
||||
|
138
debian/patches/patchset-pf/amd-pstate/0010-x86-amd-Move-amd_get_highest_perf-out-of-amd-pstate.patch
vendored
Normal file
138
debian/patches/patchset-pf/amd-pstate/0010-x86-amd-Move-amd_get_highest_perf-out-of-amd-pstate.patch
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
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
|
||||
@@ -837,36 +837,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)
|
||||
@@ -874,7 +844,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;
|
||||
|
||||
@@ -918,7 +888,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;
|
@@ -0,0 +1,251 @@
|
||||
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
|
||||
@@ -841,32 +841,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);
|
||||
}
|
||||
@@ -1037,12 +1023,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;
|
||||
@@ -1493,12 +1479,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;
|
||||
@@ -1960,6 +1946,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*/
|
@@ -0,0 +1,169 @@
|
||||
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);
|
||||
@@ -944,8 +910,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;
|
||||
@@ -967,8 +933,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);
|
@@ -0,0 +1,42 @@
|
||||
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
|
||||
@@ -836,17 +836,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)
|
@@ -0,0 +1,29 @@
|
||||
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,42 @@
|
||||
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
|
24
debian/patches/patchset-pf/amd-pstate/0016-cpufreq-amd-pstate-Fix-non-kerneldoc-comment.patch
vendored
Normal file
24
debian/patches/patchset-pf/amd-pstate/0016-cpufreq-amd-pstate-Fix-non-kerneldoc-comment.patch
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
From 2e2ba39aec71fb51e897c3275b255ef806800cf0 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
|
||||
|
||||
The comment for amd_cppc_supported() isn't meant to be kernel doc.
|
||||
|
||||
Fixes: cb817ec6673b7 ("cpufreq: amd-pstate: show CPPC debug message if CPPC is not supported")
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1786,7 +1786,7 @@ static int __init amd_pstate_set_driver(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
-/**
|
||||
+/*
|
||||
* CPPC function is not supported for family ID 17H with model_ID ranging from 0x10 to 0x2F.
|
||||
* show the debug message that helps to check if the CPU has CPPC support for loading issue.
|
||||
*/
|
@@ -0,0 +1,24 @@
|
||||
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,108 @@
|
||||
From d74ce254cc470da670d6b90c69bab553cdbde62b 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
|
||||
|
||||
Existing function names "cppc_*" and "pstate_*" for shared memory and
|
||||
MSR based systems are not intuitive enough, replace them with "shmem_*" and
|
||||
"msr_*" respectively.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 24 ++++++++++++------------
|
||||
1 file changed, 12 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -263,7 +263,7 @@ static int amd_pstate_get_energy_pref_in
|
||||
return index;
|
||||
}
|
||||
|
||||
-static void pstate_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
|
||||
+static void msr_update_perf(struct amd_cpudata *cpudata, u32 min_perf,
|
||||
u32 des_perf, u32 max_perf, bool fast_switch)
|
||||
{
|
||||
if (fast_switch)
|
||||
@@ -273,7 +273,7 @@ static void pstate_update_perf(struct am
|
||||
READ_ONCE(cpudata->cppc_req_cached));
|
||||
}
|
||||
|
||||
-DEFINE_STATIC_CALL(amd_pstate_update_perf, pstate_update_perf);
|
||||
+DEFINE_STATIC_CALL(amd_pstate_update_perf, msr_update_perf);
|
||||
|
||||
static inline void amd_pstate_update_perf(struct amd_cpudata *cpudata,
|
||||
u32 min_perf, u32 des_perf,
|
||||
@@ -336,7 +336,7 @@ static int amd_pstate_set_energy_pref_in
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static inline int pstate_enable(bool enable)
|
||||
+static inline int msr_enable(bool enable)
|
||||
{
|
||||
int ret, cpu;
|
||||
unsigned long logical_proc_id_mask = 0;
|
||||
@@ -362,7 +362,7 @@ static inline int pstate_enable(bool ena
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int cppc_enable(bool enable)
|
||||
+static int shmem_enable(bool enable)
|
||||
{
|
||||
int cpu, ret = 0;
|
||||
struct cppc_perf_ctrls perf_ctrls;
|
||||
@@ -389,14 +389,14 @@ static int cppc_enable(bool enable)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-DEFINE_STATIC_CALL(amd_pstate_enable, pstate_enable);
|
||||
+DEFINE_STATIC_CALL(amd_pstate_enable, msr_enable);
|
||||
|
||||
static inline int amd_pstate_enable(bool enable)
|
||||
{
|
||||
return static_call(amd_pstate_enable)(enable);
|
||||
}
|
||||
|
||||
-static int pstate_init_perf(struct amd_cpudata *cpudata)
|
||||
+static int msr_init_perf(struct amd_cpudata *cpudata)
|
||||
{
|
||||
u64 cap1;
|
||||
|
||||
@@ -415,7 +415,7 @@ static int pstate_init_perf(struct amd_c
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int cppc_init_perf(struct amd_cpudata *cpudata)
|
||||
+static int shmem_init_perf(struct amd_cpudata *cpudata)
|
||||
{
|
||||
struct cppc_perf_caps cppc_perf;
|
||||
|
||||
@@ -450,14 +450,14 @@ static int cppc_init_perf(struct amd_cpu
|
||||
return ret;
|
||||
}
|
||||
|
||||
-DEFINE_STATIC_CALL(amd_pstate_init_perf, pstate_init_perf);
|
||||
+DEFINE_STATIC_CALL(amd_pstate_init_perf, msr_init_perf);
|
||||
|
||||
static inline int amd_pstate_init_perf(struct amd_cpudata *cpudata)
|
||||
{
|
||||
return static_call(amd_pstate_init_perf)(cpudata);
|
||||
}
|
||||
|
||||
-static void cppc_update_perf(struct amd_cpudata *cpudata,
|
||||
+static void shmem_update_perf(struct amd_cpudata *cpudata,
|
||||
u32 min_perf, u32 des_perf,
|
||||
u32 max_perf, bool fast_switch)
|
||||
{
|
||||
@@ -1909,9 +1909,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");
|
||||
- static_call_update(amd_pstate_enable, cppc_enable);
|
||||
- static_call_update(amd_pstate_init_perf, cppc_init_perf);
|
||||
- static_call_update(amd_pstate_update_perf, cppc_update_perf);
|
||||
+ static_call_update(amd_pstate_enable, shmem_enable);
|
||||
+ static_call_update(amd_pstate_init_perf, shmem_init_perf);
|
||||
+ static_call_update(amd_pstate_update_perf, shmem_update_perf);
|
||||
}
|
||||
|
||||
if (amd_pstate_prefcore) {
|
@@ -0,0 +1,115 @@
|
||||
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,79 @@
|
||||
From f5b234be445a45b0bcacc37e0aad7a6bc7900eac Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Thu, 3 Oct 2024 08:39:54 +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
|
||||
section "17.6.4.1 CPPC_CAPABILITY_1" lowest_nonlinear_perf is described
|
||||
as "Reports the most energy efficient performance level (in terms of
|
||||
performance per watt). Above this threshold, lower performance levels
|
||||
generally result in increased energy efficiency. Reducing performance
|
||||
below this threshold does not result in total energy savings for a given
|
||||
computation, although it reduces instantaneous power consumption". So
|
||||
lowest_nonlinear_perf is the most power efficient performance level, and
|
||||
going below that would lead to a worse performance/watt.
|
||||
|
||||
Also, setting the minimum frequency to lowest_nonlinear_freq (instead of
|
||||
lowest_freq) allows the CPU to idle at a higher frequency which leads
|
||||
to more time being spent in a deeper idle state (as trivial idle tasks
|
||||
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.
|
||||
|
||||
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(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1025,13 +1025,6 @@ 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[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) {
|
||||
@@ -1736,6 +1729,13 @@ 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,
|
||||
@@ -1749,6 +1749,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,
|
||||
};
|
||||
|
||||
static struct cpufreq_driver amd_pstate_epp_driver = {
|
||||
@@ -1765,6 +1766,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)
|
@@ -0,0 +1,103 @@
|
||||
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
|
||||
@@ -726,7 +726,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);
|
||||
}
|
||||
@@ -993,17 +993,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);
|
||||
@@ -1025,11 +1025,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;
|
||||
@@ -1042,9 +1042,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;
|
||||
}
|
||||
@@ -1053,8 +1051,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;
|
@@ -0,0 +1,42 @@
|
||||
From d1216c052bedbf6d79e4b0261e2f09e17c66ffd3 Mon Sep 17 00:00:00 2001
|
||||
From: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
Date: Fri, 4 Oct 2024 12:23:04 +0000
|
||||
Subject: cpufreq/amd-pstate: Fix amd_pstate mode switch on shared memory
|
||||
systems
|
||||
|
||||
While switching the driver mode between active and passive, Collaborative
|
||||
Processor Performance Control (CPPC) is disabled in
|
||||
amd_pstate_unregister_driver(). But, it is not enabled back while registering
|
||||
the new driver (passive or active). This leads to the new driver mode not
|
||||
working correctly, so enable it back in amd_pstate_register_driver().
|
||||
|
||||
Fixes: 3ca7bc818d8c ("cpufreq: amd-pstate: Add guided mode control support via sysfs")
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1221,11 +1221,21 @@ static int amd_pstate_register_driver(in
|
||||
return -EINVAL;
|
||||
|
||||
cppc_state = mode;
|
||||
+
|
||||
+ ret = amd_pstate_enable(true);
|
||||
+ if (ret) {
|
||||
+ pr_err("failed to enable cppc during amd-pstate driver registration, return %d\n",
|
||||
+ ret);
|
||||
+ amd_pstate_driver_cleanup();
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
ret = cpufreq_register_driver(current_pstate_driver);
|
||||
if (ret) {
|
||||
amd_pstate_driver_cleanup();
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
@@ -0,0 +1,57 @@
|
||||
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)
|
||||
@@ -1526,10 +1531,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,55 @@
|
||||
From 01ad0fb3da95867947d923596a26b18d844afe3c Mon Sep 17 00:00:00 2001
|
||||
From: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Date: Sat, 12 Oct 2024 12:45:17 -0500
|
||||
Subject: cpufreq/amd-pstate: Don't update CPPC request in
|
||||
amd_pstate_cpu_boost_update()
|
||||
|
||||
When boost is changed the CPPC value is changed in amd_pstate_cpu_boost_update()
|
||||
but then changed again when refresh_frequency_limits() and all it's callbacks
|
||||
occur. The first is a pointless write, so instead just update the limits for
|
||||
the policy and let the policy refresh anchor everything properly.
|
||||
|
||||
Fixes: c8c68c38b56f ("cpufreq: amd-pstate: initialize core precision boost state")
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 24 +-----------------------
|
||||
1 file changed, 1 insertion(+), 23 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -695,34 +695,12 @@ static void amd_pstate_adjust_perf(unsig
|
||||
static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on)
|
||||
{
|
||||
struct amd_cpudata *cpudata = policy->driver_data;
|
||||
- struct cppc_perf_ctrls perf_ctrls;
|
||||
- u32 highest_perf, nominal_perf, nominal_freq, max_freq;
|
||||
+ u32 nominal_freq, max_freq;
|
||||
int ret = 0;
|
||||
|
||||
- highest_perf = READ_ONCE(cpudata->highest_perf);
|
||||
- nominal_perf = READ_ONCE(cpudata->nominal_perf);
|
||||
nominal_freq = READ_ONCE(cpudata->nominal_freq);
|
||||
max_freq = READ_ONCE(cpudata->max_freq);
|
||||
|
||||
- if (boot_cpu_has(X86_FEATURE_CPPC)) {
|
||||
- u64 value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
-
|
||||
- value &= ~GENMASK_ULL(7, 0);
|
||||
- value |= on ? highest_perf : nominal_perf;
|
||||
- WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
-
|
||||
- wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
|
||||
- } else {
|
||||
- perf_ctrls.max_perf = on ? highest_perf : nominal_perf;
|
||||
- ret = cppc_set_perf(cpudata->cpu, &perf_ctrls);
|
||||
- if (ret) {
|
||||
- cpufreq_cpu_release(policy);
|
||||
- pr_debug("Failed to set max perf on CPU:%d. ret:%d\n",
|
||||
- cpudata->cpu, ret);
|
||||
- return ret;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
if (on)
|
||||
policy->cpuinfo.max_freq = max_freq;
|
||||
else if (policy->cpuinfo.max_freq > nominal_freq * 1000)
|
@@ -0,0 +1,49 @@
|
||||
From 684d162c08ab86fff02861c907ecc92bf9c09af4 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
|
||||
limits
|
||||
|
||||
When the EPP updates are set the maximum capable frequency for the
|
||||
CPU is used to set the upper limit instead of that of the policy.
|
||||
|
||||
Adjust amd_pstate_epp_update_limit() to reuse policy calculation code
|
||||
from amd_pstate_update_min_max_limit().
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 19 +++----------------
|
||||
1 file changed, 3 insertions(+), 16 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1505,26 +1505,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;
|
||||
- u32 max_perf, min_perf, min_limit_perf, max_limit_perf;
|
||||
+ u32 max_perf, min_perf;
|
||||
u64 value;
|
||||
s16 epp;
|
||||
|
||||
- if (cpudata->boost_supported && !policy->boost_enabled)
|
||||
- max_perf = READ_ONCE(cpudata->nominal_perf);
|
||||
- else
|
||||
- max_perf = READ_ONCE(cpudata->highest_perf);
|
||||
+ max_perf = READ_ONCE(cpudata->highest_perf);
|
||||
min_perf = READ_ONCE(cpudata->lowest_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);
|
||||
-
|
||||
- if (min_limit_perf < min_perf)
|
||||
- min_limit_perf = min_perf;
|
||||
-
|
||||
- if (max_limit_perf < min_limit_perf)
|
||||
- max_limit_perf = min_limit_perf;
|
||||
-
|
||||
- WRITE_ONCE(cpudata->max_limit_perf, max_limit_perf);
|
||||
- WRITE_ONCE(cpudata->min_limit_perf, min_limit_perf);
|
||||
+ amd_pstate_update_min_max_limit(policy);
|
||||
|
||||
max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_perf,
|
||||
cpudata->max_limit_perf);
|
@@ -0,0 +1,29 @@
|
||||
From fa46d2873c9fa4060ce407e4bc5c7e29babce9d0 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
|
||||
|
||||
The EPP value doesn't need to be cached to the CPPC request in
|
||||
amd_pstate_epp_update_limit() because it's passed as an argument
|
||||
at the end to amd_pstate_set_epp() and stored at that time.
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 6 ------
|
||||
1 file changed, 6 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1548,12 +1548,6 @@ static int amd_pstate_epp_update_limit(s
|
||||
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
|
||||
epp = 0;
|
||||
|
||||
- /* Set initial EPP value */
|
||||
- if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
||||
- value &= ~GENMASK_ULL(31, 24);
|
||||
- value |= (u64)epp << 24;
|
||||
- }
|
||||
-
|
||||
WRITE_ONCE(cpudata->cppc_req_cached, value);
|
||||
return amd_pstate_set_epp(cpudata, epp);
|
||||
}
|
@@ -0,0 +1,228 @@
|
||||
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,44 @@
|
||||
From db147a0a6341822a15fd9c4cd51f8dc4a9a1747b 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()
|
||||
|
||||
Replace a similar chunk of code in amd_pstate_init() with
|
||||
amd_pstate_register() call.
|
||||
|
||||
Suggested-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 12 ++----------
|
||||
1 file changed, 2 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1909,17 +1909,10 @@ static int __init amd_pstate_init(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- /* enable amd pstate feature */
|
||||
- ret = amd_pstate_enable(true);
|
||||
- if (ret) {
|
||||
- pr_err("failed to enable driver mode(%d)\n", cppc_state);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
- ret = cpufreq_register_driver(current_pstate_driver);
|
||||
+ ret = amd_pstate_register_driver(cppc_state);
|
||||
if (ret) {
|
||||
pr_err("failed to register with return %d\n", ret);
|
||||
- goto disable_driver;
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
dev_root = bus_get_dev_root(&cpu_subsys);
|
||||
@@ -1936,7 +1929,6 @@ static int __init amd_pstate_init(void)
|
||||
|
||||
global_attr_free:
|
||||
cpufreq_unregister_driver(current_pstate_driver);
|
||||
-disable_driver:
|
||||
amd_pstate_enable(false);
|
||||
return ret;
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
From 7c658490b05f6ab4dd59e1c25e75ba1037f6cfeb 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
|
||||
amd_pstate_register_driver()
|
||||
|
||||
Replace a similar chunk of code in amd_pstate_register_driver() with
|
||||
amd_pstate_set_driver() call.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 47 +++++++++++++++++-------------------
|
||||
1 file changed, 22 insertions(+), 25 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1221,16 +1221,32 @@ static void amd_pstate_driver_cleanup(vo
|
||||
current_pstate_driver = NULL;
|
||||
}
|
||||
|
||||
+static int amd_pstate_set_driver(int mode_idx)
|
||||
+{
|
||||
+ if (mode_idx >= AMD_PSTATE_DISABLE && mode_idx < AMD_PSTATE_MAX) {
|
||||
+ cppc_state = mode_idx;
|
||||
+ if (cppc_state == AMD_PSTATE_DISABLE)
|
||||
+ pr_info("driver is explicitly disabled\n");
|
||||
+
|
||||
+ if (cppc_state == AMD_PSTATE_ACTIVE)
|
||||
+ current_pstate_driver = &amd_pstate_epp_driver;
|
||||
+
|
||||
+ if (cppc_state == AMD_PSTATE_PASSIVE || cppc_state == AMD_PSTATE_GUIDED)
|
||||
+ current_pstate_driver = &amd_pstate_driver;
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
static int amd_pstate_register_driver(int mode)
|
||||
{
|
||||
int ret;
|
||||
|
||||
- if (mode == AMD_PSTATE_PASSIVE || mode == AMD_PSTATE_GUIDED)
|
||||
- current_pstate_driver = &amd_pstate_driver;
|
||||
- else if (mode == AMD_PSTATE_ACTIVE)
|
||||
- current_pstate_driver = &amd_pstate_epp_driver;
|
||||
- else
|
||||
- return -EINVAL;
|
||||
+ ret = amd_pstate_set_driver(mode);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
|
||||
cppc_state = mode;
|
||||
|
||||
@@ -1756,25 +1772,6 @@ static struct cpufreq_driver amd_pstate_
|
||||
.attr = amd_pstate_epp_attr,
|
||||
};
|
||||
|
||||
-static int __init amd_pstate_set_driver(int mode_idx)
|
||||
-{
|
||||
- if (mode_idx >= AMD_PSTATE_DISABLE && mode_idx < AMD_PSTATE_MAX) {
|
||||
- cppc_state = mode_idx;
|
||||
- if (cppc_state == AMD_PSTATE_DISABLE)
|
||||
- pr_info("driver is explicitly disabled\n");
|
||||
-
|
||||
- if (cppc_state == AMD_PSTATE_ACTIVE)
|
||||
- current_pstate_driver = &amd_pstate_epp_driver;
|
||||
-
|
||||
- if (cppc_state == AMD_PSTATE_PASSIVE || cppc_state == AMD_PSTATE_GUIDED)
|
||||
- current_pstate_driver = &amd_pstate_driver;
|
||||
-
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- return -EINVAL;
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* CPPC function is not supported for family ID 17H with model_ID ranging from 0x10 to 0x2F.
|
||||
* show the debug message that helps to check if the CPU has CPPC support for loading issue.
|
@@ -0,0 +1,41 @@
|
||||
From 55be5db97f4f52badc958463ee8d9cbc2ae91615 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()
|
||||
|
||||
Replace the switch case with a more readable if condition.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 16 +++++-----------
|
||||
1 file changed, 5 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1873,21 +1873,15 @@ static int __init amd_pstate_init(void)
|
||||
cppc_state = CONFIG_X86_AMD_PSTATE_DEFAULT_MODE;
|
||||
}
|
||||
|
||||
- switch (cppc_state) {
|
||||
- case AMD_PSTATE_DISABLE:
|
||||
+ if (cppc_state == AMD_PSTATE_DISABLE) {
|
||||
pr_info("driver load is disabled, boot with specific mode to enable this\n");
|
||||
return -ENODEV;
|
||||
- case AMD_PSTATE_PASSIVE:
|
||||
- case AMD_PSTATE_ACTIVE:
|
||||
- case AMD_PSTATE_GUIDED:
|
||||
- ret = amd_pstate_set_driver(cppc_state);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
- break;
|
||||
- default:
|
||||
- return -EINVAL;
|
||||
}
|
||||
|
||||
+ ret = amd_pstate_set_driver(cppc_state);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
/* capability check */
|
||||
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
||||
pr_debug("AMD CPPC MSR based functionality is supported\n");
|
@@ -0,0 +1,43 @@
|
||||
From 7305364888151cb9e6b435c5f219ccfd18132b58 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
|
||||
|
||||
amd_pstate_set_driver() is called twice, once in amd_pstate_init() and once
|
||||
as part of amd_pstate_register_driver(). Move around code and eliminate
|
||||
the redundancy.
|
||||
|
||||
Signed-off-by: Dhananjay Ugwekar <Dhananjay.Ugwekar@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 12 ++++--------
|
||||
1 file changed, 4 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1878,9 +1878,11 @@ static int __init amd_pstate_init(void)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
- ret = amd_pstate_set_driver(cppc_state);
|
||||
- if (ret)
|
||||
+ 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)) {
|
||||
@@ -1900,12 +1902,6 @@ static int __init amd_pstate_init(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
- ret = amd_pstate_register_driver(cppc_state);
|
||||
- if (ret) {
|
||||
- pr_err("failed to register with return %d\n", ret);
|
||||
- return ret;
|
||||
- }
|
||||
-
|
||||
dev_root = bus_get_dev_root(&cpu_subsys);
|
||||
if (dev_root) {
|
||||
ret = sysfs_create_group(&dev_root->kobj, &amd_pstate_global_attr_group);
|
@@ -0,0 +1,33 @@
|
||||
From 5886ef269d069c72ea952cb00699e16221289e8c 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
|
||||
|
||||
commit 642aff3964b0f ("cpufreq/amd-pstate: Set the initial min_freq to
|
||||
lowest_nonlinear_freq") changed the iniital minimum frequency to lowest
|
||||
nonlinear frequency, but the unit tests weren't updated and now fail.
|
||||
|
||||
Update them to match this same change.
|
||||
|
||||
Fixes: 642aff3964b0f ("cpufreq/amd-pstate: Set the initial min_freq to lowest_nonlinear_freq")
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate-ut.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate-ut.c
|
||||
+++ b/drivers/cpufreq/amd-pstate-ut.c
|
||||
@@ -227,10 +227,10 @@ static void amd_pstate_ut_check_freq(u32
|
||||
goto skip_test;
|
||||
}
|
||||
|
||||
- if (cpudata->min_freq != policy->min) {
|
||||
+ if (cpudata->lowest_nonlinear_freq != policy->min) {
|
||||
amd_pstate_ut_cases[index].result = AMD_PSTATE_UT_RESULT_FAIL;
|
||||
- pr_err("%s cpu%d cpudata_min_freq=%d policy_min=%d, they should be equal!\n",
|
||||
- __func__, cpu, cpudata->min_freq, policy->min);
|
||||
+ pr_err("%s cpu%d cpudata_lowest_nonlinear_freq=%d policy_min=%d, they should be equal!\n",
|
||||
+ __func__, cpu, cpudata->lowest_nonlinear_freq, policy->min);
|
||||
goto skip_test;
|
||||
}
|
||||
|
@@ -0,0 +1,33 @@
|
||||
From e82b9b5a56bcac18cae68878fe67263279805735 Mon Sep 17 00:00:00 2001
|
||||
From: "Gautham R. Shenoy" <gautham.shenoy@amd.com>
|
||||
Date: Mon, 21 Oct 2024 15:48:35 +0530
|
||||
Subject: amd-pstate: Set min_perf to nominal_perf for active mode performance
|
||||
gov
|
||||
|
||||
The amd-pstate driver sets CPPC_REQ.min_perf to CPPC_REQ.max_perf when
|
||||
in active mode with performance governor. Typically CPPC_REQ.max_perf
|
||||
is set to CPPC.highest_perf. This causes frequency throttling on
|
||||
power-limited platforms which causes performance regressions on
|
||||
certain classes of workloads.
|
||||
|
||||
Hence, set the CPPC_REQ.min_perf to the CPPC.nominal_perf or
|
||||
CPPC_REQ.max_perf, whichever is lower of the two.
|
||||
|
||||
Fixes: ffa5096a7c33 ("cpufreq: amd-pstate: implement Pstate EPP support for the AMD processors")
|
||||
Signed-off-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1565,7 +1565,7 @@ static int amd_pstate_epp_update_limit(s
|
||||
value = READ_ONCE(cpudata->cppc_req_cached);
|
||||
|
||||
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
|
||||
- min_perf = max_perf;
|
||||
+ min_perf = min(cpudata->nominal_perf, max_perf);
|
||||
|
||||
/* Initial min/max values for CPPC Performance Controls Register */
|
||||
value &= ~AMD_CPPC_MIN_PERF(~0L);
|
@@ -0,0 +1,44 @@
|
||||
From 497447cf96a785a4edd0756da5d5718037f5687c 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
|
||||
|
||||
Currently the default cpufreq driver for all the AMD EPYC servers is
|
||||
acpi-cpufreq. Going forward, switch to amd-pstate as the default
|
||||
driver on the AMD EPYC server platforms with CPU family 0x1A or
|
||||
higher. The default mode will be active mode.
|
||||
|
||||
Testing shows that amd-pstate with active mode and performance
|
||||
governor provides comparable or better performance per-watt against
|
||||
acpi-cpufreq + performance governor.
|
||||
|
||||
Likewise, amd-pstate with active mode and powersave governor with the
|
||||
energy_performance_preference=power (EPP=255) provides comparable or
|
||||
better performance per-watt against acpi-cpufreq + schedutil governor
|
||||
for a wide range of workloads.
|
||||
|
||||
Users can still revert to using acpi-cpufreq driver on these platforms
|
||||
with the "amd_pstate=disable" kernel commandline parameter.
|
||||
|
||||
Signed-off-by: Swapnil Sapkal <swapnil.sapkal@amd.com>
|
||||
Signed-off-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
|
||||
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1862,10 +1862,10 @@ static int __init amd_pstate_init(void)
|
||||
if (cppc_state == AMD_PSTATE_UNDEFINED) {
|
||||
/* Disable on the following configs by default:
|
||||
* 1. Undefined platforms
|
||||
- * 2. Server platforms
|
||||
+ * 2. Server platforms with CPUs older than Family 0x1A.
|
||||
*/
|
||||
if (amd_pstate_acpi_pm_profile_undefined() ||
|
||||
- amd_pstate_acpi_pm_profile_server()) {
|
||||
+ (amd_pstate_acpi_pm_profile_server() && boot_cpu_data.x86 < 0x1A)) {
|
||||
pr_info("driver load is disabled, boot with specific mode to enable this\n");
|
||||
return -ENODEV;
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
From a4d255935a1ea6e4b10167df942ec641079bcdf7 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
|
||||
|
||||
As the driver can be changed in and out of different modes it's possible
|
||||
that adjust_perf is assigned when it shouldn't be.
|
||||
|
||||
This could happen if an MSR design is started up in passive mode and then
|
||||
switches to active mode.
|
||||
|
||||
To solve this explicitly clear `adjust_perf` in amd_pstate_epp_cpu_init().
|
||||
|
||||
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
|
||||
---
|
||||
drivers/cpufreq/amd-pstate.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/cpufreq/amd-pstate.c
|
||||
+++ b/drivers/cpufreq/amd-pstate.c
|
||||
@@ -1528,6 +1528,8 @@ static int amd_pstate_epp_cpu_init(struc
|
||||
WRITE_ONCE(cpudata->cppc_cap1_cached, value);
|
||||
}
|
||||
|
||||
+ current_pstate_driver->adjust_perf = NULL;
|
||||
+
|
||||
return 0;
|
||||
|
||||
free_cpudata1:
|
||||
@@ -1887,8 +1889,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");
|
||||
- if (cppc_state != AMD_PSTATE_ACTIVE)
|
||||
- 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);
|
@@ -0,0 +1,47 @@
|
||||
From c42a82a583646dcbba8500d47ed878616ab5c33a 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
|
||||
@@ -1880,12 +1880,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");
|
||||
@@ -1896,6 +1890,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)
|
Reference in New Issue
Block a user