summaryrefslogtreecommitdiff
path: root/arch/s390
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2009-10-29 17:04:13 +0300
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2009-10-29 17:05:13 +0300
commitf8501ba77d69c88a65e4ebbe03bdc65b1edb0b86 (patch)
tree27e42cf7bd5171c5b17c2d423b6ae5d3394cb6ef /arch/s390
parent70f5dc514c0b183ee813dc3b3983b04891fd1e7a (diff)
downloadlinux-f8501ba77d69c88a65e4ebbe03bdc65b1edb0b86.tar.xz
[S390] smp: fix sigp stop handling
According to the architecture a cpu must not necessarily enter stopped state after completion of a sigp instruction with "stop" order code. So remove the BUG() statement after self sending sigp stop to avoid that it ever gets reached. Also add a sigp busy check to make sure that the order gets delivered. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/kernel/ipl.c7
-rw-r--r--arch/s390/kernel/smp.c4
-rw-r--r--arch/s390/kernel/swsusp_asm64.S1
3 files changed, 6 insertions, 6 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index ee57a42e6e93..4890ac6d7faa 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -1595,10 +1595,9 @@ static void stop_run(struct shutdown_trigger *trigger)
{
if (strcmp(trigger->name, ON_PANIC_STR) == 0)
disabled_wait((unsigned long) __builtin_return_address(0));
- else {
- signal_processor(smp_processor_id(), sigp_stop);
- for (;;);
- }
+ while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy)
+ cpu_relax();
+ for (;;);
}
static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR,
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index c699ac538c49..c99c45b848e3 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -647,8 +647,8 @@ void __cpu_die(unsigned int cpu)
void cpu_die(void)
{
idle_task_exit();
- signal_processor(smp_processor_id(), sigp_stop);
- BUG();
+ while (signal_processor(smp_processor_id(), sigp_stop) == sigp_busy)
+ cpu_relax();
for (;;);
}
diff --git a/arch/s390/kernel/swsusp_asm64.S b/arch/s390/kernel/swsusp_asm64.S
index 7c8653e27db6..0f4ef3b856d9 100644
--- a/arch/s390/kernel/swsusp_asm64.S
+++ b/arch/s390/kernel/swsusp_asm64.S
@@ -199,6 +199,7 @@ pgm_check_entry:
brc 2,4b /* busy, try again */
5:
sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */
+ brc 2,5b /* busy, try again */
6: j 6b
restart_suspend: