1 /*
2 * Copyright 2012 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 * Authors: Ben Skeggs
23 */
24 #include "nv50.h"
25
26 #include <core/client.h>
27 #include <core/gpuobj.h>
28 #include <engine/fifo.h>
29
30 u64
nv50_gr_units(struct nvkm_gr * gr)31 nv50_gr_units(struct nvkm_gr *gr)
32 {
33 return nvkm_rd32(gr->engine.subdev.device, 0x1540);
34 }
35
36 /*******************************************************************************
37 * Graphics object classes
38 ******************************************************************************/
39
40 static int
nv50_gr_object_bind(struct nvkm_object * object,struct nvkm_gpuobj * parent,int align,struct nvkm_gpuobj ** pgpuobj)41 nv50_gr_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
42 int align, struct nvkm_gpuobj **pgpuobj)
43 {
44 int ret = nvkm_gpuobj_new(object->engine->subdev.device, 16,
45 align, false, parent, pgpuobj);
46 if (ret == 0) {
47 nvkm_kmap(*pgpuobj);
48 nvkm_wo32(*pgpuobj, 0x00, object->oclass);
49 nvkm_wo32(*pgpuobj, 0x04, 0x00000000);
50 nvkm_wo32(*pgpuobj, 0x08, 0x00000000);
51 nvkm_wo32(*pgpuobj, 0x0c, 0x00000000);
52 nvkm_done(*pgpuobj);
53 }
54 return ret;
55 }
56
57 const struct nvkm_object_func
58 nv50_gr_object = {
59 .bind = nv50_gr_object_bind,
60 };
61
62 /*******************************************************************************
63 * PGRAPH context
64 ******************************************************************************/
65
66 static int
nv50_gr_chan_bind(struct nvkm_object * object,struct nvkm_gpuobj * parent,int align,struct nvkm_gpuobj ** pgpuobj)67 nv50_gr_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
68 int align, struct nvkm_gpuobj **pgpuobj)
69 {
70 struct nv50_gr *gr = nv50_gr_chan(object)->gr;
71 int ret = nvkm_gpuobj_new(gr->base.engine.subdev.device, gr->size,
72 align, true, parent, pgpuobj);
73 if (ret == 0) {
74 nvkm_kmap(*pgpuobj);
75 nv50_grctx_fill(gr->base.engine.subdev.device, *pgpuobj);
76 nvkm_done(*pgpuobj);
77 }
78 return ret;
79 }
80
81 static const struct nvkm_object_func
82 nv50_gr_chan = {
83 .bind = nv50_gr_chan_bind,
84 };
85
86 int
nv50_gr_chan_new(struct nvkm_gr * base,struct nvkm_fifo_chan * fifoch,const struct nvkm_oclass * oclass,struct nvkm_object ** pobject)87 nv50_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
88 const struct nvkm_oclass *oclass, struct nvkm_object **pobject)
89 {
90 struct nv50_gr *gr = nv50_gr(base);
91 struct nv50_gr_chan *chan;
92
93 if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
94 return -ENOMEM;
95 nvkm_object_ctor(&nv50_gr_chan, oclass, &chan->object);
96 chan->gr = gr;
97 *pobject = &chan->object;
98 return 0;
99 }
100
101 /*******************************************************************************
102 * PGRAPH engine/subdev functions
103 ******************************************************************************/
104
105 static const struct nvkm_bitfield nv50_mp_exec_errors[] = {
106 { 0x01, "STACK_UNDERFLOW" },
107 { 0x02, "STACK_MISMATCH" },
108 { 0x04, "QUADON_ACTIVE" },
109 { 0x08, "TIMEOUT" },
110 { 0x10, "INVALID_OPCODE" },
111 { 0x20, "PM_OVERFLOW" },
112 { 0x40, "BREAKPOINT" },
113 {}
114 };
115
116 static const struct nvkm_bitfield nv50_mpc_traps[] = {
117 { 0x0000001, "LOCAL_LIMIT_READ" },
118 { 0x0000010, "LOCAL_LIMIT_WRITE" },
119 { 0x0000040, "STACK_LIMIT" },
120 { 0x0000100, "GLOBAL_LIMIT_READ" },
121 { 0x0001000, "GLOBAL_LIMIT_WRITE" },
122 { 0x0010000, "MP0" },
123 { 0x0020000, "MP1" },
124 { 0x0040000, "GLOBAL_LIMIT_RED" },
125 { 0x0400000, "GLOBAL_LIMIT_ATOM" },
126 { 0x4000000, "MP2" },
127 {}
128 };
129
130 static const struct nvkm_bitfield nv50_tex_traps[] = {
131 { 0x00000001, "" }, /* any bit set? */
132 { 0x00000002, "FAULT" },
133 { 0x00000004, "STORAGE_TYPE_MISMATCH" },
134 { 0x00000008, "LINEAR_MISMATCH" },
135 { 0x00000020, "WRONG_MEMTYPE" },
136 {}
137 };
138
139 static const struct nvkm_bitfield nv50_gr_trap_m2mf[] = {
140 { 0x00000001, "NOTIFY" },
141 { 0x00000002, "IN" },
142 { 0x00000004, "OUT" },
143 {}
144 };
145
146 static const struct nvkm_bitfield nv50_gr_trap_vfetch[] = {
147 { 0x00000001, "FAULT" },
148 {}
149 };
150
151 static const struct nvkm_bitfield nv50_gr_trap_strmout[] = {
152 { 0x00000001, "FAULT" },
153 {}
154 };
155
156 static const struct nvkm_bitfield nv50_gr_trap_ccache[] = {
157 { 0x00000001, "FAULT" },
158 {}
159 };
160
161 /* There must be a *lot* of these. Will take some time to gather them up. */
162 const struct nvkm_enum nv50_data_error_names[] = {
163 { 0x00000003, "INVALID_OPERATION", NULL },
164 { 0x00000004, "INVALID_VALUE", NULL },
165 { 0x00000005, "INVALID_ENUM", NULL },
166 { 0x00000008, "INVALID_OBJECT", NULL },
167 { 0x00000009, "READ_ONLY_OBJECT", NULL },
168 { 0x0000000a, "SUPERVISOR_OBJECT", NULL },
169 { 0x0000000b, "INVALID_ADDRESS_ALIGNMENT", NULL },
170 { 0x0000000c, "INVALID_BITFIELD", NULL },
171 { 0x0000000d, "BEGIN_END_ACTIVE", NULL },
172 { 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT", NULL },
173 { 0x0000000f, "VIEWPORT_ID_NEEDS_GP", NULL },
174 { 0x00000010, "RT_DOUBLE_BIND", NULL },
175 { 0x00000011, "RT_TYPES_MISMATCH", NULL },
176 { 0x00000012, "RT_LINEAR_WITH_ZETA", NULL },
177 { 0x00000015, "FP_TOO_FEW_REGS", NULL },
178 { 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH", NULL },
179 { 0x00000017, "RT_LINEAR_WITH_MSAA", NULL },
180 { 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT", NULL },
181 { 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT", NULL },
182 { 0x0000001a, "RT_INVALID_ALIGNMENT", NULL },
183 { 0x0000001b, "SAMPLER_OVER_LIMIT", NULL },
184 { 0x0000001c, "TEXTURE_OVER_LIMIT", NULL },
185 { 0x0000001e, "GP_TOO_MANY_OUTPUTS", NULL },
186 { 0x0000001f, "RT_BPP128_WITH_MS8", NULL },
187 { 0x00000021, "Z_OUT_OF_BOUNDS", NULL },
188 { 0x00000023, "XY_OUT_OF_BOUNDS", NULL },
189 { 0x00000024, "VP_ZERO_INPUTS", NULL },
190 { 0x00000027, "CP_MORE_PARAMS_THAN_SHARED", NULL },
191 { 0x00000028, "CP_NO_REG_SPACE_STRIPED", NULL },
192 { 0x00000029, "CP_NO_REG_SPACE_PACKED", NULL },
193 { 0x0000002a, "CP_NOT_ENOUGH_WARPS", NULL },
194 { 0x0000002b, "CP_BLOCK_SIZE_MISMATCH", NULL },
195 { 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS", NULL },
196 { 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS", NULL },
197 { 0x0000002e, "CP_NO_BLOCKDIM_LATCH", NULL },
198 { 0x00000031, "ENG2D_FORMAT_MISMATCH", NULL },
199 { 0x0000003f, "PRIMITIVE_ID_NEEDS_GP", NULL },
200 { 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT", NULL },
201 { 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT", NULL },
202 { 0x00000046, "LAYER_ID_NEEDS_GP", NULL },
203 { 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT", NULL },
204 { 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT", NULL },
205 {}
206 };
207
208 static const struct nvkm_bitfield nv50_gr_intr_name[] = {
209 { 0x00000001, "NOTIFY" },
210 { 0x00000002, "COMPUTE_QUERY" },
211 { 0x00000010, "ILLEGAL_MTHD" },
212 { 0x00000020, "ILLEGAL_CLASS" },
213 { 0x00000040, "DOUBLE_NOTIFY" },
214 { 0x00001000, "CONTEXT_SWITCH" },
215 { 0x00010000, "BUFFER_NOTIFY" },
216 { 0x00100000, "DATA_ERROR" },
217 { 0x00200000, "TRAP" },
218 { 0x01000000, "SINGLE_STEP" },
219 {}
220 };
221
222 static const struct nvkm_bitfield nv50_gr_trap_prop[] = {
223 { 0x00000004, "SURF_WIDTH_OVERRUN" },
224 { 0x00000008, "SURF_HEIGHT_OVERRUN" },
225 { 0x00000010, "DST2D_FAULT" },
226 { 0x00000020, "ZETA_FAULT" },
227 { 0x00000040, "RT_FAULT" },
228 { 0x00000080, "CUDA_FAULT" },
229 { 0x00000100, "DST2D_STORAGE_TYPE_MISMATCH" },
230 { 0x00000200, "ZETA_STORAGE_TYPE_MISMATCH" },
231 { 0x00000400, "RT_STORAGE_TYPE_MISMATCH" },
232 { 0x00000800, "DST2D_LINEAR_MISMATCH" },
233 { 0x00001000, "RT_LINEAR_MISMATCH" },
234 {}
235 };
236
237 static void
nv50_gr_prop_trap(struct nv50_gr * gr,u32 ustatus_addr,u32 ustatus,u32 tp)238 nv50_gr_prop_trap(struct nv50_gr *gr, u32 ustatus_addr, u32 ustatus, u32 tp)
239 {
240 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
241 struct nvkm_device *device = subdev->device;
242 u32 e0c = nvkm_rd32(device, ustatus_addr + 0x04);
243 u32 e10 = nvkm_rd32(device, ustatus_addr + 0x08);
244 u32 e14 = nvkm_rd32(device, ustatus_addr + 0x0c);
245 u32 e18 = nvkm_rd32(device, ustatus_addr + 0x10);
246 u32 e1c = nvkm_rd32(device, ustatus_addr + 0x14);
247 u32 e20 = nvkm_rd32(device, ustatus_addr + 0x18);
248 u32 e24 = nvkm_rd32(device, ustatus_addr + 0x1c);
249 char msg[128];
250
251 /* CUDA memory: l[], g[] or stack. */
252 if (ustatus & 0x00000080) {
253 if (e18 & 0x80000000) {
254 /* g[] read fault? */
255 nvkm_error(subdev, "TRAP_PROP - TP %d - CUDA_FAULT - Global read fault at address %02x%08x\n",
256 tp, e14, e10 | ((e18 >> 24) & 0x1f));
257 e18 &= ~0x1f000000;
258 } else if (e18 & 0xc) {
259 /* g[] write fault? */
260 nvkm_error(subdev, "TRAP_PROP - TP %d - CUDA_FAULT - Global write fault at address %02x%08x\n",
261 tp, e14, e10 | ((e18 >> 7) & 0x1f));
262 e18 &= ~0x00000f80;
263 } else {
264 nvkm_error(subdev, "TRAP_PROP - TP %d - Unknown CUDA fault at address %02x%08x\n",
265 tp, e14, e10);
266 }
267 ustatus &= ~0x00000080;
268 }
269 if (ustatus) {
270 nvkm_snprintbf(msg, sizeof(msg), nv50_gr_trap_prop, ustatus);
271 nvkm_error(subdev, "TRAP_PROP - TP %d - %08x [%s] - "
272 "Address %02x%08x\n",
273 tp, ustatus, msg, e14, e10);
274 }
275 nvkm_error(subdev, "TRAP_PROP - TP %d - e0c: %08x, e18: %08x, e1c: %08x, e20: %08x, e24: %08x\n",
276 tp, e0c, e18, e1c, e20, e24);
277 }
278
279 static void
nv50_gr_mp_trap(struct nv50_gr * gr,int tpid,int display)280 nv50_gr_mp_trap(struct nv50_gr *gr, int tpid, int display)
281 {
282 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
283 struct nvkm_device *device = subdev->device;
284 u32 units = nvkm_rd32(device, 0x1540);
285 u32 addr, mp10, status, pc, oplow, ophigh;
286 char msg[128];
287 int i;
288 int mps = 0;
289 for (i = 0; i < 4; i++) {
290 if (!(units & 1 << (i+24)))
291 continue;
292 if (device->chipset < 0xa0)
293 addr = 0x408200 + (tpid << 12) + (i << 7);
294 else
295 addr = 0x408100 + (tpid << 11) + (i << 7);
296 mp10 = nvkm_rd32(device, addr + 0x10);
297 status = nvkm_rd32(device, addr + 0x14);
298 if (!status)
299 continue;
300 if (display) {
301 nvkm_rd32(device, addr + 0x20);
302 pc = nvkm_rd32(device, addr + 0x24);
303 oplow = nvkm_rd32(device, addr + 0x70);
304 ophigh = nvkm_rd32(device, addr + 0x74);
305 nvkm_snprintbf(msg, sizeof(msg),
306 nv50_mp_exec_errors, status);
307 nvkm_error(subdev, "TRAP_MP_EXEC - TP %d MP %d: "
308 "%08x [%s] at %06x warp %d, "
309 "opcode %08x %08x\n",
310 tpid, i, status, msg, pc & 0xffffff,
311 pc >> 24, oplow, ophigh);
312 }
313 nvkm_wr32(device, addr + 0x10, mp10);
314 nvkm_wr32(device, addr + 0x14, 0);
315 mps++;
316 }
317 if (!mps && display)
318 nvkm_error(subdev, "TRAP_MP_EXEC - TP %d: "
319 "No MPs claiming errors?\n", tpid);
320 }
321
322 static void
nv50_gr_tp_trap(struct nv50_gr * gr,int type,u32 ustatus_old,u32 ustatus_new,int display,const char * name)323 nv50_gr_tp_trap(struct nv50_gr *gr, int type, u32 ustatus_old,
324 u32 ustatus_new, int display, const char *name)
325 {
326 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
327 struct nvkm_device *device = subdev->device;
328 u32 units = nvkm_rd32(device, 0x1540);
329 int tps = 0;
330 int i, r;
331 char msg[128];
332 u32 ustatus_addr, ustatus;
333 for (i = 0; i < 16; i++) {
334 if (!(units & (1 << i)))
335 continue;
336 if (device->chipset < 0xa0)
337 ustatus_addr = ustatus_old + (i << 12);
338 else
339 ustatus_addr = ustatus_new + (i << 11);
340 ustatus = nvkm_rd32(device, ustatus_addr) & 0x7fffffff;
341 if (!ustatus)
342 continue;
343 tps++;
344 switch (type) {
345 case 6: /* texture error... unknown for now */
346 if (display) {
347 nvkm_error(subdev, "magic set %d:\n", i);
348 for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
349 nvkm_error(subdev, "\t%08x: %08x\n", r,
350 nvkm_rd32(device, r));
351 if (ustatus) {
352 nvkm_snprintbf(msg, sizeof(msg),
353 nv50_tex_traps, ustatus);
354 nvkm_error(subdev,
355 "%s - TP%d: %08x [%s]\n",
356 name, i, ustatus, msg);
357 ustatus = 0;
358 }
359 }
360 break;
361 case 7: /* MP error */
362 if (ustatus & 0x04030000) {
363 nv50_gr_mp_trap(gr, i, display);
364 ustatus &= ~0x04030000;
365 }
366 if (ustatus && display) {
367 nvkm_snprintbf(msg, sizeof(msg),
368 nv50_mpc_traps, ustatus);
369 nvkm_error(subdev, "%s - TP%d: %08x [%s]\n",
370 name, i, ustatus, msg);
371 ustatus = 0;
372 }
373 break;
374 case 8: /* PROP error */
375 if (display)
376 nv50_gr_prop_trap(
377 gr, ustatus_addr, ustatus, i);
378 ustatus = 0;
379 break;
380 }
381 if (ustatus) {
382 if (display)
383 nvkm_error(subdev, "%s - TP%d: Unhandled ustatus %08x\n", name, i, ustatus);
384 }
385 nvkm_wr32(device, ustatus_addr, 0xc0000000);
386 }
387
388 if (!tps && display)
389 nvkm_warn(subdev, "%s - No TPs claiming errors?\n", name);
390 }
391
392 static int
nv50_gr_trap_handler(struct nv50_gr * gr,u32 display,int chid,u64 inst,const char * name)393 nv50_gr_trap_handler(struct nv50_gr *gr, u32 display,
394 int chid, u64 inst, const char *name)
395 {
396 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
397 struct nvkm_device *device = subdev->device;
398 u32 status = nvkm_rd32(device, 0x400108);
399 u32 ustatus;
400 char msg[128];
401
402 if (!status && display) {
403 nvkm_error(subdev, "TRAP: no units reporting traps?\n");
404 return 1;
405 }
406
407 /* DISPATCH: Relays commands to other units and handles NOTIFY,
408 * COND, QUERY. If you get a trap from it, the command is still stuck
409 * in DISPATCH and you need to do something about it. */
410 if (status & 0x001) {
411 ustatus = nvkm_rd32(device, 0x400804) & 0x7fffffff;
412 if (!ustatus && display) {
413 nvkm_error(subdev, "TRAP_DISPATCH - no ustatus?\n");
414 }
415
416 nvkm_wr32(device, 0x400500, 0x00000000);
417
418 /* Known to be triggered by screwed up NOTIFY and COND... */
419 if (ustatus & 0x00000001) {
420 u32 addr = nvkm_rd32(device, 0x400808);
421 u32 subc = (addr & 0x00070000) >> 16;
422 u32 mthd = (addr & 0x00001ffc);
423 u32 datal = nvkm_rd32(device, 0x40080c);
424 u32 datah = nvkm_rd32(device, 0x400810);
425 u32 class = nvkm_rd32(device, 0x400814);
426 u32 r848 = nvkm_rd32(device, 0x400848);
427
428 nvkm_error(subdev, "TRAP DISPATCH_FAULT\n");
429 if (display && (addr & 0x80000000)) {
430 nvkm_error(subdev,
431 "ch %d [%010llx %s] subc %d "
432 "class %04x mthd %04x data %08x%08x "
433 "400808 %08x 400848 %08x\n",
434 chid, inst, name, subc, class, mthd,
435 datah, datal, addr, r848);
436 } else
437 if (display) {
438 nvkm_error(subdev, "no stuck command?\n");
439 }
440
441 nvkm_wr32(device, 0x400808, 0);
442 nvkm_wr32(device, 0x4008e8, nvkm_rd32(device, 0x4008e8) & 3);
443 nvkm_wr32(device, 0x400848, 0);
444 ustatus &= ~0x00000001;
445 }
446
447 if (ustatus & 0x00000002) {
448 u32 addr = nvkm_rd32(device, 0x40084c);
449 u32 subc = (addr & 0x00070000) >> 16;
450 u32 mthd = (addr & 0x00001ffc);
451 u32 data = nvkm_rd32(device, 0x40085c);
452 u32 class = nvkm_rd32(device, 0x400814);
453
454 nvkm_error(subdev, "TRAP DISPATCH_QUERY\n");
455 if (display && (addr & 0x80000000)) {
456 nvkm_error(subdev,
457 "ch %d [%010llx %s] subc %d "
458 "class %04x mthd %04x data %08x "
459 "40084c %08x\n", chid, inst, name,
460 subc, class, mthd, data, addr);
461 } else
462 if (display) {
463 nvkm_error(subdev, "no stuck command?\n");
464 }
465
466 nvkm_wr32(device, 0x40084c, 0);
467 ustatus &= ~0x00000002;
468 }
469
470 if (ustatus && display) {
471 nvkm_error(subdev, "TRAP_DISPATCH "
472 "(unknown %08x)\n", ustatus);
473 }
474
475 nvkm_wr32(device, 0x400804, 0xc0000000);
476 nvkm_wr32(device, 0x400108, 0x001);
477 status &= ~0x001;
478 if (!status)
479 return 0;
480 }
481
482 /* M2MF: Memory to memory copy engine. */
483 if (status & 0x002) {
484 u32 ustatus = nvkm_rd32(device, 0x406800) & 0x7fffffff;
485 if (display) {
486 nvkm_snprintbf(msg, sizeof(msg),
487 nv50_gr_trap_m2mf, ustatus);
488 nvkm_error(subdev, "TRAP_M2MF %08x [%s]\n",
489 ustatus, msg);
490 nvkm_error(subdev, "TRAP_M2MF %08x %08x %08x %08x\n",
491 nvkm_rd32(device, 0x406804),
492 nvkm_rd32(device, 0x406808),
493 nvkm_rd32(device, 0x40680c),
494 nvkm_rd32(device, 0x406810));
495 }
496
497 /* No sane way found yet -- just reset the bugger. */
498 nvkm_wr32(device, 0x400040, 2);
499 nvkm_wr32(device, 0x400040, 0);
500 nvkm_wr32(device, 0x406800, 0xc0000000);
501 nvkm_wr32(device, 0x400108, 0x002);
502 status &= ~0x002;
503 }
504
505 /* VFETCH: Fetches data from vertex buffers. */
506 if (status & 0x004) {
507 u32 ustatus = nvkm_rd32(device, 0x400c04) & 0x7fffffff;
508 if (display) {
509 nvkm_snprintbf(msg, sizeof(msg),
510 nv50_gr_trap_vfetch, ustatus);
511 nvkm_error(subdev, "TRAP_VFETCH %08x [%s]\n",
512 ustatus, msg);
513 nvkm_error(subdev, "TRAP_VFETCH %08x %08x %08x %08x\n",
514 nvkm_rd32(device, 0x400c00),
515 nvkm_rd32(device, 0x400c08),
516 nvkm_rd32(device, 0x400c0c),
517 nvkm_rd32(device, 0x400c10));
518 }
519
520 nvkm_wr32(device, 0x400c04, 0xc0000000);
521 nvkm_wr32(device, 0x400108, 0x004);
522 status &= ~0x004;
523 }
524
525 /* STRMOUT: DirectX streamout / OpenGL transform feedback. */
526 if (status & 0x008) {
527 ustatus = nvkm_rd32(device, 0x401800) & 0x7fffffff;
528 if (display) {
529 nvkm_snprintbf(msg, sizeof(msg),
530 nv50_gr_trap_strmout, ustatus);
531 nvkm_error(subdev, "TRAP_STRMOUT %08x [%s]\n",
532 ustatus, msg);
533 nvkm_error(subdev, "TRAP_STRMOUT %08x %08x %08x %08x\n",
534 nvkm_rd32(device, 0x401804),
535 nvkm_rd32(device, 0x401808),
536 nvkm_rd32(device, 0x40180c),
537 nvkm_rd32(device, 0x401810));
538 }
539
540 /* No sane way found yet -- just reset the bugger. */
541 nvkm_wr32(device, 0x400040, 0x80);
542 nvkm_wr32(device, 0x400040, 0);
543 nvkm_wr32(device, 0x401800, 0xc0000000);
544 nvkm_wr32(device, 0x400108, 0x008);
545 status &= ~0x008;
546 }
547
548 /* CCACHE: Handles code and c[] caches and fills them. */
549 if (status & 0x010) {
550 ustatus = nvkm_rd32(device, 0x405018) & 0x7fffffff;
551 if (display) {
552 nvkm_snprintbf(msg, sizeof(msg),
553 nv50_gr_trap_ccache, ustatus);
554 nvkm_error(subdev, "TRAP_CCACHE %08x [%s]\n",
555 ustatus, msg);
556 nvkm_error(subdev, "TRAP_CCACHE %08x %08x %08x %08x "
557 "%08x %08x %08x\n",
558 nvkm_rd32(device, 0x405000),
559 nvkm_rd32(device, 0x405004),
560 nvkm_rd32(device, 0x405008),
561 nvkm_rd32(device, 0x40500c),
562 nvkm_rd32(device, 0x405010),
563 nvkm_rd32(device, 0x405014),
564 nvkm_rd32(device, 0x40501c));
565 }
566
567 nvkm_wr32(device, 0x405018, 0xc0000000);
568 nvkm_wr32(device, 0x400108, 0x010);
569 status &= ~0x010;
570 }
571
572 /* Unknown, not seen yet... 0x402000 is the only trap status reg
573 * remaining, so try to handle it anyway. Perhaps related to that
574 * unknown DMA slot on tesla? */
575 if (status & 0x20) {
576 ustatus = nvkm_rd32(device, 0x402000) & 0x7fffffff;
577 if (display)
578 nvkm_error(subdev, "TRAP_UNKC04 %08x\n", ustatus);
579 nvkm_wr32(device, 0x402000, 0xc0000000);
580 /* no status modifiction on purpose */
581 }
582
583 /* TEXTURE: CUDA texturing units */
584 if (status & 0x040) {
585 nv50_gr_tp_trap(gr, 6, 0x408900, 0x408600, display,
586 "TRAP_TEXTURE");
587 nvkm_wr32(device, 0x400108, 0x040);
588 status &= ~0x040;
589 }
590
591 /* MP: CUDA execution engines. */
592 if (status & 0x080) {
593 nv50_gr_tp_trap(gr, 7, 0x408314, 0x40831c, display,
594 "TRAP_MP");
595 nvkm_wr32(device, 0x400108, 0x080);
596 status &= ~0x080;
597 }
598
599 /* PROP: Handles TP-initiated uncached memory accesses:
600 * l[], g[], stack, 2d surfaces, render targets. */
601 if (status & 0x100) {
602 nv50_gr_tp_trap(gr, 8, 0x408e08, 0x408708, display,
603 "TRAP_PROP");
604 nvkm_wr32(device, 0x400108, 0x100);
605 status &= ~0x100;
606 }
607
608 if (status) {
609 if (display)
610 nvkm_error(subdev, "TRAP: unknown %08x\n", status);
611 nvkm_wr32(device, 0x400108, status);
612 }
613
614 return 1;
615 }
616
617 void
nv50_gr_intr(struct nvkm_gr * base)618 nv50_gr_intr(struct nvkm_gr *base)
619 {
620 struct nv50_gr *gr = nv50_gr(base);
621 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
622 struct nvkm_device *device = subdev->device;
623 struct nvkm_fifo_chan *chan;
624 u32 stat = nvkm_rd32(device, 0x400100);
625 u32 inst = nvkm_rd32(device, 0x40032c) & 0x0fffffff;
626 u32 addr = nvkm_rd32(device, 0x400704);
627 u32 subc = (addr & 0x00070000) >> 16;
628 u32 mthd = (addr & 0x00001ffc);
629 u32 data = nvkm_rd32(device, 0x400708);
630 u32 class = nvkm_rd32(device, 0x400814);
631 u32 show = stat, show_bitfield = stat;
632 const struct nvkm_enum *en;
633 unsigned long flags;
634 const char *name = "unknown";
635 char msg[128];
636 int chid = -1;
637
638 chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags);
639 if (chan) {
640 name = chan->object.client->name;
641 chid = chan->chid;
642 }
643
644 if (show & 0x00100000) {
645 u32 ecode = nvkm_rd32(device, 0x400110);
646 en = nvkm_enum_find(nv50_data_error_names, ecode);
647 nvkm_error(subdev, "DATA_ERROR %08x [%s]\n",
648 ecode, en ? en->name : "");
649 show_bitfield &= ~0x00100000;
650 }
651
652 if (stat & 0x00200000) {
653 if (!nv50_gr_trap_handler(gr, show, chid, (u64)inst << 12, name))
654 show &= ~0x00200000;
655 show_bitfield &= ~0x00200000;
656 }
657
658 nvkm_wr32(device, 0x400100, stat);
659 nvkm_wr32(device, 0x400500, 0x00010001);
660
661 if (show) {
662 show &= show_bitfield;
663 nvkm_snprintbf(msg, sizeof(msg), nv50_gr_intr_name, show);
664 nvkm_error(subdev, "%08x [%s] ch %d [%010llx %s] subc %d "
665 "class %04x mthd %04x data %08x\n",
666 stat, msg, chid, (u64)inst << 12, name,
667 subc, class, mthd, data);
668 }
669
670 if (nvkm_rd32(device, 0x400824) & (1 << 31))
671 nvkm_wr32(device, 0x400824, nvkm_rd32(device, 0x400824) & ~(1 << 31));
672
673 nvkm_fifo_chan_put(device->fifo, flags, &chan);
674 }
675
676 int
nv50_gr_init(struct nvkm_gr * base)677 nv50_gr_init(struct nvkm_gr *base)
678 {
679 struct nv50_gr *gr = nv50_gr(base);
680 struct nvkm_device *device = gr->base.engine.subdev.device;
681 int ret, units, i;
682
683 /* NV_PGRAPH_DEBUG_3_HW_CTX_SWITCH_ENABLED */
684 nvkm_wr32(device, 0x40008c, 0x00000004);
685
686 /* reset/enable traps and interrupts */
687 nvkm_wr32(device, 0x400804, 0xc0000000);
688 nvkm_wr32(device, 0x406800, 0xc0000000);
689 nvkm_wr32(device, 0x400c04, 0xc0000000);
690 nvkm_wr32(device, 0x401800, 0xc0000000);
691 nvkm_wr32(device, 0x405018, 0xc0000000);
692 nvkm_wr32(device, 0x402000, 0xc0000000);
693
694 units = nvkm_rd32(device, 0x001540);
695 for (i = 0; i < 16; i++) {
696 if (!(units & (1 << i)))
697 continue;
698
699 if (device->chipset < 0xa0) {
700 nvkm_wr32(device, 0x408900 + (i << 12), 0xc0000000);
701 nvkm_wr32(device, 0x408e08 + (i << 12), 0xc0000000);
702 nvkm_wr32(device, 0x408314 + (i << 12), 0xc0000000);
703 } else {
704 nvkm_wr32(device, 0x408600 + (i << 11), 0xc0000000);
705 nvkm_wr32(device, 0x408708 + (i << 11), 0xc0000000);
706 nvkm_wr32(device, 0x40831c + (i << 11), 0xc0000000);
707 }
708 }
709
710 nvkm_wr32(device, 0x400108, 0xffffffff);
711 nvkm_wr32(device, 0x400138, 0xffffffff);
712 nvkm_wr32(device, 0x400100, 0xffffffff);
713 nvkm_wr32(device, 0x40013c, 0xffffffff);
714 nvkm_wr32(device, 0x400500, 0x00010001);
715
716 /* upload context program, initialise ctxctl defaults */
717 ret = nv50_grctx_init(device, &gr->size);
718 if (ret)
719 return ret;
720
721 nvkm_wr32(device, 0x400824, 0x00000000);
722 nvkm_wr32(device, 0x400828, 0x00000000);
723 nvkm_wr32(device, 0x40082c, 0x00000000);
724 nvkm_wr32(device, 0x400830, 0x00000000);
725 nvkm_wr32(device, 0x40032c, 0x00000000);
726 nvkm_wr32(device, 0x400330, 0x00000000);
727
728 /* some unknown zcull magic */
729 switch (device->chipset & 0xf0) {
730 case 0x50:
731 case 0x80:
732 case 0x90:
733 nvkm_wr32(device, 0x402ca8, 0x00000800);
734 break;
735 case 0xa0:
736 default:
737 if (device->chipset == 0xa0 ||
738 device->chipset == 0xaa ||
739 device->chipset == 0xac) {
740 nvkm_wr32(device, 0x402ca8, 0x00000802);
741 } else {
742 nvkm_wr32(device, 0x402cc0, 0x00000000);
743 nvkm_wr32(device, 0x402ca8, 0x00000002);
744 }
745
746 break;
747 }
748
749 /* zero out zcull regions */
750 for (i = 0; i < 8; i++) {
751 nvkm_wr32(device, 0x402c20 + (i * 0x10), 0x00000000);
752 nvkm_wr32(device, 0x402c24 + (i * 0x10), 0x00000000);
753 nvkm_wr32(device, 0x402c28 + (i * 0x10), 0x00000000);
754 nvkm_wr32(device, 0x402c2c + (i * 0x10), 0x00000000);
755 }
756
757 return 0;
758 }
759
760 int
nv50_gr_new_(const struct nvkm_gr_func * func,struct nvkm_device * device,int index,struct nvkm_gr ** pgr)761 nv50_gr_new_(const struct nvkm_gr_func *func, struct nvkm_device *device,
762 int index, struct nvkm_gr **pgr)
763 {
764 struct nv50_gr *gr;
765
766 if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL)))
767 return -ENOMEM;
768 spin_lock_init(&gr->lock);
769 *pgr = &gr->base;
770
771 return nvkm_gr_ctor(func, device, index, 0x00201000, true, &gr->base);
772 }
773
774 static const struct nvkm_gr_func
775 nv50_gr = {
776 .init = nv50_gr_init,
777 .intr = nv50_gr_intr,
778 .chan_new = nv50_gr_chan_new,
779 .units = nv50_gr_units,
780 .sclass = {
781 { -1, -1, 0x0030, &nv50_gr_object },
782 { -1, -1, 0x502d, &nv50_gr_object },
783 { -1, -1, 0x5039, &nv50_gr_object },
784 { -1, -1, 0x5097, &nv50_gr_object },
785 { -1, -1, 0x50c0, &nv50_gr_object },
786 {}
787 }
788 };
789
790 int
nv50_gr_new(struct nvkm_device * device,int index,struct nvkm_gr ** pgr)791 nv50_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
792 {
793 return nv50_gr_new_(&nv50_gr, device, index, pgr);
794 }
795