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