Merge tag 'xtensa-20190917' of git://github.com/jcmvbkbc/linux-xtensa
[linux-2.6-microblaze.git] / kernel / cpu.c
index e84c087..e1967e9 100644 (file)
@@ -62,7 +62,6 @@ struct cpuhp_cpu_state {
        bool                    rollback;
        bool                    single;
        bool                    bringup;
-       bool                    booted_once;
        struct hlist_node       *node;
        struct hlist_node       *last;
        enum cpuhp_state        cb_state;
@@ -76,6 +75,10 @@ static DEFINE_PER_CPU(struct cpuhp_cpu_state, cpuhp_state) = {
        .fail = CPUHP_INVALID,
 };
 
+#ifdef CONFIG_SMP
+cpumask_t cpus_booted_once_mask;
+#endif
+
 #if defined(CONFIG_LOCKDEP) && defined(CONFIG_SMP)
 static struct lockdep_map cpuhp_state_up_map =
        STATIC_LOCKDEP_MAP_INIT("cpuhp_state-up", &cpuhp_state_up_map);
@@ -433,7 +436,7 @@ static inline bool cpu_smt_allowed(unsigned int cpu)
         * CPU. Otherwise, a broadacasted MCE observing CR4.MCE=0b on any
         * core will shutdown the machine.
         */
-       return !per_cpu(cpuhp_state, cpu).booted_once;
+       return !cpumask_test_cpu(cpu, &cpus_booted_once_mask);
 }
 #else
 static inline bool cpu_smt_allowed(unsigned int cpu) { return true; }
@@ -1066,7 +1069,7 @@ void notify_cpu_starting(unsigned int cpu)
        int ret;
 
        rcu_cpu_starting(cpu);  /* Enables RCU usage on this CPU. */
-       st->booted_once = true;
+       cpumask_set_cpu(cpu, &cpus_booted_once_mask);
        while (st->state < target) {
                st->state++;
                ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL);
@@ -2295,6 +2298,9 @@ EXPORT_SYMBOL(__cpu_present_mask);
 struct cpumask __cpu_active_mask __read_mostly;
 EXPORT_SYMBOL(__cpu_active_mask);
 
+atomic_t __num_online_cpus __read_mostly;
+EXPORT_SYMBOL(__num_online_cpus);
+
 void init_cpu_present(const struct cpumask *src)
 {
        cpumask_copy(&__cpu_present_mask, src);
@@ -2310,6 +2316,27 @@ void init_cpu_online(const struct cpumask *src)
        cpumask_copy(&__cpu_online_mask, src);
 }
 
+void set_cpu_online(unsigned int cpu, bool online)
+{
+       /*
+        * atomic_inc/dec() is required to handle the horrid abuse of this
+        * function by the reboot and kexec code which invoke it from
+        * IPI/NMI broadcasts when shutting down CPUs. Invocation from
+        * regular CPU hotplug is properly serialized.
+        *
+        * Note, that the fact that __num_online_cpus is of type atomic_t
+        * does not protect readers which are not serialized against
+        * concurrent hotplug operations.
+        */
+       if (online) {
+               if (!cpumask_test_and_set_cpu(cpu, &__cpu_online_mask))
+                       atomic_inc(&__num_online_cpus);
+       } else {
+               if (cpumask_test_and_clear_cpu(cpu, &__cpu_online_mask))
+                       atomic_dec(&__num_online_cpus);
+       }
+}
+
 /*
  * Activate the first processor.
  */
@@ -2334,7 +2361,7 @@ void __init boot_cpu_init(void)
 void __init boot_cpu_hotplug_init(void)
 {
 #ifdef CONFIG_SMP
-       this_cpu_write(cpuhp_state.booted_once, true);
+       cpumask_set_cpu(smp_processor_id(), &cpus_booted_once_mask);
 #endif
        this_cpu_write(cpuhp_state.state, CPUHP_ONLINE);
 }