aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv40_graph.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv40_graph.c')
-rw-r--r--drivers/gpu/drm/nouveau/nv40_graph.c69
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
32static int nv40_graph_register(struct drm_device *); 32static int nv40_graph_register(struct drm_device *);
33static void nv40_graph_isr(struct drm_device *);
33 34
34struct nouveau_channel * 35struct nouveau_channel *
35nv40_graph_channel(struct drm_device *dev) 36nv40_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
409void nv40_graph_takedown(struct drm_device *dev) 411void nv40_graph_takedown(struct drm_device *dev)
410{ 412{
413 nouveau_irq_unregister(dev, 12);
411} 414}
412 415
413static int 416static 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
456static int
457nv40_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
477static void
478nv40_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}