aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/kernel/smp.c63
-rw-r--r--arch/x86_64/kernel/smpboot.c21
-rw-r--r--include/asm-x86_64/smp.h3
3 files changed, 78 insertions, 9 deletions
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index 6ee74db52303..e5958220d6b8 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -293,6 +293,69 @@ void unlock_ipi_call_lock(void)
293} 293}
294 294
295/* 295/*
296 * this function sends a 'generic call function' IPI to one other CPU
297 * in the system.
298 */
299static void __smp_call_function_single (int cpu, void (*func) (void *info), void *info,
300 int nonatomic, int wait)
301{
302 struct call_data_struct data;
303 int cpus = 1;
304
305 data.func = func;
306 data.info = info;
307 atomic_set(&data.started, 0);
308 data.wait = wait;
309 if (wait)
310 atomic_set(&data.finished, 0);
311
312 call_data = &data;
313 wmb();
314 /* Send a message to all other CPUs and wait for them to respond */
315 send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR);
316
317 /* Wait for response */
318 while (atomic_read(&data.started) != cpus)
319 cpu_relax();
320
321 if (!wait)
322 return;
323
324 while (atomic_read(&data.finished) != cpus)
325 cpu_relax();
326}
327
328/*
329 * smp_call_function_single - Run a function on another CPU
330 * @func: The function to run. This must be fast and non-blocking.
331 * @info: An arbitrary pointer to pass to the function.
332 * @nonatomic: Currently unused.
333 * @wait: If true, wait until function has completed on other CPUs.
334 *
335 * Retrurns 0 on success, else a negative status code.
336 *
337 * Does not return until the remote CPU is nearly ready to execute <func>
338 * or is or has executed.
339 */
340
341int smp_call_function_single (int cpu, void (*func) (void *info), void *info,
342 int nonatomic, int wait)
343{
344 /* prevent preemption and reschedule on another processor */
345 int me = get_cpu();
346 if (cpu == me) {
347 WARN_ON(1);
348 put_cpu();
349 return -EBUSY;
350 }
351 spin_lock_bh(&call_lock);
352 __smp_call_function_single(cpu, func, info, nonatomic, wait);
353 spin_unlock_bh(&call_lock);
354 put_cpu();
355 return 0;
356}
357
358/*
296 * this function sends a 'generic call function' IPI to all other CPUs 359 * this function sends a 'generic call function' IPI to all other CPUs
297 * in the system. 360 * in the system.
298 */ 361 */
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 6d23354443c0..6e4807d64d46 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -211,9 +211,6 @@ static __cpuinit void sync_master(void *arg)
211{ 211{
212 unsigned long flags, i; 212 unsigned long flags, i;
213 213
214 if (smp_processor_id() != 0)
215 return;
216
217 go[MASTER] = 0; 214 go[MASTER] = 0;
218 215
219 local_irq_save(flags); 216 local_irq_save(flags);
@@ -262,7 +259,7 @@ get_delta(long *rt, long *master)
262 return tcenter - best_tm; 259 return tcenter - best_tm;
263} 260}
264 261
265static __cpuinit void sync_tsc(void) 262static __cpuinit void sync_tsc(unsigned int master)
266{ 263{
267 int i, done = 0; 264 int i, done = 0;
268 long delta, adj, adjust_latency = 0; 265 long delta, adj, adjust_latency = 0;
@@ -276,9 +273,17 @@ static __cpuinit void sync_tsc(void)
276 } t[NUM_ROUNDS] __cpuinitdata; 273 } t[NUM_ROUNDS] __cpuinitdata;
277#endif 274#endif
278 275
276 printk(KERN_INFO "CPU %d: Syncing TSC to CPU %u.\n",
277 smp_processor_id(), master);
278
279 go[MASTER] = 1; 279 go[MASTER] = 1;
280 280
281 smp_call_function(sync_master, NULL, 1, 0); 281 /* It is dangerous to broadcast IPI as cpus are coming up,
282 * as they may not be ready to accept them. So since
283 * we only need to send the ipi to the boot cpu direct
284 * the message, and avoid the race.
285 */
286 smp_call_function_single(master, sync_master, NULL, 1, 0);
282 287
283 while (go[MASTER]) /* wait for master to be ready */ 288 while (go[MASTER]) /* wait for master to be ready */
284 no_cpu_relax(); 289 no_cpu_relax();
@@ -322,16 +327,14 @@ static __cpuinit void sync_tsc(void)
322 printk(KERN_INFO 327 printk(KERN_INFO
323 "CPU %d: synchronized TSC with CPU %u (last diff %ld cycles, " 328 "CPU %d: synchronized TSC with CPU %u (last diff %ld cycles, "
324 "maxerr %lu cycles)\n", 329 "maxerr %lu cycles)\n",
325 smp_processor_id(), boot_cpu_id, delta, rt); 330 smp_processor_id(), master, delta, rt);
326} 331}
327 332
328static void __cpuinit tsc_sync_wait(void) 333static void __cpuinit tsc_sync_wait(void)
329{ 334{
330 if (notscsync || !cpu_has_tsc) 335 if (notscsync || !cpu_has_tsc)
331 return; 336 return;
332 printk(KERN_INFO "CPU %d: Syncing TSC to CPU %u.\n", smp_processor_id(), 337 sync_tsc(boot_cpu_id);
333 boot_cpu_id);
334 sync_tsc();
335} 338}
336 339
337static __init int notscsync_setup(char *s) 340static __init int notscsync_setup(char *s)
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index 18ac762e1ab8..de8b57b2b62b 100644
--- a/include/asm-x86_64/smp.h
+++ b/include/asm-x86_64/smp.h
@@ -49,6 +49,9 @@ extern int smp_num_siblings;
49extern void smp_send_reschedule(int cpu); 49extern void smp_send_reschedule(int cpu);
50extern void zap_low_mappings(void); 50extern void zap_low_mappings(void);
51void smp_stop_cpu(void); 51void smp_stop_cpu(void);
52extern int smp_call_function_single(int cpuid, void (*func) (void *info),
53 void *info, int retry, int wait);
54
52extern cpumask_t cpu_sibling_map[NR_CPUS]; 55extern cpumask_t cpu_sibling_map[NR_CPUS];
53extern cpumask_t cpu_core_map[NR_CPUS]; 56extern cpumask_t cpu_core_map[NR_CPUS];
54extern u8 phys_proc_id[NR_CPUS]; 57extern u8 phys_proc_id[NR_CPUS];