Skip to content

Commit e571a5e

Browse files
Meng Lirafaeljw
authored andcommitted
cpufreq: amd-pstate: Update amd-pstate preferred core ranking dynamically
Preferred core rankings can be changed dynamically by the platform based on the workload and platform conditions and accounting for thermals and aging. When this occurs, cpu priority need to be set. Tested-by: Oleksandr Natalenko <[email protected]> Reviewed-by: Mario Limonciello <[email protected]> Reviewed-by: Wyes Karny <[email protected]> Reviewed-by: Huang Rui <[email protected]> Reviewed-by: Perry Yuan <[email protected]> Signed-off-by: Meng Li <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 9c4a13a commit e571a5e

File tree

2 files changed

+58
-0
lines changed

2 files changed

+58
-0
lines changed

drivers/cpufreq/amd-pstate.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
315315
WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1));
316316
WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1));
317317
WRITE_ONCE(cpudata->lowest_perf, AMD_CPPC_LOWEST_PERF(cap1));
318+
WRITE_ONCE(cpudata->prefcore_ranking, AMD_CPPC_HIGHEST_PERF(cap1));
318319
WRITE_ONCE(cpudata->min_limit_perf, AMD_CPPC_LOWEST_PERF(cap1));
319320
return 0;
320321
}
@@ -339,6 +340,7 @@ static int cppc_init_perf(struct amd_cpudata *cpudata)
339340
WRITE_ONCE(cpudata->lowest_nonlinear_perf,
340341
cppc_perf.lowest_nonlinear_perf);
341342
WRITE_ONCE(cpudata->lowest_perf, cppc_perf.lowest_perf);
343+
WRITE_ONCE(cpudata->prefcore_ranking, cppc_perf.highest_perf);
342344
WRITE_ONCE(cpudata->min_limit_perf, cppc_perf.lowest_perf);
343345

344346
if (cppc_state == AMD_PSTATE_ACTIVE)
@@ -785,6 +787,40 @@ static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata)
785787
schedule_work(&sched_prefcore_work);
786788
}
787789

