Skip to content

Commit 2064543

Browse files
committed
cpufreq/amd-pstate: Rework CPPC enabling
The CPPC enable register is configured as "write once". That is any future writes don't actually do anything. Because of this, all the cleanup paths that currently exist for CPPC disable are non-effective. Rework CPPC enable to only enable after all the CAP registers have been read to avoid enabling CPPC on CPUs with invalid _CPC or unpopulated MSRs. As the register is write once, remove all cleanup paths as well. Reviewed-by: Dhananjay Ugwekar <[email protected]> Signed-off-by: Mario Limonciello <[email protected]>
1 parent 93039a6 commit 2064543

File tree

1 file changed

+35
-144
lines changed

1 file changed

+35
-144
lines changed

drivers/cpufreq/amd-pstate.c

Lines changed: 35 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ static struct cpufreq_driver *current_pstate_driver;
8585
static struct cpufreq_driver amd_pstate_driver;
8686
static struct cpufreq_driver amd_pstate_epp_driver;
8787
static int cppc_state = AMD_PSTATE_UNDEFINED;
88-
static bool cppc_enabled;
8988
static bool amd_pstate_prefcore = true;
9089
static struct quirk_entry *quirks;
9190

@@ -371,89 +370,21 @@ static int shmem_set_epp(struct cpufreq_policy *policy, u8 epp)
371370
return ret;
372371
}
373372

374-
static int amd_pstate_set_energy_pref_index(struct cpufreq_policy *policy,
375-
int pref_index)
373+
static inline int msr_cppc_enable(struct cpufreq_policy *policy)
376374
{
377-
struct amd_cpudata *cpudata = policy->driver_data;
378-
u8 epp;
379-
380-
if (!pref_index)
381-
epp = cpudata->epp_default;
382-
else
383-
epp = epp_values[pref_index];
384-
385-
if (epp > 0 && cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) {
386-
pr_debug("EPP cannot be set under performance policy\n");
387-
return -EBUSY;
388-
}
389-
390-
return amd_pstate_set_epp(policy, epp);
391-
}
392-
393-
static inline int msr_cppc_enable(bool enable)
394-
{
395-
int ret, cpu;
396-
unsigned long logical_proc_id_mask = 0;
397-
398-
/*
399-
* MSR_AMD_CPPC_ENABLE is write-once, once set it cannot be cleared.
400-
*/
401-
if (!enable)
402-
return 0;
403-
404-
if (enable == cppc_enabled)
405-
return 0;
406-
407-
for_each_present_cpu(cpu) {
408-
unsigned long logical_id = topology_logical_package_id(cpu);
409-
410-
if (test_bit(logical_id, &logical_proc_id_mask))
411-
continue;
412-
413-
set_bit(logical_id, &logical_proc_id_mask);
414-
415-
ret = wrmsrl_safe_on_cpu(cpu, MSR_AMD_CPPC_ENABLE,
416-
enable);
417-
if (ret)
418-
return ret;
419-
}
420-
421-
cppc_enabled = enable;
422-
return 0;
375+
return wrmsrl_safe_on_cpu(policy->cpu, MSR_AMD_CPPC_ENABLE, 1);
423376
}
424377

425-
static int shmem_cppc_enable(bool enable)
378+
static int shmem_cppc_enable(struct cpufreq_policy *policy)
426379
{
427-
int cpu, ret = 0;
428-
struct cppc_perf_ctrls perf_ctrls;
429-
430-
if (enable == cppc_enabled)
431-
return 0;
432-
433-
for_each_present_cpu(cpu) {
434-
ret = cppc_set_enable(cpu, enable);
435-
if (ret)
436-
return ret;
437-
438-
/* Enable autonomous mode for EPP */
439-
if (cppc_state == AMD_PSTATE_ACTIVE) {
440-
/* Set desired perf as zero to allow EPP firmware control */
441-
perf_ctrls.desired_perf = 0;
442-
ret = cppc_set_perf(cpu, &perf_ctrls);
443-
if (ret)
444-
return ret;
445-
}
446-
}
447-
448-
cppc_enabled = enable;
449-
return ret;
380+
return cppc_set_enable(policy->cpu, 1);
450381
}
451382

