aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/io_apic.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index eb10bd5da64e..507983c513c3 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -147,12 +147,34 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
147 return eu.entry; 147 return eu.entry;
148} 148}
149 149
150/*
151 * When we write a new IO APIC routing entry, we need to write the high
152 * word first! If the mask bit in the low word is clear, we will enable
153 * the interrupt, and we need to make sure the entry is fully populated
154 * before that happens.
155 */
150static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) 156static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
151{ 157{
152 unsigned long flags; 158 unsigned long flags;
153 union entry_union eu; 159 union entry_union eu;
154 eu.entry = e; 160 eu.entry = e;
155 spin_lock_irqsave(&ioapic_lock, flags); 161 spin_lock_irqsave(&ioapic_lock, flags);
162 io_apic_write(apic, 0x11 + 2*pin, eu.w2);
163 io_apic_write(apic, 0x10 + 2*pin, eu.w1);
164 spin_unlock_irqrestore(&ioapic_lock, flags);
165}
166
167/*
168 * When we mask an IO APIC routing entry, we need to write the low
169 * word first, in order to set the mask bit before we change the
170 * high bits!
171 */
172static void ioapic_mask_entry(int apic, int pin)
173{
174 unsigned long flags;
175 union entry_union eu = { .entry.mask = 1 };
176
177 spin_lock_irqsave(&ioapic_lock, flags);
156 io_apic_write(apic, 0x10 + 2*pin, eu.w1); 178 io_apic_write(apic, 0x10 + 2*pin, eu.w1);
157 io_apic_write(apic, 0x11 + 2*pin, eu.w2); 179 io_apic_write(apic, 0x11 + 2*pin, eu.w2);
158 spin_unlock_irqrestore(&ioapic_lock, flags); 180 spin_unlock_irqrestore(&ioapic_lock, flags);
@@ -274,9 +296,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
274 /* 296 /*
275 * Disable it in the IO-APIC irq-routing table: 297 * Disable it in the IO-APIC irq-routing table:
276 */ 298 */
277 memset(&entry, 0, sizeof(entry)); 299 ioapic_mask_entry(apic, pin);
278 entry.mask = 1;
279 ioapic_write_entry(apic, pin, entry);
280} 300}
281 301
282static void clear_IO_APIC (void) 302static void clear_IO_APIC (void)