Sven Schnelle (svens@stackframe.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1461
-gerrit
commit f15b66959c5b42857e710cb20130c50003975cfa Author: Sven Schnelle svens@stackframe.org Date: Mon Aug 20 11:19:00 2012 +0200
MPTABLE: check for fixed IRQ entries on all pins
Don't derive the IRQ pin from the function number. Especially onboard chipset devices don't follow that rule. Instead check and add all fixed IRQ entries.
Change-Id: I46c88bad39104c1d9b4154f180f8b3c42df28262 Signed-off-by: Sven Schnelle svens@stackframe.org --- src/arch/x86/boot/mpspec.c | 89 ++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 42 deletions(-)
diff --git a/src/arch/x86/boot/mpspec.c b/src/arch/x86/boot/mpspec.c index 010bca1..1f583fd 100644 --- a/src/arch/x86/boot/mpspec.c +++ b/src/arch/x86/boot/mpspec.c @@ -419,7 +419,7 @@ unsigned long __attribute__((weak)) write_smp_table(unsigned long addr) int isa_bus, pin, parentpin; device_t dev, parent, oldparent; void *tmp, *v; - int isaioapic = -1; + int isaioapic = -1, have_fixed_entries;
v = smp_write_floating_table(addr, 0); mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN); @@ -461,48 +461,53 @@ unsigned long __attribute__((weak)) write_smp_table(unsigned long addr) if (dev->path.type != DEVICE_PATH_PCI || !dev->enabled) continue;
- pin = (dev->path.pci.devfn & 7) % 4; - - if (dev->pci_irq_info[pin].ioapic_dst_id) { - printk(BIOS_DEBUG, "fixed IRQ entry for: %s: INT%c# -> IOAPIC %d PIN %d\n", dev_path(dev), - pin + 'A', - dev->pci_irq_info[pin].ioapic_dst_id, - dev->pci_irq_info[pin].ioapic_irq_pin); - smp_write_intsrc(mc, mp_INT, - dev->pci_irq_info[pin].ioapic_flags, - dev->bus->secondary, - ((dev->path.pci.devfn & 0xf8) >> 1) | pin, - dev->pci_irq_info[pin].ioapic_dst_id, - dev->pci_irq_info[pin].ioapic_irq_pin); - } else { - oldparent = parent = dev; - while((parent = parent->bus->dev)) { - parentpin = (oldparent->path.pci.devfn >> 3) + (oldparent->path.pci.devfn & 7); - parentpin += dev->path.pci.devfn & 7; - parentpin += dev->path.pci.devfn >> 3; - parentpin %= 4; - - if (parent->pci_irq_info[parentpin].ioapic_dst_id) { - printk(BIOS_DEBUG, "automatic IRQ entry for %s: INT%c# -> IOAPIC %d PIN %d\n", - dev_path(dev), pin + 'A', - parent->pci_irq_info[parentpin].ioapic_dst_id, - parent->pci_irq_info[parentpin].ioapic_irq_pin); - smp_write_intsrc(mc, mp_INT, - parent->pci_irq_info[parentpin].ioapic_flags, - dev->bus->secondary, - ((dev->path.pci.devfn & 0xf8) >> 1) | pin, - parent->pci_irq_info[parentpin].ioapic_dst_id, - parent->pci_irq_info[parentpin].ioapic_irq_pin); - - break; - } - - if (parent->path.type == DEVICE_PATH_PCI_DOMAIN) { - printk(BIOS_WARNING, "no IRQ found for %s\n", dev_path(dev)); - break; - } - oldparent = parent; + have_fixed_entries = 0; + for (pin = 0; pin < 4; pin++) { + if (dev->pci_irq_info[pin].ioapic_dst_id) { + printk(BIOS_DEBUG, "fixed IRQ entry for: %s: INT%c# -> IOAPIC %d PIN %d\n", dev_path(dev), + pin + 'A', + dev->pci_irq_info[pin].ioapic_dst_id, + dev->pci_irq_info[pin].ioapic_irq_pin); + smp_write_intsrc(mc, mp_INT, + dev->pci_irq_info[pin].ioapic_flags, + dev->bus->secondary, + ((dev->path.pci.devfn & 0xf8) >> 1) | pin, + dev->pci_irq_info[pin].ioapic_dst_id, + dev->pci_irq_info[pin].ioapic_irq_pin); + have_fixed_entries = 1; + } + } + + if (!have_fixed_entries) { + pin = (dev->path.pci.devfn & 7) % 4; + oldparent = parent = dev; + while((parent = parent->bus->dev)) { + parentpin = (oldparent->path.pci.devfn >> 3) + (oldparent->path.pci.devfn & 7); + parentpin += dev->path.pci.devfn & 7; + parentpin += dev->path.pci.devfn >> 3; + parentpin %= 4; + + if (parent->pci_irq_info[parentpin].ioapic_dst_id) { + printk(BIOS_DEBUG, "automatic IRQ entry for %s: INT%c# -> IOAPIC %d PIN %d\n", + dev_path(dev), pin + 'A', + parent->pci_irq_info[parentpin].ioapic_dst_id, + parent->pci_irq_info[parentpin].ioapic_irq_pin); + smp_write_intsrc(mc, mp_INT, + parent->pci_irq_info[parentpin].ioapic_flags, + dev->bus->secondary, + ((dev->path.pci.devfn & 0xf8) >> 1) | pin, + parent->pci_irq_info[parentpin].ioapic_dst_id, + parent->pci_irq_info[parentpin].ioapic_irq_pin); + + break; } + + if (parent->path.type == DEVICE_PATH_PCI_DOMAIN) { + printk(BIOS_WARNING, "no IRQ found for %s\n", dev_path(dev)); + break; + } + oldparent = parent; + } } }