icu/x86_64: Implement MSI-X alloc/release
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 20 Jan 2012 05:09:05 +0000 (13:09 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 20 Jan 2012 05:12:21 +0000 (13:12 +0800)
sys/platform/pc64/icu/icu_abi.c
sys/platform/pc64/x86_64/nexus.c

index cc8112b..cb48665 100644 (file)
@@ -97,6 +97,7 @@ static struct lwkt_token icu_irqmap_tok =
 #define ICU_IMT_LEGACY         2
 #define ICU_IMT_SYSCALL                3
 #define ICU_IMT_MSI            4
+#define ICU_IMT_MSIX           5
 
 #define ICU_IMT_ISHWI(map)     ((map)->im_type != ICU_IMT_RESERVED && \
                                 (map)->im_type != ICU_IMT_SYSCALL)
@@ -118,6 +119,13 @@ static int icu_abi_legacy_intr_cpuid(int);
 static int     icu_abi_msi_alloc(int [], int, int);
 static void    icu_abi_msi_release(const int [], int, int);
 static void    icu_abi_msi_map(int, uint64_t *, uint32_t *, int);
+static int     icu_abi_msix_alloc(int *, int);
+static void    icu_abi_msix_release(int, int);
+
+static int     icu_abi_msi_alloc_intern(int, const char *,
+                   int [], int, int);
+static void    icu_abi_msi_release_intern(int, const char *,
+                   const int [], int, int);
 
 static void    icu_abi_finalize(void);
 static void    icu_abi_cleanup(void);
@@ -139,6 +147,8 @@ struct machintr_abi MachIntrABI_ICU = {
        .msi_alloc      = icu_abi_msi_alloc,
        .msi_release    = icu_abi_msi_release,
        .msi_map        = icu_abi_msi_map,
+       .msix_alloc     = icu_abi_msix_alloc,
+       .msix_release   = icu_abi_msix_release,
 
        .finalize       = icu_abi_finalize,
        .cleanup        = icu_abi_cleanup,
@@ -432,7 +442,8 @@ icu_abi_rman_setup(struct rman *rm)
 }
 
 static int
-icu_abi_msi_alloc(int intrs[], int count, int cpuid)
+icu_abi_msi_alloc_intern(int type, const char *desc,
+    int intrs[], int count, int cpuid)
 {
        int i, error;
 
@@ -472,18 +483,18 @@ icu_abi_msi_alloc(int intrs[], int count, int cpuid)
 
                        map = &icu_irqmaps[cpuid][intr];
                        KASSERT(map->im_msi_base < 0,
-                           ("intr %d, stale MSI-base %d\n",
-                            intr, map->im_msi_base));
+                           ("intr %d, stale %s-base %d\n",
+                            intr, desc, map->im_msi_base));
 
-                       map->im_type = ICU_IMT_MSI;
+                       map->im_type = type;
                        map->im_msi_base = i;
 
                        intrs[j] = intr;
                        msi_setup(intr, cpuid);
 
                        if (bootverbose) {
-                               kprintf("alloc MSI intr %d on cpu%d\n",
-                                   intr, cpuid);
+                               kprintf("alloc %s intr %d on cpu%d\n",
+                                   desc, intr, cpuid);
                        }
                }
                error = 0;
@@ -496,7 +507,8 @@ icu_abi_msi_alloc(int intrs[], int count, int cpuid)
 }
 
 static void
-icu_abi_msi_release(const int intrs[], int count, int cpuid)
+icu_abi_msi_release_intern(int type, const char *desc,
+    const int intrs[], int count, int cpuid)
 {
        int i, msi_base = -1, intr_next = -1, mask;
 
@@ -518,22 +530,23 @@ icu_abi_msi_release(const int intrs[], int count, int cpuid)
                    ("invalid intr %d\n", intr));
 
                map = &icu_irqmaps[cpuid][intr];
-               KASSERT(map->im_type == ICU_IMT_MSI,
-                   ("try release non-MSI intr %d, type %d\n",
+               KASSERT(map->im_type == type,
+                   ("try release non-%s intr %d, type %d\n", desc,
                     intr, map->im_type));
                KASSERT(map->im_msi_base >= 0 && map->im_msi_base <= intr,
-                   ("intr %d, invalid MSI-base %d\n", intr, map->im_msi_base));
+                   ("intr %d, invalid %s-base %d\n", intr, desc,
+                    map->im_msi_base));
                KASSERT((map->im_msi_base & mask) == 0,
-                   ("intr %d, MSI-base %d is not proper aligned %d\n",
-                    intr, map->im_msi_base, count));
+                   ("intr %d, %s-base %d is not proper aligned %d\n",
+                    intr, desc, map->im_msi_base, count));
 
                if (msi_base < 0) {
                        msi_base = map->im_msi_base;
                } else {
                        KASSERT(map->im_msi_base == msi_base,
-                           ("intr %d, inconsistent MSI-base, "
+                           ("intr %d, inconsistent %s-base, "
                             "was %d, now %d\n",
-                            intr, msi_base, map->im_msi_base));
+                            intr, desc, msi_base, map->im_msi_base));
                }
 
                if (intr_next < intr)
