|
|
|
@@ -86,15 +86,6 @@ struct quirk_entry {
|
|
|
|
|
u32 lowest_freq;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* TODO: We need more time to fine tune processors with shared memory solution
|
|
|
|
|
* with community together.
|
|
|
|
|
*
|
|
|
|
|
* There are some performance drops on the CPU benchmarks which reports from
|
|
|
|
|
* Suse. We are co-working with them to fine tune the shared memory solution. So
|
|
|
|
|
* we disable it by default to go acpi-cpufreq on these processors and add a
|
|
|
|
|
* module parameter to be able to enable it manually for debugging.
|
|
|
|
|
*/
|
|
|
|
|
static struct cpufreq_driver *current_pstate_driver;
|
|
|
|
|
static struct cpufreq_driver amd_pstate_driver;
|
|
|
|
|
static struct cpufreq_driver amd_pstate_epp_driver;
|
|
|
|
@@ -158,7 +149,7 @@ static int __init dmi_matched_7k62_bios_bug(const struct dmi_system_id *dmi)
|
|
|
|
|
* broken BIOS lack of nominal_freq and lowest_freq capabilities
|
|
|
|
|
* definition in ACPI tables
|
|
|
|
|
*/
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_ZEN2)) {
|
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_ZEN2)) {
|
|
|
|
|
quirks = dmi->driver_data;
|
|
|
|
|
pr_info("Overriding nominal and lowest frequencies for %s\n", dmi->ident);
|
|
|
|
|
return 1;
|
|
|
|
@@ -200,7 +191,7 @@ static s16 amd_pstate_get_epp(struct amd_cpudata *cpudata, u64 cppc_req_cached)
|
|
|
|
|
u64 epp;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_CPPC)) {
|
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
|
|
|
|
if (!cppc_req_cached) {
|
|
|
|
|
epp = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ,
|
|
|
|
|
&cppc_req_cached);
|
|
|
|
@@ -253,7 +244,7 @@ static int amd_pstate_set_epp(struct amd_cpudata *cpudata, u32 epp)
|
|
|
|
|
int ret;
|
|
|
|
|
struct cppc_perf_ctrls perf_ctrls;
|
|
|
|
|
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_CPPC)) {
|
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
|
|
|
|
u64 value = READ_ONCE(cpudata->cppc_req_cached);
|
|
|
|
|
|
|
|
|
|
value &= ~GENMASK_ULL(31, 24);
|
|
|
|
@@ -282,10 +273,8 @@ static int amd_pstate_set_energy_pref_index(struct amd_cpudata *cpudata,
|
|
|
|
|
int epp = -EINVAL;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
if (!pref_index) {
|
|
|
|
|
pr_debug("EPP pref_index is invalid\n");
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
if (!pref_index)
|
|
|
|
|
epp = cpudata->epp_default;
|
|
|
|
|
|
|
|
|
|
if (epp == -EINVAL)
|
|
|
|
|
epp = epp_values[pref_index];
|
|
|
|
@@ -522,6 +511,8 @@ static inline bool amd_pstate_sample(struct amd_cpudata *cpudata)
|
|
|
|
|
static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
|
|
|
|
|
u32 des_perf, u32 max_perf, bool fast_switch, int gov_flags)
|
|
|
|
|
{
|
|
|
|
|
unsigned long max_freq;
|
|
|
|
|
struct cpufreq_policy *policy = cpufreq_cpu_get(cpudata->cpu);
|
|
|
|
|
u64 prev = READ_ONCE(cpudata->cppc_req_cached);
|
|
|
|
|
u64 value = prev;
|
|
|
|
|
|
|
|
|
@@ -531,6 +522,9 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
|
|
|
|
|
cpudata->max_limit_perf);
|
|
|
|
|
des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
|
|
|
|
|
|
|
|
|
|
max_freq = READ_ONCE(cpudata->max_limit_freq);
|
|
|
|
|
policy->cur = div_u64(des_perf * max_freq, max_perf);
|
|
|
|
|
|
|
|
|
|
if ((cppc_state == AMD_PSTATE_GUIDED) && (gov_flags & CPUFREQ_GOV_DYNAMIC_SWITCHING)) {
|
|
|
|
|
min_perf = des_perf;
|
|
|
|
|
des_perf = 0;
|
|
|
|
@@ -652,10 +646,9 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
|
|
|
|
|
unsigned long capacity)
|
|
|
|
|
{
|
|
|
|
|
unsigned long max_perf, min_perf, des_perf,
|
|
|
|
|
cap_perf, lowest_nonlinear_perf, max_freq;
|
|
|
|
|
cap_perf, lowest_nonlinear_perf;
|
|
|
|
|
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
|
|
|
|
|
struct amd_cpudata *cpudata = policy->driver_data;
|
|
|
|
|
unsigned int target_freq;
|
|
|
|
|
|
|
|
|
|
if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq)
|
|
|
|
|
amd_pstate_update_min_max_limit(policy);
|
|
|
|
@@ -663,7 +656,6 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
|
|
|
|
|
|
|
|
|
|
cap_perf = READ_ONCE(cpudata->highest_perf);
|
|
|
|
|
lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
|
|
|
|
|
max_freq = READ_ONCE(cpudata->max_freq);
|
|
|
|
|
|
|
|
|
|
des_perf = cap_perf;
|
|
|
|
|
if (target_perf < capacity)
|
|
|
|
@@ -681,8 +673,6 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
|
|
|
|
|
max_perf = min_perf;
|
|
|
|
|
|
|
|
|
|
des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
|
|
|
|
|
target_freq = div_u64(des_perf * max_freq, max_perf);
|
|
|
|
|
policy->cur = target_freq;
|
|
|
|
|
|
|
|
|
|
amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true,
|
|
|
|
|
policy->governor->flags);
|
|
|
|
@@ -754,7 +744,7 @@ static int amd_pstate_get_highest_perf(int cpu, u32 *highest_perf)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_CPPC)) {
|
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
|
|
|
|
u64 cap1;
|
|
|
|
|
|
|
|
|
|
ret = rdmsrl_safe_on_cpu(cpu, MSR_AMD_CPPC_CAP1, &cap1);
|
|
|
|
@@ -926,12 +916,30 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
|
|
|
|
|
WRITE_ONCE(cpudata->nominal_freq, nominal_freq);
|
|
|
|
|
WRITE_ONCE(cpudata->max_freq, max_freq);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Below values need to be initialized correctly, otherwise driver will fail to load
|
|
|
|
|
* max_freq is calculated according to (nominal_freq * highest_perf)/nominal_perf
|
|
|
|
|
* lowest_nonlinear_freq is a value between [min_freq, nominal_freq]
|
|
|
|
|
* Check _CPC in ACPI table objects if any values are incorrect
|
|
|
|
|
*/
|
|
|
|
|
if (min_freq <= 0 || max_freq <= 0 || nominal_freq <= 0 || min_freq > max_freq) {
|
|
|
|
|
pr_err("min_freq(%d) or max_freq(%d) or nominal_freq(%d) value is incorrect\n",
|
|
|
|
|
min_freq, max_freq, nominal_freq * 1000);
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lowest_nonlinear_freq <= min_freq || lowest_nonlinear_freq > nominal_freq * 1000) {
|
|
|
|
|
pr_err("lowest_nonlinear_freq(%d) value is out of range [min_freq(%d), nominal_freq(%d)]\n",
|
|
|
|
|
lowest_nonlinear_freq, min_freq, nominal_freq * 1000);
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
|
|
|
|
|
{
|
|
|
|
|
int min_freq, max_freq, nominal_freq, ret;
|
|
|
|
|
int min_freq, max_freq, ret;
|
|
|
|
|
struct device *dev;
|
|
|
|
|
struct amd_cpudata *cpudata;
|
|
|
|
|
|
|
|
|
@@ -962,16 +970,6 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
|
|
|
|
|
|
|
|
|
|
min_freq = READ_ONCE(cpudata->min_freq);
|
|
|
|
|
max_freq = READ_ONCE(cpudata->max_freq);
|
|
|
|
|
nominal_freq = READ_ONCE(cpudata->nominal_freq);
|
|
|
|
|
|
|
|
|
|
if (min_freq <= 0 || max_freq <= 0 ||
|
|
|
|
|
nominal_freq <= 0 || min_freq > max_freq) {
|
|
|
|
|
dev_err(dev,
|
|
|
|
|
"min_freq(%d) or max_freq(%d) or nominal_freq (%d) value is incorrect, check _CPC in ACPI tables\n",
|
|
|
|
|
min_freq, max_freq, nominal_freq);
|
|
|
|
|
ret = -EINVAL;
|
|
|
|
|
goto free_cpudata1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
policy->cpuinfo.transition_latency = amd_pstate_get_transition_latency(policy->cpu);
|
|
|
|
|
policy->transition_delay_us = amd_pstate_get_transition_delay_us(policy->cpu);
|
|
|
|
@@ -985,7 +983,7 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
|
|
|
|
|
/* It will be updated by governor */
|
|
|
|
|
policy->cur = policy->cpuinfo.min_freq;
|
|
|
|
|
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_CPPC))
|
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_CPPC))
|
|
|
|
|
policy->fast_switch_possible = true;
|
|
|
|
|
|
|
|
|
|
ret = freq_qos_add_request(&policy->constraints, &cpudata->req[0],
|
|
|
|
@@ -1218,7 +1216,7 @@ static int amd_pstate_change_mode_without_dvr_change(int mode)
|
|
|
|
|
|
|
|
|
|
cppc_state = mode;
|
|
|
|
|
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_CPPC) || cppc_state == AMD_PSTATE_ACTIVE)
|
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_CPPC) || cppc_state == AMD_PSTATE_ACTIVE)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
for_each_present_cpu(cpu) {
|
|
|
|
@@ -1391,7 +1389,7 @@ static bool amd_pstate_acpi_pm_profile_undefined(void)
|
|
|
|
|
|
|
|
|
|
static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
|
|
|
|
|
{
|
|
|
|
|
int min_freq, max_freq, nominal_freq, ret;
|
|
|
|
|
int min_freq, max_freq, ret;
|
|
|
|
|
struct amd_cpudata *cpudata;
|
|
|
|
|
struct device *dev;
|
|
|
|
|
u64 value;
|
|
|
|
@@ -1424,15 +1422,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
|
|
|
|
|
|
|
|
|
|
min_freq = READ_ONCE(cpudata->min_freq);
|
|
|
|
|
max_freq = READ_ONCE(cpudata->max_freq);
|
|
|
|
|
nominal_freq = READ_ONCE(cpudata->nominal_freq);
|
|
|
|
|
if (min_freq <= 0 || max_freq <= 0 ||
|
|
|
|
|
nominal_freq <= 0 || min_freq > max_freq) {
|
|
|
|
|
dev_err(dev,
|
|
|
|
|
"min_freq(%d) or max_freq(%d) or nominal_freq(%d) value is incorrect, check _CPC in ACPI tables\n",
|
|
|
|
|
min_freq, max_freq, nominal_freq);
|
|
|
|
|
ret = -EINVAL;
|
|
|
|
|
goto free_cpudata1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
policy->cpuinfo.min_freq = min_freq;
|
|
|
|
|
policy->cpuinfo.max_freq = max_freq;
|
|
|
|
@@ -1441,7 +1430,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
|
|
|
|
|
|
|
|
|
|
policy->driver_data = cpudata;
|
|
|
|
|
|
|
|
|
|
cpudata->epp_cached = amd_pstate_get_epp(cpudata, 0);
|
|
|
|
|
cpudata->epp_cached = cpudata->epp_default = amd_pstate_get_epp(cpudata, 0);
|
|
|
|
|
|
|
|
|
|
policy->min = policy->cpuinfo.min_freq;
|
|
|
|
|
policy->max = policy->cpuinfo.max_freq;
|
|
|
|
@@ -1456,7 +1445,7 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
|
|
|
|
|
else
|
|
|
|
|
policy->policy = CPUFREQ_POLICY_POWERSAVE;
|
|
|
|
|
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_CPPC)) {
|
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
|
|
|
|
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
@@ -1546,7 +1535,7 @@ static void amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
|
|
|
|
|
epp = 0;
|
|
|
|
|
|
|
|
|
|
/* Set initial EPP value */
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_CPPC)) {
|
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
|
|
|
|
value &= ~GENMASK_ULL(31, 24);
|
|
|
|
|
value |= (u64)epp << 24;
|
|
|
|
|
}
|
|
|
|
@@ -1569,6 +1558,12 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
|
|
|
|
|
|
|
|
|
|
amd_pstate_epp_update_limit(policy);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* policy->cur is never updated with the amd_pstate_epp driver, but it
|
|
|
|
|
* is used as a stale frequency value. So, keep it within limits.
|
|
|
|
|
*/
|
|
|
|
|
policy->cur = policy->min;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -1585,7 +1580,7 @@ static void amd_pstate_epp_reenable(struct amd_cpudata *cpudata)
|
|
|
|
|
value = READ_ONCE(cpudata->cppc_req_cached);
|
|
|
|
|
max_perf = READ_ONCE(cpudata->highest_perf);
|
|
|
|
|
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_CPPC)) {
|
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
|
|
|
|
wrmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, value);
|
|
|
|
|
} else {
|
|
|
|
|
perf_ctrls.max_perf = max_perf;
|
|
|
|
@@ -1619,7 +1614,7 @@ static void amd_pstate_epp_offline(struct cpufreq_policy *policy)
|
|
|
|
|
value = READ_ONCE(cpudata->cppc_req_cached);
|
|
|
|
|
|
|
|
|
|
mutex_lock(&amd_pstate_limits_lock);
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_CPPC)) {
|
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
|
|
|
|
cpudata->epp_policy = CPUFREQ_POLICY_UNKNOWN;
|
|
|
|
|
|
|
|
|
|
/* Set max perf same as min perf */
|
|
|
|
@@ -1746,6 +1741,46 @@ static int __init amd_pstate_set_driver(int mode_idx)
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* CPPC function is not supported for family ID 17H with model_ID ranging from 0x10 to 0x2F.
|
|
|
|
|
* show the debug message that helps to check if the CPU has CPPC support for loading issue.
|
|
|
|
|
*/
|
|
|
|
|
static bool amd_cppc_supported(void)
|
|
|
|
|
{
|
|
|
|
|
struct cpuinfo_x86 *c = &cpu_data(0);
|
|
|
|
|
bool warn = false;
|
|
|
|
|
|
|
|
|
|
if ((boot_cpu_data.x86 == 0x17) && (boot_cpu_data.x86_model < 0x30)) {
|
|
|
|
|
pr_debug_once("CPPC feature is not supported by the processor\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If the CPPC feature is disabled in the BIOS for processors that support MSR-based CPPC,
|
|
|
|
|
* the AMD Pstate driver may not function correctly.
|
|
|
|
|
* Check the CPPC flag and display a warning message if the platform supports CPPC.
|
|
|
|
|
* Note: below checking code will not abort the driver registeration process because of
|
|
|
|
|
* the code is added for debugging purposes.
|
|
|
|
|
*/
|
|
|
|
|
if (!cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_ZEN1) || cpu_feature_enabled(X86_FEATURE_ZEN2)) {
|
|
|
|
|
if (c->x86_model > 0x60 && c->x86_model < 0xaf)
|
|
|
|
|
warn = true;
|
|
|
|
|
} else if (cpu_feature_enabled(X86_FEATURE_ZEN3) || cpu_feature_enabled(X86_FEATURE_ZEN4)) {
|
|
|
|
|
if ((c->x86_model > 0x10 && c->x86_model < 0x1F) ||
|
|
|
|
|
(c->x86_model > 0x40 && c->x86_model < 0xaf))
|
|
|
|
|
warn = true;
|
|
|
|
|
} else if (cpu_feature_enabled(X86_FEATURE_ZEN5)) {
|
|
|
|
|
warn = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (warn)
|
|
|
|
|
pr_warn_once("The CPPC feature is supported but currently disabled by the BIOS.\n"
|
|
|
|
|
"Please enable it if your BIOS has the CPPC option.\n");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __init amd_pstate_init(void)
|
|
|
|
|
{
|
|
|
|
|
struct device *dev_root;
|
|
|
|
@@ -1754,6 +1789,11 @@ static int __init amd_pstate_init(void)
|
|
|
|
|
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
|
|
/* show debug message only if CPPC is not supported */
|
|
|
|
|
if (!amd_cppc_supported())
|
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
|
|
/* show warning message when BIOS broken or ACPI disabled */
|
|
|
|
|
if (!acpi_cpc_valid()) {
|
|
|
|
|
pr_warn_once("the _CPC object is not present in SBIOS or ACPI disabled\n");
|
|
|
|
|
return -ENODEV;
|
|
|
|
@@ -1768,35 +1808,43 @@ static int __init amd_pstate_init(void)
|
|
|
|
|
/* check if this machine need CPPC quirks */
|
|
|
|
|
dmi_check_system(amd_pstate_quirks_table);
|
|
|
|
|
|
|
|
|
|
switch (cppc_state) {
|
|
|
|
|
case AMD_PSTATE_UNDEFINED:
|
|
|
|
|
/*
|
|
|
|
|
* determine the driver mode from the command line or kernel config.
|
|
|
|
|
* If no command line input is provided, cppc_state will be AMD_PSTATE_UNDEFINED.
|
|
|
|
|
* command line options will override the kernel config settings.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (cppc_state == AMD_PSTATE_UNDEFINED) {
|
|
|
|
|
/* Disable on the following configs by default:
|
|
|
|
|
* 1. Undefined platforms
|
|
|
|
|
* 2. Server platforms
|
|
|
|
|
* 3. Shared memory designs
|
|
|
|
|
*/
|
|
|
|
|
if (amd_pstate_acpi_pm_profile_undefined() ||
|
|
|
|
|
amd_pstate_acpi_pm_profile_server() ||
|
|
|
|
|
!boot_cpu_has(X86_FEATURE_CPPC)) {
|
|
|
|
|
amd_pstate_acpi_pm_profile_server()) {
|
|
|
|
|
pr_info("driver load is disabled, boot with specific mode to enable this\n");
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
}
|
|
|
|
|
ret = amd_pstate_set_driver(CONFIG_X86_AMD_PSTATE_DEFAULT_MODE);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
break;
|
|
|
|
|
/* get driver mode from kernel config option [1:4] */
|
|
|
|
|
cppc_state = CONFIG_X86_AMD_PSTATE_DEFAULT_MODE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (cppc_state) {
|
|
|
|
|
case AMD_PSTATE_DISABLE:
|
|
|
|
|
pr_info("driver load is disabled, boot with specific mode to enable this\n");
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
case AMD_PSTATE_PASSIVE:
|
|
|
|
|
case AMD_PSTATE_ACTIVE:
|
|
|
|
|
case AMD_PSTATE_GUIDED:
|
|
|
|
|
ret = amd_pstate_set_driver(cppc_state);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* capability check */
|
|
|
|
|
if (boot_cpu_has(X86_FEATURE_CPPC)) {
|
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_CPPC)) {
|
|
|
|
|
pr_debug("AMD CPPC MSR based functionality is supported\n");
|
|
|
|
|
if (cppc_state != AMD_PSTATE_ACTIVE)
|
|
|
|
|
current_pstate_driver->adjust_perf = amd_pstate_adjust_perf;
|
|
|
|
@@ -1810,13 +1858,15 @@ static int __init amd_pstate_init(void)
|
|
|
|
|
/* enable amd pstate feature */
|
|
|
|
|
ret = amd_pstate_enable(true);
|
|
|
|
|
if (ret) {
|
|
|
|
|
pr_err("failed to enable with return %d\n", ret);
|
|
|
|
|
pr_err("failed to enable driver mode(%d)\n", cppc_state);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = cpufreq_register_driver(current_pstate_driver);
|
|
|
|
|
if (ret)
|
|
|
|
|
if (ret) {
|
|
|
|
|
pr_err("failed to register with return %d\n", ret);
|
|
|
|
|
goto disable_driver;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dev_root = bus_get_dev_root(&cpu_subsys);
|
|
|
|
|
if (dev_root) {
|
|
|
|
@@ -1832,6 +1882,8 @@ static int __init amd_pstate_init(void)
|
|
|
|
|
|
|
|
|
|
global_attr_free:
|
|
|
|
|
cpufreq_unregister_driver(current_pstate_driver);
|
|
|
|
|
disable_driver:
|
|
|
|
|
amd_pstate_enable(false);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
device_initcall(amd_pstate_init);
|
|
|
|
|