diff options
-rw-r--r-- | kernel/smp.c | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/kernel/smp.c b/kernel/smp.c index 17c6e5860231..2fe66f7c617a 100644 --- a/kernel/smp.c +++ b/kernel/smp.c | |||
@@ -194,6 +194,7 @@ void generic_smp_call_function_interrupt(void) | |||
194 | */ | 194 | */ |
195 | list_for_each_entry_rcu(data, &call_function.queue, csd.list) { | 195 | list_for_each_entry_rcu(data, &call_function.queue, csd.list) { |
196 | int refs; | 196 | int refs; |
197 | void (*func) (void *info); | ||
197 | 198 | ||
198 | /* | 199 | /* |
199 | * Since we walk the list without any locks, we might | 200 | * Since we walk the list without any locks, we might |
@@ -213,24 +214,32 @@ void generic_smp_call_function_interrupt(void) | |||
213 | if (atomic_read(&data->refs) == 0) | 214 | if (atomic_read(&data->refs) == 0) |
214 | continue; | 215 | continue; |
215 | 216 | ||
216 | if (!cpumask_test_and_clear_cpu(cpu, data->cpumask)) | 217 | func = data->csd.func; /* for later warn */ |
217 | continue; | ||
218 | |||
219 | data->csd.func(data->csd.info); | 218 | data->csd.func(data->csd.info); |
220 | 219 | ||
220 | /* | ||
221 | * If the cpu mask is not still set then it enabled interrupts, | ||
222 | * we took another smp interrupt, and executed the function | ||
223 | * twice on this cpu. In theory that copy decremented refs. | ||
224 | */ | ||
225 | if (!cpumask_test_and_clear_cpu(cpu, data->cpumask)) { | ||
226 | WARN(1, "%pS enabled interrupts and double executed\n", | ||
227 | func); | ||
228 | continue; | ||
229 | } | ||
230 | |||
221 | refs = atomic_dec_return(&data->refs); | 231 | refs = atomic_dec_return(&data->refs); |
222 | WARN_ON(refs < 0); | 232 | WARN_ON(refs < 0); |
223 | if (!refs) { | ||
224 | WARN_ON(!cpumask_empty(data->cpumask)); | ||
225 | |||
226 | raw_spin_lock(&call_function.lock); | ||
227 | list_del_rcu(&data->csd.list); | ||
228 | raw_spin_unlock(&call_function.lock); | ||
229 | } | ||
230 | 233 | ||
231 | if (refs) | 234 | if (refs) |
232 | continue; | 235 | continue; |
233 | 236 | ||
237 | WARN_ON(!cpumask_empty(data->cpumask)); | ||
238 | |||
239 | raw_spin_lock(&call_function.lock); | ||
240 | list_del_rcu(&data->csd.list); | ||
241 | raw_spin_unlock(&call_function.lock); | ||
242 | |||
234 | csd_unlock(&data->csd); | 243 | csd_unlock(&data->csd); |
235 | } | 244 | } |
236 | 245 | ||