summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2012-05-24 11:30:30 +0300
committerSimone Willett <swillett@nvidia.com>2012-05-25 14:49:03 -0700
commit839b2b9c17da5b96ecccf0acf5e8c9d3ae3816af (patch)
tree1a36db656853e238b95235fa725b9ff938770634 /drivers
parent98c26489fd954b63655c805ff87b8dd6368b31d5 (diff)
video: tegra: host: Merge waitchk and relocation
Job pinning and relocation already maps the gather buffers to kernel memory. Move waitchk to be done at the same time so that we do not need to re-map the memory to patch expired waits. Bug 965206 Change-Id: I23634b501a45de080200e57d3debf267b39fea38 Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Reviewed-on: http://git-master/r/104415 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Juha Tukkinen <jtukkinen@nvidia.com> Reviewed-by: Mayuresh Kulkarni <mkulkarni@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/tegra/host/bus_client.c8
-rw-r--r--drivers/video/tegra/host/chip_support.h8
-rw-r--r--drivers/video/tegra/host/host1x/host1x_channel.c16
-rw-r--r--drivers/video/tegra/host/host1x/host1x_syncpt.c64
-rw-r--r--drivers/video/tegra/host/nvhost_channel.h1
-rw-r--r--drivers/video/tegra/host/nvhost_job.c58
-rw-r--r--drivers/video/tegra/host/nvhost_job.h7
-rw-r--r--drivers/video/tegra/host/nvhost_syncpt.c13
-rw-r--r--drivers/video/tegra/host/nvhost_syncpt.h18
9 files changed, 81 insertions, 112 deletions
diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c
index 822f8f3a456d..397cd21f555d 100644
--- a/drivers/video/tegra/host/bus_client.c
+++ b/drivers/video/tegra/host/bus_client.c
@@ -306,7 +306,7 @@ static int nvhost_ioctl_channel_flush(
struct nvhost_get_param_args *args,
int null_kickoff)
{
- struct device *device = &ctx->ch->dev->dev;
+ struct nvhost_device *ndev = to_nvhost_device(&ctx->ch->dev->dev);
int err;
trace_nvhost_ioctl_channel_flush(ctx->ch->dev->name);
@@ -316,13 +316,13 @@ static int nvhost_ioctl_channel_flush(
ctx->hdr.num_cmdbufs ||
ctx->hdr.num_waitchks) {
reset_submit(ctx);
- dev_err(device, "channel submit out of sync\n");
+ dev_err(&ndev->dev, "channel submit out of sync\n");
return -EFAULT;
}
- err = nvhost_job_pin(ctx->job);
+ err = nvhost_job_pin(ctx->job, &nvhost_get_host(ndev)->syncpt);
if (err) {
- dev_warn(device, "nvhost_job_pin failed: %d\n", err);
+ dev_warn(&ndev->dev, "nvhost_job_pin failed: %d\n", err);
return err;
}
diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h
index 173a36065458..d69e1c4bccb9 100644
--- a/drivers/video/tegra/host/chip_support.h
+++ b/drivers/video/tegra/host/chip_support.h
@@ -28,7 +28,6 @@ struct output;
struct nvhost_master;
struct nvhost_intr;
struct nvhost_syncpt;
-struct nvhost_waitchk;
struct nvhost_userctx_timeout;
struct nvhost_channel;
struct nvmap_handle_ref;
@@ -106,11 +105,8 @@ struct nvhost_chip_support {
void (*read_wait_base)(struct nvhost_syncpt *, u32 id);
u32 (*update_min)(struct nvhost_syncpt *, u32 id);
void (*cpu_incr)(struct nvhost_syncpt *, u32 id);
- int (*wait_check)(struct nvhost_syncpt *sp,
- struct nvmap_client *nvmap,
- u32 waitchk_mask,
- struct nvhost_waitchk *wait,
- int num_waitchk);
+ int (*patch_wait)(struct nvhost_syncpt *sp,
+ void *patch_addr);
void (*debug)(struct nvhost_syncpt *);
const char * (*name)(struct nvhost_syncpt *, u32 id);
int (*mutex_try_lock)(struct nvhost_syncpt *,
diff --git a/drivers/video/tegra/host/host1x/host1x_channel.c b/drivers/video/tegra/host/host1x/host1x_channel.c
index 0b4d07cb9e47..c72e6478b806 100644
--- a/drivers/video/tegra/host/host1x/host1x_channel.c
+++ b/drivers/video/tegra/host/host1x/host1x_channel.c
@@ -242,22 +242,6 @@ int host1x_channel_submit(struct nvhost_job *job)
goto error;
}
- /* remove stale waits */
- if (job->num_waitchk) {
- err = nvhost_syncpt_wait_check(sp,
- job->nvmap,
- job->waitchk_mask,
- job->waitchk,
- job->num_waitchk);
- if (err) {
- dev_warn(&ch->dev->dev,
- "nvhost_syncpt_wait_check failed: %d\n", err);
- mutex_unlock(&ch->submitlock);
- nvhost_module_idle(ch->dev);
- goto error;
- }
- }
-
/* begin a CDMA submit */
err = nvhost_cdma_begin(&ch->cdma, job);
if (err) {
diff --git a/drivers/video/tegra/host/host1x/host1x_syncpt.c b/drivers/video/tegra/host/host1x/host1x_syncpt.c
index b7d6587acc61..4cc8e9e212fa 100644
--- a/drivers/video/tegra/host/host1x/host1x_syncpt.c
+++ b/drivers/video/tegra/host/host1x/host1x_syncpt.c
@@ -103,62 +103,14 @@ static void t20_syncpt_cpu_incr(struct nvhost_syncpt *sp, u32 id)
wmb();
}
-/* check for old WAITs to be removed (avoiding a wrap) */
-static int t20_syncpt_wait_check(struct nvhost_syncpt *sp,
- struct nvmap_client *nvmap,
- u32 waitchk_mask,
- struct nvhost_waitchk *wait,
- int num_waitchk)
+/* remove a wait pointed to by patch_addr */
+static int host1x_syncpt_patch_wait(struct nvhost_syncpt *sp,
+ void *patch_addr)
{
- 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(!wait && !num_waitchk);
-
- /* compare syncpt vs wait threshold */
- while (num_waitchk) {
- u32 override;
-
- BUG_ON(wait->syncpt_id >= NV_HOST1X_SYNCPT_NB_PTS);
- trace_nvhost_syncpt_wait_check(wait->mem, wait->offset,
- wait->syncpt_id, wait->thresh);
- if (nvhost_syncpt_is_expired(sp,
- wait->syncpt_id, wait->thresh)) {
- /*
- * NULL an already satisfied WAIT_SYNCPT host method,
- * by patching its args in the command stream. The
- * method data is changed to reference a reserved
- * (never given out or incr) NVSYNCPT_GRAPHICS_HOST
- * syncpt with a matching threshold value of 0, so
- * is guaranteed to be popped by the host HW.
- */
- dev_dbg(&syncpt_to_dev(sp)->dev->dev,
- "drop WAIT id %d (%s) thresh 0x%x, min 0x%x\n",
- wait->syncpt_id,
- syncpt_op().name(sp, wait->syncpt_id),
- wait->thresh,
- nvhost_syncpt_read_min(sp, wait->syncpt_id));
-
- /* patch the wait */
- override = nvhost_class_host_wait_syncpt(
- NVSYNCPT_GRAPHICS_HOST, 0);
- err = nvmap_patch_word(nvmap,
- (struct nvmap_handle *)wait->mem,
- wait->offset, override);
- if (err)
- break;
- }
-
- wait++;
- num_waitchk--;
- }
- return err;
+ u32 override = nvhost_class_host_wait_syncpt(
+ NVSYNCPT_GRAPHICS_HOST, 0);
+ __raw_writel(override, patch_addr);
+ return 0;
}
@@ -241,7 +193,7 @@ int host1x_init_syncpt_support(struct nvhost_master *host,
op->syncpt.read_wait_base = t20_syncpt_read_wait_base;
op->syncpt.update_min = t20_syncpt_update_min;
op->syncpt.cpu_incr = t20_syncpt_cpu_incr;
- op->syncpt.wait_check = t20_syncpt_wait_check;
+ op->syncpt.patch_wait = host1x_syncpt_patch_wait;
op->syncpt.debug = t20_syncpt_debug;
op->syncpt.name = t20_syncpt_name;
op->syncpt.mutex_try_lock = syncpt_mutex_try_lock;
diff --git a/drivers/video/tegra/host/nvhost_channel.h b/drivers/video/tegra/host/nvhost_channel.h
index a8f16f0c5abc..b3a904d5a3ee 100644
--- a/drivers/video/tegra/host/nvhost_channel.h
+++ b/drivers/video/tegra/host/nvhost_channel.h
@@ -31,7 +31,6 @@
#define NVHOST_MAX_POWERGATE_IDS 2
struct nvhost_master;
-struct nvhost_waitchk;
struct nvhost_device;
struct nvhost_channel;
struct nvhost_hwctx;
diff --git a/drivers/video/tegra/host/nvhost_job.c b/drivers/video/tegra/host/nvhost_job.c
index 11d65964e2c9..6d8c3bd2bd50 100644
--- a/drivers/video/tegra/host/nvhost_job.c
+++ b/drivers/video/tegra/host/nvhost_job.c
@@ -27,6 +27,7 @@
#include "nvhost_channel.h"
#include "nvhost_job.h"
#include "nvhost_hwctx.h"
+#include "nvhost_syncpt.h"
#include "dev.h"
/* Magic to use to fill freed handle slots */
@@ -196,11 +197,63 @@ static int do_relocs(struct nvhost_job *job, u32 patch_mem, void *patch_addr)
return 0;
}
-int nvhost_job_pin(struct nvhost_job *job)
+/*
+ * Check driver supplied waitchk structs for syncpt thresholds
+ * that have already been satisfied and NULL the comparison (to
+ * avoid a wrap condition in the HW).
+ */
+static int do_waitchks(struct nvhost_job *job, struct nvhost_syncpt *sp,
+ u32 patch_mem, void *patch_addr)
+{
+ int i;
+
+ /* compare syncpt vs wait threshold */
+ for (i = 0; i < job->num_waitchk; i++) {
+ struct nvhost_waitchk *wait = &job->waitchk[i];
+
+ /* skip all other gathers */
+ if (patch_mem != wait->mem)
+ continue;
+
+ trace_nvhost_syncpt_wait_check(wait->mem, wait->offset,
+ wait->syncpt_id, wait->thresh);
+ if (nvhost_syncpt_is_expired(sp,
+ wait->syncpt_id, wait->thresh)) {
+ /*
+ * NULL an already satisfied WAIT_SYNCPT host method,
+ * by patching its args in the command stream. The
+ * method data is changed to reference a reserved
+ * (never given out or incr) NVSYNCPT_GRAPHICS_HOST
+ * syncpt with a matching threshold value of 0, so
+ * is guaranteed to be popped by the host HW.
+ */
+ dev_dbg(&syncpt_to_dev(sp)->dev->dev,
+ "drop WAIT id %d (%s) thresh 0x%x, min 0x%x\n",
+ wait->syncpt_id,
+ syncpt_op().name(sp, wait->syncpt_id),
+ wait->thresh,
+ nvhost_syncpt_read_min(sp, wait->syncpt_id));
+
+ /* patch the wait */
+ nvhost_syncpt_patch_wait(sp,
+ (patch_addr + wait->offset));
+ }
+
+ wait->mem = 0;
+ }
+ return 0;
+}
+
+int nvhost_job_pin(struct nvhost_job *job, struct nvhost_syncpt *sp)
{
int err = 0, i = 0;
phys_addr_t gather_phys = 0;
void *gather_addr = NULL;
+ unsigned long waitchk_mask = job->waitchk_mask;
+
+ /* get current syncpt values for waitchk */
+ for_each_set_bit(i, &waitchk_mask, sizeof(job->waitchk_mask))
+ nvhost_syncpt_update_min(sp, i);
/* pin gathers */
for (i = 0; i < job->num_gathers; i++) {
@@ -233,6 +286,9 @@ int nvhost_job_pin(struct nvhost_job *job)
}
err = do_relocs(job, g->mem_id, gather_addr);
+ if (!err)
+ err = do_waitchks(job, sp,
+ g->mem_id, gather_addr);
nvmap_munmap(g->ref, gather_addr);
if (err)
diff --git a/drivers/video/tegra/host/nvhost_job.h b/drivers/video/tegra/host/nvhost_job.h
index 48555a231412..b30f5faf7e8f 100644
--- a/drivers/video/tegra/host/nvhost_job.h
+++ b/drivers/video/tegra/host/nvhost_job.h
@@ -27,7 +27,7 @@ struct nvhost_channel;
struct nvhost_hwctx;
struct nvmap_client;
struct nvhost_waitchk;
-struct nvmap_handle;
+struct nvhost_syncpt;
struct nvhost_job_gather {
u32 words;
@@ -129,8 +129,11 @@ void nvhost_job_put(struct nvhost_job *job);
* Pin memory related to job. This handles relocation of addresses to the
* host1x address space. Handles both the gather memory and any other memory
* referred to from the gather buffers.
+ *
+ * Handles also patching out host waits that would wait for an expired sync
+ * point value.
*/
-int nvhost_job_pin(struct nvhost_job *job);
+int nvhost_job_pin(struct nvhost_job *job, struct nvhost_syncpt *sp);
/*
* Unpin memory related to job.
diff --git a/drivers/video/tegra/host/nvhost_syncpt.c b/drivers/video/tegra/host/nvhost_syncpt.c
index 1458a7cb5acc..7550512b0214 100644
--- a/drivers/video/tegra/host/nvhost_syncpt.c
+++ b/drivers/video/tegra/host/nvhost_syncpt.c
@@ -74,7 +74,7 @@ u32 nvhost_syncpt_update_min(struct nvhost_syncpt *sp, u32 id)
BUG_ON(!syncpt_op().update_min);
- return syncpt_op().update_min(sp, id);
+ val = syncpt_op().update_min(sp, id);
trace_nvhost_syncpt_update_min(id, val);
return val;
@@ -330,15 +330,10 @@ void nvhost_mutex_unlock(struct nvhost_syncpt *sp, int idx)
atomic_dec(&sp->lock_counts[idx]);
}
-/* check for old WAITs to be removed (avoiding a wrap) */
-int nvhost_syncpt_wait_check(struct nvhost_syncpt *sp,
- struct nvmap_client *nvmap,
- u32 waitchk_mask,
- struct nvhost_waitchk *wait,
- int num_waitchk)
+/* remove a wait pointed to by patch_addr */
+int nvhost_syncpt_patch_wait(struct nvhost_syncpt *sp, void *patch_addr)
{
- return syncpt_op().wait_check(sp, nvmap,
- waitchk_mask, wait, num_waitchk);
+ return syncpt_op().patch_wait(sp, patch_addr);
}
/* Displays the current value of the sync point via sysfs */
diff --git a/drivers/video/tegra/host/nvhost_syncpt.h b/drivers/video/tegra/host/nvhost_syncpt.h
index b770ed91c76c..b58921bffa9c 100644
--- a/drivers/video/tegra/host/nvhost_syncpt.h
+++ b/drivers/video/tegra/host/nvhost_syncpt.h
@@ -136,23 +136,7 @@ static inline int nvhost_syncpt_wait(struct nvhost_syncpt *sp, u32 id, u32 thres
MAX_SCHEDULE_TIMEOUT, NULL);
}
-/*
- * Check driver supplied waitchk structs for syncpt thresholds
- * that have already been satisfied and NULL the comparison (to
- * avoid a wrap condition in the HW).
- *
- * @param: sp - global shadowed syncpt struct
- * @param: nvmap - needed to access command buffer
- * @param: mask - bit mask of syncpt IDs referenced in WAITs
- * @param: wait - start of filled in array of waitchk structs
- * @param: waitend - end ptr (one beyond last valid waitchk)
- */
-struct nvhost_waitchk;
-int nvhost_syncpt_wait_check(struct nvhost_syncpt *sp,
- struct nvmap_client *nvmap,
- u32 mask,
- struct nvhost_waitchk *wait,
- int num_waitchk);
+int nvhost_syncpt_patch_wait(struct nvhost_syncpt *sp, void *patch_addr);
void nvhost_syncpt_debug(struct nvhost_syncpt *sp);