From f8c80f4ea8930af9e2e93765e635d84fe6e22575 Mon Sep 17 00:00:00 2001 From: Terje Bergstrom Date: Fri, 29 Jul 2011 09:09:43 +0300 Subject: nvhost: Fix tegra_host/status debug output Add tracking of mapping between push buffer gathers and nvmap handles. Use the mapping to access contents of gather buffers. Bug 840976 Change-Id: Ic6fe2fc7a83e8f14cd606a9e638b6420aa714495 Signed-off-by: Terje Bergstrom Reviewed-on: http://git-master/r/44779 Reviewed-by: Varun Colbert Tested-by: Varun Colbert --- drivers/video/tegra/host/chip_support.h | 1 + drivers/video/tegra/host/nvhost_cdma.c | 15 +++++- drivers/video/tegra/host/nvhost_cdma.h | 13 +++-- drivers/video/tegra/host/t20/3dctx_t20.c | 6 ++- drivers/video/tegra/host/t20/cdma_t20.c | 14 +++++- drivers/video/tegra/host/t20/channel_t20.c | 14 ++++-- drivers/video/tegra/host/t20/debug_t20.c | 78 +++++++++++++++++++++--------- 7 files changed, 102 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h index a0b0f0278a0f..eae99671a20d 100644 --- a/drivers/video/tegra/host/chip_support.h +++ b/drivers/video/tegra/host/chip_support.h @@ -61,6 +61,7 @@ struct nvhost_chip_support { int (*init)(struct push_buffer *); void (*destroy)(struct push_buffer *); void (*push_to)(struct push_buffer *, + struct nvmap_handle *, u32 op1, u32 op2); void (*pop_from)(struct push_buffer *, unsigned int slots); diff --git a/drivers/video/tegra/host/nvhost_cdma.c b/drivers/video/tegra/host/nvhost_cdma.c index 24c0c0fff0c0..fcce8334f272 100644 --- a/drivers/video/tegra/host/nvhost_cdma.c +++ b/drivers/video/tegra/host/nvhost_cdma.c @@ -407,6 +407,16 @@ void nvhost_cdma_begin(struct nvhost_cdma *cdma) * Blocks as necessary if the push buffer is full. */ void nvhost_cdma_push(struct nvhost_cdma *cdma, u32 op1, u32 op2) +{ + nvhost_cdma_push_gather(cdma, NULL, op1, op2); +} + +/** + * Push two words into a push buffer slot + * Blocks as necessary if the push buffer is full. + */ +void nvhost_cdma_push_gather(struct nvhost_cdma *cdma, + struct nvmap_handle *handle, u32 op1, u32 op2) { u32 slots_free = cdma->slots_free; struct push_buffer *pb = &cdma->push_buffer; @@ -414,11 +424,12 @@ void nvhost_cdma_push(struct nvhost_cdma *cdma, u32 op1, u32 op2) BUG_ON(!cdma_op(cdma).kick); if (slots_free == 0) { cdma_op(cdma).kick(cdma); - slots_free = nvhost_cdma_wait(cdma, CDMA_EVENT_PUSH_BUFFER_SPACE); + slots_free = nvhost_cdma_wait(cdma, + CDMA_EVENT_PUSH_BUFFER_SPACE); } cdma->slots_free = slots_free - 1; cdma->slots_used++; - cdma_pb_op(cdma).push_to(pb, op1, op2); + cdma_pb_op(cdma).push_to(pb, handle, op1, op2); } /** diff --git a/drivers/video/tegra/host/nvhost_cdma.h b/drivers/video/tegra/host/nvhost_cdma.h index e48d733850a9..45c2f7c57a7f 100644 --- a/drivers/video/tegra/host/nvhost_cdma.h +++ b/drivers/video/tegra/host/nvhost_cdma.h @@ -47,11 +47,12 @@ struct push_buffer { - struct nvmap_handle_ref *mem; /* handle to pushbuffer memory */ - u32 *mapped; /* mapped pushbuffer memory */ - u32 phys; /* physical address of pushbuffer */ - u32 fence; /* index we've written */ - u32 cur; /* index to write to */ + struct nvmap_handle_ref *mem; /* handle to pushbuffer memory */ + u32 *mapped; /* mapped pushbuffer memory */ + u32 phys; /* physical address of pushbuffer */ + u32 fence; /* index we've written */ + u32 cur; /* index to write to */ + struct nvmap_handle **handles; /* nvmap handle for each opcode pair */ }; struct sync_queue { @@ -93,6 +94,8 @@ void nvhost_cdma_deinit(struct nvhost_cdma *cdma); void nvhost_cdma_stop(struct nvhost_cdma *cdma); void nvhost_cdma_begin(struct nvhost_cdma *cdma); void nvhost_cdma_push(struct nvhost_cdma *cdma, u32 op1, u32 op2); +void nvhost_cdma_push_gather(struct nvhost_cdma *cdma, + struct nvmap_handle *handle, u32 op1, u32 op2); void nvhost_cdma_end(struct nvhost_cdma *cdma, struct nvmap_client *user_nvmap, u32 sync_point_id, u32 sync_point_value, diff --git a/drivers/video/tegra/host/t20/3dctx_t20.c b/drivers/video/tegra/host/t20/3dctx_t20.c index f3f1e9475efa..dadfbed3434a 100644 --- a/drivers/video/tegra/host/t20/3dctx_t20.c +++ b/drivers/video/tegra/host/t20/3dctx_t20.c @@ -392,7 +392,8 @@ static void __init setup_save(const struct ctx_saver *saver, u32 *ptr) static void save_push_v0(struct nvhost_cdma *cdma, struct nvhost_hwctx *ctx) { - nvhost_cdma_push(cdma, + nvhost_cdma_push_gather(cdma, + nvmap_ref_to_handle(save_buf), nvhost_opcode_gather(save_size), save_phys); } @@ -524,7 +525,8 @@ static void save_push_v1(struct nvhost_cdma *cdma, nvhost_opcode_nonincr(0x904, 1), ctx->restore_phys); /* gather the save buffer */ - nvhost_cdma_push(cdma, + nvhost_cdma_push_gather(cdma, + nvmap_ref_to_handle(save_buf), nvhost_opcode_gather(save_size), save_phys); } diff --git a/drivers/video/tegra/host/t20/cdma_t20.c b/drivers/video/tegra/host/t20/cdma_t20.c index 77f514eb4e01..eaba1c78af92 100644 --- a/drivers/video/tegra/host/t20/cdma_t20.c +++ b/drivers/video/tegra/host/t20/cdma_t20.c @@ -20,6 +20,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include #include "../nvhost_cdma.h" #include "../dev.h" @@ -53,6 +54,7 @@ static int t20_push_buffer_init(struct push_buffer *pb) pb->mem = NULL; pb->mapped = NULL; pb->phys = 0; + pb->handles = NULL; BUG_ON(!cdma_pb_op(cdma).reset); cdma_pb_op(cdma).reset(pb); @@ -75,6 +77,11 @@ static int t20_push_buffer_init(struct push_buffer *pb) goto fail; } + /* memory for storing nvmap handles for each opcode pair */ + pb->handles = kzalloc(PUSH_BUFFER_SIZE/2, GFP_KERNEL); + if (!pb->handles) + goto fail; + /* put the restart at the end of pushbuffer memory */ *(pb->mapped + (PUSH_BUFFER_SIZE >> 2)) = nvhost_opcode_restart(pb->phys); @@ -101,22 +108,27 @@ static void t20_push_buffer_destroy(struct push_buffer *pb) if (pb->mem) nvmap_free(nvmap, pb->mem); + kfree(pb->handles); + pb->mem = NULL; pb->mapped = NULL; pb->phys = 0; + pb->handles = 0; } /** * Push two words to the push buffer * Caller must ensure push buffer is not full */ -static void t20_push_buffer_push_to(struct push_buffer *pb, u32 op1, u32 op2) +static void t20_push_buffer_push_to(struct push_buffer *pb, + struct nvmap_handle *handle, u32 op1, u32 op2) { u32 cur = pb->cur; u32 *p = (u32*)((u32)pb->mapped + cur); BUG_ON(cur == pb->fence); *(p++) = op1; *(p++) = op2; + pb->handles[cur/8] = handle; pb->cur = (cur + 8) & (PUSH_BUFFER_SIZE - 1); /* printk("push_to_push_buffer: op1=%08x; op2=%08x; cur=%x\n", op1, op2, pb->cur); */ } diff --git a/drivers/video/tegra/host/t20/channel_t20.c b/drivers/video/tegra/host/t20/channel_t20.c index a3fb15212820..fdbf6ba7355d 100644 --- a/drivers/video/tegra/host/t20/channel_t20.c +++ b/drivers/video/tegra/host/t20/channel_t20.c @@ -232,7 +232,8 @@ static int t20_channel_submit(struct nvhost_channel *channel, /* gather restore buffer */ if (need_restore) - nvhost_cdma_push(&channel->cdma, + nvhost_cdma_push_gather(&channel->cdma, + nvmap_ref_to_handle(channel->cur_ctx->restore), nvhost_opcode_gather(channel->cur_ctx->restore_size), channel->cur_ctx->restore_phys); @@ -269,10 +270,13 @@ static int t20_channel_submit(struct nvhost_channel *channel, } else { /* push user gathers */ - for ( ; gather != gather_end; gather += 2) - nvhost_cdma_push(&channel->cdma, - nvhost_opcode_gather(gather[0]), - gather[1]); + int i = 0; + for ( ; i < gather_end-gather; i += 2) { + nvhost_cdma_push_gather(&channel->cdma, + unpins[i/2], + nvhost_opcode_gather(gather[i]), + gather[i+1]); + } } /* end CDMA submit & stash pinned hMems into sync queue */ diff --git a/drivers/video/tegra/host/t20/debug_t20.c b/drivers/video/tegra/host/t20/debug_t20.c index 0c77745b8c41..d3329bf2ed9e 100644 --- a/drivers/video/tegra/host/t20/debug_t20.c +++ b/drivers/video/tegra/host/t20/debug_t20.c @@ -19,12 +19,14 @@ #include #include +#include #include #include "../dev.h" #include "../debug.h" #include "../nvhost_cdma.h" +#include "../../nvmap/nvmap.h" #include "hardware_t20.h" @@ -34,7 +36,7 @@ enum { NVHOST_DBG_STATE_GATHER = 2 }; -static int show_channel_command(struct output *o, u32 val, int *count) +static int show_channel_command(struct output *o, u32 addr, u32 val, int *count) { unsigned mask; unsigned subop; @@ -104,11 +106,11 @@ static int show_channel_command(struct output *o, u32 val, int *count) * TODO: This uses ioremap_xxx on memory which is deprecated. * Also, it won't work properly with SMMU. */ -static void show_channel_gather(struct output *o, u32 phys_addr, - phys_addr_t words); +static void show_channel_gather(struct output *o, u32 addr, u32 phys_addr, + phys_addr_t words, struct nvhost_cdma *cdma); static void show_channel_word(struct output *o, int *state, int *count, - u32 addr, u32 val) + u32 addr, u32 val, struct nvhost_cdma *cdma) { switch (*state) { case NVHOST_DBG_STATE_CMD: @@ -117,7 +119,7 @@ static void show_channel_word(struct output *o, int *state, int *count, else nvhost_debug_output(o, "%08x:", val); - *state = show_channel_command(o, val, count); + *state = show_channel_command(o, addr, val, count); if (*state == NVHOST_DBG_STATE_DATA && *count == 0) { *state = NVHOST_DBG_STATE_CMD; nvhost_debug_output(o, "])\n"); @@ -134,38 +136,54 @@ static void show_channel_word(struct output *o, int *state, int *count, case NVHOST_DBG_STATE_GATHER: *state = NVHOST_DBG_STATE_CMD; nvhost_debug_output(o, "%08x]):\n", val); - show_channel_gather(o, val, *count); + if (cdma) + show_channel_gather(o, addr, val, *count, cdma); break; } } -static void show_channel_gather(struct output *o, phys_addr_t phys_addr, - u32 words) +static void show_channel_gather(struct output *o, u32 addr, + phys_addr_t phys_addr, + u32 words, struct nvhost_cdma *cdma) { + /* Calculate page boundary and offset */ phys_addr_t map_base = phys_addr & PAGE_MASK; - phys_addr_t map_end = (phys_addr + words * 4 + PAGE_SIZE - 1) & PAGE_MASK; - phys_addr_t map_size = map_end - map_base; phys_addr_t map_offset = phys_addr - map_base; - void *map_addr = ioremap_nocache(map_base, map_size); - int state = NVHOST_DBG_STATE_CMD; - int count, i; + /* Map dmaget cursor to corresponding nvmap_handle */ + struct push_buffer *pb = &cdma->push_buffer; + u32 cur = addr - pb->phys; + struct nvmap_handle *h = pb->handles[cur/8]; + + /* Create a fake nvmap_handle_ref - nvmap_mmap requires it + * but accesses only the first field - nvmap_handle */ + struct nvmap_handle_ref ref = {.handle = h}; + + u32 *map_addr; + int state, count, i; + + map_addr = nvmap_mmap(&ref); if (!map_addr) return; + + /* GATHER buffer starts always with commands */ + state = NVHOST_DBG_STATE_CMD; for (i = 0; i < words; i++) - show_channel_word(o, &state, &count, phys_addr + i * 4, - readl(map_addr + map_offset + i * 4)); - iounmap(map_addr); + show_channel_word(o, &state, &count, + phys_addr + i * 4, + *(map_addr + map_offset/4 + i), cdma); + + nvmap_munmap(&ref, map_addr); } static void show_channel_pair(struct output *o, u32 addr, - u32 w0, u32 w1) + u32 w0, u32 w1, struct nvhost_cdma *cdma) { int state = NVHOST_DBG_STATE_CMD; int count; - show_channel_word(o, &state, &count, addr, w0); - show_channel_word(o, &state, &count, addr, w1); + show_channel_word(o, &state, &count, addr, w0, cdma); + show_channel_word(o, &state, &count, addr+4, w1, cdma); } /** @@ -182,10 +200,20 @@ static void cdma_peek(struct nvhost_cdma *cdma, out[1] = p[offset + 1]; } +u32 previous_oppair(struct nvhost_cdma *cdma, u32 cur) +{ + u32 pb = cdma->push_buffer.phys; + u32 prev = cur-8; + if (prev < pb) + prev += PUSH_BUFFER_SIZE; + return prev; +} + static void t20_debug_show_channel_cdma(struct nvhost_master *m, struct output *o, int chid) { struct nvhost_channel *channel = m->channels + chid; + struct nvhost_cdma *cdma = &channel->cdma; u32 dmaput, dmaget, dmactrl; u32 cbstat, cbread; u32 val, base, baseval; @@ -198,7 +226,8 @@ static void t20_debug_show_channel_cdma(struct nvhost_master *m, cbstat = readl(m->aperture + HOST1X_SYNC_CBSTAT(chid)); nvhost_debug_output(o, "%d-%s (%d): ", chid, - channel->mod.name, atomic_read(&channel->mod.refcount)); + channel->mod.name, + atomic_read(&channel->mod.refcount)); if ((dmactrl & 1) || !channel->cdma.push_buffer.mapped) { nvhost_debug_output(o, "inactive\n\n"); @@ -223,13 +252,14 @@ static void t20_debug_show_channel_cdma(struct nvhost_master *m, break; default: - nvhost_debug_output(o, "active class %02x, offset %04x, val %08x\n", + nvhost_debug_output(o, + "active class %02x, offset %04x, val %08x\n", cbstat >> 16, cbstat & 0xffff, cbread); break; } - cdma_peek(&channel->cdma, dmaget, -1, pbw); - show_channel_pair(o, chid, pbw[0], pbw[1]); + cdma_peek(cdma, dmaget, -1, pbw); + show_channel_pair(o, previous_oppair(cdma, dmaget), pbw[0], pbw[1], &channel->cdma); nvhost_debug_output(o, "\n"); } @@ -264,7 +294,7 @@ void t20_debug_show_channel_fifo(struct nvhost_master *m, m->aperture + HOST1X_SYNC_CFPEEK_CTRL); val = readl(m->aperture + HOST1X_SYNC_CFPEEK_READ); - show_channel_word(o, &state, &count, 0, val); + show_channel_word(o, &state, &count, 0, val, NULL); if (rd_ptr == end) rd_ptr = start; -- cgit v1.2.3