[Patch] io-apic-patch-2.1.85-A

MOLNAR Ingo (mingo@chiara.csoma.elte.hu)
Thu, 5 Feb 1998 00:17:48 +0100 (CET)


This 2.1.85 based patch fixes an already existing workaround. There exists
a nasty problem with certain older SMP boards, the mptable claims to have
IRQ 0 (timer) connected, but in reality the timer IRQ is only connected to
the 8259A-style PIC ...

the 'old' solution was to use IRQ0 always as a 8259A interrupt.
Unfortunately, some newer boards like the Dell PowerEdge 6100 seem to
disable timer IRQs towards the 8259A when the IO-APIC is activated ...
resulting in a hang during bootup.

the workaround is to 'probe' for timer IRQs as bootup. Now the default
operation for timer IRQs is IO-APIC, but if for some reason there are no
timer IRQs arriving, we switch back to 8259A type timer interrupts.

the patch also contains some other minor fixes.

This Dell PowerEdge was the last failing board, and now it seems 100% of
all boards tested work with the new autodetection code. Unless i've missed
some failure reports, i'd say we should make IO-APIC+autodetect the
default bootup mode? [even with this patch it's still necessary to use
pirq=0 to get autodetection running]

there seem to be problems with aha1542 hardware and the new SMP IRQ
handling code [SCSI hw related lockups], plus there was one report of
'jumpy' PS/2 mouse, and one report of 'lost PS/2 mouse/keyboard'. Is
anyone else experiencing other types of problems with the new IO-APIC
code?

-- mingo

--- linux/arch/i386/kernel/.io_apic.c.orig Tue Feb 10 09:14:54 1998
+++ linux/arch/i386/kernel/io_apic.c Tue Feb 10 09:41:07 1998
@@ -191,10 +191,12 @@
{
int i;

- for (i=mp_irq_entries-1; i>=0; i--) {
- if (mp_irqs[i].mpc_dstirq == pin)
+ for (i=0; i<mp_irq_entries; i++)
+ if ( (mp_irqs[i].mpc_irqtype == 0x00) &&
+ (mp_irqs[i].mpc_dstirq == pin))
+
return i;
- }
+
return -1;
}

@@ -397,7 +399,7 @@
for (i=0; i<mp_irq_entries; i++) {
int lbus = mp_irqs[i].mpc_srcbus;

- if (IO_APIC_IRQ(i) &&
+ if (IO_APIC_IRQ(mp_irqs[i].mpc_dstirq) &&
(mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
!mp_irqs[i].mpc_irqtype &&
(bus == mp_irqs[i].mpc_srcbus) &&
@@ -409,6 +411,30 @@
return -1;
}

+/*
+ * There is a nasty bug in some older SMP boards, their mptable lies
+ * about the timer IRQ. We do the following to work around the situation:
+ *
+ * - timer IRQ defaults to IO-APIC IRQ
+ * - if this function detects that timer IRQs are defunct, then we fall
+ * back to ISA timer IRQs
+ */
+static int timer_irq_works (void)
+{
+ unsigned int t1=jiffies;
+ unsigned long flags;
+
+ save_flags(flags);
+ sti();
+
+ udelay(100*1000);
+
+ if (jiffies-t1>1)
+ return 1;
+
+ return 0;
+}
+
void print_IO_APIC (void)
{
int i;
@@ -579,7 +605,7 @@
pirqs_enabled)
{
printk("ENABLING IO-APIC IRQs\n");
- io_apic_irqs = ~((1<<0)|(1<<2)|(1<<13));
+ io_apic_irqs = ~((1<<2)|(1<<13));
} else {
if (ioapic_blacklisted())
printk(" blacklisted board, DISABLING IO-APIC IRQs\n");
@@ -592,6 +618,18 @@

init_IO_APIC_traps();
setup_IO_APIC_irqs ();
+
+ if (!timer_irq_works ()) {
+ io_apic_irqs &= ~(1<<0);
+ /*
+ * Repeat setup with this one
+ */
+ init_IO_APIC_traps();
+ setup_IO_APIC_irqs ();
+ if (!timer_irq_works ())
+ panic("IO-APIC + timer doesnt work!");
+ printk("i8452 timer not connected to IO-APIC\n");
+ }

printk("nr of MP irq sources: %d.\n", mp_irq_entries);
printk("nr of IOAPIC registers: %d.\n", nr_ioapic_registers);