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

cpufreq: amd-pstate: Add guided autonomous mode

From ACPI spec below 3 modes for CPPC can be defined:

1. Non autonomous: OS scaling governor specifies operating frequency/
performance level through `Desired Performance` register and platform
follows that.

2. Guided autonomous: OS scaling governor specifies min and max
frequencies/ performance levels through `Minimum Performance` and
`Maximum Performance` register, and platform can autonomously select an
operating frequency in this range.

3. Fully autonomous: OS only hints (via EPP) to platform for the required
energy performance preference for the workload and platform autonomously
scales the frequency.

Currently (1) is supported by amd_pstate as passive mode, and (3) is
implemented by EPP support. This change is to support (2).

In guided autonomous mode the min_perf is based on the input from the
scaling governor. For example, in case of schedutil this value depends
on the current utilization. And max_perf is set to max capacity.

To activate guided auto mode ``amd_pstate=guided`` command line
parameter has to be passed in the kernel.

Acked-by: Huang Rui <ray.huang@amd.com>
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
Signed-off-by: Wyes Karny <wyes.karny@amd.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Wyes Karny and committed by
Rafael J. Wysocki
2dd6d0eb 3e6e0780

+40 -11
+10 -5
Documentation/admin-guide/kernel-parameters.txt
··· 344 344 Do not enable amd_pstate as the default 345 345 scaling driver for the supported processors 346 346 passive 347 - Use amd_pstate as a scaling driver, driver requests a 348 - desired performance on this abstract scale and the power 349 - management firmware translates the requests into actual 350 - hardware states (core frequency, data fabric and memory 351 - clocks etc.) 347 + Use amd_pstate with passive mode as a scaling driver. 348 + In this mode autonomous selection is disabled. 349 + Driver requests a desired performance level and platform 350 + tries to match the same performance level if it is 351 + satisfied by guaranteed performance level. 352 352 active 353 353 Use amd_pstate_epp driver instance as the scaling driver, 354 354 driver provides a hint to the hardware if software wants ··· 356 356 to the CPPC firmware. then CPPC power algorithm will 357 357 calculate the runtime workload and adjust the realtime cores 358 358 frequency. 359 + guided 360 + Activate guided autonomous mode. Driver requests minimum and 361 + maximum performance level and the platform autonomously 362 + selects a performance level in this range and appropriate 363 + to the current workload. 359 364 360 365 amijoy.map= [HW,JOY] Amiga joystick support 361 366 Map of devices attached to JOY0DAT and JOY1DAT
+28 -6
drivers/cpufreq/amd-pstate.c
··· 308 308 cppc_perf.lowest_nonlinear_perf); 309 309 WRITE_ONCE(cpudata->lowest_perf, cppc_perf.lowest_perf); 310 310 311 - return 0; 311 + if (cppc_state == AMD_PSTATE_ACTIVE) 312 + return 0; 313 + 314 + ret = cppc_get_auto_sel_caps(cpudata->cpu, &cppc_perf); 315 + if (ret) { 316 + pr_warn("failed to get auto_sel, ret: %d\n", ret); 317 + return 0; 318 + } 319 + 320 + ret = cppc_set_auto_sel(cpudata->cpu, 321 + (cppc_state == AMD_PSTATE_PASSIVE) ? 0 : 1); 322 + 323 + if (ret) 324 + pr_warn("failed to set auto_sel, ret: %d\n", ret); 325 + 326 + return ret; 312 327 } 313 328 314 329 DEFINE_STATIC_CALL(amd_pstate_init_perf, pstate_init_perf); ··· 400 385 } 401 386 402 387 static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf, 403 - u32 des_perf, u32 max_perf, bool fast_switch) 388 + u32 des_perf, u32 max_perf, bool fast_switch, int gov_flags) 404 389 { 405 390 u64 prev = READ_ONCE(cpudata->cppc_req_cached); 406 391 u64 value = prev; 407 392 408 393 des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf); 394 + 395 + if ((cppc_state == AMD_PSTATE_GUIDED) && (gov_flags & CPUFREQ_GOV_DYNAMIC_SWITCHING)) { 396 + min_perf = des_perf; 397 + des_perf = 0; 398 + } 399 + 409 400 value &= ~AMD_CPPC_MIN_PERF(~0L); 410 401 value |= AMD_CPPC_MIN_PERF(min_perf); 411 402 ··· 466 445 467 446 cpufreq_freq_transition_begin(policy, &freqs); 468 447 amd_pstate_update(cpudata, min_perf, des_perf, 469 - max_perf, false); 448 + max_perf, false, policy->governor->flags); 470 449 cpufreq_freq_transition_end(policy, &freqs, false); 471 450 472 451 return 0; ··· 500 479 if (max_perf < min_perf) 501 480 max_perf = min_perf; 502 481 503 - amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true); 482 + amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true, 483 + policy->governor->flags); 504 484 cpufreq_cpu_put(policy); 505 485 } 506 486 ··· 1301 1279 /* capability check */ 1302 1280 if (boot_cpu_has(X86_FEATURE_CPPC)) { 1303 1281 pr_debug("AMD CPPC MSR based functionality is supported\n"); 1304 - if (cppc_state == AMD_PSTATE_PASSIVE) 1282 + if (cppc_state != AMD_PSTATE_ACTIVE) 1305 1283 current_pstate_driver->adjust_perf = amd_pstate_adjust_perf; 1306 1284 } else { 1307 1285 pr_debug("AMD CPPC shared memory based functionality is supported\n"); ··· 1363 1341 if (cppc_state == AMD_PSTATE_ACTIVE) 1364 1342 current_pstate_driver = &amd_pstate_epp_driver; 1365 1343 1366 - if (cppc_state == AMD_PSTATE_PASSIVE) 1344 + if (cppc_state == AMD_PSTATE_PASSIVE || cppc_state == AMD_PSTATE_GUIDED) 1367 1345 current_pstate_driver = &amd_pstate_driver; 1368 1346 1369 1347 return 0;
+2
include/linux/amd-pstate.h
··· 97 97 AMD_PSTATE_DISABLE = 0, 98 98 AMD_PSTATE_PASSIVE, 99 99 AMD_PSTATE_ACTIVE, 100 + AMD_PSTATE_GUIDED, 100 101 AMD_PSTATE_MAX, 101 102 }; 102 103 ··· 105 104 [AMD_PSTATE_DISABLE] = "disable", 106 105 [AMD_PSTATE_PASSIVE] = "passive", 107 106 [AMD_PSTATE_ACTIVE] = "active", 107 + [AMD_PSTATE_GUIDED] = "guided", 108 108 NULL, 109 109 }; 110 110 #endif /* _LINUX_AMD_PSTATE_H */