diff options
author | Roman Zippel <zippel@linux-m68k.org> | 2006-10-01 02:28:27 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-01 03:39:27 -0400 |
commit | 04b617e71e363e640e88be1e43f53fa6a3afef9f (patch) | |
tree | b59e8e75e4671bc5e10f4fcaace85d4658d4d0f0 | |
parent | 97eebe138caaf78354b1fad233e63bafdcc4fd54 (diff) |
[PATCH] ntp: convert time_freq to nsec value
This converts time_freq to a scaled nsec value and adds around 6bit of extra
resolution. This pushes the time_freq to its 32bit limits so the calculatons
have to be done with 64bit.
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Cc: john stultz <johnstul@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | include/linux/timex.h | 2 | ||||
-rw-r--r-- | kernel/time/ntp.c | 36 |
2 files changed, 24 insertions, 14 deletions
diff --git a/include/linux/timex.h b/include/linux/timex.h index 7715b4c0caf9..671609ee1a3d 100644 --- a/include/linux/timex.h +++ b/include/linux/timex.h | |||
@@ -91,10 +91,12 @@ | |||
91 | #define SHIFT_SCALE 22 /* phase scale (shift) */ | 91 | #define SHIFT_SCALE 22 /* phase scale (shift) */ |
92 | #define SHIFT_UPDATE (SHIFT_HZ + 1) /* time offset scale (shift) */ | 92 | #define SHIFT_UPDATE (SHIFT_HZ + 1) /* time offset scale (shift) */ |
93 | #define SHIFT_USEC 16 /* frequency offset scale (shift) */ | 93 | #define SHIFT_USEC 16 /* frequency offset scale (shift) */ |
94 | #define SHIFT_NSEC 12 /* kernel frequency offset scale */ | ||
94 | #define FINENSEC (1L << (SHIFT_SCALE - 10)) /* ~1 ns in phase units */ | 95 | #define FINENSEC (1L << (SHIFT_SCALE - 10)) /* ~1 ns in phase units */ |
95 | 96 | ||
96 | #define MAXPHASE 512000L /* max phase error (us) */ | 97 | #define MAXPHASE 512000L /* max phase error (us) */ |
97 | #define MAXFREQ (512L << SHIFT_USEC) /* max frequency error (ppm) */ | 98 | #define MAXFREQ (512L << SHIFT_USEC) /* max frequency error (ppm) */ |
99 | #define MAXFREQ_NSEC (512000L << SHIFT_NSEC) /* max frequency error (ppb) */ | ||
98 | #define MINSEC 16L /* min interval between updates (s) */ | 100 | #define MINSEC 16L /* min interval between updates (s) */ |
99 | #define MAXSEC 1200L /* max interval between updates (s) */ | 101 | #define MAXSEC 1200L /* max interval between updates (s) */ |
100 | #define NTP_PHASE_LIMIT (MAXPHASE << 5) /* beyond max. dispersion */ | 102 | #define NTP_PHASE_LIMIT (MAXPHASE << 5) /* beyond max. dispersion */ |
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; |