aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/io_apic.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-12-06 20:14:07 -0500
committerAndi Kleen <andi@basil.nowhere.org>2006-12-06 20:14:07 -0500
commitd15512f442ef1ea60f6195b0444fb27b3cf8d0e6 (patch)
tree71764761d19509d5ffcea0b6ef9965a2f489691c /arch/i386/kernel/io_apic.c
parente6536c1262c56d302e749ab1b44fdb0b9786327d (diff)
[PATCH] i386: Fix race in IO-APIC routing entry setup.
Interrupt could happen between setting the IO-APIC entry and setting its interrupt data. Pointed out by Linus. Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/i386/kernel/io_apic.c')
-rw-r--r--arch/i386/kernel/io_apic.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 3b7a63e0ed1..e33b7a84529 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -153,14 +153,20 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
153 * the interrupt, and we need to make sure the entry is fully populated 153 * the interrupt, and we need to make sure the entry is fully populated
154 * before that happens. 154 * before that happens.
155 */ 155 */
156static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) 156static void
157__ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
157{ 158{
158 unsigned long flags;
159 union entry_union eu; 159 union entry_union eu;
160 eu.entry = e; 160 eu.entry = e;
161 spin_lock_irqsave(&ioapic_lock, flags);
162 io_apic_write(apic, 0x11 + 2*pin, eu.w2); 161 io_apic_write(apic, 0x11 + 2*pin, eu.w2);
163 io_apic_write(apic, 0x10 + 2*pin, eu.w1); 162 io_apic_write(apic, 0x10 + 2*pin, eu.w1);
163}
164
165static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
166{
167 unsigned long flags;
168 spin_lock_irqsave(&ioapic_lock, flags);
169 __ioapic_write_entry(apic, pin, e);
164 spin_unlock_irqrestore(&ioapic_lock, flags); 170 spin_unlock_irqrestore(&ioapic_lock, flags);
165} 171}
166 172
@@ -1360,8 +1366,8 @@ static void __init setup_IO_APIC_irqs(void)
1360 if (!apic && (irq < 16)) 1366 if (!apic && (irq < 16))
1361 disable_8259A_irq(irq); 1367 disable_8259A_irq(irq);
1362 } 1368 }
1363 ioapic_write_entry(apic, pin, entry);
1364 spin_lock_irqsave(&ioapic_lock, flags); 1369 spin_lock_irqsave(&ioapic_lock, flags);
1370 __ioapic_write_entry(apic, pin, entry);
1365 set_native_irq_info(irq, TARGET_CPUS); 1371 set_native_irq_info(irq, TARGET_CPUS);
1366 spin_unlock_irqrestore(&ioapic_lock, flags); 1372 spin_unlock_irqrestore(&ioapic_lock, flags);
1367 } 1373 }
@@ -2856,8 +2862,8 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
2856 if (!ioapic && (irq < 16)) 2862 if (!ioapic && (irq < 16))
2857 disable_8259A_irq(irq); 2863 disable_8259A_irq(irq);
2858 2864
2859 ioapic_write_entry(ioapic, pin, entry);
2860 spin_lock_irqsave(&ioapic_lock, flags); 2865 spin_lock_irqsave(&ioapic_lock, flags);
2866 __ioapic_write_entry(ioapic, pin, entry);
2861 set_native_irq_info(irq, TARGET_CPUS); 2867 set_native_irq_info(irq, TARGET_CPUS);
2862 spin_unlock_irqrestore(&ioapic_lock, flags); 2868 spin_unlock_irqrestore(&ioapic_lock, flags);
2863 2869