diff options
author | Alexandre Courbot <acourbot@nvidia.com> | 2014-02-28 16:39:39 +0900 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2014-08-07 16:54:53 +0200 |
commit | 4511013785df8a5b40dce998f04d8c694d45845b (patch) | |
tree | 7dd601e79f88f7bb89db39bf3702d4363a1f9f69 | |
parent | 309c23af705b2cf8ded3a1455b77f29eb976498d (diff) |
[DEBUG] Add channel dumping functions for NVEA
-rw-r--r-- | drivers/gpu/drm/nouveau/Makefile | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_debug.c | 185 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_debug.h | 11 |
3 files changed, 197 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 561df2d91c3f..9e8298719a64 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -325,6 +325,7 @@ nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o nouveau-y += nouveau_prime.o nouveau_abi16.o nouveau-y += nv04_fence.o nv10_fence.o nv17_fence.o nouveau-y += nv50_fence.o nv84_fence.o nvc0_fence.o +nouveau-y += nouveau_debug.o # drm/kms nouveau-y += nouveau_bios.o nouveau_fbcon.o nouveau_display.o diff --git a/drivers/gpu/drm/nouveau/nouveau_debug.c b/drivers/gpu/drm/nouveau/nouveau_debug.c new file mode 100644 index 000000000000..92b5f5a2bb7d --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_debug.c @@ -0,0 +1,185 @@ + +#include <linux/highmem.h> +#include <linux/printk.h> +#include <core/object.h> +#include <core/gpuobj.h> +#include <engine/fifo.h> +#include <subdev/vm.h> +#include <nouveau_drm.h> +#include <nouveau_chan.h> +#include <nouveau_bo.h> + +static u32 +pfn_for_vaddr(u32 pgtpfn, u64 vaddr) +{ + u32 pde = vaddr >> 26; + u32 pte = (vaddr & 0x3ffffff) >> 12; + u32 ptepfn; + struct page *p = pfn_to_page(pgtpfn); + u32 *pgt = kmap(p); + u32 *pet; + u32 ret; + ptepfn = pgt[pde * 2 + 1] >> 4; + kunmap(p); + + p = pfn_to_page(ptepfn); + pet = kmap(p); + ret = pet[pte * 2] >> 4; + kunmap(p); + + return ret; +} + +void +dump_pte(u32 ptepfn, u32 base) +{ + struct page *p = pfn_to_page(ptepfn); + u32 *pte = kmap(p); + int k; + + for (k = 0; k < 512; k++) { + u32 mappfn = pte[0] >> 4; + bool ptevol = pte[1] & 0x1; + u32 pteflags = pte[1] & (0x7 << 1); + if (pte[0] & 1) { + printk(" %08x -> %08x VOL=%d FLAGS=%x\n", base * 0x4000000 + k * 0x1000, mappfn << 12, ptevol, pteflags); + } + pte += 2; + } + + kunmap(p); +} + +void +dump_pgt(u32 pgtpfn) +{ + struct page *p = pfn_to_page(pgtpfn); + u32 *pgt = kmap(p); + int j; + + for (j = 0; j < 128; j++) { + int flags = pgt[1] & 0xf; + int ptepfn = pgt[1] >> 4; + /* PTE valid */ + if ((flags & 0x3) != 0) { + dump_pte(ptepfn, j); + } + pgt += 2; + } + + kunmap(p); +} + +void +dump_ramuser(struct nouveau_channel *ch) +{ + struct nouveau_fifo_chan *chan = (struct nouveau_fifo_chan *) ch->object; + /* Read the values from the snoop area to get up-to-date information */ + u32 *ramuser = chan->user; + u32 get, get_hi, put, put_hi; + /* Read the low fields first as specified in the doc */ + get = ramuser[17]; + rmb(); + get_hi = ramuser[24]; + rmb(); + put = ramuser[16]; + rmb(); + put_hi = ramuser[19]; + rmb(); + printk(" PUT: %08x%08x\n", put_hi, put); + printk(" GET: %08x%08x\n", get_hi, get); + printk(" GP_PUT: %08x\n", ramuser[35]); + printk(" GP_GET: %08x\n", ramuser[34]); +} + +void dump_pb(u32 pbpfn, u32 start, u32 len) +{ + struct page *p = pfn_to_page(pbpfn); + u32 *pb = kmap(p) + start; + u32 i; + + for (i = start; i < start + len; i++) + printk("%08x: %08x\n", (pbpfn << PAGE_SHIFT) + i * 4, pb[i]); + + kunmap(p); +} + +void dump_gpentries(struct nouveau_channel *ch, u32 gppfn, u32 pgtpfn) +{ + struct nouveau_fifo_chan *chan = (struct nouveau_fifo_chan *) ch->object; + struct page *p = pfn_to_page(gppfn); + u32 *gp = kmap(p); + u32 *ramuser = chan->user; + u32 gp0, gp1; + u64 addr; + u32 len; + u32 gp_get, gp_put, i; + + gp_get = ramuser[34]; + gp_put = ramuser[35]; + + for (i = gp_get; i <= gp_put; i++) { + gp0 = gp[i * 2]; + gp1 = gp[i * 2 + 1]; + addr = ((u64)gp0) | (((u64)(gp1 & 0xff)) << 32); + len = ((gp1 & 0x7ffffc00) >> 10); + printk(" addr: %llx len: %x\n", addr, len); + if (addr != 0) + dump_pb(pfn_for_vaddr(pgtpfn, addr), addr & (~PAGE_MASK), len); + } + + kunmap(p); +} + +void dump_ramin(struct nouveau_channel *ch, u32 raminpfn) +{ + struct page *p = pfn_to_page(raminpfn); + u32 *ramin = kmap(p); + u32 pgtpfn; + u64 gpbase; + + pgtpfn = (ramin[128] & (~0x3)) >> PAGE_SHIFT; + + gpbase = (((u64)(ramin[19] & 0xff)) << 32) | (ramin[18] & 0xfffffff8); + + printk(" GP_BASE: %llx\n", gpbase); + printk(" phys: %x\n", pfn_for_vaddr(pgtpfn, gpbase)); + printk(" GP ENTRIES:\n"); + dump_gpentries(ch, pfn_for_vaddr(pgtpfn, gpbase), pgtpfn); + printk(" USERD: %08x%08x\n", ramin[3], ramin[2]); + dump_ramuser(ch); + printk(" PGT: %02x%08x %02x%08x\n", ramin[129], ramin[128], ramin[131], ramin[130]); + dump_pgt(pgtpfn); + kunmap(p); +} + +void dump_channel(struct nouveau_channel *chan) +{ + struct nouveau_device *device = nv_device(chan->drm->device); + struct nouveau_fifo_chan *fchan = (struct nouveau_fifo_chan *) chan->object; + + u32 raminpfn = nv_rd32(device, 0x800000 + (fchan->chid * 8)) & 0xfffff; + printk("Channel 0x%x, RAMIN: %x\n", fchan->chid, raminpfn << PAGE_SHIFT); + + dump_ramin(chan, raminpfn); +} + +/* +void +dump_runlist(struct nouveau_object *priv, u32 nchan, struct nouveau_gpuobj *cur) +{ + int i; + + for (i = 0; i < nchan; i++) { + u32 val = nv_ro32(cur, i * 8); + u32 chst1 = nv_rd32(priv, 0x800000 + (val * 8)); + u32 chst2 = nv_rd32(priv, 0x800004 + (val * 8)); + u32 raminpfn = chst1 & 0xfffff; + if ((chst1 & 0x80000000) && val) { + printk(" channel %x %08x %08x\n", val, chst1, chst2); + printk(" RAMIN: %08x\n", raminpfn << PAGE_SHIFT); + dump_ramin(raminpfn); + } + } +} +*/
\ No newline at end of file diff --git a/drivers/gpu/drm/nouveau/nouveau_debug.h b/drivers/gpu/drm/nouveau/nouveau_debug.h new file mode 100644 index 000000000000..b5a3a4209266 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_debug.h @@ -0,0 +1,11 @@ + +struct nouveau_object; +struct nouveau_gpuobj; +struct nouveau_channel; + +void dump_pte(u32 ptepfn, u32 base); +void dump_pgt(u32 pgtpfn); +void dump_ramuser(struct nouveau_channel *chan); +void dump_ramin(struct nouveau_channel *chan, u32 raminpfn); +void dump_channel(struct nouveau_channel *chan); +/*void dump_runlist(struct nouveau_object *priv, u32 nchan, struct nouveau_gpuobj *cur);*/
\ No newline at end of file |