aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/smp.c')
-rw-r--r--arch/powerpc/kernel/smp.c71
1 files changed, 63 insertions, 8 deletions
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index ff9f7010097d..8ac3f721d235 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -57,7 +57,6 @@
57#define DBG(fmt...) 57#define DBG(fmt...)
58#endif 58#endif
59 59
60int smp_hw_index[NR_CPUS];
61struct thread_info *secondary_ti; 60struct thread_info *secondary_ti;
62 61
63cpumask_t cpu_possible_map = CPU_MASK_NONE; 62cpumask_t cpu_possible_map = CPU_MASK_NONE;
@@ -123,6 +122,65 @@ void smp_message_recv(int msg)
123 } 122 }
124} 123}
125 124
125static irqreturn_t call_function_action(int irq, void *data)
126{
127 generic_smp_call_function_interrupt();
128 return IRQ_HANDLED;
129}
130
131static irqreturn_t reschedule_action(int irq, void *data)
132{
133 /* we just need the return path side effect of checking need_resched */
134 return IRQ_HANDLED;
135}
136
137static irqreturn_t call_function_single_action(int irq, void *data)
138{
139 generic_smp_call_function_single_interrupt();
140 return IRQ_HANDLED;
141}
142
143static irqreturn_t debug_ipi_action(int irq, void *data)
144{
145 smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
146 return IRQ_HANDLED;
147}
148
149static irq_handler_t smp_ipi_action[] = {
150 [PPC_MSG_CALL_FUNCTION] = call_function_action,
151 [PPC_MSG_RESCHEDULE] = reschedule_action,
152 [PPC_MSG_CALL_FUNC_SINGLE] = call_function_single_action,
153 [PPC_MSG_DEBUGGER_BREAK] = debug_ipi_action,
154};
155
156const char *smp_ipi_name[] = {
157 [PPC_MSG_CALL_FUNCTION] = "ipi call function",
158 [PPC_MSG_RESCHEDULE] = "ipi reschedule",
159 [PPC_MSG_CALL_FUNC_SINGLE] = "ipi call function single",
160 [PPC_MSG_DEBUGGER_BREAK] = "ipi debugger",
161};
162
163/* optional function to request ipi, for controllers with >= 4 ipis */
164int smp_request_message_ipi(int virq, int msg)
165{
166 int err;
167
168 if (msg < 0 || msg > PPC_MSG_DEBUGGER_BREAK) {
169 return -EINVAL;
170 }
171#if !defined(CONFIG_DEBUGGER) && !defined(CONFIG_KEXEC)
172 if (msg == PPC_MSG_DEBUGGER_BREAK) {
173 return 1;
174 }
175#endif
176 err = request_irq(virq, smp_ipi_action[msg], IRQF_DISABLED|IRQF_PERCPU,
177 smp_ipi_name[msg], 0);
178 WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
179 virq, smp_ipi_name[msg], err);
180
181 return err;
182}
183
126void smp_send_reschedule(int cpu) 184void smp_send_reschedule(int cpu)
127{ 185{
128 if (likely(smp_ops)) 186 if (likely(smp_ops))
@@ -408,8 +466,7 @@ out:
408static struct device_node *cpu_to_l2cache(int cpu) 466static struct device_node *cpu_to_l2cache(int cpu)
409{ 467{
410 struct device_node *np; 468 struct device_node *np;
411 const phandle *php; 469 struct device_node *cache;
412 phandle ph;
413 470
414 if (!cpu_present(cpu)) 471 if (!cpu_present(cpu))
415 return NULL; 472 return NULL;
@@ -418,13 +475,11 @@ static struct device_node *cpu_to_l2cache(int cpu)
418 if (np == NULL) 475 if (np == NULL)
419 return NULL; 476 return NULL;
420 477
421 php = of_get_property(np, "l2-cache", NULL); 478 cache = of_find_next_cache_node(np);
422 if (php == NULL) 479
423 return NULL;
424 ph = *php;
425 of_node_put(np); 480 of_node_put(np);
426 481
427 return of_find_node_by_phandle(ph); 482 return cache;
428} 483}
429 484
430/* Activate a secondary processor. */ 485/* Activate a secondary processor. */