diff options
Diffstat (limited to 'arch/x86/kernel/io_apic_32.c')
-rw-r--r-- | arch/x86/kernel/io_apic_32.c | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/arch/x86/kernel/io_apic_32.c b/arch/x86/kernel/io_apic_32.c index 63a2f64c765b..a69a59d19e18 100644 --- a/arch/x86/kernel/io_apic_32.c +++ b/arch/x86/kernel/io_apic_32.c | |||
@@ -2122,6 +2122,7 @@ static inline void __init unlock_ExtINT_logic(void) | |||
2122 | static inline void __init check_timer(void) | 2122 | static inline void __init check_timer(void) |
2123 | { | 2123 | { |
2124 | int apic1, pin1, apic2, pin2; | 2124 | int apic1, pin1, apic2, pin2; |
2125 | int no_pin1 = 0; | ||
2125 | int vector; | 2126 | int vector; |
2126 | unsigned int ver; | 2127 | unsigned int ver; |
2127 | unsigned long flags; | 2128 | unsigned long flags; |
@@ -2159,10 +2160,30 @@ static inline void __init check_timer(void) | |||
2159 | printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", | 2160 | printk(KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n", |
2160 | vector, apic1, pin1, apic2, pin2); | 2161 | vector, apic1, pin1, apic2, pin2); |
2161 | 2162 | ||
2163 | /* | ||
2164 | * Some BIOS writers are clueless and report the ExtINTA | ||
2165 | * I/O APIC input from the cascaded 8259A as the timer | ||
2166 | * interrupt input. So just in case, if only one pin | ||
2167 | * was found above, try it both directly and through the | ||
2168 | * 8259A. | ||
2169 | */ | ||
2170 | if (pin1 == -1) { | ||
2171 | pin1 = pin2; | ||
2172 | apic1 = apic2; | ||
2173 | no_pin1 = 1; | ||
2174 | } else if (pin2 == -1) { | ||
2175 | pin2 = pin1; | ||
2176 | apic2 = apic1; | ||
2177 | } | ||
2178 | |||
2162 | if (pin1 != -1) { | 2179 | if (pin1 != -1) { |
2163 | /* | 2180 | /* |
2164 | * Ok, does IRQ0 through the IOAPIC work? | 2181 | * Ok, does IRQ0 through the IOAPIC work? |
2165 | */ | 2182 | */ |
2183 | if (no_pin1) { | ||
2184 | add_pin_to_irq(0, apic1, pin1); | ||
2185 | setup_timer_IRQ0_pin(apic1, pin1, vector); | ||
2186 | } | ||
2166 | unmask_IO_APIC_irq(0); | 2187 | unmask_IO_APIC_irq(0); |
2167 | if (timer_irq_works()) { | 2188 | if (timer_irq_works()) { |
2168 | if (nmi_watchdog == NMI_IO_APIC) { | 2189 | if (nmi_watchdog == NMI_IO_APIC) { |
@@ -2174,26 +2195,23 @@ static inline void __init check_timer(void) | |||
2174 | goto out; | 2195 | goto out; |
2175 | } | 2196 | } |
2176 | clear_IO_APIC_pin(apic1, pin1); | 2197 | clear_IO_APIC_pin(apic1, pin1); |
2177 | printk(KERN_ERR "..MP-BIOS bug: 8254 timer not connected to " | 2198 | if (!no_pin1) |
2178 | "IO-APIC\n"); | 2199 | printk(KERN_ERR "..MP-BIOS bug: " |
2179 | } | 2200 | "8254 timer not connected to IO-APIC\n"); |
2180 | 2201 | ||
2181 | printk(KERN_INFO "...trying to set up timer (IRQ0) through the 8259A ... "); | 2202 | printk(KERN_INFO "...trying to set up timer (IRQ0) " |
2182 | if (pin2 != -1) { | 2203 | "through the 8259A ... "); |
2183 | printk("\n..... (found pin %d) ...", pin2); | 2204 | printk("\n..... (found pin %d) ...", pin2); |
2184 | /* | 2205 | /* |
2185 | * legacy devices should be connected to IO APIC #0 | 2206 | * legacy devices should be connected to IO APIC #0 |
2186 | */ | 2207 | */ |
2208 | replace_pin_at_irq(0, apic1, pin1, apic2, pin2); | ||
2187 | setup_timer_IRQ0_pin(apic2, pin2, vector); | 2209 | setup_timer_IRQ0_pin(apic2, pin2, vector); |
2188 | unmask_IO_APIC_irq(0); | 2210 | unmask_IO_APIC_irq(0); |
2189 | enable_8259A_irq(0); | 2211 | enable_8259A_irq(0); |
2190 | if (timer_irq_works()) { | 2212 | if (timer_irq_works()) { |
2191 | printk("works.\n"); | 2213 | printk("works.\n"); |
2192 | timer_through_8259 = 1; | 2214 | timer_through_8259 = 1; |
2193 | if (pin1 != -1) | ||
2194 | replace_pin_at_irq(0, apic1, pin1, apic2, pin2); | ||
2195 | else | ||
2196 | add_pin_to_irq(0, apic2, pin2); | ||
2197 | if (nmi_watchdog == NMI_IO_APIC) { | 2215 | if (nmi_watchdog == NMI_IO_APIC) { |
2198 | disable_8259A_irq(0); | 2216 | disable_8259A_irq(0); |
2199 | setup_nmi(); | 2217 | setup_nmi(); |
@@ -2206,8 +2224,8 @@ static inline void __init check_timer(void) | |||
2206 | */ | 2224 | */ |
2207 | disable_8259A_irq(0); | 2225 | disable_8259A_irq(0); |
2208 | clear_IO_APIC_pin(apic2, pin2); | 2226 | clear_IO_APIC_pin(apic2, pin2); |
2227 | printk(" failed.\n"); | ||
2209 | } | 2228 | } |
2210 | printk(" failed.\n"); | ||
2211 | 2229 | ||
2212 | if (nmi_watchdog == NMI_IO_APIC) { | 2230 | if (nmi_watchdog == NMI_IO_APIC) { |
2213 | printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); | 2231 | printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n"); |