]> Pileus Git - ~andy/linux/blobdiff - kernel/time/ntp.c
ntp: Move do_adjtimex() and hardpps() functions to timekeeping.c
[~andy/linux] / kernel / time / ntp.c
index 072bb066bb7d1b26b4f5f613c3c2be464bc7c323..8b107068d7e31d3e9732272931b91ad7afe2fc0f 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/rtc.h>
 
 #include "tick-internal.h"
+#include "ntp_internal.h"
 
 /*
  * NTP timekeeping variables:
@@ -53,9 +54,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 +413,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 +422,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 +575,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 +611,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);
@@ -625,16 +623,13 @@ static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts
                ntp_update_frequency();
 }
 
-/*
- * adjtimex mainly allows reading (and writing, if superuser) of
- * kernel time-keeping variables. used by xntpd.
+
+
+/**
+ * ntp_validate_timex - Ensures the timex is ok for use in do_adjtimex
  */
-int do_adjtimex(struct timex *txc)
+int ntp_validate_timex(struct timex *txc)
 {
-       struct timespec ts;
-       int result;
-
-       /* Validate the data before disabling interrupts */
        if (txc->modes & ADJ_ADJTIME) {
                /* singleshot must not be used with any other mode bits */
                if (!(txc->modes & ADJ_OFFSET_SINGLESHOT))
@@ -646,7 +641,6 @@ int do_adjtimex(struct timex *txc)
                /* In order to modify anything, you gotta be super-user! */
                 if (txc->modes && !capable(CAP_SYS_TIME))
                        return -EPERM;
-
                /*
                 * if the quartz is off by more than 10% then
                 * something is VERY wrong!
@@ -657,12 +651,32 @@ int do_adjtimex(struct timex *txc)
                        return -EINVAL;
        }
 
+       if ((txc->modes & ADJ_SETOFFSET) && (!capable(CAP_SYS_TIME)))
+               return -EPERM;
+
+       return 0;
+}
+
+
+/*
+ * adjtimex mainly allows reading (and writing, if superuser) of
+ * kernel time-keeping variables. used by xntpd.
+ */
+int __do_adjtimex(struct timex *txc)
+{
+       struct timespec ts;
+       u32 time_tai, orig_tai;
+       int result;
+
+       /* Validate the data before disabling interrupts */
+       result = ntp_validate_timex(txc);
+       if (result)
+               return result;
+
        if (txc->modes & ADJ_SETOFFSET) {
                struct timespec delta;
                delta.tv_sec  = txc->time.tv_sec;
                delta.tv_nsec = txc->time.tv_usec;
-               if (!capable(CAP_SYS_TIME))
-                       return -EPERM;
                if (!(txc->modes & ADJ_NANO))
                        delta.tv_nsec *= 1000;
                result = timekeeping_inject_offset(&delta);
@@ -671,6 +685,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 +702,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 +731,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))
@@ -894,7 +912,7 @@ static void hardpps_update_phase(long error)
 }
 
 /*
- * hardpps() - discipline CPU clock oscillator to external PPS signal
+ * __hardpps() - discipline CPU clock oscillator to external PPS signal
  *
  * This routine is called at each PPS signal arrival in order to
  * discipline the CPU clock oscillator to the PPS signal. It takes two
@@ -905,7 +923,7 @@ static void hardpps_update_phase(long error)
  * This code is based on David Mills's reference nanokernel
  * implementation. It was mostly rewritten but keeps the same idea.
  */
-void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
+void __hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
 {
        struct pps_normtime pts_norm, freq_norm;
        unsigned long flags;
@@ -959,8 +977,6 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts)
 
        raw_spin_unlock_irqrestore(&ntp_lock, flags);
 }
-EXPORT_SYMBOL(hardpps);
-
 #endif /* CONFIG_NTP_PPS */
 
 static int __init ntp_tick_adj_setup(char *str)