Merge tag 'v4.1' into p/abusse/merge_upgrade
[projects/modsched/linux.git] / kernel / cpu.c
index 64a87d7..ef1d2b3 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/gfp.h>
 #include <linux/suspend.h>
 #include <linux/lockdep.h>
 #include <linux/gfp.h>
 #include <linux/suspend.h>
 #include <linux/lockdep.h>
+#include <linux/tick.h>
 #include <trace/events/power.h>
 
 #ifdef CONFIG_MOD_SCHED
 #include <trace/events/power.h>
 
 #ifdef CONFIG_MOD_SCHED
@@ -342,6 +343,8 @@ static int __ref take_cpu_down(void *_param)
                return err;
 
        cpu_notify(CPU_DYING | param->mod, param->hcpu);
                return err;
 
        cpu_notify(CPU_DYING | param->mod, param->hcpu);
+       /* Give up timekeeping duties */
+       tick_handover_do_timer();
        /* Park the stopper thread */
        kthread_park(current);
        return 0;
        /* Park the stopper thread */
        kthread_park(current);
        return 0;
@@ -412,13 +415,17 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
         *
         * Wait for the stop thread to go away.
         */
         *
         * Wait for the stop thread to go away.
         */
-       while (!idle_cpu(cpu))
+       while (!per_cpu(cpu_dead_idle, cpu))
                cpu_relax();
                cpu_relax();
+       smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */
+       per_cpu(cpu_dead_idle, cpu) = false;
 
 
+       hotplug_cpu__broadcast_tick_pull(cpu);
        /* This actually kills the CPU. */
        __cpu_die(cpu);
 
        /* CPU is completely dead: tell everyone.  Too late to complain. */
        /* This actually kills the CPU. */
        __cpu_die(cpu);
 
        /* CPU is completely dead: tell everyone.  Too late to complain. */
+       tick_cleanup_dead_cpu(cpu);
        cpu_notify_nofail(CPU_DEAD | mod, hcpu);
 
        check_for_tasks(cpu);
        cpu_notify_nofail(CPU_DEAD | mod, hcpu);
 
        check_for_tasks(cpu);
@@ -450,6 +457,37 @@ out:
 EXPORT_SYMBOL(cpu_down);
 #endif /*CONFIG_HOTPLUG_CPU*/
 
 EXPORT_SYMBOL(cpu_down);
 #endif /*CONFIG_HOTPLUG_CPU*/
 
+/*
+ * Unpark per-CPU smpboot kthreads at CPU-online time.
+ */
+static int smpboot_thread_call(struct notifier_block *nfb,
+                              unsigned long action, void *hcpu)
+{
+       int cpu = (long)hcpu;
+
+       switch (action & ~CPU_TASKS_FROZEN) {
+
+       case CPU_ONLINE:
+               smpboot_unpark_threads(cpu);
+               break;
+
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block smpboot_thread_notifier = {
+       .notifier_call = smpboot_thread_call,
+       .priority = CPU_PRI_SMPBOOT,
+};
+
+void __cpuinit smpboot_thread_init(void)
+{
+       register_cpu_notifier(&smpboot_thread_notifier);
+}
+
 /* Requires cpu_add_remove_lock to be held */
 static int _cpu_up(unsigned int cpu, int tasks_frozen)
 {
 /* Requires cpu_add_remove_lock to be held */
 static int _cpu_up(unsigned int cpu, int tasks_frozen)
 {
@@ -489,9 +527,6 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen)
                goto out_notify;
        BUG_ON(!cpu_online(cpu));
 
                goto out_notify;
        BUG_ON(!cpu_online(cpu));
 
-       /* Wake the per cpu threads */
-       smpboot_unpark_threads(cpu);
-
        /* Now call notifier in preparation. */
        cpu_notify(CPU_ONLINE | mod, hcpu);
 
        /* Now call notifier in preparation. */
        cpu_notify(CPU_ONLINE | mod, hcpu);