diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 78960a3b0ed0..c0b4468683f9 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -2586,6 +2586,19 @@ static void ack_apic_level(unsigned int irq) | |||
2586 | * level-triggered interrupt. We mask the source for the time of the | 2586 | * level-triggered interrupt. We mask the source for the time of the |
2587 | * operation to prevent an edge-triggered interrupt escaping meanwhile. | 2587 | * operation to prevent an edge-triggered interrupt escaping meanwhile. |
2588 | * The idea is from Manfred Spraul. --macro | 2588 | * The idea is from Manfred Spraul. --macro |
2589 | * | ||
2590 | * Also in the case when cpu goes offline, fixup_irqs() will forward | ||
2591 | * any unhandled interrupt on the offlined cpu to the new cpu | ||
2592 | * destination that is handling the corresponding interrupt. This | ||
2593 | * interrupt forwarding is done via IPI's. Hence, in this case also | ||
2594 | * level-triggered io-apic interrupt will be seen as an edge | ||
2595 | * interrupt in the IRR. And we can't rely on the cpu's EOI | ||
2596 | * to be broadcasted to the IO-APIC's which will clear the remoteIRR | ||
2597 | * corresponding to the level-triggered interrupt. Hence on IO-APIC's | ||
2598 | * supporting EOI register, we do an explicit EOI to clear the | ||
2599 | * remote IRR and on IO-APIC's which don't have an EOI register, | ||
2600 | * we use the above logic (mask+edge followed by unmask+level) from | ||
2601 | * Manfred Spraul to clear the remote IRR. | ||
2589 | */ | 2602 | */ |
2590 | cfg = desc->chip_data; | 2603 | cfg = desc->chip_data; |
2591 | i = cfg->vector; | 2604 | i = cfg->vector; |
@@ -2597,7 +2610,13 @@ static void ack_apic_level(unsigned int irq) | |||
2597 | */ | 2610 | */ |
2598 | ack_APIC_irq(); | 2611 | ack_APIC_irq(); |
2599 | 2612 | ||
2600 | /* Tail end of version 0x11 I/O APIC bug workaround */ | 2613 | /* |
2614 | * Tail end of clearing remote IRR bit (either by delivering the EOI | ||
2615 | * message via io-apic EOI register write or simulating it using | ||
2616 | * mask+edge followed by unnask+level logic) manually when the | ||
2617 | * level triggered interrupt is seen as the edge triggered interrupt | ||
2618 | * at the cpu. | ||
2619 | */ | ||
2601 | if (!(v & (1 << (i & 0x1f)))) { | 2620 | if (!(v & (1 << (i & 0x1f)))) { |
2602 | atomic_inc(&irq_mis_count); | 2621 | atomic_inc(&irq_mis_count); |
2603 | 2622 | ||