From: <gregkh@linuxfoundation.org>
To: javi.merino@arm.com, edubezval@gmail.com,
gregkh@linuxfoundation.org, rui.zhang@intel.com
Cc: <stable@vger.kernel.org>, <stable-commits@vger.kernel.org>
Subject: Patch "thermal: cpu_cooling: don't call kcalloc() under rcu_read_lock" has been added to the 4.2-stable tree
Date: Sat, 17 Oct 2015 15:04:46 -0700 [thread overview]
Message-ID: <1445119486193112@kroah.com> (raw)
This is a note to let you know that I've just added the patch titled
thermal: cpu_cooling: don't call kcalloc() under rcu_read_lock
to the 4.2-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
thermal-cpu_cooling-don-t-call-kcalloc-under-rcu_read_lock.patch
and it can be found in the queue-4.2 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@vger.kernel.org> know about it.
>From 459ac37506d195713b5e82271a2ac44a777e47df Mon Sep 17 00:00:00 2001
From: Javi Merino <javi.merino@arm.com>
Date: Mon, 17 Aug 2015 19:21:42 +0100
Subject: thermal: cpu_cooling: don't call kcalloc() under rcu_read_lock
From: Javi Merino <javi.merino@arm.com>
commit 459ac37506d195713b5e82271a2ac44a777e47df upstream.
build_dyn_power_table() allocates the power table while holding
rcu_read_lock. kcalloc using GFP_KERNEL may sleep, so it can't be
called in an RCU read-side path.
Move the rcu protection to the part of the function that really needs
it: the part that handles the dev_pm_opp pointer received from
dev_pm_opp_find_freq_ceil(). In the unlikely case that there is an OPP
added to the cpu while this function is running, return -EAGAIN.
Fixes: c36cf0717631 ("thermal: cpu_cooling: implement the power cooling device API")
Cc: Zhang Rui <rui.zhang@intel.com>
Cc: Eduardo Valentin <edubezval@gmail.com>
Signed-off-by: Javi Merino <javi.merino@arm.com>
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/thermal/cpu_cooling.c | 47 ++++++++++++++++++++----------------------
1 file changed, 23 insertions(+), 24 deletions(-)
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -262,7 +262,9 @@ static int cpufreq_thermal_notifier(stru
* efficiently. Power is stored in mW, frequency in KHz. The
* resulting table is in ascending order.
*
- * Return: 0 on success, -E* on error.
+ * Return: 0 on success, -EINVAL if there are no OPPs for any CPUs,
+ * -ENOMEM if we run out of memory or -EAGAIN if an OPP was
+ * added/enabled while the function was executing.
*/
static int build_dyn_power_table(struct cpufreq_cooling_device *cpufreq_device,
u32 capacitance)
@@ -270,11 +272,9 @@ static int build_dyn_power_table(struct
struct power_table *power_table;
struct dev_pm_opp *opp;
struct device *dev = NULL;
- int num_opps = 0, cpu, i, ret = 0;
+ int num_opps = 0, cpu, i;
unsigned long freq;
- rcu_read_lock();
-
for_each_cpu(cpu, &cpufreq_device->allowed_cpus) {
dev = get_cpu_device(cpu);
if (!dev) {
@@ -284,24 +284,20 @@ static int build_dyn_power_table(struct
}
num_opps = dev_pm_opp_get_opp_count(dev);
- if (num_opps > 0) {
+ if (num_opps > 0)
break;
- } else if (num_opps < 0) {
- ret = num_opps;
- goto unlock;
- }
+ else if (num_opps < 0)
+ return num_opps;
}
- if (num_opps == 0) {
- ret = -EINVAL;
- goto unlock;
- }
+ if (num_opps == 0)
+ return -EINVAL;
power_table = kcalloc(num_opps, sizeof(*power_table), GFP_KERNEL);
- if (!power_table) {
- ret = -ENOMEM;
- goto unlock;
- }
+ if (!power_table)
+ return -ENOMEM;
+
+ rcu_read_lock();
for (freq = 0, i = 0;
opp = dev_pm_opp_find_freq_ceil(dev, &freq), !IS_ERR(opp);
@@ -309,6 +305,11 @@ static int build_dyn_power_table(struct
u32 freq_mhz, voltage_mv;
u64 power;
+ if (i >= num_opps) {
+ rcu_read_unlock();
+ return -EAGAIN;
+ }
+
freq_mhz = freq / 1000000;
voltage_mv = dev_pm_opp_get_voltage(opp) / 1000;
@@ -326,18 +327,16 @@ static int build_dyn_power_table(struct
power_table[i].power = power;
}
- if (i == 0) {
- ret = PTR_ERR(opp);
- goto unlock;
- }
+ rcu_read_unlock();
+
+ if (i != num_opps)
+ return PTR_ERR(opp);
cpufreq_device->cpu_dev = dev;
cpufreq_device->dyn_power_table = power_table;
cpufreq_device->dyn_power_table_entries = i;
-unlock:
- rcu_read_unlock();
- return ret;
+ return 0;
}
static u32 cpu_freq_to_power(struct cpufreq_cooling_device *cpufreq_device,
Patches currently in stable-queue which might be from javi.merino@arm.com are
queue-4.2/thermal-cpu_cooling-don-t-call-kcalloc-under-rcu_read_lock.patch
queue-4.2/thermal-cpu_cooling-free-power-table-on-error-or-when-unregistering.patch
reply other threads:[~2015-10-17 22:04 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1445119486193112@kroah.com \
--to=gregkh@linuxfoundation.org \
--cc=edubezval@gmail.com \
--cc=javi.merino@arm.com \
--cc=rui.zhang@intel.com \
--cc=stable-commits@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.