summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/nv40_graph.c
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-11-03 13:16:18 +1000
committerBen Skeggs <bskeggs@redhat.com>2010-12-03 15:11:41 +1000
commit274fec93cdd627408a799519fa602f2eecb14d2f (patch)
tree1ffc788a096237583608dfa3f09caccfc500ec82 /drivers/gpu/drm/nouveau/nv40_graph.c
parent5178d40dff23b5eef7f0a3be2411fa6a347e750d (diff)
drm/nouveau: tidy+move PGRAPH ISRs to their respective *_graph.c files
Reviewed-by: Francisco Jerez <currojerez@riseup.net> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
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 7a51608b55b..0618846a97c 100644
--- a/drivers/gpu/drm/nouveau/nv40_graph.c
+++ b/drivers/gpu/drm/nouveau/nv40_graph.c
@@ -30,6 +30,7 @@
#include "nouveau_grctx.h"
static int nv40_graph_register(struct drm_device *);
+static void nv40_graph_isr(struct drm_device *);
struct nouveau_channel *
nv40_graph_channel(struct drm_device *dev)
@@ -277,6 +278,7 @@ nv40_graph_init(struct drm_device *dev)
/* No context present currently */
nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
+ nouveau_irq_register(dev, 12, nv40_graph_isr);
nv_wr32(dev, NV03_PGRAPH_INTR , 0xFFFFFFFF);
nv_wr32(dev, NV40_PGRAPH_INTR_EN, 0xFFFFFFFF);
@@ -408,6 +410,7 @@ nv40_graph_init(struct drm_device *dev)
void nv40_graph_takedown(struct drm_device *dev)
{
+ nouveau_irq_unregister(dev, 12);
}
static int
@@ -449,3 +452,69 @@ nv40_graph_register(struct drm_device *dev)
dev_priv->engine.graph.registered = true;
return 0;
}
+
+static int
+nv40_graph_isr_chid(struct drm_device *dev, u32 inst)
+{
+ struct drm_nouveau_private *dev_priv = dev->dev_private;
+ struct nouveau_channel *chan;
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&dev_priv->channels.lock, flags);
+ for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
+ chan = dev_priv->channels.ptr[i];
+ if (!chan || !chan->ramin_grctx)
+ continue;
+
+ if (inst == chan->ramin_grctx->pinst)
+ break;
+ }
+ spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
+ return i;
+}
+
+static void
+nv40_graph_isr(struct drm_device *dev)
+{
+ u32 stat;
+
+ while ((stat = nv_rd32(dev, NV03_PGRAPH_INTR))) {
+ u32 nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
+ u32 nstatus = nv_rd32(dev, NV03_PGRAPH_NSTATUS);
+ u32 inst = (nv_rd32(dev, 0x40032c) & 0x000fffff) << 4;
+ u32 chid = nv40_graph_isr_chid(dev, inst);
+ u32 addr = nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR);
+ u32 subc = (addr & 0x00070000) >> 16;
+ u32 mthd = (addr & 0x00001ffc);
+ u32 data = nv_rd32(dev, NV04_PGRAPH_TRAPPED_DATA);
+ u32 class = nv_rd32(dev, 0x400160 + subc * 4) & 0xffff;
+ u32 show = stat;
+
+ if (stat & NV_PGRAPH_INTR_ERROR) {
+ if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) {
+ if (!nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data))
+ show &= ~NV_PGRAPH_INTR_ERROR;
+ } else
+ if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) {
+ nv_mask(dev, 0x402000, 0, 0);
+ }
+ }
+
+ nv_wr32(dev, NV03_PGRAPH_INTR, stat);
+ nv_wr32(dev, NV04_PGRAPH_FIFO, 0x00000001);
+
+ if (show && nouveau_ratelimit()) {
+ NV_INFO(dev, "PGRAPH -");
+ nouveau_bitfield_print(nv10_graph_intr, show);
+ printk(" nsource:");
+ nouveau_bitfield_print(nv04_graph_nsource, nsource);
+ printk(" nstatus:");
+ nouveau_bitfield_print(nv10_graph_nstatus, nstatus);
+ printk("\n");
+ NV_INFO(dev, "PGRAPH - ch %d (0x%08x) subc %d "
+ "class 0x%04x mthd 0x%04x data 0x%08x\n",
+ chid, inst, subc, class, mthd, data);
+ }
+ }
+}