blob: 988dfbe6bbe87666ad61ef8efd3b64255609ba6d [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>
Heiko Carstensa0e39ed2009-04-29 13:51:39 +020027
28#define CREATE_TRACE_POINTS
Steven Rostedtad8d75f2009-04-14 19:39:12 -040029#include <trace/events/irq.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
31#include <asm/irq.h>
32/*
33 - No shared variables, all the data are CPU local.
34 - If a softirq needs serialization, let it serialize itself
35 by its own spinlocks.
36 - Even if softirq is serialized, only local cpu is marked for
37 execution. Hence, we get something sort of weak cpu binding.
38 Though it is still not clear, will it result in better locality
39 or will not.
40
41 Examples:
42 - NET RX softirq. It is multithreaded and does not require
43 any global serialization.
44 - NET TX softirq. It kicks software netdevice queues, hence
45 it is logically serialized per device, but this serialization
46 is invisible to common code.
47 - Tasklets: serialized wrt itself.
48 */
49
50#ifndef __ARCH_IRQ_STAT
51irq_cpustat_t irq_stat[NR_CPUS] ____cacheline_aligned;
52EXPORT_SYMBOL(irq_stat);
53#endif
54
Alexey Dobriyan978b0112008-09-06 20:04:36 +020055static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp;
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57static DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
58
Jason Baron5d592b42009-03-12 14:33:36 -040059char *softirq_to_name[NR_SOFTIRQS] = {
Li Zefan5dd4de52009-09-17 17:38:32 +080060 "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL",
Steven Rostedt899039e2009-03-13 00:43:33 -040061 "TASKLET", "SCHED", "HRTIMER", "RCU"
Jason Baron5d592b42009-03-12 14:33:36 -040062};
63
Linus Torvalds1da177e2005-04-16 15:20:36 -070064/*
65 * we cannot loop indefinitely here to avoid userspace starvation,
66 * but we also don't want to introduce a worst case 1/HZ latency
67 * to the pending events, so lets the scheduler to balance
68 * the softirq load for us.
69 */
Peter Zijlstra7f1e2ca2009-03-13 12:21:27 +010070void wakeup_softirqd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -070071{
72 /* Interrupts are disabled: no need to stop preemption */
73 struct task_struct *tsk = __get_cpu_var(ksoftirqd);
74
75 if (tsk && tsk->state != TASK_RUNNING)
76 wake_up_process(tsk);
77}
78
79/*
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -070080 * preempt_count and SOFTIRQ_OFFSET usage:
81 * - preempt_count is changed by SOFTIRQ_OFFSET on entering or leaving
82 * softirq processing.
83 * - preempt_count is changed by SOFTIRQ_DISABLE_OFFSET (= 2 * SOFTIRQ_OFFSET)
84 * on local_bh_disable or local_bh_enable.
85 * This lets us distinguish between whether we are currently processing
86 * softirq and whether we just have bh disabled.
87 */
88
89/*
Ingo Molnarde30a2b2006-07-03 00:24:42 -070090 * This one is for softirq.c-internal use,
91 * where hardirqs are disabled legitimately:
92 */
Tim Chen3c829c32006-07-30 03:04:02 -070093#ifdef CONFIG_TRACE_IRQFLAGS
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -070094static void __local_bh_disable(unsigned long ip, unsigned int cnt)
Ingo Molnarde30a2b2006-07-03 00:24:42 -070095{
96 unsigned long flags;
97
98 WARN_ON_ONCE(in_irq());
99
100 raw_local_irq_save(flags);
Steven Rostedt7e49fcc2009-01-22 19:01:40 -0500101 /*
102 * The preempt tracer hooks into add_preempt_count and will break
103 * lockdep because it calls back into lockdep after SOFTIRQ_OFFSET
104 * is set and before current->softirq_enabled is cleared.
105 * We must manually increment preempt_count here and manually
106 * call the trace_preempt_off later.
107 */
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700108 preempt_count() += cnt;
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700109 /*
110 * Were softirqs turned off above:
111 */
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700112 if (softirq_count() == cnt)
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700113 trace_softirqs_off(ip);
114 raw_local_irq_restore(flags);
Steven Rostedt7e49fcc2009-01-22 19:01:40 -0500115
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700116 if (preempt_count() == cnt)
Steven Rostedt7e49fcc2009-01-22 19:01:40 -0500117 trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1));
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700118}
Tim Chen3c829c32006-07-30 03:04:02 -0700119#else /* !CONFIG_TRACE_IRQFLAGS */
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700120static inline void __local_bh_disable(unsigned long ip, unsigned int cnt)
Tim Chen3c829c32006-07-30 03:04:02 -0700121{
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700122 add_preempt_count(cnt);
Tim Chen3c829c32006-07-30 03:04:02 -0700123 barrier();
124}
125#endif /* CONFIG_TRACE_IRQFLAGS */
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700126
127void local_bh_disable(void)
128{
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700129 __local_bh_disable((unsigned long)__builtin_return_address(0),
130 SOFTIRQ_DISABLE_OFFSET);
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700131}
132
133EXPORT_SYMBOL(local_bh_disable);
134
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700135static void __local_bh_enable(unsigned int cnt)
136{
137 WARN_ON_ONCE(in_irq());
138 WARN_ON_ONCE(!irqs_disabled());
139
140 if (softirq_count() == cnt)
141 trace_softirqs_on((unsigned long)__builtin_return_address(0));
142 sub_preempt_count(cnt);
143}
144
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700145/*
146 * Special-case - softirqs can safely be enabled in
147 * cond_resched_softirq(), or by __do_softirq(),
148 * without processing still-pending softirqs:
149 */
150void _local_bh_enable(void)
151{
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700152 __local_bh_enable(SOFTIRQ_DISABLE_OFFSET);
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700153}
154
155EXPORT_SYMBOL(_local_bh_enable);
156
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200157static inline void _local_bh_enable_ip(unsigned long ip)
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700158{
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200159 WARN_ON_ONCE(in_irq() || irqs_disabled());
Tim Chen3c829c32006-07-30 03:04:02 -0700160#ifdef CONFIG_TRACE_IRQFLAGS
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200161 local_irq_disable();
Tim Chen3c829c32006-07-30 03:04:02 -0700162#endif
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700163 /*
164 * Are softirqs going to be turned on now:
165 */
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700166 if (softirq_count() == SOFTIRQ_DISABLE_OFFSET)
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700167 trace_softirqs_on(ip);
168 /*
169 * Keep preemption disabled until we are done with
170 * softirq processing:
171 */
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700172 sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1);
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700173
174 if (unlikely(!in_interrupt() && local_softirq_pending()))
175 do_softirq();
176
177 dec_preempt_count();
Tim Chen3c829c32006-07-30 03:04:02 -0700178#ifdef CONFIG_TRACE_IRQFLAGS
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200179 local_irq_enable();
Tim Chen3c829c32006-07-30 03:04:02 -0700180#endif
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700181 preempt_check_resched();
182}
Johannes Berg0f476b6d2008-06-18 09:29:37 +0200183
184void local_bh_enable(void)
185{
186 _local_bh_enable_ip((unsigned long)__builtin_return_address(0));
187}
188EXPORT_SYMBOL(local_bh_enable);
189
190void local_bh_enable_ip(unsigned long ip)
191{
192 _local_bh_enable_ip(ip);
193}
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700194EXPORT_SYMBOL(local_bh_enable_ip);
195
196/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 * We restart softirq processing MAX_SOFTIRQ_RESTART times,
198 * and we fall back to softirqd after that.
199 *
200 * This number has been established via experimentation.
201 * The two things to balance is latency against fairness -
202 * we want to handle softirqs as soon as possible, but they
203 * should not be able to lock up the box.
204 */
205#define MAX_SOFTIRQ_RESTART 10
206
207asmlinkage void __do_softirq(void)
208{
209 struct softirq_action *h;
210 __u32 pending;
211 int max_restart = MAX_SOFTIRQ_RESTART;
212 int cpu;
213
214 pending = local_softirq_pending();
Paul Mackerras829035fd2006-07-03 00:25:40 -0700215 account_system_vtime(current);
216
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700217 __local_bh_disable((unsigned long)__builtin_return_address(0),
218 SOFTIRQ_OFFSET);
Ingo Molnard820ac42009-03-13 01:30:40 +0100219 lockdep_softirq_enter();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 cpu = smp_processor_id();
222restart:
223 /* Reset the pending bitmask before enabling irqs */
Andi Kleen3f744782005-09-12 18:49:24 +0200224 set_softirq_pending(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225
Andrew Mortonc70f5d62005-07-30 10:22:49 -0700226 local_irq_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
228 h = softirq_vec;
229
230 do {
231 if (pending & 1) {
Thomas Gleixner8e85b4b2008-10-02 10:50:53 +0200232 int prev_count = preempt_count();
Keika Kobayashiaa0ce5b2009-06-17 16:25:52 -0700233 kstat_incr_softirqs_this_cpu(h - softirq_vec);
Thomas Gleixner8e85b4b2008-10-02 10:50:53 +0200234
Jason Baron39842322009-03-12 14:36:03 -0400235 trace_softirq_entry(h, softirq_vec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 h->action(h);
Jason Baron39842322009-03-12 14:36:03 -0400237 trace_softirq_exit(h, softirq_vec);
Thomas Gleixner8e85b4b2008-10-02 10:50:53 +0200238 if (unlikely(prev_count != preempt_count())) {
Jason Baron5d592b42009-03-12 14:33:36 -0400239 printk(KERN_ERR "huh, entered softirq %td %s %p"
Thomas Gleixner8e85b4b2008-10-02 10:50:53 +0200240 "with preempt_count %08x,"
241 " exited with %08x?\n", h - softirq_vec,
Jason Baron5d592b42009-03-12 14:33:36 -0400242 softirq_to_name[h - softirq_vec],
Thomas Gleixner8e85b4b2008-10-02 10:50:53 +0200243 h->action, prev_count, preempt_count());
244 preempt_count() = prev_count;
245 }
246
Paul E. McKenneyd6714c22009-08-22 13:56:46 -0700247 rcu_bh_qs(cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 }
249 h++;
250 pending >>= 1;
251 } while (pending);
252
Andrew Mortonc70f5d62005-07-30 10:22:49 -0700253 local_irq_disable();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254
255 pending = local_softirq_pending();
256 if (pending && --max_restart)
257 goto restart;
258
259 if (pending)
260 wakeup_softirqd();
261
Ingo Molnard820ac42009-03-13 01:30:40 +0100262 lockdep_softirq_exit();
Paul Mackerras829035fd2006-07-03 00:25:40 -0700263
264 account_system_vtime(current);
Venkatesh Pallipadi75e10562010-10-04 17:03:16 -0700265 __local_bh_enable(SOFTIRQ_OFFSET);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266}
267
268#ifndef __ARCH_HAS_DO_SOFTIRQ
269
270asmlinkage void do_softirq(void)
271{
272 __u32 pending;
273 unsigned long flags;
274
275 if (in_interrupt())
276 return;
277
278 local_irq_save(flags);
279
280 pending = local_softirq_pending();
281
282 if (pending)
283 __do_softirq();
284
285 local_irq_restore(flags);
286}
287
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288#endif
289
Ingo Molnardde4b2b2007-02-16 01:27:45 -0800290/*
291 * Enter an interrupt context.
292 */
293void irq_enter(void)
294{
Venki Pallipadi6378ddb2008-01-30 13:30:04 +0100295 int cpu = smp_processor_id();
Thomas Gleixner719254f2008-10-17 09:59:47 +0200296
Paul E. McKenney64db4cf2008-12-18 21:55:32 +0100297 rcu_irq_enter();
Thomas Gleixneree5f80a2008-11-07 11:06:00 +0100298 if (idle_cpu(cpu) && !in_interrupt()) {
299 __irq_enter();
Thomas Gleixner719254f2008-10-17 09:59:47 +0200300 tick_check_idle(cpu);
Thomas Gleixneree5f80a2008-11-07 11:06:00 +0100301 } else
302 __irq_enter();
Ingo Molnardde4b2b2007-02-16 01:27:45 -0800303}
304
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
306# define invoke_softirq() __do_softirq()
307#else
308# define invoke_softirq() do_softirq()
309#endif
310
311/*
312 * Exit an interrupt context. Process softirqs if needed and possible:
313 */
314void irq_exit(void)
315{
316 account_system_vtime(current);
Ingo Molnarde30a2b2006-07-03 00:24:42 -0700317 trace_hardirq_exit();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 sub_preempt_count(IRQ_EXIT_OFFSET);
319 if (!in_interrupt() && local_softirq_pending())
320 invoke_softirq();
Thomas Gleixner79bf2bb2007-02-16 01:28:03 -0800321
Lai Jiangshanc5e0cb32009-10-28 08:14:48 -0700322 rcu_irq_exit();
Thomas Gleixner79bf2bb2007-02-16 01:28:03 -0800323#ifdef CONFIG_NO_HZ
324 /* Make sure that timer wheel updates are propagated */
Paul E. McKenney64db4cf2008-12-18 21:55:32 +0100325 if (idle_cpu(smp_processor_id()) && !in_interrupt() && !need_resched())
326 tick_nohz_stop_sched_tick(0);
Thomas Gleixner79bf2bb2007-02-16 01:28:03 -0800327#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 preempt_enable_no_resched();
329}
330
331/*
332 * This function must run with irqs disabled!
333 */
Harvey Harrison7ad5b3a2008-02-08 04:19:53 -0800334inline void raise_softirq_irqoff(unsigned int nr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335{
336 __raise_softirq_irqoff(nr);
337
338 /*
339 * If we're in an interrupt or softirq, we're done
340 * (this also catches softirq-disabled code). We will
341 * actually run the softirq once we return from
342 * the irq or softirq.
343 *
344 * Otherwise we wake up ksoftirqd to make sure we
345 * schedule the softirq soon.
346 */
347 if (!in_interrupt())
348 wakeup_softirqd();
349}
350
Harvey Harrison7ad5b3a2008-02-08 04:19:53 -0800351void raise_softirq(unsigned int nr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352{
353 unsigned long flags;
354
355 local_irq_save(flags);
356 raise_softirq_irqoff(nr);
357 local_irq_restore(flags);
358}
359
Carlos R. Mafra962cf362008-05-15 11:15:37 -0300360void open_softirq(int nr, void (*action)(struct softirq_action *))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 softirq_vec[nr].action = action;
363}
364
Peter Zijlstra9ba5f002009-07-22 14:18:35 +0200365/*
366 * Tasklets
367 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368struct tasklet_head
369{
Olof Johansson48f20a92008-03-04 15:23:25 -0800370 struct tasklet_struct *head;
371 struct tasklet_struct **tail;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372};
373
Vegard Nossum4620b492008-06-12 23:21:53 +0200374static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);
375static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
Harvey Harrison7ad5b3a2008-02-08 04:19:53 -0800377void __tasklet_schedule(struct tasklet_struct *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378{
379 unsigned long flags;
380
381 local_irq_save(flags);
Olof Johansson48f20a92008-03-04 15:23:25 -0800382 t->next = NULL;
383 *__get_cpu_var(tasklet_vec).tail = t;
384 __get_cpu_var(tasklet_vec).tail = &(t->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 raise_softirq_irqoff(TASKLET_SOFTIRQ);
386 local_irq_restore(flags);
387}
388
389EXPORT_SYMBOL(__tasklet_schedule);
390
Harvey Harrison7ad5b3a2008-02-08 04:19:53 -0800391void __tasklet_hi_schedule(struct tasklet_struct *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392{
393 unsigned long flags;
394
395 local_irq_save(flags);
Olof Johansson48f20a92008-03-04 15:23:25 -0800396 t->next = NULL;
397 *__get_cpu_var(tasklet_hi_vec).tail = t;
398 __get_cpu_var(tasklet_hi_vec).tail = &(t->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 raise_softirq_irqoff(HI_SOFTIRQ);
400 local_irq_restore(flags);
401}
402
403EXPORT_SYMBOL(__tasklet_hi_schedule);
404
Vegard Nossum7c692cb2008-05-21 22:53:13 +0200405void __tasklet_hi_schedule_first(struct tasklet_struct *t)
406{
407 BUG_ON(!irqs_disabled());
408
409 t->next = __get_cpu_var(tasklet_hi_vec).head;
410 __get_cpu_var(tasklet_hi_vec).head = t;
411 __raise_softirq_irqoff(HI_SOFTIRQ);
412}
413
414EXPORT_SYMBOL(__tasklet_hi_schedule_first);
415
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416static void tasklet_action(struct softirq_action *a)
417{
418 struct tasklet_struct *list;
419
420 local_irq_disable();
Olof Johansson48f20a92008-03-04 15:23:25 -0800421 list = __get_cpu_var(tasklet_vec).head;
422 __get_cpu_var(tasklet_vec).head = NULL;
423 __get_cpu_var(tasklet_vec).tail = &__get_cpu_var(tasklet_vec).head;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 local_irq_enable();
425
426 while (list) {
427 struct tasklet_struct *t = list;
428
429 list = list->next;
430
431 if (tasklet_trylock(t)) {
432 if (!atomic_read(&t->count)) {
433 if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
434 BUG();
435 t->func(t->data);
436 tasklet_unlock(t);
437 continue;
438 }
439 tasklet_unlock(t);
440 }
441
442 local_irq_disable();
Olof Johansson48f20a92008-03-04 15:23:25 -0800443 t->next = NULL;
444 *__get_cpu_var(tasklet_vec).tail = t;
445 __get_cpu_var(tasklet_vec).tail = &(t->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 __raise_softirq_irqoff(TASKLET_SOFTIRQ);
447 local_irq_enable();
448 }
449}
450
451static void tasklet_hi_action(struct softirq_action *a)
452{
453 struct tasklet_struct *list;
454
455 local_irq_disable();
Olof Johansson48f20a92008-03-04 15:23:25 -0800456 list = __get_cpu_var(tasklet_hi_vec).head;
457 __get_cpu_var(tasklet_hi_vec).head = NULL;
458 __get_cpu_var(tasklet_hi_vec).tail = &__get_cpu_var(tasklet_hi_vec).head;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 local_irq_enable();
460
461 while (list) {
462 struct tasklet_struct *t = list;
463
464 list = list->next;
465
466 if (tasklet_trylock(t)) {
467 if (!atomic_read(&t->count)) {
468 if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
469 BUG();
470 t->func(t->data);
471 tasklet_unlock(t);
472 continue;
473 }
474 tasklet_unlock(t);
475 }
476
477 local_irq_disable();
Olof Johansson48f20a92008-03-04 15:23:25 -0800478 t->next = NULL;
479 *__get_cpu_var(tasklet_hi_vec).tail = t;
480 __get_cpu_var(tasklet_hi_vec).tail = &(t->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 __raise_softirq_irqoff(HI_SOFTIRQ);
482 local_irq_enable();
483 }
484}
485
486
487void tasklet_init(struct tasklet_struct *t,
488 void (*func)(unsigned long), unsigned long data)
489{
490 t->next = NULL;
491 t->state = 0;
492 atomic_set(&t->count, 0);
493 t->func = func;
494 t->data = data;
495}
496
497EXPORT_SYMBOL(tasklet_init);
498
499void tasklet_kill(struct tasklet_struct *t)
500{
501 if (in_interrupt())
502 printk("Attempt to kill tasklet from interrupt\n");
503
504 while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {
H Hartley Sweeten79d381c2009-04-16 19:30:18 -0400505 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 yield();
H Hartley Sweeten79d381c2009-04-16 19:30:18 -0400507 } while (test_bit(TASKLET_STATE_SCHED, &t->state));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 }
509 tasklet_unlock_wait(t);
510 clear_bit(TASKLET_STATE_SCHED, &t->state);
511}
512
513EXPORT_SYMBOL(tasklet_kill);
514
Peter Zijlstra9ba5f002009-07-22 14:18:35 +0200515/*
516 * tasklet_hrtimer
517 */
518
519/*
Peter Zijlstrab9c30322010-02-03 18:08:52 +0100520 * The trampoline is called when the hrtimer expires. It schedules a tasklet
521 * to run __tasklet_hrtimer_trampoline() which in turn will call the intended
522 * hrtimer callback, but from softirq context.
Peter Zijlstra9ba5f002009-07-22 14:18:35 +0200523 */
524static enum hrtimer_restart __hrtimer_tasklet_trampoline(struct hrtimer *timer)
525{
526 struct tasklet_hrtimer *ttimer =
527 container_of(timer, struct tasklet_hrtimer, timer);
528
Peter Zijlstrab9c30322010-02-03 18:08:52 +0100529 tasklet_hi_schedule(&ttimer->tasklet);
530 return HRTIMER_NORESTART;
Peter Zijlstra9ba5f002009-07-22 14:18:35 +0200531}
532
533/*
534 * Helper function which calls the hrtimer callback from
535 * tasklet/softirq context
536 */
537static void __tasklet_hrtimer_trampoline(unsigned long data)
538{
539 struct tasklet_hrtimer *ttimer = (void *)data;
540 enum hrtimer_restart restart;
541
542 restart = ttimer->function(&ttimer->timer);
543 if (restart != HRTIMER_NORESTART)
544 hrtimer_restart(&ttimer->timer);
545}
546
547/**
548 * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks
549 * @ttimer: tasklet_hrtimer which is initialized
550 * @function: hrtimer callback funtion which gets called from softirq context
551 * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME)
552 * @mode: hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL)
553 */
554void tasklet_hrtimer_init(struct tasklet_hrtimer *ttimer,
555 enum hrtimer_restart (*function)(struct hrtimer *),
556 clockid_t which_clock, enum hrtimer_mode mode)
557{
558 hrtimer_init(&ttimer->timer, which_clock, mode);
559 ttimer->timer.function = __hrtimer_tasklet_trampoline;
560 tasklet_init(&ttimer->tasklet, __tasklet_hrtimer_trampoline,
561 (unsigned long)ttimer);
562 ttimer->function = function;
563}
564EXPORT_SYMBOL_GPL(tasklet_hrtimer_init);
565
566/*
567 * Remote softirq bits
568 */
569
David S. Miller54514a72008-09-23 22:15:57 -0700570DEFINE_PER_CPU(struct list_head [NR_SOFTIRQS], softirq_work_list);
571EXPORT_PER_CPU_SYMBOL(softirq_work_list);
572
573static void __local_trigger(struct call_single_data *cp, int softirq)
574{
575 struct list_head *head = &__get_cpu_var(softirq_work_list[softirq]);
576
577 list_add_tail(&cp->list, head);
578
579 /* Trigger the softirq only if the list was previously empty. */
580 if (head->next == &cp->list)
581 raise_softirq_irqoff(softirq);
582}
583
584#ifdef CONFIG_USE_GENERIC_SMP_HELPERS
585static void remote_softirq_receive(void *data)
586{
587 struct call_single_data *cp = data;
588 unsigned long flags;
589 int softirq;
590
591 softirq = cp->priv;
592
593 local_irq_save(flags);
594 __local_trigger(cp, softirq);
595 local_irq_restore(flags);
596}
597
598static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
599{
600 if (cpu_online(cpu)) {
601 cp->func = remote_softirq_receive;
602 cp->info = cp;
603 cp->flags = 0;
604 cp->priv = softirq;
605
Peter Zijlstra6e275632009-02-25 13:59:48 +0100606 __smp_call_function_single(cpu, cp, 0);
David S. Miller54514a72008-09-23 22:15:57 -0700607 return 0;
608 }
609 return 1;
610}
611#else /* CONFIG_USE_GENERIC_SMP_HELPERS */
612static int __try_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
613{
614 return 1;
615}
616#endif
617
618/**
619 * __send_remote_softirq - try to schedule softirq work on a remote cpu
620 * @cp: private SMP call function data area
621 * @cpu: the remote cpu
622 * @this_cpu: the currently executing cpu
623 * @softirq: the softirq for the work
624 *
625 * Attempt to schedule softirq work on a remote cpu. If this cannot be
626 * done, the work is instead queued up on the local cpu.
627 *
628 * Interrupts must be disabled.
629 */
630void __send_remote_softirq(struct call_single_data *cp, int cpu, int this_cpu, int softirq)
631{
632 if (cpu == this_cpu || __try_remote_softirq(cp, cpu, softirq))
633 __local_trigger(cp, softirq);
634}
635EXPORT_SYMBOL(__send_remote_softirq);
636
637/**
638 * send_remote_softirq - try to schedule softirq work on a remote cpu
639 * @cp: private SMP call function data area
640 * @cpu: the remote cpu
641 * @softirq: the softirq for the work
642 *
643 * Like __send_remote_softirq except that disabling interrupts and
644 * computing the current cpu is done for the caller.
645 */
646void send_remote_softirq(struct call_single_data *cp, int cpu, int softirq)
647{
648 unsigned long flags;
649 int this_cpu;
650
651 local_irq_save(flags);
652 this_cpu = smp_processor_id();
653 __send_remote_softirq(cp, cpu, this_cpu, softirq);
654 local_irq_restore(flags);
655}
656EXPORT_SYMBOL(send_remote_softirq);
657
658static int __cpuinit remote_softirq_cpu_notify(struct notifier_block *self,
659 unsigned long action, void *hcpu)
660{
661 /*
662 * If a CPU goes away, splice its entries to the current CPU
663 * and trigger a run of the softirq
664 */
665 if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
666 int cpu = (unsigned long) hcpu;
667 int i;
668
669 local_irq_disable();
670 for (i = 0; i < NR_SOFTIRQS; i++) {
671 struct list_head *head = &per_cpu(softirq_work_list[i], cpu);
672 struct list_head *local_head;
673
674 if (list_empty(head))
675 continue;
676
677 local_head = &__get_cpu_var(softirq_work_list[i]);
678 list_splice_init(head, local_head);
679 raise_softirq_irqoff(i);
680 }
681 local_irq_enable();
682 }
683
684 return NOTIFY_OK;
685}
686
687static struct notifier_block __cpuinitdata remote_softirq_cpu_notifier = {
688 .notifier_call = remote_softirq_cpu_notify,
689};
690
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691void __init softirq_init(void)
692{
Olof Johansson48f20a92008-03-04 15:23:25 -0800693 int cpu;
694
695 for_each_possible_cpu(cpu) {
David S. Miller54514a72008-09-23 22:15:57 -0700696 int i;
697
Olof Johansson48f20a92008-03-04 15:23:25 -0800698 per_cpu(tasklet_vec, cpu).tail =
699 &per_cpu(tasklet_vec, cpu).head;
700 per_cpu(tasklet_hi_vec, cpu).tail =
701 &per_cpu(tasklet_hi_vec, cpu).head;
David S. Miller54514a72008-09-23 22:15:57 -0700702 for (i = 0; i < NR_SOFTIRQS; i++)
703 INIT_LIST_HEAD(&per_cpu(softirq_work_list[i], cpu));
Olof Johansson48f20a92008-03-04 15:23:25 -0800704 }
705
David S. Miller54514a72008-09-23 22:15:57 -0700706 register_hotcpu_notifier(&remote_softirq_cpu_notifier);
707
Carlos R. Mafra962cf362008-05-15 11:15:37 -0300708 open_softirq(TASKLET_SOFTIRQ, tasklet_action);
709 open_softirq(HI_SOFTIRQ, tasklet_hi_action);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710}
711
Tejun Heo1871e522009-10-29 22:34:13 +0900712static int run_ksoftirqd(void * __bind_cpu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 set_current_state(TASK_INTERRUPTIBLE);
715
716 while (!kthread_should_stop()) {
717 preempt_disable();
718 if (!local_softirq_pending()) {
719 preempt_enable_no_resched();
720 schedule();
721 preempt_disable();
722 }
723
724 __set_current_state(TASK_RUNNING);
725
726 while (local_softirq_pending()) {
727 /* Preempt disable stops cpu going offline.
728 If already offline, we'll be on wrong CPU:
729 don't process */
730 if (cpu_is_offline((long)__bind_cpu))
731 goto wait_to_die;
732 do_softirq();
733 preempt_enable_no_resched();
734 cond_resched();
735 preempt_disable();
Paul E. McKenney25502a62010-04-01 17:37:01 -0700736 rcu_note_context_switch((long)__bind_cpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 }
738 preempt_enable();
739 set_current_state(TASK_INTERRUPTIBLE);
740 }
741 __set_current_state(TASK_RUNNING);
742 return 0;
743
744wait_to_die:
745 preempt_enable();
746 /* Wait for kthread_stop */
747 set_current_state(TASK_INTERRUPTIBLE);
748 while (!kthread_should_stop()) {
749 schedule();
750 set_current_state(TASK_INTERRUPTIBLE);
751 }
752 __set_current_state(TASK_RUNNING);
753 return 0;
754}
755
756#ifdef CONFIG_HOTPLUG_CPU
757/*
758 * tasklet_kill_immediate is called to remove a tasklet which can already be
759 * scheduled for execution on @cpu.
760 *
761 * Unlike tasklet_kill, this function removes the tasklet
762 * _immediately_, even if the tasklet is in TASKLET_STATE_SCHED state.
763 *
764 * When this function is called, @cpu must be in the CPU_DEAD state.
765 */
766void tasklet_kill_immediate(struct tasklet_struct *t, unsigned int cpu)
767{
768 struct tasklet_struct **i;
769
770 BUG_ON(cpu_online(cpu));
771 BUG_ON(test_bit(TASKLET_STATE_RUN, &t->state));
772
773 if (!test_bit(TASKLET_STATE_SCHED, &t->state))
774 return;
775
776 /* CPU is dead, so no lock needed. */
Olof Johansson48f20a92008-03-04 15:23:25 -0800777 for (i = &per_cpu(tasklet_vec, cpu).head; *i; i = &(*i)->next) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 if (*i == t) {
779 *i = t->next;
Olof Johansson48f20a92008-03-04 15:23:25 -0800780 /* If this was the tail element, move the tail ptr */
781 if (*i == NULL)
782 per_cpu(tasklet_vec, cpu).tail = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783 return;
784 }
785 }
786 BUG();
787}
788
789static void takeover_tasklets(unsigned int cpu)
790{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 /* CPU is dead, so no lock needed. */
792 local_irq_disable();
793
794 /* Find end, append list for that CPU. */
Christian Borntraegere5e41722008-05-01 04:34:23 -0700795 if (&per_cpu(tasklet_vec, cpu).head != per_cpu(tasklet_vec, cpu).tail) {
796 *(__get_cpu_var(tasklet_vec).tail) = per_cpu(tasklet_vec, cpu).head;
797 __get_cpu_var(tasklet_vec).tail = per_cpu(tasklet_vec, cpu).tail;
798 per_cpu(tasklet_vec, cpu).head = NULL;
799 per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head;
800 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 raise_softirq_irqoff(TASKLET_SOFTIRQ);
802
Christian Borntraegere5e41722008-05-01 04:34:23 -0700803 if (&per_cpu(tasklet_hi_vec, cpu).head != per_cpu(tasklet_hi_vec, cpu).tail) {
804 *__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).head;
805 __get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).tail;
806 per_cpu(tasklet_hi_vec, cpu).head = NULL;
807 per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head;
808 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 raise_softirq_irqoff(HI_SOFTIRQ);
810
811 local_irq_enable();
812}
813#endif /* CONFIG_HOTPLUG_CPU */
814
Chandra Seetharaman8c78f302006-07-30 03:03:35 -0700815static int __cpuinit cpu_callback(struct notifier_block *nfb,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 unsigned long action,
817 void *hcpu)
818{
819 int hotcpu = (unsigned long)hcpu;
820 struct task_struct *p;
821
822 switch (action) {
823 case CPU_UP_PREPARE:
Rafael J. Wysocki8bb78442007-05-09 02:35:10 -0700824 case CPU_UP_PREPARE_FROZEN:
Tejun Heo1871e522009-10-29 22:34:13 +0900825 p = kthread_create(run_ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 if (IS_ERR(p)) {
827 printk("ksoftirqd for %i failed\n", hotcpu);
Akinobu Mita80b51842010-05-26 14:43:32 -0700828 return notifier_from_errno(PTR_ERR(p));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 }
830 kthread_bind(p, hotcpu);
831 per_cpu(ksoftirqd, hotcpu) = p;
832 break;
833 case CPU_ONLINE:
Rafael J. Wysocki8bb78442007-05-09 02:35:10 -0700834 case CPU_ONLINE_FROZEN:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 wake_up_process(per_cpu(ksoftirqd, hotcpu));
836 break;
837#ifdef CONFIG_HOTPLUG_CPU
838 case CPU_UP_CANCELED:
Rafael J. Wysocki8bb78442007-05-09 02:35:10 -0700839 case CPU_UP_CANCELED_FROZEN:
Heiko Carstensfc75cdf2006-06-25 05:49:10 -0700840 if (!per_cpu(ksoftirqd, hotcpu))
841 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 /* Unbind so it can run. Fall thru. */
Heiko Carstensa4c4af72005-11-07 00:58:38 -0800843 kthread_bind(per_cpu(ksoftirqd, hotcpu),
Rusty Russellf1fc0572009-01-01 10:12:23 +1030844 cpumask_any(cpu_online_mask));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 case CPU_DEAD:
Satoru Takeuchi1c6b4aa2007-07-15 23:39:48 -0700846 case CPU_DEAD_FROZEN: {
847 struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
848
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 p = per_cpu(ksoftirqd, hotcpu);
850 per_cpu(ksoftirqd, hotcpu) = NULL;
Rusty Russell961ccdd2008-06-23 13:55:38 +1000851 sched_setscheduler_nocheck(p, SCHED_FIFO, &param);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 kthread_stop(p);
853 takeover_tasklets(hotcpu);
854 break;
Satoru Takeuchi1c6b4aa2007-07-15 23:39:48 -0700855 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856#endif /* CONFIG_HOTPLUG_CPU */
857 }
858 return NOTIFY_OK;
859}
860
Chandra Seetharaman8c78f302006-07-30 03:03:35 -0700861static struct notifier_block __cpuinitdata cpu_nfb = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 .notifier_call = cpu_callback
863};
864
Eduard - Gabriel Munteanu7babe8d2008-07-25 19:45:11 -0700865static __init int spawn_ksoftirqd(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866{
867 void *cpu = (void *)(long)smp_processor_id();
Akinobu Mita07dccf32006-09-29 02:00:22 -0700868 int err = cpu_callback(&cpu_nfb, CPU_UP_PREPARE, cpu);
869
Akinobu Mita9e506f72010-06-04 14:15:04 -0700870 BUG_ON(err != NOTIFY_OK);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 cpu_callback(&cpu_nfb, CPU_ONLINE, cpu);
872 register_cpu_notifier(&cpu_nfb);
873 return 0;
874}
Eduard - Gabriel Munteanu7babe8d2008-07-25 19:45:11 -0700875early_initcall(spawn_ksoftirqd);
Andrew Morton78eef012006-03-22 00:08:16 -0800876
877#ifdef CONFIG_SMP
878/*
879 * Call a function on all processors
880 */
Jens Axboe15c8b6c2008-05-09 09:39:44 +0200881int on_each_cpu(void (*func) (void *info), void *info, int wait)
Andrew Morton78eef012006-03-22 00:08:16 -0800882{
883 int ret = 0;
884
885 preempt_disable();
Jens Axboe8691e5a2008-06-06 11:18:06 +0200886 ret = smp_call_function(func, info, wait);
Andrew Morton78eef012006-03-22 00:08:16 -0800887 local_irq_disable();
888 func(info);
889 local_irq_enable();
890 preempt_enable();
891 return ret;
892}
893EXPORT_SYMBOL(on_each_cpu);
894#endif
Yinghai Lu43a25632008-12-28 16:01:13 -0800895
896/*
897 * [ These __weak aliases are kept in a separate compilation unit, so that
898 * GCC does not inline them incorrectly. ]
899 */
900
901int __init __weak early_irq_init(void)
902{
903 return 0;
904}
905
Yinghai Lu4a046d12009-01-12 17:39:24 -0800906int __init __weak arch_probe_nr_irqs(void)
907{
908 return 0;
909}
910
Yinghai Lu43a25632008-12-28 16:01:13 -0800911int __init __weak arch_early_irq_init(void)
912{
913 return 0;
914}
915
Yinghai Lu85ac16d2009-04-27 18:00:38 -0700916int __weak arch_init_chip_data(struct irq_desc *desc, int node)
Yinghai Lu43a25632008-12-28 16:01:13 -0800917{
918 return 0;
919}