diff options
-rw-r--r-- | arch/i386/kernel/io_apic.c | 5 | ||||
-rw-r--r-- | arch/i386/kernel/mpparse.c | 12 | ||||
-rw-r--r-- | arch/x86_64/kernel/io_apic.c | 5 | ||||
-rw-r--r-- | arch/x86_64/kernel/mpparse.c | 12 | ||||
-rw-r--r-- | include/asm-i386/io_apic.h | 1 | ||||
-rw-r--r-- | include/asm-x86_64/io_apic.h | 1 |
6 files changed, 34 insertions, 2 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index f8f132aa5472..d70f2ade5cde 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c | |||
@@ -2238,6 +2238,8 @@ static inline void unlock_ExtINT_logic(void) | |||
2238 | spin_unlock_irqrestore(&ioapic_lock, flags); | 2238 | spin_unlock_irqrestore(&ioapic_lock, flags); |
2239 | } | 2239 | } |
2240 | 2240 | ||
2241 | int timer_uses_ioapic_pin_0; | ||
2242 | |||
2241 | /* | 2243 | /* |
2242 | * This code may look a bit paranoid, but it's supposed to cooperate with | 2244 | * This code may look a bit paranoid, but it's supposed to cooperate with |
2243 | * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ | 2245 | * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ |
@@ -2274,6 +2276,9 @@ static inline void check_timer(void) | |||
2274 | pin2 = ioapic_i8259.pin; | 2276 | pin2 = ioapic_i8259.pin; |
2275 | apic2 = ioapic_i8259.apic; | 2277 | apic2 = ioapic_i8259.apic; |
2276 | 2278 | ||
2279 | if (pin1 == 0) | ||
2280 | timer_uses_ioapic_pin_0 = 1; | ||
2281 | |||
2277 | printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", | 2282 | printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", |
2278 | vector, apic1, pin1, apic2, pin2); | 2283 | vector, apic1, pin1, apic2, pin2); |
2279 | 2284 | ||
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 34d21e21e012..6b1392d33ed5 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c | |||
@@ -1130,7 +1130,17 @@ int mp_register_gsi (u32 gsi, int triggering, int polarity) | |||
1130 | */ | 1130 | */ |
1131 | int irq = gsi; | 1131 | int irq = gsi; |
1132 | if (gsi < MAX_GSI_NUM) { | 1132 | if (gsi < MAX_GSI_NUM) { |
1133 | if (gsi > 15) | 1133 | /* |
1134 | * Retain the VIA chipset work-around (gsi > 15), but | ||
1135 | * avoid a problem where the 8254 timer (IRQ0) is setup | ||
1136 | * via an override (so it's not on pin 0 of the ioapic), | ||
1137 | * and at the same time, the pin 0 interrupt is a PCI | ||
1138 | * type. The gsi > 15 test could cause these two pins | ||
1139 | * to be shared as IRQ0, and they are not shareable. | ||
1140 | * So test for this condition, and if necessary, avoid | ||
1141 | * the pin collision. | ||
1142 | */ | ||
1143 | if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0)) | ||
1134 | gsi = pci_irq++; | 1144 | gsi = pci_irq++; |
1135 | /* | 1145 | /* |
1136 | * Don't assign IRQ used by ACPI SCI | 1146 | * Don't assign IRQ used by ACPI SCI |
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 77b4c608cca0..0de3ea938830 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c | |||
@@ -1777,6 +1777,8 @@ static inline void unlock_ExtINT_logic(void) | |||
1777 | spin_unlock_irqrestore(&ioapic_lock, flags); | 1777 | spin_unlock_irqrestore(&ioapic_lock, flags); |
1778 | } | 1778 | } |
1779 | 1779 | ||
1780 | int timer_uses_ioapic_pin_0; | ||
1781 | |||
1780 | /* | 1782 | /* |
1781 | * This code may look a bit paranoid, but it's supposed to cooperate with | 1783 | * This code may look a bit paranoid, but it's supposed to cooperate with |
1782 | * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ | 1784 | * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ |
@@ -1814,6 +1816,9 @@ static inline void check_timer(void) | |||
1814 | pin2 = ioapic_i8259.pin; | 1816 | pin2 = ioapic_i8259.pin; |
1815 | apic2 = ioapic_i8259.apic; | 1817 | apic2 = ioapic_i8259.apic; |
1816 | 1818 | ||
1819 | if (pin1 == 0) | ||
1820 | timer_uses_ioapic_pin_0 = 1; | ||
1821 | |||
1817 | apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", | 1822 | apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", |
1818 | vector, apic1, pin1, apic2, pin2); | 1823 | vector, apic1, pin1, apic2, pin2); |
1819 | 1824 | ||
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c index b17cf3eba359..083da7e606b1 100644 --- a/arch/x86_64/kernel/mpparse.c +++ b/arch/x86_64/kernel/mpparse.c | |||
@@ -968,7 +968,17 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity) | |||
968 | */ | 968 | */ |
969 | int irq = gsi; | 969 | int irq = gsi; |
970 | if (gsi < MAX_GSI_NUM) { | 970 | if (gsi < MAX_GSI_NUM) { |
971 | if (gsi > 15) | 971 | /* |
972 | * Retain the VIA chipset work-around (gsi > 15), but | ||
973 | * avoid a problem where the 8254 timer (IRQ0) is setup | ||
974 | * via an override (so it's not on pin 0 of the ioapic), | ||
975 | * and at the same time, the pin 0 interrupt is a PCI | ||
976 | * type. The gsi > 15 test could cause these two pins | ||
977 | * to be shared as IRQ0, and they are not shareable. | ||
978 | * So test for this condition, and if necessary, avoid | ||
979 | * the pin collision. | ||
980 | */ | ||
981 | if (gsi > 15 || (gsi == 0 && !timer_uses_ioapic_pin_0)) | ||
972 | gsi = pci_irq++; | 982 | gsi = pci_irq++; |
973 | /* | 983 | /* |
974 | * Don't assign IRQ used by ACPI SCI | 984 | * Don't assign IRQ used by ACPI SCI |
diff --git a/include/asm-i386/io_apic.h b/include/asm-i386/io_apic.h index 51c4e5fe6062..d92e253f7f6f 100644 --- a/include/asm-i386/io_apic.h +++ b/include/asm-i386/io_apic.h | |||
@@ -200,6 +200,7 @@ extern int io_apic_get_unique_id (int ioapic, int apic_id); | |||
200 | extern int io_apic_get_version (int ioapic); | 200 | extern int io_apic_get_version (int ioapic); |
201 | extern int io_apic_get_redir_entries (int ioapic); | 201 | extern int io_apic_get_redir_entries (int ioapic); |
202 | extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low); | 202 | extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int active_high_low); |
203 | extern int timer_uses_ioapic_pin_0; | ||
203 | #endif /* CONFIG_ACPI */ | 204 | #endif /* CONFIG_ACPI */ |
204 | 205 | ||
205 | extern int (*ioapic_renumber_irq)(int ioapic, int irq); | 206 | extern int (*ioapic_renumber_irq)(int ioapic, int irq); |
diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h index ee1bc69aec9c..52484e82c641 100644 --- a/include/asm-x86_64/io_apic.h +++ b/include/asm-x86_64/io_apic.h | |||
@@ -205,6 +205,7 @@ extern int skip_ioapic_setup; | |||
205 | extern int io_apic_get_version (int ioapic); | 205 | extern int io_apic_get_version (int ioapic); |
206 | extern int io_apic_get_redir_entries (int ioapic); | 206 | extern int io_apic_get_redir_entries (int ioapic); |
207 | extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int, int); | 207 | extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int, int); |
208 | extern int timer_uses_ioapic_pin_0; | ||
208 | #endif | 209 | #endif |
209 | 210 | ||
210 | extern int sis_apic_bug; /* dummy */ | 211 | extern int sis_apic_bug; /* dummy */ |