diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv40_graph.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv40_graph.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c index 7a51608b55ba..0618846a97ce 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "nouveau_grctx.h" | 30 | #include "nouveau_grctx.h" |
31 | 31 | ||
32 | static int nv40_graph_register(struct drm_device *); | 32 | static int nv40_graph_register(struct drm_device *); |
33 | static void nv40_graph_isr(struct drm_device *); | ||
33 | 34 | ||
34 | struct nouveau_channel * | 35 | struct nouveau_channel * |
35 | nv40_graph_channel(struct drm_device *dev) | 36 | nv40_graph_channel(struct drm_device *dev) |
@@ -277,6 +278,7 @@ nv40_graph_init(struct drm_device *dev) | |||
277 | /* No context present currently */ | 278 | /* No context present currently */ |
278 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); | 279 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); |
279 | 280 | ||
281 | nouveau_irq_register(dev, 12, nv40_graph_isr); | ||
280 | nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); | 282 | nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF); |
281 | nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); | 283 | nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF); |
282 | 284 | ||
@@ -408,6 +410,7 @@ nv40_graph_init(struct drm_device *dev) | |||
408 | 410 | ||
409 | void nv40_graph_takedown(struct drm_device *dev) | 411 | void nv40_graph_takedown(struct drm_device *dev) |
410 | { | 412 | { |
413 | nouveau_irq_unregister(dev, 12); | ||
411 | } | 414 | } |
412 | 415 | ||
413 | static int | 416 | static int |
@@ -449,3 +452,69 @@ nv40_graph_register(struct drm_device *dev) | |||
449 | dev_priv->engine.graph.registered = true; | 452 | dev_priv->engine.graph.registered = true; |
450 | return 0; | 453 | return 0; |
451 | } | 454 | } |
455 | |||
456 | static int | ||
457 | nv40_graph_isr_chid(struct drm_device *dev, u32 inst) | ||
458 | { | ||
459 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
460 | struct nouveau_channel *chan; | ||
461 | unsigned long flags; | ||
462 | int i; | ||
463 | |||
464 | spin_lock_irqsave(&dev_priv->channels.lock, flags); | ||
465 | for (i = 0; i < dev_priv->engine.fifo.channels; i++) { | ||
466 | chan = dev_priv->channels.ptr[i]; | ||
467 | if (!chan || !chan->ramin_grctx) | ||
468 | continue; | ||
469 | |||
470 | if (inst == chan->ramin_grctx->pinst) | ||
471 | break; | ||
472 | } | ||
473 | spin_unlock_irqrestore(&dev_priv->channels.lock, flags); | ||
474 | return i; | ||
475 | } | ||
476 | |||
477 | static void | ||
478 | nv40_graph_isr(struct drm_device *dev) | ||
479 | { | ||
480 | u32 stat; | ||
481 | |||
482 | while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) { | ||
483 | u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); | ||
484 | u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS); | ||
485 | u32 inst = (nv_rd32(dev, 0x40032c) & 0x000fffff) << 4; | ||
486 | u32 chid = nv40_graph_isr_chid(dev, inst); | ||
487 | u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR); | ||
488 | u32 subc = (addr & 0x00070000) >> 16; | ||
489 | u32 mthd = (addr & 0x00001ffc); | ||
490 | u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA); | ||
491 | u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xffff; | ||
492 | u32 show = stat; | ||
493 | |||
494 | if (stat & NV_PGRAPH_INTR_ERROR) { | ||
495 | if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { | ||
496 | if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) | ||
497 | show &= ~NV_PGRAPH_INTR_ERROR; | ||
498 | } else | ||
499 | if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { | ||
500 | nv_mask(dev, 0x402000, 0, 0); | ||
501 | } | ||
502 | } | ||
503 | |||
504 | nv_wr32(dev, NV03_PGRAPH_INTR, stat); | ||
505 | nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001); | ||
506 | |||
507 | if (show && nouveau_ratelimit()) { | ||
508 | NV_INFO(dev, "PGRAPH -"); | ||
509 | nouveau_bitfield_print(nv10_graph_intr, show); | ||
510 | printk(" nsource:"); | ||
511 | nouveau_bitfield_print(nv04_graph_nsource, nsource); | ||
512 | printk(" nstatus:"); | ||
513 | nouveau_bitfield_print(nv10_graph_nstatus, nstatus); | ||
514 | printk("\n"); | ||
515 | NV_INFO(dev, "PGRAPH - ch %d (0x%08x) subc %d " | ||
516 | "class 0x%04x mthd 0x%04x data 0x%08x\n", | ||
517 | chid, inst, subc, class, mthd, data); | ||
518 | } | ||
519 | } | ||
520 | } | ||