aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2016-07-13 13:17:00 -0400
committerIngo Molnar <mingo@kernel.org>2016-07-15 04:41:42 -0400
commit6b2c28471de550308784560206c3365e5179d42f (patch)
tree999635046bf5f350a5cfb281ec4251bf149cfc19
parente722d8daafb974b9ad1bbaf42f384a5ea5929f5f (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.c80
-rw-r--r--include/linux/cpuhotplug.h1
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 */
158static int 158int x2apic_prepare_cpu(unsigned int cpu)
159update_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
193static struct notifier_block x2apic_cpu_notifier = { 171int x2apic_dead_cpu(unsigned int this_cpu)
194 .notifier_call = update_clusterinfo,
195};
196
197static 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
211static int x2apic_cluster_probe(void) 186static 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
219static const struct cpumask *x2apic_cluster_target_cpus(void) 199static 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,