From: Sepherosa Ziehau Date: Wed, 23 Mar 2011 14:33:52 +0000 (+0800) Subject: ioapic: Allow interrupt trigger mode override in MADT X-Git-Tag: v2.11.0~164 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/ae80be109c082484e11483414625a90914253202 ioapic: Allow interrupt trigger mode override in MADT --- diff --git a/sys/platform/pc32/apic/mpapic.c b/sys/platform/pc32/apic/mpapic.c index 870e736800..0ac746d81c 100644 --- a/sys/platform/pc32/apic/mpapic.c +++ b/sys/platform/pc32/apic/mpapic.c @@ -63,9 +63,15 @@ struct ioapic_info { }; TAILQ_HEAD(ioapic_info_list, ioapic_info); +struct ioapic_intsrc { + int int_gsi; + enum intr_trigger int_trig; + enum intr_polarity int_pola; +}; + struct ioapic_conf { struct ioapic_info_list ioc_list; - int ioc_intsrc[16]; /* XXX magic number */ + struct ioapic_intsrc ioc_intsrc[16]; /* XXX magic number */ }; static void lapic_timer_calibrate(void); @@ -1148,7 +1154,7 @@ ioapic_config(void) TAILQ_INIT(&ioapic_conf.ioc_list); /* XXX magic number */ for (i = 0; i < 16; ++i) - ioapic_conf.ioc_intsrc[i] = -1; + ioapic_conf.ioc_intsrc[i].int_gsi = -1; TAILQ_FOREACH(e, &ioapic_enumerators, ioapic_link) { error = e->ioapic_probe(e); @@ -1323,10 +1329,12 @@ ioapic_add(void *addr, int gsi_base, int npin) } void -ioapic_intsrc(int irq, int gsi) +ioapic_intsrc(int irq, int gsi, enum intr_trigger trig, enum intr_polarity pola) { - KKASSERT(irq != gsi); + struct ioapic_intsrc *int_src; + KKASSERT(irq < 16); + int_src = &ioapic_conf.ioc_intsrc[irq]; if (gsi == 0) { /* Don't allow mixed mode */ @@ -1334,12 +1342,29 @@ ioapic_intsrc(int irq, int gsi) return; } - if (ioapic_conf.ioc_intsrc[irq] != -1 && - ioapic_conf.ioc_intsrc[irq] != gsi) { - kprintf("IOAPIC: warning intsrc irq %d, gsi %d -> gsi %d\n", - irq, ioapic_conf.ioc_intsrc[irq], gsi); + if (int_src->int_gsi != -1) { + if (int_src->int_gsi != gsi) { + kprintf("IOAPIC: warning intsrc irq %d, gsi " + "%d -> %d\n", irq, int_src->int_gsi, gsi); + } + if (int_src->int_trig != trig) { + kprintf("IOAPIC: warning intsrc irq %d, trig " + "%c -> %c\n", irq, + int_src->int_trig == INTR_TRIGGER_EDGE + ? 'E' : 'L', + trig == INTR_TRIGGER_EDGE ? 'E' : 'L'); + } + if (int_src->int_pola != pola) { + kprintf("IOAPIC: warning intsrc irq %d, pola " + "%s -> %s\n", irq, + int_src->int_pola == INTR_POLARITY_HIGH + ? "hi" : "lo", + pola == INTR_POLARITY_HIGH ? "hi" : "lo"); + } } - ioapic_conf.ioc_intsrc[irq] = gsi; + int_src->int_gsi = gsi; + int_src->int_trig = trig; + int_src->int_pola = pola; } static void @@ -1391,9 +1416,12 @@ ioapic_gsi_setup(int gsi) pola = 0; /* silence older gcc's */ for (irq = 0; irq < 16; ++irq) { - if (gsi == ioapic_conf.ioc_intsrc[irq]) { - trig = INTR_TRIGGER_EDGE; - pola = INTR_POLARITY_HIGH; + const struct ioapic_intsrc *int_src = + &ioapic_conf.ioc_intsrc[irq]; + + if (gsi == int_src->int_gsi) { + trig = int_src->int_trig; + pola = int_src->int_pola; break; } } diff --git a/sys/platform/pc32/i386/mp_machdep.c b/sys/platform/pc32/i386/mp_machdep.c index 1ada24a1cd..f83afe5e9d 100644 --- a/sys/platform/pc32/i386/mp_machdep.c +++ b/sys/platform/pc32/i386/mp_machdep.c @@ -3641,7 +3641,8 @@ mptable_ioapic_int_callback(void *xarg, const void *pos, int type) kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n", ent->src_bus_irq, gsi); } - ioapic_intsrc(ent->src_bus_irq, gsi); + ioapic_intsrc(ent->src_bus_irq, gsi, + INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); } } else { /* XXX rough estimation */ @@ -3705,7 +3706,7 @@ mptable_ioapic_enumerate(struct ioapic_enumerator *e) if (mptable_use_default) { if (bootverbose) kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (default)\n"); - ioapic_intsrc(0, 2); + ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); return; } @@ -3721,7 +3722,7 @@ mptable_ioapic_enumerate(struct ioapic_enumerator *e) if (TAILQ_EMPTY(&bus_info.mbi_list)) { if (bootverbose) kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (no bus)\n"); - ioapic_intsrc(0, 2); + ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); } else { struct mptable_ioapic_int_cbarg arg; @@ -3738,7 +3739,8 @@ mptable_ioapic_enumerate(struct ioapic_enumerator *e) kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 " "(no int)\n"); } - ioapic_intsrc(0, 2); + ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, + INTR_POLARITY_HIGH); } } diff --git a/sys/platform/pc32/i386/mp_madt.c b/sys/platform/pc32/i386/mp_madt.c index 163f8a8827..51ddcb1b8f 100644 --- a/sys/platform/pc32/i386/mp_madt.c +++ b/sys/platform/pc32/i386/mp_madt.c @@ -33,6 +33,7 @@ */ #include +#include #include #include @@ -760,11 +761,6 @@ madt_ioapic_probe_callback(void *xarg, const struct acpi_madt_ent *ent) return EINVAL; } - if (intsrc_ent->mint_src == intsrc_ent->mint_gsi) { - kprintf("ACPI MADT: warning intsrc irq %d " - "no gsi change\n", intsrc_ent->mint_src); - } - if (intsrc_ent->mint_bus != MADT_INT_BUS_ISA) { kprintf("ACPI MADT: warning intsrc irq %d " "bus is not ISA (%d)\n", @@ -773,16 +769,14 @@ madt_ioapic_probe_callback(void *xarg, const struct acpi_madt_ent *ent) trig = (intsrc_ent->mint_flags & MADT_INT_TRIG_MASK) >> MADT_INT_TRIG_SHIFT; - if (trig != MADT_INT_TRIG_EDGE && - trig != MADT_INT_TRIG_CONFORM) { + if (trig == MADT_INT_TRIG_RSVD) { kprintf("ACPI MADT: warning invalid intsrc irq %d " "trig (%d)\n", intsrc_ent->mint_src, trig); } pola = (intsrc_ent->mint_flags & MADT_INT_POLA_MASK) >> MADT_INT_POLA_SHIFT; - if (pola != MADT_INT_POLA_HIGH && - pola != MADT_INT_POLA_CONFORM) { + if (pola == MADT_INT_POLA_RSVD) { kprintf("ACPI MADT: warning invalid intsrc irq %d " "pola (%d)\n", intsrc_ent->mint_src, pola); } @@ -838,15 +832,39 @@ madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) { if (ent->me_type == MADT_ENT_INTSRC) { const struct acpi_madt_intsrc *intsrc_ent; + enum intr_trigger trig; + enum intr_polarity pola; + int ent_trig; intsrc_ent = (const struct acpi_madt_intsrc *)ent; - if (intsrc_ent->mint_src == intsrc_ent->mint_gsi || - intsrc_ent->mint_bus != MADT_INT_BUS_ISA) + + KKASSERT(intsrc_ent->mint_src < 16); + if (intsrc_ent->mint_bus != MADT_INT_BUS_ISA) + return 0; + + ent_trig = (intsrc_ent->mint_flags & MADT_INT_TRIG_MASK) >> + MADT_INT_TRIG_SHIFT; + if (ent_trig == MADT_INT_TRIG_RSVD) { return 0; + } else if (ent_trig == MADT_INT_TRIG_LEVEL) { + trig = INTR_TRIGGER_LEVEL; + pola = INTR_POLARITY_LOW; + } else { + trig = INTR_TRIGGER_EDGE; + pola = INTR_POLARITY_HIGH; + } + + if (intsrc_ent->mint_src == intsrc_ent->mint_gsi && + trig == INTR_TRIGGER_EDGE) { + /* Nothing changed */ + return 0; + } - MADT_VPRINTF("INTSRC irq %d -> gsi %u\n", - intsrc_ent->mint_src, intsrc_ent->mint_gsi); - ioapic_intsrc(intsrc_ent->mint_src, intsrc_ent->mint_gsi); + MADT_VPRINTF("INTSRC irq %d -> gsi %u %c\n", + intsrc_ent->mint_src, intsrc_ent->mint_gsi, + trig == INTR_TRIGGER_EDGE ? 'E' : 'L'); + ioapic_intsrc(intsrc_ent->mint_src, intsrc_ent->mint_gsi, + trig, pola); } else if (ent->me_type == MADT_ENT_IOAPIC) { const struct acpi_madt_ioapic *ioapic_ent; diff --git a/sys/platform/pc32/include/smp.h b/sys/platform/pc32/include/smp.h index 806f9c2a61..0ffcb39121 100644 --- a/sys/platform/pc32/include/smp.h +++ b/sys/platform/pc32/include/smp.h @@ -167,7 +167,7 @@ void lapic_enumerator_register(struct lapic_enumerator *); void ioapic_config(void); void ioapic_enumerator_register(struct ioapic_enumerator *); void ioapic_add(void *, int, int); -void ioapic_intsrc(int, int); +void ioapic_intsrc(int, int, enum intr_trigger, enum intr_polarity); void *ioapic_gsi_ioaddr(int); int ioapic_gsi_pin(int); void ioapic_pin_setup(void *, int, int, diff --git a/sys/platform/pc64/apic/mpapic.c b/sys/platform/pc64/apic/mpapic.c index 2a57f61304..64d7878ebb 100644 --- a/sys/platform/pc64/apic/mpapic.c +++ b/sys/platform/pc64/apic/mpapic.c @@ -61,9 +61,15 @@ struct ioapic_info { }; TAILQ_HEAD(ioapic_info_list, ioapic_info); +struct ioapic_intsrc { + int int_gsi; + enum intr_trigger int_trig; + enum intr_polarity int_pola; +}; + struct ioapic_conf { struct ioapic_info_list ioc_list; - int ioc_intsrc[16]; /* XXX magic number */ + struct ioapic_intsrc ioc_intsrc[16]; /* XXX magic number */ }; volatile lapic_t *lapic; @@ -1210,7 +1216,7 @@ ioapic_config(void) TAILQ_INIT(&ioapic_conf.ioc_list); /* XXX magic number */ for (i = 0; i < 16; ++i) - ioapic_conf.ioc_intsrc[i] = -1; + ioapic_conf.ioc_intsrc[i].int_gsi = -1; TAILQ_FOREACH(e, &ioapic_enumerators, ioapic_link) { error = e->ioapic_probe(e); @@ -1385,10 +1391,12 @@ ioapic_add(void *addr, int gsi_base, int npin) } void -ioapic_intsrc(int irq, int gsi) +ioapic_intsrc(int irq, int gsi, enum intr_trigger trig, enum intr_polarity pola) { - KKASSERT(irq != gsi); + struct ioapic_intsrc *int_src; + KKASSERT(irq < 16); + int_src = &ioapic_conf.ioc_intsrc[irq]; if (gsi == 0) { /* Don't allow mixed mode */ @@ -1396,12 +1404,29 @@ ioapic_intsrc(int irq, int gsi) return; } - if (ioapic_conf.ioc_intsrc[irq] != -1 && - ioapic_conf.ioc_intsrc[irq] != gsi) { - kprintf("IOAPIC: warning intsrc irq %d, gsi %d -> gsi %d\n", - irq, ioapic_conf.ioc_intsrc[irq], gsi); + if (int_src->int_gsi != -1) { + if (int_src->int_gsi != gsi) { + kprintf("IOAPIC: warning intsrc irq %d, gsi " + "%d -> %d\n", irq, int_src->int_gsi, gsi); + } + if (int_src->int_trig != trig) { + kprintf("IOAPIC: warning intsrc irq %d, trig " + "%c -> %c\n", irq, + int_src->int_trig == INTR_TRIGGER_EDGE + ? 'E' : 'L', + trig == INTR_TRIGGER_EDGE ? 'E' : 'L'); + } + if (int_src->int_pola != pola) { + kprintf("IOAPIC: warning intsrc irq %d, pola " + "%s -> %s\n", irq, + int_src->int_pola == INTR_POLARITY_HIGH + ? "hi" : "lo", + pola == INTR_POLARITY_HIGH ? "hi" : "lo"); + } } - ioapic_conf.ioc_intsrc[irq] = gsi; + int_src->int_gsi = gsi; + int_src->int_trig = trig; + int_src->int_pola = pola; } static void @@ -1450,9 +1475,12 @@ ioapic_gsi_setup(int gsi) } for (irq = 0; irq < 16; ++irq) { - if (gsi == ioapic_conf.ioc_intsrc[irq]) { - trig = INTR_TRIGGER_EDGE; - pola = INTR_POLARITY_HIGH; + const struct ioapic_intsrc *int_src = + &ioapic_conf.ioc_intsrc[irq]; + + if (gsi == int_src->int_gsi) { + trig = int_src->int_trig; + pola = int_src->int_pola; break; } } diff --git a/sys/platform/pc64/include/smp.h b/sys/platform/pc64/include/smp.h index 4631111ba7..c6e10ab0c8 100644 --- a/sys/platform/pc64/include/smp.h +++ b/sys/platform/pc64/include/smp.h @@ -178,7 +178,7 @@ void lapic_enumerator_register(struct lapic_enumerator *); void ioapic_config(void); void ioapic_enumerator_register(struct ioapic_enumerator *); void ioapic_add(void *, int, int); -void ioapic_intsrc(int, int); +void ioapic_intsrc(int, int, enum intr_trigger, enum intr_polarity); void *ioapic_gsi_ioaddr(int); int ioapic_gsi_pin(int); void ioapic_pin_setup(void *, int, int, diff --git a/sys/platform/pc64/x86_64/mp_machdep.c b/sys/platform/pc64/x86_64/mp_machdep.c index a71d2d868c..201a7d99ac 100644 --- a/sys/platform/pc64/x86_64/mp_machdep.c +++ b/sys/platform/pc64/x86_64/mp_machdep.c @@ -3634,7 +3634,8 @@ mptable_ioapic_int_callback(void *xarg, const void *pos, int type) kprintf("MPTABLE: INTSRC irq %d -> GSI %d\n", ent->src_bus_irq, gsi); } - ioapic_intsrc(ent->src_bus_irq, gsi); + ioapic_intsrc(ent->src_bus_irq, gsi, + INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); } } else { /* XXX rough estimation */ @@ -3698,7 +3699,7 @@ mptable_ioapic_enumerate(struct ioapic_enumerator *e) if (mptable_use_default) { if (bootverbose) kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (default)\n"); - ioapic_intsrc(0, 2); + ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); return; } @@ -3714,7 +3715,7 @@ mptable_ioapic_enumerate(struct ioapic_enumerator *e) if (TAILQ_EMPTY(&bus_info.mbi_list)) { if (bootverbose) kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 (no bus)\n"); - ioapic_intsrc(0, 2); + ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH); } else { struct mptable_ioapic_int_cbarg arg; @@ -3731,7 +3732,8 @@ mptable_ioapic_enumerate(struct ioapic_enumerator *e) kprintf("MPTABLE: INTSRC irq 0 -> GSI 2 " "(no int)\n"); } - ioapic_intsrc(0, 2); + ioapic_intsrc(0, 2, INTR_TRIGGER_EDGE, + INTR_POLARITY_HIGH); } } diff --git a/sys/platform/pc64/x86_64/mp_madt.c b/sys/platform/pc64/x86_64/mp_madt.c index c784a45698..aafcbd8a99 100644 --- a/sys/platform/pc64/x86_64/mp_madt.c +++ b/sys/platform/pc64/x86_64/mp_madt.c @@ -33,6 +33,7 @@ */ #include +#include #include #include @@ -759,11 +760,6 @@ madt_ioapic_probe_callback(void *xarg, const struct acpi_madt_ent *ent) return EINVAL; } - if (intsrc_ent->mint_src == intsrc_ent->mint_gsi) { - kprintf("ACPI MADT: warning intsrc irq %d " - "no gsi change\n", intsrc_ent->mint_src); - } - if (intsrc_ent->mint_bus != MADT_INT_BUS_ISA) { kprintf("ACPI MADT: warning intsrc irq %d " "bus is not ISA (%d)\n", @@ -772,16 +768,14 @@ madt_ioapic_probe_callback(void *xarg, const struct acpi_madt_ent *ent) trig = (intsrc_ent->mint_flags & MADT_INT_TRIG_MASK) >> MADT_INT_TRIG_SHIFT; - if (trig != MADT_INT_TRIG_EDGE && - trig != MADT_INT_TRIG_CONFORM) { + if (trig == MADT_INT_TRIG_RSVD) { kprintf("ACPI MADT: warning invalid intsrc irq %d " "trig (%d)\n", intsrc_ent->mint_src, trig); } pola = (intsrc_ent->mint_flags & MADT_INT_POLA_MASK) >> MADT_INT_POLA_SHIFT; - if (pola != MADT_INT_POLA_HIGH && - pola != MADT_INT_POLA_CONFORM) { + if (pola == MADT_INT_POLA_RSVD) { kprintf("ACPI MADT: warning invalid intsrc irq %d " "pola (%d)\n", intsrc_ent->mint_src, pola); } @@ -837,15 +831,39 @@ madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) { if (ent->me_type == MADT_ENT_INTSRC) { const struct acpi_madt_intsrc *intsrc_ent; + enum intr_trigger trig; + enum intr_polarity pola; + int ent_trig; intsrc_ent = (const struct acpi_madt_intsrc *)ent; - if (intsrc_ent->mint_src == intsrc_ent->mint_gsi || - intsrc_ent->mint_bus != MADT_INT_BUS_ISA) + + KKASSERT(intsrc_ent->mint_src < 16); + if (intsrc_ent->mint_bus != MADT_INT_BUS_ISA) + return 0; + + ent_trig = (intsrc_ent->mint_flags & MADT_INT_TRIG_MASK) >> + MADT_INT_TRIG_SHIFT; + if (ent_trig == MADT_INT_TRIG_RSVD) { return 0; + } else if (ent_trig == MADT_INT_TRIG_LEVEL) { + trig = INTR_TRIGGER_LEVEL; + pola = INTR_POLARITY_LOW; + } else { + trig = INTR_TRIGGER_EDGE; + pola = INTR_POLARITY_HIGH; + } + + if (intsrc_ent->mint_src == intsrc_ent->mint_gsi && + trig == INTR_TRIGGER_EDGE) { + /* Nothing changed */ + return 0; + } - MADT_VPRINTF("INTSRC irq %d -> gsi %u\n", - intsrc_ent->mint_src, intsrc_ent->mint_gsi); - ioapic_intsrc(intsrc_ent->mint_src, intsrc_ent->mint_gsi); + MADT_VPRINTF("INTSRC irq %d -> gsi %u %c\n", + intsrc_ent->mint_src, intsrc_ent->mint_gsi, + trig == INTR_TRIGGER_EDGE ? 'E' : 'L'); + ioapic_intsrc(intsrc_ent->mint_src, intsrc_ent->mint_gsi, + trig, pola); } else if (ent->me_type == MADT_ENT_IOAPIC) { const struct acpi_madt_ioapic *ioapic_ent;