aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/irq.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c
index b10a5e1da06c..8a82728d47c1 100644
--- a/arch/x86/kernel/irq.c
+++ b/arch/x86/kernel/irq.c
@@ -281,7 +281,7 @@ EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
281/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */ 281/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
282void fixup_irqs(void) 282void fixup_irqs(void)
283{ 283{
284 unsigned int irq; 284 unsigned int irq, vector;
285 static int warned; 285 static int warned;
286 struct irq_desc *desc; 286 struct irq_desc *desc;
287 287
@@ -336,9 +336,33 @@ void fixup_irqs(void)
336 printk("Cannot set affinity for irq %i\n", irq); 336 printk("Cannot set affinity for irq %i\n", irq);
337 } 337 }
338 338
339 /* That doesn't seem sufficient. Give it 1ms. */ 339 /*
340 local_irq_enable(); 340 * We can remove mdelay() and then send spuriuous interrupts to
341 * new cpu targets for all the irqs that were handled previously by
342 * this cpu. While it works, I have seen spurious interrupt messages
343 * (nothing wrong but still...).
344 *
345 * So for now, retain mdelay(1) and check the IRR and then send those
346 * interrupts to new targets as this cpu is already offlined...
347 */
341 mdelay(1); 348 mdelay(1);
342 local_irq_disable(); 349
350 for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
351 unsigned int irr;
352
353 if (__get_cpu_var(vector_irq)[vector] < 0)
354 continue;
355
356 irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
357 if (irr & (1 << (vector % 32))) {
358 irq = __get_cpu_var(vector_irq)[vector];
359
360 desc = irq_to_desc(irq);
361 spin_lock(&desc->lock);
362 if (desc->chip->retrigger)
363 desc->chip->retrigger(irq);
364 spin_unlock(&desc->lock);
365 }
366 }
343} 367}
344#endif 368#endif