diff options
Diffstat (limited to 'arch/blackfin/mach-common/smp.c')
-rw-r--r-- | arch/blackfin/mach-common/smp.c | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 0784a52389c8..d3464053dfdb 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/cache.h> | 16 | #include <linux/cache.h> |
17 | #include <linux/clockchips.h> | ||
17 | #include <linux/profile.h> | 18 | #include <linux/profile.h> |
18 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
19 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
@@ -47,9 +48,10 @@ unsigned long blackfin_iflush_l1_entry[NR_CPUS]; | |||
47 | 48 | ||
48 | struct blackfin_initial_pda __cpuinitdata initial_pda_coreb; | 49 | struct blackfin_initial_pda __cpuinitdata initial_pda_coreb; |
49 | 50 | ||
50 | #define BFIN_IPI_RESCHEDULE 0 | 51 | #define BFIN_IPI_TIMER 0 |
51 | #define BFIN_IPI_CALL_FUNC 1 | 52 | #define BFIN_IPI_RESCHEDULE 1 |
52 | #define BFIN_IPI_CPU_STOP 2 | 53 | #define BFIN_IPI_CALL_FUNC 2 |
54 | #define BFIN_IPI_CPU_STOP 3 | ||
53 | 55 | ||
54 | struct blackfin_flush_data { | 56 | struct blackfin_flush_data { |
55 | unsigned long start; | 57 | unsigned long start; |
@@ -160,6 +162,14 @@ static irqreturn_t ipi_handler_int0(int irq, void *dev_instance) | |||
160 | return IRQ_HANDLED; | 162 | return IRQ_HANDLED; |
161 | } | 163 | } |
162 | 164 | ||
165 | DECLARE_PER_CPU(struct clock_event_device, coretmr_events); | ||
166 | void ipi_timer(void) | ||
167 | { | ||
168 | int cpu = smp_processor_id(); | ||
169 | struct clock_event_device *evt = &per_cpu(coretmr_events, cpu); | ||
170 | evt->event_handler(evt); | ||
171 | } | ||
172 | |||
163 | static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) | 173 | static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) |
164 | { | 174 | { |
165 | struct ipi_message *msg; | 175 | struct ipi_message *msg; |
@@ -176,6 +186,9 @@ static irqreturn_t ipi_handler_int1(int irq, void *dev_instance) | |||
176 | while (msg_queue->count) { | 186 | while (msg_queue->count) { |
177 | msg = &msg_queue->ipi_message[msg_queue->head]; | 187 | msg = &msg_queue->ipi_message[msg_queue->head]; |
178 | switch (msg->type) { | 188 | switch (msg->type) { |
189 | case BFIN_IPI_TIMER: | ||
190 | ipi_timer(); | ||
191 | break; | ||
179 | case BFIN_IPI_RESCHEDULE: | 192 | case BFIN_IPI_RESCHEDULE: |
180 | scheduler_ipi(); | 193 | scheduler_ipi(); |
181 | break; | 194 | break; |
@@ -297,8 +310,6 @@ void smp_send_reschedule(int cpu) | |||
297 | { | 310 | { |
298 | cpumask_t callmap; | 311 | cpumask_t callmap; |
299 | /* simply trigger an ipi */ | 312 | /* simply trigger an ipi */ |
300 | if (cpu_is_offline(cpu)) | ||
301 | return; | ||
302 | 313 | ||
303 | cpumask_clear(&callmap); | 314 | cpumask_clear(&callmap); |
304 | cpumask_set_cpu(cpu, &callmap); | 315 | cpumask_set_cpu(cpu, &callmap); |
@@ -308,6 +319,16 @@ void smp_send_reschedule(int cpu) | |||
308 | return; | 319 | return; |
309 | } | 320 | } |
310 | 321 | ||
322 | void smp_send_msg(const struct cpumask *mask, unsigned long type) | ||
323 | { | ||
324 | smp_send_message(*mask, type, NULL, NULL, 0); | ||
325 | } | ||
326 | |||
327 | void smp_timer_broadcast(const struct cpumask *mask) | ||
328 | { | ||
329 | smp_send_msg(mask, BFIN_IPI_TIMER); | ||
330 | } | ||
331 | |||
311 | void smp_send_stop(void) | 332 | void smp_send_stop(void) |
312 | { | 333 | { |
313 | cpumask_t callmap; | 334 | cpumask_t callmap; |
@@ -326,17 +347,24 @@ void smp_send_stop(void) | |||
326 | int __cpuinit __cpu_up(unsigned int cpu) | 347 | int __cpuinit __cpu_up(unsigned int cpu) |
327 | { | 348 | { |
328 | int ret; | 349 | int ret; |
329 | static struct task_struct *idle; | 350 | struct blackfin_cpudata *ci = &per_cpu(cpu_data, cpu); |
351 | struct task_struct *idle = ci->idle; | ||
330 | 352 | ||
331 | if (idle) | 353 | if (idle) { |
332 | free_task(idle); | 354 | free_task(idle); |
333 | 355 | idle = NULL; | |
334 | idle = fork_idle(cpu); | ||
335 | if (IS_ERR(idle)) { | ||
336 | printk(KERN_ERR "CPU%u: fork() failed\n", cpu); | ||
337 | return PTR_ERR(idle); | ||
338 | } | 356 | } |
339 | 357 | ||
358 | if (!idle) { | ||
359 | idle = fork_idle(cpu); | ||
360 | if (IS_ERR(idle)) { | ||
361 | printk(KERN_ERR "CPU%u: fork() failed\n", cpu); | ||
362 | return PTR_ERR(idle); | ||
363 | } | ||
364 | ci->idle = idle; | ||
365 | } else { | ||
366 | init_idle(idle, cpu); | ||
367 | } | ||
340 | secondary_stack = task_stack_page(idle) + THREAD_SIZE; | 368 | secondary_stack = task_stack_page(idle) + THREAD_SIZE; |
341 | 369 | ||
342 | ret = platform_boot_secondary(cpu, idle); | 370 | ret = platform_boot_secondary(cpu, idle); |
@@ -411,6 +439,7 @@ void __cpuinit secondary_start_kernel(void) | |||
411 | 439 | ||
412 | bfin_setup_caches(cpu); | 440 | bfin_setup_caches(cpu); |
413 | 441 | ||
442 | notify_cpu_starting(cpu); | ||
414 | /* | 443 | /* |
415 | * Calibrate loops per jiffy value. | 444 | * Calibrate loops per jiffy value. |
416 | * IRQs need to be enabled here - D-cache can be invalidated | 445 | * IRQs need to be enabled here - D-cache can be invalidated |