Blame view

arch/blackfin/mach-common/smp.c 12.5 KB
6b3087c64   Graf Yang   Blackfin arch: SM...
1
  /*
96f1050d3   Robin Getz   Blackfin: mass cl...
2
   * IPI management based on arch/arm/kernel/smp.c (Copyright 2002 ARM Limited)
6b3087c64   Graf Yang   Blackfin arch: SM...
3
   *
96f1050d3   Robin Getz   Blackfin: mass cl...
4
5
   * Copyright 2007-2009 Analog Devices Inc.
   *                         Philippe Gerum <rpm@xenomai.org>
6b3087c64   Graf Yang   Blackfin arch: SM...
6
   *
96f1050d3   Robin Getz   Blackfin: mass cl...
7
   * Licensed under the GPL-2.
6b3087c64   Graf Yang   Blackfin arch: SM...
8
9
10
11
12
13
14
15
16
   */
  
  #include <linux/module.h>
  #include <linux/delay.h>
  #include <linux/init.h>
  #include <linux/spinlock.h>
  #include <linux/sched.h>
  #include <linux/interrupt.h>
  #include <linux/cache.h>
d0014be47   Bob Liu   blackfin: smp: cl...
17
  #include <linux/clockchips.h>
6b3087c64   Graf Yang   Blackfin arch: SM...
18
19
20
21
22
  #include <linux/profile.h>
  #include <linux/errno.h>
  #include <linux/mm.h>
  #include <linux/cpu.h>
  #include <linux/smp.h>
9c199b596   Graf Yang   Blackfin: SMP: fi...
23
  #include <linux/cpumask.h>
6b3087c64   Graf Yang   Blackfin arch: SM...
24
25
  #include <linux/seq_file.h>
  #include <linux/irq.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
26
  #include <linux/slab.h>
60063497a   Arun Sharma   atomic: use <linu...
27
  #include <linux/atomic.h>
6b3087c64   Graf Yang   Blackfin arch: SM...
28
  #include <asm/cacheflush.h>
6327a574f   Mike Frysinger   Blackfin: move in...
29
  #include <asm/irq_handler.h>
6b3087c64   Graf Yang   Blackfin arch: SM...
30
31
32
33
34
35
  #include <asm/mmu_context.h>
  #include <asm/pgtable.h>
  #include <asm/pgalloc.h>
  #include <asm/processor.h>
  #include <asm/ptrace.h>
  #include <asm/cpu.h>
1fa9be72b   Graf Yang   Blackfin: add sup...
36
  #include <asm/time.h>
6b3087c64   Graf Yang   Blackfin arch: SM...
37
  #include <linux/err.h>
555487bbb   Graf Yang   Blackfin: annotat...
38
39
40
41
  /*
   * Anomaly notes:
   * 05000120 - we always define corelock as 32-bit integer in L2
   */
6b3087c64   Graf Yang   Blackfin arch: SM...
42
  struct corelock_slot corelock __attribute__ ((__section__(".l2.bss")));
c6345ab1a   Sonic Zhang   Blackfin: SMP: wo...
43
44
45
  #ifdef CONFIG_ICACHE_FLUSH_L1
  unsigned long blackfin_iflush_l1_entry[NR_CPUS];
  #endif
fb1d9be59   Mike Frysinger   Blackfin: optimiz...
46
  struct blackfin_initial_pda __cpuinitdata initial_pda_coreb;
6b3087c64   Graf Yang   Blackfin arch: SM...
47

d0014be47   Bob Liu   blackfin: smp: cl...
48
49
50
51
  #define BFIN_IPI_TIMER	      0
  #define BFIN_IPI_RESCHEDULE   1
  #define BFIN_IPI_CALL_FUNC    2
  #define BFIN_IPI_CPU_STOP     3
6b3087c64   Graf Yang   Blackfin arch: SM...
52
53
54
55
56
57
58
59
60
61
62
63
64
  
  struct blackfin_flush_data {
  	unsigned long start;
  	unsigned long end;
  };
  
  void *secondary_stack;
  
  
  struct smp_call_struct {
  	void (*func)(void *info);
  	void *info;
  	int wait;
73a400646   Yi Li   Blackfin: SMP: re...
65
  	cpumask_t *waitmask;
6b3087c64   Graf Yang   Blackfin arch: SM...
66
67
68
69
70
71
72
  };
  
  static struct blackfin_flush_data smp_flush_data;
  
  static DEFINE_SPINLOCK(stop_lock);
  
  struct ipi_message {
6b3087c64   Graf Yang   Blackfin arch: SM...
73
74
75
  	unsigned long type;
  	struct smp_call_struct call_struct;
  };
