diff options
-rw-r--r-- | kernel/time/ntp.c | 61 |
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) | |||
332 | static inline void notify_cmos_timer(void) { } | 332 | static inline void notify_cmos_timer(void) { } |
333 | #endif | 333 | #endif |
334 | 334 | ||
335 | /* | ||
336 | * Start the leap seconds timer: | ||
337 | */ | ||
338 | static 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 | */ |
339 | static inline void process_adj_status(struct timex *txc, struct timespec *ts) | 360 | static 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 | ||
492 | adj_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; |