patch-2.4.0-test3 linux/arch/mips64/sgi-ip27/ip27-timer.c

Next file: linux/arch/mips64/tools/Makefile
Previous file: linux/arch/mips64/sgi-ip27/ip27-setup.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/sgi-ip27/ip27-timer.c linux/arch/mips64/sgi-ip27/ip27-timer.c
@@ -1,9 +1,7 @@
-/* $Id: ip27-timer.c,v 1.3 2000/02/18 09:54:40 ulfc Exp $
- *
- * Copytight (C) 1999 Ralf Baechle (ralf@gnu.org)
- * Copytight (C) 1999 Silicon Graphics, Inc.
+/*
+ * Copytight (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
+ * Copytight (C) 1999, 2000 Silicon Graphics, Inc.
  */
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -36,10 +34,11 @@
 #define CYCLES_PER_SEC		(NSEC_PER_SEC/NSEC_PER_CYCLE)
 #define CYCLES_PER_JIFFY	(CYCLES_PER_SEC/HZ)
 
-static unsigned long ct_cur;		/* What counter should be at next timer irq */
+static unsigned long ct_cur[NR_CPUS];	/* What counter should be at next timer irq */
 static long last_rtc_update = 0;	/* Last time the rtc clock got updated */
 
 extern rwlock_t xtime_lock;
+extern volatile unsigned long lost_ticks;
 
 
 static int set_rtc_mmss(unsigned long nowtime)
@@ -91,26 +90,28 @@
 void rt_timer_interrupt(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
-	int cpuA = ((cputoslice(smp_processor_id())) == 0);
-	int user = user_mode(regs);
+	int cpuA = ((cputoslice(cpu)) == 0);
 	int irq = 7;				/* XXX Assign number */
 
 	write_lock(&xtime_lock);
 
 again:
 	LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0);	/* Ack  */
-	ct_cur += CYCLES_PER_JIFFY;
-	LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur);
+	ct_cur[cpu] += CYCLES_PER_JIFFY;
+	LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]);
 
-	if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur)
+	if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu])
 		goto again;
 
-	kstat.irqs[cpu][irq]++;		/* kstat+do_timer only for bootcpu? */
-	do_timer(regs);
+	kstat.irqs[cpu][irq]++;		/* kstat only for bootcpu? */
+
+	if (cpu == 0)
+		do_timer(regs);
 
 #ifdef CONFIG_SMP
 	if (current->pid) {
 		unsigned int *inc, *inc2;
+		int user = user_mode(regs);
 
 		update_one_process(current, 1, user, !user, cpu);
 		if (--current->counter <= 0) {
@@ -119,7 +120,7 @@
 		}
 
 		if (user) {
-			if (current->priority < DEF_PRIORITY) {
+			if (current->nice > 0) {
 				inc = &kstat.cpu_nice;
 				inc2 = &kstat.per_cpu_nice[cpu];
 			} else {
@@ -159,19 +160,51 @@
 	write_unlock(&xtime_lock);
 }
 
+unsigned long inline do_gettimeoffset(void)
+{
+	unsigned long ct_cur1;
+	ct_cur1 = REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT) + CYCLES_PER_JIFFY;
+	return (ct_cur1 - ct_cur[0]) * NSEC_PER_CYCLE / 1000;
+}
+
 void do_gettimeofday(struct timeval *tv)
 {
 	unsigned long flags;
+	unsigned long usec, sec;
 
 	read_lock_irqsave(&xtime_lock, flags);
-	*tv = xtime;
+	usec = do_gettimeoffset();
+	{
+		unsigned long lost = lost_ticks;
+		if (lost)
+			usec += lost * (1000000 / HZ);
+	}
+	sec = xtime.tv_sec;
+	usec += xtime.tv_usec;
 	read_unlock_irqrestore(&xtime_lock, flags);
+
+	while (usec >= 1000000) {
+		usec -= 1000000;
+		sec++;
+	}
+
+	tv->tv_sec = sec;
+	tv->tv_usec = usec;
 }
 
 void do_settimeofday(struct timeval *tv)
 {
 	write_lock_irq(&xtime_lock);
+	tv->tv_usec -= do_gettimeoffset();
+	tv->tv_usec -= lost_ticks * (1000000 / HZ);
+
+	while (tv->tv_usec < 0) {
+		tv->tv_usec += 1000000;
+		tv->tv_sec--;
+	}
+
 	xtime = *tv;
+	time_adjust = 0;		/* stop active adjtime() */
 	time_state = TIME_BAD;
 	time_maxerror = MAXPHASE;
 	time_esterror = MAXPHASE;
@@ -286,15 +319,16 @@
 	 * node and timeouts will not happen there.
 	 */
 	if (get_compact_nodeid() == cnode) {
+		int cpu = smp_processor_id();
 		LOCAL_HUB_S(PI_RT_EN_A, 1);
 		LOCAL_HUB_S(PI_RT_EN_B, 1);
 		LOCAL_HUB_S(PI_PROF_EN_A, 0);
 		LOCAL_HUB_S(PI_PROF_EN_B, 0);
-		ct_cur = CYCLES_PER_JIFFY;
-		LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur);
+		ct_cur[cpu] = CYCLES_PER_JIFFY;
+		LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]);
 		LOCAL_HUB_S(PI_RT_COUNT, 0);
 		LOCAL_HUB_S(PI_RT_PEND_A, 0);
-		LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur);
+		LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]);
 		LOCAL_HUB_S(PI_RT_COUNT, 0);
 		LOCAL_HUB_S(PI_RT_PEND_B, 0);
 	}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)