]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
x86/irq: Handle spurious interrupt after shutdown gracefully
authorThomas Gleixner <tglx@linutronix.de>
Fri, 28 Jun 2019 11:11:53 +0000 (13:11 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 21 Jul 2019 07:00:40 +0000 (09:00 +0200)
commit b7107a67f0d125459fe41f86e8079afd1a5e0b15 upstream.

Since the rework of the vector management, warnings about spurious
interrupts have been reported. Robert provided some more information and
did an initial analysis. The following situation leads to these warnings:

   CPU 0                  CPU 1               IO_APIC

                                              interrupt is raised
                                              sent to CPU1
  Unable to handle
  immediately
  (interrupts off,
   deep idle delay)
   mask()
   ...
   free()
     shutdown()
     synchronize_irq()
     clear_vector()
                          do_IRQ()
                            -> vector is clear

Before the rework the vector entries of legacy interrupts were statically
assigned and occupied precious vector space while most of them were
unused. Due to that the above situation was handled silently because the
vector was handled and the core handler of the assigned interrupt
descriptor noticed that it is shut down and returned.

While this has been usually observed with legacy interrupts, this situation
is not limited to them. Any other interrupt source, e.g. MSI, can cause the
same issue.

After adding proper synchronization for level triggered interrupts, this
can only happen for edge triggered interrupts where the IO-APIC obviously
cannot provide information about interrupts in flight.

While the spurious warning is actually harmless in this case it worries
users and driver developers.

Handle it gracefully by marking the vector entry as VECTOR_SHUTDOWN instead
of VECTOR_UNUSED when the vector is freed up.

If that above late handling happens the spurious detector will not complain
and switch the entry to VECTOR_UNUSED. Any subsequent spurious interrupt on
that line will trigger the spurious warning as before.

Fixes: 464d12309e1b ("x86/vector: Switch IOAPIC to global reservation mode")
Reported-by: Robert Hodaszi <Robert.Hodaszi@digi.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>-
Tested-by: Robert Hodaszi <Robert.Hodaszi@digi.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Link: https://lkml.kernel.org/r/20190628111440.459647741@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/x86/include/asm/hw_irq.h
arch/x86/kernel/apic/vector.c
arch/x86/kernel/irq.c

index 32e666e1231e77f128252b2f9354f708081cafdb..626e1ac6516ee63628765d83187011afff887d49 100644 (file)
@@ -151,7 +151,8 @@ extern char irq_entries_start[];
 #endif
 
 #define VECTOR_UNUSED          NULL
-#define VECTOR_RETRIGGERED     ((void *)~0UL)
+#define VECTOR_SHUTDOWN                ((void *)~0UL)
+#define VECTOR_RETRIGGERED     ((void *)~1UL)
 
 typedef struct irq_desc* vector_irq_t[NR_VECTORS];
 DECLARE_PER_CPU(vector_irq_t, vector_irq);
index e7cb78aed644b28a40c5bf9a8e7f178bc383f524..fdacb864c3dd4f8f3756ebf715678136876b0ebc 100644 (file)
@@ -340,7 +340,7 @@ static void clear_irq_vector(struct irq_data *irqd)
        trace_vector_clear(irqd->irq, vector, apicd->cpu, apicd->prev_vector,
                           apicd->prev_cpu);
 
-       per_cpu(vector_irq, apicd->cpu)[vector] = VECTOR_UNUSED;
+       per_cpu(vector_irq, apicd->cpu)[vector] = VECTOR_SHUTDOWN;
        irq_matrix_free(vector_matrix, apicd->cpu, vector, managed);
        apicd->vector = 0;
 
@@ -349,7 +349,7 @@ static void clear_irq_vector(struct irq_data *irqd)
        if (!vector)
                return;
 
-       per_cpu(vector_irq, apicd->prev_cpu)[vector] = VECTOR_UNUSED;
+       per_cpu(vector_irq, apicd->prev_cpu)[vector] = VECTOR_SHUTDOWN;
        irq_matrix_free(vector_matrix, apicd->prev_cpu, vector, managed);
        apicd->prev_vector = 0;
        apicd->move_in_progress = 0;
index 9b68b5b00ac91cf7755c9767d8e78c1a558dacb8..cc496eb7a8d21880cf80141ba69f5d4c759a3ba4 100644 (file)
@@ -247,7 +247,7 @@ __visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
        if (!handle_irq(desc, regs)) {
                ack_APIC_irq();
 
-               if (desc != VECTOR_RETRIGGERED) {
+               if (desc != VECTOR_RETRIGGERED && desc != VECTOR_SHUTDOWN) {
                        pr_emerg_ratelimited("%s: %d.%d No irq handler for vector\n",
                                             __func__, smp_processor_id(),
                                             vector);