drm/nouveau/fifo/gv100: initial support
authorBen Skeggs <bskeggs@redhat.com>
Tue, 8 May 2018 10:39:48 +0000 (20:39 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Fri, 18 May 2018 05:01:46 +0000 (15:01 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
21 files changed:
drivers/gpu/drm/nouveau/include/nvif/class.h
drivers/gpu/drm/nouveau/include/nvif/device.h
drivers/gpu/drm/nouveau/include/nvif/user.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
drivers/gpu/drm/nouveau/nouveau_chan.c
drivers/gpu/drm/nouveau/nouveau_dma.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nvif/Kbuild
drivers/gpu/drm/nouveau/nvif/device.c
drivers/gpu/drm/nouveau/nvif/user.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvif/userc361.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild
drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c [new file with mode: 0644]

index 8c9aa55..a2fdbc6 100644 (file)
@@ -52,6 +52,8 @@
 
 #define NV04_DISP                                     /* cl0046.h */ 0x00000046
 
+#define VOLTA_USERMODE_A                                             0x0000c361
+
 #define NV03_CHANNEL_DMA                              /* cl506b.h */ 0x0000006b
 #define NV10_CHANNEL_DMA                              /* cl506b.h */ 0x0000006e
 #define NV17_CHANNEL_DMA                              /* cl506b.h */ 0x0000176e
@@ -66,6 +68,7 @@
 #define KEPLER_CHANNEL_GPFIFO_B                       /* cla06f.h */ 0x0000a16f
 #define MAXWELL_CHANNEL_GPFIFO_A                      /* cla06f.h */ 0x0000b06f
 #define PASCAL_CHANNEL_GPFIFO_A                       /* cla06f.h */ 0x0000c06f
+#define VOLTA_CHANNEL_GPFIFO_A                        /* cla06f.h */ 0x0000c36f
 
 #define NV50_DISP                                     /* cl5070.h */ 0x00005070
 #define G82_DISP                                      /* cl5070.h */ 0x00008270
index 76fe21e..ef839bd 100644 (file)
@@ -4,6 +4,7 @@
 
 #include <nvif/object.h>
 #include <nvif/cl0080.h>
+#include <nvif/user.h>
 
 struct nvif_device {
        struct nvif_object object;
@@ -13,6 +14,8 @@ struct nvif_device {
                u64 engines;
        } *runlist;
        int runlists;
+
+       struct nvif_user user;
 };
 
 int  nvif_device_init(struct nvif_object *, u32 handle, s32 oclass, void *, u32,
diff --git a/drivers/gpu/drm/nouveau/include/nvif/user.h b/drivers/gpu/drm/nouveau/include/nvif/user.h
new file mode 100644 (file)
index 0000000..03c1182
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __NVIF_USER_H__
+#define __NVIF_USER_H__
+#include <nvif/object.h>
+struct nvif_device;
+
+struct nvif_user {
+       const struct nvif_user_func *func;
+       struct nvif_object object;
+};
+
+struct nvif_user_func {
+       void (*doorbell)(struct nvif_user *, u32 token);
+};
+
+int nvif_user_init(struct nvif_device *);
+void nvif_user_fini(struct nvif_device *);
+
+extern const struct nvif_user_func nvif_userc361;
+#endif
index 0d96ede..7e39fbe 100644 (file)
@@ -73,4 +73,5 @@ int gm200_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
 int gm20b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
 int gp100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
 int gp10b_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
+int gv100_fifo_new(struct nvkm_device *, int, struct nvkm_fifo **);
 #endif
index 97900e9..92d3115 100644 (file)
@@ -220,7 +220,8 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
                    u64 runlist, struct nouveau_channel **pchan)
 {
        struct nouveau_cli *cli = (void *)device->object.client;
-       static const u16 oclasses[] = { PASCAL_CHANNEL_GPFIFO_A,
+       static const u16 oclasses[] = { VOLTA_CHANNEL_GPFIFO_A,
+                                       PASCAL_CHANNEL_GPFIFO_A,
                                        MAXWELL_CHANNEL_GPFIFO_A,
                                        KEPLER_CHANNEL_GPFIFO_B,
                                        KEPLER_CHANNEL_GPFIFO_A,
index e0664d2..945afd3 100644 (file)
@@ -28,6 +28,8 @@
 #include "nouveau_dma.h"
 #include "nouveau_vmm.h"
 
+#include <nvif/user.h>
+
 void
 OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords)
 {
@@ -82,6 +84,7 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout)
 void
 nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length)
 {
+       struct nvif_user *user = &chan->drm->client.device.user;
        struct nouveau_bo *pb = chan->push.buffer;
        int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;
 
@@ -97,6 +100,8 @@ nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length)
        nouveau_bo_rd32(pb, 0);
 
        nvif_wr32(&chan->user, 0x8c, chan->dma.ib_put);
+       if (user->func && user->func->doorbell)
+               user->func->doorbell(user, chan->chid);
        chan->dma.ib_free--;
 }
 
index 8e506c5..775443c 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <nvif/driver.h>
 #include <nvif/fifo.h>
+#include <nvif/user.h>
 
 #include <nvif/class.h>
 #include <nvif/cl0002.h>
@@ -310,6 +311,12 @@ nouveau_accel_init(struct nouveau_drm *drm)
        if (ret)
                return;
 
+       if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_VOLTA) {
+               ret = nvif_user_init(device);
+               if (ret)
+                       return;
+       }
+
        /* initialise synchronisation routines */
        /*XXX: this is crap, but the fence/channel stuff is a little
         *     backwards in some places.  this will be fixed.
@@ -341,6 +348,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
                case KEPLER_CHANNEL_GPFIFO_B:
                case MAXWELL_CHANNEL_GPFIFO_A:
                case PASCAL_CHANNEL_GPFIFO_A:
+               case VOLTA_CHANNEL_GPFIFO_A:
                        ret = nvc0_fence_create(drm);
                        break;
                default:
index 3db1250..42e8c85 100644 (file)
@@ -8,3 +8,7 @@ nvif-y += nvif/mem.o
 nvif-y += nvif/mmu.o
 nvif-y += nvif/notify.o
 nvif-y += nvif/vmm.o
+
+# Usermode classes
+nvif-y += nvif/user.o
+nvif-y += nvif/userc361.o
index ca5eb3d..1ec101b 100644 (file)
@@ -37,6 +37,7 @@ nvif_device_time(struct nvif_device *device)
 void
 nvif_device_fini(struct nvif_device *device)
 {
+       nvif_user_fini(device);
        kfree(device->runlist);
        device->runlist = NULL;
        nvif_object_fini(&device->object);
@@ -49,6 +50,7 @@ nvif_device_init(struct nvif_object *parent, u32 handle, s32 oclass,
        int ret = nvif_object_init(parent, handle, oclass, data, size,
                                   &device->object);
        device->runlist = NULL;
+       device->user.func = NULL;
        if (ret == 0) {
                device->info.version = 0;
                ret = nvif_object_mthd(&device->object, NV_DEVICE_V0_INFO,
diff --git a/drivers/gpu/drm/nouveau/nvif/user.c b/drivers/gpu/drm/nouveau/nvif/user.c
new file mode 100644 (file)
index 0000000..10da3cd
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2018 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <nvif/user.h>
+#include <nvif/device.h>
+
+#include <nvif/class.h>
+
+void
+nvif_user_fini(struct nvif_device *device)
+{
+       if (device->user.func) {
+               nvif_object_fini(&device->user.object);
+               device->user.func = NULL;
+       }
+}
+
+int
+nvif_user_init(struct nvif_device *device)
+{
+       struct {
+               s32 oclass;
+               int version;
+               const struct nvif_user_func *func;
+       } users[] = {
+               { VOLTA_USERMODE_A, -1, &nvif_userc361 },
+               {}
+       };
+       int cid, ret;
+
+       if (device->user.func)
+               return 0;
+
+       cid = nvif_mclass(&device->object, users);
+       if (cid < 0)
+               return cid;
+
+       ret = nvif_object_init(&device->object, 0, users[cid].oclass, NULL, 0,
+                              &device->user.object);
+       if (ret)
+               return ret;
+
+       nvif_object_map(&device->user.object, NULL, 0);
+       device->user.func = users[cid].func;
+       return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvif/userc361.c b/drivers/gpu/drm/nouveau/nvif/userc361.c
new file mode 100644 (file)
index 0000000..19f9958
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2018 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <nvif/user.h>
+
+static void
+nvif_userc361_doorbell(struct nvif_user *user, u32 token)
+{
+       nvif_wr32(&user->object, 0x90, token);
+}
+
+const struct nvif_user_func
+nvif_userc361 = {
+       .doorbell = nvif_userc361_doorbell,
+};
index 43f6b7a..95a56d4 100644 (file)
@@ -2418,6 +2418,7 @@ nv140_chipset = {
        .top = gk104_top_new,
        .disp = gv100_disp_new,
        .dma = gv100_dma_new,
+       .fifo = gv100_fifo_new,
 };
 
 static int
index b888ea6..f004085 100644 (file)
@@ -15,6 +15,7 @@ nvkm-y += nvkm/engine/fifo/gm200.o
 nvkm-y += nvkm/engine/fifo/gm20b.o
 nvkm-y += nvkm/engine/fifo/gp100.o
 nvkm-y += nvkm/engine/fifo/gp10b.o
+nvkm-y += nvkm/engine/fifo/gv100.o
 
 nvkm-y += nvkm/engine/fifo/chan.o
 nvkm-y += nvkm/engine/fifo/channv50.o
@@ -31,3 +32,6 @@ nvkm-y += nvkm/engine/fifo/gpfifonv50.o
 nvkm-y += nvkm/engine/fifo/gpfifog84.o
 nvkm-y += nvkm/engine/fifo/gpfifogf100.o
 nvkm-y += nvkm/engine/fifo/gpfifogk104.o
+nvkm-y += nvkm/engine/fifo/gpfifogv100.o
+
+nvkm-y += nvkm/engine/fifo/usergv100.o
index 391e864..8e28ba6 100644 (file)
@@ -20,6 +20,20 @@ struct gk104_fifo_chan {
        } engn[NVKM_SUBDEV_NR];
 };
 
+extern const struct nvkm_fifo_chan_func gk104_fifo_gpfifo_func;
+
 int gk104_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
                          void *data, u32 size, struct nvkm_object **);
+void *gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *);
+void gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *);
+void gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *);
+int gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *, struct nvkm_engine *,
+                                 struct nvkm_object *);
+void gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *,
+                                  struct nvkm_engine *);
+int gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *);
+int gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *);
+
+int gv100_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
+                         void *data, u32 size, struct nvkm_object **);
 #endif
index 767e0ab..a990464 100644 (file)
@@ -103,6 +103,10 @@ gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
        if (oclass->engn == &fifo->func->chan) {
                const struct gk104_fifo_chan_user *user = oclass->engn;
                return user->ctor(fifo, oclass, argv, argc, pobject);
+       } else
+       if (oclass->engn == &fifo->func->user) {
+               const struct gk104_fifo_user_user *user = oclass->engn;
+               return user->ctor(oclass, argv, argc, pobject);
        }
        WARN_ON(1);
        return -EINVAL;
@@ -115,6 +119,12 @@ gk104_fifo_class_get(struct nvkm_fifo *base, int index,
        struct gk104_fifo *fifo = gk104_fifo(base);
        int c = 0;
 
+       if (fifo->func->user.ctor && c++ == index) {
+               oclass->base =  fifo->func->user.user;
+               oclass->engn = &fifo->func->user;
+               return 0;
+       }
+
        if (fifo->func->chan.ctor && c++ == index) {
                oclass->base =  fifo->func->chan.user;
                oclass->engn = &fifo->func->chan;
index 1d182d8..d295b81 100644 (file)
@@ -63,6 +63,12 @@ struct gk104_fifo_func {
                             struct nvkm_memory *, u32 offset);
        } *runlist;
 
+       struct gk104_fifo_user_user {
+               struct nvkm_sclass user;
+               int (*ctor)(const struct nvkm_oclass *, void *, u32,
+                           struct nvkm_object **);
+       } user;
+
        struct gk104_fifo_chan_user {
                struct nvkm_sclass user;
                int (*ctor)(struct gk104_fifo *, const struct nvkm_oclass *,
index 60e7d72..118b37a 100644 (file)
@@ -34,8 +34,8 @@
 #include <nvif/cla06f.h>
 #include <nvif/unpack.h>
 
-static int
-gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
+int
+gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *chan)
 {
        struct gk104_fifo *fifo = chan->fifo;
        struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
@@ -44,7 +44,6 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
        struct nvkm_fifo_cgrp *cgrp = chan->cgrp;
        int ret = 0;
 
-       mutex_lock(&subdev->mutex);
        if (cgrp)
                nvkm_wr32(device, 0x002634, cgrp->id | 0x01000000);
        else
@@ -59,7 +58,16 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
                nvkm_fifo_recover_chan(&fifo->base, chan->base.chid);
                ret = -ETIMEDOUT;
        }
-       mutex_unlock(&subdev->mutex);
+       return ret;
+}
+
+int
+gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
+{
+       int ret;
+       mutex_lock(&chan->base.fifo->engine.subdev.mutex);
+       ret = gk104_fifo_gpfifo_kick_locked(chan);
+       mutex_unlock(&chan->base.fifo->engine.subdev.mutex);
        return ret;
 }
 
@@ -138,7 +146,7 @@ gk104_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
        return 0;
 }
 
-static void
+void
 gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base,
                              struct nvkm_engine *engine)
 {
@@ -147,7 +155,7 @@ gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base,
        nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst);
 }
 
-static int
+int
 gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base,
                              struct nvkm_engine *engine,
                              struct nvkm_object *object)
@@ -172,7 +180,7 @@ gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base,
                               chan->engn[engn].vma, NULL, 0);
 }
 
-static void
+void
 gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
 {
        struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
@@ -190,7 +198,7 @@ gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
        nvkm_wr32(device, 0x800000 + coff, 0x00000000);
 }
 
-static void
+void
 gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
 {
        struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
@@ -210,7 +218,7 @@ gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
        }
 }
 
-static void *
+void *
 gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
 {
        struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
@@ -218,7 +226,7 @@ gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
        return chan;
 }
 
-static const struct nvkm_fifo_chan_func
+const struct nvkm_fifo_chan_func
 gk104_fifo_gpfifo_func = {
        .dtor = gk104_fifo_gpfifo_dtor,
        .init = gk104_fifo_gpfifo_init,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c
new file mode 100644 (file)
index 0000000..9598853
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2018 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "changk104.h"
+#include "cgrp.h"
+
+#include <core/client.h>
+#include <core/gpuobj.h>
+
+#include <nvif/cla06f.h>
+#include <nvif/unpack.h>
+
+static int
+gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid)
+{
+       struct nvkm_subdev *subdev = &chan->base.fifo->engine.subdev;
+       struct nvkm_device *device = subdev->device;
+       const u32 mask = ce ? 0x00020000 : 0x00010000;
+       const u32 data = valid ? mask : 0x00000000;
+       int ret;
+
+       /* Block runlist to prevent the channel from being rescheduled. */
+       mutex_lock(&subdev->mutex);
+       nvkm_mask(device, 0x002630, BIT(chan->runl), BIT(chan->runl));
+
+       /* Preempt the channel. */
+       ret = gk104_fifo_gpfifo_kick_locked(chan);
+       if (ret == 0) {
+               /* Update engine context validity. */
+               nvkm_kmap(chan->base.inst);
+               nvkm_mo32(chan->base.inst, 0x0ac, mask, data);
+               nvkm_done(chan->base.inst);
+       }
+
+       /* Resume runlist. */
+       nvkm_mask(device, 0x002630, BIT(chan->runl), 0);
+       mutex_unlock(&subdev->mutex);
+       return ret;
+}
+
+static int
+gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
+                             struct nvkm_engine *engine, bool suspend)
+{
+       struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       struct nvkm_gpuobj *inst = chan->base.inst;
+       int ret;
+
+       if (engine->subdev.index >= NVKM_ENGINE_CE0 &&
+           engine->subdev.index <= NVKM_ENGINE_CE_LAST)
+               return gk104_fifo_gpfifo_kick(chan);
+
+       ret = gv100_fifo_gpfifo_engine_valid(chan, false, false);
+       if (ret && suspend)
+               return ret;
+
+       nvkm_kmap(inst);
+       nvkm_wo32(inst, 0x0210, 0x00000000);
+       nvkm_wo32(inst, 0x0214, 0x00000000);
+       nvkm_done(inst);
+       return ret;
+}
+
+static int
+gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
+                             struct nvkm_engine *engine)
+{
+       struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
+       struct nvkm_gpuobj *inst = chan->base.inst;
+       u64 addr;
+
+       if (engine->subdev.index >= NVKM_ENGINE_CE0 &&
+           engine->subdev.index <= NVKM_ENGINE_CE_LAST)
+               return 0;
+
+       addr = chan->engn[engine->subdev.index].vma->addr;
+       nvkm_kmap(inst);
+       nvkm_wo32(inst, 0x210, lower_32_bits(addr) | 0x00000004);
+       nvkm_wo32(inst, 0x214, upper_32_bits(addr));
+       nvkm_done(inst);
+
+       return gv100_fifo_gpfifo_engine_valid(chan, false, true);
+}
+
+const struct nvkm_fifo_chan_func
+gv100_fifo_gpfifo_func = {
+       .dtor = gk104_fifo_gpfifo_dtor,
+       .init = gk104_fifo_gpfifo_init,
+       .fini = gk104_fifo_gpfifo_fini,
+       .ntfy = gf100_fifo_chan_ntfy,
+       .engine_ctor = gk104_fifo_gpfifo_engine_ctor,
+       .engine_dtor = gk104_fifo_gpfifo_engine_dtor,
+       .engine_init = gv100_fifo_gpfifo_engine_init,
+       .engine_fini = gv100_fifo_gpfifo_engine_fini,
+};
+
+static int
+gv100_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
+                      u64 vmm, u64 ioffset, u64 ilength,
+                      const struct nvkm_oclass *oclass,
+                      struct nvkm_object **pobject)
+{
+       struct gk104_fifo_chan *chan;
+       int runlist = ffs(*runlists) -1, ret, i;
+       unsigned long engm;
+       u64 subdevs = 0;
+       u64 usermem;
+
+       if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr)
+               return -EINVAL;
+       *runlists = BIT_ULL(runlist);
+
+       engm = fifo->runlist[runlist].engm;
+       for_each_set_bit(i, &engm, fifo->engine_nr) {
+               if (fifo->engine[i].engine)
+                       subdevs |= BIT_ULL(fifo->engine[i].engine->subdev.index);
+       }
+
+       /* Allocate the channel. */
+       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+               return -ENOMEM;
+       *pobject = &chan->base.object;
+       chan->fifo = fifo;
+       chan->runl = runlist;
+       INIT_LIST_HEAD(&chan->head);
+
+       ret = nvkm_fifo_chan_ctor(&gv100_fifo_gpfifo_func, &fifo->base,
+                                 0x1000, 0x1000, true, vmm, 0, subdevs,
+                                 1, fifo->user.bar->addr, 0x200,
+                                 oclass, &chan->base);
+       if (ret)
+               return ret;
+
+       *chid = chan->base.chid;
+
+       /* Hack to support GPUs where even individual channels should be
+        * part of a channel group.
+        */
+       if (fifo->func->cgrp_force) {
+               if (!(chan->cgrp = kmalloc(sizeof(*chan->cgrp), GFP_KERNEL)))
+                       return -ENOMEM;
+               chan->cgrp->id = chan->base.chid;
+               INIT_LIST_HEAD(&chan->cgrp->head);
+               INIT_LIST_HEAD(&chan->cgrp->chan);
+               chan->cgrp->chan_nr = 0;
+       }
+
+       /* Clear channel control registers. */
+       usermem = chan->base.chid * 0x200;
+       ilength = order_base_2(ilength / 8);
+
+       nvkm_kmap(fifo->user.mem);
+       for (i = 0; i < 0x200; i += 4)
+               nvkm_wo32(fifo->user.mem, usermem + i, 0x00000000);
+       nvkm_done(fifo->user.mem);
+       usermem = nvkm_memory_addr(fifo->user.mem) + usermem;
+
+       /* RAMFC */
+       nvkm_kmap(chan->base.inst);
+       nvkm_wo32(chan->base.inst, 0x008, lower_32_bits(usermem));
+       nvkm_wo32(chan->base.inst, 0x00c, upper_32_bits(usermem));
+       nvkm_wo32(chan->base.inst, 0x010, 0x0000face);
+       nvkm_wo32(chan->base.inst, 0x030, 0x7ffff902);
+       nvkm_wo32(chan->base.inst, 0x048, lower_32_bits(ioffset));
+       nvkm_wo32(chan->base.inst, 0x04c, upper_32_bits(ioffset) |
+                                         (ilength << 16));
+       nvkm_wo32(chan->base.inst, 0x084, 0x20400000);
+       nvkm_wo32(chan->base.inst, 0x094, 0x30000001);
+       nvkm_wo32(chan->base.inst, 0x0e4, 0x00000020);
+       nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid);
+       nvkm_wo32(chan->base.inst, 0x0f4, 0x00001100);
+       nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080);
+       nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000);
+       nvkm_wo32(chan->base.inst, 0x220, 0x020a1000);
+       nvkm_wo32(chan->base.inst, 0x224, 0x00000000);
+       nvkm_done(chan->base.inst);
+       return gv100_fifo_gpfifo_engine_valid(chan, true, true);
+}
+
+int
+gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
+                     void *data, u32 size, struct nvkm_object **pobject)
+{
+       struct nvkm_object *parent = oclass->parent;
+       union {
+               struct kepler_channel_gpfifo_a_v0 v0;
+       } *args = data;
+       int ret = -ENOSYS;
+
+       nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
+       if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
+               nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
+                                  "ioffset %016llx ilength %08x "
+                                  "runlist %016llx\n",
+                          args->v0.version, args->v0.vmm, args->v0.ioffset,
+                          args->v0.ilength, args->v0.runlist);
+               return gv100_fifo_gpfifo_new_(fifo,
+                                             &args->v0.runlist,
+                                             &args->v0.chid,
+                                              args->v0.vmm,
+                                              args->v0.ioffset,
+                                              args->v0.ilength,
+                                             oclass, pobject);
+       }
+
+       return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c
new file mode 100644 (file)
index 0000000..4e1d159
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2018 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "gk104.h"
+#include "cgrp.h"
+#include "changk104.h"
+#include "user.h"
+
+#include <core/gpuobj.h>
+
+#include <nvif/class.h>
+
+static void
+gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan,
+                       struct nvkm_memory *memory, u32 offset)
+{
+       struct nvkm_memory *usermem = chan->fifo->user.mem;
+       const u64 user = nvkm_memory_addr(usermem) + (chan->base.chid * 0x200);
+       const u64 inst = chan->base.inst->addr;
+
+       nvkm_wo32(memory, offset + 0x0, lower_32_bits(user));
+       nvkm_wo32(memory, offset + 0x4, upper_32_bits(user));
+       nvkm_wo32(memory, offset + 0x8, lower_32_bits(inst) | chan->base.chid);
+       nvkm_wo32(memory, offset + 0xc, upper_32_bits(inst));
+}
+
+static void
+gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp,
+                       struct nvkm_memory *memory, u32 offset)
+{
+       nvkm_wo32(memory, offset + 0x0, (128 << 24) | (3 << 16) | 0x00000001);
+       nvkm_wo32(memory, offset + 0x4, cgrp->chan_nr);
+       nvkm_wo32(memory, offset + 0x8, cgrp->id);
+       nvkm_wo32(memory, offset + 0xc, 0x00000000);
+}
+
+const struct gk104_fifo_runlist_func
+gv100_fifo_runlist = {
+       .size = 16,
+       .cgrp = gv100_fifo_runlist_cgrp,
+       .chan = gv100_fifo_runlist_chan,
+};
+
+static const struct nvkm_enum
+gv100_fifo_fault_gpcclient[] = {
+       { 0x00, "T1_0" },
+       { 0x01, "T1_1" },
+       { 0x02, "T1_2" },
+       { 0x03, "T1_3" },
+       { 0x04, "T1_4" },
+       { 0x05, "T1_5" },
+       { 0x06, "T1_6" },
+       { 0x07, "T1_7" },
+       { 0x08, "PE_0" },
+       { 0x09, "PE_1" },
+       { 0x0a, "PE_2" },
+       { 0x0b, "PE_3" },
+       { 0x0c, "PE_4" },
+       { 0x0d, "PE_5" },
+       { 0x0e, "PE_6" },
+       { 0x0f, "PE_7" },
+       { 0x10, "RAST" },
+       { 0x11, "GCC" },
+       { 0x12, "GPCCS" },
+       { 0x13, "PROP_0" },
+       { 0x14, "PROP_1" },
+       { 0x15, "PROP_2" },
+       { 0x16, "PROP_3" },
+       { 0x17, "GPM" },
+       { 0x18, "LTP_UTLB_0" },
+       { 0x19, "LTP_UTLB_1" },
+       { 0x1a, "LTP_UTLB_2" },
+       { 0x1b, "LTP_UTLB_3" },
+       { 0x1c, "LTP_UTLB_4" },
+       { 0x1d, "LTP_UTLB_5" },
+       { 0x1e, "LTP_UTLB_6" },
+       { 0x1f, "LTP_UTLB_7" },
+       { 0x20, "RGG_UTLB" },
+       { 0x21, "T1_8" },
+       { 0x22, "T1_9" },
+       { 0x23, "T1_10" },
+       { 0x24, "T1_11" },
+       { 0x25, "T1_12" },
+       { 0x26, "T1_13" },
+       { 0x27, "T1_14" },
+       { 0x28, "T1_15" },
+       { 0x29, "TPCCS_0" },
+       { 0x2a, "TPCCS_1" },
+       { 0x2b, "TPCCS_2" },
+       { 0x2c, "TPCCS_3" },
+       { 0x2d, "TPCCS_4" },
+       { 0x2e, "TPCCS_5" },
+       { 0x2f, "TPCCS_6" },
+       { 0x30, "TPCCS_7" },
+       { 0x31, "PE_8" },
+       { 0x32, "PE_9" },
+       { 0x33, "TPCCS_8" },
+       { 0x34, "TPCCS_9" },
+       { 0x35, "T1_16" },
+       { 0x36, "T1_17" },
+       { 0x37, "T1_18" },
+       { 0x38, "T1_19" },
+       { 0x39, "PE_10" },
+       { 0x3a, "PE_11" },
+       { 0x3b, "TPCCS_10" },
+       { 0x3c, "TPCCS_11" },
+       { 0x3d, "T1_20" },
+       { 0x3e, "T1_21" },
+       { 0x3f, "T1_22" },
+       { 0x40, "T1_23" },
+       { 0x41, "PE_12" },
+       { 0x42, "PE_13" },
+       { 0x43, "TPCCS_12" },
+       { 0x44, "TPCCS_13" },
+       { 0x45, "T1_24" },
+       { 0x46, "T1_25" },
+       { 0x47, "T1_26" },
+       { 0x48, "T1_27" },
+       { 0x49, "PE_14" },
+       { 0x4a, "PE_15" },
+       { 0x4b, "TPCCS_14" },
+       { 0x4c, "TPCCS_15" },
+       { 0x4d, "T1_28" },
+       { 0x4e, "T1_29" },
+       { 0x4f, "T1_30" },
+       { 0x50, "T1_31" },
+       { 0x51, "PE_16" },
+       { 0x52, "PE_17" },
+       { 0x53, "TPCCS_16" },
+       { 0x54, "TPCCS_17" },
+       { 0x55, "T1_32" },
+       { 0x56, "T1_33" },
+       { 0x57, "T1_34" },
+       { 0x58, "T1_35" },
+       { 0x59, "PE_18" },
+       { 0x5a, "PE_19" },
+       { 0x5b, "TPCCS_18" },
+       { 0x5c, "TPCCS_19" },
+       { 0x5d, "T1_36" },
+       { 0x5e, "T1_37" },
+       { 0x5f, "T1_38" },
+       { 0x60, "T1_39" },
+       {}
+};
+
+static const struct nvkm_enum
+gv100_fifo_fault_hubclient[] = {
+       { 0x00, "VIP" },
+       { 0x01, "CE0" },
+       { 0x02, "CE1" },
+       { 0x03, "DNISO" },
+       { 0x04, "FE" },
+       { 0x05, "FECS" },
+       { 0x06, "HOST" },
+       { 0x07, "HOST_CPU" },
+       { 0x08, "HOST_CPU_NB" },
+       { 0x09, "ISO" },
+       { 0x0a, "MMU" },
+       { 0x0b, "NVDEC" },
+       { 0x0d, "NVENC1" },
+       { 0x0e, "NISO" },
+       { 0x0f, "P2P" },
+       { 0x10, "PD" },
+       { 0x11, "PERF" },
+       { 0x12, "PMU" },
+       { 0x13, "RASTERTWOD" },
+       { 0x14, "SCC" },
+       { 0x15, "SCC_NB" },
+       { 0x16, "SEC" },
+       { 0x17, "SSYNC" },
+       { 0x18, "CE2" },
+       { 0x19, "XV" },
+       { 0x1a, "MMU_NB" },
+       { 0x1b, "NVENC0" },
+       { 0x1c, "DFALCON" },
+       { 0x1d, "SKED" },
+       { 0x1e, "AFALCON" },
+       { 0x1f, "DONT_CARE" },
+       { 0x20, "HSCE0" },
+       { 0x21, "HSCE1" },
+       { 0x22, "HSCE2" },
+       { 0x23, "HSCE3" },
+       { 0x24, "HSCE4" },
+       { 0x25, "HSCE5" },
+       { 0x26, "HSCE6" },
+       { 0x27, "HSCE7" },
+       { 0x28, "HSCE8" },
+       { 0x29, "HSCE9" },
+       { 0x2a, "HSHUB" },
+       { 0x2b, "PTP_X0" },
+       { 0x2c, "PTP_X1" },
+       { 0x2d, "PTP_X2" },
+       { 0x2e, "PTP_X3" },
+       { 0x2f, "PTP_X4" },
+       { 0x30, "PTP_X5" },
+       { 0x31, "PTP_X6" },
+       { 0x32, "PTP_X7" },
+       { 0x33, "NVENC2" },
+       { 0x34, "VPR_SCRUBBER0" },
+       { 0x35, "VPR_SCRUBBER1" },
+       { 0x36, "DWBIF" },
+       { 0x37, "FBFALCON" },
+       { 0x38, "CE_SHIM" },
+       { 0x39, "GSP" },
+       {}
+};
+
+static const struct nvkm_enum
+gv100_fifo_fault_reason[] = {
+       { 0x00, "PDE" },
+       { 0x01, "PDE_SIZE" },
+       { 0x02, "PTE" },
+       { 0x03, "VA_LIMIT_VIOLATION" },
+       { 0x04, "UNBOUND_INST_BLOCK" },
+       { 0x05, "PRIV_VIOLATION" },
+       { 0x06, "RO_VIOLATION" },
+       { 0x07, "WO_VIOLATION" },
+       { 0x08, "PITCH_MASK_VIOLATION" },
+       { 0x09, "WORK_CREATION" },
+       { 0x0a, "UNSUPPORTED_APERTURE" },
+       { 0x0b, "COMPRESSION_FAILURE" },
+       { 0x0c, "UNSUPPORTED_KIND" },
+       { 0x0d, "REGION_VIOLATION" },
+       { 0x0e, "POISONED" },
+       { 0x0f, "ATOMIC_VIOLATION" },
+       {}
+};
+
+static const struct nvkm_enum
+gv100_fifo_fault_engine[] = {
+       { 0x01, "DISPLAY" },
+       { 0x03, "PTP" },
+       { 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
+       { 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
+       { 0x06, "PWR_PMU" },
+       { 0x08, "IFB", NULL, NVKM_ENGINE_IFB },
+       { 0x09, "PERF" },
+       { 0x1f, "PHYSICAL" },
+       { 0x20, "HOST0" },
+       { 0x21, "HOST1" },
+       { 0x22, "HOST2" },
+       { 0x23, "HOST3" },
+       { 0x24, "HOST4" },
+       { 0x25, "HOST5" },
+       { 0x26, "HOST6" },
+       { 0x27, "HOST7" },
+       { 0x28, "HOST8" },
+       { 0x29, "HOST9" },
+       { 0x2a, "HOST10" },
+       { 0x2b, "HOST11" },
+       { 0x2c, "HOST12" },
+       { 0x2d, "HOST13" },
+       {}
+};
+
+static const struct nvkm_enum
+gv100_fifo_fault_access[] = {
+       { 0x0, "VIRT_READ" },
+       { 0x1, "VIRT_WRITE" },
+       { 0x2, "VIRT_ATOMIC" },
+       { 0x3, "VIRT_PREFETCH" },
+       { 0x4, "VIRT_ATOMIC_WEAK" },
+       { 0x8, "PHYS_READ" },
+       { 0x9, "PHYS_WRITE" },
+       { 0xa, "PHYS_ATOMIC" },
+       { 0xb, "PHYS_PREFETCH" },
+       {}
+};
+
+static const struct gk104_fifo_func
+gv100_fifo = {
+       .init_pbdma_timeout = gk208_fifo_init_pbdma_timeout,
+       .fault.access = gv100_fifo_fault_access,
+       .fault.engine = gv100_fifo_fault_engine,
+       .fault.reason = gv100_fifo_fault_reason,
+       .fault.hubclient = gv100_fifo_fault_hubclient,
+       .fault.gpcclient = gv100_fifo_fault_gpcclient,
+       .runlist = &gv100_fifo_runlist,
+       .user = {{-1,-1,VOLTA_USERMODE_A      }, gv100_fifo_user_new   },
+       .chan = {{ 0, 0,VOLTA_CHANNEL_GPFIFO_A}, gv100_fifo_gpfifo_new },
+       .cgrp_force = true,
+};
+
+int
+gv100_fifo_new(struct nvkm_device *device, int index, struct nvkm_fifo **pfifo)
+{
+       return gk104_fifo_new_(&gv100_fifo, device, index, 4096, pfifo);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h
new file mode 100644 (file)
index 0000000..ed84092
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __NVKM_FIFO_USER_H__
+#define __NVKM_FIFO_USER_H__
+#include "priv.h"
+int gv100_fifo_user_new(const struct nvkm_oclass *, void *, u32,
+                       struct nvkm_object **);
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c
new file mode 100644 (file)
index 0000000..3dc3b8b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include "user.h"
+
+static int
+gv100_fifo_user_map(struct nvkm_object *object, void *argv, u32 argc,
+                   enum nvkm_object_map *type, u64 *addr, u64 *size)
+{
+       struct nvkm_device *device = object->engine->subdev.device;
+       *addr = 0x810000 + device->func->resource_addr(device, 0);
+       *size = 0x010000;
+       *type = NVKM_OBJECT_MAP_IO;
+       return 0;
+}
+
+static const struct nvkm_object_func
+gv100_fifo_user = {
+       .map = gv100_fifo_user_map,
+};
+
+int
+gv100_fifo_user_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
+                   struct nvkm_object **pobject)
+{
+       return nvkm_object_new_(&gv100_fifo_user, oclass, argv, argc, pobject);
+}