73a400646   Yi Li   Blackfin: SMP: re...
76
77
78
79
  /* A magic number - stress test shows this is safe for common cases */
  #define BFIN_IPI_MSGQ_LEN 5
  
  /* Simple FIFO buffer, overflow leads to panic */
6b3087c64   Graf Yang   Blackfin arch: SM...
80
  struct ipi_message_queue {
6b3087c64   Graf Yang   Blackfin arch: SM...
81
82
  	spinlock_t lock;
  	unsigned long count;
73a400646   Yi Li   Blackfin: SMP: re...
83
84
  	unsigned long head; /* head of the queue */
  	struct ipi_message ipi_message[BFIN_IPI_MSGQ_LEN];
6b3087c64   Graf Yang   Blackfin arch: SM...
85
86
87
88
89
90
91
92
93
94
95
  };
  
  static DEFINE_PER_CPU(struct ipi_message_queue, ipi_msg_queue);
  
  static void ipi_cpu_stop(unsigned int cpu)
  {
  	spin_lock(&stop_lock);
  	printk(KERN_CRIT "CPU%u: stopping
  ", cpu);
  	dump_stack();
  	spin_unlock(&stop_lock);
fecedc807   KOSAKI Motohiro   Blackfin: convert...
96
  	set_cpu_online(cpu, false);
6b3087c64   Graf Yang   Blackfin arch: SM...
97
98
99
100
101
102
103
104
105
106
107
108
  
  	local_irq_disable();
  
  	while (1)
  		SSYNC();
  }
  
  static void ipi_flush_icache(void *info)
  {
  	struct blackfin_flush_data *fdata = info;
  
  	/* Invalidate the memory holding the bounds of the flushed region. */
8d50de9ee   Sonic Zhang   Blackfin: SMP: fi...
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
  	blackfin_dcache_invalidate_range((unsigned long)fdata,
  					 (unsigned long)fdata + sizeof(*fdata));
  
  	/* Make sure all write buffers in the data side of the core
  	 * are flushed before trying to invalidate the icache.  This
  	 * needs to be after the data flush and before the icache
  	 * flush so that the SSYNC does the right thing in preventing
  	 * the instruction prefetcher from hitting things in cached
  	 * memory at the wrong time -- it runs much further ahead than
  	 * the pipeline.
  	 */
  	SSYNC();
  
  	/* ipi_flaush_icache is invoked by generic flush_icache_range,
  	 * so call blackfin arch icache flush directly here.
  	 */
  	blackfin_icache_flush_range(fdata->start, fdata->end);
6b3087c64   Graf Yang   Blackfin arch: SM...
126
127
128
129
130
131
132
133
134
135
  }
  
  static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
  {
  	int wait;
  	void (*func)(void *info);
  	void *info;
  	func = msg->call_struct.func;
  	info = msg->call_struct.info;
  	wait = msg->call_struct.wait;
6b3087c64   Graf Yang   Blackfin arch: SM...
136
  	func(info);
c9784ebb2   Yi Li   Blackfin: flush c...
137
138
139
140
141
142
143
144
145
  	if (wait) {
  #ifdef __ARCH_SYNC_CORE_DCACHE
  		/*
  		 * 'wait' usually means synchronization between CPUs.
  		 * Invalidate D cache in case shared data was changed
  		 * by func() to ensure cache coherence.
  		 */
  		resync_core_dcache();
  #endif
fecedc807   KOSAKI Motohiro   Blackfin: convert...
146
  		cpumask_clear_cpu(cpu, msg->call_struct.waitmask);
73a400646   Yi Li   Blackfin: SMP: re...
147
  	}
6b3087c64   Graf Yang   Blackfin arch: SM...
148
  }
73a400646   Yi Li   Blackfin: SMP: re...
149
150
151
152
153
154
155
156
157
158
  /* Use IRQ_SUPPLE_0 to request reschedule.
   * When returning from interrupt to user space,
   * there is chance to reschedule */
  static irqreturn_t ipi_handler_int0(int irq, void *dev_instance)
  {
  	unsigned int cpu = smp_processor_id();
  
  	platform_clear_ipi(cpu, IRQ_SUPPLE_0);
  	return IRQ_HANDLED;
  }
d0014be47   Bob Liu   blackfin: smp: cl...
159
160
161
162
163
164
165
  DECLARE_PER_CPU(struct clock_event_device, coretmr_events);
  void ipi_timer(void)
  {
  	int cpu = smp_processor_id();
  	struct clock_event_device *evt = &per_cpu(coretmr_events, cpu);
  	evt->event_handler(evt);
  }
73a400646   Yi Li   Blackfin: SMP: re...
166
  static irqreturn_t ipi_handler_int1(int irq, void *dev_instance)
6b3087c64   Graf Yang   Blackfin arch: SM...
167
  {
86f2008bf   Sonic Zhang   Blackfin: fix dea...
168
  	struct ipi_message *msg;
6b3087c64   Graf Yang   Blackfin arch: SM...
169
170
  	struct ipi_message_queue *msg_queue;
  	unsigned int cpu = smp_processor_id();
73a400646   Yi Li   Blackfin: SMP: re...
171
  	unsigned long flags;
6b3087c64   Graf Yang   Blackfin arch: SM...
172

73a400646   Yi Li   Blackfin: SMP: re...
173
  	platform_clear_ipi(cpu, IRQ_SUPPLE_1);
6b3087c64   Graf Yang   Blackfin arch: SM...
174
175
  
  	msg_queue = &__get_cpu_var(ipi_msg_queue);
6b3087c64   Graf Yang   Blackfin arch: SM...
176

73a400646   Yi Li   Blackfin: SMP: re...
177
178
179
180
  	spin_lock_irqsave(&msg_queue->lock, flags);
  
  	while (msg_queue->count) {
  		msg = &msg_queue->ipi_message[msg_queue->head];
6b3087c64   Graf Yang   Blackfin arch: SM...
181
  		switch (msg->type) {
d0014be47   Bob Liu   blackfin: smp: cl...
182
183
184
  		case BFIN_IPI_TIMER:
  			ipi_timer();
  			break;
184748cc5   Peter Zijlstra   sched: Provide sc...
185
186
187
  		case BFIN_IPI_RESCHEDULE:
  			scheduler_ipi();
  			break;
6b3087c64   Graf Yang   Blackfin arch: SM...
188
189
190
191
192
  		case BFIN_IPI_CALL_FUNC:
  			ipi_call_function(cpu, msg);
  			break;
  		case BFIN_IPI_CPU_STOP:
  			ipi_cpu_stop(cpu);
6b3087c64   Graf Yang   Blackfin arch: SM...
193
194
  			break;
  		default:
db52ecc29   Joe Perches   Blackfin: SMP: fi...
195
196
197
  			printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx
  ",
  			       cpu, msg->type);
6b3087c64   Graf Yang   Blackfin arch: SM...
198
199
  			break;
  		}
73a400646   Yi Li   Blackfin: SMP: re...
200
201
202
  		msg_queue->head++;
  		msg_queue->head %= BFIN_IPI_MSGQ_LEN;
  		msg_queue->count--;
6b3087c64   Graf Yang   Blackfin arch: SM...
203
  	}
73a400646   Yi Li   Blackfin: SMP: re...
204
  	spin_unlock_irqrestore(&msg_queue->lock, flags);
6b3087c64   Graf Yang   Blackfin arch: SM...
205
206
207
208
209
210
211
212
213
  	return IRQ_HANDLED;
  }
  
  static void ipi_queue_init(void)
  {
  	unsigned int cpu;
  	struct ipi_message_queue *msg_queue;
  	for_each_possible_cpu(cpu) {
  		msg_queue = &per_cpu(ipi_msg_queue, cpu);
6b3087c64   Graf Yang   Blackfin arch: SM...
214
215
  		spin_lock_init(&msg_queue->lock);
  		msg_queue->count = 0;
73a400646   Yi Li   Blackfin: SMP: re...
216
  		msg_queue->head = 0;
6b3087c64   Graf Yang   Blackfin arch: SM...
217
218
  	}
  }
