msm: event_timer: Fix potential race condition

There is a possible race condition which could happen in the following
scenario:

Core 0 PC: lock_hrtimer_base

 lock_hrtimer_base
 hrtimer_get_remaining
 get_next_event_time
 msm_pm_idle_prepare
 msm_cpuidle_enter

Core 1 PC: generic_exec_single

 generic_exec_single
 smp_call_function_single
 setup_event_timer
 mdp_update_pm

If core0 idle thread runs before core1 has had the chance to make the
smp_call_function_single, then idle thread could end up spinning on
lock_hrtimer_base() since setup_event_timer adds an event to the event
queue but the smp cross call is the one that initializes the event timer.
So Core0 could spin on lock_hrtimer_base() since CPU1's SMP call won't be
handled as idle thread runs in noirq context.

To prevent this scenario make a change to the code flow to do the queue
operations and the timer operations on the same CPU. Meaning
setup_event_timer will only make an SMP cross call to re-organize the event
queue and reset the event timer all of which will be run on CPU0.

CRs-fixed: 425587
Change-Id: I53fc551d18f350c47e05a94976b56a5fd2e9050b
Signed-off-by: Girish Mahadevan <girishm@codeaurora.org>
(cherry picked from commit e73869cb18ee79bd0b951fd7effd6565ce7ccfb4)
diff --git a/arch/arm/mach-msm/event_timer.c b/arch/arm/mach-msm/event_timer.c
index e06dad4..9f46f68 100644
--- a/arch/arm/mach-msm/event_timer.c
+++ b/arch/arm/mach-msm/event_timer.c
@@ -193,21 +193,7 @@
 	unsigned long flags;
 	struct event_timer_info *event =
 		(struct event_timer_info *)data;
-
-	local_irq_save(flags);
-	create_hrtimer(event->node.expires);
-	local_irq_restore(flags);
-}
-
-/**
- *  setup_timer() : Helper function to setup timer on primary
- *                  core during hrtimer callback.
- *  @event: event handle causing the wakeup.
- */
-static void setup_event_hrtimer(struct event_timer_info *event)
-{
 	struct timerqueue_node *next;
-	unsigned long flags;
 
 	spin_lock_irqsave(&event_timer_lock, flags);
 	if (is_event_active(event))
@@ -223,9 +209,18 @@
 		if (msm_event_debug_mask && MSM_EVENT_TIMER_DEBUG)
 			pr_info("%s: Setting timer for %lu", __func__,
 			(unsigned long)ktime_to_ns(event->node.expires));
+		create_hrtimer(event->node.expires);
+	}
+}
 
-		smp_call_function_single(0, create_timer_smp, event, 1);
-		}
+/**
+ *  setup_timer() : Helper function to setup timer on primary
+ *                  core during hrtimer callback.
+ *  @event: event handle causing the wakeup.
+ */
+static void setup_event_hrtimer(struct event_timer_info *event)
+{
+	smp_call_function_single(0, create_timer_smp, event, 1);
 }
 
 /**