Blackfin: SMP: disable preempt with smp_processor_id to send messages
[pandora-kernel.git] / arch / blackfin / mach-common / smp.c
1 /*
2  * IPI management based on arch/arm/kernel/smp.c (Copyright 2002 ARM Limited)
3  *
4  * Copyright 2007-2009 Analog Devices Inc.
5  *                         Philippe Gerum <rpm@xenomai.org>
6  *
7  * Licensed under the GPL-2.
8  */
9
10 #include <linux/module.h>
11 #include <linux/delay.h>
12 #include <linux/init.h>
13 #include <linux/spinlock.h>
14 #include <linux/sched.h>
15 #include <linux/interrupt.h>
16 #include <linux/cache.h>
17 #include <linux/profile.h>
18 #include <linux/errno.h>
19 #include <linux/mm.h>
20 #include <linux/cpu.h>
21 #include <linux/smp.h>
22 #include <linux/cpumask.h>
23 #include <linux/seq_file.h>
24 #include <linux/irq.h>
25 #include <linux/slab.h>
26 #include <asm/atomic.h>
27 #include <asm/cacheflush.h>
28 #include <asm/mmu_context.h>
29 #include <asm/pgtable.h>
30 #include <asm/pgalloc.h>
31 #include <asm/processor.h>
32 #include <asm/ptrace.h>
33 #include <asm/cpu.h>
34 #include <asm/time.h>
35 #include <linux/err.h>
36
37 /*
38  * Anomaly notes:
39  * 05000120 - we always define corelock as 32-bit integer in L2
40  */
41 struct corelock_slot corelock __attribute__ ((__section__(".l2.bss")));
42
43 void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb,
44         *init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb,
45         *init_saved_dcplb_fault_addr_coreb;
46
47 #define BFIN_IPI_RESCHEDULE   0
48 #define BFIN_IPI_CALL_FUNC    1
49 #define BFIN_IPI_CPU_STOP     2
50
51 struct blackfin_flush_data {
52         unsigned long start;
53         unsigned long end;
54 };
55
56 void *secondary_stack;
57
58
59 struct smp_call_struct {
60         void (*func)(void *info);
61         void *info;
62         int wait;
63         cpumask_t *waitmask;
64 };
65
66 static struct blackfin_flush_data smp_flush_data;
67
68 static DEFINE_SPINLOCK(stop_lock);
69
70 struct ipi_message {
71         unsigned long type;
72         struct smp_call_struct call_struct;
73 };
74
75 /* A magic number - stress test shows this is safe for common cases */
76 #define BFIN_IPI_MSGQ_LEN 5
77
78 /* Simple FIFO buffer, overflow leads to panic */
79 struct ipi_message_queue {
80         spinlock_t lock;
81         unsigned long count;
82         unsigned long head; /* head of the queue */
83         struct ipi_message ipi_message[BFIN_IPI_MSGQ_LEN];
84 };
85
86 static DEFINE_PER_CPU(struct ipi_message_queue, ipi_msg_queue);
87
88 static void ipi_cpu_stop(unsigned int cpu)
89 {
90         spin_lock(&stop_lock);
91         printk(KERN_CRIT "CPU%u: stopping\n", cpu);
92         dump_stack();
93         spin_unlock(&stop_lock);
94
95         cpu_clear(cpu, cpu_online_map);
96
97         local_irq_disable();
98
99         while (1)
100                 SSYNC();
101 }
102
103 static void ipi_flush_icache(void *info)
104 {
105         struct blackfin_flush_data *fdata = info;
106
107         /* Invalidate the memory holding the bounds of the flushed region. */
108         invalidate_dcache_range((unsigned long)fdata,
109                 (unsigned long)fdata + sizeof(*fdata));
110
111         flush_icache_range(fdata->start, fdata->end);
112 }
113
114 static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
115 {
116         int wait;
117         void (*func)(void *info);
118         void *info;
119         func = msg->call_struct.func;
120         info = msg->call_struct.info;
121         wait = msg->call_struct.wait;
122         func(info);
123         if (wait) {
124 #ifdef __ARCH_SYNC_CORE_DCACHE
125                 /*
126                  * 'wait' usually means synchronization between CPUs.
127                  * Invalidate D cache in case shared data was changed
128                  * by func() to ensure cache coherence.
129                  */
130                 resync_core_dcache();
131 #endif
132                 cpu_clear(cpu, *msg->call_struct.waitmask);
133         }
134 }
135
136 /* Use IRQ_SUPPLE_0 to request reschedule.
137  * When returning from interrupt to user space,
138  * there is chance to reschedule */
139 static irqreturn_t ipi_handler_int0(int irq, void *dev_instance)
140 {
141         unsigned int cpu = smp_processor_id();
142
143         platform_clear_ipi(cpu, IRQ_SUPPLE_0);
144         return IRQ_HANDLED;
145 }
146
147 static irqreturn_t ipi_handler_int1(int irq, void *dev_instance)
148 {
149         struct ipi_message *msg;
150         struct ipi_message_queue *msg_queue;
151         unsigned int cpu = smp_processor_id();
152         unsigned long flags;
153
154         platform_clear_ipi(cpu, IRQ_SUPPLE_1);
155
156         msg_queue = &__get_cpu_var(ipi_msg_queue);
157
158         spin_lock_irqsave(&msg_queue->lock, flags);
159
160         while (msg_queue->count) {
161                 msg = &msg_queue->ipi_message[msg_queue->head];
162                 switch (msg->type) {
163                 case BFIN_IPI_CALL_FUNC:
164                         spin_unlock_irqrestore(&msg_queue->lock, flags);
165                         ipi_call_function(cpu, msg);
166                         spin_lock_irqsave(&msg_queue->lock, flags);
167                         break;
168                 case BFIN_IPI_CPU_STOP:
169                         spin_unlock_irqrestore(&msg_queue->lock, flags);
170                         ipi_cpu_stop(cpu);
171                         spin_lock_irqsave(&msg_queue->lock, flags);
172                         break;
173                 default:
174                         printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n",
175                                cpu, msg->type);
176                         break;
177                 }
178                 msg_queue->head++;
179                 msg_queue->head %= BFIN_IPI_MSGQ_LEN;
180                 msg_queue->count--;
181         }
182         spin_unlock_irqrestore(&msg_queue->lock, flags);
183         return IRQ_HANDLED;
184 }
185
186 static void ipi_queue_init(void)
187 {
188         unsigned int cpu;
189         struct ipi_message_queue *msg_queue;
190         for_each_possible_cpu(cpu) {
191                 msg_queue = &per_cpu(ipi_msg_queue, cpu);
192                 spin_lock_init(&msg_queue->lock);
193                 msg_queue->count = 0;
194                 msg_queue->head = 0;
195         }
196 }
197
198 static inline void smp_send_message(cpumask_t callmap, unsigned long type,
199                                         void (*func) (void *info), void *info, int wait)
200 {
201         unsigned int cpu;
202         struct ipi_message_queue *msg_queue;
203         struct ipi_message *msg;
204         unsigned long flags, next_msg;
205         cpumask_t waitmask = callmap; /* waitmask is shared by all cpus */
206
207         for_each_cpu_mask(cpu, callmap) {
208                 msg_queue = &per_cpu(ipi_msg_queue, cpu);
209                 spin_lock_irqsave(&msg_queue->lock, flags);
210                 if (msg_queue->count < BFIN_IPI_MSGQ_LEN) {
211                         next_msg = (msg_queue->head + msg_queue->count)
212                                         % BFIN_IPI_MSGQ_LEN;
213                         msg = &msg_queue->ipi_message[next_msg];
214                         msg->type = type;
215                         if (type == BFIN_IPI_CALL_FUNC) {
216                                 msg->call_struct.func = func;
217                                 msg->call_struct.info = info;
218                                 msg->call_struct.wait = wait;
219                                 msg->call_struct.waitmask = &waitmask;
220                         }
221                         msg_queue->count++;
222                 } else
223                         panic("IPI message queue overflow\n");
224                 spin_unlock_irqrestore(&msg_queue->lock, flags);
225                 platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1);
226         }
227
228         if (wait) {
229                 while (!cpus_empty(waitmask))
230                         blackfin_dcache_invalidate_range(
231                                 (unsigned long)(&waitmask),
232                                 (unsigned long)(&waitmask));
233 #ifdef __ARCH_SYNC_CORE_DCACHE
234                 /*
235                  * Invalidate D cache in case shared data was changed by
236                  * other processors to ensure cache coherence.
237                  */
238                 resync_core_dcache();
239 #endif
240         }
241 }
242
243 int smp_call_function(void (*func)(void *info), void *info, int wait)
244 {
245         cpumask_t callmap;
246
247         preempt_disable();
248         callmap = cpu_online_map;
249         cpu_clear(smp_processor_id(), callmap);
250         if (!cpus_empty(callmap))
251                 smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
252
253         preempt_enable();
254
255         return 0;
256 }
257 EXPORT_SYMBOL_GPL(smp_call_function);
258
259 int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
260                                 int wait)
261 {
262         unsigned int cpu = cpuid;
263         cpumask_t callmap;
264
265         if (cpu_is_offline(cpu))
266                 return 0;
267         cpus_clear(callmap);
268         cpu_set(cpu, callmap);
269
270         smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
271
272         return 0;
273 }
274 EXPORT_SYMBOL_GPL(smp_call_function_single);
275
276 void smp_send_reschedule(int cpu)
277 {
278         /* simply trigger an ipi */
279         if (cpu_is_offline(cpu))
280                 return;
281         platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
282
283         return;
284 }
285
286 void smp_send_stop(void)
287 {
288         cpumask_t callmap;
289
290         preempt_disable();
291         callmap = cpu_online_map;
292         cpu_clear(smp_processor_id(), callmap);
293         if (!cpus_empty(callmap))
294                 smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0);
295
296         preempt_enable();
297
298         return;
299 }
300
301 int __cpuinit __cpu_up(unsigned int cpu)
302 {
303         int ret;
304         static struct task_struct *idle;
305
306         if (idle)
307                 free_task(idle);
308
309         idle = fork_idle(cpu);
310         if (IS_ERR(idle)) {
311                 printk(KERN_ERR "CPU%u: fork() failed\n", cpu);
312                 return PTR_ERR(idle);
313         }
314
315         secondary_stack = task_stack_page(idle) + THREAD_SIZE;
316
317         ret = platform_boot_secondary(cpu, idle);
318
319         secondary_stack = NULL;
320
321         return ret;
322 }
323
324 static void __cpuinit setup_secondary(unsigned int cpu)
325 {
326         unsigned long ilat;
327
328         bfin_write_IMASK(0);
329         CSYNC();
330         ilat = bfin_read_ILAT();
331         CSYNC();
332         bfin_write_ILAT(ilat);
333         CSYNC();
334
335         /* Enable interrupt levels IVG7-15. IARs have been already
336          * programmed by the boot CPU.  */
337         bfin_irq_flags |= IMASK_IVG15 |
338             IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
339             IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
340 }
341
342 void __cpuinit secondary_start_kernel(void)
343 {
344         unsigned int cpu = smp_processor_id();
345         struct mm_struct *mm = &init_mm;
346
347         if (_bfin_swrst & SWRST_DBL_FAULT_B) {
348                 printk(KERN_EMERG "CoreB Recovering from DOUBLE FAULT event\n");
349 #ifdef CONFIG_DEBUG_DOUBLEFAULT
350                 printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n",
351                         (int)init_saved_seqstat_coreb & SEQSTAT_EXCAUSE, init_saved_retx_coreb);
352                 printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr_coreb);
353                 printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr_coreb);
354 #endif
355                 printk(KERN_NOTICE " The instruction at %pF caused a double exception\n",
356                         init_retx_coreb);
357         }
358
359         /*
360          * We want the D-cache to be enabled early, in case the atomic
361          * support code emulates cache coherence (see
362          * __ARCH_SYNC_CORE_DCACHE).
363          */
364         init_exception_vectors();
365
366         local_irq_disable();
367
368         /* Attach the new idle task to the global mm. */
369         atomic_inc(&mm->mm_users);
370         atomic_inc(&mm->mm_count);
371         current->active_mm = mm;
372
373         preempt_disable();
374
375         setup_secondary(cpu);
376
377         platform_secondary_init(cpu);
378
379         /* setup local core timer */
380         bfin_local_timer_setup();
381
382         local_irq_enable();
383
384         bfin_setup_caches(cpu);
385
386         /*
387          * Calibrate loops per jiffy value.
388          * IRQs need to be enabled here - D-cache can be invalidated
389          * in timer irq handler, so core B can read correct jiffies.
390          */
391         calibrate_delay();
392
393         cpu_idle();
394 }
395
396 void __init smp_prepare_boot_cpu(void)
397 {
398 }
399
400 void __init smp_prepare_cpus(unsigned int max_cpus)
401 {
402         platform_prepare_cpus(max_cpus);
403         ipi_queue_init();
404         platform_request_ipi(IRQ_SUPPLE_0, ipi_handler_int0);
405         platform_request_ipi(IRQ_SUPPLE_1, ipi_handler_int1);
406 }
407
408 void __init smp_cpus_done(unsigned int max_cpus)
409 {
410         unsigned long bogosum = 0;
411         unsigned int cpu;
412
413         for_each_online_cpu(cpu)
414                 bogosum += loops_per_jiffy;
415
416         printk(KERN_INFO "SMP: Total of %d processors activated "
417                "(%lu.%02lu BogoMIPS).\n",
418                num_online_cpus(),
419                bogosum / (500000/HZ),
420                (bogosum / (5000/HZ)) % 100);
421 }
422
423 void smp_icache_flush_range_others(unsigned long start, unsigned long end)
424 {
425         smp_flush_data.start = start;
426         smp_flush_data.end = end;
427
428         if (smp_call_function(&ipi_flush_icache, &smp_flush_data, 0))
429                 printk(KERN_WARNING "SMP: failed to run I-cache flush request on other CPUs\n");
430 }
431 EXPORT_SYMBOL_GPL(smp_icache_flush_range_others);
432
433 #ifdef __ARCH_SYNC_CORE_ICACHE
434 unsigned long icache_invld_count[NR_CPUS];
435 void resync_core_icache(void)
436 {
437         unsigned int cpu = get_cpu();
438         blackfin_invalidate_entire_icache();
439         icache_invld_count[cpu]++;
440         put_cpu();
441 }
442 EXPORT_SYMBOL(resync_core_icache);
443 #endif
444
445 #ifdef __ARCH_SYNC_CORE_DCACHE
446 unsigned long dcache_invld_count[NR_CPUS];
447 unsigned long barrier_mask __attribute__ ((__section__(".l2.bss")));
448
449 void resync_core_dcache(void)
450 {
451         unsigned int cpu = get_cpu();
452         blackfin_invalidate_entire_dcache();
453         dcache_invld_count[cpu]++;
454         put_cpu();
455 }
456 EXPORT_SYMBOL(resync_core_dcache);
457 #endif
458
459 #ifdef CONFIG_HOTPLUG_CPU
460 int __cpuexit __cpu_disable(void)
461 {
462         unsigned int cpu = smp_processor_id();
463
464         if (cpu == 0)
465                 return -EPERM;
466
467         set_cpu_online(cpu, false);
468         return 0;
469 }
470
471 static DECLARE_COMPLETION(cpu_killed);
472
473 int __cpuexit __cpu_die(unsigned int cpu)
474 {
475         return wait_for_completion_timeout(&cpu_killed, 5000);
476 }
477
478 void cpu_die(void)
479 {
480         complete(&cpu_killed);
481
482         atomic_dec(&init_mm.mm_users);
483         atomic_dec(&init_mm.mm_count);
484
485         local_irq_disable();
486         platform_cpu_die();
487 }
488 #endif