Commit 192b3516 authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] x86_64: drop old APIC workaround

Suggested by Ingo Molnar.

Drop APIC level workaround for old IO-APICs on x86-64 because it is a
significant part of interrupt handling time.  x86-64 only runs on modern
chipsets that probably don't have this bug.
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 9229204b
...@@ -41,10 +41,6 @@ ...@@ -41,10 +41,6 @@
int sis_apic_bug; /* not actually supported, dummy for compile */ int sis_apic_bug; /* not actually supported, dummy for compile */
#undef APIC_LOCKUP_DEBUG
#define APIC_LOCKUP_DEBUG
static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED; static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED;
/* /*
...@@ -131,10 +127,6 @@ DO_ACTION( __mask, 0, |= 0x00010000, io_apic_sync(entry->apic) ) ...@@ -131,10 +127,6 @@ DO_ACTION( __mask, 0, |= 0x00010000, io_apic_sync(entry->apic) )
/* mask = 1 */ /* mask = 1 */
DO_ACTION( __unmask, 0, &= 0xfffeffff, ) DO_ACTION( __unmask, 0, &= 0xfffeffff, )
/* mask = 0 */ /* mask = 0 */
DO_ACTION( __mask_and_edge, 0, = (reg & 0xffff7fff) | 0x00010000, )
/* mask = 1, trigger = 0 */
DO_ACTION( __unmask_and_level, 0, = (reg & 0xfffeffff) | 0x00008000, )
/* mask = 0, trigger = 1 */
static void mask_IO_APIC_irq (unsigned int irq) static void mask_IO_APIC_irq (unsigned int irq)
{ {
...@@ -1343,61 +1335,7 @@ static unsigned int startup_level_ioapic_irq (unsigned int irq) ...@@ -1343,61 +1335,7 @@ static unsigned int startup_level_ioapic_irq (unsigned int irq)
static void end_level_ioapic_irq (unsigned int irq) static void end_level_ioapic_irq (unsigned int irq)
{ {
unsigned long v;
int i;
/*
* It appears there is an erratum which affects at least version 0x11
* of I/O APIC (that's the 82093AA and cores integrated into various
* chipsets). Under certain conditions a level-triggered interrupt is
* erroneously delivered as edge-triggered one but the respective IRR
* bit gets set nevertheless. As a result the I/O unit expects an EOI
* message but it will never arrive and further interrupts are blocked
* from the source. The exact reason is so far unknown, but the
* phenomenon was observed when two consecutive interrupt requests
* from a given source get delivered to the same CPU and the source is
* temporarily disabled in between.
*
* A workaround is to simulate an EOI message manually. We achieve it
* by setting the trigger mode to edge and then to level when the edge
* trigger mode gets detected in the TMR of a local APIC for a
* level-triggered interrupt. We mask the source for the time of the
* operation to prevent an edge-triggered interrupt escaping meanwhile.
* The idea is from Manfred Spraul. --macro
*/
i = IO_APIC_VECTOR(irq);
v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
ack_APIC_irq(); ack_APIC_irq();
if (!(v & (1 << (i & 0x1f)))) {
#ifdef APIC_LOCKUP_DEBUG
struct irq_pin_list *entry;
#endif
#ifdef APIC_MISMATCH_DEBUG
atomic_inc(&irq_mis_count);
#endif
spin_lock(&ioapic_lock);
__mask_and_edge_IO_APIC_irq(irq);
#ifdef APIC_LOCKUP_DEBUG
for (entry = irq_2_pin + irq;;) {
unsigned int reg;
if (entry->pin == -1)
break;
reg = io_apic_read(entry->apic, 0x10 + entry->pin * 2);
if (reg & 0x00004000)
printk(KERN_CRIT "Aieee!!! Remote IRR"
" still set after unlock!\n");
if (!entry->next)
break;
entry = irq_2_pin + entry->next;
}
#endif
__unmask_and_level_IO_APIC_irq(irq);
spin_unlock(&ioapic_lock);
}
} }
static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask) static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment