the attached ioapic-2.4.5-A1 patch includes a number of important IO-APIC
related fixes (against 2.4.5-ac3):

 - correctly handle bridged devices that are not listed in the mptable
   directly. This fixes eg. dual-port eepro100 devices on Compaq boxes
   with such PCI layout:

    -+-[0d]---0b.0
     +-[05]-+-02.0
     |      \-0b.0
     \-[00]-+-02.0
            +-03.0-[01]--+-04.0    <=== eth0
            |            \-05.0    <=== eth1
            +-0b.0
            +-0c.0
            +-0d.0
            +-0e.0
            +-0f.0
            +-14.0
            +-14.1
            +-19.0
            +-1a.0
            \-1b.0

   without the patch the eepro100 devices get misdetected as XT-PIC IRQs
   and their interrupts are stuck.

 - the srcbus entry in the mptable does not have to be translated into
   a PCI-bus value.

 - add more APIC versions to the whitelist

 - initialize mp_bus_id_to_pci_bus[] correctly, so that we can detect
   nonlisted/bridged PCI busses more accurately.

the patch should only affect systems that were not working properly
before, but it might break broken-mptable systems - we'll see.

        Ingo
--- linux/arch/i386/kernel/io_apic.c.orig       Tue May 29 12:13:15 2001
+++ linux/arch/i386/kernel/io_apic.c    Tue May 29 12:19:55 2001
@@ -256,10 +256,16 @@
  */
 static int pin_2_irq(int idx, int apic, int pin);
 
-int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin)
+int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
 {
        int apic, i, best_guess = -1;
 
+       Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
+               bus, slot, pin);
+       if (mp_bus_id_to_pci_bus[bus] == -1) {
+               printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+               return -1;
+       }
        for (i = 0; i < mp_irq_entries; i++) {
                int lbus = mp_irqs[i].mpc_srcbus;
 
@@ -270,14 +276,14 @@
 
                if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
                    !mp_irqs[i].mpc_irqtype &&
-                   (bus == mp_bus_id_to_pci_bus[mp_irqs[i].mpc_srcbus]) &&
+                   (bus == lbus) &&
                    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
                        int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
 
                        if (!(apic || IO_APIC_IRQ(irq)))
                                continue;
 
-                       if (pci_pin == (mp_irqs[i].mpc_srcbusirq & 3))
+                       if (pin == (mp_irqs[i].mpc_srcbusirq & 3))
                                return irq;
                        /*
                         * Use the first all-but-pin matching entry as a
@@ -738,9 +744,11 @@
        printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
        printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", 
reg_01.entries);
        if (    (reg_01.entries != 0x0f) && /* older (Neptune) boards */
+               (reg_01.entries != 0x11) &&
                (reg_01.entries != 0x17) && /* typical ISA+PCI boards */
                (reg_01.entries != 0x1b) && /* Compaq Proliant boards */
                (reg_01.entries != 0x1f) && /* dual Xeon boards */
+               (reg_01.entries != 0x20) &&
                (reg_01.entries != 0x22) && /* bigger Xeon boards */
                (reg_01.entries != 0x2E) &&
                (reg_01.entries != 0x3F)
--- linux/arch/i386/kernel/mpparse.c.orig       Tue May 29 12:13:15 2001
+++ linux/arch/i386/kernel/mpparse.c    Tue May 29 12:13:46 2001
@@ -36,7 +36,7 @@
  */
 int apic_version [MAX_APICS];
 int mp_bus_id_to_type [MAX_MP_BUSSES];
-int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
+int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
 int mp_current_pci_id;
 
 /* I/O APIC entries */
--- linux/arch/i386/kernel/pci-irq.c.orig       Tue May 29 12:13:15 2001
+++ linux/arch/i386/kernel/pci-irq.c    Tue May 29 12:13:46 2001
@@ -660,10 +660,12 @@
                        if (pin) {
                                pin--;          /* interrupt pins are numbered 
starting from 1 */
                                irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, 
PCI_SLOT(dev->devfn), pin);
-/*
- * Will be removed completely if things work out well with fuzzy parsing
- */
-#if 0
+       /*
+        * Busses behind bridges are typically not listed in the MP-table.
+        * In this case we have to look up the IRQ based on the parent bus,
+        * parent slot, and pin number. The SMP code detects such bridged
+        * busses itself so we should get into this branch reliably.
+        */
                                if (irq < 0 && dev->bus->parent) { /* go back to the 
bridge */
                                        struct pci_dev * bridge = dev->bus->self;
 
@@ -674,7 +676,6 @@
                                                printk(KERN_WARNING "PCI: using 
PPB(B%d,I%d,P%d) to get irq %d\n", 
                                                        bridge->bus->number, 
PCI_SLOT(bridge->devfn), pin, irq);
                                }
-#endif
                                if (irq >= 0) {
                                        printk(KERN_INFO "PCI->APIC IRQ transform: 
(B%d,I%d,P%d) -> %d\n",
                                                dev->bus->number, 
PCI_SLOT(dev->devfn), pin, irq);

Reply via email to