diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nv50_fb.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_fb.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nv50_fb.c b/drivers/gpu/drm/nouveau/nv50_fb.c index 32611bd30e6..cd1988b15d2 100644 --- a/drivers/gpu/drm/nouveau/nv50_fb.c +++ b/drivers/gpu/drm/nouveau/nv50_fb.c @@ -20,6 +20,7 @@ nv50_fb_init(struct drm_device *dev) case 0x50: nv_wr32(dev, 0x100c90, 0x0707ff); break; + case 0xa3: case 0xa5: case 0xa8: nv_wr32(dev, 0x100c90, 0x0d0fff); @@ -36,3 +37,42 @@ void nv50_fb_takedown(struct drm_device *dev) { } + +void +nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + u32 trap[6], idx, chinst; + int i, ch; + + idx = nv_rd32(dev, 0x100c90); + if (!(idx & 0x80000000)) + return; + idx &= 0x00ffffff; + + for (i = 0; i < 6; i++) { + nv_wr32(dev, 0x100c90, idx | i << 24); + trap[i] = nv_rd32(dev, 0x100c94); + } + nv_wr32(dev, 0x100c90, idx | 0x80000000); + + if (!display) + return; + + chinst = (trap[2] << 16) | trap[1]; + for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) { + struct nouveau_channel *chan = dev_priv->fifos[ch]; + + if (!chan || !chan->ramin) + continue; + + if (chinst == chan->ramin->vinst >> 12) + break; + } + + NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x " + "channel %d (0x%08x)\n", + name, (trap[5] & 0x100 ? "read" : "write"), + trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, + trap[0], ch, chinst); +} |