diff options
-rw-r--r-- | arch/x86_64/kernel/io_apic.c | 26 |
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 | */ | ||
175 | static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) | 181 | static 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 | */ | ||
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); | ||
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 | ||
310 | static void clear_IO_APIC (void) | 330 | static void clear_IO_APIC (void) |