ioapic: Allow interrupt trigger mode override in MADT
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 23 Mar 2011 14:33:52 +0000 (22:33 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 25 Mar 2011 14:58:18 +0000 (22:58 +0800)
sys/platform/pc32/apic/mpapic.c
sys/platform/pc32/i386/mp_machdep.c
sys/platform/pc32/i386/mp_madt.c
sys/platform/pc32/include/smp.h
sys/platform/pc64/apic/mpapic.c
sys/platform/pc64/include/smp.h
sys/platform/pc64/x86_64/mp_machdep.c
sys/platform/pc64/x86_64/mp_madt.c

index 870e736..0ac746d 100644 (file)
@@ -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;
                }
        }
index 1ada24a..f83afe5 100644 (file)
@@ -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);
                }
        }
 
index 163f8a8..51ddcb1 100644 (file)
@@ -33,6 +33,7 @@
  */
 
 #include <sys/param.h>
+#include <sys/bus.h>
 #include <sys/kernel.h>
 #include <sys/systm.h>
 
@@ -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;
 
index 806f9c2..0ffcb39 100644 (file)
@@ -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,
index 2a57f61..64d7878 100644 (file)
@@ -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;
                }
        }
index 4631111..c6e10ab 100644 (file)
@@ -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,
index a71d2d8..201a7d9 100644 (file)
@@ -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);
                }
        }
 
index c784a45..aafcbd8 100644 (file)
@@ -33,6 +33,7 @@
  */
 
 #include <sys/param.h>
+#include <sys/bus.h>
 #include <sys/kernel.h>
 #include <sys/systm.h>
 
@@ -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;