ioapic/x86_64: Add missing imen_lock/unlock
[dragonfly.git] / sys / platform / pc64 / apic / ioapic.c
index 95d774a..2ff9d58 100644 (file)
@@ -33,6 +33,7 @@
 #include <sys/thread2.h>
 
 #include <machine/pmap.h>
+#include <machine_base/isa/isa_intr.h>
 #include <machine_base/icu/icu_var.h>
 #include <machine_base/apic/lapic.h>
 #include <machine_base/apic/ioapic.h>
@@ -61,7 +62,7 @@ struct ioapic_intsrc {
 
 struct ioapic_conf {
        struct ioapic_info_list ioc_list;
-       struct ioapic_intsrc ioc_intsrc[16];    /* XXX magic number */
+       struct ioapic_intsrc ioc_intsrc[ISA_IRQ_CNT];
 };
 
 static int     ioapic_config(void);
@@ -72,7 +73,7 @@ static void   ioapic_gsi_setup(int);
 static const struct ioapic_info *
                ioapic_gsi_search(int);
 static void    ioapic_pin_prog(void *, int, int,
-                   enum intr_trigger, enum intr_polarity, uint32_t);
+                   enum intr_trigger, enum intr_polarity, uint32_t, int);
 
 static struct ioapic_conf      ioapic_conf;
 
@@ -91,8 +92,7 @@ ioapic_config(void)
        register_t ef = 0;
 
        TAILQ_INIT(&ioapic_conf.ioc_list);
-       /* XXX magic number */
-       for (i = 0; i < 16; ++i)
+       for (i = 0; i < ISA_IRQ_CNT; ++i)
                ioapic_conf.ioc_intsrc[i].int_gsi = -1;
 
        probe = 1;
@@ -133,7 +133,7 @@ ioapic_config(void)
        TAILQ_FOREACH(info, &ioapic_conf.ioc_list, io_link)
                info->io_idx = i++;
 
-       if (i > IOAPIC_COUNT_MAX) /* XXX magic number */
+       if (i > IOAPIC_COUNT_MAX)
                panic("ioapic_config: more than 16 I/O APIC\n");
 
        /*
@@ -270,7 +270,7 @@ ioapic_intsrc(int irq, int gsi, enum intr_trigger trig, enum intr_polarity pola)
 {
        struct ioapic_intsrc *int_src;
 
-       KKASSERT(irq < 16);
+       KKASSERT(irq < ISA_IRQ_CNT);
        int_src = &ioapic_conf.ioc_intsrc[irq];
 
        if (gsi == 0) {
@@ -347,7 +347,7 @@ ioapic_gsi_setup(int gsi)
                return;
        }
 
-       for (irq = 0; irq < 16; ++irq) {
+       for (irq = 0; irq < ISA_IRQ_CNT; ++irq) {
                const struct ioapic_intsrc *int_src =
                    &ioapic_conf.ioc_intsrc[irq];
 
@@ -358,15 +358,35 @@ ioapic_gsi_setup(int gsi)
                }
        }
 
-       if (irq == 16) {
-               if (gsi < 16) {
+       if (irq == ISA_IRQ_CNT) {
+               /*
+                * No explicit IRQ to GSI mapping;
+                * use the default 1:1 mapping
+                */
+               irq = gsi;
+               if (irq < ISA_IRQ_CNT) {
+                       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.
+                                *
+                                * This GSI is not used, disable it.
+                                */
+                               imen_lock();
+                               ioapic_pin_setup(ioapic_gsi_ioaddr(gsi),
+                                   ioapic_gsi_pin(gsi), 0,
+                                   INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH, 0);
+                               imen_unlock();
+                               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);
@@ -423,7 +443,7 @@ void
 ioapic_extpin_setup(void *addr, int pin, int vec)
 {
        ioapic_pin_prog(addr, pin, vec,
-           INTR_TRIGGER_CONFORM, INTR_POLARITY_CONFORM, IOART_DELEXINT);
+           INTR_TRIGGER_CONFORM, INTR_POLARITY_CONFORM, IOART_DELEXINT, 0);
 }
 
 int
@@ -434,7 +454,7 @@ ioapic_extpin_gsi(void)
 
 void
 ioapic_pin_setup(void *addr, int pin, int vec,
-    enum intr_trigger trig, enum intr_polarity pola)
+    enum intr_trigger trig, enum intr_polarity pola, int cpuid)
 {
        /*
         * Always clear an I/O APIC pin before [re]programming it.  This is
@@ -449,13 +469,14 @@ ioapic_pin_setup(void *addr, int pin, int vec,
         * interrupt.
         */
        ioapic_pin_prog(addr, pin, vec, INTR_TRIGGER_EDGE, INTR_POLARITY_HIGH,
-           IOART_DELFIXED);
-       ioapic_pin_prog(addr, pin, vec, trig, pola, IOART_DELFIXED);
+           IOART_DELFIXED, cpuid);
+       ioapic_pin_prog(addr, pin, vec, trig, pola, IOART_DELFIXED, cpuid);
 }
 
 static void
 ioapic_pin_prog(void *addr, int pin, int vec,
-    enum intr_trigger trig, enum intr_polarity pola, uint32_t del_mode)
+    enum intr_trigger trig, enum intr_polarity pola,
+    uint32_t del_mode, int cpuid)
 {
        uint32_t flags, target;
        int select;
@@ -511,7 +532,7 @@ ioapic_pin_prog(void *addr, int pin, int vec,
        }
 
        target = ioapic_read(addr, select + 1) & IOART_HI_DEST_RESV;
-       target |= (CPUID_TO_APICID(0) << IOART_HI_DEST_SHIFT) &
+       target |= (CPUID_TO_APICID(cpuid) << IOART_HI_DEST_SHIFT) &
                  IOART_HI_DEST_MASK;
 
        ioapic_write(addr, select, flags | vec);