aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-08-30 02:13:16 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-08-31 00:21:55 -0400
commiteb36c2884a1a2190791afe65fd833b2d3cd4b999 (patch)
tree2bc7defdfee59f273e81a5ddd2e792c65bb93d4c /arch/powerpc
parent98a3c781057fa43494e7e8b39d639e93fca0ecbf (diff)
[PATCH] ppc32: fix last_jiffy time comparison
This fixes a hang on ppc32. The problem was that I was comparing a 32-bit quantity with a 64-bit quantity, and consequently time wasn't advancing. This makes us use a 64-bit quantity on all platforms, which ends up simplifying the code since we can now get rid of the tb_last_stamp variable (which actually fixes another bug that Ben H and I noticed while going carefully through the code). This works fine on my G4 tibook. Let me know how it goes on your machines. Acked-by: Olaf Hering <olaf@aepfle.de> Acked-by: Mikael Pettersson <mikpe@it.uu.se> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/time.c25
1 files changed, 8 insertions, 17 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 18e59e43d2b3..a124499e65d9 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -125,15 +125,8 @@ static long timezone_offset;
125unsigned long ppc_proc_freq; 125unsigned long ppc_proc_freq;
126unsigned long ppc_tb_freq; 126unsigned long ppc_tb_freq;
127 127
128u64 tb_last_jiffy __cacheline_aligned_in_smp; 128static u64 tb_last_jiffy __cacheline_aligned_in_smp;
129unsigned long tb_last_stamp; 129static DEFINE_PER_CPU(u64, last_jiffy);
130
131/*
132 * Note that on ppc32 this only stores the bottom 32 bits of
133 * the timebase value, but that's enough to tell when a jiffy
134 * has passed.
135 */
136DEFINE_PER_CPU(unsigned long, last_jiffy);
137 130
138#ifdef CONFIG_VIRT_CPU_ACCOUNTING 131#ifdef CONFIG_VIRT_CPU_ACCOUNTING
139/* 132/*
@@ -458,7 +451,7 @@ void do_gettimeofday(struct timeval *tv)
458 do { 451 do {
459 seq = read_seqbegin_irqsave(&xtime_lock, flags); 452 seq = read_seqbegin_irqsave(&xtime_lock, flags);
460 sec = xtime.tv_sec; 453 sec = xtime.tv_sec;
461 nsec = xtime.tv_nsec + tb_ticks_since(tb_last_stamp); 454 nsec = xtime.tv_nsec + tb_ticks_since(tb_last_jiffy);
462 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); 455 } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
463 usec = nsec / 1000; 456 usec = nsec / 1000;
464 while (usec >= 1000000) { 457 while (usec >= 1000000) {
@@ -700,7 +693,6 @@ void timer_interrupt(struct pt_regs * regs)
700 tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy; 693 tb_next_jiffy = tb_last_jiffy + tb_ticks_per_jiffy;
701 if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) { 694 if (per_cpu(last_jiffy, cpu) >= tb_next_jiffy) {
702 tb_last_jiffy = tb_next_jiffy; 695 tb_last_jiffy = tb_next_jiffy;
703 tb_last_stamp = per_cpu(last_jiffy, cpu);
704 do_timer(regs); 696 do_timer(regs);
705 timer_recalc_offset(tb_last_jiffy); 697 timer_recalc_offset(tb_last_jiffy);
706 timer_check_rtc(); 698 timer_check_rtc();
@@ -749,7 +741,7 @@ void __init smp_space_timers(unsigned int max_cpus)
749 int i; 741 int i;
750 unsigned long half = tb_ticks_per_jiffy / 2; 742 unsigned long half = tb_ticks_per_jiffy / 2;
751 unsigned long offset = tb_ticks_per_jiffy / max_cpus; 743 unsigned long offset = tb_ticks_per_jiffy / max_cpus;
752 unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); 744 u64 previous_tb = per_cpu(last_jiffy, boot_cpuid);
753 745
754 /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ 746 /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */
755 previous_tb -= tb_ticks_per_jiffy; 747 previous_tb -= tb_ticks_per_jiffy;
@@ -830,7 +822,7 @@ int do_settimeofday(struct timespec *tv)
830 * and therefore the (jiffies - wall_jiffies) computation 822 * and therefore the (jiffies - wall_jiffies) computation
831 * has been removed. 823 * has been removed.
832 */ 824 */
833 tb_delta = tb_ticks_since(tb_last_stamp); 825 tb_delta = tb_ticks_since(tb_last_jiffy);
834 tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */ 826 tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */
835 new_nsec -= SCALE_XSEC(tb_delta, 1000000000); 827 new_nsec -= SCALE_XSEC(tb_delta, 1000000000);
836 828
@@ -950,8 +942,7 @@ void __init time_init(void)
950 if (__USE_RTC()) { 942 if (__USE_RTC()) {
951 /* 601 processor: dec counts down by 128 every 128ns */ 943 /* 601 processor: dec counts down by 128 every 128ns */
952 ppc_tb_freq = 1000000000; 944 ppc_tb_freq = 1000000000;
953 tb_last_stamp = get_rtcl(); 945 tb_last_jiffy = get_rtcl();
954 tb_last_jiffy = tb_last_stamp;
955 } else { 946 } else {
956 /* Normal PowerPC with timebase register */ 947 /* Normal PowerPC with timebase register */
957 ppc_md.calibrate_decr(); 948 ppc_md.calibrate_decr();
@@ -959,7 +950,7 @@ void __init time_init(void)
959 ppc_tb_freq / 1000000, ppc_tb_freq % 1000000); 950 ppc_tb_freq / 1000000, ppc_tb_freq % 1000000);
960 printk(KERN_DEBUG "time_init: processor frequency = %lu.%.6lu MHz\n", 951 printk(KERN_DEBUG "time_init: processor frequency = %lu.%.6lu MHz\n",
961 ppc_proc_freq / 1000000, ppc_proc_freq % 1000000); 952 ppc_proc_freq / 1000000, ppc_proc_freq % 1000000);
962 tb_last_stamp = tb_last_jiffy = get_tb(); 953 tb_last_jiffy = get_tb();
963 } 954 }
964 955
965 tb_ticks_per_jiffy = ppc_tb_freq / HZ; 956 tb_ticks_per_jiffy = ppc_tb_freq / HZ;
@@ -1036,7 +1027,7 @@ void __init time_init(void)
1036 do_gtod.varp = &do_gtod.vars[0]; 1027 do_gtod.varp = &do_gtod.vars[0];
1037 do_gtod.var_idx = 0; 1028 do_gtod.var_idx = 0;
1038 do_gtod.varp->tb_orig_stamp = tb_last_jiffy; 1029 do_gtod.varp->tb_orig_stamp = tb_last_jiffy;
1039 __get_cpu_var(last_jiffy) = tb_last_stamp; 1030 __get_cpu_var(last_jiffy) = tb_last_jiffy;
1040 do_gtod.varp->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC; 1031 do_gtod.varp->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC;
1041 do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; 1032 do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
1042 do_gtod.varp->tb_to_xs = tb_to_xs; 1033 do_gtod.varp->tb_to_xs = tb_to_xs;