From f327d9f9540971518e1661e1f50d30ffa6b74173 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 20 Feb 2008 17:41:38 +0000 Subject: Route device IRQ through PCI bridge instead in mptable. Don't enable pin0 for ioapic of io-4. 1. apic error in kernel for MB with mcp55+io55 2. some pcie-cards could have pci bridge there, so need to put entries for device under them in mptable. Signed-off-by: Yinghai Lu Acked-by: Stefan Reinauer git-svn-id: svn://svn.coreboot.org/coreboot/trunk@3112 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/arch/i386/include/arch/smp/mpspec.h | 4 +++ src/arch/i386/smp/mpspec.c | 60 ++++++++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 4 deletions(-) (limited to 'src/arch/i386') diff --git a/src/arch/i386/include/arch/smp/mpspec.h b/src/arch/i386/include/arch/smp/mpspec.h index 600a584514..9acaeccd23 100644 --- a/src/arch/i386/include/arch/smp/mpspec.h +++ b/src/arch/i386/include/arch/smp/mpspec.h @@ -248,6 +248,10 @@ void smp_write_intsrc(struct mp_config_table *mc, unsigned char irqtype, unsigned short irqflag, unsigned char srcbus, unsigned char srcbusirq, unsigned char dstapic, unsigned char dstirq); +void smp_write_intsrc_pci_bridge(struct mp_config_table *mc, + unsigned char irqtype, unsigned short irqflag, + struct device *dev, + unsigned char dstapic, unsigned char *dstirq); void smp_write_lintsrc(struct mp_config_table *mc, unsigned char irqtype, unsigned short irqflag, unsigned char srcbusid, unsigned char srcbusirq, diff --git a/src/arch/i386/smp/mpspec.c b/src/arch/i386/smp/mpspec.c index 797dab43c6..3aedd21088 100644 --- a/src/arch/i386/smp/mpspec.c +++ b/src/arch/i386/smp/mpspec.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -26,8 +27,7 @@ void *smp_write_floating_table(unsigned long addr) void *v; /* 16 byte align the table address */ - addr += 15; - addr &= ~15; + addr = (addr + 0xf) & (~0xf); v = (void *)addr; mf = v; @@ -52,8 +52,8 @@ void *smp_write_floating_table_physaddr(unsigned long addr, unsigned long mpf_ph { struct intel_mp_floating *mf; void *v; - - v = (void *)addr; + + v = (void *)addr; mf = v; mf->mpf_signature[0] = '_'; mf->mpf_signature[1] = 'M'; @@ -204,6 +204,58 @@ void smp_write_intsrc(struct mp_config_table *mc, #endif } +void smp_write_intsrc_pci_bridge(struct mp_config_table *mc, + unsigned char irqtype, unsigned short irqflag, + struct device *dev, + unsigned char dstapic, unsigned char *dstirq) +{ + struct device *child; + + int linkn; + int i; + int srcbus; + int slot; + + struct bus *link; + unsigned char dstirq_x[4]; + + for (linkn = 0; linkn < dev->links; linkn++) { + + link = &dev->link[linkn]; + child = link->children; + srcbus = link->secondary; + + while (child) { + if (child->path.type != DEVICE_PATH_PCI) + goto next; + + slot = (child->path.u.pci.devfn >> 3); + /* round pins */ + for (i = 0; i < 4; i++) + dstirq_x[i] = dstirq[(i + slot) % 4]; + + if ((child->class >> 16) != PCI_BASE_CLASS_BRIDGE) { + /* pci device */ + printk_debug("route irq: %s %04x\n", dev_path(child)); + for (i = 0; i < 4; i++) + smp_write_intsrc(mc, irqtype, irqflag, srcbus, (slot<<2)|i, dstapic, dstirq_x[i]); + goto next; + } + + switch (child->class>>8) { + case PCI_CLASS_BRIDGE_PCI: + case PCI_CLASS_BRIDGE_PCMCIA: + case PCI_CLASS_BRIDGE_CARDBUS: + printk_debug("route irq bridge: %s %04x\n", dev_path(child)); + smp_write_intsrc_pci_bridge(mc, irqtype, irqflag, child, dstapic, dstirq_x); + } + + next: + child = child->sibling; + } + + } +} void smp_write_lintsrc(struct mp_config_table *mc, unsigned char irqtype, unsigned short irqflag, -- cgit v1.2.3