[Intel-gfx] [CI] Revert "x86/irq: Simplify hotplug vector accounting"
Chris Wilson
chris at chris-wilson.co.uk
Tue Nov 28 10:25:33 UTC 2017
This reverts commit 2cffad7bad83157f89332872015f4305d2ac09ac.
Lost interrupts upon resume, characterised by
<0>[ 1806.220332] do_IRQ: 4.33 No irq handler for vecto
---
arch/x86/include/asm/apic.h | 1 -
arch/x86/include/asm/irq.h | 4 ++
arch/x86/kernel/apic/vector.c | 32 +-------------
arch/x86/kernel/irq.c | 99 +++++++++++++++++++++++++++++++++++++++++++
arch/x86/kernel/smpboot.c | 2 +-
5 files changed, 105 insertions(+), 33 deletions(-)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index a9e57f08bfa6..7a8651921ed5 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -386,7 +386,6 @@ extern struct apic *__apicdrivers[], *__apicdrivers_end[];
*/
#ifdef CONFIG_SMP
extern int wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip);
-extern int lapic_can_unplug_cpu(void);
#endif
#ifdef CONFIG_X86_LOCAL_APIC
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index 2395bb794c7b..d8632f8fa17d 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -26,7 +26,11 @@ extern void irq_ctx_init(int cpu);
struct irq_desc;
+#ifdef CONFIG_HOTPLUG_CPU
+#include <linux/cpumask.h>
+extern int check_irq_vectors_for_cpu_disable(void);
extern void fixup_irqs(void);
+#endif
#ifdef CONFIG_HAVE_KVM
extern void kvm_set_posted_intr_wakeup_handler(void (*handler)(void));
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index 6a823a25eaff..b9f96e506724 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -970,37 +970,7 @@ void irq_force_complete_move(struct irq_desc *desc)
unlock:
raw_spin_unlock(&vector_lock);
}
-
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * Note, this is not accurate accounting, but at least good enough to
- * prevent that the actual interrupt move will run out of vectors.
- */
-int lapic_can_unplug_cpu(void)
-{
- unsigned int rsvd, avl, tomove, cpu = smp_processor_id();
- int ret = 0;
-
- raw_spin_lock(&vector_lock);
- tomove = irq_matrix_allocated(vector_matrix);
- avl = irq_matrix_available(vector_matrix, true);
- if (avl < tomove) {
- pr_warn("CPU %u has %u vectors, %u available. Cannot disable CPU\n",
- cpu, tomove, avl);
- ret = -ENOSPC;
- goto out;
- }
- rsvd = irq_matrix_reserved(vector_matrix);
- if (avl < rsvd) {
- pr_warn("Reserved vectors %u > available %u. IRQ request may fail\n",
- rsvd, avl);
- }
-out:
- raw_spin_unlock(&vector_lock);
- return ret;
-}
-#endif /* HOTPLUG_CPU */
-#endif /* SMP */
+#endif
static void __init print_APIC_field(int base)
{
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index 49cfd9fe7589..188990c3a514 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -333,6 +333,105 @@ __visible void smp_kvm_posted_intr_nested_ipi(struct pt_regs *regs)
#ifdef CONFIG_HOTPLUG_CPU
+
+/* These two declarations are only used in check_irq_vectors_for_cpu_disable()
+ * below, which is protected by stop_machine(). Putting them on the stack
+ * results in a stack frame overflow. Dynamically allocating could result in a
+ * failure so declare these two cpumasks as global.
+ */
+static struct cpumask affinity_new, online_new;
+
+/*
+ * This cpu is going to be removed and its vectors migrated to the remaining
+ * online cpus. Check to see if there are enough vectors in the remaining cpus.
+ * This function is protected by stop_machine().
+ */
+int check_irq_vectors_for_cpu_disable(void)
+{
+ unsigned int this_cpu, vector, this_count, count;
+ struct irq_desc *desc;
+ struct irq_data *data;
+ int cpu;
+
+ this_cpu = smp_processor_id();
+ cpumask_copy(&online_new, cpu_online_mask);
+ cpumask_clear_cpu(this_cpu, &online_new);
+
+ this_count = 0;
+ for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
+ desc = __this_cpu_read(vector_irq[vector]);
+ if (IS_ERR_OR_NULL(desc))
+ continue;
+ /*
+ * Protect against concurrent action removal, affinity
+ * changes etc.
+ */
+ raw_spin_lock(&desc->lock);
+ data = irq_desc_get_irq_data(desc);
+ cpumask_copy(&affinity_new,
+ irq_data_get_affinity_mask(data));
+ cpumask_clear_cpu(this_cpu, &affinity_new);
+
+ /* Do not count inactive or per-cpu irqs. */
+ if (!irq_desc_has_action(desc) || irqd_is_per_cpu(data)) {
+ raw_spin_unlock(&desc->lock);
+ continue;
+ }
+
+ raw_spin_unlock(&desc->lock);
+ /*
+ * A single irq may be mapped to multiple cpu's
+ * vector_irq[] (for example IOAPIC cluster mode). In
+ * this case we have two possibilities:
+ *
+ * 1) the resulting affinity mask is empty; that is
+ * this the down'd cpu is the last cpu in the irq's
+ * affinity mask, or
+ *
+ * 2) the resulting affinity mask is no longer a
+ * subset of the online cpus but the affinity mask is
+ * not zero; that is the down'd cpu is the last online
+ * cpu in a user set affinity mask.
+ */
+ if (cpumask_empty(&affinity_new) ||
+ !cpumask_subset(&affinity_new, &online_new))
+ this_count++;
+ }
+ /* No need to check any further. */
+ if (!this_count)
+ return 0;
+
+ count = 0;
+ for_each_online_cpu(cpu) {
+ if (cpu == this_cpu)
+ continue;
+ /*
+ * We scan from FIRST_EXTERNAL_VECTOR to first system
+ * vector. If the vector is marked in the used vectors
+ * bitmap or an irq is assigned to it, we don't count
+ * it as available.
+ *
+ * As this is an inaccurate snapshot anyway, we can do
+ * this w/o holding vector_lock.
+ */
+ for (vector = FIRST_EXTERNAL_VECTOR;
+ vector < FIRST_SYSTEM_VECTOR; vector++) {
+ if (!test_bit(vector, system_vectors) &&
+ IS_ERR_OR_NULL(per_cpu(vector_irq, cpu)[vector])) {
+ if (++count == this_count)
+ return 0;
+ }
+ }
+ }
+
+ if (count < this_count) {
+ pr_warn("CPU %d disable failed: CPU has %u vectors assigned and there are only %u available.\n",
+ this_cpu, this_count, count);
+ return -ERANGE;
+ }
+ return 0;
+}
+
/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
void fixup_irqs(void)
{
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 3d01df7d7cf6..bdcfc0964b1f 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1478,7 +1478,7 @@ int native_cpu_disable(void)
{
int ret;
- ret = lapic_can_unplug_cpu();
+ ret = check_irq_vectors_for_cpu_disable();
if (ret)
return ret;
--
2.15.0
More information about the Intel-gfx
mailing list