cpufreq: interactive: fix race between input event and governor exit

The input event callback does not check the governor_enabled state on
affected CPUS, which will cause kernel panic because the governor_data
will be NULL when governor exit.

Change-Id: Ic2e5cdaefa519701b23203bb77804ce850a5d349
Signed-off-by: Liang Chen <cl@rock-chips.com>
This commit is contained in:
Liang Chen
2019-12-18 20:16:15 +08:00
committed by Tao Huang
parent 8497bd742e
commit a4524d29de

View File

@@ -1125,20 +1125,34 @@ static void cpufreq_interactive_input_event(struct input_handle *handle,
now = ktime_to_us(ktime_get());
for_each_online_cpu(i) {
pcpu = &per_cpu(cpuinfo, i);
if (!pcpu->policy)
if (!down_read_trylock(&pcpu->enable_sem))
continue;
if (!pcpu->governor_enabled) {
up_read(&pcpu->enable_sem);
continue;
}
if (!pcpu->policy) {
up_read(&pcpu->enable_sem);
continue;
}
if (have_governor_per_policy())
tunables = pcpu->policy->governor_data;
else
tunables = common_tunables;
if (!tunables)
if (!tunables) {
up_read(&pcpu->enable_sem);
continue;
}
endtime = now + tunables->touchboostpulse_duration_val;
if (endtime < (tunables->touchboostpulse_endtime +
10 * USEC_PER_MSEC))
10 * USEC_PER_MSEC)) {
up_read(&pcpu->enable_sem);
continue;
}
tunables->touchboostpulse_endtime = endtime;
spin_lock_irqsave(&pcpu->target_freq_lock, flags[1]);
@@ -1421,6 +1435,7 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
pcpu = &per_cpu(cpuinfo, j);
down_write(&pcpu->enable_sem);
pcpu->governor_enabled = 0;
pcpu->policy = NULL;
del_timer_sync(&pcpu->cpu_timer);
del_timer_sync(&pcpu->cpu_slack_timer);
up_write(&pcpu->enable_sem);