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 d1165566f064..65484b2200b3 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
63DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE; 62DEFINE_PER_CPU(cpumask_t, cpu_sibling_map) = CPU_MASK_NONE;
@@ -119,6 +118,65 @@ void smp_message_recv(int msg)
119 } 118 }
120} 119}
121 120
121static irqreturn_t call_function_action(int irq, void *data)
122{
123 generic_smp_call_function_interrupt();
124 return IRQ_HANDLED;
125}
126
127static irqreturn_t reschedule_action(int irq, void *data)
128{
129 /* we just need the return path side effect of checking need_resched */
130 return IRQ_HANDLED;
131}
132
133static irqreturn_t call_function_single_action(int irq, void *data)
134{
135 generic_smp_call_function_single_interrupt();
136 return IRQ_HANDLED;
137}
138
139static irqreturn_t debug_ipi_action(int irq, void *data)
140{
141 smp_message_recv(PPC_MSG_DEBUGGER_BREAK);
142 return IRQ_HANDLED;
143}
144
145static irq_handler_t smp_ipi_action[] = {
146 [PPC_MSG_CALL_FUNCTION] = call_function_action,
147 [PPC_MSG_RESCHEDULE] = reschedule_action,
148 [PPC_MSG_CALL_FUNC_SINGLE] = call_function_single_action,
149 [PPC_MSG_DEBUGGER_BREAK] = debug_ipi_action,
150};
151
152const char *smp_ipi_name[] = {
153 [PPC_MSG_CALL_FUNCTION] = "ipi call function",
154 [PPC_MSG_RESCHEDULE] = "ipi reschedule",
155 [PPC_MSG_CALL_FUNC_SINGLE] = "ipi call function single",
156 [PPC_MSG_DEBUGGER_BREAK] = "ipi debugger",
157};
158
159/* optional function to request ipi, for controllers with >= 4 ipis */
160int smp_request_message_ipi(int virq, int msg)
161{
162 int err;
163
164 if (msg < 0 || msg > PPC_MSG_DEBUGGER_BREAK) {
165 return -EINVAL;
166 }
167#if !defined(CONFIG_DEBUGGER) && !defined(CONFIG_KEXEC)
168 if (msg == PPC_MSG_DEBUGGER_BREAK) {
169 return 1;
170 }
171#endif
172 err = request_irq(virq, smp_ipi_action[msg], IRQF_DISABLED|IRQF_PERCPU,
173 smp_ipi_name[msg], 0);
174 WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
175 virq, smp_ipi_name[msg], err);
176
177 return err;
178}
179
122void smp_send_reschedule(int cpu) 180void smp_send_reschedule(int cpu)
123{ 181{
124 if (likely(smp_ops)) 182 if (likely(smp_ops))
@@ -404,8 +462,7 @@ out:
404static struct device_node *cpu_to_l2cache(int cpu) 462static struct device_node *cpu_to_l2cache(int cpu)
405{ 463{
406 struct device_node *np; 464 struct device_node *np;
407 const phandle *php; 465 struct device_node *cache;
408 phandle ph;
409 466
410 if (!cpu_present(cpu)) 467 if (!cpu_present(cpu))
411 return NULL; 468 return NULL;
@@ -414,13 +471,11 @@ static struct device_node *cpu_to_l2cache(int cpu)
414 if (np == NULL) 471 if (np == NULL)
415 return NULL; 472 return NULL;
416 473
417 php = of_get_property(np, "l2-cache", NULL); 474 cache = of_find_next_cache_node(np);
418 if (php == NULL) 475
419 return NULL;
420 ph = *php;
421 of_node_put(np); 476 of_node_put(np);
422 477
423 return of_find_node_by_phandle(ph); 478 return cache;
424} 479}
425 480
426/* Activate a secondary processor. */ 481/* Activate a secondary processor. */