diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-01-13 10:00:22 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-01-13 10:00:22 -0500 |
commit | 4de3a8e101150feaefa1139611a50ff37467f33e (patch) | |
tree | daada742542518b02d7db7c5d32e715eaa5f166d /arch/blackfin/mach-common/smp.c | |
parent | 294064f58953f9964e5945424b09c51800330a83 (diff) | |
parent | 099469502f62fbe0d7e4f0b83a2f22538367f734 (diff) |
Merge branch 'master' into fixes
Diffstat (limited to 'arch/blackfin/mach-common/smp.c')
-rw-r--r-- | arch/blackfin/mach-common/smp.c | 61 |
1 files changed, 44 insertions, 17 deletions
diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index 0784a52389c8..ac8f8a43158c 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,18 +186,17 @@ 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; |
182 | case BFIN_IPI_CALL_FUNC: | 195 | case BFIN_IPI_CALL_FUNC: |
183 | spin_unlock_irqrestore(&msg_queue->lock, flags); | ||
184 | ipi_call_function(cpu, msg); | 196 | ipi_call_function(cpu, msg); |
185 | spin_lock_irqsave(&msg_queue->lock, flags); | ||
186 | break; | 197 | break; |
187 | case BFIN_IPI_CPU_STOP: | 198 | case BFIN_IPI_CPU_STOP: |
188 | spin_unlock_irqrestore(&msg_queue->lock, flags); | ||
189 | ipi_cpu_stop(cpu); | 199 | ipi_cpu_stop(cpu); |
190 | spin_lock_irqsave(&msg_queue->lock, flags); | ||
191 | break; | 200 | break; |
192 | default: | 201 | default: |
193 | printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n", | 202 | printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n", |
@@ -297,8 +306,6 @@ void smp_send_reschedule(int cpu) | |||
297 | { | 306 | { |
298 | cpumask_t callmap; | 307 | cpumask_t callmap; |
299 | /* simply trigger an ipi */ | 308 | /* simply trigger an ipi */ |
300 | if (cpu_is_offline(cpu)) | ||
301 | return; | ||
302 | 309 | ||
303 | cpumask_clear(&callmap); | 310 | cpumask_clear(&callmap); |
304 | cpumask_set_cpu(cpu, &callmap); | 311 | cpumask_set_cpu(cpu, &callmap); |
@@ -308,6 +315,16 @@ void smp_send_reschedule(int cpu) | |||
308 | return; | 315 | return; |
309 | } | 316 | } |
310 | 317 | ||
318 | void smp_send_msg(const struct cpumask *mask, unsigned long type) | ||
319 | { | ||
320 | smp_send_message(*mask, type, NULL, NULL, 0); | ||
321 | } | ||
322 | |||
323 | void smp_timer_broadcast(const struct cpumask *mask) | ||
324 | { | ||
325 | smp_send_msg(mask, BFIN_IPI_TIMER); | ||
326 | } | ||
327 | |||
311 | void smp_send_stop(void) | 328 | void smp_send_stop(void) |
312 | { | 329 | { |
313 | cpumask_t callmap; | 330 | cpumask_t callmap; |
@@ -326,17 +343,24 @@ void smp_send_stop(void) | |||
326 | int __cpuinit __cpu_up(unsigned int cpu) | 343 | int __cpuinit __cpu_up(unsigned int cpu) |
327 | { | 344 | { |
328 | int ret; | 345 | int ret; |
329 | static struct task_struct *idle; | 346 | struct blackfin_cpudata *ci = &per_cpu(cpu_data, cpu); |
347 | struct task_struct *idle = ci->idle; | ||
330 | 348 | ||
331 | if (idle) | 349 | if (idle) { |
332 | free_task(idle); | 350 | free_task(idle); |
333 | 351 | 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 | } | 352 | } |
339 | 353 | ||
354 | if (!idle) { | ||
355 | idle = fork_idle(cpu); | ||
356 | if (IS_ERR(idle)) { | ||
357 | printk(KERN_ERR "CPU%u: fork() failed\n", cpu); | ||
358 | return PTR_ERR(idle); | ||
359 | } | ||
360 | ci->idle = idle; | ||
361 | } else { | ||
362 | init_idle(idle, cpu); | ||
363 | } | ||
340 | secondary_stack = task_stack_page(idle) + THREAD_SIZE; | 364 | secondary_stack = task_stack_page(idle) + THREAD_SIZE; |
341 | 365 | ||
342 | ret = platform_boot_secondary(cpu, idle); | 366 | ret = platform_boot_secondary(cpu, idle); |
@@ -411,6 +435,7 @@ void __cpuinit secondary_start_kernel(void) | |||
411 | 435 | ||
412 | bfin_setup_caches(cpu); | 436 | bfin_setup_caches(cpu); |
413 | 437 | ||
438 | notify_cpu_starting(cpu); | ||
414 | /* | 439 | /* |
415 | * Calibrate loops per jiffy value. | 440 | * Calibrate loops per jiffy value. |
416 | * IRQs need to be enabled here - D-cache can be invalidated | 441 | * IRQs need to be enabled here - D-cache can be invalidated |
@@ -453,8 +478,10 @@ void smp_icache_flush_range_others(unsigned long start, unsigned long end) | |||
453 | smp_flush_data.start = start; | 478 | smp_flush_data.start = start; |
454 | smp_flush_data.end = end; | 479 | smp_flush_data.end = end; |
455 | 480 | ||
456 | if (smp_call_function(&ipi_flush_icache, &smp_flush_data, 0)) | 481 | preempt_disable(); |
482 | if (smp_call_function(&ipi_flush_icache, &smp_flush_data, 1)) | ||
457 | printk(KERN_WARNING "SMP: failed to run I-cache flush request on other CPUs\n"); | 483 | printk(KERN_WARNING "SMP: failed to run I-cache flush request on other CPUs\n"); |
484 | preempt_enable(); | ||
458 | } | 485 | } |
459 | EXPORT_SYMBOL_GPL(smp_icache_flush_range_others); | 486 | EXPORT_SYMBOL_GPL(smp_icache_flush_range_others); |
460 | 487 | ||