@@ -542,8 +555,10 @@ icu_abi_msi_release(const int intrs[], int count, int cpuid)
                map->im_type = ICU_IMT_UNUSED;
                map->im_msi_base = -1;
 
-               if (bootverbose)
-                       kprintf("release MSI intr %d on cpu%d\n", intr, cpuid);
+               if (bootverbose) {
+                       kprintf("release %s intr %d on cpu%d\n",
+                           desc, intr, cpuid);
+               }
        }
 
        KKASSERT(intr_next > 0);
@@ -553,15 +568,43 @@ icu_abi_msi_release(const int intrs[], int count, int cpuid)
        if (intr_next < IDT_HWI_VECTORS) {
                const struct icu_irqmap *map = &icu_irqmaps[cpuid][intr_next];
 
-               if (map->im_type == ICU_IMT_MSI) {
+               if (map->im_type == type) {
                        KASSERT(map->im_msi_base != msi_base,
-                           ("more than %d MSI was allocated\n", count));
+                           ("more than %d %s was allocated\n", count, desc));
                }
        }
 
        lwkt_reltoken(&icu_irqmap_tok);
 }
 
+static int
+icu_abi_msi_alloc(int intrs[], int count, int cpuid)
+{
+       return icu_abi_msi_alloc_intern(ICU_IMT_MSI, "MSI",
+           intrs, count, cpuid);
+}
+
+static void
+icu_abi_msi_release(const int intrs[], int count, int cpuid)
+{
+       return icu_abi_msi_release_intern(ICU_IMT_MSI, "MSI",
+           intrs, count, cpuid);
+}
+
+static int
+icu_abi_msix_alloc(int *intr, int cpuid)
+{
+       return icu_abi_msi_alloc_intern(ICU_IMT_MSIX, "MSI-X",
+           intr, 1, cpuid);
+}
+
+static void
+icu_abi_msix_release(int intr, int cpuid)
+{
+       return icu_abi_msi_release_intern(ICU_IMT_MSIX, "MXI-X",
+           &intr, 1, cpuid);
+}
+
 static void
 icu_abi_msi_map(int intr, uint64_t *addr, uint32_t *data, int cpuid)
 {
@@ -576,15 +619,21 @@ icu_abi_msi_map(int intr, uint64_t *addr, uint32_t *data, int cpuid)
        lwkt_gettoken(&icu_irqmap_tok);
 
        map = &icu_irqmaps[cpuid][intr];
-       KASSERT(map->im_type == ICU_IMT_MSI,
-           ("try map non-MSI intr %d, type %d\n", intr, map->im_type));
+       KASSERT(map->im_type == ICU_IMT_MSI ||
+           map->im_type == ICU_IMT_MSIX,
+           ("try map non-MSI/MSI-X intr %d, type %d\n", intr, map->im_type));
        KASSERT(map->im_msi_base >= 0 && map->im_msi_base <= intr,
-           ("intr %d, invalid MSI-base %d\n", intr, map->im_msi_base));
+           ("intr %d, invalid %s-base %d\n", intr,
+            map->im_type == ICU_IMT_MSI ? "MSI" : "MSI-X",
+            map->im_msi_base));
 
        msi_map(map->im_msi_base, addr, data, cpuid);
 
-       if (bootverbose)
-               kprintf("map MSI intr %d on cpu%d\n", intr, cpuid);
+       if (bootverbose) {
+               kprintf("map %s intr %d on cpu%d\n",
+                   map->im_type == ICU_IMT_MSI ? "MSI" : "MSI-X",
+                   intr, cpuid);
+       }
 
        lwkt_reltoken(&icu_irqmap_tok);
 }
index fb6a078..a46d4bb 100644 (file)
@@ -609,10 +609,6 @@ nexus_alloc_msix(device_t dev, device_t child, int *irq, int cpuid)
        if (!lapic_enable)
                return ENODEV;
 
-       /* XXX temporary */
-       if (MachIntrABI.msix_alloc == NULL)
-               return EOPNOTSUPP;
-
        return MachIntrABI.msix_alloc(irq, cpuid);
 }