summaryrefslogtreecommitdiff
path: root/kernel/stop_machine.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2012-10-03 16:21:53 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-10 00:19:13 (GMT)
commitfe3989bebde11ecb64dc78cbd568f0e4798b6d4a (patch)
tree91dcec549f7b286df9771cb8d822c708a0349f8f /kernel/stop_machine.c
parent93dd9624644443b7e0aa847704e4987a7f03ff22 (diff)
downloadlinux-fsl-qoriq-fe3989bebde11ecb64dc78cbd568f0e4798b6d4a.tar.xz
stomp_machine: Use mutex_trylock when called from inactive cpu
If the stop machinery is called from inactive CPU we cannot use mutex_lock, because some other stomp machine invokation might be in progress and the mutex can be contended. We cannot schedule from this context, so trylock and loop. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: stable-rt@vger.kernel.org
Diffstat (limited to 'kernel/stop_machine.c')
-rw-r--r--kernel/stop_machine.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index bbdef53..5f02a3f 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -160,7 +160,7 @@ static DEFINE_PER_CPU(struct cpu_stop_work, stop_cpus_work);
static void queue_stop_cpus_work(const struct cpumask *cpumask,
cpu_stop_fn_t fn, void *arg,
- struct cpu_stop_done *done)
+ struct cpu_stop_done *done, bool inactive)
{
struct cpu_stop_work *work;
unsigned int cpu;
@@ -177,7 +177,12 @@ static void queue_stop_cpus_work(const struct cpumask *cpumask,
* Make sure that all work is queued on all cpus before we
* any of the cpus can execute it.
*/
- mutex_lock(&stopper_lock);
+ if (!inactive) {
+ mutex_lock(&stopper_lock);
+ } else {
+ while (!mutex_trylock(&stopper_lock))
+ cpu_relax();
+ }
for_each_cpu(cpu, cpumask)
cpu_stop_queue_work(cpu, &per_cpu(stop_cpus_work, cpu));
mutex_unlock(&stopper_lock);
@@ -189,7 +194,7 @@ static int __stop_cpus(const struct cpumask *cpumask,
struct cpu_stop_done done;
cpu_stop_init_done(&done, cpumask_weight(cpumask));
- queue_stop_cpus_work(cpumask, fn, arg, &done);
+ queue_stop_cpus_work(cpumask, fn, arg, &done, false);
wait_for_stop_done(&done);
return done.executed ? done.ret : -ENOENT;
}
@@ -564,7 +569,7 @@ int stop_machine_from_inactive_cpu(int (*fn)(void *), void *data,
set_state(&smdata, STOPMACHINE_PREPARE);
cpu_stop_init_done(&done, num_active_cpus());
queue_stop_cpus_work(cpu_active_mask, stop_machine_cpu_stop, &smdata,
- &done);
+ &done, true);
ret = stop_machine_cpu_stop(&smdata);
/* Busy wait for completion. */