aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/irq.c')
-rw-r--r--arch/x86/kernel/irq.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 884d875c1434..dbb60878b744 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -266,6 +266,76 @@ __visible void smp_trace_x86_platform_ipi(struct pt_regs *regs)
266EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); 266EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
267 267
268#ifdef CONFIG_HOTPLUG_CPU 268#ifdef CONFIG_HOTPLUG_CPU
269/*
270 * This cpu is going to be removed and its vectors migrated to the remaining
271 * online cpus. Check to see if there are enough vectors in the remaining cpus.
272 * This function is protected by stop_machine().
273 */
274int check_irq_vectors_for_cpu_disable(void)
275{
276 int irq, cpu;
277 unsigned int this_cpu, vector, this_count, count;
278 struct irq_desc *desc;
279 struct irq_data *data;
280 struct cpumask affinity_new, online_new;
281
282 this_cpu = smp_processor_id();
283 cpumask_copy(&online_new, cpu_online_mask);
284 cpu_clear(this_cpu, online_new);
285
286 this_count = 0;
287 for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
288 irq = __this_cpu_read(vector_irq[vector]);
289 if (irq >= 0) {
290 desc = irq_to_desc(irq);
291 data = irq_desc_get_irq_data(desc);
292 cpumask_copy(&affinity_new, data->affinity);
293 cpu_clear(this_cpu, affinity_new);
294
295 /* Do not count inactive or per-cpu irqs. */
296 if (!irq_has_action(irq) || irqd_is_per_cpu(data))
297 continue;
298
299 /*
300 * A single irq may be mapped to multiple
301 * cpu's vector_irq[] (for example IOAPIC cluster
302 * mode). In this case we have two
303 * possibilities:
304 *
305 * 1) the resulting affinity mask is empty; that is
306 * this the down'd cpu is the last cpu in the irq's
307 * affinity mask, or
308 *
309 * 2) the resulting affinity mask is no longer
310 * a subset of the online cpus but the affinity
311 * mask is not zero; that is the down'd cpu is the
312 * last online cpu in a user set affinity mask.
313 */
314 if (cpumask_empty(&affinity_new) ||
315 !cpumask_subset(&affinity_new, &online_new))
316 this_count++;
317 }
318 }
319
320 count = 0;
321 for_each_online_cpu(cpu) {
322 if (cpu == this_cpu)
323 continue;
324 for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS;
325 vector++) {
326 if (per_cpu(vector_irq, cpu)[vector] < 0)
327 count++;
328 }
329 }
330
331 if (count < this_count) {
332 pr_warn("CPU %d disable failed: CPU has %u vectors assigned and there are only %u available.\n",
333 this_cpu, this_count, count);
334 return -ERANGE;
335 }
336 return 0;
337}
338
269/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ 339/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
270void fixup_irqs(void) 340void fixup_irqs(void)
271{ 341{