aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/smp.c')
-rw-r--r--kernel/smp.c79
1 files changed, 32 insertions, 47 deletions
diff --git a/kernel/smp.c b/kernel/smp.c
index 36552beed397..3aa642d39c03 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -33,69 +33,54 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(struct llist_head, call_single_queue);
33 33
34static void flush_smp_call_function_queue(bool warn_cpu_offline); 34static void flush_smp_call_function_queue(bool warn_cpu_offline);
35 35
36static int 36int smpcfd_prepare_cpu(unsigned int cpu)
37hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
38{ 37{
39 long cpu = (long)hcpu;
40 struct call_function_data *cfd = &per_cpu(cfd_data, cpu); 38 struct call_function_data *cfd = &per_cpu(cfd_data, cpu);
41 39
42 switch (action) { 40 if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL,
43 case CPU_UP_PREPARE: 41 cpu_to_node(cpu)))
44 case CPU_UP_PREPARE_FROZEN: 42 return -ENOMEM;
45 if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL, 43 cfd->csd = alloc_percpu(struct call_single_data);
46 cpu_to_node(cpu))) 44 if (!cfd->csd) {
47 return notifier_from_errno(-ENOMEM);
48 cfd->csd = alloc_percpu(struct call_single_data);
49 if (!cfd->csd) {
50 free_cpumask_var(cfd->cpumask);
51 return notifier_from_errno(-ENOMEM);
52 }
53 break;
54
55#ifdef CONFIG_HOTPLUG_CPU
56 case CPU_UP_CANCELED:
57 case CPU_UP_CANCELED_FROZEN:
58 /* Fall-through to the CPU_DEAD[_FROZEN] case. */
59
60 case CPU_DEAD:
61 case CPU_DEAD_FROZEN:
62 free_cpumask_var(cfd->cpumask); 45 free_cpumask_var(cfd->cpumask);
63 free_percpu(cfd->csd); 46 return -ENOMEM;
64 break; 47 }
65 48
66 case CPU_DYING: 49 return 0;
67 case CPU_DYING_FROZEN: 50}
68 /* 51
69 * The IPIs for the smp-call-function callbacks queued by other 52int smpcfd_dead_cpu(unsigned int cpu)
70 * CPUs might arrive late, either due to hardware latencies or 53{
71 * because this CPU disabled interrupts (inside stop-machine) 54 struct call_function_data *cfd = &per_cpu(cfd_data, cpu);
72 * before the IPIs were sent. So flush out any pending callbacks
73 * explicitly (without waiting for the IPIs to arrive), to
74 * ensure that the outgoing CPU doesn't go offline with work
75 * still pending.
76 */
77 flush_smp_call_function_queue(false);
78 break;
79#endif
80 };
81 55
82 return NOTIFY_OK; 56 free_cpumask_var(cfd->cpumask);
57 free_percpu(cfd->csd);
58 return 0;
83} 59}
84 60
85static struct notifier_block hotplug_cfd_notifier = { 61int smpcfd_dying_cpu(unsigned int cpu)
86 .notifier_call = hotplug_cfd, 62{
87}; 63 /*
64 * The IPIs for the smp-call-function callbacks queued by other
65 * CPUs might arrive late, either due to hardware latencies or
66 * because this CPU disabled interrupts (inside stop-machine)
67 * before the IPIs were sent. So flush out any pending callbacks
68 * explicitly (without waiting for the IPIs to arrive), to
69 * ensure that the outgoing CPU doesn't go offline with work
70 * still pending.
71 */
72 flush_smp_call_function_queue(false);
73 return 0;
74}
88 75
89void __init call_function_init(void) 76void __init call_function_init(void)
90{ 77{
91 void *cpu = (void *)(long)smp_processor_id();
92 int i; 78 int i;
93 79
94 for_each_possible_cpu(i) 80 for_each_possible_cpu(i)
95 init_llist_head(&per_cpu(call_single_queue, i)); 81 init_llist_head(&per_cpu(call_single_queue, i));
96 82
97 hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu); 83 smpcfd_prepare_cpu(smp_processor_id());
98 register_cpu_notifier(&hotplug_cfd_notifier);
99} 84}
100 85
101/* 86/*