nvhost: Fix tegra_host/status debug output
Terje Bergstrom [Fri, 29 Jul 2011 06:09:43 +0000 (09:09 +0300)]
Add tracking of mapping between push buffer gathers and nvmap handles.
Use the mapping to access contents of gather buffers.

Bug 840976

Original-Change-Id: Ic6fe2fc7a83e8f14cd606a9e638b6420aa714495
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/44779
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>

Rebase-Id: Rd0c946095890cfe15a68d3c5eaa181a9ac02cf07

drivers/video/tegra/host/chip_support.h
drivers/video/tegra/host/nvhost_cdma.c
drivers/video/tegra/host/nvhost_cdma.h
drivers/video/tegra/host/t20/3dctx_t20.c
drivers/video/tegra/host/t20/cdma_t20.c
drivers/video/tegra/host/t20/channel_t20.c
drivers/video/tegra/host/t20/debug_t20.c

index a0b0f02..eae9967 100644 (file)
@@ -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);
index 24c0c0f..fcce833 100644 (file)
@@ -408,17 +408,28 @@ void nvhost_cdma_begin(struct nvhost_cdma *cdma)
  */
 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;
        BUG_ON(!cdma_pb_op(cdma).push_to);
        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);
 }
 
 /**
index e48d733..45c2f7c 100644 (file)
 
 
 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,
index f3f1e94..dadfbed 100644 (file)
@@ -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);
 }
index 77f514e..eaba1c7 100644 (file)
@@ -20,6 +20,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
+#include <linux/slab.h>
 #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); */
 }
index a3fb152..fdbf6ba 100644 (file)
@@ -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 */
index 0c77745..d3329bf 100644 (file)
 
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/mm.h>
 
 #include <asm/io.h>
 
 #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;