aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/smp.h7
-rw-r--r--arch/powerpc/kernel/smp.c59
2 files changed, 66 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 1866cec4f967..c25f73d1d842 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -81,6 +81,13 @@ extern int cpu_to_core_id(int cpu);
81#define PPC_MSG_CALL_FUNC_SINGLE 2 81#define PPC_MSG_CALL_FUNC_SINGLE 2
82#define PPC_MSG_DEBUGGER_BREAK 3 82#define PPC_MSG_DEBUGGER_BREAK 3
83 83
84/*
85 * irq controllers that have dedicated ipis per message and don't
86 * need additional code in the action handler may use this
87 */
88extern int smp_request_message_ipi(int virq, int message);
89extern const char *smp_ipi_name[];
90
84void smp_init_iSeries(void); 91void smp_init_iSeries(void);
85void smp_init_pSeries(void); 92void smp_init_pSeries(void);
86void smp_init_cell(void); 93void smp_init_cell(void);
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))