Skip to content

Commit febab20

Browse files
wkarnyrafaeljw
authored andcommitted
cpufreq/amd-pstate: Fix scaling_min_freq and scaling_max_freq update
When amd_pstate is running, writing to scaling_min_freq and scaling_max_freq has no effect. These values are only passed to the policy level, but not to the platform level. This means that the platform does not know about the frequency limits set by the user. To fix this, update the min_perf and max_perf values at the platform level whenever the user changes the scaling_min_freq and scaling_max_freq values. Fixes: ffa5096 ("cpufreq: amd-pstate: implement Pstate EPP support for the AMD processors") Acked-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Wyes Karny <wyes.karny@amd.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent bb87be2 commit febab20

File tree

2 files changed

+51
-13
lines changed

2 files changed

+51
-13
lines changed

drivers/cpufreq/amd-pstate.c

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -307,11 +307,11 @@ static int pstate_init_perf(struct amd_cpudata *cpudata)
307307
highest_perf = AMD_CPPC_HIGHEST_PERF(cap1);
308308

309309
WRITE_ONCE(cpudata->highest_perf, highest_perf);
310-
310+
WRITE_ONCE(cpudata->max_limit_perf, highest_perf);
311311
WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1));
312312
WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1));
313313
WRITE_ONCE(cpudata->lowest_perf, AMD_CPPC_LOWEST_PERF(cap1));
314-
314+
WRITE_ONCE(cpudata->min_limit_perf, AMD_CPPC_LOWEST_PERF(cap1));
315315
return 0;
316316
}
317317

@@ -329,11 +329,12 @@ static int cppc_init_perf(struct amd_cpudata *cpudata)
329329
highest_perf = cppc_perf.highest_perf;
330330

331331
WRITE_ONCE(cpudata->highest_perf, highest_perf);
332-
332+
WRITE_ONCE(cpudata->max_limit_perf, highest_perf);
333333
WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf);
334334
WRITE_ONCE(cpudata->lowest_nonlinear_perf,
335335
cppc_perf.lowest_nonlinear_perf);
336336
WRITE_ONCE(cpudata->lowest_perf, cppc_perf.lowest_perf);
337+
WRITE_ONCE(cpudata->min_limit_perf, cppc_perf.lowest_perf);
337338

338339
if (cppc_state == AMD_PSTATE_ACTIVE)
339340
return 0;
@@ -432,6 +433,10 @@ static void amd_pstate_update(struct amd_cpudata *cpudata, u32 min_perf,
432433
u64 prev = READ_ONCE(cpudata->cppc_req_cached);
433434
u64 value = prev;
434435

436+
min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf,
437+
cpudata->max_limit_perf);
438+
max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_perf,
439+
cpudata->max_limit_perf);
435440
des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
436441

437442
if ((cppc_state == AMD_PSTATE_GUIDED) && (gov_flags & CPUFREQ_GOV_DYNAMIC_SWITCHING)) {
@@ -470,6 +475,22 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy)
470475
return 0;
471476
}
472477

478+
static int amd_pstate_update_min_max_limit(struct cpufreq_policy *policy)
479+
{
480+
u32 max_limit_perf, min_limit_perf;
481+
struct amd_cpudata *cpudata = policy->driver_data;
482+
483+
max_limit_perf = div_u64(policy->max * cpudata->highest_perf, cpudata->max_freq);
484+
min_limit_perf = div_u64(policy->min * cpudata->highest_perf, cpudata->max_freq);
485+
486+
WRITE_ONCE(cpudata->max_limit_perf, max_limit_perf);
487+
WRITE_ONCE(cpudata->min_limit_perf, min_limit_perf);
488+
WRITE_ONCE(cpudata->max_limit_freq, policy->max);
489+
WRITE_ONCE(cpudata->min_limit_freq, policy->min);
490+
491+
return 0;
492+
}
493+
473494
static int amd_pstate_update_freq(struct cpufreq_policy *policy,
474495
unsigned int target_freq, bool fast_switch)
475496
{
@@ -480,6 +501,9 @@ static int amd_pstate_update_freq(struct cpufreq_policy *policy,
480501
if (!cpudata->max_freq)
481502
return -ENODEV;
482503

504+
if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq)
505+
amd_pstate_update_min_max_limit(policy);
506+
483507
cap_perf = READ_ONCE(cpudata->highest_perf);
484508
min_perf = READ_ONCE(cpudata->lowest_perf);
485509
max_perf = cap_perf;
@@ -534,6 +558,10 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
534558
struct amd_cpudata *cpudata = policy->driver_data;
535559
unsigned int target_freq;
536560

561+
if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq)
562+
amd_pstate_update_min_max_limit(policy);
563+
564+
537565
cap_perf = READ_ONCE(cpudata->highest_perf);
538566
lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
539567
max_freq = READ_ONCE(cpudata->max_freq);
@@ -747,6 +775,8 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy)
747775
/* Initial processor data capability frequencies */
748776
cpudata->max_freq = max_freq;
749777
cpudata->min_freq = min_freq;
778+
cpudata->max_limit_freq = max_freq;
779+
cpudata->min_limit_freq = min_freq;
750780
cpudata->nominal_freq = nominal_freq;
751781
cpudata->lowest_nonlinear_freq = lowest_nonlinear_freq;
752782

