Skip to content

Commit 798c475

Browse files
committed
cpufreq/amd-pstate: Add support for platform profile class
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. Reviewed-by: Gautham R. Shenoy <gautham.shenoy@amd.com> Signed-off-by: Mario Limonciello (AMD) <superm1@kernel.org>
1 parent da8afb1 commit 798c475

4 files changed

Lines changed: 110 additions & 7 deletions

File tree

Documentation/admin-guide/pm/amd-pstate.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,9 @@ config option `CONFIG_X86_AMD_PSTATE_DYNAMIC_EPP`. This behavior can also be ove
357357
at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``.
358358

359359
When set to enabled, the driver will select a different energy performance
360-
profile when the machine is running on battery or AC power.
360+
profile when the machine is running on battery or AC power. The driver will
361+
also register with the platform profile handler to receive notifications of
362+
user desired power state and react to those.
361363
When set to disabled, the driver will not change the energy performance profile
362364
based on the power source and will not react to user desired power state.
363365

drivers/cpufreq/Kconfig.x86

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ config X86_AMD_PSTATE
4040
select ACPI_PROCESSOR
4141
select ACPI_CPPC_LIB if X86_64
4242
select CPU_FREQ_GOV_SCHEDUTIL if SMP
43+
select ACPI_PLATFORM_PROFILE
4344
help
4445
This driver adds a CPUFreq driver which utilizes a fine grain
4546
processor performance frequency control range instead of legacy

drivers/cpufreq/amd-pstate.c

Lines changed: 100 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,10 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
11821182
if (event != PSY_EVENT_PROP_CHANGED)
11831183
return NOTIFY_OK;
11841184

1185+
/* dynamic actions are only applied while platform profile is in balanced */
1186+
if (cpudata->current_profile != PLATFORM_PROFILE_BALANCED)
1187+
return 0;
1188+
11851189
epp = amd_pstate_get_balanced_epp(policy);
11861190

11871191
ret = amd_pstate_set_epp(policy, epp);
@@ -1190,12 +1194,77 @@ static int amd_pstate_power_supply_notifier(struct notifier_block *nb,
11901194

11911195
return NOTIFY_OK;
11921196
}
1197+
1198+
static int amd_pstate_profile_probe(void *drvdata, unsigned long *choices)
1199+
{
1200+
set_bit(PLATFORM_PROFILE_LOW_POWER, choices);
1201+
set_bit(PLATFORM_PROFILE_BALANCED, choices);
1202+
set_bit(PLATFORM_PROFILE_PERFORMANCE, choices);
1203+
1204+
return 0;
1205+
}
1206+
1207+
static int amd_pstate_profile_get(struct device *dev,
1208+
enum platform_profile_option *profile)
1209+
{
1210+
struct amd_cpudata *cpudata = dev_get_drvdata(dev);
1211+
1212+
*profile = cpudata->current_profile;
1213+
1214+
return 0;
1215+
}
1216+
1217+
static int amd_pstate_profile_set(struct device *dev,
1218+
enum platform_profile_option profile)
1219+
{
1220+
struct amd_cpudata *cpudata = dev_get_drvdata(dev);
1221+
struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu);
1222+
int ret;
1223+
1224+
switch (profile) {
1225+
case PLATFORM_PROFILE_LOW_POWER:
1226+
ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_POWERSAVE);
1227+
if (ret)
1228+
return ret;
1229+
break;
1230+
case PLATFORM_PROFILE_BALANCED:
1231+
ret = amd_pstate_set_epp(policy,
1232+
amd_pstate_get_balanced_epp(policy));
1233+
if (ret)
1234+
return ret;
1235+
break;
1236+
case PLATFORM_PROFILE_PERFORMANCE:
1237+
ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_PERFORMANCE);
1238+
if (ret)
1239+
return ret;
1240+
break;
1241+
default:
1242+
pr_err("Unknown Platform Profile %d\n", profile);
1243+
return -EOPNOTSUPP;
1244+
}
1245+
1246+
cpudata->current_profile = profile;
1247+
1248+
return 0;
1249+
}
1250+
1251+
static const struct platform_profile_ops amd_pstate_profile_ops = {
1252+
.probe = amd_pstate_profile_probe,
1253+
.profile_set = amd_pstate_profile_set,
1254+
.profile_get = amd_pstate_profile_get,
1255+
};
1256+
11931257
static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy)
11941258
{
11951259
struct amd_cpudata *cpudata = policy->driver_data;
11961260

11971261
if (cpudata->power_nb.notifier_call)
11981262
power_supply_unreg_notifier(&cpudata->power_nb);
1263+
if (cpudata->ppdev) {
1264+
platform_profile_remove(cpudata->ppdev);
1265+
cpudata->ppdev = NULL;
1266+
}
1267+
kfree(cpudata->profile_name);
11991268
cpudata->dynamic_epp = false;
12001269
}
12011270

