diff options
Diffstat (limited to 'kernel/time/ntp.c')
-rw-r--r-- | kernel/time/ntp.c | 85 |
1 files changed, 64 insertions, 21 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index f6117a4c7cb8..6e039b144daf 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -22,13 +22,16 @@ | |||
22 | * NTP timekeeping variables: | 22 | * NTP timekeeping variables: |
23 | */ | 23 | */ |
24 | 24 | ||
25 | DEFINE_SPINLOCK(ntp_lock); | ||
26 | |||
27 | |||
25 | /* USER_HZ period (usecs): */ | 28 | /* USER_HZ period (usecs): */ |
26 | unsigned long tick_usec = TICK_USEC; | 29 | unsigned long tick_usec = TICK_USEC; |
27 | 30 | ||
28 | /* ACTHZ period (nsecs): */ | 31 | /* ACTHZ period (nsecs): */ |
29 | unsigned long tick_nsec; | 32 | unsigned long tick_nsec; |
30 | 33 | ||
31 | u64 tick_length; | 34 | static u64 tick_length; |
32 | static u64 tick_length_base; | 35 | static u64 tick_length_base; |
33 | 36 | ||
34 | static struct hrtimer leap_timer; | 37 | static struct hrtimer leap_timer; |
@@ -49,7 +52,7 @@ static struct hrtimer leap_timer; | |||
49 | static int time_state = TIME_OK; | 52 | static int time_state = TIME_OK; |
50 | 53 | ||
51 | /* clock status bits: */ | 54 | /* clock status bits: */ |
52 | int time_status = STA_UNSYNC; | 55 | static int time_status = STA_UNSYNC; |
53 | 56 | ||
54 | /* TAI offset (secs): */ | 57 | /* TAI offset (secs): */ |
55 | static long time_tai; | 58 | static long time_tai; |
@@ -133,7 +136,7 @@ static inline void pps_reset_freq_interval(void) | |||
133 | /** | 136 | /** |
134 | * pps_clear - Clears the PPS state variables | 137 | * pps_clear - Clears the PPS state variables |
135 | * | 138 | * |
136 | * Must be called while holding a write on the xtime_lock | 139 | * Must be called while holding a write on the ntp_lock |
137 | */ | 140 | */ |
138 | static inline void pps_clear(void) | 141 | static inline void pps_clear(void) |
139 | { | 142 | { |
@@ -149,7 +152,7 @@ static inline void pps_clear(void) | |||
149 | * the last PPS signal. When it reaches 0, indicate that PPS signal is | 152 | * the last PPS signal. When it reaches 0, indicate that PPS signal is |
150 | * missing. | 153 | * missing. |
151 | * | 154 | * |
152 | * Must be called while holding a write on the xtime_lock | 155 | * Must be called while holding a write on the ntp_lock |
153 | */ | 156 | */ |
154 | static inline void pps_dec_valid(void) | 157 | static inline void pps_dec_valid(void) |
155 | { | 158 | { |
@@ -233,6 +236,17 @@ static inline void pps_fill_timex(struct timex *txc) | |||
233 | 236 | ||
234 | #endif /* CONFIG_NTP_PPS */ | 237 | #endif /* CONFIG_NTP_PPS */ |
235 | 238 | ||
239 | |||
240 | /** | ||
241 | * ntp_synced - Returns 1 if the NTP status is not UNSYNC | ||
242 | * | ||
243 | */ | ||
244 | static inline int ntp_synced(void) | ||
245 | { | ||
246 | return !(time_status & STA_UNSYNC); | ||
247 | } | ||
248 | |||
249 | |||
236 | /* | 250 | /* |
237 | * NTP methods: | 251 | * NTP methods: |
238 | */ | 252 | */ |
@@ -275,7 +289,7 @@ static inline s64 ntp_update_offset_fll(s64 offset64, long secs) | |||
275 | 289 | ||
276 | time_status |= STA_MODE; | 290 | time_status |= STA_MODE; |
277 | 291 | ||
278 | return div_s64(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs); | 292 | return div64_long(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs); |
279 | } | 293 | } |
280 | 294 | ||
281 | static void ntp_update_offset(long offset) | 295 | static void ntp_update_offset(long offset) |
@@ -330,11 +344,13 @@ static void ntp_update_offset(long offset) | |||
330 | 344 | ||
331 | /** | 345 | /** |
332 | * ntp_clear - Clears the NTP state variables | 346 | * ntp_clear - Clears the NTP state variables |
333 | * | ||
334 | * Must be called while holding a write on the xtime_lock | ||
335 | */ | 347 | */ |
336 | void ntp_clear(void) | 348 | void ntp_clear(void) |
337 | { | 349 | { |
350 | unsigned long flags; | ||
351 | |||
352 | spin_lock_irqsave(&ntp_lock, flags); | ||
353 | |||
338 | time_adjust = 0; /* stop active adjtime() */ | 354 | time_adjust = 0; /* stop active adjtime() */ |
339 | time_status |= STA_UNSYNC; | 355 | time_status |= STA_UNSYNC; |
340 | time_maxerror = NTP_PHASE_LIMIT; | 356 | time_maxerror = NTP_PHASE_LIMIT; |
@@ -347,8 +363,23 @@ void ntp_clear(void) | |||
347 | 363 | ||
348 | /* Clear PPS state variables */ | 364 | /* Clear PPS state variables */ |
349 | pps_clear(); | 365 | pps_clear(); |
366 | spin_unlock_irqrestore(&ntp_lock, flags); | ||
367 | |||
350 | } | 368 | } |
351 | 369 | ||
370 | |||
371 | u64 ntp_tick_length(void) | ||
372 | { | ||
373 | unsigned long flags; | ||
374 | s64 ret; | ||
375 | |||
376 | spin_lock_irqsave(&ntp_lock, flags); | ||
377 | ret = tick_length; | ||
378 | spin_unlock_irqrestore(&ntp_lock, flags); | ||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | |||
352 | /* | 383 | /* |
353 | * Leap second processing. If in leap-insert state at the end of the | 384 | * Leap second processing. If in leap-insert state at the end of the |
354 | * day, the system clock is set back one second; if in leap-delete | 385 | * day, the system clock is set back one second; if in leap-delete |
@@ -357,14 +388,15 @@ void ntp_clear(void) | |||
357 | static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) | 388 | static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) |
358 | { | 389 | { |
359 | enum hrtimer_restart res = HRTIMER_NORESTART; | 390 | enum hrtimer_restart res = HRTIMER_NORESTART; |
391 | unsigned long flags; | ||
392 | int leap = 0; | ||
360 | 393 | ||
361 | write_seqlock(&xtime_lock); | 394 | spin_lock_irqsave(&ntp_lock, flags); |
362 | |||
363 | switch (time_state) { | 395 | switch (time_state) { |
364 | case TIME_OK: | 396 | case TIME_OK: |
365 | break; | 397 | break; |
366 | case TIME_INS: | 398 | case TIME_INS: |
367 | timekeeping_leap_insert(-1); | 399 | leap = -1; |
368 | time_state = TIME_OOP; | 400 | time_state = TIME_OOP; |
369 | printk(KERN_NOTICE | 401 | printk(KERN_NOTICE |
370 | "Clock: inserting leap second 23:59:60 UTC\n"); | 402 | "Clock: inserting leap second 23:59:60 UTC\n"); |
@@ -372,7 +404,7 @@ static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) | |||
372 | res = HRTIMER_RESTART; | 404 | res = HRTIMER_RESTART; |
373 | break; | 405 | break; |
374 | case TIME_DEL: | 406 | case TIME_DEL: |
375 | timekeeping_leap_insert(1); | 407 | leap = 1; |
376 | time_tai--; | 408 | time_tai--; |
377 | time_state = TIME_WAIT; | 409 | time_state = TIME_WAIT; |
378 | printk(KERN_NOTICE | 410 | printk(KERN_NOTICE |
@@ -387,8 +419,14 @@ static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) | |||
387 | time_state = TIME_OK; | 419 | time_state = TIME_OK; |
388 | break; | 420 | break; |
389 | } | 421 | } |
422 | spin_unlock_irqrestore(&ntp_lock, flags); | ||
390 | 423 | ||
391 | write_sequnlock(&xtime_lock); | 424 | /* |
425 | * We have to call this outside of the ntp_lock to keep | ||
426 | * the proper locking hierarchy | ||
427 | */ | ||
428 | if (leap) | ||
429 | timekeeping_leap_insert(leap); | ||
392 | 430 | ||
393 | return res; | 431 | return res; |
394 | } | 432 | } |
@@ -404,6 +442,9 @@ static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) | |||
404 | void second_overflow(void) | 442 | void second_overflow(void) |
405 | { | 443 | { |
406 | s64 delta; | 444 | s64 delta; |
445 | unsigned long flags; | ||
446 | |||
447 | spin_lock_irqsave(&ntp_lock, flags); | ||
407 | 448 | ||
408 | /* Bump the maxerror field */ | 449 | /* Bump the maxerror field */ |
409 | time_maxerror += MAXFREQ / NSEC_PER_USEC; | 450 | time_maxerror += MAXFREQ / NSEC_PER_USEC; |
@@ -423,23 +464,25 @@ void second_overflow(void) | |||
423 | pps_dec_valid(); | 464 | pps_dec_valid(); |
424 | 465 | ||
425 | if (!time_adjust) | 466 | if (!time_adjust) |
426 | return; | 467 | goto out; |
427 | 468 | ||
428 | if (time_adjust > MAX_TICKADJ) { | 469 | if (time_adjust > MAX_TICKADJ) { |
429 | time_adjust -= MAX_TICKADJ; | 470 | time_adjust -= MAX_TICKADJ; |
430 | tick_length += MAX_TICKADJ_SCALED; | 471 | tick_length += MAX_TICKADJ_SCALED; |
431 | return; | 472 | goto out; |
432 | } | 473 | } |
433 | 474 | ||
434 | if (time_adjust < -MAX_TICKADJ) { | 475 | if (time_adjust < -MAX_TICKADJ) { |
435 | time_adjust += MAX_TICKADJ; | 476 | time_adjust += MAX_TICKADJ; |
436 | tick_length -= MAX_TICKADJ_SCALED; | 477 | tick_length -= MAX_TICKADJ_SCALED; |
437 | return; | 478 | goto out; |
438 | } | 479 | } |
439 | 480 | ||
440 | tick_length += (s64)(time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ) | 481 | tick_length += (s64)(time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ) |
441 | << NTP_SCALE_SHIFT; | 482 | << NTP_SCALE_SHIFT; |
442 | time_adjust = 0; | 483 | time_adjust = 0; |
484 | out: | ||
485 | spin_unlock_irqrestore(&ntp_lock, flags); | ||
443 | } | 486 | } |
444 | 487 | ||
445 | #ifdef CONFIG_GENERIC_CMOS_UPDATE | 488 | #ifdef CONFIG_GENERIC_CMOS_UPDATE |
@@ -663,7 +706,7 @@ int do_adjtimex(struct timex *txc) | |||
663 | 706 | ||
664 | getnstimeofday(&ts); | 707 | getnstimeofday(&ts); |
665 | 708 | ||
666 | write_seqlock_irq(&xtime_lock); | 709 | spin_lock_irq(&ntp_lock); |
667 | 710 | ||
668 | if (txc->modes & ADJ_ADJTIME) { | 711 | if (txc->modes & ADJ_ADJTIME) { |
669 | long save_adjust = time_adjust; | 712 | long save_adjust = time_adjust; |
@@ -705,7 +748,7 @@ int do_adjtimex(struct timex *txc) | |||
705 | /* fill PPS status fields */ | 748 | /* fill PPS status fields */ |
706 | pps_fill_timex(txc); | 749 | pps_fill_timex(txc); |
707 | 750 | ||
708 | write_sequnlock_irq(&xtime_lock); | 751 | spin_unlock_irq(&ntp_lock); |
709 | 752 | ||
710 | txc->time.tv_sec = ts.tv_sec; | 753 | txc->time.tv_sec = ts.tv_sec; |
711 | txc->time.tv_usec = ts.tv_nsec; | 754 | txc->time.tv_usec = ts.tv_nsec; |
@@ -903,7 +946,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts) | |||
903 | 946 | ||
904 | pts_norm = pps_normalize_ts(*phase_ts); | 947 | pts_norm = pps_normalize_ts(*phase_ts); |
905 | 948 | ||
906 | write_seqlock_irqsave(&xtime_lock, flags); | 949 | spin_lock_irqsave(&ntp_lock, flags); |
907 | 950 | ||
908 | /* clear the error bits, they will be set again if needed */ | 951 | /* clear the error bits, they will be set again if needed */ |
909 | time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR); | 952 | time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR); |
@@ -916,7 +959,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts) | |||
916 | * just start the frequency interval */ | 959 | * just start the frequency interval */ |
917 | if (unlikely(pps_fbase.tv_sec == 0)) { | 960 | if (unlikely(pps_fbase.tv_sec == 0)) { |
918 | pps_fbase = *raw_ts; | 961 | pps_fbase = *raw_ts; |
919 | write_sequnlock_irqrestore(&xtime_lock, flags); | 962 | spin_unlock_irqrestore(&ntp_lock, flags); |
920 | return; | 963 | return; |
921 | } | 964 | } |
922 | 965 | ||
@@ -931,7 +974,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts) | |||
931 | time_status |= STA_PPSJITTER; | 974 | time_status |= STA_PPSJITTER; |
932 | /* restart the frequency calibration interval */ | 975 | /* restart the frequency calibration interval */ |
933 | pps_fbase = *raw_ts; | 976 | pps_fbase = *raw_ts; |
934 | write_sequnlock_irqrestore(&xtime_lock, flags); | 977 | spin_unlock_irqrestore(&ntp_lock, flags); |
935 | pr_err("hardpps: PPSJITTER: bad pulse\n"); | 978 | pr_err("hardpps: PPSJITTER: bad pulse\n"); |
936 | return; | 979 | return; |
937 | } | 980 | } |
@@ -948,7 +991,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts) | |||
948 | 991 | ||
949 | hardpps_update_phase(pts_norm.nsec); | 992 | hardpps_update_phase(pts_norm.nsec); |
950 | 993 | ||
951 | write_sequnlock_irqrestore(&xtime_lock, flags); | 994 | spin_unlock_irqrestore(&ntp_lock, flags); |
952 | } | 995 | } |
953 | EXPORT_SYMBOL(hardpps); | 996 | EXPORT_SYMBOL(hardpps); |
954 | 997 | ||