--- 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 *)®_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);