aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/time/ntp.c61
1 files changed, 36 insertions, 25 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index aded09be98cc..4346ed6e623f 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -332,14 +332,33 @@ static void notify_cmos_timer(void)
332static inline void notify_cmos_timer(void) { } 332static inline void notify_cmos_timer(void) { }
333#endif 333#endif
334 334
335/*
336 * Start the leap seconds timer:
337 */
338static inline void ntp_start_leap_timer(struct timespec *ts)
339{
340 long now = ts->tv_sec;
341
342 if (time_status & STA_INS) {
343 time_state = TIME_INS;
344 now += 86400 - now % 86400;
345 hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS);
346
347 return;
348 }
349
350 if (time_status & STA_DEL) {
351 time_state = TIME_DEL;
352 now += 86400 - (now + 1) % 86400;
353 hrtimer_start(&leap_timer, ktime_set(now, 0), HRTIMER_MODE_ABS);
354 }
355}
335 356
336/* 357/*
337 * Propagate a new txc->status value into the NTP state: 358 * Propagate a new txc->status value into the NTP state:
338 */ 359 */
339static inline void process_adj_status(struct timex *txc, struct timespec *ts) 360static inline void process_adj_status(struct timex *txc, struct timespec *ts)
340{ 361{
341 long now;
342
343 if ((time_status & STA_PLL) && !(txc->status & STA_PLL)) { 362 if ((time_status & STA_PLL) && !(txc->status & STA_PLL)) {
344 time_state = TIME_OK; 363 time_state = TIME_OK;
345 time_status = STA_UNSYNC; 364 time_status = STA_UNSYNC;
@@ -358,22 +377,12 @@ static inline void process_adj_status(struct timex *txc, struct timespec *ts)
358 377
359 switch (time_state) { 378 switch (time_state) {
360 case TIME_OK: 379 case TIME_OK:
361 start_timer: 380 ntp_start_leap_timer(ts);
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; 381 break;
373 case TIME_INS: 382 case TIME_INS:
374 case TIME_DEL: 383 case TIME_DEL:
375 time_state = TIME_OK; 384 time_state = TIME_OK;
376 goto start_timer; 385 ntp_start_leap_timer(ts);
377 case TIME_WAIT: 386 case TIME_WAIT:
378 if (!(time_status & (STA_INS | STA_DEL))) 387 if (!(time_status & (STA_INS | STA_DEL)))
379 time_state = TIME_OK; 388 time_state = TIME_OK;
@@ -394,6 +403,7 @@ static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts
394 403
395 if (txc->modes & ADJ_NANO) 404 if (txc->modes & ADJ_NANO)
396 time_status |= STA_NANO; 405 time_status |= STA_NANO;
406
397 if (txc->modes & ADJ_MICRO) 407 if (txc->modes & ADJ_MICRO)
398 time_status &= ~STA_NANO; 408 time_status &= ~STA_NANO;
399 409
@@ -405,6 +415,7 @@ static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts
405 415
406 if (txc->modes & ADJ_MAXERROR) 416 if (txc->modes & ADJ_MAXERROR)
407 time_maxerror = txc->maxerror; 417 time_maxerror = txc->maxerror;
418
408 if (txc->modes & ADJ_ESTERROR) 419 if (txc->modes & ADJ_ESTERROR)
409 time_esterror = txc->esterror; 420 time_esterror = txc->esterror;
410 421
@@ -421,6 +432,7 @@ static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts
421 432
422 if (txc->modes & ADJ_OFFSET) 433 if (txc->modes & ADJ_OFFSET)
423 ntp_update_offset(txc->offset); 434 ntp_update_offset(txc->offset);
435
424 if (txc->modes & ADJ_TICK) 436 if (txc->modes & ADJ_TICK)
425 tick_usec = txc->tick; 437 tick_usec = txc->tick;
426 438
@@ -457,7 +469,7 @@ int do_adjtimex(struct timex *txc)
457 if (txc->modes & ADJ_TICK && 469 if (txc->modes & ADJ_TICK &&
458 (txc->tick < 900000/USER_HZ || 470 (txc->tick < 900000/USER_HZ ||
459 txc->tick > 1100000/USER_HZ)) 471 txc->tick > 1100000/USER_HZ))
460 return -EINVAL; 472 return -EINVAL;
461 473
462 if (txc->modes & ADJ_STATUS && time_state != TIME_OK) 474 if (txc->modes & ADJ_STATUS && time_state != TIME_OK)
463 hrtimer_cancel(&leap_timer); 475 hrtimer_cancel(&leap_timer);
@@ -467,7 +479,6 @@ int do_adjtimex(struct timex *txc)
467 479
468 write_seqlock_irq(&xtime_lock); 480 write_seqlock_irq(&xtime_lock);
469 481
470 /* If there are input parameters, then process them */
471 if (txc->modes & ADJ_ADJTIME) { 482 if (txc->modes & ADJ_ADJTIME) {
472 long save_adjust = time_adjust; 483 long save_adjust = time_adjust;
473 484
@@ -477,19 +488,18 @@ int do_adjtimex(struct timex *txc)
477 ntp_update_frequency(); 488 ntp_update_frequency();
478 } 489 }
479 txc->offset = save_adjust; 490 txc->offset = save_adjust;
480 goto adj_done; 491 } else {
481 }
482 492
483 /* If there are input parameters, then process them: */ 493 /* If there are input parameters, then process them: */
484 if (txc->modes) 494 if (txc->modes)
485 process_adjtimex_modes(txc, &ts); 495 process_adjtimex_modes(txc, &ts);
486 496
487 txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ, 497 txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ,
488 NTP_SCALE_SHIFT); 498 NTP_SCALE_SHIFT);
489 if (!(time_status & STA_NANO)) 499 if (!(time_status & STA_NANO))
490 txc->offset /= NSEC_PER_USEC; 500 txc->offset /= NSEC_PER_USEC;
501 }
491 502
492adj_done:
493 result = time_state; /* mostly `TIME_OK' */ 503 result = time_state; /* mostly `TIME_OK' */
494 if (time_status & (STA_UNSYNC|STA_CLOCKERR)) 504 if (time_status & (STA_UNSYNC|STA_CLOCKERR))
495 result = TIME_ERROR; 505 result = TIME_ERROR;
@@ -514,6 +524,7 @@ adj_done:
514 txc->calcnt = 0; 524 txc->calcnt = 0;
515 txc->errcnt = 0; 525 txc->errcnt = 0;
516 txc->stbcnt = 0; 526 txc->stbcnt = 0;
527
517 write_sequnlock_irq(&xtime_lock); 528 write_sequnlock_irq(&xtime_lock);
518 529
519 txc->time.tv_sec = ts.tv_sec; 530 txc->time.tv_sec = ts.tv_sec;