ntp: support for TAI
Roman Zippel [Thu, 1 May 2008 11:34:37 +0000 (04:34 -0700)]
This adds support for setting the TAI value (International Atomic Time).  The
value is reported back to userspace via timex (as we don't have a
ntp_gettime() syscall).

Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Cc: john stultz <johnstul@us.ibm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

include/linux/compat.h
include/linux/timex.h
kernel/compat.c
kernel/time/ntp.c

index 8fa7857..cf8d11c 100644 (file)
@@ -65,10 +65,11 @@ struct compat_timex {
        compat_long_t calcnt;
        compat_long_t errcnt;
        compat_long_t stbcnt;
+       compat_int_t tai;
 
        compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32;
        compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32;
-       compat_int_t :32; compat_int_t :32; compat_int_t :32; compat_int_t :32;
+       compat_int_t :32; compat_int_t :32; compat_int_t :32;
 };
 
 #define _COMPAT_NSIG_WORDS     (_COMPAT_NSIG / _COMPAT_NSIG_BPW)
index 9fbdd12..6ff9223 100644 (file)
@@ -121,9 +121,11 @@ struct timex {
        long errcnt;            /* calibration errors (ro) */
        long stbcnt;            /* stability limit exceeded (ro) */
 
+       int tai;                /* TAI offset (ro) */
+
        int  :32; int  :32; int  :32; int  :32;
        int  :32; int  :32; int  :32; int  :32;
-       int  :32; int  :32; int  :32; int  :32;
+       int  :32; int  :32; int  :32;
 };
 
 /*
@@ -135,6 +137,7 @@ struct timex {
 #define ADJ_ESTERROR           0x0008  /* estimated time error */
 #define ADJ_STATUS             0x0010  /* clock status */
 #define ADJ_TIMECONST          0x0020  /* pll time constant */
+#define ADJ_TAI                        0x0080  /* set TAI offset */
 #define ADJ_MICRO              0x1000  /* select microsecond resolution */
 #define ADJ_NANO               0x2000  /* select nanosecond resolution */
 #define ADJ_TICK               0x4000  /* tick value */
index 4a856a3..32c254a 100644 (file)
@@ -955,7 +955,8 @@ asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp)
                        __put_user(txc.jitcnt, &utp->jitcnt) ||
                        __put_user(txc.calcnt, &utp->calcnt) ||
                        __put_user(txc.errcnt, &utp->errcnt) ||
-                       __put_user(txc.stbcnt, &utp->stbcnt))
+                       __put_user(txc.stbcnt, &utp->stbcnt) ||
+                       __put_user(txc.tai, &utp->tai))
                ret = -EFAULT;
 
        return ret;
index 44491de..10fe17d 100644 (file)
@@ -35,6 +35,7 @@ static u64 tick_length, tick_length_base;
 /* TIME_ERROR prevents overwriting the CMOS clock */
 static int time_state = TIME_OK;       /* clock synchronization status */
 int time_status = STA_UNSYNC;          /* clock status bits            */
+static long time_tai;                  /* TAI offset (s)               */
 static s64 time_offset;                        /* time adjustment (ns)         */
 static long time_constant = 2;         /* pll time constant            */
 long time_maxerror = NTP_PHASE_LIMIT;  /* maximum error (us)           */
@@ -162,6 +163,7 @@ void second_overflow(void)
        case TIME_DEL:
                if ((xtime.tv_sec + 1) % 86400 == 0) {
                        xtime.tv_sec++;
+                       time_tai--;
                        wall_to_monotonic.tv_sec--;
                        time_state = TIME_WAIT;
                        printk(KERN_NOTICE "Clock: deleting leap second "
@@ -169,6 +171,7 @@ void second_overflow(void)
                }
                break;
        case TIME_OOP:
+               time_tai++;
                time_state = TIME_WAIT;
                break;
        case TIME_WAIT:
@@ -340,6 +343,9 @@ int do_adjtimex(struct timex *txc)
                        time_constant = max(time_constant, 0l);
                }
 
+               if (txc->modes & ADJ_TAI && txc->constant > 0)
+                       time_tai = txc->constant;
+
                if (txc->modes & ADJ_OFFSET) {
                        if (txc->modes == ADJ_OFFSET_SINGLESHOT)
                                /* adjtime() is independent from ntp_adjtime() */
@@ -377,6 +383,7 @@ int do_adjtimex(struct timex *txc)
        txc->precision     = 1;
        txc->tolerance     = MAXFREQ_SCALED / PPM_SCALE;
        txc->tick          = tick_usec;
+       txc->tai           = time_tai;
 
        /* PPS is not implemented, so these are zero */
        txc->ppsfreq       = 0;