|
@@ -34,8 +34,6 @@ unsigned long tick_nsec;
|
|
|
static u64 tick_length;
|
|
|
static u64 tick_length_base;
|
|
|
|
|
|
-static struct hrtimer leap_timer;
|
|
|
-
|
|
|
#define MAX_TICKADJ 500LL /* usecs */
|
|
|
#define MAX_TICKADJ_SCALED \
|
|
|
(((MAX_TICKADJ * NSEC_PER_USEC) << NTP_SCALE_SHIFT) / NTP_INTERVAL_FREQ)
|
|
@@ -381,70 +379,63 @@ u64 ntp_tick_length(void)
|
|
|
|
|
|
|
|
|
/*
|
|
|
- * Leap second processing. If in leap-insert state at the end of the
|
|
|
- * day, the system clock is set back one second; if in leap-delete
|
|
|
- * state, the system clock is set ahead one second.
|
|
|
+ * this routine handles the overflow of the microsecond field
|
|
|
+ *
|
|
|
+ * The tricky bits of code to handle the accurate clock support
|
|
|
+ * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
|
|
|
+ * They were originally developed for SUN and DEC kernels.
|
|
|
+ * All the kudos should go to Dave for this stuff.
|
|
|
+ *
|
|
|
+ * Also handles leap second processing, and returns leap offset
|
|
|
*/
|
|
|
-static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer)
|
|
|
+int second_overflow(unsigned long secs)
|
|
|
{
|
|
|
- enum hrtimer_restart res = HRTIMER_NORESTART;
|
|
|
- unsigned long flags;
|
|
|
+ s64 delta;
|
|
|
int leap = 0;
|
|
|
+ unsigned long flags;
|
|
|
|
|
|
spin_lock_irqsave(&ntp_lock, flags);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Leap second processing. If in leap-insert state at the end of the
|
|
|
+ * day, the system clock is set back one second; if in leap-delete
|
|
|
+ * state, the system clock is set ahead one second.
|
|
|
+ */
|
|
|
switch (time_state) {
|
|
|
case TIME_OK:
|
|
|
+ if (time_status & STA_INS)
|
|
|
+ time_state = TIME_INS;
|
|
|
+ else if (time_status & STA_DEL)
|
|
|
+ time_state = TIME_DEL;
|
|
|
break;
|
|
|
case TIME_INS:
|
|
|
- leap = -1;
|
|
|
- time_state = TIME_OOP;
|
|
|
- printk(KERN_NOTICE
|
|
|
- "Clock: inserting leap second 23:59:60 UTC\n");
|
|
|
- hrtimer_add_expires_ns(&leap_timer, NSEC_PER_SEC);
|
|
|
- res = HRTIMER_RESTART;
|
|
|
+ if (secs % 86400 == 0) {
|
|
|
+ leap = -1;
|
|
|
+ time_state = TIME_OOP;
|
|
|
+ printk(KERN_NOTICE
|
|
|
+ "Clock: inserting leap second 23:59:60 UTC\n");
|
|
|
+ }
|
|
|
break;
|
|
|
case TIME_DEL:
|
|
|
- leap = 1;
|
|
|
- time_tai--;
|
|
|
- time_state = TIME_WAIT;
|
|
|
- printk(KERN_NOTICE
|
|
|
- "Clock: deleting leap second 23:59:59 UTC\n");
|
|
|
+ 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");
|
|
|
+ }
|
|
|
break;
|
|
|
case TIME_OOP:
|
|
|
time_tai++;
|
|
|
time_state = TIME_WAIT;
|
|
|
- /* fall through */
|
|
|
+ break;
|
|
|
+
|
|
|
case TIME_WAIT:
|
|
|
if (!(time_status & (STA_INS | STA_DEL)))
|
|
|
time_state = TIME_OK;
|
|
|
break;
|
|
|
}
|
|
|
- spin_unlock_irqrestore(&ntp_lock, flags);
|
|
|
-
|
|
|
- /*
|
|
|
- * We have to call this outside of the ntp_lock to keep
|
|
|
- * the proper locking hierarchy
|
|
|
- */
|
|
|
- if (leap)
|
|
|
- timekeeping_leap_insert(leap);
|
|
|
-
|
|
|
- return res;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * this routine handles the overflow of the microsecond field
|
|
|
- *
|
|
|
- * The tricky bits of code to handle the accurate clock support
|
|
|
- * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
|
|
|
- * They were originally developed for SUN and DEC kernels.
|
|
|
- * All the kudos should go to Dave for this stuff.
|
|
|
- */
|
|
|
-void second_overflow(void)
|
|
|
-{
|
|
|
- s64 delta;
|
|
|
- unsigned long flags;
|
|
|
|
|
|
- spin_lock_irqsave(&ntp_lock, flags);
|
|
|
|
|
|
/* Bump the maxerror field */
|
|
|
time_maxerror += MAXFREQ / NSEC_PER_USEC;
|
|
@@ -481,8 +472,13 @@ void second_overflow(void)
|
|
|
tick_length += (s64)(time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ)
|
|
|
<< NTP_SCALE_SHIFT;
|
|
|
time_adjust = 0;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
out:
|
|
|
spin_unlock_irqrestore(&ntp_lock, flags);
|
|
|
+
|
|
|
+ return leap;
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_GENERIC_CMOS_UPDATE
|
|
@@ -544,27 +540,6 @@ static void notify_cmos_timer(void)
|
|
|
static inline void notify_cmos_timer(void) { }
|
|
|
#endif
|
|
|
|
|
|
-/*
|
|
|
- * Start the leap seconds timer:
|
|
|
- */
|
|
|
-static inline void ntp_start_leap_timer(struct timespec *ts)
|
|
|
-{
|
|
|
- long now = ts->tv_sec;
|
|
|
-
|
|
|
- if (time_status & STA_INS) {
|
|
|
- time_state = TIME_INS;
|
|
|
- now += 86400 - now % 86400;
|
|
|
- hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS);
|
|
|
-
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- if (time_status & STA_DEL) {
|
|
|
- time_state = TIME_DEL;
|
|
|
- now += 86400 - (now + 1) % 86400;
|
|
|
- hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS);
|
|
|
- }
|
|
|
-}
|
|
|
|
|
|
/*
|
|
|
* Propagate a new txc->status value into the NTP state:
|
|
@@ -589,22 +564,6 @@ static inline void process_adj_status(struct timex *txc, struct timespec *ts)
|
|
|
time_status &= STA_RONLY;
|
|
|
time_status |= txc->status & ~STA_RONLY;
|
|
|
|
|
|
- switch (time_state) {
|
|
|
- case TIME_OK:
|
|
|
- ntp_start_leap_timer(ts);
|
|
|
- break;
|
|
|
- case TIME_INS:
|
|
|
- case TIME_DEL:
|
|
|
- time_state = TIME_OK;
|
|
|
- ntp_start_leap_timer(ts);
|
|
|
- case TIME_WAIT:
|
|
|
- if (!(time_status & (STA_INS | STA_DEL)))
|
|
|
- time_state = TIME_OK;
|
|
|
- break;
|
|
|
- case TIME_OOP:
|
|
|
- hrtimer_restart(&leap_timer);
|
|
|
- break;
|
|
|
- }
|
|
|
}
|
|
|
/*
|
|
|
* Called with the xtime lock held, so we can access and modify
|
|
@@ -686,9 +645,6 @@ int do_adjtimex(struct timex *txc)
|
|
|
(txc->tick < 900000/USER_HZ ||
|
|
|
txc->tick > 1100000/USER_HZ))
|
|
|
return -EINVAL;
|
|
|
-
|
|
|
- if (txc->modes & ADJ_STATUS && time_state != TIME_OK)
|
|
|
- hrtimer_cancel(&leap_timer);
|
|
|
}
|
|
|
|
|
|
if (txc->modes & ADJ_SETOFFSET) {
|
|
@@ -1010,6 +966,4 @@ __setup("ntp_tick_adj=", ntp_tick_adj_setup);
|
|
|
void __init ntp_init(void)
|
|
|
{
|
|
|
ntp_clear();
|
|
|
- hrtimer_init(&leap_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
|
|
|
- leap_timer.function = ntp_leap_second;
|
|
|
}
|