diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2011-10-24 15:08:43 +0300 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-11-07 13:50:29 -0800 |
commit | 420a73b658b5c2236f3e1433a61304c08cfdf1d3 (patch) | |
tree | 9cf4860ef2c21afaee268af4d97a0c131555f32f /drivers | |
parent | b8d1c4365628577236106a7ec7029f128629d530 (diff) |
video: tegra: host: Add extra syncpt debug info
Add extra syncpt debug info and kernel panic when device stuck
waiting at syncpts.
Tested by inducing syncpt stuck-wait by bypassing nvhost_syncpt-
_cpu_incr.
Bug 822880
Bug 820056
Bug 818058
Bug 810463
Bug 803452
Reviewed-on: http://git-master/r/60206
(cherry picked from commit e73caae974f43ac5bf30589fc3cbc1fa66df926e)
Change-Id: Ia9a99cad17cbf49bf2fb860f783d0e94de0cec8e
Reviewed-on: http://git-master/r/62355
Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-by: Yu-Huan Hsu <yhsu@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/video/tegra/host/nvhost_syncpt.c | 9 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_syncpt.h | 21 | ||||
-rw-r--r-- | drivers/video/tegra/host/t20/syncpt_t20.c | 43 |
3 files changed, 46 insertions, 27 deletions
diff --git a/drivers/video/tegra/host/nvhost_syncpt.c b/drivers/video/tegra/host/nvhost_syncpt.c index 1c63b69fb294..f5e788551a05 100644 --- a/drivers/video/tegra/host/nvhost_syncpt.c +++ b/drivers/video/tegra/host/nvhost_syncpt.c @@ -119,9 +119,11 @@ int nvhost_syncpt_wait_timeout(struct nvhost_syncpt *sp, u32 id, BUG_ON(!syncpt_op(sp).update_min); if (!nvhost_syncpt_check_max(sp, id, thresh)) { - WARN(1, "wait %d (%s) for (%d) wouldn't be met (max %d)\n", + dev_warn(&syncpt_to_dev(sp)->pdev->dev, + "wait %d (%s) for (%d) wouldn't be met (max %d)\n", id, syncpt_op(sp).name(sp, id), thresh, nvhost_syncpt_read_max(sp, id)); + nvhost_debug_dump(syncpt_to_dev(sp)); return -EINVAL; } @@ -185,8 +187,9 @@ int nvhost_syncpt_wait_timeout(struct nvhost_syncpt *sp, u32 id, timeout -= check; if (timeout) { dev_warn(&syncpt_to_dev(sp)->pdev->dev, - "syncpoint id %d (%s) stuck waiting %d\n", - id, syncpt_op(sp).name(sp, id), thresh); + "%s: syncpoint id %d (%s) stuck waiting %d, timeout=%d\n", + current->comm, id, syncpt_op(sp).name(sp, id), + thresh, timeout); syncpt_op(sp).debug(sp); } } diff --git a/drivers/video/tegra/host/nvhost_syncpt.h b/drivers/video/tegra/host/nvhost_syncpt.h index c8f8b4bb1262..b8d15383c510 100644 --- a/drivers/video/tegra/host/nvhost_syncpt.h +++ b/drivers/video/tegra/host/nvhost_syncpt.h @@ -50,17 +50,6 @@ int nvhost_syncpt_init(struct nvhost_syncpt *); #define syncpt_to_dev(sp) container_of(sp, struct nvhost_master, syncpt) #define syncpt_op(sp) (syncpt_to_dev(sp)->op.syncpt) #define SYNCPT_CHECK_PERIOD 2*HZ -static inline bool nvhost_syncpt_check_max(struct nvhost_syncpt *sp, u32 id, u32 real) -{ - u32 max; - if (client_managed(id)) - return true; - smp_rmb(); - max = (u32)atomic_read(&sp->max_val[id]); - return ((s32)(max - real) >= 0); -} - - /** * Updates the value sent to hardware. */ @@ -93,6 +82,16 @@ static inline u32 nvhost_syncpt_read_min(struct nvhost_syncpt *sp, u32 id) return (u32)atomic_read(&sp->min_val[id]); } +static inline bool nvhost_syncpt_check_max(struct nvhost_syncpt *sp, + u32 id, u32 real) +{ + u32 max; + if (client_managed(id)) + return true; + max = nvhost_syncpt_read_max(sp, id); + return (s32)(max - real) >= 0; +} + /** * Returns true if syncpoint has reached threshold */ diff --git a/drivers/video/tegra/host/t20/syncpt_t20.c b/drivers/video/tegra/host/t20/syncpt_t20.c index 781654b656da..c42877493582 100644 --- a/drivers/video/tegra/host/t20/syncpt_t20.c +++ b/drivers/video/tegra/host/t20/syncpt_t20.c @@ -33,9 +33,7 @@ static void t20_syncpt_reset(struct nvhost_syncpt *sp, u32 id) { struct nvhost_master *dev = syncpt_to_dev(sp); - int min; - smp_rmb(); - min = atomic_read(&sp->min_val[id]); + int min = nvhost_syncpt_read_min(sp, id); writel(min, dev->sync_aperture + (HOST1X_SYNC_SYNCPT_0 + id * 4)); } @@ -70,13 +68,18 @@ static u32 t20_syncpt_update_min(struct nvhost_syncpt *sp, u32 id) u32 old, live; do { - smp_rmb(); - old = (u32)atomic_read(&sp->min_val[id]); + old = nvhost_syncpt_read_min(sp, id); live = readl(sync_regs + (HOST1X_SYNC_SYNCPT_0 + id * 4)); } while ((u32)atomic_cmpxchg(&sp->min_val[id], old, live) != old); - BUG_ON(!nvhost_syncpt_check_max(sp, id, live)); - + if (!nvhost_syncpt_check_max(sp, id, live)) { + dev_err(&syncpt_to_dev(sp)->pdev->dev, + "%s failed: id=%u\n", + __func__, + id); + nvhost_debug_dump(syncpt_to_dev(sp)); + BUG(); + } return live; } @@ -88,7 +91,13 @@ static void t20_syncpt_cpu_incr(struct nvhost_syncpt *sp, u32 id) { struct nvhost_master *dev = syncpt_to_dev(sp); BUG_ON(!nvhost_module_powered(&dev->mod)); - BUG_ON(!client_managed(id) && nvhost_syncpt_min_eq_max(sp, id)); + if (!client_managed(id) && nvhost_syncpt_min_eq_max(sp, id)) { + dev_err(&syncpt_to_dev(sp)->pdev->dev, + "Syncpoint id %d\n", + id); + nvhost_debug_dump(syncpt_to_dev(sp)); + BUG(); + } writel(BIT(id), dev->sync_aperture + HOST1X_SYNC_SYNCPT_CPU_INCR); wmb(); } @@ -162,12 +171,20 @@ static int t20_syncpt_wait_check(struct nvhost_syncpt *sp, static const char *s_syncpt_names[32] = { - "gfx_host", "", "", "", "", "", "", "", "", "", "avp_0", - "csi_vi_0", "csi_vi_1", "vi_isp_0", "vi_isp_1", "vi_isp_2", "vi_isp_3", "vi_isp_4", + "gfx_host", + "", "", "", "", "", "", "", + "disp0_a", "disp1_a", "avp_0", + "csi_vi_0", "csi_vi_1", + "vi_isp_0", "vi_isp_1", "vi_isp_2", "vi_isp_3", "vi_isp_4", "2d_0", "2d_1", - "", "", - "3d", "mpe", "disp0", "disp1", "vblank0", "vblank1", "mpe_ebm_eof", "mpe_wr_safe", - "2d_tinyblt", "dsi" + "disp0_b", "disp1_b", + "3d", + "mpe", + "disp0_c", "disp1_c", + "vblank0", "vblank1", + "mpe_ebm_eof", "mpe_wr_safe", + "2d_tinyblt", + "dsi" }; static const char *t20_syncpt_name(struct nvhost_syncpt *s, u32 id) |