patch-2.3.99-pre9 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.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-timer.c linux/arch/mips64/sgi-ip27/ip27-timer.c
@@ -3,6 +3,7 @@
  * Copytight (C) 1999 Ralf Baechle (ralf@gnu.org)
  * Copytight (C) 1999 Silicon Graphics, Inc.
  */
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -19,6 +20,7 @@
 #include <asm/sn/klconfig.h>
 #include <asm/sn/arch.h>
 #include <asm/sn/addrs.h>
+#include <asm/sn/sn_private.h>
 #include <asm/sn/sn0/ip27.h>
 #include <asm/sn/sn0/hub.h>
 
@@ -44,7 +46,6 @@
 {               
         int retval = 0;
         int real_seconds, real_minutes, cmos_minutes;
-        unsigned char save_control, save_freq_select;
 	struct m48t35_rtc *rtc;
 	nasid_t nid;
 
@@ -89,20 +90,50 @@
 
 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 irq = 7;				/* XXX Assign number */
 
 	write_lock(&xtime_lock);
 
 again:
-	LOCAL_HUB_S(PI_RT_PEND_A, 0);		/* Ack  */
+	LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0);	/* Ack  */
 	ct_cur += CYCLES_PER_JIFFY;
-	LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur);
+	LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur);
 
 	if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur)
 		goto again;
 
-	kstat.irqs[0][irq]++;
+	kstat.irqs[cpu][irq]++;		/* kstat+do_timer only for bootcpu? */
 	do_timer(regs);
+
+#ifdef CONFIG_SMP
+	if (current->pid) {
+		unsigned int *inc, *inc2;
+
+		update_one_process(current, 1, user, !user, cpu);
+		if (--current->counter <= 0) {
+			current->counter = 0;
+			current->need_resched = 1;
+		}
+
+		if (user) {
+			if (current->priority < DEF_PRIORITY) {
+				inc = &kstat.cpu_nice;
+				inc2 = &kstat.per_cpu_nice[cpu];
+			} else {
+				inc = &kstat.cpu_user;
+				inc2 = &kstat.per_cpu_user[cpu];
+			}
+		} else {
+			inc = &kstat.cpu_system;
+			inc2 = &kstat.per_cpu_system[cpu];
+		}
+		atomic_inc((atomic_t *)inc);
+		atomic_inc((atomic_t *)inc2);
+	}
+#endif /* CONFIG_SMP */
 	
         /*
          * If we have an externally synchronized Linux clock, then update
@@ -194,7 +225,8 @@
 	nasid_t nid;
 
 	nid = get_nasid();
-	rtc = KL_CONFIG_CH_CONS_INFO(nid)->memory_base + IOC3_BYTEBUS_DEV0;
+	rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + 
+							IOC3_BYTEBUS_DEV0);
 
         rtc->control |= M48T35_RTC_READ;
 	sec = rtc->sec;
@@ -221,15 +253,18 @@
 
 void __init time_init(void)
 {
+	xtime.tv_sec = get_m48t35_time();
+	xtime.tv_usec = 0;
+}
+
+void __init cpu_time_init(void)
+{
 	lboard_t *board;
 	klcpu_t *cpu;
 	int cpuid;
 	
-	xtime.tv_sec = get_m48t35_time();
-	xtime.tv_usec = 0;
-
 	/* Don't use ARCS.  ARCS is fragile.  Klconfig is simple and sane.  */
-	board = find_lboard(KLTYPE_IP27);
+	board = find_lboard(KL_CONFIG_INFO(get_nasid()), KLTYPE_IP27);
 	if (!board)
 		panic("Can't find board info for myself.");
 
@@ -238,15 +273,29 @@
 	if (!cpu)
 		panic("No information about myself?");
 
-	printk("CPU clock is %dMHz.\n", cpu->cpu_speed);
-
-	/* Don't worry about second CPU, it's disabled.  */
-	LOCAL_HUB_S(PI_RT_EN_A, 1);
-	LOCAL_HUB_S(PI_PROF_EN_A, 0);
-	ct_cur = CYCLES_PER_JIFFY;
-	LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur);
-	LOCAL_HUB_S(PI_RT_COUNT, 0);
-	LOCAL_HUB_S(PI_RT_PEND_A, 0);
+	printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed);
 
 	set_cp0_status(SRB_TIMOCLK, SRB_TIMOCLK);
+}
+
+void __init hub_rtc_init(cnodeid_t cnode)
+{
+	/*
+	 * We only need to initialize the current node.
+	 * If this is not the current node then it is a cpuless
+	 * node and timeouts will not happen there.
+	 */
+	if (get_compact_nodeid() == cnode) {
+		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);
+		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_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)