diff options
Diffstat (limited to 'kernel/softirq.c')
-rw-r--r-- | kernel/softirq.c | 195 |
1 files changed, 113 insertions, 82 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c index 07b4f1b1a73a..fca82c32042b 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -54,11 +54,11 @@ EXPORT_SYMBOL(irq_stat); | |||
54 | 54 | ||
55 | static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp; | 55 | static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp; |
56 | 56 | ||
57 | static DEFINE_PER_CPU(struct task_struct *, ksoftirqd); | 57 | DEFINE_PER_CPU(struct task_struct *, ksoftirqd); |
58 | 58 | ||
59 | char *softirq_to_name[NR_SOFTIRQS] = { | 59 | char *softirq_to_name[NR_SOFTIRQS] = { |
60 | "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL", | 60 | "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL", |
61 | "TASKLET", "SCHED", "HRTIMER", "RCU" | 61 | "TASKLET", "SCHED", "HRTIMER", "RCU" |
62 | }; | 62 | }; |
63 | 63 | ||
64 | /* | 64 | /* |
@@ -67,21 +67,31 @@ char *softirq_to_name[NR_SOFTIRQS] = { | |||
67 | * to the pending events, so lets the scheduler to balance | 67 | * to the pending events, so lets the scheduler to balance |
68 | * the softirq load for us. | 68 | * the softirq load for us. |
69 | */ | 69 | */ |
70 | void wakeup_softirqd(void) | 70 | static void wakeup_softirqd(void) |
71 | { | 71 | { |
72 | /* Interrupts are disabled: no need to stop preemption */ | 72 | /* Interrupts are disabled: no need to stop preemption */ |
73 | struct task_struct *tsk = __get_cpu_var(ksoftirqd); | 73 | struct task_struct *tsk = __this_cpu_read(ksoftirqd); |
74 | 74 | ||
75 | if (tsk && tsk->state != TASK_RUNNING) | 75 | if (tsk && tsk->state != TASK_RUNNING) |
76 | wake_up_process(tsk); | 76 | wake_up_process(tsk); |
77 | } | 77 | } |
78 | 78 | ||
79 | /* | 79 | /* |
80 | * 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 | /* | ||
80 | * This one is for softirq.c-internal use, | 90 | * This one is for softirq.c-internal use, |
81 | * where hardirqs are disabled legitimately: | 91 | * where hardirqs are disabled legitimately: |
82 | */ | 92 | */ |
83 | #ifdef CONFIG_TRACE_IRQFLAGS | 93 | #ifdef CONFIG_TRACE_IRQFLAGS |
84 | static void __local_bh_disable(unsigned long ip) | 94 | static void __local_bh_disable(unsigned long ip, unsigned int cnt) |
85 | { | 95 | { |
86 | unsigned long flags; | 96 | unsigned long flags; |
87 | 97 | ||
@@ -95,32 +105,43 @@ static void __local_bh_disable(unsigned long ip) | |||
95 | * We must manually increment preempt_count here and manually | 105 | * We must manually increment preempt_count here and manually |
96 | * call the trace_preempt_off later. | 106 | * call the trace_preempt_off later. |
97 | */ | 107 | */ |
98 | preempt_count() += SOFTIRQ_OFFSET; | 108 | preempt_count() += cnt; |
99 | /* | 109 | /* |
100 | * Were softirqs turned off above: | 110 | * Were softirqs turned off above: |
101 | */ | 111 | */ |
102 | if (softirq_count() == SOFTIRQ_OFFSET) | 112 | if (softirq_count() == cnt) |
103 | trace_softirqs_off(ip); | 113 | trace_softirqs_off(ip); |
104 | raw_local_irq_restore(flags); | 114 | raw_local_irq_restore(flags); |
105 | 115 | ||
106 | if (preempt_count() == SOFTIRQ_OFFSET) | 116 | if (preempt_count() == cnt) |
107 | trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); | 117 | trace_preempt_off(CALLER_ADDR0, get_parent_ip(CALLER_ADDR1)); |
108 | } | 118 | } |
109 | #else /* !CONFIG_TRACE_IRQFLAGS */ | 119 | #else /* !CONFIG_TRACE_IRQFLAGS */ |
110 | static inline void __local_bh_disable(unsigned long ip) | 120 | static inline void __local_bh_disable(unsigned long ip, unsigned int cnt) |
111 | { | 121 | { |
112 | add_preempt_count(SOFTIRQ_OFFSET); | 122 | add_preempt_count(cnt); |
113 | barrier(); | 123 | barrier(); |
114 | } | 124 | } |
115 | #endif /* CONFIG_TRACE_IRQFLAGS */ | 125 | #endif /* CONFIG_TRACE_IRQFLAGS */ |
116 | 126 | ||
117 | void local_bh_disable(void) | 127 | void local_bh_disable(void) |
118 | { | 128 | { |
119 | __local_bh_disable((unsigned long)__builtin_return_address(0)); | 129 | __local_bh_disable((unsigned long)__builtin_return_address(0), |
130 | SOFTIRQ_DISABLE_OFFSET); | ||
120 | } | 131 | } |
121 | 132 | ||
122 | EXPORT_SYMBOL(local_bh_disable); | 133 | EXPORT_SYMBOL(local_bh_disable); |
123 | 134 | ||
135 | static 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 | |||
124 | /* | 145 | /* |
125 | * Special-case - softirqs can safely be enabled in | 146 | * Special-case - softirqs can safely be enabled in |
126 | * cond_resched_softirq(), or by __do_softirq(), | 147 | * cond_resched_softirq(), or by __do_softirq(), |
@@ -128,12 +149,7 @@ EXPORT_SYMBOL(local_bh_disable); | |||
128 | */ | 149 | */ |
129 | void _local_bh_enable(void) | 150 | void _local_bh_enable(void) |
130 | { | 151 | { |
131 | WARN_ON_ONCE(in_irq()); | 152 | __local_bh_enable(SOFTIRQ_DISABLE_OFFSET); |
132 | WARN_ON_ONCE(!irqs_disabled()); | ||
133 | |||
134 | if (softirq_count() == SOFTIRQ_OFFSET) | ||
135 | trace_softirqs_on((unsigned long)__builtin_return_address(0)); | ||
136 | sub_preempt_count(SOFTIRQ_OFFSET); | ||
137 | } | 153 | } |
138 | 154 | ||
139 | EXPORT_SYMBOL(_local_bh_enable); | 155 | EXPORT_SYMBOL(_local_bh_enable); |
@@ -147,13 +163,13 @@ static inline void _local_bh_enable_ip(unsigned long ip) | |||
147 | /* | 163 | /* |
148 | * Are softirqs going to be turned on now: | 164 | * Are softirqs going to be turned on now: |
149 | */ | 165 | */ |
150 | if (softirq_count() == SOFTIRQ_OFFSET) | 166 | if (softirq_count() == SOFTIRQ_DISABLE_OFFSET) |
151 | trace_softirqs_on(ip); | 167 | trace_softirqs_on(ip); |
152 | /* | 168 | /* |
153 | * Keep preemption disabled until we are done with | 169 | * Keep preemption disabled until we are done with |
154 | * softirq processing: | 170 | * softirq processing: |
155 | */ | 171 | */ |
156 | sub_preempt_count(SOFTIRQ_OFFSET - 1); | 172 | sub_preempt_count(SOFTIRQ_DISABLE_OFFSET - 1); |
157 | 173 | ||
158 | if (unlikely(!in_interrupt() && local_softirq_pending())) | 174 | if (unlikely(!in_interrupt() && local_softirq_pending())) |
159 | do_softirq(); | 175 | do_softirq(); |
@@ -198,7 +214,8 @@ asmlinkage void __do_softirq(void) | |||
198 | pending = local_softirq_pending(); | 214 | pending = local_softirq_pending(); |
199 | account_system_vtime(current); | 215 | account_system_vtime(current); |
200 | 216 | ||
201 | __local_bh_disable((unsigned long)__builtin_return_address(0)); | 217 | __local_bh_disable((unsigned long)__builtin_return_address(0), |
218 | SOFTIRQ_OFFSET); | ||
202 | lockdep_softirq_enter(); | 219 | lockdep_softirq_enter(); |
203 | 220 | ||
204 | cpu = smp_processor_id(); | 221 | cpu = smp_processor_id(); |
@@ -212,18 +229,20 @@ restart: | |||
212 | 229 | ||
213 | do { | 230 | do { |
214 | if (pending & 1) { | 231 | if (pending & 1) { |
232 | unsigned int vec_nr = h - softirq_vec; | ||
215 | int prev_count = preempt_count(); | 233 | int prev_count = preempt_count(); |
216 | kstat_incr_softirqs_this_cpu(h - softirq_vec); | ||
217 | 234 | ||
218 | trace_softirq_entry(h, softirq_vec); | 235 | kstat_incr_softirqs_this_cpu(vec_nr); |
236 | |||
237 | trace_softirq_entry(vec_nr); | ||
219 | h->action(h); | 238 | h->action(h); |
220 | trace_softirq_exit(h, softirq_vec); | 239 | trace_softirq_exit(vec_nr); |
221 | if (unlikely(prev_count != preempt_count())) { | 240 | if (unlikely(prev_count != preempt_count())) { |
222 | printk(KERN_ERR "huh, entered softirq %td %s %p" | 241 | printk(KERN_ERR "huh, entered softirq %u %s %p" |
223 | "with preempt_count %08x," | 242 | "with preempt_count %08x," |
224 | " exited with %08x?\n", h - softirq_vec, | 243 | " exited with %08x?\n", vec_nr, |
225 | softirq_to_name[h - softirq_vec], | 244 | softirq_to_name[vec_nr], h->action, |
226 | h->action, prev_count, preempt_count()); | 245 | prev_count, preempt_count()); |
227 | preempt_count() = prev_count; | 246 | preempt_count() = prev_count; |
228 | } | 247 | } |
229 | 248 | ||
@@ -245,7 +264,7 @@ restart: | |||
245 | lockdep_softirq_exit(); | 264 | lockdep_softirq_exit(); |
246 | 265 | ||
247 | account_system_vtime(current); | 266 | account_system_vtime(current); |
248 | _local_bh_enable(); | 267 | __local_bh_enable(SOFTIRQ_OFFSET); |
249 | } | 268 | } |
250 | 269 | ||
251 | #ifndef __ARCH_HAS_DO_SOFTIRQ | 270 | #ifndef __ARCH_HAS_DO_SOFTIRQ |
@@ -279,16 +298,42 @@ void irq_enter(void) | |||
279 | 298 | ||
280 | rcu_irq_enter(); | 299 | rcu_irq_enter(); |
281 | if (idle_cpu(cpu) && !in_interrupt()) { | 300 | if (idle_cpu(cpu) && !in_interrupt()) { |
282 | __irq_enter(); | 301 | /* |
302 | * Prevent raise_softirq from needlessly waking up ksoftirqd | ||
303 | * here, as softirq will be serviced on return from interrupt. | ||
304 | */ | ||
305 | local_bh_disable(); | ||
283 | tick_check_idle(cpu); | 306 | tick_check_idle(cpu); |
284 | } else | 307 | _local_bh_enable(); |
285 | __irq_enter(); | 308 | } |
309 | |||
310 | __irq_enter(); | ||
286 | } | 311 | } |
287 | 312 | ||
288 | #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED | 313 | #ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED |
289 | # define invoke_softirq() __do_softirq() | 314 | static inline void invoke_softirq(void) |
315 | { | ||
316 | if (!force_irqthreads) | ||
317 | __do_softirq(); | ||
318 | else { | ||
319 | __local_bh_disable((unsigned long)__builtin_return_address(0), | ||
320 | SOFTIRQ_OFFSET); | ||
321 | wakeup_softirqd(); | ||
322 | __local_bh_enable(SOFTIRQ_OFFSET); | ||
323 | } | ||
324 | } | ||
290 | #else | 325 | #else |
291 | # define invoke_softirq() do_softirq() | 326 | static inline void invoke_softirq(void) |
327 | { | ||
328 | if (!force_irqthreads) | ||
329 | do_softirq(); | ||
330 | else { | ||
331 | __local_bh_disable((unsigned long)__builtin_return_address(0), | ||
332 | SOFTIRQ_OFFSET); | ||
333 | wakeup_softirqd(); | ||
334 | __local_bh_enable(SOFTIRQ_OFFSET); | ||
335 | } | ||
336 | } | ||
292 | #endif | 337 | #endif |
293 | 338 | ||
294 | /* | 339 | /* |
@@ -363,8 +408,8 @@ void __tasklet_schedule(struct tasklet_struct *t) | |||
363 | 408 | ||
364 | local_irq_save(flags); | 409 | local_irq_save(flags); |
365 | t->next = NULL; | 410 | t->next = NULL; |
366 | *__get_cpu_var(tasklet_vec).tail = t; | 411 | *__this_cpu_read(tasklet_vec.tail) = t; |
367 | __get_cpu_var(tasklet_vec).tail = &(t->next); | 412 | __this_cpu_write(tasklet_vec.tail, &(t->next)); |
368 | raise_softirq_irqoff(TASKLET_SOFTIRQ); | 413 | raise_softirq_irqoff(TASKLET_SOFTIRQ); |
369 | local_irq_restore(flags); | 414 | local_irq_restore(flags); |
370 | } | 415 | } |
@@ -377,8 +422,8 @@ void __tasklet_hi_schedule(struct tasklet_struct *t) | |||
377 | 422 | ||
378 | local_irq_save(flags); | 423 | local_irq_save(flags); |
379 | t->next = NULL; | 424 | t->next = NULL; |
380 | *__get_cpu_var(tasklet_hi_vec).tail = t; | 425 | *__this_cpu_read(tasklet_hi_vec.tail) = t; |
381 | __get_cpu_var(tasklet_hi_vec).tail = &(t->next); | 426 | __this_cpu_write(tasklet_hi_vec.tail, &(t->next)); |
382 | raise_softirq_irqoff(HI_SOFTIRQ); | 427 | raise_softirq_irqoff(HI_SOFTIRQ); |
383 | local_irq_restore(flags); | 428 | local_irq_restore(flags); |
384 | } | 429 | } |
@@ -389,8 +434,8 @@ void __tasklet_hi_schedule_first(struct tasklet_struct *t) | |||
389 | { | 434 | { |
390 | BUG_ON(!irqs_disabled()); | 435 | BUG_ON(!irqs_disabled()); |
391 | 436 | ||
392 | t->next = __get_cpu_var(tasklet_hi_vec).head; | 437 | t->next = __this_cpu_read(tasklet_hi_vec.head); |
393 | __get_cpu_var(tasklet_hi_vec).head = t; | 438 | __this_cpu_write(tasklet_hi_vec.head, t); |
394 | __raise_softirq_irqoff(HI_SOFTIRQ); | 439 | __raise_softirq_irqoff(HI_SOFTIRQ); |
395 | } | 440 | } |
396 | 441 | ||
@@ -401,9 +446,9 @@ static void tasklet_action(struct softirq_action *a) | |||
401 | struct tasklet_struct *list; | 446 | struct tasklet_struct *list; |
402 | 447 | ||
403 | local_irq_disable(); | 448 | local_irq_disable(); |
404 | list = __get_cpu_var(tasklet_vec).head; | 449 | list = __this_cpu_read(tasklet_vec.head); |
405 | __get_cpu_var(tasklet_vec).head = NULL; | 450 | __this_cpu_write(tasklet_vec.head, NULL); |
406 | __get_cpu_var(tasklet_vec).tail = &__get_cpu_var(tasklet_vec).head; | 451 | __this_cpu_write(tasklet_vec.tail, &__get_cpu_var(tasklet_vec).head); |
407 | local_irq_enable(); | 452 | local_irq_enable(); |
408 | 453 | ||
409 | while (list) { | 454 | while (list) { |
@@ -424,8 +469,8 @@ static void tasklet_action(struct softirq_action *a) | |||
424 | 469 | ||
425 | local_irq_disable(); | 470 | local_irq_disable(); |
426 | t->next = NULL; | 471 | t->next = NULL; |
427 | *__get_cpu_var(tasklet_vec).tail = t; | 472 | *__this_cpu_read(tasklet_vec.tail) = t; |
428 | __get_cpu_var(tasklet_vec).tail = &(t->next); | 473 | __this_cpu_write(tasklet_vec.tail, &(t->next)); |
429 | __raise_softirq_irqoff(TASKLET_SOFTIRQ); | 474 | __raise_softirq_irqoff(TASKLET_SOFTIRQ); |
430 | local_irq_enable(); | 475 | local_irq_enable(); |
431 | } | 476 | } |
@@ -436,9 +481,9 @@ static void tasklet_hi_action(struct softirq_action *a) | |||
436 | struct tasklet_struct *list; | 481 | struct tasklet_struct *list; |
437 | 482 | ||
438 | local_irq_disable(); | 483 | local_irq_disable(); |
439 | list = __get_cpu_var(tasklet_hi_vec).head; | 484 | list = __this_cpu_read(tasklet_hi_vec.head); |
440 | __get_cpu_var(tasklet_hi_vec).head = NULL; | 485 | __this_cpu_write(tasklet_hi_vec.head, NULL); |
441 | __get_cpu_var(tasklet_hi_vec).tail = &__get_cpu_var(tasklet_hi_vec).head; | 486 | __this_cpu_write(tasklet_hi_vec.tail, &__get_cpu_var(tasklet_hi_vec).head); |
442 | local_irq_enable(); | 487 | local_irq_enable(); |
443 | 488 | ||
444 | while (list) { | 489 | while (list) { |
@@ -459,8 +504,8 @@ static void tasklet_hi_action(struct softirq_action *a) | |||
459 | 504 | ||
460 | local_irq_disable(); | 505 | local_irq_disable(); |
461 | t->next = NULL; | 506 | t->next = NULL; |
462 | *__get_cpu_var(tasklet_hi_vec).tail = t; | 507 | *__this_cpu_read(tasklet_hi_vec.tail) = t; |
463 | __get_cpu_var(tasklet_hi_vec).tail = &(t->next); | 508 | __this_cpu_write(tasklet_hi_vec.tail, &(t->next)); |
464 | __raise_softirq_irqoff(HI_SOFTIRQ); | 509 | __raise_softirq_irqoff(HI_SOFTIRQ); |
465 | local_irq_enable(); | 510 | local_irq_enable(); |
466 | } | 511 | } |
@@ -530,7 +575,7 @@ static void __tasklet_hrtimer_trampoline(unsigned long data) | |||
530 | /** | 575 | /** |
531 | * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks | 576 | * tasklet_hrtimer_init - Init a tasklet/hrtimer combo for softirq callbacks |
532 | * @ttimer: tasklet_hrtimer which is initialized | 577 | * @ttimer: tasklet_hrtimer which is initialized |
533 | * @function: hrtimer callback funtion which gets called from softirq context | 578 | * @function: hrtimer callback function which gets called from softirq context |
534 | * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME) | 579 | * @which_clock: clock id (CLOCK_MONOTONIC/CLOCK_REALTIME) |
535 | * @mode: hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL) | 580 | * @mode: hrtimer mode (HRTIMER_MODE_ABS/HRTIMER_MODE_REL) |
536 | */ | 581 | */ |
@@ -712,7 +757,10 @@ static int run_ksoftirqd(void * __bind_cpu) | |||
712 | don't process */ | 757 | don't process */ |
713 | if (cpu_is_offline((long)__bind_cpu)) | 758 | if (cpu_is_offline((long)__bind_cpu)) |
714 | goto wait_to_die; | 759 | goto wait_to_die; |
715 | do_softirq(); | 760 | local_irq_disable(); |
761 | if (local_softirq_pending()) | ||
762 | __do_softirq(); | ||
763 | local_irq_enable(); | ||
716 | preempt_enable_no_resched(); | 764 | preempt_enable_no_resched(); |
717 | cond_resched(); | 765 | cond_resched(); |
718 | preempt_disable(); | 766 | preempt_disable(); |
@@ -776,16 +824,16 @@ static void takeover_tasklets(unsigned int cpu) | |||
776 | 824 | ||
777 | /* Find end, append list for that CPU. */ | 825 | /* Find end, append list for that CPU. */ |
778 | if (&per_cpu(tasklet_vec, cpu).head != per_cpu(tasklet_vec, cpu).tail) { | 826 | if (&per_cpu(tasklet_vec, cpu).head != per_cpu(tasklet_vec, cpu).tail) { |
779 | *(__get_cpu_var(tasklet_vec).tail) = per_cpu(tasklet_vec, cpu).head; | 827 | *__this_cpu_read(tasklet_vec.tail) = per_cpu(tasklet_vec, cpu).head; |
780 | __get_cpu_var(tasklet_vec).tail = per_cpu(tasklet_vec, cpu).tail; | 828 | this_cpu_write(tasklet_vec.tail, per_cpu(tasklet_vec, cpu).tail); |
781 | per_cpu(tasklet_vec, cpu).head = NULL; | 829 | per_cpu(tasklet_vec, cpu).head = NULL; |
782 | per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head; | 830 | per_cpu(tasklet_vec, cpu).tail = &per_cpu(tasklet_vec, cpu).head; |
783 | } | 831 | } |
784 | raise_softirq_irqoff(TASKLET_SOFTIRQ); | 832 | raise_softirq_irqoff(TASKLET_SOFTIRQ); |
785 | 833 | ||
786 | if (&per_cpu(tasklet_hi_vec, cpu).head != per_cpu(tasklet_hi_vec, cpu).tail) { | 834 | if (&per_cpu(tasklet_hi_vec, cpu).head != per_cpu(tasklet_hi_vec, cpu).tail) { |
787 | *__get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).head; | 835 | *__this_cpu_read(tasklet_hi_vec.tail) = per_cpu(tasklet_hi_vec, cpu).head; |
788 | __get_cpu_var(tasklet_hi_vec).tail = per_cpu(tasklet_hi_vec, cpu).tail; | 836 | __this_cpu_write(tasklet_hi_vec.tail, per_cpu(tasklet_hi_vec, cpu).tail); |
789 | per_cpu(tasklet_hi_vec, cpu).head = NULL; | 837 | per_cpu(tasklet_hi_vec, cpu).head = NULL; |
790 | per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head; | 838 | per_cpu(tasklet_hi_vec, cpu).tail = &per_cpu(tasklet_hi_vec, cpu).head; |
791 | } | 839 | } |
@@ -805,7 +853,10 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb, | |||
805 | switch (action) { | 853 | switch (action) { |
806 | case CPU_UP_PREPARE: | 854 | case CPU_UP_PREPARE: |
807 | case CPU_UP_PREPARE_FROZEN: | 855 | case CPU_UP_PREPARE_FROZEN: |
808 | p = kthread_create(run_ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu); | 856 | p = kthread_create_on_node(run_ksoftirqd, |
857 | hcpu, | ||
858 | cpu_to_node(hotcpu), | ||
859 | "ksoftirqd/%d", hotcpu); | ||
809 | if (IS_ERR(p)) { | 860 | if (IS_ERR(p)) { |
810 | printk("ksoftirqd for %i failed\n", hotcpu); | 861 | printk("ksoftirqd for %i failed\n", hotcpu); |
811 | return notifier_from_errno(PTR_ERR(p)); | 862 | return notifier_from_errno(PTR_ERR(p)); |
@@ -827,7 +878,9 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb, | |||
827 | cpumask_any(cpu_online_mask)); | 878 | cpumask_any(cpu_online_mask)); |
828 | case CPU_DEAD: | 879 | case CPU_DEAD: |
829 | case CPU_DEAD_FROZEN: { | 880 | case CPU_DEAD_FROZEN: { |
830 | struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; | 881 | static const struct sched_param param = { |
882 | .sched_priority = MAX_RT_PRIO-1 | ||
883 | }; | ||
831 | 884 | ||
832 | p = per_cpu(ksoftirqd, hotcpu); | 885 | p = per_cpu(ksoftirqd, hotcpu); |
833 | per_cpu(ksoftirqd, hotcpu) = NULL; | 886 | per_cpu(ksoftirqd, hotcpu) = NULL; |
@@ -857,25 +910,6 @@ static __init int spawn_ksoftirqd(void) | |||
857 | } | 910 | } |
858 | early_initcall(spawn_ksoftirqd); | 911 | early_initcall(spawn_ksoftirqd); |
859 | 912 | ||
860 | #ifdef CONFIG_SMP | ||
861 | /* | ||
862 | * Call a function on all processors | ||
863 | */ | ||
864 | int on_each_cpu(void (*func) (void *info), void *info, int wait) | ||
865 | { | ||
866 | int ret = 0; | ||
867 | |||
868 | preempt_disable(); | ||
869 | ret = smp_call_function(func, info, wait); | ||
870 | local_irq_disable(); | ||
871 | func(info); | ||
872 | local_irq_enable(); | ||
873 | preempt_enable(); | ||
874 | return ret; | ||
875 | } | ||
876 | EXPORT_SYMBOL(on_each_cpu); | ||
877 | #endif | ||
878 | |||
879 | /* | 913 | /* |
880 | * [ These __weak aliases are kept in a separate compilation unit, so that | 914 | * [ These __weak aliases are kept in a separate compilation unit, so that |
881 | * GCC does not inline them incorrectly. ] | 915 | * GCC does not inline them incorrectly. ] |
@@ -886,17 +920,14 @@ int __init __weak early_irq_init(void) | |||
886 | return 0; | 920 | return 0; |
887 | } | 921 | } |
888 | 922 | ||
923 | #ifdef CONFIG_GENERIC_HARDIRQS | ||
889 | int __init __weak arch_probe_nr_irqs(void) | 924 | int __init __weak arch_probe_nr_irqs(void) |
890 | { | 925 | { |
891 | return 0; | 926 | return NR_IRQS_LEGACY; |
892 | } | 927 | } |
893 | 928 | ||
894 | int __init __weak arch_early_irq_init(void) | 929 | int __init __weak arch_early_irq_init(void) |
895 | { | 930 | { |
896 | return 0; | 931 | return 0; |
897 | } | 932 | } |
898 | 933 | #endif | |
899 | int __weak arch_init_chip_data(struct irq_desc *desc, int node) | ||
900 | { | ||
901 | return 0; | ||
902 | } | ||