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

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


this patch is based on vanilla 2.1.85. (those who have applied
io-apic-patch-2.1.85-A, should unapply it first)

thanks to the debugging work of Harald Evensen, this patch fixes an
mptable parsing error, which makes even more systems boot with pirq=0. The
patch also includes the timer IRQ workaround.

systems with multiple PCI buses should now work correctly with the
PCI->APIC IRQ translation method too.

-- mingo

--- linux/arch/i386/kernel/.smp.c.orig Wed Feb 11 08:41:25 1998
+++ linux/arch/i386/kernel/smp.c Wed Feb 11 08:44:01 1998
@@ -148,6 +148,8 @@
int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
extern int mp_irq_entries;
extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
+int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
+int mp_current_pci_id = 0;

/* #define SMP_DEBUG */

@@ -336,9 +338,13 @@
mp_bus_id_to_type[m->mpc_busid] =
MP_BUS_ISA;
else
- if (strncmp(m->mpc_bustype,"PCI",3) == 0)
+ if (strncmp(m->mpc_bustype,"PCI",3) == 0) {
mp_bus_id_to_type[m->mpc_busid] =
MP_BUS_PCI;
+ mp_bus_id_to_pci_bus[m->mpc_busid] =
+ mp_current_pci_id;
+ mp_current_pci_id++;
+ }
mpt+=sizeof(*m);
count+=sizeof(*m);
break;
--- linux/arch/i386/kernel/.irq.h.orig Wed Feb 11 08:44:05 1998
+++ linux/arch/i386/kernel/irq.h Wed Feb 11 08:44:25 1998
@@ -34,6 +34,7 @@
MP_BUS_PCI
};
extern int mp_bus_id_to_type [MAX_MP_BUSSES];
+extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
extern char ioapic_OEM_ID [16];
extern char ioapic_Product_ID [16];

--- linux/arch/i386/kernel/.io_apic.c.orig Tue Feb 10 09:14:54 1998
+++ linux/arch/i386/kernel/io_apic.c Wed Feb 11 08:45:01 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,11 +399,11 @@
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) &&
- (slot == (mp_irqs[i].mpc_srcbusirq >> 2)) &&
+ (bus == mp_bus_id_to_pci_bus[mp_irqs[i].mpc_srcbus]) &&
+ (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f)) &&
(pci_pin == (mp_irqs[i].mpc_srcbusirq & 3)))

return mp_irqs[i].mpc_dstirq;
@@ -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("i8254 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);

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu