diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2005-05-01 17:58:57 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-05-01 17:58:57 +0200 |
commit | 4b7e0706620e3947dc1685dfdbc1413404afb545 (patch) | |
tree | c5ba1c919b6d1ca1141fbb0b6e9e0e933a51cc89 | |
parent | [PATCH] s390: regenerate defconfig (diff) | |
download | linux-4b7e0706620e3947dc1685dfdbc1413404afb545.tar.xz linux-4b7e0706620e3947dc1685dfdbc1413404afb545.zip |
[PATCH] s390: idle timer setup
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>
-rw-r--r-- | arch/s390/kernel/time.c | 12 | ||||
-rw-r--r-- | arch/s390/kernel/vtime.c | 25 |
2 files changed, 22 insertions, 15 deletions
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 061e81138dc2..8ca485676780 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -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)); } /* diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index bb6cf02418a2..fa0726507b3d 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -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 |