diff options
author | Peter Zijlstra <peterz@infradead.org> | 2014-06-25 01:13:07 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-07-05 05:17:26 -0400 |
commit | a77353e5eb56b6c6098bfce59aff1f449451b0b7 (patch) | |
tree | 5728e7452061d5edc49059d0c8e97f473e7fea83 /kernel/irq_work.c | |
parent | 51da9830d7a58c8f77127c622ee57d453c88af09 (diff) |
irq_work: Remove BUG_ON in irq_work_run()
Because of a collision with 8d056c48e486 ("CPU hotplug, smp: flush any
pending IPI callbacks before CPU offline"), which ends up calling
hotplug_cfd()->flush_smp_call_function_queue()->irq_work_run(), which
is not from IRQ context.
And since that already calls irq_work_run() from the hotplug path,
remove our entire hotplug handling.
Reported-by: Stephen Warren <swarren@wwwdotorg.org>
Tested-by: Stephen Warren <swarren@wwwdotorg.org>
Reviewed-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/n/tip-busatzs2gvz4v62258agipuf@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/irq_work.c')
-rw-r--r-- | kernel/irq_work.c | 46 |
1 files changed, 4 insertions, 42 deletions
diff --git a/kernel/irq_work.c b/kernel/irq_work.c index 4b0a890a304a..e6bcbe756663 100644 --- a/kernel/irq_work.c +++ b/kernel/irq_work.c | |||
@@ -160,20 +160,14 @@ static void irq_work_run_list(struct llist_head *list) | |||
160 | } | 160 | } |
161 | } | 161 | } |
162 | 162 | ||
163 | static void __irq_work_run(void) | ||
164 | { | ||
165 | irq_work_run_list(&__get_cpu_var(raised_list)); | ||
166 | irq_work_run_list(&__get_cpu_var(lazy_list)); | ||
167 | } | ||
168 | |||
169 | /* | 163 | /* |
170 | * Run the irq_work entries on this cpu. Requires to be ran from hardirq | 164 | * hotplug calls this through: |
171 | * context with local IRQs disabled. | 165 | * hotplug_cfd() -> flush_smp_call_function_queue() |
172 | */ | 166 | */ |
173 | void irq_work_run(void) | 167 | void irq_work_run(void) |
174 | { | 168 | { |
175 | BUG_ON(!in_irq()); | 169 | irq_work_run_list(&__get_cpu_var(raised_list)); |
176 | __irq_work_run(); | 170 | irq_work_run_list(&__get_cpu_var(lazy_list)); |
177 | } | 171 | } |
178 | EXPORT_SYMBOL_GPL(irq_work_run); | 172 | EXPORT_SYMBOL_GPL(irq_work_run); |
179 | 173 | ||
@@ -189,35 +183,3 @@ void irq_work_sync(struct irq_work *work) | |||
189 | cpu_relax(); | 183 | cpu_relax(); |
190 | } | 184 | } |
191 | EXPORT_SYMBOL_GPL(irq_work_sync); | 185 | EXPORT_SYMBOL_GPL(irq_work_sync); |
192 | |||
193 | #ifdef CONFIG_HOTPLUG_CPU | ||
194 | static int irq_work_cpu_notify(struct notifier_block *self, | ||
195 | unsigned long action, void *hcpu) | ||
196 | { | ||
197 | long cpu = (long)hcpu; | ||
198 | |||
199 | switch (action) { | ||
200 | case CPU_DYING: | ||
201 | /* Called from stop_machine */ | ||
202 | if (WARN_ON_ONCE(cpu != smp_processor_id())) | ||
203 | break; | ||
204 | __irq_work_run(); | ||
205 | break; | ||
206 | default: | ||
207 | break; | ||
208 | } | ||
209 | return NOTIFY_OK; | ||
210 | } | ||
211 | |||
212 | static struct notifier_block cpu_notify; | ||
213 | |||
214 | static __init int irq_work_init_cpu_notifier(void) | ||
215 | { | ||
216 | cpu_notify.notifier_call = irq_work_cpu_notify; | ||
217 | cpu_notify.priority = 0; | ||
218 | register_cpu_notifier(&cpu_notify); | ||
219 | return 0; | ||
220 | } | ||
221 | device_initcall(irq_work_init_cpu_notifier); | ||
222 | |||
223 | #endif /* CONFIG_HOTPLUG_CPU */ | ||