aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic
diff options
context:
space:
mode:
authorPrarit Bhargava <prarit@redhat.com>2014-01-05 11:10:52 -0500
committerIngo Molnar <mingo@kernel.org>2014-01-12 07:13:02 -0500
commit9345005f4eed805308193658d12e4e7e9c261e74 (patch)
tree8dce273d90c66709baaef7ce91fc8710de78de2f /arch/x86/kernel/apic
parent228fdc083b017eaf90e578fa86fb1ecfd5ffae87 (diff)
x86/irq: Fix do_IRQ() interrupt warning for cpu hotplug retriggered irqs
During heavy CPU-hotplug operations the following spurious kernel warnings can trigger: do_IRQ: No ... irq handler for vector (irq -1) [ See: https://bugzilla.kernel.org/show_bug.cgi?id=64831 ] When downing a cpu it is possible that there are unhandled irqs left in the APIC IRR register. The following code path shows how the problem can occur: 1. CPU 5 is to go down. 2. cpu_disable() on CPU 5 executes with interrupt flag cleared by local_irq_save() via stop_machine(). 3. IRQ 12 asserts on CPU 5, setting IRR but not ISR because interrupt flag is cleared (CPU unabled to handle the irq) 4. IRQs are migrated off of CPU 5, and the vectors' irqs are set to -1. 5. stop_machine() finishes cpu_disable() 6. cpu_die() for CPU 5 executes in normal context. 7. CPU 5 attempts to handle IRQ 12 because the IRR is set for IRQ 12. The code attempts to find the vector's IRQ and cannot because it has been set to -1. 8. do_IRQ() warning displays warning about CPU 5 IRQ 12. I added a debug printk to output which CPU & vector was retriggered and discovered that that we are getting bogus events. I see a 100% correlation between this debug printk in fixup_irqs() and the do_IRQ() warning. This patchset resolves this by adding definitions for VECTOR_UNDEFINED(-1) and VECTOR_RETRIGGERED(-2) and modifying the code to use them. Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=64831 Signed-off-by: Prarit Bhargava <prarit@redhat.com> Reviewed-by: Rui Wang <rui.y.wang@intel.com> Cc: Michel Lespinasse <walken@google.com> Cc: Seiji Aguchi <seiji.aguchi@hds.com> Cc: Yang Zhang <yang.z.zhang@Intel.com> Cc: Paul Gortmaker <paul.gortmaker@windriver.com> Cc: janet.morgan@Intel.com Cc: tony.luck@Intel.com Cc: ruiv.wang@gmail.com Link: http://lkml.kernel.org/r/1388938252-16627-1-git-send-email-prarit@redhat.com [ Cleaned up the code a bit. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch/x86/kernel/apic')
-rw-r--r--arch/x86/kernel/apic/io_apic.c18
1 files changed, 9 insertions, 9 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index e63a5bd2a78f..6df0b660753b 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1142,9 +1142,10 @@ next:
1142 if (test_bit(vector, used_vectors)) 1142 if (test_bit(vector, used_vectors))
1143 goto next; 1143 goto next;
1144 1144
1145 for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask) 1145 for_each_cpu_and(new_cpu, tmp_mask, cpu_online_mask) {
1146 if (per_cpu(vector_irq, new_cpu)[vector] != -1) 1146 if (per_cpu(vector_irq, new_cpu)[vector] > VECTOR_UNDEFINED)
1147 goto next; 1147 goto next;
1148 }
1148 /* Found one! */ 1149 /* Found one! */
1149 current_vector = vector; 1150 current_vector = vector;
1150 current_offset = offset; 1151 current_offset = offset;
@@ -1183,7 +1184,7 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg)
1183 1184
1184 vector = cfg->vector; 1185 vector = cfg->vector;
1185 for_each_cpu_and(cpu, cfg->domain, cpu_online_mask) 1186 for_each_cpu_and(cpu, cfg->domain, cpu_online_mask)
1186 per_cpu(vector_irq, cpu)[vector] = -1; 1187 per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED;
1187 1188
1188 cfg->vector = 0; 1189 cfg->vector = 0;
1189 cpumask_clear(cfg->domain); 1190 cpumask_clear(cfg->domain);
@@ -1191,11 +1192,10 @@ static void __clear_irq_vector(int irq, struct irq_cfg *cfg)
1191 if (likely(!cfg->move_in_progress)) 1192 if (likely(!cfg->move_in_progress))
1192 return; 1193 return;
1193 for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) { 1194 for_each_cpu_and(cpu, cfg->old_domain, cpu_online_mask) {
1194 for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; 1195 for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
1195 vector++) {
1196 if (per_cpu(vector_irq, cpu)[vector] != irq) 1196 if (per_cpu(vector_irq, cpu)[vector] != irq)
1197 continue; 1197 continue;
1198 per_cpu(vector_irq, cpu)[vector] = -1; 1198 per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED;
1199 break; 1199 break;
1200 } 1200 }
1201 } 1201 }
@@ -1228,12 +1228,12 @@ void __setup_vector_irq(int cpu)
1228 /* Mark the free vectors */ 1228 /* Mark the free vectors */
1229 for (vector = 0; vector < NR_VECTORS; ++vector) { 1229 for (vector = 0; vector < NR_VECTORS; ++vector) {
1230 irq = per_cpu(vector_irq, cpu)[vector]; 1230 irq = per_cpu(vector_irq, cpu)[vector];
1231 if (irq < 0) 1231 if (irq <= VECTOR_UNDEFINED)
1232 continue; 1232 continue;
1233 1233
1234 cfg = irq_cfg(irq); 1234 cfg = irq_cfg(irq);
1235 if (!cpumask_test_cpu(cpu, cfg->domain)) 1235 if (!cpumask_test_cpu(cpu, cfg->domain))
1236 per_cpu(vector_irq, cpu)[vector] = -1; 1236 per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED;
1237 } 1237 }
1238 raw_spin_unlock(&vector_lock); 1238 raw_spin_unlock(&vector_lock);
1239} 1239}
@@ -2208,7 +2208,7 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
2208 struct irq_cfg *cfg; 2208 struct irq_cfg *cfg;
2209 irq = __this_cpu_read(vector_irq[vector]); 2209 irq = __this_cpu_read(vector_irq[vector]);
2210 2210
2211 if (irq == -1) 2211 if (irq <= VECTOR_UNDEFINED)
2212 continue; 2212 continue;
2213 2213
2214 desc = irq_to_desc(irq); 2214 desc = irq_to_desc(irq);