diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/kernel/apic.c | 38 | ||||
-rw-r--r-- | arch/i386/kernel/io_apic.c | 33 |
2 files changed, 69 insertions, 2 deletions
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index cf45bed96d08..93df90bbb87e 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c | |||
@@ -211,7 +211,7 @@ void __init connect_bsp_APIC(void) | |||
211 | enable_apic_mode(); | 211 | enable_apic_mode(); |
212 | } | 212 | } |
213 | 213 | ||
214 | void disconnect_bsp_APIC(void) | 214 | void disconnect_bsp_APIC(int virt_wire_setup) |
215 | { | 215 | { |
216 | if (pic_mode) { | 216 | if (pic_mode) { |
217 | /* | 217 | /* |
@@ -225,6 +225,42 @@ void disconnect_bsp_APIC(void) | |||
225 | outb(0x70, 0x22); | 225 | outb(0x70, 0x22); |
226 | outb(0x00, 0x23); | 226 | outb(0x00, 0x23); |
227 | } | 227 | } |
228 | else { | ||
229 | /* Go back to Virtual Wire compatibility mode */ | ||
230 | unsigned long value; | ||
231 | |||
232 | /* For the spurious interrupt use vector F, and enable it */ | ||
233 | value = apic_read(APIC_SPIV); | ||
234 | value &= ~APIC_VECTOR_MASK; | ||
235 | value |= APIC_SPIV_APIC_ENABLED; | ||
236 | value |= 0xf; | ||
237 | apic_write_around(APIC_SPIV, value); | ||
238 | |||
239 | if (!virt_wire_setup) { | ||
240 | /* For LVT0 make it edge triggered, active high, external and enabled */ | ||
241 | value = apic_read(APIC_LVT0); | ||
242 | value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING | | ||
243 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
244 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED ); | ||
245 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
246 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT); | ||
247 | apic_write_around(APIC_LVT0, value); | ||
248 | } | ||
249 | else { | ||
250 | /* Disable LVT0 */ | ||
251 | apic_write_around(APIC_LVT0, APIC_LVT_MASKED); | ||
252 | } | ||
253 | |||
254 | /* For LVT1 make it edge triggered, active high, nmi and enabled */ | ||
255 | value = apic_read(APIC_LVT1); | ||
256 | value &= ~( | ||
257 | APIC_MODE_MASK | APIC_SEND_PENDING | | ||
258 | APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR | | ||
259 | APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED); | ||
260 | value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING; | ||
261 | value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI); | ||
262 | apic_write_around(APIC_LVT1, value); | ||
263 | } | ||
228 | } | 264 | } |
229 | 265 | ||
230 | void disable_local_APIC(void) | 266 | void disable_local_APIC(void) |
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 3c2b3bdfc807..fc81c8cddd22 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
@@ -1636,12 +1636,43 @@ static void __init enable_IO_APIC(void) | |||
1636 | */ | 1636 | */ |
1637 | void disable_IO_APIC(void) | 1637 | void disable_IO_APIC(void) |
1638 | { | 1638 | { |
1639 | int pin; | ||
1639 | /* | 1640 | /* |
1640 | * Clear the IO-APIC before rebooting: | 1641 | * Clear the IO-APIC before rebooting: |
1641 | */ | 1642 | */ |
1642 | clear_IO_APIC(); | 1643 | clear_IO_APIC(); |
1643 | 1644 | ||
1644 | disconnect_bsp_APIC(); | 1645 | /* |
1646 | * If the i82559 is routed through an IOAPIC | ||
1647 | * Put that IOAPIC in virtual wire mode | ||
1648 | * so legacy interrups can be delivered. | ||
1649 | */ | ||
1650 | pin = find_isa_irq_pin(0, mp_ExtINT); | ||
1651 | if (pin != -1) { | ||
1652 | struct IO_APIC_route_entry entry; | ||
1653 | unsigned long flags; | ||
1654 | |||
1655 | memset(&entry, 0, sizeof(entry)); | ||
1656 | entry.mask = 0; /* Enabled */ | ||
1657 | entry.trigger = 0; /* Edge */ | ||
1658 | entry.irr = 0; | ||
1659 | entry.polarity = 0; /* High */ | ||
1660 | entry.delivery_status = 0; | ||
1661 | entry.dest_mode = 0; /* Physical */ | ||
1662 | entry.delivery_mode = 7; /* ExtInt */ | ||
1663 | entry.vector = 0; | ||
1664 | entry.dest.physical.physical_dest = 0; | ||
1665 | |||
1666 | |||
1667 | /* | ||
1668 | * Add it to the IO-APIC irq-routing table: | ||
1669 | */ | ||
1670 | spin_lock_irqsave(&ioapic_lock, flags); | ||
1671 | io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1)); | ||
1672 | io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0)); | ||
1673 | spin_unlock_irqrestore(&ioapic_lock, flags); | ||
1674 | } | ||
1675 | disconnect_bsp_APIC(pin != -1); | ||
1645 | } | 1676 | } |
1646 | 1677 | ||
1647 | /* | 1678 | /* |