From: Sepherosa Ziehau Date: Wed, 29 Aug 2012 02:25:47 +0000 (+0800) Subject: acpi/sci: Test ACPI MADT interrupt override entry's preferred mode first X-Git-Tag: v3.2.0~232 X-Git-Url: http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/c098b394a7c60e4eac9e48b147f5c90c133a6fd4 acpi/sci: Test ACPI MADT interrupt override entry's preferred mode first --- diff --git a/sys/dev/acpica5/acpi_sci_var.h b/sys/dev/acpica5/acpi_sci_var.h index 7d41314..effb899 100644 --- a/sys/dev/acpica5/acpi_sci_var.h +++ b/sys/dev/acpica5/acpi_sci_var.h @@ -1,9 +1,14 @@ #ifndef _ACPI_SCI_VAR_H_ #define _ACPI_SCI_VAR_H_ +#ifndef _SYS_BUS_H_ +#include +#endif + void acpi_sci_config(void); int acpi_sci_enabled(void); int acpi_sci_pci_shariable(void); int acpi_sci_irqno(void); +void acpi_sci_setmode1(enum intr_trigger, enum intr_polarity); #endif /* !_ACPI_SCI_VAR_H_ */ diff --git a/sys/platform/pc32/acpica5/acpi_fadt.c b/sys/platform/pc32/acpica5/acpi_fadt.c index 6918f25..daa53f9 100644 --- a/sys/platform/pc32/acpica5/acpi_fadt.c +++ b/sys/platform/pc32/acpica5/acpi_fadt.c @@ -74,6 +74,7 @@ struct acpi_sci_mode { static int acpi_sci_irq = -1; static enum intr_trigger acpi_sci_trig = INTR_TRIGGER_CONFORM; static enum intr_polarity acpi_sci_pola = INTR_POLARITY_CONFORM; +static const struct acpi_sci_mode *acpi_sci_mode1 = NULL; static const struct acpi_sci_mode acpi_sci_modes[] = { /* @@ -177,6 +178,42 @@ acpi_sci_dummy_intr(void *dummy __unused, void *frame __unused) { } +static boolean_t +acpi_sci_test(const struct acpi_sci_mode *mode) +{ + void *sci_desc; + long last_cnt; + + FADT_VPRINTF("SCI testing %s/%s\n", + intr_str_trigger(mode->sci_trig), + intr_str_polarity(mode->sci_pola)); + + last_cnt = get_interrupt_counter(acpi_sci_irq, 0); + + machintr_legacy_intr_config(acpi_sci_irq, + mode->sci_trig, mode->sci_pola); + + sci_desc = register_int(acpi_sci_irq, + acpi_sci_dummy_intr, NULL, "sci", NULL, + INTR_EXCL | INTR_CLOCK | + INTR_NOPOLL | INTR_MPSAFE | INTR_NOENTROPY, 0); + + DELAY(100 * 1000); + + unregister_int(sci_desc, 0); + + if (get_interrupt_counter(acpi_sci_irq, 0) - last_cnt < 20) { + acpi_sci_trig = mode->sci_trig; + acpi_sci_pola = mode->sci_pola; + + kprintf("ACPI FADT: SCI select %s/%s\n", + intr_str_trigger(acpi_sci_trig), + intr_str_polarity(acpi_sci_pola)); + return TRUE; + } + return FALSE; +} + void acpi_sci_config(void) { @@ -203,38 +240,16 @@ acpi_sci_config(void) } kprintf("ACPI FADT: SCI testing interrupt mode ...\n"); + if (acpi_sci_mode1 != NULL) { + if (acpi_sci_test(acpi_sci_mode1)) + return; + } for (mode = acpi_sci_modes; mode->sci_trig != INTR_TRIGGER_CONFORM; ++mode) { - void *sci_desc; - long last_cnt; - - FADT_VPRINTF("SCI testing %s/%s\n", - intr_str_trigger(mode->sci_trig), - intr_str_polarity(mode->sci_pola)); - - last_cnt = get_interrupt_counter(acpi_sci_irq, 0); - - machintr_legacy_intr_config(acpi_sci_irq, - mode->sci_trig, mode->sci_pola); - - sci_desc = register_int(acpi_sci_irq, - acpi_sci_dummy_intr, NULL, "sci", NULL, - INTR_EXCL | INTR_CLOCK | - INTR_NOPOLL | INTR_MPSAFE | INTR_NOENTROPY, 0); - - DELAY(100 * 1000); - - unregister_int(sci_desc, 0); - - if (get_interrupt_counter(acpi_sci_irq, 0) - last_cnt < 20) { - acpi_sci_trig = mode->sci_trig; - acpi_sci_pola = mode->sci_pola; - - kprintf("ACPI FADT: SCI select %s/%s\n", - intr_str_trigger(acpi_sci_trig), - intr_str_polarity(acpi_sci_pola)); + if (mode == acpi_sci_mode1) + continue; + if (acpi_sci_test(mode)) return; - } } kprintf("ACPI FADT: no suitable interrupt mode for SCI, disable\n"); @@ -266,3 +281,17 @@ acpi_sci_irqno(void) { return acpi_sci_irq; } + +void +acpi_sci_setmode1(enum intr_trigger trig, enum intr_polarity pola) +{ + const struct acpi_sci_mode *mode; + + for (mode = acpi_sci_modes; mode->sci_trig != INTR_TRIGGER_CONFORM; + ++mode) { + if (mode->sci_trig == trig && mode->sci_pola == pola) { + acpi_sci_mode1 = mode; + return; + } + } +} diff --git a/sys/platform/pc32/acpica5/acpi_madt.c b/sys/platform/pc32/acpica5/acpi_madt.c index fa03da7..2a7575c 100644 --- a/sys/platform/pc32/acpica5/acpi_madt.c +++ b/sys/platform/pc32/acpica5/acpi_madt.c @@ -44,6 +44,7 @@ #include "acpi_sdt.h" #include "acpi_sdt_var.h" +#include "acpi_sci_var.h" extern int naps; @@ -608,9 +609,7 @@ madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) const struct acpi_madt_intsrc *intsrc_ent; enum intr_trigger trig; enum intr_polarity pola; -#ifdef foo int ent_trig, ent_pola; -#endif intsrc_ent = (const struct acpi_madt_intsrc *)ent; @@ -618,7 +617,6 @@ madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) if (intsrc_ent->mint_bus != MADT_INT_BUS_ISA) return 0; -#ifdef foo ent_trig = (intsrc_ent->mint_flags & MADT_INT_TRIG_MASK) >> MADT_INT_TRIG_SHIFT; if (ent_trig == MADT_INT_TRIG_RSVD) @@ -636,7 +634,14 @@ madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) pola = INTR_POLARITY_LOW; else pola = INTR_POLARITY_HIGH; -#else + + if (intsrc_ent->mint_src == acpi_sci_irqno()) { + acpi_sci_setmode1(trig, pola); + MADT_VPRINTF("SCI irq %d, first test %s/%s\n", + intsrc_ent->mint_src, + intr_str_trigger(trig), intr_str_polarity(pola)); + } + /* * We ignore the polarity and trigger changes, since * most of them are wrong or useless at best. @@ -647,7 +652,6 @@ madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) } trig = INTR_TRIGGER_EDGE; pola = INTR_POLARITY_HIGH; -#endif MADT_VPRINTF("INTSRC irq %d -> gsi %u %s/%s\n", intsrc_ent->mint_src, intsrc_ent->mint_gsi, diff --git a/sys/platform/pc64/acpica5/acpi_fadt.c b/sys/platform/pc64/acpica5/acpi_fadt.c index 6918f25..daa53f9 100644 --- a/sys/platform/pc64/acpica5/acpi_fadt.c +++ b/sys/platform/pc64/acpica5/acpi_fadt.c @@ -74,6 +74,7 @@ struct acpi_sci_mode { static int acpi_sci_irq = -1; static enum intr_trigger acpi_sci_trig = INTR_TRIGGER_CONFORM; static enum intr_polarity acpi_sci_pola = INTR_POLARITY_CONFORM; +static const struct acpi_sci_mode *acpi_sci_mode1 = NULL; static const struct acpi_sci_mode acpi_sci_modes[] = { /* @@ -177,6 +178,42 @@ acpi_sci_dummy_intr(void *dummy __unused, void *frame __unused) { } +static boolean_t +acpi_sci_test(const struct acpi_sci_mode *mode) +{ + void *sci_desc; + long last_cnt; + + FADT_VPRINTF("SCI testing %s/%s\n", + intr_str_trigger(mode->sci_trig), + intr_str_polarity(mode->sci_pola)); + + last_cnt = get_interrupt_counter(acpi_sci_irq, 0); + + machintr_legacy_intr_config(acpi_sci_irq, + mode->sci_trig, mode->sci_pola); + + sci_desc = register_int(acpi_sci_irq, + acpi_sci_dummy_intr, NULL, "sci", NULL, + INTR_EXCL | INTR_CLOCK | + INTR_NOPOLL | INTR_MPSAFE | INTR_NOENTROPY, 0); + + DELAY(100 * 1000); + + unregister_int(sci_desc, 0); + + if (get_interrupt_counter(acpi_sci_irq, 0) - last_cnt < 20) { + acpi_sci_trig = mode->sci_trig; + acpi_sci_pola = mode->sci_pola; + + kprintf("ACPI FADT: SCI select %s/%s\n", + intr_str_trigger(acpi_sci_trig), + intr_str_polarity(acpi_sci_pola)); + return TRUE; + } + return FALSE; +} + void acpi_sci_config(void) { @@ -203,38 +240,16 @@ acpi_sci_config(void) } kprintf("ACPI FADT: SCI testing interrupt mode ...\n"); + if (acpi_sci_mode1 != NULL) { + if (acpi_sci_test(acpi_sci_mode1)) + return; + } for (mode = acpi_sci_modes; mode->sci_trig != INTR_TRIGGER_CONFORM; ++mode) { - void *sci_desc; - long last_cnt; - - FADT_VPRINTF("SCI testing %s/%s\n", - intr_str_trigger(mode->sci_trig), - intr_str_polarity(mode->sci_pola)); - - last_cnt = get_interrupt_counter(acpi_sci_irq, 0); - - machintr_legacy_intr_config(acpi_sci_irq, - mode->sci_trig, mode->sci_pola); - - sci_desc = register_int(acpi_sci_irq, - acpi_sci_dummy_intr, NULL, "sci", NULL, - INTR_EXCL | INTR_CLOCK | - INTR_NOPOLL | INTR_MPSAFE | INTR_NOENTROPY, 0); - - DELAY(100 * 1000); - - unregister_int(sci_desc, 0); - - if (get_interrupt_counter(acpi_sci_irq, 0) - last_cnt < 20) { - acpi_sci_trig = mode->sci_trig; - acpi_sci_pola = mode->sci_pola; - - kprintf("ACPI FADT: SCI select %s/%s\n", - intr_str_trigger(acpi_sci_trig), - intr_str_polarity(acpi_sci_pola)); + if (mode == acpi_sci_mode1) + continue; + if (acpi_sci_test(mode)) return; - } } kprintf("ACPI FADT: no suitable interrupt mode for SCI, disable\n"); @@ -266,3 +281,17 @@ acpi_sci_irqno(void) { return acpi_sci_irq; } + +void +acpi_sci_setmode1(enum intr_trigger trig, enum intr_polarity pola) +{ + const struct acpi_sci_mode *mode; + + for (mode = acpi_sci_modes; mode->sci_trig != INTR_TRIGGER_CONFORM; + ++mode) { + if (mode->sci_trig == trig && mode->sci_pola == pola) { + acpi_sci_mode1 = mode; + return; + } + } +} diff --git a/sys/platform/pc64/acpica5/acpi_madt.c b/sys/platform/pc64/acpica5/acpi_madt.c index 5c3d74a..2fb3c4c 100644 --- a/sys/platform/pc64/acpica5/acpi_madt.c +++ b/sys/platform/pc64/acpica5/acpi_madt.c @@ -44,6 +44,7 @@ #include "acpi_sdt.h" #include "acpi_sdt_var.h" +#include "acpi_sci_var.h" extern int naps; @@ -608,9 +609,7 @@ madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) const struct acpi_madt_intsrc *intsrc_ent; enum intr_trigger trig; enum intr_polarity pola; -#ifdef foo int ent_trig, ent_pola; -#endif intsrc_ent = (const struct acpi_madt_intsrc *)ent; @@ -618,7 +617,6 @@ madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) if (intsrc_ent->mint_bus != MADT_INT_BUS_ISA) return 0; -#ifdef foo ent_trig = (intsrc_ent->mint_flags & MADT_INT_TRIG_MASK) >> MADT_INT_TRIG_SHIFT; if (ent_trig == MADT_INT_TRIG_RSVD) @@ -636,7 +634,14 @@ madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) pola = INTR_POLARITY_LOW; else pola = INTR_POLARITY_HIGH; -#else + + if (intsrc_ent->mint_src == acpi_sci_irqno()) { + acpi_sci_setmode1(trig, pola); + MADT_VPRINTF("SCI irq %d, first test %s/%s\n", + intsrc_ent->mint_src, + intr_str_trigger(trig), intr_str_polarity(pola)); + } + /* * We ignore the polarity and trigger changes, since * most of them are wrong or useless at best. @@ -647,7 +652,6 @@ madt_ioapic_enum_callback(void *xarg, const struct acpi_madt_ent *ent) } trig = INTR_TRIGGER_EDGE; pola = INTR_POLARITY_HIGH; -#endif MADT_VPRINTF("INTSRC irq %d -> gsi %u %s/%s\n", intsrc_ent->mint_src, intsrc_ent->mint_gsi,