Commit 60da26d9 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] s390: sclp console

From: Martin Schwidefsky <schwidefsky@de.ibm.com>

sclp console fixes:

- Add signal-quiesce bug-fix from 2.4.

- Add irq_enter/irq_exit to sclp_sync_wait to prevent the softirqs from
  processing after the external interrupt.
parent 35181f43
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/cpumask.h>
#include <asm/s390_ext.h> #include <asm/s390_ext.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -334,6 +335,8 @@ sclp_sync_wait(void) ...@@ -334,6 +335,8 @@ sclp_sync_wait(void)
unsigned long psw_mask; unsigned long psw_mask;
unsigned long cr0, cr0_sync; unsigned long cr0, cr0_sync;
/* Need to irq_enter() to prevent BH from executing. */
irq_enter();
/* /*
* save cr0 * save cr0
* enable service signal external interruption (cr0.22) * enable service signal external interruption (cr0.22)
...@@ -362,6 +365,7 @@ sclp_sync_wait(void) ...@@ -362,6 +365,7 @@ sclp_sync_wait(void)
/* restore cr0 */ /* restore cr0 */
__ctl_load(cr0, 0, 0); __ctl_load(cr0, 0, 0);
irq_exit();
} }
/* /*
...@@ -467,29 +471,45 @@ static struct sclp_register sclp_state_change_event = { ...@@ -467,29 +471,45 @@ static struct sclp_register sclp_state_change_event = {
* SCLP quiesce event handler * SCLP quiesce event handler
*/ */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
static cpumask_t cpu_quiesce_map;
static void static void
do_load_quiesce_psw(void * __unused) do_load_quiesce_psw(void * __unused)
{ {
psw_t quiesce_psw; psw_t quiesce_psw;
unsigned long status;
int i;
cpu_clear(smp_processor_id(), cpu_quiesce_map); if (smp_processor_id() != 0)
if (smp_processor_id() == 0) { signal_processor(smp_processor_id(), sigp_stop);
/* Wait for all other cpus to enter do_load_quiesce_psw */ /* Wait for all other cpus to enter stopped state */
while (!cpus_empty(cpu_quiesce_map)); i = 1;
/* Quiesce the last cpu with the special psw */ while (i < NR_CPUS) {
quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT; if (!cpu_online(i)) {
quiesce_psw.addr = 0xfff; i++;
__load_psw(quiesce_psw); continue;
}
switch (signal_processor_ps(&status, 0, i, sigp_sense)) {
case sigp_order_code_accepted:
case sigp_status_stored:
/* Check for stopped and check stop state */
if (test_bit(6, &status) || test_bit(4, &status))
i++;
break;
case sigp_busy:
break;
case sigp_not_operational:
i++;
break;
}
} }
signal_processor(smp_processor_id(), sigp_stop); /* Quiesce the last cpu with the special psw */
quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
quiesce_psw.addr = 0xfff;
__load_psw(quiesce_psw);
} }
static void static void
do_machine_quiesce(void) do_machine_quiesce(void)
{ {
cpu_quiesce_map = cpu_online_map;
on_each_cpu(do_load_quiesce_psw, NULL, 0, 0); on_each_cpu(do_load_quiesce_psw, NULL, 0, 0);
} }
#else #else
......
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