summaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2009-03-26 15:24:53 +0100
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-03-26 15:24:30 +0100
commitd0d3cdf4c27fa4ce241616da08138954e02890f7 (patch)
treed41f825cc2259b1f687d4c49d2b0fba597f3da2d /arch/s390/kernel
parent[S390] smp: fix memory leak on __cpu_up (diff)
downloadlinux-d0d3cdf4c27fa4ce241616da08138954e02890f7.tar.xz
linux-d0d3cdf4c27fa4ce241616da08138954e02890f7.zip
[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/kernel')
-rw-r--r--arch/s390/kernel/smp.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 1f4711b60aab..fe5f8dc1e6fa 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)