diff options
-rw-r--r-- | arch/x86_64/kernel/smp.c | 63 | ||||
-rw-r--r-- | arch/x86_64/kernel/smpboot.c | 21 | ||||
-rw-r--r-- | include/asm-x86_64/smp.h | 3 |
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 | */ | ||
299 | static 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 | |||
341 | int 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 | ||
265 | static __cpuinit void sync_tsc(void) | 262 | static __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 | ||
328 | static void __cpuinit tsc_sync_wait(void) | 333 | static 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 | ||
337 | static __init int notscsync_setup(char *s) | 340 | static __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; | |||
49 | extern void smp_send_reschedule(int cpu); | 49 | extern void smp_send_reschedule(int cpu); |
50 | extern void zap_low_mappings(void); | 50 | extern void zap_low_mappings(void); |
51 | void smp_stop_cpu(void); | 51 | void smp_stop_cpu(void); |
52 | extern int smp_call_function_single(int cpuid, void (*func) (void *info), | ||
53 | void *info, int retry, int wait); | ||
54 | |||
52 | extern cpumask_t cpu_sibling_map[NR_CPUS]; | 55 | extern cpumask_t cpu_sibling_map[NR_CPUS]; |
53 | extern cpumask_t cpu_core_map[NR_CPUS]; | 56 | extern cpumask_t cpu_core_map[NR_CPUS]; |
54 | extern u8 phys_proc_id[NR_CPUS]; | 57 | extern u8 phys_proc_id[NR_CPUS]; |