summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAntoine Chauveau <achauveau@nvidia.com>2010-08-11 10:55:17 +0300
committerAntti Hatala <ahatala@nvidia.com>2010-08-19 06:09:18 -0700
commitd535635a14a7f5f82ab10456bd49e32c49285e00 (patch)
tree522a9f1174d3fd95059959744695de4e60bc8422 /drivers
parent99a3207d5fce5b87654cb90d26a03b2ae19bf57c (diff)
nvhost: Reimplement null kickoff functionality.
For each channel submit where null kickoff is requested, we don't place the user's commands in the pushbuffer. All necessary context switches, syncpoint increments and waitbase increments do happen though. Bug 717235 Change-Id: I51c323729ea57993a5b52fb395ab90cb8608ee6b Reviewed-on: http://git-master/r/5091 Reviewed-by: Antoine Chauveau <achauveau@nvidia.com> Reviewed-by: Antti Hatala <ahatala@nvidia.com> Tested-by: Antti Hatala <ahatala@nvidia.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/video/tegra/host/nvhost_channel.c30
-rw-r--r--drivers/video/tegra/host/nvhost_channel.h3
-rw-r--r--drivers/video/tegra/host/nvhost_dev.c7
3 files changed, 35 insertions, 5 deletions
diff --git a/drivers/video/tegra/host/nvhost_channel.c b/drivers/video/tegra/host/nvhost_channel.c
index f75ee292b57a..5adcf2175684 100644
--- a/drivers/video/tegra/host/nvhost_channel.c
+++ b/drivers/video/tegra/host/nvhost_channel.c
@@ -180,7 +180,8 @@ void nvhost_channel_submit(
struct nvmap_handle **unpins,
int num_unpins,
u32 syncpt_id,
- u32 syncpt_val)
+ u32 syncpt_val,
+ int num_nulled_incrs)
{
int i;
struct nvhost_op_pair* p;
@@ -198,6 +199,31 @@ void nvhost_channel_submit(
for (i = 0, p = ops; i < num_pairs; i++, p++)
nvhost_cdma_push(&ch->cdma, p->op1, p->op2);
+ /* extra work to do for null kickoff */
+ if (num_nulled_incrs) {
+ u32 incr;
+ u32 op_incr;
+
+ /* TODO ideally we'd also perform host waits here */
+
+ /* push increments that correspond to nulled out commands */
+ op_incr = nvhost_opcode_imm(0, 0x100 | syncpt_id);
+ for (incr = 0; incr < (num_nulled_incrs >> 1); incr++)
+ nvhost_cdma_push(&ch->cdma, op_incr, op_incr);
+ if (num_nulled_incrs & 1)
+ nvhost_cdma_push(&ch->cdma, op_incr, NVHOST_OPCODE_NOOP);
+
+ /* for 3d, waitbase needs to be incremented after each submit */
+ if (ch->desc->class == NV_GRAPHICS_3D_CLASS_ID) {
+ u32 op1 = nvhost_opcode_setclass(NV_HOST1X_CLASS_ID,
+ NV_CLASS_HOST_INCR_SYNCPT_BASE, 1);
+ u32 op2 = nvhost_class_host_incr_syncpt_base(NVWAITBASE_3D,
+ num_nulled_incrs);
+
+ nvhost_cdma_push(&ch->cdma, op1, op2);
+ }
+ }
+
/* end CDMA submit & stash pinned hMems into sync queue for later cleanup */
nvhost_cdma_end(&ch->cdma, syncpt_id, syncpt_val, unpins, num_unpins);
}
@@ -231,7 +257,7 @@ static void power_3d(struct nvhost_module *mod, enum nvhost_power_action action)
ch->cur_ctx->valid = true;
ch->ctxhandler.get(ch->cur_ctx);
ch->cur_ctx = NULL;
- nvhost_channel_submit(ch, &save, 1, &ctxsw, 1, NULL, 0, NVSYNCPT_3D, syncval);
+ nvhost_channel_submit(ch, &save, 1, &ctxsw, 1, NULL, 0, NVSYNCPT_3D, syncval, 0);
nvhost_intr_add_action(&ch->dev->intr, NVSYNCPT_3D, syncval,
NVHOST_INTR_ACTION_WAKEUP, &wq, NULL);
wait_event(wq, nvhost_syncpt_min_cmp(&ch->dev->syncpt, NVSYNCPT_3D, syncval));
diff --git a/drivers/video/tegra/host/nvhost_channel.h b/drivers/video/tegra/host/nvhost_channel.h
index a32f97266c02..193aa0395bb5 100644
--- a/drivers/video/tegra/host/nvhost_channel.h
+++ b/drivers/video/tegra/host/nvhost_channel.h
@@ -85,7 +85,8 @@ void nvhost_channel_submit(
struct nvmap_handle **unpins,
int num_unpins,
u32 syncpt_id,
- u32 syncpt_val);
+ u32 syncpt_val,
+ int num_nulled_incrs);
struct nvhost_channel *nvhost_getchannel(struct nvhost_channel *ch);
void nvhost_putchannel(struct nvhost_channel *ch, struct nvhost_hwctx *ctx);
diff --git a/drivers/video/tegra/host/nvhost_dev.c b/drivers/video/tegra/host/nvhost_dev.c
index b74e140d278e..bc63d24c73b7 100644
--- a/drivers/video/tegra/host/nvhost_dev.c
+++ b/drivers/video/tegra/host/nvhost_dev.c
@@ -47,6 +47,7 @@ struct nvhost_channel_userctx {
u32 syncpt_incrs;
u32 cmdbufs_pending;
u32 relocs_pending;
+ u32 null_kickoff;
struct nvmap_handle *gather_mem;
struct nvhost_op_pair *gathers;
int num_gathers;
@@ -206,6 +207,7 @@ static int nvhost_ioctl_channel_flush(
u32 syncval;
int num_unpin;
int err;
+ int nulled_incrs = ctx->null_kickoff ? ctx->syncpt_incrs : 0;
if (ctx->relocs_pending || ctx->cmdbufs_pending) {
reset_submit(ctx);
@@ -285,8 +287,9 @@ static int nvhost_ioctl_channel_flush(
ctxsw.syncpt_val += syncval - ctx->syncpt_incrs;
nvhost_channel_submit(ctx->ch, &ctx->gathers[gather_idx],
- ctx->num_gathers - gather_idx, &ctxsw, num_intrs,
- ctx->unpinarray, num_unpin, ctx->syncpt_id, syncval);
+ (ctx->null_kickoff ? 2 : ctx->num_gathers) - gather_idx,
+ &ctxsw, num_intrs, ctx->unpinarray, num_unpin, ctx->syncpt_id,
+ syncval, nulled_incrs);
/* schedule a submit complete interrupt */
nvhost_intr_add_action(&ctx->ch->dev->intr, ctx->syncpt_id, syncval,