drm/nouveau/fault/gp100: expose MaxwellFaultBufferA
authorBen Skeggs <bskeggs@redhat.com>
Tue, 8 May 2018 10:39:48 +0000 (20:39 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 19 Feb 2019 23:00:00 +0000 (09:00 +1000)
This nvclass exposes the replayable fault buffer, which will be used
by SVM to manage GPU page faults.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/include/nvif/class.h
drivers/gpu/drm/nouveau/include/nvif/clb069.h [new file with mode: 0644]
drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h
drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild
drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c
drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h
drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c [new file with mode: 0644]

index 214cb6f..6c2cbb1 100644 (file)
@@ -54,6 +54,8 @@
 
 #define VOLTA_USERMODE_A                                             0x0000c361
 
+#define MAXWELL_FAULT_BUFFER_A                        /* clb069.h */ 0x0000b069
+
 #define NV03_CHANNEL_DMA                              /* cl506b.h */ 0x0000006b
 #define NV10_CHANNEL_DMA                              /* cl506b.h */ 0x0000006e
 #define NV17_CHANNEL_DMA                              /* cl506b.h */ 0x0000176e
diff --git a/drivers/gpu/drm/nouveau/include/nvif/clb069.h b/drivers/gpu/drm/nouveau/include/nvif/clb069.h
new file mode 100644 (file)
index 0000000..eef5d02
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __NVIF_CLB069_H__
+#define __NVIF_CLB069_H__
+struct nvif_clb069_v0 {
+       __u8  version;
+       __u8  pad01[3];
+       __u32 entries;
+       __u32 get;
+       __u32 put;
+};
+
+#define NVB069_V0_NTFY_FAULT                                                0x00
+#endif
index 1cb465a..97322f9 100644 (file)
@@ -13,6 +13,8 @@ struct nvkm_fault {
        struct nvkm_event event;
 
        struct nvkm_notify nrpfb;
+
+       struct nvkm_device_oclass user;
 };
 
 struct nvkm_fault_data {
index 092ddc4..03c6d9a 100644 (file)
@@ -365,16 +365,15 @@ nvkm_udevice_child_get(struct nvkm_object *object, int index,
        }
 
        if (!sclass) {
-               switch (index) {
-               case 0: sclass = &nvkm_control_oclass; break;
-               case 1:
-                       if (!device->mmu)
-                               return -EINVAL;
+               if (index-- == 0)
+                       sclass = &nvkm_control_oclass;
+               else if (device->mmu && index-- == 0)
                        sclass = &device->mmu->user;
-                       break;
-               default:
+               else if (device->fault && index-- == 0)
+                       sclass = &device->fault->user;
+               else
                        return -EINVAL;
-               }
+
                oclass->base = sclass->base;
        }
 
index 801fd5c..4258626 100644 (file)
@@ -1,4 +1,5 @@
 nvkm-y += nvkm/subdev/fault/base.o
+nvkm-y += nvkm/subdev/fault/user.o
 nvkm-y += nvkm/subdev/fault/gp100.o
 nvkm-y += nvkm/subdev/fault/gv100.o
 nvkm-y += nvkm/subdev/fault/tu102.o
index 4ba1e21..ca25156 100644 (file)
@@ -176,5 +176,7 @@ nvkm_fault_new_(const struct nvkm_fault_func *func, struct nvkm_device *device,
                return -ENOMEM;
        nvkm_subdev_ctor(&nvkm_fault, device, index, &fault->subdev);
        fault->func = func;
+       fault->user.ctor = nvkm_ufault_new;
+       fault->user.base = func->user.base;
        return 0;
 }
index 8fb96fe..4f3c4e0 100644 (file)
@@ -23,6 +23,8 @@
 
 #include <subdev/mc.h>
 
+#include <nvif/class.h>
+
 static void
 gp100_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable)
 {
@@ -69,6 +71,7 @@ gp100_fault = {
        .buffer.init = gp100_fault_buffer_init,
        .buffer.fini = gp100_fault_buffer_fini,
        .buffer.intr = gp100_fault_buffer_intr,
+       .user = { { 0, 0, MAXWELL_FAULT_BUFFER_A }, 0 },
 };
 
 int
index 8ca8b28..975e66a 100644 (file)
@@ -34,7 +34,14 @@ struct nvkm_fault_func {
                void (*fini)(struct nvkm_fault_buffer *);
                void (*intr)(struct nvkm_fault_buffer *, bool enable);
        } buffer;
+       struct {
+               struct nvkm_sclass base;
+               int rp;
+       } user;
 };
 
 int gv100_fault_oneinit(struct nvkm_fault *);
+
+int nvkm_ufault_new(struct nvkm_device *, const struct nvkm_oclass *,
+                   void *, u32, struct nvkm_object **);
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c
new file mode 100644 (file)
index 0000000..ac835c9
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * 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 "priv.h"
+
+#include <core/memory.h>
+#include <subdev/mmu.h>
+
+#include <nvif/clb069.h>
+#include <nvif/unpack.h>
+
+static int
+nvkm_ufault_map(struct nvkm_object *object, void *argv, u32 argc,
+               enum nvkm_object_map *type, u64 *addr, u64 *size)
+{
+       struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
+       struct nvkm_device *device = buffer->fault->subdev.device;
+       *type = NVKM_OBJECT_MAP_IO;
+       *addr = device->func->resource_addr(device, 3) + buffer->addr;
+       *size = nvkm_memory_size(buffer->mem);
+       return 0;
+}
+
+static int
+nvkm_ufault_ntfy(struct nvkm_object *object, u32 type,
+                struct nvkm_event **pevent)
+{
+       struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
+       if (type == NVB069_V0_NTFY_FAULT) {
+               *pevent = &buffer->fault->event;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int
+nvkm_ufault_fini(struct nvkm_object *object, bool suspend)
+{
+       struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
+       buffer->fault->func->buffer.fini(buffer);
+       return 0;
+}
+
+static int
+nvkm_ufault_init(struct nvkm_object *object)
+{
+       struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
+       buffer->fault->func->buffer.init(buffer);
+       return 0;
+}
+
+static void *
+nvkm_ufault_dtor(struct nvkm_object *object)
+{
+       return NULL;
+}
+
+static const struct nvkm_object_func
+nvkm_ufault = {
+       .dtor = nvkm_ufault_dtor,
+       .init = nvkm_ufault_init,
+       .fini = nvkm_ufault_fini,
+       .ntfy = nvkm_ufault_ntfy,
+       .map = nvkm_ufault_map,
+};
+
+int
+nvkm_ufault_new(struct nvkm_device *device, const struct nvkm_oclass *oclass,
+               void *argv, u32 argc, struct nvkm_object **pobject)
+{
+       union {
+               struct nvif_clb069_v0 v0;
+       } *args = argv;
+       struct nvkm_fault *fault = device->fault;
+       struct nvkm_fault_buffer *buffer = fault->buffer[fault->func->user.rp];
+       int ret = -ENOSYS;
+
+       if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) {
+               args->v0.entries = buffer->entries;
+               args->v0.get = buffer->get;
+               args->v0.put = buffer->put;
+       } else
+               return ret;
+
+       nvkm_object_ctor(&nvkm_ufault, oclass, &buffer->object);
+       *pobject = &buffer->object;
+       return 0;
+}