x86-64: write IO APIC irq routing entries in correct order

This is the x86-64 version of f9dadfa71bc594df09044da61d1c72701121d802
that did the same thing on i386.

Since the "mask" bit is in the low word, when we write a new entry, we
need to write the high word first, before we potentially unmask it.

The exception is when we actually want to mask the interrupt, in which
case we want to write the low word first to make sure that the high word
doesn't change while the interrupt routing is still active.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>

+23 -3
+23 -3
arch/x86_64/kernel/io_apic.c
··· 172 return eu.entry; 173 } 174 175 static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) 176 { 177 unsigned long flags; 178 union entry_union eu; 179 eu.entry = e; 180 spin_lock_irqsave(&ioapic_lock, flags); 181 io_apic_write(apic, 0x10 + 2*pin, eu.w1); 182 io_apic_write(apic, 0x11 + 2*pin, eu.w2); ··· 324 /* 325 * Disable it in the IO-APIC irq-routing table: 326 */ 327 - memset(&entry, 0, sizeof(entry)); 328 - entry.mask = 1; 329 - ioapic_write_entry(apic, pin, entry); 330 } 331 332 static void clear_IO_APIC (void)
··· 172 return eu.entry; 173 } 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 + */ 181 static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) 182 { 183 unsigned long flags; 184 union entry_union eu; 185 eu.entry = e; 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 + */ 197 + static 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); 203 io_apic_write(apic, 0x10 + 2*pin, eu.w1); 204 io_apic_write(apic, 0x11 + 2*pin, eu.w2); ··· 302 /* 303 * Disable it in the IO-APIC irq-routing table: 304 */ 305 + ioapic_mask_entry(apic, pin); 306 } 307 308 static void clear_IO_APIC (void)