diff options
author | Sven Schnelle <svens@stackframe.org> | 2012-08-20 11:19:00 +0200 |
---|---|---|
committer | Alexandru Gagniuc <mr.nuke.me@gmail.com> | 2012-08-25 05:15:50 +0200 |
commit | 8c0279088266beccdc8953ecf2dd340fa27ed768 (patch) | |
tree | aa51ca4c3d14e6a3a5a473c2fe372532a461057f /src/arch/x86/boot | |
parent | 651339bb5d3114a83b2ae4bf5d1da87636e7dadc (diff) |
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>
Reviewed-on: http://review.coreboot.org/1461
Tested-by: build bot (Jenkins)
Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Diffstat (limited to 'src/arch/x86/boot')
-rw-r--r-- | src/arch/x86/boot/mpspec.c | 89 |
1 files changed, 47 insertions, 42 deletions
diff --git a/src/arch/x86/boot/mpspec.c b/src/arch/x86/boot/mpspec.c index 78996c7d70..cf346a5d67 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; + } } } |