73a400646   Yi Li   Blackfin: SMP: re...
219
220
  static inline void smp_send_message(cpumask_t callmap, unsigned long type,
  					void (*func) (void *info), void *info, int wait)
6b3087c64   Graf Yang   Blackfin arch: SM...
221
222
  {
  	unsigned int cpu;
6b3087c64   Graf Yang   Blackfin arch: SM...
223
224
  	struct ipi_message_queue *msg_queue;
  	struct ipi_message *msg;
73a400646   Yi Li   Blackfin: SMP: re...
225
  	unsigned long flags, next_msg;
fecedc807   KOSAKI Motohiro   Blackfin: convert...
226
  	cpumask_t waitmask; /* waitmask is shared by all cpus */
6b3087c64   Graf Yang   Blackfin arch: SM...
227

fecedc807   KOSAKI Motohiro   Blackfin: convert...
228
229
  	cpumask_copy(&waitmask, &callmap);
  	for_each_cpu(cpu, &callmap) {
6b3087c64   Graf Yang   Blackfin arch: SM...
230
231
  		msg_queue = &per_cpu(ipi_msg_queue, cpu);
  		spin_lock_irqsave(&msg_queue->lock, flags);
73a400646   Yi Li   Blackfin: SMP: re...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
  		if (msg_queue->count < BFIN_IPI_MSGQ_LEN) {
  			next_msg = (msg_queue->head + msg_queue->count)
  					% BFIN_IPI_MSGQ_LEN;
  			msg = &msg_queue->ipi_message[next_msg];
  			msg->type = type;
  			if (type == BFIN_IPI_CALL_FUNC) {
  				msg->call_struct.func = func;
  				msg->call_struct.info = info;
  				msg->call_struct.wait = wait;
  				msg->call_struct.waitmask = &waitmask;
  			}
  			msg_queue->count++;
  		} else
  			panic("IPI message queue overflow
  ");
6b3087c64   Graf Yang   Blackfin arch: SM...
247
  		spin_unlock_irqrestore(&msg_queue->lock, flags);
73a400646   Yi Li   Blackfin: SMP: re...
248
  		platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1);
6b3087c64   Graf Yang   Blackfin arch: SM...
249
  	}
73a400646   Yi Li   Blackfin: SMP: re...
250

6b3087c64   Graf Yang   Blackfin arch: SM...
251
  	if (wait) {
fecedc807   KOSAKI Motohiro   Blackfin: convert...
252
  		while (!cpumask_empty(&waitmask))
6b3087c64   Graf Yang   Blackfin arch: SM...
253
  			blackfin_dcache_invalidate_range(
73a400646   Yi Li   Blackfin: SMP: re...
254
255
  				(unsigned long)(&waitmask),
  				(unsigned long)(&waitmask));
c9784ebb2   Yi Li   Blackfin: flush c...
256
257
258
259
260
261
262
  #ifdef __ARCH_SYNC_CORE_DCACHE
  		/*
  		 * Invalidate D cache in case shared data was changed by
  		 * other processors to ensure cache coherence.
  		 */
  		resync_core_dcache();
  #endif
6b3087c64   Graf Yang   Blackfin arch: SM...
263
  	}
73a400646   Yi Li   Blackfin: SMP: re...
264
265
266
267
268
  }
  
  int smp_call_function(void (*func)(void *info), void *info, int wait)
  {
  	cpumask_t callmap;
567ebfc99   Sonic Zhang   Blackfin: SMP: di...
269
  	preempt_disable();
fecedc807   KOSAKI Motohiro   Blackfin: convert...
270
271
272
  	cpumask_copy(&callmap, cpu_online_mask);
  	cpumask_clear_cpu(smp_processor_id(), &callmap);
  	if (!cpumask_empty(&callmap))
567ebfc99   Sonic Zhang   Blackfin: SMP: di...
273
  		smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
73a400646   Yi Li   Blackfin: SMP: re...
274

567ebfc99   Sonic Zhang   Blackfin: SMP: di...
275
  	preempt_enable();
73a400646   Yi Li   Blackfin: SMP: re...
276

6b3087c64   Graf Yang   Blackfin arch: SM...
277
278
279
280
281
282
283
284
285
  	return 0;
  }
  EXPORT_SYMBOL_GPL(smp_call_function);
  
  int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
  				int wait)
  {
  	unsigned int cpu = cpuid;
  	cpumask_t callmap;
6b3087c64   Graf Yang   Blackfin arch: SM...
286
287
288
  
  	if (cpu_is_offline(cpu))
  		return 0;
fecedc807   KOSAKI Motohiro   Blackfin: convert...
289
290
  	cpumask_clear(&callmap);
  	cpumask_set_cpu(cpu, &callmap);
6b3087c64   Graf Yang   Blackfin arch: SM...
291

73a400646   Yi Li   Blackfin: SMP: re...
292
  	smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
6b3087c64   Graf Yang   Blackfin arch: SM...
293

6b3087c64   Graf Yang   Blackfin arch: SM...
294
295
296
297
298
299
  	return 0;
  }
  EXPORT_SYMBOL_GPL(smp_call_function_single);
  
  void smp_send_reschedule(int cpu)
  {
0b2b06efd   Steven Miao   Blackfin: SMP: fi...
300
  	cpumask_t callmap;
73a400646   Yi Li   Blackfin: SMP: re...
301
  	/* simply trigger an ipi */
0b2b06efd   Steven Miao   Blackfin: SMP: fi...
302
303
304
305
306
  
  	cpumask_clear(&callmap);
  	cpumask_set_cpu(cpu, &callmap);
  
  	smp_send_message(callmap, BFIN_IPI_RESCHEDULE, NULL, NULL, 0);
6b3087c64   Graf Yang   Blackfin arch: SM...
307
308
309
  
  	return;
  }
