drm/nouveau/mmu: Add correct turing page kinds
authorJames Jones <jajones@nvidia.com>
Tue, 17 Dec 2019 00:58:05 +0000 (16:58 -0800)
committerBen Skeggs <bskeggs@redhat.com>
Wed, 15 Jan 2020 00:49:59 +0000 (10:49 +1000)
Turing introduced a new simplified page kind
scheme, reducing the number of possible page
kinds from 256 to 16.  It also is the first
NVIDIA GPU in which the highest possible page
kind value is not reserved as an "invalid" page
kind.

To address this, the invalid page kind is made
an explicit property of the MMU HAL, and a new
table of page kinds is added to the tu102 MMU
HAL.

One hardware change not addressed here is that
0x00 is technically no longer a supported page
kind, and pitch surfaces are instead intended to
share the block-linear generic page kind 0x06.
However, because that will be a rather invasive
change to nouveau and 0x00 still works fine in
practice on Turing hardware, addressing this new
behavior is deferred.

Signed-off-by: James Jones <jajones@nvidia.com>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
12 files changed:
drivers/gpu/drm/nouveau/include/nvif/if0008.h
drivers/gpu/drm/nouveau/include/nvif/mmu.h
drivers/gpu/drm/nouveau/nvif/mmu.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/tu102.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c

