patch-2.4.18 linux/arch/s390/kernel/time.c
Next file: linux/arch/s390/kernel/traps.c
Previous file: linux/arch/s390/kernel/smp.c
Back to the patch index
Back to the overall index
- Lines: 187
- Date:
Mon Feb 4 16:55:13 2002
- Orig file:
linux.orig/arch/s390/kernel/time.c
- Orig date:
Mon Feb 18 20:18:39 2002
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/kernel/time.c linux/arch/s390/kernel/time.c
@@ -33,19 +33,18 @@
#include <asm/irq.h>
-
/* change this if you have some constant time drift */
-#define USECS_PER_JIFFY ((signed long)1000000/HZ)
-#define CLK_TICKS_PER_JIFFY ((signed long)USECS_PER_JIFFY<<12)
+#define USECS_PER_JIFFY ((unsigned long) 1000000/HZ)
+#define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY << 12)
#define TICK_SIZE tick
-static uint64_t init_timer_cc, last_timer_cc;
+static uint64_t init_timer_cc;
extern rwlock_t xtime_lock;
extern unsigned long wall_jiffies;
-void tod_to_timeval(uint64_t todval, struct timeval *xtime)
+void tod_to_timeval(__u64 todval, struct timeval *xtime)
{
const int high_bit = 0x80000000L;
const int c_f4240 = 0xf4240L;
@@ -79,13 +78,15 @@
: "cc", "memory", "2", "3", "4" );
}
-unsigned long do_gettimeoffset(void)
+static inline unsigned long do_gettimeoffset(void)
{
- __u64 timer_cc;
+ __u64 now;
- asm volatile ("STCK %0" : "=m" (timer_cc));
- /* We require the offset from the previous interrupt */
- return ((unsigned long)((timer_cc - last_timer_cc)>>12));
+ asm ("STCK %0" : "=m" (now));
+ now = (now - init_timer_cc) >> 12;
+ /* We require the offset from the latest update of xtime */
+ now -= (__u64) wall_jiffies*USECS_PER_JIFFY;
+ return (unsigned long) now;
}
/*
@@ -95,15 +96,10 @@
{
unsigned long flags;
unsigned long usec, sec;
- unsigned long lost_ticks;
read_lock_irqsave(&xtime_lock, flags);
- lost_ticks = jiffies - wall_jiffies;
- usec = do_gettimeoffset();
- if (lost_ticks)
- usec +=(USECS_PER_JIFFY*lost_ticks);
sec = xtime.tv_sec;
- usec += xtime.tv_usec;
+ usec = xtime.tv_usec + do_gettimeoffset();
read_unlock_irqrestore(&xtime_lock, flags);
while (usec >= 1000000) {
@@ -149,51 +145,31 @@
extern __u16 boot_cpu_addr;
#endif
-void do_timer_interrupt(struct pt_regs *regs, __u16 error_code)
+static void do_comparator_interrupt(struct pt_regs *regs, __u16 error_code)
{
int cpu = smp_processor_id();
irq_enter(cpu, 0);
- /*
- * reset timer to 10ms minus time already elapsed
- * since timer-interrupt pending
- */
+ /*
+ * set clock comparator for next tick
+ */
+ S390_lowcore.jiffy_timer += CLK_TICKS_PER_JIFFY;
+ asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer));
+
#ifdef CONFIG_SMP
- if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr) {
+ if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr)
write_lock(&xtime_lock);
- last_timer_cc = S390_lowcore.jiffy_timer_cc;
- }
-#else
- last_timer_cc = S390_lowcore.jiffy_timer_cc;
-#endif
- /* set clock comparator */
- S390_lowcore.jiffy_timer_cc += CLK_TICKS_PER_JIFFY;
- asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer_cc));
-/*
- * In the SMP case we use the local timer interrupt to do the
- * profiling, except when we simulate SMP mode on a uniprocessor
- * system, in that case we have to call the local interrupt handler.
- */
-#ifdef CONFIG_SMP
- /* when SMP, do smp_local_timer_interrupt for *all* CPUs,
- but only do the rest for the boot CPU */
- smp_local_timer_interrupt(regs);
-#else
- if (!user_mode(regs))
- s390_do_profile(regs->psw.addr);
-#endif
+ update_process_times(user_mode(regs));
-#ifdef CONFIG_SMP
- if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr)
-#endif
- {
+ if (S390_lowcore.cpu_data.cpu_addr == boot_cpu_addr) {
do_timer(regs);
-#ifdef CONFIG_SMP
write_unlock(&xtime_lock);
-#endif
}
+#else
+ do_timer(regs);
+#endif
irq_exit(cpu, 0);
}
@@ -201,19 +177,17 @@
/*
* Start the clock comparator on the current CPU
*/
-static long cr0 __attribute__ ((aligned (8)));
-
-void init_100hz_timer(void)
+void init_cpu_timer(void)
{
+ unsigned long cr0;
+
/* allow clock comparator timer interrupt */
asm volatile ("STCTL 0,0,%0" : "=m" (cr0) : : "memory");
cr0 |= 0x800;
asm volatile ("LCTL 0,0,%0" : : "m" (cr0) : "memory");
- /* set clock comparator */
- /* read the TOD clock */
- asm volatile ("STCK %0" : "=m" (S390_lowcore.jiffy_timer_cc));
- S390_lowcore.jiffy_timer_cc += CLK_TICKS_PER_JIFFY;
- asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer_cc));
+ S390_lowcore.jiffy_timer = (__u64) jiffies * CLK_TICKS_PER_JIFFY;
+ S390_lowcore.jiffy_timer += init_timer_cc + CLK_TICKS_PER_JIFFY;
+ asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer));
}
/*
@@ -222,6 +196,7 @@
*/
void __init time_init(void)
{
+ __u64 set_time_cc;
int cc;
/* kick the TOD clock */
@@ -241,15 +216,16 @@
printk("time_init: TOD clock stopped/non-operational\n");
break;
}
+
+ /* set xtime */
+ set_time_cc = init_timer_cc - 0x8126d60e46000000LL +
+ (0x3c26700LL*1000000*4096);
+ tod_to_timeval(set_time_cc, &xtime);
+
/* request the 0x1004 external interrupt */
- if (register_external_interrupt(0x1004, do_timer_interrupt) != 0)
- panic("Couldn't request external interrupts 0x1004");
- init_100hz_timer();
- init_timer_cc = S390_lowcore.jiffy_timer_cc;
- init_timer_cc -= 0x8126d60e46000000LL -
- (0x3c26700LL*1000000*4096);
- tod_to_timeval(init_timer_cc, &xtime);
+ if (register_external_interrupt(0x1004, do_comparator_interrupt) != 0)
+ panic("Couldn't request external interrupt 0x1004");
- /* Set do_get_fast_time function pointer. */
- do_get_fast_time = do_gettimeofday;
+ /* init CPU timer */
+ init_cpu_timer();
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)