Skip to content

Commit c551afc

Browse files
committed
Merge tag 'pm-6.4-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull power management fixes from Rafael Wysocki: "Fix three issues related to the ->fast_switch callback in the AMD P-state cpufreq driver (Gautham R. Shenoy and Wyes Karny)" * tag 'pm-6.4-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: cpufreq: amd-pstate: Update policy->cur in amd_pstate_adjust_perf() cpufreq: amd-pstate: Remove fast_switch_possible flag from active driver cpufreq: amd-pstate: Add ->fast_switch() callback
2 parents 91a3043 + 3bf8c63 commit c551afc

File tree

1 file changed

+37
-9
lines changed

1 file changed

+37
-9
lines changed

drivers/cpufreq/amd-pstate.c

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -444,9 +444,8 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy)
444444
return 0;
445445
}
446446

447-
static int amd_pstate_target(struct cpufreq_policy *policy,
448-
unsigned int target_freq,
449-
unsigned int relation)
447+
static int amd_pstate_update_freq(struct cpufreq_policy *policy,
448+
unsigned int target_freq, bool fast_switch)
450449
{
451450
struct cpufreq_freqs freqs;
452451
struct amd_cpudata *cpudata = policy->driver_data;
@@ -465,26 +464,51 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
465464
des_perf = DIV_ROUND_CLOSEST(target_freq * cap_perf,
466465
cpudata->max_freq);
467466

468-
cpufreq_freq_transition_begin(policy, &freqs);
467+
WARN_ON(fast_switch && !policy->fast_switch_enabled);
468+
/*
469+
* If fast_switch is desired, then there aren't any registered
470+
* transition notifiers. See comment for
471+
* cpufreq_enable_fast_switch().
472+
*/
473+
if (!fast_switch)
474+
cpufreq_freq_transition_begin(policy, &freqs);
475+
469476
amd_pstate_update(cpudata, min_perf, des_perf,
470-
max_perf, false, policy->governor->flags);
471-
cpufreq_freq_transition_end(policy, &freqs, false);
477+
max_perf, fast_switch, policy->governor->flags);
478+
479+
if (!fast_switch)
480+
cpufreq_freq_transition_end(policy, &freqs, false);
472481

473482
return 0;
474483
}
475484

485+
static int amd_pstate_target(struct cpufreq_policy *policy,
486+
unsigned int target_freq,
487+
unsigned int relation)
488+
{
489+
return amd_pstate_update_freq(policy, target_freq, false);
490+
}
491+
492+
static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
493+
unsigned int target_freq)
494+
{
495+
return amd_pstate_update_freq(policy, target_freq, true);
496+
}
497+
476498
static void amd_pstate_adjust_perf(unsigned int cpu,
477499
unsigned long _min_perf,
478500
unsigned long target_perf,
479501
unsigned long capacity)
480502
{
481503
unsigned long max_perf, min_perf, des_perf,
482-
cap_perf, lowest_nonlinear_perf;
504+
cap_perf, lowest_nonlinear_perf, max_freq;
483505
struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
484506
struct amd_cpudata *cpudata = policy->driver_data;
507+
unsigned int target_freq;
485508

486509
cap_perf = READ_ONCE(cpudata->highest_perf);
487510
lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
511+
max_freq = READ_ONCE(cpudata->max_freq);
488512

489513
des_perf = cap_perf;
490514
if (target_perf < capacity)
@@ -501,6 +525,10 @@ static void amd_pstate_adjust_perf(unsigned int cpu,
501525
if (max_perf < min_perf)
502526
max_perf = min_perf;
503527

528+
des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf);
529+
target_freq = div_u64(des_perf * max_freq, max_perf);
530+
policy->cur = target_freq;
531+
504532
amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true,
505533
policy->governor->flags);
506534
cpufreq_cpu_put(policy);
@@ -715,6 +743,7 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)
715743

716744
freq_qos_remove_request(&cpudata->req[1]);
717745
freq_qos_remove_request(&cpudata->req[0]);
746+
policy->fast_switch_possible = false;
718747
kfree(cpudata);
719748

720749
return 0;
@@ -1079,7 +1108,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
10791108
policy->policy = CPUFREQ_POLICY_POWERSAVE;
10801109

10811110
if (boot_cpu_has(X86_FEATURE_CPPC)) {
1082-
policy->fast_switch_possible = true;
10831111
ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value);
10841112
if (ret)
10851113
return ret;
@@ -1102,7 +1130,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy)
11021130
static int amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy)
11031131
{
11041132
pr_debug("CPU %d exiting\n", policy->cpu);
1105-
policy->fast_switch_possible = false;
11061133
return 0;
11071134
}
11081135

@@ -1309,6 +1336,7 @@ static struct cpufreq_driver amd_pstate_driver = {
13091336
.flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
13101337
.verify = amd_pstate_verify,
13111338
.target = amd_pstate_target,
1339+
.fast_switch = amd_pstate_fast_switch,
13121340
.init = amd_pstate_cpu_init,
13131341
.exit = amd_pstate_cpu_exit,
13141342
.suspend = amd_pstate_cpu_suspend,

0 commit comments

Comments
 (0)