diff options
Diffstat (limited to 'drivers/video/tegra/host/nvhost_syncpt.c')
-rw-r--r-- | drivers/video/tegra/host/nvhost_syncpt.c | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/drivers/video/tegra/host/nvhost_syncpt.c b/drivers/video/tegra/host/nvhost_syncpt.c index dd2ab0d379e0..1881716ed428 100644 --- a/drivers/video/tegra/host/nvhost_syncpt.c +++ b/drivers/video/tegra/host/nvhost_syncpt.c @@ -226,7 +226,7 @@ done: } static const char *s_syncpt_names[32] = { - "", "", "", "", "", "", "", "", "", "", "", "", + "gfx_host", "", "", "", "", "", "", "", "", "", "", "", "vi_isp_0", "vi_isp_1", "vi_isp_2", "vi_isp_3", "vi_isp_4", "vi_isp_5", "2d_0", "2d_1", "", "", @@ -254,3 +254,63 @@ void nvhost_syncpt_debug(struct nvhost_syncpt *sp) } } + +/* returns true, if a <= b < c using wrapping comparison */ +static inline bool nvhost_syncpt_is_between(u32 a, u32 b, u32 c) +{ + return b-a < c-a; +} + +/* returns true, if x >= y (mod 1 << 32) */ +static bool nvhost_syncpt_wrapping_comparison(u32 x, u32 y) +{ + return nvhost_syncpt_is_between(y, x, (1UL<<31UL)+y); +} + +/* check for old WAITs to be removed (avoiding a wrap) */ +int nvhost_syncpt_wait_check(struct nvmap_client *nvmap, + struct nvhost_syncpt *sp, u32 waitchk_mask, + struct nvhost_waitchk *waitp, u32 waitchks) +{ + u32 idx; + int err = 0; + + /* get current syncpt values */ + for (idx = 0; idx < NV_HOST1X_SYNCPT_NB_PTS; idx++) { + if (BIT(idx) & waitchk_mask) { + nvhost_syncpt_update_min(sp, idx); + } + } + + BUG_ON(!waitp); + + /* compare syncpt vs wait threshold */ + while (waitchks) { + u32 syncpt, override; + + BUG_ON(waitp->syncpt_id > NV_HOST1X_SYNCPT_NB_PTS); + + syncpt = atomic_read(&sp->min_val[waitp->syncpt_id]); + if (nvhost_syncpt_wrapping_comparison(syncpt, waitp->thresh)) { + + /* wait has completed already, so can be removed */ + dev_dbg(&syncpt_to_dev(sp)->pdev->dev, + "drop WAIT id %d (%s) thresh 0x%x, syncpt 0x%x\n", + waitp->syncpt_id, nvhost_syncpt_name(waitp->syncpt_id), + waitp->thresh, syncpt); + + /* move wait to a kernel reserved syncpt (that's always 0) */ + override = nvhost_class_host_wait_syncpt(NVSYNCPT_GRAPHICS_HOST, 0); + + /* patch the wait */ + err = nvmap_patch_wait(nvmap, + (struct nvmap_handle *)waitp->mem, + waitp->offset, override); + if (err) + break; + } + waitchks--; + waitp++; + } + return err; +} |