diff options
Diffstat (limited to 'arch/powerpc/kernel/time.c')
-rw-r--r-- | arch/powerpc/kernel/time.c | 61 |
1 files changed, 34 insertions, 27 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 0441bbdadbd1..5adebaf47f13 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -423,30 +423,6 @@ void udelay(unsigned long usecs) | |||
423 | } | 423 | } |
424 | EXPORT_SYMBOL(udelay); | 424 | EXPORT_SYMBOL(udelay); |
425 | 425 | ||
426 | static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec, | ||
427 | u64 new_tb_to_xs) | ||
428 | { | ||
429 | /* | ||
430 | * tb_update_count is used to allow the userspace gettimeofday code | ||
431 | * to assure itself that it sees a consistent view of the tb_to_xs and | ||
432 | * stamp_xsec variables. It reads the tb_update_count, then reads | ||
433 | * tb_to_xs and stamp_xsec and then reads tb_update_count again. If | ||
434 | * the two values of tb_update_count match and are even then the | ||
435 | * tb_to_xs and stamp_xsec values are consistent. If not, then it | ||
436 | * loops back and reads them again until this criteria is met. | ||
437 | * We expect the caller to have done the first increment of | ||
438 | * vdso_data->tb_update_count already. | ||
439 | */ | ||
440 | vdso_data->tb_orig_stamp = new_tb_stamp; | ||
441 | vdso_data->stamp_xsec = new_stamp_xsec; | ||
442 | vdso_data->tb_to_xs = new_tb_to_xs; | ||
443 | vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec; | ||
444 | vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec; | ||
445 | vdso_data->stamp_xtime = xtime; | ||
446 | smp_wmb(); | ||
447 | ++(vdso_data->tb_update_count); | ||
448 | } | ||
449 | |||
450 | #ifdef CONFIG_SMP | 426 | #ifdef CONFIG_SMP |
451 | unsigned long profile_pc(struct pt_regs *regs) | 427 | unsigned long profile_pc(struct pt_regs *regs) |
452 | { | 428 | { |
@@ -873,10 +849,37 @@ static cycle_t timebase_read(struct clocksource *cs) | |||
873 | return (cycle_t)get_tb(); | 849 | return (cycle_t)get_tb(); |
874 | } | 850 | } |
875 | 851 | ||
852 | static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec, | ||
853 | u64 new_tb_to_xs, struct timespec *now, | ||
854 | u32 frac_sec) | ||
855 | { | ||
856 | /* | ||
857 | * tb_update_count is used to allow the userspace gettimeofday code | ||
858 | * to assure itself that it sees a consistent view of the tb_to_xs and | ||
859 | * stamp_xsec variables. It reads the tb_update_count, then reads | ||
860 | * tb_to_xs and stamp_xsec and then reads tb_update_count again. If | ||
861 | * the two values of tb_update_count match and are even then the | ||
862 | * tb_to_xs and stamp_xsec values are consistent. If not, then it | ||
863 | * loops back and reads them again until this criteria is met. | ||
864 | * We expect the caller to have done the first increment of | ||
865 | * vdso_data->tb_update_count already. | ||
866 | */ | ||
867 | vdso_data->tb_orig_stamp = new_tb_stamp; | ||
868 | vdso_data->stamp_xsec = new_stamp_xsec; | ||
869 | vdso_data->tb_to_xs = new_tb_to_xs; | ||
870 | vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec; | ||
871 | vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec; | ||
872 | vdso_data->stamp_xtime = *now; | ||
873 | vdso_data->stamp_sec_fraction = frac_sec; | ||
874 | smp_wmb(); | ||
875 | ++(vdso_data->tb_update_count); | ||
876 | } | ||
877 | |||
876 | void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, | 878 | void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, |
877 | u32 mult) | 879 | u32 mult) |
878 | { | 880 | { |
879 | u64 t2x, stamp_xsec; | 881 | u64 t2x, stamp_xsec; |
882 | u32 frac_sec; | ||
880 | 883 | ||
881 | if (clock != &clocksource_timebase) | 884 | if (clock != &clocksource_timebase) |
882 | return; | 885 | return; |
@@ -888,10 +891,14 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock, | |||
888 | /* XXX this assumes clock->shift == 22 */ | 891 | /* XXX this assumes clock->shift == 22 */ |
889 | /* 4611686018 ~= 2^(20+64-22) / 1e9 */ | 892 | /* 4611686018 ~= 2^(20+64-22) / 1e9 */ |
890 | t2x = (u64) mult * 4611686018ULL; | 893 | t2x = (u64) mult * 4611686018ULL; |
891 | stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC; | 894 | stamp_xsec = (u64) wall_time->tv_nsec * XSEC_PER_SEC; |
892 | do_div(stamp_xsec, 1000000000); | 895 | do_div(stamp_xsec, 1000000000); |
893 | stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC; | 896 | stamp_xsec += (u64) wall_time->tv_sec * XSEC_PER_SEC; |
894 | update_gtod(clock->cycle_last, stamp_xsec, t2x); | 897 | |
898 | BUG_ON(wall_time->tv_nsec >= NSEC_PER_SEC); | ||
899 | /* this is tv_nsec / 1e9 as a 0.32 fraction */ | ||
900 | frac_sec = ((u64) wall_time->tv_nsec * 18446744073ULL) >> 32; | ||
901 | update_gtod(clock->cycle_last, stamp_xsec, t2x, wall_time, frac_sec); | ||
895 | } | 902 | } |
896 | 903 | ||
897 | void update_vsyscall_tz(void) | 904 | void update_vsyscall_tz(void) |