diff options
| -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) |
