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>
This commit is contained in:
parent
3e6e078057
commit
2dd6d0ebf7
|
@ -344,11 +344,11 @@
|
||||||
Do not enable amd_pstate as the default
|
Do not enable amd_pstate as the default
|
||||||
scaling driver for the supported processors
|
scaling driver for the supported processors
|
||||||
passive
|
passive
|
||||||
Use amd_pstate as a scaling driver, driver requests a
|
Use amd_pstate with passive mode as a scaling driver.
|
||||||
desired performance on this abstract scale and the power
|
In this mode autonomous selection is disabled.
|
||||||
management firmware translates the requests into actual
|
Driver requests a desired performance level and platform
|
||||||
hardware states (core frequency, data fabric and memory
|
tries to match the same performance level if it is
|
||||||
clocks etc.)
|
satisfied by guaranteed performance level.
|
||||||
active
|
active
|
||||||
Use amd_pstate_epp driver instance as the scaling driver,
|
Use amd_pstate_epp driver instance as the scaling driver,
|
||||||
driver provides a hint to the hardware if software wants
|
driver provides a hint to the hardware if software wants
|
||||||
|
@ -356,6 +356,11 @@
|
||||||
to the CPPC firmware. then CPPC power algorithm will
|
to the CPPC firmware. then CPPC power algorithm will
|
||||||
calculate the runtime workload and adjust the realtime cores
|
calculate the runtime workload and adjust the realtime cores
|
||||||
frequency.
|
frequency.
|
||||||
|
guided
|
||||||
|
Activate guided autonomous mode. Driver requests minimum and
|
||||||
|
maximum performance level and the platform autonomously
|
||||||
|
selects a performance level in this range and appropriate
|
||||||
|
to the current workload.
|
||||||
|
|
||||||
amijoy.map= [HW,JOY] Amiga joystick support
|
amijoy.map= [HW,JOY] Amiga joystick support
|
||||||
Map of devices attached to JOY0DAT and JOY1DAT
|
Map of devices attached to JOY0DAT and JOY1DAT
|
||||||
|
|
|
@ -308,7 +308,22 @@ static int cppc_init_perf(struct amd_cpudata *cpudata)
|
||||||
cppc_perf.lowest_nonlinear_perf);
|
cppc_perf.lowest_nonlinear_perf);
|
||||||
WRITE_ONCE(cpudata->lowest_perf, cppc_perf.lowest_perf);
|
WRITE_ONCE(cpudata->lowest_perf, cppc_perf.lowest_perf);
|
||||||
|
|
||||||
return 0;
|
if (cppc_state == AMD_PSTATE_ACTIVE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ret = cppc_get_auto_sel_caps(cpudata->cpu, &cppc_perf);
|
||||||
|
if (ret) {
|
||||||
|
pr_warn("failed to get auto_sel, ret: %d\n", ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = cppc_set_auto_sel(cpudata->cpu,
|
||||||
|
(cppc_state == AMD_PSTATE_PASSIVE) ? 0 : 1);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
pr_warn("failed to set auto_sel, ret: %d\n", ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_STATIC_CALL(amd_pstate_init_perf, pstate_init_perf);
|
DEFINE_STATIC_CALL(amd_pstate_init_perf, pstate_init_perf);
|
||||||
|
@ -385,12 +400,18 @@ static inline bool amd_pstate_sample(struct amd_cpudata *cpudata)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
|
static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
|
||||||
u32 des_perf, u32 max_perf, bool fast_switch)
|
u32 des_perf, u32 max_perf, bool fast_switch, int gov_flags)
|
||||||
{
|
{
|
||||||
u64 prev = READ_ONCE(cpudata->cppc_req_cached);
|
u64 prev = READ_ONCE(cpudata->cppc_req_cached);
|
||||||
u64 value = prev;
|
u64 value = prev;
|
||||||
|
|
||||||
des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
|
des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
|
||||||
|
|
||||||
|
if ((cppc_state == AMD_PSTATE_GUIDED) && (gov_flags & CPUFREQ_GOV_DYNAMIC_SWITCHING)) {
|
||||||
|
min_perf = des_perf;
|
||||||
|
des_perf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
value &= ~AMD_CPPC_MIN_PERF(~0L);
|
value &= ~AMD_CPPC_MIN_PERF(~0L);
|
||||||
value |= AMD_CPPC_MIN_PERF(min_perf);
|
value |= AMD_CPPC_MIN_PERF(min_perf);
|
||||||
|
|
||||||
|
@ -445,7 +466,7 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
|
||||||
|
|
||||||
cpufreq_freq_transition_begin(policy, &freqs);
|
cpufreq_freq_transition_begin(policy, &freqs);
|
||||||
amd_pstate_update(cpudata, min_perf, des_perf,
|
amd_pstate_update(cpudata, min_perf, des_perf,
|
||||||
max_perf, false);
|
max_perf, false, policy->governor->flags);
|
||||||
cpufreq_freq_transition_end(policy, &freqs, false);
|
cpufreq_freq_transition_end(policy, &freqs, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -479,7 +500,8 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
|
||||||
if (max_perf < min_perf)
|
if (max_perf < min_perf)
|
||||||
max_perf = min_perf;
|
max_perf = min_perf;
|
||||||
|
|
||||||
amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true);
|
amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true,
|
||||||
|
policy->governor->flags);
|
||||||
cpufreq_cpu_put(policy);
|
cpufreq_cpu_put(policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1279,7 +1301,7 @@ static int __init amd_pstate_init(void)
|
||||||
/* capability check */
|
/* capability check */
|
||||||
if (boot_cpu_has(X86_FEATURE_CPPC)) {
|
if (boot_cpu_has(X86_FEATURE_CPPC)) {
|
||||||
pr_debug("AMD CPPC MSR based functionality is supported\n");
|
pr_debug("AMD CPPC MSR based functionality is supported\n");
|
||||||
if (cppc_state == AMD_PSTATE_PASSIVE)
|
if (cppc_state != AMD_PSTATE_ACTIVE)
|
||||||
current_pstate_driver->adjust_perf = amd_pstate_adjust_perf;
|
current_pstate_driver->adjust_perf = amd_pstate_adjust_perf;
|
||||||
} else {
|
} else {
|
||||||
pr_debug("AMD CPPC shared memory based functionality is supported\n");
|
pr_debug("AMD CPPC shared memory based functionality is supported\n");
|
||||||
|
@ -1341,7 +1363,7 @@ static int __init amd_pstate_param(char *str)
|
||||||
if (cppc_state == AMD_PSTATE_ACTIVE)
|
if (cppc_state == AMD_PSTATE_ACTIVE)
|
||||||
current_pstate_driver = &amd_pstate_epp_driver;
|
current_pstate_driver = &amd_pstate_epp_driver;
|
||||||
|
|
||||||
if (cppc_state == AMD_PSTATE_PASSIVE)
|
if (cppc_state == AMD_PSTATE_PASSIVE || cppc_state == AMD_PSTATE_GUIDED)
|
||||||
current_pstate_driver = &amd_pstate_driver;
|
current_pstate_driver = &amd_pstate_driver;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -97,6 +97,7 @@ enum amd_pstate_mode {
|
||||||
AMD_PSTATE_DISABLE = 0,
|
AMD_PSTATE_DISABLE = 0,
|
||||||
AMD_PSTATE_PASSIVE,
|
AMD_PSTATE_PASSIVE,
|
||||||
AMD_PSTATE_ACTIVE,
|
AMD_PSTATE_ACTIVE,
|
||||||
|
AMD_PSTATE_GUIDED,
|
||||||
AMD_PSTATE_MAX,
|
AMD_PSTATE_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,6 +105,7 @@ static const char * const amd_pstate_mode_string[] = {
|
||||||
[AMD_PSTATE_DISABLE] = "disable",
|
[AMD_PSTATE_DISABLE] = "disable",
|
||||||
[AMD_PSTATE_PASSIVE] = "passive",
|
[AMD_PSTATE_PASSIVE] = "passive",
|
||||||
[AMD_PSTATE_ACTIVE] = "active",
|
[AMD_PSTATE_ACTIVE] = "active",
|
||||||
|
[AMD_PSTATE_GUIDED] = "guided",
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
#endif /* _LINUX_AMD_PSTATE_H */
|
#endif /* _LINUX_AMD_PSTATE_H */
|
||||||
|
|
Loading…
Reference in New Issue