summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorErik Gilling <konkers@android.com>2011-01-24 12:35:11 -0800
committerErik Gilling <konkers@android.com>2011-01-24 12:37:38 -0800
commit28b85f11c6dc65ac2c70f159a8210a4dd9554881 (patch)
treec1e10d428980c4b539168384fa5df72a4d0aa915 /drivers
parent3edd9628c0206b4239e2bcec977ca3b4e618a199 (diff)
video: tegra: dump host state when timing out on suspend
Change-Id: I718fb071ac74f5a051a7d5b9fcdd782163ed48b6 Signed-off-by: Erik Gilling <konkers@android.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/tegra/host/debug.c76
-rw-r--r--drivers/video/tegra/host/dev.h1
-rw-r--r--drivers/video/tegra/host/nvhost_acm.c9
3 files changed, 76 insertions, 10 deletions
diff --git a/drivers/video/tegra/host/debug.c b/drivers/video/tegra/host/debug.c
index c1cfd6ee229c..d533310e3999 100644
--- a/drivers/video/tegra/host/debug.c
+++ b/drivers/video/tegra/host/debug.c
@@ -22,7 +22,7 @@
#include "dev.h"
-#ifdef CONFIG_DEBUG_FS
+static struct nvhost_master *debug_master;
enum {
NVHOST_DBG_STATE_CMD = 0,
@@ -134,6 +134,28 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
nvhost_module_busy(&m->mod);
+ seq_printf(s, "---- mlocks ----\n");
+ for (i = 0; i < NV_HOST1X_NB_MLOCKS; i++) {
+ u32 owner = readl(m->sync_aperture + HOST1X_SYNC_MLOCK_OWNER_0 + i * 4);
+ if (owner & 0x1)
+ seq_printf(s, "%d: locked by channel %d\n", i, (owner >> 8) * 0xff);
+ else if (owner & 0x2)
+ seq_printf(s, "%d: locked by cpu\n", i);
+ else
+ seq_printf(s, "%d: unlocked\n", i);
+ }
+ seq_printf(s, "\n---- syncpts ----\n");
+ for (i = 0; i < NV_HOST1X_SYNCPT_NB_PTS; i++) {
+ u32 max = nvhost_syncpt_read_max(&m->syncpt, i);
+ if (!max)
+ continue;
+ seq_printf(s, "id %d (%s) min %d max %d\n",
+ i, nvhost_syncpt_name(i),
+ nvhost_syncpt_update_min(&m->syncpt, i), max);
+
+ }
+
+ seq_printf(s, "\n---- channels ----\n");
for (i = 0; i < NVHOST_NUMCHANNELS; i++) {
void __iomem *regs = m->channels[i].aperture;
u32 dmaput, dmaget, dmactrl;
@@ -152,15 +174,18 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
cbread = readl(m->aperture + HOST1X_SYNC_CBREAD(i));
cbstat = readl(m->aperture + HOST1X_SYNC_CBSTAT(i));
+ seq_printf(s, "%d-%s (%d): ", i, m->channels[i].mod.name,
+ m->channels[i].mod.refcount);
+
if (dmactrl != 0x0 || !m->channels[i].cdma.push_buffer.mapped) {
- seq_printf(s, "%d: inactive\n\n", i);
+ seq_printf(s, "inactive\n\n");
continue;
}
switch (cbstat) {
case 0x00010008:
- seq_printf(s, "%d: waiting on syncpt %d val %d\n",
- i, cbread >> 24, cbread & 0xffffff);
+ seq_printf(s, "waiting on syncpt %d val %d\n",
+ cbread >> 24, cbread & 0xffffff);
break;
case 0x00010009:
@@ -169,13 +194,13 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
val = readl(m->aperture + HOST1X_SYNC_SYNCPT_BASE(base)) & 0xffff;
val += cbread & 0xffff;
- seq_printf(s, "%d: waiting on syncpt %d val %d\n",
- i, cbread >> 24, val);
+ seq_printf(s, "waiting on syncpt %d val %d\n",
+ cbread >> 24, val);
break;
default:
- seq_printf(s, "%d: active class %02x, offset %04x, val %08x\n",
- i, cbstat >> 16, cbstat & 0xffff, cbread);
+ seq_printf(s, "active class %02x, offset %04x, val %08x\n",
+ cbstat >> 16, cbstat & 0xffff, cbread);
break;
}
@@ -244,6 +269,7 @@ static int nvhost_debug_show(struct seq_file *s, void *unused)
return 0;
}
+#ifdef CONFIG_DEBUG_FS
static int nvhost_debug_open(struct inode *inode, struct file *file)
{
@@ -259,12 +285,44 @@ static const struct file_operations nvhost_debug_fops = {
void nvhost_debug_init(struct nvhost_master *master)
{
+ debug_master = master;
debugfs_create_file("tegra_host", S_IRUGO, NULL, master, &nvhost_debug_fops);
}
#else
-void nvhost_debug_add(struct nvhost_master *master)
+void nvhost_debug_init(struct nvhost_master *master)
{
+ debug_master = master;
}
#endif
+static char nvhost_debug_dump_buff[16 * 1024];
+
+void nvhost_debug_dump(void)
+{
+ struct seq_file s;
+ int i;
+ char c;
+
+ memset(&s, 0x0, sizeof(s));
+
+ s.buf = nvhost_debug_dump_buff;
+ s.size = sizeof(nvhost_debug_dump_buff);
+ s.private = debug_master;
+
+ nvhost_debug_show(&s, NULL);
+
+ i = 0;
+ while (i < s.count ) {
+ if ((s.count - i) > 256) {
+ c = s.buf[i + 256];
+ s.buf[i + 256] = 0;
+ printk("%s", s.buf + i);
+ s.buf[i + 256] = c;
+ } else {
+ printk("%s", s.buf + i);
+ }
+ i += 256;
+ }
+}
+
diff --git a/drivers/video/tegra/host/dev.h b/drivers/video/tegra/host/dev.h
index ae9847c2bd74..4f71ff5d9a9d 100644
--- a/drivers/video/tegra/host/dev.h
+++ b/drivers/video/tegra/host/dev.h
@@ -48,5 +48,6 @@ struct nvhost_master {
};
void nvhost_debug_init(struct nvhost_master *master);
+void nvhost_debug_dump(void);
#endif
diff --git a/drivers/video/tegra/host/nvhost_acm.c b/drivers/video/tegra/host/nvhost_acm.c
index cf542be8a645..ef8f1ea2c13a 100644
--- a/drivers/video/tegra/host/nvhost_acm.c
+++ b/drivers/video/tegra/host/nvhost_acm.c
@@ -28,6 +28,8 @@
#include <mach/powergate.h>
#include <mach/clk.h>
+#include "dev.h"
+
#define ACM_TIMEOUT 1*HZ
#define DISABLE_3D_POWERGATING
@@ -194,7 +196,12 @@ static int is_module_idle(struct nvhost_module *mod)
void nvhost_module_suspend(struct nvhost_module *mod)
{
- wait_event(mod->idle, is_module_idle(mod));
+ int ret;
+
+ ret = wait_event_timeout(mod->idle, is_module_idle(mod),
+ ACM_TIMEOUT + msecs_to_jiffies(500));
+ if (ret == 0)
+ nvhost_debug_dump();
flush_delayed_work(&mod->powerdown);
BUG_ON(mod->powered);
}