aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/stop_machine.c
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2008-10-22 11:00:26 -0400
committerRusty Russell <rusty@rustcorp.com.au>2008-10-21 19:00:26 -0400
commit8163bcac779f62c6bf847caed9bce905db0693fb (patch)
tree8fcf397c504fadbebecde09901aacef06b4551d8 /kernel/stop_machine.c
parentc9583e55fa2b08a230c549bd1e3c0bde6c50d9cc (diff)
stop_machine: fix error code handling on multiple cpus
Using |= for updating a value which might be updated on several cpus concurrently will not always work since we need to make sure that the update happens atomically. To fix this just use a write if the called function returns an error code on a cpu. We end up writing the error code of an arbitrary cpu if multiple ones fail but that should be sufficient. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'kernel/stop_machine.c')
-rw-r--r--kernel/stop_machine.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 0e688c6a1a63..8aff79d90ddc 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -66,6 +66,7 @@ static void stop_cpu(struct work_struct *unused)
66 enum stopmachine_state curstate = STOPMACHINE_NONE; 66 enum stopmachine_state curstate = STOPMACHINE_NONE;
67 struct stop_machine_data *smdata = &idle; 67 struct stop_machine_data *smdata = &idle;
68 int cpu = smp_processor_id(); 68 int cpu = smp_processor_id();
69 int err;
69 70
70 if (!active_cpus) { 71 if (!active_cpus) {
71 if (cpu == first_cpu(cpu_online_map)) 72 if (cpu == first_cpu(cpu_online_map))
@@ -86,9 +87,11 @@ static void stop_cpu(struct work_struct *unused)
86 hard_irq_disable(); 87 hard_irq_disable();
87 break; 88 break;
88 case STOPMACHINE_RUN: 89 case STOPMACHINE_RUN:
89 /* |= allows error detection if functions on 90 /* On multiple CPUs only a single error code
90 * multiple CPUs. */ 91 * is needed to tell that something failed. */
91 smdata->fnret |= smdata->fn(smdata->data); 92 err = smdata->fn(smdata->data);
93 if (err)
94 smdata->fnret = err;
92 break; 95 break;
93 default: 96 default:
94 break; 97 break;