index 8450127420f550c7ff1d038f1b671b2c544f942c..c21d09f04f1d6db5c0323c7e4622f2f53ffc86aa 100644 (file)
@@ -35,7 +35,7 @@ struct nvif_mmu_type_v0 {
 
 struct nvif_mmu_kind_v0 {
        __u8  version;
-       __u8  pad01[1];
+       __u8  kind_inv;
        __u16 count;
        __u8  data[];
 };
index 747ecf67e40382e165431323b233ffb2ac13e588..cec1e88a0a05c7eee4cd4fc08d4a6e70f93f1139 100644 (file)
@@ -7,6 +7,7 @@ struct nvif_mmu {
        u8  dmabits;
        u8  heap_nr;
        u8  type_nr;
+       u8  kind_inv;
        u16 kind_nr;
        s32 mem;
 
@@ -36,9 +37,8 @@ void nvif_mmu_fini(struct nvif_mmu *);
 static inline bool
 nvif_mmu_kind_valid(struct nvif_mmu *mmu, u8 kind)
 {
-       const u8 invalid = mmu->kind_nr - 1;
        if (kind) {
-               if (kind >= mmu->kind_nr || mmu->kind[kind] == invalid)
+               if (kind >= mmu->kind_nr || mmu->kind[kind] == mmu->kind_inv)
                        return false;
        }
        return true;
index 5641bda2046da6efb3d73cca0f5adde90ef13ae2..47efc408efa6a1d75e21c6f48ae65a76b428352c 100644 (file)
@@ -121,6 +121,7 @@ nvif_mmu_init(struct nvif_object *parent, s32 oclass, struct nvif_mmu *mmu)
                                       kind, argc);
                if (ret == 0)
                        memcpy(mmu->kind, kind->data, kind->count);
+               mmu->kind_inv = kind->kind_inv;
                kfree(kind);
        }
 
index 2d075246dc46073564dd316154f66fe0cf0f1096..2cd5ec81c0d0ad6b4976f640394e38262201b889 100644 (file)
@@ -30,7 +30,7 @@
  * The value 0xff represents an invalid storage type.
  */
 const u8 *
-gf100_mmu_kind(struct nvkm_mmu *mmu, int *count)
+gf100_mmu_kind(struct nvkm_mmu *mmu, int *count, u8 *invalid)
 {
        static const u8
        kind[256] = {
@@ -69,6 +69,7 @@ gf100_mmu_kind(struct nvkm_mmu *mmu, int *count)
        };
 
        *count = ARRAY_SIZE(kind);
+       *invalid = 0xff;
        return kind;
 }
 
index dbf644ebac97bd2f141755e7658d10a8b65d0ea3..83990c83f9f81728490b8eed1d54f5dfbfbbf01c 100644 (file)
@@ -27,7 +27,7 @@
 #include <nvif/class.h>
 
 const u8 *
-gm200_mmu_kind(struct nvkm_mmu *mmu, int *count)
+gm200_mmu_kind(struct nvkm_mmu *mmu, int *count, u8 *invalid)
 {
        static const u8
        kind[256] = {
@@ -65,6 +65,7 @@ gm200_mmu_kind(struct nvkm_mmu *mmu, int *count)
                0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfe, 0xff
        };
        *count = ARRAY_SIZE(kind);
+       *invalid = 0xff;
        return kind;
 }
 
index db3dfbbb2aa08a8af72527ce13ae3b9befaf6080..c0083ddda65a08a534ec3116e0d759158dac9ab4 100644 (file)
@@ -27,7 +27,7 @@
 #include <nvif/class.h>
 
 const u8 *
-nv50_mmu_kind(struct nvkm_mmu *base, int *count)
+nv50_mmu_kind(struct nvkm_mmu *base, int *count, u8 *invalid)
 {
        /* 0x01: no bank swizzle
         * 0x02: bank swizzled
@@ -57,6 +57,7 @@ nv50_mmu_kind(struct nvkm_mmu *base, int *count)
                0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x7f, 0x7f
        };
        *count = ARRAY_SIZE(kind);
+       *invalid = 0x7f;
        return kind;
 }
 
index 07f2fcd18f3df7c402aa690ae2db995e0a80ff73..479b023442710a41d23c7fc44f0723b7f6e6a20b 100644 (file)
@@ -35,17 +35,17 @@ struct nvkm_mmu_func {
                u32 pd_offset;
        } vmm;
 
-       const u8 *(*kind)(struct nvkm_mmu *, int *count);
+       const u8 *(*kind)(struct nvkm_mmu *, int *count, u8 *invalid);
        bool kind_sys;
 };
 
 extern const struct nvkm_mmu_func nv04_mmu;
 
-const u8 *nv50_mmu_kind(struct nvkm_mmu *, int *count);
+const u8 *nv50_mmu_kind(struct nvkm_mmu *, int *count, u8 *invalid);
 
-const u8 *gf100_mmu_kind(struct nvkm_mmu *, int *count);
+const u8 *gf100_mmu_kind(struct nvkm_mmu *, int *count, u8 *invalid);
 
-const u8 *gm200_mmu_kind(struct nvkm_mmu *, int *);
+const u8 *gm200_mmu_kind(struct nvkm_mmu *, int *, u8 *);
 
 struct nvkm_mmu_pt {
        union {
index c0db0ce10cba153f1637b5d77ba1a75a067fbfdf..b21e82eb0916277d6aca2f2a3483fea7bcf5b26c 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2018 Red Hat Inc.
+ * Copyright 2019 NVIDIA Corporation.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 
 #include <nvif/class.h>
 
+const u8 *
+tu102_mmu_kind(struct nvkm_mmu *mmu, int *count, u8 *invalid)
+{
+       static const u8
+       kind[16] = {
+               0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00 */
+               0x06, 0x06, 0x02, 0x01, 0x03, 0x04, 0x05, 0x07,
+       };
+       *count = ARRAY_SIZE(kind);
+       *invalid = 0x07;
+       return kind;
+}
+
 static const struct nvkm_mmu_func
 tu102_mmu = {
        .dma_bits = 47,
        .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
        .mem = {{ -1,  0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map },
        .vmm = {{ -1,  0, NVIF_CLASS_VMM_GP100}, tu102_vmm_new },
-       .kind = gm200_mmu_kind,
+       .kind = tu102_mmu_kind,
        .kind_sys = true,
 };
 
index 353f10f92b774f56defd53720f93defaa05aba57..0e4b8941da372ce5d55c386546f988283b0b7621 100644 (file)
@@ -111,15 +111,17 @@ nvkm_ummu_kind(struct nvkm_ummu *ummu, void *argv, u32 argc)
        } *args = argv;
        const u8 *kind = NULL;
        int ret = -ENOSYS, count = 0;
+       u8 kind_inv = 0;
 
        if (mmu->func->kind)
