aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2012-05-03 15:30:07 -0400
committerJohn Stultz <john.stultz@linaro.org>2013-03-22 19:19:58 -0400
commitcc244ddae6d4c6902ac9d7d64023534f8c44a7eb (patch)
tree9f9e26d214bd0113d8722c0a683e003cbc1bf165 /kernel
parente445cf1c4257cc0238d72e4129eb4739f46fd3de (diff)
timekeeping: Move TAI managment into timekeeping core from ntp
Currently NTP manages the TAI offset. Since there's plans for a CLOCK_TAI clockid, push the TAI management into the timekeeping core. CC: Thomas Gleixner <tglx@linutronix.de> CC: Eric Dumazet <eric.dumazet@gmail.com> CC: Richard Cochran <richardcochran@gmail.com> Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/time/ntp.c18
-rw-r--r--kernel/time/timekeeping.c44
2 files changed, 54 insertions, 8 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 072bb066bb7d..59e2749be0fa 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -53,9 +53,6 @@ static int time_state = TIME_OK;
53/* clock status bits: */ 53/* clock status bits: */
54static int time_status = STA_UNSYNC; 54static int time_status = STA_UNSYNC;
55 55
56/* TAI offset (secs): */
57static long time_tai;
58
59/* time adjustment (nsecs): */ 56/* time adjustment (nsecs): */
60static s64 time_offset; 57static s64 time_offset;
61 58
@@ -415,7 +412,6 @@ int second_overflow(unsigned long secs)
415 else if (secs % 86400 == 0) { 412 else if (secs % 86400 == 0) {
416 leap = -1; 413 leap = -1;
417 time_state = TIME_OOP; 414 time_state = TIME_OOP;
418 time_tai++;
419 printk(KERN_NOTICE 415 printk(KERN_NOTICE
420 "Clock: inserting leap second 23:59:60 UTC\n"); 416 "Clock: inserting leap second 23:59:60 UTC\n");
421 } 417 }
@@ -425,7 +421,6 @@ int second_overflow(unsigned long secs)
425 time_state = TIME_OK; 421 time_state = TIME_OK;
426 else if ((secs + 1) % 86400 == 0) { 422 else if ((secs + 1) % 86400 == 0) {
427 leap = 1; 423 leap = 1;
428 time_tai--;
429 time_state = TIME_WAIT; 424 time_state = TIME_WAIT;
430 printk(KERN_NOTICE 425 printk(KERN_NOTICE
431 "Clock: deleting leap second 23:59:59 UTC\n"); 426 "Clock: deleting leap second 23:59:59 UTC\n");
@@ -579,7 +574,9 @@ static inline void process_adj_status(struct timex *txc, struct timespec *ts)
579 * Called with ntp_lock held, so we can access and modify 574 * Called with ntp_lock held, so we can access and modify
580 * all the global NTP state: 575 * all the global NTP state:
581 */ 576 */
582static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts) 577static inline void process_adjtimex_modes(struct timex *txc,
578 struct timespec *ts,
579 s32 *time_tai)
583{ 580{
584 if (txc->modes & ADJ_STATUS) 581 if (txc->modes & ADJ_STATUS)
585 process_adj_status(txc, ts); 582 process_adj_status(txc, ts);
@@ -613,7 +610,7 @@ static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts
613 } 610 }
614 611
615 if (txc->modes & ADJ_TAI && txc->constant > 0) 612 if (txc->modes & ADJ_TAI && txc->constant > 0)
616 time_tai = txc->constant; 613 *time_tai = txc->constant;
617 614
618 if (txc->modes & ADJ_OFFSET) 615 if (txc->modes & ADJ_OFFSET)
619 ntp_update_offset(txc->offset); 616 ntp_update_offset(txc->offset);
@@ -632,6 +629,7 @@ static inline void process_adjtimex_modes(struct timex *txc, struct timespec *ts
632int do_adjtimex(struct timex *txc) 629int do_adjtimex(struct timex *txc)
633{ 630{
634 struct timespec ts; 631 struct timespec ts;
632 u32 time_tai, orig_tai;
635 int result; 633 int result;
636 634
637 /* Validate the data before disabling interrupts */ 635 /* Validate the data before disabling interrupts */
@@ -671,6 +669,7 @@ int do_adjtimex(struct timex *txc)
671 } 669 }
672 670
673 getnstimeofday(&ts); 671 getnstimeofday(&ts);
672 orig_tai = time_tai = timekeeping_get_tai_offset();
674 673
675 raw_spin_lock_irq(&ntp_lock); 674 raw_spin_lock_irq(&ntp_lock);
676 675
@@ -687,7 +686,7 @@ int do_adjtimex(struct timex *txc)
687 686
688 /* If there are input parameters, then process them: */ 687 /* If there are input parameters, then process them: */
689 if (txc->modes) 688 if (txc->modes)
690 process_adjtimex_modes(txc, &ts); 689 process_adjtimex_modes(txc, &ts, &time_tai);
691 690
692 txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ, 691 txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ,
693 NTP_SCALE_SHIFT); 692 NTP_SCALE_SHIFT);
@@ -716,6 +715,9 @@ int do_adjtimex(struct timex *txc)
716 715
717 raw_spin_unlock_irq(&ntp_lock); 716 raw_spin_unlock_irq(&ntp_lock);
718 717
718 if (time_tai != orig_tai)
719 timekeeping_set_tai_offset(time_tai);
720
719 txc->time.tv_sec = ts.tv_sec; 721 txc->time.tv_sec = ts.tv_sec;
720 txc->time.tv_usec = ts.tv_nsec; 722 txc->time.tv_usec = ts.tv_nsec;
721 if (!(time_status & STA_NANO)) 723 if (!(time_status & STA_NANO))
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 0355f125d585..937098aab498 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -513,6 +513,48 @@ error: /* even if we error out, we forwarded the time, so call update */
513} 513}
514EXPORT_SYMBOL(timekeeping_inject_offset); 514EXPORT_SYMBOL(timekeeping_inject_offset);
515 515
516
517/**
518 * timekeeping_get_tai_offset - Returns current TAI offset from UTC
519 *
520 */
521s32 timekeeping_get_tai_offset(void)
522{
523 struct timekeeper *tk = &timekeeper;
524 unsigned int seq;
525 s32 ret;
526
527 do {
528 seq = read_seqbegin(&tk->lock);
529 ret = tk->tai_offset;
530 } while (read_seqretry(&tk->lock, seq));
531
532 return ret;
533}
534
535/**
536 * __timekeeping_set_tai_offset - Lock free worker function
537 *
538 */
539void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset)
540{
541 tk->tai_offset = tai_offset;
542}
543
544/**
545 * timekeeping_set_tai_offset - Sets the current TAI offset from UTC
546 *
547 */
548void timekeeping_set_tai_offset(s32 tai_offset)
549{
550 struct timekeeper *tk = &timekeeper;
551 unsigned long flags;
552
553 write_seqlock_irqsave(&tk->lock, flags);
554 __timekeeping_set_tai_offset(tk, tai_offset);
555 write_sequnlock_irqrestore(&tk->lock, flags);
556}
557
516/** 558/**
517 * change_clocksource - Swaps clocksources if a new one is available 559 * change_clocksource - Swaps clocksources if a new one is available
518 * 560 *
@@ -1143,6 +1185,8 @@ static inline void accumulate_nsecs_to_secs(struct timekeeper *tk)
1143 tk_set_wall_to_mono(tk, 1185 tk_set_wall_to_mono(tk,
1144 timespec_sub(tk->wall_to_monotonic, ts)); 1186 timespec_sub(tk->wall_to_monotonic, ts));
1145 1187
1188 __timekeeping_set_tai_offset(tk, tk->tai_offset - leap);
1189
1146 clock_was_set_delayed(); 1190 clock_was_set_delayed();
1147 } 1191 }
1148 } 1192 }