Blame view

arch/sh/kernel/smp.c 9.92 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
  /*
   * arch/sh/kernel/smp.c
   *
   * SMP support for the SuperH processors.
   *
3366e3585   Paul Mundt   sh: Move platform...
6
   * Copyright (C) 2002 - 2010 Paul Mundt
aba1030a7   Paul Mundt   sh: Bring SMP sup...
7
   * Copyright (C) 2006 - 2007 Akio Idehara
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
   *
aba1030a7   Paul Mundt   sh: Bring SMP sup...
9
10
11
   * This file is subject to the terms and conditions of the GNU General Public
   * License.  See the file "COPYING" in the main directory of this archive
   * for more details.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
   */
66c5227ec   Evgeniy Polyakov   sh: trivial build...
13
  #include <linux/err.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
  #include <linux/cache.h>
  #include <linux/cpumask.h>
  #include <linux/delay.h>
  #include <linux/init.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
  #include <linux/spinlock.h>
aba1030a7   Paul Mundt   sh: Bring SMP sup...
19
  #include <linux/mm.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
  #include <linux/module.h>
b56050ae5   Paul Mundt   sh: arch/sh/kerne...
21
  #include <linux/cpu.h>
aba1030a7   Paul Mundt   sh: Bring SMP sup...
22
  #include <linux/interrupt.h>
184748cc5   Peter Zijlstra   sched: Provide sc...
23
  #include <linux/sched.h>
60063497a   Arun Sharma   atomic: use <linu...
24
  #include <linux/atomic.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25
26
27
28
  #include <asm/processor.h>
  #include <asm/system.h>
  #include <asm/mmu_context.h>
  #include <asm/smp.h>
aba1030a7   Paul Mundt   sh: Bring SMP sup...
29
30
  #include <asm/cacheflush.h>
  #include <asm/sections.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31

aba1030a7   Paul Mundt   sh: Bring SMP sup...
32
33
  int __cpu_number_map[NR_CPUS];		/* Map physical to logical */
  int __cpu_logical_map[NR_CPUS];		/* Map logical to physical */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34

3366e3585   Paul Mundt   sh: Move platform...
35
  struct plat_smp_ops *mp_ops = NULL;
9715b8c7d   Paul Mundt   sh: provide percp...
36
37
  /* State of each CPU */
  DEFINE_PER_CPU(int, cpu_state) = { 0 };
