diff options
Diffstat (limited to 'kernel/time/ntp.c')
-rw-r--r-- | kernel/time/ntp.c | 182 |
1 files changed, 99 insertions, 83 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index fc08eb10ced4..aded09be98cc 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -332,6 +332,102 @@ static void notify_cmos_timer(void) | |||
332 | static inline void notify_cmos_timer(void) { } | 332 | static inline void notify_cmos_timer(void) { } |
333 | #endif | 333 | #endif |
334 | 334 | ||
335 | |||
336 | /* | ||
337 | * Propagate a new txc->status value into the NTP state: | ||
338 | */ | ||
339 | static inline void process_adj_status(struct timex *txc, struct timespec *ts) | ||
340 | { | ||
341 | long now; | ||
342 | |||
343 | if ((time_status & STA_PLL) && !(txc->status & STA_PLL)) { | ||
344 | time_state = TIME_OK; | ||
345 | time_status = STA_UNSYNC; | ||
346 | } | ||
347 | /* only set allowed bits */ | ||
348 | time_status &= STA_RONLY; | ||
349 | |||
350 | /* | ||
351 | * If we turn on PLL adjustments then reset the | ||
352 | * reference time to current time. | ||
353 | */ | ||
354 | if (!(time_status & STA_PLL) && (txc->status & STA_PLL)) | ||
355 | time_reftime = xtime.tv_sec; | ||
356 | |||
357 | time_status |= txc->status & ~STA_RONLY; | ||
358 | |||
359 | switch (time_state) { | ||
360 | case TIME_OK: | ||
361 | start_timer: | ||
362 | now = ts->tv_sec; | ||
363 | if (time_status & STA_INS) { | ||
364 | time_state = TIME_INS; | ||
365 | now += 86400 - now % 86400; | ||
366 | hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS); | ||
367 | } else if (time_status & STA_DEL) { | ||
368 | time_state = TIME_DEL; | ||
369 | now += 86400 - (now + 1) % 86400; | ||
370 | hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS); | ||
371 | } | ||
372 | break; | ||
373 | case TIME_INS: | ||
374 | case TIME_DEL: | ||
375 | time_state = TIME_OK; | ||
376 | goto start_timer; | ||
377 | case TIME_WAIT: | ||
378 | if (!(time_status & (STA_INS | STA_DEL))) | ||
379 | time_state = TIME_OK; | ||
380 | break; | ||
381 | case TIME_OOP: | ||
382 | hrtimer_restart(&leap_timer); | ||
383 | break; | ||
384 | } | ||
385 | } | ||
386 | /* | ||
387 | * Called with the xtime lock held, so we can access and modify | ||
388 | * all the global NTP state: | ||
389 | */ | ||
390 | static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts) | ||
391 | { | ||
392 | if (txc->modes & ADJ_STATUS) | ||
393 | process_adj_status(txc, ts); | ||
394 | |||
395 | if (txc->modes & ADJ_NANO) | ||
396 | time_status |= STA_NANO; | ||
397 | if (txc->modes & ADJ_MICRO) | ||
398 | time_status &= ~STA_NANO; | ||
399 | |||
400 | if (txc->modes & ADJ_FREQUENCY) { | ||
401 | time_freq = (s64)txc->freq * PPM_SCALE; | ||
402 | time_freq = min(time_freq, MAXFREQ_SCALED); | ||
403 | time_freq = max(time_freq, -MAXFREQ_SCALED); | ||
404 | } | ||
405 | |||
406 | if (txc->modes & ADJ_MAXERROR) | ||
407 | time_maxerror = txc->maxerror; | ||
408 | if (txc->modes & ADJ_ESTERROR) | ||
409 | time_esterror = txc->esterror; | ||
410 | |||
411 | if (txc->modes & ADJ_TIMECONST) { | ||
412 | time_constant = txc->constant; | ||
413 | if (!(time_status & STA_NANO)) | ||
414 | time_constant += 4; | ||
415 | time_constant = min(time_constant, (long)MAXTC); | ||
416 | time_constant = max(time_constant, 0l); | ||
417 | } | ||
418 | |||
419 | if (txc->modes & ADJ_TAI && txc->constant > 0) | ||
420 | time_tai = txc->constant; | ||
421 | |||
422 | if (txc->modes & ADJ_OFFSET) | ||
423 | ntp_update_offset(txc->offset); | ||
424 | if (txc->modes & ADJ_TICK) | ||
425 | tick_usec = txc->tick; | ||
426 | |||
427 | if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET)) | ||
428 | ntp_update_frequency(); | ||
429 | } | ||
430 | |||
335 | /* | 431 | /* |
336 | * adjtimex mainly allows reading (and writing, if superuser) of | 432 | * adjtimex mainly allows reading (and writing, if superuser) of |
337 | * kernel time-keeping variables. used by xntpd. | 433 | * kernel time-keeping variables. used by xntpd. |
@@ -383,90 +479,10 @@ int do_adjtimex(struct timex *txc) | |||
383 | txc->offset = save_adjust; | 479 | txc->offset = save_adjust; |
384 | goto adj_done; | 480 | goto adj_done; |
385 | } | 481 | } |
386 | if (txc->modes) { | ||
387 | long sec; | ||
388 | |||
389 | if (txc->modes & ADJ_STATUS) { | ||
390 | if ((time_status & STA_PLL) && | ||
391 | !(txc->status & STA_PLL)) { | ||
392 | time_state = TIME_OK; | ||
393 | time_status = STA_UNSYNC; | ||
394 | } | ||
395 | /* only set allowed bits */ | ||
396 | time_status &= STA_RONLY; | ||
397 | /* | ||
398 | * If we turn on PLL adjustments then reset the | ||
399 | * reference time to current time. | ||
400 | */ | ||
401 | if (!(time_status & STA_PLL) && (txc->status & STA_PLL)) | ||
402 | time_reftime = xtime.tv_sec; | ||
403 | |||
404 | time_status |= txc->status & ~STA_RONLY; | ||
405 | |||
406 | switch (time_state) { | ||
407 | case TIME_OK: | ||
408 | start_timer: | ||
409 | sec = ts.tv_sec; | ||
410 | if (time_status & STA_INS) { | ||
411 | time_state = TIME_INS; | ||
412 | sec += 86400 - sec % 86400; | ||
413 | hrtimer_start(&leap_timer, ktime_set(sec, 0), HRTIMER_MODE_ABS); | ||
414 | } else if (time_status & STA_DEL) { | ||
415 | time_state = TIME_DEL; | ||
416 | sec += 86400 - (sec + 1) % 86400; | ||
417 | hrtimer_start(&leap_timer, ktime_set(sec, 0), HRTIMER_MODE_ABS); | ||
418 | } | ||
419 | break; | ||
420 | case TIME_INS: | ||
421 | case TIME_DEL: | ||
422 | time_state = TIME_OK; | ||
423 | goto start_timer; | ||
424 | break; | ||
425 | case TIME_WAIT: | ||
426 | if (!(time_status & (STA_INS | STA_DEL))) | ||
427 | time_state = TIME_OK; | ||
428 | break; | ||
429 | case TIME_OOP: | ||
430 | hrtimer_restart(&leap_timer); | ||
431 | break; | ||
432 | } | ||
433 | } | ||
434 | |||
435 | if (txc->modes & ADJ_NANO) | ||
436 | time_status |= STA_NANO; | ||
437 | if (txc->modes & ADJ_MICRO) | ||
438 | time_status &= ~STA_NANO; | ||
439 | 482 | ||
440 | if (txc->modes & ADJ_FREQUENCY) { | 483 | /* If there are input parameters, then process them: */ |
441 | time_freq = (s64)txc->freq * PPM_SCALE; | 484 | if (txc->modes) |
442 | time_freq = min(time_freq, MAXFREQ_SCALED); | 485 | process_adjtimex_modes(txc, &ts); |
443 | time_freq = max(time_freq, -MAXFREQ_SCALED); | ||
444 | } | ||
445 | |||
446 | if (txc->modes & ADJ_MAXERROR) | ||
447 | time_maxerror = txc->maxerror; | ||
448 | if (txc->modes & ADJ_ESTERROR) | ||
449 | time_esterror = txc->esterror; | ||
450 | |||
451 | if (txc->modes & ADJ_TIMECONST) { | ||
452 | time_constant = txc->constant; | ||
453 | if (!(time_status & STA_NANO)) | ||
454 | time_constant += 4; | ||
455 | time_constant = min(time_constant, (long)MAXTC); | ||
456 | time_constant = max(time_constant, 0l); | ||
457 | } | ||
458 | |||
459 | if (txc->modes & ADJ_TAI && txc->constant > 0) | ||
460 | time_tai = txc->constant; | ||
461 | |||
462 | if (txc->modes & ADJ_OFFSET) | ||
463 | ntp_update_offset(txc->offset); | ||
464 | if (txc->modes & ADJ_TICK) | ||
465 | tick_usec = txc->tick; | ||
466 | |||
467 | if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET)) | ||
468 | ntp_update_frequency(); | ||
469 | } | ||
470 | 486 | ||
471 | txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ, | 487 | txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ, |
472 | NTP_SCALE_SHIFT); | 488 | NTP_SCALE_SHIFT); |