timekeeping: Move TAI managment into timekeeping core from ntp
[platform/adaptation/renesas_rcar/renesas_kernel.git] / kernel / time / ntp.c
index b10a42b..59e2749 100644 (file)
@@ -23,7 +23,7 @@
  * NTP timekeeping variables:
  */
 
-DEFINE_SPINLOCK(ntp_lock);
+DEFINE_RAW_SPINLOCK(ntp_lock);
 
 
 /* USER_HZ period (usecs): */
@@ -53,9 +53,6 @@ static int                    time_state = TIME_OK;
 /* clock status bits:                                                  */
 static int                     time_status = STA_UNSYNC;
 
-/* TAI offset (secs):                                                  */
-static long                    time_tai;
-
 /* time adjustment (nsecs):                                            */
 static s64                     time_offset;
 
@@ -348,7 +345,7 @@ void ntp_clear(void)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&ntp_lock, flags);
+       raw_spin_lock_irqsave(&ntp_lock, flags);
 
        time_adjust     = 0;            /* stop active adjtime() */
        time_status     |= STA_UNSYNC;
@@ -362,7 +359,7 @@ void ntp_clear(void)
 
        /* Clear PPS state variables */
        pps_clear();
-       spin_unlock_irqrestore(&ntp_lock, flags);
+       raw_spin_unlock_irqrestore(&ntp_lock, flags);
 
 }
 
@@ -372,9 +369,9 @@ u64 ntp_tick_length(void)
        unsigned long flags;
        s64 ret;
 
-       spin_lock_irqsave(&ntp_lock, flags);
+       raw_spin_lock_irqsave(&ntp_lock, flags);
        ret = tick_length;
-       spin_unlock_irqrestore(&ntp_lock, flags);
+       raw_spin_unlock_irqrestore(&ntp_lock, flags);
        return ret;
 }
 
@@ -395,7 +392,7 @@ int second_overflow(unsigned long secs)
        int leap = 0;
        unsigned long flags;
 
-       spin_lock_irqsave(&ntp_lock, flags);
+       raw_spin_lock_irqsave(&ntp_lock, flags);
 
        /*
         * Leap second processing. If in leap-insert state at the end of the
@@ -415,7 +412,6 @@ int second_overflow(unsigned long secs)
                else if (secs % 86400 == 0) {
                        leap = -1;
                        time_state = TIME_OOP;
-                       time_tai++;
                        printk(KERN_NOTICE
                                "Clock: inserting leap second 23:59:60 UTC\n");
                }
@@ -425,7 +421,6 @@ int second_overflow(unsigned long secs)
                        time_state = TIME_OK;
                else if ((secs + 1) % 86400 == 0) {
                        leap = 1;
-                       time_tai--;
                        time_state = TIME_WAIT;
                        printk(KERN_NOTICE
                                "Clock: deleting leap second 23:59:59 UTC\n");
@@ -479,7 +474,7 @@ int second_overflow(unsigned long secs)
        time_adjust = 0;
 
 out:
-       spin_unlock_irqrestore(&ntp_lock, flags);
+       raw_spin_unlock_irqrestore(&ntp_lock, flags);
 
        return leap;
 }
@@ -579,7 +574,9 @@ static inline void process_adj_status(struct timex *txc, struct timespec *ts)
  * Called with ntp_lock held, so we can access and modify
  * all the global NTP state:
  */
-static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts)
+static inline void process_adjtimex_modes(struct timex *txc,
+                                               struct timespec *ts,
+                                               s32 *time_tai)
 {
        if (txc->modes & ADJ_STATUS)
                process_adj_status(txc, ts);
@@ -613,7 +610,7 @@ static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts
        }
 
        if (txc->modes & ADJ_TAI && txc->constant > 0)
-               time_tai = txc->constant;
+               *time_tai = txc->constant;
 
        if (txc->modes & ADJ_OFFSET)
                ntp_update_offset(txc->offset);
@@ -632,6 +629,7 @@ static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts
 int do_adjtimex(struct timex *txc)
 {
        struct timespec ts;
+       u32 time_tai, orig_tai;
        int result;
 
        /* Validate the data before disabling interrupts */
@@ -671,8 +669,9 @@ int do_adjtimex(struct timex *txc)
        }
 
        getnstimeofday(&ts);
+       orig_tai = time_tai = timekeeping_get_tai_offset();
 
-       spin_lock_irq(&ntp_lock);
+       raw_spin_lock_irq(&ntp_lock);
 
        if (txc->modes & ADJ_ADJTIME) {
                long save_adjust = time_adjust;
@@ -687,7 +686,7 @@ int do_adjtimex(struct timex *txc)
 
                /* If there are input parameters, then process them: */
                if (txc->modes)
-                       process_adjtimex_modes(txc, &ts);
+                       process_adjtimex_modes(txc, &ts, &time_tai);
 
                txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ,
                                  NTP_SCALE_SHIFT);
@@ -714,7 +713,10 @@ int do_adjtimex(struct timex *txc)
        /* fill PPS status fields */
        pps_fill_timex(txc);
 
-       spin_unlock_irq(&ntp_lock);
+       raw_spin_unlock_irq(&ntp_lock);
+
+       if (time_tai != orig_tai)
+               timekeeping_set_tai_offset(time_tai);
 
        txc->time.tv_sec = ts.tv_sec;
        txc->time.tv_usec = ts.tv_nsec;
@@ -912,7 +914,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
 
        pts_norm = pps_normalize_ts(*phase_ts);
 
-       spin_lock_irqsave(&ntp_lock, flags);
+       raw_spin_lock_irqsave(&ntp_lock, flags);
 
        /* clear the error bits, they will be set again if needed */
        time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR);
@@ -925,7 +927,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
         * just start the frequency interval */
        if (unlikely(pps_fbase.tv_sec == 0)) {
                pps_fbase = *raw_ts;
-               spin_unlock_irqrestore(&ntp_lock, flags);
+               raw_spin_unlock_irqrestore(&ntp_lock, flags);
                return;
        }
 
@@ -940,7 +942,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
                time_status |= STA_PPSJITTER;
                /* restart the frequency calibration interval */
                pps_fbase = *raw_ts;
-               spin_unlock_irqrestore(&ntp_lock, flags);
+               raw_spin_unlock_irqrestore(&ntp_lock, flags);
                pr_err("hardpps: PPSJITTER: bad pulse\n");
                return;
        }
@@ -957,7 +959,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
 
        hardpps_update_phase(pts_norm.nsec);
 
-       spin_unlock_irqrestore(&ntp_lock, flags);
+       raw_spin_unlock_irqrestore(&ntp_lock, flags);
 }
 EXPORT_SYMBOL(hardpps);