Merge branch 'v3.10/topic/configs' of git://git.linaro.org/kernel/linux-linaro-stable...
[firefly-linux-kernel-4.4.55.git] / kernel / time / timekeeping.c
index d81b1117561c678a5b6968e3f26a9c8c81bc8ac5..76fefb1613b29d2606edc863e8b819cabd9ef171 100644 (file)
@@ -1239,9 +1239,10 @@ out_adjust:
  * It also calls into the NTP code to handle leapsecond processing.
  *
  */
-static inline void accumulate_nsecs_to_secs(struct timekeeper *tk)
+static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk)
 {
        u64 nsecps = (u64)NSEC_PER_SEC << tk->shift;
+       unsigned int clock_set = 0;
 
        while (tk->xtime_nsec >= nsecps) {
                int leap;
@@ -1263,9 +1264,10 @@ static inline void accumulate_nsecs_to_secs(struct timekeeper *tk)
 
                        __timekeeping_set_tai_offset(tk, tk->tai_offset - leap);
 
-                       clock_was_set_delayed();
+                       clock_set = 1;
                }
        }
+       return clock_set;
 }
 
 /**
@@ -1278,7 +1280,8 @@ static inline void accumulate_nsecs_to_secs(struct timekeeper *tk)
  * Returns the unconsumed cycles.
  */
 static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
-                                               u32 shift)
+                                               u32 shift,
+                                               unsigned int *clock_set)
 {
        cycle_t interval = tk->cycle_interval << shift;
        u64 raw_nsecs;
@@ -1292,7 +1295,7 @@ static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
        tk->cycle_last += interval;
 
        tk->xtime_nsec += tk->xtime_interval << shift;
-       accumulate_nsecs_to_secs(tk);
+       *clock_set |= accumulate_nsecs_to_secs(tk);
 
        /* Accumulate raw time */
        raw_nsecs = (u64)tk->raw_interval << shift;
@@ -1350,6 +1353,7 @@ static void update_wall_time(void)
        struct timekeeper *tk = &shadow_timekeeper;
        cycle_t offset;
        int shift = 0, maxshift;
+       unsigned int clock_set = 0;
        unsigned long flags;
 
        raw_spin_lock_irqsave(&timekeeper_lock, flags);
@@ -1384,7 +1388,8 @@ static void update_wall_time(void)
        maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1;
        shift = min(shift, maxshift);
        while (offset >= tk->cycle_interval) {
-               offset = logarithmic_accumulation(tk, offset, shift);
+               offset = logarithmic_accumulation(tk, offset, shift,
+                                                       &clock_set);
                if (offset < tk->cycle_interval<<shift)
                        shift--;
        }
@@ -1402,7 +1407,7 @@ static void update_wall_time(void)
         * Finally, make sure that after the rounding
         * xtime_nsec isn't larger than NSEC_PER_SEC
         */
-       accumulate_nsecs_to_secs(tk);
+       clock_set |= accumulate_nsecs_to_secs(tk);
 
        write_seqcount_begin(&timekeeper_seq);
        /* Update clock->cycle_last with the new value */
@@ -1422,6 +1427,10 @@ static void update_wall_time(void)
        write_seqcount_end(&timekeeper_seq);
 out:
        raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
+       if (clock_set)
+               /* have to call outside the timekeeper_seq */
+               clock_was_set_delayed();
+
 }
 
 /**
@@ -1681,11 +1690,13 @@ int do_adjtimex(struct timex *txc)
        if (tai != orig_tai) {
                __timekeeping_set_tai_offset(tk, tai);
                timekeeping_update(tk, false, true);
-               clock_was_set_delayed();
        }
        write_seqcount_end(&timekeeper_seq);
        raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
 
+       if (tai != orig_tai)
+               clock_was_set();
+
        ntp_notify_cmos_timer();
 
        return ret;