diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2012-09-06 01:03:47 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2012-10-02 23:13:10 -0400 |
commit | f73221e4aa766a58b784729968159013cc73459d (patch) | |
tree | e70aa1f96602724989b776cc5a0ca5442f02a63f | |
parent | d66b9d9a6839129e11b94c90ec415b244b44414d (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.c | 192 |
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 | ||
226 | static void | 226 | static void |
227 | nvc0_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 | |||
272 | static void | ||
273 | nvc0_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 | |||
325 | static void | ||
326 | nvc0_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 | |||
412 | static void | ||
227 | nvc0_graph_intr(struct nouveau_subdev *subdev) | 413 | nvc0_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 | } |