Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

[PATCH] x86_64: avoid IRQ0 ioapic pin collision

The patch addresses a problem with ACPI SCI interrupt entry, which gets
re-used, and the IRQ is assigned to another unrelated device. The patch
corrects the code such that SCI IRQ is skipped and duplicate entry is
avoided. Second issue came up with VIA chipset, the problem was caused by
original patch assigning IRQs starting 16 and up. The VIA chipset uses
4-bit IRQ register for internal interrupt routing, and therefore cannot
handle IRQ numbers assigned to its devices. The patch corrects this
problem by allowing PCI IRQs below 16.

Cc: len.brown@intel.com

Signed-off by: Natalie Protasevich <Natalie.Protasevich@unisys.com>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Kimball Murray and committed by
Linus Torvalds
e0c1e9bf abfd3057

+34 -2
+5
arch/i386/kernel/io_apic.c
··· 2238 2238 spin_unlock_irqrestore(&ioapic_lock, flags); 2239 2239 } 2240 2240 2241 + int timer_uses_ioapic_pin_0; 2242 + 2241 2243 /* 2242 2244 * This code may look a bit paranoid, but it's supposed to cooperate with 2243 2245 * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ ··· 2275 2273 apic1 = find_isa_irq_apic(0, mp_INT); 2276 2274 pin2 = ioapic_i8259.pin; 2277 2275 apic2 = ioapic_i8259.apic; 2276 + 2277 + if (pin1 == 0) 2278 + timer_uses_ioapic_pin_0 = 1; 2278 2279 2279 2280 printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", 2280 2281 vector, apic1, pin1, apic2, pin2);
+11 -1
arch/i386/kernel/mpparse.c
··· 1130 1130 */ 1131 1131 int irq = gsi; 1132 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 1144 gsi = pci_irq++; 1135 1145 /* 1136 1146 * Don't assign IRQ used by ACPI SCI
+5
arch/x86_64/kernel/io_apic.c
··· 1777 1777 spin_unlock_irqrestore(&ioapic_lock, flags); 1778 1778 } 1779 1779 1780 + int timer_uses_ioapic_pin_0; 1781 + 1780 1782 /* 1781 1783 * This code may look a bit paranoid, but it's supposed to cooperate with 1782 1784 * a wide range of boards and BIOS bugs. Fortunately only the timer IRQ ··· 1815 1813 apic1 = find_isa_irq_apic(0, mp_INT); 1816 1814 pin2 = ioapic_i8259.pin; 1817 1815 apic2 = ioapic_i8259.apic; 1816 + 1817 + if (pin1 == 0) 1818 + timer_uses_ioapic_pin_0 = 1; 1818 1819 1819 1820 apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", 1820 1821 vector, apic1, pin1, apic2, pin2);
+11 -1
arch/x86_64/kernel/mpparse.c
··· 968 968 */ 969 969 int irq = gsi; 970 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 982 gsi = pci_irq++; 973 983 /* 974 984 * Don't assign IRQ used by ACPI SCI
+1
include/asm-i386/io_apic.h
··· 200 200 extern int io_apic_get_version (int ioapic); 201 201 extern int io_apic_get_redir_entries (int ioapic); 202 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 204 #endif /* CONFIG_ACPI */ 204 205 205 206 extern int (*ioapic_renumber_irq)(int ioapic, int irq);
+1
include/asm-x86_64/io_apic.h
··· 205 205 extern int io_apic_get_version (int ioapic); 206 206 extern int io_apic_get_redir_entries (int ioapic); 207 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 209 #endif 209 210 210 211 extern int sis_apic_bug; /* dummy */