Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -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));
}

/*
+13 −12
Original line number Diff line number Diff line
@@ -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