[S390] smp: perform initial cpu reset before starting a cpu
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Thu, 26 Mar 2009 14:24:53 +0000 (15:24 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 26 Mar 2009 14:24:30 +0000 (15:24 +0100)
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>
arch/s390/kernel/smp.c

index 1f4711b60aab10eaaa6fce732e7d479f217eaace..fe5f8dc1e6fa096aa202a03e9274fc362dc3b7bf 100644 (file)
@@ -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)