aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/time/ntp.c173
1 files changed, 91 insertions, 82 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index dbd6f8905614..2586c30f0658 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -35,7 +35,7 @@ static u64 tick_length, tick_length_base;
35/* TIME_ERROR prevents overwriting the CMOS clock */ 35/* TIME_ERROR prevents overwriting the CMOS clock */
36static int time_state = TIME_OK; /* clock synchronization status */ 36static int time_state = TIME_OK; /* clock synchronization status */
37int time_status = STA_UNSYNC; /* clock status bits */ 37int time_status = STA_UNSYNC; /* clock status bits */
38static s64 time_offset; /* time adjustment (ns) */ 38static s64 time_offset; /* time adjustment (ns) */
39static long time_constant = 2; /* pll time constant */ 39static long time_constant = 2; /* pll time constant */
40long time_maxerror = NTP_PHASE_LIMIT; /* maximum error (us) */ 40long time_maxerror = NTP_PHASE_LIMIT; /* maximum error (us) */
41long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */ 41long time_esterror = NTP_PHASE_LIMIT; /* estimated error (us) */
@@ -57,6 +57,44 @@ static void ntp_update_frequency(void)
57 tick_length_base = div_u64(tick_length_base, NTP_INTERVAL_FREQ); 57 tick_length_base = div_u64(tick_length_base, NTP_INTERVAL_FREQ);
58} 58}
59 59
60static void ntp_update_offset(long offset)
61{
62 long mtemp;
63 s64 freq_adj;
64
65 if (!(time_status & STA_PLL))
66 return;
67
68 time_offset = offset * NSEC_PER_USEC;
69
70 /*
71 * Scale the phase adjustment and
72 * clamp to the operating range.
73 */
74 time_offset = min(time_offset, (s64)MAXPHASE * NSEC_PER_USEC);
75 time_offset = max(time_offset, (s64)-MAXPHASE * NSEC_PER_USEC);
76
77 /*
78 * Select how the frequency is to be controlled
79 * and in which mode (PLL or FLL).
80 */
81 if (time_status & STA_FREQHOLD || time_reftime == 0)
82 time_reftime = xtime.tv_sec;
83 mtemp = xtime.tv_sec - time_reftime;
84 time_reftime = xtime.tv_sec;
85
86 freq_adj = time_offset * mtemp;
87 freq_adj = shift_right(freq_adj, time_constant * 2 +
88 (SHIFT_PLL + 2) * 2 - SHIFT_NSEC);
89 if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC))
90 freq_adj += div_s64(time_offset << (SHIFT_NSEC - SHIFT_FLL), mtemp);
91 freq_adj += time_freq;
92 freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);
93 time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC);
94 time_offset = div_s64(time_offset, NTP_INTERVAL_FREQ);
95 time_offset <<= SHIFT_UPDATE;
96}
97
60/** 98/**
61 * ntp_clear - Clears the NTP state variables 99 * ntp_clear - Clears the NTP state variables
62 * 100 *
@@ -131,7 +169,7 @@ void second_overflow(void)
131 break; 169 break;
132 case TIME_WAIT: 170 case TIME_WAIT:
133 if (!(time_status & (STA_INS | STA_DEL))) 171 if (!(time_status & (STA_INS | STA_DEL)))
134 time_state = TIME_OK; 172 time_state = TIME_OK;
135 } 173 }
136 174
137 /* 175 /*
@@ -234,8 +272,7 @@ static inline void notify_cmos_timer(void) { }
234 */ 272 */
235int do_adjtimex(struct timex *txc) 273int do_adjtimex(struct timex *txc)
236{ 274{
237 long mtemp, save_adjust; 275 long save_adjust;
238 s64 freq_adj;
239 int result; 276 int result;
240 277
241 /* In order to modify anything, you gotta be super-user! */ 278 /* In order to modify anything, you gotta be super-user! */
@@ -272,94 +309,63 @@ int do_adjtimex(struct timex *txc)
272 time_status &= ~STA_CLOCKERR; /* reset STA_CLOCKERR */ 309 time_status &= ~STA_CLOCKERR; /* reset STA_CLOCKERR */
273#endif 310#endif
274 /* If there are input parameters, then process them */ 311 /* If there are input parameters, then process them */
275 if (txc->modes) 312 if (txc->modes) {
276 { 313 if (txc->modes & ADJ_STATUS) /* only set allowed bits */
277 if (txc->modes & ADJ_STATUS) /* only set allowed bits */ 314 time_status = (txc->status & ~STA_RONLY) |
278 time_status = (txc->status & ~STA_RONLY) | 315 (time_status & STA_RONLY);
279 (time_status & STA_RONLY); 316
280 317 if (txc->modes & ADJ_FREQUENCY) {
281 if (txc->modes & ADJ_FREQUENCY) { /* p. 22 */ 318 if (txc->freq > MAXFREQ || txc->freq < -MAXFREQ) {
282 if (txc->freq > MAXFREQ || txc->freq < -MAXFREQ) { 319 result = -EINVAL;
283 result = -EINVAL; 320 goto leave;
284 goto leave; 321 }
322 time_freq = ((s64)txc->freq * NSEC_PER_USEC)
323 >> (SHIFT_USEC - SHIFT_NSEC);
285 } 324 }
286 time_freq = ((s64)txc->freq * NSEC_PER_USEC) 325
287 >> (SHIFT_USEC - SHIFT_NSEC); 326 if (txc->modes & ADJ_MAXERROR) {
288 } 327 if (txc->maxerror < 0 || txc->maxerror >= NTP_PHASE_LIMIT) {
289 328 result = -EINVAL;
290 if (txc->modes & ADJ_MAXERROR) { 329 goto leave;
291 if (txc->maxerror < 0 || txc->maxerror >= NTP_PHASE_LIMIT) { 330 }
292 result = -EINVAL; 331 time_maxerror = txc->maxerror;
293 goto leave;
294 } 332 }
295 time_maxerror = txc->maxerror;
296 }
297 333
298 if (txc->modes & ADJ_ESTERROR) { 334 if (txc->modes & ADJ_ESTERROR) {
299 if (txc->esterror < 0 || txc->esterror >= NTP_PHASE_LIMIT) { 335 if (txc->esterror < 0 || txc->esterror >= NTP_PHASE_LIMIT) {
300 result = -EINVAL; 336 result = -EINVAL;
301 goto leave; 337 goto leave;
338 }
339 time_esterror = txc->esterror;
302 } 340 }
303 time_esterror = txc->esterror;
304 }
305 341
306 if (txc->modes & ADJ_TIMECONST) { /* p. 24 */ 342 if (txc->modes & ADJ_TIMECONST) {
307 if (txc->constant < 0) { /* NTP v4 uses values > 6 */ 343 if (txc->constant < 0) { /* NTP v4 uses values > 6 */
308 result = -EINVAL; 344 result = -EINVAL;
309 goto leave; 345 goto leave;
346 }
347 time_constant = min(txc->constant + 4, (long)MAXTC);
310 } 348 }
311 time_constant = min(txc->constant + 4, (long)MAXTC);
312 }
313 349
314 if (txc->modes & ADJ_OFFSET) { /* values checked earlier */ 350 if (txc->modes & ADJ_OFFSET) {
315 if (txc->modes == ADJ_OFFSET_SINGLESHOT) { 351 if (txc->modes == ADJ_OFFSET_SINGLESHOT)
316 /* adjtime() is independent from ntp_adjtime() */ 352 /* adjtime() is independent from ntp_adjtime() */
317 time_adjust = txc->offset; 353 time_adjust = txc->offset;
354 else
355 ntp_update_offset(txc->offset);
318 } 356 }
319 else if (time_status & STA_PLL) { 357 if (txc->modes & ADJ_TICK)
320 time_offset = txc->offset * NSEC_PER_USEC; 358 tick_usec = txc->tick;
321 359
322 /* 360 if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET))
323 * Scale the phase adjustment and 361 ntp_update_frequency();
324 * clamp to the operating range. 362 }
325 */ 363leave:
326 time_offset = min(time_offset, (s64)MAXPHASE * NSEC_PER_USEC); 364 if (time_status & (STA_UNSYNC|STA_CLOCKERR))
327 time_offset = max(time_offset, (s64)-MAXPHASE * NSEC_PER_USEC);
328
329 /*
330 * Select whether the frequency is to be controlled
331 * and in which mode (PLL or FLL). Clamp to the operating
332 * range. Ugly multiply/divide should be replaced someday.
333 */
334
335 if (time_status & STA_FREQHOLD || time_reftime == 0)
336 time_reftime = xtime.tv_sec;
337 mtemp = xtime.tv_sec - time_reftime;
338 time_reftime = xtime.tv_sec;
339
340 freq_adj = time_offset * mtemp;
341 freq_adj = shift_right(freq_adj, time_constant * 2 +
342 (SHIFT_PLL + 2) * 2 - SHIFT_NSEC);
343 if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC))
344 freq_adj += div_s64(time_offset << (SHIFT_NSEC - SHIFT_FLL), mtemp);
345 freq_adj += time_freq;
346 freq_adj = min(freq_adj, (s64)MAXFREQ_NSEC);
347 time_freq = max(freq_adj, (s64)-MAXFREQ_NSEC);
348 time_offset = div_s64(time_offset, NTP_INTERVAL_FREQ);
349 time_offset <<= SHIFT_UPDATE;
350 } /* STA_PLL */
351 } /* txc->modes & ADJ_OFFSET */
352 if (txc->modes & ADJ_TICK)
353 tick_usec = txc->tick;
354
355 if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET))
356 ntp_update_frequency();
357 } /* txc->modes */
358leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
359 result = TIME_ERROR; 365 result = TIME_ERROR;
360 366
361 if ((txc->modes == ADJ_OFFSET_SINGLESHOT) || 367 if ((txc->modes == ADJ_OFFSET_SINGLESHOT) ||
362 (txc->modes == ADJ_OFFSET_SS_READ)) 368 (txc->modes == ADJ_OFFSET_SS_READ))
363 txc->offset = save_adjust; 369 txc->offset = save_adjust;
364 else 370 else
365 txc->offset = ((long)shift_right(time_offset, SHIFT_UPDATE)) * 371 txc->offset = ((long)shift_right(time_offset, SHIFT_UPDATE)) *
@@ -384,9 +390,12 @@ leave: if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0)
384 txc->errcnt = 0; 390 txc->errcnt = 0;
385 txc->stbcnt = 0; 391 txc->stbcnt = 0;
386 write_sequnlock_irq(&xtime_lock); 392 write_sequnlock_irq(&xtime_lock);
393
387 do_gettimeofday(&txc->time); 394 do_gettimeofday(&txc->time);
395
388 notify_cmos_timer(); 396 notify_cmos_timer();
389 return(result); 397
398 return result;
390} 399}
391 400
392static int __init ntp_tick_adj_setup(char *str) 401static int __init ntp_tick_adj_setup(char *str)