diff options
author | Chris Johnson <cwj@cjohnson-dt2.nvidia.com> | 2011-02-05 01:37:38 -0800 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-03-16 19:43:31 -0800 |
commit | 87a9efe751716ca741caac72b9061fdfdcec540a (patch) | |
tree | 0e47e57faba89b2c089abe99bf8378b6fbec173a /drivers/video/tegra/host/nvhost_syncpt.c | |
parent | de005987c3eb20820d373caf4b13c09c8aa2bfc1 (diff) |
nvrm: move stale wait checking into the kernel
The kernel now receives wait tracking data (similar to gathers and
relocs) and compares the current syncpt with the threshold value.
If it's old, it gets a kernel mapping and rewrites the method data
to use a kernel reserved syncpt that is always 0 (so trivially pops
when seen by the HW).
Bug 519650
Bug 785525
Bug 803452
(cherry picked from commit 4069d8e67665624ad3dceb628e572980dd57acd0)
(cherry picked from commit 6e4336408588e348804a62e53386acc9abc06823)
Change-Id: I60374cb81318f9166e49aa2afca52c9d44d4a20e
Reviewed-on: http://git-master/r/23159
Tested-by: Nitin Kumbhar <nkumbhar@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
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; +} |