aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/io_apic_64.c
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2008-06-19 20:35:07 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-08 03:13:24 -0400
commit7f0dbbc08d80df7ea15d8da4f0d78255891c8812 (patch)
tree14b876a80d9fc32574485d82ce456adfc6ddc252 /arch/x86/kernel/io_apic_64.c
parentcd08d0754ecb0cb9293c8476cb33ded1d23d0d8f (diff)
x86: fix IO APIC breakage on HP nx6325, v2
> That helped a lot, the system seems to work normally now. > > Here's the relevant snippet from dmesg: > > [ 0.108006] ..TIMER: vector=0x30 apic1=0 pin1=2 apic2=-1 pin2=-1 > [ 0.108006] ..MP-BIOS bug: 8254 timer not connected to IO-APIC > [ 0.108006] ...trying to set up timer (IRQ0) through the 8259A ... <3> > [ 0.108006] ..... (found apic 0 pin 2) ...<3> failed. > [ 0.108006] ...trying to set up timer as Virtual Wire IRQ...<3> works. > > and the whole thing is at: http://www.sisk.pl/kernel/debug/20080618/dmesg-2.log Hmm, that only proved the 8259A is indeed wired to the pin #2 of the I/O APIC. > I, personally, don't have any and AMD only has SB600 documentation on its > web page (it's still marked as "AMD confidential" ;-)). Well, the IC block is most likely the same as that's not rocket science and once done there is no need to fiddle with that. That written, I am afraid there is nothing useful about the IC in the document, except that it's there and consists of an I/O APIC providing 24 inputs and the usual pair of 8259A cores. Thanks for the reference anyway. > There is an interrupt controller in there, but I'm not sure if there's any > 8259A. The northbridge is on the CPU, actually. I will praise the day someone ships an x86 machine without an 8259A core! As expressed in another mail I suspect there may actually be a direct route from the 8254 to INTIN0 in the southbridge -- this is what other bootstrap logs seen in the Internet suggest. This would mean this particular BIOS is buggy (is it the latest version?) and provides an incorrect IRQ override in its ACPI tables, for example because the responsible block has been blindly copied from a machine using a commoner wiring. This could be moderately easily fixed up with a quirk based on the PCI ID (after checking it again, we actually used to have a quirk for ATI in this area, but the way it was done suggests the issue was not understood well enough). Could you please remove the hack sent yesterday and test the patch provided below? I do hope it builds, but I have no immediate means to check it. Please report the output. The intent is to test INTIN0 directly before testing INTIN2 through the 8259A. Thanks. Aside of that, what I have gathered from your reports (please correct me if I have got it wrong) is that when the through-8259A mode is used, then after a while 8254 timer interrupts stop arriving. What's interesting, the "Virtual Wire IRQ" seems to work for you correctly (that's quite an odd setup where a local APIC input is used in the native mode -- please post /proc/interrupts for confirmation), which in turn implies the master 8259A drives its INT output as we expect. Why would the I/O APIC input have problems then? Hmm... [ mingo@elte.hu: revert the "x86: fix IO APIC breakage on HP nx6325" version. ] Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/io_apic_64.c')
-rw-r--r--arch/x86/kernel/io_apic_64.c28
1 files changed, 26 insertions, 2 deletions
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index f06f5b4fb35f..40aa041b2987 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -360,6 +360,26 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
360 entry->pin = pin; 360 entry->pin = pin;
361} 361}
362 362
363/*
364 * Reroute an IRQ to a different pin.
365 */
366static void __init replace_pin_at_irq(unsigned int irq,
367 int oldapic, int oldpin,
368 int newapic, int newpin)
369{
370 struct irq_pin_list *entry = irq_2_pin + irq;
371
372 while (1) {
373 if (entry->apic == oldapic && entry->pin == oldpin) {
374 entry->apic = newapic;
375 entry->pin = newpin;
376 }
377 if (!entry->next)
378 break;
379 entry = irq_2_pin + entry->next;
380 }
381}
382
363 383
364#define DO_ACTION(name,R,ACTION, FINAL) \ 384#define DO_ACTION(name,R,ACTION, FINAL) \
365 \ 385 \
@@ -1680,6 +1700,11 @@ static inline void __init check_timer(void)
1680 apic2 = apic1; 1700 apic2 = apic1;
1681 } 1701 }
1682 1702
1703 replace_pin_at_irq(0, 0, 0, apic1, pin1);
1704 apic1 = 0;
1705 pin1 = 0;
1706 setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
1707
1683 if (pin1 != -1) { 1708 if (pin1 != -1) {
1684 /* 1709 /*
1685 * Ok, does IRQ0 through the IOAPIC work? 1710 * Ok, does IRQ0 through the IOAPIC work?
@@ -1712,10 +1737,9 @@ static inline void __init check_timer(void)
1712 /* 1737 /*
1713 * legacy devices should be connected to IO APIC #0 1738 * legacy devices should be connected to IO APIC #0
1714 */ 1739 */
1715 /* replace_pin_at_irq(0, apic1, pin1, apic2, pin2); */ 1740 replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
1716 setup_timer_IRQ0_pin(apic2, pin2, cfg->vector); 1741 setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
1717 unmask_IO_APIC_irq(0); 1742 unmask_IO_APIC_irq(0);
1718 clear_IO_APIC_pin(apic2, pin2);
1719 enable_8259A_irq(0); 1743 enable_8259A_irq(0);
1720 if (timer_irq_works()) { 1744 if (timer_irq_works()) {
1721 apic_printk(APIC_VERBOSE," works.\n"); 1745 apic_printk(APIC_VERBOSE," works.\n");