452383
DEFINE_STATIC_CALL(amd_pstate_cppc_enable, msr_cppc_enable);
453384

454-
static inline int amd_pstate_cppc_enable(bool enable)
385+
static inline int amd_pstate_cppc_enable(struct cpufreq_policy *policy)
455386
{
456-
return static_call(amd_pstate_cppc_enable)(enable);
387+
return static_call(amd_pstate_cppc_enable)(policy);
457388
}
458389

459390
static int msr_init_perf(struct amd_cpudata *cpudata)
@@ -1063,6 +994,10 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
1063994
cpudata->nominal_freq,
1064995
perf.highest_perf);
1065996

997+
ret = amd_pstate_cppc_enable(policy);
998+
if (ret)
999+
goto free_cpudata1;
1000+
10661001
policy->boost_enabled = READ_ONCE(cpudata->boost_supported);
10671002

10681003
/* It will be updated by governor */
@@ -1110,28 +1045,6 @@ static void amd_pstate_cpu_exit(struct cpufreq_policy *policy)
11101045
kfree(cpudata);
11111046
}
11121047

1113-
static int amd_pstate_cpu_resume(struct cpufreq_policy *policy)
1114-
{
1115-
int ret;
1116-
1117-
ret = amd_pstate_cppc_enable(true);
1118-
if (ret)
1119-
pr_err("failed to enable amd-pstate during resume, return %d\n", ret);
1120-
1121-
return ret;
1122-
}
1123-
1124-
static int amd_pstate_cpu_suspend(struct cpufreq_policy *policy)
1125-
{
1126-
int ret;
1127-
1128-
ret = amd_pstate_cppc_enable(false);
1129-
if (ret)
1130-
pr_err("failed to disable amd-pstate during suspend, return %d\n", ret);
1131-
1132-
return ret;
1133-
}
1134-
11351048
/* Sysfs attributes */
11361049

11371050
/*
@@ -1223,8 +1136,10 @@ static ssize_t show_energy_performance_available_preferences(
12231136
static ssize_t store_energy_performance_preference(
12241137
struct cpufreq_policy *policy, const char *buf, size_t count)
12251138
{
1139+
struct amd_cpudata *cpudata = policy->driver_data;
12261140
char str_preference[21];
12271141
ssize_t ret;
1142+
u8 epp;
12281143

12291144
ret = sscanf(buf, "%20s", str_preference);
12301145
if (ret != 1)
@@ -1234,7 +1149,17 @@ static ssize_t store_energy_performance_preference(
12341149
if (ret < 0)
12351150
return -EINVAL;
12361151

1237-
ret = amd_pstate_set_energy_pref_index(policy, ret);
1152+
if (!ret)
1153+
epp = cpudata->epp_default;
1154+
else
1155+
epp = epp_values[ret];
1156+
1157+
if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
1158+
pr_debug("EPP cannot be set under performance policy\n");
1159+
return -EBUSY;
1160+
}
1161+
1162+
ret = amd_pstate_set_epp(policy, epp);
12381163

12391164
return ret ? ret : count;
12401165
}
@@ -1267,7 +1192,6 @@ static ssize_t show_energy_performance_preference(
12671192

12681193
static void amd_pstate_driver_cleanup(void)
12691194
{
1270-
amd_pstate_cppc_enable(false);
12711195
cppc_state = AMD_PSTATE_DISABLE;
12721196
current_pstate_driver = NULL;
12731197
}
@@ -1301,14 +1225,6 @@ static int amd_pstate_register_driver(int mode)
13011225

13021226
cppc_state = mode;
13031227

1304-
ret = amd_pstate_cppc_enable(true);
1305-
if (ret) {
1306-
pr_err("failed to enable cppc during amd-pstate driver registration, return %d\n",
1307-
ret);
1308-
amd_pstate_driver_cleanup();
1309-
return ret;
1310-
}
1311-
13121228
/* at least one CPU supports CPB */
13131229
current_pstate_driver->boost_enabled = cpu_feature_enabled(X86_FEATURE_CPB);
13141230

@@ -1548,11 +1464,15 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
15481464
policy->cpuinfo.max_freq = policy->max = perf_to_freq(perf,
15491465
cpudata->nominal_freq,
15501466
perf.highest_perf);
1467+
policy->driver_data = cpudata;
1468+
1469+
ret = amd_pstate_cppc_enable(policy);
1470+
if (ret)
1471+
goto free_cpudata1;
15511472

