diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2016-07-13 13:17:00 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-07-15 04:41:42 -0400 |
commit | 6b2c28471de550308784560206c3365e5179d42f (patch) | |
tree | 999635046bf5f350a5cfb281ec4251bf149cfc19 | |
parent | e722d8daafb974b9ad1bbaf42f384a5ea5929f5f (diff) |
x86/x2apic: Convert to CPU hotplug state machine
Install the callbacks via the state machine and let the core invoke
the callbacks on the already online CPUs.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Anna-Maria Gleixner <anna-maria@linutronix.de>
Cc: Len Brown <len.brown@intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mathias Krause <minipli@googlemail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: rt@linutronix.de
Link: http://lkml.kernel.org/r/20160713153337.736898691@linutronix.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/x86/kernel/apic/x2apic_cluster.c | 80 | ||||
-rw-r--r-- | include/linux/cpuhotplug.h | 1 |
2 files changed, 31 insertions, 50 deletions
diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index aca8b75c1552..b5da5a8e5e45 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c | |||
@@ -152,68 +152,48 @@ static void init_x2apic_ldr(void) | |||
152 | } | 152 | } |
153 | } | 153 | } |
154 | 154 | ||
155 | /* | 155 | /* |
156 | * At CPU state changes, update the x2apic cluster sibling info. | 156 | * At CPU state changes, update the x2apic cluster sibling info. |
157 | */ | 157 | */ |
158 | static int | 158 | int x2apic_prepare_cpu(unsigned int cpu) |
159 | update_clusterinfo(struct notifier_block *nfb, unsigned long action, void *hcpu) | ||
160 | { | 159 | { |
161 | unsigned int this_cpu = (unsigned long)hcpu; | 160 | if (!zalloc_cpumask_var(&per_cpu(cpus_in_cluster, cpu), GFP_KERNEL)) |
162 | unsigned int cpu; | 161 | return -ENOMEM; |
163 | int err = 0; | 162 | |
164 | 163 | if (!zalloc_cpumask_var(&per_cpu(ipi_mask, cpu), GFP_KERNEL)) { | |
165 | switch (action) { | 164 | free_cpumask_var(per_cpu(cpus_in_cluster, cpu)); |
166 | case CPU_UP_PREPARE: | 165 | return -ENOMEM; |
167 | if (!zalloc_cpumask_var(&per_cpu(cpus_in_cluster, this_cpu), | ||
168 | GFP_KERNEL)) { | ||
169 | err = -ENOMEM; | ||
170 | } else if (!zalloc_cpumask_var(&per_cpu(ipi_mask, this_cpu), | ||
171 | GFP_KERNEL)) { | ||
172 | free_cpumask_var(per_cpu(cpus_in_cluster, this_cpu)); | ||
173 | err = -ENOMEM; | ||
174 | } | ||
175 | break; | ||
176 | case CPU_UP_CANCELED: | ||
177 | case CPU_UP_CANCELED_FROZEN: | ||
178 | case CPU_DEAD: | ||
179 | for_each_online_cpu(cpu) { | ||
180 | if (x2apic_cluster(this_cpu) != x2apic_cluster(cpu)) | ||
181 | continue; | ||
182 | cpumask_clear_cpu(this_cpu, per_cpu(cpus_in_cluster, cpu)); | ||
183 | cpumask_clear_cpu(cpu, per_cpu(cpus_in_cluster, this_cpu)); | ||
184 | } | ||
185 | free_cpumask_var(per_cpu(cpus_in_cluster, this_cpu)); | ||
186 | free_cpumask_var(per_cpu(ipi_mask, this_cpu)); | ||
187 | break; | ||
188 | } | 166 | } |
189 | 167 | ||
190 | return notifier_from_errno(err); | 168 | return 0; |
191 | } | 169 | } |
192 | 170 | ||
193 | static struct notifier_block x2apic_cpu_notifier = { | 171 | int x2apic_dead_cpu(unsigned int this_cpu) |
194 | .notifier_call = update_clusterinfo, | ||
195 | }; | ||
196 | |||
197 | static int x2apic_init_cpu_notifier(void) | ||
198 | { | 172 | { |
199 | int cpu = smp_processor_id(); | 173 | int cpu; |
200 | |||
201 | zalloc_cpumask_var(&per_cpu(cpus_in_cluster, cpu), GFP_KERNEL); | ||
202 | zalloc_cpumask_var(&per_cpu(ipi_mask, cpu), GFP_KERNEL); | ||
203 | 174 | ||
204 | BUG_ON(!per_cpu(cpus_in_cluster, cpu) || !per_cpu(ipi_mask, cpu)); | 175 | for_each_online_cpu(cpu) { |
205 | 176 | if (x2apic_cluster(this_cpu) != x2apic_cluster(cpu)) | |
206 | cpumask_set_cpu(cpu, per_cpu(cpus_in_cluster, cpu)); | 177 | continue; |
207 | register_hotcpu_notifier(&x2apic_cpu_notifier); | 178 | cpumask_clear_cpu(this_cpu, per_cpu(cpus_in_cluster, cpu)); |
208 | return 1; | 179 | cpumask_clear_cpu(cpu, per_cpu(cpus_in_cluster, this_cpu)); |
180 | } | ||
181 | free_cpumask_var(per_cpu(cpus_in_cluster, this_cpu)); | ||
182 | free_cpumask_var(per_cpu(ipi_mask, this_cpu)); | ||
183 | return 0; | ||
209 | } | 184 | } |
210 | 185 | ||
211 | static int x2apic_cluster_probe(void) | 186 | static int x2apic_cluster_probe(void) |
212 | { | 187 | { |
213 | if (x2apic_mode) | 188 | int cpu = smp_processor_id(); |
214 | return x2apic_init_cpu_notifier(); | 189 | |
215 | else | 190 | if (!x2apic_mode) |
216 | return 0; | 191 | return 0; |
192 | |||
193 | cpumask_set_cpu(cpu, per_cpu(cpus_in_cluster, cpu)); | ||
194 | cpuhp_setup_state(CPUHP_X2APIC_PREPARE, "X2APIC_PREPARE", | ||
195 | x2apic_prepare_cpu, x2apic_dead_cpu); | ||
196 | return 1; | ||
217 | } | 197 | } |
218 | 198 | ||
219 | static const struct cpumask *x2apic_cluster_target_cpus(void) | 199 | static const struct cpumask *x2apic_cluster_target_cpus(void) |
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index ace5ad0fc3ec..78170827a776 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h | |||
@@ -17,6 +17,7 @@ enum cpuhp_state { | |||
17 | CPUHP_WORKQUEUE_PREP, | 17 | CPUHP_WORKQUEUE_PREP, |
18 | CPUHP_HRTIMERS_PREPARE, | 18 | CPUHP_HRTIMERS_PREPARE, |
19 | CPUHP_PROFILE_PREPARE, | 19 | CPUHP_PROFILE_PREPARE, |
20 | CPUHP_X2APIC_PREPARE, | ||
20 | CPUHP_TIMERS_DEAD, | 21 | CPUHP_TIMERS_DEAD, |
21 | CPUHP_NOTIFY_PREPARE, | 22 | CPUHP_NOTIFY_PREPARE, |
22 | CPUHP_BRINGUP_CPU, | 23 | CPUHP_BRINGUP_CPU, |