]> Pileus Git - ~andy/linux/blobdiff - kernel/time/ntp.c
timekeeping: Move TAI managment into timekeeping core from ntp
[~andy/linux] / kernel / time / ntp.c
index 072bb066bb7d1b26b4f5f613c3c2be464bc7c323..59e2749be0fa37c6ed4be7842fb4c267db3f91e3 100644 (file)
@@ -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;
 
@@ -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");
@@ -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,6 +669,7 @@ int do_adjtimex(struct timex *txc)
        }
 
        getnstimeofday(&ts);
+       orig_tai = time_tai = timekeeping_get_tai_offset();
 
        raw_spin_lock_irq(&ntp_lock);
 
@@ -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);
@@ -716,6 +715,9 @@ int do_adjtimex(struct timex *txc)
 
        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;
        if (!(time_status & STA_NANO))