[PATCH] s390: idle timer setup
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Sun, 1 May 2005 15:58:57 +0000 (08:58 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Sun, 1 May 2005 15:58:57 +0000 (08:58 -0700)
Fix overflow in calculation of the new tod value in stop_hz_timer and fix
wrong virtual timer list idle time in case the virtual timer is already
expired in stop_cpu_timer.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/s390/kernel/time.c
arch/s390/kernel/vtime.c

index 061e81138dc21b9293c410e829341b4d79ca8d78..8ca485676780de694b31134f2303b094e5053e68 100644 (file)
@@ -244,7 +244,7 @@ int sysctl_hz_timer = 1;
  */
 static inline void stop_hz_timer(void)
 {
-       __u64 timer;
+       __u64 timer, todval;
 
        if (sysctl_hz_timer != 0)
                return;
@@ -265,8 +265,14 @@ static inline void stop_hz_timer(void)
         * for the next event.
         */
        timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64;
-       timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
-       asm volatile ("SCKC %0" : : "m" (timer));
+       todval = -1ULL;
+       /* Be careful about overflows. */
+       if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) {
+               timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
+               if (timer >= jiffies_timer_cc)
+                       todval = timer;
+       }
+       asm volatile ("SCKC %0" : : "m" (todval));
 }
 
 /*
index bb6cf02418a28e46e80184c84eeda90abd9e339a..fa0726507b3d57152e5af6b11448757050ece7cc 100644 (file)
@@ -122,12 +122,17 @@ static void start_cpu_timer(void)
        struct vtimer_queue *vt_list;
 
        vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
-       set_vtimer(vt_list->idle);
+
+       /* CPU timer interrupt is pending, don't reprogramm it */
+       if (vt_list->idle & 1LL<<63)
+               return;
+
+       if (!list_empty(&vt_list->list))
+               set_vtimer(vt_list->idle);
 }
 
 static void stop_cpu_timer(void)
 {
-       __u64 done;
        struct vtimer_queue *vt_list;
 
        vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
@@ -138,21 +143,17 @@ static void stop_cpu_timer(void)
                goto fire;
        }
 
-       /* store progress */
-       asm volatile ("STPT %0" : "=m" (done));
+       /* store the actual expire value */
+       asm volatile ("STPT %0" : "=m" (vt_list->idle));
 
        /*
-        * If done is negative we do not stop the CPU timer
-        * because we will get instantly an interrupt that
-        * will start the CPU timer again.
+        * If the CPU timer is negative we don't reprogramm
+        * it because we will get instantly an interrupt.
         */
-       if (done & 1LL<<63)
+       if (vt_list->idle & 1LL<<63)
                return;
-       else
-               vt_list->offset += vt_list->to_expire - done;
 
-       /* save the actual expire value */
-       vt_list->idle = done;
+       vt_list->offset += vt_list->to_expire - vt_list->idle;
 
        /*
         * We cannot halt the CPU timer, we just write a value that