summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTerje Bergstrom <tbergstrom@nvidia.com>2011-10-03 13:51:10 +0300
committerRyan Wong <ryanw@nvidia.com>2011-10-04 15:47:58 -0700
commita25281464a359cd3626ac107d7e8a303d6a99265 (patch)
tree633e217933b064eac2d09d3333d6e77e95ebb0bf
parent89df4a6ca6435388ea7f3bd5d7aab1e98e27ac34 (diff)
nvhost: Reference count context to be restored
Context to be restored needs to be reference counted. Otherwise a sequence of process submitting the work and exiting before hardware executes the work can result in access to memory that is not mapped anymore. Bug 870787 Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com> Change-Id: I8f21db3ab85ab574d577a27081a5bbbf0f797968 Reviewed-on: http://git-master/r/55888 Reviewed-by: Ryan Wong <ryanw@nvidia.com> Tested-by: Ryan Wong <ryanw@nvidia.com>
-rw-r--r--drivers/video/tegra/host/nvhost_intr.c9
-rw-r--r--drivers/video/tegra/host/nvhost_intr.h6
-rw-r--r--drivers/video/tegra/host/t20/channel_t20.c9
3 files changed, 23 insertions, 1 deletions
diff --git a/drivers/video/tegra/host/nvhost_intr.c b/drivers/video/tegra/host/nvhost_intr.c
index 30ef7d2b8bc6..738cf9dc8acd 100644
--- a/drivers/video/tegra/host/nvhost_intr.c
+++ b/drivers/video/tegra/host/nvhost_intr.c
@@ -150,6 +150,14 @@ static void action_ctxsave(struct nvhost_waitlist *waiter)
channel->ctxhandler.put(hwctx);
}
+static void action_ctxrestore(struct nvhost_waitlist *waiter)
+{
+ struct nvhost_hwctx *hwctx = waiter->data;
+ struct nvhost_channel *channel = hwctx->channel;
+
+ channel->ctxhandler.put(hwctx);
+}
+
static void action_wakeup(struct nvhost_waitlist *waiter)
{
wait_queue_head_t *wq = waiter->data;
@@ -169,6 +177,7 @@ typedef void (*action_handler)(struct nvhost_waitlist *waiter);
static action_handler action_handlers[NVHOST_INTR_ACTION_COUNT] = {
action_submit_complete,
action_ctxsave,
+ action_ctxrestore,
action_wakeup,
action_wakeup_interruptible,
};
diff --git a/drivers/video/tegra/host/nvhost_intr.h b/drivers/video/tegra/host/nvhost_intr.h
index 150fd6c5694c..d8b52a9e7dfa 100644
--- a/drivers/video/tegra/host/nvhost_intr.h
+++ b/drivers/video/tegra/host/nvhost_intr.h
@@ -42,6 +42,12 @@ enum nvhost_intr_action {
NVHOST_INTR_ACTION_CTXSAVE,
/**
+ * Restore a HW context.
+ * 'data' points to a context
+ */
+ NVHOST_INTR_ACTION_CTXRESTORE,
+
+ /**
* Wake up a task.
* 'data' points to a wait_queue_head_t
*/
diff --git a/drivers/video/tegra/host/t20/channel_t20.c b/drivers/video/tegra/host/t20/channel_t20.c
index 2617c9bd46da..d0d3506446d7 100644
--- a/drivers/video/tegra/host/t20/channel_t20.c
+++ b/drivers/video/tegra/host/t20/channel_t20.c
@@ -268,12 +268,14 @@ static int t20_channel_submit(struct nvhost_channel *channel,
channel->ctxhandler.save_push(&channel->cdma, hwctx_to_save);
/* gather restore buffer */
- if (need_restore)
+ if (need_restore) {
nvhost_cdma_push_gather(&channel->cdma,
channel->dev->nvmap,
nvmap_ref_to_handle(channel->cur_ctx->restore),
nvhost_opcode_gather(channel->cur_ctx->restore_size),
channel->cur_ctx->restore_phys);
+ channel->ctxhandler.get(channel->cur_ctx);
+ }
/* add a setclass for modules that require it (unless ctxsw added it) */
if (!hwctx_to_save && !need_restore && channel->desc->class)
@@ -335,6 +337,11 @@ static int t20_channel_submit(struct nvhost_channel *channel,
syncval - syncpt_incrs + hwctx_to_save->save_thresh,
NVHOST_INTR_ACTION_CTXSAVE, hwctx_to_save, NULL);
+ if (need_restore)
+ nvhost_intr_add_action(&channel->dev->intr, syncpt_id,
+ syncval - user_syncpt_incrs,
+ NVHOST_INTR_ACTION_CTXRESTORE, channel->cur_ctx, NULL);
+
/* schedule a submit complete interrupt */
err = nvhost_intr_add_action(&channel->dev->intr, syncpt_id, syncval,
NVHOST_INTR_ACTION_SUBMIT_COMPLETE, channel, NULL);