d0014be47   Bob Liu   blackfin: smp: cl...
310
311
312
313
314
315
316
317
318
  void smp_send_msg(const struct cpumask *mask, unsigned long type)
  {
  	smp_send_message(*mask, type, NULL, NULL, 0);
  }
  
  void smp_timer_broadcast(const struct cpumask *mask)
  {
  	smp_send_msg(mask, BFIN_IPI_TIMER);
  }
6b3087c64   Graf Yang   Blackfin arch: SM...
319
320
  void smp_send_stop(void)
  {
6b3087c64   Graf Yang   Blackfin arch: SM...
321
  	cpumask_t callmap;
6b3087c64   Graf Yang   Blackfin arch: SM...
322

567ebfc99   Sonic Zhang   Blackfin: SMP: di...
323
  	preempt_disable();
fecedc807   KOSAKI Motohiro   Blackfin: convert...
324
325
326
  	cpumask_copy(&callmap, cpu_online_mask);
  	cpumask_clear_cpu(smp_processor_id(), &callmap);
  	if (!cpumask_empty(&callmap))
567ebfc99   Sonic Zhang   Blackfin: SMP: di...
327
  		smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0);
6b3087c64   Graf Yang   Blackfin arch: SM...
328

567ebfc99   Sonic Zhang   Blackfin: SMP: di...
329
  	preempt_enable();
