summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/host/nvhost_syncpt.c
diff options
context:
space:
mode:
authorChris Johnson <cwj@cjohnson-dt2.nvidia.com>2011-02-05 01:37:38 -0800
committerVarun Colbert <vcolbert@nvidia.com>2011-03-16 19:43:31 -0800
commit87a9efe751716ca741caac72b9061fdfdcec540a (patch)
tree0e47e57faba89b2c089abe99bf8378b6fbec173a /drivers/video/tegra/host/nvhost_syncpt.c
parentde005987c3eb20820d373caf4b13c09c8aa2bfc1 (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.c62
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;
+}