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 Original line Diff line number Diff line
@@ -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)
	 * for the next event.
	 * for the next event.
	 */
	 */
	timer = (__u64) (next_timer_interrupt() - jiffies) + jiffies_64;
	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;
		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 Original line Diff line number Diff line
@@ -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());

	/* 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);
		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)
		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