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]; |
