Merge branch 'sched/for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip...
[pandora-kernel.git] / kernel / cpu.c
index c77bc3a..2cc409c 100644 (file)
 #include <linux/stop_machine.h>
 #include <linux/mutex.h>
 
+/*
+ * Represents all cpu's present in the system
+ * In systems capable of hotplug, this map could dynamically grow
+ * as new cpu's are detected in the system via any platform specific
+ * method, such as ACPI for e.g.
+ */
+cpumask_t cpu_present_map __read_mostly;
+EXPORT_SYMBOL(cpu_present_map);
+
+#ifndef CONFIG_SMP
+
+/*
+ * Represents all cpu's that are currently online.
+ */
+cpumask_t cpu_online_map __read_mostly = CPU_MASK_ALL;
+EXPORT_SYMBOL(cpu_online_map);
+
+cpumask_t cpu_possible_map __read_mostly = CPU_MASK_ALL;
+EXPORT_SYMBOL(cpu_possible_map);
+
+#else /* CONFIG_SMP */
+
 /* Serializes the updates to cpu_online_map, cpu_present_map */
 static DEFINE_MUTEX(cpu_add_remove_lock);
 
@@ -42,6 +64,8 @@ void __init cpu_hotplug_init(void)
        cpu_hotplug.refcount = 0;
 }
 
+cpumask_t cpu_active_map;
+
 #ifdef CONFIG_HOTPLUG_CPU
 
 void get_online_cpus(void)
@@ -269,14 +293,34 @@ int __ref cpu_down(unsigned int cpu)
        int err = 0;
 
        cpu_maps_update_begin();
-       if (cpu_hotplug_disabled)
+
+       if (cpu_hotplug_disabled) {
                err = -EBUSY;
-       else
-               err = _cpu_down(cpu, 0);
+               goto out;
+       }
+
+       cpu_clear(cpu, cpu_active_map);
 
+       /*
+        * Make sure the all cpus did the reschedule and are not
+        * using stale version of the cpu_active_map.
+        * This is not strictly necessary becuase stop_machine()
+        * that we run down the line already provides the required
+        * synchronization. But it's really a side effect and we do not
+        * want to depend on the innards of the stop_machine here.
+        */
+       synchronize_sched();
+
+       err = _cpu_down(cpu, 0);
+
+       if (cpu_online(cpu))
+               cpu_set(cpu, cpu_active_map);
+
+out:
        cpu_maps_update_done();
        return err;
 }
+EXPORT_SYMBOL(cpu_down);
 #endif /*CONFIG_HOTPLUG_CPU*/
 
 /* Requires cpu_add_remove_lock to be held */
@@ -332,11 +376,18 @@ int __cpuinit cpu_up(unsigned int cpu)
        }
 
        cpu_maps_update_begin();
-       if (cpu_hotplug_disabled)
+
+       if (cpu_hotplug_disabled) {
                err = -EBUSY;
-       else
-               err = _cpu_up(cpu, 0);
+               goto out;
+       }
+
+       err = _cpu_up(cpu, 0);
 
+       if (cpu_online(cpu))
+               cpu_set(cpu, cpu_active_map);
+
+out:
        cpu_maps_update_done();
        return err;
 }
@@ -390,7 +441,7 @@ void __ref enable_nonboot_cpus(void)
                goto out;
 
        printk("Enabling non-boot CPUs ...\n");
-       for_each_cpu_mask(cpu, frozen_cpus) {
+       for_each_cpu_mask_nr(cpu, frozen_cpus) {
                error = _cpu_up(cpu, 1);
                if (!error) {
                        printk("CPU%d is up\n", cpu);
@@ -403,3 +454,5 @@ out:
        cpu_maps_update_done();
 }
 #endif /* CONFIG_PM_SLEEP_SMP */
+
+#endif /* CONFIG_SMP */