diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2011-10-03 13:51:10 +0300 |
---|---|---|
committer | Ryan Wong <ryanw@nvidia.com> | 2011-10-04 15:47:58 -0700 |
commit | a25281464a359cd3626ac107d7e8a303d6a99265 (patch) | |
tree | 633e217933b064eac2d09d3333d6e77e95ebb0bf | |
parent | 89df4a6ca6435388ea7f3bd5d7aab1e98e27ac34 (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.c | 9 | ||||
-rw-r--r-- | drivers/video/tegra/host/nvhost_intr.h | 6 | ||||
-rw-r--r-- | drivers/video/tegra/host/t20/channel_t20.c | 9 |
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); |