diff options
Diffstat (limited to 'kernel/time')
-rw-r--r-- | kernel/time/ntp.c | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index af7563f5d4e2..9137b54613e0 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -66,7 +66,7 @@ void ntp_update_frequency(void) | |||
66 | { | 66 | { |
67 | tick_length_base = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT; | 67 | tick_length_base = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << TICK_LENGTH_SHIFT; |
68 | tick_length_base += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT; | 68 | tick_length_base += (s64)CLOCK_TICK_ADJUST << TICK_LENGTH_SHIFT; |
69 | tick_length_base += ((s64)time_freq * NSEC_PER_USEC) << (TICK_LENGTH_SHIFT - SHIFT_USEC); | 69 | tick_length_base += (s64)time_freq << (TICK_LENGTH_SHIFT - SHIFT_NSEC); |
70 | 70 | ||
71 | do_div(tick_length_base, HZ); | 71 | do_div(tick_length_base, HZ); |
72 | 72 | ||
@@ -200,6 +200,7 @@ void __attribute__ ((weak)) notify_arch_cmos_timer(void) | |||
200 | int do_adjtimex(struct timex *txc) | 200 | int do_adjtimex(struct timex *txc) |
201 | { | 201 | { |
202 | long ltemp, mtemp, save_adjust; | 202 | long ltemp, mtemp, save_adjust; |
203 | s64 freq_adj; | ||
203 | int result; | 204 | int result; |
204 | 205 | ||
205 | /* In order to modify anything, you gotta be super-user! */ | 206 | /* In order to modify anything, you gotta be super-user! */ |
@@ -245,7 +246,7 @@ int do_adjtimex(struct timex *txc) | |||
245 | result = -EINVAL; | 246 | result = -EINVAL; |
246 | goto leave; | 247 | goto leave; |
247 | } | 248 | } |
248 | time_freq = txc->freq; | 249 | time_freq = ((s64)txc->freq * NSEC_PER_USEC) >> (SHIFT_USEC - SHIFT_NSEC); |
249 | } | 250 | } |
250 | 251 | ||
251 | if (txc->modes & ADJ_MAXERROR) { | 252 | if (txc->modes & ADJ_MAXERROR) { |
@@ -278,14 +279,14 @@ int do_adjtimex(struct timex *txc) | |||
278 | time_adjust = txc->offset; | 279 | time_adjust = txc->offset; |
279 | } | 280 | } |
280 | else if (time_status & STA_PLL) { | 281 | else if (time_status & STA_PLL) { |
281 | ltemp = txc->offset; | 282 | ltemp = txc->offset * NSEC_PER_USEC; |
282 | 283 | ||
283 | /* | 284 | /* |
284 | * Scale the phase adjustment and | 285 | * Scale the phase adjustment and |
285 | * clamp to the operating range. | 286 | * clamp to the operating range. |
286 | */ | 287 | */ |
287 | time_offset = min(ltemp, MAXPHASE); | 288 | time_offset = min(ltemp, MAXPHASE * NSEC_PER_USEC); |
288 | time_offset = max(time_offset, -MAXPHASE); | 289 | time_offset = max(time_offset, -MAXPHASE * NSEC_PER_USEC); |
289 | 290 | ||
290 | /* | 291 | /* |
291 | * Select whether the frequency is to be controlled | 292 | * Select whether the frequency is to be controlled |
@@ -297,24 +298,31 @@ int do_adjtimex(struct timex *txc) | |||
297 | time_reftime = xtime.tv_sec; | 298 | time_reftime = xtime.tv_sec; |
298 | mtemp = xtime.tv_sec - time_reftime; | 299 | mtemp = xtime.tv_sec - time_reftime; |
299 | time_reftime = xtime.tv_sec; | 300 | time_reftime = xtime.tv_sec; |
301 | freq_adj = 0; | ||
300 | if (time_status & STA_FLL) { | 302 | if (time_status & STA_FLL) { |
301 | if (mtemp >= MINSEC) { | 303 | if (mtemp >= MINSEC) { |
302 | ltemp = ((time_offset << 12) / mtemp) << (SHIFT_USEC - 12); | 304 | freq_adj = (s64)time_offset << (SHIFT_NSEC - SHIFT_KH); |
303 | time_freq += shift_right(ltemp, SHIFT_KH); | 305 | if (time_offset < 0) { |
306 | freq_adj = -freq_adj; | ||
307 | do_div(freq_adj, mtemp); | ||
308 | freq_adj = -freq_adj; | ||
309 | } else | ||
310 | do_div(freq_adj, mtemp); | ||
304 | } else /* calibration interval too short (p. 12) */ | 311 | } else /* calibration interval too short (p. 12) */ |
305 | result = TIME_ERROR; | 312 | result = TIME_ERROR; |
306 | } else { /* PLL mode */ | 313 | } else { /* PLL mode */ |
307 | if (mtemp < MAXSEC) { | 314 | if (mtemp < MAXSEC) { |
308 | ltemp *= mtemp; | 315 | freq_adj = (s64)ltemp * mtemp; |
309 | time_freq += shift_right(ltemp,(time_constant + | 316 | freq_adj = shift_right(freq_adj,(time_constant + |
310 | time_constant + | 317 | time_constant + |
311 | SHIFT_KF - SHIFT_USEC)); | 318 | SHIFT_KF - SHIFT_NSEC)); |
312 | } else /* calibration interval too long (p. 12) */ | 319 | } else /* calibration interval too long (p. 12) */ |
313 | result = TIME_ERROR; | 320 | result = TIME_ERROR; |
314 | } | 321 | } |
315 | time_freq = min(time_freq, MAXFREQ); | 322 | freq_adj += time_freq; |
316 | time_freq = max(time_freq, -MAXFREQ); | 323 | freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC); |
317 | time_offset = (time_offset * NSEC_PER_USEC / HZ) << SHIFT_UPDATE; | 324 | time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC); |
325 | time_offset = (time_offset / HZ) << SHIFT_UPDATE; | ||
318 | } /* STA_PLL */ | 326 | } /* STA_PLL */ |
319 | } /* txc->modes & ADJ_OFFSET */ | 327 | } /* txc->modes & ADJ_OFFSET */ |
320 | if (txc->modes & ADJ_TICK) | 328 | if (txc->modes & ADJ_TICK) |
@@ -330,7 +338,7 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0) | |||
330 | txc->offset = save_adjust; | 338 | txc->offset = save_adjust; |
331 | else | 339 | else |
332 | txc->offset = shift_right(time_offset, SHIFT_UPDATE) * HZ / 1000; | 340 | txc->offset = shift_right(time_offset, SHIFT_UPDATE) * HZ / 1000; |
333 | txc->freq = time_freq; | 341 | txc->freq = (time_freq / NSEC_PER_USEC) << (SHIFT_USEC - SHIFT_NSEC); |
334 | txc->maxerror = time_maxerror; | 342 | txc->maxerror = time_maxerror; |
335 | txc->esterror = time_esterror; | 343 | txc->esterror = time_esterror; |
336 | txc->status = time_status; | 344 | txc->status = time_status; |