* [PATCH v2 0/5] amd-pstate Dynamic EPP and raw EPP
@ 2025-03-04 15:23 Mario Limonciello
2025-03-04 15:23 ` [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference Mario Limonciello
` (4 more replies)
0 siblings, 5 replies; 20+ messages in thread
From: Mario Limonciello @ 2025-03-04 15:23 UTC (permalink / raw)
To: Gautham R . Shenoy, Perry Yuan
Cc: Dhananjay Ugwekar, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
From: Mario Limonciello <mario.limonciello@amd.com>
Dynamic EPP allows the kernel to register amd-pstate as part of
a platform profile. It will change EPP modes matching the user's
preference to the platform profile sysfs files as well as power
adapter state.
Raw EPP allows userspace to write integers to
energy_performance_preference.
This series is based off superm1/linux.git bleeding-edge branch
v1->v2:
* Rebase
* Change some defaults
Mario Limonciello (5):
cpufreq/amd-pstate: Add dynamic energy performance preference
cpufreq/amd-pstate: add kernel command line to override dynamic epp
cpufreq/amd-pstate: Add support for platform profile class
cpufreq/amd-pstate: Add support for raw EPP writes
cpufreq/amd-pstate-ut: Add a unit test for raw EPP
.../admin-guide/kernel-parameters.txt | 7 +
Documentation/admin-guide/pm/amd-pstate.rst | 41 ++-
drivers/cpufreq/Kconfig.x86 | 13 +
drivers/cpufreq/amd-pstate-ut.c | 58 ++++
drivers/cpufreq/amd-pstate.c | 279 ++++++++++++++++--
drivers/cpufreq/amd-pstate.h | 16 +-
6 files changed, 390 insertions(+), 24 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference
2025-03-04 15:23 [PATCH v2 0/5] amd-pstate Dynamic EPP and raw EPP Mario Limonciello
@ 2025-03-04 15:23 ` Mario Limonciello
2025-03-07 6:45 ` Gautham R. Shenoy
` (2 more replies)
2025-03-04 15:23 ` [PATCH v2 2/5] cpufreq/amd-pstate: add kernel command line to override dynamic epp Mario Limonciello
` (3 subsequent siblings)
4 siblings, 3 replies; 20+ messages in thread
From: Mario Limonciello @ 2025-03-04 15:23 UTC (permalink / raw)
To: Gautham R . Shenoy, Perry Yuan
Cc: Dhananjay Ugwekar, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
From: Mario Limonciello <mario.limonciello@amd.com>
Dynamic energy performance preference will change the EPP profile
based on whether the machine is running on AC or DC power.
A notification chain from the power supply core is used to adjust
EPP values on plug in or plug out events.
For non-server systems:
* the default EPP for AC mode is `performance`.
* the default EPP for DC mode is `balance_performance`.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
v1->v2:
* Change defaults to performance (AC) and balance_performance (DC)
* Default Kconfig to disabled for now
* Rebase on latest branch
---
Documentation/admin-guide/pm/amd-pstate.rst | 18 ++-
drivers/cpufreq/Kconfig.x86 | 12 ++
drivers/cpufreq/amd-pstate.c | 129 ++++++++++++++++++--
drivers/cpufreq/amd-pstate.h | 5 +-
4 files changed, 155 insertions(+), 9 deletions(-)
diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
index 412423c54f258..2e076650dc77c 100644
--- a/Documentation/admin-guide/pm/amd-pstate.rst
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
@@ -289,7 +289,7 @@ and user can change current preference according to energy or performance needs
Please get all support profiles list from
``energy_performance_available_preferences`` attribute, all the profiles are
integer values defined between 0 to 255 when EPP feature is enabled by platform
-firmware, if EPP feature is disabled, driver will ignore the written value
+firmware, but if the dynamic EPP feature is enabled, driver will block writes.
This attribute is read-write.
``boost``
@@ -311,6 +311,22 @@ boost or `1` to enable it, for the respective CPU using the sysfs path
Other performance and frequency values can be read back from
``/sys/devices/system/cpu/cpuX/acpi_cppc/``, see :ref:`cppc_sysfs`.
+Dynamic energy performance profile
+==================================
+The amd-pstate driver supports dynamically selecting the energy performance
+profile based on whether the machine is running on AC or DC power.
+
+Whether this behavior is enabled by default with the kernel config option
+`CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`. This behavior can also be overridden
+at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``.
+
+When set to enabled, the driver will select a different energy performance
+profile when the machine is running on battery or AC power.
+When set to disabled, the driver will not change the energy performance profile
+based on the power source and will not react to user desired power state.
+
+Attempting to manually write to the ``energy_performance_preference`` sysfs
+file will fail when ``dynamic_epp`` is enabled.
``amd-pstate`` vs ``acpi-cpufreq``
======================================
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index 97c2d4f15d76e..c5ef92634ddf4 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
@@ -68,6 +68,18 @@ config X86_AMD_PSTATE_DEFAULT_MODE
For details, take a look at:
<file:Documentation/admin-guide/pm/amd-pstate.rst>.
+config X86_AMD_PSTATE_DYNAMIC_EPP
+ bool "AMD Processor P-State dynamic EPP support"
+ depends on X86_AMD_PSTATE
+ default n
+ help
+ Allow the kenrel to dynamically change the energy performance
+ value from events like ACPI platform profile and AC adapter plug
+ events.
+
+ This feature can also be changed at runtime, this configuration
+ option only sets the kernel default value behavior.
+
config X86_AMD_PSTATE_UT
tristate "selftest for AMD Processor P-State driver"
depends on X86 && ACPI_PROCESSOR
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index e98ef41083ba1..f00fb4ba9f26e 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -36,6 +36,7 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
+#include <linux/power_supply.h>
#include <linux/static_call.h>
#include <linux/topology.h>
@@ -86,6 +87,7 @@ static struct cpufreq_driver amd_pstate_driver;
static struct cpufreq_driver amd_pstate_epp_driver;
static int cppc_state = AMD_PSTATE_UNDEFINED;
static bool amd_pstate_prefcore = true;
+static bool dynamic_epp = CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP;
static struct quirk_entry *quirks;
/*
@@ -1050,6 +1052,73 @@ static void amd_pstate_cpu_exit(struct cpufreq_policy *policy)
kfree(cpudata);
}
+static int amd_pstate_get_balanced_epp(struct cpufreq_policy *policy)
+{
+ struct amd_cpudata *cpudata = policy->driver_data;
+
+ if (power_supply_is_system_supplied())
+ return cpudata->epp_default_ac;
+ else
+ return cpudata->epp_default_dc;
+}
+
+static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct amd_cpudata *cpudata = container_of(nb, struct amd_cpudata, power_nb);
+ struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
+ u8 epp;
+ int ret;
+
+ if (event != PSY_EVENT_PROP_CHANGED)
+ return NOTIFY_OK;
+
+ epp = amd_pstate_get_balanced_epp(policy);
+
+ ret = amd_pstate_set_epp(policy, epp);
+ if (ret)
+ pr_warn("Failed to set CPU %d EPP %u: %d\n", cpudata->cpu, epp, ret);
+
+ return NOTIFY_OK;
+}
+static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
+{
+ struct amd_cpudata *cpudata = policy->driver_data;
+
+ if (cpudata->power_nb.notifier_call)
+ power_supply_unreg_notifier(&cpudata->power_nb);
+ cpudata->dynamic_epp = false;
+}
+
+static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy)
+{
+ struct amd_cpudata *cpudata = policy->driver_data;
+ int ret;
+ u8 epp;
+
+ epp = amd_pstate_get_balanced_epp(policy);
+ ret = amd_pstate_set_epp(policy, epp);
+ if (ret)
+ return ret;
+
+ /* only enable notifier if things will actually change */
+ if (cpudata->epp_default_ac != cpudata->epp_default_dc) {
+ ret = power_supply_reg_notifier(&cpudata->power_nb);
+ if (ret)
+ goto cleanup;
+ cpudata->power_nb.notifier_call = amd_pstate_power_supply_notifier;
+ }
+
+ cpudata->dynamic_epp = true;
+
+ return 0;
+
+cleanup:
+ amd_pstate_clear_dynamic_epp(policy);
+
+ return ret;
+}
+
/* Sysfs attributes */
/*
@@ -1146,6 +1215,11 @@ static ssize_t store_energy_performance_preference(
ssize_t ret;
u8 epp;
+ if (cpudata->dynamic_epp) {
+ pr_debug("EPP cannot be set when dynamic EPP is enabled\n");
+ return -EBUSY;
+ }
+
ret = sscanf(buf, "%20s", str_preference);
if (ret != 1)
return -EINVAL;
@@ -1154,10 +1228,10 @@ static ssize_t store_energy_performance_preference(
if (ret < 0)
return -EINVAL;
- if (!ret)
- epp = cpudata->epp_default;
- else
+ if (ret)
epp = epp_values[ret];
+ else
+ epp = amd_pstate_get_balanced_epp(policy);
if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
pr_debug("EPP cannot be set under performance policy\n");
@@ -1165,6 +1239,8 @@ static ssize_t store_energy_performance_preference(
}
ret = amd_pstate_set_epp(policy, epp);
+ if (ret)
+ return ret;
return ret ? ret : count;
}
@@ -1364,6 +1440,32 @@ static ssize_t prefcore_show(struct device *dev,
return sysfs_emit(buf, "%s\n", str_enabled_disabled(amd_pstate_prefcore));
}
+static ssize_t dynamic_epp_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sysfs_emit(buf, "%s\n", str_enabled_disabled(dynamic_epp));
+}
+
+static ssize_t dynamic_epp_store(struct device *a, struct device_attribute *b,
+ const char *buf, size_t count)
+{
+ bool enabled;
+ int ret;
+
+ ret = kstrtobool(buf, &enabled);
+ if (ret)
+ return ret;
+
+ if (dynamic_epp == enabled)
+ return -EINVAL;
+
+ /* reinitialize with desired dynamic EPP value */
+ dynamic_epp = enabled;
+ ret = amd_pstate_change_driver_mode(cppc_state);
+
+ return ret ? ret : count;
+}
+
cpufreq_freq_attr_ro(amd_pstate_max_freq);
cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
@@ -1374,6 +1476,7 @@ cpufreq_freq_attr_rw(energy_performance_preference);
cpufreq_freq_attr_ro(energy_performance_available_preferences);
static DEVICE_ATTR_RW(status);
static DEVICE_ATTR_RO(prefcore);
+static DEVICE_ATTR_RW(dynamic_epp);
static struct freq_attr *amd_pstate_attr[] = {
&amd_pstate_max_freq,
@@ -1398,6 +1501,7 @@ static struct freq_attr *amd_pstate_epp_attr[] = {
static struct attribute *pstate_global_attributes[] = {
&dev_attr_status.attr,
&dev_attr_prefcore.attr,
+ &dev_attr_dynamic_epp.attr,
NULL
};
@@ -1490,10 +1594,11 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
if (amd_pstate_acpi_pm_profile_server() ||
amd_pstate_acpi_pm_profile_undefined()) {
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
- cpudata->epp_default = amd_pstate_get_epp(cpudata);
+ cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata);
} else {
policy->policy = CPUFREQ_POLICY_POWERSAVE;
- cpudata->epp_default = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
+ cpudata->epp_default_ac = AMD_CPPC_EPP_PERFORMANCE;
+ cpudata->epp_default_dc = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
}
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
@@ -1502,9 +1607,13 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
return ret;
WRITE_ONCE(cpudata->cppc_req_cached, value);
}
- ret = amd_pstate_set_epp(policy, cpudata->epp_default);
+
+ if (dynamic_epp)
+ ret = amd_pstate_set_dynamic_epp(policy);
+ else
+ ret = amd_pstate_set_epp(policy, amd_pstate_get_balanced_epp(policy));
if (ret)
- return ret;
+ goto free_cpudata1;
current_pstate_driver->adjust_perf = NULL;
@@ -1521,6 +1630,8 @@ static void amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
struct amd_cpudata *cpudata = policy->driver_data;
if (cpudata) {
+ if (cpudata->dynamic_epp)
+ amd_pstate_clear_dynamic_epp(policy);
kfree(cpudata);
policy->driver_data = NULL;
}
@@ -1556,6 +1667,10 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
if (!policy->cpuinfo.max_freq)
return -ENODEV;
+ /* policy can't be changed to performance policy while dynamic epp is enabled */
+ if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && cpudata->dynamic_epp)
+ return -EBUSY;
+
cpudata->policy = policy->policy;
ret = amd_pstate_epp_update_limit(policy);
diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
index fbe1c08d3f061..6882876f895de 100644
--- a/drivers/cpufreq/amd-pstate.h
+++ b/drivers/cpufreq/amd-pstate.h
@@ -104,7 +104,10 @@ struct amd_cpudata {
/* EPP feature related attributes*/
u32 policy;
bool suspended;
- u8 epp_default;
+ u8 epp_default_ac;
+ u8 epp_default_dc;
+ bool dynamic_epp;
+ struct notifier_block power_nb;
};
/*
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 2/5] cpufreq/amd-pstate: add kernel command line to override dynamic epp
2025-03-04 15:23 [PATCH v2 0/5] amd-pstate Dynamic EPP and raw EPP Mario Limonciello
2025-03-04 15:23 ` [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference Mario Limonciello
@ 2025-03-04 15:23 ` Mario Limonciello
2025-03-07 8:53 ` Gautham R. Shenoy
2025-03-04 15:23 ` [PATCH v2 3/5] cpufreq/amd-pstate: Add support for platform profile class Mario Limonciello
` (2 subsequent siblings)
4 siblings, 1 reply; 20+ messages in thread
From: Mario Limonciello @ 2025-03-04 15:23 UTC (permalink / raw)
To: Gautham R . Shenoy, Perry Yuan
Cc: Dhananjay Ugwekar, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
From: Mario Limonciello <mario.limonciello@amd.com>
Add `amd_dynamic_epp=enable` and `amd_dynamic_epp=disable` to override
the kernel configuration option `CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`
locally.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
Documentation/admin-guide/kernel-parameters.txt | 7 +++++++
Documentation/admin-guide/pm/amd-pstate.rst | 7 +++++++
drivers/cpufreq/amd-pstate.c | 11 +++++++++++
3 files changed, 25 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index fb8752b42ec85..1afe6d8ab09bb 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -392,6 +392,13 @@
disable
Disable amd-pstate preferred core.
+ amd_dynamic_epp=
+ [X86]
+ disable
+ Disable amd-pstate dynamic EPP.
+ enable
+ Enable amd-pstate dynamic EPP.
+
amijoy.map= [HW,JOY] Amiga joystick support
Map of devices attached to JOY0DAT and JOY1DAT
Format: <a>,<b>
diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
index 2e076650dc77c..8424e7119dd7e 100644
--- a/Documentation/admin-guide/pm/amd-pstate.rst
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
@@ -438,6 +438,13 @@ For systems that support ``amd-pstate`` preferred core, the core rankings will
always be advertised by the platform. But OS can choose to ignore that via the
kernel parameter ``amd_prefcore=disable``.
+``amd_dynamic_epp``
+
+When AMD pstate is in auto mode, dynamic EPP will control whether the kernel
+autonomously changes the EPP mode. The default is configured by
+``CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`` but can be explicitly enabled with
+``amd_pstate_epp=enable`` or disabled with ``amd_pstate_epp=disable``.
+
User Space Interface in ``sysfs`` - General
===========================================
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index f00fb4ba9f26e..9911808fe0bcf 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -1928,8 +1928,19 @@ static int __init amd_prefcore_param(char *str)
return 0;
}
+static int __init amd_dynamic_epp_param(char *str)
+{
+ if (!strcmp(str, "disable"))
+ dynamic_epp = false;
+ if (!strcmp(str, "enable"))
+ dynamic_epp = true;
+
+ return 0;
+}
+
early_param("amd_pstate", amd_pstate_param);
early_param("amd_prefcore", amd_prefcore_param);
+early_param("amd_dynamic_epp", amd_dynamic_epp_param);
MODULE_AUTHOR("Huang Rui <ray.huang@amd.com>");
MODULE_DESCRIPTION("AMD Processor P-state Frequency Driver");
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 3/5] cpufreq/amd-pstate: Add support for platform profile class
2025-03-04 15:23 [PATCH v2 0/5] amd-pstate Dynamic EPP and raw EPP Mario Limonciello
2025-03-04 15:23 ` [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference Mario Limonciello
2025-03-04 15:23 ` [PATCH v2 2/5] cpufreq/amd-pstate: add kernel command line to override dynamic epp Mario Limonciello
@ 2025-03-04 15:23 ` Mario Limonciello
2025-03-07 16:22 ` Gautham R. Shenoy
2025-03-04 15:23 ` [PATCH v2 4/5] cpufreq/amd-pstate: Add support for raw EPP writes Mario Limonciello
2025-03-04 15:23 ` [PATCH v2 5/5] cpufreq/amd-pstate-ut: Add a unit test for raw EPP Mario Limonciello
4 siblings, 1 reply; 20+ messages in thread
From: Mario Limonciello @ 2025-03-04 15:23 UTC (permalink / raw)
To: Gautham R . Shenoy, Perry Yuan
Cc: Dhananjay Ugwekar, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
From: Mario Limonciello <mario.limonciello@amd.com>
The platform profile core allows multiple drivers and devices to
register platform profile support.
When the legacy platform profile interface is used all drivers will
adjust the platform profile as well.
Add support for registering every CPU with the platform profile handler
when dynamic EPP is enabled.
The end result will be that changing the platform profile will modify
EPP accordingly.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
Documentation/admin-guide/pm/amd-pstate.rst | 4 +-
drivers/cpufreq/Kconfig.x86 | 1 +
drivers/cpufreq/amd-pstate.c | 142 +++++++++++++++++---
drivers/cpufreq/amd-pstate.h | 10 ++
4 files changed, 140 insertions(+), 17 deletions(-)
diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
index 8424e7119dd7e..36950fb6568c0 100644
--- a/Documentation/admin-guide/pm/amd-pstate.rst
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
@@ -321,7 +321,9 @@ Whether this behavior is enabled by default with the kernel config option
at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``.
When set to enabled, the driver will select a different energy performance
-profile when the machine is running on battery or AC power.
+profile when the machine is running on battery or AC power. The driver will
+also register with the platform profile handler to receive notifications of
+user desired power state and react to those.
When set to disabled, the driver will not change the energy performance profile
based on the power source and will not react to user desired power state.
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index c5ef92634ddf4..905eab998b836 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
@@ -40,6 +40,7 @@ config X86_AMD_PSTATE
select ACPI_PROCESSOR
select ACPI_CPPC_LIB if X86_64
select CPU_FREQ_GOV_SCHEDUTIL if SMP
+ select ACPI_PLATFORM_PROFILE
help
This driver adds a CPUFreq driver which utilizes a fine grain
processor performance frequency control range instead of legacy
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 9911808fe0bcf..28c02edf6e40b 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -105,6 +105,7 @@ static struct quirk_entry *quirks;
* 2 balance_performance
* 3 balance_power
* 4 power
+ * 5 custom (for raw EPP values)
*/
enum energy_perf_value_index {
EPP_INDEX_DEFAULT = 0,
@@ -112,6 +113,7 @@ enum energy_perf_value_index {
EPP_INDEX_BALANCE_PERFORMANCE,
EPP_INDEX_BALANCE_POWERSAVE,
EPP_INDEX_POWERSAVE,
+ EPP_INDEX_CUSTOM,
};
static const char * const energy_perf_strings[] = {
@@ -120,6 +122,7 @@ static const char * const energy_perf_strings[] = {
[EPP_INDEX_BALANCE_PERFORMANCE] = "balance_performance",
[EPP_INDEX_BALANCE_POWERSAVE] = "balance_power",
[EPP_INDEX_POWERSAVE] = "power",
+ [EPP_INDEX_CUSTOM] = "custom",
NULL
};
@@ -1073,6 +1076,10 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
if (event != PSY_EVENT_PROP_CHANGED)
return NOTIFY_OK;
+ /* dynamic actions are only applied while platform profile is in balanced */
+ if (cpudata->current_profile != PLATFORM_PROFILE_BALANCED)
+ return 0;
+
epp = amd_pstate_get_balanced_epp(policy);
ret = amd_pstate_set_epp(policy, epp);
@@ -1081,14 +1088,84 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
return NOTIFY_OK;
}
-static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
+
+static int amd_pstate_profile_probe(void *drvdata, unsigned long *choices)
+{
+ set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
+ set_bit(PLATFORM_PROFILE_BALANCED, choices);
+ set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
+
+ return 0;
+}
+
+static int amd_pstate_profile_get(struct device *dev,
+ enum platform_profile_option *profile)
+{
+ struct amd_cpudata *cpudata = dev_get_drvdata(dev);
+
+ *profile = cpudata->current_profile;
+
+ return 0;
+}
+
+static int amd_pstate_profile_set(struct device *dev,
+ enum platform_profile_option profile)
+{
+ struct amd_cpudata *cpudata = dev_get_drvdata(dev);
+ struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
+ int ret;
+
+ switch (profile) {
+ case PLATFORM_PROFILE_LOW_POWER:
+ if (cpudata->policy != CPUFREQ_POLICY_POWERSAVE)
+ cpudata->policy = CPUFREQ_POLICY_POWERSAVE;
+ ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_POWERSAVE);
+ if (ret)
+ return ret;
+ break;
+ case PLATFORM_PROFILE_BALANCED:
+ if (cpudata->policy != CPUFREQ_POLICY_POWERSAVE)
+ cpudata->policy = CPUFREQ_POLICY_POWERSAVE;
+ ret = amd_pstate_set_epp(policy,
+ amd_pstate_get_balanced_epp(policy));
+ if (ret)
+ return ret;
+ break;
+ case PLATFORM_PROFILE_PERFORMANCE:
+ ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_PERFORMANCE);
+ if (ret)
+ return ret;
+ break;
+ default:
+ pr_err("Unknown Platform Profile %d\n", profile);
+ return -EOPNOTSUPP;
+ }
+
+ cpudata->current_profile = profile;
+
+ return 0;
+}
+
+static const struct platform_profile_ops amd_pstate_profile_ops = {
+ .probe = amd_pstate_profile_probe,
+ .profile_set = amd_pstate_profile_set,
+ .profile_get = amd_pstate_profile_get,
+};
+
+void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
{
struct amd_cpudata *cpudata = policy->driver_data;
if (cpudata->power_nb.notifier_call)
power_supply_unreg_notifier(&cpudata->power_nb);
+ if (cpudata->ppdev) {
+ platform_profile_remove(cpudata->ppdev);
+ cpudata->ppdev = NULL;
+ }
+ kfree(cpudata->profile_name);
cpudata->dynamic_epp = false;
}
+EXPORT_SYMBOL_GPL(amd_pstate_clear_dynamic_epp);
static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy)
{
@@ -1096,11 +1173,35 @@ static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy)
int ret;
u8 epp;
- epp = amd_pstate_get_balanced_epp(policy);
+ switch (cpudata->current_profile) {
+ case PLATFORM_PROFILE_PERFORMANCE:
+ epp = AMD_CPPC_EPP_PERFORMANCE;
+ break;
+ case PLATFORM_PROFILE_LOW_POWER:
+ epp = AMD_CPPC_EPP_POWERSAVE;
+ break;
+ case PLATFORM_PROFILE_BALANCED:
+ epp = amd_pstate_get_balanced_epp(policy);
+ break;
+ default:
+ pr_err("Unknown Platform Profile %d\n", cpudata->current_profile);
+ return -EOPNOTSUPP;
+ }
ret = amd_pstate_set_epp(policy, epp);
if (ret)
return ret;
+ cpudata->profile_name = kasprintf(GFP_KERNEL, "amd-pstate-epp-cpu%d", cpudata->cpu);
+
+ cpudata->ppdev = platform_profile_register(get_cpu_device(policy->cpu),
+ cpudata->profile_name,
+ policy->driver_data,
+ &amd_pstate_profile_ops);
+ if (IS_ERR(cpudata->ppdev)) {
+ ret = PTR_ERR(cpudata->ppdev);
+ goto cleanup;
+ }
+
/* only enable notifier if things will actually change */
if (cpudata->epp_default_ac != cpudata->epp_default_dc) {
ret = power_supply_reg_notifier(&cpudata->power_nb);
@@ -1207,8 +1308,8 @@ static ssize_t show_energy_performance_available_preferences(
return offset;
}
-static ssize_t store_energy_performance_preference(
- struct cpufreq_policy *policy, const char *buf, size_t count)
+ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
+ const char *buf, size_t count)
{
struct amd_cpudata *cpudata = policy->driver_data;
char str_preference[21];
@@ -1224,16 +1325,22 @@ static ssize_t store_energy_performance_preference(
if (ret != 1)
return -EINVAL;
- ret = match_string(energy_perf_strings, -1, str_preference);
- if (ret < 0)
- return -EINVAL;
-
- if (ret)
- epp = epp_values[ret];
- else
- epp = amd_pstate_get_balanced_epp(policy);
+ /*
+ * if the value matches a number, use that, otherwise see if
+ * matches an index in the energy_perf_strings array
+ */
+ ret = kstrtou8(str_preference, 0, &epp);
+ if (ret) {
+ ret = match_string(energy_perf_strings, -1, str_preference);
+ if (ret < 0 || ret == EPP_INDEX_CUSTOM)
+ return -EINVAL;
+ if (ret)
+ epp = epp_values[ret];
+ else
+ epp = amd_pstate_get_balanced_epp(policy);
+ }
- if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
+ if (epp > 0 && cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
pr_debug("EPP cannot be set under performance policy\n");
return -EBUSY;
}
@@ -1244,9 +1351,9 @@ static ssize_t store_energy_performance_preference(
return ret ? ret : count;
}
+EXPORT_SYMBOL_GPL(store_energy_performance_preference);
-static ssize_t show_energy_performance_preference(
- struct cpufreq_policy *policy, char *buf)
+ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf)
{
struct amd_cpudata *cpudata = policy->driver_data;
u8 preference, epp;
@@ -1267,11 +1374,12 @@ static ssize_t show_energy_performance_preference(
preference = EPP_INDEX_POWERSAVE;
break;
default:
- return -EINVAL;
+ return sysfs_emit(buf, "%u\n", epp);
}
return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]);
}
+EXPORT_SYMBOL_GPL(show_energy_performance_preference);
static void amd_pstate_driver_cleanup(void)
{
@@ -1595,10 +1703,12 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
amd_pstate_acpi_pm_profile_undefined()) {
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata);
+ cpudata->current_profile = PLATFORM_PROFILE_PERFORMANCE;
} else {
policy->policy = CPUFREQ_POLICY_POWERSAVE;
cpudata->epp_default_ac = AMD_CPPC_EPP_PERFORMANCE;
cpudata->epp_default_dc = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
+ cpudata->current_profile = PLATFORM_PROFILE_BALANCED;
}
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
index 6882876f895de..b4c5374762110 100644
--- a/drivers/cpufreq/amd-pstate.h
+++ b/drivers/cpufreq/amd-pstate.h
@@ -9,6 +9,7 @@
#define _LINUX_AMD_PSTATE_H
#include <linux/pm_qos.h>
+#include <linux/platform_profile.h>
/*********************************************************************
* AMD P-state INTERFACE *
@@ -108,6 +109,11 @@ struct amd_cpudata {
u8 epp_default_dc;
bool dynamic_epp;
struct notifier_block power_nb;
+
+ /* platform profile */
+ enum platform_profile_option current_profile;
+ struct device *ppdev;
+ char *profile_name;
};
/*
@@ -123,5 +129,9 @@ enum amd_pstate_mode {
};
const char *amd_pstate_get_mode_string(enum amd_pstate_mode mode);
int amd_pstate_update_status(const char *buf, size_t size);
+ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
+ const char *buf, size_t count);
+ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf);
+void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy);
#endif /* _LINUX_AMD_PSTATE_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 4/5] cpufreq/amd-pstate: Add support for raw EPP writes
2025-03-04 15:23 [PATCH v2 0/5] amd-pstate Dynamic EPP and raw EPP Mario Limonciello
` (2 preceding siblings ...)
2025-03-04 15:23 ` [PATCH v2 3/5] cpufreq/amd-pstate: Add support for platform profile class Mario Limonciello
@ 2025-03-04 15:23 ` Mario Limonciello
2025-03-04 15:23 ` [PATCH v2 5/5] cpufreq/amd-pstate-ut: Add a unit test for raw EPP Mario Limonciello
4 siblings, 0 replies; 20+ messages in thread
From: Mario Limonciello @ 2025-03-04 15:23 UTC (permalink / raw)
To: Gautham R . Shenoy, Perry Yuan
Cc: Dhananjay Ugwekar, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
From: Mario Limonciello <mario.limonciello@amd.com>
The energy performance preference field of the CPPC request MSR
supports values from 0 to 255, but the strings only offer 4 values.
The other values are useful for tuning the performance of some
workloads.
Add support for writing the raw energy performance preference value
to the sysfs file. If the last value written was an integer then
an integer will be returned. If the last value written was a string
then a string will be returned.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
Documentation/admin-guide/pm/amd-pstate.rst | 16 +++++++++++-----
drivers/cpufreq/amd-pstate.c | 11 +++++++++--
drivers/cpufreq/amd-pstate.h | 1 +
3 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
index 36950fb6568c0..0e4d2e0aaeff7 100644
--- a/Documentation/admin-guide/pm/amd-pstate.rst
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
@@ -280,16 +280,22 @@ A list of all the supported EPP preferences that could be used for
These profiles represent different hints that are provided
to the low-level firmware about the user's desired energy vs efficiency
tradeoff. ``default`` represents the epp value is set by platform
-firmware. This attribute is read-only.
+firmware. ``custom`` designates that integer values 0-255 may be written
+as well. This attribute is read-only.
``energy_performance_preference``
The current energy performance preference can be read from this attribute.
and user can change current preference according to energy or performance needs
-Please get all support profiles list from
-``energy_performance_available_preferences`` attribute, all the profiles are
-integer values defined between 0 to 255 when EPP feature is enabled by platform
-firmware, but if the dynamic EPP feature is enabled, driver will block writes.
+Coarse named profiles are available in the attribute
+``energy_performance_available_preferences``.
+Users can also write individual integer values between 0 to 255.
+When EPP feature is enabled by platform firmware but if the dynamic EPP feature is
+enabled, driver will ignore the written value. Lower epp values shift the bias
+towards improved performance while a higher epp value shifts the bias towards
+power-savings. The exact impact can change from one platform to the other.
+If a valid integer was last written, then a number will be returned on future reads.
+If a valid string was last written then a string will be returned on future reads.
This attribute is read-write.
``boost``
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 28c02edf6e40b..dcf6e36d693f8 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -1314,6 +1314,7 @@ ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
struct amd_cpudata *cpudata = policy->driver_data;
char str_preference[21];
ssize_t ret;
+ bool raw_epp = FALSE;
u8 epp;
if (cpudata->dynamic_epp) {
@@ -1330,6 +1331,7 @@ ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
* matches an index in the energy_perf_strings array
*/
ret = kstrtou8(str_preference, 0, &epp);
+ raw_epp = !ret;
if (ret) {
ret = match_string(energy_perf_strings, -1, str_preference);
if (ret < 0 || ret == EPP_INDEX_CUSTOM)
@@ -1349,7 +1351,9 @@ ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
if (ret)
return ret;
- return ret ? ret : count;
+ cpudata->raw_epp = raw_epp;
+
+ return count;
}
EXPORT_SYMBOL_GPL(store_energy_performance_preference);
@@ -1360,6 +1364,9 @@ ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *
epp = FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached);
+ if (cpudata->raw_epp)
+ return sysfs_emit(buf, "%u\n", epp);
+
switch (epp) {
case AMD_CPPC_EPP_PERFORMANCE:
preference = EPP_INDEX_PERFORMANCE;
@@ -1374,7 +1381,7 @@ ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *
preference = EPP_INDEX_POWERSAVE;
break;
default:
- return sysfs_emit(buf, "%u\n", epp);
+ return -EINVAL;
}
return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]);
diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
index b4c5374762110..b6be2b8fbffbf 100644
--- a/drivers/cpufreq/amd-pstate.h
+++ b/drivers/cpufreq/amd-pstate.h
@@ -108,6 +108,7 @@ struct amd_cpudata {
u8 epp_default_ac;
u8 epp_default_dc;
bool dynamic_epp;
+ bool raw_epp;
struct notifier_block power_nb;
/* platform profile */
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v2 5/5] cpufreq/amd-pstate-ut: Add a unit test for raw EPP
2025-03-04 15:23 [PATCH v2 0/5] amd-pstate Dynamic EPP and raw EPP Mario Limonciello
` (3 preceding siblings ...)
2025-03-04 15:23 ` [PATCH v2 4/5] cpufreq/amd-pstate: Add support for raw EPP writes Mario Limonciello
@ 2025-03-04 15:23 ` Mario Limonciello
4 siblings, 0 replies; 20+ messages in thread
From: Mario Limonciello @ 2025-03-04 15:23 UTC (permalink / raw)
To: Gautham R . Shenoy, Perry Yuan
Cc: Dhananjay Ugwekar, open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
From: Mario Limonciello <mario.limonciello@amd.com>
Ensure that all supported raw EPP values work properly.
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
drivers/cpufreq/amd-pstate-ut.c | 58 +++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/drivers/cpufreq/amd-pstate-ut.c b/drivers/cpufreq/amd-pstate-ut.c
index e671bc7d15508..d0c5c0aa3cc94 100644
--- a/drivers/cpufreq/amd-pstate-ut.c
+++ b/drivers/cpufreq/amd-pstate-ut.c
@@ -26,6 +26,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/cleanup.h>
@@ -33,6 +34,7 @@
#include "amd-pstate.h"
+DEFINE_FREE(free_page, void *, if (_T) free_page((unsigned long)_T))
struct amd_pstate_ut_struct {
const char *name;
@@ -46,6 +48,7 @@ static int amd_pstate_ut_acpi_cpc_valid(u32 index);
static int amd_pstate_ut_check_enabled(u32 index);
static int amd_pstate_ut_check_perf(u32 index);
static int amd_pstate_ut_check_freq(u32 index);
+static int amd_pstate_ut_epp(u32 index);
static int amd_pstate_ut_check_driver(u32 index);
static struct amd_pstate_ut_struct amd_pstate_ut_cases[] = {
@@ -53,6 +56,7 @@ static struct amd_pstate_ut_struct amd_pstate_ut_cases[] = {
{"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_epp", amd_pstate_ut_epp },
{"amd_pstate_ut_check_driver", amd_pstate_ut_check_driver }
};
@@ -239,6 +243,60 @@ static int amd_pstate_set_mode(enum amd_pstate_mode mode)
return amd_pstate_update_status(mode_str, strlen(mode_str));
}
+static int amd_pstate_ut_epp(u32 index)
+{
+ struct cpufreq_policy *policy __free(put_cpufreq_policy) = NULL;
+ void *buf __free(free_page) = NULL;
+ struct amd_cpudata *cpudata;
+ int ret, cpu = 0;
+ u16 epp;
+
+ policy = cpufreq_cpu_get(cpu);
+ if (!policy)
+ return -ENODEV;
+
+ cpudata = policy->driver_data;
+
+ /* disable dynamic EPP before running test */
+ if (cpudata->dynamic_epp) {
+ pr_debug("Dynamic EPP is enabled, disabling it\n");
+ amd_pstate_clear_dynamic_epp(policy);
+ }
+
+ buf = (void *)__get_free_page(GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = amd_pstate_set_mode(AMD_PSTATE_ACTIVE);
+ if (ret)
+ return ret;
+
+ for (epp = 0; epp <= U8_MAX; epp++) {
+ u8 val;
+
+ /* write all EPP values */
+ memset(buf, 0, sizeof(*buf));
+ snprintf(buf, PAGE_SIZE, "%d", epp);
+ ret = store_energy_performance_preference(policy, buf, sizeof(*buf));
+ if (ret < 0)
+ return ret;
+
+ /* check if the EPP value reads back correctly for raw numbers */
+ memset(buf, 0, sizeof(*buf));
+ ret = show_energy_performance_preference(policy, buf);
+ if (ret < 0)
+ return ret;
+ strreplace(buf, '\n', '\0');
+ ret = kstrtou8(buf, 0, &val);
+ if (!ret && epp != val) {
+ pr_err("Raw EPP value mismatch: %d != %d\n", epp, val);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int amd_pstate_ut_check_driver(u32 index)
{
enum amd_pstate_mode mode1, mode2 = AMD_PSTATE_DISABLE;
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference
2025-03-04 15:23 ` [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference Mario Limonciello
@ 2025-03-07 6:45 ` Gautham R. Shenoy
2025-03-11 6:34 ` Dhananjay Ugwekar
2025-03-12 12:16 ` Dhananjay Ugwekar
2 siblings, 0 replies; 20+ messages in thread
From: Gautham R. Shenoy @ 2025-03-07 6:45 UTC (permalink / raw)
To: Mario Limonciello
Cc: Perry Yuan, Dhananjay Ugwekar,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
Hello Mario,
On Tue, Mar 04, 2025 at 09:23:23AM -0600, Mario Limonciello wrote:
> From: Mario Limonciello <mario.limonciello@amd.com>
>
> Dynamic energy performance preference will change the EPP profile
> based on whether the machine is running on AC or DC power.
>
> A notification chain from the power supply core is used to adjust
> EPP values on plug in or plug out events.
>
> For non-server systems:
> * the default EPP for AC mode is `performance`.
> * the default EPP for DC mode is `balance_performance`.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
> v1->v2:
> * Change defaults to performance (AC) and balance_performance (DC)
> * Default Kconfig to disabled for now
> * Rebase on latest branch
> ---
> Documentation/admin-guide/pm/amd-pstate.rst | 18 ++-
> drivers/cpufreq/Kconfig.x86 | 12 ++
> drivers/cpufreq/amd-pstate.c | 129 ++++++++++++++++++--
> drivers/cpufreq/amd-pstate.h | 5 +-
> 4 files changed, 155 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
> index 412423c54f258..2e076650dc77c 100644
> --- a/Documentation/admin-guide/pm/amd-pstate.rst
> +++ b/Documentation/admin-guide/pm/amd-pstate.rst
[...snip..]
> @@ -311,6 +311,22 @@ boost or `1` to enable it, for the respective CPU using the sysfs path
> Other performance and frequency values can be read back from
> ``/sys/devices/system/cpu/cpuX/acpi_cppc/``, see :ref:`cppc_sysfs`.
>
> +Dynamic energy performance profile
> +==================================
> +The amd-pstate driver supports dynamically selecting the energy performance
> +profile based on whether the machine is running on AC or DC power.
> +
> +Whether this behavior is enabled by default with the kernel config option
> +`CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`. This behavior can also be overridden
> +at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``.
> +
> +When set to enabled, the driver will select a different energy performance
> +profile when the machine is running on battery or AC power.
> +When set to disabled, the driver will not change the energy performance profile
> +based on the power source and will not react to user desired power state.
> +
> +Attempting to manually write to the ``energy_performance_preference`` sysfs
> +file will fail when ``dynamic_epp`` is enabled.
>
> ``amd-pstate`` vs ``acpi-cpufreq``
> ======================================
> diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
> index 97c2d4f15d76e..c5ef92634ddf4 100644
> --- a/drivers/cpufreq/Kconfig.x86
> +++ b/drivers/cpufreq/Kconfig.x86
> @@ -68,6 +68,18 @@ config X86_AMD_PSTATE_DEFAULT_MODE
> For details, take a look at:
> <file:Documentation/admin-guide/pm/amd-pstate.rst>.
>
> +config X86_AMD_PSTATE_DYNAMIC_EPP
> + bool "AMD Processor P-State dynamic EPP support"
> + depends on X86_AMD_PSTATE
> + default n
> + help
> + Allow the kenrel to dynamically change the energy performance
^^^^^^
kernel
> + value from events like ACPI platform profile and AC adapter plug
> + events.
> +
> + This feature can also be changed at runtime, this configuration
> + option only sets the kernel default value behavior.
> +
> config X86_AMD_PSTATE_UT
> tristate "selftest for AMD Processor P-State driver"
> depends on X86 && ACPI_PROCESSOR
> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
> index e98ef41083ba1..f00fb4ba9f26e 100644
> --- a/drivers/cpufreq/amd-pstate.c
> +++ b/drivers/cpufreq/amd-pstate.c
> @@ -36,6 +36,7 @@
> #include <linux/io.h>
> #include <linux/delay.h>
> #include <linux/uaccess.h>
> +#include <linux/power_supply.h>
> #include <linux/static_call.h>
> #include <linux/topology.h>
>
> @@ -86,6 +87,7 @@ static struct cpufreq_driver amd_pstate_driver;
> static struct cpufreq_driver amd_pstate_epp_driver;
> static int cppc_state = AMD_PSTATE_UNDEFINED;
> static bool amd_pstate_prefcore = true;
> +static bool dynamic_epp = CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP;
> static struct quirk_entry *quirks;
>
> /*
> @@ -1050,6 +1052,73 @@ static void amd_pstate_cpu_exit(struct cpufreq_policy *policy)
> kfree(cpudata);
> }
>
> +static int amd_pstate_get_balanced_epp(struct cpufreq_policy *policy)
Can we rename this function as amd_pstate_get_dynamic_epp() ?
Because the values being returned may not be
balance_performance/balance_power.
> +{
> + struct amd_cpudata *cpudata = policy->driver_data;
> +
> + if (power_supply_is_system_supplied())
> + return cpudata->epp_default_ac;
> + else
> + return cpudata->epp_default_dc;
> +}
> +
> +static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
> + unsigned long event, void *data)
> +{
> + struct amd_cpudata *cpudata = container_of(nb, struct amd_cpudata, power_nb);
> + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
> + u8 epp;
> + int ret;
> +
> + if (event != PSY_EVENT_PROP_CHANGED)
> + return NOTIFY_OK;
> +
> + epp = amd_pstate_get_balanced_epp(policy);
> +
> + ret = amd_pstate_set_epp(policy, epp);
> + if (ret)
> + pr_warn("Failed to set CPU %d EPP %u: %d\n", cpudata->cpu, epp, ret);
> +
> + return NOTIFY_OK;
> +}
> +static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
> +{
> + struct amd_cpudata *cpudata = policy->driver_data;
> +
> + if (cpudata->power_nb.notifier_call)
> + power_supply_unreg_notifier(&cpudata->power_nb);
> + cpudata->dynamic_epp = false;
> +}
> +
> +static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy)
> +{
> + struct amd_cpudata *cpudata = policy->driver_data;
> + int ret;
> + u8 epp;
> +
> + epp = amd_pstate_get_balanced_epp(policy);
> + ret = amd_pstate_set_epp(policy, epp);
> + if (ret)
> + return ret;
> +
> + /* only enable notifier if things will actually change */
> + if (cpudata->epp_default_ac != cpudata->epp_default_dc) {
> + ret = power_supply_reg_notifier(&cpudata->power_nb);
> + if (ret)
> + goto cleanup;
> + cpudata->power_nb.notifier_call = amd_pstate_power_supply_notifier;
> + }
> +
> + cpudata->dynamic_epp = true;
> +
> + return 0;
> +
> +cleanup:
> + amd_pstate_clear_dynamic_epp(policy);
> +
> + return ret;
> +}
> +
> /* Sysfs attributes */
>
> /*
> @@ -1146,6 +1215,11 @@ static ssize_t store_energy_performance_preference(
> ssize_t ret;
> u8 epp;
>
> + if (cpudata->dynamic_epp) {
> + pr_debug("EPP cannot be set when dynamic EPP is enabled\n");
> + return -EBUSY;
> + }
> +
> ret = sscanf(buf, "%20s", str_preference);
> if (ret != 1)
> return -EINVAL;
> @@ -1154,10 +1228,10 @@ static ssize_t store_energy_performance_preference(
> if (ret < 0)
> return -EINVAL;
>
> - if (!ret)
> - epp = cpudata->epp_default;
> - else
> + if (ret)
> epp = epp_values[ret];
> + else
> + epp = amd_pstate_get_balanced_epp(policy);
>
> if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
> pr_debug("EPP cannot be set under performance policy\n");
> @@ -1165,6 +1239,8 @@ static ssize_t store_energy_performance_preference(
> }
>
> ret = amd_pstate_set_epp(policy, epp);
> + if (ret)
> + return ret;
Isn't this unecessary given that the next line is doing exactly this ?
>
> return ret ? ret : count;
> }
Rest of the patch looks good to me.
--
Thanks and Regards
gautham.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 2/5] cpufreq/amd-pstate: add kernel command line to override dynamic epp
2025-03-04 15:23 ` [PATCH v2 2/5] cpufreq/amd-pstate: add kernel command line to override dynamic epp Mario Limonciello
@ 2025-03-07 8:53 ` Gautham R. Shenoy
0 siblings, 0 replies; 20+ messages in thread
From: Gautham R. Shenoy @ 2025-03-07 8:53 UTC (permalink / raw)
To: Mario Limonciello
Cc: Perry Yuan, Dhananjay Ugwekar,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
On Tue, Mar 04, 2025 at 09:23:24AM -0600, Mario Limonciello wrote:
> From: Mario Limonciello <mario.limonciello@amd.com>
>
> Add `amd_dynamic_epp=enable` and `amd_dynamic_epp=disable` to override
> the kernel configuration option `CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`
> locally.
Even with this patch, the user can switch the dynamic_epp value via
the sysfs file. However, it is useful in case the
CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP value is switched in the future.
I suspect that the servers will prefer to have this feature disabled
by default (they are always on AC power!) while the laptop/battery
operated devices would prefer to have this option enabled by default.
Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
--
Thanks and Regards
gautham.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
> Documentation/admin-guide/kernel-parameters.txt | 7 +++++++
> Documentation/admin-guide/pm/amd-pstate.rst | 7 +++++++
> drivers/cpufreq/amd-pstate.c | 11 +++++++++++
> 3 files changed, 25 insertions(+)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index fb8752b42ec85..1afe6d8ab09bb 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -392,6 +392,13 @@
> disable
> Disable amd-pstate preferred core.
>
> + amd_dynamic_epp=
> + [X86]
> + disable
> + Disable amd-pstate dynamic EPP.
> + enable
> + Enable amd-pstate dynamic EPP.
> +
> amijoy.map= [HW,JOY] Amiga joystick support
> Map of devices attached to JOY0DAT and JOY1DAT
> Format: <a>,<b>
> diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
> index 2e076650dc77c..8424e7119dd7e 100644
> --- a/Documentation/admin-guide/pm/amd-pstate.rst
> +++ b/Documentation/admin-guide/pm/amd-pstate.rst
> @@ -438,6 +438,13 @@ For systems that support ``amd-pstate`` preferred core, the core rankings will
> always be advertised by the platform. But OS can choose to ignore that via the
> kernel parameter ``amd_prefcore=disable``.
>
> +``amd_dynamic_epp``
> +
> +When AMD pstate is in auto mode, dynamic EPP will control whether the kernel
> +autonomously changes the EPP mode. The default is configured by
> +``CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`` but can be explicitly enabled with
> +``amd_pstate_epp=enable`` or disabled with ``amd_pstate_epp=disable``.
> +
> User Space Interface in ``sysfs`` - General
> ===========================================
>
> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
> index f00fb4ba9f26e..9911808fe0bcf 100644
> --- a/drivers/cpufreq/amd-pstate.c
> +++ b/drivers/cpufreq/amd-pstate.c
> @@ -1928,8 +1928,19 @@ static int __init amd_prefcore_param(char *str)
> return 0;
> }
>
> +static int __init amd_dynamic_epp_param(char *str)
> +{
> + if (!strcmp(str, "disable"))
> + dynamic_epp = false;
> + if (!strcmp(str, "enable"))
> + dynamic_epp = true;
> +
> + return 0;
> +}
> +
> early_param("amd_pstate", amd_pstate_param);
> early_param("amd_prefcore", amd_prefcore_param);
> +early_param("amd_dynamic_epp", amd_dynamic_epp_param);
>
> MODULE_AUTHOR("Huang Rui <ray.huang@amd.com>");
> MODULE_DESCRIPTION("AMD Processor P-state Frequency Driver");
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 3/5] cpufreq/amd-pstate: Add support for platform profile class
2025-03-04 15:23 ` [PATCH v2 3/5] cpufreq/amd-pstate: Add support for platform profile class Mario Limonciello
@ 2025-03-07 16:22 ` Gautham R. Shenoy
2025-03-07 16:55 ` Mario Limonciello
0 siblings, 1 reply; 20+ messages in thread
From: Gautham R. Shenoy @ 2025-03-07 16:22 UTC (permalink / raw)
To: Mario Limonciello
Cc: Perry Yuan, Dhananjay Ugwekar,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
On Tue, Mar 04, 2025 at 09:23:25AM -0600, Mario Limonciello wrote:
> From: Mario Limonciello <mario.limonciello@amd.com>
>
> The platform profile core allows multiple drivers and devices to
> register platform profile support.
>
> When the legacy platform profile interface is used all drivers will
> adjust the platform profile as well.
>
> Add support for registering every CPU with the platform profile handler
> when dynamic EPP is enabled.
>
> The end result will be that changing the platform profile will modify
> EPP accordingly.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
> Documentation/admin-guide/pm/amd-pstate.rst | 4 +-
> drivers/cpufreq/Kconfig.x86 | 1 +
> drivers/cpufreq/amd-pstate.c | 142 +++++++++++++++++---
> drivers/cpufreq/amd-pstate.h | 10 ++
> 4 files changed, 140 insertions(+), 17 deletions(-)
>
> diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
> index 8424e7119dd7e..36950fb6568c0 100644
> --- a/Documentation/admin-guide/pm/amd-pstate.rst
> +++ b/Documentation/admin-guide/pm/amd-pstate.rst
> @@ -321,7 +321,9 @@ Whether this behavior is enabled by default with the kernel config option
> at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``.
>
> When set to enabled, the driver will select a different energy performance
> -profile when the machine is running on battery or AC power.
> +profile when the machine is running on battery or AC power. The driver will
> +also register with the platform profile handler to receive notifications of
> +user desired power state and react to those.
> When set to disabled, the driver will not change the energy performance profile
> based on the power source and will not react to user desired power state.
>
> diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
> index c5ef92634ddf4..905eab998b836 100644
> --- a/drivers/cpufreq/Kconfig.x86
> +++ b/drivers/cpufreq/Kconfig.x86
> @@ -40,6 +40,7 @@ config X86_AMD_PSTATE
> select ACPI_PROCESSOR
> select ACPI_CPPC_LIB if X86_64
> select CPU_FREQ_GOV_SCHEDUTIL if SMP
> + select ACPI_PLATFORM_PROFILE
> help
> This driver adds a CPUFreq driver which utilizes a fine grain
> processor performance frequency control range instead of legacy
> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
> index 9911808fe0bcf..28c02edf6e40b 100644
> --- a/drivers/cpufreq/amd-pstate.c
> +++ b/drivers/cpufreq/amd-pstate.c
> @@ -105,6 +105,7 @@ static struct quirk_entry *quirks;
> * 2 balance_performance
> * 3 balance_power
> * 4 power
> + * 5 custom (for raw EPP values)
> */
> enum energy_perf_value_index {
> EPP_INDEX_DEFAULT = 0,
> @@ -112,6 +113,7 @@ enum energy_perf_value_index {
> EPP_INDEX_BALANCE_PERFORMANCE,
> EPP_INDEX_BALANCE_POWERSAVE,
> EPP_INDEX_POWERSAVE,
> + EPP_INDEX_CUSTOM,
> };
>
> static const char * const energy_perf_strings[] = {
> @@ -120,6 +122,7 @@ static const char * const energy_perf_strings[] = {
> [EPP_INDEX_BALANCE_PERFORMANCE] = "balance_performance",
> [EPP_INDEX_BALANCE_POWERSAVE] = "balance_power",
> [EPP_INDEX_POWERSAVE] = "power",
> + [EPP_INDEX_CUSTOM] = "custom",
> NULL
> };
>
> @@ -1073,6 +1076,10 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
> if (event != PSY_EVENT_PROP_CHANGED)
> return NOTIFY_OK;
>
> + /* dynamic actions are only applied while platform profile is in balanced */
> + if (cpudata->current_profile != PLATFORM_PROFILE_BALANCED)
> + return 0;
> +
> epp = amd_pstate_get_balanced_epp(policy);
>
> ret = amd_pstate_set_epp(policy, epp);
> @@ -1081,14 +1088,84 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
>
> return NOTIFY_OK;
> }
> -static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
> +
> +static int amd_pstate_profile_probe(void *drvdata, unsigned long *choices)
> +{
> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
> +
> + return 0;
> +}
> +
> +static int amd_pstate_profile_get(struct device *dev,
> + enum platform_profile_option *profile)
> +{
> + struct amd_cpudata *cpudata = dev_get_drvdata(dev);
> +
> + *profile = cpudata->current_profile;
> +
> + return 0;
> +}
> +
> +static int amd_pstate_profile_set(struct device *dev,
> + enum platform_profile_option profile)
> +{
> + struct amd_cpudata *cpudata = dev_get_drvdata(dev);
> + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
> + int ret;
> +
> + switch (profile) {
> + case PLATFORM_PROFILE_LOW_POWER:
> + if (cpudata->policy != CPUFREQ_POLICY_POWERSAVE)
> + cpudata->policy = CPUFREQ_POLICY_POWERSAVE;
So prior to the patch, cpudata->policy is supposed to mirror
policy->policy. With this patch, this assumption is no longer
true. So it is possible for the user to again override the choice of
EPP set via platform profile by changing the cpufreq governor ?
Is this the expected behaviour?
The bigger concern is, if the governor was previously "performance"
and then the platform profile requested "low power", "cat
/sys/devices/system/cpu/cpuX/cpufreq/scaling_governor" would still
show "performance", which is inconsistent with the behaviour.
--
Thanks and Regards
gautham.
> + ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_POWERSAVE);
> + if (ret)
> + return ret;
> + break;
> + case PLATFORM_PROFILE_BALANCED:
> + if (cpudata->policy != CPUFREQ_POLICY_POWERSAVE)
> + cpudata->policy = CPUFREQ_POLICY_POWERSAVE;
> + ret = amd_pstate_set_epp(policy,
> + amd_pstate_get_balanced_epp(policy));
> + if (ret)
> + return ret;
> + break;
> + case PLATFORM_PROFILE_PERFORMANCE:
> + ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_PERFORMANCE);
> + if (ret)
> + return ret;
> + break;
> + default:
> + pr_err("Unknown Platform Profile %d\n", profile);
> + return -EOPNOTSUPP;
> + }
> +
> + cpudata->current_profile = profile;
> +
> + return 0;
> +}
> +
> +static const struct platform_profile_ops amd_pstate_profile_ops = {
> + .probe = amd_pstate_profile_probe,
> + .profile_set = amd_pstate_profile_set,
> + .profile_get = amd_pstate_profile_get,
> +};
> +
> +void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
> {
> struct amd_cpudata *cpudata = policy->driver_data;
>
> if (cpudata->power_nb.notifier_call)
> power_supply_unreg_notifier(&cpudata->power_nb);
> + if (cpudata->ppdev) {
> + platform_profile_remove(cpudata->ppdev);
> + cpudata->ppdev = NULL;
> + }
> + kfree(cpudata->profile_name);
> cpudata->dynamic_epp = false;
> }
> +EXPORT_SYMBOL_GPL(amd_pstate_clear_dynamic_epp);
>
> static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy)
> {
> @@ -1096,11 +1173,35 @@ static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy)
> int ret;
> u8 epp;
>
> - epp = amd_pstate_get_balanced_epp(policy);
> + switch (cpudata->current_profile) {
> + case PLATFORM_PROFILE_PERFORMANCE:
> + epp = AMD_CPPC_EPP_PERFORMANCE;
> + break;
> + case PLATFORM_PROFILE_LOW_POWER:
> + epp = AMD_CPPC_EPP_POWERSAVE;
> + break;
> + case PLATFORM_PROFILE_BALANCED:
> + epp = amd_pstate_get_balanced_epp(policy);
> + break;
> + default:
> + pr_err("Unknown Platform Profile %d\n", cpudata->current_profile);
> + return -EOPNOTSUPP;
> + }
> ret = amd_pstate_set_epp(policy, epp);
> if (ret)
> return ret;
>
> + cpudata->profile_name = kasprintf(GFP_KERNEL, "amd-pstate-epp-cpu%d", cpudata->cpu);
> +
> + cpudata->ppdev = platform_profile_register(get_cpu_device(policy->cpu),
> + cpudata->profile_name,
> + policy->driver_data,
> + &amd_pstate_profile_ops);
> + if (IS_ERR(cpudata->ppdev)) {
> + ret = PTR_ERR(cpudata->ppdev);
> + goto cleanup;
> + }
> +
> /* only enable notifier if things will actually change */
> if (cpudata->epp_default_ac != cpudata->epp_default_dc) {
> ret = power_supply_reg_notifier(&cpudata->power_nb);
> @@ -1207,8 +1308,8 @@ static ssize_t show_energy_performance_available_preferences(
> return offset;
> }
>
> -static ssize_t store_energy_performance_preference(
> - struct cpufreq_policy *policy, const char *buf, size_t count)
> +ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
> + const char *buf, size_t count)
> {
> struct amd_cpudata *cpudata = policy->driver_data;
> char str_preference[21];
> @@ -1224,16 +1325,22 @@ static ssize_t store_energy_performance_preference(
> if (ret != 1)
> return -EINVAL;
>
> - ret = match_string(energy_perf_strings, -1, str_preference);
> - if (ret < 0)
> - return -EINVAL;
> -
> - if (ret)
> - epp = epp_values[ret];
> - else
> - epp = amd_pstate_get_balanced_epp(policy);
> + /*
> + * if the value matches a number, use that, otherwise see if
> + * matches an index in the energy_perf_strings array
> + */
> + ret = kstrtou8(str_preference, 0, &epp);
> + if (ret) {
> + ret = match_string(energy_perf_strings, -1, str_preference);
> + if (ret < 0 || ret == EPP_INDEX_CUSTOM)
> + return -EINVAL;
> + if (ret)
> + epp = epp_values[ret];
> + else
> + epp = amd_pstate_get_balanced_epp(policy);
> + }
>
> - if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
> + if (epp > 0 && cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
> pr_debug("EPP cannot be set under performance policy\n");
> return -EBUSY;
> }
> @@ -1244,9 +1351,9 @@ static ssize_t store_energy_performance_preference(
>
> return ret ? ret : count;
> }
> +EXPORT_SYMBOL_GPL(store_energy_performance_preference);
>
> -static ssize_t show_energy_performance_preference(
> - struct cpufreq_policy *policy, char *buf)
> +ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf)
> {
> struct amd_cpudata *cpudata = policy->driver_data;
> u8 preference, epp;
> @@ -1267,11 +1374,12 @@ static ssize_t show_energy_performance_preference(
> preference = EPP_INDEX_POWERSAVE;
> break;
> default:
> - return -EINVAL;
> + return sysfs_emit(buf, "%u\n", epp);
> }
>
> return sysfs_emit(buf, "%s\n", energy_perf_strings[preference]);
> }
> +EXPORT_SYMBOL_GPL(show_energy_performance_preference);
>
> static void amd_pstate_driver_cleanup(void)
> {
> @@ -1595,10 +1703,12 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
> amd_pstate_acpi_pm_profile_undefined()) {
> policy->policy = CPUFREQ_POLICY_PERFORMANCE;
> cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata);
> + cpudata->current_profile = PLATFORM_PROFILE_PERFORMANCE;
> } else {
> policy->policy = CPUFREQ_POLICY_POWERSAVE;
> cpudata->epp_default_ac = AMD_CPPC_EPP_PERFORMANCE;
> cpudata->epp_default_dc = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
> + cpudata->current_profile = PLATFORM_PROFILE_BALANCED;
> }
>
> if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
> diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
> index 6882876f895de..b4c5374762110 100644
> --- a/drivers/cpufreq/amd-pstate.h
> +++ b/drivers/cpufreq/amd-pstate.h
> @@ -9,6 +9,7 @@
> #define _LINUX_AMD_PSTATE_H
>
> #include <linux/pm_qos.h>
> +#include <linux/platform_profile.h>
>
> /*********************************************************************
> * AMD P-state INTERFACE *
> @@ -108,6 +109,11 @@ struct amd_cpudata {
> u8 epp_default_dc;
> bool dynamic_epp;
> struct notifier_block power_nb;
> +
> + /* platform profile */
> + enum platform_profile_option current_profile;
> + struct device *ppdev;
> + char *profile_name;
> };
>
> /*
> @@ -123,5 +129,9 @@ enum amd_pstate_mode {
> };
> const char *amd_pstate_get_mode_string(enum amd_pstate_mode mode);
> int amd_pstate_update_status(const char *buf, size_t size);
> +ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
> + const char *buf, size_t count);
> +ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf);
> +void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy);
>
> #endif /* _LINUX_AMD_PSTATE_H */
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 3/5] cpufreq/amd-pstate: Add support for platform profile class
2025-03-07 16:22 ` Gautham R. Shenoy
@ 2025-03-07 16:55 ` Mario Limonciello
2025-03-08 4:30 ` Mario Limonciello
0 siblings, 1 reply; 20+ messages in thread
From: Mario Limonciello @ 2025-03-07 16:55 UTC (permalink / raw)
To: Gautham R. Shenoy
Cc: Perry Yuan, Dhananjay Ugwekar,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
On 3/7/2025 10:22, Gautham R. Shenoy wrote:
> On Tue, Mar 04, 2025 at 09:23:25AM -0600, Mario Limonciello wrote:
>> From: Mario Limonciello <mario.limonciello@amd.com>
>>
>> The platform profile core allows multiple drivers and devices to
>> register platform profile support.
>>
>> When the legacy platform profile interface is used all drivers will
>> adjust the platform profile as well.
>>
>> Add support for registering every CPU with the platform profile handler
>> when dynamic EPP is enabled.
>>
>> The end result will be that changing the platform profile will modify
>> EPP accordingly.
>>
>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>> ---
>> Documentation/admin-guide/pm/amd-pstate.rst | 4 +-
>> drivers/cpufreq/Kconfig.x86 | 1 +
>> drivers/cpufreq/amd-pstate.c | 142 +++++++++++++++++---
>> drivers/cpufreq/amd-pstate.h | 10 ++
>> 4 files changed, 140 insertions(+), 17 deletions(-)
>>
>> diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
>> index 8424e7119dd7e..36950fb6568c0 100644
>> --- a/Documentation/admin-guide/pm/amd-pstate.rst
>> +++ b/Documentation/admin-guide/pm/amd-pstate.rst
>> @@ -321,7 +321,9 @@ Whether this behavior is enabled by default with the kernel config option
>> at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``.
>>
>> When set to enabled, the driver will select a different energy performance
>> -profile when the machine is running on battery or AC power.
>> +profile when the machine is running on battery or AC power. The driver will
>> +also register with the platform profile handler to receive notifications of
>> +user desired power state and react to those.
>> When set to disabled, the driver will not change the energy performance profile
>> based on the power source and will not react to user desired power state.
>>
>> diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
>> index c5ef92634ddf4..905eab998b836 100644
>> --- a/drivers/cpufreq/Kconfig.x86
>> +++ b/drivers/cpufreq/Kconfig.x86
>> @@ -40,6 +40,7 @@ config X86_AMD_PSTATE
>> select ACPI_PROCESSOR
>> select ACPI_CPPC_LIB if X86_64
>> select CPU_FREQ_GOV_SCHEDUTIL if SMP
>> + select ACPI_PLATFORM_PROFILE
>> help
>> This driver adds a CPUFreq driver which utilizes a fine grain
>> processor performance frequency control range instead of legacy
>> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
>> index 9911808fe0bcf..28c02edf6e40b 100644
>> --- a/drivers/cpufreq/amd-pstate.c
>> +++ b/drivers/cpufreq/amd-pstate.c
>> @@ -105,6 +105,7 @@ static struct quirk_entry *quirks;
>> * 2 balance_performance
>> * 3 balance_power
>> * 4 power
>> + * 5 custom (for raw EPP values)
>> */
>> enum energy_perf_value_index {
>> EPP_INDEX_DEFAULT = 0,
>> @@ -112,6 +113,7 @@ enum energy_perf_value_index {
>> EPP_INDEX_BALANCE_PERFORMANCE,
>> EPP_INDEX_BALANCE_POWERSAVE,
>> EPP_INDEX_POWERSAVE,
>> + EPP_INDEX_CUSTOM,
>> };
>>
>> static const char * const energy_perf_strings[] = {
>> @@ -120,6 +122,7 @@ static const char * const energy_perf_strings[] = {
>> [EPP_INDEX_BALANCE_PERFORMANCE] = "balance_performance",
>> [EPP_INDEX_BALANCE_POWERSAVE] = "balance_power",
>> [EPP_INDEX_POWERSAVE] = "power",
>> + [EPP_INDEX_CUSTOM] = "custom",
>> NULL
>> };
>>
>> @@ -1073,6 +1076,10 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
>> if (event != PSY_EVENT_PROP_CHANGED)
>> return NOTIFY_OK;
>>
>> + /* dynamic actions are only applied while platform profile is in balanced */
>> + if (cpudata->current_profile != PLATFORM_PROFILE_BALANCED)
>> + return 0;
>> +
>> epp = amd_pstate_get_balanced_epp(policy);
>>
>> ret = amd_pstate_set_epp(policy, epp);
>> @@ -1081,14 +1088,84 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
>>
>> return NOTIFY_OK;
>> }
>> -static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
>> +
>> +static int amd_pstate_profile_probe(void *drvdata, unsigned long *choices)
>> +{
>> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
>> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
>> +
>> + return 0;
>> +}
>> +
>> +static int amd_pstate_profile_get(struct device *dev,
>> + enum platform_profile_option *profile)
>> +{
>> + struct amd_cpudata *cpudata = dev_get_drvdata(dev);
>> +
>> + *profile = cpudata->current_profile;
>> +
>> + return 0;
>> +}
>> +
>> +static int amd_pstate_profile_set(struct device *dev,
>> + enum platform_profile_option profile)
>> +{
>> + struct amd_cpudata *cpudata = dev_get_drvdata(dev);
>> + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
>> + int ret;
>> +
>> + switch (profile) {
>> + case PLATFORM_PROFILE_LOW_POWER:
>> + if (cpudata->policy != CPUFREQ_POLICY_POWERSAVE)
>> + cpudata->policy = CPUFREQ_POLICY_POWERSAVE;
>
> So prior to the patch, cpudata->policy is supposed to mirror
> policy->policy. With this patch, this assumption is no longer
> true. So it is possible for the user to again override the choice of
> EPP set via platform profile by changing the cpufreq governor ?
>
> Is this the expected behaviour?
>
> The bigger concern is, if the governor was previously "performance"
> and then the platform profile requested "low power", "cat
> /sys/devices/system/cpu/cpuX/cpufreq/scaling_governor" would still
> show "performance", which is inconsistent with the behaviour.
>
>
This ties back to the previous patches for dynamic EPP. My expectation
was that when dynamic EPP is enabled that users can't manually set the
EPP anymore (it will return -EBUSY) and likewise turning on dynamic EPP
should keep the governor as powersave.
I'll double check all those are properly enforced; but that's at least
the intent.
IMO this "should" all work because turning on Dynamic EPP sysfs file
forces the driver to go through a state transition that it will tear
everything down and back up. The policy will come back up in
"powersave" even if it was previously in "performance" when the dynamic
EPP sysfs file was turned on.
Longer term; I also envision the scheduler influencing EPP values when
dynamic_epp is turned on. The "platform profile" would be an "input" to
that decision making process (maybe giving a weighting?), not the only
lever.
I haven't given any serious look at how to do this with the scheduler, I
wanted to lay the foundation first being dynamic EPP and raw EPP.
So even if dynamic_epp isn't interesting "right now" for server because
the focus is around behavior for AC/DC, don't write it off just yet.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 3/5] cpufreq/amd-pstate: Add support for platform profile class
2025-03-07 16:55 ` Mario Limonciello
@ 2025-03-08 4:30 ` Mario Limonciello
2025-03-10 5:09 ` Gautham R. Shenoy
0 siblings, 1 reply; 20+ messages in thread
From: Mario Limonciello @ 2025-03-08 4:30 UTC (permalink / raw)
To: Mario Limonciello, Gautham R. Shenoy
Cc: Perry Yuan, Dhananjay Ugwekar,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK
On 3/7/2025 10:55, Mario Limonciello wrote:
> On 3/7/2025 10:22, Gautham R. Shenoy wrote:
>> On Tue, Mar 04, 2025 at 09:23:25AM -0600, Mario Limonciello wrote:
>>> From: Mario Limonciello <mario.limonciello@amd.com>
>>>
>>> The platform profile core allows multiple drivers and devices to
>>> register platform profile support.
>>>
>>> When the legacy platform profile interface is used all drivers will
>>> adjust the platform profile as well.
>>>
>>> Add support for registering every CPU with the platform profile handler
>>> when dynamic EPP is enabled.
>>>
>>> The end result will be that changing the platform profile will modify
>>> EPP accordingly.
>>>
>>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>>> ---
>>> Documentation/admin-guide/pm/amd-pstate.rst | 4 +-
>>> drivers/cpufreq/Kconfig.x86 | 1 +
>>> drivers/cpufreq/amd-pstate.c | 142 +++++++++++++++++---
>>> drivers/cpufreq/amd-pstate.h | 10 ++
>>> 4 files changed, 140 insertions(+), 17 deletions(-)
>>>
>>> diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/
>>> Documentation/admin-guide/pm/amd-pstate.rst
>>> index 8424e7119dd7e..36950fb6568c0 100644
>>> --- a/Documentation/admin-guide/pm/amd-pstate.rst
>>> +++ b/Documentation/admin-guide/pm/amd-pstate.rst
>>> @@ -321,7 +321,9 @@ Whether this behavior is enabled by default with
>>> the kernel config option
>>> at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/
>>> policyX/dynamic_epp``.
>>> When set to enabled, the driver will select a different energy
>>> performance
>>> -profile when the machine is running on battery or AC power.
>>> +profile when the machine is running on battery or AC power. The
>>> driver will
>>> +also register with the platform profile handler to receive
>>> notifications of
>>> +user desired power state and react to those.
>>> When set to disabled, the driver will not change the energy
>>> performance profile
>>> based on the power source and will not react to user desired power
>>> state.
>>> diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
>>> index c5ef92634ddf4..905eab998b836 100644
>>> --- a/drivers/cpufreq/Kconfig.x86
>>> +++ b/drivers/cpufreq/Kconfig.x86
>>> @@ -40,6 +40,7 @@ config X86_AMD_PSTATE
>>> select ACPI_PROCESSOR
>>> select ACPI_CPPC_LIB if X86_64
>>> select CPU_FREQ_GOV_SCHEDUTIL if SMP
>>> + select ACPI_PLATFORM_PROFILE
>>> help
>>> This driver adds a CPUFreq driver which utilizes a fine grain
>>> processor performance frequency control range instead of legacy
>>> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
>>> index 9911808fe0bcf..28c02edf6e40b 100644
>>> --- a/drivers/cpufreq/amd-pstate.c
>>> +++ b/drivers/cpufreq/amd-pstate.c
>>> @@ -105,6 +105,7 @@ static struct quirk_entry *quirks;
>>> * 2 balance_performance
>>> * 3 balance_power
>>> * 4 power
>>> + * 5 custom (for raw EPP values)
>>> */
>>> enum energy_perf_value_index {
>>> EPP_INDEX_DEFAULT = 0,
>>> @@ -112,6 +113,7 @@ enum energy_perf_value_index {
>>> EPP_INDEX_BALANCE_PERFORMANCE,
>>> EPP_INDEX_BALANCE_POWERSAVE,
>>> EPP_INDEX_POWERSAVE,
>>> + EPP_INDEX_CUSTOM,
>>> };
>>> static const char * const energy_perf_strings[] = {
>>> @@ -120,6 +122,7 @@ static const char * const energy_perf_strings[] = {
>>> [EPP_INDEX_BALANCE_PERFORMANCE] = "balance_performance",
>>> [EPP_INDEX_BALANCE_POWERSAVE] = "balance_power",
>>> [EPP_INDEX_POWERSAVE] = "power",
>>> + [EPP_INDEX_CUSTOM] = "custom",
>>> NULL
>>> };
>>> @@ -1073,6 +1076,10 @@ static int
>>> amd_pstate_power_supply_notifier(struct notifier_block *nb,
>>> if (event != PSY_EVENT_PROP_CHANGED)
>>> return NOTIFY_OK;
>>> + /* dynamic actions are only applied while platform profile is in
>>> balanced */
>>> + if (cpudata->current_profile != PLATFORM_PROFILE_BALANCED)
>>> + return 0;
>>> +
>>> epp = amd_pstate_get_balanced_epp(policy);
>>> ret = amd_pstate_set_epp(policy, epp);
>>> @@ -1081,14 +1088,84 @@ static int
>>> amd_pstate_power_supply_notifier(struct notifier_block *nb,
>>> return NOTIFY_OK;
>>> }
>>> -static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
>>> +
>>> +static int amd_pstate_profile_probe(void *drvdata, unsigned long
>>> *choices)
>>> +{
>>> + set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
>>> + set_bit(PLATFORM_PROFILE_BALANCED, choices);
>>> + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int amd_pstate_profile_get(struct device *dev,
>>> + enum platform_profile_option *profile)
>>> +{
>>> + struct amd_cpudata *cpudata = dev_get_drvdata(dev);
>>> +
>>> + *profile = cpudata->current_profile;
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int amd_pstate_profile_set(struct device *dev,
>>> + enum platform_profile_option profile)
>>> +{
>>> + struct amd_cpudata *cpudata = dev_get_drvdata(dev);
>>> + struct cpufreq_policy *policy __free(put_cpufreq_policy) =
>>> cpufreq_cpu_get(cpudata->cpu);
>>> + int ret;
>>> +
>>> + switch (profile) {
>>> + case PLATFORM_PROFILE_LOW_POWER:
>>> + if (cpudata->policy != CPUFREQ_POLICY_POWERSAVE)
>>> + cpudata->policy = CPUFREQ_POLICY_POWERSAVE;
>>
>> So prior to the patch, cpudata->policy is supposed to mirror
>> policy->policy. With this patch, this assumption is no longer
>> true. So it is possible for the user to again override the choice of
>> EPP set via platform profile by changing the cpufreq governor ?
>>
>> Is this the expected behaviour?
>>
>> The bigger concern is, if the governor was previously "performance"
>> and then the platform profile requested "low power", "cat
>> /sys/devices/system/cpu/cpuX/cpufreq/scaling_governor" would still
>> show "performance", which is inconsistent with the behaviour.
>>
>>
>
> This ties back to the previous patches for dynamic EPP. My expectation
> was that when dynamic EPP is enabled that users can't manually set the
> EPP anymore (it will return -EBUSY) and likewise turning on dynamic EPP
> should keep the governor as powersave.
>
> I'll double check all those are properly enforced; but that's at least
> the intent.
FWIW - I double checked and confirmed that this is working as intended.
* I couldn't change from powersave to performance when dynamic_epp was
enabled (-EBUSY)
* I couldn't change energy_performance_preference when dynamic_epp was
enabled (-EBUSY)
>
> IMO this "should" all work because turning on Dynamic EPP sysfs file
> forces the driver to go through a state transition that it will tear
> everything down and back up. The policy will come back up in
> "powersave" even if it was previously in "performance" when the dynamic
> EPP sysfs file was turned on.
>
> Longer term; I also envision the scheduler influencing EPP values when
> dynamic_epp is turned on. The "platform profile" would be an "input" to
> that decision making process (maybe giving a weighting?), not the only
> lever.
>
> I haven't given any serious look at how to do this with the scheduler, I
> wanted to lay the foundation first being dynamic EPP and raw EPP.
>
> So even if dynamic_epp isn't interesting "right now" for server because
> the focus is around behavior for AC/DC, don't write it off just yet.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 3/5] cpufreq/amd-pstate: Add support for platform profile class
2025-03-08 4:30 ` Mario Limonciello
@ 2025-03-10 5:09 ` Gautham R. Shenoy
2025-03-18 19:07 ` Mario Limonciello
0 siblings, 1 reply; 20+ messages in thread
From: Gautham R. Shenoy @ 2025-03-10 5:09 UTC (permalink / raw)
To: Mario Limonciello
Cc: Mario Limonciello, Perry Yuan, Dhananjay Ugwekar,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK
[...snip...]
On Fri, Mar 07, 2025 at 10:30:25PM -0600, Mario Limonciello wrote:
> On 3/7/2025 10:55, Mario Limonciello wrote:
> > On 3/7/2025 10:22, Gautham R. Shenoy wrote:
> > > > +static int amd_pstate_profile_set(struct device *dev,
> > > > + enum platform_profile_option profile)
> > > > +{
> > > > + struct amd_cpudata *cpudata = dev_get_drvdata(dev);
> > > > + struct cpufreq_policy *policy __free(put_cpufreq_policy) =
> > > > cpufreq_cpu_get(cpudata->cpu);
> > > > + int ret;
> > > > +
> > > > + switch (profile) {
> > > > + case PLATFORM_PROFILE_LOW_POWER:
> > > > + if (cpudata->policy != CPUFREQ_POLICY_POWERSAVE)
> > > > + cpudata->policy = CPUFREQ_POLICY_POWERSAVE;
> > >
> > > So prior to the patch, cpudata->policy is supposed to mirror
> > > policy->policy. With this patch, this assumption is no longer
> > > true. So it is possible for the user to again override the choice of
> > > EPP set via platform profile by changing the cpufreq governor ?
> > >
> > > Is this the expected behaviour?
> > >
> > > The bigger concern is, if the governor was previously "performance"
> > > and then the platform profile requested "low power", "cat
> > > /sys/devices/system/cpu/cpuX/cpufreq/scaling_governor" would still
> > > show "performance", which is inconsistent with the behaviour.
> > >
> > >
> >
> > This ties back to the previous patches for dynamic EPP. My expectation
> > was that when dynamic EPP is enabled that users can't manually set the
> > EPP anymore (it will return -EBUSY) and likewise turning on dynamic EPP
> > should keep the governor as powersave.
> >
> > I'll double check all those are properly enforced; but that's at least
> > the intent.
>
> FWIW - I double checked and confirmed that this is working as intended.
> * I couldn't change from powersave to performance when dynamic_epp was
> enabled (-EBUSY)
> * I couldn't change energy_performance_preference when dynamic_epp was
> enabled (-EBUSY)
Thanks for double checking this.
>
> >
> > IMO this "should" all work because turning on Dynamic EPP sysfs file
> > forces the driver to go through a state transition that it will tear
> > everything down and back up. The policy will come back up in
> > "powersave" even if it was previously in "performance" when the dynamic
> > EPP sysfs file was turned on.
> >
> > Longer term; I also envision the scheduler influencing EPP values when
> > dynamic_epp is turned on. The "platform profile" would be an "input" to
> > that decision making process (maybe giving a weighting?), not the only
> > lever.
Yes, the scheduler influencing the EPP values is something that I have
been wanting to explore as well. My idea was to use the nature of the
task + the load on the rq to determine the EPP value.
> >
> > I haven't given any serious look at how to do this with the scheduler, I
> > wanted to lay the foundation first being dynamic EPP and raw EPP.
> >
> > So even if dynamic_epp isn't interesting "right now" for server because
> > the focus is around behavior for AC/DC, don't write it off just yet.
>
Fair enough.
--
Thanks and Regards
gautham.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference
2025-03-04 15:23 ` [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference Mario Limonciello
2025-03-07 6:45 ` Gautham R. Shenoy
@ 2025-03-11 6:34 ` Dhananjay Ugwekar
2025-03-18 19:08 ` Mario Limonciello
2025-03-12 12:16 ` Dhananjay Ugwekar
2 siblings, 1 reply; 20+ messages in thread
From: Dhananjay Ugwekar @ 2025-03-11 6:34 UTC (permalink / raw)
To: Mario Limonciello, Gautham R . Shenoy, Perry Yuan
Cc: open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
On 3/4/2025 8:53 PM, Mario Limonciello wrote:
> From: Mario Limonciello <mario.limonciello@amd.com>
>
> Dynamic energy performance preference will change the EPP profile
> based on whether the machine is running on AC or DC power.
>
> A notification chain from the power supply core is used to adjust
> EPP values on plug in or plug out events.
>
> For non-server systems:
> * the default EPP for AC mode is `performance`.
> * the default EPP for DC mode is `balance_performance`.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
> v1->v2:
> * Change defaults to performance (AC) and balance_performance (DC)
> * Default Kconfig to disabled for now
> * Rebase on latest branch
> ---
> Documentation/admin-guide/pm/amd-pstate.rst | 18 ++-
> drivers/cpufreq/Kconfig.x86 | 12 ++
> drivers/cpufreq/amd-pstate.c | 129 ++++++++++++++++++--
> drivers/cpufreq/amd-pstate.h | 5 +-
> 4 files changed, 155 insertions(+), 9 deletions(-)
>
[Snip]
> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
> index e98ef41083ba1..f00fb4ba9f26e 100644
> --- a/drivers/cpufreq/amd-pstate.c
> +++ b/drivers/cpufreq/amd-pstate.c
> @@ -36,6 +36,7 @@
> #include <linux/io.h>
> #include <linux/delay.h>
> #include <linux/uaccess.h>
> +#include <linux/power_supply.h>
> #include <linux/static_call.h>
> #include <linux/topology.h>
>
> @@ -86,6 +87,7 @@ static struct cpufreq_driver amd_pstate_driver;
> static struct cpufreq_driver amd_pstate_epp_driver;
> static int cppc_state = AMD_PSTATE_UNDEFINED;
> static bool amd_pstate_prefcore = true;
> +static bool dynamic_epp = CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP;
Is there an #ifdef needed here? I see build error when X86_AMD_PSTATE_DYNAMIC_EPP is not set in config
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference
2025-03-04 15:23 ` [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference Mario Limonciello
2025-03-07 6:45 ` Gautham R. Shenoy
2025-03-11 6:34 ` Dhananjay Ugwekar
@ 2025-03-12 12:16 ` Dhananjay Ugwekar
2025-03-18 19:36 ` Mario Limonciello
2 siblings, 1 reply; 20+ messages in thread
From: Dhananjay Ugwekar @ 2025-03-12 12:16 UTC (permalink / raw)
To: Mario Limonciello, Gautham R . Shenoy, Perry Yuan
Cc: open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
On 3/4/2025 8:53 PM, Mario Limonciello wrote:
> From: Mario Limonciello <mario.limonciello@amd.com>
>
> Dynamic energy performance preference will change the EPP profile
> based on whether the machine is running on AC or DC power.
>
> A notification chain from the power supply core is used to adjust
> EPP values on plug in or plug out events.
>
> For non-server systems:
> * the default EPP for AC mode is `performance`.
> * the default EPP for DC mode is `balance_performance`.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
> ---
> v1->v2:
> * Change defaults to performance (AC) and balance_performance (DC)
> * Default Kconfig to disabled for now
> * Rebase on latest branch
> ---
> Documentation/admin-guide/pm/amd-pstate.rst | 18 ++-
> drivers/cpufreq/Kconfig.x86 | 12 ++
> drivers/cpufreq/amd-pstate.c | 129 ++++++++++++++++++--
> drivers/cpufreq/amd-pstate.h | 5 +-
> 4 files changed, 155 insertions(+), 9 deletions(-)
>
[Snip]
> @@ -1556,6 +1667,10 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
> if (!policy->cpuinfo.max_freq)
> return -ENODEV;
>
> + /* policy can't be changed to performance policy while dynamic epp is enabled */
> + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && cpudata->dynamic_epp)
> + return -EBUSY;
We might need to tweak this condition, because if we enable "CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP" in config
and boot with "amd_pstate=active" it lands here (cpufreq_online()->amd_pstate_epp_set_policy()) driver init fails
as the default governor is performance.
> +
> cpudata->policy = policy->policy;
>
> ret = amd_pstate_epp_update_limit(policy);
> diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
> index fbe1c08d3f061..6882876f895de 100644
> --- a/drivers/cpufreq/amd-pstate.h
> +++ b/drivers/cpufreq/amd-pstate.h
> @@ -104,7 +104,10 @@ struct amd_cpudata {
> /* EPP feature related attributes*/
> u32 policy;
> bool suspended;
> - u8 epp_default;
> + u8 epp_default_ac;
> + u8 epp_default_dc;
> + bool dynamic_epp;
> + struct notifier_block power_nb;
> };
>
> /*
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 3/5] cpufreq/amd-pstate: Add support for platform profile class
2025-03-10 5:09 ` Gautham R. Shenoy
@ 2025-03-18 19:07 ` Mario Limonciello
0 siblings, 0 replies; 20+ messages in thread
From: Mario Limonciello @ 2025-03-18 19:07 UTC (permalink / raw)
To: Gautham R. Shenoy
Cc: Mario Limonciello, Perry Yuan, Dhananjay Ugwekar,
open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK
On 3/10/2025 00:09, Gautham R. Shenoy wrote:
> [...snip...]
>
> On Fri, Mar 07, 2025 at 10:30:25PM -0600, Mario Limonciello wrote:
>> On 3/7/2025 10:55, Mario Limonciello wrote:
>>> On 3/7/2025 10:22, Gautham R. Shenoy wrote:
>>>>> +static int amd_pstate_profile_set(struct device *dev,
>>>>> + enum platform_profile_option profile)
>>>>> +{
>>>>> + struct amd_cpudata *cpudata = dev_get_drvdata(dev);
>>>>> + struct cpufreq_policy *policy __free(put_cpufreq_policy) =
>>>>> cpufreq_cpu_get(cpudata->cpu);
>>>>> + int ret;
>>>>> +
>>>>> + switch (profile) {
>>>>> + case PLATFORM_PROFILE_LOW_POWER:
>>>>> + if (cpudata->policy != CPUFREQ_POLICY_POWERSAVE)
>>>>> + cpudata->policy = CPUFREQ_POLICY_POWERSAVE;
>>>>
>>>> So prior to the patch, cpudata->policy is supposed to mirror
>>>> policy->policy. With this patch, this assumption is no longer
>>>> true. So it is possible for the user to again override the choice of
>>>> EPP set via platform profile by changing the cpufreq governor ?
>>>>
>>>> Is this the expected behaviour?
>>>>
>>>> The bigger concern is, if the governor was previously "performance"
>>>> and then the platform profile requested "low power", "cat
>>>> /sys/devices/system/cpu/cpuX/cpufreq/scaling_governor" would still
>>>> show "performance", which is inconsistent with the behaviour.
>>>>
>>>>
>>>
>>> This ties back to the previous patches for dynamic EPP. My expectation
>>> was that when dynamic EPP is enabled that users can't manually set the
>>> EPP anymore (it will return -EBUSY) and likewise turning on dynamic EPP
>>> should keep the governor as powersave.
>>>
>>> I'll double check all those are properly enforced; but that's at least
>>> the intent.
>>
>> FWIW - I double checked and confirmed that this is working as intended.
>> * I couldn't change from powersave to performance when dynamic_epp was
>> enabled (-EBUSY)
>> * I couldn't change energy_performance_preference when dynamic_epp was
>> enabled (-EBUSY)
>
> Thanks for double checking this.
The other option is to create a "3rd" cpufreq driver for amd-pstate when
dynamic epp is in use.
The upside is this one could then exclude
"energy_performance_preference" and
"energy_performance_available_preferences" so no need to report -EBUSY
for that case since you can't manually change EPP.
The downside is that you couldn't discover what the kernel was doing
with EPP without ftrace.
>
>
>>
>>>
>>> IMO this "should" all work because turning on Dynamic EPP sysfs file
>>> forces the driver to go through a state transition that it will tear
>>> everything down and back up. The policy will come back up in
>>> "powersave" even if it was previously in "performance" when the dynamic
>>> EPP sysfs file was turned on.
>>>
>>> Longer term; I also envision the scheduler influencing EPP values when
>>> dynamic_epp is turned on. The "platform profile" would be an "input" to
>>> that decision making process (maybe giving a weighting?), not the only
>>> lever.
>
> Yes, the scheduler influencing the EPP values is something that I have
> been wanting to explore as well. My idea was to use the nature of the
> task + the load on the rq to determine the EPP value.
>
>>>
>>> I haven't given any serious look at how to do this with the scheduler, I
>>> wanted to lay the foundation first being dynamic EPP and raw EPP.
>>>
>>> So even if dynamic_epp isn't interesting "right now" for server because
>>> the focus is around behavior for AC/DC, don't write it off just yet.
>>
>
> Fair enough.
>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference
2025-03-11 6:34 ` Dhananjay Ugwekar
@ 2025-03-18 19:08 ` Mario Limonciello
0 siblings, 0 replies; 20+ messages in thread
From: Mario Limonciello @ 2025-03-18 19:08 UTC (permalink / raw)
To: Dhananjay Ugwekar, Gautham R . Shenoy, Perry Yuan
Cc: open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
On 3/11/2025 01:34, Dhananjay Ugwekar wrote:
> On 3/4/2025 8:53 PM, Mario Limonciello wrote:
>> From: Mario Limonciello <mario.limonciello@amd.com>
>>
>> Dynamic energy performance preference will change the EPP profile
>> based on whether the machine is running on AC or DC power.
>>
>> A notification chain from the power supply core is used to adjust
>> EPP values on plug in or plug out events.
>>
>> For non-server systems:
>> * the default EPP for AC mode is `performance`.
>> * the default EPP for DC mode is `balance_performance`.
>>
>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>> ---
>> v1->v2:
>> * Change defaults to performance (AC) and balance_performance (DC)
>> * Default Kconfig to disabled for now
>> * Rebase on latest branch
>> ---
>> Documentation/admin-guide/pm/amd-pstate.rst | 18 ++-
>> drivers/cpufreq/Kconfig.x86 | 12 ++
>> drivers/cpufreq/amd-pstate.c | 129 ++++++++++++++++++--
>> drivers/cpufreq/amd-pstate.h | 5 +-
>> 4 files changed, 155 insertions(+), 9 deletions(-)
>>
> [Snip]
>> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
>> index e98ef41083ba1..f00fb4ba9f26e 100644
>> --- a/drivers/cpufreq/amd-pstate.c
>> +++ b/drivers/cpufreq/amd-pstate.c
>> @@ -36,6 +36,7 @@
>> #include <linux/io.h>
>> #include <linux/delay.h>
>> #include <linux/uaccess.h>
>> +#include <linux/power_supply.h>
>> #include <linux/static_call.h>
>> #include <linux/topology.h>
>>
>> @@ -86,6 +87,7 @@ static struct cpufreq_driver amd_pstate_driver;
>> static struct cpufreq_driver amd_pstate_epp_driver;
>> static int cppc_state = AMD_PSTATE_UNDEFINED;
>> static bool amd_pstate_prefcore = true;
>> +static bool dynamic_epp = CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP;
>
> Is there an #ifdef needed here? I see build error when X86_AMD_PSTATE_DYNAMIC_EPP is not set in config
>
Ah yeah, I see the same too when I check that config. Not sure why
build robot didn't catch this.
Will add this for next version.
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index dcf6e36d693f8..824756ac0010e 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -87,7 +87,11 @@ static struct cpufreq_driver amd_pstate_driver;
static struct cpufreq_driver amd_pstate_epp_driver;
static int cppc_state = AMD_PSTATE_UNDEFINED;
static bool amd_pstate_prefcore = true;
+#ifdef CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP
static bool dynamic_epp = CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP;
+#else
+static bool dynamic_epp = false;
+#endif
static struct quirk_entry *quirks;
/*
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference
2025-03-12 12:16 ` Dhananjay Ugwekar
@ 2025-03-18 19:36 ` Mario Limonciello
2025-03-19 3:43 ` Dhananjay Ugwekar
0 siblings, 1 reply; 20+ messages in thread
From: Mario Limonciello @ 2025-03-18 19:36 UTC (permalink / raw)
To: Dhananjay Ugwekar, Gautham R . Shenoy, Perry Yuan
Cc: open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
On 3/12/2025 07:16, Dhananjay Ugwekar wrote:
> On 3/4/2025 8:53 PM, Mario Limonciello wrote:
>> From: Mario Limonciello <mario.limonciello@amd.com>
>>
>> Dynamic energy performance preference will change the EPP profile
>> based on whether the machine is running on AC or DC power.
>>
>> A notification chain from the power supply core is used to adjust
>> EPP values on plug in or plug out events.
>>
>> For non-server systems:
>> * the default EPP for AC mode is `performance`.
>> * the default EPP for DC mode is `balance_performance`.
>>
>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>> ---
>> v1->v2:
>> * Change defaults to performance (AC) and balance_performance (DC)
>> * Default Kconfig to disabled for now
>> * Rebase on latest branch
>> ---
>> Documentation/admin-guide/pm/amd-pstate.rst | 18 ++-
>> drivers/cpufreq/Kconfig.x86 | 12 ++
>> drivers/cpufreq/amd-pstate.c | 129 ++++++++++++++++++--
>> drivers/cpufreq/amd-pstate.h | 5 +-
>> 4 files changed, 155 insertions(+), 9 deletions(-)
>>
> [Snip]
>> @@ -1556,6 +1667,10 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
>> if (!policy->cpuinfo.max_freq)
>> return -ENODEV;
>>
>> + /* policy can't be changed to performance policy while dynamic epp is enabled */
>> + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && cpudata->dynamic_epp)
>> + return -EBUSY;
>
> We might need to tweak this condition, because if we enable "CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP" in config
> and boot with "amd_pstate=active" it lands here (cpufreq_online()->amd_pstate_epp_set_policy()) driver init fails
> as the default governor is performance.
>
The check is important to make sure that you can't go to performance
mode after init.
I think this is the way I would want to solve it.
Set policy to powersave before enabling dynamic epp for
amd_pstate_epp_cpu_init().
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index 824756ac0010e..4a0f561d0e2d1 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -1729,8 +1729,10 @@ static int amd_pstate_epp_cpu_init(struct
cpufreq_policy *policy)
WRITE_ONCE(cpudata->cppc_req_cached, value);
}
- if (dynamic_epp)
+ if (dynamic_epp) {
+ policy->policy = CPUFREQ_POLICY_POWERSAVE;
ret = amd_pstate_set_dynamic_epp(policy);
+ }
else
ret = amd_pstate_set_epp(policy,
amd_pstate_get_balanced_epp(policy));
if (ret)
Thoughts?
>> +
>> cpudata->policy = policy->policy;
>>
>> ret = amd_pstate_epp_update_limit(policy);
>> diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
>> index fbe1c08d3f061..6882876f895de 100644
>> --- a/drivers/cpufreq/amd-pstate.h
>> +++ b/drivers/cpufreq/amd-pstate.h
>> @@ -104,7 +104,10 @@ struct amd_cpudata {
>> /* EPP feature related attributes*/
>> u32 policy;
>> bool suspended;
>> - u8 epp_default;
>> + u8 epp_default_ac;
>> + u8 epp_default_dc;
>> + bool dynamic_epp;
>> + struct notifier_block power_nb;
>> };
>>
>> /*
>
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference
2025-03-18 19:36 ` Mario Limonciello
@ 2025-03-19 3:43 ` Dhananjay Ugwekar
2025-03-19 16:50 ` Mario Limonciello
0 siblings, 1 reply; 20+ messages in thread
From: Dhananjay Ugwekar @ 2025-03-19 3:43 UTC (permalink / raw)
To: Mario Limonciello, Gautham R . Shenoy, Perry Yuan
Cc: open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
On 3/19/2025 1:06 AM, Mario Limonciello wrote:
> On 3/12/2025 07:16, Dhananjay Ugwekar wrote:
>> On 3/4/2025 8:53 PM, Mario Limonciello wrote:
>>> From: Mario Limonciello <mario.limonciello@amd.com>
>>>
>>> Dynamic energy performance preference will change the EPP profile
>>> based on whether the machine is running on AC or DC power.
>>>
>>> A notification chain from the power supply core is used to adjust
>>> EPP values on plug in or plug out events.
>>>
>>> For non-server systems:
>>> * the default EPP for AC mode is `performance`.
>>> * the default EPP for DC mode is `balance_performance`.
>>>
>>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>>> ---
>>> v1->v2:
>>> * Change defaults to performance (AC) and balance_performance (DC)
>>> * Default Kconfig to disabled for now
>>> * Rebase on latest branch
>>> ---
>>> Documentation/admin-guide/pm/amd-pstate.rst | 18 ++-
>>> drivers/cpufreq/Kconfig.x86 | 12 ++
>>> drivers/cpufreq/amd-pstate.c | 129 ++++++++++++++++++--
>>> drivers/cpufreq/amd-pstate.h | 5 +-
>>> 4 files changed, 155 insertions(+), 9 deletions(-)
>>>
>> [Snip]
>>> @@ -1556,6 +1667,10 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
>>> if (!policy->cpuinfo.max_freq)
>>> return -ENODEV;
>>> + /* policy can't be changed to performance policy while dynamic epp is enabled */
>>> + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && cpudata->dynamic_epp)
>>> + return -EBUSY;
>>
>> We might need to tweak this condition, because if we enable "CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP" in config
>> and boot with "amd_pstate=active" it lands here (cpufreq_online()->amd_pstate_epp_set_policy()) driver init fails
>> as the default governor is performance.
>>
>
> The check is important to make sure that you can't go to performance mode after init.
>
> I think this is the way I would want to solve it.
> Set policy to powersave before enabling dynamic epp for amd_pstate_epp_cpu_init().
>
> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
> index 824756ac0010e..4a0f561d0e2d1 100644
> --- a/drivers/cpufreq/amd-pstate.c
> +++ b/drivers/cpufreq/amd-pstate.c
> @@ -1729,8 +1729,10 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
> WRITE_ONCE(cpudata->cppc_req_cached, value);
> }
>
> - if (dynamic_epp)
> + if (dynamic_epp) {
> + policy->policy = CPUFREQ_POLICY_POWERSAVE;
> ret = amd_pstate_set_dynamic_epp(policy);
> + }
> else
> ret = amd_pstate_set_epp(policy, amd_pstate_get_balanced_epp(policy));
^^^^^^^^^^^^ (mentioned below)
> if (ret)
>
> Thoughts?
Yes, this looks good, because anyway there is no point in having performance governor and dynamic
epp set at the same time.
I found one related quirk though, we are setting performance governor for server platforms in
amd_pstate_epp_cpu_init() and then setting epp at the line highlighted above. We dont have a
check in *_set_epp() functions for performance governor. This could alter the performance governor
behavior if we set a "balanced" epp for it. I haven't tested this part yet.
Thanks,
Dhananjay
>
>>> +
>>> cpudata->policy = policy->policy;
>>> ret = amd_pstate_epp_update_limit(policy);
>>> diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
>>> index fbe1c08d3f061..6882876f895de 100644
>>> --- a/drivers/cpufreq/amd-pstate.h
>>> +++ b/drivers/cpufreq/amd-pstate.h
>>> @@ -104,7 +104,10 @@ struct amd_cpudata {
>>> /* EPP feature related attributes*/
>>> u32 policy;
>>> bool suspended;
>>> - u8 epp_default;
>>> + u8 epp_default_ac;
>>> + u8 epp_default_dc;
>>> + bool dynamic_epp;
>>> + struct notifier_block power_nb;
>>> };
>>> /*
>>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference
2025-03-19 3:43 ` Dhananjay Ugwekar
@ 2025-03-19 16:50 ` Mario Limonciello
2025-03-19 17:13 ` Mario Limonciello
0 siblings, 1 reply; 20+ messages in thread
From: Mario Limonciello @ 2025-03-19 16:50 UTC (permalink / raw)
To: Dhananjay Ugwekar, Gautham R . Shenoy, Perry Yuan
Cc: open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK, Mario Limonciello
On 3/18/2025 22:43, Dhananjay Ugwekar wrote:
> On 3/19/2025 1:06 AM, Mario Limonciello wrote:
>> On 3/12/2025 07:16, Dhananjay Ugwekar wrote:
>>> On 3/4/2025 8:53 PM, Mario Limonciello wrote:
>>>> From: Mario Limonciello <mario.limonciello@amd.com>
>>>>
>>>> Dynamic energy performance preference will change the EPP profile
>>>> based on whether the machine is running on AC or DC power.
>>>>
>>>> A notification chain from the power supply core is used to adjust
>>>> EPP values on plug in or plug out events.
>>>>
>>>> For non-server systems:
>>>> * the default EPP for AC mode is `performance`.
>>>> * the default EPP for DC mode is `balance_performance`.
>>>>
>>>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>>>> ---
>>>> v1->v2:
>>>> * Change defaults to performance (AC) and balance_performance (DC)
>>>> * Default Kconfig to disabled for now
>>>> * Rebase on latest branch
>>>> ---
>>>> Documentation/admin-guide/pm/amd-pstate.rst | 18 ++-
>>>> drivers/cpufreq/Kconfig.x86 | 12 ++
>>>> drivers/cpufreq/amd-pstate.c | 129 ++++++++++++++++++--
>>>> drivers/cpufreq/amd-pstate.h | 5 +-
>>>> 4 files changed, 155 insertions(+), 9 deletions(-)
>>>>
>>> [Snip]
>>>> @@ -1556,6 +1667,10 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
>>>> if (!policy->cpuinfo.max_freq)
>>>> return -ENODEV;
>>>> + /* policy can't be changed to performance policy while dynamic epp is enabled */
>>>> + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && cpudata->dynamic_epp)
>>>> + return -EBUSY;
>>>
>>> We might need to tweak this condition, because if we enable "CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP" in config
>>> and boot with "amd_pstate=active" it lands here (cpufreq_online()->amd_pstate_epp_set_policy()) driver init fails
>>> as the default governor is performance.
>>>
>>
>> The check is important to make sure that you can't go to performance mode after init.
>>
>> I think this is the way I would want to solve it.
>> Set policy to powersave before enabling dynamic epp for amd_pstate_epp_cpu_init().
>>
>> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
>> index 824756ac0010e..4a0f561d0e2d1 100644
>> --- a/drivers/cpufreq/amd-pstate.c
>> +++ b/drivers/cpufreq/amd-pstate.c
>> @@ -1729,8 +1729,10 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
>> WRITE_ONCE(cpudata->cppc_req_cached, value);
>> }
>>
>> - if (dynamic_epp)
>> + if (dynamic_epp) {
>> + policy->policy = CPUFREQ_POLICY_POWERSAVE;
>> ret = amd_pstate_set_dynamic_epp(policy);
>> + }
>> else
>> ret = amd_pstate_set_epp(policy, amd_pstate_get_balanced_epp(policy));
> ^^^^^^^^^^^^ (mentioned below)
>> if (ret)
>>
>> Thoughts?
>
> Yes, this looks good, because anyway there is no point in having performance governor and dynamic
> epp set at the same time.
>
> I found one related quirk though, we are setting performance governor for server platforms in
> amd_pstate_epp_cpu_init() and then setting epp at the line highlighted above. We dont have a
> check in *_set_epp() functions for performance governor. This could alter the performance governor
> behavior if we set a "balanced" epp for it. I haven't tested this part yet.
In that case we probably want the "default" ACPI platform profile to be
"performance" when on a server instead of balanced.
>
> Thanks,
> Dhananjay
>
>>
>>>> +
>>>> cpudata->policy = policy->policy;
>>>> ret = amd_pstate_epp_update_limit(policy);
>>>> diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-pstate.h
>>>> index fbe1c08d3f061..6882876f895de 100644
>>>> --- a/drivers/cpufreq/amd-pstate.h
>>>> +++ b/drivers/cpufreq/amd-pstate.h
>>>> @@ -104,7 +104,10 @@ struct amd_cpudata {
>>>> /* EPP feature related attributes*/
>>>> u32 policy;
>>>> bool suspended;
>>>> - u8 epp_default;
>>>> + u8 epp_default_ac;
>>>> + u8 epp_default_dc;
>>>> + bool dynamic_epp;
>>>> + struct notifier_block power_nb;
>>>> };
>>>> /*
>>>
>>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference
2025-03-19 16:50 ` Mario Limonciello
@ 2025-03-19 17:13 ` Mario Limonciello
0 siblings, 0 replies; 20+ messages in thread
From: Mario Limonciello @ 2025-03-19 17:13 UTC (permalink / raw)
To: Mario Limonciello, Dhananjay Ugwekar, Gautham R . Shenoy,
Perry Yuan
Cc: open list:X86 ARCHITECTURE (32-BIT AND 64-BIT),
open list:CPU FREQUENCY SCALING FRAMEWORK
On 3/19/2025 11:50, Mario Limonciello wrote:
> On 3/18/2025 22:43, Dhananjay Ugwekar wrote:
>> On 3/19/2025 1:06 AM, Mario Limonciello wrote:
>>> On 3/12/2025 07:16, Dhananjay Ugwekar wrote:
>>>> On 3/4/2025 8:53 PM, Mario Limonciello wrote:
>>>>> From: Mario Limonciello <mario.limonciello@amd.com>
>>>>>
>>>>> Dynamic energy performance preference will change the EPP profile
>>>>> based on whether the machine is running on AC or DC power.
>>>>>
>>>>> A notification chain from the power supply core is used to adjust
>>>>> EPP values on plug in or plug out events.
>>>>>
>>>>> For non-server systems:
>>>>> * the default EPP for AC mode is `performance`.
>>>>> * the default EPP for DC mode is `balance_performance`.
>>>>>
>>>>> Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
>>>>> ---
>>>>> v1->v2:
>>>>> * Change defaults to performance (AC) and balance_performance (DC)
>>>>> * Default Kconfig to disabled for now
>>>>> * Rebase on latest branch
>>>>> ---
>>>>> Documentation/admin-guide/pm/amd-pstate.rst | 18 ++-
>>>>> drivers/cpufreq/Kconfig.x86 | 12 ++
>>>>> drivers/cpufreq/amd-pstate.c | 129 ++++++++++++++
>>>>> ++++--
>>>>> drivers/cpufreq/amd-pstate.h | 5 +-
>>>>> 4 files changed, 155 insertions(+), 9 deletions(-)
>>>>>
>>>> [Snip]
>>>>> @@ -1556,6 +1667,10 @@ static int amd_pstate_epp_set_policy(struct
>>>>> cpufreq_policy *policy)
>>>>> if (!policy->cpuinfo.max_freq)
>>>>> return -ENODEV;
>>>>> + /* policy can't be changed to performance policy while
>>>>> dynamic epp is enabled */
>>>>> + if (policy->policy == CPUFREQ_POLICY_PERFORMANCE && cpudata-
>>>>> >dynamic_epp)
>>>>> + return -EBUSY;
>>>>
>>>> We might need to tweak this condition, because if we enable
>>>> "CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP" in config
>>>> and boot with "amd_pstate=active" it lands here (cpufreq_online()-
>>>> >amd_pstate_epp_set_policy()) driver init fails
>>>> as the default governor is performance.
>>>>
>>>
>>> The check is important to make sure that you can't go to performance
>>> mode after init.
>>>
>>> I think this is the way I would want to solve it.
>>> Set policy to powersave before enabling dynamic epp for
>>> amd_pstate_epp_cpu_init().
>>>
>>> diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
>>> index 824756ac0010e..4a0f561d0e2d1 100644
>>> --- a/drivers/cpufreq/amd-pstate.c
>>> +++ b/drivers/cpufreq/amd-pstate.c
>>> @@ -1729,8 +1729,10 @@ static int amd_pstate_epp_cpu_init(struct
>>> cpufreq_policy *policy)
>>> WRITE_ONCE(cpudata->cppc_req_cached, value);
>>> }
>>>
>>> - if (dynamic_epp)
>>> + if (dynamic_epp) {
>>> + policy->policy = CPUFREQ_POLICY_POWERSAVE;
>>> ret = amd_pstate_set_dynamic_epp(policy);
>>> + }
>>> else
>>> ret = amd_pstate_set_epp(policy,
>>> amd_pstate_get_balanced_epp(policy));
>> ^^^^^^^^^^^^ (mentioned below)
>>> if (ret)
>>>
>>> Thoughts?
>>
>> Yes, this looks good, because anyway there is no point in having
>> performance governor and dynamic
>> epp set at the same time.
>>
>> I found one related quirk though, we are setting performance governor
>> for server platforms in
>> amd_pstate_epp_cpu_init() and then setting epp at the line highlighted
>> above. We dont have a
>> check in *_set_epp() functions for performance governor. This could
>> alter the performance governor
>> behavior if we set a "balanced" epp for it. I haven't tested this part
>> yet.
>
> In that case we probably want the "default" ACPI platform profile to be
> "performance" when on a server instead of balanced.
Actually this is already done:
cpudata->current_profile = PLATFORM_PROFILE_PERFORMANCE;
I'll post an updated patch series for you to test.
>
>>
>> Thanks,
>> Dhananjay
>>
>>>
>>>>> +
>>>>> cpudata->policy = policy->policy;
>>>>> ret = amd_pstate_epp_update_limit(policy);
>>>>> diff --git a/drivers/cpufreq/amd-pstate.h b/drivers/cpufreq/amd-
>>>>> pstate.h
>>>>> index fbe1c08d3f061..6882876f895de 100644
>>>>> --- a/drivers/cpufreq/amd-pstate.h
>>>>> +++ b/drivers/cpufreq/amd-pstate.h
>>>>> @@ -104,7 +104,10 @@ struct amd_cpudata {
>>>>> /* EPP feature related attributes*/
>>>>> u32 policy;
>>>>> bool suspended;
>>>>> - u8 epp_default;
>>>>> + u8 epp_default_ac;
>>>>> + u8 epp_default_dc;
>>>>> + bool dynamic_epp;
>>>>> + struct notifier_block power_nb;
>>>>> };
>>>>> /*
>>>>
>>>
>>
>
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2025-03-19 17:14 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-04 15:23 [PATCH v2 0/5] amd-pstate Dynamic EPP and raw EPP Mario Limonciello
2025-03-04 15:23 ` [PATCH v2 1/5] cpufreq/amd-pstate: Add dynamic energy performance preference Mario Limonciello
2025-03-07 6:45 ` Gautham R. Shenoy
2025-03-11 6:34 ` Dhananjay Ugwekar
2025-03-18 19:08 ` Mario Limonciello
2025-03-12 12:16 ` Dhananjay Ugwekar
2025-03-18 19:36 ` Mario Limonciello
2025-03-19 3:43 ` Dhananjay Ugwekar
2025-03-19 16:50 ` Mario Limonciello
2025-03-19 17:13 ` Mario Limonciello
2025-03-04 15:23 ` [PATCH v2 2/5] cpufreq/amd-pstate: add kernel command line to override dynamic epp Mario Limonciello
2025-03-07 8:53 ` Gautham R. Shenoy
2025-03-04 15:23 ` [PATCH v2 3/5] cpufreq/amd-pstate: Add support for platform profile class Mario Limonciello
2025-03-07 16:22 ` Gautham R. Shenoy
2025-03-07 16:55 ` Mario Limonciello
2025-03-08 4:30 ` Mario Limonciello
2025-03-10 5:09 ` Gautham R. Shenoy
2025-03-18 19:07 ` Mario Limonciello
2025-03-04 15:23 ` [PATCH v2 4/5] cpufreq/amd-pstate: Add support for raw EPP writes Mario Limonciello
2025-03-04 15:23 ` [PATCH v2 5/5] cpufreq/amd-pstate-ut: Add a unit test for raw EPP Mario Limonciello
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).