diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2011-04-05 11:23:39 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-04-14 02:52:32 -0400 |
commit | 184748cc50b2dceb8287f9fb657eda48ff8fcfe7 (patch) | |
tree | da32494cf29e5ec9f80b17dc8590bdc450ea545a | |
parent | a4c98f8bbeafee12c979c90743f6fda94f7515c7 (diff) |
sched: Provide scheduler_ipi() callback in response to smp_send_reschedule()
For future rework of try_to_wake_up() we'd like to push part of that
function onto the CPU the task is actually going to run on.
In order to do so we need a generic callback from the existing scheduler IPI.
This patch introduces such a generic callback: scheduler_ipi() and
implements it as a NOP.
BenH notes: PowerPC might use this IPI on offline CPUs under rare conditions!
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Acked-by: Chris Metcalf <cmetcalf@tilera.com>
Acked-by: Jesper Nilsson <jesper.nilsson@axis.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Reviewed-by: Frank Rowand <frank.rowand@am.sony.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Nick Piggin <npiggin@kernel.dk>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/20110405152728.744338123@chello.nl
-rw-r--r-- | arch/alpha/kernel/smp.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/smp.c | 5 | ||||
-rw-r--r-- | arch/blackfin/mach-common/smp.c | 3 | ||||
-rw-r--r-- | arch/cris/arch-v32/kernel/smp.c | 13 | ||||
-rw-r--r-- | arch/ia64/kernel/irq_ia64.c | 2 | ||||
-rw-r--r-- | arch/ia64/xen/irq_xen.c | 10 | ||||
-rw-r--r-- | arch/m32r/kernel/smp.c | 4 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/smp.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/smtc.c | 2 | ||||
-rw-r--r-- | arch/mips/mti-malta/malta-int.c | 2 | ||||
-rw-r--r-- | arch/mips/pmc-sierra/yosemite/smp.c | 4 | ||||
-rw-r--r-- | arch/mips/sgi-ip27/ip27-irq.c | 2 | ||||
-rw-r--r-- | arch/mips/sibyte/bcm1480/smp.c | 7 | ||||
-rw-r--r-- | arch/mips/sibyte/sb1250/smp.c | 7 | ||||
-rw-r--r-- | arch/mn10300/kernel/smp.c | 5 | ||||
-rw-r--r-- | arch/parisc/kernel/smp.c | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/smp.c | 4 | ||||
-rw-r--r-- | arch/s390/kernel/smp.c | 6 | ||||
-rw-r--r-- | arch/sh/kernel/smp.c | 2 | ||||
-rw-r--r-- | arch/sparc/kernel/smp_32.c | 4 | ||||
-rw-r--r-- | arch/sparc/kernel/smp_64.c | 1 | ||||
-rw-r--r-- | arch/tile/kernel/smp.c | 6 | ||||
-rw-r--r-- | arch/um/kernel/smp.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/smp.c | 5 | ||||
-rw-r--r-- | arch/x86/xen/smp.c | 5 | ||||
-rw-r--r-- | include/linux/sched.h | 2 |
26 files changed, 63 insertions, 50 deletions
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 42aa078a5e4d..5a621c6d22ab 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c | |||
@@ -585,8 +585,7 @@ handle_ipi(struct pt_regs *regs) | |||
585 | 585 | ||
586 | switch (which) { | 586 | switch (which) { |
587 | case IPI_RESCHEDULE: | 587 | case IPI_RESCHEDULE: |
588 | /* Reschedule callback. Everything to be done | 588 | scheduler_ipi(); |
589 | is done by the interrupt return path. */ | ||
590 | break; | 589 | break; |
591 | 590 | ||
592 | case IPI_CALL_FUNC: | 591 | case IPI_CALL_FUNC: |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 8fe05ad932e4..7a561eb731ea 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -560,10 +560,7 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) | |||
560 | break; | 560 | break; |
561 | 561 | ||
562 | case IPI_RESCHEDULE: | 562 | case IPI_RESCHEDULE: |
563 | /* | 563 | scheduler_ipi(); |
564 | * nothing more to do - eveything is | ||
565 | * done on the interrupt return path | ||
566 | */ | ||
567 | break; | 564 | break; |
568 | 565 | ||
569 | case IPI_CALL_FUNC: | 566 | case IPI_CALL_FUNC: |
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 6e17a265c4d3..326bb86f4d29 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c | |||
@@ -164,6 +164,9 @@ static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) | |||
164 | while (msg_queue->count) { | 164 | while (msg_queue->count) { |
165 | msg = &msg_queue->ipi_message[msg_queue->head]; | 165 | msg = &msg_queue->ipi_message[msg_queue->head]; |
166 | switch (msg->type) { | 166 | switch (msg->type) { |
167 | case BFIN_IPI_RESCHEDULE: | ||
168 | scheduler_ipi(); | ||
169 | break; | ||
167 | case BFIN_IPI_CALL_FUNC: | 170 | case BFIN_IPI_CALL_FUNC: |
168 | spin_unlock_irqrestore(&msg_queue->lock, flags); | 171 | spin_unlock_irqrestore(&msg_queue->lock, flags); |
169 | ipi_call_function(cpu, msg); | 172 | ipi_call_function(cpu, msg); |
diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 4c9e3e1ba5d1..66cc75657e2f 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c | |||
@@ -342,15 +342,18 @@ irqreturn_t crisv32_ipi_interrupt(int irq, void *dev_id) | |||
342 | 342 | ||
343 | ipi = REG_RD(intr_vect, irq_regs[smp_processor_id()], rw_ipi); | 343 | ipi = REG_RD(intr_vect, irq_regs[smp_processor_id()], rw_ipi); |
344 | 344 | ||
345 | if (ipi.vector & IPI_SCHEDULE) { | ||
346 | scheduler_ipi(); | ||
347 | } | ||
345 | if (ipi.vector & IPI_CALL) { | 348 | if (ipi.vector & IPI_CALL) { |
346 | func(info); | 349 | func(info); |
347 | } | 350 | } |
348 | if (ipi.vector & IPI_FLUSH_TLB) { | 351 | if (ipi.vector & IPI_FLUSH_TLB) { |
349 | if (flush_mm == FLUSH_ALL) | 352 | if (flush_mm == FLUSH_ALL) |
350 | __flush_tlb_all(); | 353 | __flush_tlb_all(); |
351 | else if (flush_vma == FLUSH_ALL) | 354 | else if (flush_vma == FLUSH_ALL) |
352 | __flush_tlb_mm(flush_mm); | 355 | __flush_tlb_mm(flush_mm); |
353 | else | 356 | else |
354 | __flush_tlb_page(flush_vma, flush_addr); | 357 | __flush_tlb_page(flush_vma, flush_addr); |
355 | } | 358 | } |
356 | 359 | ||
diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 5b704740f160..782c3a357f24 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/irq.h> | 31 | #include <linux/irq.h> |
32 | #include <linux/ratelimit.h> | 32 | #include <linux/ratelimit.h> |
33 | #include <linux/acpi.h> | 33 | #include <linux/acpi.h> |
34 | #include <linux/sched.h> | ||
34 | 35 | ||
35 | #include <asm/delay.h> | 36 | #include <asm/delay.h> |
36 | #include <asm/intrinsics.h> | 37 | #include <asm/intrinsics.h> |
@@ -496,6 +497,7 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) | |||
496 | smp_local_flush_tlb(); | 497 | smp_local_flush_tlb(); |
497 | kstat_incr_irqs_this_cpu(irq, desc); | 498 | kstat_incr_irqs_this_cpu(irq, desc); |
498 | } else if (unlikely(IS_RESCHEDULE(vector))) { | 499 | } else if (unlikely(IS_RESCHEDULE(vector))) { |
500 | scheduler_ipi(); | ||
499 | kstat_incr_irqs_this_cpu(irq, desc); | 501 | kstat_incr_irqs_this_cpu(irq, desc); |
500 | } else { | 502 | } else { |
501 | ia64_setreg(_IA64_REG_CR_TPR, vector); | 503 | ia64_setreg(_IA64_REG_CR_TPR, vector); |
diff --git a/arch/ia64/xen/irq_xen.c b/arch/ia64/xen/irq_xen.c index 108bb858acf2..b279e142c633 100644 --- a/arch/ia64/xen/irq_xen.c +++ b/arch/ia64/xen/irq_xen.c | |||
@@ -92,6 +92,8 @@ static unsigned short saved_irq_cnt; | |||
92 | static int xen_slab_ready; | 92 | static int xen_slab_ready; |
93 | 93 | ||
94 | #ifdef CONFIG_SMP | 94 | #ifdef CONFIG_SMP |
95 | #include <linux/sched.h> | ||
96 | |||
95 | /* Dummy stub. Though we may check XEN_RESCHEDULE_VECTOR before __do_IRQ, | 97 | /* Dummy stub. Though we may check XEN_RESCHEDULE_VECTOR before __do_IRQ, |
96 | * it ends up to issue several memory accesses upon percpu data and | 98 | * it ends up to issue several memory accesses upon percpu data and |
97 | * thus adds unnecessary traffic to other paths. | 99 | * thus adds unnecessary traffic to other paths. |
@@ -99,7 +101,13 @@ static int xen_slab_ready; | |||
99 | static irqreturn_t | 101 | static irqreturn_t |
100 | xen_dummy_handler(int irq, void *dev_id) | 102 | xen_dummy_handler(int irq, void *dev_id) |
101 | { | 103 | { |
104 | return IRQ_HANDLED; | ||
105 | } | ||
102 | 106 | ||
107 | static irqreturn_t | ||
108 | xen_resched_handler(int irq, void *dev_id) | ||
109 | { | ||
110 | scheduler_ipi(); | ||
103 | return IRQ_HANDLED; | 111 | return IRQ_HANDLED; |
104 | } | 112 | } |
105 | 113 | ||
@@ -110,7 +118,7 @@ static struct irqaction xen_ipi_irqaction = { | |||
110 | }; | 118 | }; |
111 | 119 | ||
112 | static struct irqaction xen_resched_irqaction = { | 120 | static struct irqaction xen_resched_irqaction = { |
113 | .handler = xen_dummy_handler, | 121 | .handler = xen_resched_handler, |
114 | .flags = IRQF_DISABLED, | 122 | .flags = IRQF_DISABLED, |
115 | .name = "resched" | 123 | .name = "resched" |
116 | }; | 124 | }; |
diff --git a/arch/m32r/kernel/smp.c b/arch/m32r/kernel/smp.c index 31cef20b2996..fc10b39893d4 100644 --- a/arch/m32r/kernel/smp.c +++ b/arch/m32r/kernel/smp.c | |||
@@ -122,8 +122,6 @@ void smp_send_reschedule(int cpu_id) | |||
122 | * | 122 | * |
123 | * Description: This routine executes on CPU which received | 123 | * Description: This routine executes on CPU which received |
124 | * 'RESCHEDULE_IPI'. | 124 | * 'RESCHEDULE_IPI'. |
125 | * Rescheduling is processed at the exit of interrupt | ||
126 | * operation. | ||
127 | * | 125 | * |
128 | * Born on Date: 2002.02.05 | 126 | * Born on Date: 2002.02.05 |
129 | * | 127 | * |
@@ -138,7 +136,7 @@ void smp_send_reschedule(int cpu_id) | |||
138 | *==========================================================================*/ | 136 | *==========================================================================*/ |
139 | void smp_reschedule_interrupt(void) | 137 | void smp_reschedule_interrupt(void) |
140 | { | 138 | { |
141 | /* nothing to do */ | 139 | scheduler_ipi(); |
142 | } | 140 | } |
143 | 141 | ||
144 | /*==========================================================================* | 142 | /*==========================================================================* |
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index ba78b21cc8d0..76923eeb58b9 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c | |||
@@ -44,6 +44,8 @@ static irqreturn_t mailbox_interrupt(int irq, void *dev_id) | |||
44 | 44 | ||
45 | if (action & SMP_CALL_FUNCTION) | 45 | if (action & SMP_CALL_FUNCTION) |
46 | smp_call_function_interrupt(); | 46 | smp_call_function_interrupt(); |
47 | if (action & SMP_RESCHEDULE_YOURSELF) | ||
48 | scheduler_ipi(); | ||
47 | 49 | ||
48 | /* Check if we've been told to flush the icache */ | 50 | /* Check if we've been told to flush the icache */ |
49 | if (action & SMP_ICACHE_FLUSH) | 51 | if (action & SMP_ICACHE_FLUSH) |
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index 5a88cc4ccd5a..cedac4633741 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c | |||
@@ -929,7 +929,7 @@ static void post_direct_ipi(int cpu, struct smtc_ipi *pipi) | |||
929 | 929 | ||
930 | static void ipi_resched_interrupt(void) | 930 | static void ipi_resched_interrupt(void) |
931 | { | 931 | { |
932 | /* Return from interrupt should be enough to cause scheduler check */ | 932 | scheduler_ipi(); |
933 | } | 933 | } |
934 | 934 | ||
935 | static void ipi_call_interrupt(void) | 935 | static void ipi_call_interrupt(void) |
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c index 9027061f0ead..7d93e6fbfa5a 100644 --- a/arch/mips/mti-malta/malta-int.c +++ b/arch/mips/mti-malta/malta-int.c | |||
@@ -309,6 +309,8 @@ static void ipi_call_dispatch(void) | |||
309 | 309 | ||
310 | static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) | 310 | static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id) |
311 | { | 311 | { |
312 | scheduler_ipi(); | ||
313 | |||
312 | return IRQ_HANDLED; | 314 | return IRQ_HANDLED; |
313 | } | 315 | } |
314 | 316 | ||
diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index efc9e889b349..2608752898c0 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c | |||
@@ -55,6 +55,8 @@ void titan_mailbox_irq(void) | |||
55 | 55 | ||
56 | if (status & 0x2) | 56 | if (status & 0x2) |
57 | smp_call_function_interrupt(); | 57 | smp_call_function_interrupt(); |
58 | if (status & 0x4) | ||
59 | scheduler_ipi(); | ||
58 | break; | 60 | break; |
59 | 61 | ||
60 | case 1: | 62 | case 1: |
@@ -63,6 +65,8 @@ void titan_mailbox_irq(void) | |||
63 | 65 | ||
64 | if (status & 0x2) | 66 | if (status & 0x2) |
65 | smp_call_function_interrupt(); | 67 | smp_call_function_interrupt(); |
68 | if (status & 0x4) | ||
69 | scheduler_ipi(); | ||
66 | break; | 70 | break; |
67 | } | 71 | } |
68 | } | 72 | } |
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 0a04603d577c..b18b04e48577 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c | |||
@@ -147,8 +147,10 @@ static void ip27_do_irq_mask0(void) | |||
147 | #ifdef CONFIG_SMP | 147 | #ifdef CONFIG_SMP |
148 | if (pend0 & (1UL << CPU_RESCHED_A_IRQ)) { | 148 | if (pend0 & (1UL << CPU_RESCHED_A_IRQ)) { |
149 | LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); | 149 | LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); |
150 | scheduler_ipi(); | ||
150 | } else if (pend0 & (1UL << CPU_RESCHED_B_IRQ)) { | 151 | } else if (pend0 & (1UL << CPU_RESCHED_B_IRQ)) { |
151 | LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ); | 152 | LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ); |
153 | scheduler_ipi(); | ||
152 | } else if (pend0 & (1UL << CPU_CALL_A_IRQ)) { | 154 | } else if (pend0 & (1UL << CPU_CALL_A_IRQ)) { |
153 | LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ); | 155 | LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ); |
154 | smp_call_function_interrupt(); | 156 | smp_call_function_interrupt(); |
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index 47b347c992ea..d667875be564 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/smp.h> | 21 | #include <linux/smp.h> |
22 | #include <linux/kernel_stat.h> | 22 | #include <linux/kernel_stat.h> |
23 | #include <linux/sched.h> | ||
23 | 24 | ||
24 | #include <asm/mmu_context.h> | 25 | #include <asm/mmu_context.h> |
25 | #include <asm/io.h> | 26 | #include <asm/io.h> |
@@ -189,10 +190,8 @@ void bcm1480_mailbox_interrupt(void) | |||
189 | /* Clear the mailbox to clear the interrupt */ | 190 | /* Clear the mailbox to clear the interrupt */ |
190 | __raw_writeq(((u64)action)<<48, mailbox_0_clear_regs[cpu]); | 191 | __raw_writeq(((u64)action)<<48, mailbox_0_clear_regs[cpu]); |
191 | 192 | ||
192 | /* | 193 | if (action & SMP_RESCHEDULE_YOURSELF) |
193 | * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the | 194 | scheduler_ipi(); |
194 | * interrupt will do the reschedule for us | ||
195 | */ | ||
196 | 195 | ||
197 | if (action & SMP_CALL_FUNCTION) | 196 | if (action & SMP_CALL_FUNCTION) |
198 | smp_call_function_interrupt(); | 197 | smp_call_function_interrupt(); |
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c index c00a5cb1128d..38e7f6bd7922 100644 --- a/arch/mips/sibyte/sb1250/smp.c +++ b/arch/mips/sibyte/sb1250/smp.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/smp.h> | 22 | #include <linux/smp.h> |
23 | #include <linux/kernel_stat.h> | 23 | #include <linux/kernel_stat.h> |
24 | #include <linux/sched.h> | ||
24 | 25 | ||
25 | #include <asm/mmu_context.h> | 26 | #include <asm/mmu_context.h> |
26 | #include <asm/io.h> | 27 | #include <asm/io.h> |
@@ -177,10 +178,8 @@ void sb1250_mailbox_interrupt(void) | |||
177 | /* Clear the mailbox to clear the interrupt */ | 178 | /* Clear the mailbox to clear the interrupt */ |
178 | ____raw_writeq(((u64)action) << 48, mailbox_clear_regs[cpu]); | 179 | ____raw_writeq(((u64)action) << 48, mailbox_clear_regs[cpu]); |
179 | 180 | ||
180 | /* | 181 | if (action & SMP_RESCHEDULE_YOURSELF) |
181 | * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the | 182 | scheduler_ipi(); |
182 | * interrupt will do the reschedule for us | ||
183 | */ | ||
184 | 183 | ||
185 | if (action & SMP_CALL_FUNCTION) | 184 | if (action & SMP_CALL_FUNCTION) |
186 | smp_call_function_interrupt(); | 185 | smp_call_function_interrupt(); |
diff --git a/arch/mn10300/kernel/smp.c b/arch/mn10300/kernel/smp.c index 226c826a2194..83fb27912231 100644 --- a/arch/mn10300/kernel/smp.c +++ b/arch/mn10300/kernel/smp.c | |||
@@ -494,14 +494,11 @@ void smp_send_stop(void) | |||
494 | * @irq: The interrupt number. | 494 | * @irq: The interrupt number. |
495 | * @dev_id: The device ID. | 495 | * @dev_id: The device ID. |
496 | * | 496 | * |
497 | * We need do nothing here, since the scheduling will be effected on our way | ||
498 | * back through entry.S. | ||
499 | * | ||
500 | * Returns IRQ_HANDLED to indicate we handled the interrupt successfully. | 497 | * Returns IRQ_HANDLED to indicate we handled the interrupt successfully. |
501 | */ | 498 | */ |
502 | static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id) | 499 | static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id) |
503 | { | 500 | { |
504 | /* do nothing */ | 501 | scheduler_ipi(); |
505 | return IRQ_HANDLED; | 502 | return IRQ_HANDLED; |
506 | } | 503 | } |
507 | 504 | ||
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 69d63d354ef0..828305f19cff 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c | |||
@@ -155,10 +155,7 @@ ipi_interrupt(int irq, void *dev_id) | |||
155 | 155 | ||
156 | case IPI_RESCHEDULE: | 156 | case IPI_RESCHEDULE: |
157 | smp_debug(100, KERN_DEBUG "CPU%d IPI_RESCHEDULE\n", this_cpu); | 157 | smp_debug(100, KERN_DEBUG "CPU%d IPI_RESCHEDULE\n", this_cpu); |
158 | /* | 158 | scheduler_ipi(); |
159 | * Reschedule callback. Everything to be | ||
160 | * done is done by the interrupt return path. | ||
161 | */ | ||
162 | break; | 159 | break; |
163 | 160 | ||
164 | case IPI_CALL_FUNC: | 161 | case IPI_CALL_FUNC: |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index cbdbb14be4b0..9f9c204bef69 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -116,7 +116,7 @@ void smp_message_recv(int msg) | |||
116 | generic_smp_call_function_interrupt(); | 116 | generic_smp_call_function_interrupt(); |
117 | break; | 117 | break; |
118 | case PPC_MSG_RESCHEDULE: | 118 | case PPC_MSG_RESCHEDULE: |
119 | /* we notice need_resched on exit */ | 119 | scheduler_ipi(); |
120 | break; | 120 | break; |
121 | case PPC_MSG_CALL_FUNC_SINGLE: | 121 | case PPC_MSG_CALL_FUNC_SINGLE: |
122 | generic_smp_call_function_single_interrupt(); | 122 | generic_smp_call_function_single_interrupt(); |
@@ -146,7 +146,7 @@ static irqreturn_t call_function_action(int irq, void *data) | |||
146 | 146 | ||
147 | static irqreturn_t reschedule_action(int irq, void *data) | 147 | static irqreturn_t reschedule_action(int irq, void *data) |
148 | { | 148 | { |
149 | /* we just need the return path side effect of checking need_resched */ | 149 | scheduler_ipi(); |
150 | return IRQ_HANDLED; | 150 | return IRQ_HANDLED; |
151 | } | 151 | } |
152 | 152 | ||
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 63a97db83f96..63c7d9ff220d 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -165,12 +165,12 @@ static void do_ext_call_interrupt(unsigned int ext_int_code, | |||
165 | kstat_cpu(smp_processor_id()).irqs[EXTINT_IPI]++; | 165 | kstat_cpu(smp_processor_id()).irqs[EXTINT_IPI]++; |
166 | /* | 166 | /* |
167 | * handle bit signal external calls | 167 | * handle bit signal external calls |
168 | * | ||
169 | * For the ec_schedule signal we have to do nothing. All the work | ||
170 | * is done automatically when we return from the interrupt. | ||
171 | */ | 168 | */ |
172 | bits = xchg(&S390_lowcore.ext_call_fast, 0); | 169 | bits = xchg(&S390_lowcore.ext_call_fast, 0); |
173 | 170 | ||
171 | if (test_bit(ec_schedule, &bits)) | ||
172 | scheduler_ipi(); | ||
173 | |||
174 | if (test_bit(ec_call_function, &bits)) | 174 | if (test_bit(ec_call_function, &bits)) |
175 | generic_smp_call_function_interrupt(); | 175 | generic_smp_call_function_interrupt(); |
176 | 176 | ||
diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 509b36b45115..6207561ea34a 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/cpu.h> | 21 | #include <linux/cpu.h> |
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/sched.h> | ||
23 | #include <asm/atomic.h> | 24 | #include <asm/atomic.h> |
24 | #include <asm/processor.h> | 25 | #include <asm/processor.h> |
25 | #include <asm/system.h> | 26 | #include <asm/system.h> |
@@ -323,6 +324,7 @@ void smp_message_recv(unsigned int msg) | |||
323 | generic_smp_call_function_interrupt(); | 324 | generic_smp_call_function_interrupt(); |
324 | break; | 325 | break; |
325 | case SMP_MSG_RESCHEDULE: | 326 | case SMP_MSG_RESCHEDULE: |
327 | scheduler_ipi(); | ||
326 | break; | 328 | break; |
327 | case SMP_MSG_FUNCTION_SINGLE: | 329 | case SMP_MSG_FUNCTION_SINGLE: |
328 | generic_smp_call_function_single_interrupt(); | 330 | generic_smp_call_function_single_interrupt(); |
diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index 91c10fb70858..f95690c167b6 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c | |||
@@ -125,7 +125,9 @@ struct linux_prom_registers smp_penguin_ctable __cpuinitdata = { 0 }; | |||
125 | 125 | ||
126 | void smp_send_reschedule(int cpu) | 126 | void smp_send_reschedule(int cpu) |
127 | { | 127 | { |
128 | /* See sparc64 */ | 128 | /* |
129 | * XXX missing reschedule IPI, see scheduler_ipi() | ||
130 | */ | ||
129 | } | 131 | } |
130 | 132 | ||
131 | void smp_send_stop(void) | 133 | void smp_send_stop(void) |
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 3e94a8c23238..9478da7fdb3e 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c | |||
@@ -1368,6 +1368,7 @@ void smp_send_reschedule(int cpu) | |||
1368 | void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs) | 1368 | void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs) |
1369 | { | 1369 | { |
1370 | clear_softint(1 << irq); | 1370 | clear_softint(1 << irq); |
1371 | scheduler_ipi(); | ||
1371 | } | 1372 | } |
1372 | 1373 | ||
1373 | /* This is a nop because we capture all other cpus | 1374 | /* This is a nop because we capture all other cpus |
diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c index a4293102ef81..c52224d5ed45 100644 --- a/arch/tile/kernel/smp.c +++ b/arch/tile/kernel/smp.c | |||
@@ -189,12 +189,8 @@ void flush_icache_range(unsigned long start, unsigned long end) | |||
189 | /* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */ | 189 | /* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */ |
190 | static irqreturn_t handle_reschedule_ipi(int irq, void *token) | 190 | static irqreturn_t handle_reschedule_ipi(int irq, void *token) |
191 | { | 191 | { |
192 | /* | ||
193 | * Nothing to do here; when we return from interrupt, the | ||
194 | * rescheduling will occur there. But do bump the interrupt | ||
195 | * profiler count in the meantime. | ||
196 | */ | ||
197 | __get_cpu_var(irq_stat).irq_resched_count++; | 192 | __get_cpu_var(irq_stat).irq_resched_count++; |
193 | scheduler_ipi(); | ||
198 | 194 | ||
199 | return IRQ_HANDLED; | 195 | return IRQ_HANDLED; |
200 | } | 196 | } |
diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c index 106bf27e2a9a..eefb107d2d73 100644 --- a/arch/um/kernel/smp.c +++ b/arch/um/kernel/smp.c | |||
@@ -173,7 +173,7 @@ void IPI_handler(int cpu) | |||
173 | break; | 173 | break; |
174 | 174 | ||
175 | case 'R': | 175 | case 'R': |
176 | set_tsk_need_resched(current); | 176 | scheduler_ipi(); |
177 | break; | 177 | break; |
178 | 178 | ||
179 | case 'S': | 179 | case 'S': |
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 513deac7228d..013e7eba83bb 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c | |||
@@ -194,14 +194,13 @@ static void native_stop_other_cpus(int wait) | |||
194 | } | 194 | } |
195 | 195 | ||
196 | /* | 196 | /* |
197 | * Reschedule call back. Nothing to do, | 197 | * Reschedule call back. |
198 | * all the work is done automatically when | ||
199 | * we return from the interrupt. | ||
200 | */ | 198 | */ |
201 | void smp_reschedule_interrupt(struct pt_regs *regs) | 199 | void smp_reschedule_interrupt(struct pt_regs *regs) |
202 | { | 200 | { |
203 | ack_APIC_irq(); | 201 | ack_APIC_irq(); |
204 | inc_irq_stat(irq_resched_count); | 202 | inc_irq_stat(irq_resched_count); |
203 | scheduler_ipi(); | ||
205 | /* | 204 | /* |
206 | * KVM uses this interrupt to force a cpu out of guest mode | 205 | * KVM uses this interrupt to force a cpu out of guest mode |
207 | */ | 206 | */ |
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 30612441ed99..762b46ab14d5 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c | |||
@@ -46,13 +46,12 @@ static irqreturn_t xen_call_function_interrupt(int irq, void *dev_id); | |||
46 | static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id); | 46 | static irqreturn_t xen_call_function_single_interrupt(int irq, void *dev_id); |
47 | 47 | ||
48 | /* | 48 | /* |
49 | * Reschedule call back. Nothing to do, | 49 | * Reschedule call back. |
50 | * all the work is done automatically when | ||
51 | * we return from the interrupt. | ||
52 | */ | 50 | */ |
53 | static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id) | 51 | static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id) |
54 | { | 52 | { |
55 | inc_irq_stat(irq_resched_count); | 53 | inc_irq_stat(irq_resched_count); |
54 | scheduler_ipi(); | ||
56 | 55 | ||
57 | return IRQ_HANDLED; | 56 | return IRQ_HANDLED; |
58 | } | 57 | } |
diff --git a/include/linux/sched.h b/include/linux/sched.h index 4ec2c027e92c..758e27afcda5 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -2189,8 +2189,10 @@ extern void set_task_comm(struct task_struct *tsk, char *from); | |||
2189 | extern char *get_task_comm(char *to, struct task_struct *tsk); | 2189 | extern char *get_task_comm(char *to, struct task_struct *tsk); |
2190 | 2190 | ||
2191 | #ifdef CONFIG_SMP | 2191 | #ifdef CONFIG_SMP |
2192 | static inline void scheduler_ipi(void) { } | ||
2192 | extern unsigned long wait_task_inactive(struct task_struct *, long match_state); | 2193 | extern unsigned long wait_task_inactive(struct task_struct *, long match_state); |
2193 | #else | 2194 | #else |
2195 | static inline void scheduler_ipi(void) { } | ||
2194 | static inline unsigned long wait_task_inactive(struct task_struct *p, | 2196 | static inline unsigned long wait_task_inactive(struct task_struct *p, |
2195 | long match_state) | 2197 | long match_state) |
2196 | { | 2198 | { |