diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/time/ntp.c | 51 |
1 files changed, 19 insertions, 32 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 9137b54613e0..1ab5e9d7fa50 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -145,18 +145,11 @@ void second_overflow(void) | |||
145 | } | 145 | } |
146 | 146 | ||
147 | /* | 147 | /* |
148 | * Compute the phase adjustment for the next second. In PLL mode, the | 148 | * Compute the phase adjustment for the next second. The offset is |
149 | * offset is reduced by a fixed factor times the time constant. In FLL | 149 | * reduced by a fixed factor times the time constant. |
150 | * mode the offset is used directly. In either mode, the maximum phase | ||
151 | * adjustment for each second is clamped so as to spread the adjustment | ||
152 | * over not more than the number of seconds between updates. | ||
153 | */ | 150 | */ |
154 | tick_length = tick_length_base; | 151 | tick_length = tick_length_base; |
155 | time_adj = time_offset; | 152 | time_adj = shift_right(time_offset, SHIFT_PLL + time_constant); |
156 | if (!(time_status & STA_FLL)) | ||
157 | time_adj = shift_right(time_adj, SHIFT_KG + time_constant); | ||
158 | time_adj = min(time_adj, -((MAXPHASE / HZ) << SHIFT_UPDATE) / MINSEC); | ||
159 | time_adj = max(time_adj, ((MAXPHASE / HZ) << SHIFT_UPDATE) / MINSEC); | ||
160 | time_offset -= time_adj; | 153 | time_offset -= time_adj; |
161 | tick_length += (s64)time_adj << (TICK_LENGTH_SHIFT - SHIFT_UPDATE); | 154 | tick_length += (s64)time_adj << (TICK_LENGTH_SHIFT - SHIFT_UPDATE); |
162 | 155 | ||
@@ -200,7 +193,7 @@ void __attribute__ ((weak)) notify_arch_cmos_timer(void) | |||
200 | int do_adjtimex(struct timex *txc) | 193 | int do_adjtimex(struct timex *txc) |
201 | { | 194 | { |
202 | long ltemp, mtemp, save_adjust; | 195 | long ltemp, mtemp, save_adjust; |
203 | s64 freq_adj; | 196 | s64 freq_adj, temp64; |
204 | int result; | 197 | int result; |
205 | 198 | ||
206 | /* In order to modify anything, you gotta be super-user! */ | 199 | /* In order to modify anything, you gotta be super-user! */ |
@@ -270,7 +263,7 @@ int do_adjtimex(struct timex *txc) | |||
270 | result = -EINVAL; | 263 | result = -EINVAL; |
271 | goto leave; | 264 | goto leave; |
272 | } | 265 | } |
273 | time_constant = txc->constant; | 266 | time_constant = min(txc->constant + 4, (long)MAXTC); |
274 | } | 267 | } |
275 | 268 | ||
276 | if (txc->modes & ADJ_OFFSET) { /* values checked earlier */ | 269 | if (txc->modes & ADJ_OFFSET) { /* values checked earlier */ |
@@ -298,26 +291,20 @@ int do_adjtimex(struct timex *txc) | |||
298 | time_reftime = xtime.tv_sec; | 291 | time_reftime = xtime.tv_sec; |
299 | mtemp = xtime.tv_sec - time_reftime; | 292 | mtemp = xtime.tv_sec - time_reftime; |
300 | time_reftime = xtime.tv_sec; | 293 | time_reftime = xtime.tv_sec; |
301 | freq_adj = 0; | 294 | |
302 | if (time_status & STA_FLL) { | 295 | freq_adj = (s64)time_offset * mtemp; |
303 | if (mtemp >= MINSEC) { | 296 | freq_adj = shift_right(freq_adj, time_constant * 2 + |
304 | freq_adj = (s64)time_offset << (SHIFT_NSEC - SHIFT_KH); | 297 | (SHIFT_PLL + 2) * 2 - SHIFT_NSEC); |
305 | if (time_offset < 0) { | 298 | if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC)) { |
306 | freq_adj = -freq_adj; | 299 | temp64 = (s64)time_offset << (SHIFT_NSEC - SHIFT_FLL); |
307 | do_div(freq_adj, mtemp); | 300 | if (time_offset < 0) { |
308 | freq_adj = -freq_adj; | 301 | temp64 = -temp64; |
309 | } else | 302 | do_div(temp64, mtemp); |
310 | do_div(freq_adj, mtemp); | 303 | freq_adj -= temp64; |
311 | } else /* calibration interval too short (p. 12) */ | 304 | } else { |
312 | result = TIME_ERROR; | 305 | do_div(temp64, mtemp); |
313 | } else { /* PLL mode */ | 306 | freq_adj += temp64; |
314 | if (mtemp < MAXSEC) { | 307 | } |
315 | freq_adj = (s64)ltemp * mtemp; | ||
316 | freq_adj = shift_right(freq_adj,(time_constant + | ||
317 | time_constant + | ||
318 | SHIFT_KF - SHIFT_NSEC)); | ||
319 | } else /* calibration interval too long (p. 12) */ | ||
320 | result = TIME_ERROR; | ||
321 | } | 308 | } |
322 | freq_adj += time_freq; | 309 | freq_adj += time_freq; |
323 | freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC); | 310 | freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC); |