@@ -1205,11 +1274,35 @@ static int amd_pstate_set_dynamic_epp(struct cpufreq_policy *policy)
12051274
int ret;
12061275
u8 epp;
12071276

1208-
epp = amd_pstate_get_balanced_epp(policy);
1277+
switch (cpudata->current_profile) {
1278+
case PLATFORM_PROFILE_PERFORMANCE:
1279+
epp = AMD_CPPC_EPP_PERFORMANCE;
1280+
break;
1281+
case PLATFORM_PROFILE_LOW_POWER:
1282+
epp = AMD_CPPC_EPP_POWERSAVE;
1283+
break;
1284+
case PLATFORM_PROFILE_BALANCED:
1285+
epp = amd_pstate_get_balanced_epp(policy);
1286+
break;
1287+
default:
1288+
pr_err("Unknown Platform Profile %d\n", cpudata->current_profile);
1289+
return -EOPNOTSUPP;
1290+
}
12091291
ret = amd_pstate_set_epp(policy, epp);
12101292
if (ret)
12111293
return ret;
12121294

1295+
cpudata->profile_name = kasprintf(GFP_KERNEL, "amd-pstate-epp-cpu%d", cpudata->cpu);
1296+
1297+
cpudata->ppdev = platform_profile_register(get_cpu_device(policy->cpu),
1298+
cpudata->profile_name,
1299+
policy->driver_data,
1300+
&amd_pstate_profile_ops);
1301+
if (IS_ERR(cpudata->ppdev)) {
1302+
ret = PTR_ERR(cpudata->ppdev);
1303+
goto cleanup;
1304+
}
1305+
12131306
/* only enable notifier if things will actually change */
12141307
if (cpudata->epp_default_ac != cpudata->epp_default_dc) {
12151308
cpudata->power_nb.notifier_call = amd_pstate_power_supply_notifier;
@@ -1310,8 +1403,8 @@ static ssize_t show_energy_performance_available_preferences(
13101403
return offset;
13111404
}
13121405

1313-
static ssize_t store_energy_performance_preference(
1314-
struct cpufreq_policy *policy, const char *buf, size_t count)
1406+
static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy,
1407+
const char *buf, size_t count)
13151408
{
13161409
struct amd_cpudata *cpudata = policy->driver_data;
13171410
ssize_t ret;
@@ -1331,7 +1424,7 @@ static ssize_t store_energy_performance_preference(
13311424
else
13321425
epp = amd_pstate_get_balanced_epp(policy);
13331426

1334-
if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
1427+
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
13351428
pr_debug("EPP cannot be set under performance policy\n");
13361429
return -EBUSY;
13371430
}
@@ -1343,8 +1436,7 @@ static ssize_t store_energy_performance_preference(
13431436
return ret ? ret : count;
13441437
}
13451438

1346-
static ssize_t show_energy_performance_preference(
1347-
struct cpufreq_policy *policy, char *buf)
1439+
static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf)
13481440
{
13491441
struct amd_cpudata *cpudata = policy->driver_data;
13501442
u8 preference, epp;
@@ -1826,10 +1918,12 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
18261918
amd_pstate_acpi_pm_profile_undefined()) {
18271919
policy->policy = CPUFREQ_POLICY_PERFORMANCE;
18281920
cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata);
1921+
cpudata->current_profile = PLATFORM_PROFILE_PERFORMANCE;
18291922
} else {
18301923
policy->policy = CPUFREQ_POLICY_POWERSAVE;
18311924
cpudata->epp_default_ac = AMD_CPPC_EPP_PERFORMANCE;
18321925
cpudata->epp_default_dc = AMD_CPPC_EPP_BALANCE_PERFORMANCE;
1926+
cpudata->current_profile = PLATFORM_PROFILE_BALANCED;
18331927
}
18341928

18351929
if (dynamic_epp)

drivers/cpufreq/amd-pstate.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#define _LINUX_AMD_PSTATE_H
1010

1111
#include <linux/pm_qos.h>
12+
#include <linux/platform_profile.h>
1213

1314
/*********************************************************************
1415
* AMD P-state INTERFACE *
@@ -127,6 +128,11 @@ struct amd_cpudata {
127128
u8 epp_default_dc;
128129
bool dynamic_epp;
129130
struct notifier_block power_nb;
131+
132+
/* platform profile */
133+
enum platform_profile_option current_profile;
134+
struct device *ppdev;
135+
char *profile_name;
130136
};
131137

132138
/*

0 commit comments

Comments
 (0)