time: ntp: fix bug in ntp_update_offset() & do_adjtimex()
Impact: change (fix) the way the NTP PLL seconds offset is initialized/tracked
Fix a bug and do a micro-optimization:
When PLL is enabled we do not reset time_reftime. If the PLL
was off for a long time (for example after bootup), this is
arguably the wrong thing to do.
We already had a hack for the common boot-time case in
ntp_update_offset(), in form of:
if (unlikely(time_status & STA_FREQHOLD || time_reftime == 0))
secs = 0;
But the update delta should be reset later on too - not just when
the PLL is enabled for the first time after bootup.
So do it on !STA_PLL -> STA_PLL transitions.
This changes behavior, as previously if ntpd was disabled for
a long time and we restarted it, we'd run from that last update,
with a very large delta.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 580a350..fc08eb1 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -142,7 +142,7 @@
* and in which mode (PLL or FLL).
*/
secs = xtime.tv_sec - time_reftime;
- if (unlikely(time_status & STA_FREQHOLD || time_reftime == 0))
+ if (unlikely(time_status & STA_FREQHOLD))
secs = 0;
time_reftime = xtime.tv_sec;
@@ -394,6 +394,13 @@
}
/* only set allowed bits */
time_status &= STA_RONLY;
+ /*
+ * If we turn on PLL adjustments then reset the
+ * reference time to current time.
+ */
+ if (!(time_status & STA_PLL) && (txc->status & STA_PLL))
+ time_reftime = xtime.tv_sec;
+
time_status |= txc->status & ~STA_RONLY;
switch (time_state) {