From 934b2857cc576ae53c92a66e63fce7ddcfa74691 Mon Sep 17 00:00:00 2001
From: Heiko Carstens <heiko.carstens@de.ibm.com>
Date: Fri, 1 Aug 2008 16:39:11 +0200
Subject: [S390] nohz/sclp: disable timer on synchronous waits.

sclp_sync_wait wait synchronously for an sclp interrupt and disables
timer interrupts. However on the irq enter paths there is an extra
check if a timer interrupt would be due and calls the timer callback.
This would schedule softirqs in the wrong context.
So introduce local_tick_enable/disable which prevents this.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
---
 drivers/s390/char/sclp.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

(limited to 'drivers/s390')

diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 3c8b25e..1fd8f21 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -399,6 +399,7 @@ sclp_tod_from_jiffies(unsigned long jiffies)
 void
 sclp_sync_wait(void)
 {
+	unsigned long long old_tick;
 	unsigned long flags;
 	unsigned long cr0, cr0_sync;
 	u64 timeout;
@@ -419,11 +420,12 @@ sclp_sync_wait(void)
 	if (!irq_context)
 		local_bh_disable();
 	/* Enable service-signal interruption, disable timer interrupts */
+	old_tick = local_tick_disable();
 	trace_hardirqs_on();
 	__ctl_store(cr0, 0, 0);
 	cr0_sync = cr0;
+	cr0_sync &= 0xffff00a0;
 	cr0_sync |= 0x00000200;
-	cr0_sync &= 0xFFFFF3AC;
 	__ctl_load(cr0_sync, 0, 0);
 	__raw_local_irq_stosm(0x01);
 	/* Loop until driver state indicates finished request */
@@ -439,9 +441,9 @@ sclp_sync_wait(void)
 	__ctl_load(cr0, 0, 0);
 	if (!irq_context)
 		_local_bh_enable();
+	local_tick_enable(old_tick);
 	local_irq_restore(flags);
 }
-
 EXPORT_SYMBOL(sclp_sync_wait);
 
 /* Dispatch changes in send and receive mask to registered listeners. */
-- 
cgit v1.1