aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/smp.c
diff options
context:
space:
mode:
authorMilton Miller <miltonm@bga.com>2008-11-14 15:11:49 -0500
committerPaul Mackerras <paulus@samba.org>2008-11-19 00:05:06 -0500
commit25ddd738c2ebffb6c2d3cf29c91b986d1bb39c99 (patch)
treecc22b3a4b2481954c1bcbfececac2abfcdb7af40 /arch/powerpc/kernel/smp.c
parenta6326e98a28d8a57f693369c82559543c6950f09 (diff)
powerpc: Provide a separate handler for each IPI action
With the new generic smp call function helpers, I noticed the code in smp_message_recv was a single function call in many cases. While getting the message number from the ipi data is easy, we can reduce the path length by a function and data-dependent switch by registering seperate IPI actions for these simple calls. Originally I left the ipi action array exposed, but then I realized the registration code should be common too. The three users each had their own name array, so I made a fourth to convert all users to use a common one. Signed-off-by: Milton Miller <miltonm@bga.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/smp.c')
-rw-r--r--arch/powerpc/kernel/smp.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index ff9f7010097d..a59d8d72bb97 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -123,6 +123,65 @@ void smp_message_recv(int msg)
123 } 123 }
124} 124}
125 125
126static irqreturn_t call_function_action(int irq, void *data)
127{
128 generic_smp_call_function_interrupt();
129 return IRQ_HANDLED;
130}
131
132static irqreturn_t reschedule_action(int irq, void *data)
133{
134 /* we just need the return path side effect of checking need_resched */
135 return IRQ_HANDLED;
136}
137
138static irqreturn_t call_function_single_action(int irq, void *data)
139{
140 generic_smp_call_function_single_interrupt();
141 return IRQ_HANDLED;
142}
143
144static irqreturn_t debug_ipi_action(int irq, void *data)
145{
146 smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
147 return IRQ_HANDLED;
148}
149
150static irq_handler_t smp_ipi_action[] = {
151 [PPC_MSG_CALL_FUNCTION] = call_function_action,
152 [PPC_MSG_RESCHEDULE] = reschedule_action,
153 [PPC_MSG_CALL_FUNC_SINGLE] = call_function_single_action,
154 [PPC_MSG_DEBUGGER_BREAK] = debug_ipi_action,
155};
156
157const char *smp_ipi_name[] = {
158 [PPC_MSG_CALL_FUNCTION] = "ipi call function",
159 [PPC_MSG_RESCHEDULE] = "ipi reschedule",
160 [PPC_MSG_CALL_FUNC_SINGLE] = "ipi call function single",
161 [PPC_MSG_DEBUGGER_BREAK] = "ipi debugger",
162};
163
164/* optional function to request ipi, for controllers with >= 4 ipis */
165int smp_request_message_ipi(int virq, int msg)
166{
167 int err;
168
169 if (msg < 0 || msg > PPC_MSG_DEBUGGER_BREAK) {
170 return -EINVAL;
171 }
172#if !defined(CONFIG_DEBUGGER) && !defined(CONFIG_KEXEC)
173 if (msg == PPC_MSG_DEBUGGER_BREAK) {
174 return 1;
175 }
176#endif
177 err = request_irq(virq, smp_ipi_action[msg], IRQF_DISABLED|IRQF_PERCPU,
178 smp_ipi_name[msg], 0);
179 WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
180 virq, smp_ipi_name[msg], err);
181
182 return err;
183}
184
126void smp_send_reschedule(int cpu) 185void smp_send_reschedule(int cpu)
127{ 186{
128 if (likely(smp_ops)) 187 if (likely(smp_ops))