3366e3585   Paul Mundt   sh: Move platform...
38
39
40
41
42
43
44
45
  void __cpuinit register_smp_ops(struct plat_smp_ops *ops)
  {
  	if (mp_ops)
  		printk(KERN_WARNING "Overriding previously set SMP ops
  ");
  
  	mp_ops = ops;
  }
1cfa1e8f2   Paul Mundt   sh: flag smp_stor...
46
  static inline void __cpuinit smp_store_cpu_info(unsigned int cpu)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
  {
aba1030a7   Paul Mundt   sh: Bring SMP sup...
48
  	struct sh_cpuinfo *c = cpu_data + cpu;
a66c2edea   Paul Mundt   sh: Populate init...
49
  	memcpy(c, &boot_cpu_data, sizeof(struct sh_cpuinfo));
aba1030a7   Paul Mundt   sh: Bring SMP sup...
50
  	c->loops_per_jiffy = loops_per_jiffy;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
55
  }
  
  void __init smp_prepare_cpus(unsigned int max_cpus)
  {
  	unsigned int cpu = smp_processor_id();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56

aba1030a7   Paul Mundt   sh: Bring SMP sup...
57
58
  	init_new_context(current, &init_mm);
  	current_thread_info()->cpu = cpu;
3366e3585   Paul Mundt   sh: Move platform...
59
  	mp_ops->prepare_cpus(max_cpus);
aba1030a7   Paul Mundt   sh: Bring SMP sup...
60
61
  
  #ifndef CONFIG_HOTPLUG_CPU
e09377bae   Rusty Russell   cpumask: Use acce...
62
  	init_cpu_present(&cpu_possible_map);
aba1030a7   Paul Mundt   sh: Bring SMP sup...
63
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
64
  }
1cfa1e8f2   Paul Mundt   sh: flag smp_stor...
65
  void __init smp_prepare_boot_cpu(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
  {
  	unsigned int cpu = smp_processor_id();
aba1030a7   Paul Mundt   sh: Bring SMP sup...
68
69
  	__cpu_number_map[0] = cpu;
  	__cpu_logical_map[0] = cpu;
e09377bae   Rusty Russell   cpumask: Use acce...
70
71
  	set_cpu_online(cpu, true);
  	set_cpu_possible(cpu, true);
9715b8c7d   Paul Mundt   sh: provide percp...
72
73
  
  	per_cpu(cpu_state, cpu) = CPU_ONLINE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
  }
763142d1e   Paul Mundt   sh: CPU hotplug s...
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  #ifdef CONFIG_HOTPLUG_CPU
  void native_cpu_die(unsigned int cpu)
  {
  	unsigned int i;
  
  	for (i = 0; i < 10; i++) {
  		smp_rmb();
  		if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
  			if (system_state == SYSTEM_RUNNING)
  				pr_info("CPU %u is now offline
  ", cpu);
  
  			return;
  		}
  
  		msleep(100);
  	}
  
  	pr_err("CPU %u didn't die...
  ", cpu);
  }
  
  int native_cpu_disable(unsigned int cpu)
  {
  	return cpu == 0 ? -EPERM : 0;
  }
  
  void play_dead_common(void)
  {
  	idle_task_exit();
  	irq_ctx_exit(raw_smp_processor_id());
  	mb();
  
  	__get_cpu_var(cpu_state) = CPU_DEAD;
  	local_irq_disable();
  }
  
  void native_play_dead(void)
  {
  	play_dead_common();
  }
  
  int __cpu_disable(void)
  {
  	unsigned int cpu = smp_processor_id();
  	struct task_struct *p;
  	int ret;
  
  	ret = mp_ops->cpu_disable(cpu);
  	if (ret)
  		return ret;
  
  	/*
  	 * Take this CPU offline.  Once we clear this, we can't return,
  	 * and we must not schedule until we're ready to give up the cpu.
  	 */
  	set_cpu_online(cpu, false);
  
  	/*
  	 * OK - migrate IRQs away from this CPU
  	 */
  	migrate_irqs();
  
  	/*
  	 * Stop the local timer for this CPU.
  	 */
  	local_timer_stop(cpu);
  
  	/*
  	 * Flush user cache and TLB mappings, and then remove this CPU
  	 * from the vm mask set of all processes.
  	 */
  	flush_cache_all();
  	local_flush_tlb_all();
  
  	read_lock(&tasklist_lock);
  	for_each_process(p)
  		if (p->mm)
  			cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
  	read_unlock(&tasklist_lock);
  
  	return 0;
  }
  #else /* ... !CONFIG_HOTPLUG_CPU */
1483feac7   Matt Fleming   sh: native_cpu_di...
159
  int native_cpu_disable(unsigned int cpu)
763142d1e   Paul Mundt   sh: CPU hotplug s...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
  {
  	return -ENOSYS;
  }
  
  void native_cpu_die(unsigned int cpu)
  {
  	/* We said "no" in __cpu_disable */
  	BUG();
  }
  
  void native_play_dead(void)
  {
  	BUG();
  }
  #endif
aba1030a7   Paul Mundt   sh: Bring SMP sup...
175
  asmlinkage void __cpuinit start_secondary(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
176
  {
9715b8c7d   Paul Mundt   sh: provide percp...
177
  	unsigned int cpu = smp_processor_id();
aba1030a7   Paul Mundt   sh: Bring SMP sup...
178
  	struct mm_struct *mm = &init_mm;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179

4bea3418c   Matt Fleming   sh: Enable the mm...
180
  	enable_mmu();
aba1030a7   Paul Mundt   sh: Bring SMP sup...
181
182
183
  	atomic_inc(&mm->mm_count);
  	atomic_inc(&mm->mm_users);
  	current->active_mm = mm;
aba1030a7   Paul Mundt   sh: Bring SMP sup...
184
  	enter_lazy_tlb(mm, current);
763142d1e   Paul Mundt   sh: CPU hotplug s...
185
  	local_flush_tlb_all();
aba1030a7   Paul Mundt   sh: Bring SMP sup...
186
187
188
189
  
  	per_cpu_trap_init();
  
  	preempt_disable();
9715b8c7d   Paul Mundt   sh: provide percp...
190
  	notify_cpu_starting(cpu);
e545a6140   Manfred Spraul   kernel/cpu.c: cre...
191

aba1030a7   Paul Mundt   sh: Bring SMP sup...
192
  	local_irq_enable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193

8c24594de   Paul Mundt   sh: generic clock...
194
195
  	/* Enable local timers */
  	local_timer_setup(cpu);
aba1030a7   Paul Mundt   sh: Bring SMP sup...
196
  	calibrate_delay();
aba1030a7   Paul Mundt   sh: Bring SMP sup...
197
  	smp_store_cpu_info(cpu);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198

f0ccf2770   Paul Mundt   sh: convert onlin...
199
  	set_cpu_online(cpu, true);
9715b8c7d   Paul Mundt   sh: provide percp...
200
  	per_cpu(cpu_state, cpu) = CPU_ONLINE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
201

aba1030a7   Paul Mundt   sh: Bring SMP sup...
202
  	cpu_idle();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203
  }
aba1030a7   Paul Mundt   sh: Bring SMP sup...
204
205
206
207
208
209
210
211
212
213
  extern struct {
  	unsigned long sp;
  	unsigned long bss_start;
  	unsigned long bss_end;
  	void *start_kernel_fn;
  	void *cpu_init_fn;
  	void *thread_info;
  } stack_start;
  
  int __cpuinit __cpu_up(unsigned int cpu)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  {
aba1030a7   Paul Mundt   sh: Bring SMP sup...
215
216
  	struct task_struct *tsk;
  	unsigned long timeout;
5bfb5d690   Nick Piggin   [PATCH] sched: di...
217

8db2bc455   Paul Mundt   sh: cache seconda...
218
219
220
221
222
223
224
225
226
227
  	tsk = cpu_data[cpu].idle;
  	if (!tsk) {
  		tsk = fork_idle(cpu);
  		if (IS_ERR(tsk)) {
  			pr_err("Failed forking idle task for cpu %d
  ", cpu);
  			return PTR_ERR(tsk);
  		}
  
  		cpu_data[cpu].idle = tsk;
aba1030a7   Paul Mundt   sh: Bring SMP sup...
228
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
229

9715b8c7d   Paul Mundt   sh: provide percp...
230
  	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
aba1030a7   Paul Mundt   sh: Bring SMP sup...
231
232
233
234
235
  	/* Fill in data in head.S for secondary cpus */
  	stack_start.sp = tsk->thread.sp;
  	stack_start.thread_info = tsk->stack;
  	stack_start.bss_start = 0; /* don't clear bss for secondary cpus */
  	stack_start.start_kernel_fn = start_secondary;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236

d780613ac   Paul Mundt   sh: Only invalida...
237
238
239
  	flush_icache_range((unsigned long)&stack_start,
  			   (unsigned long)&stack_start + sizeof(stack_start));
  	wmb();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240

3366e3585   Paul Mundt   sh: Move platform...
241
  	mp_ops->start_cpu(cpu, (unsigned long)_stext);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242

aba1030a7   Paul Mundt   sh: Bring SMP sup...
243
244
245
246
247
248
  	timeout = jiffies + HZ;
  	while (time_before(jiffies, timeout)) {
  		if (cpu_online(cpu))
  			break;
  
  		udelay(10);
763142d1e   Paul Mundt   sh: CPU hotplug s...
249
  		barrier();
aba1030a7   Paul Mundt   sh: Bring SMP sup...
250
251
252
253
254
255
  	}
  
  	if (cpu_online(cpu))
  		return 0;
  
  	return -ENOENT;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
257
258
259
  }
  
  void __init smp_cpus_done(unsigned int max_cpus)
  {
aba1030a7   Paul Mundt   sh: Bring SMP sup...
260
261
262
263
264
265
266
267
268
269
270
  	unsigned long bogosum = 0;
  	int cpu;
  
  	for_each_online_cpu(cpu)
  		bogosum += cpu_data[cpu].loops_per_jiffy;
  
  	printk(KERN_INFO "SMP: Total of %d processors activated "
  	       "(%lu.%02lu BogoMIPS).
  ", num_online_cpus(),
  	       bogosum / (500000/HZ),
  	       (bogosum / (5000/HZ)) % 100);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
271
272
273
274
  }
  
  void smp_send_reschedule(int cpu)
  {
3366e3585   Paul Mundt   sh: Move platform...
275
  	mp_ops->send_ipi(cpu, SMP_MSG_RESCHEDULE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
278
  void smp_send_stop(void)
  {
8691e5a8f   Jens Axboe   smp_call_function...
279
  	smp_call_function(stop_this_cpu, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280
  }
819807df6   Rusty Russell   cpumask: arch_sen...
281
  void arch_send_call_function_ipi_mask(const struct cpumask *mask)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
282
  {
490f5de52   Jens Axboe   sh: convert to ge...
283
  	int cpu;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284

819807df6   Rusty Russell   cpumask: arch_sen...
285
  	for_each_cpu(cpu, mask)
3366e3585   Paul Mundt   sh: Move platform...
286
  		mp_ops->send_ipi(cpu, SMP_MSG_FUNCTION);
490f5de52   Jens Axboe   sh: convert to ge...
287
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288

490f5de52   Jens Axboe   sh: convert to ge...
289
290
  void arch_send_call_function_single_ipi(int cpu)
  {
3366e3585   Paul Mundt   sh: Move platform...
291
  	mp_ops->send_ipi(cpu, SMP_MSG_FUNCTION_SINGLE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
  }
320ab2b0b   Rusty Russell   cpumask: convert ...
293
  void smp_timer_broadcast(const struct cpumask *mask)
6f52707e6   Paul Mundt   sh: smp: Hook up ...
294
295
  {
  	int cpu;
320ab2b0b   Rusty Russell   cpumask: convert ...
296
  	for_each_cpu(cpu, mask)
3366e3585   Paul Mundt   sh: Move platform...
297
  		mp_ops->send_ipi(cpu, SMP_MSG_TIMER);
6f52707e6   Paul Mundt   sh: smp: Hook up ...
298
299
300
301
302
  }
  
  static void ipi_timer(void)
  {
  	irq_enter();
8c24594de   Paul Mundt   sh: generic clock...
303
  	local_timer_interrupt();
6f52707e6   Paul Mundt   sh: smp: Hook up ...
304
305
  	irq_exit();
  }
173a44dd1   Paul Mundt   sh: smp: Provide ...
306
307
308
309
310
311
312
  void smp_message_recv(unsigned int msg)
  {
  	switch (msg) {
  	case SMP_MSG_FUNCTION:
  		generic_smp_call_function_interrupt();
  		break;
  	case SMP_MSG_RESCHEDULE:
184748cc5   Peter Zijlstra   sched: Provide sc...
313
  		scheduler_ipi();
173a44dd1   Paul Mundt   sh: smp: Provide ...
314
315
316
317
  		break;
  	case SMP_MSG_FUNCTION_SINGLE:
  		generic_smp_call_function_single_interrupt();
  		break;
6f52707e6   Paul Mundt   sh: smp: Hook up ...
318
319
320
  	case SMP_MSG_TIMER:
  		ipi_timer();
  		break;
173a44dd1   Paul Mundt   sh: smp: Provide ...
321
322
323
324
325
326
327
  	default:
  		printk(KERN_WARNING "SMP %d: %s(): unknown IPI %d
  ",
  		       smp_processor_id(), __func__, msg);
  		break;
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
329
330
331
332
  /* Not really SMP stuff ... */
  int setup_profiling_timer(unsigned int multiplier)
  {
  	return 0;
  }
9964fa8bf   Paul Mundt   sh: Add SMP tlbfl...
333
334
335
336
337
338
339
  static void flush_tlb_all_ipi(void *info)
  {
  	local_flush_tlb_all();
  }
  
  void flush_tlb_all(void)
  {
15c8b6c1a   Jens Axboe   on_each_cpu(): ki...
340
  	on_each_cpu(flush_tlb_all_ipi, 0, 1);
9964fa8bf   Paul Mundt   sh: Add SMP tlbfl...
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
  }
  
  static void flush_tlb_mm_ipi(void *mm)
  {
  	local_flush_tlb_mm((struct mm_struct *)mm);
  }
  
  /*
   * The following tlb flush calls are invoked when old translations are
   * being torn down, or pte attributes are changing. For single threaded
   * address spaces, a new context is obtained on the current cpu, and tlb
   * context on other cpus are invalidated to force a new context allocation
   * at switch_mm time, should the mm ever be used on other cpus. For
   * multithreaded address spaces, intercpu interrupts have to be sent.
   * Another case where intercpu interrupts are required is when the target
   * mm might be active on another cpu (eg debuggers doing the flushes on
   * behalf of debugees, kswapd stealing pages from another process etc).
   * Kanoj 07/00.
   */
9964fa8bf   Paul Mundt   sh: Add SMP tlbfl...
360
361
362
363
364
  void flush_tlb_mm(struct mm_struct *mm)
  {
  	preempt_disable();
  
  	if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
8691e5a8f   Jens Axboe   smp_call_function...
365
  		smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1);
9964fa8bf   Paul Mundt   sh: Add SMP tlbfl...
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
  	} else {
  		int i;
  		for (i = 0; i < num_online_cpus(); i++)
  			if (smp_processor_id() != i)
  				cpu_context(i, mm) = 0;
  	}
  	local_flush_tlb_mm(mm);
  
  	preempt_enable();
  }
  
  struct flush_tlb_data {
  	struct vm_area_struct *vma;
  	unsigned long addr1;
  	unsigned long addr2;
  };
  
  static void flush_tlb_range_ipi(void *info)
  {
  	struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
  
  	local_flush_tlb_range(fd->vma, fd->addr1, fd->addr2);
  }
  
  void flush_tlb_range(struct vm_area_struct *vma,
  		     unsigned long start, unsigned long end)
  {
  	struct mm_struct *mm = vma->vm_mm;
  
  	preempt_disable();
  	if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) {
  		struct flush_tlb_data fd;
  
  		fd.vma = vma;
  		fd.addr1 = start;
  		fd.addr2 = end;
8691e5a8f   Jens Axboe   smp_call_function...
402
  		smp_call_function(flush_tlb_range_ipi, (void *)&fd, 1);
9964fa8bf   Paul Mundt   sh: Add SMP tlbfl...
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  	} else {
  		int i;
  		for (i = 0; i < num_online_cpus(); i++)
  			if (smp_processor_id() != i)
  				cpu_context(i, mm) = 0;
  	}
  	local_flush_tlb_range(vma, start, end);
  	preempt_enable();
  }
  
  static void flush_tlb_kernel_range_ipi(void *info)
  {
  	struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
  
  	local_flush_tlb_kernel_range(fd->addr1, fd->addr2);
  }
  
  void flush_tlb_kernel_range(unsigned long start, unsigned long end)
  {
  	struct flush_tlb_data fd;
  
  	fd.addr1 = start;
  	fd.addr2 = end;
15c8b6c1a   Jens Axboe   on_each_cpu(): ki...
426
  	on_each_cpu(flush_tlb_kernel_range_ipi, (void *)&fd, 1);
9964fa8bf   Paul Mundt   sh: Add SMP tlbfl...
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
  }
  
  static void flush_tlb_page_ipi(void *info)
  {
  	struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
  
  	local_flush_tlb_page(fd->vma, fd->addr1);
  }
  
  void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
  {
  	preempt_disable();
  	if ((atomic_read(&vma->vm_mm->mm_users) != 1) ||
  	    (current->mm != vma->vm_mm)) {
  		struct flush_tlb_data fd;
  
  		fd.vma = vma;
  		fd.addr1 = page;
8691e5a8f   Jens Axboe   smp_call_function...
445
  		smp_call_function(flush_tlb_page_ipi, (void *)&fd, 1);
9964fa8bf   Paul Mundt   sh: Add SMP tlbfl...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
  	} else {
  		int i;
  		for (i = 0; i < num_online_cpus(); i++)
  			if (smp_processor_id() != i)
  				cpu_context(i, vma->vm_mm) = 0;
  	}
  	local_flush_tlb_page(vma, page);
  	preempt_enable();
  }
  
  static void flush_tlb_one_ipi(void *info)
  {
  	struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
  	local_flush_tlb_one(fd->addr1, fd->addr2);
  }
  
  void flush_tlb_one(unsigned long asid, unsigned long vaddr)
  {
  	struct flush_tlb_data fd;
  
  	fd.addr1 = asid;
  	fd.addr2 = vaddr;
8691e5a8f   Jens Axboe   smp_call_function...
468
  	smp_call_function(flush_tlb_one_ipi, (void *)&fd, 1);
9964fa8bf   Paul Mundt   sh: Add SMP tlbfl...
469
470
  	local_flush_tlb_one(asid, vaddr);
  }