15521473
/* It will be updated by governor */
15531474
policy->cur = policy->cpuinfo.min_freq;
15541475

1555-
policy->driver_data = cpudata;
15561476

15571477
policy->boost_enabled = READ_ONCE(cpudata->boost_supported);
15581478

@@ -1644,31 +1564,11 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
16441564
return 0;
16451565
}
16461566

1647-
static int amd_pstate_epp_reenable(struct cpufreq_policy *policy)
1648-
{
1649-
int ret;
1650-
1651-
ret = amd_pstate_cppc_enable(true);
1652-
if (ret)
1653-
pr_err("failed to enable amd pstate during resume, return %d\n", ret);
1654-
1655-
1656-
return amd_pstate_epp_update_limit(policy);
1657-
}
1658-
16591567
static int amd_pstate_epp_cpu_online(struct cpufreq_policy *policy)
16601568
{
1661-
struct amd_cpudata *cpudata = policy->driver_data;
1662-
int ret;
1663-
1664-
pr_debug("AMD CPU Core %d going online\n", cpudata->cpu);
1569+
pr_debug("AMD CPU Core %d going online\n", policy->cpu);
16651570

1666-
ret = amd_pstate_epp_reenable(policy);
1667-
if (ret)
1668-
return ret;
1669-
cpudata->suspended = false;
1670-
1671-
return 0;
1571+
return amd_pstate_cppc_enable(policy);
16721572
}
16731573

16741574
static int amd_pstate_epp_cpu_offline(struct cpufreq_policy *policy)
@@ -1686,23 +1586,13 @@ static int amd_pstate_epp_cpu_offline(struct cpufreq_policy *policy)
16861586
static int amd_pstate_epp_suspend(struct cpufreq_policy *policy)
16871587
{
16881588
struct amd_cpudata *cpudata = policy->driver_data;
1689-
int ret;
1690-
1691-
/* avoid suspending when EPP is not enabled */
1692-
if (cppc_state != AMD_PSTATE_ACTIVE)
1693-
return 0;
16941589

16951590
/* invalidate to ensure it's rewritten during resume */
16961591
cpudata->cppc_req_cached = 0;
16971592

16981593
/* set this flag to avoid setting core offline*/
16991594
cpudata->suspended = true;
17001595

1701-
/* disable CPPC in lowlevel firmware */
1702-
ret = amd_pstate_cppc_enable(false);
1703-
if (ret)
1704-
pr_err("failed to suspend, return %d\n", ret);
1705-
17061596
return 0;
17071597
}
17081598

@@ -1711,8 +1601,12 @@ static int amd_pstate_epp_resume(struct cpufreq_policy *policy)
17111601
struct amd_cpudata *cpudata = policy->driver_data;
17121602

17131603
if (cpudata->suspended) {
1604+
int ret;
1605+
17141606
/* enable amd pstate from suspend state*/
1715-
amd_pstate_epp_reenable(policy);
1607+
ret = amd_pstate_epp_update_limit(policy);
1608+
if (ret)
1609+
return ret;
17161610

17171611
cpudata->suspended = false;
17181612
}
@@ -1727,8 +1621,6 @@ static struct cpufreq_driver amd_pstate_driver = {
17271621
.fast_switch = amd_pstate_fast_switch,
17281622
.init = amd_pstate_cpu_init,
17291623
.exit = amd_pstate_cpu_exit,
1730-
.suspend = amd_pstate_cpu_suspend,
1731-
.resume = amd_pstate_cpu_resume,
17321624
.set_boost = amd_pstate_set_boost,
17331625
.update_limits = amd_pstate_update_limits,
17341626
.name = "amd-pstate",
@@ -1895,7 +1787,6 @@ static int __init amd_pstate_init(void)
18951787

18961788
global_attr_free:
18971789
cpufreq_unregister_driver(current_pstate_driver);
1898-
amd_pstate_cppc_enable(false);
18991790
return ret;
19001791
}
19011792
device_initcall(amd_pstate_init);

0 commit comments

Comments
 (0)