-               kind = mmu->func->kind(mmu, &count);
+               kind = mmu->func->kind(mmu, &count, &kind_inv);
 
        if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, true))) {
                if (argc != args->v0.count * sizeof(*args->v0.data))
                        return -EINVAL;
                if (args->v0.count > count)
                        return -EINVAL;
+               args->v0.kind_inv = kind_inv;
                memcpy(args->v0.data, kind, args->v0.count);
        } else
                return ret;
@@ -157,9 +159,10 @@ nvkm_ummu_new(struct nvkm_device *device, const struct nvkm_oclass *oclass,
        struct nvkm_mmu *mmu = device->mmu;
        struct nvkm_ummu *ummu;
        int ret = -ENOSYS, kinds = 0;
+       u8 unused = 0;
 
        if (mmu->func->kind)
-               mmu->func->kind(mmu, &kinds);
+               mmu->func->kind(mmu, &kinds, &unused);
 
        if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
                args->v0.dmabits = mmu->dma_bits;
index ab6424faf84cb39181705b68c2a06bfdefc82299..6a2d9eb8e1ea8fbb6885c5064a1e2e988afd8782 100644 (file)
@@ -247,7 +247,7 @@ gf100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
        } *args = argv;
        struct nvkm_device *device = vmm->mmu->subdev.device;
        struct nvkm_memory *memory = map->memory;
-       u8  kind, priv, ro, vol;
+       u8  kind, kind_inv, priv, ro, vol;
        int kindn, aper, ret = -ENOSYS;
        const u8 *kindm;
 
@@ -274,8 +274,8 @@ gf100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
        if (WARN_ON(aper < 0))
                return aper;
 
-       kindm = vmm->mmu->func->kind(vmm->mmu, &kindn);
-       if (kind >= kindn || kindm[kind] == 0xff) {
+       kindm = vmm->mmu->func->kind(vmm->mmu, &kindn, &kind_inv);
+       if (kind >= kindn || kindm[kind] == kind_inv) {
                VMM_DEBUG(vmm, "kind %02x", kind);
                return -EINVAL;
        }
index b4f519768d5e082b1b8c0754b12666656e5b730e..d8628756554281520da40a050fe27c109ed27746 100644 (file)
@@ -320,7 +320,7 @@ gp100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
        } *args = argv;
        struct nvkm_device *device = vmm->mmu->subdev.device;
        struct nvkm_memory *memory = map->memory;
-       u8  kind, priv, ro, vol;
+       u8  kind, kind_inv, priv, ro, vol;
        int kindn, aper, ret = -ENOSYS;
        const u8 *kindm;
 
@@ -347,8 +347,8 @@ gp100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
        if (WARN_ON(aper < 0))
                return aper;
 
-       kindm = vmm->mmu->func->kind(vmm->mmu, &kindn);
-       if (kind >= kindn || kindm[kind] == 0xff) {
+       kindm = vmm->mmu->func->kind(vmm->mmu, &kindn, &kind_inv);
+       if (kind >= kindn || kindm[kind] == kind_inv) {
                VMM_DEBUG(vmm, "kind %02x", kind);
                return -EINVAL;
        }
index c98afe3134eed65cba3e542cf6a1d4b4d2c35f20..2d89e27e8e9e5eb60e7164957dc1e36c27b4fc3d 100644 (file)
@@ -235,7 +235,7 @@ nv50_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
        struct nvkm_device *device = vmm->mmu->subdev.device;
        struct nvkm_ram *ram = device->fb->ram;
        struct nvkm_memory *memory = map->memory;
-       u8  aper, kind, comp, priv, ro;
+       u8  aper, kind, kind_inv, comp, priv, ro;
        int kindn, ret = -ENOSYS;
        const u8 *kindm;
 
@@ -278,8 +278,8 @@ nv50_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
                return -EINVAL;
        }
 
-       kindm = vmm->mmu->func->kind(vmm->mmu, &kindn);
-       if (kind >= kindn || kindm[kind] == 0x7f) {
+       kindm = vmm->mmu->func->kind(vmm->mmu, &kindn, &kind_inv);
+       if (kind >= kindn || kindm[kind] == kind_inv) {
                VMM_DEBUG(vmm, "kind %02x", kind);
                return -EINVAL;
        }