diff options
author | John Stultz <john.stultz@linaro.org> | 2011-11-14 16:48:36 -0500 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2012-01-26 22:44:25 -0500 |
commit | bd3312681f69207a40431981c1bce1afdc9b7975 (patch) | |
tree | ad95aba265a7e6033e81cbc9b3054fac176ab6ce /kernel/time | |
parent | ea7cf49a7633c2b70125f59b4e3553d9181cb15d (diff) |
ntp: Add ntp_lock to replace xtime_locking
Use a ntp_lock spin lock to replace xtime_lock locking in ntp.c
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/time')
-rw-r--r-- | kernel/time/ntp.c | 63 |
1 files changed, 44 insertions, 19 deletions
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index f131ba62da62..17fb1b9807d0 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c | |||
@@ -22,6 +22,9 @@ | |||
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 | ||
@@ -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 | { |
@@ -341,11 +344,13 @@ static void ntp_update_offset(long offset) | |||
341 | 344 | ||
342 | /** | 345 | /** |
343 | * ntp_clear - Clears the NTP state variables | 346 | * ntp_clear - Clears the NTP state variables |
344 | * | ||
345 | * Must be called while holding a write on the xtime_lock | ||
346 | */ | 347 | */ |
347 | void ntp_clear(void) | 348 | void ntp_clear(void) |
348 | { | 349 | { |
350 | unsigned long flags; | ||
351 | |||
352 | spin_lock_irqsave(&ntp_lock, flags); | ||
353 | |||
349 | time_adjust = 0; /* stop active adjtime() */ | 354 | time_adjust = 0; /* stop active adjtime() */ |
350 | time_status |= STA_UNSYNC; | 355 | time_status |= STA_UNSYNC; |
351 | time_maxerror = NTP_PHASE_LIMIT; | 356 | time_maxerror = NTP_PHASE_LIMIT; |
@@ -358,12 +363,20 @@ void ntp_clear(void) | |||
358 | 363 | ||
359 | /* Clear PPS state variables */ | 364 | /* Clear PPS state variables */ |
360 | pps_clear(); | 365 | pps_clear(); |
366 | spin_unlock_irqrestore(&ntp_lock, flags); | ||
367 | |||
361 | } | 368 | } |
362 | 369 | ||
363 | 370 | ||
364 | u64 ntp_tick_length(void) | 371 | u64 ntp_tick_length(void) |
365 | { | 372 | { |
366 | return tick_length; | 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; | ||
367 | } | 380 | } |
368 | 381 | ||
369 | 382 | ||
@@ -375,14 +388,15 @@ u64 ntp_tick_length(void) | |||
375 | static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) | 388 | static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) |
376 | { | 389 | { |
377 | enum hrtimer_restart res = HRTIMER_NORESTART; | 390 | enum hrtimer_restart res = HRTIMER_NORESTART; |
391 | unsigned long flags; | ||
392 | int leap = 0; | ||
378 | 393 | ||
379 | write_seqlock(&xtime_lock); | 394 | spin_lock_irqsave(&ntp_lock, flags); |
380 | |||
381 | switch (time_state) { | 395 | switch (time_state) { |
382 | case TIME_OK: | 396 | case TIME_OK: |
383 | break; | 397 | break; |
384 | case TIME_INS: | 398 | case TIME_INS: |
385 | timekeeping_leap_insert(-1); | 399 | leap = -1; |
386 | time_state = TIME_OOP; | 400 | time_state = TIME_OOP; |
387 | printk(KERN_NOTICE | 401 | printk(KERN_NOTICE |
388 | "Clock: inserting leap second 23:59:60 UTC\n"); | 402 | "Clock: inserting leap second 23:59:60 UTC\n"); |
@@ -390,7 +404,7 @@ static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) | |||
390 | res = HRTIMER_RESTART; | 404 | res = HRTIMER_RESTART; |
391 | break; | 405 | break; |
392 | case TIME_DEL: | 406 | case TIME_DEL: |
393 | timekeeping_leap_insert(1); | 407 | leap = 1; |
394 | time_tai--; | 408 | time_tai--; |
395 | time_state = TIME_WAIT; | 409 | time_state = TIME_WAIT; |
396 | printk(KERN_NOTICE | 410 | printk(KERN_NOTICE |
@@ -405,8 +419,14 @@ static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) | |||
405 | time_state = TIME_OK; | 419 | time_state = TIME_OK; |
406 | break; | 420 | break; |
407 | } | 421 | } |
422 | spin_unlock_irqrestore(&ntp_lock, flags); | ||
408 | 423 | ||
409 | 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); | ||
410 | 430 | ||
411 | return res; | 431 | return res; |
412 | } | 432 | } |
@@ -422,6 +442,9 @@ static enum hrtimer_restart ntp_leap_second(struct hrtimer *timer) | |||
422 | void second_overflow(void) | 442 | void second_overflow(void) |
423 | { | 443 | { |
424 | s64 delta; | 444 | s64 delta; |
445 | unsigned long flags; | ||
446 | |||
447 | spin_lock_irqsave(&ntp_lock, flags); | ||
425 | 448 | ||
426 | /* Bump the maxerror field */ | 449 | /* Bump the maxerror field */ |
427 | time_maxerror += MAXFREQ / NSEC_PER_USEC; | 450 | time_maxerror += MAXFREQ / NSEC_PER_USEC; |
@@ -441,23 +464,25 @@ void second_overflow(void) | |||
441 | pps_dec_valid(); | 464 | pps_dec_valid(); |
442 | 465 | ||
443 | if (!time_adjust) | 466 | if (!time_adjust) |
444 | return; | 467 | goto out; |
445 | 468 | ||
446 | if (time_adjust > MAX_TICKADJ) { | 469 | if (time_adjust > MAX_TICKADJ) { |
447 | time_adjust -= MAX_TICKADJ; | 470 | time_adjust -= MAX_TICKADJ; |
448 | tick_length += MAX_TICKADJ_SCALED; | 471 | tick_length += MAX_TICKADJ_SCALED; |
449 | return; | 472 | goto out; |
450 | } | 473 | } |
451 | 474 | ||
452 | if (time_adjust < -MAX_TICKADJ) { | 475 | if (time_adjust < -MAX_TICKADJ) { |
453 | time_adjust += MAX_TICKADJ; | 476 | time_adjust += MAX_TICKADJ; |
454 | tick_length -= MAX_TICKADJ_SCALED; | 477 | tick_length -= MAX_TICKADJ_SCALED; |
455 | return; | 478 | goto out; |
456 | } | 479 | } |
457 | 480 | ||
458 | tick_length += (s64)(time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ) | 481 | tick_length += (s64)(time_adjust * NSEC_PER_USEC / NTP_INTERVAL_FREQ) |
459 | << NTP_SCALE_SHIFT; | 482 | << NTP_SCALE_SHIFT; |
460 | time_adjust = 0; | 483 | time_adjust = 0; |
484 | out: | ||
485 | spin_unlock_irqrestore(&ntp_lock, flags); | ||
461 | } | 486 | } |
462 | 487 | ||
463 | #ifdef CONFIG_GENERIC_CMOS_UPDATE | 488 | #ifdef CONFIG_GENERIC_CMOS_UPDATE |
@@ -681,7 +706,7 @@ int do_adjtimex(struct timex *txc) | |||
681 | 706 | ||
682 | getnstimeofday(&ts); | 707 | getnstimeofday(&ts); |
683 | 708 | ||
684 | write_seqlock_irq(&xtime_lock); | 709 | spin_lock_irq(&ntp_lock); |
685 | 710 | ||
686 | if (txc->modes & ADJ_ADJTIME) { | 711 | if (txc->modes & ADJ_ADJTIME) { |
687 | long save_adjust = time_adjust; | 712 | long save_adjust = time_adjust; |
@@ -723,7 +748,7 @@ int do_adjtimex(struct timex *txc) | |||
723 | /* fill PPS status fields */ | 748 | /* fill PPS status fields */ |
724 | pps_fill_timex(txc); | 749 | pps_fill_timex(txc); |
725 | 750 | ||
726 | write_sequnlock_irq(&xtime_lock); | 751 | spin_unlock_irq(&ntp_lock); |
727 | 752 | ||
728 | txc->time.tv_sec = ts.tv_sec; | 753 | txc->time.tv_sec = ts.tv_sec; |
729 | txc->time.tv_usec = ts.tv_nsec; | 754 | txc->time.tv_usec = ts.tv_nsec; |
@@ -921,7 +946,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts) | |||
921 | 946 | ||
922 | pts_norm = pps_normalize_ts(*phase_ts); | 947 | pts_norm = pps_normalize_ts(*phase_ts); |
923 | 948 | ||
924 | write_seqlock_irqsave(&xtime_lock, flags); | 949 | spin_lock_irqsave(&ntp_lock, flags); |
925 | 950 | ||
926 | /* clear the error bits, they will be set again if needed */ | 951 | /* clear the error bits, they will be set again if needed */ |
927 | time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR); | 952 | time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR); |
@@ -934,7 +959,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts) | |||
934 | * just start the frequency interval */ | 959 | * just start the frequency interval */ |
935 | if (unlikely(pps_fbase.tv_sec == 0)) { | 960 | if (unlikely(pps_fbase.tv_sec == 0)) { |
936 | pps_fbase = *raw_ts; | 961 | pps_fbase = *raw_ts; |
937 | write_sequnlock_irqrestore(&xtime_lock, flags); | 962 | spin_unlock_irqrestore(&ntp_lock, flags); |
938 | return; | 963 | return; |
939 | } | 964 | } |
940 | 965 | ||
@@ -949,7 +974,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts) | |||
949 | time_status |= STA_PPSJITTER; | 974 | time_status |= STA_PPSJITTER; |
950 | /* restart the frequency calibration interval */ | 975 | /* restart the frequency calibration interval */ |
951 | pps_fbase = *raw_ts; | 976 | pps_fbase = *raw_ts; |
952 | write_sequnlock_irqrestore(&xtime_lock, flags); | 977 | spin_unlock_irqrestore(&ntp_lock, flags); |
953 | pr_err("hardpps: PPSJITTER: bad pulse\n"); | 978 | pr_err("hardpps: PPSJITTER: bad pulse\n"); |
954 | return; | 979 | return; |
955 | } | 980 | } |
@@ -966,7 +991,7 @@ void hardpps(const struct timespec *phase_ts, const struct timespec *raw_ts) | |||
966 | 991 | ||
967 | hardpps_update_phase(pts_norm.nsec); | 992 | hardpps_update_phase(pts_norm.nsec); |
968 | 993 | ||
969 | write_sequnlock_irqrestore(&xtime_lock, flags); | 994 | spin_unlock_irqrestore(&ntp_lock, flags); |
970 | } | 995 | } |
971 | EXPORT_SYMBOL(hardpps); | 996 | EXPORT_SYMBOL(hardpps); |
972 | 997 | ||