summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2011-07-29 09:09:43 +0300
committerVarun Colbert <vcolbert@nvidia.com>2011-08-17 16:23:19 -0700
commitf8c80f4ea8930af9e2e93765e635d84fe6e22575 (patch)
treee6c6aa1733c800b5dbb8662097b6407d53650283 /drivers
parentb6aad8653ca8bbdd964c8fafcb1faab96c88f9af (diff)
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 <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/44779 Reviewed-by: Varun Colbert <vcolbert@nvidia.com> Tested-by: Varun Colbert <vcolbert@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/tegra/host/chip_support.h1
-rw-r--r--drivers/video/tegra/host/nvhost_cdma.c15
-rw-r--r--drivers/video/tegra/host/nvhost_cdma.h13
-rw-r--r--drivers/video/tegra/host/t20/3dctx_t20.c6
-rw-r--r--drivers/video/tegra/host/t20/cdma_t20.c14
-rw-r--r--drivers/video/tegra/host/t20/channel_t20.c14
-rw-r--r--drivers/video/tegra/host/t20/debug_t20.c78
7 files changed, 102 insertions, 39 deletions
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
@@ -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);
}
/**
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 <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); */
}
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 <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;