summaryrefslogtreecommitdiffstats
path: root/kernel/time/ntp.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/ntp.c')
-rw-r--r--kernel/time/ntp.c51
1 files changed, 19 insertions, 32 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 9137b54613e..1ab5e9d7fa5 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -145,18 +145,11 @@ void second_overflow(void)
}
/*
- * Compute the phase adjustment for the next second. In PLL mode, the
- * offset is reduced by a fixed factor times the time constant. In FLL
- * mode the offset is used directly. In either mode, the maximum phase
- * adjustment for each second is clamped so as to spread the adjustment
- * over not more than the number of seconds between updates.
+ * Compute the phase adjustment for the next second. The offset is
+ * reduced by a fixed factor times the time constant.
*/
tick_length = tick_length_base;
- time_adj = time_offset;
- if (!(time_status & STA_FLL))
- time_adj = shift_right(time_adj, SHIFT_KG + time_constant);
- time_adj = min(time_adj, -((MAXPHASE / HZ) << SHIFT_UPDATE) / MINSEC);
- time_adj = max(time_adj, ((MAXPHASE / HZ) << SHIFT_UPDATE) / MINSEC);
+ time_adj = shift_right(time_offset, SHIFT_PLL + time_constant);
time_offset -= time_adj;
tick_length += (s64)time_adj << (TICK_LENGTH_SHIFT - SHIFT_UPDATE);
@@ -200,7 +193,7 @@ void __attribute__ ((weak)) notify_arch_cmos_timer(void)
int do_adjtimex(struct timex *txc)
{
long ltemp, mtemp, save_adjust;
- s64 freq_adj;
+ s64 freq_adj, temp64;
int result;
/* In order to modify anything, you gotta be super-user! */
@@ -270,7 +263,7 @@ int do_adjtimex(struct timex *txc)
result = -EINVAL;
goto leave;
}
- time_constant = txc->constant;
+ time_constant = min(txc->constant + 4, (long)MAXTC);
}
if (txc->modes & ADJ_OFFSET) { /* values checked earlier */
@@ -298,26 +291,20 @@ int do_adjtimex(struct timex *txc)
time_reftime = xtime.tv_sec;
mtemp = xtime.tv_sec - time_reftime;
time_reftime = xtime.tv_sec;
- freq_adj = 0;
- if (time_status & STA_FLL) {
- if (mtemp >= MINSEC) {
- freq_adj = (s64)time_offset << (SHIFT_NSEC - SHIFT_KH);
- if (time_offset < 0) {
- freq_adj = -freq_adj;
- do_div(freq_adj, mtemp);
- freq_adj = -freq_adj;
- } else
- do_div(freq_adj, mtemp);
- } else /* calibration interval too short (p. 12) */
- result = TIME_ERROR;
- } else { /* PLL mode */
- if (mtemp < MAXSEC) {
- freq_adj = (s64)ltemp * mtemp;
- freq_adj = shift_right(freq_adj,(time_constant +
- time_constant +
- SHIFT_KF - SHIFT_NSEC));
- } else /* calibration interval too long (p. 12) */
- result = TIME_ERROR;
+
+ freq_adj = (s64)time_offset * mtemp;
+ freq_adj = shift_right(freq_adj, time_constant * 2 +
+ (SHIFT_PLL + 2) * 2 - SHIFT_NSEC);
+ if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC)) {
+ temp64 = (s64)time_offset << (SHIFT_NSEC - SHIFT_FLL);
+ if (time_offset < 0) {
+ temp64 = -temp64;
+ do_div(temp64, mtemp);
+ freq_adj -= temp64;
+ } else {
+ do_div(temp64, mtemp);
+ freq_adj += temp64;
+ }
}
freq_adj += time_freq;
freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);