summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/class.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/clb069.h8
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/fault.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/base.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/user.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fault/Kbuild4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fault/base.c116
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fault/gp100.c61
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fault/priv.h29
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fault/user.c136
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fault/user.h7
11 files changed, 371 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h
index d08da82ba7ed..d88ee6e60a1a 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/class.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/class.h
@@ -34,6 +34,8 @@
#define NV04_DISP /* cl0046.h */ 0x00000046
+#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
index 000000000000..b0d509fd8631
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/clb069.h
@@ -0,0 +1,8 @@
+#ifndef __NVIF_CLB069_H__
+#define __NVIF_CLB069_H__
+
+struct nvb069_vn {
+};
+
+#define NVB069_VN_NTFY_FAULT 0x00
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fault.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fault.h
index 398ca5a02eee..08893f13e2f9 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fault.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fault.h
@@ -1,4 +1,5 @@
#ifndef __NVKM_FAULT_H__
#define __NVKM_FAULT_H__
#include <core/engine.h>
+int gp100_fault_new(struct nvkm_device *, int, struct nvkm_engine **);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index 4fb3dd63cbc0..548a5d2712c1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -2179,6 +2179,7 @@ nv130_chipset = {
.ce[5] = gp100_ce_new,
.dma = gf119_dma_new,
.disp = gp100_disp_new,
+ .fault = gp100_fault_new,
.fifo = gp100_fifo_new,
.gr = gp100_gr_new,
.sw = gf100_sw_new,
@@ -2211,6 +2212,7 @@ nv132_chipset = {
.ce[3] = gp102_ce_new,
.disp = gp102_disp_new,
.dma = gf119_dma_new,
+ .fault = gp100_fault_new,
.fifo = gp100_fifo_new,
.gr = gp102_gr_new,
.nvdec = gp102_nvdec_new,
@@ -2245,6 +2247,7 @@ nv134_chipset = {
.ce[3] = gp102_ce_new,
.disp = gp102_disp_new,
.dma = gf119_dma_new,
+ .fault = gp100_fault_new,
.fifo = gp100_fifo_new,
.gr = gp102_gr_new,
.nvdec = gp102_nvdec_new,
@@ -2279,6 +2282,7 @@ nv136_chipset = {
.ce[3] = gp102_ce_new,
.disp = gp102_disp_new,
.dma = gf119_dma_new,
+ .fault = gp100_fault_new,
.fifo = gp100_fifo_new,
.gr = gp102_gr_new,
.nvdec = gp102_nvdec_new,
@@ -2313,6 +2317,7 @@ nv137_chipset = {
.ce[3] = gp102_ce_new,
.disp = gp102_disp_new,
.dma = gf119_dma_new,
+ .fault = gp100_fault_new,
.fifo = gp100_fifo_new,
.gr = gp107_gr_new,
.nvdec = gp102_nvdec_new,
@@ -2338,6 +2343,7 @@ nv13b_chipset = {
.top = gk104_top_new,
.ce[2] = gp102_ce_new,
.dma = gf119_dma_new,
+ .fault = gp100_fault_new,
.fifo = gp10b_fifo_new,
.gr = gp10b_gr_new,
.sw = gf100_sw_new,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
index 513ee6b79553..7c4abe71a449 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
@@ -274,6 +274,7 @@ nvkm_udevice_child_get(struct nvkm_object *object, int index,
struct nvkm_device *device = udev->device;
struct nvkm_engine *engine;
u64 mask = (1ULL << NVKM_ENGINE_DMAOBJ) |
+ (1ULL << NVKM_ENGINE_FAULT) |
(1ULL << NVKM_ENGINE_FIFO) |
(1ULL << NVKM_ENGINE_DISP) |
(1ULL << NVKM_ENGINE_PM);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fault/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fault/Kbuild
index e69de29bb2d1..627d74eaba1d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fault/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fault/Kbuild
@@ -0,0 +1,4 @@
+nvkm-y += nvkm/engine/fault/base.o
+nvkm-y += nvkm/engine/fault/gp100.o
+
+nvkm-y += nvkm/engine/fault/user.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fault/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fault/base.c
new file mode 100644
index 000000000000..a970012e84c8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fault/base.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2017 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 "user.h"
+
+#include <core/client.h>
+#include <core/notify.h>
+
+static int
+nvkm_fault_ntfy_ctor(struct nvkm_object *object, void *data, u32 size,
+ struct nvkm_notify *notify)
+{
+ if (size == 0) {
+ notify->size = 0;
+ notify->types = 1;
+ notify->index = 0;
+ return 0;
+ }
+ return -ENOSYS;
+}
+
+static const struct nvkm_event_func
+nvkm_fault_ntfy = {
+ .ctor = nvkm_fault_ntfy_ctor,
+};
+
+static int
+nvkm_fault_class_new(struct nvkm_device *device,
+ const struct nvkm_oclass *oclass, void *data, u32 size,
+ struct nvkm_object **pobject)
+{
+ struct nvkm_fault *fault = nvkm_fault(device->fault);
+ if (!oclass->client->super)
+ return -EACCES;
+ return nvkm_ufault_new(fault, oclass, data, size, pobject);
+}
+
+static const struct nvkm_device_oclass
+nvkm_fault_class = {
+ .ctor = nvkm_fault_class_new,
+};
+
+static int
+nvkm_fault_class_get(struct nvkm_oclass *oclass, int index,
+ const struct nvkm_device_oclass **class)
+{
+ struct nvkm_fault *fault = nvkm_fault(oclass->engine);
+ if (index == 0) {
+ oclass->base.oclass = fault->func->oclass;
+ oclass->base.minver = -1;
+ oclass->base.maxver = -1;
+ *class = &nvkm_fault_class;
+ }
+ return 1;
+}
+
+static void
+nvkm_fault_intr(struct nvkm_engine *engine)
+{
+ struct nvkm_fault *fault = nvkm_fault(engine);
+ nvkm_event_send(&fault->event, 1, 0, NULL, 0);
+}
+
+static void *
+nvkm_fault_dtor(struct nvkm_engine *engine)
+{
+ struct nvkm_fault *fault = nvkm_fault(engine);
+ nvkm_event_fini(&fault->event);
+ return fault;
+}
+
+static const struct nvkm_engine_func
+nvkm_fault = {
+ .dtor = nvkm_fault_dtor,
+ .intr = nvkm_fault_intr,
+ .base.sclass = nvkm_fault_class_get,
+};
+
+int
+nvkm_fault_new_(const struct nvkm_fault_func *func, struct nvkm_device *device,
+ int index, struct nvkm_engine **pengine)
+{
+ struct nvkm_fault *fault;
+ int ret;
+
+ if (!(fault = kzalloc(sizeof(*fault), GFP_KERNEL)))
+ return -ENOMEM;
+ *pengine = &fault->engine;
+ fault->func = func;
+
+ ret = nvkm_engine_ctor(&nvkm_fault, device, index, true,
+ &fault->engine);
+ if (ret)
+ return ret;
+
+ return nvkm_event_init(&nvkm_fault_ntfy, 1, 1, &fault->event);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fault/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fault/gp100.c
new file mode 100644
index 000000000000..384bf6069ed9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fault/gp100.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2017 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 <nvif/class.h>
+
+static void
+gp100_fault_fini(struct nvkm_fault *fault)
+{
+ struct nvkm_device *device = fault->engine.subdev.device;
+ nvkm_mask(device, 0x002a70, 0x00000001, 0x00000000);
+}
+
+static void
+gp100_fault_init(struct nvkm_fault *fault)
+{
+ struct nvkm_device *device = fault->engine.subdev.device;
+ nvkm_wr32(device, 0x002a74, upper_32_bits(fault->vma.offset));
+ nvkm_wr32(device, 0x002a70, lower_32_bits(fault->vma.offset));
+ nvkm_mask(device, 0x002a70, 0x00000001, 0x00000001);
+}
+
+static u32
+gp100_fault_size(struct nvkm_fault *fault)
+{
+ return nvkm_rd32(fault->engine.subdev.device, 0x002a78) * 32;
+}
+
+static const struct nvkm_fault_func
+gp100_fault = {
+ .size = gp100_fault_size,
+ .init = gp100_fault_init,
+ .fini = gp100_fault_fini,
+ .oclass = MAXWELL_FAULT_BUFFER_A,
+};
+
+int
+gp100_fault_new(struct nvkm_device *device, int index,
+ struct nvkm_engine **pengine)
+{
+ return nvkm_fault_new_(&gp100_fault, device, index, pengine);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fault/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fault/priv.h
new file mode 100644
index 000000000000..5f876a37bdb8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fault/priv.h
@@ -0,0 +1,29 @@
+#ifndef __NVKM_FAULT_PRIV_H__
+#define __NVKM_FAULT_PRIV_H__
+#define nvkm_fault(p) container_of((p), struct nvkm_fault, engine)
+#include <engine/fault.h>
+
+#include <core/event.h>
+#include <subdev/mmu.h>
+
+struct nvkm_fault {
+ const struct nvkm_fault_func *func;
+ struct nvkm_engine engine;
+
+ struct nvkm_event event;
+
+ struct nvkm_object *user;
+ struct nvkm_memory *mem;
+ struct nvkm_vma vma;
+};
+
+struct nvkm_fault_func {
+ u32 (*size)(struct nvkm_fault *);
+ void (*init)(struct nvkm_fault *);
+ void (*fini)(struct nvkm_fault *);
+ s32 oclass;
+};
+
+int nvkm_fault_new_(const struct nvkm_fault_func *, struct nvkm_device *,
+ int, struct nvkm_engine **);
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fault/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/fault/user.c
new file mode 100644
index 000000000000..e4c152cd9016
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fault/user.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2017 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"
+
+#include <core/memory.h>
+#include <subdev/bar.h>
+#include <subdev/fb.h>
+
+#include <nvif/clb069.h>
+#include <nvif/unpack.h>
+
+static int
+nvkm_ufault_map(struct nvkm_object *object, u64 *addr, u32 *size)
+{
+ struct nvkm_fault *fault = nvkm_fault(object->engine);
+ struct nvkm_device *device = fault->engine.subdev.device;
+ *addr = device->func->resource_addr(device, 3) + fault->vma.offset;
+ *size = nvkm_memory_size(fault->mem);
+ return 0;
+}
+
+static int
+nvkm_ufault_ntfy(struct nvkm_object *object, u32 type,
+ struct nvkm_event **pevent)
+{
+ struct nvkm_fault *fault = nvkm_fault(object->engine);
+ if (type == NVB069_VN_NTFY_FAULT) {
+ *pevent = &fault->event;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int
+nvkm_ufault_fini(struct nvkm_object *object, bool suspend)
+{
+ struct nvkm_fault *fault = nvkm_fault(object->engine);
+ fault->func->fini(fault);
+ return 0;
+}
+
+static int
+nvkm_ufault_init(struct nvkm_object *object)
+{
+ struct nvkm_fault *fault = nvkm_fault(object->engine);
+ fault->func->init(fault);
+ return 0;
+}
+
+static void *
+nvkm_ufault_dtor(struct nvkm_object *object)
+{
+ struct nvkm_fault *fault = nvkm_fault(object->engine);
+
+ mutex_lock(&fault->engine.subdev.mutex);
+ if (fault->user == object)
+ fault->user = NULL;
+ mutex_unlock(&fault->engine.subdev.mutex);
+
+ if (fault->vma.node) {
+ nvkm_vm_unmap(&fault->vma);
+ nvkm_vm_put(&fault->vma);
+ }
+
+ nvkm_memory_del(&fault->mem);
+ return object;
+}
+
+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_fault *fault, const struct nvkm_oclass *oclass,
+ void *argv, u32 argc, struct nvkm_object **pobject)
+{
+ union {
+ struct nvb069_vn vn;
+ } *args = argv;
+ struct nvkm_subdev *subdev = &fault->engine.subdev;
+ struct nvkm_device *device = subdev->device;
+ struct nvkm_vm *bar2 = nvkm_bar_kmap(device->bar);
+ u32 size = fault->func->size(fault);
+ int ret = -ENOSYS;
+
+ if ((ret = nvif_unvers(ret, &argv, &argc, args->vn)))
+ return ret;
+
+ ret = nvkm_object_new_(&nvkm_ufault, oclass, NULL, 0, pobject);
+ if (ret)
+ return ret;
+
+ ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, size,
+ 0x1000, false, &fault->mem);
+ if (ret)
+ return ret;
+
+ ret = nvkm_vm_get(bar2, nvkm_memory_size(fault->mem), 12,
+ NV_MEM_ACCESS_RW, &fault->vma);
+ if (ret)
+ return ret;
+
+ nvkm_memory_map(fault->mem, &fault->vma, 0);
+
+ mutex_lock(&subdev->mutex);
+ if (!fault->user)
+ fault->user = *pobject;
+ else
+ ret = -EBUSY;
+ mutex_unlock(&subdev->mutex);
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fault/user.h b/drivers/gpu/drm/nouveau/nvkm/engine/fault/user.h
new file mode 100644
index 000000000000..70c03bbbc0b2
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fault/user.h
@@ -0,0 +1,7 @@
+#ifndef __NVKM_FAULT_USER_H__
+#define __NVKM_FAULT_USER_H__
+#include "priv.h"
+
+int nvkm_ufault_new(struct nvkm_fault *, const struct nvkm_oclass *,
+ void *, u32, struct nvkm_object **);
+#endif