Skip to content

Commit

Permalink
cpufreq: amd-pstate: Add ->fast_switch() callback
Browse files Browse the repository at this point in the history
commit 4badf2e upstream.

Schedutil normally calls the adjust_perf callback for drivers with
adjust_perf callback available and fast_switch_possible flag set.
However, when frequency invariance is disabled and schedutil tries to
invoke fast_switch. So, there is a chance of kernel crash if this
function pointer is not set. To protect against this scenario add
fast_switch callback to amd_pstate driver.

Fixes: 1d215f0 ("cpufreq: amd-pstate: Add fast switch function for AMD P-State")
Signed-off-by: Gautham R. Shenoy <gautham.shenoy@amd.com>
Signed-off-by: Wyes Karny <wyes.karny@amd.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
gautshen authored and gregkh committed Jun 5, 2023
1 parent c18f691 commit 55ce796
Showing 1 changed file with 30 additions and 7 deletions.
37 changes: 30 additions & 7 deletions drivers/cpufreq/amd-pstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,8 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy)
return 0;
}

static int amd_pstate_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
static int amd_pstate_update_freq(struct cpufreq_policy *policy,
unsigned int target_freq, bool fast_switch)
{
struct cpufreq_freqs freqs;
struct amd_cpudata *cpudata = policy->driver_data;
Expand All @@ -270,14 +269,36 @@ static int amd_pstate_target(struct cpufreq_policy *policy,
des_perf = DIV_ROUND_CLOSEST(target_freq * cap_perf,
cpudata->max_freq);

cpufreq_freq_transition_begin(policy, &freqs);
amd_pstate_update(cpudata, min_perf, des_perf,
max_perf, false);
cpufreq_freq_transition_end(policy, &freqs, false);
WARN_ON(fast_switch && !policy->fast_switch_enabled);
/*
* If fast_switch is desired, then there aren't any registered
* transition notifiers. See comment for
* cpufreq_enable_fast_switch().
*/
if (!fast_switch)
cpufreq_freq_transition_begin(policy, &freqs);

amd_pstate_update(cpudata, min_perf, des_perf, max_perf, fast_switch);

if (!fast_switch)
cpufreq_freq_transition_end(policy, &freqs, false);

return 0;
}

static int amd_pstate_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
return amd_pstate_update_freq(policy, target_freq, false);
}

static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy,
unsigned int target_freq)
{
return amd_pstate_update_freq(policy, target_freq, true);
}

static void amd_pstate_adjust_perf(unsigned int cpu,
unsigned long _min_perf,
unsigned long target_perf,
Expand Down Expand Up @@ -523,6 +544,7 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy)

freq_qos_remove_request(&cpudata->req[1]);
freq_qos_remove_request(&cpudata->req[0]);
policy->fast_switch_possible = false;
kfree(cpudata);

return 0;
Expand Down Expand Up @@ -614,6 +636,7 @@ static struct cpufreq_driver amd_pstate_driver = {
.flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS,
.verify = amd_pstate_verify,
.target = amd_pstate_target,
.fast_switch = amd_pstate_fast_switch,
.init = amd_pstate_cpu_init,
.exit = amd_pstate_cpu_exit,
.suspend = amd_pstate_cpu_suspend,
Expand Down

0 comments on commit 55ce796

Please sign in to comment.