Commit 4b7e0706 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[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: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b2c6678c
...@@ -244,7 +244,7 @@ int sysctl_hz_timer = 1; ...@@ -244,7 +244,7 @@ int sysctl_hz_timer = 1;
*/ */
static inline void stop_hz_timer(void) static inline void stop_hz_timer(void)
{ {
__u64 timer; __u64 timer, todval;
if (sysctl_hz_timer != 0) if (sysctl_hz_timer != 0)
return; return;
...@@ -265,8 +265,14 @@ static inline void stop_hz_timer(void) ...@@ -265,8 +265,14 @@ static inline void stop_hz_timer(void)
* for the next event. * for the next event.
*/ */
timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64; timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64;
timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY; todval = -1ULL;
asm volatile ("SCKC %0" : : "m" (timer)); /* 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));
} }
/* /*
......
...@@ -122,12 +122,17 @@ static void start_cpu_timer(void) ...@@ -122,12 +122,17 @@ static void start_cpu_timer(void)
struct vtimer_queue *vt_list; struct vtimer_queue *vt_list;
vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); 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) static void stop_cpu_timer(void)
{ {
__u64 done;
struct vtimer_queue *vt_list; struct vtimer_queue *vt_list;
vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); vt_list = &per_cpu(virt_cpu_timer, smp_processor_id());
...@@ -138,21 +143,17 @@ static void stop_cpu_timer(void) ...@@ -138,21 +143,17 @@ static void stop_cpu_timer(void)
goto fire; goto fire;
} }
/* store progress */ /* store the actual expire value */
asm volatile ("STPT %0" : "=m" (done)); asm volatile ("STPT %0" : "=m" (vt_list->idle));
/* /*
* If done is negative we do not stop the CPU timer * If the CPU timer is negative we don't reprogramm
* because we will get instantly an interrupt that * it because we will get instantly an interrupt.
* will start the CPU timer again.
*/ */
if (done & 1LL<<63) if (vt_list->idle & 1LL<<63)
return; return;
else
vt_list->offset += vt_list->to_expire - done;
/* save the actual expire value */ vt_list->offset += vt_list->to_expire - vt_list->idle;
vt_list->idle = done;
/* /*
* We cannot halt the CPU timer, we just write a value that * We cannot halt the CPU timer, we just write a value that
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment