diff options
Diffstat (limited to 'arch/powerpc/kernel/time.c')
| -rw-r--r-- | arch/powerpc/kernel/time.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 774c0a3c5019..18e59e43d2b3 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
| @@ -417,7 +417,7 @@ static __inline__ void timer_check_rtc(void) | |||
| 417 | /* | 417 | /* |
| 418 | * This version of gettimeofday has microsecond resolution. | 418 | * This version of gettimeofday has microsecond resolution. |
| 419 | */ | 419 | */ |
| 420 | static inline void __do_gettimeofday(struct timeval *tv, u64 tb_val) | 420 | static inline void __do_gettimeofday(struct timeval *tv) |
| 421 | { | 421 | { |
| 422 | unsigned long sec, usec; | 422 | unsigned long sec, usec; |
| 423 | u64 tb_ticks, xsec; | 423 | u64 tb_ticks, xsec; |
| @@ -431,7 +431,12 @@ static inline void __do_gettimeofday(struct timeval *tv, u64 tb_val) | |||
| 431 | * without a divide (and in fact, without a multiply) | 431 | * without a divide (and in fact, without a multiply) |
| 432 | */ | 432 | */ |
| 433 | temp_varp = do_gtod.varp; | 433 | temp_varp = do_gtod.varp; |
| 434 | tb_ticks = tb_val - temp_varp->tb_orig_stamp; | 434 | |
| 435 | /* Sampling the time base must be done after loading | ||
| 436 | * do_gtod.varp in order to avoid racing with update_gtod. | ||
| 437 | */ | ||
| 438 | data_barrier(temp_varp); | ||
| 439 | tb_ticks = get_tb() - temp_varp->tb_orig_stamp; | ||
| 435 | temp_tb_to_xs = temp_varp->tb_to_xs; | 440 | temp_tb_to_xs = temp_varp->tb_to_xs; |
| 436 | temp_stamp_xsec = temp_varp->stamp_xsec; | 441 | temp_stamp_xsec = temp_varp->stamp_xsec; |
| 437 | xsec = temp_stamp_xsec + mulhdu(tb_ticks, temp_tb_to_xs); | 442 | xsec = temp_stamp_xsec + mulhdu(tb_ticks, temp_tb_to_xs); |
| @@ -464,7 +469,7 @@ void do_gettimeofday(struct timeval *tv) | |||
| 464 | tv->tv_usec = usec; | 469 | tv->tv_usec = usec; |
| 465 | return; | 470 | return; |
| 466 | } | 471 | } |
| 467 | __do_gettimeofday(tv, get_tb()); | 472 | __do_gettimeofday(tv); |
| 468 | } | 473 | } |
| 469 | 474 | ||
| 470 | EXPORT_SYMBOL(do_gettimeofday); | 475 | EXPORT_SYMBOL(do_gettimeofday); |
| @@ -650,6 +655,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
| 650 | int next_dec; | 655 | int next_dec; |
| 651 | int cpu = smp_processor_id(); | 656 | int cpu = smp_processor_id(); |
| 652 | unsigned long ticks; | 657 | unsigned long ticks; |
| 658 | u64 tb_next_jiffy; | ||
| 653 | 659 | ||
| 654 | #ifdef CONFIG_PPC32 | 660 | #ifdef CONFIG_PPC32 |
| 655 | if (atomic_read(&ppc_n_lost_interrupts) != 0) | 661 | if (atomic_read(&ppc_n_lost_interrupts) != 0) |
| @@ -691,11 +697,14 @@ void timer_interrupt(struct pt_regs * regs) | |||
| 691 | continue; | 697 | continue; |
| 692 | 698 | ||
| 693 | write_seqlock(&xtime_lock); | 699 | write_seqlock(&xtime_lock); |
| 694 | tb_last_jiffy += tb_ticks_per_jiffy; | 700 | tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy; |
| 695 | tb_last_stamp = per_cpu(last_jiffy, cpu); | 701 | if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) { |
| 696 | do_timer(regs); | 702 | tb_last_jiffy = tb_next_jiffy; |
| 697 | timer_recalc_offset(tb_last_jiffy); | 703 | tb_last_stamp = per_cpu(last_jiffy, cpu); |
| 698 | timer_check_rtc(); | 704 | do_timer(regs); |
| 705 | timer_recalc_offset(tb_last_jiffy); | ||
| 706 | timer_check_rtc(); | ||
| 707 | } | ||
| 699 | write_sequnlock(&xtime_lock); | 708 | write_sequnlock(&xtime_lock); |
| 700 | } | 709 | } |
| 701 | 710 | ||
