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;
*/
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;
todval = -1ULL;
/* Be careful about overflows. */
if (timer < (-1ULL / CLK_TICKS_PER_JIFFY)) {
timer = jiffies_timer_cc + timer * CLK_TICKS_PER_JIFFY;
asm volatile ("SCKC %0" : : "m" (timer));
if (timer >= jiffies_timer_cc)
todval = timer;
}
asm volatile ("SCKC %0" : : "m" (todval));
}
/*
......
......@@ -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());
/* 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
......
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