aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86_64/kernel/io_apic.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 96e02d845716..3b8f9c68ad3c 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -172,12 +172,34 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
172 return eu.entry; 172 return eu.entry;
173} 173}
174 174
175/*
176 * When we write a new IO APIC routing entry, we need to write the high
177 * word first! If the mask bit in the low word is clear, we will enable
178 * the interrupt, and we need to make sure the entry is fully populated
179 * before that happens.
180 */
175static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) 181static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
176{ 182{
177 unsigned long flags; 183 unsigned long flags;
178 union entry_union eu; 184 union entry_union eu;
179 eu.entry = e; 185 eu.entry = e;
180 spin_lock_irqsave(&ioapic_lock, flags); 186 spin_lock_irqsave(&ioapic_lock, flags);
187 io_apic_write(apic, 0x11 + 2*pin, eu.w2);
188 io_apic_write(apic, 0x10 + 2*pin, eu.w1);
189 spin_unlock_irqrestore(&ioapic_lock, flags);
190}
191
192/*
193 * When we mask an IO APIC routing entry, we need to write the low
194 * word first, in order to set the mask bit before we change the
195 * high bits!
196 */
197static void ioapic_mask_entry(int apic, int pin)
198{
199 unsigned long flags;
200 union entry_union eu = { .entry.mask = 1 };
201
202 spin_lock_irqsave(&ioapic_lock, flags);
181 io_apic_write(apic, 0x10 + 2*pin, eu.w1); 203 io_apic_write(apic, 0x10 + 2*pin, eu.w1);
182 io_apic_write(apic, 0x11 + 2*pin, eu.w2); 204 io_apic_write(apic, 0x11 + 2*pin, eu.w2);
183 spin_unlock_irqrestore(&ioapic_lock, flags); 205 spin_unlock_irqrestore(&ioapic_lock, flags);
@@ -302,9 +324,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
302 /* 324 /*
303 * Disable it in the IO-APIC irq-routing table: 325 * Disable it in the IO-APIC irq-routing table:
304 */ 326 */
305 memset(&entry, 0, sizeof(entry)); 327 ioapic_mask_entry(apic, pin);
306 entry.mask = 1;
307 ioapic_write_entry(apic, pin, entry);
308} 328}
309 329
310static void clear_IO_APIC (void) 330static void clear_IO_APIC (void)