aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2012-09-06 01:03:47 -0400
committerBen Skeggs <bskeggs@redhat.com>2012-10-02 23:13:10 -0400
commitf73221e4aa766a58b784729968159013cc73459d (patch)
treee70aa1f96602724989b776cc5a0ca5442f02a63f
parentd66b9d9a6839129e11b94c90ec415b244b44414d (diff)
drm/nvc0/gr: implement initial trap handler
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c192
1 files changed, 188 insertions, 4 deletions
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
index f002e7e91318..c62f2d0f5f0a 100644
--- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
@@ -224,6 +224,192 @@ nvc0_graph_ctxctl_isr(struct nvc0_graph_priv *priv)
224} 224}
225 225
226static void 226static void
227nvc0_graph_trap_tpc(struct nvc0_graph_priv *priv, int gpc, int tpc)
228{
229 u32 stat = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0508));
230
231 if (stat & 0x00000001) {
232 u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0224));
233 nv_error(priv, "GPC%d/TPC%d/TEX: 0x%08x\n", gpc, tpc, trap);
234 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0224), 0xc0000000);
235 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0508), 0x00000001);
236 stat &= ~0x00000001;
237 }
238
239 if (stat & 0x00000002) {
240 u32 trap0 = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0644));
241 u32 trap1 = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x064c));
242 nv_error(priv, "GPC%d/TPC%d/MP: 0x%08x 0x%08x\n",
243 gpc, tpc, trap0, trap1);
244 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0644), 0x001ffffe);
245 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x064c), 0x0000000f);
246 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0508), 0x00000002);
247 stat &= ~0x00000002;
248 }
249
250 if (stat & 0x00000004) {
251 u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0084));
252 nv_error(priv, "GPC%d/TPC%d/POLY: 0x%08x\n", gpc, tpc, trap);
253 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0084), 0xc0000000);
254 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0508), 0x00000004);
255 stat &= ~0x00000004;
256 }
257
258 if (stat & 0x00000008) {
259 u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x048c));
260 nv_error(priv, "GPC%d/TPC%d/L1C: 0x%08x\n", gpc, tpc, trap);
261 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x048c), 0xc0000000);
262 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0508), 0x00000008);
263 stat &= ~0x00000008;
264 }
265
266 if (stat) {
267 nv_error(priv, "GPC%d/TPC%d/0x%08x: unknown\n", gpc, tpc, stat);
268 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0508), stat);
269 }
270}
271
272static void
273nvc0_graph_trap_gpc(struct nvc0_graph_priv *priv, int gpc)
274{
275 u32 stat = nv_rd32(priv, GPC_UNIT(gpc, 0x2c90));
276 int tpc;
277
278 if (stat & 0x00000001) {
279 u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0420));
280 nv_error(priv, "GPC%d/PROP: 0x%08x\n", gpc, trap);
281 nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000);
282 nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0x00000001);
283 stat &= ~0x00000001;
284 }
285
286 if (stat & 0x00000002) {
287 u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0900));
288 nv_error(priv, "GPC%d/ZCULL: 0x%08x\n", gpc, trap);
289 nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000);
290 nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0x00000002);
291 stat &= ~0x00000002;
292 }
293
294 if (stat & 0x00000004) {
295 u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x1028));
296 nv_error(priv, "GPC%d/CCACHE: 0x%08x\n", gpc, trap);
297 nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000);
298 nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0x00000004);
299 stat &= ~0x00000004;
300 }
301
302 if (stat & 0x00000008) {
303 u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0824));
304 nv_error(priv, "GPC%d/ESETUP: 0x%08x\n", gpc, trap);
305 nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000);
306 nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0x00000008);
307 stat &= ~0x00000009;
308 }
309
310 for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
311 u32 mask = 0x00010000 << tpc;
312 if (stat & mask) {
313 nvc0_graph_trap_tpc(priv, gpc, tpc);
314 nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), mask);
315 stat &= ~mask;
316 }
317 }
318
319 if (stat) {
320 nv_error(priv, "GPC%d/0x%08x: unknown\n", gpc, stat);
321 nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), stat);
322 }
323}
324
325static void
326nvc0_graph_trap_intr(struct nvc0_graph_priv *priv)
327{
328 u32 trap = nv_rd32(priv, 0x400108);
329 int rop, gpc;
330
331 if (trap & 0x00000001) {
332 u32 stat = nv_rd32(priv, 0x404000);
333 nv_error(priv, "DISPATCH 0x%08x\n", stat);
334 nv_wr32(priv, 0x404000, 0xc0000000);
335 nv_wr32(priv, 0x400108, 0x00000001);
336 trap &= ~0x00000001;
337 }
338
339 if (trap & 0x00000002) {
340 u32 stat = nv_rd32(priv, 0x404600);
341 nv_error(priv, "M2MF 0x%08x\n", stat);
342 nv_wr32(priv, 0x404600, 0xc0000000);
343 nv_wr32(priv, 0x400108, 0x00000002);
344 trap &= ~0x00000002;
345 }
346
347 if (trap & 0x00000008) {
348 u32 stat = nv_rd32(priv, 0x408030);
349 nv_error(priv, "CCACHE 0x%08x\n", stat);
350 nv_wr32(priv, 0x408030, 0xc0000000);
351 nv_wr32(priv, 0x400108, 0x00000008);
352 trap &= ~0x00000008;
353 }
354
355 if (trap & 0x00000010) {
356 u32 stat = nv_rd32(priv, 0x405840);
357 nv_error(priv, "SHADER 0x%08x\n", stat);
358 nv_wr32(priv, 0x405840, 0xc0000000);
359 nv_wr32(priv, 0x400108, 0x00000010);
360 trap &= ~0x00000010;
361 }
362
363 if (trap & 0x00000040) {
364 u32 stat = nv_rd32(priv, 0x40601c);
365 nv_error(priv, "UNK6 0x%08x\n", stat);
366 nv_wr32(priv, 0x40601c, 0xc0000000);
367 nv_wr32(priv, 0x400108, 0x00000040);
368 trap &= ~0x00000040;
369 }
370
371 if (trap & 0x00000080) {
372 u32 stat = nv_rd32(priv, 0x404490);
373 nv_error(priv, "MACRO 0x%08x\n", stat);
374 nv_wr32(priv, 0x404490, 0xc0000000);
375 nv_wr32(priv, 0x400108, 0x00000080);
376 trap &= ~0x00000080;
377 }
378
379 if (trap & 0x01000000) {
380 u32 stat = nv_rd32(priv, 0x400118);
381 for (gpc = 0; stat && gpc < priv->gpc_nr; gpc++) {
382 u32 mask = 0x00000001 << gpc;
383 if (stat & mask) {
384 nvc0_graph_trap_gpc(priv, gpc);
385 nv_wr32(priv, 0x400118, mask);
386 stat &= ~mask;
387 }
388 }
389 nv_wr32(priv, 0x400108, 0x01000000);
390 trap &= ~0x01000000;
391 }
392
393 if (trap & 0x02000000) {
394 for (rop = 0; rop < priv->rop_nr; rop++) {
395 u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070));
396 u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144));
397 nv_error(priv, "ROP%d 0x%08x 0x%08x\n",
398 rop, statz, statc);
399 nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000);
400 nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000);
401 }
402 nv_wr32(priv, 0x400108, 0x02000000);
403 trap &= ~0x02000000;
404 }
405
406 if (trap) {
407 nv_error(priv, "TRAP UNHANDLED 0x%08x\n", trap);
408 nv_wr32(priv, 0x400108, trap);
409 }
410}
411
412static void
227nvc0_graph_intr(struct nouveau_subdev *subdev) 413nvc0_graph_intr(struct nouveau_subdev *subdev)
228{ 414{
229 struct nouveau_fifo *pfifo = nouveau_fifo(subdev); 415 struct nouveau_fifo *pfifo = nouveau_fifo(subdev);
@@ -276,10 +462,8 @@ nvc0_graph_intr(struct nouveau_subdev *subdev)
276 } 462 }
277 463
278 if (stat & 0x00200000) { 464 if (stat & 0x00200000) {
279 u32 trap = nv_rd32(priv, 0x400108); 465 nv_error(priv, "TRAP ch %d [0x%010llx]\n", chid, inst << 12);
280 nv_error(priv, "TRAP ch %d [0x%010llx] status 0x%08x\n", 466 nvc0_graph_trap_intr(priv);
281 chid, inst << 12, trap);
282 nv_wr32(priv, 0x400108, trap);
283 nv_wr32(priv, 0x400100, 0x00200000); 467 nv_wr32(priv, 0x400100, 0x00200000);
284 stat &= ~0x00200000; 468 stat &= ~0x00200000;
285 } 469 }