diff options
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/mpspec.h | 17 | ||||
-rw-r--r-- | arch/x86/lib/mpspec.c | 24 |
2 files changed, 34 insertions, 7 deletions
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index efa9231..ad8eba9 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -432,6 +432,23 @@ void mp_write_compat_address_space(struct mp_config_table *mc, int busid, u32 mptable_finalize(struct mp_config_table *mc); /** + * mp_determine_pci_dstirq() - Determine PCI device's int pin on the I/O APIC + * + * This determines a PCI device's interrupt pin number on the I/O APIC. + * + * This can be implemented by platform codes to handle specifal cases, which + * do not conform to the normal chipset/board design where PIRQ[A-H] are mapped + * directly to I/O APIC INTPIN#16-23. + * + * @bus: bus number of the pci device + * @dev: device number of the pci device + * @func: function number of the pci device + * @pirq: PIRQ number the PCI device's interrupt pin is routed to + * @return: interrupt pin number on the I/O APIC + */ +int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq); + +/** * write_mp_table() - Write MP table * * This writes MP table at a given address. diff --git a/arch/x86/lib/mpspec.c b/arch/x86/lib/mpspec.c index f16fbcb..9b2a59b 100644 --- a/arch/x86/lib/mpspec.c +++ b/arch/x86/lib/mpspec.c @@ -269,6 +269,13 @@ static bool check_dup_entry(struct mpc_config_intsrc *intsrc_base, return (i == entry_num) ? false : true; } +/* TODO: move this to driver model */ +__weak int mp_determine_pci_dstirq(int bus, int dev, int func, int pirq) +{ + /* PIRQ[A-H] are connected to I/O APIC INTPIN#16-23 */ + return pirq + 16; +} + static int mptable_add_intsrc(struct mp_config_table *mc, int bus_isa, int apicid) { @@ -304,24 +311,27 @@ static int mptable_add_intsrc(struct mp_config_table *mc, for (i = 0; i < count; i++) { struct pirq_routing pr; + int bus, dev, func; + int dstirq; pr.bdf = fdt_addr_to_cpu(cell[0]); pr.pin = fdt_addr_to_cpu(cell[1]); pr.pirq = fdt_addr_to_cpu(cell[2]); + bus = PCI_BUS(pr.bdf); + dev = PCI_DEV(pr.bdf); + func = PCI_FUNC(pr.bdf); if (check_dup_entry(intsrc_base, intsrc_entries, - PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), pr.pin)) { + bus, dev, pr.pin)) { debug("found entry for bus %d device %d INT%c, skipping\n", - PCI_BUS(pr.bdf), PCI_DEV(pr.bdf), - 'A' + pr.pin - 1); + bus, dev, 'A' + pr.pin - 1); cell += sizeof(struct pirq_routing) / sizeof(u32); continue; } - /* PIRQ[A-H] are always connected to I/O APIC INTPIN#16-23 */ - mp_write_pci_intsrc(mc, MP_INT, PCI_BUS(pr.bdf), - PCI_DEV(pr.bdf), pr.pin, apicid, - pr.pirq + 16); + dstirq = mp_determine_pci_dstirq(bus, dev, func, pr.pirq); + mp_write_pci_intsrc(mc, MP_INT, bus, dev, pr.pin, + apicid, dstirq); intsrc_entries++; cell += sizeof(struct pirq_routing) / sizeof(u32); } |