790+
static void amd_pstate_update_limits(unsigned int cpu)
791+
{
792+
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
793+
struct amd_cpudata *cpudata = policy->driver_data;
794+
u32 prev_high = 0, cur_high = 0;
795+
int ret;
796+
bool highest_perf_changed = false;
797+
798+
mutex_lock(&amd_pstate_driver_lock);
799+
if ((!amd_pstate_prefcore) || (!cpudata->hw_prefcore))
800+
goto free_cpufreq_put;
801+
802+
ret = amd_pstate_get_highest_perf(cpu, &cur_high);
803+
if (ret)
804+
goto free_cpufreq_put;
805+
806+
prev_high = READ_ONCE(cpudata->prefcore_ranking);
807+
if (prev_high != cur_high) {
808+
highest_perf_changed = true;
809+
WRITE_ONCE(cpudata->prefcore_ranking, cur_high);
810+
811+
if (cur_high < CPPC_MAX_PERF)
812+
sched_set_itmt_core_prio((int)cur_high, cpu);
813+
}
814+
815+
free_cpufreq_put:
816+
cpufreq_cpu_put(policy);
817+
818+
if (!highest_perf_changed)
819+
cpufreq_update_policy(cpu);
820+
821+
mutex_unlock(&amd_pstate_driver_lock);
822+
}
823+
788824
static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
789825
{
790826
int min_freq, max_freq, nominal_freq, lowest_nonlinear_freq, ret;
@@ -958,6 +994,17 @@ static ssize_t show_amd_pstate_highest_perf(struct cpufreq_policy *policy,
958994
return sysfs_emit(buf, "%u\n", perf);
959995
}
960996

997+
static ssize_t show_amd_pstate_prefcore_ranking(struct cpufreq_policy *policy,
998+
char *buf)
999+
{
1000+
u32 perf;
1001+
struct amd_cpudata *cpudata = policy->driver_data;
1002+
1003+
perf = READ_ONCE(cpudata->prefcore_ranking);
1004+
1005+
return sysfs_emit(buf, "%u\n", perf);
1006+
}
1007+
9611008
static ssize_t show_amd_pstate_hw_prefcore(struct cpufreq_policy *policy,
9621009
char *buf)
9631010
{
@@ -1176,6 +1223,7 @@ cpufreq_freq_attr_ro(amd_pstate_max_freq);
11761223
cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq);
11771224

11781225
cpufreq_freq_attr_ro(amd_pstate_highest_perf);
1226+
cpufreq_freq_attr_ro(amd_pstate_prefcore_ranking);
11791227
cpufreq_freq_attr_ro(amd_pstate_hw_prefcore);
11801228
cpufreq_freq_attr_rw(energy_performance_preference);
11811229
cpufreq_freq_attr_ro(energy_performance_available_preferences);
@@ -1186,6 +1234,7 @@ static struct freq_attr *amd_pstate_attr[] = {
11861234
&amd_pstate_max_freq,
11871235
&amd_pstate_lowest_nonlinear_freq,
11881236
&amd_pstate_highest_perf,
1237+
&amd_pstate_prefcore_ranking,
11891238
&amd_pstate_hw_prefcore,
11901239
NULL,
11911240
};
@@ -1194,6 +1243,7 @@ static struct freq_attr *amd_pstate_epp_attr[] = {
11941243
&amd_pstate_max_freq,
11951244
&amd_pstate_lowest_nonlinear_freq,
11961245
&amd_pstate_highest_perf,
1246+
&amd_pstate_prefcore_ranking,
11971247
&amd_pstate_hw_prefcore,
11981248
&energy_performance_preference,
11991249
&energy_performance_available_preferences,
@@ -1537,6 +1587,7 @@ static struct cpufreq_driver amd_pstate_driver = {
15371587
.suspend = amd_pstate_cpu_suspend,
15381588
.resume = amd_pstate_cpu_resume,
15391589
.set_boost = amd_pstate_set_boost,
1590+
.update_limits = amd_pstate_update_limits,
15401591
.name = "amd-pstate",
15411592
.attr = amd_pstate_attr,
15421593
};
@@ -1551,6 +1602,7 @@ static struct cpufreq_driver amd_pstate_epp_driver = {
15511602
.online = amd_pstate_epp_cpu_online,
15521603
.suspend = amd_pstate_epp_suspend,
15531604
.resume = amd_pstate_epp_resume,
1605+
.update_limits = amd_pstate_update_limits,
15541606
.name = "amd-pstate-epp",
15551607
.attr = amd_pstate_epp_attr,
15561608
};

include/linux/amd-pstate.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,16 @@ struct amd_aperf_mperf {
3939
* @cppc_req_cached: cached performance request hints
4040
* @highest_perf: the maximum performance an individual processor may reach,
4141
* assuming ideal conditions
42+
* For platforms that do not support the preferred core feature, the
43+
* highest_pef may be configured with 166 or 255, to avoid max frequency
44+
* calculated wrongly. we take the fixed value as the highest_perf.
4245
* @nominal_perf: the maximum sustained performance level of the processor,
4346
* assuming ideal operating conditions
4447
* @lowest_nonlinear_perf: the lowest performance level at which nonlinear power
4548
* savings are achieved
4649
* @lowest_perf: the absolute lowest performance level of the processor
50+
* @prefcore_ranking: the preferred core ranking, the higher value indicates a higher
51+
* priority.
4752
* @max_freq: the frequency that mapped to highest_perf
4853
* @min_freq: the frequency that mapped to lowest_perf
4954
* @nominal_freq: the frequency that mapped to nominal_perf
@@ -73,6 +78,7 @@ struct amd_cpudata {
7378
u32 nominal_perf;
7479
u32 lowest_nonlinear_perf;
7580
u32 lowest_perf;
81+
u32 prefcore_ranking;
7682
u32 min_limit_perf;
7783
u32 max_limit_perf;
7884
u32 min_limit_freq;

0 commit comments

Comments
 (0)