@@ -1185,16 +1215,25 @@ static int amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
11851215
return 0;
11861216
}
11871217

1188-
static void amd_pstate_epp_init(unsigned int cpu)
1218+
static void amd_pstate_epp_update_limit(struct cpufreq_policy *policy)
11891219
{
1190-
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
11911220
struct amd_cpudata *cpudata = policy->driver_data;
1192-
u32 max_perf, min_perf;
1221+
u32 max_perf, min_perf, min_limit_perf, max_limit_perf;
11931222
u64 value;
11941223
s16 epp;
11951224

11961225
max_perf = READ_ONCE(cpudata->highest_perf);
11971226
min_perf = READ_ONCE(cpudata->lowest_perf);
1227+
max_limit_perf = div_u64(policy->max * cpudata->highest_perf, cpudata->max_freq);
1228+
min_limit_perf = div_u64(policy->min * cpudata->highest_perf, cpudata->max_freq);
1229+
1230+
max_perf = clamp_t(unsigned long, max_perf, cpudata->min_limit_perf,
1231+
cpudata->max_limit_perf);
1232+
min_perf = clamp_t(unsigned long, min_perf, cpudata->min_limit_perf,
1233+
cpudata->max_limit_perf);
1234+
1235+
WRITE_ONCE(cpudata->max_limit_perf, max_limit_perf);
1236+
WRITE_ONCE(cpudata->min_limit_perf, min_limit_perf);
11981237

11991238
value = READ_ONCE(cpudata->cppc_req_cached);
12001239

@@ -1212,9 +1251,6 @@ static void amd_pstate_epp_init(unsigned int cpu)
12121251
value &= ~AMD_CPPC_DES_PERF(~0L);
12131252
value |= AMD_CPPC_DES_PERF(0);
12141253

1215-
if (cpudata->epp_policy == cpudata->policy)
1216-
goto skip_epp;
1217-
12181254
cpudata->epp_policy = cpudata->policy;
12191255

12201256
/* Get BIOS pre-defined epp value */
@@ -1224,7 +1260,7 @@ static void amd_pstate_epp_init(unsigned int cpu)
12241260
* This return value can only be negative for shared_memory
12251261
* systems where EPP register read/write not supported.
12261262
*/
1227-
goto skip_epp;
1263+
return;
12281264
}
12291265

12301266
if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE)
@@ -1238,8 +1274,6 @@ static void amd_pstate_epp_init(unsigned int cpu)
12381274

12391275
WRITE_ONCE(cpudata->cppc_req_cached, value);
12401276
amd_pstate_set_epp(cpudata, epp);
1241-
skip_epp:
1242-
cpufreq_cpu_put(policy);
12431277
}
12441278

12451279
static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
@@ -1254,7 +1288,7 @@ static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy)
12541288

12551289
cpudata->policy = policy->policy;
12561290

1257-
amd_pstate_epp_init(policy->cpu);
1291+
amd_pstate_epp_update_limit(policy);
12581292

12591293
return 0;
12601294
}

include/linux/amd-pstate.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ struct amd_cpudata {
7070
u32 nominal_perf;
7171
u32 lowest_nonlinear_perf;
7272
u32 lowest_perf;
73+
u32 min_limit_perf;
74+
u32 max_limit_perf;
75+
u32 min_limit_freq;
76+
u32 max_limit_freq;
7377

7478
u32 max_freq;
7579
u32 min_freq;

0 commit comments

Comments
 (0)