summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSudeep Holla <sudeep.holla@arm.com>2019-10-18 06:58:15 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-10-22 12:07:30 -0400
commit6941051d3028963c3b0b3fcdd0815f2b51b957bb (patch)
treef2838c99cbc57ffb008cc2736a8e431fb1eef0be
parent2aac8bdf7a0fbd3e2a34141d28b57a7e21482cf7 (diff)
cpufreq: Cancel policy update work scheduled before freeing
Scheduled policy update work may end up racing with the freeing of the policy and unregistering the driver. One possible race is as below, where the cpufreq_driver is unregistered, but the scheduled work gets executed at later stage when, cpufreq_driver is NULL (i.e. after freeing the policy and driver). Unable to handle kernel NULL pointer dereference at virtual address 0000001c pgd = (ptrval) [0000001c] *pgd=80000080204003, *pmd=00000000 Internal error: Oops: 206 [#1] SMP THUMB2 Modules linked in: CPU: 0 PID: 34 Comm: kworker/0:1 Not tainted 5.4.0-rc3-00006-g67f5a8081a4b #86 Hardware name: ARM-Versatile Express Workqueue: events handle_update PC is at cpufreq_set_policy+0x58/0x228 LR is at dev_pm_qos_read_value+0x77/0xac Control: 70c5387d Table: 80203000 DAC: fffffffd Process kworker/0:1 (pid: 34, stack limit = 0x(ptrval)) (cpufreq_set_policy) from (refresh_frequency_limits.part.24+0x37/0x48) (refresh_frequency_limits.part.24) from (handle_update+0x2f/0x38) (handle_update) from (process_one_work+0x16d/0x3cc) (process_one_work) from (worker_thread+0xff/0x414) (worker_thread) from (kthread+0xff/0x100) (kthread) from (ret_from_fork+0x11/0x28) Fixes: 67d874c3b2c6 ("cpufreq: Register notifiers with the PM QoS framework") Signed-off-by: Sudeep Holla <sudeep.holla@arm.com> [ rjw: Cancel the work before dropping the QoS requests ] Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/cpufreq/cpufreq.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 8478ff6f3045..48a224a6b178 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1268,6 +1268,9 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
1268 freq_qos_remove_notifier(&policy->constraints, FREQ_QOS_MIN, 1268 freq_qos_remove_notifier(&policy->constraints, FREQ_QOS_MIN,
1269 &policy->nb_min); 1269 &policy->nb_min);
1270 1270
1271 /* Cancel any pending policy->update work before freeing the policy. */
1272 cancel_work_sync(&policy->update);
1273
1271 if (policy->max_freq_req) { 1274 if (policy->max_freq_req) {
1272 /* 1275 /*
1273 * CPUFREQ_CREATE_POLICY notification is sent only after 1276 * CPUFREQ_CREATE_POLICY notification is sent only after