aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/i8259.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2007-02-23 06:40:58 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-26 13:34:08 -0500
commit610142927b5bc149da92b03c7ab08b8b5f205b74 (patch)
tree600c115072fc5f28c07dddfbe52f0dcf376d8504 /arch/x86_64/kernel/i8259.c
parentbc5e81a1519abc69472bb67deace7bb1ac09d65a (diff)
[PATCH] x86_64 irq: Safely cleanup an irq after moving it.
The problem: After moving an interrupt when is it safe to teardown the data structures for receiving the interrupt at the old location? With a normal pci device it is possible to issue a read to a device to flush all posted writes. This does not work for the oldest ioapics because they are on a 3-wire apic bus which is a completely different data path. For some more modern ioapics when everything is using front side bus delivery you can flush interrupts by simply issuing a read to the ioapic. For other modern ioapics emperical testing has shown that this does not work. So it appears the only reliable way to know the last of the irqs from an ioapic have been received from before the ioapic was reprogrammed is to received the first irq from the ioapic from after it was reprogrammed. Once we know the last irq message has been received from an ioapic into a local apic we then need to know that irq message has been processed through the local apics. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/x86_64/kernel/i8259.c')
-rw-r--r--arch/x86_64/kernel/i8259.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index 45d85630196a..21d95b747437 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -450,6 +450,7 @@ void spurious_interrupt(void);
450void error_interrupt(void); 450void error_interrupt(void);
451void reschedule_interrupt(void); 451void reschedule_interrupt(void);
452void call_function_interrupt(void); 452void call_function_interrupt(void);
453void irq_move_cleanup_interrupt(void);
453void invalidate_interrupt0(void); 454void invalidate_interrupt0(void);
454void invalidate_interrupt1(void); 455void invalidate_interrupt1(void);
455void invalidate_interrupt2(void); 456void invalidate_interrupt2(void);
@@ -537,7 +538,10 @@ void __init init_IRQ(void)
537 538
538 /* IPI for generic function call */ 539 /* IPI for generic function call */
539 set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); 540 set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
540#endif 541
542 /* Low priority IPI to cleanup after moving an irq */
543 set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
544#endif
541 set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); 545 set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
542 set_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt); 546 set_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
543 547