blob: 6edfc2c11d99af1c845689adf0e9fbf1043e723d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/kernel/softirq.c
3 *
4 * Copyright (C) 1992 Linus Torvalds
5 *
Pavel Machekb10db7f2008-01-30 13:30:00 +01006 * Distribute under GPLv2.
7 *
8 * Rewritten. Old one was good in 2.2, but in 2.3 it was immoral. --ANK (990903)
David S. Miller54514a72008-09-23 22:15:57 -07009 *
10 * Remote softirq infrastructure is by Jens Axboe.
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 */
12
13#include <linux/module.h>
14#include <linux/kernel_stat.h>
15#include <linux/interrupt.h>
16#include <linux/init.h>
17#include <linux/mm.h>
18#include <linux/notifier.h>
19#include <linux/percpu.h>
20#include <linux/cpu.h>
Rafael J. Wysocki83144182007-07-17 04:03:35 -070021#include <linux/freezer.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/kthread.h>
23#include <linux/rcupdate.h>
Steven Rostedt7e49fcc2009-01-22 19:01:40 -050024#include <linux/ftrace.h>
Andrew Morton78eef012006-03-22 00:08:16 -080025#include <linux/smp.h>
Thomas Gleixner79bf2bb2007-02-16 01:28:03 -080026#include <linux/tick.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
28#include <asm/irq.h>
29/*
30 - No shared variables, all the data are CPU local.
31 - If a softirq needs serialization, let it serialize itself
32 by its own spinlocks.
33 - Even if softirq is serialized, only local cpu is marked for
34 execution. Hence, we get something sort of weak cpu binding.
35 Though it is still not clear, will it result in better locality
36 or will not.
37
38 Examples:
39 - NET RX softirq. It is multithreaded and does not require
40 any global serialization.
41 - NET TX softirq. It kicks software netdevice queues, hence
42 it is logically serialized per device, but this serialization
43 is invisible to common code.
44 - Tasklets: serialized wrt itself.
45 */
46
47#ifndef __ARCH_IRQ_STAT
48irq_cpustat_t irq_stat[NR_CPUS] ____cacheline_aligned;
49EXPORT_SYMBOL(irq_stat);
50#endif
51
Alexey Dobriyan978b0112008-09-06 20:04:36 +020052static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
54static DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
55
56/*
57 * we cannot loop indefinitely here to avoid userspace starvation,
58 * but we also don't want to introduce a worst case 1/HZ latency
59 * to the pending events, so lets the scheduler to balance
60 * the softirq load for us.
61 */
62static inline void wakeup_softirqd(void)
63{
64 /* Interrupts are disabled: no need to stop preemption */
65 struct task_struct *tsk = __get_cpu_var(ksoftirqd);
66
67 if (tsk && tsk->state != TASK_RUNNING)
68 wake_up_process(tsk);
69}
70
71/*
Ingo Molnarde30a2b2006-07-03 00:24:42 -070072 * This one is for softirq.c-internal use,
73 * where hardirqs are disabled legitimately:
74 */
Tim Chen3c829c32006-07-30 03:04:02 -070075#ifdef CONFIG_TRACE_IRQFLAGS
Ingo Molnarde30a2b2006-07-03 00:24:42 -070076static void __local_bh_disable(unsigned long ip)
77{
78 unsigned long flags;
79
80 WARN_ON_ONCE(in_irq());
81
82 raw_local_irq_save(flags);
Steven Rostedt7e49fcc2009-01-22 19:01:40 -050083 /*
84 * The preempt tracer hooks into add_preempt_count and will break
85 * lockdep because it calls back into lockdep after SOFTIRQ_OFFSET
86 * is set and before current->softirq_enabled is cleared.
87 * We must manually increment preempt_count here and manually
88 * call the trace_preempt_off later.
89 */
90 preempt_count() += SOFTIRQ_OFFSET;
Ingo Molnarde30a2b2006-07-03 00:24:42 -070091 /*
92 * Were softirqs turned off above:
93 */
94 if (softirq_count() == SOFTIRQ_OFFSET)
95 trace_softirqs_off(ip);
96 raw_local_irq_restore(flags);
Steven Rostedt7e49fcc2009-01-22 19:01:40 -050097
98 if (preempt_count() == SOFTIRQ_OFFSET)
99 trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700100}
Tim Chen3c829c32006-07-30 03:04:02 -0700101#else /* !CONFIG_TRACE_IRQFLAGS */
102static inline void __local_bh_disable(unsigned long ip)
103{
104 add_preempt_count(SOFTIRQ_OFFSET);
105 barrier();
106}
107#endif /* CONFIG_TRACE_IRQFLAGS */
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700108
109void local_bh_disable(void)
110{
111 __local_bh_disable((unsigned long)__builtin_return_address(0));
112}
113
114EXPORT_SYMBOL(local_bh_disable);
115
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700116/*
117 * Special-case - softirqs can safely be enabled in
118 * cond_resched_softirq(), or by __do_softirq(),
119 * without processing still-pending softirqs:
120 */
121void _local_bh_enable(void)
122{
123 WARN_ON_ONCE(in_irq());
124 WARN_ON_ONCE(!irqs_disabled());
125
126 if (softirq_count() == SOFTIRQ_OFFSET)
127 trace_softirqs_on((unsigned long)__builtin_return_address(0));
128 sub_preempt_count(SOFTIRQ_OFFSET);
129}
130
131EXPORT_SYMBOL(_local_bh_enable);
132
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200133static inline void _local_bh_enable_ip(unsigned long ip)
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700134{
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200135 WARN_ON_ONCE(in_irq() || irqs_disabled());
Tim Chen3c829c32006-07-30 03:04:02 -0700136#ifdef CONFIG_TRACE_IRQFLAGS
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200137 local_irq_disable();
Tim Chen3c829c32006-07-30 03:04:02 -0700138#endif
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700139 /*
140 * Are softirqs going to be turned on now:
141 */
142 if (softirq_count() == SOFTIRQ_OFFSET)
143 trace_softirqs_on(ip);
144 /*
145 * Keep preemption disabled until we are done with
146 * softirq processing:
147 */
148 sub_preempt_count(SOFTIRQ_OFFSET - 1);
149
150 if (unlikely(!in_interrupt() && local_softirq_pending()))
151 do_softirq();
152
153 dec_preempt_count();
Tim Chen3c829c32006-07-30 03:04:02 -0700154#ifdef CONFIG_TRACE_IRQFLAGS
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200155 local_irq_enable();
Tim Chen3c829c32006-07-30 03:04:02 -0700156#endif
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700157 preempt_check_resched();
158}
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200159
160void local_bh_enable(void)
161{
162 _local_bh_enable_ip((unsigned long)__builtin_return_address(0));
163}
164EXPORT_SYMBOL(local_bh_enable);
165
166void local_bh_enable_ip(unsigned long ip)
167{
168 _local_bh_enable_ip(ip);
169}
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700170EXPORT_SYMBOL(local_bh_enable_ip);
171
172/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 * We restart softirq processing MAX_SOFTIRQ_RESTART times,
174 * and we fall back to softirqd after that.
175 *
176 * This number has been established via experimentation.
177 * The two things to balance is latency against fairness -
178 * we want to handle softirqs as soon as possible, but they
179 * should not be able to lock up the box.
180 */
181#define MAX_SOFTIRQ_RESTART 10
182
183asmlinkage void __do_softirq(void)
184{
185 struct softirq_action *h;
186 __u32 pending;
187 int max_restart = MAX_SOFTIRQ_RESTART;
188 int cpu;
189
190 pending = local_softirq_pending();
Paul Mackerras829035fd2006-07-03 00:25:40 -0700191 account_system_vtime(current);
192
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700193 __local_bh_disable((unsigned long)__builtin_return_address(0));
194 trace_softirq_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196 cpu = smp_processor_id();
197restart:
198 /* Reset the pending bitmask before enabling irqs */
Andi Kleen3f744782005-09-12 18:49:24 +0200199 set_softirq_pending(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
Andrew Mortonc70f5d62005-07-30 10:22:49 -0700201 local_irq_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
203 h = softirq_vec;
204
205 do {
206 if (pending & 1) {
Thomas Gleixner8e85b4b2008-10-02 10:50:53 +0200207 int prev_count = preempt_count();
208
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 h->action(h);
Thomas Gleixner8e85b4b2008-10-02 10:50:53 +0200210
211 if (unlikely(prev_count != preempt_count())) {
Linus Torvalds1c95e1b2008-10-16 15:32:46 -0700212 printk(KERN_ERR "huh, entered softirq %td %p"
Thomas Gleixner8e85b4b2008-10-02 10:50:53 +0200213 "with preempt_count %08x,"
214 " exited with %08x?\n", h - softirq_vec,
215 h->action, prev_count, preempt_count());
216 preempt_count() = prev_count;
217 }
218
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219 rcu_bh_qsctr_inc(cpu);
220 }
221 h++;
222 pending >>= 1;
223 } while (pending);
224
Andrew Mortonc70f5d62005-07-30 10:22:49 -0700225 local_irq_disable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226
227 pending = local_softirq_pending();
228 if (pending && --max_restart)
229 goto restart;
230
231 if (pending)
232 wakeup_softirqd();
233
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700234 trace_softirq_exit();
Paul Mackerras829035fd2006-07-03 00:25:40 -0700235
236 account_system_vtime(current);
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700237 _local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238}
239
240#ifndef __ARCH_HAS_DO_SOFTIRQ
241
242asmlinkage void do_softirq(void)
243{
244 __u32 pending;
245 unsigned long flags;
246
247 if (in_interrupt())
248 return;
249
250 local_irq_save(flags);
251
252 pending = local_softirq_pending();
253
254 if (pending)
255 __do_softirq();
256
257 local_irq_restore(flags);
258}
259
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260#endif
261
Ingo Molnardde4b2b2007-02-16 01:27:45 -0800262/*
263 * Enter an interrupt context.
264 */
265void irq_enter(void)
266{
Venki Pallipadi6378ddb2008-01-30 13:30:04 +0100267 int cpu = smp_processor_id();
Thomas Gleixner719254f2008-10-17 09:59:47 +0200268
Paul E. McKenney64db4cf2008-12-18 21:55:32 +0100269 rcu_irq_enter();
Thomas Gleixneree5f80a2008-11-07 11:06:00 +0100270 if (idle_cpu(cpu) && !in_interrupt()) {
271 __irq_enter();
Thomas Gleixner719254f2008-10-17 09:59:47 +0200272 tick_check_idle(cpu);
Thomas Gleixneree5f80a2008-11-07 11:06:00 +0100273 } else
274 __irq_enter();
Ingo Molnardde4b2b2007-02-16 01:27:45 -0800275}
276
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
278# define invoke_softirq() __do_softirq()
279#else
280# define invoke_softirq() do_softirq()
281#endif
282
283/*
284 * Exit an interrupt context. Process softirqs if needed and possible:
285 */
286void irq_exit(void)
287{
288 account_system_vtime(current);
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700289 trace_hardirq_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 sub_preempt_count(IRQ_EXIT_OFFSET);
291 if (!in_interrupt() && local_softirq_pending())
292 invoke_softirq();
Thomas Gleixner79bf2bb2007-02-16 01:28:03 -0800293
294#ifdef CONFIG_NO_HZ
295 /* Make sure that timer wheel updates are propagated */
Steven Rostedt2232c2d2008-02-29 18:46:50 +0100296 rcu_irq_exit();
Paul E. McKenney64db4cf2008-12-18 21:55:32 +0100297 if (idle_cpu(smp_processor_id()) && !in_interrupt() && !need_resched())
298 tick_nohz_stop_sched_tick(0);
Thomas Gleixner79bf2bb2007-02-16 01:28:03 -0800299#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 preempt_enable_no_resched();
301}
302
303/*
304 * This function must run with irqs disabled!
305 */
Harvey Harrison7ad5b3a2008-02-08 04:19:53 -0800306inline void raise_softirq_irqoff(unsigned int nr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307{
308 __raise_softirq_irqoff(nr);
309
310 /*
311 * If we're in an interrupt or softirq, we're done
312 * (this also catches softirq-disabled code). We will
313 * actually run the softirq once we return from
314 * the irq or softirq.
315 *
316 * Otherwise we wake up ksoftirqd to make sure we
317 * schedule the softirq soon.
318 */
319 if (!in_interrupt())
320 wakeup_softirqd();
321}
322
Harvey Harrison7ad5b3a2008-02-08 04:19:53 -0800323void raise_softirq(unsigned int nr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324{
325 unsigned long flags;
326
327 local_irq_save(flags);
328 raise_softirq_irqoff(nr);
329 local_irq_restore(flags);
330}
331
Carlos R. Mafra962cf362008-05-15 11:15:37 -0300332void open_softirq(int nr, void (*action)(struct softirq_action *))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 softirq_vec[nr].action = action;
335}
336
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337/* Tasklets */
338struct tasklet_head
339{
Olof Johansson48f20a92008-03-04 15:23:25 -0800340 struct tasklet_struct *head;
341 struct tasklet_struct **tail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342};
343
Vegard Nossum4620b492008-06-12 23:21:53 +0200344static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);
345static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346
Harvey Harrison7ad5b3a2008-02-08 04:19:53 -0800347void __tasklet_schedule(struct tasklet_struct *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348{
349 unsigned long flags;
350
351 local_irq_save(flags);
Olof Johansson48f20a92008-03-04 15:23:25 -0800352 t->next = NULL;
353 *__get_cpu_var(tasklet_vec).tail = t;
354 __get_cpu_var(tasklet_vec).tail = &(t->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 raise_softirq_irqoff(TASKLET_SOFTIRQ);
356 local_irq_restore(flags);
357}
358
359EXPORT_SYMBOL(__tasklet_schedule);
360
Harvey Harrison7ad5b3a2008-02-08 04:19:53 -0800361void __tasklet_hi_schedule(struct tasklet_struct *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362{
363 unsigned long flags;
364
365 local_irq_save(flags);
Olof Johansson48f20a92008-03-04 15:23:25 -0800366 t->next = NULL;
367 *__get_cpu_var(tasklet_hi_vec).tail = t;
368 __get_cpu_var(tasklet_hi_vec).tail = &(t->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369 raise_softirq_irqoff(HI_SOFTIRQ);
370 local_irq_restore(flags);
371}
372
373EXPORT_SYMBOL(__tasklet_hi_schedule);
374
375static void tasklet_action(struct softirq_action *a)
376{
377 struct tasklet_struct *list;
378
379 local_irq_disable();
Olof Johansson48f20a92008-03-04 15:23:25 -0800380 list = __get_cpu_var(tasklet_vec).head;
381 __get_cpu_var(tasklet_vec).head = NULL;
382 __get_cpu_var(tasklet_vec).tail = &__get_cpu_var(tasklet_vec).head;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 local_irq_enable();
384
385 while (list) {
386 struct tasklet_struct *t = list;
387
388 list = list->next;
389
390 if (tasklet_trylock(t)) {
391 if (!atomic_read(&t->count)) {
392 if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
393 BUG();
394 t->func(t->data);
395 tasklet_unlock(t);
396 continue;
397 }
398 tasklet_unlock(t);
399 }
400
401 local_irq_disable();
Olof Johansson48f20a92008-03-04 15:23:25 -0800402 t->next = NULL;
403 *__get_cpu_var(tasklet_vec).tail = t;
404 __get_cpu_var(tasklet_vec).tail = &(t->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 __raise_softirq_irqoff(TASKLET_SOFTIRQ);
406 local_irq_enable();
407 }
408}
409
410static void tasklet_hi_action(struct softirq_action *a)
411{
412 struct tasklet_struct *list;
413
414 local_irq_disable();
Olof Johansson48f20a92008-03-04 15:23:25 -0800415 list = __get_cpu_var(tasklet_hi_vec).head;
416 __get_cpu_var(tasklet_hi_vec).head = NULL;
417 __get_cpu_var(tasklet_hi_vec).tail = &__get_cpu_var(tasklet_hi_vec).head;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 local_irq_enable();
419
420 while (list) {
421 struct tasklet_struct *t = list;
422
423 list = list->next;
424
425 if (tasklet_trylock(t)) {
426 if (!atomic_read(&t->count)) {
427 if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
428 BUG();
429 t->func(t->data);
430 tasklet_unlock(t);
431 continue;
432 }
433 tasklet_unlock(t);
434 }
435
436 local_irq_disable();
Olof Johansson48f20a92008-03-04 15:23:25 -0800437 t->next = NULL;
438 *__get_cpu_var(tasklet_hi_vec).tail = t;
439 __get_cpu_var(tasklet_hi_vec).tail = &(t->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 __raise_softirq_irqoff(HI_SOFTIRQ);
441 local_irq_enable();
442 }
443}
444
445
446void tasklet_init(struct tasklet_struct *t,
447 void (*func)(unsigned long), unsigned long data)
448{
449 t->next = NULL;
450 t->state = 0;
451 atomic_set(&t->count, 0);
452 t->func = func;
453 t->data = data;
454}
455
456EXPORT_SYMBOL(tasklet_init);
457
458void tasklet_kill(struct tasklet_struct *t)
459{
460 if (in_interrupt())
461 printk("Attempt to kill tasklet from interrupt\n");
462
463 while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
464 do
465 yield();
466 while (test_bit(TASKLET_STATE_SCHED, &t->state));
467 }
468 tasklet_unlock_wait(t);
469 clear_bit(TASKLET_STATE_SCHED, &t->state);
470}
471
472EXPORT_SYMBOL(tasklet_kill);
473
David S. Miller54514a72008-09-23 22:15:57 -0700474DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
475EXPORT_PER_CPU_SYMBOL(softirq_work_list);
476
477static void __local_trigger(struct call_single_data *cp, int softirq)
478{
479 struct list_head *head = &__get_cpu_var(softirq_work_list[softirq]);
480
481 list_add_tail(&cp->list, head);
482
483 /* Trigger the softirq only if the list was previously empty. */
484 if (head->next == &cp->list)
485 raise_softirq_irqoff(softirq);
486}
487
488#ifdef CONFIG_USE_GENERIC_SMP_HELPERS
489static void remote_softirq_receive(void *data)
490{
491 struct call_single_data *cp = data;
492 unsigned long flags;
493 int softirq;
494
495 softirq = cp->priv;
496
497 local_irq_save(flags);
498 __local_trigger(cp, softirq);
499 local_irq_restore(flags);
500}
501
502static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
503{
504 if (cpu_online(cpu)) {
505 cp->func = remote_softirq_receive;
506 cp->info = cp;
507 cp->flags = 0;
508 cp->priv = softirq;
509
510 __smp_call_function_single(cpu, cp);
511 return 0;
512 }
513 return 1;
514}
515#else /* CONFIG_USE_GENERIC_SMP_HELPERS */
516static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
517{
518 return 1;
519}
520#endif
521
522/**
523 * __send_remote_softirq - try to schedule softirq work on a remote cpu
524 * @cp: private SMP call function data area
525 * @cpu: the remote cpu
526 * @this_cpu: the currently executing cpu
527 * @softirq: the softirq for the work
528 *
529 * Attempt to schedule softirq work on a remote cpu. If this cannot be
530 * done, the work is instead queued up on the local cpu.
531 *
532 * Interrupts must be disabled.
533 */
534void __send_remote_softirq(struct call_single_data *cp, int cpu, int this_cpu, int softirq)
535{
536 if (cpu == this_cpu || __try_remote_softirq(cp, cpu, softirq))
537 __local_trigger(cp, softirq);
538}
539EXPORT_SYMBOL(__send_remote_softirq);
540
541/**
542 * send_remote_softirq - try to schedule softirq work on a remote cpu
543 * @cp: private SMP call function data area
544 * @cpu: the remote cpu
545 * @softirq: the softirq for the work
546 *
547 * Like __send_remote_softirq except that disabling interrupts and
548 * computing the current cpu is done for the caller.
549 */
550void send_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
551{
552 unsigned long flags;
553 int this_cpu;
554
555 local_irq_save(flags);
556 this_cpu = smp_processor_id();
557 __send_remote_softirq(cp, cpu, this_cpu, softirq);
558 local_irq_restore(flags);
559}
560EXPORT_SYMBOL(send_remote_softirq);
561
562static int __cpuinit remote_softirq_cpu_notify(struct notifier_block *self,
563 unsigned long action, void *hcpu)
564{
565 /*
566 * If a CPU goes away, splice its entries to the current CPU
567 * and trigger a run of the softirq
568 */
569 if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
570 int cpu = (unsigned long) hcpu;
571 int i;
572
573 local_irq_disable();
574 for (i = 0; i < NR_SOFTIRQS; i++) {
575 struct list_head *head = &per_cpu(softirq_work_list[i], cpu);
576 struct list_head *local_head;
577
578 if (list_empty(head))
579 continue;
580
581 local_head = &__get_cpu_var(softirq_work_list[i]);
582 list_splice_init(head, local_head);
583 raise_softirq_irqoff(i);
584 }
585 local_irq_enable();
586 }
587
588 return NOTIFY_OK;
589}
590
591static struct notifier_block __cpuinitdata remote_softirq_cpu_notifier = {
592 .notifier_call = remote_softirq_cpu_notify,
593};
594
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595void __init softirq_init(void)
596{
Olof Johansson48f20a92008-03-04 15:23:25 -0800597 int cpu;
598
599 for_each_possible_cpu(cpu) {
David S. Miller54514a72008-09-23 22:15:57 -0700600 int i;
601
Olof Johansson48f20a92008-03-04 15:23:25 -0800602 per_cpu(tasklet_vec, cpu).tail =
603 &per_cpu(tasklet_vec, cpu).head;
604 per_cpu(tasklet_hi_vec, cpu).tail =
605 &per_cpu(tasklet_hi_vec, cpu).head;
David S. Miller54514a72008-09-23 22:15:57 -0700606 for (i = 0; i < NR_SOFTIRQS; i++)
607 INIT_LIST_HEAD(&per_cpu(softirq_work_list[i], cpu));
Olof Johansson48f20a92008-03-04 15:23:25 -0800608 }
609
David S. Miller54514a72008-09-23 22:15:57 -0700610 register_hotcpu_notifier(&remote_softirq_cpu_notifier);
611
Carlos R. Mafra962cf362008-05-15 11:15:37 -0300612 open_softirq(TASKLET_SOFTIRQ, tasklet_action);
613 open_softirq(HI_SOFTIRQ, tasklet_hi_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614}
615
616static int ksoftirqd(void * __bind_cpu)
617{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 set_current_state(TASK_INTERRUPTIBLE);
619
620 while (!kthread_should_stop()) {
621 preempt_disable();
622 if (!local_softirq_pending()) {
623 preempt_enable_no_resched();
624 schedule();
625 preempt_disable();
626 }
627
628 __set_current_state(TASK_RUNNING);
629
630 while (local_softirq_pending()) {
631 /* Preempt disable stops cpu going offline.
632 If already offline, we'll be on wrong CPU:
633 don't process */
634 if (cpu_is_offline((long)__bind_cpu))
635 goto wait_to_die;
636 do_softirq();
637 preempt_enable_no_resched();
638 cond_resched();
639 preempt_disable();
640 }
641 preempt_enable();
642 set_current_state(TASK_INTERRUPTIBLE);
643 }
644 __set_current_state(TASK_RUNNING);
645 return 0;
646
647wait_to_die:
648 preempt_enable();
649 /* Wait for kthread_stop */
650 set_current_state(TASK_INTERRUPTIBLE);
651 while (!kthread_should_stop()) {
652 schedule();
653 set_current_state(TASK_INTERRUPTIBLE);
654 }
655 __set_current_state(TASK_RUNNING);
656 return 0;
657}
658
659#ifdef CONFIG_HOTPLUG_CPU
660/*
661 * tasklet_kill_immediate is called to remove a tasklet which can already be
662 * scheduled for execution on @cpu.
663 *
664 * Unlike tasklet_kill, this function removes the tasklet
665 * _immediately_, even if the tasklet is in TASKLET_STATE_SCHED state.
666 *
667 * When this function is called, @cpu must be in the CPU_DEAD state.
668 */
669void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu)
670{
671 struct tasklet_struct **i;
672
673 BUG_ON(cpu_online(cpu));
674 BUG_ON(test_bit(TASKLET_STATE_RUN, &t->state));
675
676 if (!test_bit(TASKLET_STATE_SCHED, &t->state))
677 return;
678
679 /* CPU is dead, so no lock needed. */
Olof Johansson48f20a92008-03-04 15:23:25 -0800680 for (i = &per_cpu(tasklet_vec, cpu).head; *i; i = &(*i)->next) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681 if (*i == t) {
682 *i = t->next;
Olof Johansson48f20a92008-03-04 15:23:25 -0800683 /* If this was the tail element, move the tail ptr */
684 if (*i == NULL)
685 per_cpu(tasklet_vec, cpu).tail = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 return;
687 }
688 }
689 BUG();
690}
691
692static void takeover_tasklets(unsigned int cpu)
693{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 /* CPU is dead, so no lock needed. */
695 local_irq_disable();
696
697 /* Find end, append list for that CPU. */
Christian Borntraegere5e41722008-05-01 04:34:23 -0700698 if (&per_cpu(tasklet_vec, cpu).head != per_cpu(tasklet_vec, cpu).tail) {
699 *(__get_cpu_var(tasklet_vec).tail) = per_cpu(tasklet_vec, cpu).head;
700 __get_cpu_var(tasklet_vec).tail = per_cpu(tasklet_vec, cpu).tail;
701 per_cpu(tasklet_vec, cpu).head = NULL;
702 per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head;
703 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 raise_softirq_irqoff(TASKLET_SOFTIRQ);
705
Christian Borntraegere5e41722008-05-01 04:34:23 -0700706 if (&per_cpu(tasklet_hi_vec, cpu).head != per_cpu(tasklet_hi_vec, cpu).tail) {
707 *__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).head;
708 __get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).tail;
709 per_cpu(tasklet_hi_vec, cpu).head = NULL;
710 per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head;
711 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 raise_softirq_irqoff(HI_SOFTIRQ);
713
714 local_irq_enable();
715}
716#endif /* CONFIG_HOTPLUG_CPU */
717
Chandra Seetharaman8c78f302006-07-30 03:03:35 -0700718static int __cpuinit cpu_callback(struct notifier_block *nfb,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 unsigned long action,
720 void *hcpu)
721{
722 int hotcpu = (unsigned long)hcpu;
723 struct task_struct *p;
724
725 switch (action) {
726 case CPU_UP_PREPARE:
Rafael J. Wysocki8bb78442007-05-09 02:35:10 -0700727 case CPU_UP_PREPARE_FROZEN:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 p = kthread_create(ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu);
729 if (IS_ERR(p)) {
730 printk("ksoftirqd for %i failed\n", hotcpu);
731 return NOTIFY_BAD;
732 }
733 kthread_bind(p, hotcpu);
734 per_cpu(ksoftirqd, hotcpu) = p;
735 break;
736 case CPU_ONLINE:
Rafael J. Wysocki8bb78442007-05-09 02:35:10 -0700737 case CPU_ONLINE_FROZEN:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 wake_up_process(per_cpu(ksoftirqd, hotcpu));
739 break;
740#ifdef CONFIG_HOTPLUG_CPU
741 case CPU_UP_CANCELED:
Rafael J. Wysocki8bb78442007-05-09 02:35:10 -0700742 case CPU_UP_CANCELED_FROZEN:
Heiko Carstensfc75cdf2006-06-25 05:49:10 -0700743 if (!per_cpu(ksoftirqd, hotcpu))
744 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 /* Unbind so it can run. Fall thru. */
Heiko Carstensa4c4af72005-11-07 00:58:38 -0800746 kthread_bind(per_cpu(ksoftirqd, hotcpu),
Rusty Russellf1fc0572009-01-01 10:12:23 +1030747 cpumask_any(cpu_online_mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 case CPU_DEAD:
Satoru Takeuchi1c6b4aa2007-07-15 23:39:48 -0700749 case CPU_DEAD_FROZEN: {
750 struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 p = per_cpu(ksoftirqd, hotcpu);
753 per_cpu(ksoftirqd, hotcpu) = NULL;
Rusty Russell961ccdd2008-06-23 13:55:38 +1000754 sched_setscheduler_nocheck(p, SCHED_FIFO, &param);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 kthread_stop(p);
756 takeover_tasklets(hotcpu);
757 break;
Satoru Takeuchi1c6b4aa2007-07-15 23:39:48 -0700758 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759#endif /* CONFIG_HOTPLUG_CPU */
760 }
761 return NOTIFY_OK;
762}
763
Chandra Seetharaman8c78f302006-07-30 03:03:35 -0700764static struct notifier_block __cpuinitdata cpu_nfb = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 .notifier_call = cpu_callback
766};
767
Eduard - Gabriel Munteanu7babe8d2008-07-25 19:45:11 -0700768static __init int spawn_ksoftirqd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769{
770 void *cpu = (void *)(long)smp_processor_id();
Akinobu Mita07dccf32006-09-29 02:00:22 -0700771 int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
772
773 BUG_ON(err == NOTIFY_BAD);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
775 register_cpu_notifier(&cpu_nfb);
776 return 0;
777}
Eduard - Gabriel Munteanu7babe8d2008-07-25 19:45:11 -0700778early_initcall(spawn_ksoftirqd);
Andrew Morton78eef012006-03-22 00:08:16 -0800779
780#ifdef CONFIG_SMP
781/*
782 * Call a function on all processors
783 */
Jens Axboe15c8b6c2008-05-09 09:39:44 +0200784int on_each_cpu(void (*func) (void *info), void *info, int wait)
Andrew Morton78eef012006-03-22 00:08:16 -0800785{
786 int ret = 0;
787
788 preempt_disable();
Jens Axboe8691e5a2008-06-06 11:18:06 +0200789 ret = smp_call_function(func, info, wait);
Andrew Morton78eef012006-03-22 00:08:16 -0800790 local_irq_disable();
791 func(info);
792 local_irq_enable();
793 preempt_enable();
794 return ret;
795}
796EXPORT_SYMBOL(on_each_cpu);
797#endif
Yinghai Lu43a25632008-12-28 16:01:13 -0800798
799/*
800 * [ These __weak aliases are kept in a separate compilation unit, so that
801 * GCC does not inline them incorrectly. ]
802 */
803
804int __init __weak early_irq_init(void)
805{
806 return 0;
807}
808
809int __init __weak arch_early_irq_init(void)
810{
811 return 0;
812}
813
814int __weak arch_init_chip_data(struct irq_desc *desc, int cpu)
815{
816 return 0;
817}