Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+110 -7
+3 -1
Documentation/admin-guide/pm/amd-pstate.rst
··· 357 357 at runtime by the sysfs file ``/sys/devices/system/cpu/cpufreq/policyX/dynamic_epp``. 358 358 359 359 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. 361 363 When set to disabled, the driver will not change the energy performance profile 362 364 based on the power source and will not react to user desired power state. 363 365
+1
drivers/cpufreq/Kconfig.x86
··· 40 40 select ACPI_PROCESSOR 41 41 select ACPI_CPPC_LIB if X86_64 42 42 select CPU_FREQ_GOV_SCHEDUTIL if SMP 43 + select ACPI_PLATFORM_PROFILE 43 44 help 44 45 This driver adds a CPUFreq driver which utilizes a fine grain 45 46 processor performance frequency control range instead of legacy
+100 -6
drivers/cpufreq/amd-pstate.c
··· 1182 1182 if (event != PSY_EVENT_PROP_CHANGED) 1183 1183 return NOTIFY_OK; 1184 1184 1185 + /* dynamic actions are only applied while platform profile is in balanced */ 1186 + if (cpudata->current_profile != PLATFORM_PROFILE_BALANCED) 1187 + return 0; 1188 + 1185 1189 epp = amd_pstate_get_balanced_epp(policy); 1186 1190 1187 1191 ret = amd_pstate_set_epp(policy, epp); ··· 1194 1190 1195 1191 return NOTIFY_OK; 1196 1192 } 1193 + 1194 + static int amd_pstate_profile_probe(void *drvdata, unsigned long *choices) 1195 + { 1196 + set_bit(PLATFORM_PROFILE_LOW_POWER, choices); 1197 + set_bit(PLATFORM_PROFILE_BALANCED, choices); 1198 + set_bit(PLATFORM_PROFILE_PERFORMANCE, choices); 1199 + 1200 + return 0; 1201 + } 1202 + 1203 + static int amd_pstate_profile_get(struct device *dev, 1204 + enum platform_profile_option *profile) 1205 + { 1206 + struct amd_cpudata *cpudata = dev_get_drvdata(dev); 1207 + 1208 + *profile = cpudata->current_profile; 1209 + 1210 + return 0; 1211 + } 1212 + 1213 + static int amd_pstate_profile_set(struct device *dev, 1214 + enum platform_profile_option profile) 1215 + { 1216 + struct amd_cpudata *cpudata = dev_get_drvdata(dev); 1217 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu); 1218 + int ret; 1219 + 1220 + switch (profile) { 1221 + case PLATFORM_PROFILE_LOW_POWER: 1222 + ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_POWERSAVE); 1223 + if (ret) 1224 + return ret; 1225 + break; 1226 + case PLATFORM_PROFILE_BALANCED: 1227 + ret = amd_pstate_set_epp(policy, 1228 + amd_pstate_get_balanced_epp(policy)); 1229 + if (ret) 1230 + return ret; 1231 + break; 1232 + case PLATFORM_PROFILE_PERFORMANCE: 1233 + ret = amd_pstate_set_epp(policy, AMD_CPPC_EPP_PERFORMANCE); 1234 + if (ret) 1235 + return ret; 1236 + break; 1237 + default: 1238 + pr_err("Unknown Platform Profile %d\n", profile); 1239 + return -EOPNOTSUPP; 1240 + } 1241 + 1242 + cpudata->current_profile = profile; 1243 + 1244 + return 0; 1245 + } 1246 + 1247 + static const struct platform_profile_ops amd_pstate_profile_ops = { 1248 + .probe = amd_pstate_profile_probe, 1249 + .profile_set = amd_pstate_profile_set, 1250 + .profile_get = amd_pstate_profile_get, 1251 + }; 1252 + 1197 1253 static void amd_pstate_clear_dynamic_epp(struct cpufreq_policy *policy) 1198 1254 { 1199 1255 struct amd_cpudata *cpudata = policy->driver_data; 1200 1256 1201 1257 if (cpudata->power_nb.notifier_call) 1202 1258 power_supply_unreg_notifier(&cpudata->power_nb); 1259 + if (cpudata->ppdev) { 1260 + platform_profile_remove(cpudata->ppdev); 1261 + cpudata->ppdev = NULL; 1262 + } 1263 + kfree(cpudata->profile_name); 1203 1264 cpudata->dynamic_epp = false; 1204 1265 } 1205 1266 ··· 1274 1205 int ret; 1275 1206 u8 epp; 1276 1207 1277 - epp = amd_pstate_get_balanced_epp(policy); 1208 + switch (cpudata->current_profile) { 1209 + case PLATFORM_PROFILE_PERFORMANCE: 1210 + epp = AMD_CPPC_EPP_PERFORMANCE; 1211 + break; 1212 + case PLATFORM_PROFILE_LOW_POWER: 1213 + epp = AMD_CPPC_EPP_POWERSAVE; 1214 + break; 1215 + case PLATFORM_PROFILE_BALANCED: 1216 + epp = amd_pstate_get_balanced_epp(policy); 1217 + break; 1218 + default: 1219 + pr_err("Unknown Platform Profile %d\n", cpudata->current_profile); 1220 + return -EOPNOTSUPP; 1221 + } 1278 1222 ret = amd_pstate_set_epp(policy, epp); 1279 1223 if (ret) 1280 1224 return ret; 1225 + 1226 + cpudata->profile_name = kasprintf(GFP_KERNEL, "amd-pstate-epp-cpu%d", cpudata->cpu); 1227 + 1228 + cpudata->ppdev = platform_profile_register(get_cpu_device(policy->cpu), 1229 + cpudata->profile_name, 1230 + policy->driver_data, 1231 + &amd_pstate_profile_ops); 1232 + if (IS_ERR(cpudata->ppdev)) { 1233 + ret = PTR_ERR(cpudata->ppdev); 1234 + goto cleanup; 1235 + } 1281 1236 1282 1237 /* only enable notifier if things will actually change */ 1283 1238 if (cpudata->epp_default_ac != cpudata->epp_default_dc) { ··· 1403 1310 return offset; 1404 1311 } 1405 1312 1406 - static ssize_t store_energy_performance_preference( 1407 - struct cpufreq_policy *policy, const char *buf, size_t count) 1313 + static ssize_t store_energy_performance_preference(struct cpufreq_policy *policy, 1314 + const char *buf, size_t count) 1408 1315 { 1409 1316 struct amd_cpudata *cpudata = policy->driver_data; 1410 1317 ssize_t ret; ··· 1424 1331 else 1425 1332 epp = amd_pstate_get_balanced_epp(policy); 1426 1333 1427 - if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) { 1334 + if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) { 1428 1335 pr_debug("EPP cannot be set under performance policy\n"); 1429 1336 return -EBUSY; 1430 1337 } ··· 1436 1343 return ret ? ret : count; 1437 1344 } 1438 1345 1439 - static ssize_t show_energy_performance_preference( 1440 - struct cpufreq_policy *policy, char *buf) 1346 + static ssize_t show_energy_performance_preference(struct cpufreq_policy *policy, char *buf) 1441 1347 { 1442 1348 struct amd_cpudata *cpudata = policy->driver_data; 1443 1349 u8 preference, epp; ··· 1918 1826 amd_pstate_acpi_pm_profile_undefined()) { 1919 1827 policy->policy = CPUFREQ_POLICY_PERFORMANCE; 1920 1828 cpudata->epp_default_ac = cpudata->epp_default_dc = amd_pstate_get_epp(cpudata); 1829 + cpudata->current_profile = PLATFORM_PROFILE_PERFORMANCE; 1921 1830 } else { 1922 1831 policy->policy = CPUFREQ_POLICY_POWERSAVE; 1923 1832 cpudata->epp_default_ac = AMD_CPPC_EPP_PERFORMANCE; 1924 1833 cpudata->epp_default_dc = AMD_CPPC_EPP_BALANCE_PERFORMANCE; 1834 + cpudata->current_profile = PLATFORM_PROFILE_BALANCED; 1925 1835 } 1926 1836 1927 1837 if (dynamic_epp)
+6
drivers/cpufreq/amd-pstate.h
··· 9 9 #define _LINUX_AMD_PSTATE_H 10 10 11 11 #include <linux/pm_qos.h> 12 + #include <linux/platform_profile.h> 12 13 13 14 /********************************************************************* 14 15 * AMD P-state INTERFACE * ··· 128 127 u8 epp_default_dc; 129 128 bool dynamic_epp; 130 129 struct notifier_block power_nb; 130 + 131 + /* platform profile */ 132 + enum platform_profile_option current_profile; 133 + struct device *ppdev; 134 + char *profile_name; 131 135 }; 132 136 133 137 /*