aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/cpu.c')
-rw-r--r--kernel/cpu.c67
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 */
24cpumask_t cpu_present_map __read_mostly;
25EXPORT_SYMBOL(cpu_present_map);
26
27#ifndef CONFIG_SMP
28
29/*
30 * Represents all cpu's that are currently online.
31 */
32cpumask_t cpu_online_map __read_mostly = CPU_MASK_ALL;
33EXPORT_SYMBOL(cpu_online_map);
34
35cpumask_t cpu_possible_map __read_mostly = CPU_MASK_ALL;
36EXPORT_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 */
19static DEFINE_MUTEX(cpu_add_remove_lock); 41static 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
67cpumask_t cpu_active_map;
68
45#ifdef CONFIG_HOTPLUG_CPU 69#ifdef CONFIG_HOTPLUG_CPU
46 70
47void get_online_cpus(void) 71void 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
319out:
277 cpu_maps_update_done(); 320 cpu_maps_update_done();
278 return err; 321 return err;
279} 322}
323EXPORT_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
390out:
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 */