relay file read: start-pos fix
[linux-drm-fsl-dcu.git] / kernel / hrtimer.c
index ec4cb9f3e3b70c39044cf2ed41b6d7d3785f8d37..23c03f43e1962d6f0dfa4cb8a716080cf671a48c 100644 (file)
@@ -59,6 +59,7 @@ ktime_t ktime_get(void)
 
        return timespec_to_ktime(now);
 }
+EXPORT_SYMBOL_GPL(ktime_get);
 
 /**
  * ktime_get_real - get the real (wall-) time in ktime_t format
@@ -135,7 +136,7 @@ EXPORT_SYMBOL_GPL(ktime_get_ts);
 static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base)
 {
        ktime_t xtim, tomono;
-       struct timespec xts;
+       struct timespec xts, tom;
        unsigned long seq;
 
        do {
@@ -145,10 +146,11 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base)
 #else
                xts = xtime;
 #endif
+               tom = wall_to_monotonic;
        } while (read_seqretry(&xtime_lock, seq));
 
        xtim = timespec_to_ktime(xts);
-       tomono = timespec_to_ktime(wall_to_monotonic);
+       tomono = timespec_to_ktime(tom);
        base->clock_base[CLOCK_REALTIME].softirq_time = xtim;
        base->clock_base[CLOCK_MONOTONIC].softirq_time =
                ktime_add(xtim, tomono);
@@ -277,6 +279,8 @@ ktime_t ktime_add_ns(const ktime_t kt, u64 nsec)
 
        return ktime_add(kt, tmp);
 }
+
+EXPORT_SYMBOL_GPL(ktime_add_ns);
 # endif /* !CONFIG_KTIME_SCALAR */
 
 /*
@@ -457,6 +461,18 @@ void clock_was_set(void)
        on_each_cpu(retrigger_next_event, NULL, 0, 1);
 }
 
+/*
+ * During resume we might have to reprogram the high resolution timer
+ * interrupt (on the local CPU):
+ */
+void hres_timers_resume(void)
+{
+       WARN_ON_ONCE(num_online_cpus() > 1);
+
+       /* Retrigger the CPU local events: */
+       retrigger_next_event(NULL);
+}
+
 /*
  * Check, whether the timer is on the callback pending list
  */
@@ -644,9 +660,16 @@ hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
                orun++;
        }
        timer->expires = ktime_add(timer->expires, interval);
+       /*
+        * Make sure, that the result did not wrap with a very large
+        * interval.
+        */
+       if (timer->expires.tv64 < 0)
+               timer->expires = ktime_set(KTIME_SEC_MAX, 0);
 
        return orun;
 }
+EXPORT_SYMBOL_GPL(hrtimer_forward);
 
 /*
  * enqueue_hrtimer - internal function to (re)start a timer
@@ -807,7 +830,12 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
 
        timer_stats_hrtimer_set_start_info(timer);
 
-       enqueue_hrtimer(timer, new_base, base == new_base);
+       /*
+        * Only allow reprogramming if the new base is on this CPU.
+        * (it might still be on another CPU if the timer was pending)
+        */
+       enqueue_hrtimer(timer, new_base,
+                       new_base->cpu_base == &__get_cpu_var(hrtimer_bases));
 
        unlock_hrtimer_base(timer, &flags);
 
@@ -1383,11 +1411,13 @@ static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self,
        switch (action) {
 
        case CPU_UP_PREPARE:
+       case CPU_UP_PREPARE_FROZEN:
                init_hrtimers_cpu(cpu);
                break;
 
 #ifdef CONFIG_HOTPLUG_CPU
        case CPU_DEAD:
+       case CPU_DEAD_FROZEN:
                clockevents_notify(CLOCK_EVT_NOTIFY_CPU_DEAD, &cpu);
                migrate_hrtimers(cpu);
                break;