These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / nouveau / nvkm / engine / gr / nv50.c
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
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
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
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
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
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
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
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
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
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
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
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
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 }