aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/smp.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2013-02-04 09:51:49 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2013-02-04 09:51:49 -0500
commit2fb20e2e35cd1455d022ab7a553d7f1663ffbdeb (patch)
tree4b3bb0f76c15264fe7d4cced91127f3d96ff31f5 /kernel/smp.c
parent9cb543124a2d31af42ce61a4c30765ecc8e5f1fa (diff)
parent5b91ab0abc957145c3ff6be03eb9a3901797019f (diff)
Merge branch 'for-rmk/broadcast' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into devel-stable
Diffstat (limited to 'kernel/smp.c')
-rw-r--r--kernel/smp.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/kernel/smp.c b/kernel/smp.c
index 29dd40a9f2f4..69f38bd98b42 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -33,6 +33,7 @@ struct call_function_data {
33 struct call_single_data csd; 33 struct call_single_data csd;
34 atomic_t refs; 34 atomic_t refs;
35 cpumask_var_t cpumask; 35 cpumask_var_t cpumask;
36 cpumask_var_t cpumask_ipi;
36}; 37};
37 38
38static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data); 39static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data);
@@ -56,6 +57,9 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
56 if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL, 57 if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL,
57 cpu_to_node(cpu))) 58 cpu_to_node(cpu)))
58 return notifier_from_errno(-ENOMEM); 59 return notifier_from_errno(-ENOMEM);
60 if (!zalloc_cpumask_var_node(&cfd->cpumask_ipi, GFP_KERNEL,
61 cpu_to_node(cpu)))
62 return notifier_from_errno(-ENOMEM);
59 break; 63 break;
60 64
61#ifdef CONFIG_HOTPLUG_CPU 65#ifdef CONFIG_HOTPLUG_CPU
@@ -65,6 +69,7 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
65 case CPU_DEAD: 69 case CPU_DEAD:
66 case CPU_DEAD_FROZEN: 70 case CPU_DEAD_FROZEN:
67 free_cpumask_var(cfd->cpumask); 71 free_cpumask_var(cfd->cpumask);
72 free_cpumask_var(cfd->cpumask_ipi);
68 break; 73 break;
69#endif 74#endif
70 }; 75 };
@@ -526,6 +531,12 @@ void smp_call_function_many(const struct cpumask *mask,
526 return; 531 return;
527 } 532 }
528 533
534 /*
535 * After we put an entry into the list, data->cpumask
536 * may be cleared again when another CPU sends another IPI for
537 * a SMP function call, so data->cpumask will be zero.
538 */
539 cpumask_copy(data->cpumask_ipi, data->cpumask);
529 raw_spin_lock_irqsave(&call_function.lock, flags); 540 raw_spin_lock_irqsave(&call_function.lock, flags);
530 /* 541 /*
531 * Place entry at the _HEAD_ of the list, so that any cpu still 542 * Place entry at the _HEAD_ of the list, so that any cpu still
@@ -549,7 +560,7 @@ void smp_call_function_many(const struct cpumask *mask,
549 smp_mb(); 560 smp_mb();
550 561
551 /* Send a message to all CPUs in the map */ 562 /* Send a message to all CPUs in the map */
552 arch_send_call_function_ipi_mask(data->cpumask); 563 arch_send_call_function_ipi_mask(data->cpumask_ipi);
553 564
554 /* Optionally wait for the CPUs to complete */ 565 /* Optionally wait for the CPUs to complete */
555 if (wait) 566 if (wait)