diff options
Diffstat (limited to 'kernel/cpu.c')
-rw-r--r-- | kernel/cpu.c | 67 |
1 files changed, 60 insertions, 7 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index c77bc3a1c722..2cc409ce0a8f 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
@@ -15,6 +15,28 @@ | |||
15 | #include <linux/stop_machine.h> | 15 | #include <linux/stop_machine.h> |
16 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
17 | 17 | ||
18 | /* | ||
19 | * Represents all cpu's present in the system | ||
20 | * In systems capable of hotplug, this map could dynamically grow | ||
21 | * as new cpu's are detected in the system via any platform specific | ||
22 | * method, such as ACPI for e.g. | ||
23 | */ | ||
24 | cpumask_t cpu_present_map __read_mostly; | ||
25 | EXPORT_SYMBOL(cpu_present_map); | ||
26 | |||
27 | #ifndef CONFIG_SMP | ||
28 | |||
29 | /* | ||
30 | * Represents all cpu's that are currently online. | ||
31 | */ | ||
32 | cpumask_t cpu_online_map __read_mostly = CPU_MASK_ALL; | ||
33 | EXPORT_SYMBOL(cpu_online_map); | ||
34 | |||
35 | cpumask_t cpu_possible_map __read_mostly = CPU_MASK_ALL; | ||
36 | EXPORT_SYMBOL(cpu_possible_map); | ||
37 | |||
38 | #else /* CONFIG_SMP */ | ||
39 | |||
18 | /* Serializes the updates to cpu_online_map, cpu_present_map */ | 40 | /* Serializes the updates to cpu_online_map, cpu_present_map */ |
19 | static DEFINE_MUTEX(cpu_add_remove_lock); | 41 | static DEFINE_MUTEX(cpu_add_remove_lock); |
20 | 42 | ||
@@ -42,6 +64,8 @@ void __init cpu_hotplug_init(void) | |||
42 | cpu_hotplug.refcount = 0; | 64 | cpu_hotplug.refcount = 0; |
43 | } | 65 | } |
44 | 66 | ||
67 | cpumask_t cpu_active_map; | ||
68 | |||
45 | #ifdef CONFIG_HOTPLUG_CPU | 69 | #ifdef CONFIG_HOTPLUG_CPU |
46 | 70 | ||
47 | void get_online_cpus(void) | 71 | void get_online_cpus(void) |
@@ -269,14 +293,34 @@ int __ref cpu_down(unsigned int cpu) | |||
269 | int err = 0; | 293 | int err = 0; |
270 | 294 | ||
271 | cpu_maps_update_begin(); | 295 | cpu_maps_update_begin(); |
272 | if (cpu_hotplug_disabled) | 296 | |
297 | if (cpu_hotplug_disabled) { | ||
273 | err = -EBUSY; | 298 | err = -EBUSY; |
274 | else | 299 | goto out; |
275 | err = _cpu_down(cpu, 0); | 300 | } |
301 | |||
302 | cpu_clear(cpu, cpu_active_map); | ||
276 | 303 | ||
304 | /* | ||
305 | * Make sure the all cpus did the reschedule and are not | ||
306 | * using stale version of the cpu_active_map. | ||
307 | * This is not strictly necessary becuase stop_machine() | ||
308 | * that we run down the line already provides the required | ||
309 | * synchronization. But it's really a side effect and we do not | ||
310 | * want to depend on the innards of the stop_machine here. | ||
311 | */ | ||
312 | synchronize_sched(); | ||
313 | |||
314 | err = _cpu_down(cpu, 0); | ||
315 | |||
316 | if (cpu_online(cpu)) | ||
317 | cpu_set(cpu, cpu_active_map); | ||
318 | |||
319 | out: | ||
277 | cpu_maps_update_done(); | 320 | cpu_maps_update_done(); |
278 | return err; | 321 | return err; |
279 | } | 322 | } |
323 | EXPORT_SYMBOL(cpu_down); | ||
280 | #endif /*CONFIG_HOTPLUG_CPU*/ | 324 | #endif /*CONFIG_HOTPLUG_CPU*/ |
281 | 325 | ||
282 | /* Requires cpu_add_remove_lock to be held */ | 326 | /* Requires cpu_add_remove_lock to be held */ |
@@ -332,11 +376,18 @@ int __cpuinit cpu_up(unsigned int cpu) | |||
332 | } | 376 | } |
333 | 377 | ||
334 | cpu_maps_update_begin(); | 378 | cpu_maps_update_begin(); |
335 | if (cpu_hotplug_disabled) | 379 | |
380 | if (cpu_hotplug_disabled) { | ||
336 | err = -EBUSY; | 381 | err = -EBUSY; |
337 | else | 382 | goto out; |
338 | err = _cpu_up(cpu, 0); | 383 | } |
384 | |||
385 | err = _cpu_up(cpu, 0); | ||
339 | 386 | ||
387 | if (cpu_online(cpu)) | ||
388 | cpu_set(cpu, cpu_active_map); | ||
389 | |||
390 | out: | ||
340 | cpu_maps_update_done(); | 391 | cpu_maps_update_done(); |
341 | return err; | 392 | return err; |
342 | } | 393 | } |
@@ -390,7 +441,7 @@ void __ref enable_nonboot_cpus(void) | |||
390 | goto out; | 441 | goto out; |
391 | 442 | ||
392 | printk("Enabling non-boot CPUs ...\n"); | 443 | printk("Enabling non-boot CPUs ...\n"); |
393 | for_each_cpu_mask(cpu, frozen_cpus) { | 444 | for_each_cpu_mask_nr(cpu, frozen_cpus) { |
394 | error = _cpu_up(cpu, 1); | 445 | error = _cpu_up(cpu, 1); |
395 | if (!error) { | 446 | if (!error) { |
396 | printk("CPU%d is up\n", cpu); | 447 | printk("CPU%d is up\n", cpu); |
@@ -403,3 +454,5 @@ out: | |||
403 | cpu_maps_update_done(); | 454 | cpu_maps_update_done(); |
404 | } | 455 | } |
405 | #endif /* CONFIG_PM_SLEEP_SMP */ | 456 | #endif /* CONFIG_PM_SLEEP_SMP */ |
457 | |||
458 | #endif /* CONFIG_SMP */ | ||