static struct task_struct      *wakeup_task;
 static int                     wakeup_cpu;
+static int                     wakeup_current_cpu;
 static unsigned                        wakeup_prio = -1;
 static int                     wakeup_rt;
 
        resched = ftrace_preempt_disable();
 
        cpu = raw_smp_processor_id();
+       if (cpu != wakeup_current_cpu)
+               goto out_enable;
+
        data = tr->data[cpu];
        disabled = atomic_inc_return(&data->disabled);
        if (unlikely(disabled != 1))
                goto out;
 
        local_irq_save(flags);
-       __raw_spin_lock(&wakeup_lock);
-
-       if (unlikely(!wakeup_task))
-               goto unlock;
-
-       /*
-        * The task can't disappear because it needs to
-        * wake up first, and we have the wakeup_lock.
-        */
-       if (task_cpu(wakeup_task) != cpu)
-               goto unlock;
 
        trace_function(tr, ip, parent_ip, flags, pc);
 
- unlock:
-       __raw_spin_unlock(&wakeup_lock);
        local_irq_restore(flags);
 
  out:
        atomic_dec(&data->disabled);
-
+ out_enable:
        ftrace_preempt_enable(resched);
 }
 
        return 1;
 }
 
+static void probe_wakeup_migrate_task(struct task_struct *task, int cpu)
+{
+       if (task != wakeup_task)
+               return;
+
+       wakeup_current_cpu = cpu;
+}
+
 static void notrace
 probe_wakeup_sched_switch(struct rq *rq, struct task_struct *prev,
        struct task_struct *next)
        __wakeup_reset(wakeup_trace);
 
        wakeup_cpu = task_cpu(p);
+       wakeup_current_cpu = wakeup_cpu;
        wakeup_prio = p->prio;
 
        wakeup_task = p;
                goto fail_deprobe_wake_new;
        }
 
+       ret = register_trace_sched_migrate_task(probe_wakeup_migrate_task);
+       if (ret) {
+               pr_info("wakeup trace: Couldn't activate tracepoint"
+                       " probe to kernel_sched_migrate_task\n");
+               return;
+       }
+
        wakeup_reset(tr);
 
        /*
        unregister_trace_sched_switch(probe_wakeup_sched_switch);
        unregister_trace_sched_wakeup_new(probe_wakeup);
        unregister_trace_sched_wakeup(probe_wakeup);
+       unregister_trace_sched_migrate_task(probe_wakeup_migrate_task);
 }
 
 static int __wakeup_tracer_init(struct trace_array *tr)