diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index ff1759a1128e..42cdc78427a2 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -2414,6 +2414,7 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) | |||
2414 | me = smp_processor_id(); | 2414 | me = smp_processor_id(); |
2415 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { | 2415 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { |
2416 | unsigned int irq; | 2416 | unsigned int irq; |
2417 | unsigned int irr; | ||
2417 | struct irq_desc *desc; | 2418 | struct irq_desc *desc; |
2418 | struct irq_cfg *cfg; | 2419 | struct irq_cfg *cfg; |
2419 | irq = __get_cpu_var(vector_irq)[vector]; | 2420 | irq = __get_cpu_var(vector_irq)[vector]; |
@@ -2433,6 +2434,18 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void) | |||
2433 | if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) | 2434 | if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) |
2434 | goto unlock; | 2435 | goto unlock; |
2435 | 2436 | ||
2437 | irr = apic_read(APIC_IRR + (vector / 32 * 0x10)); | ||
2438 | /* | ||
2439 | * Check if the vector that needs to be cleanedup is | ||
2440 | * registered at the cpu's IRR. If so, then this is not | ||
2441 | * the best time to clean it up. Lets clean it up in the | ||
2442 | * next attempt by sending another IRQ_MOVE_CLEANUP_VECTOR | ||
2443 | * to myself. | ||
2444 | */ | ||
2445 | if (irr & (1 << (vector % 32))) { | ||
2446 | apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR); | ||
2447 | goto unlock; | ||
2448 | } | ||
2436 | __get_cpu_var(vector_irq)[vector] = -1; | 2449 | __get_cpu_var(vector_irq)[vector] = -1; |
2437 | cfg->move_cleanup_count--; | 2450 | cfg->move_cleanup_count--; |
2438 | unlock: | 2451 | unlock: |