acpi/sci: Test ACPI MADT interrupt override entry's preferred mode first
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 29 Aug 2012 02:25:47 +0000 (10:25 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 29 Aug 2012 02:27:31 +0000 (10:27 +0800)
sys/dev/acpica5/acpi_sci_var.h
sys/platform/pc32/acpica5/acpi_fadt.c
sys/platform/pc32/acpica5/acpi_madt.c
sys/platform/pc64/acpica5/acpi_fadt.c
sys/platform/pc64/acpica5/acpi_madt.c

index 7d41314..effb899 100644 (file)
@@ -1,9 +1,14 @@
 #ifndef _ACPI_SCI_VAR_H_
 #define _ACPI_SCI_VAR_H_
 
+#ifndef _SYS_BUS_H_
+#include <sys/bus.h>
+#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_ */
index 6918f25..daa53f9 100644 (file)
@@ -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;
+               }
+       }
+}
index fa03da7..2a7575c 100644 (file)
@@ -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,
index 6918f25..daa53f9 100644 (file)
@@ -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;
+               }
+       }
+}
index 5c3d74a..2fb3c4c 100644 (file)
@@ -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,