aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2018-05-08 06:39:47 -0400
committerBen Skeggs <bskeggs@redhat.com>2018-05-18 01:01:38 -0400
commit8b811951c604e417b4511e3d17a75bb8c84b8f08 (patch)
tree60988ef26e5fb89bcae1d501168db54adeada4c3
parent013b7b37739ca883b2dd5ef979e0e250ac3dafc1 (diff)
drm/nouveau/fault/gv100: initial support
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/base.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c206
4 files changed, 213 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h
index 8e9bc30fe65d..5a77498fe6a0 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h
@@ -1,15 +1,18 @@
1#ifndef __NVKM_FAULT_H__ 1#ifndef __NVKM_FAULT_H__
2#define __NVKM_FAULT_H__ 2#define __NVKM_FAULT_H__
3#include <core/subdev.h> 3#include <core/subdev.h>
4#include <core/notify.h>
4 5
5struct nvkm_fault { 6struct nvkm_fault {
6 const struct nvkm_fault_func *func; 7 const struct nvkm_fault_func *func;
7 struct nvkm_subdev subdev; 8 struct nvkm_subdev subdev;
8 9
9 struct nvkm_fault_buffer *buffer[1]; 10 struct nvkm_fault_buffer *buffer[2];
10 int buffer_nr; 11 int buffer_nr;
11 12
12 struct nvkm_event event; 13 struct nvkm_event event;
14
15 struct nvkm_notify nrpfb;
13}; 16};
14 17
15struct nvkm_fault_data { 18struct nvkm_fault_data {
@@ -26,4 +29,5 @@ struct nvkm_fault_data {
26}; 29};
27 30
28int gp100_fault_new(struct nvkm_device *, int, struct nvkm_fault **); 31int gp100_fault_new(struct nvkm_device *, int, struct nvkm_fault **);
32int gv100_fault_new(struct nvkm_device *, int, struct nvkm_fault **);
29#endif 33#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index 6aaa3d9cb88c..7f0385dbed06 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -2401,6 +2401,7 @@ nv140_chipset = {
2401 .bios = nvkm_bios_new, 2401 .bios = nvkm_bios_new,
2402 .bus = gf100_bus_new, 2402 .bus = gf100_bus_new,
2403 .devinit = gv100_devinit_new, 2403 .devinit = gv100_devinit_new,
2404 .fault = gv100_fault_new,
2404 .fb = gv100_fb_new, 2405 .fb = gv100_fb_new,
2405 .fuse = gm107_fuse_new, 2406 .fuse = gm107_fuse_new,
2406 .gpio = gk104_gpio_new, 2407 .gpio = gk104_gpio_new,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild
index 807ea402a162..45bb46fb0929 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/Kbuild
@@ -1,2 +1,3 @@
1nvkm-y += nvkm/subdev/fault/base.o 1nvkm-y += nvkm/subdev/fault/base.o
2nvkm-y += nvkm/subdev/fault/gp100.o 2nvkm-y += nvkm/subdev/fault/gp100.o
3nvkm-y += nvkm/subdev/fault/gv100.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c
new file mode 100644
index 000000000000..73c7728b5969
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c
@@ -0,0 +1,206 @@
1/*
2 * Copyright 2018 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22#include "priv.h"
23
24#include <core/memory.h>
25#include <subdev/mmu.h>
26#include <engine/fifo.h>
27
28static void
29gv100_fault_buffer_process(struct nvkm_fault_buffer *buffer)
30{
31 struct nvkm_device *device = buffer->fault->subdev.device;
32 struct nvkm_memory *mem = buffer->mem;
33 const u32 foff = buffer->id * 0x14;
34 u32 get = nvkm_rd32(device, 0x100e2c + foff);
35 u32 put = nvkm_rd32(device, 0x100e30 + foff);
36 if (put == get)
37 return;
38
39 nvkm_kmap(mem);
40 while (get != put) {
41 const u32 base = get * buffer->fault->func->buffer.entry_size;
42 const u32 instlo = nvkm_ro32(mem, base + 0x00);
43 const u32 insthi = nvkm_ro32(mem, base + 0x04);
44 const u32 addrlo = nvkm_ro32(mem, base + 0x08);
45 const u32 addrhi = nvkm_ro32(mem, base + 0x0c);
46 const u32 timelo = nvkm_ro32(mem, base + 0x10);
47 const u32 timehi = nvkm_ro32(mem, base + 0x14);
48 const u32 info0 = nvkm_ro32(mem, base + 0x18);
49 const u32 info1 = nvkm_ro32(mem, base + 0x1c);
50 struct nvkm_fault_data info;
51
52 if (++get == buffer->entries)
53 get = 0;
54 nvkm_wr32(device, 0x100e2c + foff, get);
55
56 info.addr = ((u64)addrhi << 32) | addrlo;
57 info.inst = ((u64)insthi << 32) | instlo;
58 info.time = ((u64)timehi << 32) | timelo;
59 info.engine = (info0 & 0x000000ff);
60 info.valid = (info1 & 0x80000000) >> 31;
61 info.gpc = (info1 & 0x1f000000) >> 24;
62 info.hub = (info1 & 0x00100000) >> 20;
63 info.access = (info1 & 0x000f0000) >> 16;
64 info.client = (info1 & 0x00007f00) >> 8;
65 info.reason = (info1 & 0x0000001f);
66
67 nvkm_fifo_fault(device->fifo, &info);
68 }
69 nvkm_done(mem);
70}
71
72static void
73gv100_fault_buffer_fini(struct nvkm_fault_buffer *buffer)
74{
75 struct nvkm_device *device = buffer->fault->subdev.device;
76 const u32 intr = buffer->id ? 0x08000000 : 0x20000000;
77 const u32 foff = buffer->id * 0x14;
78
79 nvkm_mask(device, 0x100a34, intr, intr);
80 nvkm_mask(device, 0x100e34 + foff, 0x80000000, 0x00000000);
81}
82
83static void
84gv100_fault_buffer_init(struct nvkm_fault_buffer *buffer)
85{
86 struct nvkm_device *device = buffer->fault->subdev.device;
87 const u32 intr = buffer->id ? 0x08000000 : 0x20000000;
88 const u32 foff = buffer->id * 0x14;
89
90 nvkm_mask(device, 0x100e34 + foff, 0xc0000000, 0x40000000);
91 nvkm_wr32(device, 0x100e28 + foff, upper_32_bits(buffer->vma->addr));
92 nvkm_wr32(device, 0x100e24 + foff, lower_32_bits(buffer->vma->addr));
93 nvkm_mask(device, 0x100e34 + foff, 0x80000000, 0x80000000);
94 nvkm_mask(device, 0x100a2c, intr, intr);
95}
96
97static u32
98gv100_fault_buffer_entries(struct nvkm_fault_buffer *buffer)
99{
100 struct nvkm_device *device = buffer->fault->subdev.device;
101 const u32 foff = buffer->id * 0x14;
102 nvkm_mask(device, 0x100e34 + foff, 0x40000000, 0x40000000);
103 return nvkm_rd32(device, 0x100e34 + foff) & 0x000fffff;
104}
105
106static int
107gv100_fault_ntfy_nrpfb(struct nvkm_notify *notify)
108{
109 struct nvkm_fault *fault = container_of(notify, typeof(*fault), nrpfb);
110 gv100_fault_buffer_process(fault->buffer[0]);
111 return NVKM_NOTIFY_KEEP;
112}
113
114static void
115gv100_fault_intr_fault(struct nvkm_fault *fault)
116{
117 struct nvkm_subdev *subdev = &fault->subdev;
118 struct nvkm_device *device = subdev->device;
119 struct nvkm_fault_data info;
120 const u32 addrlo = nvkm_rd32(device, 0x100e4c);
121 const u32 addrhi = nvkm_rd32(device, 0x100e50);
122 const u32 info0 = nvkm_rd32(device, 0x100e54);
123 const u32 insthi = nvkm_rd32(device, 0x100e58);
124 const u32 info1 = nvkm_rd32(device, 0x100e5c);
125
126 info.addr = ((u64)addrhi << 32) | addrlo;
127 info.inst = ((u64)insthi << 32) | (info0 & 0xfffff000);
128 info.time = 0;
129 info.engine = (info0 & 0x000000ff);
130 info.valid = (info1 & 0x80000000) >> 31;
131 info.gpc = (info1 & 0x1f000000) >> 24;
132 info.hub = (info1 & 0x00100000) >> 20;
133 info.access = (info1 & 0x000f0000) >> 16;
134 info.client = (info1 & 0x00007f00) >> 8;
135 info.reason = (info1 & 0x0000001f);
136
137 nvkm_fifo_fault(device->fifo, &info);
138}
139
140static void
141gv100_fault_intr(struct nvkm_fault *fault)
142{
143 struct nvkm_subdev *subdev = &fault->subdev;
144 struct nvkm_device *device = subdev->device;
145 u32 stat = nvkm_rd32(device, 0x100a20);
146
147 if (stat & 0x80000000) {
148 gv100_fault_intr_fault(fault);
149 nvkm_wr32(device, 0x100e60, 0x80000000);
150 stat &= ~0x80000000;
151 }
152
153 if (stat & 0x20000000) {
154 if (fault->buffer[0]) {
155 nvkm_event_send(&fault->event, 1, 0, NULL, 0);
156 stat &= ~0x20000000;
157 }
158 }
159
160 if (stat) {
161 nvkm_debug(subdev, "intr %08x\n", stat);
162 }
163}
164
165static void
166gv100_fault_fini(struct nvkm_fault *fault)
167{
168 nvkm_notify_put(&fault->nrpfb);
169 nvkm_mask(fault->subdev.device, 0x100a34, 0x80000000, 0x80000000);
170}
171
172static void
173gv100_fault_init(struct nvkm_fault *fault)
174{
175 nvkm_mask(fault->subdev.device, 0x100a2c, 0x80000000, 0x80000000);
176 nvkm_notify_get(&fault->nrpfb);
177}
178
179static const struct nvkm_fault_func
180gv100_fault = {
181 .init = gv100_fault_init,
182 .fini = gv100_fault_fini,
183 .intr = gv100_fault_intr,
184 .buffer.nr = 2,
185 .buffer.entry_size = 32,
186 .buffer.entries = gv100_fault_buffer_entries,
187 .buffer.init = gv100_fault_buffer_init,
188 .buffer.fini = gv100_fault_buffer_fini,
189};
190
191int
192gv100_fault_new(struct nvkm_device *device, int index,
193 struct nvkm_fault **pfault)
194{
195 struct nvkm_fault *fault;
196 int ret;
197
198 ret = nvkm_fault_new_(&gv100_fault, device, index, &fault);
199 *pfault = fault;
200 if (ret)
201 return ret;
202
203 return nvkm_notify_init(&fault->buffer[0]->object, &fault->event,
204 gv100_fault_ntfy_nrpfb, false, NULL, 0, 0,
205 &fault->nrpfb);
206}