aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/stop_machine.h
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-06-23 14:19:28 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2011-06-27 18:17:08 -0400
commitf740e6cd0cb5e7468e46831aeb4d9c30e03d5ebc (patch)
tree83d81928de5d3ebc3b325f633dddd77a0e6ad662 /include/linux/stop_machine.h
parentfd7355ba1e936487f5aae6fc058c6cb300e44a64 (diff)
stop_machine: implement stop_machine_from_inactive_cpu()
Currently, mtrr wants stop_machine functionality while a CPU is being brought up. As stop_machine() requires the calling CPU to be active, mtrr implements its own stop_machine using stop_one_cpu() on each online CPU. This doesn't only unnecessarily duplicate complex logic but also introduces a possibility of deadlock when it races against the generic stop_machine(). This patch implements stop_machine_from_inactive_cpu() to serve such use cases. Its functionality is basically the same as stop_machine(); however, it should be called from a CPU which isn't active and doesn't depend on working scheduling on the calling CPU. This is achieved by using busy loops for synchronization and open-coding stop_cpus queuing and waiting with direct invocation of fn() for local CPU inbetween. Signed-off-by: Tejun Heo <tj@kernel.org> Link: http://lkml.kernel.org/r/20110623182056.982526827@sbsiddha-MOBL3.sc.intel.com Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'include/linux/stop_machine.h')
-rw-r--r--include/linux/stop_machine.h14
1 files changed, 12 insertions, 2 deletions
diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h
index 14d3524d1274..e0f2da25d751 100644
--- a/include/linux/stop_machine.h
+++ b/include/linux/stop_machine.h
@@ -126,15 +126,19 @@ int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
126 */ 126 */
127int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus); 127int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus);
128 128
129int stop_machine_from_inactive_cpu(int (*fn)(void *), void *data,
130 const struct cpumask *cpus);
131
129#else /* CONFIG_STOP_MACHINE && CONFIG_SMP */ 132#else /* CONFIG_STOP_MACHINE && CONFIG_SMP */
130 133
131static inline int __stop_machine(int (*fn)(void *), void *data, 134static inline int __stop_machine(int (*fn)(void *), void *data,
132 const struct cpumask *cpus) 135 const struct cpumask *cpus)
133{ 136{
137 unsigned long flags;
134 int ret; 138 int ret;
135 local_irq_disable(); 139 local_irq_save(flags);
136 ret = fn(data); 140 ret = fn(data);
137 local_irq_enable(); 141 local_irq_restore(flags);
138 return ret; 142 return ret;
139} 143}
140 144
@@ -144,5 +148,11 @@ static inline int stop_machine(int (*fn)(void *), void *data,
144 return __stop_machine(fn, data, cpus); 148 return __stop_machine(fn, data, cpus);
145} 149}
146 150
151static inline int stop_machine_from_inactive_cpu(int (*fn)(void *), void *data,
152 const struct cpumask *cpus)
153{
154 return __stop_machine(fn, data, cpus);
155}
156
147#endif /* CONFIG_STOP_MACHINE && CONFIG_SMP */ 157#endif /* CONFIG_STOP_MACHINE && CONFIG_SMP */
148#endif /* _LINUX_STOP_MACHINE */ 158#endif /* _LINUX_STOP_MACHINE */