Vectors are meaningless when allocating IRQs with NMI as the delivery mode. In such case, skip the reservation of IRQ vectors. Do it in the lowest- level functions where the actual IRQ reservation takes place.
Since NMIs target specific CPUs, keep the functionality to find the best CPU. Cc: Andi Kleen <a...@linux.intel.com> Cc: "Ravi V. Shankar" <ravi.v.shan...@intel.com> Cc: Stephane Eranian <eran...@google.com> Cc: io...@lists.linux-foundation.org Cc: linuxppc-dev@lists.ozlabs.org Cc: x...@kernel.org Reviewed-by: Tony Luck <tony.l...@intel.com> Signed-off-by: Ricardo Neri <ricardo.neri-calde...@linux.intel.com> --- Changes since v5: * Introduced this patch. Changes since v4: * N/A Changes since v3: * N/A Changes since v2: * N/A Changes since v1: * N/A --- arch/x86/kernel/apic/vector.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 838e220e8860..11f881f45cec 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -245,11 +245,20 @@ assign_vector_locked(struct irq_data *irqd, const struct cpumask *dest) if (apicd->move_in_progress || !hlist_unhashed(&apicd->clist)) return -EBUSY; + if (apicd->hw_irq_cfg.delivery_mode == APIC_DELIVERY_MODE_NMI) { + cpu = irq_matrix_find_best_cpu(vector_matrix, dest); + apicd->cpu = cpu; + vector = 0; + goto no_vector; + } + vector = irq_matrix_alloc(vector_matrix, dest, resvd, &cpu); trace_vector_alloc(irqd->irq, vector, resvd, vector); if (vector < 0) return vector; apic_update_vector(irqd, vector, cpu); + +no_vector: apic_update_irq_cfg(irqd, vector, cpu); return 0; @@ -321,12 +330,22 @@ assign_managed_vector(struct irq_data *irqd, const struct cpumask *dest) /* set_affinity might call here for nothing */ if (apicd->vector && cpumask_test_cpu(apicd->cpu, vector_searchmask)) return 0; + + if (apicd->hw_irq_cfg.delivery_mode == APIC_DELIVERY_MODE_NMI) { + cpu = irq_matrix_find_best_cpu_managed(vector_matrix, dest); + apicd->cpu = cpu; + vector = 0; + goto no_vector; + } + vector = irq_matrix_alloc_managed(vector_matrix, vector_searchmask, &cpu); trace_vector_alloc_managed(irqd->irq, vector, vector); if (vector < 0) return vector; apic_update_vector(irqd, vector, cpu); + +no_vector: apic_update_irq_cfg(irqd, vector, cpu); return 0; } @@ -376,6 +395,10 @@ static void x86_vector_deactivate(struct irq_domain *dom, struct irq_data *irqd) if (apicd->has_reserved) return; + /* NMI IRQs do not have associated vectors; nothing to do. */ + if (apicd->hw_irq_cfg.delivery_mode == APIC_DELIVERY_MODE_NMI) + return; + raw_spin_lock_irqsave(&vector_lock, flags); clear_irq_vector(irqd); if (apicd->can_reserve) @@ -472,6 +495,10 @@ static void vector_free_reserved_and_managed(struct irq_data *irqd) trace_vector_teardown(irqd->irq, apicd->is_managed, apicd->has_reserved); + /* NMI IRQs do not have associated vectors; nothing to do. */ + if (apicd->hw_irq_cfg.delivery_mode == APIC_DELIVERY_MODE_NMI) + return; + if (apicd->has_reserved) irq_matrix_remove_reserved(vector_matrix); if (apicd->is_managed) -- 2.17.1