diff options
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r-- | arch/i386/kernel/io_apic.c | 26 |
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 | */ | ||
150 | static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) | 156 | static 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 | */ | ||
172 | static 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 | ||
282 | static void clear_IO_APIC (void) | 302 | static void clear_IO_APIC (void) |