diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2009-03-26 14:24:53 (GMT) |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-03-26 14:24:30 (GMT) |
commit | d0d3cdf4c27fa4ce241616da08138954e02890f7 (patch) | |
tree | d41f825cc2259b1f687d4c49d2b0fba597f3da2d /arch/s390 | |
parent | 6d54c5a3fb13d32d66a8383cb0b5fb422a563051 (diff) | |
download | linux-d0d3cdf4c27fa4ce241616da08138954e02890f7.tar.xz |
[S390] smp: perform initial cpu reset before starting a cpu
Performing an initial cpu reset makes sure all registers and tlbs of
the targeted cpu are initialized and flushed.
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/smp.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 1f4711b..fe5f8dc 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -534,18 +534,23 @@ int __cpuinit __cpu_up(unsigned int cpu) struct _lowcore *cpu_lowcore; struct stack_frame *sf; sigp_ccode ccode; + u32 lowcore; if (smp_cpu_state[cpu] != CPU_STATE_CONFIGURED) return -EIO; if (smp_alloc_lowcore(cpu)) return -ENOMEM; - - ccode = signal_processor_p((__u32)(unsigned long)(lowcore_ptr[cpu]), - cpu, sigp_set_prefix); - if (ccode) { - smp_free_lowcore(cpu); - return -EIO; - } + do { + ccode = signal_processor(cpu, sigp_initial_cpu_reset); + if (ccode == sigp_busy) + udelay(10); + if (ccode == sigp_not_operational) + goto err_out; + } while (ccode == sigp_busy); + + lowcore = (u32)(unsigned long)lowcore_ptr[cpu]; + while (signal_processor_p(lowcore, cpu, sigp_set_prefix) == sigp_busy) + udelay(10); idle = current_set[cpu]; cpu_lowcore = lowcore_ptr[cpu]; @@ -574,6 +579,10 @@ int __cpuinit __cpu_up(unsigned int cpu) while (!cpu_online(cpu)) cpu_relax(); return 0; + +err_out: + smp_free_lowcore(cpu); + return -EIO; } static int __init setup_possible_cpus(char *s) |