From: Sepherosa Ziehau Date: Fri, 22 Jul 2011 01:54:03 +0000 (+0800) Subject: ioapic: Don't do the default IRQ configure, if it is mapped to different GSI X-Git-Tag: v2.12.0~301 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/41f4f2876f040377b466c255ffe4c957f84b1af2 ioapic: Don't do the default IRQ configure, if it is mapped to different GSI The problem went on unnoticed for such a long time, mainly because most of the mobos only map IRQ0 to GSI2, and GSI0 is taken as being hooked to the external interrupt source like i8259. However, the bug reporter's mobo has an extra IRQ source override entry in ACPI MADT, which maps IRQ9 to GSI21. The problem reported is actually caused by: GSI is configured in the ascending order, so GSI9 is configured before GSI21. Since there is no explicit IRQ to GSI mapping for GSI9, by using the default 1:1 mapping IRQ9 will be configured. When GSI21 is configured, due to the explicit IRQ to GSI mapping, IRQ9 will be configured again, booo Reported-by: Siju George --- diff --git a/sys/platform/pc32/apic/ioapic.c b/sys/platform/pc32/apic/ioapic.c index 162dffaa77..c3f6316138 100644 --- a/sys/platform/pc32/apic/ioapic.c +++ b/sys/platform/pc32/apic/ioapic.c @@ -362,14 +362,27 @@ ioapic_gsi_setup(int gsi) } if (irq == 16) { - if (gsi < 16) { + /* + * No explicit IRQ to GSI mapping; + * use the default 1:1 mapping + */ + irq = gsi; + if (irq < 16) { + if (ioapic_conf.ioc_intsrc[irq].int_gsi >= 0) { + /* + * This IRQ is mapped to different GSI, + * don't do the default configuration. + * The configuration of the target GSI + * will finally setup this IRQ. + */ + return; + } trig = INTR_TRIGGER_EDGE; pola = INTR_POLARITY_HIGH; } else { trig = INTR_TRIGGER_LEVEL; pola = INTR_POLARITY_LOW; } - irq = gsi; } ioapic_abi_set_irqmap(irq, gsi, trig, pola); diff --git a/sys/platform/pc64/apic/ioapic.c b/sys/platform/pc64/apic/ioapic.c index 95d774a1a2..ad0dd2c9a7 100644 --- a/sys/platform/pc64/apic/ioapic.c +++ b/sys/platform/pc64/apic/ioapic.c @@ -359,14 +359,27 @@ ioapic_gsi_setup(int gsi) } if (irq == 16) { - if (gsi < 16) { + /* + * No explicit IRQ to GSI mapping; + * use the default 1:1 mapping + */ + irq = gsi; + if (irq < 16) { + if (ioapic_conf.ioc_intsrc[irq].int_gsi >= 0) { + /* + * This IRQ is mapped to different GSI, + * don't do the default configuration. + * The configuration of the target GSI + * will finally setup this IRQ. + */ + return; + } trig = INTR_TRIGGER_EDGE; pola = INTR_POLARITY_HIGH; } else { trig = INTR_TRIGGER_LEVEL; pola = INTR_POLARITY_LOW; } - irq = gsi; } ioapic_abi_set_irqmap(irq, gsi, trig, pola);