diff --git a/arch/x86/lib/mpspec.c b/arch/x86/lib/mpspec.c index 9b2a59b911..f3ad116316 100644 --- a/arch/x86/lib/mpspec.c +++ b/arch/x86/lib/mpspec.c @@ -21,6 +21,8 @@ DECLARE_GLOBAL_DATA_PTR; +static bool isa_irq_occupied[16]; + struct mp_config_table *mp_write_floating_table(struct mp_floating_table *mf) { u32 mc; @@ -243,10 +245,18 @@ static void mptable_add_isa_interrupts(struct mp_config_table *mc, int bus_isa, MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, bus_isa, 0, apicid, 2); - for (i = 3; i < 16; i++) + for (i = 3; i < 16; i++) { + /* + * Do not write ISA interrupt entry if it is already occupied + * by the platform devices. + */ + if (isa_irq_occupied[i]) + continue; + mp_write_intsrc(mc, MP_INT, MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, bus_isa, i, apicid, i); + } } /* @@ -287,10 +297,6 @@ static int mptable_add_intsrc(struct mp_config_table *mc, const u32 *cell; int i; - /* Legacy Interrupts */ - debug("Writing ISA IRQs\n"); - mptable_add_isa_interrupts(mc, bus_isa, apicid, 0); - /* Get I/O interrupt information from device tree */ node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_IRQ_ROUTER); if (node < 0) { @@ -330,12 +336,22 @@ static int mptable_add_intsrc(struct mp_config_table *mc, } dstirq = mp_determine_pci_dstirq(bus, dev, func, pr.pirq); + /* + * For PIRQ which is connected to I/O APIC interrupt pin#0-15, + * mark it as occupied so that we can skip it later. + */ + if (dstirq < 16) + isa_irq_occupied[dstirq] = true; mp_write_pci_intsrc(mc, MP_INT, bus, dev, pr.pin, apicid, dstirq); intsrc_entries++; cell += sizeof(struct pirq_routing) / sizeof(u32); } + /* Legacy Interrupts */ + debug("Writing ISA IRQs\n"); + mptable_add_isa_interrupts(mc, bus_isa, apicid, 0); + return 0; }