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: iommu@lists.linux-foundation.org
Cc: linuxppc-...@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

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to