6b3087c64   Graf Yang   Blackfin arch: SM...
330

6b3087c64   Graf Yang   Blackfin arch: SM...
331
332
333
334
335
  	return;
  }
  
  int __cpuinit __cpu_up(unsigned int cpu)
  {
6b3087c64   Graf Yang   Blackfin arch: SM...
336
  	int ret;
d0014be47   Bob Liu   blackfin: smp: cl...
337
338
  	struct blackfin_cpudata *ci = &per_cpu(cpu_data, cpu);
  	struct task_struct *idle = ci->idle;
0b39db28b   Graf Yang   Blackfin: SMP: ad...
339

d0014be47   Bob Liu   blackfin: smp: cl...
340
  	if (idle) {
0b39db28b   Graf Yang   Blackfin: SMP: ad...
341
  		free_task(idle);
d0014be47   Bob Liu   blackfin: smp: cl...
342
  		idle = NULL;
6b3087c64   Graf Yang   Blackfin arch: SM...
343
  	}
d0014be47   Bob Liu   blackfin: smp: cl...
344
345
346
347
348
349
350
351
352
353
354
  	if (!idle) {
  		idle = fork_idle(cpu);
  		if (IS_ERR(idle)) {
  			printk(KERN_ERR "CPU%u: fork() failed
  ", cpu);
  			return PTR_ERR(idle);
  		}
  		ci->idle = idle;
  	} else {
  		init_idle(idle, cpu);
  	}
6b3087c64   Graf Yang   Blackfin arch: SM...
355
  	secondary_stack = task_stack_page(idle) + THREAD_SIZE;
6b3087c64   Graf Yang   Blackfin arch: SM...
356
357
  
  	ret = platform_boot_secondary(cpu, idle);
6b3087c64   Graf Yang   Blackfin arch: SM...
358
359
360
361
362
363
364
  	secondary_stack = NULL;
  
  	return ret;
  }
  
  static void __cpuinit setup_secondary(unsigned int cpu)
  {
6b3087c64   Graf Yang   Blackfin arch: SM...
365
366
367
368
369
370
371
372
  	unsigned long ilat;
  
  	bfin_write_IMASK(0);
  	CSYNC();
  	ilat = bfin_read_ILAT();
  	CSYNC();
  	bfin_write_ILAT(ilat);
  	CSYNC();
6b3087c64   Graf Yang   Blackfin arch: SM...
373
374
  	/* Enable interrupt levels IVG7-15. IARs have been already
  	 * programmed by the boot CPU.  */
400597842   Mike Frysinger   Blackfin arch: re...
375
  	bfin_irq_flags |= IMASK_IVG15 |
6b3087c64   Graf Yang   Blackfin arch: SM...
376
377
  	    IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
  	    IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
6b3087c64   Graf Yang   Blackfin arch: SM...
378
379
380
381
382
383
384
385
386
387
388
  }
  
  void __cpuinit secondary_start_kernel(void)
  {
  	unsigned int cpu = smp_processor_id();
  	struct mm_struct *mm = &init_mm;
  
  	if (_bfin_swrst & SWRST_DBL_FAULT_B) {
  		printk(KERN_EMERG "CoreB Recovering from DOUBLE FAULT event
  ");
  #ifdef CONFIG_DEBUG_DOUBLEFAULT
fb1d9be59   Mike Frysinger   Blackfin: optimiz...
389
390
391
392
393
394
395
396
397
398
  		printk(KERN_EMERG " While handling exception (EXCAUSE = %#x) at %pF
  ",
  			initial_pda_coreb.seqstat_doublefault & SEQSTAT_EXCAUSE,
  			initial_pda_coreb.retx_doublefault);
  		printk(KERN_NOTICE "   DCPLB_FAULT_ADDR: %pF
  ",
  			initial_pda_coreb.dcplb_doublefault_addr);
  		printk(KERN_NOTICE "   ICPLB_FAULT_ADDR: %pF
  ",
  			initial_pda_coreb.icplb_doublefault_addr);
6b3087c64   Graf Yang   Blackfin arch: SM...
399
400
401
  #endif
  		printk(KERN_NOTICE " The instruction at %pF caused a double exception
  ",
fb1d9be59   Mike Frysinger   Blackfin: optimiz...
402
  			initial_pda_coreb.retx);
6b3087c64   Graf Yang   Blackfin arch: SM...
403
404
405
406
407
408
409
410
  	}
  
  	/*
  	 * We want the D-cache to be enabled early, in case the atomic
  	 * support code emulates cache coherence (see
  	 * __ARCH_SYNC_CORE_DCACHE).
  	 */
  	init_exception_vectors();
6b3087c64   Graf Yang   Blackfin arch: SM...
411
412
413
414
415
416
  	local_irq_disable();
  
  	/* Attach the new idle task to the global mm. */
  	atomic_inc(&mm->mm_users);
  	atomic_inc(&mm->mm_count);
  	current->active_mm = mm;
6b3087c64   Graf Yang   Blackfin arch: SM...
417
418
419
420
  
  	preempt_disable();
  
  	setup_secondary(cpu);
578d36f5e   Yi Li   Blackfin: SMP: do...
421
  	platform_secondary_init(cpu);
0d152c27e   Yi Li   Blackfin: SMP: ma...
422
423
  	/* setup local core timer */
  	bfin_local_timer_setup();
6b3087c64   Graf Yang   Blackfin arch: SM...
424
  	local_irq_enable();
ab61d2ac5   steven miao   Blackfin: SMP: de...
425
  	bfin_setup_caches(cpu);
d0014be47   Bob Liu   blackfin: smp: cl...
426
  	notify_cpu_starting(cpu);
578d36f5e   Yi Li   Blackfin: SMP: do...
427
428
429
430
431
432
  	/*
  	 * Calibrate loops per jiffy value.
  	 * IRQs need to be enabled here - D-cache can be invalidated
  	 * in timer irq handler, so core B can read correct jiffies.
  	 */
  	calibrate_delay();
6b3087c64   Graf Yang   Blackfin arch: SM...
433
434
435
436
437
438
439
440
441
442
443
444
  
  	cpu_idle();
  }
  
  void __init smp_prepare_boot_cpu(void)
  {
  }
  
  void __init smp_prepare_cpus(unsigned int max_cpus)
  {
  	platform_prepare_cpus(max_cpus);
  	ipi_queue_init();
73a400646   Yi Li   Blackfin: SMP: re...
445
446
  	platform_request_ipi(IRQ_SUPPLE_0, ipi_handler_int0);
  	platform_request_ipi(IRQ_SUPPLE_1, ipi_handler_int1);
6b3087c64   Graf Yang   Blackfin arch: SM...
447
448
449
450
451
452
453
454
  }
  
  void __init smp_cpus_done(unsigned int max_cpus)
  {
  	unsigned long bogosum = 0;
  	unsigned int cpu;
  
  	for_each_online_cpu(cpu)
c70c754ff   Michael Hennerich   Blackfin: drop pe...
455
  		bogosum += loops_per_jiffy;
6b3087c64   Graf Yang   Blackfin arch: SM...
456
457
458
459
460
461
462
463
464
465
466
467
468
  
  	printk(KERN_INFO "SMP: Total of %d processors activated "
  	       "(%lu.%02lu BogoMIPS).
  ",
  	       num_online_cpus(),
  	       bogosum / (500000/HZ),
  	       (bogosum / (5000/HZ)) % 100);
  }
  
  void smp_icache_flush_range_others(unsigned long start, unsigned long end)
  {
  	smp_flush_data.start = start;
  	smp_flush_data.end = end;
a2eff9dd8   Steven Miao   blackfin: smp: fi...
469
470
  	preempt_disable();
  	if (smp_call_function(&ipi_flush_icache, &smp_flush_data, 1))
6b3087c64   Graf Yang   Blackfin arch: SM...
471
472
  		printk(KERN_WARNING "SMP: failed to run I-cache flush request on other CPUs
  ");
a2eff9dd8   Steven Miao   blackfin: smp: fi...
473
  	preempt_enable();
6b3087c64   Graf Yang   Blackfin arch: SM...
474
475
  }
  EXPORT_SYMBOL_GPL(smp_icache_flush_range_others);
47e9dedb7   Sonic Zhang   Blackfin: add bla...
476
  #ifdef __ARCH_SYNC_CORE_ICACHE
718340f62   Graf Yang   Blackfin: rewrite...
477
  unsigned long icache_invld_count[NR_CPUS];
47e9dedb7   Sonic Zhang   Blackfin: add bla...
478
479
480
481
  void resync_core_icache(void)
  {
  	unsigned int cpu = get_cpu();
  	blackfin_invalidate_entire_icache();
718340f62   Graf Yang   Blackfin: rewrite...
482
  	icache_invld_count[cpu]++;
47e9dedb7   Sonic Zhang   Blackfin: add bla...
483
484
485
486
  	put_cpu();
  }
  EXPORT_SYMBOL(resync_core_icache);
  #endif
6b3087c64   Graf Yang   Blackfin arch: SM...
487
  #ifdef __ARCH_SYNC_CORE_DCACHE
718340f62   Graf Yang   Blackfin: rewrite...
488
  unsigned long dcache_invld_count[NR_CPUS];
6b3087c64   Graf Yang   Blackfin arch: SM...
489
490
491
492
493
494
  unsigned long barrier_mask __attribute__ ((__section__(".l2.bss")));
  
  void resync_core_dcache(void)
  {
  	unsigned int cpu = get_cpu();
  	blackfin_invalidate_entire_dcache();
718340f62   Graf Yang   Blackfin: rewrite...
495
  	dcache_invld_count[cpu]++;
6b3087c64   Graf Yang   Blackfin arch: SM...
496
497
498
499
  	put_cpu();
  }
  EXPORT_SYMBOL(resync_core_dcache);
  #endif
0b39db28b   Graf Yang   Blackfin: SMP: ad...
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
  
  #ifdef CONFIG_HOTPLUG_CPU
  int __cpuexit __cpu_disable(void)
  {
  	unsigned int cpu = smp_processor_id();
  
  	if (cpu == 0)
  		return -EPERM;
  
  	set_cpu_online(cpu, false);
  	return 0;
  }
  
  static DECLARE_COMPLETION(cpu_killed);
  
  int __cpuexit __cpu_die(unsigned int cpu)
  {
  	return wait_for_completion_timeout(&cpu_killed, 5000);
  }
  
  void cpu_die(void)
  {
  	complete(&cpu_killed);
  
  	atomic_dec(&init_mm.mm_users);
  	atomic_dec(&init_mm.mm_count);
  
  	local_irq_disable();
  	platform_cpu_die();
  }
  #endif